vga optimization (Glauber Costa)
[qemu/qemu-JZ.git] / target-mips / translate.c
blobcc7e71c5750a3ab50b642b27dd88d5e47d4429c7
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 gen_load_gpr(t0, base);
992 tcg_gen_movi_tl(t1, offset);
993 gen_op_addr_add(ctx, t0, t1);
995 /* Don't do NOP if destination is zero: we must perform the actual
996 memory access. */
997 switch (opc) {
998 #if defined(TARGET_MIPS64)
999 case OPC_LWU:
1000 op_ldst_lwu(t0, ctx);
1001 gen_store_gpr(t0, rt);
1002 opn = "lwu";
1003 break;
1004 case OPC_LD:
1005 op_ldst_ld(t0, ctx);
1006 gen_store_gpr(t0, rt);
1007 opn = "ld";
1008 break;
1009 case OPC_LLD:
1010 op_ldst_lld(t0, t1, ctx);
1011 gen_store_gpr(t0, rt);
1012 opn = "lld";
1013 break;
1014 case OPC_SD:
1015 gen_load_gpr(t1, rt);
1016 op_ldst_sd(t0, t1, ctx);
1017 opn = "sd";
1018 break;
1019 case OPC_SCD:
1020 save_cpu_state(ctx, 1);
1021 gen_load_gpr(t1, rt);
1022 op_ldst_scd(t0, t1, ctx);
1023 gen_store_gpr(t0, rt);
1024 opn = "scd";
1025 break;
1026 case OPC_LDL:
1027 save_cpu_state(ctx, 1);
1028 gen_load_gpr(t1, rt);
1029 gen_helper_3i(ldl, t1, t0, t1, ctx->mem_idx);
1030 gen_store_gpr(t1, rt);
1031 opn = "ldl";
1032 break;
1033 case OPC_SDL:
1034 save_cpu_state(ctx, 1);
1035 gen_load_gpr(t1, rt);
1036 gen_helper_2i(sdl, t0, t1, ctx->mem_idx);
1037 opn = "sdl";
1038 break;
1039 case OPC_LDR:
1040 save_cpu_state(ctx, 1);
1041 gen_load_gpr(t1, rt);
1042 gen_helper_3i(ldr, t1, t0, t1, ctx->mem_idx);
1043 gen_store_gpr(t1, rt);
1044 opn = "ldr";
1045 break;
1046 case OPC_SDR:
1047 save_cpu_state(ctx, 1);
1048 gen_load_gpr(t1, rt);
1049 gen_helper_2i(sdr, t0, t1, ctx->mem_idx);
1050 opn = "sdr";
1051 break;
1052 #endif
1053 case OPC_LW:
1054 op_ldst_lw(t0, ctx);
1055 gen_store_gpr(t0, rt);
1056 opn = "lw";
1057 break;
1058 case OPC_SW:
1059 gen_load_gpr(t1, rt);
1060 op_ldst_sw(t0, t1, ctx);
1061 opn = "sw";
1062 break;
1063 case OPC_LH:
1064 op_ldst_lh(t0, ctx);
1065 gen_store_gpr(t0, rt);
1066 opn = "lh";
1067 break;
1068 case OPC_SH:
1069 gen_load_gpr(t1, rt);
1070 op_ldst_sh(t0, t1, ctx);
1071 opn = "sh";
1072 break;
1073 case OPC_LHU:
1074 op_ldst_lhu(t0, ctx);
1075 gen_store_gpr(t0, rt);
1076 opn = "lhu";
1077 break;
1078 case OPC_LB:
1079 op_ldst_lb(t0, ctx);
1080 gen_store_gpr(t0, rt);
1081 opn = "lb";
1082 break;
1083 case OPC_SB:
1084 gen_load_gpr(t1, rt);
1085 op_ldst_sb(t0, t1, ctx);
1086 opn = "sb";
1087 break;
1088 case OPC_LBU:
1089 op_ldst_lbu(t0, ctx);
1090 gen_store_gpr(t0, rt);
1091 opn = "lbu";
1092 break;
1093 case OPC_LWL:
1094 save_cpu_state(ctx, 1);
1095 gen_load_gpr(t1, rt);
1096 gen_helper_3i(lwl, t1, t0, t1, ctx->mem_idx);
1097 gen_store_gpr(t1, rt);
1098 opn = "lwl";
1099 break;
1100 case OPC_SWL:
1101 save_cpu_state(ctx, 1);
1102 gen_load_gpr(t1, rt);
1103 gen_helper_2i(swl, t0, t1, ctx->mem_idx);
1104 opn = "swr";
1105 break;
1106 case OPC_LWR:
1107 save_cpu_state(ctx, 1);
1108 gen_load_gpr(t1, rt);
1109 gen_helper_3i(lwr, t1, t0, t1, ctx->mem_idx);
1110 gen_store_gpr(t1, rt);
1111 opn = "lwr";
1112 break;
1113 case OPC_SWR:
1114 save_cpu_state(ctx, 1);
1115 gen_load_gpr(t1, rt);
1116 gen_helper_2i(swr, t0, t1, ctx->mem_idx);
1117 opn = "swr";
1118 break;
1119 case OPC_LL:
1120 op_ldst_ll(t0, t1, ctx);
1121 gen_store_gpr(t0, rt);
1122 opn = "ll";
1123 break;
1124 case OPC_SC:
1125 save_cpu_state(ctx, 1);
1126 gen_load_gpr(t1, rt);
1127 op_ldst_sc(t0, t1, ctx);
1128 gen_store_gpr(t0, rt);
1129 opn = "sc";
1130 break;
1131 default:
1132 MIPS_INVAL(opn);
1133 generate_exception(ctx, EXCP_RI);
1134 goto out;
1136 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1137 out:
1138 tcg_temp_free(t0);
1139 tcg_temp_free(t1);
1142 /* Load and store */
1143 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1144 int base, int16_t offset)
1146 const char *opn = "flt_ldst";
1147 TCGv t0 = tcg_temp_local_new();
1149 if (base == 0) {
1150 tcg_gen_movi_tl(t0, offset);
1151 } else if (offset == 0) {
1152 gen_load_gpr(t0, base);
1153 } else {
1154 TCGv t1 = tcg_temp_local_new();
1156 gen_load_gpr(t0, base);
1157 tcg_gen_movi_tl(t1, offset);
1158 gen_op_addr_add(ctx, t0, t1);
1159 tcg_temp_free(t1);
1161 /* Don't do NOP if destination is zero: we must perform the actual
1162 memory access. */
1163 switch (opc) {
1164 case OPC_LWC1:
1166 TCGv_i32 fp0 = tcg_temp_new_i32();
1167 TCGv t1 = tcg_temp_new();
1169 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
1170 tcg_gen_trunc_tl_i32(fp0, t1);
1171 gen_store_fpr32(fp0, ft);
1172 tcg_temp_free(t1);
1173 tcg_temp_free_i32(fp0);
1175 opn = "lwc1";
1176 break;
1177 case OPC_SWC1:
1179 TCGv_i32 fp0 = tcg_temp_new_i32();
1180 TCGv t1 = tcg_temp_new();
1182 gen_load_fpr32(fp0, ft);
1183 tcg_gen_extu_i32_tl(t1, fp0);
1184 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1185 tcg_temp_free(t1);
1186 tcg_temp_free_i32(fp0);
1188 opn = "swc1";
1189 break;
1190 case OPC_LDC1:
1192 TCGv_i64 fp0 = tcg_temp_new_i64();
1194 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1195 gen_store_fpr64(ctx, fp0, ft);
1196 tcg_temp_free_i64(fp0);
1198 opn = "ldc1";
1199 break;
1200 case OPC_SDC1:
1202 TCGv_i64 fp0 = tcg_temp_new_i64();
1204 gen_load_fpr64(ctx, fp0, ft);
1205 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1206 tcg_temp_free_i64(fp0);
1208 opn = "sdc1";
1209 break;
1210 default:
1211 MIPS_INVAL(opn);
1212 generate_exception(ctx, EXCP_RI);
1213 goto out;
1215 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1216 out:
1217 tcg_temp_free(t0);
1220 /* Arithmetic with immediate operand */
1221 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1222 int rt, int rs, int16_t imm)
1224 target_ulong uimm;
1225 const char *opn = "imm arith";
1226 TCGv t0 = tcg_temp_local_new();
1228 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1229 /* If no destination, treat it as a NOP.
1230 For addi, we must generate the overflow exception when needed. */
1231 MIPS_DEBUG("NOP");
1232 goto out;
1234 uimm = (uint16_t)imm;
1235 switch (opc) {
1236 case OPC_ADDI:
1237 case OPC_ADDIU:
1238 #if defined(TARGET_MIPS64)
1239 case OPC_DADDI:
1240 case OPC_DADDIU:
1241 #endif
1242 case OPC_SLTI:
1243 case OPC_SLTIU:
1244 uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1245 /* Fall through. */
1246 case OPC_ANDI:
1247 case OPC_ORI:
1248 case OPC_XORI:
1249 gen_load_gpr(t0, rs);
1250 break;
1251 case OPC_LUI:
1252 tcg_gen_movi_tl(t0, imm << 16);
1253 break;
1254 case OPC_SLL:
1255 case OPC_SRA:
1256 case OPC_SRL:
1257 #if defined(TARGET_MIPS64)
1258 case OPC_DSLL:
1259 case OPC_DSRA:
1260 case OPC_DSRL:
1261 case OPC_DSLL32:
1262 case OPC_DSRA32:
1263 case OPC_DSRL32:
1264 #endif
1265 uimm &= 0x1f;
1266 gen_load_gpr(t0, rs);
1267 break;
1269 switch (opc) {
1270 case OPC_ADDI:
1272 TCGv r_tmp1 = tcg_temp_new();
1273 TCGv r_tmp2 = tcg_temp_new();
1274 int l1 = gen_new_label();
1276 save_cpu_state(ctx, 1);
1277 tcg_gen_ext32s_tl(r_tmp1, t0);
1278 tcg_gen_addi_tl(t0, r_tmp1, uimm);
1280 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
1281 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1282 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1283 tcg_temp_free(r_tmp2);
1284 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1285 /* operands of same sign, result different sign */
1286 generate_exception(ctx, EXCP_OVERFLOW);
1287 gen_set_label(l1);
1288 tcg_temp_free(r_tmp1);
1290 tcg_gen_ext32s_tl(t0, t0);
1292 opn = "addi";
1293 break;
1294 case OPC_ADDIU:
1295 tcg_gen_addi_tl(t0, t0, uimm);
1296 tcg_gen_ext32s_tl(t0, t0);
1297 opn = "addiu";
1298 break;
1299 #if defined(TARGET_MIPS64)
1300 case OPC_DADDI:
1302 TCGv r_tmp1 = tcg_temp_new();
1303 TCGv r_tmp2 = tcg_temp_new();
1304 int l1 = gen_new_label();
1306 save_cpu_state(ctx, 1);
1307 tcg_gen_mov_tl(r_tmp1, t0);
1308 tcg_gen_addi_tl(t0, t0, uimm);
1310 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
1311 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1312 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1313 tcg_temp_free(r_tmp2);
1314 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1315 /* operands of same sign, result different sign */
1316 generate_exception(ctx, EXCP_OVERFLOW);
1317 gen_set_label(l1);
1318 tcg_temp_free(r_tmp1);
1320 opn = "daddi";
1321 break;
1322 case OPC_DADDIU:
1323 tcg_gen_addi_tl(t0, t0, uimm);
1324 opn = "daddiu";
1325 break;
1326 #endif
1327 case OPC_SLTI:
1328 gen_op_lti(t0, uimm);
1329 opn = "slti";
1330 break;
1331 case OPC_SLTIU:
1332 gen_op_ltiu(t0, uimm);
1333 opn = "sltiu";
1334 break;
1335 case OPC_ANDI:
1336 tcg_gen_andi_tl(t0, t0, uimm);
1337 opn = "andi";
1338 break;
1339 case OPC_ORI:
1340 tcg_gen_ori_tl(t0, t0, uimm);
1341 opn = "ori";
1342 break;
1343 case OPC_XORI:
1344 tcg_gen_xori_tl(t0, t0, uimm);
1345 opn = "xori";
1346 break;
1347 case OPC_LUI:
1348 opn = "lui";
1349 break;
1350 case OPC_SLL:
1351 tcg_gen_shli_tl(t0, t0, uimm);
1352 tcg_gen_ext32s_tl(t0, t0);
1353 opn = "sll";
1354 break;
1355 case OPC_SRA:
1356 tcg_gen_ext32s_tl(t0, t0);
1357 tcg_gen_sari_tl(t0, t0, uimm);
1358 opn = "sra";
1359 break;
1360 case OPC_SRL:
1361 switch ((ctx->opcode >> 21) & 0x1f) {
1362 case 0:
1363 if (uimm != 0) {
1364 tcg_gen_ext32u_tl(t0, t0);
1365 tcg_gen_shri_tl(t0, t0, uimm);
1366 } else {
1367 tcg_gen_ext32s_tl(t0, t0);
1369 opn = "srl";
1370 break;
1371 case 1:
1372 /* rotr is decoded as srl on non-R2 CPUs */
1373 if (env->insn_flags & ISA_MIPS32R2) {
1374 if (uimm != 0) {
1375 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
1377 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1378 tcg_gen_rotri_i32(r_tmp1, r_tmp1, uimm);
1379 tcg_gen_ext_i32_tl(t0, r_tmp1);
1380 tcg_temp_free_i32(r_tmp1);
1382 opn = "rotr";
1383 } else {
1384 if (uimm != 0) {
1385 tcg_gen_ext32u_tl(t0, t0);
1386 tcg_gen_shri_tl(t0, t0, uimm);
1387 } else {
1388 tcg_gen_ext32s_tl(t0, t0);
1390 opn = "srl";
1392 break;
1393 default:
1394 MIPS_INVAL("invalid srl flag");
1395 generate_exception(ctx, EXCP_RI);
1396 break;
1398 break;
1399 #if defined(TARGET_MIPS64)
1400 case OPC_DSLL:
1401 tcg_gen_shli_tl(t0, t0, uimm);
1402 opn = "dsll";
1403 break;
1404 case OPC_DSRA:
1405 tcg_gen_sari_tl(t0, t0, uimm);
1406 opn = "dsra";
1407 break;
1408 case OPC_DSRL:
1409 switch ((ctx->opcode >> 21) & 0x1f) {
1410 case 0:
1411 tcg_gen_shri_tl(t0, t0, uimm);
1412 opn = "dsrl";
1413 break;
1414 case 1:
1415 /* drotr is decoded as dsrl on non-R2 CPUs */
1416 if (env->insn_flags & ISA_MIPS32R2) {
1417 if (uimm != 0) {
1418 tcg_gen_rotri_tl(t0, t0, uimm);
1420 opn = "drotr";
1421 } else {
1422 tcg_gen_shri_tl(t0, t0, uimm);
1423 opn = "dsrl";
1425 break;
1426 default:
1427 MIPS_INVAL("invalid dsrl flag");
1428 generate_exception(ctx, EXCP_RI);
1429 break;
1431 break;
1432 case OPC_DSLL32:
1433 tcg_gen_shli_tl(t0, t0, uimm + 32);
1434 opn = "dsll32";
1435 break;
1436 case OPC_DSRA32:
1437 tcg_gen_sari_tl(t0, t0, uimm + 32);
1438 opn = "dsra32";
1439 break;
1440 case OPC_DSRL32:
1441 switch ((ctx->opcode >> 21) & 0x1f) {
1442 case 0:
1443 tcg_gen_shri_tl(t0, t0, uimm + 32);
1444 opn = "dsrl32";
1445 break;
1446 case 1:
1447 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1448 if (env->insn_flags & ISA_MIPS32R2) {
1449 tcg_gen_rotri_tl(t0, t0, uimm + 32);
1450 opn = "drotr32";
1451 } else {
1452 tcg_gen_shri_tl(t0, t0, uimm + 32);
1453 opn = "dsrl32";
1455 break;
1456 default:
1457 MIPS_INVAL("invalid dsrl32 flag");
1458 generate_exception(ctx, EXCP_RI);
1459 break;
1461 break;
1462 #endif
1463 default:
1464 MIPS_INVAL(opn);
1465 generate_exception(ctx, EXCP_RI);
1466 goto out;
1468 gen_store_gpr(t0, rt);
1469 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1470 out:
1471 tcg_temp_free(t0);
1474 /* Arithmetic */
1475 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1476 int rd, int rs, int rt)
1478 const char *opn = "arith";
1479 TCGv t0 = tcg_temp_local_new();
1480 TCGv t1 = tcg_temp_local_new();
1482 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1483 && opc != OPC_DADD && opc != OPC_DSUB) {
1484 /* If no destination, treat it as a NOP.
1485 For add & sub, we must generate the overflow exception when needed. */
1486 MIPS_DEBUG("NOP");
1487 goto out;
1489 gen_load_gpr(t0, rs);
1490 /* Specialcase the conventional move operation. */
1491 if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1492 || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1493 gen_store_gpr(t0, rd);
1494 goto out;
1496 gen_load_gpr(t1, rt);
1497 switch (opc) {
1498 case OPC_ADD:
1500 TCGv r_tmp1 = tcg_temp_new();
1501 TCGv r_tmp2 = tcg_temp_new();
1502 int l1 = gen_new_label();
1504 save_cpu_state(ctx, 1);
1505 tcg_gen_ext32s_tl(r_tmp1, t0);
1506 tcg_gen_ext32s_tl(r_tmp2, t1);
1507 tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
1509 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1510 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1511 tcg_gen_xor_tl(r_tmp2, t0, t1);
1512 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1513 tcg_temp_free(r_tmp2);
1514 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1515 /* operands of same sign, result different sign */
1516 generate_exception(ctx, EXCP_OVERFLOW);
1517 gen_set_label(l1);
1518 tcg_temp_free(r_tmp1);
1520 tcg_gen_ext32s_tl(t0, t0);
1522 opn = "add";
1523 break;
1524 case OPC_ADDU:
1525 tcg_gen_add_tl(t0, t0, t1);
1526 tcg_gen_ext32s_tl(t0, t0);
1527 opn = "addu";
1528 break;
1529 case OPC_SUB:
1531 TCGv r_tmp1 = tcg_temp_new();
1532 TCGv r_tmp2 = tcg_temp_new();
1533 int l1 = gen_new_label();
1535 save_cpu_state(ctx, 1);
1536 tcg_gen_ext32s_tl(r_tmp1, t0);
1537 tcg_gen_ext32s_tl(r_tmp2, t1);
1538 tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
1540 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1541 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1542 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1543 tcg_temp_free(r_tmp2);
1544 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1545 /* operands of different sign, first operand and result different sign */
1546 generate_exception(ctx, EXCP_OVERFLOW);
1547 gen_set_label(l1);
1548 tcg_temp_free(r_tmp1);
1550 tcg_gen_ext32s_tl(t0, t0);
1552 opn = "sub";
1553 break;
1554 case OPC_SUBU:
1555 tcg_gen_sub_tl(t0, t0, t1);
1556 tcg_gen_ext32s_tl(t0, t0);
1557 opn = "subu";
1558 break;
1559 #if defined(TARGET_MIPS64)
1560 case OPC_DADD:
1562 TCGv r_tmp1 = tcg_temp_new();
1563 TCGv r_tmp2 = tcg_temp_new();
1564 int l1 = gen_new_label();
1566 save_cpu_state(ctx, 1);
1567 tcg_gen_mov_tl(r_tmp1, t0);
1568 tcg_gen_add_tl(t0, t0, t1);
1570 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1571 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1572 tcg_gen_xor_tl(r_tmp2, t0, t1);
1573 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1574 tcg_temp_free(r_tmp2);
1575 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1576 /* operands of same sign, result different sign */
1577 generate_exception(ctx, EXCP_OVERFLOW);
1578 gen_set_label(l1);
1579 tcg_temp_free(r_tmp1);
1581 opn = "dadd";
1582 break;
1583 case OPC_DADDU:
1584 tcg_gen_add_tl(t0, t0, t1);
1585 opn = "daddu";
1586 break;
1587 case OPC_DSUB:
1589 TCGv r_tmp1 = tcg_temp_new();
1590 TCGv r_tmp2 = tcg_temp_new();
1591 int l1 = gen_new_label();
1593 save_cpu_state(ctx, 1);
1594 tcg_gen_mov_tl(r_tmp1, t0);
1595 tcg_gen_sub_tl(t0, t0, t1);
1597 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1598 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1599 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1600 tcg_temp_free(r_tmp2);
1601 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1602 /* operands of different sign, first operand and result different sign */
1603 generate_exception(ctx, EXCP_OVERFLOW);
1604 gen_set_label(l1);
1605 tcg_temp_free(r_tmp1);
1607 opn = "dsub";
1608 break;
1609 case OPC_DSUBU:
1610 tcg_gen_sub_tl(t0, t0, t1);
1611 opn = "dsubu";
1612 break;
1613 #endif
1614 case OPC_SLT:
1615 gen_op_lt(t0, t1);
1616 opn = "slt";
1617 break;
1618 case OPC_SLTU:
1619 gen_op_ltu(t0, t1);
1620 opn = "sltu";
1621 break;
1622 case OPC_AND:
1623 tcg_gen_and_tl(t0, t0, t1);
1624 opn = "and";
1625 break;
1626 case OPC_NOR:
1627 tcg_gen_or_tl(t0, t0, t1);
1628 tcg_gen_not_tl(t0, t0);
1629 opn = "nor";
1630 break;
1631 case OPC_OR:
1632 tcg_gen_or_tl(t0, t0, t1);
1633 opn = "or";
1634 break;
1635 case OPC_XOR:
1636 tcg_gen_xor_tl(t0, t0, t1);
1637 opn = "xor";
1638 break;
1639 case OPC_MUL:
1640 tcg_gen_mul_tl(t0, t0, t1);
1641 tcg_gen_ext32s_tl(t0, t0);
1642 opn = "mul";
1643 break;
1644 case OPC_MOVN:
1646 int l1 = gen_new_label();
1648 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1649 gen_store_gpr(t0, rd);
1650 gen_set_label(l1);
1652 opn = "movn";
1653 goto print;
1654 case OPC_MOVZ:
1656 int l1 = gen_new_label();
1658 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
1659 gen_store_gpr(t0, rd);
1660 gen_set_label(l1);
1662 opn = "movz";
1663 goto print;
1664 case OPC_SLLV:
1665 tcg_gen_andi_tl(t0, t0, 0x1f);
1666 tcg_gen_shl_tl(t0, t1, t0);
1667 tcg_gen_ext32s_tl(t0, t0);
1668 opn = "sllv";
1669 break;
1670 case OPC_SRAV:
1671 tcg_gen_ext32s_tl(t1, t1);
1672 tcg_gen_andi_tl(t0, t0, 0x1f);
1673 tcg_gen_sar_tl(t0, t1, t0);
1674 opn = "srav";
1675 break;
1676 case OPC_SRLV:
1677 switch ((ctx->opcode >> 6) & 0x1f) {
1678 case 0:
1679 tcg_gen_ext32u_tl(t1, t1);
1680 tcg_gen_andi_tl(t0, t0, 0x1f);
1681 tcg_gen_shr_tl(t0, t1, t0);
1682 tcg_gen_ext32s_tl(t0, t0);
1683 opn = "srlv";
1684 break;
1685 case 1:
1686 /* rotrv is decoded as srlv on non-R2 CPUs */
1687 if (env->insn_flags & ISA_MIPS32R2) {
1688 int l1 = gen_new_label();
1689 int l2 = gen_new_label();
1691 tcg_gen_andi_tl(t0, t0, 0x1f);
1692 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1694 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
1695 TCGv_i32 r_tmp2 = tcg_temp_new_i32();
1697 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1698 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1699 tcg_gen_rotr_i32(r_tmp1, r_tmp1, r_tmp2);
1700 tcg_temp_free_i32(r_tmp1);
1701 tcg_temp_free_i32(r_tmp2);
1702 tcg_gen_br(l2);
1704 gen_set_label(l1);
1705 tcg_gen_mov_tl(t0, t1);
1706 gen_set_label(l2);
1707 opn = "rotrv";
1708 } else {
1709 tcg_gen_ext32u_tl(t1, t1);
1710 tcg_gen_andi_tl(t0, t0, 0x1f);
1711 tcg_gen_shr_tl(t0, t1, t0);
1712 tcg_gen_ext32s_tl(t0, t0);
1713 opn = "srlv";
1715 break;
1716 default:
1717 MIPS_INVAL("invalid srlv flag");
1718 generate_exception(ctx, EXCP_RI);
1719 break;
1721 break;
1722 #if defined(TARGET_MIPS64)
1723 case OPC_DSLLV:
1724 tcg_gen_andi_tl(t0, t0, 0x3f);
1725 tcg_gen_shl_tl(t0, t1, t0);
1726 opn = "dsllv";
1727 break;
1728 case OPC_DSRAV:
1729 tcg_gen_andi_tl(t0, t0, 0x3f);
1730 tcg_gen_sar_tl(t0, t1, t0);
1731 opn = "dsrav";
1732 break;
1733 case OPC_DSRLV:
1734 switch ((ctx->opcode >> 6) & 0x1f) {
1735 case 0:
1736 tcg_gen_andi_tl(t0, t0, 0x3f);
1737 tcg_gen_shr_tl(t0, t1, t0);
1738 opn = "dsrlv";
1739 break;
1740 case 1:
1741 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1742 if (env->insn_flags & ISA_MIPS32R2) {
1743 int l1 = gen_new_label();
1744 int l2 = gen_new_label();
1746 tcg_gen_andi_tl(t0, t0, 0x3f);
1747 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1749 tcg_gen_rotr_tl(t0, t1, t0);
1750 tcg_gen_br(l2);
1752 gen_set_label(l1);
1753 tcg_gen_mov_tl(t0, t1);
1754 gen_set_label(l2);
1755 opn = "drotrv";
1756 } else {
1757 tcg_gen_andi_tl(t0, t0, 0x3f);
1758 tcg_gen_shr_tl(t0, t1, t0);
1759 opn = "dsrlv";
1761 break;
1762 default:
1763 MIPS_INVAL("invalid dsrlv flag");
1764 generate_exception(ctx, EXCP_RI);
1765 break;
1767 break;
1768 #endif
1769 default:
1770 MIPS_INVAL(opn);
1771 generate_exception(ctx, EXCP_RI);
1772 goto out;
1774 gen_store_gpr(t0, rd);
1775 print:
1776 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1777 out:
1778 tcg_temp_free(t0);
1779 tcg_temp_free(t1);
1782 /* Arithmetic on HI/LO registers */
1783 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1785 const char *opn = "hilo";
1786 TCGv t0 = tcg_temp_local_new();
1788 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1789 /* Treat as NOP. */
1790 MIPS_DEBUG("NOP");
1791 goto out;
1793 switch (opc) {
1794 case OPC_MFHI:
1795 tcg_gen_mov_tl(t0, cpu_HI[0]);
1796 gen_store_gpr(t0, reg);
1797 opn = "mfhi";
1798 break;
1799 case OPC_MFLO:
1800 tcg_gen_mov_tl(t0, cpu_LO[0]);
1801 gen_store_gpr(t0, reg);
1802 opn = "mflo";
1803 break;
1804 case OPC_MTHI:
1805 gen_load_gpr(t0, reg);
1806 tcg_gen_mov_tl(cpu_HI[0], t0);
1807 opn = "mthi";
1808 break;
1809 case OPC_MTLO:
1810 gen_load_gpr(t0, reg);
1811 tcg_gen_mov_tl(cpu_LO[0], t0);
1812 opn = "mtlo";
1813 break;
1814 default:
1815 MIPS_INVAL(opn);
1816 generate_exception(ctx, EXCP_RI);
1817 goto out;
1819 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1820 out:
1821 tcg_temp_free(t0);
1824 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1825 int rs, int rt)
1827 const char *opn = "mul/div";
1828 TCGv t0 = tcg_temp_local_new();
1829 TCGv t1 = tcg_temp_local_new();
1831 gen_load_gpr(t0, rs);
1832 gen_load_gpr(t1, rt);
1833 switch (opc) {
1834 case OPC_DIV:
1836 int l1 = gen_new_label();
1838 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1840 int l2 = gen_new_label();
1841 TCGv_i32 r_tmp1 = tcg_temp_local_new_i32();
1842 TCGv_i32 r_tmp2 = tcg_temp_local_new_i32();
1843 TCGv_i32 r_tmp3 = tcg_temp_local_new_i32();
1845 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1846 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1847 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp1, -1 << 31, l2);
1848 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp2, -1, l2);
1849 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1850 tcg_gen_movi_tl(cpu_HI[0], 0);
1851 tcg_gen_br(l1);
1852 gen_set_label(l2);
1853 tcg_gen_div_i32(r_tmp3, r_tmp1, r_tmp2);
1854 tcg_gen_rem_i32(r_tmp2, r_tmp1, r_tmp2);
1855 tcg_gen_ext_i32_tl(cpu_LO[0], r_tmp3);
1856 tcg_gen_ext_i32_tl(cpu_HI[0], r_tmp2);
1857 tcg_temp_free_i32(r_tmp1);
1858 tcg_temp_free_i32(r_tmp2);
1859 tcg_temp_free_i32(r_tmp3);
1861 gen_set_label(l1);
1863 opn = "div";
1864 break;
1865 case OPC_DIVU:
1867 int l1 = gen_new_label();
1869 tcg_gen_ext32s_tl(t1, t1);
1870 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1872 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
1873 TCGv_i32 r_tmp2 = tcg_temp_new_i32();
1874 TCGv_i32 r_tmp3 = tcg_temp_new_i32();
1876 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1877 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1878 tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2);
1879 tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2);
1880 tcg_gen_ext_i32_tl(cpu_LO[0], r_tmp3);
1881 tcg_gen_ext_i32_tl(cpu_HI[0], r_tmp1);
1882 tcg_temp_free_i32(r_tmp1);
1883 tcg_temp_free_i32(r_tmp2);
1884 tcg_temp_free_i32(r_tmp3);
1886 gen_set_label(l1);
1888 opn = "divu";
1889 break;
1890 case OPC_MULT:
1892 TCGv_i64 r_tmp1 = tcg_temp_new_i64();
1893 TCGv_i64 r_tmp2 = tcg_temp_new_i64();
1895 tcg_gen_ext_tl_i64(r_tmp1, t0);
1896 tcg_gen_ext_tl_i64(r_tmp2, t1);
1897 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
1898 tcg_temp_free_i64(r_tmp2);
1899 tcg_gen_trunc_i64_tl(t0, r_tmp1);
1900 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
1901 tcg_gen_trunc_i64_tl(t1, r_tmp1);
1902 tcg_temp_free_i64(r_tmp1);
1903 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1904 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1906 opn = "mult";
1907 break;
1908 case OPC_MULTU:
1910 TCGv_i64 r_tmp1 = tcg_temp_new_i64();
1911 TCGv_i64 r_tmp2 = tcg_temp_new_i64();
1913 tcg_gen_ext32u_tl(t0, t0);
1914 tcg_gen_ext32u_tl(t1, t1);
1915 tcg_gen_extu_tl_i64(r_tmp1, t0);
1916 tcg_gen_extu_tl_i64(r_tmp2, t1);
1917 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
1918 tcg_temp_free_i64(r_tmp2);
1919 tcg_gen_trunc_i64_tl(t0, r_tmp1);
1920 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
1921 tcg_gen_trunc_i64_tl(t1, r_tmp1);
1922 tcg_temp_free_i64(r_tmp1);
1923 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1924 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1926 opn = "multu";
1927 break;
1928 #if defined(TARGET_MIPS64)
1929 case OPC_DDIV:
1931 int l1 = gen_new_label();
1933 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1935 int l2 = gen_new_label();
1937 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
1938 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
1939 tcg_gen_mov_tl(cpu_LO[0], t0);
1940 tcg_gen_movi_tl(cpu_HI[0], 0);
1941 tcg_gen_br(l1);
1942 gen_set_label(l2);
1943 tcg_gen_div_i64(cpu_LO[0], t0, t1);
1944 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
1946 gen_set_label(l1);
1948 opn = "ddiv";
1949 break;
1950 case OPC_DDIVU:
1952 int l1 = gen_new_label();
1954 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1955 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
1956 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
1957 gen_set_label(l1);
1959 opn = "ddivu";
1960 break;
1961 case OPC_DMULT:
1962 gen_helper_dmult(t0, t1);
1963 opn = "dmult";
1964 break;
1965 case OPC_DMULTU:
1966 gen_helper_dmultu(t0, t1);
1967 opn = "dmultu";
1968 break;
1969 #endif
1970 case OPC_MADD:
1972 TCGv_i64 r_tmp1 = tcg_temp_new_i64();
1973 TCGv_i64 r_tmp2 = tcg_temp_new_i64();
1975 tcg_gen_ext_tl_i64(r_tmp1, t0);
1976 tcg_gen_ext_tl_i64(r_tmp2, t1);
1977 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
1978 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
1979 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
1980 tcg_temp_free_i64(r_tmp2);
1981 tcg_gen_trunc_i64_tl(t0, r_tmp1);
1982 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
1983 tcg_gen_trunc_i64_tl(t1, r_tmp1);
1984 tcg_temp_free_i64(r_tmp1);
1985 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1986 tcg_gen_ext32s_tl(cpu_LO[1], t1);
1988 opn = "madd";
1989 break;
1990 case OPC_MADDU:
1992 TCGv_i64 r_tmp1 = tcg_temp_new_i64();
1993 TCGv_i64 r_tmp2 = tcg_temp_new_i64();
1995 tcg_gen_ext32u_tl(t0, t0);
1996 tcg_gen_ext32u_tl(t1, t1);
1997 tcg_gen_extu_tl_i64(r_tmp1, t0);
1998 tcg_gen_extu_tl_i64(r_tmp2, t1);
1999 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2000 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
2001 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
2002 tcg_temp_free_i64(r_tmp2);
2003 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2004 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2005 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2006 tcg_temp_free_i64(r_tmp1);
2007 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2008 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2010 opn = "maddu";
2011 break;
2012 case OPC_MSUB:
2014 TCGv_i64 r_tmp1 = tcg_temp_new_i64();
2015 TCGv_i64 r_tmp2 = tcg_temp_new_i64();
2017 tcg_gen_ext_tl_i64(r_tmp1, t0);
2018 tcg_gen_ext_tl_i64(r_tmp2, t1);
2019 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2020 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
2021 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
2022 tcg_temp_free_i64(r_tmp2);
2023 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2024 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2025 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2026 tcg_temp_free_i64(r_tmp1);
2027 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2028 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2030 opn = "msub";
2031 break;
2032 case OPC_MSUBU:
2034 TCGv_i64 r_tmp1 = tcg_temp_new_i64();
2035 TCGv_i64 r_tmp2 = tcg_temp_new_i64();
2037 tcg_gen_ext32u_tl(t0, t0);
2038 tcg_gen_ext32u_tl(t1, t1);
2039 tcg_gen_extu_tl_i64(r_tmp1, t0);
2040 tcg_gen_extu_tl_i64(r_tmp2, t1);
2041 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2042 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
2043 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
2044 tcg_temp_free_i64(r_tmp2);
2045 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2046 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2047 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2048 tcg_temp_free_i64(r_tmp1);
2049 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2050 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2052 opn = "msubu";
2053 break;
2054 default:
2055 MIPS_INVAL(opn);
2056 generate_exception(ctx, EXCP_RI);
2057 goto out;
2059 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2060 out:
2061 tcg_temp_free(t0);
2062 tcg_temp_free(t1);
2065 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2066 int rd, int rs, int rt)
2068 const char *opn = "mul vr54xx";
2069 TCGv t0 = tcg_temp_local_new();
2070 TCGv t1 = tcg_temp_local_new();
2072 gen_load_gpr(t0, rs);
2073 gen_load_gpr(t1, rt);
2075 switch (opc) {
2076 case OPC_VR54XX_MULS:
2077 gen_helper_muls(t0, t0, t1);
2078 opn = "muls";
2079 break;
2080 case OPC_VR54XX_MULSU:
2081 gen_helper_mulsu(t0, t0, t1);
2082 opn = "mulsu";
2083 break;
2084 case OPC_VR54XX_MACC:
2085 gen_helper_macc(t0, t0, t1);
2086 opn = "macc";
2087 break;
2088 case OPC_VR54XX_MACCU:
2089 gen_helper_maccu(t0, t0, t1);
2090 opn = "maccu";
2091 break;
2092 case OPC_VR54XX_MSAC:
2093 gen_helper_msac(t0, t0, t1);
2094 opn = "msac";
2095 break;
2096 case OPC_VR54XX_MSACU:
2097 gen_helper_msacu(t0, t0, t1);
2098 opn = "msacu";
2099 break;
2100 case OPC_VR54XX_MULHI:
2101 gen_helper_mulhi(t0, t0, t1);
2102 opn = "mulhi";
2103 break;
2104 case OPC_VR54XX_MULHIU:
2105 gen_helper_mulhiu(t0, t0, t1);
2106 opn = "mulhiu";
2107 break;
2108 case OPC_VR54XX_MULSHI:
2109 gen_helper_mulshi(t0, t0, t1);
2110 opn = "mulshi";
2111 break;
2112 case OPC_VR54XX_MULSHIU:
2113 gen_helper_mulshiu(t0, t0, t1);
2114 opn = "mulshiu";
2115 break;
2116 case OPC_VR54XX_MACCHI:
2117 gen_helper_macchi(t0, t0, t1);
2118 opn = "macchi";
2119 break;
2120 case OPC_VR54XX_MACCHIU:
2121 gen_helper_macchiu(t0, t0, t1);
2122 opn = "macchiu";
2123 break;
2124 case OPC_VR54XX_MSACHI:
2125 gen_helper_msachi(t0, t0, t1);
2126 opn = "msachi";
2127 break;
2128 case OPC_VR54XX_MSACHIU:
2129 gen_helper_msachiu(t0, t0, t1);
2130 opn = "msachiu";
2131 break;
2132 default:
2133 MIPS_INVAL("mul vr54xx");
2134 generate_exception(ctx, EXCP_RI);
2135 goto out;
2137 gen_store_gpr(t0, rd);
2138 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2140 out:
2141 tcg_temp_free(t0);
2142 tcg_temp_free(t1);
2145 static void gen_cl (DisasContext *ctx, uint32_t opc,
2146 int rd, int rs)
2148 const char *opn = "CLx";
2149 TCGv t0 = tcg_temp_local_new();
2151 if (rd == 0) {
2152 /* Treat as NOP. */
2153 MIPS_DEBUG("NOP");
2154 goto out;
2156 gen_load_gpr(t0, rs);
2157 switch (opc) {
2158 case OPC_CLO:
2159 gen_helper_clo(t0, t0);
2160 opn = "clo";
2161 break;
2162 case OPC_CLZ:
2163 gen_helper_clz(t0, t0);
2164 opn = "clz";
2165 break;
2166 #if defined(TARGET_MIPS64)
2167 case OPC_DCLO:
2168 gen_helper_dclo(t0, t0);
2169 opn = "dclo";
2170 break;
2171 case OPC_DCLZ:
2172 gen_helper_dclz(t0, t0);
2173 opn = "dclz";
2174 break;
2175 #endif
2176 default:
2177 MIPS_INVAL(opn);
2178 generate_exception(ctx, EXCP_RI);
2179 goto out;
2181 gen_store_gpr(t0, rd);
2182 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2184 out:
2185 tcg_temp_free(t0);
2188 /* Traps */
2189 static void gen_trap (DisasContext *ctx, uint32_t opc,
2190 int rs, int rt, int16_t imm)
2192 int cond;
2193 TCGv t0 = tcg_temp_local_new();
2194 TCGv t1 = tcg_temp_local_new();
2196 cond = 0;
2197 /* Load needed operands */
2198 switch (opc) {
2199 case OPC_TEQ:
2200 case OPC_TGE:
2201 case OPC_TGEU:
2202 case OPC_TLT:
2203 case OPC_TLTU:
2204 case OPC_TNE:
2205 /* Compare two registers */
2206 if (rs != rt) {
2207 gen_load_gpr(t0, rs);
2208 gen_load_gpr(t1, rt);
2209 cond = 1;
2211 break;
2212 case OPC_TEQI:
2213 case OPC_TGEI:
2214 case OPC_TGEIU:
2215 case OPC_TLTI:
2216 case OPC_TLTIU:
2217 case OPC_TNEI:
2218 /* Compare register to immediate */
2219 if (rs != 0 || imm != 0) {
2220 gen_load_gpr(t0, rs);
2221 tcg_gen_movi_tl(t1, (int32_t)imm);
2222 cond = 1;
2224 break;
2226 if (cond == 0) {
2227 switch (opc) {
2228 case OPC_TEQ: /* rs == rs */
2229 case OPC_TEQI: /* r0 == 0 */
2230 case OPC_TGE: /* rs >= rs */
2231 case OPC_TGEI: /* r0 >= 0 */
2232 case OPC_TGEU: /* rs >= rs unsigned */
2233 case OPC_TGEIU: /* r0 >= 0 unsigned */
2234 /* Always trap */
2235 tcg_gen_movi_tl(t0, 1);
2236 break;
2237 case OPC_TLT: /* rs < rs */
2238 case OPC_TLTI: /* r0 < 0 */
2239 case OPC_TLTU: /* rs < rs unsigned */
2240 case OPC_TLTIU: /* r0 < 0 unsigned */
2241 case OPC_TNE: /* rs != rs */
2242 case OPC_TNEI: /* r0 != 0 */
2243 /* Never trap: treat as NOP. */
2244 goto out;
2245 default:
2246 MIPS_INVAL("trap");
2247 generate_exception(ctx, EXCP_RI);
2248 goto out;
2250 } else {
2251 switch (opc) {
2252 case OPC_TEQ:
2253 case OPC_TEQI:
2254 gen_op_eq(t0, t1);
2255 break;
2256 case OPC_TGE:
2257 case OPC_TGEI:
2258 gen_op_ge(t0, t1);
2259 break;
2260 case OPC_TGEU:
2261 case OPC_TGEIU:
2262 gen_op_geu(t0, t1);
2263 break;
2264 case OPC_TLT:
2265 case OPC_TLTI:
2266 gen_op_lt(t0, t1);
2267 break;
2268 case OPC_TLTU:
2269 case OPC_TLTIU:
2270 gen_op_ltu(t0, t1);
2271 break;
2272 case OPC_TNE:
2273 case OPC_TNEI:
2274 gen_op_ne(t0, t1);
2275 break;
2276 default:
2277 MIPS_INVAL("trap");
2278 generate_exception(ctx, EXCP_RI);
2279 goto out;
2282 save_cpu_state(ctx, 1);
2284 int l1 = gen_new_label();
2286 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2287 gen_helper_0i(raise_exception, EXCP_TRAP);
2288 gen_set_label(l1);
2290 ctx->bstate = BS_STOP;
2291 out:
2292 tcg_temp_free(t0);
2293 tcg_temp_free(t1);
2296 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2298 TranslationBlock *tb;
2299 tb = ctx->tb;
2300 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2301 tcg_gen_goto_tb(n);
2302 gen_save_pc(dest);
2303 tcg_gen_exit_tb((long)tb + n);
2304 } else {
2305 gen_save_pc(dest);
2306 tcg_gen_exit_tb(0);
2310 /* Branches (before delay slot) */
2311 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2312 int rs, int rt, int32_t offset)
2314 target_ulong btgt = -1;
2315 int blink = 0;
2316 int bcond_compute = 0;
2317 TCGv t0 = tcg_temp_local_new();
2318 TCGv t1 = tcg_temp_local_new();
2320 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2321 #ifdef MIPS_DEBUG_DISAS
2322 if (loglevel & CPU_LOG_TB_IN_ASM) {
2323 fprintf(logfile,
2324 "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
2325 ctx->pc);
2327 #endif
2328 generate_exception(ctx, EXCP_RI);
2329 goto out;
2332 /* Load needed operands */
2333 switch (opc) {
2334 case OPC_BEQ:
2335 case OPC_BEQL:
2336 case OPC_BNE:
2337 case OPC_BNEL:
2338 /* Compare two registers */
2339 if (rs != rt) {
2340 gen_load_gpr(t0, rs);
2341 gen_load_gpr(t1, rt);
2342 bcond_compute = 1;
2344 btgt = ctx->pc + 4 + offset;
2345 break;
2346 case OPC_BGEZ:
2347 case OPC_BGEZAL:
2348 case OPC_BGEZALL:
2349 case OPC_BGEZL:
2350 case OPC_BGTZ:
2351 case OPC_BGTZL:
2352 case OPC_BLEZ:
2353 case OPC_BLEZL:
2354 case OPC_BLTZ:
2355 case OPC_BLTZAL:
2356 case OPC_BLTZALL:
2357 case OPC_BLTZL:
2358 /* Compare to zero */
2359 if (rs != 0) {
2360 gen_load_gpr(t0, rs);
2361 bcond_compute = 1;
2363 btgt = ctx->pc + 4 + offset;
2364 break;
2365 case OPC_J:
2366 case OPC_JAL:
2367 /* Jump to immediate */
2368 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2369 break;
2370 case OPC_JR:
2371 case OPC_JALR:
2372 /* Jump to register */
2373 if (offset != 0 && offset != 16) {
2374 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2375 others are reserved. */
2376 MIPS_INVAL("jump hint");
2377 generate_exception(ctx, EXCP_RI);
2378 goto out;
2380 gen_load_gpr(btarget, rs);
2381 break;
2382 default:
2383 MIPS_INVAL("branch/jump");
2384 generate_exception(ctx, EXCP_RI);
2385 goto out;
2387 if (bcond_compute == 0) {
2388 /* No condition to be computed */
2389 switch (opc) {
2390 case OPC_BEQ: /* rx == rx */
2391 case OPC_BEQL: /* rx == rx likely */
2392 case OPC_BGEZ: /* 0 >= 0 */
2393 case OPC_BGEZL: /* 0 >= 0 likely */
2394 case OPC_BLEZ: /* 0 <= 0 */
2395 case OPC_BLEZL: /* 0 <= 0 likely */
2396 /* Always take */
2397 ctx->hflags |= MIPS_HFLAG_B;
2398 MIPS_DEBUG("balways");
2399 break;
2400 case OPC_BGEZAL: /* 0 >= 0 */
2401 case OPC_BGEZALL: /* 0 >= 0 likely */
2402 /* Always take and link */
2403 blink = 31;
2404 ctx->hflags |= MIPS_HFLAG_B;
2405 MIPS_DEBUG("balways and link");
2406 break;
2407 case OPC_BNE: /* rx != rx */
2408 case OPC_BGTZ: /* 0 > 0 */
2409 case OPC_BLTZ: /* 0 < 0 */
2410 /* Treat as NOP. */
2411 MIPS_DEBUG("bnever (NOP)");
2412 goto out;
2413 case OPC_BLTZAL: /* 0 < 0 */
2414 tcg_gen_movi_tl(t0, ctx->pc + 8);
2415 gen_store_gpr(t0, 31);
2416 MIPS_DEBUG("bnever and link");
2417 goto out;
2418 case OPC_BLTZALL: /* 0 < 0 likely */
2419 tcg_gen_movi_tl(t0, ctx->pc + 8);
2420 gen_store_gpr(t0, 31);
2421 /* Skip the instruction in the delay slot */
2422 MIPS_DEBUG("bnever, link and skip");
2423 ctx->pc += 4;
2424 goto out;
2425 case OPC_BNEL: /* rx != rx likely */
2426 case OPC_BGTZL: /* 0 > 0 likely */
2427 case OPC_BLTZL: /* 0 < 0 likely */
2428 /* Skip the instruction in the delay slot */
2429 MIPS_DEBUG("bnever and skip");
2430 ctx->pc += 4;
2431 goto out;
2432 case OPC_J:
2433 ctx->hflags |= MIPS_HFLAG_B;
2434 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2435 break;
2436 case OPC_JAL:
2437 blink = 31;
2438 ctx->hflags |= MIPS_HFLAG_B;
2439 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2440 break;
2441 case OPC_JR:
2442 ctx->hflags |= MIPS_HFLAG_BR;
2443 MIPS_DEBUG("jr %s", regnames[rs]);
2444 break;
2445 case OPC_JALR:
2446 blink = rt;
2447 ctx->hflags |= MIPS_HFLAG_BR;
2448 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2449 break;
2450 default:
2451 MIPS_INVAL("branch/jump");
2452 generate_exception(ctx, EXCP_RI);
2453 goto out;
2455 } else {
2456 switch (opc) {
2457 case OPC_BEQ:
2458 gen_op_eq(t0, t1);
2459 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2460 regnames[rs], regnames[rt], btgt);
2461 goto not_likely;
2462 case OPC_BEQL:
2463 gen_op_eq(t0, t1);
2464 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2465 regnames[rs], regnames[rt], btgt);
2466 goto likely;
2467 case OPC_BNE:
2468 gen_op_ne(t0, t1);
2469 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2470 regnames[rs], regnames[rt], btgt);
2471 goto not_likely;
2472 case OPC_BNEL:
2473 gen_op_ne(t0, t1);
2474 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2475 regnames[rs], regnames[rt], btgt);
2476 goto likely;
2477 case OPC_BGEZ:
2478 gen_op_gez(t0);
2479 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2480 goto not_likely;
2481 case OPC_BGEZL:
2482 gen_op_gez(t0);
2483 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2484 goto likely;
2485 case OPC_BGEZAL:
2486 gen_op_gez(t0);
2487 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2488 blink = 31;
2489 goto not_likely;
2490 case OPC_BGEZALL:
2491 gen_op_gez(t0);
2492 blink = 31;
2493 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2494 goto likely;
2495 case OPC_BGTZ:
2496 gen_op_gtz(t0);
2497 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2498 goto not_likely;
2499 case OPC_BGTZL:
2500 gen_op_gtz(t0);
2501 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2502 goto likely;
2503 case OPC_BLEZ:
2504 gen_op_lez(t0);
2505 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2506 goto not_likely;
2507 case OPC_BLEZL:
2508 gen_op_lez(t0);
2509 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2510 goto likely;
2511 case OPC_BLTZ:
2512 gen_op_ltz(t0);
2513 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2514 goto not_likely;
2515 case OPC_BLTZL:
2516 gen_op_ltz(t0);
2517 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2518 goto likely;
2519 case OPC_BLTZAL:
2520 gen_op_ltz(t0);
2521 blink = 31;
2522 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2523 not_likely:
2524 ctx->hflags |= MIPS_HFLAG_BC;
2525 tcg_gen_trunc_tl_i32(bcond, t0);
2526 break;
2527 case OPC_BLTZALL:
2528 gen_op_ltz(t0);
2529 blink = 31;
2530 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2531 likely:
2532 ctx->hflags |= MIPS_HFLAG_BL;
2533 tcg_gen_trunc_tl_i32(bcond, t0);
2534 break;
2535 default:
2536 MIPS_INVAL("conditional branch/jump");
2537 generate_exception(ctx, EXCP_RI);
2538 goto out;
2541 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2542 blink, ctx->hflags, btgt);
2544 ctx->btarget = btgt;
2545 if (blink > 0) {
2546 tcg_gen_movi_tl(t0, ctx->pc + 8);
2547 gen_store_gpr(t0, blink);
2550 out:
2551 tcg_temp_free(t0);
2552 tcg_temp_free(t1);
2555 /* special3 bitfield operations */
2556 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2557 int rs, int lsb, int msb)
2559 TCGv t0 = tcg_temp_new();
2560 TCGv t1 = tcg_temp_new();
2561 target_ulong mask;
2563 gen_load_gpr(t1, rs);
2564 switch (opc) {
2565 case OPC_EXT:
2566 if (lsb + msb > 31)
2567 goto fail;
2568 tcg_gen_shri_tl(t0, t1, lsb);
2569 if (msb != 31) {
2570 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2571 } else {
2572 tcg_gen_ext32s_tl(t0, t0);
2574 break;
2575 #if defined(TARGET_MIPS64)
2576 case OPC_DEXTM:
2577 tcg_gen_shri_tl(t0, t1, lsb);
2578 if (msb != 31) {
2579 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2581 break;
2582 case OPC_DEXTU:
2583 tcg_gen_shri_tl(t0, t1, lsb + 32);
2584 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2585 break;
2586 case OPC_DEXT:
2587 tcg_gen_shri_tl(t0, t1, lsb);
2588 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2589 break;
2590 #endif
2591 case OPC_INS:
2592 if (lsb > msb)
2593 goto fail;
2594 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2595 gen_load_gpr(t0, rt);
2596 tcg_gen_andi_tl(t0, t0, ~mask);
2597 tcg_gen_shli_tl(t1, t1, lsb);
2598 tcg_gen_andi_tl(t1, t1, mask);
2599 tcg_gen_or_tl(t0, t0, t1);
2600 tcg_gen_ext32s_tl(t0, t0);
2601 break;
2602 #if defined(TARGET_MIPS64)
2603 case OPC_DINSM:
2604 if (lsb > msb)
2605 goto fail;
2606 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2607 gen_load_gpr(t0, rt);
2608 tcg_gen_andi_tl(t0, t0, ~mask);
2609 tcg_gen_shli_tl(t1, t1, lsb);
2610 tcg_gen_andi_tl(t1, t1, mask);
2611 tcg_gen_or_tl(t0, t0, t1);
2612 break;
2613 case OPC_DINSU:
2614 if (lsb > msb)
2615 goto fail;
2616 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2617 gen_load_gpr(t0, rt);
2618 tcg_gen_andi_tl(t0, t0, ~mask);
2619 tcg_gen_shli_tl(t1, t1, lsb + 32);
2620 tcg_gen_andi_tl(t1, t1, mask);
2621 tcg_gen_or_tl(t0, t0, t1);
2622 break;
2623 case OPC_DINS:
2624 if (lsb > msb)
2625 goto fail;
2626 gen_load_gpr(t0, rt);
2627 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2628 gen_load_gpr(t0, rt);
2629 tcg_gen_andi_tl(t0, t0, ~mask);
2630 tcg_gen_shli_tl(t1, t1, lsb);
2631 tcg_gen_andi_tl(t1, t1, mask);
2632 tcg_gen_or_tl(t0, t0, t1);
2633 break;
2634 #endif
2635 default:
2636 fail:
2637 MIPS_INVAL("bitops");
2638 generate_exception(ctx, EXCP_RI);
2639 tcg_temp_free(t0);
2640 tcg_temp_free(t1);
2641 return;
2643 gen_store_gpr(t0, rt);
2644 tcg_temp_free(t0);
2645 tcg_temp_free(t1);
2648 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2650 TCGv t0 = tcg_temp_new();
2651 TCGv t1 = tcg_temp_new();
2653 gen_load_gpr(t1, rt);
2654 switch (op2) {
2655 case OPC_WSBH:
2656 tcg_gen_shri_tl(t0, t1, 8);
2657 tcg_gen_andi_tl(t0, t0, 0x00FF00FF);
2658 tcg_gen_shli_tl(t1, t1, 8);
2659 tcg_gen_andi_tl(t1, t1, ~0x00FF00FF);
2660 tcg_gen_or_tl(t0, t0, t1);
2661 tcg_gen_ext32s_tl(t0, t0);
2662 break;
2663 case OPC_SEB:
2664 tcg_gen_ext8s_tl(t0, t1);
2665 break;
2666 case OPC_SEH:
2667 tcg_gen_ext16s_tl(t0, t1);
2668 break;
2669 #if defined(TARGET_MIPS64)
2670 case OPC_DSBH:
2671 gen_load_gpr(t1, rt);
2672 tcg_gen_shri_tl(t0, t1, 8);
2673 tcg_gen_andi_tl(t0, t0, 0x00FF00FF00FF00FFULL);
2674 tcg_gen_shli_tl(t1, t1, 8);
2675 tcg_gen_andi_tl(t1, t1, ~0x00FF00FF00FF00FFULL);
2676 tcg_gen_or_tl(t0, t0, t1);
2677 break;
2678 case OPC_DSHD:
2679 gen_load_gpr(t1, rt);
2680 tcg_gen_shri_tl(t0, t1, 16);
2681 tcg_gen_andi_tl(t0, t0, 0x0000FFFF0000FFFFULL);
2682 tcg_gen_shli_tl(t1, t1, 16);
2683 tcg_gen_andi_tl(t1, t1, ~0x0000FFFF0000FFFFULL);
2684 tcg_gen_or_tl(t1, t0, t1);
2685 tcg_gen_shri_tl(t0, t1, 32);
2686 tcg_gen_shli_tl(t1, t1, 32);
2687 tcg_gen_or_tl(t0, t0, t1);
2688 break;
2689 #endif
2690 default:
2691 MIPS_INVAL("bsfhl");
2692 generate_exception(ctx, EXCP_RI);
2693 tcg_temp_free(t0);
2694 tcg_temp_free(t1);
2695 return;
2697 gen_store_gpr(t0, rd);
2698 tcg_temp_free(t0);
2699 tcg_temp_free(t1);
2702 #ifndef CONFIG_USER_ONLY
2703 /* CP0 (MMU and control) */
2704 static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
2706 TCGv_i32 r_tmp = tcg_temp_new_i32();
2708 tcg_gen_ld_i32(r_tmp, cpu_env, off);
2709 tcg_gen_ext_i32_tl(t, r_tmp);
2710 tcg_temp_free_i32(r_tmp);
2713 static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
2715 tcg_gen_ld_tl(t, cpu_env, off);
2716 tcg_gen_ext32s_tl(t, t);
2719 static inline void gen_mtc0_store32 (TCGv t, target_ulong off)
2721 TCGv_i32 r_tmp = tcg_temp_new_i32();
2723 tcg_gen_trunc_tl_i32(r_tmp, t);
2724 tcg_gen_st_i32(r_tmp, cpu_env, off);
2725 tcg_temp_free_i32(r_tmp);
2728 static inline void gen_mtc0_store64 (TCGv t, target_ulong off)
2730 tcg_gen_ext32s_tl(t, t);
2731 tcg_gen_st_tl(t, cpu_env, off);
2734 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
2736 const char *rn = "invalid";
2738 if (sel != 0)
2739 check_insn(env, ctx, ISA_MIPS32);
2741 switch (reg) {
2742 case 0:
2743 switch (sel) {
2744 case 0:
2745 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
2746 rn = "Index";
2747 break;
2748 case 1:
2749 check_insn(env, ctx, ASE_MT);
2750 gen_helper_mfc0_mvpcontrol(t0);
2751 rn = "MVPControl";
2752 break;
2753 case 2:
2754 check_insn(env, ctx, ASE_MT);
2755 gen_helper_mfc0_mvpconf0(t0);
2756 rn = "MVPConf0";
2757 break;
2758 case 3:
2759 check_insn(env, ctx, ASE_MT);
2760 gen_helper_mfc0_mvpconf1(t0);
2761 rn = "MVPConf1";
2762 break;
2763 default:
2764 goto die;
2766 break;
2767 case 1:
2768 switch (sel) {
2769 case 0:
2770 gen_helper_mfc0_random(t0);
2771 rn = "Random";
2772 break;
2773 case 1:
2774 check_insn(env, ctx, ASE_MT);
2775 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
2776 rn = "VPEControl";
2777 break;
2778 case 2:
2779 check_insn(env, ctx, ASE_MT);
2780 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
2781 rn = "VPEConf0";
2782 break;
2783 case 3:
2784 check_insn(env, ctx, ASE_MT);
2785 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
2786 rn = "VPEConf1";
2787 break;
2788 case 4:
2789 check_insn(env, ctx, ASE_MT);
2790 gen_mfc0_load64(t0, offsetof(CPUState, CP0_YQMask));
2791 rn = "YQMask";
2792 break;
2793 case 5:
2794 check_insn(env, ctx, ASE_MT);
2795 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPESchedule));
2796 rn = "VPESchedule";
2797 break;
2798 case 6:
2799 check_insn(env, ctx, ASE_MT);
2800 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPEScheFBack));
2801 rn = "VPEScheFBack";
2802 break;
2803 case 7:
2804 check_insn(env, ctx, ASE_MT);
2805 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
2806 rn = "VPEOpt";
2807 break;
2808 default:
2809 goto die;
2811 break;
2812 case 2:
2813 switch (sel) {
2814 case 0:
2815 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2816 tcg_gen_ext32s_tl(t0, t0);
2817 rn = "EntryLo0";
2818 break;
2819 case 1:
2820 check_insn(env, ctx, ASE_MT);
2821 gen_helper_mfc0_tcstatus(t0);
2822 rn = "TCStatus";
2823 break;
2824 case 2:
2825 check_insn(env, ctx, ASE_MT);
2826 gen_helper_mfc0_tcbind(t0);
2827 rn = "TCBind";
2828 break;
2829 case 3:
2830 check_insn(env, ctx, ASE_MT);
2831 gen_helper_mfc0_tcrestart(t0);
2832 rn = "TCRestart";
2833 break;
2834 case 4:
2835 check_insn(env, ctx, ASE_MT);
2836 gen_helper_mfc0_tchalt(t0);
2837 rn = "TCHalt";
2838 break;
2839 case 5:
2840 check_insn(env, ctx, ASE_MT);
2841 gen_helper_mfc0_tccontext(t0);
2842 rn = "TCContext";
2843 break;
2844 case 6:
2845 check_insn(env, ctx, ASE_MT);
2846 gen_helper_mfc0_tcschedule(t0);
2847 rn = "TCSchedule";
2848 break;
2849 case 7:
2850 check_insn(env, ctx, ASE_MT);
2851 gen_helper_mfc0_tcschefback(t0);
2852 rn = "TCScheFBack";
2853 break;
2854 default:
2855 goto die;
2857 break;
2858 case 3:
2859 switch (sel) {
2860 case 0:
2861 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2862 tcg_gen_ext32s_tl(t0, t0);
2863 rn = "EntryLo1";
2864 break;
2865 default:
2866 goto die;
2868 break;
2869 case 4:
2870 switch (sel) {
2871 case 0:
2872 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
2873 tcg_gen_ext32s_tl(t0, t0);
2874 rn = "Context";
2875 break;
2876 case 1:
2877 // gen_helper_mfc0_contextconfig(t0); /* SmartMIPS ASE */
2878 rn = "ContextConfig";
2879 // break;
2880 default:
2881 goto die;
2883 break;
2884 case 5:
2885 switch (sel) {
2886 case 0:
2887 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
2888 rn = "PageMask";
2889 break;
2890 case 1:
2891 check_insn(env, ctx, ISA_MIPS32R2);
2892 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
2893 rn = "PageGrain";
2894 break;
2895 default:
2896 goto die;
2898 break;
2899 case 6:
2900 switch (sel) {
2901 case 0:
2902 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
2903 rn = "Wired";
2904 break;
2905 case 1:
2906 check_insn(env, ctx, ISA_MIPS32R2);
2907 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
2908 rn = "SRSConf0";
2909 break;
2910 case 2:
2911 check_insn(env, ctx, ISA_MIPS32R2);
2912 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
2913 rn = "SRSConf1";
2914 break;
2915 case 3:
2916 check_insn(env, ctx, ISA_MIPS32R2);
2917 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
2918 rn = "SRSConf2";
2919 break;
2920 case 4:
2921 check_insn(env, ctx, ISA_MIPS32R2);
2922 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
2923 rn = "SRSConf3";
2924 break;
2925 case 5:
2926 check_insn(env, ctx, ISA_MIPS32R2);
2927 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
2928 rn = "SRSConf4";
2929 break;
2930 default:
2931 goto die;
2933 break;
2934 case 7:
2935 switch (sel) {
2936 case 0:
2937 check_insn(env, ctx, ISA_MIPS32R2);
2938 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
2939 rn = "HWREna";
2940 break;
2941 default:
2942 goto die;
2944 break;
2945 case 8:
2946 switch (sel) {
2947 case 0:
2948 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
2949 tcg_gen_ext32s_tl(t0, t0);
2950 rn = "BadVAddr";
2951 break;
2952 default:
2953 goto die;
2955 break;
2956 case 9:
2957 switch (sel) {
2958 case 0:
2959 /* Mark as an IO operation because we read the time. */
2960 if (use_icount)
2961 gen_io_start();
2962 gen_helper_mfc0_count(t0);
2963 if (use_icount) {
2964 gen_io_end();
2965 ctx->bstate = BS_STOP;
2967 rn = "Count";
2968 break;
2969 /* 6,7 are implementation dependent */
2970 default:
2971 goto die;
2973 break;
2974 case 10:
2975 switch (sel) {
2976 case 0:
2977 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
2978 tcg_gen_ext32s_tl(t0, t0);
2979 rn = "EntryHi";
2980 break;
2981 default:
2982 goto die;
2984 break;
2985 case 11:
2986 switch (sel) {
2987 case 0:
2988 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
2989 rn = "Compare";
2990 break;
2991 /* 6,7 are implementation dependent */
2992 default:
2993 goto die;
2995 break;
2996 case 12:
2997 switch (sel) {
2998 case 0:
2999 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
3000 rn = "Status";
3001 break;
3002 case 1:
3003 check_insn(env, ctx, ISA_MIPS32R2);
3004 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
3005 rn = "IntCtl";
3006 break;
3007 case 2:
3008 check_insn(env, ctx, ISA_MIPS32R2);
3009 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
3010 rn = "SRSCtl";
3011 break;
3012 case 3:
3013 check_insn(env, ctx, ISA_MIPS32R2);
3014 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
3015 rn = "SRSMap";
3016 break;
3017 default:
3018 goto die;
3020 break;
3021 case 13:
3022 switch (sel) {
3023 case 0:
3024 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
3025 rn = "Cause";
3026 break;
3027 default:
3028 goto die;
3030 break;
3031 case 14:
3032 switch (sel) {
3033 case 0:
3034 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
3035 tcg_gen_ext32s_tl(t0, t0);
3036 rn = "EPC";
3037 break;
3038 default:
3039 goto die;
3041 break;
3042 case 15:
3043 switch (sel) {
3044 case 0:
3045 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
3046 rn = "PRid";
3047 break;
3048 case 1:
3049 check_insn(env, ctx, ISA_MIPS32R2);
3050 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
3051 rn = "EBase";
3052 break;
3053 default:
3054 goto die;
3056 break;
3057 case 16:
3058 switch (sel) {
3059 case 0:
3060 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
3061 rn = "Config";
3062 break;
3063 case 1:
3064 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
3065 rn = "Config1";
3066 break;
3067 case 2:
3068 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
3069 rn = "Config2";
3070 break;
3071 case 3:
3072 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
3073 rn = "Config3";
3074 break;
3075 /* 4,5 are reserved */
3076 /* 6,7 are implementation dependent */
3077 case 6:
3078 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
3079 rn = "Config6";
3080 break;
3081 case 7:
3082 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
3083 rn = "Config7";
3084 break;
3085 default:
3086 goto die;
3088 break;
3089 case 17:
3090 switch (sel) {
3091 case 0:
3092 gen_helper_mfc0_lladdr(t0);
3093 rn = "LLAddr";
3094 break;
3095 default:
3096 goto die;
3098 break;
3099 case 18:
3100 switch (sel) {
3101 case 0 ... 7:
3102 gen_helper_1i(mfc0_watchlo, t0, sel);
3103 rn = "WatchLo";
3104 break;
3105 default:
3106 goto die;
3108 break;
3109 case 19:
3110 switch (sel) {
3111 case 0 ...7:
3112 gen_helper_1i(mfc0_watchhi, t0, sel);
3113 rn = "WatchHi";
3114 break;
3115 default:
3116 goto die;
3118 break;
3119 case 20:
3120 switch (sel) {
3121 case 0:
3122 #if defined(TARGET_MIPS64)
3123 check_insn(env, ctx, ISA_MIPS3);
3124 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
3125 tcg_gen_ext32s_tl(t0, t0);
3126 rn = "XContext";
3127 break;
3128 #endif
3129 default:
3130 goto die;
3132 break;
3133 case 21:
3134 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3135 switch (sel) {
3136 case 0:
3137 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
3138 rn = "Framemask";
3139 break;
3140 default:
3141 goto die;
3143 break;
3144 case 22:
3145 tcg_gen_movi_tl(t0, 0); /* unimplemented */
3146 rn = "'Diagnostic"; /* implementation dependent */
3147 break;
3148 case 23:
3149 switch (sel) {
3150 case 0:
3151 gen_helper_mfc0_debug(t0); /* EJTAG support */
3152 rn = "Debug";
3153 break;
3154 case 1:
3155 // gen_helper_mfc0_tracecontrol(t0); /* PDtrace support */
3156 rn = "TraceControl";
3157 // break;
3158 case 2:
3159 // gen_helper_mfc0_tracecontrol2(t0); /* PDtrace support */
3160 rn = "TraceControl2";
3161 // break;
3162 case 3:
3163 // gen_helper_mfc0_usertracedata(t0); /* PDtrace support */
3164 rn = "UserTraceData";
3165 // break;
3166 case 4:
3167 // gen_helper_mfc0_tracebpc(t0); /* PDtrace support */
3168 rn = "TraceBPC";
3169 // break;
3170 default:
3171 goto die;
3173 break;
3174 case 24:
3175 switch (sel) {
3176 case 0:
3177 /* EJTAG support */
3178 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
3179 tcg_gen_ext32s_tl(t0, t0);
3180 rn = "DEPC";
3181 break;
3182 default:
3183 goto die;
3185 break;
3186 case 25:
3187 switch (sel) {
3188 case 0:
3189 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
3190 rn = "Performance0";
3191 break;
3192 case 1:
3193 // gen_helper_mfc0_performance1(t0);
3194 rn = "Performance1";
3195 // break;
3196 case 2:
3197 // gen_helper_mfc0_performance2(t0);
3198 rn = "Performance2";
3199 // break;
3200 case 3:
3201 // gen_helper_mfc0_performance3(t0);
3202 rn = "Performance3";
3203 // break;
3204 case 4:
3205 // gen_helper_mfc0_performance4(t0);
3206 rn = "Performance4";
3207 // break;
3208 case 5:
3209 // gen_helper_mfc0_performance5(t0);
3210 rn = "Performance5";
3211 // break;
3212 case 6:
3213 // gen_helper_mfc0_performance6(t0);
3214 rn = "Performance6";
3215 // break;
3216 case 7:
3217 // gen_helper_mfc0_performance7(t0);
3218 rn = "Performance7";
3219 // break;
3220 default:
3221 goto die;
3223 break;
3224 case 26:
3225 tcg_gen_movi_tl(t0, 0); /* unimplemented */
3226 rn = "ECC";
3227 break;
3228 case 27:
3229 switch (sel) {
3230 case 0 ... 3:
3231 tcg_gen_movi_tl(t0, 0); /* unimplemented */
3232 rn = "CacheErr";
3233 break;
3234 default:
3235 goto die;
3237 break;
3238 case 28:
3239 switch (sel) {
3240 case 0:
3241 case 2:
3242 case 4:
3243 case 6:
3244 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
3245 rn = "TagLo";
3246 break;
3247 case 1:
3248 case 3:
3249 case 5:
3250 case 7:
3251 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
3252 rn = "DataLo";
3253 break;
3254 default:
3255 goto die;
3257 break;
3258 case 29:
3259 switch (sel) {
3260 case 0:
3261 case 2:
3262 case 4:
3263 case 6:
3264 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
3265 rn = "TagHi";
3266 break;
3267 case 1:
3268 case 3:
3269 case 5:
3270 case 7:
3271 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
3272 rn = "DataHi";
3273 break;
3274 default:
3275 goto die;
3277 break;
3278 case 30:
3279 switch (sel) {
3280 case 0:
3281 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3282 tcg_gen_ext32s_tl(t0, t0);
3283 rn = "ErrorEPC";
3284 break;
3285 default:
3286 goto die;
3288 break;
3289 case 31:
3290 switch (sel) {
3291 case 0:
3292 /* EJTAG support */
3293 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
3294 rn = "DESAVE";
3295 break;
3296 default:
3297 goto die;
3299 break;
3300 default:
3301 goto die;
3303 #if defined MIPS_DEBUG_DISAS
3304 if (loglevel & CPU_LOG_TB_IN_ASM) {
3305 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3306 rn, reg, sel);
3308 #endif
3309 return;
3311 die:
3312 #if defined MIPS_DEBUG_DISAS
3313 if (loglevel & CPU_LOG_TB_IN_ASM) {
3314 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3315 rn, reg, sel);
3317 #endif
3318 generate_exception(ctx, EXCP_RI);
3321 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
3323 const char *rn = "invalid";
3325 if (sel != 0)
3326 check_insn(env, ctx, ISA_MIPS32);
3328 if (use_icount)
3329 gen_io_start();
3331 switch (reg) {
3332 case 0:
3333 switch (sel) {
3334 case 0:
3335 gen_helper_mtc0_index(t0);
3336 rn = "Index";
3337 break;
3338 case 1:
3339 check_insn(env, ctx, ASE_MT);
3340 gen_helper_mtc0_mvpcontrol(t0);
3341 rn = "MVPControl";
3342 break;
3343 case 2:
3344 check_insn(env, ctx, ASE_MT);
3345 /* ignored */
3346 rn = "MVPConf0";
3347 break;
3348 case 3:
3349 check_insn(env, ctx, ASE_MT);
3350 /* ignored */
3351 rn = "MVPConf1";
3352 break;
3353 default:
3354 goto die;
3356 break;
3357 case 1:
3358 switch (sel) {
3359 case 0:
3360 /* ignored */
3361 rn = "Random";
3362 break;
3363 case 1:
3364 check_insn(env, ctx, ASE_MT);
3365 gen_helper_mtc0_vpecontrol(t0);
3366 rn = "VPEControl";
3367 break;
3368 case 2:
3369 check_insn(env, ctx, ASE_MT);
3370 gen_helper_mtc0_vpeconf0(t0);
3371 rn = "VPEConf0";
3372 break;
3373 case 3:
3374 check_insn(env, ctx, ASE_MT);
3375 gen_helper_mtc0_vpeconf1(t0);
3376 rn = "VPEConf1";
3377 break;
3378 case 4:
3379 check_insn(env, ctx, ASE_MT);
3380 gen_helper_mtc0_yqmask(t0);
3381 rn = "YQMask";
3382 break;
3383 case 5:
3384 check_insn(env, ctx, ASE_MT);
3385 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule));
3386 rn = "VPESchedule";
3387 break;
3388 case 6:
3389 check_insn(env, ctx, ASE_MT);
3390 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack));
3391 rn = "VPEScheFBack";
3392 break;
3393 case 7:
3394 check_insn(env, ctx, ASE_MT);
3395 gen_helper_mtc0_vpeopt(t0);
3396 rn = "VPEOpt";
3397 break;
3398 default:
3399 goto die;
3401 break;
3402 case 2:
3403 switch (sel) {
3404 case 0:
3405 gen_helper_mtc0_entrylo0(t0);
3406 rn = "EntryLo0";
3407 break;
3408 case 1:
3409 check_insn(env, ctx, ASE_MT);
3410 gen_helper_mtc0_tcstatus(t0);
3411 rn = "TCStatus";
3412 break;
3413 case 2:
3414 check_insn(env, ctx, ASE_MT);
3415 gen_helper_mtc0_tcbind(t0);
3416 rn = "TCBind";
3417 break;
3418 case 3:
3419 check_insn(env, ctx, ASE_MT);
3420 gen_helper_mtc0_tcrestart(t0);
3421 rn = "TCRestart";
3422 break;
3423 case 4:
3424 check_insn(env, ctx, ASE_MT);
3425 gen_helper_mtc0_tchalt(t0);
3426 rn = "TCHalt";
3427 break;
3428 case 5:
3429 check_insn(env, ctx, ASE_MT);
3430 gen_helper_mtc0_tccontext(t0);
3431 rn = "TCContext";
3432 break;
3433 case 6:
3434 check_insn(env, ctx, ASE_MT);
3435 gen_helper_mtc0_tcschedule(t0);
3436 rn = "TCSchedule";
3437 break;
3438 case 7:
3439 check_insn(env, ctx, ASE_MT);
3440 gen_helper_mtc0_tcschefback(t0);
3441 rn = "TCScheFBack";
3442 break;
3443 default:
3444 goto die;
3446 break;
3447 case 3:
3448 switch (sel) {
3449 case 0:
3450 gen_helper_mtc0_entrylo1(t0);
3451 rn = "EntryLo1";
3452 break;
3453 default:
3454 goto die;
3456 break;
3457 case 4:
3458 switch (sel) {
3459 case 0:
3460 gen_helper_mtc0_context(t0);
3461 rn = "Context";
3462 break;
3463 case 1:
3464 // gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
3465 rn = "ContextConfig";
3466 // break;
3467 default:
3468 goto die;
3470 break;
3471 case 5:
3472 switch (sel) {
3473 case 0:
3474 gen_helper_mtc0_pagemask(t0);
3475 rn = "PageMask";
3476 break;
3477 case 1:
3478 check_insn(env, ctx, ISA_MIPS32R2);
3479 gen_helper_mtc0_pagegrain(t0);
3480 rn = "PageGrain";
3481 break;
3482 default:
3483 goto die;
3485 break;
3486 case 6:
3487 switch (sel) {
3488 case 0:
3489 gen_helper_mtc0_wired(t0);
3490 rn = "Wired";
3491 break;
3492 case 1:
3493 check_insn(env, ctx, ISA_MIPS32R2);
3494 gen_helper_mtc0_srsconf0(t0);
3495 rn = "SRSConf0";
3496 break;
3497 case 2:
3498 check_insn(env, ctx, ISA_MIPS32R2);
3499 gen_helper_mtc0_srsconf1(t0);
3500 rn = "SRSConf1";
3501 break;
3502 case 3:
3503 check_insn(env, ctx, ISA_MIPS32R2);
3504 gen_helper_mtc0_srsconf2(t0);
3505 rn = "SRSConf2";
3506 break;
3507 case 4:
3508 check_insn(env, ctx, ISA_MIPS32R2);
3509 gen_helper_mtc0_srsconf3(t0);
3510 rn = "SRSConf3";
3511 break;
3512 case 5:
3513 check_insn(env, ctx, ISA_MIPS32R2);
3514 gen_helper_mtc0_srsconf4(t0);
3515 rn = "SRSConf4";
3516 break;
3517 default:
3518 goto die;
3520 break;
3521 case 7:
3522 switch (sel) {
3523 case 0:
3524 check_insn(env, ctx, ISA_MIPS32R2);
3525 gen_helper_mtc0_hwrena(t0);
3526 rn = "HWREna";
3527 break;
3528 default:
3529 goto die;
3531 break;
3532 case 8:
3533 /* ignored */
3534 rn = "BadVAddr";
3535 break;
3536 case 9:
3537 switch (sel) {
3538 case 0:
3539 gen_helper_mtc0_count(t0);
3540 rn = "Count";
3541 break;
3542 /* 6,7 are implementation dependent */
3543 default:
3544 goto die;
3546 /* Stop translation as we may have switched the execution mode */
3547 ctx->bstate = BS_STOP;
3548 break;
3549 case 10:
3550 switch (sel) {
3551 case 0:
3552 gen_helper_mtc0_entryhi(t0);
3553 rn = "EntryHi";
3554 break;
3555 default:
3556 goto die;
3558 break;
3559 case 11:
3560 switch (sel) {
3561 case 0:
3562 gen_helper_mtc0_compare(t0);
3563 rn = "Compare";
3564 break;
3565 /* 6,7 are implementation dependent */
3566 default:
3567 goto die;
3569 /* Stop translation as we may have switched the execution mode */
3570 ctx->bstate = BS_STOP;
3571 break;
3572 case 12:
3573 switch (sel) {
3574 case 0:
3575 gen_helper_mtc0_status(t0);
3576 /* BS_STOP isn't good enough here, hflags may have changed. */
3577 gen_save_pc(ctx->pc + 4);
3578 ctx->bstate = BS_EXCP;
3579 rn = "Status";
3580 break;
3581 case 1:
3582 check_insn(env, ctx, ISA_MIPS32R2);
3583 gen_helper_mtc0_intctl(t0);
3584 /* Stop translation as we may have switched the execution mode */
3585 ctx->bstate = BS_STOP;
3586 rn = "IntCtl";
3587 break;
3588 case 2:
3589 check_insn(env, ctx, ISA_MIPS32R2);
3590 gen_helper_mtc0_srsctl(t0);
3591 /* Stop translation as we may have switched the execution mode */
3592 ctx->bstate = BS_STOP;
3593 rn = "SRSCtl";
3594 break;
3595 case 3:
3596 check_insn(env, ctx, ISA_MIPS32R2);
3597 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
3598 /* Stop translation as we may have switched the execution mode */
3599 ctx->bstate = BS_STOP;
3600 rn = "SRSMap";
3601 break;
3602 default:
3603 goto die;
3605 break;
3606 case 13:
3607 switch (sel) {
3608 case 0:
3609 gen_helper_mtc0_cause(t0);
3610 rn = "Cause";
3611 break;
3612 default:
3613 goto die;
3615 /* Stop translation as we may have switched the execution mode */
3616 ctx->bstate = BS_STOP;
3617 break;
3618 case 14:
3619 switch (sel) {
3620 case 0:
3621 gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC));
3622 rn = "EPC";
3623 break;
3624 default:
3625 goto die;
3627 break;
3628 case 15:
3629 switch (sel) {
3630 case 0:
3631 /* ignored */
3632 rn = "PRid";
3633 break;
3634 case 1:
3635 check_insn(env, ctx, ISA_MIPS32R2);
3636 gen_helper_mtc0_ebase(t0);
3637 rn = "EBase";
3638 break;
3639 default:
3640 goto die;
3642 break;
3643 case 16:
3644 switch (sel) {
3645 case 0:
3646 gen_helper_mtc0_config0(t0);
3647 rn = "Config";
3648 /* Stop translation as we may have switched the execution mode */
3649 ctx->bstate = BS_STOP;
3650 break;
3651 case 1:
3652 /* ignored, read only */
3653 rn = "Config1";
3654 break;
3655 case 2:
3656 gen_helper_mtc0_config2(t0);
3657 rn = "Config2";
3658 /* Stop translation as we may have switched the execution mode */
3659 ctx->bstate = BS_STOP;
3660 break;
3661 case 3:
3662 /* ignored, read only */
3663 rn = "Config3";
3664 break;
3665 /* 4,5 are reserved */
3666 /* 6,7 are implementation dependent */
3667 case 6:
3668 /* ignored */
3669 rn = "Config6";
3670 break;
3671 case 7:
3672 /* ignored */
3673 rn = "Config7";
3674 break;
3675 default:
3676 rn = "Invalid config selector";
3677 goto die;
3679 break;
3680 case 17:
3681 switch (sel) {
3682 case 0:
3683 /* ignored */
3684 rn = "LLAddr";
3685 break;
3686 default:
3687 goto die;
3689 break;
3690 case 18:
3691 switch (sel) {
3692 case 0 ... 7:
3693 gen_helper_1i(mtc0_watchlo, t0, sel);
3694 rn = "WatchLo";
3695 break;
3696 default:
3697 goto die;
3699 break;
3700 case 19:
3701 switch (sel) {
3702 case 0 ... 7:
3703 gen_helper_1i(mtc0_watchhi, t0, sel);
3704 rn = "WatchHi";
3705 break;
3706 default:
3707 goto die;
3709 break;
3710 case 20:
3711 switch (sel) {
3712 case 0:
3713 #if defined(TARGET_MIPS64)
3714 check_insn(env, ctx, ISA_MIPS3);
3715 gen_helper_mtc0_xcontext(t0);
3716 rn = "XContext";
3717 break;
3718 #endif
3719 default:
3720 goto die;
3722 break;
3723 case 21:
3724 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3725 switch (sel) {
3726 case 0:
3727 gen_helper_mtc0_framemask(t0);
3728 rn = "Framemask";
3729 break;
3730 default:
3731 goto die;
3733 break;
3734 case 22:
3735 /* ignored */
3736 rn = "Diagnostic"; /* implementation dependent */
3737 break;
3738 case 23:
3739 switch (sel) {
3740 case 0:
3741 gen_helper_mtc0_debug(t0); /* EJTAG support */
3742 /* BS_STOP isn't good enough here, hflags may have changed. */
3743 gen_save_pc(ctx->pc + 4);
3744 ctx->bstate = BS_EXCP;
3745 rn = "Debug";
3746 break;
3747 case 1:
3748 // gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
3749 rn = "TraceControl";
3750 /* Stop translation as we may have switched the execution mode */
3751 ctx->bstate = BS_STOP;
3752 // break;
3753 case 2:
3754 // gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
3755 rn = "TraceControl2";
3756 /* Stop translation as we may have switched the execution mode */
3757 ctx->bstate = BS_STOP;
3758 // break;
3759 case 3:
3760 /* Stop translation as we may have switched the execution mode */
3761 ctx->bstate = BS_STOP;
3762 // gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
3763 rn = "UserTraceData";
3764 /* Stop translation as we may have switched the execution mode */
3765 ctx->bstate = BS_STOP;
3766 // break;
3767 case 4:
3768 // gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
3769 /* Stop translation as we may have switched the execution mode */
3770 ctx->bstate = BS_STOP;
3771 rn = "TraceBPC";
3772 // break;
3773 default:
3774 goto die;
3776 break;
3777 case 24:
3778 switch (sel) {
3779 case 0:
3780 /* EJTAG support */
3781 gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC));
3782 rn = "DEPC";
3783 break;
3784 default:
3785 goto die;
3787 break;
3788 case 25:
3789 switch (sel) {
3790 case 0:
3791 gen_helper_mtc0_performance0(t0);
3792 rn = "Performance0";
3793 break;
3794 case 1:
3795 // gen_helper_mtc0_performance1(t0);
3796 rn = "Performance1";
3797 // break;
3798 case 2:
3799 // gen_helper_mtc0_performance2(t0);
3800 rn = "Performance2";
3801 // break;
3802 case 3:
3803 // gen_helper_mtc0_performance3(t0);
3804 rn = "Performance3";
3805 // break;
3806 case 4:
3807 // gen_helper_mtc0_performance4(t0);
3808 rn = "Performance4";
3809 // break;
3810 case 5:
3811 // gen_helper_mtc0_performance5(t0);
3812 rn = "Performance5";
3813 // break;
3814 case 6:
3815 // gen_helper_mtc0_performance6(t0);
3816 rn = "Performance6";
3817 // break;
3818 case 7:
3819 // gen_helper_mtc0_performance7(t0);
3820 rn = "Performance7";
3821 // break;
3822 default:
3823 goto die;
3825 break;
3826 case 26:
3827 /* ignored */
3828 rn = "ECC";
3829 break;
3830 case 27:
3831 switch (sel) {
3832 case 0 ... 3:
3833 /* ignored */
3834 rn = "CacheErr";
3835 break;
3836 default:
3837 goto die;
3839 break;
3840 case 28:
3841 switch (sel) {
3842 case 0:
3843 case 2:
3844 case 4:
3845 case 6:
3846 gen_helper_mtc0_taglo(t0);
3847 rn = "TagLo";
3848 break;
3849 case 1:
3850 case 3:
3851 case 5:
3852 case 7:
3853 gen_helper_mtc0_datalo(t0);
3854 rn = "DataLo";
3855 break;
3856 default:
3857 goto die;
3859 break;
3860 case 29:
3861 switch (sel) {
3862 case 0:
3863 case 2:
3864 case 4:
3865 case 6:
3866 gen_helper_mtc0_taghi(t0);
3867 rn = "TagHi";
3868 break;
3869 case 1:
3870 case 3:
3871 case 5:
3872 case 7:
3873 gen_helper_mtc0_datahi(t0);
3874 rn = "DataHi";
3875 break;
3876 default:
3877 rn = "invalid sel";
3878 goto die;
3880 break;
3881 case 30:
3882 switch (sel) {
3883 case 0:
3884 gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC));
3885 rn = "ErrorEPC";
3886 break;
3887 default:
3888 goto die;
3890 break;
3891 case 31:
3892 switch (sel) {
3893 case 0:
3894 /* EJTAG support */
3895 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
3896 rn = "DESAVE";
3897 break;
3898 default:
3899 goto die;
3901 /* Stop translation as we may have switched the execution mode */
3902 ctx->bstate = BS_STOP;
3903 break;
3904 default:
3905 goto die;
3907 #if defined MIPS_DEBUG_DISAS
3908 if (loglevel & CPU_LOG_TB_IN_ASM) {
3909 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3910 rn, reg, sel);
3912 #endif
3913 /* For simplicity assume that all writes can cause interrupts. */
3914 if (use_icount) {
3915 gen_io_end();
3916 ctx->bstate = BS_STOP;
3918 return;
3920 die:
3921 #if defined MIPS_DEBUG_DISAS
3922 if (loglevel & CPU_LOG_TB_IN_ASM) {
3923 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3924 rn, reg, sel);
3926 #endif
3927 generate_exception(ctx, EXCP_RI);
3930 #if defined(TARGET_MIPS64)
3931 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
3933 const char *rn = "invalid";
3935 if (sel != 0)
3936 check_insn(env, ctx, ISA_MIPS64);
3938 switch (reg) {
3939 case 0:
3940 switch (sel) {
3941 case 0:
3942 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
3943 rn = "Index";
3944 break;
3945 case 1:
3946 check_insn(env, ctx, ASE_MT);
3947 gen_helper_mfc0_mvpcontrol(t0);
3948 rn = "MVPControl";
3949 break;
3950 case 2:
3951 check_insn(env, ctx, ASE_MT);
3952 gen_helper_mfc0_mvpconf0(t0);
3953 rn = "MVPConf0";
3954 break;
3955 case 3:
3956 check_insn(env, ctx, ASE_MT);
3957 gen_helper_mfc0_mvpconf1(t0);
3958 rn = "MVPConf1";
3959 break;
3960 default:
3961 goto die;
3963 break;
3964 case 1:
3965 switch (sel) {
3966 case 0:
3967 gen_helper_mfc0_random(t0);
3968 rn = "Random";
3969 break;
3970 case 1:
3971 check_insn(env, ctx, ASE_MT);
3972 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
3973 rn = "VPEControl";
3974 break;
3975 case 2:
3976 check_insn(env, ctx, ASE_MT);
3977 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
3978 rn = "VPEConf0";
3979 break;
3980 case 3:
3981 check_insn(env, ctx, ASE_MT);
3982 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
3983 rn = "VPEConf1";
3984 break;
3985 case 4:
3986 check_insn(env, ctx, ASE_MT);
3987 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask));
3988 rn = "YQMask";
3989 break;
3990 case 5:
3991 check_insn(env, ctx, ASE_MT);
3992 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
3993 rn = "VPESchedule";
3994 break;
3995 case 6:
3996 check_insn(env, ctx, ASE_MT);
3997 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
3998 rn = "VPEScheFBack";
3999 break;
4000 case 7:
4001 check_insn(env, ctx, ASE_MT);
4002 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
4003 rn = "VPEOpt";
4004 break;
4005 default:
4006 goto die;
4008 break;
4009 case 2:
4010 switch (sel) {
4011 case 0:
4012 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4013 rn = "EntryLo0";
4014 break;
4015 case 1:
4016 check_insn(env, ctx, ASE_MT);
4017 gen_helper_mfc0_tcstatus(t0);
4018 rn = "TCStatus";
4019 break;
4020 case 2:
4021 check_insn(env, ctx, ASE_MT);
4022 gen_helper_mfc0_tcbind(t0);
4023 rn = "TCBind";
4024 break;
4025 case 3:
4026 check_insn(env, ctx, ASE_MT);
4027 gen_helper_dmfc0_tcrestart(t0);
4028 rn = "TCRestart";
4029 break;
4030 case 4:
4031 check_insn(env, ctx, ASE_MT);
4032 gen_helper_dmfc0_tchalt(t0);
4033 rn = "TCHalt";
4034 break;
4035 case 5:
4036 check_insn(env, ctx, ASE_MT);
4037 gen_helper_dmfc0_tccontext(t0);
4038 rn = "TCContext";
4039 break;
4040 case 6:
4041 check_insn(env, ctx, ASE_MT);
4042 gen_helper_dmfc0_tcschedule(t0);
4043 rn = "TCSchedule";
4044 break;
4045 case 7:
4046 check_insn(env, ctx, ASE_MT);
4047 gen_helper_dmfc0_tcschefback(t0);
4048 rn = "TCScheFBack";
4049 break;
4050 default:
4051 goto die;
4053 break;
4054 case 3:
4055 switch (sel) {
4056 case 0:
4057 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4058 rn = "EntryLo1";
4059 break;
4060 default:
4061 goto die;
4063 break;
4064 case 4:
4065 switch (sel) {
4066 case 0:
4067 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
4068 rn = "Context";
4069 break;
4070 case 1:
4071 // gen_helper_dmfc0_contextconfig(t0); /* SmartMIPS ASE */
4072 rn = "ContextConfig";
4073 // break;
4074 default:
4075 goto die;
4077 break;
4078 case 5:
4079 switch (sel) {
4080 case 0:
4081 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
4082 rn = "PageMask";
4083 break;
4084 case 1:
4085 check_insn(env, ctx, ISA_MIPS32R2);
4086 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
4087 rn = "PageGrain";
4088 break;
4089 default:
4090 goto die;
4092 break;
4093 case 6:
4094 switch (sel) {
4095 case 0:
4096 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
4097 rn = "Wired";
4098 break;
4099 case 1:
4100 check_insn(env, ctx, ISA_MIPS32R2);
4101 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
4102 rn = "SRSConf0";
4103 break;
4104 case 2:
4105 check_insn(env, ctx, ISA_MIPS32R2);
4106 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
4107 rn = "SRSConf1";
4108 break;
4109 case 3:
4110 check_insn(env, ctx, ISA_MIPS32R2);
4111 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
4112 rn = "SRSConf2";
4113 break;
4114 case 4:
4115 check_insn(env, ctx, ISA_MIPS32R2);
4116 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
4117 rn = "SRSConf3";
4118 break;
4119 case 5:
4120 check_insn(env, ctx, ISA_MIPS32R2);
4121 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
4122 rn = "SRSConf4";
4123 break;
4124 default:
4125 goto die;
4127 break;
4128 case 7:
4129 switch (sel) {
4130 case 0:
4131 check_insn(env, ctx, ISA_MIPS32R2);
4132 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
4133 rn = "HWREna";
4134 break;
4135 default:
4136 goto die;
4138 break;
4139 case 8:
4140 switch (sel) {
4141 case 0:
4142 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4143 rn = "BadVAddr";
4144 break;
4145 default:
4146 goto die;
4148 break;
4149 case 9:
4150 switch (sel) {
4151 case 0:
4152 /* Mark as an IO operation because we read the time. */
4153 if (use_icount)
4154 gen_io_start();
4155 gen_helper_mfc0_count(t0);
4156 if (use_icount) {
4157 gen_io_end();
4158 ctx->bstate = BS_STOP;
4160 rn = "Count";
4161 break;
4162 /* 6,7 are implementation dependent */
4163 default:
4164 goto die;
4166 break;
4167 case 10:
4168 switch (sel) {
4169 case 0:
4170 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
4171 rn = "EntryHi";
4172 break;
4173 default:
4174 goto die;
4176 break;
4177 case 11:
4178 switch (sel) {
4179 case 0:
4180 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
4181 rn = "Compare";
4182 break;
4183 /* 6,7 are implementation dependent */
4184 default:
4185 goto die;
4187 break;
4188 case 12:
4189 switch (sel) {
4190 case 0:
4191 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
4192 rn = "Status";
4193 break;
4194 case 1:
4195 check_insn(env, ctx, ISA_MIPS32R2);
4196 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
4197 rn = "IntCtl";
4198 break;
4199 case 2:
4200 check_insn(env, ctx, ISA_MIPS32R2);
4201 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
4202 rn = "SRSCtl";
4203 break;
4204 case 3:
4205 check_insn(env, ctx, ISA_MIPS32R2);
4206 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
4207 rn = "SRSMap";
4208 break;
4209 default:
4210 goto die;
4212 break;
4213 case 13:
4214 switch (sel) {
4215 case 0:
4216 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
4217 rn = "Cause";
4218 break;
4219 default:
4220 goto die;
4222 break;
4223 case 14:
4224 switch (sel) {
4225 case 0:
4226 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4227 rn = "EPC";
4228 break;
4229 default:
4230 goto die;
4232 break;
4233 case 15:
4234 switch (sel) {
4235 case 0:
4236 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
4237 rn = "PRid";
4238 break;
4239 case 1:
4240 check_insn(env, ctx, ISA_MIPS32R2);
4241 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
4242 rn = "EBase";
4243 break;
4244 default:
4245 goto die;
4247 break;
4248 case 16:
4249 switch (sel) {
4250 case 0:
4251 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
4252 rn = "Config";
4253 break;
4254 case 1:
4255 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
4256 rn = "Config1";
4257 break;
4258 case 2:
4259 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
4260 rn = "Config2";
4261 break;
4262 case 3:
4263 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
4264 rn = "Config3";
4265 break;
4266 /* 6,7 are implementation dependent */
4267 case 6:
4268 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
4269 rn = "Config6";
4270 break;
4271 case 7:
4272 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
4273 rn = "Config7";
4274 break;
4275 default:
4276 goto die;
4278 break;
4279 case 17:
4280 switch (sel) {
4281 case 0:
4282 gen_helper_dmfc0_lladdr(t0);
4283 rn = "LLAddr";
4284 break;
4285 default:
4286 goto die;
4288 break;
4289 case 18:
4290 switch (sel) {
4291 case 0 ... 7:
4292 gen_helper_1i(dmfc0_watchlo, t0, sel);
4293 rn = "WatchLo";
4294 break;
4295 default:
4296 goto die;
4298 break;
4299 case 19:
4300 switch (sel) {
4301 case 0 ... 7:
4302 gen_helper_1i(mfc0_watchhi, t0, sel);
4303 rn = "WatchHi";
4304 break;
4305 default:
4306 goto die;
4308 break;
4309 case 20:
4310 switch (sel) {
4311 case 0:
4312 check_insn(env, ctx, ISA_MIPS3);
4313 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
4314 rn = "XContext";
4315 break;
4316 default:
4317 goto die;
4319 break;
4320 case 21:
4321 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4322 switch (sel) {
4323 case 0:
4324 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
4325 rn = "Framemask";
4326 break;
4327 default:
4328 goto die;
4330 break;
4331 case 22:
4332 tcg_gen_movi_tl(t0, 0); /* unimplemented */
4333 rn = "'Diagnostic"; /* implementation dependent */
4334 break;
4335 case 23:
4336 switch (sel) {
4337 case 0:
4338 gen_helper_mfc0_debug(t0); /* EJTAG support */
4339 rn = "Debug";
4340 break;
4341 case 1:
4342 // gen_helper_dmfc0_tracecontrol(t0); /* PDtrace support */
4343 rn = "TraceControl";
4344 // break;
4345 case 2:
4346 // gen_helper_dmfc0_tracecontrol2(t0); /* PDtrace support */
4347 rn = "TraceControl2";
4348 // break;
4349 case 3:
4350 // gen_helper_dmfc0_usertracedata(t0); /* PDtrace support */
4351 rn = "UserTraceData";
4352 // break;
4353 case 4:
4354 // gen_helper_dmfc0_tracebpc(t0); /* PDtrace support */
4355 rn = "TraceBPC";
4356 // break;
4357 default:
4358 goto die;
4360 break;
4361 case 24:
4362 switch (sel) {
4363 case 0:
4364 /* EJTAG support */
4365 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
4366 rn = "DEPC";
4367 break;
4368 default:
4369 goto die;
4371 break;
4372 case 25:
4373 switch (sel) {
4374 case 0:
4375 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
4376 rn = "Performance0";
4377 break;
4378 case 1:
4379 // gen_helper_dmfc0_performance1(t0);
4380 rn = "Performance1";
4381 // break;
4382 case 2:
4383 // gen_helper_dmfc0_performance2(t0);
4384 rn = "Performance2";
4385 // break;
4386 case 3:
4387 // gen_helper_dmfc0_performance3(t0);
4388 rn = "Performance3";
4389 // break;
4390 case 4:
4391 // gen_helper_dmfc0_performance4(t0);
4392 rn = "Performance4";
4393 // break;
4394 case 5:
4395 // gen_helper_dmfc0_performance5(t0);
4396 rn = "Performance5";
4397 // break;
4398 case 6:
4399 // gen_helper_dmfc0_performance6(t0);
4400 rn = "Performance6";
4401 // break;
4402 case 7:
4403 // gen_helper_dmfc0_performance7(t0);
4404 rn = "Performance7";
4405 // break;
4406 default:
4407 goto die;
4409 break;
4410 case 26:
4411 tcg_gen_movi_tl(t0, 0); /* unimplemented */
4412 rn = "ECC";
4413 break;
4414 case 27:
4415 switch (sel) {
4416 /* ignored */
4417 case 0 ... 3:
4418 tcg_gen_movi_tl(t0, 0); /* unimplemented */
4419 rn = "CacheErr";
4420 break;
4421 default:
4422 goto die;
4424 break;
4425 case 28:
4426 switch (sel) {
4427 case 0:
4428 case 2:
4429 case 4:
4430 case 6:
4431 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
4432 rn = "TagLo";
4433 break;
4434 case 1:
4435 case 3:
4436 case 5:
4437 case 7:
4438 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
4439 rn = "DataLo";
4440 break;
4441 default:
4442 goto die;
4444 break;
4445 case 29:
4446 switch (sel) {
4447 case 0:
4448 case 2:
4449 case 4:
4450 case 6:
4451 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
4452 rn = "TagHi";
4453 break;
4454 case 1:
4455 case 3:
4456 case 5:
4457 case 7:
4458 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
4459 rn = "DataHi";
4460 break;
4461 default:
4462 goto die;
4464 break;
4465 case 30:
4466 switch (sel) {
4467 case 0:
4468 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4469 rn = "ErrorEPC";
4470 break;
4471 default:
4472 goto die;
4474 break;
4475 case 31:
4476 switch (sel) {
4477 case 0:
4478 /* EJTAG support */
4479 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
4480 rn = "DESAVE";
4481 break;
4482 default:
4483 goto die;
4485 break;
4486 default:
4487 goto die;
4489 #if defined MIPS_DEBUG_DISAS
4490 if (loglevel & CPU_LOG_TB_IN_ASM) {
4491 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4492 rn, reg, sel);
4494 #endif
4495 return;
4497 die:
4498 #if defined MIPS_DEBUG_DISAS
4499 if (loglevel & CPU_LOG_TB_IN_ASM) {
4500 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4501 rn, reg, sel);
4503 #endif
4504 generate_exception(ctx, EXCP_RI);
4507 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
4509 const char *rn = "invalid";
4511 if (sel != 0)
4512 check_insn(env, ctx, ISA_MIPS64);
4514 if (use_icount)
4515 gen_io_start();
4517 switch (reg) {
4518 case 0:
4519 switch (sel) {
4520 case 0:
4521 gen_helper_mtc0_index(t0);
4522 rn = "Index";
4523 break;
4524 case 1:
4525 check_insn(env, ctx, ASE_MT);
4526 gen_helper_mtc0_mvpcontrol(t0);
4527 rn = "MVPControl";
4528 break;
4529 case 2:
4530 check_insn(env, ctx, ASE_MT);
4531 /* ignored */
4532 rn = "MVPConf0";
4533 break;
4534 case 3:
4535 check_insn(env, ctx, ASE_MT);
4536 /* ignored */
4537 rn = "MVPConf1";
4538 break;
4539 default:
4540 goto die;
4542 break;
4543 case 1:
4544 switch (sel) {
4545 case 0:
4546 /* ignored */
4547 rn = "Random";
4548 break;
4549 case 1:
4550 check_insn(env, ctx, ASE_MT);
4551 gen_helper_mtc0_vpecontrol(t0);
4552 rn = "VPEControl";
4553 break;
4554 case 2:
4555 check_insn(env, ctx, ASE_MT);
4556 gen_helper_mtc0_vpeconf0(t0);
4557 rn = "VPEConf0";
4558 break;
4559 case 3:
4560 check_insn(env, ctx, ASE_MT);
4561 gen_helper_mtc0_vpeconf1(t0);
4562 rn = "VPEConf1";
4563 break;
4564 case 4:
4565 check_insn(env, ctx, ASE_MT);
4566 gen_helper_mtc0_yqmask(t0);
4567 rn = "YQMask";
4568 break;
4569 case 5:
4570 check_insn(env, ctx, ASE_MT);
4571 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4572 rn = "VPESchedule";
4573 break;
4574 case 6:
4575 check_insn(env, ctx, ASE_MT);
4576 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4577 rn = "VPEScheFBack";
4578 break;
4579 case 7:
4580 check_insn(env, ctx, ASE_MT);
4581 gen_helper_mtc0_vpeopt(t0);
4582 rn = "VPEOpt";
4583 break;
4584 default:
4585 goto die;
4587 break;
4588 case 2:
4589 switch (sel) {
4590 case 0:
4591 gen_helper_mtc0_entrylo0(t0);
4592 rn = "EntryLo0";
4593 break;
4594 case 1:
4595 check_insn(env, ctx, ASE_MT);
4596 gen_helper_mtc0_tcstatus(t0);
4597 rn = "TCStatus";
4598 break;
4599 case 2:
4600 check_insn(env, ctx, ASE_MT);
4601 gen_helper_mtc0_tcbind(t0);
4602 rn = "TCBind";
4603 break;
4604 case 3:
4605 check_insn(env, ctx, ASE_MT);
4606 gen_helper_mtc0_tcrestart(t0);
4607 rn = "TCRestart";
4608 break;
4609 case 4:
4610 check_insn(env, ctx, ASE_MT);
4611 gen_helper_mtc0_tchalt(t0);
4612 rn = "TCHalt";
4613 break;
4614 case 5:
4615 check_insn(env, ctx, ASE_MT);
4616 gen_helper_mtc0_tccontext(t0);
4617 rn = "TCContext";
4618 break;
4619 case 6:
4620 check_insn(env, ctx, ASE_MT);
4621 gen_helper_mtc0_tcschedule(t0);
4622 rn = "TCSchedule";
4623 break;
4624 case 7:
4625 check_insn(env, ctx, ASE_MT);
4626 gen_helper_mtc0_tcschefback(t0);
4627 rn = "TCScheFBack";
4628 break;
4629 default:
4630 goto die;
4632 break;
4633 case 3:
4634 switch (sel) {
4635 case 0:
4636 gen_helper_mtc0_entrylo1(t0);
4637 rn = "EntryLo1";
4638 break;
4639 default:
4640 goto die;
4642 break;
4643 case 4:
4644 switch (sel) {
4645 case 0:
4646 gen_helper_mtc0_context(t0);
4647 rn = "Context";
4648 break;
4649 case 1:
4650 // gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
4651 rn = "ContextConfig";
4652 // break;
4653 default:
4654 goto die;
4656 break;
4657 case 5:
4658 switch (sel) {
4659 case 0:
4660 gen_helper_mtc0_pagemask(t0);
4661 rn = "PageMask";
4662 break;
4663 case 1:
4664 check_insn(env, ctx, ISA_MIPS32R2);
4665 gen_helper_mtc0_pagegrain(t0);
4666 rn = "PageGrain";
4667 break;
4668 default:
4669 goto die;
4671 break;
4672 case 6:
4673 switch (sel) {
4674 case 0:
4675 gen_helper_mtc0_wired(t0);
4676 rn = "Wired";
4677 break;
4678 case 1:
4679 check_insn(env, ctx, ISA_MIPS32R2);
4680 gen_helper_mtc0_srsconf0(t0);
4681 rn = "SRSConf0";
4682 break;
4683 case 2:
4684 check_insn(env, ctx, ISA_MIPS32R2);
4685 gen_helper_mtc0_srsconf1(t0);
4686 rn = "SRSConf1";
4687 break;
4688 case 3:
4689 check_insn(env, ctx, ISA_MIPS32R2);
4690 gen_helper_mtc0_srsconf2(t0);
4691 rn = "SRSConf2";
4692 break;
4693 case 4:
4694 check_insn(env, ctx, ISA_MIPS32R2);
4695 gen_helper_mtc0_srsconf3(t0);
4696 rn = "SRSConf3";
4697 break;
4698 case 5:
4699 check_insn(env, ctx, ISA_MIPS32R2);
4700 gen_helper_mtc0_srsconf4(t0);
4701 rn = "SRSConf4";
4702 break;
4703 default:
4704 goto die;
4706 break;
4707 case 7:
4708 switch (sel) {
4709 case 0:
4710 check_insn(env, ctx, ISA_MIPS32R2);
4711 gen_helper_mtc0_hwrena(t0);
4712 rn = "HWREna";
4713 break;
4714 default:
4715 goto die;
4717 break;
4718 case 8:
4719 /* ignored */
4720 rn = "BadVAddr";
4721 break;
4722 case 9:
4723 switch (sel) {
4724 case 0:
4725 gen_helper_mtc0_count(t0);
4726 rn = "Count";
4727 break;
4728 /* 6,7 are implementation dependent */
4729 default:
4730 goto die;
4732 /* Stop translation as we may have switched the execution mode */
4733 ctx->bstate = BS_STOP;
4734 break;
4735 case 10:
4736 switch (sel) {
4737 case 0:
4738 gen_helper_mtc0_entryhi(t0);
4739 rn = "EntryHi";
4740 break;
4741 default:
4742 goto die;
4744 break;
4745 case 11:
4746 switch (sel) {
4747 case 0:
4748 gen_helper_mtc0_compare(t0);
4749 rn = "Compare";
4750 break;
4751 /* 6,7 are implementation dependent */
4752 default:
4753 goto die;
4755 /* Stop translation as we may have switched the execution mode */
4756 ctx->bstate = BS_STOP;
4757 break;
4758 case 12:
4759 switch (sel) {
4760 case 0:
4761 gen_helper_mtc0_status(t0);
4762 /* BS_STOP isn't good enough here, hflags may have changed. */
4763 gen_save_pc(ctx->pc + 4);
4764 ctx->bstate = BS_EXCP;
4765 rn = "Status";
4766 break;
4767 case 1:
4768 check_insn(env, ctx, ISA_MIPS32R2);
4769 gen_helper_mtc0_intctl(t0);
4770 /* Stop translation as we may have switched the execution mode */
4771 ctx->bstate = BS_STOP;
4772 rn = "IntCtl";
4773 break;
4774 case 2:
4775 check_insn(env, ctx, ISA_MIPS32R2);
4776 gen_helper_mtc0_srsctl(t0);
4777 /* Stop translation as we may have switched the execution mode */
4778 ctx->bstate = BS_STOP;
4779 rn = "SRSCtl";
4780 break;
4781 case 3:
4782 check_insn(env, ctx, ISA_MIPS32R2);
4783 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
4784 /* Stop translation as we may have switched the execution mode */
4785 ctx->bstate = BS_STOP;
4786 rn = "SRSMap";
4787 break;
4788 default:
4789 goto die;
4791 break;
4792 case 13:
4793 switch (sel) {
4794 case 0:
4795 gen_helper_mtc0_cause(t0);
4796 rn = "Cause";
4797 break;
4798 default:
4799 goto die;
4801 /* Stop translation as we may have switched the execution mode */
4802 ctx->bstate = BS_STOP;
4803 break;
4804 case 14:
4805 switch (sel) {
4806 case 0:
4807 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4808 rn = "EPC";
4809 break;
4810 default:
4811 goto die;
4813 break;
4814 case 15:
4815 switch (sel) {
4816 case 0:
4817 /* ignored */
4818 rn = "PRid";
4819 break;
4820 case 1:
4821 check_insn(env, ctx, ISA_MIPS32R2);
4822 gen_helper_mtc0_ebase(t0);
4823 rn = "EBase";
4824 break;
4825 default:
4826 goto die;
4828 break;
4829 case 16:
4830 switch (sel) {
4831 case 0:
4832 gen_helper_mtc0_config0(t0);
4833 rn = "Config";
4834 /* Stop translation as we may have switched the execution mode */
4835 ctx->bstate = BS_STOP;
4836 break;
4837 case 1:
4838 /* ignored */
4839 rn = "Config1";
4840 break;
4841 case 2:
4842 gen_helper_mtc0_config2(t0);
4843 rn = "Config2";
4844 /* Stop translation as we may have switched the execution mode */
4845 ctx->bstate = BS_STOP;
4846 break;
4847 case 3:
4848 /* ignored */
4849 rn = "Config3";
4850 break;
4851 /* 6,7 are implementation dependent */
4852 default:
4853 rn = "Invalid config selector";
4854 goto die;
4856 break;
4857 case 17:
4858 switch (sel) {
4859 case 0:
4860 /* ignored */
4861 rn = "LLAddr";
4862 break;
4863 default:
4864 goto die;
4866 break;
4867 case 18:
4868 switch (sel) {
4869 case 0 ... 7:
4870 gen_helper_1i(mtc0_watchlo, t0, sel);
4871 rn = "WatchLo";
4872 break;
4873 default:
4874 goto die;
4876 break;
4877 case 19:
4878 switch (sel) {
4879 case 0 ... 7:
4880 gen_helper_1i(mtc0_watchhi, t0, sel);
4881 rn = "WatchHi";
4882 break;
4883 default:
4884 goto die;
4886 break;
4887 case 20:
4888 switch (sel) {
4889 case 0:
4890 check_insn(env, ctx, ISA_MIPS3);
4891 gen_helper_mtc0_xcontext(t0);
4892 rn = "XContext";
4893 break;
4894 default:
4895 goto die;
4897 break;
4898 case 21:
4899 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4900 switch (sel) {
4901 case 0:
4902 gen_helper_mtc0_framemask(t0);
4903 rn = "Framemask";
4904 break;
4905 default:
4906 goto die;
4908 break;
4909 case 22:
4910 /* ignored */
4911 rn = "Diagnostic"; /* implementation dependent */
4912 break;
4913 case 23:
4914 switch (sel) {
4915 case 0:
4916 gen_helper_mtc0_debug(t0); /* EJTAG support */
4917 /* BS_STOP isn't good enough here, hflags may have changed. */
4918 gen_save_pc(ctx->pc + 4);
4919 ctx->bstate = BS_EXCP;
4920 rn = "Debug";
4921 break;
4922 case 1:
4923 // gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
4924 /* Stop translation as we may have switched the execution mode */
4925 ctx->bstate = BS_STOP;
4926 rn = "TraceControl";
4927 // break;
4928 case 2:
4929 // gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
4930 /* Stop translation as we may have switched the execution mode */
4931 ctx->bstate = BS_STOP;
4932 rn = "TraceControl2";
4933 // break;
4934 case 3:
4935 // gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
4936 /* Stop translation as we may have switched the execution mode */
4937 ctx->bstate = BS_STOP;
4938 rn = "UserTraceData";
4939 // break;
4940 case 4:
4941 // gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
4942 /* Stop translation as we may have switched the execution mode */
4943 ctx->bstate = BS_STOP;
4944 rn = "TraceBPC";
4945 // break;
4946 default:
4947 goto die;
4949 break;
4950 case 24:
4951 switch (sel) {
4952 case 0:
4953 /* EJTAG support */
4954 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
4955 rn = "DEPC";
4956 break;
4957 default:
4958 goto die;
4960 break;
4961 case 25:
4962 switch (sel) {
4963 case 0:
4964 gen_helper_mtc0_performance0(t0);
4965 rn = "Performance0";
4966 break;
4967 case 1:
4968 // gen_helper_mtc0_performance1(t0);
4969 rn = "Performance1";
4970 // break;
4971 case 2:
4972 // gen_helper_mtc0_performance2(t0);
4973 rn = "Performance2";
4974 // break;
4975 case 3:
4976 // gen_helper_mtc0_performance3(t0);
4977 rn = "Performance3";
4978 // break;
4979 case 4:
4980 // gen_helper_mtc0_performance4(t0);
4981 rn = "Performance4";
4982 // break;
4983 case 5:
4984 // gen_helper_mtc0_performance5(t0);
4985 rn = "Performance5";
4986 // break;
4987 case 6:
4988 // gen_helper_mtc0_performance6(t0);
4989 rn = "Performance6";
4990 // break;
4991 case 7:
4992 // gen_helper_mtc0_performance7(t0);
4993 rn = "Performance7";
4994 // break;
4995 default:
4996 goto die;
4998 break;
4999 case 26:
5000 /* ignored */
5001 rn = "ECC";
5002 break;
5003 case 27:
5004 switch (sel) {
5005 case 0 ... 3:
5006 /* ignored */
5007 rn = "CacheErr";
5008 break;
5009 default:
5010 goto die;
5012 break;
5013 case 28:
5014 switch (sel) {
5015 case 0:
5016 case 2:
5017 case 4:
5018 case 6:
5019 gen_helper_mtc0_taglo(t0);
5020 rn = "TagLo";
5021 break;
5022 case 1:
5023 case 3:
5024 case 5:
5025 case 7:
5026 gen_helper_mtc0_datalo(t0);
5027 rn = "DataLo";
5028 break;
5029 default:
5030 goto die;
5032 break;
5033 case 29:
5034 switch (sel) {
5035 case 0:
5036 case 2:
5037 case 4:
5038 case 6:
5039 gen_helper_mtc0_taghi(t0);
5040 rn = "TagHi";
5041 break;
5042 case 1:
5043 case 3:
5044 case 5:
5045 case 7:
5046 gen_helper_mtc0_datahi(t0);
5047 rn = "DataHi";
5048 break;
5049 default:
5050 rn = "invalid sel";
5051 goto die;
5053 break;
5054 case 30:
5055 switch (sel) {
5056 case 0:
5057 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5058 rn = "ErrorEPC";
5059 break;
5060 default:
5061 goto die;
5063 break;
5064 case 31:
5065 switch (sel) {
5066 case 0:
5067 /* EJTAG support */
5068 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
5069 rn = "DESAVE";
5070 break;
5071 default:
5072 goto die;
5074 /* Stop translation as we may have switched the execution mode */
5075 ctx->bstate = BS_STOP;
5076 break;
5077 default:
5078 goto die;
5080 #if defined MIPS_DEBUG_DISAS
5081 if (loglevel & CPU_LOG_TB_IN_ASM) {
5082 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5083 rn, reg, sel);
5085 #endif
5086 /* For simplicity assume that all writes can cause interrupts. */
5087 if (use_icount) {
5088 gen_io_end();
5089 ctx->bstate = BS_STOP;
5091 return;
5093 die:
5094 #if defined MIPS_DEBUG_DISAS
5095 if (loglevel & CPU_LOG_TB_IN_ASM) {
5096 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5097 rn, reg, sel);
5099 #endif
5100 generate_exception(ctx, EXCP_RI);
5102 #endif /* TARGET_MIPS64 */
5104 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5105 int u, int sel, int h)
5107 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5108 TCGv t0 = tcg_temp_local_new();
5110 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5111 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5112 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5113 tcg_gen_movi_tl(t0, -1);
5114 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5115 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5116 tcg_gen_movi_tl(t0, -1);
5117 else if (u == 0) {
5118 switch (rt) {
5119 case 2:
5120 switch (sel) {
5121 case 1:
5122 gen_helper_mftc0_tcstatus(t0);
5123 break;
5124 case 2:
5125 gen_helper_mftc0_tcbind(t0);
5126 break;
5127 case 3:
5128 gen_helper_mftc0_tcrestart(t0);
5129 break;
5130 case 4:
5131 gen_helper_mftc0_tchalt(t0);
5132 break;
5133 case 5:
5134 gen_helper_mftc0_tccontext(t0);
5135 break;
5136 case 6:
5137 gen_helper_mftc0_tcschedule(t0);
5138 break;
5139 case 7:
5140 gen_helper_mftc0_tcschefback(t0);
5141 break;
5142 default:
5143 gen_mfc0(env, ctx, t0, rt, sel);
5144 break;
5146 break;
5147 case 10:
5148 switch (sel) {
5149 case 0:
5150 gen_helper_mftc0_entryhi(t0);
5151 break;
5152 default:
5153 gen_mfc0(env, ctx, t0, rt, sel);
5154 break;
5156 case 12:
5157 switch (sel) {
5158 case 0:
5159 gen_helper_mftc0_status(t0);
5160 break;
5161 default:
5162 gen_mfc0(env, ctx, t0, rt, sel);
5163 break;
5165 case 23:
5166 switch (sel) {
5167 case 0:
5168 gen_helper_mftc0_debug(t0);
5169 break;
5170 default:
5171 gen_mfc0(env, ctx, t0, rt, sel);
5172 break;
5174 break;
5175 default:
5176 gen_mfc0(env, ctx, t0, rt, sel);
5178 } else switch (sel) {
5179 /* GPR registers. */
5180 case 0:
5181 gen_helper_1i(mftgpr, t0, rt);
5182 break;
5183 /* Auxiliary CPU registers */
5184 case 1:
5185 switch (rt) {
5186 case 0:
5187 gen_helper_1i(mftlo, t0, 0);
5188 break;
5189 case 1:
5190 gen_helper_1i(mfthi, t0, 0);
5191 break;
5192 case 2:
5193 gen_helper_1i(mftacx, t0, 0);
5194 break;
5195 case 4:
5196 gen_helper_1i(mftlo, t0, 1);
5197 break;
5198 case 5:
5199 gen_helper_1i(mfthi, t0, 1);
5200 break;
5201 case 6:
5202 gen_helper_1i(mftacx, t0, 1);
5203 break;
5204 case 8:
5205 gen_helper_1i(mftlo, t0, 2);
5206 break;
5207 case 9:
5208 gen_helper_1i(mfthi, t0, 2);
5209 break;
5210 case 10:
5211 gen_helper_1i(mftacx, t0, 2);
5212 break;
5213 case 12:
5214 gen_helper_1i(mftlo, t0, 3);
5215 break;
5216 case 13:
5217 gen_helper_1i(mfthi, t0, 3);
5218 break;
5219 case 14:
5220 gen_helper_1i(mftacx, t0, 3);
5221 break;
5222 case 16:
5223 gen_helper_mftdsp(t0);
5224 break;
5225 default:
5226 goto die;
5228 break;
5229 /* Floating point (COP1). */
5230 case 2:
5231 /* XXX: For now we support only a single FPU context. */
5232 if (h == 0) {
5233 TCGv_i32 fp0 = tcg_temp_new_i32();
5235 gen_load_fpr32(fp0, rt);
5236 tcg_gen_ext_i32_tl(t0, fp0);
5237 tcg_temp_free_i32(fp0);
5238 } else {
5239 TCGv_i32 fp0 = tcg_temp_new_i32();
5241 gen_load_fpr32h(fp0, rt);
5242 tcg_gen_ext_i32_tl(t0, fp0);
5243 tcg_temp_free_i32(fp0);
5245 break;
5246 case 3:
5247 /* XXX: For now we support only a single FPU context. */
5248 gen_helper_1i(cfc1, t0, rt);
5249 break;
5250 /* COP2: Not implemented. */
5251 case 4:
5252 case 5:
5253 /* fall through */
5254 default:
5255 goto die;
5257 #if defined MIPS_DEBUG_DISAS
5258 if (loglevel & CPU_LOG_TB_IN_ASM) {
5259 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5260 rt, u, sel, h);
5262 #endif
5263 gen_store_gpr(t0, rd);
5264 tcg_temp_free(t0);
5265 return;
5267 die:
5268 tcg_temp_free(t0);
5269 #if defined MIPS_DEBUG_DISAS
5270 if (loglevel & CPU_LOG_TB_IN_ASM) {
5271 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5272 rt, u, sel, h);
5274 #endif
5275 generate_exception(ctx, EXCP_RI);
5278 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5279 int u, int sel, int h)
5281 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5282 TCGv t0 = tcg_temp_local_new();
5284 gen_load_gpr(t0, rt);
5285 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5286 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5287 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5288 /* NOP */ ;
5289 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5290 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5291 /* NOP */ ;
5292 else if (u == 0) {
5293 switch (rd) {
5294 case 2:
5295 switch (sel) {
5296 case 1:
5297 gen_helper_mttc0_tcstatus(t0);
5298 break;
5299 case 2:
5300 gen_helper_mttc0_tcbind(t0);
5301 break;
5302 case 3:
5303 gen_helper_mttc0_tcrestart(t0);
5304 break;
5305 case 4:
5306 gen_helper_mttc0_tchalt(t0);
5307 break;
5308 case 5:
5309 gen_helper_mttc0_tccontext(t0);
5310 break;
5311 case 6:
5312 gen_helper_mttc0_tcschedule(t0);
5313 break;
5314 case 7:
5315 gen_helper_mttc0_tcschefback(t0);
5316 break;
5317 default:
5318 gen_mtc0(env, ctx, t0, rd, sel);
5319 break;
5321 break;
5322 case 10:
5323 switch (sel) {
5324 case 0:
5325 gen_helper_mttc0_entryhi(t0);
5326 break;
5327 default:
5328 gen_mtc0(env, ctx, t0, rd, sel);
5329 break;
5331 case 12:
5332 switch (sel) {
5333 case 0:
5334 gen_helper_mttc0_status(t0);
5335 break;
5336 default:
5337 gen_mtc0(env, ctx, t0, rd, sel);
5338 break;
5340 case 23:
5341 switch (sel) {
5342 case 0:
5343 gen_helper_mttc0_debug(t0);
5344 break;
5345 default:
5346 gen_mtc0(env, ctx, t0, rd, sel);
5347 break;
5349 break;
5350 default:
5351 gen_mtc0(env, ctx, t0, rd, sel);
5353 } else switch (sel) {
5354 /* GPR registers. */
5355 case 0:
5356 gen_helper_1i(mttgpr, t0, rd);
5357 break;
5358 /* Auxiliary CPU registers */
5359 case 1:
5360 switch (rd) {
5361 case 0:
5362 gen_helper_1i(mttlo, t0, 0);
5363 break;
5364 case 1:
5365 gen_helper_1i(mtthi, t0, 0);
5366 break;
5367 case 2:
5368 gen_helper_1i(mttacx, t0, 0);
5369 break;
5370 case 4:
5371 gen_helper_1i(mttlo, t0, 1);
5372 break;
5373 case 5:
5374 gen_helper_1i(mtthi, t0, 1);
5375 break;
5376 case 6:
5377 gen_helper_1i(mttacx, t0, 1);
5378 break;
5379 case 8:
5380 gen_helper_1i(mttlo, t0, 2);
5381 break;
5382 case 9:
5383 gen_helper_1i(mtthi, t0, 2);
5384 break;
5385 case 10:
5386 gen_helper_1i(mttacx, t0, 2);
5387 break;
5388 case 12:
5389 gen_helper_1i(mttlo, t0, 3);
5390 break;
5391 case 13:
5392 gen_helper_1i(mtthi, t0, 3);
5393 break;
5394 case 14:
5395 gen_helper_1i(mttacx, t0, 3);
5396 break;
5397 case 16:
5398 gen_helper_mttdsp(t0);
5399 break;
5400 default:
5401 goto die;
5403 break;
5404 /* Floating point (COP1). */
5405 case 2:
5406 /* XXX: For now we support only a single FPU context. */
5407 if (h == 0) {
5408 TCGv_i32 fp0 = tcg_temp_new_i32();
5410 tcg_gen_trunc_tl_i32(fp0, t0);
5411 gen_store_fpr32(fp0, rd);
5412 tcg_temp_free_i32(fp0);
5413 } else {
5414 TCGv_i32 fp0 = tcg_temp_new_i32();
5416 tcg_gen_trunc_tl_i32(fp0, t0);
5417 gen_store_fpr32h(fp0, rd);
5418 tcg_temp_free_i32(fp0);
5420 break;
5421 case 3:
5422 /* XXX: For now we support only a single FPU context. */
5423 gen_helper_1i(ctc1, t0, rd);
5424 break;
5425 /* COP2: Not implemented. */
5426 case 4:
5427 case 5:
5428 /* fall through */
5429 default:
5430 goto die;
5432 #if defined MIPS_DEBUG_DISAS
5433 if (loglevel & CPU_LOG_TB_IN_ASM) {
5434 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5435 rd, u, sel, h);
5437 #endif
5438 tcg_temp_free(t0);
5439 return;
5441 die:
5442 tcg_temp_free(t0);
5443 #if defined MIPS_DEBUG_DISAS
5444 if (loglevel & CPU_LOG_TB_IN_ASM) {
5445 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5446 rd, u, sel, h);
5448 #endif
5449 generate_exception(ctx, EXCP_RI);
5452 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5454 const char *opn = "ldst";
5456 switch (opc) {
5457 case OPC_MFC0:
5458 if (rt == 0) {
5459 /* Treat as NOP. */
5460 return;
5463 TCGv t0 = tcg_temp_local_new();
5465 gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5466 gen_store_gpr(t0, rt);
5467 tcg_temp_free(t0);
5469 opn = "mfc0";
5470 break;
5471 case OPC_MTC0:
5473 TCGv t0 = tcg_temp_local_new();
5475 gen_load_gpr(t0, rt);
5476 save_cpu_state(ctx, 1);
5477 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5478 tcg_temp_free(t0);
5480 opn = "mtc0";
5481 break;
5482 #if defined(TARGET_MIPS64)
5483 case OPC_DMFC0:
5484 check_insn(env, ctx, ISA_MIPS3);
5485 if (rt == 0) {
5486 /* Treat as NOP. */
5487 return;
5490 TCGv t0 = tcg_temp_local_new();
5492 gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5493 gen_store_gpr(t0, rt);
5494 tcg_temp_free(t0);
5496 opn = "dmfc0";
5497 break;
5498 case OPC_DMTC0:
5499 check_insn(env, ctx, ISA_MIPS3);
5501 TCGv t0 = tcg_temp_local_new();
5503 gen_load_gpr(t0, rt);
5504 save_cpu_state(ctx, 1);
5505 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5506 tcg_temp_free(t0);
5508 opn = "dmtc0";
5509 break;
5510 #endif
5511 case OPC_MFTR:
5512 check_insn(env, ctx, ASE_MT);
5513 if (rd == 0) {
5514 /* Treat as NOP. */
5515 return;
5517 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5518 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5519 opn = "mftr";
5520 break;
5521 case OPC_MTTR:
5522 check_insn(env, ctx, ASE_MT);
5523 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5524 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5525 opn = "mttr";
5526 break;
5527 case OPC_TLBWI:
5528 opn = "tlbwi";
5529 if (!env->tlb->do_tlbwi)
5530 goto die;
5531 gen_helper_tlbwi();
5532 break;
5533 case OPC_TLBWR:
5534 opn = "tlbwr";
5535 if (!env->tlb->do_tlbwr)
5536 goto die;
5537 gen_helper_tlbwr();
5538 break;
5539 case OPC_TLBP:
5540 opn = "tlbp";
5541 if (!env->tlb->do_tlbp)
5542 goto die;
5543 gen_helper_tlbp();
5544 break;
5545 case OPC_TLBR:
5546 opn = "tlbr";
5547 if (!env->tlb->do_tlbr)
5548 goto die;
5549 gen_helper_tlbr();
5550 break;
5551 case OPC_ERET:
5552 opn = "eret";
5553 check_insn(env, ctx, ISA_MIPS2);
5554 save_cpu_state(ctx, 1);
5555 gen_helper_eret();
5556 ctx->bstate = BS_EXCP;
5557 break;
5558 case OPC_DERET:
5559 opn = "deret";
5560 check_insn(env, ctx, ISA_MIPS32);
5561 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5562 MIPS_INVAL(opn);
5563 generate_exception(ctx, EXCP_RI);
5564 } else {
5565 save_cpu_state(ctx, 1);
5566 gen_helper_deret();
5567 ctx->bstate = BS_EXCP;
5569 break;
5570 case OPC_WAIT:
5571 opn = "wait";
5572 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5573 /* If we get an exception, we want to restart at next instruction */
5574 ctx->pc += 4;
5575 save_cpu_state(ctx, 1);
5576 ctx->pc -= 4;
5577 gen_helper_wait();
5578 ctx->bstate = BS_EXCP;
5579 break;
5580 default:
5581 die:
5582 MIPS_INVAL(opn);
5583 generate_exception(ctx, EXCP_RI);
5584 return;
5586 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5588 #endif /* !CONFIG_USER_ONLY */
5590 /* CP1 Branches (before delay slot) */
5591 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5592 int32_t cc, int32_t offset)
5594 target_ulong btarget;
5595 const char *opn = "cp1 cond branch";
5596 TCGv_i32 t0 = tcg_temp_new_i32();
5598 if (cc != 0)
5599 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5601 btarget = ctx->pc + 4 + offset;
5603 switch (op) {
5604 case OPC_BC1F:
5606 int l1 = gen_new_label();
5607 int l2 = gen_new_label();
5609 get_fp_cond(t0);
5610 tcg_gen_andi_i32(t0, t0, 0x1 << cc);
5611 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
5612 tcg_gen_movi_i32(bcond, 0);
5613 tcg_gen_br(l2);
5614 gen_set_label(l1);
5615 tcg_gen_movi_i32(bcond, 1);
5616 gen_set_label(l2);
5618 opn = "bc1f";
5619 goto not_likely;
5620 case OPC_BC1FL:
5622 int l1 = gen_new_label();
5623 int l2 = gen_new_label();
5625 get_fp_cond(t0);
5626 tcg_gen_andi_i32(t0, t0, 0x1 << cc);
5627 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
5628 tcg_gen_movi_i32(bcond, 0);
5629 tcg_gen_br(l2);
5630 gen_set_label(l1);
5631 tcg_gen_movi_i32(bcond, 1);
5632 gen_set_label(l2);
5634 opn = "bc1fl";
5635 goto likely;
5636 case OPC_BC1T:
5638 int l1 = gen_new_label();
5639 int l2 = gen_new_label();
5641 get_fp_cond(t0);
5642 tcg_gen_andi_i32(t0, t0, 0x1 << cc);
5643 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
5644 tcg_gen_movi_i32(bcond, 0);
5645 tcg_gen_br(l2);
5646 gen_set_label(l1);
5647 tcg_gen_movi_i32(bcond, 1);
5648 gen_set_label(l2);
5650 opn = "bc1t";
5651 goto not_likely;
5652 case OPC_BC1TL:
5654 int l1 = gen_new_label();
5655 int l2 = gen_new_label();
5657 get_fp_cond(t0);
5658 tcg_gen_andi_i32(t0, t0, 0x1 << cc);
5659 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
5660 tcg_gen_movi_i32(bcond, 0);
5661 tcg_gen_br(l2);
5662 gen_set_label(l1);
5663 tcg_gen_movi_i32(bcond, 1);
5664 gen_set_label(l2);
5666 opn = "bc1tl";
5667 likely:
5668 ctx->hflags |= MIPS_HFLAG_BL;
5669 break;
5670 case OPC_BC1FANY2:
5672 int l1 = gen_new_label();
5673 int l2 = gen_new_label();
5675 get_fp_cond(t0);
5676 tcg_gen_andi_i32(t0, t0, 0x3 << cc);
5677 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
5678 tcg_gen_movi_i32(bcond, 0);
5679 tcg_gen_br(l2);
5680 gen_set_label(l1);
5681 tcg_gen_movi_i32(bcond, 1);
5682 gen_set_label(l2);
5684 opn = "bc1any2f";
5685 goto not_likely;
5686 case OPC_BC1TANY2:
5688 int l1 = gen_new_label();
5689 int l2 = gen_new_label();
5691 get_fp_cond(t0);
5692 tcg_gen_andi_i32(t0, t0, 0x3 << cc);
5693 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
5694 tcg_gen_movi_i32(bcond, 0);
5695 tcg_gen_br(l2);
5696 gen_set_label(l1);
5697 tcg_gen_movi_i32(bcond, 1);
5698 gen_set_label(l2);
5700 opn = "bc1any2t";
5701 goto not_likely;
5702 case OPC_BC1FANY4:
5704 int l1 = gen_new_label();
5705 int l2 = gen_new_label();
5707 get_fp_cond(t0);
5708 tcg_gen_andi_i32(t0, t0, 0xf << cc);
5709 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
5710 tcg_gen_movi_i32(bcond, 0);
5711 tcg_gen_br(l2);
5712 gen_set_label(l1);
5713 tcg_gen_movi_i32(bcond, 1);
5714 gen_set_label(l2);
5716 opn = "bc1any4f";
5717 goto not_likely;
5718 case OPC_BC1TANY4:
5720 int l1 = gen_new_label();
5721 int l2 = gen_new_label();
5723 get_fp_cond(t0);
5724 tcg_gen_andi_i32(t0, t0, 0xf << cc);
5725 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
5726 tcg_gen_movi_i32(bcond, 0);
5727 tcg_gen_br(l2);
5728 gen_set_label(l1);
5729 tcg_gen_movi_i32(bcond, 1);
5730 gen_set_label(l2);
5732 opn = "bc1any4t";
5733 not_likely:
5734 ctx->hflags |= MIPS_HFLAG_BC;
5735 break;
5736 default:
5737 MIPS_INVAL(opn);
5738 generate_exception (ctx, EXCP_RI);
5739 goto out;
5741 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5742 ctx->hflags, btarget);
5743 ctx->btarget = btarget;
5745 out:
5746 tcg_temp_free_i32(t0);
5749 /* Coprocessor 1 (FPU) */
5751 #define FOP(func, fmt) (((fmt) << 21) | (func))
5753 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5755 const char *opn = "cp1 move";
5756 TCGv t0 = tcg_temp_local_new();
5758 switch (opc) {
5759 case OPC_MFC1:
5761 TCGv_i32 fp0 = tcg_temp_new_i32();
5763 gen_load_fpr32(fp0, fs);
5764 tcg_gen_ext_i32_tl(t0, fp0);
5765 tcg_temp_free_i32(fp0);
5767 gen_store_gpr(t0, rt);
5768 opn = "mfc1";
5769 break;
5770 case OPC_MTC1:
5771 gen_load_gpr(t0, rt);
5773 TCGv_i32 fp0 = tcg_temp_new_i32();
5775 tcg_gen_trunc_tl_i32(fp0, t0);
5776 gen_store_fpr32(fp0, fs);
5777 tcg_temp_free_i32(fp0);
5779 opn = "mtc1";
5780 break;
5781 case OPC_CFC1:
5782 gen_helper_1i(cfc1, t0, fs);
5783 gen_store_gpr(t0, rt);
5784 opn = "cfc1";
5785 break;
5786 case OPC_CTC1:
5787 gen_load_gpr(t0, rt);
5788 gen_helper_1i(ctc1, t0, fs);
5789 opn = "ctc1";
5790 break;
5791 case OPC_DMFC1:
5793 TCGv_i64 fp0 = tcg_temp_new_i64();
5795 gen_load_fpr64(ctx, fp0, fs);
5796 tcg_gen_trunc_i64_tl(t0, fp0);
5797 tcg_temp_free_i64(fp0);
5799 gen_store_gpr(t0, rt);
5800 opn = "dmfc1";
5801 break;
5802 case OPC_DMTC1:
5803 gen_load_gpr(t0, rt);
5805 TCGv_i64 fp0 = tcg_temp_new_i64();
5807 tcg_gen_extu_tl_i64(fp0, t0);
5808 gen_store_fpr64(ctx, fp0, fs);
5809 tcg_temp_free_i64(fp0);
5811 opn = "dmtc1";
5812 break;
5813 case OPC_MFHC1:
5815 TCGv_i32 fp0 = tcg_temp_new_i32();
5817 gen_load_fpr32h(fp0, fs);
5818 tcg_gen_ext_i32_tl(t0, fp0);
5819 tcg_temp_free_i32(fp0);
5821 gen_store_gpr(t0, rt);
5822 opn = "mfhc1";
5823 break;
5824 case OPC_MTHC1:
5825 gen_load_gpr(t0, rt);
5827 TCGv_i32 fp0 = tcg_temp_new_i32();
5829 tcg_gen_trunc_tl_i32(fp0, t0);
5830 gen_store_fpr32h(fp0, fs);
5831 tcg_temp_free_i32(fp0);
5833 opn = "mthc1";
5834 break;
5835 default:
5836 MIPS_INVAL(opn);
5837 generate_exception (ctx, EXCP_RI);
5838 goto out;
5840 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5842 out:
5843 tcg_temp_free(t0);
5846 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5848 int l1 = gen_new_label();
5849 uint32_t ccbit;
5850 TCGCond cond;
5851 TCGv t0 = tcg_temp_local_new();
5852 TCGv_i32 r_tmp = tcg_temp_new_i32();
5854 if (cc)
5855 ccbit = 1 << (24 + cc);
5856 else
5857 ccbit = 1 << 23;
5858 if (tf)
5859 cond = TCG_COND_EQ;
5860 else
5861 cond = TCG_COND_NE;
5863 gen_load_gpr(t0, rd);
5864 tcg_gen_andi_i32(r_tmp, fpu_fcr31, ccbit);
5865 tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
5866 tcg_temp_free_i32(r_tmp);
5867 gen_load_gpr(t0, rs);
5868 gen_set_label(l1);
5869 gen_store_gpr(t0, rd);
5870 tcg_temp_free(t0);
5873 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5875 uint32_t ccbit;
5876 int cond;
5877 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
5878 TCGv_i32 fp0 = tcg_temp_local_new_i32();
5879 int l1 = gen_new_label();
5881 if (cc)
5882 ccbit = 1 << (24 + cc);
5883 else
5884 ccbit = 1 << 23;
5886 if (tf)
5887 cond = TCG_COND_EQ;
5888 else
5889 cond = TCG_COND_NE;
5891 gen_load_fpr32(fp0, fd);
5892 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
5893 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
5894 tcg_temp_free_i32(r_tmp1);
5895 gen_load_fpr32(fp0, fs);
5896 gen_set_label(l1);
5897 gen_store_fpr32(fp0, fd);
5898 tcg_temp_free_i32(fp0);
5901 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5903 uint32_t ccbit;
5904 int cond;
5905 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
5906 TCGv_i64 fp0 = tcg_temp_local_new_i64();
5907 int l1 = gen_new_label();
5909 if (cc)
5910 ccbit = 1 << (24 + cc);
5911 else
5912 ccbit = 1 << 23;
5914 if (tf)
5915 cond = TCG_COND_EQ;
5916 else
5917 cond = TCG_COND_NE;
5919 gen_load_fpr64(ctx, fp0, fd);
5920 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
5921 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
5922 tcg_temp_free_i32(r_tmp1);
5923 gen_load_fpr64(ctx, fp0, fs);
5924 gen_set_label(l1);
5925 gen_store_fpr64(ctx, fp0, fd);
5926 tcg_temp_free_i64(fp0);
5929 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5931 uint32_t ccbit1, ccbit2;
5932 int cond;
5933 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
5934 TCGv_i32 fp0 = tcg_temp_local_new_i32();
5935 int l1 = gen_new_label();
5936 int l2 = gen_new_label();
5938 if (cc) {
5939 ccbit1 = 1 << (24 + cc);
5940 ccbit2 = 1 << (25 + cc);
5941 } else {
5942 ccbit1 = 1 << 23;
5943 ccbit2 = 1 << 25;
5946 if (tf)
5947 cond = TCG_COND_EQ;
5948 else
5949 cond = TCG_COND_NE;
5951 gen_load_fpr32(fp0, fd);
5952 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit1);
5953 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
5954 gen_load_fpr32(fp0, fs);
5955 gen_set_label(l1);
5956 gen_store_fpr32(fp0, fd);
5958 gen_load_fpr32h(fp0, fd);
5959 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit2);
5960 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l2);
5961 gen_load_fpr32h(fp0, fs);
5962 gen_set_label(l2);
5963 gen_store_fpr32h(fp0, fd);
5965 tcg_temp_free_i32(r_tmp1);
5966 tcg_temp_free_i32(fp0);
5970 static void gen_farith (DisasContext *ctx, uint32_t op1,
5971 int ft, int fs, int fd, int cc)
5973 const char *opn = "farith";
5974 const char *condnames[] = {
5975 "c.f",
5976 "c.un",
5977 "c.eq",
5978 "c.ueq",
5979 "c.olt",
5980 "c.ult",
5981 "c.ole",
5982 "c.ule",
5983 "c.sf",
5984 "c.ngle",
5985 "c.seq",
5986 "c.ngl",
5987 "c.lt",
5988 "c.nge",
5989 "c.le",
5990 "c.ngt",
5992 const char *condnames_abs[] = {
5993 "cabs.f",
5994 "cabs.un",
5995 "cabs.eq",
5996 "cabs.ueq",
5997 "cabs.olt",
5998 "cabs.ult",
5999 "cabs.ole",
6000 "cabs.ule",
6001 "cabs.sf",
6002 "cabs.ngle",
6003 "cabs.seq",
6004 "cabs.ngl",
6005 "cabs.lt",
6006 "cabs.nge",
6007 "cabs.le",
6008 "cabs.ngt",
6010 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6011 uint32_t func = ctx->opcode & 0x3f;
6013 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
6014 case FOP(0, 16):
6016 TCGv_i32 fp0 = tcg_temp_new_i32();
6017 TCGv_i32 fp1 = tcg_temp_new_i32();
6019 gen_load_fpr32(fp0, fs);
6020 gen_load_fpr32(fp1, ft);
6021 gen_helper_float_add_s(fp0, fp0, fp1);
6022 tcg_temp_free_i32(fp1);
6023 gen_store_fpr32(fp0, fd);
6024 tcg_temp_free_i32(fp0);
6026 opn = "add.s";
6027 optype = BINOP;
6028 break;
6029 case FOP(1, 16):
6031 TCGv_i32 fp0 = tcg_temp_new_i32();
6032 TCGv_i32 fp1 = tcg_temp_new_i32();
6034 gen_load_fpr32(fp0, fs);
6035 gen_load_fpr32(fp1, ft);
6036 gen_helper_float_sub_s(fp0, fp0, fp1);
6037 tcg_temp_free_i32(fp1);
6038 gen_store_fpr32(fp0, fd);
6039 tcg_temp_free_i32(fp0);
6041 opn = "sub.s";
6042 optype = BINOP;
6043 break;
6044 case FOP(2, 16):
6046 TCGv_i32 fp0 = tcg_temp_new_i32();
6047 TCGv_i32 fp1 = tcg_temp_new_i32();
6049 gen_load_fpr32(fp0, fs);
6050 gen_load_fpr32(fp1, ft);
6051 gen_helper_float_mul_s(fp0, fp0, fp1);
6052 tcg_temp_free_i32(fp1);
6053 gen_store_fpr32(fp0, fd);
6054 tcg_temp_free_i32(fp0);
6056 opn = "mul.s";
6057 optype = BINOP;
6058 break;
6059 case FOP(3, 16):
6061 TCGv_i32 fp0 = tcg_temp_new_i32();
6062 TCGv_i32 fp1 = tcg_temp_new_i32();
6064 gen_load_fpr32(fp0, fs);
6065 gen_load_fpr32(fp1, ft);
6066 gen_helper_float_div_s(fp0, fp0, fp1);
6067 tcg_temp_free_i32(fp1);
6068 gen_store_fpr32(fp0, fd);
6069 tcg_temp_free_i32(fp0);
6071 opn = "div.s";
6072 optype = BINOP;
6073 break;
6074 case FOP(4, 16):
6076 TCGv_i32 fp0 = tcg_temp_new_i32();
6078 gen_load_fpr32(fp0, fs);
6079 gen_helper_float_sqrt_s(fp0, fp0);
6080 gen_store_fpr32(fp0, fd);
6081 tcg_temp_free_i32(fp0);
6083 opn = "sqrt.s";
6084 break;
6085 case FOP(5, 16):
6087 TCGv_i32 fp0 = tcg_temp_new_i32();
6089 gen_load_fpr32(fp0, fs);
6090 gen_helper_float_abs_s(fp0, fp0);
6091 gen_store_fpr32(fp0, fd);
6092 tcg_temp_free_i32(fp0);
6094 opn = "abs.s";
6095 break;
6096 case FOP(6, 16):
6098 TCGv_i32 fp0 = tcg_temp_new_i32();
6100 gen_load_fpr32(fp0, fs);
6101 gen_store_fpr32(fp0, fd);
6102 tcg_temp_free_i32(fp0);
6104 opn = "mov.s";
6105 break;
6106 case FOP(7, 16):
6108 TCGv_i32 fp0 = tcg_temp_new_i32();
6110 gen_load_fpr32(fp0, fs);
6111 gen_helper_float_chs_s(fp0, fp0);
6112 gen_store_fpr32(fp0, fd);
6113 tcg_temp_free_i32(fp0);
6115 opn = "neg.s";
6116 break;
6117 case FOP(8, 16):
6118 check_cp1_64bitmode(ctx);
6120 TCGv_i32 fp32 = tcg_temp_new_i32();
6121 TCGv_i64 fp64 = tcg_temp_new_i64();
6123 gen_load_fpr32(fp32, fs);
6124 gen_helper_float_roundl_s(fp64, fp32);
6125 tcg_temp_free_i32(fp32);
6126 gen_store_fpr64(ctx, fp64, fd);
6127 tcg_temp_free_i64(fp64);
6129 opn = "round.l.s";
6130 break;
6131 case FOP(9, 16):
6132 check_cp1_64bitmode(ctx);
6134 TCGv_i32 fp32 = tcg_temp_new_i32();
6135 TCGv_i64 fp64 = tcg_temp_new_i64();
6137 gen_load_fpr32(fp32, fs);
6138 gen_helper_float_truncl_s(fp64, fp32);
6139 tcg_temp_free_i32(fp32);
6140 gen_store_fpr64(ctx, fp64, fd);
6141 tcg_temp_free_i64(fp64);
6143 opn = "trunc.l.s";
6144 break;
6145 case FOP(10, 16):
6146 check_cp1_64bitmode(ctx);
6148 TCGv_i32 fp32 = tcg_temp_new_i32();
6149 TCGv_i64 fp64 = tcg_temp_new_i64();
6151 gen_load_fpr32(fp32, fs);
6152 gen_helper_float_ceill_s(fp64, fp32);
6153 tcg_temp_free_i32(fp32);
6154 gen_store_fpr64(ctx, fp64, fd);
6155 tcg_temp_free_i64(fp64);
6157 opn = "ceil.l.s";
6158 break;
6159 case FOP(11, 16):
6160 check_cp1_64bitmode(ctx);
6162 TCGv_i32 fp32 = tcg_temp_new_i32();
6163 TCGv_i64 fp64 = tcg_temp_new_i64();
6165 gen_load_fpr32(fp32, fs);
6166 gen_helper_float_floorl_s(fp64, fp32);
6167 tcg_temp_free_i32(fp32);
6168 gen_store_fpr64(ctx, fp64, fd);
6169 tcg_temp_free_i64(fp64);
6171 opn = "floor.l.s";
6172 break;
6173 case FOP(12, 16):
6175 TCGv_i32 fp0 = tcg_temp_new_i32();
6177 gen_load_fpr32(fp0, fs);
6178 gen_helper_float_roundw_s(fp0, fp0);
6179 gen_store_fpr32(fp0, fd);
6180 tcg_temp_free_i32(fp0);
6182 opn = "round.w.s";
6183 break;
6184 case FOP(13, 16):
6186 TCGv_i32 fp0 = tcg_temp_new_i32();
6188 gen_load_fpr32(fp0, fs);
6189 gen_helper_float_truncw_s(fp0, fp0);
6190 gen_store_fpr32(fp0, fd);
6191 tcg_temp_free_i32(fp0);
6193 opn = "trunc.w.s";
6194 break;
6195 case FOP(14, 16):
6197 TCGv_i32 fp0 = tcg_temp_new_i32();
6199 gen_load_fpr32(fp0, fs);
6200 gen_helper_float_ceilw_s(fp0, fp0);
6201 gen_store_fpr32(fp0, fd);
6202 tcg_temp_free_i32(fp0);
6204 opn = "ceil.w.s";
6205 break;
6206 case FOP(15, 16):
6208 TCGv_i32 fp0 = tcg_temp_new_i32();
6210 gen_load_fpr32(fp0, fs);
6211 gen_helper_float_floorw_s(fp0, fp0);
6212 gen_store_fpr32(fp0, fd);
6213 tcg_temp_free_i32(fp0);
6215 opn = "floor.w.s";
6216 break;
6217 case FOP(17, 16):
6218 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6219 opn = "movcf.s";
6220 break;
6221 case FOP(18, 16):
6223 int l1 = gen_new_label();
6224 TCGv t0 = tcg_temp_new();
6225 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6227 gen_load_gpr(t0, ft);
6228 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6229 gen_load_fpr32(fp0, fs);
6230 gen_store_fpr32(fp0, fd);
6231 tcg_temp_free_i32(fp0);
6232 gen_set_label(l1);
6233 tcg_temp_free(t0);
6235 opn = "movz.s";
6236 break;
6237 case FOP(19, 16):
6239 int l1 = gen_new_label();
6240 TCGv t0 = tcg_temp_new();
6241 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6243 gen_load_gpr(t0, ft);
6244 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6245 gen_load_fpr32(fp0, fs);
6246 gen_store_fpr32(fp0, fd);
6247 tcg_temp_free_i32(fp0);
6248 gen_set_label(l1);
6249 tcg_temp_free(t0);
6251 opn = "movn.s";
6252 break;
6253 case FOP(21, 16):
6254 check_cop1x(ctx);
6256 TCGv_i32 fp0 = tcg_temp_new_i32();
6258 gen_load_fpr32(fp0, fs);
6259 gen_helper_float_recip_s(fp0, fp0);
6260 gen_store_fpr32(fp0, fd);
6261 tcg_temp_free_i32(fp0);
6263 opn = "recip.s";
6264 break;
6265 case FOP(22, 16):
6266 check_cop1x(ctx);
6268 TCGv_i32 fp0 = tcg_temp_new_i32();
6270 gen_load_fpr32(fp0, fs);
6271 gen_helper_float_rsqrt_s(fp0, fp0);
6272 gen_store_fpr32(fp0, fd);
6273 tcg_temp_free_i32(fp0);
6275 opn = "rsqrt.s";
6276 break;
6277 case FOP(28, 16):
6278 check_cp1_64bitmode(ctx);
6280 TCGv_i32 fp0 = tcg_temp_new_i32();
6281 TCGv_i32 fp1 = tcg_temp_new_i32();
6283 gen_load_fpr32(fp0, fs);
6284 gen_load_fpr32(fp1, fd);
6285 gen_helper_float_recip2_s(fp0, fp0, fp1);
6286 tcg_temp_free_i32(fp1);
6287 gen_store_fpr32(fp0, fd);
6288 tcg_temp_free_i32(fp0);
6290 opn = "recip2.s";
6291 break;
6292 case FOP(29, 16):
6293 check_cp1_64bitmode(ctx);
6295 TCGv_i32 fp0 = tcg_temp_new_i32();
6297 gen_load_fpr32(fp0, fs);
6298 gen_helper_float_recip1_s(fp0, fp0);
6299 gen_store_fpr32(fp0, fd);
6300 tcg_temp_free_i32(fp0);
6302 opn = "recip1.s";
6303 break;
6304 case FOP(30, 16):
6305 check_cp1_64bitmode(ctx);
6307 TCGv_i32 fp0 = tcg_temp_new_i32();
6309 gen_load_fpr32(fp0, fs);
6310 gen_helper_float_rsqrt1_s(fp0, fp0);
6311 gen_store_fpr32(fp0, fd);
6312 tcg_temp_free_i32(fp0);
6314 opn = "rsqrt1.s";
6315 break;
6316 case FOP(31, 16):
6317 check_cp1_64bitmode(ctx);
6319 TCGv_i32 fp0 = tcg_temp_new_i32();
6320 TCGv_i32 fp1 = tcg_temp_new_i32();
6322 gen_load_fpr32(fp0, fs);
6323 gen_load_fpr32(fp1, ft);
6324 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6325 tcg_temp_free_i32(fp1);
6326 gen_store_fpr32(fp0, fd);
6327 tcg_temp_free_i32(fp0);
6329 opn = "rsqrt2.s";
6330 break;
6331 case FOP(33, 16):
6332 check_cp1_registers(ctx, fd);
6334 TCGv_i32 fp32 = tcg_temp_new_i32();
6335 TCGv_i64 fp64 = tcg_temp_new_i64();
6337 gen_load_fpr32(fp32, fs);
6338 gen_helper_float_cvtd_s(fp64, fp32);
6339 tcg_temp_free_i32(fp32);
6340 gen_store_fpr64(ctx, fp64, fd);
6341 tcg_temp_free_i64(fp64);
6343 opn = "cvt.d.s";
6344 break;
6345 case FOP(36, 16):
6347 TCGv_i32 fp0 = tcg_temp_new_i32();
6349 gen_load_fpr32(fp0, fs);
6350 gen_helper_float_cvtw_s(fp0, fp0);
6351 gen_store_fpr32(fp0, fd);
6352 tcg_temp_free_i32(fp0);
6354 opn = "cvt.w.s";
6355 break;
6356 case FOP(37, 16):
6357 check_cp1_64bitmode(ctx);
6359 TCGv_i32 fp32 = tcg_temp_new_i32();
6360 TCGv_i64 fp64 = tcg_temp_new_i64();
6362 gen_load_fpr32(fp32, fs);
6363 gen_helper_float_cvtl_s(fp64, fp32);
6364 tcg_temp_free_i32(fp32);
6365 gen_store_fpr64(ctx, fp64, fd);
6366 tcg_temp_free_i64(fp64);
6368 opn = "cvt.l.s";
6369 break;
6370 case FOP(38, 16):
6371 check_cp1_64bitmode(ctx);
6373 TCGv_i64 fp64 = tcg_temp_new_i64();
6374 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6375 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6377 gen_load_fpr32(fp32_0, fs);
6378 gen_load_fpr32(fp32_1, ft);
6379 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6380 tcg_temp_free_i32(fp32_1);
6381 tcg_temp_free_i32(fp32_0);
6382 gen_store_fpr64(ctx, fp64, fd);
6383 tcg_temp_free_i64(fp64);
6385 opn = "cvt.ps.s";
6386 break;
6387 case FOP(48, 16):
6388 case FOP(49, 16):
6389 case FOP(50, 16):
6390 case FOP(51, 16):
6391 case FOP(52, 16):
6392 case FOP(53, 16):
6393 case FOP(54, 16):
6394 case FOP(55, 16):
6395 case FOP(56, 16):
6396 case FOP(57, 16):
6397 case FOP(58, 16):
6398 case FOP(59, 16):
6399 case FOP(60, 16):
6400 case FOP(61, 16):
6401 case FOP(62, 16):
6402 case FOP(63, 16):
6404 TCGv_i32 fp0 = tcg_temp_new_i32();
6405 TCGv_i32 fp1 = tcg_temp_new_i32();
6407 gen_load_fpr32(fp0, fs);
6408 gen_load_fpr32(fp1, ft);
6409 if (ctx->opcode & (1 << 6)) {
6410 check_cop1x(ctx);
6411 gen_cmpabs_s(func-48, fp0, fp1, cc);
6412 opn = condnames_abs[func-48];
6413 } else {
6414 gen_cmp_s(func-48, fp0, fp1, cc);
6415 opn = condnames[func-48];
6417 tcg_temp_free_i32(fp0);
6418 tcg_temp_free_i32(fp1);
6420 break;
6421 case FOP(0, 17):
6422 check_cp1_registers(ctx, fs | ft | fd);
6424 TCGv_i64 fp0 = tcg_temp_new_i64();
6425 TCGv_i64 fp1 = tcg_temp_new_i64();
6427 gen_load_fpr64(ctx, fp0, fs);
6428 gen_load_fpr64(ctx, fp1, ft);
6429 gen_helper_float_add_d(fp0, fp0, fp1);
6430 tcg_temp_free_i64(fp1);
6431 gen_store_fpr64(ctx, fp0, fd);
6432 tcg_temp_free_i64(fp0);
6434 opn = "add.d";
6435 optype = BINOP;
6436 break;
6437 case FOP(1, 17):
6438 check_cp1_registers(ctx, fs | ft | fd);
6440 TCGv_i64 fp0 = tcg_temp_new_i64();
6441 TCGv_i64 fp1 = tcg_temp_new_i64();
6443 gen_load_fpr64(ctx, fp0, fs);
6444 gen_load_fpr64(ctx, fp1, ft);
6445 gen_helper_float_sub_d(fp0, fp0, fp1);
6446 tcg_temp_free_i64(fp1);
6447 gen_store_fpr64(ctx, fp0, fd);
6448 tcg_temp_free_i64(fp0);
6450 opn = "sub.d";
6451 optype = BINOP;
6452 break;
6453 case FOP(2, 17):
6454 check_cp1_registers(ctx, fs | ft | fd);
6456 TCGv_i64 fp0 = tcg_temp_new_i64();
6457 TCGv_i64 fp1 = tcg_temp_new_i64();
6459 gen_load_fpr64(ctx, fp0, fs);
6460 gen_load_fpr64(ctx, fp1, ft);
6461 gen_helper_float_mul_d(fp0, fp0, fp1);
6462 tcg_temp_free_i64(fp1);
6463 gen_store_fpr64(ctx, fp0, fd);
6464 tcg_temp_free_i64(fp0);
6466 opn = "mul.d";
6467 optype = BINOP;
6468 break;
6469 case FOP(3, 17):
6470 check_cp1_registers(ctx, fs | ft | fd);
6472 TCGv_i64 fp0 = tcg_temp_new_i64();
6473 TCGv_i64 fp1 = tcg_temp_new_i64();
6475 gen_load_fpr64(ctx, fp0, fs);
6476 gen_load_fpr64(ctx, fp1, ft);
6477 gen_helper_float_div_d(fp0, fp0, fp1);
6478 tcg_temp_free_i64(fp1);
6479 gen_store_fpr64(ctx, fp0, fd);
6480 tcg_temp_free_i64(fp0);
6482 opn = "div.d";
6483 optype = BINOP;
6484 break;
6485 case FOP(4, 17):
6486 check_cp1_registers(ctx, fs | fd);
6488 TCGv_i64 fp0 = tcg_temp_new_i64();
6490 gen_load_fpr64(ctx, fp0, fs);
6491 gen_helper_float_sqrt_d(fp0, fp0);
6492 gen_store_fpr64(ctx, fp0, fd);
6493 tcg_temp_free_i64(fp0);
6495 opn = "sqrt.d";
6496 break;
6497 case FOP(5, 17):
6498 check_cp1_registers(ctx, fs | fd);
6500 TCGv_i64 fp0 = tcg_temp_new_i64();
6502 gen_load_fpr64(ctx, fp0, fs);
6503 gen_helper_float_abs_d(fp0, fp0);
6504 gen_store_fpr64(ctx, fp0, fd);
6505 tcg_temp_free_i64(fp0);
6507 opn = "abs.d";
6508 break;
6509 case FOP(6, 17):
6510 check_cp1_registers(ctx, fs | fd);
6512 TCGv_i64 fp0 = tcg_temp_new_i64();
6514 gen_load_fpr64(ctx, fp0, fs);
6515 gen_store_fpr64(ctx, fp0, fd);
6516 tcg_temp_free_i64(fp0);
6518 opn = "mov.d";
6519 break;
6520 case FOP(7, 17):
6521 check_cp1_registers(ctx, fs | fd);
6523 TCGv_i64 fp0 = tcg_temp_new_i64();
6525 gen_load_fpr64(ctx, fp0, fs);
6526 gen_helper_float_chs_d(fp0, fp0);
6527 gen_store_fpr64(ctx, fp0, fd);
6528 tcg_temp_free_i64(fp0);
6530 opn = "neg.d";
6531 break;
6532 case FOP(8, 17):
6533 check_cp1_64bitmode(ctx);
6535 TCGv_i64 fp0 = tcg_temp_new_i64();
6537 gen_load_fpr64(ctx, fp0, fs);
6538 gen_helper_float_roundl_d(fp0, fp0);
6539 gen_store_fpr64(ctx, fp0, fd);
6540 tcg_temp_free_i64(fp0);
6542 opn = "round.l.d";
6543 break;
6544 case FOP(9, 17):
6545 check_cp1_64bitmode(ctx);
6547 TCGv_i64 fp0 = tcg_temp_new_i64();
6549 gen_load_fpr64(ctx, fp0, fs);
6550 gen_helper_float_truncl_d(fp0, fp0);
6551 gen_store_fpr64(ctx, fp0, fd);
6552 tcg_temp_free_i64(fp0);
6554 opn = "trunc.l.d";
6555 break;
6556 case FOP(10, 17):
6557 check_cp1_64bitmode(ctx);
6559 TCGv_i64 fp0 = tcg_temp_new_i64();
6561 gen_load_fpr64(ctx, fp0, fs);
6562 gen_helper_float_ceill_d(fp0, fp0);
6563 gen_store_fpr64(ctx, fp0, fd);
6564 tcg_temp_free_i64(fp0);
6566 opn = "ceil.l.d";
6567 break;
6568 case FOP(11, 17):
6569 check_cp1_64bitmode(ctx);
6571 TCGv_i64 fp0 = tcg_temp_new_i64();
6573 gen_load_fpr64(ctx, fp0, fs);
6574 gen_helper_float_floorl_d(fp0, fp0);
6575 gen_store_fpr64(ctx, fp0, fd);
6576 tcg_temp_free_i64(fp0);
6578 opn = "floor.l.d";
6579 break;
6580 case FOP(12, 17):
6581 check_cp1_registers(ctx, fs);
6583 TCGv_i32 fp32 = tcg_temp_new_i32();
6584 TCGv_i64 fp64 = tcg_temp_new_i64();
6586 gen_load_fpr64(ctx, fp64, fs);
6587 gen_helper_float_roundw_d(fp32, fp64);
6588 tcg_temp_free_i64(fp64);
6589 gen_store_fpr32(fp32, fd);
6590 tcg_temp_free_i32(fp32);
6592 opn = "round.w.d";
6593 break;
6594 case FOP(13, 17):
6595 check_cp1_registers(ctx, fs);
6597 TCGv_i32 fp32 = tcg_temp_new_i32();
6598 TCGv_i64 fp64 = tcg_temp_new_i64();
6600 gen_load_fpr64(ctx, fp64, fs);
6601 gen_helper_float_truncw_d(fp32, fp64);
6602 tcg_temp_free_i64(fp64);
6603 gen_store_fpr32(fp32, fd);
6604 tcg_temp_free_i32(fp32);
6606 opn = "trunc.w.d";
6607 break;
6608 case FOP(14, 17):
6609 check_cp1_registers(ctx, fs);
6611 TCGv_i32 fp32 = tcg_temp_new_i32();
6612 TCGv_i64 fp64 = tcg_temp_new_i64();
6614 gen_load_fpr64(ctx, fp64, fs);
6615 gen_helper_float_ceilw_d(fp32, fp64);
6616 tcg_temp_free_i64(fp64);
6617 gen_store_fpr32(fp32, fd);
6618 tcg_temp_free_i32(fp32);
6620 opn = "ceil.w.d";
6621 break;
6622 case FOP(15, 17):
6623 check_cp1_registers(ctx, fs);
6625 TCGv_i32 fp32 = tcg_temp_new_i32();
6626 TCGv_i64 fp64 = tcg_temp_new_i64();
6628 gen_load_fpr64(ctx, fp64, fs);
6629 gen_helper_float_floorw_d(fp32, fp64);
6630 tcg_temp_free_i64(fp64);
6631 gen_store_fpr32(fp32, fd);
6632 tcg_temp_free_i32(fp32);
6634 opn = "floor.w.d";
6635 break;
6636 case FOP(17, 17):
6637 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6638 opn = "movcf.d";
6639 break;
6640 case FOP(18, 17):
6642 int l1 = gen_new_label();
6643 TCGv t0 = tcg_temp_new();
6644 TCGv_i64 fp0 = tcg_temp_local_new_i64();
6646 gen_load_gpr(t0, ft);
6647 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6648 gen_load_fpr64(ctx, fp0, fs);
6649 gen_store_fpr64(ctx, fp0, fd);
6650 tcg_temp_free_i64(fp0);
6651 gen_set_label(l1);
6652 tcg_temp_free(t0);
6654 opn = "movz.d";
6655 break;
6656 case FOP(19, 17):
6658 int l1 = gen_new_label();
6659 TCGv t0 = tcg_temp_new();
6660 TCGv_i64 fp0 = tcg_temp_local_new_i64();
6662 gen_load_gpr(t0, ft);
6663 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6664 gen_load_fpr64(ctx, fp0, fs);
6665 gen_store_fpr64(ctx, fp0, fd);
6666 tcg_temp_free_i64(fp0);
6667 gen_set_label(l1);
6668 tcg_temp_free(t0);
6670 opn = "movn.d";
6671 break;
6672 case FOP(21, 17):
6673 check_cp1_64bitmode(ctx);
6675 TCGv_i64 fp0 = tcg_temp_new_i64();
6677 gen_load_fpr64(ctx, fp0, fs);
6678 gen_helper_float_recip_d(fp0, fp0);
6679 gen_store_fpr64(ctx, fp0, fd);
6680 tcg_temp_free_i64(fp0);
6682 opn = "recip.d";
6683 break;
6684 case FOP(22, 17):
6685 check_cp1_64bitmode(ctx);
6687 TCGv_i64 fp0 = tcg_temp_new_i64();
6689 gen_load_fpr64(ctx, fp0, fs);
6690 gen_helper_float_rsqrt_d(fp0, fp0);
6691 gen_store_fpr64(ctx, fp0, fd);
6692 tcg_temp_free_i64(fp0);
6694 opn = "rsqrt.d";
6695 break;
6696 case FOP(28, 17):
6697 check_cp1_64bitmode(ctx);
6699 TCGv_i64 fp0 = tcg_temp_new_i64();
6700 TCGv_i64 fp1 = tcg_temp_new_i64();
6702 gen_load_fpr64(ctx, fp0, fs);
6703 gen_load_fpr64(ctx, fp1, ft);
6704 gen_helper_float_recip2_d(fp0, fp0, fp1);
6705 tcg_temp_free_i64(fp1);
6706 gen_store_fpr64(ctx, fp0, fd);
6707 tcg_temp_free_i64(fp0);
6709 opn = "recip2.d";
6710 break;
6711 case FOP(29, 17):
6712 check_cp1_64bitmode(ctx);
6714 TCGv_i64 fp0 = tcg_temp_new_i64();
6716 gen_load_fpr64(ctx, fp0, fs);
6717 gen_helper_float_recip1_d(fp0, fp0);
6718 gen_store_fpr64(ctx, fp0, fd);
6719 tcg_temp_free_i64(fp0);
6721 opn = "recip1.d";
6722 break;
6723 case FOP(30, 17):
6724 check_cp1_64bitmode(ctx);
6726 TCGv_i64 fp0 = tcg_temp_new_i64();
6728 gen_load_fpr64(ctx, fp0, fs);
6729 gen_helper_float_rsqrt1_d(fp0, fp0);
6730 gen_store_fpr64(ctx, fp0, fd);
6731 tcg_temp_free_i64(fp0);
6733 opn = "rsqrt1.d";
6734 break;
6735 case FOP(31, 17):
6736 check_cp1_64bitmode(ctx);
6738 TCGv_i64 fp0 = tcg_temp_new_i64();
6739 TCGv_i64 fp1 = tcg_temp_new_i64();
6741 gen_load_fpr64(ctx, fp0, fs);
6742 gen_load_fpr64(ctx, fp1, ft);
6743 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6744 tcg_temp_free_i64(fp1);
6745 gen_store_fpr64(ctx, fp0, fd);
6746 tcg_temp_free_i64(fp0);
6748 opn = "rsqrt2.d";
6749 break;
6750 case FOP(48, 17):
6751 case FOP(49, 17):
6752 case FOP(50, 17):
6753 case FOP(51, 17):
6754 case FOP(52, 17):
6755 case FOP(53, 17):
6756 case FOP(54, 17):
6757 case FOP(55, 17):
6758 case FOP(56, 17):
6759 case FOP(57, 17):
6760 case FOP(58, 17):
6761 case FOP(59, 17):
6762 case FOP(60, 17):
6763 case FOP(61, 17):
6764 case FOP(62, 17):
6765 case FOP(63, 17):
6767 TCGv_i64 fp0 = tcg_temp_new_i64();
6768 TCGv_i64 fp1 = tcg_temp_new_i64();
6770 gen_load_fpr64(ctx, fp0, fs);
6771 gen_load_fpr64(ctx, fp1, ft);
6772 if (ctx->opcode & (1 << 6)) {
6773 check_cop1x(ctx);
6774 check_cp1_registers(ctx, fs | ft);
6775 gen_cmpabs_d(func-48, fp0, fp1, cc);
6776 opn = condnames_abs[func-48];
6777 } else {
6778 check_cp1_registers(ctx, fs | ft);
6779 gen_cmp_d(func-48, fp0, fp1, cc);
6780 opn = condnames[func-48];
6782 tcg_temp_free_i64(fp0);
6783 tcg_temp_free_i64(fp1);
6785 break;
6786 case FOP(32, 17):
6787 check_cp1_registers(ctx, fs);
6789 TCGv_i32 fp32 = tcg_temp_new_i32();
6790 TCGv_i64 fp64 = tcg_temp_new_i64();
6792 gen_load_fpr64(ctx, fp64, fs);
6793 gen_helper_float_cvts_d(fp32, fp64);
6794 tcg_temp_free_i64(fp64);
6795 gen_store_fpr32(fp32, fd);
6796 tcg_temp_free_i32(fp32);
6798 opn = "cvt.s.d";
6799 break;
6800 case FOP(36, 17):
6801 check_cp1_registers(ctx, fs);
6803 TCGv_i32 fp32 = tcg_temp_new_i32();
6804 TCGv_i64 fp64 = tcg_temp_new_i64();
6806 gen_load_fpr64(ctx, fp64, fs);
6807 gen_helper_float_cvtw_d(fp32, fp64);
6808 tcg_temp_free_i64(fp64);
6809 gen_store_fpr32(fp32, fd);
6810 tcg_temp_free_i32(fp32);
6812 opn = "cvt.w.d";
6813 break;
6814 case FOP(37, 17):
6815 check_cp1_64bitmode(ctx);
6817 TCGv_i64 fp0 = tcg_temp_new_i64();
6819 gen_load_fpr64(ctx, fp0, fs);
6820 gen_helper_float_cvtl_d(fp0, fp0);
6821 gen_store_fpr64(ctx, fp0, fd);
6822 tcg_temp_free_i64(fp0);
6824 opn = "cvt.l.d";
6825 break;
6826 case FOP(32, 20):
6828 TCGv_i32 fp0 = tcg_temp_new_i32();
6830 gen_load_fpr32(fp0, fs);
6831 gen_helper_float_cvts_w(fp0, fp0);
6832 gen_store_fpr32(fp0, fd);
6833 tcg_temp_free_i32(fp0);
6835 opn = "cvt.s.w";
6836 break;
6837 case FOP(33, 20):
6838 check_cp1_registers(ctx, fd);
6840 TCGv_i32 fp32 = tcg_temp_new_i32();
6841 TCGv_i64 fp64 = tcg_temp_new_i64();
6843 gen_load_fpr32(fp32, fs);
6844 gen_helper_float_cvtd_w(fp64, fp32);
6845 tcg_temp_free_i32(fp32);
6846 gen_store_fpr64(ctx, fp64, fd);
6847 tcg_temp_free_i64(fp64);
6849 opn = "cvt.d.w";
6850 break;
6851 case FOP(32, 21):
6852 check_cp1_64bitmode(ctx);
6854 TCGv_i32 fp32 = tcg_temp_new_i32();
6855 TCGv_i64 fp64 = tcg_temp_new_i64();
6857 gen_load_fpr64(ctx, fp64, fs);
6858 gen_helper_float_cvts_l(fp32, fp64);
6859 tcg_temp_free_i64(fp64);
6860 gen_store_fpr32(fp32, fd);
6861 tcg_temp_free_i32(fp32);
6863 opn = "cvt.s.l";
6864 break;
6865 case FOP(33, 21):
6866 check_cp1_64bitmode(ctx);
6868 TCGv_i64 fp0 = tcg_temp_new_i64();
6870 gen_load_fpr64(ctx, fp0, fs);
6871 gen_helper_float_cvtd_l(fp0, fp0);
6872 gen_store_fpr64(ctx, fp0, fd);
6873 tcg_temp_free_i64(fp0);
6875 opn = "cvt.d.l";
6876 break;
6877 case FOP(38, 20):
6878 check_cp1_64bitmode(ctx);
6880 TCGv_i64 fp0 = tcg_temp_new_i64();
6882 gen_load_fpr64(ctx, fp0, fs);
6883 gen_helper_float_cvtps_pw(fp0, fp0);
6884 gen_store_fpr64(ctx, fp0, fd);
6885 tcg_temp_free_i64(fp0);
6887 opn = "cvt.ps.pw";
6888 break;
6889 case FOP(0, 22):
6890 check_cp1_64bitmode(ctx);
6892 TCGv_i64 fp0 = tcg_temp_new_i64();
6893 TCGv_i64 fp1 = tcg_temp_new_i64();
6895 gen_load_fpr64(ctx, fp0, fs);
6896 gen_load_fpr64(ctx, fp1, ft);
6897 gen_helper_float_add_ps(fp0, fp0, fp1);
6898 tcg_temp_free_i64(fp1);
6899 gen_store_fpr64(ctx, fp0, fd);
6900 tcg_temp_free_i64(fp0);
6902 opn = "add.ps";
6903 break;
6904 case FOP(1, 22):
6905 check_cp1_64bitmode(ctx);
6907 TCGv_i64 fp0 = tcg_temp_new_i64();
6908 TCGv_i64 fp1 = tcg_temp_new_i64();
6910 gen_load_fpr64(ctx, fp0, fs);
6911 gen_load_fpr64(ctx, fp1, ft);
6912 gen_helper_float_sub_ps(fp0, fp0, fp1);
6913 tcg_temp_free_i64(fp1);
6914 gen_store_fpr64(ctx, fp0, fd);
6915 tcg_temp_free_i64(fp0);
6917 opn = "sub.ps";
6918 break;
6919 case FOP(2, 22):
6920 check_cp1_64bitmode(ctx);
6922 TCGv_i64 fp0 = tcg_temp_new_i64();
6923 TCGv_i64 fp1 = tcg_temp_new_i64();
6925 gen_load_fpr64(ctx, fp0, fs);
6926 gen_load_fpr64(ctx, fp1, ft);
6927 gen_helper_float_mul_ps(fp0, fp0, fp1);
6928 tcg_temp_free_i64(fp1);
6929 gen_store_fpr64(ctx, fp0, fd);
6930 tcg_temp_free_i64(fp0);
6932 opn = "mul.ps";
6933 break;
6934 case FOP(5, 22):
6935 check_cp1_64bitmode(ctx);
6937 TCGv_i64 fp0 = tcg_temp_new_i64();
6939 gen_load_fpr64(ctx, fp0, fs);
6940 gen_helper_float_abs_ps(fp0, fp0);
6941 gen_store_fpr64(ctx, fp0, fd);
6942 tcg_temp_free_i64(fp0);
6944 opn = "abs.ps";
6945 break;
6946 case FOP(6, 22):
6947 check_cp1_64bitmode(ctx);
6949 TCGv_i64 fp0 = tcg_temp_new_i64();
6951 gen_load_fpr64(ctx, fp0, fs);
6952 gen_store_fpr64(ctx, fp0, fd);
6953 tcg_temp_free_i64(fp0);
6955 opn = "mov.ps";
6956 break;
6957 case FOP(7, 22):
6958 check_cp1_64bitmode(ctx);
6960 TCGv_i64 fp0 = tcg_temp_new_i64();
6962 gen_load_fpr64(ctx, fp0, fs);
6963 gen_helper_float_chs_ps(fp0, fp0);
6964 gen_store_fpr64(ctx, fp0, fd);
6965 tcg_temp_free_i64(fp0);
6967 opn = "neg.ps";
6968 break;
6969 case FOP(17, 22):
6970 check_cp1_64bitmode(ctx);
6971 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6972 opn = "movcf.ps";
6973 break;
6974 case FOP(18, 22):
6975 check_cp1_64bitmode(ctx);
6977 int l1 = gen_new_label();
6978 TCGv t0 = tcg_temp_new();
6979 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6980 TCGv_i32 fph0 = tcg_temp_local_new_i32();
6982 gen_load_gpr(t0, ft);
6983 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6984 gen_load_fpr32(fp0, fs);
6985 gen_load_fpr32h(fph0, fs);
6986 gen_store_fpr32(fp0, fd);
6987 gen_store_fpr32h(fph0, fd);
6988 tcg_temp_free_i32(fp0);
6989 tcg_temp_free_i32(fph0);
6990 gen_set_label(l1);
6991 tcg_temp_free(t0);
6993 opn = "movz.ps";
6994 break;
6995 case FOP(19, 22):
6996 check_cp1_64bitmode(ctx);
6998 int l1 = gen_new_label();
6999 TCGv t0 = tcg_temp_new();
7000 TCGv_i32 fp0 = tcg_temp_local_new_i32();
7001 TCGv_i32 fph0 = tcg_temp_local_new_i32();
7003 gen_load_gpr(t0, ft);
7004 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
7005 gen_load_fpr32(fp0, fs);
7006 gen_load_fpr32h(fph0, fs);
7007 gen_store_fpr32(fp0, fd);
7008 gen_store_fpr32h(fph0, fd);
7009 tcg_temp_free_i32(fp0);
7010 tcg_temp_free_i32(fph0);
7011 gen_set_label(l1);
7012 tcg_temp_free(t0);
7014 opn = "movn.ps";
7015 break;
7016 case FOP(24, 22):
7017 check_cp1_64bitmode(ctx);
7019 TCGv_i64 fp0 = tcg_temp_new_i64();
7020 TCGv_i64 fp1 = tcg_temp_new_i64();
7022 gen_load_fpr64(ctx, fp0, ft);
7023 gen_load_fpr64(ctx, fp1, fs);
7024 gen_helper_float_addr_ps(fp0, fp0, fp1);
7025 tcg_temp_free_i64(fp1);
7026 gen_store_fpr64(ctx, fp0, fd);
7027 tcg_temp_free_i64(fp0);
7029 opn = "addr.ps";
7030 break;
7031 case FOP(26, 22):
7032 check_cp1_64bitmode(ctx);
7034 TCGv_i64 fp0 = tcg_temp_new_i64();
7035 TCGv_i64 fp1 = tcg_temp_new_i64();
7037 gen_load_fpr64(ctx, fp0, ft);
7038 gen_load_fpr64(ctx, fp1, fs);
7039 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7040 tcg_temp_free_i64(fp1);
7041 gen_store_fpr64(ctx, fp0, fd);
7042 tcg_temp_free_i64(fp0);
7044 opn = "mulr.ps";
7045 break;
7046 case FOP(28, 22):
7047 check_cp1_64bitmode(ctx);
7049 TCGv_i64 fp0 = tcg_temp_new_i64();
7050 TCGv_i64 fp1 = tcg_temp_new_i64();
7052 gen_load_fpr64(ctx, fp0, fs);
7053 gen_load_fpr64(ctx, fp1, fd);
7054 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7055 tcg_temp_free_i64(fp1);
7056 gen_store_fpr64(ctx, fp0, fd);
7057 tcg_temp_free_i64(fp0);
7059 opn = "recip2.ps";
7060 break;
7061 case FOP(29, 22):
7062 check_cp1_64bitmode(ctx);
7064 TCGv_i64 fp0 = tcg_temp_new_i64();
7066 gen_load_fpr64(ctx, fp0, fs);
7067 gen_helper_float_recip1_ps(fp0, fp0);
7068 gen_store_fpr64(ctx, fp0, fd);
7069 tcg_temp_free_i64(fp0);
7071 opn = "recip1.ps";
7072 break;
7073 case FOP(30, 22):
7074 check_cp1_64bitmode(ctx);
7076 TCGv_i64 fp0 = tcg_temp_new_i64();
7078 gen_load_fpr64(ctx, fp0, fs);
7079 gen_helper_float_rsqrt1_ps(fp0, fp0);
7080 gen_store_fpr64(ctx, fp0, fd);
7081 tcg_temp_free_i64(fp0);
7083 opn = "rsqrt1.ps";
7084 break;
7085 case FOP(31, 22):
7086 check_cp1_64bitmode(ctx);
7088 TCGv_i64 fp0 = tcg_temp_new_i64();
7089 TCGv_i64 fp1 = tcg_temp_new_i64();
7091 gen_load_fpr64(ctx, fp0, fs);
7092 gen_load_fpr64(ctx, fp1, ft);
7093 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7094 tcg_temp_free_i64(fp1);
7095 gen_store_fpr64(ctx, fp0, fd);
7096 tcg_temp_free_i64(fp0);
7098 opn = "rsqrt2.ps";
7099 break;
7100 case FOP(32, 22):
7101 check_cp1_64bitmode(ctx);
7103 TCGv_i32 fp0 = tcg_temp_new_i32();
7105 gen_load_fpr32h(fp0, fs);
7106 gen_helper_float_cvts_pu(fp0, fp0);
7107 gen_store_fpr32(fp0, fd);
7108 tcg_temp_free_i32(fp0);
7110 opn = "cvt.s.pu";
7111 break;
7112 case FOP(36, 22):
7113 check_cp1_64bitmode(ctx);
7115 TCGv_i64 fp0 = tcg_temp_new_i64();
7117 gen_load_fpr64(ctx, fp0, fs);
7118 gen_helper_float_cvtpw_ps(fp0, fp0);
7119 gen_store_fpr64(ctx, fp0, fd);
7120 tcg_temp_free_i64(fp0);
7122 opn = "cvt.pw.ps";
7123 break;
7124 case FOP(40, 22):
7125 check_cp1_64bitmode(ctx);
7127 TCGv_i32 fp0 = tcg_temp_new_i32();
7129 gen_load_fpr32(fp0, fs);
7130 gen_helper_float_cvts_pl(fp0, fp0);
7131 gen_store_fpr32(fp0, fd);
7132 tcg_temp_free_i32(fp0);
7134 opn = "cvt.s.pl";
7135 break;
7136 case FOP(44, 22):
7137 check_cp1_64bitmode(ctx);
7139 TCGv_i32 fp0 = tcg_temp_new_i32();
7140 TCGv_i32 fp1 = tcg_temp_new_i32();
7142 gen_load_fpr32(fp0, fs);
7143 gen_load_fpr32(fp1, ft);
7144 gen_store_fpr32h(fp0, fd);
7145 gen_store_fpr32(fp1, fd);
7146 tcg_temp_free_i32(fp0);
7147 tcg_temp_free_i32(fp1);
7149 opn = "pll.ps";
7150 break;
7151 case FOP(45, 22):
7152 check_cp1_64bitmode(ctx);
7154 TCGv_i32 fp0 = tcg_temp_new_i32();
7155 TCGv_i32 fp1 = tcg_temp_new_i32();
7157 gen_load_fpr32(fp0, fs);
7158 gen_load_fpr32h(fp1, ft);
7159 gen_store_fpr32(fp1, fd);
7160 gen_store_fpr32h(fp0, fd);
7161 tcg_temp_free_i32(fp0);
7162 tcg_temp_free_i32(fp1);
7164 opn = "plu.ps";
7165 break;
7166 case FOP(46, 22):
7167 check_cp1_64bitmode(ctx);
7169 TCGv_i32 fp0 = tcg_temp_new_i32();
7170 TCGv_i32 fp1 = tcg_temp_new_i32();
7172 gen_load_fpr32h(fp0, fs);
7173 gen_load_fpr32(fp1, ft);
7174 gen_store_fpr32(fp1, fd);
7175 gen_store_fpr32h(fp0, fd);
7176 tcg_temp_free_i32(fp0);
7177 tcg_temp_free_i32(fp1);
7179 opn = "pul.ps";
7180 break;
7181 case FOP(47, 22):
7182 check_cp1_64bitmode(ctx);
7184 TCGv_i32 fp0 = tcg_temp_new_i32();
7185 TCGv_i32 fp1 = tcg_temp_new_i32();
7187 gen_load_fpr32h(fp0, fs);
7188 gen_load_fpr32h(fp1, ft);
7189 gen_store_fpr32(fp1, fd);
7190 gen_store_fpr32h(fp0, fd);
7191 tcg_temp_free_i32(fp0);
7192 tcg_temp_free_i32(fp1);
7194 opn = "puu.ps";
7195 break;
7196 case FOP(48, 22):
7197 case FOP(49, 22):
7198 case FOP(50, 22):
7199 case FOP(51, 22):
7200 case FOP(52, 22):
7201 case FOP(53, 22):
7202 case FOP(54, 22):
7203 case FOP(55, 22):
7204 case FOP(56, 22):
7205 case FOP(57, 22):
7206 case FOP(58, 22):
7207 case FOP(59, 22):
7208 case FOP(60, 22):
7209 case FOP(61, 22):
7210 case FOP(62, 22):
7211 case FOP(63, 22):
7212 check_cp1_64bitmode(ctx);
7214 TCGv_i64 fp0 = tcg_temp_new_i64();
7215 TCGv_i64 fp1 = tcg_temp_new_i64();
7217 gen_load_fpr64(ctx, fp0, fs);
7218 gen_load_fpr64(ctx, fp1, ft);
7219 if (ctx->opcode & (1 << 6)) {
7220 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7221 opn = condnames_abs[func-48];
7222 } else {
7223 gen_cmp_ps(func-48, fp0, fp1, cc);
7224 opn = condnames[func-48];
7226 tcg_temp_free_i64(fp0);
7227 tcg_temp_free_i64(fp1);
7229 break;
7230 default:
7231 MIPS_INVAL(opn);
7232 generate_exception (ctx, EXCP_RI);
7233 return;
7235 switch (optype) {
7236 case BINOP:
7237 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7238 break;
7239 case CMPOP:
7240 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7241 break;
7242 default:
7243 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7244 break;
7248 /* Coprocessor 3 (FPU) */
7249 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7250 int fd, int fs, int base, int index)
7252 const char *opn = "extended float load/store";
7253 int store = 0;
7254 TCGv t0 = tcg_temp_local_new();
7255 TCGv t1 = tcg_temp_local_new();
7257 if (base == 0) {
7258 gen_load_gpr(t0, index);
7259 } else if (index == 0) {
7260 gen_load_gpr(t0, base);
7261 } else {
7262 gen_load_gpr(t0, base);
7263 gen_load_gpr(t1, index);
7264 gen_op_addr_add(ctx, t0, t1);
7266 /* Don't do NOP if destination is zero: we must perform the actual
7267 memory access. */
7268 switch (opc) {
7269 case OPC_LWXC1:
7270 check_cop1x(ctx);
7272 TCGv_i32 fp0 = tcg_temp_new_i32();
7274 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
7275 tcg_gen_trunc_tl_i32(fp0, t1);
7276 gen_store_fpr32(fp0, fd);
7277 tcg_temp_free_i32(fp0);
7279 opn = "lwxc1";
7280 break;
7281 case OPC_LDXC1:
7282 check_cop1x(ctx);
7283 check_cp1_registers(ctx, fd);
7285 TCGv_i64 fp0 = tcg_temp_new_i64();
7287 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7288 gen_store_fpr64(ctx, fp0, fd);
7289 tcg_temp_free_i64(fp0);
7291 opn = "ldxc1";
7292 break;
7293 case OPC_LUXC1:
7294 check_cp1_64bitmode(ctx);
7295 tcg_gen_andi_tl(t0, t0, ~0x7);
7297 TCGv_i64 fp0 = tcg_temp_new_i64();
7299 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7300 gen_store_fpr64(ctx, fp0, fd);
7301 tcg_temp_free_i64(fp0);
7303 opn = "luxc1";
7304 break;
7305 case OPC_SWXC1:
7306 check_cop1x(ctx);
7308 TCGv_i32 fp0 = tcg_temp_new_i32();
7310 gen_load_fpr32(fp0, fs);
7311 tcg_gen_extu_i32_tl(t1, fp0);
7312 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7313 tcg_temp_free_i32(fp0);
7315 opn = "swxc1";
7316 store = 1;
7317 break;
7318 case OPC_SDXC1:
7319 check_cop1x(ctx);
7320 check_cp1_registers(ctx, fs);
7322 TCGv_i64 fp0 = tcg_temp_new_i64();
7324 gen_load_fpr64(ctx, fp0, fs);
7325 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7326 tcg_temp_free_i64(fp0);
7328 opn = "sdxc1";
7329 store = 1;
7330 break;
7331 case OPC_SUXC1:
7332 check_cp1_64bitmode(ctx);
7333 tcg_gen_andi_tl(t0, t0, ~0x7);
7335 TCGv_i64 fp0 = tcg_temp_new_i64();
7337 gen_load_fpr64(ctx, fp0, fs);
7338 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7339 tcg_temp_free_i64(fp0);
7341 opn = "suxc1";
7342 store = 1;
7343 break;
7344 default:
7345 MIPS_INVAL(opn);
7346 generate_exception(ctx, EXCP_RI);
7347 tcg_temp_free(t0);
7348 tcg_temp_free(t1);
7349 return;
7351 tcg_temp_free(t0);
7352 tcg_temp_free(t1);
7353 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7354 regnames[index], regnames[base]);
7357 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7358 int fd, int fr, int fs, int ft)
7360 const char *opn = "flt3_arith";
7362 switch (opc) {
7363 case OPC_ALNV_PS:
7364 check_cp1_64bitmode(ctx);
7366 TCGv t0 = tcg_temp_local_new();
7367 TCGv_i32 fp0 = tcg_temp_local_new_i32();
7368 TCGv_i32 fph0 = tcg_temp_local_new_i32();
7369 TCGv_i32 fp1 = tcg_temp_local_new_i32();
7370 TCGv_i32 fph1 = tcg_temp_local_new_i32();
7371 int l1 = gen_new_label();
7372 int l2 = gen_new_label();
7374 gen_load_gpr(t0, fr);
7375 tcg_gen_andi_tl(t0, t0, 0x7);
7376 gen_load_fpr32(fp0, fs);
7377 gen_load_fpr32h(fph0, fs);
7378 gen_load_fpr32(fp1, ft);
7379 gen_load_fpr32h(fph1, ft);
7381 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7382 gen_store_fpr32(fp0, fd);
7383 gen_store_fpr32h(fph0, fd);
7384 tcg_gen_br(l2);
7385 gen_set_label(l1);
7386 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7387 tcg_temp_free(t0);
7388 #ifdef TARGET_WORDS_BIGENDIAN
7389 gen_store_fpr32(fph1, fd);
7390 gen_store_fpr32h(fp0, fd);
7391 #else
7392 gen_store_fpr32(fph0, fd);
7393 gen_store_fpr32h(fp1, fd);
7394 #endif
7395 gen_set_label(l2);
7396 tcg_temp_free_i32(fp0);
7397 tcg_temp_free_i32(fph0);
7398 tcg_temp_free_i32(fp1);
7399 tcg_temp_free_i32(fph1);
7401 opn = "alnv.ps";
7402 break;
7403 case OPC_MADD_S:
7404 check_cop1x(ctx);
7406 TCGv_i32 fp0 = tcg_temp_new_i32();
7407 TCGv_i32 fp1 = tcg_temp_new_i32();
7408 TCGv_i32 fp2 = tcg_temp_new_i32();
7410 gen_load_fpr32(fp0, fs);
7411 gen_load_fpr32(fp1, ft);
7412 gen_load_fpr32(fp2, fr);
7413 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7414 tcg_temp_free_i32(fp0);
7415 tcg_temp_free_i32(fp1);
7416 gen_store_fpr32(fp2, fd);
7417 tcg_temp_free_i32(fp2);
7419 opn = "madd.s";
7420 break;
7421 case OPC_MADD_D:
7422 check_cop1x(ctx);
7423 check_cp1_registers(ctx, fd | fs | ft | fr);
7425 TCGv_i64 fp0 = tcg_temp_new_i64();
7426 TCGv_i64 fp1 = tcg_temp_new_i64();
7427 TCGv_i64 fp2 = tcg_temp_new_i64();
7429 gen_load_fpr64(ctx, fp0, fs);
7430 gen_load_fpr64(ctx, fp1, ft);
7431 gen_load_fpr64(ctx, fp2, fr);
7432 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7433 tcg_temp_free_i64(fp0);
7434 tcg_temp_free_i64(fp1);
7435 gen_store_fpr64(ctx, fp2, fd);
7436 tcg_temp_free_i64(fp2);
7438 opn = "madd.d";
7439 break;
7440 case OPC_MADD_PS:
7441 check_cp1_64bitmode(ctx);
7443 TCGv_i64 fp0 = tcg_temp_new_i64();
7444 TCGv_i64 fp1 = tcg_temp_new_i64();
7445 TCGv_i64 fp2 = tcg_temp_new_i64();
7447 gen_load_fpr64(ctx, fp0, fs);
7448 gen_load_fpr64(ctx, fp1, ft);
7449 gen_load_fpr64(ctx, fp2, fr);
7450 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7451 tcg_temp_free_i64(fp0);
7452 tcg_temp_free_i64(fp1);
7453 gen_store_fpr64(ctx, fp2, fd);
7454 tcg_temp_free_i64(fp2);
7456 opn = "madd.ps";
7457 break;
7458 case OPC_MSUB_S:
7459 check_cop1x(ctx);
7461 TCGv_i32 fp0 = tcg_temp_new_i32();
7462 TCGv_i32 fp1 = tcg_temp_new_i32();
7463 TCGv_i32 fp2 = tcg_temp_new_i32();
7465 gen_load_fpr32(fp0, fs);
7466 gen_load_fpr32(fp1, ft);
7467 gen_load_fpr32(fp2, fr);
7468 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7469 tcg_temp_free_i32(fp0);
7470 tcg_temp_free_i32(fp1);
7471 gen_store_fpr32(fp2, fd);
7472 tcg_temp_free_i32(fp2);
7474 opn = "msub.s";
7475 break;
7476 case OPC_MSUB_D:
7477 check_cop1x(ctx);
7478 check_cp1_registers(ctx, fd | fs | ft | fr);
7480 TCGv_i64 fp0 = tcg_temp_new_i64();
7481 TCGv_i64 fp1 = tcg_temp_new_i64();
7482 TCGv_i64 fp2 = tcg_temp_new_i64();
7484 gen_load_fpr64(ctx, fp0, fs);
7485 gen_load_fpr64(ctx, fp1, ft);
7486 gen_load_fpr64(ctx, fp2, fr);
7487 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7488 tcg_temp_free_i64(fp0);
7489 tcg_temp_free_i64(fp1);
7490 gen_store_fpr64(ctx, fp2, fd);
7491 tcg_temp_free_i64(fp2);
7493 opn = "msub.d";
7494 break;
7495 case OPC_MSUB_PS:
7496 check_cp1_64bitmode(ctx);
7498 TCGv_i64 fp0 = tcg_temp_new_i64();
7499 TCGv_i64 fp1 = tcg_temp_new_i64();
7500 TCGv_i64 fp2 = tcg_temp_new_i64();
7502 gen_load_fpr64(ctx, fp0, fs);
7503 gen_load_fpr64(ctx, fp1, ft);
7504 gen_load_fpr64(ctx, fp2, fr);
7505 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7506 tcg_temp_free_i64(fp0);
7507 tcg_temp_free_i64(fp1);
7508 gen_store_fpr64(ctx, fp2, fd);
7509 tcg_temp_free_i64(fp2);
7511 opn = "msub.ps";
7512 break;
7513 case OPC_NMADD_S:
7514 check_cop1x(ctx);
7516 TCGv_i32 fp0 = tcg_temp_new_i32();
7517 TCGv_i32 fp1 = tcg_temp_new_i32();
7518 TCGv_i32 fp2 = tcg_temp_new_i32();
7520 gen_load_fpr32(fp0, fs);
7521 gen_load_fpr32(fp1, ft);
7522 gen_load_fpr32(fp2, fr);
7523 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7524 tcg_temp_free_i32(fp0);
7525 tcg_temp_free_i32(fp1);
7526 gen_store_fpr32(fp2, fd);
7527 tcg_temp_free_i32(fp2);
7529 opn = "nmadd.s";
7530 break;
7531 case OPC_NMADD_D:
7532 check_cop1x(ctx);
7533 check_cp1_registers(ctx, fd | fs | ft | fr);
7535 TCGv_i64 fp0 = tcg_temp_new_i64();
7536 TCGv_i64 fp1 = tcg_temp_new_i64();
7537 TCGv_i64 fp2 = tcg_temp_new_i64();
7539 gen_load_fpr64(ctx, fp0, fs);
7540 gen_load_fpr64(ctx, fp1, ft);
7541 gen_load_fpr64(ctx, fp2, fr);
7542 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7543 tcg_temp_free_i64(fp0);
7544 tcg_temp_free_i64(fp1);
7545 gen_store_fpr64(ctx, fp2, fd);
7546 tcg_temp_free_i64(fp2);
7548 opn = "nmadd.d";
7549 break;
7550 case OPC_NMADD_PS:
7551 check_cp1_64bitmode(ctx);
7553 TCGv_i64 fp0 = tcg_temp_new_i64();
7554 TCGv_i64 fp1 = tcg_temp_new_i64();
7555 TCGv_i64 fp2 = tcg_temp_new_i64();
7557 gen_load_fpr64(ctx, fp0, fs);
7558 gen_load_fpr64(ctx, fp1, ft);
7559 gen_load_fpr64(ctx, fp2, fr);
7560 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7561 tcg_temp_free_i64(fp0);
7562 tcg_temp_free_i64(fp1);
7563 gen_store_fpr64(ctx, fp2, fd);
7564 tcg_temp_free_i64(fp2);
7566 opn = "nmadd.ps";
7567 break;
7568 case OPC_NMSUB_S:
7569 check_cop1x(ctx);
7571 TCGv_i32 fp0 = tcg_temp_new_i32();
7572 TCGv_i32 fp1 = tcg_temp_new_i32();
7573 TCGv_i32 fp2 = tcg_temp_new_i32();
7575 gen_load_fpr32(fp0, fs);
7576 gen_load_fpr32(fp1, ft);
7577 gen_load_fpr32(fp2, fr);
7578 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7579 tcg_temp_free_i32(fp0);
7580 tcg_temp_free_i32(fp1);
7581 gen_store_fpr32(fp2, fd);
7582 tcg_temp_free_i32(fp2);
7584 opn = "nmsub.s";
7585 break;
7586 case OPC_NMSUB_D:
7587 check_cop1x(ctx);
7588 check_cp1_registers(ctx, fd | fs | ft | fr);
7590 TCGv_i64 fp0 = tcg_temp_new_i64();
7591 TCGv_i64 fp1 = tcg_temp_new_i64();
7592 TCGv_i64 fp2 = tcg_temp_new_i64();
7594 gen_load_fpr64(ctx, fp0, fs);
7595 gen_load_fpr64(ctx, fp1, ft);
7596 gen_load_fpr64(ctx, fp2, fr);
7597 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7598 tcg_temp_free_i64(fp0);
7599 tcg_temp_free_i64(fp1);
7600 gen_store_fpr64(ctx, fp2, fd);
7601 tcg_temp_free_i64(fp2);
7603 opn = "nmsub.d";
7604 break;
7605 case OPC_NMSUB_PS:
7606 check_cp1_64bitmode(ctx);
7608 TCGv_i64 fp0 = tcg_temp_new_i64();
7609 TCGv_i64 fp1 = tcg_temp_new_i64();
7610 TCGv_i64 fp2 = tcg_temp_new_i64();
7612 gen_load_fpr64(ctx, fp0, fs);
7613 gen_load_fpr64(ctx, fp1, ft);
7614 gen_load_fpr64(ctx, fp2, fr);
7615 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7616 tcg_temp_free_i64(fp0);
7617 tcg_temp_free_i64(fp1);
7618 gen_store_fpr64(ctx, fp2, fd);
7619 tcg_temp_free_i64(fp2);
7621 opn = "nmsub.ps";
7622 break;
7623 default:
7624 MIPS_INVAL(opn);
7625 generate_exception (ctx, EXCP_RI);
7626 return;
7628 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7629 fregnames[fs], fregnames[ft]);
7632 /* ISA extensions (ASEs) */
7633 /* MIPS16 extension to MIPS32 */
7634 /* SmartMIPS extension to MIPS32 */
7636 #if defined(TARGET_MIPS64)
7638 /* MDMX extension to MIPS64 */
7640 #endif
7642 static void decode_opc (CPUState *env, DisasContext *ctx)
7644 int32_t offset;
7645 int rs, rt, rd, sa;
7646 uint32_t op, op1, op2;
7647 int16_t imm;
7649 /* make sure instructions are on a word boundary */
7650 if (ctx->pc & 0x3) {
7651 env->CP0_BadVAddr = ctx->pc;
7652 generate_exception(ctx, EXCP_AdEL);
7653 return;
7656 /* Handle blikely not taken case */
7657 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7658 int l1 = gen_new_label();
7660 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7661 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
7663 TCGv_i32 r_tmp = tcg_temp_new_i32();
7665 tcg_gen_movi_i32(r_tmp, ctx->hflags & ~MIPS_HFLAG_BMASK);
7666 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
7667 tcg_temp_free_i32(r_tmp);
7669 gen_goto_tb(ctx, 1, ctx->pc + 4);
7670 gen_set_label(l1);
7672 op = MASK_OP_MAJOR(ctx->opcode);
7673 rs = (ctx->opcode >> 21) & 0x1f;
7674 rt = (ctx->opcode >> 16) & 0x1f;
7675 rd = (ctx->opcode >> 11) & 0x1f;
7676 sa = (ctx->opcode >> 6) & 0x1f;
7677 imm = (int16_t)ctx->opcode;
7678 switch (op) {
7679 case OPC_SPECIAL:
7680 op1 = MASK_SPECIAL(ctx->opcode);
7681 switch (op1) {
7682 case OPC_SLL: /* Arithmetic with immediate */
7683 case OPC_SRL ... OPC_SRA:
7684 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7685 break;
7686 case OPC_MOVZ ... OPC_MOVN:
7687 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7688 case OPC_SLLV: /* Arithmetic */
7689 case OPC_SRLV ... OPC_SRAV:
7690 case OPC_ADD ... OPC_NOR:
7691 case OPC_SLT ... OPC_SLTU:
7692 gen_arith(env, ctx, op1, rd, rs, rt);
7693 break;
7694 case OPC_MULT ... OPC_DIVU:
7695 if (sa) {
7696 check_insn(env, ctx, INSN_VR54XX);
7697 op1 = MASK_MUL_VR54XX(ctx->opcode);
7698 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7699 } else
7700 gen_muldiv(ctx, op1, rs, rt);
7701 break;
7702 case OPC_JR ... OPC_JALR:
7703 gen_compute_branch(ctx, op1, rs, rd, sa);
7704 return;
7705 case OPC_TGE ... OPC_TEQ: /* Traps */
7706 case OPC_TNE:
7707 gen_trap(ctx, op1, rs, rt, -1);
7708 break;
7709 case OPC_MFHI: /* Move from HI/LO */
7710 case OPC_MFLO:
7711 gen_HILO(ctx, op1, rd);
7712 break;
7713 case OPC_MTHI:
7714 case OPC_MTLO: /* Move to HI/LO */
7715 gen_HILO(ctx, op1, rs);
7716 break;
7717 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7718 #ifdef MIPS_STRICT_STANDARD
7719 MIPS_INVAL("PMON / selsl");
7720 generate_exception(ctx, EXCP_RI);
7721 #else
7722 gen_helper_0i(pmon, sa);
7723 #endif
7724 break;
7725 case OPC_SYSCALL:
7726 generate_exception(ctx, EXCP_SYSCALL);
7727 break;
7728 case OPC_BREAK:
7729 generate_exception(ctx, EXCP_BREAK);
7730 break;
7731 case OPC_SPIM:
7732 #ifdef MIPS_STRICT_STANDARD
7733 MIPS_INVAL("SPIM");
7734 generate_exception(ctx, EXCP_RI);
7735 #else
7736 /* Implemented as RI exception for now. */
7737 MIPS_INVAL("spim (unofficial)");
7738 generate_exception(ctx, EXCP_RI);
7739 #endif
7740 break;
7741 case OPC_SYNC:
7742 /* Treat as NOP. */
7743 break;
7745 case OPC_MOVCI:
7746 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7747 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7748 save_cpu_state(ctx, 1);
7749 check_cp1_enabled(ctx);
7750 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7751 (ctx->opcode >> 16) & 1);
7752 } else {
7753 generate_exception_err(ctx, EXCP_CpU, 1);
7755 break;
7757 #if defined(TARGET_MIPS64)
7758 /* MIPS64 specific opcodes */
7759 case OPC_DSLL:
7760 case OPC_DSRL ... OPC_DSRA:
7761 case OPC_DSLL32:
7762 case OPC_DSRL32 ... OPC_DSRA32:
7763 check_insn(env, ctx, ISA_MIPS3);
7764 check_mips_64(ctx);
7765 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7766 break;
7767 case OPC_DSLLV:
7768 case OPC_DSRLV ... OPC_DSRAV:
7769 case OPC_DADD ... OPC_DSUBU:
7770 check_insn(env, ctx, ISA_MIPS3);
7771 check_mips_64(ctx);
7772 gen_arith(env, ctx, op1, rd, rs, rt);
7773 break;
7774 case OPC_DMULT ... OPC_DDIVU:
7775 check_insn(env, ctx, ISA_MIPS3);
7776 check_mips_64(ctx);
7777 gen_muldiv(ctx, op1, rs, rt);
7778 break;
7779 #endif
7780 default: /* Invalid */
7781 MIPS_INVAL("special");
7782 generate_exception(ctx, EXCP_RI);
7783 break;
7785 break;
7786 case OPC_SPECIAL2:
7787 op1 = MASK_SPECIAL2(ctx->opcode);
7788 switch (op1) {
7789 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7790 case OPC_MSUB ... OPC_MSUBU:
7791 check_insn(env, ctx, ISA_MIPS32);
7792 gen_muldiv(ctx, op1, rs, rt);
7793 break;
7794 case OPC_MUL:
7795 gen_arith(env, ctx, op1, rd, rs, rt);
7796 break;
7797 case OPC_CLZ ... OPC_CLO:
7798 check_insn(env, ctx, ISA_MIPS32);
7799 gen_cl(ctx, op1, rd, rs);
7800 break;
7801 case OPC_SDBBP:
7802 /* XXX: not clear which exception should be raised
7803 * when in debug mode...
7805 check_insn(env, ctx, ISA_MIPS32);
7806 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7807 generate_exception(ctx, EXCP_DBp);
7808 } else {
7809 generate_exception(ctx, EXCP_DBp);
7811 /* Treat as NOP. */
7812 break;
7813 #if defined(TARGET_MIPS64)
7814 case OPC_DCLZ ... OPC_DCLO:
7815 check_insn(env, ctx, ISA_MIPS64);
7816 check_mips_64(ctx);
7817 gen_cl(ctx, op1, rd, rs);
7818 break;
7819 #endif
7820 default: /* Invalid */
7821 MIPS_INVAL("special2");
7822 generate_exception(ctx, EXCP_RI);
7823 break;
7825 break;
7826 case OPC_SPECIAL3:
7827 op1 = MASK_SPECIAL3(ctx->opcode);
7828 switch (op1) {
7829 case OPC_EXT:
7830 case OPC_INS:
7831 check_insn(env, ctx, ISA_MIPS32R2);
7832 gen_bitops(ctx, op1, rt, rs, sa, rd);
7833 break;
7834 case OPC_BSHFL:
7835 check_insn(env, ctx, ISA_MIPS32R2);
7836 op2 = MASK_BSHFL(ctx->opcode);
7837 gen_bshfl(ctx, op2, rt, rd);
7838 break;
7839 case OPC_RDHWR:
7840 check_insn(env, ctx, ISA_MIPS32R2);
7842 TCGv t0 = tcg_temp_local_new();
7844 switch (rd) {
7845 case 0:
7846 save_cpu_state(ctx, 1);
7847 gen_helper_rdhwr_cpunum(t0);
7848 break;
7849 case 1:
7850 save_cpu_state(ctx, 1);
7851 gen_helper_rdhwr_synci_step(t0);
7852 break;
7853 case 2:
7854 save_cpu_state(ctx, 1);
7855 gen_helper_rdhwr_cc(t0);
7856 break;
7857 case 3:
7858 save_cpu_state(ctx, 1);
7859 gen_helper_rdhwr_ccres(t0);
7860 break;
7861 case 29:
7862 if (env->user_mode_only) {
7863 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7864 break;
7865 } else {
7866 /* XXX: Some CPUs implement this in hardware.
7867 Not supported yet. */
7869 default: /* Invalid */
7870 MIPS_INVAL("rdhwr");
7871 generate_exception(ctx, EXCP_RI);
7872 break;
7874 gen_store_gpr(t0, rt);
7875 tcg_temp_free(t0);
7877 break;
7878 case OPC_FORK:
7879 check_insn(env, ctx, ASE_MT);
7881 TCGv t0 = tcg_temp_local_new();
7882 TCGv t1 = tcg_temp_local_new();
7884 gen_load_gpr(t0, rt);
7885 gen_load_gpr(t1, rs);
7886 gen_helper_fork(t0, t1);
7887 tcg_temp_free(t0);
7888 tcg_temp_free(t1);
7890 break;
7891 case OPC_YIELD:
7892 check_insn(env, ctx, ASE_MT);
7894 TCGv t0 = tcg_temp_local_new();
7896 gen_load_gpr(t0, rs);
7897 gen_helper_yield(t0, t0);
7898 gen_store_gpr(t0, rd);
7899 tcg_temp_free(t0);
7901 break;
7902 #if defined(TARGET_MIPS64)
7903 case OPC_DEXTM ... OPC_DEXT:
7904 case OPC_DINSM ... OPC_DINS:
7905 check_insn(env, ctx, ISA_MIPS64R2);
7906 check_mips_64(ctx);
7907 gen_bitops(ctx, op1, rt, rs, sa, rd);
7908 break;
7909 case OPC_DBSHFL:
7910 check_insn(env, ctx, ISA_MIPS64R2);
7911 check_mips_64(ctx);
7912 op2 = MASK_DBSHFL(ctx->opcode);
7913 gen_bshfl(ctx, op2, rt, rd);
7914 break;
7915 #endif
7916 default: /* Invalid */
7917 MIPS_INVAL("special3");
7918 generate_exception(ctx, EXCP_RI);
7919 break;
7921 break;
7922 case OPC_REGIMM:
7923 op1 = MASK_REGIMM(ctx->opcode);
7924 switch (op1) {
7925 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7926 case OPC_BLTZAL ... OPC_BGEZALL:
7927 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
7928 return;
7929 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7930 case OPC_TNEI:
7931 gen_trap(ctx, op1, rs, -1, imm);
7932 break;
7933 case OPC_SYNCI:
7934 check_insn(env, ctx, ISA_MIPS32R2);
7935 /* Treat as NOP. */
7936 break;
7937 default: /* Invalid */
7938 MIPS_INVAL("regimm");
7939 generate_exception(ctx, EXCP_RI);
7940 break;
7942 break;
7943 case OPC_CP0:
7944 check_cp0_enabled(ctx);
7945 op1 = MASK_CP0(ctx->opcode);
7946 switch (op1) {
7947 case OPC_MFC0:
7948 case OPC_MTC0:
7949 case OPC_MFTR:
7950 case OPC_MTTR:
7951 #if defined(TARGET_MIPS64)
7952 case OPC_DMFC0:
7953 case OPC_DMTC0:
7954 #endif
7955 #ifndef CONFIG_USER_ONLY
7956 if (!env->user_mode_only)
7957 gen_cp0(env, ctx, op1, rt, rd);
7958 #endif /* !CONFIG_USER_ONLY */
7959 break;
7960 case OPC_C0_FIRST ... OPC_C0_LAST:
7961 #ifndef CONFIG_USER_ONLY
7962 if (!env->user_mode_only)
7963 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
7964 #endif /* !CONFIG_USER_ONLY */
7965 break;
7966 case OPC_MFMC0:
7967 #ifndef CONFIG_USER_ONLY
7968 if (!env->user_mode_only) {
7969 TCGv t0 = tcg_temp_local_new();
7971 op2 = MASK_MFMC0(ctx->opcode);
7972 switch (op2) {
7973 case OPC_DMT:
7974 check_insn(env, ctx, ASE_MT);
7975 gen_helper_dmt(t0, t0);
7976 break;
7977 case OPC_EMT:
7978 check_insn(env, ctx, ASE_MT);
7979 gen_helper_emt(t0, t0);
7980 break;
7981 case OPC_DVPE:
7982 check_insn(env, ctx, ASE_MT);
7983 gen_helper_dvpe(t0, t0);
7984 break;
7985 case OPC_EVPE:
7986 check_insn(env, ctx, ASE_MT);
7987 gen_helper_evpe(t0, t0);
7988 break;
7989 case OPC_DI:
7990 check_insn(env, ctx, ISA_MIPS32R2);
7991 save_cpu_state(ctx, 1);
7992 gen_helper_di(t0);
7993 /* Stop translation as we may have switched the execution mode */
7994 ctx->bstate = BS_STOP;
7995 break;
7996 case OPC_EI:
7997 check_insn(env, ctx, ISA_MIPS32R2);
7998 save_cpu_state(ctx, 1);
7999 gen_helper_ei(t0);
8000 /* Stop translation as we may have switched the execution mode */
8001 ctx->bstate = BS_STOP;
8002 break;
8003 default: /* Invalid */
8004 MIPS_INVAL("mfmc0");
8005 generate_exception(ctx, EXCP_RI);
8006 break;
8008 gen_store_gpr(t0, rt);
8009 tcg_temp_free(t0);
8011 #endif /* !CONFIG_USER_ONLY */
8012 break;
8013 case OPC_RDPGPR:
8014 check_insn(env, ctx, ISA_MIPS32R2);
8015 gen_load_srsgpr(rt, rd);
8016 break;
8017 case OPC_WRPGPR:
8018 check_insn(env, ctx, ISA_MIPS32R2);
8019 gen_store_srsgpr(rt, rd);
8020 break;
8021 default:
8022 MIPS_INVAL("cp0");
8023 generate_exception(ctx, EXCP_RI);
8024 break;
8026 break;
8027 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
8028 gen_arith_imm(env, ctx, op, rt, rs, imm);
8029 break;
8030 case OPC_J ... OPC_JAL: /* Jump */
8031 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8032 gen_compute_branch(ctx, op, rs, rt, offset);
8033 return;
8034 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8035 case OPC_BEQL ... OPC_BGTZL:
8036 gen_compute_branch(ctx, op, rs, rt, imm << 2);
8037 return;
8038 case OPC_LB ... OPC_LWR: /* Load and stores */
8039 case OPC_SB ... OPC_SW:
8040 case OPC_SWR:
8041 case OPC_LL:
8042 case OPC_SC:
8043 gen_ldst(ctx, op, rt, rs, imm);
8044 break;
8045 case OPC_CACHE:
8046 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
8047 /* Treat as NOP. */
8048 break;
8049 case OPC_PREF:
8050 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8051 /* Treat as NOP. */
8052 break;
8054 /* Floating point (COP1). */
8055 case OPC_LWC1:
8056 case OPC_LDC1:
8057 case OPC_SWC1:
8058 case OPC_SDC1:
8059 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8060 save_cpu_state(ctx, 1);
8061 check_cp1_enabled(ctx);
8062 gen_flt_ldst(ctx, op, rt, rs, imm);
8063 } else {
8064 generate_exception_err(ctx, EXCP_CpU, 1);
8066 break;
8068 case OPC_CP1:
8069 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8070 save_cpu_state(ctx, 1);
8071 check_cp1_enabled(ctx);
8072 op1 = MASK_CP1(ctx->opcode);
8073 switch (op1) {
8074 case OPC_MFHC1:
8075 case OPC_MTHC1:
8076 check_insn(env, ctx, ISA_MIPS32R2);
8077 case OPC_MFC1:
8078 case OPC_CFC1:
8079 case OPC_MTC1:
8080 case OPC_CTC1:
8081 gen_cp1(ctx, op1, rt, rd);
8082 break;
8083 #if defined(TARGET_MIPS64)
8084 case OPC_DMFC1:
8085 case OPC_DMTC1:
8086 check_insn(env, ctx, ISA_MIPS3);
8087 gen_cp1(ctx, op1, rt, rd);
8088 break;
8089 #endif
8090 case OPC_BC1ANY2:
8091 case OPC_BC1ANY4:
8092 check_cop1x(ctx);
8093 check_insn(env, ctx, ASE_MIPS3D);
8094 /* fall through */
8095 case OPC_BC1:
8096 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8097 (rt >> 2) & 0x7, imm << 2);
8098 return;
8099 case OPC_S_FMT:
8100 case OPC_D_FMT:
8101 case OPC_W_FMT:
8102 case OPC_L_FMT:
8103 case OPC_PS_FMT:
8104 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8105 (imm >> 8) & 0x7);
8106 break;
8107 default:
8108 MIPS_INVAL("cp1");
8109 generate_exception (ctx, EXCP_RI);
8110 break;
8112 } else {
8113 generate_exception_err(ctx, EXCP_CpU, 1);
8115 break;
8117 /* COP2. */
8118 case OPC_LWC2:
8119 case OPC_LDC2:
8120 case OPC_SWC2:
8121 case OPC_SDC2:
8122 case OPC_CP2:
8123 /* COP2: Not implemented. */
8124 generate_exception_err(ctx, EXCP_CpU, 2);
8125 break;
8127 case OPC_CP3:
8128 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8129 save_cpu_state(ctx, 1);
8130 check_cp1_enabled(ctx);
8131 op1 = MASK_CP3(ctx->opcode);
8132 switch (op1) {
8133 case OPC_LWXC1:
8134 case OPC_LDXC1:
8135 case OPC_LUXC1:
8136 case OPC_SWXC1:
8137 case OPC_SDXC1:
8138 case OPC_SUXC1:
8139 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8140 break;
8141 case OPC_PREFX:
8142 /* Treat as NOP. */
8143 break;
8144 case OPC_ALNV_PS:
8145 case OPC_MADD_S:
8146 case OPC_MADD_D:
8147 case OPC_MADD_PS:
8148 case OPC_MSUB_S:
8149 case OPC_MSUB_D:
8150 case OPC_MSUB_PS:
8151 case OPC_NMADD_S:
8152 case OPC_NMADD_D:
8153 case OPC_NMADD_PS:
8154 case OPC_NMSUB_S:
8155 case OPC_NMSUB_D:
8156 case OPC_NMSUB_PS:
8157 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8158 break;
8159 default:
8160 MIPS_INVAL("cp3");
8161 generate_exception (ctx, EXCP_RI);
8162 break;
8164 } else {
8165 generate_exception_err(ctx, EXCP_CpU, 1);
8167 break;
8169 #if defined(TARGET_MIPS64)
8170 /* MIPS64 opcodes */
8171 case OPC_LWU:
8172 case OPC_LDL ... OPC_LDR:
8173 case OPC_SDL ... OPC_SDR:
8174 case OPC_LLD:
8175 case OPC_LD:
8176 case OPC_SCD:
8177 case OPC_SD:
8178 check_insn(env, ctx, ISA_MIPS3);
8179 check_mips_64(ctx);
8180 gen_ldst(ctx, op, rt, rs, imm);
8181 break;
8182 case OPC_DADDI ... OPC_DADDIU:
8183 check_insn(env, ctx, ISA_MIPS3);
8184 check_mips_64(ctx);
8185 gen_arith_imm(env, ctx, op, rt, rs, imm);
8186 break;
8187 #endif
8188 case OPC_JALX:
8189 check_insn(env, ctx, ASE_MIPS16);
8190 /* MIPS16: Not implemented. */
8191 case OPC_MDMX:
8192 check_insn(env, ctx, ASE_MDMX);
8193 /* MDMX: Not implemented. */
8194 default: /* Invalid */
8195 MIPS_INVAL("major opcode");
8196 generate_exception(ctx, EXCP_RI);
8197 break;
8199 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8200 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8201 /* Branches completion */
8202 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8203 ctx->bstate = BS_BRANCH;
8204 save_cpu_state(ctx, 0);
8205 /* FIXME: Need to clear can_do_io. */
8206 switch (hflags) {
8207 case MIPS_HFLAG_B:
8208 /* unconditional branch */
8209 MIPS_DEBUG("unconditional branch");
8210 gen_goto_tb(ctx, 0, ctx->btarget);
8211 break;
8212 case MIPS_HFLAG_BL:
8213 /* blikely taken case */
8214 MIPS_DEBUG("blikely branch taken");
8215 gen_goto_tb(ctx, 0, ctx->btarget);
8216 break;
8217 case MIPS_HFLAG_BC:
8218 /* Conditional branch */
8219 MIPS_DEBUG("conditional branch");
8221 int l1 = gen_new_label();
8223 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
8224 gen_goto_tb(ctx, 1, ctx->pc + 4);
8225 gen_set_label(l1);
8226 gen_goto_tb(ctx, 0, ctx->btarget);
8228 break;
8229 case MIPS_HFLAG_BR:
8230 /* unconditional branch to register */
8231 MIPS_DEBUG("branch to register");
8232 tcg_gen_mov_tl(cpu_PC, btarget);
8233 tcg_gen_exit_tb(0);
8234 break;
8235 default:
8236 MIPS_DEBUG("unknown branch");
8237 break;
8242 static inline void
8243 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8244 int search_pc)
8246 DisasContext ctx;
8247 target_ulong pc_start;
8248 uint16_t *gen_opc_end;
8249 CPUBreakpoint *bp;
8250 int j, lj = -1;
8251 int num_insns;
8252 int max_insns;
8254 if (search_pc && loglevel)
8255 fprintf (logfile, "search pc %d\n", search_pc);
8257 pc_start = tb->pc;
8258 /* Leave some spare opc slots for branch handling. */
8259 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
8260 ctx.pc = pc_start;
8261 ctx.saved_pc = -1;
8262 ctx.tb = tb;
8263 ctx.bstate = BS_NONE;
8264 /* Restore delay slot state from the tb context. */
8265 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8266 restore_cpu_state(env, &ctx);
8267 if (env->user_mode_only)
8268 ctx.mem_idx = MIPS_HFLAG_UM;
8269 else
8270 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8271 num_insns = 0;
8272 max_insns = tb->cflags & CF_COUNT_MASK;
8273 if (max_insns == 0)
8274 max_insns = CF_COUNT_MASK;
8275 #ifdef DEBUG_DISAS
8276 if (loglevel & CPU_LOG_TB_CPU) {
8277 fprintf(logfile, "------------------------------------------------\n");
8278 /* FIXME: This may print out stale hflags from env... */
8279 cpu_dump_state(env, logfile, fprintf, 0);
8281 #endif
8282 #ifdef MIPS_DEBUG_DISAS
8283 if (loglevel & CPU_LOG_TB_IN_ASM)
8284 fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
8285 tb, ctx.mem_idx, ctx.hflags);
8286 #endif
8287 gen_icount_start();
8288 while (ctx.bstate == BS_NONE) {
8289 if (unlikely(env->breakpoints)) {
8290 for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
8291 if (bp->pc == ctx.pc) {
8292 save_cpu_state(&ctx, 1);
8293 ctx.bstate = BS_BRANCH;
8294 gen_helper_0i(raise_exception, EXCP_DEBUG);
8295 /* Include the breakpoint location or the tb won't
8296 * be flushed when it must be. */
8297 ctx.pc += 4;
8298 goto done_generating;
8303 if (search_pc) {
8304 j = gen_opc_ptr - gen_opc_buf;
8305 if (lj < j) {
8306 lj++;
8307 while (lj < j)
8308 gen_opc_instr_start[lj++] = 0;
8310 gen_opc_pc[lj] = ctx.pc;
8311 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8312 gen_opc_instr_start[lj] = 1;
8313 gen_opc_icount[lj] = num_insns;
8315 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8316 gen_io_start();
8317 ctx.opcode = ldl_code(ctx.pc);
8318 decode_opc(env, &ctx);
8319 ctx.pc += 4;
8320 num_insns++;
8322 if (env->singlestep_enabled)
8323 break;
8325 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8326 break;
8328 if (gen_opc_ptr >= gen_opc_end)
8329 break;
8331 if (num_insns >= max_insns)
8332 break;
8333 #if defined (MIPS_SINGLE_STEP)
8334 break;
8335 #endif
8337 if (tb->cflags & CF_LAST_IO)
8338 gen_io_end();
8339 if (env->singlestep_enabled) {
8340 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
8341 gen_helper_0i(raise_exception, EXCP_DEBUG);
8342 } else {
8343 switch (ctx.bstate) {
8344 case BS_STOP:
8345 gen_helper_interrupt_restart();
8346 gen_goto_tb(&ctx, 0, ctx.pc);
8347 break;
8348 case BS_NONE:
8349 save_cpu_state(&ctx, 0);
8350 gen_goto_tb(&ctx, 0, ctx.pc);
8351 break;
8352 case BS_EXCP:
8353 gen_helper_interrupt_restart();
8354 tcg_gen_exit_tb(0);
8355 break;
8356 case BS_BRANCH:
8357 default:
8358 break;
8361 done_generating:
8362 gen_icount_end(tb, num_insns);
8363 *gen_opc_ptr = INDEX_op_end;
8364 if (search_pc) {
8365 j = gen_opc_ptr - gen_opc_buf;
8366 lj++;
8367 while (lj <= j)
8368 gen_opc_instr_start[lj++] = 0;
8369 } else {
8370 tb->size = ctx.pc - pc_start;
8371 tb->icount = num_insns;
8373 #ifdef DEBUG_DISAS
8374 #if defined MIPS_DEBUG_DISAS
8375 if (loglevel & CPU_LOG_TB_IN_ASM)
8376 fprintf(logfile, "\n");
8377 #endif
8378 if (loglevel & CPU_LOG_TB_IN_ASM) {
8379 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
8380 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
8381 fprintf(logfile, "\n");
8383 if (loglevel & CPU_LOG_TB_CPU) {
8384 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8386 #endif
8389 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8391 gen_intermediate_code_internal(env, tb, 0);
8394 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8396 gen_intermediate_code_internal(env, tb, 1);
8399 static void fpu_dump_state(CPUState *env, FILE *f,
8400 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8401 int flags)
8403 int i;
8404 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8406 #define printfpr(fp) \
8407 do { \
8408 if (is_fpu64) \
8409 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8410 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8411 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8412 else { \
8413 fpr_t tmp; \
8414 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8415 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8416 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8417 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8418 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8420 } while(0)
8423 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8424 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8425 get_float_exception_flags(&env->active_fpu.fp_status));
8426 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8427 fpu_fprintf(f, "%3s: ", fregnames[i]);
8428 printfpr(&env->active_fpu.fpr[i]);
8431 #undef printfpr
8434 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8435 /* Debug help: The architecture requires 32bit code to maintain proper
8436 sign-extended values on 64bit machines. */
8438 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8440 static void
8441 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8442 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8443 int flags)
8445 int i;
8447 if (!SIGN_EXT_P(env->active_tc.PC))
8448 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8449 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8450 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8451 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8452 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8453 if (!SIGN_EXT_P(env->btarget))
8454 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8456 for (i = 0; i < 32; i++) {
8457 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8458 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8461 if (!SIGN_EXT_P(env->CP0_EPC))
8462 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8463 if (!SIGN_EXT_P(env->CP0_LLAddr))
8464 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
8466 #endif
8468 void cpu_dump_state (CPUState *env, FILE *f,
8469 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8470 int flags)
8472 int i;
8474 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",
8475 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8476 env->hflags, env->btarget, env->bcond);
8477 for (i = 0; i < 32; i++) {
8478 if ((i & 3) == 0)
8479 cpu_fprintf(f, "GPR%02d:", i);
8480 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8481 if ((i & 3) == 3)
8482 cpu_fprintf(f, "\n");
8485 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8486 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8487 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8488 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
8489 if (env->hflags & MIPS_HFLAG_FPU)
8490 fpu_dump_state(env, f, cpu_fprintf, flags);
8491 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8492 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8493 #endif
8496 static void mips_tcg_init(void)
8498 int i;
8499 static int inited;
8501 /* Initialize various static tables. */
8502 if (inited)
8503 return;
8505 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8506 for (i = 0; i < 32; i++)
8507 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
8508 offsetof(CPUState, active_tc.gpr[i]),
8509 regnames[i]);
8510 cpu_PC = tcg_global_mem_new(TCG_AREG0,
8511 offsetof(CPUState, active_tc.PC), "PC");
8512 for (i = 0; i < MIPS_DSP_ACC; i++) {
8513 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
8514 offsetof(CPUState, active_tc.HI[i]),
8515 regnames_HI[i]);
8516 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
8517 offsetof(CPUState, active_tc.LO[i]),
8518 regnames_LO[i]);
8519 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
8520 offsetof(CPUState, active_tc.ACX[i]),
8521 regnames_ACX[i]);
8523 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
8524 offsetof(CPUState, active_tc.DSPControl),
8525 "DSPControl");
8526 bcond = tcg_global_mem_new_i32(TCG_AREG0,
8527 offsetof(CPUState, bcond), "bcond");
8528 btarget = tcg_global_mem_new(TCG_AREG0,
8529 offsetof(CPUState, btarget), "btarget");
8530 for (i = 0; i < 32; i++)
8531 fpu_fpr32[i] = tcg_global_mem_new_i32(TCG_AREG0,
8532 offsetof(CPUState, active_fpu.fpr[i].w[FP_ENDIAN_IDX]),
8533 fregnames[i]);
8534 for (i = 0; i < 32; i++)
8535 fpu_fpr64[i] = tcg_global_mem_new_i64(TCG_AREG0,
8536 offsetof(CPUState, active_fpu.fpr[i]),
8537 fregnames_64[i]);
8538 for (i = 0; i < 32; i++)
8539 fpu_fpr32h[i] = tcg_global_mem_new_i32(TCG_AREG0,
8540 offsetof(CPUState, active_fpu.fpr[i].w[!FP_ENDIAN_IDX]),
8541 fregnames_h[i]);
8542 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
8543 offsetof(CPUState, active_fpu.fcr0),
8544 "fcr0");
8545 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
8546 offsetof(CPUState, active_fpu.fcr31),
8547 "fcr31");
8549 /* register helpers */
8550 #define GEN_HELPER 2
8551 #include "helper.h"
8553 inited = 1;
8556 #include "translate_init.c"
8558 CPUMIPSState *cpu_mips_init (const char *cpu_model)
8560 CPUMIPSState *env;
8561 const mips_def_t *def;
8563 def = cpu_mips_find_by_name(cpu_model);
8564 if (!def)
8565 return NULL;
8566 env = qemu_mallocz(sizeof(CPUMIPSState));
8567 if (!env)
8568 return NULL;
8569 env->cpu_model = def;
8571 cpu_exec_init(env);
8572 env->cpu_model_str = cpu_model;
8573 mips_tcg_init();
8574 cpu_reset(env);
8575 return env;
8578 void cpu_reset (CPUMIPSState *env)
8580 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8582 tlb_flush(env, 1);
8584 /* Minimal init */
8585 #if defined(CONFIG_USER_ONLY)
8586 env->user_mode_only = 1;
8587 #endif
8588 if (env->user_mode_only) {
8589 env->hflags = MIPS_HFLAG_UM;
8590 } else {
8591 if (env->hflags & MIPS_HFLAG_BMASK) {
8592 /* If the exception was raised from a delay slot,
8593 come back to the jump. */
8594 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8595 } else {
8596 env->CP0_ErrorEPC = env->active_tc.PC;
8598 env->active_tc.PC = (int32_t)0xBFC00000;
8599 env->CP0_Wired = 0;
8600 /* SMP not implemented */
8601 env->CP0_EBase = 0x80000000;
8602 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8603 /* vectored interrupts not implemented, timer on int 7,
8604 no performance counters. */
8605 env->CP0_IntCtl = 0xe0000000;
8607 int i;
8609 for (i = 0; i < 7; i++) {
8610 env->CP0_WatchLo[i] = 0;
8611 env->CP0_WatchHi[i] = 0x80000000;
8613 env->CP0_WatchLo[7] = 0;
8614 env->CP0_WatchHi[7] = 0;
8616 /* Count register increments in debug mode, EJTAG version 1 */
8617 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8618 env->hflags = MIPS_HFLAG_CP0;
8620 env->exception_index = EXCP_NONE;
8621 cpu_mips_register(env, env->cpu_model);
8624 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8625 unsigned long searched_pc, int pc_pos, void *puc)
8627 env->active_tc.PC = gen_opc_pc[pc_pos];
8628 env->hflags &= ~MIPS_HFLAG_BMASK;
8629 env->hflags |= gen_opc_hflags[pc_pos];