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