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