Merge commit '92aa5c6d77ac29574c1717bcf57827fa1e586f31' into upstream-merge
[qemu-kvm.git] / target-mips / translate.c
blob454e5cc81877e5d3bf15a042dd47da4718bbae11
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 0
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_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
451 enum {
452 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
453 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
454 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
455 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
456 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
457 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
458 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
459 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
461 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
462 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
463 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
464 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
465 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
466 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
467 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
468 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
470 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
471 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
472 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
473 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
474 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
475 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
476 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
477 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
479 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
480 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
481 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
482 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
483 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
484 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
485 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
486 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
488 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
489 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
490 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
491 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
492 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
493 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
495 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
496 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
497 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
498 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
499 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
500 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
502 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
503 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
504 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
505 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
506 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
507 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
509 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
510 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
511 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
512 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
513 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
514 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
516 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
517 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
518 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
519 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
520 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
521 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
523 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
524 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
525 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
526 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
527 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
528 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
530 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
531 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
532 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
533 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
534 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
535 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
537 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
538 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
539 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
540 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
541 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
542 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
546 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
548 enum {
549 OPC_LWXC1 = 0x00 | OPC_CP3,
550 OPC_LDXC1 = 0x01 | OPC_CP3,
551 OPC_LUXC1 = 0x05 | OPC_CP3,
552 OPC_SWXC1 = 0x08 | OPC_CP3,
553 OPC_SDXC1 = 0x09 | OPC_CP3,
554 OPC_SUXC1 = 0x0D | OPC_CP3,
555 OPC_PREFX = 0x0F | OPC_CP3,
556 OPC_ALNV_PS = 0x1E | OPC_CP3,
557 OPC_MADD_S = 0x20 | OPC_CP3,
558 OPC_MADD_D = 0x21 | OPC_CP3,
559 OPC_MADD_PS = 0x26 | OPC_CP3,
560 OPC_MSUB_S = 0x28 | OPC_CP3,
561 OPC_MSUB_D = 0x29 | OPC_CP3,
562 OPC_MSUB_PS = 0x2E | OPC_CP3,
563 OPC_NMADD_S = 0x30 | OPC_CP3,
564 OPC_NMADD_D = 0x31 | OPC_CP3,
565 OPC_NMADD_PS= 0x36 | OPC_CP3,
566 OPC_NMSUB_S = 0x38 | OPC_CP3,
567 OPC_NMSUB_D = 0x39 | OPC_CP3,
568 OPC_NMSUB_PS= 0x3E | OPC_CP3,
571 /* global register indices */
572 static TCGv_ptr cpu_env;
573 static TCGv cpu_gpr[32], cpu_PC;
574 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
575 static TCGv cpu_dspctrl, btarget, bcond;
576 static TCGv_i32 hflags;
577 static TCGv_i32 fpu_fcr0, fpu_fcr31;
579 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
581 #include "gen-icount.h"
583 #define gen_helper_0e0i(name, arg) do { \
584 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
585 gen_helper_##name(cpu_env, helper_tmp); \
586 tcg_temp_free_i32(helper_tmp); \
587 } while(0)
589 #define gen_helper_0e1i(name, arg1, arg2) do { \
590 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
591 gen_helper_##name(cpu_env, arg1, helper_tmp); \
592 tcg_temp_free_i32(helper_tmp); \
593 } while(0)
595 #define gen_helper_1e0i(name, ret, arg1) do { \
596 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
597 gen_helper_##name(ret, cpu_env, helper_tmp); \
598 tcg_temp_free_i32(helper_tmp); \
599 } while(0)
601 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
602 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
603 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
604 tcg_temp_free_i32(helper_tmp); \
605 } while(0)
607 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
608 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
609 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
610 tcg_temp_free_i32(helper_tmp); \
611 } while(0)
613 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
614 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
615 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
616 tcg_temp_free_i32(helper_tmp); \
617 } while(0)
619 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
620 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
621 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
622 tcg_temp_free_i32(helper_tmp); \
623 } while(0)
625 typedef struct DisasContext {
626 struct TranslationBlock *tb;
627 target_ulong pc, saved_pc;
628 uint32_t opcode;
629 int singlestep_enabled;
630 /* Routine used to access memory */
631 int mem_idx;
632 uint32_t hflags, saved_hflags;
633 int bstate;
634 target_ulong btarget;
635 } DisasContext;
637 enum {
638 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
639 * exception condition */
640 BS_STOP = 1, /* We want to stop translation for any reason */
641 BS_BRANCH = 2, /* We reached a branch condition */
642 BS_EXCP = 3, /* We reached an exception condition */
645 static const char *regnames[] =
646 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
647 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
648 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
649 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
651 static const char *regnames_HI[] =
652 { "HI0", "HI1", "HI2", "HI3", };
654 static const char *regnames_LO[] =
655 { "LO0", "LO1", "LO2", "LO3", };
657 static const char *regnames_ACX[] =
658 { "ACX0", "ACX1", "ACX2", "ACX3", };
660 static const char *fregnames[] =
661 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
662 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
663 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
664 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
666 #define MIPS_DEBUG(fmt, ...) \
667 do { \
668 if (MIPS_DEBUG_DISAS) { \
669 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
670 TARGET_FMT_lx ": %08x " fmt "\n", \
671 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
673 } while (0)
675 #define LOG_DISAS(...) \
676 do { \
677 if (MIPS_DEBUG_DISAS) { \
678 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
680 } while (0)
682 #define MIPS_INVAL(op) \
683 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
684 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
686 /* General purpose registers moves. */
687 static inline void gen_load_gpr (TCGv t, int reg)
689 if (reg == 0)
690 tcg_gen_movi_tl(t, 0);
691 else
692 tcg_gen_mov_tl(t, cpu_gpr[reg]);
695 static inline void gen_store_gpr (TCGv t, int reg)
697 if (reg != 0)
698 tcg_gen_mov_tl(cpu_gpr[reg], t);
701 /* Moves to/from ACX register. */
702 static inline void gen_load_ACX (TCGv t, int reg)
704 tcg_gen_mov_tl(t, cpu_ACX[reg]);
707 static inline void gen_store_ACX (TCGv t, int reg)
709 tcg_gen_mov_tl(cpu_ACX[reg], t);
712 /* Moves to/from shadow registers. */
713 static inline void gen_load_srsgpr (int from, int to)
715 TCGv t0 = tcg_temp_new();
717 if (from == 0)
718 tcg_gen_movi_tl(t0, 0);
719 else {
720 TCGv_i32 t2 = tcg_temp_new_i32();
721 TCGv_ptr addr = tcg_temp_new_ptr();
723 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
724 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
725 tcg_gen_andi_i32(t2, t2, 0xf);
726 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
727 tcg_gen_ext_i32_ptr(addr, t2);
728 tcg_gen_add_ptr(addr, cpu_env, addr);
730 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
731 tcg_temp_free_ptr(addr);
732 tcg_temp_free_i32(t2);
734 gen_store_gpr(t0, to);
735 tcg_temp_free(t0);
738 static inline void gen_store_srsgpr (int from, int to)
740 if (to != 0) {
741 TCGv t0 = tcg_temp_new();
742 TCGv_i32 t2 = tcg_temp_new_i32();
743 TCGv_ptr addr = tcg_temp_new_ptr();
745 gen_load_gpr(t0, from);
746 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
747 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
748 tcg_gen_andi_i32(t2, t2, 0xf);
749 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
750 tcg_gen_ext_i32_ptr(addr, t2);
751 tcg_gen_add_ptr(addr, cpu_env, addr);
753 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
754 tcg_temp_free_ptr(addr);
755 tcg_temp_free_i32(t2);
756 tcg_temp_free(t0);
760 /* Floating point register moves. */
761 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
763 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
766 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
768 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
771 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
773 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
776 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
778 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
781 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
783 if (ctx->hflags & MIPS_HFLAG_F64) {
784 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
785 } else {
786 TCGv_i32 t0 = tcg_temp_new_i32();
787 TCGv_i32 t1 = tcg_temp_new_i32();
788 gen_load_fpr32(t0, reg & ~1);
789 gen_load_fpr32(t1, reg | 1);
790 tcg_gen_concat_i32_i64(t, t0, t1);
791 tcg_temp_free_i32(t0);
792 tcg_temp_free_i32(t1);
796 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
798 if (ctx->hflags & MIPS_HFLAG_F64) {
799 tcg_gen_st_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
800 } else {
801 TCGv_i64 t0 = tcg_temp_new_i64();
802 TCGv_i32 t1 = tcg_temp_new_i32();
803 tcg_gen_trunc_i64_i32(t1, t);
804 gen_store_fpr32(t1, reg & ~1);
805 tcg_gen_shri_i64(t0, t, 32);
806 tcg_gen_trunc_i64_i32(t1, t0);
807 gen_store_fpr32(t1, reg | 1);
808 tcg_temp_free_i32(t1);
809 tcg_temp_free_i64(t0);
813 static inline int get_fp_bit (int cc)
815 if (cc)
816 return 24 + cc;
817 else
818 return 23;
821 /* Tests */
822 static inline void gen_save_pc(target_ulong pc)
824 tcg_gen_movi_tl(cpu_PC, pc);
827 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
829 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
830 if (do_save_pc && ctx->pc != ctx->saved_pc) {
831 gen_save_pc(ctx->pc);
832 ctx->saved_pc = ctx->pc;
834 if (ctx->hflags != ctx->saved_hflags) {
835 tcg_gen_movi_i32(hflags, ctx->hflags);
836 ctx->saved_hflags = ctx->hflags;
837 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
838 case MIPS_HFLAG_BR:
839 break;
840 case MIPS_HFLAG_BC:
841 case MIPS_HFLAG_BL:
842 case MIPS_HFLAG_B:
843 tcg_gen_movi_tl(btarget, ctx->btarget);
844 break;
849 static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
851 ctx->saved_hflags = ctx->hflags;
852 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
853 case MIPS_HFLAG_BR:
854 break;
855 case MIPS_HFLAG_BC:
856 case MIPS_HFLAG_BL:
857 case MIPS_HFLAG_B:
858 ctx->btarget = env->btarget;
859 break;
863 static inline void
864 generate_exception_err (DisasContext *ctx, int excp, int err)
866 TCGv_i32 texcp = tcg_const_i32(excp);
867 TCGv_i32 terr = tcg_const_i32(err);
868 save_cpu_state(ctx, 1);
869 gen_helper_raise_exception_err(cpu_env, texcp, terr);
870 tcg_temp_free_i32(terr);
871 tcg_temp_free_i32(texcp);
874 static inline void
875 generate_exception (DisasContext *ctx, int excp)
877 save_cpu_state(ctx, 1);
878 gen_helper_0e0i(raise_exception, excp);
881 /* Addresses computation */
882 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
884 tcg_gen_add_tl(ret, arg0, arg1);
886 #if defined(TARGET_MIPS64)
887 /* For compatibility with 32-bit code, data reference in user mode
888 with Status_UX = 0 should be casted to 32-bit and sign extended.
889 See the MIPS64 PRA manual, section 4.10. */
890 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
891 !(ctx->hflags & MIPS_HFLAG_UX)) {
892 tcg_gen_ext32s_i64(ret, ret);
894 #endif
897 static inline void check_cp0_enabled(DisasContext *ctx)
899 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
900 generate_exception_err(ctx, EXCP_CpU, 0);
903 static inline void check_cp1_enabled(DisasContext *ctx)
905 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
906 generate_exception_err(ctx, EXCP_CpU, 1);
909 /* Verify that the processor is running with COP1X instructions enabled.
910 This is associated with the nabla symbol in the MIPS32 and MIPS64
911 opcode tables. */
913 static inline void check_cop1x(DisasContext *ctx)
915 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
916 generate_exception(ctx, EXCP_RI);
919 /* Verify that the processor is running with 64-bit floating-point
920 operations enabled. */
922 static inline void check_cp1_64bitmode(DisasContext *ctx)
924 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
925 generate_exception(ctx, EXCP_RI);
929 * Verify if floating point register is valid; an operation is not defined
930 * if bit 0 of any register specification is set and the FR bit in the
931 * Status register equals zero, since the register numbers specify an
932 * even-odd pair of adjacent coprocessor general registers. When the FR bit
933 * in the Status register equals one, both even and odd register numbers
934 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
936 * Multiple 64 bit wide registers can be checked by calling
937 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
939 static inline void check_cp1_registers(DisasContext *ctx, int regs)
941 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
942 generate_exception(ctx, EXCP_RI);
945 /* This code generates a "reserved instruction" exception if the
946 CPU does not support the instruction set corresponding to flags. */
947 static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
949 if (unlikely(!(env->insn_flags & flags)))
950 generate_exception(ctx, EXCP_RI);
953 /* This code generates a "reserved instruction" exception if 64-bit
954 instructions are not enabled. */
955 static inline void check_mips_64(DisasContext *ctx)
957 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
958 generate_exception(ctx, EXCP_RI);
961 /* Define small wrappers for gen_load_fpr* so that we have a uniform
962 calling interface for 32 and 64-bit FPRs. No sense in changing
963 all callers for gen_load_fpr32 when we need the CTX parameter for
964 this one use. */
965 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
966 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
967 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
968 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
969 int ft, int fs, int cc) \
971 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
972 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
973 switch (ifmt) { \
974 case FMT_PS: \
975 check_cp1_64bitmode(ctx); \
976 break; \
977 case FMT_D: \
978 if (abs) { \
979 check_cop1x(ctx); \
981 check_cp1_registers(ctx, fs | ft); \
982 break; \
983 case FMT_S: \
984 if (abs) { \
985 check_cop1x(ctx); \
987 break; \
989 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
990 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
991 switch (n) { \
992 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
993 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
994 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
995 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
996 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
997 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
998 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
999 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1000 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1001 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1002 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1003 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1004 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1005 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1006 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1007 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1008 default: abort(); \
1010 tcg_temp_free_i##bits (fp0); \
1011 tcg_temp_free_i##bits (fp1); \
1014 FOP_CONDS(, 0, d, FMT_D, 64)
1015 FOP_CONDS(abs, 1, d, FMT_D, 64)
1016 FOP_CONDS(, 0, s, FMT_S, 32)
1017 FOP_CONDS(abs, 1, s, FMT_S, 32)
1018 FOP_CONDS(, 0, ps, FMT_PS, 64)
1019 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1020 #undef FOP_CONDS
1021 #undef gen_ldcmp_fpr32
1022 #undef gen_ldcmp_fpr64
1024 /* load/store instructions. */
1025 #define OP_LD(insn,fname) \
1026 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1028 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1030 OP_LD(lb,ld8s);
1031 OP_LD(lbu,ld8u);
1032 OP_LD(lh,ld16s);
1033 OP_LD(lhu,ld16u);
1034 OP_LD(lw,ld32s);
1035 #if defined(TARGET_MIPS64)
1036 OP_LD(lwu,ld32u);
1037 OP_LD(ld,ld64);
1038 #endif
1039 #undef OP_LD
1041 #define OP_ST(insn,fname) \
1042 static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
1044 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
1046 OP_ST(sb,st8);
1047 OP_ST(sh,st16);
1048 OP_ST(sw,st32);
1049 #if defined(TARGET_MIPS64)
1050 OP_ST(sd,st64);
1051 #endif
1052 #undef OP_ST
1054 #ifdef CONFIG_USER_ONLY
1055 #define OP_LD_ATOMIC(insn,fname) \
1056 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1058 TCGv t0 = tcg_temp_new(); \
1059 tcg_gen_mov_tl(t0, arg1); \
1060 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1061 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1062 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
1063 tcg_temp_free(t0); \
1065 #else
1066 #define OP_LD_ATOMIC(insn,fname) \
1067 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1069 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
1071 #endif
1072 OP_LD_ATOMIC(ll,ld32s);
1073 #if defined(TARGET_MIPS64)
1074 OP_LD_ATOMIC(lld,ld64);
1075 #endif
1076 #undef OP_LD_ATOMIC
1078 #ifdef CONFIG_USER_ONLY
1079 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1080 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1082 TCGv t0 = tcg_temp_new(); \
1083 int l1 = gen_new_label(); \
1084 int l2 = gen_new_label(); \
1086 tcg_gen_andi_tl(t0, arg2, almask); \
1087 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
1088 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
1089 generate_exception(ctx, EXCP_AdES); \
1090 gen_set_label(l1); \
1091 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1092 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
1093 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
1094 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
1095 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
1096 gen_helper_0e0i(raise_exception, EXCP_SC); \
1097 gen_set_label(l2); \
1098 tcg_gen_movi_tl(t0, 0); \
1099 gen_store_gpr(t0, rt); \
1100 tcg_temp_free(t0); \
1102 #else
1103 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1104 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1106 TCGv t0 = tcg_temp_new(); \
1107 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
1108 gen_store_gpr(t0, rt); \
1109 tcg_temp_free(t0); \
1111 #endif
1112 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1113 #if defined(TARGET_MIPS64)
1114 OP_ST_ATOMIC(scd,st64,ld64,0x7);
1115 #endif
1116 #undef OP_ST_ATOMIC
1118 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1119 int base, int16_t offset)
1121 if (base == 0) {
1122 tcg_gen_movi_tl(addr, offset);
1123 } else if (offset == 0) {
1124 gen_load_gpr(addr, base);
1125 } else {
1126 tcg_gen_movi_tl(addr, offset);
1127 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1131 static target_ulong pc_relative_pc (DisasContext *ctx)
1133 target_ulong pc = ctx->pc;
1135 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1136 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1138 pc -= branch_bytes;
1141 pc &= ~(target_ulong)3;
1142 return pc;
1145 /* Load */
1146 static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1147 int rt, int base, int16_t offset)
1149 const char *opn = "ld";
1150 TCGv t0, t1;
1152 if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1153 /* Loongson CPU uses a load to zero register for prefetch.
1154 We emulate it as a NOP. On other CPU we must perform the
1155 actual memory access. */
1156 MIPS_DEBUG("NOP");
1157 return;
1160 t0 = tcg_temp_new();
1161 t1 = tcg_temp_new();
1162 gen_base_offset_addr(ctx, t0, base, offset);
1164 switch (opc) {
1165 #if defined(TARGET_MIPS64)
1166 case OPC_LWU:
1167 save_cpu_state(ctx, 0);
1168 op_ld_lwu(t0, t0, ctx);
1169 gen_store_gpr(t0, rt);
1170 opn = "lwu";
1171 break;
1172 case OPC_LD:
1173 save_cpu_state(ctx, 0);
1174 op_ld_ld(t0, t0, ctx);
1175 gen_store_gpr(t0, rt);
1176 opn = "ld";
1177 break;
1178 case OPC_LLD:
1179 save_cpu_state(ctx, 1);
1180 op_ld_lld(t0, t0, ctx);
1181 gen_store_gpr(t0, rt);
1182 opn = "lld";
1183 break;
1184 case OPC_LDL:
1185 save_cpu_state(ctx, 1);
1186 gen_load_gpr(t1, rt);
1187 gen_helper_1e2i(ldl, t1, t1, t0, ctx->mem_idx);
1188 gen_store_gpr(t1, rt);
1189 opn = "ldl";
1190 break;
1191 case OPC_LDR:
1192 save_cpu_state(ctx, 1);
1193 gen_load_gpr(t1, rt);
1194 gen_helper_1e2i(ldr, t1, t1, t0, ctx->mem_idx);
1195 gen_store_gpr(t1, rt);
1196 opn = "ldr";
1197 break;
1198 case OPC_LDPC:
1199 save_cpu_state(ctx, 0);
1200 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1201 gen_op_addr_add(ctx, t0, t0, t1);
1202 op_ld_ld(t0, t0, ctx);
1203 gen_store_gpr(t0, rt);
1204 opn = "ldpc";
1205 break;
1206 #endif
1207 case OPC_LWPC:
1208 save_cpu_state(ctx, 0);
1209 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1210 gen_op_addr_add(ctx, t0, t0, t1);
1211 op_ld_lw(t0, t0, ctx);
1212 gen_store_gpr(t0, rt);
1213 opn = "lwpc";
1214 break;
1215 case OPC_LW:
1216 save_cpu_state(ctx, 0);
1217 op_ld_lw(t0, t0, ctx);
1218 gen_store_gpr(t0, rt);
1219 opn = "lw";
1220 break;
1221 case OPC_LH:
1222 save_cpu_state(ctx, 0);
1223 op_ld_lh(t0, t0, ctx);
1224 gen_store_gpr(t0, rt);
1225 opn = "lh";
1226 break;
1227 case OPC_LHU:
1228 save_cpu_state(ctx, 0);
1229 op_ld_lhu(t0, t0, ctx);
1230 gen_store_gpr(t0, rt);
1231 opn = "lhu";
1232 break;
1233 case OPC_LB:
1234 save_cpu_state(ctx, 0);
1235 op_ld_lb(t0, t0, ctx);
1236 gen_store_gpr(t0, rt);
1237 opn = "lb";
1238 break;
1239 case OPC_LBU:
1240 save_cpu_state(ctx, 0);
1241 op_ld_lbu(t0, t0, ctx);
1242 gen_store_gpr(t0, rt);
1243 opn = "lbu";
1244 break;
1245 case OPC_LWL:
1246 save_cpu_state(ctx, 1);
1247 gen_load_gpr(t1, rt);
1248 gen_helper_1e2i(lwl, t1, t1, t0, ctx->mem_idx);
1249 gen_store_gpr(t1, rt);
1250 opn = "lwl";
1251 break;
1252 case OPC_LWR:
1253 save_cpu_state(ctx, 1);
1254 gen_load_gpr(t1, rt);
1255 gen_helper_1e2i(lwr, t1, t1, t0, ctx->mem_idx);
1256 gen_store_gpr(t1, rt);
1257 opn = "lwr";
1258 break;
1259 case OPC_LL:
1260 save_cpu_state(ctx, 1);
1261 op_ld_ll(t0, t0, ctx);
1262 gen_store_gpr(t0, rt);
1263 opn = "ll";
1264 break;
1266 (void)opn; /* avoid a compiler warning */
1267 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1268 tcg_temp_free(t0);
1269 tcg_temp_free(t1);
1272 /* Store */
1273 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1274 int base, int16_t offset)
1276 const char *opn = "st";
1277 TCGv t0 = tcg_temp_new();
1278 TCGv t1 = tcg_temp_new();
1280 gen_base_offset_addr(ctx, t0, base, offset);
1281 gen_load_gpr(t1, rt);
1282 switch (opc) {
1283 #if defined(TARGET_MIPS64)
1284 case OPC_SD:
1285 save_cpu_state(ctx, 0);
1286 op_st_sd(t1, t0, ctx);
1287 opn = "sd";
1288 break;
1289 case OPC_SDL:
1290 save_cpu_state(ctx, 1);
1291 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
1292 opn = "sdl";
1293 break;
1294 case OPC_SDR:
1295 save_cpu_state(ctx, 1);
1296 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
1297 opn = "sdr";
1298 break;
1299 #endif
1300 case OPC_SW:
1301 save_cpu_state(ctx, 0);
1302 op_st_sw(t1, t0, ctx);
1303 opn = "sw";
1304 break;
1305 case OPC_SH:
1306 save_cpu_state(ctx, 0);
1307 op_st_sh(t1, t0, ctx);
1308 opn = "sh";
1309 break;
1310 case OPC_SB:
1311 save_cpu_state(ctx, 0);
1312 op_st_sb(t1, t0, ctx);
1313 opn = "sb";
1314 break;
1315 case OPC_SWL:
1316 save_cpu_state(ctx, 1);
1317 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
1318 opn = "swl";
1319 break;
1320 case OPC_SWR:
1321 save_cpu_state(ctx, 1);
1322 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
1323 opn = "swr";
1324 break;
1326 (void)opn; /* avoid a compiler warning */
1327 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1328 tcg_temp_free(t0);
1329 tcg_temp_free(t1);
1333 /* Store conditional */
1334 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1335 int base, int16_t offset)
1337 const char *opn = "st_cond";
1338 TCGv t0, t1;
1340 t0 = tcg_temp_local_new();
1342 gen_base_offset_addr(ctx, t0, base, offset);
1343 /* Don't do NOP if destination is zero: we must perform the actual
1344 memory access. */
1346 t1 = tcg_temp_local_new();
1347 gen_load_gpr(t1, rt);
1348 switch (opc) {
1349 #if defined(TARGET_MIPS64)
1350 case OPC_SCD:
1351 save_cpu_state(ctx, 1);
1352 op_st_scd(t1, t0, rt, ctx);
1353 opn = "scd";
1354 break;
1355 #endif
1356 case OPC_SC:
1357 save_cpu_state(ctx, 1);
1358 op_st_sc(t1, t0, rt, ctx);
1359 opn = "sc";
1360 break;
1362 (void)opn; /* avoid a compiler warning */
1363 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1364 tcg_temp_free(t1);
1365 tcg_temp_free(t0);
1368 /* Load and store */
1369 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1370 int base, int16_t offset)
1372 const char *opn = "flt_ldst";
1373 TCGv t0 = tcg_temp_new();
1375 gen_base_offset_addr(ctx, t0, base, offset);
1376 /* Don't do NOP if destination is zero: we must perform the actual
1377 memory access. */
1378 switch (opc) {
1379 case OPC_LWC1:
1381 TCGv_i32 fp0 = tcg_temp_new_i32();
1383 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1384 tcg_gen_trunc_tl_i32(fp0, t0);
1385 gen_store_fpr32(fp0, ft);
1386 tcg_temp_free_i32(fp0);
1388 opn = "lwc1";
1389 break;
1390 case OPC_SWC1:
1392 TCGv_i32 fp0 = tcg_temp_new_i32();
1393 TCGv t1 = tcg_temp_new();
1395 gen_load_fpr32(fp0, ft);
1396 tcg_gen_extu_i32_tl(t1, fp0);
1397 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1398 tcg_temp_free(t1);
1399 tcg_temp_free_i32(fp0);
1401 opn = "swc1";
1402 break;
1403 case OPC_LDC1:
1405 TCGv_i64 fp0 = tcg_temp_new_i64();
1407 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1408 gen_store_fpr64(ctx, fp0, ft);
1409 tcg_temp_free_i64(fp0);
1411 opn = "ldc1";
1412 break;
1413 case OPC_SDC1:
1415 TCGv_i64 fp0 = tcg_temp_new_i64();
1417 gen_load_fpr64(ctx, fp0, ft);
1418 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1419 tcg_temp_free_i64(fp0);
1421 opn = "sdc1";
1422 break;
1423 default:
1424 MIPS_INVAL(opn);
1425 generate_exception(ctx, EXCP_RI);
1426 goto out;
1428 (void)opn; /* avoid a compiler warning */
1429 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1430 out:
1431 tcg_temp_free(t0);
1434 static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
1435 uint32_t op, int rt, int rs, int16_t imm)
1437 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1438 check_cp1_enabled(ctx);
1439 gen_flt_ldst(ctx, op, rt, rs, imm);
1440 } else {
1441 generate_exception_err(ctx, EXCP_CpU, 1);
1445 /* Arithmetic with immediate operand */
1446 static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1447 int rt, int rs, int16_t imm)
1449 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1450 const char *opn = "imm arith";
1452 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1453 /* If no destination, treat it as a NOP.
1454 For addi, we must generate the overflow exception when needed. */
1455 MIPS_DEBUG("NOP");
1456 return;
1458 switch (opc) {
1459 case OPC_ADDI:
1461 TCGv t0 = tcg_temp_local_new();
1462 TCGv t1 = tcg_temp_new();
1463 TCGv t2 = tcg_temp_new();
1464 int l1 = gen_new_label();
1466 gen_load_gpr(t1, rs);
1467 tcg_gen_addi_tl(t0, t1, uimm);
1468 tcg_gen_ext32s_tl(t0, t0);
1470 tcg_gen_xori_tl(t1, t1, ~uimm);
1471 tcg_gen_xori_tl(t2, t0, uimm);
1472 tcg_gen_and_tl(t1, t1, t2);
1473 tcg_temp_free(t2);
1474 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1475 tcg_temp_free(t1);
1476 /* operands of same sign, result different sign */
1477 generate_exception(ctx, EXCP_OVERFLOW);
1478 gen_set_label(l1);
1479 tcg_gen_ext32s_tl(t0, t0);
1480 gen_store_gpr(t0, rt);
1481 tcg_temp_free(t0);
1483 opn = "addi";
1484 break;
1485 case OPC_ADDIU:
1486 if (rs != 0) {
1487 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1488 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1489 } else {
1490 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1492 opn = "addiu";
1493 break;
1494 #if defined(TARGET_MIPS64)
1495 case OPC_DADDI:
1497 TCGv t0 = tcg_temp_local_new();
1498 TCGv t1 = tcg_temp_new();
1499 TCGv t2 = tcg_temp_new();
1500 int l1 = gen_new_label();
1502 gen_load_gpr(t1, rs);
1503 tcg_gen_addi_tl(t0, t1, uimm);
1505 tcg_gen_xori_tl(t1, t1, ~uimm);
1506 tcg_gen_xori_tl(t2, t0, uimm);
1507 tcg_gen_and_tl(t1, t1, t2);
1508 tcg_temp_free(t2);
1509 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1510 tcg_temp_free(t1);
1511 /* operands of same sign, result different sign */
1512 generate_exception(ctx, EXCP_OVERFLOW);
1513 gen_set_label(l1);
1514 gen_store_gpr(t0, rt);
1515 tcg_temp_free(t0);
1517 opn = "daddi";
1518 break;
1519 case OPC_DADDIU:
1520 if (rs != 0) {
1521 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1522 } else {
1523 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1525 opn = "daddiu";
1526 break;
1527 #endif
1529 (void)opn; /* avoid a compiler warning */
1530 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1533 /* Logic with immediate operand */
1534 static void gen_logic_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1535 int rt, int rs, int16_t imm)
1537 target_ulong uimm;
1538 const char *opn = "imm logic";
1540 if (rt == 0) {
1541 /* If no destination, treat it as a NOP. */
1542 MIPS_DEBUG("NOP");
1543 return;
1545 uimm = (uint16_t)imm;
1546 switch (opc) {
1547 case OPC_ANDI:
1548 if (likely(rs != 0))
1549 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1550 else
1551 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1552 opn = "andi";
1553 break;
1554 case OPC_ORI:
1555 if (rs != 0)
1556 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1557 else
1558 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1559 opn = "ori";
1560 break;
1561 case OPC_XORI:
1562 if (likely(rs != 0))
1563 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1564 else
1565 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1566 opn = "xori";
1567 break;
1568 case OPC_LUI:
1569 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1570 opn = "lui";
1571 break;
1573 (void)opn; /* avoid a compiler warning */
1574 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1577 /* Set on less than with immediate operand */
1578 static void gen_slt_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1579 int rt, int rs, int16_t imm)
1581 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1582 const char *opn = "imm arith";
1583 TCGv t0;
1585 if (rt == 0) {
1586 /* If no destination, treat it as a NOP. */
1587 MIPS_DEBUG("NOP");
1588 return;
1590 t0 = tcg_temp_new();
1591 gen_load_gpr(t0, rs);
1592 switch (opc) {
1593 case OPC_SLTI:
1594 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1595 opn = "slti";
1596 break;
1597 case OPC_SLTIU:
1598 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1599 opn = "sltiu";
1600 break;
1602 (void)opn; /* avoid a compiler warning */
1603 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1604 tcg_temp_free(t0);
1607 /* Shifts with immediate operand */
1608 static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1609 int rt, int rs, int16_t imm)
1611 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1612 const char *opn = "imm shift";
1613 TCGv t0;
1615 if (rt == 0) {
1616 /* If no destination, treat it as a NOP. */
1617 MIPS_DEBUG("NOP");
1618 return;
1621 t0 = tcg_temp_new();
1622 gen_load_gpr(t0, rs);
1623 switch (opc) {
1624 case OPC_SLL:
1625 tcg_gen_shli_tl(t0, t0, uimm);
1626 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1627 opn = "sll";
1628 break;
1629 case OPC_SRA:
1630 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1631 opn = "sra";
1632 break;
1633 case OPC_SRL:
1634 if (uimm != 0) {
1635 tcg_gen_ext32u_tl(t0, t0);
1636 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1637 } else {
1638 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1640 opn = "srl";
1641 break;
1642 case OPC_ROTR:
1643 if (uimm != 0) {
1644 TCGv_i32 t1 = tcg_temp_new_i32();
1646 tcg_gen_trunc_tl_i32(t1, t0);
1647 tcg_gen_rotri_i32(t1, t1, uimm);
1648 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1649 tcg_temp_free_i32(t1);
1650 } else {
1651 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1653 opn = "rotr";
1654 break;
1655 #if defined(TARGET_MIPS64)
1656 case OPC_DSLL:
1657 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1658 opn = "dsll";
1659 break;
1660 case OPC_DSRA:
1661 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1662 opn = "dsra";
1663 break;
1664 case OPC_DSRL:
1665 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1666 opn = "dsrl";
1667 break;
1668 case OPC_DROTR:
1669 if (uimm != 0) {
1670 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1671 } else {
1672 tcg_gen_mov_tl(cpu_gpr[rt], t0);
1674 opn = "drotr";
1675 break;
1676 case OPC_DSLL32:
1677 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1678 opn = "dsll32";
1679 break;
1680 case OPC_DSRA32:
1681 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1682 opn = "dsra32";
1683 break;
1684 case OPC_DSRL32:
1685 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1686 opn = "dsrl32";
1687 break;
1688 case OPC_DROTR32:
1689 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1690 opn = "drotr32";
1691 break;
1692 #endif
1694 (void)opn; /* avoid a compiler warning */
1695 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1696 tcg_temp_free(t0);
1699 /* Arithmetic */
1700 static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1701 int rd, int rs, int rt)
1703 const char *opn = "arith";
1705 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1706 && opc != OPC_DADD && opc != OPC_DSUB) {
1707 /* If no destination, treat it as a NOP.
1708 For add & sub, we must generate the overflow exception when needed. */
1709 MIPS_DEBUG("NOP");
1710 return;
1713 switch (opc) {
1714 case OPC_ADD:
1716 TCGv t0 = tcg_temp_local_new();
1717 TCGv t1 = tcg_temp_new();
1718 TCGv t2 = tcg_temp_new();
1719 int l1 = gen_new_label();
1721 gen_load_gpr(t1, rs);
1722 gen_load_gpr(t2, rt);
1723 tcg_gen_add_tl(t0, t1, t2);
1724 tcg_gen_ext32s_tl(t0, t0);
1725 tcg_gen_xor_tl(t1, t1, t2);
1726 tcg_gen_xor_tl(t2, t0, t2);
1727 tcg_gen_andc_tl(t1, t2, t1);
1728 tcg_temp_free(t2);
1729 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1730 tcg_temp_free(t1);
1731 /* operands of same sign, result different sign */
1732 generate_exception(ctx, EXCP_OVERFLOW);
1733 gen_set_label(l1);
1734 gen_store_gpr(t0, rd);
1735 tcg_temp_free(t0);
1737 opn = "add";
1738 break;
1739 case OPC_ADDU:
1740 if (rs != 0 && rt != 0) {
1741 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1742 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1743 } else if (rs == 0 && rt != 0) {
1744 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1745 } else if (rs != 0 && rt == 0) {
1746 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1747 } else {
1748 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1750 opn = "addu";
1751 break;
1752 case OPC_SUB:
1754 TCGv t0 = tcg_temp_local_new();
1755 TCGv t1 = tcg_temp_new();
1756 TCGv t2 = tcg_temp_new();
1757 int l1 = gen_new_label();
1759 gen_load_gpr(t1, rs);
1760 gen_load_gpr(t2, rt);
1761 tcg_gen_sub_tl(t0, t1, t2);
1762 tcg_gen_ext32s_tl(t0, t0);
1763 tcg_gen_xor_tl(t2, t1, t2);
1764 tcg_gen_xor_tl(t1, t0, t1);
1765 tcg_gen_and_tl(t1, t1, t2);
1766 tcg_temp_free(t2);
1767 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1768 tcg_temp_free(t1);
1769 /* operands of different sign, first operand and result different sign */
1770 generate_exception(ctx, EXCP_OVERFLOW);
1771 gen_set_label(l1);
1772 gen_store_gpr(t0, rd);
1773 tcg_temp_free(t0);
1775 opn = "sub";
1776 break;
1777 case OPC_SUBU:
1778 if (rs != 0 && rt != 0) {
1779 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1780 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1781 } else if (rs == 0 && rt != 0) {
1782 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1783 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1784 } else if (rs != 0 && rt == 0) {
1785 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1786 } else {
1787 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1789 opn = "subu";
1790 break;
1791 #if defined(TARGET_MIPS64)
1792 case OPC_DADD:
1794 TCGv t0 = tcg_temp_local_new();
1795 TCGv t1 = tcg_temp_new();
1796 TCGv t2 = tcg_temp_new();
1797 int l1 = gen_new_label();
1799 gen_load_gpr(t1, rs);
1800 gen_load_gpr(t2, rt);
1801 tcg_gen_add_tl(t0, t1, t2);
1802 tcg_gen_xor_tl(t1, t1, t2);
1803 tcg_gen_xor_tl(t2, t0, t2);
1804 tcg_gen_andc_tl(t1, t2, t1);
1805 tcg_temp_free(t2);
1806 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1807 tcg_temp_free(t1);
1808 /* operands of same sign, result different sign */
1809 generate_exception(ctx, EXCP_OVERFLOW);
1810 gen_set_label(l1);
1811 gen_store_gpr(t0, rd);
1812 tcg_temp_free(t0);
1814 opn = "dadd";
1815 break;
1816 case OPC_DADDU:
1817 if (rs != 0 && rt != 0) {
1818 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1819 } else if (rs == 0 && rt != 0) {
1820 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1821 } else if (rs != 0 && rt == 0) {
1822 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1823 } else {
1824 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1826 opn = "daddu";
1827 break;
1828 case OPC_DSUB:
1830 TCGv t0 = tcg_temp_local_new();
1831 TCGv t1 = tcg_temp_new();
1832 TCGv t2 = tcg_temp_new();
1833 int l1 = gen_new_label();
1835 gen_load_gpr(t1, rs);
1836 gen_load_gpr(t2, rt);
1837 tcg_gen_sub_tl(t0, t1, t2);
1838 tcg_gen_xor_tl(t2, t1, t2);
1839 tcg_gen_xor_tl(t1, t0, t1);
1840 tcg_gen_and_tl(t1, t1, t2);
1841 tcg_temp_free(t2);
1842 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1843 tcg_temp_free(t1);
1844 /* operands of different sign, first operand and result different sign */
1845 generate_exception(ctx, EXCP_OVERFLOW);
1846 gen_set_label(l1);
1847 gen_store_gpr(t0, rd);
1848 tcg_temp_free(t0);
1850 opn = "dsub";
1851 break;
1852 case OPC_DSUBU:
1853 if (rs != 0 && rt != 0) {
1854 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1855 } else if (rs == 0 && rt != 0) {
1856 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1857 } else if (rs != 0 && rt == 0) {
1858 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1859 } else {
1860 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1862 opn = "dsubu";
1863 break;
1864 #endif
1865 case OPC_MUL:
1866 if (likely(rs != 0 && rt != 0)) {
1867 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1868 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1869 } else {
1870 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1872 opn = "mul";
1873 break;
1875 (void)opn; /* avoid a compiler warning */
1876 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1879 /* Conditional move */
1880 static void gen_cond_move(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1881 int rd, int rs, int rt)
1883 const char *opn = "cond move";
1884 int l1;
1886 if (rd == 0) {
1887 /* If no destination, treat it as a NOP.
1888 For add & sub, we must generate the overflow exception when needed. */
1889 MIPS_DEBUG("NOP");
1890 return;
1893 l1 = gen_new_label();
1894 switch (opc) {
1895 case OPC_MOVN:
1896 if (likely(rt != 0))
1897 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1898 else
1899 tcg_gen_br(l1);
1900 opn = "movn";
1901 break;
1902 case OPC_MOVZ:
1903 if (likely(rt != 0))
1904 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1905 opn = "movz";
1906 break;
1908 if (rs != 0)
1909 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1910 else
1911 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1912 gen_set_label(l1);
1914 (void)opn; /* avoid a compiler warning */
1915 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1918 /* Logic */
1919 static void gen_logic(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1920 int rd, int rs, int rt)
1922 const char *opn = "logic";
1924 if (rd == 0) {
1925 /* If no destination, treat it as a NOP. */
1926 MIPS_DEBUG("NOP");
1927 return;
1930 switch (opc) {
1931 case OPC_AND:
1932 if (likely(rs != 0 && rt != 0)) {
1933 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1934 } else {
1935 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1937 opn = "and";
1938 break;
1939 case OPC_NOR:
1940 if (rs != 0 && rt != 0) {
1941 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1942 } else if (rs == 0 && rt != 0) {
1943 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1944 } else if (rs != 0 && rt == 0) {
1945 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1946 } else {
1947 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1949 opn = "nor";
1950 break;
1951 case OPC_OR:
1952 if (likely(rs != 0 && rt != 0)) {
1953 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1954 } else if (rs == 0 && rt != 0) {
1955 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1956 } else if (rs != 0 && rt == 0) {
1957 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1958 } else {
1959 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1961 opn = "or";
1962 break;
1963 case OPC_XOR:
1964 if (likely(rs != 0 && rt != 0)) {
1965 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1966 } else if (rs == 0 && rt != 0) {
1967 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1968 } else if (rs != 0 && rt == 0) {
1969 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1970 } else {
1971 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1973 opn = "xor";
1974 break;
1976 (void)opn; /* avoid a compiler warning */
1977 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1980 /* Set on lower than */
1981 static void gen_slt(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1982 int rd, int rs, int rt)
1984 const char *opn = "slt";
1985 TCGv t0, t1;
1987 if (rd == 0) {
1988 /* If no destination, treat it as a NOP. */
1989 MIPS_DEBUG("NOP");
1990 return;
1993 t0 = tcg_temp_new();
1994 t1 = tcg_temp_new();
1995 gen_load_gpr(t0, rs);
1996 gen_load_gpr(t1, rt);
1997 switch (opc) {
1998 case OPC_SLT:
1999 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2000 opn = "slt";
2001 break;
2002 case OPC_SLTU:
2003 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2004 opn = "sltu";
2005 break;
2007 (void)opn; /* avoid a compiler warning */
2008 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2009 tcg_temp_free(t0);
2010 tcg_temp_free(t1);
2013 /* Shifts */
2014 static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
2015 int rd, int rs, int rt)
2017 const char *opn = "shifts";
2018 TCGv t0, t1;
2020 if (rd == 0) {
2021 /* If no destination, treat it as a NOP.
2022 For add & sub, we must generate the overflow exception when needed. */
2023 MIPS_DEBUG("NOP");
2024 return;
2027 t0 = tcg_temp_new();
2028 t1 = tcg_temp_new();
2029 gen_load_gpr(t0, rs);
2030 gen_load_gpr(t1, rt);
2031 switch (opc) {
2032 case OPC_SLLV:
2033 tcg_gen_andi_tl(t0, t0, 0x1f);
2034 tcg_gen_shl_tl(t0, t1, t0);
2035 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2036 opn = "sllv";
2037 break;
2038 case OPC_SRAV:
2039 tcg_gen_andi_tl(t0, t0, 0x1f);
2040 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2041 opn = "srav";
2042 break;
2043 case OPC_SRLV:
2044 tcg_gen_ext32u_tl(t1, t1);
2045 tcg_gen_andi_tl(t0, t0, 0x1f);
2046 tcg_gen_shr_tl(t0, t1, t0);
2047 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2048 opn = "srlv";
2049 break;
2050 case OPC_ROTRV:
2052 TCGv_i32 t2 = tcg_temp_new_i32();
2053 TCGv_i32 t3 = tcg_temp_new_i32();
2055 tcg_gen_trunc_tl_i32(t2, t0);
2056 tcg_gen_trunc_tl_i32(t3, t1);
2057 tcg_gen_andi_i32(t2, t2, 0x1f);
2058 tcg_gen_rotr_i32(t2, t3, t2);
2059 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2060 tcg_temp_free_i32(t2);
2061 tcg_temp_free_i32(t3);
2062 opn = "rotrv";
2064 break;
2065 #if defined(TARGET_MIPS64)
2066 case OPC_DSLLV:
2067 tcg_gen_andi_tl(t0, t0, 0x3f);
2068 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2069 opn = "dsllv";
2070 break;
2071 case OPC_DSRAV:
2072 tcg_gen_andi_tl(t0, t0, 0x3f);
2073 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2074 opn = "dsrav";
2075 break;
2076 case OPC_DSRLV:
2077 tcg_gen_andi_tl(t0, t0, 0x3f);
2078 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2079 opn = "dsrlv";
2080 break;
2081 case OPC_DROTRV:
2082 tcg_gen_andi_tl(t0, t0, 0x3f);
2083 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2084 opn = "drotrv";
2085 break;
2086 #endif
2088 (void)opn; /* avoid a compiler warning */
2089 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2090 tcg_temp_free(t0);
2091 tcg_temp_free(t1);
2094 /* Arithmetic on HI/LO registers */
2095 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
2097 const char *opn = "hilo";
2099 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
2100 /* Treat as NOP. */
2101 MIPS_DEBUG("NOP");
2102 return;
2104 switch (opc) {
2105 case OPC_MFHI:
2106 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
2107 opn = "mfhi";
2108 break;
2109 case OPC_MFLO:
2110 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
2111 opn = "mflo";
2112 break;
2113 case OPC_MTHI:
2114 if (reg != 0)
2115 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
2116 else
2117 tcg_gen_movi_tl(cpu_HI[0], 0);
2118 opn = "mthi";
2119 break;
2120 case OPC_MTLO:
2121 if (reg != 0)
2122 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2123 else
2124 tcg_gen_movi_tl(cpu_LO[0], 0);
2125 opn = "mtlo";
2126 break;
2128 (void)opn; /* avoid a compiler warning */
2129 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2132 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
2133 int rs, int rt)
2135 const char *opn = "mul/div";
2136 TCGv t0, t1;
2138 switch (opc) {
2139 case OPC_DIV:
2140 case OPC_DIVU:
2141 #if defined(TARGET_MIPS64)
2142 case OPC_DDIV:
2143 case OPC_DDIVU:
2144 #endif
2145 t0 = tcg_temp_local_new();
2146 t1 = tcg_temp_local_new();
2147 break;
2148 default:
2149 t0 = tcg_temp_new();
2150 t1 = tcg_temp_new();
2151 break;
2154 gen_load_gpr(t0, rs);
2155 gen_load_gpr(t1, rt);
2156 switch (opc) {
2157 case OPC_DIV:
2159 int l1 = gen_new_label();
2160 int l2 = gen_new_label();
2162 tcg_gen_ext32s_tl(t0, t0);
2163 tcg_gen_ext32s_tl(t1, t1);
2164 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2165 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2166 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2168 tcg_gen_mov_tl(cpu_LO[0], t0);
2169 tcg_gen_movi_tl(cpu_HI[0], 0);
2170 tcg_gen_br(l1);
2171 gen_set_label(l2);
2172 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2173 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2174 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2175 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2176 gen_set_label(l1);
2178 opn = "div";
2179 break;
2180 case OPC_DIVU:
2182 int l1 = gen_new_label();
2184 tcg_gen_ext32u_tl(t0, t0);
2185 tcg_gen_ext32u_tl(t1, t1);
2186 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2187 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2188 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2189 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2190 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2191 gen_set_label(l1);
2193 opn = "divu";
2194 break;
2195 case OPC_MULT:
2197 TCGv_i64 t2 = tcg_temp_new_i64();
2198 TCGv_i64 t3 = tcg_temp_new_i64();
2200 tcg_gen_ext_tl_i64(t2, t0);
2201 tcg_gen_ext_tl_i64(t3, t1);
2202 tcg_gen_mul_i64(t2, t2, t3);
2203 tcg_temp_free_i64(t3);
2204 tcg_gen_trunc_i64_tl(t0, t2);
2205 tcg_gen_shri_i64(t2, t2, 32);
2206 tcg_gen_trunc_i64_tl(t1, t2);
2207 tcg_temp_free_i64(t2);
2208 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2209 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2211 opn = "mult";
2212 break;
2213 case OPC_MULTU:
2215 TCGv_i64 t2 = tcg_temp_new_i64();
2216 TCGv_i64 t3 = tcg_temp_new_i64();
2218 tcg_gen_ext32u_tl(t0, t0);
2219 tcg_gen_ext32u_tl(t1, t1);
2220 tcg_gen_extu_tl_i64(t2, t0);
2221 tcg_gen_extu_tl_i64(t3, t1);
2222 tcg_gen_mul_i64(t2, t2, t3);
2223 tcg_temp_free_i64(t3);
2224 tcg_gen_trunc_i64_tl(t0, t2);
2225 tcg_gen_shri_i64(t2, t2, 32);
2226 tcg_gen_trunc_i64_tl(t1, t2);
2227 tcg_temp_free_i64(t2);
2228 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2229 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2231 opn = "multu";
2232 break;
2233 #if defined(TARGET_MIPS64)
2234 case OPC_DDIV:
2236 int l1 = gen_new_label();
2237 int l2 = gen_new_label();
2239 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2240 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2241 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2242 tcg_gen_mov_tl(cpu_LO[0], t0);
2243 tcg_gen_movi_tl(cpu_HI[0], 0);
2244 tcg_gen_br(l1);
2245 gen_set_label(l2);
2246 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2247 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2248 gen_set_label(l1);
2250 opn = "ddiv";
2251 break;
2252 case OPC_DDIVU:
2254 int l1 = gen_new_label();
2256 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2257 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2258 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2259 gen_set_label(l1);
2261 opn = "ddivu";
2262 break;
2263 case OPC_DMULT:
2264 gen_helper_dmult(cpu_env, t0, t1);
2265 opn = "dmult";
2266 break;
2267 case OPC_DMULTU:
2268 gen_helper_dmultu(cpu_env, t0, t1);
2269 opn = "dmultu";
2270 break;
2271 #endif
2272 case OPC_MADD:
2274 TCGv_i64 t2 = tcg_temp_new_i64();
2275 TCGv_i64 t3 = tcg_temp_new_i64();
2277 tcg_gen_ext_tl_i64(t2, t0);
2278 tcg_gen_ext_tl_i64(t3, t1);
2279 tcg_gen_mul_i64(t2, t2, t3);
2280 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2281 tcg_gen_add_i64(t2, t2, t3);
2282 tcg_temp_free_i64(t3);
2283 tcg_gen_trunc_i64_tl(t0, t2);
2284 tcg_gen_shri_i64(t2, t2, 32);
2285 tcg_gen_trunc_i64_tl(t1, t2);
2286 tcg_temp_free_i64(t2);
2287 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2288 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2290 opn = "madd";
2291 break;
2292 case OPC_MADDU:
2294 TCGv_i64 t2 = tcg_temp_new_i64();
2295 TCGv_i64 t3 = tcg_temp_new_i64();
2297 tcg_gen_ext32u_tl(t0, t0);
2298 tcg_gen_ext32u_tl(t1, t1);
2299 tcg_gen_extu_tl_i64(t2, t0);
2300 tcg_gen_extu_tl_i64(t3, t1);
2301 tcg_gen_mul_i64(t2, t2, t3);
2302 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2303 tcg_gen_add_i64(t2, t2, t3);
2304 tcg_temp_free_i64(t3);
2305 tcg_gen_trunc_i64_tl(t0, t2);
2306 tcg_gen_shri_i64(t2, t2, 32);
2307 tcg_gen_trunc_i64_tl(t1, t2);
2308 tcg_temp_free_i64(t2);
2309 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2310 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2312 opn = "maddu";
2313 break;
2314 case OPC_MSUB:
2316 TCGv_i64 t2 = tcg_temp_new_i64();
2317 TCGv_i64 t3 = tcg_temp_new_i64();
2319 tcg_gen_ext_tl_i64(t2, t0);
2320 tcg_gen_ext_tl_i64(t3, t1);
2321 tcg_gen_mul_i64(t2, t2, t3);
2322 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2323 tcg_gen_sub_i64(t2, t3, t2);
2324 tcg_temp_free_i64(t3);
2325 tcg_gen_trunc_i64_tl(t0, t2);
2326 tcg_gen_shri_i64(t2, t2, 32);
2327 tcg_gen_trunc_i64_tl(t1, t2);
2328 tcg_temp_free_i64(t2);
2329 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2330 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2332 opn = "msub";
2333 break;
2334 case OPC_MSUBU:
2336 TCGv_i64 t2 = tcg_temp_new_i64();
2337 TCGv_i64 t3 = tcg_temp_new_i64();
2339 tcg_gen_ext32u_tl(t0, t0);
2340 tcg_gen_ext32u_tl(t1, t1);
2341 tcg_gen_extu_tl_i64(t2, t0);
2342 tcg_gen_extu_tl_i64(t3, t1);
2343 tcg_gen_mul_i64(t2, t2, t3);
2344 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2345 tcg_gen_sub_i64(t2, t3, t2);
2346 tcg_temp_free_i64(t3);
2347 tcg_gen_trunc_i64_tl(t0, t2);
2348 tcg_gen_shri_i64(t2, t2, 32);
2349 tcg_gen_trunc_i64_tl(t1, t2);
2350 tcg_temp_free_i64(t2);
2351 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2352 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2354 opn = "msubu";
2355 break;
2356 default:
2357 MIPS_INVAL(opn);
2358 generate_exception(ctx, EXCP_RI);
2359 goto out;
2361 (void)opn; /* avoid a compiler warning */
2362 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2363 out:
2364 tcg_temp_free(t0);
2365 tcg_temp_free(t1);
2368 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2369 int rd, int rs, int rt)
2371 const char *opn = "mul vr54xx";
2372 TCGv t0 = tcg_temp_new();
2373 TCGv t1 = tcg_temp_new();
2375 gen_load_gpr(t0, rs);
2376 gen_load_gpr(t1, rt);
2378 switch (opc) {
2379 case OPC_VR54XX_MULS:
2380 gen_helper_muls(t0, cpu_env, t0, t1);
2381 opn = "muls";
2382 break;
2383 case OPC_VR54XX_MULSU:
2384 gen_helper_mulsu(t0, cpu_env, t0, t1);
2385 opn = "mulsu";
2386 break;
2387 case OPC_VR54XX_MACC:
2388 gen_helper_macc(t0, cpu_env, t0, t1);
2389 opn = "macc";
2390 break;
2391 case OPC_VR54XX_MACCU:
2392 gen_helper_maccu(t0, cpu_env, t0, t1);
2393 opn = "maccu";
2394 break;
2395 case OPC_VR54XX_MSAC:
2396 gen_helper_msac(t0, cpu_env, t0, t1);
2397 opn = "msac";
2398 break;
2399 case OPC_VR54XX_MSACU:
2400 gen_helper_msacu(t0, cpu_env, t0, t1);
2401 opn = "msacu";
2402 break;
2403 case OPC_VR54XX_MULHI:
2404 gen_helper_mulhi(t0, cpu_env, t0, t1);
2405 opn = "mulhi";
2406 break;
2407 case OPC_VR54XX_MULHIU:
2408 gen_helper_mulhiu(t0, cpu_env, t0, t1);
2409 opn = "mulhiu";
2410 break;
2411 case OPC_VR54XX_MULSHI:
2412 gen_helper_mulshi(t0, cpu_env, t0, t1);
2413 opn = "mulshi";
2414 break;
2415 case OPC_VR54XX_MULSHIU:
2416 gen_helper_mulshiu(t0, cpu_env, t0, t1);
2417 opn = "mulshiu";
2418 break;
2419 case OPC_VR54XX_MACCHI:
2420 gen_helper_macchi(t0, cpu_env, t0, t1);
2421 opn = "macchi";
2422 break;
2423 case OPC_VR54XX_MACCHIU:
2424 gen_helper_macchiu(t0, cpu_env, t0, t1);
2425 opn = "macchiu";
2426 break;
2427 case OPC_VR54XX_MSACHI:
2428 gen_helper_msachi(t0, cpu_env, t0, t1);
2429 opn = "msachi";
2430 break;
2431 case OPC_VR54XX_MSACHIU:
2432 gen_helper_msachiu(t0, cpu_env, t0, t1);
2433 opn = "msachiu";
2434 break;
2435 default:
2436 MIPS_INVAL("mul vr54xx");
2437 generate_exception(ctx, EXCP_RI);
2438 goto out;
2440 gen_store_gpr(t0, rd);
2441 (void)opn; /* avoid a compiler warning */
2442 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2444 out:
2445 tcg_temp_free(t0);
2446 tcg_temp_free(t1);
2449 static void gen_cl (DisasContext *ctx, uint32_t opc,
2450 int rd, int rs)
2452 const char *opn = "CLx";
2453 TCGv t0;
2455 if (rd == 0) {
2456 /* Treat as NOP. */
2457 MIPS_DEBUG("NOP");
2458 return;
2460 t0 = tcg_temp_new();
2461 gen_load_gpr(t0, rs);
2462 switch (opc) {
2463 case OPC_CLO:
2464 gen_helper_clo(cpu_gpr[rd], t0);
2465 opn = "clo";
2466 break;
2467 case OPC_CLZ:
2468 gen_helper_clz(cpu_gpr[rd], t0);
2469 opn = "clz";
2470 break;
2471 #if defined(TARGET_MIPS64)
2472 case OPC_DCLO:
2473 gen_helper_dclo(cpu_gpr[rd], t0);
2474 opn = "dclo";
2475 break;
2476 case OPC_DCLZ:
2477 gen_helper_dclz(cpu_gpr[rd], t0);
2478 opn = "dclz";
2479 break;
2480 #endif
2482 (void)opn; /* avoid a compiler warning */
2483 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2484 tcg_temp_free(t0);
2487 /* Godson integer instructions */
2488 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
2489 int rd, int rs, int rt)
2491 const char *opn = "loongson";
2492 TCGv t0, t1;
2494 if (rd == 0) {
2495 /* Treat as NOP. */
2496 MIPS_DEBUG("NOP");
2497 return;
2500 switch (opc) {
2501 case OPC_MULT_G_2E:
2502 case OPC_MULT_G_2F:
2503 case OPC_MULTU_G_2E:
2504 case OPC_MULTU_G_2F:
2505 #if defined(TARGET_MIPS64)
2506 case OPC_DMULT_G_2E:
2507 case OPC_DMULT_G_2F:
2508 case OPC_DMULTU_G_2E:
2509 case OPC_DMULTU_G_2F:
2510 #endif
2511 t0 = tcg_temp_new();
2512 t1 = tcg_temp_new();
2513 break;
2514 default:
2515 t0 = tcg_temp_local_new();
2516 t1 = tcg_temp_local_new();
2517 break;
2520 gen_load_gpr(t0, rs);
2521 gen_load_gpr(t1, rt);
2523 switch (opc) {
2524 case OPC_MULT_G_2E:
2525 case OPC_MULT_G_2F:
2526 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2527 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2528 opn = "mult.g";
2529 break;
2530 case OPC_MULTU_G_2E:
2531 case OPC_MULTU_G_2F:
2532 tcg_gen_ext32u_tl(t0, t0);
2533 tcg_gen_ext32u_tl(t1, t1);
2534 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2535 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2536 opn = "multu.g";
2537 break;
2538 case OPC_DIV_G_2E:
2539 case OPC_DIV_G_2F:
2541 int l1 = gen_new_label();
2542 int l2 = gen_new_label();
2543 int l3 = gen_new_label();
2544 tcg_gen_ext32s_tl(t0, t0);
2545 tcg_gen_ext32s_tl(t1, t1);
2546 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2547 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2548 tcg_gen_br(l3);
2549 gen_set_label(l1);
2550 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2551 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2552 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2553 tcg_gen_br(l3);
2554 gen_set_label(l2);
2555 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2556 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2557 gen_set_label(l3);
2559 opn = "div.g";
2560 break;
2561 case OPC_DIVU_G_2E:
2562 case OPC_DIVU_G_2F:
2564 int l1 = gen_new_label();
2565 int l2 = gen_new_label();
2566 tcg_gen_ext32u_tl(t0, t0);
2567 tcg_gen_ext32u_tl(t1, t1);
2568 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2569 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2570 tcg_gen_br(l2);
2571 gen_set_label(l1);
2572 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2573 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2574 gen_set_label(l2);
2576 opn = "divu.g";
2577 break;
2578 case OPC_MOD_G_2E:
2579 case OPC_MOD_G_2F:
2581 int l1 = gen_new_label();
2582 int l2 = gen_new_label();
2583 int l3 = gen_new_label();
2584 tcg_gen_ext32u_tl(t0, t0);
2585 tcg_gen_ext32u_tl(t1, t1);
2586 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2587 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2588 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2589 gen_set_label(l1);
2590 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2591 tcg_gen_br(l3);
2592 gen_set_label(l2);
2593 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2594 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2595 gen_set_label(l3);
2597 opn = "mod.g";
2598 break;
2599 case OPC_MODU_G_2E:
2600 case OPC_MODU_G_2F:
2602 int l1 = gen_new_label();
2603 int l2 = gen_new_label();
2604 tcg_gen_ext32u_tl(t0, t0);
2605 tcg_gen_ext32u_tl(t1, t1);
2606 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2607 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2608 tcg_gen_br(l2);
2609 gen_set_label(l1);
2610 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2611 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2612 gen_set_label(l2);
2614 opn = "modu.g";
2615 break;
2616 #if defined(TARGET_MIPS64)
2617 case OPC_DMULT_G_2E:
2618 case OPC_DMULT_G_2F:
2619 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2620 opn = "dmult.g";
2621 break;
2622 case OPC_DMULTU_G_2E:
2623 case OPC_DMULTU_G_2F:
2624 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2625 opn = "dmultu.g";
2626 break;
2627 case OPC_DDIV_G_2E:
2628 case OPC_DDIV_G_2F:
2630 int l1 = gen_new_label();
2631 int l2 = gen_new_label();
2632 int l3 = gen_new_label();
2633 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2634 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2635 tcg_gen_br(l3);
2636 gen_set_label(l1);
2637 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2638 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2639 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2640 tcg_gen_br(l3);
2641 gen_set_label(l2);
2642 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2643 gen_set_label(l3);
2645 opn = "ddiv.g";
2646 break;
2647 case OPC_DDIVU_G_2E:
2648 case OPC_DDIVU_G_2F:
2650 int l1 = gen_new_label();
2651 int l2 = gen_new_label();
2652 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2653 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2654 tcg_gen_br(l2);
2655 gen_set_label(l1);
2656 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2657 gen_set_label(l2);
2659 opn = "ddivu.g";
2660 break;
2661 case OPC_DMOD_G_2E:
2662 case OPC_DMOD_G_2F:
2664 int l1 = gen_new_label();
2665 int l2 = gen_new_label();
2666 int l3 = gen_new_label();
2667 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2668 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2669 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2670 gen_set_label(l1);
2671 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2672 tcg_gen_br(l3);
2673 gen_set_label(l2);
2674 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2675 gen_set_label(l3);
2677 opn = "dmod.g";
2678 break;
2679 case OPC_DMODU_G_2E:
2680 case OPC_DMODU_G_2F:
2682 int l1 = gen_new_label();
2683 int l2 = gen_new_label();
2684 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2685 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2686 tcg_gen_br(l2);
2687 gen_set_label(l1);
2688 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2689 gen_set_label(l2);
2691 opn = "dmodu.g";
2692 break;
2693 #endif
2696 (void)opn; /* avoid a compiler warning */
2697 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2698 tcg_temp_free(t0);
2699 tcg_temp_free(t1);
2702 /* Loongson multimedia instructions */
2703 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
2705 const char *opn = "loongson_cp2";
2706 uint32_t opc, shift_max;
2707 TCGv_i64 t0, t1;
2709 opc = MASK_LMI(ctx->opcode);
2710 switch (opc) {
2711 case OPC_ADD_CP2:
2712 case OPC_SUB_CP2:
2713 case OPC_DADD_CP2:
2714 case OPC_DSUB_CP2:
2715 t0 = tcg_temp_local_new_i64();
2716 t1 = tcg_temp_local_new_i64();
2717 break;
2718 default:
2719 t0 = tcg_temp_new_i64();
2720 t1 = tcg_temp_new_i64();
2721 break;
2724 gen_load_fpr64(ctx, t0, rs);
2725 gen_load_fpr64(ctx, t1, rt);
2727 #define LMI_HELPER(UP, LO) \
2728 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
2729 #define LMI_HELPER_1(UP, LO) \
2730 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
2731 #define LMI_DIRECT(UP, LO, OP) \
2732 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
2734 switch (opc) {
2735 LMI_HELPER(PADDSH, paddsh);
2736 LMI_HELPER(PADDUSH, paddush);
2737 LMI_HELPER(PADDH, paddh);
2738 LMI_HELPER(PADDW, paddw);
2739 LMI_HELPER(PADDSB, paddsb);
2740 LMI_HELPER(PADDUSB, paddusb);
2741 LMI_HELPER(PADDB, paddb);
2743 LMI_HELPER(PSUBSH, psubsh);
2744 LMI_HELPER(PSUBUSH, psubush);
2745 LMI_HELPER(PSUBH, psubh);
2746 LMI_HELPER(PSUBW, psubw);
2747 LMI_HELPER(PSUBSB, psubsb);
2748 LMI_HELPER(PSUBUSB, psubusb);
2749 LMI_HELPER(PSUBB, psubb);
2751 LMI_HELPER(PSHUFH, pshufh);
2752 LMI_HELPER(PACKSSWH, packsswh);
2753 LMI_HELPER(PACKSSHB, packsshb);
2754 LMI_HELPER(PACKUSHB, packushb);
2756 LMI_HELPER(PUNPCKLHW, punpcklhw);
2757 LMI_HELPER(PUNPCKHHW, punpckhhw);
2758 LMI_HELPER(PUNPCKLBH, punpcklbh);
2759 LMI_HELPER(PUNPCKHBH, punpckhbh);
2760 LMI_HELPER(PUNPCKLWD, punpcklwd);
2761 LMI_HELPER(PUNPCKHWD, punpckhwd);
2763 LMI_HELPER(PAVGH, pavgh);
2764 LMI_HELPER(PAVGB, pavgb);
2765 LMI_HELPER(PMAXSH, pmaxsh);
2766 LMI_HELPER(PMINSH, pminsh);
2767 LMI_HELPER(PMAXUB, pmaxub);
2768 LMI_HELPER(PMINUB, pminub);
2770 LMI_HELPER(PCMPEQW, pcmpeqw);
2771 LMI_HELPER(PCMPGTW, pcmpgtw);
2772 LMI_HELPER(PCMPEQH, pcmpeqh);
2773 LMI_HELPER(PCMPGTH, pcmpgth);
2774 LMI_HELPER(PCMPEQB, pcmpeqb);
2775 LMI_HELPER(PCMPGTB, pcmpgtb);
2777 LMI_HELPER(PSLLW, psllw);
2778 LMI_HELPER(PSLLH, psllh);
2779 LMI_HELPER(PSRLW, psrlw);
2780 LMI_HELPER(PSRLH, psrlh);
2781 LMI_HELPER(PSRAW, psraw);
2782 LMI_HELPER(PSRAH, psrah);
2784 LMI_HELPER(PMULLH, pmullh);
2785 LMI_HELPER(PMULHH, pmulhh);
2786 LMI_HELPER(PMULHUH, pmulhuh);
2787 LMI_HELPER(PMADDHW, pmaddhw);
2789 LMI_HELPER(PASUBUB, pasubub);
2790 LMI_HELPER_1(BIADD, biadd);
2791 LMI_HELPER_1(PMOVMSKB, pmovmskb);
2793 LMI_DIRECT(PADDD, paddd, add);
2794 LMI_DIRECT(PSUBD, psubd, sub);
2795 LMI_DIRECT(XOR_CP2, xor, xor);
2796 LMI_DIRECT(NOR_CP2, nor, nor);
2797 LMI_DIRECT(AND_CP2, and, and);
2798 LMI_DIRECT(PANDN, pandn, andc);
2799 LMI_DIRECT(OR, or, or);
2801 case OPC_PINSRH_0:
2802 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
2803 opn = "pinsrh_0";
2804 break;
2805 case OPC_PINSRH_1:
2806 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
2807 opn = "pinsrh_1";
2808 break;
2809 case OPC_PINSRH_2:
2810 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
2811 opn = "pinsrh_2";
2812 break;
2813 case OPC_PINSRH_3:
2814 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
2815 opn = "pinsrh_3";
2816 break;
2818 case OPC_PEXTRH:
2819 tcg_gen_andi_i64(t1, t1, 3);
2820 tcg_gen_shli_i64(t1, t1, 4);
2821 tcg_gen_shr_i64(t0, t0, t1);
2822 tcg_gen_ext16u_i64(t0, t0);
2823 opn = "pextrh";
2824 break;
2826 case OPC_ADDU_CP2:
2827 tcg_gen_add_i64(t0, t0, t1);
2828 tcg_gen_ext32s_i64(t0, t0);
2829 opn = "addu";
2830 break;
2831 case OPC_SUBU_CP2:
2832 tcg_gen_sub_i64(t0, t0, t1);
2833 tcg_gen_ext32s_i64(t0, t0);
2834 opn = "addu";
2835 break;
2837 case OPC_SLL_CP2:
2838 opn = "sll";
2839 shift_max = 32;
2840 goto do_shift;
2841 case OPC_SRL_CP2:
2842 opn = "srl";
2843 shift_max = 32;
2844 goto do_shift;
2845 case OPC_SRA_CP2:
2846 opn = "sra";
2847 shift_max = 32;
2848 goto do_shift;
2849 case OPC_DSLL_CP2:
2850 opn = "dsll";
2851 shift_max = 64;
2852 goto do_shift;
2853 case OPC_DSRL_CP2:
2854 opn = "dsrl";
2855 shift_max = 64;
2856 goto do_shift;
2857 case OPC_DSRA_CP2:
2858 opn = "dsra";
2859 shift_max = 64;
2860 goto do_shift;
2861 do_shift:
2862 /* Make sure shift count isn't TCG undefined behaviour. */
2863 tcg_gen_andi_i64(t1, t1, shift_max - 1);
2865 switch (opc) {
2866 case OPC_SLL_CP2:
2867 case OPC_DSLL_CP2:
2868 tcg_gen_shl_i64(t0, t0, t1);
2869 break;
2870 case OPC_SRA_CP2:
2871 case OPC_DSRA_CP2:
2872 /* Since SRA is UndefinedResult without sign-extended inputs,
2873 we can treat SRA and DSRA the same. */
2874 tcg_gen_sar_i64(t0, t0, t1);
2875 break;
2876 case OPC_SRL_CP2:
2877 /* We want to shift in zeros for SRL; zero-extend first. */
2878 tcg_gen_ext32u_i64(t0, t0);
2879 /* FALLTHRU */
2880 case OPC_DSRL_CP2:
2881 tcg_gen_shr_i64(t0, t0, t1);
2882 break;
2885 if (shift_max == 32) {
2886 tcg_gen_ext32s_i64(t0, t0);
2889 /* Shifts larger than MAX produce zero. */
2890 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
2891 tcg_gen_neg_i64(t1, t1);
2892 tcg_gen_and_i64(t0, t0, t1);
2893 break;
2895 case OPC_ADD_CP2:
2896 case OPC_DADD_CP2:
2898 TCGv_i64 t2 = tcg_temp_new_i64();
2899 int lab = gen_new_label();
2901 tcg_gen_mov_i64(t2, t0);
2902 tcg_gen_add_i64(t0, t1, t2);
2903 if (opc == OPC_ADD_CP2) {
2904 tcg_gen_ext32s_i64(t0, t0);
2906 tcg_gen_xor_i64(t1, t1, t2);
2907 tcg_gen_xor_i64(t2, t2, t0);
2908 tcg_gen_andc_i64(t1, t2, t1);
2909 tcg_temp_free_i64(t2);
2910 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
2911 generate_exception(ctx, EXCP_OVERFLOW);
2912 gen_set_label(lab);
2914 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
2915 break;
2918 case OPC_SUB_CP2:
2919 case OPC_DSUB_CP2:
2921 TCGv_i64 t2 = tcg_temp_new_i64();
2922 int lab = gen_new_label();
2924 tcg_gen_mov_i64(t2, t0);
2925 tcg_gen_sub_i64(t0, t1, t2);
2926 if (opc == OPC_SUB_CP2) {
2927 tcg_gen_ext32s_i64(t0, t0);
2929 tcg_gen_xor_i64(t1, t1, t2);
2930 tcg_gen_xor_i64(t2, t2, t0);
2931 tcg_gen_and_i64(t1, t1, t2);
2932 tcg_temp_free_i64(t2);
2933 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
2934 generate_exception(ctx, EXCP_OVERFLOW);
2935 gen_set_label(lab);
2937 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
2938 break;
2941 case OPC_PMULUW:
2942 tcg_gen_ext32u_i64(t0, t0);
2943 tcg_gen_ext32u_i64(t1, t1);
2944 tcg_gen_mul_i64(t0, t0, t1);
2945 opn = "pmuluw";
2946 break;
2948 case OPC_SEQU_CP2:
2949 case OPC_SEQ_CP2:
2950 case OPC_SLTU_CP2:
2951 case OPC_SLT_CP2:
2952 case OPC_SLEU_CP2:
2953 case OPC_SLE_CP2:
2954 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
2955 FD field is the CC field? */
2956 default:
2957 MIPS_INVAL(opn);
2958 generate_exception(ctx, EXCP_RI);
2959 return;
2962 #undef LMI_HELPER
2963 #undef LMI_DIRECT
2965 gen_store_fpr64(ctx, t0, rd);
2967 (void)opn; /* avoid a compiler warning */
2968 MIPS_DEBUG("%s %s, %s, %s", opn,
2969 fregnames[rd], fregnames[rs], fregnames[rt]);
2970 tcg_temp_free_i64(t0);
2971 tcg_temp_free_i64(t1);
2974 /* Traps */
2975 static void gen_trap (DisasContext *ctx, uint32_t opc,
2976 int rs, int rt, int16_t imm)
2978 int cond;
2979 TCGv t0 = tcg_temp_new();
2980 TCGv t1 = tcg_temp_new();
2982 cond = 0;
2983 /* Load needed operands */
2984 switch (opc) {
2985 case OPC_TEQ:
2986 case OPC_TGE:
2987 case OPC_TGEU:
2988 case OPC_TLT:
2989 case OPC_TLTU:
2990 case OPC_TNE:
2991 /* Compare two registers */
2992 if (rs != rt) {
2993 gen_load_gpr(t0, rs);
2994 gen_load_gpr(t1, rt);
2995 cond = 1;
2997 break;
2998 case OPC_TEQI:
2999 case OPC_TGEI:
3000 case OPC_TGEIU:
3001 case OPC_TLTI:
3002 case OPC_TLTIU:
3003 case OPC_TNEI:
3004 /* Compare register to immediate */
3005 if (rs != 0 || imm != 0) {
3006 gen_load_gpr(t0, rs);
3007 tcg_gen_movi_tl(t1, (int32_t)imm);
3008 cond = 1;
3010 break;
3012 if (cond == 0) {
3013 switch (opc) {
3014 case OPC_TEQ: /* rs == rs */
3015 case OPC_TEQI: /* r0 == 0 */
3016 case OPC_TGE: /* rs >= rs */
3017 case OPC_TGEI: /* r0 >= 0 */
3018 case OPC_TGEU: /* rs >= rs unsigned */
3019 case OPC_TGEIU: /* r0 >= 0 unsigned */
3020 /* Always trap */
3021 generate_exception(ctx, EXCP_TRAP);
3022 break;
3023 case OPC_TLT: /* rs < rs */
3024 case OPC_TLTI: /* r0 < 0 */
3025 case OPC_TLTU: /* rs < rs unsigned */
3026 case OPC_TLTIU: /* r0 < 0 unsigned */
3027 case OPC_TNE: /* rs != rs */
3028 case OPC_TNEI: /* r0 != 0 */
3029 /* Never trap: treat as NOP. */
3030 break;
3032 } else {
3033 int l1 = gen_new_label();
3035 switch (opc) {
3036 case OPC_TEQ:
3037 case OPC_TEQI:
3038 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
3039 break;
3040 case OPC_TGE:
3041 case OPC_TGEI:
3042 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
3043 break;
3044 case OPC_TGEU:
3045 case OPC_TGEIU:
3046 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
3047 break;
3048 case OPC_TLT:
3049 case OPC_TLTI:
3050 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
3051 break;
3052 case OPC_TLTU:
3053 case OPC_TLTIU:
3054 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
3055 break;
3056 case OPC_TNE:
3057 case OPC_TNEI:
3058 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
3059 break;
3061 generate_exception(ctx, EXCP_TRAP);
3062 gen_set_label(l1);
3064 tcg_temp_free(t0);
3065 tcg_temp_free(t1);
3068 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3070 TranslationBlock *tb;
3071 tb = ctx->tb;
3072 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3073 likely(!ctx->singlestep_enabled)) {
3074 tcg_gen_goto_tb(n);
3075 gen_save_pc(dest);
3076 tcg_gen_exit_tb((tcg_target_long)tb + n);
3077 } else {
3078 gen_save_pc(dest);
3079 if (ctx->singlestep_enabled) {
3080 save_cpu_state(ctx, 0);
3081 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
3083 tcg_gen_exit_tb(0);
3087 /* Branches (before delay slot) */
3088 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
3089 int insn_bytes,
3090 int rs, int rt, int32_t offset)
3092 target_ulong btgt = -1;
3093 int blink = 0;
3094 int bcond_compute = 0;
3095 TCGv t0 = tcg_temp_new();
3096 TCGv t1 = tcg_temp_new();
3098 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3099 #ifdef MIPS_DEBUG_DISAS
3100 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
3101 #endif
3102 generate_exception(ctx, EXCP_RI);
3103 goto out;
3106 /* Load needed operands */
3107 switch (opc) {
3108 case OPC_BEQ:
3109 case OPC_BEQL:
3110 case OPC_BNE:
3111 case OPC_BNEL:
3112 /* Compare two registers */
3113 if (rs != rt) {
3114 gen_load_gpr(t0, rs);
3115 gen_load_gpr(t1, rt);
3116 bcond_compute = 1;
3118 btgt = ctx->pc + insn_bytes + offset;
3119 break;
3120 case OPC_BGEZ:
3121 case OPC_BGEZAL:
3122 case OPC_BGEZALS:
3123 case OPC_BGEZALL:
3124 case OPC_BGEZL:
3125 case OPC_BGTZ:
3126 case OPC_BGTZL:
3127 case OPC_BLEZ:
3128 case OPC_BLEZL:
3129 case OPC_BLTZ:
3130 case OPC_BLTZAL:
3131 case OPC_BLTZALS:
3132 case OPC_BLTZALL:
3133 case OPC_BLTZL:
3134 /* Compare to zero */
3135 if (rs != 0) {
3136 gen_load_gpr(t0, rs);
3137 bcond_compute = 1;
3139 btgt = ctx->pc + insn_bytes + offset;
3140 break;
3141 case OPC_J:
3142 case OPC_JAL:
3143 case OPC_JALX:
3144 case OPC_JALS:
3145 case OPC_JALXS:
3146 /* Jump to immediate */
3147 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
3148 break;
3149 case OPC_JR:
3150 case OPC_JALR:
3151 case OPC_JALRC:
3152 case OPC_JALRS:
3153 /* Jump to register */
3154 if (offset != 0 && offset != 16) {
3155 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
3156 others are reserved. */
3157 MIPS_INVAL("jump hint");
3158 generate_exception(ctx, EXCP_RI);
3159 goto out;
3161 gen_load_gpr(btarget, rs);
3162 break;
3163 default:
3164 MIPS_INVAL("branch/jump");
3165 generate_exception(ctx, EXCP_RI);
3166 goto out;
3168 if (bcond_compute == 0) {
3169 /* No condition to be computed */
3170 switch (opc) {
3171 case OPC_BEQ: /* rx == rx */
3172 case OPC_BEQL: /* rx == rx likely */
3173 case OPC_BGEZ: /* 0 >= 0 */
3174 case OPC_BGEZL: /* 0 >= 0 likely */
3175 case OPC_BLEZ: /* 0 <= 0 */
3176 case OPC_BLEZL: /* 0 <= 0 likely */
3177 /* Always take */
3178 ctx->hflags |= MIPS_HFLAG_B;
3179 MIPS_DEBUG("balways");
3180 break;
3181 case OPC_BGEZALS:
3182 case OPC_BGEZAL: /* 0 >= 0 */
3183 case OPC_BGEZALL: /* 0 >= 0 likely */
3184 ctx->hflags |= (opc == OPC_BGEZALS
3185 ? MIPS_HFLAG_BDS16
3186 : MIPS_HFLAG_BDS32);
3187 /* Always take and link */
3188 blink = 31;
3189 ctx->hflags |= MIPS_HFLAG_B;
3190 MIPS_DEBUG("balways and link");
3191 break;
3192 case OPC_BNE: /* rx != rx */
3193 case OPC_BGTZ: /* 0 > 0 */
3194 case OPC_BLTZ: /* 0 < 0 */
3195 /* Treat as NOP. */
3196 MIPS_DEBUG("bnever (NOP)");
3197 goto out;
3198 case OPC_BLTZALS:
3199 case OPC_BLTZAL: /* 0 < 0 */
3200 ctx->hflags |= (opc == OPC_BLTZALS
3201 ? MIPS_HFLAG_BDS16
3202 : MIPS_HFLAG_BDS32);
3203 /* Handle as an unconditional branch to get correct delay
3204 slot checking. */
3205 blink = 31;
3206 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
3207 ctx->hflags |= MIPS_HFLAG_B;
3208 MIPS_DEBUG("bnever and link");
3209 break;
3210 case OPC_BLTZALL: /* 0 < 0 likely */
3211 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
3212 /* Skip the instruction in the delay slot */
3213 MIPS_DEBUG("bnever, link and skip");
3214 ctx->pc += 4;
3215 goto out;
3216 case OPC_BNEL: /* rx != rx likely */
3217 case OPC_BGTZL: /* 0 > 0 likely */
3218 case OPC_BLTZL: /* 0 < 0 likely */
3219 /* Skip the instruction in the delay slot */
3220 MIPS_DEBUG("bnever and skip");
3221 ctx->pc += 4;
3222 goto out;
3223 case OPC_J:
3224 ctx->hflags |= MIPS_HFLAG_B;
3225 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
3226 break;
3227 case OPC_JALXS:
3228 case OPC_JALX:
3229 ctx->hflags |= MIPS_HFLAG_BX;
3230 /* Fallthrough */
3231 case OPC_JALS:
3232 case OPC_JAL:
3233 blink = 31;
3234 ctx->hflags |= MIPS_HFLAG_B;
3235 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
3236 ? MIPS_HFLAG_BDS16
3237 : MIPS_HFLAG_BDS32);
3238 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
3239 break;
3240 case OPC_JR:
3241 ctx->hflags |= MIPS_HFLAG_BR;
3242 if (insn_bytes == 4)
3243 ctx->hflags |= MIPS_HFLAG_BDS32;
3244 MIPS_DEBUG("jr %s", regnames[rs]);
3245 break;
3246 case OPC_JALRS:
3247 case OPC_JALR:
3248 case OPC_JALRC:
3249 blink = rt;
3250 ctx->hflags |= MIPS_HFLAG_BR;
3251 ctx->hflags |= (opc == OPC_JALRS
3252 ? MIPS_HFLAG_BDS16
3253 : MIPS_HFLAG_BDS32);
3254 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
3255 break;
3256 default:
3257 MIPS_INVAL("branch/jump");
3258 generate_exception(ctx, EXCP_RI);
3259 goto out;
3261 } else {
3262 switch (opc) {
3263 case OPC_BEQ:
3264 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
3265 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
3266 regnames[rs], regnames[rt], btgt);
3267 goto not_likely;
3268 case OPC_BEQL:
3269 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
3270 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
3271 regnames[rs], regnames[rt], btgt);
3272 goto likely;
3273 case OPC_BNE:
3274 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
3275 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
3276 regnames[rs], regnames[rt], btgt);
3277 goto not_likely;
3278 case OPC_BNEL:
3279 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
3280 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
3281 regnames[rs], regnames[rt], btgt);
3282 goto likely;
3283 case OPC_BGEZ:
3284 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3285 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
3286 goto not_likely;
3287 case OPC_BGEZL:
3288 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3289 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3290 goto likely;
3291 case OPC_BGEZALS:
3292 case OPC_BGEZAL:
3293 ctx->hflags |= (opc == OPC_BGEZALS
3294 ? MIPS_HFLAG_BDS16
3295 : MIPS_HFLAG_BDS32);
3296 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3297 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
3298 blink = 31;
3299 goto not_likely;
3300 case OPC_BGEZALL:
3301 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3302 blink = 31;
3303 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
3304 goto likely;
3305 case OPC_BGTZ:
3306 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
3307 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
3308 goto not_likely;
3309 case OPC_BGTZL:
3310 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
3311 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3312 goto likely;
3313 case OPC_BLEZ:
3314 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
3315 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
3316 goto not_likely;
3317 case OPC_BLEZL:
3318 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
3319 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3320 goto likely;
3321 case OPC_BLTZ:
3322 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3323 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
3324 goto not_likely;
3325 case OPC_BLTZL:
3326 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3327 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3328 goto likely;
3329 case OPC_BLTZALS:
3330 case OPC_BLTZAL:
3331 ctx->hflags |= (opc == OPC_BLTZALS
3332 ? MIPS_HFLAG_BDS16
3333 : MIPS_HFLAG_BDS32);
3334 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3335 blink = 31;
3336 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
3337 not_likely:
3338 ctx->hflags |= MIPS_HFLAG_BC;
3339 break;
3340 case OPC_BLTZALL:
3341 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3342 blink = 31;
3343 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
3344 likely:
3345 ctx->hflags |= MIPS_HFLAG_BL;
3346 break;
3347 default:
3348 MIPS_INVAL("conditional branch/jump");
3349 generate_exception(ctx, EXCP_RI);
3350 goto out;
3353 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
3354 blink, ctx->hflags, btgt);
3356 ctx->btarget = btgt;
3357 if (blink > 0) {
3358 int post_delay = insn_bytes;
3359 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
3361 if (opc != OPC_JALRC)
3362 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
3364 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
3367 out:
3368 if (insn_bytes == 2)
3369 ctx->hflags |= MIPS_HFLAG_B16;
3370 tcg_temp_free(t0);
3371 tcg_temp_free(t1);
3374 /* special3 bitfield operations */
3375 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
3376 int rs, int lsb, int msb)
3378 TCGv t0 = tcg_temp_new();
3379 TCGv t1 = tcg_temp_new();
3380 target_ulong mask;
3382 gen_load_gpr(t1, rs);
3383 switch (opc) {
3384 case OPC_EXT:
3385 if (lsb + msb > 31)
3386 goto fail;
3387 tcg_gen_shri_tl(t0, t1, lsb);
3388 if (msb != 31) {
3389 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3390 } else {
3391 tcg_gen_ext32s_tl(t0, t0);
3393 break;
3394 #if defined(TARGET_MIPS64)
3395 case OPC_DEXTM:
3396 tcg_gen_shri_tl(t0, t1, lsb);
3397 if (msb != 31) {
3398 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3400 break;
3401 case OPC_DEXTU:
3402 tcg_gen_shri_tl(t0, t1, lsb + 32);
3403 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3404 break;
3405 case OPC_DEXT:
3406 tcg_gen_shri_tl(t0, t1, lsb);
3407 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3408 break;
3409 #endif
3410 case OPC_INS:
3411 if (lsb > msb)
3412 goto fail;
3413 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
3414 gen_load_gpr(t0, rt);
3415 tcg_gen_andi_tl(t0, t0, ~mask);
3416 tcg_gen_shli_tl(t1, t1, lsb);
3417 tcg_gen_andi_tl(t1, t1, mask);
3418 tcg_gen_or_tl(t0, t0, t1);
3419 tcg_gen_ext32s_tl(t0, t0);
3420 break;
3421 #if defined(TARGET_MIPS64)
3422 case OPC_DINSM:
3423 if (lsb > msb)
3424 goto fail;
3425 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
3426 gen_load_gpr(t0, rt);
3427 tcg_gen_andi_tl(t0, t0, ~mask);
3428 tcg_gen_shli_tl(t1, t1, lsb);
3429 tcg_gen_andi_tl(t1, t1, mask);
3430 tcg_gen_or_tl(t0, t0, t1);
3431 break;
3432 case OPC_DINSU:
3433 if (lsb > msb)
3434 goto fail;
3435 mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
3436 gen_load_gpr(t0, rt);
3437 tcg_gen_andi_tl(t0, t0, ~mask);
3438 tcg_gen_shli_tl(t1, t1, lsb + 32);
3439 tcg_gen_andi_tl(t1, t1, mask);
3440 tcg_gen_or_tl(t0, t0, t1);
3441 break;
3442 case OPC_DINS:
3443 if (lsb > msb)
3444 goto fail;
3445 gen_load_gpr(t0, rt);
3446 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3447 gen_load_gpr(t0, rt);
3448 tcg_gen_andi_tl(t0, t0, ~mask);
3449 tcg_gen_shli_tl(t1, t1, lsb);
3450 tcg_gen_andi_tl(t1, t1, mask);
3451 tcg_gen_or_tl(t0, t0, t1);
3452 break;
3453 #endif
3454 default:
3455 fail:
3456 MIPS_INVAL("bitops");
3457 generate_exception(ctx, EXCP_RI);
3458 tcg_temp_free(t0);
3459 tcg_temp_free(t1);
3460 return;
3462 gen_store_gpr(t0, rt);
3463 tcg_temp_free(t0);
3464 tcg_temp_free(t1);
3467 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3469 TCGv t0;
3471 if (rd == 0) {
3472 /* If no destination, treat it as a NOP. */
3473 MIPS_DEBUG("NOP");
3474 return;
3477 t0 = tcg_temp_new();
3478 gen_load_gpr(t0, rt);
3479 switch (op2) {
3480 case OPC_WSBH:
3482 TCGv t1 = tcg_temp_new();
3484 tcg_gen_shri_tl(t1, t0, 8);
3485 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3486 tcg_gen_shli_tl(t0, t0, 8);
3487 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3488 tcg_gen_or_tl(t0, t0, t1);
3489 tcg_temp_free(t1);
3490 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3492 break;
3493 case OPC_SEB:
3494 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
3495 break;
3496 case OPC_SEH:
3497 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
3498 break;
3499 #if defined(TARGET_MIPS64)
3500 case OPC_DSBH:
3502 TCGv t1 = tcg_temp_new();
3504 tcg_gen_shri_tl(t1, t0, 8);
3505 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3506 tcg_gen_shli_tl(t0, t0, 8);
3507 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3508 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3509 tcg_temp_free(t1);
3511 break;
3512 case OPC_DSHD:
3514 TCGv t1 = tcg_temp_new();
3516 tcg_gen_shri_tl(t1, t0, 16);
3517 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3518 tcg_gen_shli_tl(t0, t0, 16);
3519 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3520 tcg_gen_or_tl(t0, t0, t1);
3521 tcg_gen_shri_tl(t1, t0, 32);
3522 tcg_gen_shli_tl(t0, t0, 32);
3523 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3524 tcg_temp_free(t1);
3526 break;
3527 #endif
3528 default:
3529 MIPS_INVAL("bsfhl");
3530 generate_exception(ctx, EXCP_RI);
3531 tcg_temp_free(t0);
3532 return;
3534 tcg_temp_free(t0);
3537 #ifndef CONFIG_USER_ONLY
3538 /* CP0 (MMU and control) */
3539 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
3541 TCGv_i32 t0 = tcg_temp_new_i32();
3543 tcg_gen_ld_i32(t0, cpu_env, off);
3544 tcg_gen_ext_i32_tl(arg, t0);
3545 tcg_temp_free_i32(t0);
3548 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
3550 tcg_gen_ld_tl(arg, cpu_env, off);
3551 tcg_gen_ext32s_tl(arg, arg);
3554 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
3556 TCGv_i32 t0 = tcg_temp_new_i32();
3558 tcg_gen_trunc_tl_i32(t0, arg);
3559 tcg_gen_st_i32(t0, cpu_env, off);
3560 tcg_temp_free_i32(t0);
3563 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
3565 tcg_gen_ext32s_tl(arg, arg);
3566 tcg_gen_st_tl(arg, cpu_env, off);
3569 static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3571 const char *rn = "invalid";
3573 if (sel != 0)
3574 check_insn(env, ctx, ISA_MIPS32);
3576 switch (reg) {
3577 case 0:
3578 switch (sel) {
3579 case 0:
3580 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
3581 rn = "Index";
3582 break;
3583 case 1:
3584 check_insn(env, ctx, ASE_MT);
3585 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
3586 rn = "MVPControl";
3587 break;
3588 case 2:
3589 check_insn(env, ctx, ASE_MT);
3590 gen_helper_mfc0_mvpconf0(arg, cpu_env);
3591 rn = "MVPConf0";
3592 break;
3593 case 3:
3594 check_insn(env, ctx, ASE_MT);
3595 gen_helper_mfc0_mvpconf1(arg, cpu_env);
3596 rn = "MVPConf1";
3597 break;
3598 default:
3599 goto die;
3601 break;
3602 case 1:
3603 switch (sel) {
3604 case 0:
3605 gen_helper_mfc0_random(arg, cpu_env);
3606 rn = "Random";
3607 break;
3608 case 1:
3609 check_insn(env, ctx, ASE_MT);
3610 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
3611 rn = "VPEControl";
3612 break;
3613 case 2:
3614 check_insn(env, ctx, ASE_MT);
3615 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
3616 rn = "VPEConf0";
3617 break;
3618 case 3:
3619 check_insn(env, ctx, ASE_MT);
3620 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
3621 rn = "VPEConf1";
3622 break;
3623 case 4:
3624 check_insn(env, ctx, ASE_MT);
3625 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
3626 rn = "YQMask";
3627 break;
3628 case 5:
3629 check_insn(env, ctx, ASE_MT);
3630 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
3631 rn = "VPESchedule";
3632 break;
3633 case 6:
3634 check_insn(env, ctx, ASE_MT);
3635 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
3636 rn = "VPEScheFBack";
3637 break;
3638 case 7:
3639 check_insn(env, ctx, ASE_MT);
3640 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
3641 rn = "VPEOpt";
3642 break;
3643 default:
3644 goto die;
3646 break;
3647 case 2:
3648 switch (sel) {
3649 case 0:
3650 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
3651 tcg_gen_ext32s_tl(arg, arg);
3652 rn = "EntryLo0";
3653 break;
3654 case 1:
3655 check_insn(env, ctx, ASE_MT);
3656 gen_helper_mfc0_tcstatus(arg, cpu_env);
3657 rn = "TCStatus";
3658 break;
3659 case 2:
3660 check_insn(env, ctx, ASE_MT);
3661 gen_helper_mfc0_tcbind(arg, cpu_env);
3662 rn = "TCBind";
3663 break;
3664 case 3:
3665 check_insn(env, ctx, ASE_MT);
3666 gen_helper_mfc0_tcrestart(arg, cpu_env);
3667 rn = "TCRestart";
3668 break;
3669 case 4:
3670 check_insn(env, ctx, ASE_MT);
3671 gen_helper_mfc0_tchalt(arg, cpu_env);
3672 rn = "TCHalt";
3673 break;
3674 case 5:
3675 check_insn(env, ctx, ASE_MT);
3676 gen_helper_mfc0_tccontext(arg, cpu_env);
3677 rn = "TCContext";
3678 break;
3679 case 6:
3680 check_insn(env, ctx, ASE_MT);
3681 gen_helper_mfc0_tcschedule(arg, cpu_env);
3682 rn = "TCSchedule";
3683 break;
3684 case 7:
3685 check_insn(env, ctx, ASE_MT);
3686 gen_helper_mfc0_tcschefback(arg, cpu_env);
3687 rn = "TCScheFBack";
3688 break;
3689 default:
3690 goto die;
3692 break;
3693 case 3:
3694 switch (sel) {
3695 case 0:
3696 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
3697 tcg_gen_ext32s_tl(arg, arg);
3698 rn = "EntryLo1";
3699 break;
3700 default:
3701 goto die;
3703 break;
3704 case 4:
3705 switch (sel) {
3706 case 0:
3707 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
3708 tcg_gen_ext32s_tl(arg, arg);
3709 rn = "Context";
3710 break;
3711 case 1:
3712 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3713 rn = "ContextConfig";
3714 // break;
3715 default:
3716 goto die;
3718 break;
3719 case 5:
3720 switch (sel) {
3721 case 0:
3722 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
3723 rn = "PageMask";
3724 break;
3725 case 1:
3726 check_insn(env, ctx, ISA_MIPS32R2);
3727 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
3728 rn = "PageGrain";
3729 break;
3730 default:
3731 goto die;
3733 break;
3734 case 6:
3735 switch (sel) {
3736 case 0:
3737 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
3738 rn = "Wired";
3739 break;
3740 case 1:
3741 check_insn(env, ctx, ISA_MIPS32R2);
3742 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
3743 rn = "SRSConf0";
3744 break;
3745 case 2:
3746 check_insn(env, ctx, ISA_MIPS32R2);
3747 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
3748 rn = "SRSConf1";
3749 break;
3750 case 3:
3751 check_insn(env, ctx, ISA_MIPS32R2);
3752 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
3753 rn = "SRSConf2";
3754 break;
3755 case 4:
3756 check_insn(env, ctx, ISA_MIPS32R2);
3757 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
3758 rn = "SRSConf3";
3759 break;
3760 case 5:
3761 check_insn(env, ctx, ISA_MIPS32R2);
3762 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
3763 rn = "SRSConf4";
3764 break;
3765 default:
3766 goto die;
3768 break;
3769 case 7:
3770 switch (sel) {
3771 case 0:
3772 check_insn(env, ctx, ISA_MIPS32R2);
3773 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
3774 rn = "HWREna";
3775 break;
3776 default:
3777 goto die;
3779 break;
3780 case 8:
3781 switch (sel) {
3782 case 0:
3783 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
3784 tcg_gen_ext32s_tl(arg, arg);
3785 rn = "BadVAddr";
3786 break;
3787 default:
3788 goto die;
3790 break;
3791 case 9:
3792 switch (sel) {
3793 case 0:
3794 /* Mark as an IO operation because we read the time. */
3795 if (use_icount)
3796 gen_io_start();
3797 gen_helper_mfc0_count(arg, cpu_env);
3798 if (use_icount) {
3799 gen_io_end();
3801 /* Break the TB to be able to take timer interrupts immediately
3802 after reading count. */
3803 ctx->bstate = BS_STOP;
3804 rn = "Count";
3805 break;
3806 /* 6,7 are implementation dependent */
3807 default:
3808 goto die;
3810 break;
3811 case 10:
3812 switch (sel) {
3813 case 0:
3814 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
3815 tcg_gen_ext32s_tl(arg, arg);
3816 rn = "EntryHi";
3817 break;
3818 default:
3819 goto die;
3821 break;
3822 case 11:
3823 switch (sel) {
3824 case 0:
3825 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
3826 rn = "Compare";
3827 break;
3828 /* 6,7 are implementation dependent */
3829 default:
3830 goto die;
3832 break;
3833 case 12:
3834 switch (sel) {
3835 case 0:
3836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
3837 rn = "Status";
3838 break;
3839 case 1:
3840 check_insn(env, ctx, ISA_MIPS32R2);
3841 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
3842 rn = "IntCtl";
3843 break;
3844 case 2:
3845 check_insn(env, ctx, ISA_MIPS32R2);
3846 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
3847 rn = "SRSCtl";
3848 break;
3849 case 3:
3850 check_insn(env, ctx, ISA_MIPS32R2);
3851 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
3852 rn = "SRSMap";
3853 break;
3854 default:
3855 goto die;
3857 break;
3858 case 13:
3859 switch (sel) {
3860 case 0:
3861 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
3862 rn = "Cause";
3863 break;
3864 default:
3865 goto die;
3867 break;
3868 case 14:
3869 switch (sel) {
3870 case 0:
3871 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
3872 tcg_gen_ext32s_tl(arg, arg);
3873 rn = "EPC";
3874 break;
3875 default:
3876 goto die;
3878 break;
3879 case 15:
3880 switch (sel) {
3881 case 0:
3882 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
3883 rn = "PRid";
3884 break;
3885 case 1:
3886 check_insn(env, ctx, ISA_MIPS32R2);
3887 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
3888 rn = "EBase";
3889 break;
3890 default:
3891 goto die;
3893 break;
3894 case 16:
3895 switch (sel) {
3896 case 0:
3897 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
3898 rn = "Config";
3899 break;
3900 case 1:
3901 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
3902 rn = "Config1";
3903 break;
3904 case 2:
3905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
3906 rn = "Config2";
3907 break;
3908 case 3:
3909 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
3910 rn = "Config3";
3911 break;
3912 /* 4,5 are reserved */
3913 /* 6,7 are implementation dependent */
3914 case 6:
3915 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
3916 rn = "Config6";
3917 break;
3918 case 7:
3919 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
3920 rn = "Config7";
3921 break;
3922 default:
3923 goto die;
3925 break;
3926 case 17:
3927 switch (sel) {
3928 case 0:
3929 gen_helper_mfc0_lladdr(arg, cpu_env);
3930 rn = "LLAddr";
3931 break;
3932 default:
3933 goto die;
3935 break;
3936 case 18:
3937 switch (sel) {
3938 case 0 ... 7:
3939 gen_helper_1e0i(mfc0_watchlo, arg, sel);
3940 rn = "WatchLo";
3941 break;
3942 default:
3943 goto die;
3945 break;
3946 case 19:
3947 switch (sel) {
3948 case 0 ...7:
3949 gen_helper_1e0i(mfc0_watchhi, arg, sel);
3950 rn = "WatchHi";
3951 break;
3952 default:
3953 goto die;
3955 break;
3956 case 20:
3957 switch (sel) {
3958 case 0:
3959 #if defined(TARGET_MIPS64)
3960 check_insn(env, ctx, ISA_MIPS3);
3961 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
3962 tcg_gen_ext32s_tl(arg, arg);
3963 rn = "XContext";
3964 break;
3965 #endif
3966 default:
3967 goto die;
3969 break;
3970 case 21:
3971 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3972 switch (sel) {
3973 case 0:
3974 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
3975 rn = "Framemask";
3976 break;
3977 default:
3978 goto die;
3980 break;
3981 case 22:
3982 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3983 rn = "'Diagnostic"; /* implementation dependent */
3984 break;
3985 case 23:
3986 switch (sel) {
3987 case 0:
3988 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
3989 rn = "Debug";
3990 break;
3991 case 1:
3992 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3993 rn = "TraceControl";
3994 // break;
3995 case 2:
3996 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3997 rn = "TraceControl2";
3998 // break;
3999 case 3:
4000 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
4001 rn = "UserTraceData";
4002 // break;
4003 case 4:
4004 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
4005 rn = "TraceBPC";
4006 // break;
4007 default:
4008 goto die;
4010 break;
4011 case 24:
4012 switch (sel) {
4013 case 0:
4014 /* EJTAG support */
4015 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
4016 tcg_gen_ext32s_tl(arg, arg);
4017 rn = "DEPC";
4018 break;
4019 default:
4020 goto die;
4022 break;
4023 case 25:
4024 switch (sel) {
4025 case 0:
4026 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
4027 rn = "Performance0";
4028 break;
4029 case 1:
4030 // gen_helper_mfc0_performance1(arg);
4031 rn = "Performance1";
4032 // break;
4033 case 2:
4034 // gen_helper_mfc0_performance2(arg);
4035 rn = "Performance2";
4036 // break;
4037 case 3:
4038 // gen_helper_mfc0_performance3(arg);
4039 rn = "Performance3";
4040 // break;
4041 case 4:
4042 // gen_helper_mfc0_performance4(arg);
4043 rn = "Performance4";
4044 // break;
4045 case 5:
4046 // gen_helper_mfc0_performance5(arg);
4047 rn = "Performance5";
4048 // break;
4049 case 6:
4050 // gen_helper_mfc0_performance6(arg);
4051 rn = "Performance6";
4052 // break;
4053 case 7:
4054 // gen_helper_mfc0_performance7(arg);
4055 rn = "Performance7";
4056 // break;
4057 default:
4058 goto die;
4060 break;
4061 case 26:
4062 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4063 rn = "ECC";
4064 break;
4065 case 27:
4066 switch (sel) {
4067 case 0 ... 3:
4068 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4069 rn = "CacheErr";
4070 break;
4071 default:
4072 goto die;
4074 break;
4075 case 28:
4076 switch (sel) {
4077 case 0:
4078 case 2:
4079 case 4:
4080 case 6:
4081 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
4082 rn = "TagLo";
4083 break;
4084 case 1:
4085 case 3:
4086 case 5:
4087 case 7:
4088 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
4089 rn = "DataLo";
4090 break;
4091 default:
4092 goto die;
4094 break;
4095 case 29:
4096 switch (sel) {
4097 case 0:
4098 case 2:
4099 case 4:
4100 case 6:
4101 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
4102 rn = "TagHi";
4103 break;
4104 case 1:
4105 case 3:
4106 case 5:
4107 case 7:
4108 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
4109 rn = "DataHi";
4110 break;
4111 default:
4112 goto die;
4114 break;
4115 case 30:
4116 switch (sel) {
4117 case 0:
4118 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
4119 tcg_gen_ext32s_tl(arg, arg);
4120 rn = "ErrorEPC";
4121 break;
4122 default:
4123 goto die;
4125 break;
4126 case 31:
4127 switch (sel) {
4128 case 0:
4129 /* EJTAG support */
4130 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
4131 rn = "DESAVE";
4132 break;
4133 default:
4134 goto die;
4136 break;
4137 default:
4138 goto die;
4140 (void)rn; /* avoid a compiler warning */
4141 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4142 return;
4144 die:
4145 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4146 generate_exception(ctx, EXCP_RI);
4149 static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4151 const char *rn = "invalid";
4153 if (sel != 0)
4154 check_insn(env, ctx, ISA_MIPS32);
4156 if (use_icount)
4157 gen_io_start();
4159 switch (reg) {
4160 case 0:
4161 switch (sel) {
4162 case 0:
4163 gen_helper_mtc0_index(cpu_env, arg);
4164 rn = "Index";
4165 break;
4166 case 1:
4167 check_insn(env, ctx, ASE_MT);
4168 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
4169 rn = "MVPControl";
4170 break;
4171 case 2:
4172 check_insn(env, ctx, ASE_MT);
4173 /* ignored */
4174 rn = "MVPConf0";
4175 break;
4176 case 3:
4177 check_insn(env, ctx, ASE_MT);
4178 /* ignored */
4179 rn = "MVPConf1";
4180 break;
4181 default:
4182 goto die;
4184 break;
4185 case 1:
4186 switch (sel) {
4187 case 0:
4188 /* ignored */
4189 rn = "Random";
4190 break;
4191 case 1:
4192 check_insn(env, ctx, ASE_MT);
4193 gen_helper_mtc0_vpecontrol(cpu_env, arg);
4194 rn = "VPEControl";
4195 break;
4196 case 2:
4197 check_insn(env, ctx, ASE_MT);
4198 gen_helper_mtc0_vpeconf0(cpu_env, arg);
4199 rn = "VPEConf0";
4200 break;
4201 case 3:
4202 check_insn(env, ctx, ASE_MT);
4203 gen_helper_mtc0_vpeconf1(cpu_env, arg);
4204 rn = "VPEConf1";
4205 break;
4206 case 4:
4207 check_insn(env, ctx, ASE_MT);
4208 gen_helper_mtc0_yqmask(cpu_env, arg);
4209 rn = "YQMask";
4210 break;
4211 case 5:
4212 check_insn(env, ctx, ASE_MT);
4213 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4214 rn = "VPESchedule";
4215 break;
4216 case 6:
4217 check_insn(env, ctx, ASE_MT);
4218 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4219 rn = "VPEScheFBack";
4220 break;
4221 case 7:
4222 check_insn(env, ctx, ASE_MT);
4223 gen_helper_mtc0_vpeopt(cpu_env, arg);
4224 rn = "VPEOpt";
4225 break;
4226 default:
4227 goto die;
4229 break;
4230 case 2:
4231 switch (sel) {
4232 case 0:
4233 gen_helper_mtc0_entrylo0(cpu_env, arg);
4234 rn = "EntryLo0";
4235 break;
4236 case 1:
4237 check_insn(env, ctx, ASE_MT);
4238 gen_helper_mtc0_tcstatus(cpu_env, arg);
4239 rn = "TCStatus";
4240 break;
4241 case 2:
4242 check_insn(env, ctx, ASE_MT);
4243 gen_helper_mtc0_tcbind(cpu_env, arg);
4244 rn = "TCBind";
4245 break;
4246 case 3:
4247 check_insn(env, ctx, ASE_MT);
4248 gen_helper_mtc0_tcrestart(cpu_env, arg);
4249 rn = "TCRestart";
4250 break;
4251 case 4:
4252 check_insn(env, ctx, ASE_MT);
4253 gen_helper_mtc0_tchalt(cpu_env, arg);
4254 rn = "TCHalt";
4255 break;
4256 case 5:
4257 check_insn(env, ctx, ASE_MT);
4258 gen_helper_mtc0_tccontext(cpu_env, arg);
4259 rn = "TCContext";
4260 break;
4261 case 6:
4262 check_insn(env, ctx, ASE_MT);
4263 gen_helper_mtc0_tcschedule(cpu_env, arg);
4264 rn = "TCSchedule";
4265 break;
4266 case 7:
4267 check_insn(env, ctx, ASE_MT);
4268 gen_helper_mtc0_tcschefback(cpu_env, arg);
4269 rn = "TCScheFBack";
4270 break;
4271 default:
4272 goto die;
4274 break;
4275 case 3:
4276 switch (sel) {
4277 case 0:
4278 gen_helper_mtc0_entrylo1(cpu_env, arg);
4279 rn = "EntryLo1";
4280 break;
4281 default:
4282 goto die;
4284 break;
4285 case 4:
4286 switch (sel) {
4287 case 0:
4288 gen_helper_mtc0_context(cpu_env, arg);
4289 rn = "Context";
4290 break;
4291 case 1:
4292 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
4293 rn = "ContextConfig";
4294 // break;
4295 default:
4296 goto die;
4298 break;
4299 case 5:
4300 switch (sel) {
4301 case 0:
4302 gen_helper_mtc0_pagemask(cpu_env, arg);
4303 rn = "PageMask";
4304 break;
4305 case 1:
4306 check_insn(env, ctx, ISA_MIPS32R2);
4307 gen_helper_mtc0_pagegrain(cpu_env, arg);
4308 rn = "PageGrain";
4309 break;
4310 default:
4311 goto die;
4313 break;
4314 case 6:
4315 switch (sel) {
4316 case 0:
4317 gen_helper_mtc0_wired(cpu_env, arg);
4318 rn = "Wired";
4319 break;
4320 case 1:
4321 check_insn(env, ctx, ISA_MIPS32R2);
4322 gen_helper_mtc0_srsconf0(cpu_env, arg);
4323 rn = "SRSConf0";
4324 break;
4325 case 2:
4326 check_insn(env, ctx, ISA_MIPS32R2);
4327 gen_helper_mtc0_srsconf1(cpu_env, arg);
4328 rn = "SRSConf1";
4329 break;
4330 case 3:
4331 check_insn(env, ctx, ISA_MIPS32R2);
4332 gen_helper_mtc0_srsconf2(cpu_env, arg);
4333 rn = "SRSConf2";
4334 break;
4335 case 4:
4336 check_insn(env, ctx, ISA_MIPS32R2);
4337 gen_helper_mtc0_srsconf3(cpu_env, arg);
4338 rn = "SRSConf3";
4339 break;
4340 case 5:
4341 check_insn(env, ctx, ISA_MIPS32R2);
4342 gen_helper_mtc0_srsconf4(cpu_env, arg);
4343 rn = "SRSConf4";
4344 break;
4345 default:
4346 goto die;
4348 break;
4349 case 7:
4350 switch (sel) {
4351 case 0:
4352 check_insn(env, ctx, ISA_MIPS32R2);
4353 gen_helper_mtc0_hwrena(cpu_env, arg);
4354 rn = "HWREna";
4355 break;
4356 default:
4357 goto die;
4359 break;
4360 case 8:
4361 /* ignored */
4362 rn = "BadVAddr";
4363 break;
4364 case 9:
4365 switch (sel) {
4366 case 0:
4367 gen_helper_mtc0_count(cpu_env, arg);
4368 rn = "Count";
4369 break;
4370 /* 6,7 are implementation dependent */
4371 default:
4372 goto die;
4374 break;
4375 case 10:
4376 switch (sel) {
4377 case 0:
4378 gen_helper_mtc0_entryhi(cpu_env, arg);
4379 rn = "EntryHi";
4380 break;
4381 default:
4382 goto die;
4384 break;
4385 case 11:
4386 switch (sel) {
4387 case 0:
4388 gen_helper_mtc0_compare(cpu_env, arg);
4389 rn = "Compare";
4390 break;
4391 /* 6,7 are implementation dependent */
4392 default:
4393 goto die;
4395 break;
4396 case 12:
4397 switch (sel) {
4398 case 0:
4399 save_cpu_state(ctx, 1);
4400 gen_helper_mtc0_status(cpu_env, arg);
4401 /* BS_STOP isn't good enough here, hflags may have changed. */
4402 gen_save_pc(ctx->pc + 4);
4403 ctx->bstate = BS_EXCP;
4404 rn = "Status";
4405 break;
4406 case 1:
4407 check_insn(env, ctx, ISA_MIPS32R2);
4408 gen_helper_mtc0_intctl(cpu_env, arg);
4409 /* Stop translation as we may have switched the execution mode */
4410 ctx->bstate = BS_STOP;
4411 rn = "IntCtl";
4412 break;
4413 case 2:
4414 check_insn(env, ctx, ISA_MIPS32R2);
4415 gen_helper_mtc0_srsctl(cpu_env, arg);
4416 /* Stop translation as we may have switched the execution mode */
4417 ctx->bstate = BS_STOP;
4418 rn = "SRSCtl";
4419 break;
4420 case 3:
4421 check_insn(env, ctx, ISA_MIPS32R2);
4422 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
4423 /* Stop translation as we may have switched the execution mode */
4424 ctx->bstate = BS_STOP;
4425 rn = "SRSMap";
4426 break;
4427 default:
4428 goto die;
4430 break;
4431 case 13:
4432 switch (sel) {
4433 case 0:
4434 save_cpu_state(ctx, 1);
4435 gen_helper_mtc0_cause(cpu_env, arg);
4436 rn = "Cause";
4437 break;
4438 default:
4439 goto die;
4441 break;
4442 case 14:
4443 switch (sel) {
4444 case 0:
4445 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
4446 rn = "EPC";
4447 break;
4448 default:
4449 goto die;
4451 break;
4452 case 15:
4453 switch (sel) {
4454 case 0:
4455 /* ignored */
4456 rn = "PRid";
4457 break;
4458 case 1:
4459 check_insn(env, ctx, ISA_MIPS32R2);
4460 gen_helper_mtc0_ebase(cpu_env, arg);
4461 rn = "EBase";
4462 break;
4463 default:
4464 goto die;
4466 break;
4467 case 16:
4468 switch (sel) {
4469 case 0:
4470 gen_helper_mtc0_config0(cpu_env, arg);
4471 rn = "Config";
4472 /* Stop translation as we may have switched the execution mode */
4473 ctx->bstate = BS_STOP;
4474 break;
4475 case 1:
4476 /* ignored, read only */
4477 rn = "Config1";
4478 break;
4479 case 2:
4480 gen_helper_mtc0_config2(cpu_env, arg);
4481 rn = "Config2";
4482 /* Stop translation as we may have switched the execution mode */
4483 ctx->bstate = BS_STOP;
4484 break;
4485 case 3:
4486 /* ignored, read only */
4487 rn = "Config3";
4488 break;
4489 /* 4,5 are reserved */
4490 /* 6,7 are implementation dependent */
4491 case 6:
4492 /* ignored */
4493 rn = "Config6";
4494 break;
4495 case 7:
4496 /* ignored */
4497 rn = "Config7";
4498 break;
4499 default:
4500 rn = "Invalid config selector";
4501 goto die;
4503 break;
4504 case 17:
4505 switch (sel) {
4506 case 0:
4507 gen_helper_mtc0_lladdr(cpu_env, arg);
4508 rn = "LLAddr";
4509 break;
4510 default:
4511 goto die;
4513 break;
4514 case 18:
4515 switch (sel) {
4516 case 0 ... 7:
4517 gen_helper_0e1i(mtc0_watchlo, arg, sel);
4518 rn = "WatchLo";
4519 break;
4520 default:
4521 goto die;
4523 break;
4524 case 19:
4525 switch (sel) {
4526 case 0 ... 7:
4527 gen_helper_0e1i(mtc0_watchhi, arg, sel);
4528 rn = "WatchHi";
4529 break;
4530 default:
4531 goto die;
4533 break;
4534 case 20:
4535 switch (sel) {
4536 case 0:
4537 #if defined(TARGET_MIPS64)
4538 check_insn(env, ctx, ISA_MIPS3);
4539 gen_helper_mtc0_xcontext(cpu_env, arg);
4540 rn = "XContext";
4541 break;
4542 #endif
4543 default:
4544 goto die;
4546 break;
4547 case 21:
4548 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4549 switch (sel) {
4550 case 0:
4551 gen_helper_mtc0_framemask(cpu_env, arg);
4552 rn = "Framemask";
4553 break;
4554 default:
4555 goto die;
4557 break;
4558 case 22:
4559 /* ignored */
4560 rn = "Diagnostic"; /* implementation dependent */
4561 break;
4562 case 23:
4563 switch (sel) {
4564 case 0:
4565 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
4566 /* BS_STOP isn't good enough here, hflags may have changed. */
4567 gen_save_pc(ctx->pc + 4);
4568 ctx->bstate = BS_EXCP;
4569 rn = "Debug";
4570 break;
4571 case 1:
4572 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
4573 rn = "TraceControl";
4574 /* Stop translation as we may have switched the execution mode */
4575 ctx->bstate = BS_STOP;
4576 // break;
4577 case 2:
4578 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
4579 rn = "TraceControl2";
4580 /* Stop translation as we may have switched the execution mode */
4581 ctx->bstate = BS_STOP;
4582 // break;
4583 case 3:
4584 /* Stop translation as we may have switched the execution mode */
4585 ctx->bstate = BS_STOP;
4586 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
4587 rn = "UserTraceData";
4588 /* Stop translation as we may have switched the execution mode */
4589 ctx->bstate = BS_STOP;
4590 // break;
4591 case 4:
4592 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
4593 /* Stop translation as we may have switched the execution mode */
4594 ctx->bstate = BS_STOP;
4595 rn = "TraceBPC";
4596 // break;
4597 default:
4598 goto die;
4600 break;
4601 case 24:
4602 switch (sel) {
4603 case 0:
4604 /* EJTAG support */
4605 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
4606 rn = "DEPC";
4607 break;
4608 default:
4609 goto die;
4611 break;
4612 case 25:
4613 switch (sel) {
4614 case 0:
4615 gen_helper_mtc0_performance0(cpu_env, arg);
4616 rn = "Performance0";
4617 break;
4618 case 1:
4619 // gen_helper_mtc0_performance1(arg);
4620 rn = "Performance1";
4621 // break;
4622 case 2:
4623 // gen_helper_mtc0_performance2(arg);
4624 rn = "Performance2";
4625 // break;
4626 case 3:
4627 // gen_helper_mtc0_performance3(arg);
4628 rn = "Performance3";
4629 // break;
4630 case 4:
4631 // gen_helper_mtc0_performance4(arg);
4632 rn = "Performance4";
4633 // break;
4634 case 5:
4635 // gen_helper_mtc0_performance5(arg);
4636 rn = "Performance5";
4637 // break;
4638 case 6:
4639 // gen_helper_mtc0_performance6(arg);
4640 rn = "Performance6";
4641 // break;
4642 case 7:
4643 // gen_helper_mtc0_performance7(arg);
4644 rn = "Performance7";
4645 // break;
4646 default:
4647 goto die;
4649 break;
4650 case 26:
4651 /* ignored */
4652 rn = "ECC";
4653 break;
4654 case 27:
4655 switch (sel) {
4656 case 0 ... 3:
4657 /* ignored */
4658 rn = "CacheErr";
4659 break;
4660 default:
4661 goto die;
4663 break;
4664 case 28:
4665 switch (sel) {
4666 case 0:
4667 case 2:
4668 case 4:
4669 case 6:
4670 gen_helper_mtc0_taglo(cpu_env, arg);
4671 rn = "TagLo";
4672 break;
4673 case 1:
4674 case 3:
4675 case 5:
4676 case 7:
4677 gen_helper_mtc0_datalo(cpu_env, arg);
4678 rn = "DataLo";
4679 break;
4680 default:
4681 goto die;
4683 break;
4684 case 29:
4685 switch (sel) {
4686 case 0:
4687 case 2:
4688 case 4:
4689 case 6:
4690 gen_helper_mtc0_taghi(cpu_env, arg);
4691 rn = "TagHi";
4692 break;
4693 case 1:
4694 case 3:
4695 case 5:
4696 case 7:
4697 gen_helper_mtc0_datahi(cpu_env, arg);
4698 rn = "DataHi";
4699 break;
4700 default:
4701 rn = "invalid sel";
4702 goto die;
4704 break;
4705 case 30:
4706 switch (sel) {
4707 case 0:
4708 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
4709 rn = "ErrorEPC";
4710 break;
4711 default:
4712 goto die;
4714 break;
4715 case 31:
4716 switch (sel) {
4717 case 0:
4718 /* EJTAG support */
4719 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
4720 rn = "DESAVE";
4721 break;
4722 default:
4723 goto die;
4725 /* Stop translation as we may have switched the execution mode */
4726 ctx->bstate = BS_STOP;
4727 break;
4728 default:
4729 goto die;
4731 (void)rn; /* avoid a compiler warning */
4732 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4733 /* For simplicity assume that all writes can cause interrupts. */
4734 if (use_icount) {
4735 gen_io_end();
4736 ctx->bstate = BS_STOP;
4738 return;
4740 die:
4741 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4742 generate_exception(ctx, EXCP_RI);
4745 #if defined(TARGET_MIPS64)
4746 static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4748 const char *rn = "invalid";
4750 if (sel != 0)
4751 check_insn(env, ctx, ISA_MIPS64);
4753 switch (reg) {
4754 case 0:
4755 switch (sel) {
4756 case 0:
4757 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4758 rn = "Index";
4759 break;
4760 case 1:
4761 check_insn(env, ctx, ASE_MT);
4762 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4763 rn = "MVPControl";
4764 break;
4765 case 2:
4766 check_insn(env, ctx, ASE_MT);
4767 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4768 rn = "MVPConf0";
4769 break;
4770 case 3:
4771 check_insn(env, ctx, ASE_MT);
4772 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4773 rn = "MVPConf1";
4774 break;
4775 default:
4776 goto die;
4778 break;
4779 case 1:
4780 switch (sel) {
4781 case 0:
4782 gen_helper_mfc0_random(arg, cpu_env);
4783 rn = "Random";
4784 break;
4785 case 1:
4786 check_insn(env, ctx, ASE_MT);
4787 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4788 rn = "VPEControl";
4789 break;
4790 case 2:
4791 check_insn(env, ctx, ASE_MT);
4792 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4793 rn = "VPEConf0";
4794 break;
4795 case 3:
4796 check_insn(env, ctx, ASE_MT);
4797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4798 rn = "VPEConf1";
4799 break;
4800 case 4:
4801 check_insn(env, ctx, ASE_MT);
4802 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
4803 rn = "YQMask";
4804 break;
4805 case 5:
4806 check_insn(env, ctx, ASE_MT);
4807 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
4808 rn = "VPESchedule";
4809 break;
4810 case 6:
4811 check_insn(env, ctx, ASE_MT);
4812 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4813 rn = "VPEScheFBack";
4814 break;
4815 case 7:
4816 check_insn(env, ctx, ASE_MT);
4817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
4818 rn = "VPEOpt";
4819 break;
4820 default:
4821 goto die;
4823 break;
4824 case 2:
4825 switch (sel) {
4826 case 0:
4827 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
4828 rn = "EntryLo0";
4829 break;
4830 case 1:
4831 check_insn(env, ctx, ASE_MT);
4832 gen_helper_mfc0_tcstatus(arg, cpu_env);
4833 rn = "TCStatus";
4834 break;
4835 case 2:
4836 check_insn(env, ctx, ASE_MT);
4837 gen_helper_mfc0_tcbind(arg, cpu_env);
4838 rn = "TCBind";
4839 break;
4840 case 3:
4841 check_insn(env, ctx, ASE_MT);
4842 gen_helper_dmfc0_tcrestart(arg, cpu_env);
4843 rn = "TCRestart";
4844 break;
4845 case 4:
4846 check_insn(env, ctx, ASE_MT);
4847 gen_helper_dmfc0_tchalt(arg, cpu_env);
4848 rn = "TCHalt";
4849 break;
4850 case 5:
4851 check_insn(env, ctx, ASE_MT);
4852 gen_helper_dmfc0_tccontext(arg, cpu_env);
4853 rn = "TCContext";
4854 break;
4855 case 6:
4856 check_insn(env, ctx, ASE_MT);
4857 gen_helper_dmfc0_tcschedule(arg, cpu_env);
4858 rn = "TCSchedule";
4859 break;
4860 case 7:
4861 check_insn(env, ctx, ASE_MT);
4862 gen_helper_dmfc0_tcschefback(arg, cpu_env);
4863 rn = "TCScheFBack";
4864 break;
4865 default:
4866 goto die;
4868 break;
4869 case 3:
4870 switch (sel) {
4871 case 0:
4872 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
4873 rn = "EntryLo1";
4874 break;
4875 default:
4876 goto die;
4878 break;
4879 case 4:
4880 switch (sel) {
4881 case 0:
4882 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
4883 rn = "Context";
4884 break;
4885 case 1:
4886 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4887 rn = "ContextConfig";
4888 // break;
4889 default:
4890 goto die;
4892 break;
4893 case 5:
4894 switch (sel) {
4895 case 0:
4896 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
4897 rn = "PageMask";
4898 break;
4899 case 1:
4900 check_insn(env, ctx, ISA_MIPS32R2);
4901 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
4902 rn = "PageGrain";
4903 break;
4904 default:
4905 goto die;
4907 break;
4908 case 6:
4909 switch (sel) {
4910 case 0:
4911 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
4912 rn = "Wired";
4913 break;
4914 case 1:
4915 check_insn(env, ctx, ISA_MIPS32R2);
4916 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
4917 rn = "SRSConf0";
4918 break;
4919 case 2:
4920 check_insn(env, ctx, ISA_MIPS32R2);
4921 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
4922 rn = "SRSConf1";
4923 break;
4924 case 3:
4925 check_insn(env, ctx, ISA_MIPS32R2);
4926 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
4927 rn = "SRSConf2";
4928 break;
4929 case 4:
4930 check_insn(env, ctx, ISA_MIPS32R2);
4931 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
4932 rn = "SRSConf3";
4933 break;
4934 case 5:
4935 check_insn(env, ctx, ISA_MIPS32R2);
4936 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
4937 rn = "SRSConf4";
4938 break;
4939 default:
4940 goto die;
4942 break;
4943 case 7:
4944 switch (sel) {
4945 case 0:
4946 check_insn(env, ctx, ISA_MIPS32R2);
4947 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
4948 rn = "HWREna";
4949 break;
4950 default:
4951 goto die;
4953 break;
4954 case 8:
4955 switch (sel) {
4956 case 0:
4957 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
4958 rn = "BadVAddr";
4959 break;
4960 default:
4961 goto die;
4963 break;
4964 case 9:
4965 switch (sel) {
4966 case 0:
4967 /* Mark as an IO operation because we read the time. */
4968 if (use_icount)
4969 gen_io_start();
4970 gen_helper_mfc0_count(arg, cpu_env);
4971 if (use_icount) {
4972 gen_io_end();
4974 /* Break the TB to be able to take timer interrupts immediately
4975 after reading count. */
4976 ctx->bstate = BS_STOP;
4977 rn = "Count";
4978 break;
4979 /* 6,7 are implementation dependent */
4980 default:
4981 goto die;
4983 break;
4984 case 10:
4985 switch (sel) {
4986 case 0:
4987 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
4988 rn = "EntryHi";
4989 break;
4990 default:
4991 goto die;
4993 break;
4994 case 11:
4995 switch (sel) {
4996 case 0:
4997 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
4998 rn = "Compare";
4999 break;
5000 /* 6,7 are implementation dependent */
5001 default:
5002 goto die;
5004 break;
5005 case 12:
5006 switch (sel) {
5007 case 0:
5008 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5009 rn = "Status";
5010 break;
5011 case 1:
5012 check_insn(env, ctx, ISA_MIPS32R2);
5013 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5014 rn = "IntCtl";
5015 break;
5016 case 2:
5017 check_insn(env, ctx, ISA_MIPS32R2);
5018 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5019 rn = "SRSCtl";
5020 break;
5021 case 3:
5022 check_insn(env, ctx, ISA_MIPS32R2);
5023 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5024 rn = "SRSMap";
5025 break;
5026 default:
5027 goto die;
5029 break;
5030 case 13:
5031 switch (sel) {
5032 case 0:
5033 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5034 rn = "Cause";
5035 break;
5036 default:
5037 goto die;
5039 break;
5040 case 14:
5041 switch (sel) {
5042 case 0:
5043 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5044 rn = "EPC";
5045 break;
5046 default:
5047 goto die;
5049 break;
5050 case 15:
5051 switch (sel) {
5052 case 0:
5053 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5054 rn = "PRid";
5055 break;
5056 case 1:
5057 check_insn(env, ctx, ISA_MIPS32R2);
5058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5059 rn = "EBase";
5060 break;
5061 default:
5062 goto die;
5064 break;
5065 case 16:
5066 switch (sel) {
5067 case 0:
5068 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5069 rn = "Config";
5070 break;
5071 case 1:
5072 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5073 rn = "Config1";
5074 break;
5075 case 2:
5076 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5077 rn = "Config2";
5078 break;
5079 case 3:
5080 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5081 rn = "Config3";
5082 break;
5083 /* 6,7 are implementation dependent */
5084 case 6:
5085 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5086 rn = "Config6";
5087 break;
5088 case 7:
5089 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5090 rn = "Config7";
5091 break;
5092 default:
5093 goto die;
5095 break;
5096 case 17:
5097 switch (sel) {
5098 case 0:
5099 gen_helper_dmfc0_lladdr(arg, cpu_env);
5100 rn = "LLAddr";
5101 break;
5102 default:
5103 goto die;
5105 break;
5106 case 18:
5107 switch (sel) {
5108 case 0 ... 7:
5109 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
5110 rn = "WatchLo";
5111 break;
5112 default:
5113 goto die;
5115 break;
5116 case 19:
5117 switch (sel) {
5118 case 0 ... 7:
5119 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5120 rn = "WatchHi";
5121 break;
5122 default:
5123 goto die;
5125 break;
5126 case 20:
5127 switch (sel) {
5128 case 0:
5129 check_insn(env, ctx, ISA_MIPS3);
5130 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5131 rn = "XContext";
5132 break;
5133 default:
5134 goto die;
5136 break;
5137 case 21:
5138 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5139 switch (sel) {
5140 case 0:
5141 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5142 rn = "Framemask";
5143 break;
5144 default:
5145 goto die;
5147 break;
5148 case 22:
5149 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5150 rn = "'Diagnostic"; /* implementation dependent */
5151 break;
5152 case 23:
5153 switch (sel) {
5154 case 0:
5155 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5156 rn = "Debug";
5157 break;
5158 case 1:
5159 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
5160 rn = "TraceControl";
5161 // break;
5162 case 2:
5163 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
5164 rn = "TraceControl2";
5165 // break;
5166 case 3:
5167 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
5168 rn = "UserTraceData";
5169 // break;
5170 case 4:
5171 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
5172 rn = "TraceBPC";
5173 // break;
5174 default:
5175 goto die;
5177 break;
5178 case 24:
5179 switch (sel) {
5180 case 0:
5181 /* EJTAG support */
5182 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5183 rn = "DEPC";
5184 break;
5185 default:
5186 goto die;
5188 break;
5189 case 25:
5190 switch (sel) {
5191 case 0:
5192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5193 rn = "Performance0";
5194 break;
5195 case 1:
5196 // gen_helper_dmfc0_performance1(arg);
5197 rn = "Performance1";
5198 // break;
5199 case 2:
5200 // gen_helper_dmfc0_performance2(arg);
5201 rn = "Performance2";
5202 // break;
5203 case 3:
5204 // gen_helper_dmfc0_performance3(arg);
5205 rn = "Performance3";
5206 // break;
5207 case 4:
5208 // gen_helper_dmfc0_performance4(arg);
5209 rn = "Performance4";
5210 // break;
5211 case 5:
5212 // gen_helper_dmfc0_performance5(arg);
5213 rn = "Performance5";
5214 // break;
5215 case 6:
5216 // gen_helper_dmfc0_performance6(arg);
5217 rn = "Performance6";
5218 // break;
5219 case 7:
5220 // gen_helper_dmfc0_performance7(arg);
5221 rn = "Performance7";
5222 // break;
5223 default:
5224 goto die;
5226 break;
5227 case 26:
5228 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5229 rn = "ECC";
5230 break;
5231 case 27:
5232 switch (sel) {
5233 /* ignored */
5234 case 0 ... 3:
5235 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5236 rn = "CacheErr";
5237 break;
5238 default:
5239 goto die;
5241 break;
5242 case 28:
5243 switch (sel) {
5244 case 0:
5245 case 2:
5246 case 4:
5247 case 6:
5248 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
5249 rn = "TagLo";
5250 break;
5251 case 1:
5252 case 3:
5253 case 5:
5254 case 7:
5255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5256 rn = "DataLo";
5257 break;
5258 default:
5259 goto die;
5261 break;
5262 case 29:
5263 switch (sel) {
5264 case 0:
5265 case 2:
5266 case 4:
5267 case 6:
5268 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5269 rn = "TagHi";
5270 break;
5271 case 1:
5272 case 3:
5273 case 5:
5274 case 7:
5275 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5276 rn = "DataHi";
5277 break;
5278 default:
5279 goto die;
5281 break;
5282 case 30:
5283 switch (sel) {
5284 case 0:
5285 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5286 rn = "ErrorEPC";
5287 break;
5288 default:
5289 goto die;
5291 break;
5292 case 31:
5293 switch (sel) {
5294 case 0:
5295 /* EJTAG support */
5296 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5297 rn = "DESAVE";
5298 break;
5299 default:
5300 goto die;
5302 break;
5303 default:
5304 goto die;
5306 (void)rn; /* avoid a compiler warning */
5307 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5308 return;
5310 die:
5311 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5312 generate_exception(ctx, EXCP_RI);
5315 static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
5317 const char *rn = "invalid";
5319 if (sel != 0)
5320 check_insn(env, ctx, ISA_MIPS64);
5322 if (use_icount)
5323 gen_io_start();
5325 switch (reg) {
5326 case 0:
5327 switch (sel) {
5328 case 0:
5329 gen_helper_mtc0_index(cpu_env, arg);
5330 rn = "Index";
5331 break;
5332 case 1:
5333 check_insn(env, ctx, ASE_MT);
5334 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5335 rn = "MVPControl";
5336 break;
5337 case 2:
5338 check_insn(env, ctx, ASE_MT);
5339 /* ignored */
5340 rn = "MVPConf0";
5341 break;
5342 case 3:
5343 check_insn(env, ctx, ASE_MT);
5344 /* ignored */
5345 rn = "MVPConf1";
5346 break;
5347 default:
5348 goto die;
5350 break;
5351 case 1:
5352 switch (sel) {
5353 case 0:
5354 /* ignored */
5355 rn = "Random";
5356 break;
5357 case 1:
5358 check_insn(env, ctx, ASE_MT);
5359 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5360 rn = "VPEControl";
5361 break;
5362 case 2:
5363 check_insn(env, ctx, ASE_MT);
5364 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5365 rn = "VPEConf0";
5366 break;
5367 case 3:
5368 check_insn(env, ctx, ASE_MT);
5369 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5370 rn = "VPEConf1";
5371 break;
5372 case 4:
5373 check_insn(env, ctx, ASE_MT);
5374 gen_helper_mtc0_yqmask(cpu_env, arg);
5375 rn = "YQMask";
5376 break;
5377 case 5:
5378 check_insn(env, ctx, ASE_MT);
5379 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
5380 rn = "VPESchedule";
5381 break;
5382 case 6:
5383 check_insn(env, ctx, ASE_MT);
5384 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5385 rn = "VPEScheFBack";
5386 break;
5387 case 7:
5388 check_insn(env, ctx, ASE_MT);
5389 gen_helper_mtc0_vpeopt(cpu_env, arg);
5390 rn = "VPEOpt";
5391 break;
5392 default:
5393 goto die;
5395 break;
5396 case 2:
5397 switch (sel) {
5398 case 0:
5399 gen_helper_mtc0_entrylo0(cpu_env, arg);
5400 rn = "EntryLo0";
5401 break;
5402 case 1:
5403 check_insn(env, ctx, ASE_MT);
5404 gen_helper_mtc0_tcstatus(cpu_env, arg);
5405 rn = "TCStatus";
5406 break;
5407 case 2:
5408 check_insn(env, ctx, ASE_MT);
5409 gen_helper_mtc0_tcbind(cpu_env, arg);
5410 rn = "TCBind";
5411 break;
5412 case 3:
5413 check_insn(env, ctx, ASE_MT);
5414 gen_helper_mtc0_tcrestart(cpu_env, arg);
5415 rn = "TCRestart";
5416 break;
5417 case 4:
5418 check_insn(env, ctx, ASE_MT);
5419 gen_helper_mtc0_tchalt(cpu_env, arg);
5420 rn = "TCHalt";
5421 break;
5422 case 5:
5423 check_insn(env, ctx, ASE_MT);
5424 gen_helper_mtc0_tccontext(cpu_env, arg);
5425 rn = "TCContext";
5426 break;
5427 case 6:
5428 check_insn(env, ctx, ASE_MT);
5429 gen_helper_mtc0_tcschedule(cpu_env, arg);
5430 rn = "TCSchedule";
5431 break;
5432 case 7:
5433 check_insn(env, ctx, ASE_MT);
5434 gen_helper_mtc0_tcschefback(cpu_env, arg);
5435 rn = "TCScheFBack";
5436 break;
5437 default:
5438 goto die;
5440 break;
5441 case 3:
5442 switch (sel) {
5443 case 0:
5444 gen_helper_mtc0_entrylo1(cpu_env, arg);
5445 rn = "EntryLo1";
5446 break;
5447 default:
5448 goto die;
5450 break;
5451 case 4:
5452 switch (sel) {
5453 case 0:
5454 gen_helper_mtc0_context(cpu_env, arg);
5455 rn = "Context";
5456 break;
5457 case 1:
5458 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5459 rn = "ContextConfig";
5460 // break;
5461 default:
5462 goto die;
5464 break;
5465 case 5:
5466 switch (sel) {
5467 case 0:
5468 gen_helper_mtc0_pagemask(cpu_env, arg);
5469 rn = "PageMask";
5470 break;
5471 case 1:
5472 check_insn(env, ctx, ISA_MIPS32R2);
5473 gen_helper_mtc0_pagegrain(cpu_env, arg);
5474 rn = "PageGrain";
5475 break;
5476 default:
5477 goto die;
5479 break;
5480 case 6:
5481 switch (sel) {
5482 case 0:
5483 gen_helper_mtc0_wired(cpu_env, arg);
5484 rn = "Wired";
5485 break;
5486 case 1:
5487 check_insn(env, ctx, ISA_MIPS32R2);
5488 gen_helper_mtc0_srsconf0(cpu_env, arg);
5489 rn = "SRSConf0";
5490 break;
5491 case 2:
5492 check_insn(env, ctx, ISA_MIPS32R2);
5493 gen_helper_mtc0_srsconf1(cpu_env, arg);
5494 rn = "SRSConf1";
5495 break;
5496 case 3:
5497 check_insn(env, ctx, ISA_MIPS32R2);
5498 gen_helper_mtc0_srsconf2(cpu_env, arg);
5499 rn = "SRSConf2";
5500 break;
5501 case 4:
5502 check_insn(env, ctx, ISA_MIPS32R2);
5503 gen_helper_mtc0_srsconf3(cpu_env, arg);
5504 rn = "SRSConf3";
5505 break;
5506 case 5:
5507 check_insn(env, ctx, ISA_MIPS32R2);
5508 gen_helper_mtc0_srsconf4(cpu_env, arg);
5509 rn = "SRSConf4";
5510 break;
5511 default:
5512 goto die;
5514 break;
5515 case 7:
5516 switch (sel) {
5517 case 0:
5518 check_insn(env, ctx, ISA_MIPS32R2);
5519 gen_helper_mtc0_hwrena(cpu_env, arg);
5520 rn = "HWREna";
5521 break;
5522 default:
5523 goto die;
5525 break;
5526 case 8:
5527 /* ignored */
5528 rn = "BadVAddr";
5529 break;
5530 case 9:
5531 switch (sel) {
5532 case 0:
5533 gen_helper_mtc0_count(cpu_env, arg);
5534 rn = "Count";
5535 break;
5536 /* 6,7 are implementation dependent */
5537 default:
5538 goto die;
5540 /* Stop translation as we may have switched the execution mode */
5541 ctx->bstate = BS_STOP;
5542 break;
5543 case 10:
5544 switch (sel) {
5545 case 0:
5546 gen_helper_mtc0_entryhi(cpu_env, arg);
5547 rn = "EntryHi";
5548 break;
5549 default:
5550 goto die;
5552 break;
5553 case 11:
5554 switch (sel) {
5555 case 0:
5556 gen_helper_mtc0_compare(cpu_env, arg);
5557 rn = "Compare";
5558 break;
5559 /* 6,7 are implementation dependent */
5560 default:
5561 goto die;
5563 /* Stop translation as we may have switched the execution mode */
5564 ctx->bstate = BS_STOP;
5565 break;
5566 case 12:
5567 switch (sel) {
5568 case 0:
5569 save_cpu_state(ctx, 1);
5570 gen_helper_mtc0_status(cpu_env, arg);
5571 /* BS_STOP isn't good enough here, hflags may have changed. */
5572 gen_save_pc(ctx->pc + 4);
5573 ctx->bstate = BS_EXCP;
5574 rn = "Status";
5575 break;
5576 case 1:
5577 check_insn(env, ctx, ISA_MIPS32R2);
5578 gen_helper_mtc0_intctl(cpu_env, arg);
5579 /* Stop translation as we may have switched the execution mode */
5580 ctx->bstate = BS_STOP;
5581 rn = "IntCtl";
5582 break;
5583 case 2:
5584 check_insn(env, ctx, ISA_MIPS32R2);
5585 gen_helper_mtc0_srsctl(cpu_env, arg);
5586 /* Stop translation as we may have switched the execution mode */
5587 ctx->bstate = BS_STOP;
5588 rn = "SRSCtl";
5589 break;
5590 case 3:
5591 check_insn(env, ctx, ISA_MIPS32R2);
5592 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5593 /* Stop translation as we may have switched the execution mode */
5594 ctx->bstate = BS_STOP;
5595 rn = "SRSMap";
5596 break;
5597 default:
5598 goto die;
5600 break;
5601 case 13:
5602 switch (sel) {
5603 case 0:
5604 save_cpu_state(ctx, 1);
5605 /* Mark as an IO operation because we may trigger a software
5606 interrupt. */
5607 if (use_icount) {
5608 gen_io_start();
5610 gen_helper_mtc0_cause(cpu_env, arg);
5611 if (use_icount) {
5612 gen_io_end();
5614 /* Stop translation as we may have triggered an intetrupt */
5615 ctx->bstate = BS_STOP;
5616 rn = "Cause";
5617 break;
5618 default:
5619 goto die;
5621 break;
5622 case 14:
5623 switch (sel) {
5624 case 0:
5625 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5626 rn = "EPC";
5627 break;
5628 default:
5629 goto die;
5631 break;
5632 case 15:
5633 switch (sel) {
5634 case 0:
5635 /* ignored */
5636 rn = "PRid";
5637 break;
5638 case 1:
5639 check_insn(env, ctx, ISA_MIPS32R2);
5640 gen_helper_mtc0_ebase(cpu_env, arg);
5641 rn = "EBase";
5642 break;
5643 default:
5644 goto die;
5646 break;
5647 case 16:
5648 switch (sel) {
5649 case 0:
5650 gen_helper_mtc0_config0(cpu_env, arg);
5651 rn = "Config";
5652 /* Stop translation as we may have switched the execution mode */
5653 ctx->bstate = BS_STOP;
5654 break;
5655 case 1:
5656 /* ignored, read only */
5657 rn = "Config1";
5658 break;
5659 case 2:
5660 gen_helper_mtc0_config2(cpu_env, arg);
5661 rn = "Config2";
5662 /* Stop translation as we may have switched the execution mode */
5663 ctx->bstate = BS_STOP;
5664 break;
5665 case 3:
5666 /* ignored */
5667 rn = "Config3";
5668 break;
5669 /* 6,7 are implementation dependent */
5670 default:
5671 rn = "Invalid config selector";
5672 goto die;
5674 break;
5675 case 17:
5676 switch (sel) {
5677 case 0:
5678 gen_helper_mtc0_lladdr(cpu_env, arg);
5679 rn = "LLAddr";
5680 break;
5681 default:
5682 goto die;
5684 break;
5685 case 18:
5686 switch (sel) {
5687 case 0 ... 7:
5688 gen_helper_0e1i(mtc0_watchlo, arg, sel);
5689 rn = "WatchLo";
5690 break;
5691 default:
5692 goto die;
5694 break;
5695 case 19:
5696 switch (sel) {
5697 case 0 ... 7:
5698 gen_helper_0e1i(mtc0_watchhi, arg, sel);
5699 rn = "WatchHi";
5700 break;
5701 default:
5702 goto die;
5704 break;
5705 case 20:
5706 switch (sel) {
5707 case 0:
5708 check_insn(env, ctx, ISA_MIPS3);
5709 gen_helper_mtc0_xcontext(cpu_env, arg);
5710 rn = "XContext";
5711 break;
5712 default:
5713 goto die;
5715 break;
5716 case 21:
5717 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5718 switch (sel) {
5719 case 0:
5720 gen_helper_mtc0_framemask(cpu_env, arg);
5721 rn = "Framemask";
5722 break;
5723 default:
5724 goto die;
5726 break;
5727 case 22:
5728 /* ignored */
5729 rn = "Diagnostic"; /* implementation dependent */
5730 break;
5731 case 23:
5732 switch (sel) {
5733 case 0:
5734 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
5735 /* BS_STOP isn't good enough here, hflags may have changed. */
5736 gen_save_pc(ctx->pc + 4);
5737 ctx->bstate = BS_EXCP;
5738 rn = "Debug";
5739 break;
5740 case 1:
5741 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
5742 /* Stop translation as we may have switched the execution mode */
5743 ctx->bstate = BS_STOP;
5744 rn = "TraceControl";
5745 // break;
5746 case 2:
5747 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
5748 /* Stop translation as we may have switched the execution mode */
5749 ctx->bstate = BS_STOP;
5750 rn = "TraceControl2";
5751 // break;
5752 case 3:
5753 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
5754 /* Stop translation as we may have switched the execution mode */
5755 ctx->bstate = BS_STOP;
5756 rn = "UserTraceData";
5757 // break;
5758 case 4:
5759 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
5760 /* Stop translation as we may have switched the execution mode */
5761 ctx->bstate = BS_STOP;
5762 rn = "TraceBPC";
5763 // break;
5764 default:
5765 goto die;
5767 break;
5768 case 24:
5769 switch (sel) {
5770 case 0:
5771 /* EJTAG support */
5772 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5773 rn = "DEPC";
5774 break;
5775 default:
5776 goto die;
5778 break;
5779 case 25:
5780 switch (sel) {
5781 case 0:
5782 gen_helper_mtc0_performance0(cpu_env, arg);
5783 rn = "Performance0";
5784 break;
5785 case 1:
5786 // gen_helper_mtc0_performance1(cpu_env, arg);
5787 rn = "Performance1";
5788 // break;
5789 case 2:
5790 // gen_helper_mtc0_performance2(cpu_env, arg);
5791 rn = "Performance2";
5792 // break;
5793 case 3:
5794 // gen_helper_mtc0_performance3(cpu_env, arg);
5795 rn = "Performance3";
5796 // break;
5797 case 4:
5798 // gen_helper_mtc0_performance4(cpu_env, arg);
5799 rn = "Performance4";
5800 // break;
5801 case 5:
5802 // gen_helper_mtc0_performance5(cpu_env, arg);
5803 rn = "Performance5";
5804 // break;
5805 case 6:
5806 // gen_helper_mtc0_performance6(cpu_env, arg);
5807 rn = "Performance6";
5808 // break;
5809 case 7:
5810 // gen_helper_mtc0_performance7(cpu_env, arg);
5811 rn = "Performance7";
5812 // break;
5813 default:
5814 goto die;
5816 break;
5817 case 26:
5818 /* ignored */
5819 rn = "ECC";
5820 break;
5821 case 27:
5822 switch (sel) {
5823 case 0 ... 3:
5824 /* ignored */
5825 rn = "CacheErr";
5826 break;
5827 default:
5828 goto die;
5830 break;
5831 case 28:
5832 switch (sel) {
5833 case 0:
5834 case 2:
5835 case 4:
5836 case 6:
5837 gen_helper_mtc0_taglo(cpu_env, arg);
5838 rn = "TagLo";
5839 break;
5840 case 1:
5841 case 3:
5842 case 5:
5843 case 7:
5844 gen_helper_mtc0_datalo(cpu_env, arg);
5845 rn = "DataLo";
5846 break;
5847 default:
5848 goto die;
5850 break;
5851 case 29:
5852 switch (sel) {
5853 case 0:
5854 case 2:
5855 case 4:
5856 case 6:
5857 gen_helper_mtc0_taghi(cpu_env, arg);
5858 rn = "TagHi";
5859 break;
5860 case 1:
5861 case 3:
5862 case 5:
5863 case 7:
5864 gen_helper_mtc0_datahi(cpu_env, arg);
5865 rn = "DataHi";
5866 break;
5867 default:
5868 rn = "invalid sel";
5869 goto die;
5871 break;
5872 case 30:
5873 switch (sel) {
5874 case 0:
5875 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5876 rn = "ErrorEPC";
5877 break;
5878 default:
5879 goto die;
5881 break;
5882 case 31:
5883 switch (sel) {
5884 case 0:
5885 /* EJTAG support */
5886 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5887 rn = "DESAVE";
5888 break;
5889 default:
5890 goto die;
5892 /* Stop translation as we may have switched the execution mode */
5893 ctx->bstate = BS_STOP;
5894 break;
5895 default:
5896 goto die;
5898 (void)rn; /* avoid a compiler warning */
5899 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5900 /* For simplicity assume that all writes can cause interrupts. */
5901 if (use_icount) {
5902 gen_io_end();
5903 ctx->bstate = BS_STOP;
5905 return;
5907 die:
5908 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5909 generate_exception(ctx, EXCP_RI);
5911 #endif /* TARGET_MIPS64 */
5913 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
5914 int u, int sel, int h)
5916 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5917 TCGv t0 = tcg_temp_local_new();
5919 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5920 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5921 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5922 tcg_gen_movi_tl(t0, -1);
5923 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5924 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5925 tcg_gen_movi_tl(t0, -1);
5926 else if (u == 0) {
5927 switch (rt) {
5928 case 1:
5929 switch (sel) {
5930 case 1:
5931 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5932 break;
5933 case 2:
5934 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5935 break;
5936 default:
5937 goto die;
5938 break;
5940 break;
5941 case 2:
5942 switch (sel) {
5943 case 1:
5944 gen_helper_mftc0_tcstatus(t0, cpu_env);
5945 break;
5946 case 2:
5947 gen_helper_mftc0_tcbind(t0, cpu_env);
5948 break;
5949 case 3:
5950 gen_helper_mftc0_tcrestart(t0, cpu_env);
5951 break;
5952 case 4:
5953 gen_helper_mftc0_tchalt(t0, cpu_env);
5954 break;
5955 case 5:
5956 gen_helper_mftc0_tccontext(t0, cpu_env);
5957 break;
5958 case 6:
5959 gen_helper_mftc0_tcschedule(t0, cpu_env);
5960 break;
5961 case 7:
5962 gen_helper_mftc0_tcschefback(t0, cpu_env);
5963 break;
5964 default:
5965 gen_mfc0(env, ctx, t0, rt, sel);
5966 break;
5968 break;
5969 case 10:
5970 switch (sel) {
5971 case 0:
5972 gen_helper_mftc0_entryhi(t0, cpu_env);
5973 break;
5974 default:
5975 gen_mfc0(env, ctx, t0, rt, sel);
5976 break;
5978 case 12:
5979 switch (sel) {
5980 case 0:
5981 gen_helper_mftc0_status(t0, cpu_env);
5982 break;
5983 default:
5984 gen_mfc0(env, ctx, t0, rt, sel);
5985 break;
5987 case 13:
5988 switch (sel) {
5989 case 0:
5990 gen_helper_mftc0_cause(t0, cpu_env);
5991 break;
5992 default:
5993 goto die;
5994 break;
5996 break;
5997 case 14:
5998 switch (sel) {
5999 case 0:
6000 gen_helper_mftc0_epc(t0, cpu_env);
6001 break;
6002 default:
6003 goto die;
6004 break;
6006 break;
6007 case 15:
6008 switch (sel) {
6009 case 1:
6010 gen_helper_mftc0_ebase(t0, cpu_env);
6011 break;
6012 default:
6013 goto die;
6014 break;
6016 break;
6017 case 16:
6018 switch (sel) {
6019 case 0 ... 7:
6020 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
6021 break;
6022 default:
6023 goto die;
6024 break;
6026 break;
6027 case 23:
6028 switch (sel) {
6029 case 0:
6030 gen_helper_mftc0_debug(t0, cpu_env);
6031 break;
6032 default:
6033 gen_mfc0(env, ctx, t0, rt, sel);
6034 break;
6036 break;
6037 default:
6038 gen_mfc0(env, ctx, t0, rt, sel);
6040 } else switch (sel) {
6041 /* GPR registers. */
6042 case 0:
6043 gen_helper_1e0i(mftgpr, t0, rt);
6044 break;
6045 /* Auxiliary CPU registers */
6046 case 1:
6047 switch (rt) {
6048 case 0:
6049 gen_helper_1e0i(mftlo, t0, 0);
6050 break;
6051 case 1:
6052 gen_helper_1e0i(mfthi, t0, 0);
6053 break;
6054 case 2:
6055 gen_helper_1e0i(mftacx, t0, 0);
6056 break;
6057 case 4:
6058 gen_helper_1e0i(mftlo, t0, 1);
6059 break;
6060 case 5:
6061 gen_helper_1e0i(mfthi, t0, 1);
6062 break;
6063 case 6:
6064 gen_helper_1e0i(mftacx, t0, 1);
6065 break;
6066 case 8:
6067 gen_helper_1e0i(mftlo, t0, 2);
6068 break;
6069 case 9:
6070 gen_helper_1e0i(mfthi, t0, 2);
6071 break;
6072 case 10:
6073 gen_helper_1e0i(mftacx, t0, 2);
6074 break;
6075 case 12:
6076 gen_helper_1e0i(mftlo, t0, 3);
6077 break;
6078 case 13:
6079 gen_helper_1e0i(mfthi, t0, 3);
6080 break;
6081 case 14:
6082 gen_helper_1e0i(mftacx, t0, 3);
6083 break;
6084 case 16:
6085 gen_helper_mftdsp(t0, cpu_env);
6086 break;
6087 default:
6088 goto die;
6090 break;
6091 /* Floating point (COP1). */
6092 case 2:
6093 /* XXX: For now we support only a single FPU context. */
6094 if (h == 0) {
6095 TCGv_i32 fp0 = tcg_temp_new_i32();
6097 gen_load_fpr32(fp0, rt);
6098 tcg_gen_ext_i32_tl(t0, fp0);
6099 tcg_temp_free_i32(fp0);
6100 } else {
6101 TCGv_i32 fp0 = tcg_temp_new_i32();
6103 gen_load_fpr32h(fp0, rt);
6104 tcg_gen_ext_i32_tl(t0, fp0);
6105 tcg_temp_free_i32(fp0);
6107 break;
6108 case 3:
6109 /* XXX: For now we support only a single FPU context. */
6110 gen_helper_1e0i(cfc1, t0, rt);
6111 break;
6112 /* COP2: Not implemented. */
6113 case 4:
6114 case 5:
6115 /* fall through */
6116 default:
6117 goto die;
6119 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
6120 gen_store_gpr(t0, rd);
6121 tcg_temp_free(t0);
6122 return;
6124 die:
6125 tcg_temp_free(t0);
6126 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
6127 generate_exception(ctx, EXCP_RI);
6130 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
6131 int u, int sel, int h)
6133 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
6134 TCGv t0 = tcg_temp_local_new();
6136 gen_load_gpr(t0, rt);
6137 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
6138 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6139 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
6140 /* NOP */ ;
6141 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6142 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
6143 /* NOP */ ;
6144 else if (u == 0) {
6145 switch (rd) {
6146 case 1:
6147 switch (sel) {
6148 case 1:
6149 gen_helper_mttc0_vpecontrol(cpu_env, t0);
6150 break;
6151 case 2:
6152 gen_helper_mttc0_vpeconf0(cpu_env, t0);
6153 break;
6154 default:
6155 goto die;
6156 break;
6158 break;
6159 case 2:
6160 switch (sel) {
6161 case 1:
6162 gen_helper_mttc0_tcstatus(cpu_env, t0);
6163 break;
6164 case 2:
6165 gen_helper_mttc0_tcbind(cpu_env, t0);
6166 break;
6167 case 3:
6168 gen_helper_mttc0_tcrestart(cpu_env, t0);
6169 break;
6170 case 4:
6171 gen_helper_mttc0_tchalt(cpu_env, t0);
6172 break;
6173 case 5:
6174 gen_helper_mttc0_tccontext(cpu_env, t0);
6175 break;
6176 case 6:
6177 gen_helper_mttc0_tcschedule(cpu_env, t0);
6178 break;
6179 case 7:
6180 gen_helper_mttc0_tcschefback(cpu_env, t0);
6181 break;
6182 default:
6183 gen_mtc0(env, ctx, t0, rd, sel);
6184 break;
6186 break;
6187 case 10:
6188 switch (sel) {
6189 case 0:
6190 gen_helper_mttc0_entryhi(cpu_env, t0);
6191 break;
6192 default:
6193 gen_mtc0(env, ctx, t0, rd, sel);
6194 break;
6196 case 12:
6197 switch (sel) {
6198 case 0:
6199 gen_helper_mttc0_status(cpu_env, t0);
6200 break;
6201 default:
6202 gen_mtc0(env, ctx, t0, rd, sel);
6203 break;
6205 case 13:
6206 switch (sel) {
6207 case 0:
6208 gen_helper_mttc0_cause(cpu_env, t0);
6209 break;
6210 default:
6211 goto die;
6212 break;
6214 break;
6215 case 15:
6216 switch (sel) {
6217 case 1:
6218 gen_helper_mttc0_ebase(cpu_env, t0);
6219 break;
6220 default:
6221 goto die;
6222 break;
6224 break;
6225 case 23:
6226 switch (sel) {
6227 case 0:
6228 gen_helper_mttc0_debug(cpu_env, t0);
6229 break;
6230 default:
6231 gen_mtc0(env, ctx, t0, rd, sel);
6232 break;
6234 break;
6235 default:
6236 gen_mtc0(env, ctx, t0, rd, sel);
6238 } else switch (sel) {
6239 /* GPR registers. */
6240 case 0:
6241 gen_helper_0e1i(mttgpr, t0, rd);
6242 break;
6243 /* Auxiliary CPU registers */
6244 case 1:
6245 switch (rd) {
6246 case 0:
6247 gen_helper_0e1i(mttlo, t0, 0);
6248 break;
6249 case 1:
6250 gen_helper_0e1i(mtthi, t0, 0);
6251 break;
6252 case 2:
6253 gen_helper_0e1i(mttacx, t0, 0);
6254 break;
6255 case 4:
6256 gen_helper_0e1i(mttlo, t0, 1);
6257 break;
6258 case 5:
6259 gen_helper_0e1i(mtthi, t0, 1);
6260 break;
6261 case 6:
6262 gen_helper_0e1i(mttacx, t0, 1);
6263 break;
6264 case 8:
6265 gen_helper_0e1i(mttlo, t0, 2);
6266 break;
6267 case 9:
6268 gen_helper_0e1i(mtthi, t0, 2);
6269 break;
6270 case 10:
6271 gen_helper_0e1i(mttacx, t0, 2);
6272 break;
6273 case 12:
6274 gen_helper_0e1i(mttlo, t0, 3);
6275 break;
6276 case 13:
6277 gen_helper_0e1i(mtthi, t0, 3);
6278 break;
6279 case 14:
6280 gen_helper_0e1i(mttacx, t0, 3);
6281 break;
6282 case 16:
6283 gen_helper_mttdsp(cpu_env, t0);
6284 break;
6285 default:
6286 goto die;
6288 break;
6289 /* Floating point (COP1). */
6290 case 2:
6291 /* XXX: For now we support only a single FPU context. */
6292 if (h == 0) {
6293 TCGv_i32 fp0 = tcg_temp_new_i32();
6295 tcg_gen_trunc_tl_i32(fp0, t0);
6296 gen_store_fpr32(fp0, rd);
6297 tcg_temp_free_i32(fp0);
6298 } else {
6299 TCGv_i32 fp0 = tcg_temp_new_i32();
6301 tcg_gen_trunc_tl_i32(fp0, t0);
6302 gen_store_fpr32h(fp0, rd);
6303 tcg_temp_free_i32(fp0);
6305 break;
6306 case 3:
6307 /* XXX: For now we support only a single FPU context. */
6308 gen_helper_0e1i(ctc1, t0, rd);
6309 break;
6310 /* COP2: Not implemented. */
6311 case 4:
6312 case 5:
6313 /* fall through */
6314 default:
6315 goto die;
6317 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
6318 tcg_temp_free(t0);
6319 return;
6321 die:
6322 tcg_temp_free(t0);
6323 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
6324 generate_exception(ctx, EXCP_RI);
6327 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6329 const char *opn = "ldst";
6331 check_cp0_enabled(ctx);
6332 switch (opc) {
6333 case OPC_MFC0:
6334 if (rt == 0) {
6335 /* Treat as NOP. */
6336 return;
6338 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6339 opn = "mfc0";
6340 break;
6341 case OPC_MTC0:
6343 TCGv t0 = tcg_temp_new();
6345 gen_load_gpr(t0, rt);
6346 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
6347 tcg_temp_free(t0);
6349 opn = "mtc0";
6350 break;
6351 #if defined(TARGET_MIPS64)
6352 case OPC_DMFC0:
6353 check_insn(env, ctx, ISA_MIPS3);
6354 if (rt == 0) {
6355 /* Treat as NOP. */
6356 return;
6358 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6359 opn = "dmfc0";
6360 break;
6361 case OPC_DMTC0:
6362 check_insn(env, ctx, ISA_MIPS3);
6364 TCGv t0 = tcg_temp_new();
6366 gen_load_gpr(t0, rt);
6367 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
6368 tcg_temp_free(t0);
6370 opn = "dmtc0";
6371 break;
6372 #endif
6373 case OPC_MFTR:
6374 check_insn(env, ctx, ASE_MT);
6375 if (rd == 0) {
6376 /* Treat as NOP. */
6377 return;
6379 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
6380 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6381 opn = "mftr";
6382 break;
6383 case OPC_MTTR:
6384 check_insn(env, ctx, ASE_MT);
6385 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
6386 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6387 opn = "mttr";
6388 break;
6389 case OPC_TLBWI:
6390 opn = "tlbwi";
6391 if (!env->tlb->helper_tlbwi)
6392 goto die;
6393 gen_helper_tlbwi(cpu_env);
6394 break;
6395 case OPC_TLBWR:
6396 opn = "tlbwr";
6397 if (!env->tlb->helper_tlbwr)
6398 goto die;
6399 gen_helper_tlbwr(cpu_env);
6400 break;
6401 case OPC_TLBP:
6402 opn = "tlbp";
6403 if (!env->tlb->helper_tlbp)
6404 goto die;
6405 gen_helper_tlbp(cpu_env);
6406 break;
6407 case OPC_TLBR:
6408 opn = "tlbr";
6409 if (!env->tlb->helper_tlbr)
6410 goto die;
6411 gen_helper_tlbr(cpu_env);
6412 break;
6413 case OPC_ERET:
6414 opn = "eret";
6415 check_insn(env, ctx, ISA_MIPS2);
6416 gen_helper_eret(cpu_env);
6417 ctx->bstate = BS_EXCP;
6418 break;
6419 case OPC_DERET:
6420 opn = "deret";
6421 check_insn(env, ctx, ISA_MIPS32);
6422 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
6423 MIPS_INVAL(opn);
6424 generate_exception(ctx, EXCP_RI);
6425 } else {
6426 gen_helper_deret(cpu_env);
6427 ctx->bstate = BS_EXCP;
6429 break;
6430 case OPC_WAIT:
6431 opn = "wait";
6432 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
6433 /* If we get an exception, we want to restart at next instruction */
6434 ctx->pc += 4;
6435 save_cpu_state(ctx, 1);
6436 ctx->pc -= 4;
6437 gen_helper_wait(cpu_env);
6438 ctx->bstate = BS_EXCP;
6439 break;
6440 default:
6441 die:
6442 MIPS_INVAL(opn);
6443 generate_exception(ctx, EXCP_RI);
6444 return;
6446 (void)opn; /* avoid a compiler warning */
6447 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
6449 #endif /* !CONFIG_USER_ONLY */
6451 /* CP1 Branches (before delay slot) */
6452 static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
6453 int32_t cc, int32_t offset)
6455 target_ulong btarget;
6456 const char *opn = "cp1 cond branch";
6457 TCGv_i32 t0 = tcg_temp_new_i32();
6459 if (cc != 0)
6460 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6462 btarget = ctx->pc + 4 + offset;
6464 switch (op) {
6465 case OPC_BC1F:
6466 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6467 tcg_gen_not_i32(t0, t0);
6468 tcg_gen_andi_i32(t0, t0, 1);
6469 tcg_gen_extu_i32_tl(bcond, t0);
6470 opn = "bc1f";
6471 goto not_likely;
6472 case OPC_BC1FL:
6473 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6474 tcg_gen_not_i32(t0, t0);
6475 tcg_gen_andi_i32(t0, t0, 1);
6476 tcg_gen_extu_i32_tl(bcond, t0);
6477 opn = "bc1fl";
6478 goto likely;
6479 case OPC_BC1T:
6480 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6481 tcg_gen_andi_i32(t0, t0, 1);
6482 tcg_gen_extu_i32_tl(bcond, t0);
6483 opn = "bc1t";
6484 goto not_likely;
6485 case OPC_BC1TL:
6486 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6487 tcg_gen_andi_i32(t0, t0, 1);
6488 tcg_gen_extu_i32_tl(bcond, t0);
6489 opn = "bc1tl";
6490 likely:
6491 ctx->hflags |= MIPS_HFLAG_BL;
6492 break;
6493 case OPC_BC1FANY2:
6495 TCGv_i32 t1 = tcg_temp_new_i32();
6496 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6497 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6498 tcg_gen_nand_i32(t0, t0, t1);
6499 tcg_temp_free_i32(t1);
6500 tcg_gen_andi_i32(t0, t0, 1);
6501 tcg_gen_extu_i32_tl(bcond, t0);
6503 opn = "bc1any2f";
6504 goto not_likely;
6505 case OPC_BC1TANY2:
6507 TCGv_i32 t1 = tcg_temp_new_i32();
6508 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6509 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6510 tcg_gen_or_i32(t0, t0, t1);
6511 tcg_temp_free_i32(t1);
6512 tcg_gen_andi_i32(t0, t0, 1);
6513 tcg_gen_extu_i32_tl(bcond, t0);
6515 opn = "bc1any2t";
6516 goto not_likely;
6517 case OPC_BC1FANY4:
6519 TCGv_i32 t1 = tcg_temp_new_i32();
6520 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6521 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6522 tcg_gen_and_i32(t0, t0, t1);
6523 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6524 tcg_gen_and_i32(t0, t0, t1);
6525 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6526 tcg_gen_nand_i32(t0, t0, t1);
6527 tcg_temp_free_i32(t1);
6528 tcg_gen_andi_i32(t0, t0, 1);
6529 tcg_gen_extu_i32_tl(bcond, t0);
6531 opn = "bc1any4f";
6532 goto not_likely;
6533 case OPC_BC1TANY4:
6535 TCGv_i32 t1 = tcg_temp_new_i32();
6536 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6537 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6538 tcg_gen_or_i32(t0, t0, t1);
6539 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6540 tcg_gen_or_i32(t0, t0, t1);
6541 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6542 tcg_gen_or_i32(t0, t0, t1);
6543 tcg_temp_free_i32(t1);
6544 tcg_gen_andi_i32(t0, t0, 1);
6545 tcg_gen_extu_i32_tl(bcond, t0);
6547 opn = "bc1any4t";
6548 not_likely:
6549 ctx->hflags |= MIPS_HFLAG_BC;
6550 break;
6551 default:
6552 MIPS_INVAL(opn);
6553 generate_exception (ctx, EXCP_RI);
6554 goto out;
6556 (void)opn; /* avoid a compiler warning */
6557 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6558 ctx->hflags, btarget);
6559 ctx->btarget = btarget;
6561 out:
6562 tcg_temp_free_i32(t0);
6565 /* Coprocessor 1 (FPU) */
6567 #define FOP(func, fmt) (((fmt) << 21) | (func))
6569 enum fopcode {
6570 OPC_ADD_S = FOP(0, FMT_S),
6571 OPC_SUB_S = FOP(1, FMT_S),
6572 OPC_MUL_S = FOP(2, FMT_S),
6573 OPC_DIV_S = FOP(3, FMT_S),
6574 OPC_SQRT_S = FOP(4, FMT_S),
6575 OPC_ABS_S = FOP(5, FMT_S),
6576 OPC_MOV_S = FOP(6, FMT_S),
6577 OPC_NEG_S = FOP(7, FMT_S),
6578 OPC_ROUND_L_S = FOP(8, FMT_S),
6579 OPC_TRUNC_L_S = FOP(9, FMT_S),
6580 OPC_CEIL_L_S = FOP(10, FMT_S),
6581 OPC_FLOOR_L_S = FOP(11, FMT_S),
6582 OPC_ROUND_W_S = FOP(12, FMT_S),
6583 OPC_TRUNC_W_S = FOP(13, FMT_S),
6584 OPC_CEIL_W_S = FOP(14, FMT_S),
6585 OPC_FLOOR_W_S = FOP(15, FMT_S),
6586 OPC_MOVCF_S = FOP(17, FMT_S),
6587 OPC_MOVZ_S = FOP(18, FMT_S),
6588 OPC_MOVN_S = FOP(19, FMT_S),
6589 OPC_RECIP_S = FOP(21, FMT_S),
6590 OPC_RSQRT_S = FOP(22, FMT_S),
6591 OPC_RECIP2_S = FOP(28, FMT_S),
6592 OPC_RECIP1_S = FOP(29, FMT_S),
6593 OPC_RSQRT1_S = FOP(30, FMT_S),
6594 OPC_RSQRT2_S = FOP(31, FMT_S),
6595 OPC_CVT_D_S = FOP(33, FMT_S),
6596 OPC_CVT_W_S = FOP(36, FMT_S),
6597 OPC_CVT_L_S = FOP(37, FMT_S),
6598 OPC_CVT_PS_S = FOP(38, FMT_S),
6599 OPC_CMP_F_S = FOP (48, FMT_S),
6600 OPC_CMP_UN_S = FOP (49, FMT_S),
6601 OPC_CMP_EQ_S = FOP (50, FMT_S),
6602 OPC_CMP_UEQ_S = FOP (51, FMT_S),
6603 OPC_CMP_OLT_S = FOP (52, FMT_S),
6604 OPC_CMP_ULT_S = FOP (53, FMT_S),
6605 OPC_CMP_OLE_S = FOP (54, FMT_S),
6606 OPC_CMP_ULE_S = FOP (55, FMT_S),
6607 OPC_CMP_SF_S = FOP (56, FMT_S),
6608 OPC_CMP_NGLE_S = FOP (57, FMT_S),
6609 OPC_CMP_SEQ_S = FOP (58, FMT_S),
6610 OPC_CMP_NGL_S = FOP (59, FMT_S),
6611 OPC_CMP_LT_S = FOP (60, FMT_S),
6612 OPC_CMP_NGE_S = FOP (61, FMT_S),
6613 OPC_CMP_LE_S = FOP (62, FMT_S),
6614 OPC_CMP_NGT_S = FOP (63, FMT_S),
6616 OPC_ADD_D = FOP(0, FMT_D),
6617 OPC_SUB_D = FOP(1, FMT_D),
6618 OPC_MUL_D = FOP(2, FMT_D),
6619 OPC_DIV_D = FOP(3, FMT_D),
6620 OPC_SQRT_D = FOP(4, FMT_D),
6621 OPC_ABS_D = FOP(5, FMT_D),
6622 OPC_MOV_D = FOP(6, FMT_D),
6623 OPC_NEG_D = FOP(7, FMT_D),
6624 OPC_ROUND_L_D = FOP(8, FMT_D),
6625 OPC_TRUNC_L_D = FOP(9, FMT_D),
6626 OPC_CEIL_L_D = FOP(10, FMT_D),
6627 OPC_FLOOR_L_D = FOP(11, FMT_D),
6628 OPC_ROUND_W_D = FOP(12, FMT_D),
6629 OPC_TRUNC_W_D = FOP(13, FMT_D),
6630 OPC_CEIL_W_D = FOP(14, FMT_D),
6631 OPC_FLOOR_W_D = FOP(15, FMT_D),
6632 OPC_MOVCF_D = FOP(17, FMT_D),
6633 OPC_MOVZ_D = FOP(18, FMT_D),
6634 OPC_MOVN_D = FOP(19, FMT_D),
6635 OPC_RECIP_D = FOP(21, FMT_D),
6636 OPC_RSQRT_D = FOP(22, FMT_D),
6637 OPC_RECIP2_D = FOP(28, FMT_D),
6638 OPC_RECIP1_D = FOP(29, FMT_D),
6639 OPC_RSQRT1_D = FOP(30, FMT_D),
6640 OPC_RSQRT2_D = FOP(31, FMT_D),
6641 OPC_CVT_S_D = FOP(32, FMT_D),
6642 OPC_CVT_W_D = FOP(36, FMT_D),
6643 OPC_CVT_L_D = FOP(37, FMT_D),
6644 OPC_CMP_F_D = FOP (48, FMT_D),
6645 OPC_CMP_UN_D = FOP (49, FMT_D),
6646 OPC_CMP_EQ_D = FOP (50, FMT_D),
6647 OPC_CMP_UEQ_D = FOP (51, FMT_D),
6648 OPC_CMP_OLT_D = FOP (52, FMT_D),
6649 OPC_CMP_ULT_D = FOP (53, FMT_D),
6650 OPC_CMP_OLE_D = FOP (54, FMT_D),
6651 OPC_CMP_ULE_D = FOP (55, FMT_D),
6652 OPC_CMP_SF_D = FOP (56, FMT_D),
6653 OPC_CMP_NGLE_D = FOP (57, FMT_D),
6654 OPC_CMP_SEQ_D = FOP (58, FMT_D),
6655 OPC_CMP_NGL_D = FOP (59, FMT_D),
6656 OPC_CMP_LT_D = FOP (60, FMT_D),
6657 OPC_CMP_NGE_D = FOP (61, FMT_D),
6658 OPC_CMP_LE_D = FOP (62, FMT_D),
6659 OPC_CMP_NGT_D = FOP (63, FMT_D),
6661 OPC_CVT_S_W = FOP(32, FMT_W),
6662 OPC_CVT_D_W = FOP(33, FMT_W),
6663 OPC_CVT_S_L = FOP(32, FMT_L),
6664 OPC_CVT_D_L = FOP(33, FMT_L),
6665 OPC_CVT_PS_PW = FOP(38, FMT_W),
6667 OPC_ADD_PS = FOP(0, FMT_PS),
6668 OPC_SUB_PS = FOP(1, FMT_PS),
6669 OPC_MUL_PS = FOP(2, FMT_PS),
6670 OPC_DIV_PS = FOP(3, FMT_PS),
6671 OPC_ABS_PS = FOP(5, FMT_PS),
6672 OPC_MOV_PS = FOP(6, FMT_PS),
6673 OPC_NEG_PS = FOP(7, FMT_PS),
6674 OPC_MOVCF_PS = FOP(17, FMT_PS),
6675 OPC_MOVZ_PS = FOP(18, FMT_PS),
6676 OPC_MOVN_PS = FOP(19, FMT_PS),
6677 OPC_ADDR_PS = FOP(24, FMT_PS),
6678 OPC_MULR_PS = FOP(26, FMT_PS),
6679 OPC_RECIP2_PS = FOP(28, FMT_PS),
6680 OPC_RECIP1_PS = FOP(29, FMT_PS),
6681 OPC_RSQRT1_PS = FOP(30, FMT_PS),
6682 OPC_RSQRT2_PS = FOP(31, FMT_PS),
6684 OPC_CVT_S_PU = FOP(32, FMT_PS),
6685 OPC_CVT_PW_PS = FOP(36, FMT_PS),
6686 OPC_CVT_S_PL = FOP(40, FMT_PS),
6687 OPC_PLL_PS = FOP(44, FMT_PS),
6688 OPC_PLU_PS = FOP(45, FMT_PS),
6689 OPC_PUL_PS = FOP(46, FMT_PS),
6690 OPC_PUU_PS = FOP(47, FMT_PS),
6691 OPC_CMP_F_PS = FOP (48, FMT_PS),
6692 OPC_CMP_UN_PS = FOP (49, FMT_PS),
6693 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6694 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6695 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6696 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6697 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6698 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6699 OPC_CMP_SF_PS = FOP (56, FMT_PS),
6700 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6701 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6702 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6703 OPC_CMP_LT_PS = FOP (60, FMT_PS),
6704 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6705 OPC_CMP_LE_PS = FOP (62, FMT_PS),
6706 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6709 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6711 const char *opn = "cp1 move";
6712 TCGv t0 = tcg_temp_new();
6714 switch (opc) {
6715 case OPC_MFC1:
6717 TCGv_i32 fp0 = tcg_temp_new_i32();
6719 gen_load_fpr32(fp0, fs);
6720 tcg_gen_ext_i32_tl(t0, fp0);
6721 tcg_temp_free_i32(fp0);
6723 gen_store_gpr(t0, rt);
6724 opn = "mfc1";
6725 break;
6726 case OPC_MTC1:
6727 gen_load_gpr(t0, rt);
6729 TCGv_i32 fp0 = tcg_temp_new_i32();
6731 tcg_gen_trunc_tl_i32(fp0, t0);
6732 gen_store_fpr32(fp0, fs);
6733 tcg_temp_free_i32(fp0);
6735 opn = "mtc1";
6736 break;
6737 case OPC_CFC1:
6738 gen_helper_1e0i(cfc1, t0, fs);
6739 gen_store_gpr(t0, rt);
6740 opn = "cfc1";
6741 break;
6742 case OPC_CTC1:
6743 gen_load_gpr(t0, rt);
6744 gen_helper_0e1i(ctc1, t0, fs);
6745 opn = "ctc1";
6746 break;
6747 #if defined(TARGET_MIPS64)
6748 case OPC_DMFC1:
6749 gen_load_fpr64(ctx, t0, fs);
6750 gen_store_gpr(t0, rt);
6751 opn = "dmfc1";
6752 break;
6753 case OPC_DMTC1:
6754 gen_load_gpr(t0, rt);
6755 gen_store_fpr64(ctx, t0, fs);
6756 opn = "dmtc1";
6757 break;
6758 #endif
6759 case OPC_MFHC1:
6761 TCGv_i32 fp0 = tcg_temp_new_i32();
6763 gen_load_fpr32h(fp0, fs);
6764 tcg_gen_ext_i32_tl(t0, fp0);
6765 tcg_temp_free_i32(fp0);
6767 gen_store_gpr(t0, rt);
6768 opn = "mfhc1";
6769 break;
6770 case OPC_MTHC1:
6771 gen_load_gpr(t0, rt);
6773 TCGv_i32 fp0 = tcg_temp_new_i32();
6775 tcg_gen_trunc_tl_i32(fp0, t0);
6776 gen_store_fpr32h(fp0, fs);
6777 tcg_temp_free_i32(fp0);
6779 opn = "mthc1";
6780 break;
6781 default:
6782 MIPS_INVAL(opn);
6783 generate_exception (ctx, EXCP_RI);
6784 goto out;
6786 (void)opn; /* avoid a compiler warning */
6787 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6789 out:
6790 tcg_temp_free(t0);
6793 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6795 int l1;
6796 TCGCond cond;
6797 TCGv_i32 t0;
6799 if (rd == 0) {
6800 /* Treat as NOP. */
6801 return;
6804 if (tf)
6805 cond = TCG_COND_EQ;
6806 else
6807 cond = TCG_COND_NE;
6809 l1 = gen_new_label();
6810 t0 = tcg_temp_new_i32();
6811 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6812 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6813 tcg_temp_free_i32(t0);
6814 if (rs == 0) {
6815 tcg_gen_movi_tl(cpu_gpr[rd], 0);
6816 } else {
6817 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6819 gen_set_label(l1);
6822 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6824 int cond;
6825 TCGv_i32 t0 = tcg_temp_new_i32();
6826 int l1 = gen_new_label();
6828 if (tf)
6829 cond = TCG_COND_EQ;
6830 else
6831 cond = TCG_COND_NE;
6833 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6834 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6835 gen_load_fpr32(t0, fs);
6836 gen_store_fpr32(t0, fd);
6837 gen_set_label(l1);
6838 tcg_temp_free_i32(t0);
6841 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6843 int cond;
6844 TCGv_i32 t0 = tcg_temp_new_i32();
6845 TCGv_i64 fp0;
6846 int l1 = gen_new_label();
6848 if (tf)
6849 cond = TCG_COND_EQ;
6850 else
6851 cond = TCG_COND_NE;
6853 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6854 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6855 tcg_temp_free_i32(t0);
6856 fp0 = tcg_temp_new_i64();
6857 gen_load_fpr64(ctx, fp0, fs);
6858 gen_store_fpr64(ctx, fp0, fd);
6859 tcg_temp_free_i64(fp0);
6860 gen_set_label(l1);
6863 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6865 int cond;
6866 TCGv_i32 t0 = tcg_temp_new_i32();
6867 int l1 = gen_new_label();
6868 int l2 = gen_new_label();
6870 if (tf)
6871 cond = TCG_COND_EQ;
6872 else
6873 cond = TCG_COND_NE;
6875 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6876 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6877 gen_load_fpr32(t0, fs);
6878 gen_store_fpr32(t0, fd);
6879 gen_set_label(l1);
6881 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
6882 tcg_gen_brcondi_i32(cond, t0, 0, l2);
6883 gen_load_fpr32h(t0, fs);
6884 gen_store_fpr32h(t0, fd);
6885 tcg_temp_free_i32(t0);
6886 gen_set_label(l2);
6890 static void gen_farith (DisasContext *ctx, enum fopcode op1,
6891 int ft, int fs, int fd, int cc)
6893 const char *opn = "farith";
6894 const char *condnames[] = {
6895 "c.f",
6896 "c.un",
6897 "c.eq",
6898 "c.ueq",
6899 "c.olt",
6900 "c.ult",
6901 "c.ole",
6902 "c.ule",
6903 "c.sf",
6904 "c.ngle",
6905 "c.seq",
6906 "c.ngl",
6907 "c.lt",
6908 "c.nge",
6909 "c.le",
6910 "c.ngt",
6912 const char *condnames_abs[] = {
6913 "cabs.f",
6914 "cabs.un",
6915 "cabs.eq",
6916 "cabs.ueq",
6917 "cabs.olt",
6918 "cabs.ult",
6919 "cabs.ole",
6920 "cabs.ule",
6921 "cabs.sf",
6922 "cabs.ngle",
6923 "cabs.seq",
6924 "cabs.ngl",
6925 "cabs.lt",
6926 "cabs.nge",
6927 "cabs.le",
6928 "cabs.ngt",
6930 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6931 uint32_t func = ctx->opcode & 0x3f;
6933 switch (op1) {
6934 case OPC_ADD_S:
6936 TCGv_i32 fp0 = tcg_temp_new_i32();
6937 TCGv_i32 fp1 = tcg_temp_new_i32();
6939 gen_load_fpr32(fp0, fs);
6940 gen_load_fpr32(fp1, ft);
6941 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
6942 tcg_temp_free_i32(fp1);
6943 gen_store_fpr32(fp0, fd);
6944 tcg_temp_free_i32(fp0);
6946 opn = "add.s";
6947 optype = BINOP;
6948 break;
6949 case OPC_SUB_S:
6951 TCGv_i32 fp0 = tcg_temp_new_i32();
6952 TCGv_i32 fp1 = tcg_temp_new_i32();
6954 gen_load_fpr32(fp0, fs);
6955 gen_load_fpr32(fp1, ft);
6956 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
6957 tcg_temp_free_i32(fp1);
6958 gen_store_fpr32(fp0, fd);
6959 tcg_temp_free_i32(fp0);
6961 opn = "sub.s";
6962 optype = BINOP;
6963 break;
6964 case OPC_MUL_S:
6966 TCGv_i32 fp0 = tcg_temp_new_i32();
6967 TCGv_i32 fp1 = tcg_temp_new_i32();
6969 gen_load_fpr32(fp0, fs);
6970 gen_load_fpr32(fp1, ft);
6971 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
6972 tcg_temp_free_i32(fp1);
6973 gen_store_fpr32(fp0, fd);
6974 tcg_temp_free_i32(fp0);
6976 opn = "mul.s";
6977 optype = BINOP;
6978 break;
6979 case OPC_DIV_S:
6981 TCGv_i32 fp0 = tcg_temp_new_i32();
6982 TCGv_i32 fp1 = tcg_temp_new_i32();
6984 gen_load_fpr32(fp0, fs);
6985 gen_load_fpr32(fp1, ft);
6986 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
6987 tcg_temp_free_i32(fp1);
6988 gen_store_fpr32(fp0, fd);
6989 tcg_temp_free_i32(fp0);
6991 opn = "div.s";
6992 optype = BINOP;
6993 break;
6994 case OPC_SQRT_S:
6996 TCGv_i32 fp0 = tcg_temp_new_i32();
6998 gen_load_fpr32(fp0, fs);
6999 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7000 gen_store_fpr32(fp0, fd);
7001 tcg_temp_free_i32(fp0);
7003 opn = "sqrt.s";
7004 break;
7005 case OPC_ABS_S:
7007 TCGv_i32 fp0 = tcg_temp_new_i32();
7009 gen_load_fpr32(fp0, fs);
7010 gen_helper_float_abs_s(fp0, fp0);
7011 gen_store_fpr32(fp0, fd);
7012 tcg_temp_free_i32(fp0);
7014 opn = "abs.s";
7015 break;
7016 case OPC_MOV_S:
7018 TCGv_i32 fp0 = tcg_temp_new_i32();
7020 gen_load_fpr32(fp0, fs);
7021 gen_store_fpr32(fp0, fd);
7022 tcg_temp_free_i32(fp0);
7024 opn = "mov.s";
7025 break;
7026 case OPC_NEG_S:
7028 TCGv_i32 fp0 = tcg_temp_new_i32();
7030 gen_load_fpr32(fp0, fs);
7031 gen_helper_float_chs_s(fp0, fp0);
7032 gen_store_fpr32(fp0, fd);
7033 tcg_temp_free_i32(fp0);
7035 opn = "neg.s";
7036 break;
7037 case OPC_ROUND_L_S:
7038 check_cp1_64bitmode(ctx);
7040 TCGv_i32 fp32 = tcg_temp_new_i32();
7041 TCGv_i64 fp64 = tcg_temp_new_i64();
7043 gen_load_fpr32(fp32, fs);
7044 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
7045 tcg_temp_free_i32(fp32);
7046 gen_store_fpr64(ctx, fp64, fd);
7047 tcg_temp_free_i64(fp64);
7049 opn = "round.l.s";
7050 break;
7051 case OPC_TRUNC_L_S:
7052 check_cp1_64bitmode(ctx);
7054 TCGv_i32 fp32 = tcg_temp_new_i32();
7055 TCGv_i64 fp64 = tcg_temp_new_i64();
7057 gen_load_fpr32(fp32, fs);
7058 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
7059 tcg_temp_free_i32(fp32);
7060 gen_store_fpr64(ctx, fp64, fd);
7061 tcg_temp_free_i64(fp64);
7063 opn = "trunc.l.s";
7064 break;
7065 case OPC_CEIL_L_S:
7066 check_cp1_64bitmode(ctx);
7068 TCGv_i32 fp32 = tcg_temp_new_i32();
7069 TCGv_i64 fp64 = tcg_temp_new_i64();
7071 gen_load_fpr32(fp32, fs);
7072 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
7073 tcg_temp_free_i32(fp32);
7074 gen_store_fpr64(ctx, fp64, fd);
7075 tcg_temp_free_i64(fp64);
7077 opn = "ceil.l.s";
7078 break;
7079 case OPC_FLOOR_L_S:
7080 check_cp1_64bitmode(ctx);
7082 TCGv_i32 fp32 = tcg_temp_new_i32();
7083 TCGv_i64 fp64 = tcg_temp_new_i64();
7085 gen_load_fpr32(fp32, fs);
7086 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
7087 tcg_temp_free_i32(fp32);
7088 gen_store_fpr64(ctx, fp64, fd);
7089 tcg_temp_free_i64(fp64);
7091 opn = "floor.l.s";
7092 break;
7093 case OPC_ROUND_W_S:
7095 TCGv_i32 fp0 = tcg_temp_new_i32();
7097 gen_load_fpr32(fp0, fs);
7098 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
7099 gen_store_fpr32(fp0, fd);
7100 tcg_temp_free_i32(fp0);
7102 opn = "round.w.s";
7103 break;
7104 case OPC_TRUNC_W_S:
7106 TCGv_i32 fp0 = tcg_temp_new_i32();
7108 gen_load_fpr32(fp0, fs);
7109 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
7110 gen_store_fpr32(fp0, fd);
7111 tcg_temp_free_i32(fp0);
7113 opn = "trunc.w.s";
7114 break;
7115 case OPC_CEIL_W_S:
7117 TCGv_i32 fp0 = tcg_temp_new_i32();
7119 gen_load_fpr32(fp0, fs);
7120 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
7121 gen_store_fpr32(fp0, fd);
7122 tcg_temp_free_i32(fp0);
7124 opn = "ceil.w.s";
7125 break;
7126 case OPC_FLOOR_W_S:
7128 TCGv_i32 fp0 = tcg_temp_new_i32();
7130 gen_load_fpr32(fp0, fs);
7131 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
7132 gen_store_fpr32(fp0, fd);
7133 tcg_temp_free_i32(fp0);
7135 opn = "floor.w.s";
7136 break;
7137 case OPC_MOVCF_S:
7138 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7139 opn = "movcf.s";
7140 break;
7141 case OPC_MOVZ_S:
7143 int l1 = gen_new_label();
7144 TCGv_i32 fp0;
7146 if (ft != 0) {
7147 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7149 fp0 = tcg_temp_new_i32();
7150 gen_load_fpr32(fp0, fs);
7151 gen_store_fpr32(fp0, fd);
7152 tcg_temp_free_i32(fp0);
7153 gen_set_label(l1);
7155 opn = "movz.s";
7156 break;
7157 case OPC_MOVN_S:
7159 int l1 = gen_new_label();
7160 TCGv_i32 fp0;
7162 if (ft != 0) {
7163 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7164 fp0 = tcg_temp_new_i32();
7165 gen_load_fpr32(fp0, fs);
7166 gen_store_fpr32(fp0, fd);
7167 tcg_temp_free_i32(fp0);
7168 gen_set_label(l1);
7171 opn = "movn.s";
7172 break;
7173 case OPC_RECIP_S:
7174 check_cop1x(ctx);
7176 TCGv_i32 fp0 = tcg_temp_new_i32();
7178 gen_load_fpr32(fp0, fs);
7179 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7180 gen_store_fpr32(fp0, fd);
7181 tcg_temp_free_i32(fp0);
7183 opn = "recip.s";
7184 break;
7185 case OPC_RSQRT_S:
7186 check_cop1x(ctx);
7188 TCGv_i32 fp0 = tcg_temp_new_i32();
7190 gen_load_fpr32(fp0, fs);
7191 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7192 gen_store_fpr32(fp0, fd);
7193 tcg_temp_free_i32(fp0);
7195 opn = "rsqrt.s";
7196 break;
7197 case OPC_RECIP2_S:
7198 check_cp1_64bitmode(ctx);
7200 TCGv_i32 fp0 = tcg_temp_new_i32();
7201 TCGv_i32 fp1 = tcg_temp_new_i32();
7203 gen_load_fpr32(fp0, fs);
7204 gen_load_fpr32(fp1, ft);
7205 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
7206 tcg_temp_free_i32(fp1);
7207 gen_store_fpr32(fp0, fd);
7208 tcg_temp_free_i32(fp0);
7210 opn = "recip2.s";
7211 break;
7212 case OPC_RECIP1_S:
7213 check_cp1_64bitmode(ctx);
7215 TCGv_i32 fp0 = tcg_temp_new_i32();
7217 gen_load_fpr32(fp0, fs);
7218 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7219 gen_store_fpr32(fp0, fd);
7220 tcg_temp_free_i32(fp0);
7222 opn = "recip1.s";
7223 break;
7224 case OPC_RSQRT1_S:
7225 check_cp1_64bitmode(ctx);
7227 TCGv_i32 fp0 = tcg_temp_new_i32();
7229 gen_load_fpr32(fp0, fs);
7230 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7231 gen_store_fpr32(fp0, fd);
7232 tcg_temp_free_i32(fp0);
7234 opn = "rsqrt1.s";
7235 break;
7236 case OPC_RSQRT2_S:
7237 check_cp1_64bitmode(ctx);
7239 TCGv_i32 fp0 = tcg_temp_new_i32();
7240 TCGv_i32 fp1 = tcg_temp_new_i32();
7242 gen_load_fpr32(fp0, fs);
7243 gen_load_fpr32(fp1, ft);
7244 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
7245 tcg_temp_free_i32(fp1);
7246 gen_store_fpr32(fp0, fd);
7247 tcg_temp_free_i32(fp0);
7249 opn = "rsqrt2.s";
7250 break;
7251 case OPC_CVT_D_S:
7252 check_cp1_registers(ctx, fd);
7254 TCGv_i32 fp32 = tcg_temp_new_i32();
7255 TCGv_i64 fp64 = tcg_temp_new_i64();
7257 gen_load_fpr32(fp32, fs);
7258 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
7259 tcg_temp_free_i32(fp32);
7260 gen_store_fpr64(ctx, fp64, fd);
7261 tcg_temp_free_i64(fp64);
7263 opn = "cvt.d.s";
7264 break;
7265 case OPC_CVT_W_S:
7267 TCGv_i32 fp0 = tcg_temp_new_i32();
7269 gen_load_fpr32(fp0, fs);
7270 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
7271 gen_store_fpr32(fp0, fd);
7272 tcg_temp_free_i32(fp0);
7274 opn = "cvt.w.s";
7275 break;
7276 case OPC_CVT_L_S:
7277 check_cp1_64bitmode(ctx);
7279 TCGv_i32 fp32 = tcg_temp_new_i32();
7280 TCGv_i64 fp64 = tcg_temp_new_i64();
7282 gen_load_fpr32(fp32, fs);
7283 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
7284 tcg_temp_free_i32(fp32);
7285 gen_store_fpr64(ctx, fp64, fd);
7286 tcg_temp_free_i64(fp64);
7288 opn = "cvt.l.s";
7289 break;
7290 case OPC_CVT_PS_S:
7291 check_cp1_64bitmode(ctx);
7293 TCGv_i64 fp64 = tcg_temp_new_i64();
7294 TCGv_i32 fp32_0 = tcg_temp_new_i32();
7295 TCGv_i32 fp32_1 = tcg_temp_new_i32();
7297 gen_load_fpr32(fp32_0, fs);
7298 gen_load_fpr32(fp32_1, ft);
7299 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
7300 tcg_temp_free_i32(fp32_1);
7301 tcg_temp_free_i32(fp32_0);
7302 gen_store_fpr64(ctx, fp64, fd);
7303 tcg_temp_free_i64(fp64);
7305 opn = "cvt.ps.s";
7306 break;
7307 case OPC_CMP_F_S:
7308 case OPC_CMP_UN_S:
7309 case OPC_CMP_EQ_S:
7310 case OPC_CMP_UEQ_S:
7311 case OPC_CMP_OLT_S:
7312 case OPC_CMP_ULT_S:
7313 case OPC_CMP_OLE_S:
7314 case OPC_CMP_ULE_S:
7315 case OPC_CMP_SF_S:
7316 case OPC_CMP_NGLE_S:
7317 case OPC_CMP_SEQ_S:
7318 case OPC_CMP_NGL_S:
7319 case OPC_CMP_LT_S:
7320 case OPC_CMP_NGE_S:
7321 case OPC_CMP_LE_S:
7322 case OPC_CMP_NGT_S:
7323 if (ctx->opcode & (1 << 6)) {
7324 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
7325 opn = condnames_abs[func-48];
7326 } else {
7327 gen_cmp_s(ctx, func-48, ft, fs, cc);
7328 opn = condnames[func-48];
7330 break;
7331 case OPC_ADD_D:
7332 check_cp1_registers(ctx, fs | ft | fd);
7334 TCGv_i64 fp0 = tcg_temp_new_i64();
7335 TCGv_i64 fp1 = tcg_temp_new_i64();
7337 gen_load_fpr64(ctx, fp0, fs);
7338 gen_load_fpr64(ctx, fp1, ft);
7339 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
7340 tcg_temp_free_i64(fp1);
7341 gen_store_fpr64(ctx, fp0, fd);
7342 tcg_temp_free_i64(fp0);
7344 opn = "add.d";
7345 optype = BINOP;
7346 break;
7347 case OPC_SUB_D:
7348 check_cp1_registers(ctx, fs | ft | fd);
7350 TCGv_i64 fp0 = tcg_temp_new_i64();
7351 TCGv_i64 fp1 = tcg_temp_new_i64();
7353 gen_load_fpr64(ctx, fp0, fs);
7354 gen_load_fpr64(ctx, fp1, ft);
7355 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
7356 tcg_temp_free_i64(fp1);
7357 gen_store_fpr64(ctx, fp0, fd);
7358 tcg_temp_free_i64(fp0);
7360 opn = "sub.d";
7361 optype = BINOP;
7362 break;
7363 case OPC_MUL_D:
7364 check_cp1_registers(ctx, fs | ft | fd);
7366 TCGv_i64 fp0 = tcg_temp_new_i64();
7367 TCGv_i64 fp1 = tcg_temp_new_i64();
7369 gen_load_fpr64(ctx, fp0, fs);
7370 gen_load_fpr64(ctx, fp1, ft);
7371 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
7372 tcg_temp_free_i64(fp1);
7373 gen_store_fpr64(ctx, fp0, fd);
7374 tcg_temp_free_i64(fp0);
7376 opn = "mul.d";
7377 optype = BINOP;
7378 break;
7379 case OPC_DIV_D:
7380 check_cp1_registers(ctx, fs | ft | fd);
7382 TCGv_i64 fp0 = tcg_temp_new_i64();
7383 TCGv_i64 fp1 = tcg_temp_new_i64();
7385 gen_load_fpr64(ctx, fp0, fs);
7386 gen_load_fpr64(ctx, fp1, ft);
7387 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
7388 tcg_temp_free_i64(fp1);
7389 gen_store_fpr64(ctx, fp0, fd);
7390 tcg_temp_free_i64(fp0);
7392 opn = "div.d";
7393 optype = BINOP;
7394 break;
7395 case OPC_SQRT_D:
7396 check_cp1_registers(ctx, fs | fd);
7398 TCGv_i64 fp0 = tcg_temp_new_i64();
7400 gen_load_fpr64(ctx, fp0, fs);
7401 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
7402 gen_store_fpr64(ctx, fp0, fd);
7403 tcg_temp_free_i64(fp0);
7405 opn = "sqrt.d";
7406 break;
7407 case OPC_ABS_D:
7408 check_cp1_registers(ctx, fs | fd);
7410 TCGv_i64 fp0 = tcg_temp_new_i64();
7412 gen_load_fpr64(ctx, fp0, fs);
7413 gen_helper_float_abs_d(fp0, fp0);
7414 gen_store_fpr64(ctx, fp0, fd);
7415 tcg_temp_free_i64(fp0);
7417 opn = "abs.d";
7418 break;
7419 case OPC_MOV_D:
7420 check_cp1_registers(ctx, fs | fd);
7422 TCGv_i64 fp0 = tcg_temp_new_i64();
7424 gen_load_fpr64(ctx, fp0, fs);
7425 gen_store_fpr64(ctx, fp0, fd);
7426 tcg_temp_free_i64(fp0);
7428 opn = "mov.d";
7429 break;
7430 case OPC_NEG_D:
7431 check_cp1_registers(ctx, fs | fd);
7433 TCGv_i64 fp0 = tcg_temp_new_i64();
7435 gen_load_fpr64(ctx, fp0, fs);
7436 gen_helper_float_chs_d(fp0, fp0);
7437 gen_store_fpr64(ctx, fp0, fd);
7438 tcg_temp_free_i64(fp0);
7440 opn = "neg.d";
7441 break;
7442 case OPC_ROUND_L_D:
7443 check_cp1_64bitmode(ctx);
7445 TCGv_i64 fp0 = tcg_temp_new_i64();
7447 gen_load_fpr64(ctx, fp0, fs);
7448 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
7449 gen_store_fpr64(ctx, fp0, fd);
7450 tcg_temp_free_i64(fp0);
7452 opn = "round.l.d";
7453 break;
7454 case OPC_TRUNC_L_D:
7455 check_cp1_64bitmode(ctx);
7457 TCGv_i64 fp0 = tcg_temp_new_i64();
7459 gen_load_fpr64(ctx, fp0, fs);
7460 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
7461 gen_store_fpr64(ctx, fp0, fd);
7462 tcg_temp_free_i64(fp0);
7464 opn = "trunc.l.d";
7465 break;
7466 case OPC_CEIL_L_D:
7467 check_cp1_64bitmode(ctx);
7469 TCGv_i64 fp0 = tcg_temp_new_i64();
7471 gen_load_fpr64(ctx, fp0, fs);
7472 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
7473 gen_store_fpr64(ctx, fp0, fd);
7474 tcg_temp_free_i64(fp0);
7476 opn = "ceil.l.d";
7477 break;
7478 case OPC_FLOOR_L_D:
7479 check_cp1_64bitmode(ctx);
7481 TCGv_i64 fp0 = tcg_temp_new_i64();
7483 gen_load_fpr64(ctx, fp0, fs);
7484 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
7485 gen_store_fpr64(ctx, fp0, fd);
7486 tcg_temp_free_i64(fp0);
7488 opn = "floor.l.d";
7489 break;
7490 case OPC_ROUND_W_D:
7491 check_cp1_registers(ctx, fs);
7493 TCGv_i32 fp32 = tcg_temp_new_i32();
7494 TCGv_i64 fp64 = tcg_temp_new_i64();
7496 gen_load_fpr64(ctx, fp64, fs);
7497 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
7498 tcg_temp_free_i64(fp64);
7499 gen_store_fpr32(fp32, fd);
7500 tcg_temp_free_i32(fp32);
7502 opn = "round.w.d";
7503 break;
7504 case OPC_TRUNC_W_D:
7505 check_cp1_registers(ctx, fs);
7507 TCGv_i32 fp32 = tcg_temp_new_i32();
7508 TCGv_i64 fp64 = tcg_temp_new_i64();
7510 gen_load_fpr64(ctx, fp64, fs);
7511 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
7512 tcg_temp_free_i64(fp64);
7513 gen_store_fpr32(fp32, fd);
7514 tcg_temp_free_i32(fp32);
7516 opn = "trunc.w.d";
7517 break;
7518 case OPC_CEIL_W_D:
7519 check_cp1_registers(ctx, fs);
7521 TCGv_i32 fp32 = tcg_temp_new_i32();
7522 TCGv_i64 fp64 = tcg_temp_new_i64();
7524 gen_load_fpr64(ctx, fp64, fs);
7525 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
7526 tcg_temp_free_i64(fp64);
7527 gen_store_fpr32(fp32, fd);
7528 tcg_temp_free_i32(fp32);
7530 opn = "ceil.w.d";
7531 break;
7532 case OPC_FLOOR_W_D:
7533 check_cp1_registers(ctx, fs);
7535 TCGv_i32 fp32 = tcg_temp_new_i32();
7536 TCGv_i64 fp64 = tcg_temp_new_i64();
7538 gen_load_fpr64(ctx, fp64, fs);
7539 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
7540 tcg_temp_free_i64(fp64);
7541 gen_store_fpr32(fp32, fd);
7542 tcg_temp_free_i32(fp32);
7544 opn = "floor.w.d";
7545 break;
7546 case OPC_MOVCF_D:
7547 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7548 opn = "movcf.d";
7549 break;
7550 case OPC_MOVZ_D:
7552 int l1 = gen_new_label();
7553 TCGv_i64 fp0;
7555 if (ft != 0) {
7556 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7558 fp0 = tcg_temp_new_i64();
7559 gen_load_fpr64(ctx, fp0, fs);
7560 gen_store_fpr64(ctx, fp0, fd);
7561 tcg_temp_free_i64(fp0);
7562 gen_set_label(l1);
7564 opn = "movz.d";
7565 break;
7566 case OPC_MOVN_D:
7568 int l1 = gen_new_label();
7569 TCGv_i64 fp0;
7571 if (ft != 0) {
7572 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7573 fp0 = tcg_temp_new_i64();
7574 gen_load_fpr64(ctx, fp0, fs);
7575 gen_store_fpr64(ctx, fp0, fd);
7576 tcg_temp_free_i64(fp0);
7577 gen_set_label(l1);
7580 opn = "movn.d";
7581 break;
7582 case OPC_RECIP_D:
7583 check_cp1_64bitmode(ctx);
7585 TCGv_i64 fp0 = tcg_temp_new_i64();
7587 gen_load_fpr64(ctx, fp0, fs);
7588 gen_helper_float_recip_d(fp0, cpu_env, fp0);
7589 gen_store_fpr64(ctx, fp0, fd);
7590 tcg_temp_free_i64(fp0);
7592 opn = "recip.d";
7593 break;
7594 case OPC_RSQRT_D:
7595 check_cp1_64bitmode(ctx);
7597 TCGv_i64 fp0 = tcg_temp_new_i64();
7599 gen_load_fpr64(ctx, fp0, fs);
7600 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
7601 gen_store_fpr64(ctx, fp0, fd);
7602 tcg_temp_free_i64(fp0);
7604 opn = "rsqrt.d";
7605 break;
7606 case OPC_RECIP2_D:
7607 check_cp1_64bitmode(ctx);
7609 TCGv_i64 fp0 = tcg_temp_new_i64();
7610 TCGv_i64 fp1 = tcg_temp_new_i64();
7612 gen_load_fpr64(ctx, fp0, fs);
7613 gen_load_fpr64(ctx, fp1, ft);
7614 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
7615 tcg_temp_free_i64(fp1);
7616 gen_store_fpr64(ctx, fp0, fd);
7617 tcg_temp_free_i64(fp0);
7619 opn = "recip2.d";
7620 break;
7621 case OPC_RECIP1_D:
7622 check_cp1_64bitmode(ctx);
7624 TCGv_i64 fp0 = tcg_temp_new_i64();
7626 gen_load_fpr64(ctx, fp0, fs);
7627 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
7628 gen_store_fpr64(ctx, fp0, fd);
7629 tcg_temp_free_i64(fp0);
7631 opn = "recip1.d";
7632 break;
7633 case OPC_RSQRT1_D:
7634 check_cp1_64bitmode(ctx);
7636 TCGv_i64 fp0 = tcg_temp_new_i64();
7638 gen_load_fpr64(ctx, fp0, fs);
7639 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
7640 gen_store_fpr64(ctx, fp0, fd);
7641 tcg_temp_free_i64(fp0);
7643 opn = "rsqrt1.d";
7644 break;
7645 case OPC_RSQRT2_D:
7646 check_cp1_64bitmode(ctx);
7648 TCGv_i64 fp0 = tcg_temp_new_i64();
7649 TCGv_i64 fp1 = tcg_temp_new_i64();
7651 gen_load_fpr64(ctx, fp0, fs);
7652 gen_load_fpr64(ctx, fp1, ft);
7653 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
7654 tcg_temp_free_i64(fp1);
7655 gen_store_fpr64(ctx, fp0, fd);
7656 tcg_temp_free_i64(fp0);
7658 opn = "rsqrt2.d";
7659 break;
7660 case OPC_CMP_F_D:
7661 case OPC_CMP_UN_D:
7662 case OPC_CMP_EQ_D:
7663 case OPC_CMP_UEQ_D:
7664 case OPC_CMP_OLT_D:
7665 case OPC_CMP_ULT_D:
7666 case OPC_CMP_OLE_D:
7667 case OPC_CMP_ULE_D:
7668 case OPC_CMP_SF_D:
7669 case OPC_CMP_NGLE_D:
7670 case OPC_CMP_SEQ_D:
7671 case OPC_CMP_NGL_D:
7672 case OPC_CMP_LT_D:
7673 case OPC_CMP_NGE_D:
7674 case OPC_CMP_LE_D:
7675 case OPC_CMP_NGT_D:
7676 if (ctx->opcode & (1 << 6)) {
7677 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7678 opn = condnames_abs[func-48];
7679 } else {
7680 gen_cmp_d(ctx, func-48, ft, fs, cc);
7681 opn = condnames[func-48];
7683 break;
7684 case OPC_CVT_S_D:
7685 check_cp1_registers(ctx, fs);
7687 TCGv_i32 fp32 = tcg_temp_new_i32();
7688 TCGv_i64 fp64 = tcg_temp_new_i64();
7690 gen_load_fpr64(ctx, fp64, fs);
7691 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
7692 tcg_temp_free_i64(fp64);
7693 gen_store_fpr32(fp32, fd);
7694 tcg_temp_free_i32(fp32);
7696 opn = "cvt.s.d";
7697 break;
7698 case OPC_CVT_W_D:
7699 check_cp1_registers(ctx, fs);
7701 TCGv_i32 fp32 = tcg_temp_new_i32();
7702 TCGv_i64 fp64 = tcg_temp_new_i64();
7704 gen_load_fpr64(ctx, fp64, fs);
7705 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
7706 tcg_temp_free_i64(fp64);
7707 gen_store_fpr32(fp32, fd);
7708 tcg_temp_free_i32(fp32);
7710 opn = "cvt.w.d";
7711 break;
7712 case OPC_CVT_L_D:
7713 check_cp1_64bitmode(ctx);
7715 TCGv_i64 fp0 = tcg_temp_new_i64();
7717 gen_load_fpr64(ctx, fp0, fs);
7718 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
7719 gen_store_fpr64(ctx, fp0, fd);
7720 tcg_temp_free_i64(fp0);
7722 opn = "cvt.l.d";
7723 break;
7724 case OPC_CVT_S_W:
7726 TCGv_i32 fp0 = tcg_temp_new_i32();
7728 gen_load_fpr32(fp0, fs);
7729 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7730 gen_store_fpr32(fp0, fd);
7731 tcg_temp_free_i32(fp0);
7733 opn = "cvt.s.w";
7734 break;
7735 case OPC_CVT_D_W:
7736 check_cp1_registers(ctx, fd);
7738 TCGv_i32 fp32 = tcg_temp_new_i32();
7739 TCGv_i64 fp64 = tcg_temp_new_i64();
7741 gen_load_fpr32(fp32, fs);
7742 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
7743 tcg_temp_free_i32(fp32);
7744 gen_store_fpr64(ctx, fp64, fd);
7745 tcg_temp_free_i64(fp64);
7747 opn = "cvt.d.w";
7748 break;
7749 case OPC_CVT_S_L:
7750 check_cp1_64bitmode(ctx);
7752 TCGv_i32 fp32 = tcg_temp_new_i32();
7753 TCGv_i64 fp64 = tcg_temp_new_i64();
7755 gen_load_fpr64(ctx, fp64, fs);
7756 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
7757 tcg_temp_free_i64(fp64);
7758 gen_store_fpr32(fp32, fd);
7759 tcg_temp_free_i32(fp32);
7761 opn = "cvt.s.l";
7762 break;
7763 case OPC_CVT_D_L:
7764 check_cp1_64bitmode(ctx);
7766 TCGv_i64 fp0 = tcg_temp_new_i64();
7768 gen_load_fpr64(ctx, fp0, fs);
7769 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
7770 gen_store_fpr64(ctx, fp0, fd);
7771 tcg_temp_free_i64(fp0);
7773 opn = "cvt.d.l";
7774 break;
7775 case OPC_CVT_PS_PW:
7776 check_cp1_64bitmode(ctx);
7778 TCGv_i64 fp0 = tcg_temp_new_i64();
7780 gen_load_fpr64(ctx, fp0, fs);
7781 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
7782 gen_store_fpr64(ctx, fp0, fd);
7783 tcg_temp_free_i64(fp0);
7785 opn = "cvt.ps.pw";
7786 break;
7787 case OPC_ADD_PS:
7788 check_cp1_64bitmode(ctx);
7790 TCGv_i64 fp0 = tcg_temp_new_i64();
7791 TCGv_i64 fp1 = tcg_temp_new_i64();
7793 gen_load_fpr64(ctx, fp0, fs);
7794 gen_load_fpr64(ctx, fp1, ft);
7795 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
7796 tcg_temp_free_i64(fp1);
7797 gen_store_fpr64(ctx, fp0, fd);
7798 tcg_temp_free_i64(fp0);
7800 opn = "add.ps";
7801 break;
7802 case OPC_SUB_PS:
7803 check_cp1_64bitmode(ctx);
7805 TCGv_i64 fp0 = tcg_temp_new_i64();
7806 TCGv_i64 fp1 = tcg_temp_new_i64();
7808 gen_load_fpr64(ctx, fp0, fs);
7809 gen_load_fpr64(ctx, fp1, ft);
7810 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
7811 tcg_temp_free_i64(fp1);
7812 gen_store_fpr64(ctx, fp0, fd);
7813 tcg_temp_free_i64(fp0);
7815 opn = "sub.ps";
7816 break;
7817 case OPC_MUL_PS:
7818 check_cp1_64bitmode(ctx);
7820 TCGv_i64 fp0 = tcg_temp_new_i64();
7821 TCGv_i64 fp1 = tcg_temp_new_i64();
7823 gen_load_fpr64(ctx, fp0, fs);
7824 gen_load_fpr64(ctx, fp1, ft);
7825 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
7826 tcg_temp_free_i64(fp1);
7827 gen_store_fpr64(ctx, fp0, fd);
7828 tcg_temp_free_i64(fp0);
7830 opn = "mul.ps";
7831 break;
7832 case OPC_ABS_PS:
7833 check_cp1_64bitmode(ctx);
7835 TCGv_i64 fp0 = tcg_temp_new_i64();
7837 gen_load_fpr64(ctx, fp0, fs);
7838 gen_helper_float_abs_ps(fp0, fp0);
7839 gen_store_fpr64(ctx, fp0, fd);
7840 tcg_temp_free_i64(fp0);
7842 opn = "abs.ps";
7843 break;
7844 case OPC_MOV_PS:
7845 check_cp1_64bitmode(ctx);
7847 TCGv_i64 fp0 = tcg_temp_new_i64();
7849 gen_load_fpr64(ctx, fp0, fs);
7850 gen_store_fpr64(ctx, fp0, fd);
7851 tcg_temp_free_i64(fp0);
7853 opn = "mov.ps";
7854 break;
7855 case OPC_NEG_PS:
7856 check_cp1_64bitmode(ctx);
7858 TCGv_i64 fp0 = tcg_temp_new_i64();
7860 gen_load_fpr64(ctx, fp0, fs);
7861 gen_helper_float_chs_ps(fp0, fp0);
7862 gen_store_fpr64(ctx, fp0, fd);
7863 tcg_temp_free_i64(fp0);
7865 opn = "neg.ps";
7866 break;
7867 case OPC_MOVCF_PS:
7868 check_cp1_64bitmode(ctx);
7869 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7870 opn = "movcf.ps";
7871 break;
7872 case OPC_MOVZ_PS:
7873 check_cp1_64bitmode(ctx);
7875 int l1 = gen_new_label();
7876 TCGv_i64 fp0;
7878 if (ft != 0)
7879 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7880 fp0 = tcg_temp_new_i64();
7881 gen_load_fpr64(ctx, fp0, fs);
7882 gen_store_fpr64(ctx, fp0, fd);
7883 tcg_temp_free_i64(fp0);
7884 gen_set_label(l1);
7886 opn = "movz.ps";
7887 break;
7888 case OPC_MOVN_PS:
7889 check_cp1_64bitmode(ctx);
7891 int l1 = gen_new_label();
7892 TCGv_i64 fp0;
7894 if (ft != 0) {
7895 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7896 fp0 = tcg_temp_new_i64();
7897 gen_load_fpr64(ctx, fp0, fs);
7898 gen_store_fpr64(ctx, fp0, fd);
7899 tcg_temp_free_i64(fp0);
7900 gen_set_label(l1);
7903 opn = "movn.ps";
7904 break;
7905 case OPC_ADDR_PS:
7906 check_cp1_64bitmode(ctx);
7908 TCGv_i64 fp0 = tcg_temp_new_i64();
7909 TCGv_i64 fp1 = tcg_temp_new_i64();
7911 gen_load_fpr64(ctx, fp0, ft);
7912 gen_load_fpr64(ctx, fp1, fs);
7913 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
7914 tcg_temp_free_i64(fp1);
7915 gen_store_fpr64(ctx, fp0, fd);
7916 tcg_temp_free_i64(fp0);
7918 opn = "addr.ps";
7919 break;
7920 case OPC_MULR_PS:
7921 check_cp1_64bitmode(ctx);
7923 TCGv_i64 fp0 = tcg_temp_new_i64();
7924 TCGv_i64 fp1 = tcg_temp_new_i64();
7926 gen_load_fpr64(ctx, fp0, ft);
7927 gen_load_fpr64(ctx, fp1, fs);
7928 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
7929 tcg_temp_free_i64(fp1);
7930 gen_store_fpr64(ctx, fp0, fd);
7931 tcg_temp_free_i64(fp0);
7933 opn = "mulr.ps";
7934 break;
7935 case OPC_RECIP2_PS:
7936 check_cp1_64bitmode(ctx);
7938 TCGv_i64 fp0 = tcg_temp_new_i64();
7939 TCGv_i64 fp1 = tcg_temp_new_i64();
7941 gen_load_fpr64(ctx, fp0, fs);
7942 gen_load_fpr64(ctx, fp1, ft);
7943 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
7944 tcg_temp_free_i64(fp1);
7945 gen_store_fpr64(ctx, fp0, fd);
7946 tcg_temp_free_i64(fp0);
7948 opn = "recip2.ps";
7949 break;
7950 case OPC_RECIP1_PS:
7951 check_cp1_64bitmode(ctx);
7953 TCGv_i64 fp0 = tcg_temp_new_i64();
7955 gen_load_fpr64(ctx, fp0, fs);
7956 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
7957 gen_store_fpr64(ctx, fp0, fd);
7958 tcg_temp_free_i64(fp0);
7960 opn = "recip1.ps";
7961 break;
7962 case OPC_RSQRT1_PS:
7963 check_cp1_64bitmode(ctx);
7965 TCGv_i64 fp0 = tcg_temp_new_i64();
7967 gen_load_fpr64(ctx, fp0, fs);
7968 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
7969 gen_store_fpr64(ctx, fp0, fd);
7970 tcg_temp_free_i64(fp0);
7972 opn = "rsqrt1.ps";
7973 break;
7974 case OPC_RSQRT2_PS:
7975 check_cp1_64bitmode(ctx);
7977 TCGv_i64 fp0 = tcg_temp_new_i64();
7978 TCGv_i64 fp1 = tcg_temp_new_i64();
7980 gen_load_fpr64(ctx, fp0, fs);
7981 gen_load_fpr64(ctx, fp1, ft);
7982 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
7983 tcg_temp_free_i64(fp1);
7984 gen_store_fpr64(ctx, fp0, fd);
7985 tcg_temp_free_i64(fp0);
7987 opn = "rsqrt2.ps";
7988 break;
7989 case OPC_CVT_S_PU:
7990 check_cp1_64bitmode(ctx);
7992 TCGv_i32 fp0 = tcg_temp_new_i32();
7994 gen_load_fpr32h(fp0, fs);
7995 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7996 gen_store_fpr32(fp0, fd);
7997 tcg_temp_free_i32(fp0);
7999 opn = "cvt.s.pu";
8000 break;
8001 case OPC_CVT_PW_PS:
8002 check_cp1_64bitmode(ctx);
8004 TCGv_i64 fp0 = tcg_temp_new_i64();
8006 gen_load_fpr64(ctx, fp0, fs);
8007 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
8008 gen_store_fpr64(ctx, fp0, fd);
8009 tcg_temp_free_i64(fp0);
8011 opn = "cvt.pw.ps";
8012 break;
8013 case OPC_CVT_S_PL:
8014 check_cp1_64bitmode(ctx);
8016 TCGv_i32 fp0 = tcg_temp_new_i32();
8018 gen_load_fpr32(fp0, fs);
8019 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
8020 gen_store_fpr32(fp0, fd);
8021 tcg_temp_free_i32(fp0);
8023 opn = "cvt.s.pl";
8024 break;
8025 case OPC_PLL_PS:
8026 check_cp1_64bitmode(ctx);
8028 TCGv_i32 fp0 = tcg_temp_new_i32();
8029 TCGv_i32 fp1 = tcg_temp_new_i32();
8031 gen_load_fpr32(fp0, fs);
8032 gen_load_fpr32(fp1, ft);
8033 gen_store_fpr32h(fp0, fd);
8034 gen_store_fpr32(fp1, fd);
8035 tcg_temp_free_i32(fp0);
8036 tcg_temp_free_i32(fp1);
8038 opn = "pll.ps";
8039 break;
8040 case OPC_PLU_PS:
8041 check_cp1_64bitmode(ctx);
8043 TCGv_i32 fp0 = tcg_temp_new_i32();
8044 TCGv_i32 fp1 = tcg_temp_new_i32();
8046 gen_load_fpr32(fp0, fs);
8047 gen_load_fpr32h(fp1, ft);
8048 gen_store_fpr32(fp1, fd);
8049 gen_store_fpr32h(fp0, fd);
8050 tcg_temp_free_i32(fp0);
8051 tcg_temp_free_i32(fp1);
8053 opn = "plu.ps";
8054 break;
8055 case OPC_PUL_PS:
8056 check_cp1_64bitmode(ctx);
8058 TCGv_i32 fp0 = tcg_temp_new_i32();
8059 TCGv_i32 fp1 = tcg_temp_new_i32();
8061 gen_load_fpr32h(fp0, fs);
8062 gen_load_fpr32(fp1, ft);
8063 gen_store_fpr32(fp1, fd);
8064 gen_store_fpr32h(fp0, fd);
8065 tcg_temp_free_i32(fp0);
8066 tcg_temp_free_i32(fp1);
8068 opn = "pul.ps";
8069 break;
8070 case OPC_PUU_PS:
8071 check_cp1_64bitmode(ctx);
8073 TCGv_i32 fp0 = tcg_temp_new_i32();
8074 TCGv_i32 fp1 = tcg_temp_new_i32();
8076 gen_load_fpr32h(fp0, fs);
8077 gen_load_fpr32h(fp1, ft);
8078 gen_store_fpr32(fp1, fd);
8079 gen_store_fpr32h(fp0, fd);
8080 tcg_temp_free_i32(fp0);
8081 tcg_temp_free_i32(fp1);
8083 opn = "puu.ps";
8084 break;
8085 case OPC_CMP_F_PS:
8086 case OPC_CMP_UN_PS:
8087 case OPC_CMP_EQ_PS:
8088 case OPC_CMP_UEQ_PS:
8089 case OPC_CMP_OLT_PS:
8090 case OPC_CMP_ULT_PS:
8091 case OPC_CMP_OLE_PS:
8092 case OPC_CMP_ULE_PS:
8093 case OPC_CMP_SF_PS:
8094 case OPC_CMP_NGLE_PS:
8095 case OPC_CMP_SEQ_PS:
8096 case OPC_CMP_NGL_PS:
8097 case OPC_CMP_LT_PS:
8098 case OPC_CMP_NGE_PS:
8099 case OPC_CMP_LE_PS:
8100 case OPC_CMP_NGT_PS:
8101 if (ctx->opcode & (1 << 6)) {
8102 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8103 opn = condnames_abs[func-48];
8104 } else {
8105 gen_cmp_ps(ctx, func-48, ft, fs, cc);
8106 opn = condnames[func-48];
8108 break;
8109 default:
8110 MIPS_INVAL(opn);
8111 generate_exception (ctx, EXCP_RI);
8112 return;
8114 (void)opn; /* avoid a compiler warning */
8115 switch (optype) {
8116 case BINOP:
8117 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
8118 break;
8119 case CMPOP:
8120 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
8121 break;
8122 default:
8123 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
8124 break;
8128 /* Coprocessor 3 (FPU) */
8129 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
8130 int fd, int fs, int base, int index)
8132 const char *opn = "extended float load/store";
8133 int store = 0;
8134 TCGv t0 = tcg_temp_new();
8136 if (base == 0) {
8137 gen_load_gpr(t0, index);
8138 } else if (index == 0) {
8139 gen_load_gpr(t0, base);
8140 } else {
8141 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
8143 /* Don't do NOP if destination is zero: we must perform the actual
8144 memory access. */
8145 save_cpu_state(ctx, 0);
8146 switch (opc) {
8147 case OPC_LWXC1:
8148 check_cop1x(ctx);
8150 TCGv_i32 fp0 = tcg_temp_new_i32();
8152 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
8153 tcg_gen_trunc_tl_i32(fp0, t0);
8154 gen_store_fpr32(fp0, fd);
8155 tcg_temp_free_i32(fp0);
8157 opn = "lwxc1";
8158 break;
8159 case OPC_LDXC1:
8160 check_cop1x(ctx);
8161 check_cp1_registers(ctx, fd);
8163 TCGv_i64 fp0 = tcg_temp_new_i64();
8165 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8166 gen_store_fpr64(ctx, fp0, fd);
8167 tcg_temp_free_i64(fp0);
8169 opn = "ldxc1";
8170 break;
8171 case OPC_LUXC1:
8172 check_cp1_64bitmode(ctx);
8173 tcg_gen_andi_tl(t0, t0, ~0x7);
8175 TCGv_i64 fp0 = tcg_temp_new_i64();
8177 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8178 gen_store_fpr64(ctx, fp0, fd);
8179 tcg_temp_free_i64(fp0);
8181 opn = "luxc1";
8182 break;
8183 case OPC_SWXC1:
8184 check_cop1x(ctx);
8186 TCGv_i32 fp0 = tcg_temp_new_i32();
8187 TCGv t1 = tcg_temp_new();
8189 gen_load_fpr32(fp0, fs);
8190 tcg_gen_extu_i32_tl(t1, fp0);
8191 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
8192 tcg_temp_free_i32(fp0);
8193 tcg_temp_free(t1);
8195 opn = "swxc1";
8196 store = 1;
8197 break;
8198 case OPC_SDXC1:
8199 check_cop1x(ctx);
8200 check_cp1_registers(ctx, fs);
8202 TCGv_i64 fp0 = tcg_temp_new_i64();
8204 gen_load_fpr64(ctx, fp0, fs);
8205 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
8206 tcg_temp_free_i64(fp0);
8208 opn = "sdxc1";
8209 store = 1;
8210 break;
8211 case OPC_SUXC1:
8212 check_cp1_64bitmode(ctx);
8213 tcg_gen_andi_tl(t0, t0, ~0x7);
8215 TCGv_i64 fp0 = tcg_temp_new_i64();
8217 gen_load_fpr64(ctx, fp0, fs);
8218 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
8219 tcg_temp_free_i64(fp0);
8221 opn = "suxc1";
8222 store = 1;
8223 break;
8225 tcg_temp_free(t0);
8226 (void)opn; (void)store; /* avoid compiler warnings */
8227 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
8228 regnames[index], regnames[base]);
8231 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
8232 int fd, int fr, int fs, int ft)
8234 const char *opn = "flt3_arith";
8236 switch (opc) {
8237 case OPC_ALNV_PS:
8238 check_cp1_64bitmode(ctx);
8240 TCGv t0 = tcg_temp_local_new();
8241 TCGv_i32 fp = tcg_temp_new_i32();
8242 TCGv_i32 fph = tcg_temp_new_i32();
8243 int l1 = gen_new_label();
8244 int l2 = gen_new_label();
8246 gen_load_gpr(t0, fr);
8247 tcg_gen_andi_tl(t0, t0, 0x7);
8249 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
8250 gen_load_fpr32(fp, fs);
8251 gen_load_fpr32h(fph, fs);
8252 gen_store_fpr32(fp, fd);
8253 gen_store_fpr32h(fph, fd);
8254 tcg_gen_br(l2);
8255 gen_set_label(l1);
8256 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
8257 tcg_temp_free(t0);
8258 #ifdef TARGET_WORDS_BIGENDIAN
8259 gen_load_fpr32(fp, fs);
8260 gen_load_fpr32h(fph, ft);
8261 gen_store_fpr32h(fp, fd);
8262 gen_store_fpr32(fph, fd);
8263 #else
8264 gen_load_fpr32h(fph, fs);
8265 gen_load_fpr32(fp, ft);
8266 gen_store_fpr32(fph, fd);
8267 gen_store_fpr32h(fp, fd);
8268 #endif
8269 gen_set_label(l2);
8270 tcg_temp_free_i32(fp);
8271 tcg_temp_free_i32(fph);
8273 opn = "alnv.ps";
8274 break;
8275 case OPC_MADD_S:
8276 check_cop1x(ctx);
8278 TCGv_i32 fp0 = tcg_temp_new_i32();
8279 TCGv_i32 fp1 = tcg_temp_new_i32();
8280 TCGv_i32 fp2 = tcg_temp_new_i32();
8282 gen_load_fpr32(fp0, fs);
8283 gen_load_fpr32(fp1, ft);
8284 gen_load_fpr32(fp2, fr);
8285 gen_helper_float_muladd_s(fp2, cpu_env, fp0, fp1, fp2);
8286 tcg_temp_free_i32(fp0);
8287 tcg_temp_free_i32(fp1);
8288 gen_store_fpr32(fp2, fd);
8289 tcg_temp_free_i32(fp2);
8291 opn = "madd.s";
8292 break;
8293 case OPC_MADD_D:
8294 check_cop1x(ctx);
8295 check_cp1_registers(ctx, fd | fs | ft | fr);
8297 TCGv_i64 fp0 = tcg_temp_new_i64();
8298 TCGv_i64 fp1 = tcg_temp_new_i64();
8299 TCGv_i64 fp2 = tcg_temp_new_i64();
8301 gen_load_fpr64(ctx, fp0, fs);
8302 gen_load_fpr64(ctx, fp1, ft);
8303 gen_load_fpr64(ctx, fp2, fr);
8304 gen_helper_float_muladd_d(fp2, cpu_env, fp0, fp1, fp2);
8305 tcg_temp_free_i64(fp0);
8306 tcg_temp_free_i64(fp1);
8307 gen_store_fpr64(ctx, fp2, fd);
8308 tcg_temp_free_i64(fp2);
8310 opn = "madd.d";
8311 break;
8312 case OPC_MADD_PS:
8313 check_cp1_64bitmode(ctx);
8315 TCGv_i64 fp0 = tcg_temp_new_i64();
8316 TCGv_i64 fp1 = tcg_temp_new_i64();
8317 TCGv_i64 fp2 = tcg_temp_new_i64();
8319 gen_load_fpr64(ctx, fp0, fs);
8320 gen_load_fpr64(ctx, fp1, ft);
8321 gen_load_fpr64(ctx, fp2, fr);
8322 gen_helper_float_muladd_ps(fp2, cpu_env, fp0, fp1, fp2);
8323 tcg_temp_free_i64(fp0);
8324 tcg_temp_free_i64(fp1);
8325 gen_store_fpr64(ctx, fp2, fd);
8326 tcg_temp_free_i64(fp2);
8328 opn = "madd.ps";
8329 break;
8330 case OPC_MSUB_S:
8331 check_cop1x(ctx);
8333 TCGv_i32 fp0 = tcg_temp_new_i32();
8334 TCGv_i32 fp1 = tcg_temp_new_i32();
8335 TCGv_i32 fp2 = tcg_temp_new_i32();
8337 gen_load_fpr32(fp0, fs);
8338 gen_load_fpr32(fp1, ft);
8339 gen_load_fpr32(fp2, fr);
8340 gen_helper_float_mulsub_s(fp2, cpu_env, fp0, fp1, fp2);
8341 tcg_temp_free_i32(fp0);
8342 tcg_temp_free_i32(fp1);
8343 gen_store_fpr32(fp2, fd);
8344 tcg_temp_free_i32(fp2);
8346 opn = "msub.s";
8347 break;
8348 case OPC_MSUB_D:
8349 check_cop1x(ctx);
8350 check_cp1_registers(ctx, fd | fs | ft | fr);
8352 TCGv_i64 fp0 = tcg_temp_new_i64();
8353 TCGv_i64 fp1 = tcg_temp_new_i64();
8354 TCGv_i64 fp2 = tcg_temp_new_i64();
8356 gen_load_fpr64(ctx, fp0, fs);
8357 gen_load_fpr64(ctx, fp1, ft);
8358 gen_load_fpr64(ctx, fp2, fr);
8359 gen_helper_float_mulsub_d(fp2, cpu_env, fp0, fp1, fp2);
8360 tcg_temp_free_i64(fp0);
8361 tcg_temp_free_i64(fp1);
8362 gen_store_fpr64(ctx, fp2, fd);
8363 tcg_temp_free_i64(fp2);
8365 opn = "msub.d";
8366 break;
8367 case OPC_MSUB_PS:
8368 check_cp1_64bitmode(ctx);
8370 TCGv_i64 fp0 = tcg_temp_new_i64();
8371 TCGv_i64 fp1 = tcg_temp_new_i64();
8372 TCGv_i64 fp2 = tcg_temp_new_i64();
8374 gen_load_fpr64(ctx, fp0, fs);
8375 gen_load_fpr64(ctx, fp1, ft);
8376 gen_load_fpr64(ctx, fp2, fr);
8377 gen_helper_float_mulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
8378 tcg_temp_free_i64(fp0);
8379 tcg_temp_free_i64(fp1);
8380 gen_store_fpr64(ctx, fp2, fd);
8381 tcg_temp_free_i64(fp2);
8383 opn = "msub.ps";
8384 break;
8385 case OPC_NMADD_S:
8386 check_cop1x(ctx);
8388 TCGv_i32 fp0 = tcg_temp_new_i32();
8389 TCGv_i32 fp1 = tcg_temp_new_i32();
8390 TCGv_i32 fp2 = tcg_temp_new_i32();
8392 gen_load_fpr32(fp0, fs);
8393 gen_load_fpr32(fp1, ft);
8394 gen_load_fpr32(fp2, fr);
8395 gen_helper_float_nmuladd_s(fp2, cpu_env, fp0, fp1, fp2);
8396 tcg_temp_free_i32(fp0);
8397 tcg_temp_free_i32(fp1);
8398 gen_store_fpr32(fp2, fd);
8399 tcg_temp_free_i32(fp2);
8401 opn = "nmadd.s";
8402 break;
8403 case OPC_NMADD_D:
8404 check_cop1x(ctx);
8405 check_cp1_registers(ctx, fd | fs | ft | fr);
8407 TCGv_i64 fp0 = tcg_temp_new_i64();
8408 TCGv_i64 fp1 = tcg_temp_new_i64();
8409 TCGv_i64 fp2 = tcg_temp_new_i64();
8411 gen_load_fpr64(ctx, fp0, fs);
8412 gen_load_fpr64(ctx, fp1, ft);
8413 gen_load_fpr64(ctx, fp2, fr);
8414 gen_helper_float_nmuladd_d(fp2, cpu_env, fp0, fp1, fp2);
8415 tcg_temp_free_i64(fp0);
8416 tcg_temp_free_i64(fp1);
8417 gen_store_fpr64(ctx, fp2, fd);
8418 tcg_temp_free_i64(fp2);
8420 opn = "nmadd.d";
8421 break;
8422 case OPC_NMADD_PS:
8423 check_cp1_64bitmode(ctx);
8425 TCGv_i64 fp0 = tcg_temp_new_i64();
8426 TCGv_i64 fp1 = tcg_temp_new_i64();
8427 TCGv_i64 fp2 = tcg_temp_new_i64();
8429 gen_load_fpr64(ctx, fp0, fs);
8430 gen_load_fpr64(ctx, fp1, ft);
8431 gen_load_fpr64(ctx, fp2, fr);
8432 gen_helper_float_nmuladd_ps(fp2, cpu_env, fp0, fp1, fp2);
8433 tcg_temp_free_i64(fp0);
8434 tcg_temp_free_i64(fp1);
8435 gen_store_fpr64(ctx, fp2, fd);
8436 tcg_temp_free_i64(fp2);
8438 opn = "nmadd.ps";
8439 break;
8440 case OPC_NMSUB_S:
8441 check_cop1x(ctx);
8443 TCGv_i32 fp0 = tcg_temp_new_i32();
8444 TCGv_i32 fp1 = tcg_temp_new_i32();
8445 TCGv_i32 fp2 = tcg_temp_new_i32();
8447 gen_load_fpr32(fp0, fs);
8448 gen_load_fpr32(fp1, ft);
8449 gen_load_fpr32(fp2, fr);
8450 gen_helper_float_nmulsub_s(fp2, cpu_env, fp0, fp1, fp2);
8451 tcg_temp_free_i32(fp0);
8452 tcg_temp_free_i32(fp1);
8453 gen_store_fpr32(fp2, fd);
8454 tcg_temp_free_i32(fp2);
8456 opn = "nmsub.s";
8457 break;
8458 case OPC_NMSUB_D:
8459 check_cop1x(ctx);
8460 check_cp1_registers(ctx, fd | fs | ft | fr);
8462 TCGv_i64 fp0 = tcg_temp_new_i64();
8463 TCGv_i64 fp1 = tcg_temp_new_i64();
8464 TCGv_i64 fp2 = tcg_temp_new_i64();
8466 gen_load_fpr64(ctx, fp0, fs);
8467 gen_load_fpr64(ctx, fp1, ft);
8468 gen_load_fpr64(ctx, fp2, fr);
8469 gen_helper_float_nmulsub_d(fp2, cpu_env, fp0, fp1, fp2);
8470 tcg_temp_free_i64(fp0);
8471 tcg_temp_free_i64(fp1);
8472 gen_store_fpr64(ctx, fp2, fd);
8473 tcg_temp_free_i64(fp2);
8475 opn = "nmsub.d";
8476 break;
8477 case OPC_NMSUB_PS:
8478 check_cp1_64bitmode(ctx);
8480 TCGv_i64 fp0 = tcg_temp_new_i64();
8481 TCGv_i64 fp1 = tcg_temp_new_i64();
8482 TCGv_i64 fp2 = tcg_temp_new_i64();
8484 gen_load_fpr64(ctx, fp0, fs);
8485 gen_load_fpr64(ctx, fp1, ft);
8486 gen_load_fpr64(ctx, fp2, fr);
8487 gen_helper_float_nmulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
8488 tcg_temp_free_i64(fp0);
8489 tcg_temp_free_i64(fp1);
8490 gen_store_fpr64(ctx, fp2, fd);
8491 tcg_temp_free_i64(fp2);
8493 opn = "nmsub.ps";
8494 break;
8495 default:
8496 MIPS_INVAL(opn);
8497 generate_exception (ctx, EXCP_RI);
8498 return;
8500 (void)opn; /* avoid a compiler warning */
8501 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8502 fregnames[fs], fregnames[ft]);
8505 static void
8506 gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
8508 TCGv t0;
8510 #if !defined(CONFIG_USER_ONLY)
8511 /* The Linux kernel will emulate rdhwr if it's not supported natively.
8512 Therefore only check the ISA in system mode. */
8513 check_insn(env, ctx, ISA_MIPS32R2);
8514 #endif
8515 t0 = tcg_temp_new();
8517 switch (rd) {
8518 case 0:
8519 save_cpu_state(ctx, 1);
8520 gen_helper_rdhwr_cpunum(t0, cpu_env);
8521 gen_store_gpr(t0, rt);
8522 break;
8523 case 1:
8524 save_cpu_state(ctx, 1);
8525 gen_helper_rdhwr_synci_step(t0, cpu_env);
8526 gen_store_gpr(t0, rt);
8527 break;
8528 case 2:
8529 save_cpu_state(ctx, 1);
8530 gen_helper_rdhwr_cc(t0, cpu_env);
8531 gen_store_gpr(t0, rt);
8532 break;
8533 case 3:
8534 save_cpu_state(ctx, 1);
8535 gen_helper_rdhwr_ccres(t0, cpu_env);
8536 gen_store_gpr(t0, rt);
8537 break;
8538 case 29:
8539 #if defined(CONFIG_USER_ONLY)
8540 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
8541 gen_store_gpr(t0, rt);
8542 break;
8543 #else
8544 /* XXX: Some CPUs implement this in hardware.
8545 Not supported yet. */
8546 #endif
8547 default: /* Invalid */
8548 MIPS_INVAL("rdhwr");
8549 generate_exception(ctx, EXCP_RI);
8550 break;
8552 tcg_temp_free(t0);
8555 static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
8556 int insn_bytes)
8558 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8559 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8560 /* Branches completion */
8561 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8562 ctx->bstate = BS_BRANCH;
8563 save_cpu_state(ctx, 0);
8564 /* FIXME: Need to clear can_do_io. */
8565 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
8566 case MIPS_HFLAG_B:
8567 /* unconditional branch */
8568 MIPS_DEBUG("unconditional branch");
8569 if (proc_hflags & MIPS_HFLAG_BX) {
8570 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8572 gen_goto_tb(ctx, 0, ctx->btarget);
8573 break;
8574 case MIPS_HFLAG_BL:
8575 /* blikely taken case */
8576 MIPS_DEBUG("blikely branch taken");
8577 gen_goto_tb(ctx, 0, ctx->btarget);
8578 break;
8579 case MIPS_HFLAG_BC:
8580 /* Conditional branch */
8581 MIPS_DEBUG("conditional branch");
8583 int l1 = gen_new_label();
8585 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8586 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8587 gen_set_label(l1);
8588 gen_goto_tb(ctx, 0, ctx->btarget);
8590 break;
8591 case MIPS_HFLAG_BR:
8592 /* unconditional branch to register */
8593 MIPS_DEBUG("branch to register");
8594 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
8595 TCGv t0 = tcg_temp_new();
8596 TCGv_i32 t1 = tcg_temp_new_i32();
8598 tcg_gen_andi_tl(t0, btarget, 0x1);
8599 tcg_gen_trunc_tl_i32(t1, t0);
8600 tcg_temp_free(t0);
8601 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8602 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8603 tcg_gen_or_i32(hflags, hflags, t1);
8604 tcg_temp_free_i32(t1);
8606 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8607 } else {
8608 tcg_gen_mov_tl(cpu_PC, btarget);
8610 if (ctx->singlestep_enabled) {
8611 save_cpu_state(ctx, 0);
8612 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
8614 tcg_gen_exit_tb(0);
8615 break;
8616 default:
8617 MIPS_DEBUG("unknown branch");
8618 break;
8623 /* ISA extensions (ASEs) */
8624 /* MIPS16 extension to MIPS32 */
8626 /* MIPS16 major opcodes */
8627 enum {
8628 M16_OPC_ADDIUSP = 0x00,
8629 M16_OPC_ADDIUPC = 0x01,
8630 M16_OPC_B = 0x02,
8631 M16_OPC_JAL = 0x03,
8632 M16_OPC_BEQZ = 0x04,
8633 M16_OPC_BNEQZ = 0x05,
8634 M16_OPC_SHIFT = 0x06,
8635 M16_OPC_LD = 0x07,
8636 M16_OPC_RRIA = 0x08,
8637 M16_OPC_ADDIU8 = 0x09,
8638 M16_OPC_SLTI = 0x0a,
8639 M16_OPC_SLTIU = 0x0b,
8640 M16_OPC_I8 = 0x0c,
8641 M16_OPC_LI = 0x0d,
8642 M16_OPC_CMPI = 0x0e,
8643 M16_OPC_SD = 0x0f,
8644 M16_OPC_LB = 0x10,
8645 M16_OPC_LH = 0x11,
8646 M16_OPC_LWSP = 0x12,
8647 M16_OPC_LW = 0x13,
8648 M16_OPC_LBU = 0x14,
8649 M16_OPC_LHU = 0x15,
8650 M16_OPC_LWPC = 0x16,
8651 M16_OPC_LWU = 0x17,
8652 M16_OPC_SB = 0x18,
8653 M16_OPC_SH = 0x19,
8654 M16_OPC_SWSP = 0x1a,
8655 M16_OPC_SW = 0x1b,
8656 M16_OPC_RRR = 0x1c,
8657 M16_OPC_RR = 0x1d,
8658 M16_OPC_EXTEND = 0x1e,
8659 M16_OPC_I64 = 0x1f
8662 /* I8 funct field */
8663 enum {
8664 I8_BTEQZ = 0x0,
8665 I8_BTNEZ = 0x1,
8666 I8_SWRASP = 0x2,
8667 I8_ADJSP = 0x3,
8668 I8_SVRS = 0x4,
8669 I8_MOV32R = 0x5,
8670 I8_MOVR32 = 0x7
8673 /* RRR f field */
8674 enum {
8675 RRR_DADDU = 0x0,
8676 RRR_ADDU = 0x1,
8677 RRR_DSUBU = 0x2,
8678 RRR_SUBU = 0x3
8681 /* RR funct field */
8682 enum {
8683 RR_JR = 0x00,
8684 RR_SDBBP = 0x01,
8685 RR_SLT = 0x02,
8686 RR_SLTU = 0x03,
8687 RR_SLLV = 0x04,
8688 RR_BREAK = 0x05,
8689 RR_SRLV = 0x06,
8690 RR_SRAV = 0x07,
8691 RR_DSRL = 0x08,
8692 RR_CMP = 0x0a,
8693 RR_NEG = 0x0b,
8694 RR_AND = 0x0c,
8695 RR_OR = 0x0d,
8696 RR_XOR = 0x0e,
8697 RR_NOT = 0x0f,
8698 RR_MFHI = 0x10,
8699 RR_CNVT = 0x11,
8700 RR_MFLO = 0x12,
8701 RR_DSRA = 0x13,
8702 RR_DSLLV = 0x14,
8703 RR_DSRLV = 0x16,
8704 RR_DSRAV = 0x17,
8705 RR_MULT = 0x18,
8706 RR_MULTU = 0x19,
8707 RR_DIV = 0x1a,
8708 RR_DIVU = 0x1b,
8709 RR_DMULT = 0x1c,
8710 RR_DMULTU = 0x1d,
8711 RR_DDIV = 0x1e,
8712 RR_DDIVU = 0x1f
8715 /* I64 funct field */
8716 enum {
8717 I64_LDSP = 0x0,
8718 I64_SDSP = 0x1,
8719 I64_SDRASP = 0x2,
8720 I64_DADJSP = 0x3,
8721 I64_LDPC = 0x4,
8722 I64_DADDIU5 = 0x5,
8723 I64_DADDIUPC = 0x6,
8724 I64_DADDIUSP = 0x7
8727 /* RR ry field for CNVT */
8728 enum {
8729 RR_RY_CNVT_ZEB = 0x0,
8730 RR_RY_CNVT_ZEH = 0x1,
8731 RR_RY_CNVT_ZEW = 0x2,
8732 RR_RY_CNVT_SEB = 0x4,
8733 RR_RY_CNVT_SEH = 0x5,
8734 RR_RY_CNVT_SEW = 0x6,
8737 static int xlat (int r)
8739 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8741 return map[r];
8744 static void gen_mips16_save (DisasContext *ctx,
8745 int xsregs, int aregs,
8746 int do_ra, int do_s0, int do_s1,
8747 int framesize)
8749 TCGv t0 = tcg_temp_new();
8750 TCGv t1 = tcg_temp_new();
8751 int args, astatic;
8753 switch (aregs) {
8754 case 0:
8755 case 1:
8756 case 2:
8757 case 3:
8758 case 11:
8759 args = 0;
8760 break;
8761 case 4:
8762 case 5:
8763 case 6:
8764 case 7:
8765 args = 1;
8766 break;
8767 case 8:
8768 case 9:
8769 case 10:
8770 args = 2;
8771 break;
8772 case 12:
8773 case 13:
8774 args = 3;
8775 break;
8776 case 14:
8777 args = 4;
8778 break;
8779 default:
8780 generate_exception(ctx, EXCP_RI);
8781 return;
8784 switch (args) {
8785 case 4:
8786 gen_base_offset_addr(ctx, t0, 29, 12);
8787 gen_load_gpr(t1, 7);
8788 op_st_sw(t1, t0, ctx);
8789 /* Fall through */
8790 case 3:
8791 gen_base_offset_addr(ctx, t0, 29, 8);
8792 gen_load_gpr(t1, 6);
8793 op_st_sw(t1, t0, ctx);
8794 /* Fall through */
8795 case 2:
8796 gen_base_offset_addr(ctx, t0, 29, 4);
8797 gen_load_gpr(t1, 5);
8798 op_st_sw(t1, t0, ctx);
8799 /* Fall through */
8800 case 1:
8801 gen_base_offset_addr(ctx, t0, 29, 0);
8802 gen_load_gpr(t1, 4);
8803 op_st_sw(t1, t0, ctx);
8806 gen_load_gpr(t0, 29);
8808 #define DECR_AND_STORE(reg) do { \
8809 tcg_gen_subi_tl(t0, t0, 4); \
8810 gen_load_gpr(t1, reg); \
8811 op_st_sw(t1, t0, ctx); \
8812 } while (0)
8814 if (do_ra) {
8815 DECR_AND_STORE(31);
8818 switch (xsregs) {
8819 case 7:
8820 DECR_AND_STORE(30);
8821 /* Fall through */
8822 case 6:
8823 DECR_AND_STORE(23);
8824 /* Fall through */
8825 case 5:
8826 DECR_AND_STORE(22);
8827 /* Fall through */
8828 case 4:
8829 DECR_AND_STORE(21);
8830 /* Fall through */
8831 case 3:
8832 DECR_AND_STORE(20);
8833 /* Fall through */
8834 case 2:
8835 DECR_AND_STORE(19);
8836 /* Fall through */
8837 case 1:
8838 DECR_AND_STORE(18);
8841 if (do_s1) {
8842 DECR_AND_STORE(17);
8844 if (do_s0) {
8845 DECR_AND_STORE(16);
8848 switch (aregs) {
8849 case 0:
8850 case 4:
8851 case 8:
8852 case 12:
8853 case 14:
8854 astatic = 0;
8855 break;
8856 case 1:
8857 case 5:
8858 case 9:
8859 case 13:
8860 astatic = 1;
8861 break;
8862 case 2:
8863 case 6:
8864 case 10:
8865 astatic = 2;
8866 break;
8867 case 3:
8868 case 7:
8869 astatic = 3;
8870 break;
8871 case 11:
8872 astatic = 4;
8873 break;
8874 default:
8875 generate_exception(ctx, EXCP_RI);
8876 return;
8879 if (astatic > 0) {
8880 DECR_AND_STORE(7);
8881 if (astatic > 1) {
8882 DECR_AND_STORE(6);
8883 if (astatic > 2) {
8884 DECR_AND_STORE(5);
8885 if (astatic > 3) {
8886 DECR_AND_STORE(4);
8891 #undef DECR_AND_STORE
8893 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8894 tcg_temp_free(t0);
8895 tcg_temp_free(t1);
8898 static void gen_mips16_restore (DisasContext *ctx,
8899 int xsregs, int aregs,
8900 int do_ra, int do_s0, int do_s1,
8901 int framesize)
8903 int astatic;
8904 TCGv t0 = tcg_temp_new();
8905 TCGv t1 = tcg_temp_new();
8907 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8909 #define DECR_AND_LOAD(reg) do { \
8910 tcg_gen_subi_tl(t0, t0, 4); \
8911 op_ld_lw(t1, t0, ctx); \
8912 gen_store_gpr(t1, reg); \
8913 } while (0)
8915 if (do_ra) {
8916 DECR_AND_LOAD(31);
8919 switch (xsregs) {
8920 case 7:
8921 DECR_AND_LOAD(30);
8922 /* Fall through */
8923 case 6:
8924 DECR_AND_LOAD(23);
8925 /* Fall through */
8926 case 5:
8927 DECR_AND_LOAD(22);
8928 /* Fall through */
8929 case 4:
8930 DECR_AND_LOAD(21);
8931 /* Fall through */
8932 case 3:
8933 DECR_AND_LOAD(20);
8934 /* Fall through */
8935 case 2:
8936 DECR_AND_LOAD(19);
8937 /* Fall through */
8938 case 1:
8939 DECR_AND_LOAD(18);
8942 if (do_s1) {
8943 DECR_AND_LOAD(17);
8945 if (do_s0) {
8946 DECR_AND_LOAD(16);
8949 switch (aregs) {
8950 case 0:
8951 case 4:
8952 case 8:
8953 case 12:
8954 case 14:
8955 astatic = 0;
8956 break;
8957 case 1:
8958 case 5:
8959 case 9:
8960 case 13:
8961 astatic = 1;
8962 break;
8963 case 2:
8964 case 6:
8965 case 10:
8966 astatic = 2;
8967 break;
8968 case 3:
8969 case 7:
8970 astatic = 3;
8971 break;
8972 case 11:
8973 astatic = 4;
8974 break;
8975 default:
8976 generate_exception(ctx, EXCP_RI);
8977 return;
8980 if (astatic > 0) {
8981 DECR_AND_LOAD(7);
8982 if (astatic > 1) {
8983 DECR_AND_LOAD(6);
8984 if (astatic > 2) {
8985 DECR_AND_LOAD(5);
8986 if (astatic > 3) {
8987 DECR_AND_LOAD(4);
8992 #undef DECR_AND_LOAD
8994 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8995 tcg_temp_free(t0);
8996 tcg_temp_free(t1);
8999 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
9000 int is_64_bit, int extended)
9002 TCGv t0;
9004 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9005 generate_exception(ctx, EXCP_RI);
9006 return;
9009 t0 = tcg_temp_new();
9011 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
9012 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
9013 if (!is_64_bit) {
9014 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9017 tcg_temp_free(t0);
9020 #if defined(TARGET_MIPS64)
9021 static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
9022 int ry, int funct, int16_t offset,
9023 int extended)
9025 switch (funct) {
9026 case I64_LDSP:
9027 check_mips_64(ctx);
9028 offset = extended ? offset : offset << 3;
9029 gen_ld(env, ctx, OPC_LD, ry, 29, offset);
9030 break;
9031 case I64_SDSP:
9032 check_mips_64(ctx);
9033 offset = extended ? offset : offset << 3;
9034 gen_st(ctx, OPC_SD, ry, 29, offset);
9035 break;
9036 case I64_SDRASP:
9037 check_mips_64(ctx);
9038 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
9039 gen_st(ctx, OPC_SD, 31, 29, offset);
9040 break;
9041 case I64_DADJSP:
9042 check_mips_64(ctx);
9043 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
9044 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
9045 break;
9046 case I64_LDPC:
9047 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9048 generate_exception(ctx, EXCP_RI);
9049 } else {
9050 offset = extended ? offset : offset << 3;
9051 gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
9053 break;
9054 case I64_DADDIU5:
9055 check_mips_64(ctx);
9056 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
9057 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
9058 break;
9059 case I64_DADDIUPC:
9060 check_mips_64(ctx);
9061 offset = extended ? offset : offset << 2;
9062 gen_addiupc(ctx, ry, offset, 1, extended);
9063 break;
9064 case I64_DADDIUSP:
9065 check_mips_64(ctx);
9066 offset = extended ? offset : offset << 2;
9067 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
9068 break;
9071 #endif
9073 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
9074 int *is_branch)
9076 int extend = cpu_lduw_code(env, ctx->pc + 2);
9077 int op, rx, ry, funct, sa;
9078 int16_t imm, offset;
9080 ctx->opcode = (ctx->opcode << 16) | extend;
9081 op = (ctx->opcode >> 11) & 0x1f;
9082 sa = (ctx->opcode >> 22) & 0x1f;
9083 funct = (ctx->opcode >> 8) & 0x7;
9084 rx = xlat((ctx->opcode >> 8) & 0x7);
9085 ry = xlat((ctx->opcode >> 5) & 0x7);
9086 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
9087 | ((ctx->opcode >> 21) & 0x3f) << 5
9088 | (ctx->opcode & 0x1f));
9090 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
9091 counterparts. */
9092 switch (op) {
9093 case M16_OPC_ADDIUSP:
9094 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
9095 break;
9096 case M16_OPC_ADDIUPC:
9097 gen_addiupc(ctx, rx, imm, 0, 1);
9098 break;
9099 case M16_OPC_B:
9100 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
9101 /* No delay slot, so just process as a normal instruction */
9102 break;
9103 case M16_OPC_BEQZ:
9104 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
9105 /* No delay slot, so just process as a normal instruction */
9106 break;
9107 case M16_OPC_BNEQZ:
9108 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
9109 /* No delay slot, so just process as a normal instruction */
9110 break;
9111 case M16_OPC_SHIFT:
9112 switch (ctx->opcode & 0x3) {
9113 case 0x0:
9114 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
9115 break;
9116 case 0x1:
9117 #if defined(TARGET_MIPS64)
9118 check_mips_64(ctx);
9119 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
9120 #else
9121 generate_exception(ctx, EXCP_RI);
9122 #endif
9123 break;
9124 case 0x2:
9125 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
9126 break;
9127 case 0x3:
9128 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
9129 break;
9131 break;
9132 #if defined(TARGET_MIPS64)
9133 case M16_OPC_LD:
9134 check_mips_64(ctx);
9135 gen_ld(env, ctx, OPC_LD, ry, rx, offset);
9136 break;
9137 #endif
9138 case M16_OPC_RRIA:
9139 imm = ctx->opcode & 0xf;
9140 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
9141 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
9142 imm = (int16_t) (imm << 1) >> 1;
9143 if ((ctx->opcode >> 4) & 0x1) {
9144 #if defined(TARGET_MIPS64)
9145 check_mips_64(ctx);
9146 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
9147 #else
9148 generate_exception(ctx, EXCP_RI);
9149 #endif
9150 } else {
9151 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
9153 break;
9154 case M16_OPC_ADDIU8:
9155 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
9156 break;
9157 case M16_OPC_SLTI:
9158 gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
9159 break;
9160 case M16_OPC_SLTIU:
9161 gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
9162 break;
9163 case M16_OPC_I8:
9164 switch (funct) {
9165 case I8_BTEQZ:
9166 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
9167 break;
9168 case I8_BTNEZ:
9169 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
9170 break;
9171 case I8_SWRASP:
9172 gen_st(ctx, OPC_SW, 31, 29, imm);
9173 break;
9174 case I8_ADJSP:
9175 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
9176 break;
9177 case I8_SVRS:
9179 int xsregs = (ctx->opcode >> 24) & 0x7;
9180 int aregs = (ctx->opcode >> 16) & 0xf;
9181 int do_ra = (ctx->opcode >> 6) & 0x1;
9182 int do_s0 = (ctx->opcode >> 5) & 0x1;
9183 int do_s1 = (ctx->opcode >> 4) & 0x1;
9184 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
9185 | (ctx->opcode & 0xf)) << 3;
9187 if (ctx->opcode & (1 << 7)) {
9188 gen_mips16_save(ctx, xsregs, aregs,
9189 do_ra, do_s0, do_s1,
9190 framesize);
9191 } else {
9192 gen_mips16_restore(ctx, xsregs, aregs,
9193 do_ra, do_s0, do_s1,
9194 framesize);
9197 break;
9198 default:
9199 generate_exception(ctx, EXCP_RI);
9200 break;
9202 break;
9203 case M16_OPC_LI:
9204 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
9205 break;
9206 case M16_OPC_CMPI:
9207 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
9208 break;
9209 #if defined(TARGET_MIPS64)
9210 case M16_OPC_SD:
9211 gen_st(ctx, OPC_SD, ry, rx, offset);
9212 break;
9213 #endif
9214 case M16_OPC_LB:
9215 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
9216 break;
9217 case M16_OPC_LH:
9218 gen_ld(env, ctx, OPC_LH, ry, rx, offset);
9219 break;
9220 case M16_OPC_LWSP:
9221 gen_ld(env, ctx, OPC_LW, rx, 29, offset);
9222 break;
9223 case M16_OPC_LW:
9224 gen_ld(env, ctx, OPC_LW, ry, rx, offset);
9225 break;
9226 case M16_OPC_LBU:
9227 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
9228 break;
9229 case M16_OPC_LHU:
9230 gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
9231 break;
9232 case M16_OPC_LWPC:
9233 gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
9234 break;
9235 #if defined(TARGET_MIPS64)
9236 case M16_OPC_LWU:
9237 gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
9238 break;
9239 #endif
9240 case M16_OPC_SB:
9241 gen_st(ctx, OPC_SB, ry, rx, offset);
9242 break;
9243 case M16_OPC_SH:
9244 gen_st(ctx, OPC_SH, ry, rx, offset);
9245 break;
9246 case M16_OPC_SWSP:
9247 gen_st(ctx, OPC_SW, rx, 29, offset);
9248 break;
9249 case M16_OPC_SW:
9250 gen_st(ctx, OPC_SW, ry, rx, offset);
9251 break;
9252 #if defined(TARGET_MIPS64)
9253 case M16_OPC_I64:
9254 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
9255 break;
9256 #endif
9257 default:
9258 generate_exception(ctx, EXCP_RI);
9259 break;
9262 return 4;
9265 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
9266 int *is_branch)
9268 int rx, ry;
9269 int sa;
9270 int op, cnvt_op, op1, offset;
9271 int funct;
9272 int n_bytes;
9274 op = (ctx->opcode >> 11) & 0x1f;
9275 sa = (ctx->opcode >> 2) & 0x7;
9276 sa = sa == 0 ? 8 : sa;
9277 rx = xlat((ctx->opcode >> 8) & 0x7);
9278 cnvt_op = (ctx->opcode >> 5) & 0x7;
9279 ry = xlat((ctx->opcode >> 5) & 0x7);
9280 op1 = offset = ctx->opcode & 0x1f;
9282 n_bytes = 2;
9284 switch (op) {
9285 case M16_OPC_ADDIUSP:
9287 int16_t imm = ((uint8_t) ctx->opcode) << 2;
9289 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
9291 break;
9292 case M16_OPC_ADDIUPC:
9293 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
9294 break;
9295 case M16_OPC_B:
9296 offset = (ctx->opcode & 0x7ff) << 1;
9297 offset = (int16_t)(offset << 4) >> 4;
9298 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
9299 /* No delay slot, so just process as a normal instruction */
9300 break;
9301 case M16_OPC_JAL:
9302 offset = cpu_lduw_code(env, ctx->pc + 2);
9303 offset = (((ctx->opcode & 0x1f) << 21)
9304 | ((ctx->opcode >> 5) & 0x1f) << 16
9305 | offset) << 2;
9306 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
9307 gen_compute_branch(ctx, op, 4, rx, ry, offset);
9308 n_bytes = 4;
9309 *is_branch = 1;
9310 break;
9311 case M16_OPC_BEQZ:
9312 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9313 /* No delay slot, so just process as a normal instruction */
9314 break;
9315 case M16_OPC_BNEQZ:
9316 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9317 /* No delay slot, so just process as a normal instruction */
9318 break;
9319 case M16_OPC_SHIFT:
9320 switch (ctx->opcode & 0x3) {
9321 case 0x0:
9322 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
9323 break;
9324 case 0x1:
9325 #if defined(TARGET_MIPS64)
9326 check_mips_64(ctx);
9327 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
9328 #else
9329 generate_exception(ctx, EXCP_RI);
9330 #endif
9331 break;
9332 case 0x2:
9333 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
9334 break;
9335 case 0x3:
9336 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
9337 break;
9339 break;
9340 #if defined(TARGET_MIPS64)
9341 case M16_OPC_LD:
9342 check_mips_64(ctx);
9343 gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
9344 break;
9345 #endif
9346 case M16_OPC_RRIA:
9348 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
9350 if ((ctx->opcode >> 4) & 1) {
9351 #if defined(TARGET_MIPS64)
9352 check_mips_64(ctx);
9353 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
9354 #else
9355 generate_exception(ctx, EXCP_RI);
9356 #endif
9357 } else {
9358 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
9361 break;
9362 case M16_OPC_ADDIU8:
9364 int16_t imm = (int8_t) ctx->opcode;
9366 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
9368 break;
9369 case M16_OPC_SLTI:
9371 int16_t imm = (uint8_t) ctx->opcode;
9372 gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
9374 break;
9375 case M16_OPC_SLTIU:
9377 int16_t imm = (uint8_t) ctx->opcode;
9378 gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
9380 break;
9381 case M16_OPC_I8:
9383 int reg32;
9385 funct = (ctx->opcode >> 8) & 0x7;
9386 switch (funct) {
9387 case I8_BTEQZ:
9388 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
9389 ((int8_t)ctx->opcode) << 1);
9390 break;
9391 case I8_BTNEZ:
9392 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
9393 ((int8_t)ctx->opcode) << 1);
9394 break;
9395 case I8_SWRASP:
9396 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
9397 break;
9398 case I8_ADJSP:
9399 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
9400 ((int8_t)ctx->opcode) << 3);
9401 break;
9402 case I8_SVRS:
9404 int do_ra = ctx->opcode & (1 << 6);
9405 int do_s0 = ctx->opcode & (1 << 5);
9406 int do_s1 = ctx->opcode & (1 << 4);
9407 int framesize = ctx->opcode & 0xf;
9409 if (framesize == 0) {
9410 framesize = 128;
9411 } else {
9412 framesize = framesize << 3;
9415 if (ctx->opcode & (1 << 7)) {
9416 gen_mips16_save(ctx, 0, 0,
9417 do_ra, do_s0, do_s1, framesize);
9418 } else {
9419 gen_mips16_restore(ctx, 0, 0,
9420 do_ra, do_s0, do_s1, framesize);
9423 break;
9424 case I8_MOV32R:
9426 int rz = xlat(ctx->opcode & 0x7);
9428 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9429 ((ctx->opcode >> 5) & 0x7);
9430 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
9432 break;
9433 case I8_MOVR32:
9434 reg32 = ctx->opcode & 0x1f;
9435 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
9436 break;
9437 default:
9438 generate_exception(ctx, EXCP_RI);
9439 break;
9442 break;
9443 case M16_OPC_LI:
9445 int16_t imm = (uint8_t) ctx->opcode;
9447 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
9449 break;
9450 case M16_OPC_CMPI:
9452 int16_t imm = (uint8_t) ctx->opcode;
9453 gen_logic_imm(env, ctx, OPC_XORI, 24, rx, imm);
9455 break;
9456 #if defined(TARGET_MIPS64)
9457 case M16_OPC_SD:
9458 check_mips_64(ctx);
9459 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
9460 break;
9461 #endif
9462 case M16_OPC_LB:
9463 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
9464 break;
9465 case M16_OPC_LH:
9466 gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
9467 break;
9468 case M16_OPC_LWSP:
9469 gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9470 break;
9471 case M16_OPC_LW:
9472 gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
9473 break;
9474 case M16_OPC_LBU:
9475 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
9476 break;
9477 case M16_OPC_LHU:
9478 gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
9479 break;
9480 case M16_OPC_LWPC:
9481 gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
9482 break;
9483 #if defined (TARGET_MIPS64)
9484 case M16_OPC_LWU:
9485 check_mips_64(ctx);
9486 gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
9487 break;
9488 #endif
9489 case M16_OPC_SB:
9490 gen_st(ctx, OPC_SB, ry, rx, offset);
9491 break;
9492 case M16_OPC_SH:
9493 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
9494 break;
9495 case M16_OPC_SWSP:
9496 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9497 break;
9498 case M16_OPC_SW:
9499 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
9500 break;
9501 case M16_OPC_RRR:
9503 int rz = xlat((ctx->opcode >> 2) & 0x7);
9504 int mips32_op;
9506 switch (ctx->opcode & 0x3) {
9507 case RRR_ADDU:
9508 mips32_op = OPC_ADDU;
9509 break;
9510 case RRR_SUBU:
9511 mips32_op = OPC_SUBU;
9512 break;
9513 #if defined(TARGET_MIPS64)
9514 case RRR_DADDU:
9515 mips32_op = OPC_DADDU;
9516 check_mips_64(ctx);
9517 break;
9518 case RRR_DSUBU:
9519 mips32_op = OPC_DSUBU;
9520 check_mips_64(ctx);
9521 break;
9522 #endif
9523 default:
9524 generate_exception(ctx, EXCP_RI);
9525 goto done;
9528 gen_arith(env, ctx, mips32_op, rz, rx, ry);
9529 done:
9532 break;
9533 case M16_OPC_RR:
9534 switch (op1) {
9535 case RR_JR:
9537 int nd = (ctx->opcode >> 7) & 0x1;
9538 int link = (ctx->opcode >> 6) & 0x1;
9539 int ra = (ctx->opcode >> 5) & 0x1;
9541 if (link) {
9542 op = nd ? OPC_JALRC : OPC_JALRS;
9543 } else {
9544 op = OPC_JR;
9547 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9548 if (!nd) {
9549 *is_branch = 1;
9552 break;
9553 case RR_SDBBP:
9554 /* XXX: not clear which exception should be raised
9555 * when in debug mode...
9557 check_insn(env, ctx, ISA_MIPS32);
9558 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9559 generate_exception(ctx, EXCP_DBp);
9560 } else {
9561 generate_exception(ctx, EXCP_DBp);
9563 break;
9564 case RR_SLT:
9565 gen_slt(env, ctx, OPC_SLT, 24, rx, ry);
9566 break;
9567 case RR_SLTU:
9568 gen_slt(env, ctx, OPC_SLTU, 24, rx, ry);
9569 break;
9570 case RR_BREAK:
9571 generate_exception(ctx, EXCP_BREAK);
9572 break;
9573 case RR_SLLV:
9574 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9575 break;
9576 case RR_SRLV:
9577 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9578 break;
9579 case RR_SRAV:
9580 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9581 break;
9582 #if defined (TARGET_MIPS64)
9583 case RR_DSRL:
9584 check_mips_64(ctx);
9585 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9586 break;
9587 #endif
9588 case RR_CMP:
9589 gen_logic(env, ctx, OPC_XOR, 24, rx, ry);
9590 break;
9591 case RR_NEG:
9592 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9593 break;
9594 case RR_AND:
9595 gen_logic(env, ctx, OPC_AND, rx, rx, ry);
9596 break;
9597 case RR_OR:
9598 gen_logic(env, ctx, OPC_OR, rx, rx, ry);
9599 break;
9600 case RR_XOR:
9601 gen_logic(env, ctx, OPC_XOR, rx, rx, ry);
9602 break;
9603 case RR_NOT:
9604 gen_logic(env, ctx, OPC_NOR, rx, ry, 0);
9605 break;
9606 case RR_MFHI:
9607 gen_HILO(ctx, OPC_MFHI, rx);
9608 break;
9609 case RR_CNVT:
9610 switch (cnvt_op) {
9611 case RR_RY_CNVT_ZEB:
9612 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9613 break;
9614 case RR_RY_CNVT_ZEH:
9615 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9616 break;
9617 case RR_RY_CNVT_SEB:
9618 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9619 break;
9620 case RR_RY_CNVT_SEH:
9621 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9622 break;
9623 #if defined (TARGET_MIPS64)
9624 case RR_RY_CNVT_ZEW:
9625 check_mips_64(ctx);
9626 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9627 break;
9628 case RR_RY_CNVT_SEW:
9629 check_mips_64(ctx);
9630 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9631 break;
9632 #endif
9633 default:
9634 generate_exception(ctx, EXCP_RI);
9635 break;
9637 break;
9638 case RR_MFLO:
9639 gen_HILO(ctx, OPC_MFLO, rx);
9640 break;
9641 #if defined (TARGET_MIPS64)
9642 case RR_DSRA:
9643 check_mips_64(ctx);
9644 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9645 break;
9646 case RR_DSLLV:
9647 check_mips_64(ctx);
9648 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9649 break;
9650 case RR_DSRLV:
9651 check_mips_64(ctx);
9652 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9653 break;
9654 case RR_DSRAV:
9655 check_mips_64(ctx);
9656 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9657 break;
9658 #endif
9659 case RR_MULT:
9660 gen_muldiv(ctx, OPC_MULT, rx, ry);
9661 break;
9662 case RR_MULTU:
9663 gen_muldiv(ctx, OPC_MULTU, rx, ry);
9664 break;
9665 case RR_DIV:
9666 gen_muldiv(ctx, OPC_DIV, rx, ry);
9667 break;
9668 case RR_DIVU:
9669 gen_muldiv(ctx, OPC_DIVU, rx, ry);
9670 break;
9671 #if defined (TARGET_MIPS64)
9672 case RR_DMULT:
9673 check_mips_64(ctx);
9674 gen_muldiv(ctx, OPC_DMULT, rx, ry);
9675 break;
9676 case RR_DMULTU:
9677 check_mips_64(ctx);
9678 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9679 break;
9680 case RR_DDIV:
9681 check_mips_64(ctx);
9682 gen_muldiv(ctx, OPC_DDIV, rx, ry);
9683 break;
9684 case RR_DDIVU:
9685 check_mips_64(ctx);
9686 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9687 break;
9688 #endif
9689 default:
9690 generate_exception(ctx, EXCP_RI);
9691 break;
9693 break;
9694 case M16_OPC_EXTEND:
9695 decode_extended_mips16_opc(env, ctx, is_branch);
9696 n_bytes = 4;
9697 break;
9698 #if defined(TARGET_MIPS64)
9699 case M16_OPC_I64:
9700 funct = (ctx->opcode >> 8) & 0x7;
9701 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9702 break;
9703 #endif
9704 default:
9705 generate_exception(ctx, EXCP_RI);
9706 break;
9709 return n_bytes;
9712 /* microMIPS extension to MIPS32 */
9714 /* microMIPS32 major opcodes */
9716 enum {
9717 POOL32A = 0x00,
9718 POOL16A = 0x01,
9719 LBU16 = 0x02,
9720 MOVE16 = 0x03,
9721 ADDI32 = 0x04,
9722 LBU32 = 0x05,
9723 SB32 = 0x06,
9724 LB32 = 0x07,
9726 POOL32B = 0x08,
9727 POOL16B = 0x09,
9728 LHU16 = 0x0a,
9729 ANDI16 = 0x0b,
9730 ADDIU32 = 0x0c,
9731 LHU32 = 0x0d,
9732 SH32 = 0x0e,
9733 LH32 = 0x0f,
9735 POOL32I = 0x10,
9736 POOL16C = 0x11,
9737 LWSP16 = 0x12,
9738 POOL16D = 0x13,
9739 ORI32 = 0x14,
9740 POOL32F = 0x15,
9741 POOL32S = 0x16,
9742 DADDIU32 = 0x17,
9744 POOL32C = 0x18,
9745 LWGP16 = 0x19,
9746 LW16 = 0x1a,
9747 POOL16E = 0x1b,
9748 XORI32 = 0x1c,
9749 JALS32 = 0x1d,
9750 ADDIUPC = 0x1e,
9751 POOL48A = 0x1f,
9753 /* 0x20 is reserved */
9754 RES_20 = 0x20,
9755 POOL16F = 0x21,
9756 SB16 = 0x22,
9757 BEQZ16 = 0x23,
9758 SLTI32 = 0x24,
9759 BEQ32 = 0x25,
9760 SWC132 = 0x26,
9761 LWC132 = 0x27,
9763 /* 0x28 and 0x29 are reserved */
9764 RES_28 = 0x28,
9765 RES_29 = 0x29,
9766 SH16 = 0x2a,
9767 BNEZ16 = 0x2b,
9768 SLTIU32 = 0x2c,
9769 BNE32 = 0x2d,
9770 SDC132 = 0x2e,
9771 LDC132 = 0x2f,
9773 /* 0x30 and 0x31 are reserved */
9774 RES_30 = 0x30,
9775 RES_31 = 0x31,
9776 SWSP16 = 0x32,
9777 B16 = 0x33,
9778 ANDI32 = 0x34,
9779 J32 = 0x35,
9780 SD32 = 0x36,
9781 LD32 = 0x37,
9783 /* 0x38 and 0x39 are reserved */
9784 RES_38 = 0x38,
9785 RES_39 = 0x39,
9786 SW16 = 0x3a,
9787 LI16 = 0x3b,
9788 JALX32 = 0x3c,
9789 JAL32 = 0x3d,
9790 SW32 = 0x3e,
9791 LW32 = 0x3f
9794 /* POOL32A encoding of minor opcode field */
9796 enum {
9797 /* These opcodes are distinguished only by bits 9..6; those bits are
9798 * what are recorded below. */
9799 SLL32 = 0x0,
9800 SRL32 = 0x1,
9801 SRA = 0x2,
9802 ROTR = 0x3,
9804 SLLV = 0x0,
9805 SRLV = 0x1,
9806 SRAV = 0x2,
9807 ROTRV = 0x3,
9808 ADD = 0x4,
9809 ADDU32 = 0x5,
9810 SUB = 0x6,
9811 SUBU32 = 0x7,
9812 MUL = 0x8,
9813 AND = 0x9,
9814 OR32 = 0xa,
9815 NOR = 0xb,
9816 XOR32 = 0xc,
9817 SLT = 0xd,
9818 SLTU = 0xe,
9820 MOVN = 0x0,
9821 MOVZ = 0x1,
9822 LWXS = 0x4,
9824 /* The following can be distinguished by their lower 6 bits. */
9825 INS = 0x0c,
9826 EXT = 0x2c,
9827 POOL32AXF = 0x3c
9830 /* POOL32AXF encoding of minor opcode field extension */
9832 enum {
9833 /* bits 11..6 */
9834 TEQ = 0x00,
9835 TGE = 0x08,
9836 TGEU = 0x10,
9837 TLT = 0x20,
9838 TLTU = 0x28,
9839 TNE = 0x30,
9841 MFC0 = 0x03,
9842 MTC0 = 0x0b,
9844 /* bits 13..12 for 0x01 */
9845 MFHI_ACC = 0x0,
9846 MFLO_ACC = 0x1,
9847 MTHI_ACC = 0x2,
9848 MTLO_ACC = 0x3,
9850 /* bits 13..12 for 0x2a */
9851 MADD_ACC = 0x0,
9852 MADDU_ACC = 0x1,
9853 MSUB_ACC = 0x2,
9854 MSUBU_ACC = 0x3,
9856 /* bits 13..12 for 0x32 */
9857 MULT_ACC = 0x0,
9858 MULTU_ACC = 0x0,
9860 /* bits 15..12 for 0x2c */
9861 SEB = 0x2,
9862 SEH = 0x3,
9863 CLO = 0x4,
9864 CLZ = 0x5,
9865 RDHWR = 0x6,
9866 WSBH = 0x7,
9867 MULT = 0x8,
9868 MULTU = 0x9,
9869 DIV = 0xa,
9870 DIVU = 0xb,
9871 MADD = 0xc,
9872 MADDU = 0xd,
9873 MSUB = 0xe,
9874 MSUBU = 0xf,
9876 /* bits 15..12 for 0x34 */
9877 MFC2 = 0x4,
9878 MTC2 = 0x5,
9879 MFHC2 = 0x8,
9880 MTHC2 = 0x9,
9881 CFC2 = 0xc,
9882 CTC2 = 0xd,
9884 /* bits 15..12 for 0x3c */
9885 JALR = 0x0,
9886 JR = 0x0, /* alias */
9887 JALR_HB = 0x1,
9888 JALRS = 0x4,
9889 JALRS_HB = 0x5,
9891 /* bits 15..12 for 0x05 */
9892 RDPGPR = 0xe,
9893 WRPGPR = 0xf,
9895 /* bits 15..12 for 0x0d */
9896 TLBP = 0x0,
9897 TLBR = 0x1,
9898 TLBWI = 0x2,
9899 TLBWR = 0x3,
9900 WAIT = 0x9,
9901 IRET = 0xd,
9902 DERET = 0xe,
9903 ERET = 0xf,
9905 /* bits 15..12 for 0x15 */
9906 DMT = 0x0,
9907 DVPE = 0x1,
9908 EMT = 0x2,
9909 EVPE = 0x3,
9911 /* bits 15..12 for 0x1d */
9912 DI = 0x4,
9913 EI = 0x5,
9915 /* bits 15..12 for 0x2d */
9916 SYNC = 0x6,
9917 SYSCALL = 0x8,
9918 SDBBP = 0xd,
9920 /* bits 15..12 for 0x35 */
9921 MFHI32 = 0x0,
9922 MFLO32 = 0x1,
9923 MTHI32 = 0x2,
9924 MTLO32 = 0x3,
9927 /* POOL32B encoding of minor opcode field (bits 15..12) */
9929 enum {
9930 LWC2 = 0x0,
9931 LWP = 0x1,
9932 LDP = 0x4,
9933 LWM32 = 0x5,
9934 CACHE = 0x6,
9935 LDM = 0x7,
9936 SWC2 = 0x8,
9937 SWP = 0x9,
9938 SDP = 0xc,
9939 SWM32 = 0xd,
9940 SDM = 0xf
9943 /* POOL32C encoding of minor opcode field (bits 15..12) */
9945 enum {
9946 LWL = 0x0,
9947 SWL = 0x8,
9948 LWR = 0x1,
9949 SWR = 0x9,
9950 PREF = 0x2,
9951 /* 0xa is reserved */
9952 LL = 0x3,
9953 SC = 0xb,
9954 LDL = 0x4,
9955 SDL = 0xc,
9956 LDR = 0x5,
9957 SDR = 0xd,
9958 /* 0x6 is reserved */
9959 LWU = 0xe,
9960 LLD = 0x7,
9961 SCD = 0xf
9964 /* POOL32F encoding of minor opcode field (bits 5..0) */
9966 enum {
9967 /* These are the bit 7..6 values */
9968 ADD_FMT = 0x0,
9969 MOVN_FMT = 0x0,
9971 SUB_FMT = 0x1,
9972 MOVZ_FMT = 0x1,
9974 MUL_FMT = 0x2,
9976 DIV_FMT = 0x3,
9978 /* These are the bit 8..6 values */
9979 RSQRT2_FMT = 0x0,
9980 MOVF_FMT = 0x0,
9982 LWXC1 = 0x1,
9983 MOVT_FMT = 0x1,
9985 PLL_PS = 0x2,
9986 SWXC1 = 0x2,
9988 PLU_PS = 0x3,
9989 LDXC1 = 0x3,
9991 PUL_PS = 0x4,
9992 SDXC1 = 0x4,
9993 RECIP2_FMT = 0x4,
9995 PUU_PS = 0x5,
9996 LUXC1 = 0x5,
9998 CVT_PS_S = 0x6,
9999 SUXC1 = 0x6,
10000 ADDR_PS = 0x6,
10001 PREFX = 0x6,
10003 MULR_PS = 0x7,
10005 MADD_S = 0x01,
10006 MADD_D = 0x09,
10007 MADD_PS = 0x11,
10008 ALNV_PS = 0x19,
10009 MSUB_S = 0x21,
10010 MSUB_D = 0x29,
10011 MSUB_PS = 0x31,
10013 NMADD_S = 0x02,
10014 NMADD_D = 0x0a,
10015 NMADD_PS = 0x12,
10016 NMSUB_S = 0x22,
10017 NMSUB_D = 0x2a,
10018 NMSUB_PS = 0x32,
10020 POOL32FXF = 0x3b,
10022 CABS_COND_FMT = 0x1c, /* MIPS3D */
10023 C_COND_FMT = 0x3c
10026 /* POOL32Fxf encoding of minor opcode extension field */
10028 enum {
10029 CVT_L = 0x04,
10030 RSQRT_FMT = 0x08,
10031 FLOOR_L = 0x0c,
10032 CVT_PW_PS = 0x1c,
10033 CVT_W = 0x24,
10034 SQRT_FMT = 0x28,
10035 FLOOR_W = 0x2c,
10036 CVT_PS_PW = 0x3c,
10037 CFC1 = 0x40,
10038 RECIP_FMT = 0x48,
10039 CEIL_L = 0x4c,
10040 CTC1 = 0x60,
10041 CEIL_W = 0x6c,
10042 MFC1 = 0x80,
10043 CVT_S_PL = 0x84,
10044 TRUNC_L = 0x8c,
10045 MTC1 = 0xa0,
10046 CVT_S_PU = 0xa4,
10047 TRUNC_W = 0xac,
10048 MFHC1 = 0xc0,
10049 ROUND_L = 0xcc,
10050 MTHC1 = 0xe0,
10051 ROUND_W = 0xec,
10053 MOV_FMT = 0x01,
10054 MOVF = 0x05,
10055 ABS_FMT = 0x0d,
10056 RSQRT1_FMT = 0x1d,
10057 MOVT = 0x25,
10058 NEG_FMT = 0x2d,
10059 CVT_D = 0x4d,
10060 RECIP1_FMT = 0x5d,
10061 CVT_S = 0x6d
10064 /* POOL32I encoding of minor opcode field (bits 25..21) */
10066 enum {
10067 BLTZ = 0x00,
10068 BLTZAL = 0x01,
10069 BGEZ = 0x02,
10070 BGEZAL = 0x03,
10071 BLEZ = 0x04,
10072 BNEZC = 0x05,
10073 BGTZ = 0x06,
10074 BEQZC = 0x07,
10075 TLTI = 0x08,
10076 TGEI = 0x09,
10077 TLTIU = 0x0a,
10078 TGEIU = 0x0b,
10079 TNEI = 0x0c,
10080 LUI = 0x0d,
10081 TEQI = 0x0e,
10082 SYNCI = 0x10,
10083 BLTZALS = 0x11,
10084 BGEZALS = 0x13,
10085 BC2F = 0x14,
10086 BC2T = 0x15,
10087 BPOSGE64 = 0x1a,
10088 BPOSGE32 = 0x1b,
10089 /* These overlap and are distinguished by bit16 of the instruction */
10090 BC1F = 0x1c,
10091 BC1T = 0x1d,
10092 BC1ANY2F = 0x1c,
10093 BC1ANY2T = 0x1d,
10094 BC1ANY4F = 0x1e,
10095 BC1ANY4T = 0x1f
10098 /* POOL16A encoding of minor opcode field */
10100 enum {
10101 ADDU16 = 0x0,
10102 SUBU16 = 0x1
10105 /* POOL16B encoding of minor opcode field */
10107 enum {
10108 SLL16 = 0x0,
10109 SRL16 = 0x1
10112 /* POOL16C encoding of minor opcode field */
10114 enum {
10115 NOT16 = 0x00,
10116 XOR16 = 0x04,
10117 AND16 = 0x08,
10118 OR16 = 0x0c,
10119 LWM16 = 0x10,
10120 SWM16 = 0x14,
10121 JR16 = 0x18,
10122 JRC16 = 0x1a,
10123 JALR16 = 0x1c,
10124 JALR16S = 0x1e,
10125 MFHI16 = 0x20,
10126 MFLO16 = 0x24,
10127 BREAK16 = 0x28,
10128 SDBBP16 = 0x2c,
10129 JRADDIUSP = 0x30
10132 /* POOL16D encoding of minor opcode field */
10134 enum {
10135 ADDIUS5 = 0x0,
10136 ADDIUSP = 0x1
10139 /* POOL16E encoding of minor opcode field */
10141 enum {
10142 ADDIUR2 = 0x0,
10143 ADDIUR1SP = 0x1
10146 static int mmreg (int r)
10148 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10150 return map[r];
10153 /* Used for 16-bit store instructions. */
10154 static int mmreg2 (int r)
10156 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
10158 return map[r];
10161 #define uMIPS_RD(op) ((op >> 7) & 0x7)
10162 #define uMIPS_RS(op) ((op >> 4) & 0x7)
10163 #define uMIPS_RS2(op) uMIPS_RS(op)
10164 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
10165 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
10166 #define uMIPS_RS5(op) (op & 0x1f)
10168 /* Signed immediate */
10169 #define SIMM(op, start, width) \
10170 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
10171 << (32-width)) \
10172 >> (32-width))
10173 /* Zero-extended immediate */
10174 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
10176 static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
10178 int rd = mmreg(uMIPS_RD(ctx->opcode));
10180 gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
10183 static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
10185 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
10186 int rd = mmreg(uMIPS_RD(ctx->opcode));
10187 int rs = mmreg(uMIPS_RS(ctx->opcode));
10189 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
10192 static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
10194 int encoded = ZIMM(ctx->opcode, 1, 9);
10195 int decoded;
10197 if (encoded <= 1) {
10198 decoded = 256 + encoded;
10199 } else if (encoded <= 255) {
10200 decoded = encoded;
10201 } else if (encoded <= 509) {
10202 decoded = encoded - 512;
10203 } else {
10204 decoded = encoded - 768;
10207 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
10210 static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
10212 int imm = SIMM(ctx->opcode, 1, 4);
10213 int rd = (ctx->opcode >> 5) & 0x1f;
10215 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
10218 static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
10220 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
10221 31, 32, 63, 64, 255, 32768, 65535 };
10222 int rd = mmreg(uMIPS_RD(ctx->opcode));
10223 int rs = mmreg(uMIPS_RS(ctx->opcode));
10224 int encoded = ZIMM(ctx->opcode, 0, 4);
10226 gen_logic_imm(env, ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
10229 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
10230 int base, int16_t offset)
10232 const char *opn = "ldst_multiple";
10233 TCGv t0, t1;
10234 TCGv_i32 t2;
10236 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10237 generate_exception(ctx, EXCP_RI);
10238 return;
10241 t0 = tcg_temp_new();
10243 gen_base_offset_addr(ctx, t0, base, offset);
10245 t1 = tcg_const_tl(reglist);
10246 t2 = tcg_const_i32(ctx->mem_idx);
10248 save_cpu_state(ctx, 1);
10249 switch (opc) {
10250 case LWM32:
10251 gen_helper_lwm(cpu_env, t0, t1, t2);
10252 opn = "lwm";
10253 break;
10254 case SWM32:
10255 gen_helper_swm(cpu_env, t0, t1, t2);
10256 opn = "swm";
10257 break;
10258 #ifdef TARGET_MIPS64
10259 case LDM:
10260 gen_helper_ldm(cpu_env, t0, t1, t2);
10261 opn = "ldm";
10262 break;
10263 case SDM:
10264 gen_helper_sdm(cpu_env, t0, t1, t2);
10265 opn = "sdm";
10266 break;
10267 #endif
10269 (void)opn;
10270 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
10271 tcg_temp_free(t0);
10272 tcg_temp_free(t1);
10273 tcg_temp_free_i32(t2);
10277 static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
10279 int rd = mmreg((ctx->opcode >> 3) & 0x7);
10280 int rs = mmreg(ctx->opcode & 0x7);
10281 int opc;
10283 switch (((ctx->opcode) >> 4) & 0x3f) {
10284 case NOT16 + 0:
10285 case NOT16 + 1:
10286 case NOT16 + 2:
10287 case NOT16 + 3:
10288 gen_logic(env, ctx, OPC_NOR, rd, rs, 0);
10289 break;
10290 case XOR16 + 0:
10291 case XOR16 + 1:
10292 case XOR16 + 2:
10293 case XOR16 + 3:
10294 gen_logic(env, ctx, OPC_XOR, rd, rd, rs);
10295 break;
10296 case AND16 + 0:
10297 case AND16 + 1:
10298 case AND16 + 2:
10299 case AND16 + 3:
10300 gen_logic(env, ctx, OPC_AND, rd, rd, rs);
10301 break;
10302 case OR16 + 0:
10303 case OR16 + 1:
10304 case OR16 + 2:
10305 case OR16 + 3:
10306 gen_logic(env, ctx, OPC_OR, rd, rd, rs);
10307 break;
10308 case LWM16 + 0:
10309 case LWM16 + 1:
10310 case LWM16 + 2:
10311 case LWM16 + 3:
10313 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10314 int offset = ZIMM(ctx->opcode, 0, 4);
10316 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
10317 29, offset << 2);
10319 break;
10320 case SWM16 + 0:
10321 case SWM16 + 1:
10322 case SWM16 + 2:
10323 case SWM16 + 3:
10325 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10326 int offset = ZIMM(ctx->opcode, 0, 4);
10328 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
10329 29, offset << 2);
10331 break;
10332 case JR16 + 0:
10333 case JR16 + 1:
10335 int reg = ctx->opcode & 0x1f;
10337 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10339 *is_branch = 1;
10340 break;
10341 case JRC16 + 0:
10342 case JRC16 + 1:
10344 int reg = ctx->opcode & 0x1f;
10346 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10347 /* Let normal delay slot handling in our caller take us
10348 to the branch target. */
10350 break;
10351 case JALR16 + 0:
10352 case JALR16 + 1:
10353 opc = OPC_JALR;
10354 goto do_jalr;
10355 case JALR16S + 0:
10356 case JALR16S + 1:
10357 opc = OPC_JALRS;
10358 do_jalr:
10360 int reg = ctx->opcode & 0x1f;
10362 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
10364 *is_branch = 1;
10365 break;
10366 case MFHI16 + 0:
10367 case MFHI16 + 1:
10368 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
10369 break;
10370 case MFLO16 + 0:
10371 case MFLO16 + 1:
10372 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
10373 break;
10374 case BREAK16:
10375 generate_exception(ctx, EXCP_BREAK);
10376 break;
10377 case SDBBP16:
10378 /* XXX: not clear which exception should be raised
10379 * when in debug mode...
10381 check_insn(env, ctx, ISA_MIPS32);
10382 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10383 generate_exception(ctx, EXCP_DBp);
10384 } else {
10385 generate_exception(ctx, EXCP_DBp);
10387 break;
10388 case JRADDIUSP + 0:
10389 case JRADDIUSP + 1:
10391 int imm = ZIMM(ctx->opcode, 0, 5);
10393 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
10394 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
10395 /* Let normal delay slot handling in our caller take us
10396 to the branch target. */
10398 break;
10399 default:
10400 generate_exception(ctx, EXCP_RI);
10401 break;
10405 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10407 TCGv t0 = tcg_temp_new();
10408 TCGv t1 = tcg_temp_new();
10410 gen_load_gpr(t0, base);
10412 if (index != 0) {
10413 gen_load_gpr(t1, index);
10414 tcg_gen_shli_tl(t1, t1, 2);
10415 gen_op_addr_add(ctx, t0, t1, t0);
10418 save_cpu_state(ctx, 0);
10419 op_ld_lw(t1, t0, ctx);
10420 gen_store_gpr(t1, rd);
10422 tcg_temp_free(t0);
10423 tcg_temp_free(t1);
10426 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
10427 int base, int16_t offset)
10429 const char *opn = "ldst_pair";
10430 TCGv t0, t1;
10432 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
10433 generate_exception(ctx, EXCP_RI);
10434 return;
10437 t0 = tcg_temp_new();
10438 t1 = tcg_temp_new();
10440 gen_base_offset_addr(ctx, t0, base, offset);
10442 switch (opc) {
10443 case LWP:
10444 if (rd == base) {
10445 generate_exception(ctx, EXCP_RI);
10446 return;
10448 save_cpu_state(ctx, 0);
10449 op_ld_lw(t1, t0, ctx);
10450 gen_store_gpr(t1, rd);
10451 tcg_gen_movi_tl(t1, 4);
10452 gen_op_addr_add(ctx, t0, t0, t1);
10453 op_ld_lw(t1, t0, ctx);
10454 gen_store_gpr(t1, rd+1);
10455 opn = "lwp";
10456 break;
10457 case SWP:
10458 save_cpu_state(ctx, 0);
10459 gen_load_gpr(t1, rd);
10460 op_st_sw(t1, t0, ctx);
10461 tcg_gen_movi_tl(t1, 4);
10462 gen_op_addr_add(ctx, t0, t0, t1);
10463 gen_load_gpr(t1, rd+1);
10464 op_st_sw(t1, t0, ctx);
10465 opn = "swp";
10466 break;
10467 #ifdef TARGET_MIPS64
10468 case LDP:
10469 if (rd == base) {
10470 generate_exception(ctx, EXCP_RI);
10471 return;
10473 save_cpu_state(ctx, 0);
10474 op_ld_ld(t1, t0, ctx);
10475 gen_store_gpr(t1, rd);
10476 tcg_gen_movi_tl(t1, 8);
10477 gen_op_addr_add(ctx, t0, t0, t1);
10478 op_ld_ld(t1, t0, ctx);
10479 gen_store_gpr(t1, rd+1);
10480 opn = "ldp";
10481 break;
10482 case SDP:
10483 save_cpu_state(ctx, 0);
10484 gen_load_gpr(t1, rd);
10485 op_st_sd(t1, t0, ctx);
10486 tcg_gen_movi_tl(t1, 8);
10487 gen_op_addr_add(ctx, t0, t0, t1);
10488 gen_load_gpr(t1, rd+1);
10489 op_st_sd(t1, t0, ctx);
10490 opn = "sdp";
10491 break;
10492 #endif
10494 (void)opn; /* avoid a compiler warning */
10495 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10496 tcg_temp_free(t0);
10497 tcg_temp_free(t1);
10500 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
10501 int *is_branch)
10503 int extension = (ctx->opcode >> 6) & 0x3f;
10504 int minor = (ctx->opcode >> 12) & 0xf;
10505 uint32_t mips32_op;
10507 switch (extension) {
10508 case TEQ:
10509 mips32_op = OPC_TEQ;
10510 goto do_trap;
10511 case TGE:
10512 mips32_op = OPC_TGE;
10513 goto do_trap;
10514 case TGEU:
10515 mips32_op = OPC_TGEU;
10516 goto do_trap;
10517 case TLT:
10518 mips32_op = OPC_TLT;
10519 goto do_trap;
10520 case TLTU:
10521 mips32_op = OPC_TLTU;
10522 goto do_trap;
10523 case TNE:
10524 mips32_op = OPC_TNE;
10525 do_trap:
10526 gen_trap(ctx, mips32_op, rs, rt, -1);
10527 break;
10528 #ifndef CONFIG_USER_ONLY
10529 case MFC0:
10530 case MFC0 + 32:
10531 check_cp0_enabled(ctx);
10532 if (rt == 0) {
10533 /* Treat as NOP. */
10534 break;
10536 gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10537 break;
10538 case MTC0:
10539 case MTC0 + 32:
10540 check_cp0_enabled(ctx);
10542 TCGv t0 = tcg_temp_new();
10544 gen_load_gpr(t0, rt);
10545 gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10546 tcg_temp_free(t0);
10548 break;
10549 #endif
10550 case 0x2c:
10551 switch (minor) {
10552 case SEB:
10553 gen_bshfl(ctx, OPC_SEB, rs, rt);
10554 break;
10555 case SEH:
10556 gen_bshfl(ctx, OPC_SEH, rs, rt);
10557 break;
10558 case CLO:
10559 mips32_op = OPC_CLO;
10560 goto do_cl;
10561 case CLZ:
10562 mips32_op = OPC_CLZ;
10563 do_cl:
10564 check_insn(env, ctx, ISA_MIPS32);
10565 gen_cl(ctx, mips32_op, rt, rs);
10566 break;
10567 case RDHWR:
10568 gen_rdhwr(env, ctx, rt, rs);
10569 break;
10570 case WSBH:
10571 gen_bshfl(ctx, OPC_WSBH, rs, rt);
10572 break;
10573 case MULT:
10574 mips32_op = OPC_MULT;
10575 goto do_muldiv;
10576 case MULTU:
10577 mips32_op = OPC_MULTU;
10578 goto do_muldiv;
10579 case DIV:
10580 mips32_op = OPC_DIV;
10581 goto do_muldiv;
10582 case DIVU:
10583 mips32_op = OPC_DIVU;
10584 goto do_muldiv;
10585 case MADD:
10586 mips32_op = OPC_MADD;
10587 goto do_muldiv;
10588 case MADDU:
10589 mips32_op = OPC_MADDU;
10590 goto do_muldiv;
10591 case MSUB:
10592 mips32_op = OPC_MSUB;
10593 goto do_muldiv;
10594 case MSUBU:
10595 mips32_op = OPC_MSUBU;
10596 do_muldiv:
10597 check_insn(env, ctx, ISA_MIPS32);
10598 gen_muldiv(ctx, mips32_op, rs, rt);
10599 break;
10600 default:
10601 goto pool32axf_invalid;
10603 break;
10604 case 0x34:
10605 switch (minor) {
10606 case MFC2:
10607 case MTC2:
10608 case MFHC2:
10609 case MTHC2:
10610 case CFC2:
10611 case CTC2:
10612 generate_exception_err(ctx, EXCP_CpU, 2);
10613 break;
10614 default:
10615 goto pool32axf_invalid;
10617 break;
10618 case 0x3c:
10619 switch (minor) {
10620 case JALR:
10621 case JALR_HB:
10622 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10623 *is_branch = 1;
10624 break;
10625 case JALRS:
10626 case JALRS_HB:
10627 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10628 *is_branch = 1;
10629 break;
10630 default:
10631 goto pool32axf_invalid;
10633 break;
10634 case 0x05:
10635 switch (minor) {
10636 case RDPGPR:
10637 check_cp0_enabled(ctx);
10638 check_insn(env, ctx, ISA_MIPS32R2);
10639 gen_load_srsgpr(rt, rs);
10640 break;
10641 case WRPGPR:
10642 check_cp0_enabled(ctx);
10643 check_insn(env, ctx, ISA_MIPS32R2);
10644 gen_store_srsgpr(rt, rs);
10645 break;
10646 default:
10647 goto pool32axf_invalid;
10649 break;
10650 #ifndef CONFIG_USER_ONLY
10651 case 0x0d:
10652 switch (minor) {
10653 case TLBP:
10654 mips32_op = OPC_TLBP;
10655 goto do_cp0;
10656 case TLBR:
10657 mips32_op = OPC_TLBR;
10658 goto do_cp0;
10659 case TLBWI:
10660 mips32_op = OPC_TLBWI;
10661 goto do_cp0;
10662 case TLBWR:
10663 mips32_op = OPC_TLBWR;
10664 goto do_cp0;
10665 case WAIT:
10666 mips32_op = OPC_WAIT;
10667 goto do_cp0;
10668 case DERET:
10669 mips32_op = OPC_DERET;
10670 goto do_cp0;
10671 case ERET:
10672 mips32_op = OPC_ERET;
10673 do_cp0:
10674 gen_cp0(env, ctx, mips32_op, rt, rs);
10675 break;
10676 default:
10677 goto pool32axf_invalid;
10679 break;
10680 case 0x1d:
10681 switch (minor) {
10682 case DI:
10683 check_cp0_enabled(ctx);
10685 TCGv t0 = tcg_temp_new();
10687 save_cpu_state(ctx, 1);
10688 gen_helper_di(t0, cpu_env);
10689 gen_store_gpr(t0, rs);
10690 /* Stop translation as we may have switched the execution mode */
10691 ctx->bstate = BS_STOP;
10692 tcg_temp_free(t0);
10694 break;
10695 case EI:
10696 check_cp0_enabled(ctx);
10698 TCGv t0 = tcg_temp_new();
10700 save_cpu_state(ctx, 1);
10701 gen_helper_ei(t0, cpu_env);
10702 gen_store_gpr(t0, rs);
10703 /* Stop translation as we may have switched the execution mode */
10704 ctx->bstate = BS_STOP;
10705 tcg_temp_free(t0);
10707 break;
10708 default:
10709 goto pool32axf_invalid;
10711 break;
10712 #endif
10713 case 0x2d:
10714 switch (minor) {
10715 case SYNC:
10716 /* NOP */
10717 break;
10718 case SYSCALL:
10719 generate_exception(ctx, EXCP_SYSCALL);
10720 ctx->bstate = BS_STOP;
10721 break;
10722 case SDBBP:
10723 check_insn(env, ctx, ISA_MIPS32);
10724 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10725 generate_exception(ctx, EXCP_DBp);
10726 } else {
10727 generate_exception(ctx, EXCP_DBp);
10729 break;
10730 default:
10731 goto pool32axf_invalid;
10733 break;
10734 case 0x35:
10735 switch (minor) {
10736 case MFHI32:
10737 gen_HILO(ctx, OPC_MFHI, rs);
10738 break;
10739 case MFLO32:
10740 gen_HILO(ctx, OPC_MFLO, rs);
10741 break;
10742 case MTHI32:
10743 gen_HILO(ctx, OPC_MTHI, rs);
10744 break;
10745 case MTLO32:
10746 gen_HILO(ctx, OPC_MTLO, rs);
10747 break;
10748 default:
10749 goto pool32axf_invalid;
10751 break;
10752 default:
10753 pool32axf_invalid:
10754 MIPS_INVAL("pool32axf");
10755 generate_exception(ctx, EXCP_RI);
10756 break;
10760 /* Values for microMIPS fmt field. Variable-width, depending on which
10761 formats the instruction supports. */
10763 enum {
10764 FMT_SD_S = 0,
10765 FMT_SD_D = 1,
10767 FMT_SDPS_S = 0,
10768 FMT_SDPS_D = 1,
10769 FMT_SDPS_PS = 2,
10771 FMT_SWL_S = 0,
10772 FMT_SWL_W = 1,
10773 FMT_SWL_L = 2,
10775 FMT_DWL_D = 0,
10776 FMT_DWL_W = 1,
10777 FMT_DWL_L = 2
10780 static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
10782 int extension = (ctx->opcode >> 6) & 0x3ff;
10783 uint32_t mips32_op;
10785 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10786 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10787 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10789 switch (extension) {
10790 case FLOAT_1BIT_FMT(CFC1, 0):
10791 mips32_op = OPC_CFC1;
10792 goto do_cp1;
10793 case FLOAT_1BIT_FMT(CTC1, 0):
10794 mips32_op = OPC_CTC1;
10795 goto do_cp1;
10796 case FLOAT_1BIT_FMT(MFC1, 0):
10797 mips32_op = OPC_MFC1;
10798 goto do_cp1;
10799 case FLOAT_1BIT_FMT(MTC1, 0):
10800 mips32_op = OPC_MTC1;
10801 goto do_cp1;
10802 case FLOAT_1BIT_FMT(MFHC1, 0):
10803 mips32_op = OPC_MFHC1;
10804 goto do_cp1;
10805 case FLOAT_1BIT_FMT(MTHC1, 0):
10806 mips32_op = OPC_MTHC1;
10807 do_cp1:
10808 gen_cp1(ctx, mips32_op, rt, rs);
10809 break;
10811 /* Reciprocal square root */
10812 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10813 mips32_op = OPC_RSQRT_S;
10814 goto do_unaryfp;
10815 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10816 mips32_op = OPC_RSQRT_D;
10817 goto do_unaryfp;
10819 /* Square root */
10820 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10821 mips32_op = OPC_SQRT_S;
10822 goto do_unaryfp;
10823 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10824 mips32_op = OPC_SQRT_D;
10825 goto do_unaryfp;
10827 /* Reciprocal */
10828 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10829 mips32_op = OPC_RECIP_S;
10830 goto do_unaryfp;
10831 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10832 mips32_op = OPC_RECIP_D;
10833 goto do_unaryfp;
10835 /* Floor */
10836 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10837 mips32_op = OPC_FLOOR_L_S;
10838 goto do_unaryfp;
10839 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10840 mips32_op = OPC_FLOOR_L_D;
10841 goto do_unaryfp;
10842 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10843 mips32_op = OPC_FLOOR_W_S;
10844 goto do_unaryfp;
10845 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10846 mips32_op = OPC_FLOOR_W_D;
10847 goto do_unaryfp;
10849 /* Ceiling */
10850 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10851 mips32_op = OPC_CEIL_L_S;
10852 goto do_unaryfp;
10853 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10854 mips32_op = OPC_CEIL_L_D;
10855 goto do_unaryfp;
10856 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10857 mips32_op = OPC_CEIL_W_S;
10858 goto do_unaryfp;
10859 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10860 mips32_op = OPC_CEIL_W_D;
10861 goto do_unaryfp;
10863 /* Truncation */
10864 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10865 mips32_op = OPC_TRUNC_L_S;
10866 goto do_unaryfp;
10867 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10868 mips32_op = OPC_TRUNC_L_D;
10869 goto do_unaryfp;
10870 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10871 mips32_op = OPC_TRUNC_W_S;
10872 goto do_unaryfp;
10873 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10874 mips32_op = OPC_TRUNC_W_D;
10875 goto do_unaryfp;
10877 /* Round */
10878 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10879 mips32_op = OPC_ROUND_L_S;
10880 goto do_unaryfp;
10881 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10882 mips32_op = OPC_ROUND_L_D;
10883 goto do_unaryfp;
10884 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10885 mips32_op = OPC_ROUND_W_S;
10886 goto do_unaryfp;
10887 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10888 mips32_op = OPC_ROUND_W_D;
10889 goto do_unaryfp;
10891 /* Integer to floating-point conversion */
10892 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10893 mips32_op = OPC_CVT_L_S;
10894 goto do_unaryfp;
10895 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10896 mips32_op = OPC_CVT_L_D;
10897 goto do_unaryfp;
10898 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10899 mips32_op = OPC_CVT_W_S;
10900 goto do_unaryfp;
10901 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10902 mips32_op = OPC_CVT_W_D;
10903 goto do_unaryfp;
10905 /* Paired-foo conversions */
10906 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10907 mips32_op = OPC_CVT_S_PL;
10908 goto do_unaryfp;
10909 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10910 mips32_op = OPC_CVT_S_PU;
10911 goto do_unaryfp;
10912 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10913 mips32_op = OPC_CVT_PW_PS;
10914 goto do_unaryfp;
10915 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10916 mips32_op = OPC_CVT_PS_PW;
10917 goto do_unaryfp;
10919 /* Floating-point moves */
10920 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10921 mips32_op = OPC_MOV_S;
10922 goto do_unaryfp;
10923 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10924 mips32_op = OPC_MOV_D;
10925 goto do_unaryfp;
10926 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10927 mips32_op = OPC_MOV_PS;
10928 goto do_unaryfp;
10930 /* Absolute value */
10931 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10932 mips32_op = OPC_ABS_S;
10933 goto do_unaryfp;
10934 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10935 mips32_op = OPC_ABS_D;
10936 goto do_unaryfp;
10937 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10938 mips32_op = OPC_ABS_PS;
10939 goto do_unaryfp;
10941 /* Negation */
10942 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10943 mips32_op = OPC_NEG_S;
10944 goto do_unaryfp;
10945 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10946 mips32_op = OPC_NEG_D;
10947 goto do_unaryfp;
10948 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10949 mips32_op = OPC_NEG_PS;
10950 goto do_unaryfp;
10952 /* Reciprocal square root step */
10953 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10954 mips32_op = OPC_RSQRT1_S;
10955 goto do_unaryfp;
10956 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10957 mips32_op = OPC_RSQRT1_D;
10958 goto do_unaryfp;
10959 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10960 mips32_op = OPC_RSQRT1_PS;
10961 goto do_unaryfp;
10963 /* Reciprocal step */
10964 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10965 mips32_op = OPC_RECIP1_S;
10966 goto do_unaryfp;
10967 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10968 mips32_op = OPC_RECIP1_S;
10969 goto do_unaryfp;
10970 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10971 mips32_op = OPC_RECIP1_PS;
10972 goto do_unaryfp;
10974 /* Conversions from double */
10975 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10976 mips32_op = OPC_CVT_D_S;
10977 goto do_unaryfp;
10978 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10979 mips32_op = OPC_CVT_D_W;
10980 goto do_unaryfp;
10981 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10982 mips32_op = OPC_CVT_D_L;
10983 goto do_unaryfp;
10985 /* Conversions from single */
10986 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10987 mips32_op = OPC_CVT_S_D;
10988 goto do_unaryfp;
10989 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10990 mips32_op = OPC_CVT_S_W;
10991 goto do_unaryfp;
10992 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10993 mips32_op = OPC_CVT_S_L;
10994 do_unaryfp:
10995 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10996 break;
10998 /* Conditional moves on floating-point codes */
10999 case COND_FLOAT_MOV(MOVT, 0):
11000 case COND_FLOAT_MOV(MOVT, 1):
11001 case COND_FLOAT_MOV(MOVT, 2):
11002 case COND_FLOAT_MOV(MOVT, 3):
11003 case COND_FLOAT_MOV(MOVT, 4):
11004 case COND_FLOAT_MOV(MOVT, 5):
11005 case COND_FLOAT_MOV(MOVT, 6):
11006 case COND_FLOAT_MOV(MOVT, 7):
11007 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
11008 break;
11009 case COND_FLOAT_MOV(MOVF, 0):
11010 case COND_FLOAT_MOV(MOVF, 1):
11011 case COND_FLOAT_MOV(MOVF, 2):
11012 case COND_FLOAT_MOV(MOVF, 3):
11013 case COND_FLOAT_MOV(MOVF, 4):
11014 case COND_FLOAT_MOV(MOVF, 5):
11015 case COND_FLOAT_MOV(MOVF, 6):
11016 case COND_FLOAT_MOV(MOVF, 7):
11017 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
11018 break;
11019 default:
11020 MIPS_INVAL("pool32fxf");
11021 generate_exception(ctx, EXCP_RI);
11022 break;
11026 static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
11027 uint16_t insn_hw1, int *is_branch)
11029 int32_t offset;
11030 uint16_t insn;
11031 int rt, rs, rd, rr;
11032 int16_t imm;
11033 uint32_t op, minor, mips32_op;
11034 uint32_t cond, fmt, cc;
11036 insn = cpu_lduw_code(env, ctx->pc + 2);
11037 ctx->opcode = (ctx->opcode << 16) | insn;
11039 rt = (ctx->opcode >> 21) & 0x1f;
11040 rs = (ctx->opcode >> 16) & 0x1f;
11041 rd = (ctx->opcode >> 11) & 0x1f;
11042 rr = (ctx->opcode >> 6) & 0x1f;
11043 imm = (int16_t) ctx->opcode;
11045 op = (ctx->opcode >> 26) & 0x3f;
11046 switch (op) {
11047 case POOL32A:
11048 minor = ctx->opcode & 0x3f;
11049 switch (minor) {
11050 case 0x00:
11051 minor = (ctx->opcode >> 6) & 0xf;
11052 switch (minor) {
11053 case SLL32:
11054 mips32_op = OPC_SLL;
11055 goto do_shifti;
11056 case SRA:
11057 mips32_op = OPC_SRA;
11058 goto do_shifti;
11059 case SRL32:
11060 mips32_op = OPC_SRL;
11061 goto do_shifti;
11062 case ROTR:
11063 mips32_op = OPC_ROTR;
11064 do_shifti:
11065 gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
11066 break;
11067 default:
11068 goto pool32a_invalid;
11070 break;
11071 case 0x10:
11072 minor = (ctx->opcode >> 6) & 0xf;
11073 switch (minor) {
11074 /* Arithmetic */
11075 case ADD:
11076 mips32_op = OPC_ADD;
11077 goto do_arith;
11078 case ADDU32:
11079 mips32_op = OPC_ADDU;
11080 goto do_arith;
11081 case SUB:
11082 mips32_op = OPC_SUB;
11083 goto do_arith;
11084 case SUBU32:
11085 mips32_op = OPC_SUBU;
11086 goto do_arith;
11087 case MUL:
11088 mips32_op = OPC_MUL;
11089 do_arith:
11090 gen_arith(env, ctx, mips32_op, rd, rs, rt);
11091 break;
11092 /* Shifts */
11093 case SLLV:
11094 mips32_op = OPC_SLLV;
11095 goto do_shift;
11096 case SRLV:
11097 mips32_op = OPC_SRLV;
11098 goto do_shift;
11099 case SRAV:
11100 mips32_op = OPC_SRAV;
11101 goto do_shift;
11102 case ROTRV:
11103 mips32_op = OPC_ROTRV;
11104 do_shift:
11105 gen_shift(env, ctx, mips32_op, rd, rs, rt);
11106 break;
11107 /* Logical operations */
11108 case AND:
11109 mips32_op = OPC_AND;
11110 goto do_logic;
11111 case OR32:
11112 mips32_op = OPC_OR;
11113 goto do_logic;
11114 case NOR:
11115 mips32_op = OPC_NOR;
11116 goto do_logic;
11117 case XOR32:
11118 mips32_op = OPC_XOR;
11119 do_logic:
11120 gen_logic(env, ctx, mips32_op, rd, rs, rt);
11121 break;
11122 /* Set less than */
11123 case SLT:
11124 mips32_op = OPC_SLT;
11125 goto do_slt;
11126 case SLTU:
11127 mips32_op = OPC_SLTU;
11128 do_slt:
11129 gen_slt(env, ctx, mips32_op, rd, rs, rt);
11130 break;
11131 default:
11132 goto pool32a_invalid;
11134 break;
11135 case 0x18:
11136 minor = (ctx->opcode >> 6) & 0xf;
11137 switch (minor) {
11138 /* Conditional moves */
11139 case MOVN:
11140 mips32_op = OPC_MOVN;
11141 goto do_cmov;
11142 case MOVZ:
11143 mips32_op = OPC_MOVZ;
11144 do_cmov:
11145 gen_cond_move(env, ctx, mips32_op, rd, rs, rt);
11146 break;
11147 case LWXS:
11148 gen_ldxs(ctx, rs, rt, rd);
11149 break;
11150 default:
11151 goto pool32a_invalid;
11153 break;
11154 case INS:
11155 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
11156 return;
11157 case EXT:
11158 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
11159 return;
11160 case POOL32AXF:
11161 gen_pool32axf(env, ctx, rt, rs, is_branch);
11162 break;
11163 case 0x07:
11164 generate_exception(ctx, EXCP_BREAK);
11165 break;
11166 default:
11167 pool32a_invalid:
11168 MIPS_INVAL("pool32a");
11169 generate_exception(ctx, EXCP_RI);
11170 break;
11172 break;
11173 case POOL32B:
11174 minor = (ctx->opcode >> 12) & 0xf;
11175 switch (minor) {
11176 case CACHE:
11177 check_cp0_enabled(ctx);
11178 /* Treat as no-op. */
11179 break;
11180 case LWC2:
11181 case SWC2:
11182 /* COP2: Not implemented. */
11183 generate_exception_err(ctx, EXCP_CpU, 2);
11184 break;
11185 case LWP:
11186 case SWP:
11187 #ifdef TARGET_MIPS64
11188 case LDP:
11189 case SDP:
11190 #endif
11191 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11192 break;
11193 case LWM32:
11194 case SWM32:
11195 #ifdef TARGET_MIPS64
11196 case LDM:
11197 case SDM:
11198 #endif
11199 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11200 break;
11201 default:
11202 MIPS_INVAL("pool32b");
11203 generate_exception(ctx, EXCP_RI);
11204 break;
11206 break;
11207 case POOL32F:
11208 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11209 minor = ctx->opcode & 0x3f;
11210 check_cp1_enabled(ctx);
11211 switch (minor) {
11212 case ALNV_PS:
11213 mips32_op = OPC_ALNV_PS;
11214 goto do_madd;
11215 case MADD_S:
11216 mips32_op = OPC_MADD_S;
11217 goto do_madd;
11218 case MADD_D:
11219 mips32_op = OPC_MADD_D;
11220 goto do_madd;
11221 case MADD_PS:
11222 mips32_op = OPC_MADD_PS;
11223 goto do_madd;
11224 case MSUB_S:
11225 mips32_op = OPC_MSUB_S;
11226 goto do_madd;
11227 case MSUB_D:
11228 mips32_op = OPC_MSUB_D;
11229 goto do_madd;
11230 case MSUB_PS:
11231 mips32_op = OPC_MSUB_PS;
11232 goto do_madd;
11233 case NMADD_S:
11234 mips32_op = OPC_NMADD_S;
11235 goto do_madd;
11236 case NMADD_D:
11237 mips32_op = OPC_NMADD_D;
11238 goto do_madd;
11239 case NMADD_PS:
11240 mips32_op = OPC_NMADD_PS;
11241 goto do_madd;
11242 case NMSUB_S:
11243 mips32_op = OPC_NMSUB_S;
11244 goto do_madd;
11245 case NMSUB_D:
11246 mips32_op = OPC_NMSUB_D;
11247 goto do_madd;
11248 case NMSUB_PS:
11249 mips32_op = OPC_NMSUB_PS;
11250 do_madd:
11251 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
11252 break;
11253 case CABS_COND_FMT:
11254 cond = (ctx->opcode >> 6) & 0xf;
11255 cc = (ctx->opcode >> 13) & 0x7;
11256 fmt = (ctx->opcode >> 10) & 0x3;
11257 switch (fmt) {
11258 case 0x0:
11259 gen_cmpabs_s(ctx, cond, rt, rs, cc);
11260 break;
11261 case 0x1:
11262 gen_cmpabs_d(ctx, cond, rt, rs, cc);
11263 break;
11264 case 0x2:
11265 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
11266 break;
11267 default:
11268 goto pool32f_invalid;
11270 break;
11271 case C_COND_FMT:
11272 cond = (ctx->opcode >> 6) & 0xf;
11273 cc = (ctx->opcode >> 13) & 0x7;
11274 fmt = (ctx->opcode >> 10) & 0x3;
11275 switch (fmt) {
11276 case 0x0:
11277 gen_cmp_s(ctx, cond, rt, rs, cc);
11278 break;
11279 case 0x1:
11280 gen_cmp_d(ctx, cond, rt, rs, cc);
11281 break;
11282 case 0x2:
11283 gen_cmp_ps(ctx, cond, rt, rs, cc);
11284 break;
11285 default:
11286 goto pool32f_invalid;
11288 break;
11289 case POOL32FXF:
11290 gen_pool32fxf(env, ctx, rt, rs);
11291 break;
11292 case 0x00:
11293 /* PLL foo */
11294 switch ((ctx->opcode >> 6) & 0x7) {
11295 case PLL_PS:
11296 mips32_op = OPC_PLL_PS;
11297 goto do_ps;
11298 case PLU_PS:
11299 mips32_op = OPC_PLU_PS;
11300 goto do_ps;
11301 case PUL_PS:
11302 mips32_op = OPC_PUL_PS;
11303 goto do_ps;
11304 case PUU_PS:
11305 mips32_op = OPC_PUU_PS;
11306 goto do_ps;
11307 case CVT_PS_S:
11308 mips32_op = OPC_CVT_PS_S;
11309 do_ps:
11310 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11311 break;
11312 default:
11313 goto pool32f_invalid;
11315 break;
11316 case 0x08:
11317 /* [LS][WDU]XC1 */
11318 switch ((ctx->opcode >> 6) & 0x7) {
11319 case LWXC1:
11320 mips32_op = OPC_LWXC1;
11321 goto do_ldst_cp1;
11322 case SWXC1:
11323 mips32_op = OPC_SWXC1;
11324 goto do_ldst_cp1;
11325 case LDXC1:
11326 mips32_op = OPC_LDXC1;
11327 goto do_ldst_cp1;
11328 case SDXC1:
11329 mips32_op = OPC_SDXC1;
11330 goto do_ldst_cp1;
11331 case LUXC1:
11332 mips32_op = OPC_LUXC1;
11333 goto do_ldst_cp1;
11334 case SUXC1:
11335 mips32_op = OPC_SUXC1;
11336 do_ldst_cp1:
11337 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
11338 break;
11339 default:
11340 goto pool32f_invalid;
11342 break;
11343 case 0x18:
11344 /* 3D insns */
11345 fmt = (ctx->opcode >> 9) & 0x3;
11346 switch ((ctx->opcode >> 6) & 0x7) {
11347 case RSQRT2_FMT:
11348 switch (fmt) {
11349 case FMT_SDPS_S:
11350 mips32_op = OPC_RSQRT2_S;
11351 goto do_3d;
11352 case FMT_SDPS_D:
11353 mips32_op = OPC_RSQRT2_D;
11354 goto do_3d;
11355 case FMT_SDPS_PS:
11356 mips32_op = OPC_RSQRT2_PS;
11357 goto do_3d;
11358 default:
11359 goto pool32f_invalid;
11361 break;
11362 case RECIP2_FMT:
11363 switch (fmt) {
11364 case FMT_SDPS_S:
11365 mips32_op = OPC_RECIP2_S;
11366 goto do_3d;
11367 case FMT_SDPS_D:
11368 mips32_op = OPC_RECIP2_D;
11369 goto do_3d;
11370 case FMT_SDPS_PS:
11371 mips32_op = OPC_RECIP2_PS;
11372 goto do_3d;
11373 default:
11374 goto pool32f_invalid;
11376 break;
11377 case ADDR_PS:
11378 mips32_op = OPC_ADDR_PS;
11379 goto do_3d;
11380 case MULR_PS:
11381 mips32_op = OPC_MULR_PS;
11382 do_3d:
11383 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11384 break;
11385 default:
11386 goto pool32f_invalid;
11388 break;
11389 case 0x20:
11390 /* MOV[FT].fmt and PREFX */
11391 cc = (ctx->opcode >> 13) & 0x7;
11392 fmt = (ctx->opcode >> 9) & 0x3;
11393 switch ((ctx->opcode >> 6) & 0x7) {
11394 case MOVF_FMT:
11395 switch (fmt) {
11396 case FMT_SDPS_S:
11397 gen_movcf_s(rs, rt, cc, 0);
11398 break;
11399 case FMT_SDPS_D:
11400 gen_movcf_d(ctx, rs, rt, cc, 0);
11401 break;
11402 case FMT_SDPS_PS:
11403 gen_movcf_ps(rs, rt, cc, 0);
11404 break;
11405 default:
11406 goto pool32f_invalid;
11408 break;
11409 case MOVT_FMT:
11410 switch (fmt) {
11411 case FMT_SDPS_S:
11412 gen_movcf_s(rs, rt, cc, 1);
11413 break;
11414 case FMT_SDPS_D:
11415 gen_movcf_d(ctx, rs, rt, cc, 1);
11416 break;
11417 case FMT_SDPS_PS:
11418 gen_movcf_ps(rs, rt, cc, 1);
11419 break;
11420 default:
11421 goto pool32f_invalid;
11423 break;
11424 case PREFX:
11425 break;
11426 default:
11427 goto pool32f_invalid;
11429 break;
11430 #define FINSN_3ARG_SDPS(prfx) \
11431 switch ((ctx->opcode >> 8) & 0x3) { \
11432 case FMT_SDPS_S: \
11433 mips32_op = OPC_##prfx##_S; \
11434 goto do_fpop; \
11435 case FMT_SDPS_D: \
11436 mips32_op = OPC_##prfx##_D; \
11437 goto do_fpop; \
11438 case FMT_SDPS_PS: \
11439 mips32_op = OPC_##prfx##_PS; \
11440 goto do_fpop; \
11441 default: \
11442 goto pool32f_invalid; \
11444 case 0x30:
11445 /* regular FP ops */
11446 switch ((ctx->opcode >> 6) & 0x3) {
11447 case ADD_FMT:
11448 FINSN_3ARG_SDPS(ADD);
11449 break;
11450 case SUB_FMT:
11451 FINSN_3ARG_SDPS(SUB);
11452 break;
11453 case MUL_FMT:
11454 FINSN_3ARG_SDPS(MUL);
11455 break;
11456 case DIV_FMT:
11457 fmt = (ctx->opcode >> 8) & 0x3;
11458 if (fmt == 1) {
11459 mips32_op = OPC_DIV_D;
11460 } else if (fmt == 0) {
11461 mips32_op = OPC_DIV_S;
11462 } else {
11463 goto pool32f_invalid;
11465 goto do_fpop;
11466 default:
11467 goto pool32f_invalid;
11469 break;
11470 case 0x38:
11471 /* cmovs */
11472 switch ((ctx->opcode >> 6) & 0x3) {
11473 case MOVN_FMT:
11474 FINSN_3ARG_SDPS(MOVN);
11475 break;
11476 case MOVZ_FMT:
11477 FINSN_3ARG_SDPS(MOVZ);
11478 break;
11479 default:
11480 goto pool32f_invalid;
11482 break;
11483 do_fpop:
11484 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11485 break;
11486 default:
11487 pool32f_invalid:
11488 MIPS_INVAL("pool32f");
11489 generate_exception(ctx, EXCP_RI);
11490 break;
11492 } else {
11493 generate_exception_err(ctx, EXCP_CpU, 1);
11495 break;
11496 case POOL32I:
11497 minor = (ctx->opcode >> 21) & 0x1f;
11498 switch (minor) {
11499 case BLTZ:
11500 mips32_op = OPC_BLTZ;
11501 goto do_branch;
11502 case BLTZAL:
11503 mips32_op = OPC_BLTZAL;
11504 goto do_branch;
11505 case BLTZALS:
11506 mips32_op = OPC_BLTZALS;
11507 goto do_branch;
11508 case BGEZ:
11509 mips32_op = OPC_BGEZ;
11510 goto do_branch;
11511 case BGEZAL:
11512 mips32_op = OPC_BGEZAL;
11513 goto do_branch;
11514 case BGEZALS:
11515 mips32_op = OPC_BGEZALS;
11516 goto do_branch;
11517 case BLEZ:
11518 mips32_op = OPC_BLEZ;
11519 goto do_branch;
11520 case BGTZ:
11521 mips32_op = OPC_BGTZ;
11522 do_branch:
11523 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11524 *is_branch = 1;
11525 break;
11527 /* Traps */
11528 case TLTI:
11529 mips32_op = OPC_TLTI;
11530 goto do_trapi;
11531 case TGEI:
11532 mips32_op = OPC_TGEI;
11533 goto do_trapi;
11534 case TLTIU:
11535 mips32_op = OPC_TLTIU;
11536 goto do_trapi;
11537 case TGEIU:
11538 mips32_op = OPC_TGEIU;
11539 goto do_trapi;
11540 case TNEI:
11541 mips32_op = OPC_TNEI;
11542 goto do_trapi;
11543 case TEQI:
11544 mips32_op = OPC_TEQI;
11545 do_trapi:
11546 gen_trap(ctx, mips32_op, rs, -1, imm);
11547 break;
11549 case BNEZC:
11550 case BEQZC:
11551 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11552 4, rs, 0, imm << 1);
11553 /* Compact branches don't have a delay slot, so just let
11554 the normal delay slot handling take us to the branch
11555 target. */
11556 break;
11557 case LUI:
11558 gen_logic_imm(env, ctx, OPC_LUI, rs, -1, imm);
11559 break;
11560 case SYNCI:
11561 break;
11562 case BC2F:
11563 case BC2T:
11564 /* COP2: Not implemented. */
11565 generate_exception_err(ctx, EXCP_CpU, 2);
11566 break;
11567 case BC1F:
11568 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11569 goto do_cp1branch;
11570 case BC1T:
11571 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11572 goto do_cp1branch;
11573 case BC1ANY4F:
11574 mips32_op = OPC_BC1FANY4;
11575 goto do_cp1mips3d;
11576 case BC1ANY4T:
11577 mips32_op = OPC_BC1TANY4;
11578 do_cp1mips3d:
11579 check_cop1x(ctx);
11580 check_insn(env, ctx, ASE_MIPS3D);
11581 /* Fall through */
11582 do_cp1branch:
11583 gen_compute_branch1(env, ctx, mips32_op,
11584 (ctx->opcode >> 18) & 0x7, imm << 1);
11585 *is_branch = 1;
11586 break;
11587 case BPOSGE64:
11588 case BPOSGE32:
11589 /* MIPS DSP: not implemented */
11590 /* Fall through */
11591 default:
11592 MIPS_INVAL("pool32i");
11593 generate_exception(ctx, EXCP_RI);
11594 break;
11596 break;
11597 case POOL32C:
11598 minor = (ctx->opcode >> 12) & 0xf;
11599 switch (minor) {
11600 case LWL:
11601 mips32_op = OPC_LWL;
11602 goto do_ld_lr;
11603 case SWL:
11604 mips32_op = OPC_SWL;
11605 goto do_st_lr;
11606 case LWR:
11607 mips32_op = OPC_LWR;
11608 goto do_ld_lr;
11609 case SWR:
11610 mips32_op = OPC_SWR;
11611 goto do_st_lr;
11612 #if defined(TARGET_MIPS64)
11613 case LDL:
11614 mips32_op = OPC_LDL;
11615 goto do_ld_lr;
11616 case SDL:
11617 mips32_op = OPC_SDL;
11618 goto do_st_lr;
11619 case LDR:
11620 mips32_op = OPC_LDR;
11621 goto do_ld_lr;
11622 case SDR:
11623 mips32_op = OPC_SDR;
11624 goto do_st_lr;
11625 case LWU:
11626 mips32_op = OPC_LWU;
11627 goto do_ld_lr;
11628 case LLD:
11629 mips32_op = OPC_LLD;
11630 goto do_ld_lr;
11631 #endif
11632 case LL:
11633 mips32_op = OPC_LL;
11634 goto do_ld_lr;
11635 do_ld_lr:
11636 gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11637 break;
11638 do_st_lr:
11639 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11640 break;
11641 case SC:
11642 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11643 break;
11644 #if defined(TARGET_MIPS64)
11645 case SCD:
11646 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11647 break;
11648 #endif
11649 case PREF:
11650 /* Treat as no-op */
11651 break;
11652 default:
11653 MIPS_INVAL("pool32c");
11654 generate_exception(ctx, EXCP_RI);
11655 break;
11657 break;
11658 case ADDI32:
11659 mips32_op = OPC_ADDI;
11660 goto do_addi;
11661 case ADDIU32:
11662 mips32_op = OPC_ADDIU;
11663 do_addi:
11664 gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11665 break;
11667 /* Logical operations */
11668 case ORI32:
11669 mips32_op = OPC_ORI;
11670 goto do_logici;
11671 case XORI32:
11672 mips32_op = OPC_XORI;
11673 goto do_logici;
11674 case ANDI32:
11675 mips32_op = OPC_ANDI;
11676 do_logici:
11677 gen_logic_imm(env, ctx, mips32_op, rt, rs, imm);
11678 break;
11680 /* Set less than immediate */
11681 case SLTI32:
11682 mips32_op = OPC_SLTI;
11683 goto do_slti;
11684 case SLTIU32:
11685 mips32_op = OPC_SLTIU;
11686 do_slti:
11687 gen_slt_imm(env, ctx, mips32_op, rt, rs, imm);
11688 break;
11689 case JALX32:
11690 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11691 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11692 *is_branch = 1;
11693 break;
11694 case JALS32:
11695 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11696 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11697 *is_branch = 1;
11698 break;
11699 case BEQ32:
11700 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11701 *is_branch = 1;
11702 break;
11703 case BNE32:
11704 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11705 *is_branch = 1;
11706 break;
11707 case J32:
11708 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11709 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11710 *is_branch = 1;
11711 break;
11712 case JAL32:
11713 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11714 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11715 *is_branch = 1;
11716 break;
11717 /* Floating point (COP1) */
11718 case LWC132:
11719 mips32_op = OPC_LWC1;
11720 goto do_cop1;
11721 case LDC132:
11722 mips32_op = OPC_LDC1;
11723 goto do_cop1;
11724 case SWC132:
11725 mips32_op = OPC_SWC1;
11726 goto do_cop1;
11727 case SDC132:
11728 mips32_op = OPC_SDC1;
11729 do_cop1:
11730 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11731 break;
11732 case ADDIUPC:
11734 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11735 int offset = SIMM(ctx->opcode, 0, 23) << 2;
11737 gen_addiupc(ctx, reg, offset, 0, 0);
11739 break;
11740 /* Loads and stores */
11741 case LB32:
11742 mips32_op = OPC_LB;
11743 goto do_ld;
11744 case LBU32:
11745 mips32_op = OPC_LBU;
11746 goto do_ld;
11747 case LH32:
11748 mips32_op = OPC_LH;
11749 goto do_ld;
11750 case LHU32:
11751 mips32_op = OPC_LHU;
11752 goto do_ld;
11753 case LW32:
11754 mips32_op = OPC_LW;
11755 goto do_ld;
11756 #ifdef TARGET_MIPS64
11757 case LD32:
11758 mips32_op = OPC_LD;
11759 goto do_ld;
11760 case SD32:
11761 mips32_op = OPC_SD;
11762 goto do_st;
11763 #endif
11764 case SB32:
11765 mips32_op = OPC_SB;
11766 goto do_st;
11767 case SH32:
11768 mips32_op = OPC_SH;
11769 goto do_st;
11770 case SW32:
11771 mips32_op = OPC_SW;
11772 goto do_st;
11773 do_ld:
11774 gen_ld(env, ctx, mips32_op, rt, rs, imm);
11775 break;
11776 do_st:
11777 gen_st(ctx, mips32_op, rt, rs, imm);
11778 break;
11779 default:
11780 generate_exception(ctx, EXCP_RI);
11781 break;
11785 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
11787 uint32_t op;
11789 /* make sure instructions are on a halfword boundary */
11790 if (ctx->pc & 0x1) {
11791 env->CP0_BadVAddr = ctx->pc;
11792 generate_exception(ctx, EXCP_AdEL);
11793 ctx->bstate = BS_STOP;
11794 return 2;
11797 op = (ctx->opcode >> 10) & 0x3f;
11798 /* Enforce properly-sized instructions in a delay slot */
11799 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11800 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11802 switch (op) {
11803 case POOL32A:
11804 case POOL32B:
11805 case POOL32I:
11806 case POOL32C:
11807 case ADDI32:
11808 case ADDIU32:
11809 case ORI32:
11810 case XORI32:
11811 case SLTI32:
11812 case SLTIU32:
11813 case ANDI32:
11814 case JALX32:
11815 case LBU32:
11816 case LHU32:
11817 case POOL32F:
11818 case JALS32:
11819 case BEQ32:
11820 case BNE32:
11821 case J32:
11822 case JAL32:
11823 case SB32:
11824 case SH32:
11825 case POOL32S:
11826 case ADDIUPC:
11827 case SWC132:
11828 case SDC132:
11829 case SD32:
11830 case SW32:
11831 case LB32:
11832 case LH32:
11833 case DADDIU32:
11834 case POOL48A: /* ??? */
11835 case LWC132:
11836 case LDC132:
11837 case LD32:
11838 case LW32:
11839 if (bits & MIPS_HFLAG_BDS16) {
11840 generate_exception(ctx, EXCP_RI);
11841 /* Just stop translation; the user is confused. */
11842 ctx->bstate = BS_STOP;
11843 return 2;
11845 break;
11846 case POOL16A:
11847 case POOL16B:
11848 case POOL16C:
11849 case LWGP16:
11850 case POOL16F:
11851 case LBU16:
11852 case LHU16:
11853 case LWSP16:
11854 case LW16:
11855 case SB16:
11856 case SH16:
11857 case SWSP16:
11858 case SW16:
11859 case MOVE16:
11860 case ANDI16:
11861 case POOL16D:
11862 case POOL16E:
11863 case BEQZ16:
11864 case BNEZ16:
11865 case B16:
11866 case LI16:
11867 if (bits & MIPS_HFLAG_BDS32) {
11868 generate_exception(ctx, EXCP_RI);
11869 /* Just stop translation; the user is confused. */
11870 ctx->bstate = BS_STOP;
11871 return 2;
11873 break;
11874 default:
11875 break;
11878 switch (op) {
11879 case POOL16A:
11881 int rd = mmreg(uMIPS_RD(ctx->opcode));
11882 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11883 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11884 uint32_t opc = 0;
11886 switch (ctx->opcode & 0x1) {
11887 case ADDU16:
11888 opc = OPC_ADDU;
11889 break;
11890 case SUBU16:
11891 opc = OPC_SUBU;
11892 break;
11895 gen_arith(env, ctx, opc, rd, rs1, rs2);
11897 break;
11898 case POOL16B:
11900 int rd = mmreg(uMIPS_RD(ctx->opcode));
11901 int rs = mmreg(uMIPS_RS(ctx->opcode));
11902 int amount = (ctx->opcode >> 1) & 0x7;
11903 uint32_t opc = 0;
11904 amount = amount == 0 ? 8 : amount;
11906 switch (ctx->opcode & 0x1) {
11907 case SLL16:
11908 opc = OPC_SLL;
11909 break;
11910 case SRL16:
11911 opc = OPC_SRL;
11912 break;
11915 gen_shift_imm(env, ctx, opc, rd, rs, amount);
11917 break;
11918 case POOL16C:
11919 gen_pool16c_insn(env, ctx, is_branch);
11920 break;
11921 case LWGP16:
11923 int rd = mmreg(uMIPS_RD(ctx->opcode));
11924 int rb = 28; /* GP */
11925 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11927 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11929 break;
11930 case POOL16F:
11931 if (ctx->opcode & 1) {
11932 generate_exception(ctx, EXCP_RI);
11933 } else {
11934 /* MOVEP */
11935 int enc_dest = uMIPS_RD(ctx->opcode);
11936 int enc_rt = uMIPS_RS2(ctx->opcode);
11937 int enc_rs = uMIPS_RS1(ctx->opcode);
11938 int rd, rs, re, rt;
11939 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11940 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11941 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11943 rd = rd_enc[enc_dest];
11944 re = re_enc[enc_dest];
11945 rs = rs_rt_enc[enc_rs];
11946 rt = rs_rt_enc[enc_rt];
11948 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11949 gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11951 break;
11952 case LBU16:
11954 int rd = mmreg(uMIPS_RD(ctx->opcode));
11955 int rb = mmreg(uMIPS_RS(ctx->opcode));
11956 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11957 offset = (offset == 0xf ? -1 : offset);
11959 gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
11961 break;
11962 case LHU16:
11964 int rd = mmreg(uMIPS_RD(ctx->opcode));
11965 int rb = mmreg(uMIPS_RS(ctx->opcode));
11966 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11968 gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
11970 break;
11971 case LWSP16:
11973 int rd = (ctx->opcode >> 5) & 0x1f;
11974 int rb = 29; /* SP */
11975 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11977 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11979 break;
11980 case LW16:
11982 int rd = mmreg(uMIPS_RD(ctx->opcode));
11983 int rb = mmreg(uMIPS_RS(ctx->opcode));
11984 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11986 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11988 break;
11989 case SB16:
11991 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11992 int rb = mmreg(uMIPS_RS(ctx->opcode));
11993 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11995 gen_st(ctx, OPC_SB, rd, rb, offset);
11997 break;
11998 case SH16:
12000 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12001 int rb = mmreg(uMIPS_RS(ctx->opcode));
12002 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12004 gen_st(ctx, OPC_SH, rd, rb, offset);
12006 break;
12007 case SWSP16:
12009 int rd = (ctx->opcode >> 5) & 0x1f;
12010 int rb = 29; /* SP */
12011 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12013 gen_st(ctx, OPC_SW, rd, rb, offset);
12015 break;
12016 case SW16:
12018 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12019 int rb = mmreg(uMIPS_RS(ctx->opcode));
12020 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12022 gen_st(ctx, OPC_SW, rd, rb, offset);
12024 break;
12025 case MOVE16:
12027 int rd = uMIPS_RD5(ctx->opcode);
12028 int rs = uMIPS_RS5(ctx->opcode);
12030 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
12032 break;
12033 case ANDI16:
12034 gen_andi16(env, ctx);
12035 break;
12036 case POOL16D:
12037 switch (ctx->opcode & 0x1) {
12038 case ADDIUS5:
12039 gen_addius5(env, ctx);
12040 break;
12041 case ADDIUSP:
12042 gen_addiusp(env, ctx);
12043 break;
12045 break;
12046 case POOL16E:
12047 switch (ctx->opcode & 0x1) {
12048 case ADDIUR2:
12049 gen_addiur2(env, ctx);
12050 break;
12051 case ADDIUR1SP:
12052 gen_addiur1sp(env, ctx);
12053 break;
12055 break;
12056 case B16:
12057 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
12058 SIMM(ctx->opcode, 0, 10) << 1);
12059 *is_branch = 1;
12060 break;
12061 case BNEZ16:
12062 case BEQZ16:
12063 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
12064 mmreg(uMIPS_RD(ctx->opcode)),
12065 0, SIMM(ctx->opcode, 0, 7) << 1);
12066 *is_branch = 1;
12067 break;
12068 case LI16:
12070 int reg = mmreg(uMIPS_RD(ctx->opcode));
12071 int imm = ZIMM(ctx->opcode, 0, 7);
12073 imm = (imm == 0x7f ? -1 : imm);
12074 tcg_gen_movi_tl(cpu_gpr[reg], imm);
12076 break;
12077 case RES_20:
12078 case RES_28:
12079 case RES_29:
12080 case RES_30:
12081 case RES_31:
12082 case RES_38:
12083 case RES_39:
12084 generate_exception(ctx, EXCP_RI);
12085 break;
12086 default:
12087 decode_micromips32_opc (env, ctx, op, is_branch);
12088 return 4;
12091 return 2;
12094 /* SmartMIPS extension to MIPS32 */
12096 #if defined(TARGET_MIPS64)
12098 /* MDMX extension to MIPS64 */
12100 #endif
12102 static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
12104 int32_t offset;
12105 int rs, rt, rd, sa;
12106 uint32_t op, op1, op2;
12107 int16_t imm;
12109 /* make sure instructions are on a word boundary */
12110 if (ctx->pc & 0x3) {
12111 env->CP0_BadVAddr = ctx->pc;
12112 generate_exception(ctx, EXCP_AdEL);
12113 return;
12116 /* Handle blikely not taken case */
12117 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
12118 int l1 = gen_new_label();
12120 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
12121 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12122 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
12123 gen_goto_tb(ctx, 1, ctx->pc + 4);
12124 gen_set_label(l1);
12127 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
12128 tcg_gen_debug_insn_start(ctx->pc);
12131 op = MASK_OP_MAJOR(ctx->opcode);
12132 rs = (ctx->opcode >> 21) & 0x1f;
12133 rt = (ctx->opcode >> 16) & 0x1f;
12134 rd = (ctx->opcode >> 11) & 0x1f;
12135 sa = (ctx->opcode >> 6) & 0x1f;
12136 imm = (int16_t)ctx->opcode;
12137 switch (op) {
12138 case OPC_SPECIAL:
12139 op1 = MASK_SPECIAL(ctx->opcode);
12140 switch (op1) {
12141 case OPC_SLL: /* Shift with immediate */
12142 case OPC_SRA:
12143 gen_shift_imm(env, ctx, op1, rd, rt, sa);
12144 break;
12145 case OPC_SRL:
12146 switch ((ctx->opcode >> 21) & 0x1f) {
12147 case 1:
12148 /* rotr is decoded as srl on non-R2 CPUs */
12149 if (env->insn_flags & ISA_MIPS32R2) {
12150 op1 = OPC_ROTR;
12152 /* Fallthrough */
12153 case 0:
12154 gen_shift_imm(env, ctx, op1, rd, rt, sa);
12155 break;
12156 default:
12157 generate_exception(ctx, EXCP_RI);
12158 break;
12160 break;
12161 case OPC_MOVN: /* Conditional move */
12162 case OPC_MOVZ:
12163 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
12164 INSN_LOONGSON2E | INSN_LOONGSON2F);
12165 gen_cond_move(env, ctx, op1, rd, rs, rt);
12166 break;
12167 case OPC_ADD ... OPC_SUBU:
12168 gen_arith(env, ctx, op1, rd, rs, rt);
12169 break;
12170 case OPC_SLLV: /* Shifts */
12171 case OPC_SRAV:
12172 gen_shift(env, ctx, op1, rd, rs, rt);
12173 break;
12174 case OPC_SRLV:
12175 switch ((ctx->opcode >> 6) & 0x1f) {
12176 case 1:
12177 /* rotrv is decoded as srlv on non-R2 CPUs */
12178 if (env->insn_flags & ISA_MIPS32R2) {
12179 op1 = OPC_ROTRV;
12181 /* Fallthrough */
12182 case 0:
12183 gen_shift(env, ctx, op1, rd, rs, rt);
12184 break;
12185 default:
12186 generate_exception(ctx, EXCP_RI);
12187 break;
12189 break;
12190 case OPC_SLT: /* Set on less than */
12191 case OPC_SLTU:
12192 gen_slt(env, ctx, op1, rd, rs, rt);
12193 break;
12194 case OPC_AND: /* Logic*/
12195 case OPC_OR:
12196 case OPC_NOR:
12197 case OPC_XOR:
12198 gen_logic(env, ctx, op1, rd, rs, rt);
12199 break;
12200 case OPC_MULT ... OPC_DIVU:
12201 if (sa) {
12202 check_insn(env, ctx, INSN_VR54XX);
12203 op1 = MASK_MUL_VR54XX(ctx->opcode);
12204 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
12205 } else
12206 gen_muldiv(ctx, op1, rs, rt);
12207 break;
12208 case OPC_JR ... OPC_JALR:
12209 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
12210 *is_branch = 1;
12211 break;
12212 case OPC_TGE ... OPC_TEQ: /* Traps */
12213 case OPC_TNE:
12214 gen_trap(ctx, op1, rs, rt, -1);
12215 break;
12216 case OPC_MFHI: /* Move from HI/LO */
12217 case OPC_MFLO:
12218 gen_HILO(ctx, op1, rd);
12219 break;
12220 case OPC_MTHI:
12221 case OPC_MTLO: /* Move to HI/LO */
12222 gen_HILO(ctx, op1, rs);
12223 break;
12224 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
12225 #ifdef MIPS_STRICT_STANDARD
12226 MIPS_INVAL("PMON / selsl");
12227 generate_exception(ctx, EXCP_RI);
12228 #else
12229 gen_helper_0e0i(pmon, sa);
12230 #endif
12231 break;
12232 case OPC_SYSCALL:
12233 generate_exception(ctx, EXCP_SYSCALL);
12234 ctx->bstate = BS_STOP;
12235 break;
12236 case OPC_BREAK:
12237 generate_exception(ctx, EXCP_BREAK);
12238 break;
12239 case OPC_SPIM:
12240 #ifdef MIPS_STRICT_STANDARD
12241 MIPS_INVAL("SPIM");
12242 generate_exception(ctx, EXCP_RI);
12243 #else
12244 /* Implemented as RI exception for now. */
12245 MIPS_INVAL("spim (unofficial)");
12246 generate_exception(ctx, EXCP_RI);
12247 #endif
12248 break;
12249 case OPC_SYNC:
12250 /* Treat as NOP. */
12251 break;
12253 case OPC_MOVCI:
12254 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
12255 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12256 check_cp1_enabled(ctx);
12257 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
12258 (ctx->opcode >> 16) & 1);
12259 } else {
12260 generate_exception_err(ctx, EXCP_CpU, 1);
12262 break;
12264 #if defined(TARGET_MIPS64)
12265 /* MIPS64 specific opcodes */
12266 case OPC_DSLL:
12267 case OPC_DSRA:
12268 case OPC_DSLL32:
12269 case OPC_DSRA32:
12270 check_insn(env, ctx, ISA_MIPS3);
12271 check_mips_64(ctx);
12272 gen_shift_imm(env, ctx, op1, rd, rt, sa);
12273 break;
12274 case OPC_DSRL:
12275 switch ((ctx->opcode >> 21) & 0x1f) {
12276 case 1:
12277 /* drotr is decoded as dsrl on non-R2 CPUs */
12278 if (env->insn_flags & ISA_MIPS32R2) {
12279 op1 = OPC_DROTR;
12281 /* Fallthrough */
12282 case 0:
12283 check_insn(env, ctx, ISA_MIPS3);
12284 check_mips_64(ctx);
12285 gen_shift_imm(env, ctx, op1, rd, rt, sa);
12286 break;
12287 default:
12288 generate_exception(ctx, EXCP_RI);
12289 break;
12291 break;
12292 case OPC_DSRL32:
12293 switch ((ctx->opcode >> 21) & 0x1f) {
12294 case 1:
12295 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
12296 if (env->insn_flags & ISA_MIPS32R2) {
12297 op1 = OPC_DROTR32;
12299 /* Fallthrough */
12300 case 0:
12301 check_insn(env, ctx, ISA_MIPS3);
12302 check_mips_64(ctx);
12303 gen_shift_imm(env, ctx, op1, rd, rt, sa);
12304 break;
12305 default:
12306 generate_exception(ctx, EXCP_RI);
12307 break;
12309 break;
12310 case OPC_DADD ... OPC_DSUBU:
12311 check_insn(env, ctx, ISA_MIPS3);
12312 check_mips_64(ctx);
12313 gen_arith(env, ctx, op1, rd, rs, rt);
12314 break;
12315 case OPC_DSLLV:
12316 case OPC_DSRAV:
12317 check_insn(env, ctx, ISA_MIPS3);
12318 check_mips_64(ctx);
12319 gen_shift(env, ctx, op1, rd, rs, rt);
12320 break;
12321 case OPC_DSRLV:
12322 switch ((ctx->opcode >> 6) & 0x1f) {
12323 case 1:
12324 /* drotrv is decoded as dsrlv on non-R2 CPUs */
12325 if (env->insn_flags & ISA_MIPS32R2) {
12326 op1 = OPC_DROTRV;
12328 /* Fallthrough */
12329 case 0:
12330 check_insn(env, ctx, ISA_MIPS3);
12331 check_mips_64(ctx);
12332 gen_shift(env, ctx, op1, rd, rs, rt);
12333 break;
12334 default:
12335 generate_exception(ctx, EXCP_RI);
12336 break;
12338 break;
12339 case OPC_DMULT ... OPC_DDIVU:
12340 check_insn(env, ctx, ISA_MIPS3);
12341 check_mips_64(ctx);
12342 gen_muldiv(ctx, op1, rs, rt);
12343 break;
12344 #endif
12345 default: /* Invalid */
12346 MIPS_INVAL("special");
12347 generate_exception(ctx, EXCP_RI);
12348 break;
12350 break;
12351 case OPC_SPECIAL2:
12352 op1 = MASK_SPECIAL2(ctx->opcode);
12353 switch (op1) {
12354 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
12355 case OPC_MSUB ... OPC_MSUBU:
12356 check_insn(env, ctx, ISA_MIPS32);
12357 gen_muldiv(ctx, op1, rs, rt);
12358 break;
12359 case OPC_MUL:
12360 gen_arith(env, ctx, op1, rd, rs, rt);
12361 break;
12362 case OPC_CLO:
12363 case OPC_CLZ:
12364 check_insn(env, ctx, ISA_MIPS32);
12365 gen_cl(ctx, op1, rd, rs);
12366 break;
12367 case OPC_SDBBP:
12368 /* XXX: not clear which exception should be raised
12369 * when in debug mode...
12371 check_insn(env, ctx, ISA_MIPS32);
12372 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12373 generate_exception(ctx, EXCP_DBp);
12374 } else {
12375 generate_exception(ctx, EXCP_DBp);
12377 /* Treat as NOP. */
12378 break;
12379 case OPC_DIV_G_2F:
12380 case OPC_DIVU_G_2F:
12381 case OPC_MULT_G_2F:
12382 case OPC_MULTU_G_2F:
12383 case OPC_MOD_G_2F:
12384 case OPC_MODU_G_2F:
12385 check_insn(env, ctx, INSN_LOONGSON2F);
12386 gen_loongson_integer(ctx, op1, rd, rs, rt);
12387 break;
12388 #if defined(TARGET_MIPS64)
12389 case OPC_DCLO:
12390 case OPC_DCLZ:
12391 check_insn(env, ctx, ISA_MIPS64);
12392 check_mips_64(ctx);
12393 gen_cl(ctx, op1, rd, rs);
12394 break;
12395 case OPC_DMULT_G_2F:
12396 case OPC_DMULTU_G_2F:
12397 case OPC_DDIV_G_2F:
12398 case OPC_DDIVU_G_2F:
12399 case OPC_DMOD_G_2F:
12400 case OPC_DMODU_G_2F:
12401 check_insn(env, ctx, INSN_LOONGSON2F);
12402 gen_loongson_integer(ctx, op1, rd, rs, rt);
12403 break;
12404 #endif
12405 default: /* Invalid */
12406 MIPS_INVAL("special2");
12407 generate_exception(ctx, EXCP_RI);
12408 break;
12410 break;
12411 case OPC_SPECIAL3:
12412 op1 = MASK_SPECIAL3(ctx->opcode);
12413 switch (op1) {
12414 case OPC_EXT:
12415 case OPC_INS:
12416 check_insn(env, ctx, ISA_MIPS32R2);
12417 gen_bitops(ctx, op1, rt, rs, sa, rd);
12418 break;
12419 case OPC_BSHFL:
12420 check_insn(env, ctx, ISA_MIPS32R2);
12421 op2 = MASK_BSHFL(ctx->opcode);
12422 gen_bshfl(ctx, op2, rt, rd);
12423 break;
12424 case OPC_RDHWR:
12425 gen_rdhwr(env, ctx, rt, rd);
12426 break;
12427 case OPC_FORK:
12428 check_insn(env, ctx, ASE_MT);
12430 TCGv t0 = tcg_temp_new();
12431 TCGv t1 = tcg_temp_new();
12433 gen_load_gpr(t0, rt);
12434 gen_load_gpr(t1, rs);
12435 gen_helper_fork(t0, t1);
12436 tcg_temp_free(t0);
12437 tcg_temp_free(t1);
12439 break;
12440 case OPC_YIELD:
12441 check_insn(env, ctx, ASE_MT);
12443 TCGv t0 = tcg_temp_new();
12445 save_cpu_state(ctx, 1);
12446 gen_load_gpr(t0, rs);
12447 gen_helper_yield(t0, cpu_env, t0);
12448 gen_store_gpr(t0, rd);
12449 tcg_temp_free(t0);
12451 break;
12452 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
12453 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
12454 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
12455 check_insn(env, ctx, INSN_LOONGSON2E);
12456 gen_loongson_integer(ctx, op1, rd, rs, rt);
12457 break;
12458 #if defined(TARGET_MIPS64)
12459 case OPC_DEXTM ... OPC_DEXT:
12460 case OPC_DINSM ... OPC_DINS:
12461 check_insn(env, ctx, ISA_MIPS64R2);
12462 check_mips_64(ctx);
12463 gen_bitops(ctx, op1, rt, rs, sa, rd);
12464 break;
12465 case OPC_DBSHFL:
12466 check_insn(env, ctx, ISA_MIPS64R2);
12467 check_mips_64(ctx);
12468 op2 = MASK_DBSHFL(ctx->opcode);
12469 gen_bshfl(ctx, op2, rt, rd);
12470 break;
12471 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
12472 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
12473 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
12474 check_insn(env, ctx, INSN_LOONGSON2E);
12475 gen_loongson_integer(ctx, op1, rd, rs, rt);
12476 break;
12477 #endif
12478 default: /* Invalid */
12479 MIPS_INVAL("special3");
12480 generate_exception(ctx, EXCP_RI);
12481 break;
12483 break;
12484 case OPC_REGIMM:
12485 op1 = MASK_REGIMM(ctx->opcode);
12486 switch (op1) {
12487 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
12488 case OPC_BLTZAL ... OPC_BGEZALL:
12489 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
12490 *is_branch = 1;
12491 break;
12492 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
12493 case OPC_TNEI:
12494 gen_trap(ctx, op1, rs, -1, imm);
12495 break;
12496 case OPC_SYNCI:
12497 check_insn(env, ctx, ISA_MIPS32R2);
12498 /* Treat as NOP. */
12499 break;
12500 default: /* Invalid */
12501 MIPS_INVAL("regimm");
12502 generate_exception(ctx, EXCP_RI);
12503 break;
12505 break;
12506 case OPC_CP0:
12507 check_cp0_enabled(ctx);
12508 op1 = MASK_CP0(ctx->opcode);
12509 switch (op1) {
12510 case OPC_MFC0:
12511 case OPC_MTC0:
12512 case OPC_MFTR:
12513 case OPC_MTTR:
12514 #if defined(TARGET_MIPS64)
12515 case OPC_DMFC0:
12516 case OPC_DMTC0:
12517 #endif
12518 #ifndef CONFIG_USER_ONLY
12519 gen_cp0(env, ctx, op1, rt, rd);
12520 #endif /* !CONFIG_USER_ONLY */
12521 break;
12522 case OPC_C0_FIRST ... OPC_C0_LAST:
12523 #ifndef CONFIG_USER_ONLY
12524 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
12525 #endif /* !CONFIG_USER_ONLY */
12526 break;
12527 case OPC_MFMC0:
12528 #ifndef CONFIG_USER_ONLY
12530 TCGv t0 = tcg_temp_new();
12532 op2 = MASK_MFMC0(ctx->opcode);
12533 switch (op2) {
12534 case OPC_DMT:
12535 check_insn(env, ctx, ASE_MT);
12536 gen_helper_dmt(t0);
12537 gen_store_gpr(t0, rt);
12538 break;
12539 case OPC_EMT:
12540 check_insn(env, ctx, ASE_MT);
12541 gen_helper_emt(t0);
12542 gen_store_gpr(t0, rt);
12543 break;
12544 case OPC_DVPE:
12545 check_insn(env, ctx, ASE_MT);
12546 gen_helper_dvpe(t0, cpu_env);
12547 gen_store_gpr(t0, rt);
12548 break;
12549 case OPC_EVPE:
12550 check_insn(env, ctx, ASE_MT);
12551 gen_helper_evpe(t0, cpu_env);
12552 gen_store_gpr(t0, rt);
12553 break;
12554 case OPC_DI:
12555 check_insn(env, ctx, ISA_MIPS32R2);
12556 save_cpu_state(ctx, 1);
12557 gen_helper_di(t0, cpu_env);
12558 gen_store_gpr(t0, rt);
12559 /* Stop translation as we may have switched the execution mode */
12560 ctx->bstate = BS_STOP;
12561 break;
12562 case OPC_EI:
12563 check_insn(env, ctx, ISA_MIPS32R2);
12564 save_cpu_state(ctx, 1);
12565 gen_helper_ei(t0, cpu_env);
12566 gen_store_gpr(t0, rt);
12567 /* Stop translation as we may have switched the execution mode */
12568 ctx->bstate = BS_STOP;
12569 break;
12570 default: /* Invalid */
12571 MIPS_INVAL("mfmc0");
12572 generate_exception(ctx, EXCP_RI);
12573 break;
12575 tcg_temp_free(t0);
12577 #endif /* !CONFIG_USER_ONLY */
12578 break;
12579 case OPC_RDPGPR:
12580 check_insn(env, ctx, ISA_MIPS32R2);
12581 gen_load_srsgpr(rt, rd);
12582 break;
12583 case OPC_WRPGPR:
12584 check_insn(env, ctx, ISA_MIPS32R2);
12585 gen_store_srsgpr(rt, rd);
12586 break;
12587 default:
12588 MIPS_INVAL("cp0");
12589 generate_exception(ctx, EXCP_RI);
12590 break;
12592 break;
12593 case OPC_ADDI: /* Arithmetic with immediate opcode */
12594 case OPC_ADDIU:
12595 gen_arith_imm(env, ctx, op, rt, rs, imm);
12596 break;
12597 case OPC_SLTI: /* Set on less than with immediate opcode */
12598 case OPC_SLTIU:
12599 gen_slt_imm(env, ctx, op, rt, rs, imm);
12600 break;
12601 case OPC_ANDI: /* Arithmetic with immediate opcode */
12602 case OPC_LUI:
12603 case OPC_ORI:
12604 case OPC_XORI:
12605 gen_logic_imm(env, ctx, op, rt, rs, imm);
12606 break;
12607 case OPC_J ... OPC_JAL: /* Jump */
12608 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12609 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12610 *is_branch = 1;
12611 break;
12612 case OPC_BEQ ... OPC_BGTZ: /* Branch */
12613 case OPC_BEQL ... OPC_BGTZL:
12614 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
12615 *is_branch = 1;
12616 break;
12617 case OPC_LB ... OPC_LWR: /* Load and stores */
12618 case OPC_LL:
12619 gen_ld(env, ctx, op, rt, rs, imm);
12620 break;
12621 case OPC_SB ... OPC_SW:
12622 case OPC_SWR:
12623 gen_st(ctx, op, rt, rs, imm);
12624 break;
12625 case OPC_SC:
12626 gen_st_cond(ctx, op, rt, rs, imm);
12627 break;
12628 case OPC_CACHE:
12629 check_cp0_enabled(ctx);
12630 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
12631 /* Treat as NOP. */
12632 break;
12633 case OPC_PREF:
12634 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
12635 /* Treat as NOP. */
12636 break;
12638 /* Floating point (COP1). */
12639 case OPC_LWC1:
12640 case OPC_LDC1:
12641 case OPC_SWC1:
12642 case OPC_SDC1:
12643 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
12644 break;
12646 case OPC_CP1:
12647 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12648 check_cp1_enabled(ctx);
12649 op1 = MASK_CP1(ctx->opcode);
12650 switch (op1) {
12651 case OPC_MFHC1:
12652 case OPC_MTHC1:
12653 check_insn(env, ctx, ISA_MIPS32R2);
12654 case OPC_MFC1:
12655 case OPC_CFC1:
12656 case OPC_MTC1:
12657 case OPC_CTC1:
12658 gen_cp1(ctx, op1, rt, rd);
12659 break;
12660 #if defined(TARGET_MIPS64)
12661 case OPC_DMFC1:
12662 case OPC_DMTC1:
12663 check_insn(env, ctx, ISA_MIPS3);
12664 gen_cp1(ctx, op1, rt, rd);
12665 break;
12666 #endif
12667 case OPC_BC1ANY2:
12668 case OPC_BC1ANY4:
12669 check_cop1x(ctx);
12670 check_insn(env, ctx, ASE_MIPS3D);
12671 /* fall through */
12672 case OPC_BC1:
12673 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
12674 (rt >> 2) & 0x7, imm << 2);
12675 *is_branch = 1;
12676 break;
12677 case OPC_S_FMT:
12678 case OPC_D_FMT:
12679 case OPC_W_FMT:
12680 case OPC_L_FMT:
12681 case OPC_PS_FMT:
12682 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
12683 (imm >> 8) & 0x7);
12684 break;
12685 default:
12686 MIPS_INVAL("cp1");
12687 generate_exception (ctx, EXCP_RI);
12688 break;
12690 } else {
12691 generate_exception_err(ctx, EXCP_CpU, 1);
12693 break;
12695 /* COP2. */
12696 case OPC_LWC2:
12697 case OPC_LDC2:
12698 case OPC_SWC2:
12699 case OPC_SDC2:
12700 /* COP2: Not implemented. */
12701 generate_exception_err(ctx, EXCP_CpU, 2);
12702 break;
12703 case OPC_CP2:
12704 check_insn(env, ctx, INSN_LOONGSON2F);
12705 /* Note that these instructions use different fields. */
12706 gen_loongson_multimedia(ctx, sa, rd, rt);
12707 break;
12709 case OPC_CP3:
12710 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12711 check_cp1_enabled(ctx);
12712 op1 = MASK_CP3(ctx->opcode);
12713 switch (op1) {
12714 case OPC_LWXC1:
12715 case OPC_LDXC1:
12716 case OPC_LUXC1:
12717 case OPC_SWXC1:
12718 case OPC_SDXC1:
12719 case OPC_SUXC1:
12720 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
12721 break;
12722 case OPC_PREFX:
12723 /* Treat as NOP. */
12724 break;
12725 case OPC_ALNV_PS:
12726 case OPC_MADD_S:
12727 case OPC_MADD_D:
12728 case OPC_MADD_PS:
12729 case OPC_MSUB_S:
12730 case OPC_MSUB_D:
12731 case OPC_MSUB_PS:
12732 case OPC_NMADD_S:
12733 case OPC_NMADD_D:
12734 case OPC_NMADD_PS:
12735 case OPC_NMSUB_S:
12736 case OPC_NMSUB_D:
12737 case OPC_NMSUB_PS:
12738 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12739 break;
12740 default:
12741 MIPS_INVAL("cp3");
12742 generate_exception (ctx, EXCP_RI);
12743 break;
12745 } else {
12746 generate_exception_err(ctx, EXCP_CpU, 1);
12748 break;
12750 #if defined(TARGET_MIPS64)
12751 /* MIPS64 opcodes */
12752 case OPC_LWU:
12753 case OPC_LDL ... OPC_LDR:
12754 case OPC_LLD:
12755 case OPC_LD:
12756 check_insn(env, ctx, ISA_MIPS3);
12757 check_mips_64(ctx);
12758 gen_ld(env, ctx, op, rt, rs, imm);
12759 break;
12760 case OPC_SDL ... OPC_SDR:
12761 case OPC_SD:
12762 check_insn(env, ctx, ISA_MIPS3);
12763 check_mips_64(ctx);
12764 gen_st(ctx, op, rt, rs, imm);
12765 break;
12766 case OPC_SCD:
12767 check_insn(env, ctx, ISA_MIPS3);
12768 check_mips_64(ctx);
12769 gen_st_cond(ctx, op, rt, rs, imm);
12770 break;
12771 case OPC_DADDI:
12772 case OPC_DADDIU:
12773 check_insn(env, ctx, ISA_MIPS3);
12774 check_mips_64(ctx);
12775 gen_arith_imm(env, ctx, op, rt, rs, imm);
12776 break;
12777 #endif
12778 case OPC_JALX:
12779 check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
12780 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12781 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12782 *is_branch = 1;
12783 break;
12784 case OPC_MDMX:
12785 check_insn(env, ctx, ASE_MDMX);
12786 /* MDMX: Not implemented. */
12787 default: /* Invalid */
12788 MIPS_INVAL("major opcode");
12789 generate_exception(ctx, EXCP_RI);
12790 break;
12794 static inline void
12795 gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
12796 int search_pc)
12798 DisasContext ctx;
12799 target_ulong pc_start;
12800 uint16_t *gen_opc_end;
12801 CPUBreakpoint *bp;
12802 int j, lj = -1;
12803 int num_insns;
12804 int max_insns;
12805 int insn_bytes;
12806 int is_branch;
12808 if (search_pc)
12809 qemu_log("search pc %d\n", search_pc);
12811 pc_start = tb->pc;
12812 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
12813 ctx.pc = pc_start;
12814 ctx.saved_pc = -1;
12815 ctx.singlestep_enabled = env->singlestep_enabled;
12816 ctx.tb = tb;
12817 ctx.bstate = BS_NONE;
12818 /* Restore delay slot state from the tb context. */
12819 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
12820 restore_cpu_state(env, &ctx);
12821 #ifdef CONFIG_USER_ONLY
12822 ctx.mem_idx = MIPS_HFLAG_UM;
12823 #else
12824 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
12825 #endif
12826 num_insns = 0;
12827 max_insns = tb->cflags & CF_COUNT_MASK;
12828 if (max_insns == 0)
12829 max_insns = CF_COUNT_MASK;
12830 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
12831 gen_icount_start();
12832 while (ctx.bstate == BS_NONE) {
12833 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12834 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
12835 if (bp->pc == ctx.pc) {
12836 save_cpu_state(&ctx, 1);
12837 ctx.bstate = BS_BRANCH;
12838 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
12839 /* Include the breakpoint location or the tb won't
12840 * be flushed when it must be. */
12841 ctx.pc += 4;
12842 goto done_generating;
12847 if (search_pc) {
12848 j = gen_opc_ptr - gen_opc_buf;
12849 if (lj < j) {
12850 lj++;
12851 while (lj < j)
12852 gen_opc_instr_start[lj++] = 0;
12854 gen_opc_pc[lj] = ctx.pc;
12855 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12856 gen_opc_instr_start[lj] = 1;
12857 gen_opc_icount[lj] = num_insns;
12859 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12860 gen_io_start();
12862 is_branch = 0;
12863 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
12864 ctx.opcode = cpu_ldl_code(env, ctx.pc);
12865 insn_bytes = 4;
12866 decode_opc(env, &ctx, &is_branch);
12867 } else if (env->insn_flags & ASE_MICROMIPS) {
12868 ctx.opcode = cpu_lduw_code(env, ctx.pc);
12869 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
12870 } else if (env->insn_flags & ASE_MIPS16) {
12871 ctx.opcode = cpu_lduw_code(env, ctx.pc);
12872 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
12873 } else {
12874 generate_exception(&ctx, EXCP_RI);
12875 ctx.bstate = BS_STOP;
12876 break;
12878 if (!is_branch) {
12879 handle_delay_slot(env, &ctx, insn_bytes);
12881 ctx.pc += insn_bytes;
12883 num_insns++;
12885 /* Execute a branch and its delay slot as a single instruction.
12886 This is what GDB expects and is consistent with what the
12887 hardware does (e.g. if a delay slot instruction faults, the
12888 reported PC is the PC of the branch). */
12889 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
12890 break;
12892 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12893 break;
12895 if (gen_opc_ptr >= gen_opc_end)
12896 break;
12898 if (num_insns >= max_insns)
12899 break;
12901 if (singlestep)
12902 break;
12904 if (tb->cflags & CF_LAST_IO)
12905 gen_io_end();
12906 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
12907 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
12908 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
12909 } else {
12910 switch (ctx.bstate) {
12911 case BS_STOP:
12912 gen_goto_tb(&ctx, 0, ctx.pc);
12913 break;
12914 case BS_NONE:
12915 save_cpu_state(&ctx, 0);
12916 gen_goto_tb(&ctx, 0, ctx.pc);
12917 break;
12918 case BS_EXCP:
12919 tcg_gen_exit_tb(0);
12920 break;
12921 case BS_BRANCH:
12922 default:
12923 break;
12926 done_generating:
12927 gen_icount_end(tb, num_insns);
12928 *gen_opc_ptr = INDEX_op_end;
12929 if (search_pc) {
12930 j = gen_opc_ptr - gen_opc_buf;
12931 lj++;
12932 while (lj <= j)
12933 gen_opc_instr_start[lj++] = 0;
12934 } else {
12935 tb->size = ctx.pc - pc_start;
12936 tb->icount = num_insns;
12938 #ifdef DEBUG_DISAS
12939 LOG_DISAS("\n");
12940 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
12941 qemu_log("IN: %s\n", lookup_symbol(pc_start));
12942 log_target_disas(pc_start, ctx.pc - pc_start, 0);
12943 qemu_log("\n");
12945 #endif
12948 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
12950 gen_intermediate_code_internal(env, tb, 0);
12953 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
12955 gen_intermediate_code_internal(env, tb, 1);
12958 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
12959 int flags)
12961 int i;
12962 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
12964 #define printfpr(fp) \
12965 do { \
12966 if (is_fpu64) \
12967 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12968 " fd:%13g fs:%13g psu: %13g\n", \
12969 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12970 (double)(fp)->fd, \
12971 (double)(fp)->fs[FP_ENDIAN_IDX], \
12972 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12973 else { \
12974 fpr_t tmp; \
12975 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12976 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12977 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12978 " fd:%13g fs:%13g psu:%13g\n", \
12979 tmp.w[FP_ENDIAN_IDX], tmp.d, \
12980 (double)tmp.fd, \
12981 (double)tmp.fs[FP_ENDIAN_IDX], \
12982 (double)tmp.fs[!FP_ENDIAN_IDX]); \
12984 } while(0)
12987 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
12988 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
12989 get_float_exception_flags(&env->active_fpu.fp_status));
12990 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12991 fpu_fprintf(f, "%3s: ", fregnames[i]);
12992 printfpr(&env->active_fpu.fpr[i]);
12995 #undef printfpr
12998 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
12999 /* Debug help: The architecture requires 32bit code to maintain proper
13000 sign-extended values on 64bit machines. */
13002 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
13004 static void
13005 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
13006 fprintf_function cpu_fprintf,
13007 int flags)
13009 int i;
13011 if (!SIGN_EXT_P(env->active_tc.PC))
13012 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
13013 if (!SIGN_EXT_P(env->active_tc.HI[0]))
13014 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
13015 if (!SIGN_EXT_P(env->active_tc.LO[0]))
13016 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
13017 if (!SIGN_EXT_P(env->btarget))
13018 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
13020 for (i = 0; i < 32; i++) {
13021 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
13022 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
13025 if (!SIGN_EXT_P(env->CP0_EPC))
13026 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
13027 if (!SIGN_EXT_P(env->lladdr))
13028 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
13030 #endif
13032 void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
13033 int flags)
13035 int i;
13037 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
13038 " LO=0x" TARGET_FMT_lx " ds %04x "
13039 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
13040 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
13041 env->hflags, env->btarget, env->bcond);
13042 for (i = 0; i < 32; i++) {
13043 if ((i & 3) == 0)
13044 cpu_fprintf(f, "GPR%02d:", i);
13045 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
13046 if ((i & 3) == 3)
13047 cpu_fprintf(f, "\n");
13050 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
13051 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
13052 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
13053 env->CP0_Config0, env->CP0_Config1, env->lladdr);
13054 if (env->hflags & MIPS_HFLAG_FPU)
13055 fpu_dump_state(env, f, cpu_fprintf, flags);
13056 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
13057 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
13058 #endif
13061 static void mips_tcg_init(void)
13063 int i;
13064 static int inited;
13066 /* Initialize various static tables. */
13067 if (inited)
13068 return;
13070 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
13071 TCGV_UNUSED(cpu_gpr[0]);
13072 for (i = 1; i < 32; i++)
13073 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
13074 offsetof(CPUMIPSState, active_tc.gpr[i]),
13075 regnames[i]);
13076 cpu_PC = tcg_global_mem_new(TCG_AREG0,
13077 offsetof(CPUMIPSState, active_tc.PC), "PC");
13078 for (i = 0; i < MIPS_DSP_ACC; i++) {
13079 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
13080 offsetof(CPUMIPSState, active_tc.HI[i]),
13081 regnames_HI[i]);
13082 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
13083 offsetof(CPUMIPSState, active_tc.LO[i]),
13084 regnames_LO[i]);
13085 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
13086 offsetof(CPUMIPSState, active_tc.ACX[i]),
13087 regnames_ACX[i]);
13089 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
13090 offsetof(CPUMIPSState, active_tc.DSPControl),
13091 "DSPControl");
13092 bcond = tcg_global_mem_new(TCG_AREG0,
13093 offsetof(CPUMIPSState, bcond), "bcond");
13094 btarget = tcg_global_mem_new(TCG_AREG0,
13095 offsetof(CPUMIPSState, btarget), "btarget");
13096 hflags = tcg_global_mem_new_i32(TCG_AREG0,
13097 offsetof(CPUMIPSState, hflags), "hflags");
13099 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
13100 offsetof(CPUMIPSState, active_fpu.fcr0),
13101 "fcr0");
13102 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
13103 offsetof(CPUMIPSState, active_fpu.fcr31),
13104 "fcr31");
13106 /* register helpers */
13107 #define GEN_HELPER 2
13108 #include "helper.h"
13110 inited = 1;
13113 #include "translate_init.c"
13115 MIPSCPU *cpu_mips_init(const char *cpu_model)
13117 MIPSCPU *cpu;
13118 CPUMIPSState *env;
13119 const mips_def_t *def;
13121 def = cpu_mips_find_by_name(cpu_model);
13122 if (!def)
13123 return NULL;
13124 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
13125 env = &cpu->env;
13126 env->cpu_model = def;
13127 env->cpu_model_str = cpu_model;
13129 #ifndef CONFIG_USER_ONLY
13130 mmu_init(env, def);
13131 #endif
13132 fpu_init(env, def);
13133 mvp_init(env, def);
13134 mips_tcg_init();
13135 cpu_reset(CPU(cpu));
13136 qemu_init_vcpu(env);
13137 return cpu;
13140 void cpu_state_reset(CPUMIPSState *env)
13142 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
13143 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
13144 log_cpu_state(env, 0);
13147 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
13148 tlb_flush(env, 1);
13150 /* Reset registers to their default values */
13151 env->CP0_PRid = env->cpu_model->CP0_PRid;
13152 env->CP0_Config0 = env->cpu_model->CP0_Config0;
13153 #ifdef TARGET_WORDS_BIGENDIAN
13154 env->CP0_Config0 |= (1 << CP0C0_BE);
13155 #endif
13156 env->CP0_Config1 = env->cpu_model->CP0_Config1;
13157 env->CP0_Config2 = env->cpu_model->CP0_Config2;
13158 env->CP0_Config3 = env->cpu_model->CP0_Config3;
13159 env->CP0_Config6 = env->cpu_model->CP0_Config6;
13160 env->CP0_Config7 = env->cpu_model->CP0_Config7;
13161 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
13162 << env->cpu_model->CP0_LLAddr_shift;
13163 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
13164 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
13165 env->CCRes = env->cpu_model->CCRes;
13166 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
13167 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
13168 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
13169 env->current_tc = 0;
13170 env->SEGBITS = env->cpu_model->SEGBITS;
13171 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
13172 #if defined(TARGET_MIPS64)
13173 if (env->cpu_model->insn_flags & ISA_MIPS3) {
13174 env->SEGMask |= 3ULL << 62;
13176 #endif
13177 env->PABITS = env->cpu_model->PABITS;
13178 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
13179 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
13180 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
13181 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
13182 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
13183 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
13184 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
13185 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
13186 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
13187 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
13188 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
13189 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
13190 env->insn_flags = env->cpu_model->insn_flags;
13192 #if defined(CONFIG_USER_ONLY)
13193 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
13194 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
13195 hardware registers. */
13196 env->CP0_HWREna |= 0x0000000F;
13197 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
13198 env->CP0_Status |= (1 << CP0St_CU1);
13200 #else
13201 if (env->hflags & MIPS_HFLAG_BMASK) {
13202 /* If the exception was raised from a delay slot,
13203 come back to the jump. */
13204 env->CP0_ErrorEPC = env->active_tc.PC - 4;
13205 } else {
13206 env->CP0_ErrorEPC = env->active_tc.PC;
13208 env->active_tc.PC = (int32_t)0xBFC00000;
13209 env->CP0_Random = env->tlb->nb_tlb - 1;
13210 env->tlb->tlb_in_use = env->tlb->nb_tlb;
13211 env->CP0_Wired = 0;
13212 env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
13213 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
13214 /* vectored interrupts not implemented, timer on int 7,
13215 no performance counters. */
13216 env->CP0_IntCtl = 0xe0000000;
13218 int i;
13220 for (i = 0; i < 7; i++) {
13221 env->CP0_WatchLo[i] = 0;
13222 env->CP0_WatchHi[i] = 0x80000000;
13224 env->CP0_WatchLo[7] = 0;
13225 env->CP0_WatchHi[7] = 0;
13227 /* Count register increments in debug mode, EJTAG version 1 */
13228 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
13230 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
13231 int i;
13233 /* Only TC0 on VPE 0 starts as active. */
13234 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
13235 env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
13236 env->tcs[i].CP0_TCHalt = 1;
13238 env->active_tc.CP0_TCHalt = 1;
13239 env->halted = 1;
13241 if (!env->cpu_index) {
13242 /* VPE0 starts up enabled. */
13243 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
13244 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
13246 /* TC0 starts up unhalted. */
13247 env->halted = 0;
13248 env->active_tc.CP0_TCHalt = 0;
13249 env->tcs[0].CP0_TCHalt = 0;
13250 /* With thread 0 active. */
13251 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
13252 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
13255 #endif
13256 compute_hflags(env);
13257 env->exception_index = EXCP_NONE;
13260 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
13262 env->active_tc.PC = gen_opc_pc[pc_pos];
13263 env->hflags &= ~MIPS_HFLAG_BMASK;
13264 env->hflags |= gen_opc_hflags[pc_pos];