qdev/prop: convert vga.c to helper macros.
[qemu/cris-port.git] / target-mips / translate.c
blob6a1273f0362b7a0b924d54491b9cde061406b208
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <inttypes.h>
28 #include "cpu.h"
29 #include "exec-all.h"
30 #include "disas.h"
31 #include "tcg-op.h"
32 #include "qemu-common.h"
34 #include "helper.h"
35 #define GEN_HELPER 1
36 #include "helper.h"
38 //#define MIPS_DEBUG_DISAS
39 //#define MIPS_DEBUG_SIGN_EXTENSIONS
41 /* MIPS major opcodes */
42 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
44 enum {
45 /* indirect opcode tables */
46 OPC_SPECIAL = (0x00 << 26),
47 OPC_REGIMM = (0x01 << 26),
48 OPC_CP0 = (0x10 << 26),
49 OPC_CP1 = (0x11 << 26),
50 OPC_CP2 = (0x12 << 26),
51 OPC_CP3 = (0x13 << 26),
52 OPC_SPECIAL2 = (0x1C << 26),
53 OPC_SPECIAL3 = (0x1F << 26),
54 /* arithmetic with immediate */
55 OPC_ADDI = (0x08 << 26),
56 OPC_ADDIU = (0x09 << 26),
57 OPC_SLTI = (0x0A << 26),
58 OPC_SLTIU = (0x0B << 26),
59 /* logic with immediate */
60 OPC_ANDI = (0x0C << 26),
61 OPC_ORI = (0x0D << 26),
62 OPC_XORI = (0x0E << 26),
63 OPC_LUI = (0x0F << 26),
64 /* arithmetic with immediate */
65 OPC_DADDI = (0x18 << 26),
66 OPC_DADDIU = (0x19 << 26),
67 /* Jump and branches */
68 OPC_J = (0x02 << 26),
69 OPC_JAL = (0x03 << 26),
70 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
71 OPC_BEQL = (0x14 << 26),
72 OPC_BNE = (0x05 << 26),
73 OPC_BNEL = (0x15 << 26),
74 OPC_BLEZ = (0x06 << 26),
75 OPC_BLEZL = (0x16 << 26),
76 OPC_BGTZ = (0x07 << 26),
77 OPC_BGTZL = (0x17 << 26),
78 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
79 /* Load and stores */
80 OPC_LDL = (0x1A << 26),
81 OPC_LDR = (0x1B << 26),
82 OPC_LB = (0x20 << 26),
83 OPC_LH = (0x21 << 26),
84 OPC_LWL = (0x22 << 26),
85 OPC_LW = (0x23 << 26),
86 OPC_LBU = (0x24 << 26),
87 OPC_LHU = (0x25 << 26),
88 OPC_LWR = (0x26 << 26),
89 OPC_LWU = (0x27 << 26),
90 OPC_SB = (0x28 << 26),
91 OPC_SH = (0x29 << 26),
92 OPC_SWL = (0x2A << 26),
93 OPC_SW = (0x2B << 26),
94 OPC_SDL = (0x2C << 26),
95 OPC_SDR = (0x2D << 26),
96 OPC_SWR = (0x2E << 26),
97 OPC_LL = (0x30 << 26),
98 OPC_LLD = (0x34 << 26),
99 OPC_LD = (0x37 << 26),
100 OPC_SC = (0x38 << 26),
101 OPC_SCD = (0x3C << 26),
102 OPC_SD = (0x3F << 26),
103 /* Floating point load/store */
104 OPC_LWC1 = (0x31 << 26),
105 OPC_LWC2 = (0x32 << 26),
106 OPC_LDC1 = (0x35 << 26),
107 OPC_LDC2 = (0x36 << 26),
108 OPC_SWC1 = (0x39 << 26),
109 OPC_SWC2 = (0x3A << 26),
110 OPC_SDC1 = (0x3D << 26),
111 OPC_SDC2 = (0x3E << 26),
112 /* MDMX ASE specific */
113 OPC_MDMX = (0x1E << 26),
114 /* Cache and prefetch */
115 OPC_CACHE = (0x2F << 26),
116 OPC_PREF = (0x33 << 26),
117 /* Reserved major opcode */
118 OPC_MAJOR3B_RESERVED = (0x3B << 26),
121 /* MIPS special opcodes */
122 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
124 enum {
125 /* Shifts */
126 OPC_SLL = 0x00 | OPC_SPECIAL,
127 /* NOP is SLL r0, r0, 0 */
128 /* SSNOP is SLL r0, r0, 1 */
129 /* EHB is SLL r0, r0, 3 */
130 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
131 OPC_SRA = 0x03 | OPC_SPECIAL,
132 OPC_SLLV = 0x04 | OPC_SPECIAL,
133 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
134 OPC_SRAV = 0x07 | OPC_SPECIAL,
135 OPC_DSLLV = 0x14 | OPC_SPECIAL,
136 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
137 OPC_DSRAV = 0x17 | OPC_SPECIAL,
138 OPC_DSLL = 0x38 | OPC_SPECIAL,
139 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
140 OPC_DSRA = 0x3B | OPC_SPECIAL,
141 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
142 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
143 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
144 /* Multiplication / division */
145 OPC_MULT = 0x18 | OPC_SPECIAL,
146 OPC_MULTU = 0x19 | OPC_SPECIAL,
147 OPC_DIV = 0x1A | OPC_SPECIAL,
148 OPC_DIVU = 0x1B | OPC_SPECIAL,
149 OPC_DMULT = 0x1C | OPC_SPECIAL,
150 OPC_DMULTU = 0x1D | OPC_SPECIAL,
151 OPC_DDIV = 0x1E | OPC_SPECIAL,
152 OPC_DDIVU = 0x1F | OPC_SPECIAL,
153 /* 2 registers arithmetic / logic */
154 OPC_ADD = 0x20 | OPC_SPECIAL,
155 OPC_ADDU = 0x21 | OPC_SPECIAL,
156 OPC_SUB = 0x22 | OPC_SPECIAL,
157 OPC_SUBU = 0x23 | OPC_SPECIAL,
158 OPC_AND = 0x24 | OPC_SPECIAL,
159 OPC_OR = 0x25 | OPC_SPECIAL,
160 OPC_XOR = 0x26 | OPC_SPECIAL,
161 OPC_NOR = 0x27 | OPC_SPECIAL,
162 OPC_SLT = 0x2A | OPC_SPECIAL,
163 OPC_SLTU = 0x2B | OPC_SPECIAL,
164 OPC_DADD = 0x2C | OPC_SPECIAL,
165 OPC_DADDU = 0x2D | OPC_SPECIAL,
166 OPC_DSUB = 0x2E | OPC_SPECIAL,
167 OPC_DSUBU = 0x2F | OPC_SPECIAL,
168 /* Jumps */
169 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
170 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
171 /* Traps */
172 OPC_TGE = 0x30 | OPC_SPECIAL,
173 OPC_TGEU = 0x31 | OPC_SPECIAL,
174 OPC_TLT = 0x32 | OPC_SPECIAL,
175 OPC_TLTU = 0x33 | OPC_SPECIAL,
176 OPC_TEQ = 0x34 | OPC_SPECIAL,
177 OPC_TNE = 0x36 | OPC_SPECIAL,
178 /* HI / LO registers load & stores */
179 OPC_MFHI = 0x10 | OPC_SPECIAL,
180 OPC_MTHI = 0x11 | OPC_SPECIAL,
181 OPC_MFLO = 0x12 | OPC_SPECIAL,
182 OPC_MTLO = 0x13 | OPC_SPECIAL,
183 /* Conditional moves */
184 OPC_MOVZ = 0x0A | OPC_SPECIAL,
185 OPC_MOVN = 0x0B | OPC_SPECIAL,
187 OPC_MOVCI = 0x01 | OPC_SPECIAL,
189 /* Special */
190 OPC_PMON = 0x05 | OPC_SPECIAL, /* 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, bcond;
433 static TCGv_i32 hflags;
434 static TCGv_i32 fpu_fcr0, fpu_fcr31;
436 #include "gen-icount.h"
438 #define gen_helper_0i(name, arg) do { \
439 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
440 gen_helper_##name(helper_tmp); \
441 tcg_temp_free_i32(helper_tmp); \
442 } while(0)
444 #define gen_helper_1i(name, arg1, arg2) do { \
445 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
446 gen_helper_##name(arg1, helper_tmp); \
447 tcg_temp_free_i32(helper_tmp); \
448 } while(0)
450 #define gen_helper_2i(name, arg1, arg2, arg3) do { \
451 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
452 gen_helper_##name(arg1, arg2, helper_tmp); \
453 tcg_temp_free_i32(helper_tmp); \
454 } while(0)
456 #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
457 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
458 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
459 tcg_temp_free_i32(helper_tmp); \
460 } while(0)
462 typedef struct DisasContext {
463 struct TranslationBlock *tb;
464 target_ulong pc, saved_pc;
465 uint32_t opcode;
466 /* Routine used to access memory */
467 int mem_idx;
468 uint32_t hflags, saved_hflags;
469 int bstate;
470 target_ulong btarget;
471 } DisasContext;
473 enum {
474 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
475 * exception condition */
476 BS_STOP = 1, /* We want to stop translation for any reason */
477 BS_BRANCH = 2, /* We reached a branch condition */
478 BS_EXCP = 3, /* We reached an exception condition */
481 static const char *regnames[] =
482 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
483 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
484 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
485 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
487 static const char *regnames_HI[] =
488 { "HI0", "HI1", "HI2", "HI3", };
490 static const char *regnames_LO[] =
491 { "LO0", "LO1", "LO2", "LO3", };
493 static const char *regnames_ACX[] =
494 { "ACX0", "ACX1", "ACX2", "ACX3", };
496 static const char *fregnames[] =
497 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
498 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
499 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
500 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
502 #ifdef MIPS_DEBUG_DISAS
503 #define MIPS_DEBUG(fmt, ...) \
504 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
505 TARGET_FMT_lx ": %08x " fmt "\n", \
506 ctx->pc, ctx->opcode , ## __VA_ARGS__)
507 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
508 #else
509 #define MIPS_DEBUG(fmt, ...) do { } while(0)
510 #define LOG_DISAS(...) do { } while (0)
511 #endif
513 #define MIPS_INVAL(op) \
514 do { \
515 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
516 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
517 } while (0)
519 /* General purpose registers moves. */
520 static inline void gen_load_gpr (TCGv t, int reg)
522 if (reg == 0)
523 tcg_gen_movi_tl(t, 0);
524 else
525 tcg_gen_mov_tl(t, cpu_gpr[reg]);
528 static inline void gen_store_gpr (TCGv t, int reg)
530 if (reg != 0)
531 tcg_gen_mov_tl(cpu_gpr[reg], t);
534 /* Moves to/from ACX register. */
535 static inline void gen_load_ACX (TCGv t, int reg)
537 tcg_gen_mov_tl(t, cpu_ACX[reg]);
540 static inline void gen_store_ACX (TCGv t, int reg)
542 tcg_gen_mov_tl(cpu_ACX[reg], t);
545 /* Moves to/from shadow registers. */
546 static inline void gen_load_srsgpr (int from, int to)
548 TCGv t0 = tcg_temp_new();
550 if (from == 0)
551 tcg_gen_movi_tl(t0, 0);
552 else {
553 TCGv_i32 t2 = tcg_temp_new_i32();
554 TCGv_ptr addr = tcg_temp_new_ptr();
556 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
557 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
558 tcg_gen_andi_i32(t2, t2, 0xf);
559 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
560 tcg_gen_ext_i32_ptr(addr, t2);
561 tcg_gen_add_ptr(addr, cpu_env, addr);
563 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
564 tcg_temp_free_ptr(addr);
565 tcg_temp_free_i32(t2);
567 gen_store_gpr(t0, to);
568 tcg_temp_free(t0);
571 static inline void gen_store_srsgpr (int from, int to)
573 if (to != 0) {
574 TCGv t0 = tcg_temp_new();
575 TCGv_i32 t2 = tcg_temp_new_i32();
576 TCGv_ptr addr = tcg_temp_new_ptr();
578 gen_load_gpr(t0, from);
579 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
580 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
581 tcg_gen_andi_i32(t2, t2, 0xf);
582 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
583 tcg_gen_ext_i32_ptr(addr, t2);
584 tcg_gen_add_ptr(addr, cpu_env, addr);
586 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
587 tcg_temp_free_ptr(addr);
588 tcg_temp_free_i32(t2);
589 tcg_temp_free(t0);
593 /* Floating point register moves. */
594 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
596 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
599 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
601 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
604 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
606 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
609 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
611 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
614 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
616 if (ctx->hflags & MIPS_HFLAG_F64) {
617 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
618 } else {
619 TCGv_i32 t0 = tcg_temp_new_i32();
620 TCGv_i32 t1 = tcg_temp_new_i32();
621 gen_load_fpr32(t0, reg & ~1);
622 gen_load_fpr32(t1, reg | 1);
623 tcg_gen_concat_i32_i64(t, t0, t1);
624 tcg_temp_free_i32(t0);
625 tcg_temp_free_i32(t1);
629 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
631 if (ctx->hflags & MIPS_HFLAG_F64) {
632 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
633 } else {
634 TCGv_i64 t0 = tcg_temp_new_i64();
635 TCGv_i32 t1 = tcg_temp_new_i32();
636 tcg_gen_trunc_i64_i32(t1, t);
637 gen_store_fpr32(t1, reg & ~1);
638 tcg_gen_shri_i64(t0, t, 32);
639 tcg_gen_trunc_i64_i32(t1, t0);
640 gen_store_fpr32(t1, reg | 1);
641 tcg_temp_free_i32(t1);
642 tcg_temp_free_i64(t0);
646 static inline int get_fp_bit (int cc)
648 if (cc)
649 return 24 + cc;
650 else
651 return 23;
654 #define FOP_CONDS(type, fmt, bits) \
655 static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
656 TCGv_i##bits b, int cc) \
658 switch (n) { \
659 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
660 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
661 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
662 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
663 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
664 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
665 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
666 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
667 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
668 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
669 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
670 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
671 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
672 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
673 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
674 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
675 default: abort(); \
679 FOP_CONDS(, d, 64)
680 FOP_CONDS(abs, d, 64)
681 FOP_CONDS(, s, 32)
682 FOP_CONDS(abs, s, 32)
683 FOP_CONDS(, ps, 64)
684 FOP_CONDS(abs, ps, 64)
685 #undef FOP_CONDS
687 /* Tests */
688 #define OP_COND(name, cond) \
689 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, TCGv t1) \
691 int l1 = gen_new_label(); \
692 int l2 = gen_new_label(); \
694 tcg_gen_brcond_tl(cond, t0, t1, l1); \
695 tcg_gen_movi_tl(ret, 0); \
696 tcg_gen_br(l2); \
697 gen_set_label(l1); \
698 tcg_gen_movi_tl(ret, 1); \
699 gen_set_label(l2); \
701 OP_COND(eq, TCG_COND_EQ);
702 OP_COND(ne, TCG_COND_NE);
703 OP_COND(ge, TCG_COND_GE);
704 OP_COND(geu, TCG_COND_GEU);
705 OP_COND(lt, TCG_COND_LT);
706 OP_COND(ltu, TCG_COND_LTU);
707 #undef OP_COND
709 #define OP_CONDI(name, cond) \
710 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, target_ulong val) \
712 int l1 = gen_new_label(); \
713 int l2 = gen_new_label(); \
715 tcg_gen_brcondi_tl(cond, t0, val, l1); \
716 tcg_gen_movi_tl(ret, 0); \
717 tcg_gen_br(l2); \
718 gen_set_label(l1); \
719 tcg_gen_movi_tl(ret, 1); \
720 gen_set_label(l2); \
722 OP_CONDI(lti, TCG_COND_LT);
723 OP_CONDI(ltiu, TCG_COND_LTU);
724 #undef OP_CONDI
726 #define OP_CONDZ(name, cond) \
727 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0) \
729 int l1 = gen_new_label(); \
730 int l2 = gen_new_label(); \
732 tcg_gen_brcondi_tl(cond, t0, 0, l1); \
733 tcg_gen_movi_tl(ret, 0); \
734 tcg_gen_br(l2); \
735 gen_set_label(l1); \
736 tcg_gen_movi_tl(ret, 1); \
737 gen_set_label(l2); \
739 OP_CONDZ(gez, TCG_COND_GE);
740 OP_CONDZ(gtz, TCG_COND_GT);
741 OP_CONDZ(lez, TCG_COND_LE);
742 OP_CONDZ(ltz, TCG_COND_LT);
743 #undef OP_CONDZ
745 static inline void gen_save_pc(target_ulong pc)
747 tcg_gen_movi_tl(cpu_PC, pc);
750 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
752 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
753 if (do_save_pc && ctx->pc != ctx->saved_pc) {
754 gen_save_pc(ctx->pc);
755 ctx->saved_pc = ctx->pc;
757 if (ctx->hflags != ctx->saved_hflags) {
758 tcg_gen_movi_i32(hflags, ctx->hflags);
759 ctx->saved_hflags = ctx->hflags;
760 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
761 case MIPS_HFLAG_BR:
762 break;
763 case MIPS_HFLAG_BC:
764 case MIPS_HFLAG_BL:
765 case MIPS_HFLAG_B:
766 tcg_gen_movi_tl(btarget, ctx->btarget);
767 break;
772 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
774 ctx->saved_hflags = ctx->hflags;
775 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
776 case MIPS_HFLAG_BR:
777 break;
778 case MIPS_HFLAG_BC:
779 case MIPS_HFLAG_BL:
780 case MIPS_HFLAG_B:
781 ctx->btarget = env->btarget;
782 break;
786 static inline void
787 generate_exception_err (DisasContext *ctx, int excp, int err)
789 TCGv_i32 texcp = tcg_const_i32(excp);
790 TCGv_i32 terr = tcg_const_i32(err);
791 save_cpu_state(ctx, 1);
792 gen_helper_raise_exception_err(texcp, terr);
793 tcg_temp_free_i32(terr);
794 tcg_temp_free_i32(texcp);
797 static inline void
798 generate_exception (DisasContext *ctx, int excp)
800 save_cpu_state(ctx, 1);
801 gen_helper_0i(raise_exception, excp);
804 /* Addresses computation */
805 static inline void gen_op_addr_add (DisasContext *ctx, TCGv t0, TCGv t1)
807 tcg_gen_add_tl(t0, t0, t1);
809 #if defined(TARGET_MIPS64)
810 /* For compatibility with 32-bit code, data reference in user mode
811 with Status_UX = 0 should be casted to 32-bit and sign extended.
812 See the MIPS64 PRA manual, section 4.10. */
813 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
814 !(ctx->hflags & MIPS_HFLAG_UX)) {
815 tcg_gen_ext32s_i64(t0, t0);
817 #endif
820 static inline void check_cp0_enabled(DisasContext *ctx)
822 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
823 generate_exception_err(ctx, EXCP_CpU, 1);
826 static inline void check_cp1_enabled(DisasContext *ctx)
828 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
829 generate_exception_err(ctx, EXCP_CpU, 1);
832 /* Verify that the processor is running with COP1X instructions enabled.
833 This is associated with the nabla symbol in the MIPS32 and MIPS64
834 opcode tables. */
836 static inline void check_cop1x(DisasContext *ctx)
838 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
839 generate_exception(ctx, EXCP_RI);
842 /* Verify that the processor is running with 64-bit floating-point
843 operations enabled. */
845 static inline void check_cp1_64bitmode(DisasContext *ctx)
847 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
848 generate_exception(ctx, EXCP_RI);
852 * Verify if floating point register is valid; an operation is not defined
853 * if bit 0 of any register specification is set and the FR bit in the
854 * Status register equals zero, since the register numbers specify an
855 * even-odd pair of adjacent coprocessor general registers. When the FR bit
856 * in the Status register equals one, both even and odd register numbers
857 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
859 * Multiple 64 bit wide registers can be checked by calling
860 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
862 static inline void check_cp1_registers(DisasContext *ctx, int regs)
864 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
865 generate_exception(ctx, EXCP_RI);
868 /* This code generates a "reserved instruction" exception if the
869 CPU does not support the instruction set corresponding to flags. */
870 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
872 if (unlikely(!(env->insn_flags & flags)))
873 generate_exception(ctx, EXCP_RI);
876 /* This code generates a "reserved instruction" exception if 64-bit
877 instructions are not enabled. */
878 static inline void check_mips_64(DisasContext *ctx)
880 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
881 generate_exception(ctx, EXCP_RI);
884 /* load/store instructions. */
885 #define OP_LD(insn,fname) \
886 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
888 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
890 OP_LD(lb,ld8s);
891 OP_LD(lbu,ld8u);
892 OP_LD(lh,ld16s);
893 OP_LD(lhu,ld16u);
894 OP_LD(lw,ld32s);
895 #if defined(TARGET_MIPS64)
896 OP_LD(lwu,ld32u);
897 OP_LD(ld,ld64);
898 #endif
899 #undef OP_LD
901 #define OP_ST(insn,fname) \
902 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
904 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
906 OP_ST(sb,st8);
907 OP_ST(sh,st16);
908 OP_ST(sw,st32);
909 #if defined(TARGET_MIPS64)
910 OP_ST(sd,st64);
911 #endif
912 #undef OP_ST
914 #define OP_LD_ATOMIC(insn,fname) \
915 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
917 TCGv t0 = tcg_temp_new(); \
918 tcg_gen_mov_tl(t0, arg1); \
919 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
920 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
921 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
922 tcg_temp_free(t0); \
924 OP_LD_ATOMIC(ll,ld32s);
925 #if defined(TARGET_MIPS64)
926 OP_LD_ATOMIC(lld,ld64);
927 #endif
928 #undef OP_LD_ATOMIC
930 #ifdef CONFIG_USER_ONLY
931 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
932 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
934 TCGv t0 = tcg_temp_new(); \
935 int l1 = gen_new_label(); \
936 int l2 = gen_new_label(); \
938 tcg_gen_andi_tl(t0, arg2, almask); \
939 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
940 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
941 generate_exception(ctx, EXCP_AdES); \
942 gen_set_label(l1); \
943 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
944 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
945 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
946 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
947 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
948 gen_helper_0i(raise_exception, EXCP_SC); \
949 gen_set_label(l2); \
950 tcg_gen_movi_tl(t0, 0); \
951 gen_store_gpr(t0, rt); \
952 tcg_temp_free(t0); \
954 #else
955 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
956 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
958 TCGv t0 = tcg_temp_new(); \
959 TCGv t1 = tcg_temp_new(); \
960 int l1 = gen_new_label(); \
961 int l2 = gen_new_label(); \
962 int l3 = gen_new_label(); \
964 tcg_gen_andi_tl(t0, arg2, almask); \
965 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
966 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
967 generate_exception(ctx, EXCP_AdES); \
968 gen_set_label(l1); \
969 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
970 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
971 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, llval)); \
972 tcg_gen_qemu_##ldname(t1, arg2, ctx->mem_idx); \
973 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l2); \
974 tcg_temp_free(t1); \
975 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
976 tcg_gen_movi_tl(t0, 1); \
977 gen_store_gpr(t0, rt); \
978 tcg_gen_br(l3); \
979 gen_set_label(l2); \
980 tcg_gen_movi_tl(t0, 0); \
981 gen_store_gpr(t0, rt); \
982 gen_set_label(l3); \
983 tcg_temp_free(t0); \
985 #endif
987 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
988 #if defined(TARGET_MIPS64)
989 OP_ST_ATOMIC(scd,st64,ld64,0x7);
990 #endif
991 #undef OP_ST_ATOMIC
993 /* Load and store */
994 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
995 int base, int16_t offset)
997 const char *opn = "ldst";
998 TCGv t0 = tcg_temp_new();
999 TCGv t1 = tcg_temp_new();
1001 if (base == 0) {
1002 tcg_gen_movi_tl(t0, offset);
1003 } else if (offset == 0) {
1004 gen_load_gpr(t0, base);
1005 } else {
1006 tcg_gen_movi_tl(t0, offset);
1007 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
1009 /* Don't do NOP if destination is zero: we must perform the actual
1010 memory access. */
1011 switch (opc) {
1012 #if defined(TARGET_MIPS64)
1013 case OPC_LWU:
1014 save_cpu_state(ctx, 0);
1015 op_ldst_lwu(t0, t0, ctx);
1016 gen_store_gpr(t0, rt);
1017 opn = "lwu";
1018 break;
1019 case OPC_LD:
1020 save_cpu_state(ctx, 0);
1021 op_ldst_ld(t0, t0, ctx);
1022 gen_store_gpr(t0, rt);
1023 opn = "ld";
1024 break;
1025 case OPC_LLD:
1026 save_cpu_state(ctx, 0);
1027 op_ldst_lld(t0, t0, ctx);
1028 gen_store_gpr(t0, rt);
1029 opn = "lld";
1030 break;
1031 case OPC_SD:
1032 save_cpu_state(ctx, 0);
1033 gen_load_gpr(t1, rt);
1034 op_ldst_sd(t1, t0, ctx);
1035 opn = "sd";
1036 break;
1037 case OPC_LDL:
1038 save_cpu_state(ctx, 1);
1039 gen_load_gpr(t1, rt);
1040 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1041 gen_store_gpr(t1, rt);
1042 opn = "ldl";
1043 break;
1044 case OPC_SDL:
1045 save_cpu_state(ctx, 1);
1046 gen_load_gpr(t1, rt);
1047 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1048 opn = "sdl";
1049 break;
1050 case OPC_LDR:
1051 save_cpu_state(ctx, 1);
1052 gen_load_gpr(t1, rt);
1053 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1054 gen_store_gpr(t1, rt);
1055 opn = "ldr";
1056 break;
1057 case OPC_SDR:
1058 save_cpu_state(ctx, 1);
1059 gen_load_gpr(t1, rt);
1060 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1061 opn = "sdr";
1062 break;
1063 #endif
1064 case OPC_LW:
1065 save_cpu_state(ctx, 0);
1066 op_ldst_lw(t0, t0, ctx);
1067 gen_store_gpr(t0, rt);
1068 opn = "lw";
1069 break;
1070 case OPC_SW:
1071 save_cpu_state(ctx, 0);
1072 gen_load_gpr(t1, rt);
1073 op_ldst_sw(t1, t0, ctx);
1074 opn = "sw";
1075 break;
1076 case OPC_LH:
1077 save_cpu_state(ctx, 0);
1078 op_ldst_lh(t0, t0, ctx);
1079 gen_store_gpr(t0, rt);
1080 opn = "lh";
1081 break;
1082 case OPC_SH:
1083 save_cpu_state(ctx, 0);
1084 gen_load_gpr(t1, rt);
1085 op_ldst_sh(t1, t0, ctx);
1086 opn = "sh";
1087 break;
1088 case OPC_LHU:
1089 save_cpu_state(ctx, 0);
1090 op_ldst_lhu(t0, t0, ctx);
1091 gen_store_gpr(t0, rt);
1092 opn = "lhu";
1093 break;
1094 case OPC_LB:
1095 save_cpu_state(ctx, 0);
1096 op_ldst_lb(t0, t0, ctx);
1097 gen_store_gpr(t0, rt);
1098 opn = "lb";
1099 break;
1100 case OPC_SB:
1101 save_cpu_state(ctx, 0);
1102 gen_load_gpr(t1, rt);
1103 op_ldst_sb(t1, t0, ctx);
1104 opn = "sb";
1105 break;
1106 case OPC_LBU:
1107 save_cpu_state(ctx, 0);
1108 op_ldst_lbu(t0, t0, ctx);
1109 gen_store_gpr(t0, rt);
1110 opn = "lbu";
1111 break;
1112 case OPC_LWL:
1113 save_cpu_state(ctx, 1);
1114 gen_load_gpr(t1, rt);
1115 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1116 gen_store_gpr(t1, rt);
1117 opn = "lwl";
1118 break;
1119 case OPC_SWL:
1120 save_cpu_state(ctx, 1);
1121 gen_load_gpr(t1, rt);
1122 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1123 opn = "swr";
1124 break;
1125 case OPC_LWR:
1126 save_cpu_state(ctx, 1);
1127 gen_load_gpr(t1, rt);
1128 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1129 gen_store_gpr(t1, rt);
1130 opn = "lwr";
1131 break;
1132 case OPC_SWR:
1133 save_cpu_state(ctx, 1);
1134 gen_load_gpr(t1, rt);
1135 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1136 opn = "swr";
1137 break;
1138 case OPC_LL:
1139 save_cpu_state(ctx, 0);
1140 op_ldst_ll(t0, t0, ctx);
1141 gen_store_gpr(t0, rt);
1142 opn = "ll";
1143 break;
1145 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1146 tcg_temp_free(t0);
1147 tcg_temp_free(t1);
1150 /* Store conditional */
1151 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1152 int base, int16_t offset)
1154 const char *opn = "st_cond";
1155 TCGv t0, t1;
1157 t0 = tcg_temp_local_new();
1159 if (base == 0) {
1160 tcg_gen_movi_tl(t0, offset);
1161 } else if (offset == 0) {
1162 gen_load_gpr(t0, base);
1163 } else {
1164 tcg_gen_movi_tl(t0, offset);
1165 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
1167 /* Don't do NOP if destination is zero: we must perform the actual
1168 memory access. */
1170 t1 = tcg_temp_local_new();
1171 gen_load_gpr(t1, rt);
1172 switch (opc) {
1173 #if defined(TARGET_MIPS64)
1174 case OPC_SCD:
1175 save_cpu_state(ctx, 0);
1176 op_ldst_scd(t1, t0, rt, ctx);
1177 opn = "scd";
1178 break;
1179 #endif
1180 case OPC_SC:
1181 save_cpu_state(ctx, 0);
1182 op_ldst_sc(t1, t0, rt, ctx);
1183 opn = "sc";
1184 break;
1186 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1187 tcg_temp_free(t1);
1188 tcg_temp_free(t0);
1191 /* Load and store */
1192 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1193 int base, int16_t offset)
1195 const char *opn = "flt_ldst";
1196 TCGv t0 = tcg_temp_new();
1198 if (base == 0) {
1199 tcg_gen_movi_tl(t0, offset);
1200 } else if (offset == 0) {
1201 gen_load_gpr(t0, base);
1202 } else {
1203 tcg_gen_movi_tl(t0, offset);
1204 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
1206 /* Don't do NOP if destination is zero: we must perform the actual
1207 memory access. */
1208 switch (opc) {
1209 case OPC_LWC1:
1211 TCGv_i32 fp0 = tcg_temp_new_i32();
1213 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1214 tcg_gen_trunc_tl_i32(fp0, t0);
1215 gen_store_fpr32(fp0, ft);
1216 tcg_temp_free_i32(fp0);
1218 opn = "lwc1";
1219 break;
1220 case OPC_SWC1:
1222 TCGv_i32 fp0 = tcg_temp_new_i32();
1223 TCGv t1 = tcg_temp_new();
1225 gen_load_fpr32(fp0, ft);
1226 tcg_gen_extu_i32_tl(t1, fp0);
1227 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1228 tcg_temp_free(t1);
1229 tcg_temp_free_i32(fp0);
1231 opn = "swc1";
1232 break;
1233 case OPC_LDC1:
1235 TCGv_i64 fp0 = tcg_temp_new_i64();
1237 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1238 gen_store_fpr64(ctx, fp0, ft);
1239 tcg_temp_free_i64(fp0);
1241 opn = "ldc1";
1242 break;
1243 case OPC_SDC1:
1245 TCGv_i64 fp0 = tcg_temp_new_i64();
1247 gen_load_fpr64(ctx, fp0, ft);
1248 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1249 tcg_temp_free_i64(fp0);
1251 opn = "sdc1";
1252 break;
1253 default:
1254 MIPS_INVAL(opn);
1255 generate_exception(ctx, EXCP_RI);
1256 goto out;
1258 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1259 out:
1260 tcg_temp_free(t0);
1263 /* Arithmetic with immediate operand */
1264 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1265 int rt, int rs, int16_t imm)
1267 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1268 const char *opn = "imm arith";
1270 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1271 /* If no destination, treat it as a NOP.
1272 For addi, we must generate the overflow exception when needed. */
1273 MIPS_DEBUG("NOP");
1274 return;
1276 switch (opc) {
1277 case OPC_ADDI:
1279 TCGv t0 = tcg_temp_local_new();
1280 TCGv t1 = tcg_temp_new();
1281 TCGv t2 = tcg_temp_new();
1282 int l1 = gen_new_label();
1284 gen_load_gpr(t1, rs);
1285 tcg_gen_addi_tl(t0, t1, uimm);
1286 tcg_gen_ext32s_tl(t0, t0);
1288 tcg_gen_xori_tl(t1, t1, ~uimm);
1289 tcg_gen_xori_tl(t2, t0, uimm);
1290 tcg_gen_and_tl(t1, t1, t2);
1291 tcg_temp_free(t2);
1292 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1293 tcg_temp_free(t1);
1294 /* operands of same sign, result different sign */
1295 generate_exception(ctx, EXCP_OVERFLOW);
1296 gen_set_label(l1);
1297 tcg_gen_ext32s_tl(t0, t0);
1298 gen_store_gpr(t0, rt);
1299 tcg_temp_free(t0);
1301 opn = "addi";
1302 break;
1303 case OPC_ADDIU:
1304 if (rs != 0) {
1305 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1306 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1307 } else {
1308 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1310 opn = "addiu";
1311 break;
1312 #if defined(TARGET_MIPS64)
1313 case OPC_DADDI:
1315 TCGv t0 = tcg_temp_local_new();
1316 TCGv t1 = tcg_temp_new();
1317 TCGv t2 = tcg_temp_new();
1318 int l1 = gen_new_label();
1320 gen_load_gpr(t1, rs);
1321 tcg_gen_addi_tl(t0, t1, uimm);
1323 tcg_gen_xori_tl(t1, t1, ~uimm);
1324 tcg_gen_xori_tl(t2, t0, uimm);
1325 tcg_gen_and_tl(t1, t1, t2);
1326 tcg_temp_free(t2);
1327 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1328 tcg_temp_free(t1);
1329 /* operands of same sign, result different sign */
1330 generate_exception(ctx, EXCP_OVERFLOW);
1331 gen_set_label(l1);
1332 gen_store_gpr(t0, rt);
1333 tcg_temp_free(t0);
1335 opn = "daddi";
1336 break;
1337 case OPC_DADDIU:
1338 if (rs != 0) {
1339 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1340 } else {
1341 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1343 opn = "daddiu";
1344 break;
1345 #endif
1347 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1350 /* Logic with immediate operand */
1351 static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1353 target_ulong uimm;
1354 const char *opn = "imm logic";
1356 if (rt == 0) {
1357 /* If no destination, treat it as a NOP. */
1358 MIPS_DEBUG("NOP");
1359 return;
1361 uimm = (uint16_t)imm;
1362 switch (opc) {
1363 case OPC_ANDI:
1364 if (likely(rs != 0))
1365 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1366 else
1367 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1368 opn = "andi";
1369 break;
1370 case OPC_ORI:
1371 if (rs != 0)
1372 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1373 else
1374 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1375 opn = "ori";
1376 break;
1377 case OPC_XORI:
1378 if (likely(rs != 0))
1379 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1380 else
1381 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1382 opn = "xori";
1383 break;
1384 case OPC_LUI:
1385 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1386 opn = "lui";
1387 break;
1389 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1392 /* Set on less than with immediate operand */
1393 static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1395 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1396 const char *opn = "imm arith";
1397 TCGv t0;
1399 if (rt == 0) {
1400 /* If no destination, treat it as a NOP. */
1401 MIPS_DEBUG("NOP");
1402 return;
1404 t0 = tcg_temp_new();
1405 gen_load_gpr(t0, rs);
1406 switch (opc) {
1407 case OPC_SLTI:
1408 gen_op_lti(cpu_gpr[rt], t0, uimm);
1409 opn = "slti";
1410 break;
1411 case OPC_SLTIU:
1412 gen_op_ltiu(cpu_gpr[rt], t0, uimm);
1413 opn = "sltiu";
1414 break;
1416 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1417 tcg_temp_free(t0);
1420 /* Shifts with immediate operand */
1421 static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1422 int rt, int rs, int16_t imm)
1424 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1425 const char *opn = "imm shift";
1426 TCGv t0;
1428 if (rt == 0) {
1429 /* If no destination, treat it as a NOP. */
1430 MIPS_DEBUG("NOP");
1431 return;
1434 t0 = tcg_temp_new();
1435 gen_load_gpr(t0, rs);
1436 switch (opc) {
1437 case OPC_SLL:
1438 tcg_gen_shli_tl(t0, t0, uimm);
1439 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1440 opn = "sll";
1441 break;
1442 case OPC_SRA:
1443 tcg_gen_ext32s_tl(t0, t0);
1444 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1445 opn = "sra";
1446 break;
1447 case OPC_SRL:
1448 switch ((ctx->opcode >> 21) & 0x1f) {
1449 case 0:
1450 if (uimm != 0) {
1451 tcg_gen_ext32u_tl(t0, t0);
1452 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1453 } else {
1454 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1456 opn = "srl";
1457 break;
1458 case 1:
1459 /* rotr is decoded as srl on non-R2 CPUs */
1460 if (env->insn_flags & ISA_MIPS32R2) {
1461 if (uimm != 0) {
1462 TCGv_i32 t1 = tcg_temp_new_i32();
1464 tcg_gen_trunc_tl_i32(t1, t0);
1465 tcg_gen_rotri_i32(t1, t1, uimm);
1466 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1467 tcg_temp_free_i32(t1);
1469 opn = "rotr";
1470 } else {
1471 if (uimm != 0) {
1472 tcg_gen_ext32u_tl(t0, t0);
1473 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1474 } else {
1475 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1477 opn = "srl";
1479 break;
1480 default:
1481 MIPS_INVAL("invalid srl flag");
1482 generate_exception(ctx, EXCP_RI);
1483 break;
1485 break;
1486 #if defined(TARGET_MIPS64)
1487 case OPC_DSLL:
1488 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1489 opn = "dsll";
1490 break;
1491 case OPC_DSRA:
1492 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1493 opn = "dsra";
1494 break;
1495 case OPC_DSRL:
1496 switch ((ctx->opcode >> 21) & 0x1f) {
1497 case 0:
1498 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1499 opn = "dsrl";
1500 break;
1501 case 1:
1502 /* drotr is decoded as dsrl on non-R2 CPUs */
1503 if (env->insn_flags & ISA_MIPS32R2) {
1504 if (uimm != 0) {
1505 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1507 opn = "drotr";
1508 } else {
1509 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1510 opn = "dsrl";
1512 break;
1513 default:
1514 MIPS_INVAL("invalid dsrl flag");
1515 generate_exception(ctx, EXCP_RI);
1516 break;
1518 break;
1519 case OPC_DSLL32:
1520 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1521 opn = "dsll32";
1522 break;
1523 case OPC_DSRA32:
1524 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1525 opn = "dsra32";
1526 break;
1527 case OPC_DSRL32:
1528 switch ((ctx->opcode >> 21) & 0x1f) {
1529 case 0:
1530 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1531 opn = "dsrl32";
1532 break;
1533 case 1:
1534 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1535 if (env->insn_flags & ISA_MIPS32R2) {
1536 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1537 opn = "drotr32";
1538 } else {
1539 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1540 opn = "dsrl32";
1542 break;
1543 default:
1544 MIPS_INVAL("invalid dsrl32 flag");
1545 generate_exception(ctx, EXCP_RI);
1546 break;
1548 break;
1549 #endif
1551 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1552 tcg_temp_free(t0);
1555 /* Arithmetic */
1556 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1557 int rd, int rs, int rt)
1559 const char *opn = "arith";
1561 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1562 && opc != OPC_DADD && opc != OPC_DSUB) {
1563 /* If no destination, treat it as a NOP.
1564 For add & sub, we must generate the overflow exception when needed. */
1565 MIPS_DEBUG("NOP");
1566 return;
1569 switch (opc) {
1570 case OPC_ADD:
1572 TCGv t0 = tcg_temp_local_new();
1573 TCGv t1 = tcg_temp_new();
1574 TCGv t2 = tcg_temp_new();
1575 int l1 = gen_new_label();
1577 gen_load_gpr(t1, rs);
1578 gen_load_gpr(t2, rt);
1579 tcg_gen_add_tl(t0, t1, t2);
1580 tcg_gen_ext32s_tl(t0, t0);
1581 tcg_gen_xor_tl(t1, t1, t2);
1582 tcg_gen_not_tl(t1, t1);
1583 tcg_gen_xor_tl(t2, t0, t2);
1584 tcg_gen_and_tl(t1, t1, t2);
1585 tcg_temp_free(t2);
1586 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1587 tcg_temp_free(t1);
1588 /* operands of same sign, result different sign */
1589 generate_exception(ctx, EXCP_OVERFLOW);
1590 gen_set_label(l1);
1591 gen_store_gpr(t0, rd);
1592 tcg_temp_free(t0);
1594 opn = "add";
1595 break;
1596 case OPC_ADDU:
1597 if (rs != 0 && rt != 0) {
1598 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1599 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1600 } else if (rs == 0 && rt != 0) {
1601 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1602 } else if (rs != 0 && rt == 0) {
1603 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1604 } else {
1605 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1607 opn = "addu";
1608 break;
1609 case OPC_SUB:
1611 TCGv t0 = tcg_temp_local_new();
1612 TCGv t1 = tcg_temp_new();
1613 TCGv t2 = tcg_temp_new();
1614 int l1 = gen_new_label();
1616 gen_load_gpr(t1, rs);
1617 gen_load_gpr(t2, rt);
1618 tcg_gen_sub_tl(t0, t1, t2);
1619 tcg_gen_ext32s_tl(t0, t0);
1620 tcg_gen_xor_tl(t2, t1, t2);
1621 tcg_gen_xor_tl(t1, t0, t1);
1622 tcg_gen_and_tl(t1, t1, t2);
1623 tcg_temp_free(t2);
1624 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1625 tcg_temp_free(t1);
1626 /* operands of different sign, first operand and result different sign */
1627 generate_exception(ctx, EXCP_OVERFLOW);
1628 gen_set_label(l1);
1629 gen_store_gpr(t0, rd);
1630 tcg_temp_free(t0);
1632 opn = "sub";
1633 break;
1634 case OPC_SUBU:
1635 if (rs != 0 && rt != 0) {
1636 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1637 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1638 } else if (rs == 0 && rt != 0) {
1639 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1640 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1641 } else if (rs != 0 && rt == 0) {
1642 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1643 } else {
1644 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1646 opn = "subu";
1647 break;
1648 #if defined(TARGET_MIPS64)
1649 case OPC_DADD:
1651 TCGv t0 = tcg_temp_local_new();
1652 TCGv t1 = tcg_temp_new();
1653 TCGv t2 = tcg_temp_new();
1654 int l1 = gen_new_label();
1656 gen_load_gpr(t1, rs);
1657 gen_load_gpr(t2, rt);
1658 tcg_gen_add_tl(t0, t1, t2);
1659 tcg_gen_xor_tl(t1, t1, t2);
1660 tcg_gen_not_tl(t1, t1);
1661 tcg_gen_xor_tl(t2, t0, t2);
1662 tcg_gen_and_tl(t1, t1, t2);
1663 tcg_temp_free(t2);
1664 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1665 tcg_temp_free(t1);
1666 /* operands of same sign, result different sign */
1667 generate_exception(ctx, EXCP_OVERFLOW);
1668 gen_set_label(l1);
1669 gen_store_gpr(t0, rd);
1670 tcg_temp_free(t0);
1672 opn = "dadd";
1673 break;
1674 case OPC_DADDU:
1675 if (rs != 0 && rt != 0) {
1676 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1677 } else if (rs == 0 && rt != 0) {
1678 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1679 } else if (rs != 0 && rt == 0) {
1680 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1681 } else {
1682 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1684 opn = "daddu";
1685 break;
1686 case OPC_DSUB:
1688 TCGv t0 = tcg_temp_local_new();
1689 TCGv t1 = tcg_temp_new();
1690 TCGv t2 = tcg_temp_new();
1691 int l1 = gen_new_label();
1693 gen_load_gpr(t1, rs);
1694 gen_load_gpr(t2, rt);
1695 tcg_gen_sub_tl(t0, t1, t2);
1696 tcg_gen_xor_tl(t2, t1, t2);
1697 tcg_gen_xor_tl(t1, t0, t1);
1698 tcg_gen_and_tl(t1, t1, t2);
1699 tcg_temp_free(t2);
1700 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1701 tcg_temp_free(t1);
1702 /* operands of different sign, first operand and result different sign */
1703 generate_exception(ctx, EXCP_OVERFLOW);
1704 gen_set_label(l1);
1705 gen_store_gpr(t0, rd);
1706 tcg_temp_free(t0);
1708 opn = "dsub";
1709 break;
1710 case OPC_DSUBU:
1711 if (rs != 0 && rt != 0) {
1712 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1713 } else if (rs == 0 && rt != 0) {
1714 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1715 } else if (rs != 0 && rt == 0) {
1716 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1717 } else {
1718 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1720 opn = "dsubu";
1721 break;
1722 #endif
1723 case OPC_MUL:
1724 if (likely(rs != 0 && rt != 0)) {
1725 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1726 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1727 } else {
1728 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1730 opn = "mul";
1731 break;
1733 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1736 /* Conditional move */
1737 static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1739 const char *opn = "cond move";
1740 int l1;
1742 if (rd == 0) {
1743 /* If no destination, treat it as a NOP.
1744 For add & sub, we must generate the overflow exception when needed. */
1745 MIPS_DEBUG("NOP");
1746 return;
1749 l1 = gen_new_label();
1750 switch (opc) {
1751 case OPC_MOVN:
1752 if (likely(rt != 0))
1753 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1754 else
1755 tcg_gen_br(l1);
1756 opn = "movn";
1757 break;
1758 case OPC_MOVZ:
1759 if (likely(rt != 0))
1760 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1761 opn = "movz";
1762 break;
1764 if (rs != 0)
1765 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1766 else
1767 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1768 gen_set_label(l1);
1770 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1773 /* Logic */
1774 static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1776 const char *opn = "logic";
1778 if (rd == 0) {
1779 /* If no destination, treat it as a NOP. */
1780 MIPS_DEBUG("NOP");
1781 return;
1784 switch (opc) {
1785 case OPC_AND:
1786 if (likely(rs != 0 && rt != 0)) {
1787 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1788 } else {
1789 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1791 opn = "and";
1792 break;
1793 case OPC_NOR:
1794 if (rs != 0 && rt != 0) {
1795 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1796 } else if (rs == 0 && rt != 0) {
1797 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1798 } else if (rs != 0 && rt == 0) {
1799 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1800 } else {
1801 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1803 opn = "nor";
1804 break;
1805 case OPC_OR:
1806 if (likely(rs != 0 && rt != 0)) {
1807 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1808 } else if (rs == 0 && rt != 0) {
1809 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1810 } else if (rs != 0 && rt == 0) {
1811 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1812 } else {
1813 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1815 opn = "or";
1816 break;
1817 case OPC_XOR:
1818 if (likely(rs != 0 && rt != 0)) {
1819 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1820 } else if (rs == 0 && rt != 0) {
1821 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1822 } else if (rs != 0 && rt == 0) {
1823 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1824 } else {
1825 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1827 opn = "xor";
1828 break;
1830 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1833 /* Set on lower than */
1834 static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1836 const char *opn = "slt";
1837 TCGv t0, t1;
1839 if (rd == 0) {
1840 /* If no destination, treat it as a NOP. */
1841 MIPS_DEBUG("NOP");
1842 return;
1845 t0 = tcg_temp_new();
1846 t1 = tcg_temp_new();
1847 gen_load_gpr(t0, rs);
1848 gen_load_gpr(t1, rt);
1849 switch (opc) {
1850 case OPC_SLT:
1851 gen_op_lt(cpu_gpr[rd], t0, t1);
1852 opn = "slt";
1853 break;
1854 case OPC_SLTU:
1855 gen_op_ltu(cpu_gpr[rd], t0, t1);
1856 opn = "sltu";
1857 break;
1859 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1860 tcg_temp_free(t0);
1861 tcg_temp_free(t1);
1864 /* Shifts */
1865 static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1866 int rd, int rs, int rt)
1868 const char *opn = "shifts";
1869 TCGv t0, t1;
1871 if (rd == 0) {
1872 /* If no destination, treat it as a NOP.
1873 For add & sub, we must generate the overflow exception when needed. */
1874 MIPS_DEBUG("NOP");
1875 return;
1878 t0 = tcg_temp_new();
1879 t1 = tcg_temp_new();
1880 gen_load_gpr(t0, rs);
1881 gen_load_gpr(t1, rt);
1882 switch (opc) {
1883 case OPC_SLLV:
1884 tcg_gen_andi_tl(t0, t0, 0x1f);
1885 tcg_gen_shl_tl(t0, t1, t0);
1886 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1887 opn = "sllv";
1888 break;
1889 case OPC_SRAV:
1890 tcg_gen_ext32s_tl(t1, t1);
1891 tcg_gen_andi_tl(t0, t0, 0x1f);
1892 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1893 opn = "srav";
1894 break;
1895 case OPC_SRLV:
1896 switch ((ctx->opcode >> 6) & 0x1f) {
1897 case 0:
1898 tcg_gen_ext32u_tl(t1, t1);
1899 tcg_gen_andi_tl(t0, t0, 0x1f);
1900 tcg_gen_shr_tl(t0, t1, t0);
1901 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1902 opn = "srlv";
1903 break;
1904 case 1:
1905 /* rotrv is decoded as srlv on non-R2 CPUs */
1906 if (env->insn_flags & ISA_MIPS32R2) {
1907 TCGv_i32 t2 = tcg_temp_new_i32();
1908 TCGv_i32 t3 = tcg_temp_new_i32();
1910 tcg_gen_trunc_tl_i32(t2, t0);
1911 tcg_gen_trunc_tl_i32(t3, t1);
1912 tcg_gen_andi_i32(t2, t2, 0x1f);
1913 tcg_gen_rotr_i32(t2, t3, t2);
1914 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1915 tcg_temp_free_i32(t2);
1916 tcg_temp_free_i32(t3);
1917 opn = "rotrv";
1918 } else {
1919 tcg_gen_ext32u_tl(t1, t1);
1920 tcg_gen_andi_tl(t0, t0, 0x1f);
1921 tcg_gen_shr_tl(t0, t1, t0);
1922 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1923 opn = "srlv";
1925 break;
1926 default:
1927 MIPS_INVAL("invalid srlv flag");
1928 generate_exception(ctx, EXCP_RI);
1929 break;
1931 break;
1932 #if defined(TARGET_MIPS64)
1933 case OPC_DSLLV:
1934 tcg_gen_andi_tl(t0, t0, 0x3f);
1935 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1936 opn = "dsllv";
1937 break;
1938 case OPC_DSRAV:
1939 tcg_gen_andi_tl(t0, t0, 0x3f);
1940 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1941 opn = "dsrav";
1942 break;
1943 case OPC_DSRLV:
1944 switch ((ctx->opcode >> 6) & 0x1f) {
1945 case 0:
1946 tcg_gen_andi_tl(t0, t0, 0x3f);
1947 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1948 opn = "dsrlv";
1949 break;
1950 case 1:
1951 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1952 if (env->insn_flags & ISA_MIPS32R2) {
1953 tcg_gen_andi_tl(t0, t0, 0x3f);
1954 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1955 opn = "drotrv";
1956 } else {
1957 tcg_gen_andi_tl(t0, t0, 0x3f);
1958 tcg_gen_shr_tl(t0, t1, t0);
1959 opn = "dsrlv";
1961 break;
1962 default:
1963 MIPS_INVAL("invalid dsrlv flag");
1964 generate_exception(ctx, EXCP_RI);
1965 break;
1967 break;
1968 #endif
1970 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1971 tcg_temp_free(t0);
1972 tcg_temp_free(t1);
1975 /* Arithmetic on HI/LO registers */
1976 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1978 const char *opn = "hilo";
1980 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1981 /* Treat as NOP. */
1982 MIPS_DEBUG("NOP");
1983 return;
1985 switch (opc) {
1986 case OPC_MFHI:
1987 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1988 opn = "mfhi";
1989 break;
1990 case OPC_MFLO:
1991 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1992 opn = "mflo";
1993 break;
1994 case OPC_MTHI:
1995 if (reg != 0)
1996 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1997 else
1998 tcg_gen_movi_tl(cpu_HI[0], 0);
1999 opn = "mthi";
2000 break;
2001 case OPC_MTLO:
2002 if (reg != 0)
2003 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2004 else
2005 tcg_gen_movi_tl(cpu_LO[0], 0);
2006 opn = "mtlo";
2007 break;
2009 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2012 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
2013 int rs, int rt)
2015 const char *opn = "mul/div";
2016 TCGv t0, t1;
2018 switch (opc) {
2019 case OPC_DIV:
2020 case OPC_DIVU:
2021 #if defined(TARGET_MIPS64)
2022 case OPC_DDIV:
2023 case OPC_DDIVU:
2024 #endif
2025 t0 = tcg_temp_local_new();
2026 t1 = tcg_temp_local_new();
2027 break;
2028 default:
2029 t0 = tcg_temp_new();
2030 t1 = tcg_temp_new();
2031 break;
2034 gen_load_gpr(t0, rs);
2035 gen_load_gpr(t1, rt);
2036 switch (opc) {
2037 case OPC_DIV:
2039 int l1 = gen_new_label();
2040 int l2 = gen_new_label();
2042 tcg_gen_ext32s_tl(t0, t0);
2043 tcg_gen_ext32s_tl(t1, t1);
2044 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2045 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2046 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2048 tcg_gen_mov_tl(cpu_LO[0], t0);
2049 tcg_gen_movi_tl(cpu_HI[0], 0);
2050 tcg_gen_br(l1);
2051 gen_set_label(l2);
2052 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2053 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2054 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2055 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2056 gen_set_label(l1);
2058 opn = "div";
2059 break;
2060 case OPC_DIVU:
2062 int l1 = gen_new_label();
2064 tcg_gen_ext32u_tl(t0, t0);
2065 tcg_gen_ext32u_tl(t1, t1);
2066 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2067 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2068 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2069 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2070 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2071 gen_set_label(l1);
2073 opn = "divu";
2074 break;
2075 case OPC_MULT:
2077 TCGv_i64 t2 = tcg_temp_new_i64();
2078 TCGv_i64 t3 = tcg_temp_new_i64();
2080 tcg_gen_ext_tl_i64(t2, t0);
2081 tcg_gen_ext_tl_i64(t3, t1);
2082 tcg_gen_mul_i64(t2, t2, t3);
2083 tcg_temp_free_i64(t3);
2084 tcg_gen_trunc_i64_tl(t0, t2);
2085 tcg_gen_shri_i64(t2, t2, 32);
2086 tcg_gen_trunc_i64_tl(t1, t2);
2087 tcg_temp_free_i64(t2);
2088 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2089 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2091 opn = "mult";
2092 break;
2093 case OPC_MULTU:
2095 TCGv_i64 t2 = tcg_temp_new_i64();
2096 TCGv_i64 t3 = tcg_temp_new_i64();
2098 tcg_gen_ext32u_tl(t0, t0);
2099 tcg_gen_ext32u_tl(t1, t1);
2100 tcg_gen_extu_tl_i64(t2, t0);
2101 tcg_gen_extu_tl_i64(t3, t1);
2102 tcg_gen_mul_i64(t2, t2, t3);
2103 tcg_temp_free_i64(t3);
2104 tcg_gen_trunc_i64_tl(t0, t2);
2105 tcg_gen_shri_i64(t2, t2, 32);
2106 tcg_gen_trunc_i64_tl(t1, t2);
2107 tcg_temp_free_i64(t2);
2108 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2109 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2111 opn = "multu";
2112 break;
2113 #if defined(TARGET_MIPS64)
2114 case OPC_DDIV:
2116 int l1 = gen_new_label();
2117 int l2 = gen_new_label();
2119 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2120 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2121 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2122 tcg_gen_mov_tl(cpu_LO[0], t0);
2123 tcg_gen_movi_tl(cpu_HI[0], 0);
2124 tcg_gen_br(l1);
2125 gen_set_label(l2);
2126 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2127 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2128 gen_set_label(l1);
2130 opn = "ddiv";
2131 break;
2132 case OPC_DDIVU:
2134 int l1 = gen_new_label();
2136 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2137 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2138 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2139 gen_set_label(l1);
2141 opn = "ddivu";
2142 break;
2143 case OPC_DMULT:
2144 gen_helper_dmult(t0, t1);
2145 opn = "dmult";
2146 break;
2147 case OPC_DMULTU:
2148 gen_helper_dmultu(t0, t1);
2149 opn = "dmultu";
2150 break;
2151 #endif
2152 case OPC_MADD:
2154 TCGv_i64 t2 = tcg_temp_new_i64();
2155 TCGv_i64 t3 = tcg_temp_new_i64();
2157 tcg_gen_ext_tl_i64(t2, t0);
2158 tcg_gen_ext_tl_i64(t3, t1);
2159 tcg_gen_mul_i64(t2, t2, t3);
2160 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2161 tcg_gen_add_i64(t2, t2, t3);
2162 tcg_temp_free_i64(t3);
2163 tcg_gen_trunc_i64_tl(t0, t2);
2164 tcg_gen_shri_i64(t2, t2, 32);
2165 tcg_gen_trunc_i64_tl(t1, t2);
2166 tcg_temp_free_i64(t2);
2167 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2168 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2170 opn = "madd";
2171 break;
2172 case OPC_MADDU:
2174 TCGv_i64 t2 = tcg_temp_new_i64();
2175 TCGv_i64 t3 = tcg_temp_new_i64();
2177 tcg_gen_ext32u_tl(t0, t0);
2178 tcg_gen_ext32u_tl(t1, t1);
2179 tcg_gen_extu_tl_i64(t2, t0);
2180 tcg_gen_extu_tl_i64(t3, t1);
2181 tcg_gen_mul_i64(t2, t2, t3);
2182 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2183 tcg_gen_add_i64(t2, t2, t3);
2184 tcg_temp_free_i64(t3);
2185 tcg_gen_trunc_i64_tl(t0, t2);
2186 tcg_gen_shri_i64(t2, t2, 32);
2187 tcg_gen_trunc_i64_tl(t1, t2);
2188 tcg_temp_free_i64(t2);
2189 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2190 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2192 opn = "maddu";
2193 break;
2194 case OPC_MSUB:
2196 TCGv_i64 t2 = tcg_temp_new_i64();
2197 TCGv_i64 t3 = tcg_temp_new_i64();
2199 tcg_gen_ext_tl_i64(t2, t0);
2200 tcg_gen_ext_tl_i64(t3, t1);
2201 tcg_gen_mul_i64(t2, t2, t3);
2202 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2203 tcg_gen_sub_i64(t2, t3, t2);
2204 tcg_temp_free_i64(t3);
2205 tcg_gen_trunc_i64_tl(t0, t2);
2206 tcg_gen_shri_i64(t2, t2, 32);
2207 tcg_gen_trunc_i64_tl(t1, t2);
2208 tcg_temp_free_i64(t2);
2209 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2210 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2212 opn = "msub";
2213 break;
2214 case OPC_MSUBU:
2216 TCGv_i64 t2 = tcg_temp_new_i64();
2217 TCGv_i64 t3 = tcg_temp_new_i64();
2219 tcg_gen_ext32u_tl(t0, t0);
2220 tcg_gen_ext32u_tl(t1, t1);
2221 tcg_gen_extu_tl_i64(t2, t0);
2222 tcg_gen_extu_tl_i64(t3, t1);
2223 tcg_gen_mul_i64(t2, t2, t3);
2224 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2225 tcg_gen_sub_i64(t2, t3, t2);
2226 tcg_temp_free_i64(t3);
2227 tcg_gen_trunc_i64_tl(t0, t2);
2228 tcg_gen_shri_i64(t2, t2, 32);
2229 tcg_gen_trunc_i64_tl(t1, t2);
2230 tcg_temp_free_i64(t2);
2231 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2232 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2234 opn = "msubu";
2235 break;
2236 default:
2237 MIPS_INVAL(opn);
2238 generate_exception(ctx, EXCP_RI);
2239 goto out;
2241 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2242 out:
2243 tcg_temp_free(t0);
2244 tcg_temp_free(t1);
2247 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2248 int rd, int rs, int rt)
2250 const char *opn = "mul vr54xx";
2251 TCGv t0 = tcg_temp_new();
2252 TCGv t1 = tcg_temp_new();
2254 gen_load_gpr(t0, rs);
2255 gen_load_gpr(t1, rt);
2257 switch (opc) {
2258 case OPC_VR54XX_MULS:
2259 gen_helper_muls(t0, t0, t1);
2260 opn = "muls";
2261 break;
2262 case OPC_VR54XX_MULSU:
2263 gen_helper_mulsu(t0, t0, t1);
2264 opn = "mulsu";
2265 break;
2266 case OPC_VR54XX_MACC:
2267 gen_helper_macc(t0, t0, t1);
2268 opn = "macc";
2269 break;
2270 case OPC_VR54XX_MACCU:
2271 gen_helper_maccu(t0, t0, t1);
2272 opn = "maccu";
2273 break;
2274 case OPC_VR54XX_MSAC:
2275 gen_helper_msac(t0, t0, t1);
2276 opn = "msac";
2277 break;
2278 case OPC_VR54XX_MSACU:
2279 gen_helper_msacu(t0, t0, t1);
2280 opn = "msacu";
2281 break;
2282 case OPC_VR54XX_MULHI:
2283 gen_helper_mulhi(t0, t0, t1);
2284 opn = "mulhi";
2285 break;
2286 case OPC_VR54XX_MULHIU:
2287 gen_helper_mulhiu(t0, t0, t1);
2288 opn = "mulhiu";
2289 break;
2290 case OPC_VR54XX_MULSHI:
2291 gen_helper_mulshi(t0, t0, t1);
2292 opn = "mulshi";
2293 break;
2294 case OPC_VR54XX_MULSHIU:
2295 gen_helper_mulshiu(t0, t0, t1);
2296 opn = "mulshiu";
2297 break;
2298 case OPC_VR54XX_MACCHI:
2299 gen_helper_macchi(t0, t0, t1);
2300 opn = "macchi";
2301 break;
2302 case OPC_VR54XX_MACCHIU:
2303 gen_helper_macchiu(t0, t0, t1);
2304 opn = "macchiu";
2305 break;
2306 case OPC_VR54XX_MSACHI:
2307 gen_helper_msachi(t0, t0, t1);
2308 opn = "msachi";
2309 break;
2310 case OPC_VR54XX_MSACHIU:
2311 gen_helper_msachiu(t0, t0, t1);
2312 opn = "msachiu";
2313 break;
2314 default:
2315 MIPS_INVAL("mul vr54xx");
2316 generate_exception(ctx, EXCP_RI);
2317 goto out;
2319 gen_store_gpr(t0, rd);
2320 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2322 out:
2323 tcg_temp_free(t0);
2324 tcg_temp_free(t1);
2327 static void gen_cl (DisasContext *ctx, uint32_t opc,
2328 int rd, int rs)
2330 const char *opn = "CLx";
2331 TCGv t0;
2333 if (rd == 0) {
2334 /* Treat as NOP. */
2335 MIPS_DEBUG("NOP");
2336 return;
2338 t0 = tcg_temp_new();
2339 gen_load_gpr(t0, rs);
2340 switch (opc) {
2341 case OPC_CLO:
2342 gen_helper_clo(cpu_gpr[rd], t0);
2343 opn = "clo";
2344 break;
2345 case OPC_CLZ:
2346 gen_helper_clz(cpu_gpr[rd], t0);
2347 opn = "clz";
2348 break;
2349 #if defined(TARGET_MIPS64)
2350 case OPC_DCLO:
2351 gen_helper_dclo(cpu_gpr[rd], t0);
2352 opn = "dclo";
2353 break;
2354 case OPC_DCLZ:
2355 gen_helper_dclz(cpu_gpr[rd], t0);
2356 opn = "dclz";
2357 break;
2358 #endif
2360 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2361 tcg_temp_free(t0);
2364 /* Traps */
2365 static void gen_trap (DisasContext *ctx, uint32_t opc,
2366 int rs, int rt, int16_t imm)
2368 int cond;
2369 TCGv t0 = tcg_temp_new();
2370 TCGv t1 = tcg_temp_new();
2372 cond = 0;
2373 /* Load needed operands */
2374 switch (opc) {
2375 case OPC_TEQ:
2376 case OPC_TGE:
2377 case OPC_TGEU:
2378 case OPC_TLT:
2379 case OPC_TLTU:
2380 case OPC_TNE:
2381 /* Compare two registers */
2382 if (rs != rt) {
2383 gen_load_gpr(t0, rs);
2384 gen_load_gpr(t1, rt);
2385 cond = 1;
2387 break;
2388 case OPC_TEQI:
2389 case OPC_TGEI:
2390 case OPC_TGEIU:
2391 case OPC_TLTI:
2392 case OPC_TLTIU:
2393 case OPC_TNEI:
2394 /* Compare register to immediate */
2395 if (rs != 0 || imm != 0) {
2396 gen_load_gpr(t0, rs);
2397 tcg_gen_movi_tl(t1, (int32_t)imm);
2398 cond = 1;
2400 break;
2402 if (cond == 0) {
2403 switch (opc) {
2404 case OPC_TEQ: /* rs == rs */
2405 case OPC_TEQI: /* r0 == 0 */
2406 case OPC_TGE: /* rs >= rs */
2407 case OPC_TGEI: /* r0 >= 0 */
2408 case OPC_TGEU: /* rs >= rs unsigned */
2409 case OPC_TGEIU: /* r0 >= 0 unsigned */
2410 /* Always trap */
2411 generate_exception(ctx, EXCP_TRAP);
2412 break;
2413 case OPC_TLT: /* rs < rs */
2414 case OPC_TLTI: /* r0 < 0 */
2415 case OPC_TLTU: /* rs < rs unsigned */
2416 case OPC_TLTIU: /* r0 < 0 unsigned */
2417 case OPC_TNE: /* rs != rs */
2418 case OPC_TNEI: /* r0 != 0 */
2419 /* Never trap: treat as NOP. */
2420 break;
2422 } else {
2423 int l1 = gen_new_label();
2425 switch (opc) {
2426 case OPC_TEQ:
2427 case OPC_TEQI:
2428 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2429 break;
2430 case OPC_TGE:
2431 case OPC_TGEI:
2432 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2433 break;
2434 case OPC_TGEU:
2435 case OPC_TGEIU:
2436 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2437 break;
2438 case OPC_TLT:
2439 case OPC_TLTI:
2440 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2441 break;
2442 case OPC_TLTU:
2443 case OPC_TLTIU:
2444 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2445 break;
2446 case OPC_TNE:
2447 case OPC_TNEI:
2448 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2449 break;
2451 generate_exception(ctx, EXCP_TRAP);
2452 gen_set_label(l1);
2454 tcg_temp_free(t0);
2455 tcg_temp_free(t1);
2458 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2460 TranslationBlock *tb;
2461 tb = ctx->tb;
2462 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2463 tcg_gen_goto_tb(n);
2464 gen_save_pc(dest);
2465 tcg_gen_exit_tb((long)tb + n);
2466 } else {
2467 gen_save_pc(dest);
2468 tcg_gen_exit_tb(0);
2472 /* Branches (before delay slot) */
2473 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2474 int rs, int rt, int32_t offset)
2476 target_ulong btgt = -1;
2477 int blink = 0;
2478 int bcond_compute = 0;
2479 TCGv t0 = tcg_temp_new();
2480 TCGv t1 = tcg_temp_new();
2482 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2483 #ifdef MIPS_DEBUG_DISAS
2484 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2485 #endif
2486 generate_exception(ctx, EXCP_RI);
2487 goto out;
2490 /* Load needed operands */
2491 switch (opc) {
2492 case OPC_BEQ:
2493 case OPC_BEQL:
2494 case OPC_BNE:
2495 case OPC_BNEL:
2496 /* Compare two registers */
2497 if (rs != rt) {
2498 gen_load_gpr(t0, rs);
2499 gen_load_gpr(t1, rt);
2500 bcond_compute = 1;
2502 btgt = ctx->pc + 4 + offset;
2503 break;
2504 case OPC_BGEZ:
2505 case OPC_BGEZAL:
2506 case OPC_BGEZALL:
2507 case OPC_BGEZL:
2508 case OPC_BGTZ:
2509 case OPC_BGTZL:
2510 case OPC_BLEZ:
2511 case OPC_BLEZL:
2512 case OPC_BLTZ:
2513 case OPC_BLTZAL:
2514 case OPC_BLTZALL:
2515 case OPC_BLTZL:
2516 /* Compare to zero */
2517 if (rs != 0) {
2518 gen_load_gpr(t0, rs);
2519 bcond_compute = 1;
2521 btgt = ctx->pc + 4 + offset;
2522 break;
2523 case OPC_J:
2524 case OPC_JAL:
2525 /* Jump to immediate */
2526 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2527 break;
2528 case OPC_JR:
2529 case OPC_JALR:
2530 /* Jump to register */
2531 if (offset != 0 && offset != 16) {
2532 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2533 others are reserved. */
2534 MIPS_INVAL("jump hint");
2535 generate_exception(ctx, EXCP_RI);
2536 goto out;
2538 gen_load_gpr(btarget, rs);
2539 break;
2540 default:
2541 MIPS_INVAL("branch/jump");
2542 generate_exception(ctx, EXCP_RI);
2543 goto out;
2545 if (bcond_compute == 0) {
2546 /* No condition to be computed */
2547 switch (opc) {
2548 case OPC_BEQ: /* rx == rx */
2549 case OPC_BEQL: /* rx == rx likely */
2550 case OPC_BGEZ: /* 0 >= 0 */
2551 case OPC_BGEZL: /* 0 >= 0 likely */
2552 case OPC_BLEZ: /* 0 <= 0 */
2553 case OPC_BLEZL: /* 0 <= 0 likely */
2554 /* Always take */
2555 ctx->hflags |= MIPS_HFLAG_B;
2556 MIPS_DEBUG("balways");
2557 break;
2558 case OPC_BGEZAL: /* 0 >= 0 */
2559 case OPC_BGEZALL: /* 0 >= 0 likely */
2560 /* Always take and link */
2561 blink = 31;
2562 ctx->hflags |= MIPS_HFLAG_B;
2563 MIPS_DEBUG("balways and link");
2564 break;
2565 case OPC_BNE: /* rx != rx */
2566 case OPC_BGTZ: /* 0 > 0 */
2567 case OPC_BLTZ: /* 0 < 0 */
2568 /* Treat as NOP. */
2569 MIPS_DEBUG("bnever (NOP)");
2570 goto out;
2571 case OPC_BLTZAL: /* 0 < 0 */
2572 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2573 MIPS_DEBUG("bnever and link");
2574 goto out;
2575 case OPC_BLTZALL: /* 0 < 0 likely */
2576 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2577 /* Skip the instruction in the delay slot */
2578 MIPS_DEBUG("bnever, link and skip");
2579 ctx->pc += 4;
2580 goto out;
2581 case OPC_BNEL: /* rx != rx likely */
2582 case OPC_BGTZL: /* 0 > 0 likely */
2583 case OPC_BLTZL: /* 0 < 0 likely */
2584 /* Skip the instruction in the delay slot */
2585 MIPS_DEBUG("bnever and skip");
2586 ctx->pc += 4;
2587 goto out;
2588 case OPC_J:
2589 ctx->hflags |= MIPS_HFLAG_B;
2590 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2591 break;
2592 case OPC_JAL:
2593 blink = 31;
2594 ctx->hflags |= MIPS_HFLAG_B;
2595 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2596 break;
2597 case OPC_JR:
2598 ctx->hflags |= MIPS_HFLAG_BR;
2599 MIPS_DEBUG("jr %s", regnames[rs]);
2600 break;
2601 case OPC_JALR:
2602 blink = rt;
2603 ctx->hflags |= MIPS_HFLAG_BR;
2604 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2605 break;
2606 default:
2607 MIPS_INVAL("branch/jump");
2608 generate_exception(ctx, EXCP_RI);
2609 goto out;
2611 } else {
2612 switch (opc) {
2613 case OPC_BEQ:
2614 gen_op_eq(bcond, t0, t1);
2615 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2616 regnames[rs], regnames[rt], btgt);
2617 goto not_likely;
2618 case OPC_BEQL:
2619 gen_op_eq(bcond, t0, t1);
2620 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2621 regnames[rs], regnames[rt], btgt);
2622 goto likely;
2623 case OPC_BNE:
2624 gen_op_ne(bcond, t0, t1);
2625 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2626 regnames[rs], regnames[rt], btgt);
2627 goto not_likely;
2628 case OPC_BNEL:
2629 gen_op_ne(bcond, t0, t1);
2630 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2631 regnames[rs], regnames[rt], btgt);
2632 goto likely;
2633 case OPC_BGEZ:
2634 gen_op_gez(bcond, t0);
2635 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2636 goto not_likely;
2637 case OPC_BGEZL:
2638 gen_op_gez(bcond, t0);
2639 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2640 goto likely;
2641 case OPC_BGEZAL:
2642 gen_op_gez(bcond, t0);
2643 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2644 blink = 31;
2645 goto not_likely;
2646 case OPC_BGEZALL:
2647 gen_op_gez(bcond, t0);
2648 blink = 31;
2649 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2650 goto likely;
2651 case OPC_BGTZ:
2652 gen_op_gtz(bcond, t0);
2653 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2654 goto not_likely;
2655 case OPC_BGTZL:
2656 gen_op_gtz(bcond, t0);
2657 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2658 goto likely;
2659 case OPC_BLEZ:
2660 gen_op_lez(bcond, t0);
2661 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2662 goto not_likely;
2663 case OPC_BLEZL:
2664 gen_op_lez(bcond, t0);
2665 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2666 goto likely;
2667 case OPC_BLTZ:
2668 gen_op_ltz(bcond, t0);
2669 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2670 goto not_likely;
2671 case OPC_BLTZL:
2672 gen_op_ltz(bcond, t0);
2673 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2674 goto likely;
2675 case OPC_BLTZAL:
2676 gen_op_ltz(bcond, t0);
2677 blink = 31;
2678 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2679 not_likely:
2680 ctx->hflags |= MIPS_HFLAG_BC;
2681 break;
2682 case OPC_BLTZALL:
2683 gen_op_ltz(bcond, t0);
2684 blink = 31;
2685 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2686 likely:
2687 ctx->hflags |= MIPS_HFLAG_BL;
2688 break;
2689 default:
2690 MIPS_INVAL("conditional branch/jump");
2691 generate_exception(ctx, EXCP_RI);
2692 goto out;
2695 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2696 blink, ctx->hflags, btgt);
2698 ctx->btarget = btgt;
2699 if (blink > 0) {
2700 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8);
2703 out:
2704 tcg_temp_free(t0);
2705 tcg_temp_free(t1);
2708 /* special3 bitfield operations */
2709 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2710 int rs, int lsb, int msb)
2712 TCGv t0 = tcg_temp_new();
2713 TCGv t1 = tcg_temp_new();
2714 target_ulong mask;
2716 gen_load_gpr(t1, rs);
2717 switch (opc) {
2718 case OPC_EXT:
2719 if (lsb + msb > 31)
2720 goto fail;
2721 tcg_gen_shri_tl(t0, t1, lsb);
2722 if (msb != 31) {
2723 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2724 } else {
2725 tcg_gen_ext32s_tl(t0, t0);
2727 break;
2728 #if defined(TARGET_MIPS64)
2729 case OPC_DEXTM:
2730 tcg_gen_shri_tl(t0, t1, lsb);
2731 if (msb != 31) {
2732 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2734 break;
2735 case OPC_DEXTU:
2736 tcg_gen_shri_tl(t0, t1, lsb + 32);
2737 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2738 break;
2739 case OPC_DEXT:
2740 tcg_gen_shri_tl(t0, t1, lsb);
2741 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2742 break;
2743 #endif
2744 case OPC_INS:
2745 if (lsb > msb)
2746 goto fail;
2747 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2748 gen_load_gpr(t0, rt);
2749 tcg_gen_andi_tl(t0, t0, ~mask);
2750 tcg_gen_shli_tl(t1, t1, lsb);
2751 tcg_gen_andi_tl(t1, t1, mask);
2752 tcg_gen_or_tl(t0, t0, t1);
2753 tcg_gen_ext32s_tl(t0, t0);
2754 break;
2755 #if defined(TARGET_MIPS64)
2756 case OPC_DINSM:
2757 if (lsb > msb)
2758 goto fail;
2759 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2760 gen_load_gpr(t0, rt);
2761 tcg_gen_andi_tl(t0, t0, ~mask);
2762 tcg_gen_shli_tl(t1, t1, lsb);
2763 tcg_gen_andi_tl(t1, t1, mask);
2764 tcg_gen_or_tl(t0, t0, t1);
2765 break;
2766 case OPC_DINSU:
2767 if (lsb > msb)
2768 goto fail;
2769 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2770 gen_load_gpr(t0, rt);
2771 tcg_gen_andi_tl(t0, t0, ~mask);
2772 tcg_gen_shli_tl(t1, t1, lsb + 32);
2773 tcg_gen_andi_tl(t1, t1, mask);
2774 tcg_gen_or_tl(t0, t0, t1);
2775 break;
2776 case OPC_DINS:
2777 if (lsb > msb)
2778 goto fail;
2779 gen_load_gpr(t0, rt);
2780 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2781 gen_load_gpr(t0, rt);
2782 tcg_gen_andi_tl(t0, t0, ~mask);
2783 tcg_gen_shli_tl(t1, t1, lsb);
2784 tcg_gen_andi_tl(t1, t1, mask);
2785 tcg_gen_or_tl(t0, t0, t1);
2786 break;
2787 #endif
2788 default:
2789 fail:
2790 MIPS_INVAL("bitops");
2791 generate_exception(ctx, EXCP_RI);
2792 tcg_temp_free(t0);
2793 tcg_temp_free(t1);
2794 return;
2796 gen_store_gpr(t0, rt);
2797 tcg_temp_free(t0);
2798 tcg_temp_free(t1);
2801 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2803 TCGv t0;
2805 if (rd == 0) {
2806 /* If no destination, treat it as a NOP. */
2807 MIPS_DEBUG("NOP");
2808 return;
2811 t0 = tcg_temp_new();
2812 gen_load_gpr(t0, rt);
2813 switch (op2) {
2814 case OPC_WSBH:
2816 TCGv t1 = tcg_temp_new();
2818 tcg_gen_shri_tl(t1, t0, 8);
2819 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2820 tcg_gen_shli_tl(t0, t0, 8);
2821 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2822 tcg_gen_or_tl(t0, t0, t1);
2823 tcg_temp_free(t1);
2824 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2826 break;
2827 case OPC_SEB:
2828 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2829 break;
2830 case OPC_SEH:
2831 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2832 break;
2833 #if defined(TARGET_MIPS64)
2834 case OPC_DSBH:
2836 TCGv t1 = tcg_temp_new();
2838 tcg_gen_shri_tl(t1, t0, 8);
2839 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2840 tcg_gen_shli_tl(t0, t0, 8);
2841 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2842 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2843 tcg_temp_free(t1);
2845 break;
2846 case OPC_DSHD:
2848 TCGv t1 = tcg_temp_new();
2850 tcg_gen_shri_tl(t1, t0, 16);
2851 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2852 tcg_gen_shli_tl(t0, t0, 16);
2853 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2854 tcg_gen_or_tl(t0, t0, t1);
2855 tcg_gen_shri_tl(t1, t0, 32);
2856 tcg_gen_shli_tl(t0, t0, 32);
2857 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2858 tcg_temp_free(t1);
2860 break;
2861 #endif
2862 default:
2863 MIPS_INVAL("bsfhl");
2864 generate_exception(ctx, EXCP_RI);
2865 tcg_temp_free(t0);
2866 return;
2868 tcg_temp_free(t0);
2871 #ifndef CONFIG_USER_ONLY
2872 /* CP0 (MMU and control) */
2873 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
2875 TCGv_i32 t0 = tcg_temp_new_i32();
2877 tcg_gen_ld_i32(t0, cpu_env, off);
2878 tcg_gen_ext_i32_tl(arg, t0);
2879 tcg_temp_free_i32(t0);
2882 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
2884 tcg_gen_ld_tl(arg, cpu_env, off);
2885 tcg_gen_ext32s_tl(arg, arg);
2888 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
2890 TCGv_i32 t0 = tcg_temp_new_i32();
2892 tcg_gen_trunc_tl_i32(t0, arg);
2893 tcg_gen_st_i32(t0, cpu_env, off);
2894 tcg_temp_free_i32(t0);
2897 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
2899 tcg_gen_ext32s_tl(arg, arg);
2900 tcg_gen_st_tl(arg, cpu_env, off);
2903 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
2905 const char *rn = "invalid";
2907 if (sel != 0)
2908 check_insn(env, ctx, ISA_MIPS32);
2910 switch (reg) {
2911 case 0:
2912 switch (sel) {
2913 case 0:
2914 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
2915 rn = "Index";
2916 break;
2917 case 1:
2918 check_insn(env, ctx, ASE_MT);
2919 gen_helper_mfc0_mvpcontrol(arg);
2920 rn = "MVPControl";
2921 break;
2922 case 2:
2923 check_insn(env, ctx, ASE_MT);
2924 gen_helper_mfc0_mvpconf0(arg);
2925 rn = "MVPConf0";
2926 break;
2927 case 3:
2928 check_insn(env, ctx, ASE_MT);
2929 gen_helper_mfc0_mvpconf1(arg);
2930 rn = "MVPConf1";
2931 break;
2932 default:
2933 goto die;
2935 break;
2936 case 1:
2937 switch (sel) {
2938 case 0:
2939 gen_helper_mfc0_random(arg);
2940 rn = "Random";
2941 break;
2942 case 1:
2943 check_insn(env, ctx, ASE_MT);
2944 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
2945 rn = "VPEControl";
2946 break;
2947 case 2:
2948 check_insn(env, ctx, ASE_MT);
2949 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
2950 rn = "VPEConf0";
2951 break;
2952 case 3:
2953 check_insn(env, ctx, ASE_MT);
2954 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
2955 rn = "VPEConf1";
2956 break;
2957 case 4:
2958 check_insn(env, ctx, ASE_MT);
2959 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
2960 rn = "YQMask";
2961 break;
2962 case 5:
2963 check_insn(env, ctx, ASE_MT);
2964 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
2965 rn = "VPESchedule";
2966 break;
2967 case 6:
2968 check_insn(env, ctx, ASE_MT);
2969 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
2970 rn = "VPEScheFBack";
2971 break;
2972 case 7:
2973 check_insn(env, ctx, ASE_MT);
2974 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
2975 rn = "VPEOpt";
2976 break;
2977 default:
2978 goto die;
2980 break;
2981 case 2:
2982 switch (sel) {
2983 case 0:
2984 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2985 tcg_gen_ext32s_tl(arg, arg);
2986 rn = "EntryLo0";
2987 break;
2988 case 1:
2989 check_insn(env, ctx, ASE_MT);
2990 gen_helper_mfc0_tcstatus(arg);
2991 rn = "TCStatus";
2992 break;
2993 case 2:
2994 check_insn(env, ctx, ASE_MT);
2995 gen_helper_mfc0_tcbind(arg);
2996 rn = "TCBind";
2997 break;
2998 case 3:
2999 check_insn(env, ctx, ASE_MT);
3000 gen_helper_mfc0_tcrestart(arg);
3001 rn = "TCRestart";
3002 break;
3003 case 4:
3004 check_insn(env, ctx, ASE_MT);
3005 gen_helper_mfc0_tchalt(arg);
3006 rn = "TCHalt";
3007 break;
3008 case 5:
3009 check_insn(env, ctx, ASE_MT);
3010 gen_helper_mfc0_tccontext(arg);
3011 rn = "TCContext";
3012 break;
3013 case 6:
3014 check_insn(env, ctx, ASE_MT);
3015 gen_helper_mfc0_tcschedule(arg);
3016 rn = "TCSchedule";
3017 break;
3018 case 7:
3019 check_insn(env, ctx, ASE_MT);
3020 gen_helper_mfc0_tcschefback(arg);
3021 rn = "TCScheFBack";
3022 break;
3023 default:
3024 goto die;
3026 break;
3027 case 3:
3028 switch (sel) {
3029 case 0:
3030 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
3031 tcg_gen_ext32s_tl(arg, arg);
3032 rn = "EntryLo1";
3033 break;
3034 default:
3035 goto die;
3037 break;
3038 case 4:
3039 switch (sel) {
3040 case 0:
3041 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3042 tcg_gen_ext32s_tl(arg, arg);
3043 rn = "Context";
3044 break;
3045 case 1:
3046 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3047 rn = "ContextConfig";
3048 // break;
3049 default:
3050 goto die;
3052 break;
3053 case 5:
3054 switch (sel) {
3055 case 0:
3056 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
3057 rn = "PageMask";
3058 break;
3059 case 1:
3060 check_insn(env, ctx, ISA_MIPS32R2);
3061 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
3062 rn = "PageGrain";
3063 break;
3064 default:
3065 goto die;
3067 break;
3068 case 6:
3069 switch (sel) {
3070 case 0:
3071 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
3072 rn = "Wired";
3073 break;
3074 case 1:
3075 check_insn(env, ctx, ISA_MIPS32R2);
3076 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
3077 rn = "SRSConf0";
3078 break;
3079 case 2:
3080 check_insn(env, ctx, ISA_MIPS32R2);
3081 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
3082 rn = "SRSConf1";
3083 break;
3084 case 3:
3085 check_insn(env, ctx, ISA_MIPS32R2);
3086 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
3087 rn = "SRSConf2";
3088 break;
3089 case 4:
3090 check_insn(env, ctx, ISA_MIPS32R2);
3091 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
3092 rn = "SRSConf3";
3093 break;
3094 case 5:
3095 check_insn(env, ctx, ISA_MIPS32R2);
3096 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
3097 rn = "SRSConf4";
3098 break;
3099 default:
3100 goto die;
3102 break;
3103 case 7:
3104 switch (sel) {
3105 case 0:
3106 check_insn(env, ctx, ISA_MIPS32R2);
3107 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
3108 rn = "HWREna";
3109 break;
3110 default:
3111 goto die;
3113 break;
3114 case 8:
3115 switch (sel) {
3116 case 0:
3117 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3118 tcg_gen_ext32s_tl(arg, arg);
3119 rn = "BadVAddr";
3120 break;
3121 default:
3122 goto die;
3124 break;
3125 case 9:
3126 switch (sel) {
3127 case 0:
3128 /* Mark as an IO operation because we read the time. */
3129 if (use_icount)
3130 gen_io_start();
3131 gen_helper_mfc0_count(arg);
3132 if (use_icount) {
3133 gen_io_end();
3134 ctx->bstate = BS_STOP;
3136 rn = "Count";
3137 break;
3138 /* 6,7 are implementation dependent */
3139 default:
3140 goto die;
3142 break;
3143 case 10:
3144 switch (sel) {
3145 case 0:
3146 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3147 tcg_gen_ext32s_tl(arg, arg);
3148 rn = "EntryHi";
3149 break;
3150 default:
3151 goto die;
3153 break;
3154 case 11:
3155 switch (sel) {
3156 case 0:
3157 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
3158 rn = "Compare";
3159 break;
3160 /* 6,7 are implementation dependent */
3161 default:
3162 goto die;
3164 break;
3165 case 12:
3166 switch (sel) {
3167 case 0:
3168 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
3169 rn = "Status";
3170 break;
3171 case 1:
3172 check_insn(env, ctx, ISA_MIPS32R2);
3173 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
3174 rn = "IntCtl";
3175 break;
3176 case 2:
3177 check_insn(env, ctx, ISA_MIPS32R2);
3178 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
3179 rn = "SRSCtl";
3180 break;
3181 case 3:
3182 check_insn(env, ctx, ISA_MIPS32R2);
3183 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
3184 rn = "SRSMap";
3185 break;
3186 default:
3187 goto die;
3189 break;
3190 case 13:
3191 switch (sel) {
3192 case 0:
3193 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
3194 rn = "Cause";
3195 break;
3196 default:
3197 goto die;
3199 break;
3200 case 14:
3201 switch (sel) {
3202 case 0:
3203 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3204 tcg_gen_ext32s_tl(arg, arg);
3205 rn = "EPC";
3206 break;
3207 default:
3208 goto die;
3210 break;
3211 case 15:
3212 switch (sel) {
3213 case 0:
3214 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
3215 rn = "PRid";
3216 break;
3217 case 1:
3218 check_insn(env, ctx, ISA_MIPS32R2);
3219 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
3220 rn = "EBase";
3221 break;
3222 default:
3223 goto die;
3225 break;
3226 case 16:
3227 switch (sel) {
3228 case 0:
3229 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
3230 rn = "Config";
3231 break;
3232 case 1:
3233 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
3234 rn = "Config1";
3235 break;
3236 case 2:
3237 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
3238 rn = "Config2";
3239 break;
3240 case 3:
3241 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
3242 rn = "Config3";
3243 break;
3244 /* 4,5 are reserved */
3245 /* 6,7 are implementation dependent */
3246 case 6:
3247 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
3248 rn = "Config6";
3249 break;
3250 case 7:
3251 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
3252 rn = "Config7";
3253 break;
3254 default:
3255 goto die;
3257 break;
3258 case 17:
3259 switch (sel) {
3260 case 0:
3261 gen_helper_mfc0_lladdr(arg);
3262 rn = "LLAddr";
3263 break;
3264 default:
3265 goto die;
3267 break;
3268 case 18:
3269 switch (sel) {
3270 case 0 ... 7:
3271 gen_helper_1i(mfc0_watchlo, arg, sel);
3272 rn = "WatchLo";
3273 break;
3274 default:
3275 goto die;
3277 break;
3278 case 19:
3279 switch (sel) {
3280 case 0 ...7:
3281 gen_helper_1i(mfc0_watchhi, arg, sel);
3282 rn = "WatchHi";
3283 break;
3284 default:
3285 goto die;
3287 break;
3288 case 20:
3289 switch (sel) {
3290 case 0:
3291 #if defined(TARGET_MIPS64)
3292 check_insn(env, ctx, ISA_MIPS3);
3293 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3294 tcg_gen_ext32s_tl(arg, arg);
3295 rn = "XContext";
3296 break;
3297 #endif
3298 default:
3299 goto die;
3301 break;
3302 case 21:
3303 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3304 switch (sel) {
3305 case 0:
3306 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
3307 rn = "Framemask";
3308 break;
3309 default:
3310 goto die;
3312 break;
3313 case 22:
3314 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3315 rn = "'Diagnostic"; /* implementation dependent */
3316 break;
3317 case 23:
3318 switch (sel) {
3319 case 0:
3320 gen_helper_mfc0_debug(arg); /* EJTAG support */
3321 rn = "Debug";
3322 break;
3323 case 1:
3324 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3325 rn = "TraceControl";
3326 // break;
3327 case 2:
3328 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3329 rn = "TraceControl2";
3330 // break;
3331 case 3:
3332 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3333 rn = "UserTraceData";
3334 // break;
3335 case 4:
3336 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3337 rn = "TraceBPC";
3338 // break;
3339 default:
3340 goto die;
3342 break;
3343 case 24:
3344 switch (sel) {
3345 case 0:
3346 /* EJTAG support */
3347 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3348 tcg_gen_ext32s_tl(arg, arg);
3349 rn = "DEPC";
3350 break;
3351 default:
3352 goto die;
3354 break;
3355 case 25:
3356 switch (sel) {
3357 case 0:
3358 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
3359 rn = "Performance0";
3360 break;
3361 case 1:
3362 // gen_helper_mfc0_performance1(arg);
3363 rn = "Performance1";
3364 // break;
3365 case 2:
3366 // gen_helper_mfc0_performance2(arg);
3367 rn = "Performance2";
3368 // break;
3369 case 3:
3370 // gen_helper_mfc0_performance3(arg);
3371 rn = "Performance3";
3372 // break;
3373 case 4:
3374 // gen_helper_mfc0_performance4(arg);
3375 rn = "Performance4";
3376 // break;
3377 case 5:
3378 // gen_helper_mfc0_performance5(arg);
3379 rn = "Performance5";
3380 // break;
3381 case 6:
3382 // gen_helper_mfc0_performance6(arg);
3383 rn = "Performance6";
3384 // break;
3385 case 7:
3386 // gen_helper_mfc0_performance7(arg);
3387 rn = "Performance7";
3388 // break;
3389 default:
3390 goto die;
3392 break;
3393 case 26:
3394 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3395 rn = "ECC";
3396 break;
3397 case 27:
3398 switch (sel) {
3399 case 0 ... 3:
3400 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3401 rn = "CacheErr";
3402 break;
3403 default:
3404 goto die;
3406 break;
3407 case 28:
3408 switch (sel) {
3409 case 0:
3410 case 2:
3411 case 4:
3412 case 6:
3413 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
3414 rn = "TagLo";
3415 break;
3416 case 1:
3417 case 3:
3418 case 5:
3419 case 7:
3420 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
3421 rn = "DataLo";
3422 break;
3423 default:
3424 goto die;
3426 break;
3427 case 29:
3428 switch (sel) {
3429 case 0:
3430 case 2:
3431 case 4:
3432 case 6:
3433 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
3434 rn = "TagHi";
3435 break;
3436 case 1:
3437 case 3:
3438 case 5:
3439 case 7:
3440 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
3441 rn = "DataHi";
3442 break;
3443 default:
3444 goto die;
3446 break;
3447 case 30:
3448 switch (sel) {
3449 case 0:
3450 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3451 tcg_gen_ext32s_tl(arg, arg);
3452 rn = "ErrorEPC";
3453 break;
3454 default:
3455 goto die;
3457 break;
3458 case 31:
3459 switch (sel) {
3460 case 0:
3461 /* EJTAG support */
3462 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
3463 rn = "DESAVE";
3464 break;
3465 default:
3466 goto die;
3468 break;
3469 default:
3470 goto die;
3472 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3473 return;
3475 die:
3476 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3477 generate_exception(ctx, EXCP_RI);
3480 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3482 const char *rn = "invalid";
3484 if (sel != 0)
3485 check_insn(env, ctx, ISA_MIPS32);
3487 if (use_icount)
3488 gen_io_start();
3490 switch (reg) {
3491 case 0:
3492 switch (sel) {
3493 case 0:
3494 gen_helper_mtc0_index(arg);
3495 rn = "Index";
3496 break;
3497 case 1:
3498 check_insn(env, ctx, ASE_MT);
3499 gen_helper_mtc0_mvpcontrol(arg);
3500 rn = "MVPControl";
3501 break;
3502 case 2:
3503 check_insn(env, ctx, ASE_MT);
3504 /* ignored */
3505 rn = "MVPConf0";
3506 break;
3507 case 3:
3508 check_insn(env, ctx, ASE_MT);
3509 /* ignored */
3510 rn = "MVPConf1";
3511 break;
3512 default:
3513 goto die;
3515 break;
3516 case 1:
3517 switch (sel) {
3518 case 0:
3519 /* ignored */
3520 rn = "Random";
3521 break;
3522 case 1:
3523 check_insn(env, ctx, ASE_MT);
3524 gen_helper_mtc0_vpecontrol(arg);
3525 rn = "VPEControl";
3526 break;
3527 case 2:
3528 check_insn(env, ctx, ASE_MT);
3529 gen_helper_mtc0_vpeconf0(arg);
3530 rn = "VPEConf0";
3531 break;
3532 case 3:
3533 check_insn(env, ctx, ASE_MT);
3534 gen_helper_mtc0_vpeconf1(arg);
3535 rn = "VPEConf1";
3536 break;
3537 case 4:
3538 check_insn(env, ctx, ASE_MT);
3539 gen_helper_mtc0_yqmask(arg);
3540 rn = "YQMask";
3541 break;
3542 case 5:
3543 check_insn(env, ctx, ASE_MT);
3544 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
3545 rn = "VPESchedule";
3546 break;
3547 case 6:
3548 check_insn(env, ctx, ASE_MT);
3549 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3550 rn = "VPEScheFBack";
3551 break;
3552 case 7:
3553 check_insn(env, ctx, ASE_MT);
3554 gen_helper_mtc0_vpeopt(arg);
3555 rn = "VPEOpt";
3556 break;
3557 default:
3558 goto die;
3560 break;
3561 case 2:
3562 switch (sel) {
3563 case 0:
3564 gen_helper_mtc0_entrylo0(arg);
3565 rn = "EntryLo0";
3566 break;
3567 case 1:
3568 check_insn(env, ctx, ASE_MT);
3569 gen_helper_mtc0_tcstatus(arg);
3570 rn = "TCStatus";
3571 break;
3572 case 2:
3573 check_insn(env, ctx, ASE_MT);
3574 gen_helper_mtc0_tcbind(arg);
3575 rn = "TCBind";
3576 break;
3577 case 3:
3578 check_insn(env, ctx, ASE_MT);
3579 gen_helper_mtc0_tcrestart(arg);
3580 rn = "TCRestart";
3581 break;
3582 case 4:
3583 check_insn(env, ctx, ASE_MT);
3584 gen_helper_mtc0_tchalt(arg);
3585 rn = "TCHalt";
3586 break;
3587 case 5:
3588 check_insn(env, ctx, ASE_MT);
3589 gen_helper_mtc0_tccontext(arg);
3590 rn = "TCContext";
3591 break;
3592 case 6:
3593 check_insn(env, ctx, ASE_MT);
3594 gen_helper_mtc0_tcschedule(arg);
3595 rn = "TCSchedule";
3596 break;
3597 case 7:
3598 check_insn(env, ctx, ASE_MT);
3599 gen_helper_mtc0_tcschefback(arg);
3600 rn = "TCScheFBack";
3601 break;
3602 default:
3603 goto die;
3605 break;
3606 case 3:
3607 switch (sel) {
3608 case 0:
3609 gen_helper_mtc0_entrylo1(arg);
3610 rn = "EntryLo1";
3611 break;
3612 default:
3613 goto die;
3615 break;
3616 case 4:
3617 switch (sel) {
3618 case 0:
3619 gen_helper_mtc0_context(arg);
3620 rn = "Context";
3621 break;
3622 case 1:
3623 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3624 rn = "ContextConfig";
3625 // break;
3626 default:
3627 goto die;
3629 break;
3630 case 5:
3631 switch (sel) {
3632 case 0:
3633 gen_helper_mtc0_pagemask(arg);
3634 rn = "PageMask";
3635 break;
3636 case 1:
3637 check_insn(env, ctx, ISA_MIPS32R2);
3638 gen_helper_mtc0_pagegrain(arg);
3639 rn = "PageGrain";
3640 break;
3641 default:
3642 goto die;
3644 break;
3645 case 6:
3646 switch (sel) {
3647 case 0:
3648 gen_helper_mtc0_wired(arg);
3649 rn = "Wired";
3650 break;
3651 case 1:
3652 check_insn(env, ctx, ISA_MIPS32R2);
3653 gen_helper_mtc0_srsconf0(arg);
3654 rn = "SRSConf0";
3655 break;
3656 case 2:
3657 check_insn(env, ctx, ISA_MIPS32R2);
3658 gen_helper_mtc0_srsconf1(arg);
3659 rn = "SRSConf1";
3660 break;
3661 case 3:
3662 check_insn(env, ctx, ISA_MIPS32R2);
3663 gen_helper_mtc0_srsconf2(arg);
3664 rn = "SRSConf2";
3665 break;
3666 case 4:
3667 check_insn(env, ctx, ISA_MIPS32R2);
3668 gen_helper_mtc0_srsconf3(arg);
3669 rn = "SRSConf3";
3670 break;
3671 case 5:
3672 check_insn(env, ctx, ISA_MIPS32R2);
3673 gen_helper_mtc0_srsconf4(arg);
3674 rn = "SRSConf4";
3675 break;
3676 default:
3677 goto die;
3679 break;
3680 case 7:
3681 switch (sel) {
3682 case 0:
3683 check_insn(env, ctx, ISA_MIPS32R2);
3684 gen_helper_mtc0_hwrena(arg);
3685 rn = "HWREna";
3686 break;
3687 default:
3688 goto die;
3690 break;
3691 case 8:
3692 /* ignored */
3693 rn = "BadVAddr";
3694 break;
3695 case 9:
3696 switch (sel) {
3697 case 0:
3698 gen_helper_mtc0_count(arg);
3699 rn = "Count";
3700 break;
3701 /* 6,7 are implementation dependent */
3702 default:
3703 goto die;
3705 break;
3706 case 10:
3707 switch (sel) {
3708 case 0:
3709 gen_helper_mtc0_entryhi(arg);
3710 rn = "EntryHi";
3711 break;
3712 default:
3713 goto die;
3715 break;
3716 case 11:
3717 switch (sel) {
3718 case 0:
3719 gen_helper_mtc0_compare(arg);
3720 rn = "Compare";
3721 break;
3722 /* 6,7 are implementation dependent */
3723 default:
3724 goto die;
3726 break;
3727 case 12:
3728 switch (sel) {
3729 case 0:
3730 save_cpu_state(ctx, 1);
3731 gen_helper_mtc0_status(arg);
3732 /* BS_STOP isn't good enough here, hflags may have changed. */
3733 gen_save_pc(ctx->pc + 4);
3734 ctx->bstate = BS_EXCP;
3735 rn = "Status";
3736 break;
3737 case 1:
3738 check_insn(env, ctx, ISA_MIPS32R2);
3739 gen_helper_mtc0_intctl(arg);
3740 /* Stop translation as we may have switched the execution mode */
3741 ctx->bstate = BS_STOP;
3742 rn = "IntCtl";
3743 break;
3744 case 2:
3745 check_insn(env, ctx, ISA_MIPS32R2);
3746 gen_helper_mtc0_srsctl(arg);
3747 /* Stop translation as we may have switched the execution mode */
3748 ctx->bstate = BS_STOP;
3749 rn = "SRSCtl";
3750 break;
3751 case 3:
3752 check_insn(env, ctx, ISA_MIPS32R2);
3753 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
3754 /* Stop translation as we may have switched the execution mode */
3755 ctx->bstate = BS_STOP;
3756 rn = "SRSMap";
3757 break;
3758 default:
3759 goto die;
3761 break;
3762 case 13:
3763 switch (sel) {
3764 case 0:
3765 save_cpu_state(ctx, 1);
3766 gen_helper_mtc0_cause(arg);
3767 rn = "Cause";
3768 break;
3769 default:
3770 goto die;
3772 break;
3773 case 14:
3774 switch (sel) {
3775 case 0:
3776 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
3777 rn = "EPC";
3778 break;
3779 default:
3780 goto die;
3782 break;
3783 case 15:
3784 switch (sel) {
3785 case 0:
3786 /* ignored */
3787 rn = "PRid";
3788 break;
3789 case 1:
3790 check_insn(env, ctx, ISA_MIPS32R2);
3791 gen_helper_mtc0_ebase(arg);
3792 rn = "EBase";
3793 break;
3794 default:
3795 goto die;
3797 break;
3798 case 16:
3799 switch (sel) {
3800 case 0:
3801 gen_helper_mtc0_config0(arg);
3802 rn = "Config";
3803 /* Stop translation as we may have switched the execution mode */
3804 ctx->bstate = BS_STOP;
3805 break;
3806 case 1:
3807 /* ignored, read only */
3808 rn = "Config1";
3809 break;
3810 case 2:
3811 gen_helper_mtc0_config2(arg);
3812 rn = "Config2";
3813 /* Stop translation as we may have switched the execution mode */
3814 ctx->bstate = BS_STOP;
3815 break;
3816 case 3:
3817 /* ignored, read only */
3818 rn = "Config3";
3819 break;
3820 /* 4,5 are reserved */
3821 /* 6,7 are implementation dependent */
3822 case 6:
3823 /* ignored */
3824 rn = "Config6";
3825 break;
3826 case 7:
3827 /* ignored */
3828 rn = "Config7";
3829 break;
3830 default:
3831 rn = "Invalid config selector";
3832 goto die;
3834 break;
3835 case 17:
3836 switch (sel) {
3837 case 0:
3838 /* ignored */
3839 rn = "LLAddr";
3840 break;
3841 default:
3842 goto die;
3844 break;
3845 case 18:
3846 switch (sel) {
3847 case 0 ... 7:
3848 gen_helper_1i(mtc0_watchlo, arg, sel);
3849 rn = "WatchLo";
3850 break;
3851 default:
3852 goto die;
3854 break;
3855 case 19:
3856 switch (sel) {
3857 case 0 ... 7:
3858 gen_helper_1i(mtc0_watchhi, arg, sel);
3859 rn = "WatchHi";
3860 break;
3861 default:
3862 goto die;
3864 break;
3865 case 20:
3866 switch (sel) {
3867 case 0:
3868 #if defined(TARGET_MIPS64)
3869 check_insn(env, ctx, ISA_MIPS3);
3870 gen_helper_mtc0_xcontext(arg);
3871 rn = "XContext";
3872 break;
3873 #endif
3874 default:
3875 goto die;
3877 break;
3878 case 21:
3879 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3880 switch (sel) {
3881 case 0:
3882 gen_helper_mtc0_framemask(arg);
3883 rn = "Framemask";
3884 break;
3885 default:
3886 goto die;
3888 break;
3889 case 22:
3890 /* ignored */
3891 rn = "Diagnostic"; /* implementation dependent */
3892 break;
3893 case 23:
3894 switch (sel) {
3895 case 0:
3896 gen_helper_mtc0_debug(arg); /* EJTAG support */
3897 /* BS_STOP isn't good enough here, hflags may have changed. */
3898 gen_save_pc(ctx->pc + 4);
3899 ctx->bstate = BS_EXCP;
3900 rn = "Debug";
3901 break;
3902 case 1:
3903 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
3904 rn = "TraceControl";
3905 /* Stop translation as we may have switched the execution mode */
3906 ctx->bstate = BS_STOP;
3907 // break;
3908 case 2:
3909 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
3910 rn = "TraceControl2";
3911 /* Stop translation as we may have switched the execution mode */
3912 ctx->bstate = BS_STOP;
3913 // break;
3914 case 3:
3915 /* Stop translation as we may have switched the execution mode */
3916 ctx->bstate = BS_STOP;
3917 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
3918 rn = "UserTraceData";
3919 /* Stop translation as we may have switched the execution mode */
3920 ctx->bstate = BS_STOP;
3921 // break;
3922 case 4:
3923 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
3924 /* Stop translation as we may have switched the execution mode */
3925 ctx->bstate = BS_STOP;
3926 rn = "TraceBPC";
3927 // break;
3928 default:
3929 goto die;
3931 break;
3932 case 24:
3933 switch (sel) {
3934 case 0:
3935 /* EJTAG support */
3936 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
3937 rn = "DEPC";
3938 break;
3939 default:
3940 goto die;
3942 break;
3943 case 25:
3944 switch (sel) {
3945 case 0:
3946 gen_helper_mtc0_performance0(arg);
3947 rn = "Performance0";
3948 break;
3949 case 1:
3950 // gen_helper_mtc0_performance1(arg);
3951 rn = "Performance1";
3952 // break;
3953 case 2:
3954 // gen_helper_mtc0_performance2(arg);
3955 rn = "Performance2";
3956 // break;
3957 case 3:
3958 // gen_helper_mtc0_performance3(arg);
3959 rn = "Performance3";
3960 // break;
3961 case 4:
3962 // gen_helper_mtc0_performance4(arg);
3963 rn = "Performance4";
3964 // break;
3965 case 5:
3966 // gen_helper_mtc0_performance5(arg);
3967 rn = "Performance5";
3968 // break;
3969 case 6:
3970 // gen_helper_mtc0_performance6(arg);
3971 rn = "Performance6";
3972 // break;
3973 case 7:
3974 // gen_helper_mtc0_performance7(arg);
3975 rn = "Performance7";
3976 // break;
3977 default:
3978 goto die;
3980 break;
3981 case 26:
3982 /* ignored */
3983 rn = "ECC";
3984 break;
3985 case 27:
3986 switch (sel) {
3987 case 0 ... 3:
3988 /* ignored */
3989 rn = "CacheErr";
3990 break;
3991 default:
3992 goto die;
3994 break;
3995 case 28:
3996 switch (sel) {
3997 case 0:
3998 case 2:
3999 case 4:
4000 case 6:
4001 gen_helper_mtc0_taglo(arg);
4002 rn = "TagLo";
4003 break;
4004 case 1:
4005 case 3:
4006 case 5:
4007 case 7:
4008 gen_helper_mtc0_datalo(arg);
4009 rn = "DataLo";
4010 break;
4011 default:
4012 goto die;
4014 break;
4015 case 29:
4016 switch (sel) {
4017 case 0:
4018 case 2:
4019 case 4:
4020 case 6:
4021 gen_helper_mtc0_taghi(arg);
4022 rn = "TagHi";
4023 break;
4024 case 1:
4025 case 3:
4026 case 5:
4027 case 7:
4028 gen_helper_mtc0_datahi(arg);
4029 rn = "DataHi";
4030 break;
4031 default:
4032 rn = "invalid sel";
4033 goto die;
4035 break;
4036 case 30:
4037 switch (sel) {
4038 case 0:
4039 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
4040 rn = "ErrorEPC";
4041 break;
4042 default:
4043 goto die;
4045 break;
4046 case 31:
4047 switch (sel) {
4048 case 0:
4049 /* EJTAG support */
4050 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
4051 rn = "DESAVE";
4052 break;
4053 default:
4054 goto die;
4056 /* Stop translation as we may have switched the execution mode */
4057 ctx->bstate = BS_STOP;
4058 break;
4059 default:
4060 goto die;
4062 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4063 /* For simplicity assume that all writes can cause interrupts. */
4064 if (use_icount) {
4065 gen_io_end();
4066 ctx->bstate = BS_STOP;
4068 return;
4070 die:
4071 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4072 generate_exception(ctx, EXCP_RI);
4075 #if defined(TARGET_MIPS64)
4076 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4078 const char *rn = "invalid";
4080 if (sel != 0)
4081 check_insn(env, ctx, ISA_MIPS64);
4083 switch (reg) {
4084 case 0:
4085 switch (sel) {
4086 case 0:
4087 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
4088 rn = "Index";
4089 break;
4090 case 1:
4091 check_insn(env, ctx, ASE_MT);
4092 gen_helper_mfc0_mvpcontrol(arg);
4093 rn = "MVPControl";
4094 break;
4095 case 2:
4096 check_insn(env, ctx, ASE_MT);
4097 gen_helper_mfc0_mvpconf0(arg);
4098 rn = "MVPConf0";
4099 break;
4100 case 3:
4101 check_insn(env, ctx, ASE_MT);
4102 gen_helper_mfc0_mvpconf1(arg);
4103 rn = "MVPConf1";
4104 break;
4105 default:
4106 goto die;
4108 break;
4109 case 1:
4110 switch (sel) {
4111 case 0:
4112 gen_helper_mfc0_random(arg);
4113 rn = "Random";
4114 break;
4115 case 1:
4116 check_insn(env, ctx, ASE_MT);
4117 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
4118 rn = "VPEControl";
4119 break;
4120 case 2:
4121 check_insn(env, ctx, ASE_MT);
4122 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
4123 rn = "VPEConf0";
4124 break;
4125 case 3:
4126 check_insn(env, ctx, ASE_MT);
4127 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
4128 rn = "VPEConf1";
4129 break;
4130 case 4:
4131 check_insn(env, ctx, ASE_MT);
4132 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
4133 rn = "YQMask";
4134 break;
4135 case 5:
4136 check_insn(env, ctx, ASE_MT);
4137 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4138 rn = "VPESchedule";
4139 break;
4140 case 6:
4141 check_insn(env, ctx, ASE_MT);
4142 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4143 rn = "VPEScheFBack";
4144 break;
4145 case 7:
4146 check_insn(env, ctx, ASE_MT);
4147 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
4148 rn = "VPEOpt";
4149 break;
4150 default:
4151 goto die;
4153 break;
4154 case 2:
4155 switch (sel) {
4156 case 0:
4157 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4158 rn = "EntryLo0";
4159 break;
4160 case 1:
4161 check_insn(env, ctx, ASE_MT);
4162 gen_helper_mfc0_tcstatus(arg);
4163 rn = "TCStatus";
4164 break;
4165 case 2:
4166 check_insn(env, ctx, ASE_MT);
4167 gen_helper_mfc0_tcbind(arg);
4168 rn = "TCBind";
4169 break;
4170 case 3:
4171 check_insn(env, ctx, ASE_MT);
4172 gen_helper_dmfc0_tcrestart(arg);
4173 rn = "TCRestart";
4174 break;
4175 case 4:
4176 check_insn(env, ctx, ASE_MT);
4177 gen_helper_dmfc0_tchalt(arg);
4178 rn = "TCHalt";
4179 break;
4180 case 5:
4181 check_insn(env, ctx, ASE_MT);
4182 gen_helper_dmfc0_tccontext(arg);
4183 rn = "TCContext";
4184 break;
4185 case 6:
4186 check_insn(env, ctx, ASE_MT);
4187 gen_helper_dmfc0_tcschedule(arg);
4188 rn = "TCSchedule";
4189 break;
4190 case 7:
4191 check_insn(env, ctx, ASE_MT);
4192 gen_helper_dmfc0_tcschefback(arg);
4193 rn = "TCScheFBack";
4194 break;
4195 default:
4196 goto die;
4198 break;
4199 case 3:
4200 switch (sel) {
4201 case 0:
4202 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4203 rn = "EntryLo1";
4204 break;
4205 default:
4206 goto die;
4208 break;
4209 case 4:
4210 switch (sel) {
4211 case 0:
4212 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
4213 rn = "Context";
4214 break;
4215 case 1:
4216 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4217 rn = "ContextConfig";
4218 // break;
4219 default:
4220 goto die;
4222 break;
4223 case 5:
4224 switch (sel) {
4225 case 0:
4226 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
4227 rn = "PageMask";
4228 break;
4229 case 1:
4230 check_insn(env, ctx, ISA_MIPS32R2);
4231 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
4232 rn = "PageGrain";
4233 break;
4234 default:
4235 goto die;
4237 break;
4238 case 6:
4239 switch (sel) {
4240 case 0:
4241 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
4242 rn = "Wired";
4243 break;
4244 case 1:
4245 check_insn(env, ctx, ISA_MIPS32R2);
4246 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
4247 rn = "SRSConf0";
4248 break;
4249 case 2:
4250 check_insn(env, ctx, ISA_MIPS32R2);
4251 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
4252 rn = "SRSConf1";
4253 break;
4254 case 3:
4255 check_insn(env, ctx, ISA_MIPS32R2);
4256 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
4257 rn = "SRSConf2";
4258 break;
4259 case 4:
4260 check_insn(env, ctx, ISA_MIPS32R2);
4261 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
4262 rn = "SRSConf3";
4263 break;
4264 case 5:
4265 check_insn(env, ctx, ISA_MIPS32R2);
4266 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
4267 rn = "SRSConf4";
4268 break;
4269 default:
4270 goto die;
4272 break;
4273 case 7:
4274 switch (sel) {
4275 case 0:
4276 check_insn(env, ctx, ISA_MIPS32R2);
4277 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
4278 rn = "HWREna";
4279 break;
4280 default:
4281 goto die;
4283 break;
4284 case 8:
4285 switch (sel) {
4286 case 0:
4287 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4288 rn = "BadVAddr";
4289 break;
4290 default:
4291 goto die;
4293 break;
4294 case 9:
4295 switch (sel) {
4296 case 0:
4297 /* Mark as an IO operation because we read the time. */
4298 if (use_icount)
4299 gen_io_start();
4300 gen_helper_mfc0_count(arg);
4301 if (use_icount) {
4302 gen_io_end();
4303 ctx->bstate = BS_STOP;
4305 rn = "Count";
4306 break;
4307 /* 6,7 are implementation dependent */
4308 default:
4309 goto die;
4311 break;
4312 case 10:
4313 switch (sel) {
4314 case 0:
4315 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
4316 rn = "EntryHi";
4317 break;
4318 default:
4319 goto die;
4321 break;
4322 case 11:
4323 switch (sel) {
4324 case 0:
4325 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
4326 rn = "Compare";
4327 break;
4328 /* 6,7 are implementation dependent */
4329 default:
4330 goto die;
4332 break;
4333 case 12:
4334 switch (sel) {
4335 case 0:
4336 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
4337 rn = "Status";
4338 break;
4339 case 1:
4340 check_insn(env, ctx, ISA_MIPS32R2);
4341 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
4342 rn = "IntCtl";
4343 break;
4344 case 2:
4345 check_insn(env, ctx, ISA_MIPS32R2);
4346 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
4347 rn = "SRSCtl";
4348 break;
4349 case 3:
4350 check_insn(env, ctx, ISA_MIPS32R2);
4351 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
4352 rn = "SRSMap";
4353 break;
4354 default:
4355 goto die;
4357 break;
4358 case 13:
4359 switch (sel) {
4360 case 0:
4361 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
4362 rn = "Cause";
4363 break;
4364 default:
4365 goto die;
4367 break;
4368 case 14:
4369 switch (sel) {
4370 case 0:
4371 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4372 rn = "EPC";
4373 break;
4374 default:
4375 goto die;
4377 break;
4378 case 15:
4379 switch (sel) {
4380 case 0:
4381 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
4382 rn = "PRid";
4383 break;
4384 case 1:
4385 check_insn(env, ctx, ISA_MIPS32R2);
4386 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
4387 rn = "EBase";
4388 break;
4389 default:
4390 goto die;
4392 break;
4393 case 16:
4394 switch (sel) {
4395 case 0:
4396 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
4397 rn = "Config";
4398 break;
4399 case 1:
4400 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
4401 rn = "Config1";
4402 break;
4403 case 2:
4404 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
4405 rn = "Config2";
4406 break;
4407 case 3:
4408 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
4409 rn = "Config3";
4410 break;
4411 /* 6,7 are implementation dependent */
4412 case 6:
4413 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
4414 rn = "Config6";
4415 break;
4416 case 7:
4417 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
4418 rn = "Config7";
4419 break;
4420 default:
4421 goto die;
4423 break;
4424 case 17:
4425 switch (sel) {
4426 case 0:
4427 gen_helper_dmfc0_lladdr(arg);
4428 rn = "LLAddr";
4429 break;
4430 default:
4431 goto die;
4433 break;
4434 case 18:
4435 switch (sel) {
4436 case 0 ... 7:
4437 gen_helper_1i(dmfc0_watchlo, arg, sel);
4438 rn = "WatchLo";
4439 break;
4440 default:
4441 goto die;
4443 break;
4444 case 19:
4445 switch (sel) {
4446 case 0 ... 7:
4447 gen_helper_1i(mfc0_watchhi, arg, sel);
4448 rn = "WatchHi";
4449 break;
4450 default:
4451 goto die;
4453 break;
4454 case 20:
4455 switch (sel) {
4456 case 0:
4457 check_insn(env, ctx, ISA_MIPS3);
4458 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
4459 rn = "XContext";
4460 break;
4461 default:
4462 goto die;
4464 break;
4465 case 21:
4466 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4467 switch (sel) {
4468 case 0:
4469 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
4470 rn = "Framemask";
4471 break;
4472 default:
4473 goto die;
4475 break;
4476 case 22:
4477 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4478 rn = "'Diagnostic"; /* implementation dependent */
4479 break;
4480 case 23:
4481 switch (sel) {
4482 case 0:
4483 gen_helper_mfc0_debug(arg); /* EJTAG support */
4484 rn = "Debug";
4485 break;
4486 case 1:
4487 // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4488 rn = "TraceControl";
4489 // break;
4490 case 2:
4491 // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4492 rn = "TraceControl2";
4493 // break;
4494 case 3:
4495 // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4496 rn = "UserTraceData";
4497 // break;
4498 case 4:
4499 // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4500 rn = "TraceBPC";
4501 // break;
4502 default:
4503 goto die;
4505 break;
4506 case 24:
4507 switch (sel) {
4508 case 0:
4509 /* EJTAG support */
4510 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4511 rn = "DEPC";
4512 break;
4513 default:
4514 goto die;
4516 break;
4517 case 25:
4518 switch (sel) {
4519 case 0:
4520 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
4521 rn = "Performance0";
4522 break;
4523 case 1:
4524 // gen_helper_dmfc0_performance1(arg);
4525 rn = "Performance1";
4526 // break;
4527 case 2:
4528 // gen_helper_dmfc0_performance2(arg);
4529 rn = "Performance2";
4530 // break;
4531 case 3:
4532 // gen_helper_dmfc0_performance3(arg);
4533 rn = "Performance3";
4534 // break;
4535 case 4:
4536 // gen_helper_dmfc0_performance4(arg);
4537 rn = "Performance4";
4538 // break;
4539 case 5:
4540 // gen_helper_dmfc0_performance5(arg);
4541 rn = "Performance5";
4542 // break;
4543 case 6:
4544 // gen_helper_dmfc0_performance6(arg);
4545 rn = "Performance6";
4546 // break;
4547 case 7:
4548 // gen_helper_dmfc0_performance7(arg);
4549 rn = "Performance7";
4550 // break;
4551 default:
4552 goto die;
4554 break;
4555 case 26:
4556 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4557 rn = "ECC";
4558 break;
4559 case 27:
4560 switch (sel) {
4561 /* ignored */
4562 case 0 ... 3:
4563 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4564 rn = "CacheErr";
4565 break;
4566 default:
4567 goto die;
4569 break;
4570 case 28:
4571 switch (sel) {
4572 case 0:
4573 case 2:
4574 case 4:
4575 case 6:
4576 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
4577 rn = "TagLo";
4578 break;
4579 case 1:
4580 case 3:
4581 case 5:
4582 case 7:
4583 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
4584 rn = "DataLo";
4585 break;
4586 default:
4587 goto die;
4589 break;
4590 case 29:
4591 switch (sel) {
4592 case 0:
4593 case 2:
4594 case 4:
4595 case 6:
4596 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
4597 rn = "TagHi";
4598 break;
4599 case 1:
4600 case 3:
4601 case 5:
4602 case 7:
4603 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
4604 rn = "DataHi";
4605 break;
4606 default:
4607 goto die;
4609 break;
4610 case 30:
4611 switch (sel) {
4612 case 0:
4613 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4614 rn = "ErrorEPC";
4615 break;
4616 default:
4617 goto die;
4619 break;
4620 case 31:
4621 switch (sel) {
4622 case 0:
4623 /* EJTAG support */
4624 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
4625 rn = "DESAVE";
4626 break;
4627 default:
4628 goto die;
4630 break;
4631 default:
4632 goto die;
4634 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4635 return;
4637 die:
4638 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4639 generate_exception(ctx, EXCP_RI);
4642 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4644 const char *rn = "invalid";
4646 if (sel != 0)
4647 check_insn(env, ctx, ISA_MIPS64);
4649 if (use_icount)
4650 gen_io_start();
4652 switch (reg) {
4653 case 0:
4654 switch (sel) {
4655 case 0:
4656 gen_helper_mtc0_index(arg);
4657 rn = "Index";
4658 break;
4659 case 1:
4660 check_insn(env, ctx, ASE_MT);
4661 gen_helper_mtc0_mvpcontrol(arg);
4662 rn = "MVPControl";
4663 break;
4664 case 2:
4665 check_insn(env, ctx, ASE_MT);
4666 /* ignored */
4667 rn = "MVPConf0";
4668 break;
4669 case 3:
4670 check_insn(env, ctx, ASE_MT);
4671 /* ignored */
4672 rn = "MVPConf1";
4673 break;
4674 default:
4675 goto die;
4677 break;
4678 case 1:
4679 switch (sel) {
4680 case 0:
4681 /* ignored */
4682 rn = "Random";
4683 break;
4684 case 1:
4685 check_insn(env, ctx, ASE_MT);
4686 gen_helper_mtc0_vpecontrol(arg);
4687 rn = "VPEControl";
4688 break;
4689 case 2:
4690 check_insn(env, ctx, ASE_MT);
4691 gen_helper_mtc0_vpeconf0(arg);
4692 rn = "VPEConf0";
4693 break;
4694 case 3:
4695 check_insn(env, ctx, ASE_MT);
4696 gen_helper_mtc0_vpeconf1(arg);
4697 rn = "VPEConf1";
4698 break;
4699 case 4:
4700 check_insn(env, ctx, ASE_MT);
4701 gen_helper_mtc0_yqmask(arg);
4702 rn = "YQMask";
4703 break;
4704 case 5:
4705 check_insn(env, ctx, ASE_MT);
4706 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4707 rn = "VPESchedule";
4708 break;
4709 case 6:
4710 check_insn(env, ctx, ASE_MT);
4711 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4712 rn = "VPEScheFBack";
4713 break;
4714 case 7:
4715 check_insn(env, ctx, ASE_MT);
4716 gen_helper_mtc0_vpeopt(arg);
4717 rn = "VPEOpt";
4718 break;
4719 default:
4720 goto die;
4722 break;
4723 case 2:
4724 switch (sel) {
4725 case 0:
4726 gen_helper_mtc0_entrylo0(arg);
4727 rn = "EntryLo0";
4728 break;
4729 case 1:
4730 check_insn(env, ctx, ASE_MT);
4731 gen_helper_mtc0_tcstatus(arg);
4732 rn = "TCStatus";
4733 break;
4734 case 2:
4735 check_insn(env, ctx, ASE_MT);
4736 gen_helper_mtc0_tcbind(arg);
4737 rn = "TCBind";
4738 break;
4739 case 3:
4740 check_insn(env, ctx, ASE_MT);
4741 gen_helper_mtc0_tcrestart(arg);
4742 rn = "TCRestart";
4743 break;
4744 case 4:
4745 check_insn(env, ctx, ASE_MT);
4746 gen_helper_mtc0_tchalt(arg);
4747 rn = "TCHalt";
4748 break;
4749 case 5:
4750 check_insn(env, ctx, ASE_MT);
4751 gen_helper_mtc0_tccontext(arg);
4752 rn = "TCContext";
4753 break;
4754 case 6:
4755 check_insn(env, ctx, ASE_MT);
4756 gen_helper_mtc0_tcschedule(arg);
4757 rn = "TCSchedule";
4758 break;
4759 case 7:
4760 check_insn(env, ctx, ASE_MT);
4761 gen_helper_mtc0_tcschefback(arg);
4762 rn = "TCScheFBack";
4763 break;
4764 default:
4765 goto die;
4767 break;
4768 case 3:
4769 switch (sel) {
4770 case 0:
4771 gen_helper_mtc0_entrylo1(arg);
4772 rn = "EntryLo1";
4773 break;
4774 default:
4775 goto die;
4777 break;
4778 case 4:
4779 switch (sel) {
4780 case 0:
4781 gen_helper_mtc0_context(arg);
4782 rn = "Context";
4783 break;
4784 case 1:
4785 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
4786 rn = "ContextConfig";
4787 // break;
4788 default:
4789 goto die;
4791 break;
4792 case 5:
4793 switch (sel) {
4794 case 0:
4795 gen_helper_mtc0_pagemask(arg);
4796 rn = "PageMask";
4797 break;
4798 case 1:
4799 check_insn(env, ctx, ISA_MIPS32R2);
4800 gen_helper_mtc0_pagegrain(arg);
4801 rn = "PageGrain";
4802 break;
4803 default:
4804 goto die;
4806 break;
4807 case 6:
4808 switch (sel) {
4809 case 0:
4810 gen_helper_mtc0_wired(arg);
4811 rn = "Wired";
4812 break;
4813 case 1:
4814 check_insn(env, ctx, ISA_MIPS32R2);
4815 gen_helper_mtc0_srsconf0(arg);
4816 rn = "SRSConf0";
4817 break;
4818 case 2:
4819 check_insn(env, ctx, ISA_MIPS32R2);
4820 gen_helper_mtc0_srsconf1(arg);
4821 rn = "SRSConf1";
4822 break;
4823 case 3:
4824 check_insn(env, ctx, ISA_MIPS32R2);
4825 gen_helper_mtc0_srsconf2(arg);
4826 rn = "SRSConf2";
4827 break;
4828 case 4:
4829 check_insn(env, ctx, ISA_MIPS32R2);
4830 gen_helper_mtc0_srsconf3(arg);
4831 rn = "SRSConf3";
4832 break;
4833 case 5:
4834 check_insn(env, ctx, ISA_MIPS32R2);
4835 gen_helper_mtc0_srsconf4(arg);
4836 rn = "SRSConf4";
4837 break;
4838 default:
4839 goto die;
4841 break;
4842 case 7:
4843 switch (sel) {
4844 case 0:
4845 check_insn(env, ctx, ISA_MIPS32R2);
4846 gen_helper_mtc0_hwrena(arg);
4847 rn = "HWREna";
4848 break;
4849 default:
4850 goto die;
4852 break;
4853 case 8:
4854 /* ignored */
4855 rn = "BadVAddr";
4856 break;
4857 case 9:
4858 switch (sel) {
4859 case 0:
4860 gen_helper_mtc0_count(arg);
4861 rn = "Count";
4862 break;
4863 /* 6,7 are implementation dependent */
4864 default:
4865 goto die;
4867 /* Stop translation as we may have switched the execution mode */
4868 ctx->bstate = BS_STOP;
4869 break;
4870 case 10:
4871 switch (sel) {
4872 case 0:
4873 gen_helper_mtc0_entryhi(arg);
4874 rn = "EntryHi";
4875 break;
4876 default:
4877 goto die;
4879 break;
4880 case 11:
4881 switch (sel) {
4882 case 0:
4883 gen_helper_mtc0_compare(arg);
4884 rn = "Compare";
4885 break;
4886 /* 6,7 are implementation dependent */
4887 default:
4888 goto die;
4890 /* Stop translation as we may have switched the execution mode */
4891 ctx->bstate = BS_STOP;
4892 break;
4893 case 12:
4894 switch (sel) {
4895 case 0:
4896 save_cpu_state(ctx, 1);
4897 gen_helper_mtc0_status(arg);
4898 /* BS_STOP isn't good enough here, hflags may have changed. */
4899 gen_save_pc(ctx->pc + 4);
4900 ctx->bstate = BS_EXCP;
4901 rn = "Status";
4902 break;
4903 case 1:
4904 check_insn(env, ctx, ISA_MIPS32R2);
4905 gen_helper_mtc0_intctl(arg);
4906 /* Stop translation as we may have switched the execution mode */
4907 ctx->bstate = BS_STOP;
4908 rn = "IntCtl";
4909 break;
4910 case 2:
4911 check_insn(env, ctx, ISA_MIPS32R2);
4912 gen_helper_mtc0_srsctl(arg);
4913 /* Stop translation as we may have switched the execution mode */
4914 ctx->bstate = BS_STOP;
4915 rn = "SRSCtl";
4916 break;
4917 case 3:
4918 check_insn(env, ctx, ISA_MIPS32R2);
4919 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
4920 /* Stop translation as we may have switched the execution mode */
4921 ctx->bstate = BS_STOP;
4922 rn = "SRSMap";
4923 break;
4924 default:
4925 goto die;
4927 break;
4928 case 13:
4929 switch (sel) {
4930 case 0:
4931 save_cpu_state(ctx, 1);
4932 gen_helper_mtc0_cause(arg);
4933 rn = "Cause";
4934 break;
4935 default:
4936 goto die;
4938 break;
4939 case 14:
4940 switch (sel) {
4941 case 0:
4942 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4943 rn = "EPC";
4944 break;
4945 default:
4946 goto die;
4948 break;
4949 case 15:
4950 switch (sel) {
4951 case 0:
4952 /* ignored */
4953 rn = "PRid";
4954 break;
4955 case 1:
4956 check_insn(env, ctx, ISA_MIPS32R2);
4957 gen_helper_mtc0_ebase(arg);
4958 rn = "EBase";
4959 break;
4960 default:
4961 goto die;
4963 break;
4964 case 16:
4965 switch (sel) {
4966 case 0:
4967 gen_helper_mtc0_config0(arg);
4968 rn = "Config";
4969 /* Stop translation as we may have switched the execution mode */
4970 ctx->bstate = BS_STOP;
4971 break;
4972 case 1:
4973 /* ignored, read only */
4974 rn = "Config1";
4975 break;
4976 case 2:
4977 gen_helper_mtc0_config2(arg);
4978 rn = "Config2";
4979 /* Stop translation as we may have switched the execution mode */
4980 ctx->bstate = BS_STOP;
4981 break;
4982 case 3:
4983 /* ignored */
4984 rn = "Config3";
4985 break;
4986 /* 6,7 are implementation dependent */
4987 default:
4988 rn = "Invalid config selector";
4989 goto die;
4991 break;
4992 case 17:
4993 switch (sel) {
4994 case 0:
4995 /* ignored */
4996 rn = "LLAddr";
4997 break;
4998 default:
4999 goto die;
5001 break;
5002 case 18:
5003 switch (sel) {
5004 case 0 ... 7:
5005 gen_helper_1i(mtc0_watchlo, arg, sel);
5006 rn = "WatchLo";
5007 break;
5008 default:
5009 goto die;
5011 break;
5012 case 19:
5013 switch (sel) {
5014 case 0 ... 7:
5015 gen_helper_1i(mtc0_watchhi, arg, sel);
5016 rn = "WatchHi";
5017 break;
5018 default:
5019 goto die;
5021 break;
5022 case 20:
5023 switch (sel) {
5024 case 0:
5025 check_insn(env, ctx, ISA_MIPS3);
5026 gen_helper_mtc0_xcontext(arg);
5027 rn = "XContext";
5028 break;
5029 default:
5030 goto die;
5032 break;
5033 case 21:
5034 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5035 switch (sel) {
5036 case 0:
5037 gen_helper_mtc0_framemask(arg);
5038 rn = "Framemask";
5039 break;
5040 default:
5041 goto die;
5043 break;
5044 case 22:
5045 /* ignored */
5046 rn = "Diagnostic"; /* implementation dependent */
5047 break;
5048 case 23:
5049 switch (sel) {
5050 case 0:
5051 gen_helper_mtc0_debug(arg); /* EJTAG support */
5052 /* BS_STOP isn't good enough here, hflags may have changed. */
5053 gen_save_pc(ctx->pc + 4);
5054 ctx->bstate = BS_EXCP;
5055 rn = "Debug";
5056 break;
5057 case 1:
5058 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
5059 /* Stop translation as we may have switched the execution mode */
5060 ctx->bstate = BS_STOP;
5061 rn = "TraceControl";
5062 // break;
5063 case 2:
5064 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
5065 /* Stop translation as we may have switched the execution mode */
5066 ctx->bstate = BS_STOP;
5067 rn = "TraceControl2";
5068 // break;
5069 case 3:
5070 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
5071 /* Stop translation as we may have switched the execution mode */
5072 ctx->bstate = BS_STOP;
5073 rn = "UserTraceData";
5074 // break;
5075 case 4:
5076 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
5077 /* Stop translation as we may have switched the execution mode */
5078 ctx->bstate = BS_STOP;
5079 rn = "TraceBPC";
5080 // break;
5081 default:
5082 goto die;
5084 break;
5085 case 24:
5086 switch (sel) {
5087 case 0:
5088 /* EJTAG support */
5089 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
5090 rn = "DEPC";
5091 break;
5092 default:
5093 goto die;
5095 break;
5096 case 25:
5097 switch (sel) {
5098 case 0:
5099 gen_helper_mtc0_performance0(arg);
5100 rn = "Performance0";
5101 break;
5102 case 1:
5103 // gen_helper_mtc0_performance1(arg);
5104 rn = "Performance1";
5105 // break;
5106 case 2:
5107 // gen_helper_mtc0_performance2(arg);
5108 rn = "Performance2";
5109 // break;
5110 case 3:
5111 // gen_helper_mtc0_performance3(arg);
5112 rn = "Performance3";
5113 // break;
5114 case 4:
5115 // gen_helper_mtc0_performance4(arg);
5116 rn = "Performance4";
5117 // break;
5118 case 5:
5119 // gen_helper_mtc0_performance5(arg);
5120 rn = "Performance5";
5121 // break;
5122 case 6:
5123 // gen_helper_mtc0_performance6(arg);
5124 rn = "Performance6";
5125 // break;
5126 case 7:
5127 // gen_helper_mtc0_performance7(arg);
5128 rn = "Performance7";
5129 // break;
5130 default:
5131 goto die;
5133 break;
5134 case 26:
5135 /* ignored */
5136 rn = "ECC";
5137 break;
5138 case 27:
5139 switch (sel) {
5140 case 0 ... 3:
5141 /* ignored */
5142 rn = "CacheErr";
5143 break;
5144 default:
5145 goto die;
5147 break;
5148 case 28:
5149 switch (sel) {
5150 case 0:
5151 case 2:
5152 case 4:
5153 case 6:
5154 gen_helper_mtc0_taglo(arg);
5155 rn = "TagLo";
5156 break;
5157 case 1:
5158 case 3:
5159 case 5:
5160 case 7:
5161 gen_helper_mtc0_datalo(arg);
5162 rn = "DataLo";
5163 break;
5164 default:
5165 goto die;
5167 break;
5168 case 29:
5169 switch (sel) {
5170 case 0:
5171 case 2:
5172 case 4:
5173 case 6:
5174 gen_helper_mtc0_taghi(arg);
5175 rn = "TagHi";
5176 break;
5177 case 1:
5178 case 3:
5179 case 5:
5180 case 7:
5181 gen_helper_mtc0_datahi(arg);
5182 rn = "DataHi";
5183 break;
5184 default:
5185 rn = "invalid sel";
5186 goto die;
5188 break;
5189 case 30:
5190 switch (sel) {
5191 case 0:
5192 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5193 rn = "ErrorEPC";
5194 break;
5195 default:
5196 goto die;
5198 break;
5199 case 31:
5200 switch (sel) {
5201 case 0:
5202 /* EJTAG support */
5203 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
5204 rn = "DESAVE";
5205 break;
5206 default:
5207 goto die;
5209 /* Stop translation as we may have switched the execution mode */
5210 ctx->bstate = BS_STOP;
5211 break;
5212 default:
5213 goto die;
5215 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5216 /* For simplicity assume that all writes can cause interrupts. */
5217 if (use_icount) {
5218 gen_io_end();
5219 ctx->bstate = BS_STOP;
5221 return;
5223 die:
5224 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5225 generate_exception(ctx, EXCP_RI);
5227 #endif /* TARGET_MIPS64 */
5229 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5230 int u, int sel, int h)
5232 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5233 TCGv t0 = tcg_temp_local_new();
5235 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5236 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5237 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5238 tcg_gen_movi_tl(t0, -1);
5239 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5240 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5241 tcg_gen_movi_tl(t0, -1);
5242 else if (u == 0) {
5243 switch (rt) {
5244 case 2:
5245 switch (sel) {
5246 case 1:
5247 gen_helper_mftc0_tcstatus(t0);
5248 break;
5249 case 2:
5250 gen_helper_mftc0_tcbind(t0);
5251 break;
5252 case 3:
5253 gen_helper_mftc0_tcrestart(t0);
5254 break;
5255 case 4:
5256 gen_helper_mftc0_tchalt(t0);
5257 break;
5258 case 5:
5259 gen_helper_mftc0_tccontext(t0);
5260 break;
5261 case 6:
5262 gen_helper_mftc0_tcschedule(t0);
5263 break;
5264 case 7:
5265 gen_helper_mftc0_tcschefback(t0);
5266 break;
5267 default:
5268 gen_mfc0(env, ctx, t0, rt, sel);
5269 break;
5271 break;
5272 case 10:
5273 switch (sel) {
5274 case 0:
5275 gen_helper_mftc0_entryhi(t0);
5276 break;
5277 default:
5278 gen_mfc0(env, ctx, t0, rt, sel);
5279 break;
5281 case 12:
5282 switch (sel) {
5283 case 0:
5284 gen_helper_mftc0_status(t0);
5285 break;
5286 default:
5287 gen_mfc0(env, ctx, t0, rt, sel);
5288 break;
5290 case 23:
5291 switch (sel) {
5292 case 0:
5293 gen_helper_mftc0_debug(t0);
5294 break;
5295 default:
5296 gen_mfc0(env, ctx, t0, rt, sel);
5297 break;
5299 break;
5300 default:
5301 gen_mfc0(env, ctx, t0, rt, sel);
5303 } else switch (sel) {
5304 /* GPR registers. */
5305 case 0:
5306 gen_helper_1i(mftgpr, t0, rt);
5307 break;
5308 /* Auxiliary CPU registers */
5309 case 1:
5310 switch (rt) {
5311 case 0:
5312 gen_helper_1i(mftlo, t0, 0);
5313 break;
5314 case 1:
5315 gen_helper_1i(mfthi, t0, 0);
5316 break;
5317 case 2:
5318 gen_helper_1i(mftacx, t0, 0);
5319 break;
5320 case 4:
5321 gen_helper_1i(mftlo, t0, 1);
5322 break;
5323 case 5:
5324 gen_helper_1i(mfthi, t0, 1);
5325 break;
5326 case 6:
5327 gen_helper_1i(mftacx, t0, 1);
5328 break;
5329 case 8:
5330 gen_helper_1i(mftlo, t0, 2);
5331 break;
5332 case 9:
5333 gen_helper_1i(mfthi, t0, 2);
5334 break;
5335 case 10:
5336 gen_helper_1i(mftacx, t0, 2);
5337 break;
5338 case 12:
5339 gen_helper_1i(mftlo, t0, 3);
5340 break;
5341 case 13:
5342 gen_helper_1i(mfthi, t0, 3);
5343 break;
5344 case 14:
5345 gen_helper_1i(mftacx, t0, 3);
5346 break;
5347 case 16:
5348 gen_helper_mftdsp(t0);
5349 break;
5350 default:
5351 goto die;
5353 break;
5354 /* Floating point (COP1). */
5355 case 2:
5356 /* XXX: For now we support only a single FPU context. */
5357 if (h == 0) {
5358 TCGv_i32 fp0 = tcg_temp_new_i32();
5360 gen_load_fpr32(fp0, rt);
5361 tcg_gen_ext_i32_tl(t0, fp0);
5362 tcg_temp_free_i32(fp0);
5363 } else {
5364 TCGv_i32 fp0 = tcg_temp_new_i32();
5366 gen_load_fpr32h(fp0, rt);
5367 tcg_gen_ext_i32_tl(t0, fp0);
5368 tcg_temp_free_i32(fp0);
5370 break;
5371 case 3:
5372 /* XXX: For now we support only a single FPU context. */
5373 gen_helper_1i(cfc1, t0, rt);
5374 break;
5375 /* COP2: Not implemented. */
5376 case 4:
5377 case 5:
5378 /* fall through */
5379 default:
5380 goto die;
5382 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5383 gen_store_gpr(t0, rd);
5384 tcg_temp_free(t0);
5385 return;
5387 die:
5388 tcg_temp_free(t0);
5389 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5390 generate_exception(ctx, EXCP_RI);
5393 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5394 int u, int sel, int h)
5396 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5397 TCGv t0 = tcg_temp_local_new();
5399 gen_load_gpr(t0, rt);
5400 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5401 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5402 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5403 /* NOP */ ;
5404 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5405 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5406 /* NOP */ ;
5407 else if (u == 0) {
5408 switch (rd) {
5409 case 2:
5410 switch (sel) {
5411 case 1:
5412 gen_helper_mttc0_tcstatus(t0);
5413 break;
5414 case 2:
5415 gen_helper_mttc0_tcbind(t0);
5416 break;
5417 case 3:
5418 gen_helper_mttc0_tcrestart(t0);
5419 break;
5420 case 4:
5421 gen_helper_mttc0_tchalt(t0);
5422 break;
5423 case 5:
5424 gen_helper_mttc0_tccontext(t0);
5425 break;
5426 case 6:
5427 gen_helper_mttc0_tcschedule(t0);
5428 break;
5429 case 7:
5430 gen_helper_mttc0_tcschefback(t0);
5431 break;
5432 default:
5433 gen_mtc0(env, ctx, t0, rd, sel);
5434 break;
5436 break;
5437 case 10:
5438 switch (sel) {
5439 case 0:
5440 gen_helper_mttc0_entryhi(t0);
5441 break;
5442 default:
5443 gen_mtc0(env, ctx, t0, rd, sel);
5444 break;
5446 case 12:
5447 switch (sel) {
5448 case 0:
5449 gen_helper_mttc0_status(t0);
5450 break;
5451 default:
5452 gen_mtc0(env, ctx, t0, rd, sel);
5453 break;
5455 case 23:
5456 switch (sel) {
5457 case 0:
5458 gen_helper_mttc0_debug(t0);
5459 break;
5460 default:
5461 gen_mtc0(env, ctx, t0, rd, sel);
5462 break;
5464 break;
5465 default:
5466 gen_mtc0(env, ctx, t0, rd, sel);
5468 } else switch (sel) {
5469 /* GPR registers. */
5470 case 0:
5471 gen_helper_1i(mttgpr, t0, rd);
5472 break;
5473 /* Auxiliary CPU registers */
5474 case 1:
5475 switch (rd) {
5476 case 0:
5477 gen_helper_1i(mttlo, t0, 0);
5478 break;
5479 case 1:
5480 gen_helper_1i(mtthi, t0, 0);
5481 break;
5482 case 2:
5483 gen_helper_1i(mttacx, t0, 0);
5484 break;
5485 case 4:
5486 gen_helper_1i(mttlo, t0, 1);
5487 break;
5488 case 5:
5489 gen_helper_1i(mtthi, t0, 1);
5490 break;
5491 case 6:
5492 gen_helper_1i(mttacx, t0, 1);
5493 break;
5494 case 8:
5495 gen_helper_1i(mttlo, t0, 2);
5496 break;
5497 case 9:
5498 gen_helper_1i(mtthi, t0, 2);
5499 break;
5500 case 10:
5501 gen_helper_1i(mttacx, t0, 2);
5502 break;
5503 case 12:
5504 gen_helper_1i(mttlo, t0, 3);
5505 break;
5506 case 13:
5507 gen_helper_1i(mtthi, t0, 3);
5508 break;
5509 case 14:
5510 gen_helper_1i(mttacx, t0, 3);
5511 break;
5512 case 16:
5513 gen_helper_mttdsp(t0);
5514 break;
5515 default:
5516 goto die;
5518 break;
5519 /* Floating point (COP1). */
5520 case 2:
5521 /* XXX: For now we support only a single FPU context. */
5522 if (h == 0) {
5523 TCGv_i32 fp0 = tcg_temp_new_i32();
5525 tcg_gen_trunc_tl_i32(fp0, t0);
5526 gen_store_fpr32(fp0, rd);
5527 tcg_temp_free_i32(fp0);
5528 } else {
5529 TCGv_i32 fp0 = tcg_temp_new_i32();
5531 tcg_gen_trunc_tl_i32(fp0, t0);
5532 gen_store_fpr32h(fp0, rd);
5533 tcg_temp_free_i32(fp0);
5535 break;
5536 case 3:
5537 /* XXX: For now we support only a single FPU context. */
5538 gen_helper_1i(ctc1, t0, rd);
5539 break;
5540 /* COP2: Not implemented. */
5541 case 4:
5542 case 5:
5543 /* fall through */
5544 default:
5545 goto die;
5547 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5548 tcg_temp_free(t0);
5549 return;
5551 die:
5552 tcg_temp_free(t0);
5553 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5554 generate_exception(ctx, EXCP_RI);
5557 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5559 const char *opn = "ldst";
5561 switch (opc) {
5562 case OPC_MFC0:
5563 if (rt == 0) {
5564 /* Treat as NOP. */
5565 return;
5567 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5568 opn = "mfc0";
5569 break;
5570 case OPC_MTC0:
5572 TCGv t0 = tcg_temp_new();
5574 gen_load_gpr(t0, rt);
5575 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5576 tcg_temp_free(t0);
5578 opn = "mtc0";
5579 break;
5580 #if defined(TARGET_MIPS64)
5581 case OPC_DMFC0:
5582 check_insn(env, ctx, ISA_MIPS3);
5583 if (rt == 0) {
5584 /* Treat as NOP. */
5585 return;
5587 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5588 opn = "dmfc0";
5589 break;
5590 case OPC_DMTC0:
5591 check_insn(env, ctx, ISA_MIPS3);
5593 TCGv t0 = tcg_temp_new();
5595 gen_load_gpr(t0, rt);
5596 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5597 tcg_temp_free(t0);
5599 opn = "dmtc0";
5600 break;
5601 #endif
5602 case OPC_MFTR:
5603 check_insn(env, ctx, ASE_MT);
5604 if (rd == 0) {
5605 /* Treat as NOP. */
5606 return;
5608 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5609 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5610 opn = "mftr";
5611 break;
5612 case OPC_MTTR:
5613 check_insn(env, ctx, ASE_MT);
5614 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5615 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5616 opn = "mttr";
5617 break;
5618 case OPC_TLBWI:
5619 opn = "tlbwi";
5620 if (!env->tlb->helper_tlbwi)
5621 goto die;
5622 gen_helper_tlbwi();
5623 break;
5624 case OPC_TLBWR:
5625 opn = "tlbwr";
5626 if (!env->tlb->helper_tlbwr)
5627 goto die;
5628 gen_helper_tlbwr();
5629 break;
5630 case OPC_TLBP:
5631 opn = "tlbp";
5632 if (!env->tlb->helper_tlbp)
5633 goto die;
5634 gen_helper_tlbp();
5635 break;
5636 case OPC_TLBR:
5637 opn = "tlbr";
5638 if (!env->tlb->helper_tlbr)
5639 goto die;
5640 gen_helper_tlbr();
5641 break;
5642 case OPC_ERET:
5643 opn = "eret";
5644 check_insn(env, ctx, ISA_MIPS2);
5645 gen_helper_eret();
5646 ctx->bstate = BS_EXCP;
5647 break;
5648 case OPC_DERET:
5649 opn = "deret";
5650 check_insn(env, ctx, ISA_MIPS32);
5651 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5652 MIPS_INVAL(opn);
5653 generate_exception(ctx, EXCP_RI);
5654 } else {
5655 gen_helper_deret();
5656 ctx->bstate = BS_EXCP;
5658 break;
5659 case OPC_WAIT:
5660 opn = "wait";
5661 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5662 /* If we get an exception, we want to restart at next instruction */
5663 ctx->pc += 4;
5664 save_cpu_state(ctx, 1);
5665 ctx->pc -= 4;
5666 gen_helper_wait();
5667 ctx->bstate = BS_EXCP;
5668 break;
5669 default:
5670 die:
5671 MIPS_INVAL(opn);
5672 generate_exception(ctx, EXCP_RI);
5673 return;
5675 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5677 #endif /* !CONFIG_USER_ONLY */
5679 /* CP1 Branches (before delay slot) */
5680 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5681 int32_t cc, int32_t offset)
5683 target_ulong btarget;
5684 const char *opn = "cp1 cond branch";
5685 TCGv_i32 t0 = tcg_temp_new_i32();
5687 if (cc != 0)
5688 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5690 btarget = ctx->pc + 4 + offset;
5692 switch (op) {
5693 case OPC_BC1F:
5694 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5695 tcg_gen_not_i32(t0, t0);
5696 tcg_gen_andi_i32(t0, t0, 1);
5697 tcg_gen_extu_i32_tl(bcond, t0);
5698 opn = "bc1f";
5699 goto not_likely;
5700 case OPC_BC1FL:
5701 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5702 tcg_gen_not_i32(t0, t0);
5703 tcg_gen_andi_i32(t0, t0, 1);
5704 tcg_gen_extu_i32_tl(bcond, t0);
5705 opn = "bc1fl";
5706 goto likely;
5707 case OPC_BC1T:
5708 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5709 tcg_gen_andi_i32(t0, t0, 1);
5710 tcg_gen_extu_i32_tl(bcond, t0);
5711 opn = "bc1t";
5712 goto not_likely;
5713 case OPC_BC1TL:
5714 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5715 tcg_gen_andi_i32(t0, t0, 1);
5716 tcg_gen_extu_i32_tl(bcond, t0);
5717 opn = "bc1tl";
5718 likely:
5719 ctx->hflags |= MIPS_HFLAG_BL;
5720 break;
5721 case OPC_BC1FANY2:
5723 TCGv_i32 t1 = tcg_temp_new_i32();
5724 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5725 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5726 tcg_gen_or_i32(t0, t0, t1);
5727 tcg_temp_free_i32(t1);
5728 tcg_gen_not_i32(t0, t0);
5729 tcg_gen_andi_i32(t0, t0, 1);
5730 tcg_gen_extu_i32_tl(bcond, t0);
5732 opn = "bc1any2f";
5733 goto not_likely;
5734 case OPC_BC1TANY2:
5736 TCGv_i32 t1 = tcg_temp_new_i32();
5737 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5738 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5739 tcg_gen_or_i32(t0, t0, t1);
5740 tcg_temp_free_i32(t1);
5741 tcg_gen_andi_i32(t0, t0, 1);
5742 tcg_gen_extu_i32_tl(bcond, t0);
5744 opn = "bc1any2t";
5745 goto not_likely;
5746 case OPC_BC1FANY4:
5748 TCGv_i32 t1 = tcg_temp_new_i32();
5749 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5750 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5751 tcg_gen_or_i32(t0, t0, t1);
5752 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5753 tcg_gen_or_i32(t0, t0, t1);
5754 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5755 tcg_gen_or_i32(t0, t0, t1);
5756 tcg_temp_free_i32(t1);
5757 tcg_gen_not_i32(t0, t0);
5758 tcg_gen_andi_i32(t0, t0, 1);
5759 tcg_gen_extu_i32_tl(bcond, t0);
5761 opn = "bc1any4f";
5762 goto not_likely;
5763 case OPC_BC1TANY4:
5765 TCGv_i32 t1 = tcg_temp_new_i32();
5766 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5767 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5768 tcg_gen_or_i32(t0, t0, t1);
5769 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5770 tcg_gen_or_i32(t0, t0, t1);
5771 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5772 tcg_gen_or_i32(t0, t0, t1);
5773 tcg_temp_free_i32(t1);
5774 tcg_gen_andi_i32(t0, t0, 1);
5775 tcg_gen_extu_i32_tl(bcond, t0);
5777 opn = "bc1any4t";
5778 not_likely:
5779 ctx->hflags |= MIPS_HFLAG_BC;
5780 break;
5781 default:
5782 MIPS_INVAL(opn);
5783 generate_exception (ctx, EXCP_RI);
5784 goto out;
5786 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5787 ctx->hflags, btarget);
5788 ctx->btarget = btarget;
5790 out:
5791 tcg_temp_free_i32(t0);
5794 /* Coprocessor 1 (FPU) */
5796 #define FOP(func, fmt) (((fmt) << 21) | (func))
5798 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5800 const char *opn = "cp1 move";
5801 TCGv t0 = tcg_temp_new();
5803 switch (opc) {
5804 case OPC_MFC1:
5806 TCGv_i32 fp0 = tcg_temp_new_i32();
5808 gen_load_fpr32(fp0, fs);
5809 tcg_gen_ext_i32_tl(t0, fp0);
5810 tcg_temp_free_i32(fp0);
5812 gen_store_gpr(t0, rt);
5813 opn = "mfc1";
5814 break;
5815 case OPC_MTC1:
5816 gen_load_gpr(t0, rt);
5818 TCGv_i32 fp0 = tcg_temp_new_i32();
5820 tcg_gen_trunc_tl_i32(fp0, t0);
5821 gen_store_fpr32(fp0, fs);
5822 tcg_temp_free_i32(fp0);
5824 opn = "mtc1";
5825 break;
5826 case OPC_CFC1:
5827 gen_helper_1i(cfc1, t0, fs);
5828 gen_store_gpr(t0, rt);
5829 opn = "cfc1";
5830 break;
5831 case OPC_CTC1:
5832 gen_load_gpr(t0, rt);
5833 gen_helper_1i(ctc1, t0, fs);
5834 opn = "ctc1";
5835 break;
5836 #if defined(TARGET_MIPS64)
5837 case OPC_DMFC1:
5838 gen_load_fpr64(ctx, t0, fs);
5839 gen_store_gpr(t0, rt);
5840 opn = "dmfc1";
5841 break;
5842 case OPC_DMTC1:
5843 gen_load_gpr(t0, rt);
5844 gen_store_fpr64(ctx, t0, fs);
5845 opn = "dmtc1";
5846 break;
5847 #endif
5848 case OPC_MFHC1:
5850 TCGv_i32 fp0 = tcg_temp_new_i32();
5852 gen_load_fpr32h(fp0, fs);
5853 tcg_gen_ext_i32_tl(t0, fp0);
5854 tcg_temp_free_i32(fp0);
5856 gen_store_gpr(t0, rt);
5857 opn = "mfhc1";
5858 break;
5859 case OPC_MTHC1:
5860 gen_load_gpr(t0, rt);
5862 TCGv_i32 fp0 = tcg_temp_new_i32();
5864 tcg_gen_trunc_tl_i32(fp0, t0);
5865 gen_store_fpr32h(fp0, fs);
5866 tcg_temp_free_i32(fp0);
5868 opn = "mthc1";
5869 break;
5870 default:
5871 MIPS_INVAL(opn);
5872 generate_exception (ctx, EXCP_RI);
5873 goto out;
5875 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5877 out:
5878 tcg_temp_free(t0);
5881 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5883 int l1;
5884 TCGCond cond;
5885 TCGv_i32 t0;
5887 if (rd == 0) {
5888 /* Treat as NOP. */
5889 return;
5892 if (tf)
5893 cond = TCG_COND_EQ;
5894 else
5895 cond = TCG_COND_NE;
5897 l1 = gen_new_label();
5898 t0 = tcg_temp_new_i32();
5899 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5900 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5901 tcg_temp_free_i32(t0);
5902 if (rs == 0) {
5903 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5904 } else {
5905 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5907 gen_set_label(l1);
5910 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5912 int cond;
5913 TCGv_i32 t0 = tcg_temp_new_i32();
5914 int l1 = gen_new_label();
5916 if (tf)
5917 cond = TCG_COND_EQ;
5918 else
5919 cond = TCG_COND_NE;
5921 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5922 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5923 gen_load_fpr32(t0, fs);
5924 gen_store_fpr32(t0, fd);
5925 gen_set_label(l1);
5926 tcg_temp_free_i32(t0);
5929 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5931 int cond;
5932 TCGv_i32 t0 = tcg_temp_new_i32();
5933 TCGv_i64 fp0;
5934 int l1 = gen_new_label();
5936 if (tf)
5937 cond = TCG_COND_EQ;
5938 else
5939 cond = TCG_COND_NE;
5941 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5942 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5943 tcg_temp_free_i32(t0);
5944 fp0 = tcg_temp_new_i64();
5945 gen_load_fpr64(ctx, fp0, fs);
5946 gen_store_fpr64(ctx, fp0, fd);
5947 tcg_temp_free_i64(fp0);
5948 gen_set_label(l1);
5951 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5953 int cond;
5954 TCGv_i32 t0 = tcg_temp_new_i32();
5955 int l1 = gen_new_label();
5956 int l2 = gen_new_label();
5958 if (tf)
5959 cond = TCG_COND_EQ;
5960 else
5961 cond = TCG_COND_NE;
5963 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5964 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5965 gen_load_fpr32(t0, fs);
5966 gen_store_fpr32(t0, fd);
5967 gen_set_label(l1);
5969 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc+1));
5970 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5971 gen_load_fpr32h(t0, fs);
5972 gen_store_fpr32h(t0, fd);
5973 tcg_temp_free_i32(t0);
5974 gen_set_label(l2);
5978 static void gen_farith (DisasContext *ctx, uint32_t op1,
5979 int ft, int fs, int fd, int cc)
5981 const char *opn = "farith";
5982 const char *condnames[] = {
5983 "c.f",
5984 "c.un",
5985 "c.eq",
5986 "c.ueq",
5987 "c.olt",
5988 "c.ult",
5989 "c.ole",
5990 "c.ule",
5991 "c.sf",
5992 "c.ngle",
5993 "c.seq",
5994 "c.ngl",
5995 "c.lt",
5996 "c.nge",
5997 "c.le",
5998 "c.ngt",
6000 const char *condnames_abs[] = {
6001 "cabs.f",
6002 "cabs.un",
6003 "cabs.eq",
6004 "cabs.ueq",
6005 "cabs.olt",
6006 "cabs.ult",
6007 "cabs.ole",
6008 "cabs.ule",
6009 "cabs.sf",
6010 "cabs.ngle",
6011 "cabs.seq",
6012 "cabs.ngl",
6013 "cabs.lt",
6014 "cabs.nge",
6015 "cabs.le",
6016 "cabs.ngt",
6018 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6019 uint32_t func = ctx->opcode & 0x3f;
6021 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
6022 case FOP(0, 16):
6024 TCGv_i32 fp0 = tcg_temp_new_i32();
6025 TCGv_i32 fp1 = tcg_temp_new_i32();
6027 gen_load_fpr32(fp0, fs);
6028 gen_load_fpr32(fp1, ft);
6029 gen_helper_float_add_s(fp0, fp0, fp1);
6030 tcg_temp_free_i32(fp1);
6031 gen_store_fpr32(fp0, fd);
6032 tcg_temp_free_i32(fp0);
6034 opn = "add.s";
6035 optype = BINOP;
6036 break;
6037 case FOP(1, 16):
6039 TCGv_i32 fp0 = tcg_temp_new_i32();
6040 TCGv_i32 fp1 = tcg_temp_new_i32();
6042 gen_load_fpr32(fp0, fs);
6043 gen_load_fpr32(fp1, ft);
6044 gen_helper_float_sub_s(fp0, fp0, fp1);
6045 tcg_temp_free_i32(fp1);
6046 gen_store_fpr32(fp0, fd);
6047 tcg_temp_free_i32(fp0);
6049 opn = "sub.s";
6050 optype = BINOP;
6051 break;
6052 case FOP(2, 16):
6054 TCGv_i32 fp0 = tcg_temp_new_i32();
6055 TCGv_i32 fp1 = tcg_temp_new_i32();
6057 gen_load_fpr32(fp0, fs);
6058 gen_load_fpr32(fp1, ft);
6059 gen_helper_float_mul_s(fp0, fp0, fp1);
6060 tcg_temp_free_i32(fp1);
6061 gen_store_fpr32(fp0, fd);
6062 tcg_temp_free_i32(fp0);
6064 opn = "mul.s";
6065 optype = BINOP;
6066 break;
6067 case FOP(3, 16):
6069 TCGv_i32 fp0 = tcg_temp_new_i32();
6070 TCGv_i32 fp1 = tcg_temp_new_i32();
6072 gen_load_fpr32(fp0, fs);
6073 gen_load_fpr32(fp1, ft);
6074 gen_helper_float_div_s(fp0, fp0, fp1);
6075 tcg_temp_free_i32(fp1);
6076 gen_store_fpr32(fp0, fd);
6077 tcg_temp_free_i32(fp0);
6079 opn = "div.s";
6080 optype = BINOP;
6081 break;
6082 case FOP(4, 16):
6084 TCGv_i32 fp0 = tcg_temp_new_i32();
6086 gen_load_fpr32(fp0, fs);
6087 gen_helper_float_sqrt_s(fp0, fp0);
6088 gen_store_fpr32(fp0, fd);
6089 tcg_temp_free_i32(fp0);
6091 opn = "sqrt.s";
6092 break;
6093 case FOP(5, 16):
6095 TCGv_i32 fp0 = tcg_temp_new_i32();
6097 gen_load_fpr32(fp0, fs);
6098 gen_helper_float_abs_s(fp0, fp0);
6099 gen_store_fpr32(fp0, fd);
6100 tcg_temp_free_i32(fp0);
6102 opn = "abs.s";
6103 break;
6104 case FOP(6, 16):
6106 TCGv_i32 fp0 = tcg_temp_new_i32();
6108 gen_load_fpr32(fp0, fs);
6109 gen_store_fpr32(fp0, fd);
6110 tcg_temp_free_i32(fp0);
6112 opn = "mov.s";
6113 break;
6114 case FOP(7, 16):
6116 TCGv_i32 fp0 = tcg_temp_new_i32();
6118 gen_load_fpr32(fp0, fs);
6119 gen_helper_float_chs_s(fp0, fp0);
6120 gen_store_fpr32(fp0, fd);
6121 tcg_temp_free_i32(fp0);
6123 opn = "neg.s";
6124 break;
6125 case FOP(8, 16):
6126 check_cp1_64bitmode(ctx);
6128 TCGv_i32 fp32 = tcg_temp_new_i32();
6129 TCGv_i64 fp64 = tcg_temp_new_i64();
6131 gen_load_fpr32(fp32, fs);
6132 gen_helper_float_roundl_s(fp64, fp32);
6133 tcg_temp_free_i32(fp32);
6134 gen_store_fpr64(ctx, fp64, fd);
6135 tcg_temp_free_i64(fp64);
6137 opn = "round.l.s";
6138 break;
6139 case FOP(9, 16):
6140 check_cp1_64bitmode(ctx);
6142 TCGv_i32 fp32 = tcg_temp_new_i32();
6143 TCGv_i64 fp64 = tcg_temp_new_i64();
6145 gen_load_fpr32(fp32, fs);
6146 gen_helper_float_truncl_s(fp64, fp32);
6147 tcg_temp_free_i32(fp32);
6148 gen_store_fpr64(ctx, fp64, fd);
6149 tcg_temp_free_i64(fp64);
6151 opn = "trunc.l.s";
6152 break;
6153 case FOP(10, 16):
6154 check_cp1_64bitmode(ctx);
6156 TCGv_i32 fp32 = tcg_temp_new_i32();
6157 TCGv_i64 fp64 = tcg_temp_new_i64();
6159 gen_load_fpr32(fp32, fs);
6160 gen_helper_float_ceill_s(fp64, fp32);
6161 tcg_temp_free_i32(fp32);
6162 gen_store_fpr64(ctx, fp64, fd);
6163 tcg_temp_free_i64(fp64);
6165 opn = "ceil.l.s";
6166 break;
6167 case FOP(11, 16):
6168 check_cp1_64bitmode(ctx);
6170 TCGv_i32 fp32 = tcg_temp_new_i32();
6171 TCGv_i64 fp64 = tcg_temp_new_i64();
6173 gen_load_fpr32(fp32, fs);
6174 gen_helper_float_floorl_s(fp64, fp32);
6175 tcg_temp_free_i32(fp32);
6176 gen_store_fpr64(ctx, fp64, fd);
6177 tcg_temp_free_i64(fp64);
6179 opn = "floor.l.s";
6180 break;
6181 case FOP(12, 16):
6183 TCGv_i32 fp0 = tcg_temp_new_i32();
6185 gen_load_fpr32(fp0, fs);
6186 gen_helper_float_roundw_s(fp0, fp0);
6187 gen_store_fpr32(fp0, fd);
6188 tcg_temp_free_i32(fp0);
6190 opn = "round.w.s";
6191 break;
6192 case FOP(13, 16):
6194 TCGv_i32 fp0 = tcg_temp_new_i32();
6196 gen_load_fpr32(fp0, fs);
6197 gen_helper_float_truncw_s(fp0, fp0);
6198 gen_store_fpr32(fp0, fd);
6199 tcg_temp_free_i32(fp0);
6201 opn = "trunc.w.s";
6202 break;
6203 case FOP(14, 16):
6205 TCGv_i32 fp0 = tcg_temp_new_i32();
6207 gen_load_fpr32(fp0, fs);
6208 gen_helper_float_ceilw_s(fp0, fp0);
6209 gen_store_fpr32(fp0, fd);
6210 tcg_temp_free_i32(fp0);
6212 opn = "ceil.w.s";
6213 break;
6214 case FOP(15, 16):
6216 TCGv_i32 fp0 = tcg_temp_new_i32();
6218 gen_load_fpr32(fp0, fs);
6219 gen_helper_float_floorw_s(fp0, fp0);
6220 gen_store_fpr32(fp0, fd);
6221 tcg_temp_free_i32(fp0);
6223 opn = "floor.w.s";
6224 break;
6225 case FOP(17, 16):
6226 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6227 opn = "movcf.s";
6228 break;
6229 case FOP(18, 16):
6231 int l1 = gen_new_label();
6232 TCGv_i32 fp0;
6234 if (ft != 0) {
6235 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6237 fp0 = tcg_temp_new_i32();
6238 gen_load_fpr32(fp0, fs);
6239 gen_store_fpr32(fp0, fd);
6240 tcg_temp_free_i32(fp0);
6241 gen_set_label(l1);
6243 opn = "movz.s";
6244 break;
6245 case FOP(19, 16):
6247 int l1 = gen_new_label();
6248 TCGv_i32 fp0;
6250 if (ft != 0) {
6251 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6252 fp0 = tcg_temp_new_i32();
6253 gen_load_fpr32(fp0, fs);
6254 gen_store_fpr32(fp0, fd);
6255 tcg_temp_free_i32(fp0);
6256 gen_set_label(l1);
6259 opn = "movn.s";
6260 break;
6261 case FOP(21, 16):
6262 check_cop1x(ctx);
6264 TCGv_i32 fp0 = tcg_temp_new_i32();
6266 gen_load_fpr32(fp0, fs);
6267 gen_helper_float_recip_s(fp0, fp0);
6268 gen_store_fpr32(fp0, fd);
6269 tcg_temp_free_i32(fp0);
6271 opn = "recip.s";
6272 break;
6273 case FOP(22, 16):
6274 check_cop1x(ctx);
6276 TCGv_i32 fp0 = tcg_temp_new_i32();
6278 gen_load_fpr32(fp0, fs);
6279 gen_helper_float_rsqrt_s(fp0, fp0);
6280 gen_store_fpr32(fp0, fd);
6281 tcg_temp_free_i32(fp0);
6283 opn = "rsqrt.s";
6284 break;
6285 case FOP(28, 16):
6286 check_cp1_64bitmode(ctx);
6288 TCGv_i32 fp0 = tcg_temp_new_i32();
6289 TCGv_i32 fp1 = tcg_temp_new_i32();
6291 gen_load_fpr32(fp0, fs);
6292 gen_load_fpr32(fp1, fd);
6293 gen_helper_float_recip2_s(fp0, fp0, fp1);
6294 tcg_temp_free_i32(fp1);
6295 gen_store_fpr32(fp0, fd);
6296 tcg_temp_free_i32(fp0);
6298 opn = "recip2.s";
6299 break;
6300 case FOP(29, 16):
6301 check_cp1_64bitmode(ctx);
6303 TCGv_i32 fp0 = tcg_temp_new_i32();
6305 gen_load_fpr32(fp0, fs);
6306 gen_helper_float_recip1_s(fp0, fp0);
6307 gen_store_fpr32(fp0, fd);
6308 tcg_temp_free_i32(fp0);
6310 opn = "recip1.s";
6311 break;
6312 case FOP(30, 16):
6313 check_cp1_64bitmode(ctx);
6315 TCGv_i32 fp0 = tcg_temp_new_i32();
6317 gen_load_fpr32(fp0, fs);
6318 gen_helper_float_rsqrt1_s(fp0, fp0);
6319 gen_store_fpr32(fp0, fd);
6320 tcg_temp_free_i32(fp0);
6322 opn = "rsqrt1.s";
6323 break;
6324 case FOP(31, 16):
6325 check_cp1_64bitmode(ctx);
6327 TCGv_i32 fp0 = tcg_temp_new_i32();
6328 TCGv_i32 fp1 = tcg_temp_new_i32();
6330 gen_load_fpr32(fp0, fs);
6331 gen_load_fpr32(fp1, ft);
6332 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6333 tcg_temp_free_i32(fp1);
6334 gen_store_fpr32(fp0, fd);
6335 tcg_temp_free_i32(fp0);
6337 opn = "rsqrt2.s";
6338 break;
6339 case FOP(33, 16):
6340 check_cp1_registers(ctx, fd);
6342 TCGv_i32 fp32 = tcg_temp_new_i32();
6343 TCGv_i64 fp64 = tcg_temp_new_i64();
6345 gen_load_fpr32(fp32, fs);
6346 gen_helper_float_cvtd_s(fp64, fp32);
6347 tcg_temp_free_i32(fp32);
6348 gen_store_fpr64(ctx, fp64, fd);
6349 tcg_temp_free_i64(fp64);
6351 opn = "cvt.d.s";
6352 break;
6353 case FOP(36, 16):
6355 TCGv_i32 fp0 = tcg_temp_new_i32();
6357 gen_load_fpr32(fp0, fs);
6358 gen_helper_float_cvtw_s(fp0, fp0);
6359 gen_store_fpr32(fp0, fd);
6360 tcg_temp_free_i32(fp0);
6362 opn = "cvt.w.s";
6363 break;
6364 case FOP(37, 16):
6365 check_cp1_64bitmode(ctx);
6367 TCGv_i32 fp32 = tcg_temp_new_i32();
6368 TCGv_i64 fp64 = tcg_temp_new_i64();
6370 gen_load_fpr32(fp32, fs);
6371 gen_helper_float_cvtl_s(fp64, fp32);
6372 tcg_temp_free_i32(fp32);
6373 gen_store_fpr64(ctx, fp64, fd);
6374 tcg_temp_free_i64(fp64);
6376 opn = "cvt.l.s";
6377 break;
6378 case FOP(38, 16):
6379 check_cp1_64bitmode(ctx);
6381 TCGv_i64 fp64 = tcg_temp_new_i64();
6382 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6383 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6385 gen_load_fpr32(fp32_0, fs);
6386 gen_load_fpr32(fp32_1, ft);
6387 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6388 tcg_temp_free_i32(fp32_1);
6389 tcg_temp_free_i32(fp32_0);
6390 gen_store_fpr64(ctx, fp64, fd);
6391 tcg_temp_free_i64(fp64);
6393 opn = "cvt.ps.s";
6394 break;
6395 case FOP(48, 16):
6396 case FOP(49, 16):
6397 case FOP(50, 16):
6398 case FOP(51, 16):
6399 case FOP(52, 16):
6400 case FOP(53, 16):
6401 case FOP(54, 16):
6402 case FOP(55, 16):
6403 case FOP(56, 16):
6404 case FOP(57, 16):
6405 case FOP(58, 16):
6406 case FOP(59, 16):
6407 case FOP(60, 16):
6408 case FOP(61, 16):
6409 case FOP(62, 16):
6410 case FOP(63, 16):
6412 TCGv_i32 fp0 = tcg_temp_new_i32();
6413 TCGv_i32 fp1 = tcg_temp_new_i32();
6415 gen_load_fpr32(fp0, fs);
6416 gen_load_fpr32(fp1, ft);
6417 if (ctx->opcode & (1 << 6)) {
6418 check_cop1x(ctx);
6419 gen_cmpabs_s(func-48, fp0, fp1, cc);
6420 opn = condnames_abs[func-48];
6421 } else {
6422 gen_cmp_s(func-48, fp0, fp1, cc);
6423 opn = condnames[func-48];
6425 tcg_temp_free_i32(fp0);
6426 tcg_temp_free_i32(fp1);
6428 break;
6429 case FOP(0, 17):
6430 check_cp1_registers(ctx, fs | ft | fd);
6432 TCGv_i64 fp0 = tcg_temp_new_i64();
6433 TCGv_i64 fp1 = tcg_temp_new_i64();
6435 gen_load_fpr64(ctx, fp0, fs);
6436 gen_load_fpr64(ctx, fp1, ft);
6437 gen_helper_float_add_d(fp0, fp0, fp1);
6438 tcg_temp_free_i64(fp1);
6439 gen_store_fpr64(ctx, fp0, fd);
6440 tcg_temp_free_i64(fp0);
6442 opn = "add.d";
6443 optype = BINOP;
6444 break;
6445 case FOP(1, 17):
6446 check_cp1_registers(ctx, fs | ft | fd);
6448 TCGv_i64 fp0 = tcg_temp_new_i64();
6449 TCGv_i64 fp1 = tcg_temp_new_i64();
6451 gen_load_fpr64(ctx, fp0, fs);
6452 gen_load_fpr64(ctx, fp1, ft);
6453 gen_helper_float_sub_d(fp0, fp0, fp1);
6454 tcg_temp_free_i64(fp1);
6455 gen_store_fpr64(ctx, fp0, fd);
6456 tcg_temp_free_i64(fp0);
6458 opn = "sub.d";
6459 optype = BINOP;
6460 break;
6461 case FOP(2, 17):
6462 check_cp1_registers(ctx, fs | ft | fd);
6464 TCGv_i64 fp0 = tcg_temp_new_i64();
6465 TCGv_i64 fp1 = tcg_temp_new_i64();
6467 gen_load_fpr64(ctx, fp0, fs);
6468 gen_load_fpr64(ctx, fp1, ft);
6469 gen_helper_float_mul_d(fp0, fp0, fp1);
6470 tcg_temp_free_i64(fp1);
6471 gen_store_fpr64(ctx, fp0, fd);
6472 tcg_temp_free_i64(fp0);
6474 opn = "mul.d";
6475 optype = BINOP;
6476 break;
6477 case FOP(3, 17):
6478 check_cp1_registers(ctx, fs | ft | fd);
6480 TCGv_i64 fp0 = tcg_temp_new_i64();
6481 TCGv_i64 fp1 = tcg_temp_new_i64();
6483 gen_load_fpr64(ctx, fp0, fs);
6484 gen_load_fpr64(ctx, fp1, ft);
6485 gen_helper_float_div_d(fp0, fp0, fp1);
6486 tcg_temp_free_i64(fp1);
6487 gen_store_fpr64(ctx, fp0, fd);
6488 tcg_temp_free_i64(fp0);
6490 opn = "div.d";
6491 optype = BINOP;
6492 break;
6493 case FOP(4, 17):
6494 check_cp1_registers(ctx, fs | fd);
6496 TCGv_i64 fp0 = tcg_temp_new_i64();
6498 gen_load_fpr64(ctx, fp0, fs);
6499 gen_helper_float_sqrt_d(fp0, fp0);
6500 gen_store_fpr64(ctx, fp0, fd);
6501 tcg_temp_free_i64(fp0);
6503 opn = "sqrt.d";
6504 break;
6505 case FOP(5, 17):
6506 check_cp1_registers(ctx, fs | fd);
6508 TCGv_i64 fp0 = tcg_temp_new_i64();
6510 gen_load_fpr64(ctx, fp0, fs);
6511 gen_helper_float_abs_d(fp0, fp0);
6512 gen_store_fpr64(ctx, fp0, fd);
6513 tcg_temp_free_i64(fp0);
6515 opn = "abs.d";
6516 break;
6517 case FOP(6, 17):
6518 check_cp1_registers(ctx, fs | fd);
6520 TCGv_i64 fp0 = tcg_temp_new_i64();
6522 gen_load_fpr64(ctx, fp0, fs);
6523 gen_store_fpr64(ctx, fp0, fd);
6524 tcg_temp_free_i64(fp0);
6526 opn = "mov.d";
6527 break;
6528 case FOP(7, 17):
6529 check_cp1_registers(ctx, fs | fd);
6531 TCGv_i64 fp0 = tcg_temp_new_i64();
6533 gen_load_fpr64(ctx, fp0, fs);
6534 gen_helper_float_chs_d(fp0, fp0);
6535 gen_store_fpr64(ctx, fp0, fd);
6536 tcg_temp_free_i64(fp0);
6538 opn = "neg.d";
6539 break;
6540 case FOP(8, 17):
6541 check_cp1_64bitmode(ctx);
6543 TCGv_i64 fp0 = tcg_temp_new_i64();
6545 gen_load_fpr64(ctx, fp0, fs);
6546 gen_helper_float_roundl_d(fp0, fp0);
6547 gen_store_fpr64(ctx, fp0, fd);
6548 tcg_temp_free_i64(fp0);
6550 opn = "round.l.d";
6551 break;
6552 case FOP(9, 17):
6553 check_cp1_64bitmode(ctx);
6555 TCGv_i64 fp0 = tcg_temp_new_i64();
6557 gen_load_fpr64(ctx, fp0, fs);
6558 gen_helper_float_truncl_d(fp0, fp0);
6559 gen_store_fpr64(ctx, fp0, fd);
6560 tcg_temp_free_i64(fp0);
6562 opn = "trunc.l.d";
6563 break;
6564 case FOP(10, 17):
6565 check_cp1_64bitmode(ctx);
6567 TCGv_i64 fp0 = tcg_temp_new_i64();
6569 gen_load_fpr64(ctx, fp0, fs);
6570 gen_helper_float_ceill_d(fp0, fp0);
6571 gen_store_fpr64(ctx, fp0, fd);
6572 tcg_temp_free_i64(fp0);
6574 opn = "ceil.l.d";
6575 break;
6576 case FOP(11, 17):
6577 check_cp1_64bitmode(ctx);
6579 TCGv_i64 fp0 = tcg_temp_new_i64();
6581 gen_load_fpr64(ctx, fp0, fs);
6582 gen_helper_float_floorl_d(fp0, fp0);
6583 gen_store_fpr64(ctx, fp0, fd);
6584 tcg_temp_free_i64(fp0);
6586 opn = "floor.l.d";
6587 break;
6588 case FOP(12, 17):
6589 check_cp1_registers(ctx, fs);
6591 TCGv_i32 fp32 = tcg_temp_new_i32();
6592 TCGv_i64 fp64 = tcg_temp_new_i64();
6594 gen_load_fpr64(ctx, fp64, fs);
6595 gen_helper_float_roundw_d(fp32, fp64);
6596 tcg_temp_free_i64(fp64);
6597 gen_store_fpr32(fp32, fd);
6598 tcg_temp_free_i32(fp32);
6600 opn = "round.w.d";
6601 break;
6602 case FOP(13, 17):
6603 check_cp1_registers(ctx, fs);
6605 TCGv_i32 fp32 = tcg_temp_new_i32();
6606 TCGv_i64 fp64 = tcg_temp_new_i64();
6608 gen_load_fpr64(ctx, fp64, fs);
6609 gen_helper_float_truncw_d(fp32, fp64);
6610 tcg_temp_free_i64(fp64);
6611 gen_store_fpr32(fp32, fd);
6612 tcg_temp_free_i32(fp32);
6614 opn = "trunc.w.d";
6615 break;
6616 case FOP(14, 17):
6617 check_cp1_registers(ctx, fs);
6619 TCGv_i32 fp32 = tcg_temp_new_i32();
6620 TCGv_i64 fp64 = tcg_temp_new_i64();
6622 gen_load_fpr64(ctx, fp64, fs);
6623 gen_helper_float_ceilw_d(fp32, fp64);
6624 tcg_temp_free_i64(fp64);
6625 gen_store_fpr32(fp32, fd);
6626 tcg_temp_free_i32(fp32);
6628 opn = "ceil.w.d";
6629 break;
6630 case FOP(15, 17):
6631 check_cp1_registers(ctx, fs);
6633 TCGv_i32 fp32 = tcg_temp_new_i32();
6634 TCGv_i64 fp64 = tcg_temp_new_i64();
6636 gen_load_fpr64(ctx, fp64, fs);
6637 gen_helper_float_floorw_d(fp32, fp64);
6638 tcg_temp_free_i64(fp64);
6639 gen_store_fpr32(fp32, fd);
6640 tcg_temp_free_i32(fp32);
6642 opn = "floor.w.d";
6643 break;
6644 case FOP(17, 17):
6645 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6646 opn = "movcf.d";
6647 break;
6648 case FOP(18, 17):
6650 int l1 = gen_new_label();
6651 TCGv_i64 fp0;
6653 if (ft != 0) {
6654 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6656 fp0 = tcg_temp_new_i64();
6657 gen_load_fpr64(ctx, fp0, fs);
6658 gen_store_fpr64(ctx, fp0, fd);
6659 tcg_temp_free_i64(fp0);
6660 gen_set_label(l1);
6662 opn = "movz.d";
6663 break;
6664 case FOP(19, 17):
6666 int l1 = gen_new_label();
6667 TCGv_i64 fp0;
6669 if (ft != 0) {
6670 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6671 fp0 = tcg_temp_new_i64();
6672 gen_load_fpr64(ctx, fp0, fs);
6673 gen_store_fpr64(ctx, fp0, fd);
6674 tcg_temp_free_i64(fp0);
6675 gen_set_label(l1);
6678 opn = "movn.d";
6679 break;
6680 case FOP(21, 17):
6681 check_cp1_64bitmode(ctx);
6683 TCGv_i64 fp0 = tcg_temp_new_i64();
6685 gen_load_fpr64(ctx, fp0, fs);
6686 gen_helper_float_recip_d(fp0, fp0);
6687 gen_store_fpr64(ctx, fp0, fd);
6688 tcg_temp_free_i64(fp0);
6690 opn = "recip.d";
6691 break;
6692 case FOP(22, 17):
6693 check_cp1_64bitmode(ctx);
6695 TCGv_i64 fp0 = tcg_temp_new_i64();
6697 gen_load_fpr64(ctx, fp0, fs);
6698 gen_helper_float_rsqrt_d(fp0, fp0);
6699 gen_store_fpr64(ctx, fp0, fd);
6700 tcg_temp_free_i64(fp0);
6702 opn = "rsqrt.d";
6703 break;
6704 case FOP(28, 17):
6705 check_cp1_64bitmode(ctx);
6707 TCGv_i64 fp0 = tcg_temp_new_i64();
6708 TCGv_i64 fp1 = tcg_temp_new_i64();
6710 gen_load_fpr64(ctx, fp0, fs);
6711 gen_load_fpr64(ctx, fp1, ft);
6712 gen_helper_float_recip2_d(fp0, fp0, fp1);
6713 tcg_temp_free_i64(fp1);
6714 gen_store_fpr64(ctx, fp0, fd);
6715 tcg_temp_free_i64(fp0);
6717 opn = "recip2.d";
6718 break;
6719 case FOP(29, 17):
6720 check_cp1_64bitmode(ctx);
6722 TCGv_i64 fp0 = tcg_temp_new_i64();
6724 gen_load_fpr64(ctx, fp0, fs);
6725 gen_helper_float_recip1_d(fp0, fp0);
6726 gen_store_fpr64(ctx, fp0, fd);
6727 tcg_temp_free_i64(fp0);
6729 opn = "recip1.d";
6730 break;
6731 case FOP(30, 17):
6732 check_cp1_64bitmode(ctx);
6734 TCGv_i64 fp0 = tcg_temp_new_i64();
6736 gen_load_fpr64(ctx, fp0, fs);
6737 gen_helper_float_rsqrt1_d(fp0, fp0);
6738 gen_store_fpr64(ctx, fp0, fd);
6739 tcg_temp_free_i64(fp0);
6741 opn = "rsqrt1.d";
6742 break;
6743 case FOP(31, 17):
6744 check_cp1_64bitmode(ctx);
6746 TCGv_i64 fp0 = tcg_temp_new_i64();
6747 TCGv_i64 fp1 = tcg_temp_new_i64();
6749 gen_load_fpr64(ctx, fp0, fs);
6750 gen_load_fpr64(ctx, fp1, ft);
6751 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6752 tcg_temp_free_i64(fp1);
6753 gen_store_fpr64(ctx, fp0, fd);
6754 tcg_temp_free_i64(fp0);
6756 opn = "rsqrt2.d";
6757 break;
6758 case FOP(48, 17):
6759 case FOP(49, 17):
6760 case FOP(50, 17):
6761 case FOP(51, 17):
6762 case FOP(52, 17):
6763 case FOP(53, 17):
6764 case FOP(54, 17):
6765 case FOP(55, 17):
6766 case FOP(56, 17):
6767 case FOP(57, 17):
6768 case FOP(58, 17):
6769 case FOP(59, 17):
6770 case FOP(60, 17):
6771 case FOP(61, 17):
6772 case FOP(62, 17):
6773 case FOP(63, 17):
6775 TCGv_i64 fp0 = tcg_temp_new_i64();
6776 TCGv_i64 fp1 = tcg_temp_new_i64();
6778 gen_load_fpr64(ctx, fp0, fs);
6779 gen_load_fpr64(ctx, fp1, ft);
6780 if (ctx->opcode & (1 << 6)) {
6781 check_cop1x(ctx);
6782 check_cp1_registers(ctx, fs | ft);
6783 gen_cmpabs_d(func-48, fp0, fp1, cc);
6784 opn = condnames_abs[func-48];
6785 } else {
6786 check_cp1_registers(ctx, fs | ft);
6787 gen_cmp_d(func-48, fp0, fp1, cc);
6788 opn = condnames[func-48];
6790 tcg_temp_free_i64(fp0);
6791 tcg_temp_free_i64(fp1);
6793 break;
6794 case FOP(32, 17):
6795 check_cp1_registers(ctx, fs);
6797 TCGv_i32 fp32 = tcg_temp_new_i32();
6798 TCGv_i64 fp64 = tcg_temp_new_i64();
6800 gen_load_fpr64(ctx, fp64, fs);
6801 gen_helper_float_cvts_d(fp32, fp64);
6802 tcg_temp_free_i64(fp64);
6803 gen_store_fpr32(fp32, fd);
6804 tcg_temp_free_i32(fp32);
6806 opn = "cvt.s.d";
6807 break;
6808 case FOP(36, 17):
6809 check_cp1_registers(ctx, fs);
6811 TCGv_i32 fp32 = tcg_temp_new_i32();
6812 TCGv_i64 fp64 = tcg_temp_new_i64();
6814 gen_load_fpr64(ctx, fp64, fs);
6815 gen_helper_float_cvtw_d(fp32, fp64);
6816 tcg_temp_free_i64(fp64);
6817 gen_store_fpr32(fp32, fd);
6818 tcg_temp_free_i32(fp32);
6820 opn = "cvt.w.d";
6821 break;
6822 case FOP(37, 17):
6823 check_cp1_64bitmode(ctx);
6825 TCGv_i64 fp0 = tcg_temp_new_i64();
6827 gen_load_fpr64(ctx, fp0, fs);
6828 gen_helper_float_cvtl_d(fp0, fp0);
6829 gen_store_fpr64(ctx, fp0, fd);
6830 tcg_temp_free_i64(fp0);
6832 opn = "cvt.l.d";
6833 break;
6834 case FOP(32, 20):
6836 TCGv_i32 fp0 = tcg_temp_new_i32();
6838 gen_load_fpr32(fp0, fs);
6839 gen_helper_float_cvts_w(fp0, fp0);
6840 gen_store_fpr32(fp0, fd);
6841 tcg_temp_free_i32(fp0);
6843 opn = "cvt.s.w";
6844 break;
6845 case FOP(33, 20):
6846 check_cp1_registers(ctx, fd);
6848 TCGv_i32 fp32 = tcg_temp_new_i32();
6849 TCGv_i64 fp64 = tcg_temp_new_i64();
6851 gen_load_fpr32(fp32, fs);
6852 gen_helper_float_cvtd_w(fp64, fp32);
6853 tcg_temp_free_i32(fp32);
6854 gen_store_fpr64(ctx, fp64, fd);
6855 tcg_temp_free_i64(fp64);
6857 opn = "cvt.d.w";
6858 break;
6859 case FOP(32, 21):
6860 check_cp1_64bitmode(ctx);
6862 TCGv_i32 fp32 = tcg_temp_new_i32();
6863 TCGv_i64 fp64 = tcg_temp_new_i64();
6865 gen_load_fpr64(ctx, fp64, fs);
6866 gen_helper_float_cvts_l(fp32, fp64);
6867 tcg_temp_free_i64(fp64);
6868 gen_store_fpr32(fp32, fd);
6869 tcg_temp_free_i32(fp32);
6871 opn = "cvt.s.l";
6872 break;
6873 case FOP(33, 21):
6874 check_cp1_64bitmode(ctx);
6876 TCGv_i64 fp0 = tcg_temp_new_i64();
6878 gen_load_fpr64(ctx, fp0, fs);
6879 gen_helper_float_cvtd_l(fp0, fp0);
6880 gen_store_fpr64(ctx, fp0, fd);
6881 tcg_temp_free_i64(fp0);
6883 opn = "cvt.d.l";
6884 break;
6885 case FOP(38, 20):
6886 check_cp1_64bitmode(ctx);
6888 TCGv_i64 fp0 = tcg_temp_new_i64();
6890 gen_load_fpr64(ctx, fp0, fs);
6891 gen_helper_float_cvtps_pw(fp0, fp0);
6892 gen_store_fpr64(ctx, fp0, fd);
6893 tcg_temp_free_i64(fp0);
6895 opn = "cvt.ps.pw";
6896 break;
6897 case FOP(0, 22):
6898 check_cp1_64bitmode(ctx);
6900 TCGv_i64 fp0 = tcg_temp_new_i64();
6901 TCGv_i64 fp1 = tcg_temp_new_i64();
6903 gen_load_fpr64(ctx, fp0, fs);
6904 gen_load_fpr64(ctx, fp1, ft);
6905 gen_helper_float_add_ps(fp0, fp0, fp1);
6906 tcg_temp_free_i64(fp1);
6907 gen_store_fpr64(ctx, fp0, fd);
6908 tcg_temp_free_i64(fp0);
6910 opn = "add.ps";
6911 break;
6912 case FOP(1, 22):
6913 check_cp1_64bitmode(ctx);
6915 TCGv_i64 fp0 = tcg_temp_new_i64();
6916 TCGv_i64 fp1 = tcg_temp_new_i64();
6918 gen_load_fpr64(ctx, fp0, fs);
6919 gen_load_fpr64(ctx, fp1, ft);
6920 gen_helper_float_sub_ps(fp0, fp0, fp1);
6921 tcg_temp_free_i64(fp1);
6922 gen_store_fpr64(ctx, fp0, fd);
6923 tcg_temp_free_i64(fp0);
6925 opn = "sub.ps";
6926 break;
6927 case FOP(2, 22):
6928 check_cp1_64bitmode(ctx);
6930 TCGv_i64 fp0 = tcg_temp_new_i64();
6931 TCGv_i64 fp1 = tcg_temp_new_i64();
6933 gen_load_fpr64(ctx, fp0, fs);
6934 gen_load_fpr64(ctx, fp1, ft);
6935 gen_helper_float_mul_ps(fp0, fp0, fp1);
6936 tcg_temp_free_i64(fp1);
6937 gen_store_fpr64(ctx, fp0, fd);
6938 tcg_temp_free_i64(fp0);
6940 opn = "mul.ps";
6941 break;
6942 case FOP(5, 22):
6943 check_cp1_64bitmode(ctx);
6945 TCGv_i64 fp0 = tcg_temp_new_i64();
6947 gen_load_fpr64(ctx, fp0, fs);
6948 gen_helper_float_abs_ps(fp0, fp0);
6949 gen_store_fpr64(ctx, fp0, fd);
6950 tcg_temp_free_i64(fp0);
6952 opn = "abs.ps";
6953 break;
6954 case FOP(6, 22):
6955 check_cp1_64bitmode(ctx);
6957 TCGv_i64 fp0 = tcg_temp_new_i64();
6959 gen_load_fpr64(ctx, fp0, fs);
6960 gen_store_fpr64(ctx, fp0, fd);
6961 tcg_temp_free_i64(fp0);
6963 opn = "mov.ps";
6964 break;
6965 case FOP(7, 22):
6966 check_cp1_64bitmode(ctx);
6968 TCGv_i64 fp0 = tcg_temp_new_i64();
6970 gen_load_fpr64(ctx, fp0, fs);
6971 gen_helper_float_chs_ps(fp0, fp0);
6972 gen_store_fpr64(ctx, fp0, fd);
6973 tcg_temp_free_i64(fp0);
6975 opn = "neg.ps";
6976 break;
6977 case FOP(17, 22):
6978 check_cp1_64bitmode(ctx);
6979 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6980 opn = "movcf.ps";
6981 break;
6982 case FOP(18, 22):
6983 check_cp1_64bitmode(ctx);
6985 int l1 = gen_new_label();
6986 TCGv_i64 fp0;
6988 if (ft != 0)
6989 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6990 fp0 = tcg_temp_new_i64();
6991 gen_load_fpr64(ctx, fp0, fs);
6992 gen_store_fpr64(ctx, fp0, fd);
6993 tcg_temp_free_i64(fp0);
6994 gen_set_label(l1);
6996 opn = "movz.ps";
6997 break;
6998 case FOP(19, 22):
6999 check_cp1_64bitmode(ctx);
7001 int l1 = gen_new_label();
7002 TCGv_i64 fp0;
7004 if (ft != 0) {
7005 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7006 fp0 = tcg_temp_new_i64();
7007 gen_load_fpr64(ctx, fp0, fs);
7008 gen_store_fpr64(ctx, fp0, fd);
7009 tcg_temp_free_i64(fp0);
7010 gen_set_label(l1);
7013 opn = "movn.ps";
7014 break;
7015 case FOP(24, 22):
7016 check_cp1_64bitmode(ctx);
7018 TCGv_i64 fp0 = tcg_temp_new_i64();
7019 TCGv_i64 fp1 = tcg_temp_new_i64();
7021 gen_load_fpr64(ctx, fp0, ft);
7022 gen_load_fpr64(ctx, fp1, fs);
7023 gen_helper_float_addr_ps(fp0, fp0, fp1);
7024 tcg_temp_free_i64(fp1);
7025 gen_store_fpr64(ctx, fp0, fd);
7026 tcg_temp_free_i64(fp0);
7028 opn = "addr.ps";
7029 break;
7030 case FOP(26, 22):
7031 check_cp1_64bitmode(ctx);
7033 TCGv_i64 fp0 = tcg_temp_new_i64();
7034 TCGv_i64 fp1 = tcg_temp_new_i64();
7036 gen_load_fpr64(ctx, fp0, ft);
7037 gen_load_fpr64(ctx, fp1, fs);
7038 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7039 tcg_temp_free_i64(fp1);
7040 gen_store_fpr64(ctx, fp0, fd);
7041 tcg_temp_free_i64(fp0);
7043 opn = "mulr.ps";
7044 break;
7045 case FOP(28, 22):
7046 check_cp1_64bitmode(ctx);
7048 TCGv_i64 fp0 = tcg_temp_new_i64();
7049 TCGv_i64 fp1 = tcg_temp_new_i64();
7051 gen_load_fpr64(ctx, fp0, fs);
7052 gen_load_fpr64(ctx, fp1, fd);
7053 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7054 tcg_temp_free_i64(fp1);
7055 gen_store_fpr64(ctx, fp0, fd);
7056 tcg_temp_free_i64(fp0);
7058 opn = "recip2.ps";
7059 break;
7060 case FOP(29, 22):
7061 check_cp1_64bitmode(ctx);
7063 TCGv_i64 fp0 = tcg_temp_new_i64();
7065 gen_load_fpr64(ctx, fp0, fs);
7066 gen_helper_float_recip1_ps(fp0, fp0);
7067 gen_store_fpr64(ctx, fp0, fd);
7068 tcg_temp_free_i64(fp0);
7070 opn = "recip1.ps";
7071 break;
7072 case FOP(30, 22):
7073 check_cp1_64bitmode(ctx);
7075 TCGv_i64 fp0 = tcg_temp_new_i64();
7077 gen_load_fpr64(ctx, fp0, fs);
7078 gen_helper_float_rsqrt1_ps(fp0, fp0);
7079 gen_store_fpr64(ctx, fp0, fd);
7080 tcg_temp_free_i64(fp0);
7082 opn = "rsqrt1.ps";
7083 break;
7084 case FOP(31, 22):
7085 check_cp1_64bitmode(ctx);
7087 TCGv_i64 fp0 = tcg_temp_new_i64();
7088 TCGv_i64 fp1 = tcg_temp_new_i64();
7090 gen_load_fpr64(ctx, fp0, fs);
7091 gen_load_fpr64(ctx, fp1, ft);
7092 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7093 tcg_temp_free_i64(fp1);
7094 gen_store_fpr64(ctx, fp0, fd);
7095 tcg_temp_free_i64(fp0);
7097 opn = "rsqrt2.ps";
7098 break;
7099 case FOP(32, 22):
7100 check_cp1_64bitmode(ctx);
7102 TCGv_i32 fp0 = tcg_temp_new_i32();
7104 gen_load_fpr32h(fp0, fs);
7105 gen_helper_float_cvts_pu(fp0, fp0);
7106 gen_store_fpr32(fp0, fd);
7107 tcg_temp_free_i32(fp0);
7109 opn = "cvt.s.pu";
7110 break;
7111 case FOP(36, 22):
7112 check_cp1_64bitmode(ctx);
7114 TCGv_i64 fp0 = tcg_temp_new_i64();
7116 gen_load_fpr64(ctx, fp0, fs);
7117 gen_helper_float_cvtpw_ps(fp0, fp0);
7118 gen_store_fpr64(ctx, fp0, fd);
7119 tcg_temp_free_i64(fp0);
7121 opn = "cvt.pw.ps";
7122 break;
7123 case FOP(40, 22):
7124 check_cp1_64bitmode(ctx);
7126 TCGv_i32 fp0 = tcg_temp_new_i32();
7128 gen_load_fpr32(fp0, fs);
7129 gen_helper_float_cvts_pl(fp0, fp0);
7130 gen_store_fpr32(fp0, fd);
7131 tcg_temp_free_i32(fp0);
7133 opn = "cvt.s.pl";
7134 break;
7135 case FOP(44, 22):
7136 check_cp1_64bitmode(ctx);
7138 TCGv_i32 fp0 = tcg_temp_new_i32();
7139 TCGv_i32 fp1 = tcg_temp_new_i32();
7141 gen_load_fpr32(fp0, fs);
7142 gen_load_fpr32(fp1, ft);
7143 gen_store_fpr32h(fp0, fd);
7144 gen_store_fpr32(fp1, fd);
7145 tcg_temp_free_i32(fp0);
7146 tcg_temp_free_i32(fp1);
7148 opn = "pll.ps";
7149 break;
7150 case FOP(45, 22):
7151 check_cp1_64bitmode(ctx);
7153 TCGv_i32 fp0 = tcg_temp_new_i32();
7154 TCGv_i32 fp1 = tcg_temp_new_i32();
7156 gen_load_fpr32(fp0, fs);
7157 gen_load_fpr32h(fp1, ft);
7158 gen_store_fpr32(fp1, fd);
7159 gen_store_fpr32h(fp0, fd);
7160 tcg_temp_free_i32(fp0);
7161 tcg_temp_free_i32(fp1);
7163 opn = "plu.ps";
7164 break;
7165 case FOP(46, 22):
7166 check_cp1_64bitmode(ctx);
7168 TCGv_i32 fp0 = tcg_temp_new_i32();
7169 TCGv_i32 fp1 = tcg_temp_new_i32();
7171 gen_load_fpr32h(fp0, fs);
7172 gen_load_fpr32(fp1, ft);
7173 gen_store_fpr32(fp1, fd);
7174 gen_store_fpr32h(fp0, fd);
7175 tcg_temp_free_i32(fp0);
7176 tcg_temp_free_i32(fp1);
7178 opn = "pul.ps";
7179 break;
7180 case FOP(47, 22):
7181 check_cp1_64bitmode(ctx);
7183 TCGv_i32 fp0 = tcg_temp_new_i32();
7184 TCGv_i32 fp1 = tcg_temp_new_i32();
7186 gen_load_fpr32h(fp0, fs);
7187 gen_load_fpr32h(fp1, ft);
7188 gen_store_fpr32(fp1, fd);
7189 gen_store_fpr32h(fp0, fd);
7190 tcg_temp_free_i32(fp0);
7191 tcg_temp_free_i32(fp1);
7193 opn = "puu.ps";
7194 break;
7195 case FOP(48, 22):
7196 case FOP(49, 22):
7197 case FOP(50, 22):
7198 case FOP(51, 22):
7199 case FOP(52, 22):
7200 case FOP(53, 22):
7201 case FOP(54, 22):
7202 case FOP(55, 22):
7203 case FOP(56, 22):
7204 case FOP(57, 22):
7205 case FOP(58, 22):
7206 case FOP(59, 22):
7207 case FOP(60, 22):
7208 case FOP(61, 22):
7209 case FOP(62, 22):
7210 case FOP(63, 22):
7211 check_cp1_64bitmode(ctx);
7213 TCGv_i64 fp0 = tcg_temp_new_i64();
7214 TCGv_i64 fp1 = tcg_temp_new_i64();
7216 gen_load_fpr64(ctx, fp0, fs);
7217 gen_load_fpr64(ctx, fp1, ft);
7218 if (ctx->opcode & (1 << 6)) {
7219 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7220 opn = condnames_abs[func-48];
7221 } else {
7222 gen_cmp_ps(func-48, fp0, fp1, cc);
7223 opn = condnames[func-48];
7225 tcg_temp_free_i64(fp0);
7226 tcg_temp_free_i64(fp1);
7228 break;
7229 default:
7230 MIPS_INVAL(opn);
7231 generate_exception (ctx, EXCP_RI);
7232 return;
7234 switch (optype) {
7235 case BINOP:
7236 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7237 break;
7238 case CMPOP:
7239 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7240 break;
7241 default:
7242 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7243 break;
7247 /* Coprocessor 3 (FPU) */
7248 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7249 int fd, int fs, int base, int index)
7251 const char *opn = "extended float load/store";
7252 int store = 0;
7253 TCGv t0 = tcg_temp_new();
7255 if (base == 0) {
7256 gen_load_gpr(t0, index);
7257 } else if (index == 0) {
7258 gen_load_gpr(t0, base);
7259 } else {
7260 gen_load_gpr(t0, index);
7261 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
7263 /* Don't do NOP if destination is zero: we must perform the actual
7264 memory access. */
7265 save_cpu_state(ctx, 0);
7266 switch (opc) {
7267 case OPC_LWXC1:
7268 check_cop1x(ctx);
7270 TCGv_i32 fp0 = tcg_temp_new_i32();
7272 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7273 tcg_gen_trunc_tl_i32(fp0, t0);
7274 gen_store_fpr32(fp0, fd);
7275 tcg_temp_free_i32(fp0);
7277 opn = "lwxc1";
7278 break;
7279 case OPC_LDXC1:
7280 check_cop1x(ctx);
7281 check_cp1_registers(ctx, fd);
7283 TCGv_i64 fp0 = tcg_temp_new_i64();
7285 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7286 gen_store_fpr64(ctx, fp0, fd);
7287 tcg_temp_free_i64(fp0);
7289 opn = "ldxc1";
7290 break;
7291 case OPC_LUXC1:
7292 check_cp1_64bitmode(ctx);
7293 tcg_gen_andi_tl(t0, t0, ~0x7);
7295 TCGv_i64 fp0 = tcg_temp_new_i64();
7297 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7298 gen_store_fpr64(ctx, fp0, fd);
7299 tcg_temp_free_i64(fp0);
7301 opn = "luxc1";
7302 break;
7303 case OPC_SWXC1:
7304 check_cop1x(ctx);
7306 TCGv_i32 fp0 = tcg_temp_new_i32();
7307 TCGv t1 = tcg_temp_new();
7309 gen_load_fpr32(fp0, fs);
7310 tcg_gen_extu_i32_tl(t1, fp0);
7311 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7312 tcg_temp_free_i32(fp0);
7313 tcg_temp_free(t1);
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;
7345 tcg_temp_free(t0);
7346 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7347 regnames[index], regnames[base]);
7350 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7351 int fd, int fr, int fs, int ft)
7353 const char *opn = "flt3_arith";
7355 switch (opc) {
7356 case OPC_ALNV_PS:
7357 check_cp1_64bitmode(ctx);
7359 TCGv t0 = tcg_temp_local_new();
7360 TCGv_i32 fp = tcg_temp_new_i32();
7361 TCGv_i32 fph = tcg_temp_new_i32();
7362 int l1 = gen_new_label();
7363 int l2 = gen_new_label();
7365 gen_load_gpr(t0, fr);
7366 tcg_gen_andi_tl(t0, t0, 0x7);
7368 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7369 gen_load_fpr32(fp, fs);
7370 gen_load_fpr32h(fph, fs);
7371 gen_store_fpr32(fp, fd);
7372 gen_store_fpr32h(fph, fd);
7373 tcg_gen_br(l2);
7374 gen_set_label(l1);
7375 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7376 tcg_temp_free(t0);
7377 #ifdef TARGET_WORDS_BIGENDIAN
7378 gen_load_fpr32(fp, fs);
7379 gen_load_fpr32h(fph, ft);
7380 gen_store_fpr32h(fp, fd);
7381 gen_store_fpr32(fph, fd);
7382 #else
7383 gen_load_fpr32h(fph, fs);
7384 gen_load_fpr32(fp, ft);
7385 gen_store_fpr32(fph, fd);
7386 gen_store_fpr32h(fp, fd);
7387 #endif
7388 gen_set_label(l2);
7389 tcg_temp_free_i32(fp);
7390 tcg_temp_free_i32(fph);
7392 opn = "alnv.ps";
7393 break;
7394 case OPC_MADD_S:
7395 check_cop1x(ctx);
7397 TCGv_i32 fp0 = tcg_temp_new_i32();
7398 TCGv_i32 fp1 = tcg_temp_new_i32();
7399 TCGv_i32 fp2 = tcg_temp_new_i32();
7401 gen_load_fpr32(fp0, fs);
7402 gen_load_fpr32(fp1, ft);
7403 gen_load_fpr32(fp2, fr);
7404 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7405 tcg_temp_free_i32(fp0);
7406 tcg_temp_free_i32(fp1);
7407 gen_store_fpr32(fp2, fd);
7408 tcg_temp_free_i32(fp2);
7410 opn = "madd.s";
7411 break;
7412 case OPC_MADD_D:
7413 check_cop1x(ctx);
7414 check_cp1_registers(ctx, fd | fs | ft | fr);
7416 TCGv_i64 fp0 = tcg_temp_new_i64();
7417 TCGv_i64 fp1 = tcg_temp_new_i64();
7418 TCGv_i64 fp2 = tcg_temp_new_i64();
7420 gen_load_fpr64(ctx, fp0, fs);
7421 gen_load_fpr64(ctx, fp1, ft);
7422 gen_load_fpr64(ctx, fp2, fr);
7423 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7424 tcg_temp_free_i64(fp0);
7425 tcg_temp_free_i64(fp1);
7426 gen_store_fpr64(ctx, fp2, fd);
7427 tcg_temp_free_i64(fp2);
7429 opn = "madd.d";
7430 break;
7431 case OPC_MADD_PS:
7432 check_cp1_64bitmode(ctx);
7434 TCGv_i64 fp0 = tcg_temp_new_i64();
7435 TCGv_i64 fp1 = tcg_temp_new_i64();
7436 TCGv_i64 fp2 = tcg_temp_new_i64();
7438 gen_load_fpr64(ctx, fp0, fs);
7439 gen_load_fpr64(ctx, fp1, ft);
7440 gen_load_fpr64(ctx, fp2, fr);
7441 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7442 tcg_temp_free_i64(fp0);
7443 tcg_temp_free_i64(fp1);
7444 gen_store_fpr64(ctx, fp2, fd);
7445 tcg_temp_free_i64(fp2);
7447 opn = "madd.ps";
7448 break;
7449 case OPC_MSUB_S:
7450 check_cop1x(ctx);
7452 TCGv_i32 fp0 = tcg_temp_new_i32();
7453 TCGv_i32 fp1 = tcg_temp_new_i32();
7454 TCGv_i32 fp2 = tcg_temp_new_i32();
7456 gen_load_fpr32(fp0, fs);
7457 gen_load_fpr32(fp1, ft);
7458 gen_load_fpr32(fp2, fr);
7459 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7460 tcg_temp_free_i32(fp0);
7461 tcg_temp_free_i32(fp1);
7462 gen_store_fpr32(fp2, fd);
7463 tcg_temp_free_i32(fp2);
7465 opn = "msub.s";
7466 break;
7467 case OPC_MSUB_D:
7468 check_cop1x(ctx);
7469 check_cp1_registers(ctx, fd | fs | ft | fr);
7471 TCGv_i64 fp0 = tcg_temp_new_i64();
7472 TCGv_i64 fp1 = tcg_temp_new_i64();
7473 TCGv_i64 fp2 = tcg_temp_new_i64();
7475 gen_load_fpr64(ctx, fp0, fs);
7476 gen_load_fpr64(ctx, fp1, ft);
7477 gen_load_fpr64(ctx, fp2, fr);
7478 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7479 tcg_temp_free_i64(fp0);
7480 tcg_temp_free_i64(fp1);
7481 gen_store_fpr64(ctx, fp2, fd);
7482 tcg_temp_free_i64(fp2);
7484 opn = "msub.d";
7485 break;
7486 case OPC_MSUB_PS:
7487 check_cp1_64bitmode(ctx);
7489 TCGv_i64 fp0 = tcg_temp_new_i64();
7490 TCGv_i64 fp1 = tcg_temp_new_i64();
7491 TCGv_i64 fp2 = tcg_temp_new_i64();
7493 gen_load_fpr64(ctx, fp0, fs);
7494 gen_load_fpr64(ctx, fp1, ft);
7495 gen_load_fpr64(ctx, fp2, fr);
7496 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7497 tcg_temp_free_i64(fp0);
7498 tcg_temp_free_i64(fp1);
7499 gen_store_fpr64(ctx, fp2, fd);
7500 tcg_temp_free_i64(fp2);
7502 opn = "msub.ps";
7503 break;
7504 case OPC_NMADD_S:
7505 check_cop1x(ctx);
7507 TCGv_i32 fp0 = tcg_temp_new_i32();
7508 TCGv_i32 fp1 = tcg_temp_new_i32();
7509 TCGv_i32 fp2 = tcg_temp_new_i32();
7511 gen_load_fpr32(fp0, fs);
7512 gen_load_fpr32(fp1, ft);
7513 gen_load_fpr32(fp2, fr);
7514 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7515 tcg_temp_free_i32(fp0);
7516 tcg_temp_free_i32(fp1);
7517 gen_store_fpr32(fp2, fd);
7518 tcg_temp_free_i32(fp2);
7520 opn = "nmadd.s";
7521 break;
7522 case OPC_NMADD_D:
7523 check_cop1x(ctx);
7524 check_cp1_registers(ctx, fd | fs | ft | fr);
7526 TCGv_i64 fp0 = tcg_temp_new_i64();
7527 TCGv_i64 fp1 = tcg_temp_new_i64();
7528 TCGv_i64 fp2 = tcg_temp_new_i64();
7530 gen_load_fpr64(ctx, fp0, fs);
7531 gen_load_fpr64(ctx, fp1, ft);
7532 gen_load_fpr64(ctx, fp2, fr);
7533 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7534 tcg_temp_free_i64(fp0);
7535 tcg_temp_free_i64(fp1);
7536 gen_store_fpr64(ctx, fp2, fd);
7537 tcg_temp_free_i64(fp2);
7539 opn = "nmadd.d";
7540 break;
7541 case OPC_NMADD_PS:
7542 check_cp1_64bitmode(ctx);
7544 TCGv_i64 fp0 = tcg_temp_new_i64();
7545 TCGv_i64 fp1 = tcg_temp_new_i64();
7546 TCGv_i64 fp2 = tcg_temp_new_i64();
7548 gen_load_fpr64(ctx, fp0, fs);
7549 gen_load_fpr64(ctx, fp1, ft);
7550 gen_load_fpr64(ctx, fp2, fr);
7551 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7552 tcg_temp_free_i64(fp0);
7553 tcg_temp_free_i64(fp1);
7554 gen_store_fpr64(ctx, fp2, fd);
7555 tcg_temp_free_i64(fp2);
7557 opn = "nmadd.ps";
7558 break;
7559 case OPC_NMSUB_S:
7560 check_cop1x(ctx);
7562 TCGv_i32 fp0 = tcg_temp_new_i32();
7563 TCGv_i32 fp1 = tcg_temp_new_i32();
7564 TCGv_i32 fp2 = tcg_temp_new_i32();
7566 gen_load_fpr32(fp0, fs);
7567 gen_load_fpr32(fp1, ft);
7568 gen_load_fpr32(fp2, fr);
7569 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7570 tcg_temp_free_i32(fp0);
7571 tcg_temp_free_i32(fp1);
7572 gen_store_fpr32(fp2, fd);
7573 tcg_temp_free_i32(fp2);
7575 opn = "nmsub.s";
7576 break;
7577 case OPC_NMSUB_D:
7578 check_cop1x(ctx);
7579 check_cp1_registers(ctx, fd | fs | ft | fr);
7581 TCGv_i64 fp0 = tcg_temp_new_i64();
7582 TCGv_i64 fp1 = tcg_temp_new_i64();
7583 TCGv_i64 fp2 = tcg_temp_new_i64();
7585 gen_load_fpr64(ctx, fp0, fs);
7586 gen_load_fpr64(ctx, fp1, ft);
7587 gen_load_fpr64(ctx, fp2, fr);
7588 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7589 tcg_temp_free_i64(fp0);
7590 tcg_temp_free_i64(fp1);
7591 gen_store_fpr64(ctx, fp2, fd);
7592 tcg_temp_free_i64(fp2);
7594 opn = "nmsub.d";
7595 break;
7596 case OPC_NMSUB_PS:
7597 check_cp1_64bitmode(ctx);
7599 TCGv_i64 fp0 = tcg_temp_new_i64();
7600 TCGv_i64 fp1 = tcg_temp_new_i64();
7601 TCGv_i64 fp2 = tcg_temp_new_i64();
7603 gen_load_fpr64(ctx, fp0, fs);
7604 gen_load_fpr64(ctx, fp1, ft);
7605 gen_load_fpr64(ctx, fp2, fr);
7606 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7607 tcg_temp_free_i64(fp0);
7608 tcg_temp_free_i64(fp1);
7609 gen_store_fpr64(ctx, fp2, fd);
7610 tcg_temp_free_i64(fp2);
7612 opn = "nmsub.ps";
7613 break;
7614 default:
7615 MIPS_INVAL(opn);
7616 generate_exception (ctx, EXCP_RI);
7617 return;
7619 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7620 fregnames[fs], fregnames[ft]);
7623 /* ISA extensions (ASEs) */
7624 /* MIPS16 extension to MIPS32 */
7625 /* SmartMIPS extension to MIPS32 */
7627 #if defined(TARGET_MIPS64)
7629 /* MDMX extension to MIPS64 */
7631 #endif
7633 static void decode_opc (CPUState *env, DisasContext *ctx)
7635 int32_t offset;
7636 int rs, rt, rd, sa;
7637 uint32_t op, op1, op2;
7638 int16_t imm;
7640 /* make sure instructions are on a word boundary */
7641 if (ctx->pc & 0x3) {
7642 env->CP0_BadVAddr = ctx->pc;
7643 generate_exception(ctx, EXCP_AdEL);
7644 return;
7647 /* Handle blikely not taken case */
7648 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7649 int l1 = gen_new_label();
7651 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7652 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7653 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
7654 gen_goto_tb(ctx, 1, ctx->pc + 4);
7655 gen_set_label(l1);
7657 op = MASK_OP_MAJOR(ctx->opcode);
7658 rs = (ctx->opcode >> 21) & 0x1f;
7659 rt = (ctx->opcode >> 16) & 0x1f;
7660 rd = (ctx->opcode >> 11) & 0x1f;
7661 sa = (ctx->opcode >> 6) & 0x1f;
7662 imm = (int16_t)ctx->opcode;
7663 switch (op) {
7664 case OPC_SPECIAL:
7665 op1 = MASK_SPECIAL(ctx->opcode);
7666 switch (op1) {
7667 case OPC_SLL: /* Shift with immediate */
7668 case OPC_SRA:
7669 case OPC_SRL:
7670 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7671 break;
7672 case OPC_MOVN: /* Conditional move */
7673 case OPC_MOVZ:
7674 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7675 gen_cond_move(env, op1, rd, rs, rt);
7676 break;
7677 case OPC_ADD ... OPC_SUBU:
7678 gen_arith(env, ctx, op1, rd, rs, rt);
7679 break;
7680 case OPC_SLLV: /* Shifts */
7681 case OPC_SRLV:
7682 case OPC_SRAV:
7683 gen_shift(env, ctx, op1, rd, rs, rt);
7684 break;
7685 case OPC_SLT: /* Set on less than */
7686 case OPC_SLTU:
7687 gen_slt(env, op1, rd, rs, rt);
7688 break;
7689 case OPC_AND: /* Logic*/
7690 case OPC_OR:
7691 case OPC_NOR:
7692 case OPC_XOR:
7693 gen_logic(env, op1, rd, rs, rt);
7694 break;
7695 case OPC_MULT ... OPC_DIVU:
7696 if (sa) {
7697 check_insn(env, ctx, INSN_VR54XX);
7698 op1 = MASK_MUL_VR54XX(ctx->opcode);
7699 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7700 } else
7701 gen_muldiv(ctx, op1, rs, rt);
7702 break;
7703 case OPC_JR ... OPC_JALR:
7704 gen_compute_branch(ctx, op1, rs, rd, sa);
7705 return;
7706 case OPC_TGE ... OPC_TEQ: /* Traps */
7707 case OPC_TNE:
7708 gen_trap(ctx, op1, rs, rt, -1);
7709 break;
7710 case OPC_MFHI: /* Move from HI/LO */
7711 case OPC_MFLO:
7712 gen_HILO(ctx, op1, rd);
7713 break;
7714 case OPC_MTHI:
7715 case OPC_MTLO: /* Move to HI/LO */
7716 gen_HILO(ctx, op1, rs);
7717 break;
7718 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7719 #ifdef MIPS_STRICT_STANDARD
7720 MIPS_INVAL("PMON / selsl");
7721 generate_exception(ctx, EXCP_RI);
7722 #else
7723 gen_helper_0i(pmon, sa);
7724 #endif
7725 break;
7726 case OPC_SYSCALL:
7727 generate_exception(ctx, EXCP_SYSCALL);
7728 ctx->bstate = BS_STOP;
7729 break;
7730 case OPC_BREAK:
7731 generate_exception(ctx, EXCP_BREAK);
7732 break;
7733 case OPC_SPIM:
7734 #ifdef MIPS_STRICT_STANDARD
7735 MIPS_INVAL("SPIM");
7736 generate_exception(ctx, EXCP_RI);
7737 #else
7738 /* Implemented as RI exception for now. */
7739 MIPS_INVAL("spim (unofficial)");
7740 generate_exception(ctx, EXCP_RI);
7741 #endif
7742 break;
7743 case OPC_SYNC:
7744 /* Treat as NOP. */
7745 break;
7747 case OPC_MOVCI:
7748 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7749 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7750 check_cp1_enabled(ctx);
7751 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7752 (ctx->opcode >> 16) & 1);
7753 } else {
7754 generate_exception_err(ctx, EXCP_CpU, 1);
7756 break;
7758 #if defined(TARGET_MIPS64)
7759 /* MIPS64 specific opcodes */
7760 case OPC_DSLL:
7761 case OPC_DSRA:
7762 case OPC_DSRL:
7763 case OPC_DSLL32:
7764 case OPC_DSRA32:
7765 case OPC_DSRL32:
7766 check_insn(env, ctx, ISA_MIPS3);
7767 check_mips_64(ctx);
7768 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7769 break;
7770 case OPC_DADD ... OPC_DSUBU:
7771 check_insn(env, ctx, ISA_MIPS3);
7772 check_mips_64(ctx);
7773 gen_arith(env, ctx, op1, rd, rs, rt);
7774 break;
7775 case OPC_DSLLV:
7776 case OPC_DSRAV:
7777 case OPC_DSRLV:
7778 check_insn(env, ctx, ISA_MIPS3);
7779 check_mips_64(ctx);
7780 gen_shift(env, ctx, op1, rd, rs, rt);
7781 break;
7782 case OPC_DMULT ... OPC_DDIVU:
7783 check_insn(env, ctx, ISA_MIPS3);
7784 check_mips_64(ctx);
7785 gen_muldiv(ctx, op1, rs, rt);
7786 break;
7787 #endif
7788 default: /* Invalid */
7789 MIPS_INVAL("special");
7790 generate_exception(ctx, EXCP_RI);
7791 break;
7793 break;
7794 case OPC_SPECIAL2:
7795 op1 = MASK_SPECIAL2(ctx->opcode);
7796 switch (op1) {
7797 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7798 case OPC_MSUB ... OPC_MSUBU:
7799 check_insn(env, ctx, ISA_MIPS32);
7800 gen_muldiv(ctx, op1, rs, rt);
7801 break;
7802 case OPC_MUL:
7803 gen_arith(env, ctx, op1, rd, rs, rt);
7804 break;
7805 case OPC_CLO:
7806 case OPC_CLZ:
7807 check_insn(env, ctx, ISA_MIPS32);
7808 gen_cl(ctx, op1, rd, rs);
7809 break;
7810 case OPC_SDBBP:
7811 /* XXX: not clear which exception should be raised
7812 * when in debug mode...
7814 check_insn(env, ctx, ISA_MIPS32);
7815 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7816 generate_exception(ctx, EXCP_DBp);
7817 } else {
7818 generate_exception(ctx, EXCP_DBp);
7820 /* Treat as NOP. */
7821 break;
7822 #if defined(TARGET_MIPS64)
7823 case OPC_DCLO:
7824 case OPC_DCLZ:
7825 check_insn(env, ctx, ISA_MIPS64);
7826 check_mips_64(ctx);
7827 gen_cl(ctx, op1, rd, rs);
7828 break;
7829 #endif
7830 default: /* Invalid */
7831 MIPS_INVAL("special2");
7832 generate_exception(ctx, EXCP_RI);
7833 break;
7835 break;
7836 case OPC_SPECIAL3:
7837 op1 = MASK_SPECIAL3(ctx->opcode);
7838 switch (op1) {
7839 case OPC_EXT:
7840 case OPC_INS:
7841 check_insn(env, ctx, ISA_MIPS32R2);
7842 gen_bitops(ctx, op1, rt, rs, sa, rd);
7843 break;
7844 case OPC_BSHFL:
7845 check_insn(env, ctx, ISA_MIPS32R2);
7846 op2 = MASK_BSHFL(ctx->opcode);
7847 gen_bshfl(ctx, op2, rt, rd);
7848 break;
7849 case OPC_RDHWR:
7850 check_insn(env, ctx, ISA_MIPS32R2);
7852 TCGv t0 = tcg_temp_new();
7854 switch (rd) {
7855 case 0:
7856 save_cpu_state(ctx, 1);
7857 gen_helper_rdhwr_cpunum(t0);
7858 gen_store_gpr(t0, rt);
7859 break;
7860 case 1:
7861 save_cpu_state(ctx, 1);
7862 gen_helper_rdhwr_synci_step(t0);
7863 gen_store_gpr(t0, rt);
7864 break;
7865 case 2:
7866 save_cpu_state(ctx, 1);
7867 gen_helper_rdhwr_cc(t0);
7868 gen_store_gpr(t0, rt);
7869 break;
7870 case 3:
7871 save_cpu_state(ctx, 1);
7872 gen_helper_rdhwr_ccres(t0);
7873 gen_store_gpr(t0, rt);
7874 break;
7875 case 29:
7876 #if defined(CONFIG_USER_ONLY)
7877 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7878 gen_store_gpr(t0, rt);
7879 break;
7880 #else
7881 /* XXX: Some CPUs implement this in hardware.
7882 Not supported yet. */
7883 #endif
7884 default: /* Invalid */
7885 MIPS_INVAL("rdhwr");
7886 generate_exception(ctx, EXCP_RI);
7887 break;
7889 tcg_temp_free(t0);
7891 break;
7892 case OPC_FORK:
7893 check_insn(env, ctx, ASE_MT);
7895 TCGv t0 = tcg_temp_new();
7896 TCGv t1 = tcg_temp_new();
7898 gen_load_gpr(t0, rt);
7899 gen_load_gpr(t1, rs);
7900 gen_helper_fork(t0, t1);
7901 tcg_temp_free(t0);
7902 tcg_temp_free(t1);
7904 break;
7905 case OPC_YIELD:
7906 check_insn(env, ctx, ASE_MT);
7908 TCGv t0 = tcg_temp_new();
7910 save_cpu_state(ctx, 1);
7911 gen_load_gpr(t0, rs);
7912 gen_helper_yield(t0, t0);
7913 gen_store_gpr(t0, rd);
7914 tcg_temp_free(t0);
7916 break;
7917 #if defined(TARGET_MIPS64)
7918 case OPC_DEXTM ... OPC_DEXT:
7919 case OPC_DINSM ... OPC_DINS:
7920 check_insn(env, ctx, ISA_MIPS64R2);
7921 check_mips_64(ctx);
7922 gen_bitops(ctx, op1, rt, rs, sa, rd);
7923 break;
7924 case OPC_DBSHFL:
7925 check_insn(env, ctx, ISA_MIPS64R2);
7926 check_mips_64(ctx);
7927 op2 = MASK_DBSHFL(ctx->opcode);
7928 gen_bshfl(ctx, op2, rt, rd);
7929 break;
7930 #endif
7931 default: /* Invalid */
7932 MIPS_INVAL("special3");
7933 generate_exception(ctx, EXCP_RI);
7934 break;
7936 break;
7937 case OPC_REGIMM:
7938 op1 = MASK_REGIMM(ctx->opcode);
7939 switch (op1) {
7940 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7941 case OPC_BLTZAL ... OPC_BGEZALL:
7942 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
7943 return;
7944 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7945 case OPC_TNEI:
7946 gen_trap(ctx, op1, rs, -1, imm);
7947 break;
7948 case OPC_SYNCI:
7949 check_insn(env, ctx, ISA_MIPS32R2);
7950 /* Treat as NOP. */
7951 break;
7952 default: /* Invalid */
7953 MIPS_INVAL("regimm");
7954 generate_exception(ctx, EXCP_RI);
7955 break;
7957 break;
7958 case OPC_CP0:
7959 check_cp0_enabled(ctx);
7960 op1 = MASK_CP0(ctx->opcode);
7961 switch (op1) {
7962 case OPC_MFC0:
7963 case OPC_MTC0:
7964 case OPC_MFTR:
7965 case OPC_MTTR:
7966 #if defined(TARGET_MIPS64)
7967 case OPC_DMFC0:
7968 case OPC_DMTC0:
7969 #endif
7970 #ifndef CONFIG_USER_ONLY
7971 gen_cp0(env, ctx, op1, rt, rd);
7972 #endif /* !CONFIG_USER_ONLY */
7973 break;
7974 case OPC_C0_FIRST ... OPC_C0_LAST:
7975 #ifndef CONFIG_USER_ONLY
7976 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
7977 #endif /* !CONFIG_USER_ONLY */
7978 break;
7979 case OPC_MFMC0:
7980 #ifndef CONFIG_USER_ONLY
7982 TCGv t0 = tcg_temp_new();
7984 op2 = MASK_MFMC0(ctx->opcode);
7985 switch (op2) {
7986 case OPC_DMT:
7987 check_insn(env, ctx, ASE_MT);
7988 gen_helper_dmt(t0, t0);
7989 gen_store_gpr(t0, rt);
7990 break;
7991 case OPC_EMT:
7992 check_insn(env, ctx, ASE_MT);
7993 gen_helper_emt(t0, t0);
7994 gen_store_gpr(t0, rt);
7995 break;
7996 case OPC_DVPE:
7997 check_insn(env, ctx, ASE_MT);
7998 gen_helper_dvpe(t0, t0);
7999 gen_store_gpr(t0, rt);
8000 break;
8001 case OPC_EVPE:
8002 check_insn(env, ctx, ASE_MT);
8003 gen_helper_evpe(t0, t0);
8004 gen_store_gpr(t0, rt);
8005 break;
8006 case OPC_DI:
8007 check_insn(env, ctx, ISA_MIPS32R2);
8008 save_cpu_state(ctx, 1);
8009 gen_helper_di(t0);
8010 gen_store_gpr(t0, rt);
8011 /* Stop translation as we may have switched the execution mode */
8012 ctx->bstate = BS_STOP;
8013 break;
8014 case OPC_EI:
8015 check_insn(env, ctx, ISA_MIPS32R2);
8016 save_cpu_state(ctx, 1);
8017 gen_helper_ei(t0);
8018 gen_store_gpr(t0, rt);
8019 /* Stop translation as we may have switched the execution mode */
8020 ctx->bstate = BS_STOP;
8021 break;
8022 default: /* Invalid */
8023 MIPS_INVAL("mfmc0");
8024 generate_exception(ctx, EXCP_RI);
8025 break;
8027 tcg_temp_free(t0);
8029 #endif /* !CONFIG_USER_ONLY */
8030 break;
8031 case OPC_RDPGPR:
8032 check_insn(env, ctx, ISA_MIPS32R2);
8033 gen_load_srsgpr(rt, rd);
8034 break;
8035 case OPC_WRPGPR:
8036 check_insn(env, ctx, ISA_MIPS32R2);
8037 gen_store_srsgpr(rt, rd);
8038 break;
8039 default:
8040 MIPS_INVAL("cp0");
8041 generate_exception(ctx, EXCP_RI);
8042 break;
8044 break;
8045 case OPC_ADDI: /* Arithmetic with immediate opcode */
8046 case OPC_ADDIU:
8047 gen_arith_imm(env, ctx, op, rt, rs, imm);
8048 break;
8049 case OPC_SLTI: /* Set on less than with immediate opcode */
8050 case OPC_SLTIU:
8051 gen_slt_imm(env, op, rt, rs, imm);
8052 break;
8053 case OPC_ANDI: /* Arithmetic with immediate opcode */
8054 case OPC_LUI:
8055 case OPC_ORI:
8056 case OPC_XORI:
8057 gen_logic_imm(env, op, rt, rs, imm);
8058 break;
8059 case OPC_J ... OPC_JAL: /* Jump */
8060 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8061 gen_compute_branch(ctx, op, rs, rt, offset);
8062 return;
8063 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8064 case OPC_BEQL ... OPC_BGTZL:
8065 gen_compute_branch(ctx, op, rs, rt, imm << 2);
8066 return;
8067 case OPC_LB ... OPC_LWR: /* Load and stores */
8068 case OPC_SB ... OPC_SW:
8069 case OPC_SWR:
8070 case OPC_LL:
8071 gen_ldst(ctx, op, rt, rs, imm);
8072 break;
8073 case OPC_SC:
8074 gen_st_cond(ctx, op, rt, rs, imm);
8075 break;
8076 case OPC_CACHE:
8077 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
8078 /* Treat as NOP. */
8079 break;
8080 case OPC_PREF:
8081 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8082 /* Treat as NOP. */
8083 break;
8085 /* Floating point (COP1). */
8086 case OPC_LWC1:
8087 case OPC_LDC1:
8088 case OPC_SWC1:
8089 case OPC_SDC1:
8090 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8091 check_cp1_enabled(ctx);
8092 gen_flt_ldst(ctx, op, rt, rs, imm);
8093 } else {
8094 generate_exception_err(ctx, EXCP_CpU, 1);
8096 break;
8098 case OPC_CP1:
8099 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8100 check_cp1_enabled(ctx);
8101 op1 = MASK_CP1(ctx->opcode);
8102 switch (op1) {
8103 case OPC_MFHC1:
8104 case OPC_MTHC1:
8105 check_insn(env, ctx, ISA_MIPS32R2);
8106 case OPC_MFC1:
8107 case OPC_CFC1:
8108 case OPC_MTC1:
8109 case OPC_CTC1:
8110 gen_cp1(ctx, op1, rt, rd);
8111 break;
8112 #if defined(TARGET_MIPS64)
8113 case OPC_DMFC1:
8114 case OPC_DMTC1:
8115 check_insn(env, ctx, ISA_MIPS3);
8116 gen_cp1(ctx, op1, rt, rd);
8117 break;
8118 #endif
8119 case OPC_BC1ANY2:
8120 case OPC_BC1ANY4:
8121 check_cop1x(ctx);
8122 check_insn(env, ctx, ASE_MIPS3D);
8123 /* fall through */
8124 case OPC_BC1:
8125 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8126 (rt >> 2) & 0x7, imm << 2);
8127 return;
8128 case OPC_S_FMT:
8129 case OPC_D_FMT:
8130 case OPC_W_FMT:
8131 case OPC_L_FMT:
8132 case OPC_PS_FMT:
8133 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8134 (imm >> 8) & 0x7);
8135 break;
8136 default:
8137 MIPS_INVAL("cp1");
8138 generate_exception (ctx, EXCP_RI);
8139 break;
8141 } else {
8142 generate_exception_err(ctx, EXCP_CpU, 1);
8144 break;
8146 /* COP2. */
8147 case OPC_LWC2:
8148 case OPC_LDC2:
8149 case OPC_SWC2:
8150 case OPC_SDC2:
8151 case OPC_CP2:
8152 /* COP2: Not implemented. */
8153 generate_exception_err(ctx, EXCP_CpU, 2);
8154 break;
8156 case OPC_CP3:
8157 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8158 check_cp1_enabled(ctx);
8159 op1 = MASK_CP3(ctx->opcode);
8160 switch (op1) {
8161 case OPC_LWXC1:
8162 case OPC_LDXC1:
8163 case OPC_LUXC1:
8164 case OPC_SWXC1:
8165 case OPC_SDXC1:
8166 case OPC_SUXC1:
8167 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8168 break;
8169 case OPC_PREFX:
8170 /* Treat as NOP. */
8171 break;
8172 case OPC_ALNV_PS:
8173 case OPC_MADD_S:
8174 case OPC_MADD_D:
8175 case OPC_MADD_PS:
8176 case OPC_MSUB_S:
8177 case OPC_MSUB_D:
8178 case OPC_MSUB_PS:
8179 case OPC_NMADD_S:
8180 case OPC_NMADD_D:
8181 case OPC_NMADD_PS:
8182 case OPC_NMSUB_S:
8183 case OPC_NMSUB_D:
8184 case OPC_NMSUB_PS:
8185 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8186 break;
8187 default:
8188 MIPS_INVAL("cp3");
8189 generate_exception (ctx, EXCP_RI);
8190 break;
8192 } else {
8193 generate_exception_err(ctx, EXCP_CpU, 1);
8195 break;
8197 #if defined(TARGET_MIPS64)
8198 /* MIPS64 opcodes */
8199 case OPC_LWU:
8200 case OPC_LDL ... OPC_LDR:
8201 case OPC_SDL ... OPC_SDR:
8202 case OPC_LLD:
8203 case OPC_LD:
8204 case OPC_SD:
8205 check_insn(env, ctx, ISA_MIPS3);
8206 check_mips_64(ctx);
8207 gen_ldst(ctx, op, rt, rs, imm);
8208 break;
8209 case OPC_SCD:
8210 check_insn(env, ctx, ISA_MIPS3);
8211 check_mips_64(ctx);
8212 gen_st_cond(ctx, op, rt, rs, imm);
8213 break;
8214 case OPC_DADDI:
8215 case OPC_DADDIU:
8216 check_insn(env, ctx, ISA_MIPS3);
8217 check_mips_64(ctx);
8218 gen_arith_imm(env, ctx, op, rt, rs, imm);
8219 break;
8220 #endif
8221 case OPC_JALX:
8222 check_insn(env, ctx, ASE_MIPS16);
8223 /* MIPS16: Not implemented. */
8224 case OPC_MDMX:
8225 check_insn(env, ctx, ASE_MDMX);
8226 /* MDMX: Not implemented. */
8227 default: /* Invalid */
8228 MIPS_INVAL("major opcode");
8229 generate_exception(ctx, EXCP_RI);
8230 break;
8232 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8233 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8234 /* Branches completion */
8235 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8236 ctx->bstate = BS_BRANCH;
8237 save_cpu_state(ctx, 0);
8238 /* FIXME: Need to clear can_do_io. */
8239 switch (hflags) {
8240 case MIPS_HFLAG_B:
8241 /* unconditional branch */
8242 MIPS_DEBUG("unconditional branch");
8243 gen_goto_tb(ctx, 0, ctx->btarget);
8244 break;
8245 case MIPS_HFLAG_BL:
8246 /* blikely taken case */
8247 MIPS_DEBUG("blikely branch taken");
8248 gen_goto_tb(ctx, 0, ctx->btarget);
8249 break;
8250 case MIPS_HFLAG_BC:
8251 /* Conditional branch */
8252 MIPS_DEBUG("conditional branch");
8254 int l1 = gen_new_label();
8256 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8257 gen_goto_tb(ctx, 1, ctx->pc + 4);
8258 gen_set_label(l1);
8259 gen_goto_tb(ctx, 0, ctx->btarget);
8261 break;
8262 case MIPS_HFLAG_BR:
8263 /* unconditional branch to register */
8264 MIPS_DEBUG("branch to register");
8265 tcg_gen_mov_tl(cpu_PC, btarget);
8266 tcg_gen_exit_tb(0);
8267 break;
8268 default:
8269 MIPS_DEBUG("unknown branch");
8270 break;
8275 static inline void
8276 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8277 int search_pc)
8279 DisasContext ctx;
8280 target_ulong pc_start;
8281 uint16_t *gen_opc_end;
8282 CPUBreakpoint *bp;
8283 int j, lj = -1;
8284 int num_insns;
8285 int max_insns;
8287 if (search_pc)
8288 qemu_log("search pc %d\n", search_pc);
8290 pc_start = tb->pc;
8291 /* Leave some spare opc slots for branch handling. */
8292 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
8293 ctx.pc = pc_start;
8294 ctx.saved_pc = -1;
8295 ctx.tb = tb;
8296 ctx.bstate = BS_NONE;
8297 /* Restore delay slot state from the tb context. */
8298 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8299 restore_cpu_state(env, &ctx);
8300 #ifdef CONFIG_USER_ONLY
8301 ctx.mem_idx = MIPS_HFLAG_UM;
8302 #else
8303 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8304 #endif
8305 num_insns = 0;
8306 max_insns = tb->cflags & CF_COUNT_MASK;
8307 if (max_insns == 0)
8308 max_insns = CF_COUNT_MASK;
8309 #ifdef DEBUG_DISAS
8310 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
8311 /* FIXME: This may print out stale hflags from env... */
8312 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
8313 #endif
8314 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
8315 gen_icount_start();
8316 while (ctx.bstate == BS_NONE) {
8317 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8318 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8319 if (bp->pc == ctx.pc) {
8320 save_cpu_state(&ctx, 1);
8321 ctx.bstate = BS_BRANCH;
8322 gen_helper_0i(raise_exception, EXCP_DEBUG);
8323 /* Include the breakpoint location or the tb won't
8324 * be flushed when it must be. */
8325 ctx.pc += 4;
8326 goto done_generating;
8331 if (search_pc) {
8332 j = gen_opc_ptr - gen_opc_buf;
8333 if (lj < j) {
8334 lj++;
8335 while (lj < j)
8336 gen_opc_instr_start[lj++] = 0;
8338 gen_opc_pc[lj] = ctx.pc;
8339 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8340 gen_opc_instr_start[lj] = 1;
8341 gen_opc_icount[lj] = num_insns;
8343 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8344 gen_io_start();
8345 ctx.opcode = ldl_code(ctx.pc);
8346 decode_opc(env, &ctx);
8347 ctx.pc += 4;
8348 num_insns++;
8350 if (env->singlestep_enabled)
8351 break;
8353 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8354 break;
8356 if (gen_opc_ptr >= gen_opc_end)
8357 break;
8359 if (num_insns >= max_insns)
8360 break;
8362 if (singlestep)
8363 break;
8365 if (tb->cflags & CF_LAST_IO)
8366 gen_io_end();
8367 if (env->singlestep_enabled) {
8368 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
8369 gen_helper_0i(raise_exception, EXCP_DEBUG);
8370 } else {
8371 switch (ctx.bstate) {
8372 case BS_STOP:
8373 gen_helper_interrupt_restart();
8374 gen_goto_tb(&ctx, 0, ctx.pc);
8375 break;
8376 case BS_NONE:
8377 save_cpu_state(&ctx, 0);
8378 gen_goto_tb(&ctx, 0, ctx.pc);
8379 break;
8380 case BS_EXCP:
8381 gen_helper_interrupt_restart();
8382 tcg_gen_exit_tb(0);
8383 break;
8384 case BS_BRANCH:
8385 default:
8386 break;
8389 done_generating:
8390 gen_icount_end(tb, num_insns);
8391 *gen_opc_ptr = INDEX_op_end;
8392 if (search_pc) {
8393 j = gen_opc_ptr - gen_opc_buf;
8394 lj++;
8395 while (lj <= j)
8396 gen_opc_instr_start[lj++] = 0;
8397 } else {
8398 tb->size = ctx.pc - pc_start;
8399 tb->icount = num_insns;
8401 #ifdef DEBUG_DISAS
8402 LOG_DISAS("\n");
8403 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8404 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8405 log_target_disas(pc_start, ctx.pc - pc_start, 0);
8406 qemu_log("\n");
8408 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8409 #endif
8412 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8414 gen_intermediate_code_internal(env, tb, 0);
8417 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8419 gen_intermediate_code_internal(env, tb, 1);
8422 static void fpu_dump_state(CPUState *env, FILE *f,
8423 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8424 int flags)
8426 int i;
8427 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8429 #define printfpr(fp) \
8430 do { \
8431 if (is_fpu64) \
8432 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8433 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8434 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8435 else { \
8436 fpr_t tmp; \
8437 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8438 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8439 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8440 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8441 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8443 } while(0)
8446 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8447 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8448 get_float_exception_flags(&env->active_fpu.fp_status));
8449 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8450 fpu_fprintf(f, "%3s: ", fregnames[i]);
8451 printfpr(&env->active_fpu.fpr[i]);
8454 #undef printfpr
8457 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8458 /* Debug help: The architecture requires 32bit code to maintain proper
8459 sign-extended values on 64bit machines. */
8461 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8463 static void
8464 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8465 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8466 int flags)
8468 int i;
8470 if (!SIGN_EXT_P(env->active_tc.PC))
8471 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8472 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8473 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8474 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8475 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8476 if (!SIGN_EXT_P(env->btarget))
8477 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8479 for (i = 0; i < 32; i++) {
8480 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8481 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8484 if (!SIGN_EXT_P(env->CP0_EPC))
8485 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8486 if (!SIGN_EXT_P(env->CP0_LLAddr))
8487 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
8489 #endif
8491 void cpu_dump_state (CPUState *env, FILE *f,
8492 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8493 int flags)
8495 int i;
8497 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",
8498 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8499 env->hflags, env->btarget, env->bcond);
8500 for (i = 0; i < 32; i++) {
8501 if ((i & 3) == 0)
8502 cpu_fprintf(f, "GPR%02d:", i);
8503 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8504 if ((i & 3) == 3)
8505 cpu_fprintf(f, "\n");
8508 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8509 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8510 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8511 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
8512 if (env->hflags & MIPS_HFLAG_FPU)
8513 fpu_dump_state(env, f, cpu_fprintf, flags);
8514 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8515 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8516 #endif
8519 static void mips_tcg_init(void)
8521 int i;
8522 static int inited;
8524 /* Initialize various static tables. */
8525 if (inited)
8526 return;
8528 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8529 TCGV_UNUSED(cpu_gpr[0]);
8530 for (i = 1; i < 32; i++)
8531 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
8532 offsetof(CPUState, active_tc.gpr[i]),
8533 regnames[i]);
8534 cpu_PC = tcg_global_mem_new(TCG_AREG0,
8535 offsetof(CPUState, active_tc.PC), "PC");
8536 for (i = 0; i < MIPS_DSP_ACC; i++) {
8537 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
8538 offsetof(CPUState, active_tc.HI[i]),
8539 regnames_HI[i]);
8540 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
8541 offsetof(CPUState, active_tc.LO[i]),
8542 regnames_LO[i]);
8543 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
8544 offsetof(CPUState, active_tc.ACX[i]),
8545 regnames_ACX[i]);
8547 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
8548 offsetof(CPUState, active_tc.DSPControl),
8549 "DSPControl");
8550 bcond = tcg_global_mem_new(TCG_AREG0,
8551 offsetof(CPUState, bcond), "bcond");
8552 btarget = tcg_global_mem_new(TCG_AREG0,
8553 offsetof(CPUState, btarget), "btarget");
8554 hflags = tcg_global_mem_new_i32(TCG_AREG0,
8555 offsetof(CPUState, hflags), "hflags");
8557 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
8558 offsetof(CPUState, active_fpu.fcr0),
8559 "fcr0");
8560 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
8561 offsetof(CPUState, active_fpu.fcr31),
8562 "fcr31");
8564 /* register helpers */
8565 #define GEN_HELPER 2
8566 #include "helper.h"
8568 inited = 1;
8571 #include "translate_init.c"
8573 CPUMIPSState *cpu_mips_init (const char *cpu_model)
8575 CPUMIPSState *env;
8576 const mips_def_t *def;
8578 def = cpu_mips_find_by_name(cpu_model);
8579 if (!def)
8580 return NULL;
8581 env = qemu_mallocz(sizeof(CPUMIPSState));
8582 env->cpu_model = def;
8584 cpu_exec_init(env);
8585 env->cpu_model_str = cpu_model;
8586 mips_tcg_init();
8587 cpu_reset(env);
8588 qemu_init_vcpu(env);
8589 return env;
8592 void cpu_reset (CPUMIPSState *env)
8594 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
8595 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
8596 log_cpu_state(env, 0);
8599 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8601 tlb_flush(env, 1);
8603 /* Minimal init */
8604 #if defined(CONFIG_USER_ONLY)
8605 env->hflags = MIPS_HFLAG_UM;
8606 /* Enable access to the SYNCI_Step register. */
8607 env->CP0_HWREna |= (1 << 1);
8608 #else
8609 if (env->hflags & MIPS_HFLAG_BMASK) {
8610 /* If the exception was raised from a delay slot,
8611 come back to the jump. */
8612 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8613 } else {
8614 env->CP0_ErrorEPC = env->active_tc.PC;
8616 env->active_tc.PC = (int32_t)0xBFC00000;
8617 env->CP0_Wired = 0;
8618 /* SMP not implemented */
8619 env->CP0_EBase = 0x80000000;
8620 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8621 /* vectored interrupts not implemented, timer on int 7,
8622 no performance counters. */
8623 env->CP0_IntCtl = 0xe0000000;
8625 int i;
8627 for (i = 0; i < 7; i++) {
8628 env->CP0_WatchLo[i] = 0;
8629 env->CP0_WatchHi[i] = 0x80000000;
8631 env->CP0_WatchLo[7] = 0;
8632 env->CP0_WatchHi[7] = 0;
8634 /* Count register increments in debug mode, EJTAG version 1 */
8635 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8636 env->hflags = MIPS_HFLAG_CP0;
8637 #endif
8638 env->exception_index = EXCP_NONE;
8639 cpu_mips_register(env, env->cpu_model);
8642 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8643 unsigned long searched_pc, int pc_pos, void *puc)
8645 env->active_tc.PC = gen_opc_pc[pc_pos];
8646 env->hflags &= ~MIPS_HFLAG_BMASK;
8647 env->hflags |= gen_opc_hflags[pc_pos];