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