Remove redundant #define
[qemu/mini2440.git] / target-mips / translate.c
blobe96fe60fd2754810433bd8d1082503a1c159f8db
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, args...) \
505 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
506 TARGET_FMT_lx ": %08x " fmt "\n", \
507 ctx->pc, ctx->opcode , ##args)
508 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
509 #else
510 #define MIPS_DEBUG(fmt, args...) 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 same sign, 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 } else if (rs != 0 && rt == 0) {
1608 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1609 } else {
1610 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1612 opn = "subu";
1613 break;
1614 #if defined(TARGET_MIPS64)
1615 case OPC_DADD:
1617 TCGv t0 = tcg_temp_local_new();
1618 TCGv t1 = tcg_temp_new();
1619 TCGv t2 = tcg_temp_new();
1620 int l1 = gen_new_label();
1622 gen_load_gpr(t1, rs);
1623 gen_load_gpr(t2, rt);
1624 tcg_gen_add_tl(t0, t1, t2);
1625 tcg_gen_xor_tl(t1, t1, t2);
1626 tcg_gen_not_tl(t1, t1);
1627 tcg_gen_xor_tl(t2, t0, t2);
1628 tcg_gen_and_tl(t1, t1, t2);
1629 tcg_temp_free(t2);
1630 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1631 tcg_temp_free(t1);
1632 /* operands of same sign, result different sign */
1633 generate_exception(ctx, EXCP_OVERFLOW);
1634 gen_set_label(l1);
1635 gen_store_gpr(t0, rd);
1636 tcg_temp_free(t0);
1638 opn = "dadd";
1639 break;
1640 case OPC_DADDU:
1641 if (rs != 0 && rt != 0) {
1642 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1643 } else if (rs == 0 && rt != 0) {
1644 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1645 } else if (rs != 0 && rt == 0) {
1646 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1647 } else {
1648 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1650 opn = "daddu";
1651 break;
1652 case OPC_DSUB:
1654 TCGv t0 = tcg_temp_local_new();
1655 TCGv t1 = tcg_temp_new();
1656 TCGv t2 = tcg_temp_new();
1657 int l1 = gen_new_label();
1659 gen_load_gpr(t1, rs);
1660 gen_load_gpr(t2, rt);
1661 tcg_gen_sub_tl(t0, t1, t2);
1662 tcg_gen_xor_tl(t2, t1, t2);
1663 tcg_gen_xor_tl(t1, t0, t1);
1664 tcg_gen_and_tl(t1, t1, t2);
1665 tcg_temp_free(t2);
1666 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1667 tcg_temp_free(t1);
1668 /* operands of same sign, result different sign */
1669 generate_exception(ctx, EXCP_OVERFLOW);
1670 gen_set_label(l1);
1671 gen_store_gpr(t0, rd);
1672 tcg_temp_free(t0);
1674 opn = "dsub";
1675 break;
1676 case OPC_DSUBU:
1677 if (rs != 0 && rt != 0) {
1678 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1679 } else if (rs == 0 && rt != 0) {
1680 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1681 } else if (rs != 0 && rt == 0) {
1682 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1683 } else {
1684 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1686 opn = "dsubu";
1687 break;
1688 #endif
1689 case OPC_MUL:
1690 if (likely(rs != 0 && rt != 0)) {
1691 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1692 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1693 } else {
1694 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1696 opn = "mul";
1697 break;
1699 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1702 /* Conditional move */
1703 static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1705 const char *opn = "cond move";
1706 int l1;
1708 if (rd == 0) {
1709 /* If no destination, treat it as a NOP.
1710 For add & sub, we must generate the overflow exception when needed. */
1711 MIPS_DEBUG("NOP");
1712 return;
1715 l1 = gen_new_label();
1716 switch (opc) {
1717 case OPC_MOVN:
1718 if (likely(rt != 0))
1719 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1720 else
1721 tcg_gen_br(l1);
1722 opn = "movn";
1723 break;
1724 case OPC_MOVZ:
1725 if (likely(rt != 0))
1726 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1727 opn = "movz";
1728 break;
1730 if (rs != 0)
1731 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1732 else
1733 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1734 gen_set_label(l1);
1736 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1739 /* Logic */
1740 static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1742 const char *opn = "logic";
1744 if (rd == 0) {
1745 /* If no destination, treat it as a NOP. */
1746 MIPS_DEBUG("NOP");
1747 return;
1750 switch (opc) {
1751 case OPC_AND:
1752 if (likely(rs != 0 && rt != 0)) {
1753 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1754 } else {
1755 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1757 opn = "and";
1758 break;
1759 case OPC_NOR:
1760 if (rs != 0 && rt != 0) {
1761 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1762 } else if (rs == 0 && rt != 0) {
1763 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1764 } else if (rs != 0 && rt == 0) {
1765 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1766 } else {
1767 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1769 opn = "nor";
1770 break;
1771 case OPC_OR:
1772 if (likely(rs != 0 && rt != 0)) {
1773 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1774 } else if (rs == 0 && rt != 0) {
1775 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1776 } else if (rs != 0 && rt == 0) {
1777 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1778 } else {
1779 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1781 opn = "or";
1782 break;
1783 case OPC_XOR:
1784 if (likely(rs != 0 && rt != 0)) {
1785 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1786 } else if (rs == 0 && rt != 0) {
1787 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1788 } else if (rs != 0 && rt == 0) {
1789 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1790 } else {
1791 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1793 opn = "xor";
1794 break;
1796 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1799 /* Set on lower than */
1800 static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1802 const char *opn = "slt";
1803 TCGv t0, t1;
1805 if (rd == 0) {
1806 /* If no destination, treat it as a NOP. */
1807 MIPS_DEBUG("NOP");
1808 return;
1811 t0 = tcg_temp_new();
1812 t1 = tcg_temp_new();
1813 gen_load_gpr(t0, rs);
1814 gen_load_gpr(t1, rt);
1815 switch (opc) {
1816 case OPC_SLT:
1817 gen_op_lt(cpu_gpr[rd], t0, t1);
1818 opn = "slt";
1819 break;
1820 case OPC_SLTU:
1821 gen_op_ltu(cpu_gpr[rd], t0, t1);
1822 opn = "sltu";
1823 break;
1825 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1826 tcg_temp_free(t0);
1827 tcg_temp_free(t1);
1830 /* Shifts */
1831 static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1832 int rd, int rs, int rt)
1834 const char *opn = "shifts";
1835 TCGv t0, t1;
1837 if (rd == 0) {
1838 /* If no destination, treat it as a NOP.
1839 For add & sub, we must generate the overflow exception when needed. */
1840 MIPS_DEBUG("NOP");
1841 return;
1844 t0 = tcg_temp_new();
1845 t1 = tcg_temp_new();
1846 gen_load_gpr(t0, rs);
1847 gen_load_gpr(t1, rt);
1848 switch (opc) {
1849 case OPC_SLLV:
1850 tcg_gen_andi_tl(t0, t0, 0x1f);
1851 tcg_gen_shl_tl(t0, t1, t0);
1852 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1853 opn = "sllv";
1854 break;
1855 case OPC_SRAV:
1856 tcg_gen_ext32s_tl(t1, t1);
1857 tcg_gen_andi_tl(t0, t0, 0x1f);
1858 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1859 opn = "srav";
1860 break;
1861 case OPC_SRLV:
1862 switch ((ctx->opcode >> 6) & 0x1f) {
1863 case 0:
1864 tcg_gen_ext32u_tl(t1, t1);
1865 tcg_gen_andi_tl(t0, t0, 0x1f);
1866 tcg_gen_shr_tl(t0, t1, t0);
1867 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1868 opn = "srlv";
1869 break;
1870 case 1:
1871 /* rotrv is decoded as srlv on non-R2 CPUs */
1872 if (env->insn_flags & ISA_MIPS32R2) {
1873 TCGv_i32 t2 = tcg_temp_new_i32();
1874 TCGv_i32 t3 = tcg_temp_new_i32();
1876 tcg_gen_trunc_tl_i32(t2, t0);
1877 tcg_gen_trunc_tl_i32(t3, t1);
1878 tcg_gen_andi_i32(t2, t2, 0x1f);
1879 tcg_gen_rotr_i32(t2, t3, t2);
1880 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1881 tcg_temp_free_i32(t2);
1882 tcg_temp_free_i32(t3);
1883 opn = "rotrv";
1884 } else {
1885 tcg_gen_ext32u_tl(t1, t1);
1886 tcg_gen_andi_tl(t0, t0, 0x1f);
1887 tcg_gen_shr_tl(t0, t1, t0);
1888 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1889 opn = "srlv";
1891 break;
1892 default:
1893 MIPS_INVAL("invalid srlv flag");
1894 generate_exception(ctx, EXCP_RI);
1895 break;
1897 break;
1898 #if defined(TARGET_MIPS64)
1899 case OPC_DSLLV:
1900 tcg_gen_andi_tl(t0, t0, 0x3f);
1901 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1902 opn = "dsllv";
1903 break;
1904 case OPC_DSRAV:
1905 tcg_gen_andi_tl(t0, t0, 0x3f);
1906 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1907 opn = "dsrav";
1908 break;
1909 case OPC_DSRLV:
1910 switch ((ctx->opcode >> 6) & 0x1f) {
1911 case 0:
1912 tcg_gen_andi_tl(t0, t0, 0x3f);
1913 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1914 opn = "dsrlv";
1915 break;
1916 case 1:
1917 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1918 if (env->insn_flags & ISA_MIPS32R2) {
1919 tcg_gen_andi_tl(t0, t0, 0x3f);
1920 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1921 opn = "drotrv";
1922 } else {
1923 tcg_gen_andi_tl(t0, t0, 0x3f);
1924 tcg_gen_shr_tl(t0, t1, t0);
1925 opn = "dsrlv";
1927 break;
1928 default:
1929 MIPS_INVAL("invalid dsrlv flag");
1930 generate_exception(ctx, EXCP_RI);
1931 break;
1933 break;
1934 #endif
1936 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1937 tcg_temp_free(t0);
1938 tcg_temp_free(t1);
1941 /* Arithmetic on HI/LO registers */
1942 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1944 const char *opn = "hilo";
1946 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1947 /* Treat as NOP. */
1948 MIPS_DEBUG("NOP");
1949 return;
1951 switch (opc) {
1952 case OPC_MFHI:
1953 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1954 opn = "mfhi";
1955 break;
1956 case OPC_MFLO:
1957 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1958 opn = "mflo";
1959 break;
1960 case OPC_MTHI:
1961 if (reg != 0)
1962 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1963 else
1964 tcg_gen_movi_tl(cpu_HI[0], 0);
1965 opn = "mthi";
1966 break;
1967 case OPC_MTLO:
1968 if (reg != 0)
1969 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1970 else
1971 tcg_gen_movi_tl(cpu_LO[0], 0);
1972 opn = "mtlo";
1973 break;
1975 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1978 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1979 int rs, int rt)
1981 const char *opn = "mul/div";
1982 TCGv t0, t1;
1984 switch (opc) {
1985 case OPC_DIV:
1986 case OPC_DIVU:
1987 #if defined(TARGET_MIPS64)
1988 case OPC_DDIV:
1989 case OPC_DDIVU:
1990 #endif
1991 t0 = tcg_temp_local_new();
1992 t1 = tcg_temp_local_new();
1993 break;
1994 default:
1995 t0 = tcg_temp_new();
1996 t1 = tcg_temp_new();
1997 break;
2000 gen_load_gpr(t0, rs);
2001 gen_load_gpr(t1, rt);
2002 switch (opc) {
2003 case OPC_DIV:
2005 int l1 = gen_new_label();
2006 int l2 = gen_new_label();
2008 tcg_gen_ext32s_tl(t0, t0);
2009 tcg_gen_ext32s_tl(t1, t1);
2010 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2011 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2012 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2014 tcg_gen_mov_tl(cpu_LO[0], t0);
2015 tcg_gen_movi_tl(cpu_HI[0], 0);
2016 tcg_gen_br(l1);
2017 gen_set_label(l2);
2018 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2019 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2020 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2021 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2022 gen_set_label(l1);
2024 opn = "div";
2025 break;
2026 case OPC_DIVU:
2028 int l1 = gen_new_label();
2030 tcg_gen_ext32u_tl(t0, t0);
2031 tcg_gen_ext32u_tl(t1, t1);
2032 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2033 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2034 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2035 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2036 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2037 gen_set_label(l1);
2039 opn = "divu";
2040 break;
2041 case OPC_MULT:
2043 TCGv_i64 t2 = tcg_temp_new_i64();
2044 TCGv_i64 t3 = tcg_temp_new_i64();
2046 tcg_gen_ext_tl_i64(t2, t0);
2047 tcg_gen_ext_tl_i64(t3, t1);
2048 tcg_gen_mul_i64(t2, t2, t3);
2049 tcg_temp_free_i64(t3);
2050 tcg_gen_trunc_i64_tl(t0, t2);
2051 tcg_gen_shri_i64(t2, t2, 32);
2052 tcg_gen_trunc_i64_tl(t1, t2);
2053 tcg_temp_free_i64(t2);
2054 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2055 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2057 opn = "mult";
2058 break;
2059 case OPC_MULTU:
2061 TCGv_i64 t2 = tcg_temp_new_i64();
2062 TCGv_i64 t3 = tcg_temp_new_i64();
2064 tcg_gen_ext32u_tl(t0, t0);
2065 tcg_gen_ext32u_tl(t1, t1);
2066 tcg_gen_extu_tl_i64(t2, t0);
2067 tcg_gen_extu_tl_i64(t3, t1);
2068 tcg_gen_mul_i64(t2, t2, t3);
2069 tcg_temp_free_i64(t3);
2070 tcg_gen_trunc_i64_tl(t0, t2);
2071 tcg_gen_shri_i64(t2, t2, 32);
2072 tcg_gen_trunc_i64_tl(t1, t2);
2073 tcg_temp_free_i64(t2);
2074 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2075 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2077 opn = "multu";
2078 break;
2079 #if defined(TARGET_MIPS64)
2080 case OPC_DDIV:
2082 int l1 = gen_new_label();
2083 int l2 = gen_new_label();
2085 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2086 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2087 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2088 tcg_gen_mov_tl(cpu_LO[0], t0);
2089 tcg_gen_movi_tl(cpu_HI[0], 0);
2090 tcg_gen_br(l1);
2091 gen_set_label(l2);
2092 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2093 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2094 gen_set_label(l1);
2096 opn = "ddiv";
2097 break;
2098 case OPC_DDIVU:
2100 int l1 = gen_new_label();
2102 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2103 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2104 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2105 gen_set_label(l1);
2107 opn = "ddivu";
2108 break;
2109 case OPC_DMULT:
2110 gen_helper_dmult(t0, t1);
2111 opn = "dmult";
2112 break;
2113 case OPC_DMULTU:
2114 gen_helper_dmultu(t0, t1);
2115 opn = "dmultu";
2116 break;
2117 #endif
2118 case OPC_MADD:
2120 TCGv_i64 t2 = tcg_temp_new_i64();
2121 TCGv_i64 t3 = tcg_temp_new_i64();
2123 tcg_gen_ext_tl_i64(t2, t0);
2124 tcg_gen_ext_tl_i64(t3, t1);
2125 tcg_gen_mul_i64(t2, t2, t3);
2126 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2127 tcg_gen_add_i64(t2, t2, t3);
2128 tcg_temp_free_i64(t3);
2129 tcg_gen_trunc_i64_tl(t0, t2);
2130 tcg_gen_shri_i64(t2, t2, 32);
2131 tcg_gen_trunc_i64_tl(t1, t2);
2132 tcg_temp_free_i64(t2);
2133 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2134 tcg_gen_ext32s_tl(cpu_LO[1], t1);
2136 opn = "madd";
2137 break;
2138 case OPC_MADDU:
2140 TCGv_i64 t2 = tcg_temp_new_i64();
2141 TCGv_i64 t3 = tcg_temp_new_i64();
2143 tcg_gen_ext32u_tl(t0, t0);
2144 tcg_gen_ext32u_tl(t1, t1);
2145 tcg_gen_extu_tl_i64(t2, t0);
2146 tcg_gen_extu_tl_i64(t3, t1);
2147 tcg_gen_mul_i64(t2, t2, t3);
2148 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2149 tcg_gen_add_i64(t2, t2, t3);
2150 tcg_temp_free_i64(t3);
2151 tcg_gen_trunc_i64_tl(t0, t2);
2152 tcg_gen_shri_i64(t2, t2, 32);
2153 tcg_gen_trunc_i64_tl(t1, t2);
2154 tcg_temp_free_i64(t2);
2155 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2156 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2158 opn = "maddu";
2159 break;
2160 case OPC_MSUB:
2162 TCGv_i64 t2 = tcg_temp_new_i64();
2163 TCGv_i64 t3 = tcg_temp_new_i64();
2165 tcg_gen_ext_tl_i64(t2, t0);
2166 tcg_gen_ext_tl_i64(t3, t1);
2167 tcg_gen_mul_i64(t2, t2, t3);
2168 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2169 tcg_gen_sub_i64(t2, t2, t3);
2170 tcg_temp_free_i64(t3);
2171 tcg_gen_trunc_i64_tl(t0, t2);
2172 tcg_gen_shri_i64(t2, t2, 32);
2173 tcg_gen_trunc_i64_tl(t1, t2);
2174 tcg_temp_free_i64(t2);
2175 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2176 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2178 opn = "msub";
2179 break;
2180 case OPC_MSUBU:
2182 TCGv_i64 t2 = tcg_temp_new_i64();
2183 TCGv_i64 t3 = tcg_temp_new_i64();
2185 tcg_gen_ext32u_tl(t0, t0);
2186 tcg_gen_ext32u_tl(t1, t1);
2187 tcg_gen_extu_tl_i64(t2, t0);
2188 tcg_gen_extu_tl_i64(t3, t1);
2189 tcg_gen_mul_i64(t2, t2, t3);
2190 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2191 tcg_gen_sub_i64(t2, t2, t3);
2192 tcg_temp_free_i64(t3);
2193 tcg_gen_trunc_i64_tl(t0, t2);
2194 tcg_gen_shri_i64(t2, t2, 32);
2195 tcg_gen_trunc_i64_tl(t1, t2);
2196 tcg_temp_free_i64(t2);
2197 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2198 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2200 opn = "msubu";
2201 break;
2202 default:
2203 MIPS_INVAL(opn);
2204 generate_exception(ctx, EXCP_RI);
2205 goto out;
2207 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2208 out:
2209 tcg_temp_free(t0);
2210 tcg_temp_free(t1);
2213 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2214 int rd, int rs, int rt)
2216 const char *opn = "mul vr54xx";
2217 TCGv t0 = tcg_temp_new();
2218 TCGv t1 = tcg_temp_new();
2220 gen_load_gpr(t0, rs);
2221 gen_load_gpr(t1, rt);
2223 switch (opc) {
2224 case OPC_VR54XX_MULS:
2225 gen_helper_muls(t0, t0, t1);
2226 opn = "muls";
2227 break;
2228 case OPC_VR54XX_MULSU:
2229 gen_helper_mulsu(t0, t0, t1);
2230 opn = "mulsu";
2231 break;
2232 case OPC_VR54XX_MACC:
2233 gen_helper_macc(t0, t0, t1);
2234 opn = "macc";
2235 break;
2236 case OPC_VR54XX_MACCU:
2237 gen_helper_maccu(t0, t0, t1);
2238 opn = "maccu";
2239 break;
2240 case OPC_VR54XX_MSAC:
2241 gen_helper_msac(t0, t0, t1);
2242 opn = "msac";
2243 break;
2244 case OPC_VR54XX_MSACU:
2245 gen_helper_msacu(t0, t0, t1);
2246 opn = "msacu";
2247 break;
2248 case OPC_VR54XX_MULHI:
2249 gen_helper_mulhi(t0, t0, t1);
2250 opn = "mulhi";
2251 break;
2252 case OPC_VR54XX_MULHIU:
2253 gen_helper_mulhiu(t0, t0, t1);
2254 opn = "mulhiu";
2255 break;
2256 case OPC_VR54XX_MULSHI:
2257 gen_helper_mulshi(t0, t0, t1);
2258 opn = "mulshi";
2259 break;
2260 case OPC_VR54XX_MULSHIU:
2261 gen_helper_mulshiu(t0, t0, t1);
2262 opn = "mulshiu";
2263 break;
2264 case OPC_VR54XX_MACCHI:
2265 gen_helper_macchi(t0, t0, t1);
2266 opn = "macchi";
2267 break;
2268 case OPC_VR54XX_MACCHIU:
2269 gen_helper_macchiu(t0, t0, t1);
2270 opn = "macchiu";
2271 break;
2272 case OPC_VR54XX_MSACHI:
2273 gen_helper_msachi(t0, t0, t1);
2274 opn = "msachi";
2275 break;
2276 case OPC_VR54XX_MSACHIU:
2277 gen_helper_msachiu(t0, t0, t1);
2278 opn = "msachiu";
2279 break;
2280 default:
2281 MIPS_INVAL("mul vr54xx");
2282 generate_exception(ctx, EXCP_RI);
2283 goto out;
2285 gen_store_gpr(t0, rd);
2286 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2288 out:
2289 tcg_temp_free(t0);
2290 tcg_temp_free(t1);
2293 static void gen_cl (DisasContext *ctx, uint32_t opc,
2294 int rd, int rs)
2296 const char *opn = "CLx";
2297 TCGv t0;
2299 if (rd == 0) {
2300 /* Treat as NOP. */
2301 MIPS_DEBUG("NOP");
2302 return;
2304 t0 = tcg_temp_new();
2305 gen_load_gpr(t0, rs);
2306 switch (opc) {
2307 case OPC_CLO:
2308 gen_helper_clo(cpu_gpr[rd], t0);
2309 opn = "clo";
2310 break;
2311 case OPC_CLZ:
2312 gen_helper_clz(cpu_gpr[rd], t0);
2313 opn = "clz";
2314 break;
2315 #if defined(TARGET_MIPS64)
2316 case OPC_DCLO:
2317 gen_helper_dclo(cpu_gpr[rd], t0);
2318 opn = "dclo";
2319 break;
2320 case OPC_DCLZ:
2321 gen_helper_dclz(cpu_gpr[rd], t0);
2322 opn = "dclz";
2323 break;
2324 #endif
2326 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2327 tcg_temp_free(t0);
2330 /* Traps */
2331 static void gen_trap (DisasContext *ctx, uint32_t opc,
2332 int rs, int rt, int16_t imm)
2334 int cond;
2335 TCGv t0 = tcg_temp_new();
2336 TCGv t1 = tcg_temp_new();
2338 cond = 0;
2339 /* Load needed operands */
2340 switch (opc) {
2341 case OPC_TEQ:
2342 case OPC_TGE:
2343 case OPC_TGEU:
2344 case OPC_TLT:
2345 case OPC_TLTU:
2346 case OPC_TNE:
2347 /* Compare two registers */
2348 if (rs != rt) {
2349 gen_load_gpr(t0, rs);
2350 gen_load_gpr(t1, rt);
2351 cond = 1;
2353 break;
2354 case OPC_TEQI:
2355 case OPC_TGEI:
2356 case OPC_TGEIU:
2357 case OPC_TLTI:
2358 case OPC_TLTIU:
2359 case OPC_TNEI:
2360 /* Compare register to immediate */
2361 if (rs != 0 || imm != 0) {
2362 gen_load_gpr(t0, rs);
2363 tcg_gen_movi_tl(t1, (int32_t)imm);
2364 cond = 1;
2366 break;
2368 if (cond == 0) {
2369 switch (opc) {
2370 case OPC_TEQ: /* rs == rs */
2371 case OPC_TEQI: /* r0 == 0 */
2372 case OPC_TGE: /* rs >= rs */
2373 case OPC_TGEI: /* r0 >= 0 */
2374 case OPC_TGEU: /* rs >= rs unsigned */
2375 case OPC_TGEIU: /* r0 >= 0 unsigned */
2376 /* Always trap */
2377 generate_exception(ctx, EXCP_TRAP);
2378 break;
2379 case OPC_TLT: /* rs < rs */
2380 case OPC_TLTI: /* r0 < 0 */
2381 case OPC_TLTU: /* rs < rs unsigned */
2382 case OPC_TLTIU: /* r0 < 0 unsigned */
2383 case OPC_TNE: /* rs != rs */
2384 case OPC_TNEI: /* r0 != 0 */
2385 /* Never trap: treat as NOP. */
2386 break;
2388 } else {
2389 int l1 = gen_new_label();
2391 switch (opc) {
2392 case OPC_TEQ:
2393 case OPC_TEQI:
2394 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2395 break;
2396 case OPC_TGE:
2397 case OPC_TGEI:
2398 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2399 break;
2400 case OPC_TGEU:
2401 case OPC_TGEIU:
2402 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2403 break;
2404 case OPC_TLT:
2405 case OPC_TLTI:
2406 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2407 break;
2408 case OPC_TLTU:
2409 case OPC_TLTIU:
2410 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2411 break;
2412 case OPC_TNE:
2413 case OPC_TNEI:
2414 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2415 break;
2417 generate_exception(ctx, EXCP_TRAP);
2418 gen_set_label(l1);
2420 tcg_temp_free(t0);
2421 tcg_temp_free(t1);
2424 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2426 TranslationBlock *tb;
2427 tb = ctx->tb;
2428 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2429 tcg_gen_goto_tb(n);
2430 gen_save_pc(dest);
2431 tcg_gen_exit_tb((long)tb + n);
2432 } else {
2433 gen_save_pc(dest);
2434 tcg_gen_exit_tb(0);
2438 /* Branches (before delay slot) */
2439 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2440 int rs, int rt, int32_t offset)
2442 target_ulong btgt = -1;
2443 int blink = 0;
2444 int bcond_compute = 0;
2445 TCGv t0 = tcg_temp_new();
2446 TCGv t1 = tcg_temp_new();
2448 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2449 #ifdef MIPS_DEBUG_DISAS
2450 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2451 #endif
2452 generate_exception(ctx, EXCP_RI);
2453 goto out;
2456 /* Load needed operands */
2457 switch (opc) {
2458 case OPC_BEQ:
2459 case OPC_BEQL:
2460 case OPC_BNE:
2461 case OPC_BNEL:
2462 /* Compare two registers */
2463 if (rs != rt) {
2464 gen_load_gpr(t0, rs);
2465 gen_load_gpr(t1, rt);
2466 bcond_compute = 1;
2468 btgt = ctx->pc + 4 + offset;
2469 break;
2470 case OPC_BGEZ:
2471 case OPC_BGEZAL:
2472 case OPC_BGEZALL:
2473 case OPC_BGEZL:
2474 case OPC_BGTZ:
2475 case OPC_BGTZL:
2476 case OPC_BLEZ:
2477 case OPC_BLEZL:
2478 case OPC_BLTZ:
2479 case OPC_BLTZAL:
2480 case OPC_BLTZALL:
2481 case OPC_BLTZL:
2482 /* Compare to zero */
2483 if (rs != 0) {
2484 gen_load_gpr(t0, rs);
2485 bcond_compute = 1;
2487 btgt = ctx->pc + 4 + offset;
2488 break;
2489 case OPC_J:
2490 case OPC_JAL:
2491 /* Jump to immediate */
2492 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2493 break;
2494 case OPC_JR:
2495 case OPC_JALR:
2496 /* Jump to register */
2497 if (offset != 0 && offset != 16) {
2498 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2499 others are reserved. */
2500 MIPS_INVAL("jump hint");
2501 generate_exception(ctx, EXCP_RI);
2502 goto out;
2504 gen_load_gpr(btarget, rs);
2505 break;
2506 default:
2507 MIPS_INVAL("branch/jump");
2508 generate_exception(ctx, EXCP_RI);
2509 goto out;
2511 if (bcond_compute == 0) {
2512 /* No condition to be computed */
2513 switch (opc) {
2514 case OPC_BEQ: /* rx == rx */
2515 case OPC_BEQL: /* rx == rx likely */
2516 case OPC_BGEZ: /* 0 >= 0 */
2517 case OPC_BGEZL: /* 0 >= 0 likely */
2518 case OPC_BLEZ: /* 0 <= 0 */
2519 case OPC_BLEZL: /* 0 <= 0 likely */
2520 /* Always take */
2521 ctx->hflags |= MIPS_HFLAG_B;
2522 MIPS_DEBUG("balways");
2523 break;
2524 case OPC_BGEZAL: /* 0 >= 0 */
2525 case OPC_BGEZALL: /* 0 >= 0 likely */
2526 /* Always take and link */
2527 blink = 31;
2528 ctx->hflags |= MIPS_HFLAG_B;
2529 MIPS_DEBUG("balways and link");
2530 break;
2531 case OPC_BNE: /* rx != rx */
2532 case OPC_BGTZ: /* 0 > 0 */
2533 case OPC_BLTZ: /* 0 < 0 */
2534 /* Treat as NOP. */
2535 MIPS_DEBUG("bnever (NOP)");
2536 goto out;
2537 case OPC_BLTZAL: /* 0 < 0 */
2538 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2539 MIPS_DEBUG("bnever and link");
2540 goto out;
2541 case OPC_BLTZALL: /* 0 < 0 likely */
2542 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2543 /* Skip the instruction in the delay slot */
2544 MIPS_DEBUG("bnever, link and skip");
2545 ctx->pc += 4;
2546 goto out;
2547 case OPC_BNEL: /* rx != rx likely */
2548 case OPC_BGTZL: /* 0 > 0 likely */
2549 case OPC_BLTZL: /* 0 < 0 likely */
2550 /* Skip the instruction in the delay slot */
2551 MIPS_DEBUG("bnever and skip");
2552 ctx->pc += 4;
2553 goto out;
2554 case OPC_J:
2555 ctx->hflags |= MIPS_HFLAG_B;
2556 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2557 break;
2558 case OPC_JAL:
2559 blink = 31;
2560 ctx->hflags |= MIPS_HFLAG_B;
2561 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2562 break;
2563 case OPC_JR:
2564 ctx->hflags |= MIPS_HFLAG_BR;
2565 MIPS_DEBUG("jr %s", regnames[rs]);
2566 break;
2567 case OPC_JALR:
2568 blink = rt;
2569 ctx->hflags |= MIPS_HFLAG_BR;
2570 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2571 break;
2572 default:
2573 MIPS_INVAL("branch/jump");
2574 generate_exception(ctx, EXCP_RI);
2575 goto out;
2577 } else {
2578 switch (opc) {
2579 case OPC_BEQ:
2580 gen_op_eq(bcond, t0, t1);
2581 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2582 regnames[rs], regnames[rt], btgt);
2583 goto not_likely;
2584 case OPC_BEQL:
2585 gen_op_eq(bcond, t0, t1);
2586 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2587 regnames[rs], regnames[rt], btgt);
2588 goto likely;
2589 case OPC_BNE:
2590 gen_op_ne(bcond, t0, t1);
2591 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2592 regnames[rs], regnames[rt], btgt);
2593 goto not_likely;
2594 case OPC_BNEL:
2595 gen_op_ne(bcond, t0, t1);
2596 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2597 regnames[rs], regnames[rt], btgt);
2598 goto likely;
2599 case OPC_BGEZ:
2600 gen_op_gez(bcond, t0);
2601 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2602 goto not_likely;
2603 case OPC_BGEZL:
2604 gen_op_gez(bcond, t0);
2605 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2606 goto likely;
2607 case OPC_BGEZAL:
2608 gen_op_gez(bcond, t0);
2609 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2610 blink = 31;
2611 goto not_likely;
2612 case OPC_BGEZALL:
2613 gen_op_gez(bcond, t0);
2614 blink = 31;
2615 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2616 goto likely;
2617 case OPC_BGTZ:
2618 gen_op_gtz(bcond, t0);
2619 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2620 goto not_likely;
2621 case OPC_BGTZL:
2622 gen_op_gtz(bcond, t0);
2623 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2624 goto likely;
2625 case OPC_BLEZ:
2626 gen_op_lez(bcond, t0);
2627 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2628 goto not_likely;
2629 case OPC_BLEZL:
2630 gen_op_lez(bcond, t0);
2631 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2632 goto likely;
2633 case OPC_BLTZ:
2634 gen_op_ltz(bcond, t0);
2635 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2636 goto not_likely;
2637 case OPC_BLTZL:
2638 gen_op_ltz(bcond, t0);
2639 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2640 goto likely;
2641 case OPC_BLTZAL:
2642 gen_op_ltz(bcond, t0);
2643 blink = 31;
2644 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2645 not_likely:
2646 ctx->hflags |= MIPS_HFLAG_BC;
2647 break;
2648 case OPC_BLTZALL:
2649 gen_op_ltz(bcond, t0);
2650 blink = 31;
2651 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2652 likely:
2653 ctx->hflags |= MIPS_HFLAG_BL;
2654 break;
2655 default:
2656 MIPS_INVAL("conditional branch/jump");
2657 generate_exception(ctx, EXCP_RI);
2658 goto out;
2661 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2662 blink, ctx->hflags, btgt);
2664 ctx->btarget = btgt;
2665 if (blink > 0) {
2666 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8);
2669 out:
2670 tcg_temp_free(t0);
2671 tcg_temp_free(t1);
2674 /* special3 bitfield operations */
2675 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2676 int rs, int lsb, int msb)
2678 TCGv t0 = tcg_temp_new();
2679 TCGv t1 = tcg_temp_new();
2680 target_ulong mask;
2682 gen_load_gpr(t1, rs);
2683 switch (opc) {
2684 case OPC_EXT:
2685 if (lsb + msb > 31)
2686 goto fail;
2687 tcg_gen_shri_tl(t0, t1, lsb);
2688 if (msb != 31) {
2689 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2690 } else {
2691 tcg_gen_ext32s_tl(t0, t0);
2693 break;
2694 #if defined(TARGET_MIPS64)
2695 case OPC_DEXTM:
2696 tcg_gen_shri_tl(t0, t1, lsb);
2697 if (msb != 31) {
2698 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2700 break;
2701 case OPC_DEXTU:
2702 tcg_gen_shri_tl(t0, t1, lsb + 32);
2703 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2704 break;
2705 case OPC_DEXT:
2706 tcg_gen_shri_tl(t0, t1, lsb);
2707 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2708 break;
2709 #endif
2710 case OPC_INS:
2711 if (lsb > msb)
2712 goto fail;
2713 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2714 gen_load_gpr(t0, rt);
2715 tcg_gen_andi_tl(t0, t0, ~mask);
2716 tcg_gen_shli_tl(t1, t1, lsb);
2717 tcg_gen_andi_tl(t1, t1, mask);
2718 tcg_gen_or_tl(t0, t0, t1);
2719 tcg_gen_ext32s_tl(t0, t0);
2720 break;
2721 #if defined(TARGET_MIPS64)
2722 case OPC_DINSM:
2723 if (lsb > msb)
2724 goto fail;
2725 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2726 gen_load_gpr(t0, rt);
2727 tcg_gen_andi_tl(t0, t0, ~mask);
2728 tcg_gen_shli_tl(t1, t1, lsb);
2729 tcg_gen_andi_tl(t1, t1, mask);
2730 tcg_gen_or_tl(t0, t0, t1);
2731 break;
2732 case OPC_DINSU:
2733 if (lsb > msb)
2734 goto fail;
2735 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2736 gen_load_gpr(t0, rt);
2737 tcg_gen_andi_tl(t0, t0, ~mask);
2738 tcg_gen_shli_tl(t1, t1, lsb + 32);
2739 tcg_gen_andi_tl(t1, t1, mask);
2740 tcg_gen_or_tl(t0, t0, t1);
2741 break;
2742 case OPC_DINS:
2743 if (lsb > msb)
2744 goto fail;
2745 gen_load_gpr(t0, rt);
2746 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2747 gen_load_gpr(t0, rt);
2748 tcg_gen_andi_tl(t0, t0, ~mask);
2749 tcg_gen_shli_tl(t1, t1, lsb);
2750 tcg_gen_andi_tl(t1, t1, mask);
2751 tcg_gen_or_tl(t0, t0, t1);
2752 break;
2753 #endif
2754 default:
2755 fail:
2756 MIPS_INVAL("bitops");
2757 generate_exception(ctx, EXCP_RI);
2758 tcg_temp_free(t0);
2759 tcg_temp_free(t1);
2760 return;
2762 gen_store_gpr(t0, rt);
2763 tcg_temp_free(t0);
2764 tcg_temp_free(t1);
2767 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2769 TCGv t0;
2771 if (rd == 0) {
2772 /* If no destination, treat it as a NOP. */
2773 MIPS_DEBUG("NOP");
2774 return;
2777 t0 = tcg_temp_new();
2778 gen_load_gpr(t0, rt);
2779 switch (op2) {
2780 case OPC_WSBH:
2782 TCGv t1 = tcg_temp_new();
2784 tcg_gen_shri_tl(t1, t0, 8);
2785 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2786 tcg_gen_shli_tl(t0, t0, 8);
2787 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2788 tcg_gen_or_tl(t0, t0, t1);
2789 tcg_temp_free(t1);
2790 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2792 break;
2793 case OPC_SEB:
2794 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2795 break;
2796 case OPC_SEH:
2797 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2798 break;
2799 #if defined(TARGET_MIPS64)
2800 case OPC_DSBH:
2802 TCGv t1 = tcg_temp_new();
2804 tcg_gen_shri_tl(t1, t0, 8);
2805 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2806 tcg_gen_shli_tl(t0, t0, 8);
2807 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2808 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2809 tcg_temp_free(t1);
2811 break;
2812 case OPC_DSHD:
2814 TCGv t1 = tcg_temp_new();
2816 tcg_gen_shri_tl(t1, t0, 16);
2817 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2818 tcg_gen_shli_tl(t0, t0, 16);
2819 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2820 tcg_gen_or_tl(t0, t0, t1);
2821 tcg_gen_shri_tl(t1, t0, 32);
2822 tcg_gen_shli_tl(t0, t0, 32);
2823 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2824 tcg_temp_free(t1);
2826 break;
2827 #endif
2828 default:
2829 MIPS_INVAL("bsfhl");
2830 generate_exception(ctx, EXCP_RI);
2831 tcg_temp_free(t0);
2832 return;
2834 tcg_temp_free(t0);
2837 #ifndef CONFIG_USER_ONLY
2838 /* CP0 (MMU and control) */
2839 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
2841 TCGv_i32 t0 = tcg_temp_new_i32();
2843 tcg_gen_ld_i32(t0, cpu_env, off);
2844 tcg_gen_ext_i32_tl(arg, t0);
2845 tcg_temp_free_i32(t0);
2848 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
2850 tcg_gen_ld_tl(arg, cpu_env, off);
2851 tcg_gen_ext32s_tl(arg, arg);
2854 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
2856 TCGv_i32 t0 = tcg_temp_new_i32();
2858 tcg_gen_trunc_tl_i32(t0, arg);
2859 tcg_gen_st_i32(t0, cpu_env, off);
2860 tcg_temp_free_i32(t0);
2863 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
2865 tcg_gen_ext32s_tl(arg, arg);
2866 tcg_gen_st_tl(arg, cpu_env, off);
2869 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
2871 const char *rn = "invalid";
2873 if (sel != 0)
2874 check_insn(env, ctx, ISA_MIPS32);
2876 switch (reg) {
2877 case 0:
2878 switch (sel) {
2879 case 0:
2880 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
2881 rn = "Index";
2882 break;
2883 case 1:
2884 check_insn(env, ctx, ASE_MT);
2885 gen_helper_mfc0_mvpcontrol(arg);
2886 rn = "MVPControl";
2887 break;
2888 case 2:
2889 check_insn(env, ctx, ASE_MT);
2890 gen_helper_mfc0_mvpconf0(arg);
2891 rn = "MVPConf0";
2892 break;
2893 case 3:
2894 check_insn(env, ctx, ASE_MT);
2895 gen_helper_mfc0_mvpconf1(arg);
2896 rn = "MVPConf1";
2897 break;
2898 default:
2899 goto die;
2901 break;
2902 case 1:
2903 switch (sel) {
2904 case 0:
2905 gen_helper_mfc0_random(arg);
2906 rn = "Random";
2907 break;
2908 case 1:
2909 check_insn(env, ctx, ASE_MT);
2910 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
2911 rn = "VPEControl";
2912 break;
2913 case 2:
2914 check_insn(env, ctx, ASE_MT);
2915 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
2916 rn = "VPEConf0";
2917 break;
2918 case 3:
2919 check_insn(env, ctx, ASE_MT);
2920 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
2921 rn = "VPEConf1";
2922 break;
2923 case 4:
2924 check_insn(env, ctx, ASE_MT);
2925 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
2926 rn = "YQMask";
2927 break;
2928 case 5:
2929 check_insn(env, ctx, ASE_MT);
2930 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
2931 rn = "VPESchedule";
2932 break;
2933 case 6:
2934 check_insn(env, ctx, ASE_MT);
2935 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
2936 rn = "VPEScheFBack";
2937 break;
2938 case 7:
2939 check_insn(env, ctx, ASE_MT);
2940 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
2941 rn = "VPEOpt";
2942 break;
2943 default:
2944 goto die;
2946 break;
2947 case 2:
2948 switch (sel) {
2949 case 0:
2950 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2951 tcg_gen_ext32s_tl(arg, arg);
2952 rn = "EntryLo0";
2953 break;
2954 case 1:
2955 check_insn(env, ctx, ASE_MT);
2956 gen_helper_mfc0_tcstatus(arg);
2957 rn = "TCStatus";
2958 break;
2959 case 2:
2960 check_insn(env, ctx, ASE_MT);
2961 gen_helper_mfc0_tcbind(arg);
2962 rn = "TCBind";
2963 break;
2964 case 3:
2965 check_insn(env, ctx, ASE_MT);
2966 gen_helper_mfc0_tcrestart(arg);
2967 rn = "TCRestart";
2968 break;
2969 case 4:
2970 check_insn(env, ctx, ASE_MT);
2971 gen_helper_mfc0_tchalt(arg);
2972 rn = "TCHalt";
2973 break;
2974 case 5:
2975 check_insn(env, ctx, ASE_MT);
2976 gen_helper_mfc0_tccontext(arg);
2977 rn = "TCContext";
2978 break;
2979 case 6:
2980 check_insn(env, ctx, ASE_MT);
2981 gen_helper_mfc0_tcschedule(arg);
2982 rn = "TCSchedule";
2983 break;
2984 case 7:
2985 check_insn(env, ctx, ASE_MT);
2986 gen_helper_mfc0_tcschefback(arg);
2987 rn = "TCScheFBack";
2988 break;
2989 default:
2990 goto die;
2992 break;
2993 case 3:
2994 switch (sel) {
2995 case 0:
2996 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2997 tcg_gen_ext32s_tl(arg, arg);
2998 rn = "EntryLo1";
2999 break;
3000 default:
3001 goto die;
3003 break;
3004 case 4:
3005 switch (sel) {
3006 case 0:
3007 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3008 tcg_gen_ext32s_tl(arg, arg);
3009 rn = "Context";
3010 break;
3011 case 1:
3012 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3013 rn = "ContextConfig";
3014 // break;
3015 default:
3016 goto die;
3018 break;
3019 case 5:
3020 switch (sel) {
3021 case 0:
3022 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
3023 rn = "PageMask";
3024 break;
3025 case 1:
3026 check_insn(env, ctx, ISA_MIPS32R2);
3027 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
3028 rn = "PageGrain";
3029 break;
3030 default:
3031 goto die;
3033 break;
3034 case 6:
3035 switch (sel) {
3036 case 0:
3037 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
3038 rn = "Wired";
3039 break;
3040 case 1:
3041 check_insn(env, ctx, ISA_MIPS32R2);
3042 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
3043 rn = "SRSConf0";
3044 break;
3045 case 2:
3046 check_insn(env, ctx, ISA_MIPS32R2);
3047 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
3048 rn = "SRSConf1";
3049 break;
3050 case 3:
3051 check_insn(env, ctx, ISA_MIPS32R2);
3052 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
3053 rn = "SRSConf2";
3054 break;
3055 case 4:
3056 check_insn(env, ctx, ISA_MIPS32R2);
3057 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
3058 rn = "SRSConf3";
3059 break;
3060 case 5:
3061 check_insn(env, ctx, ISA_MIPS32R2);
3062 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
3063 rn = "SRSConf4";
3064 break;
3065 default:
3066 goto die;
3068 break;
3069 case 7:
3070 switch (sel) {
3071 case 0:
3072 check_insn(env, ctx, ISA_MIPS32R2);
3073 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
3074 rn = "HWREna";
3075 break;
3076 default:
3077 goto die;
3079 break;
3080 case 8:
3081 switch (sel) {
3082 case 0:
3083 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3084 tcg_gen_ext32s_tl(arg, arg);
3085 rn = "BadVAddr";
3086 break;
3087 default:
3088 goto die;
3090 break;
3091 case 9:
3092 switch (sel) {
3093 case 0:
3094 /* Mark as an IO operation because we read the time. */
3095 if (use_icount)
3096 gen_io_start();
3097 gen_helper_mfc0_count(arg);
3098 if (use_icount) {
3099 gen_io_end();
3100 ctx->bstate = BS_STOP;
3102 rn = "Count";
3103 break;
3104 /* 6,7 are implementation dependent */
3105 default:
3106 goto die;
3108 break;
3109 case 10:
3110 switch (sel) {
3111 case 0:
3112 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3113 tcg_gen_ext32s_tl(arg, arg);
3114 rn = "EntryHi";
3115 break;
3116 default:
3117 goto die;
3119 break;
3120 case 11:
3121 switch (sel) {
3122 case 0:
3123 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
3124 rn = "Compare";
3125 break;
3126 /* 6,7 are implementation dependent */
3127 default:
3128 goto die;
3130 break;
3131 case 12:
3132 switch (sel) {
3133 case 0:
3134 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
3135 rn = "Status";
3136 break;
3137 case 1:
3138 check_insn(env, ctx, ISA_MIPS32R2);
3139 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
3140 rn = "IntCtl";
3141 break;
3142 case 2:
3143 check_insn(env, ctx, ISA_MIPS32R2);
3144 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
3145 rn = "SRSCtl";
3146 break;
3147 case 3:
3148 check_insn(env, ctx, ISA_MIPS32R2);
3149 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
3150 rn = "SRSMap";
3151 break;
3152 default:
3153 goto die;
3155 break;
3156 case 13:
3157 switch (sel) {
3158 case 0:
3159 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
3160 rn = "Cause";
3161 break;
3162 default:
3163 goto die;
3165 break;
3166 case 14:
3167 switch (sel) {
3168 case 0:
3169 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3170 tcg_gen_ext32s_tl(arg, arg);
3171 rn = "EPC";
3172 break;
3173 default:
3174 goto die;
3176 break;
3177 case 15:
3178 switch (sel) {
3179 case 0:
3180 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
3181 rn = "PRid";
3182 break;
3183 case 1:
3184 check_insn(env, ctx, ISA_MIPS32R2);
3185 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
3186 rn = "EBase";
3187 break;
3188 default:
3189 goto die;
3191 break;
3192 case 16:
3193 switch (sel) {
3194 case 0:
3195 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
3196 rn = "Config";
3197 break;
3198 case 1:
3199 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
3200 rn = "Config1";
3201 break;
3202 case 2:
3203 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
3204 rn = "Config2";
3205 break;
3206 case 3:
3207 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
3208 rn = "Config3";
3209 break;
3210 /* 4,5 are reserved */
3211 /* 6,7 are implementation dependent */
3212 case 6:
3213 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
3214 rn = "Config6";
3215 break;
3216 case 7:
3217 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
3218 rn = "Config7";
3219 break;
3220 default:
3221 goto die;
3223 break;
3224 case 17:
3225 switch (sel) {
3226 case 0:
3227 gen_helper_mfc0_lladdr(arg);
3228 rn = "LLAddr";
3229 break;
3230 default:
3231 goto die;
3233 break;
3234 case 18:
3235 switch (sel) {
3236 case 0 ... 7:
3237 gen_helper_1i(mfc0_watchlo, arg, sel);
3238 rn = "WatchLo";
3239 break;
3240 default:
3241 goto die;
3243 break;
3244 case 19:
3245 switch (sel) {
3246 case 0 ...7:
3247 gen_helper_1i(mfc0_watchhi, arg, sel);
3248 rn = "WatchHi";
3249 break;
3250 default:
3251 goto die;
3253 break;
3254 case 20:
3255 switch (sel) {
3256 case 0:
3257 #if defined(TARGET_MIPS64)
3258 check_insn(env, ctx, ISA_MIPS3);
3259 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3260 tcg_gen_ext32s_tl(arg, arg);
3261 rn = "XContext";
3262 break;
3263 #endif
3264 default:
3265 goto die;
3267 break;
3268 case 21:
3269 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3270 switch (sel) {
3271 case 0:
3272 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
3273 rn = "Framemask";
3274 break;
3275 default:
3276 goto die;
3278 break;
3279 case 22:
3280 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3281 rn = "'Diagnostic"; /* implementation dependent */
3282 break;
3283 case 23:
3284 switch (sel) {
3285 case 0:
3286 gen_helper_mfc0_debug(arg); /* EJTAG support */
3287 rn = "Debug";
3288 break;
3289 case 1:
3290 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3291 rn = "TraceControl";
3292 // break;
3293 case 2:
3294 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3295 rn = "TraceControl2";
3296 // break;
3297 case 3:
3298 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3299 rn = "UserTraceData";
3300 // break;
3301 case 4:
3302 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3303 rn = "TraceBPC";
3304 // break;
3305 default:
3306 goto die;
3308 break;
3309 case 24:
3310 switch (sel) {
3311 case 0:
3312 /* EJTAG support */
3313 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3314 tcg_gen_ext32s_tl(arg, arg);
3315 rn = "DEPC";
3316 break;
3317 default:
3318 goto die;
3320 break;
3321 case 25:
3322 switch (sel) {
3323 case 0:
3324 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
3325 rn = "Performance0";
3326 break;
3327 case 1:
3328 // gen_helper_mfc0_performance1(arg);
3329 rn = "Performance1";
3330 // break;
3331 case 2:
3332 // gen_helper_mfc0_performance2(arg);
3333 rn = "Performance2";
3334 // break;
3335 case 3:
3336 // gen_helper_mfc0_performance3(arg);
3337 rn = "Performance3";
3338 // break;
3339 case 4:
3340 // gen_helper_mfc0_performance4(arg);
3341 rn = "Performance4";
3342 // break;
3343 case 5:
3344 // gen_helper_mfc0_performance5(arg);
3345 rn = "Performance5";
3346 // break;
3347 case 6:
3348 // gen_helper_mfc0_performance6(arg);
3349 rn = "Performance6";
3350 // break;
3351 case 7:
3352 // gen_helper_mfc0_performance7(arg);
3353 rn = "Performance7";
3354 // break;
3355 default:
3356 goto die;
3358 break;
3359 case 26:
3360 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3361 rn = "ECC";
3362 break;
3363 case 27:
3364 switch (sel) {
3365 case 0 ... 3:
3366 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3367 rn = "CacheErr";
3368 break;
3369 default:
3370 goto die;
3372 break;
3373 case 28:
3374 switch (sel) {
3375 case 0:
3376 case 2:
3377 case 4:
3378 case 6:
3379 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
3380 rn = "TagLo";
3381 break;
3382 case 1:
3383 case 3:
3384 case 5:
3385 case 7:
3386 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
3387 rn = "DataLo";
3388 break;
3389 default:
3390 goto die;
3392 break;
3393 case 29:
3394 switch (sel) {
3395 case 0:
3396 case 2:
3397 case 4:
3398 case 6:
3399 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
3400 rn = "TagHi";
3401 break;
3402 case 1:
3403 case 3:
3404 case 5:
3405 case 7:
3406 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
3407 rn = "DataHi";
3408 break;
3409 default:
3410 goto die;
3412 break;
3413 case 30:
3414 switch (sel) {
3415 case 0:
3416 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3417 tcg_gen_ext32s_tl(arg, arg);
3418 rn = "ErrorEPC";
3419 break;
3420 default:
3421 goto die;
3423 break;
3424 case 31:
3425 switch (sel) {
3426 case 0:
3427 /* EJTAG support */
3428 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
3429 rn = "DESAVE";
3430 break;
3431 default:
3432 goto die;
3434 break;
3435 default:
3436 goto die;
3438 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3439 return;
3441 die:
3442 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3443 generate_exception(ctx, EXCP_RI);
3446 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3448 const char *rn = "invalid";
3450 if (sel != 0)
3451 check_insn(env, ctx, ISA_MIPS32);
3453 if (use_icount)
3454 gen_io_start();
3456 switch (reg) {
3457 case 0:
3458 switch (sel) {
3459 case 0:
3460 gen_helper_mtc0_index(arg);
3461 rn = "Index";
3462 break;
3463 case 1:
3464 check_insn(env, ctx, ASE_MT);
3465 gen_helper_mtc0_mvpcontrol(arg);
3466 rn = "MVPControl";
3467 break;
3468 case 2:
3469 check_insn(env, ctx, ASE_MT);
3470 /* ignored */
3471 rn = "MVPConf0";
3472 break;
3473 case 3:
3474 check_insn(env, ctx, ASE_MT);
3475 /* ignored */
3476 rn = "MVPConf1";
3477 break;
3478 default:
3479 goto die;
3481 break;
3482 case 1:
3483 switch (sel) {
3484 case 0:
3485 /* ignored */
3486 rn = "Random";
3487 break;
3488 case 1:
3489 check_insn(env, ctx, ASE_MT);
3490 gen_helper_mtc0_vpecontrol(arg);
3491 rn = "VPEControl";
3492 break;
3493 case 2:
3494 check_insn(env, ctx, ASE_MT);
3495 gen_helper_mtc0_vpeconf0(arg);
3496 rn = "VPEConf0";
3497 break;
3498 case 3:
3499 check_insn(env, ctx, ASE_MT);
3500 gen_helper_mtc0_vpeconf1(arg);
3501 rn = "VPEConf1";
3502 break;
3503 case 4:
3504 check_insn(env, ctx, ASE_MT);
3505 gen_helper_mtc0_yqmask(arg);
3506 rn = "YQMask";
3507 break;
3508 case 5:
3509 check_insn(env, ctx, ASE_MT);
3510 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
3511 rn = "VPESchedule";
3512 break;
3513 case 6:
3514 check_insn(env, ctx, ASE_MT);
3515 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3516 rn = "VPEScheFBack";
3517 break;
3518 case 7:
3519 check_insn(env, ctx, ASE_MT);
3520 gen_helper_mtc0_vpeopt(arg);
3521 rn = "VPEOpt";
3522 break;
3523 default:
3524 goto die;
3526 break;
3527 case 2:
3528 switch (sel) {
3529 case 0:
3530 gen_helper_mtc0_entrylo0(arg);
3531 rn = "EntryLo0";
3532 break;
3533 case 1:
3534 check_insn(env, ctx, ASE_MT);
3535 gen_helper_mtc0_tcstatus(arg);
3536 rn = "TCStatus";
3537 break;
3538 case 2:
3539 check_insn(env, ctx, ASE_MT);
3540 gen_helper_mtc0_tcbind(arg);
3541 rn = "TCBind";
3542 break;
3543 case 3:
3544 check_insn(env, ctx, ASE_MT);
3545 gen_helper_mtc0_tcrestart(arg);
3546 rn = "TCRestart";
3547 break;
3548 case 4:
3549 check_insn(env, ctx, ASE_MT);
3550 gen_helper_mtc0_tchalt(arg);
3551 rn = "TCHalt";
3552 break;
3553 case 5:
3554 check_insn(env, ctx, ASE_MT);
3555 gen_helper_mtc0_tccontext(arg);
3556 rn = "TCContext";
3557 break;
3558 case 6:
3559 check_insn(env, ctx, ASE_MT);
3560 gen_helper_mtc0_tcschedule(arg);
3561 rn = "TCSchedule";
3562 break;
3563 case 7:
3564 check_insn(env, ctx, ASE_MT);
3565 gen_helper_mtc0_tcschefback(arg);
3566 rn = "TCScheFBack";
3567 break;
3568 default:
3569 goto die;
3571 break;
3572 case 3:
3573 switch (sel) {
3574 case 0:
3575 gen_helper_mtc0_entrylo1(arg);
3576 rn = "EntryLo1";
3577 break;
3578 default:
3579 goto die;
3581 break;
3582 case 4:
3583 switch (sel) {
3584 case 0:
3585 gen_helper_mtc0_context(arg);
3586 rn = "Context";
3587 break;
3588 case 1:
3589 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3590 rn = "ContextConfig";
3591 // break;
3592 default:
3593 goto die;
3595 break;
3596 case 5:
3597 switch (sel) {
3598 case 0:
3599 gen_helper_mtc0_pagemask(arg);
3600 rn = "PageMask";
3601 break;
3602 case 1:
3603 check_insn(env, ctx, ISA_MIPS32R2);
3604 gen_helper_mtc0_pagegrain(arg);
3605 rn = "PageGrain";
3606 break;
3607 default:
3608 goto die;
3610 break;
3611 case 6:
3612 switch (sel) {
3613 case 0:
3614 gen_helper_mtc0_wired(arg);
3615 rn = "Wired";
3616 break;
3617 case 1:
3618 check_insn(env, ctx, ISA_MIPS32R2);
3619 gen_helper_mtc0_srsconf0(arg);
3620 rn = "SRSConf0";
3621 break;
3622 case 2:
3623 check_insn(env, ctx, ISA_MIPS32R2);
3624 gen_helper_mtc0_srsconf1(arg);
3625 rn = "SRSConf1";
3626 break;
3627 case 3:
3628 check_insn(env, ctx, ISA_MIPS32R2);
3629 gen_helper_mtc0_srsconf2(arg);
3630 rn = "SRSConf2";
3631 break;
3632 case 4:
3633 check_insn(env, ctx, ISA_MIPS32R2);
3634 gen_helper_mtc0_srsconf3(arg);
3635 rn = "SRSConf3";
3636 break;
3637 case 5:
3638 check_insn(env, ctx, ISA_MIPS32R2);
3639 gen_helper_mtc0_srsconf4(arg);
3640 rn = "SRSConf4";
3641 break;
3642 default:
3643 goto die;
3645 break;
3646 case 7:
3647 switch (sel) {
3648 case 0:
3649 check_insn(env, ctx, ISA_MIPS32R2);
3650 gen_helper_mtc0_hwrena(arg);
3651 rn = "HWREna";
3652 break;
3653 default:
3654 goto die;
3656 break;
3657 case 8:
3658 /* ignored */
3659 rn = "BadVAddr";
3660 break;
3661 case 9:
3662 switch (sel) {
3663 case 0:
3664 gen_helper_mtc0_count(arg);
3665 rn = "Count";
3666 break;
3667 /* 6,7 are implementation dependent */
3668 default:
3669 goto die;
3671 break;
3672 case 10:
3673 switch (sel) {
3674 case 0:
3675 gen_helper_mtc0_entryhi(arg);
3676 rn = "EntryHi";
3677 break;
3678 default:
3679 goto die;
3681 break;
3682 case 11:
3683 switch (sel) {
3684 case 0:
3685 gen_helper_mtc0_compare(arg);
3686 rn = "Compare";
3687 break;
3688 /* 6,7 are implementation dependent */
3689 default:
3690 goto die;
3692 break;
3693 case 12:
3694 switch (sel) {
3695 case 0:
3696 save_cpu_state(ctx, 1);
3697 gen_helper_mtc0_status(arg);
3698 /* BS_STOP isn't good enough here, hflags may have changed. */
3699 gen_save_pc(ctx->pc + 4);
3700 ctx->bstate = BS_EXCP;
3701 rn = "Status";
3702 break;
3703 case 1:
3704 check_insn(env, ctx, ISA_MIPS32R2);
3705 gen_helper_mtc0_intctl(arg);
3706 /* Stop translation as we may have switched the execution mode */
3707 ctx->bstate = BS_STOP;
3708 rn = "IntCtl";
3709 break;
3710 case 2:
3711 check_insn(env, ctx, ISA_MIPS32R2);
3712 gen_helper_mtc0_srsctl(arg);
3713 /* Stop translation as we may have switched the execution mode */
3714 ctx->bstate = BS_STOP;
3715 rn = "SRSCtl";
3716 break;
3717 case 3:
3718 check_insn(env, ctx, ISA_MIPS32R2);
3719 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
3720 /* Stop translation as we may have switched the execution mode */
3721 ctx->bstate = BS_STOP;
3722 rn = "SRSMap";
3723 break;
3724 default:
3725 goto die;
3727 break;
3728 case 13:
3729 switch (sel) {
3730 case 0:
3731 save_cpu_state(ctx, 1);
3732 gen_helper_mtc0_cause(arg);
3733 rn = "Cause";
3734 break;
3735 default:
3736 goto die;
3738 break;
3739 case 14:
3740 switch (sel) {
3741 case 0:
3742 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
3743 rn = "EPC";
3744 break;
3745 default:
3746 goto die;
3748 break;
3749 case 15:
3750 switch (sel) {
3751 case 0:
3752 /* ignored */
3753 rn = "PRid";
3754 break;
3755 case 1:
3756 check_insn(env, ctx, ISA_MIPS32R2);
3757 gen_helper_mtc0_ebase(arg);
3758 rn = "EBase";
3759 break;
3760 default:
3761 goto die;
3763 break;
3764 case 16:
3765 switch (sel) {
3766 case 0:
3767 gen_helper_mtc0_config0(arg);
3768 rn = "Config";
3769 /* Stop translation as we may have switched the execution mode */
3770 ctx->bstate = BS_STOP;
3771 break;
3772 case 1:
3773 /* ignored, read only */
3774 rn = "Config1";
3775 break;
3776 case 2:
3777 gen_helper_mtc0_config2(arg);
3778 rn = "Config2";
3779 /* Stop translation as we may have switched the execution mode */
3780 ctx->bstate = BS_STOP;
3781 break;
3782 case 3:
3783 /* ignored, read only */
3784 rn = "Config3";
3785 break;
3786 /* 4,5 are reserved */
3787 /* 6,7 are implementation dependent */
3788 case 6:
3789 /* ignored */
3790 rn = "Config6";
3791 break;
3792 case 7:
3793 /* ignored */
3794 rn = "Config7";
3795 break;
3796 default:
3797 rn = "Invalid config selector";
3798 goto die;
3800 break;
3801 case 17:
3802 switch (sel) {
3803 case 0:
3804 /* ignored */
3805 rn = "LLAddr";
3806 break;
3807 default:
3808 goto die;
3810 break;
3811 case 18:
3812 switch (sel) {
3813 case 0 ... 7:
3814 gen_helper_1i(mtc0_watchlo, arg, sel);
3815 rn = "WatchLo";
3816 break;
3817 default:
3818 goto die;
3820 break;
3821 case 19:
3822 switch (sel) {
3823 case 0 ... 7:
3824 gen_helper_1i(mtc0_watchhi, arg, sel);
3825 rn = "WatchHi";
3826 break;
3827 default:
3828 goto die;
3830 break;
3831 case 20:
3832 switch (sel) {
3833 case 0:
3834 #if defined(TARGET_MIPS64)
3835 check_insn(env, ctx, ISA_MIPS3);
3836 gen_helper_mtc0_xcontext(arg);
3837 rn = "XContext";
3838 break;
3839 #endif
3840 default:
3841 goto die;
3843 break;
3844 case 21:
3845 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3846 switch (sel) {
3847 case 0:
3848 gen_helper_mtc0_framemask(arg);
3849 rn = "Framemask";
3850 break;
3851 default:
3852 goto die;
3854 break;
3855 case 22:
3856 /* ignored */
3857 rn = "Diagnostic"; /* implementation dependent */
3858 break;
3859 case 23:
3860 switch (sel) {
3861 case 0:
3862 gen_helper_mtc0_debug(arg); /* EJTAG support */
3863 /* BS_STOP isn't good enough here, hflags may have changed. */
3864 gen_save_pc(ctx->pc + 4);
3865 ctx->bstate = BS_EXCP;
3866 rn = "Debug";
3867 break;
3868 case 1:
3869 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
3870 rn = "TraceControl";
3871 /* Stop translation as we may have switched the execution mode */
3872 ctx->bstate = BS_STOP;
3873 // break;
3874 case 2:
3875 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
3876 rn = "TraceControl2";
3877 /* Stop translation as we may have switched the execution mode */
3878 ctx->bstate = BS_STOP;
3879 // break;
3880 case 3:
3881 /* Stop translation as we may have switched the execution mode */
3882 ctx->bstate = BS_STOP;
3883 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
3884 rn = "UserTraceData";
3885 /* Stop translation as we may have switched the execution mode */
3886 ctx->bstate = BS_STOP;
3887 // break;
3888 case 4:
3889 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
3890 /* Stop translation as we may have switched the execution mode */
3891 ctx->bstate = BS_STOP;
3892 rn = "TraceBPC";
3893 // break;
3894 default:
3895 goto die;
3897 break;
3898 case 24:
3899 switch (sel) {
3900 case 0:
3901 /* EJTAG support */
3902 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
3903 rn = "DEPC";
3904 break;
3905 default:
3906 goto die;
3908 break;
3909 case 25:
3910 switch (sel) {
3911 case 0:
3912 gen_helper_mtc0_performance0(arg);
3913 rn = "Performance0";
3914 break;
3915 case 1:
3916 // gen_helper_mtc0_performance1(arg);
3917 rn = "Performance1";
3918 // break;
3919 case 2:
3920 // gen_helper_mtc0_performance2(arg);
3921 rn = "Performance2";
3922 // break;
3923 case 3:
3924 // gen_helper_mtc0_performance3(arg);
3925 rn = "Performance3";
3926 // break;
3927 case 4:
3928 // gen_helper_mtc0_performance4(arg);
3929 rn = "Performance4";
3930 // break;
3931 case 5:
3932 // gen_helper_mtc0_performance5(arg);
3933 rn = "Performance5";
3934 // break;
3935 case 6:
3936 // gen_helper_mtc0_performance6(arg);
3937 rn = "Performance6";
3938 // break;
3939 case 7:
3940 // gen_helper_mtc0_performance7(arg);
3941 rn = "Performance7";
3942 // break;
3943 default:
3944 goto die;
3946 break;
3947 case 26:
3948 /* ignored */
3949 rn = "ECC";
3950 break;
3951 case 27:
3952 switch (sel) {
3953 case 0 ... 3:
3954 /* ignored */
3955 rn = "CacheErr";
3956 break;
3957 default:
3958 goto die;
3960 break;
3961 case 28:
3962 switch (sel) {
3963 case 0:
3964 case 2:
3965 case 4:
3966 case 6:
3967 gen_helper_mtc0_taglo(arg);
3968 rn = "TagLo";
3969 break;
3970 case 1:
3971 case 3:
3972 case 5:
3973 case 7:
3974 gen_helper_mtc0_datalo(arg);
3975 rn = "DataLo";
3976 break;
3977 default:
3978 goto die;
3980 break;
3981 case 29:
3982 switch (sel) {
3983 case 0:
3984 case 2:
3985 case 4:
3986 case 6:
3987 gen_helper_mtc0_taghi(arg);
3988 rn = "TagHi";
3989 break;
3990 case 1:
3991 case 3:
3992 case 5:
3993 case 7:
3994 gen_helper_mtc0_datahi(arg);
3995 rn = "DataHi";
3996 break;
3997 default:
3998 rn = "invalid sel";
3999 goto die;
4001 break;
4002 case 30:
4003 switch (sel) {
4004 case 0:
4005 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
4006 rn = "ErrorEPC";
4007 break;
4008 default:
4009 goto die;
4011 break;
4012 case 31:
4013 switch (sel) {
4014 case 0:
4015 /* EJTAG support */
4016 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
4017 rn = "DESAVE";
4018 break;
4019 default:
4020 goto die;
4022 /* Stop translation as we may have switched the execution mode */
4023 ctx->bstate = BS_STOP;
4024 break;
4025 default:
4026 goto die;
4028 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4029 /* For simplicity assume that all writes can cause interrupts. */
4030 if (use_icount) {
4031 gen_io_end();
4032 ctx->bstate = BS_STOP;
4034 return;
4036 die:
4037 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4038 generate_exception(ctx, EXCP_RI);
4041 #if defined(TARGET_MIPS64)
4042 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4044 const char *rn = "invalid";
4046 if (sel != 0)
4047 check_insn(env, ctx, ISA_MIPS64);
4049 switch (reg) {
4050 case 0:
4051 switch (sel) {
4052 case 0:
4053 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
4054 rn = "Index";
4055 break;
4056 case 1:
4057 check_insn(env, ctx, ASE_MT);
4058 gen_helper_mfc0_mvpcontrol(arg);
4059 rn = "MVPControl";
4060 break;
4061 case 2:
4062 check_insn(env, ctx, ASE_MT);
4063 gen_helper_mfc0_mvpconf0(arg);
4064 rn = "MVPConf0";
4065 break;
4066 case 3:
4067 check_insn(env, ctx, ASE_MT);
4068 gen_helper_mfc0_mvpconf1(arg);
4069 rn = "MVPConf1";
4070 break;
4071 default:
4072 goto die;
4074 break;
4075 case 1:
4076 switch (sel) {
4077 case 0:
4078 gen_helper_mfc0_random(arg);
4079 rn = "Random";
4080 break;
4081 case 1:
4082 check_insn(env, ctx, ASE_MT);
4083 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
4084 rn = "VPEControl";
4085 break;
4086 case 2:
4087 check_insn(env, ctx, ASE_MT);
4088 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
4089 rn = "VPEConf0";
4090 break;
4091 case 3:
4092 check_insn(env, ctx, ASE_MT);
4093 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
4094 rn = "VPEConf1";
4095 break;
4096 case 4:
4097 check_insn(env, ctx, ASE_MT);
4098 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
4099 rn = "YQMask";
4100 break;
4101 case 5:
4102 check_insn(env, ctx, ASE_MT);
4103 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4104 rn = "VPESchedule";
4105 break;
4106 case 6:
4107 check_insn(env, ctx, ASE_MT);
4108 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4109 rn = "VPEScheFBack";
4110 break;
4111 case 7:
4112 check_insn(env, ctx, ASE_MT);
4113 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
4114 rn = "VPEOpt";
4115 break;
4116 default:
4117 goto die;
4119 break;
4120 case 2:
4121 switch (sel) {
4122 case 0:
4123 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4124 rn = "EntryLo0";
4125 break;
4126 case 1:
4127 check_insn(env, ctx, ASE_MT);
4128 gen_helper_mfc0_tcstatus(arg);
4129 rn = "TCStatus";
4130 break;
4131 case 2:
4132 check_insn(env, ctx, ASE_MT);
4133 gen_helper_mfc0_tcbind(arg);
4134 rn = "TCBind";
4135 break;
4136 case 3:
4137 check_insn(env, ctx, ASE_MT);
4138 gen_helper_dmfc0_tcrestart(arg);
4139 rn = "TCRestart";
4140 break;
4141 case 4:
4142 check_insn(env, ctx, ASE_MT);
4143 gen_helper_dmfc0_tchalt(arg);
4144 rn = "TCHalt";
4145 break;
4146 case 5:
4147 check_insn(env, ctx, ASE_MT);
4148 gen_helper_dmfc0_tccontext(arg);
4149 rn = "TCContext";
4150 break;
4151 case 6:
4152 check_insn(env, ctx, ASE_MT);
4153 gen_helper_dmfc0_tcschedule(arg);
4154 rn = "TCSchedule";
4155 break;
4156 case 7:
4157 check_insn(env, ctx, ASE_MT);
4158 gen_helper_dmfc0_tcschefback(arg);
4159 rn = "TCScheFBack";
4160 break;
4161 default:
4162 goto die;
4164 break;
4165 case 3:
4166 switch (sel) {
4167 case 0:
4168 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4169 rn = "EntryLo1";
4170 break;
4171 default:
4172 goto die;
4174 break;
4175 case 4:
4176 switch (sel) {
4177 case 0:
4178 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
4179 rn = "Context";
4180 break;
4181 case 1:
4182 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4183 rn = "ContextConfig";
4184 // break;
4185 default:
4186 goto die;
4188 break;
4189 case 5:
4190 switch (sel) {
4191 case 0:
4192 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
4193 rn = "PageMask";
4194 break;
4195 case 1:
4196 check_insn(env, ctx, ISA_MIPS32R2);
4197 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
4198 rn = "PageGrain";
4199 break;
4200 default:
4201 goto die;
4203 break;
4204 case 6:
4205 switch (sel) {
4206 case 0:
4207 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
4208 rn = "Wired";
4209 break;
4210 case 1:
4211 check_insn(env, ctx, ISA_MIPS32R2);
4212 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
4213 rn = "SRSConf0";
4214 break;
4215 case 2:
4216 check_insn(env, ctx, ISA_MIPS32R2);
4217 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
4218 rn = "SRSConf1";
4219 break;
4220 case 3:
4221 check_insn(env, ctx, ISA_MIPS32R2);
4222 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
4223 rn = "SRSConf2";
4224 break;
4225 case 4:
4226 check_insn(env, ctx, ISA_MIPS32R2);
4227 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
4228 rn = "SRSConf3";
4229 break;
4230 case 5:
4231 check_insn(env, ctx, ISA_MIPS32R2);
4232 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
4233 rn = "SRSConf4";
4234 break;
4235 default:
4236 goto die;
4238 break;
4239 case 7:
4240 switch (sel) {
4241 case 0:
4242 check_insn(env, ctx, ISA_MIPS32R2);
4243 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
4244 rn = "HWREna";
4245 break;
4246 default:
4247 goto die;
4249 break;
4250 case 8:
4251 switch (sel) {
4252 case 0:
4253 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4254 rn = "BadVAddr";
4255 break;
4256 default:
4257 goto die;
4259 break;
4260 case 9:
4261 switch (sel) {
4262 case 0:
4263 /* Mark as an IO operation because we read the time. */
4264 if (use_icount)
4265 gen_io_start();
4266 gen_helper_mfc0_count(arg);
4267 if (use_icount) {
4268 gen_io_end();
4269 ctx->bstate = BS_STOP;
4271 rn = "Count";
4272 break;
4273 /* 6,7 are implementation dependent */
4274 default:
4275 goto die;
4277 break;
4278 case 10:
4279 switch (sel) {
4280 case 0:
4281 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
4282 rn = "EntryHi";
4283 break;
4284 default:
4285 goto die;
4287 break;
4288 case 11:
4289 switch (sel) {
4290 case 0:
4291 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
4292 rn = "Compare";
4293 break;
4294 /* 6,7 are implementation dependent */
4295 default:
4296 goto die;
4298 break;
4299 case 12:
4300 switch (sel) {
4301 case 0:
4302 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
4303 rn = "Status";
4304 break;
4305 case 1:
4306 check_insn(env, ctx, ISA_MIPS32R2);
4307 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
4308 rn = "IntCtl";
4309 break;
4310 case 2:
4311 check_insn(env, ctx, ISA_MIPS32R2);
4312 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
4313 rn = "SRSCtl";
4314 break;
4315 case 3:
4316 check_insn(env, ctx, ISA_MIPS32R2);
4317 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
4318 rn = "SRSMap";
4319 break;
4320 default:
4321 goto die;
4323 break;
4324 case 13:
4325 switch (sel) {
4326 case 0:
4327 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
4328 rn = "Cause";
4329 break;
4330 default:
4331 goto die;
4333 break;
4334 case 14:
4335 switch (sel) {
4336 case 0:
4337 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4338 rn = "EPC";
4339 break;
4340 default:
4341 goto die;
4343 break;
4344 case 15:
4345 switch (sel) {
4346 case 0:
4347 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
4348 rn = "PRid";
4349 break;
4350 case 1:
4351 check_insn(env, ctx, ISA_MIPS32R2);
4352 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
4353 rn = "EBase";
4354 break;
4355 default:
4356 goto die;
4358 break;
4359 case 16:
4360 switch (sel) {
4361 case 0:
4362 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
4363 rn = "Config";
4364 break;
4365 case 1:
4366 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
4367 rn = "Config1";
4368 break;
4369 case 2:
4370 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
4371 rn = "Config2";
4372 break;
4373 case 3:
4374 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
4375 rn = "Config3";
4376 break;
4377 /* 6,7 are implementation dependent */
4378 case 6:
4379 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
4380 rn = "Config6";
4381 break;
4382 case 7:
4383 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
4384 rn = "Config7";
4385 break;
4386 default:
4387 goto die;
4389 break;
4390 case 17:
4391 switch (sel) {
4392 case 0:
4393 gen_helper_dmfc0_lladdr(arg);
4394 rn = "LLAddr";
4395 break;
4396 default:
4397 goto die;
4399 break;
4400 case 18:
4401 switch (sel) {
4402 case 0 ... 7:
4403 gen_helper_1i(dmfc0_watchlo, arg, sel);
4404 rn = "WatchLo";
4405 break;
4406 default:
4407 goto die;
4409 break;
4410 case 19:
4411 switch (sel) {
4412 case 0 ... 7:
4413 gen_helper_1i(mfc0_watchhi, arg, sel);
4414 rn = "WatchHi";
4415 break;
4416 default:
4417 goto die;
4419 break;
4420 case 20:
4421 switch (sel) {
4422 case 0:
4423 check_insn(env, ctx, ISA_MIPS3);
4424 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
4425 rn = "XContext";
4426 break;
4427 default:
4428 goto die;
4430 break;
4431 case 21:
4432 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4433 switch (sel) {
4434 case 0:
4435 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
4436 rn = "Framemask";
4437 break;
4438 default:
4439 goto die;
4441 break;
4442 case 22:
4443 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4444 rn = "'Diagnostic"; /* implementation dependent */
4445 break;
4446 case 23:
4447 switch (sel) {
4448 case 0:
4449 gen_helper_mfc0_debug(arg); /* EJTAG support */
4450 rn = "Debug";
4451 break;
4452 case 1:
4453 // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4454 rn = "TraceControl";
4455 // break;
4456 case 2:
4457 // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4458 rn = "TraceControl2";
4459 // break;
4460 case 3:
4461 // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4462 rn = "UserTraceData";
4463 // break;
4464 case 4:
4465 // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4466 rn = "TraceBPC";
4467 // break;
4468 default:
4469 goto die;
4471 break;
4472 case 24:
4473 switch (sel) {
4474 case 0:
4475 /* EJTAG support */
4476 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4477 rn = "DEPC";
4478 break;
4479 default:
4480 goto die;
4482 break;
4483 case 25:
4484 switch (sel) {
4485 case 0:
4486 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
4487 rn = "Performance0";
4488 break;
4489 case 1:
4490 // gen_helper_dmfc0_performance1(arg);
4491 rn = "Performance1";
4492 // break;
4493 case 2:
4494 // gen_helper_dmfc0_performance2(arg);
4495 rn = "Performance2";
4496 // break;
4497 case 3:
4498 // gen_helper_dmfc0_performance3(arg);
4499 rn = "Performance3";
4500 // break;
4501 case 4:
4502 // gen_helper_dmfc0_performance4(arg);
4503 rn = "Performance4";
4504 // break;
4505 case 5:
4506 // gen_helper_dmfc0_performance5(arg);
4507 rn = "Performance5";
4508 // break;
4509 case 6:
4510 // gen_helper_dmfc0_performance6(arg);
4511 rn = "Performance6";
4512 // break;
4513 case 7:
4514 // gen_helper_dmfc0_performance7(arg);
4515 rn = "Performance7";
4516 // break;
4517 default:
4518 goto die;
4520 break;
4521 case 26:
4522 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4523 rn = "ECC";
4524 break;
4525 case 27:
4526 switch (sel) {
4527 /* ignored */
4528 case 0 ... 3:
4529 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4530 rn = "CacheErr";
4531 break;
4532 default:
4533 goto die;
4535 break;
4536 case 28:
4537 switch (sel) {
4538 case 0:
4539 case 2:
4540 case 4:
4541 case 6:
4542 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
4543 rn = "TagLo";
4544 break;
4545 case 1:
4546 case 3:
4547 case 5:
4548 case 7:
4549 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
4550 rn = "DataLo";
4551 break;
4552 default:
4553 goto die;
4555 break;
4556 case 29:
4557 switch (sel) {
4558 case 0:
4559 case 2:
4560 case 4:
4561 case 6:
4562 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
4563 rn = "TagHi";
4564 break;
4565 case 1:
4566 case 3:
4567 case 5:
4568 case 7:
4569 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
4570 rn = "DataHi";
4571 break;
4572 default:
4573 goto die;
4575 break;
4576 case 30:
4577 switch (sel) {
4578 case 0:
4579 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4580 rn = "ErrorEPC";
4581 break;
4582 default:
4583 goto die;
4585 break;
4586 case 31:
4587 switch (sel) {
4588 case 0:
4589 /* EJTAG support */
4590 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
4591 rn = "DESAVE";
4592 break;
4593 default:
4594 goto die;
4596 break;
4597 default:
4598 goto die;
4600 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4601 return;
4603 die:
4604 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4605 generate_exception(ctx, EXCP_RI);
4608 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4610 const char *rn = "invalid";
4612 if (sel != 0)
4613 check_insn(env, ctx, ISA_MIPS64);
4615 if (use_icount)
4616 gen_io_start();
4618 switch (reg) {
4619 case 0:
4620 switch (sel) {
4621 case 0:
4622 gen_helper_mtc0_index(arg);
4623 rn = "Index";
4624 break;
4625 case 1:
4626 check_insn(env, ctx, ASE_MT);
4627 gen_helper_mtc0_mvpcontrol(arg);
4628 rn = "MVPControl";
4629 break;
4630 case 2:
4631 check_insn(env, ctx, ASE_MT);
4632 /* ignored */
4633 rn = "MVPConf0";
4634 break;
4635 case 3:
4636 check_insn(env, ctx, ASE_MT);
4637 /* ignored */
4638 rn = "MVPConf1";
4639 break;
4640 default:
4641 goto die;
4643 break;
4644 case 1:
4645 switch (sel) {
4646 case 0:
4647 /* ignored */
4648 rn = "Random";
4649 break;
4650 case 1:
4651 check_insn(env, ctx, ASE_MT);
4652 gen_helper_mtc0_vpecontrol(arg);
4653 rn = "VPEControl";
4654 break;
4655 case 2:
4656 check_insn(env, ctx, ASE_MT);
4657 gen_helper_mtc0_vpeconf0(arg);
4658 rn = "VPEConf0";
4659 break;
4660 case 3:
4661 check_insn(env, ctx, ASE_MT);
4662 gen_helper_mtc0_vpeconf1(arg);
4663 rn = "VPEConf1";
4664 break;
4665 case 4:
4666 check_insn(env, ctx, ASE_MT);
4667 gen_helper_mtc0_yqmask(arg);
4668 rn = "YQMask";
4669 break;
4670 case 5:
4671 check_insn(env, ctx, ASE_MT);
4672 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4673 rn = "VPESchedule";
4674 break;
4675 case 6:
4676 check_insn(env, ctx, ASE_MT);
4677 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4678 rn = "VPEScheFBack";
4679 break;
4680 case 7:
4681 check_insn(env, ctx, ASE_MT);
4682 gen_helper_mtc0_vpeopt(arg);
4683 rn = "VPEOpt";
4684 break;
4685 default:
4686 goto die;
4688 break;
4689 case 2:
4690 switch (sel) {
4691 case 0:
4692 gen_helper_mtc0_entrylo0(arg);
4693 rn = "EntryLo0";
4694 break;
4695 case 1:
4696 check_insn(env, ctx, ASE_MT);
4697 gen_helper_mtc0_tcstatus(arg);
4698 rn = "TCStatus";
4699 break;
4700 case 2:
4701 check_insn(env, ctx, ASE_MT);
4702 gen_helper_mtc0_tcbind(arg);
4703 rn = "TCBind";
4704 break;
4705 case 3:
4706 check_insn(env, ctx, ASE_MT);
4707 gen_helper_mtc0_tcrestart(arg);
4708 rn = "TCRestart";
4709 break;
4710 case 4:
4711 check_insn(env, ctx, ASE_MT);
4712 gen_helper_mtc0_tchalt(arg);
4713 rn = "TCHalt";
4714 break;
4715 case 5:
4716 check_insn(env, ctx, ASE_MT);
4717 gen_helper_mtc0_tccontext(arg);
4718 rn = "TCContext";
4719 break;
4720 case 6:
4721 check_insn(env, ctx, ASE_MT);
4722 gen_helper_mtc0_tcschedule(arg);
4723 rn = "TCSchedule";
4724 break;
4725 case 7:
4726 check_insn(env, ctx, ASE_MT);
4727 gen_helper_mtc0_tcschefback(arg);
4728 rn = "TCScheFBack";
4729 break;
4730 default:
4731 goto die;
4733 break;
4734 case 3:
4735 switch (sel) {
4736 case 0:
4737 gen_helper_mtc0_entrylo1(arg);
4738 rn = "EntryLo1";
4739 break;
4740 default:
4741 goto die;
4743 break;
4744 case 4:
4745 switch (sel) {
4746 case 0:
4747 gen_helper_mtc0_context(arg);
4748 rn = "Context";
4749 break;
4750 case 1:
4751 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
4752 rn = "ContextConfig";
4753 // break;
4754 default:
4755 goto die;
4757 break;
4758 case 5:
4759 switch (sel) {
4760 case 0:
4761 gen_helper_mtc0_pagemask(arg);
4762 rn = "PageMask";
4763 break;
4764 case 1:
4765 check_insn(env, ctx, ISA_MIPS32R2);
4766 gen_helper_mtc0_pagegrain(arg);
4767 rn = "PageGrain";
4768 break;
4769 default:
4770 goto die;
4772 break;
4773 case 6:
4774 switch (sel) {
4775 case 0:
4776 gen_helper_mtc0_wired(arg);
4777 rn = "Wired";
4778 break;
4779 case 1:
4780 check_insn(env, ctx, ISA_MIPS32R2);
4781 gen_helper_mtc0_srsconf0(arg);
4782 rn = "SRSConf0";
4783 break;
4784 case 2:
4785 check_insn(env, ctx, ISA_MIPS32R2);
4786 gen_helper_mtc0_srsconf1(arg);
4787 rn = "SRSConf1";
4788 break;
4789 case 3:
4790 check_insn(env, ctx, ISA_MIPS32R2);
4791 gen_helper_mtc0_srsconf2(arg);
4792 rn = "SRSConf2";
4793 break;
4794 case 4:
4795 check_insn(env, ctx, ISA_MIPS32R2);
4796 gen_helper_mtc0_srsconf3(arg);
4797 rn = "SRSConf3";
4798 break;
4799 case 5:
4800 check_insn(env, ctx, ISA_MIPS32R2);
4801 gen_helper_mtc0_srsconf4(arg);
4802 rn = "SRSConf4";
4803 break;
4804 default:
4805 goto die;
4807 break;
4808 case 7:
4809 switch (sel) {
4810 case 0:
4811 check_insn(env, ctx, ISA_MIPS32R2);
4812 gen_helper_mtc0_hwrena(arg);
4813 rn = "HWREna";
4814 break;
4815 default:
4816 goto die;
4818 break;
4819 case 8:
4820 /* ignored */
4821 rn = "BadVAddr";
4822 break;
4823 case 9:
4824 switch (sel) {
4825 case 0:
4826 gen_helper_mtc0_count(arg);
4827 rn = "Count";
4828 break;
4829 /* 6,7 are implementation dependent */
4830 default:
4831 goto die;
4833 /* Stop translation as we may have switched the execution mode */
4834 ctx->bstate = BS_STOP;
4835 break;
4836 case 10:
4837 switch (sel) {
4838 case 0:
4839 gen_helper_mtc0_entryhi(arg);
4840 rn = "EntryHi";
4841 break;
4842 default:
4843 goto die;
4845 break;
4846 case 11:
4847 switch (sel) {
4848 case 0:
4849 gen_helper_mtc0_compare(arg);
4850 rn = "Compare";
4851 break;
4852 /* 6,7 are implementation dependent */
4853 default:
4854 goto die;
4856 /* Stop translation as we may have switched the execution mode */
4857 ctx->bstate = BS_STOP;
4858 break;
4859 case 12:
4860 switch (sel) {
4861 case 0:
4862 save_cpu_state(ctx, 1);
4863 gen_helper_mtc0_status(arg);
4864 /* BS_STOP isn't good enough here, hflags may have changed. */
4865 gen_save_pc(ctx->pc + 4);
4866 ctx->bstate = BS_EXCP;
4867 rn = "Status";
4868 break;
4869 case 1:
4870 check_insn(env, ctx, ISA_MIPS32R2);
4871 gen_helper_mtc0_intctl(arg);
4872 /* Stop translation as we may have switched the execution mode */
4873 ctx->bstate = BS_STOP;
4874 rn = "IntCtl";
4875 break;
4876 case 2:
4877 check_insn(env, ctx, ISA_MIPS32R2);
4878 gen_helper_mtc0_srsctl(arg);
4879 /* Stop translation as we may have switched the execution mode */
4880 ctx->bstate = BS_STOP;
4881 rn = "SRSCtl";
4882 break;
4883 case 3:
4884 check_insn(env, ctx, ISA_MIPS32R2);
4885 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
4886 /* Stop translation as we may have switched the execution mode */
4887 ctx->bstate = BS_STOP;
4888 rn = "SRSMap";
4889 break;
4890 default:
4891 goto die;
4893 break;
4894 case 13:
4895 switch (sel) {
4896 case 0:
4897 save_cpu_state(ctx, 1);
4898 gen_helper_mtc0_cause(arg);
4899 rn = "Cause";
4900 break;
4901 default:
4902 goto die;
4904 break;
4905 case 14:
4906 switch (sel) {
4907 case 0:
4908 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4909 rn = "EPC";
4910 break;
4911 default:
4912 goto die;
4914 break;
4915 case 15:
4916 switch (sel) {
4917 case 0:
4918 /* ignored */
4919 rn = "PRid";
4920 break;
4921 case 1:
4922 check_insn(env, ctx, ISA_MIPS32R2);
4923 gen_helper_mtc0_ebase(arg);
4924 rn = "EBase";
4925 break;
4926 default:
4927 goto die;
4929 break;
4930 case 16:
4931 switch (sel) {
4932 case 0:
4933 gen_helper_mtc0_config0(arg);
4934 rn = "Config";
4935 /* Stop translation as we may have switched the execution mode */
4936 ctx->bstate = BS_STOP;
4937 break;
4938 case 1:
4939 /* ignored, read only */
4940 rn = "Config1";
4941 break;
4942 case 2:
4943 gen_helper_mtc0_config2(arg);
4944 rn = "Config2";
4945 /* Stop translation as we may have switched the execution mode */
4946 ctx->bstate = BS_STOP;
4947 break;
4948 case 3:
4949 /* ignored */
4950 rn = "Config3";
4951 break;
4952 /* 6,7 are implementation dependent */
4953 default:
4954 rn = "Invalid config selector";
4955 goto die;
4957 break;
4958 case 17:
4959 switch (sel) {
4960 case 0:
4961 /* ignored */
4962 rn = "LLAddr";
4963 break;
4964 default:
4965 goto die;
4967 break;
4968 case 18:
4969 switch (sel) {
4970 case 0 ... 7:
4971 gen_helper_1i(mtc0_watchlo, arg, sel);
4972 rn = "WatchLo";
4973 break;
4974 default:
4975 goto die;
4977 break;
4978 case 19:
4979 switch (sel) {
4980 case 0 ... 7:
4981 gen_helper_1i(mtc0_watchhi, arg, sel);
4982 rn = "WatchHi";
4983 break;
4984 default:
4985 goto die;
4987 break;
4988 case 20:
4989 switch (sel) {
4990 case 0:
4991 check_insn(env, ctx, ISA_MIPS3);
4992 gen_helper_mtc0_xcontext(arg);
4993 rn = "XContext";
4994 break;
4995 default:
4996 goto die;
4998 break;
4999 case 21:
5000 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5001 switch (sel) {
5002 case 0:
5003 gen_helper_mtc0_framemask(arg);
5004 rn = "Framemask";
5005 break;
5006 default:
5007 goto die;
5009 break;
5010 case 22:
5011 /* ignored */
5012 rn = "Diagnostic"; /* implementation dependent */
5013 break;
5014 case 23:
5015 switch (sel) {
5016 case 0:
5017 gen_helper_mtc0_debug(arg); /* EJTAG support */
5018 /* BS_STOP isn't good enough here, hflags may have changed. */
5019 gen_save_pc(ctx->pc + 4);
5020 ctx->bstate = BS_EXCP;
5021 rn = "Debug";
5022 break;
5023 case 1:
5024 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
5025 /* Stop translation as we may have switched the execution mode */
5026 ctx->bstate = BS_STOP;
5027 rn = "TraceControl";
5028 // break;
5029 case 2:
5030 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
5031 /* Stop translation as we may have switched the execution mode */
5032 ctx->bstate = BS_STOP;
5033 rn = "TraceControl2";
5034 // break;
5035 case 3:
5036 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
5037 /* Stop translation as we may have switched the execution mode */
5038 ctx->bstate = BS_STOP;
5039 rn = "UserTraceData";
5040 // break;
5041 case 4:
5042 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
5043 /* Stop translation as we may have switched the execution mode */
5044 ctx->bstate = BS_STOP;
5045 rn = "TraceBPC";
5046 // break;
5047 default:
5048 goto die;
5050 break;
5051 case 24:
5052 switch (sel) {
5053 case 0:
5054 /* EJTAG support */
5055 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
5056 rn = "DEPC";
5057 break;
5058 default:
5059 goto die;
5061 break;
5062 case 25:
5063 switch (sel) {
5064 case 0:
5065 gen_helper_mtc0_performance0(arg);
5066 rn = "Performance0";
5067 break;
5068 case 1:
5069 // gen_helper_mtc0_performance1(arg);
5070 rn = "Performance1";
5071 // break;
5072 case 2:
5073 // gen_helper_mtc0_performance2(arg);
5074 rn = "Performance2";
5075 // break;
5076 case 3:
5077 // gen_helper_mtc0_performance3(arg);
5078 rn = "Performance3";
5079 // break;
5080 case 4:
5081 // gen_helper_mtc0_performance4(arg);
5082 rn = "Performance4";
5083 // break;
5084 case 5:
5085 // gen_helper_mtc0_performance5(arg);
5086 rn = "Performance5";
5087 // break;
5088 case 6:
5089 // gen_helper_mtc0_performance6(arg);
5090 rn = "Performance6";
5091 // break;
5092 case 7:
5093 // gen_helper_mtc0_performance7(arg);
5094 rn = "Performance7";
5095 // break;
5096 default:
5097 goto die;
5099 break;
5100 case 26:
5101 /* ignored */
5102 rn = "ECC";
5103 break;
5104 case 27:
5105 switch (sel) {
5106 case 0 ... 3:
5107 /* ignored */
5108 rn = "CacheErr";
5109 break;
5110 default:
5111 goto die;
5113 break;
5114 case 28:
5115 switch (sel) {
5116 case 0:
5117 case 2:
5118 case 4:
5119 case 6:
5120 gen_helper_mtc0_taglo(arg);
5121 rn = "TagLo";
5122 break;
5123 case 1:
5124 case 3:
5125 case 5:
5126 case 7:
5127 gen_helper_mtc0_datalo(arg);
5128 rn = "DataLo";
5129 break;
5130 default:
5131 goto die;
5133 break;
5134 case 29:
5135 switch (sel) {
5136 case 0:
5137 case 2:
5138 case 4:
5139 case 6:
5140 gen_helper_mtc0_taghi(arg);
5141 rn = "TagHi";
5142 break;
5143 case 1:
5144 case 3:
5145 case 5:
5146 case 7:
5147 gen_helper_mtc0_datahi(arg);
5148 rn = "DataHi";
5149 break;
5150 default:
5151 rn = "invalid sel";
5152 goto die;
5154 break;
5155 case 30:
5156 switch (sel) {
5157 case 0:
5158 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5159 rn = "ErrorEPC";
5160 break;
5161 default:
5162 goto die;
5164 break;
5165 case 31:
5166 switch (sel) {
5167 case 0:
5168 /* EJTAG support */
5169 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
5170 rn = "DESAVE";
5171 break;
5172 default:
5173 goto die;
5175 /* Stop translation as we may have switched the execution mode */
5176 ctx->bstate = BS_STOP;
5177 break;
5178 default:
5179 goto die;
5181 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5182 /* For simplicity assume that all writes can cause interrupts. */
5183 if (use_icount) {
5184 gen_io_end();
5185 ctx->bstate = BS_STOP;
5187 return;
5189 die:
5190 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5191 generate_exception(ctx, EXCP_RI);
5193 #endif /* TARGET_MIPS64 */
5195 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5196 int u, int sel, int h)
5198 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5199 TCGv t0 = tcg_temp_local_new();
5201 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5202 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5203 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5204 tcg_gen_movi_tl(t0, -1);
5205 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5206 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5207 tcg_gen_movi_tl(t0, -1);
5208 else if (u == 0) {
5209 switch (rt) {
5210 case 2:
5211 switch (sel) {
5212 case 1:
5213 gen_helper_mftc0_tcstatus(t0);
5214 break;
5215 case 2:
5216 gen_helper_mftc0_tcbind(t0);
5217 break;
5218 case 3:
5219 gen_helper_mftc0_tcrestart(t0);
5220 break;
5221 case 4:
5222 gen_helper_mftc0_tchalt(t0);
5223 break;
5224 case 5:
5225 gen_helper_mftc0_tccontext(t0);
5226 break;
5227 case 6:
5228 gen_helper_mftc0_tcschedule(t0);
5229 break;
5230 case 7:
5231 gen_helper_mftc0_tcschefback(t0);
5232 break;
5233 default:
5234 gen_mfc0(env, ctx, t0, rt, sel);
5235 break;
5237 break;
5238 case 10:
5239 switch (sel) {
5240 case 0:
5241 gen_helper_mftc0_entryhi(t0);
5242 break;
5243 default:
5244 gen_mfc0(env, ctx, t0, rt, sel);
5245 break;
5247 case 12:
5248 switch (sel) {
5249 case 0:
5250 gen_helper_mftc0_status(t0);
5251 break;
5252 default:
5253 gen_mfc0(env, ctx, t0, rt, sel);
5254 break;
5256 case 23:
5257 switch (sel) {
5258 case 0:
5259 gen_helper_mftc0_debug(t0);
5260 break;
5261 default:
5262 gen_mfc0(env, ctx, t0, rt, sel);
5263 break;
5265 break;
5266 default:
5267 gen_mfc0(env, ctx, t0, rt, sel);
5269 } else switch (sel) {
5270 /* GPR registers. */
5271 case 0:
5272 gen_helper_1i(mftgpr, t0, rt);
5273 break;
5274 /* Auxiliary CPU registers */
5275 case 1:
5276 switch (rt) {
5277 case 0:
5278 gen_helper_1i(mftlo, t0, 0);
5279 break;
5280 case 1:
5281 gen_helper_1i(mfthi, t0, 0);
5282 break;
5283 case 2:
5284 gen_helper_1i(mftacx, t0, 0);
5285 break;
5286 case 4:
5287 gen_helper_1i(mftlo, t0, 1);
5288 break;
5289 case 5:
5290 gen_helper_1i(mfthi, t0, 1);
5291 break;
5292 case 6:
5293 gen_helper_1i(mftacx, t0, 1);
5294 break;
5295 case 8:
5296 gen_helper_1i(mftlo, t0, 2);
5297 break;
5298 case 9:
5299 gen_helper_1i(mfthi, t0, 2);
5300 break;
5301 case 10:
5302 gen_helper_1i(mftacx, t0, 2);
5303 break;
5304 case 12:
5305 gen_helper_1i(mftlo, t0, 3);
5306 break;
5307 case 13:
5308 gen_helper_1i(mfthi, t0, 3);
5309 break;
5310 case 14:
5311 gen_helper_1i(mftacx, t0, 3);
5312 break;
5313 case 16:
5314 gen_helper_mftdsp(t0);
5315 break;
5316 default:
5317 goto die;
5319 break;
5320 /* Floating point (COP1). */
5321 case 2:
5322 /* XXX: For now we support only a single FPU context. */
5323 if (h == 0) {
5324 TCGv_i32 fp0 = tcg_temp_new_i32();
5326 gen_load_fpr32(fp0, rt);
5327 tcg_gen_ext_i32_tl(t0, fp0);
5328 tcg_temp_free_i32(fp0);
5329 } else {
5330 TCGv_i32 fp0 = tcg_temp_new_i32();
5332 gen_load_fpr32h(fp0, rt);
5333 tcg_gen_ext_i32_tl(t0, fp0);
5334 tcg_temp_free_i32(fp0);
5336 break;
5337 case 3:
5338 /* XXX: For now we support only a single FPU context. */
5339 gen_helper_1i(cfc1, t0, rt);
5340 break;
5341 /* COP2: Not implemented. */
5342 case 4:
5343 case 5:
5344 /* fall through */
5345 default:
5346 goto die;
5348 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5349 gen_store_gpr(t0, rd);
5350 tcg_temp_free(t0);
5351 return;
5353 die:
5354 tcg_temp_free(t0);
5355 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5356 generate_exception(ctx, EXCP_RI);
5359 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5360 int u, int sel, int h)
5362 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5363 TCGv t0 = tcg_temp_local_new();
5365 gen_load_gpr(t0, rt);
5366 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5367 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5368 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5369 /* NOP */ ;
5370 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5371 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5372 /* NOP */ ;
5373 else if (u == 0) {
5374 switch (rd) {
5375 case 2:
5376 switch (sel) {
5377 case 1:
5378 gen_helper_mttc0_tcstatus(t0);
5379 break;
5380 case 2:
5381 gen_helper_mttc0_tcbind(t0);
5382 break;
5383 case 3:
5384 gen_helper_mttc0_tcrestart(t0);
5385 break;
5386 case 4:
5387 gen_helper_mttc0_tchalt(t0);
5388 break;
5389 case 5:
5390 gen_helper_mttc0_tccontext(t0);
5391 break;
5392 case 6:
5393 gen_helper_mttc0_tcschedule(t0);
5394 break;
5395 case 7:
5396 gen_helper_mttc0_tcschefback(t0);
5397 break;
5398 default:
5399 gen_mtc0(env, ctx, t0, rd, sel);
5400 break;
5402 break;
5403 case 10:
5404 switch (sel) {
5405 case 0:
5406 gen_helper_mttc0_entryhi(t0);
5407 break;
5408 default:
5409 gen_mtc0(env, ctx, t0, rd, sel);
5410 break;
5412 case 12:
5413 switch (sel) {
5414 case 0:
5415 gen_helper_mttc0_status(t0);
5416 break;
5417 default:
5418 gen_mtc0(env, ctx, t0, rd, sel);
5419 break;
5421 case 23:
5422 switch (sel) {
5423 case 0:
5424 gen_helper_mttc0_debug(t0);
5425 break;
5426 default:
5427 gen_mtc0(env, ctx, t0, rd, sel);
5428 break;
5430 break;
5431 default:
5432 gen_mtc0(env, ctx, t0, rd, sel);
5434 } else switch (sel) {
5435 /* GPR registers. */
5436 case 0:
5437 gen_helper_1i(mttgpr, t0, rd);
5438 break;
5439 /* Auxiliary CPU registers */
5440 case 1:
5441 switch (rd) {
5442 case 0:
5443 gen_helper_1i(mttlo, t0, 0);
5444 break;
5445 case 1:
5446 gen_helper_1i(mtthi, t0, 0);
5447 break;
5448 case 2:
5449 gen_helper_1i(mttacx, t0, 0);
5450 break;
5451 case 4:
5452 gen_helper_1i(mttlo, t0, 1);
5453 break;
5454 case 5:
5455 gen_helper_1i(mtthi, t0, 1);
5456 break;
5457 case 6:
5458 gen_helper_1i(mttacx, t0, 1);
5459 break;
5460 case 8:
5461 gen_helper_1i(mttlo, t0, 2);
5462 break;
5463 case 9:
5464 gen_helper_1i(mtthi, t0, 2);
5465 break;
5466 case 10:
5467 gen_helper_1i(mttacx, t0, 2);
5468 break;
5469 case 12:
5470 gen_helper_1i(mttlo, t0, 3);
5471 break;
5472 case 13:
5473 gen_helper_1i(mtthi, t0, 3);
5474 break;
5475 case 14:
5476 gen_helper_1i(mttacx, t0, 3);
5477 break;
5478 case 16:
5479 gen_helper_mttdsp(t0);
5480 break;
5481 default:
5482 goto die;
5484 break;
5485 /* Floating point (COP1). */
5486 case 2:
5487 /* XXX: For now we support only a single FPU context. */
5488 if (h == 0) {
5489 TCGv_i32 fp0 = tcg_temp_new_i32();
5491 tcg_gen_trunc_tl_i32(fp0, t0);
5492 gen_store_fpr32(fp0, rd);
5493 tcg_temp_free_i32(fp0);
5494 } else {
5495 TCGv_i32 fp0 = tcg_temp_new_i32();
5497 tcg_gen_trunc_tl_i32(fp0, t0);
5498 gen_store_fpr32h(fp0, rd);
5499 tcg_temp_free_i32(fp0);
5501 break;
5502 case 3:
5503 /* XXX: For now we support only a single FPU context. */
5504 gen_helper_1i(ctc1, t0, rd);
5505 break;
5506 /* COP2: Not implemented. */
5507 case 4:
5508 case 5:
5509 /* fall through */
5510 default:
5511 goto die;
5513 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5514 tcg_temp_free(t0);
5515 return;
5517 die:
5518 tcg_temp_free(t0);
5519 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5520 generate_exception(ctx, EXCP_RI);
5523 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5525 const char *opn = "ldst";
5527 switch (opc) {
5528 case OPC_MFC0:
5529 if (rt == 0) {
5530 /* Treat as NOP. */
5531 return;
5533 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5534 opn = "mfc0";
5535 break;
5536 case OPC_MTC0:
5538 TCGv t0 = tcg_temp_new();
5540 gen_load_gpr(t0, rt);
5541 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5542 tcg_temp_free(t0);
5544 opn = "mtc0";
5545 break;
5546 #if defined(TARGET_MIPS64)
5547 case OPC_DMFC0:
5548 check_insn(env, ctx, ISA_MIPS3);
5549 if (rt == 0) {
5550 /* Treat as NOP. */
5551 return;
5553 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5554 opn = "dmfc0";
5555 break;
5556 case OPC_DMTC0:
5557 check_insn(env, ctx, ISA_MIPS3);
5559 TCGv t0 = tcg_temp_new();
5561 gen_load_gpr(t0, rt);
5562 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5563 tcg_temp_free(t0);
5565 opn = "dmtc0";
5566 break;
5567 #endif
5568 case OPC_MFTR:
5569 check_insn(env, ctx, ASE_MT);
5570 if (rd == 0) {
5571 /* Treat as NOP. */
5572 return;
5574 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5575 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5576 opn = "mftr";
5577 break;
5578 case OPC_MTTR:
5579 check_insn(env, ctx, ASE_MT);
5580 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5581 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5582 opn = "mttr";
5583 break;
5584 case OPC_TLBWI:
5585 opn = "tlbwi";
5586 if (!env->tlb->helper_tlbwi)
5587 goto die;
5588 gen_helper_tlbwi();
5589 break;
5590 case OPC_TLBWR:
5591 opn = "tlbwr";
5592 if (!env->tlb->helper_tlbwr)
5593 goto die;
5594 gen_helper_tlbwr();
5595 break;
5596 case OPC_TLBP:
5597 opn = "tlbp";
5598 if (!env->tlb->helper_tlbp)
5599 goto die;
5600 gen_helper_tlbp();
5601 break;
5602 case OPC_TLBR:
5603 opn = "tlbr";
5604 if (!env->tlb->helper_tlbr)
5605 goto die;
5606 gen_helper_tlbr();
5607 break;
5608 case OPC_ERET:
5609 opn = "eret";
5610 check_insn(env, ctx, ISA_MIPS2);
5611 gen_helper_eret();
5612 ctx->bstate = BS_EXCP;
5613 break;
5614 case OPC_DERET:
5615 opn = "deret";
5616 check_insn(env, ctx, ISA_MIPS32);
5617 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5618 MIPS_INVAL(opn);
5619 generate_exception(ctx, EXCP_RI);
5620 } else {
5621 gen_helper_deret();
5622 ctx->bstate = BS_EXCP;
5624 break;
5625 case OPC_WAIT:
5626 opn = "wait";
5627 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5628 /* If we get an exception, we want to restart at next instruction */
5629 ctx->pc += 4;
5630 save_cpu_state(ctx, 1);
5631 ctx->pc -= 4;
5632 gen_helper_wait();
5633 ctx->bstate = BS_EXCP;
5634 break;
5635 default:
5636 die:
5637 MIPS_INVAL(opn);
5638 generate_exception(ctx, EXCP_RI);
5639 return;
5641 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5643 #endif /* !CONFIG_USER_ONLY */
5645 /* CP1 Branches (before delay slot) */
5646 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5647 int32_t cc, int32_t offset)
5649 target_ulong btarget;
5650 const char *opn = "cp1 cond branch";
5651 TCGv_i32 t0 = tcg_temp_new_i32();
5653 if (cc != 0)
5654 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5656 btarget = ctx->pc + 4 + offset;
5658 switch (op) {
5659 case OPC_BC1F:
5660 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5661 tcg_gen_not_i32(t0, t0);
5662 tcg_gen_andi_i32(t0, t0, 1);
5663 tcg_gen_extu_i32_tl(bcond, t0);
5664 opn = "bc1f";
5665 goto not_likely;
5666 case OPC_BC1FL:
5667 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5668 tcg_gen_not_i32(t0, t0);
5669 tcg_gen_andi_i32(t0, t0, 1);
5670 tcg_gen_extu_i32_tl(bcond, t0);
5671 opn = "bc1fl";
5672 goto likely;
5673 case OPC_BC1T:
5674 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5675 tcg_gen_andi_i32(t0, t0, 1);
5676 tcg_gen_extu_i32_tl(bcond, t0);
5677 opn = "bc1t";
5678 goto not_likely;
5679 case OPC_BC1TL:
5680 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5681 tcg_gen_andi_i32(t0, t0, 1);
5682 tcg_gen_extu_i32_tl(bcond, t0);
5683 opn = "bc1tl";
5684 likely:
5685 ctx->hflags |= MIPS_HFLAG_BL;
5686 break;
5687 case OPC_BC1FANY2:
5689 TCGv_i32 t1 = tcg_temp_new_i32();
5690 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5691 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5692 tcg_gen_or_i32(t0, t0, t1);
5693 tcg_temp_free_i32(t1);
5694 tcg_gen_not_i32(t0, t0);
5695 tcg_gen_andi_i32(t0, t0, 1);
5696 tcg_gen_extu_i32_tl(bcond, t0);
5698 opn = "bc1any2f";
5699 goto not_likely;
5700 case OPC_BC1TANY2:
5702 TCGv_i32 t1 = tcg_temp_new_i32();
5703 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5704 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5705 tcg_gen_or_i32(t0, t0, t1);
5706 tcg_temp_free_i32(t1);
5707 tcg_gen_andi_i32(t0, t0, 1);
5708 tcg_gen_extu_i32_tl(bcond, t0);
5710 opn = "bc1any2t";
5711 goto not_likely;
5712 case OPC_BC1FANY4:
5714 TCGv_i32 t1 = tcg_temp_new_i32();
5715 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5716 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5717 tcg_gen_or_i32(t0, t0, t1);
5718 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5719 tcg_gen_or_i32(t0, t0, t1);
5720 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5721 tcg_gen_or_i32(t0, t0, t1);
5722 tcg_temp_free_i32(t1);
5723 tcg_gen_not_i32(t0, t0);
5724 tcg_gen_andi_i32(t0, t0, 1);
5725 tcg_gen_extu_i32_tl(bcond, t0);
5727 opn = "bc1any4f";
5728 goto not_likely;
5729 case OPC_BC1TANY4:
5731 TCGv_i32 t1 = tcg_temp_new_i32();
5732 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5733 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5734 tcg_gen_or_i32(t0, t0, t1);
5735 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5736 tcg_gen_or_i32(t0, t0, t1);
5737 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5738 tcg_gen_or_i32(t0, t0, t1);
5739 tcg_temp_free_i32(t1);
5740 tcg_gen_andi_i32(t0, t0, 1);
5741 tcg_gen_extu_i32_tl(bcond, t0);
5743 opn = "bc1any4t";
5744 not_likely:
5745 ctx->hflags |= MIPS_HFLAG_BC;
5746 break;
5747 default:
5748 MIPS_INVAL(opn);
5749 generate_exception (ctx, EXCP_RI);
5750 goto out;
5752 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5753 ctx->hflags, btarget);
5754 ctx->btarget = btarget;
5756 out:
5757 tcg_temp_free_i32(t0);
5760 /* Coprocessor 1 (FPU) */
5762 #define FOP(func, fmt) (((fmt) << 21) | (func))
5764 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5766 const char *opn = "cp1 move";
5767 TCGv t0 = tcg_temp_new();
5769 switch (opc) {
5770 case OPC_MFC1:
5772 TCGv_i32 fp0 = tcg_temp_new_i32();
5774 gen_load_fpr32(fp0, fs);
5775 tcg_gen_ext_i32_tl(t0, fp0);
5776 tcg_temp_free_i32(fp0);
5778 gen_store_gpr(t0, rt);
5779 opn = "mfc1";
5780 break;
5781 case OPC_MTC1:
5782 gen_load_gpr(t0, rt);
5784 TCGv_i32 fp0 = tcg_temp_new_i32();
5786 tcg_gen_trunc_tl_i32(fp0, t0);
5787 gen_store_fpr32(fp0, fs);
5788 tcg_temp_free_i32(fp0);
5790 opn = "mtc1";
5791 break;
5792 case OPC_CFC1:
5793 gen_helper_1i(cfc1, t0, fs);
5794 gen_store_gpr(t0, rt);
5795 opn = "cfc1";
5796 break;
5797 case OPC_CTC1:
5798 gen_load_gpr(t0, rt);
5799 gen_helper_1i(ctc1, t0, fs);
5800 opn = "ctc1";
5801 break;
5802 #if defined(TARGET_MIPS64)
5803 case OPC_DMFC1:
5804 gen_load_fpr64(ctx, t0, fs);
5805 gen_store_gpr(t0, rt);
5806 opn = "dmfc1";
5807 break;
5808 case OPC_DMTC1:
5809 gen_load_gpr(t0, rt);
5810 gen_store_fpr64(ctx, t0, fs);
5811 opn = "dmtc1";
5812 break;
5813 #endif
5814 case OPC_MFHC1:
5816 TCGv_i32 fp0 = tcg_temp_new_i32();
5818 gen_load_fpr32h(fp0, fs);
5819 tcg_gen_ext_i32_tl(t0, fp0);
5820 tcg_temp_free_i32(fp0);
5822 gen_store_gpr(t0, rt);
5823 opn = "mfhc1";
5824 break;
5825 case OPC_MTHC1:
5826 gen_load_gpr(t0, rt);
5828 TCGv_i32 fp0 = tcg_temp_new_i32();
5830 tcg_gen_trunc_tl_i32(fp0, t0);
5831 gen_store_fpr32h(fp0, fs);
5832 tcg_temp_free_i32(fp0);
5834 opn = "mthc1";
5835 break;
5836 default:
5837 MIPS_INVAL(opn);
5838 generate_exception (ctx, EXCP_RI);
5839 goto out;
5841 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5843 out:
5844 tcg_temp_free(t0);
5847 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5849 int l1;
5850 TCGCond cond;
5851 TCGv_i32 t0;
5853 if (rd == 0) {
5854 /* Treat as NOP. */
5855 return;
5858 if (tf)
5859 cond = TCG_COND_EQ;
5860 else
5861 cond = TCG_COND_NE;
5863 l1 = gen_new_label();
5864 t0 = tcg_temp_new_i32();
5865 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5866 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5867 tcg_temp_free_i32(t0);
5868 if (rs == 0) {
5869 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5870 } else {
5871 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5873 gen_set_label(l1);
5876 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5878 int cond;
5879 TCGv_i32 t0 = tcg_temp_new_i32();
5880 int l1 = gen_new_label();
5882 if (tf)
5883 cond = TCG_COND_EQ;
5884 else
5885 cond = TCG_COND_NE;
5887 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5888 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5889 gen_load_fpr32(t0, fs);
5890 gen_store_fpr32(t0, fd);
5891 gen_set_label(l1);
5892 tcg_temp_free_i32(t0);
5895 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5897 int cond;
5898 TCGv_i32 t0 = tcg_temp_new_i32();
5899 TCGv_i64 fp0;
5900 int l1 = gen_new_label();
5902 if (tf)
5903 cond = TCG_COND_EQ;
5904 else
5905 cond = TCG_COND_NE;
5907 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5908 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5909 tcg_temp_free_i32(t0);
5910 fp0 = tcg_temp_new_i64();
5911 gen_load_fpr64(ctx, fp0, fs);
5912 gen_store_fpr64(ctx, fp0, fd);
5913 tcg_temp_free_i64(fp0);
5914 gen_set_label(l1);
5917 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5919 int cond;
5920 TCGv_i32 t0 = tcg_temp_new_i32();
5921 int l1 = gen_new_label();
5922 int l2 = gen_new_label();
5924 if (tf)
5925 cond = TCG_COND_EQ;
5926 else
5927 cond = TCG_COND_NE;
5929 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5930 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5931 gen_load_fpr32(t0, fs);
5932 gen_store_fpr32(t0, fd);
5933 gen_set_label(l1);
5935 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc+1));
5936 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5937 gen_load_fpr32h(t0, fs);
5938 gen_store_fpr32h(t0, fd);
5939 tcg_temp_free_i32(t0);
5940 gen_set_label(l2);
5944 static void gen_farith (DisasContext *ctx, uint32_t op1,
5945 int ft, int fs, int fd, int cc)
5947 const char *opn = "farith";
5948 const char *condnames[] = {
5949 "c.f",
5950 "c.un",
5951 "c.eq",
5952 "c.ueq",
5953 "c.olt",
5954 "c.ult",
5955 "c.ole",
5956 "c.ule",
5957 "c.sf",
5958 "c.ngle",
5959 "c.seq",
5960 "c.ngl",
5961 "c.lt",
5962 "c.nge",
5963 "c.le",
5964 "c.ngt",
5966 const char *condnames_abs[] = {
5967 "cabs.f",
5968 "cabs.un",
5969 "cabs.eq",
5970 "cabs.ueq",
5971 "cabs.olt",
5972 "cabs.ult",
5973 "cabs.ole",
5974 "cabs.ule",
5975 "cabs.sf",
5976 "cabs.ngle",
5977 "cabs.seq",
5978 "cabs.ngl",
5979 "cabs.lt",
5980 "cabs.nge",
5981 "cabs.le",
5982 "cabs.ngt",
5984 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
5985 uint32_t func = ctx->opcode & 0x3f;
5987 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5988 case FOP(0, 16):
5990 TCGv_i32 fp0 = tcg_temp_new_i32();
5991 TCGv_i32 fp1 = tcg_temp_new_i32();
5993 gen_load_fpr32(fp0, fs);
5994 gen_load_fpr32(fp1, ft);
5995 gen_helper_float_add_s(fp0, fp0, fp1);
5996 tcg_temp_free_i32(fp1);
5997 gen_store_fpr32(fp0, fd);
5998 tcg_temp_free_i32(fp0);
6000 opn = "add.s";
6001 optype = BINOP;
6002 break;
6003 case FOP(1, 16):
6005 TCGv_i32 fp0 = tcg_temp_new_i32();
6006 TCGv_i32 fp1 = tcg_temp_new_i32();
6008 gen_load_fpr32(fp0, fs);
6009 gen_load_fpr32(fp1, ft);
6010 gen_helper_float_sub_s(fp0, fp0, fp1);
6011 tcg_temp_free_i32(fp1);
6012 gen_store_fpr32(fp0, fd);
6013 tcg_temp_free_i32(fp0);
6015 opn = "sub.s";
6016 optype = BINOP;
6017 break;
6018 case FOP(2, 16):
6020 TCGv_i32 fp0 = tcg_temp_new_i32();
6021 TCGv_i32 fp1 = tcg_temp_new_i32();
6023 gen_load_fpr32(fp0, fs);
6024 gen_load_fpr32(fp1, ft);
6025 gen_helper_float_mul_s(fp0, fp0, fp1);
6026 tcg_temp_free_i32(fp1);
6027 gen_store_fpr32(fp0, fd);
6028 tcg_temp_free_i32(fp0);
6030 opn = "mul.s";
6031 optype = BINOP;
6032 break;
6033 case FOP(3, 16):
6035 TCGv_i32 fp0 = tcg_temp_new_i32();
6036 TCGv_i32 fp1 = tcg_temp_new_i32();
6038 gen_load_fpr32(fp0, fs);
6039 gen_load_fpr32(fp1, ft);
6040 gen_helper_float_div_s(fp0, fp0, fp1);
6041 tcg_temp_free_i32(fp1);
6042 gen_store_fpr32(fp0, fd);
6043 tcg_temp_free_i32(fp0);
6045 opn = "div.s";
6046 optype = BINOP;
6047 break;
6048 case FOP(4, 16):
6050 TCGv_i32 fp0 = tcg_temp_new_i32();
6052 gen_load_fpr32(fp0, fs);
6053 gen_helper_float_sqrt_s(fp0, fp0);
6054 gen_store_fpr32(fp0, fd);
6055 tcg_temp_free_i32(fp0);
6057 opn = "sqrt.s";
6058 break;
6059 case FOP(5, 16):
6061 TCGv_i32 fp0 = tcg_temp_new_i32();
6063 gen_load_fpr32(fp0, fs);
6064 gen_helper_float_abs_s(fp0, fp0);
6065 gen_store_fpr32(fp0, fd);
6066 tcg_temp_free_i32(fp0);
6068 opn = "abs.s";
6069 break;
6070 case FOP(6, 16):
6072 TCGv_i32 fp0 = tcg_temp_new_i32();
6074 gen_load_fpr32(fp0, fs);
6075 gen_store_fpr32(fp0, fd);
6076 tcg_temp_free_i32(fp0);
6078 opn = "mov.s";
6079 break;
6080 case FOP(7, 16):
6082 TCGv_i32 fp0 = tcg_temp_new_i32();
6084 gen_load_fpr32(fp0, fs);
6085 gen_helper_float_chs_s(fp0, fp0);
6086 gen_store_fpr32(fp0, fd);
6087 tcg_temp_free_i32(fp0);
6089 opn = "neg.s";
6090 break;
6091 case FOP(8, 16):
6092 check_cp1_64bitmode(ctx);
6094 TCGv_i32 fp32 = tcg_temp_new_i32();
6095 TCGv_i64 fp64 = tcg_temp_new_i64();
6097 gen_load_fpr32(fp32, fs);
6098 gen_helper_float_roundl_s(fp64, fp32);
6099 tcg_temp_free_i32(fp32);
6100 gen_store_fpr64(ctx, fp64, fd);
6101 tcg_temp_free_i64(fp64);
6103 opn = "round.l.s";
6104 break;
6105 case FOP(9, 16):
6106 check_cp1_64bitmode(ctx);
6108 TCGv_i32 fp32 = tcg_temp_new_i32();
6109 TCGv_i64 fp64 = tcg_temp_new_i64();
6111 gen_load_fpr32(fp32, fs);
6112 gen_helper_float_truncl_s(fp64, fp32);
6113 tcg_temp_free_i32(fp32);
6114 gen_store_fpr64(ctx, fp64, fd);
6115 tcg_temp_free_i64(fp64);
6117 opn = "trunc.l.s";
6118 break;
6119 case FOP(10, 16):
6120 check_cp1_64bitmode(ctx);
6122 TCGv_i32 fp32 = tcg_temp_new_i32();
6123 TCGv_i64 fp64 = tcg_temp_new_i64();
6125 gen_load_fpr32(fp32, fs);
6126 gen_helper_float_ceill_s(fp64, fp32);
6127 tcg_temp_free_i32(fp32);
6128 gen_store_fpr64(ctx, fp64, fd);
6129 tcg_temp_free_i64(fp64);
6131 opn = "ceil.l.s";
6132 break;
6133 case FOP(11, 16):
6134 check_cp1_64bitmode(ctx);
6136 TCGv_i32 fp32 = tcg_temp_new_i32();
6137 TCGv_i64 fp64 = tcg_temp_new_i64();
6139 gen_load_fpr32(fp32, fs);
6140 gen_helper_float_floorl_s(fp64, fp32);
6141 tcg_temp_free_i32(fp32);
6142 gen_store_fpr64(ctx, fp64, fd);
6143 tcg_temp_free_i64(fp64);
6145 opn = "floor.l.s";
6146 break;
6147 case FOP(12, 16):
6149 TCGv_i32 fp0 = tcg_temp_new_i32();
6151 gen_load_fpr32(fp0, fs);
6152 gen_helper_float_roundw_s(fp0, fp0);
6153 gen_store_fpr32(fp0, fd);
6154 tcg_temp_free_i32(fp0);
6156 opn = "round.w.s";
6157 break;
6158 case FOP(13, 16):
6160 TCGv_i32 fp0 = tcg_temp_new_i32();
6162 gen_load_fpr32(fp0, fs);
6163 gen_helper_float_truncw_s(fp0, fp0);
6164 gen_store_fpr32(fp0, fd);
6165 tcg_temp_free_i32(fp0);
6167 opn = "trunc.w.s";
6168 break;
6169 case FOP(14, 16):
6171 TCGv_i32 fp0 = tcg_temp_new_i32();
6173 gen_load_fpr32(fp0, fs);
6174 gen_helper_float_ceilw_s(fp0, fp0);
6175 gen_store_fpr32(fp0, fd);
6176 tcg_temp_free_i32(fp0);
6178 opn = "ceil.w.s";
6179 break;
6180 case FOP(15, 16):
6182 TCGv_i32 fp0 = tcg_temp_new_i32();
6184 gen_load_fpr32(fp0, fs);
6185 gen_helper_float_floorw_s(fp0, fp0);
6186 gen_store_fpr32(fp0, fd);
6187 tcg_temp_free_i32(fp0);
6189 opn = "floor.w.s";
6190 break;
6191 case FOP(17, 16):
6192 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6193 opn = "movcf.s";
6194 break;
6195 case FOP(18, 16):
6197 int l1 = gen_new_label();
6198 TCGv_i32 fp0;
6200 if (ft != 0) {
6201 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6203 fp0 = tcg_temp_new_i32();
6204 gen_load_fpr32(fp0, fs);
6205 gen_store_fpr32(fp0, fd);
6206 tcg_temp_free_i32(fp0);
6207 gen_set_label(l1);
6209 opn = "movz.s";
6210 break;
6211 case FOP(19, 16):
6213 int l1 = gen_new_label();
6214 TCGv_i32 fp0;
6216 if (ft != 0) {
6217 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6218 fp0 = tcg_temp_new_i32();
6219 gen_load_fpr32(fp0, fs);
6220 gen_store_fpr32(fp0, fd);
6221 tcg_temp_free_i32(fp0);
6222 gen_set_label(l1);
6225 opn = "movn.s";
6226 break;
6227 case FOP(21, 16):
6228 check_cop1x(ctx);
6230 TCGv_i32 fp0 = tcg_temp_new_i32();
6232 gen_load_fpr32(fp0, fs);
6233 gen_helper_float_recip_s(fp0, fp0);
6234 gen_store_fpr32(fp0, fd);
6235 tcg_temp_free_i32(fp0);
6237 opn = "recip.s";
6238 break;
6239 case FOP(22, 16):
6240 check_cop1x(ctx);
6242 TCGv_i32 fp0 = tcg_temp_new_i32();
6244 gen_load_fpr32(fp0, fs);
6245 gen_helper_float_rsqrt_s(fp0, fp0);
6246 gen_store_fpr32(fp0, fd);
6247 tcg_temp_free_i32(fp0);
6249 opn = "rsqrt.s";
6250 break;
6251 case FOP(28, 16):
6252 check_cp1_64bitmode(ctx);
6254 TCGv_i32 fp0 = tcg_temp_new_i32();
6255 TCGv_i32 fp1 = tcg_temp_new_i32();
6257 gen_load_fpr32(fp0, fs);
6258 gen_load_fpr32(fp1, fd);
6259 gen_helper_float_recip2_s(fp0, fp0, fp1);
6260 tcg_temp_free_i32(fp1);
6261 gen_store_fpr32(fp0, fd);
6262 tcg_temp_free_i32(fp0);
6264 opn = "recip2.s";
6265 break;
6266 case FOP(29, 16):
6267 check_cp1_64bitmode(ctx);
6269 TCGv_i32 fp0 = tcg_temp_new_i32();
6271 gen_load_fpr32(fp0, fs);
6272 gen_helper_float_recip1_s(fp0, fp0);
6273 gen_store_fpr32(fp0, fd);
6274 tcg_temp_free_i32(fp0);
6276 opn = "recip1.s";
6277 break;
6278 case FOP(30, 16):
6279 check_cp1_64bitmode(ctx);
6281 TCGv_i32 fp0 = tcg_temp_new_i32();
6283 gen_load_fpr32(fp0, fs);
6284 gen_helper_float_rsqrt1_s(fp0, fp0);
6285 gen_store_fpr32(fp0, fd);
6286 tcg_temp_free_i32(fp0);
6288 opn = "rsqrt1.s";
6289 break;
6290 case FOP(31, 16):
6291 check_cp1_64bitmode(ctx);
6293 TCGv_i32 fp0 = tcg_temp_new_i32();
6294 TCGv_i32 fp1 = tcg_temp_new_i32();
6296 gen_load_fpr32(fp0, fs);
6297 gen_load_fpr32(fp1, ft);
6298 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6299 tcg_temp_free_i32(fp1);
6300 gen_store_fpr32(fp0, fd);
6301 tcg_temp_free_i32(fp0);
6303 opn = "rsqrt2.s";
6304 break;
6305 case FOP(33, 16):
6306 check_cp1_registers(ctx, fd);
6308 TCGv_i32 fp32 = tcg_temp_new_i32();
6309 TCGv_i64 fp64 = tcg_temp_new_i64();
6311 gen_load_fpr32(fp32, fs);
6312 gen_helper_float_cvtd_s(fp64, fp32);
6313 tcg_temp_free_i32(fp32);
6314 gen_store_fpr64(ctx, fp64, fd);
6315 tcg_temp_free_i64(fp64);
6317 opn = "cvt.d.s";
6318 break;
6319 case FOP(36, 16):
6321 TCGv_i32 fp0 = tcg_temp_new_i32();
6323 gen_load_fpr32(fp0, fs);
6324 gen_helper_float_cvtw_s(fp0, fp0);
6325 gen_store_fpr32(fp0, fd);
6326 tcg_temp_free_i32(fp0);
6328 opn = "cvt.w.s";
6329 break;
6330 case FOP(37, 16):
6331 check_cp1_64bitmode(ctx);
6333 TCGv_i32 fp32 = tcg_temp_new_i32();
6334 TCGv_i64 fp64 = tcg_temp_new_i64();
6336 gen_load_fpr32(fp32, fs);
6337 gen_helper_float_cvtl_s(fp64, fp32);
6338 tcg_temp_free_i32(fp32);
6339 gen_store_fpr64(ctx, fp64, fd);
6340 tcg_temp_free_i64(fp64);
6342 opn = "cvt.l.s";
6343 break;
6344 case FOP(38, 16):
6345 check_cp1_64bitmode(ctx);
6347 TCGv_i64 fp64 = tcg_temp_new_i64();
6348 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6349 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6351 gen_load_fpr32(fp32_0, fs);
6352 gen_load_fpr32(fp32_1, ft);
6353 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6354 tcg_temp_free_i32(fp32_1);
6355 tcg_temp_free_i32(fp32_0);
6356 gen_store_fpr64(ctx, fp64, fd);
6357 tcg_temp_free_i64(fp64);
6359 opn = "cvt.ps.s";
6360 break;
6361 case FOP(48, 16):
6362 case FOP(49, 16):
6363 case FOP(50, 16):
6364 case FOP(51, 16):
6365 case FOP(52, 16):
6366 case FOP(53, 16):
6367 case FOP(54, 16):
6368 case FOP(55, 16):
6369 case FOP(56, 16):
6370 case FOP(57, 16):
6371 case FOP(58, 16):
6372 case FOP(59, 16):
6373 case FOP(60, 16):
6374 case FOP(61, 16):
6375 case FOP(62, 16):
6376 case FOP(63, 16):
6378 TCGv_i32 fp0 = tcg_temp_new_i32();
6379 TCGv_i32 fp1 = tcg_temp_new_i32();
6381 gen_load_fpr32(fp0, fs);
6382 gen_load_fpr32(fp1, ft);
6383 if (ctx->opcode & (1 << 6)) {
6384 check_cop1x(ctx);
6385 gen_cmpabs_s(func-48, fp0, fp1, cc);
6386 opn = condnames_abs[func-48];
6387 } else {
6388 gen_cmp_s(func-48, fp0, fp1, cc);
6389 opn = condnames[func-48];
6391 tcg_temp_free_i32(fp0);
6392 tcg_temp_free_i32(fp1);
6394 break;
6395 case FOP(0, 17):
6396 check_cp1_registers(ctx, fs | ft | fd);
6398 TCGv_i64 fp0 = tcg_temp_new_i64();
6399 TCGv_i64 fp1 = tcg_temp_new_i64();
6401 gen_load_fpr64(ctx, fp0, fs);
6402 gen_load_fpr64(ctx, fp1, ft);
6403 gen_helper_float_add_d(fp0, fp0, fp1);
6404 tcg_temp_free_i64(fp1);
6405 gen_store_fpr64(ctx, fp0, fd);
6406 tcg_temp_free_i64(fp0);
6408 opn = "add.d";
6409 optype = BINOP;
6410 break;
6411 case FOP(1, 17):
6412 check_cp1_registers(ctx, fs | ft | fd);
6414 TCGv_i64 fp0 = tcg_temp_new_i64();
6415 TCGv_i64 fp1 = tcg_temp_new_i64();
6417 gen_load_fpr64(ctx, fp0, fs);
6418 gen_load_fpr64(ctx, fp1, ft);
6419 gen_helper_float_sub_d(fp0, fp0, fp1);
6420 tcg_temp_free_i64(fp1);
6421 gen_store_fpr64(ctx, fp0, fd);
6422 tcg_temp_free_i64(fp0);
6424 opn = "sub.d";
6425 optype = BINOP;
6426 break;
6427 case FOP(2, 17):
6428 check_cp1_registers(ctx, fs | ft | fd);
6430 TCGv_i64 fp0 = tcg_temp_new_i64();
6431 TCGv_i64 fp1 = tcg_temp_new_i64();
6433 gen_load_fpr64(ctx, fp0, fs);
6434 gen_load_fpr64(ctx, fp1, ft);
6435 gen_helper_float_mul_d(fp0, fp0, fp1);
6436 tcg_temp_free_i64(fp1);
6437 gen_store_fpr64(ctx, fp0, fd);
6438 tcg_temp_free_i64(fp0);
6440 opn = "mul.d";
6441 optype = BINOP;
6442 break;
6443 case FOP(3, 17):
6444 check_cp1_registers(ctx, fs | ft | fd);
6446 TCGv_i64 fp0 = tcg_temp_new_i64();
6447 TCGv_i64 fp1 = tcg_temp_new_i64();
6449 gen_load_fpr64(ctx, fp0, fs);
6450 gen_load_fpr64(ctx, fp1, ft);
6451 gen_helper_float_div_d(fp0, fp0, fp1);
6452 tcg_temp_free_i64(fp1);
6453 gen_store_fpr64(ctx, fp0, fd);
6454 tcg_temp_free_i64(fp0);
6456 opn = "div.d";
6457 optype = BINOP;
6458 break;
6459 case FOP(4, 17):
6460 check_cp1_registers(ctx, fs | fd);
6462 TCGv_i64 fp0 = tcg_temp_new_i64();
6464 gen_load_fpr64(ctx, fp0, fs);
6465 gen_helper_float_sqrt_d(fp0, fp0);
6466 gen_store_fpr64(ctx, fp0, fd);
6467 tcg_temp_free_i64(fp0);
6469 opn = "sqrt.d";
6470 break;
6471 case FOP(5, 17):
6472 check_cp1_registers(ctx, fs | fd);
6474 TCGv_i64 fp0 = tcg_temp_new_i64();
6476 gen_load_fpr64(ctx, fp0, fs);
6477 gen_helper_float_abs_d(fp0, fp0);
6478 gen_store_fpr64(ctx, fp0, fd);
6479 tcg_temp_free_i64(fp0);
6481 opn = "abs.d";
6482 break;
6483 case FOP(6, 17):
6484 check_cp1_registers(ctx, fs | fd);
6486 TCGv_i64 fp0 = tcg_temp_new_i64();
6488 gen_load_fpr64(ctx, fp0, fs);
6489 gen_store_fpr64(ctx, fp0, fd);
6490 tcg_temp_free_i64(fp0);
6492 opn = "mov.d";
6493 break;
6494 case FOP(7, 17):
6495 check_cp1_registers(ctx, fs | fd);
6497 TCGv_i64 fp0 = tcg_temp_new_i64();
6499 gen_load_fpr64(ctx, fp0, fs);
6500 gen_helper_float_chs_d(fp0, fp0);
6501 gen_store_fpr64(ctx, fp0, fd);
6502 tcg_temp_free_i64(fp0);
6504 opn = "neg.d";
6505 break;
6506 case FOP(8, 17):
6507 check_cp1_64bitmode(ctx);
6509 TCGv_i64 fp0 = tcg_temp_new_i64();
6511 gen_load_fpr64(ctx, fp0, fs);
6512 gen_helper_float_roundl_d(fp0, fp0);
6513 gen_store_fpr64(ctx, fp0, fd);
6514 tcg_temp_free_i64(fp0);
6516 opn = "round.l.d";
6517 break;
6518 case FOP(9, 17):
6519 check_cp1_64bitmode(ctx);
6521 TCGv_i64 fp0 = tcg_temp_new_i64();
6523 gen_load_fpr64(ctx, fp0, fs);
6524 gen_helper_float_truncl_d(fp0, fp0);
6525 gen_store_fpr64(ctx, fp0, fd);
6526 tcg_temp_free_i64(fp0);
6528 opn = "trunc.l.d";
6529 break;
6530 case FOP(10, 17):
6531 check_cp1_64bitmode(ctx);
6533 TCGv_i64 fp0 = tcg_temp_new_i64();
6535 gen_load_fpr64(ctx, fp0, fs);
6536 gen_helper_float_ceill_d(fp0, fp0);
6537 gen_store_fpr64(ctx, fp0, fd);
6538 tcg_temp_free_i64(fp0);
6540 opn = "ceil.l.d";
6541 break;
6542 case FOP(11, 17):
6543 check_cp1_64bitmode(ctx);
6545 TCGv_i64 fp0 = tcg_temp_new_i64();
6547 gen_load_fpr64(ctx, fp0, fs);
6548 gen_helper_float_floorl_d(fp0, fp0);
6549 gen_store_fpr64(ctx, fp0, fd);
6550 tcg_temp_free_i64(fp0);
6552 opn = "floor.l.d";
6553 break;
6554 case FOP(12, 17):
6555 check_cp1_registers(ctx, fs);
6557 TCGv_i32 fp32 = tcg_temp_new_i32();
6558 TCGv_i64 fp64 = tcg_temp_new_i64();
6560 gen_load_fpr64(ctx, fp64, fs);
6561 gen_helper_float_roundw_d(fp32, fp64);
6562 tcg_temp_free_i64(fp64);
6563 gen_store_fpr32(fp32, fd);
6564 tcg_temp_free_i32(fp32);
6566 opn = "round.w.d";
6567 break;
6568 case FOP(13, 17):
6569 check_cp1_registers(ctx, fs);
6571 TCGv_i32 fp32 = tcg_temp_new_i32();
6572 TCGv_i64 fp64 = tcg_temp_new_i64();
6574 gen_load_fpr64(ctx, fp64, fs);
6575 gen_helper_float_truncw_d(fp32, fp64);
6576 tcg_temp_free_i64(fp64);
6577 gen_store_fpr32(fp32, fd);
6578 tcg_temp_free_i32(fp32);
6580 opn = "trunc.w.d";
6581 break;
6582 case FOP(14, 17):
6583 check_cp1_registers(ctx, fs);
6585 TCGv_i32 fp32 = tcg_temp_new_i32();
6586 TCGv_i64 fp64 = tcg_temp_new_i64();
6588 gen_load_fpr64(ctx, fp64, fs);
6589 gen_helper_float_ceilw_d(fp32, fp64);
6590 tcg_temp_free_i64(fp64);
6591 gen_store_fpr32(fp32, fd);
6592 tcg_temp_free_i32(fp32);
6594 opn = "ceil.w.d";
6595 break;
6596 case FOP(15, 17):
6597 check_cp1_registers(ctx, fs);
6599 TCGv_i32 fp32 = tcg_temp_new_i32();
6600 TCGv_i64 fp64 = tcg_temp_new_i64();
6602 gen_load_fpr64(ctx, fp64, fs);
6603 gen_helper_float_floorw_d(fp32, fp64);
6604 tcg_temp_free_i64(fp64);
6605 gen_store_fpr32(fp32, fd);
6606 tcg_temp_free_i32(fp32);
6608 opn = "floor.w.d";
6609 break;
6610 case FOP(17, 17):
6611 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6612 opn = "movcf.d";
6613 break;
6614 case FOP(18, 17):
6616 int l1 = gen_new_label();
6617 TCGv_i64 fp0;
6619 if (ft != 0) {
6620 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6622 fp0 = tcg_temp_new_i64();
6623 gen_load_fpr64(ctx, fp0, fs);
6624 gen_store_fpr64(ctx, fp0, fd);
6625 tcg_temp_free_i64(fp0);
6626 gen_set_label(l1);
6628 opn = "movz.d";
6629 break;
6630 case FOP(19, 17):
6632 int l1 = gen_new_label();
6633 TCGv_i64 fp0;
6635 if (ft != 0) {
6636 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6637 fp0 = tcg_temp_new_i64();
6638 gen_load_fpr64(ctx, fp0, fs);
6639 gen_store_fpr64(ctx, fp0, fd);
6640 tcg_temp_free_i64(fp0);
6641 gen_set_label(l1);
6644 opn = "movn.d";
6645 break;
6646 case FOP(21, 17):
6647 check_cp1_64bitmode(ctx);
6649 TCGv_i64 fp0 = tcg_temp_new_i64();
6651 gen_load_fpr64(ctx, fp0, fs);
6652 gen_helper_float_recip_d(fp0, fp0);
6653 gen_store_fpr64(ctx, fp0, fd);
6654 tcg_temp_free_i64(fp0);
6656 opn = "recip.d";
6657 break;
6658 case FOP(22, 17):
6659 check_cp1_64bitmode(ctx);
6661 TCGv_i64 fp0 = tcg_temp_new_i64();
6663 gen_load_fpr64(ctx, fp0, fs);
6664 gen_helper_float_rsqrt_d(fp0, fp0);
6665 gen_store_fpr64(ctx, fp0, fd);
6666 tcg_temp_free_i64(fp0);
6668 opn = "rsqrt.d";
6669 break;
6670 case FOP(28, 17):
6671 check_cp1_64bitmode(ctx);
6673 TCGv_i64 fp0 = tcg_temp_new_i64();
6674 TCGv_i64 fp1 = tcg_temp_new_i64();
6676 gen_load_fpr64(ctx, fp0, fs);
6677 gen_load_fpr64(ctx, fp1, ft);
6678 gen_helper_float_recip2_d(fp0, fp0, fp1);
6679 tcg_temp_free_i64(fp1);
6680 gen_store_fpr64(ctx, fp0, fd);
6681 tcg_temp_free_i64(fp0);
6683 opn = "recip2.d";
6684 break;
6685 case FOP(29, 17):
6686 check_cp1_64bitmode(ctx);
6688 TCGv_i64 fp0 = tcg_temp_new_i64();
6690 gen_load_fpr64(ctx, fp0, fs);
6691 gen_helper_float_recip1_d(fp0, fp0);
6692 gen_store_fpr64(ctx, fp0, fd);
6693 tcg_temp_free_i64(fp0);
6695 opn = "recip1.d";
6696 break;
6697 case FOP(30, 17):
6698 check_cp1_64bitmode(ctx);
6700 TCGv_i64 fp0 = tcg_temp_new_i64();
6702 gen_load_fpr64(ctx, fp0, fs);
6703 gen_helper_float_rsqrt1_d(fp0, fp0);
6704 gen_store_fpr64(ctx, fp0, fd);
6705 tcg_temp_free_i64(fp0);
6707 opn = "rsqrt1.d";
6708 break;
6709 case FOP(31, 17):
6710 check_cp1_64bitmode(ctx);
6712 TCGv_i64 fp0 = tcg_temp_new_i64();
6713 TCGv_i64 fp1 = tcg_temp_new_i64();
6715 gen_load_fpr64(ctx, fp0, fs);
6716 gen_load_fpr64(ctx, fp1, ft);
6717 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6718 tcg_temp_free_i64(fp1);
6719 gen_store_fpr64(ctx, fp0, fd);
6720 tcg_temp_free_i64(fp0);
6722 opn = "rsqrt2.d";
6723 break;
6724 case FOP(48, 17):
6725 case FOP(49, 17):
6726 case FOP(50, 17):
6727 case FOP(51, 17):
6728 case FOP(52, 17):
6729 case FOP(53, 17):
6730 case FOP(54, 17):
6731 case FOP(55, 17):
6732 case FOP(56, 17):
6733 case FOP(57, 17):
6734 case FOP(58, 17):
6735 case FOP(59, 17):
6736 case FOP(60, 17):
6737 case FOP(61, 17):
6738 case FOP(62, 17):
6739 case FOP(63, 17):
6741 TCGv_i64 fp0 = tcg_temp_new_i64();
6742 TCGv_i64 fp1 = tcg_temp_new_i64();
6744 gen_load_fpr64(ctx, fp0, fs);
6745 gen_load_fpr64(ctx, fp1, ft);
6746 if (ctx->opcode & (1 << 6)) {
6747 check_cop1x(ctx);
6748 check_cp1_registers(ctx, fs | ft);
6749 gen_cmpabs_d(func-48, fp0, fp1, cc);
6750 opn = condnames_abs[func-48];
6751 } else {
6752 check_cp1_registers(ctx, fs | ft);
6753 gen_cmp_d(func-48, fp0, fp1, cc);
6754 opn = condnames[func-48];
6756 tcg_temp_free_i64(fp0);
6757 tcg_temp_free_i64(fp1);
6759 break;
6760 case FOP(32, 17):
6761 check_cp1_registers(ctx, fs);
6763 TCGv_i32 fp32 = tcg_temp_new_i32();
6764 TCGv_i64 fp64 = tcg_temp_new_i64();
6766 gen_load_fpr64(ctx, fp64, fs);
6767 gen_helper_float_cvts_d(fp32, fp64);
6768 tcg_temp_free_i64(fp64);
6769 gen_store_fpr32(fp32, fd);
6770 tcg_temp_free_i32(fp32);
6772 opn = "cvt.s.d";
6773 break;
6774 case FOP(36, 17):
6775 check_cp1_registers(ctx, fs);
6777 TCGv_i32 fp32 = tcg_temp_new_i32();
6778 TCGv_i64 fp64 = tcg_temp_new_i64();
6780 gen_load_fpr64(ctx, fp64, fs);
6781 gen_helper_float_cvtw_d(fp32, fp64);
6782 tcg_temp_free_i64(fp64);
6783 gen_store_fpr32(fp32, fd);
6784 tcg_temp_free_i32(fp32);
6786 opn = "cvt.w.d";
6787 break;
6788 case FOP(37, 17):
6789 check_cp1_64bitmode(ctx);
6791 TCGv_i64 fp0 = tcg_temp_new_i64();
6793 gen_load_fpr64(ctx, fp0, fs);
6794 gen_helper_float_cvtl_d(fp0, fp0);
6795 gen_store_fpr64(ctx, fp0, fd);
6796 tcg_temp_free_i64(fp0);
6798 opn = "cvt.l.d";
6799 break;
6800 case FOP(32, 20):
6802 TCGv_i32 fp0 = tcg_temp_new_i32();
6804 gen_load_fpr32(fp0, fs);
6805 gen_helper_float_cvts_w(fp0, fp0);
6806 gen_store_fpr32(fp0, fd);
6807 tcg_temp_free_i32(fp0);
6809 opn = "cvt.s.w";
6810 break;
6811 case FOP(33, 20):
6812 check_cp1_registers(ctx, fd);
6814 TCGv_i32 fp32 = tcg_temp_new_i32();
6815 TCGv_i64 fp64 = tcg_temp_new_i64();
6817 gen_load_fpr32(fp32, fs);
6818 gen_helper_float_cvtd_w(fp64, fp32);
6819 tcg_temp_free_i32(fp32);
6820 gen_store_fpr64(ctx, fp64, fd);
6821 tcg_temp_free_i64(fp64);
6823 opn = "cvt.d.w";
6824 break;
6825 case FOP(32, 21):
6826 check_cp1_64bitmode(ctx);
6828 TCGv_i32 fp32 = tcg_temp_new_i32();
6829 TCGv_i64 fp64 = tcg_temp_new_i64();
6831 gen_load_fpr64(ctx, fp64, fs);
6832 gen_helper_float_cvts_l(fp32, fp64);
6833 tcg_temp_free_i64(fp64);
6834 gen_store_fpr32(fp32, fd);
6835 tcg_temp_free_i32(fp32);
6837 opn = "cvt.s.l";
6838 break;
6839 case FOP(33, 21):
6840 check_cp1_64bitmode(ctx);
6842 TCGv_i64 fp0 = tcg_temp_new_i64();
6844 gen_load_fpr64(ctx, fp0, fs);
6845 gen_helper_float_cvtd_l(fp0, fp0);
6846 gen_store_fpr64(ctx, fp0, fd);
6847 tcg_temp_free_i64(fp0);
6849 opn = "cvt.d.l";
6850 break;
6851 case FOP(38, 20):
6852 check_cp1_64bitmode(ctx);
6854 TCGv_i64 fp0 = tcg_temp_new_i64();
6856 gen_load_fpr64(ctx, fp0, fs);
6857 gen_helper_float_cvtps_pw(fp0, fp0);
6858 gen_store_fpr64(ctx, fp0, fd);
6859 tcg_temp_free_i64(fp0);
6861 opn = "cvt.ps.pw";
6862 break;
6863 case FOP(0, 22):
6864 check_cp1_64bitmode(ctx);
6866 TCGv_i64 fp0 = tcg_temp_new_i64();
6867 TCGv_i64 fp1 = tcg_temp_new_i64();
6869 gen_load_fpr64(ctx, fp0, fs);
6870 gen_load_fpr64(ctx, fp1, ft);
6871 gen_helper_float_add_ps(fp0, fp0, fp1);
6872 tcg_temp_free_i64(fp1);
6873 gen_store_fpr64(ctx, fp0, fd);
6874 tcg_temp_free_i64(fp0);
6876 opn = "add.ps";
6877 break;
6878 case FOP(1, 22):
6879 check_cp1_64bitmode(ctx);
6881 TCGv_i64 fp0 = tcg_temp_new_i64();
6882 TCGv_i64 fp1 = tcg_temp_new_i64();
6884 gen_load_fpr64(ctx, fp0, fs);
6885 gen_load_fpr64(ctx, fp1, ft);
6886 gen_helper_float_sub_ps(fp0, fp0, fp1);
6887 tcg_temp_free_i64(fp1);
6888 gen_store_fpr64(ctx, fp0, fd);
6889 tcg_temp_free_i64(fp0);
6891 opn = "sub.ps";
6892 break;
6893 case FOP(2, 22):
6894 check_cp1_64bitmode(ctx);
6896 TCGv_i64 fp0 = tcg_temp_new_i64();
6897 TCGv_i64 fp1 = tcg_temp_new_i64();
6899 gen_load_fpr64(ctx, fp0, fs);
6900 gen_load_fpr64(ctx, fp1, ft);
6901 gen_helper_float_mul_ps(fp0, fp0, fp1);
6902 tcg_temp_free_i64(fp1);
6903 gen_store_fpr64(ctx, fp0, fd);
6904 tcg_temp_free_i64(fp0);
6906 opn = "mul.ps";
6907 break;
6908 case FOP(5, 22):
6909 check_cp1_64bitmode(ctx);
6911 TCGv_i64 fp0 = tcg_temp_new_i64();
6913 gen_load_fpr64(ctx, fp0, fs);
6914 gen_helper_float_abs_ps(fp0, fp0);
6915 gen_store_fpr64(ctx, fp0, fd);
6916 tcg_temp_free_i64(fp0);
6918 opn = "abs.ps";
6919 break;
6920 case FOP(6, 22):
6921 check_cp1_64bitmode(ctx);
6923 TCGv_i64 fp0 = tcg_temp_new_i64();
6925 gen_load_fpr64(ctx, fp0, fs);
6926 gen_store_fpr64(ctx, fp0, fd);
6927 tcg_temp_free_i64(fp0);
6929 opn = "mov.ps";
6930 break;
6931 case FOP(7, 22):
6932 check_cp1_64bitmode(ctx);
6934 TCGv_i64 fp0 = tcg_temp_new_i64();
6936 gen_load_fpr64(ctx, fp0, fs);
6937 gen_helper_float_chs_ps(fp0, fp0);
6938 gen_store_fpr64(ctx, fp0, fd);
6939 tcg_temp_free_i64(fp0);
6941 opn = "neg.ps";
6942 break;
6943 case FOP(17, 22):
6944 check_cp1_64bitmode(ctx);
6945 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6946 opn = "movcf.ps";
6947 break;
6948 case FOP(18, 22):
6949 check_cp1_64bitmode(ctx);
6951 int l1 = gen_new_label();
6952 TCGv_i64 fp0;
6954 if (ft != 0)
6955 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6956 fp0 = tcg_temp_new_i64();
6957 gen_load_fpr64(ctx, fp0, fs);
6958 gen_store_fpr64(ctx, fp0, fd);
6959 tcg_temp_free_i64(fp0);
6960 gen_set_label(l1);
6962 opn = "movz.ps";
6963 break;
6964 case FOP(19, 22):
6965 check_cp1_64bitmode(ctx);
6967 int l1 = gen_new_label();
6968 TCGv_i64 fp0;
6970 if (ft != 0) {
6971 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6972 fp0 = tcg_temp_new_i64();
6973 gen_load_fpr64(ctx, fp0, fs);
6974 gen_store_fpr64(ctx, fp0, fd);
6975 tcg_temp_free_i64(fp0);
6976 gen_set_label(l1);
6979 opn = "movn.ps";
6980 break;
6981 case FOP(24, 22):
6982 check_cp1_64bitmode(ctx);
6984 TCGv_i64 fp0 = tcg_temp_new_i64();
6985 TCGv_i64 fp1 = tcg_temp_new_i64();
6987 gen_load_fpr64(ctx, fp0, ft);
6988 gen_load_fpr64(ctx, fp1, fs);
6989 gen_helper_float_addr_ps(fp0, fp0, fp1);
6990 tcg_temp_free_i64(fp1);
6991 gen_store_fpr64(ctx, fp0, fd);
6992 tcg_temp_free_i64(fp0);
6994 opn = "addr.ps";
6995 break;
6996 case FOP(26, 22):
6997 check_cp1_64bitmode(ctx);
6999 TCGv_i64 fp0 = tcg_temp_new_i64();
7000 TCGv_i64 fp1 = tcg_temp_new_i64();
7002 gen_load_fpr64(ctx, fp0, ft);
7003 gen_load_fpr64(ctx, fp1, fs);
7004 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7005 tcg_temp_free_i64(fp1);
7006 gen_store_fpr64(ctx, fp0, fd);
7007 tcg_temp_free_i64(fp0);
7009 opn = "mulr.ps";
7010 break;
7011 case FOP(28, 22):
7012 check_cp1_64bitmode(ctx);
7014 TCGv_i64 fp0 = tcg_temp_new_i64();
7015 TCGv_i64 fp1 = tcg_temp_new_i64();
7017 gen_load_fpr64(ctx, fp0, fs);
7018 gen_load_fpr64(ctx, fp1, fd);
7019 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7020 tcg_temp_free_i64(fp1);
7021 gen_store_fpr64(ctx, fp0, fd);
7022 tcg_temp_free_i64(fp0);
7024 opn = "recip2.ps";
7025 break;
7026 case FOP(29, 22):
7027 check_cp1_64bitmode(ctx);
7029 TCGv_i64 fp0 = tcg_temp_new_i64();
7031 gen_load_fpr64(ctx, fp0, fs);
7032 gen_helper_float_recip1_ps(fp0, fp0);
7033 gen_store_fpr64(ctx, fp0, fd);
7034 tcg_temp_free_i64(fp0);
7036 opn = "recip1.ps";
7037 break;
7038 case FOP(30, 22):
7039 check_cp1_64bitmode(ctx);
7041 TCGv_i64 fp0 = tcg_temp_new_i64();
7043 gen_load_fpr64(ctx, fp0, fs);
7044 gen_helper_float_rsqrt1_ps(fp0, fp0);
7045 gen_store_fpr64(ctx, fp0, fd);
7046 tcg_temp_free_i64(fp0);
7048 opn = "rsqrt1.ps";
7049 break;
7050 case FOP(31, 22):
7051 check_cp1_64bitmode(ctx);
7053 TCGv_i64 fp0 = tcg_temp_new_i64();
7054 TCGv_i64 fp1 = tcg_temp_new_i64();
7056 gen_load_fpr64(ctx, fp0, fs);
7057 gen_load_fpr64(ctx, fp1, ft);
7058 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7059 tcg_temp_free_i64(fp1);
7060 gen_store_fpr64(ctx, fp0, fd);
7061 tcg_temp_free_i64(fp0);
7063 opn = "rsqrt2.ps";
7064 break;
7065 case FOP(32, 22):
7066 check_cp1_64bitmode(ctx);
7068 TCGv_i32 fp0 = tcg_temp_new_i32();
7070 gen_load_fpr32h(fp0, fs);
7071 gen_helper_float_cvts_pu(fp0, fp0);
7072 gen_store_fpr32(fp0, fd);
7073 tcg_temp_free_i32(fp0);
7075 opn = "cvt.s.pu";
7076 break;
7077 case FOP(36, 22):
7078 check_cp1_64bitmode(ctx);
7080 TCGv_i64 fp0 = tcg_temp_new_i64();
7082 gen_load_fpr64(ctx, fp0, fs);
7083 gen_helper_float_cvtpw_ps(fp0, fp0);
7084 gen_store_fpr64(ctx, fp0, fd);
7085 tcg_temp_free_i64(fp0);
7087 opn = "cvt.pw.ps";
7088 break;
7089 case FOP(40, 22):
7090 check_cp1_64bitmode(ctx);
7092 TCGv_i32 fp0 = tcg_temp_new_i32();
7094 gen_load_fpr32(fp0, fs);
7095 gen_helper_float_cvts_pl(fp0, fp0);
7096 gen_store_fpr32(fp0, fd);
7097 tcg_temp_free_i32(fp0);
7099 opn = "cvt.s.pl";
7100 break;
7101 case FOP(44, 22):
7102 check_cp1_64bitmode(ctx);
7104 TCGv_i32 fp0 = tcg_temp_new_i32();
7105 TCGv_i32 fp1 = tcg_temp_new_i32();
7107 gen_load_fpr32(fp0, fs);
7108 gen_load_fpr32(fp1, ft);
7109 gen_store_fpr32h(fp0, fd);
7110 gen_store_fpr32(fp1, fd);
7111 tcg_temp_free_i32(fp0);
7112 tcg_temp_free_i32(fp1);
7114 opn = "pll.ps";
7115 break;
7116 case FOP(45, 22):
7117 check_cp1_64bitmode(ctx);
7119 TCGv_i32 fp0 = tcg_temp_new_i32();
7120 TCGv_i32 fp1 = tcg_temp_new_i32();
7122 gen_load_fpr32(fp0, fs);
7123 gen_load_fpr32h(fp1, ft);
7124 gen_store_fpr32(fp1, fd);
7125 gen_store_fpr32h(fp0, fd);
7126 tcg_temp_free_i32(fp0);
7127 tcg_temp_free_i32(fp1);
7129 opn = "plu.ps";
7130 break;
7131 case FOP(46, 22):
7132 check_cp1_64bitmode(ctx);
7134 TCGv_i32 fp0 = tcg_temp_new_i32();
7135 TCGv_i32 fp1 = tcg_temp_new_i32();
7137 gen_load_fpr32h(fp0, fs);
7138 gen_load_fpr32(fp1, ft);
7139 gen_store_fpr32(fp1, fd);
7140 gen_store_fpr32h(fp0, fd);
7141 tcg_temp_free_i32(fp0);
7142 tcg_temp_free_i32(fp1);
7144 opn = "pul.ps";
7145 break;
7146 case FOP(47, 22):
7147 check_cp1_64bitmode(ctx);
7149 TCGv_i32 fp0 = tcg_temp_new_i32();
7150 TCGv_i32 fp1 = tcg_temp_new_i32();
7152 gen_load_fpr32h(fp0, fs);
7153 gen_load_fpr32h(fp1, ft);
7154 gen_store_fpr32(fp1, fd);
7155 gen_store_fpr32h(fp0, fd);
7156 tcg_temp_free_i32(fp0);
7157 tcg_temp_free_i32(fp1);
7159 opn = "puu.ps";
7160 break;
7161 case FOP(48, 22):
7162 case FOP(49, 22):
7163 case FOP(50, 22):
7164 case FOP(51, 22):
7165 case FOP(52, 22):
7166 case FOP(53, 22):
7167 case FOP(54, 22):
7168 case FOP(55, 22):
7169 case FOP(56, 22):
7170 case FOP(57, 22):
7171 case FOP(58, 22):
7172 case FOP(59, 22):
7173 case FOP(60, 22):
7174 case FOP(61, 22):
7175 case FOP(62, 22):
7176 case FOP(63, 22):
7177 check_cp1_64bitmode(ctx);
7179 TCGv_i64 fp0 = tcg_temp_new_i64();
7180 TCGv_i64 fp1 = tcg_temp_new_i64();
7182 gen_load_fpr64(ctx, fp0, fs);
7183 gen_load_fpr64(ctx, fp1, ft);
7184 if (ctx->opcode & (1 << 6)) {
7185 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7186 opn = condnames_abs[func-48];
7187 } else {
7188 gen_cmp_ps(func-48, fp0, fp1, cc);
7189 opn = condnames[func-48];
7191 tcg_temp_free_i64(fp0);
7192 tcg_temp_free_i64(fp1);
7194 break;
7195 default:
7196 MIPS_INVAL(opn);
7197 generate_exception (ctx, EXCP_RI);
7198 return;
7200 switch (optype) {
7201 case BINOP:
7202 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7203 break;
7204 case CMPOP:
7205 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7206 break;
7207 default:
7208 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7209 break;
7213 /* Coprocessor 3 (FPU) */
7214 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7215 int fd, int fs, int base, int index)
7217 const char *opn = "extended float load/store";
7218 int store = 0;
7219 TCGv t0 = tcg_temp_new();
7221 if (base == 0) {
7222 gen_load_gpr(t0, index);
7223 } else if (index == 0) {
7224 gen_load_gpr(t0, base);
7225 } else {
7226 gen_load_gpr(t0, index);
7227 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
7229 /* Don't do NOP if destination is zero: we must perform the actual
7230 memory access. */
7231 save_cpu_state(ctx, 0);
7232 switch (opc) {
7233 case OPC_LWXC1:
7234 check_cop1x(ctx);
7236 TCGv_i32 fp0 = tcg_temp_new_i32();
7238 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7239 tcg_gen_trunc_tl_i32(fp0, t0);
7240 gen_store_fpr32(fp0, fd);
7241 tcg_temp_free_i32(fp0);
7243 opn = "lwxc1";
7244 break;
7245 case OPC_LDXC1:
7246 check_cop1x(ctx);
7247 check_cp1_registers(ctx, fd);
7249 TCGv_i64 fp0 = tcg_temp_new_i64();
7251 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7252 gen_store_fpr64(ctx, fp0, fd);
7253 tcg_temp_free_i64(fp0);
7255 opn = "ldxc1";
7256 break;
7257 case OPC_LUXC1:
7258 check_cp1_64bitmode(ctx);
7259 tcg_gen_andi_tl(t0, t0, ~0x7);
7261 TCGv_i64 fp0 = tcg_temp_new_i64();
7263 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7264 gen_store_fpr64(ctx, fp0, fd);
7265 tcg_temp_free_i64(fp0);
7267 opn = "luxc1";
7268 break;
7269 case OPC_SWXC1:
7270 check_cop1x(ctx);
7272 TCGv_i32 fp0 = tcg_temp_new_i32();
7273 TCGv t1 = tcg_temp_new();
7275 gen_load_fpr32(fp0, fs);
7276 tcg_gen_extu_i32_tl(t1, fp0);
7277 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7278 tcg_temp_free_i32(fp0);
7279 tcg_temp_free(t1);
7281 opn = "swxc1";
7282 store = 1;
7283 break;
7284 case OPC_SDXC1:
7285 check_cop1x(ctx);
7286 check_cp1_registers(ctx, fs);
7288 TCGv_i64 fp0 = tcg_temp_new_i64();
7290 gen_load_fpr64(ctx, fp0, fs);
7291 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7292 tcg_temp_free_i64(fp0);
7294 opn = "sdxc1";
7295 store = 1;
7296 break;
7297 case OPC_SUXC1:
7298 check_cp1_64bitmode(ctx);
7299 tcg_gen_andi_tl(t0, t0, ~0x7);
7301 TCGv_i64 fp0 = tcg_temp_new_i64();
7303 gen_load_fpr64(ctx, fp0, fs);
7304 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7305 tcg_temp_free_i64(fp0);
7307 opn = "suxc1";
7308 store = 1;
7309 break;
7311 tcg_temp_free(t0);
7312 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7313 regnames[index], regnames[base]);
7316 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7317 int fd, int fr, int fs, int ft)
7319 const char *opn = "flt3_arith";
7321 switch (opc) {
7322 case OPC_ALNV_PS:
7323 check_cp1_64bitmode(ctx);
7325 TCGv t0 = tcg_temp_local_new();
7326 TCGv_i32 fp = tcg_temp_new_i32();
7327 TCGv_i32 fph = tcg_temp_new_i32();
7328 int l1 = gen_new_label();
7329 int l2 = gen_new_label();
7331 gen_load_gpr(t0, fr);
7332 tcg_gen_andi_tl(t0, t0, 0x7);
7334 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7335 gen_load_fpr32(fp, fs);
7336 gen_load_fpr32h(fph, fs);
7337 gen_store_fpr32(fp, fd);
7338 gen_store_fpr32h(fph, fd);
7339 tcg_gen_br(l2);
7340 gen_set_label(l1);
7341 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7342 tcg_temp_free(t0);
7343 #ifdef TARGET_WORDS_BIGENDIAN
7344 gen_load_fpr32(fp, fs);
7345 gen_load_fpr32h(fph, ft);
7346 gen_store_fpr32h(fp, fd);
7347 gen_store_fpr32(fph, fd);
7348 #else
7349 gen_load_fpr32h(fph, fs);
7350 gen_load_fpr32(fp, ft);
7351 gen_store_fpr32(fph, fd);
7352 gen_store_fpr32h(fp, fd);
7353 #endif
7354 gen_set_label(l2);
7355 tcg_temp_free_i32(fp);
7356 tcg_temp_free_i32(fph);
7358 opn = "alnv.ps";
7359 break;
7360 case OPC_MADD_S:
7361 check_cop1x(ctx);
7363 TCGv_i32 fp0 = tcg_temp_new_i32();
7364 TCGv_i32 fp1 = tcg_temp_new_i32();
7365 TCGv_i32 fp2 = tcg_temp_new_i32();
7367 gen_load_fpr32(fp0, fs);
7368 gen_load_fpr32(fp1, ft);
7369 gen_load_fpr32(fp2, fr);
7370 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7371 tcg_temp_free_i32(fp0);
7372 tcg_temp_free_i32(fp1);
7373 gen_store_fpr32(fp2, fd);
7374 tcg_temp_free_i32(fp2);
7376 opn = "madd.s";
7377 break;
7378 case OPC_MADD_D:
7379 check_cop1x(ctx);
7380 check_cp1_registers(ctx, fd | fs | ft | fr);
7382 TCGv_i64 fp0 = tcg_temp_new_i64();
7383 TCGv_i64 fp1 = tcg_temp_new_i64();
7384 TCGv_i64 fp2 = tcg_temp_new_i64();
7386 gen_load_fpr64(ctx, fp0, fs);
7387 gen_load_fpr64(ctx, fp1, ft);
7388 gen_load_fpr64(ctx, fp2, fr);
7389 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7390 tcg_temp_free_i64(fp0);
7391 tcg_temp_free_i64(fp1);
7392 gen_store_fpr64(ctx, fp2, fd);
7393 tcg_temp_free_i64(fp2);
7395 opn = "madd.d";
7396 break;
7397 case OPC_MADD_PS:
7398 check_cp1_64bitmode(ctx);
7400 TCGv_i64 fp0 = tcg_temp_new_i64();
7401 TCGv_i64 fp1 = tcg_temp_new_i64();
7402 TCGv_i64 fp2 = tcg_temp_new_i64();
7404 gen_load_fpr64(ctx, fp0, fs);
7405 gen_load_fpr64(ctx, fp1, ft);
7406 gen_load_fpr64(ctx, fp2, fr);
7407 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7408 tcg_temp_free_i64(fp0);
7409 tcg_temp_free_i64(fp1);
7410 gen_store_fpr64(ctx, fp2, fd);
7411 tcg_temp_free_i64(fp2);
7413 opn = "madd.ps";
7414 break;
7415 case OPC_MSUB_S:
7416 check_cop1x(ctx);
7418 TCGv_i32 fp0 = tcg_temp_new_i32();
7419 TCGv_i32 fp1 = tcg_temp_new_i32();
7420 TCGv_i32 fp2 = tcg_temp_new_i32();
7422 gen_load_fpr32(fp0, fs);
7423 gen_load_fpr32(fp1, ft);
7424 gen_load_fpr32(fp2, fr);
7425 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7426 tcg_temp_free_i32(fp0);
7427 tcg_temp_free_i32(fp1);
7428 gen_store_fpr32(fp2, fd);
7429 tcg_temp_free_i32(fp2);
7431 opn = "msub.s";
7432 break;
7433 case OPC_MSUB_D:
7434 check_cop1x(ctx);
7435 check_cp1_registers(ctx, fd | fs | ft | fr);
7437 TCGv_i64 fp0 = tcg_temp_new_i64();
7438 TCGv_i64 fp1 = tcg_temp_new_i64();
7439 TCGv_i64 fp2 = tcg_temp_new_i64();
7441 gen_load_fpr64(ctx, fp0, fs);
7442 gen_load_fpr64(ctx, fp1, ft);
7443 gen_load_fpr64(ctx, fp2, fr);
7444 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7445 tcg_temp_free_i64(fp0);
7446 tcg_temp_free_i64(fp1);
7447 gen_store_fpr64(ctx, fp2, fd);
7448 tcg_temp_free_i64(fp2);
7450 opn = "msub.d";
7451 break;
7452 case OPC_MSUB_PS:
7453 check_cp1_64bitmode(ctx);
7455 TCGv_i64 fp0 = tcg_temp_new_i64();
7456 TCGv_i64 fp1 = tcg_temp_new_i64();
7457 TCGv_i64 fp2 = tcg_temp_new_i64();
7459 gen_load_fpr64(ctx, fp0, fs);
7460 gen_load_fpr64(ctx, fp1, ft);
7461 gen_load_fpr64(ctx, fp2, fr);
7462 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7463 tcg_temp_free_i64(fp0);
7464 tcg_temp_free_i64(fp1);
7465 gen_store_fpr64(ctx, fp2, fd);
7466 tcg_temp_free_i64(fp2);
7468 opn = "msub.ps";
7469 break;
7470 case OPC_NMADD_S:
7471 check_cop1x(ctx);
7473 TCGv_i32 fp0 = tcg_temp_new_i32();
7474 TCGv_i32 fp1 = tcg_temp_new_i32();
7475 TCGv_i32 fp2 = tcg_temp_new_i32();
7477 gen_load_fpr32(fp0, fs);
7478 gen_load_fpr32(fp1, ft);
7479 gen_load_fpr32(fp2, fr);
7480 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7481 tcg_temp_free_i32(fp0);
7482 tcg_temp_free_i32(fp1);
7483 gen_store_fpr32(fp2, fd);
7484 tcg_temp_free_i32(fp2);
7486 opn = "nmadd.s";
7487 break;
7488 case OPC_NMADD_D:
7489 check_cop1x(ctx);
7490 check_cp1_registers(ctx, fd | fs | ft | fr);
7492 TCGv_i64 fp0 = tcg_temp_new_i64();
7493 TCGv_i64 fp1 = tcg_temp_new_i64();
7494 TCGv_i64 fp2 = tcg_temp_new_i64();
7496 gen_load_fpr64(ctx, fp0, fs);
7497 gen_load_fpr64(ctx, fp1, ft);
7498 gen_load_fpr64(ctx, fp2, fr);
7499 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7500 tcg_temp_free_i64(fp0);
7501 tcg_temp_free_i64(fp1);
7502 gen_store_fpr64(ctx, fp2, fd);
7503 tcg_temp_free_i64(fp2);
7505 opn = "nmadd.d";
7506 break;
7507 case OPC_NMADD_PS:
7508 check_cp1_64bitmode(ctx);
7510 TCGv_i64 fp0 = tcg_temp_new_i64();
7511 TCGv_i64 fp1 = tcg_temp_new_i64();
7512 TCGv_i64 fp2 = tcg_temp_new_i64();
7514 gen_load_fpr64(ctx, fp0, fs);
7515 gen_load_fpr64(ctx, fp1, ft);
7516 gen_load_fpr64(ctx, fp2, fr);
7517 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7518 tcg_temp_free_i64(fp0);
7519 tcg_temp_free_i64(fp1);
7520 gen_store_fpr64(ctx, fp2, fd);
7521 tcg_temp_free_i64(fp2);
7523 opn = "nmadd.ps";
7524 break;
7525 case OPC_NMSUB_S:
7526 check_cop1x(ctx);
7528 TCGv_i32 fp0 = tcg_temp_new_i32();
7529 TCGv_i32 fp1 = tcg_temp_new_i32();
7530 TCGv_i32 fp2 = tcg_temp_new_i32();
7532 gen_load_fpr32(fp0, fs);
7533 gen_load_fpr32(fp1, ft);
7534 gen_load_fpr32(fp2, fr);
7535 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7536 tcg_temp_free_i32(fp0);
7537 tcg_temp_free_i32(fp1);
7538 gen_store_fpr32(fp2, fd);
7539 tcg_temp_free_i32(fp2);
7541 opn = "nmsub.s";
7542 break;
7543 case OPC_NMSUB_D:
7544 check_cop1x(ctx);
7545 check_cp1_registers(ctx, fd | fs | ft | fr);
7547 TCGv_i64 fp0 = tcg_temp_new_i64();
7548 TCGv_i64 fp1 = tcg_temp_new_i64();
7549 TCGv_i64 fp2 = tcg_temp_new_i64();
7551 gen_load_fpr64(ctx, fp0, fs);
7552 gen_load_fpr64(ctx, fp1, ft);
7553 gen_load_fpr64(ctx, fp2, fr);
7554 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7555 tcg_temp_free_i64(fp0);
7556 tcg_temp_free_i64(fp1);
7557 gen_store_fpr64(ctx, fp2, fd);
7558 tcg_temp_free_i64(fp2);
7560 opn = "nmsub.d";
7561 break;
7562 case OPC_NMSUB_PS:
7563 check_cp1_64bitmode(ctx);
7565 TCGv_i64 fp0 = tcg_temp_new_i64();
7566 TCGv_i64 fp1 = tcg_temp_new_i64();
7567 TCGv_i64 fp2 = tcg_temp_new_i64();
7569 gen_load_fpr64(ctx, fp0, fs);
7570 gen_load_fpr64(ctx, fp1, ft);
7571 gen_load_fpr64(ctx, fp2, fr);
7572 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7573 tcg_temp_free_i64(fp0);
7574 tcg_temp_free_i64(fp1);
7575 gen_store_fpr64(ctx, fp2, fd);
7576 tcg_temp_free_i64(fp2);
7578 opn = "nmsub.ps";
7579 break;
7580 default:
7581 MIPS_INVAL(opn);
7582 generate_exception (ctx, EXCP_RI);
7583 return;
7585 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7586 fregnames[fs], fregnames[ft]);
7589 /* ISA extensions (ASEs) */
7590 /* MIPS16 extension to MIPS32 */
7591 /* SmartMIPS extension to MIPS32 */
7593 #if defined(TARGET_MIPS64)
7595 /* MDMX extension to MIPS64 */
7597 #endif
7599 static void decode_opc (CPUState *env, DisasContext *ctx)
7601 int32_t offset;
7602 int rs, rt, rd, sa;
7603 uint32_t op, op1, op2;
7604 int16_t imm;
7606 /* make sure instructions are on a word boundary */
7607 if (ctx->pc & 0x3) {
7608 env->CP0_BadVAddr = ctx->pc;
7609 generate_exception(ctx, EXCP_AdEL);
7610 return;
7613 /* Handle blikely not taken case */
7614 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7615 int l1 = gen_new_label();
7617 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7618 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7619 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
7620 gen_goto_tb(ctx, 1, ctx->pc + 4);
7621 gen_set_label(l1);
7623 op = MASK_OP_MAJOR(ctx->opcode);
7624 rs = (ctx->opcode >> 21) & 0x1f;
7625 rt = (ctx->opcode >> 16) & 0x1f;
7626 rd = (ctx->opcode >> 11) & 0x1f;
7627 sa = (ctx->opcode >> 6) & 0x1f;
7628 imm = (int16_t)ctx->opcode;
7629 switch (op) {
7630 case OPC_SPECIAL:
7631 op1 = MASK_SPECIAL(ctx->opcode);
7632 switch (op1) {
7633 case OPC_SLL: /* Shift with immediate */
7634 case OPC_SRA:
7635 case OPC_SRL:
7636 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7637 break;
7638 case OPC_MOVN: /* Conditional move */
7639 case OPC_MOVZ:
7640 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7641 gen_cond_move(env, op1, rd, rs, rt);
7642 break;
7643 case OPC_ADD ... OPC_SUBU:
7644 gen_arith(env, ctx, op1, rd, rs, rt);
7645 break;
7646 case OPC_SLLV: /* Shifts */
7647 case OPC_SRLV:
7648 case OPC_SRAV:
7649 gen_shift(env, ctx, op1, rd, rs, rt);
7650 break;
7651 case OPC_SLT: /* Set on less than */
7652 case OPC_SLTU:
7653 gen_slt(env, op1, rd, rs, rt);
7654 break;
7655 case OPC_AND: /* Logic*/
7656 case OPC_OR:
7657 case OPC_NOR:
7658 case OPC_XOR:
7659 gen_logic(env, op1, rd, rs, rt);
7660 break;
7661 case OPC_MULT ... OPC_DIVU:
7662 if (sa) {
7663 check_insn(env, ctx, INSN_VR54XX);
7664 op1 = MASK_MUL_VR54XX(ctx->opcode);
7665 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7666 } else
7667 gen_muldiv(ctx, op1, rs, rt);
7668 break;
7669 case OPC_JR ... OPC_JALR:
7670 gen_compute_branch(ctx, op1, rs, rd, sa);
7671 return;
7672 case OPC_TGE ... OPC_TEQ: /* Traps */
7673 case OPC_TNE:
7674 gen_trap(ctx, op1, rs, rt, -1);
7675 break;
7676 case OPC_MFHI: /* Move from HI/LO */
7677 case OPC_MFLO:
7678 gen_HILO(ctx, op1, rd);
7679 break;
7680 case OPC_MTHI:
7681 case OPC_MTLO: /* Move to HI/LO */
7682 gen_HILO(ctx, op1, rs);
7683 break;
7684 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7685 #ifdef MIPS_STRICT_STANDARD
7686 MIPS_INVAL("PMON / selsl");
7687 generate_exception(ctx, EXCP_RI);
7688 #else
7689 gen_helper_0i(pmon, sa);
7690 #endif
7691 break;
7692 case OPC_SYSCALL:
7693 generate_exception(ctx, EXCP_SYSCALL);
7694 ctx->bstate = BS_STOP;
7695 break;
7696 case OPC_BREAK:
7697 generate_exception(ctx, EXCP_BREAK);
7698 break;
7699 case OPC_SPIM:
7700 #ifdef MIPS_STRICT_STANDARD
7701 MIPS_INVAL("SPIM");
7702 generate_exception(ctx, EXCP_RI);
7703 #else
7704 /* Implemented as RI exception for now. */
7705 MIPS_INVAL("spim (unofficial)");
7706 generate_exception(ctx, EXCP_RI);
7707 #endif
7708 break;
7709 case OPC_SYNC:
7710 /* Treat as NOP. */
7711 break;
7713 case OPC_MOVCI:
7714 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7715 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7716 check_cp1_enabled(ctx);
7717 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7718 (ctx->opcode >> 16) & 1);
7719 } else {
7720 generate_exception_err(ctx, EXCP_CpU, 1);
7722 break;
7724 #if defined(TARGET_MIPS64)
7725 /* MIPS64 specific opcodes */
7726 case OPC_DSLL:
7727 case OPC_DSRA:
7728 case OPC_DSRL:
7729 case OPC_DSLL32:
7730 case OPC_DSRA32:
7731 case OPC_DSRL32:
7732 check_insn(env, ctx, ISA_MIPS3);
7733 check_mips_64(ctx);
7734 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7735 break;
7736 case OPC_DADD ... OPC_DSUBU:
7737 check_insn(env, ctx, ISA_MIPS3);
7738 check_mips_64(ctx);
7739 gen_arith(env, ctx, op1, rd, rs, rt);
7740 break;
7741 case OPC_DSLLV:
7742 case OPC_DSRAV:
7743 case OPC_DSRLV:
7744 check_insn(env, ctx, ISA_MIPS3);
7745 check_mips_64(ctx);
7746 gen_shift(env, ctx, op1, rd, rs, rt);
7747 break;
7748 case OPC_DMULT ... OPC_DDIVU:
7749 check_insn(env, ctx, ISA_MIPS3);
7750 check_mips_64(ctx);
7751 gen_muldiv(ctx, op1, rs, rt);
7752 break;
7753 #endif
7754 default: /* Invalid */
7755 MIPS_INVAL("special");
7756 generate_exception(ctx, EXCP_RI);
7757 break;
7759 break;
7760 case OPC_SPECIAL2:
7761 op1 = MASK_SPECIAL2(ctx->opcode);
7762 switch (op1) {
7763 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7764 case OPC_MSUB ... OPC_MSUBU:
7765 check_insn(env, ctx, ISA_MIPS32);
7766 gen_muldiv(ctx, op1, rs, rt);
7767 break;
7768 case OPC_MUL:
7769 gen_arith(env, ctx, op1, rd, rs, rt);
7770 break;
7771 case OPC_CLO:
7772 case OPC_CLZ:
7773 check_insn(env, ctx, ISA_MIPS32);
7774 gen_cl(ctx, op1, rd, rs);
7775 break;
7776 case OPC_SDBBP:
7777 /* XXX: not clear which exception should be raised
7778 * when in debug mode...
7780 check_insn(env, ctx, ISA_MIPS32);
7781 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7782 generate_exception(ctx, EXCP_DBp);
7783 } else {
7784 generate_exception(ctx, EXCP_DBp);
7786 /* Treat as NOP. */
7787 break;
7788 #if defined(TARGET_MIPS64)
7789 case OPC_DCLO:
7790 case OPC_DCLZ:
7791 check_insn(env, ctx, ISA_MIPS64);
7792 check_mips_64(ctx);
7793 gen_cl(ctx, op1, rd, rs);
7794 break;
7795 #endif
7796 default: /* Invalid */
7797 MIPS_INVAL("special2");
7798 generate_exception(ctx, EXCP_RI);
7799 break;
7801 break;
7802 case OPC_SPECIAL3:
7803 op1 = MASK_SPECIAL3(ctx->opcode);
7804 switch (op1) {
7805 case OPC_EXT:
7806 case OPC_INS:
7807 check_insn(env, ctx, ISA_MIPS32R2);
7808 gen_bitops(ctx, op1, rt, rs, sa, rd);
7809 break;
7810 case OPC_BSHFL:
7811 check_insn(env, ctx, ISA_MIPS32R2);
7812 op2 = MASK_BSHFL(ctx->opcode);
7813 gen_bshfl(ctx, op2, rt, rd);
7814 break;
7815 case OPC_RDHWR:
7816 check_insn(env, ctx, ISA_MIPS32R2);
7818 TCGv t0 = tcg_temp_new();
7820 switch (rd) {
7821 case 0:
7822 save_cpu_state(ctx, 1);
7823 gen_helper_rdhwr_cpunum(t0);
7824 gen_store_gpr(t0, rt);
7825 break;
7826 case 1:
7827 save_cpu_state(ctx, 1);
7828 gen_helper_rdhwr_synci_step(t0);
7829 gen_store_gpr(t0, rt);
7830 break;
7831 case 2:
7832 save_cpu_state(ctx, 1);
7833 gen_helper_rdhwr_cc(t0);
7834 gen_store_gpr(t0, rt);
7835 break;
7836 case 3:
7837 save_cpu_state(ctx, 1);
7838 gen_helper_rdhwr_ccres(t0);
7839 gen_store_gpr(t0, rt);
7840 break;
7841 case 29:
7842 #if defined(CONFIG_USER_ONLY)
7843 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7844 gen_store_gpr(t0, rt);
7845 break;
7846 #else
7847 /* XXX: Some CPUs implement this in hardware.
7848 Not supported yet. */
7849 #endif
7850 default: /* Invalid */
7851 MIPS_INVAL("rdhwr");
7852 generate_exception(ctx, EXCP_RI);
7853 break;
7855 tcg_temp_free(t0);
7857 break;
7858 case OPC_FORK:
7859 check_insn(env, ctx, ASE_MT);
7861 TCGv t0 = tcg_temp_new();
7862 TCGv t1 = tcg_temp_new();
7864 gen_load_gpr(t0, rt);
7865 gen_load_gpr(t1, rs);
7866 gen_helper_fork(t0, t1);
7867 tcg_temp_free(t0);
7868 tcg_temp_free(t1);
7870 break;
7871 case OPC_YIELD:
7872 check_insn(env, ctx, ASE_MT);
7874 TCGv t0 = tcg_temp_new();
7876 save_cpu_state(ctx, 1);
7877 gen_load_gpr(t0, rs);
7878 gen_helper_yield(t0, t0);
7879 gen_store_gpr(t0, rd);
7880 tcg_temp_free(t0);
7882 break;
7883 #if defined(TARGET_MIPS64)
7884 case OPC_DEXTM ... OPC_DEXT:
7885 case OPC_DINSM ... OPC_DINS:
7886 check_insn(env, ctx, ISA_MIPS64R2);
7887 check_mips_64(ctx);
7888 gen_bitops(ctx, op1, rt, rs, sa, rd);
7889 break;
7890 case OPC_DBSHFL:
7891 check_insn(env, ctx, ISA_MIPS64R2);
7892 check_mips_64(ctx);
7893 op2 = MASK_DBSHFL(ctx->opcode);
7894 gen_bshfl(ctx, op2, rt, rd);
7895 break;
7896 #endif
7897 default: /* Invalid */
7898 MIPS_INVAL("special3");
7899 generate_exception(ctx, EXCP_RI);
7900 break;
7902 break;
7903 case OPC_REGIMM:
7904 op1 = MASK_REGIMM(ctx->opcode);
7905 switch (op1) {
7906 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7907 case OPC_BLTZAL ... OPC_BGEZALL:
7908 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
7909 return;
7910 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7911 case OPC_TNEI:
7912 gen_trap(ctx, op1, rs, -1, imm);
7913 break;
7914 case OPC_SYNCI:
7915 check_insn(env, ctx, ISA_MIPS32R2);
7916 /* Treat as NOP. */
7917 break;
7918 default: /* Invalid */
7919 MIPS_INVAL("regimm");
7920 generate_exception(ctx, EXCP_RI);
7921 break;
7923 break;
7924 case OPC_CP0:
7925 check_cp0_enabled(ctx);
7926 op1 = MASK_CP0(ctx->opcode);
7927 switch (op1) {
7928 case OPC_MFC0:
7929 case OPC_MTC0:
7930 case OPC_MFTR:
7931 case OPC_MTTR:
7932 #if defined(TARGET_MIPS64)
7933 case OPC_DMFC0:
7934 case OPC_DMTC0:
7935 #endif
7936 #ifndef CONFIG_USER_ONLY
7937 gen_cp0(env, ctx, op1, rt, rd);
7938 #endif /* !CONFIG_USER_ONLY */
7939 break;
7940 case OPC_C0_FIRST ... OPC_C0_LAST:
7941 #ifndef CONFIG_USER_ONLY
7942 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
7943 #endif /* !CONFIG_USER_ONLY */
7944 break;
7945 case OPC_MFMC0:
7946 #ifndef CONFIG_USER_ONLY
7948 TCGv t0 = tcg_temp_new();
7950 op2 = MASK_MFMC0(ctx->opcode);
7951 switch (op2) {
7952 case OPC_DMT:
7953 check_insn(env, ctx, ASE_MT);
7954 gen_helper_dmt(t0, t0);
7955 gen_store_gpr(t0, rt);
7956 break;
7957 case OPC_EMT:
7958 check_insn(env, ctx, ASE_MT);
7959 gen_helper_emt(t0, t0);
7960 gen_store_gpr(t0, rt);
7961 break;
7962 case OPC_DVPE:
7963 check_insn(env, ctx, ASE_MT);
7964 gen_helper_dvpe(t0, t0);
7965 gen_store_gpr(t0, rt);
7966 break;
7967 case OPC_EVPE:
7968 check_insn(env, ctx, ASE_MT);
7969 gen_helper_evpe(t0, t0);
7970 gen_store_gpr(t0, rt);
7971 break;
7972 case OPC_DI:
7973 check_insn(env, ctx, ISA_MIPS32R2);
7974 save_cpu_state(ctx, 1);
7975 gen_helper_di(t0);
7976 gen_store_gpr(t0, rt);
7977 /* Stop translation as we may have switched the execution mode */
7978 ctx->bstate = BS_STOP;
7979 break;
7980 case OPC_EI:
7981 check_insn(env, ctx, ISA_MIPS32R2);
7982 save_cpu_state(ctx, 1);
7983 gen_helper_ei(t0);
7984 gen_store_gpr(t0, rt);
7985 /* Stop translation as we may have switched the execution mode */
7986 ctx->bstate = BS_STOP;
7987 break;
7988 default: /* Invalid */
7989 MIPS_INVAL("mfmc0");
7990 generate_exception(ctx, EXCP_RI);
7991 break;
7993 tcg_temp_free(t0);
7995 #endif /* !CONFIG_USER_ONLY */
7996 break;
7997 case OPC_RDPGPR:
7998 check_insn(env, ctx, ISA_MIPS32R2);
7999 gen_load_srsgpr(rt, rd);
8000 break;
8001 case OPC_WRPGPR:
8002 check_insn(env, ctx, ISA_MIPS32R2);
8003 gen_store_srsgpr(rt, rd);
8004 break;
8005 default:
8006 MIPS_INVAL("cp0");
8007 generate_exception(ctx, EXCP_RI);
8008 break;
8010 break;
8011 case OPC_ADDI: /* Arithmetic with immediate opcode */
8012 case OPC_ADDIU:
8013 gen_arith_imm(env, ctx, op, rt, rs, imm);
8014 break;
8015 case OPC_SLTI: /* Set on less than with immediate opcode */
8016 case OPC_SLTIU:
8017 gen_slt_imm(env, op, rt, rs, imm);
8018 break;
8019 case OPC_ANDI: /* Arithmetic with immediate opcode */
8020 case OPC_LUI:
8021 case OPC_ORI:
8022 case OPC_XORI:
8023 gen_logic_imm(env, op, rt, rs, imm);
8024 break;
8025 case OPC_J ... OPC_JAL: /* Jump */
8026 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8027 gen_compute_branch(ctx, op, rs, rt, offset);
8028 return;
8029 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8030 case OPC_BEQL ... OPC_BGTZL:
8031 gen_compute_branch(ctx, op, rs, rt, imm << 2);
8032 return;
8033 case OPC_LB ... OPC_LWR: /* Load and stores */
8034 case OPC_SB ... OPC_SW:
8035 case OPC_SWR:
8036 case OPC_LL:
8037 gen_ldst(ctx, op, rt, rs, imm);
8038 break;
8039 case OPC_SC:
8040 gen_st_cond(ctx, op, rt, rs, imm);
8041 break;
8042 case OPC_CACHE:
8043 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
8044 /* Treat as NOP. */
8045 break;
8046 case OPC_PREF:
8047 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8048 /* Treat as NOP. */
8049 break;
8051 /* Floating point (COP1). */
8052 case OPC_LWC1:
8053 case OPC_LDC1:
8054 case OPC_SWC1:
8055 case OPC_SDC1:
8056 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8057 check_cp1_enabled(ctx);
8058 gen_flt_ldst(ctx, op, rt, rs, imm);
8059 } else {
8060 generate_exception_err(ctx, EXCP_CpU, 1);
8062 break;
8064 case OPC_CP1:
8065 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8066 check_cp1_enabled(ctx);
8067 op1 = MASK_CP1(ctx->opcode);
8068 switch (op1) {
8069 case OPC_MFHC1:
8070 case OPC_MTHC1:
8071 check_insn(env, ctx, ISA_MIPS32R2);
8072 case OPC_MFC1:
8073 case OPC_CFC1:
8074 case OPC_MTC1:
8075 case OPC_CTC1:
8076 gen_cp1(ctx, op1, rt, rd);
8077 break;
8078 #if defined(TARGET_MIPS64)
8079 case OPC_DMFC1:
8080 case OPC_DMTC1:
8081 check_insn(env, ctx, ISA_MIPS3);
8082 gen_cp1(ctx, op1, rt, rd);
8083 break;
8084 #endif
8085 case OPC_BC1ANY2:
8086 case OPC_BC1ANY4:
8087 check_cop1x(ctx);
8088 check_insn(env, ctx, ASE_MIPS3D);
8089 /* fall through */
8090 case OPC_BC1:
8091 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8092 (rt >> 2) & 0x7, imm << 2);
8093 return;
8094 case OPC_S_FMT:
8095 case OPC_D_FMT:
8096 case OPC_W_FMT:
8097 case OPC_L_FMT:
8098 case OPC_PS_FMT:
8099 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8100 (imm >> 8) & 0x7);
8101 break;
8102 default:
8103 MIPS_INVAL("cp1");
8104 generate_exception (ctx, EXCP_RI);
8105 break;
8107 } else {
8108 generate_exception_err(ctx, EXCP_CpU, 1);
8110 break;
8112 /* COP2. */
8113 case OPC_LWC2:
8114 case OPC_LDC2:
8115 case OPC_SWC2:
8116 case OPC_SDC2:
8117 case OPC_CP2:
8118 /* COP2: Not implemented. */
8119 generate_exception_err(ctx, EXCP_CpU, 2);
8120 break;
8122 case OPC_CP3:
8123 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8124 check_cp1_enabled(ctx);
8125 op1 = MASK_CP3(ctx->opcode);
8126 switch (op1) {
8127 case OPC_LWXC1:
8128 case OPC_LDXC1:
8129 case OPC_LUXC1:
8130 case OPC_SWXC1:
8131 case OPC_SDXC1:
8132 case OPC_SUXC1:
8133 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8134 break;
8135 case OPC_PREFX:
8136 /* Treat as NOP. */
8137 break;
8138 case OPC_ALNV_PS:
8139 case OPC_MADD_S:
8140 case OPC_MADD_D:
8141 case OPC_MADD_PS:
8142 case OPC_MSUB_S:
8143 case OPC_MSUB_D:
8144 case OPC_MSUB_PS:
8145 case OPC_NMADD_S:
8146 case OPC_NMADD_D:
8147 case OPC_NMADD_PS:
8148 case OPC_NMSUB_S:
8149 case OPC_NMSUB_D:
8150 case OPC_NMSUB_PS:
8151 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8152 break;
8153 default:
8154 MIPS_INVAL("cp3");
8155 generate_exception (ctx, EXCP_RI);
8156 break;
8158 } else {
8159 generate_exception_err(ctx, EXCP_CpU, 1);
8161 break;
8163 #if defined(TARGET_MIPS64)
8164 /* MIPS64 opcodes */
8165 case OPC_LWU:
8166 case OPC_LDL ... OPC_LDR:
8167 case OPC_SDL ... OPC_SDR:
8168 case OPC_LLD:
8169 case OPC_LD:
8170 case OPC_SD:
8171 check_insn(env, ctx, ISA_MIPS3);
8172 check_mips_64(ctx);
8173 gen_ldst(ctx, op, rt, rs, imm);
8174 break;
8175 case OPC_SCD:
8176 check_insn(env, ctx, ISA_MIPS3);
8177 check_mips_64(ctx);
8178 gen_st_cond(ctx, op, rt, rs, imm);
8179 break;
8180 case OPC_DADDI:
8181 case OPC_DADDIU:
8182 check_insn(env, ctx, ISA_MIPS3);
8183 check_mips_64(ctx);
8184 gen_arith_imm(env, ctx, op, rt, rs, imm);
8185 break;
8186 #endif
8187 case OPC_JALX:
8188 check_insn(env, ctx, ASE_MIPS16);
8189 /* MIPS16: Not implemented. */
8190 case OPC_MDMX:
8191 check_insn(env, ctx, ASE_MDMX);
8192 /* MDMX: Not implemented. */
8193 default: /* Invalid */
8194 MIPS_INVAL("major opcode");
8195 generate_exception(ctx, EXCP_RI);
8196 break;
8198 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8199 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8200 /* Branches completion */
8201 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8202 ctx->bstate = BS_BRANCH;
8203 save_cpu_state(ctx, 0);
8204 /* FIXME: Need to clear can_do_io. */
8205 switch (hflags) {
8206 case MIPS_HFLAG_B:
8207 /* unconditional branch */
8208 MIPS_DEBUG("unconditional branch");
8209 gen_goto_tb(ctx, 0, ctx->btarget);
8210 break;
8211 case MIPS_HFLAG_BL:
8212 /* blikely taken case */
8213 MIPS_DEBUG("blikely branch taken");
8214 gen_goto_tb(ctx, 0, ctx->btarget);
8215 break;
8216 case MIPS_HFLAG_BC:
8217 /* Conditional branch */
8218 MIPS_DEBUG("conditional branch");
8220 int l1 = gen_new_label();
8222 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8223 gen_goto_tb(ctx, 1, ctx->pc + 4);
8224 gen_set_label(l1);
8225 gen_goto_tb(ctx, 0, ctx->btarget);
8227 break;
8228 case MIPS_HFLAG_BR:
8229 /* unconditional branch to register */
8230 MIPS_DEBUG("branch to register");
8231 tcg_gen_mov_tl(cpu_PC, btarget);
8232 tcg_gen_exit_tb(0);
8233 break;
8234 default:
8235 MIPS_DEBUG("unknown branch");
8236 break;
8241 static inline void
8242 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8243 int search_pc)
8245 DisasContext ctx;
8246 target_ulong pc_start;
8247 uint16_t *gen_opc_end;
8248 CPUBreakpoint *bp;
8249 int j, lj = -1;
8250 int num_insns;
8251 int max_insns;
8253 if (search_pc)
8254 qemu_log("search pc %d\n", search_pc);
8256 pc_start = tb->pc;
8257 /* Leave some spare opc slots for branch handling. */
8258 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
8259 ctx.pc = pc_start;
8260 ctx.saved_pc = -1;
8261 ctx.tb = tb;
8262 ctx.bstate = BS_NONE;
8263 /* Restore delay slot state from the tb context. */
8264 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8265 restore_cpu_state(env, &ctx);
8266 #ifdef CONFIG_USER_ONLY
8267 ctx.mem_idx = MIPS_HFLAG_UM;
8268 #else
8269 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8270 #endif
8271 num_insns = 0;
8272 max_insns = tb->cflags & CF_COUNT_MASK;
8273 if (max_insns == 0)
8274 max_insns = CF_COUNT_MASK;
8275 #ifdef DEBUG_DISAS
8276 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
8277 /* FIXME: This may print out stale hflags from env... */
8278 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
8279 #endif
8280 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
8281 gen_icount_start();
8282 while (ctx.bstate == BS_NONE) {
8283 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8284 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8285 if (bp->pc == ctx.pc) {
8286 save_cpu_state(&ctx, 1);
8287 ctx.bstate = BS_BRANCH;
8288 gen_helper_0i(raise_exception, EXCP_DEBUG);
8289 /* Include the breakpoint location or the tb won't
8290 * be flushed when it must be. */
8291 ctx.pc += 4;
8292 goto done_generating;
8297 if (search_pc) {
8298 j = gen_opc_ptr - gen_opc_buf;
8299 if (lj < j) {
8300 lj++;
8301 while (lj < j)
8302 gen_opc_instr_start[lj++] = 0;
8304 gen_opc_pc[lj] = ctx.pc;
8305 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8306 gen_opc_instr_start[lj] = 1;
8307 gen_opc_icount[lj] = num_insns;
8309 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8310 gen_io_start();
8311 ctx.opcode = ldl_code(ctx.pc);
8312 decode_opc(env, &ctx);
8313 ctx.pc += 4;
8314 num_insns++;
8316 if (env->singlestep_enabled)
8317 break;
8319 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8320 break;
8322 if (gen_opc_ptr >= gen_opc_end)
8323 break;
8325 if (num_insns >= max_insns)
8326 break;
8328 if (singlestep)
8329 break;
8331 if (tb->cflags & CF_LAST_IO)
8332 gen_io_end();
8333 if (env->singlestep_enabled) {
8334 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
8335 gen_helper_0i(raise_exception, EXCP_DEBUG);
8336 } else {
8337 switch (ctx.bstate) {
8338 case BS_STOP:
8339 gen_helper_interrupt_restart();
8340 gen_goto_tb(&ctx, 0, ctx.pc);
8341 break;
8342 case BS_NONE:
8343 save_cpu_state(&ctx, 0);
8344 gen_goto_tb(&ctx, 0, ctx.pc);
8345 break;
8346 case BS_EXCP:
8347 gen_helper_interrupt_restart();
8348 tcg_gen_exit_tb(0);
8349 break;
8350 case BS_BRANCH:
8351 default:
8352 break;
8355 done_generating:
8356 gen_icount_end(tb, num_insns);
8357 *gen_opc_ptr = INDEX_op_end;
8358 if (search_pc) {
8359 j = gen_opc_ptr - gen_opc_buf;
8360 lj++;
8361 while (lj <= j)
8362 gen_opc_instr_start[lj++] = 0;
8363 } else {
8364 tb->size = ctx.pc - pc_start;
8365 tb->icount = num_insns;
8367 #ifdef DEBUG_DISAS
8368 LOG_DISAS("\n");
8369 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8370 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8371 log_target_disas(pc_start, ctx.pc - pc_start, 0);
8372 qemu_log("\n");
8374 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8375 #endif
8378 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8380 gen_intermediate_code_internal(env, tb, 0);
8383 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8385 gen_intermediate_code_internal(env, tb, 1);
8388 static void fpu_dump_state(CPUState *env, FILE *f,
8389 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8390 int flags)
8392 int i;
8393 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8395 #define printfpr(fp) \
8396 do { \
8397 if (is_fpu64) \
8398 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8399 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8400 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8401 else { \
8402 fpr_t tmp; \
8403 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8404 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8405 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8406 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8407 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8409 } while(0)
8412 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8413 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8414 get_float_exception_flags(&env->active_fpu.fp_status));
8415 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8416 fpu_fprintf(f, "%3s: ", fregnames[i]);
8417 printfpr(&env->active_fpu.fpr[i]);
8420 #undef printfpr
8423 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8424 /* Debug help: The architecture requires 32bit code to maintain proper
8425 sign-extended values on 64bit machines. */
8427 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8429 static void
8430 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8431 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8432 int flags)
8434 int i;
8436 if (!SIGN_EXT_P(env->active_tc.PC))
8437 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8438 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8439 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8440 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8441 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8442 if (!SIGN_EXT_P(env->btarget))
8443 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8445 for (i = 0; i < 32; i++) {
8446 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8447 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8450 if (!SIGN_EXT_P(env->CP0_EPC))
8451 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8452 if (!SIGN_EXT_P(env->CP0_LLAddr))
8453 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
8455 #endif
8457 void cpu_dump_state (CPUState *env, FILE *f,
8458 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8459 int flags)
8461 int i;
8463 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",
8464 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8465 env->hflags, env->btarget, env->bcond);
8466 for (i = 0; i < 32; i++) {
8467 if ((i & 3) == 0)
8468 cpu_fprintf(f, "GPR%02d:", i);
8469 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8470 if ((i & 3) == 3)
8471 cpu_fprintf(f, "\n");
8474 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8475 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8476 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8477 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
8478 if (env->hflags & MIPS_HFLAG_FPU)
8479 fpu_dump_state(env, f, cpu_fprintf, flags);
8480 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8481 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8482 #endif
8485 static void mips_tcg_init(void)
8487 int i;
8488 static int inited;
8490 /* Initialize various static tables. */
8491 if (inited)
8492 return;
8494 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8495 TCGV_UNUSED(cpu_gpr[0]);
8496 for (i = 1; i < 32; i++)
8497 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
8498 offsetof(CPUState, active_tc.gpr[i]),
8499 regnames[i]);
8500 cpu_PC = tcg_global_mem_new(TCG_AREG0,
8501 offsetof(CPUState, active_tc.PC), "PC");
8502 for (i = 0; i < MIPS_DSP_ACC; i++) {
8503 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
8504 offsetof(CPUState, active_tc.HI[i]),
8505 regnames_HI[i]);
8506 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
8507 offsetof(CPUState, active_tc.LO[i]),
8508 regnames_LO[i]);
8509 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
8510 offsetof(CPUState, active_tc.ACX[i]),
8511 regnames_ACX[i]);
8513 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
8514 offsetof(CPUState, active_tc.DSPControl),
8515 "DSPControl");
8516 bcond = tcg_global_mem_new(TCG_AREG0,
8517 offsetof(CPUState, bcond), "bcond");
8518 btarget = tcg_global_mem_new(TCG_AREG0,
8519 offsetof(CPUState, btarget), "btarget");
8520 hflags = tcg_global_mem_new_i32(TCG_AREG0,
8521 offsetof(CPUState, hflags), "hflags");
8523 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
8524 offsetof(CPUState, active_fpu.fcr0),
8525 "fcr0");
8526 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
8527 offsetof(CPUState, active_fpu.fcr31),
8528 "fcr31");
8530 /* register helpers */
8531 #define GEN_HELPER 2
8532 #include "helper.h"
8534 inited = 1;
8537 #include "translate_init.c"
8539 CPUMIPSState *cpu_mips_init (const char *cpu_model)
8541 CPUMIPSState *env;
8542 const mips_def_t *def;
8544 def = cpu_mips_find_by_name(cpu_model);
8545 if (!def)
8546 return NULL;
8547 env = qemu_mallocz(sizeof(CPUMIPSState));
8548 env->cpu_model = def;
8550 cpu_exec_init(env);
8551 env->cpu_model_str = cpu_model;
8552 mips_tcg_init();
8553 cpu_reset(env);
8554 qemu_init_vcpu(env);
8555 return env;
8558 void cpu_reset (CPUMIPSState *env)
8560 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
8561 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
8562 log_cpu_state(env, 0);
8565 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8567 tlb_flush(env, 1);
8569 /* Minimal init */
8570 #if defined(CONFIG_USER_ONLY)
8571 env->hflags = MIPS_HFLAG_UM;
8572 /* Enable access to the SYNCI_Step register. */
8573 env->CP0_HWREna |= (1 << 1);
8574 #else
8575 if (env->hflags & MIPS_HFLAG_BMASK) {
8576 /* If the exception was raised from a delay slot,
8577 come back to the jump. */
8578 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8579 } else {
8580 env->CP0_ErrorEPC = env->active_tc.PC;
8582 env->active_tc.PC = (int32_t)0xBFC00000;
8583 env->CP0_Wired = 0;
8584 /* SMP not implemented */
8585 env->CP0_EBase = 0x80000000;
8586 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8587 /* vectored interrupts not implemented, timer on int 7,
8588 no performance counters. */
8589 env->CP0_IntCtl = 0xe0000000;
8591 int i;
8593 for (i = 0; i < 7; i++) {
8594 env->CP0_WatchLo[i] = 0;
8595 env->CP0_WatchHi[i] = 0x80000000;
8597 env->CP0_WatchLo[7] = 0;
8598 env->CP0_WatchHi[7] = 0;
8600 /* Count register increments in debug mode, EJTAG version 1 */
8601 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8602 env->hflags = MIPS_HFLAG_CP0;
8603 #endif
8604 env->exception_index = EXCP_NONE;
8605 cpu_mips_register(env, env->cpu_model);
8608 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8609 unsigned long searched_pc, int pc_pos, void *puc)
8611 env->active_tc.PC = gen_opc_pc[pc_pos];
8612 env->hflags &= ~MIPS_HFLAG_BMASK;
8613 env->hflags |= gen_opc_hflags[pc_pos];