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