Increase size of virtio_net rings
[qemu-kvm/fedora.git] / target-mips / translate.c
blob06a5f350b11327d39a8cd2c220fd461b23882330
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 /* Routine used to access memory */
523 int mem_idx;
524 uint32_t hflags, saved_hflags;
525 int bstate;
526 target_ulong btarget;
527 } DisasContext;
529 enum {
530 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
531 * exception condition */
532 BS_STOP = 1, /* We want to stop translation for any reason */
533 BS_BRANCH = 2, /* We reached a branch condition */
534 BS_EXCP = 3, /* We reached an exception condition */
537 static const char *regnames[] =
538 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
539 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
540 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
541 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
543 static const char *fregnames[] =
544 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
545 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
546 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
547 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
549 #ifdef MIPS_DEBUG_DISAS
550 #define MIPS_DEBUG(fmt, args...) \
551 do { \
552 if (loglevel & CPU_LOG_TB_IN_ASM) { \
553 fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n", \
554 ctx->pc, ctx->opcode , ##args); \
556 } while (0)
557 #else
558 #define MIPS_DEBUG(fmt, args...) do { } while(0)
559 #endif
561 #define MIPS_INVAL(op) \
562 do { \
563 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
564 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
565 } while (0)
567 /* General purpose registers moves. */
568 static inline void gen_load_gpr (TCGv t, int reg)
570 if (reg == 0)
571 tcg_gen_movi_tl(t, 0);
572 else
573 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.gpr) +
574 sizeof(target_ulong) * reg);
577 static inline void gen_store_gpr (TCGv t, int reg)
579 if (reg != 0)
580 tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.gpr) +
581 sizeof(target_ulong) * reg);
584 /* Moves to/from HI and LO registers. */
585 static inline void gen_load_LO (TCGv t, int reg)
587 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.LO) +
588 sizeof(target_ulong) * reg);
591 static inline void gen_store_LO (TCGv t, int reg)
593 tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.LO) +
594 sizeof(target_ulong) * reg);
597 static inline void gen_load_HI (TCGv t, int reg)
599 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.HI) +
600 sizeof(target_ulong) * reg);
603 static inline void gen_store_HI (TCGv t, int reg)
605 tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.HI) +
606 sizeof(target_ulong) * reg);
609 /* Moves to/from shadow registers. */
610 static inline void gen_load_srsgpr (int from, int to)
612 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
614 if (from == 0)
615 tcg_gen_movi_tl(r_tmp1, 0);
616 else {
617 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
619 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
620 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
621 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
622 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
623 tcg_gen_add_i32(r_tmp2, cpu_env, r_tmp2);
625 tcg_gen_ld_tl(r_tmp1, r_tmp2, sizeof(target_ulong) * from);
626 tcg_temp_free(r_tmp2);
628 gen_store_gpr(r_tmp1, to);
629 tcg_temp_free(r_tmp1);
632 static inline void gen_store_srsgpr (int from, int to)
634 if (to != 0) {
635 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
636 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
638 gen_load_gpr(r_tmp1, from);
639 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
640 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
641 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
642 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
643 tcg_gen_add_i32(r_tmp2, cpu_env, r_tmp2);
645 tcg_gen_st_tl(r_tmp1, r_tmp2, sizeof(target_ulong) * to);
646 tcg_temp_free(r_tmp1);
647 tcg_temp_free(r_tmp2);
651 /* Floating point register moves. */
652 static inline void gen_load_fpr32 (TCGv t, int reg)
654 tcg_gen_ld_i32(t, current_fpu, 8 * reg + 4 * FP_ENDIAN_IDX);
657 static inline void gen_store_fpr32 (TCGv t, int reg)
659 tcg_gen_st_i32(t, current_fpu, 8 * reg + 4 * FP_ENDIAN_IDX);
662 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv t, int reg)
664 if (ctx->hflags & MIPS_HFLAG_F64) {
665 tcg_gen_ld_i64(t, current_fpu, 8 * reg);
666 } else {
667 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
668 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
670 tcg_gen_ld_i32(r_tmp1, current_fpu, 8 * (reg | 1) + 4 * FP_ENDIAN_IDX);
671 tcg_gen_extu_i32_i64(t, r_tmp1);
672 tcg_gen_shli_i64(t, t, 32);
673 tcg_gen_ld_i32(r_tmp1, current_fpu, 8 * (reg & ~1) + 4 * FP_ENDIAN_IDX);
674 tcg_gen_extu_i32_i64(r_tmp2, r_tmp1);
675 tcg_gen_or_i64(t, t, r_tmp2);
676 tcg_temp_free(r_tmp1);
677 tcg_temp_free(r_tmp2);
681 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv t, int reg)
683 if (ctx->hflags & MIPS_HFLAG_F64) {
684 tcg_gen_st_i64(t, current_fpu, 8 * reg);
685 } else {
686 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
688 tcg_gen_trunc_i64_i32(r_tmp, t);
689 tcg_gen_st_i32(r_tmp, current_fpu, 8 * (reg & ~1) + 4 * FP_ENDIAN_IDX);
690 tcg_gen_shri_i64(t, t, 32);
691 tcg_gen_trunc_i64_i32(r_tmp, t);
692 tcg_gen_st_i32(r_tmp, current_fpu, 8 * (reg | 1) + 4 * FP_ENDIAN_IDX);
693 tcg_temp_free(r_tmp);
697 static inline void gen_load_fpr32h (TCGv t, int reg)
699 tcg_gen_ld_i32(t, current_fpu, 8 * reg + 4 * !FP_ENDIAN_IDX);
702 static inline void gen_store_fpr32h (TCGv t, int reg)
704 tcg_gen_st_i32(t, current_fpu, 8 * reg + 4 * !FP_ENDIAN_IDX);
707 static inline void get_fp_cond (TCGv t)
709 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
710 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
712 tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
713 tcg_gen_shri_i32(r_tmp2, r_tmp1, 24);
714 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xfe);
715 tcg_gen_shri_i32(r_tmp1, r_tmp1, 23);
716 tcg_gen_andi_i32(r_tmp1, r_tmp1, 0x1);
717 tcg_gen_or_i32(t, r_tmp1, r_tmp2);
718 tcg_temp_free(r_tmp1);
719 tcg_temp_free(r_tmp2);
722 typedef void (fcmp_fun32)(uint32_t, uint32_t, int);
723 typedef void (fcmp_fun64)(uint64_t, uint64_t, int);
725 #define FOP_CONDS(fcmp_fun, type, arg0, arg1, fmt) \
726 static fcmp_fun * fcmp ## type ## _ ## fmt ## _table[16] = { \
727 do_cmp ## type ## _ ## fmt ## _f, \
728 do_cmp ## type ## _ ## fmt ## _un, \
729 do_cmp ## type ## _ ## fmt ## _eq, \
730 do_cmp ## type ## _ ## fmt ## _ueq, \
731 do_cmp ## type ## _ ## fmt ## _olt, \
732 do_cmp ## type ## _ ## fmt ## _ult, \
733 do_cmp ## type ## _ ## fmt ## _ole, \
734 do_cmp ## type ## _ ## fmt ## _ule, \
735 do_cmp ## type ## _ ## fmt ## _sf, \
736 do_cmp ## type ## _ ## fmt ## _ngle, \
737 do_cmp ## type ## _ ## fmt ## _seq, \
738 do_cmp ## type ## _ ## fmt ## _ngl, \
739 do_cmp ## type ## _ ## fmt ## _lt, \
740 do_cmp ## type ## _ ## fmt ## _nge, \
741 do_cmp ## type ## _ ## fmt ## _le, \
742 do_cmp ## type ## _ ## fmt ## _ngt, \
743 }; \
744 static inline void gen_cmp ## type ## _ ## fmt(int n, arg0 a, arg1 b, int cc) \
746 tcg_gen_helper_0_2i(fcmp ## type ## _ ## fmt ## _table[n], a, b, cc); \
749 FOP_CONDS(fcmp_fun64, , uint64_t, uint64_t, d)
750 FOP_CONDS(fcmp_fun64, abs, uint64_t, uint64_t, d)
751 FOP_CONDS(fcmp_fun32, , uint32_t, uint32_t, s)
752 FOP_CONDS(fcmp_fun32, abs, uint32_t, uint32_t, s)
753 FOP_CONDS(fcmp_fun64, , uint64_t, uint64_t, ps)
754 FOP_CONDS(fcmp_fun64, abs, uint64_t, uint64_t, ps)
755 #undef FOP_CONDS
757 /* Tests */
758 #define OP_COND(name, cond) \
759 static inline void glue(gen_op_, name) (TCGv t0, TCGv t1) \
761 int l1 = gen_new_label(); \
762 int l2 = gen_new_label(); \
764 tcg_gen_brcond_tl(cond, t0, t1, l1); \
765 tcg_gen_movi_tl(t0, 0); \
766 tcg_gen_br(l2); \
767 gen_set_label(l1); \
768 tcg_gen_movi_tl(t0, 1); \
769 gen_set_label(l2); \
771 OP_COND(eq, TCG_COND_EQ);
772 OP_COND(ne, TCG_COND_NE);
773 OP_COND(ge, TCG_COND_GE);
774 OP_COND(geu, TCG_COND_GEU);
775 OP_COND(lt, TCG_COND_LT);
776 OP_COND(ltu, TCG_COND_LTU);
777 #undef OP_COND
779 #define OP_CONDI(name, cond) \
780 static inline void glue(gen_op_, name) (TCGv t, target_ulong val) \
782 int l1 = gen_new_label(); \
783 int l2 = gen_new_label(); \
785 tcg_gen_brcondi_tl(cond, t, val, l1); \
786 tcg_gen_movi_tl(t, 0); \
787 tcg_gen_br(l2); \
788 gen_set_label(l1); \
789 tcg_gen_movi_tl(t, 1); \
790 gen_set_label(l2); \
792 OP_CONDI(lti, TCG_COND_LT);
793 OP_CONDI(ltiu, TCG_COND_LTU);
794 #undef OP_CONDI
796 #define OP_CONDZ(name, cond) \
797 static inline void glue(gen_op_, name) (TCGv t) \
799 int l1 = gen_new_label(); \
800 int l2 = gen_new_label(); \
802 tcg_gen_brcondi_tl(cond, t, 0, l1); \
803 tcg_gen_movi_tl(t, 0); \
804 tcg_gen_br(l2); \
805 gen_set_label(l1); \
806 tcg_gen_movi_tl(t, 1); \
807 gen_set_label(l2); \
809 OP_CONDZ(gez, TCG_COND_GE);
810 OP_CONDZ(gtz, TCG_COND_GT);
811 OP_CONDZ(lez, TCG_COND_LE);
812 OP_CONDZ(ltz, TCG_COND_LT);
813 #undef OP_CONDZ
815 static inline void gen_save_pc(target_ulong pc)
817 TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);
819 tcg_gen_movi_tl(r_tmp, pc);
820 tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, active_tc.PC));
821 tcg_temp_free(r_tmp);
824 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
826 #if defined MIPS_DEBUG_DISAS
827 if (loglevel & CPU_LOG_TB_IN_ASM) {
828 fprintf(logfile, "hflags %08x saved %08x\n",
829 ctx->hflags, ctx->saved_hflags);
831 #endif
832 if (do_save_pc && ctx->pc != ctx->saved_pc) {
833 gen_save_pc(ctx->pc);
834 ctx->saved_pc = ctx->pc;
836 if (ctx->hflags != ctx->saved_hflags) {
837 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
839 tcg_gen_movi_i32(r_tmp, ctx->hflags);
840 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
841 tcg_temp_free(r_tmp);
842 ctx->saved_hflags = ctx->hflags;
843 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
844 case MIPS_HFLAG_BR:
845 break;
846 case MIPS_HFLAG_BC:
847 case MIPS_HFLAG_BL:
848 case MIPS_HFLAG_B:
849 tcg_gen_movi_tl(btarget, ctx->btarget);
850 break;
855 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
857 ctx->saved_hflags = ctx->hflags;
858 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
859 case MIPS_HFLAG_BR:
860 break;
861 case MIPS_HFLAG_BC:
862 case MIPS_HFLAG_BL:
863 case MIPS_HFLAG_B:
864 ctx->btarget = env->btarget;
865 break;
869 static inline void
870 generate_exception_err (DisasContext *ctx, int excp, int err)
872 save_cpu_state(ctx, 1);
873 tcg_gen_helper_0_ii(do_raise_exception_err, excp, err);
874 tcg_gen_helper_0_0(do_interrupt_restart);
875 tcg_gen_exit_tb(0);
878 static inline void
879 generate_exception (DisasContext *ctx, int excp)
881 save_cpu_state(ctx, 1);
882 tcg_gen_helper_0_i(do_raise_exception, excp);
883 tcg_gen_helper_0_0(do_interrupt_restart);
884 tcg_gen_exit_tb(0);
887 /* Addresses computation */
888 static inline void gen_op_addr_add (TCGv t0, TCGv t1)
890 tcg_gen_add_tl(t0, t0, t1);
892 #if defined(TARGET_MIPS64)
893 /* For compatibility with 32-bit code, data reference in user mode
894 with Status_UX = 0 should be casted to 32-bit and sign extended.
895 See the MIPS64 PRA manual, section 4.10. */
897 int l1 = gen_new_label();
898 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_I32);
900 tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
901 tcg_gen_andi_i32(r_tmp, r_tmp, MIPS_HFLAG_KSU);
902 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp, MIPS_HFLAG_UM, l1);
903 tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_Status));
904 tcg_gen_andi_i32(r_tmp, r_tmp, (1 << CP0St_UX));
905 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp, 0, l1);
906 tcg_temp_free(r_tmp);
907 tcg_gen_ext32s_i64(t0, t0);
908 gen_set_label(l1);
910 #endif
913 static inline void check_cp0_enabled(DisasContext *ctx)
915 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
916 generate_exception_err(ctx, EXCP_CpU, 1);
919 static inline void check_cp1_enabled(DisasContext *ctx)
921 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
922 generate_exception_err(ctx, EXCP_CpU, 1);
925 /* Verify that the processor is running with COP1X instructions enabled.
926 This is associated with the nabla symbol in the MIPS32 and MIPS64
927 opcode tables. */
929 static inline void check_cop1x(DisasContext *ctx)
931 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
932 generate_exception(ctx, EXCP_RI);
935 /* Verify that the processor is running with 64-bit floating-point
936 operations enabled. */
938 static inline void check_cp1_64bitmode(DisasContext *ctx)
940 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
941 generate_exception(ctx, EXCP_RI);
945 * Verify if floating point register is valid; an operation is not defined
946 * if bit 0 of any register specification is set and the FR bit in the
947 * Status register equals zero, since the register numbers specify an
948 * even-odd pair of adjacent coprocessor general registers. When the FR bit
949 * in the Status register equals one, both even and odd register numbers
950 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
952 * Multiple 64 bit wide registers can be checked by calling
953 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
955 static inline void check_cp1_registers(DisasContext *ctx, int regs)
957 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
958 generate_exception(ctx, EXCP_RI);
961 /* This code generates a "reserved instruction" exception if the
962 CPU does not support the instruction set corresponding to flags. */
963 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
965 if (unlikely(!(env->insn_flags & flags)))
966 generate_exception(ctx, EXCP_RI);
969 /* This code generates a "reserved instruction" exception if 64-bit
970 instructions are not enabled. */
971 static inline void check_mips_64(DisasContext *ctx)
973 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
974 generate_exception(ctx, EXCP_RI);
977 /* load/store instructions. */
978 #define OP_LD(insn,fname) \
979 static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx) \
981 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
983 OP_LD(lb,ld8s);
984 OP_LD(lbu,ld8u);
985 OP_LD(lh,ld16s);
986 OP_LD(lhu,ld16u);
987 OP_LD(lw,ld32s);
988 #if defined(TARGET_MIPS64)
989 OP_LD(lwu,ld32u);
990 OP_LD(ld,ld64);
991 #endif
992 #undef OP_LD
994 #define OP_ST(insn,fname) \
995 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
997 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
999 OP_ST(sb,st8);
1000 OP_ST(sh,st16);
1001 OP_ST(sw,st32);
1002 #if defined(TARGET_MIPS64)
1003 OP_ST(sd,st64);
1004 #endif
1005 #undef OP_ST
1007 #define OP_LD_ATOMIC(insn,fname) \
1008 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
1010 tcg_gen_mov_tl(t1, t0); \
1011 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
1012 tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
1014 OP_LD_ATOMIC(ll,ld32s);
1015 #if defined(TARGET_MIPS64)
1016 OP_LD_ATOMIC(lld,ld64);
1017 #endif
1018 #undef OP_LD_ATOMIC
1020 #define OP_ST_ATOMIC(insn,fname,almask) \
1021 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
1023 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL); \
1024 int l1 = gen_new_label(); \
1025 int l2 = gen_new_label(); \
1026 int l3 = gen_new_label(); \
1028 tcg_gen_andi_tl(r_tmp, t0, almask); \
1029 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1); \
1030 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
1031 generate_exception(ctx, EXCP_AdES); \
1032 gen_set_label(l1); \
1033 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
1034 tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2); \
1035 tcg_temp_free(r_tmp); \
1036 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
1037 tcg_gen_movi_tl(t0, 1); \
1038 tcg_gen_br(l3); \
1039 gen_set_label(l2); \
1040 tcg_gen_movi_tl(t0, 0); \
1041 gen_set_label(l3); \
1043 OP_ST_ATOMIC(sc,st32,0x3);
1044 #if defined(TARGET_MIPS64)
1045 OP_ST_ATOMIC(scd,st64,0x7);
1046 #endif
1047 #undef OP_ST_ATOMIC
1049 /* Load and store */
1050 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1051 int base, int16_t offset)
1053 const char *opn = "ldst";
1054 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1055 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1057 if (base == 0) {
1058 tcg_gen_movi_tl(t0, offset);
1059 } else if (offset == 0) {
1060 gen_load_gpr(t0, base);
1061 } else {
1062 gen_load_gpr(t0, base);
1063 tcg_gen_movi_tl(t1, offset);
1064 gen_op_addr_add(t0, t1);
1066 /* Don't do NOP if destination is zero: we must perform the actual
1067 memory access. */
1068 switch (opc) {
1069 #if defined(TARGET_MIPS64)
1070 case OPC_LWU:
1071 op_ldst_lwu(t0, ctx);
1072 gen_store_gpr(t0, rt);
1073 opn = "lwu";
1074 break;
1075 case OPC_LD:
1076 op_ldst_ld(t0, ctx);
1077 gen_store_gpr(t0, rt);
1078 opn = "ld";
1079 break;
1080 case OPC_LLD:
1081 op_ldst_lld(t0, t1, ctx);
1082 gen_store_gpr(t0, rt);
1083 opn = "lld";
1084 break;
1085 case OPC_SD:
1086 gen_load_gpr(t1, rt);
1087 op_ldst_sd(t0, t1, ctx);
1088 opn = "sd";
1089 break;
1090 case OPC_SCD:
1091 save_cpu_state(ctx, 1);
1092 gen_load_gpr(t1, rt);
1093 op_ldst_scd(t0, t1, ctx);
1094 gen_store_gpr(t0, rt);
1095 opn = "scd";
1096 break;
1097 case OPC_LDL:
1098 save_cpu_state(ctx, 1);
1099 gen_load_gpr(t1, rt);
1100 tcg_gen_helper_1_2i(do_ldl, t1, t0, t1, ctx->mem_idx);
1101 gen_store_gpr(t1, rt);
1102 opn = "ldl";
1103 break;
1104 case OPC_SDL:
1105 save_cpu_state(ctx, 1);
1106 gen_load_gpr(t1, rt);
1107 tcg_gen_helper_0_2i(do_sdl, t0, t1, ctx->mem_idx);
1108 opn = "sdl";
1109 break;
1110 case OPC_LDR:
1111 save_cpu_state(ctx, 1);
1112 gen_load_gpr(t1, rt);
1113 tcg_gen_helper_1_2i(do_ldr, t1, t0, t1, ctx->mem_idx);
1114 gen_store_gpr(t1, rt);
1115 opn = "ldr";
1116 break;
1117 case OPC_SDR:
1118 save_cpu_state(ctx, 1);
1119 gen_load_gpr(t1, rt);
1120 tcg_gen_helper_0_2i(do_sdr, t0, t1, ctx->mem_idx);
1121 opn = "sdr";
1122 break;
1123 #endif
1124 case OPC_LW:
1125 op_ldst_lw(t0, ctx);
1126 gen_store_gpr(t0, rt);
1127 opn = "lw";
1128 break;
1129 case OPC_SW:
1130 gen_load_gpr(t1, rt);
1131 op_ldst_sw(t0, t1, ctx);
1132 opn = "sw";
1133 break;
1134 case OPC_LH:
1135 op_ldst_lh(t0, ctx);
1136 gen_store_gpr(t0, rt);
1137 opn = "lh";
1138 break;
1139 case OPC_SH:
1140 gen_load_gpr(t1, rt);
1141 op_ldst_sh(t0, t1, ctx);
1142 opn = "sh";
1143 break;
1144 case OPC_LHU:
1145 op_ldst_lhu(t0, ctx);
1146 gen_store_gpr(t0, rt);
1147 opn = "lhu";
1148 break;
1149 case OPC_LB:
1150 op_ldst_lb(t0, ctx);
1151 gen_store_gpr(t0, rt);
1152 opn = "lb";
1153 break;
1154 case OPC_SB:
1155 gen_load_gpr(t1, rt);
1156 op_ldst_sb(t0, t1, ctx);
1157 opn = "sb";
1158 break;
1159 case OPC_LBU:
1160 op_ldst_lbu(t0, ctx);
1161 gen_store_gpr(t0, rt);
1162 opn = "lbu";
1163 break;
1164 case OPC_LWL:
1165 save_cpu_state(ctx, 1);
1166 gen_load_gpr(t1, rt);
1167 tcg_gen_helper_1_2i(do_lwl, t1, t0, t1, ctx->mem_idx);
1168 gen_store_gpr(t1, rt);
1169 opn = "lwl";
1170 break;
1171 case OPC_SWL:
1172 save_cpu_state(ctx, 1);
1173 gen_load_gpr(t1, rt);
1174 tcg_gen_helper_0_2i(do_swl, t0, t1, ctx->mem_idx);
1175 opn = "swr";
1176 break;
1177 case OPC_LWR:
1178 save_cpu_state(ctx, 1);
1179 gen_load_gpr(t1, rt);
1180 tcg_gen_helper_1_2i(do_lwr, t1, t0, t1, ctx->mem_idx);
1181 gen_store_gpr(t1, rt);
1182 opn = "lwr";
1183 break;
1184 case OPC_SWR:
1185 save_cpu_state(ctx, 1);
1186 gen_load_gpr(t1, rt);
1187 tcg_gen_helper_0_2i(do_swr, t0, t1, ctx->mem_idx);
1188 opn = "swr";
1189 break;
1190 case OPC_LL:
1191 op_ldst_ll(t0, t1, ctx);
1192 gen_store_gpr(t0, rt);
1193 opn = "ll";
1194 break;
1195 case OPC_SC:
1196 save_cpu_state(ctx, 1);
1197 gen_load_gpr(t1, rt);
1198 op_ldst_sc(t0, t1, ctx);
1199 gen_store_gpr(t0, rt);
1200 opn = "sc";
1201 break;
1202 default:
1203 MIPS_INVAL(opn);
1204 generate_exception(ctx, EXCP_RI);
1205 goto out;
1207 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1208 out:
1209 tcg_temp_free(t0);
1210 tcg_temp_free(t1);
1213 /* Load and store */
1214 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1215 int base, int16_t offset)
1217 const char *opn = "flt_ldst";
1218 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1220 if (base == 0) {
1221 tcg_gen_movi_tl(t0, offset);
1222 } else if (offset == 0) {
1223 gen_load_gpr(t0, base);
1224 } else {
1225 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1227 gen_load_gpr(t0, base);
1228 tcg_gen_movi_tl(t1, offset);
1229 gen_op_addr_add(t0, t1);
1230 tcg_temp_free(t1);
1232 /* Don't do NOP if destination is zero: we must perform the actual
1233 memory access. */
1234 switch (opc) {
1235 case OPC_LWC1:
1237 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
1239 tcg_gen_qemu_ld32s(fp0, t0, ctx->mem_idx);
1240 gen_store_fpr32(fp0, ft);
1241 tcg_temp_free(fp0);
1243 opn = "lwc1";
1244 break;
1245 case OPC_SWC1:
1247 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
1249 gen_load_fpr32(fp0, ft);
1250 tcg_gen_qemu_st32(fp0, t0, ctx->mem_idx);
1251 tcg_temp_free(fp0);
1253 opn = "swc1";
1254 break;
1255 case OPC_LDC1:
1257 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
1259 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1260 gen_store_fpr64(ctx, fp0, ft);
1261 tcg_temp_free(fp0);
1263 opn = "ldc1";
1264 break;
1265 case OPC_SDC1:
1267 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
1269 gen_load_fpr64(ctx, fp0, ft);
1270 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1271 tcg_temp_free(fp0);
1273 opn = "sdc1";
1274 break;
1275 default:
1276 MIPS_INVAL(opn);
1277 generate_exception(ctx, EXCP_RI);
1278 goto out;
1280 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1281 out:
1282 tcg_temp_free(t0);
1285 /* Arithmetic with immediate operand */
1286 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1287 int rt, int rs, int16_t imm)
1289 target_ulong uimm;
1290 const char *opn = "imm arith";
1291 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1293 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1294 /* If no destination, treat it as a NOP.
1295 For addi, we must generate the overflow exception when needed. */
1296 MIPS_DEBUG("NOP");
1297 goto out;
1299 uimm = (uint16_t)imm;
1300 switch (opc) {
1301 case OPC_ADDI:
1302 case OPC_ADDIU:
1303 #if defined(TARGET_MIPS64)
1304 case OPC_DADDI:
1305 case OPC_DADDIU:
1306 #endif
1307 case OPC_SLTI:
1308 case OPC_SLTIU:
1309 uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1310 /* Fall through. */
1311 case OPC_ANDI:
1312 case OPC_ORI:
1313 case OPC_XORI:
1314 gen_load_gpr(t0, rs);
1315 break;
1316 case OPC_LUI:
1317 tcg_gen_movi_tl(t0, imm << 16);
1318 break;
1319 case OPC_SLL:
1320 case OPC_SRA:
1321 case OPC_SRL:
1322 #if defined(TARGET_MIPS64)
1323 case OPC_DSLL:
1324 case OPC_DSRA:
1325 case OPC_DSRL:
1326 case OPC_DSLL32:
1327 case OPC_DSRA32:
1328 case OPC_DSRL32:
1329 #endif
1330 uimm &= 0x1f;
1331 gen_load_gpr(t0, rs);
1332 break;
1334 switch (opc) {
1335 case OPC_ADDI:
1337 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1338 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1339 int l1 = gen_new_label();
1341 save_cpu_state(ctx, 1);
1342 tcg_gen_ext32s_tl(r_tmp1, t0);
1343 tcg_gen_addi_tl(t0, r_tmp1, uimm);
1345 tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
1346 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1347 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1348 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1349 tcg_temp_free(r_tmp2);
1350 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1351 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1352 tcg_temp_free(r_tmp1);
1353 /* operands of same sign, result different sign */
1354 generate_exception(ctx, EXCP_OVERFLOW);
1355 gen_set_label(l1);
1357 tcg_gen_ext32s_tl(t0, t0);
1359 opn = "addi";
1360 break;
1361 case OPC_ADDIU:
1362 tcg_gen_ext32s_tl(t0, t0);
1363 tcg_gen_addi_tl(t0, t0, uimm);
1364 tcg_gen_ext32s_tl(t0, t0);
1365 opn = "addiu";
1366 break;
1367 #if defined(TARGET_MIPS64)
1368 case OPC_DADDI:
1370 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1371 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1372 int l1 = gen_new_label();
1374 save_cpu_state(ctx, 1);
1375 tcg_gen_mov_tl(r_tmp1, t0);
1376 tcg_gen_addi_tl(t0, t0, uimm);
1378 tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
1379 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1380 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1381 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1382 tcg_temp_free(r_tmp2);
1383 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1384 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1385 tcg_temp_free(r_tmp1);
1386 /* operands of same sign, result different sign */
1387 generate_exception(ctx, EXCP_OVERFLOW);
1388 gen_set_label(l1);
1390 opn = "daddi";
1391 break;
1392 case OPC_DADDIU:
1393 tcg_gen_addi_tl(t0, t0, uimm);
1394 opn = "daddiu";
1395 break;
1396 #endif
1397 case OPC_SLTI:
1398 gen_op_lti(t0, uimm);
1399 opn = "slti";
1400 break;
1401 case OPC_SLTIU:
1402 gen_op_ltiu(t0, uimm);
1403 opn = "sltiu";
1404 break;
1405 case OPC_ANDI:
1406 tcg_gen_andi_tl(t0, t0, uimm);
1407 opn = "andi";
1408 break;
1409 case OPC_ORI:
1410 tcg_gen_ori_tl(t0, t0, uimm);
1411 opn = "ori";
1412 break;
1413 case OPC_XORI:
1414 tcg_gen_xori_tl(t0, t0, uimm);
1415 opn = "xori";
1416 break;
1417 case OPC_LUI:
1418 opn = "lui";
1419 break;
1420 case OPC_SLL:
1421 tcg_gen_ext32u_tl(t0, t0);
1422 tcg_gen_shli_tl(t0, t0, uimm);
1423 tcg_gen_ext32s_tl(t0, t0);
1424 opn = "sll";
1425 break;
1426 case OPC_SRA:
1427 tcg_gen_ext32s_tl(t0, t0);
1428 tcg_gen_sari_tl(t0, t0, uimm);
1429 tcg_gen_ext32s_tl(t0, t0);
1430 opn = "sra";
1431 break;
1432 case OPC_SRL:
1433 switch ((ctx->opcode >> 21) & 0x1f) {
1434 case 0:
1435 tcg_gen_ext32u_tl(t0, t0);
1436 tcg_gen_shri_tl(t0, t0, uimm);
1437 tcg_gen_ext32s_tl(t0, t0);
1438 opn = "srl";
1439 break;
1440 case 1:
1441 /* rotr is decoded as srl on non-R2 CPUs */
1442 if (env->insn_flags & ISA_MIPS32R2) {
1443 if (uimm != 0) {
1444 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1445 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1447 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1448 tcg_gen_movi_i32(r_tmp2, 0x20);
1449 tcg_gen_subi_i32(r_tmp2, r_tmp2, uimm);
1450 tcg_gen_shl_i32(r_tmp2, r_tmp1, r_tmp2);
1451 tcg_gen_shri_i32(r_tmp1, r_tmp1, uimm);
1452 tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp2);
1453 tcg_gen_ext_i32_tl(t0, r_tmp1);
1454 tcg_temp_free(r_tmp1);
1455 tcg_temp_free(r_tmp2);
1457 opn = "rotr";
1458 } else {
1459 tcg_gen_ext32u_tl(t0, t0);
1460 tcg_gen_shri_tl(t0, t0, uimm);
1461 tcg_gen_ext32s_tl(t0, t0);
1462 opn = "srl";
1464 break;
1465 default:
1466 MIPS_INVAL("invalid srl flag");
1467 generate_exception(ctx, EXCP_RI);
1468 break;
1470 break;
1471 #if defined(TARGET_MIPS64)
1472 case OPC_DSLL:
1473 tcg_gen_shli_tl(t0, t0, uimm);
1474 opn = "dsll";
1475 break;
1476 case OPC_DSRA:
1477 tcg_gen_sari_tl(t0, t0, uimm);
1478 opn = "dsra";
1479 break;
1480 case OPC_DSRL:
1481 switch ((ctx->opcode >> 21) & 0x1f) {
1482 case 0:
1483 tcg_gen_shri_tl(t0, t0, uimm);
1484 opn = "dsrl";
1485 break;
1486 case 1:
1487 /* drotr is decoded as dsrl on non-R2 CPUs */
1488 if (env->insn_flags & ISA_MIPS32R2) {
1489 if (uimm != 0) {
1490 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1492 tcg_gen_movi_tl(r_tmp1, 0x40);
1493 tcg_gen_subi_tl(r_tmp1, r_tmp1, uimm);
1494 tcg_gen_shl_tl(r_tmp1, t0, r_tmp1);
1495 tcg_gen_shri_tl(t0, t0, uimm);
1496 tcg_gen_or_tl(t0, t0, r_tmp1);
1497 tcg_temp_free(r_tmp1);
1499 opn = "drotr";
1500 } else {
1501 tcg_gen_shri_tl(t0, t0, uimm);
1502 opn = "dsrl";
1504 break;
1505 default:
1506 MIPS_INVAL("invalid dsrl flag");
1507 generate_exception(ctx, EXCP_RI);
1508 break;
1510 break;
1511 case OPC_DSLL32:
1512 tcg_gen_shli_tl(t0, t0, uimm + 32);
1513 opn = "dsll32";
1514 break;
1515 case OPC_DSRA32:
1516 tcg_gen_sari_tl(t0, t0, uimm + 32);
1517 opn = "dsra32";
1518 break;
1519 case OPC_DSRL32:
1520 switch ((ctx->opcode >> 21) & 0x1f) {
1521 case 0:
1522 tcg_gen_shri_tl(t0, t0, uimm + 32);
1523 opn = "dsrl32";
1524 break;
1525 case 1:
1526 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1527 if (env->insn_flags & ISA_MIPS32R2) {
1528 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1529 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1531 tcg_gen_movi_tl(r_tmp1, 0x40);
1532 tcg_gen_movi_tl(r_tmp2, 32);
1533 tcg_gen_addi_tl(r_tmp2, r_tmp2, uimm);
1534 tcg_gen_sub_tl(r_tmp1, r_tmp1, r_tmp2);
1535 tcg_gen_shl_tl(r_tmp1, t0, r_tmp1);
1536 tcg_gen_shr_tl(t0, t0, r_tmp2);
1537 tcg_gen_or_tl(t0, t0, r_tmp1);
1538 tcg_temp_free(r_tmp1);
1539 tcg_temp_free(r_tmp2);
1540 opn = "drotr32";
1541 } else {
1542 tcg_gen_shri_tl(t0, t0, uimm + 32);
1543 opn = "dsrl32";
1545 break;
1546 default:
1547 MIPS_INVAL("invalid dsrl32 flag");
1548 generate_exception(ctx, EXCP_RI);
1549 break;
1551 break;
1552 #endif
1553 default:
1554 MIPS_INVAL(opn);
1555 generate_exception(ctx, EXCP_RI);
1556 goto out;
1558 gen_store_gpr(t0, rt);
1559 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1560 out:
1561 tcg_temp_free(t0);
1564 /* Arithmetic */
1565 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1566 int rd, int rs, int rt)
1568 const char *opn = "arith";
1569 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1570 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1572 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1573 && opc != OPC_DADD && opc != OPC_DSUB) {
1574 /* If no destination, treat it as a NOP.
1575 For add & sub, we must generate the overflow exception when needed. */
1576 MIPS_DEBUG("NOP");
1577 goto out;
1579 gen_load_gpr(t0, rs);
1580 /* Specialcase the conventional move operation. */
1581 if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1582 || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1583 gen_store_gpr(t0, rd);
1584 goto out;
1586 gen_load_gpr(t1, rt);
1587 switch (opc) {
1588 case OPC_ADD:
1590 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1591 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1592 int l1 = gen_new_label();
1594 save_cpu_state(ctx, 1);
1595 tcg_gen_ext32s_tl(r_tmp1, t0);
1596 tcg_gen_ext32s_tl(r_tmp2, t1);
1597 tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
1599 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1600 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1601 tcg_gen_xor_tl(r_tmp2, t0, t1);
1602 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1603 tcg_temp_free(r_tmp2);
1604 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1605 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1606 tcg_temp_free(r_tmp1);
1607 /* operands of same sign, result different sign */
1608 generate_exception(ctx, EXCP_OVERFLOW);
1609 gen_set_label(l1);
1611 tcg_gen_ext32s_tl(t0, t0);
1613 opn = "add";
1614 break;
1615 case OPC_ADDU:
1616 tcg_gen_ext32s_tl(t0, t0);
1617 tcg_gen_ext32s_tl(t1, t1);
1618 tcg_gen_add_tl(t0, t0, t1);
1619 tcg_gen_ext32s_tl(t0, t0);
1620 opn = "addu";
1621 break;
1622 case OPC_SUB:
1624 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1625 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1626 int l1 = gen_new_label();
1628 save_cpu_state(ctx, 1);
1629 tcg_gen_ext32s_tl(r_tmp1, t0);
1630 tcg_gen_ext32s_tl(r_tmp2, t1);
1631 tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
1633 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1634 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1635 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1636 tcg_temp_free(r_tmp2);
1637 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1638 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1639 tcg_temp_free(r_tmp1);
1640 /* operands of different sign, first operand and result different sign */
1641 generate_exception(ctx, EXCP_OVERFLOW);
1642 gen_set_label(l1);
1644 tcg_gen_ext32s_tl(t0, t0);
1646 opn = "sub";
1647 break;
1648 case OPC_SUBU:
1649 tcg_gen_ext32s_tl(t0, t0);
1650 tcg_gen_ext32s_tl(t1, t1);
1651 tcg_gen_sub_tl(t0, t0, t1);
1652 tcg_gen_ext32s_tl(t0, t0);
1653 opn = "subu";
1654 break;
1655 #if defined(TARGET_MIPS64)
1656 case OPC_DADD:
1658 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1659 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1660 int l1 = gen_new_label();
1662 save_cpu_state(ctx, 1);
1663 tcg_gen_mov_tl(r_tmp1, t0);
1664 tcg_gen_add_tl(t0, t0, t1);
1666 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1667 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1668 tcg_gen_xor_tl(r_tmp2, t0, t1);
1669 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1670 tcg_temp_free(r_tmp2);
1671 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1672 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1673 tcg_temp_free(r_tmp1);
1674 /* operands of same sign, result different sign */
1675 generate_exception(ctx, EXCP_OVERFLOW);
1676 gen_set_label(l1);
1678 opn = "dadd";
1679 break;
1680 case OPC_DADDU:
1681 tcg_gen_add_tl(t0, t0, t1);
1682 opn = "daddu";
1683 break;
1684 case OPC_DSUB:
1686 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1687 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1688 int l1 = gen_new_label();
1690 save_cpu_state(ctx, 1);
1691 tcg_gen_mov_tl(r_tmp1, t0);
1692 tcg_gen_sub_tl(t0, t0, t1);
1694 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1695 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1696 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1697 tcg_temp_free(r_tmp2);
1698 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1699 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1700 tcg_temp_free(r_tmp1);
1701 /* operands of different sign, first operand and result different sign */
1702 generate_exception(ctx, EXCP_OVERFLOW);
1703 gen_set_label(l1);
1705 opn = "dsub";
1706 break;
1707 case OPC_DSUBU:
1708 tcg_gen_sub_tl(t0, t0, t1);
1709 opn = "dsubu";
1710 break;
1711 #endif
1712 case OPC_SLT:
1713 gen_op_lt(t0, t1);
1714 opn = "slt";
1715 break;
1716 case OPC_SLTU:
1717 gen_op_ltu(t0, t1);
1718 opn = "sltu";
1719 break;
1720 case OPC_AND:
1721 tcg_gen_and_tl(t0, t0, t1);
1722 opn = "and";
1723 break;
1724 case OPC_NOR:
1725 tcg_gen_or_tl(t0, t0, t1);
1726 tcg_gen_not_tl(t0, t0);
1727 opn = "nor";
1728 break;
1729 case OPC_OR:
1730 tcg_gen_or_tl(t0, t0, t1);
1731 opn = "or";
1732 break;
1733 case OPC_XOR:
1734 tcg_gen_xor_tl(t0, t0, t1);
1735 opn = "xor";
1736 break;
1737 case OPC_MUL:
1738 tcg_gen_ext32s_tl(t0, t0);
1739 tcg_gen_ext32s_tl(t1, t1);
1740 tcg_gen_mul_tl(t0, t0, t1);
1741 tcg_gen_ext32s_tl(t0, t0);
1742 opn = "mul";
1743 break;
1744 case OPC_MOVN:
1746 int l1 = gen_new_label();
1748 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1749 gen_store_gpr(t0, rd);
1750 gen_set_label(l1);
1752 opn = "movn";
1753 goto print;
1754 case OPC_MOVZ:
1756 int l1 = gen_new_label();
1758 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
1759 gen_store_gpr(t0, rd);
1760 gen_set_label(l1);
1762 opn = "movz";
1763 goto print;
1764 case OPC_SLLV:
1765 tcg_gen_ext32u_tl(t0, t0);
1766 tcg_gen_ext32u_tl(t1, t1);
1767 tcg_gen_andi_tl(t0, t0, 0x1f);
1768 tcg_gen_shl_tl(t0, t1, t0);
1769 tcg_gen_ext32s_tl(t0, t0);
1770 opn = "sllv";
1771 break;
1772 case OPC_SRAV:
1773 tcg_gen_ext32s_tl(t1, t1);
1774 tcg_gen_andi_tl(t0, t0, 0x1f);
1775 tcg_gen_sar_tl(t0, t1, t0);
1776 tcg_gen_ext32s_tl(t0, t0);
1777 opn = "srav";
1778 break;
1779 case OPC_SRLV:
1780 switch ((ctx->opcode >> 6) & 0x1f) {
1781 case 0:
1782 tcg_gen_ext32u_tl(t1, t1);
1783 tcg_gen_andi_tl(t0, t0, 0x1f);
1784 tcg_gen_shr_tl(t0, t1, t0);
1785 tcg_gen_ext32s_tl(t0, t0);
1786 opn = "srlv";
1787 break;
1788 case 1:
1789 /* rotrv is decoded as srlv on non-R2 CPUs */
1790 if (env->insn_flags & ISA_MIPS32R2) {
1791 int l1 = gen_new_label();
1792 int l2 = gen_new_label();
1794 tcg_gen_andi_tl(t0, t0, 0x1f);
1795 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1797 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1798 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1799 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
1801 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1802 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1803 tcg_gen_movi_i32(r_tmp3, 0x20);
1804 tcg_gen_sub_i32(r_tmp3, r_tmp3, r_tmp1);
1805 tcg_gen_shl_i32(r_tmp3, r_tmp2, r_tmp3);
1806 tcg_gen_shr_i32(r_tmp1, r_tmp2, r_tmp1);
1807 tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp3);
1808 tcg_gen_ext_i32_tl(t0, r_tmp1);
1809 tcg_temp_free(r_tmp1);
1810 tcg_temp_free(r_tmp2);
1811 tcg_temp_free(r_tmp3);
1812 tcg_gen_br(l2);
1814 gen_set_label(l1);
1815 tcg_gen_mov_tl(t0, t1);
1816 gen_set_label(l2);
1817 opn = "rotrv";
1818 } else {
1819 tcg_gen_ext32u_tl(t1, t1);
1820 tcg_gen_andi_tl(t0, t0, 0x1f);
1821 tcg_gen_shr_tl(t0, t1, t0);
1822 tcg_gen_ext32s_tl(t0, t0);
1823 opn = "srlv";
1825 break;
1826 default:
1827 MIPS_INVAL("invalid srlv flag");
1828 generate_exception(ctx, EXCP_RI);
1829 break;
1831 break;
1832 #if defined(TARGET_MIPS64)
1833 case OPC_DSLLV:
1834 tcg_gen_andi_tl(t0, t0, 0x3f);
1835 tcg_gen_shl_tl(t0, t1, t0);
1836 opn = "dsllv";
1837 break;
1838 case OPC_DSRAV:
1839 tcg_gen_andi_tl(t0, t0, 0x3f);
1840 tcg_gen_sar_tl(t0, t1, t0);
1841 opn = "dsrav";
1842 break;
1843 case OPC_DSRLV:
1844 switch ((ctx->opcode >> 6) & 0x1f) {
1845 case 0:
1846 tcg_gen_andi_tl(t0, t0, 0x3f);
1847 tcg_gen_shr_tl(t0, t1, t0);
1848 opn = "dsrlv";
1849 break;
1850 case 1:
1851 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1852 if (env->insn_flags & ISA_MIPS32R2) {
1853 int l1 = gen_new_label();
1854 int l2 = gen_new_label();
1856 tcg_gen_andi_tl(t0, t0, 0x3f);
1857 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1859 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1861 tcg_gen_movi_tl(r_tmp1, 0x40);
1862 tcg_gen_sub_tl(r_tmp1, r_tmp1, t0);
1863 tcg_gen_shl_tl(r_tmp1, t1, r_tmp1);
1864 tcg_gen_shr_tl(t0, t1, t0);
1865 tcg_gen_or_tl(t0, t0, r_tmp1);
1866 tcg_temp_free(r_tmp1);
1867 tcg_gen_br(l2);
1869 gen_set_label(l1);
1870 tcg_gen_mov_tl(t0, t1);
1871 gen_set_label(l2);
1872 opn = "drotrv";
1873 } else {
1874 tcg_gen_andi_tl(t0, t0, 0x3f);
1875 tcg_gen_shr_tl(t0, t1, t0);
1876 opn = "dsrlv";
1878 break;
1879 default:
1880 MIPS_INVAL("invalid dsrlv flag");
1881 generate_exception(ctx, EXCP_RI);
1882 break;
1884 break;
1885 #endif
1886 default:
1887 MIPS_INVAL(opn);
1888 generate_exception(ctx, EXCP_RI);
1889 goto out;
1891 gen_store_gpr(t0, rd);
1892 print:
1893 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1894 out:
1895 tcg_temp_free(t0);
1896 tcg_temp_free(t1);
1899 /* Arithmetic on HI/LO registers */
1900 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1902 const char *opn = "hilo";
1903 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1905 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1906 /* Treat as NOP. */
1907 MIPS_DEBUG("NOP");
1908 goto out;
1910 switch (opc) {
1911 case OPC_MFHI:
1912 gen_load_HI(t0, 0);
1913 gen_store_gpr(t0, reg);
1914 opn = "mfhi";
1915 break;
1916 case OPC_MFLO:
1917 gen_load_LO(t0, 0);
1918 gen_store_gpr(t0, reg);
1919 opn = "mflo";
1920 break;
1921 case OPC_MTHI:
1922 gen_load_gpr(t0, reg);
1923 gen_store_HI(t0, 0);
1924 opn = "mthi";
1925 break;
1926 case OPC_MTLO:
1927 gen_load_gpr(t0, reg);
1928 gen_store_LO(t0, 0);
1929 opn = "mtlo";
1930 break;
1931 default:
1932 MIPS_INVAL(opn);
1933 generate_exception(ctx, EXCP_RI);
1934 goto out;
1936 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1937 out:
1938 tcg_temp_free(t0);
1941 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1942 int rs, int rt)
1944 const char *opn = "mul/div";
1945 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1946 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1948 gen_load_gpr(t0, rs);
1949 gen_load_gpr(t1, rt);
1950 switch (opc) {
1951 case OPC_DIV:
1953 int l1 = gen_new_label();
1955 tcg_gen_ext32s_tl(t0, t0);
1956 tcg_gen_ext32s_tl(t1, t1);
1957 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1959 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
1960 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
1961 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
1963 tcg_gen_ext_tl_i64(r_tmp1, t0);
1964 tcg_gen_ext_tl_i64(r_tmp2, t1);
1965 tcg_gen_div_i64(r_tmp3, r_tmp1, r_tmp2);
1966 tcg_gen_rem_i64(r_tmp2, r_tmp1, r_tmp2);
1967 tcg_gen_trunc_i64_tl(t0, r_tmp3);
1968 tcg_gen_trunc_i64_tl(t1, r_tmp2);
1969 tcg_temp_free(r_tmp1);
1970 tcg_temp_free(r_tmp2);
1971 tcg_temp_free(r_tmp3);
1972 tcg_gen_ext32s_tl(t0, t0);
1973 tcg_gen_ext32s_tl(t1, t1);
1974 gen_store_LO(t0, 0);
1975 gen_store_HI(t1, 0);
1977 gen_set_label(l1);
1979 opn = "div";
1980 break;
1981 case OPC_DIVU:
1983 int l1 = gen_new_label();
1985 tcg_gen_ext32s_tl(t1, t1);
1986 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1988 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1989 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1990 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
1992 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1993 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1994 tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2);
1995 tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2);
1996 tcg_gen_ext_i32_tl(t0, r_tmp3);
1997 tcg_gen_ext_i32_tl(t1, r_tmp1);
1998 tcg_temp_free(r_tmp1);
1999 tcg_temp_free(r_tmp2);
2000 tcg_temp_free(r_tmp3);
2001 gen_store_LO(t0, 0);
2002 gen_store_HI(t1, 0);
2004 gen_set_label(l1);
2006 opn = "divu";
2007 break;
2008 case OPC_MULT:
2010 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2011 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2013 tcg_gen_ext32s_tl(t0, t0);
2014 tcg_gen_ext32s_tl(t1, t1);
2015 tcg_gen_ext_tl_i64(r_tmp1, t0);
2016 tcg_gen_ext_tl_i64(r_tmp2, t1);
2017 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2018 tcg_temp_free(r_tmp2);
2019 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2020 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2021 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2022 tcg_temp_free(r_tmp1);
2023 tcg_gen_ext32s_tl(t0, t0);
2024 tcg_gen_ext32s_tl(t1, t1);
2025 gen_store_LO(t0, 0);
2026 gen_store_HI(t1, 0);
2028 opn = "mult";
2029 break;
2030 case OPC_MULTU:
2032 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2033 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2035 tcg_gen_ext32u_tl(t0, t0);
2036 tcg_gen_ext32u_tl(t1, t1);
2037 tcg_gen_extu_tl_i64(r_tmp1, t0);
2038 tcg_gen_extu_tl_i64(r_tmp2, t1);
2039 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2040 tcg_temp_free(r_tmp2);
2041 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2042 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2043 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2044 tcg_temp_free(r_tmp1);
2045 tcg_gen_ext32s_tl(t0, t0);
2046 tcg_gen_ext32s_tl(t1, t1);
2047 gen_store_LO(t0, 0);
2048 gen_store_HI(t1, 0);
2050 opn = "multu";
2051 break;
2052 #if defined(TARGET_MIPS64)
2053 case OPC_DDIV:
2055 int l1 = gen_new_label();
2057 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2059 int l2 = gen_new_label();
2061 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2062 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2064 tcg_gen_movi_tl(t1, 0);
2065 gen_store_LO(t0, 0);
2066 gen_store_HI(t1, 0);
2067 tcg_gen_br(l1);
2069 gen_set_label(l2);
2071 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2072 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2074 tcg_gen_div_i64(r_tmp1, t0, t1);
2075 tcg_gen_rem_i64(r_tmp2, t0, t1);
2076 gen_store_LO(r_tmp1, 0);
2077 gen_store_HI(r_tmp2, 0);
2078 tcg_temp_free(r_tmp1);
2079 tcg_temp_free(r_tmp2);
2082 gen_set_label(l1);
2084 opn = "ddiv";
2085 break;
2086 case OPC_DDIVU:
2088 int l1 = gen_new_label();
2090 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2092 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2093 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2095 tcg_gen_divu_i64(r_tmp1, t0, t1);
2096 tcg_gen_remu_i64(r_tmp2, t0, t1);
2097 tcg_temp_free(r_tmp1);
2098 tcg_temp_free(r_tmp2);
2099 gen_store_LO(r_tmp1, 0);
2100 gen_store_HI(r_tmp2, 0);
2102 gen_set_label(l1);
2104 opn = "ddivu";
2105 break;
2106 case OPC_DMULT:
2107 tcg_gen_helper_0_2(do_dmult, t0, t1);
2108 opn = "dmult";
2109 break;
2110 case OPC_DMULTU:
2111 tcg_gen_helper_0_2(do_dmultu, t0, t1);
2112 opn = "dmultu";
2113 break;
2114 #endif
2115 case OPC_MADD:
2117 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2118 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2119 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
2121 tcg_gen_ext32s_tl(t0, t0);
2122 tcg_gen_ext32s_tl(t1, t1);
2123 tcg_gen_ext_tl_i64(r_tmp1, t0);
2124 tcg_gen_ext_tl_i64(r_tmp2, t1);
2125 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2126 gen_load_LO(t0, 0);
2127 gen_load_HI(t1, 0);
2128 tcg_gen_extu_tl_i64(r_tmp2, t0);
2129 tcg_gen_extu_tl_i64(r_tmp3, t1);
2130 tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
2131 tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
2132 tcg_temp_free(r_tmp3);
2133 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
2134 tcg_temp_free(r_tmp2);
2135 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2136 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2137 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2138 tcg_temp_free(r_tmp1);
2139 tcg_gen_ext32s_tl(t0, t0);
2140 tcg_gen_ext32s_tl(t1, t1);
2141 gen_store_LO(t0, 0);
2142 gen_store_HI(t1, 0);
2144 opn = "madd";
2145 break;
2146 case OPC_MADDU:
2148 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2149 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2150 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
2152 tcg_gen_ext32u_tl(t0, t0);
2153 tcg_gen_ext32u_tl(t1, t1);
2154 tcg_gen_extu_tl_i64(r_tmp1, t0);
2155 tcg_gen_extu_tl_i64(r_tmp2, t1);
2156 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2157 gen_load_LO(t0, 0);
2158 gen_load_HI(t1, 0);
2159 tcg_gen_extu_tl_i64(r_tmp2, t0);
2160 tcg_gen_extu_tl_i64(r_tmp3, t1);
2161 tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
2162 tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
2163 tcg_temp_free(r_tmp3);
2164 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
2165 tcg_temp_free(r_tmp2);
2166 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2167 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2168 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2169 tcg_temp_free(r_tmp1);
2170 tcg_gen_ext32s_tl(t0, t0);
2171 tcg_gen_ext32s_tl(t1, t1);
2172 gen_store_LO(t0, 0);
2173 gen_store_HI(t1, 0);
2175 opn = "maddu";
2176 break;
2177 case OPC_MSUB:
2179 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2180 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2181 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
2183 tcg_gen_ext32s_tl(t0, t0);
2184 tcg_gen_ext32s_tl(t1, t1);
2185 tcg_gen_ext_tl_i64(r_tmp1, t0);
2186 tcg_gen_ext_tl_i64(r_tmp2, t1);
2187 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2188 gen_load_LO(t0, 0);
2189 gen_load_HI(t1, 0);
2190 tcg_gen_extu_tl_i64(r_tmp2, t0);
2191 tcg_gen_extu_tl_i64(r_tmp3, t1);
2192 tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
2193 tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
2194 tcg_temp_free(r_tmp3);
2195 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
2196 tcg_temp_free(r_tmp2);
2197 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2198 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2199 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2200 tcg_temp_free(r_tmp1);
2201 tcg_gen_ext32s_tl(t0, t0);
2202 tcg_gen_ext32s_tl(t1, t1);
2203 gen_store_LO(t0, 0);
2204 gen_store_HI(t1, 0);
2206 opn = "msub";
2207 break;
2208 case OPC_MSUBU:
2210 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2211 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2212 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
2214 tcg_gen_ext32u_tl(t0, t0);
2215 tcg_gen_ext32u_tl(t1, t1);
2216 tcg_gen_extu_tl_i64(r_tmp1, t0);
2217 tcg_gen_extu_tl_i64(r_tmp2, t1);
2218 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2219 gen_load_LO(t0, 0);
2220 gen_load_HI(t1, 0);
2221 tcg_gen_extu_tl_i64(r_tmp2, t0);
2222 tcg_gen_extu_tl_i64(r_tmp3, t1);
2223 tcg_gen_shli_i64(r_tmp3, r_tmp3, 32);
2224 tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3);
2225 tcg_temp_free(r_tmp3);
2226 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
2227 tcg_temp_free(r_tmp2);
2228 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2229 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2230 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2231 tcg_temp_free(r_tmp1);
2232 tcg_gen_ext32s_tl(t0, t0);
2233 tcg_gen_ext32s_tl(t1, t1);
2234 gen_store_LO(t0, 0);
2235 gen_store_HI(t1, 0);
2237 opn = "msubu";
2238 break;
2239 default:
2240 MIPS_INVAL(opn);
2241 generate_exception(ctx, EXCP_RI);
2242 goto out;
2244 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2245 out:
2246 tcg_temp_free(t0);
2247 tcg_temp_free(t1);
2250 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2251 int rd, int rs, int rt)
2253 const char *opn = "mul vr54xx";
2254 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2255 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2257 gen_load_gpr(t0, rs);
2258 gen_load_gpr(t1, rt);
2260 switch (opc) {
2261 case OPC_VR54XX_MULS:
2262 tcg_gen_helper_1_2(do_muls, t0, t0, t1);
2263 opn = "muls";
2264 break;
2265 case OPC_VR54XX_MULSU:
2266 tcg_gen_helper_1_2(do_mulsu, t0, t0, t1);
2267 opn = "mulsu";
2268 break;
2269 case OPC_VR54XX_MACC:
2270 tcg_gen_helper_1_2(do_macc, t0, t0, t1);
2271 opn = "macc";
2272 break;
2273 case OPC_VR54XX_MACCU:
2274 tcg_gen_helper_1_2(do_maccu, t0, t0, t1);
2275 opn = "maccu";
2276 break;
2277 case OPC_VR54XX_MSAC:
2278 tcg_gen_helper_1_2(do_msac, t0, t0, t1);
2279 opn = "msac";
2280 break;
2281 case OPC_VR54XX_MSACU:
2282 tcg_gen_helper_1_2(do_msacu, t0, t0, t1);
2283 opn = "msacu";
2284 break;
2285 case OPC_VR54XX_MULHI:
2286 tcg_gen_helper_1_2(do_mulhi, t0, t0, t1);
2287 opn = "mulhi";
2288 break;
2289 case OPC_VR54XX_MULHIU:
2290 tcg_gen_helper_1_2(do_mulhiu, t0, t0, t1);
2291 opn = "mulhiu";
2292 break;
2293 case OPC_VR54XX_MULSHI:
2294 tcg_gen_helper_1_2(do_mulshi, t0, t0, t1);
2295 opn = "mulshi";
2296 break;
2297 case OPC_VR54XX_MULSHIU:
2298 tcg_gen_helper_1_2(do_mulshiu, t0, t0, t1);
2299 opn = "mulshiu";
2300 break;
2301 case OPC_VR54XX_MACCHI:
2302 tcg_gen_helper_1_2(do_macchi, t0, t0, t1);
2303 opn = "macchi";
2304 break;
2305 case OPC_VR54XX_MACCHIU:
2306 tcg_gen_helper_1_2(do_macchiu, t0, t0, t1);
2307 opn = "macchiu";
2308 break;
2309 case OPC_VR54XX_MSACHI:
2310 tcg_gen_helper_1_2(do_msachi, t0, t0, t1);
2311 opn = "msachi";
2312 break;
2313 case OPC_VR54XX_MSACHIU:
2314 tcg_gen_helper_1_2(do_msachiu, t0, t0, t1);
2315 opn = "msachiu";
2316 break;
2317 default:
2318 MIPS_INVAL("mul vr54xx");
2319 generate_exception(ctx, EXCP_RI);
2320 goto out;
2322 gen_store_gpr(t0, rd);
2323 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2325 out:
2326 tcg_temp_free(t0);
2327 tcg_temp_free(t1);
2330 static void gen_cl (DisasContext *ctx, uint32_t opc,
2331 int rd, int rs)
2333 const char *opn = "CLx";
2334 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2336 if (rd == 0) {
2337 /* Treat as NOP. */
2338 MIPS_DEBUG("NOP");
2339 goto out;
2341 gen_load_gpr(t0, rs);
2342 switch (opc) {
2343 case OPC_CLO:
2344 tcg_gen_helper_1_1(do_clo, t0, t0);
2345 opn = "clo";
2346 break;
2347 case OPC_CLZ:
2348 tcg_gen_helper_1_1(do_clz, t0, t0);
2349 opn = "clz";
2350 break;
2351 #if defined(TARGET_MIPS64)
2352 case OPC_DCLO:
2353 tcg_gen_helper_1_1(do_dclo, t0, t0);
2354 opn = "dclo";
2355 break;
2356 case OPC_DCLZ:
2357 tcg_gen_helper_1_1(do_dclz, t0, t0);
2358 opn = "dclz";
2359 break;
2360 #endif
2361 default:
2362 MIPS_INVAL(opn);
2363 generate_exception(ctx, EXCP_RI);
2364 goto out;
2366 gen_store_gpr(t0, rd);
2367 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2369 out:
2370 tcg_temp_free(t0);
2373 /* Traps */
2374 static void gen_trap (DisasContext *ctx, uint32_t opc,
2375 int rs, int rt, int16_t imm)
2377 int cond;
2378 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2379 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2381 cond = 0;
2382 /* Load needed operands */
2383 switch (opc) {
2384 case OPC_TEQ:
2385 case OPC_TGE:
2386 case OPC_TGEU:
2387 case OPC_TLT:
2388 case OPC_TLTU:
2389 case OPC_TNE:
2390 /* Compare two registers */
2391 if (rs != rt) {
2392 gen_load_gpr(t0, rs);
2393 gen_load_gpr(t1, rt);
2394 cond = 1;
2396 break;
2397 case OPC_TEQI:
2398 case OPC_TGEI:
2399 case OPC_TGEIU:
2400 case OPC_TLTI:
2401 case OPC_TLTIU:
2402 case OPC_TNEI:
2403 /* Compare register to immediate */
2404 if (rs != 0 || imm != 0) {
2405 gen_load_gpr(t0, rs);
2406 tcg_gen_movi_tl(t1, (int32_t)imm);
2407 cond = 1;
2409 break;
2411 if (cond == 0) {
2412 switch (opc) {
2413 case OPC_TEQ: /* rs == rs */
2414 case OPC_TEQI: /* r0 == 0 */
2415 case OPC_TGE: /* rs >= rs */
2416 case OPC_TGEI: /* r0 >= 0 */
2417 case OPC_TGEU: /* rs >= rs unsigned */
2418 case OPC_TGEIU: /* r0 >= 0 unsigned */
2419 /* Always trap */
2420 tcg_gen_movi_tl(t0, 1);
2421 break;
2422 case OPC_TLT: /* rs < rs */
2423 case OPC_TLTI: /* r0 < 0 */
2424 case OPC_TLTU: /* rs < rs unsigned */
2425 case OPC_TLTIU: /* r0 < 0 unsigned */
2426 case OPC_TNE: /* rs != rs */
2427 case OPC_TNEI: /* r0 != 0 */
2428 /* Never trap: treat as NOP. */
2429 goto out;
2430 default:
2431 MIPS_INVAL("trap");
2432 generate_exception(ctx, EXCP_RI);
2433 goto out;
2435 } else {
2436 switch (opc) {
2437 case OPC_TEQ:
2438 case OPC_TEQI:
2439 gen_op_eq(t0, t1);
2440 break;
2441 case OPC_TGE:
2442 case OPC_TGEI:
2443 gen_op_ge(t0, t1);
2444 break;
2445 case OPC_TGEU:
2446 case OPC_TGEIU:
2447 gen_op_geu(t0, t1);
2448 break;
2449 case OPC_TLT:
2450 case OPC_TLTI:
2451 gen_op_lt(t0, t1);
2452 break;
2453 case OPC_TLTU:
2454 case OPC_TLTIU:
2455 gen_op_ltu(t0, t1);
2456 break;
2457 case OPC_TNE:
2458 case OPC_TNEI:
2459 gen_op_ne(t0, t1);
2460 break;
2461 default:
2462 MIPS_INVAL("trap");
2463 generate_exception(ctx, EXCP_RI);
2464 goto out;
2467 save_cpu_state(ctx, 1);
2469 int l1 = gen_new_label();
2471 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2472 tcg_gen_helper_0_i(do_raise_exception, EXCP_TRAP);
2473 gen_set_label(l1);
2475 ctx->bstate = BS_STOP;
2476 out:
2477 tcg_temp_free(t0);
2478 tcg_temp_free(t1);
2481 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2483 TranslationBlock *tb;
2484 tb = ctx->tb;
2485 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2486 tcg_gen_goto_tb(n);
2487 gen_save_pc(dest);
2488 tcg_gen_exit_tb((long)tb + n);
2489 } else {
2490 gen_save_pc(dest);
2491 tcg_gen_exit_tb(0);
2495 /* Branches (before delay slot) */
2496 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2497 int rs, int rt, int32_t offset)
2499 target_ulong btgt = -1;
2500 int blink = 0;
2501 int bcond = 0;
2502 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2503 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2505 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2506 #ifdef MIPS_DEBUG_DISAS
2507 if (loglevel & CPU_LOG_TB_IN_ASM) {
2508 fprintf(logfile,
2509 "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
2510 ctx->pc);
2512 #endif
2513 generate_exception(ctx, EXCP_RI);
2514 goto out;
2517 /* Load needed operands */
2518 switch (opc) {
2519 case OPC_BEQ:
2520 case OPC_BEQL:
2521 case OPC_BNE:
2522 case OPC_BNEL:
2523 /* Compare two registers */
2524 if (rs != rt) {
2525 gen_load_gpr(t0, rs);
2526 gen_load_gpr(t1, rt);
2527 bcond = 1;
2529 btgt = ctx->pc + 4 + offset;
2530 break;
2531 case OPC_BGEZ:
2532 case OPC_BGEZAL:
2533 case OPC_BGEZALL:
2534 case OPC_BGEZL:
2535 case OPC_BGTZ:
2536 case OPC_BGTZL:
2537 case OPC_BLEZ:
2538 case OPC_BLEZL:
2539 case OPC_BLTZ:
2540 case OPC_BLTZAL:
2541 case OPC_BLTZALL:
2542 case OPC_BLTZL:
2543 /* Compare to zero */
2544 if (rs != 0) {
2545 gen_load_gpr(t0, rs);
2546 bcond = 1;
2548 btgt = ctx->pc + 4 + offset;
2549 break;
2550 case OPC_J:
2551 case OPC_JAL:
2552 /* Jump to immediate */
2553 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2554 break;
2555 case OPC_JR:
2556 case OPC_JALR:
2557 /* Jump to register */
2558 if (offset != 0 && offset != 16) {
2559 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2560 others are reserved. */
2561 MIPS_INVAL("jump hint");
2562 generate_exception(ctx, EXCP_RI);
2563 goto out;
2565 gen_load_gpr(btarget, rs);
2566 break;
2567 default:
2568 MIPS_INVAL("branch/jump");
2569 generate_exception(ctx, EXCP_RI);
2570 goto out;
2572 if (bcond == 0) {
2573 /* No condition to be computed */
2574 switch (opc) {
2575 case OPC_BEQ: /* rx == rx */
2576 case OPC_BEQL: /* rx == rx likely */
2577 case OPC_BGEZ: /* 0 >= 0 */
2578 case OPC_BGEZL: /* 0 >= 0 likely */
2579 case OPC_BLEZ: /* 0 <= 0 */
2580 case OPC_BLEZL: /* 0 <= 0 likely */
2581 /* Always take */
2582 ctx->hflags |= MIPS_HFLAG_B;
2583 MIPS_DEBUG("balways");
2584 break;
2585 case OPC_BGEZAL: /* 0 >= 0 */
2586 case OPC_BGEZALL: /* 0 >= 0 likely */
2587 /* Always take and link */
2588 blink = 31;
2589 ctx->hflags |= MIPS_HFLAG_B;
2590 MIPS_DEBUG("balways and link");
2591 break;
2592 case OPC_BNE: /* rx != rx */
2593 case OPC_BGTZ: /* 0 > 0 */
2594 case OPC_BLTZ: /* 0 < 0 */
2595 /* Treat as NOP. */
2596 MIPS_DEBUG("bnever (NOP)");
2597 goto out;
2598 case OPC_BLTZAL: /* 0 < 0 */
2599 tcg_gen_movi_tl(t0, ctx->pc + 8);
2600 gen_store_gpr(t0, 31);
2601 MIPS_DEBUG("bnever and link");
2602 goto out;
2603 case OPC_BLTZALL: /* 0 < 0 likely */
2604 tcg_gen_movi_tl(t0, ctx->pc + 8);
2605 gen_store_gpr(t0, 31);
2606 /* Skip the instruction in the delay slot */
2607 MIPS_DEBUG("bnever, link and skip");
2608 ctx->pc += 4;
2609 goto out;
2610 case OPC_BNEL: /* rx != rx likely */
2611 case OPC_BGTZL: /* 0 > 0 likely */
2612 case OPC_BLTZL: /* 0 < 0 likely */
2613 /* Skip the instruction in the delay slot */
2614 MIPS_DEBUG("bnever and skip");
2615 ctx->pc += 4;
2616 goto out;
2617 case OPC_J:
2618 ctx->hflags |= MIPS_HFLAG_B;
2619 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2620 break;
2621 case OPC_JAL:
2622 blink = 31;
2623 ctx->hflags |= MIPS_HFLAG_B;
2624 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2625 break;
2626 case OPC_JR:
2627 ctx->hflags |= MIPS_HFLAG_BR;
2628 MIPS_DEBUG("jr %s", regnames[rs]);
2629 break;
2630 case OPC_JALR:
2631 blink = rt;
2632 ctx->hflags |= MIPS_HFLAG_BR;
2633 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2634 break;
2635 default:
2636 MIPS_INVAL("branch/jump");
2637 generate_exception(ctx, EXCP_RI);
2638 goto out;
2640 } else {
2641 switch (opc) {
2642 case OPC_BEQ:
2643 gen_op_eq(t0, t1);
2644 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2645 regnames[rs], regnames[rt], btgt);
2646 goto not_likely;
2647 case OPC_BEQL:
2648 gen_op_eq(t0, t1);
2649 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2650 regnames[rs], regnames[rt], btgt);
2651 goto likely;
2652 case OPC_BNE:
2653 gen_op_ne(t0, t1);
2654 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2655 regnames[rs], regnames[rt], btgt);
2656 goto not_likely;
2657 case OPC_BNEL:
2658 gen_op_ne(t0, t1);
2659 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2660 regnames[rs], regnames[rt], btgt);
2661 goto likely;
2662 case OPC_BGEZ:
2663 gen_op_gez(t0);
2664 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2665 goto not_likely;
2666 case OPC_BGEZL:
2667 gen_op_gez(t0);
2668 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2669 goto likely;
2670 case OPC_BGEZAL:
2671 gen_op_gez(t0);
2672 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2673 blink = 31;
2674 goto not_likely;
2675 case OPC_BGEZALL:
2676 gen_op_gez(t0);
2677 blink = 31;
2678 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2679 goto likely;
2680 case OPC_BGTZ:
2681 gen_op_gtz(t0);
2682 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2683 goto not_likely;
2684 case OPC_BGTZL:
2685 gen_op_gtz(t0);
2686 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2687 goto likely;
2688 case OPC_BLEZ:
2689 gen_op_lez(t0);
2690 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2691 goto not_likely;
2692 case OPC_BLEZL:
2693 gen_op_lez(t0);
2694 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2695 goto likely;
2696 case OPC_BLTZ:
2697 gen_op_ltz(t0);
2698 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2699 goto not_likely;
2700 case OPC_BLTZL:
2701 gen_op_ltz(t0);
2702 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2703 goto likely;
2704 case OPC_BLTZAL:
2705 gen_op_ltz(t0);
2706 blink = 31;
2707 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2708 not_likely:
2709 ctx->hflags |= MIPS_HFLAG_BC;
2710 tcg_gen_trunc_tl_i32(bcond, t0);
2711 break;
2712 case OPC_BLTZALL:
2713 gen_op_ltz(t0);
2714 blink = 31;
2715 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2716 likely:
2717 ctx->hflags |= MIPS_HFLAG_BL;
2718 tcg_gen_trunc_tl_i32(bcond, t0);
2719 break;
2720 default:
2721 MIPS_INVAL("conditional branch/jump");
2722 generate_exception(ctx, EXCP_RI);
2723 goto out;
2726 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2727 blink, ctx->hflags, btgt);
2729 ctx->btarget = btgt;
2730 if (blink > 0) {
2731 tcg_gen_movi_tl(t0, ctx->pc + 8);
2732 gen_store_gpr(t0, blink);
2735 out:
2736 tcg_temp_free(t0);
2737 tcg_temp_free(t1);
2740 /* special3 bitfield operations */
2741 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2742 int rs, int lsb, int msb)
2744 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2745 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2747 gen_load_gpr(t1, rs);
2748 switch (opc) {
2749 case OPC_EXT:
2750 if (lsb + msb > 31)
2751 goto fail;
2752 tcg_gen_helper_1_1ii(do_ext, t0, t1, lsb, msb + 1);
2753 break;
2754 #if defined(TARGET_MIPS64)
2755 case OPC_DEXTM:
2756 if (lsb + msb > 63)
2757 goto fail;
2758 tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb, msb + 1 + 32);
2759 break;
2760 case OPC_DEXTU:
2761 if (lsb + msb > 63)
2762 goto fail;
2763 tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb + 32, msb + 1);
2764 break;
2765 case OPC_DEXT:
2766 if (lsb + msb > 63)
2767 goto fail;
2768 tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb, msb + 1);
2769 break;
2770 #endif
2771 case OPC_INS:
2772 if (lsb > msb)
2773 goto fail;
2774 gen_load_gpr(t0, rt);
2775 tcg_gen_helper_1_2ii(do_ins, t0, t0, t1, lsb, msb - lsb + 1);
2776 break;
2777 #if defined(TARGET_MIPS64)
2778 case OPC_DINSM:
2779 if (lsb > msb)
2780 goto fail;
2781 gen_load_gpr(t0, rt);
2782 tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb, msb - lsb + 1 + 32);
2783 break;
2784 case OPC_DINSU:
2785 if (lsb > msb)
2786 goto fail;
2787 gen_load_gpr(t0, rt);
2788 tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb + 32, msb - lsb + 1);
2789 break;
2790 case OPC_DINS:
2791 if (lsb > msb)
2792 goto fail;
2793 gen_load_gpr(t0, rt);
2794 tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb, msb - lsb + 1);
2795 break;
2796 #endif
2797 default:
2798 fail:
2799 MIPS_INVAL("bitops");
2800 generate_exception(ctx, EXCP_RI);
2801 tcg_temp_free(t0);
2802 tcg_temp_free(t1);
2803 return;
2805 gen_store_gpr(t0, rt);
2806 tcg_temp_free(t0);
2807 tcg_temp_free(t1);
2810 #ifndef CONFIG_USER_ONLY
2811 /* CP0 (MMU and control) */
2812 static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
2814 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
2816 tcg_gen_ld_i32(r_tmp, cpu_env, off);
2817 tcg_gen_ext_i32_tl(t, r_tmp);
2818 tcg_temp_free(r_tmp);
2821 static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
2823 tcg_gen_ld_tl(t, cpu_env, off);
2824 tcg_gen_ext32s_tl(t, t);
2827 static inline void gen_mtc0_store32 (TCGv t, target_ulong off)
2829 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
2831 tcg_gen_trunc_tl_i32(r_tmp, t);
2832 tcg_gen_st_i32(r_tmp, cpu_env, off);
2833 tcg_temp_free(r_tmp);
2836 static inline void gen_mtc0_store64 (TCGv t, target_ulong off)
2838 tcg_gen_ext32s_tl(t, t);
2839 tcg_gen_st_tl(t, cpu_env, off);
2842 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
2844 const char *rn = "invalid";
2846 if (sel != 0)
2847 check_insn(env, ctx, ISA_MIPS32);
2849 switch (reg) {
2850 case 0:
2851 switch (sel) {
2852 case 0:
2853 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
2854 rn = "Index";
2855 break;
2856 case 1:
2857 check_insn(env, ctx, ASE_MT);
2858 tcg_gen_helper_1_0(do_mfc0_mvpcontrol, t0);
2859 rn = "MVPControl";
2860 break;
2861 case 2:
2862 check_insn(env, ctx, ASE_MT);
2863 tcg_gen_helper_1_0(do_mfc0_mvpconf0, t0);
2864 rn = "MVPConf0";
2865 break;
2866 case 3:
2867 check_insn(env, ctx, ASE_MT);
2868 tcg_gen_helper_1_0(do_mfc0_mvpconf1, t0);
2869 rn = "MVPConf1";
2870 break;
2871 default:
2872 goto die;
2874 break;
2875 case 1:
2876 switch (sel) {
2877 case 0:
2878 tcg_gen_helper_1_0(do_mfc0_random, t0);
2879 rn = "Random";
2880 break;
2881 case 1:
2882 check_insn(env, ctx, ASE_MT);
2883 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
2884 rn = "VPEControl";
2885 break;
2886 case 2:
2887 check_insn(env, ctx, ASE_MT);
2888 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
2889 rn = "VPEConf0";
2890 break;
2891 case 3:
2892 check_insn(env, ctx, ASE_MT);
2893 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
2894 rn = "VPEConf1";
2895 break;
2896 case 4:
2897 check_insn(env, ctx, ASE_MT);
2898 gen_mfc0_load64(t0, offsetof(CPUState, CP0_YQMask));
2899 rn = "YQMask";
2900 break;
2901 case 5:
2902 check_insn(env, ctx, ASE_MT);
2903 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPESchedule));
2904 rn = "VPESchedule";
2905 break;
2906 case 6:
2907 check_insn(env, ctx, ASE_MT);
2908 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPEScheFBack));
2909 rn = "VPEScheFBack";
2910 break;
2911 case 7:
2912 check_insn(env, ctx, ASE_MT);
2913 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
2914 rn = "VPEOpt";
2915 break;
2916 default:
2917 goto die;
2919 break;
2920 case 2:
2921 switch (sel) {
2922 case 0:
2923 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2924 tcg_gen_ext32s_tl(t0, t0);
2925 rn = "EntryLo0";
2926 break;
2927 case 1:
2928 check_insn(env, ctx, ASE_MT);
2929 tcg_gen_helper_1_0(do_mfc0_tcstatus, t0);
2930 rn = "TCStatus";
2931 break;
2932 case 2:
2933 check_insn(env, ctx, ASE_MT);
2934 tcg_gen_helper_1_0(do_mfc0_tcbind, t0);
2935 rn = "TCBind";
2936 break;
2937 case 3:
2938 check_insn(env, ctx, ASE_MT);
2939 tcg_gen_helper_1_0(do_mfc0_tcrestart, t0);
2940 rn = "TCRestart";
2941 break;
2942 case 4:
2943 check_insn(env, ctx, ASE_MT);
2944 tcg_gen_helper_1_0(do_mfc0_tchalt, t0);
2945 rn = "TCHalt";
2946 break;
2947 case 5:
2948 check_insn(env, ctx, ASE_MT);
2949 tcg_gen_helper_1_0(do_mfc0_tccontext, t0);
2950 rn = "TCContext";
2951 break;
2952 case 6:
2953 check_insn(env, ctx, ASE_MT);
2954 tcg_gen_helper_1_0(do_mfc0_tcschedule, t0);
2955 rn = "TCSchedule";
2956 break;
2957 case 7:
2958 check_insn(env, ctx, ASE_MT);
2959 tcg_gen_helper_1_0(do_mfc0_tcschefback, t0);
2960 rn = "TCScheFBack";
2961 break;
2962 default:
2963 goto die;
2965 break;
2966 case 3:
2967 switch (sel) {
2968 case 0:
2969 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2970 tcg_gen_ext32s_tl(t0, t0);
2971 rn = "EntryLo1";
2972 break;
2973 default:
2974 goto die;
2976 break;
2977 case 4:
2978 switch (sel) {
2979 case 0:
2980 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
2981 tcg_gen_ext32s_tl(t0, t0);
2982 rn = "Context";
2983 break;
2984 case 1:
2985 // tcg_gen_helper_1_0(do_mfc0_contextconfig, t0); /* SmartMIPS ASE */
2986 rn = "ContextConfig";
2987 // break;
2988 default:
2989 goto die;
2991 break;
2992 case 5:
2993 switch (sel) {
2994 case 0:
2995 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
2996 rn = "PageMask";
2997 break;
2998 case 1:
2999 check_insn(env, ctx, ISA_MIPS32R2);
3000 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
3001 rn = "PageGrain";
3002 break;
3003 default:
3004 goto die;
3006 break;
3007 case 6:
3008 switch (sel) {
3009 case 0:
3010 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
3011 rn = "Wired";
3012 break;
3013 case 1:
3014 check_insn(env, ctx, ISA_MIPS32R2);
3015 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
3016 rn = "SRSConf0";
3017 break;
3018 case 2:
3019 check_insn(env, ctx, ISA_MIPS32R2);
3020 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
3021 rn = "SRSConf1";
3022 break;
3023 case 3:
3024 check_insn(env, ctx, ISA_MIPS32R2);
3025 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
3026 rn = "SRSConf2";
3027 break;
3028 case 4:
3029 check_insn(env, ctx, ISA_MIPS32R2);
3030 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
3031 rn = "SRSConf3";
3032 break;
3033 case 5:
3034 check_insn(env, ctx, ISA_MIPS32R2);
3035 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
3036 rn = "SRSConf4";
3037 break;
3038 default:
3039 goto die;
3041 break;
3042 case 7:
3043 switch (sel) {
3044 case 0:
3045 check_insn(env, ctx, ISA_MIPS32R2);
3046 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
3047 rn = "HWREna";
3048 break;
3049 default:
3050 goto die;
3052 break;
3053 case 8:
3054 switch (sel) {
3055 case 0:
3056 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3057 tcg_gen_ext32s_tl(t0, t0);
3058 rn = "BadVAddr";
3059 break;
3060 default:
3061 goto die;
3063 break;
3064 case 9:
3065 switch (sel) {
3066 case 0:
3067 /* Mark as an IO operation because we read the time. */
3068 if (use_icount)
3069 gen_io_start();
3070 tcg_gen_helper_1_0(do_mfc0_count, t0);
3071 if (use_icount) {
3072 gen_io_end();
3073 ctx->bstate = BS_STOP;
3075 rn = "Count";
3076 break;
3077 /* 6,7 are implementation dependent */
3078 default:
3079 goto die;
3081 break;
3082 case 10:
3083 switch (sel) {
3084 case 0:
3085 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
3086 tcg_gen_ext32s_tl(t0, t0);
3087 rn = "EntryHi";
3088 break;
3089 default:
3090 goto die;
3092 break;
3093 case 11:
3094 switch (sel) {
3095 case 0:
3096 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
3097 rn = "Compare";
3098 break;
3099 /* 6,7 are implementation dependent */
3100 default:
3101 goto die;
3103 break;
3104 case 12:
3105 switch (sel) {
3106 case 0:
3107 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
3108 rn = "Status";
3109 break;
3110 case 1:
3111 check_insn(env, ctx, ISA_MIPS32R2);
3112 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
3113 rn = "IntCtl";
3114 break;
3115 case 2:
3116 check_insn(env, ctx, ISA_MIPS32R2);
3117 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
3118 rn = "SRSCtl";
3119 break;
3120 case 3:
3121 check_insn(env, ctx, ISA_MIPS32R2);
3122 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
3123 rn = "SRSMap";
3124 break;
3125 default:
3126 goto die;
3128 break;
3129 case 13:
3130 switch (sel) {
3131 case 0:
3132 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
3133 rn = "Cause";
3134 break;
3135 default:
3136 goto die;
3138 break;
3139 case 14:
3140 switch (sel) {
3141 case 0:
3142 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
3143 tcg_gen_ext32s_tl(t0, t0);
3144 rn = "EPC";
3145 break;
3146 default:
3147 goto die;
3149 break;
3150 case 15:
3151 switch (sel) {
3152 case 0:
3153 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
3154 rn = "PRid";
3155 break;
3156 case 1:
3157 check_insn(env, ctx, ISA_MIPS32R2);
3158 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
3159 rn = "EBase";
3160 break;
3161 default:
3162 goto die;
3164 break;
3165 case 16:
3166 switch (sel) {
3167 case 0:
3168 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
3169 rn = "Config";
3170 break;
3171 case 1:
3172 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
3173 rn = "Config1";
3174 break;
3175 case 2:
3176 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
3177 rn = "Config2";
3178 break;
3179 case 3:
3180 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
3181 rn = "Config3";
3182 break;
3183 /* 4,5 are reserved */
3184 /* 6,7 are implementation dependent */
3185 case 6:
3186 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
3187 rn = "Config6";
3188 break;
3189 case 7:
3190 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
3191 rn = "Config7";
3192 break;
3193 default:
3194 goto die;
3196 break;
3197 case 17:
3198 switch (sel) {
3199 case 0:
3200 tcg_gen_helper_1_0(do_mfc0_lladdr, t0);
3201 rn = "LLAddr";
3202 break;
3203 default:
3204 goto die;
3206 break;
3207 case 18:
3208 switch (sel) {
3209 case 0 ... 7:
3210 tcg_gen_helper_1_i(do_mfc0_watchlo, t0, sel);
3211 rn = "WatchLo";
3212 break;
3213 default:
3214 goto die;
3216 break;
3217 case 19:
3218 switch (sel) {
3219 case 0 ...7:
3220 tcg_gen_helper_1_i(do_mfc0_watchhi, t0, sel);
3221 rn = "WatchHi";
3222 break;
3223 default:
3224 goto die;
3226 break;
3227 case 20:
3228 switch (sel) {
3229 case 0:
3230 #if defined(TARGET_MIPS64)
3231 check_insn(env, ctx, ISA_MIPS3);
3232 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
3233 tcg_gen_ext32s_tl(t0, t0);
3234 rn = "XContext";
3235 break;
3236 #endif
3237 default:
3238 goto die;
3240 break;
3241 case 21:
3242 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3243 switch (sel) {
3244 case 0:
3245 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
3246 rn = "Framemask";
3247 break;
3248 default:
3249 goto die;
3251 break;
3252 case 22:
3253 /* ignored */
3254 rn = "'Diagnostic"; /* implementation dependent */
3255 break;
3256 case 23:
3257 switch (sel) {
3258 case 0:
3259 tcg_gen_helper_1_0(do_mfc0_debug, t0); /* EJTAG support */
3260 rn = "Debug";
3261 break;
3262 case 1:
3263 // tcg_gen_helper_1_0(do_mfc0_tracecontrol, t0); /* PDtrace support */
3264 rn = "TraceControl";
3265 // break;
3266 case 2:
3267 // tcg_gen_helper_1_0(do_mfc0_tracecontrol2, t0); /* PDtrace support */
3268 rn = "TraceControl2";
3269 // break;
3270 case 3:
3271 // tcg_gen_helper_1_0(do_mfc0_usertracedata, t0); /* PDtrace support */
3272 rn = "UserTraceData";
3273 // break;
3274 case 4:
3275 // tcg_gen_helper_1_0(do_mfc0_tracebpc, t0); /* PDtrace support */
3276 rn = "TraceBPC";
3277 // break;
3278 default:
3279 goto die;
3281 break;
3282 case 24:
3283 switch (sel) {
3284 case 0:
3285 /* EJTAG support */
3286 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
3287 tcg_gen_ext32s_tl(t0, t0);
3288 rn = "DEPC";
3289 break;
3290 default:
3291 goto die;
3293 break;
3294 case 25:
3295 switch (sel) {
3296 case 0:
3297 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
3298 rn = "Performance0";
3299 break;
3300 case 1:
3301 // tcg_gen_helper_1_0(do_mfc0_performance1, t0);
3302 rn = "Performance1";
3303 // break;
3304 case 2:
3305 // tcg_gen_helper_1_0(do_mfc0_performance2, t0);
3306 rn = "Performance2";
3307 // break;
3308 case 3:
3309 // tcg_gen_helper_1_0(do_mfc0_performance3, t0);
3310 rn = "Performance3";
3311 // break;
3312 case 4:
3313 // tcg_gen_helper_1_0(do_mfc0_performance4, t0);
3314 rn = "Performance4";
3315 // break;
3316 case 5:
3317 // tcg_gen_helper_1_0(do_mfc0_performance5, t0);
3318 rn = "Performance5";
3319 // break;
3320 case 6:
3321 // tcg_gen_helper_1_0(do_mfc0_performance6, t0);
3322 rn = "Performance6";
3323 // break;
3324 case 7:
3325 // tcg_gen_helper_1_0(do_mfc0_performance7, t0);
3326 rn = "Performance7";
3327 // break;
3328 default:
3329 goto die;
3331 break;
3332 case 26:
3333 rn = "ECC";
3334 break;
3335 case 27:
3336 switch (sel) {
3337 /* ignored */
3338 case 0 ... 3:
3339 rn = "CacheErr";
3340 break;
3341 default:
3342 goto die;
3344 break;
3345 case 28:
3346 switch (sel) {
3347 case 0:
3348 case 2:
3349 case 4:
3350 case 6:
3351 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
3352 rn = "TagLo";
3353 break;
3354 case 1:
3355 case 3:
3356 case 5:
3357 case 7:
3358 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
3359 rn = "DataLo";
3360 break;
3361 default:
3362 goto die;
3364 break;
3365 case 29:
3366 switch (sel) {
3367 case 0:
3368 case 2:
3369 case 4:
3370 case 6:
3371 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
3372 rn = "TagHi";
3373 break;
3374 case 1:
3375 case 3:
3376 case 5:
3377 case 7:
3378 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
3379 rn = "DataHi";
3380 break;
3381 default:
3382 goto die;
3384 break;
3385 case 30:
3386 switch (sel) {
3387 case 0:
3388 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3389 tcg_gen_ext32s_tl(t0, t0);
3390 rn = "ErrorEPC";
3391 break;
3392 default:
3393 goto die;
3395 break;
3396 case 31:
3397 switch (sel) {
3398 case 0:
3399 /* EJTAG support */
3400 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
3401 rn = "DESAVE";
3402 break;
3403 default:
3404 goto die;
3406 break;
3407 default:
3408 goto die;
3410 #if defined MIPS_DEBUG_DISAS
3411 if (loglevel & CPU_LOG_TB_IN_ASM) {
3412 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3413 rn, reg, sel);
3415 #endif
3416 return;
3418 die:
3419 #if defined MIPS_DEBUG_DISAS
3420 if (loglevel & CPU_LOG_TB_IN_ASM) {
3421 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3422 rn, reg, sel);
3424 #endif
3425 generate_exception(ctx, EXCP_RI);
3428 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
3430 const char *rn = "invalid";
3432 if (sel != 0)
3433 check_insn(env, ctx, ISA_MIPS32);
3435 if (use_icount)
3436 gen_io_start();
3438 switch (reg) {
3439 case 0:
3440 switch (sel) {
3441 case 0:
3442 tcg_gen_helper_0_1(do_mtc0_index, t0);
3443 rn = "Index";
3444 break;
3445 case 1:
3446 check_insn(env, ctx, ASE_MT);
3447 tcg_gen_helper_0_1(do_mtc0_mvpcontrol, t0);
3448 rn = "MVPControl";
3449 break;
3450 case 2:
3451 check_insn(env, ctx, ASE_MT);
3452 /* ignored */
3453 rn = "MVPConf0";
3454 break;
3455 case 3:
3456 check_insn(env, ctx, ASE_MT);
3457 /* ignored */
3458 rn = "MVPConf1";
3459 break;
3460 default:
3461 goto die;
3463 break;
3464 case 1:
3465 switch (sel) {
3466 case 0:
3467 /* ignored */
3468 rn = "Random";
3469 break;
3470 case 1:
3471 check_insn(env, ctx, ASE_MT);
3472 tcg_gen_helper_0_1(do_mtc0_vpecontrol, t0);
3473 rn = "VPEControl";
3474 break;
3475 case 2:
3476 check_insn(env, ctx, ASE_MT);
3477 tcg_gen_helper_0_1(do_mtc0_vpeconf0, t0);
3478 rn = "VPEConf0";
3479 break;
3480 case 3:
3481 check_insn(env, ctx, ASE_MT);
3482 tcg_gen_helper_0_1(do_mtc0_vpeconf1, t0);
3483 rn = "VPEConf1";
3484 break;
3485 case 4:
3486 check_insn(env, ctx, ASE_MT);
3487 tcg_gen_helper_0_1(do_mtc0_yqmask, t0);
3488 rn = "YQMask";
3489 break;
3490 case 5:
3491 check_insn(env, ctx, ASE_MT);
3492 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule));
3493 rn = "VPESchedule";
3494 break;
3495 case 6:
3496 check_insn(env, ctx, ASE_MT);
3497 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack));
3498 rn = "VPEScheFBack";
3499 break;
3500 case 7:
3501 check_insn(env, ctx, ASE_MT);
3502 tcg_gen_helper_0_1(do_mtc0_vpeopt, t0);
3503 rn = "VPEOpt";
3504 break;
3505 default:
3506 goto die;
3508 break;
3509 case 2:
3510 switch (sel) {
3511 case 0:
3512 tcg_gen_helper_0_1(do_mtc0_entrylo0, t0);
3513 rn = "EntryLo0";
3514 break;
3515 case 1:
3516 check_insn(env, ctx, ASE_MT);
3517 tcg_gen_helper_0_1(do_mtc0_tcstatus, t0);
3518 rn = "TCStatus";
3519 break;
3520 case 2:
3521 check_insn(env, ctx, ASE_MT);
3522 tcg_gen_helper_0_1(do_mtc0_tcbind, t0);
3523 rn = "TCBind";
3524 break;
3525 case 3:
3526 check_insn(env, ctx, ASE_MT);
3527 tcg_gen_helper_0_1(do_mtc0_tcrestart, t0);
3528 rn = "TCRestart";
3529 break;
3530 case 4:
3531 check_insn(env, ctx, ASE_MT);
3532 tcg_gen_helper_0_1(do_mtc0_tchalt, t0);
3533 rn = "TCHalt";
3534 break;
3535 case 5:
3536 check_insn(env, ctx, ASE_MT);
3537 tcg_gen_helper_0_1(do_mtc0_tccontext, t0);
3538 rn = "TCContext";
3539 break;
3540 case 6:
3541 check_insn(env, ctx, ASE_MT);
3542 tcg_gen_helper_0_1(do_mtc0_tcschedule, t0);
3543 rn = "TCSchedule";
3544 break;
3545 case 7:
3546 check_insn(env, ctx, ASE_MT);
3547 tcg_gen_helper_0_1(do_mtc0_tcschefback, t0);
3548 rn = "TCScheFBack";
3549 break;
3550 default:
3551 goto die;
3553 break;
3554 case 3:
3555 switch (sel) {
3556 case 0:
3557 tcg_gen_helper_0_1(do_mtc0_entrylo1, t0);
3558 rn = "EntryLo1";
3559 break;
3560 default:
3561 goto die;
3563 break;
3564 case 4:
3565 switch (sel) {
3566 case 0:
3567 tcg_gen_helper_0_1(do_mtc0_context, t0);
3568 rn = "Context";
3569 break;
3570 case 1:
3571 // tcg_gen_helper_0_1(do_mtc0_contextconfig, t0); /* SmartMIPS ASE */
3572 rn = "ContextConfig";
3573 // break;
3574 default:
3575 goto die;
3577 break;
3578 case 5:
3579 switch (sel) {
3580 case 0:
3581 tcg_gen_helper_0_1(do_mtc0_pagemask, t0);
3582 rn = "PageMask";
3583 break;
3584 case 1:
3585 check_insn(env, ctx, ISA_MIPS32R2);
3586 tcg_gen_helper_0_1(do_mtc0_pagegrain, t0);
3587 rn = "PageGrain";
3588 break;
3589 default:
3590 goto die;
3592 break;
3593 case 6:
3594 switch (sel) {
3595 case 0:
3596 tcg_gen_helper_0_1(do_mtc0_wired, t0);
3597 rn = "Wired";
3598 break;
3599 case 1:
3600 check_insn(env, ctx, ISA_MIPS32R2);
3601 tcg_gen_helper_0_1(do_mtc0_srsconf0, t0);
3602 rn = "SRSConf0";
3603 break;
3604 case 2:
3605 check_insn(env, ctx, ISA_MIPS32R2);
3606 tcg_gen_helper_0_1(do_mtc0_srsconf1, t0);
3607 rn = "SRSConf1";
3608 break;
3609 case 3:
3610 check_insn(env, ctx, ISA_MIPS32R2);
3611 tcg_gen_helper_0_1(do_mtc0_srsconf2, t0);
3612 rn = "SRSConf2";
3613 break;
3614 case 4:
3615 check_insn(env, ctx, ISA_MIPS32R2);
3616 tcg_gen_helper_0_1(do_mtc0_srsconf3, t0);
3617 rn = "SRSConf3";
3618 break;
3619 case 5:
3620 check_insn(env, ctx, ISA_MIPS32R2);
3621 tcg_gen_helper_0_1(do_mtc0_srsconf4, t0);
3622 rn = "SRSConf4";
3623 break;
3624 default:
3625 goto die;
3627 break;
3628 case 7:
3629 switch (sel) {
3630 case 0:
3631 check_insn(env, ctx, ISA_MIPS32R2);
3632 tcg_gen_helper_0_1(do_mtc0_hwrena, t0);
3633 rn = "HWREna";
3634 break;
3635 default:
3636 goto die;
3638 break;
3639 case 8:
3640 /* ignored */
3641 rn = "BadVAddr";
3642 break;
3643 case 9:
3644 switch (sel) {
3645 case 0:
3646 tcg_gen_helper_0_1(do_mtc0_count, t0);
3647 rn = "Count";
3648 break;
3649 /* 6,7 are implementation dependent */
3650 default:
3651 goto die;
3653 /* Stop translation as we may have switched the execution mode */
3654 ctx->bstate = BS_STOP;
3655 break;
3656 case 10:
3657 switch (sel) {
3658 case 0:
3659 tcg_gen_helper_0_1(do_mtc0_entryhi, t0);
3660 rn = "EntryHi";
3661 break;
3662 default:
3663 goto die;
3665 break;
3666 case 11:
3667 switch (sel) {
3668 case 0:
3669 tcg_gen_helper_0_1(do_mtc0_compare, t0);
3670 rn = "Compare";
3671 break;
3672 /* 6,7 are implementation dependent */
3673 default:
3674 goto die;
3676 /* Stop translation as we may have switched the execution mode */
3677 ctx->bstate = BS_STOP;
3678 break;
3679 case 12:
3680 switch (sel) {
3681 case 0:
3682 tcg_gen_helper_0_1(do_mtc0_status, t0);
3683 /* BS_STOP isn't good enough here, hflags may have changed. */
3684 gen_save_pc(ctx->pc + 4);
3685 ctx->bstate = BS_EXCP;
3686 rn = "Status";
3687 break;
3688 case 1:
3689 check_insn(env, ctx, ISA_MIPS32R2);
3690 tcg_gen_helper_0_1(do_mtc0_intctl, t0);
3691 /* Stop translation as we may have switched the execution mode */
3692 ctx->bstate = BS_STOP;
3693 rn = "IntCtl";
3694 break;
3695 case 2:
3696 check_insn(env, ctx, ISA_MIPS32R2);
3697 tcg_gen_helper_0_1(do_mtc0_srsctl, t0);
3698 /* Stop translation as we may have switched the execution mode */
3699 ctx->bstate = BS_STOP;
3700 rn = "SRSCtl";
3701 break;
3702 case 3:
3703 check_insn(env, ctx, ISA_MIPS32R2);
3704 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
3705 /* Stop translation as we may have switched the execution mode */
3706 ctx->bstate = BS_STOP;
3707 rn = "SRSMap";
3708 break;
3709 default:
3710 goto die;
3712 break;
3713 case 13:
3714 switch (sel) {
3715 case 0:
3716 tcg_gen_helper_0_1(do_mtc0_cause, t0);
3717 rn = "Cause";
3718 break;
3719 default:
3720 goto die;
3722 /* Stop translation as we may have switched the execution mode */
3723 ctx->bstate = BS_STOP;
3724 break;
3725 case 14:
3726 switch (sel) {
3727 case 0:
3728 gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC));
3729 rn = "EPC";
3730 break;
3731 default:
3732 goto die;
3734 break;
3735 case 15:
3736 switch (sel) {
3737 case 0:
3738 /* ignored */
3739 rn = "PRid";
3740 break;
3741 case 1:
3742 check_insn(env, ctx, ISA_MIPS32R2);
3743 tcg_gen_helper_0_1(do_mtc0_ebase, t0);
3744 rn = "EBase";
3745 break;
3746 default:
3747 goto die;
3749 break;
3750 case 16:
3751 switch (sel) {
3752 case 0:
3753 tcg_gen_helper_0_1(do_mtc0_config0, t0);
3754 rn = "Config";
3755 /* Stop translation as we may have switched the execution mode */
3756 ctx->bstate = BS_STOP;
3757 break;
3758 case 1:
3759 /* ignored, read only */
3760 rn = "Config1";
3761 break;
3762 case 2:
3763 tcg_gen_helper_0_1(do_mtc0_config2, t0);
3764 rn = "Config2";
3765 /* Stop translation as we may have switched the execution mode */
3766 ctx->bstate = BS_STOP;
3767 break;
3768 case 3:
3769 /* ignored, read only */
3770 rn = "Config3";
3771 break;
3772 /* 4,5 are reserved */
3773 /* 6,7 are implementation dependent */
3774 case 6:
3775 /* ignored */
3776 rn = "Config6";
3777 break;
3778 case 7:
3779 /* ignored */
3780 rn = "Config7";
3781 break;
3782 default:
3783 rn = "Invalid config selector";
3784 goto die;
3786 break;
3787 case 17:
3788 switch (sel) {
3789 case 0:
3790 /* ignored */
3791 rn = "LLAddr";
3792 break;
3793 default:
3794 goto die;
3796 break;
3797 case 18:
3798 switch (sel) {
3799 case 0 ... 7:
3800 tcg_gen_helper_0_1i(do_mtc0_watchlo, t0, sel);
3801 rn = "WatchLo";
3802 break;
3803 default:
3804 goto die;
3806 break;
3807 case 19:
3808 switch (sel) {
3809 case 0 ... 7:
3810 tcg_gen_helper_0_1i(do_mtc0_watchhi, t0, sel);
3811 rn = "WatchHi";
3812 break;
3813 default:
3814 goto die;
3816 break;
3817 case 20:
3818 switch (sel) {
3819 case 0:
3820 #if defined(TARGET_MIPS64)
3821 check_insn(env, ctx, ISA_MIPS3);
3822 tcg_gen_helper_0_1(do_mtc0_xcontext, t0);
3823 rn = "XContext";
3824 break;
3825 #endif
3826 default:
3827 goto die;
3829 break;
3830 case 21:
3831 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3832 switch (sel) {
3833 case 0:
3834 tcg_gen_helper_0_1(do_mtc0_framemask, t0);
3835 rn = "Framemask";
3836 break;
3837 default:
3838 goto die;
3840 break;
3841 case 22:
3842 /* ignored */
3843 rn = "Diagnostic"; /* implementation dependent */
3844 break;
3845 case 23:
3846 switch (sel) {
3847 case 0:
3848 tcg_gen_helper_0_1(do_mtc0_debug, t0); /* EJTAG support */
3849 /* BS_STOP isn't good enough here, hflags may have changed. */
3850 gen_save_pc(ctx->pc + 4);
3851 ctx->bstate = BS_EXCP;
3852 rn = "Debug";
3853 break;
3854 case 1:
3855 // tcg_gen_helper_0_1(do_mtc0_tracecontrol, t0); /* PDtrace support */
3856 rn = "TraceControl";
3857 /* Stop translation as we may have switched the execution mode */
3858 ctx->bstate = BS_STOP;
3859 // break;
3860 case 2:
3861 // tcg_gen_helper_0_1(do_mtc0_tracecontrol2, t0); /* PDtrace support */
3862 rn = "TraceControl2";
3863 /* Stop translation as we may have switched the execution mode */
3864 ctx->bstate = BS_STOP;
3865 // break;
3866 case 3:
3867 /* Stop translation as we may have switched the execution mode */
3868 ctx->bstate = BS_STOP;
3869 // tcg_gen_helper_0_1(do_mtc0_usertracedata, t0); /* PDtrace support */
3870 rn = "UserTraceData";
3871 /* Stop translation as we may have switched the execution mode */
3872 ctx->bstate = BS_STOP;
3873 // break;
3874 case 4:
3875 // tcg_gen_helper_0_1(do_mtc0_tracebpc, t0); /* PDtrace support */
3876 /* Stop translation as we may have switched the execution mode */
3877 ctx->bstate = BS_STOP;
3878 rn = "TraceBPC";
3879 // break;
3880 default:
3881 goto die;
3883 break;
3884 case 24:
3885 switch (sel) {
3886 case 0:
3887 /* EJTAG support */
3888 gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC));
3889 rn = "DEPC";
3890 break;
3891 default:
3892 goto die;
3894 break;
3895 case 25:
3896 switch (sel) {
3897 case 0:
3898 tcg_gen_helper_0_1(do_mtc0_performance0, t0);
3899 rn = "Performance0";
3900 break;
3901 case 1:
3902 // tcg_gen_helper_0_1(do_mtc0_performance1, t0);
3903 rn = "Performance1";
3904 // break;
3905 case 2:
3906 // tcg_gen_helper_0_1(do_mtc0_performance2, t0);
3907 rn = "Performance2";
3908 // break;
3909 case 3:
3910 // tcg_gen_helper_0_1(do_mtc0_performance3, t0);
3911 rn = "Performance3";
3912 // break;
3913 case 4:
3914 // tcg_gen_helper_0_1(do_mtc0_performance4, t0);
3915 rn = "Performance4";
3916 // break;
3917 case 5:
3918 // tcg_gen_helper_0_1(do_mtc0_performance5, t0);
3919 rn = "Performance5";
3920 // break;
3921 case 6:
3922 // tcg_gen_helper_0_1(do_mtc0_performance6, t0);
3923 rn = "Performance6";
3924 // break;
3925 case 7:
3926 // tcg_gen_helper_0_1(do_mtc0_performance7, t0);
3927 rn = "Performance7";
3928 // break;
3929 default:
3930 goto die;
3932 break;
3933 case 26:
3934 /* ignored */
3935 rn = "ECC";
3936 break;
3937 case 27:
3938 switch (sel) {
3939 case 0 ... 3:
3940 /* ignored */
3941 rn = "CacheErr";
3942 break;
3943 default:
3944 goto die;
3946 break;
3947 case 28:
3948 switch (sel) {
3949 case 0:
3950 case 2:
3951 case 4:
3952 case 6:
3953 tcg_gen_helper_0_1(do_mtc0_taglo, t0);
3954 rn = "TagLo";
3955 break;
3956 case 1:
3957 case 3:
3958 case 5:
3959 case 7:
3960 tcg_gen_helper_0_1(do_mtc0_datalo, t0);
3961 rn = "DataLo";
3962 break;
3963 default:
3964 goto die;
3966 break;
3967 case 29:
3968 switch (sel) {
3969 case 0:
3970 case 2:
3971 case 4:
3972 case 6:
3973 tcg_gen_helper_0_1(do_mtc0_taghi, t0);
3974 rn = "TagHi";
3975 break;
3976 case 1:
3977 case 3:
3978 case 5:
3979 case 7:
3980 tcg_gen_helper_0_1(do_mtc0_datahi, t0);
3981 rn = "DataHi";
3982 break;
3983 default:
3984 rn = "invalid sel";
3985 goto die;
3987 break;
3988 case 30:
3989 switch (sel) {
3990 case 0:
3991 gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC));
3992 rn = "ErrorEPC";
3993 break;
3994 default:
3995 goto die;
3997 break;
3998 case 31:
3999 switch (sel) {
4000 case 0:
4001 /* EJTAG support */
4002 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
4003 rn = "DESAVE";
4004 break;
4005 default:
4006 goto die;
4008 /* Stop translation as we may have switched the execution mode */
4009 ctx->bstate = BS_STOP;
4010 break;
4011 default:
4012 goto die;
4014 #if defined MIPS_DEBUG_DISAS
4015 if (loglevel & CPU_LOG_TB_IN_ASM) {
4016 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
4017 rn, reg, sel);
4019 #endif
4020 /* For simplicity assume that all writes can cause interrupts. */
4021 if (use_icount) {
4022 gen_io_end();
4023 ctx->bstate = BS_STOP;
4025 return;
4027 die:
4028 #if defined MIPS_DEBUG_DISAS
4029 if (loglevel & CPU_LOG_TB_IN_ASM) {
4030 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
4031 rn, reg, sel);
4033 #endif
4034 generate_exception(ctx, EXCP_RI);
4037 #if defined(TARGET_MIPS64)
4038 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
4040 const char *rn = "invalid";
4042 if (sel != 0)
4043 check_insn(env, ctx, ISA_MIPS64);
4045 switch (reg) {
4046 case 0:
4047 switch (sel) {
4048 case 0:
4049 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
4050 rn = "Index";
4051 break;
4052 case 1:
4053 check_insn(env, ctx, ASE_MT);
4054 tcg_gen_helper_1_0(do_mfc0_mvpcontrol, t0);
4055 rn = "MVPControl";
4056 break;
4057 case 2:
4058 check_insn(env, ctx, ASE_MT);
4059 tcg_gen_helper_1_0(do_mfc0_mvpconf0, t0);
4060 rn = "MVPConf0";
4061 break;
4062 case 3:
4063 check_insn(env, ctx, ASE_MT);
4064 tcg_gen_helper_1_0(do_mfc0_mvpconf1, t0);
4065 rn = "MVPConf1";
4066 break;
4067 default:
4068 goto die;
4070 break;
4071 case 1:
4072 switch (sel) {
4073 case 0:
4074 tcg_gen_helper_1_0(do_mfc0_random, t0);
4075 rn = "Random";
4076 break;
4077 case 1:
4078 check_insn(env, ctx, ASE_MT);
4079 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
4080 rn = "VPEControl";
4081 break;
4082 case 2:
4083 check_insn(env, ctx, ASE_MT);
4084 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
4085 rn = "VPEConf0";
4086 break;
4087 case 3:
4088 check_insn(env, ctx, ASE_MT);
4089 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
4090 rn = "VPEConf1";
4091 break;
4092 case 4:
4093 check_insn(env, ctx, ASE_MT);
4094 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask));
4095 rn = "YQMask";
4096 break;
4097 case 5:
4098 check_insn(env, ctx, ASE_MT);
4099 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4100 rn = "VPESchedule";
4101 break;
4102 case 6:
4103 check_insn(env, ctx, ASE_MT);
4104 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4105 rn = "VPEScheFBack";
4106 break;
4107 case 7:
4108 check_insn(env, ctx, ASE_MT);
4109 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
4110 rn = "VPEOpt";
4111 break;
4112 default:
4113 goto die;
4115 break;
4116 case 2:
4117 switch (sel) {
4118 case 0:
4119 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4120 rn = "EntryLo0";
4121 break;
4122 case 1:
4123 check_insn(env, ctx, ASE_MT);
4124 tcg_gen_helper_1_0(do_mfc0_tcstatus, t0);
4125 rn = "TCStatus";
4126 break;
4127 case 2:
4128 check_insn(env, ctx, ASE_MT);
4129 tcg_gen_helper_1_0(do_mfc0_tcbind, t0);
4130 rn = "TCBind";
4131 break;
4132 case 3:
4133 check_insn(env, ctx, ASE_MT);
4134 tcg_gen_helper_1_0(do_dmfc0_tcrestart, t0);
4135 rn = "TCRestart";
4136 break;
4137 case 4:
4138 check_insn(env, ctx, ASE_MT);
4139 tcg_gen_helper_1_0(do_dmfc0_tchalt, t0);
4140 rn = "TCHalt";
4141 break;
4142 case 5:
4143 check_insn(env, ctx, ASE_MT);
4144 tcg_gen_helper_1_0(do_dmfc0_tccontext, t0);
4145 rn = "TCContext";
4146 break;
4147 case 6:
4148 check_insn(env, ctx, ASE_MT);
4149 tcg_gen_helper_1_0(do_dmfc0_tcschedule, t0);
4150 rn = "TCSchedule";
4151 break;
4152 case 7:
4153 check_insn(env, ctx, ASE_MT);
4154 tcg_gen_helper_1_0(do_dmfc0_tcschefback, t0);
4155 rn = "TCScheFBack";
4156 break;
4157 default:
4158 goto die;
4160 break;
4161 case 3:
4162 switch (sel) {
4163 case 0:
4164 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4165 rn = "EntryLo1";
4166 break;
4167 default:
4168 goto die;
4170 break;
4171 case 4:
4172 switch (sel) {
4173 case 0:
4174 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
4175 rn = "Context";
4176 break;
4177 case 1:
4178 // tcg_gen_helper_1_0(do_dmfc0_contextconfig, t0); /* SmartMIPS ASE */
4179 rn = "ContextConfig";
4180 // break;
4181 default:
4182 goto die;
4184 break;
4185 case 5:
4186 switch (sel) {
4187 case 0:
4188 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
4189 rn = "PageMask";
4190 break;
4191 case 1:
4192 check_insn(env, ctx, ISA_MIPS32R2);
4193 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
4194 rn = "PageGrain";
4195 break;
4196 default:
4197 goto die;
4199 break;
4200 case 6:
4201 switch (sel) {
4202 case 0:
4203 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
4204 rn = "Wired";
4205 break;
4206 case 1:
4207 check_insn(env, ctx, ISA_MIPS32R2);
4208 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
4209 rn = "SRSConf0";
4210 break;
4211 case 2:
4212 check_insn(env, ctx, ISA_MIPS32R2);
4213 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
4214 rn = "SRSConf1";
4215 break;
4216 case 3:
4217 check_insn(env, ctx, ISA_MIPS32R2);
4218 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
4219 rn = "SRSConf2";
4220 break;
4221 case 4:
4222 check_insn(env, ctx, ISA_MIPS32R2);
4223 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
4224 rn = "SRSConf3";
4225 break;
4226 case 5:
4227 check_insn(env, ctx, ISA_MIPS32R2);
4228 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
4229 rn = "SRSConf4";
4230 break;
4231 default:
4232 goto die;
4234 break;
4235 case 7:
4236 switch (sel) {
4237 case 0:
4238 check_insn(env, ctx, ISA_MIPS32R2);
4239 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
4240 rn = "HWREna";
4241 break;
4242 default:
4243 goto die;
4245 break;
4246 case 8:
4247 switch (sel) {
4248 case 0:
4249 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4250 rn = "BadVAddr";
4251 break;
4252 default:
4253 goto die;
4255 break;
4256 case 9:
4257 switch (sel) {
4258 case 0:
4259 /* Mark as an IO operation because we read the time. */
4260 if (use_icount)
4261 gen_io_start();
4262 tcg_gen_helper_1_0(do_mfc0_count, t0);
4263 if (use_icount) {
4264 gen_io_end();
4265 ctx->bstate = BS_STOP;
4267 rn = "Count";
4268 break;
4269 /* 6,7 are implementation dependent */
4270 default:
4271 goto die;
4273 break;
4274 case 10:
4275 switch (sel) {
4276 case 0:
4277 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
4278 rn = "EntryHi";
4279 break;
4280 default:
4281 goto die;
4283 break;
4284 case 11:
4285 switch (sel) {
4286 case 0:
4287 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
4288 rn = "Compare";
4289 break;
4290 /* 6,7 are implementation dependent */
4291 default:
4292 goto die;
4294 break;
4295 case 12:
4296 switch (sel) {
4297 case 0:
4298 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
4299 rn = "Status";
4300 break;
4301 case 1:
4302 check_insn(env, ctx, ISA_MIPS32R2);
4303 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
4304 rn = "IntCtl";
4305 break;
4306 case 2:
4307 check_insn(env, ctx, ISA_MIPS32R2);
4308 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
4309 rn = "SRSCtl";
4310 break;
4311 case 3:
4312 check_insn(env, ctx, ISA_MIPS32R2);
4313 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
4314 rn = "SRSMap";
4315 break;
4316 default:
4317 goto die;
4319 break;
4320 case 13:
4321 switch (sel) {
4322 case 0:
4323 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
4324 rn = "Cause";
4325 break;
4326 default:
4327 goto die;
4329 break;
4330 case 14:
4331 switch (sel) {
4332 case 0:
4333 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4334 rn = "EPC";
4335 break;
4336 default:
4337 goto die;
4339 break;
4340 case 15:
4341 switch (sel) {
4342 case 0:
4343 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
4344 rn = "PRid";
4345 break;
4346 case 1:
4347 check_insn(env, ctx, ISA_MIPS32R2);
4348 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
4349 rn = "EBase";
4350 break;
4351 default:
4352 goto die;
4354 break;
4355 case 16:
4356 switch (sel) {
4357 case 0:
4358 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
4359 rn = "Config";
4360 break;
4361 case 1:
4362 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
4363 rn = "Config1";
4364 break;
4365 case 2:
4366 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
4367 rn = "Config2";
4368 break;
4369 case 3:
4370 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
4371 rn = "Config3";
4372 break;
4373 /* 6,7 are implementation dependent */
4374 case 6:
4375 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
4376 rn = "Config6";
4377 break;
4378 case 7:
4379 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
4380 rn = "Config7";
4381 break;
4382 default:
4383 goto die;
4385 break;
4386 case 17:
4387 switch (sel) {
4388 case 0:
4389 tcg_gen_helper_1_0(do_dmfc0_lladdr, t0);
4390 rn = "LLAddr";
4391 break;
4392 default:
4393 goto die;
4395 break;
4396 case 18:
4397 switch (sel) {
4398 case 0 ... 7:
4399 tcg_gen_helper_1_i(do_dmfc0_watchlo, t0, sel);
4400 rn = "WatchLo";
4401 break;
4402 default:
4403 goto die;
4405 break;
4406 case 19:
4407 switch (sel) {
4408 case 0 ... 7:
4409 tcg_gen_helper_1_i(do_mfc0_watchhi, t0, sel);
4410 rn = "WatchHi";
4411 break;
4412 default:
4413 goto die;
4415 break;
4416 case 20:
4417 switch (sel) {
4418 case 0:
4419 check_insn(env, ctx, ISA_MIPS3);
4420 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
4421 rn = "XContext";
4422 break;
4423 default:
4424 goto die;
4426 break;
4427 case 21:
4428 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4429 switch (sel) {
4430 case 0:
4431 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
4432 rn = "Framemask";
4433 break;
4434 default:
4435 goto die;
4437 break;
4438 case 22:
4439 /* ignored */
4440 rn = "'Diagnostic"; /* implementation dependent */
4441 break;
4442 case 23:
4443 switch (sel) {
4444 case 0:
4445 tcg_gen_helper_1_0(do_mfc0_debug, t0); /* EJTAG support */
4446 rn = "Debug";
4447 break;
4448 case 1:
4449 // tcg_gen_helper_1_0(do_dmfc0_tracecontrol, t0); /* PDtrace support */
4450 rn = "TraceControl";
4451 // break;
4452 case 2:
4453 // tcg_gen_helper_1_0(do_dmfc0_tracecontrol2, t0); /* PDtrace support */
4454 rn = "TraceControl2";
4455 // break;
4456 case 3:
4457 // tcg_gen_helper_1_0(do_dmfc0_usertracedata, t0); /* PDtrace support */
4458 rn = "UserTraceData";
4459 // break;
4460 case 4:
4461 // tcg_gen_helper_1_0(do_dmfc0_tracebpc, t0); /* PDtrace support */
4462 rn = "TraceBPC";
4463 // break;
4464 default:
4465 goto die;
4467 break;
4468 case 24:
4469 switch (sel) {
4470 case 0:
4471 /* EJTAG support */
4472 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
4473 rn = "DEPC";
4474 break;
4475 default:
4476 goto die;
4478 break;
4479 case 25:
4480 switch (sel) {
4481 case 0:
4482 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
4483 rn = "Performance0";
4484 break;
4485 case 1:
4486 // tcg_gen_helper_1_0(do_dmfc0_performance1, t0);
4487 rn = "Performance1";
4488 // break;
4489 case 2:
4490 // tcg_gen_helper_1_0(do_dmfc0_performance2, t0);
4491 rn = "Performance2";
4492 // break;
4493 case 3:
4494 // tcg_gen_helper_1_0(do_dmfc0_performance3, t0);
4495 rn = "Performance3";
4496 // break;
4497 case 4:
4498 // tcg_gen_helper_1_0(do_dmfc0_performance4, t0);
4499 rn = "Performance4";
4500 // break;
4501 case 5:
4502 // tcg_gen_helper_1_0(do_dmfc0_performance5, t0);
4503 rn = "Performance5";
4504 // break;
4505 case 6:
4506 // tcg_gen_helper_1_0(do_dmfc0_performance6, t0);
4507 rn = "Performance6";
4508 // break;
4509 case 7:
4510 // tcg_gen_helper_1_0(do_dmfc0_performance7, t0);
4511 rn = "Performance7";
4512 // break;
4513 default:
4514 goto die;
4516 break;
4517 case 26:
4518 rn = "ECC";
4519 break;
4520 case 27:
4521 switch (sel) {
4522 /* ignored */
4523 case 0 ... 3:
4524 rn = "CacheErr";
4525 break;
4526 default:
4527 goto die;
4529 break;
4530 case 28:
4531 switch (sel) {
4532 case 0:
4533 case 2:
4534 case 4:
4535 case 6:
4536 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
4537 rn = "TagLo";
4538 break;
4539 case 1:
4540 case 3:
4541 case 5:
4542 case 7:
4543 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
4544 rn = "DataLo";
4545 break;
4546 default:
4547 goto die;
4549 break;
4550 case 29:
4551 switch (sel) {
4552 case 0:
4553 case 2:
4554 case 4:
4555 case 6:
4556 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
4557 rn = "TagHi";
4558 break;
4559 case 1:
4560 case 3:
4561 case 5:
4562 case 7:
4563 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
4564 rn = "DataHi";
4565 break;
4566 default:
4567 goto die;
4569 break;
4570 case 30:
4571 switch (sel) {
4572 case 0:
4573 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4574 rn = "ErrorEPC";
4575 break;
4576 default:
4577 goto die;
4579 break;
4580 case 31:
4581 switch (sel) {
4582 case 0:
4583 /* EJTAG support */
4584 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
4585 rn = "DESAVE";
4586 break;
4587 default:
4588 goto die;
4590 break;
4591 default:
4592 goto die;
4594 #if defined MIPS_DEBUG_DISAS
4595 if (loglevel & CPU_LOG_TB_IN_ASM) {
4596 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4597 rn, reg, sel);
4599 #endif
4600 return;
4602 die:
4603 #if defined MIPS_DEBUG_DISAS
4604 if (loglevel & CPU_LOG_TB_IN_ASM) {
4605 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4606 rn, reg, sel);
4608 #endif
4609 generate_exception(ctx, EXCP_RI);
4612 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
4614 const char *rn = "invalid";
4616 if (sel != 0)
4617 check_insn(env, ctx, ISA_MIPS64);
4619 if (use_icount)
4620 gen_io_start();
4622 switch (reg) {
4623 case 0:
4624 switch (sel) {
4625 case 0:
4626 tcg_gen_helper_0_1(do_mtc0_index, t0);
4627 rn = "Index";
4628 break;
4629 case 1:
4630 check_insn(env, ctx, ASE_MT);
4631 tcg_gen_helper_0_1(do_mtc0_mvpcontrol, t0);
4632 rn = "MVPControl";
4633 break;
4634 case 2:
4635 check_insn(env, ctx, ASE_MT);
4636 /* ignored */
4637 rn = "MVPConf0";
4638 break;
4639 case 3:
4640 check_insn(env, ctx, ASE_MT);
4641 /* ignored */
4642 rn = "MVPConf1";
4643 break;
4644 default:
4645 goto die;
4647 break;
4648 case 1:
4649 switch (sel) {
4650 case 0:
4651 /* ignored */
4652 rn = "Random";
4653 break;
4654 case 1:
4655 check_insn(env, ctx, ASE_MT);
4656 tcg_gen_helper_0_1(do_mtc0_vpecontrol, t0);
4657 rn = "VPEControl";
4658 break;
4659 case 2:
4660 check_insn(env, ctx, ASE_MT);
4661 tcg_gen_helper_0_1(do_mtc0_vpeconf0, t0);
4662 rn = "VPEConf0";
4663 break;
4664 case 3:
4665 check_insn(env, ctx, ASE_MT);
4666 tcg_gen_helper_0_1(do_mtc0_vpeconf1, t0);
4667 rn = "VPEConf1";
4668 break;
4669 case 4:
4670 check_insn(env, ctx, ASE_MT);
4671 tcg_gen_helper_0_1(do_mtc0_yqmask, t0);
4672 rn = "YQMask";
4673 break;
4674 case 5:
4675 check_insn(env, ctx, ASE_MT);
4676 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4677 rn = "VPESchedule";
4678 break;
4679 case 6:
4680 check_insn(env, ctx, ASE_MT);
4681 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4682 rn = "VPEScheFBack";
4683 break;
4684 case 7:
4685 check_insn(env, ctx, ASE_MT);
4686 tcg_gen_helper_0_1(do_mtc0_vpeopt, t0);
4687 rn = "VPEOpt";
4688 break;
4689 default:
4690 goto die;
4692 break;
4693 case 2:
4694 switch (sel) {
4695 case 0:
4696 tcg_gen_helper_0_1(do_mtc0_entrylo0, t0);
4697 rn = "EntryLo0";
4698 break;
4699 case 1:
4700 check_insn(env, ctx, ASE_MT);
4701 tcg_gen_helper_0_1(do_mtc0_tcstatus, t0);
4702 rn = "TCStatus";
4703 break;
4704 case 2:
4705 check_insn(env, ctx, ASE_MT);
4706 tcg_gen_helper_0_1(do_mtc0_tcbind, t0);
4707 rn = "TCBind";
4708 break;
4709 case 3:
4710 check_insn(env, ctx, ASE_MT);
4711 tcg_gen_helper_0_1(do_mtc0_tcrestart, t0);
4712 rn = "TCRestart";
4713 break;
4714 case 4:
4715 check_insn(env, ctx, ASE_MT);
4716 tcg_gen_helper_0_1(do_mtc0_tchalt, t0);
4717 rn = "TCHalt";
4718 break;
4719 case 5:
4720 check_insn(env, ctx, ASE_MT);
4721 tcg_gen_helper_0_1(do_mtc0_tccontext, t0);
4722 rn = "TCContext";
4723 break;
4724 case 6:
4725 check_insn(env, ctx, ASE_MT);
4726 tcg_gen_helper_0_1(do_mtc0_tcschedule, t0);
4727 rn = "TCSchedule";
4728 break;
4729 case 7:
4730 check_insn(env, ctx, ASE_MT);
4731 tcg_gen_helper_0_1(do_mtc0_tcschefback, t0);
4732 rn = "TCScheFBack";
4733 break;
4734 default:
4735 goto die;
4737 break;
4738 case 3:
4739 switch (sel) {
4740 case 0:
4741 tcg_gen_helper_0_1(do_mtc0_entrylo1, t0);
4742 rn = "EntryLo1";
4743 break;
4744 default:
4745 goto die;
4747 break;
4748 case 4:
4749 switch (sel) {
4750 case 0:
4751 tcg_gen_helper_0_1(do_mtc0_context, t0);
4752 rn = "Context";
4753 break;
4754 case 1:
4755 // tcg_gen_helper_0_1(do_mtc0_contextconfig, t0); /* SmartMIPS ASE */
4756 rn = "ContextConfig";
4757 // break;
4758 default:
4759 goto die;
4761 break;
4762 case 5:
4763 switch (sel) {
4764 case 0:
4765 tcg_gen_helper_0_1(do_mtc0_pagemask, t0);
4766 rn = "PageMask";
4767 break;
4768 case 1:
4769 check_insn(env, ctx, ISA_MIPS32R2);
4770 tcg_gen_helper_0_1(do_mtc0_pagegrain, t0);
4771 rn = "PageGrain";
4772 break;
4773 default:
4774 goto die;
4776 break;
4777 case 6:
4778 switch (sel) {
4779 case 0:
4780 tcg_gen_helper_0_1(do_mtc0_wired, t0);
4781 rn = "Wired";
4782 break;
4783 case 1:
4784 check_insn(env, ctx, ISA_MIPS32R2);
4785 tcg_gen_helper_0_1(do_mtc0_srsconf0, t0);
4786 rn = "SRSConf0";
4787 break;
4788 case 2:
4789 check_insn(env, ctx, ISA_MIPS32R2);
4790 tcg_gen_helper_0_1(do_mtc0_srsconf1, t0);
4791 rn = "SRSConf1";
4792 break;
4793 case 3:
4794 check_insn(env, ctx, ISA_MIPS32R2);
4795 tcg_gen_helper_0_1(do_mtc0_srsconf2, t0);
4796 rn = "SRSConf2";
4797 break;
4798 case 4:
4799 check_insn(env, ctx, ISA_MIPS32R2);
4800 tcg_gen_helper_0_1(do_mtc0_srsconf3, t0);
4801 rn = "SRSConf3";
4802 break;
4803 case 5:
4804 check_insn(env, ctx, ISA_MIPS32R2);
4805 tcg_gen_helper_0_1(do_mtc0_srsconf4, t0);
4806 rn = "SRSConf4";
4807 break;
4808 default:
4809 goto die;
4811 break;
4812 case 7:
4813 switch (sel) {
4814 case 0:
4815 check_insn(env, ctx, ISA_MIPS32R2);
4816 tcg_gen_helper_0_1(do_mtc0_hwrena, t0);
4817 rn = "HWREna";
4818 break;
4819 default:
4820 goto die;
4822 break;
4823 case 8:
4824 /* ignored */
4825 rn = "BadVAddr";
4826 break;
4827 case 9:
4828 switch (sel) {
4829 case 0:
4830 tcg_gen_helper_0_1(do_mtc0_count, t0);
4831 rn = "Count";
4832 break;
4833 /* 6,7 are implementation dependent */
4834 default:
4835 goto die;
4837 /* Stop translation as we may have switched the execution mode */
4838 ctx->bstate = BS_STOP;
4839 break;
4840 case 10:
4841 switch (sel) {
4842 case 0:
4843 tcg_gen_helper_0_1(do_mtc0_entryhi, t0);
4844 rn = "EntryHi";
4845 break;
4846 default:
4847 goto die;
4849 break;
4850 case 11:
4851 switch (sel) {
4852 case 0:
4853 tcg_gen_helper_0_1(do_mtc0_compare, t0);
4854 rn = "Compare";
4855 break;
4856 /* 6,7 are implementation dependent */
4857 default:
4858 goto die;
4860 /* Stop translation as we may have switched the execution mode */
4861 ctx->bstate = BS_STOP;
4862 break;
4863 case 12:
4864 switch (sel) {
4865 case 0:
4866 tcg_gen_helper_0_1(do_mtc0_status, t0);
4867 /* BS_STOP isn't good enough here, hflags may have changed. */
4868 gen_save_pc(ctx->pc + 4);
4869 ctx->bstate = BS_EXCP;
4870 rn = "Status";
4871 break;
4872 case 1:
4873 check_insn(env, ctx, ISA_MIPS32R2);
4874 tcg_gen_helper_0_1(do_mtc0_intctl, t0);
4875 /* Stop translation as we may have switched the execution mode */
4876 ctx->bstate = BS_STOP;
4877 rn = "IntCtl";
4878 break;
4879 case 2:
4880 check_insn(env, ctx, ISA_MIPS32R2);
4881 tcg_gen_helper_0_1(do_mtc0_srsctl, t0);
4882 /* Stop translation as we may have switched the execution mode */
4883 ctx->bstate = BS_STOP;
4884 rn = "SRSCtl";
4885 break;
4886 case 3:
4887 check_insn(env, ctx, ISA_MIPS32R2);
4888 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
4889 /* Stop translation as we may have switched the execution mode */
4890 ctx->bstate = BS_STOP;
4891 rn = "SRSMap";
4892 break;
4893 default:
4894 goto die;
4896 break;
4897 case 13:
4898 switch (sel) {
4899 case 0:
4900 tcg_gen_helper_0_1(do_mtc0_cause, t0);
4901 rn = "Cause";
4902 break;
4903 default:
4904 goto die;
4906 /* Stop translation as we may have switched the execution mode */
4907 ctx->bstate = BS_STOP;
4908 break;
4909 case 14:
4910 switch (sel) {
4911 case 0:
4912 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4913 rn = "EPC";
4914 break;
4915 default:
4916 goto die;
4918 break;
4919 case 15:
4920 switch (sel) {
4921 case 0:
4922 /* ignored */
4923 rn = "PRid";
4924 break;
4925 case 1:
4926 check_insn(env, ctx, ISA_MIPS32R2);
4927 tcg_gen_helper_0_1(do_mtc0_ebase, t0);
4928 rn = "EBase";
4929 break;
4930 default:
4931 goto die;
4933 break;
4934 case 16:
4935 switch (sel) {
4936 case 0:
4937 tcg_gen_helper_0_1(do_mtc0_config0, t0);
4938 rn = "Config";
4939 /* Stop translation as we may have switched the execution mode */
4940 ctx->bstate = BS_STOP;
4941 break;
4942 case 1:
4943 /* ignored */
4944 rn = "Config1";
4945 break;
4946 case 2:
4947 tcg_gen_helper_0_1(do_mtc0_config2, t0);
4948 rn = "Config2";
4949 /* Stop translation as we may have switched the execution mode */
4950 ctx->bstate = BS_STOP;
4951 break;
4952 case 3:
4953 /* ignored */
4954 rn = "Config3";
4955 break;
4956 /* 6,7 are implementation dependent */
4957 default:
4958 rn = "Invalid config selector";
4959 goto die;
4961 break;
4962 case 17:
4963 switch (sel) {
4964 case 0:
4965 /* ignored */
4966 rn = "LLAddr";
4967 break;
4968 default:
4969 goto die;
4971 break;
4972 case 18:
4973 switch (sel) {
4974 case 0 ... 7:
4975 tcg_gen_helper_0_1i(do_mtc0_watchlo, t0, sel);
4976 rn = "WatchLo";
4977 break;
4978 default:
4979 goto die;
4981 break;
4982 case 19:
4983 switch (sel) {
4984 case 0 ... 7:
4985 tcg_gen_helper_0_1i(do_mtc0_watchhi, t0, sel);
4986 rn = "WatchHi";
4987 break;
4988 default:
4989 goto die;
4991 break;
4992 case 20:
4993 switch (sel) {
4994 case 0:
4995 check_insn(env, ctx, ISA_MIPS3);
4996 tcg_gen_helper_0_1(do_mtc0_xcontext, t0);
4997 rn = "XContext";
4998 break;
4999 default:
5000 goto die;
5002 break;
5003 case 21:
5004 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5005 switch (sel) {
5006 case 0:
5007 tcg_gen_helper_0_1(do_mtc0_framemask, t0);
5008 rn = "Framemask";
5009 break;
5010 default:
5011 goto die;
5013 break;
5014 case 22:
5015 /* ignored */
5016 rn = "Diagnostic"; /* implementation dependent */
5017 break;
5018 case 23:
5019 switch (sel) {
5020 case 0:
5021 tcg_gen_helper_0_1(do_mtc0_debug, t0); /* EJTAG support */
5022 /* BS_STOP isn't good enough here, hflags may have changed. */
5023 gen_save_pc(ctx->pc + 4);
5024 ctx->bstate = BS_EXCP;
5025 rn = "Debug";
5026 break;
5027 case 1:
5028 // tcg_gen_helper_0_1(do_mtc0_tracecontrol, t0); /* PDtrace support */
5029 /* Stop translation as we may have switched the execution mode */
5030 ctx->bstate = BS_STOP;
5031 rn = "TraceControl";
5032 // break;
5033 case 2:
5034 // tcg_gen_helper_0_1(do_mtc0_tracecontrol2, t0); /* PDtrace support */
5035 /* Stop translation as we may have switched the execution mode */
5036 ctx->bstate = BS_STOP;
5037 rn = "TraceControl2";
5038 // break;
5039 case 3:
5040 // tcg_gen_helper_0_1(do_mtc0_usertracedata, t0); /* PDtrace support */
5041 /* Stop translation as we may have switched the execution mode */
5042 ctx->bstate = BS_STOP;
5043 rn = "UserTraceData";
5044 // break;
5045 case 4:
5046 // tcg_gen_helper_0_1(do_mtc0_tracebpc, t0); /* PDtrace support */
5047 /* Stop translation as we may have switched the execution mode */
5048 ctx->bstate = BS_STOP;
5049 rn = "TraceBPC";
5050 // break;
5051 default:
5052 goto die;
5054 break;
5055 case 24:
5056 switch (sel) {
5057 case 0:
5058 /* EJTAG support */
5059 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
5060 rn = "DEPC";
5061 break;
5062 default:
5063 goto die;
5065 break;
5066 case 25:
5067 switch (sel) {
5068 case 0:
5069 tcg_gen_helper_0_1(do_mtc0_performance0, t0);
5070 rn = "Performance0";
5071 break;
5072 case 1:
5073 // tcg_gen_helper_0_1(do_mtc0_performance1, t0);
5074 rn = "Performance1";
5075 // break;
5076 case 2:
5077 // tcg_gen_helper_0_1(do_mtc0_performance2, t0);
5078 rn = "Performance2";
5079 // break;
5080 case 3:
5081 // tcg_gen_helper_0_1(do_mtc0_performance3, t0);
5082 rn = "Performance3";
5083 // break;
5084 case 4:
5085 // tcg_gen_helper_0_1(do_mtc0_performance4, t0);
5086 rn = "Performance4";
5087 // break;
5088 case 5:
5089 // tcg_gen_helper_0_1(do_mtc0_performance5, t0);
5090 rn = "Performance5";
5091 // break;
5092 case 6:
5093 // tcg_gen_helper_0_1(do_mtc0_performance6, t0);
5094 rn = "Performance6";
5095 // break;
5096 case 7:
5097 // tcg_gen_helper_0_1(do_mtc0_performance7, t0);
5098 rn = "Performance7";
5099 // break;
5100 default:
5101 goto die;
5103 break;
5104 case 26:
5105 /* ignored */
5106 rn = "ECC";
5107 break;
5108 case 27:
5109 switch (sel) {
5110 case 0 ... 3:
5111 /* ignored */
5112 rn = "CacheErr";
5113 break;
5114 default:
5115 goto die;
5117 break;
5118 case 28:
5119 switch (sel) {
5120 case 0:
5121 case 2:
5122 case 4:
5123 case 6:
5124 tcg_gen_helper_0_1(do_mtc0_taglo, t0);
5125 rn = "TagLo";
5126 break;
5127 case 1:
5128 case 3:
5129 case 5:
5130 case 7:
5131 tcg_gen_helper_0_1(do_mtc0_datalo, t0);
5132 rn = "DataLo";
5133 break;
5134 default:
5135 goto die;
5137 break;
5138 case 29:
5139 switch (sel) {
5140 case 0:
5141 case 2:
5142 case 4:
5143 case 6:
5144 tcg_gen_helper_0_1(do_mtc0_taghi, t0);
5145 rn = "TagHi";
5146 break;
5147 case 1:
5148 case 3:
5149 case 5:
5150 case 7:
5151 tcg_gen_helper_0_1(do_mtc0_datahi, t0);
5152 rn = "DataHi";
5153 break;
5154 default:
5155 rn = "invalid sel";
5156 goto die;
5158 break;
5159 case 30:
5160 switch (sel) {
5161 case 0:
5162 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5163 rn = "ErrorEPC";
5164 break;
5165 default:
5166 goto die;
5168 break;
5169 case 31:
5170 switch (sel) {
5171 case 0:
5172 /* EJTAG support */
5173 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
5174 rn = "DESAVE";
5175 break;
5176 default:
5177 goto die;
5179 /* Stop translation as we may have switched the execution mode */
5180 ctx->bstate = BS_STOP;
5181 break;
5182 default:
5183 goto die;
5185 #if defined MIPS_DEBUG_DISAS
5186 if (loglevel & CPU_LOG_TB_IN_ASM) {
5187 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5188 rn, reg, sel);
5190 #endif
5191 tcg_temp_free(t0);
5192 /* For simplicity assume that all writes can cause interrupts. */
5193 if (use_icount) {
5194 gen_io_end();
5195 ctx->bstate = BS_STOP;
5197 return;
5199 die:
5200 tcg_temp_free(t0);
5201 #if defined MIPS_DEBUG_DISAS
5202 if (loglevel & CPU_LOG_TB_IN_ASM) {
5203 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5204 rn, reg, sel);
5206 #endif
5207 generate_exception(ctx, EXCP_RI);
5209 #endif /* TARGET_MIPS64 */
5211 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5212 int u, int sel, int h)
5214 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5215 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5217 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5218 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5219 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5220 tcg_gen_movi_tl(t0, -1);
5221 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5222 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5223 tcg_gen_movi_tl(t0, -1);
5224 else if (u == 0) {
5225 switch (rt) {
5226 case 2:
5227 switch (sel) {
5228 case 1:
5229 tcg_gen_helper_1_1(do_mftc0_tcstatus, t0, t0);
5230 break;
5231 case 2:
5232 tcg_gen_helper_1_1(do_mftc0_tcbind, t0, t0);
5233 break;
5234 case 3:
5235 tcg_gen_helper_1_1(do_mftc0_tcrestart, t0, t0);
5236 break;
5237 case 4:
5238 tcg_gen_helper_1_1(do_mftc0_tchalt, t0, t0);
5239 break;
5240 case 5:
5241 tcg_gen_helper_1_1(do_mftc0_tccontext, t0, t0);
5242 break;
5243 case 6:
5244 tcg_gen_helper_1_1(do_mftc0_tcschedule, t0, t0);
5245 break;
5246 case 7:
5247 tcg_gen_helper_1_1(do_mftc0_tcschefback, t0, t0);
5248 break;
5249 default:
5250 gen_mfc0(env, ctx, t0, rt, sel);
5251 break;
5253 break;
5254 case 10:
5255 switch (sel) {
5256 case 0:
5257 tcg_gen_helper_1_1(do_mftc0_entryhi, t0, t0);
5258 break;
5259 default:
5260 gen_mfc0(env, ctx, t0, rt, sel);
5261 break;
5263 case 12:
5264 switch (sel) {
5265 case 0:
5266 tcg_gen_helper_1_1(do_mftc0_status, t0, t0);
5267 break;
5268 default:
5269 gen_mfc0(env, ctx, t0, rt, sel);
5270 break;
5272 case 23:
5273 switch (sel) {
5274 case 0:
5275 tcg_gen_helper_1_1(do_mftc0_debug, t0, t0);
5276 break;
5277 default:
5278 gen_mfc0(env, ctx, t0, rt, sel);
5279 break;
5281 break;
5282 default:
5283 gen_mfc0(env, ctx, t0, rt, sel);
5285 } else switch (sel) {
5286 /* GPR registers. */
5287 case 0:
5288 tcg_gen_helper_1_1i(do_mftgpr, t0, t0, rt);
5289 break;
5290 /* Auxiliary CPU registers */
5291 case 1:
5292 switch (rt) {
5293 case 0:
5294 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 0);
5295 break;
5296 case 1:
5297 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 0);
5298 break;
5299 case 2:
5300 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 0);
5301 break;
5302 case 4:
5303 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 1);
5304 break;
5305 case 5:
5306 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 1);
5307 break;
5308 case 6:
5309 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 1);
5310 break;
5311 case 8:
5312 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 2);
5313 break;
5314 case 9:
5315 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 2);
5316 break;
5317 case 10:
5318 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 2);
5319 break;
5320 case 12:
5321 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 3);
5322 break;
5323 case 13:
5324 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 3);
5325 break;
5326 case 14:
5327 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 3);
5328 break;
5329 case 16:
5330 tcg_gen_helper_1_1(do_mftdsp, t0, t0);
5331 break;
5332 default:
5333 goto die;
5335 break;
5336 /* Floating point (COP1). */
5337 case 2:
5338 /* XXX: For now we support only a single FPU context. */
5339 if (h == 0) {
5340 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5342 gen_load_fpr32(fp0, rt);
5343 tcg_gen_ext_i32_tl(t0, fp0);
5344 tcg_temp_free(fp0);
5345 } else {
5346 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5348 gen_load_fpr32h(fp0, rt);
5349 tcg_gen_ext_i32_tl(t0, fp0);
5350 tcg_temp_free(fp0);
5352 break;
5353 case 3:
5354 /* XXX: For now we support only a single FPU context. */
5355 tcg_gen_helper_1_1i(do_cfc1, t0, t0, rt);
5356 break;
5357 /* COP2: Not implemented. */
5358 case 4:
5359 case 5:
5360 /* fall through */
5361 default:
5362 goto die;
5364 #if defined MIPS_DEBUG_DISAS
5365 if (loglevel & CPU_LOG_TB_IN_ASM) {
5366 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5367 rt, u, sel, h);
5369 #endif
5370 gen_store_gpr(t0, rd);
5371 tcg_temp_free(t0);
5372 return;
5374 die:
5375 tcg_temp_free(t0);
5376 #if defined MIPS_DEBUG_DISAS
5377 if (loglevel & CPU_LOG_TB_IN_ASM) {
5378 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5379 rt, u, sel, h);
5381 #endif
5382 generate_exception(ctx, EXCP_RI);
5385 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5386 int u, int sel, int h)
5388 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5389 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5391 gen_load_gpr(t0, rt);
5392 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5393 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5394 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5395 /* NOP */ ;
5396 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5397 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5398 /* NOP */ ;
5399 else if (u == 0) {
5400 switch (rd) {
5401 case 2:
5402 switch (sel) {
5403 case 1:
5404 tcg_gen_helper_0_1(do_mttc0_tcstatus, t0);
5405 break;
5406 case 2:
5407 tcg_gen_helper_0_1(do_mttc0_tcbind, t0);
5408 break;
5409 case 3:
5410 tcg_gen_helper_0_1(do_mttc0_tcrestart, t0);
5411 break;
5412 case 4:
5413 tcg_gen_helper_0_1(do_mttc0_tchalt, t0);
5414 break;
5415 case 5:
5416 tcg_gen_helper_0_1(do_mttc0_tccontext, t0);
5417 break;
5418 case 6:
5419 tcg_gen_helper_0_1(do_mttc0_tcschedule, t0);
5420 break;
5421 case 7:
5422 tcg_gen_helper_0_1(do_mttc0_tcschefback, t0);
5423 break;
5424 default:
5425 gen_mtc0(env, ctx, t0, rd, sel);
5426 break;
5428 break;
5429 case 10:
5430 switch (sel) {
5431 case 0:
5432 tcg_gen_helper_0_1(do_mttc0_entryhi, t0);
5433 break;
5434 default:
5435 gen_mtc0(env, ctx, t0, rd, sel);
5436 break;
5438 case 12:
5439 switch (sel) {
5440 case 0:
5441 tcg_gen_helper_0_1(do_mttc0_status, t0);
5442 break;
5443 default:
5444 gen_mtc0(env, ctx, t0, rd, sel);
5445 break;
5447 case 23:
5448 switch (sel) {
5449 case 0:
5450 tcg_gen_helper_0_1(do_mttc0_debug, t0);
5451 break;
5452 default:
5453 gen_mtc0(env, ctx, t0, rd, sel);
5454 break;
5456 break;
5457 default:
5458 gen_mtc0(env, ctx, t0, rd, sel);
5460 } else switch (sel) {
5461 /* GPR registers. */
5462 case 0:
5463 tcg_gen_helper_0_1i(do_mttgpr, t0, rd);
5464 break;
5465 /* Auxiliary CPU registers */
5466 case 1:
5467 switch (rd) {
5468 case 0:
5469 tcg_gen_helper_0_1i(do_mttlo, t0, 0);
5470 break;
5471 case 1:
5472 tcg_gen_helper_0_1i(do_mtthi, t0, 0);
5473 break;
5474 case 2:
5475 tcg_gen_helper_0_1i(do_mttacx, t0, 0);
5476 break;
5477 case 4:
5478 tcg_gen_helper_0_1i(do_mttlo, t0, 1);
5479 break;
5480 case 5:
5481 tcg_gen_helper_0_1i(do_mtthi, t0, 1);
5482 break;
5483 case 6:
5484 tcg_gen_helper_0_1i(do_mttacx, t0, 1);
5485 break;
5486 case 8:
5487 tcg_gen_helper_0_1i(do_mttlo, t0, 2);
5488 break;
5489 case 9:
5490 tcg_gen_helper_0_1i(do_mtthi, t0, 2);
5491 break;
5492 case 10:
5493 tcg_gen_helper_0_1i(do_mttacx, t0, 2);
5494 break;
5495 case 12:
5496 tcg_gen_helper_0_1i(do_mttlo, t0, 3);
5497 break;
5498 case 13:
5499 tcg_gen_helper_0_1i(do_mtthi, t0, 3);
5500 break;
5501 case 14:
5502 tcg_gen_helper_0_1i(do_mttacx, t0, 3);
5503 break;
5504 case 16:
5505 tcg_gen_helper_0_1(do_mttdsp, t0);
5506 break;
5507 default:
5508 goto die;
5510 break;
5511 /* Floating point (COP1). */
5512 case 2:
5513 /* XXX: For now we support only a single FPU context. */
5514 if (h == 0) {
5515 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5517 tcg_gen_trunc_tl_i32(fp0, t0);
5518 gen_store_fpr32(fp0, rd);
5519 tcg_temp_free(fp0);
5520 } else {
5521 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5523 tcg_gen_trunc_tl_i32(fp0, t0);
5524 gen_store_fpr32h(fp0, rd);
5525 tcg_temp_free(fp0);
5527 break;
5528 case 3:
5529 /* XXX: For now we support only a single FPU context. */
5530 tcg_gen_helper_0_1i(do_ctc1, t0, rd);
5531 break;
5532 /* COP2: Not implemented. */
5533 case 4:
5534 case 5:
5535 /* fall through */
5536 default:
5537 goto die;
5539 #if defined MIPS_DEBUG_DISAS
5540 if (loglevel & CPU_LOG_TB_IN_ASM) {
5541 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5542 rd, u, sel, h);
5544 #endif
5545 tcg_temp_free(t0);
5546 return;
5548 die:
5549 tcg_temp_free(t0);
5550 #if defined MIPS_DEBUG_DISAS
5551 if (loglevel & CPU_LOG_TB_IN_ASM) {
5552 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5553 rd, u, sel, h);
5555 #endif
5556 generate_exception(ctx, EXCP_RI);
5559 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5561 const char *opn = "ldst";
5563 switch (opc) {
5564 case OPC_MFC0:
5565 if (rt == 0) {
5566 /* Treat as NOP. */
5567 return;
5570 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5572 gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5573 gen_store_gpr(t0, rt);
5574 tcg_temp_free(t0);
5576 opn = "mfc0";
5577 break;
5578 case OPC_MTC0:
5580 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5582 gen_load_gpr(t0, rt);
5583 save_cpu_state(ctx, 1);
5584 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5585 tcg_temp_free(t0);
5587 opn = "mtc0";
5588 break;
5589 #if defined(TARGET_MIPS64)
5590 case OPC_DMFC0:
5591 check_insn(env, ctx, ISA_MIPS3);
5592 if (rt == 0) {
5593 /* Treat as NOP. */
5594 return;
5597 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5599 gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5600 gen_store_gpr(t0, rt);
5601 tcg_temp_free(t0);
5603 opn = "dmfc0";
5604 break;
5605 case OPC_DMTC0:
5606 check_insn(env, ctx, ISA_MIPS3);
5608 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5610 gen_load_gpr(t0, rt);
5611 save_cpu_state(ctx, 1);
5612 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5613 tcg_temp_free(t0);
5615 opn = "dmtc0";
5616 break;
5617 #endif
5618 case OPC_MFTR:
5619 check_insn(env, ctx, ASE_MT);
5620 if (rd == 0) {
5621 /* Treat as NOP. */
5622 return;
5624 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5625 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5626 opn = "mftr";
5627 break;
5628 case OPC_MTTR:
5629 check_insn(env, ctx, ASE_MT);
5630 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5631 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5632 opn = "mttr";
5633 break;
5634 case OPC_TLBWI:
5635 opn = "tlbwi";
5636 if (!env->tlb->do_tlbwi)
5637 goto die;
5638 tcg_gen_helper_0_0(env->tlb->do_tlbwi);
5639 break;
5640 case OPC_TLBWR:
5641 opn = "tlbwr";
5642 if (!env->tlb->do_tlbwr)
5643 goto die;
5644 tcg_gen_helper_0_0(env->tlb->do_tlbwr);
5645 break;
5646 case OPC_TLBP:
5647 opn = "tlbp";
5648 if (!env->tlb->do_tlbp)
5649 goto die;
5650 tcg_gen_helper_0_0(env->tlb->do_tlbp);
5651 break;
5652 case OPC_TLBR:
5653 opn = "tlbr";
5654 if (!env->tlb->do_tlbr)
5655 goto die;
5656 tcg_gen_helper_0_0(env->tlb->do_tlbr);
5657 break;
5658 case OPC_ERET:
5659 opn = "eret";
5660 check_insn(env, ctx, ISA_MIPS2);
5661 save_cpu_state(ctx, 1);
5662 tcg_gen_helper_0_0(do_eret);
5663 ctx->bstate = BS_EXCP;
5664 break;
5665 case OPC_DERET:
5666 opn = "deret";
5667 check_insn(env, ctx, ISA_MIPS32);
5668 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5669 MIPS_INVAL(opn);
5670 generate_exception(ctx, EXCP_RI);
5671 } else {
5672 save_cpu_state(ctx, 1);
5673 tcg_gen_helper_0_0(do_deret);
5674 ctx->bstate = BS_EXCP;
5676 break;
5677 case OPC_WAIT:
5678 opn = "wait";
5679 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5680 /* If we get an exception, we want to restart at next instruction */
5681 ctx->pc += 4;
5682 save_cpu_state(ctx, 1);
5683 ctx->pc -= 4;
5684 tcg_gen_helper_0_0(do_wait);
5685 ctx->bstate = BS_EXCP;
5686 break;
5687 default:
5688 die:
5689 MIPS_INVAL(opn);
5690 generate_exception(ctx, EXCP_RI);
5691 return;
5693 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5695 #endif /* !CONFIG_USER_ONLY */
5697 /* CP1 Branches (before delay slot) */
5698 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5699 int32_t cc, int32_t offset)
5701 target_ulong btarget;
5702 const char *opn = "cp1 cond branch";
5703 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5704 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
5706 if (cc != 0)
5707 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5709 btarget = ctx->pc + 4 + offset;
5711 switch (op) {
5712 case OPC_BC1F:
5714 int l1 = gen_new_label();
5715 int l2 = gen_new_label();
5716 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5718 get_fp_cond(r_tmp1);
5719 tcg_gen_ext_i32_tl(t0, r_tmp1);
5720 tcg_temp_free(r_tmp1);
5721 tcg_gen_not_tl(t0, t0);
5722 tcg_gen_movi_tl(t1, 0x1 << cc);
5723 tcg_gen_and_tl(t0, t0, t1);
5724 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5725 tcg_gen_movi_tl(t0, 0);
5726 tcg_gen_br(l2);
5727 gen_set_label(l1);
5728 tcg_gen_movi_tl(t0, 1);
5729 gen_set_label(l2);
5731 opn = "bc1f";
5732 goto not_likely;
5733 case OPC_BC1FL:
5735 int l1 = gen_new_label();
5736 int l2 = gen_new_label();
5737 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5739 get_fp_cond(r_tmp1);
5740 tcg_gen_ext_i32_tl(t0, r_tmp1);
5741 tcg_temp_free(r_tmp1);
5742 tcg_gen_not_tl(t0, t0);
5743 tcg_gen_movi_tl(t1, 0x1 << cc);
5744 tcg_gen_and_tl(t0, t0, t1);
5745 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5746 tcg_gen_movi_tl(t0, 0);
5747 tcg_gen_br(l2);
5748 gen_set_label(l1);
5749 tcg_gen_movi_tl(t0, 1);
5750 gen_set_label(l2);
5752 opn = "bc1fl";
5753 goto likely;
5754 case OPC_BC1T:
5756 int l1 = gen_new_label();
5757 int l2 = gen_new_label();
5758 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5760 get_fp_cond(r_tmp1);
5761 tcg_gen_ext_i32_tl(t0, r_tmp1);
5762 tcg_temp_free(r_tmp1);
5763 tcg_gen_movi_tl(t1, 0x1 << cc);
5764 tcg_gen_and_tl(t0, t0, t1);
5765 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5766 tcg_gen_movi_tl(t0, 0);
5767 tcg_gen_br(l2);
5768 gen_set_label(l1);
5769 tcg_gen_movi_tl(t0, 1);
5770 gen_set_label(l2);
5772 opn = "bc1t";
5773 goto not_likely;
5774 case OPC_BC1TL:
5776 int l1 = gen_new_label();
5777 int l2 = gen_new_label();
5778 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5780 get_fp_cond(r_tmp1);
5781 tcg_gen_ext_i32_tl(t0, r_tmp1);
5782 tcg_temp_free(r_tmp1);
5783 tcg_gen_movi_tl(t1, 0x1 << cc);
5784 tcg_gen_and_tl(t0, t0, t1);
5785 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5786 tcg_gen_movi_tl(t0, 0);
5787 tcg_gen_br(l2);
5788 gen_set_label(l1);
5789 tcg_gen_movi_tl(t0, 1);
5790 gen_set_label(l2);
5792 opn = "bc1tl";
5793 likely:
5794 ctx->hflags |= MIPS_HFLAG_BL;
5795 tcg_gen_trunc_tl_i32(bcond, t0);
5796 break;
5797 case OPC_BC1FANY2:
5799 int l1 = gen_new_label();
5800 int l2 = gen_new_label();
5801 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5803 get_fp_cond(r_tmp1);
5804 tcg_gen_ext_i32_tl(t0, r_tmp1);
5805 tcg_temp_free(r_tmp1);
5806 tcg_gen_not_tl(t0, t0);
5807 tcg_gen_movi_tl(t1, 0x3 << cc);
5808 tcg_gen_and_tl(t0, t0, t1);
5809 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5810 tcg_gen_movi_tl(t0, 0);
5811 tcg_gen_br(l2);
5812 gen_set_label(l1);
5813 tcg_gen_movi_tl(t0, 1);
5814 gen_set_label(l2);
5816 opn = "bc1any2f";
5817 goto not_likely;
5818 case OPC_BC1TANY2:
5820 int l1 = gen_new_label();
5821 int l2 = gen_new_label();
5822 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5824 get_fp_cond(r_tmp1);
5825 tcg_gen_ext_i32_tl(t0, r_tmp1);
5826 tcg_temp_free(r_tmp1);
5827 tcg_gen_movi_tl(t1, 0x3 << cc);
5828 tcg_gen_and_tl(t0, t0, t1);
5829 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5830 tcg_gen_movi_tl(t0, 0);
5831 tcg_gen_br(l2);
5832 gen_set_label(l1);
5833 tcg_gen_movi_tl(t0, 1);
5834 gen_set_label(l2);
5836 opn = "bc1any2t";
5837 goto not_likely;
5838 case OPC_BC1FANY4:
5840 int l1 = gen_new_label();
5841 int l2 = gen_new_label();
5842 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5844 get_fp_cond(r_tmp1);
5845 tcg_gen_ext_i32_tl(t0, r_tmp1);
5846 tcg_temp_free(r_tmp1);
5847 tcg_gen_not_tl(t0, t0);
5848 tcg_gen_movi_tl(t1, 0xf << cc);
5849 tcg_gen_and_tl(t0, t0, t1);
5850 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5851 tcg_gen_movi_tl(t0, 0);
5852 tcg_gen_br(l2);
5853 gen_set_label(l1);
5854 tcg_gen_movi_tl(t0, 1);
5855 gen_set_label(l2);
5857 opn = "bc1any4f";
5858 goto not_likely;
5859 case OPC_BC1TANY4:
5861 int l1 = gen_new_label();
5862 int l2 = gen_new_label();
5863 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5865 get_fp_cond(r_tmp1);
5866 tcg_gen_ext_i32_tl(t0, r_tmp1);
5867 tcg_temp_free(r_tmp1);
5868 tcg_gen_movi_tl(t1, 0xf << cc);
5869 tcg_gen_and_tl(t0, t0, t1);
5870 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5871 tcg_gen_movi_tl(t0, 0);
5872 tcg_gen_br(l2);
5873 gen_set_label(l1);
5874 tcg_gen_movi_tl(t0, 1);
5875 gen_set_label(l2);
5877 opn = "bc1any4t";
5878 not_likely:
5879 ctx->hflags |= MIPS_HFLAG_BC;
5880 tcg_gen_trunc_tl_i32(bcond, t0);
5881 break;
5882 default:
5883 MIPS_INVAL(opn);
5884 generate_exception (ctx, EXCP_RI);
5885 goto out;
5887 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5888 ctx->hflags, btarget);
5889 ctx->btarget = btarget;
5891 out:
5892 tcg_temp_free(t0);
5893 tcg_temp_free(t1);
5896 /* Coprocessor 1 (FPU) */
5898 #define FOP(func, fmt) (((fmt) << 21) | (func))
5900 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5902 const char *opn = "cp1 move";
5903 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5905 switch (opc) {
5906 case OPC_MFC1:
5908 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5910 gen_load_fpr32(fp0, fs);
5911 tcg_gen_ext_i32_tl(t0, fp0);
5912 tcg_temp_free(fp0);
5914 gen_store_gpr(t0, rt);
5915 opn = "mfc1";
5916 break;
5917 case OPC_MTC1:
5918 gen_load_gpr(t0, rt);
5920 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5922 tcg_gen_trunc_tl_i32(fp0, t0);
5923 gen_store_fpr32(fp0, fs);
5924 tcg_temp_free(fp0);
5926 opn = "mtc1";
5927 break;
5928 case OPC_CFC1:
5929 tcg_gen_helper_1_i(do_cfc1, t0, fs);
5930 gen_store_gpr(t0, rt);
5931 opn = "cfc1";
5932 break;
5933 case OPC_CTC1:
5934 gen_load_gpr(t0, rt);
5935 tcg_gen_helper_0_1i(do_ctc1, t0, fs);
5936 opn = "ctc1";
5937 break;
5938 case OPC_DMFC1:
5940 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
5942 gen_load_fpr64(ctx, fp0, fs);
5943 tcg_gen_mov_tl(t0, fp0);
5944 tcg_temp_free(fp0);
5946 gen_store_gpr(t0, rt);
5947 opn = "dmfc1";
5948 break;
5949 case OPC_DMTC1:
5950 gen_load_gpr(t0, rt);
5952 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
5954 tcg_gen_mov_tl(fp0, t0);
5955 gen_store_fpr64(ctx, fp0, fs);
5956 tcg_temp_free(fp0);
5958 opn = "dmtc1";
5959 break;
5960 case OPC_MFHC1:
5962 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5964 gen_load_fpr32h(fp0, fs);
5965 tcg_gen_ext_i32_tl(t0, fp0);
5966 tcg_temp_free(fp0);
5968 gen_store_gpr(t0, rt);
5969 opn = "mfhc1";
5970 break;
5971 case OPC_MTHC1:
5972 gen_load_gpr(t0, rt);
5974 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5976 tcg_gen_trunc_tl_i32(fp0, t0);
5977 gen_store_fpr32h(fp0, fs);
5978 tcg_temp_free(fp0);
5980 opn = "mthc1";
5981 break;
5982 default:
5983 MIPS_INVAL(opn);
5984 generate_exception (ctx, EXCP_RI);
5985 goto out;
5987 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5989 out:
5990 tcg_temp_free(t0);
5993 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5995 int l1 = gen_new_label();
5996 uint32_t ccbit;
5997 TCGCond cond;
5998 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5999 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
6000 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_I32);
6002 if (cc)
6003 ccbit = 1 << (24 + cc);
6004 else
6005 ccbit = 1 << 23;
6006 if (tf)
6007 cond = TCG_COND_EQ;
6008 else
6009 cond = TCG_COND_NE;
6011 gen_load_gpr(t0, rd);
6012 gen_load_gpr(t1, rs);
6013 tcg_gen_ld_i32(r_tmp, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
6014 tcg_gen_andi_i32(r_tmp, r_tmp, ccbit);
6015 tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
6016 tcg_temp_free(r_tmp);
6018 tcg_gen_mov_tl(t0, t1);
6019 tcg_temp_free(t1);
6021 gen_set_label(l1);
6022 gen_store_gpr(t0, rd);
6023 tcg_temp_free(t0);
6026 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6028 uint32_t ccbit;
6029 int cond;
6030 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
6031 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6032 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
6033 int l1 = gen_new_label();
6035 if (cc)
6036 ccbit = 1 << (24 + cc);
6037 else
6038 ccbit = 1 << 23;
6040 if (tf)
6041 cond = TCG_COND_EQ;
6042 else
6043 cond = TCG_COND_NE;
6045 gen_load_fpr32(fp0, fs);
6046 gen_load_fpr32(fp1, fd);
6047 tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
6048 tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit);
6049 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
6050 tcg_gen_movi_i32(fp1, fp0);
6051 tcg_temp_free(fp0);
6052 gen_set_label(l1);
6053 tcg_temp_free(r_tmp1);
6054 gen_store_fpr32(fp1, fd);
6055 tcg_temp_free(fp1);
6058 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6060 uint32_t ccbit;
6061 int cond;
6062 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
6063 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
6064 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I64);
6065 int l1 = gen_new_label();
6067 if (cc)
6068 ccbit = 1 << (24 + cc);
6069 else
6070 ccbit = 1 << 23;
6072 if (tf)
6073 cond = TCG_COND_EQ;
6074 else
6075 cond = TCG_COND_NE;
6077 gen_load_fpr64(ctx, fp0, fs);
6078 gen_load_fpr64(ctx, fp1, fd);
6079 tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
6080 tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit);
6081 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
6082 tcg_gen_movi_i64(fp1, fp0);
6083 tcg_temp_free(fp0);
6084 gen_set_label(l1);
6085 tcg_temp_free(r_tmp1);
6086 gen_store_fpr64(ctx, fp1, fd);
6087 tcg_temp_free(fp1);
6090 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6092 int cond;
6093 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
6094 TCGv r_tmp2 = tcg_temp_local_new(TCG_TYPE_I32);
6095 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6096 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
6097 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
6098 TCGv fph1 = tcg_temp_local_new(TCG_TYPE_I32);
6099 int l1 = gen_new_label();
6100 int l2 = gen_new_label();
6102 if (tf)
6103 cond = TCG_COND_EQ;
6104 else
6105 cond = TCG_COND_NE;
6107 gen_load_fpr32(fp0, fs);
6108 gen_load_fpr32h(fph0, fs);
6109 gen_load_fpr32(fp1, fd);
6110 gen_load_fpr32h(fph1, fd);
6111 get_fp_cond(r_tmp1);
6112 tcg_gen_shri_i32(r_tmp1, r_tmp1, cc);
6113 tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x1);
6114 tcg_gen_brcondi_i32(cond, r_tmp2, 0, l1);
6115 tcg_gen_movi_i32(fp1, fp0);
6116 tcg_temp_free(fp0);
6117 gen_set_label(l1);
6118 tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x2);
6119 tcg_gen_brcondi_i32(cond, r_tmp2, 0, l2);
6120 tcg_gen_movi_i32(fph1, fph0);
6121 tcg_temp_free(fph0);
6122 gen_set_label(l2);
6123 tcg_temp_free(r_tmp1);
6124 tcg_temp_free(r_tmp2);
6125 gen_store_fpr32(fp1, fd);
6126 gen_store_fpr32h(fph1, fd);
6127 tcg_temp_free(fp1);
6128 tcg_temp_free(fph1);
6132 static void gen_farith (DisasContext *ctx, uint32_t op1,
6133 int ft, int fs, int fd, int cc)
6135 const char *opn = "farith";
6136 const char *condnames[] = {
6137 "c.f",
6138 "c.un",
6139 "c.eq",
6140 "c.ueq",
6141 "c.olt",
6142 "c.ult",
6143 "c.ole",
6144 "c.ule",
6145 "c.sf",
6146 "c.ngle",
6147 "c.seq",
6148 "c.ngl",
6149 "c.lt",
6150 "c.nge",
6151 "c.le",
6152 "c.ngt",
6154 const char *condnames_abs[] = {
6155 "cabs.f",
6156 "cabs.un",
6157 "cabs.eq",
6158 "cabs.ueq",
6159 "cabs.olt",
6160 "cabs.ult",
6161 "cabs.ole",
6162 "cabs.ule",
6163 "cabs.sf",
6164 "cabs.ngle",
6165 "cabs.seq",
6166 "cabs.ngl",
6167 "cabs.lt",
6168 "cabs.nge",
6169 "cabs.le",
6170 "cabs.ngt",
6172 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6173 uint32_t func = ctx->opcode & 0x3f;
6175 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
6176 case FOP(0, 16):
6178 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6179 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6181 gen_load_fpr32(fp0, fs);
6182 gen_load_fpr32(fp1, ft);
6183 tcg_gen_helper_1_2(do_float_add_s, fp0, fp0, fp1);
6184 tcg_temp_free(fp1);
6185 gen_store_fpr32(fp0, fd);
6186 tcg_temp_free(fp0);
6188 opn = "add.s";
6189 optype = BINOP;
6190 break;
6191 case FOP(1, 16):
6193 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6194 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6196 gen_load_fpr32(fp0, fs);
6197 gen_load_fpr32(fp1, ft);
6198 tcg_gen_helper_1_2(do_float_sub_s, fp0, fp0, fp1);
6199 tcg_temp_free(fp1);
6200 gen_store_fpr32(fp0, fd);
6201 tcg_temp_free(fp0);
6203 opn = "sub.s";
6204 optype = BINOP;
6205 break;
6206 case FOP(2, 16):
6208 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6209 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6211 gen_load_fpr32(fp0, fs);
6212 gen_load_fpr32(fp1, ft);
6213 tcg_gen_helper_1_2(do_float_mul_s, fp0, fp0, fp1);
6214 tcg_temp_free(fp1);
6215 gen_store_fpr32(fp0, fd);
6216 tcg_temp_free(fp0);
6218 opn = "mul.s";
6219 optype = BINOP;
6220 break;
6221 case FOP(3, 16):
6223 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6224 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6226 gen_load_fpr32(fp0, fs);
6227 gen_load_fpr32(fp1, ft);
6228 tcg_gen_helper_1_2(do_float_div_s, fp0, fp0, fp1);
6229 tcg_temp_free(fp1);
6230 gen_store_fpr32(fp0, fd);
6231 tcg_temp_free(fp0);
6233 opn = "div.s";
6234 optype = BINOP;
6235 break;
6236 case FOP(4, 16):
6238 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6240 gen_load_fpr32(fp0, fs);
6241 tcg_gen_helper_1_1(do_float_sqrt_s, fp0, fp0);
6242 gen_store_fpr32(fp0, fd);
6243 tcg_temp_free(fp0);
6245 opn = "sqrt.s";
6246 break;
6247 case FOP(5, 16):
6249 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6251 gen_load_fpr32(fp0, fs);
6252 tcg_gen_helper_1_1(do_float_abs_s, fp0, fp0);
6253 gen_store_fpr32(fp0, fd);
6254 tcg_temp_free(fp0);
6256 opn = "abs.s";
6257 break;
6258 case FOP(6, 16):
6260 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6262 gen_load_fpr32(fp0, fs);
6263 gen_store_fpr32(fp0, fd);
6264 tcg_temp_free(fp0);
6266 opn = "mov.s";
6267 break;
6268 case FOP(7, 16):
6270 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6272 gen_load_fpr32(fp0, fs);
6273 tcg_gen_helper_1_1(do_float_chs_s, fp0, fp0);
6274 gen_store_fpr32(fp0, fd);
6275 tcg_temp_free(fp0);
6277 opn = "neg.s";
6278 break;
6279 case FOP(8, 16):
6280 check_cp1_64bitmode(ctx);
6282 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6283 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6285 gen_load_fpr32(fp32, fs);
6286 tcg_gen_helper_1_1(do_float_roundl_s, fp64, fp32);
6287 tcg_temp_free(fp32);
6288 gen_store_fpr64(ctx, fp64, fd);
6289 tcg_temp_free(fp64);
6291 opn = "round.l.s";
6292 break;
6293 case FOP(9, 16):
6294 check_cp1_64bitmode(ctx);
6296 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6297 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6299 gen_load_fpr32(fp32, fs);
6300 tcg_gen_helper_1_1(do_float_truncl_s, fp64, fp32);
6301 tcg_temp_free(fp32);
6302 gen_store_fpr64(ctx, fp64, fd);
6303 tcg_temp_free(fp64);
6305 opn = "trunc.l.s";
6306 break;
6307 case FOP(10, 16):
6308 check_cp1_64bitmode(ctx);
6310 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6311 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6313 gen_load_fpr32(fp32, fs);
6314 tcg_gen_helper_1_1(do_float_ceill_s, fp64, fp32);
6315 tcg_temp_free(fp32);
6316 gen_store_fpr64(ctx, fp64, fd);
6317 tcg_temp_free(fp64);
6319 opn = "ceil.l.s";
6320 break;
6321 case FOP(11, 16):
6322 check_cp1_64bitmode(ctx);
6324 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6325 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6327 gen_load_fpr32(fp32, fs);
6328 tcg_gen_helper_1_1(do_float_floorl_s, fp64, fp32);
6329 tcg_temp_free(fp32);
6330 gen_store_fpr64(ctx, fp64, fd);
6331 tcg_temp_free(fp64);
6333 opn = "floor.l.s";
6334 break;
6335 case FOP(12, 16):
6337 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6339 gen_load_fpr32(fp0, fs);
6340 tcg_gen_helper_1_1(do_float_roundw_s, fp0, fp0);
6341 gen_store_fpr32(fp0, fd);
6342 tcg_temp_free(fp0);
6344 opn = "round.w.s";
6345 break;
6346 case FOP(13, 16):
6348 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6350 gen_load_fpr32(fp0, fs);
6351 tcg_gen_helper_1_1(do_float_truncw_s, fp0, fp0);
6352 gen_store_fpr32(fp0, fd);
6353 tcg_temp_free(fp0);
6355 opn = "trunc.w.s";
6356 break;
6357 case FOP(14, 16):
6359 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6361 gen_load_fpr32(fp0, fs);
6362 tcg_gen_helper_1_1(do_float_ceilw_s, fp0, fp0);
6363 gen_store_fpr32(fp0, fd);
6364 tcg_temp_free(fp0);
6366 opn = "ceil.w.s";
6367 break;
6368 case FOP(15, 16):
6370 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6372 gen_load_fpr32(fp0, fs);
6373 tcg_gen_helper_1_1(do_float_floorw_s, fp0, fp0);
6374 gen_store_fpr32(fp0, fd);
6375 tcg_temp_free(fp0);
6377 opn = "floor.w.s";
6378 break;
6379 case FOP(17, 16):
6380 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6381 opn = "movcf.s";
6382 break;
6383 case FOP(18, 16):
6385 int l1 = gen_new_label();
6386 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6387 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6389 gen_load_gpr(t0, ft);
6390 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6391 tcg_temp_free(t0);
6392 gen_load_fpr32(fp0, fs);
6393 gen_store_fpr32(fp0, fd);
6394 tcg_temp_free(fp0);
6395 gen_set_label(l1);
6397 opn = "movz.s";
6398 break;
6399 case FOP(19, 16):
6401 int l1 = gen_new_label();
6402 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6403 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6405 gen_load_gpr(t0, ft);
6406 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6407 tcg_temp_free(t0);
6408 gen_load_fpr32(fp0, fs);
6409 gen_store_fpr32(fp0, fd);
6410 tcg_temp_free(fp0);
6411 gen_set_label(l1);
6413 opn = "movn.s";
6414 break;
6415 case FOP(21, 16):
6416 check_cop1x(ctx);
6418 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6420 gen_load_fpr32(fp0, fs);
6421 tcg_gen_helper_1_1(do_float_recip_s, fp0, fp0);
6422 gen_store_fpr32(fp0, fd);
6423 tcg_temp_free(fp0);
6425 opn = "recip.s";
6426 break;
6427 case FOP(22, 16):
6428 check_cop1x(ctx);
6430 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6432 gen_load_fpr32(fp0, fs);
6433 tcg_gen_helper_1_1(do_float_rsqrt_s, fp0, fp0);
6434 gen_store_fpr32(fp0, fd);
6435 tcg_temp_free(fp0);
6437 opn = "rsqrt.s";
6438 break;
6439 case FOP(28, 16):
6440 check_cp1_64bitmode(ctx);
6442 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6443 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6445 gen_load_fpr32(fp0, fs);
6446 gen_load_fpr32(fp1, fd);
6447 tcg_gen_helper_1_2(do_float_recip2_s, fp0, fp0, fp1);
6448 tcg_temp_free(fp1);
6449 gen_store_fpr32(fp0, fd);
6450 tcg_temp_free(fp0);
6452 opn = "recip2.s";
6453 break;
6454 case FOP(29, 16):
6455 check_cp1_64bitmode(ctx);
6457 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6459 gen_load_fpr32(fp0, fs);
6460 tcg_gen_helper_1_1(do_float_recip1_s, fp0, fp0);
6461 gen_store_fpr32(fp0, fd);
6462 tcg_temp_free(fp0);
6464 opn = "recip1.s";
6465 break;
6466 case FOP(30, 16):
6467 check_cp1_64bitmode(ctx);
6469 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6471 gen_load_fpr32(fp0, fs);
6472 tcg_gen_helper_1_1(do_float_rsqrt1_s, fp0, fp0);
6473 gen_store_fpr32(fp0, fd);
6474 tcg_temp_free(fp0);
6476 opn = "rsqrt1.s";
6477 break;
6478 case FOP(31, 16):
6479 check_cp1_64bitmode(ctx);
6481 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6482 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6484 gen_load_fpr32(fp0, fs);
6485 gen_load_fpr32(fp1, ft);
6486 tcg_gen_helper_1_2(do_float_rsqrt2_s, fp0, fp0, fp1);
6487 tcg_temp_free(fp1);
6488 gen_store_fpr32(fp0, fd);
6489 tcg_temp_free(fp0);
6491 opn = "rsqrt2.s";
6492 break;
6493 case FOP(33, 16):
6494 check_cp1_registers(ctx, fd);
6496 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6497 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6499 gen_load_fpr32(fp32, fs);
6500 tcg_gen_helper_1_1(do_float_cvtd_s, fp64, fp32);
6501 tcg_temp_free(fp32);
6502 gen_store_fpr64(ctx, fp64, fd);
6503 tcg_temp_free(fp64);
6505 opn = "cvt.d.s";
6506 break;
6507 case FOP(36, 16):
6509 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6511 gen_load_fpr32(fp0, fs);
6512 tcg_gen_helper_1_1(do_float_cvtw_s, fp0, fp0);
6513 gen_store_fpr32(fp0, fd);
6514 tcg_temp_free(fp0);
6516 opn = "cvt.w.s";
6517 break;
6518 case FOP(37, 16):
6519 check_cp1_64bitmode(ctx);
6521 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6522 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6524 gen_load_fpr32(fp32, fs);
6525 tcg_gen_helper_1_1(do_float_cvtl_s, fp64, fp32);
6526 tcg_temp_free(fp32);
6527 gen_store_fpr64(ctx, fp64, fd);
6528 tcg_temp_free(fp64);
6530 opn = "cvt.l.s";
6531 break;
6532 case FOP(38, 16):
6533 check_cp1_64bitmode(ctx);
6535 TCGv fp64_0 = tcg_temp_new(TCG_TYPE_I64);
6536 TCGv fp64_1 = tcg_temp_new(TCG_TYPE_I64);
6537 TCGv fp32_0 = tcg_temp_new(TCG_TYPE_I32);
6538 TCGv fp32_1 = tcg_temp_new(TCG_TYPE_I32);
6540 gen_load_fpr32(fp32_0, fs);
6541 gen_load_fpr32(fp32_1, ft);
6542 tcg_gen_extu_i32_i64(fp64_0, fp32_0);
6543 tcg_gen_extu_i32_i64(fp64_1, fp32_1);
6544 tcg_temp_free(fp32_0);
6545 tcg_temp_free(fp32_1);
6546 tcg_gen_shli_i64(fp64_1, fp64_1, 32);
6547 tcg_gen_or_i64(fp64_0, fp64_0, fp64_1);
6548 tcg_temp_free(fp64_1);
6549 gen_store_fpr64(ctx, fp64_0, fd);
6550 tcg_temp_free(fp64_0);
6552 opn = "cvt.ps.s";
6553 break;
6554 case FOP(48, 16):
6555 case FOP(49, 16):
6556 case FOP(50, 16):
6557 case FOP(51, 16):
6558 case FOP(52, 16):
6559 case FOP(53, 16):
6560 case FOP(54, 16):
6561 case FOP(55, 16):
6562 case FOP(56, 16):
6563 case FOP(57, 16):
6564 case FOP(58, 16):
6565 case FOP(59, 16):
6566 case FOP(60, 16):
6567 case FOP(61, 16):
6568 case FOP(62, 16):
6569 case FOP(63, 16):
6571 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6572 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6574 gen_load_fpr32(fp0, fs);
6575 gen_load_fpr32(fp1, ft);
6576 if (ctx->opcode & (1 << 6)) {
6577 check_cop1x(ctx);
6578 gen_cmpabs_s(func-48, fp0, fp1, cc);
6579 opn = condnames_abs[func-48];
6580 } else {
6581 gen_cmp_s(func-48, fp0, fp1, cc);
6582 opn = condnames[func-48];
6584 tcg_temp_free(fp0);
6585 tcg_temp_free(fp1);
6587 break;
6588 case FOP(0, 17):
6589 check_cp1_registers(ctx, fs | ft | fd);
6591 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6592 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6594 gen_load_fpr64(ctx, fp0, fs);
6595 gen_load_fpr64(ctx, fp1, ft);
6596 tcg_gen_helper_1_2(do_float_add_d, fp0, fp0, fp1);
6597 tcg_temp_free(fp1);
6598 gen_store_fpr64(ctx, fp0, fd);
6599 tcg_temp_free(fp0);
6601 opn = "add.d";
6602 optype = BINOP;
6603 break;
6604 case FOP(1, 17):
6605 check_cp1_registers(ctx, fs | ft | fd);
6607 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6608 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6610 gen_load_fpr64(ctx, fp0, fs);
6611 gen_load_fpr64(ctx, fp1, ft);
6612 tcg_gen_helper_1_2(do_float_sub_d, fp0, fp0, fp1);
6613 tcg_temp_free(fp1);
6614 gen_store_fpr64(ctx, fp0, fd);
6615 tcg_temp_free(fp0);
6617 opn = "sub.d";
6618 optype = BINOP;
6619 break;
6620 case FOP(2, 17):
6621 check_cp1_registers(ctx, fs | ft | fd);
6623 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6624 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6626 gen_load_fpr64(ctx, fp0, fs);
6627 gen_load_fpr64(ctx, fp1, ft);
6628 tcg_gen_helper_1_2(do_float_mul_d, fp0, fp0, fp1);
6629 tcg_temp_free(fp1);
6630 gen_store_fpr64(ctx, fp0, fd);
6631 tcg_temp_free(fp0);
6633 opn = "mul.d";
6634 optype = BINOP;
6635 break;
6636 case FOP(3, 17):
6637 check_cp1_registers(ctx, fs | ft | fd);
6639 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6640 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6642 gen_load_fpr64(ctx, fp0, fs);
6643 gen_load_fpr64(ctx, fp1, ft);
6644 tcg_gen_helper_1_2(do_float_div_d, fp0, fp0, fp1);
6645 tcg_temp_free(fp1);
6646 gen_store_fpr64(ctx, fp0, fd);
6647 tcg_temp_free(fp0);
6649 opn = "div.d";
6650 optype = BINOP;
6651 break;
6652 case FOP(4, 17):
6653 check_cp1_registers(ctx, fs | fd);
6655 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6657 gen_load_fpr64(ctx, fp0, fs);
6658 tcg_gen_helper_1_1(do_float_sqrt_d, fp0, fp0);
6659 gen_store_fpr64(ctx, fp0, fd);
6660 tcg_temp_free(fp0);
6662 opn = "sqrt.d";
6663 break;
6664 case FOP(5, 17):
6665 check_cp1_registers(ctx, fs | fd);
6667 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6669 gen_load_fpr64(ctx, fp0, fs);
6670 tcg_gen_helper_1_1(do_float_abs_d, fp0, fp0);
6671 gen_store_fpr64(ctx, fp0, fd);
6672 tcg_temp_free(fp0);
6674 opn = "abs.d";
6675 break;
6676 case FOP(6, 17):
6677 check_cp1_registers(ctx, fs | fd);
6679 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6681 gen_load_fpr64(ctx, fp0, fs);
6682 gen_store_fpr64(ctx, fp0, fd);
6683 tcg_temp_free(fp0);
6685 opn = "mov.d";
6686 break;
6687 case FOP(7, 17):
6688 check_cp1_registers(ctx, fs | fd);
6690 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6692 gen_load_fpr64(ctx, fp0, fs);
6693 tcg_gen_helper_1_1(do_float_chs_d, fp0, fp0);
6694 gen_store_fpr64(ctx, fp0, fd);
6695 tcg_temp_free(fp0);
6697 opn = "neg.d";
6698 break;
6699 case FOP(8, 17):
6700 check_cp1_64bitmode(ctx);
6702 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6704 gen_load_fpr64(ctx, fp0, fs);
6705 tcg_gen_helper_1_1(do_float_roundl_d, fp0, fp0);
6706 gen_store_fpr64(ctx, fp0, fd);
6707 tcg_temp_free(fp0);
6709 opn = "round.l.d";
6710 break;
6711 case FOP(9, 17):
6712 check_cp1_64bitmode(ctx);
6714 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6716 gen_load_fpr64(ctx, fp0, fs);
6717 tcg_gen_helper_1_1(do_float_truncl_d, fp0, fp0);
6718 gen_store_fpr64(ctx, fp0, fd);
6719 tcg_temp_free(fp0);
6721 opn = "trunc.l.d";
6722 break;
6723 case FOP(10, 17):
6724 check_cp1_64bitmode(ctx);
6726 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6728 gen_load_fpr64(ctx, fp0, fs);
6729 tcg_gen_helper_1_1(do_float_ceill_d, fp0, fp0);
6730 gen_store_fpr64(ctx, fp0, fd);
6731 tcg_temp_free(fp0);
6733 opn = "ceil.l.d";
6734 break;
6735 case FOP(11, 17):
6736 check_cp1_64bitmode(ctx);
6738 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6740 gen_load_fpr64(ctx, fp0, fs);
6741 tcg_gen_helper_1_1(do_float_floorl_d, fp0, fp0);
6742 gen_store_fpr64(ctx, fp0, fd);
6743 tcg_temp_free(fp0);
6745 opn = "floor.l.d";
6746 break;
6747 case FOP(12, 17):
6748 check_cp1_registers(ctx, fs);
6750 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6751 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6753 gen_load_fpr64(ctx, fp64, fs);
6754 tcg_gen_helper_1_1(do_float_roundw_d, fp32, fp64);
6755 tcg_temp_free(fp64);
6756 gen_store_fpr32(fp32, fd);
6757 tcg_temp_free(fp32);
6759 opn = "round.w.d";
6760 break;
6761 case FOP(13, 17):
6762 check_cp1_registers(ctx, fs);
6764 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6765 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6767 gen_load_fpr64(ctx, fp64, fs);
6768 tcg_gen_helper_1_1(do_float_truncw_d, fp32, fp64);
6769 tcg_temp_free(fp64);
6770 gen_store_fpr32(fp32, fd);
6771 tcg_temp_free(fp32);
6773 opn = "trunc.w.d";
6774 break;
6775 case FOP(14, 17):
6776 check_cp1_registers(ctx, fs);
6778 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6779 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6781 gen_load_fpr64(ctx, fp64, fs);
6782 tcg_gen_helper_1_1(do_float_ceilw_d, fp32, fp64);
6783 tcg_temp_free(fp64);
6784 gen_store_fpr32(fp32, fd);
6785 tcg_temp_free(fp32);
6787 opn = "ceil.w.d";
6788 break;
6789 case FOP(15, 17):
6790 check_cp1_registers(ctx, fs);
6792 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6793 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6795 gen_load_fpr64(ctx, fp64, fs);
6796 tcg_gen_helper_1_1(do_float_floorw_d, fp32, fp64);
6797 tcg_temp_free(fp64);
6798 gen_store_fpr32(fp32, fd);
6799 tcg_temp_free(fp32);
6801 opn = "floor.w.d";
6802 break;
6803 case FOP(17, 17):
6804 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6805 opn = "movcf.d";
6806 break;
6807 case FOP(18, 17):
6809 int l1 = gen_new_label();
6810 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6811 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
6813 gen_load_gpr(t0, ft);
6814 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6815 tcg_temp_free(t0);
6816 gen_load_fpr64(ctx, fp0, fs);
6817 gen_store_fpr64(ctx, fp0, fd);
6818 tcg_temp_free(fp0);
6819 gen_set_label(l1);
6821 opn = "movz.d";
6822 break;
6823 case FOP(19, 17):
6825 int l1 = gen_new_label();
6826 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6827 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
6829 gen_load_gpr(t0, ft);
6830 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6831 tcg_temp_free(t0);
6832 gen_load_fpr64(ctx, fp0, fs);
6833 gen_store_fpr64(ctx, fp0, fd);
6834 tcg_temp_free(fp0);
6835 gen_set_label(l1);
6837 opn = "movn.d";
6838 break;
6839 case FOP(21, 17):
6840 check_cp1_64bitmode(ctx);
6842 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6844 gen_load_fpr64(ctx, fp0, fs);
6845 tcg_gen_helper_1_1(do_float_recip_d, fp0, fp0);
6846 gen_store_fpr64(ctx, fp0, fd);
6847 tcg_temp_free(fp0);
6849 opn = "recip.d";
6850 break;
6851 case FOP(22, 17):
6852 check_cp1_64bitmode(ctx);
6854 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6856 gen_load_fpr64(ctx, fp0, fs);
6857 tcg_gen_helper_1_1(do_float_rsqrt_d, fp0, fp0);
6858 gen_store_fpr64(ctx, fp0, fd);
6859 tcg_temp_free(fp0);
6861 opn = "rsqrt.d";
6862 break;
6863 case FOP(28, 17):
6864 check_cp1_64bitmode(ctx);
6866 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6867 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6869 gen_load_fpr64(ctx, fp0, fs);
6870 gen_load_fpr64(ctx, fp1, ft);
6871 tcg_gen_helper_1_2(do_float_recip2_d, fp0, fp0, fp1);
6872 tcg_temp_free(fp1);
6873 gen_store_fpr64(ctx, fp0, fd);
6874 tcg_temp_free(fp0);
6876 opn = "recip2.d";
6877 break;
6878 case FOP(29, 17):
6879 check_cp1_64bitmode(ctx);
6881 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6883 gen_load_fpr64(ctx, fp0, fs);
6884 tcg_gen_helper_1_1(do_float_recip1_d, fp0, fp0);
6885 gen_store_fpr64(ctx, fp0, fd);
6886 tcg_temp_free(fp0);
6888 opn = "recip1.d";
6889 break;
6890 case FOP(30, 17):
6891 check_cp1_64bitmode(ctx);
6893 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6895 gen_load_fpr64(ctx, fp0, fs);
6896 tcg_gen_helper_1_1(do_float_rsqrt1_d, fp0, fp0);
6897 gen_store_fpr64(ctx, fp0, fd);
6898 tcg_temp_free(fp0);
6900 opn = "rsqrt1.d";
6901 break;
6902 case FOP(31, 17):
6903 check_cp1_64bitmode(ctx);
6905 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6906 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6908 gen_load_fpr64(ctx, fp0, fs);
6909 gen_load_fpr64(ctx, fp1, ft);
6910 tcg_gen_helper_1_2(do_float_rsqrt2_d, fp0, fp0, fp1);
6911 tcg_temp_free(fp1);
6912 gen_store_fpr64(ctx, fp0, fd);
6913 tcg_temp_free(fp0);
6915 opn = "rsqrt2.d";
6916 break;
6917 case FOP(48, 17):
6918 case FOP(49, 17):
6919 case FOP(50, 17):
6920 case FOP(51, 17):
6921 case FOP(52, 17):
6922 case FOP(53, 17):
6923 case FOP(54, 17):
6924 case FOP(55, 17):
6925 case FOP(56, 17):
6926 case FOP(57, 17):
6927 case FOP(58, 17):
6928 case FOP(59, 17):
6929 case FOP(60, 17):
6930 case FOP(61, 17):
6931 case FOP(62, 17):
6932 case FOP(63, 17):
6934 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6935 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6937 gen_load_fpr64(ctx, fp0, fs);
6938 gen_load_fpr64(ctx, fp1, ft);
6939 if (ctx->opcode & (1 << 6)) {
6940 check_cop1x(ctx);
6941 check_cp1_registers(ctx, fs | ft);
6942 gen_cmpabs_d(func-48, fp0, fp1, cc);
6943 opn = condnames_abs[func-48];
6944 } else {
6945 check_cp1_registers(ctx, fs | ft);
6946 gen_cmp_d(func-48, fp0, fp1, cc);
6947 opn = condnames[func-48];
6949 tcg_temp_free(fp0);
6950 tcg_temp_free(fp1);
6952 break;
6953 case FOP(32, 17):
6954 check_cp1_registers(ctx, fs);
6956 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6957 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6959 gen_load_fpr64(ctx, fp64, fs);
6960 tcg_gen_helper_1_1(do_float_cvts_d, fp32, fp64);
6961 tcg_temp_free(fp64);
6962 gen_store_fpr32(fp32, fd);
6963 tcg_temp_free(fp32);
6965 opn = "cvt.s.d";
6966 break;
6967 case FOP(36, 17):
6968 check_cp1_registers(ctx, fs);
6970 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6971 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6973 gen_load_fpr64(ctx, fp64, fs);
6974 tcg_gen_helper_1_1(do_float_cvtw_d, fp32, fp64);
6975 tcg_temp_free(fp64);
6976 gen_store_fpr32(fp32, fd);
6977 tcg_temp_free(fp32);
6979 opn = "cvt.w.d";
6980 break;
6981 case FOP(37, 17):
6982 check_cp1_64bitmode(ctx);
6984 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6986 gen_load_fpr64(ctx, fp0, fs);
6987 tcg_gen_helper_1_1(do_float_cvtl_d, fp0, fp0);
6988 gen_store_fpr64(ctx, fp0, fd);
6989 tcg_temp_free(fp0);
6991 opn = "cvt.l.d";
6992 break;
6993 case FOP(32, 20):
6995 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6997 gen_load_fpr32(fp0, fs);
6998 tcg_gen_helper_1_1(do_float_cvts_w, fp0, fp0);
6999 gen_store_fpr32(fp0, fd);
7000 tcg_temp_free(fp0);
7002 opn = "cvt.s.w";
7003 break;
7004 case FOP(33, 20):
7005 check_cp1_registers(ctx, fd);
7007 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
7008 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
7010 gen_load_fpr32(fp32, fs);
7011 tcg_gen_helper_1_1(do_float_cvtd_w, fp64, fp32);
7012 tcg_temp_free(fp32);
7013 gen_store_fpr64(ctx, fp64, fd);
7014 tcg_temp_free(fp64);
7016 opn = "cvt.d.w";
7017 break;
7018 case FOP(32, 21):
7019 check_cp1_64bitmode(ctx);
7021 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
7022 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
7024 gen_load_fpr64(ctx, fp64, fs);
7025 tcg_gen_helper_1_1(do_float_cvts_l, fp32, fp64);
7026 tcg_temp_free(fp64);
7027 gen_store_fpr32(fp32, fd);
7028 tcg_temp_free(fp32);
7030 opn = "cvt.s.l";
7031 break;
7032 case FOP(33, 21):
7033 check_cp1_64bitmode(ctx);
7035 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7037 gen_load_fpr64(ctx, fp0, fs);
7038 tcg_gen_helper_1_1(do_float_cvtd_l, fp0, fp0);
7039 gen_store_fpr64(ctx, fp0, fd);
7040 tcg_temp_free(fp0);
7042 opn = "cvt.d.l";
7043 break;
7044 case FOP(38, 20):
7045 check_cp1_64bitmode(ctx);
7047 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7049 gen_load_fpr64(ctx, fp0, fs);
7050 tcg_gen_helper_1_1(do_float_cvtps_pw, fp0, fp0);
7051 gen_store_fpr64(ctx, fp0, fd);
7052 tcg_temp_free(fp0);
7054 opn = "cvt.ps.pw";
7055 break;
7056 case FOP(0, 22):
7057 check_cp1_64bitmode(ctx);
7059 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7060 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7062 gen_load_fpr64(ctx, fp0, fs);
7063 gen_load_fpr64(ctx, fp1, ft);
7064 tcg_gen_helper_1_2(do_float_add_ps, fp0, fp0, fp1);
7065 tcg_temp_free(fp1);
7066 gen_store_fpr64(ctx, fp0, fd);
7067 tcg_temp_free(fp0);
7069 opn = "add.ps";
7070 break;
7071 case FOP(1, 22):
7072 check_cp1_64bitmode(ctx);
7074 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7075 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7077 gen_load_fpr64(ctx, fp0, fs);
7078 gen_load_fpr64(ctx, fp1, ft);
7079 tcg_gen_helper_1_2(do_float_sub_ps, fp0, fp0, fp1);
7080 tcg_temp_free(fp1);
7081 gen_store_fpr64(ctx, fp0, fd);
7082 tcg_temp_free(fp0);
7084 opn = "sub.ps";
7085 break;
7086 case FOP(2, 22):
7087 check_cp1_64bitmode(ctx);
7089 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7090 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7092 gen_load_fpr64(ctx, fp0, fs);
7093 gen_load_fpr64(ctx, fp1, ft);
7094 tcg_gen_helper_1_2(do_float_mul_ps, fp0, fp0, fp1);
7095 tcg_temp_free(fp1);
7096 gen_store_fpr64(ctx, fp0, fd);
7097 tcg_temp_free(fp0);
7099 opn = "mul.ps";
7100 break;
7101 case FOP(5, 22):
7102 check_cp1_64bitmode(ctx);
7104 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7106 gen_load_fpr64(ctx, fp0, fs);
7107 tcg_gen_helper_1_1(do_float_abs_ps, fp0, fp0);
7108 gen_store_fpr64(ctx, fp0, fd);
7109 tcg_temp_free(fp0);
7111 opn = "abs.ps";
7112 break;
7113 case FOP(6, 22):
7114 check_cp1_64bitmode(ctx);
7116 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7118 gen_load_fpr64(ctx, fp0, fs);
7119 gen_store_fpr64(ctx, fp0, fd);
7120 tcg_temp_free(fp0);
7122 opn = "mov.ps";
7123 break;
7124 case FOP(7, 22):
7125 check_cp1_64bitmode(ctx);
7127 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7129 gen_load_fpr64(ctx, fp0, fs);
7130 tcg_gen_helper_1_1(do_float_chs_ps, fp0, fp0);
7131 gen_store_fpr64(ctx, fp0, fd);
7132 tcg_temp_free(fp0);
7134 opn = "neg.ps";
7135 break;
7136 case FOP(17, 22):
7137 check_cp1_64bitmode(ctx);
7138 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7139 opn = "movcf.ps";
7140 break;
7141 case FOP(18, 22):
7142 check_cp1_64bitmode(ctx);
7144 int l1 = gen_new_label();
7145 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7146 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7147 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7149 gen_load_gpr(t0, ft);
7150 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7151 tcg_temp_free(t0);
7152 gen_load_fpr32(fp0, fs);
7153 gen_load_fpr32h(fph0, fs);
7154 gen_store_fpr32(fp0, fd);
7155 gen_store_fpr32h(fph0, fd);
7156 tcg_temp_free(fp0);
7157 tcg_temp_free(fph0);
7158 gen_set_label(l1);
7160 opn = "movz.ps";
7161 break;
7162 case FOP(19, 22):
7163 check_cp1_64bitmode(ctx);
7165 int l1 = gen_new_label();
7166 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7167 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7168 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7170 gen_load_gpr(t0, ft);
7171 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
7172 tcg_temp_free(t0);
7173 gen_load_fpr32(fp0, fs);
7174 gen_load_fpr32h(fph0, fs);
7175 gen_store_fpr32(fp0, fd);
7176 gen_store_fpr32h(fph0, fd);
7177 tcg_temp_free(fp0);
7178 tcg_temp_free(fph0);
7179 gen_set_label(l1);
7181 opn = "movn.ps";
7182 break;
7183 case FOP(24, 22):
7184 check_cp1_64bitmode(ctx);
7186 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7187 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7189 gen_load_fpr64(ctx, fp0, ft);
7190 gen_load_fpr64(ctx, fp1, fs);
7191 tcg_gen_helper_1_2(do_float_addr_ps, fp0, fp0, fp1);
7192 tcg_temp_free(fp1);
7193 gen_store_fpr64(ctx, fp0, fd);
7194 tcg_temp_free(fp0);
7196 opn = "addr.ps";
7197 break;
7198 case FOP(26, 22):
7199 check_cp1_64bitmode(ctx);
7201 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7202 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7204 gen_load_fpr64(ctx, fp0, ft);
7205 gen_load_fpr64(ctx, fp1, fs);
7206 tcg_gen_helper_1_2(do_float_mulr_ps, fp0, fp0, fp1);
7207 tcg_temp_free(fp1);
7208 gen_store_fpr64(ctx, fp0, fd);
7209 tcg_temp_free(fp0);
7211 opn = "mulr.ps";
7212 break;
7213 case FOP(28, 22):
7214 check_cp1_64bitmode(ctx);
7216 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7217 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7219 gen_load_fpr64(ctx, fp0, fs);
7220 gen_load_fpr64(ctx, fp1, fd);
7221 tcg_gen_helper_1_2(do_float_recip2_ps, fp0, fp0, fp1);
7222 tcg_temp_free(fp1);
7223 gen_store_fpr64(ctx, fp0, fd);
7224 tcg_temp_free(fp0);
7226 opn = "recip2.ps";
7227 break;
7228 case FOP(29, 22):
7229 check_cp1_64bitmode(ctx);
7231 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7233 gen_load_fpr64(ctx, fp0, fs);
7234 tcg_gen_helper_1_1(do_float_recip1_ps, fp0, fp0);
7235 gen_store_fpr64(ctx, fp0, fd);
7236 tcg_temp_free(fp0);
7238 opn = "recip1.ps";
7239 break;
7240 case FOP(30, 22):
7241 check_cp1_64bitmode(ctx);
7243 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7245 gen_load_fpr64(ctx, fp0, fs);
7246 tcg_gen_helper_1_1(do_float_rsqrt1_ps, fp0, fp0);
7247 gen_store_fpr64(ctx, fp0, fd);
7248 tcg_temp_free(fp0);
7250 opn = "rsqrt1.ps";
7251 break;
7252 case FOP(31, 22):
7253 check_cp1_64bitmode(ctx);
7255 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7256 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7258 gen_load_fpr64(ctx, fp0, fs);
7259 gen_load_fpr64(ctx, fp1, ft);
7260 tcg_gen_helper_1_2(do_float_rsqrt2_ps, fp0, fp0, fp1);
7261 tcg_temp_free(fp1);
7262 gen_store_fpr64(ctx, fp0, fd);
7263 tcg_temp_free(fp0);
7265 opn = "rsqrt2.ps";
7266 break;
7267 case FOP(32, 22):
7268 check_cp1_64bitmode(ctx);
7270 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7272 gen_load_fpr32h(fp0, fs);
7273 tcg_gen_helper_1_1(do_float_cvts_pu, fp0, fp0);
7274 gen_store_fpr32(fp0, fd);
7275 tcg_temp_free(fp0);
7277 opn = "cvt.s.pu";
7278 break;
7279 case FOP(36, 22):
7280 check_cp1_64bitmode(ctx);
7282 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7284 gen_load_fpr64(ctx, fp0, fs);
7285 tcg_gen_helper_1_1(do_float_cvtpw_ps, fp0, fp0);
7286 gen_store_fpr64(ctx, fp0, fd);
7287 tcg_temp_free(fp0);
7289 opn = "cvt.pw.ps";
7290 break;
7291 case FOP(40, 22):
7292 check_cp1_64bitmode(ctx);
7294 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7296 gen_load_fpr32(fp0, fs);
7297 tcg_gen_helper_1_1(do_float_cvts_pl, fp0, fp0);
7298 gen_store_fpr32(fp0, fd);
7299 tcg_temp_free(fp0);
7301 opn = "cvt.s.pl";
7302 break;
7303 case FOP(44, 22):
7304 check_cp1_64bitmode(ctx);
7306 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7307 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7309 gen_load_fpr32(fp0, fs);
7310 gen_load_fpr32(fp1, ft);
7311 gen_store_fpr32h(fp0, fd);
7312 gen_store_fpr32(fp1, fd);
7313 tcg_temp_free(fp0);
7314 tcg_temp_free(fp1);
7316 opn = "pll.ps";
7317 break;
7318 case FOP(45, 22):
7319 check_cp1_64bitmode(ctx);
7321 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7322 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7324 gen_load_fpr32(fp0, fs);
7325 gen_load_fpr32h(fp1, ft);
7326 gen_store_fpr32(fp1, fd);
7327 gen_store_fpr32h(fp0, fd);
7328 tcg_temp_free(fp0);
7329 tcg_temp_free(fp1);
7331 opn = "plu.ps";
7332 break;
7333 case FOP(46, 22):
7334 check_cp1_64bitmode(ctx);
7336 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7337 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7339 gen_load_fpr32h(fp0, fs);
7340 gen_load_fpr32(fp1, ft);
7341 gen_store_fpr32(fp1, fd);
7342 gen_store_fpr32h(fp0, fd);
7343 tcg_temp_free(fp0);
7344 tcg_temp_free(fp1);
7346 opn = "pul.ps";
7347 break;
7348 case FOP(47, 22):
7349 check_cp1_64bitmode(ctx);
7351 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7352 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7354 gen_load_fpr32h(fp0, fs);
7355 gen_load_fpr32h(fp1, ft);
7356 gen_store_fpr32(fp1, fd);
7357 gen_store_fpr32h(fp0, fd);
7358 tcg_temp_free(fp0);
7359 tcg_temp_free(fp1);
7361 opn = "puu.ps";
7362 break;
7363 case FOP(48, 22):
7364 case FOP(49, 22):
7365 case FOP(50, 22):
7366 case FOP(51, 22):
7367 case FOP(52, 22):
7368 case FOP(53, 22):
7369 case FOP(54, 22):
7370 case FOP(55, 22):
7371 case FOP(56, 22):
7372 case FOP(57, 22):
7373 case FOP(58, 22):
7374 case FOP(59, 22):
7375 case FOP(60, 22):
7376 case FOP(61, 22):
7377 case FOP(62, 22):
7378 case FOP(63, 22):
7379 check_cp1_64bitmode(ctx);
7381 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7382 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7384 gen_load_fpr64(ctx, fp0, fs);
7385 gen_load_fpr64(ctx, fp1, ft);
7386 if (ctx->opcode & (1 << 6)) {
7387 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7388 opn = condnames_abs[func-48];
7389 } else {
7390 gen_cmp_ps(func-48, fp0, fp1, cc);
7391 opn = condnames[func-48];
7393 tcg_temp_free(fp0);
7394 tcg_temp_free(fp1);
7396 break;
7397 default:
7398 MIPS_INVAL(opn);
7399 generate_exception (ctx, EXCP_RI);
7400 return;
7402 switch (optype) {
7403 case BINOP:
7404 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7405 break;
7406 case CMPOP:
7407 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7408 break;
7409 default:
7410 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7411 break;
7415 /* Coprocessor 3 (FPU) */
7416 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7417 int fd, int fs, int base, int index)
7419 const char *opn = "extended float load/store";
7420 int store = 0;
7421 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7422 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
7424 if (base == 0) {
7425 gen_load_gpr(t0, index);
7426 } else if (index == 0) {
7427 gen_load_gpr(t0, base);
7428 } else {
7429 gen_load_gpr(t0, base);
7430 gen_load_gpr(t1, index);
7431 gen_op_addr_add(t0, t1);
7433 /* Don't do NOP if destination is zero: we must perform the actual
7434 memory access. */
7435 switch (opc) {
7436 case OPC_LWXC1:
7437 check_cop1x(ctx);
7439 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7441 tcg_gen_qemu_ld32s(fp0, t0, ctx->mem_idx);
7442 gen_store_fpr32(fp0, fd);
7443 tcg_temp_free(fp0);
7445 opn = "lwxc1";
7446 break;
7447 case OPC_LDXC1:
7448 check_cop1x(ctx);
7449 check_cp1_registers(ctx, fd);
7451 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7453 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7454 gen_store_fpr64(ctx, fp0, fd);
7455 tcg_temp_free(fp0);
7457 opn = "ldxc1";
7458 break;
7459 case OPC_LUXC1:
7460 check_cp1_64bitmode(ctx);
7461 tcg_gen_andi_tl(t0, t0, ~0x7);
7463 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7465 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7466 gen_store_fpr64(ctx, fp0, fd);
7467 tcg_temp_free(fp0);
7469 opn = "luxc1";
7470 break;
7471 case OPC_SWXC1:
7472 check_cop1x(ctx);
7474 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7476 gen_load_fpr32(fp0, fs);
7477 tcg_gen_qemu_st32(fp0, t0, ctx->mem_idx);
7478 tcg_temp_free(fp0);
7480 opn = "swxc1";
7481 store = 1;
7482 break;
7483 case OPC_SDXC1:
7484 check_cop1x(ctx);
7485 check_cp1_registers(ctx, fs);
7487 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7489 gen_load_fpr64(ctx, fp0, fs);
7490 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7491 tcg_temp_free(fp0);
7493 opn = "sdxc1";
7494 store = 1;
7495 break;
7496 case OPC_SUXC1:
7497 check_cp1_64bitmode(ctx);
7498 tcg_gen_andi_tl(t0, t0, ~0x7);
7500 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7502 gen_load_fpr64(ctx, fp0, fs);
7503 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7504 tcg_temp_free(fp0);
7506 opn = "suxc1";
7507 store = 1;
7508 break;
7509 default:
7510 MIPS_INVAL(opn);
7511 generate_exception(ctx, EXCP_RI);
7512 tcg_temp_free(t0);
7513 tcg_temp_free(t1);
7514 return;
7516 tcg_temp_free(t0);
7517 tcg_temp_free(t1);
7518 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7519 regnames[index], regnames[base]);
7522 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7523 int fd, int fr, int fs, int ft)
7525 const char *opn = "flt3_arith";
7527 switch (opc) {
7528 case OPC_ALNV_PS:
7529 check_cp1_64bitmode(ctx);
7531 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7532 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7533 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7534 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
7535 TCGv fph1 = tcg_temp_local_new(TCG_TYPE_I32);
7536 int l1 = gen_new_label();
7537 int l2 = gen_new_label();
7539 gen_load_gpr(t0, fr);
7540 tcg_gen_andi_tl(t0, t0, 0x7);
7541 gen_load_fpr32(fp0, fs);
7542 gen_load_fpr32h(fph0, fs);
7543 gen_load_fpr32(fp1, ft);
7544 gen_load_fpr32h(fph1, ft);
7546 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7547 gen_store_fpr32(fp0, fd);
7548 gen_store_fpr32h(fph0, fd);
7549 tcg_gen_br(l2);
7550 gen_set_label(l1);
7551 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7552 tcg_temp_free(t0);
7553 #ifdef TARGET_WORDS_BIGENDIAN
7554 gen_store_fpr32(fph1, fd);
7555 gen_store_fpr32h(fp0, fd);
7556 #else
7557 gen_store_fpr32(fph0, fd);
7558 gen_store_fpr32h(fp1, fd);
7559 #endif
7560 gen_set_label(l2);
7561 tcg_temp_free(fp0);
7562 tcg_temp_free(fph0);
7563 tcg_temp_free(fp1);
7564 tcg_temp_free(fph1);
7566 opn = "alnv.ps";
7567 break;
7568 case OPC_MADD_S:
7569 check_cop1x(ctx);
7571 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7572 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7573 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7575 gen_load_fpr32(fp0, fs);
7576 gen_load_fpr32(fp1, ft);
7577 gen_load_fpr32(fp2, fr);
7578 tcg_gen_helper_1_3(do_float_muladd_s, fp2, fp0, fp1, fp2);
7579 tcg_temp_free(fp0);
7580 tcg_temp_free(fp1);
7581 gen_store_fpr32(fp2, fd);
7582 tcg_temp_free(fp2);
7584 opn = "madd.s";
7585 break;
7586 case OPC_MADD_D:
7587 check_cop1x(ctx);
7588 check_cp1_registers(ctx, fd | fs | ft | fr);
7590 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7591 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7592 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7594 gen_load_fpr64(ctx, fp0, fs);
7595 gen_load_fpr64(ctx, fp1, ft);
7596 gen_load_fpr64(ctx, fp2, fr);
7597 tcg_gen_helper_1_3(do_float_muladd_d, fp2, fp0, fp1, fp2);
7598 tcg_temp_free(fp0);
7599 tcg_temp_free(fp1);
7600 gen_store_fpr64(ctx, fp2, fd);
7601 tcg_temp_free(fp2);
7603 opn = "madd.d";
7604 break;
7605 case OPC_MADD_PS:
7606 check_cp1_64bitmode(ctx);
7608 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7609 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7610 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7612 gen_load_fpr64(ctx, fp0, fs);
7613 gen_load_fpr64(ctx, fp1, ft);
7614 gen_load_fpr64(ctx, fp2, fr);
7615 tcg_gen_helper_1_3(do_float_muladd_ps, fp2, fp0, fp1, fp2);
7616 tcg_temp_free(fp0);
7617 tcg_temp_free(fp1);
7618 gen_store_fpr64(ctx, fp2, fd);
7619 tcg_temp_free(fp2);
7621 opn = "madd.ps";
7622 break;
7623 case OPC_MSUB_S:
7624 check_cop1x(ctx);
7626 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7627 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7628 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7630 gen_load_fpr32(fp0, fs);
7631 gen_load_fpr32(fp1, ft);
7632 gen_load_fpr32(fp2, fr);
7633 tcg_gen_helper_1_3(do_float_mulsub_s, fp2, fp0, fp1, fp2);
7634 tcg_temp_free(fp0);
7635 tcg_temp_free(fp1);
7636 gen_store_fpr32(fp2, fd);
7637 tcg_temp_free(fp2);
7639 opn = "msub.s";
7640 break;
7641 case OPC_MSUB_D:
7642 check_cop1x(ctx);
7643 check_cp1_registers(ctx, fd | fs | ft | fr);
7645 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7646 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7647 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7649 gen_load_fpr64(ctx, fp0, fs);
7650 gen_load_fpr64(ctx, fp1, ft);
7651 gen_load_fpr64(ctx, fp2, fr);
7652 tcg_gen_helper_1_3(do_float_mulsub_d, fp2, fp0, fp1, fp2);
7653 tcg_temp_free(fp0);
7654 tcg_temp_free(fp1);
7655 gen_store_fpr64(ctx, fp2, fd);
7656 tcg_temp_free(fp2);
7658 opn = "msub.d";
7659 break;
7660 case OPC_MSUB_PS:
7661 check_cp1_64bitmode(ctx);
7663 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7664 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7665 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7667 gen_load_fpr64(ctx, fp0, fs);
7668 gen_load_fpr64(ctx, fp1, ft);
7669 gen_load_fpr64(ctx, fp2, fr);
7670 tcg_gen_helper_1_3(do_float_mulsub_ps, fp2, fp0, fp1, fp2);
7671 tcg_temp_free(fp0);
7672 tcg_temp_free(fp1);
7673 gen_store_fpr64(ctx, fp2, fd);
7674 tcg_temp_free(fp2);
7676 opn = "msub.ps";
7677 break;
7678 case OPC_NMADD_S:
7679 check_cop1x(ctx);
7681 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7682 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7683 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7685 gen_load_fpr32(fp0, fs);
7686 gen_load_fpr32(fp1, ft);
7687 gen_load_fpr32(fp2, fr);
7688 tcg_gen_helper_1_3(do_float_nmuladd_s, fp2, fp0, fp1, fp2);
7689 tcg_temp_free(fp0);
7690 tcg_temp_free(fp1);
7691 gen_store_fpr32(fp2, fd);
7692 tcg_temp_free(fp2);
7694 opn = "nmadd.s";
7695 break;
7696 case OPC_NMADD_D:
7697 check_cop1x(ctx);
7698 check_cp1_registers(ctx, fd | fs | ft | fr);
7700 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7701 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7702 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7704 gen_load_fpr64(ctx, fp0, fs);
7705 gen_load_fpr64(ctx, fp1, ft);
7706 gen_load_fpr64(ctx, fp2, fr);
7707 tcg_gen_helper_1_3(do_float_nmuladd_d, fp2, fp0, fp1, fp2);
7708 tcg_temp_free(fp0);
7709 tcg_temp_free(fp1);
7710 gen_store_fpr64(ctx, fp2, fd);
7711 tcg_temp_free(fp2);
7713 opn = "nmadd.d";
7714 break;
7715 case OPC_NMADD_PS:
7716 check_cp1_64bitmode(ctx);
7718 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7719 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7720 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7722 gen_load_fpr64(ctx, fp0, fs);
7723 gen_load_fpr64(ctx, fp1, ft);
7724 gen_load_fpr64(ctx, fp2, fr);
7725 tcg_gen_helper_1_3(do_float_nmuladd_ps, fp2, fp0, fp1, fp2);
7726 tcg_temp_free(fp0);
7727 tcg_temp_free(fp1);
7728 gen_store_fpr64(ctx, fp2, fd);
7729 tcg_temp_free(fp2);
7731 opn = "nmadd.ps";
7732 break;
7733 case OPC_NMSUB_S:
7734 check_cop1x(ctx);
7736 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7737 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7738 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7740 gen_load_fpr32(fp0, fs);
7741 gen_load_fpr32(fp1, ft);
7742 gen_load_fpr32(fp2, fr);
7743 tcg_gen_helper_1_3(do_float_nmulsub_s, fp2, fp0, fp1, fp2);
7744 tcg_temp_free(fp0);
7745 tcg_temp_free(fp1);
7746 gen_store_fpr32(fp2, fd);
7747 tcg_temp_free(fp2);
7749 opn = "nmsub.s";
7750 break;
7751 case OPC_NMSUB_D:
7752 check_cop1x(ctx);
7753 check_cp1_registers(ctx, fd | fs | ft | fr);
7755 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7756 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7757 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7759 gen_load_fpr64(ctx, fp0, fs);
7760 gen_load_fpr64(ctx, fp1, ft);
7761 gen_load_fpr64(ctx, fp2, fr);
7762 tcg_gen_helper_1_3(do_float_nmulsub_d, fp2, fp0, fp1, fp2);
7763 tcg_temp_free(fp0);
7764 tcg_temp_free(fp1);
7765 gen_store_fpr64(ctx, fp2, fd);
7766 tcg_temp_free(fp2);
7768 opn = "nmsub.d";
7769 break;
7770 case OPC_NMSUB_PS:
7771 check_cp1_64bitmode(ctx);
7773 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7774 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7775 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7777 gen_load_fpr64(ctx, fp0, fs);
7778 gen_load_fpr64(ctx, fp1, ft);
7779 gen_load_fpr64(ctx, fp2, fr);
7780 tcg_gen_helper_1_3(do_float_nmulsub_ps, fp2, fp0, fp1, fp2);
7781 tcg_temp_free(fp0);
7782 tcg_temp_free(fp1);
7783 gen_store_fpr64(ctx, fp2, fd);
7784 tcg_temp_free(fp2);
7786 opn = "nmsub.ps";
7787 break;
7788 default:
7789 MIPS_INVAL(opn);
7790 generate_exception (ctx, EXCP_RI);
7791 return;
7793 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7794 fregnames[fs], fregnames[ft]);
7797 /* ISA extensions (ASEs) */
7798 /* MIPS16 extension to MIPS32 */
7799 /* SmartMIPS extension to MIPS32 */
7801 #if defined(TARGET_MIPS64)
7803 /* MDMX extension to MIPS64 */
7805 #endif
7807 static void decode_opc (CPUState *env, DisasContext *ctx)
7809 int32_t offset;
7810 int rs, rt, rd, sa;
7811 uint32_t op, op1, op2;
7812 int16_t imm;
7814 /* make sure instructions are on a word boundary */
7815 if (ctx->pc & 0x3) {
7816 env->CP0_BadVAddr = ctx->pc;
7817 generate_exception(ctx, EXCP_AdEL);
7818 return;
7821 /* Handle blikely not taken case */
7822 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7823 int l1 = gen_new_label();
7825 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7826 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
7828 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
7830 tcg_gen_movi_i32(r_tmp, ctx->hflags & ~MIPS_HFLAG_BMASK);
7831 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
7832 tcg_temp_free(r_tmp);
7834 gen_goto_tb(ctx, 1, ctx->pc + 4);
7835 gen_set_label(l1);
7837 op = MASK_OP_MAJOR(ctx->opcode);
7838 rs = (ctx->opcode >> 21) & 0x1f;
7839 rt = (ctx->opcode >> 16) & 0x1f;
7840 rd = (ctx->opcode >> 11) & 0x1f;
7841 sa = (ctx->opcode >> 6) & 0x1f;
7842 imm = (int16_t)ctx->opcode;
7843 switch (op) {
7844 case OPC_SPECIAL:
7845 op1 = MASK_SPECIAL(ctx->opcode);
7846 switch (op1) {
7847 case OPC_SLL: /* Arithmetic with immediate */
7848 case OPC_SRL ... OPC_SRA:
7849 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7850 break;
7851 case OPC_MOVZ ... OPC_MOVN:
7852 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7853 case OPC_SLLV: /* Arithmetic */
7854 case OPC_SRLV ... OPC_SRAV:
7855 case OPC_ADD ... OPC_NOR:
7856 case OPC_SLT ... OPC_SLTU:
7857 gen_arith(env, ctx, op1, rd, rs, rt);
7858 break;
7859 case OPC_MULT ... OPC_DIVU:
7860 if (sa) {
7861 check_insn(env, ctx, INSN_VR54XX);
7862 op1 = MASK_MUL_VR54XX(ctx->opcode);
7863 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7864 } else
7865 gen_muldiv(ctx, op1, rs, rt);
7866 break;
7867 case OPC_JR ... OPC_JALR:
7868 gen_compute_branch(ctx, op1, rs, rd, sa);
7869 return;
7870 case OPC_TGE ... OPC_TEQ: /* Traps */
7871 case OPC_TNE:
7872 gen_trap(ctx, op1, rs, rt, -1);
7873 break;
7874 case OPC_MFHI: /* Move from HI/LO */
7875 case OPC_MFLO:
7876 gen_HILO(ctx, op1, rd);
7877 break;
7878 case OPC_MTHI:
7879 case OPC_MTLO: /* Move to HI/LO */
7880 gen_HILO(ctx, op1, rs);
7881 break;
7882 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7883 #ifdef MIPS_STRICT_STANDARD
7884 MIPS_INVAL("PMON / selsl");
7885 generate_exception(ctx, EXCP_RI);
7886 #else
7887 tcg_gen_helper_0_i(do_pmon, sa);
7888 #endif
7889 break;
7890 case OPC_SYSCALL:
7891 generate_exception(ctx, EXCP_SYSCALL);
7892 break;
7893 case OPC_BREAK:
7894 generate_exception(ctx, EXCP_BREAK);
7895 break;
7896 case OPC_SPIM:
7897 #ifdef MIPS_STRICT_STANDARD
7898 MIPS_INVAL("SPIM");
7899 generate_exception(ctx, EXCP_RI);
7900 #else
7901 /* Implemented as RI exception for now. */
7902 MIPS_INVAL("spim (unofficial)");
7903 generate_exception(ctx, EXCP_RI);
7904 #endif
7905 break;
7906 case OPC_SYNC:
7907 /* Treat as NOP. */
7908 break;
7910 case OPC_MOVCI:
7911 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7912 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7913 save_cpu_state(ctx, 1);
7914 check_cp1_enabled(ctx);
7915 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7916 (ctx->opcode >> 16) & 1);
7917 } else {
7918 generate_exception_err(ctx, EXCP_CpU, 1);
7920 break;
7922 #if defined(TARGET_MIPS64)
7923 /* MIPS64 specific opcodes */
7924 case OPC_DSLL:
7925 case OPC_DSRL ... OPC_DSRA:
7926 case OPC_DSLL32:
7927 case OPC_DSRL32 ... OPC_DSRA32:
7928 check_insn(env, ctx, ISA_MIPS3);
7929 check_mips_64(ctx);
7930 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7931 break;
7932 case OPC_DSLLV:
7933 case OPC_DSRLV ... OPC_DSRAV:
7934 case OPC_DADD ... OPC_DSUBU:
7935 check_insn(env, ctx, ISA_MIPS3);
7936 check_mips_64(ctx);
7937 gen_arith(env, ctx, op1, rd, rs, rt);
7938 break;
7939 case OPC_DMULT ... OPC_DDIVU:
7940 check_insn(env, ctx, ISA_MIPS3);
7941 check_mips_64(ctx);
7942 gen_muldiv(ctx, op1, rs, rt);
7943 break;
7944 #endif
7945 default: /* Invalid */
7946 MIPS_INVAL("special");
7947 generate_exception(ctx, EXCP_RI);
7948 break;
7950 break;
7951 case OPC_SPECIAL2:
7952 op1 = MASK_SPECIAL2(ctx->opcode);
7953 switch (op1) {
7954 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7955 case OPC_MSUB ... OPC_MSUBU:
7956 check_insn(env, ctx, ISA_MIPS32);
7957 gen_muldiv(ctx, op1, rs, rt);
7958 break;
7959 case OPC_MUL:
7960 gen_arith(env, ctx, op1, rd, rs, rt);
7961 break;
7962 case OPC_CLZ ... OPC_CLO:
7963 check_insn(env, ctx, ISA_MIPS32);
7964 gen_cl(ctx, op1, rd, rs);
7965 break;
7966 case OPC_SDBBP:
7967 /* XXX: not clear which exception should be raised
7968 * when in debug mode...
7970 check_insn(env, ctx, ISA_MIPS32);
7971 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7972 generate_exception(ctx, EXCP_DBp);
7973 } else {
7974 generate_exception(ctx, EXCP_DBp);
7976 /* Treat as NOP. */
7977 break;
7978 #if defined(TARGET_MIPS64)
7979 case OPC_DCLZ ... OPC_DCLO:
7980 check_insn(env, ctx, ISA_MIPS64);
7981 check_mips_64(ctx);
7982 gen_cl(ctx, op1, rd, rs);
7983 break;
7984 #endif
7985 default: /* Invalid */
7986 MIPS_INVAL("special2");
7987 generate_exception(ctx, EXCP_RI);
7988 break;
7990 break;
7991 case OPC_SPECIAL3:
7992 op1 = MASK_SPECIAL3(ctx->opcode);
7993 switch (op1) {
7994 case OPC_EXT:
7995 case OPC_INS:
7996 check_insn(env, ctx, ISA_MIPS32R2);
7997 gen_bitops(ctx, op1, rt, rs, sa, rd);
7998 break;
7999 case OPC_BSHFL:
8000 check_insn(env, ctx, ISA_MIPS32R2);
8001 op2 = MASK_BSHFL(ctx->opcode);
8003 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8004 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
8006 switch (op2) {
8007 case OPC_WSBH:
8008 gen_load_gpr(t1, rt);
8009 tcg_gen_helper_1_1(do_wsbh, t0, t1);
8010 gen_store_gpr(t0, rd);
8011 break;
8012 case OPC_SEB:
8013 gen_load_gpr(t1, rt);
8014 tcg_gen_ext8s_tl(t0, t1);
8015 gen_store_gpr(t0, rd);
8016 break;
8017 case OPC_SEH:
8018 gen_load_gpr(t1, rt);
8019 tcg_gen_ext16s_tl(t0, t1);
8020 gen_store_gpr(t0, rd);
8021 break;
8022 default: /* Invalid */
8023 MIPS_INVAL("bshfl");
8024 generate_exception(ctx, EXCP_RI);
8025 break;
8027 tcg_temp_free(t0);
8028 tcg_temp_free(t1);
8030 break;
8031 case OPC_RDHWR:
8032 check_insn(env, ctx, ISA_MIPS32R2);
8034 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8036 switch (rd) {
8037 case 0:
8038 save_cpu_state(ctx, 1);
8039 tcg_gen_helper_1_0(do_rdhwr_cpunum, t0);
8040 break;
8041 case 1:
8042 save_cpu_state(ctx, 1);
8043 tcg_gen_helper_1_0(do_rdhwr_synci_step, t0);
8044 break;
8045 case 2:
8046 save_cpu_state(ctx, 1);
8047 tcg_gen_helper_1_0(do_rdhwr_cc, t0);
8048 break;
8049 case 3:
8050 save_cpu_state(ctx, 1);
8051 tcg_gen_helper_1_0(do_rdhwr_ccres, t0);
8052 break;
8053 case 29:
8054 if (env->user_mode_only) {
8055 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
8056 break;
8057 } else {
8058 /* XXX: Some CPUs implement this in hardware.
8059 Not supported yet. */
8061 default: /* Invalid */
8062 MIPS_INVAL("rdhwr");
8063 generate_exception(ctx, EXCP_RI);
8064 break;
8066 gen_store_gpr(t0, rt);
8067 tcg_temp_free(t0);
8069 break;
8070 case OPC_FORK:
8071 check_insn(env, ctx, ASE_MT);
8073 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8074 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
8076 gen_load_gpr(t0, rt);
8077 gen_load_gpr(t1, rs);
8078 tcg_gen_helper_0_2(do_fork, t0, t1);
8079 tcg_temp_free(t0);
8080 tcg_temp_free(t1);
8082 break;
8083 case OPC_YIELD:
8084 check_insn(env, ctx, ASE_MT);
8086 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8088 gen_load_gpr(t0, rs);
8089 tcg_gen_helper_1_1(do_yield, t0, t0);
8090 gen_store_gpr(t0, rd);
8091 tcg_temp_free(t0);
8093 break;
8094 #if defined(TARGET_MIPS64)
8095 case OPC_DEXTM ... OPC_DEXT:
8096 case OPC_DINSM ... OPC_DINS:
8097 check_insn(env, ctx, ISA_MIPS64R2);
8098 check_mips_64(ctx);
8099 gen_bitops(ctx, op1, rt, rs, sa, rd);
8100 break;
8101 case OPC_DBSHFL:
8102 check_insn(env, ctx, ISA_MIPS64R2);
8103 check_mips_64(ctx);
8104 op2 = MASK_DBSHFL(ctx->opcode);
8106 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8107 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
8109 switch (op2) {
8110 case OPC_DSBH:
8111 gen_load_gpr(t1, rt);
8112 tcg_gen_helper_1_1(do_dsbh, t0, t1);
8113 break;
8114 case OPC_DSHD:
8115 gen_load_gpr(t1, rt);
8116 tcg_gen_helper_1_1(do_dshd, t0, t1);
8117 break;
8118 default: /* Invalid */
8119 MIPS_INVAL("dbshfl");
8120 generate_exception(ctx, EXCP_RI);
8121 break;
8123 gen_store_gpr(t0, rd);
8124 tcg_temp_free(t0);
8125 tcg_temp_free(t1);
8127 break;
8128 #endif
8129 default: /* Invalid */
8130 MIPS_INVAL("special3");
8131 generate_exception(ctx, EXCP_RI);
8132 break;
8134 break;
8135 case OPC_REGIMM:
8136 op1 = MASK_REGIMM(ctx->opcode);
8137 switch (op1) {
8138 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
8139 case OPC_BLTZAL ... OPC_BGEZALL:
8140 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
8141 return;
8142 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
8143 case OPC_TNEI:
8144 gen_trap(ctx, op1, rs, -1, imm);
8145 break;
8146 case OPC_SYNCI:
8147 check_insn(env, ctx, ISA_MIPS32R2);
8148 /* Treat as NOP. */
8149 break;
8150 default: /* Invalid */
8151 MIPS_INVAL("regimm");
8152 generate_exception(ctx, EXCP_RI);
8153 break;
8155 break;
8156 case OPC_CP0:
8157 check_cp0_enabled(ctx);
8158 op1 = MASK_CP0(ctx->opcode);
8159 switch (op1) {
8160 case OPC_MFC0:
8161 case OPC_MTC0:
8162 case OPC_MFTR:
8163 case OPC_MTTR:
8164 #if defined(TARGET_MIPS64)
8165 case OPC_DMFC0:
8166 case OPC_DMTC0:
8167 #endif
8168 #ifndef CONFIG_USER_ONLY
8169 if (!env->user_mode_only)
8170 gen_cp0(env, ctx, op1, rt, rd);
8171 #endif /* !CONFIG_USER_ONLY */
8172 break;
8173 case OPC_C0_FIRST ... OPC_C0_LAST:
8174 #ifndef CONFIG_USER_ONLY
8175 if (!env->user_mode_only)
8176 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
8177 #endif /* !CONFIG_USER_ONLY */
8178 break;
8179 case OPC_MFMC0:
8180 #ifndef CONFIG_USER_ONLY
8181 if (!env->user_mode_only) {
8182 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8184 op2 = MASK_MFMC0(ctx->opcode);
8185 switch (op2) {
8186 case OPC_DMT:
8187 check_insn(env, ctx, ASE_MT);
8188 tcg_gen_helper_1_1(do_dmt, t0, t0);
8189 break;
8190 case OPC_EMT:
8191 check_insn(env, ctx, ASE_MT);
8192 tcg_gen_helper_1_1(do_emt, t0, t0);
8193 break;
8194 case OPC_DVPE:
8195 check_insn(env, ctx, ASE_MT);
8196 tcg_gen_helper_1_1(do_dvpe, t0, t0);
8197 break;
8198 case OPC_EVPE:
8199 check_insn(env, ctx, ASE_MT);
8200 tcg_gen_helper_1_1(do_evpe, t0, t0);
8201 break;
8202 case OPC_DI:
8203 check_insn(env, ctx, ISA_MIPS32R2);
8204 save_cpu_state(ctx, 1);
8205 tcg_gen_helper_1_0(do_di, t0);
8206 /* Stop translation as we may have switched the execution mode */
8207 ctx->bstate = BS_STOP;
8208 break;
8209 case OPC_EI:
8210 check_insn(env, ctx, ISA_MIPS32R2);
8211 save_cpu_state(ctx, 1);
8212 tcg_gen_helper_1_0(do_ei, t0);
8213 /* Stop translation as we may have switched the execution mode */
8214 ctx->bstate = BS_STOP;
8215 break;
8216 default: /* Invalid */
8217 MIPS_INVAL("mfmc0");
8218 generate_exception(ctx, EXCP_RI);
8219 break;
8221 gen_store_gpr(t0, rt);
8222 tcg_temp_free(t0);
8224 #endif /* !CONFIG_USER_ONLY */
8225 break;
8226 case OPC_RDPGPR:
8227 check_insn(env, ctx, ISA_MIPS32R2);
8228 gen_load_srsgpr(rt, rd);
8229 break;
8230 case OPC_WRPGPR:
8231 check_insn(env, ctx, ISA_MIPS32R2);
8232 gen_store_srsgpr(rt, rd);
8233 break;
8234 default:
8235 MIPS_INVAL("cp0");
8236 generate_exception(ctx, EXCP_RI);
8237 break;
8239 break;
8240 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
8241 gen_arith_imm(env, ctx, op, rt, rs, imm);
8242 break;
8243 case OPC_J ... OPC_JAL: /* Jump */
8244 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8245 gen_compute_branch(ctx, op, rs, rt, offset);
8246 return;
8247 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8248 case OPC_BEQL ... OPC_BGTZL:
8249 gen_compute_branch(ctx, op, rs, rt, imm << 2);
8250 return;
8251 case OPC_LB ... OPC_LWR: /* Load and stores */
8252 case OPC_SB ... OPC_SW:
8253 case OPC_SWR:
8254 case OPC_LL:
8255 case OPC_SC:
8256 gen_ldst(ctx, op, rt, rs, imm);
8257 break;
8258 case OPC_CACHE:
8259 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
8260 /* Treat as NOP. */
8261 break;
8262 case OPC_PREF:
8263 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8264 /* Treat as NOP. */
8265 break;
8267 /* Floating point (COP1). */
8268 case OPC_LWC1:
8269 case OPC_LDC1:
8270 case OPC_SWC1:
8271 case OPC_SDC1:
8272 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8273 save_cpu_state(ctx, 1);
8274 check_cp1_enabled(ctx);
8275 gen_flt_ldst(ctx, op, rt, rs, imm);
8276 } else {
8277 generate_exception_err(ctx, EXCP_CpU, 1);
8279 break;
8281 case OPC_CP1:
8282 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8283 save_cpu_state(ctx, 1);
8284 check_cp1_enabled(ctx);
8285 op1 = MASK_CP1(ctx->opcode);
8286 switch (op1) {
8287 case OPC_MFHC1:
8288 case OPC_MTHC1:
8289 check_insn(env, ctx, ISA_MIPS32R2);
8290 case OPC_MFC1:
8291 case OPC_CFC1:
8292 case OPC_MTC1:
8293 case OPC_CTC1:
8294 gen_cp1(ctx, op1, rt, rd);
8295 break;
8296 #if defined(TARGET_MIPS64)
8297 case OPC_DMFC1:
8298 case OPC_DMTC1:
8299 check_insn(env, ctx, ISA_MIPS3);
8300 gen_cp1(ctx, op1, rt, rd);
8301 break;
8302 #endif
8303 case OPC_BC1ANY2:
8304 case OPC_BC1ANY4:
8305 check_cop1x(ctx);
8306 check_insn(env, ctx, ASE_MIPS3D);
8307 /* fall through */
8308 case OPC_BC1:
8309 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8310 (rt >> 2) & 0x7, imm << 2);
8311 return;
8312 case OPC_S_FMT:
8313 case OPC_D_FMT:
8314 case OPC_W_FMT:
8315 case OPC_L_FMT:
8316 case OPC_PS_FMT:
8317 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8318 (imm >> 8) & 0x7);
8319 break;
8320 default:
8321 MIPS_INVAL("cp1");
8322 generate_exception (ctx, EXCP_RI);
8323 break;
8325 } else {
8326 generate_exception_err(ctx, EXCP_CpU, 1);
8328 break;
8330 /* COP2. */
8331 case OPC_LWC2:
8332 case OPC_LDC2:
8333 case OPC_SWC2:
8334 case OPC_SDC2:
8335 case OPC_CP2:
8336 /* COP2: Not implemented. */
8337 generate_exception_err(ctx, EXCP_CpU, 2);
8338 break;
8340 case OPC_CP3:
8341 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8342 save_cpu_state(ctx, 1);
8343 check_cp1_enabled(ctx);
8344 op1 = MASK_CP3(ctx->opcode);
8345 switch (op1) {
8346 case OPC_LWXC1:
8347 case OPC_LDXC1:
8348 case OPC_LUXC1:
8349 case OPC_SWXC1:
8350 case OPC_SDXC1:
8351 case OPC_SUXC1:
8352 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8353 break;
8354 case OPC_PREFX:
8355 /* Treat as NOP. */
8356 break;
8357 case OPC_ALNV_PS:
8358 case OPC_MADD_S:
8359 case OPC_MADD_D:
8360 case OPC_MADD_PS:
8361 case OPC_MSUB_S:
8362 case OPC_MSUB_D:
8363 case OPC_MSUB_PS:
8364 case OPC_NMADD_S:
8365 case OPC_NMADD_D:
8366 case OPC_NMADD_PS:
8367 case OPC_NMSUB_S:
8368 case OPC_NMSUB_D:
8369 case OPC_NMSUB_PS:
8370 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8371 break;
8372 default:
8373 MIPS_INVAL("cp3");
8374 generate_exception (ctx, EXCP_RI);
8375 break;
8377 } else {
8378 generate_exception_err(ctx, EXCP_CpU, 1);
8380 break;
8382 #if defined(TARGET_MIPS64)
8383 /* MIPS64 opcodes */
8384 case OPC_LWU:
8385 case OPC_LDL ... OPC_LDR:
8386 case OPC_SDL ... OPC_SDR:
8387 case OPC_LLD:
8388 case OPC_LD:
8389 case OPC_SCD:
8390 case OPC_SD:
8391 check_insn(env, ctx, ISA_MIPS3);
8392 check_mips_64(ctx);
8393 gen_ldst(ctx, op, rt, rs, imm);
8394 break;
8395 case OPC_DADDI ... OPC_DADDIU:
8396 check_insn(env, ctx, ISA_MIPS3);
8397 check_mips_64(ctx);
8398 gen_arith_imm(env, ctx, op, rt, rs, imm);
8399 break;
8400 #endif
8401 case OPC_JALX:
8402 check_insn(env, ctx, ASE_MIPS16);
8403 /* MIPS16: Not implemented. */
8404 case OPC_MDMX:
8405 check_insn(env, ctx, ASE_MDMX);
8406 /* MDMX: Not implemented. */
8407 default: /* Invalid */
8408 MIPS_INVAL("major opcode");
8409 generate_exception(ctx, EXCP_RI);
8410 break;
8412 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8413 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8414 /* Branches completion */
8415 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8416 ctx->bstate = BS_BRANCH;
8417 save_cpu_state(ctx, 0);
8418 /* FIXME: Need to clear can_do_io. */
8419 switch (hflags) {
8420 case MIPS_HFLAG_B:
8421 /* unconditional branch */
8422 MIPS_DEBUG("unconditional branch");
8423 gen_goto_tb(ctx, 0, ctx->btarget);
8424 break;
8425 case MIPS_HFLAG_BL:
8426 /* blikely taken case */
8427 MIPS_DEBUG("blikely branch taken");
8428 gen_goto_tb(ctx, 0, ctx->btarget);
8429 break;
8430 case MIPS_HFLAG_BC:
8431 /* Conditional branch */
8432 MIPS_DEBUG("conditional branch");
8434 int l1 = gen_new_label();
8436 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
8437 gen_goto_tb(ctx, 1, ctx->pc + 4);
8438 gen_set_label(l1);
8439 gen_goto_tb(ctx, 0, ctx->btarget);
8441 break;
8442 case MIPS_HFLAG_BR:
8443 /* unconditional branch to register */
8444 MIPS_DEBUG("branch to register");
8445 tcg_gen_st_tl(btarget, cpu_env, offsetof(CPUState, active_tc.PC));
8446 tcg_gen_exit_tb(0);
8447 break;
8448 default:
8449 MIPS_DEBUG("unknown branch");
8450 break;
8455 static inline void
8456 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8457 int search_pc)
8459 DisasContext ctx;
8460 target_ulong pc_start;
8461 uint16_t *gen_opc_end;
8462 int j, lj = -1;
8463 int num_insns;
8464 int max_insns;
8466 if (search_pc && loglevel)
8467 fprintf (logfile, "search pc %d\n", search_pc);
8469 pc_start = tb->pc;
8470 /* Leave some spare opc slots for branch handling. */
8471 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
8472 ctx.pc = pc_start;
8473 ctx.saved_pc = -1;
8474 ctx.tb = tb;
8475 ctx.bstate = BS_NONE;
8476 /* Restore delay slot state from the tb context. */
8477 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8478 restore_cpu_state(env, &ctx);
8479 if (env->user_mode_only)
8480 ctx.mem_idx = MIPS_HFLAG_UM;
8481 else
8482 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8483 num_insns = 0;
8484 max_insns = tb->cflags & CF_COUNT_MASK;
8485 if (max_insns == 0)
8486 max_insns = CF_COUNT_MASK;
8487 #ifdef DEBUG_DISAS
8488 if (loglevel & CPU_LOG_TB_CPU) {
8489 fprintf(logfile, "------------------------------------------------\n");
8490 /* FIXME: This may print out stale hflags from env... */
8491 cpu_dump_state(env, logfile, fprintf, 0);
8493 #endif
8494 #ifdef MIPS_DEBUG_DISAS
8495 if (loglevel & CPU_LOG_TB_IN_ASM)
8496 fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
8497 tb, ctx.mem_idx, ctx.hflags);
8498 #endif
8499 gen_icount_start();
8500 while (ctx.bstate == BS_NONE) {
8501 if (env->nb_breakpoints > 0) {
8502 for(j = 0; j < env->nb_breakpoints; j++) {
8503 if (env->breakpoints[j] == ctx.pc) {
8504 save_cpu_state(&ctx, 1);
8505 ctx.bstate = BS_BRANCH;
8506 tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
8507 /* Include the breakpoint location or the tb won't
8508 * be flushed when it must be. */
8509 ctx.pc += 4;
8510 goto done_generating;
8515 if (search_pc) {
8516 j = gen_opc_ptr - gen_opc_buf;
8517 if (lj < j) {
8518 lj++;
8519 while (lj < j)
8520 gen_opc_instr_start[lj++] = 0;
8522 gen_opc_pc[lj] = ctx.pc;
8523 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8524 gen_opc_instr_start[lj] = 1;
8525 gen_opc_icount[lj] = num_insns;
8527 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8528 gen_io_start();
8529 ctx.opcode = ldl_code(ctx.pc);
8530 decode_opc(env, &ctx);
8531 ctx.pc += 4;
8532 num_insns++;
8534 if (env->singlestep_enabled)
8535 break;
8537 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8538 break;
8540 if (gen_opc_ptr >= gen_opc_end)
8541 break;
8543 if (num_insns >= max_insns)
8544 break;
8545 #if defined (MIPS_SINGLE_STEP)
8546 break;
8547 #endif
8549 if (tb->cflags & CF_LAST_IO)
8550 gen_io_end();
8551 if (env->singlestep_enabled) {
8552 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
8553 tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
8554 } else {
8555 switch (ctx.bstate) {
8556 case BS_STOP:
8557 tcg_gen_helper_0_0(do_interrupt_restart);
8558 gen_goto_tb(&ctx, 0, ctx.pc);
8559 break;
8560 case BS_NONE:
8561 save_cpu_state(&ctx, 0);
8562 gen_goto_tb(&ctx, 0, ctx.pc);
8563 break;
8564 case BS_EXCP:
8565 tcg_gen_helper_0_0(do_interrupt_restart);
8566 tcg_gen_exit_tb(0);
8567 break;
8568 case BS_BRANCH:
8569 default:
8570 break;
8573 done_generating:
8574 gen_icount_end(tb, num_insns);
8575 *gen_opc_ptr = INDEX_op_end;
8576 if (search_pc) {
8577 j = gen_opc_ptr - gen_opc_buf;
8578 lj++;
8579 while (lj <= j)
8580 gen_opc_instr_start[lj++] = 0;
8581 } else {
8582 tb->size = ctx.pc - pc_start;
8583 tb->icount = num_insns;
8585 #ifdef DEBUG_DISAS
8586 #if defined MIPS_DEBUG_DISAS
8587 if (loglevel & CPU_LOG_TB_IN_ASM)
8588 fprintf(logfile, "\n");
8589 #endif
8590 if (loglevel & CPU_LOG_TB_IN_ASM) {
8591 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
8592 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
8593 fprintf(logfile, "\n");
8595 if (loglevel & CPU_LOG_TB_CPU) {
8596 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8598 #endif
8601 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8603 gen_intermediate_code_internal(env, tb, 0);
8606 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8608 gen_intermediate_code_internal(env, tb, 1);
8611 static void fpu_dump_state(CPUState *env, FILE *f,
8612 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8613 int flags)
8615 int i;
8616 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8618 #define printfpr(fp) \
8619 do { \
8620 if (is_fpu64) \
8621 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8622 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8623 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8624 else { \
8625 fpr_t tmp; \
8626 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8627 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8628 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8629 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8630 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8632 } while(0)
8635 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8636 env->fpu->fcr0, env->fpu->fcr31, is_fpu64, env->fpu->fp_status,
8637 get_float_exception_flags(&env->fpu->fp_status));
8638 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8639 fpu_fprintf(f, "%3s: ", fregnames[i]);
8640 printfpr(&env->fpu->fpr[i]);
8643 #undef printfpr
8646 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8647 /* Debug help: The architecture requires 32bit code to maintain proper
8648 sign-extended values on 64bit machines. */
8650 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8652 static void
8653 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8654 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8655 int flags)
8657 int i;
8659 if (!SIGN_EXT_P(env->active_tc.PC))
8660 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8661 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8662 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8663 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8664 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8665 if (!SIGN_EXT_P(env->btarget))
8666 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8668 for (i = 0; i < 32; i++) {
8669 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8670 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8673 if (!SIGN_EXT_P(env->CP0_EPC))
8674 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8675 if (!SIGN_EXT_P(env->CP0_LLAddr))
8676 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
8678 #endif
8680 void cpu_dump_state (CPUState *env, FILE *f,
8681 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8682 int flags)
8684 int i;
8686 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",
8687 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8688 env->hflags, env->btarget, env->bcond);
8689 for (i = 0; i < 32; i++) {
8690 if ((i & 3) == 0)
8691 cpu_fprintf(f, "GPR%02d:", i);
8692 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8693 if ((i & 3) == 3)
8694 cpu_fprintf(f, "\n");
8697 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8698 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8699 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8700 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
8701 if (env->hflags & MIPS_HFLAG_FPU)
8702 fpu_dump_state(env, f, cpu_fprintf, flags);
8703 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8704 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8705 #endif
8708 static void mips_tcg_init(void)
8710 static int inited;
8712 /* Initialize various static tables. */
8713 if (inited)
8714 return;
8716 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
8717 bcond = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8718 offsetof(CPUState, bcond), "bcond");
8719 btarget = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8720 offsetof(CPUState, btarget), "btarget");
8721 current_fpu = tcg_global_mem_new(TCG_TYPE_PTR,
8722 TCG_AREG0,
8723 offsetof(CPUState, fpu),
8724 "current_fpu");
8726 /* register helpers */
8727 #undef DEF_HELPER
8728 #define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
8729 #include "helper.h"
8731 inited = 1;
8734 #include "translate_init.c"
8736 CPUMIPSState *cpu_mips_init (const char *cpu_model)
8738 CPUMIPSState *env;
8739 const mips_def_t *def;
8741 def = cpu_mips_find_by_name(cpu_model);
8742 if (!def)
8743 return NULL;
8744 env = qemu_mallocz(sizeof(CPUMIPSState));
8745 if (!env)
8746 return NULL;
8747 env->cpu_model = def;
8749 cpu_exec_init(env);
8750 env->cpu_model_str = cpu_model;
8751 mips_tcg_init();
8752 cpu_reset(env);
8753 return env;
8756 void cpu_reset (CPUMIPSState *env)
8758 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8760 tlb_flush(env, 1);
8762 /* Minimal init */
8763 #if defined(CONFIG_USER_ONLY)
8764 env->user_mode_only = 1;
8765 #endif
8766 if (env->user_mode_only) {
8767 env->hflags = MIPS_HFLAG_UM;
8768 } else {
8769 if (env->hflags & MIPS_HFLAG_BMASK) {
8770 /* If the exception was raised from a delay slot,
8771 come back to the jump. */
8772 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8773 } else {
8774 env->CP0_ErrorEPC = env->active_tc.PC;
8776 env->active_tc.PC = (int32_t)0xBFC00000;
8777 env->CP0_Wired = 0;
8778 /* SMP not implemented */
8779 env->CP0_EBase = 0x80000000;
8780 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8781 /* vectored interrupts not implemented, timer on int 7,
8782 no performance counters. */
8783 env->CP0_IntCtl = 0xe0000000;
8785 int i;
8787 for (i = 0; i < 7; i++) {
8788 env->CP0_WatchLo[i] = 0;
8789 env->CP0_WatchHi[i] = 0x80000000;
8791 env->CP0_WatchLo[7] = 0;
8792 env->CP0_WatchHi[7] = 0;
8794 /* Count register increments in debug mode, EJTAG version 1 */
8795 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8796 env->hflags = MIPS_HFLAG_CP0;
8798 env->exception_index = EXCP_NONE;
8799 cpu_mips_register(env, env->cpu_model);
8802 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8803 unsigned long searched_pc, int pc_pos, void *puc)
8805 env->active_tc.PC = gen_opc_pc[pc_pos];
8806 env->hflags &= ~MIPS_HFLAG_BMASK;
8807 env->hflags |= gen_opc_hflags[pc_pos];