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