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