Sparc32: convert slavio interrupt controller to qdev
[qemu-kvm/fedora.git] / target-mips / translate.c
blob2eee11bd6419e94ce6a42bbab5bda5b0bc2d6906
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)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <inttypes.h>
29 #include "cpu.h"
30 #include "exec-all.h"
31 #include "disas.h"
32 #include "tcg-op.h"
33 #include "qemu-common.h"
35 #include "helper.h"
36 #define GEN_HELPER 1
37 #include "helper.h"
39 //#define MIPS_DEBUG_DISAS
40 //#define MIPS_DEBUG_SIGN_EXTENSIONS
42 /* MIPS major opcodes */
43 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
45 enum {
46 /* indirect opcode tables */
47 OPC_SPECIAL = (0x00 << 26),
48 OPC_REGIMM = (0x01 << 26),
49 OPC_CP0 = (0x10 << 26),
50 OPC_CP1 = (0x11 << 26),
51 OPC_CP2 = (0x12 << 26),
52 OPC_CP3 = (0x13 << 26),
53 OPC_SPECIAL2 = (0x1C << 26),
54 OPC_SPECIAL3 = (0x1F << 26),
55 /* arithmetic with immediate */
56 OPC_ADDI = (0x08 << 26),
57 OPC_ADDIU = (0x09 << 26),
58 OPC_SLTI = (0x0A << 26),
59 OPC_SLTIU = (0x0B << 26),
60 /* logic with immediate */
61 OPC_ANDI = (0x0C << 26),
62 OPC_ORI = (0x0D << 26),
63 OPC_XORI = (0x0E << 26),
64 OPC_LUI = (0x0F << 26),
65 /* arithmetic with immediate */
66 OPC_DADDI = (0x18 << 26),
67 OPC_DADDIU = (0x19 << 26),
68 /* Jump and branches */
69 OPC_J = (0x02 << 26),
70 OPC_JAL = (0x03 << 26),
71 OPC_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 /* Load and stores */
81 OPC_LDL = (0x1A << 26),
82 OPC_LDR = (0x1B << 26),
83 OPC_LB = (0x20 << 26),
84 OPC_LH = (0x21 << 26),
85 OPC_LWL = (0x22 << 26),
86 OPC_LW = (0x23 << 26),
87 OPC_LBU = (0x24 << 26),
88 OPC_LHU = (0x25 << 26),
89 OPC_LWR = (0x26 << 26),
90 OPC_LWU = (0x27 << 26),
91 OPC_SB = (0x28 << 26),
92 OPC_SH = (0x29 << 26),
93 OPC_SWL = (0x2A << 26),
94 OPC_SW = (0x2B << 26),
95 OPC_SDL = (0x2C << 26),
96 OPC_SDR = (0x2D << 26),
97 OPC_SWR = (0x2E << 26),
98 OPC_LL = (0x30 << 26),
99 OPC_LLD = (0x34 << 26),
100 OPC_LD = (0x37 << 26),
101 OPC_SC = (0x38 << 26),
102 OPC_SCD = (0x3C << 26),
103 OPC_SD = (0x3F << 26),
104 /* Floating point load/store */
105 OPC_LWC1 = (0x31 << 26),
106 OPC_LWC2 = (0x32 << 26),
107 OPC_LDC1 = (0x35 << 26),
108 OPC_LDC2 = (0x36 << 26),
109 OPC_SWC1 = (0x39 << 26),
110 OPC_SWC2 = (0x3A << 26),
111 OPC_SDC1 = (0x3D << 26),
112 OPC_SDC2 = (0x3E << 26),
113 /* MDMX ASE specific */
114 OPC_MDMX = (0x1E << 26),
115 /* Cache and prefetch */
116 OPC_CACHE = (0x2F << 26),
117 OPC_PREF = (0x33 << 26),
118 /* Reserved major opcode */
119 OPC_MAJOR3B_RESERVED = (0x3B << 26),
122 /* MIPS special opcodes */
123 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
125 enum {
126 /* Shifts */
127 OPC_SLL = 0x00 | OPC_SPECIAL,
128 /* NOP is SLL r0, r0, 0 */
129 /* SSNOP is SLL r0, r0, 1 */
130 /* EHB is SLL r0, r0, 3 */
131 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
132 OPC_SRA = 0x03 | OPC_SPECIAL,
133 OPC_SLLV = 0x04 | OPC_SPECIAL,
134 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
135 OPC_SRAV = 0x07 | OPC_SPECIAL,
136 OPC_DSLLV = 0x14 | OPC_SPECIAL,
137 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
138 OPC_DSRAV = 0x17 | OPC_SPECIAL,
139 OPC_DSLL = 0x38 | OPC_SPECIAL,
140 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
141 OPC_DSRA = 0x3B | OPC_SPECIAL,
142 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
143 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
144 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
145 /* Multiplication / division */
146 OPC_MULT = 0x18 | OPC_SPECIAL,
147 OPC_MULTU = 0x19 | OPC_SPECIAL,
148 OPC_DIV = 0x1A | OPC_SPECIAL,
149 OPC_DIVU = 0x1B | OPC_SPECIAL,
150 OPC_DMULT = 0x1C | OPC_SPECIAL,
151 OPC_DMULTU = 0x1D | OPC_SPECIAL,
152 OPC_DDIV = 0x1E | OPC_SPECIAL,
153 OPC_DDIVU = 0x1F | OPC_SPECIAL,
154 /* 2 registers arithmetic / logic */
155 OPC_ADD = 0x20 | OPC_SPECIAL,
156 OPC_ADDU = 0x21 | OPC_SPECIAL,
157 OPC_SUB = 0x22 | OPC_SPECIAL,
158 OPC_SUBU = 0x23 | OPC_SPECIAL,
159 OPC_AND = 0x24 | OPC_SPECIAL,
160 OPC_OR = 0x25 | OPC_SPECIAL,
161 OPC_XOR = 0x26 | OPC_SPECIAL,
162 OPC_NOR = 0x27 | OPC_SPECIAL,
163 OPC_SLT = 0x2A | OPC_SPECIAL,
164 OPC_SLTU = 0x2B | OPC_SPECIAL,
165 OPC_DADD = 0x2C | OPC_SPECIAL,
166 OPC_DADDU = 0x2D | OPC_SPECIAL,
167 OPC_DSUB = 0x2E | OPC_SPECIAL,
168 OPC_DSUBU = 0x2F | OPC_SPECIAL,
169 /* Jumps */
170 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
171 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
172 /* Traps */
173 OPC_TGE = 0x30 | OPC_SPECIAL,
174 OPC_TGEU = 0x31 | OPC_SPECIAL,
175 OPC_TLT = 0x32 | OPC_SPECIAL,
176 OPC_TLTU = 0x33 | OPC_SPECIAL,
177 OPC_TEQ = 0x34 | OPC_SPECIAL,
178 OPC_TNE = 0x36 | OPC_SPECIAL,
179 /* HI / LO registers load & stores */
180 OPC_MFHI = 0x10 | OPC_SPECIAL,
181 OPC_MTHI = 0x11 | OPC_SPECIAL,
182 OPC_MFLO = 0x12 | OPC_SPECIAL,
183 OPC_MTLO = 0x13 | OPC_SPECIAL,
184 /* Conditional moves */
185 OPC_MOVZ = 0x0A | OPC_SPECIAL,
186 OPC_MOVN = 0x0B | OPC_SPECIAL,
188 OPC_MOVCI = 0x01 | OPC_SPECIAL,
190 /* Special */
191 OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */
192 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
193 OPC_BREAK = 0x0D | OPC_SPECIAL,
194 OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */
195 OPC_SYNC = 0x0F | OPC_SPECIAL,
197 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
198 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
199 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
200 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
201 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
202 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
203 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
206 /* Multiplication variants of the vr54xx. */
207 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
209 enum {
210 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
211 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
212 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
213 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
214 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
215 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
216 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
217 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
218 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
219 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
220 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
221 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
222 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
223 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
226 /* REGIMM (rt field) opcodes */
227 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
229 enum {
230 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
231 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
232 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
233 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
234 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
235 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
236 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
237 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
238 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
239 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
240 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
241 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
242 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
243 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
244 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
247 /* Special2 opcodes */
248 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
250 enum {
251 /* Multiply & xxx operations */
252 OPC_MADD = 0x00 | OPC_SPECIAL2,
253 OPC_MADDU = 0x01 | OPC_SPECIAL2,
254 OPC_MUL = 0x02 | OPC_SPECIAL2,
255 OPC_MSUB = 0x04 | OPC_SPECIAL2,
256 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
257 /* Misc */
258 OPC_CLZ = 0x20 | OPC_SPECIAL2,
259 OPC_CLO = 0x21 | OPC_SPECIAL2,
260 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
261 OPC_DCLO = 0x25 | OPC_SPECIAL2,
262 /* Special */
263 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
266 /* Special3 opcodes */
267 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
269 enum {
270 OPC_EXT = 0x00 | OPC_SPECIAL3,
271 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
272 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
273 OPC_DEXT = 0x03 | OPC_SPECIAL3,
274 OPC_INS = 0x04 | OPC_SPECIAL3,
275 OPC_DINSM = 0x05 | OPC_SPECIAL3,
276 OPC_DINSU = 0x06 | OPC_SPECIAL3,
277 OPC_DINS = 0x07 | OPC_SPECIAL3,
278 OPC_FORK = 0x08 | OPC_SPECIAL3,
279 OPC_YIELD = 0x09 | OPC_SPECIAL3,
280 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
281 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
282 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
285 /* BSHFL opcodes */
286 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
288 enum {
289 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
290 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
291 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
294 /* DBSHFL opcodes */
295 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
297 enum {
298 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
299 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
302 /* Coprocessor 0 (rs field) */
303 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
305 enum {
306 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
307 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
308 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
309 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
310 OPC_MFTR = (0x08 << 21) | OPC_CP0,
311 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
312 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
313 OPC_MTTR = (0x0C << 21) | OPC_CP0,
314 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
315 OPC_C0 = (0x10 << 21) | OPC_CP0,
316 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
317 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
320 /* MFMC0 opcodes */
321 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
323 enum {
324 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
325 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
326 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
327 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
328 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
329 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
332 /* Coprocessor 0 (with rs == C0) */
333 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
335 enum {
336 OPC_TLBR = 0x01 | OPC_C0,
337 OPC_TLBWI = 0x02 | OPC_C0,
338 OPC_TLBWR = 0x06 | OPC_C0,
339 OPC_TLBP = 0x08 | OPC_C0,
340 OPC_RFE = 0x10 | OPC_C0,
341 OPC_ERET = 0x18 | OPC_C0,
342 OPC_DERET = 0x1F | OPC_C0,
343 OPC_WAIT = 0x20 | OPC_C0,
346 /* Coprocessor 1 (rs field) */
347 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
349 enum {
350 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
351 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
352 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
353 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
354 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
355 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
356 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
357 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
358 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
359 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
360 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
361 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
362 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
363 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
364 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
365 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
366 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
367 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
370 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
371 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
373 enum {
374 OPC_BC1F = (0x00 << 16) | OPC_BC1,
375 OPC_BC1T = (0x01 << 16) | OPC_BC1,
376 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
377 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
380 enum {
381 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
382 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
385 enum {
386 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
387 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
390 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
392 enum {
393 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
394 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
395 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
396 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
397 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
398 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
399 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
400 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
401 OPC_BC2 = (0x08 << 21) | OPC_CP2,
404 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
406 enum {
407 OPC_LWXC1 = 0x00 | OPC_CP3,
408 OPC_LDXC1 = 0x01 | OPC_CP3,
409 OPC_LUXC1 = 0x05 | OPC_CP3,
410 OPC_SWXC1 = 0x08 | OPC_CP3,
411 OPC_SDXC1 = 0x09 | OPC_CP3,
412 OPC_SUXC1 = 0x0D | OPC_CP3,
413 OPC_PREFX = 0x0F | OPC_CP3,
414 OPC_ALNV_PS = 0x1E | OPC_CP3,
415 OPC_MADD_S = 0x20 | OPC_CP3,
416 OPC_MADD_D = 0x21 | OPC_CP3,
417 OPC_MADD_PS = 0x26 | OPC_CP3,
418 OPC_MSUB_S = 0x28 | OPC_CP3,
419 OPC_MSUB_D = 0x29 | OPC_CP3,
420 OPC_MSUB_PS = 0x2E | OPC_CP3,
421 OPC_NMADD_S = 0x30 | OPC_CP3,
422 OPC_NMADD_D = 0x31 | OPC_CP3,
423 OPC_NMADD_PS= 0x36 | OPC_CP3,
424 OPC_NMSUB_S = 0x38 | OPC_CP3,
425 OPC_NMSUB_D = 0x39 | OPC_CP3,
426 OPC_NMSUB_PS= 0x3E | OPC_CP3,
429 /* global register indices */
430 static TCGv_ptr cpu_env;
431 static TCGv cpu_gpr[32], cpu_PC;
432 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
433 static TCGv cpu_dspctrl, btarget, bcond;
434 static TCGv_i32 hflags;
435 static TCGv_i32 fpu_fcr0, fpu_fcr31;
437 #include "gen-icount.h"
439 #define gen_helper_0i(name, arg) do { \
440 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
441 gen_helper_##name(helper_tmp); \
442 tcg_temp_free_i32(helper_tmp); \
443 } while(0)
445 #define gen_helper_1i(name, arg1, arg2) do { \
446 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
447 gen_helper_##name(arg1, helper_tmp); \
448 tcg_temp_free_i32(helper_tmp); \
449 } while(0)
451 #define gen_helper_2i(name, arg1, arg2, arg3) do { \
452 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
453 gen_helper_##name(arg1, arg2, helper_tmp); \
454 tcg_temp_free_i32(helper_tmp); \
455 } while(0)
457 #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
458 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
459 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
460 tcg_temp_free_i32(helper_tmp); \
461 } while(0)
463 typedef struct DisasContext {
464 struct TranslationBlock *tb;
465 target_ulong pc, saved_pc;
466 uint32_t opcode;
467 /* Routine used to access memory */
468 int mem_idx;
469 uint32_t hflags, saved_hflags;
470 int bstate;
471 target_ulong btarget;
472 } DisasContext;
474 enum {
475 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
476 * exception condition */
477 BS_STOP = 1, /* We want to stop translation for any reason */
478 BS_BRANCH = 2, /* We reached a branch condition */
479 BS_EXCP = 3, /* We reached an exception condition */
482 static const char *regnames[] =
483 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
484 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
485 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
486 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
488 static const char *regnames_HI[] =
489 { "HI0", "HI1", "HI2", "HI3", };
491 static const char *regnames_LO[] =
492 { "LO0", "LO1", "LO2", "LO3", };
494 static const char *regnames_ACX[] =
495 { "ACX0", "ACX1", "ACX2", "ACX3", };
497 static const char *fregnames[] =
498 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
499 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
500 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
501 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
503 #ifdef MIPS_DEBUG_DISAS
504 #define MIPS_DEBUG(fmt, ...) \
505 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
506 TARGET_FMT_lx ": %08x " fmt "\n", \
507 ctx->pc, ctx->opcode , ## __VA_ARGS__)
508 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
509 #else
510 #define MIPS_DEBUG(fmt, ...) do { } while(0)
511 #define LOG_DISAS(...) do { } while (0)
512 #endif
514 #define MIPS_INVAL(op) \
515 do { \
516 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
517 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
518 } while (0)
520 /* General purpose registers moves. */
521 static inline void gen_load_gpr (TCGv t, int reg)
523 if (reg == 0)
524 tcg_gen_movi_tl(t, 0);
525 else
526 tcg_gen_mov_tl(t, cpu_gpr[reg]);
529 static inline void gen_store_gpr (TCGv t, int reg)
531 if (reg != 0)
532 tcg_gen_mov_tl(cpu_gpr[reg], t);
535 /* Moves to/from ACX register. */
536 static inline void gen_load_ACX (TCGv t, int reg)
538 tcg_gen_mov_tl(t, cpu_ACX[reg]);
541 static inline void gen_store_ACX (TCGv t, int reg)
543 tcg_gen_mov_tl(cpu_ACX[reg], t);
546 /* Moves to/from shadow registers. */
547 static inline void gen_load_srsgpr (int from, int to)
549 TCGv t0 = tcg_temp_new();
551 if (from == 0)
552 tcg_gen_movi_tl(t0, 0);
553 else {
554 TCGv_i32 t2 = tcg_temp_new_i32();
555 TCGv_ptr addr = tcg_temp_new_ptr();
557 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
558 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
559 tcg_gen_andi_i32(t2, t2, 0xf);
560 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
561 tcg_gen_ext_i32_ptr(addr, t2);
562 tcg_gen_add_ptr(addr, cpu_env, addr);
564 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
565 tcg_temp_free_ptr(addr);
566 tcg_temp_free_i32(t2);
568 gen_store_gpr(t0, to);
569 tcg_temp_free(t0);
572 static inline void gen_store_srsgpr (int from, int to)
574 if (to != 0) {
575 TCGv t0 = tcg_temp_new();
576 TCGv_i32 t2 = tcg_temp_new_i32();
577 TCGv_ptr addr = tcg_temp_new_ptr();
579 gen_load_gpr(t0, from);
580 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
581 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
582 tcg_gen_andi_i32(t2, t2, 0xf);
583 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
584 tcg_gen_ext_i32_ptr(addr, t2);
585 tcg_gen_add_ptr(addr, cpu_env, addr);
587 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
588 tcg_temp_free_ptr(addr);
589 tcg_temp_free_i32(t2);
590 tcg_temp_free(t0);
594 /* Floating point register moves. */
595 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
597 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
600 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
602 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
605 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
607 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
610 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
612 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
615 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
617 if (ctx->hflags & MIPS_HFLAG_F64) {
618 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
619 } else {
620 TCGv_i32 t0 = tcg_temp_new_i32();
621 TCGv_i32 t1 = tcg_temp_new_i32();
622 gen_load_fpr32(t0, reg & ~1);
623 gen_load_fpr32(t1, reg | 1);
624 tcg_gen_concat_i32_i64(t, t0, t1);
625 tcg_temp_free_i32(t0);
626 tcg_temp_free_i32(t1);
630 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
632 if (ctx->hflags & MIPS_HFLAG_F64) {
633 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
634 } else {
635 TCGv_i64 t0 = tcg_temp_new_i64();
636 TCGv_i32 t1 = tcg_temp_new_i32();
637 tcg_gen_trunc_i64_i32(t1, t);
638 gen_store_fpr32(t1, reg & ~1);
639 tcg_gen_shri_i64(t0, t, 32);
640 tcg_gen_trunc_i64_i32(t1, t0);
641 gen_store_fpr32(t1, reg | 1);
642 tcg_temp_free_i32(t1);
643 tcg_temp_free_i64(t0);
647 static inline int get_fp_bit (int cc)
649 if (cc)
650 return 24 + cc;
651 else
652 return 23;
655 #define FOP_CONDS(type, fmt, bits) \
656 static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
657 TCGv_i##bits b, int cc) \
659 switch (n) { \
660 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
661 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
662 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
663 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
664 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
665 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
666 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
667 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
668 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
669 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
670 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
671 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
672 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
673 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
674 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
675 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
676 default: abort(); \
680 FOP_CONDS(, d, 64)
681 FOP_CONDS(abs, d, 64)
682 FOP_CONDS(, s, 32)
683 FOP_CONDS(abs, s, 32)
684 FOP_CONDS(, ps, 64)
685 FOP_CONDS(abs, ps, 64)
686 #undef FOP_CONDS
688 /* Tests */
689 #define OP_COND(name, cond) \
690 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, TCGv t1) \
692 int l1 = gen_new_label(); \
693 int l2 = gen_new_label(); \
695 tcg_gen_brcond_tl(cond, t0, t1, l1); \
696 tcg_gen_movi_tl(ret, 0); \
697 tcg_gen_br(l2); \
698 gen_set_label(l1); \
699 tcg_gen_movi_tl(ret, 1); \
700 gen_set_label(l2); \
702 OP_COND(eq, TCG_COND_EQ);
703 OP_COND(ne, TCG_COND_NE);
704 OP_COND(ge, TCG_COND_GE);
705 OP_COND(geu, TCG_COND_GEU);
706 OP_COND(lt, TCG_COND_LT);
707 OP_COND(ltu, TCG_COND_LTU);
708 #undef OP_COND
710 #define OP_CONDI(name, cond) \
711 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, target_ulong val) \
713 int l1 = gen_new_label(); \
714 int l2 = gen_new_label(); \
716 tcg_gen_brcondi_tl(cond, t0, val, l1); \
717 tcg_gen_movi_tl(ret, 0); \
718 tcg_gen_br(l2); \
719 gen_set_label(l1); \
720 tcg_gen_movi_tl(ret, 1); \
721 gen_set_label(l2); \
723 OP_CONDI(lti, TCG_COND_LT);
724 OP_CONDI(ltiu, TCG_COND_LTU);
725 #undef OP_CONDI
727 #define OP_CONDZ(name, cond) \
728 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0) \
730 int l1 = gen_new_label(); \
731 int l2 = gen_new_label(); \
733 tcg_gen_brcondi_tl(cond, t0, 0, l1); \
734 tcg_gen_movi_tl(ret, 0); \
735 tcg_gen_br(l2); \
736 gen_set_label(l1); \
737 tcg_gen_movi_tl(ret, 1); \
738 gen_set_label(l2); \
740 OP_CONDZ(gez, TCG_COND_GE);
741 OP_CONDZ(gtz, TCG_COND_GT);
742 OP_CONDZ(lez, TCG_COND_LE);
743 OP_CONDZ(ltz, TCG_COND_LT);
744 #undef OP_CONDZ
746 static inline void gen_save_pc(target_ulong pc)
748 tcg_gen_movi_tl(cpu_PC, pc);
751 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
753 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
754 if (do_save_pc && ctx->pc != ctx->saved_pc) {
755 gen_save_pc(ctx->pc);
756 ctx->saved_pc = ctx->pc;
758 if (ctx->hflags != ctx->saved_hflags) {
759 tcg_gen_movi_i32(hflags, ctx->hflags);
760 ctx->saved_hflags = ctx->hflags;
761 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
762 case MIPS_HFLAG_BR:
763 break;
764 case MIPS_HFLAG_BC:
765 case MIPS_HFLAG_BL:
766 case MIPS_HFLAG_B:
767 tcg_gen_movi_tl(btarget, ctx->btarget);
768 break;
773 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
775 ctx->saved_hflags = ctx->hflags;
776 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
777 case MIPS_HFLAG_BR:
778 break;
779 case MIPS_HFLAG_BC:
780 case MIPS_HFLAG_BL:
781 case MIPS_HFLAG_B:
782 ctx->btarget = env->btarget;
783 break;
787 static inline void
788 generate_exception_err (DisasContext *ctx, int excp, int err)
790 TCGv_i32 texcp = tcg_const_i32(excp);
791 TCGv_i32 terr = tcg_const_i32(err);
792 save_cpu_state(ctx, 1);
793 gen_helper_raise_exception_err(texcp, terr);
794 tcg_temp_free_i32(terr);
795 tcg_temp_free_i32(texcp);
798 static inline void
799 generate_exception (DisasContext *ctx, int excp)
801 save_cpu_state(ctx, 1);
802 gen_helper_0i(raise_exception, excp);
805 /* Addresses computation */
806 static inline void gen_op_addr_add (DisasContext *ctx, TCGv t0, TCGv t1)
808 tcg_gen_add_tl(t0, t0, t1);
810 #if defined(TARGET_MIPS64)
811 /* For compatibility with 32-bit code, data reference in user mode
812 with Status_UX = 0 should be casted to 32-bit and sign extended.
813 See the MIPS64 PRA manual, section 4.10. */
814 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
815 !(ctx->hflags & MIPS_HFLAG_UX)) {
816 tcg_gen_ext32s_i64(t0, t0);
818 #endif
821 static inline void check_cp0_enabled(DisasContext *ctx)
823 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
824 generate_exception_err(ctx, EXCP_CpU, 1);
827 static inline void check_cp1_enabled(DisasContext *ctx)
829 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
830 generate_exception_err(ctx, EXCP_CpU, 1);
833 /* Verify that the processor is running with COP1X instructions enabled.
834 This is associated with the nabla symbol in the MIPS32 and MIPS64
835 opcode tables. */
837 static inline void check_cop1x(DisasContext *ctx)
839 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
840 generate_exception(ctx, EXCP_RI);
843 /* Verify that the processor is running with 64-bit floating-point
844 operations enabled. */
846 static inline void check_cp1_64bitmode(DisasContext *ctx)
848 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
849 generate_exception(ctx, EXCP_RI);
853 * Verify if floating point register is valid; an operation is not defined
854 * if bit 0 of any register specification is set and the FR bit in the
855 * Status register equals zero, since the register numbers specify an
856 * even-odd pair of adjacent coprocessor general registers. When the FR bit
857 * in the Status register equals one, both even and odd register numbers
858 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
860 * Multiple 64 bit wide registers can be checked by calling
861 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
863 static inline void check_cp1_registers(DisasContext *ctx, int regs)
865 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
866 generate_exception(ctx, EXCP_RI);
869 /* This code generates a "reserved instruction" exception if the
870 CPU does not support the instruction set corresponding to flags. */
871 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
873 if (unlikely(!(env->insn_flags & flags)))
874 generate_exception(ctx, EXCP_RI);
877 /* This code generates a "reserved instruction" exception if 64-bit
878 instructions are not enabled. */
879 static inline void check_mips_64(DisasContext *ctx)
881 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
882 generate_exception(ctx, EXCP_RI);
885 /* load/store instructions. */
886 #define OP_LD(insn,fname) \
887 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
889 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
891 OP_LD(lb,ld8s);
892 OP_LD(lbu,ld8u);
893 OP_LD(lh,ld16s);
894 OP_LD(lhu,ld16u);
895 OP_LD(lw,ld32s);
896 #if defined(TARGET_MIPS64)
897 OP_LD(lwu,ld32u);
898 OP_LD(ld,ld64);
899 #endif
900 #undef OP_LD
902 #define OP_ST(insn,fname) \
903 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
905 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
907 OP_ST(sb,st8);
908 OP_ST(sh,st16);
909 OP_ST(sw,st32);
910 #if defined(TARGET_MIPS64)
911 OP_ST(sd,st64);
912 #endif
913 #undef OP_ST
915 #define OP_LD_ATOMIC(insn,fname) \
916 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
918 TCGv t0 = tcg_temp_new(); \
919 tcg_gen_mov_tl(t0, arg1); \
920 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
921 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
922 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
923 tcg_temp_free(t0); \
925 OP_LD_ATOMIC(ll,ld32s);
926 #if defined(TARGET_MIPS64)
927 OP_LD_ATOMIC(lld,ld64);
928 #endif
929 #undef OP_LD_ATOMIC
931 #ifdef CONFIG_USER_ONLY
932 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
933 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
935 TCGv t0 = tcg_temp_new(); \
936 int l1 = gen_new_label(); \
937 int l2 = gen_new_label(); \
939 tcg_gen_andi_tl(t0, arg2, almask); \
940 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
941 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
942 generate_exception(ctx, EXCP_AdES); \
943 gen_set_label(l1); \
944 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
945 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
946 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
947 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
948 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
949 gen_helper_0i(raise_exception, EXCP_SC); \
950 gen_set_label(l2); \
951 tcg_gen_movi_tl(t0, 0); \
952 gen_store_gpr(t0, rt); \
953 tcg_temp_free(t0); \
955 #else
956 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
957 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
959 TCGv t0 = tcg_temp_new(); \
960 TCGv t1 = tcg_temp_new(); \
961 int l1 = gen_new_label(); \
962 int l2 = gen_new_label(); \
963 int l3 = gen_new_label(); \
965 tcg_gen_andi_tl(t0, arg2, almask); \
966 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
967 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
968 generate_exception(ctx, EXCP_AdES); \
969 gen_set_label(l1); \
970 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
971 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
972 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, llval)); \
973 tcg_gen_qemu_##ldname(t1, arg2, ctx->mem_idx); \
974 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l2); \
975 tcg_temp_free(t1); \
976 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
977 tcg_gen_movi_tl(t0, 1); \
978 gen_store_gpr(t0, rt); \
979 tcg_gen_br(l3); \
980 gen_set_label(l2); \
981 tcg_gen_movi_tl(t0, 0); \
982 gen_store_gpr(t0, rt); \
983 gen_set_label(l3); \
984 tcg_temp_free(t0); \
986 #endif
988 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
989 #if defined(TARGET_MIPS64)
990 OP_ST_ATOMIC(scd,st64,ld64,0x7);
991 #endif
992 #undef OP_ST_ATOMIC
994 /* Load and store */
995 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
996 int base, int16_t offset)
998 const char *opn = "ldst";
999 TCGv t0 = tcg_temp_new();
1000 TCGv t1 = tcg_temp_new();
1002 if (base == 0) {
1003 tcg_gen_movi_tl(t0, offset);
1004 } else if (offset == 0) {
1005 gen_load_gpr(t0, base);
1006 } else {
1007 tcg_gen_movi_tl(t0, offset);
1008 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
1010 /* Don't do NOP if destination is zero: we must perform the actual
1011 memory access. */
1012 switch (opc) {
1013 #if defined(TARGET_MIPS64)
1014 case OPC_LWU:
1015 save_cpu_state(ctx, 0);
1016 op_ldst_lwu(t0, t0, ctx);
1017 gen_store_gpr(t0, rt);
1018 opn = "lwu";
1019 break;
1020 case OPC_LD:
1021 save_cpu_state(ctx, 0);
1022 op_ldst_ld(t0, t0, ctx);
1023 gen_store_gpr(t0, rt);
1024 opn = "ld";
1025 break;
1026 case OPC_LLD:
1027 save_cpu_state(ctx, 0);
1028 op_ldst_lld(t0, t0, ctx);
1029 gen_store_gpr(t0, rt);
1030 opn = "lld";
1031 break;
1032 case OPC_SD:
1033 save_cpu_state(ctx, 0);
1034 gen_load_gpr(t1, rt);
1035 op_ldst_sd(t1, t0, ctx);
1036 opn = "sd";
1037 break;
1038 case OPC_LDL:
1039 save_cpu_state(ctx, 1);
1040 gen_load_gpr(t1, rt);
1041 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1042 gen_store_gpr(t1, rt);
1043 opn = "ldl";
1044 break;
1045 case OPC_SDL:
1046 save_cpu_state(ctx, 1);
1047 gen_load_gpr(t1, rt);
1048 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1049 opn = "sdl";
1050 break;
1051 case OPC_LDR:
1052 save_cpu_state(ctx, 1);
1053 gen_load_gpr(t1, rt);
1054 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1055 gen_store_gpr(t1, rt);
1056 opn = "ldr";
1057 break;
1058 case OPC_SDR:
1059 save_cpu_state(ctx, 1);
1060 gen_load_gpr(t1, rt);
1061 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1062 opn = "sdr";
1063 break;
1064 #endif
1065 case OPC_LW:
1066 save_cpu_state(ctx, 0);
1067 op_ldst_lw(t0, t0, ctx);
1068 gen_store_gpr(t0, rt);
1069 opn = "lw";
1070 break;
1071 case OPC_SW:
1072 save_cpu_state(ctx, 0);
1073 gen_load_gpr(t1, rt);
1074 op_ldst_sw(t1, t0, ctx);
1075 opn = "sw";
1076 break;
1077 case OPC_LH:
1078 save_cpu_state(ctx, 0);
1079 op_ldst_lh(t0, t0, ctx);
1080 gen_store_gpr(t0, rt);
1081 opn = "lh";
1082 break;
1083 case OPC_SH:
1084 save_cpu_state(ctx, 0);
1085 gen_load_gpr(t1, rt);
1086 op_ldst_sh(t1, t0, ctx);
1087 opn = "sh";
1088 break;
1089 case OPC_LHU:
1090 save_cpu_state(ctx, 0);
1091 op_ldst_lhu(t0, t0, ctx);
1092 gen_store_gpr(t0, rt);
1093 opn = "lhu";
1094 break;
1095 case OPC_LB:
1096 save_cpu_state(ctx, 0);
1097 op_ldst_lb(t0, t0, ctx);
1098 gen_store_gpr(t0, rt);
1099 opn = "lb";
1100 break;
1101 case OPC_SB:
1102 save_cpu_state(ctx, 0);
1103 gen_load_gpr(t1, rt);
1104 op_ldst_sb(t1, t0, ctx);
1105 opn = "sb";
1106 break;
1107 case OPC_LBU:
1108 save_cpu_state(ctx, 0);
1109 op_ldst_lbu(t0, t0, ctx);
1110 gen_store_gpr(t0, rt);
1111 opn = "lbu";
1112 break;
1113 case OPC_LWL:
1114 save_cpu_state(ctx, 1);
1115 gen_load_gpr(t1, rt);
1116 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1117 gen_store_gpr(t1, rt);
1118 opn = "lwl";
1119 break;
1120 case OPC_SWL:
1121 save_cpu_state(ctx, 1);
1122 gen_load_gpr(t1, rt);
1123 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1124 opn = "swr";
1125 break;
1126 case OPC_LWR:
1127 save_cpu_state(ctx, 1);
1128 gen_load_gpr(t1, rt);
1129 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1130 gen_store_gpr(t1, rt);
1131 opn = "lwr";
1132 break;
1133 case OPC_SWR:
1134 save_cpu_state(ctx, 1);
1135 gen_load_gpr(t1, rt);
1136 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1137 opn = "swr";
1138 break;
1139 case OPC_LL:
1140 save_cpu_state(ctx, 0);
1141 op_ldst_ll(t0, t0, ctx);
1142 gen_store_gpr(t0, rt);
1143 opn = "ll";
1144 break;
1146 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1147 tcg_temp_free(t0);
1148 tcg_temp_free(t1);
1151 /* Store conditional */
1152 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1153 int base, int16_t offset)
1155 const char *opn = "st_cond";
1156 TCGv t0, t1;
1158 t0 = tcg_temp_local_new();
1160 if (base == 0) {
1161 tcg_gen_movi_tl(t0, offset);
1162 } else if (offset == 0) {
1163 gen_load_gpr(t0, base);
1164 } else {
1165 tcg_gen_movi_tl(t0, offset);
1166 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
1168 /* Don't do NOP if destination is zero: we must perform the actual
1169 memory access. */
1171 t1 = tcg_temp_local_new();
1172 gen_load_gpr(t1, rt);
1173 switch (opc) {
1174 #if defined(TARGET_MIPS64)
1175 case OPC_SCD:
1176 save_cpu_state(ctx, 0);
1177 op_ldst_scd(t1, t0, rt, ctx);
1178 opn = "scd";
1179 break;
1180 #endif
1181 case OPC_SC:
1182 save_cpu_state(ctx, 0);
1183 op_ldst_sc(t1, t0, rt, ctx);
1184 opn = "sc";
1185 break;
1187 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1188 tcg_temp_free(t1);
1189 tcg_temp_free(t0);
1192 /* Load and store */
1193 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1194 int base, int16_t offset)
1196 const char *opn = "flt_ldst";
1197 TCGv t0 = tcg_temp_new();
1199 if (base == 0) {
1200 tcg_gen_movi_tl(t0, offset);
1201 } else if (offset == 0) {
1202 gen_load_gpr(t0, base);
1203 } else {
1204 tcg_gen_movi_tl(t0, offset);
1205 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
1207 /* Don't do NOP if destination is zero: we must perform the actual
1208 memory access. */
1209 switch (opc) {
1210 case OPC_LWC1:
1212 TCGv_i32 fp0 = tcg_temp_new_i32();
1214 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1215 tcg_gen_trunc_tl_i32(fp0, t0);
1216 gen_store_fpr32(fp0, ft);
1217 tcg_temp_free_i32(fp0);
1219 opn = "lwc1";
1220 break;
1221 case OPC_SWC1:
1223 TCGv_i32 fp0 = tcg_temp_new_i32();
1224 TCGv t1 = tcg_temp_new();
1226 gen_load_fpr32(fp0, ft);
1227 tcg_gen_extu_i32_tl(t1, fp0);
1228 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1229 tcg_temp_free(t1);
1230 tcg_temp_free_i32(fp0);
1232 opn = "swc1";
1233 break;
1234 case OPC_LDC1:
1236 TCGv_i64 fp0 = tcg_temp_new_i64();
1238 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1239 gen_store_fpr64(ctx, fp0, ft);
1240 tcg_temp_free_i64(fp0);
1242 opn = "ldc1";
1243 break;
1244 case OPC_SDC1:
1246 TCGv_i64 fp0 = tcg_temp_new_i64();
1248 gen_load_fpr64(ctx, fp0, ft);
1249 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1250 tcg_temp_free_i64(fp0);
1252 opn = "sdc1";
1253 break;
1254 default:
1255 MIPS_INVAL(opn);
1256 generate_exception(ctx, EXCP_RI);
1257 goto out;
1259 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1260 out:
1261 tcg_temp_free(t0);
1264 /* Arithmetic with immediate operand */
1265 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1266 int rt, int rs, int16_t imm)
1268 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1269 const char *opn = "imm arith";
1271 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1272 /* If no destination, treat it as a NOP.
1273 For addi, we must generate the overflow exception when needed. */
1274 MIPS_DEBUG("NOP");
1275 return;
1277 switch (opc) {
1278 case OPC_ADDI:
1280 TCGv t0 = tcg_temp_local_new();
1281 TCGv t1 = tcg_temp_new();
1282 TCGv t2 = tcg_temp_new();
1283 int l1 = gen_new_label();
1285 gen_load_gpr(t1, rs);
1286 tcg_gen_addi_tl(t0, t1, uimm);
1287 tcg_gen_ext32s_tl(t0, t0);
1289 tcg_gen_xori_tl(t1, t1, ~uimm);
1290 tcg_gen_xori_tl(t2, t0, uimm);
1291 tcg_gen_and_tl(t1, t1, t2);
1292 tcg_temp_free(t2);
1293 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1294 tcg_temp_free(t1);
1295 /* operands of same sign, result different sign */
1296 generate_exception(ctx, EXCP_OVERFLOW);
1297 gen_set_label(l1);
1298 tcg_gen_ext32s_tl(t0, t0);
1299 gen_store_gpr(t0, rt);
1300 tcg_temp_free(t0);
1302 opn = "addi";
1303 break;
1304 case OPC_ADDIU:
1305 if (rs != 0) {
1306 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1307 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1308 } else {
1309 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1311 opn = "addiu";
1312 break;
1313 #if defined(TARGET_MIPS64)
1314 case OPC_DADDI:
1316 TCGv t0 = tcg_temp_local_new();
1317 TCGv t1 = tcg_temp_new();
1318 TCGv t2 = tcg_temp_new();
1319 int l1 = gen_new_label();
1321 gen_load_gpr(t1, rs);
1322 tcg_gen_addi_tl(t0, t1, uimm);
1324 tcg_gen_xori_tl(t1, t1, ~uimm);
1325 tcg_gen_xori_tl(t2, t0, uimm);
1326 tcg_gen_and_tl(t1, t1, t2);
1327 tcg_temp_free(t2);
1328 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1329 tcg_temp_free(t1);
1330 /* operands of same sign, result different sign */
1331 generate_exception(ctx, EXCP_OVERFLOW);
1332 gen_set_label(l1);
1333 gen_store_gpr(t0, rt);
1334 tcg_temp_free(t0);
1336 opn = "daddi";
1337 break;
1338 case OPC_DADDIU:
1339 if (rs != 0) {
1340 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1341 } else {
1342 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1344 opn = "daddiu";
1345 break;
1346 #endif
1348 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1351 /* Logic with immediate operand */
1352 static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1354 target_ulong uimm;
1355 const char *opn = "imm logic";
1357 if (rt == 0) {
1358 /* If no destination, treat it as a NOP. */
1359 MIPS_DEBUG("NOP");
1360 return;
1362 uimm = (uint16_t)imm;
1363 switch (opc) {
1364 case OPC_ANDI:
1365 if (likely(rs != 0))
1366 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1367 else
1368 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1369 opn = "andi";
1370 break;
1371 case OPC_ORI:
1372 if (rs != 0)
1373 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1374 else
1375 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1376 opn = "ori";
1377 break;
1378 case OPC_XORI:
1379 if (likely(rs != 0))
1380 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1381 else
1382 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1383 opn = "xori";
1384 break;
1385 case OPC_LUI:
1386 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1387 opn = "lui";
1388 break;
1390 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1393 /* Set on less than with immediate operand */
1394 static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1396 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1397 const char *opn = "imm arith";
1398 TCGv t0;
1400 if (rt == 0) {
1401 /* If no destination, treat it as a NOP. */
1402 MIPS_DEBUG("NOP");
1403 return;
1405 t0 = tcg_temp_new();
1406 gen_load_gpr(t0, rs);
1407 switch (opc) {
1408 case OPC_SLTI:
1409 gen_op_lti(cpu_gpr[rt], t0, uimm);
1410 opn = "slti";
1411 break;
1412 case OPC_SLTIU:
1413 gen_op_ltiu(cpu_gpr[rt], t0, uimm);
1414 opn = "sltiu";
1415 break;
1417 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1418 tcg_temp_free(t0);
1421 /* Shifts with immediate operand */
1422 static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1423 int rt, int rs, int16_t imm)
1425 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1426 const char *opn = "imm shift";
1427 TCGv t0;
1429 if (rt == 0) {
1430 /* If no destination, treat it as a NOP. */
1431 MIPS_DEBUG("NOP");
1432 return;
1435 t0 = tcg_temp_new();
1436 gen_load_gpr(t0, rs);
1437 switch (opc) {
1438 case OPC_SLL:
1439 tcg_gen_shli_tl(t0, t0, uimm);
1440 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1441 opn = "sll";
1442 break;
1443 case OPC_SRA:
1444 tcg_gen_ext32s_tl(t0, t0);
1445 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1446 opn = "sra";
1447 break;
1448 case OPC_SRL:
1449 switch ((ctx->opcode >> 21) & 0x1f) {
1450 case 0:
1451 if (uimm != 0) {
1452 tcg_gen_ext32u_tl(t0, t0);
1453 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1454 } else {
1455 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1457 opn = "srl";
1458 break;
1459 case 1:
1460 /* rotr is decoded as srl on non-R2 CPUs */
1461 if (env->insn_flags & ISA_MIPS32R2) {
1462 if (uimm != 0) {
1463 TCGv_i32 t1 = tcg_temp_new_i32();
1465 tcg_gen_trunc_tl_i32(t1, t0);
1466 tcg_gen_rotri_i32(t1, t1, uimm);
1467 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1468 tcg_temp_free_i32(t1);
1470 opn = "rotr";
1471 } else {
1472 if (uimm != 0) {
1473 tcg_gen_ext32u_tl(t0, t0);
1474 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1475 } else {
1476 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1478 opn = "srl";
1480 break;
1481 default:
1482 MIPS_INVAL("invalid srl flag");
1483 generate_exception(ctx, EXCP_RI);
1484 break;
1486 break;
1487 #if defined(TARGET_MIPS64)
1488 case OPC_DSLL:
1489 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1490 opn = "dsll";
1491 break;
1492 case OPC_DSRA:
1493 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1494 opn = "dsra";
1495 break;
1496 case OPC_DSRL:
1497 switch ((ctx->opcode >> 21) & 0x1f) {
1498 case 0:
1499 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1500 opn = "dsrl";
1501 break;
1502 case 1:
1503 /* drotr is decoded as dsrl on non-R2 CPUs */
1504 if (env->insn_flags & ISA_MIPS32R2) {
1505 if (uimm != 0) {
1506 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1508 opn = "drotr";
1509 } else {
1510 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1511 opn = "dsrl";
1513 break;
1514 default:
1515 MIPS_INVAL("invalid dsrl flag");
1516 generate_exception(ctx, EXCP_RI);
1517 break;
1519 break;
1520 case OPC_DSLL32:
1521 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1522 opn = "dsll32";
1523 break;
1524 case OPC_DSRA32:
1525 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1526 opn = "dsra32";
1527 break;
1528 case OPC_DSRL32:
1529 switch ((ctx->opcode >> 21) & 0x1f) {
1530 case 0:
1531 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1532 opn = "dsrl32";
1533 break;
1534 case 1:
1535 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1536 if (env->insn_flags & ISA_MIPS32R2) {
1537 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1538 opn = "drotr32";
1539 } else {
1540 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1541 opn = "dsrl32";
1543 break;
1544 default:
1545 MIPS_INVAL("invalid dsrl32 flag");
1546 generate_exception(ctx, EXCP_RI);
1547 break;
1549 break;
1550 #endif
1552 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1553 tcg_temp_free(t0);
1556 /* Arithmetic */
1557 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1558 int rd, int rs, int rt)
1560 const char *opn = "arith";
1562 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1563 && opc != OPC_DADD && opc != OPC_DSUB) {
1564 /* If no destination, treat it as a NOP.
1565 For add & sub, we must generate the overflow exception when needed. */
1566 MIPS_DEBUG("NOP");
1567 return;
1570 switch (opc) {
1571 case OPC_ADD:
1573 TCGv t0 = tcg_temp_local_new();
1574 TCGv t1 = tcg_temp_new();
1575 TCGv t2 = tcg_temp_new();
1576 int l1 = gen_new_label();
1578 gen_load_gpr(t1, rs);
1579 gen_load_gpr(t2, rt);
1580 tcg_gen_add_tl(t0, t1, t2);
1581 tcg_gen_ext32s_tl(t0, t0);
1582 tcg_gen_xor_tl(t1, t1, t2);
1583 tcg_gen_not_tl(t1, t1);
1584 tcg_gen_xor_tl(t2, t0, t2);
1585 tcg_gen_and_tl(t1, t1, t2);
1586 tcg_temp_free(t2);
1587 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1588 tcg_temp_free(t1);
1589 /* operands of same sign, result different sign */
1590 generate_exception(ctx, EXCP_OVERFLOW);
1591 gen_set_label(l1);
1592 gen_store_gpr(t0, rd);
1593 tcg_temp_free(t0);
1595 opn = "add";
1596 break;
1597 case OPC_ADDU:
1598 if (rs != 0 && rt != 0) {
1599 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1600 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1601 } else if (rs == 0 && rt != 0) {
1602 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1603 } else if (rs != 0 && rt == 0) {
1604 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1605 } else {
1606 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1608 opn = "addu";
1609 break;
1610 case OPC_SUB:
1612 TCGv t0 = tcg_temp_local_new();
1613 TCGv t1 = tcg_temp_new();
1614 TCGv t2 = tcg_temp_new();
1615 int l1 = gen_new_label();
1617 gen_load_gpr(t1, rs);
1618 gen_load_gpr(t2, rt);
1619 tcg_gen_sub_tl(t0, t1, t2);
1620 tcg_gen_ext32s_tl(t0, t0);
1621 tcg_gen_xor_tl(t2, t1, t2);
1622 tcg_gen_xor_tl(t1, t0, t1);
1623 tcg_gen_and_tl(t1, t1, t2);
1624 tcg_temp_free(t2);
1625 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1626 tcg_temp_free(t1);
1627 /* operands of different sign, first operand and result different sign */
1628 generate_exception(ctx, EXCP_OVERFLOW);
1629 gen_set_label(l1);
1630 gen_store_gpr(t0, rd);
1631 tcg_temp_free(t0);
1633 opn = "sub";
1634 break;
1635 case OPC_SUBU:
1636 if (rs != 0 && rt != 0) {
1637 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1638 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1639 } else if (rs == 0 && rt != 0) {
1640 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1641 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1642 } else if (rs != 0 && rt == 0) {
1643 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1644 } else {
1645 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1647 opn = "subu";
1648 break;
1649 #if defined(TARGET_MIPS64)
1650 case OPC_DADD:
1652 TCGv t0 = tcg_temp_local_new();
1653 TCGv t1 = tcg_temp_new();
1654 TCGv t2 = tcg_temp_new();
1655 int l1 = gen_new_label();
1657 gen_load_gpr(t1, rs);
1658 gen_load_gpr(t2, rt);
1659 tcg_gen_add_tl(t0, t1, t2);
1660 tcg_gen_xor_tl(t1, t1, t2);
1661 tcg_gen_not_tl(t1, t1);
1662 tcg_gen_xor_tl(t2, t0, t2);
1663 tcg_gen_and_tl(t1, t1, t2);
1664 tcg_temp_free(t2);
1665 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1666 tcg_temp_free(t1);
1667 /* operands of same sign, result different sign */
1668 generate_exception(ctx, EXCP_OVERFLOW);
1669 gen_set_label(l1);
1670 gen_store_gpr(t0, rd);
1671 tcg_temp_free(t0);
1673 opn = "dadd";
1674 break;
1675 case OPC_DADDU:
1676 if (rs != 0 && rt != 0) {
1677 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1678 } else if (rs == 0 && rt != 0) {
1679 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1680 } else if (rs != 0 && rt == 0) {
1681 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1682 } else {
1683 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1685 opn = "daddu";
1686 break;
1687 case OPC_DSUB:
1689 TCGv t0 = tcg_temp_local_new();
1690 TCGv t1 = tcg_temp_new();
1691 TCGv t2 = tcg_temp_new();
1692 int l1 = gen_new_label();
1694 gen_load_gpr(t1, rs);
1695 gen_load_gpr(t2, rt);
1696 tcg_gen_sub_tl(t0, t1, t2);
1697 tcg_gen_xor_tl(t2, t1, t2);
1698 tcg_gen_xor_tl(t1, t0, t1);
1699 tcg_gen_and_tl(t1, t1, t2);
1700 tcg_temp_free(t2);
1701 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1702 tcg_temp_free(t1);
1703 /* operands of different sign, first operand and result different sign */
1704 generate_exception(ctx, EXCP_OVERFLOW);
1705 gen_set_label(l1);
1706 gen_store_gpr(t0, rd);
1707 tcg_temp_free(t0);
1709 opn = "dsub";
1710 break;
1711 case OPC_DSUBU:
1712 if (rs != 0 && rt != 0) {
1713 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1714 } else if (rs == 0 && rt != 0) {
1715 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1716 } else if (rs != 0 && rt == 0) {
1717 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1718 } else {
1719 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1721 opn = "dsubu";
1722 break;
1723 #endif
1724 case OPC_MUL:
1725 if (likely(rs != 0 && rt != 0)) {
1726 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1727 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1728 } else {
1729 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1731 opn = "mul";
1732 break;
1734 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1737 /* Conditional move */
1738 static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1740 const char *opn = "cond move";
1741 int l1;
1743 if (rd == 0) {
1744 /* If no destination, treat it as a NOP.
1745 For add & sub, we must generate the overflow exception when needed. */
1746 MIPS_DEBUG("NOP");
1747 return;
1750 l1 = gen_new_label();
1751 switch (opc) {
1752 case OPC_MOVN:
1753 if (likely(rt != 0))
1754 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1755 else
1756 tcg_gen_br(l1);
1757 opn = "movn";
1758 break;
1759 case OPC_MOVZ:
1760 if (likely(rt != 0))
1761 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1762 opn = "movz";
1763 break;
1765 if (rs != 0)
1766 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1767 else
1768 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1769 gen_set_label(l1);
1771 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1774 /* Logic */
1775 static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1777 const char *opn = "logic";
1779 if (rd == 0) {
1780 /* If no destination, treat it as a NOP. */
1781 MIPS_DEBUG("NOP");
1782 return;
1785 switch (opc) {
1786 case OPC_AND:
1787 if (likely(rs != 0 && rt != 0)) {
1788 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1789 } else {
1790 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1792 opn = "and";
1793 break;
1794 case OPC_NOR:
1795 if (rs != 0 && rt != 0) {
1796 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1797 } else if (rs == 0 && rt != 0) {
1798 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1799 } else if (rs != 0 && rt == 0) {
1800 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1801 } else {
1802 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1804 opn = "nor";
1805 break;
1806 case OPC_OR:
1807 if (likely(rs != 0 && rt != 0)) {
1808 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1809 } else if (rs == 0 && rt != 0) {
1810 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1811 } else if (rs != 0 && rt == 0) {
1812 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1813 } else {
1814 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1816 opn = "or";
1817 break;
1818 case OPC_XOR:
1819 if (likely(rs != 0 && rt != 0)) {
1820 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1821 } else if (rs == 0 && rt != 0) {
1822 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1823 } else if (rs != 0 && rt == 0) {
1824 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1825 } else {
1826 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1828 opn = "xor";
1829 break;
1831 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1834 /* Set on lower than */
1835 static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1837 const char *opn = "slt";
1838 TCGv t0, t1;
1840 if (rd == 0) {
1841 /* If no destination, treat it as a NOP. */
1842 MIPS_DEBUG("NOP");
1843 return;
1846 t0 = tcg_temp_new();
1847 t1 = tcg_temp_new();
1848 gen_load_gpr(t0, rs);
1849 gen_load_gpr(t1, rt);
1850 switch (opc) {
1851 case OPC_SLT:
1852 gen_op_lt(cpu_gpr[rd], t0, t1);
1853 opn = "slt";
1854 break;
1855 case OPC_SLTU:
1856 gen_op_ltu(cpu_gpr[rd], t0, t1);
1857 opn = "sltu";
1858 break;
1860 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1861 tcg_temp_free(t0);
1862 tcg_temp_free(t1);
1865 /* Shifts */
1866 static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1867 int rd, int rs, int rt)
1869 const char *opn = "shifts";
1870 TCGv t0, t1;
1872 if (rd == 0) {
1873 /* If no destination, treat it as a NOP.
1874 For add & sub, we must generate the overflow exception when needed. */
1875 MIPS_DEBUG("NOP");
1876 return;
1879 t0 = tcg_temp_new();
1880 t1 = tcg_temp_new();
1881 gen_load_gpr(t0, rs);
1882 gen_load_gpr(t1, rt);
1883 switch (opc) {
1884 case OPC_SLLV:
1885 tcg_gen_andi_tl(t0, t0, 0x1f);
1886 tcg_gen_shl_tl(t0, t1, t0);
1887 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1888 opn = "sllv";
1889 break;
1890 case OPC_SRAV:
1891 tcg_gen_ext32s_tl(t1, t1);
1892 tcg_gen_andi_tl(t0, t0, 0x1f);
1893 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1894 opn = "srav";
1895 break;
1896 case OPC_SRLV:
1897 switch ((ctx->opcode >> 6) & 0x1f) {
1898 case 0:
1899 tcg_gen_ext32u_tl(t1, t1);
1900 tcg_gen_andi_tl(t0, t0, 0x1f);
1901 tcg_gen_shr_tl(t0, t1, t0);
1902 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1903 opn = "srlv";
1904 break;
1905 case 1:
1906 /* rotrv is decoded as srlv on non-R2 CPUs */
1907 if (env->insn_flags & ISA_MIPS32R2) {
1908 TCGv_i32 t2 = tcg_temp_new_i32();
1909 TCGv_i32 t3 = tcg_temp_new_i32();
1911 tcg_gen_trunc_tl_i32(t2, t0);
1912 tcg_gen_trunc_tl_i32(t3, t1);
1913 tcg_gen_andi_i32(t2, t2, 0x1f);
1914 tcg_gen_rotr_i32(t2, t3, t2);
1915 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1916 tcg_temp_free_i32(t2);
1917 tcg_temp_free_i32(t3);
1918 opn = "rotrv";
1919 } else {
1920 tcg_gen_ext32u_tl(t1, t1);
1921 tcg_gen_andi_tl(t0, t0, 0x1f);
1922 tcg_gen_shr_tl(t0, t1, t0);
1923 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1924 opn = "srlv";
1926 break;
1927 default:
1928 MIPS_INVAL("invalid srlv flag");
1929 generate_exception(ctx, EXCP_RI);
1930 break;
1932 break;
1933 #if defined(TARGET_MIPS64)
1934 case OPC_DSLLV:
1935 tcg_gen_andi_tl(t0, t0, 0x3f);
1936 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1937 opn = "dsllv";
1938 break;
1939 case OPC_DSRAV:
1940 tcg_gen_andi_tl(t0, t0, 0x3f);
1941 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1942 opn = "dsrav";
1943 break;
1944 case OPC_DSRLV:
1945 switch ((ctx->opcode >> 6) & 0x1f) {
1946 case 0:
1947 tcg_gen_andi_tl(t0, t0, 0x3f);
1948 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1949 opn = "dsrlv";
1950 break;
1951 case 1:
1952 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1953 if (env->insn_flags & ISA_MIPS32R2) {
1954 tcg_gen_andi_tl(t0, t0, 0x3f);
1955 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1956 opn = "drotrv";
1957 } else {
1958 tcg_gen_andi_tl(t0, t0, 0x3f);
1959 tcg_gen_shr_tl(t0, t1, t0);
1960 opn = "dsrlv";
1962 break;
1963 default:
1964 MIPS_INVAL("invalid dsrlv flag");
1965 generate_exception(ctx, EXCP_RI);
1966 break;
1968 break;
1969 #endif
1971 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1972 tcg_temp_free(t0);
1973 tcg_temp_free(t1);
1976 /* Arithmetic on HI/LO registers */
1977 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1979 const char *opn = "hilo";
1981 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1982 /* Treat as NOP. */
1983 MIPS_DEBUG("NOP");
1984 return;
1986 switch (opc) {
1987 case OPC_MFHI:
1988 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1989 opn = "mfhi";
1990 break;
1991 case OPC_MFLO:
1992 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1993 opn = "mflo";
1994 break;
1995 case OPC_MTHI:
1996 if (reg != 0)
1997 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1998 else
1999 tcg_gen_movi_tl(cpu_HI[0], 0);
2000 opn = "mthi";
2001 break;
2002 case OPC_MTLO:
2003 if (reg != 0)
2004 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2005 else
2006 tcg_gen_movi_tl(cpu_LO[0], 0);
2007 opn = "mtlo";
2008 break;
2010 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2013 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
2014 int rs, int rt)
2016 const char *opn = "mul/div";
2017 TCGv t0, t1;
2019 switch (opc) {
2020 case OPC_DIV:
2021 case OPC_DIVU:
2022 #if defined(TARGET_MIPS64)
2023 case OPC_DDIV:
2024 case OPC_DDIVU:
2025 #endif
2026 t0 = tcg_temp_local_new();
2027 t1 = tcg_temp_local_new();
2028 break;
2029 default:
2030 t0 = tcg_temp_new();
2031 t1 = tcg_temp_new();
2032 break;
2035 gen_load_gpr(t0, rs);
2036 gen_load_gpr(t1, rt);
2037 switch (opc) {
2038 case OPC_DIV:
2040 int l1 = gen_new_label();
2041 int l2 = gen_new_label();
2043 tcg_gen_ext32s_tl(t0, t0);
2044 tcg_gen_ext32s_tl(t1, t1);
2045 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2046 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2047 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2049 tcg_gen_mov_tl(cpu_LO[0], t0);
2050 tcg_gen_movi_tl(cpu_HI[0], 0);
2051 tcg_gen_br(l1);
2052 gen_set_label(l2);
2053 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2054 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2055 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2056 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2057 gen_set_label(l1);
2059 opn = "div";
2060 break;
2061 case OPC_DIVU:
2063 int l1 = gen_new_label();
2065 tcg_gen_ext32u_tl(t0, t0);
2066 tcg_gen_ext32u_tl(t1, t1);
2067 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2068 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2069 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2070 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2071 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2072 gen_set_label(l1);
2074 opn = "divu";
2075 break;
2076 case OPC_MULT:
2078 TCGv_i64 t2 = tcg_temp_new_i64();
2079 TCGv_i64 t3 = tcg_temp_new_i64();
2081 tcg_gen_ext_tl_i64(t2, t0);
2082 tcg_gen_ext_tl_i64(t3, t1);
2083 tcg_gen_mul_i64(t2, t2, t3);
2084 tcg_temp_free_i64(t3);
2085 tcg_gen_trunc_i64_tl(t0, t2);
2086 tcg_gen_shri_i64(t2, t2, 32);
2087 tcg_gen_trunc_i64_tl(t1, t2);
2088 tcg_temp_free_i64(t2);
2089 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2090 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2092 opn = "mult";
2093 break;
2094 case OPC_MULTU:
2096 TCGv_i64 t2 = tcg_temp_new_i64();
2097 TCGv_i64 t3 = tcg_temp_new_i64();
2099 tcg_gen_ext32u_tl(t0, t0);
2100 tcg_gen_ext32u_tl(t1, t1);
2101 tcg_gen_extu_tl_i64(t2, t0);
2102 tcg_gen_extu_tl_i64(t3, t1);
2103 tcg_gen_mul_i64(t2, t2, t3);
2104 tcg_temp_free_i64(t3);
2105 tcg_gen_trunc_i64_tl(t0, t2);
2106 tcg_gen_shri_i64(t2, t2, 32);
2107 tcg_gen_trunc_i64_tl(t1, t2);
2108 tcg_temp_free_i64(t2);
2109 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2110 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2112 opn = "multu";
2113 break;
2114 #if defined(TARGET_MIPS64)
2115 case OPC_DDIV:
2117 int l1 = gen_new_label();
2118 int l2 = gen_new_label();
2120 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2121 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2122 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2123 tcg_gen_mov_tl(cpu_LO[0], t0);
2124 tcg_gen_movi_tl(cpu_HI[0], 0);
2125 tcg_gen_br(l1);
2126 gen_set_label(l2);
2127 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2128 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2129 gen_set_label(l1);
2131 opn = "ddiv";
2132 break;
2133 case OPC_DDIVU:
2135 int l1 = gen_new_label();
2137 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2138 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2139 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2140 gen_set_label(l1);
2142 opn = "ddivu";
2143 break;
2144 case OPC_DMULT:
2145 gen_helper_dmult(t0, t1);
2146 opn = "dmult";
2147 break;
2148 case OPC_DMULTU:
2149 gen_helper_dmultu(t0, t1);
2150 opn = "dmultu";
2151 break;
2152 #endif
2153 case OPC_MADD:
2155 TCGv_i64 t2 = tcg_temp_new_i64();
2156 TCGv_i64 t3 = tcg_temp_new_i64();
2158 tcg_gen_ext_tl_i64(t2, t0);
2159 tcg_gen_ext_tl_i64(t3, t1);
2160 tcg_gen_mul_i64(t2, t2, t3);
2161 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2162 tcg_gen_add_i64(t2, t2, t3);
2163 tcg_temp_free_i64(t3);
2164 tcg_gen_trunc_i64_tl(t0, t2);
2165 tcg_gen_shri_i64(t2, t2, 32);
2166 tcg_gen_trunc_i64_tl(t1, t2);
2167 tcg_temp_free_i64(t2);
2168 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2169 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2171 opn = "madd";
2172 break;
2173 case OPC_MADDU:
2175 TCGv_i64 t2 = tcg_temp_new_i64();
2176 TCGv_i64 t3 = tcg_temp_new_i64();
2178 tcg_gen_ext32u_tl(t0, t0);
2179 tcg_gen_ext32u_tl(t1, t1);
2180 tcg_gen_extu_tl_i64(t2, t0);
2181 tcg_gen_extu_tl_i64(t3, t1);
2182 tcg_gen_mul_i64(t2, t2, t3);
2183 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2184 tcg_gen_add_i64(t2, t2, t3);
2185 tcg_temp_free_i64(t3);
2186 tcg_gen_trunc_i64_tl(t0, t2);
2187 tcg_gen_shri_i64(t2, t2, 32);
2188 tcg_gen_trunc_i64_tl(t1, t2);
2189 tcg_temp_free_i64(t2);
2190 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2191 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2193 opn = "maddu";
2194 break;
2195 case OPC_MSUB:
2197 TCGv_i64 t2 = tcg_temp_new_i64();
2198 TCGv_i64 t3 = tcg_temp_new_i64();
2200 tcg_gen_ext_tl_i64(t2, t0);
2201 tcg_gen_ext_tl_i64(t3, t1);
2202 tcg_gen_mul_i64(t2, t2, t3);
2203 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2204 tcg_gen_sub_i64(t2, t3, t2);
2205 tcg_temp_free_i64(t3);
2206 tcg_gen_trunc_i64_tl(t0, t2);
2207 tcg_gen_shri_i64(t2, t2, 32);
2208 tcg_gen_trunc_i64_tl(t1, t2);
2209 tcg_temp_free_i64(t2);
2210 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2211 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2213 opn = "msub";
2214 break;
2215 case OPC_MSUBU:
2217 TCGv_i64 t2 = tcg_temp_new_i64();
2218 TCGv_i64 t3 = tcg_temp_new_i64();
2220 tcg_gen_ext32u_tl(t0, t0);
2221 tcg_gen_ext32u_tl(t1, t1);
2222 tcg_gen_extu_tl_i64(t2, t0);
2223 tcg_gen_extu_tl_i64(t3, t1);
2224 tcg_gen_mul_i64(t2, t2, t3);
2225 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2226 tcg_gen_sub_i64(t2, t3, t2);
2227 tcg_temp_free_i64(t3);
2228 tcg_gen_trunc_i64_tl(t0, t2);
2229 tcg_gen_shri_i64(t2, t2, 32);
2230 tcg_gen_trunc_i64_tl(t1, t2);
2231 tcg_temp_free_i64(t2);
2232 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2233 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2235 opn = "msubu";
2236 break;
2237 default:
2238 MIPS_INVAL(opn);
2239 generate_exception(ctx, EXCP_RI);
2240 goto out;
2242 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2243 out:
2244 tcg_temp_free(t0);
2245 tcg_temp_free(t1);
2248 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2249 int rd, int rs, int rt)
2251 const char *opn = "mul vr54xx";
2252 TCGv t0 = tcg_temp_new();
2253 TCGv t1 = tcg_temp_new();
2255 gen_load_gpr(t0, rs);
2256 gen_load_gpr(t1, rt);
2258 switch (opc) {
2259 case OPC_VR54XX_MULS:
2260 gen_helper_muls(t0, t0, t1);
2261 opn = "muls";
2262 break;
2263 case OPC_VR54XX_MULSU:
2264 gen_helper_mulsu(t0, t0, t1);
2265 opn = "mulsu";
2266 break;
2267 case OPC_VR54XX_MACC:
2268 gen_helper_macc(t0, t0, t1);
2269 opn = "macc";
2270 break;
2271 case OPC_VR54XX_MACCU:
2272 gen_helper_maccu(t0, t0, t1);
2273 opn = "maccu";
2274 break;
2275 case OPC_VR54XX_MSAC:
2276 gen_helper_msac(t0, t0, t1);
2277 opn = "msac";
2278 break;
2279 case OPC_VR54XX_MSACU:
2280 gen_helper_msacu(t0, t0, t1);
2281 opn = "msacu";
2282 break;
2283 case OPC_VR54XX_MULHI:
2284 gen_helper_mulhi(t0, t0, t1);
2285 opn = "mulhi";
2286 break;
2287 case OPC_VR54XX_MULHIU:
2288 gen_helper_mulhiu(t0, t0, t1);
2289 opn = "mulhiu";
2290 break;
2291 case OPC_VR54XX_MULSHI:
2292 gen_helper_mulshi(t0, t0, t1);
2293 opn = "mulshi";
2294 break;
2295 case OPC_VR54XX_MULSHIU:
2296 gen_helper_mulshiu(t0, t0, t1);
2297 opn = "mulshiu";
2298 break;
2299 case OPC_VR54XX_MACCHI:
2300 gen_helper_macchi(t0, t0, t1);
2301 opn = "macchi";
2302 break;
2303 case OPC_VR54XX_MACCHIU:
2304 gen_helper_macchiu(t0, t0, t1);
2305 opn = "macchiu";
2306 break;
2307 case OPC_VR54XX_MSACHI:
2308 gen_helper_msachi(t0, t0, t1);
2309 opn = "msachi";
2310 break;
2311 case OPC_VR54XX_MSACHIU:
2312 gen_helper_msachiu(t0, t0, t1);
2313 opn = "msachiu";
2314 break;
2315 default:
2316 MIPS_INVAL("mul vr54xx");
2317 generate_exception(ctx, EXCP_RI);
2318 goto out;
2320 gen_store_gpr(t0, rd);
2321 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2323 out:
2324 tcg_temp_free(t0);
2325 tcg_temp_free(t1);
2328 static void gen_cl (DisasContext *ctx, uint32_t opc,
2329 int rd, int rs)
2331 const char *opn = "CLx";
2332 TCGv t0;
2334 if (rd == 0) {
2335 /* Treat as NOP. */
2336 MIPS_DEBUG("NOP");
2337 return;
2339 t0 = tcg_temp_new();
2340 gen_load_gpr(t0, rs);
2341 switch (opc) {
2342 case OPC_CLO:
2343 gen_helper_clo(cpu_gpr[rd], t0);
2344 opn = "clo";
2345 break;
2346 case OPC_CLZ:
2347 gen_helper_clz(cpu_gpr[rd], t0);
2348 opn = "clz";
2349 break;
2350 #if defined(TARGET_MIPS64)
2351 case OPC_DCLO:
2352 gen_helper_dclo(cpu_gpr[rd], t0);
2353 opn = "dclo";
2354 break;
2355 case OPC_DCLZ:
2356 gen_helper_dclz(cpu_gpr[rd], t0);
2357 opn = "dclz";
2358 break;
2359 #endif
2361 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2362 tcg_temp_free(t0);
2365 /* Traps */
2366 static void gen_trap (DisasContext *ctx, uint32_t opc,
2367 int rs, int rt, int16_t imm)
2369 int cond;
2370 TCGv t0 = tcg_temp_new();
2371 TCGv t1 = tcg_temp_new();
2373 cond = 0;
2374 /* Load needed operands */
2375 switch (opc) {
2376 case OPC_TEQ:
2377 case OPC_TGE:
2378 case OPC_TGEU:
2379 case OPC_TLT:
2380 case OPC_TLTU:
2381 case OPC_TNE:
2382 /* Compare two registers */
2383 if (rs != rt) {
2384 gen_load_gpr(t0, rs);
2385 gen_load_gpr(t1, rt);
2386 cond = 1;
2388 break;
2389 case OPC_TEQI:
2390 case OPC_TGEI:
2391 case OPC_TGEIU:
2392 case OPC_TLTI:
2393 case OPC_TLTIU:
2394 case OPC_TNEI:
2395 /* Compare register to immediate */
2396 if (rs != 0 || imm != 0) {
2397 gen_load_gpr(t0, rs);
2398 tcg_gen_movi_tl(t1, (int32_t)imm);
2399 cond = 1;
2401 break;
2403 if (cond == 0) {
2404 switch (opc) {
2405 case OPC_TEQ: /* rs == rs */
2406 case OPC_TEQI: /* r0 == 0 */
2407 case OPC_TGE: /* rs >= rs */
2408 case OPC_TGEI: /* r0 >= 0 */
2409 case OPC_TGEU: /* rs >= rs unsigned */
2410 case OPC_TGEIU: /* r0 >= 0 unsigned */
2411 /* Always trap */
2412 generate_exception(ctx, EXCP_TRAP);
2413 break;
2414 case OPC_TLT: /* rs < rs */
2415 case OPC_TLTI: /* r0 < 0 */
2416 case OPC_TLTU: /* rs < rs unsigned */
2417 case OPC_TLTIU: /* r0 < 0 unsigned */
2418 case OPC_TNE: /* rs != rs */
2419 case OPC_TNEI: /* r0 != 0 */
2420 /* Never trap: treat as NOP. */
2421 break;
2423 } else {
2424 int l1 = gen_new_label();
2426 switch (opc) {
2427 case OPC_TEQ:
2428 case OPC_TEQI:
2429 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2430 break;
2431 case OPC_TGE:
2432 case OPC_TGEI:
2433 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2434 break;
2435 case OPC_TGEU:
2436 case OPC_TGEIU:
2437 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2438 break;
2439 case OPC_TLT:
2440 case OPC_TLTI:
2441 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2442 break;
2443 case OPC_TLTU:
2444 case OPC_TLTIU:
2445 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2446 break;
2447 case OPC_TNE:
2448 case OPC_TNEI:
2449 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2450 break;
2452 generate_exception(ctx, EXCP_TRAP);
2453 gen_set_label(l1);
2455 tcg_temp_free(t0);
2456 tcg_temp_free(t1);
2459 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2461 TranslationBlock *tb;
2462 tb = ctx->tb;
2463 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2464 tcg_gen_goto_tb(n);
2465 gen_save_pc(dest);
2466 tcg_gen_exit_tb((long)tb + n);
2467 } else {
2468 gen_save_pc(dest);
2469 tcg_gen_exit_tb(0);
2473 /* Branches (before delay slot) */
2474 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2475 int rs, int rt, int32_t offset)
2477 target_ulong btgt = -1;
2478 int blink = 0;
2479 int bcond_compute = 0;
2480 TCGv t0 = tcg_temp_new();
2481 TCGv t1 = tcg_temp_new();
2483 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2484 #ifdef MIPS_DEBUG_DISAS
2485 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2486 #endif
2487 generate_exception(ctx, EXCP_RI);
2488 goto out;
2491 /* Load needed operands */
2492 switch (opc) {
2493 case OPC_BEQ:
2494 case OPC_BEQL:
2495 case OPC_BNE:
2496 case OPC_BNEL:
2497 /* Compare two registers */
2498 if (rs != rt) {
2499 gen_load_gpr(t0, rs);
2500 gen_load_gpr(t1, rt);
2501 bcond_compute = 1;
2503 btgt = ctx->pc + 4 + offset;
2504 break;
2505 case OPC_BGEZ:
2506 case OPC_BGEZAL:
2507 case OPC_BGEZALL:
2508 case OPC_BGEZL:
2509 case OPC_BGTZ:
2510 case OPC_BGTZL:
2511 case OPC_BLEZ:
2512 case OPC_BLEZL:
2513 case OPC_BLTZ:
2514 case OPC_BLTZAL:
2515 case OPC_BLTZALL:
2516 case OPC_BLTZL:
2517 /* Compare to zero */
2518 if (rs != 0) {
2519 gen_load_gpr(t0, rs);
2520 bcond_compute = 1;
2522 btgt = ctx->pc + 4 + offset;
2523 break;
2524 case OPC_J:
2525 case OPC_JAL:
2526 /* Jump to immediate */
2527 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2528 break;
2529 case OPC_JR:
2530 case OPC_JALR:
2531 /* Jump to register */
2532 if (offset != 0 && offset != 16) {
2533 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2534 others are reserved. */
2535 MIPS_INVAL("jump hint");
2536 generate_exception(ctx, EXCP_RI);
2537 goto out;
2539 gen_load_gpr(btarget, rs);
2540 break;
2541 default:
2542 MIPS_INVAL("branch/jump");
2543 generate_exception(ctx, EXCP_RI);
2544 goto out;
2546 if (bcond_compute == 0) {
2547 /* No condition to be computed */
2548 switch (opc) {
2549 case OPC_BEQ: /* rx == rx */
2550 case OPC_BEQL: /* rx == rx likely */
2551 case OPC_BGEZ: /* 0 >= 0 */
2552 case OPC_BGEZL: /* 0 >= 0 likely */
2553 case OPC_BLEZ: /* 0 <= 0 */
2554 case OPC_BLEZL: /* 0 <= 0 likely */
2555 /* Always take */
2556 ctx->hflags |= MIPS_HFLAG_B;
2557 MIPS_DEBUG("balways");
2558 break;
2559 case OPC_BGEZAL: /* 0 >= 0 */
2560 case OPC_BGEZALL: /* 0 >= 0 likely */
2561 /* Always take and link */
2562 blink = 31;
2563 ctx->hflags |= MIPS_HFLAG_B;
2564 MIPS_DEBUG("balways and link");
2565 break;
2566 case OPC_BNE: /* rx != rx */
2567 case OPC_BGTZ: /* 0 > 0 */
2568 case OPC_BLTZ: /* 0 < 0 */
2569 /* Treat as NOP. */
2570 MIPS_DEBUG("bnever (NOP)");
2571 goto out;
2572 case OPC_BLTZAL: /* 0 < 0 */
2573 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2574 MIPS_DEBUG("bnever and link");
2575 goto out;
2576 case OPC_BLTZALL: /* 0 < 0 likely */
2577 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2578 /* Skip the instruction in the delay slot */
2579 MIPS_DEBUG("bnever, link and skip");
2580 ctx->pc += 4;
2581 goto out;
2582 case OPC_BNEL: /* rx != rx likely */
2583 case OPC_BGTZL: /* 0 > 0 likely */
2584 case OPC_BLTZL: /* 0 < 0 likely */
2585 /* Skip the instruction in the delay slot */
2586 MIPS_DEBUG("bnever and skip");
2587 ctx->pc += 4;
2588 goto out;
2589 case OPC_J:
2590 ctx->hflags |= MIPS_HFLAG_B;
2591 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2592 break;
2593 case OPC_JAL:
2594 blink = 31;
2595 ctx->hflags |= MIPS_HFLAG_B;
2596 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2597 break;
2598 case OPC_JR:
2599 ctx->hflags |= MIPS_HFLAG_BR;
2600 MIPS_DEBUG("jr %s", regnames[rs]);
2601 break;
2602 case OPC_JALR:
2603 blink = rt;
2604 ctx->hflags |= MIPS_HFLAG_BR;
2605 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2606 break;
2607 default:
2608 MIPS_INVAL("branch/jump");
2609 generate_exception(ctx, EXCP_RI);
2610 goto out;
2612 } else {
2613 switch (opc) {
2614 case OPC_BEQ:
2615 gen_op_eq(bcond, t0, t1);
2616 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2617 regnames[rs], regnames[rt], btgt);
2618 goto not_likely;
2619 case OPC_BEQL:
2620 gen_op_eq(bcond, t0, t1);
2621 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2622 regnames[rs], regnames[rt], btgt);
2623 goto likely;
2624 case OPC_BNE:
2625 gen_op_ne(bcond, t0, t1);
2626 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2627 regnames[rs], regnames[rt], btgt);
2628 goto not_likely;
2629 case OPC_BNEL:
2630 gen_op_ne(bcond, t0, t1);
2631 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2632 regnames[rs], regnames[rt], btgt);
2633 goto likely;
2634 case OPC_BGEZ:
2635 gen_op_gez(bcond, t0);
2636 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2637 goto not_likely;
2638 case OPC_BGEZL:
2639 gen_op_gez(bcond, t0);
2640 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2641 goto likely;
2642 case OPC_BGEZAL:
2643 gen_op_gez(bcond, t0);
2644 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2645 blink = 31;
2646 goto not_likely;
2647 case OPC_BGEZALL:
2648 gen_op_gez(bcond, t0);
2649 blink = 31;
2650 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2651 goto likely;
2652 case OPC_BGTZ:
2653 gen_op_gtz(bcond, t0);
2654 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2655 goto not_likely;
2656 case OPC_BGTZL:
2657 gen_op_gtz(bcond, t0);
2658 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2659 goto likely;
2660 case OPC_BLEZ:
2661 gen_op_lez(bcond, t0);
2662 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2663 goto not_likely;
2664 case OPC_BLEZL:
2665 gen_op_lez(bcond, t0);
2666 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2667 goto likely;
2668 case OPC_BLTZ:
2669 gen_op_ltz(bcond, t0);
2670 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2671 goto not_likely;
2672 case OPC_BLTZL:
2673 gen_op_ltz(bcond, t0);
2674 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2675 goto likely;
2676 case OPC_BLTZAL:
2677 gen_op_ltz(bcond, t0);
2678 blink = 31;
2679 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2680 not_likely:
2681 ctx->hflags |= MIPS_HFLAG_BC;
2682 break;
2683 case OPC_BLTZALL:
2684 gen_op_ltz(bcond, t0);
2685 blink = 31;
2686 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2687 likely:
2688 ctx->hflags |= MIPS_HFLAG_BL;
2689 break;
2690 default:
2691 MIPS_INVAL("conditional branch/jump");
2692 generate_exception(ctx, EXCP_RI);
2693 goto out;
2696 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2697 blink, ctx->hflags, btgt);
2699 ctx->btarget = btgt;
2700 if (blink > 0) {
2701 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8);
2704 out:
2705 tcg_temp_free(t0);
2706 tcg_temp_free(t1);
2709 /* special3 bitfield operations */
2710 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2711 int rs, int lsb, int msb)
2713 TCGv t0 = tcg_temp_new();
2714 TCGv t1 = tcg_temp_new();
2715 target_ulong mask;
2717 gen_load_gpr(t1, rs);
2718 switch (opc) {
2719 case OPC_EXT:
2720 if (lsb + msb > 31)
2721 goto fail;
2722 tcg_gen_shri_tl(t0, t1, lsb);
2723 if (msb != 31) {
2724 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2725 } else {
2726 tcg_gen_ext32s_tl(t0, t0);
2728 break;
2729 #if defined(TARGET_MIPS64)
2730 case OPC_DEXTM:
2731 tcg_gen_shri_tl(t0, t1, lsb);
2732 if (msb != 31) {
2733 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2735 break;
2736 case OPC_DEXTU:
2737 tcg_gen_shri_tl(t0, t1, lsb + 32);
2738 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2739 break;
2740 case OPC_DEXT:
2741 tcg_gen_shri_tl(t0, t1, lsb);
2742 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2743 break;
2744 #endif
2745 case OPC_INS:
2746 if (lsb > msb)
2747 goto fail;
2748 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2749 gen_load_gpr(t0, rt);
2750 tcg_gen_andi_tl(t0, t0, ~mask);
2751 tcg_gen_shli_tl(t1, t1, lsb);
2752 tcg_gen_andi_tl(t1, t1, mask);
2753 tcg_gen_or_tl(t0, t0, t1);
2754 tcg_gen_ext32s_tl(t0, t0);
2755 break;
2756 #if defined(TARGET_MIPS64)
2757 case OPC_DINSM:
2758 if (lsb > msb)
2759 goto fail;
2760 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2761 gen_load_gpr(t0, rt);
2762 tcg_gen_andi_tl(t0, t0, ~mask);
2763 tcg_gen_shli_tl(t1, t1, lsb);
2764 tcg_gen_andi_tl(t1, t1, mask);
2765 tcg_gen_or_tl(t0, t0, t1);
2766 break;
2767 case OPC_DINSU:
2768 if (lsb > msb)
2769 goto fail;
2770 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2771 gen_load_gpr(t0, rt);
2772 tcg_gen_andi_tl(t0, t0, ~mask);
2773 tcg_gen_shli_tl(t1, t1, lsb + 32);
2774 tcg_gen_andi_tl(t1, t1, mask);
2775 tcg_gen_or_tl(t0, t0, t1);
2776 break;
2777 case OPC_DINS:
2778 if (lsb > msb)
2779 goto fail;
2780 gen_load_gpr(t0, rt);
2781 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2782 gen_load_gpr(t0, rt);
2783 tcg_gen_andi_tl(t0, t0, ~mask);
2784 tcg_gen_shli_tl(t1, t1, lsb);
2785 tcg_gen_andi_tl(t1, t1, mask);
2786 tcg_gen_or_tl(t0, t0, t1);
2787 break;
2788 #endif
2789 default:
2790 fail:
2791 MIPS_INVAL("bitops");
2792 generate_exception(ctx, EXCP_RI);
2793 tcg_temp_free(t0);
2794 tcg_temp_free(t1);
2795 return;
2797 gen_store_gpr(t0, rt);
2798 tcg_temp_free(t0);
2799 tcg_temp_free(t1);
2802 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2804 TCGv t0;
2806 if (rd == 0) {
2807 /* If no destination, treat it as a NOP. */
2808 MIPS_DEBUG("NOP");
2809 return;
2812 t0 = tcg_temp_new();
2813 gen_load_gpr(t0, rt);
2814 switch (op2) {
2815 case OPC_WSBH:
2817 TCGv t1 = tcg_temp_new();
2819 tcg_gen_shri_tl(t1, t0, 8);
2820 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2821 tcg_gen_shli_tl(t0, t0, 8);
2822 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2823 tcg_gen_or_tl(t0, t0, t1);
2824 tcg_temp_free(t1);
2825 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2827 break;
2828 case OPC_SEB:
2829 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2830 break;
2831 case OPC_SEH:
2832 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2833 break;
2834 #if defined(TARGET_MIPS64)
2835 case OPC_DSBH:
2837 TCGv t1 = tcg_temp_new();
2839 tcg_gen_shri_tl(t1, t0, 8);
2840 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2841 tcg_gen_shli_tl(t0, t0, 8);
2842 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2843 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2844 tcg_temp_free(t1);
2846 break;
2847 case OPC_DSHD:
2849 TCGv t1 = tcg_temp_new();
2851 tcg_gen_shri_tl(t1, t0, 16);
2852 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2853 tcg_gen_shli_tl(t0, t0, 16);
2854 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2855 tcg_gen_or_tl(t0, t0, t1);
2856 tcg_gen_shri_tl(t1, t0, 32);
2857 tcg_gen_shli_tl(t0, t0, 32);
2858 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2859 tcg_temp_free(t1);
2861 break;
2862 #endif
2863 default:
2864 MIPS_INVAL("bsfhl");
2865 generate_exception(ctx, EXCP_RI);
2866 tcg_temp_free(t0);
2867 return;
2869 tcg_temp_free(t0);
2872 #ifndef CONFIG_USER_ONLY
2873 /* CP0 (MMU and control) */
2874 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
2876 TCGv_i32 t0 = tcg_temp_new_i32();
2878 tcg_gen_ld_i32(t0, cpu_env, off);
2879 tcg_gen_ext_i32_tl(arg, t0);
2880 tcg_temp_free_i32(t0);
2883 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
2885 tcg_gen_ld_tl(arg, cpu_env, off);
2886 tcg_gen_ext32s_tl(arg, arg);
2889 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
2891 TCGv_i32 t0 = tcg_temp_new_i32();
2893 tcg_gen_trunc_tl_i32(t0, arg);
2894 tcg_gen_st_i32(t0, cpu_env, off);
2895 tcg_temp_free_i32(t0);
2898 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
2900 tcg_gen_ext32s_tl(arg, arg);
2901 tcg_gen_st_tl(arg, cpu_env, off);
2904 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
2906 const char *rn = "invalid";
2908 if (sel != 0)
2909 check_insn(env, ctx, ISA_MIPS32);
2911 switch (reg) {
2912 case 0:
2913 switch (sel) {
2914 case 0:
2915 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
2916 rn = "Index";
2917 break;
2918 case 1:
2919 check_insn(env, ctx, ASE_MT);
2920 gen_helper_mfc0_mvpcontrol(arg);
2921 rn = "MVPControl";
2922 break;
2923 case 2:
2924 check_insn(env, ctx, ASE_MT);
2925 gen_helper_mfc0_mvpconf0(arg);
2926 rn = "MVPConf0";
2927 break;
2928 case 3:
2929 check_insn(env, ctx, ASE_MT);
2930 gen_helper_mfc0_mvpconf1(arg);
2931 rn = "MVPConf1";
2932 break;
2933 default:
2934 goto die;
2936 break;
2937 case 1:
2938 switch (sel) {
2939 case 0:
2940 gen_helper_mfc0_random(arg);
2941 rn = "Random";
2942 break;
2943 case 1:
2944 check_insn(env, ctx, ASE_MT);
2945 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
2946 rn = "VPEControl";
2947 break;
2948 case 2:
2949 check_insn(env, ctx, ASE_MT);
2950 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
2951 rn = "VPEConf0";
2952 break;
2953 case 3:
2954 check_insn(env, ctx, ASE_MT);
2955 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
2956 rn = "VPEConf1";
2957 break;
2958 case 4:
2959 check_insn(env, ctx, ASE_MT);
2960 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
2961 rn = "YQMask";
2962 break;
2963 case 5:
2964 check_insn(env, ctx, ASE_MT);
2965 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
2966 rn = "VPESchedule";
2967 break;
2968 case 6:
2969 check_insn(env, ctx, ASE_MT);
2970 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
2971 rn = "VPEScheFBack";
2972 break;
2973 case 7:
2974 check_insn(env, ctx, ASE_MT);
2975 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
2976 rn = "VPEOpt";
2977 break;
2978 default:
2979 goto die;
2981 break;
2982 case 2:
2983 switch (sel) {
2984 case 0:
2985 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2986 tcg_gen_ext32s_tl(arg, arg);
2987 rn = "EntryLo0";
2988 break;
2989 case 1:
2990 check_insn(env, ctx, ASE_MT);
2991 gen_helper_mfc0_tcstatus(arg);
2992 rn = "TCStatus";
2993 break;
2994 case 2:
2995 check_insn(env, ctx, ASE_MT);
2996 gen_helper_mfc0_tcbind(arg);
2997 rn = "TCBind";
2998 break;
2999 case 3:
3000 check_insn(env, ctx, ASE_MT);
3001 gen_helper_mfc0_tcrestart(arg);
3002 rn = "TCRestart";
3003 break;
3004 case 4:
3005 check_insn(env, ctx, ASE_MT);
3006 gen_helper_mfc0_tchalt(arg);
3007 rn = "TCHalt";
3008 break;
3009 case 5:
3010 check_insn(env, ctx, ASE_MT);
3011 gen_helper_mfc0_tccontext(arg);
3012 rn = "TCContext";
3013 break;
3014 case 6:
3015 check_insn(env, ctx, ASE_MT);
3016 gen_helper_mfc0_tcschedule(arg);
3017 rn = "TCSchedule";
3018 break;
3019 case 7:
3020 check_insn(env, ctx, ASE_MT);
3021 gen_helper_mfc0_tcschefback(arg);
3022 rn = "TCScheFBack";
3023 break;
3024 default:
3025 goto die;
3027 break;
3028 case 3:
3029 switch (sel) {
3030 case 0:
3031 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
3032 tcg_gen_ext32s_tl(arg, arg);
3033 rn = "EntryLo1";
3034 break;
3035 default:
3036 goto die;
3038 break;
3039 case 4:
3040 switch (sel) {
3041 case 0:
3042 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3043 tcg_gen_ext32s_tl(arg, arg);
3044 rn = "Context";
3045 break;
3046 case 1:
3047 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3048 rn = "ContextConfig";
3049 // break;
3050 default:
3051 goto die;
3053 break;
3054 case 5:
3055 switch (sel) {
3056 case 0:
3057 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
3058 rn = "PageMask";
3059 break;
3060 case 1:
3061 check_insn(env, ctx, ISA_MIPS32R2);
3062 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
3063 rn = "PageGrain";
3064 break;
3065 default:
3066 goto die;
3068 break;
3069 case 6:
3070 switch (sel) {
3071 case 0:
3072 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
3073 rn = "Wired";
3074 break;
3075 case 1:
3076 check_insn(env, ctx, ISA_MIPS32R2);
3077 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
3078 rn = "SRSConf0";
3079 break;
3080 case 2:
3081 check_insn(env, ctx, ISA_MIPS32R2);
3082 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
3083 rn = "SRSConf1";
3084 break;
3085 case 3:
3086 check_insn(env, ctx, ISA_MIPS32R2);
3087 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
3088 rn = "SRSConf2";
3089 break;
3090 case 4:
3091 check_insn(env, ctx, ISA_MIPS32R2);
3092 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
3093 rn = "SRSConf3";
3094 break;
3095 case 5:
3096 check_insn(env, ctx, ISA_MIPS32R2);
3097 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
3098 rn = "SRSConf4";
3099 break;
3100 default:
3101 goto die;
3103 break;
3104 case 7:
3105 switch (sel) {
3106 case 0:
3107 check_insn(env, ctx, ISA_MIPS32R2);
3108 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
3109 rn = "HWREna";
3110 break;
3111 default:
3112 goto die;
3114 break;
3115 case 8:
3116 switch (sel) {
3117 case 0:
3118 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3119 tcg_gen_ext32s_tl(arg, arg);
3120 rn = "BadVAddr";
3121 break;
3122 default:
3123 goto die;
3125 break;
3126 case 9:
3127 switch (sel) {
3128 case 0:
3129 /* Mark as an IO operation because we read the time. */
3130 if (use_icount)
3131 gen_io_start();
3132 gen_helper_mfc0_count(arg);
3133 if (use_icount) {
3134 gen_io_end();
3135 ctx->bstate = BS_STOP;
3137 rn = "Count";
3138 break;
3139 /* 6,7 are implementation dependent */
3140 default:
3141 goto die;
3143 break;
3144 case 10:
3145 switch (sel) {
3146 case 0:
3147 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3148 tcg_gen_ext32s_tl(arg, arg);
3149 rn = "EntryHi";
3150 break;
3151 default:
3152 goto die;
3154 break;
3155 case 11:
3156 switch (sel) {
3157 case 0:
3158 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
3159 rn = "Compare";
3160 break;
3161 /* 6,7 are implementation dependent */
3162 default:
3163 goto die;
3165 break;
3166 case 12:
3167 switch (sel) {
3168 case 0:
3169 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
3170 rn = "Status";
3171 break;
3172 case 1:
3173 check_insn(env, ctx, ISA_MIPS32R2);
3174 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
3175 rn = "IntCtl";
3176 break;
3177 case 2:
3178 check_insn(env, ctx, ISA_MIPS32R2);
3179 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
3180 rn = "SRSCtl";
3181 break;
3182 case 3:
3183 check_insn(env, ctx, ISA_MIPS32R2);
3184 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
3185 rn = "SRSMap";
3186 break;
3187 default:
3188 goto die;
3190 break;
3191 case 13:
3192 switch (sel) {
3193 case 0:
3194 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
3195 rn = "Cause";
3196 break;
3197 default:
3198 goto die;
3200 break;
3201 case 14:
3202 switch (sel) {
3203 case 0:
3204 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3205 tcg_gen_ext32s_tl(arg, arg);
3206 rn = "EPC";
3207 break;
3208 default:
3209 goto die;
3211 break;
3212 case 15:
3213 switch (sel) {
3214 case 0:
3215 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
3216 rn = "PRid";
3217 break;
3218 case 1:
3219 check_insn(env, ctx, ISA_MIPS32R2);
3220 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
3221 rn = "EBase";
3222 break;
3223 default:
3224 goto die;
3226 break;
3227 case 16:
3228 switch (sel) {
3229 case 0:
3230 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
3231 rn = "Config";
3232 break;
3233 case 1:
3234 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
3235 rn = "Config1";
3236 break;
3237 case 2:
3238 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
3239 rn = "Config2";
3240 break;
3241 case 3:
3242 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
3243 rn = "Config3";
3244 break;
3245 /* 4,5 are reserved */
3246 /* 6,7 are implementation dependent */
3247 case 6:
3248 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
3249 rn = "Config6";
3250 break;
3251 case 7:
3252 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
3253 rn = "Config7";
3254 break;
3255 default:
3256 goto die;
3258 break;
3259 case 17:
3260 switch (sel) {
3261 case 0:
3262 gen_helper_mfc0_lladdr(arg);
3263 rn = "LLAddr";
3264 break;
3265 default:
3266 goto die;
3268 break;
3269 case 18:
3270 switch (sel) {
3271 case 0 ... 7:
3272 gen_helper_1i(mfc0_watchlo, arg, sel);
3273 rn = "WatchLo";
3274 break;
3275 default:
3276 goto die;
3278 break;
3279 case 19:
3280 switch (sel) {
3281 case 0 ...7:
3282 gen_helper_1i(mfc0_watchhi, arg, sel);
3283 rn = "WatchHi";
3284 break;
3285 default:
3286 goto die;
3288 break;
3289 case 20:
3290 switch (sel) {
3291 case 0:
3292 #if defined(TARGET_MIPS64)
3293 check_insn(env, ctx, ISA_MIPS3);
3294 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3295 tcg_gen_ext32s_tl(arg, arg);
3296 rn = "XContext";
3297 break;
3298 #endif
3299 default:
3300 goto die;
3302 break;
3303 case 21:
3304 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3305 switch (sel) {
3306 case 0:
3307 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
3308 rn = "Framemask";
3309 break;
3310 default:
3311 goto die;
3313 break;
3314 case 22:
3315 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3316 rn = "'Diagnostic"; /* implementation dependent */
3317 break;
3318 case 23:
3319 switch (sel) {
3320 case 0:
3321 gen_helper_mfc0_debug(arg); /* EJTAG support */
3322 rn = "Debug";
3323 break;
3324 case 1:
3325 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3326 rn = "TraceControl";
3327 // break;
3328 case 2:
3329 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3330 rn = "TraceControl2";
3331 // break;
3332 case 3:
3333 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3334 rn = "UserTraceData";
3335 // break;
3336 case 4:
3337 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3338 rn = "TraceBPC";
3339 // break;
3340 default:
3341 goto die;
3343 break;
3344 case 24:
3345 switch (sel) {
3346 case 0:
3347 /* EJTAG support */
3348 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3349 tcg_gen_ext32s_tl(arg, arg);
3350 rn = "DEPC";
3351 break;
3352 default:
3353 goto die;
3355 break;
3356 case 25:
3357 switch (sel) {
3358 case 0:
3359 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
3360 rn = "Performance0";
3361 break;
3362 case 1:
3363 // gen_helper_mfc0_performance1(arg);
3364 rn = "Performance1";
3365 // break;
3366 case 2:
3367 // gen_helper_mfc0_performance2(arg);
3368 rn = "Performance2";
3369 // break;
3370 case 3:
3371 // gen_helper_mfc0_performance3(arg);
3372 rn = "Performance3";
3373 // break;
3374 case 4:
3375 // gen_helper_mfc0_performance4(arg);
3376 rn = "Performance4";
3377 // break;
3378 case 5:
3379 // gen_helper_mfc0_performance5(arg);
3380 rn = "Performance5";
3381 // break;
3382 case 6:
3383 // gen_helper_mfc0_performance6(arg);
3384 rn = "Performance6";
3385 // break;
3386 case 7:
3387 // gen_helper_mfc0_performance7(arg);
3388 rn = "Performance7";
3389 // break;
3390 default:
3391 goto die;
3393 break;
3394 case 26:
3395 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3396 rn = "ECC";
3397 break;
3398 case 27:
3399 switch (sel) {
3400 case 0 ... 3:
3401 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3402 rn = "CacheErr";
3403 break;
3404 default:
3405 goto die;
3407 break;
3408 case 28:
3409 switch (sel) {
3410 case 0:
3411 case 2:
3412 case 4:
3413 case 6:
3414 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
3415 rn = "TagLo";
3416 break;
3417 case 1:
3418 case 3:
3419 case 5:
3420 case 7:
3421 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
3422 rn = "DataLo";
3423 break;
3424 default:
3425 goto die;
3427 break;
3428 case 29:
3429 switch (sel) {
3430 case 0:
3431 case 2:
3432 case 4:
3433 case 6:
3434 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
3435 rn = "TagHi";
3436 break;
3437 case 1:
3438 case 3:
3439 case 5:
3440 case 7:
3441 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
3442 rn = "DataHi";
3443 break;
3444 default:
3445 goto die;
3447 break;
3448 case 30:
3449 switch (sel) {
3450 case 0:
3451 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3452 tcg_gen_ext32s_tl(arg, arg);
3453 rn = "ErrorEPC";
3454 break;
3455 default:
3456 goto die;
3458 break;
3459 case 31:
3460 switch (sel) {
3461 case 0:
3462 /* EJTAG support */
3463 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
3464 rn = "DESAVE";
3465 break;
3466 default:
3467 goto die;
3469 break;
3470 default:
3471 goto die;
3473 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3474 return;
3476 die:
3477 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3478 generate_exception(ctx, EXCP_RI);
3481 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3483 const char *rn = "invalid";
3485 if (sel != 0)
3486 check_insn(env, ctx, ISA_MIPS32);
3488 if (use_icount)
3489 gen_io_start();
3491 switch (reg) {
3492 case 0:
3493 switch (sel) {
3494 case 0:
3495 gen_helper_mtc0_index(arg);
3496 rn = "Index";
3497 break;
3498 case 1:
3499 check_insn(env, ctx, ASE_MT);
3500 gen_helper_mtc0_mvpcontrol(arg);
3501 rn = "MVPControl";
3502 break;
3503 case 2:
3504 check_insn(env, ctx, ASE_MT);
3505 /* ignored */
3506 rn = "MVPConf0";
3507 break;
3508 case 3:
3509 check_insn(env, ctx, ASE_MT);
3510 /* ignored */
3511 rn = "MVPConf1";
3512 break;
3513 default:
3514 goto die;
3516 break;
3517 case 1:
3518 switch (sel) {
3519 case 0:
3520 /* ignored */
3521 rn = "Random";
3522 break;
3523 case 1:
3524 check_insn(env, ctx, ASE_MT);
3525 gen_helper_mtc0_vpecontrol(arg);
3526 rn = "VPEControl";
3527 break;
3528 case 2:
3529 check_insn(env, ctx, ASE_MT);
3530 gen_helper_mtc0_vpeconf0(arg);
3531 rn = "VPEConf0";
3532 break;
3533 case 3:
3534 check_insn(env, ctx, ASE_MT);
3535 gen_helper_mtc0_vpeconf1(arg);
3536 rn = "VPEConf1";
3537 break;
3538 case 4:
3539 check_insn(env, ctx, ASE_MT);
3540 gen_helper_mtc0_yqmask(arg);
3541 rn = "YQMask";
3542 break;
3543 case 5:
3544 check_insn(env, ctx, ASE_MT);
3545 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
3546 rn = "VPESchedule";
3547 break;
3548 case 6:
3549 check_insn(env, ctx, ASE_MT);
3550 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3551 rn = "VPEScheFBack";
3552 break;
3553 case 7:
3554 check_insn(env, ctx, ASE_MT);
3555 gen_helper_mtc0_vpeopt(arg);
3556 rn = "VPEOpt";
3557 break;
3558 default:
3559 goto die;
3561 break;
3562 case 2:
3563 switch (sel) {
3564 case 0:
3565 gen_helper_mtc0_entrylo0(arg);
3566 rn = "EntryLo0";
3567 break;
3568 case 1:
3569 check_insn(env, ctx, ASE_MT);
3570 gen_helper_mtc0_tcstatus(arg);
3571 rn = "TCStatus";
3572 break;
3573 case 2:
3574 check_insn(env, ctx, ASE_MT);
3575 gen_helper_mtc0_tcbind(arg);
3576 rn = "TCBind";
3577 break;
3578 case 3:
3579 check_insn(env, ctx, ASE_MT);
3580 gen_helper_mtc0_tcrestart(arg);
3581 rn = "TCRestart";
3582 break;
3583 case 4:
3584 check_insn(env, ctx, ASE_MT);
3585 gen_helper_mtc0_tchalt(arg);
3586 rn = "TCHalt";
3587 break;
3588 case 5:
3589 check_insn(env, ctx, ASE_MT);
3590 gen_helper_mtc0_tccontext(arg);
3591 rn = "TCContext";
3592 break;
3593 case 6:
3594 check_insn(env, ctx, ASE_MT);
3595 gen_helper_mtc0_tcschedule(arg);
3596 rn = "TCSchedule";
3597 break;
3598 case 7:
3599 check_insn(env, ctx, ASE_MT);
3600 gen_helper_mtc0_tcschefback(arg);
3601 rn = "TCScheFBack";
3602 break;
3603 default:
3604 goto die;
3606 break;
3607 case 3:
3608 switch (sel) {
3609 case 0:
3610 gen_helper_mtc0_entrylo1(arg);
3611 rn = "EntryLo1";
3612 break;
3613 default:
3614 goto die;
3616 break;
3617 case 4:
3618 switch (sel) {
3619 case 0:
3620 gen_helper_mtc0_context(arg);
3621 rn = "Context";
3622 break;
3623 case 1:
3624 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3625 rn = "ContextConfig";
3626 // break;
3627 default:
3628 goto die;
3630 break;
3631 case 5:
3632 switch (sel) {
3633 case 0:
3634 gen_helper_mtc0_pagemask(arg);
3635 rn = "PageMask";
3636 break;
3637 case 1:
3638 check_insn(env, ctx, ISA_MIPS32R2);
3639 gen_helper_mtc0_pagegrain(arg);
3640 rn = "PageGrain";
3641 break;
3642 default:
3643 goto die;
3645 break;
3646 case 6:
3647 switch (sel) {
3648 case 0:
3649 gen_helper_mtc0_wired(arg);
3650 rn = "Wired";
3651 break;
3652 case 1:
3653 check_insn(env, ctx, ISA_MIPS32R2);
3654 gen_helper_mtc0_srsconf0(arg);
3655 rn = "SRSConf0";
3656 break;
3657 case 2:
3658 check_insn(env, ctx, ISA_MIPS32R2);
3659 gen_helper_mtc0_srsconf1(arg);
3660 rn = "SRSConf1";
3661 break;
3662 case 3:
3663 check_insn(env, ctx, ISA_MIPS32R2);
3664 gen_helper_mtc0_srsconf2(arg);
3665 rn = "SRSConf2";
3666 break;
3667 case 4:
3668 check_insn(env, ctx, ISA_MIPS32R2);
3669 gen_helper_mtc0_srsconf3(arg);
3670 rn = "SRSConf3";
3671 break;
3672 case 5:
3673 check_insn(env, ctx, ISA_MIPS32R2);
3674 gen_helper_mtc0_srsconf4(arg);
3675 rn = "SRSConf4";
3676 break;
3677 default:
3678 goto die;
3680 break;
3681 case 7:
3682 switch (sel) {
3683 case 0:
3684 check_insn(env, ctx, ISA_MIPS32R2);
3685 gen_helper_mtc0_hwrena(arg);
3686 rn = "HWREna";
3687 break;
3688 default:
3689 goto die;
3691 break;
3692 case 8:
3693 /* ignored */
3694 rn = "BadVAddr";
3695 break;
3696 case 9:
3697 switch (sel) {
3698 case 0:
3699 gen_helper_mtc0_count(arg);
3700 rn = "Count";
3701 break;
3702 /* 6,7 are implementation dependent */
3703 default:
3704 goto die;
3706 break;
3707 case 10:
3708 switch (sel) {
3709 case 0:
3710 gen_helper_mtc0_entryhi(arg);
3711 rn = "EntryHi";
3712 break;
3713 default:
3714 goto die;
3716 break;
3717 case 11:
3718 switch (sel) {
3719 case 0:
3720 gen_helper_mtc0_compare(arg);
3721 rn = "Compare";
3722 break;
3723 /* 6,7 are implementation dependent */
3724 default:
3725 goto die;
3727 break;
3728 case 12:
3729 switch (sel) {
3730 case 0:
3731 save_cpu_state(ctx, 1);
3732 gen_helper_mtc0_status(arg);
3733 /* BS_STOP isn't good enough here, hflags may have changed. */
3734 gen_save_pc(ctx->pc + 4);
3735 ctx->bstate = BS_EXCP;
3736 rn = "Status";
3737 break;
3738 case 1:
3739 check_insn(env, ctx, ISA_MIPS32R2);
3740 gen_helper_mtc0_intctl(arg);
3741 /* Stop translation as we may have switched the execution mode */
3742 ctx->bstate = BS_STOP;
3743 rn = "IntCtl";
3744 break;
3745 case 2:
3746 check_insn(env, ctx, ISA_MIPS32R2);
3747 gen_helper_mtc0_srsctl(arg);
3748 /* Stop translation as we may have switched the execution mode */
3749 ctx->bstate = BS_STOP;
3750 rn = "SRSCtl";
3751 break;
3752 case 3:
3753 check_insn(env, ctx, ISA_MIPS32R2);
3754 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
3755 /* Stop translation as we may have switched the execution mode */
3756 ctx->bstate = BS_STOP;
3757 rn = "SRSMap";
3758 break;
3759 default:
3760 goto die;
3762 break;
3763 case 13:
3764 switch (sel) {
3765 case 0:
3766 save_cpu_state(ctx, 1);
3767 gen_helper_mtc0_cause(arg);
3768 rn = "Cause";
3769 break;
3770 default:
3771 goto die;
3773 break;
3774 case 14:
3775 switch (sel) {
3776 case 0:
3777 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
3778 rn = "EPC";
3779 break;
3780 default:
3781 goto die;
3783 break;
3784 case 15:
3785 switch (sel) {
3786 case 0:
3787 /* ignored */
3788 rn = "PRid";
3789 break;
3790 case 1:
3791 check_insn(env, ctx, ISA_MIPS32R2);
3792 gen_helper_mtc0_ebase(arg);
3793 rn = "EBase";
3794 break;
3795 default:
3796 goto die;
3798 break;
3799 case 16:
3800 switch (sel) {
3801 case 0:
3802 gen_helper_mtc0_config0(arg);
3803 rn = "Config";
3804 /* Stop translation as we may have switched the execution mode */
3805 ctx->bstate = BS_STOP;
3806 break;
3807 case 1:
3808 /* ignored, read only */
3809 rn = "Config1";
3810 break;
3811 case 2:
3812 gen_helper_mtc0_config2(arg);
3813 rn = "Config2";
3814 /* Stop translation as we may have switched the execution mode */
3815 ctx->bstate = BS_STOP;
3816 break;
3817 case 3:
3818 /* ignored, read only */
3819 rn = "Config3";
3820 break;
3821 /* 4,5 are reserved */
3822 /* 6,7 are implementation dependent */
3823 case 6:
3824 /* ignored */
3825 rn = "Config6";
3826 break;
3827 case 7:
3828 /* ignored */
3829 rn = "Config7";
3830 break;
3831 default:
3832 rn = "Invalid config selector";
3833 goto die;
3835 break;
3836 case 17:
3837 switch (sel) {
3838 case 0:
3839 /* ignored */
3840 rn = "LLAddr";
3841 break;
3842 default:
3843 goto die;
3845 break;
3846 case 18:
3847 switch (sel) {
3848 case 0 ... 7:
3849 gen_helper_1i(mtc0_watchlo, arg, sel);
3850 rn = "WatchLo";
3851 break;
3852 default:
3853 goto die;
3855 break;
3856 case 19:
3857 switch (sel) {
3858 case 0 ... 7:
3859 gen_helper_1i(mtc0_watchhi, arg, sel);
3860 rn = "WatchHi";
3861 break;
3862 default:
3863 goto die;
3865 break;
3866 case 20:
3867 switch (sel) {
3868 case 0:
3869 #if defined(TARGET_MIPS64)
3870 check_insn(env, ctx, ISA_MIPS3);
3871 gen_helper_mtc0_xcontext(arg);
3872 rn = "XContext";
3873 break;
3874 #endif
3875 default:
3876 goto die;
3878 break;
3879 case 21:
3880 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3881 switch (sel) {
3882 case 0:
3883 gen_helper_mtc0_framemask(arg);
3884 rn = "Framemask";
3885 break;
3886 default:
3887 goto die;
3889 break;
3890 case 22:
3891 /* ignored */
3892 rn = "Diagnostic"; /* implementation dependent */
3893 break;
3894 case 23:
3895 switch (sel) {
3896 case 0:
3897 gen_helper_mtc0_debug(arg); /* EJTAG support */
3898 /* BS_STOP isn't good enough here, hflags may have changed. */
3899 gen_save_pc(ctx->pc + 4);
3900 ctx->bstate = BS_EXCP;
3901 rn = "Debug";
3902 break;
3903 case 1:
3904 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
3905 rn = "TraceControl";
3906 /* Stop translation as we may have switched the execution mode */
3907 ctx->bstate = BS_STOP;
3908 // break;
3909 case 2:
3910 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
3911 rn = "TraceControl2";
3912 /* Stop translation as we may have switched the execution mode */
3913 ctx->bstate = BS_STOP;
3914 // break;
3915 case 3:
3916 /* Stop translation as we may have switched the execution mode */
3917 ctx->bstate = BS_STOP;
3918 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
3919 rn = "UserTraceData";
3920 /* Stop translation as we may have switched the execution mode */
3921 ctx->bstate = BS_STOP;
3922 // break;
3923 case 4:
3924 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
3925 /* Stop translation as we may have switched the execution mode */
3926 ctx->bstate = BS_STOP;
3927 rn = "TraceBPC";
3928 // break;
3929 default:
3930 goto die;
3932 break;
3933 case 24:
3934 switch (sel) {
3935 case 0:
3936 /* EJTAG support */
3937 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
3938 rn = "DEPC";
3939 break;
3940 default:
3941 goto die;
3943 break;
3944 case 25:
3945 switch (sel) {
3946 case 0:
3947 gen_helper_mtc0_performance0(arg);
3948 rn = "Performance0";
3949 break;
3950 case 1:
3951 // gen_helper_mtc0_performance1(arg);
3952 rn = "Performance1";
3953 // break;
3954 case 2:
3955 // gen_helper_mtc0_performance2(arg);
3956 rn = "Performance2";
3957 // break;
3958 case 3:
3959 // gen_helper_mtc0_performance3(arg);
3960 rn = "Performance3";
3961 // break;
3962 case 4:
3963 // gen_helper_mtc0_performance4(arg);
3964 rn = "Performance4";
3965 // break;
3966 case 5:
3967 // gen_helper_mtc0_performance5(arg);
3968 rn = "Performance5";
3969 // break;
3970 case 6:
3971 // gen_helper_mtc0_performance6(arg);
3972 rn = "Performance6";
3973 // break;
3974 case 7:
3975 // gen_helper_mtc0_performance7(arg);
3976 rn = "Performance7";
3977 // break;
3978 default:
3979 goto die;
3981 break;
3982 case 26:
3983 /* ignored */
3984 rn = "ECC";
3985 break;
3986 case 27:
3987 switch (sel) {
3988 case 0 ... 3:
3989 /* ignored */
3990 rn = "CacheErr";
3991 break;
3992 default:
3993 goto die;
3995 break;
3996 case 28:
3997 switch (sel) {
3998 case 0:
3999 case 2:
4000 case 4:
4001 case 6:
4002 gen_helper_mtc0_taglo(arg);
4003 rn = "TagLo";
4004 break;
4005 case 1:
4006 case 3:
4007 case 5:
4008 case 7:
4009 gen_helper_mtc0_datalo(arg);
4010 rn = "DataLo";
4011 break;
4012 default:
4013 goto die;
4015 break;
4016 case 29:
4017 switch (sel) {
4018 case 0:
4019 case 2:
4020 case 4:
4021 case 6:
4022 gen_helper_mtc0_taghi(arg);
4023 rn = "TagHi";
4024 break;
4025 case 1:
4026 case 3:
4027 case 5:
4028 case 7:
4029 gen_helper_mtc0_datahi(arg);
4030 rn = "DataHi";
4031 break;
4032 default:
4033 rn = "invalid sel";
4034 goto die;
4036 break;
4037 case 30:
4038 switch (sel) {
4039 case 0:
4040 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
4041 rn = "ErrorEPC";
4042 break;
4043 default:
4044 goto die;
4046 break;
4047 case 31:
4048 switch (sel) {
4049 case 0:
4050 /* EJTAG support */
4051 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
4052 rn = "DESAVE";
4053 break;
4054 default:
4055 goto die;
4057 /* Stop translation as we may have switched the execution mode */
4058 ctx->bstate = BS_STOP;
4059 break;
4060 default:
4061 goto die;
4063 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4064 /* For simplicity assume that all writes can cause interrupts. */
4065 if (use_icount) {
4066 gen_io_end();
4067 ctx->bstate = BS_STOP;
4069 return;
4071 die:
4072 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4073 generate_exception(ctx, EXCP_RI);
4076 #if defined(TARGET_MIPS64)
4077 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4079 const char *rn = "invalid";
4081 if (sel != 0)
4082 check_insn(env, ctx, ISA_MIPS64);
4084 switch (reg) {
4085 case 0:
4086 switch (sel) {
4087 case 0:
4088 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
4089 rn = "Index";
4090 break;
4091 case 1:
4092 check_insn(env, ctx, ASE_MT);
4093 gen_helper_mfc0_mvpcontrol(arg);
4094 rn = "MVPControl";
4095 break;
4096 case 2:
4097 check_insn(env, ctx, ASE_MT);
4098 gen_helper_mfc0_mvpconf0(arg);
4099 rn = "MVPConf0";
4100 break;
4101 case 3:
4102 check_insn(env, ctx, ASE_MT);
4103 gen_helper_mfc0_mvpconf1(arg);
4104 rn = "MVPConf1";
4105 break;
4106 default:
4107 goto die;
4109 break;
4110 case 1:
4111 switch (sel) {
4112 case 0:
4113 gen_helper_mfc0_random(arg);
4114 rn = "Random";
4115 break;
4116 case 1:
4117 check_insn(env, ctx, ASE_MT);
4118 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
4119 rn = "VPEControl";
4120 break;
4121 case 2:
4122 check_insn(env, ctx, ASE_MT);
4123 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
4124 rn = "VPEConf0";
4125 break;
4126 case 3:
4127 check_insn(env, ctx, ASE_MT);
4128 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
4129 rn = "VPEConf1";
4130 break;
4131 case 4:
4132 check_insn(env, ctx, ASE_MT);
4133 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
4134 rn = "YQMask";
4135 break;
4136 case 5:
4137 check_insn(env, ctx, ASE_MT);
4138 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4139 rn = "VPESchedule";
4140 break;
4141 case 6:
4142 check_insn(env, ctx, ASE_MT);
4143 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4144 rn = "VPEScheFBack";
4145 break;
4146 case 7:
4147 check_insn(env, ctx, ASE_MT);
4148 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
4149 rn = "VPEOpt";
4150 break;
4151 default:
4152 goto die;
4154 break;
4155 case 2:
4156 switch (sel) {
4157 case 0:
4158 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4159 rn = "EntryLo0";
4160 break;
4161 case 1:
4162 check_insn(env, ctx, ASE_MT);
4163 gen_helper_mfc0_tcstatus(arg);
4164 rn = "TCStatus";
4165 break;
4166 case 2:
4167 check_insn(env, ctx, ASE_MT);
4168 gen_helper_mfc0_tcbind(arg);
4169 rn = "TCBind";
4170 break;
4171 case 3:
4172 check_insn(env, ctx, ASE_MT);
4173 gen_helper_dmfc0_tcrestart(arg);
4174 rn = "TCRestart";
4175 break;
4176 case 4:
4177 check_insn(env, ctx, ASE_MT);
4178 gen_helper_dmfc0_tchalt(arg);
4179 rn = "TCHalt";
4180 break;
4181 case 5:
4182 check_insn(env, ctx, ASE_MT);
4183 gen_helper_dmfc0_tccontext(arg);
4184 rn = "TCContext";
4185 break;
4186 case 6:
4187 check_insn(env, ctx, ASE_MT);
4188 gen_helper_dmfc0_tcschedule(arg);
4189 rn = "TCSchedule";
4190 break;
4191 case 7:
4192 check_insn(env, ctx, ASE_MT);
4193 gen_helper_dmfc0_tcschefback(arg);
4194 rn = "TCScheFBack";
4195 break;
4196 default:
4197 goto die;
4199 break;
4200 case 3:
4201 switch (sel) {
4202 case 0:
4203 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4204 rn = "EntryLo1";
4205 break;
4206 default:
4207 goto die;
4209 break;
4210 case 4:
4211 switch (sel) {
4212 case 0:
4213 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
4214 rn = "Context";
4215 break;
4216 case 1:
4217 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4218 rn = "ContextConfig";
4219 // break;
4220 default:
4221 goto die;
4223 break;
4224 case 5:
4225 switch (sel) {
4226 case 0:
4227 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
4228 rn = "PageMask";
4229 break;
4230 case 1:
4231 check_insn(env, ctx, ISA_MIPS32R2);
4232 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
4233 rn = "PageGrain";
4234 break;
4235 default:
4236 goto die;
4238 break;
4239 case 6:
4240 switch (sel) {
4241 case 0:
4242 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
4243 rn = "Wired";
4244 break;
4245 case 1:
4246 check_insn(env, ctx, ISA_MIPS32R2);
4247 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
4248 rn = "SRSConf0";
4249 break;
4250 case 2:
4251 check_insn(env, ctx, ISA_MIPS32R2);
4252 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
4253 rn = "SRSConf1";
4254 break;
4255 case 3:
4256 check_insn(env, ctx, ISA_MIPS32R2);
4257 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
4258 rn = "SRSConf2";
4259 break;
4260 case 4:
4261 check_insn(env, ctx, ISA_MIPS32R2);
4262 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
4263 rn = "SRSConf3";
4264 break;
4265 case 5:
4266 check_insn(env, ctx, ISA_MIPS32R2);
4267 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
4268 rn = "SRSConf4";
4269 break;
4270 default:
4271 goto die;
4273 break;
4274 case 7:
4275 switch (sel) {
4276 case 0:
4277 check_insn(env, ctx, ISA_MIPS32R2);
4278 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
4279 rn = "HWREna";
4280 break;
4281 default:
4282 goto die;
4284 break;
4285 case 8:
4286 switch (sel) {
4287 case 0:
4288 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4289 rn = "BadVAddr";
4290 break;
4291 default:
4292 goto die;
4294 break;
4295 case 9:
4296 switch (sel) {
4297 case 0:
4298 /* Mark as an IO operation because we read the time. */
4299 if (use_icount)
4300 gen_io_start();
4301 gen_helper_mfc0_count(arg);
4302 if (use_icount) {
4303 gen_io_end();
4304 ctx->bstate = BS_STOP;
4306 rn = "Count";
4307 break;
4308 /* 6,7 are implementation dependent */
4309 default:
4310 goto die;
4312 break;
4313 case 10:
4314 switch (sel) {
4315 case 0:
4316 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
4317 rn = "EntryHi";
4318 break;
4319 default:
4320 goto die;
4322 break;
4323 case 11:
4324 switch (sel) {
4325 case 0:
4326 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
4327 rn = "Compare";
4328 break;
4329 /* 6,7 are implementation dependent */
4330 default:
4331 goto die;
4333 break;
4334 case 12:
4335 switch (sel) {
4336 case 0:
4337 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
4338 rn = "Status";
4339 break;
4340 case 1:
4341 check_insn(env, ctx, ISA_MIPS32R2);
4342 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
4343 rn = "IntCtl";
4344 break;
4345 case 2:
4346 check_insn(env, ctx, ISA_MIPS32R2);
4347 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
4348 rn = "SRSCtl";
4349 break;
4350 case 3:
4351 check_insn(env, ctx, ISA_MIPS32R2);
4352 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
4353 rn = "SRSMap";
4354 break;
4355 default:
4356 goto die;
4358 break;
4359 case 13:
4360 switch (sel) {
4361 case 0:
4362 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
4363 rn = "Cause";
4364 break;
4365 default:
4366 goto die;
4368 break;
4369 case 14:
4370 switch (sel) {
4371 case 0:
4372 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4373 rn = "EPC";
4374 break;
4375 default:
4376 goto die;
4378 break;
4379 case 15:
4380 switch (sel) {
4381 case 0:
4382 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
4383 rn = "PRid";
4384 break;
4385 case 1:
4386 check_insn(env, ctx, ISA_MIPS32R2);
4387 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
4388 rn = "EBase";
4389 break;
4390 default:
4391 goto die;
4393 break;
4394 case 16:
4395 switch (sel) {
4396 case 0:
4397 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
4398 rn = "Config";
4399 break;
4400 case 1:
4401 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
4402 rn = "Config1";
4403 break;
4404 case 2:
4405 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
4406 rn = "Config2";
4407 break;
4408 case 3:
4409 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
4410 rn = "Config3";
4411 break;
4412 /* 6,7 are implementation dependent */
4413 case 6:
4414 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
4415 rn = "Config6";
4416 break;
4417 case 7:
4418 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
4419 rn = "Config7";
4420 break;
4421 default:
4422 goto die;
4424 break;
4425 case 17:
4426 switch (sel) {
4427 case 0:
4428 gen_helper_dmfc0_lladdr(arg);
4429 rn = "LLAddr";
4430 break;
4431 default:
4432 goto die;
4434 break;
4435 case 18:
4436 switch (sel) {
4437 case 0 ... 7:
4438 gen_helper_1i(dmfc0_watchlo, arg, sel);
4439 rn = "WatchLo";
4440 break;
4441 default:
4442 goto die;
4444 break;
4445 case 19:
4446 switch (sel) {
4447 case 0 ... 7:
4448 gen_helper_1i(mfc0_watchhi, arg, sel);
4449 rn = "WatchHi";
4450 break;
4451 default:
4452 goto die;
4454 break;
4455 case 20:
4456 switch (sel) {
4457 case 0:
4458 check_insn(env, ctx, ISA_MIPS3);
4459 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
4460 rn = "XContext";
4461 break;
4462 default:
4463 goto die;
4465 break;
4466 case 21:
4467 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4468 switch (sel) {
4469 case 0:
4470 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
4471 rn = "Framemask";
4472 break;
4473 default:
4474 goto die;
4476 break;
4477 case 22:
4478 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4479 rn = "'Diagnostic"; /* implementation dependent */
4480 break;
4481 case 23:
4482 switch (sel) {
4483 case 0:
4484 gen_helper_mfc0_debug(arg); /* EJTAG support */
4485 rn = "Debug";
4486 break;
4487 case 1:
4488 // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4489 rn = "TraceControl";
4490 // break;
4491 case 2:
4492 // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4493 rn = "TraceControl2";
4494 // break;
4495 case 3:
4496 // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4497 rn = "UserTraceData";
4498 // break;
4499 case 4:
4500 // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4501 rn = "TraceBPC";
4502 // break;
4503 default:
4504 goto die;
4506 break;
4507 case 24:
4508 switch (sel) {
4509 case 0:
4510 /* EJTAG support */
4511 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4512 rn = "DEPC";
4513 break;
4514 default:
4515 goto die;
4517 break;
4518 case 25:
4519 switch (sel) {
4520 case 0:
4521 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
4522 rn = "Performance0";
4523 break;
4524 case 1:
4525 // gen_helper_dmfc0_performance1(arg);
4526 rn = "Performance1";
4527 // break;
4528 case 2:
4529 // gen_helper_dmfc0_performance2(arg);
4530 rn = "Performance2";
4531 // break;
4532 case 3:
4533 // gen_helper_dmfc0_performance3(arg);
4534 rn = "Performance3";
4535 // break;
4536 case 4:
4537 // gen_helper_dmfc0_performance4(arg);
4538 rn = "Performance4";
4539 // break;
4540 case 5:
4541 // gen_helper_dmfc0_performance5(arg);
4542 rn = "Performance5";
4543 // break;
4544 case 6:
4545 // gen_helper_dmfc0_performance6(arg);
4546 rn = "Performance6";
4547 // break;
4548 case 7:
4549 // gen_helper_dmfc0_performance7(arg);
4550 rn = "Performance7";
4551 // break;
4552 default:
4553 goto die;
4555 break;
4556 case 26:
4557 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4558 rn = "ECC";
4559 break;
4560 case 27:
4561 switch (sel) {
4562 /* ignored */
4563 case 0 ... 3:
4564 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4565 rn = "CacheErr";
4566 break;
4567 default:
4568 goto die;
4570 break;
4571 case 28:
4572 switch (sel) {
4573 case 0:
4574 case 2:
4575 case 4:
4576 case 6:
4577 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
4578 rn = "TagLo";
4579 break;
4580 case 1:
4581 case 3:
4582 case 5:
4583 case 7:
4584 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
4585 rn = "DataLo";
4586 break;
4587 default:
4588 goto die;
4590 break;
4591 case 29:
4592 switch (sel) {
4593 case 0:
4594 case 2:
4595 case 4:
4596 case 6:
4597 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
4598 rn = "TagHi";
4599 break;
4600 case 1:
4601 case 3:
4602 case 5:
4603 case 7:
4604 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
4605 rn = "DataHi";
4606 break;
4607 default:
4608 goto die;
4610 break;
4611 case 30:
4612 switch (sel) {
4613 case 0:
4614 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4615 rn = "ErrorEPC";
4616 break;
4617 default:
4618 goto die;
4620 break;
4621 case 31:
4622 switch (sel) {
4623 case 0:
4624 /* EJTAG support */
4625 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
4626 rn = "DESAVE";
4627 break;
4628 default:
4629 goto die;
4631 break;
4632 default:
4633 goto die;
4635 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4636 return;
4638 die:
4639 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4640 generate_exception(ctx, EXCP_RI);
4643 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4645 const char *rn = "invalid";
4647 if (sel != 0)
4648 check_insn(env, ctx, ISA_MIPS64);
4650 if (use_icount)
4651 gen_io_start();
4653 switch (reg) {
4654 case 0:
4655 switch (sel) {
4656 case 0:
4657 gen_helper_mtc0_index(arg);
4658 rn = "Index";
4659 break;
4660 case 1:
4661 check_insn(env, ctx, ASE_MT);
4662 gen_helper_mtc0_mvpcontrol(arg);
4663 rn = "MVPControl";
4664 break;
4665 case 2:
4666 check_insn(env, ctx, ASE_MT);
4667 /* ignored */
4668 rn = "MVPConf0";
4669 break;
4670 case 3:
4671 check_insn(env, ctx, ASE_MT);
4672 /* ignored */
4673 rn = "MVPConf1";
4674 break;
4675 default:
4676 goto die;
4678 break;
4679 case 1:
4680 switch (sel) {
4681 case 0:
4682 /* ignored */
4683 rn = "Random";
4684 break;
4685 case 1:
4686 check_insn(env, ctx, ASE_MT);
4687 gen_helper_mtc0_vpecontrol(arg);
4688 rn = "VPEControl";
4689 break;
4690 case 2:
4691 check_insn(env, ctx, ASE_MT);
4692 gen_helper_mtc0_vpeconf0(arg);
4693 rn = "VPEConf0";
4694 break;
4695 case 3:
4696 check_insn(env, ctx, ASE_MT);
4697 gen_helper_mtc0_vpeconf1(arg);
4698 rn = "VPEConf1";
4699 break;
4700 case 4:
4701 check_insn(env, ctx, ASE_MT);
4702 gen_helper_mtc0_yqmask(arg);
4703 rn = "YQMask";
4704 break;
4705 case 5:
4706 check_insn(env, ctx, ASE_MT);
4707 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4708 rn = "VPESchedule";
4709 break;
4710 case 6:
4711 check_insn(env, ctx, ASE_MT);
4712 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4713 rn = "VPEScheFBack";
4714 break;
4715 case 7:
4716 check_insn(env, ctx, ASE_MT);
4717 gen_helper_mtc0_vpeopt(arg);
4718 rn = "VPEOpt";
4719 break;
4720 default:
4721 goto die;
4723 break;
4724 case 2:
4725 switch (sel) {
4726 case 0:
4727 gen_helper_mtc0_entrylo0(arg);
4728 rn = "EntryLo0";
4729 break;
4730 case 1:
4731 check_insn(env, ctx, ASE_MT);
4732 gen_helper_mtc0_tcstatus(arg);
4733 rn = "TCStatus";
4734 break;
4735 case 2:
4736 check_insn(env, ctx, ASE_MT);
4737 gen_helper_mtc0_tcbind(arg);
4738 rn = "TCBind";
4739 break;
4740 case 3:
4741 check_insn(env, ctx, ASE_MT);
4742 gen_helper_mtc0_tcrestart(arg);
4743 rn = "TCRestart";
4744 break;
4745 case 4:
4746 check_insn(env, ctx, ASE_MT);
4747 gen_helper_mtc0_tchalt(arg);
4748 rn = "TCHalt";
4749 break;
4750 case 5:
4751 check_insn(env, ctx, ASE_MT);
4752 gen_helper_mtc0_tccontext(arg);
4753 rn = "TCContext";
4754 break;
4755 case 6:
4756 check_insn(env, ctx, ASE_MT);
4757 gen_helper_mtc0_tcschedule(arg);
4758 rn = "TCSchedule";
4759 break;
4760 case 7:
4761 check_insn(env, ctx, ASE_MT);
4762 gen_helper_mtc0_tcschefback(arg);
4763 rn = "TCScheFBack";
4764 break;
4765 default:
4766 goto die;
4768 break;
4769 case 3:
4770 switch (sel) {
4771 case 0:
4772 gen_helper_mtc0_entrylo1(arg);
4773 rn = "EntryLo1";
4774 break;
4775 default:
4776 goto die;
4778 break;
4779 case 4:
4780 switch (sel) {
4781 case 0:
4782 gen_helper_mtc0_context(arg);
4783 rn = "Context";
4784 break;
4785 case 1:
4786 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
4787 rn = "ContextConfig";
4788 // break;
4789 default:
4790 goto die;
4792 break;
4793 case 5:
4794 switch (sel) {
4795 case 0:
4796 gen_helper_mtc0_pagemask(arg);
4797 rn = "PageMask";
4798 break;
4799 case 1:
4800 check_insn(env, ctx, ISA_MIPS32R2);
4801 gen_helper_mtc0_pagegrain(arg);
4802 rn = "PageGrain";
4803 break;
4804 default:
4805 goto die;
4807 break;
4808 case 6:
4809 switch (sel) {
4810 case 0:
4811 gen_helper_mtc0_wired(arg);
4812 rn = "Wired";
4813 break;
4814 case 1:
4815 check_insn(env, ctx, ISA_MIPS32R2);
4816 gen_helper_mtc0_srsconf0(arg);
4817 rn = "SRSConf0";
4818 break;
4819 case 2:
4820 check_insn(env, ctx, ISA_MIPS32R2);
4821 gen_helper_mtc0_srsconf1(arg);
4822 rn = "SRSConf1";
4823 break;
4824 case 3:
4825 check_insn(env, ctx, ISA_MIPS32R2);
4826 gen_helper_mtc0_srsconf2(arg);
4827 rn = "SRSConf2";
4828 break;
4829 case 4:
4830 check_insn(env, ctx, ISA_MIPS32R2);
4831 gen_helper_mtc0_srsconf3(arg);
4832 rn = "SRSConf3";
4833 break;
4834 case 5:
4835 check_insn(env, ctx, ISA_MIPS32R2);
4836 gen_helper_mtc0_srsconf4(arg);
4837 rn = "SRSConf4";
4838 break;
4839 default:
4840 goto die;
4842 break;
4843 case 7:
4844 switch (sel) {
4845 case 0:
4846 check_insn(env, ctx, ISA_MIPS32R2);
4847 gen_helper_mtc0_hwrena(arg);
4848 rn = "HWREna";
4849 break;
4850 default:
4851 goto die;
4853 break;
4854 case 8:
4855 /* ignored */
4856 rn = "BadVAddr";
4857 break;
4858 case 9:
4859 switch (sel) {
4860 case 0:
4861 gen_helper_mtc0_count(arg);
4862 rn = "Count";
4863 break;
4864 /* 6,7 are implementation dependent */
4865 default:
4866 goto die;
4868 /* Stop translation as we may have switched the execution mode */
4869 ctx->bstate = BS_STOP;
4870 break;
4871 case 10:
4872 switch (sel) {
4873 case 0:
4874 gen_helper_mtc0_entryhi(arg);
4875 rn = "EntryHi";
4876 break;
4877 default:
4878 goto die;
4880 break;
4881 case 11:
4882 switch (sel) {
4883 case 0:
4884 gen_helper_mtc0_compare(arg);
4885 rn = "Compare";
4886 break;
4887 /* 6,7 are implementation dependent */
4888 default:
4889 goto die;
4891 /* Stop translation as we may have switched the execution mode */
4892 ctx->bstate = BS_STOP;
4893 break;
4894 case 12:
4895 switch (sel) {
4896 case 0:
4897 save_cpu_state(ctx, 1);
4898 gen_helper_mtc0_status(arg);
4899 /* BS_STOP isn't good enough here, hflags may have changed. */
4900 gen_save_pc(ctx->pc + 4);
4901 ctx->bstate = BS_EXCP;
4902 rn = "Status";
4903 break;
4904 case 1:
4905 check_insn(env, ctx, ISA_MIPS32R2);
4906 gen_helper_mtc0_intctl(arg);
4907 /* Stop translation as we may have switched the execution mode */
4908 ctx->bstate = BS_STOP;
4909 rn = "IntCtl";
4910 break;
4911 case 2:
4912 check_insn(env, ctx, ISA_MIPS32R2);
4913 gen_helper_mtc0_srsctl(arg);
4914 /* Stop translation as we may have switched the execution mode */
4915 ctx->bstate = BS_STOP;
4916 rn = "SRSCtl";
4917 break;
4918 case 3:
4919 check_insn(env, ctx, ISA_MIPS32R2);
4920 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
4921 /* Stop translation as we may have switched the execution mode */
4922 ctx->bstate = BS_STOP;
4923 rn = "SRSMap";
4924 break;
4925 default:
4926 goto die;
4928 break;
4929 case 13:
4930 switch (sel) {
4931 case 0:
4932 save_cpu_state(ctx, 1);
4933 gen_helper_mtc0_cause(arg);
4934 rn = "Cause";
4935 break;
4936 default:
4937 goto die;
4939 break;
4940 case 14:
4941 switch (sel) {
4942 case 0:
4943 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4944 rn = "EPC";
4945 break;
4946 default:
4947 goto die;
4949 break;
4950 case 15:
4951 switch (sel) {
4952 case 0:
4953 /* ignored */
4954 rn = "PRid";
4955 break;
4956 case 1:
4957 check_insn(env, ctx, ISA_MIPS32R2);
4958 gen_helper_mtc0_ebase(arg);
4959 rn = "EBase";
4960 break;
4961 default:
4962 goto die;
4964 break;
4965 case 16:
4966 switch (sel) {
4967 case 0:
4968 gen_helper_mtc0_config0(arg);
4969 rn = "Config";
4970 /* Stop translation as we may have switched the execution mode */
4971 ctx->bstate = BS_STOP;
4972 break;
4973 case 1:
4974 /* ignored, read only */
4975 rn = "Config1";
4976 break;
4977 case 2:
4978 gen_helper_mtc0_config2(arg);
4979 rn = "Config2";
4980 /* Stop translation as we may have switched the execution mode */
4981 ctx->bstate = BS_STOP;
4982 break;
4983 case 3:
4984 /* ignored */
4985 rn = "Config3";
4986 break;
4987 /* 6,7 are implementation dependent */
4988 default:
4989 rn = "Invalid config selector";
4990 goto die;
4992 break;
4993 case 17:
4994 switch (sel) {
4995 case 0:
4996 /* ignored */
4997 rn = "LLAddr";
4998 break;
4999 default:
5000 goto die;
5002 break;
5003 case 18:
5004 switch (sel) {
5005 case 0 ... 7:
5006 gen_helper_1i(mtc0_watchlo, arg, sel);
5007 rn = "WatchLo";
5008 break;
5009 default:
5010 goto die;
5012 break;
5013 case 19:
5014 switch (sel) {
5015 case 0 ... 7:
5016 gen_helper_1i(mtc0_watchhi, arg, sel);
5017 rn = "WatchHi";
5018 break;
5019 default:
5020 goto die;
5022 break;
5023 case 20:
5024 switch (sel) {
5025 case 0:
5026 check_insn(env, ctx, ISA_MIPS3);
5027 gen_helper_mtc0_xcontext(arg);
5028 rn = "XContext";
5029 break;
5030 default:
5031 goto die;
5033 break;
5034 case 21:
5035 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5036 switch (sel) {
5037 case 0:
5038 gen_helper_mtc0_framemask(arg);
5039 rn = "Framemask";
5040 break;
5041 default:
5042 goto die;
5044 break;
5045 case 22:
5046 /* ignored */
5047 rn = "Diagnostic"; /* implementation dependent */
5048 break;
5049 case 23:
5050 switch (sel) {
5051 case 0:
5052 gen_helper_mtc0_debug(arg); /* EJTAG support */
5053 /* BS_STOP isn't good enough here, hflags may have changed. */
5054 gen_save_pc(ctx->pc + 4);
5055 ctx->bstate = BS_EXCP;
5056 rn = "Debug";
5057 break;
5058 case 1:
5059 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
5060 /* Stop translation as we may have switched the execution mode */
5061 ctx->bstate = BS_STOP;
5062 rn = "TraceControl";
5063 // break;
5064 case 2:
5065 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
5066 /* Stop translation as we may have switched the execution mode */
5067 ctx->bstate = BS_STOP;
5068 rn = "TraceControl2";
5069 // break;
5070 case 3:
5071 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
5072 /* Stop translation as we may have switched the execution mode */
5073 ctx->bstate = BS_STOP;
5074 rn = "UserTraceData";
5075 // break;
5076 case 4:
5077 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
5078 /* Stop translation as we may have switched the execution mode */
5079 ctx->bstate = BS_STOP;
5080 rn = "TraceBPC";
5081 // break;
5082 default:
5083 goto die;
5085 break;
5086 case 24:
5087 switch (sel) {
5088 case 0:
5089 /* EJTAG support */
5090 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
5091 rn = "DEPC";
5092 break;
5093 default:
5094 goto die;
5096 break;
5097 case 25:
5098 switch (sel) {
5099 case 0:
5100 gen_helper_mtc0_performance0(arg);
5101 rn = "Performance0";
5102 break;
5103 case 1:
5104 // gen_helper_mtc0_performance1(arg);
5105 rn = "Performance1";
5106 // break;
5107 case 2:
5108 // gen_helper_mtc0_performance2(arg);
5109 rn = "Performance2";
5110 // break;
5111 case 3:
5112 // gen_helper_mtc0_performance3(arg);
5113 rn = "Performance3";
5114 // break;
5115 case 4:
5116 // gen_helper_mtc0_performance4(arg);
5117 rn = "Performance4";
5118 // break;
5119 case 5:
5120 // gen_helper_mtc0_performance5(arg);
5121 rn = "Performance5";
5122 // break;
5123 case 6:
5124 // gen_helper_mtc0_performance6(arg);
5125 rn = "Performance6";
5126 // break;
5127 case 7:
5128 // gen_helper_mtc0_performance7(arg);
5129 rn = "Performance7";
5130 // break;
5131 default:
5132 goto die;
5134 break;
5135 case 26:
5136 /* ignored */
5137 rn = "ECC";
5138 break;
5139 case 27:
5140 switch (sel) {
5141 case 0 ... 3:
5142 /* ignored */
5143 rn = "CacheErr";
5144 break;
5145 default:
5146 goto die;
5148 break;
5149 case 28:
5150 switch (sel) {
5151 case 0:
5152 case 2:
5153 case 4:
5154 case 6:
5155 gen_helper_mtc0_taglo(arg);
5156 rn = "TagLo";
5157 break;
5158 case 1:
5159 case 3:
5160 case 5:
5161 case 7:
5162 gen_helper_mtc0_datalo(arg);
5163 rn = "DataLo";
5164 break;
5165 default:
5166 goto die;
5168 break;
5169 case 29:
5170 switch (sel) {
5171 case 0:
5172 case 2:
5173 case 4:
5174 case 6:
5175 gen_helper_mtc0_taghi(arg);
5176 rn = "TagHi";
5177 break;
5178 case 1:
5179 case 3:
5180 case 5:
5181 case 7:
5182 gen_helper_mtc0_datahi(arg);
5183 rn = "DataHi";
5184 break;
5185 default:
5186 rn = "invalid sel";
5187 goto die;
5189 break;
5190 case 30:
5191 switch (sel) {
5192 case 0:
5193 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5194 rn = "ErrorEPC";
5195 break;
5196 default:
5197 goto die;
5199 break;
5200 case 31:
5201 switch (sel) {
5202 case 0:
5203 /* EJTAG support */
5204 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
5205 rn = "DESAVE";
5206 break;
5207 default:
5208 goto die;
5210 /* Stop translation as we may have switched the execution mode */
5211 ctx->bstate = BS_STOP;
5212 break;
5213 default:
5214 goto die;
5216 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5217 /* For simplicity assume that all writes can cause interrupts. */
5218 if (use_icount) {
5219 gen_io_end();
5220 ctx->bstate = BS_STOP;
5222 return;
5224 die:
5225 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5226 generate_exception(ctx, EXCP_RI);
5228 #endif /* TARGET_MIPS64 */
5230 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5231 int u, int sel, int h)
5233 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5234 TCGv t0 = tcg_temp_local_new();
5236 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5237 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5238 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5239 tcg_gen_movi_tl(t0, -1);
5240 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5241 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5242 tcg_gen_movi_tl(t0, -1);
5243 else if (u == 0) {
5244 switch (rt) {
5245 case 2:
5246 switch (sel) {
5247 case 1:
5248 gen_helper_mftc0_tcstatus(t0);
5249 break;
5250 case 2:
5251 gen_helper_mftc0_tcbind(t0);
5252 break;
5253 case 3:
5254 gen_helper_mftc0_tcrestart(t0);
5255 break;
5256 case 4:
5257 gen_helper_mftc0_tchalt(t0);
5258 break;
5259 case 5:
5260 gen_helper_mftc0_tccontext(t0);
5261 break;
5262 case 6:
5263 gen_helper_mftc0_tcschedule(t0);
5264 break;
5265 case 7:
5266 gen_helper_mftc0_tcschefback(t0);
5267 break;
5268 default:
5269 gen_mfc0(env, ctx, t0, rt, sel);
5270 break;
5272 break;
5273 case 10:
5274 switch (sel) {
5275 case 0:
5276 gen_helper_mftc0_entryhi(t0);
5277 break;
5278 default:
5279 gen_mfc0(env, ctx, t0, rt, sel);
5280 break;
5282 case 12:
5283 switch (sel) {
5284 case 0:
5285 gen_helper_mftc0_status(t0);
5286 break;
5287 default:
5288 gen_mfc0(env, ctx, t0, rt, sel);
5289 break;
5291 case 23:
5292 switch (sel) {
5293 case 0:
5294 gen_helper_mftc0_debug(t0);
5295 break;
5296 default:
5297 gen_mfc0(env, ctx, t0, rt, sel);
5298 break;
5300 break;
5301 default:
5302 gen_mfc0(env, ctx, t0, rt, sel);
5304 } else switch (sel) {
5305 /* GPR registers. */
5306 case 0:
5307 gen_helper_1i(mftgpr, t0, rt);
5308 break;
5309 /* Auxiliary CPU registers */
5310 case 1:
5311 switch (rt) {
5312 case 0:
5313 gen_helper_1i(mftlo, t0, 0);
5314 break;
5315 case 1:
5316 gen_helper_1i(mfthi, t0, 0);
5317 break;
5318 case 2:
5319 gen_helper_1i(mftacx, t0, 0);
5320 break;
5321 case 4:
5322 gen_helper_1i(mftlo, t0, 1);
5323 break;
5324 case 5:
5325 gen_helper_1i(mfthi, t0, 1);
5326 break;
5327 case 6:
5328 gen_helper_1i(mftacx, t0, 1);
5329 break;
5330 case 8:
5331 gen_helper_1i(mftlo, t0, 2);
5332 break;
5333 case 9:
5334 gen_helper_1i(mfthi, t0, 2);
5335 break;
5336 case 10:
5337 gen_helper_1i(mftacx, t0, 2);
5338 break;
5339 case 12:
5340 gen_helper_1i(mftlo, t0, 3);
5341 break;
5342 case 13:
5343 gen_helper_1i(mfthi, t0, 3);
5344 break;
5345 case 14:
5346 gen_helper_1i(mftacx, t0, 3);
5347 break;
5348 case 16:
5349 gen_helper_mftdsp(t0);
5350 break;
5351 default:
5352 goto die;
5354 break;
5355 /* Floating point (COP1). */
5356 case 2:
5357 /* XXX: For now we support only a single FPU context. */
5358 if (h == 0) {
5359 TCGv_i32 fp0 = tcg_temp_new_i32();
5361 gen_load_fpr32(fp0, rt);
5362 tcg_gen_ext_i32_tl(t0, fp0);
5363 tcg_temp_free_i32(fp0);
5364 } else {
5365 TCGv_i32 fp0 = tcg_temp_new_i32();
5367 gen_load_fpr32h(fp0, rt);
5368 tcg_gen_ext_i32_tl(t0, fp0);
5369 tcg_temp_free_i32(fp0);
5371 break;
5372 case 3:
5373 /* XXX: For now we support only a single FPU context. */
5374 gen_helper_1i(cfc1, t0, rt);
5375 break;
5376 /* COP2: Not implemented. */
5377 case 4:
5378 case 5:
5379 /* fall through */
5380 default:
5381 goto die;
5383 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5384 gen_store_gpr(t0, rd);
5385 tcg_temp_free(t0);
5386 return;
5388 die:
5389 tcg_temp_free(t0);
5390 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5391 generate_exception(ctx, EXCP_RI);
5394 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5395 int u, int sel, int h)
5397 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5398 TCGv t0 = tcg_temp_local_new();
5400 gen_load_gpr(t0, rt);
5401 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5402 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5403 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5404 /* NOP */ ;
5405 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5406 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5407 /* NOP */ ;
5408 else if (u == 0) {
5409 switch (rd) {
5410 case 2:
5411 switch (sel) {
5412 case 1:
5413 gen_helper_mttc0_tcstatus(t0);
5414 break;
5415 case 2:
5416 gen_helper_mttc0_tcbind(t0);
5417 break;
5418 case 3:
5419 gen_helper_mttc0_tcrestart(t0);
5420 break;
5421 case 4:
5422 gen_helper_mttc0_tchalt(t0);
5423 break;
5424 case 5:
5425 gen_helper_mttc0_tccontext(t0);
5426 break;
5427 case 6:
5428 gen_helper_mttc0_tcschedule(t0);
5429 break;
5430 case 7:
5431 gen_helper_mttc0_tcschefback(t0);
5432 break;
5433 default:
5434 gen_mtc0(env, ctx, t0, rd, sel);
5435 break;
5437 break;
5438 case 10:
5439 switch (sel) {
5440 case 0:
5441 gen_helper_mttc0_entryhi(t0);
5442 break;
5443 default:
5444 gen_mtc0(env, ctx, t0, rd, sel);
5445 break;
5447 case 12:
5448 switch (sel) {
5449 case 0:
5450 gen_helper_mttc0_status(t0);
5451 break;
5452 default:
5453 gen_mtc0(env, ctx, t0, rd, sel);
5454 break;
5456 case 23:
5457 switch (sel) {
5458 case 0:
5459 gen_helper_mttc0_debug(t0);
5460 break;
5461 default:
5462 gen_mtc0(env, ctx, t0, rd, sel);
5463 break;
5465 break;
5466 default:
5467 gen_mtc0(env, ctx, t0, rd, sel);
5469 } else switch (sel) {
5470 /* GPR registers. */
5471 case 0:
5472 gen_helper_1i(mttgpr, t0, rd);
5473 break;
5474 /* Auxiliary CPU registers */
5475 case 1:
5476 switch (rd) {
5477 case 0:
5478 gen_helper_1i(mttlo, t0, 0);
5479 break;
5480 case 1:
5481 gen_helper_1i(mtthi, t0, 0);
5482 break;
5483 case 2:
5484 gen_helper_1i(mttacx, t0, 0);
5485 break;
5486 case 4:
5487 gen_helper_1i(mttlo, t0, 1);
5488 break;
5489 case 5:
5490 gen_helper_1i(mtthi, t0, 1);
5491 break;
5492 case 6:
5493 gen_helper_1i(mttacx, t0, 1);
5494 break;
5495 case 8:
5496 gen_helper_1i(mttlo, t0, 2);
5497 break;
5498 case 9:
5499 gen_helper_1i(mtthi, t0, 2);
5500 break;
5501 case 10:
5502 gen_helper_1i(mttacx, t0, 2);
5503 break;
5504 case 12:
5505 gen_helper_1i(mttlo, t0, 3);
5506 break;
5507 case 13:
5508 gen_helper_1i(mtthi, t0, 3);
5509 break;
5510 case 14:
5511 gen_helper_1i(mttacx, t0, 3);
5512 break;
5513 case 16:
5514 gen_helper_mttdsp(t0);
5515 break;
5516 default:
5517 goto die;
5519 break;
5520 /* Floating point (COP1). */
5521 case 2:
5522 /* XXX: For now we support only a single FPU context. */
5523 if (h == 0) {
5524 TCGv_i32 fp0 = tcg_temp_new_i32();
5526 tcg_gen_trunc_tl_i32(fp0, t0);
5527 gen_store_fpr32(fp0, rd);
5528 tcg_temp_free_i32(fp0);
5529 } else {
5530 TCGv_i32 fp0 = tcg_temp_new_i32();
5532 tcg_gen_trunc_tl_i32(fp0, t0);
5533 gen_store_fpr32h(fp0, rd);
5534 tcg_temp_free_i32(fp0);
5536 break;
5537 case 3:
5538 /* XXX: For now we support only a single FPU context. */
5539 gen_helper_1i(ctc1, t0, rd);
5540 break;
5541 /* COP2: Not implemented. */
5542 case 4:
5543 case 5:
5544 /* fall through */
5545 default:
5546 goto die;
5548 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5549 tcg_temp_free(t0);
5550 return;
5552 die:
5553 tcg_temp_free(t0);
5554 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5555 generate_exception(ctx, EXCP_RI);
5558 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5560 const char *opn = "ldst";
5562 switch (opc) {
5563 case OPC_MFC0:
5564 if (rt == 0) {
5565 /* Treat as NOP. */
5566 return;
5568 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5569 opn = "mfc0";
5570 break;
5571 case OPC_MTC0:
5573 TCGv t0 = tcg_temp_new();
5575 gen_load_gpr(t0, rt);
5576 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5577 tcg_temp_free(t0);
5579 opn = "mtc0";
5580 break;
5581 #if defined(TARGET_MIPS64)
5582 case OPC_DMFC0:
5583 check_insn(env, ctx, ISA_MIPS3);
5584 if (rt == 0) {
5585 /* Treat as NOP. */
5586 return;
5588 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5589 opn = "dmfc0";
5590 break;
5591 case OPC_DMTC0:
5592 check_insn(env, ctx, ISA_MIPS3);
5594 TCGv t0 = tcg_temp_new();
5596 gen_load_gpr(t0, rt);
5597 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5598 tcg_temp_free(t0);
5600 opn = "dmtc0";
5601 break;
5602 #endif
5603 case OPC_MFTR:
5604 check_insn(env, ctx, ASE_MT);
5605 if (rd == 0) {
5606 /* Treat as NOP. */
5607 return;
5609 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5610 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5611 opn = "mftr";
5612 break;
5613 case OPC_MTTR:
5614 check_insn(env, ctx, ASE_MT);
5615 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5616 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5617 opn = "mttr";
5618 break;
5619 case OPC_TLBWI:
5620 opn = "tlbwi";
5621 if (!env->tlb->helper_tlbwi)
5622 goto die;
5623 gen_helper_tlbwi();
5624 break;
5625 case OPC_TLBWR:
5626 opn = "tlbwr";
5627 if (!env->tlb->helper_tlbwr)
5628 goto die;
5629 gen_helper_tlbwr();
5630 break;
5631 case OPC_TLBP:
5632 opn = "tlbp";
5633 if (!env->tlb->helper_tlbp)
5634 goto die;
5635 gen_helper_tlbp();
5636 break;
5637 case OPC_TLBR:
5638 opn = "tlbr";
5639 if (!env->tlb->helper_tlbr)
5640 goto die;
5641 gen_helper_tlbr();
5642 break;
5643 case OPC_ERET:
5644 opn = "eret";
5645 check_insn(env, ctx, ISA_MIPS2);
5646 gen_helper_eret();
5647 ctx->bstate = BS_EXCP;
5648 break;
5649 case OPC_DERET:
5650 opn = "deret";
5651 check_insn(env, ctx, ISA_MIPS32);
5652 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5653 MIPS_INVAL(opn);
5654 generate_exception(ctx, EXCP_RI);
5655 } else {
5656 gen_helper_deret();
5657 ctx->bstate = BS_EXCP;
5659 break;
5660 case OPC_WAIT:
5661 opn = "wait";
5662 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5663 /* If we get an exception, we want to restart at next instruction */
5664 ctx->pc += 4;
5665 save_cpu_state(ctx, 1);
5666 ctx->pc -= 4;
5667 gen_helper_wait();
5668 ctx->bstate = BS_EXCP;
5669 break;
5670 default:
5671 die:
5672 MIPS_INVAL(opn);
5673 generate_exception(ctx, EXCP_RI);
5674 return;
5676 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5678 #endif /* !CONFIG_USER_ONLY */
5680 /* CP1 Branches (before delay slot) */
5681 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5682 int32_t cc, int32_t offset)
5684 target_ulong btarget;
5685 const char *opn = "cp1 cond branch";
5686 TCGv_i32 t0 = tcg_temp_new_i32();
5688 if (cc != 0)
5689 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5691 btarget = ctx->pc + 4 + offset;
5693 switch (op) {
5694 case OPC_BC1F:
5695 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5696 tcg_gen_not_i32(t0, t0);
5697 tcg_gen_andi_i32(t0, t0, 1);
5698 tcg_gen_extu_i32_tl(bcond, t0);
5699 opn = "bc1f";
5700 goto not_likely;
5701 case OPC_BC1FL:
5702 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5703 tcg_gen_not_i32(t0, t0);
5704 tcg_gen_andi_i32(t0, t0, 1);
5705 tcg_gen_extu_i32_tl(bcond, t0);
5706 opn = "bc1fl";
5707 goto likely;
5708 case OPC_BC1T:
5709 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5710 tcg_gen_andi_i32(t0, t0, 1);
5711 tcg_gen_extu_i32_tl(bcond, t0);
5712 opn = "bc1t";
5713 goto not_likely;
5714 case OPC_BC1TL:
5715 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5716 tcg_gen_andi_i32(t0, t0, 1);
5717 tcg_gen_extu_i32_tl(bcond, t0);
5718 opn = "bc1tl";
5719 likely:
5720 ctx->hflags |= MIPS_HFLAG_BL;
5721 break;
5722 case OPC_BC1FANY2:
5724 TCGv_i32 t1 = tcg_temp_new_i32();
5725 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5726 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5727 tcg_gen_or_i32(t0, t0, t1);
5728 tcg_temp_free_i32(t1);
5729 tcg_gen_not_i32(t0, t0);
5730 tcg_gen_andi_i32(t0, t0, 1);
5731 tcg_gen_extu_i32_tl(bcond, t0);
5733 opn = "bc1any2f";
5734 goto not_likely;
5735 case OPC_BC1TANY2:
5737 TCGv_i32 t1 = tcg_temp_new_i32();
5738 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5739 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5740 tcg_gen_or_i32(t0, t0, t1);
5741 tcg_temp_free_i32(t1);
5742 tcg_gen_andi_i32(t0, t0, 1);
5743 tcg_gen_extu_i32_tl(bcond, t0);
5745 opn = "bc1any2t";
5746 goto not_likely;
5747 case OPC_BC1FANY4:
5749 TCGv_i32 t1 = tcg_temp_new_i32();
5750 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5751 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5752 tcg_gen_or_i32(t0, t0, t1);
5753 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5754 tcg_gen_or_i32(t0, t0, t1);
5755 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5756 tcg_gen_or_i32(t0, t0, t1);
5757 tcg_temp_free_i32(t1);
5758 tcg_gen_not_i32(t0, t0);
5759 tcg_gen_andi_i32(t0, t0, 1);
5760 tcg_gen_extu_i32_tl(bcond, t0);
5762 opn = "bc1any4f";
5763 goto not_likely;
5764 case OPC_BC1TANY4:
5766 TCGv_i32 t1 = tcg_temp_new_i32();
5767 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5768 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5769 tcg_gen_or_i32(t0, t0, t1);
5770 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5771 tcg_gen_or_i32(t0, t0, t1);
5772 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5773 tcg_gen_or_i32(t0, t0, t1);
5774 tcg_temp_free_i32(t1);
5775 tcg_gen_andi_i32(t0, t0, 1);
5776 tcg_gen_extu_i32_tl(bcond, t0);
5778 opn = "bc1any4t";
5779 not_likely:
5780 ctx->hflags |= MIPS_HFLAG_BC;
5781 break;
5782 default:
5783 MIPS_INVAL(opn);
5784 generate_exception (ctx, EXCP_RI);
5785 goto out;
5787 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5788 ctx->hflags, btarget);
5789 ctx->btarget = btarget;
5791 out:
5792 tcg_temp_free_i32(t0);
5795 /* Coprocessor 1 (FPU) */
5797 #define FOP(func, fmt) (((fmt) << 21) | (func))
5799 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5801 const char *opn = "cp1 move";
5802 TCGv t0 = tcg_temp_new();
5804 switch (opc) {
5805 case OPC_MFC1:
5807 TCGv_i32 fp0 = tcg_temp_new_i32();
5809 gen_load_fpr32(fp0, fs);
5810 tcg_gen_ext_i32_tl(t0, fp0);
5811 tcg_temp_free_i32(fp0);
5813 gen_store_gpr(t0, rt);
5814 opn = "mfc1";
5815 break;
5816 case OPC_MTC1:
5817 gen_load_gpr(t0, rt);
5819 TCGv_i32 fp0 = tcg_temp_new_i32();
5821 tcg_gen_trunc_tl_i32(fp0, t0);
5822 gen_store_fpr32(fp0, fs);
5823 tcg_temp_free_i32(fp0);
5825 opn = "mtc1";
5826 break;
5827 case OPC_CFC1:
5828 gen_helper_1i(cfc1, t0, fs);
5829 gen_store_gpr(t0, rt);
5830 opn = "cfc1";
5831 break;
5832 case OPC_CTC1:
5833 gen_load_gpr(t0, rt);
5834 gen_helper_1i(ctc1, t0, fs);
5835 opn = "ctc1";
5836 break;
5837 #if defined(TARGET_MIPS64)
5838 case OPC_DMFC1:
5839 gen_load_fpr64(ctx, t0, fs);
5840 gen_store_gpr(t0, rt);
5841 opn = "dmfc1";
5842 break;
5843 case OPC_DMTC1:
5844 gen_load_gpr(t0, rt);
5845 gen_store_fpr64(ctx, t0, fs);
5846 opn = "dmtc1";
5847 break;
5848 #endif
5849 case OPC_MFHC1:
5851 TCGv_i32 fp0 = tcg_temp_new_i32();
5853 gen_load_fpr32h(fp0, fs);
5854 tcg_gen_ext_i32_tl(t0, fp0);
5855 tcg_temp_free_i32(fp0);
5857 gen_store_gpr(t0, rt);
5858 opn = "mfhc1";
5859 break;
5860 case OPC_MTHC1:
5861 gen_load_gpr(t0, rt);
5863 TCGv_i32 fp0 = tcg_temp_new_i32();
5865 tcg_gen_trunc_tl_i32(fp0, t0);
5866 gen_store_fpr32h(fp0, fs);
5867 tcg_temp_free_i32(fp0);
5869 opn = "mthc1";
5870 break;
5871 default:
5872 MIPS_INVAL(opn);
5873 generate_exception (ctx, EXCP_RI);
5874 goto out;
5876 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5878 out:
5879 tcg_temp_free(t0);
5882 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5884 int l1;
5885 TCGCond cond;
5886 TCGv_i32 t0;
5888 if (rd == 0) {
5889 /* Treat as NOP. */
5890 return;
5893 if (tf)
5894 cond = TCG_COND_EQ;
5895 else
5896 cond = TCG_COND_NE;
5898 l1 = gen_new_label();
5899 t0 = tcg_temp_new_i32();
5900 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5901 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5902 tcg_temp_free_i32(t0);
5903 if (rs == 0) {
5904 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5905 } else {
5906 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5908 gen_set_label(l1);
5911 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5913 int cond;
5914 TCGv_i32 t0 = tcg_temp_new_i32();
5915 int l1 = gen_new_label();
5917 if (tf)
5918 cond = TCG_COND_EQ;
5919 else
5920 cond = TCG_COND_NE;
5922 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5923 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5924 gen_load_fpr32(t0, fs);
5925 gen_store_fpr32(t0, fd);
5926 gen_set_label(l1);
5927 tcg_temp_free_i32(t0);
5930 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5932 int cond;
5933 TCGv_i32 t0 = tcg_temp_new_i32();
5934 TCGv_i64 fp0;
5935 int l1 = gen_new_label();
5937 if (tf)
5938 cond = TCG_COND_EQ;
5939 else
5940 cond = TCG_COND_NE;
5942 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5943 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5944 tcg_temp_free_i32(t0);
5945 fp0 = tcg_temp_new_i64();
5946 gen_load_fpr64(ctx, fp0, fs);
5947 gen_store_fpr64(ctx, fp0, fd);
5948 tcg_temp_free_i64(fp0);
5949 gen_set_label(l1);
5952 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5954 int cond;
5955 TCGv_i32 t0 = tcg_temp_new_i32();
5956 int l1 = gen_new_label();
5957 int l2 = gen_new_label();
5959 if (tf)
5960 cond = TCG_COND_EQ;
5961 else
5962 cond = TCG_COND_NE;
5964 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5965 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5966 gen_load_fpr32(t0, fs);
5967 gen_store_fpr32(t0, fd);
5968 gen_set_label(l1);
5970 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc+1));
5971 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5972 gen_load_fpr32h(t0, fs);
5973 gen_store_fpr32h(t0, fd);
5974 tcg_temp_free_i32(t0);
5975 gen_set_label(l2);
5979 static void gen_farith (DisasContext *ctx, uint32_t op1,
5980 int ft, int fs, int fd, int cc)
5982 const char *opn = "farith";
5983 const char *condnames[] = {
5984 "c.f",
5985 "c.un",
5986 "c.eq",
5987 "c.ueq",
5988 "c.olt",
5989 "c.ult",
5990 "c.ole",
5991 "c.ule",
5992 "c.sf",
5993 "c.ngle",
5994 "c.seq",
5995 "c.ngl",
5996 "c.lt",
5997 "c.nge",
5998 "c.le",
5999 "c.ngt",
6001 const char *condnames_abs[] = {
6002 "cabs.f",
6003 "cabs.un",
6004 "cabs.eq",
6005 "cabs.ueq",
6006 "cabs.olt",
6007 "cabs.ult",
6008 "cabs.ole",
6009 "cabs.ule",
6010 "cabs.sf",
6011 "cabs.ngle",
6012 "cabs.seq",
6013 "cabs.ngl",
6014 "cabs.lt",
6015 "cabs.nge",
6016 "cabs.le",
6017 "cabs.ngt",
6019 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6020 uint32_t func = ctx->opcode & 0x3f;
6022 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
6023 case FOP(0, 16):
6025 TCGv_i32 fp0 = tcg_temp_new_i32();
6026 TCGv_i32 fp1 = tcg_temp_new_i32();
6028 gen_load_fpr32(fp0, fs);
6029 gen_load_fpr32(fp1, ft);
6030 gen_helper_float_add_s(fp0, fp0, fp1);
6031 tcg_temp_free_i32(fp1);
6032 gen_store_fpr32(fp0, fd);
6033 tcg_temp_free_i32(fp0);
6035 opn = "add.s";
6036 optype = BINOP;
6037 break;
6038 case FOP(1, 16):
6040 TCGv_i32 fp0 = tcg_temp_new_i32();
6041 TCGv_i32 fp1 = tcg_temp_new_i32();
6043 gen_load_fpr32(fp0, fs);
6044 gen_load_fpr32(fp1, ft);
6045 gen_helper_float_sub_s(fp0, fp0, fp1);
6046 tcg_temp_free_i32(fp1);
6047 gen_store_fpr32(fp0, fd);
6048 tcg_temp_free_i32(fp0);
6050 opn = "sub.s";
6051 optype = BINOP;
6052 break;
6053 case FOP(2, 16):
6055 TCGv_i32 fp0 = tcg_temp_new_i32();
6056 TCGv_i32 fp1 = tcg_temp_new_i32();
6058 gen_load_fpr32(fp0, fs);
6059 gen_load_fpr32(fp1, ft);
6060 gen_helper_float_mul_s(fp0, fp0, fp1);
6061 tcg_temp_free_i32(fp1);
6062 gen_store_fpr32(fp0, fd);
6063 tcg_temp_free_i32(fp0);
6065 opn = "mul.s";
6066 optype = BINOP;
6067 break;
6068 case FOP(3, 16):
6070 TCGv_i32 fp0 = tcg_temp_new_i32();
6071 TCGv_i32 fp1 = tcg_temp_new_i32();
6073 gen_load_fpr32(fp0, fs);
6074 gen_load_fpr32(fp1, ft);
6075 gen_helper_float_div_s(fp0, fp0, fp1);
6076 tcg_temp_free_i32(fp1);
6077 gen_store_fpr32(fp0, fd);
6078 tcg_temp_free_i32(fp0);
6080 opn = "div.s";
6081 optype = BINOP;
6082 break;
6083 case FOP(4, 16):
6085 TCGv_i32 fp0 = tcg_temp_new_i32();
6087 gen_load_fpr32(fp0, fs);
6088 gen_helper_float_sqrt_s(fp0, fp0);
6089 gen_store_fpr32(fp0, fd);
6090 tcg_temp_free_i32(fp0);
6092 opn = "sqrt.s";
6093 break;
6094 case FOP(5, 16):
6096 TCGv_i32 fp0 = tcg_temp_new_i32();
6098 gen_load_fpr32(fp0, fs);
6099 gen_helper_float_abs_s(fp0, fp0);
6100 gen_store_fpr32(fp0, fd);
6101 tcg_temp_free_i32(fp0);
6103 opn = "abs.s";
6104 break;
6105 case FOP(6, 16):
6107 TCGv_i32 fp0 = tcg_temp_new_i32();
6109 gen_load_fpr32(fp0, fs);
6110 gen_store_fpr32(fp0, fd);
6111 tcg_temp_free_i32(fp0);
6113 opn = "mov.s";
6114 break;
6115 case FOP(7, 16):
6117 TCGv_i32 fp0 = tcg_temp_new_i32();
6119 gen_load_fpr32(fp0, fs);
6120 gen_helper_float_chs_s(fp0, fp0);
6121 gen_store_fpr32(fp0, fd);
6122 tcg_temp_free_i32(fp0);
6124 opn = "neg.s";
6125 break;
6126 case FOP(8, 16):
6127 check_cp1_64bitmode(ctx);
6129 TCGv_i32 fp32 = tcg_temp_new_i32();
6130 TCGv_i64 fp64 = tcg_temp_new_i64();
6132 gen_load_fpr32(fp32, fs);
6133 gen_helper_float_roundl_s(fp64, fp32);
6134 tcg_temp_free_i32(fp32);
6135 gen_store_fpr64(ctx, fp64, fd);
6136 tcg_temp_free_i64(fp64);
6138 opn = "round.l.s";
6139 break;
6140 case FOP(9, 16):
6141 check_cp1_64bitmode(ctx);
6143 TCGv_i32 fp32 = tcg_temp_new_i32();
6144 TCGv_i64 fp64 = tcg_temp_new_i64();
6146 gen_load_fpr32(fp32, fs);
6147 gen_helper_float_truncl_s(fp64, fp32);
6148 tcg_temp_free_i32(fp32);
6149 gen_store_fpr64(ctx, fp64, fd);
6150 tcg_temp_free_i64(fp64);
6152 opn = "trunc.l.s";
6153 break;
6154 case FOP(10, 16):
6155 check_cp1_64bitmode(ctx);
6157 TCGv_i32 fp32 = tcg_temp_new_i32();
6158 TCGv_i64 fp64 = tcg_temp_new_i64();
6160 gen_load_fpr32(fp32, fs);
6161 gen_helper_float_ceill_s(fp64, fp32);
6162 tcg_temp_free_i32(fp32);
6163 gen_store_fpr64(ctx, fp64, fd);
6164 tcg_temp_free_i64(fp64);
6166 opn = "ceil.l.s";
6167 break;
6168 case FOP(11, 16):
6169 check_cp1_64bitmode(ctx);
6171 TCGv_i32 fp32 = tcg_temp_new_i32();
6172 TCGv_i64 fp64 = tcg_temp_new_i64();
6174 gen_load_fpr32(fp32, fs);
6175 gen_helper_float_floorl_s(fp64, fp32);
6176 tcg_temp_free_i32(fp32);
6177 gen_store_fpr64(ctx, fp64, fd);
6178 tcg_temp_free_i64(fp64);
6180 opn = "floor.l.s";
6181 break;
6182 case FOP(12, 16):
6184 TCGv_i32 fp0 = tcg_temp_new_i32();
6186 gen_load_fpr32(fp0, fs);
6187 gen_helper_float_roundw_s(fp0, fp0);
6188 gen_store_fpr32(fp0, fd);
6189 tcg_temp_free_i32(fp0);
6191 opn = "round.w.s";
6192 break;
6193 case FOP(13, 16):
6195 TCGv_i32 fp0 = tcg_temp_new_i32();
6197 gen_load_fpr32(fp0, fs);
6198 gen_helper_float_truncw_s(fp0, fp0);
6199 gen_store_fpr32(fp0, fd);
6200 tcg_temp_free_i32(fp0);
6202 opn = "trunc.w.s";
6203 break;
6204 case FOP(14, 16):
6206 TCGv_i32 fp0 = tcg_temp_new_i32();
6208 gen_load_fpr32(fp0, fs);
6209 gen_helper_float_ceilw_s(fp0, fp0);
6210 gen_store_fpr32(fp0, fd);
6211 tcg_temp_free_i32(fp0);
6213 opn = "ceil.w.s";
6214 break;
6215 case FOP(15, 16):
6217 TCGv_i32 fp0 = tcg_temp_new_i32();
6219 gen_load_fpr32(fp0, fs);
6220 gen_helper_float_floorw_s(fp0, fp0);
6221 gen_store_fpr32(fp0, fd);
6222 tcg_temp_free_i32(fp0);
6224 opn = "floor.w.s";
6225 break;
6226 case FOP(17, 16):
6227 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6228 opn = "movcf.s";
6229 break;
6230 case FOP(18, 16):
6232 int l1 = gen_new_label();
6233 TCGv_i32 fp0;
6235 if (ft != 0) {
6236 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6238 fp0 = tcg_temp_new_i32();
6239 gen_load_fpr32(fp0, fs);
6240 gen_store_fpr32(fp0, fd);
6241 tcg_temp_free_i32(fp0);
6242 gen_set_label(l1);
6244 opn = "movz.s";
6245 break;
6246 case FOP(19, 16):
6248 int l1 = gen_new_label();
6249 TCGv_i32 fp0;
6251 if (ft != 0) {
6252 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6253 fp0 = tcg_temp_new_i32();
6254 gen_load_fpr32(fp0, fs);
6255 gen_store_fpr32(fp0, fd);
6256 tcg_temp_free_i32(fp0);
6257 gen_set_label(l1);
6260 opn = "movn.s";
6261 break;
6262 case FOP(21, 16):
6263 check_cop1x(ctx);
6265 TCGv_i32 fp0 = tcg_temp_new_i32();
6267 gen_load_fpr32(fp0, fs);
6268 gen_helper_float_recip_s(fp0, fp0);
6269 gen_store_fpr32(fp0, fd);
6270 tcg_temp_free_i32(fp0);
6272 opn = "recip.s";
6273 break;
6274 case FOP(22, 16):
6275 check_cop1x(ctx);
6277 TCGv_i32 fp0 = tcg_temp_new_i32();
6279 gen_load_fpr32(fp0, fs);
6280 gen_helper_float_rsqrt_s(fp0, fp0);
6281 gen_store_fpr32(fp0, fd);
6282 tcg_temp_free_i32(fp0);
6284 opn = "rsqrt.s";
6285 break;
6286 case FOP(28, 16):
6287 check_cp1_64bitmode(ctx);
6289 TCGv_i32 fp0 = tcg_temp_new_i32();
6290 TCGv_i32 fp1 = tcg_temp_new_i32();
6292 gen_load_fpr32(fp0, fs);
6293 gen_load_fpr32(fp1, fd);
6294 gen_helper_float_recip2_s(fp0, fp0, fp1);
6295 tcg_temp_free_i32(fp1);
6296 gen_store_fpr32(fp0, fd);
6297 tcg_temp_free_i32(fp0);
6299 opn = "recip2.s";
6300 break;
6301 case FOP(29, 16):
6302 check_cp1_64bitmode(ctx);
6304 TCGv_i32 fp0 = tcg_temp_new_i32();
6306 gen_load_fpr32(fp0, fs);
6307 gen_helper_float_recip1_s(fp0, fp0);
6308 gen_store_fpr32(fp0, fd);
6309 tcg_temp_free_i32(fp0);
6311 opn = "recip1.s";
6312 break;
6313 case FOP(30, 16):
6314 check_cp1_64bitmode(ctx);
6316 TCGv_i32 fp0 = tcg_temp_new_i32();
6318 gen_load_fpr32(fp0, fs);
6319 gen_helper_float_rsqrt1_s(fp0, fp0);
6320 gen_store_fpr32(fp0, fd);
6321 tcg_temp_free_i32(fp0);
6323 opn = "rsqrt1.s";
6324 break;
6325 case FOP(31, 16):
6326 check_cp1_64bitmode(ctx);
6328 TCGv_i32 fp0 = tcg_temp_new_i32();
6329 TCGv_i32 fp1 = tcg_temp_new_i32();
6331 gen_load_fpr32(fp0, fs);
6332 gen_load_fpr32(fp1, ft);
6333 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6334 tcg_temp_free_i32(fp1);
6335 gen_store_fpr32(fp0, fd);
6336 tcg_temp_free_i32(fp0);
6338 opn = "rsqrt2.s";
6339 break;
6340 case FOP(33, 16):
6341 check_cp1_registers(ctx, fd);
6343 TCGv_i32 fp32 = tcg_temp_new_i32();
6344 TCGv_i64 fp64 = tcg_temp_new_i64();
6346 gen_load_fpr32(fp32, fs);
6347 gen_helper_float_cvtd_s(fp64, fp32);
6348 tcg_temp_free_i32(fp32);
6349 gen_store_fpr64(ctx, fp64, fd);
6350 tcg_temp_free_i64(fp64);
6352 opn = "cvt.d.s";
6353 break;
6354 case FOP(36, 16):
6356 TCGv_i32 fp0 = tcg_temp_new_i32();
6358 gen_load_fpr32(fp0, fs);
6359 gen_helper_float_cvtw_s(fp0, fp0);
6360 gen_store_fpr32(fp0, fd);
6361 tcg_temp_free_i32(fp0);
6363 opn = "cvt.w.s";
6364 break;
6365 case FOP(37, 16):
6366 check_cp1_64bitmode(ctx);
6368 TCGv_i32 fp32 = tcg_temp_new_i32();
6369 TCGv_i64 fp64 = tcg_temp_new_i64();
6371 gen_load_fpr32(fp32, fs);
6372 gen_helper_float_cvtl_s(fp64, fp32);
6373 tcg_temp_free_i32(fp32);
6374 gen_store_fpr64(ctx, fp64, fd);
6375 tcg_temp_free_i64(fp64);
6377 opn = "cvt.l.s";
6378 break;
6379 case FOP(38, 16):
6380 check_cp1_64bitmode(ctx);
6382 TCGv_i64 fp64 = tcg_temp_new_i64();
6383 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6384 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6386 gen_load_fpr32(fp32_0, fs);
6387 gen_load_fpr32(fp32_1, ft);
6388 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6389 tcg_temp_free_i32(fp32_1);
6390 tcg_temp_free_i32(fp32_0);
6391 gen_store_fpr64(ctx, fp64, fd);
6392 tcg_temp_free_i64(fp64);
6394 opn = "cvt.ps.s";
6395 break;
6396 case FOP(48, 16):
6397 case FOP(49, 16):
6398 case FOP(50, 16):
6399 case FOP(51, 16):
6400 case FOP(52, 16):
6401 case FOP(53, 16):
6402 case FOP(54, 16):
6403 case FOP(55, 16):
6404 case FOP(56, 16):
6405 case FOP(57, 16):
6406 case FOP(58, 16):
6407 case FOP(59, 16):
6408 case FOP(60, 16):
6409 case FOP(61, 16):
6410 case FOP(62, 16):
6411 case FOP(63, 16):
6413 TCGv_i32 fp0 = tcg_temp_new_i32();
6414 TCGv_i32 fp1 = tcg_temp_new_i32();
6416 gen_load_fpr32(fp0, fs);
6417 gen_load_fpr32(fp1, ft);
6418 if (ctx->opcode & (1 << 6)) {
6419 check_cop1x(ctx);
6420 gen_cmpabs_s(func-48, fp0, fp1, cc);
6421 opn = condnames_abs[func-48];
6422 } else {
6423 gen_cmp_s(func-48, fp0, fp1, cc);
6424 opn = condnames[func-48];
6426 tcg_temp_free_i32(fp0);
6427 tcg_temp_free_i32(fp1);
6429 break;
6430 case FOP(0, 17):
6431 check_cp1_registers(ctx, fs | ft | fd);
6433 TCGv_i64 fp0 = tcg_temp_new_i64();
6434 TCGv_i64 fp1 = tcg_temp_new_i64();
6436 gen_load_fpr64(ctx, fp0, fs);
6437 gen_load_fpr64(ctx, fp1, ft);
6438 gen_helper_float_add_d(fp0, fp0, fp1);
6439 tcg_temp_free_i64(fp1);
6440 gen_store_fpr64(ctx, fp0, fd);
6441 tcg_temp_free_i64(fp0);
6443 opn = "add.d";
6444 optype = BINOP;
6445 break;
6446 case FOP(1, 17):
6447 check_cp1_registers(ctx, fs | ft | fd);
6449 TCGv_i64 fp0 = tcg_temp_new_i64();
6450 TCGv_i64 fp1 = tcg_temp_new_i64();
6452 gen_load_fpr64(ctx, fp0, fs);
6453 gen_load_fpr64(ctx, fp1, ft);
6454 gen_helper_float_sub_d(fp0, fp0, fp1);
6455 tcg_temp_free_i64(fp1);
6456 gen_store_fpr64(ctx, fp0, fd);
6457 tcg_temp_free_i64(fp0);
6459 opn = "sub.d";
6460 optype = BINOP;
6461 break;
6462 case FOP(2, 17):
6463 check_cp1_registers(ctx, fs | ft | fd);
6465 TCGv_i64 fp0 = tcg_temp_new_i64();
6466 TCGv_i64 fp1 = tcg_temp_new_i64();
6468 gen_load_fpr64(ctx, fp0, fs);
6469 gen_load_fpr64(ctx, fp1, ft);
6470 gen_helper_float_mul_d(fp0, fp0, fp1);
6471 tcg_temp_free_i64(fp1);
6472 gen_store_fpr64(ctx, fp0, fd);
6473 tcg_temp_free_i64(fp0);
6475 opn = "mul.d";
6476 optype = BINOP;
6477 break;
6478 case FOP(3, 17):
6479 check_cp1_registers(ctx, fs | ft | fd);
6481 TCGv_i64 fp0 = tcg_temp_new_i64();
6482 TCGv_i64 fp1 = tcg_temp_new_i64();
6484 gen_load_fpr64(ctx, fp0, fs);
6485 gen_load_fpr64(ctx, fp1, ft);
6486 gen_helper_float_div_d(fp0, fp0, fp1);
6487 tcg_temp_free_i64(fp1);
6488 gen_store_fpr64(ctx, fp0, fd);
6489 tcg_temp_free_i64(fp0);
6491 opn = "div.d";
6492 optype = BINOP;
6493 break;
6494 case FOP(4, 17):
6495 check_cp1_registers(ctx, fs | fd);
6497 TCGv_i64 fp0 = tcg_temp_new_i64();
6499 gen_load_fpr64(ctx, fp0, fs);
6500 gen_helper_float_sqrt_d(fp0, fp0);
6501 gen_store_fpr64(ctx, fp0, fd);
6502 tcg_temp_free_i64(fp0);
6504 opn = "sqrt.d";
6505 break;
6506 case FOP(5, 17):
6507 check_cp1_registers(ctx, fs | fd);
6509 TCGv_i64 fp0 = tcg_temp_new_i64();
6511 gen_load_fpr64(ctx, fp0, fs);
6512 gen_helper_float_abs_d(fp0, fp0);
6513 gen_store_fpr64(ctx, fp0, fd);
6514 tcg_temp_free_i64(fp0);
6516 opn = "abs.d";
6517 break;
6518 case FOP(6, 17):
6519 check_cp1_registers(ctx, fs | fd);
6521 TCGv_i64 fp0 = tcg_temp_new_i64();
6523 gen_load_fpr64(ctx, fp0, fs);
6524 gen_store_fpr64(ctx, fp0, fd);
6525 tcg_temp_free_i64(fp0);
6527 opn = "mov.d";
6528 break;
6529 case FOP(7, 17):
6530 check_cp1_registers(ctx, fs | fd);
6532 TCGv_i64 fp0 = tcg_temp_new_i64();
6534 gen_load_fpr64(ctx, fp0, fs);
6535 gen_helper_float_chs_d(fp0, fp0);
6536 gen_store_fpr64(ctx, fp0, fd);
6537 tcg_temp_free_i64(fp0);
6539 opn = "neg.d";
6540 break;
6541 case FOP(8, 17):
6542 check_cp1_64bitmode(ctx);
6544 TCGv_i64 fp0 = tcg_temp_new_i64();
6546 gen_load_fpr64(ctx, fp0, fs);
6547 gen_helper_float_roundl_d(fp0, fp0);
6548 gen_store_fpr64(ctx, fp0, fd);
6549 tcg_temp_free_i64(fp0);
6551 opn = "round.l.d";
6552 break;
6553 case FOP(9, 17):
6554 check_cp1_64bitmode(ctx);
6556 TCGv_i64 fp0 = tcg_temp_new_i64();
6558 gen_load_fpr64(ctx, fp0, fs);
6559 gen_helper_float_truncl_d(fp0, fp0);
6560 gen_store_fpr64(ctx, fp0, fd);
6561 tcg_temp_free_i64(fp0);
6563 opn = "trunc.l.d";
6564 break;
6565 case FOP(10, 17):
6566 check_cp1_64bitmode(ctx);
6568 TCGv_i64 fp0 = tcg_temp_new_i64();
6570 gen_load_fpr64(ctx, fp0, fs);
6571 gen_helper_float_ceill_d(fp0, fp0);
6572 gen_store_fpr64(ctx, fp0, fd);
6573 tcg_temp_free_i64(fp0);
6575 opn = "ceil.l.d";
6576 break;
6577 case FOP(11, 17):
6578 check_cp1_64bitmode(ctx);
6580 TCGv_i64 fp0 = tcg_temp_new_i64();
6582 gen_load_fpr64(ctx, fp0, fs);
6583 gen_helper_float_floorl_d(fp0, fp0);
6584 gen_store_fpr64(ctx, fp0, fd);
6585 tcg_temp_free_i64(fp0);
6587 opn = "floor.l.d";
6588 break;
6589 case FOP(12, 17):
6590 check_cp1_registers(ctx, fs);
6592 TCGv_i32 fp32 = tcg_temp_new_i32();
6593 TCGv_i64 fp64 = tcg_temp_new_i64();
6595 gen_load_fpr64(ctx, fp64, fs);
6596 gen_helper_float_roundw_d(fp32, fp64);
6597 tcg_temp_free_i64(fp64);
6598 gen_store_fpr32(fp32, fd);
6599 tcg_temp_free_i32(fp32);
6601 opn = "round.w.d";
6602 break;
6603 case FOP(13, 17):
6604 check_cp1_registers(ctx, fs);
6606 TCGv_i32 fp32 = tcg_temp_new_i32();
6607 TCGv_i64 fp64 = tcg_temp_new_i64();
6609 gen_load_fpr64(ctx, fp64, fs);
6610 gen_helper_float_truncw_d(fp32, fp64);
6611 tcg_temp_free_i64(fp64);
6612 gen_store_fpr32(fp32, fd);
6613 tcg_temp_free_i32(fp32);
6615 opn = "trunc.w.d";
6616 break;
6617 case FOP(14, 17):
6618 check_cp1_registers(ctx, fs);
6620 TCGv_i32 fp32 = tcg_temp_new_i32();
6621 TCGv_i64 fp64 = tcg_temp_new_i64();
6623 gen_load_fpr64(ctx, fp64, fs);
6624 gen_helper_float_ceilw_d(fp32, fp64);
6625 tcg_temp_free_i64(fp64);
6626 gen_store_fpr32(fp32, fd);
6627 tcg_temp_free_i32(fp32);
6629 opn = "ceil.w.d";
6630 break;
6631 case FOP(15, 17):
6632 check_cp1_registers(ctx, fs);
6634 TCGv_i32 fp32 = tcg_temp_new_i32();
6635 TCGv_i64 fp64 = tcg_temp_new_i64();
6637 gen_load_fpr64(ctx, fp64, fs);
6638 gen_helper_float_floorw_d(fp32, fp64);
6639 tcg_temp_free_i64(fp64);
6640 gen_store_fpr32(fp32, fd);
6641 tcg_temp_free_i32(fp32);
6643 opn = "floor.w.d";
6644 break;
6645 case FOP(17, 17):
6646 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6647 opn = "movcf.d";
6648 break;
6649 case FOP(18, 17):
6651 int l1 = gen_new_label();
6652 TCGv_i64 fp0;
6654 if (ft != 0) {
6655 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6657 fp0 = tcg_temp_new_i64();
6658 gen_load_fpr64(ctx, fp0, fs);
6659 gen_store_fpr64(ctx, fp0, fd);
6660 tcg_temp_free_i64(fp0);
6661 gen_set_label(l1);
6663 opn = "movz.d";
6664 break;
6665 case FOP(19, 17):
6667 int l1 = gen_new_label();
6668 TCGv_i64 fp0;
6670 if (ft != 0) {
6671 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6672 fp0 = tcg_temp_new_i64();
6673 gen_load_fpr64(ctx, fp0, fs);
6674 gen_store_fpr64(ctx, fp0, fd);
6675 tcg_temp_free_i64(fp0);
6676 gen_set_label(l1);
6679 opn = "movn.d";
6680 break;
6681 case FOP(21, 17):
6682 check_cp1_64bitmode(ctx);
6684 TCGv_i64 fp0 = tcg_temp_new_i64();
6686 gen_load_fpr64(ctx, fp0, fs);
6687 gen_helper_float_recip_d(fp0, fp0);
6688 gen_store_fpr64(ctx, fp0, fd);
6689 tcg_temp_free_i64(fp0);
6691 opn = "recip.d";
6692 break;
6693 case FOP(22, 17):
6694 check_cp1_64bitmode(ctx);
6696 TCGv_i64 fp0 = tcg_temp_new_i64();
6698 gen_load_fpr64(ctx, fp0, fs);
6699 gen_helper_float_rsqrt_d(fp0, fp0);
6700 gen_store_fpr64(ctx, fp0, fd);
6701 tcg_temp_free_i64(fp0);
6703 opn = "rsqrt.d";
6704 break;
6705 case FOP(28, 17):
6706 check_cp1_64bitmode(ctx);
6708 TCGv_i64 fp0 = tcg_temp_new_i64();
6709 TCGv_i64 fp1 = tcg_temp_new_i64();
6711 gen_load_fpr64(ctx, fp0, fs);
6712 gen_load_fpr64(ctx, fp1, ft);
6713 gen_helper_float_recip2_d(fp0, fp0, fp1);
6714 tcg_temp_free_i64(fp1);
6715 gen_store_fpr64(ctx, fp0, fd);
6716 tcg_temp_free_i64(fp0);
6718 opn = "recip2.d";
6719 break;
6720 case FOP(29, 17):
6721 check_cp1_64bitmode(ctx);
6723 TCGv_i64 fp0 = tcg_temp_new_i64();
6725 gen_load_fpr64(ctx, fp0, fs);
6726 gen_helper_float_recip1_d(fp0, fp0);
6727 gen_store_fpr64(ctx, fp0, fd);
6728 tcg_temp_free_i64(fp0);
6730 opn = "recip1.d";
6731 break;
6732 case FOP(30, 17):
6733 check_cp1_64bitmode(ctx);
6735 TCGv_i64 fp0 = tcg_temp_new_i64();
6737 gen_load_fpr64(ctx, fp0, fs);
6738 gen_helper_float_rsqrt1_d(fp0, fp0);
6739 gen_store_fpr64(ctx, fp0, fd);
6740 tcg_temp_free_i64(fp0);
6742 opn = "rsqrt1.d";
6743 break;
6744 case FOP(31, 17):
6745 check_cp1_64bitmode(ctx);
6747 TCGv_i64 fp0 = tcg_temp_new_i64();
6748 TCGv_i64 fp1 = tcg_temp_new_i64();
6750 gen_load_fpr64(ctx, fp0, fs);
6751 gen_load_fpr64(ctx, fp1, ft);
6752 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6753 tcg_temp_free_i64(fp1);
6754 gen_store_fpr64(ctx, fp0, fd);
6755 tcg_temp_free_i64(fp0);
6757 opn = "rsqrt2.d";
6758 break;
6759 case FOP(48, 17):
6760 case FOP(49, 17):
6761 case FOP(50, 17):
6762 case FOP(51, 17):
6763 case FOP(52, 17):
6764 case FOP(53, 17):
6765 case FOP(54, 17):
6766 case FOP(55, 17):
6767 case FOP(56, 17):
6768 case FOP(57, 17):
6769 case FOP(58, 17):
6770 case FOP(59, 17):
6771 case FOP(60, 17):
6772 case FOP(61, 17):
6773 case FOP(62, 17):
6774 case FOP(63, 17):
6776 TCGv_i64 fp0 = tcg_temp_new_i64();
6777 TCGv_i64 fp1 = tcg_temp_new_i64();
6779 gen_load_fpr64(ctx, fp0, fs);
6780 gen_load_fpr64(ctx, fp1, ft);
6781 if (ctx->opcode & (1 << 6)) {
6782 check_cop1x(ctx);
6783 check_cp1_registers(ctx, fs | ft);
6784 gen_cmpabs_d(func-48, fp0, fp1, cc);
6785 opn = condnames_abs[func-48];
6786 } else {
6787 check_cp1_registers(ctx, fs | ft);
6788 gen_cmp_d(func-48, fp0, fp1, cc);
6789 opn = condnames[func-48];
6791 tcg_temp_free_i64(fp0);
6792 tcg_temp_free_i64(fp1);
6794 break;
6795 case FOP(32, 17):
6796 check_cp1_registers(ctx, fs);
6798 TCGv_i32 fp32 = tcg_temp_new_i32();
6799 TCGv_i64 fp64 = tcg_temp_new_i64();
6801 gen_load_fpr64(ctx, fp64, fs);
6802 gen_helper_float_cvts_d(fp32, fp64);
6803 tcg_temp_free_i64(fp64);
6804 gen_store_fpr32(fp32, fd);
6805 tcg_temp_free_i32(fp32);
6807 opn = "cvt.s.d";
6808 break;
6809 case FOP(36, 17):
6810 check_cp1_registers(ctx, fs);
6812 TCGv_i32 fp32 = tcg_temp_new_i32();
6813 TCGv_i64 fp64 = tcg_temp_new_i64();
6815 gen_load_fpr64(ctx, fp64, fs);
6816 gen_helper_float_cvtw_d(fp32, fp64);
6817 tcg_temp_free_i64(fp64);
6818 gen_store_fpr32(fp32, fd);
6819 tcg_temp_free_i32(fp32);
6821 opn = "cvt.w.d";
6822 break;
6823 case FOP(37, 17):
6824 check_cp1_64bitmode(ctx);
6826 TCGv_i64 fp0 = tcg_temp_new_i64();
6828 gen_load_fpr64(ctx, fp0, fs);
6829 gen_helper_float_cvtl_d(fp0, fp0);
6830 gen_store_fpr64(ctx, fp0, fd);
6831 tcg_temp_free_i64(fp0);
6833 opn = "cvt.l.d";
6834 break;
6835 case FOP(32, 20):
6837 TCGv_i32 fp0 = tcg_temp_new_i32();
6839 gen_load_fpr32(fp0, fs);
6840 gen_helper_float_cvts_w(fp0, fp0);
6841 gen_store_fpr32(fp0, fd);
6842 tcg_temp_free_i32(fp0);
6844 opn = "cvt.s.w";
6845 break;
6846 case FOP(33, 20):
6847 check_cp1_registers(ctx, fd);
6849 TCGv_i32 fp32 = tcg_temp_new_i32();
6850 TCGv_i64 fp64 = tcg_temp_new_i64();
6852 gen_load_fpr32(fp32, fs);
6853 gen_helper_float_cvtd_w(fp64, fp32);
6854 tcg_temp_free_i32(fp32);
6855 gen_store_fpr64(ctx, fp64, fd);
6856 tcg_temp_free_i64(fp64);
6858 opn = "cvt.d.w";
6859 break;
6860 case FOP(32, 21):
6861 check_cp1_64bitmode(ctx);
6863 TCGv_i32 fp32 = tcg_temp_new_i32();
6864 TCGv_i64 fp64 = tcg_temp_new_i64();
6866 gen_load_fpr64(ctx, fp64, fs);
6867 gen_helper_float_cvts_l(fp32, fp64);
6868 tcg_temp_free_i64(fp64);
6869 gen_store_fpr32(fp32, fd);
6870 tcg_temp_free_i32(fp32);
6872 opn = "cvt.s.l";
6873 break;
6874 case FOP(33, 21):
6875 check_cp1_64bitmode(ctx);
6877 TCGv_i64 fp0 = tcg_temp_new_i64();
6879 gen_load_fpr64(ctx, fp0, fs);
6880 gen_helper_float_cvtd_l(fp0, fp0);
6881 gen_store_fpr64(ctx, fp0, fd);
6882 tcg_temp_free_i64(fp0);
6884 opn = "cvt.d.l";
6885 break;
6886 case FOP(38, 20):
6887 check_cp1_64bitmode(ctx);
6889 TCGv_i64 fp0 = tcg_temp_new_i64();
6891 gen_load_fpr64(ctx, fp0, fs);
6892 gen_helper_float_cvtps_pw(fp0, fp0);
6893 gen_store_fpr64(ctx, fp0, fd);
6894 tcg_temp_free_i64(fp0);
6896 opn = "cvt.ps.pw";
6897 break;
6898 case FOP(0, 22):
6899 check_cp1_64bitmode(ctx);
6901 TCGv_i64 fp0 = tcg_temp_new_i64();
6902 TCGv_i64 fp1 = tcg_temp_new_i64();
6904 gen_load_fpr64(ctx, fp0, fs);
6905 gen_load_fpr64(ctx, fp1, ft);
6906 gen_helper_float_add_ps(fp0, fp0, fp1);
6907 tcg_temp_free_i64(fp1);
6908 gen_store_fpr64(ctx, fp0, fd);
6909 tcg_temp_free_i64(fp0);
6911 opn = "add.ps";
6912 break;
6913 case FOP(1, 22):
6914 check_cp1_64bitmode(ctx);
6916 TCGv_i64 fp0 = tcg_temp_new_i64();
6917 TCGv_i64 fp1 = tcg_temp_new_i64();
6919 gen_load_fpr64(ctx, fp0, fs);
6920 gen_load_fpr64(ctx, fp1, ft);
6921 gen_helper_float_sub_ps(fp0, fp0, fp1);
6922 tcg_temp_free_i64(fp1);
6923 gen_store_fpr64(ctx, fp0, fd);
6924 tcg_temp_free_i64(fp0);
6926 opn = "sub.ps";
6927 break;
6928 case FOP(2, 22):
6929 check_cp1_64bitmode(ctx);
6931 TCGv_i64 fp0 = tcg_temp_new_i64();
6932 TCGv_i64 fp1 = tcg_temp_new_i64();
6934 gen_load_fpr64(ctx, fp0, fs);
6935 gen_load_fpr64(ctx, fp1, ft);
6936 gen_helper_float_mul_ps(fp0, fp0, fp1);
6937 tcg_temp_free_i64(fp1);
6938 gen_store_fpr64(ctx, fp0, fd);
6939 tcg_temp_free_i64(fp0);
6941 opn = "mul.ps";
6942 break;
6943 case FOP(5, 22):
6944 check_cp1_64bitmode(ctx);
6946 TCGv_i64 fp0 = tcg_temp_new_i64();
6948 gen_load_fpr64(ctx, fp0, fs);
6949 gen_helper_float_abs_ps(fp0, fp0);
6950 gen_store_fpr64(ctx, fp0, fd);
6951 tcg_temp_free_i64(fp0);
6953 opn = "abs.ps";
6954 break;
6955 case FOP(6, 22):
6956 check_cp1_64bitmode(ctx);
6958 TCGv_i64 fp0 = tcg_temp_new_i64();
6960 gen_load_fpr64(ctx, fp0, fs);
6961 gen_store_fpr64(ctx, fp0, fd);
6962 tcg_temp_free_i64(fp0);
6964 opn = "mov.ps";
6965 break;
6966 case FOP(7, 22):
6967 check_cp1_64bitmode(ctx);
6969 TCGv_i64 fp0 = tcg_temp_new_i64();
6971 gen_load_fpr64(ctx, fp0, fs);
6972 gen_helper_float_chs_ps(fp0, fp0);
6973 gen_store_fpr64(ctx, fp0, fd);
6974 tcg_temp_free_i64(fp0);
6976 opn = "neg.ps";
6977 break;
6978 case FOP(17, 22):
6979 check_cp1_64bitmode(ctx);
6980 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6981 opn = "movcf.ps";
6982 break;
6983 case FOP(18, 22):
6984 check_cp1_64bitmode(ctx);
6986 int l1 = gen_new_label();
6987 TCGv_i64 fp0;
6989 if (ft != 0)
6990 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6991 fp0 = tcg_temp_new_i64();
6992 gen_load_fpr64(ctx, fp0, fs);
6993 gen_store_fpr64(ctx, fp0, fd);
6994 tcg_temp_free_i64(fp0);
6995 gen_set_label(l1);
6997 opn = "movz.ps";
6998 break;
6999 case FOP(19, 22):
7000 check_cp1_64bitmode(ctx);
7002 int l1 = gen_new_label();
7003 TCGv_i64 fp0;
7005 if (ft != 0) {
7006 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7007 fp0 = tcg_temp_new_i64();
7008 gen_load_fpr64(ctx, fp0, fs);
7009 gen_store_fpr64(ctx, fp0, fd);
7010 tcg_temp_free_i64(fp0);
7011 gen_set_label(l1);
7014 opn = "movn.ps";
7015 break;
7016 case FOP(24, 22):
7017 check_cp1_64bitmode(ctx);
7019 TCGv_i64 fp0 = tcg_temp_new_i64();
7020 TCGv_i64 fp1 = tcg_temp_new_i64();
7022 gen_load_fpr64(ctx, fp0, ft);
7023 gen_load_fpr64(ctx, fp1, fs);
7024 gen_helper_float_addr_ps(fp0, fp0, fp1);
7025 tcg_temp_free_i64(fp1);
7026 gen_store_fpr64(ctx, fp0, fd);
7027 tcg_temp_free_i64(fp0);
7029 opn = "addr.ps";
7030 break;
7031 case FOP(26, 22):
7032 check_cp1_64bitmode(ctx);
7034 TCGv_i64 fp0 = tcg_temp_new_i64();
7035 TCGv_i64 fp1 = tcg_temp_new_i64();
7037 gen_load_fpr64(ctx, fp0, ft);
7038 gen_load_fpr64(ctx, fp1, fs);
7039 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7040 tcg_temp_free_i64(fp1);
7041 gen_store_fpr64(ctx, fp0, fd);
7042 tcg_temp_free_i64(fp0);
7044 opn = "mulr.ps";
7045 break;
7046 case FOP(28, 22):
7047 check_cp1_64bitmode(ctx);
7049 TCGv_i64 fp0 = tcg_temp_new_i64();
7050 TCGv_i64 fp1 = tcg_temp_new_i64();
7052 gen_load_fpr64(ctx, fp0, fs);
7053 gen_load_fpr64(ctx, fp1, fd);
7054 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7055 tcg_temp_free_i64(fp1);
7056 gen_store_fpr64(ctx, fp0, fd);
7057 tcg_temp_free_i64(fp0);
7059 opn = "recip2.ps";
7060 break;
7061 case FOP(29, 22):
7062 check_cp1_64bitmode(ctx);
7064 TCGv_i64 fp0 = tcg_temp_new_i64();
7066 gen_load_fpr64(ctx, fp0, fs);
7067 gen_helper_float_recip1_ps(fp0, fp0);
7068 gen_store_fpr64(ctx, fp0, fd);
7069 tcg_temp_free_i64(fp0);
7071 opn = "recip1.ps";
7072 break;
7073 case FOP(30, 22):
7074 check_cp1_64bitmode(ctx);
7076 TCGv_i64 fp0 = tcg_temp_new_i64();
7078 gen_load_fpr64(ctx, fp0, fs);
7079 gen_helper_float_rsqrt1_ps(fp0, fp0);
7080 gen_store_fpr64(ctx, fp0, fd);
7081 tcg_temp_free_i64(fp0);
7083 opn = "rsqrt1.ps";
7084 break;
7085 case FOP(31, 22):
7086 check_cp1_64bitmode(ctx);
7088 TCGv_i64 fp0 = tcg_temp_new_i64();
7089 TCGv_i64 fp1 = tcg_temp_new_i64();
7091 gen_load_fpr64(ctx, fp0, fs);
7092 gen_load_fpr64(ctx, fp1, ft);
7093 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7094 tcg_temp_free_i64(fp1);
7095 gen_store_fpr64(ctx, fp0, fd);
7096 tcg_temp_free_i64(fp0);
7098 opn = "rsqrt2.ps";
7099 break;
7100 case FOP(32, 22):
7101 check_cp1_64bitmode(ctx);
7103 TCGv_i32 fp0 = tcg_temp_new_i32();
7105 gen_load_fpr32h(fp0, fs);
7106 gen_helper_float_cvts_pu(fp0, fp0);
7107 gen_store_fpr32(fp0, fd);
7108 tcg_temp_free_i32(fp0);
7110 opn = "cvt.s.pu";
7111 break;
7112 case FOP(36, 22):
7113 check_cp1_64bitmode(ctx);
7115 TCGv_i64 fp0 = tcg_temp_new_i64();
7117 gen_load_fpr64(ctx, fp0, fs);
7118 gen_helper_float_cvtpw_ps(fp0, fp0);
7119 gen_store_fpr64(ctx, fp0, fd);
7120 tcg_temp_free_i64(fp0);
7122 opn = "cvt.pw.ps";
7123 break;
7124 case FOP(40, 22):
7125 check_cp1_64bitmode(ctx);
7127 TCGv_i32 fp0 = tcg_temp_new_i32();
7129 gen_load_fpr32(fp0, fs);
7130 gen_helper_float_cvts_pl(fp0, fp0);
7131 gen_store_fpr32(fp0, fd);
7132 tcg_temp_free_i32(fp0);
7134 opn = "cvt.s.pl";
7135 break;
7136 case FOP(44, 22):
7137 check_cp1_64bitmode(ctx);
7139 TCGv_i32 fp0 = tcg_temp_new_i32();
7140 TCGv_i32 fp1 = tcg_temp_new_i32();
7142 gen_load_fpr32(fp0, fs);
7143 gen_load_fpr32(fp1, ft);
7144 gen_store_fpr32h(fp0, fd);
7145 gen_store_fpr32(fp1, fd);
7146 tcg_temp_free_i32(fp0);
7147 tcg_temp_free_i32(fp1);
7149 opn = "pll.ps";
7150 break;
7151 case FOP(45, 22):
7152 check_cp1_64bitmode(ctx);
7154 TCGv_i32 fp0 = tcg_temp_new_i32();
7155 TCGv_i32 fp1 = tcg_temp_new_i32();
7157 gen_load_fpr32(fp0, fs);
7158 gen_load_fpr32h(fp1, ft);
7159 gen_store_fpr32(fp1, fd);
7160 gen_store_fpr32h(fp0, fd);
7161 tcg_temp_free_i32(fp0);
7162 tcg_temp_free_i32(fp1);
7164 opn = "plu.ps";
7165 break;
7166 case FOP(46, 22):
7167 check_cp1_64bitmode(ctx);
7169 TCGv_i32 fp0 = tcg_temp_new_i32();
7170 TCGv_i32 fp1 = tcg_temp_new_i32();
7172 gen_load_fpr32h(fp0, fs);
7173 gen_load_fpr32(fp1, ft);
7174 gen_store_fpr32(fp1, fd);
7175 gen_store_fpr32h(fp0, fd);
7176 tcg_temp_free_i32(fp0);
7177 tcg_temp_free_i32(fp1);
7179 opn = "pul.ps";
7180 break;
7181 case FOP(47, 22):
7182 check_cp1_64bitmode(ctx);
7184 TCGv_i32 fp0 = tcg_temp_new_i32();
7185 TCGv_i32 fp1 = tcg_temp_new_i32();
7187 gen_load_fpr32h(fp0, fs);
7188 gen_load_fpr32h(fp1, ft);
7189 gen_store_fpr32(fp1, fd);
7190 gen_store_fpr32h(fp0, fd);
7191 tcg_temp_free_i32(fp0);
7192 tcg_temp_free_i32(fp1);
7194 opn = "puu.ps";
7195 break;
7196 case FOP(48, 22):
7197 case FOP(49, 22):
7198 case FOP(50, 22):
7199 case FOP(51, 22):
7200 case FOP(52, 22):
7201 case FOP(53, 22):
7202 case FOP(54, 22):
7203 case FOP(55, 22):
7204 case FOP(56, 22):
7205 case FOP(57, 22):
7206 case FOP(58, 22):
7207 case FOP(59, 22):
7208 case FOP(60, 22):
7209 case FOP(61, 22):
7210 case FOP(62, 22):
7211 case FOP(63, 22):
7212 check_cp1_64bitmode(ctx);
7214 TCGv_i64 fp0 = tcg_temp_new_i64();
7215 TCGv_i64 fp1 = tcg_temp_new_i64();
7217 gen_load_fpr64(ctx, fp0, fs);
7218 gen_load_fpr64(ctx, fp1, ft);
7219 if (ctx->opcode & (1 << 6)) {
7220 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7221 opn = condnames_abs[func-48];
7222 } else {
7223 gen_cmp_ps(func-48, fp0, fp1, cc);
7224 opn = condnames[func-48];
7226 tcg_temp_free_i64(fp0);
7227 tcg_temp_free_i64(fp1);
7229 break;
7230 default:
7231 MIPS_INVAL(opn);
7232 generate_exception (ctx, EXCP_RI);
7233 return;
7235 switch (optype) {
7236 case BINOP:
7237 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7238 break;
7239 case CMPOP:
7240 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7241 break;
7242 default:
7243 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7244 break;
7248 /* Coprocessor 3 (FPU) */
7249 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7250 int fd, int fs, int base, int index)
7252 const char *opn = "extended float load/store";
7253 int store = 0;
7254 TCGv t0 = tcg_temp_new();
7256 if (base == 0) {
7257 gen_load_gpr(t0, index);
7258 } else if (index == 0) {
7259 gen_load_gpr(t0, base);
7260 } else {
7261 gen_load_gpr(t0, index);
7262 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
7264 /* Don't do NOP if destination is zero: we must perform the actual
7265 memory access. */
7266 save_cpu_state(ctx, 0);
7267 switch (opc) {
7268 case OPC_LWXC1:
7269 check_cop1x(ctx);
7271 TCGv_i32 fp0 = tcg_temp_new_i32();
7273 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7274 tcg_gen_trunc_tl_i32(fp0, t0);
7275 gen_store_fpr32(fp0, fd);
7276 tcg_temp_free_i32(fp0);
7278 opn = "lwxc1";
7279 break;
7280 case OPC_LDXC1:
7281 check_cop1x(ctx);
7282 check_cp1_registers(ctx, fd);
7284 TCGv_i64 fp0 = tcg_temp_new_i64();
7286 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7287 gen_store_fpr64(ctx, fp0, fd);
7288 tcg_temp_free_i64(fp0);
7290 opn = "ldxc1";
7291 break;
7292 case OPC_LUXC1:
7293 check_cp1_64bitmode(ctx);
7294 tcg_gen_andi_tl(t0, t0, ~0x7);
7296 TCGv_i64 fp0 = tcg_temp_new_i64();
7298 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7299 gen_store_fpr64(ctx, fp0, fd);
7300 tcg_temp_free_i64(fp0);
7302 opn = "luxc1";
7303 break;
7304 case OPC_SWXC1:
7305 check_cop1x(ctx);
7307 TCGv_i32 fp0 = tcg_temp_new_i32();
7308 TCGv t1 = tcg_temp_new();
7310 gen_load_fpr32(fp0, fs);
7311 tcg_gen_extu_i32_tl(t1, fp0);
7312 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7313 tcg_temp_free_i32(fp0);
7314 tcg_temp_free(t1);
7316 opn = "swxc1";
7317 store = 1;
7318 break;
7319 case OPC_SDXC1:
7320 check_cop1x(ctx);
7321 check_cp1_registers(ctx, fs);
7323 TCGv_i64 fp0 = tcg_temp_new_i64();
7325 gen_load_fpr64(ctx, fp0, fs);
7326 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7327 tcg_temp_free_i64(fp0);
7329 opn = "sdxc1";
7330 store = 1;
7331 break;
7332 case OPC_SUXC1:
7333 check_cp1_64bitmode(ctx);
7334 tcg_gen_andi_tl(t0, t0, ~0x7);
7336 TCGv_i64 fp0 = tcg_temp_new_i64();
7338 gen_load_fpr64(ctx, fp0, fs);
7339 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7340 tcg_temp_free_i64(fp0);
7342 opn = "suxc1";
7343 store = 1;
7344 break;
7346 tcg_temp_free(t0);
7347 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7348 regnames[index], regnames[base]);
7351 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7352 int fd, int fr, int fs, int ft)
7354 const char *opn = "flt3_arith";
7356 switch (opc) {
7357 case OPC_ALNV_PS:
7358 check_cp1_64bitmode(ctx);
7360 TCGv t0 = tcg_temp_local_new();
7361 TCGv_i32 fp = tcg_temp_new_i32();
7362 TCGv_i32 fph = tcg_temp_new_i32();
7363 int l1 = gen_new_label();
7364 int l2 = gen_new_label();
7366 gen_load_gpr(t0, fr);
7367 tcg_gen_andi_tl(t0, t0, 0x7);
7369 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7370 gen_load_fpr32(fp, fs);
7371 gen_load_fpr32h(fph, fs);
7372 gen_store_fpr32(fp, fd);
7373 gen_store_fpr32h(fph, fd);
7374 tcg_gen_br(l2);
7375 gen_set_label(l1);
7376 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7377 tcg_temp_free(t0);
7378 #ifdef TARGET_WORDS_BIGENDIAN
7379 gen_load_fpr32(fp, fs);
7380 gen_load_fpr32h(fph, ft);
7381 gen_store_fpr32h(fp, fd);
7382 gen_store_fpr32(fph, fd);
7383 #else
7384 gen_load_fpr32h(fph, fs);
7385 gen_load_fpr32(fp, ft);
7386 gen_store_fpr32(fph, fd);
7387 gen_store_fpr32h(fp, fd);
7388 #endif
7389 gen_set_label(l2);
7390 tcg_temp_free_i32(fp);
7391 tcg_temp_free_i32(fph);
7393 opn = "alnv.ps";
7394 break;
7395 case OPC_MADD_S:
7396 check_cop1x(ctx);
7398 TCGv_i32 fp0 = tcg_temp_new_i32();
7399 TCGv_i32 fp1 = tcg_temp_new_i32();
7400 TCGv_i32 fp2 = tcg_temp_new_i32();
7402 gen_load_fpr32(fp0, fs);
7403 gen_load_fpr32(fp1, ft);
7404 gen_load_fpr32(fp2, fr);
7405 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7406 tcg_temp_free_i32(fp0);
7407 tcg_temp_free_i32(fp1);
7408 gen_store_fpr32(fp2, fd);
7409 tcg_temp_free_i32(fp2);
7411 opn = "madd.s";
7412 break;
7413 case OPC_MADD_D:
7414 check_cop1x(ctx);
7415 check_cp1_registers(ctx, fd | fs | ft | fr);
7417 TCGv_i64 fp0 = tcg_temp_new_i64();
7418 TCGv_i64 fp1 = tcg_temp_new_i64();
7419 TCGv_i64 fp2 = tcg_temp_new_i64();
7421 gen_load_fpr64(ctx, fp0, fs);
7422 gen_load_fpr64(ctx, fp1, ft);
7423 gen_load_fpr64(ctx, fp2, fr);
7424 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7425 tcg_temp_free_i64(fp0);
7426 tcg_temp_free_i64(fp1);
7427 gen_store_fpr64(ctx, fp2, fd);
7428 tcg_temp_free_i64(fp2);
7430 opn = "madd.d";
7431 break;
7432 case OPC_MADD_PS:
7433 check_cp1_64bitmode(ctx);
7435 TCGv_i64 fp0 = tcg_temp_new_i64();
7436 TCGv_i64 fp1 = tcg_temp_new_i64();
7437 TCGv_i64 fp2 = tcg_temp_new_i64();
7439 gen_load_fpr64(ctx, fp0, fs);
7440 gen_load_fpr64(ctx, fp1, ft);
7441 gen_load_fpr64(ctx, fp2, fr);
7442 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7443 tcg_temp_free_i64(fp0);
7444 tcg_temp_free_i64(fp1);
7445 gen_store_fpr64(ctx, fp2, fd);
7446 tcg_temp_free_i64(fp2);
7448 opn = "madd.ps";
7449 break;
7450 case OPC_MSUB_S:
7451 check_cop1x(ctx);
7453 TCGv_i32 fp0 = tcg_temp_new_i32();
7454 TCGv_i32 fp1 = tcg_temp_new_i32();
7455 TCGv_i32 fp2 = tcg_temp_new_i32();
7457 gen_load_fpr32(fp0, fs);
7458 gen_load_fpr32(fp1, ft);
7459 gen_load_fpr32(fp2, fr);
7460 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7461 tcg_temp_free_i32(fp0);
7462 tcg_temp_free_i32(fp1);
7463 gen_store_fpr32(fp2, fd);
7464 tcg_temp_free_i32(fp2);
7466 opn = "msub.s";
7467 break;
7468 case OPC_MSUB_D:
7469 check_cop1x(ctx);
7470 check_cp1_registers(ctx, fd | fs | ft | fr);
7472 TCGv_i64 fp0 = tcg_temp_new_i64();
7473 TCGv_i64 fp1 = tcg_temp_new_i64();
7474 TCGv_i64 fp2 = tcg_temp_new_i64();
7476 gen_load_fpr64(ctx, fp0, fs);
7477 gen_load_fpr64(ctx, fp1, ft);
7478 gen_load_fpr64(ctx, fp2, fr);
7479 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7480 tcg_temp_free_i64(fp0);
7481 tcg_temp_free_i64(fp1);
7482 gen_store_fpr64(ctx, fp2, fd);
7483 tcg_temp_free_i64(fp2);
7485 opn = "msub.d";
7486 break;
7487 case OPC_MSUB_PS:
7488 check_cp1_64bitmode(ctx);
7490 TCGv_i64 fp0 = tcg_temp_new_i64();
7491 TCGv_i64 fp1 = tcg_temp_new_i64();
7492 TCGv_i64 fp2 = tcg_temp_new_i64();
7494 gen_load_fpr64(ctx, fp0, fs);
7495 gen_load_fpr64(ctx, fp1, ft);
7496 gen_load_fpr64(ctx, fp2, fr);
7497 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7498 tcg_temp_free_i64(fp0);
7499 tcg_temp_free_i64(fp1);
7500 gen_store_fpr64(ctx, fp2, fd);
7501 tcg_temp_free_i64(fp2);
7503 opn = "msub.ps";
7504 break;
7505 case OPC_NMADD_S:
7506 check_cop1x(ctx);
7508 TCGv_i32 fp0 = tcg_temp_new_i32();
7509 TCGv_i32 fp1 = tcg_temp_new_i32();
7510 TCGv_i32 fp2 = tcg_temp_new_i32();
7512 gen_load_fpr32(fp0, fs);
7513 gen_load_fpr32(fp1, ft);
7514 gen_load_fpr32(fp2, fr);
7515 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7516 tcg_temp_free_i32(fp0);
7517 tcg_temp_free_i32(fp1);
7518 gen_store_fpr32(fp2, fd);
7519 tcg_temp_free_i32(fp2);
7521 opn = "nmadd.s";
7522 break;
7523 case OPC_NMADD_D:
7524 check_cop1x(ctx);
7525 check_cp1_registers(ctx, fd | fs | ft | fr);
7527 TCGv_i64 fp0 = tcg_temp_new_i64();
7528 TCGv_i64 fp1 = tcg_temp_new_i64();
7529 TCGv_i64 fp2 = tcg_temp_new_i64();
7531 gen_load_fpr64(ctx, fp0, fs);
7532 gen_load_fpr64(ctx, fp1, ft);
7533 gen_load_fpr64(ctx, fp2, fr);
7534 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7535 tcg_temp_free_i64(fp0);
7536 tcg_temp_free_i64(fp1);
7537 gen_store_fpr64(ctx, fp2, fd);
7538 tcg_temp_free_i64(fp2);
7540 opn = "nmadd.d";
7541 break;
7542 case OPC_NMADD_PS:
7543 check_cp1_64bitmode(ctx);
7545 TCGv_i64 fp0 = tcg_temp_new_i64();
7546 TCGv_i64 fp1 = tcg_temp_new_i64();
7547 TCGv_i64 fp2 = tcg_temp_new_i64();
7549 gen_load_fpr64(ctx, fp0, fs);
7550 gen_load_fpr64(ctx, fp1, ft);
7551 gen_load_fpr64(ctx, fp2, fr);
7552 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7553 tcg_temp_free_i64(fp0);
7554 tcg_temp_free_i64(fp1);
7555 gen_store_fpr64(ctx, fp2, fd);
7556 tcg_temp_free_i64(fp2);
7558 opn = "nmadd.ps";
7559 break;
7560 case OPC_NMSUB_S:
7561 check_cop1x(ctx);
7563 TCGv_i32 fp0 = tcg_temp_new_i32();
7564 TCGv_i32 fp1 = tcg_temp_new_i32();
7565 TCGv_i32 fp2 = tcg_temp_new_i32();
7567 gen_load_fpr32(fp0, fs);
7568 gen_load_fpr32(fp1, ft);
7569 gen_load_fpr32(fp2, fr);
7570 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7571 tcg_temp_free_i32(fp0);
7572 tcg_temp_free_i32(fp1);
7573 gen_store_fpr32(fp2, fd);
7574 tcg_temp_free_i32(fp2);
7576 opn = "nmsub.s";
7577 break;
7578 case OPC_NMSUB_D:
7579 check_cop1x(ctx);
7580 check_cp1_registers(ctx, fd | fs | ft | fr);
7582 TCGv_i64 fp0 = tcg_temp_new_i64();
7583 TCGv_i64 fp1 = tcg_temp_new_i64();
7584 TCGv_i64 fp2 = tcg_temp_new_i64();
7586 gen_load_fpr64(ctx, fp0, fs);
7587 gen_load_fpr64(ctx, fp1, ft);
7588 gen_load_fpr64(ctx, fp2, fr);
7589 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7590 tcg_temp_free_i64(fp0);
7591 tcg_temp_free_i64(fp1);
7592 gen_store_fpr64(ctx, fp2, fd);
7593 tcg_temp_free_i64(fp2);
7595 opn = "nmsub.d";
7596 break;
7597 case OPC_NMSUB_PS:
7598 check_cp1_64bitmode(ctx);
7600 TCGv_i64 fp0 = tcg_temp_new_i64();
7601 TCGv_i64 fp1 = tcg_temp_new_i64();
7602 TCGv_i64 fp2 = tcg_temp_new_i64();
7604 gen_load_fpr64(ctx, fp0, fs);
7605 gen_load_fpr64(ctx, fp1, ft);
7606 gen_load_fpr64(ctx, fp2, fr);
7607 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7608 tcg_temp_free_i64(fp0);
7609 tcg_temp_free_i64(fp1);
7610 gen_store_fpr64(ctx, fp2, fd);
7611 tcg_temp_free_i64(fp2);
7613 opn = "nmsub.ps";
7614 break;
7615 default:
7616 MIPS_INVAL(opn);
7617 generate_exception (ctx, EXCP_RI);
7618 return;
7620 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7621 fregnames[fs], fregnames[ft]);
7624 /* ISA extensions (ASEs) */
7625 /* MIPS16 extension to MIPS32 */
7626 /* SmartMIPS extension to MIPS32 */
7628 #if defined(TARGET_MIPS64)
7630 /* MDMX extension to MIPS64 */
7632 #endif
7634 static void decode_opc (CPUState *env, DisasContext *ctx)
7636 int32_t offset;
7637 int rs, rt, rd, sa;
7638 uint32_t op, op1, op2;
7639 int16_t imm;
7641 /* make sure instructions are on a word boundary */
7642 if (ctx->pc & 0x3) {
7643 env->CP0_BadVAddr = ctx->pc;
7644 generate_exception(ctx, EXCP_AdEL);
7645 return;
7648 /* Handle blikely not taken case */
7649 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7650 int l1 = gen_new_label();
7652 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7653 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7654 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
7655 gen_goto_tb(ctx, 1, ctx->pc + 4);
7656 gen_set_label(l1);
7658 op = MASK_OP_MAJOR(ctx->opcode);
7659 rs = (ctx->opcode >> 21) & 0x1f;
7660 rt = (ctx->opcode >> 16) & 0x1f;
7661 rd = (ctx->opcode >> 11) & 0x1f;
7662 sa = (ctx->opcode >> 6) & 0x1f;
7663 imm = (int16_t)ctx->opcode;
7664 switch (op) {
7665 case OPC_SPECIAL:
7666 op1 = MASK_SPECIAL(ctx->opcode);
7667 switch (op1) {
7668 case OPC_SLL: /* Shift with immediate */
7669 case OPC_SRA:
7670 case OPC_SRL:
7671 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7672 break;
7673 case OPC_MOVN: /* Conditional move */
7674 case OPC_MOVZ:
7675 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7676 gen_cond_move(env, op1, rd, rs, rt);
7677 break;
7678 case OPC_ADD ... OPC_SUBU:
7679 gen_arith(env, ctx, op1, rd, rs, rt);
7680 break;
7681 case OPC_SLLV: /* Shifts */
7682 case OPC_SRLV:
7683 case OPC_SRAV:
7684 gen_shift(env, ctx, op1, rd, rs, rt);
7685 break;
7686 case OPC_SLT: /* Set on less than */
7687 case OPC_SLTU:
7688 gen_slt(env, op1, rd, rs, rt);
7689 break;
7690 case OPC_AND: /* Logic*/
7691 case OPC_OR:
7692 case OPC_NOR:
7693 case OPC_XOR:
7694 gen_logic(env, op1, rd, rs, rt);
7695 break;
7696 case OPC_MULT ... OPC_DIVU:
7697 if (sa) {
7698 check_insn(env, ctx, INSN_VR54XX);
7699 op1 = MASK_MUL_VR54XX(ctx->opcode);
7700 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7701 } else
7702 gen_muldiv(ctx, op1, rs, rt);
7703 break;
7704 case OPC_JR ... OPC_JALR:
7705 gen_compute_branch(ctx, op1, rs, rd, sa);
7706 return;
7707 case OPC_TGE ... OPC_TEQ: /* Traps */
7708 case OPC_TNE:
7709 gen_trap(ctx, op1, rs, rt, -1);
7710 break;
7711 case OPC_MFHI: /* Move from HI/LO */
7712 case OPC_MFLO:
7713 gen_HILO(ctx, op1, rd);
7714 break;
7715 case OPC_MTHI:
7716 case OPC_MTLO: /* Move to HI/LO */
7717 gen_HILO(ctx, op1, rs);
7718 break;
7719 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7720 #ifdef MIPS_STRICT_STANDARD
7721 MIPS_INVAL("PMON / selsl");
7722 generate_exception(ctx, EXCP_RI);
7723 #else
7724 gen_helper_0i(pmon, sa);
7725 #endif
7726 break;
7727 case OPC_SYSCALL:
7728 generate_exception(ctx, EXCP_SYSCALL);
7729 ctx->bstate = BS_STOP;
7730 break;
7731 case OPC_BREAK:
7732 generate_exception(ctx, EXCP_BREAK);
7733 break;
7734 case OPC_SPIM:
7735 #ifdef MIPS_STRICT_STANDARD
7736 MIPS_INVAL("SPIM");
7737 generate_exception(ctx, EXCP_RI);
7738 #else
7739 /* Implemented as RI exception for now. */
7740 MIPS_INVAL("spim (unofficial)");
7741 generate_exception(ctx, EXCP_RI);
7742 #endif
7743 break;
7744 case OPC_SYNC:
7745 /* Treat as NOP. */
7746 break;
7748 case OPC_MOVCI:
7749 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7750 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7751 check_cp1_enabled(ctx);
7752 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7753 (ctx->opcode >> 16) & 1);
7754 } else {
7755 generate_exception_err(ctx, EXCP_CpU, 1);
7757 break;
7759 #if defined(TARGET_MIPS64)
7760 /* MIPS64 specific opcodes */
7761 case OPC_DSLL:
7762 case OPC_DSRA:
7763 case OPC_DSRL:
7764 case OPC_DSLL32:
7765 case OPC_DSRA32:
7766 case OPC_DSRL32:
7767 check_insn(env, ctx, ISA_MIPS3);
7768 check_mips_64(ctx);
7769 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7770 break;
7771 case OPC_DADD ... OPC_DSUBU:
7772 check_insn(env, ctx, ISA_MIPS3);
7773 check_mips_64(ctx);
7774 gen_arith(env, ctx, op1, rd, rs, rt);
7775 break;
7776 case OPC_DSLLV:
7777 case OPC_DSRAV:
7778 case OPC_DSRLV:
7779 check_insn(env, ctx, ISA_MIPS3);
7780 check_mips_64(ctx);
7781 gen_shift(env, ctx, op1, rd, rs, rt);
7782 break;
7783 case OPC_DMULT ... OPC_DDIVU:
7784 check_insn(env, ctx, ISA_MIPS3);
7785 check_mips_64(ctx);
7786 gen_muldiv(ctx, op1, rs, rt);
7787 break;
7788 #endif
7789 default: /* Invalid */
7790 MIPS_INVAL("special");
7791 generate_exception(ctx, EXCP_RI);
7792 break;
7794 break;
7795 case OPC_SPECIAL2:
7796 op1 = MASK_SPECIAL2(ctx->opcode);
7797 switch (op1) {
7798 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7799 case OPC_MSUB ... OPC_MSUBU:
7800 check_insn(env, ctx, ISA_MIPS32);
7801 gen_muldiv(ctx, op1, rs, rt);
7802 break;
7803 case OPC_MUL:
7804 gen_arith(env, ctx, op1, rd, rs, rt);
7805 break;
7806 case OPC_CLO:
7807 case OPC_CLZ:
7808 check_insn(env, ctx, ISA_MIPS32);
7809 gen_cl(ctx, op1, rd, rs);
7810 break;
7811 case OPC_SDBBP:
7812 /* XXX: not clear which exception should be raised
7813 * when in debug mode...
7815 check_insn(env, ctx, ISA_MIPS32);
7816 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7817 generate_exception(ctx, EXCP_DBp);
7818 } else {
7819 generate_exception(ctx, EXCP_DBp);
7821 /* Treat as NOP. */
7822 break;
7823 #if defined(TARGET_MIPS64)
7824 case OPC_DCLO:
7825 case OPC_DCLZ:
7826 check_insn(env, ctx, ISA_MIPS64);
7827 check_mips_64(ctx);
7828 gen_cl(ctx, op1, rd, rs);
7829 break;
7830 #endif
7831 default: /* Invalid */
7832 MIPS_INVAL("special2");
7833 generate_exception(ctx, EXCP_RI);
7834 break;
7836 break;
7837 case OPC_SPECIAL3:
7838 op1 = MASK_SPECIAL3(ctx->opcode);
7839 switch (op1) {
7840 case OPC_EXT:
7841 case OPC_INS:
7842 check_insn(env, ctx, ISA_MIPS32R2);
7843 gen_bitops(ctx, op1, rt, rs, sa, rd);
7844 break;
7845 case OPC_BSHFL:
7846 check_insn(env, ctx, ISA_MIPS32R2);
7847 op2 = MASK_BSHFL(ctx->opcode);
7848 gen_bshfl(ctx, op2, rt, rd);
7849 break;
7850 case OPC_RDHWR:
7851 check_insn(env, ctx, ISA_MIPS32R2);
7853 TCGv t0 = tcg_temp_new();
7855 switch (rd) {
7856 case 0:
7857 save_cpu_state(ctx, 1);
7858 gen_helper_rdhwr_cpunum(t0);
7859 gen_store_gpr(t0, rt);
7860 break;
7861 case 1:
7862 save_cpu_state(ctx, 1);
7863 gen_helper_rdhwr_synci_step(t0);
7864 gen_store_gpr(t0, rt);
7865 break;
7866 case 2:
7867 save_cpu_state(ctx, 1);
7868 gen_helper_rdhwr_cc(t0);
7869 gen_store_gpr(t0, rt);
7870 break;
7871 case 3:
7872 save_cpu_state(ctx, 1);
7873 gen_helper_rdhwr_ccres(t0);
7874 gen_store_gpr(t0, rt);
7875 break;
7876 case 29:
7877 #if defined(CONFIG_USER_ONLY)
7878 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7879 gen_store_gpr(t0, rt);
7880 break;
7881 #else
7882 /* XXX: Some CPUs implement this in hardware.
7883 Not supported yet. */
7884 #endif
7885 default: /* Invalid */
7886 MIPS_INVAL("rdhwr");
7887 generate_exception(ctx, EXCP_RI);
7888 break;
7890 tcg_temp_free(t0);
7892 break;
7893 case OPC_FORK:
7894 check_insn(env, ctx, ASE_MT);
7896 TCGv t0 = tcg_temp_new();
7897 TCGv t1 = tcg_temp_new();
7899 gen_load_gpr(t0, rt);
7900 gen_load_gpr(t1, rs);
7901 gen_helper_fork(t0, t1);
7902 tcg_temp_free(t0);
7903 tcg_temp_free(t1);
7905 break;
7906 case OPC_YIELD:
7907 check_insn(env, ctx, ASE_MT);
7909 TCGv t0 = tcg_temp_new();
7911 save_cpu_state(ctx, 1);
7912 gen_load_gpr(t0, rs);
7913 gen_helper_yield(t0, t0);
7914 gen_store_gpr(t0, rd);
7915 tcg_temp_free(t0);
7917 break;
7918 #if defined(TARGET_MIPS64)
7919 case OPC_DEXTM ... OPC_DEXT:
7920 case OPC_DINSM ... OPC_DINS:
7921 check_insn(env, ctx, ISA_MIPS64R2);
7922 check_mips_64(ctx);
7923 gen_bitops(ctx, op1, rt, rs, sa, rd);
7924 break;
7925 case OPC_DBSHFL:
7926 check_insn(env, ctx, ISA_MIPS64R2);
7927 check_mips_64(ctx);
7928 op2 = MASK_DBSHFL(ctx->opcode);
7929 gen_bshfl(ctx, op2, rt, rd);
7930 break;
7931 #endif
7932 default: /* Invalid */
7933 MIPS_INVAL("special3");
7934 generate_exception(ctx, EXCP_RI);
7935 break;
7937 break;
7938 case OPC_REGIMM:
7939 op1 = MASK_REGIMM(ctx->opcode);
7940 switch (op1) {
7941 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7942 case OPC_BLTZAL ... OPC_BGEZALL:
7943 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
7944 return;
7945 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7946 case OPC_TNEI:
7947 gen_trap(ctx, op1, rs, -1, imm);
7948 break;
7949 case OPC_SYNCI:
7950 check_insn(env, ctx, ISA_MIPS32R2);
7951 /* Treat as NOP. */
7952 break;
7953 default: /* Invalid */
7954 MIPS_INVAL("regimm");
7955 generate_exception(ctx, EXCP_RI);
7956 break;
7958 break;
7959 case OPC_CP0:
7960 check_cp0_enabled(ctx);
7961 op1 = MASK_CP0(ctx->opcode);
7962 switch (op1) {
7963 case OPC_MFC0:
7964 case OPC_MTC0:
7965 case OPC_MFTR:
7966 case OPC_MTTR:
7967 #if defined(TARGET_MIPS64)
7968 case OPC_DMFC0:
7969 case OPC_DMTC0:
7970 #endif
7971 #ifndef CONFIG_USER_ONLY
7972 gen_cp0(env, ctx, op1, rt, rd);
7973 #endif /* !CONFIG_USER_ONLY */
7974 break;
7975 case OPC_C0_FIRST ... OPC_C0_LAST:
7976 #ifndef CONFIG_USER_ONLY
7977 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
7978 #endif /* !CONFIG_USER_ONLY */
7979 break;
7980 case OPC_MFMC0:
7981 #ifndef CONFIG_USER_ONLY
7983 TCGv t0 = tcg_temp_new();
7985 op2 = MASK_MFMC0(ctx->opcode);
7986 switch (op2) {
7987 case OPC_DMT:
7988 check_insn(env, ctx, ASE_MT);
7989 gen_helper_dmt(t0, t0);
7990 gen_store_gpr(t0, rt);
7991 break;
7992 case OPC_EMT:
7993 check_insn(env, ctx, ASE_MT);
7994 gen_helper_emt(t0, t0);
7995 gen_store_gpr(t0, rt);
7996 break;
7997 case OPC_DVPE:
7998 check_insn(env, ctx, ASE_MT);
7999 gen_helper_dvpe(t0, t0);
8000 gen_store_gpr(t0, rt);
8001 break;
8002 case OPC_EVPE:
8003 check_insn(env, ctx, ASE_MT);
8004 gen_helper_evpe(t0, t0);
8005 gen_store_gpr(t0, rt);
8006 break;
8007 case OPC_DI:
8008 check_insn(env, ctx, ISA_MIPS32R2);
8009 save_cpu_state(ctx, 1);
8010 gen_helper_di(t0);
8011 gen_store_gpr(t0, rt);
8012 /* Stop translation as we may have switched the execution mode */
8013 ctx->bstate = BS_STOP;
8014 break;
8015 case OPC_EI:
8016 check_insn(env, ctx, ISA_MIPS32R2);
8017 save_cpu_state(ctx, 1);
8018 gen_helper_ei(t0);
8019 gen_store_gpr(t0, rt);
8020 /* Stop translation as we may have switched the execution mode */
8021 ctx->bstate = BS_STOP;
8022 break;
8023 default: /* Invalid */
8024 MIPS_INVAL("mfmc0");
8025 generate_exception(ctx, EXCP_RI);
8026 break;
8028 tcg_temp_free(t0);
8030 #endif /* !CONFIG_USER_ONLY */
8031 break;
8032 case OPC_RDPGPR:
8033 check_insn(env, ctx, ISA_MIPS32R2);
8034 gen_load_srsgpr(rt, rd);
8035 break;
8036 case OPC_WRPGPR:
8037 check_insn(env, ctx, ISA_MIPS32R2);
8038 gen_store_srsgpr(rt, rd);
8039 break;
8040 default:
8041 MIPS_INVAL("cp0");
8042 generate_exception(ctx, EXCP_RI);
8043 break;
8045 break;
8046 case OPC_ADDI: /* Arithmetic with immediate opcode */
8047 case OPC_ADDIU:
8048 gen_arith_imm(env, ctx, op, rt, rs, imm);
8049 break;
8050 case OPC_SLTI: /* Set on less than with immediate opcode */
8051 case OPC_SLTIU:
8052 gen_slt_imm(env, op, rt, rs, imm);
8053 break;
8054 case OPC_ANDI: /* Arithmetic with immediate opcode */
8055 case OPC_LUI:
8056 case OPC_ORI:
8057 case OPC_XORI:
8058 gen_logic_imm(env, op, rt, rs, imm);
8059 break;
8060 case OPC_J ... OPC_JAL: /* Jump */
8061 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8062 gen_compute_branch(ctx, op, rs, rt, offset);
8063 return;
8064 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8065 case OPC_BEQL ... OPC_BGTZL:
8066 gen_compute_branch(ctx, op, rs, rt, imm << 2);
8067 return;
8068 case OPC_LB ... OPC_LWR: /* Load and stores */
8069 case OPC_SB ... OPC_SW:
8070 case OPC_SWR:
8071 case OPC_LL:
8072 gen_ldst(ctx, op, rt, rs, imm);
8073 break;
8074 case OPC_SC:
8075 gen_st_cond(ctx, op, rt, rs, imm);
8076 break;
8077 case OPC_CACHE:
8078 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
8079 /* Treat as NOP. */
8080 break;
8081 case OPC_PREF:
8082 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8083 /* Treat as NOP. */
8084 break;
8086 /* Floating point (COP1). */
8087 case OPC_LWC1:
8088 case OPC_LDC1:
8089 case OPC_SWC1:
8090 case OPC_SDC1:
8091 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8092 check_cp1_enabled(ctx);
8093 gen_flt_ldst(ctx, op, rt, rs, imm);
8094 } else {
8095 generate_exception_err(ctx, EXCP_CpU, 1);
8097 break;
8099 case OPC_CP1:
8100 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8101 check_cp1_enabled(ctx);
8102 op1 = MASK_CP1(ctx->opcode);
8103 switch (op1) {
8104 case OPC_MFHC1:
8105 case OPC_MTHC1:
8106 check_insn(env, ctx, ISA_MIPS32R2);
8107 case OPC_MFC1:
8108 case OPC_CFC1:
8109 case OPC_MTC1:
8110 case OPC_CTC1:
8111 gen_cp1(ctx, op1, rt, rd);
8112 break;
8113 #if defined(TARGET_MIPS64)
8114 case OPC_DMFC1:
8115 case OPC_DMTC1:
8116 check_insn(env, ctx, ISA_MIPS3);
8117 gen_cp1(ctx, op1, rt, rd);
8118 break;
8119 #endif
8120 case OPC_BC1ANY2:
8121 case OPC_BC1ANY4:
8122 check_cop1x(ctx);
8123 check_insn(env, ctx, ASE_MIPS3D);
8124 /* fall through */
8125 case OPC_BC1:
8126 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8127 (rt >> 2) & 0x7, imm << 2);
8128 return;
8129 case OPC_S_FMT:
8130 case OPC_D_FMT:
8131 case OPC_W_FMT:
8132 case OPC_L_FMT:
8133 case OPC_PS_FMT:
8134 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8135 (imm >> 8) & 0x7);
8136 break;
8137 default:
8138 MIPS_INVAL("cp1");
8139 generate_exception (ctx, EXCP_RI);
8140 break;
8142 } else {
8143 generate_exception_err(ctx, EXCP_CpU, 1);
8145 break;
8147 /* COP2. */
8148 case OPC_LWC2:
8149 case OPC_LDC2:
8150 case OPC_SWC2:
8151 case OPC_SDC2:
8152 case OPC_CP2:
8153 /* COP2: Not implemented. */
8154 generate_exception_err(ctx, EXCP_CpU, 2);
8155 break;
8157 case OPC_CP3:
8158 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8159 check_cp1_enabled(ctx);
8160 op1 = MASK_CP3(ctx->opcode);
8161 switch (op1) {
8162 case OPC_LWXC1:
8163 case OPC_LDXC1:
8164 case OPC_LUXC1:
8165 case OPC_SWXC1:
8166 case OPC_SDXC1:
8167 case OPC_SUXC1:
8168 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8169 break;
8170 case OPC_PREFX:
8171 /* Treat as NOP. */
8172 break;
8173 case OPC_ALNV_PS:
8174 case OPC_MADD_S:
8175 case OPC_MADD_D:
8176 case OPC_MADD_PS:
8177 case OPC_MSUB_S:
8178 case OPC_MSUB_D:
8179 case OPC_MSUB_PS:
8180 case OPC_NMADD_S:
8181 case OPC_NMADD_D:
8182 case OPC_NMADD_PS:
8183 case OPC_NMSUB_S:
8184 case OPC_NMSUB_D:
8185 case OPC_NMSUB_PS:
8186 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8187 break;
8188 default:
8189 MIPS_INVAL("cp3");
8190 generate_exception (ctx, EXCP_RI);
8191 break;
8193 } else {
8194 generate_exception_err(ctx, EXCP_CpU, 1);
8196 break;
8198 #if defined(TARGET_MIPS64)
8199 /* MIPS64 opcodes */
8200 case OPC_LWU:
8201 case OPC_LDL ... OPC_LDR:
8202 case OPC_SDL ... OPC_SDR:
8203 case OPC_LLD:
8204 case OPC_LD:
8205 case OPC_SD:
8206 check_insn(env, ctx, ISA_MIPS3);
8207 check_mips_64(ctx);
8208 gen_ldst(ctx, op, rt, rs, imm);
8209 break;
8210 case OPC_SCD:
8211 check_insn(env, ctx, ISA_MIPS3);
8212 check_mips_64(ctx);
8213 gen_st_cond(ctx, op, rt, rs, imm);
8214 break;
8215 case OPC_DADDI:
8216 case OPC_DADDIU:
8217 check_insn(env, ctx, ISA_MIPS3);
8218 check_mips_64(ctx);
8219 gen_arith_imm(env, ctx, op, rt, rs, imm);
8220 break;
8221 #endif
8222 case OPC_JALX:
8223 check_insn(env, ctx, ASE_MIPS16);
8224 /* MIPS16: Not implemented. */
8225 case OPC_MDMX:
8226 check_insn(env, ctx, ASE_MDMX);
8227 /* MDMX: Not implemented. */
8228 default: /* Invalid */
8229 MIPS_INVAL("major opcode");
8230 generate_exception(ctx, EXCP_RI);
8231 break;
8233 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8234 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8235 /* Branches completion */
8236 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8237 ctx->bstate = BS_BRANCH;
8238 save_cpu_state(ctx, 0);
8239 /* FIXME: Need to clear can_do_io. */
8240 switch (hflags) {
8241 case MIPS_HFLAG_B:
8242 /* unconditional branch */
8243 MIPS_DEBUG("unconditional branch");
8244 gen_goto_tb(ctx, 0, ctx->btarget);
8245 break;
8246 case MIPS_HFLAG_BL:
8247 /* blikely taken case */
8248 MIPS_DEBUG("blikely branch taken");
8249 gen_goto_tb(ctx, 0, ctx->btarget);
8250 break;
8251 case MIPS_HFLAG_BC:
8252 /* Conditional branch */
8253 MIPS_DEBUG("conditional branch");
8255 int l1 = gen_new_label();
8257 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8258 gen_goto_tb(ctx, 1, ctx->pc + 4);
8259 gen_set_label(l1);
8260 gen_goto_tb(ctx, 0, ctx->btarget);
8262 break;
8263 case MIPS_HFLAG_BR:
8264 /* unconditional branch to register */
8265 MIPS_DEBUG("branch to register");
8266 tcg_gen_mov_tl(cpu_PC, btarget);
8267 tcg_gen_exit_tb(0);
8268 break;
8269 default:
8270 MIPS_DEBUG("unknown branch");
8271 break;
8276 static inline void
8277 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8278 int search_pc)
8280 DisasContext ctx;
8281 target_ulong pc_start;
8282 uint16_t *gen_opc_end;
8283 CPUBreakpoint *bp;
8284 int j, lj = -1;
8285 int num_insns;
8286 int max_insns;
8288 if (search_pc)
8289 qemu_log("search pc %d\n", search_pc);
8291 pc_start = tb->pc;
8292 /* Leave some spare opc slots for branch handling. */
8293 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
8294 ctx.pc = pc_start;
8295 ctx.saved_pc = -1;
8296 ctx.tb = tb;
8297 ctx.bstate = BS_NONE;
8298 /* Restore delay slot state from the tb context. */
8299 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8300 restore_cpu_state(env, &ctx);
8301 #ifdef CONFIG_USER_ONLY
8302 ctx.mem_idx = MIPS_HFLAG_UM;
8303 #else
8304 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8305 #endif
8306 num_insns = 0;
8307 max_insns = tb->cflags & CF_COUNT_MASK;
8308 if (max_insns == 0)
8309 max_insns = CF_COUNT_MASK;
8310 #ifdef DEBUG_DISAS
8311 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
8312 /* FIXME: This may print out stale hflags from env... */
8313 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
8314 #endif
8315 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
8316 gen_icount_start();
8317 while (ctx.bstate == BS_NONE) {
8318 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8319 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8320 if (bp->pc == ctx.pc) {
8321 save_cpu_state(&ctx, 1);
8322 ctx.bstate = BS_BRANCH;
8323 gen_helper_0i(raise_exception, EXCP_DEBUG);
8324 /* Include the breakpoint location or the tb won't
8325 * be flushed when it must be. */
8326 ctx.pc += 4;
8327 goto done_generating;
8332 if (search_pc) {
8333 j = gen_opc_ptr - gen_opc_buf;
8334 if (lj < j) {
8335 lj++;
8336 while (lj < j)
8337 gen_opc_instr_start[lj++] = 0;
8339 gen_opc_pc[lj] = ctx.pc;
8340 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8341 gen_opc_instr_start[lj] = 1;
8342 gen_opc_icount[lj] = num_insns;
8344 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8345 gen_io_start();
8346 ctx.opcode = ldl_code(ctx.pc);
8347 decode_opc(env, &ctx);
8348 ctx.pc += 4;
8349 num_insns++;
8351 if (env->singlestep_enabled)
8352 break;
8354 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8355 break;
8357 if (gen_opc_ptr >= gen_opc_end)
8358 break;
8360 if (num_insns >= max_insns)
8361 break;
8363 if (singlestep)
8364 break;
8366 if (tb->cflags & CF_LAST_IO)
8367 gen_io_end();
8368 if (env->singlestep_enabled) {
8369 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
8370 gen_helper_0i(raise_exception, EXCP_DEBUG);
8371 } else {
8372 switch (ctx.bstate) {
8373 case BS_STOP:
8374 gen_helper_interrupt_restart();
8375 gen_goto_tb(&ctx, 0, ctx.pc);
8376 break;
8377 case BS_NONE:
8378 save_cpu_state(&ctx, 0);
8379 gen_goto_tb(&ctx, 0, ctx.pc);
8380 break;
8381 case BS_EXCP:
8382 gen_helper_interrupt_restart();
8383 tcg_gen_exit_tb(0);
8384 break;
8385 case BS_BRANCH:
8386 default:
8387 break;
8390 done_generating:
8391 gen_icount_end(tb, num_insns);
8392 *gen_opc_ptr = INDEX_op_end;
8393 if (search_pc) {
8394 j = gen_opc_ptr - gen_opc_buf;
8395 lj++;
8396 while (lj <= j)
8397 gen_opc_instr_start[lj++] = 0;
8398 } else {
8399 tb->size = ctx.pc - pc_start;
8400 tb->icount = num_insns;
8402 #ifdef DEBUG_DISAS
8403 LOG_DISAS("\n");
8404 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8405 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8406 log_target_disas(pc_start, ctx.pc - pc_start, 0);
8407 qemu_log("\n");
8409 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8410 #endif
8413 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8415 gen_intermediate_code_internal(env, tb, 0);
8418 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8420 gen_intermediate_code_internal(env, tb, 1);
8423 static void fpu_dump_state(CPUState *env, FILE *f,
8424 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8425 int flags)
8427 int i;
8428 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8430 #define printfpr(fp) \
8431 do { \
8432 if (is_fpu64) \
8433 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8434 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8435 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8436 else { \
8437 fpr_t tmp; \
8438 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8439 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8440 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8441 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8442 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8444 } while(0)
8447 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8448 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8449 get_float_exception_flags(&env->active_fpu.fp_status));
8450 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8451 fpu_fprintf(f, "%3s: ", fregnames[i]);
8452 printfpr(&env->active_fpu.fpr[i]);
8455 #undef printfpr
8458 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8459 /* Debug help: The architecture requires 32bit code to maintain proper
8460 sign-extended values on 64bit machines. */
8462 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8464 static void
8465 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8466 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8467 int flags)
8469 int i;
8471 if (!SIGN_EXT_P(env->active_tc.PC))
8472 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8473 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8474 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8475 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8476 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8477 if (!SIGN_EXT_P(env->btarget))
8478 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8480 for (i = 0; i < 32; i++) {
8481 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8482 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8485 if (!SIGN_EXT_P(env->CP0_EPC))
8486 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8487 if (!SIGN_EXT_P(env->CP0_LLAddr))
8488 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
8490 #endif
8492 void cpu_dump_state (CPUState *env, FILE *f,
8493 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8494 int flags)
8496 int i;
8498 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
8499 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8500 env->hflags, env->btarget, env->bcond);
8501 for (i = 0; i < 32; i++) {
8502 if ((i & 3) == 0)
8503 cpu_fprintf(f, "GPR%02d:", i);
8504 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8505 if ((i & 3) == 3)
8506 cpu_fprintf(f, "\n");
8509 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8510 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8511 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8512 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
8513 if (env->hflags & MIPS_HFLAG_FPU)
8514 fpu_dump_state(env, f, cpu_fprintf, flags);
8515 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8516 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8517 #endif
8520 static void mips_tcg_init(void)
8522 int i;
8523 static int inited;
8525 /* Initialize various static tables. */
8526 if (inited)
8527 return;
8529 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8530 TCGV_UNUSED(cpu_gpr[0]);
8531 for (i = 1; i < 32; i++)
8532 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
8533 offsetof(CPUState, active_tc.gpr[i]),
8534 regnames[i]);
8535 cpu_PC = tcg_global_mem_new(TCG_AREG0,
8536 offsetof(CPUState, active_tc.PC), "PC");
8537 for (i = 0; i < MIPS_DSP_ACC; i++) {
8538 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
8539 offsetof(CPUState, active_tc.HI[i]),
8540 regnames_HI[i]);
8541 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
8542 offsetof(CPUState, active_tc.LO[i]),
8543 regnames_LO[i]);
8544 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
8545 offsetof(CPUState, active_tc.ACX[i]),
8546 regnames_ACX[i]);
8548 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
8549 offsetof(CPUState, active_tc.DSPControl),
8550 "DSPControl");
8551 bcond = tcg_global_mem_new(TCG_AREG0,
8552 offsetof(CPUState, bcond), "bcond");
8553 btarget = tcg_global_mem_new(TCG_AREG0,
8554 offsetof(CPUState, btarget), "btarget");
8555 hflags = tcg_global_mem_new_i32(TCG_AREG0,
8556 offsetof(CPUState, hflags), "hflags");
8558 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
8559 offsetof(CPUState, active_fpu.fcr0),
8560 "fcr0");
8561 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
8562 offsetof(CPUState, active_fpu.fcr31),
8563 "fcr31");
8565 /* register helpers */
8566 #define GEN_HELPER 2
8567 #include "helper.h"
8569 inited = 1;
8572 #include "translate_init.c"
8574 CPUMIPSState *cpu_mips_init (const char *cpu_model)
8576 CPUMIPSState *env;
8577 const mips_def_t *def;
8579 def = cpu_mips_find_by_name(cpu_model);
8580 if (!def)
8581 return NULL;
8582 env = qemu_mallocz(sizeof(CPUMIPSState));
8583 env->cpu_model = def;
8585 cpu_exec_init(env);
8586 env->cpu_model_str = cpu_model;
8587 mips_tcg_init();
8588 cpu_reset(env);
8589 qemu_init_vcpu(env);
8590 return env;
8593 void cpu_reset (CPUMIPSState *env)
8595 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
8596 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
8597 log_cpu_state(env, 0);
8600 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8602 tlb_flush(env, 1);
8604 /* Minimal init */
8605 #if defined(CONFIG_USER_ONLY)
8606 env->hflags = MIPS_HFLAG_UM;
8607 /* Enable access to the SYNCI_Step register. */
8608 env->CP0_HWREna |= (1 << 1);
8609 #else
8610 if (env->hflags & MIPS_HFLAG_BMASK) {
8611 /* If the exception was raised from a delay slot,
8612 come back to the jump. */
8613 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8614 } else {
8615 env->CP0_ErrorEPC = env->active_tc.PC;
8617 env->active_tc.PC = (int32_t)0xBFC00000;
8618 env->CP0_Wired = 0;
8619 /* SMP not implemented */
8620 env->CP0_EBase = 0x80000000;
8621 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8622 /* vectored interrupts not implemented, timer on int 7,
8623 no performance counters. */
8624 env->CP0_IntCtl = 0xe0000000;
8626 int i;
8628 for (i = 0; i < 7; i++) {
8629 env->CP0_WatchLo[i] = 0;
8630 env->CP0_WatchHi[i] = 0x80000000;
8632 env->CP0_WatchLo[7] = 0;
8633 env->CP0_WatchHi[7] = 0;
8635 /* Count register increments in debug mode, EJTAG version 1 */
8636 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8637 env->hflags = MIPS_HFLAG_CP0;
8638 #endif
8639 env->exception_index = EXCP_NONE;
8640 cpu_mips_register(env, env->cpu_model);
8643 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8644 unsigned long searched_pc, int pc_pos, void *puc)
8646 env->active_tc.PC = gen_opc_pc[pc_pos];
8647 env->hflags &= ~MIPS_HFLAG_BMASK;
8648 env->hflags |= gen_opc_hflags[pc_pos];