xilinx.h: Error check when setting links
[qemu-kvm.git] / target-mips / translate.c
blob52eeb2bf79bc119e16d5048ebc0aee7df6e35fa7
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_0e0i(name, arg) do { \
487 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
488 gen_helper_##name(cpu_env, helper_tmp); \
489 tcg_temp_free_i32(helper_tmp); \
490 } while(0)
492 #define gen_helper_0e1i(name, arg1, arg2) do { \
493 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
494 gen_helper_##name(cpu_env, arg1, helper_tmp); \
495 tcg_temp_free_i32(helper_tmp); \
496 } while(0)
498 #define gen_helper_1e0i(name, ret, arg1) do { \
499 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
500 gen_helper_##name(ret, cpu_env, helper_tmp); \
501 tcg_temp_free_i32(helper_tmp); \
502 } while(0)
504 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
505 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
506 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
507 tcg_temp_free_i32(helper_tmp); \
508 } while(0)
510 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
511 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
512 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
513 tcg_temp_free_i32(helper_tmp); \
514 } while(0)
516 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
517 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
518 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
519 tcg_temp_free_i32(helper_tmp); \
520 } while(0)
522 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
523 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
524 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
525 tcg_temp_free_i32(helper_tmp); \
526 } while(0)
528 typedef struct DisasContext {
529 struct TranslationBlock *tb;
530 target_ulong pc, saved_pc;
531 uint32_t opcode;
532 int singlestep_enabled;
533 /* Routine used to access memory */
534 int mem_idx;
535 uint32_t hflags, saved_hflags;
536 int bstate;
537 target_ulong btarget;
538 } DisasContext;
540 enum {
541 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
542 * exception condition */
543 BS_STOP = 1, /* We want to stop translation for any reason */
544 BS_BRANCH = 2, /* We reached a branch condition */
545 BS_EXCP = 3, /* We reached an exception condition */
548 static const char *regnames[] =
549 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
550 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
551 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
552 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
554 static const char *regnames_HI[] =
555 { "HI0", "HI1", "HI2", "HI3", };
557 static const char *regnames_LO[] =
558 { "LO0", "LO1", "LO2", "LO3", };
560 static const char *regnames_ACX[] =
561 { "ACX0", "ACX1", "ACX2", "ACX3", };
563 static const char *fregnames[] =
564 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
565 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
566 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
567 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
569 #ifdef MIPS_DEBUG_DISAS
570 #define MIPS_DEBUG(fmt, ...) \
571 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
572 TARGET_FMT_lx ": %08x " fmt "\n", \
573 ctx->pc, ctx->opcode , ## __VA_ARGS__)
574 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
575 #else
576 #define MIPS_DEBUG(fmt, ...) do { } while(0)
577 #define LOG_DISAS(...) do { } while (0)
578 #endif
580 #define MIPS_INVAL(op) \
581 do { \
582 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
583 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
584 } while (0)
586 /* General purpose registers moves. */
587 static inline void gen_load_gpr (TCGv t, int reg)
589 if (reg == 0)
590 tcg_gen_movi_tl(t, 0);
591 else
592 tcg_gen_mov_tl(t, cpu_gpr[reg]);
595 static inline void gen_store_gpr (TCGv t, int reg)
597 if (reg != 0)
598 tcg_gen_mov_tl(cpu_gpr[reg], t);
601 /* Moves to/from ACX register. */
602 static inline void gen_load_ACX (TCGv t, int reg)
604 tcg_gen_mov_tl(t, cpu_ACX[reg]);
607 static inline void gen_store_ACX (TCGv t, int reg)
609 tcg_gen_mov_tl(cpu_ACX[reg], t);
612 /* Moves to/from shadow registers. */
613 static inline void gen_load_srsgpr (int from, int to)
615 TCGv t0 = tcg_temp_new();
617 if (from == 0)
618 tcg_gen_movi_tl(t0, 0);
619 else {
620 TCGv_i32 t2 = tcg_temp_new_i32();
621 TCGv_ptr addr = tcg_temp_new_ptr();
623 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
624 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
625 tcg_gen_andi_i32(t2, t2, 0xf);
626 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
627 tcg_gen_ext_i32_ptr(addr, t2);
628 tcg_gen_add_ptr(addr, cpu_env, addr);
630 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
631 tcg_temp_free_ptr(addr);
632 tcg_temp_free_i32(t2);
634 gen_store_gpr(t0, to);
635 tcg_temp_free(t0);
638 static inline void gen_store_srsgpr (int from, int to)
640 if (to != 0) {
641 TCGv t0 = tcg_temp_new();
642 TCGv_i32 t2 = tcg_temp_new_i32();
643 TCGv_ptr addr = tcg_temp_new_ptr();
645 gen_load_gpr(t0, from);
646 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
647 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
648 tcg_gen_andi_i32(t2, t2, 0xf);
649 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
650 tcg_gen_ext_i32_ptr(addr, t2);
651 tcg_gen_add_ptr(addr, cpu_env, addr);
653 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
654 tcg_temp_free_ptr(addr);
655 tcg_temp_free_i32(t2);
656 tcg_temp_free(t0);
660 /* Floating point register moves. */
661 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
663 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
666 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
668 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
671 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
673 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
676 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
678 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
681 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
683 if (ctx->hflags & MIPS_HFLAG_F64) {
684 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
685 } else {
686 TCGv_i32 t0 = tcg_temp_new_i32();
687 TCGv_i32 t1 = tcg_temp_new_i32();
688 gen_load_fpr32(t0, reg & ~1);
689 gen_load_fpr32(t1, reg | 1);
690 tcg_gen_concat_i32_i64(t, t0, t1);
691 tcg_temp_free_i32(t0);
692 tcg_temp_free_i32(t1);
696 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
698 if (ctx->hflags & MIPS_HFLAG_F64) {
699 tcg_gen_st_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
700 } else {
701 TCGv_i64 t0 = tcg_temp_new_i64();
702 TCGv_i32 t1 = tcg_temp_new_i32();
703 tcg_gen_trunc_i64_i32(t1, t);
704 gen_store_fpr32(t1, reg & ~1);
705 tcg_gen_shri_i64(t0, t, 32);
706 tcg_gen_trunc_i64_i32(t1, t0);
707 gen_store_fpr32(t1, reg | 1);
708 tcg_temp_free_i32(t1);
709 tcg_temp_free_i64(t0);
713 static inline int get_fp_bit (int cc)
715 if (cc)
716 return 24 + cc;
717 else
718 return 23;
721 /* Tests */
722 static inline void gen_save_pc(target_ulong pc)
724 tcg_gen_movi_tl(cpu_PC, pc);
727 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
729 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
730 if (do_save_pc && ctx->pc != ctx->saved_pc) {
731 gen_save_pc(ctx->pc);
732 ctx->saved_pc = ctx->pc;
734 if (ctx->hflags != ctx->saved_hflags) {
735 tcg_gen_movi_i32(hflags, ctx->hflags);
736 ctx->saved_hflags = ctx->hflags;
737 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
738 case MIPS_HFLAG_BR:
739 break;
740 case MIPS_HFLAG_BC:
741 case MIPS_HFLAG_BL:
742 case MIPS_HFLAG_B:
743 tcg_gen_movi_tl(btarget, ctx->btarget);
744 break;
749 static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
751 ctx->saved_hflags = ctx->hflags;
752 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
753 case MIPS_HFLAG_BR:
754 break;
755 case MIPS_HFLAG_BC:
756 case MIPS_HFLAG_BL:
757 case MIPS_HFLAG_B:
758 ctx->btarget = env->btarget;
759 break;
763 static inline void
764 generate_exception_err (DisasContext *ctx, int excp, int err)
766 TCGv_i32 texcp = tcg_const_i32(excp);
767 TCGv_i32 terr = tcg_const_i32(err);
768 save_cpu_state(ctx, 1);
769 gen_helper_raise_exception_err(cpu_env, texcp, terr);
770 tcg_temp_free_i32(terr);
771 tcg_temp_free_i32(texcp);
774 static inline void
775 generate_exception (DisasContext *ctx, int excp)
777 save_cpu_state(ctx, 1);
778 gen_helper_0e0i(raise_exception, excp);
781 /* Addresses computation */
782 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
784 tcg_gen_add_tl(ret, arg0, arg1);
786 #if defined(TARGET_MIPS64)
787 /* For compatibility with 32-bit code, data reference in user mode
788 with Status_UX = 0 should be casted to 32-bit and sign extended.
789 See the MIPS64 PRA manual, section 4.10. */
790 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
791 !(ctx->hflags & MIPS_HFLAG_UX)) {
792 tcg_gen_ext32s_i64(ret, ret);
794 #endif
797 static inline void check_cp0_enabled(DisasContext *ctx)
799 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
800 generate_exception_err(ctx, EXCP_CpU, 0);
803 static inline void check_cp1_enabled(DisasContext *ctx)
805 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
806 generate_exception_err(ctx, EXCP_CpU, 1);
809 /* Verify that the processor is running with COP1X instructions enabled.
810 This is associated with the nabla symbol in the MIPS32 and MIPS64
811 opcode tables. */
813 static inline void check_cop1x(DisasContext *ctx)
815 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
816 generate_exception(ctx, EXCP_RI);
819 /* Verify that the processor is running with 64-bit floating-point
820 operations enabled. */
822 static inline void check_cp1_64bitmode(DisasContext *ctx)
824 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
825 generate_exception(ctx, EXCP_RI);
829 * Verify if floating point register is valid; an operation is not defined
830 * if bit 0 of any register specification is set and the FR bit in the
831 * Status register equals zero, since the register numbers specify an
832 * even-odd pair of adjacent coprocessor general registers. When the FR bit
833 * in the Status register equals one, both even and odd register numbers
834 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
836 * Multiple 64 bit wide registers can be checked by calling
837 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
839 static inline void check_cp1_registers(DisasContext *ctx, int regs)
841 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
842 generate_exception(ctx, EXCP_RI);
845 /* This code generates a "reserved instruction" exception if the
846 CPU does not support the instruction set corresponding to flags. */
847 static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
849 if (unlikely(!(env->insn_flags & flags)))
850 generate_exception(ctx, EXCP_RI);
853 /* This code generates a "reserved instruction" exception if 64-bit
854 instructions are not enabled. */
855 static inline void check_mips_64(DisasContext *ctx)
857 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
858 generate_exception(ctx, EXCP_RI);
861 /* Define small wrappers for gen_load_fpr* so that we have a uniform
862 calling interface for 32 and 64-bit FPRs. No sense in changing
863 all callers for gen_load_fpr32 when we need the CTX parameter for
864 this one use. */
865 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
866 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
867 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
868 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
869 int ft, int fs, int cc) \
871 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
872 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
873 switch (ifmt) { \
874 case FMT_PS: \
875 check_cp1_64bitmode(ctx); \
876 break; \
877 case FMT_D: \
878 if (abs) { \
879 check_cop1x(ctx); \
881 check_cp1_registers(ctx, fs | ft); \
882 break; \
883 case FMT_S: \
884 if (abs) { \
885 check_cop1x(ctx); \
887 break; \
889 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
890 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
891 switch (n) { \
892 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
893 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
894 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
895 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
896 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
897 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
898 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
899 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
900 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
901 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
902 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
903 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
904 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
905 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
906 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
907 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
908 default: abort(); \
910 tcg_temp_free_i##bits (fp0); \
911 tcg_temp_free_i##bits (fp1); \
914 FOP_CONDS(, 0, d, FMT_D, 64)
915 FOP_CONDS(abs, 1, d, FMT_D, 64)
916 FOP_CONDS(, 0, s, FMT_S, 32)
917 FOP_CONDS(abs, 1, s, FMT_S, 32)
918 FOP_CONDS(, 0, ps, FMT_PS, 64)
919 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
920 #undef FOP_CONDS
921 #undef gen_ldcmp_fpr32
922 #undef gen_ldcmp_fpr64
924 /* load/store instructions. */
925 #define OP_LD(insn,fname) \
926 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
928 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
930 OP_LD(lb,ld8s);
931 OP_LD(lbu,ld8u);
932 OP_LD(lh,ld16s);
933 OP_LD(lhu,ld16u);
934 OP_LD(lw,ld32s);
935 #if defined(TARGET_MIPS64)
936 OP_LD(lwu,ld32u);
937 OP_LD(ld,ld64);
938 #endif
939 #undef OP_LD
941 #define OP_ST(insn,fname) \
942 static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
944 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
946 OP_ST(sb,st8);
947 OP_ST(sh,st16);
948 OP_ST(sw,st32);
949 #if defined(TARGET_MIPS64)
950 OP_ST(sd,st64);
951 #endif
952 #undef OP_ST
954 #ifdef CONFIG_USER_ONLY
955 #define OP_LD_ATOMIC(insn,fname) \
956 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
958 TCGv t0 = tcg_temp_new(); \
959 tcg_gen_mov_tl(t0, arg1); \
960 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
961 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
962 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
963 tcg_temp_free(t0); \
965 #else
966 #define OP_LD_ATOMIC(insn,fname) \
967 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
969 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
971 #endif
972 OP_LD_ATOMIC(ll,ld32s);
973 #if defined(TARGET_MIPS64)
974 OP_LD_ATOMIC(lld,ld64);
975 #endif
976 #undef OP_LD_ATOMIC
978 #ifdef CONFIG_USER_ONLY
979 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
980 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
982 TCGv t0 = tcg_temp_new(); \
983 int l1 = gen_new_label(); \
984 int l2 = gen_new_label(); \
986 tcg_gen_andi_tl(t0, arg2, almask); \
987 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
988 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
989 generate_exception(ctx, EXCP_AdES); \
990 gen_set_label(l1); \
991 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
992 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
993 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
994 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
995 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
996 gen_helper_0e0i(raise_exception, EXCP_SC); \
997 gen_set_label(l2); \
998 tcg_gen_movi_tl(t0, 0); \
999 gen_store_gpr(t0, rt); \
1000 tcg_temp_free(t0); \
1002 #else
1003 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1004 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1006 TCGv t0 = tcg_temp_new(); \
1007 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
1008 gen_store_gpr(t0, rt); \
1009 tcg_temp_free(t0); \
1011 #endif
1012 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1013 #if defined(TARGET_MIPS64)
1014 OP_ST_ATOMIC(scd,st64,ld64,0x7);
1015 #endif
1016 #undef OP_ST_ATOMIC
1018 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1019 int base, int16_t offset)
1021 if (base == 0) {
1022 tcg_gen_movi_tl(addr, offset);
1023 } else if (offset == 0) {
1024 gen_load_gpr(addr, base);
1025 } else {
1026 tcg_gen_movi_tl(addr, offset);
1027 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1031 static target_ulong pc_relative_pc (DisasContext *ctx)
1033 target_ulong pc = ctx->pc;
1035 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1036 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1038 pc -= branch_bytes;
1041 pc &= ~(target_ulong)3;
1042 return pc;
1045 /* Load */
1046 static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1047 int rt, int base, int16_t offset)
1049 const char *opn = "ld";
1050 TCGv t0, t1;
1052 if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1053 /* Loongson CPU uses a load to zero register for prefetch.
1054 We emulate it as a NOP. On other CPU we must perform the
1055 actual memory access. */
1056 MIPS_DEBUG("NOP");
1057 return;
1060 t0 = tcg_temp_new();
1061 t1 = tcg_temp_new();
1062 gen_base_offset_addr(ctx, t0, base, offset);
1064 switch (opc) {
1065 #if defined(TARGET_MIPS64)
1066 case OPC_LWU:
1067 save_cpu_state(ctx, 0);
1068 op_ld_lwu(t0, t0, ctx);
1069 gen_store_gpr(t0, rt);
1070 opn = "lwu";
1071 break;
1072 case OPC_LD:
1073 save_cpu_state(ctx, 0);
1074 op_ld_ld(t0, t0, ctx);
1075 gen_store_gpr(t0, rt);
1076 opn = "ld";
1077 break;
1078 case OPC_LLD:
1079 save_cpu_state(ctx, 1);
1080 op_ld_lld(t0, t0, ctx);
1081 gen_store_gpr(t0, rt);
1082 opn = "lld";
1083 break;
1084 case OPC_LDL:
1085 save_cpu_state(ctx, 1);
1086 gen_load_gpr(t1, rt);
1087 gen_helper_1e2i(ldl, t1, t1, t0, ctx->mem_idx);
1088 gen_store_gpr(t1, rt);
1089 opn = "ldl";
1090 break;
1091 case OPC_LDR:
1092 save_cpu_state(ctx, 1);
1093 gen_load_gpr(t1, rt);
1094 gen_helper_1e2i(ldr, t1, t1, t0, ctx->mem_idx);
1095 gen_store_gpr(t1, rt);
1096 opn = "ldr";
1097 break;
1098 case OPC_LDPC:
1099 save_cpu_state(ctx, 0);
1100 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1101 gen_op_addr_add(ctx, t0, t0, t1);
1102 op_ld_ld(t0, t0, ctx);
1103 gen_store_gpr(t0, rt);
1104 opn = "ldpc";
1105 break;
1106 #endif
1107 case OPC_LWPC:
1108 save_cpu_state(ctx, 0);
1109 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1110 gen_op_addr_add(ctx, t0, t0, t1);
1111 op_ld_lw(t0, t0, ctx);
1112 gen_store_gpr(t0, rt);
1113 opn = "lwpc";
1114 break;
1115 case OPC_LW:
1116 save_cpu_state(ctx, 0);
1117 op_ld_lw(t0, t0, ctx);
1118 gen_store_gpr(t0, rt);
1119 opn = "lw";
1120 break;
1121 case OPC_LH:
1122 save_cpu_state(ctx, 0);
1123 op_ld_lh(t0, t0, ctx);
1124 gen_store_gpr(t0, rt);
1125 opn = "lh";
1126 break;
1127 case OPC_LHU:
1128 save_cpu_state(ctx, 0);
1129 op_ld_lhu(t0, t0, ctx);
1130 gen_store_gpr(t0, rt);
1131 opn = "lhu";
1132 break;
1133 case OPC_LB:
1134 save_cpu_state(ctx, 0);
1135 op_ld_lb(t0, t0, ctx);
1136 gen_store_gpr(t0, rt);
1137 opn = "lb";
1138 break;
1139 case OPC_LBU:
1140 save_cpu_state(ctx, 0);
1141 op_ld_lbu(t0, t0, ctx);
1142 gen_store_gpr(t0, rt);
1143 opn = "lbu";
1144 break;
1145 case OPC_LWL:
1146 save_cpu_state(ctx, 1);
1147 gen_load_gpr(t1, rt);
1148 gen_helper_1e2i(lwl, t1, t1, t0, ctx->mem_idx);
1149 gen_store_gpr(t1, rt);
1150 opn = "lwl";
1151 break;
1152 case OPC_LWR:
1153 save_cpu_state(ctx, 1);
1154 gen_load_gpr(t1, rt);
1155 gen_helper_1e2i(lwr, t1, t1, t0, ctx->mem_idx);
1156 gen_store_gpr(t1, rt);
1157 opn = "lwr";
1158 break;
1159 case OPC_LL:
1160 save_cpu_state(ctx, 1);
1161 op_ld_ll(t0, t0, ctx);
1162 gen_store_gpr(t0, rt);
1163 opn = "ll";
1164 break;
1166 (void)opn; /* avoid a compiler warning */
1167 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1168 tcg_temp_free(t0);
1169 tcg_temp_free(t1);
1172 /* Store */
1173 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1174 int base, int16_t offset)
1176 const char *opn = "st";
1177 TCGv t0 = tcg_temp_new();
1178 TCGv t1 = tcg_temp_new();
1180 gen_base_offset_addr(ctx, t0, base, offset);
1181 gen_load_gpr(t1, rt);
1182 switch (opc) {
1183 #if defined(TARGET_MIPS64)
1184 case OPC_SD:
1185 save_cpu_state(ctx, 0);
1186 op_st_sd(t1, t0, ctx);
1187 opn = "sd";
1188 break;
1189 case OPC_SDL:
1190 save_cpu_state(ctx, 1);
1191 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
1192 opn = "sdl";
1193 break;
1194 case OPC_SDR:
1195 save_cpu_state(ctx, 1);
1196 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
1197 opn = "sdr";
1198 break;
1199 #endif
1200 case OPC_SW:
1201 save_cpu_state(ctx, 0);
1202 op_st_sw(t1, t0, ctx);
1203 opn = "sw";
1204 break;
1205 case OPC_SH:
1206 save_cpu_state(ctx, 0);
1207 op_st_sh(t1, t0, ctx);
1208 opn = "sh";
1209 break;
1210 case OPC_SB:
1211 save_cpu_state(ctx, 0);
1212 op_st_sb(t1, t0, ctx);
1213 opn = "sb";
1214 break;
1215 case OPC_SWL:
1216 save_cpu_state(ctx, 1);
1217 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
1218 opn = "swl";
1219 break;
1220 case OPC_SWR:
1221 save_cpu_state(ctx, 1);
1222 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
1223 opn = "swr";
1224 break;
1226 (void)opn; /* avoid a compiler warning */
1227 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1228 tcg_temp_free(t0);
1229 tcg_temp_free(t1);
1233 /* Store conditional */
1234 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1235 int base, int16_t offset)
1237 const char *opn = "st_cond";
1238 TCGv t0, t1;
1240 t0 = tcg_temp_local_new();
1242 gen_base_offset_addr(ctx, t0, base, offset);
1243 /* Don't do NOP if destination is zero: we must perform the actual
1244 memory access. */
1246 t1 = tcg_temp_local_new();
1247 gen_load_gpr(t1, rt);
1248 switch (opc) {
1249 #if defined(TARGET_MIPS64)
1250 case OPC_SCD:
1251 save_cpu_state(ctx, 1);
1252 op_st_scd(t1, t0, rt, ctx);
1253 opn = "scd";
1254 break;
1255 #endif
1256 case OPC_SC:
1257 save_cpu_state(ctx, 1);
1258 op_st_sc(t1, t0, rt, ctx);
1259 opn = "sc";
1260 break;
1262 (void)opn; /* avoid a compiler warning */
1263 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1264 tcg_temp_free(t1);
1265 tcg_temp_free(t0);
1268 /* Load and store */
1269 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1270 int base, int16_t offset)
1272 const char *opn = "flt_ldst";
1273 TCGv t0 = tcg_temp_new();
1275 gen_base_offset_addr(ctx, t0, base, offset);
1276 /* Don't do NOP if destination is zero: we must perform the actual
1277 memory access. */
1278 switch (opc) {
1279 case OPC_LWC1:
1281 TCGv_i32 fp0 = tcg_temp_new_i32();
1283 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1284 tcg_gen_trunc_tl_i32(fp0, t0);
1285 gen_store_fpr32(fp0, ft);
1286 tcg_temp_free_i32(fp0);
1288 opn = "lwc1";
1289 break;
1290 case OPC_SWC1:
1292 TCGv_i32 fp0 = tcg_temp_new_i32();
1293 TCGv t1 = tcg_temp_new();
1295 gen_load_fpr32(fp0, ft);
1296 tcg_gen_extu_i32_tl(t1, fp0);
1297 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1298 tcg_temp_free(t1);
1299 tcg_temp_free_i32(fp0);
1301 opn = "swc1";
1302 break;
1303 case OPC_LDC1:
1305 TCGv_i64 fp0 = tcg_temp_new_i64();
1307 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1308 gen_store_fpr64(ctx, fp0, ft);
1309 tcg_temp_free_i64(fp0);
1311 opn = "ldc1";
1312 break;
1313 case OPC_SDC1:
1315 TCGv_i64 fp0 = tcg_temp_new_i64();
1317 gen_load_fpr64(ctx, fp0, ft);
1318 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1319 tcg_temp_free_i64(fp0);
1321 opn = "sdc1";
1322 break;
1323 default:
1324 MIPS_INVAL(opn);
1325 generate_exception(ctx, EXCP_RI);
1326 goto out;
1328 (void)opn; /* avoid a compiler warning */
1329 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1330 out:
1331 tcg_temp_free(t0);
1334 static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
1335 uint32_t op, int rt, int rs, int16_t imm)
1337 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1338 check_cp1_enabled(ctx);
1339 gen_flt_ldst(ctx, op, rt, rs, imm);
1340 } else {
1341 generate_exception_err(ctx, EXCP_CpU, 1);
1345 /* Arithmetic with immediate operand */
1346 static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1347 int rt, int rs, int16_t imm)
1349 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1350 const char *opn = "imm arith";
1352 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1353 /* If no destination, treat it as a NOP.
1354 For addi, we must generate the overflow exception when needed. */
1355 MIPS_DEBUG("NOP");
1356 return;
1358 switch (opc) {
1359 case OPC_ADDI:
1361 TCGv t0 = tcg_temp_local_new();
1362 TCGv t1 = tcg_temp_new();
1363 TCGv t2 = tcg_temp_new();
1364 int l1 = gen_new_label();
1366 gen_load_gpr(t1, rs);
1367 tcg_gen_addi_tl(t0, t1, uimm);
1368 tcg_gen_ext32s_tl(t0, t0);
1370 tcg_gen_xori_tl(t1, t1, ~uimm);
1371 tcg_gen_xori_tl(t2, t0, uimm);
1372 tcg_gen_and_tl(t1, t1, t2);
1373 tcg_temp_free(t2);
1374 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1375 tcg_temp_free(t1);
1376 /* operands of same sign, result different sign */
1377 generate_exception(ctx, EXCP_OVERFLOW);
1378 gen_set_label(l1);
1379 tcg_gen_ext32s_tl(t0, t0);
1380 gen_store_gpr(t0, rt);
1381 tcg_temp_free(t0);
1383 opn = "addi";
1384 break;
1385 case OPC_ADDIU:
1386 if (rs != 0) {
1387 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1388 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1389 } else {
1390 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1392 opn = "addiu";
1393 break;
1394 #if defined(TARGET_MIPS64)
1395 case OPC_DADDI:
1397 TCGv t0 = tcg_temp_local_new();
1398 TCGv t1 = tcg_temp_new();
1399 TCGv t2 = tcg_temp_new();
1400 int l1 = gen_new_label();
1402 gen_load_gpr(t1, rs);
1403 tcg_gen_addi_tl(t0, t1, uimm);
1405 tcg_gen_xori_tl(t1, t1, ~uimm);
1406 tcg_gen_xori_tl(t2, t0, uimm);
1407 tcg_gen_and_tl(t1, t1, t2);
1408 tcg_temp_free(t2);
1409 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1410 tcg_temp_free(t1);
1411 /* operands of same sign, result different sign */
1412 generate_exception(ctx, EXCP_OVERFLOW);
1413 gen_set_label(l1);
1414 gen_store_gpr(t0, rt);
1415 tcg_temp_free(t0);
1417 opn = "daddi";
1418 break;
1419 case OPC_DADDIU:
1420 if (rs != 0) {
1421 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1422 } else {
1423 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1425 opn = "daddiu";
1426 break;
1427 #endif
1429 (void)opn; /* avoid a compiler warning */
1430 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1433 /* Logic with immediate operand */
1434 static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
1436 target_ulong uimm;
1437 const char *opn = "imm logic";
1439 if (rt == 0) {
1440 /* If no destination, treat it as a NOP. */
1441 MIPS_DEBUG("NOP");
1442 return;
1444 uimm = (uint16_t)imm;
1445 switch (opc) {
1446 case OPC_ANDI:
1447 if (likely(rs != 0))
1448 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1449 else
1450 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1451 opn = "andi";
1452 break;
1453 case OPC_ORI:
1454 if (rs != 0)
1455 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1456 else
1457 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1458 opn = "ori";
1459 break;
1460 case OPC_XORI:
1461 if (likely(rs != 0))
1462 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1463 else
1464 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1465 opn = "xori";
1466 break;
1467 case OPC_LUI:
1468 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1469 opn = "lui";
1470 break;
1472 (void)opn; /* avoid a compiler warning */
1473 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1476 /* Set on less than with immediate operand */
1477 static void gen_slt_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
1479 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1480 const char *opn = "imm arith";
1481 TCGv t0;
1483 if (rt == 0) {
1484 /* If no destination, treat it as a NOP. */
1485 MIPS_DEBUG("NOP");
1486 return;
1488 t0 = tcg_temp_new();
1489 gen_load_gpr(t0, rs);
1490 switch (opc) {
1491 case OPC_SLTI:
1492 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1493 opn = "slti";
1494 break;
1495 case OPC_SLTIU:
1496 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1497 opn = "sltiu";
1498 break;
1500 (void)opn; /* avoid a compiler warning */
1501 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1502 tcg_temp_free(t0);
1505 /* Shifts with immediate operand */
1506 static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1507 int rt, int rs, int16_t imm)
1509 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1510 const char *opn = "imm shift";
1511 TCGv t0;
1513 if (rt == 0) {
1514 /* If no destination, treat it as a NOP. */
1515 MIPS_DEBUG("NOP");
1516 return;
1519 t0 = tcg_temp_new();
1520 gen_load_gpr(t0, rs);
1521 switch (opc) {
1522 case OPC_SLL:
1523 tcg_gen_shli_tl(t0, t0, uimm);
1524 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1525 opn = "sll";
1526 break;
1527 case OPC_SRA:
1528 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1529 opn = "sra";
1530 break;
1531 case OPC_SRL:
1532 if (uimm != 0) {
1533 tcg_gen_ext32u_tl(t0, t0);
1534 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1535 } else {
1536 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1538 opn = "srl";
1539 break;
1540 case OPC_ROTR:
1541 if (uimm != 0) {
1542 TCGv_i32 t1 = tcg_temp_new_i32();
1544 tcg_gen_trunc_tl_i32(t1, t0);
1545 tcg_gen_rotri_i32(t1, t1, uimm);
1546 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1547 tcg_temp_free_i32(t1);
1548 } else {
1549 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1551 opn = "rotr";
1552 break;
1553 #if defined(TARGET_MIPS64)
1554 case OPC_DSLL:
1555 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1556 opn = "dsll";
1557 break;
1558 case OPC_DSRA:
1559 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1560 opn = "dsra";
1561 break;
1562 case OPC_DSRL:
1563 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1564 opn = "dsrl";
1565 break;
1566 case OPC_DROTR:
1567 if (uimm != 0) {
1568 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1569 } else {
1570 tcg_gen_mov_tl(cpu_gpr[rt], t0);
1572 opn = "drotr";
1573 break;
1574 case OPC_DSLL32:
1575 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1576 opn = "dsll32";
1577 break;
1578 case OPC_DSRA32:
1579 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1580 opn = "dsra32";
1581 break;
1582 case OPC_DSRL32:
1583 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1584 opn = "dsrl32";
1585 break;
1586 case OPC_DROTR32:
1587 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1588 opn = "drotr32";
1589 break;
1590 #endif
1592 (void)opn; /* avoid a compiler warning */
1593 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1594 tcg_temp_free(t0);
1597 /* Arithmetic */
1598 static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1599 int rd, int rs, int rt)
1601 const char *opn = "arith";
1603 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1604 && opc != OPC_DADD && opc != OPC_DSUB) {
1605 /* If no destination, treat it as a NOP.
1606 For add & sub, we must generate the overflow exception when needed. */
1607 MIPS_DEBUG("NOP");
1608 return;
1611 switch (opc) {
1612 case OPC_ADD:
1614 TCGv t0 = tcg_temp_local_new();
1615 TCGv t1 = tcg_temp_new();
1616 TCGv t2 = tcg_temp_new();
1617 int l1 = gen_new_label();
1619 gen_load_gpr(t1, rs);
1620 gen_load_gpr(t2, rt);
1621 tcg_gen_add_tl(t0, t1, t2);
1622 tcg_gen_ext32s_tl(t0, t0);
1623 tcg_gen_xor_tl(t1, t1, t2);
1624 tcg_gen_xor_tl(t2, t0, t2);
1625 tcg_gen_andc_tl(t1, t2, t1);
1626 tcg_temp_free(t2);
1627 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1628 tcg_temp_free(t1);
1629 /* operands of same sign, result different sign */
1630 generate_exception(ctx, EXCP_OVERFLOW);
1631 gen_set_label(l1);
1632 gen_store_gpr(t0, rd);
1633 tcg_temp_free(t0);
1635 opn = "add";
1636 break;
1637 case OPC_ADDU:
1638 if (rs != 0 && rt != 0) {
1639 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1640 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1641 } else if (rs == 0 && rt != 0) {
1642 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1643 } else if (rs != 0 && rt == 0) {
1644 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1645 } else {
1646 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1648 opn = "addu";
1649 break;
1650 case OPC_SUB:
1652 TCGv t0 = tcg_temp_local_new();
1653 TCGv t1 = tcg_temp_new();
1654 TCGv t2 = tcg_temp_new();
1655 int l1 = gen_new_label();
1657 gen_load_gpr(t1, rs);
1658 gen_load_gpr(t2, rt);
1659 tcg_gen_sub_tl(t0, t1, t2);
1660 tcg_gen_ext32s_tl(t0, t0);
1661 tcg_gen_xor_tl(t2, t1, t2);
1662 tcg_gen_xor_tl(t1, t0, t1);
1663 tcg_gen_and_tl(t1, t1, t2);
1664 tcg_temp_free(t2);
1665 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1666 tcg_temp_free(t1);
1667 /* operands of different sign, first operand and result different sign */
1668 generate_exception(ctx, EXCP_OVERFLOW);
1669 gen_set_label(l1);
1670 gen_store_gpr(t0, rd);
1671 tcg_temp_free(t0);
1673 opn = "sub";
1674 break;
1675 case OPC_SUBU:
1676 if (rs != 0 && rt != 0) {
1677 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1678 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1679 } else if (rs == 0 && rt != 0) {
1680 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1681 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1682 } else if (rs != 0 && rt == 0) {
1683 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1684 } else {
1685 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1687 opn = "subu";
1688 break;
1689 #if defined(TARGET_MIPS64)
1690 case OPC_DADD:
1692 TCGv t0 = tcg_temp_local_new();
1693 TCGv t1 = tcg_temp_new();
1694 TCGv t2 = tcg_temp_new();
1695 int l1 = gen_new_label();
1697 gen_load_gpr(t1, rs);
1698 gen_load_gpr(t2, rt);
1699 tcg_gen_add_tl(t0, t1, t2);
1700 tcg_gen_xor_tl(t1, t1, t2);
1701 tcg_gen_xor_tl(t2, t0, t2);
1702 tcg_gen_andc_tl(t1, t2, t1);
1703 tcg_temp_free(t2);
1704 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1705 tcg_temp_free(t1);
1706 /* operands of same sign, result different sign */
1707 generate_exception(ctx, EXCP_OVERFLOW);
1708 gen_set_label(l1);
1709 gen_store_gpr(t0, rd);
1710 tcg_temp_free(t0);
1712 opn = "dadd";
1713 break;
1714 case OPC_DADDU:
1715 if (rs != 0 && rt != 0) {
1716 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1717 } else if (rs == 0 && rt != 0) {
1718 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1719 } else if (rs != 0 && rt == 0) {
1720 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1721 } else {
1722 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1724 opn = "daddu";
1725 break;
1726 case OPC_DSUB:
1728 TCGv t0 = tcg_temp_local_new();
1729 TCGv t1 = tcg_temp_new();
1730 TCGv t2 = tcg_temp_new();
1731 int l1 = gen_new_label();
1733 gen_load_gpr(t1, rs);
1734 gen_load_gpr(t2, rt);
1735 tcg_gen_sub_tl(t0, t1, t2);
1736 tcg_gen_xor_tl(t2, t1, t2);
1737 tcg_gen_xor_tl(t1, t0, t1);
1738 tcg_gen_and_tl(t1, t1, t2);
1739 tcg_temp_free(t2);
1740 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1741 tcg_temp_free(t1);
1742 /* operands of different sign, first operand and result different sign */
1743 generate_exception(ctx, EXCP_OVERFLOW);
1744 gen_set_label(l1);
1745 gen_store_gpr(t0, rd);
1746 tcg_temp_free(t0);
1748 opn = "dsub";
1749 break;
1750 case OPC_DSUBU:
1751 if (rs != 0 && rt != 0) {
1752 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1753 } else if (rs == 0 && rt != 0) {
1754 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1755 } else if (rs != 0 && rt == 0) {
1756 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1757 } else {
1758 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1760 opn = "dsubu";
1761 break;
1762 #endif
1763 case OPC_MUL:
1764 if (likely(rs != 0 && rt != 0)) {
1765 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1766 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1767 } else {
1768 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1770 opn = "mul";
1771 break;
1773 (void)opn; /* avoid a compiler warning */
1774 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1777 /* Conditional move */
1778 static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
1780 const char *opn = "cond move";
1781 int l1;
1783 if (rd == 0) {
1784 /* If no destination, treat it as a NOP.
1785 For add & sub, we must generate the overflow exception when needed. */
1786 MIPS_DEBUG("NOP");
1787 return;
1790 l1 = gen_new_label();
1791 switch (opc) {
1792 case OPC_MOVN:
1793 if (likely(rt != 0))
1794 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1795 else
1796 tcg_gen_br(l1);
1797 opn = "movn";
1798 break;
1799 case OPC_MOVZ:
1800 if (likely(rt != 0))
1801 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1802 opn = "movz";
1803 break;
1805 if (rs != 0)
1806 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1807 else
1808 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1809 gen_set_label(l1);
1811 (void)opn; /* avoid a compiler warning */
1812 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1815 /* Logic */
1816 static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
1818 const char *opn = "logic";
1820 if (rd == 0) {
1821 /* If no destination, treat it as a NOP. */
1822 MIPS_DEBUG("NOP");
1823 return;
1826 switch (opc) {
1827 case OPC_AND:
1828 if (likely(rs != 0 && rt != 0)) {
1829 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1830 } else {
1831 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1833 opn = "and";
1834 break;
1835 case OPC_NOR:
1836 if (rs != 0 && rt != 0) {
1837 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1838 } else if (rs == 0 && rt != 0) {
1839 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1840 } else if (rs != 0 && rt == 0) {
1841 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1842 } else {
1843 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1845 opn = "nor";
1846 break;
1847 case OPC_OR:
1848 if (likely(rs != 0 && rt != 0)) {
1849 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1850 } else if (rs == 0 && rt != 0) {
1851 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1852 } else if (rs != 0 && rt == 0) {
1853 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1854 } else {
1855 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1857 opn = "or";
1858 break;
1859 case OPC_XOR:
1860 if (likely(rs != 0 && rt != 0)) {
1861 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1862 } else if (rs == 0 && rt != 0) {
1863 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1864 } else if (rs != 0 && rt == 0) {
1865 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1866 } else {
1867 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1869 opn = "xor";
1870 break;
1872 (void)opn; /* avoid a compiler warning */
1873 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1876 /* Set on lower than */
1877 static void gen_slt (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
1879 const char *opn = "slt";
1880 TCGv t0, t1;
1882 if (rd == 0) {
1883 /* If no destination, treat it as a NOP. */
1884 MIPS_DEBUG("NOP");
1885 return;
1888 t0 = tcg_temp_new();
1889 t1 = tcg_temp_new();
1890 gen_load_gpr(t0, rs);
1891 gen_load_gpr(t1, rt);
1892 switch (opc) {
1893 case OPC_SLT:
1894 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
1895 opn = "slt";
1896 break;
1897 case OPC_SLTU:
1898 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
1899 opn = "sltu";
1900 break;
1902 (void)opn; /* avoid a compiler warning */
1903 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1904 tcg_temp_free(t0);
1905 tcg_temp_free(t1);
1908 /* Shifts */
1909 static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1910 int rd, int rs, int rt)
1912 const char *opn = "shifts";
1913 TCGv t0, t1;
1915 if (rd == 0) {
1916 /* If no destination, treat it as a NOP.
1917 For add & sub, we must generate the overflow exception when needed. */
1918 MIPS_DEBUG("NOP");
1919 return;
1922 t0 = tcg_temp_new();
1923 t1 = tcg_temp_new();
1924 gen_load_gpr(t0, rs);
1925 gen_load_gpr(t1, rt);
1926 switch (opc) {
1927 case OPC_SLLV:
1928 tcg_gen_andi_tl(t0, t0, 0x1f);
1929 tcg_gen_shl_tl(t0, t1, t0);
1930 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1931 opn = "sllv";
1932 break;
1933 case OPC_SRAV:
1934 tcg_gen_andi_tl(t0, t0, 0x1f);
1935 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1936 opn = "srav";
1937 break;
1938 case OPC_SRLV:
1939 tcg_gen_ext32u_tl(t1, t1);
1940 tcg_gen_andi_tl(t0, t0, 0x1f);
1941 tcg_gen_shr_tl(t0, t1, t0);
1942 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1943 opn = "srlv";
1944 break;
1945 case OPC_ROTRV:
1947 TCGv_i32 t2 = tcg_temp_new_i32();
1948 TCGv_i32 t3 = tcg_temp_new_i32();
1950 tcg_gen_trunc_tl_i32(t2, t0);
1951 tcg_gen_trunc_tl_i32(t3, t1);
1952 tcg_gen_andi_i32(t2, t2, 0x1f);
1953 tcg_gen_rotr_i32(t2, t3, t2);
1954 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1955 tcg_temp_free_i32(t2);
1956 tcg_temp_free_i32(t3);
1957 opn = "rotrv";
1959 break;
1960 #if defined(TARGET_MIPS64)
1961 case OPC_DSLLV:
1962 tcg_gen_andi_tl(t0, t0, 0x3f);
1963 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1964 opn = "dsllv";
1965 break;
1966 case OPC_DSRAV:
1967 tcg_gen_andi_tl(t0, t0, 0x3f);
1968 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1969 opn = "dsrav";
1970 break;
1971 case OPC_DSRLV:
1972 tcg_gen_andi_tl(t0, t0, 0x3f);
1973 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1974 opn = "dsrlv";
1975 break;
1976 case OPC_DROTRV:
1977 tcg_gen_andi_tl(t0, t0, 0x3f);
1978 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1979 opn = "drotrv";
1980 break;
1981 #endif
1983 (void)opn; /* avoid a compiler warning */
1984 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1985 tcg_temp_free(t0);
1986 tcg_temp_free(t1);
1989 /* Arithmetic on HI/LO registers */
1990 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1992 const char *opn = "hilo";
1994 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1995 /* Treat as NOP. */
1996 MIPS_DEBUG("NOP");
1997 return;
1999 switch (opc) {
2000 case OPC_MFHI:
2001 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
2002 opn = "mfhi";
2003 break;
2004 case OPC_MFLO:
2005 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
2006 opn = "mflo";
2007 break;
2008 case OPC_MTHI:
2009 if (reg != 0)
2010 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
2011 else
2012 tcg_gen_movi_tl(cpu_HI[0], 0);
2013 opn = "mthi";
2014 break;
2015 case OPC_MTLO:
2016 if (reg != 0)
2017 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2018 else
2019 tcg_gen_movi_tl(cpu_LO[0], 0);
2020 opn = "mtlo";
2021 break;
2023 (void)opn; /* avoid a compiler warning */
2024 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2027 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
2028 int rs, int rt)
2030 const char *opn = "mul/div";
2031 TCGv t0, t1;
2033 switch (opc) {
2034 case OPC_DIV:
2035 case OPC_DIVU:
2036 #if defined(TARGET_MIPS64)
2037 case OPC_DDIV:
2038 case OPC_DDIVU:
2039 #endif
2040 t0 = tcg_temp_local_new();
2041 t1 = tcg_temp_local_new();
2042 break;
2043 default:
2044 t0 = tcg_temp_new();
2045 t1 = tcg_temp_new();
2046 break;
2049 gen_load_gpr(t0, rs);
2050 gen_load_gpr(t1, rt);
2051 switch (opc) {
2052 case OPC_DIV:
2054 int l1 = gen_new_label();
2055 int l2 = gen_new_label();
2057 tcg_gen_ext32s_tl(t0, t0);
2058 tcg_gen_ext32s_tl(t1, t1);
2059 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2060 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2061 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2063 tcg_gen_mov_tl(cpu_LO[0], t0);
2064 tcg_gen_movi_tl(cpu_HI[0], 0);
2065 tcg_gen_br(l1);
2066 gen_set_label(l2);
2067 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2068 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2069 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2070 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2071 gen_set_label(l1);
2073 opn = "div";
2074 break;
2075 case OPC_DIVU:
2077 int l1 = gen_new_label();
2079 tcg_gen_ext32u_tl(t0, t0);
2080 tcg_gen_ext32u_tl(t1, t1);
2081 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2082 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2083 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2084 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2085 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2086 gen_set_label(l1);
2088 opn = "divu";
2089 break;
2090 case OPC_MULT:
2092 TCGv_i64 t2 = tcg_temp_new_i64();
2093 TCGv_i64 t3 = tcg_temp_new_i64();
2095 tcg_gen_ext_tl_i64(t2, t0);
2096 tcg_gen_ext_tl_i64(t3, t1);
2097 tcg_gen_mul_i64(t2, t2, t3);
2098 tcg_temp_free_i64(t3);
2099 tcg_gen_trunc_i64_tl(t0, t2);
2100 tcg_gen_shri_i64(t2, t2, 32);
2101 tcg_gen_trunc_i64_tl(t1, t2);
2102 tcg_temp_free_i64(t2);
2103 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2104 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2106 opn = "mult";
2107 break;
2108 case OPC_MULTU:
2110 TCGv_i64 t2 = tcg_temp_new_i64();
2111 TCGv_i64 t3 = tcg_temp_new_i64();
2113 tcg_gen_ext32u_tl(t0, t0);
2114 tcg_gen_ext32u_tl(t1, t1);
2115 tcg_gen_extu_tl_i64(t2, t0);
2116 tcg_gen_extu_tl_i64(t3, t1);
2117 tcg_gen_mul_i64(t2, t2, t3);
2118 tcg_temp_free_i64(t3);
2119 tcg_gen_trunc_i64_tl(t0, t2);
2120 tcg_gen_shri_i64(t2, t2, 32);
2121 tcg_gen_trunc_i64_tl(t1, t2);
2122 tcg_temp_free_i64(t2);
2123 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2124 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2126 opn = "multu";
2127 break;
2128 #if defined(TARGET_MIPS64)
2129 case OPC_DDIV:
2131 int l1 = gen_new_label();
2132 int l2 = gen_new_label();
2134 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2135 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2136 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2137 tcg_gen_mov_tl(cpu_LO[0], t0);
2138 tcg_gen_movi_tl(cpu_HI[0], 0);
2139 tcg_gen_br(l1);
2140 gen_set_label(l2);
2141 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2142 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2143 gen_set_label(l1);
2145 opn = "ddiv";
2146 break;
2147 case OPC_DDIVU:
2149 int l1 = gen_new_label();
2151 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2152 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2153 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2154 gen_set_label(l1);
2156 opn = "ddivu";
2157 break;
2158 case OPC_DMULT:
2159 gen_helper_dmult(cpu_env, t0, t1);
2160 opn = "dmult";
2161 break;
2162 case OPC_DMULTU:
2163 gen_helper_dmultu(cpu_env, t0, t1);
2164 opn = "dmultu";
2165 break;
2166 #endif
2167 case OPC_MADD:
2169 TCGv_i64 t2 = tcg_temp_new_i64();
2170 TCGv_i64 t3 = tcg_temp_new_i64();
2172 tcg_gen_ext_tl_i64(t2, t0);
2173 tcg_gen_ext_tl_i64(t3, t1);
2174 tcg_gen_mul_i64(t2, t2, t3);
2175 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2176 tcg_gen_add_i64(t2, t2, t3);
2177 tcg_temp_free_i64(t3);
2178 tcg_gen_trunc_i64_tl(t0, t2);
2179 tcg_gen_shri_i64(t2, t2, 32);
2180 tcg_gen_trunc_i64_tl(t1, t2);
2181 tcg_temp_free_i64(t2);
2182 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2183 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2185 opn = "madd";
2186 break;
2187 case OPC_MADDU:
2189 TCGv_i64 t2 = tcg_temp_new_i64();
2190 TCGv_i64 t3 = tcg_temp_new_i64();
2192 tcg_gen_ext32u_tl(t0, t0);
2193 tcg_gen_ext32u_tl(t1, t1);
2194 tcg_gen_extu_tl_i64(t2, t0);
2195 tcg_gen_extu_tl_i64(t3, t1);
2196 tcg_gen_mul_i64(t2, t2, t3);
2197 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2198 tcg_gen_add_i64(t2, t2, t3);
2199 tcg_temp_free_i64(t3);
2200 tcg_gen_trunc_i64_tl(t0, t2);
2201 tcg_gen_shri_i64(t2, t2, 32);
2202 tcg_gen_trunc_i64_tl(t1, t2);
2203 tcg_temp_free_i64(t2);
2204 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2205 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2207 opn = "maddu";
2208 break;
2209 case OPC_MSUB:
2211 TCGv_i64 t2 = tcg_temp_new_i64();
2212 TCGv_i64 t3 = tcg_temp_new_i64();
2214 tcg_gen_ext_tl_i64(t2, t0);
2215 tcg_gen_ext_tl_i64(t3, t1);
2216 tcg_gen_mul_i64(t2, t2, t3);
2217 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2218 tcg_gen_sub_i64(t2, t3, t2);
2219 tcg_temp_free_i64(t3);
2220 tcg_gen_trunc_i64_tl(t0, t2);
2221 tcg_gen_shri_i64(t2, t2, 32);
2222 tcg_gen_trunc_i64_tl(t1, t2);
2223 tcg_temp_free_i64(t2);
2224 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2225 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2227 opn = "msub";
2228 break;
2229 case OPC_MSUBU:
2231 TCGv_i64 t2 = tcg_temp_new_i64();
2232 TCGv_i64 t3 = tcg_temp_new_i64();
2234 tcg_gen_ext32u_tl(t0, t0);
2235 tcg_gen_ext32u_tl(t1, t1);
2236 tcg_gen_extu_tl_i64(t2, t0);
2237 tcg_gen_extu_tl_i64(t3, t1);
2238 tcg_gen_mul_i64(t2, t2, t3);
2239 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2240 tcg_gen_sub_i64(t2, t3, t2);
2241 tcg_temp_free_i64(t3);
2242 tcg_gen_trunc_i64_tl(t0, t2);
2243 tcg_gen_shri_i64(t2, t2, 32);
2244 tcg_gen_trunc_i64_tl(t1, t2);
2245 tcg_temp_free_i64(t2);
2246 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2247 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2249 opn = "msubu";
2250 break;
2251 default:
2252 MIPS_INVAL(opn);
2253 generate_exception(ctx, EXCP_RI);
2254 goto out;
2256 (void)opn; /* avoid a compiler warning */
2257 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2258 out:
2259 tcg_temp_free(t0);
2260 tcg_temp_free(t1);
2263 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2264 int rd, int rs, int rt)
2266 const char *opn = "mul vr54xx";
2267 TCGv t0 = tcg_temp_new();
2268 TCGv t1 = tcg_temp_new();
2270 gen_load_gpr(t0, rs);
2271 gen_load_gpr(t1, rt);
2273 switch (opc) {
2274 case OPC_VR54XX_MULS:
2275 gen_helper_muls(t0, cpu_env, t0, t1);
2276 opn = "muls";
2277 break;
2278 case OPC_VR54XX_MULSU:
2279 gen_helper_mulsu(t0, cpu_env, t0, t1);
2280 opn = "mulsu";
2281 break;
2282 case OPC_VR54XX_MACC:
2283 gen_helper_macc(t0, cpu_env, t0, t1);
2284 opn = "macc";
2285 break;
2286 case OPC_VR54XX_MACCU:
2287 gen_helper_maccu(t0, cpu_env, t0, t1);
2288 opn = "maccu";
2289 break;
2290 case OPC_VR54XX_MSAC:
2291 gen_helper_msac(t0, cpu_env, t0, t1);
2292 opn = "msac";
2293 break;
2294 case OPC_VR54XX_MSACU:
2295 gen_helper_msacu(t0, cpu_env, t0, t1);
2296 opn = "msacu";
2297 break;
2298 case OPC_VR54XX_MULHI:
2299 gen_helper_mulhi(t0, cpu_env, t0, t1);
2300 opn = "mulhi";
2301 break;
2302 case OPC_VR54XX_MULHIU:
2303 gen_helper_mulhiu(t0, cpu_env, t0, t1);
2304 opn = "mulhiu";
2305 break;
2306 case OPC_VR54XX_MULSHI:
2307 gen_helper_mulshi(t0, cpu_env, t0, t1);
2308 opn = "mulshi";
2309 break;
2310 case OPC_VR54XX_MULSHIU:
2311 gen_helper_mulshiu(t0, cpu_env, t0, t1);
2312 opn = "mulshiu";
2313 break;
2314 case OPC_VR54XX_MACCHI:
2315 gen_helper_macchi(t0, cpu_env, t0, t1);
2316 opn = "macchi";
2317 break;
2318 case OPC_VR54XX_MACCHIU:
2319 gen_helper_macchiu(t0, cpu_env, t0, t1);
2320 opn = "macchiu";
2321 break;
2322 case OPC_VR54XX_MSACHI:
2323 gen_helper_msachi(t0, cpu_env, t0, t1);
2324 opn = "msachi";
2325 break;
2326 case OPC_VR54XX_MSACHIU:
2327 gen_helper_msachiu(t0, cpu_env, t0, t1);
2328 opn = "msachiu";
2329 break;
2330 default:
2331 MIPS_INVAL("mul vr54xx");
2332 generate_exception(ctx, EXCP_RI);
2333 goto out;
2335 gen_store_gpr(t0, rd);
2336 (void)opn; /* avoid a compiler warning */
2337 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2339 out:
2340 tcg_temp_free(t0);
2341 tcg_temp_free(t1);
2344 static void gen_cl (DisasContext *ctx, uint32_t opc,
2345 int rd, int rs)
2347 const char *opn = "CLx";
2348 TCGv t0;
2350 if (rd == 0) {
2351 /* Treat as NOP. */
2352 MIPS_DEBUG("NOP");
2353 return;
2355 t0 = tcg_temp_new();
2356 gen_load_gpr(t0, rs);
2357 switch (opc) {
2358 case OPC_CLO:
2359 gen_helper_clo(cpu_gpr[rd], t0);
2360 opn = "clo";
2361 break;
2362 case OPC_CLZ:
2363 gen_helper_clz(cpu_gpr[rd], t0);
2364 opn = "clz";
2365 break;
2366 #if defined(TARGET_MIPS64)
2367 case OPC_DCLO:
2368 gen_helper_dclo(cpu_gpr[rd], t0);
2369 opn = "dclo";
2370 break;
2371 case OPC_DCLZ:
2372 gen_helper_dclz(cpu_gpr[rd], t0);
2373 opn = "dclz";
2374 break;
2375 #endif
2377 (void)opn; /* avoid a compiler warning */
2378 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2379 tcg_temp_free(t0);
2382 /* Godson integer instructions */
2383 static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
2384 int rd, int rs, int rt)
2386 const char *opn = "loongson";
2387 TCGv t0, t1;
2389 if (rd == 0) {
2390 /* Treat as NOP. */
2391 MIPS_DEBUG("NOP");
2392 return;
2395 switch (opc) {
2396 case OPC_MULT_G_2E:
2397 case OPC_MULT_G_2F:
2398 case OPC_MULTU_G_2E:
2399 case OPC_MULTU_G_2F:
2400 #if defined(TARGET_MIPS64)
2401 case OPC_DMULT_G_2E:
2402 case OPC_DMULT_G_2F:
2403 case OPC_DMULTU_G_2E:
2404 case OPC_DMULTU_G_2F:
2405 #endif
2406 t0 = tcg_temp_new();
2407 t1 = tcg_temp_new();
2408 break;
2409 default:
2410 t0 = tcg_temp_local_new();
2411 t1 = tcg_temp_local_new();
2412 break;
2415 gen_load_gpr(t0, rs);
2416 gen_load_gpr(t1, rt);
2418 switch (opc) {
2419 case OPC_MULT_G_2E:
2420 case OPC_MULT_G_2F:
2421 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2422 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2423 opn = "mult.g";
2424 break;
2425 case OPC_MULTU_G_2E:
2426 case OPC_MULTU_G_2F:
2427 tcg_gen_ext32u_tl(t0, t0);
2428 tcg_gen_ext32u_tl(t1, t1);
2429 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2430 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2431 opn = "multu.g";
2432 break;
2433 case OPC_DIV_G_2E:
2434 case OPC_DIV_G_2F:
2436 int l1 = gen_new_label();
2437 int l2 = gen_new_label();
2438 int l3 = gen_new_label();
2439 tcg_gen_ext32s_tl(t0, t0);
2440 tcg_gen_ext32s_tl(t1, t1);
2441 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2442 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2443 tcg_gen_br(l3);
2444 gen_set_label(l1);
2445 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2446 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2447 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2448 tcg_gen_br(l3);
2449 gen_set_label(l2);
2450 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2451 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2452 gen_set_label(l3);
2454 opn = "div.g";
2455 break;
2456 case OPC_DIVU_G_2E:
2457 case OPC_DIVU_G_2F:
2459 int l1 = gen_new_label();
2460 int l2 = gen_new_label();
2461 tcg_gen_ext32u_tl(t0, t0);
2462 tcg_gen_ext32u_tl(t1, t1);
2463 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2464 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2465 tcg_gen_br(l2);
2466 gen_set_label(l1);
2467 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2468 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2469 gen_set_label(l2);
2471 opn = "divu.g";
2472 break;
2473 case OPC_MOD_G_2E:
2474 case OPC_MOD_G_2F:
2476 int l1 = gen_new_label();
2477 int l2 = gen_new_label();
2478 int l3 = gen_new_label();
2479 tcg_gen_ext32u_tl(t0, t0);
2480 tcg_gen_ext32u_tl(t1, t1);
2481 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2482 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2483 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2484 gen_set_label(l1);
2485 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2486 tcg_gen_br(l3);
2487 gen_set_label(l2);
2488 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2489 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2490 gen_set_label(l3);
2492 opn = "mod.g";
2493 break;
2494 case OPC_MODU_G_2E:
2495 case OPC_MODU_G_2F:
2497 int l1 = gen_new_label();
2498 int l2 = gen_new_label();
2499 tcg_gen_ext32u_tl(t0, t0);
2500 tcg_gen_ext32u_tl(t1, t1);
2501 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2502 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2503 tcg_gen_br(l2);
2504 gen_set_label(l1);
2505 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2506 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2507 gen_set_label(l2);
2509 opn = "modu.g";
2510 break;
2511 #if defined(TARGET_MIPS64)
2512 case OPC_DMULT_G_2E:
2513 case OPC_DMULT_G_2F:
2514 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2515 opn = "dmult.g";
2516 break;
2517 case OPC_DMULTU_G_2E:
2518 case OPC_DMULTU_G_2F:
2519 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2520 opn = "dmultu.g";
2521 break;
2522 case OPC_DDIV_G_2E:
2523 case OPC_DDIV_G_2F:
2525 int l1 = gen_new_label();
2526 int l2 = gen_new_label();
2527 int l3 = gen_new_label();
2528 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2529 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2530 tcg_gen_br(l3);
2531 gen_set_label(l1);
2532 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2533 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2534 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2535 tcg_gen_br(l3);
2536 gen_set_label(l2);
2537 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2538 gen_set_label(l3);
2540 opn = "ddiv.g";
2541 break;
2542 case OPC_DDIVU_G_2E:
2543 case OPC_DDIVU_G_2F:
2545 int l1 = gen_new_label();
2546 int l2 = gen_new_label();
2547 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2548 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2549 tcg_gen_br(l2);
2550 gen_set_label(l1);
2551 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2552 gen_set_label(l2);
2554 opn = "ddivu.g";
2555 break;
2556 case OPC_DMOD_G_2E:
2557 case OPC_DMOD_G_2F:
2559 int l1 = gen_new_label();
2560 int l2 = gen_new_label();
2561 int l3 = gen_new_label();
2562 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2563 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2564 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2565 gen_set_label(l1);
2566 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2567 tcg_gen_br(l3);
2568 gen_set_label(l2);
2569 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2570 gen_set_label(l3);
2572 opn = "dmod.g";
2573 break;
2574 case OPC_DMODU_G_2E:
2575 case OPC_DMODU_G_2F:
2577 int l1 = gen_new_label();
2578 int l2 = gen_new_label();
2579 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2580 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2581 tcg_gen_br(l2);
2582 gen_set_label(l1);
2583 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2584 gen_set_label(l2);
2586 opn = "dmodu.g";
2587 break;
2588 #endif
2591 (void)opn; /* avoid a compiler warning */
2592 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2593 tcg_temp_free(t0);
2594 tcg_temp_free(t1);
2597 /* Traps */
2598 static void gen_trap (DisasContext *ctx, uint32_t opc,
2599 int rs, int rt, int16_t imm)
2601 int cond;
2602 TCGv t0 = tcg_temp_new();
2603 TCGv t1 = tcg_temp_new();
2605 cond = 0;
2606 /* Load needed operands */
2607 switch (opc) {
2608 case OPC_TEQ:
2609 case OPC_TGE:
2610 case OPC_TGEU:
2611 case OPC_TLT:
2612 case OPC_TLTU:
2613 case OPC_TNE:
2614 /* Compare two registers */
2615 if (rs != rt) {
2616 gen_load_gpr(t0, rs);
2617 gen_load_gpr(t1, rt);
2618 cond = 1;
2620 break;
2621 case OPC_TEQI:
2622 case OPC_TGEI:
2623 case OPC_TGEIU:
2624 case OPC_TLTI:
2625 case OPC_TLTIU:
2626 case OPC_TNEI:
2627 /* Compare register to immediate */
2628 if (rs != 0 || imm != 0) {
2629 gen_load_gpr(t0, rs);
2630 tcg_gen_movi_tl(t1, (int32_t)imm);
2631 cond = 1;
2633 break;
2635 if (cond == 0) {
2636 switch (opc) {
2637 case OPC_TEQ: /* rs == rs */
2638 case OPC_TEQI: /* r0 == 0 */
2639 case OPC_TGE: /* rs >= rs */
2640 case OPC_TGEI: /* r0 >= 0 */
2641 case OPC_TGEU: /* rs >= rs unsigned */
2642 case OPC_TGEIU: /* r0 >= 0 unsigned */
2643 /* Always trap */
2644 generate_exception(ctx, EXCP_TRAP);
2645 break;
2646 case OPC_TLT: /* rs < rs */
2647 case OPC_TLTI: /* r0 < 0 */
2648 case OPC_TLTU: /* rs < rs unsigned */
2649 case OPC_TLTIU: /* r0 < 0 unsigned */
2650 case OPC_TNE: /* rs != rs */
2651 case OPC_TNEI: /* r0 != 0 */
2652 /* Never trap: treat as NOP. */
2653 break;
2655 } else {
2656 int l1 = gen_new_label();
2658 switch (opc) {
2659 case OPC_TEQ:
2660 case OPC_TEQI:
2661 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2662 break;
2663 case OPC_TGE:
2664 case OPC_TGEI:
2665 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2666 break;
2667 case OPC_TGEU:
2668 case OPC_TGEIU:
2669 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2670 break;
2671 case OPC_TLT:
2672 case OPC_TLTI:
2673 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2674 break;
2675 case OPC_TLTU:
2676 case OPC_TLTIU:
2677 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2678 break;
2679 case OPC_TNE:
2680 case OPC_TNEI:
2681 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2682 break;
2684 generate_exception(ctx, EXCP_TRAP);
2685 gen_set_label(l1);
2687 tcg_temp_free(t0);
2688 tcg_temp_free(t1);
2691 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2693 TranslationBlock *tb;
2694 tb = ctx->tb;
2695 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2696 likely(!ctx->singlestep_enabled)) {
2697 tcg_gen_goto_tb(n);
2698 gen_save_pc(dest);
2699 tcg_gen_exit_tb((tcg_target_long)tb + n);
2700 } else {
2701 gen_save_pc(dest);
2702 if (ctx->singlestep_enabled) {
2703 save_cpu_state(ctx, 0);
2704 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
2706 tcg_gen_exit_tb(0);
2710 /* Branches (before delay slot) */
2711 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2712 int insn_bytes,
2713 int rs, int rt, int32_t offset)
2715 target_ulong btgt = -1;
2716 int blink = 0;
2717 int bcond_compute = 0;
2718 TCGv t0 = tcg_temp_new();
2719 TCGv t1 = tcg_temp_new();
2721 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2722 #ifdef MIPS_DEBUG_DISAS
2723 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2724 #endif
2725 generate_exception(ctx, EXCP_RI);
2726 goto out;
2729 /* Load needed operands */
2730 switch (opc) {
2731 case OPC_BEQ:
2732 case OPC_BEQL:
2733 case OPC_BNE:
2734 case OPC_BNEL:
2735 /* Compare two registers */
2736 if (rs != rt) {
2737 gen_load_gpr(t0, rs);
2738 gen_load_gpr(t1, rt);
2739 bcond_compute = 1;
2741 btgt = ctx->pc + insn_bytes + offset;
2742 break;
2743 case OPC_BGEZ:
2744 case OPC_BGEZAL:
2745 case OPC_BGEZALS:
2746 case OPC_BGEZALL:
2747 case OPC_BGEZL:
2748 case OPC_BGTZ:
2749 case OPC_BGTZL:
2750 case OPC_BLEZ:
2751 case OPC_BLEZL:
2752 case OPC_BLTZ:
2753 case OPC_BLTZAL:
2754 case OPC_BLTZALS:
2755 case OPC_BLTZALL:
2756 case OPC_BLTZL:
2757 /* Compare to zero */
2758 if (rs != 0) {
2759 gen_load_gpr(t0, rs);
2760 bcond_compute = 1;
2762 btgt = ctx->pc + insn_bytes + offset;
2763 break;
2764 case OPC_J:
2765 case OPC_JAL:
2766 case OPC_JALX:
2767 case OPC_JALS:
2768 case OPC_JALXS:
2769 /* Jump to immediate */
2770 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
2771 break;
2772 case OPC_JR:
2773 case OPC_JALR:
2774 case OPC_JALRC:
2775 case OPC_JALRS:
2776 /* Jump to register */
2777 if (offset != 0 && offset != 16) {
2778 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2779 others are reserved. */
2780 MIPS_INVAL("jump hint");
2781 generate_exception(ctx, EXCP_RI);
2782 goto out;
2784 gen_load_gpr(btarget, rs);
2785 break;
2786 default:
2787 MIPS_INVAL("branch/jump");
2788 generate_exception(ctx, EXCP_RI);
2789 goto out;
2791 if (bcond_compute == 0) {
2792 /* No condition to be computed */
2793 switch (opc) {
2794 case OPC_BEQ: /* rx == rx */
2795 case OPC_BEQL: /* rx == rx likely */
2796 case OPC_BGEZ: /* 0 >= 0 */
2797 case OPC_BGEZL: /* 0 >= 0 likely */
2798 case OPC_BLEZ: /* 0 <= 0 */
2799 case OPC_BLEZL: /* 0 <= 0 likely */
2800 /* Always take */
2801 ctx->hflags |= MIPS_HFLAG_B;
2802 MIPS_DEBUG("balways");
2803 break;
2804 case OPC_BGEZALS:
2805 case OPC_BGEZAL: /* 0 >= 0 */
2806 case OPC_BGEZALL: /* 0 >= 0 likely */
2807 ctx->hflags |= (opc == OPC_BGEZALS
2808 ? MIPS_HFLAG_BDS16
2809 : MIPS_HFLAG_BDS32);
2810 /* Always take and link */
2811 blink = 31;
2812 ctx->hflags |= MIPS_HFLAG_B;
2813 MIPS_DEBUG("balways and link");
2814 break;
2815 case OPC_BNE: /* rx != rx */
2816 case OPC_BGTZ: /* 0 > 0 */
2817 case OPC_BLTZ: /* 0 < 0 */
2818 /* Treat as NOP. */
2819 MIPS_DEBUG("bnever (NOP)");
2820 goto out;
2821 case OPC_BLTZALS:
2822 case OPC_BLTZAL: /* 0 < 0 */
2823 ctx->hflags |= (opc == OPC_BLTZALS
2824 ? MIPS_HFLAG_BDS16
2825 : MIPS_HFLAG_BDS32);
2826 /* Handle as an unconditional branch to get correct delay
2827 slot checking. */
2828 blink = 31;
2829 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
2830 ctx->hflags |= MIPS_HFLAG_B;
2831 MIPS_DEBUG("bnever and link");
2832 break;
2833 case OPC_BLTZALL: /* 0 < 0 likely */
2834 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2835 /* Skip the instruction in the delay slot */
2836 MIPS_DEBUG("bnever, link and skip");
2837 ctx->pc += 4;
2838 goto out;
2839 case OPC_BNEL: /* rx != rx likely */
2840 case OPC_BGTZL: /* 0 > 0 likely */
2841 case OPC_BLTZL: /* 0 < 0 likely */
2842 /* Skip the instruction in the delay slot */
2843 MIPS_DEBUG("bnever and skip");
2844 ctx->pc += 4;
2845 goto out;
2846 case OPC_J:
2847 ctx->hflags |= MIPS_HFLAG_B;
2848 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2849 break;
2850 case OPC_JALXS:
2851 case OPC_JALX:
2852 ctx->hflags |= MIPS_HFLAG_BX;
2853 /* Fallthrough */
2854 case OPC_JALS:
2855 case OPC_JAL:
2856 blink = 31;
2857 ctx->hflags |= MIPS_HFLAG_B;
2858 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
2859 ? MIPS_HFLAG_BDS16
2860 : MIPS_HFLAG_BDS32);
2861 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2862 break;
2863 case OPC_JR:
2864 ctx->hflags |= MIPS_HFLAG_BR;
2865 if (insn_bytes == 4)
2866 ctx->hflags |= MIPS_HFLAG_BDS32;
2867 MIPS_DEBUG("jr %s", regnames[rs]);
2868 break;
2869 case OPC_JALRS:
2870 case OPC_JALR:
2871 case OPC_JALRC:
2872 blink = rt;
2873 ctx->hflags |= MIPS_HFLAG_BR;
2874 ctx->hflags |= (opc == OPC_JALRS
2875 ? MIPS_HFLAG_BDS16
2876 : MIPS_HFLAG_BDS32);
2877 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2878 break;
2879 default:
2880 MIPS_INVAL("branch/jump");
2881 generate_exception(ctx, EXCP_RI);
2882 goto out;
2884 } else {
2885 switch (opc) {
2886 case OPC_BEQ:
2887 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2888 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2889 regnames[rs], regnames[rt], btgt);
2890 goto not_likely;
2891 case OPC_BEQL:
2892 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2893 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2894 regnames[rs], regnames[rt], btgt);
2895 goto likely;
2896 case OPC_BNE:
2897 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2898 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2899 regnames[rs], regnames[rt], btgt);
2900 goto not_likely;
2901 case OPC_BNEL:
2902 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2903 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2904 regnames[rs], regnames[rt], btgt);
2905 goto likely;
2906 case OPC_BGEZ:
2907 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2908 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2909 goto not_likely;
2910 case OPC_BGEZL:
2911 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2912 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2913 goto likely;
2914 case OPC_BGEZALS:
2915 case OPC_BGEZAL:
2916 ctx->hflags |= (opc == OPC_BGEZALS
2917 ? MIPS_HFLAG_BDS16
2918 : MIPS_HFLAG_BDS32);
2919 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2920 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2921 blink = 31;
2922 goto not_likely;
2923 case OPC_BGEZALL:
2924 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2925 blink = 31;
2926 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2927 goto likely;
2928 case OPC_BGTZ:
2929 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2930 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2931 goto not_likely;
2932 case OPC_BGTZL:
2933 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2934 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2935 goto likely;
2936 case OPC_BLEZ:
2937 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2938 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2939 goto not_likely;
2940 case OPC_BLEZL:
2941 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2942 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2943 goto likely;
2944 case OPC_BLTZ:
2945 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2946 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2947 goto not_likely;
2948 case OPC_BLTZL:
2949 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2950 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2951 goto likely;
2952 case OPC_BLTZALS:
2953 case OPC_BLTZAL:
2954 ctx->hflags |= (opc == OPC_BLTZALS
2955 ? MIPS_HFLAG_BDS16
2956 : MIPS_HFLAG_BDS32);
2957 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2958 blink = 31;
2959 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2960 not_likely:
2961 ctx->hflags |= MIPS_HFLAG_BC;
2962 break;
2963 case OPC_BLTZALL:
2964 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2965 blink = 31;
2966 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2967 likely:
2968 ctx->hflags |= MIPS_HFLAG_BL;
2969 break;
2970 default:
2971 MIPS_INVAL("conditional branch/jump");
2972 generate_exception(ctx, EXCP_RI);
2973 goto out;
2976 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2977 blink, ctx->hflags, btgt);
2979 ctx->btarget = btgt;
2980 if (blink > 0) {
2981 int post_delay = insn_bytes;
2982 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2984 if (opc != OPC_JALRC)
2985 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2987 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
2990 out:
2991 if (insn_bytes == 2)
2992 ctx->hflags |= MIPS_HFLAG_B16;
2993 tcg_temp_free(t0);
2994 tcg_temp_free(t1);
2997 /* special3 bitfield operations */
2998 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2999 int rs, int lsb, int msb)
3001 TCGv t0 = tcg_temp_new();
3002 TCGv t1 = tcg_temp_new();
3003 target_ulong mask;
3005 gen_load_gpr(t1, rs);
3006 switch (opc) {
3007 case OPC_EXT:
3008 if (lsb + msb > 31)
3009 goto fail;
3010 tcg_gen_shri_tl(t0, t1, lsb);
3011 if (msb != 31) {
3012 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3013 } else {
3014 tcg_gen_ext32s_tl(t0, t0);
3016 break;
3017 #if defined(TARGET_MIPS64)
3018 case OPC_DEXTM:
3019 tcg_gen_shri_tl(t0, t1, lsb);
3020 if (msb != 31) {
3021 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3023 break;
3024 case OPC_DEXTU:
3025 tcg_gen_shri_tl(t0, t1, lsb + 32);
3026 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3027 break;
3028 case OPC_DEXT:
3029 tcg_gen_shri_tl(t0, t1, lsb);
3030 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3031 break;
3032 #endif
3033 case OPC_INS:
3034 if (lsb > msb)
3035 goto fail;
3036 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
3037 gen_load_gpr(t0, rt);
3038 tcg_gen_andi_tl(t0, t0, ~mask);
3039 tcg_gen_shli_tl(t1, t1, lsb);
3040 tcg_gen_andi_tl(t1, t1, mask);
3041 tcg_gen_or_tl(t0, t0, t1);
3042 tcg_gen_ext32s_tl(t0, t0);
3043 break;
3044 #if defined(TARGET_MIPS64)
3045 case OPC_DINSM:
3046 if (lsb > msb)
3047 goto fail;
3048 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
3049 gen_load_gpr(t0, rt);
3050 tcg_gen_andi_tl(t0, t0, ~mask);
3051 tcg_gen_shli_tl(t1, t1, lsb);
3052 tcg_gen_andi_tl(t1, t1, mask);
3053 tcg_gen_or_tl(t0, t0, t1);
3054 break;
3055 case OPC_DINSU:
3056 if (lsb > msb)
3057 goto fail;
3058 mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
3059 gen_load_gpr(t0, rt);
3060 tcg_gen_andi_tl(t0, t0, ~mask);
3061 tcg_gen_shli_tl(t1, t1, lsb + 32);
3062 tcg_gen_andi_tl(t1, t1, mask);
3063 tcg_gen_or_tl(t0, t0, t1);
3064 break;
3065 case OPC_DINS:
3066 if (lsb > msb)
3067 goto fail;
3068 gen_load_gpr(t0, rt);
3069 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3070 gen_load_gpr(t0, rt);
3071 tcg_gen_andi_tl(t0, t0, ~mask);
3072 tcg_gen_shli_tl(t1, t1, lsb);
3073 tcg_gen_andi_tl(t1, t1, mask);
3074 tcg_gen_or_tl(t0, t0, t1);
3075 break;
3076 #endif
3077 default:
3078 fail:
3079 MIPS_INVAL("bitops");
3080 generate_exception(ctx, EXCP_RI);
3081 tcg_temp_free(t0);
3082 tcg_temp_free(t1);
3083 return;
3085 gen_store_gpr(t0, rt);
3086 tcg_temp_free(t0);
3087 tcg_temp_free(t1);
3090 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3092 TCGv t0;
3094 if (rd == 0) {
3095 /* If no destination, treat it as a NOP. */
3096 MIPS_DEBUG("NOP");
3097 return;
3100 t0 = tcg_temp_new();
3101 gen_load_gpr(t0, rt);
3102 switch (op2) {
3103 case OPC_WSBH:
3105 TCGv t1 = tcg_temp_new();
3107 tcg_gen_shri_tl(t1, t0, 8);
3108 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3109 tcg_gen_shli_tl(t0, t0, 8);
3110 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3111 tcg_gen_or_tl(t0, t0, t1);
3112 tcg_temp_free(t1);
3113 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3115 break;
3116 case OPC_SEB:
3117 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
3118 break;
3119 case OPC_SEH:
3120 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
3121 break;
3122 #if defined(TARGET_MIPS64)
3123 case OPC_DSBH:
3125 TCGv t1 = tcg_temp_new();
3127 tcg_gen_shri_tl(t1, t0, 8);
3128 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3129 tcg_gen_shli_tl(t0, t0, 8);
3130 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3131 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3132 tcg_temp_free(t1);
3134 break;
3135 case OPC_DSHD:
3137 TCGv t1 = tcg_temp_new();
3139 tcg_gen_shri_tl(t1, t0, 16);
3140 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3141 tcg_gen_shli_tl(t0, t0, 16);
3142 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3143 tcg_gen_or_tl(t0, t0, t1);
3144 tcg_gen_shri_tl(t1, t0, 32);
3145 tcg_gen_shli_tl(t0, t0, 32);
3146 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3147 tcg_temp_free(t1);
3149 break;
3150 #endif
3151 default:
3152 MIPS_INVAL("bsfhl");
3153 generate_exception(ctx, EXCP_RI);
3154 tcg_temp_free(t0);
3155 return;
3157 tcg_temp_free(t0);
3160 #ifndef CONFIG_USER_ONLY
3161 /* CP0 (MMU and control) */
3162 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
3164 TCGv_i32 t0 = tcg_temp_new_i32();
3166 tcg_gen_ld_i32(t0, cpu_env, off);
3167 tcg_gen_ext_i32_tl(arg, t0);
3168 tcg_temp_free_i32(t0);
3171 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
3173 tcg_gen_ld_tl(arg, cpu_env, off);
3174 tcg_gen_ext32s_tl(arg, arg);
3177 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
3179 TCGv_i32 t0 = tcg_temp_new_i32();
3181 tcg_gen_trunc_tl_i32(t0, arg);
3182 tcg_gen_st_i32(t0, cpu_env, off);
3183 tcg_temp_free_i32(t0);
3186 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
3188 tcg_gen_ext32s_tl(arg, arg);
3189 tcg_gen_st_tl(arg, cpu_env, off);
3192 static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3194 const char *rn = "invalid";
3196 if (sel != 0)
3197 check_insn(env, ctx, ISA_MIPS32);
3199 switch (reg) {
3200 case 0:
3201 switch (sel) {
3202 case 0:
3203 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
3204 rn = "Index";
3205 break;
3206 case 1:
3207 check_insn(env, ctx, ASE_MT);
3208 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
3209 rn = "MVPControl";
3210 break;
3211 case 2:
3212 check_insn(env, ctx, ASE_MT);
3213 gen_helper_mfc0_mvpconf0(arg, cpu_env);
3214 rn = "MVPConf0";
3215 break;
3216 case 3:
3217 check_insn(env, ctx, ASE_MT);
3218 gen_helper_mfc0_mvpconf1(arg, cpu_env);
3219 rn = "MVPConf1";
3220 break;
3221 default:
3222 goto die;
3224 break;
3225 case 1:
3226 switch (sel) {
3227 case 0:
3228 gen_helper_mfc0_random(arg, cpu_env);
3229 rn = "Random";
3230 break;
3231 case 1:
3232 check_insn(env, ctx, ASE_MT);
3233 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
3234 rn = "VPEControl";
3235 break;
3236 case 2:
3237 check_insn(env, ctx, ASE_MT);
3238 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
3239 rn = "VPEConf0";
3240 break;
3241 case 3:
3242 check_insn(env, ctx, ASE_MT);
3243 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
3244 rn = "VPEConf1";
3245 break;
3246 case 4:
3247 check_insn(env, ctx, ASE_MT);
3248 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
3249 rn = "YQMask";
3250 break;
3251 case 5:
3252 check_insn(env, ctx, ASE_MT);
3253 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
3254 rn = "VPESchedule";
3255 break;
3256 case 6:
3257 check_insn(env, ctx, ASE_MT);
3258 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
3259 rn = "VPEScheFBack";
3260 break;
3261 case 7:
3262 check_insn(env, ctx, ASE_MT);
3263 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
3264 rn = "VPEOpt";
3265 break;
3266 default:
3267 goto die;
3269 break;
3270 case 2:
3271 switch (sel) {
3272 case 0:
3273 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
3274 tcg_gen_ext32s_tl(arg, arg);
3275 rn = "EntryLo0";
3276 break;
3277 case 1:
3278 check_insn(env, ctx, ASE_MT);
3279 gen_helper_mfc0_tcstatus(arg, cpu_env);
3280 rn = "TCStatus";
3281 break;
3282 case 2:
3283 check_insn(env, ctx, ASE_MT);
3284 gen_helper_mfc0_tcbind(arg, cpu_env);
3285 rn = "TCBind";
3286 break;
3287 case 3:
3288 check_insn(env, ctx, ASE_MT);
3289 gen_helper_mfc0_tcrestart(arg, cpu_env);
3290 rn = "TCRestart";
3291 break;
3292 case 4:
3293 check_insn(env, ctx, ASE_MT);
3294 gen_helper_mfc0_tchalt(arg, cpu_env);
3295 rn = "TCHalt";
3296 break;
3297 case 5:
3298 check_insn(env, ctx, ASE_MT);
3299 gen_helper_mfc0_tccontext(arg, cpu_env);
3300 rn = "TCContext";
3301 break;
3302 case 6:
3303 check_insn(env, ctx, ASE_MT);
3304 gen_helper_mfc0_tcschedule(arg, cpu_env);
3305 rn = "TCSchedule";
3306 break;
3307 case 7:
3308 check_insn(env, ctx, ASE_MT);
3309 gen_helper_mfc0_tcschefback(arg, cpu_env);
3310 rn = "TCScheFBack";
3311 break;
3312 default:
3313 goto die;
3315 break;
3316 case 3:
3317 switch (sel) {
3318 case 0:
3319 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
3320 tcg_gen_ext32s_tl(arg, arg);
3321 rn = "EntryLo1";
3322 break;
3323 default:
3324 goto die;
3326 break;
3327 case 4:
3328 switch (sel) {
3329 case 0:
3330 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
3331 tcg_gen_ext32s_tl(arg, arg);
3332 rn = "Context";
3333 break;
3334 case 1:
3335 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3336 rn = "ContextConfig";
3337 // break;
3338 default:
3339 goto die;
3341 break;
3342 case 5:
3343 switch (sel) {
3344 case 0:
3345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
3346 rn = "PageMask";
3347 break;
3348 case 1:
3349 check_insn(env, ctx, ISA_MIPS32R2);
3350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
3351 rn = "PageGrain";
3352 break;
3353 default:
3354 goto die;
3356 break;
3357 case 6:
3358 switch (sel) {
3359 case 0:
3360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
3361 rn = "Wired";
3362 break;
3363 case 1:
3364 check_insn(env, ctx, ISA_MIPS32R2);
3365 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
3366 rn = "SRSConf0";
3367 break;
3368 case 2:
3369 check_insn(env, ctx, ISA_MIPS32R2);
3370 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
3371 rn = "SRSConf1";
3372 break;
3373 case 3:
3374 check_insn(env, ctx, ISA_MIPS32R2);
3375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
3376 rn = "SRSConf2";
3377 break;
3378 case 4:
3379 check_insn(env, ctx, ISA_MIPS32R2);
3380 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
3381 rn = "SRSConf3";
3382 break;
3383 case 5:
3384 check_insn(env, ctx, ISA_MIPS32R2);
3385 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
3386 rn = "SRSConf4";
3387 break;
3388 default:
3389 goto die;
3391 break;
3392 case 7:
3393 switch (sel) {
3394 case 0:
3395 check_insn(env, ctx, ISA_MIPS32R2);
3396 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
3397 rn = "HWREna";
3398 break;
3399 default:
3400 goto die;
3402 break;
3403 case 8:
3404 switch (sel) {
3405 case 0:
3406 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
3407 tcg_gen_ext32s_tl(arg, arg);
3408 rn = "BadVAddr";
3409 break;
3410 default:
3411 goto die;
3413 break;
3414 case 9:
3415 switch (sel) {
3416 case 0:
3417 /* Mark as an IO operation because we read the time. */
3418 if (use_icount)
3419 gen_io_start();
3420 gen_helper_mfc0_count(arg, cpu_env);
3421 if (use_icount) {
3422 gen_io_end();
3424 /* Break the TB to be able to take timer interrupts immediately
3425 after reading count. */
3426 ctx->bstate = BS_STOP;
3427 rn = "Count";
3428 break;
3429 /* 6,7 are implementation dependent */
3430 default:
3431 goto die;
3433 break;
3434 case 10:
3435 switch (sel) {
3436 case 0:
3437 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
3438 tcg_gen_ext32s_tl(arg, arg);
3439 rn = "EntryHi";
3440 break;
3441 default:
3442 goto die;
3444 break;
3445 case 11:
3446 switch (sel) {
3447 case 0:
3448 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
3449 rn = "Compare";
3450 break;
3451 /* 6,7 are implementation dependent */
3452 default:
3453 goto die;
3455 break;
3456 case 12:
3457 switch (sel) {
3458 case 0:
3459 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
3460 rn = "Status";
3461 break;
3462 case 1:
3463 check_insn(env, ctx, ISA_MIPS32R2);
3464 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
3465 rn = "IntCtl";
3466 break;
3467 case 2:
3468 check_insn(env, ctx, ISA_MIPS32R2);
3469 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
3470 rn = "SRSCtl";
3471 break;
3472 case 3:
3473 check_insn(env, ctx, ISA_MIPS32R2);
3474 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
3475 rn = "SRSMap";
3476 break;
3477 default:
3478 goto die;
3480 break;
3481 case 13:
3482 switch (sel) {
3483 case 0:
3484 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
3485 rn = "Cause";
3486 break;
3487 default:
3488 goto die;
3490 break;
3491 case 14:
3492 switch (sel) {
3493 case 0:
3494 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
3495 tcg_gen_ext32s_tl(arg, arg);
3496 rn = "EPC";
3497 break;
3498 default:
3499 goto die;
3501 break;
3502 case 15:
3503 switch (sel) {
3504 case 0:
3505 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
3506 rn = "PRid";
3507 break;
3508 case 1:
3509 check_insn(env, ctx, ISA_MIPS32R2);
3510 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
3511 rn = "EBase";
3512 break;
3513 default:
3514 goto die;
3516 break;
3517 case 16:
3518 switch (sel) {
3519 case 0:
3520 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
3521 rn = "Config";
3522 break;
3523 case 1:
3524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
3525 rn = "Config1";
3526 break;
3527 case 2:
3528 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
3529 rn = "Config2";
3530 break;
3531 case 3:
3532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
3533 rn = "Config3";
3534 break;
3535 /* 4,5 are reserved */
3536 /* 6,7 are implementation dependent */
3537 case 6:
3538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
3539 rn = "Config6";
3540 break;
3541 case 7:
3542 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
3543 rn = "Config7";
3544 break;
3545 default:
3546 goto die;
3548 break;
3549 case 17:
3550 switch (sel) {
3551 case 0:
3552 gen_helper_mfc0_lladdr(arg, cpu_env);
3553 rn = "LLAddr";
3554 break;
3555 default:
3556 goto die;
3558 break;
3559 case 18:
3560 switch (sel) {
3561 case 0 ... 7:
3562 gen_helper_1e0i(mfc0_watchlo, arg, sel);
3563 rn = "WatchLo";
3564 break;
3565 default:
3566 goto die;
3568 break;
3569 case 19:
3570 switch (sel) {
3571 case 0 ...7:
3572 gen_helper_1e0i(mfc0_watchhi, arg, sel);
3573 rn = "WatchHi";
3574 break;
3575 default:
3576 goto die;
3578 break;
3579 case 20:
3580 switch (sel) {
3581 case 0:
3582 #if defined(TARGET_MIPS64)
3583 check_insn(env, ctx, ISA_MIPS3);
3584 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
3585 tcg_gen_ext32s_tl(arg, arg);
3586 rn = "XContext";
3587 break;
3588 #endif
3589 default:
3590 goto die;
3592 break;
3593 case 21:
3594 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3595 switch (sel) {
3596 case 0:
3597 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
3598 rn = "Framemask";
3599 break;
3600 default:
3601 goto die;
3603 break;
3604 case 22:
3605 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3606 rn = "'Diagnostic"; /* implementation dependent */
3607 break;
3608 case 23:
3609 switch (sel) {
3610 case 0:
3611 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
3612 rn = "Debug";
3613 break;
3614 case 1:
3615 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3616 rn = "TraceControl";
3617 // break;
3618 case 2:
3619 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3620 rn = "TraceControl2";
3621 // break;
3622 case 3:
3623 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3624 rn = "UserTraceData";
3625 // break;
3626 case 4:
3627 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3628 rn = "TraceBPC";
3629 // break;
3630 default:
3631 goto die;
3633 break;
3634 case 24:
3635 switch (sel) {
3636 case 0:
3637 /* EJTAG support */
3638 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
3639 tcg_gen_ext32s_tl(arg, arg);
3640 rn = "DEPC";
3641 break;
3642 default:
3643 goto die;
3645 break;
3646 case 25:
3647 switch (sel) {
3648 case 0:
3649 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
3650 rn = "Performance0";
3651 break;
3652 case 1:
3653 // gen_helper_mfc0_performance1(arg);
3654 rn = "Performance1";
3655 // break;
3656 case 2:
3657 // gen_helper_mfc0_performance2(arg);
3658 rn = "Performance2";
3659 // break;
3660 case 3:
3661 // gen_helper_mfc0_performance3(arg);
3662 rn = "Performance3";
3663 // break;
3664 case 4:
3665 // gen_helper_mfc0_performance4(arg);
3666 rn = "Performance4";
3667 // break;
3668 case 5:
3669 // gen_helper_mfc0_performance5(arg);
3670 rn = "Performance5";
3671 // break;
3672 case 6:
3673 // gen_helper_mfc0_performance6(arg);
3674 rn = "Performance6";
3675 // break;
3676 case 7:
3677 // gen_helper_mfc0_performance7(arg);
3678 rn = "Performance7";
3679 // break;
3680 default:
3681 goto die;
3683 break;
3684 case 26:
3685 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3686 rn = "ECC";
3687 break;
3688 case 27:
3689 switch (sel) {
3690 case 0 ... 3:
3691 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3692 rn = "CacheErr";
3693 break;
3694 default:
3695 goto die;
3697 break;
3698 case 28:
3699 switch (sel) {
3700 case 0:
3701 case 2:
3702 case 4:
3703 case 6:
3704 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
3705 rn = "TagLo";
3706 break;
3707 case 1:
3708 case 3:
3709 case 5:
3710 case 7:
3711 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
3712 rn = "DataLo";
3713 break;
3714 default:
3715 goto die;
3717 break;
3718 case 29:
3719 switch (sel) {
3720 case 0:
3721 case 2:
3722 case 4:
3723 case 6:
3724 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
3725 rn = "TagHi";
3726 break;
3727 case 1:
3728 case 3:
3729 case 5:
3730 case 7:
3731 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
3732 rn = "DataHi";
3733 break;
3734 default:
3735 goto die;
3737 break;
3738 case 30:
3739 switch (sel) {
3740 case 0:
3741 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
3742 tcg_gen_ext32s_tl(arg, arg);
3743 rn = "ErrorEPC";
3744 break;
3745 default:
3746 goto die;
3748 break;
3749 case 31:
3750 switch (sel) {
3751 case 0:
3752 /* EJTAG support */
3753 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
3754 rn = "DESAVE";
3755 break;
3756 default:
3757 goto die;
3759 break;
3760 default:
3761 goto die;
3763 (void)rn; /* avoid a compiler warning */
3764 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3765 return;
3767 die:
3768 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3769 generate_exception(ctx, EXCP_RI);
3772 static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3774 const char *rn = "invalid";
3776 if (sel != 0)
3777 check_insn(env, ctx, ISA_MIPS32);
3779 if (use_icount)
3780 gen_io_start();
3782 switch (reg) {
3783 case 0:
3784 switch (sel) {
3785 case 0:
3786 gen_helper_mtc0_index(cpu_env, arg);
3787 rn = "Index";
3788 break;
3789 case 1:
3790 check_insn(env, ctx, ASE_MT);
3791 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
3792 rn = "MVPControl";
3793 break;
3794 case 2:
3795 check_insn(env, ctx, ASE_MT);
3796 /* ignored */
3797 rn = "MVPConf0";
3798 break;
3799 case 3:
3800 check_insn(env, ctx, ASE_MT);
3801 /* ignored */
3802 rn = "MVPConf1";
3803 break;
3804 default:
3805 goto die;
3807 break;
3808 case 1:
3809 switch (sel) {
3810 case 0:
3811 /* ignored */
3812 rn = "Random";
3813 break;
3814 case 1:
3815 check_insn(env, ctx, ASE_MT);
3816 gen_helper_mtc0_vpecontrol(cpu_env, arg);
3817 rn = "VPEControl";
3818 break;
3819 case 2:
3820 check_insn(env, ctx, ASE_MT);
3821 gen_helper_mtc0_vpeconf0(cpu_env, arg);
3822 rn = "VPEConf0";
3823 break;
3824 case 3:
3825 check_insn(env, ctx, ASE_MT);
3826 gen_helper_mtc0_vpeconf1(cpu_env, arg);
3827 rn = "VPEConf1";
3828 break;
3829 case 4:
3830 check_insn(env, ctx, ASE_MT);
3831 gen_helper_mtc0_yqmask(cpu_env, arg);
3832 rn = "YQMask";
3833 break;
3834 case 5:
3835 check_insn(env, ctx, ASE_MT);
3836 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
3837 rn = "VPESchedule";
3838 break;
3839 case 6:
3840 check_insn(env, ctx, ASE_MT);
3841 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
3842 rn = "VPEScheFBack";
3843 break;
3844 case 7:
3845 check_insn(env, ctx, ASE_MT);
3846 gen_helper_mtc0_vpeopt(cpu_env, arg);
3847 rn = "VPEOpt";
3848 break;
3849 default:
3850 goto die;
3852 break;
3853 case 2:
3854 switch (sel) {
3855 case 0:
3856 gen_helper_mtc0_entrylo0(cpu_env, arg);
3857 rn = "EntryLo0";
3858 break;
3859 case 1:
3860 check_insn(env, ctx, ASE_MT);
3861 gen_helper_mtc0_tcstatus(cpu_env, arg);
3862 rn = "TCStatus";
3863 break;
3864 case 2:
3865 check_insn(env, ctx, ASE_MT);
3866 gen_helper_mtc0_tcbind(cpu_env, arg);
3867 rn = "TCBind";
3868 break;
3869 case 3:
3870 check_insn(env, ctx, ASE_MT);
3871 gen_helper_mtc0_tcrestart(cpu_env, arg);
3872 rn = "TCRestart";
3873 break;
3874 case 4:
3875 check_insn(env, ctx, ASE_MT);
3876 gen_helper_mtc0_tchalt(cpu_env, arg);
3877 rn = "TCHalt";
3878 break;
3879 case 5:
3880 check_insn(env, ctx, ASE_MT);
3881 gen_helper_mtc0_tccontext(cpu_env, arg);
3882 rn = "TCContext";
3883 break;
3884 case 6:
3885 check_insn(env, ctx, ASE_MT);
3886 gen_helper_mtc0_tcschedule(cpu_env, arg);
3887 rn = "TCSchedule";
3888 break;
3889 case 7:
3890 check_insn(env, ctx, ASE_MT);
3891 gen_helper_mtc0_tcschefback(cpu_env, arg);
3892 rn = "TCScheFBack";
3893 break;
3894 default:
3895 goto die;
3897 break;
3898 case 3:
3899 switch (sel) {
3900 case 0:
3901 gen_helper_mtc0_entrylo1(cpu_env, arg);
3902 rn = "EntryLo1";
3903 break;
3904 default:
3905 goto die;
3907 break;
3908 case 4:
3909 switch (sel) {
3910 case 0:
3911 gen_helper_mtc0_context(cpu_env, arg);
3912 rn = "Context";
3913 break;
3914 case 1:
3915 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
3916 rn = "ContextConfig";
3917 // break;
3918 default:
3919 goto die;
3921 break;
3922 case 5:
3923 switch (sel) {
3924 case 0:
3925 gen_helper_mtc0_pagemask(cpu_env, arg);
3926 rn = "PageMask";
3927 break;
3928 case 1:
3929 check_insn(env, ctx, ISA_MIPS32R2);
3930 gen_helper_mtc0_pagegrain(cpu_env, arg);
3931 rn = "PageGrain";
3932 break;
3933 default:
3934 goto die;
3936 break;
3937 case 6:
3938 switch (sel) {
3939 case 0:
3940 gen_helper_mtc0_wired(cpu_env, arg);
3941 rn = "Wired";
3942 break;
3943 case 1:
3944 check_insn(env, ctx, ISA_MIPS32R2);
3945 gen_helper_mtc0_srsconf0(cpu_env, arg);
3946 rn = "SRSConf0";
3947 break;
3948 case 2:
3949 check_insn(env, ctx, ISA_MIPS32R2);
3950 gen_helper_mtc0_srsconf1(cpu_env, arg);
3951 rn = "SRSConf1";
3952 break;
3953 case 3:
3954 check_insn(env, ctx, ISA_MIPS32R2);
3955 gen_helper_mtc0_srsconf2(cpu_env, arg);
3956 rn = "SRSConf2";
3957 break;
3958 case 4:
3959 check_insn(env, ctx, ISA_MIPS32R2);
3960 gen_helper_mtc0_srsconf3(cpu_env, arg);
3961 rn = "SRSConf3";
3962 break;
3963 case 5:
3964 check_insn(env, ctx, ISA_MIPS32R2);
3965 gen_helper_mtc0_srsconf4(cpu_env, arg);
3966 rn = "SRSConf4";
3967 break;
3968 default:
3969 goto die;
3971 break;
3972 case 7:
3973 switch (sel) {
3974 case 0:
3975 check_insn(env, ctx, ISA_MIPS32R2);
3976 gen_helper_mtc0_hwrena(cpu_env, arg);
3977 rn = "HWREna";
3978 break;
3979 default:
3980 goto die;
3982 break;
3983 case 8:
3984 /* ignored */
3985 rn = "BadVAddr";
3986 break;
3987 case 9:
3988 switch (sel) {
3989 case 0:
3990 gen_helper_mtc0_count(cpu_env, arg);
3991 rn = "Count";
3992 break;
3993 /* 6,7 are implementation dependent */
3994 default:
3995 goto die;
3997 break;
3998 case 10:
3999 switch (sel) {
4000 case 0:
4001 gen_helper_mtc0_entryhi(cpu_env, arg);
4002 rn = "EntryHi";
4003 break;
4004 default:
4005 goto die;
4007 break;
4008 case 11:
4009 switch (sel) {
4010 case 0:
4011 gen_helper_mtc0_compare(cpu_env, arg);
4012 rn = "Compare";
4013 break;
4014 /* 6,7 are implementation dependent */
4015 default:
4016 goto die;
4018 break;
4019 case 12:
4020 switch (sel) {
4021 case 0:
4022 save_cpu_state(ctx, 1);
4023 gen_helper_mtc0_status(cpu_env, arg);
4024 /* BS_STOP isn't good enough here, hflags may have changed. */
4025 gen_save_pc(ctx->pc + 4);
4026 ctx->bstate = BS_EXCP;
4027 rn = "Status";
4028 break;
4029 case 1:
4030 check_insn(env, ctx, ISA_MIPS32R2);
4031 gen_helper_mtc0_intctl(cpu_env, arg);
4032 /* Stop translation as we may have switched the execution mode */
4033 ctx->bstate = BS_STOP;
4034 rn = "IntCtl";
4035 break;
4036 case 2:
4037 check_insn(env, ctx, ISA_MIPS32R2);
4038 gen_helper_mtc0_srsctl(cpu_env, arg);
4039 /* Stop translation as we may have switched the execution mode */
4040 ctx->bstate = BS_STOP;
4041 rn = "SRSCtl";
4042 break;
4043 case 3:
4044 check_insn(env, ctx, ISA_MIPS32R2);
4045 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
4046 /* Stop translation as we may have switched the execution mode */
4047 ctx->bstate = BS_STOP;
4048 rn = "SRSMap";
4049 break;
4050 default:
4051 goto die;
4053 break;
4054 case 13:
4055 switch (sel) {
4056 case 0:
4057 save_cpu_state(ctx, 1);
4058 gen_helper_mtc0_cause(cpu_env, arg);
4059 rn = "Cause";
4060 break;
4061 default:
4062 goto die;
4064 break;
4065 case 14:
4066 switch (sel) {
4067 case 0:
4068 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
4069 rn = "EPC";
4070 break;
4071 default:
4072 goto die;
4074 break;
4075 case 15:
4076 switch (sel) {
4077 case 0:
4078 /* ignored */
4079 rn = "PRid";
4080 break;
4081 case 1:
4082 check_insn(env, ctx, ISA_MIPS32R2);
4083 gen_helper_mtc0_ebase(cpu_env, arg);
4084 rn = "EBase";
4085 break;
4086 default:
4087 goto die;
4089 break;
4090 case 16:
4091 switch (sel) {
4092 case 0:
4093 gen_helper_mtc0_config0(cpu_env, arg);
4094 rn = "Config";
4095 /* Stop translation as we may have switched the execution mode */
4096 ctx->bstate = BS_STOP;
4097 break;
4098 case 1:
4099 /* ignored, read only */
4100 rn = "Config1";
4101 break;
4102 case 2:
4103 gen_helper_mtc0_config2(cpu_env, arg);
4104 rn = "Config2";
4105 /* Stop translation as we may have switched the execution mode */
4106 ctx->bstate = BS_STOP;
4107 break;
4108 case 3:
4109 /* ignored, read only */
4110 rn = "Config3";
4111 break;
4112 /* 4,5 are reserved */
4113 /* 6,7 are implementation dependent */
4114 case 6:
4115 /* ignored */
4116 rn = "Config6";
4117 break;
4118 case 7:
4119 /* ignored */
4120 rn = "Config7";
4121 break;
4122 default:
4123 rn = "Invalid config selector";
4124 goto die;
4126 break;
4127 case 17:
4128 switch (sel) {
4129 case 0:
4130 gen_helper_mtc0_lladdr(cpu_env, arg);
4131 rn = "LLAddr";
4132 break;
4133 default:
4134 goto die;
4136 break;
4137 case 18:
4138 switch (sel) {
4139 case 0 ... 7:
4140 gen_helper_0e1i(mtc0_watchlo, arg, sel);
4141 rn = "WatchLo";
4142 break;
4143 default:
4144 goto die;
4146 break;
4147 case 19:
4148 switch (sel) {
4149 case 0 ... 7:
4150 gen_helper_0e1i(mtc0_watchhi, arg, sel);
4151 rn = "WatchHi";
4152 break;
4153 default:
4154 goto die;
4156 break;
4157 case 20:
4158 switch (sel) {
4159 case 0:
4160 #if defined(TARGET_MIPS64)
4161 check_insn(env, ctx, ISA_MIPS3);
4162 gen_helper_mtc0_xcontext(cpu_env, arg);
4163 rn = "XContext";
4164 break;
4165 #endif
4166 default:
4167 goto die;
4169 break;
4170 case 21:
4171 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4172 switch (sel) {
4173 case 0:
4174 gen_helper_mtc0_framemask(cpu_env, arg);
4175 rn = "Framemask";
4176 break;
4177 default:
4178 goto die;
4180 break;
4181 case 22:
4182 /* ignored */
4183 rn = "Diagnostic"; /* implementation dependent */
4184 break;
4185 case 23:
4186 switch (sel) {
4187 case 0:
4188 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
4189 /* BS_STOP isn't good enough here, hflags may have changed. */
4190 gen_save_pc(ctx->pc + 4);
4191 ctx->bstate = BS_EXCP;
4192 rn = "Debug";
4193 break;
4194 case 1:
4195 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
4196 rn = "TraceControl";
4197 /* Stop translation as we may have switched the execution mode */
4198 ctx->bstate = BS_STOP;
4199 // break;
4200 case 2:
4201 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
4202 rn = "TraceControl2";
4203 /* Stop translation as we may have switched the execution mode */
4204 ctx->bstate = BS_STOP;
4205 // break;
4206 case 3:
4207 /* Stop translation as we may have switched the execution mode */
4208 ctx->bstate = BS_STOP;
4209 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
4210 rn = "UserTraceData";
4211 /* Stop translation as we may have switched the execution mode */
4212 ctx->bstate = BS_STOP;
4213 // break;
4214 case 4:
4215 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
4216 /* Stop translation as we may have switched the execution mode */
4217 ctx->bstate = BS_STOP;
4218 rn = "TraceBPC";
4219 // break;
4220 default:
4221 goto die;
4223 break;
4224 case 24:
4225 switch (sel) {
4226 case 0:
4227 /* EJTAG support */
4228 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
4229 rn = "DEPC";
4230 break;
4231 default:
4232 goto die;
4234 break;
4235 case 25:
4236 switch (sel) {
4237 case 0:
4238 gen_helper_mtc0_performance0(cpu_env, arg);
4239 rn = "Performance0";
4240 break;
4241 case 1:
4242 // gen_helper_mtc0_performance1(arg);
4243 rn = "Performance1";
4244 // break;
4245 case 2:
4246 // gen_helper_mtc0_performance2(arg);
4247 rn = "Performance2";
4248 // break;
4249 case 3:
4250 // gen_helper_mtc0_performance3(arg);
4251 rn = "Performance3";
4252 // break;
4253 case 4:
4254 // gen_helper_mtc0_performance4(arg);
4255 rn = "Performance4";
4256 // break;
4257 case 5:
4258 // gen_helper_mtc0_performance5(arg);
4259 rn = "Performance5";
4260 // break;
4261 case 6:
4262 // gen_helper_mtc0_performance6(arg);
4263 rn = "Performance6";
4264 // break;
4265 case 7:
4266 // gen_helper_mtc0_performance7(arg);
4267 rn = "Performance7";
4268 // break;
4269 default:
4270 goto die;
4272 break;
4273 case 26:
4274 /* ignored */
4275 rn = "ECC";
4276 break;
4277 case 27:
4278 switch (sel) {
4279 case 0 ... 3:
4280 /* ignored */
4281 rn = "CacheErr";
4282 break;
4283 default:
4284 goto die;
4286 break;
4287 case 28:
4288 switch (sel) {
4289 case 0:
4290 case 2:
4291 case 4:
4292 case 6:
4293 gen_helper_mtc0_taglo(cpu_env, arg);
4294 rn = "TagLo";
4295 break;
4296 case 1:
4297 case 3:
4298 case 5:
4299 case 7:
4300 gen_helper_mtc0_datalo(cpu_env, arg);
4301 rn = "DataLo";
4302 break;
4303 default:
4304 goto die;
4306 break;
4307 case 29:
4308 switch (sel) {
4309 case 0:
4310 case 2:
4311 case 4:
4312 case 6:
4313 gen_helper_mtc0_taghi(cpu_env, arg);
4314 rn = "TagHi";
4315 break;
4316 case 1:
4317 case 3:
4318 case 5:
4319 case 7:
4320 gen_helper_mtc0_datahi(cpu_env, arg);
4321 rn = "DataHi";
4322 break;
4323 default:
4324 rn = "invalid sel";
4325 goto die;
4327 break;
4328 case 30:
4329 switch (sel) {
4330 case 0:
4331 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
4332 rn = "ErrorEPC";
4333 break;
4334 default:
4335 goto die;
4337 break;
4338 case 31:
4339 switch (sel) {
4340 case 0:
4341 /* EJTAG support */
4342 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
4343 rn = "DESAVE";
4344 break;
4345 default:
4346 goto die;
4348 /* Stop translation as we may have switched the execution mode */
4349 ctx->bstate = BS_STOP;
4350 break;
4351 default:
4352 goto die;
4354 (void)rn; /* avoid a compiler warning */
4355 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4356 /* For simplicity assume that all writes can cause interrupts. */
4357 if (use_icount) {
4358 gen_io_end();
4359 ctx->bstate = BS_STOP;
4361 return;
4363 die:
4364 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4365 generate_exception(ctx, EXCP_RI);
4368 #if defined(TARGET_MIPS64)
4369 static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4371 const char *rn = "invalid";
4373 if (sel != 0)
4374 check_insn(env, ctx, ISA_MIPS64);
4376 switch (reg) {
4377 case 0:
4378 switch (sel) {
4379 case 0:
4380 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4381 rn = "Index";
4382 break;
4383 case 1:
4384 check_insn(env, ctx, ASE_MT);
4385 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4386 rn = "MVPControl";
4387 break;
4388 case 2:
4389 check_insn(env, ctx, ASE_MT);
4390 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4391 rn = "MVPConf0";
4392 break;
4393 case 3:
4394 check_insn(env, ctx, ASE_MT);
4395 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4396 rn = "MVPConf1";
4397 break;
4398 default:
4399 goto die;
4401 break;
4402 case 1:
4403 switch (sel) {
4404 case 0:
4405 gen_helper_mfc0_random(arg, cpu_env);
4406 rn = "Random";
4407 break;
4408 case 1:
4409 check_insn(env, ctx, ASE_MT);
4410 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4411 rn = "VPEControl";
4412 break;
4413 case 2:
4414 check_insn(env, ctx, ASE_MT);
4415 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4416 rn = "VPEConf0";
4417 break;
4418 case 3:
4419 check_insn(env, ctx, ASE_MT);
4420 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4421 rn = "VPEConf1";
4422 break;
4423 case 4:
4424 check_insn(env, ctx, ASE_MT);
4425 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
4426 rn = "YQMask";
4427 break;
4428 case 5:
4429 check_insn(env, ctx, ASE_MT);
4430 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
4431 rn = "VPESchedule";
4432 break;
4433 case 6:
4434 check_insn(env, ctx, ASE_MT);
4435 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4436 rn = "VPEScheFBack";
4437 break;
4438 case 7:
4439 check_insn(env, ctx, ASE_MT);
4440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
4441 rn = "VPEOpt";
4442 break;
4443 default:
4444 goto die;
4446 break;
4447 case 2:
4448 switch (sel) {
4449 case 0:
4450 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
4451 rn = "EntryLo0";
4452 break;
4453 case 1:
4454 check_insn(env, ctx, ASE_MT);
4455 gen_helper_mfc0_tcstatus(arg, cpu_env);
4456 rn = "TCStatus";
4457 break;
4458 case 2:
4459 check_insn(env, ctx, ASE_MT);
4460 gen_helper_mfc0_tcbind(arg, cpu_env);
4461 rn = "TCBind";
4462 break;
4463 case 3:
4464 check_insn(env, ctx, ASE_MT);
4465 gen_helper_dmfc0_tcrestart(arg, cpu_env);
4466 rn = "TCRestart";
4467 break;
4468 case 4:
4469 check_insn(env, ctx, ASE_MT);
4470 gen_helper_dmfc0_tchalt(arg, cpu_env);
4471 rn = "TCHalt";
4472 break;
4473 case 5:
4474 check_insn(env, ctx, ASE_MT);
4475 gen_helper_dmfc0_tccontext(arg, cpu_env);
4476 rn = "TCContext";
4477 break;
4478 case 6:
4479 check_insn(env, ctx, ASE_MT);
4480 gen_helper_dmfc0_tcschedule(arg, cpu_env);
4481 rn = "TCSchedule";
4482 break;
4483 case 7:
4484 check_insn(env, ctx, ASE_MT);
4485 gen_helper_dmfc0_tcschefback(arg, cpu_env);
4486 rn = "TCScheFBack";
4487 break;
4488 default:
4489 goto die;
4491 break;
4492 case 3:
4493 switch (sel) {
4494 case 0:
4495 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
4496 rn = "EntryLo1";
4497 break;
4498 default:
4499 goto die;
4501 break;
4502 case 4:
4503 switch (sel) {
4504 case 0:
4505 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
4506 rn = "Context";
4507 break;
4508 case 1:
4509 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4510 rn = "ContextConfig";
4511 // break;
4512 default:
4513 goto die;
4515 break;
4516 case 5:
4517 switch (sel) {
4518 case 0:
4519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
4520 rn = "PageMask";
4521 break;
4522 case 1:
4523 check_insn(env, ctx, ISA_MIPS32R2);
4524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
4525 rn = "PageGrain";
4526 break;
4527 default:
4528 goto die;
4530 break;
4531 case 6:
4532 switch (sel) {
4533 case 0:
4534 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
4535 rn = "Wired";
4536 break;
4537 case 1:
4538 check_insn(env, ctx, ISA_MIPS32R2);
4539 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
4540 rn = "SRSConf0";
4541 break;
4542 case 2:
4543 check_insn(env, ctx, ISA_MIPS32R2);
4544 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
4545 rn = "SRSConf1";
4546 break;
4547 case 3:
4548 check_insn(env, ctx, ISA_MIPS32R2);
4549 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
4550 rn = "SRSConf2";
4551 break;
4552 case 4:
4553 check_insn(env, ctx, ISA_MIPS32R2);
4554 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
4555 rn = "SRSConf3";
4556 break;
4557 case 5:
4558 check_insn(env, ctx, ISA_MIPS32R2);
4559 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
4560 rn = "SRSConf4";
4561 break;
4562 default:
4563 goto die;
4565 break;
4566 case 7:
4567 switch (sel) {
4568 case 0:
4569 check_insn(env, ctx, ISA_MIPS32R2);
4570 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
4571 rn = "HWREna";
4572 break;
4573 default:
4574 goto die;
4576 break;
4577 case 8:
4578 switch (sel) {
4579 case 0:
4580 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
4581 rn = "BadVAddr";
4582 break;
4583 default:
4584 goto die;
4586 break;
4587 case 9:
4588 switch (sel) {
4589 case 0:
4590 /* Mark as an IO operation because we read the time. */
4591 if (use_icount)
4592 gen_io_start();
4593 gen_helper_mfc0_count(arg, cpu_env);
4594 if (use_icount) {
4595 gen_io_end();
4597 /* Break the TB to be able to take timer interrupts immediately
4598 after reading count. */
4599 ctx->bstate = BS_STOP;
4600 rn = "Count";
4601 break;
4602 /* 6,7 are implementation dependent */
4603 default:
4604 goto die;
4606 break;
4607 case 10:
4608 switch (sel) {
4609 case 0:
4610 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
4611 rn = "EntryHi";
4612 break;
4613 default:
4614 goto die;
4616 break;
4617 case 11:
4618 switch (sel) {
4619 case 0:
4620 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
4621 rn = "Compare";
4622 break;
4623 /* 6,7 are implementation dependent */
4624 default:
4625 goto die;
4627 break;
4628 case 12:
4629 switch (sel) {
4630 case 0:
4631 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
4632 rn = "Status";
4633 break;
4634 case 1:
4635 check_insn(env, ctx, ISA_MIPS32R2);
4636 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
4637 rn = "IntCtl";
4638 break;
4639 case 2:
4640 check_insn(env, ctx, ISA_MIPS32R2);
4641 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
4642 rn = "SRSCtl";
4643 break;
4644 case 3:
4645 check_insn(env, ctx, ISA_MIPS32R2);
4646 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
4647 rn = "SRSMap";
4648 break;
4649 default:
4650 goto die;
4652 break;
4653 case 13:
4654 switch (sel) {
4655 case 0:
4656 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
4657 rn = "Cause";
4658 break;
4659 default:
4660 goto die;
4662 break;
4663 case 14:
4664 switch (sel) {
4665 case 0:
4666 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
4667 rn = "EPC";
4668 break;
4669 default:
4670 goto die;
4672 break;
4673 case 15:
4674 switch (sel) {
4675 case 0:
4676 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
4677 rn = "PRid";
4678 break;
4679 case 1:
4680 check_insn(env, ctx, ISA_MIPS32R2);
4681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
4682 rn = "EBase";
4683 break;
4684 default:
4685 goto die;
4687 break;
4688 case 16:
4689 switch (sel) {
4690 case 0:
4691 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
4692 rn = "Config";
4693 break;
4694 case 1:
4695 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
4696 rn = "Config1";
4697 break;
4698 case 2:
4699 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
4700 rn = "Config2";
4701 break;
4702 case 3:
4703 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
4704 rn = "Config3";
4705 break;
4706 /* 6,7 are implementation dependent */
4707 case 6:
4708 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
4709 rn = "Config6";
4710 break;
4711 case 7:
4712 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
4713 rn = "Config7";
4714 break;
4715 default:
4716 goto die;
4718 break;
4719 case 17:
4720 switch (sel) {
4721 case 0:
4722 gen_helper_dmfc0_lladdr(arg, cpu_env);
4723 rn = "LLAddr";
4724 break;
4725 default:
4726 goto die;
4728 break;
4729 case 18:
4730 switch (sel) {
4731 case 0 ... 7:
4732 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
4733 rn = "WatchLo";
4734 break;
4735 default:
4736 goto die;
4738 break;
4739 case 19:
4740 switch (sel) {
4741 case 0 ... 7:
4742 gen_helper_1e0i(mfc0_watchhi, arg, sel);
4743 rn = "WatchHi";
4744 break;
4745 default:
4746 goto die;
4748 break;
4749 case 20:
4750 switch (sel) {
4751 case 0:
4752 check_insn(env, ctx, ISA_MIPS3);
4753 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
4754 rn = "XContext";
4755 break;
4756 default:
4757 goto die;
4759 break;
4760 case 21:
4761 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4762 switch (sel) {
4763 case 0:
4764 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
4765 rn = "Framemask";
4766 break;
4767 default:
4768 goto die;
4770 break;
4771 case 22:
4772 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4773 rn = "'Diagnostic"; /* implementation dependent */
4774 break;
4775 case 23:
4776 switch (sel) {
4777 case 0:
4778 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
4779 rn = "Debug";
4780 break;
4781 case 1:
4782 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
4783 rn = "TraceControl";
4784 // break;
4785 case 2:
4786 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
4787 rn = "TraceControl2";
4788 // break;
4789 case 3:
4790 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
4791 rn = "UserTraceData";
4792 // break;
4793 case 4:
4794 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
4795 rn = "TraceBPC";
4796 // break;
4797 default:
4798 goto die;
4800 break;
4801 case 24:
4802 switch (sel) {
4803 case 0:
4804 /* EJTAG support */
4805 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
4806 rn = "DEPC";
4807 break;
4808 default:
4809 goto die;
4811 break;
4812 case 25:
4813 switch (sel) {
4814 case 0:
4815 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
4816 rn = "Performance0";
4817 break;
4818 case 1:
4819 // gen_helper_dmfc0_performance1(arg);
4820 rn = "Performance1";
4821 // break;
4822 case 2:
4823 // gen_helper_dmfc0_performance2(arg);
4824 rn = "Performance2";
4825 // break;
4826 case 3:
4827 // gen_helper_dmfc0_performance3(arg);
4828 rn = "Performance3";
4829 // break;
4830 case 4:
4831 // gen_helper_dmfc0_performance4(arg);
4832 rn = "Performance4";
4833 // break;
4834 case 5:
4835 // gen_helper_dmfc0_performance5(arg);
4836 rn = "Performance5";
4837 // break;
4838 case 6:
4839 // gen_helper_dmfc0_performance6(arg);
4840 rn = "Performance6";
4841 // break;
4842 case 7:
4843 // gen_helper_dmfc0_performance7(arg);
4844 rn = "Performance7";
4845 // break;
4846 default:
4847 goto die;
4849 break;
4850 case 26:
4851 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4852 rn = "ECC";
4853 break;
4854 case 27:
4855 switch (sel) {
4856 /* ignored */
4857 case 0 ... 3:
4858 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4859 rn = "CacheErr";
4860 break;
4861 default:
4862 goto die;
4864 break;
4865 case 28:
4866 switch (sel) {
4867 case 0:
4868 case 2:
4869 case 4:
4870 case 6:
4871 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
4872 rn = "TagLo";
4873 break;
4874 case 1:
4875 case 3:
4876 case 5:
4877 case 7:
4878 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
4879 rn = "DataLo";
4880 break;
4881 default:
4882 goto die;
4884 break;
4885 case 29:
4886 switch (sel) {
4887 case 0:
4888 case 2:
4889 case 4:
4890 case 6:
4891 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
4892 rn = "TagHi";
4893 break;
4894 case 1:
4895 case 3:
4896 case 5:
4897 case 7:
4898 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
4899 rn = "DataHi";
4900 break;
4901 default:
4902 goto die;
4904 break;
4905 case 30:
4906 switch (sel) {
4907 case 0:
4908 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
4909 rn = "ErrorEPC";
4910 break;
4911 default:
4912 goto die;
4914 break;
4915 case 31:
4916 switch (sel) {
4917 case 0:
4918 /* EJTAG support */
4919 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
4920 rn = "DESAVE";
4921 break;
4922 default:
4923 goto die;
4925 break;
4926 default:
4927 goto die;
4929 (void)rn; /* avoid a compiler warning */
4930 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4931 return;
4933 die:
4934 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4935 generate_exception(ctx, EXCP_RI);
4938 static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4940 const char *rn = "invalid";
4942 if (sel != 0)
4943 check_insn(env, ctx, ISA_MIPS64);
4945 if (use_icount)
4946 gen_io_start();
4948 switch (reg) {
4949 case 0:
4950 switch (sel) {
4951 case 0:
4952 gen_helper_mtc0_index(cpu_env, arg);
4953 rn = "Index";
4954 break;
4955 case 1:
4956 check_insn(env, ctx, ASE_MT);
4957 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
4958 rn = "MVPControl";
4959 break;
4960 case 2:
4961 check_insn(env, ctx, ASE_MT);
4962 /* ignored */
4963 rn = "MVPConf0";
4964 break;
4965 case 3:
4966 check_insn(env, ctx, ASE_MT);
4967 /* ignored */
4968 rn = "MVPConf1";
4969 break;
4970 default:
4971 goto die;
4973 break;
4974 case 1:
4975 switch (sel) {
4976 case 0:
4977 /* ignored */
4978 rn = "Random";
4979 break;
4980 case 1:
4981 check_insn(env, ctx, ASE_MT);
4982 gen_helper_mtc0_vpecontrol(cpu_env, arg);
4983 rn = "VPEControl";
4984 break;
4985 case 2:
4986 check_insn(env, ctx, ASE_MT);
4987 gen_helper_mtc0_vpeconf0(cpu_env, arg);
4988 rn = "VPEConf0";
4989 break;
4990 case 3:
4991 check_insn(env, ctx, ASE_MT);
4992 gen_helper_mtc0_vpeconf1(cpu_env, arg);
4993 rn = "VPEConf1";
4994 break;
4995 case 4:
4996 check_insn(env, ctx, ASE_MT);
4997 gen_helper_mtc0_yqmask(cpu_env, arg);
4998 rn = "YQMask";
4999 break;
5000 case 5:
5001 check_insn(env, ctx, ASE_MT);
5002 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
5003 rn = "VPESchedule";
5004 break;
5005 case 6:
5006 check_insn(env, ctx, ASE_MT);
5007 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5008 rn = "VPEScheFBack";
5009 break;
5010 case 7:
5011 check_insn(env, ctx, ASE_MT);
5012 gen_helper_mtc0_vpeopt(cpu_env, arg);
5013 rn = "VPEOpt";
5014 break;
5015 default:
5016 goto die;
5018 break;
5019 case 2:
5020 switch (sel) {
5021 case 0:
5022 gen_helper_mtc0_entrylo0(cpu_env, arg);
5023 rn = "EntryLo0";
5024 break;
5025 case 1:
5026 check_insn(env, ctx, ASE_MT);
5027 gen_helper_mtc0_tcstatus(cpu_env, arg);
5028 rn = "TCStatus";
5029 break;
5030 case 2:
5031 check_insn(env, ctx, ASE_MT);
5032 gen_helper_mtc0_tcbind(cpu_env, arg);
5033 rn = "TCBind";
5034 break;
5035 case 3:
5036 check_insn(env, ctx, ASE_MT);
5037 gen_helper_mtc0_tcrestart(cpu_env, arg);
5038 rn = "TCRestart";
5039 break;
5040 case 4:
5041 check_insn(env, ctx, ASE_MT);
5042 gen_helper_mtc0_tchalt(cpu_env, arg);
5043 rn = "TCHalt";
5044 break;
5045 case 5:
5046 check_insn(env, ctx, ASE_MT);
5047 gen_helper_mtc0_tccontext(cpu_env, arg);
5048 rn = "TCContext";
5049 break;
5050 case 6:
5051 check_insn(env, ctx, ASE_MT);
5052 gen_helper_mtc0_tcschedule(cpu_env, arg);
5053 rn = "TCSchedule";
5054 break;
5055 case 7:
5056 check_insn(env, ctx, ASE_MT);
5057 gen_helper_mtc0_tcschefback(cpu_env, arg);
5058 rn = "TCScheFBack";
5059 break;
5060 default:
5061 goto die;
5063 break;
5064 case 3:
5065 switch (sel) {
5066 case 0:
5067 gen_helper_mtc0_entrylo1(cpu_env, arg);
5068 rn = "EntryLo1";
5069 break;
5070 default:
5071 goto die;
5073 break;
5074 case 4:
5075 switch (sel) {
5076 case 0:
5077 gen_helper_mtc0_context(cpu_env, arg);
5078 rn = "Context";
5079 break;
5080 case 1:
5081 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5082 rn = "ContextConfig";
5083 // break;
5084 default:
5085 goto die;
5087 break;
5088 case 5:
5089 switch (sel) {
5090 case 0:
5091 gen_helper_mtc0_pagemask(cpu_env, arg);
5092 rn = "PageMask";
5093 break;
5094 case 1:
5095 check_insn(env, ctx, ISA_MIPS32R2);
5096 gen_helper_mtc0_pagegrain(cpu_env, arg);
5097 rn = "PageGrain";
5098 break;
5099 default:
5100 goto die;
5102 break;
5103 case 6:
5104 switch (sel) {
5105 case 0:
5106 gen_helper_mtc0_wired(cpu_env, arg);
5107 rn = "Wired";
5108 break;
5109 case 1:
5110 check_insn(env, ctx, ISA_MIPS32R2);
5111 gen_helper_mtc0_srsconf0(cpu_env, arg);
5112 rn = "SRSConf0";
5113 break;
5114 case 2:
5115 check_insn(env, ctx, ISA_MIPS32R2);
5116 gen_helper_mtc0_srsconf1(cpu_env, arg);
5117 rn = "SRSConf1";
5118 break;
5119 case 3:
5120 check_insn(env, ctx, ISA_MIPS32R2);
5121 gen_helper_mtc0_srsconf2(cpu_env, arg);
5122 rn = "SRSConf2";
5123 break;
5124 case 4:
5125 check_insn(env, ctx, ISA_MIPS32R2);
5126 gen_helper_mtc0_srsconf3(cpu_env, arg);
5127 rn = "SRSConf3";
5128 break;
5129 case 5:
5130 check_insn(env, ctx, ISA_MIPS32R2);
5131 gen_helper_mtc0_srsconf4(cpu_env, arg);
5132 rn = "SRSConf4";
5133 break;
5134 default:
5135 goto die;
5137 break;
5138 case 7:
5139 switch (sel) {
5140 case 0:
5141 check_insn(env, ctx, ISA_MIPS32R2);
5142 gen_helper_mtc0_hwrena(cpu_env, arg);
5143 rn = "HWREna";
5144 break;
5145 default:
5146 goto die;
5148 break;
5149 case 8:
5150 /* ignored */
5151 rn = "BadVAddr";
5152 break;
5153 case 9:
5154 switch (sel) {
5155 case 0:
5156 gen_helper_mtc0_count(cpu_env, arg);
5157 rn = "Count";
5158 break;
5159 /* 6,7 are implementation dependent */
5160 default:
5161 goto die;
5163 /* Stop translation as we may have switched the execution mode */
5164 ctx->bstate = BS_STOP;
5165 break;
5166 case 10:
5167 switch (sel) {
5168 case 0:
5169 gen_helper_mtc0_entryhi(cpu_env, arg);
5170 rn = "EntryHi";
5171 break;
5172 default:
5173 goto die;
5175 break;
5176 case 11:
5177 switch (sel) {
5178 case 0:
5179 gen_helper_mtc0_compare(cpu_env, arg);
5180 rn = "Compare";
5181 break;
5182 /* 6,7 are implementation dependent */
5183 default:
5184 goto die;
5186 /* Stop translation as we may have switched the execution mode */
5187 ctx->bstate = BS_STOP;
5188 break;
5189 case 12:
5190 switch (sel) {
5191 case 0:
5192 save_cpu_state(ctx, 1);
5193 gen_helper_mtc0_status(cpu_env, arg);
5194 /* BS_STOP isn't good enough here, hflags may have changed. */
5195 gen_save_pc(ctx->pc + 4);
5196 ctx->bstate = BS_EXCP;
5197 rn = "Status";
5198 break;
5199 case 1:
5200 check_insn(env, ctx, ISA_MIPS32R2);
5201 gen_helper_mtc0_intctl(cpu_env, arg);
5202 /* Stop translation as we may have switched the execution mode */
5203 ctx->bstate = BS_STOP;
5204 rn = "IntCtl";
5205 break;
5206 case 2:
5207 check_insn(env, ctx, ISA_MIPS32R2);
5208 gen_helper_mtc0_srsctl(cpu_env, arg);
5209 /* Stop translation as we may have switched the execution mode */
5210 ctx->bstate = BS_STOP;
5211 rn = "SRSCtl";
5212 break;
5213 case 3:
5214 check_insn(env, ctx, ISA_MIPS32R2);
5215 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5216 /* Stop translation as we may have switched the execution mode */
5217 ctx->bstate = BS_STOP;
5218 rn = "SRSMap";
5219 break;
5220 default:
5221 goto die;
5223 break;
5224 case 13:
5225 switch (sel) {
5226 case 0:
5227 save_cpu_state(ctx, 1);
5228 /* Mark as an IO operation because we may trigger a software
5229 interrupt. */
5230 if (use_icount) {
5231 gen_io_start();
5233 gen_helper_mtc0_cause(cpu_env, arg);
5234 if (use_icount) {
5235 gen_io_end();
5237 /* Stop translation as we may have triggered an intetrupt */
5238 ctx->bstate = BS_STOP;
5239 rn = "Cause";
5240 break;
5241 default:
5242 goto die;
5244 break;
5245 case 14:
5246 switch (sel) {
5247 case 0:
5248 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5249 rn = "EPC";
5250 break;
5251 default:
5252 goto die;
5254 break;
5255 case 15:
5256 switch (sel) {
5257 case 0:
5258 /* ignored */
5259 rn = "PRid";
5260 break;
5261 case 1:
5262 check_insn(env, ctx, ISA_MIPS32R2);
5263 gen_helper_mtc0_ebase(cpu_env, arg);
5264 rn = "EBase";
5265 break;
5266 default:
5267 goto die;
5269 break;
5270 case 16:
5271 switch (sel) {
5272 case 0:
5273 gen_helper_mtc0_config0(cpu_env, arg);
5274 rn = "Config";
5275 /* Stop translation as we may have switched the execution mode */
5276 ctx->bstate = BS_STOP;
5277 break;
5278 case 1:
5279 /* ignored, read only */
5280 rn = "Config1";
5281 break;
5282 case 2:
5283 gen_helper_mtc0_config2(cpu_env, arg);
5284 rn = "Config2";
5285 /* Stop translation as we may have switched the execution mode */
5286 ctx->bstate = BS_STOP;
5287 break;
5288 case 3:
5289 /* ignored */
5290 rn = "Config3";
5291 break;
5292 /* 6,7 are implementation dependent */
5293 default:
5294 rn = "Invalid config selector";
5295 goto die;
5297 break;
5298 case 17:
5299 switch (sel) {
5300 case 0:
5301 gen_helper_mtc0_lladdr(cpu_env, arg);
5302 rn = "LLAddr";
5303 break;
5304 default:
5305 goto die;
5307 break;
5308 case 18:
5309 switch (sel) {
5310 case 0 ... 7:
5311 gen_helper_0e1i(mtc0_watchlo, arg, sel);
5312 rn = "WatchLo";
5313 break;
5314 default:
5315 goto die;
5317 break;
5318 case 19:
5319 switch (sel) {
5320 case 0 ... 7:
5321 gen_helper_0e1i(mtc0_watchhi, arg, sel);
5322 rn = "WatchHi";
5323 break;
5324 default:
5325 goto die;
5327 break;
5328 case 20:
5329 switch (sel) {
5330 case 0:
5331 check_insn(env, ctx, ISA_MIPS3);
5332 gen_helper_mtc0_xcontext(cpu_env, arg);
5333 rn = "XContext";
5334 break;
5335 default:
5336 goto die;
5338 break;
5339 case 21:
5340 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5341 switch (sel) {
5342 case 0:
5343 gen_helper_mtc0_framemask(cpu_env, arg);
5344 rn = "Framemask";
5345 break;
5346 default:
5347 goto die;
5349 break;
5350 case 22:
5351 /* ignored */
5352 rn = "Diagnostic"; /* implementation dependent */
5353 break;
5354 case 23:
5355 switch (sel) {
5356 case 0:
5357 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
5358 /* BS_STOP isn't good enough here, hflags may have changed. */
5359 gen_save_pc(ctx->pc + 4);
5360 ctx->bstate = BS_EXCP;
5361 rn = "Debug";
5362 break;
5363 case 1:
5364 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
5365 /* Stop translation as we may have switched the execution mode */
5366 ctx->bstate = BS_STOP;
5367 rn = "TraceControl";
5368 // break;
5369 case 2:
5370 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
5371 /* Stop translation as we may have switched the execution mode */
5372 ctx->bstate = BS_STOP;
5373 rn = "TraceControl2";
5374 // break;
5375 case 3:
5376 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
5377 /* Stop translation as we may have switched the execution mode */
5378 ctx->bstate = BS_STOP;
5379 rn = "UserTraceData";
5380 // break;
5381 case 4:
5382 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
5383 /* Stop translation as we may have switched the execution mode */
5384 ctx->bstate = BS_STOP;
5385 rn = "TraceBPC";
5386 // break;
5387 default:
5388 goto die;
5390 break;
5391 case 24:
5392 switch (sel) {
5393 case 0:
5394 /* EJTAG support */
5395 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5396 rn = "DEPC";
5397 break;
5398 default:
5399 goto die;
5401 break;
5402 case 25:
5403 switch (sel) {
5404 case 0:
5405 gen_helper_mtc0_performance0(cpu_env, arg);
5406 rn = "Performance0";
5407 break;
5408 case 1:
5409 // gen_helper_mtc0_performance1(cpu_env, arg);
5410 rn = "Performance1";
5411 // break;
5412 case 2:
5413 // gen_helper_mtc0_performance2(cpu_env, arg);
5414 rn = "Performance2";
5415 // break;
5416 case 3:
5417 // gen_helper_mtc0_performance3(cpu_env, arg);
5418 rn = "Performance3";
5419 // break;
5420 case 4:
5421 // gen_helper_mtc0_performance4(cpu_env, arg);
5422 rn = "Performance4";
5423 // break;
5424 case 5:
5425 // gen_helper_mtc0_performance5(cpu_env, arg);
5426 rn = "Performance5";
5427 // break;
5428 case 6:
5429 // gen_helper_mtc0_performance6(cpu_env, arg);
5430 rn = "Performance6";
5431 // break;
5432 case 7:
5433 // gen_helper_mtc0_performance7(cpu_env, arg);
5434 rn = "Performance7";
5435 // break;
5436 default:
5437 goto die;
5439 break;
5440 case 26:
5441 /* ignored */
5442 rn = "ECC";
5443 break;
5444 case 27:
5445 switch (sel) {
5446 case 0 ... 3:
5447 /* ignored */
5448 rn = "CacheErr";
5449 break;
5450 default:
5451 goto die;
5453 break;
5454 case 28:
5455 switch (sel) {
5456 case 0:
5457 case 2:
5458 case 4:
5459 case 6:
5460 gen_helper_mtc0_taglo(cpu_env, arg);
5461 rn = "TagLo";
5462 break;
5463 case 1:
5464 case 3:
5465 case 5:
5466 case 7:
5467 gen_helper_mtc0_datalo(cpu_env, arg);
5468 rn = "DataLo";
5469 break;
5470 default:
5471 goto die;
5473 break;
5474 case 29:
5475 switch (sel) {
5476 case 0:
5477 case 2:
5478 case 4:
5479 case 6:
5480 gen_helper_mtc0_taghi(cpu_env, arg);
5481 rn = "TagHi";
5482 break;
5483 case 1:
5484 case 3:
5485 case 5:
5486 case 7:
5487 gen_helper_mtc0_datahi(cpu_env, arg);
5488 rn = "DataHi";
5489 break;
5490 default:
5491 rn = "invalid sel";
5492 goto die;
5494 break;
5495 case 30:
5496 switch (sel) {
5497 case 0:
5498 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5499 rn = "ErrorEPC";
5500 break;
5501 default:
5502 goto die;
5504 break;
5505 case 31:
5506 switch (sel) {
5507 case 0:
5508 /* EJTAG support */
5509 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5510 rn = "DESAVE";
5511 break;
5512 default:
5513 goto die;
5515 /* Stop translation as we may have switched the execution mode */
5516 ctx->bstate = BS_STOP;
5517 break;
5518 default:
5519 goto die;
5521 (void)rn; /* avoid a compiler warning */
5522 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5523 /* For simplicity assume that all writes can cause interrupts. */
5524 if (use_icount) {
5525 gen_io_end();
5526 ctx->bstate = BS_STOP;
5528 return;
5530 die:
5531 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5532 generate_exception(ctx, EXCP_RI);
5534 #endif /* TARGET_MIPS64 */
5536 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
5537 int u, int sel, int h)
5539 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5540 TCGv t0 = tcg_temp_local_new();
5542 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5543 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5544 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5545 tcg_gen_movi_tl(t0, -1);
5546 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5547 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5548 tcg_gen_movi_tl(t0, -1);
5549 else if (u == 0) {
5550 switch (rt) {
5551 case 1:
5552 switch (sel) {
5553 case 1:
5554 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5555 break;
5556 case 2:
5557 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5558 break;
5559 default:
5560 goto die;
5561 break;
5563 break;
5564 case 2:
5565 switch (sel) {
5566 case 1:
5567 gen_helper_mftc0_tcstatus(t0, cpu_env);
5568 break;
5569 case 2:
5570 gen_helper_mftc0_tcbind(t0, cpu_env);
5571 break;
5572 case 3:
5573 gen_helper_mftc0_tcrestart(t0, cpu_env);
5574 break;
5575 case 4:
5576 gen_helper_mftc0_tchalt(t0, cpu_env);
5577 break;
5578 case 5:
5579 gen_helper_mftc0_tccontext(t0, cpu_env);
5580 break;
5581 case 6:
5582 gen_helper_mftc0_tcschedule(t0, cpu_env);
5583 break;
5584 case 7:
5585 gen_helper_mftc0_tcschefback(t0, cpu_env);
5586 break;
5587 default:
5588 gen_mfc0(env, ctx, t0, rt, sel);
5589 break;
5591 break;
5592 case 10:
5593 switch (sel) {
5594 case 0:
5595 gen_helper_mftc0_entryhi(t0, cpu_env);
5596 break;
5597 default:
5598 gen_mfc0(env, ctx, t0, rt, sel);
5599 break;
5601 case 12:
5602 switch (sel) {
5603 case 0:
5604 gen_helper_mftc0_status(t0, cpu_env);
5605 break;
5606 default:
5607 gen_mfc0(env, ctx, t0, rt, sel);
5608 break;
5610 case 13:
5611 switch (sel) {
5612 case 0:
5613 gen_helper_mftc0_cause(t0, cpu_env);
5614 break;
5615 default:
5616 goto die;
5617 break;
5619 break;
5620 case 14:
5621 switch (sel) {
5622 case 0:
5623 gen_helper_mftc0_epc(t0, cpu_env);
5624 break;
5625 default:
5626 goto die;
5627 break;
5629 break;
5630 case 15:
5631 switch (sel) {
5632 case 1:
5633 gen_helper_mftc0_ebase(t0, cpu_env);
5634 break;
5635 default:
5636 goto die;
5637 break;
5639 break;
5640 case 16:
5641 switch (sel) {
5642 case 0 ... 7:
5643 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5644 break;
5645 default:
5646 goto die;
5647 break;
5649 break;
5650 case 23:
5651 switch (sel) {
5652 case 0:
5653 gen_helper_mftc0_debug(t0, cpu_env);
5654 break;
5655 default:
5656 gen_mfc0(env, ctx, t0, rt, sel);
5657 break;
5659 break;
5660 default:
5661 gen_mfc0(env, ctx, t0, rt, sel);
5663 } else switch (sel) {
5664 /* GPR registers. */
5665 case 0:
5666 gen_helper_1e0i(mftgpr, t0, rt);
5667 break;
5668 /* Auxiliary CPU registers */
5669 case 1:
5670 switch (rt) {
5671 case 0:
5672 gen_helper_1e0i(mftlo, t0, 0);
5673 break;
5674 case 1:
5675 gen_helper_1e0i(mfthi, t0, 0);
5676 break;
5677 case 2:
5678 gen_helper_1e0i(mftacx, t0, 0);
5679 break;
5680 case 4:
5681 gen_helper_1e0i(mftlo, t0, 1);
5682 break;
5683 case 5:
5684 gen_helper_1e0i(mfthi, t0, 1);
5685 break;
5686 case 6:
5687 gen_helper_1e0i(mftacx, t0, 1);
5688 break;
5689 case 8:
5690 gen_helper_1e0i(mftlo, t0, 2);
5691 break;
5692 case 9:
5693 gen_helper_1e0i(mfthi, t0, 2);
5694 break;
5695 case 10:
5696 gen_helper_1e0i(mftacx, t0, 2);
5697 break;
5698 case 12:
5699 gen_helper_1e0i(mftlo, t0, 3);
5700 break;
5701 case 13:
5702 gen_helper_1e0i(mfthi, t0, 3);
5703 break;
5704 case 14:
5705 gen_helper_1e0i(mftacx, t0, 3);
5706 break;
5707 case 16:
5708 gen_helper_mftdsp(t0, cpu_env);
5709 break;
5710 default:
5711 goto die;
5713 break;
5714 /* Floating point (COP1). */
5715 case 2:
5716 /* XXX: For now we support only a single FPU context. */
5717 if (h == 0) {
5718 TCGv_i32 fp0 = tcg_temp_new_i32();
5720 gen_load_fpr32(fp0, rt);
5721 tcg_gen_ext_i32_tl(t0, fp0);
5722 tcg_temp_free_i32(fp0);
5723 } else {
5724 TCGv_i32 fp0 = tcg_temp_new_i32();
5726 gen_load_fpr32h(fp0, rt);
5727 tcg_gen_ext_i32_tl(t0, fp0);
5728 tcg_temp_free_i32(fp0);
5730 break;
5731 case 3:
5732 /* XXX: For now we support only a single FPU context. */
5733 gen_helper_1e0i(cfc1, t0, rt);
5734 break;
5735 /* COP2: Not implemented. */
5736 case 4:
5737 case 5:
5738 /* fall through */
5739 default:
5740 goto die;
5742 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5743 gen_store_gpr(t0, rd);
5744 tcg_temp_free(t0);
5745 return;
5747 die:
5748 tcg_temp_free(t0);
5749 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5750 generate_exception(ctx, EXCP_RI);
5753 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
5754 int u, int sel, int h)
5756 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5757 TCGv t0 = tcg_temp_local_new();
5759 gen_load_gpr(t0, rt);
5760 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5761 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5762 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5763 /* NOP */ ;
5764 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5765 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5766 /* NOP */ ;
5767 else if (u == 0) {
5768 switch (rd) {
5769 case 1:
5770 switch (sel) {
5771 case 1:
5772 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5773 break;
5774 case 2:
5775 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5776 break;
5777 default:
5778 goto die;
5779 break;
5781 break;
5782 case 2:
5783 switch (sel) {
5784 case 1:
5785 gen_helper_mttc0_tcstatus(cpu_env, t0);
5786 break;
5787 case 2:
5788 gen_helper_mttc0_tcbind(cpu_env, t0);
5789 break;
5790 case 3:
5791 gen_helper_mttc0_tcrestart(cpu_env, t0);
5792 break;
5793 case 4:
5794 gen_helper_mttc0_tchalt(cpu_env, t0);
5795 break;
5796 case 5:
5797 gen_helper_mttc0_tccontext(cpu_env, t0);
5798 break;
5799 case 6:
5800 gen_helper_mttc0_tcschedule(cpu_env, t0);
5801 break;
5802 case 7:
5803 gen_helper_mttc0_tcschefback(cpu_env, t0);
5804 break;
5805 default:
5806 gen_mtc0(env, ctx, t0, rd, sel);
5807 break;
5809 break;
5810 case 10:
5811 switch (sel) {
5812 case 0:
5813 gen_helper_mttc0_entryhi(cpu_env, t0);
5814 break;
5815 default:
5816 gen_mtc0(env, ctx, t0, rd, sel);
5817 break;
5819 case 12:
5820 switch (sel) {
5821 case 0:
5822 gen_helper_mttc0_status(cpu_env, t0);
5823 break;
5824 default:
5825 gen_mtc0(env, ctx, t0, rd, sel);
5826 break;
5828 case 13:
5829 switch (sel) {
5830 case 0:
5831 gen_helper_mttc0_cause(cpu_env, t0);
5832 break;
5833 default:
5834 goto die;
5835 break;
5837 break;
5838 case 15:
5839 switch (sel) {
5840 case 1:
5841 gen_helper_mttc0_ebase(cpu_env, t0);
5842 break;
5843 default:
5844 goto die;
5845 break;
5847 break;
5848 case 23:
5849 switch (sel) {
5850 case 0:
5851 gen_helper_mttc0_debug(cpu_env, t0);
5852 break;
5853 default:
5854 gen_mtc0(env, ctx, t0, rd, sel);
5855 break;
5857 break;
5858 default:
5859 gen_mtc0(env, ctx, t0, rd, sel);
5861 } else switch (sel) {
5862 /* GPR registers. */
5863 case 0:
5864 gen_helper_0e1i(mttgpr, t0, rd);
5865 break;
5866 /* Auxiliary CPU registers */
5867 case 1:
5868 switch (rd) {
5869 case 0:
5870 gen_helper_0e1i(mttlo, t0, 0);
5871 break;
5872 case 1:
5873 gen_helper_0e1i(mtthi, t0, 0);
5874 break;
5875 case 2:
5876 gen_helper_0e1i(mttacx, t0, 0);
5877 break;
5878 case 4:
5879 gen_helper_0e1i(mttlo, t0, 1);
5880 break;
5881 case 5:
5882 gen_helper_0e1i(mtthi, t0, 1);
5883 break;
5884 case 6:
5885 gen_helper_0e1i(mttacx, t0, 1);
5886 break;
5887 case 8:
5888 gen_helper_0e1i(mttlo, t0, 2);
5889 break;
5890 case 9:
5891 gen_helper_0e1i(mtthi, t0, 2);
5892 break;
5893 case 10:
5894 gen_helper_0e1i(mttacx, t0, 2);
5895 break;
5896 case 12:
5897 gen_helper_0e1i(mttlo, t0, 3);
5898 break;
5899 case 13:
5900 gen_helper_0e1i(mtthi, t0, 3);
5901 break;
5902 case 14:
5903 gen_helper_0e1i(mttacx, t0, 3);
5904 break;
5905 case 16:
5906 gen_helper_mttdsp(cpu_env, t0);
5907 break;
5908 default:
5909 goto die;
5911 break;
5912 /* Floating point (COP1). */
5913 case 2:
5914 /* XXX: For now we support only a single FPU context. */
5915 if (h == 0) {
5916 TCGv_i32 fp0 = tcg_temp_new_i32();
5918 tcg_gen_trunc_tl_i32(fp0, t0);
5919 gen_store_fpr32(fp0, rd);
5920 tcg_temp_free_i32(fp0);
5921 } else {
5922 TCGv_i32 fp0 = tcg_temp_new_i32();
5924 tcg_gen_trunc_tl_i32(fp0, t0);
5925 gen_store_fpr32h(fp0, rd);
5926 tcg_temp_free_i32(fp0);
5928 break;
5929 case 3:
5930 /* XXX: For now we support only a single FPU context. */
5931 gen_helper_0e1i(ctc1, t0, rd);
5932 break;
5933 /* COP2: Not implemented. */
5934 case 4:
5935 case 5:
5936 /* fall through */
5937 default:
5938 goto die;
5940 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5941 tcg_temp_free(t0);
5942 return;
5944 die:
5945 tcg_temp_free(t0);
5946 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5947 generate_exception(ctx, EXCP_RI);
5950 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5952 const char *opn = "ldst";
5954 check_cp0_enabled(ctx);
5955 switch (opc) {
5956 case OPC_MFC0:
5957 if (rt == 0) {
5958 /* Treat as NOP. */
5959 return;
5961 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5962 opn = "mfc0";
5963 break;
5964 case OPC_MTC0:
5966 TCGv t0 = tcg_temp_new();
5968 gen_load_gpr(t0, rt);
5969 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5970 tcg_temp_free(t0);
5972 opn = "mtc0";
5973 break;
5974 #if defined(TARGET_MIPS64)
5975 case OPC_DMFC0:
5976 check_insn(env, ctx, ISA_MIPS3);
5977 if (rt == 0) {
5978 /* Treat as NOP. */
5979 return;
5981 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5982 opn = "dmfc0";
5983 break;
5984 case OPC_DMTC0:
5985 check_insn(env, ctx, ISA_MIPS3);
5987 TCGv t0 = tcg_temp_new();
5989 gen_load_gpr(t0, rt);
5990 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5991 tcg_temp_free(t0);
5993 opn = "dmtc0";
5994 break;
5995 #endif
5996 case OPC_MFTR:
5997 check_insn(env, ctx, ASE_MT);
5998 if (rd == 0) {
5999 /* Treat as NOP. */
6000 return;
6002 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
6003 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6004 opn = "mftr";
6005 break;
6006 case OPC_MTTR:
6007 check_insn(env, ctx, ASE_MT);
6008 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
6009 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6010 opn = "mttr";
6011 break;
6012 case OPC_TLBWI:
6013 opn = "tlbwi";
6014 if (!env->tlb->helper_tlbwi)
6015 goto die;
6016 gen_helper_tlbwi(cpu_env);
6017 break;
6018 case OPC_TLBWR:
6019 opn = "tlbwr";
6020 if (!env->tlb->helper_tlbwr)
6021 goto die;
6022 gen_helper_tlbwr(cpu_env);
6023 break;
6024 case OPC_TLBP:
6025 opn = "tlbp";
6026 if (!env->tlb->helper_tlbp)
6027 goto die;
6028 gen_helper_tlbp(cpu_env);
6029 break;
6030 case OPC_TLBR:
6031 opn = "tlbr";
6032 if (!env->tlb->helper_tlbr)
6033 goto die;
6034 gen_helper_tlbr(cpu_env);
6035 break;
6036 case OPC_ERET:
6037 opn = "eret";
6038 check_insn(env, ctx, ISA_MIPS2);
6039 gen_helper_eret(cpu_env);
6040 ctx->bstate = BS_EXCP;
6041 break;
6042 case OPC_DERET:
6043 opn = "deret";
6044 check_insn(env, ctx, ISA_MIPS32);
6045 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
6046 MIPS_INVAL(opn);
6047 generate_exception(ctx, EXCP_RI);
6048 } else {
6049 gen_helper_deret(cpu_env);
6050 ctx->bstate = BS_EXCP;
6052 break;
6053 case OPC_WAIT:
6054 opn = "wait";
6055 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
6056 /* If we get an exception, we want to restart at next instruction */
6057 ctx->pc += 4;
6058 save_cpu_state(ctx, 1);
6059 ctx->pc -= 4;
6060 gen_helper_wait(cpu_env);
6061 ctx->bstate = BS_EXCP;
6062 break;
6063 default:
6064 die:
6065 MIPS_INVAL(opn);
6066 generate_exception(ctx, EXCP_RI);
6067 return;
6069 (void)opn; /* avoid a compiler warning */
6070 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
6072 #endif /* !CONFIG_USER_ONLY */
6074 /* CP1 Branches (before delay slot) */
6075 static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
6076 int32_t cc, int32_t offset)
6078 target_ulong btarget;
6079 const char *opn = "cp1 cond branch";
6080 TCGv_i32 t0 = tcg_temp_new_i32();
6082 if (cc != 0)
6083 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6085 btarget = ctx->pc + 4 + offset;
6087 switch (op) {
6088 case OPC_BC1F:
6089 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6090 tcg_gen_not_i32(t0, t0);
6091 tcg_gen_andi_i32(t0, t0, 1);
6092 tcg_gen_extu_i32_tl(bcond, t0);
6093 opn = "bc1f";
6094 goto not_likely;
6095 case OPC_BC1FL:
6096 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6097 tcg_gen_not_i32(t0, t0);
6098 tcg_gen_andi_i32(t0, t0, 1);
6099 tcg_gen_extu_i32_tl(bcond, t0);
6100 opn = "bc1fl";
6101 goto likely;
6102 case OPC_BC1T:
6103 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6104 tcg_gen_andi_i32(t0, t0, 1);
6105 tcg_gen_extu_i32_tl(bcond, t0);
6106 opn = "bc1t";
6107 goto not_likely;
6108 case OPC_BC1TL:
6109 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6110 tcg_gen_andi_i32(t0, t0, 1);
6111 tcg_gen_extu_i32_tl(bcond, t0);
6112 opn = "bc1tl";
6113 likely:
6114 ctx->hflags |= MIPS_HFLAG_BL;
6115 break;
6116 case OPC_BC1FANY2:
6118 TCGv_i32 t1 = tcg_temp_new_i32();
6119 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6120 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6121 tcg_gen_nand_i32(t0, t0, t1);
6122 tcg_temp_free_i32(t1);
6123 tcg_gen_andi_i32(t0, t0, 1);
6124 tcg_gen_extu_i32_tl(bcond, t0);
6126 opn = "bc1any2f";
6127 goto not_likely;
6128 case OPC_BC1TANY2:
6130 TCGv_i32 t1 = tcg_temp_new_i32();
6131 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6132 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6133 tcg_gen_or_i32(t0, t0, t1);
6134 tcg_temp_free_i32(t1);
6135 tcg_gen_andi_i32(t0, t0, 1);
6136 tcg_gen_extu_i32_tl(bcond, t0);
6138 opn = "bc1any2t";
6139 goto not_likely;
6140 case OPC_BC1FANY4:
6142 TCGv_i32 t1 = tcg_temp_new_i32();
6143 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6144 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6145 tcg_gen_and_i32(t0, t0, t1);
6146 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6147 tcg_gen_and_i32(t0, t0, t1);
6148 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6149 tcg_gen_nand_i32(t0, t0, t1);
6150 tcg_temp_free_i32(t1);
6151 tcg_gen_andi_i32(t0, t0, 1);
6152 tcg_gen_extu_i32_tl(bcond, t0);
6154 opn = "bc1any4f";
6155 goto not_likely;
6156 case OPC_BC1TANY4:
6158 TCGv_i32 t1 = tcg_temp_new_i32();
6159 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6160 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6161 tcg_gen_or_i32(t0, t0, t1);
6162 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6163 tcg_gen_or_i32(t0, t0, t1);
6164 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6165 tcg_gen_or_i32(t0, t0, t1);
6166 tcg_temp_free_i32(t1);
6167 tcg_gen_andi_i32(t0, t0, 1);
6168 tcg_gen_extu_i32_tl(bcond, t0);
6170 opn = "bc1any4t";
6171 not_likely:
6172 ctx->hflags |= MIPS_HFLAG_BC;
6173 break;
6174 default:
6175 MIPS_INVAL(opn);
6176 generate_exception (ctx, EXCP_RI);
6177 goto out;
6179 (void)opn; /* avoid a compiler warning */
6180 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6181 ctx->hflags, btarget);
6182 ctx->btarget = btarget;
6184 out:
6185 tcg_temp_free_i32(t0);
6188 /* Coprocessor 1 (FPU) */
6190 #define FOP(func, fmt) (((fmt) << 21) | (func))
6192 enum fopcode {
6193 OPC_ADD_S = FOP(0, FMT_S),
6194 OPC_SUB_S = FOP(1, FMT_S),
6195 OPC_MUL_S = FOP(2, FMT_S),
6196 OPC_DIV_S = FOP(3, FMT_S),
6197 OPC_SQRT_S = FOP(4, FMT_S),
6198 OPC_ABS_S = FOP(5, FMT_S),
6199 OPC_MOV_S = FOP(6, FMT_S),
6200 OPC_NEG_S = FOP(7, FMT_S),
6201 OPC_ROUND_L_S = FOP(8, FMT_S),
6202 OPC_TRUNC_L_S = FOP(9, FMT_S),
6203 OPC_CEIL_L_S = FOP(10, FMT_S),
6204 OPC_FLOOR_L_S = FOP(11, FMT_S),
6205 OPC_ROUND_W_S = FOP(12, FMT_S),
6206 OPC_TRUNC_W_S = FOP(13, FMT_S),
6207 OPC_CEIL_W_S = FOP(14, FMT_S),
6208 OPC_FLOOR_W_S = FOP(15, FMT_S),
6209 OPC_MOVCF_S = FOP(17, FMT_S),
6210 OPC_MOVZ_S = FOP(18, FMT_S),
6211 OPC_MOVN_S = FOP(19, FMT_S),
6212 OPC_RECIP_S = FOP(21, FMT_S),
6213 OPC_RSQRT_S = FOP(22, FMT_S),
6214 OPC_RECIP2_S = FOP(28, FMT_S),
6215 OPC_RECIP1_S = FOP(29, FMT_S),
6216 OPC_RSQRT1_S = FOP(30, FMT_S),
6217 OPC_RSQRT2_S = FOP(31, FMT_S),
6218 OPC_CVT_D_S = FOP(33, FMT_S),
6219 OPC_CVT_W_S = FOP(36, FMT_S),
6220 OPC_CVT_L_S = FOP(37, FMT_S),
6221 OPC_CVT_PS_S = FOP(38, FMT_S),
6222 OPC_CMP_F_S = FOP (48, FMT_S),
6223 OPC_CMP_UN_S = FOP (49, FMT_S),
6224 OPC_CMP_EQ_S = FOP (50, FMT_S),
6225 OPC_CMP_UEQ_S = FOP (51, FMT_S),
6226 OPC_CMP_OLT_S = FOP (52, FMT_S),
6227 OPC_CMP_ULT_S = FOP (53, FMT_S),
6228 OPC_CMP_OLE_S = FOP (54, FMT_S),
6229 OPC_CMP_ULE_S = FOP (55, FMT_S),
6230 OPC_CMP_SF_S = FOP (56, FMT_S),
6231 OPC_CMP_NGLE_S = FOP (57, FMT_S),
6232 OPC_CMP_SEQ_S = FOP (58, FMT_S),
6233 OPC_CMP_NGL_S = FOP (59, FMT_S),
6234 OPC_CMP_LT_S = FOP (60, FMT_S),
6235 OPC_CMP_NGE_S = FOP (61, FMT_S),
6236 OPC_CMP_LE_S = FOP (62, FMT_S),
6237 OPC_CMP_NGT_S = FOP (63, FMT_S),
6239 OPC_ADD_D = FOP(0, FMT_D),
6240 OPC_SUB_D = FOP(1, FMT_D),
6241 OPC_MUL_D = FOP(2, FMT_D),
6242 OPC_DIV_D = FOP(3, FMT_D),
6243 OPC_SQRT_D = FOP(4, FMT_D),
6244 OPC_ABS_D = FOP(5, FMT_D),
6245 OPC_MOV_D = FOP(6, FMT_D),
6246 OPC_NEG_D = FOP(7, FMT_D),
6247 OPC_ROUND_L_D = FOP(8, FMT_D),
6248 OPC_TRUNC_L_D = FOP(9, FMT_D),
6249 OPC_CEIL_L_D = FOP(10, FMT_D),
6250 OPC_FLOOR_L_D = FOP(11, FMT_D),
6251 OPC_ROUND_W_D = FOP(12, FMT_D),
6252 OPC_TRUNC_W_D = FOP(13, FMT_D),
6253 OPC_CEIL_W_D = FOP(14, FMT_D),
6254 OPC_FLOOR_W_D = FOP(15, FMT_D),
6255 OPC_MOVCF_D = FOP(17, FMT_D),
6256 OPC_MOVZ_D = FOP(18, FMT_D),
6257 OPC_MOVN_D = FOP(19, FMT_D),
6258 OPC_RECIP_D = FOP(21, FMT_D),
6259 OPC_RSQRT_D = FOP(22, FMT_D),
6260 OPC_RECIP2_D = FOP(28, FMT_D),
6261 OPC_RECIP1_D = FOP(29, FMT_D),
6262 OPC_RSQRT1_D = FOP(30, FMT_D),
6263 OPC_RSQRT2_D = FOP(31, FMT_D),
6264 OPC_CVT_S_D = FOP(32, FMT_D),
6265 OPC_CVT_W_D = FOP(36, FMT_D),
6266 OPC_CVT_L_D = FOP(37, FMT_D),
6267 OPC_CMP_F_D = FOP (48, FMT_D),
6268 OPC_CMP_UN_D = FOP (49, FMT_D),
6269 OPC_CMP_EQ_D = FOP (50, FMT_D),
6270 OPC_CMP_UEQ_D = FOP (51, FMT_D),
6271 OPC_CMP_OLT_D = FOP (52, FMT_D),
6272 OPC_CMP_ULT_D = FOP (53, FMT_D),
6273 OPC_CMP_OLE_D = FOP (54, FMT_D),
6274 OPC_CMP_ULE_D = FOP (55, FMT_D),
6275 OPC_CMP_SF_D = FOP (56, FMT_D),
6276 OPC_CMP_NGLE_D = FOP (57, FMT_D),
6277 OPC_CMP_SEQ_D = FOP (58, FMT_D),
6278 OPC_CMP_NGL_D = FOP (59, FMT_D),
6279 OPC_CMP_LT_D = FOP (60, FMT_D),
6280 OPC_CMP_NGE_D = FOP (61, FMT_D),
6281 OPC_CMP_LE_D = FOP (62, FMT_D),
6282 OPC_CMP_NGT_D = FOP (63, FMT_D),
6284 OPC_CVT_S_W = FOP(32, FMT_W),
6285 OPC_CVT_D_W = FOP(33, FMT_W),
6286 OPC_CVT_S_L = FOP(32, FMT_L),
6287 OPC_CVT_D_L = FOP(33, FMT_L),
6288 OPC_CVT_PS_PW = FOP(38, FMT_W),
6290 OPC_ADD_PS = FOP(0, FMT_PS),
6291 OPC_SUB_PS = FOP(1, FMT_PS),
6292 OPC_MUL_PS = FOP(2, FMT_PS),
6293 OPC_DIV_PS = FOP(3, FMT_PS),
6294 OPC_ABS_PS = FOP(5, FMT_PS),
6295 OPC_MOV_PS = FOP(6, FMT_PS),
6296 OPC_NEG_PS = FOP(7, FMT_PS),
6297 OPC_MOVCF_PS = FOP(17, FMT_PS),
6298 OPC_MOVZ_PS = FOP(18, FMT_PS),
6299 OPC_MOVN_PS = FOP(19, FMT_PS),
6300 OPC_ADDR_PS = FOP(24, FMT_PS),
6301 OPC_MULR_PS = FOP(26, FMT_PS),
6302 OPC_RECIP2_PS = FOP(28, FMT_PS),
6303 OPC_RECIP1_PS = FOP(29, FMT_PS),
6304 OPC_RSQRT1_PS = FOP(30, FMT_PS),
6305 OPC_RSQRT2_PS = FOP(31, FMT_PS),
6307 OPC_CVT_S_PU = FOP(32, FMT_PS),
6308 OPC_CVT_PW_PS = FOP(36, FMT_PS),
6309 OPC_CVT_S_PL = FOP(40, FMT_PS),
6310 OPC_PLL_PS = FOP(44, FMT_PS),
6311 OPC_PLU_PS = FOP(45, FMT_PS),
6312 OPC_PUL_PS = FOP(46, FMT_PS),
6313 OPC_PUU_PS = FOP(47, FMT_PS),
6314 OPC_CMP_F_PS = FOP (48, FMT_PS),
6315 OPC_CMP_UN_PS = FOP (49, FMT_PS),
6316 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6317 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6318 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6319 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6320 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6321 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6322 OPC_CMP_SF_PS = FOP (56, FMT_PS),
6323 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6324 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6325 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6326 OPC_CMP_LT_PS = FOP (60, FMT_PS),
6327 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6328 OPC_CMP_LE_PS = FOP (62, FMT_PS),
6329 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6332 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6334 const char *opn = "cp1 move";
6335 TCGv t0 = tcg_temp_new();
6337 switch (opc) {
6338 case OPC_MFC1:
6340 TCGv_i32 fp0 = tcg_temp_new_i32();
6342 gen_load_fpr32(fp0, fs);
6343 tcg_gen_ext_i32_tl(t0, fp0);
6344 tcg_temp_free_i32(fp0);
6346 gen_store_gpr(t0, rt);
6347 opn = "mfc1";
6348 break;
6349 case OPC_MTC1:
6350 gen_load_gpr(t0, rt);
6352 TCGv_i32 fp0 = tcg_temp_new_i32();
6354 tcg_gen_trunc_tl_i32(fp0, t0);
6355 gen_store_fpr32(fp0, fs);
6356 tcg_temp_free_i32(fp0);
6358 opn = "mtc1";
6359 break;
6360 case OPC_CFC1:
6361 gen_helper_1e0i(cfc1, t0, fs);
6362 gen_store_gpr(t0, rt);
6363 opn = "cfc1";
6364 break;
6365 case OPC_CTC1:
6366 gen_load_gpr(t0, rt);
6367 gen_helper_0e1i(ctc1, t0, fs);
6368 opn = "ctc1";
6369 break;
6370 #if defined(TARGET_MIPS64)
6371 case OPC_DMFC1:
6372 gen_load_fpr64(ctx, t0, fs);
6373 gen_store_gpr(t0, rt);
6374 opn = "dmfc1";
6375 break;
6376 case OPC_DMTC1:
6377 gen_load_gpr(t0, rt);
6378 gen_store_fpr64(ctx, t0, fs);
6379 opn = "dmtc1";
6380 break;
6381 #endif
6382 case OPC_MFHC1:
6384 TCGv_i32 fp0 = tcg_temp_new_i32();
6386 gen_load_fpr32h(fp0, fs);
6387 tcg_gen_ext_i32_tl(t0, fp0);
6388 tcg_temp_free_i32(fp0);
6390 gen_store_gpr(t0, rt);
6391 opn = "mfhc1";
6392 break;
6393 case OPC_MTHC1:
6394 gen_load_gpr(t0, rt);
6396 TCGv_i32 fp0 = tcg_temp_new_i32();
6398 tcg_gen_trunc_tl_i32(fp0, t0);
6399 gen_store_fpr32h(fp0, fs);
6400 tcg_temp_free_i32(fp0);
6402 opn = "mthc1";
6403 break;
6404 default:
6405 MIPS_INVAL(opn);
6406 generate_exception (ctx, EXCP_RI);
6407 goto out;
6409 (void)opn; /* avoid a compiler warning */
6410 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6412 out:
6413 tcg_temp_free(t0);
6416 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6418 int l1;
6419 TCGCond cond;
6420 TCGv_i32 t0;
6422 if (rd == 0) {
6423 /* Treat as NOP. */
6424 return;
6427 if (tf)
6428 cond = TCG_COND_EQ;
6429 else
6430 cond = TCG_COND_NE;
6432 l1 = gen_new_label();
6433 t0 = tcg_temp_new_i32();
6434 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6435 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6436 tcg_temp_free_i32(t0);
6437 if (rs == 0) {
6438 tcg_gen_movi_tl(cpu_gpr[rd], 0);
6439 } else {
6440 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6442 gen_set_label(l1);
6445 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6447 int cond;
6448 TCGv_i32 t0 = tcg_temp_new_i32();
6449 int l1 = gen_new_label();
6451 if (tf)
6452 cond = TCG_COND_EQ;
6453 else
6454 cond = TCG_COND_NE;
6456 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6457 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6458 gen_load_fpr32(t0, fs);
6459 gen_store_fpr32(t0, fd);
6460 gen_set_label(l1);
6461 tcg_temp_free_i32(t0);
6464 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6466 int cond;
6467 TCGv_i32 t0 = tcg_temp_new_i32();
6468 TCGv_i64 fp0;
6469 int l1 = gen_new_label();
6471 if (tf)
6472 cond = TCG_COND_EQ;
6473 else
6474 cond = TCG_COND_NE;
6476 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6477 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6478 tcg_temp_free_i32(t0);
6479 fp0 = tcg_temp_new_i64();
6480 gen_load_fpr64(ctx, fp0, fs);
6481 gen_store_fpr64(ctx, fp0, fd);
6482 tcg_temp_free_i64(fp0);
6483 gen_set_label(l1);
6486 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6488 int cond;
6489 TCGv_i32 t0 = tcg_temp_new_i32();
6490 int l1 = gen_new_label();
6491 int l2 = gen_new_label();
6493 if (tf)
6494 cond = TCG_COND_EQ;
6495 else
6496 cond = TCG_COND_NE;
6498 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6499 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6500 gen_load_fpr32(t0, fs);
6501 gen_store_fpr32(t0, fd);
6502 gen_set_label(l1);
6504 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
6505 tcg_gen_brcondi_i32(cond, t0, 0, l2);
6506 gen_load_fpr32h(t0, fs);
6507 gen_store_fpr32h(t0, fd);
6508 tcg_temp_free_i32(t0);
6509 gen_set_label(l2);
6513 static void gen_farith (DisasContext *ctx, enum fopcode op1,
6514 int ft, int fs, int fd, int cc)
6516 const char *opn = "farith";
6517 const char *condnames[] = {
6518 "c.f",
6519 "c.un",
6520 "c.eq",
6521 "c.ueq",
6522 "c.olt",
6523 "c.ult",
6524 "c.ole",
6525 "c.ule",
6526 "c.sf",
6527 "c.ngle",
6528 "c.seq",
6529 "c.ngl",
6530 "c.lt",
6531 "c.nge",
6532 "c.le",
6533 "c.ngt",
6535 const char *condnames_abs[] = {
6536 "cabs.f",
6537 "cabs.un",
6538 "cabs.eq",
6539 "cabs.ueq",
6540 "cabs.olt",
6541 "cabs.ult",
6542 "cabs.ole",
6543 "cabs.ule",
6544 "cabs.sf",
6545 "cabs.ngle",
6546 "cabs.seq",
6547 "cabs.ngl",
6548 "cabs.lt",
6549 "cabs.nge",
6550 "cabs.le",
6551 "cabs.ngt",
6553 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6554 uint32_t func = ctx->opcode & 0x3f;
6556 switch (op1) {
6557 case OPC_ADD_S:
6559 TCGv_i32 fp0 = tcg_temp_new_i32();
6560 TCGv_i32 fp1 = tcg_temp_new_i32();
6562 gen_load_fpr32(fp0, fs);
6563 gen_load_fpr32(fp1, ft);
6564 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
6565 tcg_temp_free_i32(fp1);
6566 gen_store_fpr32(fp0, fd);
6567 tcg_temp_free_i32(fp0);
6569 opn = "add.s";
6570 optype = BINOP;
6571 break;
6572 case OPC_SUB_S:
6574 TCGv_i32 fp0 = tcg_temp_new_i32();
6575 TCGv_i32 fp1 = tcg_temp_new_i32();
6577 gen_load_fpr32(fp0, fs);
6578 gen_load_fpr32(fp1, ft);
6579 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
6580 tcg_temp_free_i32(fp1);
6581 gen_store_fpr32(fp0, fd);
6582 tcg_temp_free_i32(fp0);
6584 opn = "sub.s";
6585 optype = BINOP;
6586 break;
6587 case OPC_MUL_S:
6589 TCGv_i32 fp0 = tcg_temp_new_i32();
6590 TCGv_i32 fp1 = tcg_temp_new_i32();
6592 gen_load_fpr32(fp0, fs);
6593 gen_load_fpr32(fp1, ft);
6594 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
6595 tcg_temp_free_i32(fp1);
6596 gen_store_fpr32(fp0, fd);
6597 tcg_temp_free_i32(fp0);
6599 opn = "mul.s";
6600 optype = BINOP;
6601 break;
6602 case OPC_DIV_S:
6604 TCGv_i32 fp0 = tcg_temp_new_i32();
6605 TCGv_i32 fp1 = tcg_temp_new_i32();
6607 gen_load_fpr32(fp0, fs);
6608 gen_load_fpr32(fp1, ft);
6609 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
6610 tcg_temp_free_i32(fp1);
6611 gen_store_fpr32(fp0, fd);
6612 tcg_temp_free_i32(fp0);
6614 opn = "div.s";
6615 optype = BINOP;
6616 break;
6617 case OPC_SQRT_S:
6619 TCGv_i32 fp0 = tcg_temp_new_i32();
6621 gen_load_fpr32(fp0, fs);
6622 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
6623 gen_store_fpr32(fp0, fd);
6624 tcg_temp_free_i32(fp0);
6626 opn = "sqrt.s";
6627 break;
6628 case OPC_ABS_S:
6630 TCGv_i32 fp0 = tcg_temp_new_i32();
6632 gen_load_fpr32(fp0, fs);
6633 gen_helper_float_abs_s(fp0, fp0);
6634 gen_store_fpr32(fp0, fd);
6635 tcg_temp_free_i32(fp0);
6637 opn = "abs.s";
6638 break;
6639 case OPC_MOV_S:
6641 TCGv_i32 fp0 = tcg_temp_new_i32();
6643 gen_load_fpr32(fp0, fs);
6644 gen_store_fpr32(fp0, fd);
6645 tcg_temp_free_i32(fp0);
6647 opn = "mov.s";
6648 break;
6649 case OPC_NEG_S:
6651 TCGv_i32 fp0 = tcg_temp_new_i32();
6653 gen_load_fpr32(fp0, fs);
6654 gen_helper_float_chs_s(fp0, fp0);
6655 gen_store_fpr32(fp0, fd);
6656 tcg_temp_free_i32(fp0);
6658 opn = "neg.s";
6659 break;
6660 case OPC_ROUND_L_S:
6661 check_cp1_64bitmode(ctx);
6663 TCGv_i32 fp32 = tcg_temp_new_i32();
6664 TCGv_i64 fp64 = tcg_temp_new_i64();
6666 gen_load_fpr32(fp32, fs);
6667 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
6668 tcg_temp_free_i32(fp32);
6669 gen_store_fpr64(ctx, fp64, fd);
6670 tcg_temp_free_i64(fp64);
6672 opn = "round.l.s";
6673 break;
6674 case OPC_TRUNC_L_S:
6675 check_cp1_64bitmode(ctx);
6677 TCGv_i32 fp32 = tcg_temp_new_i32();
6678 TCGv_i64 fp64 = tcg_temp_new_i64();
6680 gen_load_fpr32(fp32, fs);
6681 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
6682 tcg_temp_free_i32(fp32);
6683 gen_store_fpr64(ctx, fp64, fd);
6684 tcg_temp_free_i64(fp64);
6686 opn = "trunc.l.s";
6687 break;
6688 case OPC_CEIL_L_S:
6689 check_cp1_64bitmode(ctx);
6691 TCGv_i32 fp32 = tcg_temp_new_i32();
6692 TCGv_i64 fp64 = tcg_temp_new_i64();
6694 gen_load_fpr32(fp32, fs);
6695 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
6696 tcg_temp_free_i32(fp32);
6697 gen_store_fpr64(ctx, fp64, fd);
6698 tcg_temp_free_i64(fp64);
6700 opn = "ceil.l.s";
6701 break;
6702 case OPC_FLOOR_L_S:
6703 check_cp1_64bitmode(ctx);
6705 TCGv_i32 fp32 = tcg_temp_new_i32();
6706 TCGv_i64 fp64 = tcg_temp_new_i64();
6708 gen_load_fpr32(fp32, fs);
6709 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
6710 tcg_temp_free_i32(fp32);
6711 gen_store_fpr64(ctx, fp64, fd);
6712 tcg_temp_free_i64(fp64);
6714 opn = "floor.l.s";
6715 break;
6716 case OPC_ROUND_W_S:
6718 TCGv_i32 fp0 = tcg_temp_new_i32();
6720 gen_load_fpr32(fp0, fs);
6721 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
6722 gen_store_fpr32(fp0, fd);
6723 tcg_temp_free_i32(fp0);
6725 opn = "round.w.s";
6726 break;
6727 case OPC_TRUNC_W_S:
6729 TCGv_i32 fp0 = tcg_temp_new_i32();
6731 gen_load_fpr32(fp0, fs);
6732 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
6733 gen_store_fpr32(fp0, fd);
6734 tcg_temp_free_i32(fp0);
6736 opn = "trunc.w.s";
6737 break;
6738 case OPC_CEIL_W_S:
6740 TCGv_i32 fp0 = tcg_temp_new_i32();
6742 gen_load_fpr32(fp0, fs);
6743 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
6744 gen_store_fpr32(fp0, fd);
6745 tcg_temp_free_i32(fp0);
6747 opn = "ceil.w.s";
6748 break;
6749 case OPC_FLOOR_W_S:
6751 TCGv_i32 fp0 = tcg_temp_new_i32();
6753 gen_load_fpr32(fp0, fs);
6754 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
6755 gen_store_fpr32(fp0, fd);
6756 tcg_temp_free_i32(fp0);
6758 opn = "floor.w.s";
6759 break;
6760 case OPC_MOVCF_S:
6761 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6762 opn = "movcf.s";
6763 break;
6764 case OPC_MOVZ_S:
6766 int l1 = gen_new_label();
6767 TCGv_i32 fp0;
6769 if (ft != 0) {
6770 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6772 fp0 = tcg_temp_new_i32();
6773 gen_load_fpr32(fp0, fs);
6774 gen_store_fpr32(fp0, fd);
6775 tcg_temp_free_i32(fp0);
6776 gen_set_label(l1);
6778 opn = "movz.s";
6779 break;
6780 case OPC_MOVN_S:
6782 int l1 = gen_new_label();
6783 TCGv_i32 fp0;
6785 if (ft != 0) {
6786 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6787 fp0 = tcg_temp_new_i32();
6788 gen_load_fpr32(fp0, fs);
6789 gen_store_fpr32(fp0, fd);
6790 tcg_temp_free_i32(fp0);
6791 gen_set_label(l1);
6794 opn = "movn.s";
6795 break;
6796 case OPC_RECIP_S:
6797 check_cop1x(ctx);
6799 TCGv_i32 fp0 = tcg_temp_new_i32();
6801 gen_load_fpr32(fp0, fs);
6802 gen_helper_float_recip_s(fp0, cpu_env, fp0);
6803 gen_store_fpr32(fp0, fd);
6804 tcg_temp_free_i32(fp0);
6806 opn = "recip.s";
6807 break;
6808 case OPC_RSQRT_S:
6809 check_cop1x(ctx);
6811 TCGv_i32 fp0 = tcg_temp_new_i32();
6813 gen_load_fpr32(fp0, fs);
6814 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
6815 gen_store_fpr32(fp0, fd);
6816 tcg_temp_free_i32(fp0);
6818 opn = "rsqrt.s";
6819 break;
6820 case OPC_RECIP2_S:
6821 check_cp1_64bitmode(ctx);
6823 TCGv_i32 fp0 = tcg_temp_new_i32();
6824 TCGv_i32 fp1 = tcg_temp_new_i32();
6826 gen_load_fpr32(fp0, fs);
6827 gen_load_fpr32(fp1, ft);
6828 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
6829 tcg_temp_free_i32(fp1);
6830 gen_store_fpr32(fp0, fd);
6831 tcg_temp_free_i32(fp0);
6833 opn = "recip2.s";
6834 break;
6835 case OPC_RECIP1_S:
6836 check_cp1_64bitmode(ctx);
6838 TCGv_i32 fp0 = tcg_temp_new_i32();
6840 gen_load_fpr32(fp0, fs);
6841 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
6842 gen_store_fpr32(fp0, fd);
6843 tcg_temp_free_i32(fp0);
6845 opn = "recip1.s";
6846 break;
6847 case OPC_RSQRT1_S:
6848 check_cp1_64bitmode(ctx);
6850 TCGv_i32 fp0 = tcg_temp_new_i32();
6852 gen_load_fpr32(fp0, fs);
6853 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
6854 gen_store_fpr32(fp0, fd);
6855 tcg_temp_free_i32(fp0);
6857 opn = "rsqrt1.s";
6858 break;
6859 case OPC_RSQRT2_S:
6860 check_cp1_64bitmode(ctx);
6862 TCGv_i32 fp0 = tcg_temp_new_i32();
6863 TCGv_i32 fp1 = tcg_temp_new_i32();
6865 gen_load_fpr32(fp0, fs);
6866 gen_load_fpr32(fp1, ft);
6867 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
6868 tcg_temp_free_i32(fp1);
6869 gen_store_fpr32(fp0, fd);
6870 tcg_temp_free_i32(fp0);
6872 opn = "rsqrt2.s";
6873 break;
6874 case OPC_CVT_D_S:
6875 check_cp1_registers(ctx, fd);
6877 TCGv_i32 fp32 = tcg_temp_new_i32();
6878 TCGv_i64 fp64 = tcg_temp_new_i64();
6880 gen_load_fpr32(fp32, fs);
6881 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
6882 tcg_temp_free_i32(fp32);
6883 gen_store_fpr64(ctx, fp64, fd);
6884 tcg_temp_free_i64(fp64);
6886 opn = "cvt.d.s";
6887 break;
6888 case OPC_CVT_W_S:
6890 TCGv_i32 fp0 = tcg_temp_new_i32();
6892 gen_load_fpr32(fp0, fs);
6893 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
6894 gen_store_fpr32(fp0, fd);
6895 tcg_temp_free_i32(fp0);
6897 opn = "cvt.w.s";
6898 break;
6899 case OPC_CVT_L_S:
6900 check_cp1_64bitmode(ctx);
6902 TCGv_i32 fp32 = tcg_temp_new_i32();
6903 TCGv_i64 fp64 = tcg_temp_new_i64();
6905 gen_load_fpr32(fp32, fs);
6906 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
6907 tcg_temp_free_i32(fp32);
6908 gen_store_fpr64(ctx, fp64, fd);
6909 tcg_temp_free_i64(fp64);
6911 opn = "cvt.l.s";
6912 break;
6913 case OPC_CVT_PS_S:
6914 check_cp1_64bitmode(ctx);
6916 TCGv_i64 fp64 = tcg_temp_new_i64();
6917 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6918 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6920 gen_load_fpr32(fp32_0, fs);
6921 gen_load_fpr32(fp32_1, ft);
6922 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
6923 tcg_temp_free_i32(fp32_1);
6924 tcg_temp_free_i32(fp32_0);
6925 gen_store_fpr64(ctx, fp64, fd);
6926 tcg_temp_free_i64(fp64);
6928 opn = "cvt.ps.s";
6929 break;
6930 case OPC_CMP_F_S:
6931 case OPC_CMP_UN_S:
6932 case OPC_CMP_EQ_S:
6933 case OPC_CMP_UEQ_S:
6934 case OPC_CMP_OLT_S:
6935 case OPC_CMP_ULT_S:
6936 case OPC_CMP_OLE_S:
6937 case OPC_CMP_ULE_S:
6938 case OPC_CMP_SF_S:
6939 case OPC_CMP_NGLE_S:
6940 case OPC_CMP_SEQ_S:
6941 case OPC_CMP_NGL_S:
6942 case OPC_CMP_LT_S:
6943 case OPC_CMP_NGE_S:
6944 case OPC_CMP_LE_S:
6945 case OPC_CMP_NGT_S:
6946 if (ctx->opcode & (1 << 6)) {
6947 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6948 opn = condnames_abs[func-48];
6949 } else {
6950 gen_cmp_s(ctx, func-48, ft, fs, cc);
6951 opn = condnames[func-48];
6953 break;
6954 case OPC_ADD_D:
6955 check_cp1_registers(ctx, fs | ft | fd);
6957 TCGv_i64 fp0 = tcg_temp_new_i64();
6958 TCGv_i64 fp1 = tcg_temp_new_i64();
6960 gen_load_fpr64(ctx, fp0, fs);
6961 gen_load_fpr64(ctx, fp1, ft);
6962 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
6963 tcg_temp_free_i64(fp1);
6964 gen_store_fpr64(ctx, fp0, fd);
6965 tcg_temp_free_i64(fp0);
6967 opn = "add.d";
6968 optype = BINOP;
6969 break;
6970 case OPC_SUB_D:
6971 check_cp1_registers(ctx, fs | ft | fd);
6973 TCGv_i64 fp0 = tcg_temp_new_i64();
6974 TCGv_i64 fp1 = tcg_temp_new_i64();
6976 gen_load_fpr64(ctx, fp0, fs);
6977 gen_load_fpr64(ctx, fp1, ft);
6978 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
6979 tcg_temp_free_i64(fp1);
6980 gen_store_fpr64(ctx, fp0, fd);
6981 tcg_temp_free_i64(fp0);
6983 opn = "sub.d";
6984 optype = BINOP;
6985 break;
6986 case OPC_MUL_D:
6987 check_cp1_registers(ctx, fs | ft | fd);
6989 TCGv_i64 fp0 = tcg_temp_new_i64();
6990 TCGv_i64 fp1 = tcg_temp_new_i64();
6992 gen_load_fpr64(ctx, fp0, fs);
6993 gen_load_fpr64(ctx, fp1, ft);
6994 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
6995 tcg_temp_free_i64(fp1);
6996 gen_store_fpr64(ctx, fp0, fd);
6997 tcg_temp_free_i64(fp0);
6999 opn = "mul.d";
7000 optype = BINOP;
7001 break;
7002 case OPC_DIV_D:
7003 check_cp1_registers(ctx, fs | ft | fd);
7005 TCGv_i64 fp0 = tcg_temp_new_i64();
7006 TCGv_i64 fp1 = tcg_temp_new_i64();
7008 gen_load_fpr64(ctx, fp0, fs);
7009 gen_load_fpr64(ctx, fp1, ft);
7010 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
7011 tcg_temp_free_i64(fp1);
7012 gen_store_fpr64(ctx, fp0, fd);
7013 tcg_temp_free_i64(fp0);
7015 opn = "div.d";
7016 optype = BINOP;
7017 break;
7018 case OPC_SQRT_D:
7019 check_cp1_registers(ctx, fs | fd);
7021 TCGv_i64 fp0 = tcg_temp_new_i64();
7023 gen_load_fpr64(ctx, fp0, fs);
7024 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
7025 gen_store_fpr64(ctx, fp0, fd);
7026 tcg_temp_free_i64(fp0);
7028 opn = "sqrt.d";
7029 break;
7030 case OPC_ABS_D:
7031 check_cp1_registers(ctx, fs | fd);
7033 TCGv_i64 fp0 = tcg_temp_new_i64();
7035 gen_load_fpr64(ctx, fp0, fs);
7036 gen_helper_float_abs_d(fp0, fp0);
7037 gen_store_fpr64(ctx, fp0, fd);
7038 tcg_temp_free_i64(fp0);
7040 opn = "abs.d";
7041 break;
7042 case OPC_MOV_D:
7043 check_cp1_registers(ctx, fs | fd);
7045 TCGv_i64 fp0 = tcg_temp_new_i64();
7047 gen_load_fpr64(ctx, fp0, fs);
7048 gen_store_fpr64(ctx, fp0, fd);
7049 tcg_temp_free_i64(fp0);
7051 opn = "mov.d";
7052 break;
7053 case OPC_NEG_D:
7054 check_cp1_registers(ctx, fs | fd);
7056 TCGv_i64 fp0 = tcg_temp_new_i64();
7058 gen_load_fpr64(ctx, fp0, fs);
7059 gen_helper_float_chs_d(fp0, fp0);
7060 gen_store_fpr64(ctx, fp0, fd);
7061 tcg_temp_free_i64(fp0);
7063 opn = "neg.d";
7064 break;
7065 case OPC_ROUND_L_D:
7066 check_cp1_64bitmode(ctx);
7068 TCGv_i64 fp0 = tcg_temp_new_i64();
7070 gen_load_fpr64(ctx, fp0, fs);
7071 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
7072 gen_store_fpr64(ctx, fp0, fd);
7073 tcg_temp_free_i64(fp0);
7075 opn = "round.l.d";
7076 break;
7077 case OPC_TRUNC_L_D:
7078 check_cp1_64bitmode(ctx);
7080 TCGv_i64 fp0 = tcg_temp_new_i64();
7082 gen_load_fpr64(ctx, fp0, fs);
7083 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
7084 gen_store_fpr64(ctx, fp0, fd);
7085 tcg_temp_free_i64(fp0);
7087 opn = "trunc.l.d";
7088 break;
7089 case OPC_CEIL_L_D:
7090 check_cp1_64bitmode(ctx);
7092 TCGv_i64 fp0 = tcg_temp_new_i64();
7094 gen_load_fpr64(ctx, fp0, fs);
7095 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
7096 gen_store_fpr64(ctx, fp0, fd);
7097 tcg_temp_free_i64(fp0);
7099 opn = "ceil.l.d";
7100 break;
7101 case OPC_FLOOR_L_D:
7102 check_cp1_64bitmode(ctx);
7104 TCGv_i64 fp0 = tcg_temp_new_i64();
7106 gen_load_fpr64(ctx, fp0, fs);
7107 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
7108 gen_store_fpr64(ctx, fp0, fd);
7109 tcg_temp_free_i64(fp0);
7111 opn = "floor.l.d";
7112 break;
7113 case OPC_ROUND_W_D:
7114 check_cp1_registers(ctx, fs);
7116 TCGv_i32 fp32 = tcg_temp_new_i32();
7117 TCGv_i64 fp64 = tcg_temp_new_i64();
7119 gen_load_fpr64(ctx, fp64, fs);
7120 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
7121 tcg_temp_free_i64(fp64);
7122 gen_store_fpr32(fp32, fd);
7123 tcg_temp_free_i32(fp32);
7125 opn = "round.w.d";
7126 break;
7127 case OPC_TRUNC_W_D:
7128 check_cp1_registers(ctx, fs);
7130 TCGv_i32 fp32 = tcg_temp_new_i32();
7131 TCGv_i64 fp64 = tcg_temp_new_i64();
7133 gen_load_fpr64(ctx, fp64, fs);
7134 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
7135 tcg_temp_free_i64(fp64);
7136 gen_store_fpr32(fp32, fd);
7137 tcg_temp_free_i32(fp32);
7139 opn = "trunc.w.d";
7140 break;
7141 case OPC_CEIL_W_D:
7142 check_cp1_registers(ctx, fs);
7144 TCGv_i32 fp32 = tcg_temp_new_i32();
7145 TCGv_i64 fp64 = tcg_temp_new_i64();
7147 gen_load_fpr64(ctx, fp64, fs);
7148 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
7149 tcg_temp_free_i64(fp64);
7150 gen_store_fpr32(fp32, fd);
7151 tcg_temp_free_i32(fp32);
7153 opn = "ceil.w.d";
7154 break;
7155 case OPC_FLOOR_W_D:
7156 check_cp1_registers(ctx, fs);
7158 TCGv_i32 fp32 = tcg_temp_new_i32();
7159 TCGv_i64 fp64 = tcg_temp_new_i64();
7161 gen_load_fpr64(ctx, fp64, fs);
7162 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
7163 tcg_temp_free_i64(fp64);
7164 gen_store_fpr32(fp32, fd);
7165 tcg_temp_free_i32(fp32);
7167 opn = "floor.w.d";
7168 break;
7169 case OPC_MOVCF_D:
7170 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7171 opn = "movcf.d";
7172 break;
7173 case OPC_MOVZ_D:
7175 int l1 = gen_new_label();
7176 TCGv_i64 fp0;
7178 if (ft != 0) {
7179 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7181 fp0 = tcg_temp_new_i64();
7182 gen_load_fpr64(ctx, fp0, fs);
7183 gen_store_fpr64(ctx, fp0, fd);
7184 tcg_temp_free_i64(fp0);
7185 gen_set_label(l1);
7187 opn = "movz.d";
7188 break;
7189 case OPC_MOVN_D:
7191 int l1 = gen_new_label();
7192 TCGv_i64 fp0;
7194 if (ft != 0) {
7195 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7196 fp0 = tcg_temp_new_i64();
7197 gen_load_fpr64(ctx, fp0, fs);
7198 gen_store_fpr64(ctx, fp0, fd);
7199 tcg_temp_free_i64(fp0);
7200 gen_set_label(l1);
7203 opn = "movn.d";
7204 break;
7205 case OPC_RECIP_D:
7206 check_cp1_64bitmode(ctx);
7208 TCGv_i64 fp0 = tcg_temp_new_i64();
7210 gen_load_fpr64(ctx, fp0, fs);
7211 gen_helper_float_recip_d(fp0, cpu_env, fp0);
7212 gen_store_fpr64(ctx, fp0, fd);
7213 tcg_temp_free_i64(fp0);
7215 opn = "recip.d";
7216 break;
7217 case OPC_RSQRT_D:
7218 check_cp1_64bitmode(ctx);
7220 TCGv_i64 fp0 = tcg_temp_new_i64();
7222 gen_load_fpr64(ctx, fp0, fs);
7223 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
7224 gen_store_fpr64(ctx, fp0, fd);
7225 tcg_temp_free_i64(fp0);
7227 opn = "rsqrt.d";
7228 break;
7229 case OPC_RECIP2_D:
7230 check_cp1_64bitmode(ctx);
7232 TCGv_i64 fp0 = tcg_temp_new_i64();
7233 TCGv_i64 fp1 = tcg_temp_new_i64();
7235 gen_load_fpr64(ctx, fp0, fs);
7236 gen_load_fpr64(ctx, fp1, ft);
7237 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
7238 tcg_temp_free_i64(fp1);
7239 gen_store_fpr64(ctx, fp0, fd);
7240 tcg_temp_free_i64(fp0);
7242 opn = "recip2.d";
7243 break;
7244 case OPC_RECIP1_D:
7245 check_cp1_64bitmode(ctx);
7247 TCGv_i64 fp0 = tcg_temp_new_i64();
7249 gen_load_fpr64(ctx, fp0, fs);
7250 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
7251 gen_store_fpr64(ctx, fp0, fd);
7252 tcg_temp_free_i64(fp0);
7254 opn = "recip1.d";
7255 break;
7256 case OPC_RSQRT1_D:
7257 check_cp1_64bitmode(ctx);
7259 TCGv_i64 fp0 = tcg_temp_new_i64();
7261 gen_load_fpr64(ctx, fp0, fs);
7262 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
7263 gen_store_fpr64(ctx, fp0, fd);
7264 tcg_temp_free_i64(fp0);
7266 opn = "rsqrt1.d";
7267 break;
7268 case OPC_RSQRT2_D:
7269 check_cp1_64bitmode(ctx);
7271 TCGv_i64 fp0 = tcg_temp_new_i64();
7272 TCGv_i64 fp1 = tcg_temp_new_i64();
7274 gen_load_fpr64(ctx, fp0, fs);
7275 gen_load_fpr64(ctx, fp1, ft);
7276 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
7277 tcg_temp_free_i64(fp1);
7278 gen_store_fpr64(ctx, fp0, fd);
7279 tcg_temp_free_i64(fp0);
7281 opn = "rsqrt2.d";
7282 break;
7283 case OPC_CMP_F_D:
7284 case OPC_CMP_UN_D:
7285 case OPC_CMP_EQ_D:
7286 case OPC_CMP_UEQ_D:
7287 case OPC_CMP_OLT_D:
7288 case OPC_CMP_ULT_D:
7289 case OPC_CMP_OLE_D:
7290 case OPC_CMP_ULE_D:
7291 case OPC_CMP_SF_D:
7292 case OPC_CMP_NGLE_D:
7293 case OPC_CMP_SEQ_D:
7294 case OPC_CMP_NGL_D:
7295 case OPC_CMP_LT_D:
7296 case OPC_CMP_NGE_D:
7297 case OPC_CMP_LE_D:
7298 case OPC_CMP_NGT_D:
7299 if (ctx->opcode & (1 << 6)) {
7300 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7301 opn = condnames_abs[func-48];
7302 } else {
7303 gen_cmp_d(ctx, func-48, ft, fs, cc);
7304 opn = condnames[func-48];
7306 break;
7307 case OPC_CVT_S_D:
7308 check_cp1_registers(ctx, fs);
7310 TCGv_i32 fp32 = tcg_temp_new_i32();
7311 TCGv_i64 fp64 = tcg_temp_new_i64();
7313 gen_load_fpr64(ctx, fp64, fs);
7314 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
7315 tcg_temp_free_i64(fp64);
7316 gen_store_fpr32(fp32, fd);
7317 tcg_temp_free_i32(fp32);
7319 opn = "cvt.s.d";
7320 break;
7321 case OPC_CVT_W_D:
7322 check_cp1_registers(ctx, fs);
7324 TCGv_i32 fp32 = tcg_temp_new_i32();
7325 TCGv_i64 fp64 = tcg_temp_new_i64();
7327 gen_load_fpr64(ctx, fp64, fs);
7328 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
7329 tcg_temp_free_i64(fp64);
7330 gen_store_fpr32(fp32, fd);
7331 tcg_temp_free_i32(fp32);
7333 opn = "cvt.w.d";
7334 break;
7335 case OPC_CVT_L_D:
7336 check_cp1_64bitmode(ctx);
7338 TCGv_i64 fp0 = tcg_temp_new_i64();
7340 gen_load_fpr64(ctx, fp0, fs);
7341 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
7342 gen_store_fpr64(ctx, fp0, fd);
7343 tcg_temp_free_i64(fp0);
7345 opn = "cvt.l.d";
7346 break;
7347 case OPC_CVT_S_W:
7349 TCGv_i32 fp0 = tcg_temp_new_i32();
7351 gen_load_fpr32(fp0, fs);
7352 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7353 gen_store_fpr32(fp0, fd);
7354 tcg_temp_free_i32(fp0);
7356 opn = "cvt.s.w";
7357 break;
7358 case OPC_CVT_D_W:
7359 check_cp1_registers(ctx, fd);
7361 TCGv_i32 fp32 = tcg_temp_new_i32();
7362 TCGv_i64 fp64 = tcg_temp_new_i64();
7364 gen_load_fpr32(fp32, fs);
7365 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
7366 tcg_temp_free_i32(fp32);
7367 gen_store_fpr64(ctx, fp64, fd);
7368 tcg_temp_free_i64(fp64);
7370 opn = "cvt.d.w";
7371 break;
7372 case OPC_CVT_S_L:
7373 check_cp1_64bitmode(ctx);
7375 TCGv_i32 fp32 = tcg_temp_new_i32();
7376 TCGv_i64 fp64 = tcg_temp_new_i64();
7378 gen_load_fpr64(ctx, fp64, fs);
7379 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
7380 tcg_temp_free_i64(fp64);
7381 gen_store_fpr32(fp32, fd);
7382 tcg_temp_free_i32(fp32);
7384 opn = "cvt.s.l";
7385 break;
7386 case OPC_CVT_D_L:
7387 check_cp1_64bitmode(ctx);
7389 TCGv_i64 fp0 = tcg_temp_new_i64();
7391 gen_load_fpr64(ctx, fp0, fs);
7392 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
7393 gen_store_fpr64(ctx, fp0, fd);
7394 tcg_temp_free_i64(fp0);
7396 opn = "cvt.d.l";
7397 break;
7398 case OPC_CVT_PS_PW:
7399 check_cp1_64bitmode(ctx);
7401 TCGv_i64 fp0 = tcg_temp_new_i64();
7403 gen_load_fpr64(ctx, fp0, fs);
7404 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
7405 gen_store_fpr64(ctx, fp0, fd);
7406 tcg_temp_free_i64(fp0);
7408 opn = "cvt.ps.pw";
7409 break;
7410 case OPC_ADD_PS:
7411 check_cp1_64bitmode(ctx);
7413 TCGv_i64 fp0 = tcg_temp_new_i64();
7414 TCGv_i64 fp1 = tcg_temp_new_i64();
7416 gen_load_fpr64(ctx, fp0, fs);
7417 gen_load_fpr64(ctx, fp1, ft);
7418 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
7419 tcg_temp_free_i64(fp1);
7420 gen_store_fpr64(ctx, fp0, fd);
7421 tcg_temp_free_i64(fp0);
7423 opn = "add.ps";
7424 break;
7425 case OPC_SUB_PS:
7426 check_cp1_64bitmode(ctx);
7428 TCGv_i64 fp0 = tcg_temp_new_i64();
7429 TCGv_i64 fp1 = tcg_temp_new_i64();
7431 gen_load_fpr64(ctx, fp0, fs);
7432 gen_load_fpr64(ctx, fp1, ft);
7433 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
7434 tcg_temp_free_i64(fp1);
7435 gen_store_fpr64(ctx, fp0, fd);
7436 tcg_temp_free_i64(fp0);
7438 opn = "sub.ps";
7439 break;
7440 case OPC_MUL_PS:
7441 check_cp1_64bitmode(ctx);
7443 TCGv_i64 fp0 = tcg_temp_new_i64();
7444 TCGv_i64 fp1 = tcg_temp_new_i64();
7446 gen_load_fpr64(ctx, fp0, fs);
7447 gen_load_fpr64(ctx, fp1, ft);
7448 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
7449 tcg_temp_free_i64(fp1);
7450 gen_store_fpr64(ctx, fp0, fd);
7451 tcg_temp_free_i64(fp0);
7453 opn = "mul.ps";
7454 break;
7455 case OPC_ABS_PS:
7456 check_cp1_64bitmode(ctx);
7458 TCGv_i64 fp0 = tcg_temp_new_i64();
7460 gen_load_fpr64(ctx, fp0, fs);
7461 gen_helper_float_abs_ps(fp0, fp0);
7462 gen_store_fpr64(ctx, fp0, fd);
7463 tcg_temp_free_i64(fp0);
7465 opn = "abs.ps";
7466 break;
7467 case OPC_MOV_PS:
7468 check_cp1_64bitmode(ctx);
7470 TCGv_i64 fp0 = tcg_temp_new_i64();
7472 gen_load_fpr64(ctx, fp0, fs);
7473 gen_store_fpr64(ctx, fp0, fd);
7474 tcg_temp_free_i64(fp0);
7476 opn = "mov.ps";
7477 break;
7478 case OPC_NEG_PS:
7479 check_cp1_64bitmode(ctx);
7481 TCGv_i64 fp0 = tcg_temp_new_i64();
7483 gen_load_fpr64(ctx, fp0, fs);
7484 gen_helper_float_chs_ps(fp0, fp0);
7485 gen_store_fpr64(ctx, fp0, fd);
7486 tcg_temp_free_i64(fp0);
7488 opn = "neg.ps";
7489 break;
7490 case OPC_MOVCF_PS:
7491 check_cp1_64bitmode(ctx);
7492 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7493 opn = "movcf.ps";
7494 break;
7495 case OPC_MOVZ_PS:
7496 check_cp1_64bitmode(ctx);
7498 int l1 = gen_new_label();
7499 TCGv_i64 fp0;
7501 if (ft != 0)
7502 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7503 fp0 = tcg_temp_new_i64();
7504 gen_load_fpr64(ctx, fp0, fs);
7505 gen_store_fpr64(ctx, fp0, fd);
7506 tcg_temp_free_i64(fp0);
7507 gen_set_label(l1);
7509 opn = "movz.ps";
7510 break;
7511 case OPC_MOVN_PS:
7512 check_cp1_64bitmode(ctx);
7514 int l1 = gen_new_label();
7515 TCGv_i64 fp0;
7517 if (ft != 0) {
7518 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7519 fp0 = tcg_temp_new_i64();
7520 gen_load_fpr64(ctx, fp0, fs);
7521 gen_store_fpr64(ctx, fp0, fd);
7522 tcg_temp_free_i64(fp0);
7523 gen_set_label(l1);
7526 opn = "movn.ps";
7527 break;
7528 case OPC_ADDR_PS:
7529 check_cp1_64bitmode(ctx);
7531 TCGv_i64 fp0 = tcg_temp_new_i64();
7532 TCGv_i64 fp1 = tcg_temp_new_i64();
7534 gen_load_fpr64(ctx, fp0, ft);
7535 gen_load_fpr64(ctx, fp1, fs);
7536 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
7537 tcg_temp_free_i64(fp1);
7538 gen_store_fpr64(ctx, fp0, fd);
7539 tcg_temp_free_i64(fp0);
7541 opn = "addr.ps";
7542 break;
7543 case OPC_MULR_PS:
7544 check_cp1_64bitmode(ctx);
7546 TCGv_i64 fp0 = tcg_temp_new_i64();
7547 TCGv_i64 fp1 = tcg_temp_new_i64();
7549 gen_load_fpr64(ctx, fp0, ft);
7550 gen_load_fpr64(ctx, fp1, fs);
7551 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
7552 tcg_temp_free_i64(fp1);
7553 gen_store_fpr64(ctx, fp0, fd);
7554 tcg_temp_free_i64(fp0);
7556 opn = "mulr.ps";
7557 break;
7558 case OPC_RECIP2_PS:
7559 check_cp1_64bitmode(ctx);
7561 TCGv_i64 fp0 = tcg_temp_new_i64();
7562 TCGv_i64 fp1 = tcg_temp_new_i64();
7564 gen_load_fpr64(ctx, fp0, fs);
7565 gen_load_fpr64(ctx, fp1, ft);
7566 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
7567 tcg_temp_free_i64(fp1);
7568 gen_store_fpr64(ctx, fp0, fd);
7569 tcg_temp_free_i64(fp0);
7571 opn = "recip2.ps";
7572 break;
7573 case OPC_RECIP1_PS:
7574 check_cp1_64bitmode(ctx);
7576 TCGv_i64 fp0 = tcg_temp_new_i64();
7578 gen_load_fpr64(ctx, fp0, fs);
7579 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
7580 gen_store_fpr64(ctx, fp0, fd);
7581 tcg_temp_free_i64(fp0);
7583 opn = "recip1.ps";
7584 break;
7585 case OPC_RSQRT1_PS:
7586 check_cp1_64bitmode(ctx);
7588 TCGv_i64 fp0 = tcg_temp_new_i64();
7590 gen_load_fpr64(ctx, fp0, fs);
7591 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
7592 gen_store_fpr64(ctx, fp0, fd);
7593 tcg_temp_free_i64(fp0);
7595 opn = "rsqrt1.ps";
7596 break;
7597 case OPC_RSQRT2_PS:
7598 check_cp1_64bitmode(ctx);
7600 TCGv_i64 fp0 = tcg_temp_new_i64();
7601 TCGv_i64 fp1 = tcg_temp_new_i64();
7603 gen_load_fpr64(ctx, fp0, fs);
7604 gen_load_fpr64(ctx, fp1, ft);
7605 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
7606 tcg_temp_free_i64(fp1);
7607 gen_store_fpr64(ctx, fp0, fd);
7608 tcg_temp_free_i64(fp0);
7610 opn = "rsqrt2.ps";
7611 break;
7612 case OPC_CVT_S_PU:
7613 check_cp1_64bitmode(ctx);
7615 TCGv_i32 fp0 = tcg_temp_new_i32();
7617 gen_load_fpr32h(fp0, fs);
7618 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7619 gen_store_fpr32(fp0, fd);
7620 tcg_temp_free_i32(fp0);
7622 opn = "cvt.s.pu";
7623 break;
7624 case OPC_CVT_PW_PS:
7625 check_cp1_64bitmode(ctx);
7627 TCGv_i64 fp0 = tcg_temp_new_i64();
7629 gen_load_fpr64(ctx, fp0, fs);
7630 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
7631 gen_store_fpr64(ctx, fp0, fd);
7632 tcg_temp_free_i64(fp0);
7634 opn = "cvt.pw.ps";
7635 break;
7636 case OPC_CVT_S_PL:
7637 check_cp1_64bitmode(ctx);
7639 TCGv_i32 fp0 = tcg_temp_new_i32();
7641 gen_load_fpr32(fp0, fs);
7642 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7643 gen_store_fpr32(fp0, fd);
7644 tcg_temp_free_i32(fp0);
7646 opn = "cvt.s.pl";
7647 break;
7648 case OPC_PLL_PS:
7649 check_cp1_64bitmode(ctx);
7651 TCGv_i32 fp0 = tcg_temp_new_i32();
7652 TCGv_i32 fp1 = tcg_temp_new_i32();
7654 gen_load_fpr32(fp0, fs);
7655 gen_load_fpr32(fp1, ft);
7656 gen_store_fpr32h(fp0, fd);
7657 gen_store_fpr32(fp1, fd);
7658 tcg_temp_free_i32(fp0);
7659 tcg_temp_free_i32(fp1);
7661 opn = "pll.ps";
7662 break;
7663 case OPC_PLU_PS:
7664 check_cp1_64bitmode(ctx);
7666 TCGv_i32 fp0 = tcg_temp_new_i32();
7667 TCGv_i32 fp1 = tcg_temp_new_i32();
7669 gen_load_fpr32(fp0, fs);
7670 gen_load_fpr32h(fp1, ft);
7671 gen_store_fpr32(fp1, fd);
7672 gen_store_fpr32h(fp0, fd);
7673 tcg_temp_free_i32(fp0);
7674 tcg_temp_free_i32(fp1);
7676 opn = "plu.ps";
7677 break;
7678 case OPC_PUL_PS:
7679 check_cp1_64bitmode(ctx);
7681 TCGv_i32 fp0 = tcg_temp_new_i32();
7682 TCGv_i32 fp1 = tcg_temp_new_i32();
7684 gen_load_fpr32h(fp0, fs);
7685 gen_load_fpr32(fp1, ft);
7686 gen_store_fpr32(fp1, fd);
7687 gen_store_fpr32h(fp0, fd);
7688 tcg_temp_free_i32(fp0);
7689 tcg_temp_free_i32(fp1);
7691 opn = "pul.ps";
7692 break;
7693 case OPC_PUU_PS:
7694 check_cp1_64bitmode(ctx);
7696 TCGv_i32 fp0 = tcg_temp_new_i32();
7697 TCGv_i32 fp1 = tcg_temp_new_i32();
7699 gen_load_fpr32h(fp0, fs);
7700 gen_load_fpr32h(fp1, ft);
7701 gen_store_fpr32(fp1, fd);
7702 gen_store_fpr32h(fp0, fd);
7703 tcg_temp_free_i32(fp0);
7704 tcg_temp_free_i32(fp1);
7706 opn = "puu.ps";
7707 break;
7708 case OPC_CMP_F_PS:
7709 case OPC_CMP_UN_PS:
7710 case OPC_CMP_EQ_PS:
7711 case OPC_CMP_UEQ_PS:
7712 case OPC_CMP_OLT_PS:
7713 case OPC_CMP_ULT_PS:
7714 case OPC_CMP_OLE_PS:
7715 case OPC_CMP_ULE_PS:
7716 case OPC_CMP_SF_PS:
7717 case OPC_CMP_NGLE_PS:
7718 case OPC_CMP_SEQ_PS:
7719 case OPC_CMP_NGL_PS:
7720 case OPC_CMP_LT_PS:
7721 case OPC_CMP_NGE_PS:
7722 case OPC_CMP_LE_PS:
7723 case OPC_CMP_NGT_PS:
7724 if (ctx->opcode & (1 << 6)) {
7725 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7726 opn = condnames_abs[func-48];
7727 } else {
7728 gen_cmp_ps(ctx, func-48, ft, fs, cc);
7729 opn = condnames[func-48];
7731 break;
7732 default:
7733 MIPS_INVAL(opn);
7734 generate_exception (ctx, EXCP_RI);
7735 return;
7737 (void)opn; /* avoid a compiler warning */
7738 switch (optype) {
7739 case BINOP:
7740 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7741 break;
7742 case CMPOP:
7743 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7744 break;
7745 default:
7746 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7747 break;
7751 /* Coprocessor 3 (FPU) */
7752 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7753 int fd, int fs, int base, int index)
7755 const char *opn = "extended float load/store";
7756 int store = 0;
7757 TCGv t0 = tcg_temp_new();
7759 if (base == 0) {
7760 gen_load_gpr(t0, index);
7761 } else if (index == 0) {
7762 gen_load_gpr(t0, base);
7763 } else {
7764 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
7766 /* Don't do NOP if destination is zero: we must perform the actual
7767 memory access. */
7768 save_cpu_state(ctx, 0);
7769 switch (opc) {
7770 case OPC_LWXC1:
7771 check_cop1x(ctx);
7773 TCGv_i32 fp0 = tcg_temp_new_i32();
7775 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7776 tcg_gen_trunc_tl_i32(fp0, t0);
7777 gen_store_fpr32(fp0, fd);
7778 tcg_temp_free_i32(fp0);
7780 opn = "lwxc1";
7781 break;
7782 case OPC_LDXC1:
7783 check_cop1x(ctx);
7784 check_cp1_registers(ctx, fd);
7786 TCGv_i64 fp0 = tcg_temp_new_i64();
7788 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7789 gen_store_fpr64(ctx, fp0, fd);
7790 tcg_temp_free_i64(fp0);
7792 opn = "ldxc1";
7793 break;
7794 case OPC_LUXC1:
7795 check_cp1_64bitmode(ctx);
7796 tcg_gen_andi_tl(t0, t0, ~0x7);
7798 TCGv_i64 fp0 = tcg_temp_new_i64();
7800 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7801 gen_store_fpr64(ctx, fp0, fd);
7802 tcg_temp_free_i64(fp0);
7804 opn = "luxc1";
7805 break;
7806 case OPC_SWXC1:
7807 check_cop1x(ctx);
7809 TCGv_i32 fp0 = tcg_temp_new_i32();
7810 TCGv t1 = tcg_temp_new();
7812 gen_load_fpr32(fp0, fs);
7813 tcg_gen_extu_i32_tl(t1, fp0);
7814 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7815 tcg_temp_free_i32(fp0);
7816 tcg_temp_free(t1);
7818 opn = "swxc1";
7819 store = 1;
7820 break;
7821 case OPC_SDXC1:
7822 check_cop1x(ctx);
7823 check_cp1_registers(ctx, fs);
7825 TCGv_i64 fp0 = tcg_temp_new_i64();
7827 gen_load_fpr64(ctx, fp0, fs);
7828 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7829 tcg_temp_free_i64(fp0);
7831 opn = "sdxc1";
7832 store = 1;
7833 break;
7834 case OPC_SUXC1:
7835 check_cp1_64bitmode(ctx);
7836 tcg_gen_andi_tl(t0, t0, ~0x7);
7838 TCGv_i64 fp0 = tcg_temp_new_i64();
7840 gen_load_fpr64(ctx, fp0, fs);
7841 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7842 tcg_temp_free_i64(fp0);
7844 opn = "suxc1";
7845 store = 1;
7846 break;
7848 tcg_temp_free(t0);
7849 (void)opn; (void)store; /* avoid compiler warnings */
7850 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7851 regnames[index], regnames[base]);
7854 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7855 int fd, int fr, int fs, int ft)
7857 const char *opn = "flt3_arith";
7859 switch (opc) {
7860 case OPC_ALNV_PS:
7861 check_cp1_64bitmode(ctx);
7863 TCGv t0 = tcg_temp_local_new();
7864 TCGv_i32 fp = tcg_temp_new_i32();
7865 TCGv_i32 fph = tcg_temp_new_i32();
7866 int l1 = gen_new_label();
7867 int l2 = gen_new_label();
7869 gen_load_gpr(t0, fr);
7870 tcg_gen_andi_tl(t0, t0, 0x7);
7872 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7873 gen_load_fpr32(fp, fs);
7874 gen_load_fpr32h(fph, fs);
7875 gen_store_fpr32(fp, fd);
7876 gen_store_fpr32h(fph, fd);
7877 tcg_gen_br(l2);
7878 gen_set_label(l1);
7879 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7880 tcg_temp_free(t0);
7881 #ifdef TARGET_WORDS_BIGENDIAN
7882 gen_load_fpr32(fp, fs);
7883 gen_load_fpr32h(fph, ft);
7884 gen_store_fpr32h(fp, fd);
7885 gen_store_fpr32(fph, fd);
7886 #else
7887 gen_load_fpr32h(fph, fs);
7888 gen_load_fpr32(fp, ft);
7889 gen_store_fpr32(fph, fd);
7890 gen_store_fpr32h(fp, fd);
7891 #endif
7892 gen_set_label(l2);
7893 tcg_temp_free_i32(fp);
7894 tcg_temp_free_i32(fph);
7896 opn = "alnv.ps";
7897 break;
7898 case OPC_MADD_S:
7899 check_cop1x(ctx);
7901 TCGv_i32 fp0 = tcg_temp_new_i32();
7902 TCGv_i32 fp1 = tcg_temp_new_i32();
7903 TCGv_i32 fp2 = tcg_temp_new_i32();
7905 gen_load_fpr32(fp0, fs);
7906 gen_load_fpr32(fp1, ft);
7907 gen_load_fpr32(fp2, fr);
7908 gen_helper_float_muladd_s(fp2, cpu_env, fp0, fp1, fp2);
7909 tcg_temp_free_i32(fp0);
7910 tcg_temp_free_i32(fp1);
7911 gen_store_fpr32(fp2, fd);
7912 tcg_temp_free_i32(fp2);
7914 opn = "madd.s";
7915 break;
7916 case OPC_MADD_D:
7917 check_cop1x(ctx);
7918 check_cp1_registers(ctx, fd | fs | ft | fr);
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_d(fp2, cpu_env, 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.d";
7934 break;
7935 case OPC_MADD_PS:
7936 check_cp1_64bitmode(ctx);
7938 TCGv_i64 fp0 = tcg_temp_new_i64();
7939 TCGv_i64 fp1 = tcg_temp_new_i64();
7940 TCGv_i64 fp2 = tcg_temp_new_i64();
7942 gen_load_fpr64(ctx, fp0, fs);
7943 gen_load_fpr64(ctx, fp1, ft);
7944 gen_load_fpr64(ctx, fp2, fr);
7945 gen_helper_float_muladd_ps(fp2, cpu_env, fp0, fp1, fp2);
7946 tcg_temp_free_i64(fp0);
7947 tcg_temp_free_i64(fp1);
7948 gen_store_fpr64(ctx, fp2, fd);
7949 tcg_temp_free_i64(fp2);
7951 opn = "madd.ps";
7952 break;
7953 case OPC_MSUB_S:
7954 check_cop1x(ctx);
7956 TCGv_i32 fp0 = tcg_temp_new_i32();
7957 TCGv_i32 fp1 = tcg_temp_new_i32();
7958 TCGv_i32 fp2 = tcg_temp_new_i32();
7960 gen_load_fpr32(fp0, fs);
7961 gen_load_fpr32(fp1, ft);
7962 gen_load_fpr32(fp2, fr);
7963 gen_helper_float_mulsub_s(fp2, cpu_env, fp0, fp1, fp2);
7964 tcg_temp_free_i32(fp0);
7965 tcg_temp_free_i32(fp1);
7966 gen_store_fpr32(fp2, fd);
7967 tcg_temp_free_i32(fp2);
7969 opn = "msub.s";
7970 break;
7971 case OPC_MSUB_D:
7972 check_cop1x(ctx);
7973 check_cp1_registers(ctx, fd | fs | ft | fr);
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_d(fp2, cpu_env, 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.d";
7989 break;
7990 case OPC_MSUB_PS:
7991 check_cp1_64bitmode(ctx);
7993 TCGv_i64 fp0 = tcg_temp_new_i64();
7994 TCGv_i64 fp1 = tcg_temp_new_i64();
7995 TCGv_i64 fp2 = tcg_temp_new_i64();
7997 gen_load_fpr64(ctx, fp0, fs);
7998 gen_load_fpr64(ctx, fp1, ft);
7999 gen_load_fpr64(ctx, fp2, fr);
8000 gen_helper_float_mulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
8001 tcg_temp_free_i64(fp0);
8002 tcg_temp_free_i64(fp1);
8003 gen_store_fpr64(ctx, fp2, fd);
8004 tcg_temp_free_i64(fp2);
8006 opn = "msub.ps";
8007 break;
8008 case OPC_NMADD_S:
8009 check_cop1x(ctx);
8011 TCGv_i32 fp0 = tcg_temp_new_i32();
8012 TCGv_i32 fp1 = tcg_temp_new_i32();
8013 TCGv_i32 fp2 = tcg_temp_new_i32();
8015 gen_load_fpr32(fp0, fs);
8016 gen_load_fpr32(fp1, ft);
8017 gen_load_fpr32(fp2, fr);
8018 gen_helper_float_nmuladd_s(fp2, cpu_env, fp0, fp1, fp2);
8019 tcg_temp_free_i32(fp0);
8020 tcg_temp_free_i32(fp1);
8021 gen_store_fpr32(fp2, fd);
8022 tcg_temp_free_i32(fp2);
8024 opn = "nmadd.s";
8025 break;
8026 case OPC_NMADD_D:
8027 check_cop1x(ctx);
8028 check_cp1_registers(ctx, fd | fs | ft | fr);
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_d(fp2, cpu_env, 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.d";
8044 break;
8045 case OPC_NMADD_PS:
8046 check_cp1_64bitmode(ctx);
8048 TCGv_i64 fp0 = tcg_temp_new_i64();
8049 TCGv_i64 fp1 = tcg_temp_new_i64();
8050 TCGv_i64 fp2 = tcg_temp_new_i64();
8052 gen_load_fpr64(ctx, fp0, fs);
8053 gen_load_fpr64(ctx, fp1, ft);
8054 gen_load_fpr64(ctx, fp2, fr);
8055 gen_helper_float_nmuladd_ps(fp2, cpu_env, fp0, fp1, fp2);
8056 tcg_temp_free_i64(fp0);
8057 tcg_temp_free_i64(fp1);
8058 gen_store_fpr64(ctx, fp2, fd);
8059 tcg_temp_free_i64(fp2);
8061 opn = "nmadd.ps";
8062 break;
8063 case OPC_NMSUB_S:
8064 check_cop1x(ctx);
8066 TCGv_i32 fp0 = tcg_temp_new_i32();
8067 TCGv_i32 fp1 = tcg_temp_new_i32();
8068 TCGv_i32 fp2 = tcg_temp_new_i32();
8070 gen_load_fpr32(fp0, fs);
8071 gen_load_fpr32(fp1, ft);
8072 gen_load_fpr32(fp2, fr);
8073 gen_helper_float_nmulsub_s(fp2, cpu_env, fp0, fp1, fp2);
8074 tcg_temp_free_i32(fp0);
8075 tcg_temp_free_i32(fp1);
8076 gen_store_fpr32(fp2, fd);
8077 tcg_temp_free_i32(fp2);
8079 opn = "nmsub.s";
8080 break;
8081 case OPC_NMSUB_D:
8082 check_cop1x(ctx);
8083 check_cp1_registers(ctx, fd | fs | ft | fr);
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_d(fp2, cpu_env, 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.d";
8099 break;
8100 case OPC_NMSUB_PS:
8101 check_cp1_64bitmode(ctx);
8103 TCGv_i64 fp0 = tcg_temp_new_i64();
8104 TCGv_i64 fp1 = tcg_temp_new_i64();
8105 TCGv_i64 fp2 = tcg_temp_new_i64();
8107 gen_load_fpr64(ctx, fp0, fs);
8108 gen_load_fpr64(ctx, fp1, ft);
8109 gen_load_fpr64(ctx, fp2, fr);
8110 gen_helper_float_nmulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
8111 tcg_temp_free_i64(fp0);
8112 tcg_temp_free_i64(fp1);
8113 gen_store_fpr64(ctx, fp2, fd);
8114 tcg_temp_free_i64(fp2);
8116 opn = "nmsub.ps";
8117 break;
8118 default:
8119 MIPS_INVAL(opn);
8120 generate_exception (ctx, EXCP_RI);
8121 return;
8123 (void)opn; /* avoid a compiler warning */
8124 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8125 fregnames[fs], fregnames[ft]);
8128 static void
8129 gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
8131 TCGv t0;
8133 #if !defined(CONFIG_USER_ONLY)
8134 /* The Linux kernel will emulate rdhwr if it's not supported natively.
8135 Therefore only check the ISA in system mode. */
8136 check_insn(env, ctx, ISA_MIPS32R2);
8137 #endif
8138 t0 = tcg_temp_new();
8140 switch (rd) {
8141 case 0:
8142 save_cpu_state(ctx, 1);
8143 gen_helper_rdhwr_cpunum(t0, cpu_env);
8144 gen_store_gpr(t0, rt);
8145 break;
8146 case 1:
8147 save_cpu_state(ctx, 1);
8148 gen_helper_rdhwr_synci_step(t0, cpu_env);
8149 gen_store_gpr(t0, rt);
8150 break;
8151 case 2:
8152 save_cpu_state(ctx, 1);
8153 gen_helper_rdhwr_cc(t0, cpu_env);
8154 gen_store_gpr(t0, rt);
8155 break;
8156 case 3:
8157 save_cpu_state(ctx, 1);
8158 gen_helper_rdhwr_ccres(t0, cpu_env);
8159 gen_store_gpr(t0, rt);
8160 break;
8161 case 29:
8162 #if defined(CONFIG_USER_ONLY)
8163 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
8164 gen_store_gpr(t0, rt);
8165 break;
8166 #else
8167 /* XXX: Some CPUs implement this in hardware.
8168 Not supported yet. */
8169 #endif
8170 default: /* Invalid */
8171 MIPS_INVAL("rdhwr");
8172 generate_exception(ctx, EXCP_RI);
8173 break;
8175 tcg_temp_free(t0);
8178 static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
8179 int insn_bytes)
8181 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8182 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8183 /* Branches completion */
8184 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8185 ctx->bstate = BS_BRANCH;
8186 save_cpu_state(ctx, 0);
8187 /* FIXME: Need to clear can_do_io. */
8188 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
8189 case MIPS_HFLAG_B:
8190 /* unconditional branch */
8191 MIPS_DEBUG("unconditional branch");
8192 if (proc_hflags & MIPS_HFLAG_BX) {
8193 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8195 gen_goto_tb(ctx, 0, ctx->btarget);
8196 break;
8197 case MIPS_HFLAG_BL:
8198 /* blikely taken case */
8199 MIPS_DEBUG("blikely branch taken");
8200 gen_goto_tb(ctx, 0, ctx->btarget);
8201 break;
8202 case MIPS_HFLAG_BC:
8203 /* Conditional branch */
8204 MIPS_DEBUG("conditional branch");
8206 int l1 = gen_new_label();
8208 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8209 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8210 gen_set_label(l1);
8211 gen_goto_tb(ctx, 0, ctx->btarget);
8213 break;
8214 case MIPS_HFLAG_BR:
8215 /* unconditional branch to register */
8216 MIPS_DEBUG("branch to register");
8217 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
8218 TCGv t0 = tcg_temp_new();
8219 TCGv_i32 t1 = tcg_temp_new_i32();
8221 tcg_gen_andi_tl(t0, btarget, 0x1);
8222 tcg_gen_trunc_tl_i32(t1, t0);
8223 tcg_temp_free(t0);
8224 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8225 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8226 tcg_gen_or_i32(hflags, hflags, t1);
8227 tcg_temp_free_i32(t1);
8229 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8230 } else {
8231 tcg_gen_mov_tl(cpu_PC, btarget);
8233 if (ctx->singlestep_enabled) {
8234 save_cpu_state(ctx, 0);
8235 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
8237 tcg_gen_exit_tb(0);
8238 break;
8239 default:
8240 MIPS_DEBUG("unknown branch");
8241 break;
8246 /* ISA extensions (ASEs) */
8247 /* MIPS16 extension to MIPS32 */
8249 /* MIPS16 major opcodes */
8250 enum {
8251 M16_OPC_ADDIUSP = 0x00,
8252 M16_OPC_ADDIUPC = 0x01,
8253 M16_OPC_B = 0x02,
8254 M16_OPC_JAL = 0x03,
8255 M16_OPC_BEQZ = 0x04,
8256 M16_OPC_BNEQZ = 0x05,
8257 M16_OPC_SHIFT = 0x06,
8258 M16_OPC_LD = 0x07,
8259 M16_OPC_RRIA = 0x08,
8260 M16_OPC_ADDIU8 = 0x09,
8261 M16_OPC_SLTI = 0x0a,
8262 M16_OPC_SLTIU = 0x0b,
8263 M16_OPC_I8 = 0x0c,
8264 M16_OPC_LI = 0x0d,
8265 M16_OPC_CMPI = 0x0e,
8266 M16_OPC_SD = 0x0f,
8267 M16_OPC_LB = 0x10,
8268 M16_OPC_LH = 0x11,
8269 M16_OPC_LWSP = 0x12,
8270 M16_OPC_LW = 0x13,
8271 M16_OPC_LBU = 0x14,
8272 M16_OPC_LHU = 0x15,
8273 M16_OPC_LWPC = 0x16,
8274 M16_OPC_LWU = 0x17,
8275 M16_OPC_SB = 0x18,
8276 M16_OPC_SH = 0x19,
8277 M16_OPC_SWSP = 0x1a,
8278 M16_OPC_SW = 0x1b,
8279 M16_OPC_RRR = 0x1c,
8280 M16_OPC_RR = 0x1d,
8281 M16_OPC_EXTEND = 0x1e,
8282 M16_OPC_I64 = 0x1f
8285 /* I8 funct field */
8286 enum {
8287 I8_BTEQZ = 0x0,
8288 I8_BTNEZ = 0x1,
8289 I8_SWRASP = 0x2,
8290 I8_ADJSP = 0x3,
8291 I8_SVRS = 0x4,
8292 I8_MOV32R = 0x5,
8293 I8_MOVR32 = 0x7
8296 /* RRR f field */
8297 enum {
8298 RRR_DADDU = 0x0,
8299 RRR_ADDU = 0x1,
8300 RRR_DSUBU = 0x2,
8301 RRR_SUBU = 0x3
8304 /* RR funct field */
8305 enum {
8306 RR_JR = 0x00,
8307 RR_SDBBP = 0x01,
8308 RR_SLT = 0x02,
8309 RR_SLTU = 0x03,
8310 RR_SLLV = 0x04,
8311 RR_BREAK = 0x05,
8312 RR_SRLV = 0x06,
8313 RR_SRAV = 0x07,
8314 RR_DSRL = 0x08,
8315 RR_CMP = 0x0a,
8316 RR_NEG = 0x0b,
8317 RR_AND = 0x0c,
8318 RR_OR = 0x0d,
8319 RR_XOR = 0x0e,
8320 RR_NOT = 0x0f,
8321 RR_MFHI = 0x10,
8322 RR_CNVT = 0x11,
8323 RR_MFLO = 0x12,
8324 RR_DSRA = 0x13,
8325 RR_DSLLV = 0x14,
8326 RR_DSRLV = 0x16,
8327 RR_DSRAV = 0x17,
8328 RR_MULT = 0x18,
8329 RR_MULTU = 0x19,
8330 RR_DIV = 0x1a,
8331 RR_DIVU = 0x1b,
8332 RR_DMULT = 0x1c,
8333 RR_DMULTU = 0x1d,
8334 RR_DDIV = 0x1e,
8335 RR_DDIVU = 0x1f
8338 /* I64 funct field */
8339 enum {
8340 I64_LDSP = 0x0,
8341 I64_SDSP = 0x1,
8342 I64_SDRASP = 0x2,
8343 I64_DADJSP = 0x3,
8344 I64_LDPC = 0x4,
8345 I64_DADDIU5 = 0x5,
8346 I64_DADDIUPC = 0x6,
8347 I64_DADDIUSP = 0x7
8350 /* RR ry field for CNVT */
8351 enum {
8352 RR_RY_CNVT_ZEB = 0x0,
8353 RR_RY_CNVT_ZEH = 0x1,
8354 RR_RY_CNVT_ZEW = 0x2,
8355 RR_RY_CNVT_SEB = 0x4,
8356 RR_RY_CNVT_SEH = 0x5,
8357 RR_RY_CNVT_SEW = 0x6,
8360 static int xlat (int r)
8362 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8364 return map[r];
8367 static void gen_mips16_save (DisasContext *ctx,
8368 int xsregs, int aregs,
8369 int do_ra, int do_s0, int do_s1,
8370 int framesize)
8372 TCGv t0 = tcg_temp_new();
8373 TCGv t1 = tcg_temp_new();
8374 int args, astatic;
8376 switch (aregs) {
8377 case 0:
8378 case 1:
8379 case 2:
8380 case 3:
8381 case 11:
8382 args = 0;
8383 break;
8384 case 4:
8385 case 5:
8386 case 6:
8387 case 7:
8388 args = 1;
8389 break;
8390 case 8:
8391 case 9:
8392 case 10:
8393 args = 2;
8394 break;
8395 case 12:
8396 case 13:
8397 args = 3;
8398 break;
8399 case 14:
8400 args = 4;
8401 break;
8402 default:
8403 generate_exception(ctx, EXCP_RI);
8404 return;
8407 switch (args) {
8408 case 4:
8409 gen_base_offset_addr(ctx, t0, 29, 12);
8410 gen_load_gpr(t1, 7);
8411 op_st_sw(t1, t0, ctx);
8412 /* Fall through */
8413 case 3:
8414 gen_base_offset_addr(ctx, t0, 29, 8);
8415 gen_load_gpr(t1, 6);
8416 op_st_sw(t1, t0, ctx);
8417 /* Fall through */
8418 case 2:
8419 gen_base_offset_addr(ctx, t0, 29, 4);
8420 gen_load_gpr(t1, 5);
8421 op_st_sw(t1, t0, ctx);
8422 /* Fall through */
8423 case 1:
8424 gen_base_offset_addr(ctx, t0, 29, 0);
8425 gen_load_gpr(t1, 4);
8426 op_st_sw(t1, t0, ctx);
8429 gen_load_gpr(t0, 29);
8431 #define DECR_AND_STORE(reg) do { \
8432 tcg_gen_subi_tl(t0, t0, 4); \
8433 gen_load_gpr(t1, reg); \
8434 op_st_sw(t1, t0, ctx); \
8435 } while (0)
8437 if (do_ra) {
8438 DECR_AND_STORE(31);
8441 switch (xsregs) {
8442 case 7:
8443 DECR_AND_STORE(30);
8444 /* Fall through */
8445 case 6:
8446 DECR_AND_STORE(23);
8447 /* Fall through */
8448 case 5:
8449 DECR_AND_STORE(22);
8450 /* Fall through */
8451 case 4:
8452 DECR_AND_STORE(21);
8453 /* Fall through */
8454 case 3:
8455 DECR_AND_STORE(20);
8456 /* Fall through */
8457 case 2:
8458 DECR_AND_STORE(19);
8459 /* Fall through */
8460 case 1:
8461 DECR_AND_STORE(18);
8464 if (do_s1) {
8465 DECR_AND_STORE(17);
8467 if (do_s0) {
8468 DECR_AND_STORE(16);
8471 switch (aregs) {
8472 case 0:
8473 case 4:
8474 case 8:
8475 case 12:
8476 case 14:
8477 astatic = 0;
8478 break;
8479 case 1:
8480 case 5:
8481 case 9:
8482 case 13:
8483 astatic = 1;
8484 break;
8485 case 2:
8486 case 6:
8487 case 10:
8488 astatic = 2;
8489 break;
8490 case 3:
8491 case 7:
8492 astatic = 3;
8493 break;
8494 case 11:
8495 astatic = 4;
8496 break;
8497 default:
8498 generate_exception(ctx, EXCP_RI);
8499 return;
8502 if (astatic > 0) {
8503 DECR_AND_STORE(7);
8504 if (astatic > 1) {
8505 DECR_AND_STORE(6);
8506 if (astatic > 2) {
8507 DECR_AND_STORE(5);
8508 if (astatic > 3) {
8509 DECR_AND_STORE(4);
8514 #undef DECR_AND_STORE
8516 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8517 tcg_temp_free(t0);
8518 tcg_temp_free(t1);
8521 static void gen_mips16_restore (DisasContext *ctx,
8522 int xsregs, int aregs,
8523 int do_ra, int do_s0, int do_s1,
8524 int framesize)
8526 int astatic;
8527 TCGv t0 = tcg_temp_new();
8528 TCGv t1 = tcg_temp_new();
8530 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8532 #define DECR_AND_LOAD(reg) do { \
8533 tcg_gen_subi_tl(t0, t0, 4); \
8534 op_ld_lw(t1, t0, ctx); \
8535 gen_store_gpr(t1, reg); \
8536 } while (0)
8538 if (do_ra) {
8539 DECR_AND_LOAD(31);
8542 switch (xsregs) {
8543 case 7:
8544 DECR_AND_LOAD(30);
8545 /* Fall through */
8546 case 6:
8547 DECR_AND_LOAD(23);
8548 /* Fall through */
8549 case 5:
8550 DECR_AND_LOAD(22);
8551 /* Fall through */
8552 case 4:
8553 DECR_AND_LOAD(21);
8554 /* Fall through */
8555 case 3:
8556 DECR_AND_LOAD(20);
8557 /* Fall through */
8558 case 2:
8559 DECR_AND_LOAD(19);
8560 /* Fall through */
8561 case 1:
8562 DECR_AND_LOAD(18);
8565 if (do_s1) {
8566 DECR_AND_LOAD(17);
8568 if (do_s0) {
8569 DECR_AND_LOAD(16);
8572 switch (aregs) {
8573 case 0:
8574 case 4:
8575 case 8:
8576 case 12:
8577 case 14:
8578 astatic = 0;
8579 break;
8580 case 1:
8581 case 5:
8582 case 9:
8583 case 13:
8584 astatic = 1;
8585 break;
8586 case 2:
8587 case 6:
8588 case 10:
8589 astatic = 2;
8590 break;
8591 case 3:
8592 case 7:
8593 astatic = 3;
8594 break;
8595 case 11:
8596 astatic = 4;
8597 break;
8598 default:
8599 generate_exception(ctx, EXCP_RI);
8600 return;
8603 if (astatic > 0) {
8604 DECR_AND_LOAD(7);
8605 if (astatic > 1) {
8606 DECR_AND_LOAD(6);
8607 if (astatic > 2) {
8608 DECR_AND_LOAD(5);
8609 if (astatic > 3) {
8610 DECR_AND_LOAD(4);
8615 #undef DECR_AND_LOAD
8617 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8618 tcg_temp_free(t0);
8619 tcg_temp_free(t1);
8622 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8623 int is_64_bit, int extended)
8625 TCGv t0;
8627 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8628 generate_exception(ctx, EXCP_RI);
8629 return;
8632 t0 = tcg_temp_new();
8634 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8635 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8636 if (!is_64_bit) {
8637 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8640 tcg_temp_free(t0);
8643 #if defined(TARGET_MIPS64)
8644 static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
8645 int ry, int funct, int16_t offset,
8646 int extended)
8648 switch (funct) {
8649 case I64_LDSP:
8650 check_mips_64(ctx);
8651 offset = extended ? offset : offset << 3;
8652 gen_ld(env, ctx, OPC_LD, ry, 29, offset);
8653 break;
8654 case I64_SDSP:
8655 check_mips_64(ctx);
8656 offset = extended ? offset : offset << 3;
8657 gen_st(ctx, OPC_SD, ry, 29, offset);
8658 break;
8659 case I64_SDRASP:
8660 check_mips_64(ctx);
8661 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8662 gen_st(ctx, OPC_SD, 31, 29, offset);
8663 break;
8664 case I64_DADJSP:
8665 check_mips_64(ctx);
8666 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8667 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8668 break;
8669 case I64_LDPC:
8670 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8671 generate_exception(ctx, EXCP_RI);
8672 } else {
8673 offset = extended ? offset : offset << 3;
8674 gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
8676 break;
8677 case I64_DADDIU5:
8678 check_mips_64(ctx);
8679 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8680 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8681 break;
8682 case I64_DADDIUPC:
8683 check_mips_64(ctx);
8684 offset = extended ? offset : offset << 2;
8685 gen_addiupc(ctx, ry, offset, 1, extended);
8686 break;
8687 case I64_DADDIUSP:
8688 check_mips_64(ctx);
8689 offset = extended ? offset : offset << 2;
8690 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8691 break;
8694 #endif
8696 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
8697 int *is_branch)
8699 int extend = cpu_lduw_code(env, ctx->pc + 2);
8700 int op, rx, ry, funct, sa;
8701 int16_t imm, offset;
8703 ctx->opcode = (ctx->opcode << 16) | extend;
8704 op = (ctx->opcode >> 11) & 0x1f;
8705 sa = (ctx->opcode >> 22) & 0x1f;
8706 funct = (ctx->opcode >> 8) & 0x7;
8707 rx = xlat((ctx->opcode >> 8) & 0x7);
8708 ry = xlat((ctx->opcode >> 5) & 0x7);
8709 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8710 | ((ctx->opcode >> 21) & 0x3f) << 5
8711 | (ctx->opcode & 0x1f));
8713 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8714 counterparts. */
8715 switch (op) {
8716 case M16_OPC_ADDIUSP:
8717 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8718 break;
8719 case M16_OPC_ADDIUPC:
8720 gen_addiupc(ctx, rx, imm, 0, 1);
8721 break;
8722 case M16_OPC_B:
8723 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8724 /* No delay slot, so just process as a normal instruction */
8725 break;
8726 case M16_OPC_BEQZ:
8727 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8728 /* No delay slot, so just process as a normal instruction */
8729 break;
8730 case M16_OPC_BNEQZ:
8731 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8732 /* No delay slot, so just process as a normal instruction */
8733 break;
8734 case M16_OPC_SHIFT:
8735 switch (ctx->opcode & 0x3) {
8736 case 0x0:
8737 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8738 break;
8739 case 0x1:
8740 #if defined(TARGET_MIPS64)
8741 check_mips_64(ctx);
8742 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8743 #else
8744 generate_exception(ctx, EXCP_RI);
8745 #endif
8746 break;
8747 case 0x2:
8748 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8749 break;
8750 case 0x3:
8751 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8752 break;
8754 break;
8755 #if defined(TARGET_MIPS64)
8756 case M16_OPC_LD:
8757 check_mips_64(ctx);
8758 gen_ld(env, ctx, OPC_LD, ry, rx, offset);
8759 break;
8760 #endif
8761 case M16_OPC_RRIA:
8762 imm = ctx->opcode & 0xf;
8763 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8764 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8765 imm = (int16_t) (imm << 1) >> 1;
8766 if ((ctx->opcode >> 4) & 0x1) {
8767 #if defined(TARGET_MIPS64)
8768 check_mips_64(ctx);
8769 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8770 #else
8771 generate_exception(ctx, EXCP_RI);
8772 #endif
8773 } else {
8774 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8776 break;
8777 case M16_OPC_ADDIU8:
8778 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8779 break;
8780 case M16_OPC_SLTI:
8781 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8782 break;
8783 case M16_OPC_SLTIU:
8784 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8785 break;
8786 case M16_OPC_I8:
8787 switch (funct) {
8788 case I8_BTEQZ:
8789 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8790 break;
8791 case I8_BTNEZ:
8792 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8793 break;
8794 case I8_SWRASP:
8795 gen_st(ctx, OPC_SW, 31, 29, imm);
8796 break;
8797 case I8_ADJSP:
8798 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8799 break;
8800 case I8_SVRS:
8802 int xsregs = (ctx->opcode >> 24) & 0x7;
8803 int aregs = (ctx->opcode >> 16) & 0xf;
8804 int do_ra = (ctx->opcode >> 6) & 0x1;
8805 int do_s0 = (ctx->opcode >> 5) & 0x1;
8806 int do_s1 = (ctx->opcode >> 4) & 0x1;
8807 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8808 | (ctx->opcode & 0xf)) << 3;
8810 if (ctx->opcode & (1 << 7)) {
8811 gen_mips16_save(ctx, xsregs, aregs,
8812 do_ra, do_s0, do_s1,
8813 framesize);
8814 } else {
8815 gen_mips16_restore(ctx, xsregs, aregs,
8816 do_ra, do_s0, do_s1,
8817 framesize);
8820 break;
8821 default:
8822 generate_exception(ctx, EXCP_RI);
8823 break;
8825 break;
8826 case M16_OPC_LI:
8827 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8828 break;
8829 case M16_OPC_CMPI:
8830 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8831 break;
8832 #if defined(TARGET_MIPS64)
8833 case M16_OPC_SD:
8834 gen_st(ctx, OPC_SD, ry, rx, offset);
8835 break;
8836 #endif
8837 case M16_OPC_LB:
8838 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8839 break;
8840 case M16_OPC_LH:
8841 gen_ld(env, ctx, OPC_LH, ry, rx, offset);
8842 break;
8843 case M16_OPC_LWSP:
8844 gen_ld(env, ctx, OPC_LW, rx, 29, offset);
8845 break;
8846 case M16_OPC_LW:
8847 gen_ld(env, ctx, OPC_LW, ry, rx, offset);
8848 break;
8849 case M16_OPC_LBU:
8850 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
8851 break;
8852 case M16_OPC_LHU:
8853 gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
8854 break;
8855 case M16_OPC_LWPC:
8856 gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
8857 break;
8858 #if defined(TARGET_MIPS64)
8859 case M16_OPC_LWU:
8860 gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
8861 break;
8862 #endif
8863 case M16_OPC_SB:
8864 gen_st(ctx, OPC_SB, ry, rx, offset);
8865 break;
8866 case M16_OPC_SH:
8867 gen_st(ctx, OPC_SH, ry, rx, offset);
8868 break;
8869 case M16_OPC_SWSP:
8870 gen_st(ctx, OPC_SW, rx, 29, offset);
8871 break;
8872 case M16_OPC_SW:
8873 gen_st(ctx, OPC_SW, ry, rx, offset);
8874 break;
8875 #if defined(TARGET_MIPS64)
8876 case M16_OPC_I64:
8877 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8878 break;
8879 #endif
8880 default:
8881 generate_exception(ctx, EXCP_RI);
8882 break;
8885 return 4;
8888 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
8889 int *is_branch)
8891 int rx, ry;
8892 int sa;
8893 int op, cnvt_op, op1, offset;
8894 int funct;
8895 int n_bytes;
8897 op = (ctx->opcode >> 11) & 0x1f;
8898 sa = (ctx->opcode >> 2) & 0x7;
8899 sa = sa == 0 ? 8 : sa;
8900 rx = xlat((ctx->opcode >> 8) & 0x7);
8901 cnvt_op = (ctx->opcode >> 5) & 0x7;
8902 ry = xlat((ctx->opcode >> 5) & 0x7);
8903 op1 = offset = ctx->opcode & 0x1f;
8905 n_bytes = 2;
8907 switch (op) {
8908 case M16_OPC_ADDIUSP:
8910 int16_t imm = ((uint8_t) ctx->opcode) << 2;
8912 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8914 break;
8915 case M16_OPC_ADDIUPC:
8916 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8917 break;
8918 case M16_OPC_B:
8919 offset = (ctx->opcode & 0x7ff) << 1;
8920 offset = (int16_t)(offset << 4) >> 4;
8921 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8922 /* No delay slot, so just process as a normal instruction */
8923 break;
8924 case M16_OPC_JAL:
8925 offset = cpu_lduw_code(env, ctx->pc + 2);
8926 offset = (((ctx->opcode & 0x1f) << 21)
8927 | ((ctx->opcode >> 5) & 0x1f) << 16
8928 | offset) << 2;
8929 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
8930 gen_compute_branch(ctx, op, 4, rx, ry, offset);
8931 n_bytes = 4;
8932 *is_branch = 1;
8933 break;
8934 case M16_OPC_BEQZ:
8935 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8936 /* No delay slot, so just process as a normal instruction */
8937 break;
8938 case M16_OPC_BNEQZ:
8939 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8940 /* No delay slot, so just process as a normal instruction */
8941 break;
8942 case M16_OPC_SHIFT:
8943 switch (ctx->opcode & 0x3) {
8944 case 0x0:
8945 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8946 break;
8947 case 0x1:
8948 #if defined(TARGET_MIPS64)
8949 check_mips_64(ctx);
8950 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8951 #else
8952 generate_exception(ctx, EXCP_RI);
8953 #endif
8954 break;
8955 case 0x2:
8956 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8957 break;
8958 case 0x3:
8959 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8960 break;
8962 break;
8963 #if defined(TARGET_MIPS64)
8964 case M16_OPC_LD:
8965 check_mips_64(ctx);
8966 gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
8967 break;
8968 #endif
8969 case M16_OPC_RRIA:
8971 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8973 if ((ctx->opcode >> 4) & 1) {
8974 #if defined(TARGET_MIPS64)
8975 check_mips_64(ctx);
8976 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8977 #else
8978 generate_exception(ctx, EXCP_RI);
8979 #endif
8980 } else {
8981 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8984 break;
8985 case M16_OPC_ADDIU8:
8987 int16_t imm = (int8_t) ctx->opcode;
8989 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8991 break;
8992 case M16_OPC_SLTI:
8994 int16_t imm = (uint8_t) ctx->opcode;
8996 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8998 break;
8999 case M16_OPC_SLTIU:
9001 int16_t imm = (uint8_t) ctx->opcode;
9003 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
9005 break;
9006 case M16_OPC_I8:
9008 int reg32;
9010 funct = (ctx->opcode >> 8) & 0x7;
9011 switch (funct) {
9012 case I8_BTEQZ:
9013 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
9014 ((int8_t)ctx->opcode) << 1);
9015 break;
9016 case I8_BTNEZ:
9017 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
9018 ((int8_t)ctx->opcode) << 1);
9019 break;
9020 case I8_SWRASP:
9021 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
9022 break;
9023 case I8_ADJSP:
9024 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
9025 ((int8_t)ctx->opcode) << 3);
9026 break;
9027 case I8_SVRS:
9029 int do_ra = ctx->opcode & (1 << 6);
9030 int do_s0 = ctx->opcode & (1 << 5);
9031 int do_s1 = ctx->opcode & (1 << 4);
9032 int framesize = ctx->opcode & 0xf;
9034 if (framesize == 0) {
9035 framesize = 128;
9036 } else {
9037 framesize = framesize << 3;
9040 if (ctx->opcode & (1 << 7)) {
9041 gen_mips16_save(ctx, 0, 0,
9042 do_ra, do_s0, do_s1, framesize);
9043 } else {
9044 gen_mips16_restore(ctx, 0, 0,
9045 do_ra, do_s0, do_s1, framesize);
9048 break;
9049 case I8_MOV32R:
9051 int rz = xlat(ctx->opcode & 0x7);
9053 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9054 ((ctx->opcode >> 5) & 0x7);
9055 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
9057 break;
9058 case I8_MOVR32:
9059 reg32 = ctx->opcode & 0x1f;
9060 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
9061 break;
9062 default:
9063 generate_exception(ctx, EXCP_RI);
9064 break;
9067 break;
9068 case M16_OPC_LI:
9070 int16_t imm = (uint8_t) ctx->opcode;
9072 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
9074 break;
9075 case M16_OPC_CMPI:
9077 int16_t imm = (uint8_t) ctx->opcode;
9079 gen_logic_imm(env, OPC_XORI, 24, rx, imm);
9081 break;
9082 #if defined(TARGET_MIPS64)
9083 case M16_OPC_SD:
9084 check_mips_64(ctx);
9085 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
9086 break;
9087 #endif
9088 case M16_OPC_LB:
9089 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
9090 break;
9091 case M16_OPC_LH:
9092 gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
9093 break;
9094 case M16_OPC_LWSP:
9095 gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9096 break;
9097 case M16_OPC_LW:
9098 gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
9099 break;
9100 case M16_OPC_LBU:
9101 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
9102 break;
9103 case M16_OPC_LHU:
9104 gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
9105 break;
9106 case M16_OPC_LWPC:
9107 gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
9108 break;
9109 #if defined (TARGET_MIPS64)
9110 case M16_OPC_LWU:
9111 check_mips_64(ctx);
9112 gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
9113 break;
9114 #endif
9115 case M16_OPC_SB:
9116 gen_st(ctx, OPC_SB, ry, rx, offset);
9117 break;
9118 case M16_OPC_SH:
9119 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
9120 break;
9121 case M16_OPC_SWSP:
9122 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9123 break;
9124 case M16_OPC_SW:
9125 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
9126 break;
9127 case M16_OPC_RRR:
9129 int rz = xlat((ctx->opcode >> 2) & 0x7);
9130 int mips32_op;
9132 switch (ctx->opcode & 0x3) {
9133 case RRR_ADDU:
9134 mips32_op = OPC_ADDU;
9135 break;
9136 case RRR_SUBU:
9137 mips32_op = OPC_SUBU;
9138 break;
9139 #if defined(TARGET_MIPS64)
9140 case RRR_DADDU:
9141 mips32_op = OPC_DADDU;
9142 check_mips_64(ctx);
9143 break;
9144 case RRR_DSUBU:
9145 mips32_op = OPC_DSUBU;
9146 check_mips_64(ctx);
9147 break;
9148 #endif
9149 default:
9150 generate_exception(ctx, EXCP_RI);
9151 goto done;
9154 gen_arith(env, ctx, mips32_op, rz, rx, ry);
9155 done:
9158 break;
9159 case M16_OPC_RR:
9160 switch (op1) {
9161 case RR_JR:
9163 int nd = (ctx->opcode >> 7) & 0x1;
9164 int link = (ctx->opcode >> 6) & 0x1;
9165 int ra = (ctx->opcode >> 5) & 0x1;
9167 if (link) {
9168 op = nd ? OPC_JALRC : OPC_JALRS;
9169 } else {
9170 op = OPC_JR;
9173 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9174 if (!nd) {
9175 *is_branch = 1;
9178 break;
9179 case RR_SDBBP:
9180 /* XXX: not clear which exception should be raised
9181 * when in debug mode...
9183 check_insn(env, ctx, ISA_MIPS32);
9184 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9185 generate_exception(ctx, EXCP_DBp);
9186 } else {
9187 generate_exception(ctx, EXCP_DBp);
9189 break;
9190 case RR_SLT:
9191 gen_slt(env, OPC_SLT, 24, rx, ry);
9192 break;
9193 case RR_SLTU:
9194 gen_slt(env, OPC_SLTU, 24, rx, ry);
9195 break;
9196 case RR_BREAK:
9197 generate_exception(ctx, EXCP_BREAK);
9198 break;
9199 case RR_SLLV:
9200 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9201 break;
9202 case RR_SRLV:
9203 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9204 break;
9205 case RR_SRAV:
9206 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9207 break;
9208 #if defined (TARGET_MIPS64)
9209 case RR_DSRL:
9210 check_mips_64(ctx);
9211 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9212 break;
9213 #endif
9214 case RR_CMP:
9215 gen_logic(env, OPC_XOR, 24, rx, ry);
9216 break;
9217 case RR_NEG:
9218 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9219 break;
9220 case RR_AND:
9221 gen_logic(env, OPC_AND, rx, rx, ry);
9222 break;
9223 case RR_OR:
9224 gen_logic(env, OPC_OR, rx, rx, ry);
9225 break;
9226 case RR_XOR:
9227 gen_logic(env, OPC_XOR, rx, rx, ry);
9228 break;
9229 case RR_NOT:
9230 gen_logic(env, OPC_NOR, rx, ry, 0);
9231 break;
9232 case RR_MFHI:
9233 gen_HILO(ctx, OPC_MFHI, rx);
9234 break;
9235 case RR_CNVT:
9236 switch (cnvt_op) {
9237 case RR_RY_CNVT_ZEB:
9238 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9239 break;
9240 case RR_RY_CNVT_ZEH:
9241 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9242 break;
9243 case RR_RY_CNVT_SEB:
9244 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9245 break;
9246 case RR_RY_CNVT_SEH:
9247 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9248 break;
9249 #if defined (TARGET_MIPS64)
9250 case RR_RY_CNVT_ZEW:
9251 check_mips_64(ctx);
9252 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9253 break;
9254 case RR_RY_CNVT_SEW:
9255 check_mips_64(ctx);
9256 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9257 break;
9258 #endif
9259 default:
9260 generate_exception(ctx, EXCP_RI);
9261 break;
9263 break;
9264 case RR_MFLO:
9265 gen_HILO(ctx, OPC_MFLO, rx);
9266 break;
9267 #if defined (TARGET_MIPS64)
9268 case RR_DSRA:
9269 check_mips_64(ctx);
9270 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9271 break;
9272 case RR_DSLLV:
9273 check_mips_64(ctx);
9274 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9275 break;
9276 case RR_DSRLV:
9277 check_mips_64(ctx);
9278 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9279 break;
9280 case RR_DSRAV:
9281 check_mips_64(ctx);
9282 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9283 break;
9284 #endif
9285 case RR_MULT:
9286 gen_muldiv(ctx, OPC_MULT, rx, ry);
9287 break;
9288 case RR_MULTU:
9289 gen_muldiv(ctx, OPC_MULTU, rx, ry);
9290 break;
9291 case RR_DIV:
9292 gen_muldiv(ctx, OPC_DIV, rx, ry);
9293 break;
9294 case RR_DIVU:
9295 gen_muldiv(ctx, OPC_DIVU, rx, ry);
9296 break;
9297 #if defined (TARGET_MIPS64)
9298 case RR_DMULT:
9299 check_mips_64(ctx);
9300 gen_muldiv(ctx, OPC_DMULT, rx, ry);
9301 break;
9302 case RR_DMULTU:
9303 check_mips_64(ctx);
9304 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9305 break;
9306 case RR_DDIV:
9307 check_mips_64(ctx);
9308 gen_muldiv(ctx, OPC_DDIV, rx, ry);
9309 break;
9310 case RR_DDIVU:
9311 check_mips_64(ctx);
9312 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9313 break;
9314 #endif
9315 default:
9316 generate_exception(ctx, EXCP_RI);
9317 break;
9319 break;
9320 case M16_OPC_EXTEND:
9321 decode_extended_mips16_opc(env, ctx, is_branch);
9322 n_bytes = 4;
9323 break;
9324 #if defined(TARGET_MIPS64)
9325 case M16_OPC_I64:
9326 funct = (ctx->opcode >> 8) & 0x7;
9327 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9328 break;
9329 #endif
9330 default:
9331 generate_exception(ctx, EXCP_RI);
9332 break;
9335 return n_bytes;
9338 /* microMIPS extension to MIPS32 */
9340 /* microMIPS32 major opcodes */
9342 enum {
9343 POOL32A = 0x00,
9344 POOL16A = 0x01,
9345 LBU16 = 0x02,
9346 MOVE16 = 0x03,
9347 ADDI32 = 0x04,
9348 LBU32 = 0x05,
9349 SB32 = 0x06,
9350 LB32 = 0x07,
9352 POOL32B = 0x08,
9353 POOL16B = 0x09,
9354 LHU16 = 0x0a,
9355 ANDI16 = 0x0b,
9356 ADDIU32 = 0x0c,
9357 LHU32 = 0x0d,
9358 SH32 = 0x0e,
9359 LH32 = 0x0f,
9361 POOL32I = 0x10,
9362 POOL16C = 0x11,
9363 LWSP16 = 0x12,
9364 POOL16D = 0x13,
9365 ORI32 = 0x14,
9366 POOL32F = 0x15,
9367 POOL32S = 0x16,
9368 DADDIU32 = 0x17,
9370 POOL32C = 0x18,
9371 LWGP16 = 0x19,
9372 LW16 = 0x1a,
9373 POOL16E = 0x1b,
9374 XORI32 = 0x1c,
9375 JALS32 = 0x1d,
9376 ADDIUPC = 0x1e,
9377 POOL48A = 0x1f,
9379 /* 0x20 is reserved */
9380 RES_20 = 0x20,
9381 POOL16F = 0x21,
9382 SB16 = 0x22,
9383 BEQZ16 = 0x23,
9384 SLTI32 = 0x24,
9385 BEQ32 = 0x25,
9386 SWC132 = 0x26,
9387 LWC132 = 0x27,
9389 /* 0x28 and 0x29 are reserved */
9390 RES_28 = 0x28,
9391 RES_29 = 0x29,
9392 SH16 = 0x2a,
9393 BNEZ16 = 0x2b,
9394 SLTIU32 = 0x2c,
9395 BNE32 = 0x2d,
9396 SDC132 = 0x2e,
9397 LDC132 = 0x2f,
9399 /* 0x30 and 0x31 are reserved */
9400 RES_30 = 0x30,
9401 RES_31 = 0x31,
9402 SWSP16 = 0x32,
9403 B16 = 0x33,
9404 ANDI32 = 0x34,
9405 J32 = 0x35,
9406 SD32 = 0x36,
9407 LD32 = 0x37,
9409 /* 0x38 and 0x39 are reserved */
9410 RES_38 = 0x38,
9411 RES_39 = 0x39,
9412 SW16 = 0x3a,
9413 LI16 = 0x3b,
9414 JALX32 = 0x3c,
9415 JAL32 = 0x3d,
9416 SW32 = 0x3e,
9417 LW32 = 0x3f
9420 /* POOL32A encoding of minor opcode field */
9422 enum {
9423 /* These opcodes are distinguished only by bits 9..6; those bits are
9424 * what are recorded below. */
9425 SLL32 = 0x0,
9426 SRL32 = 0x1,
9427 SRA = 0x2,
9428 ROTR = 0x3,
9430 SLLV = 0x0,
9431 SRLV = 0x1,
9432 SRAV = 0x2,
9433 ROTRV = 0x3,
9434 ADD = 0x4,
9435 ADDU32 = 0x5,
9436 SUB = 0x6,
9437 SUBU32 = 0x7,
9438 MUL = 0x8,
9439 AND = 0x9,
9440 OR32 = 0xa,
9441 NOR = 0xb,
9442 XOR32 = 0xc,
9443 SLT = 0xd,
9444 SLTU = 0xe,
9446 MOVN = 0x0,
9447 MOVZ = 0x1,
9448 LWXS = 0x4,
9450 /* The following can be distinguished by their lower 6 bits. */
9451 INS = 0x0c,
9452 EXT = 0x2c,
9453 POOL32AXF = 0x3c
9456 /* POOL32AXF encoding of minor opcode field extension */
9458 enum {
9459 /* bits 11..6 */
9460 TEQ = 0x00,
9461 TGE = 0x08,
9462 TGEU = 0x10,
9463 TLT = 0x20,
9464 TLTU = 0x28,
9465 TNE = 0x30,
9467 MFC0 = 0x03,
9468 MTC0 = 0x0b,
9470 /* bits 13..12 for 0x01 */
9471 MFHI_ACC = 0x0,
9472 MFLO_ACC = 0x1,
9473 MTHI_ACC = 0x2,
9474 MTLO_ACC = 0x3,
9476 /* bits 13..12 for 0x2a */
9477 MADD_ACC = 0x0,
9478 MADDU_ACC = 0x1,
9479 MSUB_ACC = 0x2,
9480 MSUBU_ACC = 0x3,
9482 /* bits 13..12 for 0x32 */
9483 MULT_ACC = 0x0,
9484 MULTU_ACC = 0x0,
9486 /* bits 15..12 for 0x2c */
9487 SEB = 0x2,
9488 SEH = 0x3,
9489 CLO = 0x4,
9490 CLZ = 0x5,
9491 RDHWR = 0x6,
9492 WSBH = 0x7,
9493 MULT = 0x8,
9494 MULTU = 0x9,
9495 DIV = 0xa,
9496 DIVU = 0xb,
9497 MADD = 0xc,
9498 MADDU = 0xd,
9499 MSUB = 0xe,
9500 MSUBU = 0xf,
9502 /* bits 15..12 for 0x34 */
9503 MFC2 = 0x4,
9504 MTC2 = 0x5,
9505 MFHC2 = 0x8,
9506 MTHC2 = 0x9,
9507 CFC2 = 0xc,
9508 CTC2 = 0xd,
9510 /* bits 15..12 for 0x3c */
9511 JALR = 0x0,
9512 JR = 0x0, /* alias */
9513 JALR_HB = 0x1,
9514 JALRS = 0x4,
9515 JALRS_HB = 0x5,
9517 /* bits 15..12 for 0x05 */
9518 RDPGPR = 0xe,
9519 WRPGPR = 0xf,
9521 /* bits 15..12 for 0x0d */
9522 TLBP = 0x0,
9523 TLBR = 0x1,
9524 TLBWI = 0x2,
9525 TLBWR = 0x3,
9526 WAIT = 0x9,
9527 IRET = 0xd,
9528 DERET = 0xe,
9529 ERET = 0xf,
9531 /* bits 15..12 for 0x15 */
9532 DMT = 0x0,
9533 DVPE = 0x1,
9534 EMT = 0x2,
9535 EVPE = 0x3,
9537 /* bits 15..12 for 0x1d */
9538 DI = 0x4,
9539 EI = 0x5,
9541 /* bits 15..12 for 0x2d */
9542 SYNC = 0x6,
9543 SYSCALL = 0x8,
9544 SDBBP = 0xd,
9546 /* bits 15..12 for 0x35 */
9547 MFHI32 = 0x0,
9548 MFLO32 = 0x1,
9549 MTHI32 = 0x2,
9550 MTLO32 = 0x3,
9553 /* POOL32B encoding of minor opcode field (bits 15..12) */
9555 enum {
9556 LWC2 = 0x0,
9557 LWP = 0x1,
9558 LDP = 0x4,
9559 LWM32 = 0x5,
9560 CACHE = 0x6,
9561 LDM = 0x7,
9562 SWC2 = 0x8,
9563 SWP = 0x9,
9564 SDP = 0xc,
9565 SWM32 = 0xd,
9566 SDM = 0xf
9569 /* POOL32C encoding of minor opcode field (bits 15..12) */
9571 enum {
9572 LWL = 0x0,
9573 SWL = 0x8,
9574 LWR = 0x1,
9575 SWR = 0x9,
9576 PREF = 0x2,
9577 /* 0xa is reserved */
9578 LL = 0x3,
9579 SC = 0xb,
9580 LDL = 0x4,
9581 SDL = 0xc,
9582 LDR = 0x5,
9583 SDR = 0xd,
9584 /* 0x6 is reserved */
9585 LWU = 0xe,
9586 LLD = 0x7,
9587 SCD = 0xf
9590 /* POOL32F encoding of minor opcode field (bits 5..0) */
9592 enum {
9593 /* These are the bit 7..6 values */
9594 ADD_FMT = 0x0,
9595 MOVN_FMT = 0x0,
9597 SUB_FMT = 0x1,
9598 MOVZ_FMT = 0x1,
9600 MUL_FMT = 0x2,
9602 DIV_FMT = 0x3,
9604 /* These are the bit 8..6 values */
9605 RSQRT2_FMT = 0x0,
9606 MOVF_FMT = 0x0,
9608 LWXC1 = 0x1,
9609 MOVT_FMT = 0x1,
9611 PLL_PS = 0x2,
9612 SWXC1 = 0x2,
9614 PLU_PS = 0x3,
9615 LDXC1 = 0x3,
9617 PUL_PS = 0x4,
9618 SDXC1 = 0x4,
9619 RECIP2_FMT = 0x4,
9621 PUU_PS = 0x5,
9622 LUXC1 = 0x5,
9624 CVT_PS_S = 0x6,
9625 SUXC1 = 0x6,
9626 ADDR_PS = 0x6,
9627 PREFX = 0x6,
9629 MULR_PS = 0x7,
9631 MADD_S = 0x01,
9632 MADD_D = 0x09,
9633 MADD_PS = 0x11,
9634 ALNV_PS = 0x19,
9635 MSUB_S = 0x21,
9636 MSUB_D = 0x29,
9637 MSUB_PS = 0x31,
9639 NMADD_S = 0x02,
9640 NMADD_D = 0x0a,
9641 NMADD_PS = 0x12,
9642 NMSUB_S = 0x22,
9643 NMSUB_D = 0x2a,
9644 NMSUB_PS = 0x32,
9646 POOL32FXF = 0x3b,
9648 CABS_COND_FMT = 0x1c, /* MIPS3D */
9649 C_COND_FMT = 0x3c
9652 /* POOL32Fxf encoding of minor opcode extension field */
9654 enum {
9655 CVT_L = 0x04,
9656 RSQRT_FMT = 0x08,
9657 FLOOR_L = 0x0c,
9658 CVT_PW_PS = 0x1c,
9659 CVT_W = 0x24,
9660 SQRT_FMT = 0x28,
9661 FLOOR_W = 0x2c,
9662 CVT_PS_PW = 0x3c,
9663 CFC1 = 0x40,
9664 RECIP_FMT = 0x48,
9665 CEIL_L = 0x4c,
9666 CTC1 = 0x60,
9667 CEIL_W = 0x6c,
9668 MFC1 = 0x80,
9669 CVT_S_PL = 0x84,
9670 TRUNC_L = 0x8c,
9671 MTC1 = 0xa0,
9672 CVT_S_PU = 0xa4,
9673 TRUNC_W = 0xac,
9674 MFHC1 = 0xc0,
9675 ROUND_L = 0xcc,
9676 MTHC1 = 0xe0,
9677 ROUND_W = 0xec,
9679 MOV_FMT = 0x01,
9680 MOVF = 0x05,
9681 ABS_FMT = 0x0d,
9682 RSQRT1_FMT = 0x1d,
9683 MOVT = 0x25,
9684 NEG_FMT = 0x2d,
9685 CVT_D = 0x4d,
9686 RECIP1_FMT = 0x5d,
9687 CVT_S = 0x6d
9690 /* POOL32I encoding of minor opcode field (bits 25..21) */
9692 enum {
9693 BLTZ = 0x00,
9694 BLTZAL = 0x01,
9695 BGEZ = 0x02,
9696 BGEZAL = 0x03,
9697 BLEZ = 0x04,
9698 BNEZC = 0x05,
9699 BGTZ = 0x06,
9700 BEQZC = 0x07,
9701 TLTI = 0x08,
9702 TGEI = 0x09,
9703 TLTIU = 0x0a,
9704 TGEIU = 0x0b,
9705 TNEI = 0x0c,
9706 LUI = 0x0d,
9707 TEQI = 0x0e,
9708 SYNCI = 0x10,
9709 BLTZALS = 0x11,
9710 BGEZALS = 0x13,
9711 BC2F = 0x14,
9712 BC2T = 0x15,
9713 BPOSGE64 = 0x1a,
9714 BPOSGE32 = 0x1b,
9715 /* These overlap and are distinguished by bit16 of the instruction */
9716 BC1F = 0x1c,
9717 BC1T = 0x1d,
9718 BC1ANY2F = 0x1c,
9719 BC1ANY2T = 0x1d,
9720 BC1ANY4F = 0x1e,
9721 BC1ANY4T = 0x1f
9724 /* POOL16A encoding of minor opcode field */
9726 enum {
9727 ADDU16 = 0x0,
9728 SUBU16 = 0x1
9731 /* POOL16B encoding of minor opcode field */
9733 enum {
9734 SLL16 = 0x0,
9735 SRL16 = 0x1
9738 /* POOL16C encoding of minor opcode field */
9740 enum {
9741 NOT16 = 0x00,
9742 XOR16 = 0x04,
9743 AND16 = 0x08,
9744 OR16 = 0x0c,
9745 LWM16 = 0x10,
9746 SWM16 = 0x14,
9747 JR16 = 0x18,
9748 JRC16 = 0x1a,
9749 JALR16 = 0x1c,
9750 JALR16S = 0x1e,
9751 MFHI16 = 0x20,
9752 MFLO16 = 0x24,
9753 BREAK16 = 0x28,
9754 SDBBP16 = 0x2c,
9755 JRADDIUSP = 0x30
9758 /* POOL16D encoding of minor opcode field */
9760 enum {
9761 ADDIUS5 = 0x0,
9762 ADDIUSP = 0x1
9765 /* POOL16E encoding of minor opcode field */
9767 enum {
9768 ADDIUR2 = 0x0,
9769 ADDIUR1SP = 0x1
9772 static int mmreg (int r)
9774 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9776 return map[r];
9779 /* Used for 16-bit store instructions. */
9780 static int mmreg2 (int r)
9782 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
9784 return map[r];
9787 #define uMIPS_RD(op) ((op >> 7) & 0x7)
9788 #define uMIPS_RS(op) ((op >> 4) & 0x7)
9789 #define uMIPS_RS2(op) uMIPS_RS(op)
9790 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
9791 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
9792 #define uMIPS_RS5(op) (op & 0x1f)
9794 /* Signed immediate */
9795 #define SIMM(op, start, width) \
9796 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
9797 << (32-width)) \
9798 >> (32-width))
9799 /* Zero-extended immediate */
9800 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
9802 static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
9804 int rd = mmreg(uMIPS_RD(ctx->opcode));
9806 gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
9809 static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
9811 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
9812 int rd = mmreg(uMIPS_RD(ctx->opcode));
9813 int rs = mmreg(uMIPS_RS(ctx->opcode));
9815 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
9818 static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
9820 int encoded = ZIMM(ctx->opcode, 1, 9);
9821 int decoded;
9823 if (encoded <= 1) {
9824 decoded = 256 + encoded;
9825 } else if (encoded <= 255) {
9826 decoded = encoded;
9827 } else if (encoded <= 509) {
9828 decoded = encoded - 512;
9829 } else {
9830 decoded = encoded - 768;
9833 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
9836 static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
9838 int imm = SIMM(ctx->opcode, 1, 4);
9839 int rd = (ctx->opcode >> 5) & 0x1f;
9841 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
9844 static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
9846 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
9847 31, 32, 63, 64, 255, 32768, 65535 };
9848 int rd = mmreg(uMIPS_RD(ctx->opcode));
9849 int rs = mmreg(uMIPS_RS(ctx->opcode));
9850 int encoded = ZIMM(ctx->opcode, 0, 4);
9852 gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
9855 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
9856 int base, int16_t offset)
9858 TCGv t0, t1;
9859 TCGv_i32 t2;
9861 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9862 generate_exception(ctx, EXCP_RI);
9863 return;
9866 t0 = tcg_temp_new();
9868 gen_base_offset_addr(ctx, t0, base, offset);
9870 t1 = tcg_const_tl(reglist);
9871 t2 = tcg_const_i32(ctx->mem_idx);
9873 save_cpu_state(ctx, 1);
9874 switch (opc) {
9875 case LWM32:
9876 gen_helper_lwm(cpu_env, t0, t1, t2);
9877 break;
9878 case SWM32:
9879 gen_helper_swm(cpu_env, t0, t1, t2);
9880 break;
9881 #ifdef TARGET_MIPS64
9882 case LDM:
9883 gen_helper_ldm(cpu_env, t0, t1, t2);
9884 break;
9885 case SDM:
9886 gen_helper_sdm(cpu_env, t0, t1, t2);
9887 break;
9888 #endif
9890 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
9891 tcg_temp_free(t0);
9892 tcg_temp_free(t1);
9893 tcg_temp_free_i32(t2);
9897 static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
9899 int rd = mmreg((ctx->opcode >> 3) & 0x7);
9900 int rs = mmreg(ctx->opcode & 0x7);
9901 int opc;
9903 switch (((ctx->opcode) >> 4) & 0x3f) {
9904 case NOT16 + 0:
9905 case NOT16 + 1:
9906 case NOT16 + 2:
9907 case NOT16 + 3:
9908 gen_logic(env, OPC_NOR, rd, rs, 0);
9909 break;
9910 case XOR16 + 0:
9911 case XOR16 + 1:
9912 case XOR16 + 2:
9913 case XOR16 + 3:
9914 gen_logic(env, OPC_XOR, rd, rd, rs);
9915 break;
9916 case AND16 + 0:
9917 case AND16 + 1:
9918 case AND16 + 2:
9919 case AND16 + 3:
9920 gen_logic(env, OPC_AND, rd, rd, rs);
9921 break;
9922 case OR16 + 0:
9923 case OR16 + 1:
9924 case OR16 + 2:
9925 case OR16 + 3:
9926 gen_logic(env, OPC_OR, rd, rd, rs);
9927 break;
9928 case LWM16 + 0:
9929 case LWM16 + 1:
9930 case LWM16 + 2:
9931 case LWM16 + 3:
9933 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9934 int offset = ZIMM(ctx->opcode, 0, 4);
9936 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
9937 29, offset << 2);
9939 break;
9940 case SWM16 + 0:
9941 case SWM16 + 1:
9942 case SWM16 + 2:
9943 case SWM16 + 3:
9945 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9946 int offset = ZIMM(ctx->opcode, 0, 4);
9948 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
9949 29, offset << 2);
9951 break;
9952 case JR16 + 0:
9953 case JR16 + 1:
9955 int reg = ctx->opcode & 0x1f;
9957 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9959 *is_branch = 1;
9960 break;
9961 case JRC16 + 0:
9962 case JRC16 + 1:
9964 int reg = ctx->opcode & 0x1f;
9966 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9967 /* Let normal delay slot handling in our caller take us
9968 to the branch target. */
9970 break;
9971 case JALR16 + 0:
9972 case JALR16 + 1:
9973 opc = OPC_JALR;
9974 goto do_jalr;
9975 case JALR16S + 0:
9976 case JALR16S + 1:
9977 opc = OPC_JALRS;
9978 do_jalr:
9980 int reg = ctx->opcode & 0x1f;
9982 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
9984 *is_branch = 1;
9985 break;
9986 case MFHI16 + 0:
9987 case MFHI16 + 1:
9988 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
9989 break;
9990 case MFLO16 + 0:
9991 case MFLO16 + 1:
9992 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
9993 break;
9994 case BREAK16:
9995 generate_exception(ctx, EXCP_BREAK);
9996 break;
9997 case SDBBP16:
9998 /* XXX: not clear which exception should be raised
9999 * when in debug mode...
10001 check_insn(env, ctx, ISA_MIPS32);
10002 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10003 generate_exception(ctx, EXCP_DBp);
10004 } else {
10005 generate_exception(ctx, EXCP_DBp);
10007 break;
10008 case JRADDIUSP + 0:
10009 case JRADDIUSP + 1:
10011 int imm = ZIMM(ctx->opcode, 0, 5);
10013 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
10014 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
10015 /* Let normal delay slot handling in our caller take us
10016 to the branch target. */
10018 break;
10019 default:
10020 generate_exception(ctx, EXCP_RI);
10021 break;
10025 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10027 TCGv t0 = tcg_temp_new();
10028 TCGv t1 = tcg_temp_new();
10030 gen_load_gpr(t0, base);
10032 if (index != 0) {
10033 gen_load_gpr(t1, index);
10034 tcg_gen_shli_tl(t1, t1, 2);
10035 gen_op_addr_add(ctx, t0, t1, t0);
10038 save_cpu_state(ctx, 0);
10039 op_ld_lw(t1, t0, ctx);
10040 gen_store_gpr(t1, rd);
10042 tcg_temp_free(t0);
10043 tcg_temp_free(t1);
10046 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
10047 int base, int16_t offset)
10049 const char *opn = "ldst_pair";
10050 TCGv t0, t1;
10052 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
10053 generate_exception(ctx, EXCP_RI);
10054 return;
10057 t0 = tcg_temp_new();
10058 t1 = tcg_temp_new();
10060 gen_base_offset_addr(ctx, t0, base, offset);
10062 switch (opc) {
10063 case LWP:
10064 if (rd == base) {
10065 generate_exception(ctx, EXCP_RI);
10066 return;
10068 save_cpu_state(ctx, 0);
10069 op_ld_lw(t1, t0, ctx);
10070 gen_store_gpr(t1, rd);
10071 tcg_gen_movi_tl(t1, 4);
10072 gen_op_addr_add(ctx, t0, t0, t1);
10073 op_ld_lw(t1, t0, ctx);
10074 gen_store_gpr(t1, rd+1);
10075 opn = "lwp";
10076 break;
10077 case SWP:
10078 save_cpu_state(ctx, 0);
10079 gen_load_gpr(t1, rd);
10080 op_st_sw(t1, t0, ctx);
10081 tcg_gen_movi_tl(t1, 4);
10082 gen_op_addr_add(ctx, t0, t0, t1);
10083 gen_load_gpr(t1, rd+1);
10084 op_st_sw(t1, t0, ctx);
10085 opn = "swp";
10086 break;
10087 #ifdef TARGET_MIPS64
10088 case LDP:
10089 if (rd == base) {
10090 generate_exception(ctx, EXCP_RI);
10091 return;
10093 save_cpu_state(ctx, 0);
10094 op_ld_ld(t1, t0, ctx);
10095 gen_store_gpr(t1, rd);
10096 tcg_gen_movi_tl(t1, 8);
10097 gen_op_addr_add(ctx, t0, t0, t1);
10098 op_ld_ld(t1, t0, ctx);
10099 gen_store_gpr(t1, rd+1);
10100 opn = "ldp";
10101 break;
10102 case SDP:
10103 save_cpu_state(ctx, 0);
10104 gen_load_gpr(t1, rd);
10105 op_st_sd(t1, t0, ctx);
10106 tcg_gen_movi_tl(t1, 8);
10107 gen_op_addr_add(ctx, t0, t0, t1);
10108 gen_load_gpr(t1, rd+1);
10109 op_st_sd(t1, t0, ctx);
10110 opn = "sdp";
10111 break;
10112 #endif
10114 (void)opn; /* avoid a compiler warning */
10115 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10116 tcg_temp_free(t0);
10117 tcg_temp_free(t1);
10120 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
10121 int *is_branch)
10123 int extension = (ctx->opcode >> 6) & 0x3f;
10124 int minor = (ctx->opcode >> 12) & 0xf;
10125 uint32_t mips32_op;
10127 switch (extension) {
10128 case TEQ:
10129 mips32_op = OPC_TEQ;
10130 goto do_trap;
10131 case TGE:
10132 mips32_op = OPC_TGE;
10133 goto do_trap;
10134 case TGEU:
10135 mips32_op = OPC_TGEU;
10136 goto do_trap;
10137 case TLT:
10138 mips32_op = OPC_TLT;
10139 goto do_trap;
10140 case TLTU:
10141 mips32_op = OPC_TLTU;
10142 goto do_trap;
10143 case TNE:
10144 mips32_op = OPC_TNE;
10145 do_trap:
10146 gen_trap(ctx, mips32_op, rs, rt, -1);
10147 break;
10148 #ifndef CONFIG_USER_ONLY
10149 case MFC0:
10150 case MFC0 + 32:
10151 check_cp0_enabled(ctx);
10152 if (rt == 0) {
10153 /* Treat as NOP. */
10154 break;
10156 gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10157 break;
10158 case MTC0:
10159 case MTC0 + 32:
10160 check_cp0_enabled(ctx);
10162 TCGv t0 = tcg_temp_new();
10164 gen_load_gpr(t0, rt);
10165 gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10166 tcg_temp_free(t0);
10168 break;
10169 #endif
10170 case 0x2c:
10171 switch (minor) {
10172 case SEB:
10173 gen_bshfl(ctx, OPC_SEB, rs, rt);
10174 break;
10175 case SEH:
10176 gen_bshfl(ctx, OPC_SEH, rs, rt);
10177 break;
10178 case CLO:
10179 mips32_op = OPC_CLO;
10180 goto do_cl;
10181 case CLZ:
10182 mips32_op = OPC_CLZ;
10183 do_cl:
10184 check_insn(env, ctx, ISA_MIPS32);
10185 gen_cl(ctx, mips32_op, rt, rs);
10186 break;
10187 case RDHWR:
10188 gen_rdhwr(env, ctx, rt, rs);
10189 break;
10190 case WSBH:
10191 gen_bshfl(ctx, OPC_WSBH, rs, rt);
10192 break;
10193 case MULT:
10194 mips32_op = OPC_MULT;
10195 goto do_muldiv;
10196 case MULTU:
10197 mips32_op = OPC_MULTU;
10198 goto do_muldiv;
10199 case DIV:
10200 mips32_op = OPC_DIV;
10201 goto do_muldiv;
10202 case DIVU:
10203 mips32_op = OPC_DIVU;
10204 goto do_muldiv;
10205 case MADD:
10206 mips32_op = OPC_MADD;
10207 goto do_muldiv;
10208 case MADDU:
10209 mips32_op = OPC_MADDU;
10210 goto do_muldiv;
10211 case MSUB:
10212 mips32_op = OPC_MSUB;
10213 goto do_muldiv;
10214 case MSUBU:
10215 mips32_op = OPC_MSUBU;
10216 do_muldiv:
10217 check_insn(env, ctx, ISA_MIPS32);
10218 gen_muldiv(ctx, mips32_op, rs, rt);
10219 break;
10220 default:
10221 goto pool32axf_invalid;
10223 break;
10224 case 0x34:
10225 switch (minor) {
10226 case MFC2:
10227 case MTC2:
10228 case MFHC2:
10229 case MTHC2:
10230 case CFC2:
10231 case CTC2:
10232 generate_exception_err(ctx, EXCP_CpU, 2);
10233 break;
10234 default:
10235 goto pool32axf_invalid;
10237 break;
10238 case 0x3c:
10239 switch (minor) {
10240 case JALR:
10241 case JALR_HB:
10242 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10243 *is_branch = 1;
10244 break;
10245 case JALRS:
10246 case JALRS_HB:
10247 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10248 *is_branch = 1;
10249 break;
10250 default:
10251 goto pool32axf_invalid;
10253 break;
10254 case 0x05:
10255 switch (minor) {
10256 case RDPGPR:
10257 check_cp0_enabled(ctx);
10258 check_insn(env, ctx, ISA_MIPS32R2);
10259 gen_load_srsgpr(rt, rs);
10260 break;
10261 case WRPGPR:
10262 check_cp0_enabled(ctx);
10263 check_insn(env, ctx, ISA_MIPS32R2);
10264 gen_store_srsgpr(rt, rs);
10265 break;
10266 default:
10267 goto pool32axf_invalid;
10269 break;
10270 #ifndef CONFIG_USER_ONLY
10271 case 0x0d:
10272 switch (minor) {
10273 case TLBP:
10274 mips32_op = OPC_TLBP;
10275 goto do_cp0;
10276 case TLBR:
10277 mips32_op = OPC_TLBR;
10278 goto do_cp0;
10279 case TLBWI:
10280 mips32_op = OPC_TLBWI;
10281 goto do_cp0;
10282 case TLBWR:
10283 mips32_op = OPC_TLBWR;
10284 goto do_cp0;
10285 case WAIT:
10286 mips32_op = OPC_WAIT;
10287 goto do_cp0;
10288 case DERET:
10289 mips32_op = OPC_DERET;
10290 goto do_cp0;
10291 case ERET:
10292 mips32_op = OPC_ERET;
10293 do_cp0:
10294 gen_cp0(env, ctx, mips32_op, rt, rs);
10295 break;
10296 default:
10297 goto pool32axf_invalid;
10299 break;
10300 case 0x1d:
10301 switch (minor) {
10302 case DI:
10303 check_cp0_enabled(ctx);
10305 TCGv t0 = tcg_temp_new();
10307 save_cpu_state(ctx, 1);
10308 gen_helper_di(t0, cpu_env);
10309 gen_store_gpr(t0, rs);
10310 /* Stop translation as we may have switched the execution mode */
10311 ctx->bstate = BS_STOP;
10312 tcg_temp_free(t0);
10314 break;
10315 case EI:
10316 check_cp0_enabled(ctx);
10318 TCGv t0 = tcg_temp_new();
10320 save_cpu_state(ctx, 1);
10321 gen_helper_ei(t0, cpu_env);
10322 gen_store_gpr(t0, rs);
10323 /* Stop translation as we may have switched the execution mode */
10324 ctx->bstate = BS_STOP;
10325 tcg_temp_free(t0);
10327 break;
10328 default:
10329 goto pool32axf_invalid;
10331 break;
10332 #endif
10333 case 0x2d:
10334 switch (minor) {
10335 case SYNC:
10336 /* NOP */
10337 break;
10338 case SYSCALL:
10339 generate_exception(ctx, EXCP_SYSCALL);
10340 ctx->bstate = BS_STOP;
10341 break;
10342 case SDBBP:
10343 check_insn(env, ctx, ISA_MIPS32);
10344 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10345 generate_exception(ctx, EXCP_DBp);
10346 } else {
10347 generate_exception(ctx, EXCP_DBp);
10349 break;
10350 default:
10351 goto pool32axf_invalid;
10353 break;
10354 case 0x35:
10355 switch (minor) {
10356 case MFHI32:
10357 gen_HILO(ctx, OPC_MFHI, rs);
10358 break;
10359 case MFLO32:
10360 gen_HILO(ctx, OPC_MFLO, rs);
10361 break;
10362 case MTHI32:
10363 gen_HILO(ctx, OPC_MTHI, rs);
10364 break;
10365 case MTLO32:
10366 gen_HILO(ctx, OPC_MTLO, rs);
10367 break;
10368 default:
10369 goto pool32axf_invalid;
10371 break;
10372 default:
10373 pool32axf_invalid:
10374 MIPS_INVAL("pool32axf");
10375 generate_exception(ctx, EXCP_RI);
10376 break;
10380 /* Values for microMIPS fmt field. Variable-width, depending on which
10381 formats the instruction supports. */
10383 enum {
10384 FMT_SD_S = 0,
10385 FMT_SD_D = 1,
10387 FMT_SDPS_S = 0,
10388 FMT_SDPS_D = 1,
10389 FMT_SDPS_PS = 2,
10391 FMT_SWL_S = 0,
10392 FMT_SWL_W = 1,
10393 FMT_SWL_L = 2,
10395 FMT_DWL_D = 0,
10396 FMT_DWL_W = 1,
10397 FMT_DWL_L = 2
10400 static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
10402 int extension = (ctx->opcode >> 6) & 0x3ff;
10403 uint32_t mips32_op;
10405 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10406 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10407 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10409 switch (extension) {
10410 case FLOAT_1BIT_FMT(CFC1, 0):
10411 mips32_op = OPC_CFC1;
10412 goto do_cp1;
10413 case FLOAT_1BIT_FMT(CTC1, 0):
10414 mips32_op = OPC_CTC1;
10415 goto do_cp1;
10416 case FLOAT_1BIT_FMT(MFC1, 0):
10417 mips32_op = OPC_MFC1;
10418 goto do_cp1;
10419 case FLOAT_1BIT_FMT(MTC1, 0):
10420 mips32_op = OPC_MTC1;
10421 goto do_cp1;
10422 case FLOAT_1BIT_FMT(MFHC1, 0):
10423 mips32_op = OPC_MFHC1;
10424 goto do_cp1;
10425 case FLOAT_1BIT_FMT(MTHC1, 0):
10426 mips32_op = OPC_MTHC1;
10427 do_cp1:
10428 gen_cp1(ctx, mips32_op, rt, rs);
10429 break;
10431 /* Reciprocal square root */
10432 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10433 mips32_op = OPC_RSQRT_S;
10434 goto do_unaryfp;
10435 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10436 mips32_op = OPC_RSQRT_D;
10437 goto do_unaryfp;
10439 /* Square root */
10440 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10441 mips32_op = OPC_SQRT_S;
10442 goto do_unaryfp;
10443 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10444 mips32_op = OPC_SQRT_D;
10445 goto do_unaryfp;
10447 /* Reciprocal */
10448 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10449 mips32_op = OPC_RECIP_S;
10450 goto do_unaryfp;
10451 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10452 mips32_op = OPC_RECIP_D;
10453 goto do_unaryfp;
10455 /* Floor */
10456 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10457 mips32_op = OPC_FLOOR_L_S;
10458 goto do_unaryfp;
10459 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10460 mips32_op = OPC_FLOOR_L_D;
10461 goto do_unaryfp;
10462 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10463 mips32_op = OPC_FLOOR_W_S;
10464 goto do_unaryfp;
10465 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10466 mips32_op = OPC_FLOOR_W_D;
10467 goto do_unaryfp;
10469 /* Ceiling */
10470 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10471 mips32_op = OPC_CEIL_L_S;
10472 goto do_unaryfp;
10473 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10474 mips32_op = OPC_CEIL_L_D;
10475 goto do_unaryfp;
10476 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10477 mips32_op = OPC_CEIL_W_S;
10478 goto do_unaryfp;
10479 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10480 mips32_op = OPC_CEIL_W_D;
10481 goto do_unaryfp;
10483 /* Truncation */
10484 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10485 mips32_op = OPC_TRUNC_L_S;
10486 goto do_unaryfp;
10487 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10488 mips32_op = OPC_TRUNC_L_D;
10489 goto do_unaryfp;
10490 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10491 mips32_op = OPC_TRUNC_W_S;
10492 goto do_unaryfp;
10493 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10494 mips32_op = OPC_TRUNC_W_D;
10495 goto do_unaryfp;
10497 /* Round */
10498 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10499 mips32_op = OPC_ROUND_L_S;
10500 goto do_unaryfp;
10501 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10502 mips32_op = OPC_ROUND_L_D;
10503 goto do_unaryfp;
10504 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10505 mips32_op = OPC_ROUND_W_S;
10506 goto do_unaryfp;
10507 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10508 mips32_op = OPC_ROUND_W_D;
10509 goto do_unaryfp;
10511 /* Integer to floating-point conversion */
10512 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10513 mips32_op = OPC_CVT_L_S;
10514 goto do_unaryfp;
10515 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10516 mips32_op = OPC_CVT_L_D;
10517 goto do_unaryfp;
10518 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10519 mips32_op = OPC_CVT_W_S;
10520 goto do_unaryfp;
10521 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10522 mips32_op = OPC_CVT_W_D;
10523 goto do_unaryfp;
10525 /* Paired-foo conversions */
10526 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10527 mips32_op = OPC_CVT_S_PL;
10528 goto do_unaryfp;
10529 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10530 mips32_op = OPC_CVT_S_PU;
10531 goto do_unaryfp;
10532 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10533 mips32_op = OPC_CVT_PW_PS;
10534 goto do_unaryfp;
10535 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10536 mips32_op = OPC_CVT_PS_PW;
10537 goto do_unaryfp;
10539 /* Floating-point moves */
10540 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10541 mips32_op = OPC_MOV_S;
10542 goto do_unaryfp;
10543 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10544 mips32_op = OPC_MOV_D;
10545 goto do_unaryfp;
10546 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10547 mips32_op = OPC_MOV_PS;
10548 goto do_unaryfp;
10550 /* Absolute value */
10551 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10552 mips32_op = OPC_ABS_S;
10553 goto do_unaryfp;
10554 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10555 mips32_op = OPC_ABS_D;
10556 goto do_unaryfp;
10557 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10558 mips32_op = OPC_ABS_PS;
10559 goto do_unaryfp;
10561 /* Negation */
10562 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10563 mips32_op = OPC_NEG_S;
10564 goto do_unaryfp;
10565 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10566 mips32_op = OPC_NEG_D;
10567 goto do_unaryfp;
10568 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10569 mips32_op = OPC_NEG_PS;
10570 goto do_unaryfp;
10572 /* Reciprocal square root step */
10573 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10574 mips32_op = OPC_RSQRT1_S;
10575 goto do_unaryfp;
10576 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10577 mips32_op = OPC_RSQRT1_D;
10578 goto do_unaryfp;
10579 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10580 mips32_op = OPC_RSQRT1_PS;
10581 goto do_unaryfp;
10583 /* Reciprocal step */
10584 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10585 mips32_op = OPC_RECIP1_S;
10586 goto do_unaryfp;
10587 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10588 mips32_op = OPC_RECIP1_S;
10589 goto do_unaryfp;
10590 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10591 mips32_op = OPC_RECIP1_PS;
10592 goto do_unaryfp;
10594 /* Conversions from double */
10595 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10596 mips32_op = OPC_CVT_D_S;
10597 goto do_unaryfp;
10598 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10599 mips32_op = OPC_CVT_D_W;
10600 goto do_unaryfp;
10601 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10602 mips32_op = OPC_CVT_D_L;
10603 goto do_unaryfp;
10605 /* Conversions from single */
10606 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10607 mips32_op = OPC_CVT_S_D;
10608 goto do_unaryfp;
10609 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10610 mips32_op = OPC_CVT_S_W;
10611 goto do_unaryfp;
10612 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10613 mips32_op = OPC_CVT_S_L;
10614 do_unaryfp:
10615 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10616 break;
10618 /* Conditional moves on floating-point codes */
10619 case COND_FLOAT_MOV(MOVT, 0):
10620 case COND_FLOAT_MOV(MOVT, 1):
10621 case COND_FLOAT_MOV(MOVT, 2):
10622 case COND_FLOAT_MOV(MOVT, 3):
10623 case COND_FLOAT_MOV(MOVT, 4):
10624 case COND_FLOAT_MOV(MOVT, 5):
10625 case COND_FLOAT_MOV(MOVT, 6):
10626 case COND_FLOAT_MOV(MOVT, 7):
10627 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
10628 break;
10629 case COND_FLOAT_MOV(MOVF, 0):
10630 case COND_FLOAT_MOV(MOVF, 1):
10631 case COND_FLOAT_MOV(MOVF, 2):
10632 case COND_FLOAT_MOV(MOVF, 3):
10633 case COND_FLOAT_MOV(MOVF, 4):
10634 case COND_FLOAT_MOV(MOVF, 5):
10635 case COND_FLOAT_MOV(MOVF, 6):
10636 case COND_FLOAT_MOV(MOVF, 7):
10637 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
10638 break;
10639 default:
10640 MIPS_INVAL("pool32fxf");
10641 generate_exception(ctx, EXCP_RI);
10642 break;
10646 static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
10647 uint16_t insn_hw1, int *is_branch)
10649 int32_t offset;
10650 uint16_t insn;
10651 int rt, rs, rd, rr;
10652 int16_t imm;
10653 uint32_t op, minor, mips32_op;
10654 uint32_t cond, fmt, cc;
10656 insn = cpu_lduw_code(env, ctx->pc + 2);
10657 ctx->opcode = (ctx->opcode << 16) | insn;
10659 rt = (ctx->opcode >> 21) & 0x1f;
10660 rs = (ctx->opcode >> 16) & 0x1f;
10661 rd = (ctx->opcode >> 11) & 0x1f;
10662 rr = (ctx->opcode >> 6) & 0x1f;
10663 imm = (int16_t) ctx->opcode;
10665 op = (ctx->opcode >> 26) & 0x3f;
10666 switch (op) {
10667 case POOL32A:
10668 minor = ctx->opcode & 0x3f;
10669 switch (minor) {
10670 case 0x00:
10671 minor = (ctx->opcode >> 6) & 0xf;
10672 switch (minor) {
10673 case SLL32:
10674 mips32_op = OPC_SLL;
10675 goto do_shifti;
10676 case SRA:
10677 mips32_op = OPC_SRA;
10678 goto do_shifti;
10679 case SRL32:
10680 mips32_op = OPC_SRL;
10681 goto do_shifti;
10682 case ROTR:
10683 mips32_op = OPC_ROTR;
10684 do_shifti:
10685 gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
10686 break;
10687 default:
10688 goto pool32a_invalid;
10690 break;
10691 case 0x10:
10692 minor = (ctx->opcode >> 6) & 0xf;
10693 switch (minor) {
10694 /* Arithmetic */
10695 case ADD:
10696 mips32_op = OPC_ADD;
10697 goto do_arith;
10698 case ADDU32:
10699 mips32_op = OPC_ADDU;
10700 goto do_arith;
10701 case SUB:
10702 mips32_op = OPC_SUB;
10703 goto do_arith;
10704 case SUBU32:
10705 mips32_op = OPC_SUBU;
10706 goto do_arith;
10707 case MUL:
10708 mips32_op = OPC_MUL;
10709 do_arith:
10710 gen_arith(env, ctx, mips32_op, rd, rs, rt);
10711 break;
10712 /* Shifts */
10713 case SLLV:
10714 mips32_op = OPC_SLLV;
10715 goto do_shift;
10716 case SRLV:
10717 mips32_op = OPC_SRLV;
10718 goto do_shift;
10719 case SRAV:
10720 mips32_op = OPC_SRAV;
10721 goto do_shift;
10722 case ROTRV:
10723 mips32_op = OPC_ROTRV;
10724 do_shift:
10725 gen_shift(env, ctx, mips32_op, rd, rs, rt);
10726 break;
10727 /* Logical operations */
10728 case AND:
10729 mips32_op = OPC_AND;
10730 goto do_logic;
10731 case OR32:
10732 mips32_op = OPC_OR;
10733 goto do_logic;
10734 case NOR:
10735 mips32_op = OPC_NOR;
10736 goto do_logic;
10737 case XOR32:
10738 mips32_op = OPC_XOR;
10739 do_logic:
10740 gen_logic(env, mips32_op, rd, rs, rt);
10741 break;
10742 /* Set less than */
10743 case SLT:
10744 mips32_op = OPC_SLT;
10745 goto do_slt;
10746 case SLTU:
10747 mips32_op = OPC_SLTU;
10748 do_slt:
10749 gen_slt(env, mips32_op, rd, rs, rt);
10750 break;
10751 default:
10752 goto pool32a_invalid;
10754 break;
10755 case 0x18:
10756 minor = (ctx->opcode >> 6) & 0xf;
10757 switch (minor) {
10758 /* Conditional moves */
10759 case MOVN:
10760 mips32_op = OPC_MOVN;
10761 goto do_cmov;
10762 case MOVZ:
10763 mips32_op = OPC_MOVZ;
10764 do_cmov:
10765 gen_cond_move(env, mips32_op, rd, rs, rt);
10766 break;
10767 case LWXS:
10768 gen_ldxs(ctx, rs, rt, rd);
10769 break;
10770 default:
10771 goto pool32a_invalid;
10773 break;
10774 case INS:
10775 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
10776 return;
10777 case EXT:
10778 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
10779 return;
10780 case POOL32AXF:
10781 gen_pool32axf(env, ctx, rt, rs, is_branch);
10782 break;
10783 case 0x07:
10784 generate_exception(ctx, EXCP_BREAK);
10785 break;
10786 default:
10787 pool32a_invalid:
10788 MIPS_INVAL("pool32a");
10789 generate_exception(ctx, EXCP_RI);
10790 break;
10792 break;
10793 case POOL32B:
10794 minor = (ctx->opcode >> 12) & 0xf;
10795 switch (minor) {
10796 case CACHE:
10797 check_cp0_enabled(ctx);
10798 /* Treat as no-op. */
10799 break;
10800 case LWC2:
10801 case SWC2:
10802 /* COP2: Not implemented. */
10803 generate_exception_err(ctx, EXCP_CpU, 2);
10804 break;
10805 case LWP:
10806 case SWP:
10807 #ifdef TARGET_MIPS64
10808 case LDP:
10809 case SDP:
10810 #endif
10811 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10812 break;
10813 case LWM32:
10814 case SWM32:
10815 #ifdef TARGET_MIPS64
10816 case LDM:
10817 case SDM:
10818 #endif
10819 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10820 break;
10821 default:
10822 MIPS_INVAL("pool32b");
10823 generate_exception(ctx, EXCP_RI);
10824 break;
10826 break;
10827 case POOL32F:
10828 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
10829 minor = ctx->opcode & 0x3f;
10830 check_cp1_enabled(ctx);
10831 switch (minor) {
10832 case ALNV_PS:
10833 mips32_op = OPC_ALNV_PS;
10834 goto do_madd;
10835 case MADD_S:
10836 mips32_op = OPC_MADD_S;
10837 goto do_madd;
10838 case MADD_D:
10839 mips32_op = OPC_MADD_D;
10840 goto do_madd;
10841 case MADD_PS:
10842 mips32_op = OPC_MADD_PS;
10843 goto do_madd;
10844 case MSUB_S:
10845 mips32_op = OPC_MSUB_S;
10846 goto do_madd;
10847 case MSUB_D:
10848 mips32_op = OPC_MSUB_D;
10849 goto do_madd;
10850 case MSUB_PS:
10851 mips32_op = OPC_MSUB_PS;
10852 goto do_madd;
10853 case NMADD_S:
10854 mips32_op = OPC_NMADD_S;
10855 goto do_madd;
10856 case NMADD_D:
10857 mips32_op = OPC_NMADD_D;
10858 goto do_madd;
10859 case NMADD_PS:
10860 mips32_op = OPC_NMADD_PS;
10861 goto do_madd;
10862 case NMSUB_S:
10863 mips32_op = OPC_NMSUB_S;
10864 goto do_madd;
10865 case NMSUB_D:
10866 mips32_op = OPC_NMSUB_D;
10867 goto do_madd;
10868 case NMSUB_PS:
10869 mips32_op = OPC_NMSUB_PS;
10870 do_madd:
10871 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
10872 break;
10873 case CABS_COND_FMT:
10874 cond = (ctx->opcode >> 6) & 0xf;
10875 cc = (ctx->opcode >> 13) & 0x7;
10876 fmt = (ctx->opcode >> 10) & 0x3;
10877 switch (fmt) {
10878 case 0x0:
10879 gen_cmpabs_s(ctx, cond, rt, rs, cc);
10880 break;
10881 case 0x1:
10882 gen_cmpabs_d(ctx, cond, rt, rs, cc);
10883 break;
10884 case 0x2:
10885 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
10886 break;
10887 default:
10888 goto pool32f_invalid;
10890 break;
10891 case C_COND_FMT:
10892 cond = (ctx->opcode >> 6) & 0xf;
10893 cc = (ctx->opcode >> 13) & 0x7;
10894 fmt = (ctx->opcode >> 10) & 0x3;
10895 switch (fmt) {
10896 case 0x0:
10897 gen_cmp_s(ctx, cond, rt, rs, cc);
10898 break;
10899 case 0x1:
10900 gen_cmp_d(ctx, cond, rt, rs, cc);
10901 break;
10902 case 0x2:
10903 gen_cmp_ps(ctx, cond, rt, rs, cc);
10904 break;
10905 default:
10906 goto pool32f_invalid;
10908 break;
10909 case POOL32FXF:
10910 gen_pool32fxf(env, ctx, rt, rs);
10911 break;
10912 case 0x00:
10913 /* PLL foo */
10914 switch ((ctx->opcode >> 6) & 0x7) {
10915 case PLL_PS:
10916 mips32_op = OPC_PLL_PS;
10917 goto do_ps;
10918 case PLU_PS:
10919 mips32_op = OPC_PLU_PS;
10920 goto do_ps;
10921 case PUL_PS:
10922 mips32_op = OPC_PUL_PS;
10923 goto do_ps;
10924 case PUU_PS:
10925 mips32_op = OPC_PUU_PS;
10926 goto do_ps;
10927 case CVT_PS_S:
10928 mips32_op = OPC_CVT_PS_S;
10929 do_ps:
10930 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10931 break;
10932 default:
10933 goto pool32f_invalid;
10935 break;
10936 case 0x08:
10937 /* [LS][WDU]XC1 */
10938 switch ((ctx->opcode >> 6) & 0x7) {
10939 case LWXC1:
10940 mips32_op = OPC_LWXC1;
10941 goto do_ldst_cp1;
10942 case SWXC1:
10943 mips32_op = OPC_SWXC1;
10944 goto do_ldst_cp1;
10945 case LDXC1:
10946 mips32_op = OPC_LDXC1;
10947 goto do_ldst_cp1;
10948 case SDXC1:
10949 mips32_op = OPC_SDXC1;
10950 goto do_ldst_cp1;
10951 case LUXC1:
10952 mips32_op = OPC_LUXC1;
10953 goto do_ldst_cp1;
10954 case SUXC1:
10955 mips32_op = OPC_SUXC1;
10956 do_ldst_cp1:
10957 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
10958 break;
10959 default:
10960 goto pool32f_invalid;
10962 break;
10963 case 0x18:
10964 /* 3D insns */
10965 fmt = (ctx->opcode >> 9) & 0x3;
10966 switch ((ctx->opcode >> 6) & 0x7) {
10967 case RSQRT2_FMT:
10968 switch (fmt) {
10969 case FMT_SDPS_S:
10970 mips32_op = OPC_RSQRT2_S;
10971 goto do_3d;
10972 case FMT_SDPS_D:
10973 mips32_op = OPC_RSQRT2_D;
10974 goto do_3d;
10975 case FMT_SDPS_PS:
10976 mips32_op = OPC_RSQRT2_PS;
10977 goto do_3d;
10978 default:
10979 goto pool32f_invalid;
10981 break;
10982 case RECIP2_FMT:
10983 switch (fmt) {
10984 case FMT_SDPS_S:
10985 mips32_op = OPC_RECIP2_S;
10986 goto do_3d;
10987 case FMT_SDPS_D:
10988 mips32_op = OPC_RECIP2_D;
10989 goto do_3d;
10990 case FMT_SDPS_PS:
10991 mips32_op = OPC_RECIP2_PS;
10992 goto do_3d;
10993 default:
10994 goto pool32f_invalid;
10996 break;
10997 case ADDR_PS:
10998 mips32_op = OPC_ADDR_PS;
10999 goto do_3d;
11000 case MULR_PS:
11001 mips32_op = OPC_MULR_PS;
11002 do_3d:
11003 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11004 break;
11005 default:
11006 goto pool32f_invalid;
11008 break;
11009 case 0x20:
11010 /* MOV[FT].fmt and PREFX */
11011 cc = (ctx->opcode >> 13) & 0x7;
11012 fmt = (ctx->opcode >> 9) & 0x3;
11013 switch ((ctx->opcode >> 6) & 0x7) {
11014 case MOVF_FMT:
11015 switch (fmt) {
11016 case FMT_SDPS_S:
11017 gen_movcf_s(rs, rt, cc, 0);
11018 break;
11019 case FMT_SDPS_D:
11020 gen_movcf_d(ctx, rs, rt, cc, 0);
11021 break;
11022 case FMT_SDPS_PS:
11023 gen_movcf_ps(rs, rt, cc, 0);
11024 break;
11025 default:
11026 goto pool32f_invalid;
11028 break;
11029 case MOVT_FMT:
11030 switch (fmt) {
11031 case FMT_SDPS_S:
11032 gen_movcf_s(rs, rt, cc, 1);
11033 break;
11034 case FMT_SDPS_D:
11035 gen_movcf_d(ctx, rs, rt, cc, 1);
11036 break;
11037 case FMT_SDPS_PS:
11038 gen_movcf_ps(rs, rt, cc, 1);
11039 break;
11040 default:
11041 goto pool32f_invalid;
11043 break;
11044 case PREFX:
11045 break;
11046 default:
11047 goto pool32f_invalid;
11049 break;
11050 #define FINSN_3ARG_SDPS(prfx) \
11051 switch ((ctx->opcode >> 8) & 0x3) { \
11052 case FMT_SDPS_S: \
11053 mips32_op = OPC_##prfx##_S; \
11054 goto do_fpop; \
11055 case FMT_SDPS_D: \
11056 mips32_op = OPC_##prfx##_D; \
11057 goto do_fpop; \
11058 case FMT_SDPS_PS: \
11059 mips32_op = OPC_##prfx##_PS; \
11060 goto do_fpop; \
11061 default: \
11062 goto pool32f_invalid; \
11064 case 0x30:
11065 /* regular FP ops */
11066 switch ((ctx->opcode >> 6) & 0x3) {
11067 case ADD_FMT:
11068 FINSN_3ARG_SDPS(ADD);
11069 break;
11070 case SUB_FMT:
11071 FINSN_3ARG_SDPS(SUB);
11072 break;
11073 case MUL_FMT:
11074 FINSN_3ARG_SDPS(MUL);
11075 break;
11076 case DIV_FMT:
11077 fmt = (ctx->opcode >> 8) & 0x3;
11078 if (fmt == 1) {
11079 mips32_op = OPC_DIV_D;
11080 } else if (fmt == 0) {
11081 mips32_op = OPC_DIV_S;
11082 } else {
11083 goto pool32f_invalid;
11085 goto do_fpop;
11086 default:
11087 goto pool32f_invalid;
11089 break;
11090 case 0x38:
11091 /* cmovs */
11092 switch ((ctx->opcode >> 6) & 0x3) {
11093 case MOVN_FMT:
11094 FINSN_3ARG_SDPS(MOVN);
11095 break;
11096 case MOVZ_FMT:
11097 FINSN_3ARG_SDPS(MOVZ);
11098 break;
11099 default:
11100 goto pool32f_invalid;
11102 break;
11103 do_fpop:
11104 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11105 break;
11106 default:
11107 pool32f_invalid:
11108 MIPS_INVAL("pool32f");
11109 generate_exception(ctx, EXCP_RI);
11110 break;
11112 } else {
11113 generate_exception_err(ctx, EXCP_CpU, 1);
11115 break;
11116 case POOL32I:
11117 minor = (ctx->opcode >> 21) & 0x1f;
11118 switch (minor) {
11119 case BLTZ:
11120 mips32_op = OPC_BLTZ;
11121 goto do_branch;
11122 case BLTZAL:
11123 mips32_op = OPC_BLTZAL;
11124 goto do_branch;
11125 case BLTZALS:
11126 mips32_op = OPC_BLTZALS;
11127 goto do_branch;
11128 case BGEZ:
11129 mips32_op = OPC_BGEZ;
11130 goto do_branch;
11131 case BGEZAL:
11132 mips32_op = OPC_BGEZAL;
11133 goto do_branch;
11134 case BGEZALS:
11135 mips32_op = OPC_BGEZALS;
11136 goto do_branch;
11137 case BLEZ:
11138 mips32_op = OPC_BLEZ;
11139 goto do_branch;
11140 case BGTZ:
11141 mips32_op = OPC_BGTZ;
11142 do_branch:
11143 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11144 *is_branch = 1;
11145 break;
11147 /* Traps */
11148 case TLTI:
11149 mips32_op = OPC_TLTI;
11150 goto do_trapi;
11151 case TGEI:
11152 mips32_op = OPC_TGEI;
11153 goto do_trapi;
11154 case TLTIU:
11155 mips32_op = OPC_TLTIU;
11156 goto do_trapi;
11157 case TGEIU:
11158 mips32_op = OPC_TGEIU;
11159 goto do_trapi;
11160 case TNEI:
11161 mips32_op = OPC_TNEI;
11162 goto do_trapi;
11163 case TEQI:
11164 mips32_op = OPC_TEQI;
11165 do_trapi:
11166 gen_trap(ctx, mips32_op, rs, -1, imm);
11167 break;
11169 case BNEZC:
11170 case BEQZC:
11171 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11172 4, rs, 0, imm << 1);
11173 /* Compact branches don't have a delay slot, so just let
11174 the normal delay slot handling take us to the branch
11175 target. */
11176 break;
11177 case LUI:
11178 gen_logic_imm(env, OPC_LUI, rs, -1, imm);
11179 break;
11180 case SYNCI:
11181 break;
11182 case BC2F:
11183 case BC2T:
11184 /* COP2: Not implemented. */
11185 generate_exception_err(ctx, EXCP_CpU, 2);
11186 break;
11187 case BC1F:
11188 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11189 goto do_cp1branch;
11190 case BC1T:
11191 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11192 goto do_cp1branch;
11193 case BC1ANY4F:
11194 mips32_op = OPC_BC1FANY4;
11195 goto do_cp1mips3d;
11196 case BC1ANY4T:
11197 mips32_op = OPC_BC1TANY4;
11198 do_cp1mips3d:
11199 check_cop1x(ctx);
11200 check_insn(env, ctx, ASE_MIPS3D);
11201 /* Fall through */
11202 do_cp1branch:
11203 gen_compute_branch1(env, ctx, mips32_op,
11204 (ctx->opcode >> 18) & 0x7, imm << 1);
11205 *is_branch = 1;
11206 break;
11207 case BPOSGE64:
11208 case BPOSGE32:
11209 /* MIPS DSP: not implemented */
11210 /* Fall through */
11211 default:
11212 MIPS_INVAL("pool32i");
11213 generate_exception(ctx, EXCP_RI);
11214 break;
11216 break;
11217 case POOL32C:
11218 minor = (ctx->opcode >> 12) & 0xf;
11219 switch (minor) {
11220 case LWL:
11221 mips32_op = OPC_LWL;
11222 goto do_ld_lr;
11223 case SWL:
11224 mips32_op = OPC_SWL;
11225 goto do_st_lr;
11226 case LWR:
11227 mips32_op = OPC_LWR;
11228 goto do_ld_lr;
11229 case SWR:
11230 mips32_op = OPC_SWR;
11231 goto do_st_lr;
11232 #if defined(TARGET_MIPS64)
11233 case LDL:
11234 mips32_op = OPC_LDL;
11235 goto do_ld_lr;
11236 case SDL:
11237 mips32_op = OPC_SDL;
11238 goto do_st_lr;
11239 case LDR:
11240 mips32_op = OPC_LDR;
11241 goto do_ld_lr;
11242 case SDR:
11243 mips32_op = OPC_SDR;
11244 goto do_st_lr;
11245 case LWU:
11246 mips32_op = OPC_LWU;
11247 goto do_ld_lr;
11248 case LLD:
11249 mips32_op = OPC_LLD;
11250 goto do_ld_lr;
11251 #endif
11252 case LL:
11253 mips32_op = OPC_LL;
11254 goto do_ld_lr;
11255 do_ld_lr:
11256 gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11257 break;
11258 do_st_lr:
11259 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11260 break;
11261 case SC:
11262 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11263 break;
11264 #if defined(TARGET_MIPS64)
11265 case SCD:
11266 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11267 break;
11268 #endif
11269 case PREF:
11270 /* Treat as no-op */
11271 break;
11272 default:
11273 MIPS_INVAL("pool32c");
11274 generate_exception(ctx, EXCP_RI);
11275 break;
11277 break;
11278 case ADDI32:
11279 mips32_op = OPC_ADDI;
11280 goto do_addi;
11281 case ADDIU32:
11282 mips32_op = OPC_ADDIU;
11283 do_addi:
11284 gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11285 break;
11287 /* Logical operations */
11288 case ORI32:
11289 mips32_op = OPC_ORI;
11290 goto do_logici;
11291 case XORI32:
11292 mips32_op = OPC_XORI;
11293 goto do_logici;
11294 case ANDI32:
11295 mips32_op = OPC_ANDI;
11296 do_logici:
11297 gen_logic_imm(env, mips32_op, rt, rs, imm);
11298 break;
11300 /* Set less than immediate */
11301 case SLTI32:
11302 mips32_op = OPC_SLTI;
11303 goto do_slti;
11304 case SLTIU32:
11305 mips32_op = OPC_SLTIU;
11306 do_slti:
11307 gen_slt_imm(env, mips32_op, rt, rs, imm);
11308 break;
11309 case JALX32:
11310 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11311 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11312 *is_branch = 1;
11313 break;
11314 case JALS32:
11315 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11316 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11317 *is_branch = 1;
11318 break;
11319 case BEQ32:
11320 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11321 *is_branch = 1;
11322 break;
11323 case BNE32:
11324 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11325 *is_branch = 1;
11326 break;
11327 case J32:
11328 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11329 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11330 *is_branch = 1;
11331 break;
11332 case JAL32:
11333 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11334 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11335 *is_branch = 1;
11336 break;
11337 /* Floating point (COP1) */
11338 case LWC132:
11339 mips32_op = OPC_LWC1;
11340 goto do_cop1;
11341 case LDC132:
11342 mips32_op = OPC_LDC1;
11343 goto do_cop1;
11344 case SWC132:
11345 mips32_op = OPC_SWC1;
11346 goto do_cop1;
11347 case SDC132:
11348 mips32_op = OPC_SDC1;
11349 do_cop1:
11350 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11351 break;
11352 case ADDIUPC:
11354 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11355 int offset = SIMM(ctx->opcode, 0, 23) << 2;
11357 gen_addiupc(ctx, reg, offset, 0, 0);
11359 break;
11360 /* Loads and stores */
11361 case LB32:
11362 mips32_op = OPC_LB;
11363 goto do_ld;
11364 case LBU32:
11365 mips32_op = OPC_LBU;
11366 goto do_ld;
11367 case LH32:
11368 mips32_op = OPC_LH;
11369 goto do_ld;
11370 case LHU32:
11371 mips32_op = OPC_LHU;
11372 goto do_ld;
11373 case LW32:
11374 mips32_op = OPC_LW;
11375 goto do_ld;
11376 #ifdef TARGET_MIPS64
11377 case LD32:
11378 mips32_op = OPC_LD;
11379 goto do_ld;
11380 case SD32:
11381 mips32_op = OPC_SD;
11382 goto do_st;
11383 #endif
11384 case SB32:
11385 mips32_op = OPC_SB;
11386 goto do_st;
11387 case SH32:
11388 mips32_op = OPC_SH;
11389 goto do_st;
11390 case SW32:
11391 mips32_op = OPC_SW;
11392 goto do_st;
11393 do_ld:
11394 gen_ld(env, ctx, mips32_op, rt, rs, imm);
11395 break;
11396 do_st:
11397 gen_st(ctx, mips32_op, rt, rs, imm);
11398 break;
11399 default:
11400 generate_exception(ctx, EXCP_RI);
11401 break;
11405 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
11407 uint32_t op;
11409 /* make sure instructions are on a halfword boundary */
11410 if (ctx->pc & 0x1) {
11411 env->CP0_BadVAddr = ctx->pc;
11412 generate_exception(ctx, EXCP_AdEL);
11413 ctx->bstate = BS_STOP;
11414 return 2;
11417 op = (ctx->opcode >> 10) & 0x3f;
11418 /* Enforce properly-sized instructions in a delay slot */
11419 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11420 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11422 switch (op) {
11423 case POOL32A:
11424 case POOL32B:
11425 case POOL32I:
11426 case POOL32C:
11427 case ADDI32:
11428 case ADDIU32:
11429 case ORI32:
11430 case XORI32:
11431 case SLTI32:
11432 case SLTIU32:
11433 case ANDI32:
11434 case JALX32:
11435 case LBU32:
11436 case LHU32:
11437 case POOL32F:
11438 case JALS32:
11439 case BEQ32:
11440 case BNE32:
11441 case J32:
11442 case JAL32:
11443 case SB32:
11444 case SH32:
11445 case POOL32S:
11446 case ADDIUPC:
11447 case SWC132:
11448 case SDC132:
11449 case SD32:
11450 case SW32:
11451 case LB32:
11452 case LH32:
11453 case DADDIU32:
11454 case POOL48A: /* ??? */
11455 case LWC132:
11456 case LDC132:
11457 case LD32:
11458 case LW32:
11459 if (bits & MIPS_HFLAG_BDS16) {
11460 generate_exception(ctx, EXCP_RI);
11461 /* Just stop translation; the user is confused. */
11462 ctx->bstate = BS_STOP;
11463 return 2;
11465 break;
11466 case POOL16A:
11467 case POOL16B:
11468 case POOL16C:
11469 case LWGP16:
11470 case POOL16F:
11471 case LBU16:
11472 case LHU16:
11473 case LWSP16:
11474 case LW16:
11475 case SB16:
11476 case SH16:
11477 case SWSP16:
11478 case SW16:
11479 case MOVE16:
11480 case ANDI16:
11481 case POOL16D:
11482 case POOL16E:
11483 case BEQZ16:
11484 case BNEZ16:
11485 case B16:
11486 case LI16:
11487 if (bits & MIPS_HFLAG_BDS32) {
11488 generate_exception(ctx, EXCP_RI);
11489 /* Just stop translation; the user is confused. */
11490 ctx->bstate = BS_STOP;
11491 return 2;
11493 break;
11494 default:
11495 break;
11498 switch (op) {
11499 case POOL16A:
11501 int rd = mmreg(uMIPS_RD(ctx->opcode));
11502 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11503 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11504 uint32_t opc = 0;
11506 switch (ctx->opcode & 0x1) {
11507 case ADDU16:
11508 opc = OPC_ADDU;
11509 break;
11510 case SUBU16:
11511 opc = OPC_SUBU;
11512 break;
11515 gen_arith(env, ctx, opc, rd, rs1, rs2);
11517 break;
11518 case POOL16B:
11520 int rd = mmreg(uMIPS_RD(ctx->opcode));
11521 int rs = mmreg(uMIPS_RS(ctx->opcode));
11522 int amount = (ctx->opcode >> 1) & 0x7;
11523 uint32_t opc = 0;
11524 amount = amount == 0 ? 8 : amount;
11526 switch (ctx->opcode & 0x1) {
11527 case SLL16:
11528 opc = OPC_SLL;
11529 break;
11530 case SRL16:
11531 opc = OPC_SRL;
11532 break;
11535 gen_shift_imm(env, ctx, opc, rd, rs, amount);
11537 break;
11538 case POOL16C:
11539 gen_pool16c_insn(env, ctx, is_branch);
11540 break;
11541 case LWGP16:
11543 int rd = mmreg(uMIPS_RD(ctx->opcode));
11544 int rb = 28; /* GP */
11545 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11547 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11549 break;
11550 case POOL16F:
11551 if (ctx->opcode & 1) {
11552 generate_exception(ctx, EXCP_RI);
11553 } else {
11554 /* MOVEP */
11555 int enc_dest = uMIPS_RD(ctx->opcode);
11556 int enc_rt = uMIPS_RS2(ctx->opcode);
11557 int enc_rs = uMIPS_RS1(ctx->opcode);
11558 int rd, rs, re, rt;
11559 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11560 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11561 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11563 rd = rd_enc[enc_dest];
11564 re = re_enc[enc_dest];
11565 rs = rs_rt_enc[enc_rs];
11566 rt = rs_rt_enc[enc_rt];
11568 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11569 gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11571 break;
11572 case LBU16:
11574 int rd = mmreg(uMIPS_RD(ctx->opcode));
11575 int rb = mmreg(uMIPS_RS(ctx->opcode));
11576 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11577 offset = (offset == 0xf ? -1 : offset);
11579 gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
11581 break;
11582 case LHU16:
11584 int rd = mmreg(uMIPS_RD(ctx->opcode));
11585 int rb = mmreg(uMIPS_RS(ctx->opcode));
11586 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11588 gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
11590 break;
11591 case LWSP16:
11593 int rd = (ctx->opcode >> 5) & 0x1f;
11594 int rb = 29; /* SP */
11595 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11597 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11599 break;
11600 case LW16:
11602 int rd = mmreg(uMIPS_RD(ctx->opcode));
11603 int rb = mmreg(uMIPS_RS(ctx->opcode));
11604 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11606 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11608 break;
11609 case SB16:
11611 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11612 int rb = mmreg(uMIPS_RS(ctx->opcode));
11613 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11615 gen_st(ctx, OPC_SB, rd, rb, offset);
11617 break;
11618 case SH16:
11620 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11621 int rb = mmreg(uMIPS_RS(ctx->opcode));
11622 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11624 gen_st(ctx, OPC_SH, rd, rb, offset);
11626 break;
11627 case SWSP16:
11629 int rd = (ctx->opcode >> 5) & 0x1f;
11630 int rb = 29; /* SP */
11631 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11633 gen_st(ctx, OPC_SW, rd, rb, offset);
11635 break;
11636 case SW16:
11638 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11639 int rb = mmreg(uMIPS_RS(ctx->opcode));
11640 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11642 gen_st(ctx, OPC_SW, rd, rb, offset);
11644 break;
11645 case MOVE16:
11647 int rd = uMIPS_RD5(ctx->opcode);
11648 int rs = uMIPS_RS5(ctx->opcode);
11650 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11652 break;
11653 case ANDI16:
11654 gen_andi16(env, ctx);
11655 break;
11656 case POOL16D:
11657 switch (ctx->opcode & 0x1) {
11658 case ADDIUS5:
11659 gen_addius5(env, ctx);
11660 break;
11661 case ADDIUSP:
11662 gen_addiusp(env, ctx);
11663 break;
11665 break;
11666 case POOL16E:
11667 switch (ctx->opcode & 0x1) {
11668 case ADDIUR2:
11669 gen_addiur2(env, ctx);
11670 break;
11671 case ADDIUR1SP:
11672 gen_addiur1sp(env, ctx);
11673 break;
11675 break;
11676 case B16:
11677 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
11678 SIMM(ctx->opcode, 0, 10) << 1);
11679 *is_branch = 1;
11680 break;
11681 case BNEZ16:
11682 case BEQZ16:
11683 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
11684 mmreg(uMIPS_RD(ctx->opcode)),
11685 0, SIMM(ctx->opcode, 0, 7) << 1);
11686 *is_branch = 1;
11687 break;
11688 case LI16:
11690 int reg = mmreg(uMIPS_RD(ctx->opcode));
11691 int imm = ZIMM(ctx->opcode, 0, 7);
11693 imm = (imm == 0x7f ? -1 : imm);
11694 tcg_gen_movi_tl(cpu_gpr[reg], imm);
11696 break;
11697 case RES_20:
11698 case RES_28:
11699 case RES_29:
11700 case RES_30:
11701 case RES_31:
11702 case RES_38:
11703 case RES_39:
11704 generate_exception(ctx, EXCP_RI);
11705 break;
11706 default:
11707 decode_micromips32_opc (env, ctx, op, is_branch);
11708 return 4;
11711 return 2;
11714 /* SmartMIPS extension to MIPS32 */
11716 #if defined(TARGET_MIPS64)
11718 /* MDMX extension to MIPS64 */
11720 #endif
11722 static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
11724 int32_t offset;
11725 int rs, rt, rd, sa;
11726 uint32_t op, op1, op2;
11727 int16_t imm;
11729 /* make sure instructions are on a word boundary */
11730 if (ctx->pc & 0x3) {
11731 env->CP0_BadVAddr = ctx->pc;
11732 generate_exception(ctx, EXCP_AdEL);
11733 return;
11736 /* Handle blikely not taken case */
11737 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
11738 int l1 = gen_new_label();
11740 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
11741 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11742 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
11743 gen_goto_tb(ctx, 1, ctx->pc + 4);
11744 gen_set_label(l1);
11747 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11748 tcg_gen_debug_insn_start(ctx->pc);
11750 op = MASK_OP_MAJOR(ctx->opcode);
11751 rs = (ctx->opcode >> 21) & 0x1f;
11752 rt = (ctx->opcode >> 16) & 0x1f;
11753 rd = (ctx->opcode >> 11) & 0x1f;
11754 sa = (ctx->opcode >> 6) & 0x1f;
11755 imm = (int16_t)ctx->opcode;
11756 switch (op) {
11757 case OPC_SPECIAL:
11758 op1 = MASK_SPECIAL(ctx->opcode);
11759 switch (op1) {
11760 case OPC_SLL: /* Shift with immediate */
11761 case OPC_SRA:
11762 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11763 break;
11764 case OPC_SRL:
11765 switch ((ctx->opcode >> 21) & 0x1f) {
11766 case 1:
11767 /* rotr is decoded as srl on non-R2 CPUs */
11768 if (env->insn_flags & ISA_MIPS32R2) {
11769 op1 = OPC_ROTR;
11771 /* Fallthrough */
11772 case 0:
11773 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11774 break;
11775 default:
11776 generate_exception(ctx, EXCP_RI);
11777 break;
11779 break;
11780 case OPC_MOVN: /* Conditional move */
11781 case OPC_MOVZ:
11782 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
11783 INSN_LOONGSON2E | INSN_LOONGSON2F);
11784 gen_cond_move(env, op1, rd, rs, rt);
11785 break;
11786 case OPC_ADD ... OPC_SUBU:
11787 gen_arith(env, ctx, op1, rd, rs, rt);
11788 break;
11789 case OPC_SLLV: /* Shifts */
11790 case OPC_SRAV:
11791 gen_shift(env, ctx, op1, rd, rs, rt);
11792 break;
11793 case OPC_SRLV:
11794 switch ((ctx->opcode >> 6) & 0x1f) {
11795 case 1:
11796 /* rotrv is decoded as srlv on non-R2 CPUs */
11797 if (env->insn_flags & ISA_MIPS32R2) {
11798 op1 = OPC_ROTRV;
11800 /* Fallthrough */
11801 case 0:
11802 gen_shift(env, ctx, op1, rd, rs, rt);
11803 break;
11804 default:
11805 generate_exception(ctx, EXCP_RI);
11806 break;
11808 break;
11809 case OPC_SLT: /* Set on less than */
11810 case OPC_SLTU:
11811 gen_slt(env, op1, rd, rs, rt);
11812 break;
11813 case OPC_AND: /* Logic*/
11814 case OPC_OR:
11815 case OPC_NOR:
11816 case OPC_XOR:
11817 gen_logic(env, op1, rd, rs, rt);
11818 break;
11819 case OPC_MULT ... OPC_DIVU:
11820 if (sa) {
11821 check_insn(env, ctx, INSN_VR54XX);
11822 op1 = MASK_MUL_VR54XX(ctx->opcode);
11823 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11824 } else
11825 gen_muldiv(ctx, op1, rs, rt);
11826 break;
11827 case OPC_JR ... OPC_JALR:
11828 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
11829 *is_branch = 1;
11830 break;
11831 case OPC_TGE ... OPC_TEQ: /* Traps */
11832 case OPC_TNE:
11833 gen_trap(ctx, op1, rs, rt, -1);
11834 break;
11835 case OPC_MFHI: /* Move from HI/LO */
11836 case OPC_MFLO:
11837 gen_HILO(ctx, op1, rd);
11838 break;
11839 case OPC_MTHI:
11840 case OPC_MTLO: /* Move to HI/LO */
11841 gen_HILO(ctx, op1, rs);
11842 break;
11843 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
11844 #ifdef MIPS_STRICT_STANDARD
11845 MIPS_INVAL("PMON / selsl");
11846 generate_exception(ctx, EXCP_RI);
11847 #else
11848 gen_helper_0e0i(pmon, sa);
11849 #endif
11850 break;
11851 case OPC_SYSCALL:
11852 generate_exception(ctx, EXCP_SYSCALL);
11853 ctx->bstate = BS_STOP;
11854 break;
11855 case OPC_BREAK:
11856 generate_exception(ctx, EXCP_BREAK);
11857 break;
11858 case OPC_SPIM:
11859 #ifdef MIPS_STRICT_STANDARD
11860 MIPS_INVAL("SPIM");
11861 generate_exception(ctx, EXCP_RI);
11862 #else
11863 /* Implemented as RI exception for now. */
11864 MIPS_INVAL("spim (unofficial)");
11865 generate_exception(ctx, EXCP_RI);
11866 #endif
11867 break;
11868 case OPC_SYNC:
11869 /* Treat as NOP. */
11870 break;
11872 case OPC_MOVCI:
11873 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
11874 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11875 check_cp1_enabled(ctx);
11876 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11877 (ctx->opcode >> 16) & 1);
11878 } else {
11879 generate_exception_err(ctx, EXCP_CpU, 1);
11881 break;
11883 #if defined(TARGET_MIPS64)
11884 /* MIPS64 specific opcodes */
11885 case OPC_DSLL:
11886 case OPC_DSRA:
11887 case OPC_DSLL32:
11888 case OPC_DSRA32:
11889 check_insn(env, ctx, ISA_MIPS3);
11890 check_mips_64(ctx);
11891 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11892 break;
11893 case OPC_DSRL:
11894 switch ((ctx->opcode >> 21) & 0x1f) {
11895 case 1:
11896 /* drotr is decoded as dsrl on non-R2 CPUs */
11897 if (env->insn_flags & ISA_MIPS32R2) {
11898 op1 = OPC_DROTR;
11900 /* Fallthrough */
11901 case 0:
11902 check_insn(env, ctx, ISA_MIPS3);
11903 check_mips_64(ctx);
11904 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11905 break;
11906 default:
11907 generate_exception(ctx, EXCP_RI);
11908 break;
11910 break;
11911 case OPC_DSRL32:
11912 switch ((ctx->opcode >> 21) & 0x1f) {
11913 case 1:
11914 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
11915 if (env->insn_flags & ISA_MIPS32R2) {
11916 op1 = OPC_DROTR32;
11918 /* Fallthrough */
11919 case 0:
11920 check_insn(env, ctx, ISA_MIPS3);
11921 check_mips_64(ctx);
11922 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11923 break;
11924 default:
11925 generate_exception(ctx, EXCP_RI);
11926 break;
11928 break;
11929 case OPC_DADD ... OPC_DSUBU:
11930 check_insn(env, ctx, ISA_MIPS3);
11931 check_mips_64(ctx);
11932 gen_arith(env, ctx, op1, rd, rs, rt);
11933 break;
11934 case OPC_DSLLV:
11935 case OPC_DSRAV:
11936 check_insn(env, ctx, ISA_MIPS3);
11937 check_mips_64(ctx);
11938 gen_shift(env, ctx, op1, rd, rs, rt);
11939 break;
11940 case OPC_DSRLV:
11941 switch ((ctx->opcode >> 6) & 0x1f) {
11942 case 1:
11943 /* drotrv is decoded as dsrlv on non-R2 CPUs */
11944 if (env->insn_flags & ISA_MIPS32R2) {
11945 op1 = OPC_DROTRV;
11947 /* Fallthrough */
11948 case 0:
11949 check_insn(env, ctx, ISA_MIPS3);
11950 check_mips_64(ctx);
11951 gen_shift(env, ctx, op1, rd, rs, rt);
11952 break;
11953 default:
11954 generate_exception(ctx, EXCP_RI);
11955 break;
11957 break;
11958 case OPC_DMULT ... OPC_DDIVU:
11959 check_insn(env, ctx, ISA_MIPS3);
11960 check_mips_64(ctx);
11961 gen_muldiv(ctx, op1, rs, rt);
11962 break;
11963 #endif
11964 default: /* Invalid */
11965 MIPS_INVAL("special");
11966 generate_exception(ctx, EXCP_RI);
11967 break;
11969 break;
11970 case OPC_SPECIAL2:
11971 op1 = MASK_SPECIAL2(ctx->opcode);
11972 switch (op1) {
11973 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11974 case OPC_MSUB ... OPC_MSUBU:
11975 check_insn(env, ctx, ISA_MIPS32);
11976 gen_muldiv(ctx, op1, rs, rt);
11977 break;
11978 case OPC_MUL:
11979 gen_arith(env, ctx, op1, rd, rs, rt);
11980 break;
11981 case OPC_CLO:
11982 case OPC_CLZ:
11983 check_insn(env, ctx, ISA_MIPS32);
11984 gen_cl(ctx, op1, rd, rs);
11985 break;
11986 case OPC_SDBBP:
11987 /* XXX: not clear which exception should be raised
11988 * when in debug mode...
11990 check_insn(env, ctx, ISA_MIPS32);
11991 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11992 generate_exception(ctx, EXCP_DBp);
11993 } else {
11994 generate_exception(ctx, EXCP_DBp);
11996 /* Treat as NOP. */
11997 break;
11998 case OPC_DIV_G_2F:
11999 case OPC_DIVU_G_2F:
12000 case OPC_MULT_G_2F:
12001 case OPC_MULTU_G_2F:
12002 case OPC_MOD_G_2F:
12003 case OPC_MODU_G_2F:
12004 check_insn(env, ctx, INSN_LOONGSON2F);
12005 gen_loongson_integer(ctx, op1, rd, rs, rt);
12006 break;
12007 #if defined(TARGET_MIPS64)
12008 case OPC_DCLO:
12009 case OPC_DCLZ:
12010 check_insn(env, ctx, ISA_MIPS64);
12011 check_mips_64(ctx);
12012 gen_cl(ctx, op1, rd, rs);
12013 break;
12014 case OPC_DMULT_G_2F:
12015 case OPC_DMULTU_G_2F:
12016 case OPC_DDIV_G_2F:
12017 case OPC_DDIVU_G_2F:
12018 case OPC_DMOD_G_2F:
12019 case OPC_DMODU_G_2F:
12020 check_insn(env, ctx, INSN_LOONGSON2F);
12021 gen_loongson_integer(ctx, op1, rd, rs, rt);
12022 break;
12023 #endif
12024 default: /* Invalid */
12025 MIPS_INVAL("special2");
12026 generate_exception(ctx, EXCP_RI);
12027 break;
12029 break;
12030 case OPC_SPECIAL3:
12031 op1 = MASK_SPECIAL3(ctx->opcode);
12032 switch (op1) {
12033 case OPC_EXT:
12034 case OPC_INS:
12035 check_insn(env, ctx, ISA_MIPS32R2);
12036 gen_bitops(ctx, op1, rt, rs, sa, rd);
12037 break;
12038 case OPC_BSHFL:
12039 check_insn(env, ctx, ISA_MIPS32R2);
12040 op2 = MASK_BSHFL(ctx->opcode);
12041 gen_bshfl(ctx, op2, rt, rd);
12042 break;
12043 case OPC_RDHWR:
12044 gen_rdhwr(env, ctx, rt, rd);
12045 break;
12046 case OPC_FORK:
12047 check_insn(env, ctx, ASE_MT);
12049 TCGv t0 = tcg_temp_new();
12050 TCGv t1 = tcg_temp_new();
12052 gen_load_gpr(t0, rt);
12053 gen_load_gpr(t1, rs);
12054 gen_helper_fork(t0, t1);
12055 tcg_temp_free(t0);
12056 tcg_temp_free(t1);
12058 break;
12059 case OPC_YIELD:
12060 check_insn(env, ctx, ASE_MT);
12062 TCGv t0 = tcg_temp_new();
12064 save_cpu_state(ctx, 1);
12065 gen_load_gpr(t0, rs);
12066 gen_helper_yield(t0, cpu_env, t0);
12067 gen_store_gpr(t0, rd);
12068 tcg_temp_free(t0);
12070 break;
12071 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
12072 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
12073 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
12074 check_insn(env, ctx, INSN_LOONGSON2E);
12075 gen_loongson_integer(ctx, op1, rd, rs, rt);
12076 break;
12077 #if defined(TARGET_MIPS64)
12078 case OPC_DEXTM ... OPC_DEXT:
12079 case OPC_DINSM ... OPC_DINS:
12080 check_insn(env, ctx, ISA_MIPS64R2);
12081 check_mips_64(ctx);
12082 gen_bitops(ctx, op1, rt, rs, sa, rd);
12083 break;
12084 case OPC_DBSHFL:
12085 check_insn(env, ctx, ISA_MIPS64R2);
12086 check_mips_64(ctx);
12087 op2 = MASK_DBSHFL(ctx->opcode);
12088 gen_bshfl(ctx, op2, rt, rd);
12089 break;
12090 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
12091 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
12092 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
12093 check_insn(env, ctx, INSN_LOONGSON2E);
12094 gen_loongson_integer(ctx, op1, rd, rs, rt);
12095 break;
12096 #endif
12097 default: /* Invalid */
12098 MIPS_INVAL("special3");
12099 generate_exception(ctx, EXCP_RI);
12100 break;
12102 break;
12103 case OPC_REGIMM:
12104 op1 = MASK_REGIMM(ctx->opcode);
12105 switch (op1) {
12106 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
12107 case OPC_BLTZAL ... OPC_BGEZALL:
12108 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
12109 *is_branch = 1;
12110 break;
12111 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
12112 case OPC_TNEI:
12113 gen_trap(ctx, op1, rs, -1, imm);
12114 break;
12115 case OPC_SYNCI:
12116 check_insn(env, ctx, ISA_MIPS32R2);
12117 /* Treat as NOP. */
12118 break;
12119 default: /* Invalid */
12120 MIPS_INVAL("regimm");
12121 generate_exception(ctx, EXCP_RI);
12122 break;
12124 break;
12125 case OPC_CP0:
12126 check_cp0_enabled(ctx);
12127 op1 = MASK_CP0(ctx->opcode);
12128 switch (op1) {
12129 case OPC_MFC0:
12130 case OPC_MTC0:
12131 case OPC_MFTR:
12132 case OPC_MTTR:
12133 #if defined(TARGET_MIPS64)
12134 case OPC_DMFC0:
12135 case OPC_DMTC0:
12136 #endif
12137 #ifndef CONFIG_USER_ONLY
12138 gen_cp0(env, ctx, op1, rt, rd);
12139 #endif /* !CONFIG_USER_ONLY */
12140 break;
12141 case OPC_C0_FIRST ... OPC_C0_LAST:
12142 #ifndef CONFIG_USER_ONLY
12143 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
12144 #endif /* !CONFIG_USER_ONLY */
12145 break;
12146 case OPC_MFMC0:
12147 #ifndef CONFIG_USER_ONLY
12149 TCGv t0 = tcg_temp_new();
12151 op2 = MASK_MFMC0(ctx->opcode);
12152 switch (op2) {
12153 case OPC_DMT:
12154 check_insn(env, ctx, ASE_MT);
12155 gen_helper_dmt(t0);
12156 gen_store_gpr(t0, rt);
12157 break;
12158 case OPC_EMT:
12159 check_insn(env, ctx, ASE_MT);
12160 gen_helper_emt(t0);
12161 gen_store_gpr(t0, rt);
12162 break;
12163 case OPC_DVPE:
12164 check_insn(env, ctx, ASE_MT);
12165 gen_helper_dvpe(t0, cpu_env);
12166 gen_store_gpr(t0, rt);
12167 break;
12168 case OPC_EVPE:
12169 check_insn(env, ctx, ASE_MT);
12170 gen_helper_evpe(t0, cpu_env);
12171 gen_store_gpr(t0, rt);
12172 break;
12173 case OPC_DI:
12174 check_insn(env, ctx, ISA_MIPS32R2);
12175 save_cpu_state(ctx, 1);
12176 gen_helper_di(t0, cpu_env);
12177 gen_store_gpr(t0, rt);
12178 /* Stop translation as we may have switched the execution mode */
12179 ctx->bstate = BS_STOP;
12180 break;
12181 case OPC_EI:
12182 check_insn(env, ctx, ISA_MIPS32R2);
12183 save_cpu_state(ctx, 1);
12184 gen_helper_ei(t0, cpu_env);
12185 gen_store_gpr(t0, rt);
12186 /* Stop translation as we may have switched the execution mode */
12187 ctx->bstate = BS_STOP;
12188 break;
12189 default: /* Invalid */
12190 MIPS_INVAL("mfmc0");
12191 generate_exception(ctx, EXCP_RI);
12192 break;
12194 tcg_temp_free(t0);
12196 #endif /* !CONFIG_USER_ONLY */
12197 break;
12198 case OPC_RDPGPR:
12199 check_insn(env, ctx, ISA_MIPS32R2);
12200 gen_load_srsgpr(rt, rd);
12201 break;
12202 case OPC_WRPGPR:
12203 check_insn(env, ctx, ISA_MIPS32R2);
12204 gen_store_srsgpr(rt, rd);
12205 break;
12206 default:
12207 MIPS_INVAL("cp0");
12208 generate_exception(ctx, EXCP_RI);
12209 break;
12211 break;
12212 case OPC_ADDI: /* Arithmetic with immediate opcode */
12213 case OPC_ADDIU:
12214 gen_arith_imm(env, ctx, op, rt, rs, imm);
12215 break;
12216 case OPC_SLTI: /* Set on less than with immediate opcode */
12217 case OPC_SLTIU:
12218 gen_slt_imm(env, op, rt, rs, imm);
12219 break;
12220 case OPC_ANDI: /* Arithmetic with immediate opcode */
12221 case OPC_LUI:
12222 case OPC_ORI:
12223 case OPC_XORI:
12224 gen_logic_imm(env, op, rt, rs, imm);
12225 break;
12226 case OPC_J ... OPC_JAL: /* Jump */
12227 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12228 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12229 *is_branch = 1;
12230 break;
12231 case OPC_BEQ ... OPC_BGTZ: /* Branch */
12232 case OPC_BEQL ... OPC_BGTZL:
12233 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
12234 *is_branch = 1;
12235 break;
12236 case OPC_LB ... OPC_LWR: /* Load and stores */
12237 case OPC_LL:
12238 gen_ld(env, ctx, op, rt, rs, imm);
12239 break;
12240 case OPC_SB ... OPC_SW:
12241 case OPC_SWR:
12242 gen_st(ctx, op, rt, rs, imm);
12243 break;
12244 case OPC_SC:
12245 gen_st_cond(ctx, op, rt, rs, imm);
12246 break;
12247 case OPC_CACHE:
12248 check_cp0_enabled(ctx);
12249 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
12250 /* Treat as NOP. */
12251 break;
12252 case OPC_PREF:
12253 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
12254 /* Treat as NOP. */
12255 break;
12257 /* Floating point (COP1). */
12258 case OPC_LWC1:
12259 case OPC_LDC1:
12260 case OPC_SWC1:
12261 case OPC_SDC1:
12262 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
12263 break;
12265 case OPC_CP1:
12266 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12267 check_cp1_enabled(ctx);
12268 op1 = MASK_CP1(ctx->opcode);
12269 switch (op1) {
12270 case OPC_MFHC1:
12271 case OPC_MTHC1:
12272 check_insn(env, ctx, ISA_MIPS32R2);
12273 case OPC_MFC1:
12274 case OPC_CFC1:
12275 case OPC_MTC1:
12276 case OPC_CTC1:
12277 gen_cp1(ctx, op1, rt, rd);
12278 break;
12279 #if defined(TARGET_MIPS64)
12280 case OPC_DMFC1:
12281 case OPC_DMTC1:
12282 check_insn(env, ctx, ISA_MIPS3);
12283 gen_cp1(ctx, op1, rt, rd);
12284 break;
12285 #endif
12286 case OPC_BC1ANY2:
12287 case OPC_BC1ANY4:
12288 check_cop1x(ctx);
12289 check_insn(env, ctx, ASE_MIPS3D);
12290 /* fall through */
12291 case OPC_BC1:
12292 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
12293 (rt >> 2) & 0x7, imm << 2);
12294 *is_branch = 1;
12295 break;
12296 case OPC_S_FMT:
12297 case OPC_D_FMT:
12298 case OPC_W_FMT:
12299 case OPC_L_FMT:
12300 case OPC_PS_FMT:
12301 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
12302 (imm >> 8) & 0x7);
12303 break;
12304 default:
12305 MIPS_INVAL("cp1");
12306 generate_exception (ctx, EXCP_RI);
12307 break;
12309 } else {
12310 generate_exception_err(ctx, EXCP_CpU, 1);
12312 break;
12314 /* COP2. */
12315 case OPC_LWC2:
12316 case OPC_LDC2:
12317 case OPC_SWC2:
12318 case OPC_SDC2:
12319 case OPC_CP2:
12320 /* COP2: Not implemented. */
12321 generate_exception_err(ctx, EXCP_CpU, 2);
12322 break;
12324 case OPC_CP3:
12325 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12326 check_cp1_enabled(ctx);
12327 op1 = MASK_CP3(ctx->opcode);
12328 switch (op1) {
12329 case OPC_LWXC1:
12330 case OPC_LDXC1:
12331 case OPC_LUXC1:
12332 case OPC_SWXC1:
12333 case OPC_SDXC1:
12334 case OPC_SUXC1:
12335 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
12336 break;
12337 case OPC_PREFX:
12338 /* Treat as NOP. */
12339 break;
12340 case OPC_ALNV_PS:
12341 case OPC_MADD_S:
12342 case OPC_MADD_D:
12343 case OPC_MADD_PS:
12344 case OPC_MSUB_S:
12345 case OPC_MSUB_D:
12346 case OPC_MSUB_PS:
12347 case OPC_NMADD_S:
12348 case OPC_NMADD_D:
12349 case OPC_NMADD_PS:
12350 case OPC_NMSUB_S:
12351 case OPC_NMSUB_D:
12352 case OPC_NMSUB_PS:
12353 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12354 break;
12355 default:
12356 MIPS_INVAL("cp3");
12357 generate_exception (ctx, EXCP_RI);
12358 break;
12360 } else {
12361 generate_exception_err(ctx, EXCP_CpU, 1);
12363 break;
12365 #if defined(TARGET_MIPS64)
12366 /* MIPS64 opcodes */
12367 case OPC_LWU:
12368 case OPC_LDL ... OPC_LDR:
12369 case OPC_LLD:
12370 case OPC_LD:
12371 check_insn(env, ctx, ISA_MIPS3);
12372 check_mips_64(ctx);
12373 gen_ld(env, ctx, op, rt, rs, imm);
12374 break;
12375 case OPC_SDL ... OPC_SDR:
12376 case OPC_SD:
12377 check_insn(env, ctx, ISA_MIPS3);
12378 check_mips_64(ctx);
12379 gen_st(ctx, op, rt, rs, imm);
12380 break;
12381 case OPC_SCD:
12382 check_insn(env, ctx, ISA_MIPS3);
12383 check_mips_64(ctx);
12384 gen_st_cond(ctx, op, rt, rs, imm);
12385 break;
12386 case OPC_DADDI:
12387 case OPC_DADDIU:
12388 check_insn(env, ctx, ISA_MIPS3);
12389 check_mips_64(ctx);
12390 gen_arith_imm(env, ctx, op, rt, rs, imm);
12391 break;
12392 #endif
12393 case OPC_JALX:
12394 check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
12395 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12396 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12397 *is_branch = 1;
12398 break;
12399 case OPC_MDMX:
12400 check_insn(env, ctx, ASE_MDMX);
12401 /* MDMX: Not implemented. */
12402 default: /* Invalid */
12403 MIPS_INVAL("major opcode");
12404 generate_exception(ctx, EXCP_RI);
12405 break;
12409 static inline void
12410 gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
12411 int search_pc)
12413 DisasContext ctx;
12414 target_ulong pc_start;
12415 uint16_t *gen_opc_end;
12416 CPUBreakpoint *bp;
12417 int j, lj = -1;
12418 int num_insns;
12419 int max_insns;
12420 int insn_bytes;
12421 int is_branch;
12423 if (search_pc)
12424 qemu_log("search pc %d\n", search_pc);
12426 pc_start = tb->pc;
12427 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
12428 ctx.pc = pc_start;
12429 ctx.saved_pc = -1;
12430 ctx.singlestep_enabled = env->singlestep_enabled;
12431 ctx.tb = tb;
12432 ctx.bstate = BS_NONE;
12433 /* Restore delay slot state from the tb context. */
12434 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
12435 restore_cpu_state(env, &ctx);
12436 #ifdef CONFIG_USER_ONLY
12437 ctx.mem_idx = MIPS_HFLAG_UM;
12438 #else
12439 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
12440 #endif
12441 num_insns = 0;
12442 max_insns = tb->cflags & CF_COUNT_MASK;
12443 if (max_insns == 0)
12444 max_insns = CF_COUNT_MASK;
12445 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
12446 gen_icount_start();
12447 while (ctx.bstate == BS_NONE) {
12448 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12449 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
12450 if (bp->pc == ctx.pc) {
12451 save_cpu_state(&ctx, 1);
12452 ctx.bstate = BS_BRANCH;
12453 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
12454 /* Include the breakpoint location or the tb won't
12455 * be flushed when it must be. */
12456 ctx.pc += 4;
12457 goto done_generating;
12462 if (search_pc) {
12463 j = gen_opc_ptr - gen_opc_buf;
12464 if (lj < j) {
12465 lj++;
12466 while (lj < j)
12467 gen_opc_instr_start[lj++] = 0;
12469 gen_opc_pc[lj] = ctx.pc;
12470 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12471 gen_opc_instr_start[lj] = 1;
12472 gen_opc_icount[lj] = num_insns;
12474 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12475 gen_io_start();
12477 is_branch = 0;
12478 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
12479 ctx.opcode = cpu_ldl_code(env, ctx.pc);
12480 insn_bytes = 4;
12481 decode_opc(env, &ctx, &is_branch);
12482 } else if (env->insn_flags & ASE_MICROMIPS) {
12483 ctx.opcode = cpu_lduw_code(env, ctx.pc);
12484 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
12485 } else if (env->insn_flags & ASE_MIPS16) {
12486 ctx.opcode = cpu_lduw_code(env, ctx.pc);
12487 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
12488 } else {
12489 generate_exception(&ctx, EXCP_RI);
12490 ctx.bstate = BS_STOP;
12491 break;
12493 if (!is_branch) {
12494 handle_delay_slot(env, &ctx, insn_bytes);
12496 ctx.pc += insn_bytes;
12498 num_insns++;
12500 /* Execute a branch and its delay slot as a single instruction.
12501 This is what GDB expects and is consistent with what the
12502 hardware does (e.g. if a delay slot instruction faults, the
12503 reported PC is the PC of the branch). */
12504 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
12505 break;
12507 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12508 break;
12510 if (gen_opc_ptr >= gen_opc_end)
12511 break;
12513 if (num_insns >= max_insns)
12514 break;
12516 if (singlestep)
12517 break;
12519 if (tb->cflags & CF_LAST_IO)
12520 gen_io_end();
12521 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
12522 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
12523 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
12524 } else {
12525 switch (ctx.bstate) {
12526 case BS_STOP:
12527 gen_goto_tb(&ctx, 0, ctx.pc);
12528 break;
12529 case BS_NONE:
12530 save_cpu_state(&ctx, 0);
12531 gen_goto_tb(&ctx, 0, ctx.pc);
12532 break;
12533 case BS_EXCP:
12534 tcg_gen_exit_tb(0);
12535 break;
12536 case BS_BRANCH:
12537 default:
12538 break;
12541 done_generating:
12542 gen_icount_end(tb, num_insns);
12543 *gen_opc_ptr = INDEX_op_end;
12544 if (search_pc) {
12545 j = gen_opc_ptr - gen_opc_buf;
12546 lj++;
12547 while (lj <= j)
12548 gen_opc_instr_start[lj++] = 0;
12549 } else {
12550 tb->size = ctx.pc - pc_start;
12551 tb->icount = num_insns;
12553 #ifdef DEBUG_DISAS
12554 LOG_DISAS("\n");
12555 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
12556 qemu_log("IN: %s\n", lookup_symbol(pc_start));
12557 log_target_disas(pc_start, ctx.pc - pc_start, 0);
12558 qemu_log("\n");
12560 #endif
12563 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
12565 gen_intermediate_code_internal(env, tb, 0);
12568 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
12570 gen_intermediate_code_internal(env, tb, 1);
12573 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
12574 int flags)
12576 int i;
12577 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
12579 #define printfpr(fp) \
12580 do { \
12581 if (is_fpu64) \
12582 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12583 " fd:%13g fs:%13g psu: %13g\n", \
12584 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12585 (double)(fp)->fd, \
12586 (double)(fp)->fs[FP_ENDIAN_IDX], \
12587 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12588 else { \
12589 fpr_t tmp; \
12590 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12591 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12592 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12593 " fd:%13g fs:%13g psu:%13g\n", \
12594 tmp.w[FP_ENDIAN_IDX], tmp.d, \
12595 (double)tmp.fd, \
12596 (double)tmp.fs[FP_ENDIAN_IDX], \
12597 (double)tmp.fs[!FP_ENDIAN_IDX]); \
12599 } while(0)
12602 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
12603 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
12604 get_float_exception_flags(&env->active_fpu.fp_status));
12605 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12606 fpu_fprintf(f, "%3s: ", fregnames[i]);
12607 printfpr(&env->active_fpu.fpr[i]);
12610 #undef printfpr
12613 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
12614 /* Debug help: The architecture requires 32bit code to maintain proper
12615 sign-extended values on 64bit machines. */
12617 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12619 static void
12620 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
12621 fprintf_function cpu_fprintf,
12622 int flags)
12624 int i;
12626 if (!SIGN_EXT_P(env->active_tc.PC))
12627 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12628 if (!SIGN_EXT_P(env->active_tc.HI[0]))
12629 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12630 if (!SIGN_EXT_P(env->active_tc.LO[0]))
12631 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
12632 if (!SIGN_EXT_P(env->btarget))
12633 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
12635 for (i = 0; i < 32; i++) {
12636 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12637 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
12640 if (!SIGN_EXT_P(env->CP0_EPC))
12641 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
12642 if (!SIGN_EXT_P(env->lladdr))
12643 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
12645 #endif
12647 void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
12648 int flags)
12650 int i;
12652 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
12653 " LO=0x" TARGET_FMT_lx " ds %04x "
12654 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
12655 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12656 env->hflags, env->btarget, env->bcond);
12657 for (i = 0; i < 32; i++) {
12658 if ((i & 3) == 0)
12659 cpu_fprintf(f, "GPR%02d:", i);
12660 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
12661 if ((i & 3) == 3)
12662 cpu_fprintf(f, "\n");
12665 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
12666 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
12667 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
12668 env->CP0_Config0, env->CP0_Config1, env->lladdr);
12669 if (env->hflags & MIPS_HFLAG_FPU)
12670 fpu_dump_state(env, f, cpu_fprintf, flags);
12671 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
12672 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
12673 #endif
12676 static void mips_tcg_init(void)
12678 int i;
12679 static int inited;
12681 /* Initialize various static tables. */
12682 if (inited)
12683 return;
12685 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
12686 TCGV_UNUSED(cpu_gpr[0]);
12687 for (i = 1; i < 32; i++)
12688 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
12689 offsetof(CPUMIPSState, active_tc.gpr[i]),
12690 regnames[i]);
12691 cpu_PC = tcg_global_mem_new(TCG_AREG0,
12692 offsetof(CPUMIPSState, active_tc.PC), "PC");
12693 for (i = 0; i < MIPS_DSP_ACC; i++) {
12694 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
12695 offsetof(CPUMIPSState, active_tc.HI[i]),
12696 regnames_HI[i]);
12697 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
12698 offsetof(CPUMIPSState, active_tc.LO[i]),
12699 regnames_LO[i]);
12700 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
12701 offsetof(CPUMIPSState, active_tc.ACX[i]),
12702 regnames_ACX[i]);
12704 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
12705 offsetof(CPUMIPSState, active_tc.DSPControl),
12706 "DSPControl");
12707 bcond = tcg_global_mem_new(TCG_AREG0,
12708 offsetof(CPUMIPSState, bcond), "bcond");
12709 btarget = tcg_global_mem_new(TCG_AREG0,
12710 offsetof(CPUMIPSState, btarget), "btarget");
12711 hflags = tcg_global_mem_new_i32(TCG_AREG0,
12712 offsetof(CPUMIPSState, hflags), "hflags");
12714 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
12715 offsetof(CPUMIPSState, active_fpu.fcr0),
12716 "fcr0");
12717 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
12718 offsetof(CPUMIPSState, active_fpu.fcr31),
12719 "fcr31");
12721 /* register helpers */
12722 #define GEN_HELPER 2
12723 #include "helper.h"
12725 inited = 1;
12728 #include "translate_init.c"
12730 MIPSCPU *cpu_mips_init(const char *cpu_model)
12732 MIPSCPU *cpu;
12733 CPUMIPSState *env;
12734 const mips_def_t *def;
12736 def = cpu_mips_find_by_name(cpu_model);
12737 if (!def)
12738 return NULL;
12739 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
12740 env = &cpu->env;
12741 env->cpu_model = def;
12742 env->cpu_model_str = cpu_model;
12744 #ifndef CONFIG_USER_ONLY
12745 mmu_init(env, def);
12746 #endif
12747 fpu_init(env, def);
12748 mvp_init(env, def);
12749 mips_tcg_init();
12750 cpu_reset(CPU(cpu));
12751 qemu_init_vcpu(env);
12752 return cpu;
12755 void cpu_state_reset(CPUMIPSState *env)
12757 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12758 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12759 log_cpu_state(env, 0);
12762 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
12763 tlb_flush(env, 1);
12765 /* Reset registers to their default values */
12766 env->CP0_PRid = env->cpu_model->CP0_PRid;
12767 env->CP0_Config0 = env->cpu_model->CP0_Config0;
12768 #ifdef TARGET_WORDS_BIGENDIAN
12769 env->CP0_Config0 |= (1 << CP0C0_BE);
12770 #endif
12771 env->CP0_Config1 = env->cpu_model->CP0_Config1;
12772 env->CP0_Config2 = env->cpu_model->CP0_Config2;
12773 env->CP0_Config3 = env->cpu_model->CP0_Config3;
12774 env->CP0_Config6 = env->cpu_model->CP0_Config6;
12775 env->CP0_Config7 = env->cpu_model->CP0_Config7;
12776 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12777 << env->cpu_model->CP0_LLAddr_shift;
12778 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
12779 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12780 env->CCRes = env->cpu_model->CCRes;
12781 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12782 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12783 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12784 env->current_tc = 0;
12785 env->SEGBITS = env->cpu_model->SEGBITS;
12786 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12787 #if defined(TARGET_MIPS64)
12788 if (env->cpu_model->insn_flags & ISA_MIPS3) {
12789 env->SEGMask |= 3ULL << 62;
12791 #endif
12792 env->PABITS = env->cpu_model->PABITS;
12793 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12794 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12795 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12796 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12797 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12798 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12799 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12800 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12801 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12802 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12803 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
12804 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
12805 env->insn_flags = env->cpu_model->insn_flags;
12807 #if defined(CONFIG_USER_ONLY)
12808 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
12809 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
12810 hardware registers. */
12811 env->CP0_HWREna |= 0x0000000F;
12812 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12813 env->CP0_Status |= (1 << CP0St_CU1);
12815 #else
12816 if (env->hflags & MIPS_HFLAG_BMASK) {
12817 /* If the exception was raised from a delay slot,
12818 come back to the jump. */
12819 env->CP0_ErrorEPC = env->active_tc.PC - 4;
12820 } else {
12821 env->CP0_ErrorEPC = env->active_tc.PC;
12823 env->active_tc.PC = (int32_t)0xBFC00000;
12824 env->CP0_Random = env->tlb->nb_tlb - 1;
12825 env->tlb->tlb_in_use = env->tlb->nb_tlb;
12826 env->CP0_Wired = 0;
12827 env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
12828 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
12829 /* vectored interrupts not implemented, timer on int 7,
12830 no performance counters. */
12831 env->CP0_IntCtl = 0xe0000000;
12833 int i;
12835 for (i = 0; i < 7; i++) {
12836 env->CP0_WatchLo[i] = 0;
12837 env->CP0_WatchHi[i] = 0x80000000;
12839 env->CP0_WatchLo[7] = 0;
12840 env->CP0_WatchHi[7] = 0;
12842 /* Count register increments in debug mode, EJTAG version 1 */
12843 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
12845 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
12846 int i;
12848 /* Only TC0 on VPE 0 starts as active. */
12849 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
12850 env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
12851 env->tcs[i].CP0_TCHalt = 1;
12853 env->active_tc.CP0_TCHalt = 1;
12854 env->halted = 1;
12856 if (!env->cpu_index) {
12857 /* VPE0 starts up enabled. */
12858 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
12859 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
12861 /* TC0 starts up unhalted. */
12862 env->halted = 0;
12863 env->active_tc.CP0_TCHalt = 0;
12864 env->tcs[0].CP0_TCHalt = 0;
12865 /* With thread 0 active. */
12866 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
12867 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
12870 #endif
12871 compute_hflags(env);
12872 env->exception_index = EXCP_NONE;
12875 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
12877 env->active_tc.PC = gen_opc_pc[pc_pos];
12878 env->hflags &= ~MIPS_HFLAG_BMASK;
12879 env->hflags |= gen_opc_hflags[pc_pos];