Immediate versions of some operations
[qemu/mini2440.git] / target-mips / translate.c
blobd6e54c8fa07f32ccb2c41d39d5432051b39d10ae
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <inttypes.h>
29 #include "cpu.h"
30 #include "exec-all.h"
31 #include "disas.h"
32 #include "helper.h"
33 #include "tcg-op.h"
34 #include "qemu-common.h"
36 //#define MIPS_DEBUG_DISAS
37 //#define MIPS_DEBUG_SIGN_EXTENSIONS
38 //#define MIPS_SINGLE_STEP
40 /* MIPS major opcodes */
41 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
43 enum {
44 /* indirect opcode tables */
45 OPC_SPECIAL = (0x00 << 26),
46 OPC_REGIMM = (0x01 << 26),
47 OPC_CP0 = (0x10 << 26),
48 OPC_CP1 = (0x11 << 26),
49 OPC_CP2 = (0x12 << 26),
50 OPC_CP3 = (0x13 << 26),
51 OPC_SPECIAL2 = (0x1C << 26),
52 OPC_SPECIAL3 = (0x1F << 26),
53 /* arithmetic with immediate */
54 OPC_ADDI = (0x08 << 26),
55 OPC_ADDIU = (0x09 << 26),
56 OPC_SLTI = (0x0A << 26),
57 OPC_SLTIU = (0x0B << 26),
58 OPC_ANDI = (0x0C << 26),
59 OPC_ORI = (0x0D << 26),
60 OPC_XORI = (0x0E << 26),
61 OPC_LUI = (0x0F << 26),
62 OPC_DADDI = (0x18 << 26),
63 OPC_DADDIU = (0x19 << 26),
64 /* Jump and branches */
65 OPC_J = (0x02 << 26),
66 OPC_JAL = (0x03 << 26),
67 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
68 OPC_BEQL = (0x14 << 26),
69 OPC_BNE = (0x05 << 26),
70 OPC_BNEL = (0x15 << 26),
71 OPC_BLEZ = (0x06 << 26),
72 OPC_BLEZL = (0x16 << 26),
73 OPC_BGTZ = (0x07 << 26),
74 OPC_BGTZL = (0x17 << 26),
75 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
76 /* Load and stores */
77 OPC_LDL = (0x1A << 26),
78 OPC_LDR = (0x1B << 26),
79 OPC_LB = (0x20 << 26),
80 OPC_LH = (0x21 << 26),
81 OPC_LWL = (0x22 << 26),
82 OPC_LW = (0x23 << 26),
83 OPC_LBU = (0x24 << 26),
84 OPC_LHU = (0x25 << 26),
85 OPC_LWR = (0x26 << 26),
86 OPC_LWU = (0x27 << 26),
87 OPC_SB = (0x28 << 26),
88 OPC_SH = (0x29 << 26),
89 OPC_SWL = (0x2A << 26),
90 OPC_SW = (0x2B << 26),
91 OPC_SDL = (0x2C << 26),
92 OPC_SDR = (0x2D << 26),
93 OPC_SWR = (0x2E << 26),
94 OPC_LL = (0x30 << 26),
95 OPC_LLD = (0x34 << 26),
96 OPC_LD = (0x37 << 26),
97 OPC_SC = (0x38 << 26),
98 OPC_SCD = (0x3C << 26),
99 OPC_SD = (0x3F << 26),
100 /* Floating point load/store */
101 OPC_LWC1 = (0x31 << 26),
102 OPC_LWC2 = (0x32 << 26),
103 OPC_LDC1 = (0x35 << 26),
104 OPC_LDC2 = (0x36 << 26),
105 OPC_SWC1 = (0x39 << 26),
106 OPC_SWC2 = (0x3A << 26),
107 OPC_SDC1 = (0x3D << 26),
108 OPC_SDC2 = (0x3E << 26),
109 /* MDMX ASE specific */
110 OPC_MDMX = (0x1E << 26),
111 /* Cache and prefetch */
112 OPC_CACHE = (0x2F << 26),
113 OPC_PREF = (0x33 << 26),
114 /* Reserved major opcode */
115 OPC_MAJOR3B_RESERVED = (0x3B << 26),
118 /* MIPS special opcodes */
119 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
121 enum {
122 /* Shifts */
123 OPC_SLL = 0x00 | OPC_SPECIAL,
124 /* NOP is SLL r0, r0, 0 */
125 /* SSNOP is SLL r0, r0, 1 */
126 /* EHB is SLL r0, r0, 3 */
127 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
128 OPC_SRA = 0x03 | OPC_SPECIAL,
129 OPC_SLLV = 0x04 | OPC_SPECIAL,
130 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
131 OPC_SRAV = 0x07 | OPC_SPECIAL,
132 OPC_DSLLV = 0x14 | OPC_SPECIAL,
133 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
134 OPC_DSRAV = 0x17 | OPC_SPECIAL,
135 OPC_DSLL = 0x38 | OPC_SPECIAL,
136 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
137 OPC_DSRA = 0x3B | OPC_SPECIAL,
138 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
139 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
140 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
141 /* Multiplication / division */
142 OPC_MULT = 0x18 | OPC_SPECIAL,
143 OPC_MULTU = 0x19 | OPC_SPECIAL,
144 OPC_DIV = 0x1A | OPC_SPECIAL,
145 OPC_DIVU = 0x1B | OPC_SPECIAL,
146 OPC_DMULT = 0x1C | OPC_SPECIAL,
147 OPC_DMULTU = 0x1D | OPC_SPECIAL,
148 OPC_DDIV = 0x1E | OPC_SPECIAL,
149 OPC_DDIVU = 0x1F | OPC_SPECIAL,
150 /* 2 registers arithmetic / logic */
151 OPC_ADD = 0x20 | OPC_SPECIAL,
152 OPC_ADDU = 0x21 | OPC_SPECIAL,
153 OPC_SUB = 0x22 | OPC_SPECIAL,
154 OPC_SUBU = 0x23 | OPC_SPECIAL,
155 OPC_AND = 0x24 | OPC_SPECIAL,
156 OPC_OR = 0x25 | OPC_SPECIAL,
157 OPC_XOR = 0x26 | OPC_SPECIAL,
158 OPC_NOR = 0x27 | OPC_SPECIAL,
159 OPC_SLT = 0x2A | OPC_SPECIAL,
160 OPC_SLTU = 0x2B | OPC_SPECIAL,
161 OPC_DADD = 0x2C | OPC_SPECIAL,
162 OPC_DADDU = 0x2D | OPC_SPECIAL,
163 OPC_DSUB = 0x2E | OPC_SPECIAL,
164 OPC_DSUBU = 0x2F | OPC_SPECIAL,
165 /* Jumps */
166 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
167 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
168 /* Traps */
169 OPC_TGE = 0x30 | OPC_SPECIAL,
170 OPC_TGEU = 0x31 | OPC_SPECIAL,
171 OPC_TLT = 0x32 | OPC_SPECIAL,
172 OPC_TLTU = 0x33 | OPC_SPECIAL,
173 OPC_TEQ = 0x34 | OPC_SPECIAL,
174 OPC_TNE = 0x36 | OPC_SPECIAL,
175 /* HI / LO registers load & stores */
176 OPC_MFHI = 0x10 | OPC_SPECIAL,
177 OPC_MTHI = 0x11 | OPC_SPECIAL,
178 OPC_MFLO = 0x12 | OPC_SPECIAL,
179 OPC_MTLO = 0x13 | OPC_SPECIAL,
180 /* Conditional moves */
181 OPC_MOVZ = 0x0A | OPC_SPECIAL,
182 OPC_MOVN = 0x0B | OPC_SPECIAL,
184 OPC_MOVCI = 0x01 | OPC_SPECIAL,
186 /* Special */
187 OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */
188 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
189 OPC_BREAK = 0x0D | OPC_SPECIAL,
190 OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */
191 OPC_SYNC = 0x0F | OPC_SPECIAL,
193 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
194 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
195 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
196 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
197 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
198 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
199 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
202 /* Multiplication variants of the vr54xx. */
203 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
205 enum {
206 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
207 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
208 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
209 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
210 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
211 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
212 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
213 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
214 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
215 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
216 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
217 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
218 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
219 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
222 /* REGIMM (rt field) opcodes */
223 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
225 enum {
226 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
227 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
228 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
229 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
230 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
231 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
232 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
233 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
234 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
235 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
236 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
237 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
238 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
239 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
240 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
243 /* Special2 opcodes */
244 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
246 enum {
247 /* Multiply & xxx operations */
248 OPC_MADD = 0x00 | OPC_SPECIAL2,
249 OPC_MADDU = 0x01 | OPC_SPECIAL2,
250 OPC_MUL = 0x02 | OPC_SPECIAL2,
251 OPC_MSUB = 0x04 | OPC_SPECIAL2,
252 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
253 /* Misc */
254 OPC_CLZ = 0x20 | OPC_SPECIAL2,
255 OPC_CLO = 0x21 | OPC_SPECIAL2,
256 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
257 OPC_DCLO = 0x25 | OPC_SPECIAL2,
258 /* Special */
259 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
262 /* Special3 opcodes */
263 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
265 enum {
266 OPC_EXT = 0x00 | OPC_SPECIAL3,
267 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
268 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
269 OPC_DEXT = 0x03 | OPC_SPECIAL3,
270 OPC_INS = 0x04 | OPC_SPECIAL3,
271 OPC_DINSM = 0x05 | OPC_SPECIAL3,
272 OPC_DINSU = 0x06 | OPC_SPECIAL3,
273 OPC_DINS = 0x07 | OPC_SPECIAL3,
274 OPC_FORK = 0x08 | OPC_SPECIAL3,
275 OPC_YIELD = 0x09 | OPC_SPECIAL3,
276 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
277 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
278 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
281 /* BSHFL opcodes */
282 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
284 enum {
285 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
286 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
287 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
290 /* DBSHFL opcodes */
291 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
293 enum {
294 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
295 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
298 /* Coprocessor 0 (rs field) */
299 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
301 enum {
302 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
303 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
304 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
305 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
306 OPC_MFTR = (0x08 << 21) | OPC_CP0,
307 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
308 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
309 OPC_MTTR = (0x0C << 21) | OPC_CP0,
310 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
311 OPC_C0 = (0x10 << 21) | OPC_CP0,
312 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
313 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
316 /* MFMC0 opcodes */
317 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
319 enum {
320 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
321 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
322 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
323 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
324 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
325 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
328 /* Coprocessor 0 (with rs == C0) */
329 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
331 enum {
332 OPC_TLBR = 0x01 | OPC_C0,
333 OPC_TLBWI = 0x02 | OPC_C0,
334 OPC_TLBWR = 0x06 | OPC_C0,
335 OPC_TLBP = 0x08 | OPC_C0,
336 OPC_RFE = 0x10 | OPC_C0,
337 OPC_ERET = 0x18 | OPC_C0,
338 OPC_DERET = 0x1F | OPC_C0,
339 OPC_WAIT = 0x20 | OPC_C0,
342 /* Coprocessor 1 (rs field) */
343 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
345 enum {
346 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
347 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
348 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
349 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
350 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
351 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
352 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
353 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
354 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
355 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
356 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
357 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
358 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
359 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
360 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
361 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
362 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
363 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
366 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
367 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
369 enum {
370 OPC_BC1F = (0x00 << 16) | OPC_BC1,
371 OPC_BC1T = (0x01 << 16) | OPC_BC1,
372 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
373 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
376 enum {
377 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
378 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
381 enum {
382 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
383 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
386 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
388 enum {
389 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
390 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
391 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
392 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
393 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
394 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
395 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
396 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
397 OPC_BC2 = (0x08 << 21) | OPC_CP2,
400 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
402 enum {
403 OPC_LWXC1 = 0x00 | OPC_CP3,
404 OPC_LDXC1 = 0x01 | OPC_CP3,
405 OPC_LUXC1 = 0x05 | OPC_CP3,
406 OPC_SWXC1 = 0x08 | OPC_CP3,
407 OPC_SDXC1 = 0x09 | OPC_CP3,
408 OPC_SUXC1 = 0x0D | OPC_CP3,
409 OPC_PREFX = 0x0F | OPC_CP3,
410 OPC_ALNV_PS = 0x1E | OPC_CP3,
411 OPC_MADD_S = 0x20 | OPC_CP3,
412 OPC_MADD_D = 0x21 | OPC_CP3,
413 OPC_MADD_PS = 0x26 | OPC_CP3,
414 OPC_MSUB_S = 0x28 | OPC_CP3,
415 OPC_MSUB_D = 0x29 | OPC_CP3,
416 OPC_MSUB_PS = 0x2E | OPC_CP3,
417 OPC_NMADD_S = 0x30 | OPC_CP3,
418 OPC_NMADD_D = 0x31 | OPC_CP3,
419 OPC_NMADD_PS= 0x36 | OPC_CP3,
420 OPC_NMSUB_S = 0x38 | OPC_CP3,
421 OPC_NMSUB_D = 0x39 | OPC_CP3,
422 OPC_NMSUB_PS= 0x3E | OPC_CP3,
425 /* global register indices */
426 static TCGv cpu_env, bcond, btarget, current_fpu;
428 #include "gen-icount.h"
430 static inline void tcg_gen_helper_0_i(void *func, TCGv arg)
432 TCGv tmp = tcg_const_i32(arg);
434 tcg_gen_helper_0_1(func, tmp);
435 tcg_temp_free(tmp);
438 static inline void tcg_gen_helper_0_ii(void *func, TCGv arg1, TCGv arg2)
440 TCGv tmp1 = tcg_const_i32(arg1);
441 TCGv tmp2 = tcg_const_i32(arg2);
443 tcg_gen_helper_0_2(func, tmp1, tmp2);
444 tcg_temp_free(tmp1);
445 tcg_temp_free(tmp2);
448 static inline void tcg_gen_helper_0_1i(void *func, TCGv arg1, TCGv arg2)
450 TCGv tmp = tcg_const_i32(arg2);
452 tcg_gen_helper_0_2(func, arg1, tmp);
453 tcg_temp_free(tmp);
456 static inline void tcg_gen_helper_0_2i(void *func, TCGv arg1, TCGv arg2, TCGv arg3)
458 TCGv tmp = tcg_const_i32(arg3);
460 tcg_gen_helper_0_3(func, arg1, arg2, tmp);
461 tcg_temp_free(tmp);
464 static inline void tcg_gen_helper_0_1ii(void *func, TCGv arg1, TCGv arg2, TCGv arg3)
466 TCGv tmp1 = tcg_const_i32(arg2);
467 TCGv tmp2 = tcg_const_i32(arg3);
469 tcg_gen_helper_0_3(func, arg1, tmp1, tmp2);
470 tcg_temp_free(tmp1);
471 tcg_temp_free(tmp2);
474 static inline void tcg_gen_helper_1_i(void *func, TCGv ret, TCGv arg)
476 TCGv tmp = tcg_const_i32(arg);
478 tcg_gen_helper_1_1(func, ret, tmp);
479 tcg_temp_free(tmp);
482 static inline void tcg_gen_helper_1_1i(void *func, TCGv ret, TCGv arg1, TCGv arg2)
484 TCGv tmp = tcg_const_i32(arg2);
486 tcg_gen_helper_1_2(func, ret, arg1, tmp);
487 tcg_temp_free(tmp);
490 static inline void tcg_gen_helper_1_1ii(void *func, TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3)
492 TCGv tmp1 = tcg_const_i32(arg2);
493 TCGv tmp2 = tcg_const_i32(arg3);
495 tcg_gen_helper_1_3(func, ret, arg1, tmp1, tmp2);
496 tcg_temp_free(tmp1);
497 tcg_temp_free(tmp2);
500 static inline void tcg_gen_helper_1_2i(void *func, TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3)
502 TCGv tmp = tcg_const_i32(arg3);
504 tcg_gen_helper_1_3(func, ret, arg1, arg2, tmp);
505 tcg_temp_free(tmp);
508 static inline void tcg_gen_helper_1_2ii(void *func, TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, TCGv arg4)
510 TCGv tmp1 = tcg_const_i32(arg3);
511 TCGv tmp2 = tcg_const_i32(arg4);
513 tcg_gen_helper_1_4(func, ret, arg1, arg2, tmp1, tmp2);
514 tcg_temp_free(tmp1);
515 tcg_temp_free(tmp2);
518 typedef struct DisasContext {
519 struct TranslationBlock *tb;
520 target_ulong pc, saved_pc;
521 uint32_t opcode;
522 uint32_t fp_status;
523 /* Routine used to access memory */
524 int mem_idx;
525 uint32_t hflags, saved_hflags;
526 int bstate;
527 target_ulong btarget;
528 } DisasContext;
530 enum {
531 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
532 * exception condition */
533 BS_STOP = 1, /* We want to stop translation for any reason */
534 BS_BRANCH = 2, /* We reached a branch condition */
535 BS_EXCP = 3, /* We reached an exception condition */
538 static const char *regnames[] =
539 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
540 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
541 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
542 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
544 static const char *fregnames[] =
545 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
546 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
547 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
548 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
550 #ifdef MIPS_DEBUG_DISAS
551 #define MIPS_DEBUG(fmt, args...) \
552 do { \
553 if (loglevel & CPU_LOG_TB_IN_ASM) { \
554 fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n", \
555 ctx->pc, ctx->opcode , ##args); \
557 } while (0)
558 #else
559 #define MIPS_DEBUG(fmt, args...) do { } while(0)
560 #endif
562 #define MIPS_INVAL(op) \
563 do { \
564 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
565 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
566 } while (0)
568 /* General purpose registers moves. */
569 static inline void gen_load_gpr (TCGv t, int reg)
571 if (reg == 0)
572 tcg_gen_movi_tl(t, 0);
573 else
574 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.gpr) +
575 sizeof(target_ulong) * reg);
578 static inline void gen_store_gpr (TCGv t, int reg)
580 if (reg != 0)
581 tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.gpr) +
582 sizeof(target_ulong) * reg);
585 /* Moves to/from HI and LO registers. */
586 static inline void gen_load_LO (TCGv t, int reg)
588 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.LO) +
589 sizeof(target_ulong) * reg);
592 static inline void gen_store_LO (TCGv t, int reg)
594 tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.LO) +
595 sizeof(target_ulong) * reg);
598 static inline void gen_load_HI (TCGv t, int reg)
600 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.HI) +
601 sizeof(target_ulong) * reg);
604 static inline void gen_store_HI (TCGv t, int reg)
606 tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.HI) +
607 sizeof(target_ulong) * reg);
610 /* Moves to/from shadow registers. */
611 static inline void gen_load_srsgpr (int from, int to)
613 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
615 if (from == 0)
616 tcg_gen_movi_tl(r_tmp1, 0);
617 else {
618 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
620 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
621 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
622 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
623 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
624 tcg_gen_add_i32(r_tmp2, cpu_env, r_tmp2);
626 tcg_gen_ld_tl(r_tmp1, r_tmp2, sizeof(target_ulong) * from);
627 tcg_temp_free(r_tmp2);
629 gen_store_gpr(r_tmp1, to);
630 tcg_temp_free(r_tmp1);
633 static inline void gen_store_srsgpr (int from, int to)
635 if (to != 0) {
636 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
637 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
639 gen_load_gpr(r_tmp1, from);
640 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
641 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
642 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
643 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
644 tcg_gen_add_i32(r_tmp2, cpu_env, r_tmp2);
646 tcg_gen_st_tl(r_tmp1, r_tmp2, sizeof(target_ulong) * to);
647 tcg_temp_free(r_tmp1);
648 tcg_temp_free(r_tmp2);
652 /* Floating point register moves. */
653 static inline void gen_load_fpr32 (TCGv t, int reg)
655 tcg_gen_ld_i32(t, current_fpu, 8 * reg + 4 * FP_ENDIAN_IDX);
658 static inline void gen_store_fpr32 (TCGv t, int reg)
660 tcg_gen_st_i32(t, current_fpu, 8 * reg + 4 * FP_ENDIAN_IDX);
663 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv t, int reg)
665 if (ctx->hflags & MIPS_HFLAG_F64) {
666 tcg_gen_ld_i64(t, current_fpu, 8 * reg);
667 } else {
668 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
669 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
671 tcg_gen_ld_i32(r_tmp1, current_fpu, 8 * (reg | 1) + 4 * FP_ENDIAN_IDX);
672 tcg_gen_extu_i32_i64(t, r_tmp1);
673 tcg_gen_shli_i64(t, t, 32);
674 tcg_gen_ld_i32(r_tmp1, current_fpu, 8 * (reg & ~1) + 4 * FP_ENDIAN_IDX);
675 tcg_gen_extu_i32_i64(r_tmp2, r_tmp1);
676 tcg_gen_or_i64(t, t, r_tmp2);
677 tcg_temp_free(r_tmp1);
678 tcg_temp_free(r_tmp2);
682 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv t, int reg)
684 if (ctx->hflags & MIPS_HFLAG_F64) {
685 tcg_gen_st_i64(t, current_fpu, 8 * reg);
686 } else {
687 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
689 tcg_gen_trunc_i64_i32(r_tmp, t);
690 tcg_gen_st_i32(r_tmp, current_fpu, 8 * (reg & ~1) + 4 * FP_ENDIAN_IDX);
691 tcg_gen_shri_i64(t, t, 32);
692 tcg_gen_trunc_i64_i32(r_tmp, t);
693 tcg_gen_st_i32(r_tmp, current_fpu, 8 * (reg | 1) + 4 * FP_ENDIAN_IDX);
694 tcg_temp_free(r_tmp);
698 static inline void gen_load_fpr32h (TCGv t, int reg)
700 tcg_gen_ld_i32(t, current_fpu, 8 * reg + 4 * !FP_ENDIAN_IDX);
703 static inline void gen_store_fpr32h (TCGv t, int reg)
705 tcg_gen_st_i32(t, current_fpu, 8 * reg + 4 * !FP_ENDIAN_IDX);
708 static inline void get_fp_cond (TCGv t)
710 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
711 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
713 tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
714 tcg_gen_shri_i32(r_tmp2, r_tmp1, 24);
715 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xfe);
716 tcg_gen_shri_i32(r_tmp1, r_tmp1, 23);
717 tcg_gen_andi_i32(r_tmp1, r_tmp1, 0x1);
718 tcg_gen_or_i32(t, r_tmp1, r_tmp2);
719 tcg_temp_free(r_tmp1);
720 tcg_temp_free(r_tmp2);
723 typedef void (fcmp_fun32)(uint32_t, uint32_t, int);
724 typedef void (fcmp_fun64)(uint64_t, uint64_t, int);
726 #define FOP_CONDS(fcmp_fun, type, arg0, arg1, fmt) \
727 static fcmp_fun * fcmp ## type ## _ ## fmt ## _table[16] = { \
728 do_cmp ## type ## _ ## fmt ## _f, \
729 do_cmp ## type ## _ ## fmt ## _un, \
730 do_cmp ## type ## _ ## fmt ## _eq, \
731 do_cmp ## type ## _ ## fmt ## _ueq, \
732 do_cmp ## type ## _ ## fmt ## _olt, \
733 do_cmp ## type ## _ ## fmt ## _ult, \
734 do_cmp ## type ## _ ## fmt ## _ole, \
735 do_cmp ## type ## _ ## fmt ## _ule, \
736 do_cmp ## type ## _ ## fmt ## _sf, \
737 do_cmp ## type ## _ ## fmt ## _ngle, \
738 do_cmp ## type ## _ ## fmt ## _seq, \
739 do_cmp ## type ## _ ## fmt ## _ngl, \
740 do_cmp ## type ## _ ## fmt ## _lt, \
741 do_cmp ## type ## _ ## fmt ## _nge, \
742 do_cmp ## type ## _ ## fmt ## _le, \
743 do_cmp ## type ## _ ## fmt ## _ngt, \
744 }; \
745 static inline void gen_cmp ## type ## _ ## fmt(int n, arg0 a, arg1 b, int cc) \
747 tcg_gen_helper_0_2i(fcmp ## type ## _ ## fmt ## _table[n], a, b, cc); \
750 FOP_CONDS(fcmp_fun64, , uint64_t, uint64_t, d)
751 FOP_CONDS(fcmp_fun64, abs, uint64_t, uint64_t, d)
752 FOP_CONDS(fcmp_fun32, , uint32_t, uint32_t, s)
753 FOP_CONDS(fcmp_fun32, abs, uint32_t, uint32_t, s)
754 FOP_CONDS(fcmp_fun64, , uint64_t, uint64_t, ps)
755 FOP_CONDS(fcmp_fun64, abs, uint64_t, uint64_t, ps)
756 #undef FOP_CONDS
758 /* Tests */
759 #define OP_COND(name, cond) \
760 static inline void glue(gen_op_, name) (TCGv t0, TCGv t1) \
762 int l1 = gen_new_label(); \
763 int l2 = gen_new_label(); \
765 tcg_gen_brcond_tl(cond, t0, t1, l1); \
766 tcg_gen_movi_tl(t0, 0); \
767 tcg_gen_br(l2); \
768 gen_set_label(l1); \
769 tcg_gen_movi_tl(t0, 1); \
770 gen_set_label(l2); \
772 OP_COND(eq, TCG_COND_EQ);
773 OP_COND(ne, TCG_COND_NE);
774 OP_COND(ge, TCG_COND_GE);
775 OP_COND(geu, TCG_COND_GEU);
776 OP_COND(lt, TCG_COND_LT);
777 OP_COND(ltu, TCG_COND_LTU);
778 #undef OP_COND
780 #define OP_CONDI(name, cond) \
781 static inline void glue(gen_op_, name) (TCGv t, target_ulong val) \
783 int l1 = gen_new_label(); \
784 int l2 = gen_new_label(); \
786 tcg_gen_brcondi_tl(cond, t, val, l1); \
787 tcg_gen_movi_tl(t, 0); \
788 tcg_gen_br(l2); \
789 gen_set_label(l1); \
790 tcg_gen_movi_tl(t, 1); \
791 gen_set_label(l2); \
793 OP_CONDI(lti, TCG_COND_LT);
794 OP_CONDI(ltiu, TCG_COND_LTU);
795 #undef OP_CONDI
797 #define OP_CONDZ(name, cond) \
798 static inline void glue(gen_op_, name) (TCGv t) \
800 int l1 = gen_new_label(); \
801 int l2 = gen_new_label(); \
803 tcg_gen_brcondi_tl(cond, t, 0, l1); \
804 tcg_gen_movi_tl(t, 0); \
805 tcg_gen_br(l2); \
806 gen_set_label(l1); \
807 tcg_gen_movi_tl(t, 1); \
808 gen_set_label(l2); \
810 OP_CONDZ(gez, TCG_COND_GE);
811 OP_CONDZ(gtz, TCG_COND_GT);
812 OP_CONDZ(lez, TCG_COND_LE);
813 OP_CONDZ(ltz, TCG_COND_LT);
814 #undef OP_CONDZ
816 static inline void gen_save_pc(target_ulong pc)
818 TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);
820 tcg_gen_movi_tl(r_tmp, pc);
821 tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, active_tc.PC));
822 tcg_temp_free(r_tmp);
825 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
827 #if defined MIPS_DEBUG_DISAS
828 if (loglevel & CPU_LOG_TB_IN_ASM) {
829 fprintf(logfile, "hflags %08x saved %08x\n",
830 ctx->hflags, ctx->saved_hflags);
832 #endif
833 if (do_save_pc && ctx->pc != ctx->saved_pc) {
834 gen_save_pc(ctx->pc);
835 ctx->saved_pc = ctx->pc;
837 if (ctx->hflags != ctx->saved_hflags) {
838 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
840 tcg_gen_movi_i32(r_tmp, ctx->hflags);
841 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
842 tcg_temp_free(r_tmp);
843 ctx->saved_hflags = ctx->hflags;
844 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
845 case MIPS_HFLAG_BR:
846 break;
847 case MIPS_HFLAG_BC:
848 case MIPS_HFLAG_BL:
849 case MIPS_HFLAG_B:
850 tcg_gen_movi_tl(btarget, ctx->btarget);
851 break;
856 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
858 ctx->saved_hflags = ctx->hflags;
859 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
860 case MIPS_HFLAG_BR:
861 break;
862 case MIPS_HFLAG_BC:
863 case MIPS_HFLAG_BL:
864 case MIPS_HFLAG_B:
865 ctx->btarget = env->btarget;
866 break;
870 static inline void
871 generate_exception_err (DisasContext *ctx, int excp, int err)
873 save_cpu_state(ctx, 1);
874 tcg_gen_helper_0_ii(do_raise_exception_err, excp, err);
875 tcg_gen_helper_0_0(do_interrupt_restart);
876 tcg_gen_exit_tb(0);
879 static inline void
880 generate_exception (DisasContext *ctx, int excp)
882 save_cpu_state(ctx, 1);
883 tcg_gen_helper_0_i(do_raise_exception, excp);
884 tcg_gen_helper_0_0(do_interrupt_restart);
885 tcg_gen_exit_tb(0);
888 /* Addresses computation */
889 static inline void gen_op_addr_add (TCGv t0, TCGv t1)
891 tcg_gen_add_tl(t0, t0, t1);
893 #if defined(TARGET_MIPS64)
894 /* For compatibility with 32-bit code, data reference in user mode
895 with Status_UX = 0 should be casted to 32-bit and sign extended.
896 See the MIPS64 PRA manual, section 4.10. */
898 int l1 = gen_new_label();
899 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_I32);
901 tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
902 tcg_gen_andi_i32(r_tmp, r_tmp, MIPS_HFLAG_KSU);
903 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp, MIPS_HFLAG_UM, l1);
904 tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_Status));
905 tcg_gen_andi_i32(r_tmp, r_tmp, (1 << CP0St_UX));
906 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp, 0, l1);
907 tcg_temp_free(r_tmp);
908 tcg_gen_ext32s_i64(t0, t0);
909 gen_set_label(l1);
911 #endif
914 static inline void check_cp0_enabled(DisasContext *ctx)
916 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
917 generate_exception_err(ctx, EXCP_CpU, 1);
920 static inline void check_cp1_enabled(DisasContext *ctx)
922 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
923 generate_exception_err(ctx, EXCP_CpU, 1);
926 /* Verify that the processor is running with COP1X instructions enabled.
927 This is associated with the nabla symbol in the MIPS32 and MIPS64
928 opcode tables. */
930 static inline void check_cop1x(DisasContext *ctx)
932 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
933 generate_exception(ctx, EXCP_RI);
936 /* Verify that the processor is running with 64-bit floating-point
937 operations enabled. */
939 static inline void check_cp1_64bitmode(DisasContext *ctx)
941 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
942 generate_exception(ctx, EXCP_RI);
946 * Verify if floating point register is valid; an operation is not defined
947 * if bit 0 of any register specification is set and the FR bit in the
948 * Status register equals zero, since the register numbers specify an
949 * even-odd pair of adjacent coprocessor general registers. When the FR bit
950 * in the Status register equals one, both even and odd register numbers
951 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
953 * Multiple 64 bit wide registers can be checked by calling
954 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
956 static inline void check_cp1_registers(DisasContext *ctx, int regs)
958 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
959 generate_exception(ctx, EXCP_RI);
962 /* This code generates a "reserved instruction" exception if the
963 CPU does not support the instruction set corresponding to flags. */
964 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
966 if (unlikely(!(env->insn_flags & flags)))
967 generate_exception(ctx, EXCP_RI);
970 /* This code generates a "reserved instruction" exception if 64-bit
971 instructions are not enabled. */
972 static inline void check_mips_64(DisasContext *ctx)
974 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
975 generate_exception(ctx, EXCP_RI);
978 /* load/store instructions. */
979 #define OP_LD(insn,fname) \
980 static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx) \
982 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
984 OP_LD(lb,ld8s);
985 OP_LD(lbu,ld8u);
986 OP_LD(lh,ld16s);
987 OP_LD(lhu,ld16u);
988 OP_LD(lw,ld32s);
989 #if defined(TARGET_MIPS64)
990 OP_LD(lwu,ld32u);
991 OP_LD(ld,ld64);
992 #endif
993 #undef OP_LD
995 #define OP_ST(insn,fname) \
996 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
998 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
1000 OP_ST(sb,st8);
1001 OP_ST(sh,st16);
1002 OP_ST(sw,st32);
1003 #if defined(TARGET_MIPS64)
1004 OP_ST(sd,st64);
1005 #endif
1006 #undef OP_ST
1008 #define OP_LD_ATOMIC(insn,fname) \
1009 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
1011 tcg_gen_mov_tl(t1, t0); \
1012 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
1013 tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
1015 OP_LD_ATOMIC(ll,ld32s);
1016 #if defined(TARGET_MIPS64)
1017 OP_LD_ATOMIC(lld,ld64);
1018 #endif
1019 #undef OP_LD_ATOMIC
1021 #define OP_ST_ATOMIC(insn,fname,almask) \
1022 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
1024 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL); \
1025 int l1 = gen_new_label(); \
1026 int l2 = gen_new_label(); \
1027 int l3 = gen_new_label(); \
1029 tcg_gen_andi_tl(r_tmp, t0, almask); \
1030 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1); \
1031 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
1032 generate_exception(ctx, EXCP_AdES); \
1033 gen_set_label(l1); \
1034 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
1035 tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2); \
1036 tcg_temp_free(r_tmp); \
1037 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
1038 tcg_gen_movi_tl(t0, 1); \
1039 tcg_gen_br(l3); \
1040 gen_set_label(l2); \
1041 tcg_gen_movi_tl(t0, 0); \
1042 gen_set_label(l3); \
1044 OP_ST_ATOMIC(sc,st32,0x3);
1045 #if defined(TARGET_MIPS64)
1046 OP_ST_ATOMIC(scd,st64,0x7);
1047 #endif
1048 #undef OP_ST_ATOMIC
1050 /* Load and store */
1051 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1052 int base, int16_t offset)
1054 const char *opn = "ldst";
1055 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1056 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1058 if (base == 0) {
1059 tcg_gen_movi_tl(t0, offset);
1060 } else if (offset == 0) {
1061 gen_load_gpr(t0, base);
1062 } else {
1063 gen_load_gpr(t0, base);
1064 tcg_gen_movi_tl(t1, offset);
1065 gen_op_addr_add(t0, t1);
1067 /* Don't do NOP if destination is zero: we must perform the actual
1068 memory access. */
1069 switch (opc) {
1070 #if defined(TARGET_MIPS64)
1071 case OPC_LWU:
1072 op_ldst_lwu(t0, ctx);
1073 gen_store_gpr(t0, rt);
1074 opn = "lwu";
1075 break;
1076 case OPC_LD:
1077 op_ldst_ld(t0, ctx);
1078 gen_store_gpr(t0, rt);
1079 opn = "ld";
1080 break;
1081 case OPC_LLD:
1082 op_ldst_lld(t0, t1, ctx);
1083 gen_store_gpr(t0, rt);
1084 opn = "lld";
1085 break;
1086 case OPC_SD:
1087 gen_load_gpr(t1, rt);
1088 op_ldst_sd(t0, t1, ctx);
1089 opn = "sd";
1090 break;
1091 case OPC_SCD:
1092 save_cpu_state(ctx, 1);
1093 gen_load_gpr(t1, rt);
1094 op_ldst_scd(t0, t1, ctx);
1095 gen_store_gpr(t0, rt);
1096 opn = "scd";
1097 break;
1098 case OPC_LDL:
1099 save_cpu_state(ctx, 1);
1100 gen_load_gpr(t1, rt);
1101 tcg_gen_helper_1_2i(do_ldl, t1, t0, t1, ctx->mem_idx);
1102 gen_store_gpr(t1, rt);
1103 opn = "ldl";
1104 break;
1105 case OPC_SDL:
1106 save_cpu_state(ctx, 1);
1107 gen_load_gpr(t1, rt);
1108 tcg_gen_helper_0_2i(do_sdl, t0, t1, ctx->mem_idx);
1109 opn = "sdl";
1110 break;
1111 case OPC_LDR:
1112 save_cpu_state(ctx, 1);
1113 gen_load_gpr(t1, rt);
1114 tcg_gen_helper_1_2i(do_ldr, t1, t0, t1, ctx->mem_idx);
1115 gen_store_gpr(t1, rt);
1116 opn = "ldr";
1117 break;
1118 case OPC_SDR:
1119 save_cpu_state(ctx, 1);
1120 gen_load_gpr(t1, rt);
1121 tcg_gen_helper_0_2i(do_sdr, t0, t1, ctx->mem_idx);
1122 opn = "sdr";
1123 break;
1124 #endif
1125 case OPC_LW:
1126 op_ldst_lw(t0, ctx);
1127 gen_store_gpr(t0, rt);
1128 opn = "lw";
1129 break;
1130 case OPC_SW:
1131 gen_load_gpr(t1, rt);
1132 op_ldst_sw(t0, t1, ctx);
1133 opn = "sw";
1134 break;
1135 case OPC_LH:
1136 op_ldst_lh(t0, ctx);
1137 gen_store_gpr(t0, rt);
1138 opn = "lh";
1139 break;
1140 case OPC_SH:
1141 gen_load_gpr(t1, rt);
1142 op_ldst_sh(t0, t1, ctx);
1143 opn = "sh";
1144 break;
1145 case OPC_LHU:
1146 op_ldst_lhu(t0, ctx);
1147 gen_store_gpr(t0, rt);
1148 opn = "lhu";
1149 break;
1150 case OPC_LB:
1151 op_ldst_lb(t0, ctx);
1152 gen_store_gpr(t0, rt);
1153 opn = "lb";
1154 break;
1155 case OPC_SB:
1156 gen_load_gpr(t1, rt);
1157 op_ldst_sb(t0, t1, ctx);
1158 opn = "sb";
1159 break;
1160 case OPC_LBU:
1161 op_ldst_lbu(t0, ctx);
1162 gen_store_gpr(t0, rt);
1163 opn = "lbu";
1164 break;
1165 case OPC_LWL:
1166 save_cpu_state(ctx, 1);
1167 gen_load_gpr(t1, rt);
1168 tcg_gen_helper_1_2i(do_lwl, t1, t0, t1, ctx->mem_idx);
1169 gen_store_gpr(t1, rt);
1170 opn = "lwl";
1171 break;
1172 case OPC_SWL:
1173 save_cpu_state(ctx, 1);
1174 gen_load_gpr(t1, rt);
1175 tcg_gen_helper_0_2i(do_swl, t0, t1, ctx->mem_idx);
1176 opn = "swr";
1177 break;
1178 case OPC_LWR:
1179 save_cpu_state(ctx, 1);
1180 gen_load_gpr(t1, rt);
1181 tcg_gen_helper_1_2i(do_lwr, t1, t0, t1, ctx->mem_idx);
1182 gen_store_gpr(t1, rt);
1183 opn = "lwr";
1184 break;
1185 case OPC_SWR:
1186 save_cpu_state(ctx, 1);
1187 gen_load_gpr(t1, rt);
1188 tcg_gen_helper_0_2i(do_swr, t0, t1, ctx->mem_idx);
1189 opn = "swr";
1190 break;
1191 case OPC_LL:
1192 op_ldst_ll(t0, t1, ctx);
1193 gen_store_gpr(t0, rt);
1194 opn = "ll";
1195 break;
1196 case OPC_SC:
1197 save_cpu_state(ctx, 1);
1198 gen_load_gpr(t1, rt);
1199 op_ldst_sc(t0, t1, ctx);
1200 gen_store_gpr(t0, rt);
1201 opn = "sc";
1202 break;
1203 default:
1204 MIPS_INVAL(opn);
1205 generate_exception(ctx, EXCP_RI);
1206 goto out;
1208 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1209 out:
1210 tcg_temp_free(t0);
1211 tcg_temp_free(t1);
1214 /* Load and store */
1215 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1216 int base, int16_t offset)
1218 const char *opn = "flt_ldst";
1219 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1221 if (base == 0) {
1222 tcg_gen_movi_tl(t0, offset);
1223 } else if (offset == 0) {
1224 gen_load_gpr(t0, base);
1225 } else {
1226 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1228 gen_load_gpr(t0, base);
1229 tcg_gen_movi_tl(t1, offset);
1230 gen_op_addr_add(t0, t1);
1231 tcg_temp_free(t1);
1233 /* Don't do NOP if destination is zero: we must perform the actual
1234 memory access. */
1235 switch (opc) {
1236 case OPC_LWC1:
1238 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
1240 tcg_gen_qemu_ld32s(fp0, t0, ctx->mem_idx);
1241 gen_store_fpr32(fp0, ft);
1242 tcg_temp_free(fp0);
1244 opn = "lwc1";
1245 break;
1246 case OPC_SWC1:
1248 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
1250 gen_load_fpr32(fp0, ft);
1251 tcg_gen_qemu_st32(fp0, t0, ctx->mem_idx);
1252 tcg_temp_free(fp0);
1254 opn = "swc1";
1255 break;
1256 case OPC_LDC1:
1258 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
1260 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1261 gen_store_fpr64(ctx, fp0, ft);
1262 tcg_temp_free(fp0);
1264 opn = "ldc1";
1265 break;
1266 case OPC_SDC1:
1268 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
1270 gen_load_fpr64(ctx, fp0, ft);
1271 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1272 tcg_temp_free(fp0);
1274 opn = "sdc1";
1275 break;
1276 default:
1277 MIPS_INVAL(opn);
1278 generate_exception(ctx, EXCP_RI);
1279 goto out;
1281 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1282 out:
1283 tcg_temp_free(t0);
1286 /* Arithmetic with immediate operand */
1287 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1288 int rt, int rs, int16_t imm)
1290 target_ulong uimm;
1291 const char *opn = "imm arith";
1292 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1294 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1295 /* If no destination, treat it as a NOP.
1296 For addi, we must generate the overflow exception when needed. */
1297 MIPS_DEBUG("NOP");
1298 goto out;
1300 uimm = (uint16_t)imm;
1301 switch (opc) {
1302 case OPC_ADDI:
1303 case OPC_ADDIU:
1304 #if defined(TARGET_MIPS64)
1305 case OPC_DADDI:
1306 case OPC_DADDIU:
1307 #endif
1308 case OPC_SLTI:
1309 case OPC_SLTIU:
1310 uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1311 /* Fall through. */
1312 case OPC_ANDI:
1313 case OPC_ORI:
1314 case OPC_XORI:
1315 gen_load_gpr(t0, rs);
1316 break;
1317 case OPC_LUI:
1318 tcg_gen_movi_tl(t0, imm << 16);
1319 break;
1320 case OPC_SLL:
1321 case OPC_SRA:
1322 case OPC_SRL:
1323 #if defined(TARGET_MIPS64)
1324 case OPC_DSLL:
1325 case OPC_DSRA:
1326 case OPC_DSRL:
1327 case OPC_DSLL32:
1328 case OPC_DSRA32:
1329 case OPC_DSRL32:
1330 #endif
1331 uimm &= 0x1f;
1332 gen_load_gpr(t0, rs);
1333 break;
1335 switch (opc) {
1336 case OPC_ADDI:
1338 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1339 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1340 int l1 = gen_new_label();
1342 save_cpu_state(ctx, 1);
1343 tcg_gen_ext32s_tl(r_tmp1, t0);
1344 tcg_gen_addi_tl(t0, r_tmp1, uimm);
1346 tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
1347 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1348 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1349 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1350 tcg_temp_free(r_tmp2);
1351 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1352 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1353 tcg_temp_free(r_tmp1);
1354 /* operands of same sign, result different sign */
1355 generate_exception(ctx, EXCP_OVERFLOW);
1356 gen_set_label(l1);
1358 tcg_gen_ext32s_tl(t0, t0);
1360 opn = "addi";
1361 break;
1362 case OPC_ADDIU:
1363 tcg_gen_ext32s_tl(t0, t0);
1364 tcg_gen_addi_tl(t0, t0, uimm);
1365 tcg_gen_ext32s_tl(t0, t0);
1366 opn = "addiu";
1367 break;
1368 #if defined(TARGET_MIPS64)
1369 case OPC_DADDI:
1371 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1372 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1373 int l1 = gen_new_label();
1375 save_cpu_state(ctx, 1);
1376 tcg_gen_mov_tl(r_tmp1, t0);
1377 tcg_gen_addi_tl(t0, t0, uimm);
1379 tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
1380 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1381 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1382 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1383 tcg_temp_free(r_tmp2);
1384 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1385 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1386 tcg_temp_free(r_tmp1);
1387 /* operands of same sign, result different sign */
1388 generate_exception(ctx, EXCP_OVERFLOW);
1389 gen_set_label(l1);
1391 opn = "daddi";
1392 break;
1393 case OPC_DADDIU:
1394 tcg_gen_addi_tl(t0, t0, uimm);
1395 opn = "daddiu";
1396 break;
1397 #endif
1398 case OPC_SLTI:
1399 gen_op_lti(t0, uimm);
1400 opn = "slti";
1401 break;
1402 case OPC_SLTIU:
1403 gen_op_ltiu(t0, uimm);
1404 opn = "sltiu";
1405 break;
1406 case OPC_ANDI:
1407 tcg_gen_andi_tl(t0, t0, uimm);
1408 opn = "andi";
1409 break;
1410 case OPC_ORI:
1411 tcg_gen_ori_tl(t0, t0, uimm);
1412 opn = "ori";
1413 break;
1414 case OPC_XORI:
1415 tcg_gen_xori_tl(t0, t0, uimm);
1416 opn = "xori";
1417 break;
1418 case OPC_LUI:
1419 opn = "lui";
1420 break;
1421 case OPC_SLL:
1422 tcg_gen_ext32u_tl(t0, t0);
1423 tcg_gen_shli_tl(t0, t0, uimm);
1424 tcg_gen_ext32s_tl(t0, t0);
1425 opn = "sll";
1426 break;
1427 case OPC_SRA:
1428 tcg_gen_ext32s_tl(t0, t0);
1429 tcg_gen_sari_tl(t0, t0, uimm);
1430 tcg_gen_ext32s_tl(t0, t0);
1431 opn = "sra";
1432 break;
1433 case OPC_SRL:
1434 switch ((ctx->opcode >> 21) & 0x1f) {
1435 case 0:
1436 tcg_gen_ext32u_tl(t0, t0);
1437 tcg_gen_shri_tl(t0, t0, uimm);
1438 tcg_gen_ext32s_tl(t0, t0);
1439 opn = "srl";
1440 break;
1441 case 1:
1442 /* rotr is decoded as srl on non-R2 CPUs */
1443 if (env->insn_flags & ISA_MIPS32R2) {
1444 if (uimm != 0) {
1445 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1446 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1448 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1449 tcg_gen_movi_i32(r_tmp2, 0x20);
1450 tcg_gen_subi_i32(r_tmp2, r_tmp2, uimm);
1451 tcg_gen_shl_i32(r_tmp2, r_tmp1, r_tmp2);
1452 tcg_gen_shri_i32(r_tmp1, r_tmp1, uimm);
1453 tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp2);
1454 tcg_gen_ext_i32_tl(t0, r_tmp1);
1455 tcg_temp_free(r_tmp1);
1456 tcg_temp_free(r_tmp2);
1458 opn = "rotr";
1459 } else {
1460 tcg_gen_ext32u_tl(t0, t0);
1461 tcg_gen_shri_tl(t0, t0, uimm);
1462 tcg_gen_ext32s_tl(t0, t0);
1463 opn = "srl";
1465 break;
1466 default:
1467 MIPS_INVAL("invalid srl flag");
1468 generate_exception(ctx, EXCP_RI);
1469 break;
1471 break;
1472 #if defined(TARGET_MIPS64)
1473 case OPC_DSLL:
1474 tcg_gen_shli_tl(t0, t0, uimm);
1475 opn = "dsll";
1476 break;
1477 case OPC_DSRA:
1478 tcg_gen_sari_tl(t0, t0, uimm);
1479 opn = "dsra";
1480 break;
1481 case OPC_DSRL:
1482 switch ((ctx->opcode >> 21) & 0x1f) {
1483 case 0:
1484 tcg_gen_shri_tl(t0, t0, uimm);
1485 opn = "dsrl";
1486 break;
1487 case 1:
1488 /* drotr is decoded as dsrl on non-R2 CPUs */
1489 if (env->insn_flags & ISA_MIPS32R2) {
1490 if (uimm != 0) {
1491 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1493 tcg_gen_movi_tl(r_tmp1, 0x40);
1494 tcg_gen_subi_tl(r_tmp1, r_tmp1, uimm);
1495 tcg_gen_shl_tl(r_tmp1, t0, r_tmp1);
1496 tcg_gen_shri_tl(t0, t0, uimm);
1497 tcg_gen_or_tl(t0, t0, r_tmp1);
1498 tcg_temp_free(r_tmp1);
1500 opn = "drotr";
1501 } else {
1502 tcg_gen_shri_tl(t0, t0, uimm);
1503 opn = "dsrl";
1505 break;
1506 default:
1507 MIPS_INVAL("invalid dsrl flag");
1508 generate_exception(ctx, EXCP_RI);
1509 break;
1511 break;
1512 case OPC_DSLL32:
1513 tcg_gen_shli_tl(t0, t0, uimm + 32);
1514 opn = "dsll32";
1515 break;
1516 case OPC_DSRA32:
1517 tcg_gen_sari_tl(t0, t0, uimm + 32);
1518 opn = "dsra32";
1519 break;
1520 case OPC_DSRL32:
1521 switch ((ctx->opcode >> 21) & 0x1f) {
1522 case 0:
1523 tcg_gen_shri_tl(t0, t0, uimm + 32);
1524 opn = "dsrl32";
1525 break;
1526 case 1:
1527 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1528 if (env->insn_flags & ISA_MIPS32R2) {
1529 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1530 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1532 tcg_gen_movi_tl(r_tmp1, 0x40);
1533 tcg_gen_movi_tl(r_tmp2, 32);
1534 tcg_gen_addi_tl(r_tmp2, r_tmp2, uimm);
1535 tcg_gen_sub_tl(r_tmp1, r_tmp1, r_tmp2);
1536 tcg_gen_shl_tl(r_tmp1, t0, r_tmp1);
1537 tcg_gen_shr_tl(t0, t0, r_tmp2);
1538 tcg_gen_or_tl(t0, t0, r_tmp1);
1539 tcg_temp_free(r_tmp1);
1540 tcg_temp_free(r_tmp2);
1541 opn = "drotr32";
1542 } else {
1543 tcg_gen_shri_tl(t0, t0, uimm + 32);
1544 opn = "dsrl32";
1546 break;
1547 default:
1548 MIPS_INVAL("invalid dsrl32 flag");
1549 generate_exception(ctx, EXCP_RI);
1550 break;
1552 break;
1553 #endif
1554 default:
1555 MIPS_INVAL(opn);
1556 generate_exception(ctx, EXCP_RI);
1557 goto out;
1559 gen_store_gpr(t0, rt);
1560 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1561 out:
1562 tcg_temp_free(t0);
1565 /* Arithmetic */
1566 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1567 int rd, int rs, int rt)
1569 const char *opn = "arith";
1570 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1571 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1573 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1574 && opc != OPC_DADD && opc != OPC_DSUB) {
1575 /* If no destination, treat it as a NOP.
1576 For add & sub, we must generate the overflow exception when needed. */
1577 MIPS_DEBUG("NOP");
1578 goto out;
1580 gen_load_gpr(t0, rs);
1581 /* Specialcase the conventional move operation. */
1582 if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1583 || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1584 gen_store_gpr(t0, rd);
1585 goto out;
1587 gen_load_gpr(t1, rt);
1588 switch (opc) {
1589 case OPC_ADD:
1591 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1592 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1593 int l1 = gen_new_label();
1595 save_cpu_state(ctx, 1);
1596 tcg_gen_ext32s_tl(r_tmp1, t0);
1597 tcg_gen_ext32s_tl(r_tmp2, t1);
1598 tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
1600 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1601 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1602 tcg_gen_xor_tl(r_tmp2, t0, t1);
1603 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1604 tcg_temp_free(r_tmp2);
1605 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1606 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1607 tcg_temp_free(r_tmp1);
1608 /* operands of same sign, result different sign */
1609 generate_exception(ctx, EXCP_OVERFLOW);
1610 gen_set_label(l1);
1612 tcg_gen_ext32s_tl(t0, t0);
1614 opn = "add";
1615 break;
1616 case OPC_ADDU:
1617 tcg_gen_ext32s_tl(t0, t0);
1618 tcg_gen_ext32s_tl(t1, t1);
1619 tcg_gen_add_tl(t0, t0, t1);
1620 tcg_gen_ext32s_tl(t0, t0);
1621 opn = "addu";
1622 break;
1623 case OPC_SUB:
1625 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1626 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1627 int l1 = gen_new_label();
1629 save_cpu_state(ctx, 1);
1630 tcg_gen_ext32s_tl(r_tmp1, t0);
1631 tcg_gen_ext32s_tl(r_tmp2, t1);
1632 tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
1634 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1635 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1636 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1637 tcg_temp_free(r_tmp2);
1638 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1639 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1640 tcg_temp_free(r_tmp1);
1641 /* operands of different sign, first operand and result different sign */
1642 generate_exception(ctx, EXCP_OVERFLOW);
1643 gen_set_label(l1);
1645 tcg_gen_ext32s_tl(t0, t0);
1647 opn = "sub";
1648 break;
1649 case OPC_SUBU:
1650 tcg_gen_ext32s_tl(t0, t0);
1651 tcg_gen_ext32s_tl(t1, t1);
1652 tcg_gen_sub_tl(t0, t0, t1);
1653 tcg_gen_ext32s_tl(t0, t0);
1654 opn = "subu";
1655 break;
1656 #if defined(TARGET_MIPS64)
1657 case OPC_DADD:
1659 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1660 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1661 int l1 = gen_new_label();
1663 save_cpu_state(ctx, 1);
1664 tcg_gen_mov_tl(r_tmp1, t0);
1665 tcg_gen_add_tl(t0, t0, t1);
1667 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1668 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1669 tcg_gen_xor_tl(r_tmp2, t0, t1);
1670 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1671 tcg_temp_free(r_tmp2);
1672 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1673 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1674 tcg_temp_free(r_tmp1);
1675 /* operands of same sign, result different sign */
1676 generate_exception(ctx, EXCP_OVERFLOW);
1677 gen_set_label(l1);
1679 opn = "dadd";
1680 break;
1681 case OPC_DADDU:
1682 tcg_gen_add_tl(t0, t0, t1);
1683 opn = "daddu";
1684 break;
1685 case OPC_DSUB:
1687 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1688 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1689 int l1 = gen_new_label();
1691 save_cpu_state(ctx, 1);
1692 tcg_gen_mov_tl(r_tmp1, t0);
1693 tcg_gen_sub_tl(t0, t0, t1);
1695 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1696 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1697 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1698 tcg_temp_free(r_tmp2);
1699 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1700 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1701 tcg_temp_free(r_tmp1);
1702 /* operands of different sign, first operand and result different sign */
1703 generate_exception(ctx, EXCP_OVERFLOW);
1704 gen_set_label(l1);
1706 opn = "dsub";
1707 break;
1708 case OPC_DSUBU:
1709 tcg_gen_sub_tl(t0, t0, t1);
1710 opn = "dsubu";
1711 break;
1712 #endif
1713 case OPC_SLT:
1714 gen_op_lt(t0, t1);
1715 opn = "slt";
1716 break;
1717 case OPC_SLTU:
1718 gen_op_ltu(t0, t1);
1719 opn = "sltu";
1720 break;
1721 case OPC_AND:
1722 tcg_gen_and_tl(t0, t0, t1);
1723 opn = "and";
1724 break;
1725 case OPC_NOR:
1726 tcg_gen_or_tl(t0, t0, t1);
1727 tcg_gen_not_tl(t0, t0);
1728 opn = "nor";
1729 break;
1730 case OPC_OR:
1731 tcg_gen_or_tl(t0, t0, t1);
1732 opn = "or";
1733 break;
1734 case OPC_XOR:
1735 tcg_gen_xor_tl(t0, t0, t1);
1736 opn = "xor";
1737 break;
1738 case OPC_MUL:
1739 tcg_gen_ext32s_tl(t0, t0);
1740 tcg_gen_ext32s_tl(t1, t1);
1741 tcg_gen_mul_tl(t0, t0, t1);
1742 tcg_gen_ext32s_tl(t0, t0);
1743 opn = "mul";
1744 break;
1745 case OPC_MOVN:
1747 int l1 = gen_new_label();
1749 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1750 gen_store_gpr(t0, rd);
1751 gen_set_label(l1);
1753 opn = "movn";
1754 goto print;
1755 case OPC_MOVZ:
1757 int l1 = gen_new_label();
1759 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
1760 gen_store_gpr(t0, rd);
1761 gen_set_label(l1);
1763 opn = "movz";
1764 goto print;
1765 case OPC_SLLV:
1766 tcg_gen_ext32u_tl(t0, t0);
1767 tcg_gen_ext32u_tl(t1, t1);
1768 tcg_gen_andi_tl(t0, t0, 0x1f);
1769 tcg_gen_shl_tl(t0, t1, t0);
1770 tcg_gen_ext32s_tl(t0, t0);
1771 opn = "sllv";
1772 break;
1773 case OPC_SRAV:
1774 tcg_gen_ext32s_tl(t1, t1);
1775 tcg_gen_andi_tl(t0, t0, 0x1f);
1776 tcg_gen_sar_tl(t0, t1, t0);
1777 tcg_gen_ext32s_tl(t0, t0);
1778 opn = "srav";
1779 break;
1780 case OPC_SRLV:
1781 switch ((ctx->opcode >> 6) & 0x1f) {
1782 case 0:
1783 tcg_gen_ext32u_tl(t1, t1);
1784 tcg_gen_andi_tl(t0, t0, 0x1f);
1785 tcg_gen_shr_tl(t0, t1, t0);
1786 tcg_gen_ext32s_tl(t0, t0);
1787 opn = "srlv";
1788 break;
1789 case 1:
1790 /* rotrv is decoded as srlv on non-R2 CPUs */
1791 if (env->insn_flags & ISA_MIPS32R2) {
1792 int l1 = gen_new_label();
1793 int l2 = gen_new_label();
1795 tcg_gen_andi_tl(t0, t0, 0x1f);
1796 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1798 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1799 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1800 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
1802 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1803 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1804 tcg_gen_movi_i32(r_tmp3, 0x20);
1805 tcg_gen_sub_i32(r_tmp3, r_tmp3, r_tmp1);
1806 tcg_gen_shl_i32(r_tmp3, r_tmp2, r_tmp3);
1807 tcg_gen_shr_i32(r_tmp1, r_tmp2, r_tmp1);
1808 tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp3);
1809 tcg_gen_ext_i32_tl(t0, r_tmp1);
1810 tcg_temp_free(r_tmp1);
1811 tcg_temp_free(r_tmp2);
1812 tcg_temp_free(r_tmp3);
1813 tcg_gen_br(l2);
1815 gen_set_label(l1);
1816 tcg_gen_mov_tl(t0, t1);
1817 gen_set_label(l2);
1818 opn = "rotrv";
1819 } else {
1820 tcg_gen_ext32u_tl(t1, t1);
1821 tcg_gen_andi_tl(t0, t0, 0x1f);
1822 tcg_gen_shr_tl(t0, t1, t0);
1823 tcg_gen_ext32s_tl(t0, t0);
1824 opn = "srlv";
1826 break;
1827 default:
1828 MIPS_INVAL("invalid srlv flag");
1829 generate_exception(ctx, EXCP_RI);
1830 break;
1832 break;
1833 #if defined(TARGET_MIPS64)
1834 case OPC_DSLLV:
1835 tcg_gen_andi_tl(t0, t0, 0x3f);
1836 tcg_gen_shl_tl(t0, t1, t0);
1837 opn = "dsllv";
1838 break;
1839 case OPC_DSRAV:
1840 tcg_gen_andi_tl(t0, t0, 0x3f);
1841 tcg_gen_sar_tl(t0, t1, t0);
1842 opn = "dsrav";
1843 break;
1844 case OPC_DSRLV:
1845 switch ((ctx->opcode >> 6) & 0x1f) {
1846 case 0:
1847 tcg_gen_andi_tl(t0, t0, 0x3f);
1848 tcg_gen_shr_tl(t0, t1, t0);
1849 opn = "dsrlv";
1850 break;
1851 case 1:
1852 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1853 if (env->insn_flags & ISA_MIPS32R2) {
1854 int l1 = gen_new_label();
1855 int l2 = gen_new_label();
1857 tcg_gen_andi_tl(t0, t0, 0x3f);
1858 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1860 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1862 tcg_gen_movi_tl(r_tmp1, 0x40);
1863 tcg_gen_sub_tl(r_tmp1, r_tmp1, t0);
1864 tcg_gen_shl_tl(r_tmp1, t1, r_tmp1);
1865 tcg_gen_shr_tl(t0, t1, t0);
1866 tcg_gen_or_tl(t0, t0, r_tmp1);
1867 tcg_temp_free(r_tmp1);
1868 tcg_gen_br(l2);
1870 gen_set_label(l1);
1871 tcg_gen_mov_tl(t0, t1);
1872 gen_set_label(l2);
1873 opn = "drotrv";
1874 } else {
1875 tcg_gen_andi_tl(t0, t0, 0x3f);
1876 tcg_gen_shr_tl(t0, t1, t0);
1877 opn = "dsrlv";
1879 break;
1880 default:
1881 MIPS_INVAL("invalid dsrlv flag");
1882 generate_exception(ctx, EXCP_RI);
1883 break;
1885 break;
1886 #endif
1887 default:
1888 MIPS_INVAL(opn);
1889 generate_exception(ctx, EXCP_RI);
1890 goto out;
1892 gen_store_gpr(t0, rd);
1893 print:
1894 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1895 out:
1896 tcg_temp_free(t0);
1897 tcg_temp_free(t1);
1900 /* Arithmetic on HI/LO registers */
1901 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1903 const char *opn = "hilo";
1904 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1906 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1907 /* Treat as NOP. */
1908 MIPS_DEBUG("NOP");
1909 goto out;
1911 switch (opc) {
1912 case OPC_MFHI:
1913 gen_load_HI(t0, 0);
1914 gen_store_gpr(t0, reg);
1915 opn = "mfhi";
1916 break;
1917 case OPC_MFLO:
1918 gen_load_LO(t0, 0);
1919 gen_store_gpr(t0, reg);
1920 opn = "mflo";
1921 break;
1922 case OPC_MTHI:
1923 gen_load_gpr(t0, reg);
1924 gen_store_HI(t0, 0);
1925 opn = "mthi";
1926 break;
1927 case OPC_MTLO:
1928 gen_load_gpr(t0, reg);
1929 gen_store_LO(t0, 0);
1930 opn = "mtlo";
1931 break;
1932 default:
1933 MIPS_INVAL(opn);
1934 generate_exception(ctx, EXCP_RI);
1935 goto out;
1937 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1938 out:
1939 tcg_temp_free(t0);
1942 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1943 int rs, int rt)
1945 const char *opn = "mul/div";
1946 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1947 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1949 gen_load_gpr(t0, rs);
1950 gen_load_gpr(t1, rt);
1951 switch (opc) {
1952 case OPC_DIV:
1954 int l1 = gen_new_label();
1956 tcg_gen_ext32s_tl(t0, t0);
1957 tcg_gen_ext32s_tl(t1, t1);
1958 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1960 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
1961 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
1962 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
1964 tcg_gen_ext_tl_i64(r_tmp1, t0);
1965 tcg_gen_ext_tl_i64(r_tmp2, t1);
1966 tcg_gen_div_i64(r_tmp3, r_tmp1, r_tmp2);
1967 tcg_gen_rem_i64(r_tmp2, r_tmp1, r_tmp2);
1968 tcg_gen_trunc_i64_tl(t0, r_tmp3);
1969 tcg_gen_trunc_i64_tl(t1, r_tmp2);
1970 tcg_temp_free(r_tmp1);
1971 tcg_temp_free(r_tmp2);
1972 tcg_temp_free(r_tmp3);
1973 tcg_gen_ext32s_tl(t0, t0);
1974 tcg_gen_ext32s_tl(t1, t1);
1975 gen_store_LO(t0, 0);
1976 gen_store_HI(t1, 0);
1978 gen_set_label(l1);
1980 opn = "div";
1981 break;
1982 case OPC_DIVU:
1984 int l1 = gen_new_label();
1986 tcg_gen_ext32s_tl(t1, t1);
1987 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1989 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1990 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1991 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
1993 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1994 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1995 tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2);
1996 tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2);
1997 tcg_gen_ext_i32_tl(t0, r_tmp3);
1998 tcg_gen_ext_i32_tl(t1, r_tmp1);
1999 tcg_temp_free(r_tmp1);
2000 tcg_temp_free(r_tmp2);
2001 tcg_temp_free(r_tmp3);
2002 gen_store_LO(t0, 0);
2003 gen_store_HI(t1, 0);
2005 gen_set_label(l1);
2007 opn = "divu";
2008 break;
2009 case OPC_MULT:
2011 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2012 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2014 tcg_gen_ext32s_tl(t0, t0);
2015 tcg_gen_ext32s_tl(t1, t1);
2016 tcg_gen_ext_tl_i64(r_tmp1, t0);
2017 tcg_gen_ext_tl_i64(r_tmp2, t1);
2018 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2019 tcg_temp_free(r_tmp2);
2020 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2021 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2022 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2023 tcg_temp_free(r_tmp1);
2024 tcg_gen_ext32s_tl(t0, t0);
2025 tcg_gen_ext32s_tl(t1, t1);
2026 gen_store_LO(t0, 0);
2027 gen_store_HI(t1, 0);
2029 opn = "mult";
2030 break;
2031 case OPC_MULTU:
2033 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2034 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2036 tcg_gen_ext32u_tl(t0, t0);
2037 tcg_gen_ext32u_tl(t1, t1);
2038 tcg_gen_extu_tl_i64(r_tmp1, t0);
2039 tcg_gen_extu_tl_i64(r_tmp2, t1);
2040 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2041 tcg_temp_free(r_tmp2);
2042 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2043 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2044 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2045 tcg_temp_free(r_tmp1);
2046 tcg_gen_ext32s_tl(t0, t0);
2047 tcg_gen_ext32s_tl(t1, t1);
2048 gen_store_LO(t0, 0);
2049 gen_store_HI(t1, 0);
2051 opn = "multu";
2052 break;
2053 #if defined(TARGET_MIPS64)
2054 case OPC_DDIV:
2056 int l1 = gen_new_label();
2058 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2060 int l2 = gen_new_label();
2062 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2063 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2065 tcg_gen_movi_tl(t1, 0);
2066 gen_store_LO(t0, 0);
2067 gen_store_HI(t1, 0);
2068 tcg_gen_br(l1);
2070 gen_set_label(l2);
2072 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2073 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2075 tcg_gen_div_i64(r_tmp1, t0, t1);
2076 tcg_gen_rem_i64(r_tmp2, t0, t1);
2077 gen_store_LO(r_tmp1, 0);
2078 gen_store_HI(r_tmp2, 0);
2079 tcg_temp_free(r_tmp1);
2080 tcg_temp_free(r_tmp2);
2083 gen_set_label(l1);
2085 opn = "ddiv";
2086 break;
2087 case OPC_DDIVU:
2089 int l1 = gen_new_label();
2091 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2093 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2094 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2096 tcg_gen_divu_i64(r_tmp1, t0, t1);
2097 tcg_gen_remu_i64(r_tmp2, t0, t1);
2098 tcg_temp_free(r_tmp1);
2099 tcg_temp_free(r_tmp2);
2100 gen_store_LO(r_tmp1, 0);
2101 gen_store_HI(r_tmp2, 0);
2103 gen_set_label(l1);
2105 opn = "ddivu";
2106 break;
2107 case OPC_DMULT:
2108 tcg_gen_helper_0_2(do_dmult, t0, t1);
2109 opn = "dmult";
2110 break;
2111 case OPC_DMULTU:
2112 tcg_gen_helper_0_2(do_dmultu, t0, t1);
2113 opn = "dmultu";
2114 break;
2115 #endif
2116 case OPC_MADD:
2118 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2119 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2120 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
2122 tcg_gen_ext32s_tl(t0, t0);
2123 tcg_gen_ext32s_tl(t1, t1);
2124 tcg_gen_ext_tl_i64(r_tmp1, t0);
2125 tcg_gen_ext_tl_i64(r_tmp2, t1);
2126 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2127 gen_load_LO(t0, 0);
2128 gen_load_HI(t1, 0);
2129 tcg_gen_extu_tl_i64(r_tmp2, t0);
2130 tcg_gen_extu_tl_i64(r_tmp3, t1);
2131 tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
2132 tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
2133 tcg_temp_free(r_tmp3);
2134 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
2135 tcg_temp_free(r_tmp2);
2136 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2137 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2138 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2139 tcg_temp_free(r_tmp1);
2140 tcg_gen_ext32s_tl(t0, t0);
2141 tcg_gen_ext32s_tl(t1, t1);
2142 gen_store_LO(t0, 0);
2143 gen_store_HI(t1, 0);
2145 opn = "madd";
2146 break;
2147 case OPC_MADDU:
2149 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2150 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2151 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
2153 tcg_gen_ext32u_tl(t0, t0);
2154 tcg_gen_ext32u_tl(t1, t1);
2155 tcg_gen_extu_tl_i64(r_tmp1, t0);
2156 tcg_gen_extu_tl_i64(r_tmp2, t1);
2157 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2158 gen_load_LO(t0, 0);
2159 gen_load_HI(t1, 0);
2160 tcg_gen_extu_tl_i64(r_tmp2, t0);
2161 tcg_gen_extu_tl_i64(r_tmp3, t1);
2162 tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
2163 tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
2164 tcg_temp_free(r_tmp3);
2165 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
2166 tcg_temp_free(r_tmp2);
2167 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2168 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2169 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2170 tcg_temp_free(r_tmp1);
2171 tcg_gen_ext32s_tl(t0, t0);
2172 tcg_gen_ext32s_tl(t1, t1);
2173 gen_store_LO(t0, 0);
2174 gen_store_HI(t1, 0);
2176 opn = "maddu";
2177 break;
2178 case OPC_MSUB:
2180 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2181 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2182 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
2184 tcg_gen_ext32s_tl(t0, t0);
2185 tcg_gen_ext32s_tl(t1, t1);
2186 tcg_gen_ext_tl_i64(r_tmp1, t0);
2187 tcg_gen_ext_tl_i64(r_tmp2, t1);
2188 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2189 gen_load_LO(t0, 0);
2190 gen_load_HI(t1, 0);
2191 tcg_gen_extu_tl_i64(r_tmp2, t0);
2192 tcg_gen_extu_tl_i64(r_tmp3, t1);
2193 tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
2194 tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
2195 tcg_temp_free(r_tmp3);
2196 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
2197 tcg_temp_free(r_tmp2);
2198 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2199 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2200 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2201 tcg_temp_free(r_tmp1);
2202 tcg_gen_ext32s_tl(t0, t0);
2203 tcg_gen_ext32s_tl(t1, t1);
2204 gen_store_LO(t0, 0);
2205 gen_store_HI(t1, 0);
2207 opn = "msub";
2208 break;
2209 case OPC_MSUBU:
2211 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2212 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2213 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
2215 tcg_gen_ext32u_tl(t0, t0);
2216 tcg_gen_ext32u_tl(t1, t1);
2217 tcg_gen_extu_tl_i64(r_tmp1, t0);
2218 tcg_gen_extu_tl_i64(r_tmp2, t1);
2219 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2220 gen_load_LO(t0, 0);
2221 gen_load_HI(t1, 0);
2222 tcg_gen_extu_tl_i64(r_tmp2, t0);
2223 tcg_gen_extu_tl_i64(r_tmp3, t1);
2224 tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
2225 tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
2226 tcg_temp_free(r_tmp3);
2227 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
2228 tcg_temp_free(r_tmp2);
2229 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2230 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2231 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2232 tcg_temp_free(r_tmp1);
2233 tcg_gen_ext32s_tl(t0, t0);
2234 tcg_gen_ext32s_tl(t1, t1);
2235 gen_store_LO(t0, 0);
2236 gen_store_HI(t1, 0);
2238 opn = "msubu";
2239 break;
2240 default:
2241 MIPS_INVAL(opn);
2242 generate_exception(ctx, EXCP_RI);
2243 goto out;
2245 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2246 out:
2247 tcg_temp_free(t0);
2248 tcg_temp_free(t1);
2251 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2252 int rd, int rs, int rt)
2254 const char *opn = "mul vr54xx";
2255 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2256 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2258 gen_load_gpr(t0, rs);
2259 gen_load_gpr(t1, rt);
2261 switch (opc) {
2262 case OPC_VR54XX_MULS:
2263 tcg_gen_helper_1_2(do_muls, t0, t0, t1);
2264 opn = "muls";
2265 break;
2266 case OPC_VR54XX_MULSU:
2267 tcg_gen_helper_1_2(do_mulsu, t0, t0, t1);
2268 opn = "mulsu";
2269 break;
2270 case OPC_VR54XX_MACC:
2271 tcg_gen_helper_1_2(do_macc, t0, t0, t1);
2272 opn = "macc";
2273 break;
2274 case OPC_VR54XX_MACCU:
2275 tcg_gen_helper_1_2(do_maccu, t0, t0, t1);
2276 opn = "maccu";
2277 break;
2278 case OPC_VR54XX_MSAC:
2279 tcg_gen_helper_1_2(do_msac, t0, t0, t1);
2280 opn = "msac";
2281 break;
2282 case OPC_VR54XX_MSACU:
2283 tcg_gen_helper_1_2(do_msacu, t0, t0, t1);
2284 opn = "msacu";
2285 break;
2286 case OPC_VR54XX_MULHI:
2287 tcg_gen_helper_1_2(do_mulhi, t0, t0, t1);
2288 opn = "mulhi";
2289 break;
2290 case OPC_VR54XX_MULHIU:
2291 tcg_gen_helper_1_2(do_mulhiu, t0, t0, t1);
2292 opn = "mulhiu";
2293 break;
2294 case OPC_VR54XX_MULSHI:
2295 tcg_gen_helper_1_2(do_mulshi, t0, t0, t1);
2296 opn = "mulshi";
2297 break;
2298 case OPC_VR54XX_MULSHIU:
2299 tcg_gen_helper_1_2(do_mulshiu, t0, t0, t1);
2300 opn = "mulshiu";
2301 break;
2302 case OPC_VR54XX_MACCHI:
2303 tcg_gen_helper_1_2(do_macchi, t0, t0, t1);
2304 opn = "macchi";
2305 break;
2306 case OPC_VR54XX_MACCHIU:
2307 tcg_gen_helper_1_2(do_macchiu, t0, t0, t1);
2308 opn = "macchiu";
2309 break;
2310 case OPC_VR54XX_MSACHI:
2311 tcg_gen_helper_1_2(do_msachi, t0, t0, t1);
2312 opn = "msachi";
2313 break;
2314 case OPC_VR54XX_MSACHIU:
2315 tcg_gen_helper_1_2(do_msachiu, t0, t0, t1);
2316 opn = "msachiu";
2317 break;
2318 default:
2319 MIPS_INVAL("mul vr54xx");
2320 generate_exception(ctx, EXCP_RI);
2321 goto out;
2323 gen_store_gpr(t0, rd);
2324 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2326 out:
2327 tcg_temp_free(t0);
2328 tcg_temp_free(t1);
2331 static void gen_cl (DisasContext *ctx, uint32_t opc,
2332 int rd, int rs)
2334 const char *opn = "CLx";
2335 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2337 if (rd == 0) {
2338 /* Treat as NOP. */
2339 MIPS_DEBUG("NOP");
2340 goto out;
2342 gen_load_gpr(t0, rs);
2343 switch (opc) {
2344 case OPC_CLO:
2345 tcg_gen_helper_1_1(do_clo, t0, t0);
2346 opn = "clo";
2347 break;
2348 case OPC_CLZ:
2349 tcg_gen_helper_1_1(do_clz, t0, t0);
2350 opn = "clz";
2351 break;
2352 #if defined(TARGET_MIPS64)
2353 case OPC_DCLO:
2354 tcg_gen_helper_1_1(do_dclo, t0, t0);
2355 opn = "dclo";
2356 break;
2357 case OPC_DCLZ:
2358 tcg_gen_helper_1_1(do_dclz, t0, t0);
2359 opn = "dclz";
2360 break;
2361 #endif
2362 default:
2363 MIPS_INVAL(opn);
2364 generate_exception(ctx, EXCP_RI);
2365 goto out;
2367 gen_store_gpr(t0, rd);
2368 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2370 out:
2371 tcg_temp_free(t0);
2374 /* Traps */
2375 static void gen_trap (DisasContext *ctx, uint32_t opc,
2376 int rs, int rt, int16_t imm)
2378 int cond;
2379 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2380 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2382 cond = 0;
2383 /* Load needed operands */
2384 switch (opc) {
2385 case OPC_TEQ:
2386 case OPC_TGE:
2387 case OPC_TGEU:
2388 case OPC_TLT:
2389 case OPC_TLTU:
2390 case OPC_TNE:
2391 /* Compare two registers */
2392 if (rs != rt) {
2393 gen_load_gpr(t0, rs);
2394 gen_load_gpr(t1, rt);
2395 cond = 1;
2397 break;
2398 case OPC_TEQI:
2399 case OPC_TGEI:
2400 case OPC_TGEIU:
2401 case OPC_TLTI:
2402 case OPC_TLTIU:
2403 case OPC_TNEI:
2404 /* Compare register to immediate */
2405 if (rs != 0 || imm != 0) {
2406 gen_load_gpr(t0, rs);
2407 tcg_gen_movi_tl(t1, (int32_t)imm);
2408 cond = 1;
2410 break;
2412 if (cond == 0) {
2413 switch (opc) {
2414 case OPC_TEQ: /* rs == rs */
2415 case OPC_TEQI: /* r0 == 0 */
2416 case OPC_TGE: /* rs >= rs */
2417 case OPC_TGEI: /* r0 >= 0 */
2418 case OPC_TGEU: /* rs >= rs unsigned */
2419 case OPC_TGEIU: /* r0 >= 0 unsigned */
2420 /* Always trap */
2421 tcg_gen_movi_tl(t0, 1);
2422 break;
2423 case OPC_TLT: /* rs < rs */
2424 case OPC_TLTI: /* r0 < 0 */
2425 case OPC_TLTU: /* rs < rs unsigned */
2426 case OPC_TLTIU: /* r0 < 0 unsigned */
2427 case OPC_TNE: /* rs != rs */
2428 case OPC_TNEI: /* r0 != 0 */
2429 /* Never trap: treat as NOP. */
2430 goto out;
2431 default:
2432 MIPS_INVAL("trap");
2433 generate_exception(ctx, EXCP_RI);
2434 goto out;
2436 } else {
2437 switch (opc) {
2438 case OPC_TEQ:
2439 case OPC_TEQI:
2440 gen_op_eq(t0, t1);
2441 break;
2442 case OPC_TGE:
2443 case OPC_TGEI:
2444 gen_op_ge(t0, t1);
2445 break;
2446 case OPC_TGEU:
2447 case OPC_TGEIU:
2448 gen_op_geu(t0, t1);
2449 break;
2450 case OPC_TLT:
2451 case OPC_TLTI:
2452 gen_op_lt(t0, t1);
2453 break;
2454 case OPC_TLTU:
2455 case OPC_TLTIU:
2456 gen_op_ltu(t0, t1);
2457 break;
2458 case OPC_TNE:
2459 case OPC_TNEI:
2460 gen_op_ne(t0, t1);
2461 break;
2462 default:
2463 MIPS_INVAL("trap");
2464 generate_exception(ctx, EXCP_RI);
2465 goto out;
2468 save_cpu_state(ctx, 1);
2470 int l1 = gen_new_label();
2472 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2473 tcg_gen_helper_0_i(do_raise_exception, EXCP_TRAP);
2474 gen_set_label(l1);
2476 ctx->bstate = BS_STOP;
2477 out:
2478 tcg_temp_free(t0);
2479 tcg_temp_free(t1);
2482 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2484 TranslationBlock *tb;
2485 tb = ctx->tb;
2486 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2487 tcg_gen_goto_tb(n);
2488 gen_save_pc(dest);
2489 tcg_gen_exit_tb((long)tb + n);
2490 } else {
2491 gen_save_pc(dest);
2492 tcg_gen_exit_tb(0);
2496 /* Branches (before delay slot) */
2497 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2498 int rs, int rt, int32_t offset)
2500 target_ulong btgt = -1;
2501 int blink = 0;
2502 int bcond = 0;
2503 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2504 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2506 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2507 #ifdef MIPS_DEBUG_DISAS
2508 if (loglevel & CPU_LOG_TB_IN_ASM) {
2509 fprintf(logfile,
2510 "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
2511 ctx->pc);
2513 #endif
2514 generate_exception(ctx, EXCP_RI);
2515 goto out;
2518 /* Load needed operands */
2519 switch (opc) {
2520 case OPC_BEQ:
2521 case OPC_BEQL:
2522 case OPC_BNE:
2523 case OPC_BNEL:
2524 /* Compare two registers */
2525 if (rs != rt) {
2526 gen_load_gpr(t0, rs);
2527 gen_load_gpr(t1, rt);
2528 bcond = 1;
2530 btgt = ctx->pc + 4 + offset;
2531 break;
2532 case OPC_BGEZ:
2533 case OPC_BGEZAL:
2534 case OPC_BGEZALL:
2535 case OPC_BGEZL:
2536 case OPC_BGTZ:
2537 case OPC_BGTZL:
2538 case OPC_BLEZ:
2539 case OPC_BLEZL:
2540 case OPC_BLTZ:
2541 case OPC_BLTZAL:
2542 case OPC_BLTZALL:
2543 case OPC_BLTZL:
2544 /* Compare to zero */
2545 if (rs != 0) {
2546 gen_load_gpr(t0, rs);
2547 bcond = 1;
2549 btgt = ctx->pc + 4 + offset;
2550 break;
2551 case OPC_J:
2552 case OPC_JAL:
2553 /* Jump to immediate */
2554 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2555 break;
2556 case OPC_JR:
2557 case OPC_JALR:
2558 /* Jump to register */
2559 if (offset != 0 && offset != 16) {
2560 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2561 others are reserved. */
2562 MIPS_INVAL("jump hint");
2563 generate_exception(ctx, EXCP_RI);
2564 goto out;
2566 gen_load_gpr(btarget, rs);
2567 break;
2568 default:
2569 MIPS_INVAL("branch/jump");
2570 generate_exception(ctx, EXCP_RI);
2571 goto out;
2573 if (bcond == 0) {
2574 /* No condition to be computed */
2575 switch (opc) {
2576 case OPC_BEQ: /* rx == rx */
2577 case OPC_BEQL: /* rx == rx likely */
2578 case OPC_BGEZ: /* 0 >= 0 */
2579 case OPC_BGEZL: /* 0 >= 0 likely */
2580 case OPC_BLEZ: /* 0 <= 0 */
2581 case OPC_BLEZL: /* 0 <= 0 likely */
2582 /* Always take */
2583 ctx->hflags |= MIPS_HFLAG_B;
2584 MIPS_DEBUG("balways");
2585 break;
2586 case OPC_BGEZAL: /* 0 >= 0 */
2587 case OPC_BGEZALL: /* 0 >= 0 likely */
2588 /* Always take and link */
2589 blink = 31;
2590 ctx->hflags |= MIPS_HFLAG_B;
2591 MIPS_DEBUG("balways and link");
2592 break;
2593 case OPC_BNE: /* rx != rx */
2594 case OPC_BGTZ: /* 0 > 0 */
2595 case OPC_BLTZ: /* 0 < 0 */
2596 /* Treat as NOP. */
2597 MIPS_DEBUG("bnever (NOP)");
2598 goto out;
2599 case OPC_BLTZAL: /* 0 < 0 */
2600 tcg_gen_movi_tl(t0, ctx->pc + 8);
2601 gen_store_gpr(t0, 31);
2602 MIPS_DEBUG("bnever and link");
2603 goto out;
2604 case OPC_BLTZALL: /* 0 < 0 likely */
2605 tcg_gen_movi_tl(t0, ctx->pc + 8);
2606 gen_store_gpr(t0, 31);
2607 /* Skip the instruction in the delay slot */
2608 MIPS_DEBUG("bnever, link and skip");
2609 ctx->pc += 4;
2610 goto out;
2611 case OPC_BNEL: /* rx != rx likely */
2612 case OPC_BGTZL: /* 0 > 0 likely */
2613 case OPC_BLTZL: /* 0 < 0 likely */
2614 /* Skip the instruction in the delay slot */
2615 MIPS_DEBUG("bnever and skip");
2616 ctx->pc += 4;
2617 goto out;
2618 case OPC_J:
2619 ctx->hflags |= MIPS_HFLAG_B;
2620 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2621 break;
2622 case OPC_JAL:
2623 blink = 31;
2624 ctx->hflags |= MIPS_HFLAG_B;
2625 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2626 break;
2627 case OPC_JR:
2628 ctx->hflags |= MIPS_HFLAG_BR;
2629 MIPS_DEBUG("jr %s", regnames[rs]);
2630 break;
2631 case OPC_JALR:
2632 blink = rt;
2633 ctx->hflags |= MIPS_HFLAG_BR;
2634 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2635 break;
2636 default:
2637 MIPS_INVAL("branch/jump");
2638 generate_exception(ctx, EXCP_RI);
2639 goto out;
2641 } else {
2642 switch (opc) {
2643 case OPC_BEQ:
2644 gen_op_eq(t0, t1);
2645 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2646 regnames[rs], regnames[rt], btgt);
2647 goto not_likely;
2648 case OPC_BEQL:
2649 gen_op_eq(t0, t1);
2650 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2651 regnames[rs], regnames[rt], btgt);
2652 goto likely;
2653 case OPC_BNE:
2654 gen_op_ne(t0, t1);
2655 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2656 regnames[rs], regnames[rt], btgt);
2657 goto not_likely;
2658 case OPC_BNEL:
2659 gen_op_ne(t0, t1);
2660 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2661 regnames[rs], regnames[rt], btgt);
2662 goto likely;
2663 case OPC_BGEZ:
2664 gen_op_gez(t0);
2665 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2666 goto not_likely;
2667 case OPC_BGEZL:
2668 gen_op_gez(t0);
2669 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2670 goto likely;
2671 case OPC_BGEZAL:
2672 gen_op_gez(t0);
2673 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2674 blink = 31;
2675 goto not_likely;
2676 case OPC_BGEZALL:
2677 gen_op_gez(t0);
2678 blink = 31;
2679 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2680 goto likely;
2681 case OPC_BGTZ:
2682 gen_op_gtz(t0);
2683 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2684 goto not_likely;
2685 case OPC_BGTZL:
2686 gen_op_gtz(t0);
2687 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2688 goto likely;
2689 case OPC_BLEZ:
2690 gen_op_lez(t0);
2691 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2692 goto not_likely;
2693 case OPC_BLEZL:
2694 gen_op_lez(t0);
2695 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2696 goto likely;
2697 case OPC_BLTZ:
2698 gen_op_ltz(t0);
2699 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2700 goto not_likely;
2701 case OPC_BLTZL:
2702 gen_op_ltz(t0);
2703 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2704 goto likely;
2705 case OPC_BLTZAL:
2706 gen_op_ltz(t0);
2707 blink = 31;
2708 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2709 not_likely:
2710 ctx->hflags |= MIPS_HFLAG_BC;
2711 tcg_gen_trunc_tl_i32(bcond, t0);
2712 break;
2713 case OPC_BLTZALL:
2714 gen_op_ltz(t0);
2715 blink = 31;
2716 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2717 likely:
2718 ctx->hflags |= MIPS_HFLAG_BL;
2719 tcg_gen_trunc_tl_i32(bcond, t0);
2720 break;
2721 default:
2722 MIPS_INVAL("conditional branch/jump");
2723 generate_exception(ctx, EXCP_RI);
2724 goto out;
2727 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2728 blink, ctx->hflags, btgt);
2730 ctx->btarget = btgt;
2731 if (blink > 0) {
2732 tcg_gen_movi_tl(t0, ctx->pc + 8);
2733 gen_store_gpr(t0, blink);
2736 out:
2737 tcg_temp_free(t0);
2738 tcg_temp_free(t1);
2741 /* special3 bitfield operations */
2742 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2743 int rs, int lsb, int msb)
2745 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2746 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2748 gen_load_gpr(t1, rs);
2749 switch (opc) {
2750 case OPC_EXT:
2751 if (lsb + msb > 31)
2752 goto fail;
2753 tcg_gen_helper_1_1ii(do_ext, t0, t1, lsb, msb + 1);
2754 break;
2755 #if defined(TARGET_MIPS64)
2756 case OPC_DEXTM:
2757 if (lsb + msb > 63)
2758 goto fail;
2759 tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb, msb + 1 + 32);
2760 break;
2761 case OPC_DEXTU:
2762 if (lsb + msb > 63)
2763 goto fail;
2764 tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb + 32, msb + 1);
2765 break;
2766 case OPC_DEXT:
2767 if (lsb + msb > 63)
2768 goto fail;
2769 tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb, msb + 1);
2770 break;
2771 #endif
2772 case OPC_INS:
2773 if (lsb > msb)
2774 goto fail;
2775 gen_load_gpr(t0, rt);
2776 tcg_gen_helper_1_2ii(do_ins, t0, t0, t1, lsb, msb - lsb + 1);
2777 break;
2778 #if defined(TARGET_MIPS64)
2779 case OPC_DINSM:
2780 if (lsb > msb)
2781 goto fail;
2782 gen_load_gpr(t0, rt);
2783 tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb, msb - lsb + 1 + 32);
2784 break;
2785 case OPC_DINSU:
2786 if (lsb > msb)
2787 goto fail;
2788 gen_load_gpr(t0, rt);
2789 tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb + 32, msb - lsb + 1);
2790 break;
2791 case OPC_DINS:
2792 if (lsb > msb)
2793 goto fail;
2794 gen_load_gpr(t0, rt);
2795 tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb, msb - lsb + 1);
2796 break;
2797 #endif
2798 default:
2799 fail:
2800 MIPS_INVAL("bitops");
2801 generate_exception(ctx, EXCP_RI);
2802 tcg_temp_free(t0);
2803 tcg_temp_free(t1);
2804 return;
2806 gen_store_gpr(t0, rt);
2807 tcg_temp_free(t0);
2808 tcg_temp_free(t1);
2811 #ifndef CONFIG_USER_ONLY
2812 /* CP0 (MMU and control) */
2813 static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
2815 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
2817 tcg_gen_ld_i32(r_tmp, cpu_env, off);
2818 tcg_gen_ext_i32_tl(t, r_tmp);
2819 tcg_temp_free(r_tmp);
2822 static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
2824 tcg_gen_ld_tl(t, cpu_env, off);
2825 tcg_gen_ext32s_tl(t, t);
2828 static inline void gen_mtc0_store32 (TCGv t, target_ulong off)
2830 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
2832 tcg_gen_trunc_tl_i32(r_tmp, t);
2833 tcg_gen_st_i32(r_tmp, cpu_env, off);
2834 tcg_temp_free(r_tmp);
2837 static inline void gen_mtc0_store64 (TCGv t, target_ulong off)
2839 tcg_gen_ext32s_tl(t, t);
2840 tcg_gen_st_tl(t, cpu_env, off);
2843 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
2845 const char *rn = "invalid";
2847 if (sel != 0)
2848 check_insn(env, ctx, ISA_MIPS32);
2850 switch (reg) {
2851 case 0:
2852 switch (sel) {
2853 case 0:
2854 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
2855 rn = "Index";
2856 break;
2857 case 1:
2858 check_insn(env, ctx, ASE_MT);
2859 tcg_gen_helper_1_0(do_mfc0_mvpcontrol, t0);
2860 rn = "MVPControl";
2861 break;
2862 case 2:
2863 check_insn(env, ctx, ASE_MT);
2864 tcg_gen_helper_1_0(do_mfc0_mvpconf0, t0);
2865 rn = "MVPConf0";
2866 break;
2867 case 3:
2868 check_insn(env, ctx, ASE_MT);
2869 tcg_gen_helper_1_0(do_mfc0_mvpconf1, t0);
2870 rn = "MVPConf1";
2871 break;
2872 default:
2873 goto die;
2875 break;
2876 case 1:
2877 switch (sel) {
2878 case 0:
2879 tcg_gen_helper_1_0(do_mfc0_random, t0);
2880 rn = "Random";
2881 break;
2882 case 1:
2883 check_insn(env, ctx, ASE_MT);
2884 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
2885 rn = "VPEControl";
2886 break;
2887 case 2:
2888 check_insn(env, ctx, ASE_MT);
2889 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
2890 rn = "VPEConf0";
2891 break;
2892 case 3:
2893 check_insn(env, ctx, ASE_MT);
2894 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
2895 rn = "VPEConf1";
2896 break;
2897 case 4:
2898 check_insn(env, ctx, ASE_MT);
2899 gen_mfc0_load64(t0, offsetof(CPUState, CP0_YQMask));
2900 rn = "YQMask";
2901 break;
2902 case 5:
2903 check_insn(env, ctx, ASE_MT);
2904 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPESchedule));
2905 rn = "VPESchedule";
2906 break;
2907 case 6:
2908 check_insn(env, ctx, ASE_MT);
2909 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPEScheFBack));
2910 rn = "VPEScheFBack";
2911 break;
2912 case 7:
2913 check_insn(env, ctx, ASE_MT);
2914 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
2915 rn = "VPEOpt";
2916 break;
2917 default:
2918 goto die;
2920 break;
2921 case 2:
2922 switch (sel) {
2923 case 0:
2924 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2925 tcg_gen_ext32s_tl(t0, t0);
2926 rn = "EntryLo0";
2927 break;
2928 case 1:
2929 check_insn(env, ctx, ASE_MT);
2930 tcg_gen_helper_1_0(do_mfc0_tcstatus, t0);
2931 rn = "TCStatus";
2932 break;
2933 case 2:
2934 check_insn(env, ctx, ASE_MT);
2935 tcg_gen_helper_1_0(do_mfc0_tcbind, t0);
2936 rn = "TCBind";
2937 break;
2938 case 3:
2939 check_insn(env, ctx, ASE_MT);
2940 tcg_gen_helper_1_0(do_mfc0_tcrestart, t0);
2941 rn = "TCRestart";
2942 break;
2943 case 4:
2944 check_insn(env, ctx, ASE_MT);
2945 tcg_gen_helper_1_0(do_mfc0_tchalt, t0);
2946 rn = "TCHalt";
2947 break;
2948 case 5:
2949 check_insn(env, ctx, ASE_MT);
2950 tcg_gen_helper_1_0(do_mfc0_tccontext, t0);
2951 rn = "TCContext";
2952 break;
2953 case 6:
2954 check_insn(env, ctx, ASE_MT);
2955 tcg_gen_helper_1_0(do_mfc0_tcschedule, t0);
2956 rn = "TCSchedule";
2957 break;
2958 case 7:
2959 check_insn(env, ctx, ASE_MT);
2960 tcg_gen_helper_1_0(do_mfc0_tcschefback, t0);
2961 rn = "TCScheFBack";
2962 break;
2963 default:
2964 goto die;
2966 break;
2967 case 3:
2968 switch (sel) {
2969 case 0:
2970 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2971 tcg_gen_ext32s_tl(t0, t0);
2972 rn = "EntryLo1";
2973 break;
2974 default:
2975 goto die;
2977 break;
2978 case 4:
2979 switch (sel) {
2980 case 0:
2981 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
2982 tcg_gen_ext32s_tl(t0, t0);
2983 rn = "Context";
2984 break;
2985 case 1:
2986 // tcg_gen_helper_1_0(do_mfc0_contextconfig, t0); /* SmartMIPS ASE */
2987 rn = "ContextConfig";
2988 // break;
2989 default:
2990 goto die;
2992 break;
2993 case 5:
2994 switch (sel) {
2995 case 0:
2996 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
2997 rn = "PageMask";
2998 break;
2999 case 1:
3000 check_insn(env, ctx, ISA_MIPS32R2);
3001 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
3002 rn = "PageGrain";
3003 break;
3004 default:
3005 goto die;
3007 break;
3008 case 6:
3009 switch (sel) {
3010 case 0:
3011 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
3012 rn = "Wired";
3013 break;
3014 case 1:
3015 check_insn(env, ctx, ISA_MIPS32R2);
3016 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
3017 rn = "SRSConf0";
3018 break;
3019 case 2:
3020 check_insn(env, ctx, ISA_MIPS32R2);
3021 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
3022 rn = "SRSConf1";
3023 break;
3024 case 3:
3025 check_insn(env, ctx, ISA_MIPS32R2);
3026 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
3027 rn = "SRSConf2";
3028 break;
3029 case 4:
3030 check_insn(env, ctx, ISA_MIPS32R2);
3031 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
3032 rn = "SRSConf3";
3033 break;
3034 case 5:
3035 check_insn(env, ctx, ISA_MIPS32R2);
3036 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
3037 rn = "SRSConf4";
3038 break;
3039 default:
3040 goto die;
3042 break;
3043 case 7:
3044 switch (sel) {
3045 case 0:
3046 check_insn(env, ctx, ISA_MIPS32R2);
3047 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
3048 rn = "HWREna";
3049 break;
3050 default:
3051 goto die;
3053 break;
3054 case 8:
3055 switch (sel) {
3056 case 0:
3057 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3058 tcg_gen_ext32s_tl(t0, t0);
3059 rn = "BadVAddr";
3060 break;
3061 default:
3062 goto die;
3064 break;
3065 case 9:
3066 switch (sel) {
3067 case 0:
3068 /* Mark as an IO operation because we read the time. */
3069 if (use_icount)
3070 gen_io_start();
3071 tcg_gen_helper_1_0(do_mfc0_count, t0);
3072 if (use_icount) {
3073 gen_io_end();
3074 ctx->bstate = BS_STOP;
3076 rn = "Count";
3077 break;
3078 /* 6,7 are implementation dependent */
3079 default:
3080 goto die;
3082 break;
3083 case 10:
3084 switch (sel) {
3085 case 0:
3086 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
3087 tcg_gen_ext32s_tl(t0, t0);
3088 rn = "EntryHi";
3089 break;
3090 default:
3091 goto die;
3093 break;
3094 case 11:
3095 switch (sel) {
3096 case 0:
3097 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
3098 rn = "Compare";
3099 break;
3100 /* 6,7 are implementation dependent */
3101 default:
3102 goto die;
3104 break;
3105 case 12:
3106 switch (sel) {
3107 case 0:
3108 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
3109 rn = "Status";
3110 break;
3111 case 1:
3112 check_insn(env, ctx, ISA_MIPS32R2);
3113 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
3114 rn = "IntCtl";
3115 break;
3116 case 2:
3117 check_insn(env, ctx, ISA_MIPS32R2);
3118 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
3119 rn = "SRSCtl";
3120 break;
3121 case 3:
3122 check_insn(env, ctx, ISA_MIPS32R2);
3123 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
3124 rn = "SRSMap";
3125 break;
3126 default:
3127 goto die;
3129 break;
3130 case 13:
3131 switch (sel) {
3132 case 0:
3133 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
3134 rn = "Cause";
3135 break;
3136 default:
3137 goto die;
3139 break;
3140 case 14:
3141 switch (sel) {
3142 case 0:
3143 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
3144 tcg_gen_ext32s_tl(t0, t0);
3145 rn = "EPC";
3146 break;
3147 default:
3148 goto die;
3150 break;
3151 case 15:
3152 switch (sel) {
3153 case 0:
3154 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
3155 rn = "PRid";
3156 break;
3157 case 1:
3158 check_insn(env, ctx, ISA_MIPS32R2);
3159 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
3160 rn = "EBase";
3161 break;
3162 default:
3163 goto die;
3165 break;
3166 case 16:
3167 switch (sel) {
3168 case 0:
3169 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
3170 rn = "Config";
3171 break;
3172 case 1:
3173 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
3174 rn = "Config1";
3175 break;
3176 case 2:
3177 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
3178 rn = "Config2";
3179 break;
3180 case 3:
3181 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
3182 rn = "Config3";
3183 break;
3184 /* 4,5 are reserved */
3185 /* 6,7 are implementation dependent */
3186 case 6:
3187 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
3188 rn = "Config6";
3189 break;
3190 case 7:
3191 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
3192 rn = "Config7";
3193 break;
3194 default:
3195 goto die;
3197 break;
3198 case 17:
3199 switch (sel) {
3200 case 0:
3201 tcg_gen_helper_1_0(do_mfc0_lladdr, t0);
3202 rn = "LLAddr";
3203 break;
3204 default:
3205 goto die;
3207 break;
3208 case 18:
3209 switch (sel) {
3210 case 0 ... 7:
3211 tcg_gen_helper_1_i(do_mfc0_watchlo, t0, sel);
3212 rn = "WatchLo";
3213 break;
3214 default:
3215 goto die;
3217 break;
3218 case 19:
3219 switch (sel) {
3220 case 0 ...7:
3221 tcg_gen_helper_1_i(do_mfc0_watchhi, t0, sel);
3222 rn = "WatchHi";
3223 break;
3224 default:
3225 goto die;
3227 break;
3228 case 20:
3229 switch (sel) {
3230 case 0:
3231 #if defined(TARGET_MIPS64)
3232 check_insn(env, ctx, ISA_MIPS3);
3233 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
3234 tcg_gen_ext32s_tl(t0, t0);
3235 rn = "XContext";
3236 break;
3237 #endif
3238 default:
3239 goto die;
3241 break;
3242 case 21:
3243 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3244 switch (sel) {
3245 case 0:
3246 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
3247 rn = "Framemask";
3248 break;
3249 default:
3250 goto die;
3252 break;
3253 case 22:
3254 /* ignored */
3255 rn = "'Diagnostic"; /* implementation dependent */
3256 break;
3257 case 23:
3258 switch (sel) {
3259 case 0:
3260 tcg_gen_helper_1_0(do_mfc0_debug, t0); /* EJTAG support */
3261 rn = "Debug";
3262 break;
3263 case 1:
3264 // tcg_gen_helper_1_0(do_mfc0_tracecontrol, t0); /* PDtrace support */
3265 rn = "TraceControl";
3266 // break;
3267 case 2:
3268 // tcg_gen_helper_1_0(do_mfc0_tracecontrol2, t0); /* PDtrace support */
3269 rn = "TraceControl2";
3270 // break;
3271 case 3:
3272 // tcg_gen_helper_1_0(do_mfc0_usertracedata, t0); /* PDtrace support */
3273 rn = "UserTraceData";
3274 // break;
3275 case 4:
3276 // tcg_gen_helper_1_0(do_mfc0_tracebpc, t0); /* PDtrace support */
3277 rn = "TraceBPC";
3278 // break;
3279 default:
3280 goto die;
3282 break;
3283 case 24:
3284 switch (sel) {
3285 case 0:
3286 /* EJTAG support */
3287 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
3288 tcg_gen_ext32s_tl(t0, t0);
3289 rn = "DEPC";
3290 break;
3291 default:
3292 goto die;
3294 break;
3295 case 25:
3296 switch (sel) {
3297 case 0:
3298 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
3299 rn = "Performance0";
3300 break;
3301 case 1:
3302 // tcg_gen_helper_1_0(do_mfc0_performance1, t0);
3303 rn = "Performance1";
3304 // break;
3305 case 2:
3306 // tcg_gen_helper_1_0(do_mfc0_performance2, t0);
3307 rn = "Performance2";
3308 // break;
3309 case 3:
3310 // tcg_gen_helper_1_0(do_mfc0_performance3, t0);
3311 rn = "Performance3";
3312 // break;
3313 case 4:
3314 // tcg_gen_helper_1_0(do_mfc0_performance4, t0);
3315 rn = "Performance4";
3316 // break;
3317 case 5:
3318 // tcg_gen_helper_1_0(do_mfc0_performance5, t0);
3319 rn = "Performance5";
3320 // break;
3321 case 6:
3322 // tcg_gen_helper_1_0(do_mfc0_performance6, t0);
3323 rn = "Performance6";
3324 // break;
3325 case 7:
3326 // tcg_gen_helper_1_0(do_mfc0_performance7, t0);
3327 rn = "Performance7";
3328 // break;
3329 default:
3330 goto die;
3332 break;
3333 case 26:
3334 rn = "ECC";
3335 break;
3336 case 27:
3337 switch (sel) {
3338 /* ignored */
3339 case 0 ... 3:
3340 rn = "CacheErr";
3341 break;
3342 default:
3343 goto die;
3345 break;
3346 case 28:
3347 switch (sel) {
3348 case 0:
3349 case 2:
3350 case 4:
3351 case 6:
3352 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
3353 rn = "TagLo";
3354 break;
3355 case 1:
3356 case 3:
3357 case 5:
3358 case 7:
3359 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
3360 rn = "DataLo";
3361 break;
3362 default:
3363 goto die;
3365 break;
3366 case 29:
3367 switch (sel) {
3368 case 0:
3369 case 2:
3370 case 4:
3371 case 6:
3372 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
3373 rn = "TagHi";
3374 break;
3375 case 1:
3376 case 3:
3377 case 5:
3378 case 7:
3379 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
3380 rn = "DataHi";
3381 break;
3382 default:
3383 goto die;
3385 break;
3386 case 30:
3387 switch (sel) {
3388 case 0:
3389 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3390 tcg_gen_ext32s_tl(t0, t0);
3391 rn = "ErrorEPC";
3392 break;
3393 default:
3394 goto die;
3396 break;
3397 case 31:
3398 switch (sel) {
3399 case 0:
3400 /* EJTAG support */
3401 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
3402 rn = "DESAVE";
3403 break;
3404 default:
3405 goto die;
3407 break;
3408 default:
3409 goto die;
3411 #if defined MIPS_DEBUG_DISAS
3412 if (loglevel & CPU_LOG_TB_IN_ASM) {
3413 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3414 rn, reg, sel);
3416 #endif
3417 return;
3419 die:
3420 #if defined MIPS_DEBUG_DISAS
3421 if (loglevel & CPU_LOG_TB_IN_ASM) {
3422 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3423 rn, reg, sel);
3425 #endif
3426 generate_exception(ctx, EXCP_RI);
3429 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
3431 const char *rn = "invalid";
3433 if (sel != 0)
3434 check_insn(env, ctx, ISA_MIPS32);
3436 if (use_icount)
3437 gen_io_start();
3439 switch (reg) {
3440 case 0:
3441 switch (sel) {
3442 case 0:
3443 tcg_gen_helper_0_1(do_mtc0_index, t0);
3444 rn = "Index";
3445 break;
3446 case 1:
3447 check_insn(env, ctx, ASE_MT);
3448 tcg_gen_helper_0_1(do_mtc0_mvpcontrol, t0);
3449 rn = "MVPControl";
3450 break;
3451 case 2:
3452 check_insn(env, ctx, ASE_MT);
3453 /* ignored */
3454 rn = "MVPConf0";
3455 break;
3456 case 3:
3457 check_insn(env, ctx, ASE_MT);
3458 /* ignored */
3459 rn = "MVPConf1";
3460 break;
3461 default:
3462 goto die;
3464 break;
3465 case 1:
3466 switch (sel) {
3467 case 0:
3468 /* ignored */
3469 rn = "Random";
3470 break;
3471 case 1:
3472 check_insn(env, ctx, ASE_MT);
3473 tcg_gen_helper_0_1(do_mtc0_vpecontrol, t0);
3474 rn = "VPEControl";
3475 break;
3476 case 2:
3477 check_insn(env, ctx, ASE_MT);
3478 tcg_gen_helper_0_1(do_mtc0_vpeconf0, t0);
3479 rn = "VPEConf0";
3480 break;
3481 case 3:
3482 check_insn(env, ctx, ASE_MT);
3483 tcg_gen_helper_0_1(do_mtc0_vpeconf1, t0);
3484 rn = "VPEConf1";
3485 break;
3486 case 4:
3487 check_insn(env, ctx, ASE_MT);
3488 tcg_gen_helper_0_1(do_mtc0_yqmask, t0);
3489 rn = "YQMask";
3490 break;
3491 case 5:
3492 check_insn(env, ctx, ASE_MT);
3493 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule));
3494 rn = "VPESchedule";
3495 break;
3496 case 6:
3497 check_insn(env, ctx, ASE_MT);
3498 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack));
3499 rn = "VPEScheFBack";
3500 break;
3501 case 7:
3502 check_insn(env, ctx, ASE_MT);
3503 tcg_gen_helper_0_1(do_mtc0_vpeopt, t0);
3504 rn = "VPEOpt";
3505 break;
3506 default:
3507 goto die;
3509 break;
3510 case 2:
3511 switch (sel) {
3512 case 0:
3513 tcg_gen_helper_0_1(do_mtc0_entrylo0, t0);
3514 rn = "EntryLo0";
3515 break;
3516 case 1:
3517 check_insn(env, ctx, ASE_MT);
3518 tcg_gen_helper_0_1(do_mtc0_tcstatus, t0);
3519 rn = "TCStatus";
3520 break;
3521 case 2:
3522 check_insn(env, ctx, ASE_MT);
3523 tcg_gen_helper_0_1(do_mtc0_tcbind, t0);
3524 rn = "TCBind";
3525 break;
3526 case 3:
3527 check_insn(env, ctx, ASE_MT);
3528 tcg_gen_helper_0_1(do_mtc0_tcrestart, t0);
3529 rn = "TCRestart";
3530 break;
3531 case 4:
3532 check_insn(env, ctx, ASE_MT);
3533 tcg_gen_helper_0_1(do_mtc0_tchalt, t0);
3534 rn = "TCHalt";
3535 break;
3536 case 5:
3537 check_insn(env, ctx, ASE_MT);
3538 tcg_gen_helper_0_1(do_mtc0_tccontext, t0);
3539 rn = "TCContext";
3540 break;
3541 case 6:
3542 check_insn(env, ctx, ASE_MT);
3543 tcg_gen_helper_0_1(do_mtc0_tcschedule, t0);
3544 rn = "TCSchedule";
3545 break;
3546 case 7:
3547 check_insn(env, ctx, ASE_MT);
3548 tcg_gen_helper_0_1(do_mtc0_tcschefback, t0);
3549 rn = "TCScheFBack";
3550 break;
3551 default:
3552 goto die;
3554 break;
3555 case 3:
3556 switch (sel) {
3557 case 0:
3558 tcg_gen_helper_0_1(do_mtc0_entrylo1, t0);
3559 rn = "EntryLo1";
3560 break;
3561 default:
3562 goto die;
3564 break;
3565 case 4:
3566 switch (sel) {
3567 case 0:
3568 tcg_gen_helper_0_1(do_mtc0_context, t0);
3569 rn = "Context";
3570 break;
3571 case 1:
3572 // tcg_gen_helper_0_1(do_mtc0_contextconfig, t0); /* SmartMIPS ASE */
3573 rn = "ContextConfig";
3574 // break;
3575 default:
3576 goto die;
3578 break;
3579 case 5:
3580 switch (sel) {
3581 case 0:
3582 tcg_gen_helper_0_1(do_mtc0_pagemask, t0);
3583 rn = "PageMask";
3584 break;
3585 case 1:
3586 check_insn(env, ctx, ISA_MIPS32R2);
3587 tcg_gen_helper_0_1(do_mtc0_pagegrain, t0);
3588 rn = "PageGrain";
3589 break;
3590 default:
3591 goto die;
3593 break;
3594 case 6:
3595 switch (sel) {
3596 case 0:
3597 tcg_gen_helper_0_1(do_mtc0_wired, t0);
3598 rn = "Wired";
3599 break;
3600 case 1:
3601 check_insn(env, ctx, ISA_MIPS32R2);
3602 tcg_gen_helper_0_1(do_mtc0_srsconf0, t0);
3603 rn = "SRSConf0";
3604 break;
3605 case 2:
3606 check_insn(env, ctx, ISA_MIPS32R2);
3607 tcg_gen_helper_0_1(do_mtc0_srsconf1, t0);
3608 rn = "SRSConf1";
3609 break;
3610 case 3:
3611 check_insn(env, ctx, ISA_MIPS32R2);
3612 tcg_gen_helper_0_1(do_mtc0_srsconf2, t0);
3613 rn = "SRSConf2";
3614 break;
3615 case 4:
3616 check_insn(env, ctx, ISA_MIPS32R2);
3617 tcg_gen_helper_0_1(do_mtc0_srsconf3, t0);
3618 rn = "SRSConf3";
3619 break;
3620 case 5:
3621 check_insn(env, ctx, ISA_MIPS32R2);
3622 tcg_gen_helper_0_1(do_mtc0_srsconf4, t0);
3623 rn = "SRSConf4";
3624 break;
3625 default:
3626 goto die;
3628 break;
3629 case 7:
3630 switch (sel) {
3631 case 0:
3632 check_insn(env, ctx, ISA_MIPS32R2);
3633 tcg_gen_helper_0_1(do_mtc0_hwrena, t0);
3634 rn = "HWREna";
3635 break;
3636 default:
3637 goto die;
3639 break;
3640 case 8:
3641 /* ignored */
3642 rn = "BadVAddr";
3643 break;
3644 case 9:
3645 switch (sel) {
3646 case 0:
3647 tcg_gen_helper_0_1(do_mtc0_count, t0);
3648 rn = "Count";
3649 break;
3650 /* 6,7 are implementation dependent */
3651 default:
3652 goto die;
3654 /* Stop translation as we may have switched the execution mode */
3655 ctx->bstate = BS_STOP;
3656 break;
3657 case 10:
3658 switch (sel) {
3659 case 0:
3660 tcg_gen_helper_0_1(do_mtc0_entryhi, t0);
3661 rn = "EntryHi";
3662 break;
3663 default:
3664 goto die;
3666 break;
3667 case 11:
3668 switch (sel) {
3669 case 0:
3670 tcg_gen_helper_0_1(do_mtc0_compare, t0);
3671 rn = "Compare";
3672 break;
3673 /* 6,7 are implementation dependent */
3674 default:
3675 goto die;
3677 /* Stop translation as we may have switched the execution mode */
3678 ctx->bstate = BS_STOP;
3679 break;
3680 case 12:
3681 switch (sel) {
3682 case 0:
3683 tcg_gen_helper_0_1(do_mtc0_status, t0);
3684 /* BS_STOP isn't good enough here, hflags may have changed. */
3685 gen_save_pc(ctx->pc + 4);
3686 ctx->bstate = BS_EXCP;
3687 rn = "Status";
3688 break;
3689 case 1:
3690 check_insn(env, ctx, ISA_MIPS32R2);
3691 tcg_gen_helper_0_1(do_mtc0_intctl, t0);
3692 /* Stop translation as we may have switched the execution mode */
3693 ctx->bstate = BS_STOP;
3694 rn = "IntCtl";
3695 break;
3696 case 2:
3697 check_insn(env, ctx, ISA_MIPS32R2);
3698 tcg_gen_helper_0_1(do_mtc0_srsctl, t0);
3699 /* Stop translation as we may have switched the execution mode */
3700 ctx->bstate = BS_STOP;
3701 rn = "SRSCtl";
3702 break;
3703 case 3:
3704 check_insn(env, ctx, ISA_MIPS32R2);
3705 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
3706 /* Stop translation as we may have switched the execution mode */
3707 ctx->bstate = BS_STOP;
3708 rn = "SRSMap";
3709 break;
3710 default:
3711 goto die;
3713 break;
3714 case 13:
3715 switch (sel) {
3716 case 0:
3717 tcg_gen_helper_0_1(do_mtc0_cause, t0);
3718 rn = "Cause";
3719 break;
3720 default:
3721 goto die;
3723 /* Stop translation as we may have switched the execution mode */
3724 ctx->bstate = BS_STOP;
3725 break;
3726 case 14:
3727 switch (sel) {
3728 case 0:
3729 gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC));
3730 rn = "EPC";
3731 break;
3732 default:
3733 goto die;
3735 break;
3736 case 15:
3737 switch (sel) {
3738 case 0:
3739 /* ignored */
3740 rn = "PRid";
3741 break;
3742 case 1:
3743 check_insn(env, ctx, ISA_MIPS32R2);
3744 tcg_gen_helper_0_1(do_mtc0_ebase, t0);
3745 rn = "EBase";
3746 break;
3747 default:
3748 goto die;
3750 break;
3751 case 16:
3752 switch (sel) {
3753 case 0:
3754 tcg_gen_helper_0_1(do_mtc0_config0, t0);
3755 rn = "Config";
3756 /* Stop translation as we may have switched the execution mode */
3757 ctx->bstate = BS_STOP;
3758 break;
3759 case 1:
3760 /* ignored, read only */
3761 rn = "Config1";
3762 break;
3763 case 2:
3764 tcg_gen_helper_0_1(do_mtc0_config2, t0);
3765 rn = "Config2";
3766 /* Stop translation as we may have switched the execution mode */
3767 ctx->bstate = BS_STOP;
3768 break;
3769 case 3:
3770 /* ignored, read only */
3771 rn = "Config3";
3772 break;
3773 /* 4,5 are reserved */
3774 /* 6,7 are implementation dependent */
3775 case 6:
3776 /* ignored */
3777 rn = "Config6";
3778 break;
3779 case 7:
3780 /* ignored */
3781 rn = "Config7";
3782 break;
3783 default:
3784 rn = "Invalid config selector";
3785 goto die;
3787 break;
3788 case 17:
3789 switch (sel) {
3790 case 0:
3791 /* ignored */
3792 rn = "LLAddr";
3793 break;
3794 default:
3795 goto die;
3797 break;
3798 case 18:
3799 switch (sel) {
3800 case 0 ... 7:
3801 tcg_gen_helper_0_1i(do_mtc0_watchlo, t0, sel);
3802 rn = "WatchLo";
3803 break;
3804 default:
3805 goto die;
3807 break;
3808 case 19:
3809 switch (sel) {
3810 case 0 ... 7:
3811 tcg_gen_helper_0_1i(do_mtc0_watchhi, t0, sel);
3812 rn = "WatchHi";
3813 break;
3814 default:
3815 goto die;
3817 break;
3818 case 20:
3819 switch (sel) {
3820 case 0:
3821 #if defined(TARGET_MIPS64)
3822 check_insn(env, ctx, ISA_MIPS3);
3823 tcg_gen_helper_0_1(do_mtc0_xcontext, t0);
3824 rn = "XContext";
3825 break;
3826 #endif
3827 default:
3828 goto die;
3830 break;
3831 case 21:
3832 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3833 switch (sel) {
3834 case 0:
3835 tcg_gen_helper_0_1(do_mtc0_framemask, t0);
3836 rn = "Framemask";
3837 break;
3838 default:
3839 goto die;
3841 break;
3842 case 22:
3843 /* ignored */
3844 rn = "Diagnostic"; /* implementation dependent */
3845 break;
3846 case 23:
3847 switch (sel) {
3848 case 0:
3849 tcg_gen_helper_0_1(do_mtc0_debug, t0); /* EJTAG support */
3850 /* BS_STOP isn't good enough here, hflags may have changed. */
3851 gen_save_pc(ctx->pc + 4);
3852 ctx->bstate = BS_EXCP;
3853 rn = "Debug";
3854 break;
3855 case 1:
3856 // tcg_gen_helper_0_1(do_mtc0_tracecontrol, t0); /* PDtrace support */
3857 rn = "TraceControl";
3858 /* Stop translation as we may have switched the execution mode */
3859 ctx->bstate = BS_STOP;
3860 // break;
3861 case 2:
3862 // tcg_gen_helper_0_1(do_mtc0_tracecontrol2, t0); /* PDtrace support */
3863 rn = "TraceControl2";
3864 /* Stop translation as we may have switched the execution mode */
3865 ctx->bstate = BS_STOP;
3866 // break;
3867 case 3:
3868 /* Stop translation as we may have switched the execution mode */
3869 ctx->bstate = BS_STOP;
3870 // tcg_gen_helper_0_1(do_mtc0_usertracedata, t0); /* PDtrace support */
3871 rn = "UserTraceData";
3872 /* Stop translation as we may have switched the execution mode */
3873 ctx->bstate = BS_STOP;
3874 // break;
3875 case 4:
3876 // tcg_gen_helper_0_1(do_mtc0_tracebpc, t0); /* PDtrace support */
3877 /* Stop translation as we may have switched the execution mode */
3878 ctx->bstate = BS_STOP;
3879 rn = "TraceBPC";
3880 // break;
3881 default:
3882 goto die;
3884 break;
3885 case 24:
3886 switch (sel) {
3887 case 0:
3888 /* EJTAG support */
3889 gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC));
3890 rn = "DEPC";
3891 break;
3892 default:
3893 goto die;
3895 break;
3896 case 25:
3897 switch (sel) {
3898 case 0:
3899 tcg_gen_helper_0_1(do_mtc0_performance0, t0);
3900 rn = "Performance0";
3901 break;
3902 case 1:
3903 // tcg_gen_helper_0_1(do_mtc0_performance1, t0);
3904 rn = "Performance1";
3905 // break;
3906 case 2:
3907 // tcg_gen_helper_0_1(do_mtc0_performance2, t0);
3908 rn = "Performance2";
3909 // break;
3910 case 3:
3911 // tcg_gen_helper_0_1(do_mtc0_performance3, t0);
3912 rn = "Performance3";
3913 // break;
3914 case 4:
3915 // tcg_gen_helper_0_1(do_mtc0_performance4, t0);
3916 rn = "Performance4";
3917 // break;
3918 case 5:
3919 // tcg_gen_helper_0_1(do_mtc0_performance5, t0);
3920 rn = "Performance5";
3921 // break;
3922 case 6:
3923 // tcg_gen_helper_0_1(do_mtc0_performance6, t0);
3924 rn = "Performance6";
3925 // break;
3926 case 7:
3927 // tcg_gen_helper_0_1(do_mtc0_performance7, t0);
3928 rn = "Performance7";
3929 // break;
3930 default:
3931 goto die;
3933 break;
3934 case 26:
3935 /* ignored */
3936 rn = "ECC";
3937 break;
3938 case 27:
3939 switch (sel) {
3940 case 0 ... 3:
3941 /* ignored */
3942 rn = "CacheErr";
3943 break;
3944 default:
3945 goto die;
3947 break;
3948 case 28:
3949 switch (sel) {
3950 case 0:
3951 case 2:
3952 case 4:
3953 case 6:
3954 tcg_gen_helper_0_1(do_mtc0_taglo, t0);
3955 rn = "TagLo";
3956 break;
3957 case 1:
3958 case 3:
3959 case 5:
3960 case 7:
3961 tcg_gen_helper_0_1(do_mtc0_datalo, t0);
3962 rn = "DataLo";
3963 break;
3964 default:
3965 goto die;
3967 break;
3968 case 29:
3969 switch (sel) {
3970 case 0:
3971 case 2:
3972 case 4:
3973 case 6:
3974 tcg_gen_helper_0_1(do_mtc0_taghi, t0);
3975 rn = "TagHi";
3976 break;
3977 case 1:
3978 case 3:
3979 case 5:
3980 case 7:
3981 tcg_gen_helper_0_1(do_mtc0_datahi, t0);
3982 rn = "DataHi";
3983 break;
3984 default:
3985 rn = "invalid sel";
3986 goto die;
3988 break;
3989 case 30:
3990 switch (sel) {
3991 case 0:
3992 gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC));
3993 rn = "ErrorEPC";
3994 break;
3995 default:
3996 goto die;
3998 break;
3999 case 31:
4000 switch (sel) {
4001 case 0:
4002 /* EJTAG support */
4003 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
4004 rn = "DESAVE";
4005 break;
4006 default:
4007 goto die;
4009 /* Stop translation as we may have switched the execution mode */
4010 ctx->bstate = BS_STOP;
4011 break;
4012 default:
4013 goto die;
4015 #if defined MIPS_DEBUG_DISAS
4016 if (loglevel & CPU_LOG_TB_IN_ASM) {
4017 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
4018 rn, reg, sel);
4020 #endif
4021 /* For simplicity assume that all writes can cause interrupts. */
4022 if (use_icount) {
4023 gen_io_end();
4024 ctx->bstate = BS_STOP;
4026 return;
4028 die:
4029 #if defined MIPS_DEBUG_DISAS
4030 if (loglevel & CPU_LOG_TB_IN_ASM) {
4031 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
4032 rn, reg, sel);
4034 #endif
4035 generate_exception(ctx, EXCP_RI);
4038 #if defined(TARGET_MIPS64)
4039 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
4041 const char *rn = "invalid";
4043 if (sel != 0)
4044 check_insn(env, ctx, ISA_MIPS64);
4046 switch (reg) {
4047 case 0:
4048 switch (sel) {
4049 case 0:
4050 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
4051 rn = "Index";
4052 break;
4053 case 1:
4054 check_insn(env, ctx, ASE_MT);
4055 tcg_gen_helper_1_0(do_mfc0_mvpcontrol, t0);
4056 rn = "MVPControl";
4057 break;
4058 case 2:
4059 check_insn(env, ctx, ASE_MT);
4060 tcg_gen_helper_1_0(do_mfc0_mvpconf0, t0);
4061 rn = "MVPConf0";
4062 break;
4063 case 3:
4064 check_insn(env, ctx, ASE_MT);
4065 tcg_gen_helper_1_0(do_mfc0_mvpconf1, t0);
4066 rn = "MVPConf1";
4067 break;
4068 default:
4069 goto die;
4071 break;
4072 case 1:
4073 switch (sel) {
4074 case 0:
4075 tcg_gen_helper_1_0(do_mfc0_random, t0);
4076 rn = "Random";
4077 break;
4078 case 1:
4079 check_insn(env, ctx, ASE_MT);
4080 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
4081 rn = "VPEControl";
4082 break;
4083 case 2:
4084 check_insn(env, ctx, ASE_MT);
4085 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
4086 rn = "VPEConf0";
4087 break;
4088 case 3:
4089 check_insn(env, ctx, ASE_MT);
4090 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
4091 rn = "VPEConf1";
4092 break;
4093 case 4:
4094 check_insn(env, ctx, ASE_MT);
4095 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask));
4096 rn = "YQMask";
4097 break;
4098 case 5:
4099 check_insn(env, ctx, ASE_MT);
4100 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4101 rn = "VPESchedule";
4102 break;
4103 case 6:
4104 check_insn(env, ctx, ASE_MT);
4105 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4106 rn = "VPEScheFBack";
4107 break;
4108 case 7:
4109 check_insn(env, ctx, ASE_MT);
4110 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
4111 rn = "VPEOpt";
4112 break;
4113 default:
4114 goto die;
4116 break;
4117 case 2:
4118 switch (sel) {
4119 case 0:
4120 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4121 rn = "EntryLo0";
4122 break;
4123 case 1:
4124 check_insn(env, ctx, ASE_MT);
4125 tcg_gen_helper_1_0(do_mfc0_tcstatus, t0);
4126 rn = "TCStatus";
4127 break;
4128 case 2:
4129 check_insn(env, ctx, ASE_MT);
4130 tcg_gen_helper_1_0(do_mfc0_tcbind, t0);
4131 rn = "TCBind";
4132 break;
4133 case 3:
4134 check_insn(env, ctx, ASE_MT);
4135 tcg_gen_helper_1_0(do_dmfc0_tcrestart, t0);
4136 rn = "TCRestart";
4137 break;
4138 case 4:
4139 check_insn(env, ctx, ASE_MT);
4140 tcg_gen_helper_1_0(do_dmfc0_tchalt, t0);
4141 rn = "TCHalt";
4142 break;
4143 case 5:
4144 check_insn(env, ctx, ASE_MT);
4145 tcg_gen_helper_1_0(do_dmfc0_tccontext, t0);
4146 rn = "TCContext";
4147 break;
4148 case 6:
4149 check_insn(env, ctx, ASE_MT);
4150 tcg_gen_helper_1_0(do_dmfc0_tcschedule, t0);
4151 rn = "TCSchedule";
4152 break;
4153 case 7:
4154 check_insn(env, ctx, ASE_MT);
4155 tcg_gen_helper_1_0(do_dmfc0_tcschefback, t0);
4156 rn = "TCScheFBack";
4157 break;
4158 default:
4159 goto die;
4161 break;
4162 case 3:
4163 switch (sel) {
4164 case 0:
4165 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4166 rn = "EntryLo1";
4167 break;
4168 default:
4169 goto die;
4171 break;
4172 case 4:
4173 switch (sel) {
4174 case 0:
4175 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
4176 rn = "Context";
4177 break;
4178 case 1:
4179 // tcg_gen_helper_1_0(do_dmfc0_contextconfig, t0); /* SmartMIPS ASE */
4180 rn = "ContextConfig";
4181 // break;
4182 default:
4183 goto die;
4185 break;
4186 case 5:
4187 switch (sel) {
4188 case 0:
4189 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
4190 rn = "PageMask";
4191 break;
4192 case 1:
4193 check_insn(env, ctx, ISA_MIPS32R2);
4194 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
4195 rn = "PageGrain";
4196 break;
4197 default:
4198 goto die;
4200 break;
4201 case 6:
4202 switch (sel) {
4203 case 0:
4204 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
4205 rn = "Wired";
4206 break;
4207 case 1:
4208 check_insn(env, ctx, ISA_MIPS32R2);
4209 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
4210 rn = "SRSConf0";
4211 break;
4212 case 2:
4213 check_insn(env, ctx, ISA_MIPS32R2);
4214 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
4215 rn = "SRSConf1";
4216 break;
4217 case 3:
4218 check_insn(env, ctx, ISA_MIPS32R2);
4219 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
4220 rn = "SRSConf2";
4221 break;
4222 case 4:
4223 check_insn(env, ctx, ISA_MIPS32R2);
4224 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
4225 rn = "SRSConf3";
4226 break;
4227 case 5:
4228 check_insn(env, ctx, ISA_MIPS32R2);
4229 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
4230 rn = "SRSConf4";
4231 break;
4232 default:
4233 goto die;
4235 break;
4236 case 7:
4237 switch (sel) {
4238 case 0:
4239 check_insn(env, ctx, ISA_MIPS32R2);
4240 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
4241 rn = "HWREna";
4242 break;
4243 default:
4244 goto die;
4246 break;
4247 case 8:
4248 switch (sel) {
4249 case 0:
4250 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4251 rn = "BadVAddr";
4252 break;
4253 default:
4254 goto die;
4256 break;
4257 case 9:
4258 switch (sel) {
4259 case 0:
4260 /* Mark as an IO operation because we read the time. */
4261 if (use_icount)
4262 gen_io_start();
4263 tcg_gen_helper_1_0(do_mfc0_count, t0);
4264 if (use_icount) {
4265 gen_io_end();
4266 ctx->bstate = BS_STOP;
4268 rn = "Count";
4269 break;
4270 /* 6,7 are implementation dependent */
4271 default:
4272 goto die;
4274 break;
4275 case 10:
4276 switch (sel) {
4277 case 0:
4278 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
4279 rn = "EntryHi";
4280 break;
4281 default:
4282 goto die;
4284 break;
4285 case 11:
4286 switch (sel) {
4287 case 0:
4288 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
4289 rn = "Compare";
4290 break;
4291 /* 6,7 are implementation dependent */
4292 default:
4293 goto die;
4295 break;
4296 case 12:
4297 switch (sel) {
4298 case 0:
4299 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
4300 rn = "Status";
4301 break;
4302 case 1:
4303 check_insn(env, ctx, ISA_MIPS32R2);
4304 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
4305 rn = "IntCtl";
4306 break;
4307 case 2:
4308 check_insn(env, ctx, ISA_MIPS32R2);
4309 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
4310 rn = "SRSCtl";
4311 break;
4312 case 3:
4313 check_insn(env, ctx, ISA_MIPS32R2);
4314 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
4315 rn = "SRSMap";
4316 break;
4317 default:
4318 goto die;
4320 break;
4321 case 13:
4322 switch (sel) {
4323 case 0:
4324 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
4325 rn = "Cause";
4326 break;
4327 default:
4328 goto die;
4330 break;
4331 case 14:
4332 switch (sel) {
4333 case 0:
4334 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4335 rn = "EPC";
4336 break;
4337 default:
4338 goto die;
4340 break;
4341 case 15:
4342 switch (sel) {
4343 case 0:
4344 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
4345 rn = "PRid";
4346 break;
4347 case 1:
4348 check_insn(env, ctx, ISA_MIPS32R2);
4349 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
4350 rn = "EBase";
4351 break;
4352 default:
4353 goto die;
4355 break;
4356 case 16:
4357 switch (sel) {
4358 case 0:
4359 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
4360 rn = "Config";
4361 break;
4362 case 1:
4363 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
4364 rn = "Config1";
4365 break;
4366 case 2:
4367 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
4368 rn = "Config2";
4369 break;
4370 case 3:
4371 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
4372 rn = "Config3";
4373 break;
4374 /* 6,7 are implementation dependent */
4375 case 6:
4376 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
4377 rn = "Config6";
4378 break;
4379 case 7:
4380 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
4381 rn = "Config7";
4382 break;
4383 default:
4384 goto die;
4386 break;
4387 case 17:
4388 switch (sel) {
4389 case 0:
4390 tcg_gen_helper_1_0(do_dmfc0_lladdr, t0);
4391 rn = "LLAddr";
4392 break;
4393 default:
4394 goto die;
4396 break;
4397 case 18:
4398 switch (sel) {
4399 case 0 ... 7:
4400 tcg_gen_helper_1_i(do_dmfc0_watchlo, t0, sel);
4401 rn = "WatchLo";
4402 break;
4403 default:
4404 goto die;
4406 break;
4407 case 19:
4408 switch (sel) {
4409 case 0 ... 7:
4410 tcg_gen_helper_1_i(do_mfc0_watchhi, t0, sel);
4411 rn = "WatchHi";
4412 break;
4413 default:
4414 goto die;
4416 break;
4417 case 20:
4418 switch (sel) {
4419 case 0:
4420 check_insn(env, ctx, ISA_MIPS3);
4421 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
4422 rn = "XContext";
4423 break;
4424 default:
4425 goto die;
4427 break;
4428 case 21:
4429 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4430 switch (sel) {
4431 case 0:
4432 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
4433 rn = "Framemask";
4434 break;
4435 default:
4436 goto die;
4438 break;
4439 case 22:
4440 /* ignored */
4441 rn = "'Diagnostic"; /* implementation dependent */
4442 break;
4443 case 23:
4444 switch (sel) {
4445 case 0:
4446 tcg_gen_helper_1_0(do_mfc0_debug, t0); /* EJTAG support */
4447 rn = "Debug";
4448 break;
4449 case 1:
4450 // tcg_gen_helper_1_0(do_dmfc0_tracecontrol, t0); /* PDtrace support */
4451 rn = "TraceControl";
4452 // break;
4453 case 2:
4454 // tcg_gen_helper_1_0(do_dmfc0_tracecontrol2, t0); /* PDtrace support */
4455 rn = "TraceControl2";
4456 // break;
4457 case 3:
4458 // tcg_gen_helper_1_0(do_dmfc0_usertracedata, t0); /* PDtrace support */
4459 rn = "UserTraceData";
4460 // break;
4461 case 4:
4462 // tcg_gen_helper_1_0(do_dmfc0_tracebpc, t0); /* PDtrace support */
4463 rn = "TraceBPC";
4464 // break;
4465 default:
4466 goto die;
4468 break;
4469 case 24:
4470 switch (sel) {
4471 case 0:
4472 /* EJTAG support */
4473 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
4474 rn = "DEPC";
4475 break;
4476 default:
4477 goto die;
4479 break;
4480 case 25:
4481 switch (sel) {
4482 case 0:
4483 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
4484 rn = "Performance0";
4485 break;
4486 case 1:
4487 // tcg_gen_helper_1_0(do_dmfc0_performance1, t0);
4488 rn = "Performance1";
4489 // break;
4490 case 2:
4491 // tcg_gen_helper_1_0(do_dmfc0_performance2, t0);
4492 rn = "Performance2";
4493 // break;
4494 case 3:
4495 // tcg_gen_helper_1_0(do_dmfc0_performance3, t0);
4496 rn = "Performance3";
4497 // break;
4498 case 4:
4499 // tcg_gen_helper_1_0(do_dmfc0_performance4, t0);
4500 rn = "Performance4";
4501 // break;
4502 case 5:
4503 // tcg_gen_helper_1_0(do_dmfc0_performance5, t0);
4504 rn = "Performance5";
4505 // break;
4506 case 6:
4507 // tcg_gen_helper_1_0(do_dmfc0_performance6, t0);
4508 rn = "Performance6";
4509 // break;
4510 case 7:
4511 // tcg_gen_helper_1_0(do_dmfc0_performance7, t0);
4512 rn = "Performance7";
4513 // break;
4514 default:
4515 goto die;
4517 break;
4518 case 26:
4519 rn = "ECC";
4520 break;
4521 case 27:
4522 switch (sel) {
4523 /* ignored */
4524 case 0 ... 3:
4525 rn = "CacheErr";
4526 break;
4527 default:
4528 goto die;
4530 break;
4531 case 28:
4532 switch (sel) {
4533 case 0:
4534 case 2:
4535 case 4:
4536 case 6:
4537 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
4538 rn = "TagLo";
4539 break;
4540 case 1:
4541 case 3:
4542 case 5:
4543 case 7:
4544 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
4545 rn = "DataLo";
4546 break;
4547 default:
4548 goto die;
4550 break;
4551 case 29:
4552 switch (sel) {
4553 case 0:
4554 case 2:
4555 case 4:
4556 case 6:
4557 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
4558 rn = "TagHi";
4559 break;
4560 case 1:
4561 case 3:
4562 case 5:
4563 case 7:
4564 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
4565 rn = "DataHi";
4566 break;
4567 default:
4568 goto die;
4570 break;
4571 case 30:
4572 switch (sel) {
4573 case 0:
4574 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4575 rn = "ErrorEPC";
4576 break;
4577 default:
4578 goto die;
4580 break;
4581 case 31:
4582 switch (sel) {
4583 case 0:
4584 /* EJTAG support */
4585 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
4586 rn = "DESAVE";
4587 break;
4588 default:
4589 goto die;
4591 break;
4592 default:
4593 goto die;
4595 #if defined MIPS_DEBUG_DISAS
4596 if (loglevel & CPU_LOG_TB_IN_ASM) {
4597 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4598 rn, reg, sel);
4600 #endif
4601 return;
4603 die:
4604 #if defined MIPS_DEBUG_DISAS
4605 if (loglevel & CPU_LOG_TB_IN_ASM) {
4606 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4607 rn, reg, sel);
4609 #endif
4610 generate_exception(ctx, EXCP_RI);
4613 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
4615 const char *rn = "invalid";
4617 if (sel != 0)
4618 check_insn(env, ctx, ISA_MIPS64);
4620 if (use_icount)
4621 gen_io_start();
4623 switch (reg) {
4624 case 0:
4625 switch (sel) {
4626 case 0:
4627 tcg_gen_helper_0_1(do_mtc0_index, t0);
4628 rn = "Index";
4629 break;
4630 case 1:
4631 check_insn(env, ctx, ASE_MT);
4632 tcg_gen_helper_0_1(do_mtc0_mvpcontrol, t0);
4633 rn = "MVPControl";
4634 break;
4635 case 2:
4636 check_insn(env, ctx, ASE_MT);
4637 /* ignored */
4638 rn = "MVPConf0";
4639 break;
4640 case 3:
4641 check_insn(env, ctx, ASE_MT);
4642 /* ignored */
4643 rn = "MVPConf1";
4644 break;
4645 default:
4646 goto die;
4648 break;
4649 case 1:
4650 switch (sel) {
4651 case 0:
4652 /* ignored */
4653 rn = "Random";
4654 break;
4655 case 1:
4656 check_insn(env, ctx, ASE_MT);
4657 tcg_gen_helper_0_1(do_mtc0_vpecontrol, t0);
4658 rn = "VPEControl";
4659 break;
4660 case 2:
4661 check_insn(env, ctx, ASE_MT);
4662 tcg_gen_helper_0_1(do_mtc0_vpeconf0, t0);
4663 rn = "VPEConf0";
4664 break;
4665 case 3:
4666 check_insn(env, ctx, ASE_MT);
4667 tcg_gen_helper_0_1(do_mtc0_vpeconf1, t0);
4668 rn = "VPEConf1";
4669 break;
4670 case 4:
4671 check_insn(env, ctx, ASE_MT);
4672 tcg_gen_helper_0_1(do_mtc0_yqmask, t0);
4673 rn = "YQMask";
4674 break;
4675 case 5:
4676 check_insn(env, ctx, ASE_MT);
4677 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4678 rn = "VPESchedule";
4679 break;
4680 case 6:
4681 check_insn(env, ctx, ASE_MT);
4682 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4683 rn = "VPEScheFBack";
4684 break;
4685 case 7:
4686 check_insn(env, ctx, ASE_MT);
4687 tcg_gen_helper_0_1(do_mtc0_vpeopt, t0);
4688 rn = "VPEOpt";
4689 break;
4690 default:
4691 goto die;
4693 break;
4694 case 2:
4695 switch (sel) {
4696 case 0:
4697 tcg_gen_helper_0_1(do_mtc0_entrylo0, t0);
4698 rn = "EntryLo0";
4699 break;
4700 case 1:
4701 check_insn(env, ctx, ASE_MT);
4702 tcg_gen_helper_0_1(do_mtc0_tcstatus, t0);
4703 rn = "TCStatus";
4704 break;
4705 case 2:
4706 check_insn(env, ctx, ASE_MT);
4707 tcg_gen_helper_0_1(do_mtc0_tcbind, t0);
4708 rn = "TCBind";
4709 break;
4710 case 3:
4711 check_insn(env, ctx, ASE_MT);
4712 tcg_gen_helper_0_1(do_mtc0_tcrestart, t0);
4713 rn = "TCRestart";
4714 break;
4715 case 4:
4716 check_insn(env, ctx, ASE_MT);
4717 tcg_gen_helper_0_1(do_mtc0_tchalt, t0);
4718 rn = "TCHalt";
4719 break;
4720 case 5:
4721 check_insn(env, ctx, ASE_MT);
4722 tcg_gen_helper_0_1(do_mtc0_tccontext, t0);
4723 rn = "TCContext";
4724 break;
4725 case 6:
4726 check_insn(env, ctx, ASE_MT);
4727 tcg_gen_helper_0_1(do_mtc0_tcschedule, t0);
4728 rn = "TCSchedule";
4729 break;
4730 case 7:
4731 check_insn(env, ctx, ASE_MT);
4732 tcg_gen_helper_0_1(do_mtc0_tcschefback, t0);
4733 rn = "TCScheFBack";
4734 break;
4735 default:
4736 goto die;
4738 break;
4739 case 3:
4740 switch (sel) {
4741 case 0:
4742 tcg_gen_helper_0_1(do_mtc0_entrylo1, t0);
4743 rn = "EntryLo1";
4744 break;
4745 default:
4746 goto die;
4748 break;
4749 case 4:
4750 switch (sel) {
4751 case 0:
4752 tcg_gen_helper_0_1(do_mtc0_context, t0);
4753 rn = "Context";
4754 break;
4755 case 1:
4756 // tcg_gen_helper_0_1(do_mtc0_contextconfig, t0); /* SmartMIPS ASE */
4757 rn = "ContextConfig";
4758 // break;
4759 default:
4760 goto die;
4762 break;
4763 case 5:
4764 switch (sel) {
4765 case 0:
4766 tcg_gen_helper_0_1(do_mtc0_pagemask, t0);
4767 rn = "PageMask";
4768 break;
4769 case 1:
4770 check_insn(env, ctx, ISA_MIPS32R2);
4771 tcg_gen_helper_0_1(do_mtc0_pagegrain, t0);
4772 rn = "PageGrain";
4773 break;
4774 default:
4775 goto die;
4777 break;
4778 case 6:
4779 switch (sel) {
4780 case 0:
4781 tcg_gen_helper_0_1(do_mtc0_wired, t0);
4782 rn = "Wired";
4783 break;
4784 case 1:
4785 check_insn(env, ctx, ISA_MIPS32R2);
4786 tcg_gen_helper_0_1(do_mtc0_srsconf0, t0);
4787 rn = "SRSConf0";
4788 break;
4789 case 2:
4790 check_insn(env, ctx, ISA_MIPS32R2);
4791 tcg_gen_helper_0_1(do_mtc0_srsconf1, t0);
4792 rn = "SRSConf1";
4793 break;
4794 case 3:
4795 check_insn(env, ctx, ISA_MIPS32R2);
4796 tcg_gen_helper_0_1(do_mtc0_srsconf2, t0);
4797 rn = "SRSConf2";
4798 break;
4799 case 4:
4800 check_insn(env, ctx, ISA_MIPS32R2);
4801 tcg_gen_helper_0_1(do_mtc0_srsconf3, t0);
4802 rn = "SRSConf3";
4803 break;
4804 case 5:
4805 check_insn(env, ctx, ISA_MIPS32R2);
4806 tcg_gen_helper_0_1(do_mtc0_srsconf4, t0);
4807 rn = "SRSConf4";
4808 break;
4809 default:
4810 goto die;
4812 break;
4813 case 7:
4814 switch (sel) {
4815 case 0:
4816 check_insn(env, ctx, ISA_MIPS32R2);
4817 tcg_gen_helper_0_1(do_mtc0_hwrena, t0);
4818 rn = "HWREna";
4819 break;
4820 default:
4821 goto die;
4823 break;
4824 case 8:
4825 /* ignored */
4826 rn = "BadVAddr";
4827 break;
4828 case 9:
4829 switch (sel) {
4830 case 0:
4831 tcg_gen_helper_0_1(do_mtc0_count, t0);
4832 rn = "Count";
4833 break;
4834 /* 6,7 are implementation dependent */
4835 default:
4836 goto die;
4838 /* Stop translation as we may have switched the execution mode */
4839 ctx->bstate = BS_STOP;
4840 break;
4841 case 10:
4842 switch (sel) {
4843 case 0:
4844 tcg_gen_helper_0_1(do_mtc0_entryhi, t0);
4845 rn = "EntryHi";
4846 break;
4847 default:
4848 goto die;
4850 break;
4851 case 11:
4852 switch (sel) {
4853 case 0:
4854 tcg_gen_helper_0_1(do_mtc0_compare, t0);
4855 rn = "Compare";
4856 break;
4857 /* 6,7 are implementation dependent */
4858 default:
4859 goto die;
4861 /* Stop translation as we may have switched the execution mode */
4862 ctx->bstate = BS_STOP;
4863 break;
4864 case 12:
4865 switch (sel) {
4866 case 0:
4867 tcg_gen_helper_0_1(do_mtc0_status, t0);
4868 /* BS_STOP isn't good enough here, hflags may have changed. */
4869 gen_save_pc(ctx->pc + 4);
4870 ctx->bstate = BS_EXCP;
4871 rn = "Status";
4872 break;
4873 case 1:
4874 check_insn(env, ctx, ISA_MIPS32R2);
4875 tcg_gen_helper_0_1(do_mtc0_intctl, t0);
4876 /* Stop translation as we may have switched the execution mode */
4877 ctx->bstate = BS_STOP;
4878 rn = "IntCtl";
4879 break;
4880 case 2:
4881 check_insn(env, ctx, ISA_MIPS32R2);
4882 tcg_gen_helper_0_1(do_mtc0_srsctl, t0);
4883 /* Stop translation as we may have switched the execution mode */
4884 ctx->bstate = BS_STOP;
4885 rn = "SRSCtl";
4886 break;
4887 case 3:
4888 check_insn(env, ctx, ISA_MIPS32R2);
4889 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
4890 /* Stop translation as we may have switched the execution mode */
4891 ctx->bstate = BS_STOP;
4892 rn = "SRSMap";
4893 break;
4894 default:
4895 goto die;
4897 break;
4898 case 13:
4899 switch (sel) {
4900 case 0:
4901 tcg_gen_helper_0_1(do_mtc0_cause, t0);
4902 rn = "Cause";
4903 break;
4904 default:
4905 goto die;
4907 /* Stop translation as we may have switched the execution mode */
4908 ctx->bstate = BS_STOP;
4909 break;
4910 case 14:
4911 switch (sel) {
4912 case 0:
4913 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4914 rn = "EPC";
4915 break;
4916 default:
4917 goto die;
4919 break;
4920 case 15:
4921 switch (sel) {
4922 case 0:
4923 /* ignored */
4924 rn = "PRid";
4925 break;
4926 case 1:
4927 check_insn(env, ctx, ISA_MIPS32R2);
4928 tcg_gen_helper_0_1(do_mtc0_ebase, t0);
4929 rn = "EBase";
4930 break;
4931 default:
4932 goto die;
4934 break;
4935 case 16:
4936 switch (sel) {
4937 case 0:
4938 tcg_gen_helper_0_1(do_mtc0_config0, t0);
4939 rn = "Config";
4940 /* Stop translation as we may have switched the execution mode */
4941 ctx->bstate = BS_STOP;
4942 break;
4943 case 1:
4944 /* ignored */
4945 rn = "Config1";
4946 break;
4947 case 2:
4948 tcg_gen_helper_0_1(do_mtc0_config2, t0);
4949 rn = "Config2";
4950 /* Stop translation as we may have switched the execution mode */
4951 ctx->bstate = BS_STOP;
4952 break;
4953 case 3:
4954 /* ignored */
4955 rn = "Config3";
4956 break;
4957 /* 6,7 are implementation dependent */
4958 default:
4959 rn = "Invalid config selector";
4960 goto die;
4962 break;
4963 case 17:
4964 switch (sel) {
4965 case 0:
4966 /* ignored */
4967 rn = "LLAddr";
4968 break;
4969 default:
4970 goto die;
4972 break;
4973 case 18:
4974 switch (sel) {
4975 case 0 ... 7:
4976 tcg_gen_helper_0_1i(do_mtc0_watchlo, t0, sel);
4977 rn = "WatchLo";
4978 break;
4979 default:
4980 goto die;
4982 break;
4983 case 19:
4984 switch (sel) {
4985 case 0 ... 7:
4986 tcg_gen_helper_0_1i(do_mtc0_watchhi, t0, sel);
4987 rn = "WatchHi";
4988 break;
4989 default:
4990 goto die;
4992 break;
4993 case 20:
4994 switch (sel) {
4995 case 0:
4996 check_insn(env, ctx, ISA_MIPS3);
4997 tcg_gen_helper_0_1(do_mtc0_xcontext, t0);
4998 rn = "XContext";
4999 break;
5000 default:
5001 goto die;
5003 break;
5004 case 21:
5005 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5006 switch (sel) {
5007 case 0:
5008 tcg_gen_helper_0_1(do_mtc0_framemask, t0);
5009 rn = "Framemask";
5010 break;
5011 default:
5012 goto die;
5014 break;
5015 case 22:
5016 /* ignored */
5017 rn = "Diagnostic"; /* implementation dependent */
5018 break;
5019 case 23:
5020 switch (sel) {
5021 case 0:
5022 tcg_gen_helper_0_1(do_mtc0_debug, t0); /* EJTAG support */
5023 /* BS_STOP isn't good enough here, hflags may have changed. */
5024 gen_save_pc(ctx->pc + 4);
5025 ctx->bstate = BS_EXCP;
5026 rn = "Debug";
5027 break;
5028 case 1:
5029 // tcg_gen_helper_0_1(do_mtc0_tracecontrol, t0); /* PDtrace support */
5030 /* Stop translation as we may have switched the execution mode */
5031 ctx->bstate = BS_STOP;
5032 rn = "TraceControl";
5033 // break;
5034 case 2:
5035 // tcg_gen_helper_0_1(do_mtc0_tracecontrol2, t0); /* PDtrace support */
5036 /* Stop translation as we may have switched the execution mode */
5037 ctx->bstate = BS_STOP;
5038 rn = "TraceControl2";
5039 // break;
5040 case 3:
5041 // tcg_gen_helper_0_1(do_mtc0_usertracedata, t0); /* PDtrace support */
5042 /* Stop translation as we may have switched the execution mode */
5043 ctx->bstate = BS_STOP;
5044 rn = "UserTraceData";
5045 // break;
5046 case 4:
5047 // tcg_gen_helper_0_1(do_mtc0_tracebpc, t0); /* PDtrace support */
5048 /* Stop translation as we may have switched the execution mode */
5049 ctx->bstate = BS_STOP;
5050 rn = "TraceBPC";
5051 // break;
5052 default:
5053 goto die;
5055 break;
5056 case 24:
5057 switch (sel) {
5058 case 0:
5059 /* EJTAG support */
5060 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
5061 rn = "DEPC";
5062 break;
5063 default:
5064 goto die;
5066 break;
5067 case 25:
5068 switch (sel) {
5069 case 0:
5070 tcg_gen_helper_0_1(do_mtc0_performance0, t0);
5071 rn = "Performance0";
5072 break;
5073 case 1:
5074 // tcg_gen_helper_0_1(do_mtc0_performance1, t0);
5075 rn = "Performance1";
5076 // break;
5077 case 2:
5078 // tcg_gen_helper_0_1(do_mtc0_performance2, t0);
5079 rn = "Performance2";
5080 // break;
5081 case 3:
5082 // tcg_gen_helper_0_1(do_mtc0_performance3, t0);
5083 rn = "Performance3";
5084 // break;
5085 case 4:
5086 // tcg_gen_helper_0_1(do_mtc0_performance4, t0);
5087 rn = "Performance4";
5088 // break;
5089 case 5:
5090 // tcg_gen_helper_0_1(do_mtc0_performance5, t0);
5091 rn = "Performance5";
5092 // break;
5093 case 6:
5094 // tcg_gen_helper_0_1(do_mtc0_performance6, t0);
5095 rn = "Performance6";
5096 // break;
5097 case 7:
5098 // tcg_gen_helper_0_1(do_mtc0_performance7, t0);
5099 rn = "Performance7";
5100 // break;
5101 default:
5102 goto die;
5104 break;
5105 case 26:
5106 /* ignored */
5107 rn = "ECC";
5108 break;
5109 case 27:
5110 switch (sel) {
5111 case 0 ... 3:
5112 /* ignored */
5113 rn = "CacheErr";
5114 break;
5115 default:
5116 goto die;
5118 break;
5119 case 28:
5120 switch (sel) {
5121 case 0:
5122 case 2:
5123 case 4:
5124 case 6:
5125 tcg_gen_helper_0_1(do_mtc0_taglo, t0);
5126 rn = "TagLo";
5127 break;
5128 case 1:
5129 case 3:
5130 case 5:
5131 case 7:
5132 tcg_gen_helper_0_1(do_mtc0_datalo, t0);
5133 rn = "DataLo";
5134 break;
5135 default:
5136 goto die;
5138 break;
5139 case 29:
5140 switch (sel) {
5141 case 0:
5142 case 2:
5143 case 4:
5144 case 6:
5145 tcg_gen_helper_0_1(do_mtc0_taghi, t0);
5146 rn = "TagHi";
5147 break;
5148 case 1:
5149 case 3:
5150 case 5:
5151 case 7:
5152 tcg_gen_helper_0_1(do_mtc0_datahi, t0);
5153 rn = "DataHi";
5154 break;
5155 default:
5156 rn = "invalid sel";
5157 goto die;
5159 break;
5160 case 30:
5161 switch (sel) {
5162 case 0:
5163 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5164 rn = "ErrorEPC";
5165 break;
5166 default:
5167 goto die;
5169 break;
5170 case 31:
5171 switch (sel) {
5172 case 0:
5173 /* EJTAG support */
5174 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
5175 rn = "DESAVE";
5176 break;
5177 default:
5178 goto die;
5180 /* Stop translation as we may have switched the execution mode */
5181 ctx->bstate = BS_STOP;
5182 break;
5183 default:
5184 goto die;
5186 #if defined MIPS_DEBUG_DISAS
5187 if (loglevel & CPU_LOG_TB_IN_ASM) {
5188 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5189 rn, reg, sel);
5191 #endif
5192 tcg_temp_free(t0);
5193 /* For simplicity assume that all writes can cause interrupts. */
5194 if (use_icount) {
5195 gen_io_end();
5196 ctx->bstate = BS_STOP;
5198 return;
5200 die:
5201 tcg_temp_free(t0);
5202 #if defined MIPS_DEBUG_DISAS
5203 if (loglevel & CPU_LOG_TB_IN_ASM) {
5204 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5205 rn, reg, sel);
5207 #endif
5208 generate_exception(ctx, EXCP_RI);
5210 #endif /* TARGET_MIPS64 */
5212 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5213 int u, int sel, int h)
5215 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5216 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5218 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5219 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5220 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5221 tcg_gen_movi_tl(t0, -1);
5222 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5223 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5224 tcg_gen_movi_tl(t0, -1);
5225 else if (u == 0) {
5226 switch (rt) {
5227 case 2:
5228 switch (sel) {
5229 case 1:
5230 tcg_gen_helper_1_1(do_mftc0_tcstatus, t0, t0);
5231 break;
5232 case 2:
5233 tcg_gen_helper_1_1(do_mftc0_tcbind, t0, t0);
5234 break;
5235 case 3:
5236 tcg_gen_helper_1_1(do_mftc0_tcrestart, t0, t0);
5237 break;
5238 case 4:
5239 tcg_gen_helper_1_1(do_mftc0_tchalt, t0, t0);
5240 break;
5241 case 5:
5242 tcg_gen_helper_1_1(do_mftc0_tccontext, t0, t0);
5243 break;
5244 case 6:
5245 tcg_gen_helper_1_1(do_mftc0_tcschedule, t0, t0);
5246 break;
5247 case 7:
5248 tcg_gen_helper_1_1(do_mftc0_tcschefback, t0, t0);
5249 break;
5250 default:
5251 gen_mfc0(env, ctx, t0, rt, sel);
5252 break;
5254 break;
5255 case 10:
5256 switch (sel) {
5257 case 0:
5258 tcg_gen_helper_1_1(do_mftc0_entryhi, t0, t0);
5259 break;
5260 default:
5261 gen_mfc0(env, ctx, t0, rt, sel);
5262 break;
5264 case 12:
5265 switch (sel) {
5266 case 0:
5267 tcg_gen_helper_1_1(do_mftc0_status, t0, t0);
5268 break;
5269 default:
5270 gen_mfc0(env, ctx, t0, rt, sel);
5271 break;
5273 case 23:
5274 switch (sel) {
5275 case 0:
5276 tcg_gen_helper_1_1(do_mftc0_debug, t0, t0);
5277 break;
5278 default:
5279 gen_mfc0(env, ctx, t0, rt, sel);
5280 break;
5282 break;
5283 default:
5284 gen_mfc0(env, ctx, t0, rt, sel);
5286 } else switch (sel) {
5287 /* GPR registers. */
5288 case 0:
5289 tcg_gen_helper_1_1i(do_mftgpr, t0, t0, rt);
5290 break;
5291 /* Auxiliary CPU registers */
5292 case 1:
5293 switch (rt) {
5294 case 0:
5295 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 0);
5296 break;
5297 case 1:
5298 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 0);
5299 break;
5300 case 2:
5301 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 0);
5302 break;
5303 case 4:
5304 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 1);
5305 break;
5306 case 5:
5307 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 1);
5308 break;
5309 case 6:
5310 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 1);
5311 break;
5312 case 8:
5313 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 2);
5314 break;
5315 case 9:
5316 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 2);
5317 break;
5318 case 10:
5319 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 2);
5320 break;
5321 case 12:
5322 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 3);
5323 break;
5324 case 13:
5325 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 3);
5326 break;
5327 case 14:
5328 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 3);
5329 break;
5330 case 16:
5331 tcg_gen_helper_1_1(do_mftdsp, t0, t0);
5332 break;
5333 default:
5334 goto die;
5336 break;
5337 /* Floating point (COP1). */
5338 case 2:
5339 /* XXX: For now we support only a single FPU context. */
5340 if (h == 0) {
5341 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5343 gen_load_fpr32(fp0, rt);
5344 tcg_gen_ext_i32_tl(t0, fp0);
5345 tcg_temp_free(fp0);
5346 } else {
5347 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5349 gen_load_fpr32h(fp0, rt);
5350 tcg_gen_ext_i32_tl(t0, fp0);
5351 tcg_temp_free(fp0);
5353 break;
5354 case 3:
5355 /* XXX: For now we support only a single FPU context. */
5356 tcg_gen_helper_1_1i(do_cfc1, t0, t0, rt);
5357 break;
5358 /* COP2: Not implemented. */
5359 case 4:
5360 case 5:
5361 /* fall through */
5362 default:
5363 goto die;
5365 #if defined MIPS_DEBUG_DISAS
5366 if (loglevel & CPU_LOG_TB_IN_ASM) {
5367 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5368 rt, u, sel, h);
5370 #endif
5371 gen_store_gpr(t0, rd);
5372 tcg_temp_free(t0);
5373 return;
5375 die:
5376 tcg_temp_free(t0);
5377 #if defined MIPS_DEBUG_DISAS
5378 if (loglevel & CPU_LOG_TB_IN_ASM) {
5379 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5380 rt, u, sel, h);
5382 #endif
5383 generate_exception(ctx, EXCP_RI);
5386 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5387 int u, int sel, int h)
5389 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5390 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5392 gen_load_gpr(t0, rt);
5393 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5394 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5395 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5396 /* NOP */ ;
5397 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5398 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5399 /* NOP */ ;
5400 else if (u == 0) {
5401 switch (rd) {
5402 case 2:
5403 switch (sel) {
5404 case 1:
5405 tcg_gen_helper_0_1(do_mttc0_tcstatus, t0);
5406 break;
5407 case 2:
5408 tcg_gen_helper_0_1(do_mttc0_tcbind, t0);
5409 break;
5410 case 3:
5411 tcg_gen_helper_0_1(do_mttc0_tcrestart, t0);
5412 break;
5413 case 4:
5414 tcg_gen_helper_0_1(do_mttc0_tchalt, t0);
5415 break;
5416 case 5:
5417 tcg_gen_helper_0_1(do_mttc0_tccontext, t0);
5418 break;
5419 case 6:
5420 tcg_gen_helper_0_1(do_mttc0_tcschedule, t0);
5421 break;
5422 case 7:
5423 tcg_gen_helper_0_1(do_mttc0_tcschefback, t0);
5424 break;
5425 default:
5426 gen_mtc0(env, ctx, t0, rd, sel);
5427 break;
5429 break;
5430 case 10:
5431 switch (sel) {
5432 case 0:
5433 tcg_gen_helper_0_1(do_mttc0_entryhi, t0);
5434 break;
5435 default:
5436 gen_mtc0(env, ctx, t0, rd, sel);
5437 break;
5439 case 12:
5440 switch (sel) {
5441 case 0:
5442 tcg_gen_helper_0_1(do_mttc0_status, t0);
5443 break;
5444 default:
5445 gen_mtc0(env, ctx, t0, rd, sel);
5446 break;
5448 case 23:
5449 switch (sel) {
5450 case 0:
5451 tcg_gen_helper_0_1(do_mttc0_debug, t0);
5452 break;
5453 default:
5454 gen_mtc0(env, ctx, t0, rd, sel);
5455 break;
5457 break;
5458 default:
5459 gen_mtc0(env, ctx, t0, rd, sel);
5461 } else switch (sel) {
5462 /* GPR registers. */
5463 case 0:
5464 tcg_gen_helper_0_1i(do_mttgpr, t0, rd);
5465 break;
5466 /* Auxiliary CPU registers */
5467 case 1:
5468 switch (rd) {
5469 case 0:
5470 tcg_gen_helper_0_1i(do_mttlo, t0, 0);
5471 break;
5472 case 1:
5473 tcg_gen_helper_0_1i(do_mtthi, t0, 0);
5474 break;
5475 case 2:
5476 tcg_gen_helper_0_1i(do_mttacx, t0, 0);
5477 break;
5478 case 4:
5479 tcg_gen_helper_0_1i(do_mttlo, t0, 1);
5480 break;
5481 case 5:
5482 tcg_gen_helper_0_1i(do_mtthi, t0, 1);
5483 break;
5484 case 6:
5485 tcg_gen_helper_0_1i(do_mttacx, t0, 1);
5486 break;
5487 case 8:
5488 tcg_gen_helper_0_1i(do_mttlo, t0, 2);
5489 break;
5490 case 9:
5491 tcg_gen_helper_0_1i(do_mtthi, t0, 2);
5492 break;
5493 case 10:
5494 tcg_gen_helper_0_1i(do_mttacx, t0, 2);
5495 break;
5496 case 12:
5497 tcg_gen_helper_0_1i(do_mttlo, t0, 3);
5498 break;
5499 case 13:
5500 tcg_gen_helper_0_1i(do_mtthi, t0, 3);
5501 break;
5502 case 14:
5503 tcg_gen_helper_0_1i(do_mttacx, t0, 3);
5504 break;
5505 case 16:
5506 tcg_gen_helper_0_1(do_mttdsp, t0);
5507 break;
5508 default:
5509 goto die;
5511 break;
5512 /* Floating point (COP1). */
5513 case 2:
5514 /* XXX: For now we support only a single FPU context. */
5515 if (h == 0) {
5516 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5518 tcg_gen_trunc_tl_i32(fp0, t0);
5519 gen_store_fpr32(fp0, rd);
5520 tcg_temp_free(fp0);
5521 } else {
5522 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5524 tcg_gen_trunc_tl_i32(fp0, t0);
5525 gen_store_fpr32h(fp0, rd);
5526 tcg_temp_free(fp0);
5528 break;
5529 case 3:
5530 /* XXX: For now we support only a single FPU context. */
5531 tcg_gen_helper_0_1i(do_ctc1, t0, rd);
5532 break;
5533 /* COP2: Not implemented. */
5534 case 4:
5535 case 5:
5536 /* fall through */
5537 default:
5538 goto die;
5540 #if defined MIPS_DEBUG_DISAS
5541 if (loglevel & CPU_LOG_TB_IN_ASM) {
5542 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5543 rd, u, sel, h);
5545 #endif
5546 tcg_temp_free(t0);
5547 return;
5549 die:
5550 tcg_temp_free(t0);
5551 #if defined MIPS_DEBUG_DISAS
5552 if (loglevel & CPU_LOG_TB_IN_ASM) {
5553 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5554 rd, u, sel, h);
5556 #endif
5557 generate_exception(ctx, EXCP_RI);
5560 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5562 const char *opn = "ldst";
5564 switch (opc) {
5565 case OPC_MFC0:
5566 if (rt == 0) {
5567 /* Treat as NOP. */
5568 return;
5571 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5573 gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5574 gen_store_gpr(t0, rt);
5575 tcg_temp_free(t0);
5577 opn = "mfc0";
5578 break;
5579 case OPC_MTC0:
5581 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5583 gen_load_gpr(t0, rt);
5584 save_cpu_state(ctx, 1);
5585 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5586 tcg_temp_free(t0);
5588 opn = "mtc0";
5589 break;
5590 #if defined(TARGET_MIPS64)
5591 case OPC_DMFC0:
5592 check_insn(env, ctx, ISA_MIPS3);
5593 if (rt == 0) {
5594 /* Treat as NOP. */
5595 return;
5598 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5600 gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5601 gen_store_gpr(t0, rt);
5602 tcg_temp_free(t0);
5604 opn = "dmfc0";
5605 break;
5606 case OPC_DMTC0:
5607 check_insn(env, ctx, ISA_MIPS3);
5609 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5611 gen_load_gpr(t0, rt);
5612 save_cpu_state(ctx, 1);
5613 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5614 tcg_temp_free(t0);
5616 opn = "dmtc0";
5617 break;
5618 #endif
5619 case OPC_MFTR:
5620 check_insn(env, ctx, ASE_MT);
5621 if (rd == 0) {
5622 /* Treat as NOP. */
5623 return;
5625 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5626 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5627 opn = "mftr";
5628 break;
5629 case OPC_MTTR:
5630 check_insn(env, ctx, ASE_MT);
5631 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5632 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5633 opn = "mttr";
5634 break;
5635 case OPC_TLBWI:
5636 opn = "tlbwi";
5637 if (!env->tlb->do_tlbwi)
5638 goto die;
5639 tcg_gen_helper_0_0(env->tlb->do_tlbwi);
5640 break;
5641 case OPC_TLBWR:
5642 opn = "tlbwr";
5643 if (!env->tlb->do_tlbwr)
5644 goto die;
5645 tcg_gen_helper_0_0(env->tlb->do_tlbwr);
5646 break;
5647 case OPC_TLBP:
5648 opn = "tlbp";
5649 if (!env->tlb->do_tlbp)
5650 goto die;
5651 tcg_gen_helper_0_0(env->tlb->do_tlbp);
5652 break;
5653 case OPC_TLBR:
5654 opn = "tlbr";
5655 if (!env->tlb->do_tlbr)
5656 goto die;
5657 tcg_gen_helper_0_0(env->tlb->do_tlbr);
5658 break;
5659 case OPC_ERET:
5660 opn = "eret";
5661 check_insn(env, ctx, ISA_MIPS2);
5662 save_cpu_state(ctx, 1);
5663 tcg_gen_helper_0_0(do_eret);
5664 ctx->bstate = BS_EXCP;
5665 break;
5666 case OPC_DERET:
5667 opn = "deret";
5668 check_insn(env, ctx, ISA_MIPS32);
5669 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5670 MIPS_INVAL(opn);
5671 generate_exception(ctx, EXCP_RI);
5672 } else {
5673 save_cpu_state(ctx, 1);
5674 tcg_gen_helper_0_0(do_deret);
5675 ctx->bstate = BS_EXCP;
5677 break;
5678 case OPC_WAIT:
5679 opn = "wait";
5680 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5681 /* If we get an exception, we want to restart at next instruction */
5682 ctx->pc += 4;
5683 save_cpu_state(ctx, 1);
5684 ctx->pc -= 4;
5685 tcg_gen_helper_0_0(do_wait);
5686 ctx->bstate = BS_EXCP;
5687 break;
5688 default:
5689 die:
5690 MIPS_INVAL(opn);
5691 generate_exception(ctx, EXCP_RI);
5692 return;
5694 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5696 #endif /* !CONFIG_USER_ONLY */
5698 /* CP1 Branches (before delay slot) */
5699 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5700 int32_t cc, int32_t offset)
5702 target_ulong btarget;
5703 const char *opn = "cp1 cond branch";
5704 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5705 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
5707 if (cc != 0)
5708 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5710 btarget = ctx->pc + 4 + offset;
5712 switch (op) {
5713 case OPC_BC1F:
5715 int l1 = gen_new_label();
5716 int l2 = gen_new_label();
5717 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5719 get_fp_cond(r_tmp1);
5720 tcg_gen_ext_i32_tl(t0, r_tmp1);
5721 tcg_temp_free(r_tmp1);
5722 tcg_gen_not_tl(t0, t0);
5723 tcg_gen_movi_tl(t1, 0x1 << cc);
5724 tcg_gen_and_tl(t0, t0, t1);
5725 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5726 tcg_gen_movi_tl(t0, 0);
5727 tcg_gen_br(l2);
5728 gen_set_label(l1);
5729 tcg_gen_movi_tl(t0, 1);
5730 gen_set_label(l2);
5732 opn = "bc1f";
5733 goto not_likely;
5734 case OPC_BC1FL:
5736 int l1 = gen_new_label();
5737 int l2 = gen_new_label();
5738 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5740 get_fp_cond(r_tmp1);
5741 tcg_gen_ext_i32_tl(t0, r_tmp1);
5742 tcg_temp_free(r_tmp1);
5743 tcg_gen_not_tl(t0, t0);
5744 tcg_gen_movi_tl(t1, 0x1 << cc);
5745 tcg_gen_and_tl(t0, t0, t1);
5746 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5747 tcg_gen_movi_tl(t0, 0);
5748 tcg_gen_br(l2);
5749 gen_set_label(l1);
5750 tcg_gen_movi_tl(t0, 1);
5751 gen_set_label(l2);
5753 opn = "bc1fl";
5754 goto likely;
5755 case OPC_BC1T:
5757 int l1 = gen_new_label();
5758 int l2 = gen_new_label();
5759 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5761 get_fp_cond(r_tmp1);
5762 tcg_gen_ext_i32_tl(t0, r_tmp1);
5763 tcg_temp_free(r_tmp1);
5764 tcg_gen_movi_tl(t1, 0x1 << cc);
5765 tcg_gen_and_tl(t0, t0, t1);
5766 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5767 tcg_gen_movi_tl(t0, 0);
5768 tcg_gen_br(l2);
5769 gen_set_label(l1);
5770 tcg_gen_movi_tl(t0, 1);
5771 gen_set_label(l2);
5773 opn = "bc1t";
5774 goto not_likely;
5775 case OPC_BC1TL:
5777 int l1 = gen_new_label();
5778 int l2 = gen_new_label();
5779 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5781 get_fp_cond(r_tmp1);
5782 tcg_gen_ext_i32_tl(t0, r_tmp1);
5783 tcg_temp_free(r_tmp1);
5784 tcg_gen_movi_tl(t1, 0x1 << cc);
5785 tcg_gen_and_tl(t0, t0, t1);
5786 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5787 tcg_gen_movi_tl(t0, 0);
5788 tcg_gen_br(l2);
5789 gen_set_label(l1);
5790 tcg_gen_movi_tl(t0, 1);
5791 gen_set_label(l2);
5793 opn = "bc1tl";
5794 likely:
5795 ctx->hflags |= MIPS_HFLAG_BL;
5796 tcg_gen_trunc_tl_i32(bcond, t0);
5797 break;
5798 case OPC_BC1FANY2:
5800 int l1 = gen_new_label();
5801 int l2 = gen_new_label();
5802 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5804 get_fp_cond(r_tmp1);
5805 tcg_gen_ext_i32_tl(t0, r_tmp1);
5806 tcg_temp_free(r_tmp1);
5807 tcg_gen_not_tl(t0, t0);
5808 tcg_gen_movi_tl(t1, 0x3 << cc);
5809 tcg_gen_and_tl(t0, t0, t1);
5810 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5811 tcg_gen_movi_tl(t0, 0);
5812 tcg_gen_br(l2);
5813 gen_set_label(l1);
5814 tcg_gen_movi_tl(t0, 1);
5815 gen_set_label(l2);
5817 opn = "bc1any2f";
5818 goto not_likely;
5819 case OPC_BC1TANY2:
5821 int l1 = gen_new_label();
5822 int l2 = gen_new_label();
5823 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5825 get_fp_cond(r_tmp1);
5826 tcg_gen_ext_i32_tl(t0, r_tmp1);
5827 tcg_temp_free(r_tmp1);
5828 tcg_gen_movi_tl(t1, 0x3 << cc);
5829 tcg_gen_and_tl(t0, t0, t1);
5830 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5831 tcg_gen_movi_tl(t0, 0);
5832 tcg_gen_br(l2);
5833 gen_set_label(l1);
5834 tcg_gen_movi_tl(t0, 1);
5835 gen_set_label(l2);
5837 opn = "bc1any2t";
5838 goto not_likely;
5839 case OPC_BC1FANY4:
5841 int l1 = gen_new_label();
5842 int l2 = gen_new_label();
5843 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5845 get_fp_cond(r_tmp1);
5846 tcg_gen_ext_i32_tl(t0, r_tmp1);
5847 tcg_temp_free(r_tmp1);
5848 tcg_gen_not_tl(t0, t0);
5849 tcg_gen_movi_tl(t1, 0xf << cc);
5850 tcg_gen_and_tl(t0, t0, t1);
5851 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5852 tcg_gen_movi_tl(t0, 0);
5853 tcg_gen_br(l2);
5854 gen_set_label(l1);
5855 tcg_gen_movi_tl(t0, 1);
5856 gen_set_label(l2);
5858 opn = "bc1any4f";
5859 goto not_likely;
5860 case OPC_BC1TANY4:
5862 int l1 = gen_new_label();
5863 int l2 = gen_new_label();
5864 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5866 get_fp_cond(r_tmp1);
5867 tcg_gen_ext_i32_tl(t0, r_tmp1);
5868 tcg_temp_free(r_tmp1);
5869 tcg_gen_movi_tl(t1, 0xf << cc);
5870 tcg_gen_and_tl(t0, t0, t1);
5871 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5872 tcg_gen_movi_tl(t0, 0);
5873 tcg_gen_br(l2);
5874 gen_set_label(l1);
5875 tcg_gen_movi_tl(t0, 1);
5876 gen_set_label(l2);
5878 opn = "bc1any4t";
5879 not_likely:
5880 ctx->hflags |= MIPS_HFLAG_BC;
5881 tcg_gen_trunc_tl_i32(bcond, t0);
5882 break;
5883 default:
5884 MIPS_INVAL(opn);
5885 generate_exception (ctx, EXCP_RI);
5886 goto out;
5888 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5889 ctx->hflags, btarget);
5890 ctx->btarget = btarget;
5892 out:
5893 tcg_temp_free(t0);
5894 tcg_temp_free(t1);
5897 /* Coprocessor 1 (FPU) */
5899 #define FOP(func, fmt) (((fmt) << 21) | (func))
5901 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5903 const char *opn = "cp1 move";
5904 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5906 switch (opc) {
5907 case OPC_MFC1:
5909 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5911 gen_load_fpr32(fp0, fs);
5912 tcg_gen_ext_i32_tl(t0, fp0);
5913 tcg_temp_free(fp0);
5915 gen_store_gpr(t0, rt);
5916 opn = "mfc1";
5917 break;
5918 case OPC_MTC1:
5919 gen_load_gpr(t0, rt);
5921 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5923 tcg_gen_trunc_tl_i32(fp0, t0);
5924 gen_store_fpr32(fp0, fs);
5925 tcg_temp_free(fp0);
5927 opn = "mtc1";
5928 break;
5929 case OPC_CFC1:
5930 tcg_gen_helper_1_i(do_cfc1, t0, fs);
5931 gen_store_gpr(t0, rt);
5932 opn = "cfc1";
5933 break;
5934 case OPC_CTC1:
5935 gen_load_gpr(t0, rt);
5936 tcg_gen_helper_0_1i(do_ctc1, t0, fs);
5937 opn = "ctc1";
5938 break;
5939 case OPC_DMFC1:
5941 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
5943 gen_load_fpr64(ctx, fp0, fs);
5944 tcg_gen_mov_tl(t0, fp0);
5945 tcg_temp_free(fp0);
5947 gen_store_gpr(t0, rt);
5948 opn = "dmfc1";
5949 break;
5950 case OPC_DMTC1:
5951 gen_load_gpr(t0, rt);
5953 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
5955 tcg_gen_mov_tl(fp0, t0);
5956 gen_store_fpr64(ctx, fp0, fs);
5957 tcg_temp_free(fp0);
5959 opn = "dmtc1";
5960 break;
5961 case OPC_MFHC1:
5963 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5965 gen_load_fpr32h(fp0, fs);
5966 tcg_gen_ext_i32_tl(t0, fp0);
5967 tcg_temp_free(fp0);
5969 gen_store_gpr(t0, rt);
5970 opn = "mfhc1";
5971 break;
5972 case OPC_MTHC1:
5973 gen_load_gpr(t0, rt);
5975 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5977 tcg_gen_trunc_tl_i32(fp0, t0);
5978 gen_store_fpr32h(fp0, fs);
5979 tcg_temp_free(fp0);
5981 opn = "mthc1";
5982 break;
5983 default:
5984 MIPS_INVAL(opn);
5985 generate_exception (ctx, EXCP_RI);
5986 goto out;
5988 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5990 out:
5991 tcg_temp_free(t0);
5994 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5996 int l1 = gen_new_label();
5997 uint32_t ccbit;
5998 TCGCond cond;
5999 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6000 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
6001 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_I32);
6003 if (cc)
6004 ccbit = 1 << (24 + cc);
6005 else
6006 ccbit = 1 << 23;
6007 if (tf)
6008 cond = TCG_COND_EQ;
6009 else
6010 cond = TCG_COND_NE;
6012 gen_load_gpr(t0, rd);
6013 gen_load_gpr(t1, rs);
6014 tcg_gen_ld_i32(r_tmp, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
6015 tcg_gen_andi_i32(r_tmp, r_tmp, ccbit);
6016 tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
6017 tcg_temp_free(r_tmp);
6019 tcg_gen_mov_tl(t0, t1);
6020 tcg_temp_free(t1);
6022 gen_set_label(l1);
6023 gen_store_gpr(t0, rd);
6024 tcg_temp_free(t0);
6027 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6029 uint32_t ccbit;
6030 int cond;
6031 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
6032 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6033 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
6034 int l1 = gen_new_label();
6036 if (cc)
6037 ccbit = 1 << (24 + cc);
6038 else
6039 ccbit = 1 << 23;
6041 if (tf)
6042 cond = TCG_COND_EQ;
6043 else
6044 cond = TCG_COND_NE;
6046 gen_load_fpr32(fp0, fs);
6047 gen_load_fpr32(fp1, fd);
6048 tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
6049 tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit);
6050 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
6051 tcg_gen_movi_i32(fp1, fp0);
6052 tcg_temp_free(fp0);
6053 gen_set_label(l1);
6054 tcg_temp_free(r_tmp1);
6055 gen_store_fpr32(fp1, fd);
6056 tcg_temp_free(fp1);
6059 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6061 uint32_t ccbit;
6062 int cond;
6063 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
6064 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
6065 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I64);
6066 int l1 = gen_new_label();
6068 if (cc)
6069 ccbit = 1 << (24 + cc);
6070 else
6071 ccbit = 1 << 23;
6073 if (tf)
6074 cond = TCG_COND_EQ;
6075 else
6076 cond = TCG_COND_NE;
6078 gen_load_fpr64(ctx, fp0, fs);
6079 gen_load_fpr64(ctx, fp1, fd);
6080 tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
6081 tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit);
6082 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
6083 tcg_gen_movi_i64(fp1, fp0);
6084 tcg_temp_free(fp0);
6085 gen_set_label(l1);
6086 tcg_temp_free(r_tmp1);
6087 gen_store_fpr64(ctx, fp1, fd);
6088 tcg_temp_free(fp1);
6091 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6093 int cond;
6094 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
6095 TCGv r_tmp2 = tcg_temp_local_new(TCG_TYPE_I32);
6096 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6097 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
6098 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
6099 TCGv fph1 = tcg_temp_local_new(TCG_TYPE_I32);
6100 int l1 = gen_new_label();
6101 int l2 = gen_new_label();
6103 if (tf)
6104 cond = TCG_COND_EQ;
6105 else
6106 cond = TCG_COND_NE;
6108 gen_load_fpr32(fp0, fs);
6109 gen_load_fpr32h(fph0, fs);
6110 gen_load_fpr32(fp1, fd);
6111 gen_load_fpr32h(fph1, fd);
6112 get_fp_cond(r_tmp1);
6113 tcg_gen_shri_i32(r_tmp1, r_tmp1, cc);
6114 tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x1);
6115 tcg_gen_brcondi_i32(cond, r_tmp2, 0, l1);
6116 tcg_gen_movi_i32(fp1, fp0);
6117 tcg_temp_free(fp0);
6118 gen_set_label(l1);
6119 tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x2);
6120 tcg_gen_brcondi_i32(cond, r_tmp2, 0, l2);
6121 tcg_gen_movi_i32(fph1, fph0);
6122 tcg_temp_free(fph0);
6123 gen_set_label(l2);
6124 tcg_temp_free(r_tmp1);
6125 tcg_temp_free(r_tmp2);
6126 gen_store_fpr32(fp1, fd);
6127 gen_store_fpr32h(fph1, fd);
6128 tcg_temp_free(fp1);
6129 tcg_temp_free(fph1);
6133 static void gen_farith (DisasContext *ctx, uint32_t op1,
6134 int ft, int fs, int fd, int cc)
6136 const char *opn = "farith";
6137 const char *condnames[] = {
6138 "c.f",
6139 "c.un",
6140 "c.eq",
6141 "c.ueq",
6142 "c.olt",
6143 "c.ult",
6144 "c.ole",
6145 "c.ule",
6146 "c.sf",
6147 "c.ngle",
6148 "c.seq",
6149 "c.ngl",
6150 "c.lt",
6151 "c.nge",
6152 "c.le",
6153 "c.ngt",
6155 const char *condnames_abs[] = {
6156 "cabs.f",
6157 "cabs.un",
6158 "cabs.eq",
6159 "cabs.ueq",
6160 "cabs.olt",
6161 "cabs.ult",
6162 "cabs.ole",
6163 "cabs.ule",
6164 "cabs.sf",
6165 "cabs.ngle",
6166 "cabs.seq",
6167 "cabs.ngl",
6168 "cabs.lt",
6169 "cabs.nge",
6170 "cabs.le",
6171 "cabs.ngt",
6173 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6174 uint32_t func = ctx->opcode & 0x3f;
6176 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
6177 case FOP(0, 16):
6179 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6180 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6182 gen_load_fpr32(fp0, fs);
6183 gen_load_fpr32(fp1, ft);
6184 tcg_gen_helper_1_2(do_float_add_s, fp0, fp0, fp1);
6185 tcg_temp_free(fp1);
6186 gen_store_fpr32(fp0, fd);
6187 tcg_temp_free(fp0);
6189 opn = "add.s";
6190 optype = BINOP;
6191 break;
6192 case FOP(1, 16):
6194 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6195 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6197 gen_load_fpr32(fp0, fs);
6198 gen_load_fpr32(fp1, ft);
6199 tcg_gen_helper_1_2(do_float_sub_s, fp0, fp0, fp1);
6200 tcg_temp_free(fp1);
6201 gen_store_fpr32(fp0, fd);
6202 tcg_temp_free(fp0);
6204 opn = "sub.s";
6205 optype = BINOP;
6206 break;
6207 case FOP(2, 16):
6209 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6210 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6212 gen_load_fpr32(fp0, fs);
6213 gen_load_fpr32(fp1, ft);
6214 tcg_gen_helper_1_2(do_float_mul_s, fp0, fp0, fp1);
6215 tcg_temp_free(fp1);
6216 gen_store_fpr32(fp0, fd);
6217 tcg_temp_free(fp0);
6219 opn = "mul.s";
6220 optype = BINOP;
6221 break;
6222 case FOP(3, 16):
6224 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6225 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6227 gen_load_fpr32(fp0, fs);
6228 gen_load_fpr32(fp1, ft);
6229 tcg_gen_helper_1_2(do_float_div_s, fp0, fp0, fp1);
6230 tcg_temp_free(fp1);
6231 gen_store_fpr32(fp0, fd);
6232 tcg_temp_free(fp0);
6234 opn = "div.s";
6235 optype = BINOP;
6236 break;
6237 case FOP(4, 16):
6239 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6241 gen_load_fpr32(fp0, fs);
6242 tcg_gen_helper_1_1(do_float_sqrt_s, fp0, fp0);
6243 gen_store_fpr32(fp0, fd);
6244 tcg_temp_free(fp0);
6246 opn = "sqrt.s";
6247 break;
6248 case FOP(5, 16):
6250 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6252 gen_load_fpr32(fp0, fs);
6253 tcg_gen_helper_1_1(do_float_abs_s, fp0, fp0);
6254 gen_store_fpr32(fp0, fd);
6255 tcg_temp_free(fp0);
6257 opn = "abs.s";
6258 break;
6259 case FOP(6, 16):
6261 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6263 gen_load_fpr32(fp0, fs);
6264 gen_store_fpr32(fp0, fd);
6265 tcg_temp_free(fp0);
6267 opn = "mov.s";
6268 break;
6269 case FOP(7, 16):
6271 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6273 gen_load_fpr32(fp0, fs);
6274 tcg_gen_helper_1_1(do_float_chs_s, fp0, fp0);
6275 gen_store_fpr32(fp0, fd);
6276 tcg_temp_free(fp0);
6278 opn = "neg.s";
6279 break;
6280 case FOP(8, 16):
6281 check_cp1_64bitmode(ctx);
6283 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6284 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6286 gen_load_fpr32(fp32, fs);
6287 tcg_gen_helper_1_1(do_float_roundl_s, fp64, fp32);
6288 tcg_temp_free(fp32);
6289 gen_store_fpr64(ctx, fp64, fd);
6290 tcg_temp_free(fp64);
6292 opn = "round.l.s";
6293 break;
6294 case FOP(9, 16):
6295 check_cp1_64bitmode(ctx);
6297 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6298 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6300 gen_load_fpr32(fp32, fs);
6301 tcg_gen_helper_1_1(do_float_truncl_s, fp64, fp32);
6302 tcg_temp_free(fp32);
6303 gen_store_fpr64(ctx, fp64, fd);
6304 tcg_temp_free(fp64);
6306 opn = "trunc.l.s";
6307 break;
6308 case FOP(10, 16):
6309 check_cp1_64bitmode(ctx);
6311 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6312 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6314 gen_load_fpr32(fp32, fs);
6315 tcg_gen_helper_1_1(do_float_ceill_s, fp64, fp32);
6316 tcg_temp_free(fp32);
6317 gen_store_fpr64(ctx, fp64, fd);
6318 tcg_temp_free(fp64);
6320 opn = "ceil.l.s";
6321 break;
6322 case FOP(11, 16):
6323 check_cp1_64bitmode(ctx);
6325 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6326 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6328 gen_load_fpr32(fp32, fs);
6329 tcg_gen_helper_1_1(do_float_floorl_s, fp64, fp32);
6330 tcg_temp_free(fp32);
6331 gen_store_fpr64(ctx, fp64, fd);
6332 tcg_temp_free(fp64);
6334 opn = "floor.l.s";
6335 break;
6336 case FOP(12, 16):
6338 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6340 gen_load_fpr32(fp0, fs);
6341 tcg_gen_helper_1_1(do_float_roundw_s, fp0, fp0);
6342 gen_store_fpr32(fp0, fd);
6343 tcg_temp_free(fp0);
6345 opn = "round.w.s";
6346 break;
6347 case FOP(13, 16):
6349 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6351 gen_load_fpr32(fp0, fs);
6352 tcg_gen_helper_1_1(do_float_truncw_s, fp0, fp0);
6353 gen_store_fpr32(fp0, fd);
6354 tcg_temp_free(fp0);
6356 opn = "trunc.w.s";
6357 break;
6358 case FOP(14, 16):
6360 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6362 gen_load_fpr32(fp0, fs);
6363 tcg_gen_helper_1_1(do_float_ceilw_s, fp0, fp0);
6364 gen_store_fpr32(fp0, fd);
6365 tcg_temp_free(fp0);
6367 opn = "ceil.w.s";
6368 break;
6369 case FOP(15, 16):
6371 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6373 gen_load_fpr32(fp0, fs);
6374 tcg_gen_helper_1_1(do_float_floorw_s, fp0, fp0);
6375 gen_store_fpr32(fp0, fd);
6376 tcg_temp_free(fp0);
6378 opn = "floor.w.s";
6379 break;
6380 case FOP(17, 16):
6381 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6382 opn = "movcf.s";
6383 break;
6384 case FOP(18, 16):
6386 int l1 = gen_new_label();
6387 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6388 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6390 gen_load_gpr(t0, ft);
6391 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6392 tcg_temp_free(t0);
6393 gen_load_fpr32(fp0, fs);
6394 gen_store_fpr32(fp0, fd);
6395 tcg_temp_free(fp0);
6396 gen_set_label(l1);
6398 opn = "movz.s";
6399 break;
6400 case FOP(19, 16):
6402 int l1 = gen_new_label();
6403 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6404 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6406 gen_load_gpr(t0, ft);
6407 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6408 tcg_temp_free(t0);
6409 gen_load_fpr32(fp0, fs);
6410 gen_store_fpr32(fp0, fd);
6411 tcg_temp_free(fp0);
6412 gen_set_label(l1);
6414 opn = "movn.s";
6415 break;
6416 case FOP(21, 16):
6417 check_cop1x(ctx);
6419 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6421 gen_load_fpr32(fp0, fs);
6422 tcg_gen_helper_1_1(do_float_recip_s, fp0, fp0);
6423 gen_store_fpr32(fp0, fd);
6424 tcg_temp_free(fp0);
6426 opn = "recip.s";
6427 break;
6428 case FOP(22, 16):
6429 check_cop1x(ctx);
6431 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6433 gen_load_fpr32(fp0, fs);
6434 tcg_gen_helper_1_1(do_float_rsqrt_s, fp0, fp0);
6435 gen_store_fpr32(fp0, fd);
6436 tcg_temp_free(fp0);
6438 opn = "rsqrt.s";
6439 break;
6440 case FOP(28, 16):
6441 check_cp1_64bitmode(ctx);
6443 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6444 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6446 gen_load_fpr32(fp0, fs);
6447 gen_load_fpr32(fp1, fd);
6448 tcg_gen_helper_1_2(do_float_recip2_s, fp0, fp0, fp1);
6449 tcg_temp_free(fp1);
6450 gen_store_fpr32(fp0, fd);
6451 tcg_temp_free(fp0);
6453 opn = "recip2.s";
6454 break;
6455 case FOP(29, 16):
6456 check_cp1_64bitmode(ctx);
6458 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6460 gen_load_fpr32(fp0, fs);
6461 tcg_gen_helper_1_1(do_float_recip1_s, fp0, fp0);
6462 gen_store_fpr32(fp0, fd);
6463 tcg_temp_free(fp0);
6465 opn = "recip1.s";
6466 break;
6467 case FOP(30, 16):
6468 check_cp1_64bitmode(ctx);
6470 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6472 gen_load_fpr32(fp0, fs);
6473 tcg_gen_helper_1_1(do_float_rsqrt1_s, fp0, fp0);
6474 gen_store_fpr32(fp0, fd);
6475 tcg_temp_free(fp0);
6477 opn = "rsqrt1.s";
6478 break;
6479 case FOP(31, 16):
6480 check_cp1_64bitmode(ctx);
6482 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6483 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6485 gen_load_fpr32(fp0, fs);
6486 gen_load_fpr32(fp1, ft);
6487 tcg_gen_helper_1_2(do_float_rsqrt2_s, fp0, fp0, fp1);
6488 tcg_temp_free(fp1);
6489 gen_store_fpr32(fp0, fd);
6490 tcg_temp_free(fp0);
6492 opn = "rsqrt2.s";
6493 break;
6494 case FOP(33, 16):
6495 check_cp1_registers(ctx, fd);
6497 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6498 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6500 gen_load_fpr32(fp32, fs);
6501 tcg_gen_helper_1_1(do_float_cvtd_s, fp64, fp32);
6502 tcg_temp_free(fp32);
6503 gen_store_fpr64(ctx, fp64, fd);
6504 tcg_temp_free(fp64);
6506 opn = "cvt.d.s";
6507 break;
6508 case FOP(36, 16):
6510 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6512 gen_load_fpr32(fp0, fs);
6513 tcg_gen_helper_1_1(do_float_cvtw_s, fp0, fp0);
6514 gen_store_fpr32(fp0, fd);
6515 tcg_temp_free(fp0);
6517 opn = "cvt.w.s";
6518 break;
6519 case FOP(37, 16):
6520 check_cp1_64bitmode(ctx);
6522 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6523 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6525 gen_load_fpr32(fp32, fs);
6526 tcg_gen_helper_1_1(do_float_cvtl_s, fp64, fp32);
6527 tcg_temp_free(fp32);
6528 gen_store_fpr64(ctx, fp64, fd);
6529 tcg_temp_free(fp64);
6531 opn = "cvt.l.s";
6532 break;
6533 case FOP(38, 16):
6534 check_cp1_64bitmode(ctx);
6536 TCGv fp64_0 = tcg_temp_new(TCG_TYPE_I64);
6537 TCGv fp64_1 = tcg_temp_new(TCG_TYPE_I64);
6538 TCGv fp32_0 = tcg_temp_new(TCG_TYPE_I32);
6539 TCGv fp32_1 = tcg_temp_new(TCG_TYPE_I32);
6541 gen_load_fpr32(fp32_0, fs);
6542 gen_load_fpr32(fp32_1, ft);
6543 tcg_gen_extu_i32_i64(fp64_0, fp32_0);
6544 tcg_gen_extu_i32_i64(fp64_1, fp32_1);
6545 tcg_temp_free(fp32_0);
6546 tcg_temp_free(fp32_1);
6547 tcg_gen_shli_i64(fp64_1, fp64_1, 32);
6548 tcg_gen_or_i64(fp64_0, fp64_0, fp64_1);
6549 tcg_temp_free(fp64_1);
6550 gen_store_fpr64(ctx, fp64_0, fd);
6551 tcg_temp_free(fp64_0);
6553 opn = "cvt.ps.s";
6554 break;
6555 case FOP(48, 16):
6556 case FOP(49, 16):
6557 case FOP(50, 16):
6558 case FOP(51, 16):
6559 case FOP(52, 16):
6560 case FOP(53, 16):
6561 case FOP(54, 16):
6562 case FOP(55, 16):
6563 case FOP(56, 16):
6564 case FOP(57, 16):
6565 case FOP(58, 16):
6566 case FOP(59, 16):
6567 case FOP(60, 16):
6568 case FOP(61, 16):
6569 case FOP(62, 16):
6570 case FOP(63, 16):
6572 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6573 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6575 gen_load_fpr32(fp0, fs);
6576 gen_load_fpr32(fp1, ft);
6577 if (ctx->opcode & (1 << 6)) {
6578 check_cop1x(ctx);
6579 gen_cmpabs_s(func-48, fp0, fp1, cc);
6580 opn = condnames_abs[func-48];
6581 } else {
6582 gen_cmp_s(func-48, fp0, fp1, cc);
6583 opn = condnames[func-48];
6585 tcg_temp_free(fp0);
6586 tcg_temp_free(fp1);
6588 break;
6589 case FOP(0, 17):
6590 check_cp1_registers(ctx, fs | ft | fd);
6592 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6593 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6595 gen_load_fpr64(ctx, fp0, fs);
6596 gen_load_fpr64(ctx, fp1, ft);
6597 tcg_gen_helper_1_2(do_float_add_d, fp0, fp0, fp1);
6598 tcg_temp_free(fp1);
6599 gen_store_fpr64(ctx, fp0, fd);
6600 tcg_temp_free(fp0);
6602 opn = "add.d";
6603 optype = BINOP;
6604 break;
6605 case FOP(1, 17):
6606 check_cp1_registers(ctx, fs | ft | fd);
6608 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6609 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6611 gen_load_fpr64(ctx, fp0, fs);
6612 gen_load_fpr64(ctx, fp1, ft);
6613 tcg_gen_helper_1_2(do_float_sub_d, fp0, fp0, fp1);
6614 tcg_temp_free(fp1);
6615 gen_store_fpr64(ctx, fp0, fd);
6616 tcg_temp_free(fp0);
6618 opn = "sub.d";
6619 optype = BINOP;
6620 break;
6621 case FOP(2, 17):
6622 check_cp1_registers(ctx, fs | ft | fd);
6624 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6625 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6627 gen_load_fpr64(ctx, fp0, fs);
6628 gen_load_fpr64(ctx, fp1, ft);
6629 tcg_gen_helper_1_2(do_float_mul_d, fp0, fp0, fp1);
6630 tcg_temp_free(fp1);
6631 gen_store_fpr64(ctx, fp0, fd);
6632 tcg_temp_free(fp0);
6634 opn = "mul.d";
6635 optype = BINOP;
6636 break;
6637 case FOP(3, 17):
6638 check_cp1_registers(ctx, fs | ft | fd);
6640 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6641 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6643 gen_load_fpr64(ctx, fp0, fs);
6644 gen_load_fpr64(ctx, fp1, ft);
6645 tcg_gen_helper_1_2(do_float_div_d, fp0, fp0, fp1);
6646 tcg_temp_free(fp1);
6647 gen_store_fpr64(ctx, fp0, fd);
6648 tcg_temp_free(fp0);
6650 opn = "div.d";
6651 optype = BINOP;
6652 break;
6653 case FOP(4, 17):
6654 check_cp1_registers(ctx, fs | fd);
6656 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6658 gen_load_fpr64(ctx, fp0, fs);
6659 tcg_gen_helper_1_1(do_float_sqrt_d, fp0, fp0);
6660 gen_store_fpr64(ctx, fp0, fd);
6661 tcg_temp_free(fp0);
6663 opn = "sqrt.d";
6664 break;
6665 case FOP(5, 17):
6666 check_cp1_registers(ctx, fs | fd);
6668 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6670 gen_load_fpr64(ctx, fp0, fs);
6671 tcg_gen_helper_1_1(do_float_abs_d, fp0, fp0);
6672 gen_store_fpr64(ctx, fp0, fd);
6673 tcg_temp_free(fp0);
6675 opn = "abs.d";
6676 break;
6677 case FOP(6, 17):
6678 check_cp1_registers(ctx, fs | fd);
6680 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6682 gen_load_fpr64(ctx, fp0, fs);
6683 gen_store_fpr64(ctx, fp0, fd);
6684 tcg_temp_free(fp0);
6686 opn = "mov.d";
6687 break;
6688 case FOP(7, 17):
6689 check_cp1_registers(ctx, fs | fd);
6691 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6693 gen_load_fpr64(ctx, fp0, fs);
6694 tcg_gen_helper_1_1(do_float_chs_d, fp0, fp0);
6695 gen_store_fpr64(ctx, fp0, fd);
6696 tcg_temp_free(fp0);
6698 opn = "neg.d";
6699 break;
6700 case FOP(8, 17):
6701 check_cp1_64bitmode(ctx);
6703 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6705 gen_load_fpr64(ctx, fp0, fs);
6706 tcg_gen_helper_1_1(do_float_roundl_d, fp0, fp0);
6707 gen_store_fpr64(ctx, fp0, fd);
6708 tcg_temp_free(fp0);
6710 opn = "round.l.d";
6711 break;
6712 case FOP(9, 17):
6713 check_cp1_64bitmode(ctx);
6715 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6717 gen_load_fpr64(ctx, fp0, fs);
6718 tcg_gen_helper_1_1(do_float_truncl_d, fp0, fp0);
6719 gen_store_fpr64(ctx, fp0, fd);
6720 tcg_temp_free(fp0);
6722 opn = "trunc.l.d";
6723 break;
6724 case FOP(10, 17):
6725 check_cp1_64bitmode(ctx);
6727 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6729 gen_load_fpr64(ctx, fp0, fs);
6730 tcg_gen_helper_1_1(do_float_ceill_d, fp0, fp0);
6731 gen_store_fpr64(ctx, fp0, fd);
6732 tcg_temp_free(fp0);
6734 opn = "ceil.l.d";
6735 break;
6736 case FOP(11, 17):
6737 check_cp1_64bitmode(ctx);
6739 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6741 gen_load_fpr64(ctx, fp0, fs);
6742 tcg_gen_helper_1_1(do_float_floorl_d, fp0, fp0);
6743 gen_store_fpr64(ctx, fp0, fd);
6744 tcg_temp_free(fp0);
6746 opn = "floor.l.d";
6747 break;
6748 case FOP(12, 17):
6749 check_cp1_registers(ctx, fs);
6751 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6752 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6754 gen_load_fpr64(ctx, fp64, fs);
6755 tcg_gen_helper_1_1(do_float_roundw_d, fp32, fp64);
6756 tcg_temp_free(fp64);
6757 gen_store_fpr32(fp32, fd);
6758 tcg_temp_free(fp32);
6760 opn = "round.w.d";
6761 break;
6762 case FOP(13, 17):
6763 check_cp1_registers(ctx, fs);
6765 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6766 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6768 gen_load_fpr64(ctx, fp64, fs);
6769 tcg_gen_helper_1_1(do_float_truncw_d, fp32, fp64);
6770 tcg_temp_free(fp64);
6771 gen_store_fpr32(fp32, fd);
6772 tcg_temp_free(fp32);
6774 opn = "trunc.w.d";
6775 break;
6776 case FOP(14, 17):
6777 check_cp1_registers(ctx, fs);
6779 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6780 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6782 gen_load_fpr64(ctx, fp64, fs);
6783 tcg_gen_helper_1_1(do_float_ceilw_d, fp32, fp64);
6784 tcg_temp_free(fp64);
6785 gen_store_fpr32(fp32, fd);
6786 tcg_temp_free(fp32);
6788 opn = "ceil.w.d";
6789 break;
6790 case FOP(15, 17):
6791 check_cp1_registers(ctx, fs);
6793 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6794 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6796 gen_load_fpr64(ctx, fp64, fs);
6797 tcg_gen_helper_1_1(do_float_floorw_d, fp32, fp64);
6798 tcg_temp_free(fp64);
6799 gen_store_fpr32(fp32, fd);
6800 tcg_temp_free(fp32);
6802 opn = "floor.w.d";
6803 break;
6804 case FOP(17, 17):
6805 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6806 opn = "movcf.d";
6807 break;
6808 case FOP(18, 17):
6810 int l1 = gen_new_label();
6811 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6812 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
6814 gen_load_gpr(t0, ft);
6815 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6816 tcg_temp_free(t0);
6817 gen_load_fpr64(ctx, fp0, fs);
6818 gen_store_fpr64(ctx, fp0, fd);
6819 tcg_temp_free(fp0);
6820 gen_set_label(l1);
6822 opn = "movz.d";
6823 break;
6824 case FOP(19, 17):
6826 int l1 = gen_new_label();
6827 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6828 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
6830 gen_load_gpr(t0, ft);
6831 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6832 tcg_temp_free(t0);
6833 gen_load_fpr64(ctx, fp0, fs);
6834 gen_store_fpr64(ctx, fp0, fd);
6835 tcg_temp_free(fp0);
6836 gen_set_label(l1);
6838 opn = "movn.d";
6839 break;
6840 case FOP(21, 17):
6841 check_cp1_64bitmode(ctx);
6843 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6845 gen_load_fpr64(ctx, fp0, fs);
6846 tcg_gen_helper_1_1(do_float_recip_d, fp0, fp0);
6847 gen_store_fpr64(ctx, fp0, fd);
6848 tcg_temp_free(fp0);
6850 opn = "recip.d";
6851 break;
6852 case FOP(22, 17):
6853 check_cp1_64bitmode(ctx);
6855 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6857 gen_load_fpr64(ctx, fp0, fs);
6858 tcg_gen_helper_1_1(do_float_rsqrt_d, fp0, fp0);
6859 gen_store_fpr64(ctx, fp0, fd);
6860 tcg_temp_free(fp0);
6862 opn = "rsqrt.d";
6863 break;
6864 case FOP(28, 17):
6865 check_cp1_64bitmode(ctx);
6867 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6868 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6870 gen_load_fpr64(ctx, fp0, fs);
6871 gen_load_fpr64(ctx, fp1, ft);
6872 tcg_gen_helper_1_2(do_float_recip2_d, fp0, fp0, fp1);
6873 tcg_temp_free(fp1);
6874 gen_store_fpr64(ctx, fp0, fd);
6875 tcg_temp_free(fp0);
6877 opn = "recip2.d";
6878 break;
6879 case FOP(29, 17):
6880 check_cp1_64bitmode(ctx);
6882 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6884 gen_load_fpr64(ctx, fp0, fs);
6885 tcg_gen_helper_1_1(do_float_recip1_d, fp0, fp0);
6886 gen_store_fpr64(ctx, fp0, fd);
6887 tcg_temp_free(fp0);
6889 opn = "recip1.d";
6890 break;
6891 case FOP(30, 17):
6892 check_cp1_64bitmode(ctx);
6894 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6896 gen_load_fpr64(ctx, fp0, fs);
6897 tcg_gen_helper_1_1(do_float_rsqrt1_d, fp0, fp0);
6898 gen_store_fpr64(ctx, fp0, fd);
6899 tcg_temp_free(fp0);
6901 opn = "rsqrt1.d";
6902 break;
6903 case FOP(31, 17):
6904 check_cp1_64bitmode(ctx);
6906 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6907 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6909 gen_load_fpr64(ctx, fp0, fs);
6910 gen_load_fpr64(ctx, fp1, ft);
6911 tcg_gen_helper_1_2(do_float_rsqrt2_d, fp0, fp0, fp1);
6912 tcg_temp_free(fp1);
6913 gen_store_fpr64(ctx, fp0, fd);
6914 tcg_temp_free(fp0);
6916 opn = "rsqrt2.d";
6917 break;
6918 case FOP(48, 17):
6919 case FOP(49, 17):
6920 case FOP(50, 17):
6921 case FOP(51, 17):
6922 case FOP(52, 17):
6923 case FOP(53, 17):
6924 case FOP(54, 17):
6925 case FOP(55, 17):
6926 case FOP(56, 17):
6927 case FOP(57, 17):
6928 case FOP(58, 17):
6929 case FOP(59, 17):
6930 case FOP(60, 17):
6931 case FOP(61, 17):
6932 case FOP(62, 17):
6933 case FOP(63, 17):
6935 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6936 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6938 gen_load_fpr64(ctx, fp0, fs);
6939 gen_load_fpr64(ctx, fp1, ft);
6940 if (ctx->opcode & (1 << 6)) {
6941 check_cop1x(ctx);
6942 check_cp1_registers(ctx, fs | ft);
6943 gen_cmpabs_d(func-48, fp0, fp1, cc);
6944 opn = condnames_abs[func-48];
6945 } else {
6946 check_cp1_registers(ctx, fs | ft);
6947 gen_cmp_d(func-48, fp0, fp1, cc);
6948 opn = condnames[func-48];
6950 tcg_temp_free(fp0);
6951 tcg_temp_free(fp1);
6953 break;
6954 case FOP(32, 17):
6955 check_cp1_registers(ctx, fs);
6957 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6958 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6960 gen_load_fpr64(ctx, fp64, fs);
6961 tcg_gen_helper_1_1(do_float_cvts_d, fp32, fp64);
6962 tcg_temp_free(fp64);
6963 gen_store_fpr32(fp32, fd);
6964 tcg_temp_free(fp32);
6966 opn = "cvt.s.d";
6967 break;
6968 case FOP(36, 17):
6969 check_cp1_registers(ctx, fs);
6971 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6972 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6974 gen_load_fpr64(ctx, fp64, fs);
6975 tcg_gen_helper_1_1(do_float_cvtw_d, fp32, fp64);
6976 tcg_temp_free(fp64);
6977 gen_store_fpr32(fp32, fd);
6978 tcg_temp_free(fp32);
6980 opn = "cvt.w.d";
6981 break;
6982 case FOP(37, 17):
6983 check_cp1_64bitmode(ctx);
6985 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6987 gen_load_fpr64(ctx, fp0, fs);
6988 tcg_gen_helper_1_1(do_float_cvtl_d, fp0, fp0);
6989 gen_store_fpr64(ctx, fp0, fd);
6990 tcg_temp_free(fp0);
6992 opn = "cvt.l.d";
6993 break;
6994 case FOP(32, 20):
6996 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6998 gen_load_fpr32(fp0, fs);
6999 tcg_gen_helper_1_1(do_float_cvts_w, fp0, fp0);
7000 gen_store_fpr32(fp0, fd);
7001 tcg_temp_free(fp0);
7003 opn = "cvt.s.w";
7004 break;
7005 case FOP(33, 20):
7006 check_cp1_registers(ctx, fd);
7008 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
7009 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
7011 gen_load_fpr32(fp32, fs);
7012 tcg_gen_helper_1_1(do_float_cvtd_w, fp64, fp32);
7013 tcg_temp_free(fp32);
7014 gen_store_fpr64(ctx, fp64, fd);
7015 tcg_temp_free(fp64);
7017 opn = "cvt.d.w";
7018 break;
7019 case FOP(32, 21):
7020 check_cp1_64bitmode(ctx);
7022 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
7023 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
7025 gen_load_fpr64(ctx, fp64, fs);
7026 tcg_gen_helper_1_1(do_float_cvts_l, fp32, fp64);
7027 tcg_temp_free(fp64);
7028 gen_store_fpr32(fp32, fd);
7029 tcg_temp_free(fp32);
7031 opn = "cvt.s.l";
7032 break;
7033 case FOP(33, 21):
7034 check_cp1_64bitmode(ctx);
7036 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7038 gen_load_fpr64(ctx, fp0, fs);
7039 tcg_gen_helper_1_1(do_float_cvtd_l, fp0, fp0);
7040 gen_store_fpr64(ctx, fp0, fd);
7041 tcg_temp_free(fp0);
7043 opn = "cvt.d.l";
7044 break;
7045 case FOP(38, 20):
7046 check_cp1_64bitmode(ctx);
7048 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7050 gen_load_fpr64(ctx, fp0, fs);
7051 tcg_gen_helper_1_1(do_float_cvtps_pw, fp0, fp0);
7052 gen_store_fpr64(ctx, fp0, fd);
7053 tcg_temp_free(fp0);
7055 opn = "cvt.ps.pw";
7056 break;
7057 case FOP(0, 22):
7058 check_cp1_64bitmode(ctx);
7060 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7061 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7063 gen_load_fpr64(ctx, fp0, fs);
7064 gen_load_fpr64(ctx, fp1, ft);
7065 tcg_gen_helper_1_2(do_float_add_ps, fp0, fp0, fp1);
7066 tcg_temp_free(fp1);
7067 gen_store_fpr64(ctx, fp0, fd);
7068 tcg_temp_free(fp0);
7070 opn = "add.ps";
7071 break;
7072 case FOP(1, 22):
7073 check_cp1_64bitmode(ctx);
7075 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7076 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7078 gen_load_fpr64(ctx, fp0, fs);
7079 gen_load_fpr64(ctx, fp1, ft);
7080 tcg_gen_helper_1_2(do_float_sub_ps, fp0, fp0, fp1);
7081 tcg_temp_free(fp1);
7082 gen_store_fpr64(ctx, fp0, fd);
7083 tcg_temp_free(fp0);
7085 opn = "sub.ps";
7086 break;
7087 case FOP(2, 22):
7088 check_cp1_64bitmode(ctx);
7090 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7091 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7093 gen_load_fpr64(ctx, fp0, fs);
7094 gen_load_fpr64(ctx, fp1, ft);
7095 tcg_gen_helper_1_2(do_float_mul_ps, fp0, fp0, fp1);
7096 tcg_temp_free(fp1);
7097 gen_store_fpr64(ctx, fp0, fd);
7098 tcg_temp_free(fp0);
7100 opn = "mul.ps";
7101 break;
7102 case FOP(5, 22):
7103 check_cp1_64bitmode(ctx);
7105 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7107 gen_load_fpr64(ctx, fp0, fs);
7108 tcg_gen_helper_1_1(do_float_abs_ps, fp0, fp0);
7109 gen_store_fpr64(ctx, fp0, fd);
7110 tcg_temp_free(fp0);
7112 opn = "abs.ps";
7113 break;
7114 case FOP(6, 22):
7115 check_cp1_64bitmode(ctx);
7117 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7119 gen_load_fpr64(ctx, fp0, fs);
7120 gen_store_fpr64(ctx, fp0, fd);
7121 tcg_temp_free(fp0);
7123 opn = "mov.ps";
7124 break;
7125 case FOP(7, 22):
7126 check_cp1_64bitmode(ctx);
7128 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7130 gen_load_fpr64(ctx, fp0, fs);
7131 tcg_gen_helper_1_1(do_float_chs_ps, fp0, fp0);
7132 gen_store_fpr64(ctx, fp0, fd);
7133 tcg_temp_free(fp0);
7135 opn = "neg.ps";
7136 break;
7137 case FOP(17, 22):
7138 check_cp1_64bitmode(ctx);
7139 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7140 opn = "movcf.ps";
7141 break;
7142 case FOP(18, 22):
7143 check_cp1_64bitmode(ctx);
7145 int l1 = gen_new_label();
7146 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7147 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7148 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7150 gen_load_gpr(t0, ft);
7151 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7152 tcg_temp_free(t0);
7153 gen_load_fpr32(fp0, fs);
7154 gen_load_fpr32h(fph0, fs);
7155 gen_store_fpr32(fp0, fd);
7156 gen_store_fpr32h(fph0, fd);
7157 tcg_temp_free(fp0);
7158 tcg_temp_free(fph0);
7159 gen_set_label(l1);
7161 opn = "movz.ps";
7162 break;
7163 case FOP(19, 22):
7164 check_cp1_64bitmode(ctx);
7166 int l1 = gen_new_label();
7167 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7168 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7169 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7171 gen_load_gpr(t0, ft);
7172 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
7173 tcg_temp_free(t0);
7174 gen_load_fpr32(fp0, fs);
7175 gen_load_fpr32h(fph0, fs);
7176 gen_store_fpr32(fp0, fd);
7177 gen_store_fpr32h(fph0, fd);
7178 tcg_temp_free(fp0);
7179 tcg_temp_free(fph0);
7180 gen_set_label(l1);
7182 opn = "movn.ps";
7183 break;
7184 case FOP(24, 22):
7185 check_cp1_64bitmode(ctx);
7187 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7188 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7190 gen_load_fpr64(ctx, fp0, ft);
7191 gen_load_fpr64(ctx, fp1, fs);
7192 tcg_gen_helper_1_2(do_float_addr_ps, fp0, fp0, fp1);
7193 tcg_temp_free(fp1);
7194 gen_store_fpr64(ctx, fp0, fd);
7195 tcg_temp_free(fp0);
7197 opn = "addr.ps";
7198 break;
7199 case FOP(26, 22):
7200 check_cp1_64bitmode(ctx);
7202 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7203 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7205 gen_load_fpr64(ctx, fp0, ft);
7206 gen_load_fpr64(ctx, fp1, fs);
7207 tcg_gen_helper_1_2(do_float_mulr_ps, fp0, fp0, fp1);
7208 tcg_temp_free(fp1);
7209 gen_store_fpr64(ctx, fp0, fd);
7210 tcg_temp_free(fp0);
7212 opn = "mulr.ps";
7213 break;
7214 case FOP(28, 22):
7215 check_cp1_64bitmode(ctx);
7217 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7218 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7220 gen_load_fpr64(ctx, fp0, fs);
7221 gen_load_fpr64(ctx, fp1, fd);
7222 tcg_gen_helper_1_2(do_float_recip2_ps, fp0, fp0, fp1);
7223 tcg_temp_free(fp1);
7224 gen_store_fpr64(ctx, fp0, fd);
7225 tcg_temp_free(fp0);
7227 opn = "recip2.ps";
7228 break;
7229 case FOP(29, 22):
7230 check_cp1_64bitmode(ctx);
7232 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7234 gen_load_fpr64(ctx, fp0, fs);
7235 tcg_gen_helper_1_1(do_float_recip1_ps, fp0, fp0);
7236 gen_store_fpr64(ctx, fp0, fd);
7237 tcg_temp_free(fp0);
7239 opn = "recip1.ps";
7240 break;
7241 case FOP(30, 22):
7242 check_cp1_64bitmode(ctx);
7244 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7246 gen_load_fpr64(ctx, fp0, fs);
7247 tcg_gen_helper_1_1(do_float_rsqrt1_ps, fp0, fp0);
7248 gen_store_fpr64(ctx, fp0, fd);
7249 tcg_temp_free(fp0);
7251 opn = "rsqrt1.ps";
7252 break;
7253 case FOP(31, 22):
7254 check_cp1_64bitmode(ctx);
7256 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7257 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7259 gen_load_fpr64(ctx, fp0, fs);
7260 gen_load_fpr64(ctx, fp1, ft);
7261 tcg_gen_helper_1_2(do_float_rsqrt2_ps, fp0, fp0, fp1);
7262 tcg_temp_free(fp1);
7263 gen_store_fpr64(ctx, fp0, fd);
7264 tcg_temp_free(fp0);
7266 opn = "rsqrt2.ps";
7267 break;
7268 case FOP(32, 22):
7269 check_cp1_64bitmode(ctx);
7271 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7273 gen_load_fpr32h(fp0, fs);
7274 tcg_gen_helper_1_1(do_float_cvts_pu, fp0, fp0);
7275 gen_store_fpr32(fp0, fd);
7276 tcg_temp_free(fp0);
7278 opn = "cvt.s.pu";
7279 break;
7280 case FOP(36, 22):
7281 check_cp1_64bitmode(ctx);
7283 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7285 gen_load_fpr64(ctx, fp0, fs);
7286 tcg_gen_helper_1_1(do_float_cvtpw_ps, fp0, fp0);
7287 gen_store_fpr64(ctx, fp0, fd);
7288 tcg_temp_free(fp0);
7290 opn = "cvt.pw.ps";
7291 break;
7292 case FOP(40, 22):
7293 check_cp1_64bitmode(ctx);
7295 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7297 gen_load_fpr32(fp0, fs);
7298 tcg_gen_helper_1_1(do_float_cvts_pl, fp0, fp0);
7299 gen_store_fpr32(fp0, fd);
7300 tcg_temp_free(fp0);
7302 opn = "cvt.s.pl";
7303 break;
7304 case FOP(44, 22):
7305 check_cp1_64bitmode(ctx);
7307 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7308 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7310 gen_load_fpr32(fp0, fs);
7311 gen_load_fpr32(fp1, ft);
7312 gen_store_fpr32h(fp0, fd);
7313 gen_store_fpr32(fp1, fd);
7314 tcg_temp_free(fp0);
7315 tcg_temp_free(fp1);
7317 opn = "pll.ps";
7318 break;
7319 case FOP(45, 22):
7320 check_cp1_64bitmode(ctx);
7322 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7323 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7325 gen_load_fpr32(fp0, fs);
7326 gen_load_fpr32h(fp1, ft);
7327 gen_store_fpr32(fp1, fd);
7328 gen_store_fpr32h(fp0, fd);
7329 tcg_temp_free(fp0);
7330 tcg_temp_free(fp1);
7332 opn = "plu.ps";
7333 break;
7334 case FOP(46, 22):
7335 check_cp1_64bitmode(ctx);
7337 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7338 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7340 gen_load_fpr32h(fp0, fs);
7341 gen_load_fpr32(fp1, ft);
7342 gen_store_fpr32(fp1, fd);
7343 gen_store_fpr32h(fp0, fd);
7344 tcg_temp_free(fp0);
7345 tcg_temp_free(fp1);
7347 opn = "pul.ps";
7348 break;
7349 case FOP(47, 22):
7350 check_cp1_64bitmode(ctx);
7352 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7353 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7355 gen_load_fpr32h(fp0, fs);
7356 gen_load_fpr32h(fp1, ft);
7357 gen_store_fpr32(fp1, fd);
7358 gen_store_fpr32h(fp0, fd);
7359 tcg_temp_free(fp0);
7360 tcg_temp_free(fp1);
7362 opn = "puu.ps";
7363 break;
7364 case FOP(48, 22):
7365 case FOP(49, 22):
7366 case FOP(50, 22):
7367 case FOP(51, 22):
7368 case FOP(52, 22):
7369 case FOP(53, 22):
7370 case FOP(54, 22):
7371 case FOP(55, 22):
7372 case FOP(56, 22):
7373 case FOP(57, 22):
7374 case FOP(58, 22):
7375 case FOP(59, 22):
7376 case FOP(60, 22):
7377 case FOP(61, 22):
7378 case FOP(62, 22):
7379 case FOP(63, 22):
7380 check_cp1_64bitmode(ctx);
7382 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7383 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7385 gen_load_fpr64(ctx, fp0, fs);
7386 gen_load_fpr64(ctx, fp1, ft);
7387 if (ctx->opcode & (1 << 6)) {
7388 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7389 opn = condnames_abs[func-48];
7390 } else {
7391 gen_cmp_ps(func-48, fp0, fp1, cc);
7392 opn = condnames[func-48];
7394 tcg_temp_free(fp0);
7395 tcg_temp_free(fp1);
7397 break;
7398 default:
7399 MIPS_INVAL(opn);
7400 generate_exception (ctx, EXCP_RI);
7401 return;
7403 switch (optype) {
7404 case BINOP:
7405 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7406 break;
7407 case CMPOP:
7408 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7409 break;
7410 default:
7411 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7412 break;
7416 /* Coprocessor 3 (FPU) */
7417 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7418 int fd, int fs, int base, int index)
7420 const char *opn = "extended float load/store";
7421 int store = 0;
7422 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7423 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
7425 if (base == 0) {
7426 gen_load_gpr(t0, index);
7427 } else if (index == 0) {
7428 gen_load_gpr(t0, base);
7429 } else {
7430 gen_load_gpr(t0, base);
7431 gen_load_gpr(t1, index);
7432 gen_op_addr_add(t0, t1);
7434 /* Don't do NOP if destination is zero: we must perform the actual
7435 memory access. */
7436 switch (opc) {
7437 case OPC_LWXC1:
7438 check_cop1x(ctx);
7440 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7442 tcg_gen_qemu_ld32s(fp0, t0, ctx->mem_idx);
7443 gen_store_fpr32(fp0, fd);
7444 tcg_temp_free(fp0);
7446 opn = "lwxc1";
7447 break;
7448 case OPC_LDXC1:
7449 check_cop1x(ctx);
7450 check_cp1_registers(ctx, fd);
7452 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7454 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7455 gen_store_fpr64(ctx, fp0, fd);
7456 tcg_temp_free(fp0);
7458 opn = "ldxc1";
7459 break;
7460 case OPC_LUXC1:
7461 check_cp1_64bitmode(ctx);
7462 tcg_gen_andi_tl(t0, t0, ~0x7);
7464 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7466 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7467 gen_store_fpr64(ctx, fp0, fd);
7468 tcg_temp_free(fp0);
7470 opn = "luxc1";
7471 break;
7472 case OPC_SWXC1:
7473 check_cop1x(ctx);
7475 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7477 gen_load_fpr32(fp0, fs);
7478 tcg_gen_qemu_st32(fp0, t0, ctx->mem_idx);
7479 tcg_temp_free(fp0);
7481 opn = "swxc1";
7482 store = 1;
7483 break;
7484 case OPC_SDXC1:
7485 check_cop1x(ctx);
7486 check_cp1_registers(ctx, fs);
7488 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7490 gen_load_fpr64(ctx, fp0, fs);
7491 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7492 tcg_temp_free(fp0);
7494 opn = "sdxc1";
7495 store = 1;
7496 break;
7497 case OPC_SUXC1:
7498 check_cp1_64bitmode(ctx);
7499 tcg_gen_andi_tl(t0, t0, ~0x7);
7501 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7503 gen_load_fpr64(ctx, fp0, fs);
7504 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7505 tcg_temp_free(fp0);
7507 opn = "suxc1";
7508 store = 1;
7509 break;
7510 default:
7511 MIPS_INVAL(opn);
7512 generate_exception(ctx, EXCP_RI);
7513 tcg_temp_free(t0);
7514 tcg_temp_free(t1);
7515 return;
7517 tcg_temp_free(t0);
7518 tcg_temp_free(t1);
7519 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7520 regnames[index], regnames[base]);
7523 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7524 int fd, int fr, int fs, int ft)
7526 const char *opn = "flt3_arith";
7528 switch (opc) {
7529 case OPC_ALNV_PS:
7530 check_cp1_64bitmode(ctx);
7532 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7533 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7534 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7535 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
7536 TCGv fph1 = tcg_temp_local_new(TCG_TYPE_I32);
7537 int l1 = gen_new_label();
7538 int l2 = gen_new_label();
7540 gen_load_gpr(t0, fr);
7541 tcg_gen_andi_tl(t0, t0, 0x7);
7542 gen_load_fpr32(fp0, fs);
7543 gen_load_fpr32h(fph0, fs);
7544 gen_load_fpr32(fp1, ft);
7545 gen_load_fpr32h(fph1, ft);
7547 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7548 gen_store_fpr32(fp0, fd);
7549 gen_store_fpr32h(fph0, fd);
7550 tcg_gen_br(l2);
7551 gen_set_label(l1);
7552 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7553 tcg_temp_free(t0);
7554 #ifdef TARGET_WORDS_BIGENDIAN
7555 gen_store_fpr32(fph1, fd);
7556 gen_store_fpr32h(fp0, fd);
7557 #else
7558 gen_store_fpr32(fph0, fd);
7559 gen_store_fpr32h(fp1, fd);
7560 #endif
7561 gen_set_label(l2);
7562 tcg_temp_free(fp0);
7563 tcg_temp_free(fph0);
7564 tcg_temp_free(fp1);
7565 tcg_temp_free(fph1);
7567 opn = "alnv.ps";
7568 break;
7569 case OPC_MADD_S:
7570 check_cop1x(ctx);
7572 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7573 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7574 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7576 gen_load_fpr32(fp0, fs);
7577 gen_load_fpr32(fp1, ft);
7578 gen_load_fpr32(fp2, fr);
7579 tcg_gen_helper_1_3(do_float_muladd_s, fp2, fp0, fp1, fp2);
7580 tcg_temp_free(fp0);
7581 tcg_temp_free(fp1);
7582 gen_store_fpr32(fp2, fd);
7583 tcg_temp_free(fp2);
7585 opn = "madd.s";
7586 break;
7587 case OPC_MADD_D:
7588 check_cop1x(ctx);
7589 check_cp1_registers(ctx, fd | fs | ft | fr);
7591 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7592 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7593 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7595 gen_load_fpr64(ctx, fp0, fs);
7596 gen_load_fpr64(ctx, fp1, ft);
7597 gen_load_fpr64(ctx, fp2, fr);
7598 tcg_gen_helper_1_3(do_float_muladd_d, fp2, fp0, fp1, fp2);
7599 tcg_temp_free(fp0);
7600 tcg_temp_free(fp1);
7601 gen_store_fpr64(ctx, fp2, fd);
7602 tcg_temp_free(fp2);
7604 opn = "madd.d";
7605 break;
7606 case OPC_MADD_PS:
7607 check_cp1_64bitmode(ctx);
7609 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7610 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7611 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7613 gen_load_fpr64(ctx, fp0, fs);
7614 gen_load_fpr64(ctx, fp1, ft);
7615 gen_load_fpr64(ctx, fp2, fr);
7616 tcg_gen_helper_1_3(do_float_muladd_ps, fp2, fp0, fp1, fp2);
7617 tcg_temp_free(fp0);
7618 tcg_temp_free(fp1);
7619 gen_store_fpr64(ctx, fp2, fd);
7620 tcg_temp_free(fp2);
7622 opn = "madd.ps";
7623 break;
7624 case OPC_MSUB_S:
7625 check_cop1x(ctx);
7627 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7628 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7629 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7631 gen_load_fpr32(fp0, fs);
7632 gen_load_fpr32(fp1, ft);
7633 gen_load_fpr32(fp2, fr);
7634 tcg_gen_helper_1_3(do_float_mulsub_s, fp2, fp0, fp1, fp2);
7635 tcg_temp_free(fp0);
7636 tcg_temp_free(fp1);
7637 gen_store_fpr32(fp2, fd);
7638 tcg_temp_free(fp2);
7640 opn = "msub.s";
7641 break;
7642 case OPC_MSUB_D:
7643 check_cop1x(ctx);
7644 check_cp1_registers(ctx, fd | fs | ft | fr);
7646 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7647 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7648 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7650 gen_load_fpr64(ctx, fp0, fs);
7651 gen_load_fpr64(ctx, fp1, ft);
7652 gen_load_fpr64(ctx, fp2, fr);
7653 tcg_gen_helper_1_3(do_float_mulsub_d, fp2, fp0, fp1, fp2);
7654 tcg_temp_free(fp0);
7655 tcg_temp_free(fp1);
7656 gen_store_fpr64(ctx, fp2, fd);
7657 tcg_temp_free(fp2);
7659 opn = "msub.d";
7660 break;
7661 case OPC_MSUB_PS:
7662 check_cp1_64bitmode(ctx);
7664 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7665 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7666 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7668 gen_load_fpr64(ctx, fp0, fs);
7669 gen_load_fpr64(ctx, fp1, ft);
7670 gen_load_fpr64(ctx, fp2, fr);
7671 tcg_gen_helper_1_3(do_float_mulsub_ps, fp2, fp0, fp1, fp2);
7672 tcg_temp_free(fp0);
7673 tcg_temp_free(fp1);
7674 gen_store_fpr64(ctx, fp2, fd);
7675 tcg_temp_free(fp2);
7677 opn = "msub.ps";
7678 break;
7679 case OPC_NMADD_S:
7680 check_cop1x(ctx);
7682 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7683 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7684 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7686 gen_load_fpr32(fp0, fs);
7687 gen_load_fpr32(fp1, ft);
7688 gen_load_fpr32(fp2, fr);
7689 tcg_gen_helper_1_3(do_float_nmuladd_s, fp2, fp0, fp1, fp2);
7690 tcg_temp_free(fp0);
7691 tcg_temp_free(fp1);
7692 gen_store_fpr32(fp2, fd);
7693 tcg_temp_free(fp2);
7695 opn = "nmadd.s";
7696 break;
7697 case OPC_NMADD_D:
7698 check_cop1x(ctx);
7699 check_cp1_registers(ctx, fd | fs | ft | fr);
7701 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7702 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7703 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7705 gen_load_fpr64(ctx, fp0, fs);
7706 gen_load_fpr64(ctx, fp1, ft);
7707 gen_load_fpr64(ctx, fp2, fr);
7708 tcg_gen_helper_1_3(do_float_nmuladd_d, fp2, fp0, fp1, fp2);
7709 tcg_temp_free(fp0);
7710 tcg_temp_free(fp1);
7711 gen_store_fpr64(ctx, fp2, fd);
7712 tcg_temp_free(fp2);
7714 opn = "nmadd.d";
7715 break;
7716 case OPC_NMADD_PS:
7717 check_cp1_64bitmode(ctx);
7719 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7720 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7721 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7723 gen_load_fpr64(ctx, fp0, fs);
7724 gen_load_fpr64(ctx, fp1, ft);
7725 gen_load_fpr64(ctx, fp2, fr);
7726 tcg_gen_helper_1_3(do_float_nmuladd_ps, fp2, fp0, fp1, fp2);
7727 tcg_temp_free(fp0);
7728 tcg_temp_free(fp1);
7729 gen_store_fpr64(ctx, fp2, fd);
7730 tcg_temp_free(fp2);
7732 opn = "nmadd.ps";
7733 break;
7734 case OPC_NMSUB_S:
7735 check_cop1x(ctx);
7737 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7738 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7739 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7741 gen_load_fpr32(fp0, fs);
7742 gen_load_fpr32(fp1, ft);
7743 gen_load_fpr32(fp2, fr);
7744 tcg_gen_helper_1_3(do_float_nmulsub_s, fp2, fp0, fp1, fp2);
7745 tcg_temp_free(fp0);
7746 tcg_temp_free(fp1);
7747 gen_store_fpr32(fp2, fd);
7748 tcg_temp_free(fp2);
7750 opn = "nmsub.s";
7751 break;
7752 case OPC_NMSUB_D:
7753 check_cop1x(ctx);
7754 check_cp1_registers(ctx, fd | fs | ft | fr);
7756 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7757 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7758 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7760 gen_load_fpr64(ctx, fp0, fs);
7761 gen_load_fpr64(ctx, fp1, ft);
7762 gen_load_fpr64(ctx, fp2, fr);
7763 tcg_gen_helper_1_3(do_float_nmulsub_d, fp2, fp0, fp1, fp2);
7764 tcg_temp_free(fp0);
7765 tcg_temp_free(fp1);
7766 gen_store_fpr64(ctx, fp2, fd);
7767 tcg_temp_free(fp2);
7769 opn = "nmsub.d";
7770 break;
7771 case OPC_NMSUB_PS:
7772 check_cp1_64bitmode(ctx);
7774 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7775 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7776 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7778 gen_load_fpr64(ctx, fp0, fs);
7779 gen_load_fpr64(ctx, fp1, ft);
7780 gen_load_fpr64(ctx, fp2, fr);
7781 tcg_gen_helper_1_3(do_float_nmulsub_ps, fp2, fp0, fp1, fp2);
7782 tcg_temp_free(fp0);
7783 tcg_temp_free(fp1);
7784 gen_store_fpr64(ctx, fp2, fd);
7785 tcg_temp_free(fp2);
7787 opn = "nmsub.ps";
7788 break;
7789 default:
7790 MIPS_INVAL(opn);
7791 generate_exception (ctx, EXCP_RI);
7792 return;
7794 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7795 fregnames[fs], fregnames[ft]);
7798 /* ISA extensions (ASEs) */
7799 /* MIPS16 extension to MIPS32 */
7800 /* SmartMIPS extension to MIPS32 */
7802 #if defined(TARGET_MIPS64)
7804 /* MDMX extension to MIPS64 */
7806 #endif
7808 static void decode_opc (CPUState *env, DisasContext *ctx)
7810 int32_t offset;
7811 int rs, rt, rd, sa;
7812 uint32_t op, op1, op2;
7813 int16_t imm;
7815 /* make sure instructions are on a word boundary */
7816 if (ctx->pc & 0x3) {
7817 env->CP0_BadVAddr = ctx->pc;
7818 generate_exception(ctx, EXCP_AdEL);
7819 return;
7822 /* Handle blikely not taken case */
7823 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7824 int l1 = gen_new_label();
7826 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7827 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
7829 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
7831 tcg_gen_movi_i32(r_tmp, ctx->hflags & ~MIPS_HFLAG_BMASK);
7832 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
7833 tcg_temp_free(r_tmp);
7835 gen_goto_tb(ctx, 1, ctx->pc + 4);
7836 gen_set_label(l1);
7838 op = MASK_OP_MAJOR(ctx->opcode);
7839 rs = (ctx->opcode >> 21) & 0x1f;
7840 rt = (ctx->opcode >> 16) & 0x1f;
7841 rd = (ctx->opcode >> 11) & 0x1f;
7842 sa = (ctx->opcode >> 6) & 0x1f;
7843 imm = (int16_t)ctx->opcode;
7844 switch (op) {
7845 case OPC_SPECIAL:
7846 op1 = MASK_SPECIAL(ctx->opcode);
7847 switch (op1) {
7848 case OPC_SLL: /* Arithmetic with immediate */
7849 case OPC_SRL ... OPC_SRA:
7850 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7851 break;
7852 case OPC_MOVZ ... OPC_MOVN:
7853 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7854 case OPC_SLLV: /* Arithmetic */
7855 case OPC_SRLV ... OPC_SRAV:
7856 case OPC_ADD ... OPC_NOR:
7857 case OPC_SLT ... OPC_SLTU:
7858 gen_arith(env, ctx, op1, rd, rs, rt);
7859 break;
7860 case OPC_MULT ... OPC_DIVU:
7861 if (sa) {
7862 check_insn(env, ctx, INSN_VR54XX);
7863 op1 = MASK_MUL_VR54XX(ctx->opcode);
7864 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7865 } else
7866 gen_muldiv(ctx, op1, rs, rt);
7867 break;
7868 case OPC_JR ... OPC_JALR:
7869 gen_compute_branch(ctx, op1, rs, rd, sa);
7870 return;
7871 case OPC_TGE ... OPC_TEQ: /* Traps */
7872 case OPC_TNE:
7873 gen_trap(ctx, op1, rs, rt, -1);
7874 break;
7875 case OPC_MFHI: /* Move from HI/LO */
7876 case OPC_MFLO:
7877 gen_HILO(ctx, op1, rd);
7878 break;
7879 case OPC_MTHI:
7880 case OPC_MTLO: /* Move to HI/LO */
7881 gen_HILO(ctx, op1, rs);
7882 break;
7883 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7884 #ifdef MIPS_STRICT_STANDARD
7885 MIPS_INVAL("PMON / selsl");
7886 generate_exception(ctx, EXCP_RI);
7887 #else
7888 tcg_gen_helper_0_i(do_pmon, sa);
7889 #endif
7890 break;
7891 case OPC_SYSCALL:
7892 generate_exception(ctx, EXCP_SYSCALL);
7893 break;
7894 case OPC_BREAK:
7895 generate_exception(ctx, EXCP_BREAK);
7896 break;
7897 case OPC_SPIM:
7898 #ifdef MIPS_STRICT_STANDARD
7899 MIPS_INVAL("SPIM");
7900 generate_exception(ctx, EXCP_RI);
7901 #else
7902 /* Implemented as RI exception for now. */
7903 MIPS_INVAL("spim (unofficial)");
7904 generate_exception(ctx, EXCP_RI);
7905 #endif
7906 break;
7907 case OPC_SYNC:
7908 /* Treat as NOP. */
7909 break;
7911 case OPC_MOVCI:
7912 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7913 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7914 save_cpu_state(ctx, 1);
7915 check_cp1_enabled(ctx);
7916 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7917 (ctx->opcode >> 16) & 1);
7918 } else {
7919 generate_exception_err(ctx, EXCP_CpU, 1);
7921 break;
7923 #if defined(TARGET_MIPS64)
7924 /* MIPS64 specific opcodes */
7925 case OPC_DSLL:
7926 case OPC_DSRL ... OPC_DSRA:
7927 case OPC_DSLL32:
7928 case OPC_DSRL32 ... OPC_DSRA32:
7929 check_insn(env, ctx, ISA_MIPS3);
7930 check_mips_64(ctx);
7931 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7932 break;
7933 case OPC_DSLLV:
7934 case OPC_DSRLV ... OPC_DSRAV:
7935 case OPC_DADD ... OPC_DSUBU:
7936 check_insn(env, ctx, ISA_MIPS3);
7937 check_mips_64(ctx);
7938 gen_arith(env, ctx, op1, rd, rs, rt);
7939 break;
7940 case OPC_DMULT ... OPC_DDIVU:
7941 check_insn(env, ctx, ISA_MIPS3);
7942 check_mips_64(ctx);
7943 gen_muldiv(ctx, op1, rs, rt);
7944 break;
7945 #endif
7946 default: /* Invalid */
7947 MIPS_INVAL("special");
7948 generate_exception(ctx, EXCP_RI);
7949 break;
7951 break;
7952 case OPC_SPECIAL2:
7953 op1 = MASK_SPECIAL2(ctx->opcode);
7954 switch (op1) {
7955 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7956 case OPC_MSUB ... OPC_MSUBU:
7957 check_insn(env, ctx, ISA_MIPS32);
7958 gen_muldiv(ctx, op1, rs, rt);
7959 break;
7960 case OPC_MUL:
7961 gen_arith(env, ctx, op1, rd, rs, rt);
7962 break;
7963 case OPC_CLZ ... OPC_CLO:
7964 check_insn(env, ctx, ISA_MIPS32);
7965 gen_cl(ctx, op1, rd, rs);
7966 break;
7967 case OPC_SDBBP:
7968 /* XXX: not clear which exception should be raised
7969 * when in debug mode...
7971 check_insn(env, ctx, ISA_MIPS32);
7972 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7973 generate_exception(ctx, EXCP_DBp);
7974 } else {
7975 generate_exception(ctx, EXCP_DBp);
7977 /* Treat as NOP. */
7978 break;
7979 #if defined(TARGET_MIPS64)
7980 case OPC_DCLZ ... OPC_DCLO:
7981 check_insn(env, ctx, ISA_MIPS64);
7982 check_mips_64(ctx);
7983 gen_cl(ctx, op1, rd, rs);
7984 break;
7985 #endif
7986 default: /* Invalid */
7987 MIPS_INVAL("special2");
7988 generate_exception(ctx, EXCP_RI);
7989 break;
7991 break;
7992 case OPC_SPECIAL3:
7993 op1 = MASK_SPECIAL3(ctx->opcode);
7994 switch (op1) {
7995 case OPC_EXT:
7996 case OPC_INS:
7997 check_insn(env, ctx, ISA_MIPS32R2);
7998 gen_bitops(ctx, op1, rt, rs, sa, rd);
7999 break;
8000 case OPC_BSHFL:
8001 check_insn(env, ctx, ISA_MIPS32R2);
8002 op2 = MASK_BSHFL(ctx->opcode);
8004 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8005 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
8007 switch (op2) {
8008 case OPC_WSBH:
8009 gen_load_gpr(t1, rt);
8010 tcg_gen_helper_1_1(do_wsbh, t0, t1);
8011 gen_store_gpr(t0, rd);
8012 break;
8013 case OPC_SEB:
8014 gen_load_gpr(t1, rt);
8015 tcg_gen_ext8s_tl(t0, t1);
8016 gen_store_gpr(t0, rd);
8017 break;
8018 case OPC_SEH:
8019 gen_load_gpr(t1, rt);
8020 tcg_gen_ext16s_tl(t0, t1);
8021 gen_store_gpr(t0, rd);
8022 break;
8023 default: /* Invalid */
8024 MIPS_INVAL("bshfl");
8025 generate_exception(ctx, EXCP_RI);
8026 break;
8028 tcg_temp_free(t0);
8029 tcg_temp_free(t1);
8031 break;
8032 case OPC_RDHWR:
8033 check_insn(env, ctx, ISA_MIPS32R2);
8035 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8037 switch (rd) {
8038 case 0:
8039 save_cpu_state(ctx, 1);
8040 tcg_gen_helper_1_0(do_rdhwr_cpunum, t0);
8041 break;
8042 case 1:
8043 save_cpu_state(ctx, 1);
8044 tcg_gen_helper_1_0(do_rdhwr_synci_step, t0);
8045 break;
8046 case 2:
8047 save_cpu_state(ctx, 1);
8048 tcg_gen_helper_1_0(do_rdhwr_cc, t0);
8049 break;
8050 case 3:
8051 save_cpu_state(ctx, 1);
8052 tcg_gen_helper_1_0(do_rdhwr_ccres, t0);
8053 break;
8054 case 29:
8055 if (env->user_mode_only) {
8056 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
8057 break;
8058 } else {
8059 /* XXX: Some CPUs implement this in hardware.
8060 Not supported yet. */
8062 default: /* Invalid */
8063 MIPS_INVAL("rdhwr");
8064 generate_exception(ctx, EXCP_RI);
8065 break;
8067 gen_store_gpr(t0, rt);
8068 tcg_temp_free(t0);
8070 break;
8071 case OPC_FORK:
8072 check_insn(env, ctx, ASE_MT);
8074 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8075 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
8077 gen_load_gpr(t0, rt);
8078 gen_load_gpr(t1, rs);
8079 tcg_gen_helper_0_2(do_fork, t0, t1);
8080 tcg_temp_free(t0);
8081 tcg_temp_free(t1);
8083 break;
8084 case OPC_YIELD:
8085 check_insn(env, ctx, ASE_MT);
8087 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8089 gen_load_gpr(t0, rs);
8090 tcg_gen_helper_1_1(do_yield, t0, t0);
8091 gen_store_gpr(t0, rd);
8092 tcg_temp_free(t0);
8094 break;
8095 #if defined(TARGET_MIPS64)
8096 case OPC_DEXTM ... OPC_DEXT:
8097 case OPC_DINSM ... OPC_DINS:
8098 check_insn(env, ctx, ISA_MIPS64R2);
8099 check_mips_64(ctx);
8100 gen_bitops(ctx, op1, rt, rs, sa, rd);
8101 break;
8102 case OPC_DBSHFL:
8103 check_insn(env, ctx, ISA_MIPS64R2);
8104 check_mips_64(ctx);
8105 op2 = MASK_DBSHFL(ctx->opcode);
8107 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8108 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
8110 switch (op2) {
8111 case OPC_DSBH:
8112 gen_load_gpr(t1, rt);
8113 tcg_gen_helper_1_1(do_dsbh, t0, t1);
8114 break;
8115 case OPC_DSHD:
8116 gen_load_gpr(t1, rt);
8117 tcg_gen_helper_1_1(do_dshd, t0, t1);
8118 break;
8119 default: /* Invalid */
8120 MIPS_INVAL("dbshfl");
8121 generate_exception(ctx, EXCP_RI);
8122 break;
8124 gen_store_gpr(t0, rd);
8125 tcg_temp_free(t0);
8126 tcg_temp_free(t1);
8128 break;
8129 #endif
8130 default: /* Invalid */
8131 MIPS_INVAL("special3");
8132 generate_exception(ctx, EXCP_RI);
8133 break;
8135 break;
8136 case OPC_REGIMM:
8137 op1 = MASK_REGIMM(ctx->opcode);
8138 switch (op1) {
8139 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
8140 case OPC_BLTZAL ... OPC_BGEZALL:
8141 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
8142 return;
8143 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
8144 case OPC_TNEI:
8145 gen_trap(ctx, op1, rs, -1, imm);
8146 break;
8147 case OPC_SYNCI:
8148 check_insn(env, ctx, ISA_MIPS32R2);
8149 /* Treat as NOP. */
8150 break;
8151 default: /* Invalid */
8152 MIPS_INVAL("regimm");
8153 generate_exception(ctx, EXCP_RI);
8154 break;
8156 break;
8157 case OPC_CP0:
8158 check_cp0_enabled(ctx);
8159 op1 = MASK_CP0(ctx->opcode);
8160 switch (op1) {
8161 case OPC_MFC0:
8162 case OPC_MTC0:
8163 case OPC_MFTR:
8164 case OPC_MTTR:
8165 #if defined(TARGET_MIPS64)
8166 case OPC_DMFC0:
8167 case OPC_DMTC0:
8168 #endif
8169 #ifndef CONFIG_USER_ONLY
8170 if (!env->user_mode_only)
8171 gen_cp0(env, ctx, op1, rt, rd);
8172 #endif /* !CONFIG_USER_ONLY */
8173 break;
8174 case OPC_C0_FIRST ... OPC_C0_LAST:
8175 #ifndef CONFIG_USER_ONLY
8176 if (!env->user_mode_only)
8177 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
8178 #endif /* !CONFIG_USER_ONLY */
8179 break;
8180 case OPC_MFMC0:
8181 #ifndef CONFIG_USER_ONLY
8182 if (!env->user_mode_only) {
8183 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8185 op2 = MASK_MFMC0(ctx->opcode);
8186 switch (op2) {
8187 case OPC_DMT:
8188 check_insn(env, ctx, ASE_MT);
8189 tcg_gen_helper_1_1(do_dmt, t0, t0);
8190 break;
8191 case OPC_EMT:
8192 check_insn(env, ctx, ASE_MT);
8193 tcg_gen_helper_1_1(do_emt, t0, t0);
8194 break;
8195 case OPC_DVPE:
8196 check_insn(env, ctx, ASE_MT);
8197 tcg_gen_helper_1_1(do_dvpe, t0, t0);
8198 break;
8199 case OPC_EVPE:
8200 check_insn(env, ctx, ASE_MT);
8201 tcg_gen_helper_1_1(do_evpe, t0, t0);
8202 break;
8203 case OPC_DI:
8204 check_insn(env, ctx, ISA_MIPS32R2);
8205 save_cpu_state(ctx, 1);
8206 tcg_gen_helper_1_0(do_di, t0);
8207 /* Stop translation as we may have switched the execution mode */
8208 ctx->bstate = BS_STOP;
8209 break;
8210 case OPC_EI:
8211 check_insn(env, ctx, ISA_MIPS32R2);
8212 save_cpu_state(ctx, 1);
8213 tcg_gen_helper_1_0(do_ei, t0);
8214 /* Stop translation as we may have switched the execution mode */
8215 ctx->bstate = BS_STOP;
8216 break;
8217 default: /* Invalid */
8218 MIPS_INVAL("mfmc0");
8219 generate_exception(ctx, EXCP_RI);
8220 break;
8222 gen_store_gpr(t0, rt);
8223 tcg_temp_free(t0);
8225 #endif /* !CONFIG_USER_ONLY */
8226 break;
8227 case OPC_RDPGPR:
8228 check_insn(env, ctx, ISA_MIPS32R2);
8229 gen_load_srsgpr(rt, rd);
8230 break;
8231 case OPC_WRPGPR:
8232 check_insn(env, ctx, ISA_MIPS32R2);
8233 gen_store_srsgpr(rt, rd);
8234 break;
8235 default:
8236 MIPS_INVAL("cp0");
8237 generate_exception(ctx, EXCP_RI);
8238 break;
8240 break;
8241 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
8242 gen_arith_imm(env, ctx, op, rt, rs, imm);
8243 break;
8244 case OPC_J ... OPC_JAL: /* Jump */
8245 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8246 gen_compute_branch(ctx, op, rs, rt, offset);
8247 return;
8248 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8249 case OPC_BEQL ... OPC_BGTZL:
8250 gen_compute_branch(ctx, op, rs, rt, imm << 2);
8251 return;
8252 case OPC_LB ... OPC_LWR: /* Load and stores */
8253 case OPC_SB ... OPC_SW:
8254 case OPC_SWR:
8255 case OPC_LL:
8256 case OPC_SC:
8257 gen_ldst(ctx, op, rt, rs, imm);
8258 break;
8259 case OPC_CACHE:
8260 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
8261 /* Treat as NOP. */
8262 break;
8263 case OPC_PREF:
8264 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8265 /* Treat as NOP. */
8266 break;
8268 /* Floating point (COP1). */
8269 case OPC_LWC1:
8270 case OPC_LDC1:
8271 case OPC_SWC1:
8272 case OPC_SDC1:
8273 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8274 save_cpu_state(ctx, 1);
8275 check_cp1_enabled(ctx);
8276 gen_flt_ldst(ctx, op, rt, rs, imm);
8277 } else {
8278 generate_exception_err(ctx, EXCP_CpU, 1);
8280 break;
8282 case OPC_CP1:
8283 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8284 save_cpu_state(ctx, 1);
8285 check_cp1_enabled(ctx);
8286 op1 = MASK_CP1(ctx->opcode);
8287 switch (op1) {
8288 case OPC_MFHC1:
8289 case OPC_MTHC1:
8290 check_insn(env, ctx, ISA_MIPS32R2);
8291 case OPC_MFC1:
8292 case OPC_CFC1:
8293 case OPC_MTC1:
8294 case OPC_CTC1:
8295 gen_cp1(ctx, op1, rt, rd);
8296 break;
8297 #if defined(TARGET_MIPS64)
8298 case OPC_DMFC1:
8299 case OPC_DMTC1:
8300 check_insn(env, ctx, ISA_MIPS3);
8301 gen_cp1(ctx, op1, rt, rd);
8302 break;
8303 #endif
8304 case OPC_BC1ANY2:
8305 case OPC_BC1ANY4:
8306 check_cop1x(ctx);
8307 check_insn(env, ctx, ASE_MIPS3D);
8308 /* fall through */
8309 case OPC_BC1:
8310 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8311 (rt >> 2) & 0x7, imm << 2);
8312 return;
8313 case OPC_S_FMT:
8314 case OPC_D_FMT:
8315 case OPC_W_FMT:
8316 case OPC_L_FMT:
8317 case OPC_PS_FMT:
8318 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8319 (imm >> 8) & 0x7);
8320 break;
8321 default:
8322 MIPS_INVAL("cp1");
8323 generate_exception (ctx, EXCP_RI);
8324 break;
8326 } else {
8327 generate_exception_err(ctx, EXCP_CpU, 1);
8329 break;
8331 /* COP2. */
8332 case OPC_LWC2:
8333 case OPC_LDC2:
8334 case OPC_SWC2:
8335 case OPC_SDC2:
8336 case OPC_CP2:
8337 /* COP2: Not implemented. */
8338 generate_exception_err(ctx, EXCP_CpU, 2);
8339 break;
8341 case OPC_CP3:
8342 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8343 save_cpu_state(ctx, 1);
8344 check_cp1_enabled(ctx);
8345 op1 = MASK_CP3(ctx->opcode);
8346 switch (op1) {
8347 case OPC_LWXC1:
8348 case OPC_LDXC1:
8349 case OPC_LUXC1:
8350 case OPC_SWXC1:
8351 case OPC_SDXC1:
8352 case OPC_SUXC1:
8353 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8354 break;
8355 case OPC_PREFX:
8356 /* Treat as NOP. */
8357 break;
8358 case OPC_ALNV_PS:
8359 case OPC_MADD_S:
8360 case OPC_MADD_D:
8361 case OPC_MADD_PS:
8362 case OPC_MSUB_S:
8363 case OPC_MSUB_D:
8364 case OPC_MSUB_PS:
8365 case OPC_NMADD_S:
8366 case OPC_NMADD_D:
8367 case OPC_NMADD_PS:
8368 case OPC_NMSUB_S:
8369 case OPC_NMSUB_D:
8370 case OPC_NMSUB_PS:
8371 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8372 break;
8373 default:
8374 MIPS_INVAL("cp3");
8375 generate_exception (ctx, EXCP_RI);
8376 break;
8378 } else {
8379 generate_exception_err(ctx, EXCP_CpU, 1);
8381 break;
8383 #if defined(TARGET_MIPS64)
8384 /* MIPS64 opcodes */
8385 case OPC_LWU:
8386 case OPC_LDL ... OPC_LDR:
8387 case OPC_SDL ... OPC_SDR:
8388 case OPC_LLD:
8389 case OPC_LD:
8390 case OPC_SCD:
8391 case OPC_SD:
8392 check_insn(env, ctx, ISA_MIPS3);
8393 check_mips_64(ctx);
8394 gen_ldst(ctx, op, rt, rs, imm);
8395 break;
8396 case OPC_DADDI ... OPC_DADDIU:
8397 check_insn(env, ctx, ISA_MIPS3);
8398 check_mips_64(ctx);
8399 gen_arith_imm(env, ctx, op, rt, rs, imm);
8400 break;
8401 #endif
8402 case OPC_JALX:
8403 check_insn(env, ctx, ASE_MIPS16);
8404 /* MIPS16: Not implemented. */
8405 case OPC_MDMX:
8406 check_insn(env, ctx, ASE_MDMX);
8407 /* MDMX: Not implemented. */
8408 default: /* Invalid */
8409 MIPS_INVAL("major opcode");
8410 generate_exception(ctx, EXCP_RI);
8411 break;
8413 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8414 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8415 /* Branches completion */
8416 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8417 ctx->bstate = BS_BRANCH;
8418 save_cpu_state(ctx, 0);
8419 /* FIXME: Need to clear can_do_io. */
8420 switch (hflags) {
8421 case MIPS_HFLAG_B:
8422 /* unconditional branch */
8423 MIPS_DEBUG("unconditional branch");
8424 gen_goto_tb(ctx, 0, ctx->btarget);
8425 break;
8426 case MIPS_HFLAG_BL:
8427 /* blikely taken case */
8428 MIPS_DEBUG("blikely branch taken");
8429 gen_goto_tb(ctx, 0, ctx->btarget);
8430 break;
8431 case MIPS_HFLAG_BC:
8432 /* Conditional branch */
8433 MIPS_DEBUG("conditional branch");
8435 int l1 = gen_new_label();
8437 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
8438 gen_goto_tb(ctx, 1, ctx->pc + 4);
8439 gen_set_label(l1);
8440 gen_goto_tb(ctx, 0, ctx->btarget);
8442 break;
8443 case MIPS_HFLAG_BR:
8444 /* unconditional branch to register */
8445 MIPS_DEBUG("branch to register");
8446 tcg_gen_st_tl(btarget, cpu_env, offsetof(CPUState, active_tc.PC));
8447 tcg_gen_exit_tb(0);
8448 break;
8449 default:
8450 MIPS_DEBUG("unknown branch");
8451 break;
8456 static inline void
8457 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8458 int search_pc)
8460 DisasContext ctx;
8461 target_ulong pc_start;
8462 uint16_t *gen_opc_end;
8463 int j, lj = -1;
8464 int num_insns;
8465 int max_insns;
8467 if (search_pc && loglevel)
8468 fprintf (logfile, "search pc %d\n", search_pc);
8470 pc_start = tb->pc;
8471 /* Leave some spare opc slots for branch handling. */
8472 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
8473 ctx.pc = pc_start;
8474 ctx.saved_pc = -1;
8475 ctx.tb = tb;
8476 ctx.bstate = BS_NONE;
8477 /* Restore delay slot state from the tb context. */
8478 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8479 restore_cpu_state(env, &ctx);
8480 if (env->user_mode_only)
8481 ctx.mem_idx = MIPS_HFLAG_UM;
8482 else
8483 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8484 num_insns = 0;
8485 max_insns = tb->cflags & CF_COUNT_MASK;
8486 if (max_insns == 0)
8487 max_insns = CF_COUNT_MASK;
8488 #ifdef DEBUG_DISAS
8489 if (loglevel & CPU_LOG_TB_CPU) {
8490 fprintf(logfile, "------------------------------------------------\n");
8491 /* FIXME: This may print out stale hflags from env... */
8492 cpu_dump_state(env, logfile, fprintf, 0);
8494 #endif
8495 #ifdef MIPS_DEBUG_DISAS
8496 if (loglevel & CPU_LOG_TB_IN_ASM)
8497 fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
8498 tb, ctx.mem_idx, ctx.hflags);
8499 #endif
8500 gen_icount_start();
8501 while (ctx.bstate == BS_NONE) {
8502 if (env->nb_breakpoints > 0) {
8503 for(j = 0; j < env->nb_breakpoints; j++) {
8504 if (env->breakpoints[j] == ctx.pc) {
8505 save_cpu_state(&ctx, 1);
8506 ctx.bstate = BS_BRANCH;
8507 tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
8508 /* Include the breakpoint location or the tb won't
8509 * be flushed when it must be. */
8510 ctx.pc += 4;
8511 goto done_generating;
8516 if (search_pc) {
8517 j = gen_opc_ptr - gen_opc_buf;
8518 if (lj < j) {
8519 lj++;
8520 while (lj < j)
8521 gen_opc_instr_start[lj++] = 0;
8523 gen_opc_pc[lj] = ctx.pc;
8524 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8525 gen_opc_instr_start[lj] = 1;
8526 gen_opc_icount[lj] = num_insns;
8528 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8529 gen_io_start();
8530 ctx.opcode = ldl_code(ctx.pc);
8531 decode_opc(env, &ctx);
8532 ctx.pc += 4;
8533 num_insns++;
8535 if (env->singlestep_enabled)
8536 break;
8538 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8539 break;
8541 if (gen_opc_ptr >= gen_opc_end)
8542 break;
8544 if (num_insns >= max_insns)
8545 break;
8546 #if defined (MIPS_SINGLE_STEP)
8547 break;
8548 #endif
8550 if (tb->cflags & CF_LAST_IO)
8551 gen_io_end();
8552 if (env->singlestep_enabled) {
8553 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
8554 tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
8555 } else {
8556 switch (ctx.bstate) {
8557 case BS_STOP:
8558 tcg_gen_helper_0_0(do_interrupt_restart);
8559 gen_goto_tb(&ctx, 0, ctx.pc);
8560 break;
8561 case BS_NONE:
8562 save_cpu_state(&ctx, 0);
8563 gen_goto_tb(&ctx, 0, ctx.pc);
8564 break;
8565 case BS_EXCP:
8566 tcg_gen_helper_0_0(do_interrupt_restart);
8567 tcg_gen_exit_tb(0);
8568 break;
8569 case BS_BRANCH:
8570 default:
8571 break;
8574 done_generating:
8575 gen_icount_end(tb, num_insns);
8576 *gen_opc_ptr = INDEX_op_end;
8577 if (search_pc) {
8578 j = gen_opc_ptr - gen_opc_buf;
8579 lj++;
8580 while (lj <= j)
8581 gen_opc_instr_start[lj++] = 0;
8582 } else {
8583 tb->size = ctx.pc - pc_start;
8584 tb->icount = num_insns;
8586 #ifdef DEBUG_DISAS
8587 #if defined MIPS_DEBUG_DISAS
8588 if (loglevel & CPU_LOG_TB_IN_ASM)
8589 fprintf(logfile, "\n");
8590 #endif
8591 if (loglevel & CPU_LOG_TB_IN_ASM) {
8592 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
8593 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
8594 fprintf(logfile, "\n");
8596 if (loglevel & CPU_LOG_TB_CPU) {
8597 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8599 #endif
8602 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8604 gen_intermediate_code_internal(env, tb, 0);
8607 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8609 gen_intermediate_code_internal(env, tb, 1);
8612 static void fpu_dump_state(CPUState *env, FILE *f,
8613 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8614 int flags)
8616 int i;
8617 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8619 #define printfpr(fp) \
8620 do { \
8621 if (is_fpu64) \
8622 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8623 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8624 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8625 else { \
8626 fpr_t tmp; \
8627 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8628 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8629 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8630 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8631 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8633 } while(0)
8636 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8637 env->fpu->fcr0, env->fpu->fcr31, is_fpu64, env->fpu->fp_status,
8638 get_float_exception_flags(&env->fpu->fp_status));
8639 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8640 fpu_fprintf(f, "%3s: ", fregnames[i]);
8641 printfpr(&env->fpu->fpr[i]);
8644 #undef printfpr
8647 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8648 /* Debug help: The architecture requires 32bit code to maintain proper
8649 sign-extended values on 64bit machines. */
8651 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8653 static void
8654 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8655 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8656 int flags)
8658 int i;
8660 if (!SIGN_EXT_P(env->active_tc.PC))
8661 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8662 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8663 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8664 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8665 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8666 if (!SIGN_EXT_P(env->btarget))
8667 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8669 for (i = 0; i < 32; i++) {
8670 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8671 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8674 if (!SIGN_EXT_P(env->CP0_EPC))
8675 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8676 if (!SIGN_EXT_P(env->CP0_LLAddr))
8677 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
8679 #endif
8681 void cpu_dump_state (CPUState *env, FILE *f,
8682 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8683 int flags)
8685 int i;
8687 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",
8688 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8689 env->hflags, env->btarget, env->bcond);
8690 for (i = 0; i < 32; i++) {
8691 if ((i & 3) == 0)
8692 cpu_fprintf(f, "GPR%02d:", i);
8693 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8694 if ((i & 3) == 3)
8695 cpu_fprintf(f, "\n");
8698 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8699 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8700 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8701 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
8702 if (env->hflags & MIPS_HFLAG_FPU)
8703 fpu_dump_state(env, f, cpu_fprintf, flags);
8704 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8705 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8706 #endif
8709 static void mips_tcg_init(void)
8711 static int inited;
8713 /* Initialize various static tables. */
8714 if (inited)
8715 return;
8717 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
8718 bcond = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8719 offsetof(CPUState, bcond), "bcond");
8720 btarget = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8721 offsetof(CPUState, btarget), "btarget");
8722 current_fpu = tcg_global_mem_new(TCG_TYPE_PTR,
8723 TCG_AREG0,
8724 offsetof(CPUState, fpu),
8725 "current_fpu");
8727 /* register helpers */
8728 #undef DEF_HELPER
8729 #define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
8730 #include "helper.h"
8732 inited = 1;
8735 #include "translate_init.c"
8737 CPUMIPSState *cpu_mips_init (const char *cpu_model)
8739 CPUMIPSState *env;
8740 const mips_def_t *def;
8742 def = cpu_mips_find_by_name(cpu_model);
8743 if (!def)
8744 return NULL;
8745 env = qemu_mallocz(sizeof(CPUMIPSState));
8746 if (!env)
8747 return NULL;
8748 env->cpu_model = def;
8750 cpu_exec_init(env);
8751 env->cpu_model_str = cpu_model;
8752 mips_tcg_init();
8753 cpu_reset(env);
8754 return env;
8757 void cpu_reset (CPUMIPSState *env)
8759 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8761 tlb_flush(env, 1);
8763 /* Minimal init */
8764 #if defined(CONFIG_USER_ONLY)
8765 env->user_mode_only = 1;
8766 #endif
8767 if (env->user_mode_only) {
8768 env->hflags = MIPS_HFLAG_UM;
8769 } else {
8770 if (env->hflags & MIPS_HFLAG_BMASK) {
8771 /* If the exception was raised from a delay slot,
8772 come back to the jump. */
8773 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8774 } else {
8775 env->CP0_ErrorEPC = env->active_tc.PC;
8777 env->active_tc.PC = (int32_t)0xBFC00000;
8778 env->CP0_Wired = 0;
8779 /* SMP not implemented */
8780 env->CP0_EBase = 0x80000000;
8781 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8782 /* vectored interrupts not implemented, timer on int 7,
8783 no performance counters. */
8784 env->CP0_IntCtl = 0xe0000000;
8786 int i;
8788 for (i = 0; i < 7; i++) {
8789 env->CP0_WatchLo[i] = 0;
8790 env->CP0_WatchHi[i] = 0x80000000;
8792 env->CP0_WatchLo[7] = 0;
8793 env->CP0_WatchHi[7] = 0;
8795 /* Count register increments in debug mode, EJTAG version 1 */
8796 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8797 env->hflags = MIPS_HFLAG_CP0;
8799 env->exception_index = EXCP_NONE;
8800 cpu_mips_register(env, env->cpu_model);
8803 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8804 unsigned long searched_pc, int pc_pos, void *puc)
8806 env->active_tc.PC = gen_opc_pc[pc_pos];
8807 env->hflags &= ~MIPS_HFLAG_BMASK;
8808 env->hflags |= gen_opc_hflags[pc_pos];