kvm: configure: --with-patched-kernel doesn't need kernelversion
[qemu-kvm/fedora.git] / target-mips / translate.c
blob8adc89cffa005f06b5833adca582530e14e76d98
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
41 //#define MIPS_SINGLE_STEP
43 /* MIPS major opcodes */
44 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
46 enum {
47 /* indirect opcode tables */
48 OPC_SPECIAL = (0x00 << 26),
49 OPC_REGIMM = (0x01 << 26),
50 OPC_CP0 = (0x10 << 26),
51 OPC_CP1 = (0x11 << 26),
52 OPC_CP2 = (0x12 << 26),
53 OPC_CP3 = (0x13 << 26),
54 OPC_SPECIAL2 = (0x1C << 26),
55 OPC_SPECIAL3 = (0x1F << 26),
56 /* arithmetic with immediate */
57 OPC_ADDI = (0x08 << 26),
58 OPC_ADDIU = (0x09 << 26),
59 OPC_SLTI = (0x0A << 26),
60 OPC_SLTIU = (0x0B << 26),
61 OPC_ANDI = (0x0C << 26),
62 OPC_ORI = (0x0D << 26),
63 OPC_XORI = (0x0E << 26),
64 OPC_LUI = (0x0F << 26),
65 OPC_DADDI = (0x18 << 26),
66 OPC_DADDIU = (0x19 << 26),
67 /* Jump and branches */
68 OPC_J = (0x02 << 26),
69 OPC_JAL = (0x03 << 26),
70 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
71 OPC_BEQL = (0x14 << 26),
72 OPC_BNE = (0x05 << 26),
73 OPC_BNEL = (0x15 << 26),
74 OPC_BLEZ = (0x06 << 26),
75 OPC_BLEZL = (0x16 << 26),
76 OPC_BGTZ = (0x07 << 26),
77 OPC_BGTZL = (0x17 << 26),
78 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
79 /* Load and stores */
80 OPC_LDL = (0x1A << 26),
81 OPC_LDR = (0x1B << 26),
82 OPC_LB = (0x20 << 26),
83 OPC_LH = (0x21 << 26),
84 OPC_LWL = (0x22 << 26),
85 OPC_LW = (0x23 << 26),
86 OPC_LBU = (0x24 << 26),
87 OPC_LHU = (0x25 << 26),
88 OPC_LWR = (0x26 << 26),
89 OPC_LWU = (0x27 << 26),
90 OPC_SB = (0x28 << 26),
91 OPC_SH = (0x29 << 26),
92 OPC_SWL = (0x2A << 26),
93 OPC_SW = (0x2B << 26),
94 OPC_SDL = (0x2C << 26),
95 OPC_SDR = (0x2D << 26),
96 OPC_SWR = (0x2E << 26),
97 OPC_LL = (0x30 << 26),
98 OPC_LLD = (0x34 << 26),
99 OPC_LD = (0x37 << 26),
100 OPC_SC = (0x38 << 26),
101 OPC_SCD = (0x3C << 26),
102 OPC_SD = (0x3F << 26),
103 /* Floating point load/store */
104 OPC_LWC1 = (0x31 << 26),
105 OPC_LWC2 = (0x32 << 26),
106 OPC_LDC1 = (0x35 << 26),
107 OPC_LDC2 = (0x36 << 26),
108 OPC_SWC1 = (0x39 << 26),
109 OPC_SWC2 = (0x3A << 26),
110 OPC_SDC1 = (0x3D << 26),
111 OPC_SDC2 = (0x3E << 26),
112 /* MDMX ASE specific */
113 OPC_MDMX = (0x1E << 26),
114 /* Cache and prefetch */
115 OPC_CACHE = (0x2F << 26),
116 OPC_PREF = (0x33 << 26),
117 /* Reserved major opcode */
118 OPC_MAJOR3B_RESERVED = (0x3B << 26),
121 /* MIPS special opcodes */
122 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
124 enum {
125 /* Shifts */
126 OPC_SLL = 0x00 | OPC_SPECIAL,
127 /* NOP is SLL r0, r0, 0 */
128 /* SSNOP is SLL r0, r0, 1 */
129 /* EHB is SLL r0, r0, 3 */
130 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
131 OPC_SRA = 0x03 | OPC_SPECIAL,
132 OPC_SLLV = 0x04 | OPC_SPECIAL,
133 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
134 OPC_SRAV = 0x07 | OPC_SPECIAL,
135 OPC_DSLLV = 0x14 | OPC_SPECIAL,
136 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
137 OPC_DSRAV = 0x17 | OPC_SPECIAL,
138 OPC_DSLL = 0x38 | OPC_SPECIAL,
139 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
140 OPC_DSRA = 0x3B | OPC_SPECIAL,
141 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
142 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
143 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
144 /* Multiplication / division */
145 OPC_MULT = 0x18 | OPC_SPECIAL,
146 OPC_MULTU = 0x19 | OPC_SPECIAL,
147 OPC_DIV = 0x1A | OPC_SPECIAL,
148 OPC_DIVU = 0x1B | OPC_SPECIAL,
149 OPC_DMULT = 0x1C | OPC_SPECIAL,
150 OPC_DMULTU = 0x1D | OPC_SPECIAL,
151 OPC_DDIV = 0x1E | OPC_SPECIAL,
152 OPC_DDIVU = 0x1F | OPC_SPECIAL,
153 /* 2 registers arithmetic / logic */
154 OPC_ADD = 0x20 | OPC_SPECIAL,
155 OPC_ADDU = 0x21 | OPC_SPECIAL,
156 OPC_SUB = 0x22 | OPC_SPECIAL,
157 OPC_SUBU = 0x23 | OPC_SPECIAL,
158 OPC_AND = 0x24 | OPC_SPECIAL,
159 OPC_OR = 0x25 | OPC_SPECIAL,
160 OPC_XOR = 0x26 | OPC_SPECIAL,
161 OPC_NOR = 0x27 | OPC_SPECIAL,
162 OPC_SLT = 0x2A | OPC_SPECIAL,
163 OPC_SLTU = 0x2B | OPC_SPECIAL,
164 OPC_DADD = 0x2C | OPC_SPECIAL,
165 OPC_DADDU = 0x2D | OPC_SPECIAL,
166 OPC_DSUB = 0x2E | OPC_SPECIAL,
167 OPC_DSUBU = 0x2F | OPC_SPECIAL,
168 /* Jumps */
169 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
170 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
171 /* Traps */
172 OPC_TGE = 0x30 | OPC_SPECIAL,
173 OPC_TGEU = 0x31 | OPC_SPECIAL,
174 OPC_TLT = 0x32 | OPC_SPECIAL,
175 OPC_TLTU = 0x33 | OPC_SPECIAL,
176 OPC_TEQ = 0x34 | OPC_SPECIAL,
177 OPC_TNE = 0x36 | OPC_SPECIAL,
178 /* HI / LO registers load & stores */
179 OPC_MFHI = 0x10 | OPC_SPECIAL,
180 OPC_MTHI = 0x11 | OPC_SPECIAL,
181 OPC_MFLO = 0x12 | OPC_SPECIAL,
182 OPC_MTLO = 0x13 | OPC_SPECIAL,
183 /* Conditional moves */
184 OPC_MOVZ = 0x0A | OPC_SPECIAL,
185 OPC_MOVN = 0x0B | OPC_SPECIAL,
187 OPC_MOVCI = 0x01 | OPC_SPECIAL,
189 /* Special */
190 OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */
191 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
192 OPC_BREAK = 0x0D | OPC_SPECIAL,
193 OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */
194 OPC_SYNC = 0x0F | OPC_SPECIAL,
196 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
197 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
198 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
199 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
200 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
201 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
202 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
205 /* Multiplication variants of the vr54xx. */
206 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
208 enum {
209 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
210 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
211 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
212 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
213 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
214 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
215 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
216 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
217 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
218 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
219 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
220 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
221 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
222 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
225 /* REGIMM (rt field) opcodes */
226 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
228 enum {
229 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
230 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
231 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
232 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
233 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
234 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
235 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
236 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
237 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
238 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
239 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
240 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
241 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
242 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
243 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
246 /* Special2 opcodes */
247 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
249 enum {
250 /* Multiply & xxx operations */
251 OPC_MADD = 0x00 | OPC_SPECIAL2,
252 OPC_MADDU = 0x01 | OPC_SPECIAL2,
253 OPC_MUL = 0x02 | OPC_SPECIAL2,
254 OPC_MSUB = 0x04 | OPC_SPECIAL2,
255 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
256 /* Misc */
257 OPC_CLZ = 0x20 | OPC_SPECIAL2,
258 OPC_CLO = 0x21 | OPC_SPECIAL2,
259 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
260 OPC_DCLO = 0x25 | OPC_SPECIAL2,
261 /* Special */
262 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
265 /* Special3 opcodes */
266 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
268 enum {
269 OPC_EXT = 0x00 | OPC_SPECIAL3,
270 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
271 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
272 OPC_DEXT = 0x03 | OPC_SPECIAL3,
273 OPC_INS = 0x04 | OPC_SPECIAL3,
274 OPC_DINSM = 0x05 | OPC_SPECIAL3,
275 OPC_DINSU = 0x06 | OPC_SPECIAL3,
276 OPC_DINS = 0x07 | OPC_SPECIAL3,
277 OPC_FORK = 0x08 | OPC_SPECIAL3,
278 OPC_YIELD = 0x09 | OPC_SPECIAL3,
279 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
280 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
281 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
284 /* BSHFL opcodes */
285 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
287 enum {
288 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
289 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
290 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
293 /* DBSHFL opcodes */
294 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
296 enum {
297 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
298 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
301 /* Coprocessor 0 (rs field) */
302 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
304 enum {
305 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
306 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
307 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
308 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
309 OPC_MFTR = (0x08 << 21) | OPC_CP0,
310 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
311 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
312 OPC_MTTR = (0x0C << 21) | OPC_CP0,
313 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
314 OPC_C0 = (0x10 << 21) | OPC_CP0,
315 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
316 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
319 /* MFMC0 opcodes */
320 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
322 enum {
323 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
324 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
325 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
326 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
327 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
328 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
331 /* Coprocessor 0 (with rs == C0) */
332 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
334 enum {
335 OPC_TLBR = 0x01 | OPC_C0,
336 OPC_TLBWI = 0x02 | OPC_C0,
337 OPC_TLBWR = 0x06 | OPC_C0,
338 OPC_TLBP = 0x08 | OPC_C0,
339 OPC_RFE = 0x10 | OPC_C0,
340 OPC_ERET = 0x18 | OPC_C0,
341 OPC_DERET = 0x1F | OPC_C0,
342 OPC_WAIT = 0x20 | OPC_C0,
345 /* Coprocessor 1 (rs field) */
346 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
348 enum {
349 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
350 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
351 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
352 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
353 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
354 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
355 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
356 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
357 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
358 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
359 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
360 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
361 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
362 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
363 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
364 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
365 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
366 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
369 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
370 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
372 enum {
373 OPC_BC1F = (0x00 << 16) | OPC_BC1,
374 OPC_BC1T = (0x01 << 16) | OPC_BC1,
375 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
376 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
379 enum {
380 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
381 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
384 enum {
385 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
386 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
389 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
391 enum {
392 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
393 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
394 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
395 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
396 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
397 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
398 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
399 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
400 OPC_BC2 = (0x08 << 21) | OPC_CP2,
403 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
405 enum {
406 OPC_LWXC1 = 0x00 | OPC_CP3,
407 OPC_LDXC1 = 0x01 | OPC_CP3,
408 OPC_LUXC1 = 0x05 | OPC_CP3,
409 OPC_SWXC1 = 0x08 | OPC_CP3,
410 OPC_SDXC1 = 0x09 | OPC_CP3,
411 OPC_SUXC1 = 0x0D | OPC_CP3,
412 OPC_PREFX = 0x0F | OPC_CP3,
413 OPC_ALNV_PS = 0x1E | OPC_CP3,
414 OPC_MADD_S = 0x20 | OPC_CP3,
415 OPC_MADD_D = 0x21 | OPC_CP3,
416 OPC_MADD_PS = 0x26 | OPC_CP3,
417 OPC_MSUB_S = 0x28 | OPC_CP3,
418 OPC_MSUB_D = 0x29 | OPC_CP3,
419 OPC_MSUB_PS = 0x2E | OPC_CP3,
420 OPC_NMADD_S = 0x30 | OPC_CP3,
421 OPC_NMADD_D = 0x31 | OPC_CP3,
422 OPC_NMADD_PS= 0x36 | OPC_CP3,
423 OPC_NMSUB_S = 0x38 | OPC_CP3,
424 OPC_NMSUB_D = 0x39 | OPC_CP3,
425 OPC_NMSUB_PS= 0x3E | OPC_CP3,
428 /* global register indices */
429 static TCGv_ptr cpu_env;
430 static TCGv cpu_gpr[32], cpu_PC;
431 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
432 static TCGv cpu_dspctrl, btarget, bcond;
433 static TCGv_i32 hflags;
434 static TCGv_i32 fpu_fcr0, fpu_fcr31;
436 #include "gen-icount.h"
438 #define gen_helper_0i(name, arg) do { \
439 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
440 gen_helper_##name(helper_tmp); \
441 tcg_temp_free_i32(helper_tmp); \
442 } while(0)
444 #define gen_helper_1i(name, arg1, arg2) do { \
445 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
446 gen_helper_##name(arg1, helper_tmp); \
447 tcg_temp_free_i32(helper_tmp); \
448 } while(0)
450 #define gen_helper_2i(name, arg1, arg2, arg3) do { \
451 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
452 gen_helper_##name(arg1, arg2, helper_tmp); \
453 tcg_temp_free_i32(helper_tmp); \
454 } while(0)
456 #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
457 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
458 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
459 tcg_temp_free_i32(helper_tmp); \
460 } while(0)
462 typedef struct DisasContext {
463 struct TranslationBlock *tb;
464 target_ulong pc, saved_pc;
465 uint32_t opcode;
466 /* Routine used to access memory */
467 int mem_idx;
468 uint32_t hflags, saved_hflags;
469 int bstate;
470 target_ulong btarget;
471 } DisasContext;
473 enum {
474 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
475 * exception condition */
476 BS_STOP = 1, /* We want to stop translation for any reason */
477 BS_BRANCH = 2, /* We reached a branch condition */
478 BS_EXCP = 3, /* We reached an exception condition */
481 static const char *regnames[] =
482 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
483 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
484 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
485 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
487 static const char *regnames_HI[] =
488 { "HI0", "HI1", "HI2", "HI3", };
490 static const char *regnames_LO[] =
491 { "LO0", "LO1", "LO2", "LO3", };
493 static const char *regnames_ACX[] =
494 { "ACX0", "ACX1", "ACX2", "ACX3", };
496 static const char *fregnames[] =
497 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
498 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
499 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
500 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
502 #ifdef MIPS_DEBUG_DISAS
503 #define MIPS_DEBUG(fmt, args...) \
504 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
505 TARGET_FMT_lx ": %08x " fmt "\n", \
506 ctx->pc, ctx->opcode , ##args)
507 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
508 #else
509 #define MIPS_DEBUG(fmt, args...) do { } while(0)
510 #define LOG_DISAS(...) do { } while (0)
511 #endif
513 #define MIPS_INVAL(op) \
514 do { \
515 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
516 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
517 } while (0)
519 /* General purpose registers moves. */
520 static inline void gen_load_gpr (TCGv t, int reg)
522 if (reg == 0)
523 tcg_gen_movi_tl(t, 0);
524 else
525 tcg_gen_mov_tl(t, cpu_gpr[reg]);
528 static inline void gen_store_gpr (TCGv t, int reg)
530 if (reg != 0)
531 tcg_gen_mov_tl(cpu_gpr[reg], t);
534 /* Moves to/from ACX register. */
535 static inline void gen_load_ACX (TCGv t, int reg)
537 tcg_gen_mov_tl(t, cpu_ACX[reg]);
540 static inline void gen_store_ACX (TCGv t, int reg)
542 tcg_gen_mov_tl(cpu_ACX[reg], t);
545 /* Moves to/from shadow registers. */
546 static inline void gen_load_srsgpr (int from, int to)
548 TCGv r_tmp1 = tcg_temp_new();
550 if (from == 0)
551 tcg_gen_movi_tl(r_tmp1, 0);
552 else {
553 TCGv_i32 r_tmp2 = tcg_temp_new_i32();
554 TCGv_ptr addr = tcg_temp_new_ptr();
556 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
557 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
558 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
559 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
560 tcg_gen_ext_i32_ptr(addr, r_tmp2);
561 tcg_gen_add_ptr(addr, cpu_env, addr);
563 tcg_gen_ld_tl(r_tmp1, addr, sizeof(target_ulong) * from);
564 tcg_temp_free_ptr(addr);
565 tcg_temp_free_i32(r_tmp2);
567 gen_store_gpr(r_tmp1, to);
568 tcg_temp_free(r_tmp1);
571 static inline void gen_store_srsgpr (int from, int to)
573 if (to != 0) {
574 TCGv r_tmp1 = tcg_temp_new();
575 TCGv_i32 r_tmp2 = tcg_temp_new_i32();
576 TCGv_ptr addr = tcg_temp_new_ptr();
578 gen_load_gpr(r_tmp1, from);
579 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
580 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
581 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
582 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
583 tcg_gen_ext_i32_ptr(addr, r_tmp2);
584 tcg_gen_add_ptr(addr, cpu_env, addr);
586 tcg_gen_st_tl(r_tmp1, addr, sizeof(target_ulong) * to);
587 tcg_temp_free_ptr(addr);
588 tcg_temp_free_i32(r_tmp2);
589 tcg_temp_free(r_tmp1);
593 /* Floating point register moves. */
594 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
596 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
599 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
601 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
604 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
606 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
609 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
611 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
614 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
616 if (ctx->hflags & MIPS_HFLAG_F64) {
617 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
618 } else {
619 TCGv_i32 t0 = tcg_temp_new_i32();
620 TCGv_i32 t1 = tcg_temp_new_i32();
621 gen_load_fpr32(t0, reg & ~1);
622 gen_load_fpr32(t1, reg | 1);
623 tcg_gen_concat_i32_i64(t, t0, t1);
624 tcg_temp_free_i32(t0);
625 tcg_temp_free_i32(t1);
629 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
631 if (ctx->hflags & MIPS_HFLAG_F64) {
632 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
633 } else {
634 TCGv_i64 t0 = tcg_temp_new_i64();
635 TCGv_i32 t1 = tcg_temp_new_i32();
636 tcg_gen_trunc_i64_i32(t1, t);
637 gen_store_fpr32(t1, reg & ~1);
638 tcg_gen_shri_i64(t0, t, 32);
639 tcg_gen_trunc_i64_i32(t1, t0);
640 gen_store_fpr32(t1, reg | 1);
641 tcg_temp_free_i32(t1);
642 tcg_temp_free_i64(t0);
646 static inline int get_fp_bit (int cc)
648 if (cc)
649 return 24 + cc;
650 else
651 return 23;
654 #define FOP_CONDS(type, fmt, bits) \
655 static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
656 TCGv_i##bits b, int cc) \
658 switch (n) { \
659 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
660 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
661 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
662 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
663 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
664 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
665 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
666 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
667 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
668 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
669 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
670 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
671 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
672 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
673 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
674 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
675 default: abort(); \
679 FOP_CONDS(, d, 64)
680 FOP_CONDS(abs, d, 64)
681 FOP_CONDS(, s, 32)
682 FOP_CONDS(abs, s, 32)
683 FOP_CONDS(, ps, 64)
684 FOP_CONDS(abs, ps, 64)
685 #undef FOP_CONDS
687 /* Tests */
688 #define OP_COND(name, cond) \
689 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, TCGv t1) \
691 int l1 = gen_new_label(); \
692 int l2 = gen_new_label(); \
694 tcg_gen_brcond_tl(cond, t0, t1, l1); \
695 tcg_gen_movi_tl(ret, 0); \
696 tcg_gen_br(l2); \
697 gen_set_label(l1); \
698 tcg_gen_movi_tl(ret, 1); \
699 gen_set_label(l2); \
701 OP_COND(eq, TCG_COND_EQ);
702 OP_COND(ne, TCG_COND_NE);
703 OP_COND(ge, TCG_COND_GE);
704 OP_COND(geu, TCG_COND_GEU);
705 OP_COND(lt, TCG_COND_LT);
706 OP_COND(ltu, TCG_COND_LTU);
707 #undef OP_COND
709 #define OP_CONDI(name, cond) \
710 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, target_ulong val) \
712 int l1 = gen_new_label(); \
713 int l2 = gen_new_label(); \
715 tcg_gen_brcondi_tl(cond, t0, val, l1); \
716 tcg_gen_movi_tl(ret, 0); \
717 tcg_gen_br(l2); \
718 gen_set_label(l1); \
719 tcg_gen_movi_tl(ret, 1); \
720 gen_set_label(l2); \
722 OP_CONDI(lti, TCG_COND_LT);
723 OP_CONDI(ltiu, TCG_COND_LTU);
724 #undef OP_CONDI
726 #define OP_CONDZ(name, cond) \
727 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0) \
729 int l1 = gen_new_label(); \
730 int l2 = gen_new_label(); \
732 tcg_gen_brcondi_tl(cond, t0, 0, l1); \
733 tcg_gen_movi_tl(ret, 0); \
734 tcg_gen_br(l2); \
735 gen_set_label(l1); \
736 tcg_gen_movi_tl(ret, 1); \
737 gen_set_label(l2); \
739 OP_CONDZ(gez, TCG_COND_GE);
740 OP_CONDZ(gtz, TCG_COND_GT);
741 OP_CONDZ(lez, TCG_COND_LE);
742 OP_CONDZ(ltz, TCG_COND_LT);
743 #undef OP_CONDZ
745 static inline void gen_save_pc(target_ulong pc)
747 tcg_gen_movi_tl(cpu_PC, pc);
750 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
752 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
753 if (do_save_pc && ctx->pc != ctx->saved_pc) {
754 gen_save_pc(ctx->pc);
755 ctx->saved_pc = ctx->pc;
757 if (ctx->hflags != ctx->saved_hflags) {
758 tcg_gen_movi_i32(hflags, ctx->hflags);
759 ctx->saved_hflags = ctx->hflags;
760 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
761 case MIPS_HFLAG_BR:
762 break;
763 case MIPS_HFLAG_BC:
764 case MIPS_HFLAG_BL:
765 case MIPS_HFLAG_B:
766 tcg_gen_movi_tl(btarget, ctx->btarget);
767 break;
772 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
774 ctx->saved_hflags = ctx->hflags;
775 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
776 case MIPS_HFLAG_BR:
777 break;
778 case MIPS_HFLAG_BC:
779 case MIPS_HFLAG_BL:
780 case MIPS_HFLAG_B:
781 ctx->btarget = env->btarget;
782 break;
786 static inline void
787 generate_exception_err (DisasContext *ctx, int excp, int err)
789 TCGv_i32 texcp = tcg_const_i32(excp);
790 TCGv_i32 terr = tcg_const_i32(err);
791 save_cpu_state(ctx, 1);
792 gen_helper_raise_exception_err(texcp, terr);
793 tcg_temp_free_i32(terr);
794 tcg_temp_free_i32(texcp);
795 gen_helper_interrupt_restart();
796 tcg_gen_exit_tb(0);
799 static inline void
800 generate_exception (DisasContext *ctx, int excp)
802 save_cpu_state(ctx, 1);
803 gen_helper_0i(raise_exception, excp);
804 gen_helper_interrupt_restart();
805 tcg_gen_exit_tb(0);
808 /* Addresses computation */
809 static inline void gen_op_addr_add (DisasContext *ctx, TCGv t0, TCGv t1)
811 tcg_gen_add_tl(t0, t0, t1);
813 #if defined(TARGET_MIPS64)
814 /* For compatibility with 32-bit code, data reference in user mode
815 with Status_UX = 0 should be casted to 32-bit and sign extended.
816 See the MIPS64 PRA manual, section 4.10. */
817 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
818 !(ctx->hflags & MIPS_HFLAG_UX)) {
819 tcg_gen_ext32s_i64(t0, t0);
821 #endif
824 static inline void check_cp0_enabled(DisasContext *ctx)
826 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
827 generate_exception_err(ctx, EXCP_CpU, 1);
830 static inline void check_cp1_enabled(DisasContext *ctx)
832 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
833 generate_exception_err(ctx, EXCP_CpU, 1);
836 /* Verify that the processor is running with COP1X instructions enabled.
837 This is associated with the nabla symbol in the MIPS32 and MIPS64
838 opcode tables. */
840 static inline void check_cop1x(DisasContext *ctx)
842 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
843 generate_exception(ctx, EXCP_RI);
846 /* Verify that the processor is running with 64-bit floating-point
847 operations enabled. */
849 static inline void check_cp1_64bitmode(DisasContext *ctx)
851 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
852 generate_exception(ctx, EXCP_RI);
856 * Verify if floating point register is valid; an operation is not defined
857 * if bit 0 of any register specification is set and the FR bit in the
858 * Status register equals zero, since the register numbers specify an
859 * even-odd pair of adjacent coprocessor general registers. When the FR bit
860 * in the Status register equals one, both even and odd register numbers
861 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
863 * Multiple 64 bit wide registers can be checked by calling
864 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
866 static inline void check_cp1_registers(DisasContext *ctx, int regs)
868 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
869 generate_exception(ctx, EXCP_RI);
872 /* This code generates a "reserved instruction" exception if the
873 CPU does not support the instruction set corresponding to flags. */
874 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
876 if (unlikely(!(env->insn_flags & flags)))
877 generate_exception(ctx, EXCP_RI);
880 /* This code generates a "reserved instruction" exception if 64-bit
881 instructions are not enabled. */
882 static inline void check_mips_64(DisasContext *ctx)
884 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
885 generate_exception(ctx, EXCP_RI);
888 /* load/store instructions. */
889 #define OP_LD(insn,fname) \
890 static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx) \
892 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
894 OP_LD(lb,ld8s);
895 OP_LD(lbu,ld8u);
896 OP_LD(lh,ld16s);
897 OP_LD(lhu,ld16u);
898 OP_LD(lw,ld32s);
899 #if defined(TARGET_MIPS64)
900 OP_LD(lwu,ld32u);
901 OP_LD(ld,ld64);
902 #endif
903 #undef OP_LD
905 #define OP_ST(insn,fname) \
906 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
908 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
910 OP_ST(sb,st8);
911 OP_ST(sh,st16);
912 OP_ST(sw,st32);
913 #if defined(TARGET_MIPS64)
914 OP_ST(sd,st64);
915 #endif
916 #undef OP_ST
918 #define OP_LD_ATOMIC(insn,fname) \
919 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
921 tcg_gen_mov_tl(t1, t0); \
922 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
923 tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
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 #define OP_ST_ATOMIC(insn,fname,almask) \
932 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
934 TCGv r_tmp = tcg_temp_local_new(); \
935 int l1 = gen_new_label(); \
936 int l2 = gen_new_label(); \
937 int l3 = gen_new_label(); \
939 tcg_gen_andi_tl(r_tmp, t0, almask); \
940 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1); \
941 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
942 generate_exception(ctx, EXCP_AdES); \
943 gen_set_label(l1); \
944 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
945 tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2); \
946 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
947 tcg_gen_movi_tl(t0, 1); \
948 tcg_gen_br(l3); \
949 gen_set_label(l2); \
950 tcg_gen_movi_tl(t0, 0); \
951 gen_set_label(l3); \
952 tcg_temp_free(r_tmp); \
954 OP_ST_ATOMIC(sc,st32,0x3);
955 #if defined(TARGET_MIPS64)
956 OP_ST_ATOMIC(scd,st64,0x7);
957 #endif
958 #undef OP_ST_ATOMIC
960 /* Load and store */
961 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
962 int base, int16_t offset)
964 const char *opn = "ldst";
965 TCGv t0 = tcg_temp_local_new();
966 TCGv t1 = tcg_temp_local_new();
968 if (base == 0) {
969 tcg_gen_movi_tl(t0, offset);
970 } else if (offset == 0) {
971 gen_load_gpr(t0, base);
972 } else {
973 tcg_gen_movi_tl(t0, offset);
974 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
976 /* Don't do NOP if destination is zero: we must perform the actual
977 memory access. */
978 switch (opc) {
979 #if defined(TARGET_MIPS64)
980 case OPC_LWU:
981 op_ldst_lwu(t0, ctx);
982 gen_store_gpr(t0, rt);
983 opn = "lwu";
984 break;
985 case OPC_LD:
986 op_ldst_ld(t0, ctx);
987 gen_store_gpr(t0, rt);
988 opn = "ld";
989 break;
990 case OPC_LLD:
991 op_ldst_lld(t0, t1, ctx);
992 gen_store_gpr(t0, rt);
993 opn = "lld";
994 break;
995 case OPC_SD:
996 gen_load_gpr(t1, rt);
997 op_ldst_sd(t0, t1, ctx);
998 opn = "sd";
999 break;
1000 case OPC_SCD:
1001 save_cpu_state(ctx, 1);
1002 gen_load_gpr(t1, rt);
1003 op_ldst_scd(t0, t1, ctx);
1004 gen_store_gpr(t0, rt);
1005 opn = "scd";
1006 break;
1007 case OPC_LDL:
1008 save_cpu_state(ctx, 1);
1009 gen_load_gpr(t1, rt);
1010 gen_helper_3i(ldl, t1, t0, t1, ctx->mem_idx);
1011 gen_store_gpr(t1, rt);
1012 opn = "ldl";
1013 break;
1014 case OPC_SDL:
1015 save_cpu_state(ctx, 1);
1016 gen_load_gpr(t1, rt);
1017 gen_helper_2i(sdl, t0, t1, ctx->mem_idx);
1018 opn = "sdl";
1019 break;
1020 case OPC_LDR:
1021 save_cpu_state(ctx, 1);
1022 gen_load_gpr(t1, rt);
1023 gen_helper_3i(ldr, t1, t0, t1, ctx->mem_idx);
1024 gen_store_gpr(t1, rt);
1025 opn = "ldr";
1026 break;
1027 case OPC_SDR:
1028 save_cpu_state(ctx, 1);
1029 gen_load_gpr(t1, rt);
1030 gen_helper_2i(sdr, t0, t1, ctx->mem_idx);
1031 opn = "sdr";
1032 break;
1033 #endif
1034 case OPC_LW:
1035 op_ldst_lw(t0, ctx);
1036 gen_store_gpr(t0, rt);
1037 opn = "lw";
1038 break;
1039 case OPC_SW:
1040 gen_load_gpr(t1, rt);
1041 op_ldst_sw(t0, t1, ctx);
1042 opn = "sw";
1043 break;
1044 case OPC_LH:
1045 op_ldst_lh(t0, ctx);
1046 gen_store_gpr(t0, rt);
1047 opn = "lh";
1048 break;
1049 case OPC_SH:
1050 gen_load_gpr(t1, rt);
1051 op_ldst_sh(t0, t1, ctx);
1052 opn = "sh";
1053 break;
1054 case OPC_LHU:
1055 op_ldst_lhu(t0, ctx);
1056 gen_store_gpr(t0, rt);
1057 opn = "lhu";
1058 break;
1059 case OPC_LB:
1060 op_ldst_lb(t0, ctx);
1061 gen_store_gpr(t0, rt);
1062 opn = "lb";
1063 break;
1064 case OPC_SB:
1065 gen_load_gpr(t1, rt);
1066 op_ldst_sb(t0, t1, ctx);
1067 opn = "sb";
1068 break;
1069 case OPC_LBU:
1070 op_ldst_lbu(t0, ctx);
1071 gen_store_gpr(t0, rt);
1072 opn = "lbu";
1073 break;
1074 case OPC_LWL:
1075 save_cpu_state(ctx, 1);
1076 gen_load_gpr(t1, rt);
1077 gen_helper_3i(lwl, t1, t0, t1, ctx->mem_idx);
1078 gen_store_gpr(t1, rt);
1079 opn = "lwl";
1080 break;
1081 case OPC_SWL:
1082 save_cpu_state(ctx, 1);
1083 gen_load_gpr(t1, rt);
1084 gen_helper_2i(swl, t0, t1, ctx->mem_idx);
1085 opn = "swr";
1086 break;
1087 case OPC_LWR:
1088 save_cpu_state(ctx, 1);
1089 gen_load_gpr(t1, rt);
1090 gen_helper_3i(lwr, t1, t0, t1, ctx->mem_idx);
1091 gen_store_gpr(t1, rt);
1092 opn = "lwr";
1093 break;
1094 case OPC_SWR:
1095 save_cpu_state(ctx, 1);
1096 gen_load_gpr(t1, rt);
1097 gen_helper_2i(swr, t0, t1, ctx->mem_idx);
1098 opn = "swr";
1099 break;
1100 case OPC_LL:
1101 op_ldst_ll(t0, t1, ctx);
1102 gen_store_gpr(t0, rt);
1103 opn = "ll";
1104 break;
1105 case OPC_SC:
1106 save_cpu_state(ctx, 1);
1107 gen_load_gpr(t1, rt);
1108 op_ldst_sc(t0, t1, ctx);
1109 gen_store_gpr(t0, rt);
1110 opn = "sc";
1111 break;
1112 default:
1113 MIPS_INVAL(opn);
1114 generate_exception(ctx, EXCP_RI);
1115 goto out;
1117 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1118 out:
1119 tcg_temp_free(t0);
1120 tcg_temp_free(t1);
1123 /* Load and store */
1124 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1125 int base, int16_t offset)
1127 const char *opn = "flt_ldst";
1128 TCGv t0 = tcg_temp_local_new();
1130 if (base == 0) {
1131 tcg_gen_movi_tl(t0, offset);
1132 } else if (offset == 0) {
1133 gen_load_gpr(t0, base);
1134 } else {
1135 tcg_gen_movi_tl(t0, offset);
1136 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
1138 /* Don't do NOP if destination is zero: we must perform the actual
1139 memory access. */
1140 switch (opc) {
1141 case OPC_LWC1:
1143 TCGv_i32 fp0 = tcg_temp_new_i32();
1144 TCGv t1 = tcg_temp_new();
1146 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
1147 tcg_gen_trunc_tl_i32(fp0, t1);
1148 gen_store_fpr32(fp0, ft);
1149 tcg_temp_free(t1);
1150 tcg_temp_free_i32(fp0);
1152 opn = "lwc1";
1153 break;
1154 case OPC_SWC1:
1156 TCGv_i32 fp0 = tcg_temp_new_i32();
1157 TCGv t1 = tcg_temp_new();
1159 gen_load_fpr32(fp0, ft);
1160 tcg_gen_extu_i32_tl(t1, fp0);
1161 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1162 tcg_temp_free(t1);
1163 tcg_temp_free_i32(fp0);
1165 opn = "swc1";
1166 break;
1167 case OPC_LDC1:
1169 TCGv_i64 fp0 = tcg_temp_new_i64();
1171 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1172 gen_store_fpr64(ctx, fp0, ft);
1173 tcg_temp_free_i64(fp0);
1175 opn = "ldc1";
1176 break;
1177 case OPC_SDC1:
1179 TCGv_i64 fp0 = tcg_temp_new_i64();
1181 gen_load_fpr64(ctx, fp0, ft);
1182 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1183 tcg_temp_free_i64(fp0);
1185 opn = "sdc1";
1186 break;
1187 default:
1188 MIPS_INVAL(opn);
1189 generate_exception(ctx, EXCP_RI);
1190 goto out;
1192 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1193 out:
1194 tcg_temp_free(t0);
1197 /* Arithmetic with immediate operand */
1198 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1199 int rt, int rs, int16_t imm)
1201 target_ulong uimm;
1202 const char *opn = "imm arith";
1203 TCGv t0 = tcg_temp_local_new();
1205 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1206 /* If no destination, treat it as a NOP.
1207 For addi, we must generate the overflow exception when needed. */
1208 MIPS_DEBUG("NOP");
1209 goto out;
1211 uimm = (uint16_t)imm;
1212 switch (opc) {
1213 case OPC_ADDI:
1214 case OPC_ADDIU:
1215 #if defined(TARGET_MIPS64)
1216 case OPC_DADDI:
1217 case OPC_DADDIU:
1218 #endif
1219 case OPC_SLTI:
1220 case OPC_SLTIU:
1221 uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1222 /* Fall through. */
1223 case OPC_ANDI:
1224 case OPC_ORI:
1225 case OPC_XORI:
1226 gen_load_gpr(t0, rs);
1227 break;
1228 case OPC_LUI:
1229 tcg_gen_movi_tl(t0, imm << 16);
1230 break;
1231 case OPC_SLL:
1232 case OPC_SRA:
1233 case OPC_SRL:
1234 #if defined(TARGET_MIPS64)
1235 case OPC_DSLL:
1236 case OPC_DSRA:
1237 case OPC_DSRL:
1238 case OPC_DSLL32:
1239 case OPC_DSRA32:
1240 case OPC_DSRL32:
1241 #endif
1242 uimm &= 0x1f;
1243 gen_load_gpr(t0, rs);
1244 break;
1246 switch (opc) {
1247 case OPC_ADDI:
1249 TCGv r_tmp1 = tcg_temp_new();
1250 TCGv r_tmp2 = tcg_temp_new();
1251 int l1 = gen_new_label();
1253 save_cpu_state(ctx, 1);
1254 tcg_gen_ext32s_tl(r_tmp1, t0);
1255 tcg_gen_addi_tl(t0, r_tmp1, uimm);
1257 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
1258 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1259 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1260 tcg_temp_free(r_tmp2);
1261 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1262 /* operands of same sign, result different sign */
1263 generate_exception(ctx, EXCP_OVERFLOW);
1264 gen_set_label(l1);
1265 tcg_temp_free(r_tmp1);
1267 tcg_gen_ext32s_tl(t0, t0);
1269 opn = "addi";
1270 break;
1271 case OPC_ADDIU:
1272 tcg_gen_addi_tl(t0, t0, uimm);
1273 tcg_gen_ext32s_tl(t0, t0);
1274 opn = "addiu";
1275 break;
1276 #if defined(TARGET_MIPS64)
1277 case OPC_DADDI:
1279 TCGv r_tmp1 = tcg_temp_new();
1280 TCGv r_tmp2 = tcg_temp_new();
1281 int l1 = gen_new_label();
1283 save_cpu_state(ctx, 1);
1284 tcg_gen_mov_tl(r_tmp1, t0);
1285 tcg_gen_addi_tl(t0, t0, uimm);
1287 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
1288 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1289 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1290 tcg_temp_free(r_tmp2);
1291 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1292 /* operands of same sign, result different sign */
1293 generate_exception(ctx, EXCP_OVERFLOW);
1294 gen_set_label(l1);
1295 tcg_temp_free(r_tmp1);
1297 opn = "daddi";
1298 break;
1299 case OPC_DADDIU:
1300 tcg_gen_addi_tl(t0, t0, uimm);
1301 opn = "daddiu";
1302 break;
1303 #endif
1304 case OPC_SLTI:
1305 gen_op_lti(t0, t0, uimm);
1306 opn = "slti";
1307 break;
1308 case OPC_SLTIU:
1309 gen_op_ltiu(t0, t0, uimm);
1310 opn = "sltiu";
1311 break;
1312 case OPC_ANDI:
1313 tcg_gen_andi_tl(t0, t0, uimm);
1314 opn = "andi";
1315 break;
1316 case OPC_ORI:
1317 tcg_gen_ori_tl(t0, t0, uimm);
1318 opn = "ori";
1319 break;
1320 case OPC_XORI:
1321 tcg_gen_xori_tl(t0, t0, uimm);
1322 opn = "xori";
1323 break;
1324 case OPC_LUI:
1325 opn = "lui";
1326 break;
1327 case OPC_SLL:
1328 tcg_gen_shli_tl(t0, t0, uimm);
1329 tcg_gen_ext32s_tl(t0, t0);
1330 opn = "sll";
1331 break;
1332 case OPC_SRA:
1333 tcg_gen_ext32s_tl(t0, t0);
1334 tcg_gen_sari_tl(t0, t0, uimm);
1335 opn = "sra";
1336 break;
1337 case OPC_SRL:
1338 switch ((ctx->opcode >> 21) & 0x1f) {
1339 case 0:
1340 if (uimm != 0) {
1341 tcg_gen_ext32u_tl(t0, t0);
1342 tcg_gen_shri_tl(t0, t0, uimm);
1343 } else {
1344 tcg_gen_ext32s_tl(t0, t0);
1346 opn = "srl";
1347 break;
1348 case 1:
1349 /* rotr is decoded as srl on non-R2 CPUs */
1350 if (env->insn_flags & ISA_MIPS32R2) {
1351 if (uimm != 0) {
1352 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
1354 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1355 tcg_gen_rotri_i32(r_tmp1, r_tmp1, uimm);
1356 tcg_gen_ext_i32_tl(t0, r_tmp1);
1357 tcg_temp_free_i32(r_tmp1);
1359 opn = "rotr";
1360 } else {
1361 if (uimm != 0) {
1362 tcg_gen_ext32u_tl(t0, t0);
1363 tcg_gen_shri_tl(t0, t0, uimm);
1364 } else {
1365 tcg_gen_ext32s_tl(t0, t0);
1367 opn = "srl";
1369 break;
1370 default:
1371 MIPS_INVAL("invalid srl flag");
1372 generate_exception(ctx, EXCP_RI);
1373 break;
1375 break;
1376 #if defined(TARGET_MIPS64)
1377 case OPC_DSLL:
1378 tcg_gen_shli_tl(t0, t0, uimm);
1379 opn = "dsll";
1380 break;
1381 case OPC_DSRA:
1382 tcg_gen_sari_tl(t0, t0, uimm);
1383 opn = "dsra";
1384 break;
1385 case OPC_DSRL:
1386 switch ((ctx->opcode >> 21) & 0x1f) {
1387 case 0:
1388 tcg_gen_shri_tl(t0, t0, uimm);
1389 opn = "dsrl";
1390 break;
1391 case 1:
1392 /* drotr is decoded as dsrl on non-R2 CPUs */
1393 if (env->insn_flags & ISA_MIPS32R2) {
1394 if (uimm != 0) {
1395 tcg_gen_rotri_tl(t0, t0, uimm);
1397 opn = "drotr";
1398 } else {
1399 tcg_gen_shri_tl(t0, t0, uimm);
1400 opn = "dsrl";
1402 break;
1403 default:
1404 MIPS_INVAL("invalid dsrl flag");
1405 generate_exception(ctx, EXCP_RI);
1406 break;
1408 break;
1409 case OPC_DSLL32:
1410 tcg_gen_shli_tl(t0, t0, uimm + 32);
1411 opn = "dsll32";
1412 break;
1413 case OPC_DSRA32:
1414 tcg_gen_sari_tl(t0, t0, uimm + 32);
1415 opn = "dsra32";
1416 break;
1417 case OPC_DSRL32:
1418 switch ((ctx->opcode >> 21) & 0x1f) {
1419 case 0:
1420 tcg_gen_shri_tl(t0, t0, uimm + 32);
1421 opn = "dsrl32";
1422 break;
1423 case 1:
1424 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1425 if (env->insn_flags & ISA_MIPS32R2) {
1426 tcg_gen_rotri_tl(t0, t0, uimm + 32);
1427 opn = "drotr32";
1428 } else {
1429 tcg_gen_shri_tl(t0, t0, uimm + 32);
1430 opn = "dsrl32";
1432 break;
1433 default:
1434 MIPS_INVAL("invalid dsrl32 flag");
1435 generate_exception(ctx, EXCP_RI);
1436 break;
1438 break;
1439 #endif
1440 default:
1441 MIPS_INVAL(opn);
1442 generate_exception(ctx, EXCP_RI);
1443 goto out;
1445 gen_store_gpr(t0, rt);
1446 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1447 out:
1448 tcg_temp_free(t0);
1451 /* Arithmetic */
1452 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1453 int rd, int rs, int rt)
1455 const char *opn = "arith";
1456 TCGv t0 = tcg_temp_local_new();
1457 TCGv t1 = tcg_temp_local_new();
1459 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1460 && opc != OPC_DADD && opc != OPC_DSUB) {
1461 /* If no destination, treat it as a NOP.
1462 For add & sub, we must generate the overflow exception when needed. */
1463 MIPS_DEBUG("NOP");
1464 goto out;
1466 gen_load_gpr(t0, rs);
1467 /* Specialcase the conventional move operation. */
1468 if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1469 || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1470 gen_store_gpr(t0, rd);
1471 goto out;
1473 gen_load_gpr(t1, rt);
1474 switch (opc) {
1475 case OPC_ADD:
1477 TCGv r_tmp1 = tcg_temp_new();
1478 TCGv r_tmp2 = tcg_temp_new();
1479 int l1 = gen_new_label();
1481 save_cpu_state(ctx, 1);
1482 tcg_gen_ext32s_tl(r_tmp1, t0);
1483 tcg_gen_ext32s_tl(r_tmp2, t1);
1484 tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
1486 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1487 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1488 tcg_gen_xor_tl(r_tmp2, t0, t1);
1489 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1490 tcg_temp_free(r_tmp2);
1491 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1492 /* operands of same sign, result different sign */
1493 generate_exception(ctx, EXCP_OVERFLOW);
1494 gen_set_label(l1);
1495 tcg_temp_free(r_tmp1);
1497 tcg_gen_ext32s_tl(t0, t0);
1499 opn = "add";
1500 break;
1501 case OPC_ADDU:
1502 tcg_gen_add_tl(t0, t0, t1);
1503 tcg_gen_ext32s_tl(t0, t0);
1504 opn = "addu";
1505 break;
1506 case OPC_SUB:
1508 TCGv r_tmp1 = tcg_temp_new();
1509 TCGv r_tmp2 = tcg_temp_new();
1510 int l1 = gen_new_label();
1512 save_cpu_state(ctx, 1);
1513 tcg_gen_ext32s_tl(r_tmp1, t0);
1514 tcg_gen_ext32s_tl(r_tmp2, t1);
1515 tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
1517 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1518 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1519 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1520 tcg_temp_free(r_tmp2);
1521 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1522 /* operands of different sign, first operand and result different sign */
1523 generate_exception(ctx, EXCP_OVERFLOW);
1524 gen_set_label(l1);
1525 tcg_temp_free(r_tmp1);
1527 tcg_gen_ext32s_tl(t0, t0);
1529 opn = "sub";
1530 break;
1531 case OPC_SUBU:
1532 tcg_gen_sub_tl(t0, t0, t1);
1533 tcg_gen_ext32s_tl(t0, t0);
1534 opn = "subu";
1535 break;
1536 #if defined(TARGET_MIPS64)
1537 case OPC_DADD:
1539 TCGv r_tmp1 = tcg_temp_new();
1540 TCGv r_tmp2 = tcg_temp_new();
1541 int l1 = gen_new_label();
1543 save_cpu_state(ctx, 1);
1544 tcg_gen_mov_tl(r_tmp1, t0);
1545 tcg_gen_add_tl(t0, t0, t1);
1547 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1548 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1549 tcg_gen_xor_tl(r_tmp2, t0, t1);
1550 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1551 tcg_temp_free(r_tmp2);
1552 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1553 /* operands of same sign, result different sign */
1554 generate_exception(ctx, EXCP_OVERFLOW);
1555 gen_set_label(l1);
1556 tcg_temp_free(r_tmp1);
1558 opn = "dadd";
1559 break;
1560 case OPC_DADDU:
1561 tcg_gen_add_tl(t0, t0, t1);
1562 opn = "daddu";
1563 break;
1564 case OPC_DSUB:
1566 TCGv r_tmp1 = tcg_temp_new();
1567 TCGv r_tmp2 = tcg_temp_new();
1568 int l1 = gen_new_label();
1570 save_cpu_state(ctx, 1);
1571 tcg_gen_mov_tl(r_tmp1, t0);
1572 tcg_gen_sub_tl(t0, t0, t1);
1574 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1575 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1576 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1577 tcg_temp_free(r_tmp2);
1578 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1579 /* operands of different sign, first operand and result different sign */
1580 generate_exception(ctx, EXCP_OVERFLOW);
1581 gen_set_label(l1);
1582 tcg_temp_free(r_tmp1);
1584 opn = "dsub";
1585 break;
1586 case OPC_DSUBU:
1587 tcg_gen_sub_tl(t0, t0, t1);
1588 opn = "dsubu";
1589 break;
1590 #endif
1591 case OPC_SLT:
1592 gen_op_lt(t0, t0, t1);
1593 opn = "slt";
1594 break;
1595 case OPC_SLTU:
1596 gen_op_ltu(t0, t0, t1);
1597 opn = "sltu";
1598 break;
1599 case OPC_AND:
1600 tcg_gen_and_tl(t0, t0, t1);
1601 opn = "and";
1602 break;
1603 case OPC_NOR:
1604 tcg_gen_nor_tl(t0, t0, t1);
1605 opn = "nor";
1606 break;
1607 case OPC_OR:
1608 tcg_gen_or_tl(t0, t0, t1);
1609 opn = "or";
1610 break;
1611 case OPC_XOR:
1612 tcg_gen_xor_tl(t0, t0, t1);
1613 opn = "xor";
1614 break;
1615 case OPC_MUL:
1616 tcg_gen_mul_tl(t0, t0, t1);
1617 tcg_gen_ext32s_tl(t0, t0);
1618 opn = "mul";
1619 break;
1620 case OPC_MOVN:
1622 int l1 = gen_new_label();
1624 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1625 gen_store_gpr(t0, rd);
1626 gen_set_label(l1);
1628 opn = "movn";
1629 goto print;
1630 case OPC_MOVZ:
1632 int l1 = gen_new_label();
1634 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
1635 gen_store_gpr(t0, rd);
1636 gen_set_label(l1);
1638 opn = "movz";
1639 goto print;
1640 case OPC_SLLV:
1641 tcg_gen_andi_tl(t0, t0, 0x1f);
1642 tcg_gen_shl_tl(t0, t1, t0);
1643 tcg_gen_ext32s_tl(t0, t0);
1644 opn = "sllv";
1645 break;
1646 case OPC_SRAV:
1647 tcg_gen_ext32s_tl(t1, t1);
1648 tcg_gen_andi_tl(t0, t0, 0x1f);
1649 tcg_gen_sar_tl(t0, t1, t0);
1650 opn = "srav";
1651 break;
1652 case OPC_SRLV:
1653 switch ((ctx->opcode >> 6) & 0x1f) {
1654 case 0:
1655 tcg_gen_ext32u_tl(t1, t1);
1656 tcg_gen_andi_tl(t0, t0, 0x1f);
1657 tcg_gen_shr_tl(t0, t1, t0);
1658 tcg_gen_ext32s_tl(t0, t0);
1659 opn = "srlv";
1660 break;
1661 case 1:
1662 /* rotrv is decoded as srlv on non-R2 CPUs */
1663 if (env->insn_flags & ISA_MIPS32R2) {
1664 int l1 = gen_new_label();
1665 int l2 = gen_new_label();
1667 tcg_gen_andi_tl(t0, t0, 0x1f);
1668 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1670 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
1671 TCGv_i32 r_tmp2 = tcg_temp_new_i32();
1673 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1674 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1675 tcg_gen_rotr_i32(r_tmp1, r_tmp1, r_tmp2);
1676 tcg_temp_free_i32(r_tmp1);
1677 tcg_temp_free_i32(r_tmp2);
1678 tcg_gen_br(l2);
1680 gen_set_label(l1);
1681 tcg_gen_mov_tl(t0, t1);
1682 gen_set_label(l2);
1683 opn = "rotrv";
1684 } else {
1685 tcg_gen_ext32u_tl(t1, t1);
1686 tcg_gen_andi_tl(t0, t0, 0x1f);
1687 tcg_gen_shr_tl(t0, t1, t0);
1688 tcg_gen_ext32s_tl(t0, t0);
1689 opn = "srlv";
1691 break;
1692 default:
1693 MIPS_INVAL("invalid srlv flag");
1694 generate_exception(ctx, EXCP_RI);
1695 break;
1697 break;
1698 #if defined(TARGET_MIPS64)
1699 case OPC_DSLLV:
1700 tcg_gen_andi_tl(t0, t0, 0x3f);
1701 tcg_gen_shl_tl(t0, t1, t0);
1702 opn = "dsllv";
1703 break;
1704 case OPC_DSRAV:
1705 tcg_gen_andi_tl(t0, t0, 0x3f);
1706 tcg_gen_sar_tl(t0, t1, t0);
1707 opn = "dsrav";
1708 break;
1709 case OPC_DSRLV:
1710 switch ((ctx->opcode >> 6) & 0x1f) {
1711 case 0:
1712 tcg_gen_andi_tl(t0, t0, 0x3f);
1713 tcg_gen_shr_tl(t0, t1, t0);
1714 opn = "dsrlv";
1715 break;
1716 case 1:
1717 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1718 if (env->insn_flags & ISA_MIPS32R2) {
1719 int l1 = gen_new_label();
1720 int l2 = gen_new_label();
1722 tcg_gen_andi_tl(t0, t0, 0x3f);
1723 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1725 tcg_gen_rotr_tl(t0, t1, t0);
1726 tcg_gen_br(l2);
1728 gen_set_label(l1);
1729 tcg_gen_mov_tl(t0, t1);
1730 gen_set_label(l2);
1731 opn = "drotrv";
1732 } else {
1733 tcg_gen_andi_tl(t0, t0, 0x3f);
1734 tcg_gen_shr_tl(t0, t1, t0);
1735 opn = "dsrlv";
1737 break;
1738 default:
1739 MIPS_INVAL("invalid dsrlv flag");
1740 generate_exception(ctx, EXCP_RI);
1741 break;
1743 break;
1744 #endif
1745 default:
1746 MIPS_INVAL(opn);
1747 generate_exception(ctx, EXCP_RI);
1748 goto out;
1750 gen_store_gpr(t0, rd);
1751 print:
1752 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1753 out:
1754 tcg_temp_free(t0);
1755 tcg_temp_free(t1);
1758 /* Arithmetic on HI/LO registers */
1759 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1761 const char *opn = "hilo";
1763 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1764 /* Treat as NOP. */
1765 MIPS_DEBUG("NOP");
1766 return;
1768 switch (opc) {
1769 case OPC_MFHI:
1770 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1771 opn = "mfhi";
1772 break;
1773 case OPC_MFLO:
1774 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1775 opn = "mflo";
1776 break;
1777 case OPC_MTHI:
1778 if (reg != 0)
1779 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1780 else
1781 tcg_gen_movi_tl(cpu_HI[0], 0);
1782 opn = "mthi";
1783 break;
1784 case OPC_MTLO:
1785 if (reg != 0)
1786 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1787 else
1788 tcg_gen_movi_tl(cpu_LO[0], 0);
1789 opn = "mtlo";
1790 break;
1792 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1795 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1796 int rs, int rt)
1798 const char *opn = "mul/div";
1799 TCGv t0, t1;
1801 switch (opc) {
1802 case OPC_DIV:
1803 case OPC_DIVU:
1804 #if defined(TARGET_MIPS64)
1805 case OPC_DDIV:
1806 case OPC_DDIVU:
1807 #endif
1808 t0 = tcg_temp_local_new();
1809 t1 = tcg_temp_local_new();
1810 break;
1811 default:
1812 t0 = tcg_temp_new();
1813 t1 = tcg_temp_new();
1814 break;
1817 gen_load_gpr(t0, rs);
1818 gen_load_gpr(t1, rt);
1819 switch (opc) {
1820 case OPC_DIV:
1822 int l1 = gen_new_label();
1823 int l2 = gen_new_label();
1825 tcg_gen_ext32s_tl(t0, t0);
1826 tcg_gen_ext32s_tl(t1, t1);
1827 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1828 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
1829 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
1831 tcg_gen_mov_tl(cpu_LO[0], t0);
1832 tcg_gen_movi_tl(cpu_HI[0], 0);
1833 tcg_gen_br(l1);
1834 gen_set_label(l2);
1835 tcg_gen_div_tl(cpu_LO[0], t0, t1);
1836 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
1837 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1838 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1839 gen_set_label(l1);
1841 opn = "div";
1842 break;
1843 case OPC_DIVU:
1845 int l1 = gen_new_label();
1847 tcg_gen_ext32u_tl(t0, t0);
1848 tcg_gen_ext32u_tl(t1, t1);
1849 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1850 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
1851 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
1852 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1853 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1854 gen_set_label(l1);
1856 opn = "divu";
1857 break;
1858 case OPC_MULT:
1860 TCGv_i64 t2 = tcg_temp_new_i64();
1861 TCGv_i64 t3 = tcg_temp_new_i64();
1863 tcg_gen_ext_tl_i64(t2, t0);
1864 tcg_gen_ext_tl_i64(t3, t1);
1865 tcg_gen_mul_i64(t2, t2, t3);
1866 tcg_temp_free_i64(t3);
1867 tcg_gen_trunc_i64_tl(t0, t2);
1868 tcg_gen_shri_i64(t2, t2, 32);
1869 tcg_gen_trunc_i64_tl(t1, t2);
1870 tcg_temp_free_i64(t2);
1871 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1872 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1874 opn = "mult";
1875 break;
1876 case OPC_MULTU:
1878 TCGv_i64 t2 = tcg_temp_new_i64();
1879 TCGv_i64 t3 = tcg_temp_new_i64();
1881 tcg_gen_ext32u_tl(t0, t0);
1882 tcg_gen_ext32u_tl(t1, t1);
1883 tcg_gen_extu_tl_i64(t2, t0);
1884 tcg_gen_extu_tl_i64(t3, t1);
1885 tcg_gen_mul_i64(t2, t2, t3);
1886 tcg_temp_free_i64(t3);
1887 tcg_gen_trunc_i64_tl(t0, t2);
1888 tcg_gen_shri_i64(t2, t2, 32);
1889 tcg_gen_trunc_i64_tl(t1, t2);
1890 tcg_temp_free_i64(t2);
1891 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1892 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1894 opn = "multu";
1895 break;
1896 #if defined(TARGET_MIPS64)
1897 case OPC_DDIV:
1899 int l1 = gen_new_label();
1900 int l2 = gen_new_label();
1902 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1903 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
1904 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
1905 tcg_gen_mov_tl(cpu_LO[0], t0);
1906 tcg_gen_movi_tl(cpu_HI[0], 0);
1907 tcg_gen_br(l1);
1908 gen_set_label(l2);
1909 tcg_gen_div_i64(cpu_LO[0], t0, t1);
1910 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
1911 gen_set_label(l1);
1913 opn = "ddiv";
1914 break;
1915 case OPC_DDIVU:
1917 int l1 = gen_new_label();
1919 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1920 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
1921 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
1922 gen_set_label(l1);
1924 opn = "ddivu";
1925 break;
1926 case OPC_DMULT:
1927 gen_helper_dmult(t0, t1);
1928 opn = "dmult";
1929 break;
1930 case OPC_DMULTU:
1931 gen_helper_dmultu(t0, t1);
1932 opn = "dmultu";
1933 break;
1934 #endif
1935 case OPC_MADD:
1937 TCGv_i64 t2 = tcg_temp_new_i64();
1938 TCGv_i64 t3 = tcg_temp_new_i64();
1940 tcg_gen_ext_tl_i64(t2, t0);
1941 tcg_gen_ext_tl_i64(t3, t1);
1942 tcg_gen_mul_i64(t2, t2, t3);
1943 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
1944 tcg_gen_add_i64(t2, t2, t3);
1945 tcg_temp_free_i64(t3);
1946 tcg_gen_trunc_i64_tl(t0, t2);
1947 tcg_gen_shri_i64(t2, t2, 32);
1948 tcg_gen_trunc_i64_tl(t1, t2);
1949 tcg_temp_free_i64(t2);
1950 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1951 tcg_gen_ext32s_tl(cpu_LO[1], t1);
1953 opn = "madd";
1954 break;
1955 case OPC_MADDU:
1957 TCGv_i64 t2 = tcg_temp_new_i64();
1958 TCGv_i64 t3 = tcg_temp_new_i64();
1960 tcg_gen_ext32u_tl(t0, t0);
1961 tcg_gen_ext32u_tl(t1, t1);
1962 tcg_gen_extu_tl_i64(t2, t0);
1963 tcg_gen_extu_tl_i64(t3, t1);
1964 tcg_gen_mul_i64(t2, t2, t3);
1965 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
1966 tcg_gen_add_i64(t2, t2, t3);
1967 tcg_temp_free_i64(t3);
1968 tcg_gen_trunc_i64_tl(t0, t2);
1969 tcg_gen_shri_i64(t2, t2, 32);
1970 tcg_gen_trunc_i64_tl(t1, t2);
1971 tcg_temp_free_i64(t2);
1972 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1973 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1975 opn = "maddu";
1976 break;
1977 case OPC_MSUB:
1979 TCGv_i64 t2 = tcg_temp_new_i64();
1980 TCGv_i64 t3 = tcg_temp_new_i64();
1982 tcg_gen_ext_tl_i64(t2, t0);
1983 tcg_gen_ext_tl_i64(t3, t1);
1984 tcg_gen_mul_i64(t2, t2, t3);
1985 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
1986 tcg_gen_sub_i64(t2, t2, t3);
1987 tcg_temp_free_i64(t3);
1988 tcg_gen_trunc_i64_tl(t0, t2);
1989 tcg_gen_shri_i64(t2, t2, 32);
1990 tcg_gen_trunc_i64_tl(t1, t2);
1991 tcg_temp_free_i64(t2);
1992 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1993 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1995 opn = "msub";
1996 break;
1997 case OPC_MSUBU:
1999 TCGv_i64 t2 = tcg_temp_new_i64();
2000 TCGv_i64 t3 = tcg_temp_new_i64();
2002 tcg_gen_ext32u_tl(t0, t0);
2003 tcg_gen_ext32u_tl(t1, t1);
2004 tcg_gen_extu_tl_i64(t2, t0);
2005 tcg_gen_extu_tl_i64(t3, t1);
2006 tcg_gen_mul_i64(t2, t2, t3);
2007 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2008 tcg_gen_sub_i64(t2, t2, t3);
2009 tcg_temp_free_i64(t3);
2010 tcg_gen_trunc_i64_tl(t0, t2);
2011 tcg_gen_shri_i64(t2, t2, 32);
2012 tcg_gen_trunc_i64_tl(t1, t2);
2013 tcg_temp_free_i64(t2);
2014 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2015 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2017 opn = "msubu";
2018 break;
2019 default:
2020 MIPS_INVAL(opn);
2021 generate_exception(ctx, EXCP_RI);
2022 goto out;
2024 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2025 out:
2026 tcg_temp_free(t0);
2027 tcg_temp_free(t1);
2030 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2031 int rd, int rs, int rt)
2033 const char *opn = "mul vr54xx";
2034 TCGv t0 = tcg_temp_new();
2035 TCGv t1 = tcg_temp_new();
2037 gen_load_gpr(t0, rs);
2038 gen_load_gpr(t1, rt);
2040 switch (opc) {
2041 case OPC_VR54XX_MULS:
2042 gen_helper_muls(t0, t0, t1);
2043 opn = "muls";
2044 break;
2045 case OPC_VR54XX_MULSU:
2046 gen_helper_mulsu(t0, t0, t1);
2047 opn = "mulsu";
2048 break;
2049 case OPC_VR54XX_MACC:
2050 gen_helper_macc(t0, t0, t1);
2051 opn = "macc";
2052 break;
2053 case OPC_VR54XX_MACCU:
2054 gen_helper_maccu(t0, t0, t1);
2055 opn = "maccu";
2056 break;
2057 case OPC_VR54XX_MSAC:
2058 gen_helper_msac(t0, t0, t1);
2059 opn = "msac";
2060 break;
2061 case OPC_VR54XX_MSACU:
2062 gen_helper_msacu(t0, t0, t1);
2063 opn = "msacu";
2064 break;
2065 case OPC_VR54XX_MULHI:
2066 gen_helper_mulhi(t0, t0, t1);
2067 opn = "mulhi";
2068 break;
2069 case OPC_VR54XX_MULHIU:
2070 gen_helper_mulhiu(t0, t0, t1);
2071 opn = "mulhiu";
2072 break;
2073 case OPC_VR54XX_MULSHI:
2074 gen_helper_mulshi(t0, t0, t1);
2075 opn = "mulshi";
2076 break;
2077 case OPC_VR54XX_MULSHIU:
2078 gen_helper_mulshiu(t0, t0, t1);
2079 opn = "mulshiu";
2080 break;
2081 case OPC_VR54XX_MACCHI:
2082 gen_helper_macchi(t0, t0, t1);
2083 opn = "macchi";
2084 break;
2085 case OPC_VR54XX_MACCHIU:
2086 gen_helper_macchiu(t0, t0, t1);
2087 opn = "macchiu";
2088 break;
2089 case OPC_VR54XX_MSACHI:
2090 gen_helper_msachi(t0, t0, t1);
2091 opn = "msachi";
2092 break;
2093 case OPC_VR54XX_MSACHIU:
2094 gen_helper_msachiu(t0, t0, t1);
2095 opn = "msachiu";
2096 break;
2097 default:
2098 MIPS_INVAL("mul vr54xx");
2099 generate_exception(ctx, EXCP_RI);
2100 goto out;
2102 gen_store_gpr(t0, rd);
2103 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2105 out:
2106 tcg_temp_free(t0);
2107 tcg_temp_free(t1);
2110 static void gen_cl (DisasContext *ctx, uint32_t opc,
2111 int rd, int rs)
2113 const char *opn = "CLx";
2114 TCGv t0;
2116 if (rd == 0) {
2117 /* Treat as NOP. */
2118 MIPS_DEBUG("NOP");
2119 return;
2121 t0 = tcg_temp_new();
2122 gen_load_gpr(t0, rs);
2123 switch (opc) {
2124 case OPC_CLO:
2125 gen_helper_clo(cpu_gpr[rd], t0);
2126 opn = "clo";
2127 break;
2128 case OPC_CLZ:
2129 gen_helper_clz(cpu_gpr[rd], t0);
2130 opn = "clz";
2131 break;
2132 #if defined(TARGET_MIPS64)
2133 case OPC_DCLO:
2134 gen_helper_dclo(cpu_gpr[rd], t0);
2135 opn = "dclo";
2136 break;
2137 case OPC_DCLZ:
2138 gen_helper_dclz(cpu_gpr[rd], t0);
2139 opn = "dclz";
2140 break;
2141 #endif
2143 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2144 tcg_temp_free(t0);
2147 /* Traps */
2148 static void gen_trap (DisasContext *ctx, uint32_t opc,
2149 int rs, int rt, int16_t imm)
2151 int cond;
2152 TCGv t0 = tcg_temp_new();
2153 TCGv t1 = tcg_temp_new();
2155 cond = 0;
2156 /* Load needed operands */
2157 switch (opc) {
2158 case OPC_TEQ:
2159 case OPC_TGE:
2160 case OPC_TGEU:
2161 case OPC_TLT:
2162 case OPC_TLTU:
2163 case OPC_TNE:
2164 /* Compare two registers */
2165 if (rs != rt) {
2166 gen_load_gpr(t0, rs);
2167 gen_load_gpr(t1, rt);
2168 cond = 1;
2170 break;
2171 case OPC_TEQI:
2172 case OPC_TGEI:
2173 case OPC_TGEIU:
2174 case OPC_TLTI:
2175 case OPC_TLTIU:
2176 case OPC_TNEI:
2177 /* Compare register to immediate */
2178 if (rs != 0 || imm != 0) {
2179 gen_load_gpr(t0, rs);
2180 tcg_gen_movi_tl(t1, (int32_t)imm);
2181 cond = 1;
2183 break;
2185 if (cond == 0) {
2186 switch (opc) {
2187 case OPC_TEQ: /* rs == rs */
2188 case OPC_TEQI: /* r0 == 0 */
2189 case OPC_TGE: /* rs >= rs */
2190 case OPC_TGEI: /* r0 >= 0 */
2191 case OPC_TGEU: /* rs >= rs unsigned */
2192 case OPC_TGEIU: /* r0 >= 0 unsigned */
2193 /* Always trap */
2194 generate_exception(ctx, EXCP_TRAP);
2195 break;
2196 case OPC_TLT: /* rs < rs */
2197 case OPC_TLTI: /* r0 < 0 */
2198 case OPC_TLTU: /* rs < rs unsigned */
2199 case OPC_TLTIU: /* r0 < 0 unsigned */
2200 case OPC_TNE: /* rs != rs */
2201 case OPC_TNEI: /* r0 != 0 */
2202 /* Never trap: treat as NOP. */
2203 break;
2205 } else {
2206 int l1 = gen_new_label();
2208 switch (opc) {
2209 case OPC_TEQ:
2210 case OPC_TEQI:
2211 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2212 break;
2213 case OPC_TGE:
2214 case OPC_TGEI:
2215 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2216 break;
2217 case OPC_TGEU:
2218 case OPC_TGEIU:
2219 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2220 break;
2221 case OPC_TLT:
2222 case OPC_TLTI:
2223 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2224 break;
2225 case OPC_TLTU:
2226 case OPC_TLTIU:
2227 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2228 break;
2229 case OPC_TNE:
2230 case OPC_TNEI:
2231 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2232 break;
2234 generate_exception(ctx, EXCP_TRAP);
2235 gen_set_label(l1);
2237 tcg_temp_free(t0);
2238 tcg_temp_free(t1);
2241 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2243 TranslationBlock *tb;
2244 tb = ctx->tb;
2245 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2246 tcg_gen_goto_tb(n);
2247 gen_save_pc(dest);
2248 tcg_gen_exit_tb((long)tb + n);
2249 } else {
2250 gen_save_pc(dest);
2251 tcg_gen_exit_tb(0);
2255 /* Branches (before delay slot) */
2256 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2257 int rs, int rt, int32_t offset)
2259 target_ulong btgt = -1;
2260 int blink = 0;
2261 int bcond_compute = 0;
2262 TCGv t0 = tcg_temp_new();
2263 TCGv t1 = tcg_temp_new();
2265 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2266 #ifdef MIPS_DEBUG_DISAS
2267 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2268 #endif
2269 generate_exception(ctx, EXCP_RI);
2270 goto out;
2273 /* Load needed operands */
2274 switch (opc) {
2275 case OPC_BEQ:
2276 case OPC_BEQL:
2277 case OPC_BNE:
2278 case OPC_BNEL:
2279 /* Compare two registers */
2280 if (rs != rt) {
2281 gen_load_gpr(t0, rs);
2282 gen_load_gpr(t1, rt);
2283 bcond_compute = 1;
2285 btgt = ctx->pc + 4 + offset;
2286 break;
2287 case OPC_BGEZ:
2288 case OPC_BGEZAL:
2289 case OPC_BGEZALL:
2290 case OPC_BGEZL:
2291 case OPC_BGTZ:
2292 case OPC_BGTZL:
2293 case OPC_BLEZ:
2294 case OPC_BLEZL:
2295 case OPC_BLTZ:
2296 case OPC_BLTZAL:
2297 case OPC_BLTZALL:
2298 case OPC_BLTZL:
2299 /* Compare to zero */
2300 if (rs != 0) {
2301 gen_load_gpr(t0, rs);
2302 bcond_compute = 1;
2304 btgt = ctx->pc + 4 + offset;
2305 break;
2306 case OPC_J:
2307 case OPC_JAL:
2308 /* Jump to immediate */
2309 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2310 break;
2311 case OPC_JR:
2312 case OPC_JALR:
2313 /* Jump to register */
2314 if (offset != 0 && offset != 16) {
2315 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2316 others are reserved. */
2317 MIPS_INVAL("jump hint");
2318 generate_exception(ctx, EXCP_RI);
2319 goto out;
2321 gen_load_gpr(btarget, rs);
2322 break;
2323 default:
2324 MIPS_INVAL("branch/jump");
2325 generate_exception(ctx, EXCP_RI);
2326 goto out;
2328 if (bcond_compute == 0) {
2329 /* No condition to be computed */
2330 switch (opc) {
2331 case OPC_BEQ: /* rx == rx */
2332 case OPC_BEQL: /* rx == rx likely */
2333 case OPC_BGEZ: /* 0 >= 0 */
2334 case OPC_BGEZL: /* 0 >= 0 likely */
2335 case OPC_BLEZ: /* 0 <= 0 */
2336 case OPC_BLEZL: /* 0 <= 0 likely */
2337 /* Always take */
2338 ctx->hflags |= MIPS_HFLAG_B;
2339 MIPS_DEBUG("balways");
2340 break;
2341 case OPC_BGEZAL: /* 0 >= 0 */
2342 case OPC_BGEZALL: /* 0 >= 0 likely */
2343 /* Always take and link */
2344 blink = 31;
2345 ctx->hflags |= MIPS_HFLAG_B;
2346 MIPS_DEBUG("balways and link");
2347 break;
2348 case OPC_BNE: /* rx != rx */
2349 case OPC_BGTZ: /* 0 > 0 */
2350 case OPC_BLTZ: /* 0 < 0 */
2351 /* Treat as NOP. */
2352 MIPS_DEBUG("bnever (NOP)");
2353 goto out;
2354 case OPC_BLTZAL: /* 0 < 0 */
2355 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2356 MIPS_DEBUG("bnever and link");
2357 goto out;
2358 case OPC_BLTZALL: /* 0 < 0 likely */
2359 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2360 /* Skip the instruction in the delay slot */
2361 MIPS_DEBUG("bnever, link and skip");
2362 ctx->pc += 4;
2363 goto out;
2364 case OPC_BNEL: /* rx != rx likely */
2365 case OPC_BGTZL: /* 0 > 0 likely */
2366 case OPC_BLTZL: /* 0 < 0 likely */
2367 /* Skip the instruction in the delay slot */
2368 MIPS_DEBUG("bnever and skip");
2369 ctx->pc += 4;
2370 goto out;
2371 case OPC_J:
2372 ctx->hflags |= MIPS_HFLAG_B;
2373 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2374 break;
2375 case OPC_JAL:
2376 blink = 31;
2377 ctx->hflags |= MIPS_HFLAG_B;
2378 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2379 break;
2380 case OPC_JR:
2381 ctx->hflags |= MIPS_HFLAG_BR;
2382 MIPS_DEBUG("jr %s", regnames[rs]);
2383 break;
2384 case OPC_JALR:
2385 blink = rt;
2386 ctx->hflags |= MIPS_HFLAG_BR;
2387 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2388 break;
2389 default:
2390 MIPS_INVAL("branch/jump");
2391 generate_exception(ctx, EXCP_RI);
2392 goto out;
2394 } else {
2395 switch (opc) {
2396 case OPC_BEQ:
2397 gen_op_eq(bcond, t0, t1);
2398 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2399 regnames[rs], regnames[rt], btgt);
2400 goto not_likely;
2401 case OPC_BEQL:
2402 gen_op_eq(bcond, t0, t1);
2403 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2404 regnames[rs], regnames[rt], btgt);
2405 goto likely;
2406 case OPC_BNE:
2407 gen_op_ne(bcond, t0, t1);
2408 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2409 regnames[rs], regnames[rt], btgt);
2410 goto not_likely;
2411 case OPC_BNEL:
2412 gen_op_ne(bcond, t0, t1);
2413 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2414 regnames[rs], regnames[rt], btgt);
2415 goto likely;
2416 case OPC_BGEZ:
2417 gen_op_gez(bcond, t0);
2418 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2419 goto not_likely;
2420 case OPC_BGEZL:
2421 gen_op_gez(bcond, t0);
2422 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2423 goto likely;
2424 case OPC_BGEZAL:
2425 gen_op_gez(bcond, t0);
2426 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2427 blink = 31;
2428 goto not_likely;
2429 case OPC_BGEZALL:
2430 gen_op_gez(bcond, t0);
2431 blink = 31;
2432 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2433 goto likely;
2434 case OPC_BGTZ:
2435 gen_op_gtz(bcond, t0);
2436 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2437 goto not_likely;
2438 case OPC_BGTZL:
2439 gen_op_gtz(bcond, t0);
2440 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2441 goto likely;
2442 case OPC_BLEZ:
2443 gen_op_lez(bcond, t0);
2444 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2445 goto not_likely;
2446 case OPC_BLEZL:
2447 gen_op_lez(bcond, t0);
2448 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2449 goto likely;
2450 case OPC_BLTZ:
2451 gen_op_ltz(bcond, t0);
2452 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2453 goto not_likely;
2454 case OPC_BLTZL:
2455 gen_op_ltz(bcond, t0);
2456 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2457 goto likely;
2458 case OPC_BLTZAL:
2459 gen_op_ltz(bcond, t0);
2460 blink = 31;
2461 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2462 not_likely:
2463 ctx->hflags |= MIPS_HFLAG_BC;
2464 break;
2465 case OPC_BLTZALL:
2466 gen_op_ltz(bcond, t0);
2467 blink = 31;
2468 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2469 likely:
2470 ctx->hflags |= MIPS_HFLAG_BL;
2471 break;
2472 default:
2473 MIPS_INVAL("conditional branch/jump");
2474 generate_exception(ctx, EXCP_RI);
2475 goto out;
2478 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2479 blink, ctx->hflags, btgt);
2481 ctx->btarget = btgt;
2482 if (blink > 0) {
2483 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8);
2486 out:
2487 tcg_temp_free(t0);
2488 tcg_temp_free(t1);
2491 /* special3 bitfield operations */
2492 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2493 int rs, int lsb, int msb)
2495 TCGv t0 = tcg_temp_new();
2496 TCGv t1 = tcg_temp_new();
2497 target_ulong mask;
2499 gen_load_gpr(t1, rs);
2500 switch (opc) {
2501 case OPC_EXT:
2502 if (lsb + msb > 31)
2503 goto fail;
2504 tcg_gen_shri_tl(t0, t1, lsb);
2505 if (msb != 31) {
2506 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2507 } else {
2508 tcg_gen_ext32s_tl(t0, t0);
2510 break;
2511 #if defined(TARGET_MIPS64)
2512 case OPC_DEXTM:
2513 tcg_gen_shri_tl(t0, t1, lsb);
2514 if (msb != 31) {
2515 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2517 break;
2518 case OPC_DEXTU:
2519 tcg_gen_shri_tl(t0, t1, lsb + 32);
2520 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2521 break;
2522 case OPC_DEXT:
2523 tcg_gen_shri_tl(t0, t1, lsb);
2524 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2525 break;
2526 #endif
2527 case OPC_INS:
2528 if (lsb > msb)
2529 goto fail;
2530 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2531 gen_load_gpr(t0, rt);
2532 tcg_gen_andi_tl(t0, t0, ~mask);
2533 tcg_gen_shli_tl(t1, t1, lsb);
2534 tcg_gen_andi_tl(t1, t1, mask);
2535 tcg_gen_or_tl(t0, t0, t1);
2536 tcg_gen_ext32s_tl(t0, t0);
2537 break;
2538 #if defined(TARGET_MIPS64)
2539 case OPC_DINSM:
2540 if (lsb > msb)
2541 goto fail;
2542 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2543 gen_load_gpr(t0, rt);
2544 tcg_gen_andi_tl(t0, t0, ~mask);
2545 tcg_gen_shli_tl(t1, t1, lsb);
2546 tcg_gen_andi_tl(t1, t1, mask);
2547 tcg_gen_or_tl(t0, t0, t1);
2548 break;
2549 case OPC_DINSU:
2550 if (lsb > msb)
2551 goto fail;
2552 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2553 gen_load_gpr(t0, rt);
2554 tcg_gen_andi_tl(t0, t0, ~mask);
2555 tcg_gen_shli_tl(t1, t1, lsb + 32);
2556 tcg_gen_andi_tl(t1, t1, mask);
2557 tcg_gen_or_tl(t0, t0, t1);
2558 break;
2559 case OPC_DINS:
2560 if (lsb > msb)
2561 goto fail;
2562 gen_load_gpr(t0, rt);
2563 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2564 gen_load_gpr(t0, rt);
2565 tcg_gen_andi_tl(t0, t0, ~mask);
2566 tcg_gen_shli_tl(t1, t1, lsb);
2567 tcg_gen_andi_tl(t1, t1, mask);
2568 tcg_gen_or_tl(t0, t0, t1);
2569 break;
2570 #endif
2571 default:
2572 fail:
2573 MIPS_INVAL("bitops");
2574 generate_exception(ctx, EXCP_RI);
2575 tcg_temp_free(t0);
2576 tcg_temp_free(t1);
2577 return;
2579 gen_store_gpr(t0, rt);
2580 tcg_temp_free(t0);
2581 tcg_temp_free(t1);
2584 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2586 TCGv t0;
2588 if (rd == 0) {
2589 /* If no destination, treat it as a NOP. */
2590 MIPS_DEBUG("NOP");
2591 return;
2594 t0 = tcg_temp_new();
2595 gen_load_gpr(t0, rt);
2596 switch (op2) {
2597 case OPC_WSBH:
2599 TCGv t1 = tcg_temp_new();
2601 tcg_gen_shri_tl(t1, t0, 8);
2602 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2603 tcg_gen_shli_tl(t0, t0, 8);
2604 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2605 tcg_gen_or_tl(t0, t0, t1);
2606 tcg_temp_free(t1);
2607 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2609 break;
2610 case OPC_SEB:
2611 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2612 break;
2613 case OPC_SEH:
2614 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2615 break;
2616 #if defined(TARGET_MIPS64)
2617 case OPC_DSBH:
2619 TCGv t1 = tcg_temp_new();
2621 tcg_gen_shri_tl(t1, t0, 8);
2622 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2623 tcg_gen_shli_tl(t0, t0, 8);
2624 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2625 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2626 tcg_temp_free(t1);
2628 break;
2629 case OPC_DSHD:
2631 TCGv t1 = tcg_temp_new();
2633 tcg_gen_shri_tl(t1, t0, 16);
2634 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2635 tcg_gen_shli_tl(t0, t0, 16);
2636 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2637 tcg_gen_or_tl(t0, t0, t1);
2638 tcg_gen_shri_tl(t1, t0, 32);
2639 tcg_gen_shli_tl(t0, t0, 32);
2640 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2641 tcg_temp_free(t1);
2643 break;
2644 #endif
2645 default:
2646 MIPS_INVAL("bsfhl");
2647 generate_exception(ctx, EXCP_RI);
2648 tcg_temp_free(t0);
2649 return;
2651 tcg_temp_free(t0);
2654 #ifndef CONFIG_USER_ONLY
2655 /* CP0 (MMU and control) */
2656 static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
2658 TCGv_i32 r_tmp = tcg_temp_new_i32();
2660 tcg_gen_ld_i32(r_tmp, cpu_env, off);
2661 tcg_gen_ext_i32_tl(t, r_tmp);
2662 tcg_temp_free_i32(r_tmp);
2665 static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
2667 tcg_gen_ld_tl(t, cpu_env, off);
2668 tcg_gen_ext32s_tl(t, t);
2671 static inline void gen_mtc0_store32 (TCGv t, target_ulong off)
2673 TCGv_i32 r_tmp = tcg_temp_new_i32();
2675 tcg_gen_trunc_tl_i32(r_tmp, t);
2676 tcg_gen_st_i32(r_tmp, cpu_env, off);
2677 tcg_temp_free_i32(r_tmp);
2680 static inline void gen_mtc0_store64 (TCGv t, target_ulong off)
2682 tcg_gen_ext32s_tl(t, t);
2683 tcg_gen_st_tl(t, cpu_env, off);
2686 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
2688 const char *rn = "invalid";
2690 if (sel != 0)
2691 check_insn(env, ctx, ISA_MIPS32);
2693 switch (reg) {
2694 case 0:
2695 switch (sel) {
2696 case 0:
2697 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
2698 rn = "Index";
2699 break;
2700 case 1:
2701 check_insn(env, ctx, ASE_MT);
2702 gen_helper_mfc0_mvpcontrol(t0);
2703 rn = "MVPControl";
2704 break;
2705 case 2:
2706 check_insn(env, ctx, ASE_MT);
2707 gen_helper_mfc0_mvpconf0(t0);
2708 rn = "MVPConf0";
2709 break;
2710 case 3:
2711 check_insn(env, ctx, ASE_MT);
2712 gen_helper_mfc0_mvpconf1(t0);
2713 rn = "MVPConf1";
2714 break;
2715 default:
2716 goto die;
2718 break;
2719 case 1:
2720 switch (sel) {
2721 case 0:
2722 gen_helper_mfc0_random(t0);
2723 rn = "Random";
2724 break;
2725 case 1:
2726 check_insn(env, ctx, ASE_MT);
2727 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
2728 rn = "VPEControl";
2729 break;
2730 case 2:
2731 check_insn(env, ctx, ASE_MT);
2732 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
2733 rn = "VPEConf0";
2734 break;
2735 case 3:
2736 check_insn(env, ctx, ASE_MT);
2737 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
2738 rn = "VPEConf1";
2739 break;
2740 case 4:
2741 check_insn(env, ctx, ASE_MT);
2742 gen_mfc0_load64(t0, offsetof(CPUState, CP0_YQMask));
2743 rn = "YQMask";
2744 break;
2745 case 5:
2746 check_insn(env, ctx, ASE_MT);
2747 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPESchedule));
2748 rn = "VPESchedule";
2749 break;
2750 case 6:
2751 check_insn(env, ctx, ASE_MT);
2752 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPEScheFBack));
2753 rn = "VPEScheFBack";
2754 break;
2755 case 7:
2756 check_insn(env, ctx, ASE_MT);
2757 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
2758 rn = "VPEOpt";
2759 break;
2760 default:
2761 goto die;
2763 break;
2764 case 2:
2765 switch (sel) {
2766 case 0:
2767 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2768 tcg_gen_ext32s_tl(t0, t0);
2769 rn = "EntryLo0";
2770 break;
2771 case 1:
2772 check_insn(env, ctx, ASE_MT);
2773 gen_helper_mfc0_tcstatus(t0);
2774 rn = "TCStatus";
2775 break;
2776 case 2:
2777 check_insn(env, ctx, ASE_MT);
2778 gen_helper_mfc0_tcbind(t0);
2779 rn = "TCBind";
2780 break;
2781 case 3:
2782 check_insn(env, ctx, ASE_MT);
2783 gen_helper_mfc0_tcrestart(t0);
2784 rn = "TCRestart";
2785 break;
2786 case 4:
2787 check_insn(env, ctx, ASE_MT);
2788 gen_helper_mfc0_tchalt(t0);
2789 rn = "TCHalt";
2790 break;
2791 case 5:
2792 check_insn(env, ctx, ASE_MT);
2793 gen_helper_mfc0_tccontext(t0);
2794 rn = "TCContext";
2795 break;
2796 case 6:
2797 check_insn(env, ctx, ASE_MT);
2798 gen_helper_mfc0_tcschedule(t0);
2799 rn = "TCSchedule";
2800 break;
2801 case 7:
2802 check_insn(env, ctx, ASE_MT);
2803 gen_helper_mfc0_tcschefback(t0);
2804 rn = "TCScheFBack";
2805 break;
2806 default:
2807 goto die;
2809 break;
2810 case 3:
2811 switch (sel) {
2812 case 0:
2813 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2814 tcg_gen_ext32s_tl(t0, t0);
2815 rn = "EntryLo1";
2816 break;
2817 default:
2818 goto die;
2820 break;
2821 case 4:
2822 switch (sel) {
2823 case 0:
2824 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
2825 tcg_gen_ext32s_tl(t0, t0);
2826 rn = "Context";
2827 break;
2828 case 1:
2829 // gen_helper_mfc0_contextconfig(t0); /* SmartMIPS ASE */
2830 rn = "ContextConfig";
2831 // break;
2832 default:
2833 goto die;
2835 break;
2836 case 5:
2837 switch (sel) {
2838 case 0:
2839 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
2840 rn = "PageMask";
2841 break;
2842 case 1:
2843 check_insn(env, ctx, ISA_MIPS32R2);
2844 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
2845 rn = "PageGrain";
2846 break;
2847 default:
2848 goto die;
2850 break;
2851 case 6:
2852 switch (sel) {
2853 case 0:
2854 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
2855 rn = "Wired";
2856 break;
2857 case 1:
2858 check_insn(env, ctx, ISA_MIPS32R2);
2859 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
2860 rn = "SRSConf0";
2861 break;
2862 case 2:
2863 check_insn(env, ctx, ISA_MIPS32R2);
2864 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
2865 rn = "SRSConf1";
2866 break;
2867 case 3:
2868 check_insn(env, ctx, ISA_MIPS32R2);
2869 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
2870 rn = "SRSConf2";
2871 break;
2872 case 4:
2873 check_insn(env, ctx, ISA_MIPS32R2);
2874 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
2875 rn = "SRSConf3";
2876 break;
2877 case 5:
2878 check_insn(env, ctx, ISA_MIPS32R2);
2879 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
2880 rn = "SRSConf4";
2881 break;
2882 default:
2883 goto die;
2885 break;
2886 case 7:
2887 switch (sel) {
2888 case 0:
2889 check_insn(env, ctx, ISA_MIPS32R2);
2890 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
2891 rn = "HWREna";
2892 break;
2893 default:
2894 goto die;
2896 break;
2897 case 8:
2898 switch (sel) {
2899 case 0:
2900 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
2901 tcg_gen_ext32s_tl(t0, t0);
2902 rn = "BadVAddr";
2903 break;
2904 default:
2905 goto die;
2907 break;
2908 case 9:
2909 switch (sel) {
2910 case 0:
2911 /* Mark as an IO operation because we read the time. */
2912 if (use_icount)
2913 gen_io_start();
2914 gen_helper_mfc0_count(t0);
2915 if (use_icount) {
2916 gen_io_end();
2917 ctx->bstate = BS_STOP;
2919 rn = "Count";
2920 break;
2921 /* 6,7 are implementation dependent */
2922 default:
2923 goto die;
2925 break;
2926 case 10:
2927 switch (sel) {
2928 case 0:
2929 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
2930 tcg_gen_ext32s_tl(t0, t0);
2931 rn = "EntryHi";
2932 break;
2933 default:
2934 goto die;
2936 break;
2937 case 11:
2938 switch (sel) {
2939 case 0:
2940 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
2941 rn = "Compare";
2942 break;
2943 /* 6,7 are implementation dependent */
2944 default:
2945 goto die;
2947 break;
2948 case 12:
2949 switch (sel) {
2950 case 0:
2951 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
2952 rn = "Status";
2953 break;
2954 case 1:
2955 check_insn(env, ctx, ISA_MIPS32R2);
2956 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
2957 rn = "IntCtl";
2958 break;
2959 case 2:
2960 check_insn(env, ctx, ISA_MIPS32R2);
2961 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
2962 rn = "SRSCtl";
2963 break;
2964 case 3:
2965 check_insn(env, ctx, ISA_MIPS32R2);
2966 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
2967 rn = "SRSMap";
2968 break;
2969 default:
2970 goto die;
2972 break;
2973 case 13:
2974 switch (sel) {
2975 case 0:
2976 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
2977 rn = "Cause";
2978 break;
2979 default:
2980 goto die;
2982 break;
2983 case 14:
2984 switch (sel) {
2985 case 0:
2986 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
2987 tcg_gen_ext32s_tl(t0, t0);
2988 rn = "EPC";
2989 break;
2990 default:
2991 goto die;
2993 break;
2994 case 15:
2995 switch (sel) {
2996 case 0:
2997 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
2998 rn = "PRid";
2999 break;
3000 case 1:
3001 check_insn(env, ctx, ISA_MIPS32R2);
3002 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
3003 rn = "EBase";
3004 break;
3005 default:
3006 goto die;
3008 break;
3009 case 16:
3010 switch (sel) {
3011 case 0:
3012 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
3013 rn = "Config";
3014 break;
3015 case 1:
3016 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
3017 rn = "Config1";
3018 break;
3019 case 2:
3020 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
3021 rn = "Config2";
3022 break;
3023 case 3:
3024 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
3025 rn = "Config3";
3026 break;
3027 /* 4,5 are reserved */
3028 /* 6,7 are implementation dependent */
3029 case 6:
3030 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
3031 rn = "Config6";
3032 break;
3033 case 7:
3034 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
3035 rn = "Config7";
3036 break;
3037 default:
3038 goto die;
3040 break;
3041 case 17:
3042 switch (sel) {
3043 case 0:
3044 gen_helper_mfc0_lladdr(t0);
3045 rn = "LLAddr";
3046 break;
3047 default:
3048 goto die;
3050 break;
3051 case 18:
3052 switch (sel) {
3053 case 0 ... 7:
3054 gen_helper_1i(mfc0_watchlo, t0, sel);
3055 rn = "WatchLo";
3056 break;
3057 default:
3058 goto die;
3060 break;
3061 case 19:
3062 switch (sel) {
3063 case 0 ...7:
3064 gen_helper_1i(mfc0_watchhi, t0, sel);
3065 rn = "WatchHi";
3066 break;
3067 default:
3068 goto die;
3070 break;
3071 case 20:
3072 switch (sel) {
3073 case 0:
3074 #if defined(TARGET_MIPS64)
3075 check_insn(env, ctx, ISA_MIPS3);
3076 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
3077 tcg_gen_ext32s_tl(t0, t0);
3078 rn = "XContext";
3079 break;
3080 #endif
3081 default:
3082 goto die;
3084 break;
3085 case 21:
3086 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3087 switch (sel) {
3088 case 0:
3089 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
3090 rn = "Framemask";
3091 break;
3092 default:
3093 goto die;
3095 break;
3096 case 22:
3097 tcg_gen_movi_tl(t0, 0); /* unimplemented */
3098 rn = "'Diagnostic"; /* implementation dependent */
3099 break;
3100 case 23:
3101 switch (sel) {
3102 case 0:
3103 gen_helper_mfc0_debug(t0); /* EJTAG support */
3104 rn = "Debug";
3105 break;
3106 case 1:
3107 // gen_helper_mfc0_tracecontrol(t0); /* PDtrace support */
3108 rn = "TraceControl";
3109 // break;
3110 case 2:
3111 // gen_helper_mfc0_tracecontrol2(t0); /* PDtrace support */
3112 rn = "TraceControl2";
3113 // break;
3114 case 3:
3115 // gen_helper_mfc0_usertracedata(t0); /* PDtrace support */
3116 rn = "UserTraceData";
3117 // break;
3118 case 4:
3119 // gen_helper_mfc0_tracebpc(t0); /* PDtrace support */
3120 rn = "TraceBPC";
3121 // break;
3122 default:
3123 goto die;
3125 break;
3126 case 24:
3127 switch (sel) {
3128 case 0:
3129 /* EJTAG support */
3130 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
3131 tcg_gen_ext32s_tl(t0, t0);
3132 rn = "DEPC";
3133 break;
3134 default:
3135 goto die;
3137 break;
3138 case 25:
3139 switch (sel) {
3140 case 0:
3141 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
3142 rn = "Performance0";
3143 break;
3144 case 1:
3145 // gen_helper_mfc0_performance1(t0);
3146 rn = "Performance1";
3147 // break;
3148 case 2:
3149 // gen_helper_mfc0_performance2(t0);
3150 rn = "Performance2";
3151 // break;
3152 case 3:
3153 // gen_helper_mfc0_performance3(t0);
3154 rn = "Performance3";
3155 // break;
3156 case 4:
3157 // gen_helper_mfc0_performance4(t0);
3158 rn = "Performance4";
3159 // break;
3160 case 5:
3161 // gen_helper_mfc0_performance5(t0);
3162 rn = "Performance5";
3163 // break;
3164 case 6:
3165 // gen_helper_mfc0_performance6(t0);
3166 rn = "Performance6";
3167 // break;
3168 case 7:
3169 // gen_helper_mfc0_performance7(t0);
3170 rn = "Performance7";
3171 // break;
3172 default:
3173 goto die;
3175 break;
3176 case 26:
3177 tcg_gen_movi_tl(t0, 0); /* unimplemented */
3178 rn = "ECC";
3179 break;
3180 case 27:
3181 switch (sel) {
3182 case 0 ... 3:
3183 tcg_gen_movi_tl(t0, 0); /* unimplemented */
3184 rn = "CacheErr";
3185 break;
3186 default:
3187 goto die;
3189 break;
3190 case 28:
3191 switch (sel) {
3192 case 0:
3193 case 2:
3194 case 4:
3195 case 6:
3196 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
3197 rn = "TagLo";
3198 break;
3199 case 1:
3200 case 3:
3201 case 5:
3202 case 7:
3203 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
3204 rn = "DataLo";
3205 break;
3206 default:
3207 goto die;
3209 break;
3210 case 29:
3211 switch (sel) {
3212 case 0:
3213 case 2:
3214 case 4:
3215 case 6:
3216 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
3217 rn = "TagHi";
3218 break;
3219 case 1:
3220 case 3:
3221 case 5:
3222 case 7:
3223 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
3224 rn = "DataHi";
3225 break;
3226 default:
3227 goto die;
3229 break;
3230 case 30:
3231 switch (sel) {
3232 case 0:
3233 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3234 tcg_gen_ext32s_tl(t0, t0);
3235 rn = "ErrorEPC";
3236 break;
3237 default:
3238 goto die;
3240 break;
3241 case 31:
3242 switch (sel) {
3243 case 0:
3244 /* EJTAG support */
3245 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
3246 rn = "DESAVE";
3247 break;
3248 default:
3249 goto die;
3251 break;
3252 default:
3253 goto die;
3255 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3256 return;
3258 die:
3259 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3260 generate_exception(ctx, EXCP_RI);
3263 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
3265 const char *rn = "invalid";
3267 if (sel != 0)
3268 check_insn(env, ctx, ISA_MIPS32);
3270 if (use_icount)
3271 gen_io_start();
3273 switch (reg) {
3274 case 0:
3275 switch (sel) {
3276 case 0:
3277 gen_helper_mtc0_index(t0);
3278 rn = "Index";
3279 break;
3280 case 1:
3281 check_insn(env, ctx, ASE_MT);
3282 gen_helper_mtc0_mvpcontrol(t0);
3283 rn = "MVPControl";
3284 break;
3285 case 2:
3286 check_insn(env, ctx, ASE_MT);
3287 /* ignored */
3288 rn = "MVPConf0";
3289 break;
3290 case 3:
3291 check_insn(env, ctx, ASE_MT);
3292 /* ignored */
3293 rn = "MVPConf1";
3294 break;
3295 default:
3296 goto die;
3298 break;
3299 case 1:
3300 switch (sel) {
3301 case 0:
3302 /* ignored */
3303 rn = "Random";
3304 break;
3305 case 1:
3306 check_insn(env, ctx, ASE_MT);
3307 gen_helper_mtc0_vpecontrol(t0);
3308 rn = "VPEControl";
3309 break;
3310 case 2:
3311 check_insn(env, ctx, ASE_MT);
3312 gen_helper_mtc0_vpeconf0(t0);
3313 rn = "VPEConf0";
3314 break;
3315 case 3:
3316 check_insn(env, ctx, ASE_MT);
3317 gen_helper_mtc0_vpeconf1(t0);
3318 rn = "VPEConf1";
3319 break;
3320 case 4:
3321 check_insn(env, ctx, ASE_MT);
3322 gen_helper_mtc0_yqmask(t0);
3323 rn = "YQMask";
3324 break;
3325 case 5:
3326 check_insn(env, ctx, ASE_MT);
3327 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule));
3328 rn = "VPESchedule";
3329 break;
3330 case 6:
3331 check_insn(env, ctx, ASE_MT);
3332 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack));
3333 rn = "VPEScheFBack";
3334 break;
3335 case 7:
3336 check_insn(env, ctx, ASE_MT);
3337 gen_helper_mtc0_vpeopt(t0);
3338 rn = "VPEOpt";
3339 break;
3340 default:
3341 goto die;
3343 break;
3344 case 2:
3345 switch (sel) {
3346 case 0:
3347 gen_helper_mtc0_entrylo0(t0);
3348 rn = "EntryLo0";
3349 break;
3350 case 1:
3351 check_insn(env, ctx, ASE_MT);
3352 gen_helper_mtc0_tcstatus(t0);
3353 rn = "TCStatus";
3354 break;
3355 case 2:
3356 check_insn(env, ctx, ASE_MT);
3357 gen_helper_mtc0_tcbind(t0);
3358 rn = "TCBind";
3359 break;
3360 case 3:
3361 check_insn(env, ctx, ASE_MT);
3362 gen_helper_mtc0_tcrestart(t0);
3363 rn = "TCRestart";
3364 break;
3365 case 4:
3366 check_insn(env, ctx, ASE_MT);
3367 gen_helper_mtc0_tchalt(t0);
3368 rn = "TCHalt";
3369 break;
3370 case 5:
3371 check_insn(env, ctx, ASE_MT);
3372 gen_helper_mtc0_tccontext(t0);
3373 rn = "TCContext";
3374 break;
3375 case 6:
3376 check_insn(env, ctx, ASE_MT);
3377 gen_helper_mtc0_tcschedule(t0);
3378 rn = "TCSchedule";
3379 break;
3380 case 7:
3381 check_insn(env, ctx, ASE_MT);
3382 gen_helper_mtc0_tcschefback(t0);
3383 rn = "TCScheFBack";
3384 break;
3385 default:
3386 goto die;
3388 break;
3389 case 3:
3390 switch (sel) {
3391 case 0:
3392 gen_helper_mtc0_entrylo1(t0);
3393 rn = "EntryLo1";
3394 break;
3395 default:
3396 goto die;
3398 break;
3399 case 4:
3400 switch (sel) {
3401 case 0:
3402 gen_helper_mtc0_context(t0);
3403 rn = "Context";
3404 break;
3405 case 1:
3406 // gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
3407 rn = "ContextConfig";
3408 // break;
3409 default:
3410 goto die;
3412 break;
3413 case 5:
3414 switch (sel) {
3415 case 0:
3416 gen_helper_mtc0_pagemask(t0);
3417 rn = "PageMask";
3418 break;
3419 case 1:
3420 check_insn(env, ctx, ISA_MIPS32R2);
3421 gen_helper_mtc0_pagegrain(t0);
3422 rn = "PageGrain";
3423 break;
3424 default:
3425 goto die;
3427 break;
3428 case 6:
3429 switch (sel) {
3430 case 0:
3431 gen_helper_mtc0_wired(t0);
3432 rn = "Wired";
3433 break;
3434 case 1:
3435 check_insn(env, ctx, ISA_MIPS32R2);
3436 gen_helper_mtc0_srsconf0(t0);
3437 rn = "SRSConf0";
3438 break;
3439 case 2:
3440 check_insn(env, ctx, ISA_MIPS32R2);
3441 gen_helper_mtc0_srsconf1(t0);
3442 rn = "SRSConf1";
3443 break;
3444 case 3:
3445 check_insn(env, ctx, ISA_MIPS32R2);
3446 gen_helper_mtc0_srsconf2(t0);
3447 rn = "SRSConf2";
3448 break;
3449 case 4:
3450 check_insn(env, ctx, ISA_MIPS32R2);
3451 gen_helper_mtc0_srsconf3(t0);
3452 rn = "SRSConf3";
3453 break;
3454 case 5:
3455 check_insn(env, ctx, ISA_MIPS32R2);
3456 gen_helper_mtc0_srsconf4(t0);
3457 rn = "SRSConf4";
3458 break;
3459 default:
3460 goto die;
3462 break;
3463 case 7:
3464 switch (sel) {
3465 case 0:
3466 check_insn(env, ctx, ISA_MIPS32R2);
3467 gen_helper_mtc0_hwrena(t0);
3468 rn = "HWREna";
3469 break;
3470 default:
3471 goto die;
3473 break;
3474 case 8:
3475 /* ignored */
3476 rn = "BadVAddr";
3477 break;
3478 case 9:
3479 switch (sel) {
3480 case 0:
3481 gen_helper_mtc0_count(t0);
3482 rn = "Count";
3483 break;
3484 /* 6,7 are implementation dependent */
3485 default:
3486 goto die;
3488 /* Stop translation as we may have switched the execution mode */
3489 ctx->bstate = BS_STOP;
3490 break;
3491 case 10:
3492 switch (sel) {
3493 case 0:
3494 gen_helper_mtc0_entryhi(t0);
3495 rn = "EntryHi";
3496 break;
3497 default:
3498 goto die;
3500 break;
3501 case 11:
3502 switch (sel) {
3503 case 0:
3504 gen_helper_mtc0_compare(t0);
3505 rn = "Compare";
3506 break;
3507 /* 6,7 are implementation dependent */
3508 default:
3509 goto die;
3511 /* Stop translation as we may have switched the execution mode */
3512 ctx->bstate = BS_STOP;
3513 break;
3514 case 12:
3515 switch (sel) {
3516 case 0:
3517 gen_helper_mtc0_status(t0);
3518 /* BS_STOP isn't good enough here, hflags may have changed. */
3519 gen_save_pc(ctx->pc + 4);
3520 ctx->bstate = BS_EXCP;
3521 rn = "Status";
3522 break;
3523 case 1:
3524 check_insn(env, ctx, ISA_MIPS32R2);
3525 gen_helper_mtc0_intctl(t0);
3526 /* Stop translation as we may have switched the execution mode */
3527 ctx->bstate = BS_STOP;
3528 rn = "IntCtl";
3529 break;
3530 case 2:
3531 check_insn(env, ctx, ISA_MIPS32R2);
3532 gen_helper_mtc0_srsctl(t0);
3533 /* Stop translation as we may have switched the execution mode */
3534 ctx->bstate = BS_STOP;
3535 rn = "SRSCtl";
3536 break;
3537 case 3:
3538 check_insn(env, ctx, ISA_MIPS32R2);
3539 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
3540 /* Stop translation as we may have switched the execution mode */
3541 ctx->bstate = BS_STOP;
3542 rn = "SRSMap";
3543 break;
3544 default:
3545 goto die;
3547 break;
3548 case 13:
3549 switch (sel) {
3550 case 0:
3551 gen_helper_mtc0_cause(t0);
3552 rn = "Cause";
3553 break;
3554 default:
3555 goto die;
3557 /* Stop translation as we may have switched the execution mode */
3558 ctx->bstate = BS_STOP;
3559 break;
3560 case 14:
3561 switch (sel) {
3562 case 0:
3563 gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC));
3564 rn = "EPC";
3565 break;
3566 default:
3567 goto die;
3569 break;
3570 case 15:
3571 switch (sel) {
3572 case 0:
3573 /* ignored */
3574 rn = "PRid";
3575 break;
3576 case 1:
3577 check_insn(env, ctx, ISA_MIPS32R2);
3578 gen_helper_mtc0_ebase(t0);
3579 rn = "EBase";
3580 break;
3581 default:
3582 goto die;
3584 break;
3585 case 16:
3586 switch (sel) {
3587 case 0:
3588 gen_helper_mtc0_config0(t0);
3589 rn = "Config";
3590 /* Stop translation as we may have switched the execution mode */
3591 ctx->bstate = BS_STOP;
3592 break;
3593 case 1:
3594 /* ignored, read only */
3595 rn = "Config1";
3596 break;
3597 case 2:
3598 gen_helper_mtc0_config2(t0);
3599 rn = "Config2";
3600 /* Stop translation as we may have switched the execution mode */
3601 ctx->bstate = BS_STOP;
3602 break;
3603 case 3:
3604 /* ignored, read only */
3605 rn = "Config3";
3606 break;
3607 /* 4,5 are reserved */
3608 /* 6,7 are implementation dependent */
3609 case 6:
3610 /* ignored */
3611 rn = "Config6";
3612 break;
3613 case 7:
3614 /* ignored */
3615 rn = "Config7";
3616 break;
3617 default:
3618 rn = "Invalid config selector";
3619 goto die;
3621 break;
3622 case 17:
3623 switch (sel) {
3624 case 0:
3625 /* ignored */
3626 rn = "LLAddr";
3627 break;
3628 default:
3629 goto die;
3631 break;
3632 case 18:
3633 switch (sel) {
3634 case 0 ... 7:
3635 gen_helper_1i(mtc0_watchlo, t0, sel);
3636 rn = "WatchLo";
3637 break;
3638 default:
3639 goto die;
3641 break;
3642 case 19:
3643 switch (sel) {
3644 case 0 ... 7:
3645 gen_helper_1i(mtc0_watchhi, t0, sel);
3646 rn = "WatchHi";
3647 break;
3648 default:
3649 goto die;
3651 break;
3652 case 20:
3653 switch (sel) {
3654 case 0:
3655 #if defined(TARGET_MIPS64)
3656 check_insn(env, ctx, ISA_MIPS3);
3657 gen_helper_mtc0_xcontext(t0);
3658 rn = "XContext";
3659 break;
3660 #endif
3661 default:
3662 goto die;
3664 break;
3665 case 21:
3666 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3667 switch (sel) {
3668 case 0:
3669 gen_helper_mtc0_framemask(t0);
3670 rn = "Framemask";
3671 break;
3672 default:
3673 goto die;
3675 break;
3676 case 22:
3677 /* ignored */
3678 rn = "Diagnostic"; /* implementation dependent */
3679 break;
3680 case 23:
3681 switch (sel) {
3682 case 0:
3683 gen_helper_mtc0_debug(t0); /* EJTAG support */
3684 /* BS_STOP isn't good enough here, hflags may have changed. */
3685 gen_save_pc(ctx->pc + 4);
3686 ctx->bstate = BS_EXCP;
3687 rn = "Debug";
3688 break;
3689 case 1:
3690 // gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
3691 rn = "TraceControl";
3692 /* Stop translation as we may have switched the execution mode */
3693 ctx->bstate = BS_STOP;
3694 // break;
3695 case 2:
3696 // gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
3697 rn = "TraceControl2";
3698 /* Stop translation as we may have switched the execution mode */
3699 ctx->bstate = BS_STOP;
3700 // break;
3701 case 3:
3702 /* Stop translation as we may have switched the execution mode */
3703 ctx->bstate = BS_STOP;
3704 // gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
3705 rn = "UserTraceData";
3706 /* Stop translation as we may have switched the execution mode */
3707 ctx->bstate = BS_STOP;
3708 // break;
3709 case 4:
3710 // gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
3711 /* Stop translation as we may have switched the execution mode */
3712 ctx->bstate = BS_STOP;
3713 rn = "TraceBPC";
3714 // break;
3715 default:
3716 goto die;
3718 break;
3719 case 24:
3720 switch (sel) {
3721 case 0:
3722 /* EJTAG support */
3723 gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC));
3724 rn = "DEPC";
3725 break;
3726 default:
3727 goto die;
3729 break;
3730 case 25:
3731 switch (sel) {
3732 case 0:
3733 gen_helper_mtc0_performance0(t0);
3734 rn = "Performance0";
3735 break;
3736 case 1:
3737 // gen_helper_mtc0_performance1(t0);
3738 rn = "Performance1";
3739 // break;
3740 case 2:
3741 // gen_helper_mtc0_performance2(t0);
3742 rn = "Performance2";
3743 // break;
3744 case 3:
3745 // gen_helper_mtc0_performance3(t0);
3746 rn = "Performance3";
3747 // break;
3748 case 4:
3749 // gen_helper_mtc0_performance4(t0);
3750 rn = "Performance4";
3751 // break;
3752 case 5:
3753 // gen_helper_mtc0_performance5(t0);
3754 rn = "Performance5";
3755 // break;
3756 case 6:
3757 // gen_helper_mtc0_performance6(t0);
3758 rn = "Performance6";
3759 // break;
3760 case 7:
3761 // gen_helper_mtc0_performance7(t0);
3762 rn = "Performance7";
3763 // break;
3764 default:
3765 goto die;
3767 break;
3768 case 26:
3769 /* ignored */
3770 rn = "ECC";
3771 break;
3772 case 27:
3773 switch (sel) {
3774 case 0 ... 3:
3775 /* ignored */
3776 rn = "CacheErr";
3777 break;
3778 default:
3779 goto die;
3781 break;
3782 case 28:
3783 switch (sel) {
3784 case 0:
3785 case 2:
3786 case 4:
3787 case 6:
3788 gen_helper_mtc0_taglo(t0);
3789 rn = "TagLo";
3790 break;
3791 case 1:
3792 case 3:
3793 case 5:
3794 case 7:
3795 gen_helper_mtc0_datalo(t0);
3796 rn = "DataLo";
3797 break;
3798 default:
3799 goto die;
3801 break;
3802 case 29:
3803 switch (sel) {
3804 case 0:
3805 case 2:
3806 case 4:
3807 case 6:
3808 gen_helper_mtc0_taghi(t0);
3809 rn = "TagHi";
3810 break;
3811 case 1:
3812 case 3:
3813 case 5:
3814 case 7:
3815 gen_helper_mtc0_datahi(t0);
3816 rn = "DataHi";
3817 break;
3818 default:
3819 rn = "invalid sel";
3820 goto die;
3822 break;
3823 case 30:
3824 switch (sel) {
3825 case 0:
3826 gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC));
3827 rn = "ErrorEPC";
3828 break;
3829 default:
3830 goto die;
3832 break;
3833 case 31:
3834 switch (sel) {
3835 case 0:
3836 /* EJTAG support */
3837 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
3838 rn = "DESAVE";
3839 break;
3840 default:
3841 goto die;
3843 /* Stop translation as we may have switched the execution mode */
3844 ctx->bstate = BS_STOP;
3845 break;
3846 default:
3847 goto die;
3849 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
3850 /* For simplicity assume that all writes can cause interrupts. */
3851 if (use_icount) {
3852 gen_io_end();
3853 ctx->bstate = BS_STOP;
3855 return;
3857 die:
3858 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
3859 generate_exception(ctx, EXCP_RI);
3862 #if defined(TARGET_MIPS64)
3863 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
3865 const char *rn = "invalid";
3867 if (sel != 0)
3868 check_insn(env, ctx, ISA_MIPS64);
3870 switch (reg) {
3871 case 0:
3872 switch (sel) {
3873 case 0:
3874 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
3875 rn = "Index";
3876 break;
3877 case 1:
3878 check_insn(env, ctx, ASE_MT);
3879 gen_helper_mfc0_mvpcontrol(t0);
3880 rn = "MVPControl";
3881 break;
3882 case 2:
3883 check_insn(env, ctx, ASE_MT);
3884 gen_helper_mfc0_mvpconf0(t0);
3885 rn = "MVPConf0";
3886 break;
3887 case 3:
3888 check_insn(env, ctx, ASE_MT);
3889 gen_helper_mfc0_mvpconf1(t0);
3890 rn = "MVPConf1";
3891 break;
3892 default:
3893 goto die;
3895 break;
3896 case 1:
3897 switch (sel) {
3898 case 0:
3899 gen_helper_mfc0_random(t0);
3900 rn = "Random";
3901 break;
3902 case 1:
3903 check_insn(env, ctx, ASE_MT);
3904 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
3905 rn = "VPEControl";
3906 break;
3907 case 2:
3908 check_insn(env, ctx, ASE_MT);
3909 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
3910 rn = "VPEConf0";
3911 break;
3912 case 3:
3913 check_insn(env, ctx, ASE_MT);
3914 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
3915 rn = "VPEConf1";
3916 break;
3917 case 4:
3918 check_insn(env, ctx, ASE_MT);
3919 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask));
3920 rn = "YQMask";
3921 break;
3922 case 5:
3923 check_insn(env, ctx, ASE_MT);
3924 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
3925 rn = "VPESchedule";
3926 break;
3927 case 6:
3928 check_insn(env, ctx, ASE_MT);
3929 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
3930 rn = "VPEScheFBack";
3931 break;
3932 case 7:
3933 check_insn(env, ctx, ASE_MT);
3934 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
3935 rn = "VPEOpt";
3936 break;
3937 default:
3938 goto die;
3940 break;
3941 case 2:
3942 switch (sel) {
3943 case 0:
3944 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
3945 rn = "EntryLo0";
3946 break;
3947 case 1:
3948 check_insn(env, ctx, ASE_MT);
3949 gen_helper_mfc0_tcstatus(t0);
3950 rn = "TCStatus";
3951 break;
3952 case 2:
3953 check_insn(env, ctx, ASE_MT);
3954 gen_helper_mfc0_tcbind(t0);
3955 rn = "TCBind";
3956 break;
3957 case 3:
3958 check_insn(env, ctx, ASE_MT);
3959 gen_helper_dmfc0_tcrestart(t0);
3960 rn = "TCRestart";
3961 break;
3962 case 4:
3963 check_insn(env, ctx, ASE_MT);
3964 gen_helper_dmfc0_tchalt(t0);
3965 rn = "TCHalt";
3966 break;
3967 case 5:
3968 check_insn(env, ctx, ASE_MT);
3969 gen_helper_dmfc0_tccontext(t0);
3970 rn = "TCContext";
3971 break;
3972 case 6:
3973 check_insn(env, ctx, ASE_MT);
3974 gen_helper_dmfc0_tcschedule(t0);
3975 rn = "TCSchedule";
3976 break;
3977 case 7:
3978 check_insn(env, ctx, ASE_MT);
3979 gen_helper_dmfc0_tcschefback(t0);
3980 rn = "TCScheFBack";
3981 break;
3982 default:
3983 goto die;
3985 break;
3986 case 3:
3987 switch (sel) {
3988 case 0:
3989 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
3990 rn = "EntryLo1";
3991 break;
3992 default:
3993 goto die;
3995 break;
3996 case 4:
3997 switch (sel) {
3998 case 0:
3999 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
4000 rn = "Context";
4001 break;
4002 case 1:
4003 // gen_helper_dmfc0_contextconfig(t0); /* SmartMIPS ASE */
4004 rn = "ContextConfig";
4005 // break;
4006 default:
4007 goto die;
4009 break;
4010 case 5:
4011 switch (sel) {
4012 case 0:
4013 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
4014 rn = "PageMask";
4015 break;
4016 case 1:
4017 check_insn(env, ctx, ISA_MIPS32R2);
4018 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
4019 rn = "PageGrain";
4020 break;
4021 default:
4022 goto die;
4024 break;
4025 case 6:
4026 switch (sel) {
4027 case 0:
4028 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
4029 rn = "Wired";
4030 break;
4031 case 1:
4032 check_insn(env, ctx, ISA_MIPS32R2);
4033 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
4034 rn = "SRSConf0";
4035 break;
4036 case 2:
4037 check_insn(env, ctx, ISA_MIPS32R2);
4038 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
4039 rn = "SRSConf1";
4040 break;
4041 case 3:
4042 check_insn(env, ctx, ISA_MIPS32R2);
4043 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
4044 rn = "SRSConf2";
4045 break;
4046 case 4:
4047 check_insn(env, ctx, ISA_MIPS32R2);
4048 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
4049 rn = "SRSConf3";
4050 break;
4051 case 5:
4052 check_insn(env, ctx, ISA_MIPS32R2);
4053 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
4054 rn = "SRSConf4";
4055 break;
4056 default:
4057 goto die;
4059 break;
4060 case 7:
4061 switch (sel) {
4062 case 0:
4063 check_insn(env, ctx, ISA_MIPS32R2);
4064 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
4065 rn = "HWREna";
4066 break;
4067 default:
4068 goto die;
4070 break;
4071 case 8:
4072 switch (sel) {
4073 case 0:
4074 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4075 rn = "BadVAddr";
4076 break;
4077 default:
4078 goto die;
4080 break;
4081 case 9:
4082 switch (sel) {
4083 case 0:
4084 /* Mark as an IO operation because we read the time. */
4085 if (use_icount)
4086 gen_io_start();
4087 gen_helper_mfc0_count(t0);
4088 if (use_icount) {
4089 gen_io_end();
4090 ctx->bstate = BS_STOP;
4092 rn = "Count";
4093 break;
4094 /* 6,7 are implementation dependent */
4095 default:
4096 goto die;
4098 break;
4099 case 10:
4100 switch (sel) {
4101 case 0:
4102 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
4103 rn = "EntryHi";
4104 break;
4105 default:
4106 goto die;
4108 break;
4109 case 11:
4110 switch (sel) {
4111 case 0:
4112 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
4113 rn = "Compare";
4114 break;
4115 /* 6,7 are implementation dependent */
4116 default:
4117 goto die;
4119 break;
4120 case 12:
4121 switch (sel) {
4122 case 0:
4123 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
4124 rn = "Status";
4125 break;
4126 case 1:
4127 check_insn(env, ctx, ISA_MIPS32R2);
4128 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
4129 rn = "IntCtl";
4130 break;
4131 case 2:
4132 check_insn(env, ctx, ISA_MIPS32R2);
4133 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
4134 rn = "SRSCtl";
4135 break;
4136 case 3:
4137 check_insn(env, ctx, ISA_MIPS32R2);
4138 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
4139 rn = "SRSMap";
4140 break;
4141 default:
4142 goto die;
4144 break;
4145 case 13:
4146 switch (sel) {
4147 case 0:
4148 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
4149 rn = "Cause";
4150 break;
4151 default:
4152 goto die;
4154 break;
4155 case 14:
4156 switch (sel) {
4157 case 0:
4158 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4159 rn = "EPC";
4160 break;
4161 default:
4162 goto die;
4164 break;
4165 case 15:
4166 switch (sel) {
4167 case 0:
4168 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
4169 rn = "PRid";
4170 break;
4171 case 1:
4172 check_insn(env, ctx, ISA_MIPS32R2);
4173 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
4174 rn = "EBase";
4175 break;
4176 default:
4177 goto die;
4179 break;
4180 case 16:
4181 switch (sel) {
4182 case 0:
4183 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
4184 rn = "Config";
4185 break;
4186 case 1:
4187 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
4188 rn = "Config1";
4189 break;
4190 case 2:
4191 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
4192 rn = "Config2";
4193 break;
4194 case 3:
4195 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
4196 rn = "Config3";
4197 break;
4198 /* 6,7 are implementation dependent */
4199 case 6:
4200 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
4201 rn = "Config6";
4202 break;
4203 case 7:
4204 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
4205 rn = "Config7";
4206 break;
4207 default:
4208 goto die;
4210 break;
4211 case 17:
4212 switch (sel) {
4213 case 0:
4214 gen_helper_dmfc0_lladdr(t0);
4215 rn = "LLAddr";
4216 break;
4217 default:
4218 goto die;
4220 break;
4221 case 18:
4222 switch (sel) {
4223 case 0 ... 7:
4224 gen_helper_1i(dmfc0_watchlo, t0, sel);
4225 rn = "WatchLo";
4226 break;
4227 default:
4228 goto die;
4230 break;
4231 case 19:
4232 switch (sel) {
4233 case 0 ... 7:
4234 gen_helper_1i(mfc0_watchhi, t0, sel);
4235 rn = "WatchHi";
4236 break;
4237 default:
4238 goto die;
4240 break;
4241 case 20:
4242 switch (sel) {
4243 case 0:
4244 check_insn(env, ctx, ISA_MIPS3);
4245 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
4246 rn = "XContext";
4247 break;
4248 default:
4249 goto die;
4251 break;
4252 case 21:
4253 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4254 switch (sel) {
4255 case 0:
4256 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
4257 rn = "Framemask";
4258 break;
4259 default:
4260 goto die;
4262 break;
4263 case 22:
4264 tcg_gen_movi_tl(t0, 0); /* unimplemented */
4265 rn = "'Diagnostic"; /* implementation dependent */
4266 break;
4267 case 23:
4268 switch (sel) {
4269 case 0:
4270 gen_helper_mfc0_debug(t0); /* EJTAG support */
4271 rn = "Debug";
4272 break;
4273 case 1:
4274 // gen_helper_dmfc0_tracecontrol(t0); /* PDtrace support */
4275 rn = "TraceControl";
4276 // break;
4277 case 2:
4278 // gen_helper_dmfc0_tracecontrol2(t0); /* PDtrace support */
4279 rn = "TraceControl2";
4280 // break;
4281 case 3:
4282 // gen_helper_dmfc0_usertracedata(t0); /* PDtrace support */
4283 rn = "UserTraceData";
4284 // break;
4285 case 4:
4286 // gen_helper_dmfc0_tracebpc(t0); /* PDtrace support */
4287 rn = "TraceBPC";
4288 // break;
4289 default:
4290 goto die;
4292 break;
4293 case 24:
4294 switch (sel) {
4295 case 0:
4296 /* EJTAG support */
4297 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
4298 rn = "DEPC";
4299 break;
4300 default:
4301 goto die;
4303 break;
4304 case 25:
4305 switch (sel) {
4306 case 0:
4307 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
4308 rn = "Performance0";
4309 break;
4310 case 1:
4311 // gen_helper_dmfc0_performance1(t0);
4312 rn = "Performance1";
4313 // break;
4314 case 2:
4315 // gen_helper_dmfc0_performance2(t0);
4316 rn = "Performance2";
4317 // break;
4318 case 3:
4319 // gen_helper_dmfc0_performance3(t0);
4320 rn = "Performance3";
4321 // break;
4322 case 4:
4323 // gen_helper_dmfc0_performance4(t0);
4324 rn = "Performance4";
4325 // break;
4326 case 5:
4327 // gen_helper_dmfc0_performance5(t0);
4328 rn = "Performance5";
4329 // break;
4330 case 6:
4331 // gen_helper_dmfc0_performance6(t0);
4332 rn = "Performance6";
4333 // break;
4334 case 7:
4335 // gen_helper_dmfc0_performance7(t0);
4336 rn = "Performance7";
4337 // break;
4338 default:
4339 goto die;
4341 break;
4342 case 26:
4343 tcg_gen_movi_tl(t0, 0); /* unimplemented */
4344 rn = "ECC";
4345 break;
4346 case 27:
4347 switch (sel) {
4348 /* ignored */
4349 case 0 ... 3:
4350 tcg_gen_movi_tl(t0, 0); /* unimplemented */
4351 rn = "CacheErr";
4352 break;
4353 default:
4354 goto die;
4356 break;
4357 case 28:
4358 switch (sel) {
4359 case 0:
4360 case 2:
4361 case 4:
4362 case 6:
4363 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
4364 rn = "TagLo";
4365 break;
4366 case 1:
4367 case 3:
4368 case 5:
4369 case 7:
4370 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
4371 rn = "DataLo";
4372 break;
4373 default:
4374 goto die;
4376 break;
4377 case 29:
4378 switch (sel) {
4379 case 0:
4380 case 2:
4381 case 4:
4382 case 6:
4383 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
4384 rn = "TagHi";
4385 break;
4386 case 1:
4387 case 3:
4388 case 5:
4389 case 7:
4390 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
4391 rn = "DataHi";
4392 break;
4393 default:
4394 goto die;
4396 break;
4397 case 30:
4398 switch (sel) {
4399 case 0:
4400 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4401 rn = "ErrorEPC";
4402 break;
4403 default:
4404 goto die;
4406 break;
4407 case 31:
4408 switch (sel) {
4409 case 0:
4410 /* EJTAG support */
4411 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
4412 rn = "DESAVE";
4413 break;
4414 default:
4415 goto die;
4417 break;
4418 default:
4419 goto die;
4421 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4422 return;
4424 die:
4425 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4426 generate_exception(ctx, EXCP_RI);
4429 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
4431 const char *rn = "invalid";
4433 if (sel != 0)
4434 check_insn(env, ctx, ISA_MIPS64);
4436 if (use_icount)
4437 gen_io_start();
4439 switch (reg) {
4440 case 0:
4441 switch (sel) {
4442 case 0:
4443 gen_helper_mtc0_index(t0);
4444 rn = "Index";
4445 break;
4446 case 1:
4447 check_insn(env, ctx, ASE_MT);
4448 gen_helper_mtc0_mvpcontrol(t0);
4449 rn = "MVPControl";
4450 break;
4451 case 2:
4452 check_insn(env, ctx, ASE_MT);
4453 /* ignored */
4454 rn = "MVPConf0";
4455 break;
4456 case 3:
4457 check_insn(env, ctx, ASE_MT);
4458 /* ignored */
4459 rn = "MVPConf1";
4460 break;
4461 default:
4462 goto die;
4464 break;
4465 case 1:
4466 switch (sel) {
4467 case 0:
4468 /* ignored */
4469 rn = "Random";
4470 break;
4471 case 1:
4472 check_insn(env, ctx, ASE_MT);
4473 gen_helper_mtc0_vpecontrol(t0);
4474 rn = "VPEControl";
4475 break;
4476 case 2:
4477 check_insn(env, ctx, ASE_MT);
4478 gen_helper_mtc0_vpeconf0(t0);
4479 rn = "VPEConf0";
4480 break;
4481 case 3:
4482 check_insn(env, ctx, ASE_MT);
4483 gen_helper_mtc0_vpeconf1(t0);
4484 rn = "VPEConf1";
4485 break;
4486 case 4:
4487 check_insn(env, ctx, ASE_MT);
4488 gen_helper_mtc0_yqmask(t0);
4489 rn = "YQMask";
4490 break;
4491 case 5:
4492 check_insn(env, ctx, ASE_MT);
4493 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4494 rn = "VPESchedule";
4495 break;
4496 case 6:
4497 check_insn(env, ctx, ASE_MT);
4498 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4499 rn = "VPEScheFBack";
4500 break;
4501 case 7:
4502 check_insn(env, ctx, ASE_MT);
4503 gen_helper_mtc0_vpeopt(t0);
4504 rn = "VPEOpt";
4505 break;
4506 default:
4507 goto die;
4509 break;
4510 case 2:
4511 switch (sel) {
4512 case 0:
4513 gen_helper_mtc0_entrylo0(t0);
4514 rn = "EntryLo0";
4515 break;
4516 case 1:
4517 check_insn(env, ctx, ASE_MT);
4518 gen_helper_mtc0_tcstatus(t0);
4519 rn = "TCStatus";
4520 break;
4521 case 2:
4522 check_insn(env, ctx, ASE_MT);
4523 gen_helper_mtc0_tcbind(t0);
4524 rn = "TCBind";
4525 break;
4526 case 3:
4527 check_insn(env, ctx, ASE_MT);
4528 gen_helper_mtc0_tcrestart(t0);
4529 rn = "TCRestart";
4530 break;
4531 case 4:
4532 check_insn(env, ctx, ASE_MT);
4533 gen_helper_mtc0_tchalt(t0);
4534 rn = "TCHalt";
4535 break;
4536 case 5:
4537 check_insn(env, ctx, ASE_MT);
4538 gen_helper_mtc0_tccontext(t0);
4539 rn = "TCContext";
4540 break;
4541 case 6:
4542 check_insn(env, ctx, ASE_MT);
4543 gen_helper_mtc0_tcschedule(t0);
4544 rn = "TCSchedule";
4545 break;
4546 case 7:
4547 check_insn(env, ctx, ASE_MT);
4548 gen_helper_mtc0_tcschefback(t0);
4549 rn = "TCScheFBack";
4550 break;
4551 default:
4552 goto die;
4554 break;
4555 case 3:
4556 switch (sel) {
4557 case 0:
4558 gen_helper_mtc0_entrylo1(t0);
4559 rn = "EntryLo1";
4560 break;
4561 default:
4562 goto die;
4564 break;
4565 case 4:
4566 switch (sel) {
4567 case 0:
4568 gen_helper_mtc0_context(t0);
4569 rn = "Context";
4570 break;
4571 case 1:
4572 // gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
4573 rn = "ContextConfig";
4574 // break;
4575 default:
4576 goto die;
4578 break;
4579 case 5:
4580 switch (sel) {
4581 case 0:
4582 gen_helper_mtc0_pagemask(t0);
4583 rn = "PageMask";
4584 break;
4585 case 1:
4586 check_insn(env, ctx, ISA_MIPS32R2);
4587 gen_helper_mtc0_pagegrain(t0);
4588 rn = "PageGrain";
4589 break;
4590 default:
4591 goto die;
4593 break;
4594 case 6:
4595 switch (sel) {
4596 case 0:
4597 gen_helper_mtc0_wired(t0);
4598 rn = "Wired";
4599 break;
4600 case 1:
4601 check_insn(env, ctx, ISA_MIPS32R2);
4602 gen_helper_mtc0_srsconf0(t0);
4603 rn = "SRSConf0";
4604 break;
4605 case 2:
4606 check_insn(env, ctx, ISA_MIPS32R2);
4607 gen_helper_mtc0_srsconf1(t0);
4608 rn = "SRSConf1";
4609 break;
4610 case 3:
4611 check_insn(env, ctx, ISA_MIPS32R2);
4612 gen_helper_mtc0_srsconf2(t0);
4613 rn = "SRSConf2";
4614 break;
4615 case 4:
4616 check_insn(env, ctx, ISA_MIPS32R2);
4617 gen_helper_mtc0_srsconf3(t0);
4618 rn = "SRSConf3";
4619 break;
4620 case 5:
4621 check_insn(env, ctx, ISA_MIPS32R2);
4622 gen_helper_mtc0_srsconf4(t0);
4623 rn = "SRSConf4";
4624 break;
4625 default:
4626 goto die;
4628 break;
4629 case 7:
4630 switch (sel) {
4631 case 0:
4632 check_insn(env, ctx, ISA_MIPS32R2);
4633 gen_helper_mtc0_hwrena(t0);
4634 rn = "HWREna";
4635 break;
4636 default:
4637 goto die;
4639 break;
4640 case 8:
4641 /* ignored */
4642 rn = "BadVAddr";
4643 break;
4644 case 9:
4645 switch (sel) {
4646 case 0:
4647 gen_helper_mtc0_count(t0);
4648 rn = "Count";
4649 break;
4650 /* 6,7 are implementation dependent */
4651 default:
4652 goto die;
4654 /* Stop translation as we may have switched the execution mode */
4655 ctx->bstate = BS_STOP;
4656 break;
4657 case 10:
4658 switch (sel) {
4659 case 0:
4660 gen_helper_mtc0_entryhi(t0);
4661 rn = "EntryHi";
4662 break;
4663 default:
4664 goto die;
4666 break;
4667 case 11:
4668 switch (sel) {
4669 case 0:
4670 gen_helper_mtc0_compare(t0);
4671 rn = "Compare";
4672 break;
4673 /* 6,7 are implementation dependent */
4674 default:
4675 goto die;
4677 /* Stop translation as we may have switched the execution mode */
4678 ctx->bstate = BS_STOP;
4679 break;
4680 case 12:
4681 switch (sel) {
4682 case 0:
4683 gen_helper_mtc0_status(t0);
4684 /* BS_STOP isn't good enough here, hflags may have changed. */
4685 gen_save_pc(ctx->pc + 4);
4686 ctx->bstate = BS_EXCP;
4687 rn = "Status";
4688 break;
4689 case 1:
4690 check_insn(env, ctx, ISA_MIPS32R2);
4691 gen_helper_mtc0_intctl(t0);
4692 /* Stop translation as we may have switched the execution mode */
4693 ctx->bstate = BS_STOP;
4694 rn = "IntCtl";
4695 break;
4696 case 2:
4697 check_insn(env, ctx, ISA_MIPS32R2);
4698 gen_helper_mtc0_srsctl(t0);
4699 /* Stop translation as we may have switched the execution mode */
4700 ctx->bstate = BS_STOP;
4701 rn = "SRSCtl";
4702 break;
4703 case 3:
4704 check_insn(env, ctx, ISA_MIPS32R2);
4705 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
4706 /* Stop translation as we may have switched the execution mode */
4707 ctx->bstate = BS_STOP;
4708 rn = "SRSMap";
4709 break;
4710 default:
4711 goto die;
4713 break;
4714 case 13:
4715 switch (sel) {
4716 case 0:
4717 gen_helper_mtc0_cause(t0);
4718 rn = "Cause";
4719 break;
4720 default:
4721 goto die;
4723 /* Stop translation as we may have switched the execution mode */
4724 ctx->bstate = BS_STOP;
4725 break;
4726 case 14:
4727 switch (sel) {
4728 case 0:
4729 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4730 rn = "EPC";
4731 break;
4732 default:
4733 goto die;
4735 break;
4736 case 15:
4737 switch (sel) {
4738 case 0:
4739 /* ignored */
4740 rn = "PRid";
4741 break;
4742 case 1:
4743 check_insn(env, ctx, ISA_MIPS32R2);
4744 gen_helper_mtc0_ebase(t0);
4745 rn = "EBase";
4746 break;
4747 default:
4748 goto die;
4750 break;
4751 case 16:
4752 switch (sel) {
4753 case 0:
4754 gen_helper_mtc0_config0(t0);
4755 rn = "Config";
4756 /* Stop translation as we may have switched the execution mode */
4757 ctx->bstate = BS_STOP;
4758 break;
4759 case 1:
4760 /* ignored */
4761 rn = "Config1";
4762 break;
4763 case 2:
4764 gen_helper_mtc0_config2(t0);
4765 rn = "Config2";
4766 /* Stop translation as we may have switched the execution mode */
4767 ctx->bstate = BS_STOP;
4768 break;
4769 case 3:
4770 /* ignored */
4771 rn = "Config3";
4772 break;
4773 /* 6,7 are implementation dependent */
4774 default:
4775 rn = "Invalid config selector";
4776 goto die;
4778 break;
4779 case 17:
4780 switch (sel) {
4781 case 0:
4782 /* ignored */
4783 rn = "LLAddr";
4784 break;
4785 default:
4786 goto die;
4788 break;
4789 case 18:
4790 switch (sel) {
4791 case 0 ... 7:
4792 gen_helper_1i(mtc0_watchlo, t0, sel);
4793 rn = "WatchLo";
4794 break;
4795 default:
4796 goto die;
4798 break;
4799 case 19:
4800 switch (sel) {
4801 case 0 ... 7:
4802 gen_helper_1i(mtc0_watchhi, t0, sel);
4803 rn = "WatchHi";
4804 break;
4805 default:
4806 goto die;
4808 break;
4809 case 20:
4810 switch (sel) {
4811 case 0:
4812 check_insn(env, ctx, ISA_MIPS3);
4813 gen_helper_mtc0_xcontext(t0);
4814 rn = "XContext";
4815 break;
4816 default:
4817 goto die;
4819 break;
4820 case 21:
4821 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4822 switch (sel) {
4823 case 0:
4824 gen_helper_mtc0_framemask(t0);
4825 rn = "Framemask";
4826 break;
4827 default:
4828 goto die;
4830 break;
4831 case 22:
4832 /* ignored */
4833 rn = "Diagnostic"; /* implementation dependent */
4834 break;
4835 case 23:
4836 switch (sel) {
4837 case 0:
4838 gen_helper_mtc0_debug(t0); /* EJTAG support */
4839 /* BS_STOP isn't good enough here, hflags may have changed. */
4840 gen_save_pc(ctx->pc + 4);
4841 ctx->bstate = BS_EXCP;
4842 rn = "Debug";
4843 break;
4844 case 1:
4845 // gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
4846 /* Stop translation as we may have switched the execution mode */
4847 ctx->bstate = BS_STOP;
4848 rn = "TraceControl";
4849 // break;
4850 case 2:
4851 // gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
4852 /* Stop translation as we may have switched the execution mode */
4853 ctx->bstate = BS_STOP;
4854 rn = "TraceControl2";
4855 // break;
4856 case 3:
4857 // gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
4858 /* Stop translation as we may have switched the execution mode */
4859 ctx->bstate = BS_STOP;
4860 rn = "UserTraceData";
4861 // break;
4862 case 4:
4863 // gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
4864 /* Stop translation as we may have switched the execution mode */
4865 ctx->bstate = BS_STOP;
4866 rn = "TraceBPC";
4867 // break;
4868 default:
4869 goto die;
4871 break;
4872 case 24:
4873 switch (sel) {
4874 case 0:
4875 /* EJTAG support */
4876 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
4877 rn = "DEPC";
4878 break;
4879 default:
4880 goto die;
4882 break;
4883 case 25:
4884 switch (sel) {
4885 case 0:
4886 gen_helper_mtc0_performance0(t0);
4887 rn = "Performance0";
4888 break;
4889 case 1:
4890 // gen_helper_mtc0_performance1(t0);
4891 rn = "Performance1";
4892 // break;
4893 case 2:
4894 // gen_helper_mtc0_performance2(t0);
4895 rn = "Performance2";
4896 // break;
4897 case 3:
4898 // gen_helper_mtc0_performance3(t0);
4899 rn = "Performance3";
4900 // break;
4901 case 4:
4902 // gen_helper_mtc0_performance4(t0);
4903 rn = "Performance4";
4904 // break;
4905 case 5:
4906 // gen_helper_mtc0_performance5(t0);
4907 rn = "Performance5";
4908 // break;
4909 case 6:
4910 // gen_helper_mtc0_performance6(t0);
4911 rn = "Performance6";
4912 // break;
4913 case 7:
4914 // gen_helper_mtc0_performance7(t0);
4915 rn = "Performance7";
4916 // break;
4917 default:
4918 goto die;
4920 break;
4921 case 26:
4922 /* ignored */
4923 rn = "ECC";
4924 break;
4925 case 27:
4926 switch (sel) {
4927 case 0 ... 3:
4928 /* ignored */
4929 rn = "CacheErr";
4930 break;
4931 default:
4932 goto die;
4934 break;
4935 case 28:
4936 switch (sel) {
4937 case 0:
4938 case 2:
4939 case 4:
4940 case 6:
4941 gen_helper_mtc0_taglo(t0);
4942 rn = "TagLo";
4943 break;
4944 case 1:
4945 case 3:
4946 case 5:
4947 case 7:
4948 gen_helper_mtc0_datalo(t0);
4949 rn = "DataLo";
4950 break;
4951 default:
4952 goto die;
4954 break;
4955 case 29:
4956 switch (sel) {
4957 case 0:
4958 case 2:
4959 case 4:
4960 case 6:
4961 gen_helper_mtc0_taghi(t0);
4962 rn = "TagHi";
4963 break;
4964 case 1:
4965 case 3:
4966 case 5:
4967 case 7:
4968 gen_helper_mtc0_datahi(t0);
4969 rn = "DataHi";
4970 break;
4971 default:
4972 rn = "invalid sel";
4973 goto die;
4975 break;
4976 case 30:
4977 switch (sel) {
4978 case 0:
4979 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4980 rn = "ErrorEPC";
4981 break;
4982 default:
4983 goto die;
4985 break;
4986 case 31:
4987 switch (sel) {
4988 case 0:
4989 /* EJTAG support */
4990 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
4991 rn = "DESAVE";
4992 break;
4993 default:
4994 goto die;
4996 /* Stop translation as we may have switched the execution mode */
4997 ctx->bstate = BS_STOP;
4998 break;
4999 default:
5000 goto die;
5002 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5003 /* For simplicity assume that all writes can cause interrupts. */
5004 if (use_icount) {
5005 gen_io_end();
5006 ctx->bstate = BS_STOP;
5008 return;
5010 die:
5011 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5012 generate_exception(ctx, EXCP_RI);
5014 #endif /* TARGET_MIPS64 */
5016 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5017 int u, int sel, int h)
5019 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5020 TCGv t0 = tcg_temp_local_new();
5022 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5023 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5024 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5025 tcg_gen_movi_tl(t0, -1);
5026 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5027 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5028 tcg_gen_movi_tl(t0, -1);
5029 else if (u == 0) {
5030 switch (rt) {
5031 case 2:
5032 switch (sel) {
5033 case 1:
5034 gen_helper_mftc0_tcstatus(t0);
5035 break;
5036 case 2:
5037 gen_helper_mftc0_tcbind(t0);
5038 break;
5039 case 3:
5040 gen_helper_mftc0_tcrestart(t0);
5041 break;
5042 case 4:
5043 gen_helper_mftc0_tchalt(t0);
5044 break;
5045 case 5:
5046 gen_helper_mftc0_tccontext(t0);
5047 break;
5048 case 6:
5049 gen_helper_mftc0_tcschedule(t0);
5050 break;
5051 case 7:
5052 gen_helper_mftc0_tcschefback(t0);
5053 break;
5054 default:
5055 gen_mfc0(env, ctx, t0, rt, sel);
5056 break;
5058 break;
5059 case 10:
5060 switch (sel) {
5061 case 0:
5062 gen_helper_mftc0_entryhi(t0);
5063 break;
5064 default:
5065 gen_mfc0(env, ctx, t0, rt, sel);
5066 break;
5068 case 12:
5069 switch (sel) {
5070 case 0:
5071 gen_helper_mftc0_status(t0);
5072 break;
5073 default:
5074 gen_mfc0(env, ctx, t0, rt, sel);
5075 break;
5077 case 23:
5078 switch (sel) {
5079 case 0:
5080 gen_helper_mftc0_debug(t0);
5081 break;
5082 default:
5083 gen_mfc0(env, ctx, t0, rt, sel);
5084 break;
5086 break;
5087 default:
5088 gen_mfc0(env, ctx, t0, rt, sel);
5090 } else switch (sel) {
5091 /* GPR registers. */
5092 case 0:
5093 gen_helper_1i(mftgpr, t0, rt);
5094 break;
5095 /* Auxiliary CPU registers */
5096 case 1:
5097 switch (rt) {
5098 case 0:
5099 gen_helper_1i(mftlo, t0, 0);
5100 break;
5101 case 1:
5102 gen_helper_1i(mfthi, t0, 0);
5103 break;
5104 case 2:
5105 gen_helper_1i(mftacx, t0, 0);
5106 break;
5107 case 4:
5108 gen_helper_1i(mftlo, t0, 1);
5109 break;
5110 case 5:
5111 gen_helper_1i(mfthi, t0, 1);
5112 break;
5113 case 6:
5114 gen_helper_1i(mftacx, t0, 1);
5115 break;
5116 case 8:
5117 gen_helper_1i(mftlo, t0, 2);
5118 break;
5119 case 9:
5120 gen_helper_1i(mfthi, t0, 2);
5121 break;
5122 case 10:
5123 gen_helper_1i(mftacx, t0, 2);
5124 break;
5125 case 12:
5126 gen_helper_1i(mftlo, t0, 3);
5127 break;
5128 case 13:
5129 gen_helper_1i(mfthi, t0, 3);
5130 break;
5131 case 14:
5132 gen_helper_1i(mftacx, t0, 3);
5133 break;
5134 case 16:
5135 gen_helper_mftdsp(t0);
5136 break;
5137 default:
5138 goto die;
5140 break;
5141 /* Floating point (COP1). */
5142 case 2:
5143 /* XXX: For now we support only a single FPU context. */
5144 if (h == 0) {
5145 TCGv_i32 fp0 = tcg_temp_new_i32();
5147 gen_load_fpr32(fp0, rt);
5148 tcg_gen_ext_i32_tl(t0, fp0);
5149 tcg_temp_free_i32(fp0);
5150 } else {
5151 TCGv_i32 fp0 = tcg_temp_new_i32();
5153 gen_load_fpr32h(fp0, rt);
5154 tcg_gen_ext_i32_tl(t0, fp0);
5155 tcg_temp_free_i32(fp0);
5157 break;
5158 case 3:
5159 /* XXX: For now we support only a single FPU context. */
5160 gen_helper_1i(cfc1, t0, rt);
5161 break;
5162 /* COP2: Not implemented. */
5163 case 4:
5164 case 5:
5165 /* fall through */
5166 default:
5167 goto die;
5169 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5170 gen_store_gpr(t0, rd);
5171 tcg_temp_free(t0);
5172 return;
5174 die:
5175 tcg_temp_free(t0);
5176 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5177 generate_exception(ctx, EXCP_RI);
5180 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5181 int u, int sel, int h)
5183 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5184 TCGv t0 = tcg_temp_local_new();
5186 gen_load_gpr(t0, rt);
5187 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5188 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5189 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5190 /* NOP */ ;
5191 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5192 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5193 /* NOP */ ;
5194 else if (u == 0) {
5195 switch (rd) {
5196 case 2:
5197 switch (sel) {
5198 case 1:
5199 gen_helper_mttc0_tcstatus(t0);
5200 break;
5201 case 2:
5202 gen_helper_mttc0_tcbind(t0);
5203 break;
5204 case 3:
5205 gen_helper_mttc0_tcrestart(t0);
5206 break;
5207 case 4:
5208 gen_helper_mttc0_tchalt(t0);
5209 break;
5210 case 5:
5211 gen_helper_mttc0_tccontext(t0);
5212 break;
5213 case 6:
5214 gen_helper_mttc0_tcschedule(t0);
5215 break;
5216 case 7:
5217 gen_helper_mttc0_tcschefback(t0);
5218 break;
5219 default:
5220 gen_mtc0(env, ctx, t0, rd, sel);
5221 break;
5223 break;
5224 case 10:
5225 switch (sel) {
5226 case 0:
5227 gen_helper_mttc0_entryhi(t0);
5228 break;
5229 default:
5230 gen_mtc0(env, ctx, t0, rd, sel);
5231 break;
5233 case 12:
5234 switch (sel) {
5235 case 0:
5236 gen_helper_mttc0_status(t0);
5237 break;
5238 default:
5239 gen_mtc0(env, ctx, t0, rd, sel);
5240 break;
5242 case 23:
5243 switch (sel) {
5244 case 0:
5245 gen_helper_mttc0_debug(t0);
5246 break;
5247 default:
5248 gen_mtc0(env, ctx, t0, rd, sel);
5249 break;
5251 break;
5252 default:
5253 gen_mtc0(env, ctx, t0, rd, sel);
5255 } else switch (sel) {
5256 /* GPR registers. */
5257 case 0:
5258 gen_helper_1i(mttgpr, t0, rd);
5259 break;
5260 /* Auxiliary CPU registers */
5261 case 1:
5262 switch (rd) {
5263 case 0:
5264 gen_helper_1i(mttlo, t0, 0);
5265 break;
5266 case 1:
5267 gen_helper_1i(mtthi, t0, 0);
5268 break;
5269 case 2:
5270 gen_helper_1i(mttacx, t0, 0);
5271 break;
5272 case 4:
5273 gen_helper_1i(mttlo, t0, 1);
5274 break;
5275 case 5:
5276 gen_helper_1i(mtthi, t0, 1);
5277 break;
5278 case 6:
5279 gen_helper_1i(mttacx, t0, 1);
5280 break;
5281 case 8:
5282 gen_helper_1i(mttlo, t0, 2);
5283 break;
5284 case 9:
5285 gen_helper_1i(mtthi, t0, 2);
5286 break;
5287 case 10:
5288 gen_helper_1i(mttacx, t0, 2);
5289 break;
5290 case 12:
5291 gen_helper_1i(mttlo, t0, 3);
5292 break;
5293 case 13:
5294 gen_helper_1i(mtthi, t0, 3);
5295 break;
5296 case 14:
5297 gen_helper_1i(mttacx, t0, 3);
5298 break;
5299 case 16:
5300 gen_helper_mttdsp(t0);
5301 break;
5302 default:
5303 goto die;
5305 break;
5306 /* Floating point (COP1). */
5307 case 2:
5308 /* XXX: For now we support only a single FPU context. */
5309 if (h == 0) {
5310 TCGv_i32 fp0 = tcg_temp_new_i32();
5312 tcg_gen_trunc_tl_i32(fp0, t0);
5313 gen_store_fpr32(fp0, rd);
5314 tcg_temp_free_i32(fp0);
5315 } else {
5316 TCGv_i32 fp0 = tcg_temp_new_i32();
5318 tcg_gen_trunc_tl_i32(fp0, t0);
5319 gen_store_fpr32h(fp0, rd);
5320 tcg_temp_free_i32(fp0);
5322 break;
5323 case 3:
5324 /* XXX: For now we support only a single FPU context. */
5325 gen_helper_1i(ctc1, t0, rd);
5326 break;
5327 /* COP2: Not implemented. */
5328 case 4:
5329 case 5:
5330 /* fall through */
5331 default:
5332 goto die;
5334 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5335 tcg_temp_free(t0);
5336 return;
5338 die:
5339 tcg_temp_free(t0);
5340 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5341 generate_exception(ctx, EXCP_RI);
5344 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5346 const char *opn = "ldst";
5348 switch (opc) {
5349 case OPC_MFC0:
5350 if (rt == 0) {
5351 /* Treat as NOP. */
5352 return;
5355 TCGv t0 = tcg_temp_local_new();
5357 gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5358 gen_store_gpr(t0, rt);
5359 tcg_temp_free(t0);
5361 opn = "mfc0";
5362 break;
5363 case OPC_MTC0:
5365 TCGv t0 = tcg_temp_local_new();
5367 gen_load_gpr(t0, rt);
5368 save_cpu_state(ctx, 1);
5369 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5370 tcg_temp_free(t0);
5372 opn = "mtc0";
5373 break;
5374 #if defined(TARGET_MIPS64)
5375 case OPC_DMFC0:
5376 check_insn(env, ctx, ISA_MIPS3);
5377 if (rt == 0) {
5378 /* Treat as NOP. */
5379 return;
5382 TCGv t0 = tcg_temp_local_new();
5384 gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5385 gen_store_gpr(t0, rt);
5386 tcg_temp_free(t0);
5388 opn = "dmfc0";
5389 break;
5390 case OPC_DMTC0:
5391 check_insn(env, ctx, ISA_MIPS3);
5393 TCGv t0 = tcg_temp_local_new();
5395 gen_load_gpr(t0, rt);
5396 save_cpu_state(ctx, 1);
5397 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5398 tcg_temp_free(t0);
5400 opn = "dmtc0";
5401 break;
5402 #endif
5403 case OPC_MFTR:
5404 check_insn(env, ctx, ASE_MT);
5405 if (rd == 0) {
5406 /* Treat as NOP. */
5407 return;
5409 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5410 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5411 opn = "mftr";
5412 break;
5413 case OPC_MTTR:
5414 check_insn(env, ctx, ASE_MT);
5415 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5416 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5417 opn = "mttr";
5418 break;
5419 case OPC_TLBWI:
5420 opn = "tlbwi";
5421 if (!env->tlb->helper_tlbwi)
5422 goto die;
5423 gen_helper_tlbwi();
5424 break;
5425 case OPC_TLBWR:
5426 opn = "tlbwr";
5427 if (!env->tlb->helper_tlbwr)
5428 goto die;
5429 gen_helper_tlbwr();
5430 break;
5431 case OPC_TLBP:
5432 opn = "tlbp";
5433 if (!env->tlb->helper_tlbp)
5434 goto die;
5435 gen_helper_tlbp();
5436 break;
5437 case OPC_TLBR:
5438 opn = "tlbr";
5439 if (!env->tlb->helper_tlbr)
5440 goto die;
5441 gen_helper_tlbr();
5442 break;
5443 case OPC_ERET:
5444 opn = "eret";
5445 check_insn(env, ctx, ISA_MIPS2);
5446 save_cpu_state(ctx, 1);
5447 gen_helper_eret();
5448 ctx->bstate = BS_EXCP;
5449 break;
5450 case OPC_DERET:
5451 opn = "deret";
5452 check_insn(env, ctx, ISA_MIPS32);
5453 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5454 MIPS_INVAL(opn);
5455 generate_exception(ctx, EXCP_RI);
5456 } else {
5457 save_cpu_state(ctx, 1);
5458 gen_helper_deret();
5459 ctx->bstate = BS_EXCP;
5461 break;
5462 case OPC_WAIT:
5463 opn = "wait";
5464 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5465 /* If we get an exception, we want to restart at next instruction */
5466 ctx->pc += 4;
5467 save_cpu_state(ctx, 1);
5468 ctx->pc -= 4;
5469 gen_helper_wait();
5470 ctx->bstate = BS_EXCP;
5471 break;
5472 default:
5473 die:
5474 MIPS_INVAL(opn);
5475 generate_exception(ctx, EXCP_RI);
5476 return;
5478 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5480 #endif /* !CONFIG_USER_ONLY */
5482 /* CP1 Branches (before delay slot) */
5483 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5484 int32_t cc, int32_t offset)
5486 target_ulong btarget;
5487 const char *opn = "cp1 cond branch";
5488 TCGv_i32 t0 = tcg_temp_new_i32();
5490 if (cc != 0)
5491 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5493 btarget = ctx->pc + 4 + offset;
5495 switch (op) {
5496 case OPC_BC1F:
5497 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5498 tcg_gen_not_i32(t0, t0);
5499 tcg_gen_andi_i32(t0, t0, 1);
5500 tcg_gen_extu_i32_tl(bcond, t0);
5501 opn = "bc1f";
5502 goto not_likely;
5503 case OPC_BC1FL:
5504 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5505 tcg_gen_not_i32(t0, t0);
5506 tcg_gen_andi_i32(t0, t0, 1);
5507 tcg_gen_extu_i32_tl(bcond, t0);
5508 opn = "bc1fl";
5509 goto likely;
5510 case OPC_BC1T:
5511 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5512 tcg_gen_andi_i32(t0, t0, 1);
5513 tcg_gen_extu_i32_tl(bcond, t0);
5514 opn = "bc1t";
5515 goto not_likely;
5516 case OPC_BC1TL:
5517 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5518 tcg_gen_andi_i32(t0, t0, 1);
5519 tcg_gen_extu_i32_tl(bcond, t0);
5520 opn = "bc1tl";
5521 likely:
5522 ctx->hflags |= MIPS_HFLAG_BL;
5523 break;
5524 case OPC_BC1FANY2:
5526 TCGv_i32 t1 = tcg_temp_new_i32();
5527 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5528 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5529 tcg_gen_or_i32(t0, t0, t1);
5530 tcg_temp_free_i32(t1);
5531 tcg_gen_not_i32(t0, t0);
5532 tcg_gen_andi_i32(t0, t0, 1);
5533 tcg_gen_extu_i32_tl(bcond, t0);
5535 opn = "bc1any2f";
5536 goto not_likely;
5537 case OPC_BC1TANY2:
5539 TCGv_i32 t1 = tcg_temp_new_i32();
5540 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5541 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5542 tcg_gen_or_i32(t0, t0, t1);
5543 tcg_temp_free_i32(t1);
5544 tcg_gen_andi_i32(t0, t0, 1);
5545 tcg_gen_extu_i32_tl(bcond, t0);
5547 opn = "bc1any2t";
5548 goto not_likely;
5549 case OPC_BC1FANY4:
5551 TCGv_i32 t1 = tcg_temp_new_i32();
5552 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5553 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5554 tcg_gen_or_i32(t0, t0, t1);
5555 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5556 tcg_gen_or_i32(t0, t0, t1);
5557 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5558 tcg_gen_or_i32(t0, t0, t1);
5559 tcg_temp_free_i32(t1);
5560 tcg_gen_not_i32(t0, t0);
5561 tcg_gen_andi_i32(t0, t0, 1);
5562 tcg_gen_extu_i32_tl(bcond, t0);
5564 opn = "bc1any4f";
5565 goto not_likely;
5566 case OPC_BC1TANY4:
5568 TCGv_i32 t1 = tcg_temp_new_i32();
5569 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5570 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5571 tcg_gen_or_i32(t0, t0, t1);
5572 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5573 tcg_gen_or_i32(t0, t0, t1);
5574 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5575 tcg_gen_or_i32(t0, t0, t1);
5576 tcg_temp_free_i32(t1);
5577 tcg_gen_andi_i32(t0, t0, 1);
5578 tcg_gen_extu_i32_tl(bcond, t0);
5580 opn = "bc1any4t";
5581 not_likely:
5582 ctx->hflags |= MIPS_HFLAG_BC;
5583 break;
5584 default:
5585 MIPS_INVAL(opn);
5586 generate_exception (ctx, EXCP_RI);
5587 goto out;
5589 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5590 ctx->hflags, btarget);
5591 ctx->btarget = btarget;
5593 out:
5594 tcg_temp_free_i32(t0);
5597 /* Coprocessor 1 (FPU) */
5599 #define FOP(func, fmt) (((fmt) << 21) | (func))
5601 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5603 const char *opn = "cp1 move";
5604 TCGv t0 = tcg_temp_local_new();
5606 switch (opc) {
5607 case OPC_MFC1:
5609 TCGv_i32 fp0 = tcg_temp_new_i32();
5611 gen_load_fpr32(fp0, fs);
5612 tcg_gen_ext_i32_tl(t0, fp0);
5613 tcg_temp_free_i32(fp0);
5615 gen_store_gpr(t0, rt);
5616 opn = "mfc1";
5617 break;
5618 case OPC_MTC1:
5619 gen_load_gpr(t0, rt);
5621 TCGv_i32 fp0 = tcg_temp_new_i32();
5623 tcg_gen_trunc_tl_i32(fp0, t0);
5624 gen_store_fpr32(fp0, fs);
5625 tcg_temp_free_i32(fp0);
5627 opn = "mtc1";
5628 break;
5629 case OPC_CFC1:
5630 gen_helper_1i(cfc1, t0, fs);
5631 gen_store_gpr(t0, rt);
5632 opn = "cfc1";
5633 break;
5634 case OPC_CTC1:
5635 gen_load_gpr(t0, rt);
5636 gen_helper_1i(ctc1, t0, fs);
5637 opn = "ctc1";
5638 break;
5639 case OPC_DMFC1:
5641 TCGv_i64 fp0 = tcg_temp_new_i64();
5643 gen_load_fpr64(ctx, fp0, fs);
5644 tcg_gen_trunc_i64_tl(t0, fp0);
5645 tcg_temp_free_i64(fp0);
5647 gen_store_gpr(t0, rt);
5648 opn = "dmfc1";
5649 break;
5650 case OPC_DMTC1:
5651 gen_load_gpr(t0, rt);
5653 TCGv_i64 fp0 = tcg_temp_new_i64();
5655 tcg_gen_extu_tl_i64(fp0, t0);
5656 gen_store_fpr64(ctx, fp0, fs);
5657 tcg_temp_free_i64(fp0);
5659 opn = "dmtc1";
5660 break;
5661 case OPC_MFHC1:
5663 TCGv_i32 fp0 = tcg_temp_new_i32();
5665 gen_load_fpr32h(fp0, fs);
5666 tcg_gen_ext_i32_tl(t0, fp0);
5667 tcg_temp_free_i32(fp0);
5669 gen_store_gpr(t0, rt);
5670 opn = "mfhc1";
5671 break;
5672 case OPC_MTHC1:
5673 gen_load_gpr(t0, rt);
5675 TCGv_i32 fp0 = tcg_temp_new_i32();
5677 tcg_gen_trunc_tl_i32(fp0, t0);
5678 gen_store_fpr32h(fp0, fs);
5679 tcg_temp_free_i32(fp0);
5681 opn = "mthc1";
5682 break;
5683 default:
5684 MIPS_INVAL(opn);
5685 generate_exception (ctx, EXCP_RI);
5686 goto out;
5688 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5690 out:
5691 tcg_temp_free(t0);
5694 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5696 int l1;
5697 TCGCond cond;
5698 TCGv_i32 t0;
5700 if (rd == 0) {
5701 /* Treat as NOP. */
5702 return;
5705 if (tf)
5706 cond = TCG_COND_EQ;
5707 else
5708 cond = TCG_COND_NE;
5710 l1 = gen_new_label();
5711 t0 = tcg_temp_new_i32();
5712 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5713 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5714 if (rs == 0) {
5715 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5716 } else {
5717 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5719 gen_set_label(l1);
5720 tcg_temp_free_i32(t0);
5723 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5725 int cond;
5726 TCGv_i32 t0 = tcg_temp_new_i32();
5727 int l1 = gen_new_label();
5729 if (tf)
5730 cond = TCG_COND_EQ;
5731 else
5732 cond = TCG_COND_NE;
5734 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5735 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5736 gen_load_fpr32(t0, fs);
5737 gen_store_fpr32(t0, fd);
5738 gen_set_label(l1);
5739 tcg_temp_free_i32(t0);
5742 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5744 int cond;
5745 TCGv_i32 t0 = tcg_temp_new_i32();
5746 TCGv_i64 fp0;
5747 int l1 = gen_new_label();
5749 if (tf)
5750 cond = TCG_COND_EQ;
5751 else
5752 cond = TCG_COND_NE;
5754 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5755 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5756 fp0 = tcg_temp_local_new_i64();
5757 gen_load_fpr64(ctx, fp0, fs);
5758 gen_store_fpr64(ctx, fp0, fd);
5759 tcg_temp_free_i64(fp0);
5760 gen_set_label(l1);
5761 tcg_temp_free_i32(t0);
5764 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5766 int cond;
5767 TCGv_i32 t0 = tcg_temp_new_i32();
5768 int l1 = gen_new_label();
5769 int l2 = gen_new_label();
5771 if (tf)
5772 cond = TCG_COND_EQ;
5773 else
5774 cond = TCG_COND_NE;
5776 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5777 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5778 gen_load_fpr32(t0, fs);
5779 gen_store_fpr32(t0, fd);
5780 gen_set_label(l1);
5782 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc+1));
5783 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5784 gen_load_fpr32h(t0, fs);
5785 gen_store_fpr32h(t0, fd);
5786 gen_set_label(l2);
5788 tcg_temp_free_i32(t0);
5792 static void gen_farith (DisasContext *ctx, uint32_t op1,
5793 int ft, int fs, int fd, int cc)
5795 const char *opn = "farith";
5796 const char *condnames[] = {
5797 "c.f",
5798 "c.un",
5799 "c.eq",
5800 "c.ueq",
5801 "c.olt",
5802 "c.ult",
5803 "c.ole",
5804 "c.ule",
5805 "c.sf",
5806 "c.ngle",
5807 "c.seq",
5808 "c.ngl",
5809 "c.lt",
5810 "c.nge",
5811 "c.le",
5812 "c.ngt",
5814 const char *condnames_abs[] = {
5815 "cabs.f",
5816 "cabs.un",
5817 "cabs.eq",
5818 "cabs.ueq",
5819 "cabs.olt",
5820 "cabs.ult",
5821 "cabs.ole",
5822 "cabs.ule",
5823 "cabs.sf",
5824 "cabs.ngle",
5825 "cabs.seq",
5826 "cabs.ngl",
5827 "cabs.lt",
5828 "cabs.nge",
5829 "cabs.le",
5830 "cabs.ngt",
5832 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
5833 uint32_t func = ctx->opcode & 0x3f;
5835 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5836 case FOP(0, 16):
5838 TCGv_i32 fp0 = tcg_temp_new_i32();
5839 TCGv_i32 fp1 = tcg_temp_new_i32();
5841 gen_load_fpr32(fp0, fs);
5842 gen_load_fpr32(fp1, ft);
5843 gen_helper_float_add_s(fp0, fp0, fp1);
5844 tcg_temp_free_i32(fp1);
5845 gen_store_fpr32(fp0, fd);
5846 tcg_temp_free_i32(fp0);
5848 opn = "add.s";
5849 optype = BINOP;
5850 break;
5851 case FOP(1, 16):
5853 TCGv_i32 fp0 = tcg_temp_new_i32();
5854 TCGv_i32 fp1 = tcg_temp_new_i32();
5856 gen_load_fpr32(fp0, fs);
5857 gen_load_fpr32(fp1, ft);
5858 gen_helper_float_sub_s(fp0, fp0, fp1);
5859 tcg_temp_free_i32(fp1);
5860 gen_store_fpr32(fp0, fd);
5861 tcg_temp_free_i32(fp0);
5863 opn = "sub.s";
5864 optype = BINOP;
5865 break;
5866 case FOP(2, 16):
5868 TCGv_i32 fp0 = tcg_temp_new_i32();
5869 TCGv_i32 fp1 = tcg_temp_new_i32();
5871 gen_load_fpr32(fp0, fs);
5872 gen_load_fpr32(fp1, ft);
5873 gen_helper_float_mul_s(fp0, fp0, fp1);
5874 tcg_temp_free_i32(fp1);
5875 gen_store_fpr32(fp0, fd);
5876 tcg_temp_free_i32(fp0);
5878 opn = "mul.s";
5879 optype = BINOP;
5880 break;
5881 case FOP(3, 16):
5883 TCGv_i32 fp0 = tcg_temp_new_i32();
5884 TCGv_i32 fp1 = tcg_temp_new_i32();
5886 gen_load_fpr32(fp0, fs);
5887 gen_load_fpr32(fp1, ft);
5888 gen_helper_float_div_s(fp0, fp0, fp1);
5889 tcg_temp_free_i32(fp1);
5890 gen_store_fpr32(fp0, fd);
5891 tcg_temp_free_i32(fp0);
5893 opn = "div.s";
5894 optype = BINOP;
5895 break;
5896 case FOP(4, 16):
5898 TCGv_i32 fp0 = tcg_temp_new_i32();
5900 gen_load_fpr32(fp0, fs);
5901 gen_helper_float_sqrt_s(fp0, fp0);
5902 gen_store_fpr32(fp0, fd);
5903 tcg_temp_free_i32(fp0);
5905 opn = "sqrt.s";
5906 break;
5907 case FOP(5, 16):
5909 TCGv_i32 fp0 = tcg_temp_new_i32();
5911 gen_load_fpr32(fp0, fs);
5912 gen_helper_float_abs_s(fp0, fp0);
5913 gen_store_fpr32(fp0, fd);
5914 tcg_temp_free_i32(fp0);
5916 opn = "abs.s";
5917 break;
5918 case FOP(6, 16):
5920 TCGv_i32 fp0 = tcg_temp_new_i32();
5922 gen_load_fpr32(fp0, fs);
5923 gen_store_fpr32(fp0, fd);
5924 tcg_temp_free_i32(fp0);
5926 opn = "mov.s";
5927 break;
5928 case FOP(7, 16):
5930 TCGv_i32 fp0 = tcg_temp_new_i32();
5932 gen_load_fpr32(fp0, fs);
5933 gen_helper_float_chs_s(fp0, fp0);
5934 gen_store_fpr32(fp0, fd);
5935 tcg_temp_free_i32(fp0);
5937 opn = "neg.s";
5938 break;
5939 case FOP(8, 16):
5940 check_cp1_64bitmode(ctx);
5942 TCGv_i32 fp32 = tcg_temp_new_i32();
5943 TCGv_i64 fp64 = tcg_temp_new_i64();
5945 gen_load_fpr32(fp32, fs);
5946 gen_helper_float_roundl_s(fp64, fp32);
5947 tcg_temp_free_i32(fp32);
5948 gen_store_fpr64(ctx, fp64, fd);
5949 tcg_temp_free_i64(fp64);
5951 opn = "round.l.s";
5952 break;
5953 case FOP(9, 16):
5954 check_cp1_64bitmode(ctx);
5956 TCGv_i32 fp32 = tcg_temp_new_i32();
5957 TCGv_i64 fp64 = tcg_temp_new_i64();
5959 gen_load_fpr32(fp32, fs);
5960 gen_helper_float_truncl_s(fp64, fp32);
5961 tcg_temp_free_i32(fp32);
5962 gen_store_fpr64(ctx, fp64, fd);
5963 tcg_temp_free_i64(fp64);
5965 opn = "trunc.l.s";
5966 break;
5967 case FOP(10, 16):
5968 check_cp1_64bitmode(ctx);
5970 TCGv_i32 fp32 = tcg_temp_new_i32();
5971 TCGv_i64 fp64 = tcg_temp_new_i64();
5973 gen_load_fpr32(fp32, fs);
5974 gen_helper_float_ceill_s(fp64, fp32);
5975 tcg_temp_free_i32(fp32);
5976 gen_store_fpr64(ctx, fp64, fd);
5977 tcg_temp_free_i64(fp64);
5979 opn = "ceil.l.s";
5980 break;
5981 case FOP(11, 16):
5982 check_cp1_64bitmode(ctx);
5984 TCGv_i32 fp32 = tcg_temp_new_i32();
5985 TCGv_i64 fp64 = tcg_temp_new_i64();
5987 gen_load_fpr32(fp32, fs);
5988 gen_helper_float_floorl_s(fp64, fp32);
5989 tcg_temp_free_i32(fp32);
5990 gen_store_fpr64(ctx, fp64, fd);
5991 tcg_temp_free_i64(fp64);
5993 opn = "floor.l.s";
5994 break;
5995 case FOP(12, 16):
5997 TCGv_i32 fp0 = tcg_temp_new_i32();
5999 gen_load_fpr32(fp0, fs);
6000 gen_helper_float_roundw_s(fp0, fp0);
6001 gen_store_fpr32(fp0, fd);
6002 tcg_temp_free_i32(fp0);
6004 opn = "round.w.s";
6005 break;
6006 case FOP(13, 16):
6008 TCGv_i32 fp0 = tcg_temp_new_i32();
6010 gen_load_fpr32(fp0, fs);
6011 gen_helper_float_truncw_s(fp0, fp0);
6012 gen_store_fpr32(fp0, fd);
6013 tcg_temp_free_i32(fp0);
6015 opn = "trunc.w.s";
6016 break;
6017 case FOP(14, 16):
6019 TCGv_i32 fp0 = tcg_temp_new_i32();
6021 gen_load_fpr32(fp0, fs);
6022 gen_helper_float_ceilw_s(fp0, fp0);
6023 gen_store_fpr32(fp0, fd);
6024 tcg_temp_free_i32(fp0);
6026 opn = "ceil.w.s";
6027 break;
6028 case FOP(15, 16):
6030 TCGv_i32 fp0 = tcg_temp_new_i32();
6032 gen_load_fpr32(fp0, fs);
6033 gen_helper_float_floorw_s(fp0, fp0);
6034 gen_store_fpr32(fp0, fd);
6035 tcg_temp_free_i32(fp0);
6037 opn = "floor.w.s";
6038 break;
6039 case FOP(17, 16):
6040 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6041 opn = "movcf.s";
6042 break;
6043 case FOP(18, 16):
6045 int l1 = gen_new_label();
6046 TCGv t0 = tcg_temp_new();
6047 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6049 gen_load_gpr(t0, ft);
6050 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6051 gen_load_fpr32(fp0, fs);
6052 gen_store_fpr32(fp0, fd);
6053 tcg_temp_free_i32(fp0);
6054 gen_set_label(l1);
6055 tcg_temp_free(t0);
6057 opn = "movz.s";
6058 break;
6059 case FOP(19, 16):
6061 int l1 = gen_new_label();
6062 TCGv t0 = tcg_temp_new();
6063 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6065 gen_load_gpr(t0, ft);
6066 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6067 gen_load_fpr32(fp0, fs);
6068 gen_store_fpr32(fp0, fd);
6069 tcg_temp_free_i32(fp0);
6070 gen_set_label(l1);
6071 tcg_temp_free(t0);
6073 opn = "movn.s";
6074 break;
6075 case FOP(21, 16):
6076 check_cop1x(ctx);
6078 TCGv_i32 fp0 = tcg_temp_new_i32();
6080 gen_load_fpr32(fp0, fs);
6081 gen_helper_float_recip_s(fp0, fp0);
6082 gen_store_fpr32(fp0, fd);
6083 tcg_temp_free_i32(fp0);
6085 opn = "recip.s";
6086 break;
6087 case FOP(22, 16):
6088 check_cop1x(ctx);
6090 TCGv_i32 fp0 = tcg_temp_new_i32();
6092 gen_load_fpr32(fp0, fs);
6093 gen_helper_float_rsqrt_s(fp0, fp0);
6094 gen_store_fpr32(fp0, fd);
6095 tcg_temp_free_i32(fp0);
6097 opn = "rsqrt.s";
6098 break;
6099 case FOP(28, 16):
6100 check_cp1_64bitmode(ctx);
6102 TCGv_i32 fp0 = tcg_temp_new_i32();
6103 TCGv_i32 fp1 = tcg_temp_new_i32();
6105 gen_load_fpr32(fp0, fs);
6106 gen_load_fpr32(fp1, fd);
6107 gen_helper_float_recip2_s(fp0, fp0, fp1);
6108 tcg_temp_free_i32(fp1);
6109 gen_store_fpr32(fp0, fd);
6110 tcg_temp_free_i32(fp0);
6112 opn = "recip2.s";
6113 break;
6114 case FOP(29, 16):
6115 check_cp1_64bitmode(ctx);
6117 TCGv_i32 fp0 = tcg_temp_new_i32();
6119 gen_load_fpr32(fp0, fs);
6120 gen_helper_float_recip1_s(fp0, fp0);
6121 gen_store_fpr32(fp0, fd);
6122 tcg_temp_free_i32(fp0);
6124 opn = "recip1.s";
6125 break;
6126 case FOP(30, 16):
6127 check_cp1_64bitmode(ctx);
6129 TCGv_i32 fp0 = tcg_temp_new_i32();
6131 gen_load_fpr32(fp0, fs);
6132 gen_helper_float_rsqrt1_s(fp0, fp0);
6133 gen_store_fpr32(fp0, fd);
6134 tcg_temp_free_i32(fp0);
6136 opn = "rsqrt1.s";
6137 break;
6138 case FOP(31, 16):
6139 check_cp1_64bitmode(ctx);
6141 TCGv_i32 fp0 = tcg_temp_new_i32();
6142 TCGv_i32 fp1 = tcg_temp_new_i32();
6144 gen_load_fpr32(fp0, fs);
6145 gen_load_fpr32(fp1, ft);
6146 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6147 tcg_temp_free_i32(fp1);
6148 gen_store_fpr32(fp0, fd);
6149 tcg_temp_free_i32(fp0);
6151 opn = "rsqrt2.s";
6152 break;
6153 case FOP(33, 16):
6154 check_cp1_registers(ctx, fd);
6156 TCGv_i32 fp32 = tcg_temp_new_i32();
6157 TCGv_i64 fp64 = tcg_temp_new_i64();
6159 gen_load_fpr32(fp32, fs);
6160 gen_helper_float_cvtd_s(fp64, fp32);
6161 tcg_temp_free_i32(fp32);
6162 gen_store_fpr64(ctx, fp64, fd);
6163 tcg_temp_free_i64(fp64);
6165 opn = "cvt.d.s";
6166 break;
6167 case FOP(36, 16):
6169 TCGv_i32 fp0 = tcg_temp_new_i32();
6171 gen_load_fpr32(fp0, fs);
6172 gen_helper_float_cvtw_s(fp0, fp0);
6173 gen_store_fpr32(fp0, fd);
6174 tcg_temp_free_i32(fp0);
6176 opn = "cvt.w.s";
6177 break;
6178 case FOP(37, 16):
6179 check_cp1_64bitmode(ctx);
6181 TCGv_i32 fp32 = tcg_temp_new_i32();
6182 TCGv_i64 fp64 = tcg_temp_new_i64();
6184 gen_load_fpr32(fp32, fs);
6185 gen_helper_float_cvtl_s(fp64, fp32);
6186 tcg_temp_free_i32(fp32);
6187 gen_store_fpr64(ctx, fp64, fd);
6188 tcg_temp_free_i64(fp64);
6190 opn = "cvt.l.s";
6191 break;
6192 case FOP(38, 16):
6193 check_cp1_64bitmode(ctx);
6195 TCGv_i64 fp64 = tcg_temp_new_i64();
6196 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6197 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6199 gen_load_fpr32(fp32_0, fs);
6200 gen_load_fpr32(fp32_1, ft);
6201 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6202 tcg_temp_free_i32(fp32_1);
6203 tcg_temp_free_i32(fp32_0);
6204 gen_store_fpr64(ctx, fp64, fd);
6205 tcg_temp_free_i64(fp64);
6207 opn = "cvt.ps.s";
6208 break;
6209 case FOP(48, 16):
6210 case FOP(49, 16):
6211 case FOP(50, 16):
6212 case FOP(51, 16):
6213 case FOP(52, 16):
6214 case FOP(53, 16):
6215 case FOP(54, 16):
6216 case FOP(55, 16):
6217 case FOP(56, 16):
6218 case FOP(57, 16):
6219 case FOP(58, 16):
6220 case FOP(59, 16):
6221 case FOP(60, 16):
6222 case FOP(61, 16):
6223 case FOP(62, 16):
6224 case FOP(63, 16):
6226 TCGv_i32 fp0 = tcg_temp_new_i32();
6227 TCGv_i32 fp1 = tcg_temp_new_i32();
6229 gen_load_fpr32(fp0, fs);
6230 gen_load_fpr32(fp1, ft);
6231 if (ctx->opcode & (1 << 6)) {
6232 check_cop1x(ctx);
6233 gen_cmpabs_s(func-48, fp0, fp1, cc);
6234 opn = condnames_abs[func-48];
6235 } else {
6236 gen_cmp_s(func-48, fp0, fp1, cc);
6237 opn = condnames[func-48];
6239 tcg_temp_free_i32(fp0);
6240 tcg_temp_free_i32(fp1);
6242 break;
6243 case FOP(0, 17):
6244 check_cp1_registers(ctx, fs | ft | fd);
6246 TCGv_i64 fp0 = tcg_temp_new_i64();
6247 TCGv_i64 fp1 = tcg_temp_new_i64();
6249 gen_load_fpr64(ctx, fp0, fs);
6250 gen_load_fpr64(ctx, fp1, ft);
6251 gen_helper_float_add_d(fp0, fp0, fp1);
6252 tcg_temp_free_i64(fp1);
6253 gen_store_fpr64(ctx, fp0, fd);
6254 tcg_temp_free_i64(fp0);
6256 opn = "add.d";
6257 optype = BINOP;
6258 break;
6259 case FOP(1, 17):
6260 check_cp1_registers(ctx, fs | ft | fd);
6262 TCGv_i64 fp0 = tcg_temp_new_i64();
6263 TCGv_i64 fp1 = tcg_temp_new_i64();
6265 gen_load_fpr64(ctx, fp0, fs);
6266 gen_load_fpr64(ctx, fp1, ft);
6267 gen_helper_float_sub_d(fp0, fp0, fp1);
6268 tcg_temp_free_i64(fp1);
6269 gen_store_fpr64(ctx, fp0, fd);
6270 tcg_temp_free_i64(fp0);
6272 opn = "sub.d";
6273 optype = BINOP;
6274 break;
6275 case FOP(2, 17):
6276 check_cp1_registers(ctx, fs | ft | fd);
6278 TCGv_i64 fp0 = tcg_temp_new_i64();
6279 TCGv_i64 fp1 = tcg_temp_new_i64();
6281 gen_load_fpr64(ctx, fp0, fs);
6282 gen_load_fpr64(ctx, fp1, ft);
6283 gen_helper_float_mul_d(fp0, fp0, fp1);
6284 tcg_temp_free_i64(fp1);
6285 gen_store_fpr64(ctx, fp0, fd);
6286 tcg_temp_free_i64(fp0);
6288 opn = "mul.d";
6289 optype = BINOP;
6290 break;
6291 case FOP(3, 17):
6292 check_cp1_registers(ctx, fs | ft | fd);
6294 TCGv_i64 fp0 = tcg_temp_new_i64();
6295 TCGv_i64 fp1 = tcg_temp_new_i64();
6297 gen_load_fpr64(ctx, fp0, fs);
6298 gen_load_fpr64(ctx, fp1, ft);
6299 gen_helper_float_div_d(fp0, fp0, fp1);
6300 tcg_temp_free_i64(fp1);
6301 gen_store_fpr64(ctx, fp0, fd);
6302 tcg_temp_free_i64(fp0);
6304 opn = "div.d";
6305 optype = BINOP;
6306 break;
6307 case FOP(4, 17):
6308 check_cp1_registers(ctx, fs | fd);
6310 TCGv_i64 fp0 = tcg_temp_new_i64();
6312 gen_load_fpr64(ctx, fp0, fs);
6313 gen_helper_float_sqrt_d(fp0, fp0);
6314 gen_store_fpr64(ctx, fp0, fd);
6315 tcg_temp_free_i64(fp0);
6317 opn = "sqrt.d";
6318 break;
6319 case FOP(5, 17):
6320 check_cp1_registers(ctx, fs | fd);
6322 TCGv_i64 fp0 = tcg_temp_new_i64();
6324 gen_load_fpr64(ctx, fp0, fs);
6325 gen_helper_float_abs_d(fp0, fp0);
6326 gen_store_fpr64(ctx, fp0, fd);
6327 tcg_temp_free_i64(fp0);
6329 opn = "abs.d";
6330 break;
6331 case FOP(6, 17):
6332 check_cp1_registers(ctx, fs | fd);
6334 TCGv_i64 fp0 = tcg_temp_new_i64();
6336 gen_load_fpr64(ctx, fp0, fs);
6337 gen_store_fpr64(ctx, fp0, fd);
6338 tcg_temp_free_i64(fp0);
6340 opn = "mov.d";
6341 break;
6342 case FOP(7, 17):
6343 check_cp1_registers(ctx, fs | fd);
6345 TCGv_i64 fp0 = tcg_temp_new_i64();
6347 gen_load_fpr64(ctx, fp0, fs);
6348 gen_helper_float_chs_d(fp0, fp0);
6349 gen_store_fpr64(ctx, fp0, fd);
6350 tcg_temp_free_i64(fp0);
6352 opn = "neg.d";
6353 break;
6354 case FOP(8, 17):
6355 check_cp1_64bitmode(ctx);
6357 TCGv_i64 fp0 = tcg_temp_new_i64();
6359 gen_load_fpr64(ctx, fp0, fs);
6360 gen_helper_float_roundl_d(fp0, fp0);
6361 gen_store_fpr64(ctx, fp0, fd);
6362 tcg_temp_free_i64(fp0);
6364 opn = "round.l.d";
6365 break;
6366 case FOP(9, 17):
6367 check_cp1_64bitmode(ctx);
6369 TCGv_i64 fp0 = tcg_temp_new_i64();
6371 gen_load_fpr64(ctx, fp0, fs);
6372 gen_helper_float_truncl_d(fp0, fp0);
6373 gen_store_fpr64(ctx, fp0, fd);
6374 tcg_temp_free_i64(fp0);
6376 opn = "trunc.l.d";
6377 break;
6378 case FOP(10, 17):
6379 check_cp1_64bitmode(ctx);
6381 TCGv_i64 fp0 = tcg_temp_new_i64();
6383 gen_load_fpr64(ctx, fp0, fs);
6384 gen_helper_float_ceill_d(fp0, fp0);
6385 gen_store_fpr64(ctx, fp0, fd);
6386 tcg_temp_free_i64(fp0);
6388 opn = "ceil.l.d";
6389 break;
6390 case FOP(11, 17):
6391 check_cp1_64bitmode(ctx);
6393 TCGv_i64 fp0 = tcg_temp_new_i64();
6395 gen_load_fpr64(ctx, fp0, fs);
6396 gen_helper_float_floorl_d(fp0, fp0);
6397 gen_store_fpr64(ctx, fp0, fd);
6398 tcg_temp_free_i64(fp0);
6400 opn = "floor.l.d";
6401 break;
6402 case FOP(12, 17):
6403 check_cp1_registers(ctx, fs);
6405 TCGv_i32 fp32 = tcg_temp_new_i32();
6406 TCGv_i64 fp64 = tcg_temp_new_i64();
6408 gen_load_fpr64(ctx, fp64, fs);
6409 gen_helper_float_roundw_d(fp32, fp64);
6410 tcg_temp_free_i64(fp64);
6411 gen_store_fpr32(fp32, fd);
6412 tcg_temp_free_i32(fp32);
6414 opn = "round.w.d";
6415 break;
6416 case FOP(13, 17):
6417 check_cp1_registers(ctx, fs);
6419 TCGv_i32 fp32 = tcg_temp_new_i32();
6420 TCGv_i64 fp64 = tcg_temp_new_i64();
6422 gen_load_fpr64(ctx, fp64, fs);
6423 gen_helper_float_truncw_d(fp32, fp64);
6424 tcg_temp_free_i64(fp64);
6425 gen_store_fpr32(fp32, fd);
6426 tcg_temp_free_i32(fp32);
6428 opn = "trunc.w.d";
6429 break;
6430 case FOP(14, 17):
6431 check_cp1_registers(ctx, fs);
6433 TCGv_i32 fp32 = tcg_temp_new_i32();
6434 TCGv_i64 fp64 = tcg_temp_new_i64();
6436 gen_load_fpr64(ctx, fp64, fs);
6437 gen_helper_float_ceilw_d(fp32, fp64);
6438 tcg_temp_free_i64(fp64);
6439 gen_store_fpr32(fp32, fd);
6440 tcg_temp_free_i32(fp32);
6442 opn = "ceil.w.d";
6443 break;
6444 case FOP(15, 17):
6445 check_cp1_registers(ctx, fs);
6447 TCGv_i32 fp32 = tcg_temp_new_i32();
6448 TCGv_i64 fp64 = tcg_temp_new_i64();
6450 gen_load_fpr64(ctx, fp64, fs);
6451 gen_helper_float_floorw_d(fp32, fp64);
6452 tcg_temp_free_i64(fp64);
6453 gen_store_fpr32(fp32, fd);
6454 tcg_temp_free_i32(fp32);
6456 opn = "floor.w.d";
6457 break;
6458 case FOP(17, 17):
6459 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6460 opn = "movcf.d";
6461 break;
6462 case FOP(18, 17):
6464 int l1 = gen_new_label();
6465 TCGv t0 = tcg_temp_new();
6466 TCGv_i64 fp0 = tcg_temp_local_new_i64();
6468 gen_load_gpr(t0, ft);
6469 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6470 gen_load_fpr64(ctx, fp0, fs);
6471 gen_store_fpr64(ctx, fp0, fd);
6472 tcg_temp_free_i64(fp0);
6473 gen_set_label(l1);
6474 tcg_temp_free(t0);
6476 opn = "movz.d";
6477 break;
6478 case FOP(19, 17):
6480 int l1 = gen_new_label();
6481 TCGv t0 = tcg_temp_new();
6482 TCGv_i64 fp0 = tcg_temp_local_new_i64();
6484 gen_load_gpr(t0, ft);
6485 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6486 gen_load_fpr64(ctx, fp0, fs);
6487 gen_store_fpr64(ctx, fp0, fd);
6488 tcg_temp_free_i64(fp0);
6489 gen_set_label(l1);
6490 tcg_temp_free(t0);
6492 opn = "movn.d";
6493 break;
6494 case FOP(21, 17):
6495 check_cp1_64bitmode(ctx);
6497 TCGv_i64 fp0 = tcg_temp_new_i64();
6499 gen_load_fpr64(ctx, fp0, fs);
6500 gen_helper_float_recip_d(fp0, fp0);
6501 gen_store_fpr64(ctx, fp0, fd);
6502 tcg_temp_free_i64(fp0);
6504 opn = "recip.d";
6505 break;
6506 case FOP(22, 17):
6507 check_cp1_64bitmode(ctx);
6509 TCGv_i64 fp0 = tcg_temp_new_i64();
6511 gen_load_fpr64(ctx, fp0, fs);
6512 gen_helper_float_rsqrt_d(fp0, fp0);
6513 gen_store_fpr64(ctx, fp0, fd);
6514 tcg_temp_free_i64(fp0);
6516 opn = "rsqrt.d";
6517 break;
6518 case FOP(28, 17):
6519 check_cp1_64bitmode(ctx);
6521 TCGv_i64 fp0 = tcg_temp_new_i64();
6522 TCGv_i64 fp1 = tcg_temp_new_i64();
6524 gen_load_fpr64(ctx, fp0, fs);
6525 gen_load_fpr64(ctx, fp1, ft);
6526 gen_helper_float_recip2_d(fp0, fp0, fp1);
6527 tcg_temp_free_i64(fp1);
6528 gen_store_fpr64(ctx, fp0, fd);
6529 tcg_temp_free_i64(fp0);
6531 opn = "recip2.d";
6532 break;
6533 case FOP(29, 17):
6534 check_cp1_64bitmode(ctx);
6536 TCGv_i64 fp0 = tcg_temp_new_i64();
6538 gen_load_fpr64(ctx, fp0, fs);
6539 gen_helper_float_recip1_d(fp0, fp0);
6540 gen_store_fpr64(ctx, fp0, fd);
6541 tcg_temp_free_i64(fp0);
6543 opn = "recip1.d";
6544 break;
6545 case FOP(30, 17):
6546 check_cp1_64bitmode(ctx);
6548 TCGv_i64 fp0 = tcg_temp_new_i64();
6550 gen_load_fpr64(ctx, fp0, fs);
6551 gen_helper_float_rsqrt1_d(fp0, fp0);
6552 gen_store_fpr64(ctx, fp0, fd);
6553 tcg_temp_free_i64(fp0);
6555 opn = "rsqrt1.d";
6556 break;
6557 case FOP(31, 17):
6558 check_cp1_64bitmode(ctx);
6560 TCGv_i64 fp0 = tcg_temp_new_i64();
6561 TCGv_i64 fp1 = tcg_temp_new_i64();
6563 gen_load_fpr64(ctx, fp0, fs);
6564 gen_load_fpr64(ctx, fp1, ft);
6565 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6566 tcg_temp_free_i64(fp1);
6567 gen_store_fpr64(ctx, fp0, fd);
6568 tcg_temp_free_i64(fp0);
6570 opn = "rsqrt2.d";
6571 break;
6572 case FOP(48, 17):
6573 case FOP(49, 17):
6574 case FOP(50, 17):
6575 case FOP(51, 17):
6576 case FOP(52, 17):
6577 case FOP(53, 17):
6578 case FOP(54, 17):
6579 case FOP(55, 17):
6580 case FOP(56, 17):
6581 case FOP(57, 17):
6582 case FOP(58, 17):
6583 case FOP(59, 17):
6584 case FOP(60, 17):
6585 case FOP(61, 17):
6586 case FOP(62, 17):
6587 case FOP(63, 17):
6589 TCGv_i64 fp0 = tcg_temp_new_i64();
6590 TCGv_i64 fp1 = tcg_temp_new_i64();
6592 gen_load_fpr64(ctx, fp0, fs);
6593 gen_load_fpr64(ctx, fp1, ft);
6594 if (ctx->opcode & (1 << 6)) {
6595 check_cop1x(ctx);
6596 check_cp1_registers(ctx, fs | ft);
6597 gen_cmpabs_d(func-48, fp0, fp1, cc);
6598 opn = condnames_abs[func-48];
6599 } else {
6600 check_cp1_registers(ctx, fs | ft);
6601 gen_cmp_d(func-48, fp0, fp1, cc);
6602 opn = condnames[func-48];
6604 tcg_temp_free_i64(fp0);
6605 tcg_temp_free_i64(fp1);
6607 break;
6608 case FOP(32, 17):
6609 check_cp1_registers(ctx, fs);
6611 TCGv_i32 fp32 = tcg_temp_new_i32();
6612 TCGv_i64 fp64 = tcg_temp_new_i64();
6614 gen_load_fpr64(ctx, fp64, fs);
6615 gen_helper_float_cvts_d(fp32, fp64);
6616 tcg_temp_free_i64(fp64);
6617 gen_store_fpr32(fp32, fd);
6618 tcg_temp_free_i32(fp32);
6620 opn = "cvt.s.d";
6621 break;
6622 case FOP(36, 17):
6623 check_cp1_registers(ctx, fs);
6625 TCGv_i32 fp32 = tcg_temp_new_i32();
6626 TCGv_i64 fp64 = tcg_temp_new_i64();
6628 gen_load_fpr64(ctx, fp64, fs);
6629 gen_helper_float_cvtw_d(fp32, fp64);
6630 tcg_temp_free_i64(fp64);
6631 gen_store_fpr32(fp32, fd);
6632 tcg_temp_free_i32(fp32);
6634 opn = "cvt.w.d";
6635 break;
6636 case FOP(37, 17):
6637 check_cp1_64bitmode(ctx);
6639 TCGv_i64 fp0 = tcg_temp_new_i64();
6641 gen_load_fpr64(ctx, fp0, fs);
6642 gen_helper_float_cvtl_d(fp0, fp0);
6643 gen_store_fpr64(ctx, fp0, fd);
6644 tcg_temp_free_i64(fp0);
6646 opn = "cvt.l.d";
6647 break;
6648 case FOP(32, 20):
6650 TCGv_i32 fp0 = tcg_temp_new_i32();
6652 gen_load_fpr32(fp0, fs);
6653 gen_helper_float_cvts_w(fp0, fp0);
6654 gen_store_fpr32(fp0, fd);
6655 tcg_temp_free_i32(fp0);
6657 opn = "cvt.s.w";
6658 break;
6659 case FOP(33, 20):
6660 check_cp1_registers(ctx, fd);
6662 TCGv_i32 fp32 = tcg_temp_new_i32();
6663 TCGv_i64 fp64 = tcg_temp_new_i64();
6665 gen_load_fpr32(fp32, fs);
6666 gen_helper_float_cvtd_w(fp64, fp32);
6667 tcg_temp_free_i32(fp32);
6668 gen_store_fpr64(ctx, fp64, fd);
6669 tcg_temp_free_i64(fp64);
6671 opn = "cvt.d.w";
6672 break;
6673 case FOP(32, 21):
6674 check_cp1_64bitmode(ctx);
6676 TCGv_i32 fp32 = tcg_temp_new_i32();
6677 TCGv_i64 fp64 = tcg_temp_new_i64();
6679 gen_load_fpr64(ctx, fp64, fs);
6680 gen_helper_float_cvts_l(fp32, fp64);
6681 tcg_temp_free_i64(fp64);
6682 gen_store_fpr32(fp32, fd);
6683 tcg_temp_free_i32(fp32);
6685 opn = "cvt.s.l";
6686 break;
6687 case FOP(33, 21):
6688 check_cp1_64bitmode(ctx);
6690 TCGv_i64 fp0 = tcg_temp_new_i64();
6692 gen_load_fpr64(ctx, fp0, fs);
6693 gen_helper_float_cvtd_l(fp0, fp0);
6694 gen_store_fpr64(ctx, fp0, fd);
6695 tcg_temp_free_i64(fp0);
6697 opn = "cvt.d.l";
6698 break;
6699 case FOP(38, 20):
6700 check_cp1_64bitmode(ctx);
6702 TCGv_i64 fp0 = tcg_temp_new_i64();
6704 gen_load_fpr64(ctx, fp0, fs);
6705 gen_helper_float_cvtps_pw(fp0, fp0);
6706 gen_store_fpr64(ctx, fp0, fd);
6707 tcg_temp_free_i64(fp0);
6709 opn = "cvt.ps.pw";
6710 break;
6711 case FOP(0, 22):
6712 check_cp1_64bitmode(ctx);
6714 TCGv_i64 fp0 = tcg_temp_new_i64();
6715 TCGv_i64 fp1 = tcg_temp_new_i64();
6717 gen_load_fpr64(ctx, fp0, fs);
6718 gen_load_fpr64(ctx, fp1, ft);
6719 gen_helper_float_add_ps(fp0, fp0, fp1);
6720 tcg_temp_free_i64(fp1);
6721 gen_store_fpr64(ctx, fp0, fd);
6722 tcg_temp_free_i64(fp0);
6724 opn = "add.ps";
6725 break;
6726 case FOP(1, 22):
6727 check_cp1_64bitmode(ctx);
6729 TCGv_i64 fp0 = tcg_temp_new_i64();
6730 TCGv_i64 fp1 = tcg_temp_new_i64();
6732 gen_load_fpr64(ctx, fp0, fs);
6733 gen_load_fpr64(ctx, fp1, ft);
6734 gen_helper_float_sub_ps(fp0, fp0, fp1);
6735 tcg_temp_free_i64(fp1);
6736 gen_store_fpr64(ctx, fp0, fd);
6737 tcg_temp_free_i64(fp0);
6739 opn = "sub.ps";
6740 break;
6741 case FOP(2, 22):
6742 check_cp1_64bitmode(ctx);
6744 TCGv_i64 fp0 = tcg_temp_new_i64();
6745 TCGv_i64 fp1 = tcg_temp_new_i64();
6747 gen_load_fpr64(ctx, fp0, fs);
6748 gen_load_fpr64(ctx, fp1, ft);
6749 gen_helper_float_mul_ps(fp0, fp0, fp1);
6750 tcg_temp_free_i64(fp1);
6751 gen_store_fpr64(ctx, fp0, fd);
6752 tcg_temp_free_i64(fp0);
6754 opn = "mul.ps";
6755 break;
6756 case FOP(5, 22):
6757 check_cp1_64bitmode(ctx);
6759 TCGv_i64 fp0 = tcg_temp_new_i64();
6761 gen_load_fpr64(ctx, fp0, fs);
6762 gen_helper_float_abs_ps(fp0, fp0);
6763 gen_store_fpr64(ctx, fp0, fd);
6764 tcg_temp_free_i64(fp0);
6766 opn = "abs.ps";
6767 break;
6768 case FOP(6, 22):
6769 check_cp1_64bitmode(ctx);
6771 TCGv_i64 fp0 = tcg_temp_new_i64();
6773 gen_load_fpr64(ctx, fp0, fs);
6774 gen_store_fpr64(ctx, fp0, fd);
6775 tcg_temp_free_i64(fp0);
6777 opn = "mov.ps";
6778 break;
6779 case FOP(7, 22):
6780 check_cp1_64bitmode(ctx);
6782 TCGv_i64 fp0 = tcg_temp_new_i64();
6784 gen_load_fpr64(ctx, fp0, fs);
6785 gen_helper_float_chs_ps(fp0, fp0);
6786 gen_store_fpr64(ctx, fp0, fd);
6787 tcg_temp_free_i64(fp0);
6789 opn = "neg.ps";
6790 break;
6791 case FOP(17, 22):
6792 check_cp1_64bitmode(ctx);
6793 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6794 opn = "movcf.ps";
6795 break;
6796 case FOP(18, 22):
6797 check_cp1_64bitmode(ctx);
6799 int l1 = gen_new_label();
6800 TCGv t0 = tcg_temp_new();
6801 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6802 TCGv_i32 fph0 = tcg_temp_local_new_i32();
6804 gen_load_gpr(t0, ft);
6805 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6806 gen_load_fpr32(fp0, fs);
6807 gen_load_fpr32h(fph0, fs);
6808 gen_store_fpr32(fp0, fd);
6809 gen_store_fpr32h(fph0, fd);
6810 tcg_temp_free_i32(fp0);
6811 tcg_temp_free_i32(fph0);
6812 gen_set_label(l1);
6813 tcg_temp_free(t0);
6815 opn = "movz.ps";
6816 break;
6817 case FOP(19, 22):
6818 check_cp1_64bitmode(ctx);
6820 int l1 = gen_new_label();
6821 TCGv t0 = tcg_temp_new();
6822 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6823 TCGv_i32 fph0 = tcg_temp_local_new_i32();
6825 gen_load_gpr(t0, ft);
6826 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6827 gen_load_fpr32(fp0, fs);
6828 gen_load_fpr32h(fph0, fs);
6829 gen_store_fpr32(fp0, fd);
6830 gen_store_fpr32h(fph0, fd);
6831 tcg_temp_free_i32(fp0);
6832 tcg_temp_free_i32(fph0);
6833 gen_set_label(l1);
6834 tcg_temp_free(t0);
6836 opn = "movn.ps";
6837 break;
6838 case FOP(24, 22):
6839 check_cp1_64bitmode(ctx);
6841 TCGv_i64 fp0 = tcg_temp_new_i64();
6842 TCGv_i64 fp1 = tcg_temp_new_i64();
6844 gen_load_fpr64(ctx, fp0, ft);
6845 gen_load_fpr64(ctx, fp1, fs);
6846 gen_helper_float_addr_ps(fp0, fp0, fp1);
6847 tcg_temp_free_i64(fp1);
6848 gen_store_fpr64(ctx, fp0, fd);
6849 tcg_temp_free_i64(fp0);
6851 opn = "addr.ps";
6852 break;
6853 case FOP(26, 22):
6854 check_cp1_64bitmode(ctx);
6856 TCGv_i64 fp0 = tcg_temp_new_i64();
6857 TCGv_i64 fp1 = tcg_temp_new_i64();
6859 gen_load_fpr64(ctx, fp0, ft);
6860 gen_load_fpr64(ctx, fp1, fs);
6861 gen_helper_float_mulr_ps(fp0, fp0, fp1);
6862 tcg_temp_free_i64(fp1);
6863 gen_store_fpr64(ctx, fp0, fd);
6864 tcg_temp_free_i64(fp0);
6866 opn = "mulr.ps";
6867 break;
6868 case FOP(28, 22):
6869 check_cp1_64bitmode(ctx);
6871 TCGv_i64 fp0 = tcg_temp_new_i64();
6872 TCGv_i64 fp1 = tcg_temp_new_i64();
6874 gen_load_fpr64(ctx, fp0, fs);
6875 gen_load_fpr64(ctx, fp1, fd);
6876 gen_helper_float_recip2_ps(fp0, fp0, fp1);
6877 tcg_temp_free_i64(fp1);
6878 gen_store_fpr64(ctx, fp0, fd);
6879 tcg_temp_free_i64(fp0);
6881 opn = "recip2.ps";
6882 break;
6883 case FOP(29, 22):
6884 check_cp1_64bitmode(ctx);
6886 TCGv_i64 fp0 = tcg_temp_new_i64();
6888 gen_load_fpr64(ctx, fp0, fs);
6889 gen_helper_float_recip1_ps(fp0, fp0);
6890 gen_store_fpr64(ctx, fp0, fd);
6891 tcg_temp_free_i64(fp0);
6893 opn = "recip1.ps";
6894 break;
6895 case FOP(30, 22):
6896 check_cp1_64bitmode(ctx);
6898 TCGv_i64 fp0 = tcg_temp_new_i64();
6900 gen_load_fpr64(ctx, fp0, fs);
6901 gen_helper_float_rsqrt1_ps(fp0, fp0);
6902 gen_store_fpr64(ctx, fp0, fd);
6903 tcg_temp_free_i64(fp0);
6905 opn = "rsqrt1.ps";
6906 break;
6907 case FOP(31, 22):
6908 check_cp1_64bitmode(ctx);
6910 TCGv_i64 fp0 = tcg_temp_new_i64();
6911 TCGv_i64 fp1 = tcg_temp_new_i64();
6913 gen_load_fpr64(ctx, fp0, fs);
6914 gen_load_fpr64(ctx, fp1, ft);
6915 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
6916 tcg_temp_free_i64(fp1);
6917 gen_store_fpr64(ctx, fp0, fd);
6918 tcg_temp_free_i64(fp0);
6920 opn = "rsqrt2.ps";
6921 break;
6922 case FOP(32, 22):
6923 check_cp1_64bitmode(ctx);
6925 TCGv_i32 fp0 = tcg_temp_new_i32();
6927 gen_load_fpr32h(fp0, fs);
6928 gen_helper_float_cvts_pu(fp0, fp0);
6929 gen_store_fpr32(fp0, fd);
6930 tcg_temp_free_i32(fp0);
6932 opn = "cvt.s.pu";
6933 break;
6934 case FOP(36, 22):
6935 check_cp1_64bitmode(ctx);
6937 TCGv_i64 fp0 = tcg_temp_new_i64();
6939 gen_load_fpr64(ctx, fp0, fs);
6940 gen_helper_float_cvtpw_ps(fp0, fp0);
6941 gen_store_fpr64(ctx, fp0, fd);
6942 tcg_temp_free_i64(fp0);
6944 opn = "cvt.pw.ps";
6945 break;
6946 case FOP(40, 22):
6947 check_cp1_64bitmode(ctx);
6949 TCGv_i32 fp0 = tcg_temp_new_i32();
6951 gen_load_fpr32(fp0, fs);
6952 gen_helper_float_cvts_pl(fp0, fp0);
6953 gen_store_fpr32(fp0, fd);
6954 tcg_temp_free_i32(fp0);
6956 opn = "cvt.s.pl";
6957 break;
6958 case FOP(44, 22):
6959 check_cp1_64bitmode(ctx);
6961 TCGv_i32 fp0 = tcg_temp_new_i32();
6962 TCGv_i32 fp1 = tcg_temp_new_i32();
6964 gen_load_fpr32(fp0, fs);
6965 gen_load_fpr32(fp1, ft);
6966 gen_store_fpr32h(fp0, fd);
6967 gen_store_fpr32(fp1, fd);
6968 tcg_temp_free_i32(fp0);
6969 tcg_temp_free_i32(fp1);
6971 opn = "pll.ps";
6972 break;
6973 case FOP(45, 22):
6974 check_cp1_64bitmode(ctx);
6976 TCGv_i32 fp0 = tcg_temp_new_i32();
6977 TCGv_i32 fp1 = tcg_temp_new_i32();
6979 gen_load_fpr32(fp0, fs);
6980 gen_load_fpr32h(fp1, ft);
6981 gen_store_fpr32(fp1, fd);
6982 gen_store_fpr32h(fp0, fd);
6983 tcg_temp_free_i32(fp0);
6984 tcg_temp_free_i32(fp1);
6986 opn = "plu.ps";
6987 break;
6988 case FOP(46, 22):
6989 check_cp1_64bitmode(ctx);
6991 TCGv_i32 fp0 = tcg_temp_new_i32();
6992 TCGv_i32 fp1 = tcg_temp_new_i32();
6994 gen_load_fpr32h(fp0, fs);
6995 gen_load_fpr32(fp1, ft);
6996 gen_store_fpr32(fp1, fd);
6997 gen_store_fpr32h(fp0, fd);
6998 tcg_temp_free_i32(fp0);
6999 tcg_temp_free_i32(fp1);
7001 opn = "pul.ps";
7002 break;
7003 case FOP(47, 22):
7004 check_cp1_64bitmode(ctx);
7006 TCGv_i32 fp0 = tcg_temp_new_i32();
7007 TCGv_i32 fp1 = tcg_temp_new_i32();
7009 gen_load_fpr32h(fp0, fs);
7010 gen_load_fpr32h(fp1, ft);
7011 gen_store_fpr32(fp1, fd);
7012 gen_store_fpr32h(fp0, fd);
7013 tcg_temp_free_i32(fp0);
7014 tcg_temp_free_i32(fp1);
7016 opn = "puu.ps";
7017 break;
7018 case FOP(48, 22):
7019 case FOP(49, 22):
7020 case FOP(50, 22):
7021 case FOP(51, 22):
7022 case FOP(52, 22):
7023 case FOP(53, 22):
7024 case FOP(54, 22):
7025 case FOP(55, 22):
7026 case FOP(56, 22):
7027 case FOP(57, 22):
7028 case FOP(58, 22):
7029 case FOP(59, 22):
7030 case FOP(60, 22):
7031 case FOP(61, 22):
7032 case FOP(62, 22):
7033 case FOP(63, 22):
7034 check_cp1_64bitmode(ctx);
7036 TCGv_i64 fp0 = tcg_temp_new_i64();
7037 TCGv_i64 fp1 = tcg_temp_new_i64();
7039 gen_load_fpr64(ctx, fp0, fs);
7040 gen_load_fpr64(ctx, fp1, ft);
7041 if (ctx->opcode & (1 << 6)) {
7042 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7043 opn = condnames_abs[func-48];
7044 } else {
7045 gen_cmp_ps(func-48, fp0, fp1, cc);
7046 opn = condnames[func-48];
7048 tcg_temp_free_i64(fp0);
7049 tcg_temp_free_i64(fp1);
7051 break;
7052 default:
7053 MIPS_INVAL(opn);
7054 generate_exception (ctx, EXCP_RI);
7055 return;
7057 switch (optype) {
7058 case BINOP:
7059 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7060 break;
7061 case CMPOP:
7062 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7063 break;
7064 default:
7065 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7066 break;
7070 /* Coprocessor 3 (FPU) */
7071 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7072 int fd, int fs, int base, int index)
7074 const char *opn = "extended float load/store";
7075 int store = 0;
7076 TCGv t0 = tcg_temp_local_new();
7077 TCGv t1 = tcg_temp_local_new();
7079 if (base == 0) {
7080 gen_load_gpr(t0, index);
7081 } else if (index == 0) {
7082 gen_load_gpr(t0, base);
7083 } else {
7084 gen_load_gpr(t0, index);
7085 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
7087 /* Don't do NOP if destination is zero: we must perform the actual
7088 memory access. */
7089 switch (opc) {
7090 case OPC_LWXC1:
7091 check_cop1x(ctx);
7093 TCGv_i32 fp0 = tcg_temp_new_i32();
7095 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
7096 tcg_gen_trunc_tl_i32(fp0, t1);
7097 gen_store_fpr32(fp0, fd);
7098 tcg_temp_free_i32(fp0);
7100 opn = "lwxc1";
7101 break;
7102 case OPC_LDXC1:
7103 check_cop1x(ctx);
7104 check_cp1_registers(ctx, fd);
7106 TCGv_i64 fp0 = tcg_temp_new_i64();
7108 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7109 gen_store_fpr64(ctx, fp0, fd);
7110 tcg_temp_free_i64(fp0);
7112 opn = "ldxc1";
7113 break;
7114 case OPC_LUXC1:
7115 check_cp1_64bitmode(ctx);
7116 tcg_gen_andi_tl(t0, t0, ~0x7);
7118 TCGv_i64 fp0 = tcg_temp_new_i64();
7120 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7121 gen_store_fpr64(ctx, fp0, fd);
7122 tcg_temp_free_i64(fp0);
7124 opn = "luxc1";
7125 break;
7126 case OPC_SWXC1:
7127 check_cop1x(ctx);
7129 TCGv_i32 fp0 = tcg_temp_new_i32();
7131 gen_load_fpr32(fp0, fs);
7132 tcg_gen_extu_i32_tl(t1, fp0);
7133 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7134 tcg_temp_free_i32(fp0);
7136 opn = "swxc1";
7137 store = 1;
7138 break;
7139 case OPC_SDXC1:
7140 check_cop1x(ctx);
7141 check_cp1_registers(ctx, fs);
7143 TCGv_i64 fp0 = tcg_temp_new_i64();
7145 gen_load_fpr64(ctx, fp0, fs);
7146 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7147 tcg_temp_free_i64(fp0);
7149 opn = "sdxc1";
7150 store = 1;
7151 break;
7152 case OPC_SUXC1:
7153 check_cp1_64bitmode(ctx);
7154 tcg_gen_andi_tl(t0, t0, ~0x7);
7156 TCGv_i64 fp0 = tcg_temp_new_i64();
7158 gen_load_fpr64(ctx, fp0, fs);
7159 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7160 tcg_temp_free_i64(fp0);
7162 opn = "suxc1";
7163 store = 1;
7164 break;
7165 default:
7166 MIPS_INVAL(opn);
7167 generate_exception(ctx, EXCP_RI);
7168 tcg_temp_free(t0);
7169 tcg_temp_free(t1);
7170 return;
7172 tcg_temp_free(t0);
7173 tcg_temp_free(t1);
7174 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7175 regnames[index], regnames[base]);
7178 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7179 int fd, int fr, int fs, int ft)
7181 const char *opn = "flt3_arith";
7183 switch (opc) {
7184 case OPC_ALNV_PS:
7185 check_cp1_64bitmode(ctx);
7187 TCGv t0 = tcg_temp_local_new();
7188 TCGv_i32 fp0 = tcg_temp_local_new_i32();
7189 TCGv_i32 fph0 = tcg_temp_local_new_i32();
7190 TCGv_i32 fp1 = tcg_temp_local_new_i32();
7191 TCGv_i32 fph1 = tcg_temp_local_new_i32();
7192 int l1 = gen_new_label();
7193 int l2 = gen_new_label();
7195 gen_load_gpr(t0, fr);
7196 tcg_gen_andi_tl(t0, t0, 0x7);
7197 gen_load_fpr32(fp0, fs);
7198 gen_load_fpr32h(fph0, fs);
7199 gen_load_fpr32(fp1, ft);
7200 gen_load_fpr32h(fph1, ft);
7202 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7203 gen_store_fpr32(fp0, fd);
7204 gen_store_fpr32h(fph0, fd);
7205 tcg_gen_br(l2);
7206 gen_set_label(l1);
7207 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7208 tcg_temp_free(t0);
7209 #ifdef TARGET_WORDS_BIGENDIAN
7210 gen_store_fpr32(fph1, fd);
7211 gen_store_fpr32h(fp0, fd);
7212 #else
7213 gen_store_fpr32(fph0, fd);
7214 gen_store_fpr32h(fp1, fd);
7215 #endif
7216 gen_set_label(l2);
7217 tcg_temp_free_i32(fp0);
7218 tcg_temp_free_i32(fph0);
7219 tcg_temp_free_i32(fp1);
7220 tcg_temp_free_i32(fph1);
7222 opn = "alnv.ps";
7223 break;
7224 case OPC_MADD_S:
7225 check_cop1x(ctx);
7227 TCGv_i32 fp0 = tcg_temp_new_i32();
7228 TCGv_i32 fp1 = tcg_temp_new_i32();
7229 TCGv_i32 fp2 = tcg_temp_new_i32();
7231 gen_load_fpr32(fp0, fs);
7232 gen_load_fpr32(fp1, ft);
7233 gen_load_fpr32(fp2, fr);
7234 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7235 tcg_temp_free_i32(fp0);
7236 tcg_temp_free_i32(fp1);
7237 gen_store_fpr32(fp2, fd);
7238 tcg_temp_free_i32(fp2);
7240 opn = "madd.s";
7241 break;
7242 case OPC_MADD_D:
7243 check_cop1x(ctx);
7244 check_cp1_registers(ctx, fd | fs | ft | fr);
7246 TCGv_i64 fp0 = tcg_temp_new_i64();
7247 TCGv_i64 fp1 = tcg_temp_new_i64();
7248 TCGv_i64 fp2 = tcg_temp_new_i64();
7250 gen_load_fpr64(ctx, fp0, fs);
7251 gen_load_fpr64(ctx, fp1, ft);
7252 gen_load_fpr64(ctx, fp2, fr);
7253 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7254 tcg_temp_free_i64(fp0);
7255 tcg_temp_free_i64(fp1);
7256 gen_store_fpr64(ctx, fp2, fd);
7257 tcg_temp_free_i64(fp2);
7259 opn = "madd.d";
7260 break;
7261 case OPC_MADD_PS:
7262 check_cp1_64bitmode(ctx);
7264 TCGv_i64 fp0 = tcg_temp_new_i64();
7265 TCGv_i64 fp1 = tcg_temp_new_i64();
7266 TCGv_i64 fp2 = tcg_temp_new_i64();
7268 gen_load_fpr64(ctx, fp0, fs);
7269 gen_load_fpr64(ctx, fp1, ft);
7270 gen_load_fpr64(ctx, fp2, fr);
7271 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7272 tcg_temp_free_i64(fp0);
7273 tcg_temp_free_i64(fp1);
7274 gen_store_fpr64(ctx, fp2, fd);
7275 tcg_temp_free_i64(fp2);
7277 opn = "madd.ps";
7278 break;
7279 case OPC_MSUB_S:
7280 check_cop1x(ctx);
7282 TCGv_i32 fp0 = tcg_temp_new_i32();
7283 TCGv_i32 fp1 = tcg_temp_new_i32();
7284 TCGv_i32 fp2 = tcg_temp_new_i32();
7286 gen_load_fpr32(fp0, fs);
7287 gen_load_fpr32(fp1, ft);
7288 gen_load_fpr32(fp2, fr);
7289 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7290 tcg_temp_free_i32(fp0);
7291 tcg_temp_free_i32(fp1);
7292 gen_store_fpr32(fp2, fd);
7293 tcg_temp_free_i32(fp2);
7295 opn = "msub.s";
7296 break;
7297 case OPC_MSUB_D:
7298 check_cop1x(ctx);
7299 check_cp1_registers(ctx, fd | fs | ft | fr);
7301 TCGv_i64 fp0 = tcg_temp_new_i64();
7302 TCGv_i64 fp1 = tcg_temp_new_i64();
7303 TCGv_i64 fp2 = tcg_temp_new_i64();
7305 gen_load_fpr64(ctx, fp0, fs);
7306 gen_load_fpr64(ctx, fp1, ft);
7307 gen_load_fpr64(ctx, fp2, fr);
7308 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7309 tcg_temp_free_i64(fp0);
7310 tcg_temp_free_i64(fp1);
7311 gen_store_fpr64(ctx, fp2, fd);
7312 tcg_temp_free_i64(fp2);
7314 opn = "msub.d";
7315 break;
7316 case OPC_MSUB_PS:
7317 check_cp1_64bitmode(ctx);
7319 TCGv_i64 fp0 = tcg_temp_new_i64();
7320 TCGv_i64 fp1 = tcg_temp_new_i64();
7321 TCGv_i64 fp2 = tcg_temp_new_i64();
7323 gen_load_fpr64(ctx, fp0, fs);
7324 gen_load_fpr64(ctx, fp1, ft);
7325 gen_load_fpr64(ctx, fp2, fr);
7326 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7327 tcg_temp_free_i64(fp0);
7328 tcg_temp_free_i64(fp1);
7329 gen_store_fpr64(ctx, fp2, fd);
7330 tcg_temp_free_i64(fp2);
7332 opn = "msub.ps";
7333 break;
7334 case OPC_NMADD_S:
7335 check_cop1x(ctx);
7337 TCGv_i32 fp0 = tcg_temp_new_i32();
7338 TCGv_i32 fp1 = tcg_temp_new_i32();
7339 TCGv_i32 fp2 = tcg_temp_new_i32();
7341 gen_load_fpr32(fp0, fs);
7342 gen_load_fpr32(fp1, ft);
7343 gen_load_fpr32(fp2, fr);
7344 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7345 tcg_temp_free_i32(fp0);
7346 tcg_temp_free_i32(fp1);
7347 gen_store_fpr32(fp2, fd);
7348 tcg_temp_free_i32(fp2);
7350 opn = "nmadd.s";
7351 break;
7352 case OPC_NMADD_D:
7353 check_cop1x(ctx);
7354 check_cp1_registers(ctx, fd | fs | ft | fr);
7356 TCGv_i64 fp0 = tcg_temp_new_i64();
7357 TCGv_i64 fp1 = tcg_temp_new_i64();
7358 TCGv_i64 fp2 = tcg_temp_new_i64();
7360 gen_load_fpr64(ctx, fp0, fs);
7361 gen_load_fpr64(ctx, fp1, ft);
7362 gen_load_fpr64(ctx, fp2, fr);
7363 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7364 tcg_temp_free_i64(fp0);
7365 tcg_temp_free_i64(fp1);
7366 gen_store_fpr64(ctx, fp2, fd);
7367 tcg_temp_free_i64(fp2);
7369 opn = "nmadd.d";
7370 break;
7371 case OPC_NMADD_PS:
7372 check_cp1_64bitmode(ctx);
7374 TCGv_i64 fp0 = tcg_temp_new_i64();
7375 TCGv_i64 fp1 = tcg_temp_new_i64();
7376 TCGv_i64 fp2 = tcg_temp_new_i64();
7378 gen_load_fpr64(ctx, fp0, fs);
7379 gen_load_fpr64(ctx, fp1, ft);
7380 gen_load_fpr64(ctx, fp2, fr);
7381 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7382 tcg_temp_free_i64(fp0);
7383 tcg_temp_free_i64(fp1);
7384 gen_store_fpr64(ctx, fp2, fd);
7385 tcg_temp_free_i64(fp2);
7387 opn = "nmadd.ps";
7388 break;
7389 case OPC_NMSUB_S:
7390 check_cop1x(ctx);
7392 TCGv_i32 fp0 = tcg_temp_new_i32();
7393 TCGv_i32 fp1 = tcg_temp_new_i32();
7394 TCGv_i32 fp2 = tcg_temp_new_i32();
7396 gen_load_fpr32(fp0, fs);
7397 gen_load_fpr32(fp1, ft);
7398 gen_load_fpr32(fp2, fr);
7399 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7400 tcg_temp_free_i32(fp0);
7401 tcg_temp_free_i32(fp1);
7402 gen_store_fpr32(fp2, fd);
7403 tcg_temp_free_i32(fp2);
7405 opn = "nmsub.s";
7406 break;
7407 case OPC_NMSUB_D:
7408 check_cop1x(ctx);
7409 check_cp1_registers(ctx, fd | fs | ft | fr);
7411 TCGv_i64 fp0 = tcg_temp_new_i64();
7412 TCGv_i64 fp1 = tcg_temp_new_i64();
7413 TCGv_i64 fp2 = tcg_temp_new_i64();
7415 gen_load_fpr64(ctx, fp0, fs);
7416 gen_load_fpr64(ctx, fp1, ft);
7417 gen_load_fpr64(ctx, fp2, fr);
7418 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7419 tcg_temp_free_i64(fp0);
7420 tcg_temp_free_i64(fp1);
7421 gen_store_fpr64(ctx, fp2, fd);
7422 tcg_temp_free_i64(fp2);
7424 opn = "nmsub.d";
7425 break;
7426 case OPC_NMSUB_PS:
7427 check_cp1_64bitmode(ctx);
7429 TCGv_i64 fp0 = tcg_temp_new_i64();
7430 TCGv_i64 fp1 = tcg_temp_new_i64();
7431 TCGv_i64 fp2 = tcg_temp_new_i64();
7433 gen_load_fpr64(ctx, fp0, fs);
7434 gen_load_fpr64(ctx, fp1, ft);
7435 gen_load_fpr64(ctx, fp2, fr);
7436 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7437 tcg_temp_free_i64(fp0);
7438 tcg_temp_free_i64(fp1);
7439 gen_store_fpr64(ctx, fp2, fd);
7440 tcg_temp_free_i64(fp2);
7442 opn = "nmsub.ps";
7443 break;
7444 default:
7445 MIPS_INVAL(opn);
7446 generate_exception (ctx, EXCP_RI);
7447 return;
7449 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7450 fregnames[fs], fregnames[ft]);
7453 /* ISA extensions (ASEs) */
7454 /* MIPS16 extension to MIPS32 */
7455 /* SmartMIPS extension to MIPS32 */
7457 #if defined(TARGET_MIPS64)
7459 /* MDMX extension to MIPS64 */
7461 #endif
7463 static void decode_opc (CPUState *env, DisasContext *ctx)
7465 int32_t offset;
7466 int rs, rt, rd, sa;
7467 uint32_t op, op1, op2;
7468 int16_t imm;
7470 /* make sure instructions are on a word boundary */
7471 if (ctx->pc & 0x3) {
7472 env->CP0_BadVAddr = ctx->pc;
7473 generate_exception(ctx, EXCP_AdEL);
7474 return;
7477 /* Handle blikely not taken case */
7478 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7479 int l1 = gen_new_label();
7481 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7482 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7483 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
7484 gen_goto_tb(ctx, 1, ctx->pc + 4);
7485 gen_set_label(l1);
7487 op = MASK_OP_MAJOR(ctx->opcode);
7488 rs = (ctx->opcode >> 21) & 0x1f;
7489 rt = (ctx->opcode >> 16) & 0x1f;
7490 rd = (ctx->opcode >> 11) & 0x1f;
7491 sa = (ctx->opcode >> 6) & 0x1f;
7492 imm = (int16_t)ctx->opcode;
7493 switch (op) {
7494 case OPC_SPECIAL:
7495 op1 = MASK_SPECIAL(ctx->opcode);
7496 switch (op1) {
7497 case OPC_SLL: /* Arithmetic with immediate */
7498 case OPC_SRL ... OPC_SRA:
7499 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7500 break;
7501 case OPC_MOVZ ... OPC_MOVN:
7502 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7503 case OPC_SLLV: /* Arithmetic */
7504 case OPC_SRLV ... OPC_SRAV:
7505 case OPC_ADD ... OPC_NOR:
7506 case OPC_SLT ... OPC_SLTU:
7507 gen_arith(env, ctx, op1, rd, rs, rt);
7508 break;
7509 case OPC_MULT ... OPC_DIVU:
7510 if (sa) {
7511 check_insn(env, ctx, INSN_VR54XX);
7512 op1 = MASK_MUL_VR54XX(ctx->opcode);
7513 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7514 } else
7515 gen_muldiv(ctx, op1, rs, rt);
7516 break;
7517 case OPC_JR ... OPC_JALR:
7518 gen_compute_branch(ctx, op1, rs, rd, sa);
7519 return;
7520 case OPC_TGE ... OPC_TEQ: /* Traps */
7521 case OPC_TNE:
7522 gen_trap(ctx, op1, rs, rt, -1);
7523 break;
7524 case OPC_MFHI: /* Move from HI/LO */
7525 case OPC_MFLO:
7526 gen_HILO(ctx, op1, rd);
7527 break;
7528 case OPC_MTHI:
7529 case OPC_MTLO: /* Move to HI/LO */
7530 gen_HILO(ctx, op1, rs);
7531 break;
7532 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7533 #ifdef MIPS_STRICT_STANDARD
7534 MIPS_INVAL("PMON / selsl");
7535 generate_exception(ctx, EXCP_RI);
7536 #else
7537 gen_helper_0i(pmon, sa);
7538 #endif
7539 break;
7540 case OPC_SYSCALL:
7541 generate_exception(ctx, EXCP_SYSCALL);
7542 break;
7543 case OPC_BREAK:
7544 generate_exception(ctx, EXCP_BREAK);
7545 break;
7546 case OPC_SPIM:
7547 #ifdef MIPS_STRICT_STANDARD
7548 MIPS_INVAL("SPIM");
7549 generate_exception(ctx, EXCP_RI);
7550 #else
7551 /* Implemented as RI exception for now. */
7552 MIPS_INVAL("spim (unofficial)");
7553 generate_exception(ctx, EXCP_RI);
7554 #endif
7555 break;
7556 case OPC_SYNC:
7557 /* Treat as NOP. */
7558 break;
7560 case OPC_MOVCI:
7561 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7562 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7563 save_cpu_state(ctx, 1);
7564 check_cp1_enabled(ctx);
7565 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7566 (ctx->opcode >> 16) & 1);
7567 } else {
7568 generate_exception_err(ctx, EXCP_CpU, 1);
7570 break;
7572 #if defined(TARGET_MIPS64)
7573 /* MIPS64 specific opcodes */
7574 case OPC_DSLL:
7575 case OPC_DSRL ... OPC_DSRA:
7576 case OPC_DSLL32:
7577 case OPC_DSRL32 ... OPC_DSRA32:
7578 check_insn(env, ctx, ISA_MIPS3);
7579 check_mips_64(ctx);
7580 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7581 break;
7582 case OPC_DSLLV:
7583 case OPC_DSRLV ... OPC_DSRAV:
7584 case OPC_DADD ... OPC_DSUBU:
7585 check_insn(env, ctx, ISA_MIPS3);
7586 check_mips_64(ctx);
7587 gen_arith(env, ctx, op1, rd, rs, rt);
7588 break;
7589 case OPC_DMULT ... OPC_DDIVU:
7590 check_insn(env, ctx, ISA_MIPS3);
7591 check_mips_64(ctx);
7592 gen_muldiv(ctx, op1, rs, rt);
7593 break;
7594 #endif
7595 default: /* Invalid */
7596 MIPS_INVAL("special");
7597 generate_exception(ctx, EXCP_RI);
7598 break;
7600 break;
7601 case OPC_SPECIAL2:
7602 op1 = MASK_SPECIAL2(ctx->opcode);
7603 switch (op1) {
7604 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7605 case OPC_MSUB ... OPC_MSUBU:
7606 check_insn(env, ctx, ISA_MIPS32);
7607 gen_muldiv(ctx, op1, rs, rt);
7608 break;
7609 case OPC_MUL:
7610 gen_arith(env, ctx, op1, rd, rs, rt);
7611 break;
7612 case OPC_CLO:
7613 case OPC_CLZ:
7614 check_insn(env, ctx, ISA_MIPS32);
7615 gen_cl(ctx, op1, rd, rs);
7616 break;
7617 case OPC_SDBBP:
7618 /* XXX: not clear which exception should be raised
7619 * when in debug mode...
7621 check_insn(env, ctx, ISA_MIPS32);
7622 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7623 generate_exception(ctx, EXCP_DBp);
7624 } else {
7625 generate_exception(ctx, EXCP_DBp);
7627 /* Treat as NOP. */
7628 break;
7629 #if defined(TARGET_MIPS64)
7630 case OPC_DCLO:
7631 case OPC_DCLZ:
7632 check_insn(env, ctx, ISA_MIPS64);
7633 check_mips_64(ctx);
7634 gen_cl(ctx, op1, rd, rs);
7635 break;
7636 #endif
7637 default: /* Invalid */
7638 MIPS_INVAL("special2");
7639 generate_exception(ctx, EXCP_RI);
7640 break;
7642 break;
7643 case OPC_SPECIAL3:
7644 op1 = MASK_SPECIAL3(ctx->opcode);
7645 switch (op1) {
7646 case OPC_EXT:
7647 case OPC_INS:
7648 check_insn(env, ctx, ISA_MIPS32R2);
7649 gen_bitops(ctx, op1, rt, rs, sa, rd);
7650 break;
7651 case OPC_BSHFL:
7652 check_insn(env, ctx, ISA_MIPS32R2);
7653 op2 = MASK_BSHFL(ctx->opcode);
7654 gen_bshfl(ctx, op2, rt, rd);
7655 break;
7656 case OPC_RDHWR:
7657 check_insn(env, ctx, ISA_MIPS32R2);
7659 TCGv t0 = tcg_temp_local_new();
7661 switch (rd) {
7662 case 0:
7663 save_cpu_state(ctx, 1);
7664 gen_helper_rdhwr_cpunum(t0);
7665 break;
7666 case 1:
7667 save_cpu_state(ctx, 1);
7668 gen_helper_rdhwr_synci_step(t0);
7669 break;
7670 case 2:
7671 save_cpu_state(ctx, 1);
7672 gen_helper_rdhwr_cc(t0);
7673 break;
7674 case 3:
7675 save_cpu_state(ctx, 1);
7676 gen_helper_rdhwr_ccres(t0);
7677 break;
7678 case 29:
7679 #if defined(CONFIG_USER_ONLY)
7680 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7681 break;
7682 #else
7683 /* XXX: Some CPUs implement this in hardware.
7684 Not supported yet. */
7685 #endif
7686 default: /* Invalid */
7687 MIPS_INVAL("rdhwr");
7688 generate_exception(ctx, EXCP_RI);
7689 break;
7691 gen_store_gpr(t0, rt);
7692 tcg_temp_free(t0);
7694 break;
7695 case OPC_FORK:
7696 check_insn(env, ctx, ASE_MT);
7698 TCGv t0 = tcg_temp_local_new();
7699 TCGv t1 = tcg_temp_local_new();
7701 gen_load_gpr(t0, rt);
7702 gen_load_gpr(t1, rs);
7703 gen_helper_fork(t0, t1);
7704 tcg_temp_free(t0);
7705 tcg_temp_free(t1);
7707 break;
7708 case OPC_YIELD:
7709 check_insn(env, ctx, ASE_MT);
7711 TCGv t0 = tcg_temp_local_new();
7713 gen_load_gpr(t0, rs);
7714 gen_helper_yield(t0, t0);
7715 gen_store_gpr(t0, rd);
7716 tcg_temp_free(t0);
7718 break;
7719 #if defined(TARGET_MIPS64)
7720 case OPC_DEXTM ... OPC_DEXT:
7721 case OPC_DINSM ... OPC_DINS:
7722 check_insn(env, ctx, ISA_MIPS64R2);
7723 check_mips_64(ctx);
7724 gen_bitops(ctx, op1, rt, rs, sa, rd);
7725 break;
7726 case OPC_DBSHFL:
7727 check_insn(env, ctx, ISA_MIPS64R2);
7728 check_mips_64(ctx);
7729 op2 = MASK_DBSHFL(ctx->opcode);
7730 gen_bshfl(ctx, op2, rt, rd);
7731 break;
7732 #endif
7733 default: /* Invalid */
7734 MIPS_INVAL("special3");
7735 generate_exception(ctx, EXCP_RI);
7736 break;
7738 break;
7739 case OPC_REGIMM:
7740 op1 = MASK_REGIMM(ctx->opcode);
7741 switch (op1) {
7742 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7743 case OPC_BLTZAL ... OPC_BGEZALL:
7744 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
7745 return;
7746 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7747 case OPC_TNEI:
7748 gen_trap(ctx, op1, rs, -1, imm);
7749 break;
7750 case OPC_SYNCI:
7751 check_insn(env, ctx, ISA_MIPS32R2);
7752 /* Treat as NOP. */
7753 break;
7754 default: /* Invalid */
7755 MIPS_INVAL("regimm");
7756 generate_exception(ctx, EXCP_RI);
7757 break;
7759 break;
7760 case OPC_CP0:
7761 check_cp0_enabled(ctx);
7762 op1 = MASK_CP0(ctx->opcode);
7763 switch (op1) {
7764 case OPC_MFC0:
7765 case OPC_MTC0:
7766 case OPC_MFTR:
7767 case OPC_MTTR:
7768 #if defined(TARGET_MIPS64)
7769 case OPC_DMFC0:
7770 case OPC_DMTC0:
7771 #endif
7772 #ifndef CONFIG_USER_ONLY
7773 gen_cp0(env, ctx, op1, rt, rd);
7774 #endif /* !CONFIG_USER_ONLY */
7775 break;
7776 case OPC_C0_FIRST ... OPC_C0_LAST:
7777 #ifndef CONFIG_USER_ONLY
7778 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
7779 #endif /* !CONFIG_USER_ONLY */
7780 break;
7781 case OPC_MFMC0:
7782 #ifndef CONFIG_USER_ONLY
7784 TCGv t0 = tcg_temp_local_new();
7786 op2 = MASK_MFMC0(ctx->opcode);
7787 switch (op2) {
7788 case OPC_DMT:
7789 check_insn(env, ctx, ASE_MT);
7790 gen_helper_dmt(t0, t0);
7791 break;
7792 case OPC_EMT:
7793 check_insn(env, ctx, ASE_MT);
7794 gen_helper_emt(t0, t0);
7795 break;
7796 case OPC_DVPE:
7797 check_insn(env, ctx, ASE_MT);
7798 gen_helper_dvpe(t0, t0);
7799 break;
7800 case OPC_EVPE:
7801 check_insn(env, ctx, ASE_MT);
7802 gen_helper_evpe(t0, t0);
7803 break;
7804 case OPC_DI:
7805 check_insn(env, ctx, ISA_MIPS32R2);
7806 save_cpu_state(ctx, 1);
7807 gen_helper_di(t0);
7808 /* Stop translation as we may have switched the execution mode */
7809 ctx->bstate = BS_STOP;
7810 break;
7811 case OPC_EI:
7812 check_insn(env, ctx, ISA_MIPS32R2);
7813 save_cpu_state(ctx, 1);
7814 gen_helper_ei(t0);
7815 /* Stop translation as we may have switched the execution mode */
7816 ctx->bstate = BS_STOP;
7817 break;
7818 default: /* Invalid */
7819 MIPS_INVAL("mfmc0");
7820 generate_exception(ctx, EXCP_RI);
7821 break;
7823 gen_store_gpr(t0, rt);
7824 tcg_temp_free(t0);
7826 #endif /* !CONFIG_USER_ONLY */
7827 break;
7828 case OPC_RDPGPR:
7829 check_insn(env, ctx, ISA_MIPS32R2);
7830 gen_load_srsgpr(rt, rd);
7831 break;
7832 case OPC_WRPGPR:
7833 check_insn(env, ctx, ISA_MIPS32R2);
7834 gen_store_srsgpr(rt, rd);
7835 break;
7836 default:
7837 MIPS_INVAL("cp0");
7838 generate_exception(ctx, EXCP_RI);
7839 break;
7841 break;
7842 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
7843 gen_arith_imm(env, ctx, op, rt, rs, imm);
7844 break;
7845 case OPC_J ... OPC_JAL: /* Jump */
7846 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7847 gen_compute_branch(ctx, op, rs, rt, offset);
7848 return;
7849 case OPC_BEQ ... OPC_BGTZ: /* Branch */
7850 case OPC_BEQL ... OPC_BGTZL:
7851 gen_compute_branch(ctx, op, rs, rt, imm << 2);
7852 return;
7853 case OPC_LB ... OPC_LWR: /* Load and stores */
7854 case OPC_SB ... OPC_SW:
7855 case OPC_SWR:
7856 case OPC_LL:
7857 case OPC_SC:
7858 gen_ldst(ctx, op, rt, rs, imm);
7859 break;
7860 case OPC_CACHE:
7861 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
7862 /* Treat as NOP. */
7863 break;
7864 case OPC_PREF:
7865 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7866 /* Treat as NOP. */
7867 break;
7869 /* Floating point (COP1). */
7870 case OPC_LWC1:
7871 case OPC_LDC1:
7872 case OPC_SWC1:
7873 case OPC_SDC1:
7874 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7875 save_cpu_state(ctx, 1);
7876 check_cp1_enabled(ctx);
7877 gen_flt_ldst(ctx, op, rt, rs, imm);
7878 } else {
7879 generate_exception_err(ctx, EXCP_CpU, 1);
7881 break;
7883 case OPC_CP1:
7884 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7885 save_cpu_state(ctx, 1);
7886 check_cp1_enabled(ctx);
7887 op1 = MASK_CP1(ctx->opcode);
7888 switch (op1) {
7889 case OPC_MFHC1:
7890 case OPC_MTHC1:
7891 check_insn(env, ctx, ISA_MIPS32R2);
7892 case OPC_MFC1:
7893 case OPC_CFC1:
7894 case OPC_MTC1:
7895 case OPC_CTC1:
7896 gen_cp1(ctx, op1, rt, rd);
7897 break;
7898 #if defined(TARGET_MIPS64)
7899 case OPC_DMFC1:
7900 case OPC_DMTC1:
7901 check_insn(env, ctx, ISA_MIPS3);
7902 gen_cp1(ctx, op1, rt, rd);
7903 break;
7904 #endif
7905 case OPC_BC1ANY2:
7906 case OPC_BC1ANY4:
7907 check_cop1x(ctx);
7908 check_insn(env, ctx, ASE_MIPS3D);
7909 /* fall through */
7910 case OPC_BC1:
7911 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
7912 (rt >> 2) & 0x7, imm << 2);
7913 return;
7914 case OPC_S_FMT:
7915 case OPC_D_FMT:
7916 case OPC_W_FMT:
7917 case OPC_L_FMT:
7918 case OPC_PS_FMT:
7919 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
7920 (imm >> 8) & 0x7);
7921 break;
7922 default:
7923 MIPS_INVAL("cp1");
7924 generate_exception (ctx, EXCP_RI);
7925 break;
7927 } else {
7928 generate_exception_err(ctx, EXCP_CpU, 1);
7930 break;
7932 /* COP2. */
7933 case OPC_LWC2:
7934 case OPC_LDC2:
7935 case OPC_SWC2:
7936 case OPC_SDC2:
7937 case OPC_CP2:
7938 /* COP2: Not implemented. */
7939 generate_exception_err(ctx, EXCP_CpU, 2);
7940 break;
7942 case OPC_CP3:
7943 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7944 save_cpu_state(ctx, 1);
7945 check_cp1_enabled(ctx);
7946 op1 = MASK_CP3(ctx->opcode);
7947 switch (op1) {
7948 case OPC_LWXC1:
7949 case OPC_LDXC1:
7950 case OPC_LUXC1:
7951 case OPC_SWXC1:
7952 case OPC_SDXC1:
7953 case OPC_SUXC1:
7954 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
7955 break;
7956 case OPC_PREFX:
7957 /* Treat as NOP. */
7958 break;
7959 case OPC_ALNV_PS:
7960 case OPC_MADD_S:
7961 case OPC_MADD_D:
7962 case OPC_MADD_PS:
7963 case OPC_MSUB_S:
7964 case OPC_MSUB_D:
7965 case OPC_MSUB_PS:
7966 case OPC_NMADD_S:
7967 case OPC_NMADD_D:
7968 case OPC_NMADD_PS:
7969 case OPC_NMSUB_S:
7970 case OPC_NMSUB_D:
7971 case OPC_NMSUB_PS:
7972 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
7973 break;
7974 default:
7975 MIPS_INVAL("cp3");
7976 generate_exception (ctx, EXCP_RI);
7977 break;
7979 } else {
7980 generate_exception_err(ctx, EXCP_CpU, 1);
7982 break;
7984 #if defined(TARGET_MIPS64)
7985 /* MIPS64 opcodes */
7986 case OPC_LWU:
7987 case OPC_LDL ... OPC_LDR:
7988 case OPC_SDL ... OPC_SDR:
7989 case OPC_LLD:
7990 case OPC_LD:
7991 case OPC_SCD:
7992 case OPC_SD:
7993 check_insn(env, ctx, ISA_MIPS3);
7994 check_mips_64(ctx);
7995 gen_ldst(ctx, op, rt, rs, imm);
7996 break;
7997 case OPC_DADDI ... OPC_DADDIU:
7998 check_insn(env, ctx, ISA_MIPS3);
7999 check_mips_64(ctx);
8000 gen_arith_imm(env, ctx, op, rt, rs, imm);
8001 break;
8002 #endif
8003 case OPC_JALX:
8004 check_insn(env, ctx, ASE_MIPS16);
8005 /* MIPS16: Not implemented. */
8006 case OPC_MDMX:
8007 check_insn(env, ctx, ASE_MDMX);
8008 /* MDMX: Not implemented. */
8009 default: /* Invalid */
8010 MIPS_INVAL("major opcode");
8011 generate_exception(ctx, EXCP_RI);
8012 break;
8014 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8015 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8016 /* Branches completion */
8017 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8018 ctx->bstate = BS_BRANCH;
8019 save_cpu_state(ctx, 0);
8020 /* FIXME: Need to clear can_do_io. */
8021 switch (hflags) {
8022 case MIPS_HFLAG_B:
8023 /* unconditional branch */
8024 MIPS_DEBUG("unconditional branch");
8025 gen_goto_tb(ctx, 0, ctx->btarget);
8026 break;
8027 case MIPS_HFLAG_BL:
8028 /* blikely taken case */
8029 MIPS_DEBUG("blikely branch taken");
8030 gen_goto_tb(ctx, 0, ctx->btarget);
8031 break;
8032 case MIPS_HFLAG_BC:
8033 /* Conditional branch */
8034 MIPS_DEBUG("conditional branch");
8036 int l1 = gen_new_label();
8038 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8039 gen_goto_tb(ctx, 1, ctx->pc + 4);
8040 gen_set_label(l1);
8041 gen_goto_tb(ctx, 0, ctx->btarget);
8043 break;
8044 case MIPS_HFLAG_BR:
8045 /* unconditional branch to register */
8046 MIPS_DEBUG("branch to register");
8047 tcg_gen_mov_tl(cpu_PC, btarget);
8048 tcg_gen_exit_tb(0);
8049 break;
8050 default:
8051 MIPS_DEBUG("unknown branch");
8052 break;
8057 static inline void
8058 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8059 int search_pc)
8061 DisasContext ctx;
8062 target_ulong pc_start;
8063 uint16_t *gen_opc_end;
8064 CPUBreakpoint *bp;
8065 int j, lj = -1;
8066 int num_insns;
8067 int max_insns;
8069 if (search_pc)
8070 qemu_log("search pc %d\n", search_pc);
8072 pc_start = tb->pc;
8073 /* Leave some spare opc slots for branch handling. */
8074 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
8075 ctx.pc = pc_start;
8076 ctx.saved_pc = -1;
8077 ctx.tb = tb;
8078 ctx.bstate = BS_NONE;
8079 /* Restore delay slot state from the tb context. */
8080 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8081 restore_cpu_state(env, &ctx);
8082 #ifdef CONFIG_USER_ONLY
8083 ctx.mem_idx = MIPS_HFLAG_UM;
8084 #else
8085 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8086 #endif
8087 num_insns = 0;
8088 max_insns = tb->cflags & CF_COUNT_MASK;
8089 if (max_insns == 0)
8090 max_insns = CF_COUNT_MASK;
8091 #ifdef DEBUG_DISAS
8092 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
8093 /* FIXME: This may print out stale hflags from env... */
8094 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
8095 #endif
8096 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
8097 gen_icount_start();
8098 while (ctx.bstate == BS_NONE) {
8099 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8100 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8101 if (bp->pc == ctx.pc) {
8102 save_cpu_state(&ctx, 1);
8103 ctx.bstate = BS_BRANCH;
8104 gen_helper_0i(raise_exception, EXCP_DEBUG);
8105 /* Include the breakpoint location or the tb won't
8106 * be flushed when it must be. */
8107 ctx.pc += 4;
8108 goto done_generating;
8113 if (search_pc) {
8114 j = gen_opc_ptr - gen_opc_buf;
8115 if (lj < j) {
8116 lj++;
8117 while (lj < j)
8118 gen_opc_instr_start[lj++] = 0;
8120 gen_opc_pc[lj] = ctx.pc;
8121 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8122 gen_opc_instr_start[lj] = 1;
8123 gen_opc_icount[lj] = num_insns;
8125 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8126 gen_io_start();
8127 ctx.opcode = ldl_code(ctx.pc);
8128 decode_opc(env, &ctx);
8129 ctx.pc += 4;
8130 num_insns++;
8132 if (env->singlestep_enabled)
8133 break;
8135 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8136 break;
8138 if (gen_opc_ptr >= gen_opc_end)
8139 break;
8141 if (num_insns >= max_insns)
8142 break;
8143 #if defined (MIPS_SINGLE_STEP)
8144 break;
8145 #endif
8147 if (tb->cflags & CF_LAST_IO)
8148 gen_io_end();
8149 if (env->singlestep_enabled) {
8150 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
8151 gen_helper_0i(raise_exception, EXCP_DEBUG);
8152 } else {
8153 switch (ctx.bstate) {
8154 case BS_STOP:
8155 gen_helper_interrupt_restart();
8156 gen_goto_tb(&ctx, 0, ctx.pc);
8157 break;
8158 case BS_NONE:
8159 save_cpu_state(&ctx, 0);
8160 gen_goto_tb(&ctx, 0, ctx.pc);
8161 break;
8162 case BS_EXCP:
8163 gen_helper_interrupt_restart();
8164 tcg_gen_exit_tb(0);
8165 break;
8166 case BS_BRANCH:
8167 default:
8168 break;
8171 done_generating:
8172 gen_icount_end(tb, num_insns);
8173 *gen_opc_ptr = INDEX_op_end;
8174 if (search_pc) {
8175 j = gen_opc_ptr - gen_opc_buf;
8176 lj++;
8177 while (lj <= j)
8178 gen_opc_instr_start[lj++] = 0;
8179 } else {
8180 tb->size = ctx.pc - pc_start;
8181 tb->icount = num_insns;
8183 #ifdef DEBUG_DISAS
8184 LOG_DISAS("\n");
8185 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8186 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8187 log_target_disas(pc_start, ctx.pc - pc_start, 0);
8188 qemu_log("\n");
8190 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8191 #endif
8194 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8196 gen_intermediate_code_internal(env, tb, 0);
8199 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8201 gen_intermediate_code_internal(env, tb, 1);
8204 static void fpu_dump_state(CPUState *env, FILE *f,
8205 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8206 int flags)
8208 int i;
8209 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8211 #define printfpr(fp) \
8212 do { \
8213 if (is_fpu64) \
8214 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8215 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8216 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8217 else { \
8218 fpr_t tmp; \
8219 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8220 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8221 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8222 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8223 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8225 } while(0)
8228 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8229 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8230 get_float_exception_flags(&env->active_fpu.fp_status));
8231 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8232 fpu_fprintf(f, "%3s: ", fregnames[i]);
8233 printfpr(&env->active_fpu.fpr[i]);
8236 #undef printfpr
8239 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8240 /* Debug help: The architecture requires 32bit code to maintain proper
8241 sign-extended values on 64bit machines. */
8243 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8245 static void
8246 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8247 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8248 int flags)
8250 int i;
8252 if (!SIGN_EXT_P(env->active_tc.PC))
8253 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8254 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8255 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8256 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8257 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8258 if (!SIGN_EXT_P(env->btarget))
8259 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8261 for (i = 0; i < 32; i++) {
8262 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8263 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8266 if (!SIGN_EXT_P(env->CP0_EPC))
8267 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8268 if (!SIGN_EXT_P(env->CP0_LLAddr))
8269 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
8271 #endif
8273 void cpu_dump_state (CPUState *env, FILE *f,
8274 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8275 int flags)
8277 int i;
8279 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",
8280 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8281 env->hflags, env->btarget, env->bcond);
8282 for (i = 0; i < 32; i++) {
8283 if ((i & 3) == 0)
8284 cpu_fprintf(f, "GPR%02d:", i);
8285 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8286 if ((i & 3) == 3)
8287 cpu_fprintf(f, "\n");
8290 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8291 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8292 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8293 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
8294 if (env->hflags & MIPS_HFLAG_FPU)
8295 fpu_dump_state(env, f, cpu_fprintf, flags);
8296 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8297 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8298 #endif
8301 static void mips_tcg_init(void)
8303 int i;
8304 static int inited;
8306 /* Initialize various static tables. */
8307 if (inited)
8308 return;
8310 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8311 for (i = 0; i < 32; i++)
8312 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
8313 offsetof(CPUState, active_tc.gpr[i]),
8314 regnames[i]);
8315 cpu_PC = tcg_global_mem_new(TCG_AREG0,
8316 offsetof(CPUState, active_tc.PC), "PC");
8317 for (i = 0; i < MIPS_DSP_ACC; i++) {
8318 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
8319 offsetof(CPUState, active_tc.HI[i]),
8320 regnames_HI[i]);
8321 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
8322 offsetof(CPUState, active_tc.LO[i]),
8323 regnames_LO[i]);
8324 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
8325 offsetof(CPUState, active_tc.ACX[i]),
8326 regnames_ACX[i]);
8328 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
8329 offsetof(CPUState, active_tc.DSPControl),
8330 "DSPControl");
8331 bcond = tcg_global_mem_new(TCG_AREG0,
8332 offsetof(CPUState, bcond), "bcond");
8333 btarget = tcg_global_mem_new(TCG_AREG0,
8334 offsetof(CPUState, btarget), "btarget");
8335 hflags = tcg_global_mem_new_i32(TCG_AREG0,
8336 offsetof(CPUState, hflags), "hflags");
8338 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
8339 offsetof(CPUState, active_fpu.fcr0),
8340 "fcr0");
8341 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
8342 offsetof(CPUState, active_fpu.fcr31),
8343 "fcr31");
8345 /* register helpers */
8346 #define GEN_HELPER 2
8347 #include "helper.h"
8349 inited = 1;
8352 #include "translate_init.c"
8354 CPUMIPSState *cpu_mips_init (const char *cpu_model)
8356 CPUMIPSState *env;
8357 const mips_def_t *def;
8359 def = cpu_mips_find_by_name(cpu_model);
8360 if (!def)
8361 return NULL;
8362 env = qemu_mallocz(sizeof(CPUMIPSState));
8363 env->cpu_model = def;
8365 cpu_exec_init(env);
8366 env->cpu_model_str = cpu_model;
8367 mips_tcg_init();
8368 cpu_reset(env);
8369 return env;
8372 void cpu_reset (CPUMIPSState *env)
8374 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
8375 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
8376 log_cpu_state(env, 0);
8379 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8381 tlb_flush(env, 1);
8383 /* Minimal init */
8384 #if defined(CONFIG_USER_ONLY)
8385 env->hflags = MIPS_HFLAG_UM;
8386 #else
8387 if (env->hflags & MIPS_HFLAG_BMASK) {
8388 /* If the exception was raised from a delay slot,
8389 come back to the jump. */
8390 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8391 } else {
8392 env->CP0_ErrorEPC = env->active_tc.PC;
8394 env->active_tc.PC = (int32_t)0xBFC00000;
8395 env->CP0_Wired = 0;
8396 /* SMP not implemented */
8397 env->CP0_EBase = 0x80000000;
8398 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8399 /* vectored interrupts not implemented, timer on int 7,
8400 no performance counters. */
8401 env->CP0_IntCtl = 0xe0000000;
8403 int i;
8405 for (i = 0; i < 7; i++) {
8406 env->CP0_WatchLo[i] = 0;
8407 env->CP0_WatchHi[i] = 0x80000000;
8409 env->CP0_WatchLo[7] = 0;
8410 env->CP0_WatchHi[7] = 0;
8412 /* Count register increments in debug mode, EJTAG version 1 */
8413 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8414 env->hflags = MIPS_HFLAG_CP0;
8415 #endif
8416 env->exception_index = EXCP_NONE;
8417 cpu_mips_register(env, env->cpu_model);
8420 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8421 unsigned long searched_pc, int pc_pos, void *puc)
8423 env->active_tc.PC = gen_opc_pc[pc_pos];
8424 env->hflags &= ~MIPS_HFLAG_BMASK;
8425 env->hflags |= gen_opc_hflags[pc_pos];