Optional "precise" VGA retrace support
[qemu/mini2440.git] / target-mips / translate.c
blobec375e120146690e35e7e5b8e6889db193206fcc
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, cpu_gpr[32], cpu_PC;
427 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
428 static TCGv cpu_dspctrl, bcond, btarget;
429 static TCGv fpu_fpr32[32], fpu_fpr32h[32], fpu_fpr64[32], fpu_fcr0, fpu_fcr31;
431 #include "gen-icount.h"
433 static inline void tcg_gen_helper_0_i(void *func, uint32_t arg)
436 TCGv tmp = tcg_const_i32(arg);
438 tcg_gen_helper_0_1(func, tmp);
439 tcg_temp_free(tmp);
442 static inline void tcg_gen_helper_0_ii(void *func, uint32_t arg1, uint32_t arg2)
444 TCGv tmp1 = tcg_const_i32(arg1);
445 TCGv tmp2 = tcg_const_i32(arg2);
447 tcg_gen_helper_0_2(func, tmp1, tmp2);
448 tcg_temp_free(tmp1);
449 tcg_temp_free(tmp2);
452 static inline void tcg_gen_helper_0_1i(void *func, TCGv arg1, uint32_t arg2)
454 TCGv tmp = tcg_const_i32(arg2);
456 tcg_gen_helper_0_2(func, arg1, tmp);
457 tcg_temp_free(tmp);
460 static inline void tcg_gen_helper_0_2i(void *func, TCGv arg1, TCGv arg2, uint32_t arg3)
462 TCGv tmp = tcg_const_i32(arg3);
464 tcg_gen_helper_0_3(func, arg1, arg2, tmp);
465 tcg_temp_free(tmp);
468 static inline void tcg_gen_helper_0_1ii(void *func, TCGv arg1, uint32_t arg2, uint32_t arg3)
470 TCGv tmp1 = tcg_const_i32(arg2);
471 TCGv tmp2 = tcg_const_i32(arg3);
473 tcg_gen_helper_0_3(func, arg1, tmp1, tmp2);
474 tcg_temp_free(tmp1);
475 tcg_temp_free(tmp2);
478 static inline void tcg_gen_helper_1_i(void *func, TCGv ret, uint32_t arg)
480 TCGv tmp = tcg_const_i32(arg);
482 tcg_gen_helper_1_1(func, ret, tmp);
483 tcg_temp_free(tmp);
486 static inline void tcg_gen_helper_1_1i(void *func, TCGv ret, TCGv arg1, uint32_t arg2)
488 TCGv tmp = tcg_const_i32(arg2);
490 tcg_gen_helper_1_2(func, ret, arg1, tmp);
491 tcg_temp_free(tmp);
494 static inline void tcg_gen_helper_1_1ii(void *func, TCGv ret, TCGv arg1, uint32_t arg2, uint32_t arg3)
496 TCGv tmp1 = tcg_const_i32(arg2);
497 TCGv tmp2 = tcg_const_i32(arg3);
499 tcg_gen_helper_1_3(func, ret, arg1, tmp1, tmp2);
500 tcg_temp_free(tmp1);
501 tcg_temp_free(tmp2);
504 static inline void tcg_gen_helper_1_2i(void *func, TCGv ret, TCGv arg1, TCGv arg2, uint32_t arg3)
506 TCGv tmp = tcg_const_i32(arg3);
508 tcg_gen_helper_1_3(func, ret, arg1, arg2, tmp);
509 tcg_temp_free(tmp);
512 static inline void tcg_gen_helper_1_2ii(void *func, TCGv ret, TCGv arg1, TCGv arg2, uint32_t arg3, uint32_t arg4)
514 TCGv tmp1 = tcg_const_i32(arg3);
515 TCGv tmp2 = tcg_const_i32(arg4);
517 tcg_gen_helper_1_4(func, ret, arg1, arg2, tmp1, tmp2);
518 tcg_temp_free(tmp1);
519 tcg_temp_free(tmp2);
522 typedef struct DisasContext {
523 struct TranslationBlock *tb;
524 target_ulong pc, saved_pc;
525 uint32_t opcode;
526 /* Routine used to access memory */
527 int mem_idx;
528 uint32_t hflags, saved_hflags;
529 int bstate;
530 target_ulong btarget;
531 } DisasContext;
533 enum {
534 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
535 * exception condition */
536 BS_STOP = 1, /* We want to stop translation for any reason */
537 BS_BRANCH = 2, /* We reached a branch condition */
538 BS_EXCP = 3, /* We reached an exception condition */
541 static const char *regnames[] =
542 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
543 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
544 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
545 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
547 static const char *regnames_HI[] =
548 { "HI0", "HI1", "HI2", "HI3", };
550 static const char *regnames_LO[] =
551 { "LO0", "LO1", "LO2", "LO3", };
553 static const char *regnames_ACX[] =
554 { "ACX0", "ACX1", "ACX2", "ACX3", };
556 static const char *fregnames[] =
557 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
558 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
559 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
560 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
562 static const char *fregnames_64[] =
563 { "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7",
564 "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15",
565 "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23",
566 "F24", "F25", "F26", "F27", "F28", "F29", "F30", "F31", };
568 static const char *fregnames_h[] =
569 { "h0", "h1", "h2", "h3", "h4", "h5", "h6", "h7",
570 "h8", "h9", "h10", "h11", "h12", "h13", "h14", "h15",
571 "h16", "h17", "h18", "h19", "h20", "h21", "h22", "h23",
572 "h24", "h25", "h26", "h27", "h28", "h29", "h30", "h31", };
574 #ifdef MIPS_DEBUG_DISAS
575 #define MIPS_DEBUG(fmt, args...) \
576 do { \
577 if (loglevel & CPU_LOG_TB_IN_ASM) { \
578 fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n", \
579 ctx->pc, ctx->opcode , ##args); \
581 } while (0)
582 #else
583 #define MIPS_DEBUG(fmt, args...) do { } while(0)
584 #endif
586 #define MIPS_INVAL(op) \
587 do { \
588 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
589 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
590 } while (0)
592 /* General purpose registers moves. */
593 static inline void gen_load_gpr (TCGv t, int reg)
595 if (reg == 0)
596 tcg_gen_movi_tl(t, 0);
597 else
598 tcg_gen_mov_tl(t, cpu_gpr[reg]);
601 static inline void gen_store_gpr (TCGv t, int reg)
603 if (reg != 0)
604 tcg_gen_mov_tl(cpu_gpr[reg], t);
607 /* Moves to/from HI and LO registers. */
608 static inline void gen_load_HI (TCGv t, int reg)
610 tcg_gen_mov_tl(t, cpu_HI[reg]);
613 static inline void gen_store_HI (TCGv t, int reg)
615 tcg_gen_mov_tl(cpu_HI[reg], t);
618 static inline void gen_load_LO (TCGv t, int reg)
620 tcg_gen_mov_tl(t, cpu_LO[reg]);
623 static inline void gen_store_LO (TCGv t, int reg)
625 tcg_gen_mov_tl(cpu_LO[reg], t);
628 static inline void gen_load_ACX (TCGv t, int reg)
630 tcg_gen_mov_tl(t, cpu_ACX[reg]);
633 static inline void gen_store_ACX (TCGv t, int reg)
635 tcg_gen_mov_tl(cpu_ACX[reg], t);
638 /* Moves to/from shadow registers. */
639 static inline void gen_load_srsgpr (int from, int to)
641 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
643 if (from == 0)
644 tcg_gen_movi_tl(r_tmp1, 0);
645 else {
646 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
648 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
649 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
650 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
651 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
652 tcg_gen_add_i32(r_tmp2, cpu_env, r_tmp2);
654 tcg_gen_ld_tl(r_tmp1, r_tmp2, sizeof(target_ulong) * from);
655 tcg_temp_free(r_tmp2);
657 gen_store_gpr(r_tmp1, to);
658 tcg_temp_free(r_tmp1);
661 static inline void gen_store_srsgpr (int from, int to)
663 if (to != 0) {
664 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
665 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
667 gen_load_gpr(r_tmp1, from);
668 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
669 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
670 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
671 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
672 tcg_gen_add_i32(r_tmp2, cpu_env, r_tmp2);
674 tcg_gen_st_tl(r_tmp1, r_tmp2, sizeof(target_ulong) * to);
675 tcg_temp_free(r_tmp1);
676 tcg_temp_free(r_tmp2);
680 /* Floating point register moves. */
681 static inline void gen_load_fpr32 (TCGv t, int reg)
683 tcg_gen_mov_i32(t, fpu_fpr32[reg]);
686 static inline void gen_store_fpr32 (TCGv t, int reg)
688 tcg_gen_mov_i32(fpu_fpr32[reg], t);
691 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv t, int reg)
693 if (ctx->hflags & MIPS_HFLAG_F64)
694 tcg_gen_mov_i64(t, fpu_fpr64[reg]);
695 else {
696 tcg_gen_concat_i32_i64(t, fpu_fpr32[reg & ~1], fpu_fpr32[reg | 1]);
700 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv t, int reg)
702 if (ctx->hflags & MIPS_HFLAG_F64)
703 tcg_gen_mov_i64(fpu_fpr64[reg], t);
704 else {
705 tcg_gen_trunc_i64_i32(fpu_fpr32[reg & ~1], t);
706 tcg_gen_shri_i64(t, t, 32);
707 tcg_gen_trunc_i64_i32(fpu_fpr32[reg | 1], t);
711 static inline void gen_load_fpr32h (TCGv t, int reg)
713 tcg_gen_mov_i32(t, fpu_fpr32h[reg]);
716 static inline void gen_store_fpr32h (TCGv t, int reg)
718 tcg_gen_mov_i32(fpu_fpr32h[reg], t);
721 static inline void get_fp_cond (TCGv t)
723 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
724 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
726 tcg_gen_shri_i32(r_tmp2, fpu_fcr31, 24);
727 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xfe);
728 tcg_gen_shri_i32(r_tmp1, fpu_fcr31, 23);
729 tcg_gen_andi_i32(r_tmp1, r_tmp1, 0x1);
730 tcg_gen_or_i32(t, r_tmp1, r_tmp2);
731 tcg_temp_free(r_tmp1);
732 tcg_temp_free(r_tmp2);
735 typedef void (fcmp_fun32)(uint32_t, uint32_t, int);
736 typedef void (fcmp_fun64)(uint64_t, uint64_t, int);
738 #define FOP_CONDS(fcmp_fun, type, fmt) \
739 static fcmp_fun * fcmp ## type ## _ ## fmt ## _table[16] = { \
740 do_cmp ## type ## _ ## fmt ## _f, \
741 do_cmp ## type ## _ ## fmt ## _un, \
742 do_cmp ## type ## _ ## fmt ## _eq, \
743 do_cmp ## type ## _ ## fmt ## _ueq, \
744 do_cmp ## type ## _ ## fmt ## _olt, \
745 do_cmp ## type ## _ ## fmt ## _ult, \
746 do_cmp ## type ## _ ## fmt ## _ole, \
747 do_cmp ## type ## _ ## fmt ## _ule, \
748 do_cmp ## type ## _ ## fmt ## _sf, \
749 do_cmp ## type ## _ ## fmt ## _ngle, \
750 do_cmp ## type ## _ ## fmt ## _seq, \
751 do_cmp ## type ## _ ## fmt ## _ngl, \
752 do_cmp ## type ## _ ## fmt ## _lt, \
753 do_cmp ## type ## _ ## fmt ## _nge, \
754 do_cmp ## type ## _ ## fmt ## _le, \
755 do_cmp ## type ## _ ## fmt ## _ngt, \
756 }; \
757 static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv a, TCGv b, int cc) \
759 tcg_gen_helper_0_2i(fcmp ## type ## _ ## fmt ## _table[n], a, b, cc); \
762 FOP_CONDS(fcmp_fun64, , d)
763 FOP_CONDS(fcmp_fun64, abs, d)
764 FOP_CONDS(fcmp_fun32, , s)
765 FOP_CONDS(fcmp_fun32, abs, s)
766 FOP_CONDS(fcmp_fun64, , ps)
767 FOP_CONDS(fcmp_fun64, abs, ps)
768 #undef FOP_CONDS
770 /* Tests */
771 #define OP_COND(name, cond) \
772 static inline void glue(gen_op_, name) (TCGv t0, TCGv t1) \
774 int l1 = gen_new_label(); \
775 int l2 = gen_new_label(); \
777 tcg_gen_brcond_tl(cond, t0, t1, l1); \
778 tcg_gen_movi_tl(t0, 0); \
779 tcg_gen_br(l2); \
780 gen_set_label(l1); \
781 tcg_gen_movi_tl(t0, 1); \
782 gen_set_label(l2); \
784 OP_COND(eq, TCG_COND_EQ);
785 OP_COND(ne, TCG_COND_NE);
786 OP_COND(ge, TCG_COND_GE);
787 OP_COND(geu, TCG_COND_GEU);
788 OP_COND(lt, TCG_COND_LT);
789 OP_COND(ltu, TCG_COND_LTU);
790 #undef OP_COND
792 #define OP_CONDI(name, cond) \
793 static inline void glue(gen_op_, name) (TCGv t, target_ulong val) \
795 int l1 = gen_new_label(); \
796 int l2 = gen_new_label(); \
798 tcg_gen_brcondi_tl(cond, t, val, l1); \
799 tcg_gen_movi_tl(t, 0); \
800 tcg_gen_br(l2); \
801 gen_set_label(l1); \
802 tcg_gen_movi_tl(t, 1); \
803 gen_set_label(l2); \
805 OP_CONDI(lti, TCG_COND_LT);
806 OP_CONDI(ltiu, TCG_COND_LTU);
807 #undef OP_CONDI
809 #define OP_CONDZ(name, cond) \
810 static inline void glue(gen_op_, name) (TCGv t) \
812 int l1 = gen_new_label(); \
813 int l2 = gen_new_label(); \
815 tcg_gen_brcondi_tl(cond, t, 0, l1); \
816 tcg_gen_movi_tl(t, 0); \
817 tcg_gen_br(l2); \
818 gen_set_label(l1); \
819 tcg_gen_movi_tl(t, 1); \
820 gen_set_label(l2); \
822 OP_CONDZ(gez, TCG_COND_GE);
823 OP_CONDZ(gtz, TCG_COND_GT);
824 OP_CONDZ(lez, TCG_COND_LE);
825 OP_CONDZ(ltz, TCG_COND_LT);
826 #undef OP_CONDZ
828 static inline void gen_save_pc(target_ulong pc)
830 TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL);
832 tcg_gen_movi_tl(r_tmp, pc);
833 tcg_gen_mov_tl(cpu_PC, r_tmp);
834 tcg_temp_free(r_tmp);
837 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
839 #if defined MIPS_DEBUG_DISAS
840 if (loglevel & CPU_LOG_TB_IN_ASM) {
841 fprintf(logfile, "hflags %08x saved %08x\n",
842 ctx->hflags, ctx->saved_hflags);
844 #endif
845 if (do_save_pc && ctx->pc != ctx->saved_pc) {
846 gen_save_pc(ctx->pc);
847 ctx->saved_pc = ctx->pc;
849 if (ctx->hflags != ctx->saved_hflags) {
850 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
852 tcg_gen_movi_i32(r_tmp, ctx->hflags);
853 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
854 tcg_temp_free(r_tmp);
855 ctx->saved_hflags = ctx->hflags;
856 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
857 case MIPS_HFLAG_BR:
858 break;
859 case MIPS_HFLAG_BC:
860 case MIPS_HFLAG_BL:
861 case MIPS_HFLAG_B:
862 tcg_gen_movi_tl(btarget, ctx->btarget);
863 break;
868 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
870 ctx->saved_hflags = ctx->hflags;
871 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
872 case MIPS_HFLAG_BR:
873 break;
874 case MIPS_HFLAG_BC:
875 case MIPS_HFLAG_BL:
876 case MIPS_HFLAG_B:
877 ctx->btarget = env->btarget;
878 break;
882 static inline void
883 generate_exception_err (DisasContext *ctx, int excp, int err)
885 save_cpu_state(ctx, 1);
886 tcg_gen_helper_0_ii(do_raise_exception_err, excp, err);
887 tcg_gen_helper_0_0(do_interrupt_restart);
888 tcg_gen_exit_tb(0);
891 static inline void
892 generate_exception (DisasContext *ctx, int excp)
894 save_cpu_state(ctx, 1);
895 tcg_gen_helper_0_i(do_raise_exception, excp);
896 tcg_gen_helper_0_0(do_interrupt_restart);
897 tcg_gen_exit_tb(0);
900 /* Addresses computation */
901 static inline void gen_op_addr_add (TCGv t0, TCGv t1)
903 tcg_gen_add_tl(t0, t0, t1);
905 #if defined(TARGET_MIPS64)
906 /* For compatibility with 32-bit code, data reference in user mode
907 with Status_UX = 0 should be casted to 32-bit and sign extended.
908 See the MIPS64 PRA manual, section 4.10. */
910 int l1 = gen_new_label();
911 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_I32);
913 tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
914 tcg_gen_andi_i32(r_tmp, r_tmp, MIPS_HFLAG_KSU);
915 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp, MIPS_HFLAG_UM, l1);
916 tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_Status));
917 tcg_gen_andi_i32(r_tmp, r_tmp, (1 << CP0St_UX));
918 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp, 0, l1);
919 tcg_temp_free(r_tmp);
920 tcg_gen_ext32s_i64(t0, t0);
921 gen_set_label(l1);
923 #endif
926 static inline void check_cp0_enabled(DisasContext *ctx)
928 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
929 generate_exception_err(ctx, EXCP_CpU, 1);
932 static inline void check_cp1_enabled(DisasContext *ctx)
934 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
935 generate_exception_err(ctx, EXCP_CpU, 1);
938 /* Verify that the processor is running with COP1X instructions enabled.
939 This is associated with the nabla symbol in the MIPS32 and MIPS64
940 opcode tables. */
942 static inline void check_cop1x(DisasContext *ctx)
944 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
945 generate_exception(ctx, EXCP_RI);
948 /* Verify that the processor is running with 64-bit floating-point
949 operations enabled. */
951 static inline void check_cp1_64bitmode(DisasContext *ctx)
953 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
954 generate_exception(ctx, EXCP_RI);
958 * Verify if floating point register is valid; an operation is not defined
959 * if bit 0 of any register specification is set and the FR bit in the
960 * Status register equals zero, since the register numbers specify an
961 * even-odd pair of adjacent coprocessor general registers. When the FR bit
962 * in the Status register equals one, both even and odd register numbers
963 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
965 * Multiple 64 bit wide registers can be checked by calling
966 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
968 static inline void check_cp1_registers(DisasContext *ctx, int regs)
970 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
971 generate_exception(ctx, EXCP_RI);
974 /* This code generates a "reserved instruction" exception if the
975 CPU does not support the instruction set corresponding to flags. */
976 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
978 if (unlikely(!(env->insn_flags & flags)))
979 generate_exception(ctx, EXCP_RI);
982 /* This code generates a "reserved instruction" exception if 64-bit
983 instructions are not enabled. */
984 static inline void check_mips_64(DisasContext *ctx)
986 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
987 generate_exception(ctx, EXCP_RI);
990 /* load/store instructions. */
991 #define OP_LD(insn,fname) \
992 static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx) \
994 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
996 OP_LD(lb,ld8s);
997 OP_LD(lbu,ld8u);
998 OP_LD(lh,ld16s);
999 OP_LD(lhu,ld16u);
1000 OP_LD(lw,ld32s);
1001 #if defined(TARGET_MIPS64)
1002 OP_LD(lwu,ld32u);
1003 OP_LD(ld,ld64);
1004 #endif
1005 #undef OP_LD
1007 #define OP_ST(insn,fname) \
1008 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
1010 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
1012 OP_ST(sb,st8);
1013 OP_ST(sh,st16);
1014 OP_ST(sw,st32);
1015 #if defined(TARGET_MIPS64)
1016 OP_ST(sd,st64);
1017 #endif
1018 #undef OP_ST
1020 #define OP_LD_ATOMIC(insn,fname) \
1021 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
1023 tcg_gen_mov_tl(t1, t0); \
1024 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
1025 tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
1027 OP_LD_ATOMIC(ll,ld32s);
1028 #if defined(TARGET_MIPS64)
1029 OP_LD_ATOMIC(lld,ld64);
1030 #endif
1031 #undef OP_LD_ATOMIC
1033 #define OP_ST_ATOMIC(insn,fname,almask) \
1034 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
1036 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL); \
1037 int l1 = gen_new_label(); \
1038 int l2 = gen_new_label(); \
1039 int l3 = gen_new_label(); \
1041 tcg_gen_andi_tl(r_tmp, t0, almask); \
1042 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1); \
1043 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
1044 generate_exception(ctx, EXCP_AdES); \
1045 gen_set_label(l1); \
1046 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
1047 tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2); \
1048 tcg_temp_free(r_tmp); \
1049 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
1050 tcg_gen_movi_tl(t0, 1); \
1051 tcg_gen_br(l3); \
1052 gen_set_label(l2); \
1053 tcg_gen_movi_tl(t0, 0); \
1054 gen_set_label(l3); \
1056 OP_ST_ATOMIC(sc,st32,0x3);
1057 #if defined(TARGET_MIPS64)
1058 OP_ST_ATOMIC(scd,st64,0x7);
1059 #endif
1060 #undef OP_ST_ATOMIC
1062 /* Load and store */
1063 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1064 int base, int16_t offset)
1066 const char *opn = "ldst";
1067 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1068 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1070 if (base == 0) {
1071 tcg_gen_movi_tl(t0, offset);
1072 } else if (offset == 0) {
1073 gen_load_gpr(t0, base);
1074 } else {
1075 gen_load_gpr(t0, base);
1076 tcg_gen_movi_tl(t1, offset);
1077 gen_op_addr_add(t0, t1);
1079 /* Don't do NOP if destination is zero: we must perform the actual
1080 memory access. */
1081 switch (opc) {
1082 #if defined(TARGET_MIPS64)
1083 case OPC_LWU:
1084 op_ldst_lwu(t0, ctx);
1085 gen_store_gpr(t0, rt);
1086 opn = "lwu";
1087 break;
1088 case OPC_LD:
1089 op_ldst_ld(t0, ctx);
1090 gen_store_gpr(t0, rt);
1091 opn = "ld";
1092 break;
1093 case OPC_LLD:
1094 op_ldst_lld(t0, t1, ctx);
1095 gen_store_gpr(t0, rt);
1096 opn = "lld";
1097 break;
1098 case OPC_SD:
1099 gen_load_gpr(t1, rt);
1100 op_ldst_sd(t0, t1, ctx);
1101 opn = "sd";
1102 break;
1103 case OPC_SCD:
1104 save_cpu_state(ctx, 1);
1105 gen_load_gpr(t1, rt);
1106 op_ldst_scd(t0, t1, ctx);
1107 gen_store_gpr(t0, rt);
1108 opn = "scd";
1109 break;
1110 case OPC_LDL:
1111 save_cpu_state(ctx, 1);
1112 gen_load_gpr(t1, rt);
1113 tcg_gen_helper_1_2i(do_ldl, t1, t0, t1, ctx->mem_idx);
1114 gen_store_gpr(t1, rt);
1115 opn = "ldl";
1116 break;
1117 case OPC_SDL:
1118 save_cpu_state(ctx, 1);
1119 gen_load_gpr(t1, rt);
1120 tcg_gen_helper_0_2i(do_sdl, t0, t1, ctx->mem_idx);
1121 opn = "sdl";
1122 break;
1123 case OPC_LDR:
1124 save_cpu_state(ctx, 1);
1125 gen_load_gpr(t1, rt);
1126 tcg_gen_helper_1_2i(do_ldr, t1, t0, t1, ctx->mem_idx);
1127 gen_store_gpr(t1, rt);
1128 opn = "ldr";
1129 break;
1130 case OPC_SDR:
1131 save_cpu_state(ctx, 1);
1132 gen_load_gpr(t1, rt);
1133 tcg_gen_helper_0_2i(do_sdr, t0, t1, ctx->mem_idx);
1134 opn = "sdr";
1135 break;
1136 #endif
1137 case OPC_LW:
1138 op_ldst_lw(t0, ctx);
1139 gen_store_gpr(t0, rt);
1140 opn = "lw";
1141 break;
1142 case OPC_SW:
1143 gen_load_gpr(t1, rt);
1144 op_ldst_sw(t0, t1, ctx);
1145 opn = "sw";
1146 break;
1147 case OPC_LH:
1148 op_ldst_lh(t0, ctx);
1149 gen_store_gpr(t0, rt);
1150 opn = "lh";
1151 break;
1152 case OPC_SH:
1153 gen_load_gpr(t1, rt);
1154 op_ldst_sh(t0, t1, ctx);
1155 opn = "sh";
1156 break;
1157 case OPC_LHU:
1158 op_ldst_lhu(t0, ctx);
1159 gen_store_gpr(t0, rt);
1160 opn = "lhu";
1161 break;
1162 case OPC_LB:
1163 op_ldst_lb(t0, ctx);
1164 gen_store_gpr(t0, rt);
1165 opn = "lb";
1166 break;
1167 case OPC_SB:
1168 gen_load_gpr(t1, rt);
1169 op_ldst_sb(t0, t1, ctx);
1170 opn = "sb";
1171 break;
1172 case OPC_LBU:
1173 op_ldst_lbu(t0, ctx);
1174 gen_store_gpr(t0, rt);
1175 opn = "lbu";
1176 break;
1177 case OPC_LWL:
1178 save_cpu_state(ctx, 1);
1179 gen_load_gpr(t1, rt);
1180 tcg_gen_helper_1_2i(do_lwl, t1, t0, t1, ctx->mem_idx);
1181 gen_store_gpr(t1, rt);
1182 opn = "lwl";
1183 break;
1184 case OPC_SWL:
1185 save_cpu_state(ctx, 1);
1186 gen_load_gpr(t1, rt);
1187 tcg_gen_helper_0_2i(do_swl, t0, t1, ctx->mem_idx);
1188 opn = "swr";
1189 break;
1190 case OPC_LWR:
1191 save_cpu_state(ctx, 1);
1192 gen_load_gpr(t1, rt);
1193 tcg_gen_helper_1_2i(do_lwr, t1, t0, t1, ctx->mem_idx);
1194 gen_store_gpr(t1, rt);
1195 opn = "lwr";
1196 break;
1197 case OPC_SWR:
1198 save_cpu_state(ctx, 1);
1199 gen_load_gpr(t1, rt);
1200 tcg_gen_helper_0_2i(do_swr, t0, t1, ctx->mem_idx);
1201 opn = "swr";
1202 break;
1203 case OPC_LL:
1204 op_ldst_ll(t0, t1, ctx);
1205 gen_store_gpr(t0, rt);
1206 opn = "ll";
1207 break;
1208 case OPC_SC:
1209 save_cpu_state(ctx, 1);
1210 gen_load_gpr(t1, rt);
1211 op_ldst_sc(t0, t1, ctx);
1212 gen_store_gpr(t0, rt);
1213 opn = "sc";
1214 break;
1215 default:
1216 MIPS_INVAL(opn);
1217 generate_exception(ctx, EXCP_RI);
1218 goto out;
1220 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1221 out:
1222 tcg_temp_free(t0);
1223 tcg_temp_free(t1);
1226 /* Load and store */
1227 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1228 int base, int16_t offset)
1230 const char *opn = "flt_ldst";
1231 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1233 if (base == 0) {
1234 tcg_gen_movi_tl(t0, offset);
1235 } else if (offset == 0) {
1236 gen_load_gpr(t0, base);
1237 } else {
1238 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1240 gen_load_gpr(t0, base);
1241 tcg_gen_movi_tl(t1, offset);
1242 gen_op_addr_add(t0, t1);
1243 tcg_temp_free(t1);
1245 /* Don't do NOP if destination is zero: we must perform the actual
1246 memory access. */
1247 switch (opc) {
1248 case OPC_LWC1:
1250 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
1252 tcg_gen_qemu_ld32s(fp0, t0, ctx->mem_idx);
1253 gen_store_fpr32(fp0, ft);
1254 tcg_temp_free(fp0);
1256 opn = "lwc1";
1257 break;
1258 case OPC_SWC1:
1260 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
1262 gen_load_fpr32(fp0, ft);
1263 tcg_gen_qemu_st32(fp0, t0, ctx->mem_idx);
1264 tcg_temp_free(fp0);
1266 opn = "swc1";
1267 break;
1268 case OPC_LDC1:
1270 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
1272 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1273 gen_store_fpr64(ctx, fp0, ft);
1274 tcg_temp_free(fp0);
1276 opn = "ldc1";
1277 break;
1278 case OPC_SDC1:
1280 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
1282 gen_load_fpr64(ctx, fp0, ft);
1283 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1284 tcg_temp_free(fp0);
1286 opn = "sdc1";
1287 break;
1288 default:
1289 MIPS_INVAL(opn);
1290 generate_exception(ctx, EXCP_RI);
1291 goto out;
1293 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1294 out:
1295 tcg_temp_free(t0);
1298 /* Arithmetic with immediate operand */
1299 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1300 int rt, int rs, int16_t imm)
1302 target_ulong uimm;
1303 const char *opn = "imm arith";
1304 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1306 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1307 /* If no destination, treat it as a NOP.
1308 For addi, we must generate the overflow exception when needed. */
1309 MIPS_DEBUG("NOP");
1310 goto out;
1312 uimm = (uint16_t)imm;
1313 switch (opc) {
1314 case OPC_ADDI:
1315 case OPC_ADDIU:
1316 #if defined(TARGET_MIPS64)
1317 case OPC_DADDI:
1318 case OPC_DADDIU:
1319 #endif
1320 case OPC_SLTI:
1321 case OPC_SLTIU:
1322 uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1323 /* Fall through. */
1324 case OPC_ANDI:
1325 case OPC_ORI:
1326 case OPC_XORI:
1327 gen_load_gpr(t0, rs);
1328 break;
1329 case OPC_LUI:
1330 tcg_gen_movi_tl(t0, imm << 16);
1331 break;
1332 case OPC_SLL:
1333 case OPC_SRA:
1334 case OPC_SRL:
1335 #if defined(TARGET_MIPS64)
1336 case OPC_DSLL:
1337 case OPC_DSRA:
1338 case OPC_DSRL:
1339 case OPC_DSLL32:
1340 case OPC_DSRA32:
1341 case OPC_DSRL32:
1342 #endif
1343 uimm &= 0x1f;
1344 gen_load_gpr(t0, rs);
1345 break;
1347 switch (opc) {
1348 case OPC_ADDI:
1350 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1351 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1352 int l1 = gen_new_label();
1354 save_cpu_state(ctx, 1);
1355 tcg_gen_ext32s_tl(r_tmp1, t0);
1356 tcg_gen_addi_tl(t0, r_tmp1, uimm);
1358 tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
1359 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1360 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1361 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1362 tcg_temp_free(r_tmp2);
1363 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1364 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1365 tcg_temp_free(r_tmp1);
1366 /* operands of same sign, result different sign */
1367 generate_exception(ctx, EXCP_OVERFLOW);
1368 gen_set_label(l1);
1370 tcg_gen_ext32s_tl(t0, t0);
1372 opn = "addi";
1373 break;
1374 case OPC_ADDIU:
1375 tcg_gen_ext32s_tl(t0, t0);
1376 tcg_gen_addi_tl(t0, t0, uimm);
1377 tcg_gen_ext32s_tl(t0, t0);
1378 opn = "addiu";
1379 break;
1380 #if defined(TARGET_MIPS64)
1381 case OPC_DADDI:
1383 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1384 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1385 int l1 = gen_new_label();
1387 save_cpu_state(ctx, 1);
1388 tcg_gen_mov_tl(r_tmp1, t0);
1389 tcg_gen_addi_tl(t0, t0, uimm);
1391 tcg_gen_xori_tl(r_tmp1, r_tmp1, uimm);
1392 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1393 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1394 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1395 tcg_temp_free(r_tmp2);
1396 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1397 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1398 tcg_temp_free(r_tmp1);
1399 /* operands of same sign, result different sign */
1400 generate_exception(ctx, EXCP_OVERFLOW);
1401 gen_set_label(l1);
1403 opn = "daddi";
1404 break;
1405 case OPC_DADDIU:
1406 tcg_gen_addi_tl(t0, t0, uimm);
1407 opn = "daddiu";
1408 break;
1409 #endif
1410 case OPC_SLTI:
1411 gen_op_lti(t0, uimm);
1412 opn = "slti";
1413 break;
1414 case OPC_SLTIU:
1415 gen_op_ltiu(t0, uimm);
1416 opn = "sltiu";
1417 break;
1418 case OPC_ANDI:
1419 tcg_gen_andi_tl(t0, t0, uimm);
1420 opn = "andi";
1421 break;
1422 case OPC_ORI:
1423 tcg_gen_ori_tl(t0, t0, uimm);
1424 opn = "ori";
1425 break;
1426 case OPC_XORI:
1427 tcg_gen_xori_tl(t0, t0, uimm);
1428 opn = "xori";
1429 break;
1430 case OPC_LUI:
1431 opn = "lui";
1432 break;
1433 case OPC_SLL:
1434 tcg_gen_ext32u_tl(t0, t0);
1435 tcg_gen_shli_tl(t0, t0, uimm);
1436 tcg_gen_ext32s_tl(t0, t0);
1437 opn = "sll";
1438 break;
1439 case OPC_SRA:
1440 tcg_gen_ext32s_tl(t0, t0);
1441 tcg_gen_sari_tl(t0, t0, uimm);
1442 tcg_gen_ext32s_tl(t0, t0);
1443 opn = "sra";
1444 break;
1445 case OPC_SRL:
1446 switch ((ctx->opcode >> 21) & 0x1f) {
1447 case 0:
1448 tcg_gen_ext32u_tl(t0, t0);
1449 tcg_gen_shri_tl(t0, t0, uimm);
1450 tcg_gen_ext32s_tl(t0, t0);
1451 opn = "srl";
1452 break;
1453 case 1:
1454 /* rotr is decoded as srl on non-R2 CPUs */
1455 if (env->insn_flags & ISA_MIPS32R2) {
1456 if (uimm != 0) {
1457 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1458 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1460 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1461 tcg_gen_movi_i32(r_tmp2, 0x20);
1462 tcg_gen_subi_i32(r_tmp2, r_tmp2, uimm);
1463 tcg_gen_shl_i32(r_tmp2, r_tmp1, r_tmp2);
1464 tcg_gen_shri_i32(r_tmp1, r_tmp1, uimm);
1465 tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp2);
1466 tcg_gen_ext_i32_tl(t0, r_tmp1);
1467 tcg_temp_free(r_tmp1);
1468 tcg_temp_free(r_tmp2);
1470 opn = "rotr";
1471 } else {
1472 tcg_gen_ext32u_tl(t0, t0);
1473 tcg_gen_shri_tl(t0, t0, uimm);
1474 tcg_gen_ext32s_tl(t0, t0);
1475 opn = "srl";
1477 break;
1478 default:
1479 MIPS_INVAL("invalid srl flag");
1480 generate_exception(ctx, EXCP_RI);
1481 break;
1483 break;
1484 #if defined(TARGET_MIPS64)
1485 case OPC_DSLL:
1486 tcg_gen_shli_tl(t0, t0, uimm);
1487 opn = "dsll";
1488 break;
1489 case OPC_DSRA:
1490 tcg_gen_sari_tl(t0, t0, uimm);
1491 opn = "dsra";
1492 break;
1493 case OPC_DSRL:
1494 switch ((ctx->opcode >> 21) & 0x1f) {
1495 case 0:
1496 tcg_gen_shri_tl(t0, t0, uimm);
1497 opn = "dsrl";
1498 break;
1499 case 1:
1500 /* drotr is decoded as dsrl on non-R2 CPUs */
1501 if (env->insn_flags & ISA_MIPS32R2) {
1502 if (uimm != 0) {
1503 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1505 tcg_gen_movi_tl(r_tmp1, 0x40);
1506 tcg_gen_subi_tl(r_tmp1, r_tmp1, uimm);
1507 tcg_gen_shl_tl(r_tmp1, t0, r_tmp1);
1508 tcg_gen_shri_tl(t0, t0, uimm);
1509 tcg_gen_or_tl(t0, t0, r_tmp1);
1510 tcg_temp_free(r_tmp1);
1512 opn = "drotr";
1513 } else {
1514 tcg_gen_shri_tl(t0, t0, uimm);
1515 opn = "dsrl";
1517 break;
1518 default:
1519 MIPS_INVAL("invalid dsrl flag");
1520 generate_exception(ctx, EXCP_RI);
1521 break;
1523 break;
1524 case OPC_DSLL32:
1525 tcg_gen_shli_tl(t0, t0, uimm + 32);
1526 opn = "dsll32";
1527 break;
1528 case OPC_DSRA32:
1529 tcg_gen_sari_tl(t0, t0, uimm + 32);
1530 opn = "dsra32";
1531 break;
1532 case OPC_DSRL32:
1533 switch ((ctx->opcode >> 21) & 0x1f) {
1534 case 0:
1535 tcg_gen_shri_tl(t0, t0, uimm + 32);
1536 opn = "dsrl32";
1537 break;
1538 case 1:
1539 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1540 if (env->insn_flags & ISA_MIPS32R2) {
1541 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1542 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1544 tcg_gen_movi_tl(r_tmp1, 0x40);
1545 tcg_gen_movi_tl(r_tmp2, 32);
1546 tcg_gen_addi_tl(r_tmp2, r_tmp2, uimm);
1547 tcg_gen_sub_tl(r_tmp1, r_tmp1, r_tmp2);
1548 tcg_gen_shl_tl(r_tmp1, t0, r_tmp1);
1549 tcg_gen_shr_tl(t0, t0, r_tmp2);
1550 tcg_gen_or_tl(t0, t0, r_tmp1);
1551 tcg_temp_free(r_tmp1);
1552 tcg_temp_free(r_tmp2);
1553 opn = "drotr32";
1554 } else {
1555 tcg_gen_shri_tl(t0, t0, uimm + 32);
1556 opn = "dsrl32";
1558 break;
1559 default:
1560 MIPS_INVAL("invalid dsrl32 flag");
1561 generate_exception(ctx, EXCP_RI);
1562 break;
1564 break;
1565 #endif
1566 default:
1567 MIPS_INVAL(opn);
1568 generate_exception(ctx, EXCP_RI);
1569 goto out;
1571 gen_store_gpr(t0, rt);
1572 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1573 out:
1574 tcg_temp_free(t0);
1577 /* Arithmetic */
1578 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1579 int rd, int rs, int rt)
1581 const char *opn = "arith";
1582 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1583 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1585 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1586 && opc != OPC_DADD && opc != OPC_DSUB) {
1587 /* If no destination, treat it as a NOP.
1588 For add & sub, we must generate the overflow exception when needed. */
1589 MIPS_DEBUG("NOP");
1590 goto out;
1592 gen_load_gpr(t0, rs);
1593 /* Specialcase the conventional move operation. */
1594 if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1595 || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1596 gen_store_gpr(t0, rd);
1597 goto out;
1599 gen_load_gpr(t1, rt);
1600 switch (opc) {
1601 case OPC_ADD:
1603 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1604 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1605 int l1 = gen_new_label();
1607 save_cpu_state(ctx, 1);
1608 tcg_gen_ext32s_tl(r_tmp1, t0);
1609 tcg_gen_ext32s_tl(r_tmp2, t1);
1610 tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
1612 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1613 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1614 tcg_gen_xor_tl(r_tmp2, t0, t1);
1615 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1616 tcg_temp_free(r_tmp2);
1617 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1618 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1619 tcg_temp_free(r_tmp1);
1620 /* operands of same sign, result different sign */
1621 generate_exception(ctx, EXCP_OVERFLOW);
1622 gen_set_label(l1);
1624 tcg_gen_ext32s_tl(t0, t0);
1626 opn = "add";
1627 break;
1628 case OPC_ADDU:
1629 tcg_gen_ext32s_tl(t0, t0);
1630 tcg_gen_ext32s_tl(t1, t1);
1631 tcg_gen_add_tl(t0, t0, t1);
1632 tcg_gen_ext32s_tl(t0, t0);
1633 opn = "addu";
1634 break;
1635 case OPC_SUB:
1637 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1638 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1639 int l1 = gen_new_label();
1641 save_cpu_state(ctx, 1);
1642 tcg_gen_ext32s_tl(r_tmp1, t0);
1643 tcg_gen_ext32s_tl(r_tmp2, t1);
1644 tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
1646 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1647 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1648 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1649 tcg_temp_free(r_tmp2);
1650 tcg_gen_shri_tl(r_tmp1, r_tmp1, 31);
1651 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1652 tcg_temp_free(r_tmp1);
1653 /* operands of different sign, first operand and result different sign */
1654 generate_exception(ctx, EXCP_OVERFLOW);
1655 gen_set_label(l1);
1657 tcg_gen_ext32s_tl(t0, t0);
1659 opn = "sub";
1660 break;
1661 case OPC_SUBU:
1662 tcg_gen_ext32s_tl(t0, t0);
1663 tcg_gen_ext32s_tl(t1, t1);
1664 tcg_gen_sub_tl(t0, t0, t1);
1665 tcg_gen_ext32s_tl(t0, t0);
1666 opn = "subu";
1667 break;
1668 #if defined(TARGET_MIPS64)
1669 case OPC_DADD:
1671 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1672 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1673 int l1 = gen_new_label();
1675 save_cpu_state(ctx, 1);
1676 tcg_gen_mov_tl(r_tmp1, t0);
1677 tcg_gen_add_tl(t0, t0, t1);
1679 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1680 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1681 tcg_gen_xor_tl(r_tmp2, t0, t1);
1682 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1683 tcg_temp_free(r_tmp2);
1684 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1685 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1686 tcg_temp_free(r_tmp1);
1687 /* operands of same sign, result different sign */
1688 generate_exception(ctx, EXCP_OVERFLOW);
1689 gen_set_label(l1);
1691 opn = "dadd";
1692 break;
1693 case OPC_DADDU:
1694 tcg_gen_add_tl(t0, t0, t1);
1695 opn = "daddu";
1696 break;
1697 case OPC_DSUB:
1699 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_TL);
1700 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1701 int l1 = gen_new_label();
1703 save_cpu_state(ctx, 1);
1704 tcg_gen_mov_tl(r_tmp1, t0);
1705 tcg_gen_sub_tl(t0, t0, t1);
1707 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1708 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1709 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1710 tcg_temp_free(r_tmp2);
1711 tcg_gen_shri_tl(r_tmp1, r_tmp1, 63);
1712 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp1, 0, l1);
1713 tcg_temp_free(r_tmp1);
1714 /* operands of different sign, first operand and result different sign */
1715 generate_exception(ctx, EXCP_OVERFLOW);
1716 gen_set_label(l1);
1718 opn = "dsub";
1719 break;
1720 case OPC_DSUBU:
1721 tcg_gen_sub_tl(t0, t0, t1);
1722 opn = "dsubu";
1723 break;
1724 #endif
1725 case OPC_SLT:
1726 gen_op_lt(t0, t1);
1727 opn = "slt";
1728 break;
1729 case OPC_SLTU:
1730 gen_op_ltu(t0, t1);
1731 opn = "sltu";
1732 break;
1733 case OPC_AND:
1734 tcg_gen_and_tl(t0, t0, t1);
1735 opn = "and";
1736 break;
1737 case OPC_NOR:
1738 tcg_gen_or_tl(t0, t0, t1);
1739 tcg_gen_not_tl(t0, t0);
1740 opn = "nor";
1741 break;
1742 case OPC_OR:
1743 tcg_gen_or_tl(t0, t0, t1);
1744 opn = "or";
1745 break;
1746 case OPC_XOR:
1747 tcg_gen_xor_tl(t0, t0, t1);
1748 opn = "xor";
1749 break;
1750 case OPC_MUL:
1751 tcg_gen_ext32s_tl(t0, t0);
1752 tcg_gen_ext32s_tl(t1, t1);
1753 tcg_gen_mul_tl(t0, t0, t1);
1754 tcg_gen_ext32s_tl(t0, t0);
1755 opn = "mul";
1756 break;
1757 case OPC_MOVN:
1759 int l1 = gen_new_label();
1761 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1762 gen_store_gpr(t0, rd);
1763 gen_set_label(l1);
1765 opn = "movn";
1766 goto print;
1767 case OPC_MOVZ:
1769 int l1 = gen_new_label();
1771 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
1772 gen_store_gpr(t0, rd);
1773 gen_set_label(l1);
1775 opn = "movz";
1776 goto print;
1777 case OPC_SLLV:
1778 tcg_gen_ext32u_tl(t0, t0);
1779 tcg_gen_ext32u_tl(t1, t1);
1780 tcg_gen_andi_tl(t0, t0, 0x1f);
1781 tcg_gen_shl_tl(t0, t1, t0);
1782 tcg_gen_ext32s_tl(t0, t0);
1783 opn = "sllv";
1784 break;
1785 case OPC_SRAV:
1786 tcg_gen_ext32s_tl(t1, t1);
1787 tcg_gen_andi_tl(t0, t0, 0x1f);
1788 tcg_gen_sar_tl(t0, t1, t0);
1789 tcg_gen_ext32s_tl(t0, t0);
1790 opn = "srav";
1791 break;
1792 case OPC_SRLV:
1793 switch ((ctx->opcode >> 6) & 0x1f) {
1794 case 0:
1795 tcg_gen_ext32u_tl(t1, t1);
1796 tcg_gen_andi_tl(t0, t0, 0x1f);
1797 tcg_gen_shr_tl(t0, t1, t0);
1798 tcg_gen_ext32s_tl(t0, t0);
1799 opn = "srlv";
1800 break;
1801 case 1:
1802 /* rotrv is decoded as srlv on non-R2 CPUs */
1803 if (env->insn_flags & ISA_MIPS32R2) {
1804 int l1 = gen_new_label();
1805 int l2 = gen_new_label();
1807 tcg_gen_andi_tl(t0, t0, 0x1f);
1808 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1810 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1811 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1812 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
1814 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1815 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1816 tcg_gen_movi_i32(r_tmp3, 0x20);
1817 tcg_gen_sub_i32(r_tmp3, r_tmp3, r_tmp1);
1818 tcg_gen_shl_i32(r_tmp3, r_tmp2, r_tmp3);
1819 tcg_gen_shr_i32(r_tmp1, r_tmp2, r_tmp1);
1820 tcg_gen_or_i32(r_tmp1, r_tmp1, r_tmp3);
1821 tcg_gen_ext_i32_tl(t0, r_tmp1);
1822 tcg_temp_free(r_tmp1);
1823 tcg_temp_free(r_tmp2);
1824 tcg_temp_free(r_tmp3);
1825 tcg_gen_br(l2);
1827 gen_set_label(l1);
1828 tcg_gen_mov_tl(t0, t1);
1829 gen_set_label(l2);
1830 opn = "rotrv";
1831 } else {
1832 tcg_gen_ext32u_tl(t1, t1);
1833 tcg_gen_andi_tl(t0, t0, 0x1f);
1834 tcg_gen_shr_tl(t0, t1, t0);
1835 tcg_gen_ext32s_tl(t0, t0);
1836 opn = "srlv";
1838 break;
1839 default:
1840 MIPS_INVAL("invalid srlv flag");
1841 generate_exception(ctx, EXCP_RI);
1842 break;
1844 break;
1845 #if defined(TARGET_MIPS64)
1846 case OPC_DSLLV:
1847 tcg_gen_andi_tl(t0, t0, 0x3f);
1848 tcg_gen_shl_tl(t0, t1, t0);
1849 opn = "dsllv";
1850 break;
1851 case OPC_DSRAV:
1852 tcg_gen_andi_tl(t0, t0, 0x3f);
1853 tcg_gen_sar_tl(t0, t1, t0);
1854 opn = "dsrav";
1855 break;
1856 case OPC_DSRLV:
1857 switch ((ctx->opcode >> 6) & 0x1f) {
1858 case 0:
1859 tcg_gen_andi_tl(t0, t0, 0x3f);
1860 tcg_gen_shr_tl(t0, t1, t0);
1861 opn = "dsrlv";
1862 break;
1863 case 1:
1864 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1865 if (env->insn_flags & ISA_MIPS32R2) {
1866 int l1 = gen_new_label();
1867 int l2 = gen_new_label();
1869 tcg_gen_andi_tl(t0, t0, 0x3f);
1870 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1872 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1874 tcg_gen_movi_tl(r_tmp1, 0x40);
1875 tcg_gen_sub_tl(r_tmp1, r_tmp1, t0);
1876 tcg_gen_shl_tl(r_tmp1, t1, r_tmp1);
1877 tcg_gen_shr_tl(t0, t1, t0);
1878 tcg_gen_or_tl(t0, t0, r_tmp1);
1879 tcg_temp_free(r_tmp1);
1880 tcg_gen_br(l2);
1882 gen_set_label(l1);
1883 tcg_gen_mov_tl(t0, t1);
1884 gen_set_label(l2);
1885 opn = "drotrv";
1886 } else {
1887 tcg_gen_andi_tl(t0, t0, 0x3f);
1888 tcg_gen_shr_tl(t0, t1, t0);
1889 opn = "dsrlv";
1891 break;
1892 default:
1893 MIPS_INVAL("invalid dsrlv flag");
1894 generate_exception(ctx, EXCP_RI);
1895 break;
1897 break;
1898 #endif
1899 default:
1900 MIPS_INVAL(opn);
1901 generate_exception(ctx, EXCP_RI);
1902 goto out;
1904 gen_store_gpr(t0, rd);
1905 print:
1906 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1907 out:
1908 tcg_temp_free(t0);
1909 tcg_temp_free(t1);
1912 /* Arithmetic on HI/LO registers */
1913 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1915 const char *opn = "hilo";
1916 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1918 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1919 /* Treat as NOP. */
1920 MIPS_DEBUG("NOP");
1921 goto out;
1923 switch (opc) {
1924 case OPC_MFHI:
1925 gen_load_HI(t0, 0);
1926 gen_store_gpr(t0, reg);
1927 opn = "mfhi";
1928 break;
1929 case OPC_MFLO:
1930 gen_load_LO(t0, 0);
1931 gen_store_gpr(t0, reg);
1932 opn = "mflo";
1933 break;
1934 case OPC_MTHI:
1935 gen_load_gpr(t0, reg);
1936 gen_store_HI(t0, 0);
1937 opn = "mthi";
1938 break;
1939 case OPC_MTLO:
1940 gen_load_gpr(t0, reg);
1941 gen_store_LO(t0, 0);
1942 opn = "mtlo";
1943 break;
1944 default:
1945 MIPS_INVAL(opn);
1946 generate_exception(ctx, EXCP_RI);
1947 goto out;
1949 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1950 out:
1951 tcg_temp_free(t0);
1954 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1955 int rs, int rt)
1957 const char *opn = "mul/div";
1958 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1959 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1961 gen_load_gpr(t0, rs);
1962 gen_load_gpr(t1, rt);
1963 switch (opc) {
1964 case OPC_DIV:
1966 int l1 = gen_new_label();
1968 tcg_gen_ext32s_tl(t0, t0);
1969 tcg_gen_ext32s_tl(t1, t1);
1970 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1972 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
1973 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
1974 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64);
1976 tcg_gen_ext_tl_i64(r_tmp1, t0);
1977 tcg_gen_ext_tl_i64(r_tmp2, t1);
1978 tcg_gen_div_i64(r_tmp3, r_tmp1, r_tmp2);
1979 tcg_gen_rem_i64(r_tmp2, r_tmp1, r_tmp2);
1980 tcg_gen_trunc_i64_tl(t0, r_tmp3);
1981 tcg_gen_trunc_i64_tl(t1, r_tmp2);
1982 tcg_temp_free(r_tmp1);
1983 tcg_temp_free(r_tmp2);
1984 tcg_temp_free(r_tmp3);
1985 tcg_gen_ext32s_tl(t0, t0);
1986 tcg_gen_ext32s_tl(t1, t1);
1987 gen_store_LO(t0, 0);
1988 gen_store_HI(t1, 0);
1990 gen_set_label(l1);
1992 opn = "div";
1993 break;
1994 case OPC_DIVU:
1996 int l1 = gen_new_label();
1998 tcg_gen_ext32s_tl(t1, t1);
1999 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2001 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
2002 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
2003 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
2005 tcg_gen_trunc_tl_i32(r_tmp1, t0);
2006 tcg_gen_trunc_tl_i32(r_tmp2, t1);
2007 tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2);
2008 tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2);
2009 tcg_gen_ext_i32_tl(t0, r_tmp3);
2010 tcg_gen_ext_i32_tl(t1, r_tmp1);
2011 tcg_temp_free(r_tmp1);
2012 tcg_temp_free(r_tmp2);
2013 tcg_temp_free(r_tmp3);
2014 gen_store_LO(t0, 0);
2015 gen_store_HI(t1, 0);
2017 gen_set_label(l1);
2019 opn = "divu";
2020 break;
2021 case OPC_MULT:
2023 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2024 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2026 tcg_gen_ext32s_tl(t0, t0);
2027 tcg_gen_ext32s_tl(t1, t1);
2028 tcg_gen_ext_tl_i64(r_tmp1, t0);
2029 tcg_gen_ext_tl_i64(r_tmp2, t1);
2030 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2031 tcg_temp_free(r_tmp2);
2032 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2033 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2034 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2035 tcg_temp_free(r_tmp1);
2036 tcg_gen_ext32s_tl(t0, t0);
2037 tcg_gen_ext32s_tl(t1, t1);
2038 gen_store_LO(t0, 0);
2039 gen_store_HI(t1, 0);
2041 opn = "mult";
2042 break;
2043 case OPC_MULTU:
2045 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2046 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2048 tcg_gen_ext32u_tl(t0, t0);
2049 tcg_gen_ext32u_tl(t1, t1);
2050 tcg_gen_extu_tl_i64(r_tmp1, t0);
2051 tcg_gen_extu_tl_i64(r_tmp2, t1);
2052 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2053 tcg_temp_free(r_tmp2);
2054 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2055 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2056 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2057 tcg_temp_free(r_tmp1);
2058 tcg_gen_ext32s_tl(t0, t0);
2059 tcg_gen_ext32s_tl(t1, t1);
2060 gen_store_LO(t0, 0);
2061 gen_store_HI(t1, 0);
2063 opn = "multu";
2064 break;
2065 #if defined(TARGET_MIPS64)
2066 case OPC_DDIV:
2068 int l1 = gen_new_label();
2070 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2072 int l2 = gen_new_label();
2074 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2075 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2077 tcg_gen_movi_tl(t1, 0);
2078 gen_store_LO(t0, 0);
2079 gen_store_HI(t1, 0);
2080 tcg_gen_br(l1);
2082 gen_set_label(l2);
2084 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2085 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2087 tcg_gen_div_i64(r_tmp1, t0, t1);
2088 tcg_gen_rem_i64(r_tmp2, t0, t1);
2089 gen_store_LO(r_tmp1, 0);
2090 gen_store_HI(r_tmp2, 0);
2091 tcg_temp_free(r_tmp1);
2092 tcg_temp_free(r_tmp2);
2095 gen_set_label(l1);
2097 opn = "ddiv";
2098 break;
2099 case OPC_DDIVU:
2101 int l1 = gen_new_label();
2103 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2105 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2106 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2108 tcg_gen_divu_i64(r_tmp1, t0, t1);
2109 tcg_gen_remu_i64(r_tmp2, t0, t1);
2110 tcg_temp_free(r_tmp1);
2111 tcg_temp_free(r_tmp2);
2112 gen_store_LO(r_tmp1, 0);
2113 gen_store_HI(r_tmp2, 0);
2115 gen_set_label(l1);
2117 opn = "ddivu";
2118 break;
2119 case OPC_DMULT:
2120 tcg_gen_helper_0_2(do_dmult, t0, t1);
2121 opn = "dmult";
2122 break;
2123 case OPC_DMULTU:
2124 tcg_gen_helper_0_2(do_dmultu, t0, t1);
2125 opn = "dmultu";
2126 break;
2127 #endif
2128 case OPC_MADD:
2130 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2131 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2133 tcg_gen_ext32s_tl(t0, t0);
2134 tcg_gen_ext32s_tl(t1, t1);
2135 tcg_gen_ext_tl_i64(r_tmp1, t0);
2136 tcg_gen_ext_tl_i64(r_tmp2, t1);
2137 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2138 gen_load_LO(t0, 0);
2139 gen_load_HI(t1, 0);
2140 tcg_gen_concat_tl_i64(r_tmp2, t0, t1);
2141 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
2142 tcg_temp_free(r_tmp2);
2143 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2144 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2145 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2146 tcg_temp_free(r_tmp1);
2147 tcg_gen_ext32s_tl(t0, t0);
2148 tcg_gen_ext32s_tl(t1, t1);
2149 gen_store_LO(t0, 0);
2150 gen_store_HI(t1, 0);
2152 opn = "madd";
2153 break;
2154 case OPC_MADDU:
2156 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2157 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2159 tcg_gen_ext32u_tl(t0, t0);
2160 tcg_gen_ext32u_tl(t1, t1);
2161 tcg_gen_extu_tl_i64(r_tmp1, t0);
2162 tcg_gen_extu_tl_i64(r_tmp2, t1);
2163 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2164 gen_load_LO(t0, 0);
2165 gen_load_HI(t1, 0);
2166 tcg_gen_concat_tl_i64(r_tmp2, t0, t1);
2167 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
2168 tcg_temp_free(r_tmp2);
2169 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2170 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2171 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2172 tcg_temp_free(r_tmp1);
2173 tcg_gen_ext32s_tl(t0, t0);
2174 tcg_gen_ext32s_tl(t1, t1);
2175 gen_store_LO(t0, 0);
2176 gen_store_HI(t1, 0);
2178 opn = "maddu";
2179 break;
2180 case OPC_MSUB:
2182 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2183 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2185 tcg_gen_ext32s_tl(t0, t0);
2186 tcg_gen_ext32s_tl(t1, t1);
2187 tcg_gen_ext_tl_i64(r_tmp1, t0);
2188 tcg_gen_ext_tl_i64(r_tmp2, t1);
2189 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2190 gen_load_LO(t0, 0);
2191 gen_load_HI(t1, 0);
2192 tcg_gen_concat_tl_i64(r_tmp2, t0, t1);
2193 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
2194 tcg_temp_free(r_tmp2);
2195 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2196 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2197 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2198 tcg_temp_free(r_tmp1);
2199 tcg_gen_ext32s_tl(t0, t0);
2200 tcg_gen_ext32s_tl(t1, t1);
2201 gen_store_LO(t0, 0);
2202 gen_store_HI(t1, 0);
2204 opn = "msub";
2205 break;
2206 case OPC_MSUBU:
2208 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2209 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2211 tcg_gen_ext32u_tl(t0, t0);
2212 tcg_gen_ext32u_tl(t1, t1);
2213 tcg_gen_extu_tl_i64(r_tmp1, t0);
2214 tcg_gen_extu_tl_i64(r_tmp2, t1);
2215 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2216 gen_load_LO(t0, 0);
2217 gen_load_HI(t1, 0);
2218 tcg_gen_concat_tl_i64(r_tmp2, t0, t1);
2219 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
2220 tcg_temp_free(r_tmp2);
2221 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2222 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2223 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2224 tcg_temp_free(r_tmp1);
2225 tcg_gen_ext32s_tl(t0, t0);
2226 tcg_gen_ext32s_tl(t1, t1);
2227 gen_store_LO(t0, 0);
2228 gen_store_HI(t1, 0);
2230 opn = "msubu";
2231 break;
2232 default:
2233 MIPS_INVAL(opn);
2234 generate_exception(ctx, EXCP_RI);
2235 goto out;
2237 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2238 out:
2239 tcg_temp_free(t0);
2240 tcg_temp_free(t1);
2243 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2244 int rd, int rs, int rt)
2246 const char *opn = "mul vr54xx";
2247 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2248 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2250 gen_load_gpr(t0, rs);
2251 gen_load_gpr(t1, rt);
2253 switch (opc) {
2254 case OPC_VR54XX_MULS:
2255 tcg_gen_helper_1_2(do_muls, t0, t0, t1);
2256 opn = "muls";
2257 break;
2258 case OPC_VR54XX_MULSU:
2259 tcg_gen_helper_1_2(do_mulsu, t0, t0, t1);
2260 opn = "mulsu";
2261 break;
2262 case OPC_VR54XX_MACC:
2263 tcg_gen_helper_1_2(do_macc, t0, t0, t1);
2264 opn = "macc";
2265 break;
2266 case OPC_VR54XX_MACCU:
2267 tcg_gen_helper_1_2(do_maccu, t0, t0, t1);
2268 opn = "maccu";
2269 break;
2270 case OPC_VR54XX_MSAC:
2271 tcg_gen_helper_1_2(do_msac, t0, t0, t1);
2272 opn = "msac";
2273 break;
2274 case OPC_VR54XX_MSACU:
2275 tcg_gen_helper_1_2(do_msacu, t0, t0, t1);
2276 opn = "msacu";
2277 break;
2278 case OPC_VR54XX_MULHI:
2279 tcg_gen_helper_1_2(do_mulhi, t0, t0, t1);
2280 opn = "mulhi";
2281 break;
2282 case OPC_VR54XX_MULHIU:
2283 tcg_gen_helper_1_2(do_mulhiu, t0, t0, t1);
2284 opn = "mulhiu";
2285 break;
2286 case OPC_VR54XX_MULSHI:
2287 tcg_gen_helper_1_2(do_mulshi, t0, t0, t1);
2288 opn = "mulshi";
2289 break;
2290 case OPC_VR54XX_MULSHIU:
2291 tcg_gen_helper_1_2(do_mulshiu, t0, t0, t1);
2292 opn = "mulshiu";
2293 break;
2294 case OPC_VR54XX_MACCHI:
2295 tcg_gen_helper_1_2(do_macchi, t0, t0, t1);
2296 opn = "macchi";
2297 break;
2298 case OPC_VR54XX_MACCHIU:
2299 tcg_gen_helper_1_2(do_macchiu, t0, t0, t1);
2300 opn = "macchiu";
2301 break;
2302 case OPC_VR54XX_MSACHI:
2303 tcg_gen_helper_1_2(do_msachi, t0, t0, t1);
2304 opn = "msachi";
2305 break;
2306 case OPC_VR54XX_MSACHIU:
2307 tcg_gen_helper_1_2(do_msachiu, t0, t0, t1);
2308 opn = "msachiu";
2309 break;
2310 default:
2311 MIPS_INVAL("mul vr54xx");
2312 generate_exception(ctx, EXCP_RI);
2313 goto out;
2315 gen_store_gpr(t0, rd);
2316 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2318 out:
2319 tcg_temp_free(t0);
2320 tcg_temp_free(t1);
2323 static void gen_cl (DisasContext *ctx, uint32_t opc,
2324 int rd, int rs)
2326 const char *opn = "CLx";
2327 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2329 if (rd == 0) {
2330 /* Treat as NOP. */
2331 MIPS_DEBUG("NOP");
2332 goto out;
2334 gen_load_gpr(t0, rs);
2335 switch (opc) {
2336 case OPC_CLO:
2337 tcg_gen_helper_1_1(do_clo, t0, t0);
2338 opn = "clo";
2339 break;
2340 case OPC_CLZ:
2341 tcg_gen_helper_1_1(do_clz, t0, t0);
2342 opn = "clz";
2343 break;
2344 #if defined(TARGET_MIPS64)
2345 case OPC_DCLO:
2346 tcg_gen_helper_1_1(do_dclo, t0, t0);
2347 opn = "dclo";
2348 break;
2349 case OPC_DCLZ:
2350 tcg_gen_helper_1_1(do_dclz, t0, t0);
2351 opn = "dclz";
2352 break;
2353 #endif
2354 default:
2355 MIPS_INVAL(opn);
2356 generate_exception(ctx, EXCP_RI);
2357 goto out;
2359 gen_store_gpr(t0, rd);
2360 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2362 out:
2363 tcg_temp_free(t0);
2366 /* Traps */
2367 static void gen_trap (DisasContext *ctx, uint32_t opc,
2368 int rs, int rt, int16_t imm)
2370 int cond;
2371 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2372 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2374 cond = 0;
2375 /* Load needed operands */
2376 switch (opc) {
2377 case OPC_TEQ:
2378 case OPC_TGE:
2379 case OPC_TGEU:
2380 case OPC_TLT:
2381 case OPC_TLTU:
2382 case OPC_TNE:
2383 /* Compare two registers */
2384 if (rs != rt) {
2385 gen_load_gpr(t0, rs);
2386 gen_load_gpr(t1, rt);
2387 cond = 1;
2389 break;
2390 case OPC_TEQI:
2391 case OPC_TGEI:
2392 case OPC_TGEIU:
2393 case OPC_TLTI:
2394 case OPC_TLTIU:
2395 case OPC_TNEI:
2396 /* Compare register to immediate */
2397 if (rs != 0 || imm != 0) {
2398 gen_load_gpr(t0, rs);
2399 tcg_gen_movi_tl(t1, (int32_t)imm);
2400 cond = 1;
2402 break;
2404 if (cond == 0) {
2405 switch (opc) {
2406 case OPC_TEQ: /* rs == rs */
2407 case OPC_TEQI: /* r0 == 0 */
2408 case OPC_TGE: /* rs >= rs */
2409 case OPC_TGEI: /* r0 >= 0 */
2410 case OPC_TGEU: /* rs >= rs unsigned */
2411 case OPC_TGEIU: /* r0 >= 0 unsigned */
2412 /* Always trap */
2413 tcg_gen_movi_tl(t0, 1);
2414 break;
2415 case OPC_TLT: /* rs < rs */
2416 case OPC_TLTI: /* r0 < 0 */
2417 case OPC_TLTU: /* rs < rs unsigned */
2418 case OPC_TLTIU: /* r0 < 0 unsigned */
2419 case OPC_TNE: /* rs != rs */
2420 case OPC_TNEI: /* r0 != 0 */
2421 /* Never trap: treat as NOP. */
2422 goto out;
2423 default:
2424 MIPS_INVAL("trap");
2425 generate_exception(ctx, EXCP_RI);
2426 goto out;
2428 } else {
2429 switch (opc) {
2430 case OPC_TEQ:
2431 case OPC_TEQI:
2432 gen_op_eq(t0, t1);
2433 break;
2434 case OPC_TGE:
2435 case OPC_TGEI:
2436 gen_op_ge(t0, t1);
2437 break;
2438 case OPC_TGEU:
2439 case OPC_TGEIU:
2440 gen_op_geu(t0, t1);
2441 break;
2442 case OPC_TLT:
2443 case OPC_TLTI:
2444 gen_op_lt(t0, t1);
2445 break;
2446 case OPC_TLTU:
2447 case OPC_TLTIU:
2448 gen_op_ltu(t0, t1);
2449 break;
2450 case OPC_TNE:
2451 case OPC_TNEI:
2452 gen_op_ne(t0, t1);
2453 break;
2454 default:
2455 MIPS_INVAL("trap");
2456 generate_exception(ctx, EXCP_RI);
2457 goto out;
2460 save_cpu_state(ctx, 1);
2462 int l1 = gen_new_label();
2464 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2465 tcg_gen_helper_0_i(do_raise_exception, EXCP_TRAP);
2466 gen_set_label(l1);
2468 ctx->bstate = BS_STOP;
2469 out:
2470 tcg_temp_free(t0);
2471 tcg_temp_free(t1);
2474 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2476 TranslationBlock *tb;
2477 tb = ctx->tb;
2478 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2479 tcg_gen_goto_tb(n);
2480 gen_save_pc(dest);
2481 tcg_gen_exit_tb((long)tb + n);
2482 } else {
2483 gen_save_pc(dest);
2484 tcg_gen_exit_tb(0);
2488 /* Branches (before delay slot) */
2489 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2490 int rs, int rt, int32_t offset)
2492 target_ulong btgt = -1;
2493 int blink = 0;
2494 int bcond_compute = 0;
2495 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2496 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2498 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2499 #ifdef MIPS_DEBUG_DISAS
2500 if (loglevel & CPU_LOG_TB_IN_ASM) {
2501 fprintf(logfile,
2502 "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
2503 ctx->pc);
2505 #endif
2506 generate_exception(ctx, EXCP_RI);
2507 goto out;
2510 /* Load needed operands */
2511 switch (opc) {
2512 case OPC_BEQ:
2513 case OPC_BEQL:
2514 case OPC_BNE:
2515 case OPC_BNEL:
2516 /* Compare two registers */
2517 if (rs != rt) {
2518 gen_load_gpr(t0, rs);
2519 gen_load_gpr(t1, rt);
2520 bcond_compute = 1;
2522 btgt = ctx->pc + 4 + offset;
2523 break;
2524 case OPC_BGEZ:
2525 case OPC_BGEZAL:
2526 case OPC_BGEZALL:
2527 case OPC_BGEZL:
2528 case OPC_BGTZ:
2529 case OPC_BGTZL:
2530 case OPC_BLEZ:
2531 case OPC_BLEZL:
2532 case OPC_BLTZ:
2533 case OPC_BLTZAL:
2534 case OPC_BLTZALL:
2535 case OPC_BLTZL:
2536 /* Compare to zero */
2537 if (rs != 0) {
2538 gen_load_gpr(t0, rs);
2539 bcond_compute = 1;
2541 btgt = ctx->pc + 4 + offset;
2542 break;
2543 case OPC_J:
2544 case OPC_JAL:
2545 /* Jump to immediate */
2546 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2547 break;
2548 case OPC_JR:
2549 case OPC_JALR:
2550 /* Jump to register */
2551 if (offset != 0 && offset != 16) {
2552 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2553 others are reserved. */
2554 MIPS_INVAL("jump hint");
2555 generate_exception(ctx, EXCP_RI);
2556 goto out;
2558 gen_load_gpr(btarget, rs);
2559 break;
2560 default:
2561 MIPS_INVAL("branch/jump");
2562 generate_exception(ctx, EXCP_RI);
2563 goto out;
2565 if (bcond_compute == 0) {
2566 /* No condition to be computed */
2567 switch (opc) {
2568 case OPC_BEQ: /* rx == rx */
2569 case OPC_BEQL: /* rx == rx likely */
2570 case OPC_BGEZ: /* 0 >= 0 */
2571 case OPC_BGEZL: /* 0 >= 0 likely */
2572 case OPC_BLEZ: /* 0 <= 0 */
2573 case OPC_BLEZL: /* 0 <= 0 likely */
2574 /* Always take */
2575 ctx->hflags |= MIPS_HFLAG_B;
2576 MIPS_DEBUG("balways");
2577 break;
2578 case OPC_BGEZAL: /* 0 >= 0 */
2579 case OPC_BGEZALL: /* 0 >= 0 likely */
2580 /* Always take and link */
2581 blink = 31;
2582 ctx->hflags |= MIPS_HFLAG_B;
2583 MIPS_DEBUG("balways and link");
2584 break;
2585 case OPC_BNE: /* rx != rx */
2586 case OPC_BGTZ: /* 0 > 0 */
2587 case OPC_BLTZ: /* 0 < 0 */
2588 /* Treat as NOP. */
2589 MIPS_DEBUG("bnever (NOP)");
2590 goto out;
2591 case OPC_BLTZAL: /* 0 < 0 */
2592 tcg_gen_movi_tl(t0, ctx->pc + 8);
2593 gen_store_gpr(t0, 31);
2594 MIPS_DEBUG("bnever and link");
2595 goto out;
2596 case OPC_BLTZALL: /* 0 < 0 likely */
2597 tcg_gen_movi_tl(t0, ctx->pc + 8);
2598 gen_store_gpr(t0, 31);
2599 /* Skip the instruction in the delay slot */
2600 MIPS_DEBUG("bnever, link and skip");
2601 ctx->pc += 4;
2602 goto out;
2603 case OPC_BNEL: /* rx != rx likely */
2604 case OPC_BGTZL: /* 0 > 0 likely */
2605 case OPC_BLTZL: /* 0 < 0 likely */
2606 /* Skip the instruction in the delay slot */
2607 MIPS_DEBUG("bnever and skip");
2608 ctx->pc += 4;
2609 goto out;
2610 case OPC_J:
2611 ctx->hflags |= MIPS_HFLAG_B;
2612 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2613 break;
2614 case OPC_JAL:
2615 blink = 31;
2616 ctx->hflags |= MIPS_HFLAG_B;
2617 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2618 break;
2619 case OPC_JR:
2620 ctx->hflags |= MIPS_HFLAG_BR;
2621 MIPS_DEBUG("jr %s", regnames[rs]);
2622 break;
2623 case OPC_JALR:
2624 blink = rt;
2625 ctx->hflags |= MIPS_HFLAG_BR;
2626 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2627 break;
2628 default:
2629 MIPS_INVAL("branch/jump");
2630 generate_exception(ctx, EXCP_RI);
2631 goto out;
2633 } else {
2634 switch (opc) {
2635 case OPC_BEQ:
2636 gen_op_eq(t0, t1);
2637 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2638 regnames[rs], regnames[rt], btgt);
2639 goto not_likely;
2640 case OPC_BEQL:
2641 gen_op_eq(t0, t1);
2642 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2643 regnames[rs], regnames[rt], btgt);
2644 goto likely;
2645 case OPC_BNE:
2646 gen_op_ne(t0, t1);
2647 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2648 regnames[rs], regnames[rt], btgt);
2649 goto not_likely;
2650 case OPC_BNEL:
2651 gen_op_ne(t0, t1);
2652 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2653 regnames[rs], regnames[rt], btgt);
2654 goto likely;
2655 case OPC_BGEZ:
2656 gen_op_gez(t0);
2657 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2658 goto not_likely;
2659 case OPC_BGEZL:
2660 gen_op_gez(t0);
2661 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2662 goto likely;
2663 case OPC_BGEZAL:
2664 gen_op_gez(t0);
2665 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2666 blink = 31;
2667 goto not_likely;
2668 case OPC_BGEZALL:
2669 gen_op_gez(t0);
2670 blink = 31;
2671 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2672 goto likely;
2673 case OPC_BGTZ:
2674 gen_op_gtz(t0);
2675 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2676 goto not_likely;
2677 case OPC_BGTZL:
2678 gen_op_gtz(t0);
2679 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2680 goto likely;
2681 case OPC_BLEZ:
2682 gen_op_lez(t0);
2683 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2684 goto not_likely;
2685 case OPC_BLEZL:
2686 gen_op_lez(t0);
2687 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2688 goto likely;
2689 case OPC_BLTZ:
2690 gen_op_ltz(t0);
2691 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2692 goto not_likely;
2693 case OPC_BLTZL:
2694 gen_op_ltz(t0);
2695 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2696 goto likely;
2697 case OPC_BLTZAL:
2698 gen_op_ltz(t0);
2699 blink = 31;
2700 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2701 not_likely:
2702 ctx->hflags |= MIPS_HFLAG_BC;
2703 tcg_gen_trunc_tl_i32(bcond, t0);
2704 break;
2705 case OPC_BLTZALL:
2706 gen_op_ltz(t0);
2707 blink = 31;
2708 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2709 likely:
2710 ctx->hflags |= MIPS_HFLAG_BL;
2711 tcg_gen_trunc_tl_i32(bcond, t0);
2712 break;
2713 default:
2714 MIPS_INVAL("conditional branch/jump");
2715 generate_exception(ctx, EXCP_RI);
2716 goto out;
2719 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2720 blink, ctx->hflags, btgt);
2722 ctx->btarget = btgt;
2723 if (blink > 0) {
2724 tcg_gen_movi_tl(t0, ctx->pc + 8);
2725 gen_store_gpr(t0, blink);
2728 out:
2729 tcg_temp_free(t0);
2730 tcg_temp_free(t1);
2733 /* special3 bitfield operations */
2734 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2735 int rs, int lsb, int msb)
2737 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2738 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2740 gen_load_gpr(t1, rs);
2741 switch (opc) {
2742 case OPC_EXT:
2743 if (lsb + msb > 31)
2744 goto fail;
2745 tcg_gen_helper_1_1ii(do_ext, t0, t1, lsb, msb + 1);
2746 break;
2747 #if defined(TARGET_MIPS64)
2748 case OPC_DEXTM:
2749 if (lsb + msb > 63)
2750 goto fail;
2751 tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb, msb + 1 + 32);
2752 break;
2753 case OPC_DEXTU:
2754 if (lsb + msb > 63)
2755 goto fail;
2756 tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb + 32, msb + 1);
2757 break;
2758 case OPC_DEXT:
2759 if (lsb + msb > 63)
2760 goto fail;
2761 tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb, msb + 1);
2762 break;
2763 #endif
2764 case OPC_INS:
2765 if (lsb > msb)
2766 goto fail;
2767 gen_load_gpr(t0, rt);
2768 tcg_gen_helper_1_2ii(do_ins, t0, t0, t1, lsb, msb - lsb + 1);
2769 break;
2770 #if defined(TARGET_MIPS64)
2771 case OPC_DINSM:
2772 if (lsb > msb)
2773 goto fail;
2774 gen_load_gpr(t0, rt);
2775 tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb, msb - lsb + 1 + 32);
2776 break;
2777 case OPC_DINSU:
2778 if (lsb > msb)
2779 goto fail;
2780 gen_load_gpr(t0, rt);
2781 tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb + 32, msb - lsb + 1);
2782 break;
2783 case OPC_DINS:
2784 if (lsb > msb)
2785 goto fail;
2786 gen_load_gpr(t0, rt);
2787 tcg_gen_helper_1_2ii(do_dins, t0, t0, t1, lsb, msb - lsb + 1);
2788 break;
2789 #endif
2790 default:
2791 fail:
2792 MIPS_INVAL("bitops");
2793 generate_exception(ctx, EXCP_RI);
2794 tcg_temp_free(t0);
2795 tcg_temp_free(t1);
2796 return;
2798 gen_store_gpr(t0, rt);
2799 tcg_temp_free(t0);
2800 tcg_temp_free(t1);
2803 #ifndef CONFIG_USER_ONLY
2804 /* CP0 (MMU and control) */
2805 static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
2807 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
2809 tcg_gen_ld_i32(r_tmp, cpu_env, off);
2810 tcg_gen_ext_i32_tl(t, r_tmp);
2811 tcg_temp_free(r_tmp);
2814 static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
2816 tcg_gen_ld_tl(t, cpu_env, off);
2817 tcg_gen_ext32s_tl(t, t);
2820 static inline void gen_mtc0_store32 (TCGv t, target_ulong off)
2822 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
2824 tcg_gen_trunc_tl_i32(r_tmp, t);
2825 tcg_gen_st_i32(r_tmp, cpu_env, off);
2826 tcg_temp_free(r_tmp);
2829 static inline void gen_mtc0_store64 (TCGv t, target_ulong off)
2831 tcg_gen_ext32s_tl(t, t);
2832 tcg_gen_st_tl(t, cpu_env, off);
2835 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
2837 const char *rn = "invalid";
2839 if (sel != 0)
2840 check_insn(env, ctx, ISA_MIPS32);
2842 switch (reg) {
2843 case 0:
2844 switch (sel) {
2845 case 0:
2846 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
2847 rn = "Index";
2848 break;
2849 case 1:
2850 check_insn(env, ctx, ASE_MT);
2851 tcg_gen_helper_1_0(do_mfc0_mvpcontrol, t0);
2852 rn = "MVPControl";
2853 break;
2854 case 2:
2855 check_insn(env, ctx, ASE_MT);
2856 tcg_gen_helper_1_0(do_mfc0_mvpconf0, t0);
2857 rn = "MVPConf0";
2858 break;
2859 case 3:
2860 check_insn(env, ctx, ASE_MT);
2861 tcg_gen_helper_1_0(do_mfc0_mvpconf1, t0);
2862 rn = "MVPConf1";
2863 break;
2864 default:
2865 goto die;
2867 break;
2868 case 1:
2869 switch (sel) {
2870 case 0:
2871 tcg_gen_helper_1_0(do_mfc0_random, t0);
2872 rn = "Random";
2873 break;
2874 case 1:
2875 check_insn(env, ctx, ASE_MT);
2876 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
2877 rn = "VPEControl";
2878 break;
2879 case 2:
2880 check_insn(env, ctx, ASE_MT);
2881 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
2882 rn = "VPEConf0";
2883 break;
2884 case 3:
2885 check_insn(env, ctx, ASE_MT);
2886 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
2887 rn = "VPEConf1";
2888 break;
2889 case 4:
2890 check_insn(env, ctx, ASE_MT);
2891 gen_mfc0_load64(t0, offsetof(CPUState, CP0_YQMask));
2892 rn = "YQMask";
2893 break;
2894 case 5:
2895 check_insn(env, ctx, ASE_MT);
2896 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPESchedule));
2897 rn = "VPESchedule";
2898 break;
2899 case 6:
2900 check_insn(env, ctx, ASE_MT);
2901 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPEScheFBack));
2902 rn = "VPEScheFBack";
2903 break;
2904 case 7:
2905 check_insn(env, ctx, ASE_MT);
2906 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
2907 rn = "VPEOpt";
2908 break;
2909 default:
2910 goto die;
2912 break;
2913 case 2:
2914 switch (sel) {
2915 case 0:
2916 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2917 tcg_gen_ext32s_tl(t0, t0);
2918 rn = "EntryLo0";
2919 break;
2920 case 1:
2921 check_insn(env, ctx, ASE_MT);
2922 tcg_gen_helper_1_0(do_mfc0_tcstatus, t0);
2923 rn = "TCStatus";
2924 break;
2925 case 2:
2926 check_insn(env, ctx, ASE_MT);
2927 tcg_gen_helper_1_0(do_mfc0_tcbind, t0);
2928 rn = "TCBind";
2929 break;
2930 case 3:
2931 check_insn(env, ctx, ASE_MT);
2932 tcg_gen_helper_1_0(do_mfc0_tcrestart, t0);
2933 rn = "TCRestart";
2934 break;
2935 case 4:
2936 check_insn(env, ctx, ASE_MT);
2937 tcg_gen_helper_1_0(do_mfc0_tchalt, t0);
2938 rn = "TCHalt";
2939 break;
2940 case 5:
2941 check_insn(env, ctx, ASE_MT);
2942 tcg_gen_helper_1_0(do_mfc0_tccontext, t0);
2943 rn = "TCContext";
2944 break;
2945 case 6:
2946 check_insn(env, ctx, ASE_MT);
2947 tcg_gen_helper_1_0(do_mfc0_tcschedule, t0);
2948 rn = "TCSchedule";
2949 break;
2950 case 7:
2951 check_insn(env, ctx, ASE_MT);
2952 tcg_gen_helper_1_0(do_mfc0_tcschefback, t0);
2953 rn = "TCScheFBack";
2954 break;
2955 default:
2956 goto die;
2958 break;
2959 case 3:
2960 switch (sel) {
2961 case 0:
2962 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2963 tcg_gen_ext32s_tl(t0, t0);
2964 rn = "EntryLo1";
2965 break;
2966 default:
2967 goto die;
2969 break;
2970 case 4:
2971 switch (sel) {
2972 case 0:
2973 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
2974 tcg_gen_ext32s_tl(t0, t0);
2975 rn = "Context";
2976 break;
2977 case 1:
2978 // tcg_gen_helper_1_0(do_mfc0_contextconfig, t0); /* SmartMIPS ASE */
2979 rn = "ContextConfig";
2980 // break;
2981 default:
2982 goto die;
2984 break;
2985 case 5:
2986 switch (sel) {
2987 case 0:
2988 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
2989 rn = "PageMask";
2990 break;
2991 case 1:
2992 check_insn(env, ctx, ISA_MIPS32R2);
2993 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
2994 rn = "PageGrain";
2995 break;
2996 default:
2997 goto die;
2999 break;
3000 case 6:
3001 switch (sel) {
3002 case 0:
3003 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
3004 rn = "Wired";
3005 break;
3006 case 1:
3007 check_insn(env, ctx, ISA_MIPS32R2);
3008 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
3009 rn = "SRSConf0";
3010 break;
3011 case 2:
3012 check_insn(env, ctx, ISA_MIPS32R2);
3013 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
3014 rn = "SRSConf1";
3015 break;
3016 case 3:
3017 check_insn(env, ctx, ISA_MIPS32R2);
3018 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
3019 rn = "SRSConf2";
3020 break;
3021 case 4:
3022 check_insn(env, ctx, ISA_MIPS32R2);
3023 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
3024 rn = "SRSConf3";
3025 break;
3026 case 5:
3027 check_insn(env, ctx, ISA_MIPS32R2);
3028 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
3029 rn = "SRSConf4";
3030 break;
3031 default:
3032 goto die;
3034 break;
3035 case 7:
3036 switch (sel) {
3037 case 0:
3038 check_insn(env, ctx, ISA_MIPS32R2);
3039 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
3040 rn = "HWREna";
3041 break;
3042 default:
3043 goto die;
3045 break;
3046 case 8:
3047 switch (sel) {
3048 case 0:
3049 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3050 tcg_gen_ext32s_tl(t0, t0);
3051 rn = "BadVAddr";
3052 break;
3053 default:
3054 goto die;
3056 break;
3057 case 9:
3058 switch (sel) {
3059 case 0:
3060 /* Mark as an IO operation because we read the time. */
3061 if (use_icount)
3062 gen_io_start();
3063 tcg_gen_helper_1_0(do_mfc0_count, t0);
3064 if (use_icount) {
3065 gen_io_end();
3066 ctx->bstate = BS_STOP;
3068 rn = "Count";
3069 break;
3070 /* 6,7 are implementation dependent */
3071 default:
3072 goto die;
3074 break;
3075 case 10:
3076 switch (sel) {
3077 case 0:
3078 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
3079 tcg_gen_ext32s_tl(t0, t0);
3080 rn = "EntryHi";
3081 break;
3082 default:
3083 goto die;
3085 break;
3086 case 11:
3087 switch (sel) {
3088 case 0:
3089 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
3090 rn = "Compare";
3091 break;
3092 /* 6,7 are implementation dependent */
3093 default:
3094 goto die;
3096 break;
3097 case 12:
3098 switch (sel) {
3099 case 0:
3100 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
3101 rn = "Status";
3102 break;
3103 case 1:
3104 check_insn(env, ctx, ISA_MIPS32R2);
3105 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
3106 rn = "IntCtl";
3107 break;
3108 case 2:
3109 check_insn(env, ctx, ISA_MIPS32R2);
3110 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
3111 rn = "SRSCtl";
3112 break;
3113 case 3:
3114 check_insn(env, ctx, ISA_MIPS32R2);
3115 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
3116 rn = "SRSMap";
3117 break;
3118 default:
3119 goto die;
3121 break;
3122 case 13:
3123 switch (sel) {
3124 case 0:
3125 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
3126 rn = "Cause";
3127 break;
3128 default:
3129 goto die;
3131 break;
3132 case 14:
3133 switch (sel) {
3134 case 0:
3135 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
3136 tcg_gen_ext32s_tl(t0, t0);
3137 rn = "EPC";
3138 break;
3139 default:
3140 goto die;
3142 break;
3143 case 15:
3144 switch (sel) {
3145 case 0:
3146 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
3147 rn = "PRid";
3148 break;
3149 case 1:
3150 check_insn(env, ctx, ISA_MIPS32R2);
3151 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
3152 rn = "EBase";
3153 break;
3154 default:
3155 goto die;
3157 break;
3158 case 16:
3159 switch (sel) {
3160 case 0:
3161 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
3162 rn = "Config";
3163 break;
3164 case 1:
3165 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
3166 rn = "Config1";
3167 break;
3168 case 2:
3169 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
3170 rn = "Config2";
3171 break;
3172 case 3:
3173 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
3174 rn = "Config3";
3175 break;
3176 /* 4,5 are reserved */
3177 /* 6,7 are implementation dependent */
3178 case 6:
3179 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
3180 rn = "Config6";
3181 break;
3182 case 7:
3183 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
3184 rn = "Config7";
3185 break;
3186 default:
3187 goto die;
3189 break;
3190 case 17:
3191 switch (sel) {
3192 case 0:
3193 tcg_gen_helper_1_0(do_mfc0_lladdr, t0);
3194 rn = "LLAddr";
3195 break;
3196 default:
3197 goto die;
3199 break;
3200 case 18:
3201 switch (sel) {
3202 case 0 ... 7:
3203 tcg_gen_helper_1_i(do_mfc0_watchlo, t0, sel);
3204 rn = "WatchLo";
3205 break;
3206 default:
3207 goto die;
3209 break;
3210 case 19:
3211 switch (sel) {
3212 case 0 ...7:
3213 tcg_gen_helper_1_i(do_mfc0_watchhi, t0, sel);
3214 rn = "WatchHi";
3215 break;
3216 default:
3217 goto die;
3219 break;
3220 case 20:
3221 switch (sel) {
3222 case 0:
3223 #if defined(TARGET_MIPS64)
3224 check_insn(env, ctx, ISA_MIPS3);
3225 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
3226 tcg_gen_ext32s_tl(t0, t0);
3227 rn = "XContext";
3228 break;
3229 #endif
3230 default:
3231 goto die;
3233 break;
3234 case 21:
3235 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3236 switch (sel) {
3237 case 0:
3238 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
3239 rn = "Framemask";
3240 break;
3241 default:
3242 goto die;
3244 break;
3245 case 22:
3246 /* ignored */
3247 rn = "'Diagnostic"; /* implementation dependent */
3248 break;
3249 case 23:
3250 switch (sel) {
3251 case 0:
3252 tcg_gen_helper_1_0(do_mfc0_debug, t0); /* EJTAG support */
3253 rn = "Debug";
3254 break;
3255 case 1:
3256 // tcg_gen_helper_1_0(do_mfc0_tracecontrol, t0); /* PDtrace support */
3257 rn = "TraceControl";
3258 // break;
3259 case 2:
3260 // tcg_gen_helper_1_0(do_mfc0_tracecontrol2, t0); /* PDtrace support */
3261 rn = "TraceControl2";
3262 // break;
3263 case 3:
3264 // tcg_gen_helper_1_0(do_mfc0_usertracedata, t0); /* PDtrace support */
3265 rn = "UserTraceData";
3266 // break;
3267 case 4:
3268 // tcg_gen_helper_1_0(do_mfc0_tracebpc, t0); /* PDtrace support */
3269 rn = "TraceBPC";
3270 // break;
3271 default:
3272 goto die;
3274 break;
3275 case 24:
3276 switch (sel) {
3277 case 0:
3278 /* EJTAG support */
3279 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
3280 tcg_gen_ext32s_tl(t0, t0);
3281 rn = "DEPC";
3282 break;
3283 default:
3284 goto die;
3286 break;
3287 case 25:
3288 switch (sel) {
3289 case 0:
3290 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
3291 rn = "Performance0";
3292 break;
3293 case 1:
3294 // tcg_gen_helper_1_0(do_mfc0_performance1, t0);
3295 rn = "Performance1";
3296 // break;
3297 case 2:
3298 // tcg_gen_helper_1_0(do_mfc0_performance2, t0);
3299 rn = "Performance2";
3300 // break;
3301 case 3:
3302 // tcg_gen_helper_1_0(do_mfc0_performance3, t0);
3303 rn = "Performance3";
3304 // break;
3305 case 4:
3306 // tcg_gen_helper_1_0(do_mfc0_performance4, t0);
3307 rn = "Performance4";
3308 // break;
3309 case 5:
3310 // tcg_gen_helper_1_0(do_mfc0_performance5, t0);
3311 rn = "Performance5";
3312 // break;
3313 case 6:
3314 // tcg_gen_helper_1_0(do_mfc0_performance6, t0);
3315 rn = "Performance6";
3316 // break;
3317 case 7:
3318 // tcg_gen_helper_1_0(do_mfc0_performance7, t0);
3319 rn = "Performance7";
3320 // break;
3321 default:
3322 goto die;
3324 break;
3325 case 26:
3326 rn = "ECC";
3327 break;
3328 case 27:
3329 switch (sel) {
3330 /* ignored */
3331 case 0 ... 3:
3332 rn = "CacheErr";
3333 break;
3334 default:
3335 goto die;
3337 break;
3338 case 28:
3339 switch (sel) {
3340 case 0:
3341 case 2:
3342 case 4:
3343 case 6:
3344 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
3345 rn = "TagLo";
3346 break;
3347 case 1:
3348 case 3:
3349 case 5:
3350 case 7:
3351 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
3352 rn = "DataLo";
3353 break;
3354 default:
3355 goto die;
3357 break;
3358 case 29:
3359 switch (sel) {
3360 case 0:
3361 case 2:
3362 case 4:
3363 case 6:
3364 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
3365 rn = "TagHi";
3366 break;
3367 case 1:
3368 case 3:
3369 case 5:
3370 case 7:
3371 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
3372 rn = "DataHi";
3373 break;
3374 default:
3375 goto die;
3377 break;
3378 case 30:
3379 switch (sel) {
3380 case 0:
3381 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3382 tcg_gen_ext32s_tl(t0, t0);
3383 rn = "ErrorEPC";
3384 break;
3385 default:
3386 goto die;
3388 break;
3389 case 31:
3390 switch (sel) {
3391 case 0:
3392 /* EJTAG support */
3393 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
3394 rn = "DESAVE";
3395 break;
3396 default:
3397 goto die;
3399 break;
3400 default:
3401 goto die;
3403 #if defined MIPS_DEBUG_DISAS
3404 if (loglevel & CPU_LOG_TB_IN_ASM) {
3405 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3406 rn, reg, sel);
3408 #endif
3409 return;
3411 die:
3412 #if defined MIPS_DEBUG_DISAS
3413 if (loglevel & CPU_LOG_TB_IN_ASM) {
3414 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3415 rn, reg, sel);
3417 #endif
3418 generate_exception(ctx, EXCP_RI);
3421 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
3423 const char *rn = "invalid";
3425 if (sel != 0)
3426 check_insn(env, ctx, ISA_MIPS32);
3428 if (use_icount)
3429 gen_io_start();
3431 switch (reg) {
3432 case 0:
3433 switch (sel) {
3434 case 0:
3435 tcg_gen_helper_0_1(do_mtc0_index, t0);
3436 rn = "Index";
3437 break;
3438 case 1:
3439 check_insn(env, ctx, ASE_MT);
3440 tcg_gen_helper_0_1(do_mtc0_mvpcontrol, t0);
3441 rn = "MVPControl";
3442 break;
3443 case 2:
3444 check_insn(env, ctx, ASE_MT);
3445 /* ignored */
3446 rn = "MVPConf0";
3447 break;
3448 case 3:
3449 check_insn(env, ctx, ASE_MT);
3450 /* ignored */
3451 rn = "MVPConf1";
3452 break;
3453 default:
3454 goto die;
3456 break;
3457 case 1:
3458 switch (sel) {
3459 case 0:
3460 /* ignored */
3461 rn = "Random";
3462 break;
3463 case 1:
3464 check_insn(env, ctx, ASE_MT);
3465 tcg_gen_helper_0_1(do_mtc0_vpecontrol, t0);
3466 rn = "VPEControl";
3467 break;
3468 case 2:
3469 check_insn(env, ctx, ASE_MT);
3470 tcg_gen_helper_0_1(do_mtc0_vpeconf0, t0);
3471 rn = "VPEConf0";
3472 break;
3473 case 3:
3474 check_insn(env, ctx, ASE_MT);
3475 tcg_gen_helper_0_1(do_mtc0_vpeconf1, t0);
3476 rn = "VPEConf1";
3477 break;
3478 case 4:
3479 check_insn(env, ctx, ASE_MT);
3480 tcg_gen_helper_0_1(do_mtc0_yqmask, t0);
3481 rn = "YQMask";
3482 break;
3483 case 5:
3484 check_insn(env, ctx, ASE_MT);
3485 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule));
3486 rn = "VPESchedule";
3487 break;
3488 case 6:
3489 check_insn(env, ctx, ASE_MT);
3490 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack));
3491 rn = "VPEScheFBack";
3492 break;
3493 case 7:
3494 check_insn(env, ctx, ASE_MT);
3495 tcg_gen_helper_0_1(do_mtc0_vpeopt, t0);
3496 rn = "VPEOpt";
3497 break;
3498 default:
3499 goto die;
3501 break;
3502 case 2:
3503 switch (sel) {
3504 case 0:
3505 tcg_gen_helper_0_1(do_mtc0_entrylo0, t0);
3506 rn = "EntryLo0";
3507 break;
3508 case 1:
3509 check_insn(env, ctx, ASE_MT);
3510 tcg_gen_helper_0_1(do_mtc0_tcstatus, t0);
3511 rn = "TCStatus";
3512 break;
3513 case 2:
3514 check_insn(env, ctx, ASE_MT);
3515 tcg_gen_helper_0_1(do_mtc0_tcbind, t0);
3516 rn = "TCBind";
3517 break;
3518 case 3:
3519 check_insn(env, ctx, ASE_MT);
3520 tcg_gen_helper_0_1(do_mtc0_tcrestart, t0);
3521 rn = "TCRestart";
3522 break;
3523 case 4:
3524 check_insn(env, ctx, ASE_MT);
3525 tcg_gen_helper_0_1(do_mtc0_tchalt, t0);
3526 rn = "TCHalt";
3527 break;
3528 case 5:
3529 check_insn(env, ctx, ASE_MT);
3530 tcg_gen_helper_0_1(do_mtc0_tccontext, t0);
3531 rn = "TCContext";
3532 break;
3533 case 6:
3534 check_insn(env, ctx, ASE_MT);
3535 tcg_gen_helper_0_1(do_mtc0_tcschedule, t0);
3536 rn = "TCSchedule";
3537 break;
3538 case 7:
3539 check_insn(env, ctx, ASE_MT);
3540 tcg_gen_helper_0_1(do_mtc0_tcschefback, t0);
3541 rn = "TCScheFBack";
3542 break;
3543 default:
3544 goto die;
3546 break;
3547 case 3:
3548 switch (sel) {
3549 case 0:
3550 tcg_gen_helper_0_1(do_mtc0_entrylo1, t0);
3551 rn = "EntryLo1";
3552 break;
3553 default:
3554 goto die;
3556 break;
3557 case 4:
3558 switch (sel) {
3559 case 0:
3560 tcg_gen_helper_0_1(do_mtc0_context, t0);
3561 rn = "Context";
3562 break;
3563 case 1:
3564 // tcg_gen_helper_0_1(do_mtc0_contextconfig, t0); /* SmartMIPS ASE */
3565 rn = "ContextConfig";
3566 // break;
3567 default:
3568 goto die;
3570 break;
3571 case 5:
3572 switch (sel) {
3573 case 0:
3574 tcg_gen_helper_0_1(do_mtc0_pagemask, t0);
3575 rn = "PageMask";
3576 break;
3577 case 1:
3578 check_insn(env, ctx, ISA_MIPS32R2);
3579 tcg_gen_helper_0_1(do_mtc0_pagegrain, t0);
3580 rn = "PageGrain";
3581 break;
3582 default:
3583 goto die;
3585 break;
3586 case 6:
3587 switch (sel) {
3588 case 0:
3589 tcg_gen_helper_0_1(do_mtc0_wired, t0);
3590 rn = "Wired";
3591 break;
3592 case 1:
3593 check_insn(env, ctx, ISA_MIPS32R2);
3594 tcg_gen_helper_0_1(do_mtc0_srsconf0, t0);
3595 rn = "SRSConf0";
3596 break;
3597 case 2:
3598 check_insn(env, ctx, ISA_MIPS32R2);
3599 tcg_gen_helper_0_1(do_mtc0_srsconf1, t0);
3600 rn = "SRSConf1";
3601 break;
3602 case 3:
3603 check_insn(env, ctx, ISA_MIPS32R2);
3604 tcg_gen_helper_0_1(do_mtc0_srsconf2, t0);
3605 rn = "SRSConf2";
3606 break;
3607 case 4:
3608 check_insn(env, ctx, ISA_MIPS32R2);
3609 tcg_gen_helper_0_1(do_mtc0_srsconf3, t0);
3610 rn = "SRSConf3";
3611 break;
3612 case 5:
3613 check_insn(env, ctx, ISA_MIPS32R2);
3614 tcg_gen_helper_0_1(do_mtc0_srsconf4, t0);
3615 rn = "SRSConf4";
3616 break;
3617 default:
3618 goto die;
3620 break;
3621 case 7:
3622 switch (sel) {
3623 case 0:
3624 check_insn(env, ctx, ISA_MIPS32R2);
3625 tcg_gen_helper_0_1(do_mtc0_hwrena, t0);
3626 rn = "HWREna";
3627 break;
3628 default:
3629 goto die;
3631 break;
3632 case 8:
3633 /* ignored */
3634 rn = "BadVAddr";
3635 break;
3636 case 9:
3637 switch (sel) {
3638 case 0:
3639 tcg_gen_helper_0_1(do_mtc0_count, t0);
3640 rn = "Count";
3641 break;
3642 /* 6,7 are implementation dependent */
3643 default:
3644 goto die;
3646 /* Stop translation as we may have switched the execution mode */
3647 ctx->bstate = BS_STOP;
3648 break;
3649 case 10:
3650 switch (sel) {
3651 case 0:
3652 tcg_gen_helper_0_1(do_mtc0_entryhi, t0);
3653 rn = "EntryHi";
3654 break;
3655 default:
3656 goto die;
3658 break;
3659 case 11:
3660 switch (sel) {
3661 case 0:
3662 tcg_gen_helper_0_1(do_mtc0_compare, t0);
3663 rn = "Compare";
3664 break;
3665 /* 6,7 are implementation dependent */
3666 default:
3667 goto die;
3669 /* Stop translation as we may have switched the execution mode */
3670 ctx->bstate = BS_STOP;
3671 break;
3672 case 12:
3673 switch (sel) {
3674 case 0:
3675 tcg_gen_helper_0_1(do_mtc0_status, t0);
3676 /* BS_STOP isn't good enough here, hflags may have changed. */
3677 gen_save_pc(ctx->pc + 4);
3678 ctx->bstate = BS_EXCP;
3679 rn = "Status";
3680 break;
3681 case 1:
3682 check_insn(env, ctx, ISA_MIPS32R2);
3683 tcg_gen_helper_0_1(do_mtc0_intctl, t0);
3684 /* Stop translation as we may have switched the execution mode */
3685 ctx->bstate = BS_STOP;
3686 rn = "IntCtl";
3687 break;
3688 case 2:
3689 check_insn(env, ctx, ISA_MIPS32R2);
3690 tcg_gen_helper_0_1(do_mtc0_srsctl, t0);
3691 /* Stop translation as we may have switched the execution mode */
3692 ctx->bstate = BS_STOP;
3693 rn = "SRSCtl";
3694 break;
3695 case 3:
3696 check_insn(env, ctx, ISA_MIPS32R2);
3697 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
3698 /* Stop translation as we may have switched the execution mode */
3699 ctx->bstate = BS_STOP;
3700 rn = "SRSMap";
3701 break;
3702 default:
3703 goto die;
3705 break;
3706 case 13:
3707 switch (sel) {
3708 case 0:
3709 tcg_gen_helper_0_1(do_mtc0_cause, t0);
3710 rn = "Cause";
3711 break;
3712 default:
3713 goto die;
3715 /* Stop translation as we may have switched the execution mode */
3716 ctx->bstate = BS_STOP;
3717 break;
3718 case 14:
3719 switch (sel) {
3720 case 0:
3721 gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC));
3722 rn = "EPC";
3723 break;
3724 default:
3725 goto die;
3727 break;
3728 case 15:
3729 switch (sel) {
3730 case 0:
3731 /* ignored */
3732 rn = "PRid";
3733 break;
3734 case 1:
3735 check_insn(env, ctx, ISA_MIPS32R2);
3736 tcg_gen_helper_0_1(do_mtc0_ebase, t0);
3737 rn = "EBase";
3738 break;
3739 default:
3740 goto die;
3742 break;
3743 case 16:
3744 switch (sel) {
3745 case 0:
3746 tcg_gen_helper_0_1(do_mtc0_config0, t0);
3747 rn = "Config";
3748 /* Stop translation as we may have switched the execution mode */
3749 ctx->bstate = BS_STOP;
3750 break;
3751 case 1:
3752 /* ignored, read only */
3753 rn = "Config1";
3754 break;
3755 case 2:
3756 tcg_gen_helper_0_1(do_mtc0_config2, t0);
3757 rn = "Config2";
3758 /* Stop translation as we may have switched the execution mode */
3759 ctx->bstate = BS_STOP;
3760 break;
3761 case 3:
3762 /* ignored, read only */
3763 rn = "Config3";
3764 break;
3765 /* 4,5 are reserved */
3766 /* 6,7 are implementation dependent */
3767 case 6:
3768 /* ignored */
3769 rn = "Config6";
3770 break;
3771 case 7:
3772 /* ignored */
3773 rn = "Config7";
3774 break;
3775 default:
3776 rn = "Invalid config selector";
3777 goto die;
3779 break;
3780 case 17:
3781 switch (sel) {
3782 case 0:
3783 /* ignored */
3784 rn = "LLAddr";
3785 break;
3786 default:
3787 goto die;
3789 break;
3790 case 18:
3791 switch (sel) {
3792 case 0 ... 7:
3793 tcg_gen_helper_0_1i(do_mtc0_watchlo, t0, sel);
3794 rn = "WatchLo";
3795 break;
3796 default:
3797 goto die;
3799 break;
3800 case 19:
3801 switch (sel) {
3802 case 0 ... 7:
3803 tcg_gen_helper_0_1i(do_mtc0_watchhi, t0, sel);
3804 rn = "WatchHi";
3805 break;
3806 default:
3807 goto die;
3809 break;
3810 case 20:
3811 switch (sel) {
3812 case 0:
3813 #if defined(TARGET_MIPS64)
3814 check_insn(env, ctx, ISA_MIPS3);
3815 tcg_gen_helper_0_1(do_mtc0_xcontext, t0);
3816 rn = "XContext";
3817 break;
3818 #endif
3819 default:
3820 goto die;
3822 break;
3823 case 21:
3824 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3825 switch (sel) {
3826 case 0:
3827 tcg_gen_helper_0_1(do_mtc0_framemask, t0);
3828 rn = "Framemask";
3829 break;
3830 default:
3831 goto die;
3833 break;
3834 case 22:
3835 /* ignored */
3836 rn = "Diagnostic"; /* implementation dependent */
3837 break;
3838 case 23:
3839 switch (sel) {
3840 case 0:
3841 tcg_gen_helper_0_1(do_mtc0_debug, t0); /* EJTAG support */
3842 /* BS_STOP isn't good enough here, hflags may have changed. */
3843 gen_save_pc(ctx->pc + 4);
3844 ctx->bstate = BS_EXCP;
3845 rn = "Debug";
3846 break;
3847 case 1:
3848 // tcg_gen_helper_0_1(do_mtc0_tracecontrol, t0); /* PDtrace support */
3849 rn = "TraceControl";
3850 /* Stop translation as we may have switched the execution mode */
3851 ctx->bstate = BS_STOP;
3852 // break;
3853 case 2:
3854 // tcg_gen_helper_0_1(do_mtc0_tracecontrol2, t0); /* PDtrace support */
3855 rn = "TraceControl2";
3856 /* Stop translation as we may have switched the execution mode */
3857 ctx->bstate = BS_STOP;
3858 // break;
3859 case 3:
3860 /* Stop translation as we may have switched the execution mode */
3861 ctx->bstate = BS_STOP;
3862 // tcg_gen_helper_0_1(do_mtc0_usertracedata, t0); /* PDtrace support */
3863 rn = "UserTraceData";
3864 /* Stop translation as we may have switched the execution mode */
3865 ctx->bstate = BS_STOP;
3866 // break;
3867 case 4:
3868 // tcg_gen_helper_0_1(do_mtc0_tracebpc, t0); /* PDtrace support */
3869 /* Stop translation as we may have switched the execution mode */
3870 ctx->bstate = BS_STOP;
3871 rn = "TraceBPC";
3872 // break;
3873 default:
3874 goto die;
3876 break;
3877 case 24:
3878 switch (sel) {
3879 case 0:
3880 /* EJTAG support */
3881 gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC));
3882 rn = "DEPC";
3883 break;
3884 default:
3885 goto die;
3887 break;
3888 case 25:
3889 switch (sel) {
3890 case 0:
3891 tcg_gen_helper_0_1(do_mtc0_performance0, t0);
3892 rn = "Performance0";
3893 break;
3894 case 1:
3895 // tcg_gen_helper_0_1(do_mtc0_performance1, t0);
3896 rn = "Performance1";
3897 // break;
3898 case 2:
3899 // tcg_gen_helper_0_1(do_mtc0_performance2, t0);
3900 rn = "Performance2";
3901 // break;
3902 case 3:
3903 // tcg_gen_helper_0_1(do_mtc0_performance3, t0);
3904 rn = "Performance3";
3905 // break;
3906 case 4:
3907 // tcg_gen_helper_0_1(do_mtc0_performance4, t0);
3908 rn = "Performance4";
3909 // break;
3910 case 5:
3911 // tcg_gen_helper_0_1(do_mtc0_performance5, t0);
3912 rn = "Performance5";
3913 // break;
3914 case 6:
3915 // tcg_gen_helper_0_1(do_mtc0_performance6, t0);
3916 rn = "Performance6";
3917 // break;
3918 case 7:
3919 // tcg_gen_helper_0_1(do_mtc0_performance7, t0);
3920 rn = "Performance7";
3921 // break;
3922 default:
3923 goto die;
3925 break;
3926 case 26:
3927 /* ignored */
3928 rn = "ECC";
3929 break;
3930 case 27:
3931 switch (sel) {
3932 case 0 ... 3:
3933 /* ignored */
3934 rn = "CacheErr";
3935 break;
3936 default:
3937 goto die;
3939 break;
3940 case 28:
3941 switch (sel) {
3942 case 0:
3943 case 2:
3944 case 4:
3945 case 6:
3946 tcg_gen_helper_0_1(do_mtc0_taglo, t0);
3947 rn = "TagLo";
3948 break;
3949 case 1:
3950 case 3:
3951 case 5:
3952 case 7:
3953 tcg_gen_helper_0_1(do_mtc0_datalo, t0);
3954 rn = "DataLo";
3955 break;
3956 default:
3957 goto die;
3959 break;
3960 case 29:
3961 switch (sel) {
3962 case 0:
3963 case 2:
3964 case 4:
3965 case 6:
3966 tcg_gen_helper_0_1(do_mtc0_taghi, t0);
3967 rn = "TagHi";
3968 break;
3969 case 1:
3970 case 3:
3971 case 5:
3972 case 7:
3973 tcg_gen_helper_0_1(do_mtc0_datahi, t0);
3974 rn = "DataHi";
3975 break;
3976 default:
3977 rn = "invalid sel";
3978 goto die;
3980 break;
3981 case 30:
3982 switch (sel) {
3983 case 0:
3984 gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC));
3985 rn = "ErrorEPC";
3986 break;
3987 default:
3988 goto die;
3990 break;
3991 case 31:
3992 switch (sel) {
3993 case 0:
3994 /* EJTAG support */
3995 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
3996 rn = "DESAVE";
3997 break;
3998 default:
3999 goto die;
4001 /* Stop translation as we may have switched the execution mode */
4002 ctx->bstate = BS_STOP;
4003 break;
4004 default:
4005 goto die;
4007 #if defined MIPS_DEBUG_DISAS
4008 if (loglevel & CPU_LOG_TB_IN_ASM) {
4009 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
4010 rn, reg, sel);
4012 #endif
4013 /* For simplicity assume that all writes can cause interrupts. */
4014 if (use_icount) {
4015 gen_io_end();
4016 ctx->bstate = BS_STOP;
4018 return;
4020 die:
4021 #if defined MIPS_DEBUG_DISAS
4022 if (loglevel & CPU_LOG_TB_IN_ASM) {
4023 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
4024 rn, reg, sel);
4026 #endif
4027 generate_exception(ctx, EXCP_RI);
4030 #if defined(TARGET_MIPS64)
4031 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
4033 const char *rn = "invalid";
4035 if (sel != 0)
4036 check_insn(env, ctx, ISA_MIPS64);
4038 switch (reg) {
4039 case 0:
4040 switch (sel) {
4041 case 0:
4042 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
4043 rn = "Index";
4044 break;
4045 case 1:
4046 check_insn(env, ctx, ASE_MT);
4047 tcg_gen_helper_1_0(do_mfc0_mvpcontrol, t0);
4048 rn = "MVPControl";
4049 break;
4050 case 2:
4051 check_insn(env, ctx, ASE_MT);
4052 tcg_gen_helper_1_0(do_mfc0_mvpconf0, t0);
4053 rn = "MVPConf0";
4054 break;
4055 case 3:
4056 check_insn(env, ctx, ASE_MT);
4057 tcg_gen_helper_1_0(do_mfc0_mvpconf1, t0);
4058 rn = "MVPConf1";
4059 break;
4060 default:
4061 goto die;
4063 break;
4064 case 1:
4065 switch (sel) {
4066 case 0:
4067 tcg_gen_helper_1_0(do_mfc0_random, t0);
4068 rn = "Random";
4069 break;
4070 case 1:
4071 check_insn(env, ctx, ASE_MT);
4072 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
4073 rn = "VPEControl";
4074 break;
4075 case 2:
4076 check_insn(env, ctx, ASE_MT);
4077 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
4078 rn = "VPEConf0";
4079 break;
4080 case 3:
4081 check_insn(env, ctx, ASE_MT);
4082 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
4083 rn = "VPEConf1";
4084 break;
4085 case 4:
4086 check_insn(env, ctx, ASE_MT);
4087 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask));
4088 rn = "YQMask";
4089 break;
4090 case 5:
4091 check_insn(env, ctx, ASE_MT);
4092 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4093 rn = "VPESchedule";
4094 break;
4095 case 6:
4096 check_insn(env, ctx, ASE_MT);
4097 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4098 rn = "VPEScheFBack";
4099 break;
4100 case 7:
4101 check_insn(env, ctx, ASE_MT);
4102 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
4103 rn = "VPEOpt";
4104 break;
4105 default:
4106 goto die;
4108 break;
4109 case 2:
4110 switch (sel) {
4111 case 0:
4112 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4113 rn = "EntryLo0";
4114 break;
4115 case 1:
4116 check_insn(env, ctx, ASE_MT);
4117 tcg_gen_helper_1_0(do_mfc0_tcstatus, t0);
4118 rn = "TCStatus";
4119 break;
4120 case 2:
4121 check_insn(env, ctx, ASE_MT);
4122 tcg_gen_helper_1_0(do_mfc0_tcbind, t0);
4123 rn = "TCBind";
4124 break;
4125 case 3:
4126 check_insn(env, ctx, ASE_MT);
4127 tcg_gen_helper_1_0(do_dmfc0_tcrestart, t0);
4128 rn = "TCRestart";
4129 break;
4130 case 4:
4131 check_insn(env, ctx, ASE_MT);
4132 tcg_gen_helper_1_0(do_dmfc0_tchalt, t0);
4133 rn = "TCHalt";
4134 break;
4135 case 5:
4136 check_insn(env, ctx, ASE_MT);
4137 tcg_gen_helper_1_0(do_dmfc0_tccontext, t0);
4138 rn = "TCContext";
4139 break;
4140 case 6:
4141 check_insn(env, ctx, ASE_MT);
4142 tcg_gen_helper_1_0(do_dmfc0_tcschedule, t0);
4143 rn = "TCSchedule";
4144 break;
4145 case 7:
4146 check_insn(env, ctx, ASE_MT);
4147 tcg_gen_helper_1_0(do_dmfc0_tcschefback, t0);
4148 rn = "TCScheFBack";
4149 break;
4150 default:
4151 goto die;
4153 break;
4154 case 3:
4155 switch (sel) {
4156 case 0:
4157 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4158 rn = "EntryLo1";
4159 break;
4160 default:
4161 goto die;
4163 break;
4164 case 4:
4165 switch (sel) {
4166 case 0:
4167 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
4168 rn = "Context";
4169 break;
4170 case 1:
4171 // tcg_gen_helper_1_0(do_dmfc0_contextconfig, t0); /* SmartMIPS ASE */
4172 rn = "ContextConfig";
4173 // break;
4174 default:
4175 goto die;
4177 break;
4178 case 5:
4179 switch (sel) {
4180 case 0:
4181 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
4182 rn = "PageMask";
4183 break;
4184 case 1:
4185 check_insn(env, ctx, ISA_MIPS32R2);
4186 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
4187 rn = "PageGrain";
4188 break;
4189 default:
4190 goto die;
4192 break;
4193 case 6:
4194 switch (sel) {
4195 case 0:
4196 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
4197 rn = "Wired";
4198 break;
4199 case 1:
4200 check_insn(env, ctx, ISA_MIPS32R2);
4201 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
4202 rn = "SRSConf0";
4203 break;
4204 case 2:
4205 check_insn(env, ctx, ISA_MIPS32R2);
4206 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
4207 rn = "SRSConf1";
4208 break;
4209 case 3:
4210 check_insn(env, ctx, ISA_MIPS32R2);
4211 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
4212 rn = "SRSConf2";
4213 break;
4214 case 4:
4215 check_insn(env, ctx, ISA_MIPS32R2);
4216 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
4217 rn = "SRSConf3";
4218 break;
4219 case 5:
4220 check_insn(env, ctx, ISA_MIPS32R2);
4221 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
4222 rn = "SRSConf4";
4223 break;
4224 default:
4225 goto die;
4227 break;
4228 case 7:
4229 switch (sel) {
4230 case 0:
4231 check_insn(env, ctx, ISA_MIPS32R2);
4232 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
4233 rn = "HWREna";
4234 break;
4235 default:
4236 goto die;
4238 break;
4239 case 8:
4240 switch (sel) {
4241 case 0:
4242 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4243 rn = "BadVAddr";
4244 break;
4245 default:
4246 goto die;
4248 break;
4249 case 9:
4250 switch (sel) {
4251 case 0:
4252 /* Mark as an IO operation because we read the time. */
4253 if (use_icount)
4254 gen_io_start();
4255 tcg_gen_helper_1_0(do_mfc0_count, t0);
4256 if (use_icount) {
4257 gen_io_end();
4258 ctx->bstate = BS_STOP;
4260 rn = "Count";
4261 break;
4262 /* 6,7 are implementation dependent */
4263 default:
4264 goto die;
4266 break;
4267 case 10:
4268 switch (sel) {
4269 case 0:
4270 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
4271 rn = "EntryHi";
4272 break;
4273 default:
4274 goto die;
4276 break;
4277 case 11:
4278 switch (sel) {
4279 case 0:
4280 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
4281 rn = "Compare";
4282 break;
4283 /* 6,7 are implementation dependent */
4284 default:
4285 goto die;
4287 break;
4288 case 12:
4289 switch (sel) {
4290 case 0:
4291 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
4292 rn = "Status";
4293 break;
4294 case 1:
4295 check_insn(env, ctx, ISA_MIPS32R2);
4296 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
4297 rn = "IntCtl";
4298 break;
4299 case 2:
4300 check_insn(env, ctx, ISA_MIPS32R2);
4301 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
4302 rn = "SRSCtl";
4303 break;
4304 case 3:
4305 check_insn(env, ctx, ISA_MIPS32R2);
4306 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
4307 rn = "SRSMap";
4308 break;
4309 default:
4310 goto die;
4312 break;
4313 case 13:
4314 switch (sel) {
4315 case 0:
4316 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
4317 rn = "Cause";
4318 break;
4319 default:
4320 goto die;
4322 break;
4323 case 14:
4324 switch (sel) {
4325 case 0:
4326 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4327 rn = "EPC";
4328 break;
4329 default:
4330 goto die;
4332 break;
4333 case 15:
4334 switch (sel) {
4335 case 0:
4336 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
4337 rn = "PRid";
4338 break;
4339 case 1:
4340 check_insn(env, ctx, ISA_MIPS32R2);
4341 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
4342 rn = "EBase";
4343 break;
4344 default:
4345 goto die;
4347 break;
4348 case 16:
4349 switch (sel) {
4350 case 0:
4351 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
4352 rn = "Config";
4353 break;
4354 case 1:
4355 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
4356 rn = "Config1";
4357 break;
4358 case 2:
4359 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
4360 rn = "Config2";
4361 break;
4362 case 3:
4363 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
4364 rn = "Config3";
4365 break;
4366 /* 6,7 are implementation dependent */
4367 case 6:
4368 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
4369 rn = "Config6";
4370 break;
4371 case 7:
4372 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
4373 rn = "Config7";
4374 break;
4375 default:
4376 goto die;
4378 break;
4379 case 17:
4380 switch (sel) {
4381 case 0:
4382 tcg_gen_helper_1_0(do_dmfc0_lladdr, t0);
4383 rn = "LLAddr";
4384 break;
4385 default:
4386 goto die;
4388 break;
4389 case 18:
4390 switch (sel) {
4391 case 0 ... 7:
4392 tcg_gen_helper_1_i(do_dmfc0_watchlo, t0, sel);
4393 rn = "WatchLo";
4394 break;
4395 default:
4396 goto die;
4398 break;
4399 case 19:
4400 switch (sel) {
4401 case 0 ... 7:
4402 tcg_gen_helper_1_i(do_mfc0_watchhi, t0, sel);
4403 rn = "WatchHi";
4404 break;
4405 default:
4406 goto die;
4408 break;
4409 case 20:
4410 switch (sel) {
4411 case 0:
4412 check_insn(env, ctx, ISA_MIPS3);
4413 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
4414 rn = "XContext";
4415 break;
4416 default:
4417 goto die;
4419 break;
4420 case 21:
4421 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4422 switch (sel) {
4423 case 0:
4424 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
4425 rn = "Framemask";
4426 break;
4427 default:
4428 goto die;
4430 break;
4431 case 22:
4432 /* ignored */
4433 rn = "'Diagnostic"; /* implementation dependent */
4434 break;
4435 case 23:
4436 switch (sel) {
4437 case 0:
4438 tcg_gen_helper_1_0(do_mfc0_debug, t0); /* EJTAG support */
4439 rn = "Debug";
4440 break;
4441 case 1:
4442 // tcg_gen_helper_1_0(do_dmfc0_tracecontrol, t0); /* PDtrace support */
4443 rn = "TraceControl";
4444 // break;
4445 case 2:
4446 // tcg_gen_helper_1_0(do_dmfc0_tracecontrol2, t0); /* PDtrace support */
4447 rn = "TraceControl2";
4448 // break;
4449 case 3:
4450 // tcg_gen_helper_1_0(do_dmfc0_usertracedata, t0); /* PDtrace support */
4451 rn = "UserTraceData";
4452 // break;
4453 case 4:
4454 // tcg_gen_helper_1_0(do_dmfc0_tracebpc, t0); /* PDtrace support */
4455 rn = "TraceBPC";
4456 // break;
4457 default:
4458 goto die;
4460 break;
4461 case 24:
4462 switch (sel) {
4463 case 0:
4464 /* EJTAG support */
4465 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
4466 rn = "DEPC";
4467 break;
4468 default:
4469 goto die;
4471 break;
4472 case 25:
4473 switch (sel) {
4474 case 0:
4475 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
4476 rn = "Performance0";
4477 break;
4478 case 1:
4479 // tcg_gen_helper_1_0(do_dmfc0_performance1, t0);
4480 rn = "Performance1";
4481 // break;
4482 case 2:
4483 // tcg_gen_helper_1_0(do_dmfc0_performance2, t0);
4484 rn = "Performance2";
4485 // break;
4486 case 3:
4487 // tcg_gen_helper_1_0(do_dmfc0_performance3, t0);
4488 rn = "Performance3";
4489 // break;
4490 case 4:
4491 // tcg_gen_helper_1_0(do_dmfc0_performance4, t0);
4492 rn = "Performance4";
4493 // break;
4494 case 5:
4495 // tcg_gen_helper_1_0(do_dmfc0_performance5, t0);
4496 rn = "Performance5";
4497 // break;
4498 case 6:
4499 // tcg_gen_helper_1_0(do_dmfc0_performance6, t0);
4500 rn = "Performance6";
4501 // break;
4502 case 7:
4503 // tcg_gen_helper_1_0(do_dmfc0_performance7, t0);
4504 rn = "Performance7";
4505 // break;
4506 default:
4507 goto die;
4509 break;
4510 case 26:
4511 rn = "ECC";
4512 break;
4513 case 27:
4514 switch (sel) {
4515 /* ignored */
4516 case 0 ... 3:
4517 rn = "CacheErr";
4518 break;
4519 default:
4520 goto die;
4522 break;
4523 case 28:
4524 switch (sel) {
4525 case 0:
4526 case 2:
4527 case 4:
4528 case 6:
4529 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
4530 rn = "TagLo";
4531 break;
4532 case 1:
4533 case 3:
4534 case 5:
4535 case 7:
4536 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
4537 rn = "DataLo";
4538 break;
4539 default:
4540 goto die;
4542 break;
4543 case 29:
4544 switch (sel) {
4545 case 0:
4546 case 2:
4547 case 4:
4548 case 6:
4549 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
4550 rn = "TagHi";
4551 break;
4552 case 1:
4553 case 3:
4554 case 5:
4555 case 7:
4556 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
4557 rn = "DataHi";
4558 break;
4559 default:
4560 goto die;
4562 break;
4563 case 30:
4564 switch (sel) {
4565 case 0:
4566 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4567 rn = "ErrorEPC";
4568 break;
4569 default:
4570 goto die;
4572 break;
4573 case 31:
4574 switch (sel) {
4575 case 0:
4576 /* EJTAG support */
4577 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
4578 rn = "DESAVE";
4579 break;
4580 default:
4581 goto die;
4583 break;
4584 default:
4585 goto die;
4587 #if defined MIPS_DEBUG_DISAS
4588 if (loglevel & CPU_LOG_TB_IN_ASM) {
4589 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4590 rn, reg, sel);
4592 #endif
4593 return;
4595 die:
4596 #if defined MIPS_DEBUG_DISAS
4597 if (loglevel & CPU_LOG_TB_IN_ASM) {
4598 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4599 rn, reg, sel);
4601 #endif
4602 generate_exception(ctx, EXCP_RI);
4605 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
4607 const char *rn = "invalid";
4609 if (sel != 0)
4610 check_insn(env, ctx, ISA_MIPS64);
4612 if (use_icount)
4613 gen_io_start();
4615 switch (reg) {
4616 case 0:
4617 switch (sel) {
4618 case 0:
4619 tcg_gen_helper_0_1(do_mtc0_index, t0);
4620 rn = "Index";
4621 break;
4622 case 1:
4623 check_insn(env, ctx, ASE_MT);
4624 tcg_gen_helper_0_1(do_mtc0_mvpcontrol, t0);
4625 rn = "MVPControl";
4626 break;
4627 case 2:
4628 check_insn(env, ctx, ASE_MT);
4629 /* ignored */
4630 rn = "MVPConf0";
4631 break;
4632 case 3:
4633 check_insn(env, ctx, ASE_MT);
4634 /* ignored */
4635 rn = "MVPConf1";
4636 break;
4637 default:
4638 goto die;
4640 break;
4641 case 1:
4642 switch (sel) {
4643 case 0:
4644 /* ignored */
4645 rn = "Random";
4646 break;
4647 case 1:
4648 check_insn(env, ctx, ASE_MT);
4649 tcg_gen_helper_0_1(do_mtc0_vpecontrol, t0);
4650 rn = "VPEControl";
4651 break;
4652 case 2:
4653 check_insn(env, ctx, ASE_MT);
4654 tcg_gen_helper_0_1(do_mtc0_vpeconf0, t0);
4655 rn = "VPEConf0";
4656 break;
4657 case 3:
4658 check_insn(env, ctx, ASE_MT);
4659 tcg_gen_helper_0_1(do_mtc0_vpeconf1, t0);
4660 rn = "VPEConf1";
4661 break;
4662 case 4:
4663 check_insn(env, ctx, ASE_MT);
4664 tcg_gen_helper_0_1(do_mtc0_yqmask, t0);
4665 rn = "YQMask";
4666 break;
4667 case 5:
4668 check_insn(env, ctx, ASE_MT);
4669 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4670 rn = "VPESchedule";
4671 break;
4672 case 6:
4673 check_insn(env, ctx, ASE_MT);
4674 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4675 rn = "VPEScheFBack";
4676 break;
4677 case 7:
4678 check_insn(env, ctx, ASE_MT);
4679 tcg_gen_helper_0_1(do_mtc0_vpeopt, t0);
4680 rn = "VPEOpt";
4681 break;
4682 default:
4683 goto die;
4685 break;
4686 case 2:
4687 switch (sel) {
4688 case 0:
4689 tcg_gen_helper_0_1(do_mtc0_entrylo0, t0);
4690 rn = "EntryLo0";
4691 break;
4692 case 1:
4693 check_insn(env, ctx, ASE_MT);
4694 tcg_gen_helper_0_1(do_mtc0_tcstatus, t0);
4695 rn = "TCStatus";
4696 break;
4697 case 2:
4698 check_insn(env, ctx, ASE_MT);
4699 tcg_gen_helper_0_1(do_mtc0_tcbind, t0);
4700 rn = "TCBind";
4701 break;
4702 case 3:
4703 check_insn(env, ctx, ASE_MT);
4704 tcg_gen_helper_0_1(do_mtc0_tcrestart, t0);
4705 rn = "TCRestart";
4706 break;
4707 case 4:
4708 check_insn(env, ctx, ASE_MT);
4709 tcg_gen_helper_0_1(do_mtc0_tchalt, t0);
4710 rn = "TCHalt";
4711 break;
4712 case 5:
4713 check_insn(env, ctx, ASE_MT);
4714 tcg_gen_helper_0_1(do_mtc0_tccontext, t0);
4715 rn = "TCContext";
4716 break;
4717 case 6:
4718 check_insn(env, ctx, ASE_MT);
4719 tcg_gen_helper_0_1(do_mtc0_tcschedule, t0);
4720 rn = "TCSchedule";
4721 break;
4722 case 7:
4723 check_insn(env, ctx, ASE_MT);
4724 tcg_gen_helper_0_1(do_mtc0_tcschefback, t0);
4725 rn = "TCScheFBack";
4726 break;
4727 default:
4728 goto die;
4730 break;
4731 case 3:
4732 switch (sel) {
4733 case 0:
4734 tcg_gen_helper_0_1(do_mtc0_entrylo1, t0);
4735 rn = "EntryLo1";
4736 break;
4737 default:
4738 goto die;
4740 break;
4741 case 4:
4742 switch (sel) {
4743 case 0:
4744 tcg_gen_helper_0_1(do_mtc0_context, t0);
4745 rn = "Context";
4746 break;
4747 case 1:
4748 // tcg_gen_helper_0_1(do_mtc0_contextconfig, t0); /* SmartMIPS ASE */
4749 rn = "ContextConfig";
4750 // break;
4751 default:
4752 goto die;
4754 break;
4755 case 5:
4756 switch (sel) {
4757 case 0:
4758 tcg_gen_helper_0_1(do_mtc0_pagemask, t0);
4759 rn = "PageMask";
4760 break;
4761 case 1:
4762 check_insn(env, ctx, ISA_MIPS32R2);
4763 tcg_gen_helper_0_1(do_mtc0_pagegrain, t0);
4764 rn = "PageGrain";
4765 break;
4766 default:
4767 goto die;
4769 break;
4770 case 6:
4771 switch (sel) {
4772 case 0:
4773 tcg_gen_helper_0_1(do_mtc0_wired, t0);
4774 rn = "Wired";
4775 break;
4776 case 1:
4777 check_insn(env, ctx, ISA_MIPS32R2);
4778 tcg_gen_helper_0_1(do_mtc0_srsconf0, t0);
4779 rn = "SRSConf0";
4780 break;
4781 case 2:
4782 check_insn(env, ctx, ISA_MIPS32R2);
4783 tcg_gen_helper_0_1(do_mtc0_srsconf1, t0);
4784 rn = "SRSConf1";
4785 break;
4786 case 3:
4787 check_insn(env, ctx, ISA_MIPS32R2);
4788 tcg_gen_helper_0_1(do_mtc0_srsconf2, t0);
4789 rn = "SRSConf2";
4790 break;
4791 case 4:
4792 check_insn(env, ctx, ISA_MIPS32R2);
4793 tcg_gen_helper_0_1(do_mtc0_srsconf3, t0);
4794 rn = "SRSConf3";
4795 break;
4796 case 5:
4797 check_insn(env, ctx, ISA_MIPS32R2);
4798 tcg_gen_helper_0_1(do_mtc0_srsconf4, t0);
4799 rn = "SRSConf4";
4800 break;
4801 default:
4802 goto die;
4804 break;
4805 case 7:
4806 switch (sel) {
4807 case 0:
4808 check_insn(env, ctx, ISA_MIPS32R2);
4809 tcg_gen_helper_0_1(do_mtc0_hwrena, t0);
4810 rn = "HWREna";
4811 break;
4812 default:
4813 goto die;
4815 break;
4816 case 8:
4817 /* ignored */
4818 rn = "BadVAddr";
4819 break;
4820 case 9:
4821 switch (sel) {
4822 case 0:
4823 tcg_gen_helper_0_1(do_mtc0_count, t0);
4824 rn = "Count";
4825 break;
4826 /* 6,7 are implementation dependent */
4827 default:
4828 goto die;
4830 /* Stop translation as we may have switched the execution mode */
4831 ctx->bstate = BS_STOP;
4832 break;
4833 case 10:
4834 switch (sel) {
4835 case 0:
4836 tcg_gen_helper_0_1(do_mtc0_entryhi, t0);
4837 rn = "EntryHi";
4838 break;
4839 default:
4840 goto die;
4842 break;
4843 case 11:
4844 switch (sel) {
4845 case 0:
4846 tcg_gen_helper_0_1(do_mtc0_compare, t0);
4847 rn = "Compare";
4848 break;
4849 /* 6,7 are implementation dependent */
4850 default:
4851 goto die;
4853 /* Stop translation as we may have switched the execution mode */
4854 ctx->bstate = BS_STOP;
4855 break;
4856 case 12:
4857 switch (sel) {
4858 case 0:
4859 tcg_gen_helper_0_1(do_mtc0_status, t0);
4860 /* BS_STOP isn't good enough here, hflags may have changed. */
4861 gen_save_pc(ctx->pc + 4);
4862 ctx->bstate = BS_EXCP;
4863 rn = "Status";
4864 break;
4865 case 1:
4866 check_insn(env, ctx, ISA_MIPS32R2);
4867 tcg_gen_helper_0_1(do_mtc0_intctl, t0);
4868 /* Stop translation as we may have switched the execution mode */
4869 ctx->bstate = BS_STOP;
4870 rn = "IntCtl";
4871 break;
4872 case 2:
4873 check_insn(env, ctx, ISA_MIPS32R2);
4874 tcg_gen_helper_0_1(do_mtc0_srsctl, t0);
4875 /* Stop translation as we may have switched the execution mode */
4876 ctx->bstate = BS_STOP;
4877 rn = "SRSCtl";
4878 break;
4879 case 3:
4880 check_insn(env, ctx, ISA_MIPS32R2);
4881 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
4882 /* Stop translation as we may have switched the execution mode */
4883 ctx->bstate = BS_STOP;
4884 rn = "SRSMap";
4885 break;
4886 default:
4887 goto die;
4889 break;
4890 case 13:
4891 switch (sel) {
4892 case 0:
4893 tcg_gen_helper_0_1(do_mtc0_cause, t0);
4894 rn = "Cause";
4895 break;
4896 default:
4897 goto die;
4899 /* Stop translation as we may have switched the execution mode */
4900 ctx->bstate = BS_STOP;
4901 break;
4902 case 14:
4903 switch (sel) {
4904 case 0:
4905 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4906 rn = "EPC";
4907 break;
4908 default:
4909 goto die;
4911 break;
4912 case 15:
4913 switch (sel) {
4914 case 0:
4915 /* ignored */
4916 rn = "PRid";
4917 break;
4918 case 1:
4919 check_insn(env, ctx, ISA_MIPS32R2);
4920 tcg_gen_helper_0_1(do_mtc0_ebase, t0);
4921 rn = "EBase";
4922 break;
4923 default:
4924 goto die;
4926 break;
4927 case 16:
4928 switch (sel) {
4929 case 0:
4930 tcg_gen_helper_0_1(do_mtc0_config0, t0);
4931 rn = "Config";
4932 /* Stop translation as we may have switched the execution mode */
4933 ctx->bstate = BS_STOP;
4934 break;
4935 case 1:
4936 /* ignored */
4937 rn = "Config1";
4938 break;
4939 case 2:
4940 tcg_gen_helper_0_1(do_mtc0_config2, t0);
4941 rn = "Config2";
4942 /* Stop translation as we may have switched the execution mode */
4943 ctx->bstate = BS_STOP;
4944 break;
4945 case 3:
4946 /* ignored */
4947 rn = "Config3";
4948 break;
4949 /* 6,7 are implementation dependent */
4950 default:
4951 rn = "Invalid config selector";
4952 goto die;
4954 break;
4955 case 17:
4956 switch (sel) {
4957 case 0:
4958 /* ignored */
4959 rn = "LLAddr";
4960 break;
4961 default:
4962 goto die;
4964 break;
4965 case 18:
4966 switch (sel) {
4967 case 0 ... 7:
4968 tcg_gen_helper_0_1i(do_mtc0_watchlo, t0, sel);
4969 rn = "WatchLo";
4970 break;
4971 default:
4972 goto die;
4974 break;
4975 case 19:
4976 switch (sel) {
4977 case 0 ... 7:
4978 tcg_gen_helper_0_1i(do_mtc0_watchhi, t0, sel);
4979 rn = "WatchHi";
4980 break;
4981 default:
4982 goto die;
4984 break;
4985 case 20:
4986 switch (sel) {
4987 case 0:
4988 check_insn(env, ctx, ISA_MIPS3);
4989 tcg_gen_helper_0_1(do_mtc0_xcontext, t0);
4990 rn = "XContext";
4991 break;
4992 default:
4993 goto die;
4995 break;
4996 case 21:
4997 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4998 switch (sel) {
4999 case 0:
5000 tcg_gen_helper_0_1(do_mtc0_framemask, t0);
5001 rn = "Framemask";
5002 break;
5003 default:
5004 goto die;
5006 break;
5007 case 22:
5008 /* ignored */
5009 rn = "Diagnostic"; /* implementation dependent */
5010 break;
5011 case 23:
5012 switch (sel) {
5013 case 0:
5014 tcg_gen_helper_0_1(do_mtc0_debug, t0); /* EJTAG support */
5015 /* BS_STOP isn't good enough here, hflags may have changed. */
5016 gen_save_pc(ctx->pc + 4);
5017 ctx->bstate = BS_EXCP;
5018 rn = "Debug";
5019 break;
5020 case 1:
5021 // tcg_gen_helper_0_1(do_mtc0_tracecontrol, t0); /* PDtrace support */
5022 /* Stop translation as we may have switched the execution mode */
5023 ctx->bstate = BS_STOP;
5024 rn = "TraceControl";
5025 // break;
5026 case 2:
5027 // tcg_gen_helper_0_1(do_mtc0_tracecontrol2, t0); /* PDtrace support */
5028 /* Stop translation as we may have switched the execution mode */
5029 ctx->bstate = BS_STOP;
5030 rn = "TraceControl2";
5031 // break;
5032 case 3:
5033 // tcg_gen_helper_0_1(do_mtc0_usertracedata, t0); /* PDtrace support */
5034 /* Stop translation as we may have switched the execution mode */
5035 ctx->bstate = BS_STOP;
5036 rn = "UserTraceData";
5037 // break;
5038 case 4:
5039 // tcg_gen_helper_0_1(do_mtc0_tracebpc, t0); /* PDtrace support */
5040 /* Stop translation as we may have switched the execution mode */
5041 ctx->bstate = BS_STOP;
5042 rn = "TraceBPC";
5043 // break;
5044 default:
5045 goto die;
5047 break;
5048 case 24:
5049 switch (sel) {
5050 case 0:
5051 /* EJTAG support */
5052 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
5053 rn = "DEPC";
5054 break;
5055 default:
5056 goto die;
5058 break;
5059 case 25:
5060 switch (sel) {
5061 case 0:
5062 tcg_gen_helper_0_1(do_mtc0_performance0, t0);
5063 rn = "Performance0";
5064 break;
5065 case 1:
5066 // tcg_gen_helper_0_1(do_mtc0_performance1, t0);
5067 rn = "Performance1";
5068 // break;
5069 case 2:
5070 // tcg_gen_helper_0_1(do_mtc0_performance2, t0);
5071 rn = "Performance2";
5072 // break;
5073 case 3:
5074 // tcg_gen_helper_0_1(do_mtc0_performance3, t0);
5075 rn = "Performance3";
5076 // break;
5077 case 4:
5078 // tcg_gen_helper_0_1(do_mtc0_performance4, t0);
5079 rn = "Performance4";
5080 // break;
5081 case 5:
5082 // tcg_gen_helper_0_1(do_mtc0_performance5, t0);
5083 rn = "Performance5";
5084 // break;
5085 case 6:
5086 // tcg_gen_helper_0_1(do_mtc0_performance6, t0);
5087 rn = "Performance6";
5088 // break;
5089 case 7:
5090 // tcg_gen_helper_0_1(do_mtc0_performance7, t0);
5091 rn = "Performance7";
5092 // break;
5093 default:
5094 goto die;
5096 break;
5097 case 26:
5098 /* ignored */
5099 rn = "ECC";
5100 break;
5101 case 27:
5102 switch (sel) {
5103 case 0 ... 3:
5104 /* ignored */
5105 rn = "CacheErr";
5106 break;
5107 default:
5108 goto die;
5110 break;
5111 case 28:
5112 switch (sel) {
5113 case 0:
5114 case 2:
5115 case 4:
5116 case 6:
5117 tcg_gen_helper_0_1(do_mtc0_taglo, t0);
5118 rn = "TagLo";
5119 break;
5120 case 1:
5121 case 3:
5122 case 5:
5123 case 7:
5124 tcg_gen_helper_0_1(do_mtc0_datalo, t0);
5125 rn = "DataLo";
5126 break;
5127 default:
5128 goto die;
5130 break;
5131 case 29:
5132 switch (sel) {
5133 case 0:
5134 case 2:
5135 case 4:
5136 case 6:
5137 tcg_gen_helper_0_1(do_mtc0_taghi, t0);
5138 rn = "TagHi";
5139 break;
5140 case 1:
5141 case 3:
5142 case 5:
5143 case 7:
5144 tcg_gen_helper_0_1(do_mtc0_datahi, t0);
5145 rn = "DataHi";
5146 break;
5147 default:
5148 rn = "invalid sel";
5149 goto die;
5151 break;
5152 case 30:
5153 switch (sel) {
5154 case 0:
5155 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5156 rn = "ErrorEPC";
5157 break;
5158 default:
5159 goto die;
5161 break;
5162 case 31:
5163 switch (sel) {
5164 case 0:
5165 /* EJTAG support */
5166 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
5167 rn = "DESAVE";
5168 break;
5169 default:
5170 goto die;
5172 /* Stop translation as we may have switched the execution mode */
5173 ctx->bstate = BS_STOP;
5174 break;
5175 default:
5176 goto die;
5178 #if defined MIPS_DEBUG_DISAS
5179 if (loglevel & CPU_LOG_TB_IN_ASM) {
5180 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5181 rn, reg, sel);
5183 #endif
5184 /* For simplicity assume that all writes can cause interrupts. */
5185 if (use_icount) {
5186 gen_io_end();
5187 ctx->bstate = BS_STOP;
5189 return;
5191 die:
5192 #if defined MIPS_DEBUG_DISAS
5193 if (loglevel & CPU_LOG_TB_IN_ASM) {
5194 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5195 rn, reg, sel);
5197 #endif
5198 generate_exception(ctx, EXCP_RI);
5200 #endif /* TARGET_MIPS64 */
5202 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5203 int u, int sel, int h)
5205 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5206 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5208 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5209 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5210 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5211 tcg_gen_movi_tl(t0, -1);
5212 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5213 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5214 tcg_gen_movi_tl(t0, -1);
5215 else if (u == 0) {
5216 switch (rt) {
5217 case 2:
5218 switch (sel) {
5219 case 1:
5220 tcg_gen_helper_1_1(do_mftc0_tcstatus, t0, t0);
5221 break;
5222 case 2:
5223 tcg_gen_helper_1_1(do_mftc0_tcbind, t0, t0);
5224 break;
5225 case 3:
5226 tcg_gen_helper_1_1(do_mftc0_tcrestart, t0, t0);
5227 break;
5228 case 4:
5229 tcg_gen_helper_1_1(do_mftc0_tchalt, t0, t0);
5230 break;
5231 case 5:
5232 tcg_gen_helper_1_1(do_mftc0_tccontext, t0, t0);
5233 break;
5234 case 6:
5235 tcg_gen_helper_1_1(do_mftc0_tcschedule, t0, t0);
5236 break;
5237 case 7:
5238 tcg_gen_helper_1_1(do_mftc0_tcschefback, t0, t0);
5239 break;
5240 default:
5241 gen_mfc0(env, ctx, t0, rt, sel);
5242 break;
5244 break;
5245 case 10:
5246 switch (sel) {
5247 case 0:
5248 tcg_gen_helper_1_1(do_mftc0_entryhi, t0, t0);
5249 break;
5250 default:
5251 gen_mfc0(env, ctx, t0, rt, sel);
5252 break;
5254 case 12:
5255 switch (sel) {
5256 case 0:
5257 tcg_gen_helper_1_1(do_mftc0_status, t0, t0);
5258 break;
5259 default:
5260 gen_mfc0(env, ctx, t0, rt, sel);
5261 break;
5263 case 23:
5264 switch (sel) {
5265 case 0:
5266 tcg_gen_helper_1_1(do_mftc0_debug, t0, t0);
5267 break;
5268 default:
5269 gen_mfc0(env, ctx, t0, rt, sel);
5270 break;
5272 break;
5273 default:
5274 gen_mfc0(env, ctx, t0, rt, sel);
5276 } else switch (sel) {
5277 /* GPR registers. */
5278 case 0:
5279 tcg_gen_helper_1_1i(do_mftgpr, t0, t0, rt);
5280 break;
5281 /* Auxiliary CPU registers */
5282 case 1:
5283 switch (rt) {
5284 case 0:
5285 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 0);
5286 break;
5287 case 1:
5288 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 0);
5289 break;
5290 case 2:
5291 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 0);
5292 break;
5293 case 4:
5294 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 1);
5295 break;
5296 case 5:
5297 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 1);
5298 break;
5299 case 6:
5300 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 1);
5301 break;
5302 case 8:
5303 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 2);
5304 break;
5305 case 9:
5306 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 2);
5307 break;
5308 case 10:
5309 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 2);
5310 break;
5311 case 12:
5312 tcg_gen_helper_1_1i(do_mftlo, t0, t0, 3);
5313 break;
5314 case 13:
5315 tcg_gen_helper_1_1i(do_mfthi, t0, t0, 3);
5316 break;
5317 case 14:
5318 tcg_gen_helper_1_1i(do_mftacx, t0, t0, 3);
5319 break;
5320 case 16:
5321 tcg_gen_helper_1_1(do_mftdsp, t0, t0);
5322 break;
5323 default:
5324 goto die;
5326 break;
5327 /* Floating point (COP1). */
5328 case 2:
5329 /* XXX: For now we support only a single FPU context. */
5330 if (h == 0) {
5331 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5333 gen_load_fpr32(fp0, rt);
5334 tcg_gen_ext_i32_tl(t0, fp0);
5335 tcg_temp_free(fp0);
5336 } else {
5337 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5339 gen_load_fpr32h(fp0, rt);
5340 tcg_gen_ext_i32_tl(t0, fp0);
5341 tcg_temp_free(fp0);
5343 break;
5344 case 3:
5345 /* XXX: For now we support only a single FPU context. */
5346 tcg_gen_helper_1_1i(do_cfc1, t0, t0, rt);
5347 break;
5348 /* COP2: Not implemented. */
5349 case 4:
5350 case 5:
5351 /* fall through */
5352 default:
5353 goto die;
5355 #if defined MIPS_DEBUG_DISAS
5356 if (loglevel & CPU_LOG_TB_IN_ASM) {
5357 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5358 rt, u, sel, h);
5360 #endif
5361 gen_store_gpr(t0, rd);
5362 tcg_temp_free(t0);
5363 return;
5365 die:
5366 tcg_temp_free(t0);
5367 #if defined MIPS_DEBUG_DISAS
5368 if (loglevel & CPU_LOG_TB_IN_ASM) {
5369 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5370 rt, u, sel, h);
5372 #endif
5373 generate_exception(ctx, EXCP_RI);
5376 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5377 int u, int sel, int h)
5379 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5380 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5382 gen_load_gpr(t0, rt);
5383 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5384 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5385 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5386 /* NOP */ ;
5387 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5388 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5389 /* NOP */ ;
5390 else if (u == 0) {
5391 switch (rd) {
5392 case 2:
5393 switch (sel) {
5394 case 1:
5395 tcg_gen_helper_0_1(do_mttc0_tcstatus, t0);
5396 break;
5397 case 2:
5398 tcg_gen_helper_0_1(do_mttc0_tcbind, t0);
5399 break;
5400 case 3:
5401 tcg_gen_helper_0_1(do_mttc0_tcrestart, t0);
5402 break;
5403 case 4:
5404 tcg_gen_helper_0_1(do_mttc0_tchalt, t0);
5405 break;
5406 case 5:
5407 tcg_gen_helper_0_1(do_mttc0_tccontext, t0);
5408 break;
5409 case 6:
5410 tcg_gen_helper_0_1(do_mttc0_tcschedule, t0);
5411 break;
5412 case 7:
5413 tcg_gen_helper_0_1(do_mttc0_tcschefback, t0);
5414 break;
5415 default:
5416 gen_mtc0(env, ctx, t0, rd, sel);
5417 break;
5419 break;
5420 case 10:
5421 switch (sel) {
5422 case 0:
5423 tcg_gen_helper_0_1(do_mttc0_entryhi, t0);
5424 break;
5425 default:
5426 gen_mtc0(env, ctx, t0, rd, sel);
5427 break;
5429 case 12:
5430 switch (sel) {
5431 case 0:
5432 tcg_gen_helper_0_1(do_mttc0_status, t0);
5433 break;
5434 default:
5435 gen_mtc0(env, ctx, t0, rd, sel);
5436 break;
5438 case 23:
5439 switch (sel) {
5440 case 0:
5441 tcg_gen_helper_0_1(do_mttc0_debug, t0);
5442 break;
5443 default:
5444 gen_mtc0(env, ctx, t0, rd, sel);
5445 break;
5447 break;
5448 default:
5449 gen_mtc0(env, ctx, t0, rd, sel);
5451 } else switch (sel) {
5452 /* GPR registers. */
5453 case 0:
5454 tcg_gen_helper_0_1i(do_mttgpr, t0, rd);
5455 break;
5456 /* Auxiliary CPU registers */
5457 case 1:
5458 switch (rd) {
5459 case 0:
5460 tcg_gen_helper_0_1i(do_mttlo, t0, 0);
5461 break;
5462 case 1:
5463 tcg_gen_helper_0_1i(do_mtthi, t0, 0);
5464 break;
5465 case 2:
5466 tcg_gen_helper_0_1i(do_mttacx, t0, 0);
5467 break;
5468 case 4:
5469 tcg_gen_helper_0_1i(do_mttlo, t0, 1);
5470 break;
5471 case 5:
5472 tcg_gen_helper_0_1i(do_mtthi, t0, 1);
5473 break;
5474 case 6:
5475 tcg_gen_helper_0_1i(do_mttacx, t0, 1);
5476 break;
5477 case 8:
5478 tcg_gen_helper_0_1i(do_mttlo, t0, 2);
5479 break;
5480 case 9:
5481 tcg_gen_helper_0_1i(do_mtthi, t0, 2);
5482 break;
5483 case 10:
5484 tcg_gen_helper_0_1i(do_mttacx, t0, 2);
5485 break;
5486 case 12:
5487 tcg_gen_helper_0_1i(do_mttlo, t0, 3);
5488 break;
5489 case 13:
5490 tcg_gen_helper_0_1i(do_mtthi, t0, 3);
5491 break;
5492 case 14:
5493 tcg_gen_helper_0_1i(do_mttacx, t0, 3);
5494 break;
5495 case 16:
5496 tcg_gen_helper_0_1(do_mttdsp, t0);
5497 break;
5498 default:
5499 goto die;
5501 break;
5502 /* Floating point (COP1). */
5503 case 2:
5504 /* XXX: For now we support only a single FPU context. */
5505 if (h == 0) {
5506 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5508 tcg_gen_trunc_tl_i32(fp0, t0);
5509 gen_store_fpr32(fp0, rd);
5510 tcg_temp_free(fp0);
5511 } else {
5512 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5514 tcg_gen_trunc_tl_i32(fp0, t0);
5515 gen_store_fpr32h(fp0, rd);
5516 tcg_temp_free(fp0);
5518 break;
5519 case 3:
5520 /* XXX: For now we support only a single FPU context. */
5521 tcg_gen_helper_0_1i(do_ctc1, t0, rd);
5522 break;
5523 /* COP2: Not implemented. */
5524 case 4:
5525 case 5:
5526 /* fall through */
5527 default:
5528 goto die;
5530 #if defined MIPS_DEBUG_DISAS
5531 if (loglevel & CPU_LOG_TB_IN_ASM) {
5532 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5533 rd, u, sel, h);
5535 #endif
5536 tcg_temp_free(t0);
5537 return;
5539 die:
5540 tcg_temp_free(t0);
5541 #if defined MIPS_DEBUG_DISAS
5542 if (loglevel & CPU_LOG_TB_IN_ASM) {
5543 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5544 rd, u, sel, h);
5546 #endif
5547 generate_exception(ctx, EXCP_RI);
5550 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5552 const char *opn = "ldst";
5554 switch (opc) {
5555 case OPC_MFC0:
5556 if (rt == 0) {
5557 /* Treat as NOP. */
5558 return;
5561 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5563 gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5564 gen_store_gpr(t0, rt);
5565 tcg_temp_free(t0);
5567 opn = "mfc0";
5568 break;
5569 case OPC_MTC0:
5571 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5573 gen_load_gpr(t0, rt);
5574 save_cpu_state(ctx, 1);
5575 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5576 tcg_temp_free(t0);
5578 opn = "mtc0";
5579 break;
5580 #if defined(TARGET_MIPS64)
5581 case OPC_DMFC0:
5582 check_insn(env, ctx, ISA_MIPS3);
5583 if (rt == 0) {
5584 /* Treat as NOP. */
5585 return;
5588 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5590 gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5591 gen_store_gpr(t0, rt);
5592 tcg_temp_free(t0);
5594 opn = "dmfc0";
5595 break;
5596 case OPC_DMTC0:
5597 check_insn(env, ctx, ISA_MIPS3);
5599 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5601 gen_load_gpr(t0, rt);
5602 save_cpu_state(ctx, 1);
5603 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5604 tcg_temp_free(t0);
5606 opn = "dmtc0";
5607 break;
5608 #endif
5609 case OPC_MFTR:
5610 check_insn(env, ctx, ASE_MT);
5611 if (rd == 0) {
5612 /* Treat as NOP. */
5613 return;
5615 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5616 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5617 opn = "mftr";
5618 break;
5619 case OPC_MTTR:
5620 check_insn(env, ctx, ASE_MT);
5621 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5622 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5623 opn = "mttr";
5624 break;
5625 case OPC_TLBWI:
5626 opn = "tlbwi";
5627 if (!env->tlb->do_tlbwi)
5628 goto die;
5629 tcg_gen_helper_0_0(env->tlb->do_tlbwi);
5630 break;
5631 case OPC_TLBWR:
5632 opn = "tlbwr";
5633 if (!env->tlb->do_tlbwr)
5634 goto die;
5635 tcg_gen_helper_0_0(env->tlb->do_tlbwr);
5636 break;
5637 case OPC_TLBP:
5638 opn = "tlbp";
5639 if (!env->tlb->do_tlbp)
5640 goto die;
5641 tcg_gen_helper_0_0(env->tlb->do_tlbp);
5642 break;
5643 case OPC_TLBR:
5644 opn = "tlbr";
5645 if (!env->tlb->do_tlbr)
5646 goto die;
5647 tcg_gen_helper_0_0(env->tlb->do_tlbr);
5648 break;
5649 case OPC_ERET:
5650 opn = "eret";
5651 check_insn(env, ctx, ISA_MIPS2);
5652 save_cpu_state(ctx, 1);
5653 tcg_gen_helper_0_0(do_eret);
5654 ctx->bstate = BS_EXCP;
5655 break;
5656 case OPC_DERET:
5657 opn = "deret";
5658 check_insn(env, ctx, ISA_MIPS32);
5659 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5660 MIPS_INVAL(opn);
5661 generate_exception(ctx, EXCP_RI);
5662 } else {
5663 save_cpu_state(ctx, 1);
5664 tcg_gen_helper_0_0(do_deret);
5665 ctx->bstate = BS_EXCP;
5667 break;
5668 case OPC_WAIT:
5669 opn = "wait";
5670 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5671 /* If we get an exception, we want to restart at next instruction */
5672 ctx->pc += 4;
5673 save_cpu_state(ctx, 1);
5674 ctx->pc -= 4;
5675 tcg_gen_helper_0_0(do_wait);
5676 ctx->bstate = BS_EXCP;
5677 break;
5678 default:
5679 die:
5680 MIPS_INVAL(opn);
5681 generate_exception(ctx, EXCP_RI);
5682 return;
5684 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5686 #endif /* !CONFIG_USER_ONLY */
5688 /* CP1 Branches (before delay slot) */
5689 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5690 int32_t cc, int32_t offset)
5692 target_ulong btarget;
5693 const char *opn = "cp1 cond branch";
5694 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5695 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
5697 if (cc != 0)
5698 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5700 btarget = ctx->pc + 4 + offset;
5702 switch (op) {
5703 case OPC_BC1F:
5705 int l1 = gen_new_label();
5706 int l2 = gen_new_label();
5707 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5709 get_fp_cond(r_tmp1);
5710 tcg_gen_ext_i32_tl(t0, r_tmp1);
5711 tcg_temp_free(r_tmp1);
5712 tcg_gen_not_tl(t0, t0);
5713 tcg_gen_movi_tl(t1, 0x1 << cc);
5714 tcg_gen_and_tl(t0, t0, t1);
5715 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5716 tcg_gen_movi_tl(t0, 0);
5717 tcg_gen_br(l2);
5718 gen_set_label(l1);
5719 tcg_gen_movi_tl(t0, 1);
5720 gen_set_label(l2);
5722 opn = "bc1f";
5723 goto not_likely;
5724 case OPC_BC1FL:
5726 int l1 = gen_new_label();
5727 int l2 = gen_new_label();
5728 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5730 get_fp_cond(r_tmp1);
5731 tcg_gen_ext_i32_tl(t0, r_tmp1);
5732 tcg_temp_free(r_tmp1);
5733 tcg_gen_not_tl(t0, t0);
5734 tcg_gen_movi_tl(t1, 0x1 << cc);
5735 tcg_gen_and_tl(t0, t0, t1);
5736 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5737 tcg_gen_movi_tl(t0, 0);
5738 tcg_gen_br(l2);
5739 gen_set_label(l1);
5740 tcg_gen_movi_tl(t0, 1);
5741 gen_set_label(l2);
5743 opn = "bc1fl";
5744 goto likely;
5745 case OPC_BC1T:
5747 int l1 = gen_new_label();
5748 int l2 = gen_new_label();
5749 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5751 get_fp_cond(r_tmp1);
5752 tcg_gen_ext_i32_tl(t0, r_tmp1);
5753 tcg_temp_free(r_tmp1);
5754 tcg_gen_movi_tl(t1, 0x1 << cc);
5755 tcg_gen_and_tl(t0, t0, t1);
5756 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5757 tcg_gen_movi_tl(t0, 0);
5758 tcg_gen_br(l2);
5759 gen_set_label(l1);
5760 tcg_gen_movi_tl(t0, 1);
5761 gen_set_label(l2);
5763 opn = "bc1t";
5764 goto not_likely;
5765 case OPC_BC1TL:
5767 int l1 = gen_new_label();
5768 int l2 = gen_new_label();
5769 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5771 get_fp_cond(r_tmp1);
5772 tcg_gen_ext_i32_tl(t0, r_tmp1);
5773 tcg_temp_free(r_tmp1);
5774 tcg_gen_movi_tl(t1, 0x1 << cc);
5775 tcg_gen_and_tl(t0, t0, t1);
5776 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5777 tcg_gen_movi_tl(t0, 0);
5778 tcg_gen_br(l2);
5779 gen_set_label(l1);
5780 tcg_gen_movi_tl(t0, 1);
5781 gen_set_label(l2);
5783 opn = "bc1tl";
5784 likely:
5785 ctx->hflags |= MIPS_HFLAG_BL;
5786 tcg_gen_trunc_tl_i32(bcond, t0);
5787 break;
5788 case OPC_BC1FANY2:
5790 int l1 = gen_new_label();
5791 int l2 = gen_new_label();
5792 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5794 get_fp_cond(r_tmp1);
5795 tcg_gen_ext_i32_tl(t0, r_tmp1);
5796 tcg_temp_free(r_tmp1);
5797 tcg_gen_not_tl(t0, t0);
5798 tcg_gen_movi_tl(t1, 0x3 << cc);
5799 tcg_gen_and_tl(t0, t0, t1);
5800 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5801 tcg_gen_movi_tl(t0, 0);
5802 tcg_gen_br(l2);
5803 gen_set_label(l1);
5804 tcg_gen_movi_tl(t0, 1);
5805 gen_set_label(l2);
5807 opn = "bc1any2f";
5808 goto not_likely;
5809 case OPC_BC1TANY2:
5811 int l1 = gen_new_label();
5812 int l2 = gen_new_label();
5813 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5815 get_fp_cond(r_tmp1);
5816 tcg_gen_ext_i32_tl(t0, r_tmp1);
5817 tcg_temp_free(r_tmp1);
5818 tcg_gen_movi_tl(t1, 0x3 << cc);
5819 tcg_gen_and_tl(t0, t0, t1);
5820 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5821 tcg_gen_movi_tl(t0, 0);
5822 tcg_gen_br(l2);
5823 gen_set_label(l1);
5824 tcg_gen_movi_tl(t0, 1);
5825 gen_set_label(l2);
5827 opn = "bc1any2t";
5828 goto not_likely;
5829 case OPC_BC1FANY4:
5831 int l1 = gen_new_label();
5832 int l2 = gen_new_label();
5833 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5835 get_fp_cond(r_tmp1);
5836 tcg_gen_ext_i32_tl(t0, r_tmp1);
5837 tcg_temp_free(r_tmp1);
5838 tcg_gen_not_tl(t0, t0);
5839 tcg_gen_movi_tl(t1, 0xf << cc);
5840 tcg_gen_and_tl(t0, t0, t1);
5841 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5842 tcg_gen_movi_tl(t0, 0);
5843 tcg_gen_br(l2);
5844 gen_set_label(l1);
5845 tcg_gen_movi_tl(t0, 1);
5846 gen_set_label(l2);
5848 opn = "bc1any4f";
5849 goto not_likely;
5850 case OPC_BC1TANY4:
5852 int l1 = gen_new_label();
5853 int l2 = gen_new_label();
5854 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5856 get_fp_cond(r_tmp1);
5857 tcg_gen_ext_i32_tl(t0, r_tmp1);
5858 tcg_temp_free(r_tmp1);
5859 tcg_gen_movi_tl(t1, 0xf << cc);
5860 tcg_gen_and_tl(t0, t0, t1);
5861 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5862 tcg_gen_movi_tl(t0, 0);
5863 tcg_gen_br(l2);
5864 gen_set_label(l1);
5865 tcg_gen_movi_tl(t0, 1);
5866 gen_set_label(l2);
5868 opn = "bc1any4t";
5869 not_likely:
5870 ctx->hflags |= MIPS_HFLAG_BC;
5871 tcg_gen_trunc_tl_i32(bcond, t0);
5872 break;
5873 default:
5874 MIPS_INVAL(opn);
5875 generate_exception (ctx, EXCP_RI);
5876 goto out;
5878 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5879 ctx->hflags, btarget);
5880 ctx->btarget = btarget;
5882 out:
5883 tcg_temp_free(t0);
5884 tcg_temp_free(t1);
5887 /* Coprocessor 1 (FPU) */
5889 #define FOP(func, fmt) (((fmt) << 21) | (func))
5891 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5893 const char *opn = "cp1 move";
5894 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5896 switch (opc) {
5897 case OPC_MFC1:
5899 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5901 gen_load_fpr32(fp0, fs);
5902 tcg_gen_ext_i32_tl(t0, fp0);
5903 tcg_temp_free(fp0);
5905 gen_store_gpr(t0, rt);
5906 opn = "mfc1";
5907 break;
5908 case OPC_MTC1:
5909 gen_load_gpr(t0, rt);
5911 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5913 tcg_gen_trunc_tl_i32(fp0, t0);
5914 gen_store_fpr32(fp0, fs);
5915 tcg_temp_free(fp0);
5917 opn = "mtc1";
5918 break;
5919 case OPC_CFC1:
5920 tcg_gen_helper_1_i(do_cfc1, t0, fs);
5921 gen_store_gpr(t0, rt);
5922 opn = "cfc1";
5923 break;
5924 case OPC_CTC1:
5925 gen_load_gpr(t0, rt);
5926 tcg_gen_helper_0_1i(do_ctc1, t0, fs);
5927 opn = "ctc1";
5928 break;
5929 case OPC_DMFC1:
5931 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
5933 gen_load_fpr64(ctx, fp0, fs);
5934 tcg_gen_mov_tl(t0, fp0);
5935 tcg_temp_free(fp0);
5937 gen_store_gpr(t0, rt);
5938 opn = "dmfc1";
5939 break;
5940 case OPC_DMTC1:
5941 gen_load_gpr(t0, rt);
5943 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
5945 tcg_gen_mov_tl(fp0, t0);
5946 gen_store_fpr64(ctx, fp0, fs);
5947 tcg_temp_free(fp0);
5949 opn = "dmtc1";
5950 break;
5951 case OPC_MFHC1:
5953 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5955 gen_load_fpr32h(fp0, fs);
5956 tcg_gen_ext_i32_tl(t0, fp0);
5957 tcg_temp_free(fp0);
5959 gen_store_gpr(t0, rt);
5960 opn = "mfhc1";
5961 break;
5962 case OPC_MTHC1:
5963 gen_load_gpr(t0, rt);
5965 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5967 tcg_gen_trunc_tl_i32(fp0, t0);
5968 gen_store_fpr32h(fp0, fs);
5969 tcg_temp_free(fp0);
5971 opn = "mthc1";
5972 break;
5973 default:
5974 MIPS_INVAL(opn);
5975 generate_exception (ctx, EXCP_RI);
5976 goto out;
5978 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5980 out:
5981 tcg_temp_free(t0);
5984 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5986 int l1 = gen_new_label();
5987 uint32_t ccbit;
5988 TCGCond cond;
5989 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5990 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
5991 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_I32);
5993 if (cc)
5994 ccbit = 1 << (24 + cc);
5995 else
5996 ccbit = 1 << 23;
5997 if (tf)
5998 cond = TCG_COND_EQ;
5999 else
6000 cond = TCG_COND_NE;
6002 gen_load_gpr(t0, rd);
6003 gen_load_gpr(t1, rs);
6004 tcg_gen_andi_i32(r_tmp, fpu_fcr31, ccbit);
6005 tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
6006 tcg_temp_free(r_tmp);
6008 tcg_gen_mov_tl(t0, t1);
6009 tcg_temp_free(t1);
6011 gen_set_label(l1);
6012 gen_store_gpr(t0, rd);
6013 tcg_temp_free(t0);
6016 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6018 uint32_t ccbit;
6019 int cond;
6020 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
6021 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6022 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
6023 int l1 = gen_new_label();
6025 if (cc)
6026 ccbit = 1 << (24 + cc);
6027 else
6028 ccbit = 1 << 23;
6030 if (tf)
6031 cond = TCG_COND_EQ;
6032 else
6033 cond = TCG_COND_NE;
6035 gen_load_fpr32(fp0, fs);
6036 gen_load_fpr32(fp1, fd);
6037 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
6038 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
6039 tcg_gen_mov_i32(fp1, fp0);
6040 tcg_temp_free(fp0);
6041 gen_set_label(l1);
6042 tcg_temp_free(r_tmp1);
6043 gen_store_fpr32(fp1, fd);
6044 tcg_temp_free(fp1);
6047 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6049 uint32_t ccbit;
6050 int cond;
6051 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
6052 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
6053 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I64);
6054 int l1 = gen_new_label();
6056 if (cc)
6057 ccbit = 1 << (24 + cc);
6058 else
6059 ccbit = 1 << 23;
6061 if (tf)
6062 cond = TCG_COND_EQ;
6063 else
6064 cond = TCG_COND_NE;
6066 gen_load_fpr64(ctx, fp0, fs);
6067 gen_load_fpr64(ctx, fp1, fd);
6068 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
6069 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
6070 tcg_gen_mov_i64(fp1, fp0);
6071 tcg_temp_free(fp0);
6072 gen_set_label(l1);
6073 tcg_temp_free(r_tmp1);
6074 gen_store_fpr64(ctx, fp1, fd);
6075 tcg_temp_free(fp1);
6078 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6080 int cond;
6081 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
6082 TCGv r_tmp2 = tcg_temp_local_new(TCG_TYPE_I32);
6083 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6084 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
6085 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
6086 TCGv fph1 = tcg_temp_local_new(TCG_TYPE_I32);
6087 int l1 = gen_new_label();
6088 int l2 = gen_new_label();
6090 if (tf)
6091 cond = TCG_COND_EQ;
6092 else
6093 cond = TCG_COND_NE;
6095 gen_load_fpr32(fp0, fs);
6096 gen_load_fpr32h(fph0, fs);
6097 gen_load_fpr32(fp1, fd);
6098 gen_load_fpr32h(fph1, fd);
6099 get_fp_cond(r_tmp1);
6100 tcg_gen_shri_i32(r_tmp1, r_tmp1, cc);
6101 tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x1);
6102 tcg_gen_brcondi_i32(cond, r_tmp2, 0, l1);
6103 tcg_gen_mov_i32(fp1, fp0);
6104 tcg_temp_free(fp0);
6105 gen_set_label(l1);
6106 tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x2);
6107 tcg_gen_brcondi_i32(cond, r_tmp2, 0, l2);
6108 tcg_gen_mov_i32(fph1, fph0);
6109 tcg_temp_free(fph0);
6110 gen_set_label(l2);
6111 tcg_temp_free(r_tmp1);
6112 tcg_temp_free(r_tmp2);
6113 gen_store_fpr32(fp1, fd);
6114 gen_store_fpr32h(fph1, fd);
6115 tcg_temp_free(fp1);
6116 tcg_temp_free(fph1);
6120 static void gen_farith (DisasContext *ctx, uint32_t op1,
6121 int ft, int fs, int fd, int cc)
6123 const char *opn = "farith";
6124 const char *condnames[] = {
6125 "c.f",
6126 "c.un",
6127 "c.eq",
6128 "c.ueq",
6129 "c.olt",
6130 "c.ult",
6131 "c.ole",
6132 "c.ule",
6133 "c.sf",
6134 "c.ngle",
6135 "c.seq",
6136 "c.ngl",
6137 "c.lt",
6138 "c.nge",
6139 "c.le",
6140 "c.ngt",
6142 const char *condnames_abs[] = {
6143 "cabs.f",
6144 "cabs.un",
6145 "cabs.eq",
6146 "cabs.ueq",
6147 "cabs.olt",
6148 "cabs.ult",
6149 "cabs.ole",
6150 "cabs.ule",
6151 "cabs.sf",
6152 "cabs.ngle",
6153 "cabs.seq",
6154 "cabs.ngl",
6155 "cabs.lt",
6156 "cabs.nge",
6157 "cabs.le",
6158 "cabs.ngt",
6160 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6161 uint32_t func = ctx->opcode & 0x3f;
6163 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
6164 case FOP(0, 16):
6166 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6167 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6169 gen_load_fpr32(fp0, fs);
6170 gen_load_fpr32(fp1, ft);
6171 tcg_gen_helper_1_2(do_float_add_s, fp0, fp0, fp1);
6172 tcg_temp_free(fp1);
6173 gen_store_fpr32(fp0, fd);
6174 tcg_temp_free(fp0);
6176 opn = "add.s";
6177 optype = BINOP;
6178 break;
6179 case FOP(1, 16):
6181 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6182 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6184 gen_load_fpr32(fp0, fs);
6185 gen_load_fpr32(fp1, ft);
6186 tcg_gen_helper_1_2(do_float_sub_s, fp0, fp0, fp1);
6187 tcg_temp_free(fp1);
6188 gen_store_fpr32(fp0, fd);
6189 tcg_temp_free(fp0);
6191 opn = "sub.s";
6192 optype = BINOP;
6193 break;
6194 case FOP(2, 16):
6196 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6197 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6199 gen_load_fpr32(fp0, fs);
6200 gen_load_fpr32(fp1, ft);
6201 tcg_gen_helper_1_2(do_float_mul_s, fp0, fp0, fp1);
6202 tcg_temp_free(fp1);
6203 gen_store_fpr32(fp0, fd);
6204 tcg_temp_free(fp0);
6206 opn = "mul.s";
6207 optype = BINOP;
6208 break;
6209 case FOP(3, 16):
6211 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6212 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6214 gen_load_fpr32(fp0, fs);
6215 gen_load_fpr32(fp1, ft);
6216 tcg_gen_helper_1_2(do_float_div_s, fp0, fp0, fp1);
6217 tcg_temp_free(fp1);
6218 gen_store_fpr32(fp0, fd);
6219 tcg_temp_free(fp0);
6221 opn = "div.s";
6222 optype = BINOP;
6223 break;
6224 case FOP(4, 16):
6226 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6228 gen_load_fpr32(fp0, fs);
6229 tcg_gen_helper_1_1(do_float_sqrt_s, fp0, fp0);
6230 gen_store_fpr32(fp0, fd);
6231 tcg_temp_free(fp0);
6233 opn = "sqrt.s";
6234 break;
6235 case FOP(5, 16):
6237 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6239 gen_load_fpr32(fp0, fs);
6240 tcg_gen_helper_1_1(do_float_abs_s, fp0, fp0);
6241 gen_store_fpr32(fp0, fd);
6242 tcg_temp_free(fp0);
6244 opn = "abs.s";
6245 break;
6246 case FOP(6, 16):
6248 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6250 gen_load_fpr32(fp0, fs);
6251 gen_store_fpr32(fp0, fd);
6252 tcg_temp_free(fp0);
6254 opn = "mov.s";
6255 break;
6256 case FOP(7, 16):
6258 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6260 gen_load_fpr32(fp0, fs);
6261 tcg_gen_helper_1_1(do_float_chs_s, fp0, fp0);
6262 gen_store_fpr32(fp0, fd);
6263 tcg_temp_free(fp0);
6265 opn = "neg.s";
6266 break;
6267 case FOP(8, 16):
6268 check_cp1_64bitmode(ctx);
6270 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6271 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6273 gen_load_fpr32(fp32, fs);
6274 tcg_gen_helper_1_1(do_float_roundl_s, fp64, fp32);
6275 tcg_temp_free(fp32);
6276 gen_store_fpr64(ctx, fp64, fd);
6277 tcg_temp_free(fp64);
6279 opn = "round.l.s";
6280 break;
6281 case FOP(9, 16):
6282 check_cp1_64bitmode(ctx);
6284 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6285 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6287 gen_load_fpr32(fp32, fs);
6288 tcg_gen_helper_1_1(do_float_truncl_s, fp64, fp32);
6289 tcg_temp_free(fp32);
6290 gen_store_fpr64(ctx, fp64, fd);
6291 tcg_temp_free(fp64);
6293 opn = "trunc.l.s";
6294 break;
6295 case FOP(10, 16):
6296 check_cp1_64bitmode(ctx);
6298 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6299 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6301 gen_load_fpr32(fp32, fs);
6302 tcg_gen_helper_1_1(do_float_ceill_s, fp64, fp32);
6303 tcg_temp_free(fp32);
6304 gen_store_fpr64(ctx, fp64, fd);
6305 tcg_temp_free(fp64);
6307 opn = "ceil.l.s";
6308 break;
6309 case FOP(11, 16):
6310 check_cp1_64bitmode(ctx);
6312 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6313 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6315 gen_load_fpr32(fp32, fs);
6316 tcg_gen_helper_1_1(do_float_floorl_s, fp64, fp32);
6317 tcg_temp_free(fp32);
6318 gen_store_fpr64(ctx, fp64, fd);
6319 tcg_temp_free(fp64);
6321 opn = "floor.l.s";
6322 break;
6323 case FOP(12, 16):
6325 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6327 gen_load_fpr32(fp0, fs);
6328 tcg_gen_helper_1_1(do_float_roundw_s, fp0, fp0);
6329 gen_store_fpr32(fp0, fd);
6330 tcg_temp_free(fp0);
6332 opn = "round.w.s";
6333 break;
6334 case FOP(13, 16):
6336 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6338 gen_load_fpr32(fp0, fs);
6339 tcg_gen_helper_1_1(do_float_truncw_s, fp0, fp0);
6340 gen_store_fpr32(fp0, fd);
6341 tcg_temp_free(fp0);
6343 opn = "trunc.w.s";
6344 break;
6345 case FOP(14, 16):
6347 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6349 gen_load_fpr32(fp0, fs);
6350 tcg_gen_helper_1_1(do_float_ceilw_s, fp0, fp0);
6351 gen_store_fpr32(fp0, fd);
6352 tcg_temp_free(fp0);
6354 opn = "ceil.w.s";
6355 break;
6356 case FOP(15, 16):
6358 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6360 gen_load_fpr32(fp0, fs);
6361 tcg_gen_helper_1_1(do_float_floorw_s, fp0, fp0);
6362 gen_store_fpr32(fp0, fd);
6363 tcg_temp_free(fp0);
6365 opn = "floor.w.s";
6366 break;
6367 case FOP(17, 16):
6368 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6369 opn = "movcf.s";
6370 break;
6371 case FOP(18, 16):
6373 int l1 = gen_new_label();
6374 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6375 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6377 gen_load_gpr(t0, ft);
6378 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6379 tcg_temp_free(t0);
6380 gen_load_fpr32(fp0, fs);
6381 gen_store_fpr32(fp0, fd);
6382 tcg_temp_free(fp0);
6383 gen_set_label(l1);
6385 opn = "movz.s";
6386 break;
6387 case FOP(19, 16):
6389 int l1 = gen_new_label();
6390 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6391 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6393 gen_load_gpr(t0, ft);
6394 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6395 tcg_temp_free(t0);
6396 gen_load_fpr32(fp0, fs);
6397 gen_store_fpr32(fp0, fd);
6398 tcg_temp_free(fp0);
6399 gen_set_label(l1);
6401 opn = "movn.s";
6402 break;
6403 case FOP(21, 16):
6404 check_cop1x(ctx);
6406 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6408 gen_load_fpr32(fp0, fs);
6409 tcg_gen_helper_1_1(do_float_recip_s, fp0, fp0);
6410 gen_store_fpr32(fp0, fd);
6411 tcg_temp_free(fp0);
6413 opn = "recip.s";
6414 break;
6415 case FOP(22, 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_rsqrt_s, fp0, fp0);
6422 gen_store_fpr32(fp0, fd);
6423 tcg_temp_free(fp0);
6425 opn = "rsqrt.s";
6426 break;
6427 case FOP(28, 16):
6428 check_cp1_64bitmode(ctx);
6430 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6431 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6433 gen_load_fpr32(fp0, fs);
6434 gen_load_fpr32(fp1, fd);
6435 tcg_gen_helper_1_2(do_float_recip2_s, fp0, fp0, fp1);
6436 tcg_temp_free(fp1);
6437 gen_store_fpr32(fp0, fd);
6438 tcg_temp_free(fp0);
6440 opn = "recip2.s";
6441 break;
6442 case FOP(29, 16):
6443 check_cp1_64bitmode(ctx);
6445 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6447 gen_load_fpr32(fp0, fs);
6448 tcg_gen_helper_1_1(do_float_recip1_s, fp0, fp0);
6449 gen_store_fpr32(fp0, fd);
6450 tcg_temp_free(fp0);
6452 opn = "recip1.s";
6453 break;
6454 case FOP(30, 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_rsqrt1_s, fp0, fp0);
6461 gen_store_fpr32(fp0, fd);
6462 tcg_temp_free(fp0);
6464 opn = "rsqrt1.s";
6465 break;
6466 case FOP(31, 16):
6467 check_cp1_64bitmode(ctx);
6469 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6470 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6472 gen_load_fpr32(fp0, fs);
6473 gen_load_fpr32(fp1, ft);
6474 tcg_gen_helper_1_2(do_float_rsqrt2_s, fp0, fp0, fp1);
6475 tcg_temp_free(fp1);
6476 gen_store_fpr32(fp0, fd);
6477 tcg_temp_free(fp0);
6479 opn = "rsqrt2.s";
6480 break;
6481 case FOP(33, 16):
6482 check_cp1_registers(ctx, fd);
6484 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6485 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6487 gen_load_fpr32(fp32, fs);
6488 tcg_gen_helper_1_1(do_float_cvtd_s, fp64, fp32);
6489 tcg_temp_free(fp32);
6490 gen_store_fpr64(ctx, fp64, fd);
6491 tcg_temp_free(fp64);
6493 opn = "cvt.d.s";
6494 break;
6495 case FOP(36, 16):
6497 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6499 gen_load_fpr32(fp0, fs);
6500 tcg_gen_helper_1_1(do_float_cvtw_s, fp0, fp0);
6501 gen_store_fpr32(fp0, fd);
6502 tcg_temp_free(fp0);
6504 opn = "cvt.w.s";
6505 break;
6506 case FOP(37, 16):
6507 check_cp1_64bitmode(ctx);
6509 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6510 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6512 gen_load_fpr32(fp32, fs);
6513 tcg_gen_helper_1_1(do_float_cvtl_s, fp64, fp32);
6514 tcg_temp_free(fp32);
6515 gen_store_fpr64(ctx, fp64, fd);
6516 tcg_temp_free(fp64);
6518 opn = "cvt.l.s";
6519 break;
6520 case FOP(38, 16):
6521 check_cp1_64bitmode(ctx);
6523 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6524 TCGv fp32_0 = tcg_temp_new(TCG_TYPE_I32);
6525 TCGv fp32_1 = tcg_temp_new(TCG_TYPE_I32);
6527 gen_load_fpr32(fp32_0, fs);
6528 gen_load_fpr32(fp32_1, ft);
6529 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6530 tcg_temp_free(fp32_1);
6531 tcg_temp_free(fp32_0);
6532 gen_store_fpr64(ctx, fp64, fd);
6533 tcg_temp_free(fp64);
6535 opn = "cvt.ps.s";
6536 break;
6537 case FOP(48, 16):
6538 case FOP(49, 16):
6539 case FOP(50, 16):
6540 case FOP(51, 16):
6541 case FOP(52, 16):
6542 case FOP(53, 16):
6543 case FOP(54, 16):
6544 case FOP(55, 16):
6545 case FOP(56, 16):
6546 case FOP(57, 16):
6547 case FOP(58, 16):
6548 case FOP(59, 16):
6549 case FOP(60, 16):
6550 case FOP(61, 16):
6551 case FOP(62, 16):
6552 case FOP(63, 16):
6554 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6555 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6557 gen_load_fpr32(fp0, fs);
6558 gen_load_fpr32(fp1, ft);
6559 if (ctx->opcode & (1 << 6)) {
6560 check_cop1x(ctx);
6561 gen_cmpabs_s(func-48, fp0, fp1, cc);
6562 opn = condnames_abs[func-48];
6563 } else {
6564 gen_cmp_s(func-48, fp0, fp1, cc);
6565 opn = condnames[func-48];
6567 tcg_temp_free(fp0);
6568 tcg_temp_free(fp1);
6570 break;
6571 case FOP(0, 17):
6572 check_cp1_registers(ctx, fs | ft | fd);
6574 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6575 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6577 gen_load_fpr64(ctx, fp0, fs);
6578 gen_load_fpr64(ctx, fp1, ft);
6579 tcg_gen_helper_1_2(do_float_add_d, fp0, fp0, fp1);
6580 tcg_temp_free(fp1);
6581 gen_store_fpr64(ctx, fp0, fd);
6582 tcg_temp_free(fp0);
6584 opn = "add.d";
6585 optype = BINOP;
6586 break;
6587 case FOP(1, 17):
6588 check_cp1_registers(ctx, fs | ft | fd);
6590 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6591 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6593 gen_load_fpr64(ctx, fp0, fs);
6594 gen_load_fpr64(ctx, fp1, ft);
6595 tcg_gen_helper_1_2(do_float_sub_d, fp0, fp0, fp1);
6596 tcg_temp_free(fp1);
6597 gen_store_fpr64(ctx, fp0, fd);
6598 tcg_temp_free(fp0);
6600 opn = "sub.d";
6601 optype = BINOP;
6602 break;
6603 case FOP(2, 17):
6604 check_cp1_registers(ctx, fs | ft | fd);
6606 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6607 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6609 gen_load_fpr64(ctx, fp0, fs);
6610 gen_load_fpr64(ctx, fp1, ft);
6611 tcg_gen_helper_1_2(do_float_mul_d, fp0, fp0, fp1);
6612 tcg_temp_free(fp1);
6613 gen_store_fpr64(ctx, fp0, fd);
6614 tcg_temp_free(fp0);
6616 opn = "mul.d";
6617 optype = BINOP;
6618 break;
6619 case FOP(3, 17):
6620 check_cp1_registers(ctx, fs | ft | fd);
6622 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6623 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6625 gen_load_fpr64(ctx, fp0, fs);
6626 gen_load_fpr64(ctx, fp1, ft);
6627 tcg_gen_helper_1_2(do_float_div_d, fp0, fp0, fp1);
6628 tcg_temp_free(fp1);
6629 gen_store_fpr64(ctx, fp0, fd);
6630 tcg_temp_free(fp0);
6632 opn = "div.d";
6633 optype = BINOP;
6634 break;
6635 case FOP(4, 17):
6636 check_cp1_registers(ctx, fs | fd);
6638 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6640 gen_load_fpr64(ctx, fp0, fs);
6641 tcg_gen_helper_1_1(do_float_sqrt_d, fp0, fp0);
6642 gen_store_fpr64(ctx, fp0, fd);
6643 tcg_temp_free(fp0);
6645 opn = "sqrt.d";
6646 break;
6647 case FOP(5, 17):
6648 check_cp1_registers(ctx, fs | fd);
6650 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6652 gen_load_fpr64(ctx, fp0, fs);
6653 tcg_gen_helper_1_1(do_float_abs_d, fp0, fp0);
6654 gen_store_fpr64(ctx, fp0, fd);
6655 tcg_temp_free(fp0);
6657 opn = "abs.d";
6658 break;
6659 case FOP(6, 17):
6660 check_cp1_registers(ctx, fs | fd);
6662 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6664 gen_load_fpr64(ctx, fp0, fs);
6665 gen_store_fpr64(ctx, fp0, fd);
6666 tcg_temp_free(fp0);
6668 opn = "mov.d";
6669 break;
6670 case FOP(7, 17):
6671 check_cp1_registers(ctx, fs | fd);
6673 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6675 gen_load_fpr64(ctx, fp0, fs);
6676 tcg_gen_helper_1_1(do_float_chs_d, fp0, fp0);
6677 gen_store_fpr64(ctx, fp0, fd);
6678 tcg_temp_free(fp0);
6680 opn = "neg.d";
6681 break;
6682 case FOP(8, 17):
6683 check_cp1_64bitmode(ctx);
6685 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6687 gen_load_fpr64(ctx, fp0, fs);
6688 tcg_gen_helper_1_1(do_float_roundl_d, fp0, fp0);
6689 gen_store_fpr64(ctx, fp0, fd);
6690 tcg_temp_free(fp0);
6692 opn = "round.l.d";
6693 break;
6694 case FOP(9, 17):
6695 check_cp1_64bitmode(ctx);
6697 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6699 gen_load_fpr64(ctx, fp0, fs);
6700 tcg_gen_helper_1_1(do_float_truncl_d, fp0, fp0);
6701 gen_store_fpr64(ctx, fp0, fd);
6702 tcg_temp_free(fp0);
6704 opn = "trunc.l.d";
6705 break;
6706 case FOP(10, 17):
6707 check_cp1_64bitmode(ctx);
6709 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6711 gen_load_fpr64(ctx, fp0, fs);
6712 tcg_gen_helper_1_1(do_float_ceill_d, fp0, fp0);
6713 gen_store_fpr64(ctx, fp0, fd);
6714 tcg_temp_free(fp0);
6716 opn = "ceil.l.d";
6717 break;
6718 case FOP(11, 17):
6719 check_cp1_64bitmode(ctx);
6721 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6723 gen_load_fpr64(ctx, fp0, fs);
6724 tcg_gen_helper_1_1(do_float_floorl_d, fp0, fp0);
6725 gen_store_fpr64(ctx, fp0, fd);
6726 tcg_temp_free(fp0);
6728 opn = "floor.l.d";
6729 break;
6730 case FOP(12, 17):
6731 check_cp1_registers(ctx, fs);
6733 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6734 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6736 gen_load_fpr64(ctx, fp64, fs);
6737 tcg_gen_helper_1_1(do_float_roundw_d, fp32, fp64);
6738 tcg_temp_free(fp64);
6739 gen_store_fpr32(fp32, fd);
6740 tcg_temp_free(fp32);
6742 opn = "round.w.d";
6743 break;
6744 case FOP(13, 17):
6745 check_cp1_registers(ctx, fs);
6747 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6748 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6750 gen_load_fpr64(ctx, fp64, fs);
6751 tcg_gen_helper_1_1(do_float_truncw_d, fp32, fp64);
6752 tcg_temp_free(fp64);
6753 gen_store_fpr32(fp32, fd);
6754 tcg_temp_free(fp32);
6756 opn = "trunc.w.d";
6757 break;
6758 case FOP(14, 17):
6759 check_cp1_registers(ctx, fs);
6761 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6762 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6764 gen_load_fpr64(ctx, fp64, fs);
6765 tcg_gen_helper_1_1(do_float_ceilw_d, fp32, fp64);
6766 tcg_temp_free(fp64);
6767 gen_store_fpr32(fp32, fd);
6768 tcg_temp_free(fp32);
6770 opn = "ceil.w.d";
6771 break;
6772 case FOP(15, 17):
6773 check_cp1_registers(ctx, fs);
6775 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6776 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6778 gen_load_fpr64(ctx, fp64, fs);
6779 tcg_gen_helper_1_1(do_float_floorw_d, fp32, fp64);
6780 tcg_temp_free(fp64);
6781 gen_store_fpr32(fp32, fd);
6782 tcg_temp_free(fp32);
6784 opn = "floor.w.d";
6785 break;
6786 case FOP(17, 17):
6787 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6788 opn = "movcf.d";
6789 break;
6790 case FOP(18, 17):
6792 int l1 = gen_new_label();
6793 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6794 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
6796 gen_load_gpr(t0, ft);
6797 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6798 tcg_temp_free(t0);
6799 gen_load_fpr64(ctx, fp0, fs);
6800 gen_store_fpr64(ctx, fp0, fd);
6801 tcg_temp_free(fp0);
6802 gen_set_label(l1);
6804 opn = "movz.d";
6805 break;
6806 case FOP(19, 17):
6808 int l1 = gen_new_label();
6809 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6810 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
6812 gen_load_gpr(t0, ft);
6813 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6814 tcg_temp_free(t0);
6815 gen_load_fpr64(ctx, fp0, fs);
6816 gen_store_fpr64(ctx, fp0, fd);
6817 tcg_temp_free(fp0);
6818 gen_set_label(l1);
6820 opn = "movn.d";
6821 break;
6822 case FOP(21, 17):
6823 check_cp1_64bitmode(ctx);
6825 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6827 gen_load_fpr64(ctx, fp0, fs);
6828 tcg_gen_helper_1_1(do_float_recip_d, fp0, fp0);
6829 gen_store_fpr64(ctx, fp0, fd);
6830 tcg_temp_free(fp0);
6832 opn = "recip.d";
6833 break;
6834 case FOP(22, 17):
6835 check_cp1_64bitmode(ctx);
6837 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6839 gen_load_fpr64(ctx, fp0, fs);
6840 tcg_gen_helper_1_1(do_float_rsqrt_d, fp0, fp0);
6841 gen_store_fpr64(ctx, fp0, fd);
6842 tcg_temp_free(fp0);
6844 opn = "rsqrt.d";
6845 break;
6846 case FOP(28, 17):
6847 check_cp1_64bitmode(ctx);
6849 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6850 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6852 gen_load_fpr64(ctx, fp0, fs);
6853 gen_load_fpr64(ctx, fp1, ft);
6854 tcg_gen_helper_1_2(do_float_recip2_d, fp0, fp0, fp1);
6855 tcg_temp_free(fp1);
6856 gen_store_fpr64(ctx, fp0, fd);
6857 tcg_temp_free(fp0);
6859 opn = "recip2.d";
6860 break;
6861 case FOP(29, 17):
6862 check_cp1_64bitmode(ctx);
6864 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6866 gen_load_fpr64(ctx, fp0, fs);
6867 tcg_gen_helper_1_1(do_float_recip1_d, fp0, fp0);
6868 gen_store_fpr64(ctx, fp0, fd);
6869 tcg_temp_free(fp0);
6871 opn = "recip1.d";
6872 break;
6873 case FOP(30, 17):
6874 check_cp1_64bitmode(ctx);
6876 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6878 gen_load_fpr64(ctx, fp0, fs);
6879 tcg_gen_helper_1_1(do_float_rsqrt1_d, fp0, fp0);
6880 gen_store_fpr64(ctx, fp0, fd);
6881 tcg_temp_free(fp0);
6883 opn = "rsqrt1.d";
6884 break;
6885 case FOP(31, 17):
6886 check_cp1_64bitmode(ctx);
6888 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6889 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6891 gen_load_fpr64(ctx, fp0, fs);
6892 gen_load_fpr64(ctx, fp1, ft);
6893 tcg_gen_helper_1_2(do_float_rsqrt2_d, fp0, fp0, fp1);
6894 tcg_temp_free(fp1);
6895 gen_store_fpr64(ctx, fp0, fd);
6896 tcg_temp_free(fp0);
6898 opn = "rsqrt2.d";
6899 break;
6900 case FOP(48, 17):
6901 case FOP(49, 17):
6902 case FOP(50, 17):
6903 case FOP(51, 17):
6904 case FOP(52, 17):
6905 case FOP(53, 17):
6906 case FOP(54, 17):
6907 case FOP(55, 17):
6908 case FOP(56, 17):
6909 case FOP(57, 17):
6910 case FOP(58, 17):
6911 case FOP(59, 17):
6912 case FOP(60, 17):
6913 case FOP(61, 17):
6914 case FOP(62, 17):
6915 case FOP(63, 17):
6917 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6918 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6920 gen_load_fpr64(ctx, fp0, fs);
6921 gen_load_fpr64(ctx, fp1, ft);
6922 if (ctx->opcode & (1 << 6)) {
6923 check_cop1x(ctx);
6924 check_cp1_registers(ctx, fs | ft);
6925 gen_cmpabs_d(func-48, fp0, fp1, cc);
6926 opn = condnames_abs[func-48];
6927 } else {
6928 check_cp1_registers(ctx, fs | ft);
6929 gen_cmp_d(func-48, fp0, fp1, cc);
6930 opn = condnames[func-48];
6932 tcg_temp_free(fp0);
6933 tcg_temp_free(fp1);
6935 break;
6936 case FOP(32, 17):
6937 check_cp1_registers(ctx, fs);
6939 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6940 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6942 gen_load_fpr64(ctx, fp64, fs);
6943 tcg_gen_helper_1_1(do_float_cvts_d, fp32, fp64);
6944 tcg_temp_free(fp64);
6945 gen_store_fpr32(fp32, fd);
6946 tcg_temp_free(fp32);
6948 opn = "cvt.s.d";
6949 break;
6950 case FOP(36, 17):
6951 check_cp1_registers(ctx, fs);
6953 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6954 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6956 gen_load_fpr64(ctx, fp64, fs);
6957 tcg_gen_helper_1_1(do_float_cvtw_d, fp32, fp64);
6958 tcg_temp_free(fp64);
6959 gen_store_fpr32(fp32, fd);
6960 tcg_temp_free(fp32);
6962 opn = "cvt.w.d";
6963 break;
6964 case FOP(37, 17):
6965 check_cp1_64bitmode(ctx);
6967 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6969 gen_load_fpr64(ctx, fp0, fs);
6970 tcg_gen_helper_1_1(do_float_cvtl_d, fp0, fp0);
6971 gen_store_fpr64(ctx, fp0, fd);
6972 tcg_temp_free(fp0);
6974 opn = "cvt.l.d";
6975 break;
6976 case FOP(32, 20):
6978 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6980 gen_load_fpr32(fp0, fs);
6981 tcg_gen_helper_1_1(do_float_cvts_w, fp0, fp0);
6982 gen_store_fpr32(fp0, fd);
6983 tcg_temp_free(fp0);
6985 opn = "cvt.s.w";
6986 break;
6987 case FOP(33, 20):
6988 check_cp1_registers(ctx, fd);
6990 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6991 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6993 gen_load_fpr32(fp32, fs);
6994 tcg_gen_helper_1_1(do_float_cvtd_w, fp64, fp32);
6995 tcg_temp_free(fp32);
6996 gen_store_fpr64(ctx, fp64, fd);
6997 tcg_temp_free(fp64);
6999 opn = "cvt.d.w";
7000 break;
7001 case FOP(32, 21):
7002 check_cp1_64bitmode(ctx);
7004 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
7005 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
7007 gen_load_fpr64(ctx, fp64, fs);
7008 tcg_gen_helper_1_1(do_float_cvts_l, fp32, fp64);
7009 tcg_temp_free(fp64);
7010 gen_store_fpr32(fp32, fd);
7011 tcg_temp_free(fp32);
7013 opn = "cvt.s.l";
7014 break;
7015 case FOP(33, 21):
7016 check_cp1_64bitmode(ctx);
7018 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7020 gen_load_fpr64(ctx, fp0, fs);
7021 tcg_gen_helper_1_1(do_float_cvtd_l, fp0, fp0);
7022 gen_store_fpr64(ctx, fp0, fd);
7023 tcg_temp_free(fp0);
7025 opn = "cvt.d.l";
7026 break;
7027 case FOP(38, 20):
7028 check_cp1_64bitmode(ctx);
7030 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7032 gen_load_fpr64(ctx, fp0, fs);
7033 tcg_gen_helper_1_1(do_float_cvtps_pw, fp0, fp0);
7034 gen_store_fpr64(ctx, fp0, fd);
7035 tcg_temp_free(fp0);
7037 opn = "cvt.ps.pw";
7038 break;
7039 case FOP(0, 22):
7040 check_cp1_64bitmode(ctx);
7042 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7043 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7045 gen_load_fpr64(ctx, fp0, fs);
7046 gen_load_fpr64(ctx, fp1, ft);
7047 tcg_gen_helper_1_2(do_float_add_ps, fp0, fp0, fp1);
7048 tcg_temp_free(fp1);
7049 gen_store_fpr64(ctx, fp0, fd);
7050 tcg_temp_free(fp0);
7052 opn = "add.ps";
7053 break;
7054 case FOP(1, 22):
7055 check_cp1_64bitmode(ctx);
7057 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7058 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7060 gen_load_fpr64(ctx, fp0, fs);
7061 gen_load_fpr64(ctx, fp1, ft);
7062 tcg_gen_helper_1_2(do_float_sub_ps, fp0, fp0, fp1);
7063 tcg_temp_free(fp1);
7064 gen_store_fpr64(ctx, fp0, fd);
7065 tcg_temp_free(fp0);
7067 opn = "sub.ps";
7068 break;
7069 case FOP(2, 22):
7070 check_cp1_64bitmode(ctx);
7072 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7073 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7075 gen_load_fpr64(ctx, fp0, fs);
7076 gen_load_fpr64(ctx, fp1, ft);
7077 tcg_gen_helper_1_2(do_float_mul_ps, fp0, fp0, fp1);
7078 tcg_temp_free(fp1);
7079 gen_store_fpr64(ctx, fp0, fd);
7080 tcg_temp_free(fp0);
7082 opn = "mul.ps";
7083 break;
7084 case FOP(5, 22):
7085 check_cp1_64bitmode(ctx);
7087 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7089 gen_load_fpr64(ctx, fp0, fs);
7090 tcg_gen_helper_1_1(do_float_abs_ps, fp0, fp0);
7091 gen_store_fpr64(ctx, fp0, fd);
7092 tcg_temp_free(fp0);
7094 opn = "abs.ps";
7095 break;
7096 case FOP(6, 22):
7097 check_cp1_64bitmode(ctx);
7099 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7101 gen_load_fpr64(ctx, fp0, fs);
7102 gen_store_fpr64(ctx, fp0, fd);
7103 tcg_temp_free(fp0);
7105 opn = "mov.ps";
7106 break;
7107 case FOP(7, 22):
7108 check_cp1_64bitmode(ctx);
7110 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7112 gen_load_fpr64(ctx, fp0, fs);
7113 tcg_gen_helper_1_1(do_float_chs_ps, fp0, fp0);
7114 gen_store_fpr64(ctx, fp0, fd);
7115 tcg_temp_free(fp0);
7117 opn = "neg.ps";
7118 break;
7119 case FOP(17, 22):
7120 check_cp1_64bitmode(ctx);
7121 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7122 opn = "movcf.ps";
7123 break;
7124 case FOP(18, 22):
7125 check_cp1_64bitmode(ctx);
7127 int l1 = gen_new_label();
7128 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7129 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7130 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7132 gen_load_gpr(t0, ft);
7133 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7134 tcg_temp_free(t0);
7135 gen_load_fpr32(fp0, fs);
7136 gen_load_fpr32h(fph0, fs);
7137 gen_store_fpr32(fp0, fd);
7138 gen_store_fpr32h(fph0, fd);
7139 tcg_temp_free(fp0);
7140 tcg_temp_free(fph0);
7141 gen_set_label(l1);
7143 opn = "movz.ps";
7144 break;
7145 case FOP(19, 22):
7146 check_cp1_64bitmode(ctx);
7148 int l1 = gen_new_label();
7149 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7150 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7151 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7153 gen_load_gpr(t0, ft);
7154 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
7155 tcg_temp_free(t0);
7156 gen_load_fpr32(fp0, fs);
7157 gen_load_fpr32h(fph0, fs);
7158 gen_store_fpr32(fp0, fd);
7159 gen_store_fpr32h(fph0, fd);
7160 tcg_temp_free(fp0);
7161 tcg_temp_free(fph0);
7162 gen_set_label(l1);
7164 opn = "movn.ps";
7165 break;
7166 case FOP(24, 22):
7167 check_cp1_64bitmode(ctx);
7169 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7170 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7172 gen_load_fpr64(ctx, fp0, ft);
7173 gen_load_fpr64(ctx, fp1, fs);
7174 tcg_gen_helper_1_2(do_float_addr_ps, fp0, fp0, fp1);
7175 tcg_temp_free(fp1);
7176 gen_store_fpr64(ctx, fp0, fd);
7177 tcg_temp_free(fp0);
7179 opn = "addr.ps";
7180 break;
7181 case FOP(26, 22):
7182 check_cp1_64bitmode(ctx);
7184 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7185 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7187 gen_load_fpr64(ctx, fp0, ft);
7188 gen_load_fpr64(ctx, fp1, fs);
7189 tcg_gen_helper_1_2(do_float_mulr_ps, fp0, fp0, fp1);
7190 tcg_temp_free(fp1);
7191 gen_store_fpr64(ctx, fp0, fd);
7192 tcg_temp_free(fp0);
7194 opn = "mulr.ps";
7195 break;
7196 case FOP(28, 22):
7197 check_cp1_64bitmode(ctx);
7199 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7200 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7202 gen_load_fpr64(ctx, fp0, fs);
7203 gen_load_fpr64(ctx, fp1, fd);
7204 tcg_gen_helper_1_2(do_float_recip2_ps, fp0, fp0, fp1);
7205 tcg_temp_free(fp1);
7206 gen_store_fpr64(ctx, fp0, fd);
7207 tcg_temp_free(fp0);
7209 opn = "recip2.ps";
7210 break;
7211 case FOP(29, 22):
7212 check_cp1_64bitmode(ctx);
7214 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7216 gen_load_fpr64(ctx, fp0, fs);
7217 tcg_gen_helper_1_1(do_float_recip1_ps, fp0, fp0);
7218 gen_store_fpr64(ctx, fp0, fd);
7219 tcg_temp_free(fp0);
7221 opn = "recip1.ps";
7222 break;
7223 case FOP(30, 22):
7224 check_cp1_64bitmode(ctx);
7226 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7228 gen_load_fpr64(ctx, fp0, fs);
7229 tcg_gen_helper_1_1(do_float_rsqrt1_ps, fp0, fp0);
7230 gen_store_fpr64(ctx, fp0, fd);
7231 tcg_temp_free(fp0);
7233 opn = "rsqrt1.ps";
7234 break;
7235 case FOP(31, 22):
7236 check_cp1_64bitmode(ctx);
7238 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7239 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7241 gen_load_fpr64(ctx, fp0, fs);
7242 gen_load_fpr64(ctx, fp1, ft);
7243 tcg_gen_helper_1_2(do_float_rsqrt2_ps, fp0, fp0, fp1);
7244 tcg_temp_free(fp1);
7245 gen_store_fpr64(ctx, fp0, fd);
7246 tcg_temp_free(fp0);
7248 opn = "rsqrt2.ps";
7249 break;
7250 case FOP(32, 22):
7251 check_cp1_64bitmode(ctx);
7253 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7255 gen_load_fpr32h(fp0, fs);
7256 tcg_gen_helper_1_1(do_float_cvts_pu, fp0, fp0);
7257 gen_store_fpr32(fp0, fd);
7258 tcg_temp_free(fp0);
7260 opn = "cvt.s.pu";
7261 break;
7262 case FOP(36, 22):
7263 check_cp1_64bitmode(ctx);
7265 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7267 gen_load_fpr64(ctx, fp0, fs);
7268 tcg_gen_helper_1_1(do_float_cvtpw_ps, fp0, fp0);
7269 gen_store_fpr64(ctx, fp0, fd);
7270 tcg_temp_free(fp0);
7272 opn = "cvt.pw.ps";
7273 break;
7274 case FOP(40, 22):
7275 check_cp1_64bitmode(ctx);
7277 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7279 gen_load_fpr32(fp0, fs);
7280 tcg_gen_helper_1_1(do_float_cvts_pl, fp0, fp0);
7281 gen_store_fpr32(fp0, fd);
7282 tcg_temp_free(fp0);
7284 opn = "cvt.s.pl";
7285 break;
7286 case FOP(44, 22):
7287 check_cp1_64bitmode(ctx);
7289 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7290 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7292 gen_load_fpr32(fp0, fs);
7293 gen_load_fpr32(fp1, ft);
7294 gen_store_fpr32h(fp0, fd);
7295 gen_store_fpr32(fp1, fd);
7296 tcg_temp_free(fp0);
7297 tcg_temp_free(fp1);
7299 opn = "pll.ps";
7300 break;
7301 case FOP(45, 22):
7302 check_cp1_64bitmode(ctx);
7304 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7305 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7307 gen_load_fpr32(fp0, fs);
7308 gen_load_fpr32h(fp1, ft);
7309 gen_store_fpr32(fp1, fd);
7310 gen_store_fpr32h(fp0, fd);
7311 tcg_temp_free(fp0);
7312 tcg_temp_free(fp1);
7314 opn = "plu.ps";
7315 break;
7316 case FOP(46, 22):
7317 check_cp1_64bitmode(ctx);
7319 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7320 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7322 gen_load_fpr32h(fp0, fs);
7323 gen_load_fpr32(fp1, ft);
7324 gen_store_fpr32(fp1, fd);
7325 gen_store_fpr32h(fp0, fd);
7326 tcg_temp_free(fp0);
7327 tcg_temp_free(fp1);
7329 opn = "pul.ps";
7330 break;
7331 case FOP(47, 22):
7332 check_cp1_64bitmode(ctx);
7334 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7335 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7337 gen_load_fpr32h(fp0, fs);
7338 gen_load_fpr32h(fp1, ft);
7339 gen_store_fpr32(fp1, fd);
7340 gen_store_fpr32h(fp0, fd);
7341 tcg_temp_free(fp0);
7342 tcg_temp_free(fp1);
7344 opn = "puu.ps";
7345 break;
7346 case FOP(48, 22):
7347 case FOP(49, 22):
7348 case FOP(50, 22):
7349 case FOP(51, 22):
7350 case FOP(52, 22):
7351 case FOP(53, 22):
7352 case FOP(54, 22):
7353 case FOP(55, 22):
7354 case FOP(56, 22):
7355 case FOP(57, 22):
7356 case FOP(58, 22):
7357 case FOP(59, 22):
7358 case FOP(60, 22):
7359 case FOP(61, 22):
7360 case FOP(62, 22):
7361 case FOP(63, 22):
7362 check_cp1_64bitmode(ctx);
7364 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7365 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7367 gen_load_fpr64(ctx, fp0, fs);
7368 gen_load_fpr64(ctx, fp1, ft);
7369 if (ctx->opcode & (1 << 6)) {
7370 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7371 opn = condnames_abs[func-48];
7372 } else {
7373 gen_cmp_ps(func-48, fp0, fp1, cc);
7374 opn = condnames[func-48];
7376 tcg_temp_free(fp0);
7377 tcg_temp_free(fp1);
7379 break;
7380 default:
7381 MIPS_INVAL(opn);
7382 generate_exception (ctx, EXCP_RI);
7383 return;
7385 switch (optype) {
7386 case BINOP:
7387 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7388 break;
7389 case CMPOP:
7390 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7391 break;
7392 default:
7393 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7394 break;
7398 /* Coprocessor 3 (FPU) */
7399 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7400 int fd, int fs, int base, int index)
7402 const char *opn = "extended float load/store";
7403 int store = 0;
7404 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7405 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
7407 if (base == 0) {
7408 gen_load_gpr(t0, index);
7409 } else if (index == 0) {
7410 gen_load_gpr(t0, base);
7411 } else {
7412 gen_load_gpr(t0, base);
7413 gen_load_gpr(t1, index);
7414 gen_op_addr_add(t0, t1);
7416 /* Don't do NOP if destination is zero: we must perform the actual
7417 memory access. */
7418 switch (opc) {
7419 case OPC_LWXC1:
7420 check_cop1x(ctx);
7422 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7424 tcg_gen_qemu_ld32s(fp0, t0, ctx->mem_idx);
7425 gen_store_fpr32(fp0, fd);
7426 tcg_temp_free(fp0);
7428 opn = "lwxc1";
7429 break;
7430 case OPC_LDXC1:
7431 check_cop1x(ctx);
7432 check_cp1_registers(ctx, fd);
7434 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7436 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7437 gen_store_fpr64(ctx, fp0, fd);
7438 tcg_temp_free(fp0);
7440 opn = "ldxc1";
7441 break;
7442 case OPC_LUXC1:
7443 check_cp1_64bitmode(ctx);
7444 tcg_gen_andi_tl(t0, t0, ~0x7);
7446 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7448 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7449 gen_store_fpr64(ctx, fp0, fd);
7450 tcg_temp_free(fp0);
7452 opn = "luxc1";
7453 break;
7454 case OPC_SWXC1:
7455 check_cop1x(ctx);
7457 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7459 gen_load_fpr32(fp0, fs);
7460 tcg_gen_qemu_st32(fp0, t0, ctx->mem_idx);
7461 tcg_temp_free(fp0);
7463 opn = "swxc1";
7464 store = 1;
7465 break;
7466 case OPC_SDXC1:
7467 check_cop1x(ctx);
7468 check_cp1_registers(ctx, fs);
7470 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7472 gen_load_fpr64(ctx, fp0, fs);
7473 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7474 tcg_temp_free(fp0);
7476 opn = "sdxc1";
7477 store = 1;
7478 break;
7479 case OPC_SUXC1:
7480 check_cp1_64bitmode(ctx);
7481 tcg_gen_andi_tl(t0, t0, ~0x7);
7483 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7485 gen_load_fpr64(ctx, fp0, fs);
7486 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7487 tcg_temp_free(fp0);
7489 opn = "suxc1";
7490 store = 1;
7491 break;
7492 default:
7493 MIPS_INVAL(opn);
7494 generate_exception(ctx, EXCP_RI);
7495 tcg_temp_free(t0);
7496 tcg_temp_free(t1);
7497 return;
7499 tcg_temp_free(t0);
7500 tcg_temp_free(t1);
7501 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7502 regnames[index], regnames[base]);
7505 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7506 int fd, int fr, int fs, int ft)
7508 const char *opn = "flt3_arith";
7510 switch (opc) {
7511 case OPC_ALNV_PS:
7512 check_cp1_64bitmode(ctx);
7514 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7515 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7516 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7517 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
7518 TCGv fph1 = tcg_temp_local_new(TCG_TYPE_I32);
7519 int l1 = gen_new_label();
7520 int l2 = gen_new_label();
7522 gen_load_gpr(t0, fr);
7523 tcg_gen_andi_tl(t0, t0, 0x7);
7524 gen_load_fpr32(fp0, fs);
7525 gen_load_fpr32h(fph0, fs);
7526 gen_load_fpr32(fp1, ft);
7527 gen_load_fpr32h(fph1, ft);
7529 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7530 gen_store_fpr32(fp0, fd);
7531 gen_store_fpr32h(fph0, fd);
7532 tcg_gen_br(l2);
7533 gen_set_label(l1);
7534 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7535 tcg_temp_free(t0);
7536 #ifdef TARGET_WORDS_BIGENDIAN
7537 gen_store_fpr32(fph1, fd);
7538 gen_store_fpr32h(fp0, fd);
7539 #else
7540 gen_store_fpr32(fph0, fd);
7541 gen_store_fpr32h(fp1, fd);
7542 #endif
7543 gen_set_label(l2);
7544 tcg_temp_free(fp0);
7545 tcg_temp_free(fph0);
7546 tcg_temp_free(fp1);
7547 tcg_temp_free(fph1);
7549 opn = "alnv.ps";
7550 break;
7551 case OPC_MADD_S:
7552 check_cop1x(ctx);
7554 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7555 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7556 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7558 gen_load_fpr32(fp0, fs);
7559 gen_load_fpr32(fp1, ft);
7560 gen_load_fpr32(fp2, fr);
7561 tcg_gen_helper_1_3(do_float_muladd_s, fp2, fp0, fp1, fp2);
7562 tcg_temp_free(fp0);
7563 tcg_temp_free(fp1);
7564 gen_store_fpr32(fp2, fd);
7565 tcg_temp_free(fp2);
7567 opn = "madd.s";
7568 break;
7569 case OPC_MADD_D:
7570 check_cop1x(ctx);
7571 check_cp1_registers(ctx, fd | fs | ft | fr);
7573 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7574 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7575 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7577 gen_load_fpr64(ctx, fp0, fs);
7578 gen_load_fpr64(ctx, fp1, ft);
7579 gen_load_fpr64(ctx, fp2, fr);
7580 tcg_gen_helper_1_3(do_float_muladd_d, fp2, fp0, fp1, fp2);
7581 tcg_temp_free(fp0);
7582 tcg_temp_free(fp1);
7583 gen_store_fpr64(ctx, fp2, fd);
7584 tcg_temp_free(fp2);
7586 opn = "madd.d";
7587 break;
7588 case OPC_MADD_PS:
7589 check_cp1_64bitmode(ctx);
7591 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7592 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7593 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7595 gen_load_fpr64(ctx, fp0, fs);
7596 gen_load_fpr64(ctx, fp1, ft);
7597 gen_load_fpr64(ctx, fp2, fr);
7598 tcg_gen_helper_1_3(do_float_muladd_ps, fp2, fp0, fp1, fp2);
7599 tcg_temp_free(fp0);
7600 tcg_temp_free(fp1);
7601 gen_store_fpr64(ctx, fp2, fd);
7602 tcg_temp_free(fp2);
7604 opn = "madd.ps";
7605 break;
7606 case OPC_MSUB_S:
7607 check_cop1x(ctx);
7609 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7610 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7611 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7613 gen_load_fpr32(fp0, fs);
7614 gen_load_fpr32(fp1, ft);
7615 gen_load_fpr32(fp2, fr);
7616 tcg_gen_helper_1_3(do_float_mulsub_s, fp2, fp0, fp1, fp2);
7617 tcg_temp_free(fp0);
7618 tcg_temp_free(fp1);
7619 gen_store_fpr32(fp2, fd);
7620 tcg_temp_free(fp2);
7622 opn = "msub.s";
7623 break;
7624 case OPC_MSUB_D:
7625 check_cop1x(ctx);
7626 check_cp1_registers(ctx, fd | fs | ft | fr);
7628 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7629 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7630 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7632 gen_load_fpr64(ctx, fp0, fs);
7633 gen_load_fpr64(ctx, fp1, ft);
7634 gen_load_fpr64(ctx, fp2, fr);
7635 tcg_gen_helper_1_3(do_float_mulsub_d, fp2, fp0, fp1, fp2);
7636 tcg_temp_free(fp0);
7637 tcg_temp_free(fp1);
7638 gen_store_fpr64(ctx, fp2, fd);
7639 tcg_temp_free(fp2);
7641 opn = "msub.d";
7642 break;
7643 case OPC_MSUB_PS:
7644 check_cp1_64bitmode(ctx);
7646 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7647 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7648 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7650 gen_load_fpr64(ctx, fp0, fs);
7651 gen_load_fpr64(ctx, fp1, ft);
7652 gen_load_fpr64(ctx, fp2, fr);
7653 tcg_gen_helper_1_3(do_float_mulsub_ps, fp2, fp0, fp1, fp2);
7654 tcg_temp_free(fp0);
7655 tcg_temp_free(fp1);
7656 gen_store_fpr64(ctx, fp2, fd);
7657 tcg_temp_free(fp2);
7659 opn = "msub.ps";
7660 break;
7661 case OPC_NMADD_S:
7662 check_cop1x(ctx);
7664 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7665 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7666 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7668 gen_load_fpr32(fp0, fs);
7669 gen_load_fpr32(fp1, ft);
7670 gen_load_fpr32(fp2, fr);
7671 tcg_gen_helper_1_3(do_float_nmuladd_s, fp2, fp0, fp1, fp2);
7672 tcg_temp_free(fp0);
7673 tcg_temp_free(fp1);
7674 gen_store_fpr32(fp2, fd);
7675 tcg_temp_free(fp2);
7677 opn = "nmadd.s";
7678 break;
7679 case OPC_NMADD_D:
7680 check_cop1x(ctx);
7681 check_cp1_registers(ctx, fd | fs | ft | fr);
7683 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7684 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7685 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7687 gen_load_fpr64(ctx, fp0, fs);
7688 gen_load_fpr64(ctx, fp1, ft);
7689 gen_load_fpr64(ctx, fp2, fr);
7690 tcg_gen_helper_1_3(do_float_nmuladd_d, fp2, fp0, fp1, fp2);
7691 tcg_temp_free(fp0);
7692 tcg_temp_free(fp1);
7693 gen_store_fpr64(ctx, fp2, fd);
7694 tcg_temp_free(fp2);
7696 opn = "nmadd.d";
7697 break;
7698 case OPC_NMADD_PS:
7699 check_cp1_64bitmode(ctx);
7701 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7702 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7703 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7705 gen_load_fpr64(ctx, fp0, fs);
7706 gen_load_fpr64(ctx, fp1, ft);
7707 gen_load_fpr64(ctx, fp2, fr);
7708 tcg_gen_helper_1_3(do_float_nmuladd_ps, fp2, fp0, fp1, fp2);
7709 tcg_temp_free(fp0);
7710 tcg_temp_free(fp1);
7711 gen_store_fpr64(ctx, fp2, fd);
7712 tcg_temp_free(fp2);
7714 opn = "nmadd.ps";
7715 break;
7716 case OPC_NMSUB_S:
7717 check_cop1x(ctx);
7719 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7720 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7721 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7723 gen_load_fpr32(fp0, fs);
7724 gen_load_fpr32(fp1, ft);
7725 gen_load_fpr32(fp2, fr);
7726 tcg_gen_helper_1_3(do_float_nmulsub_s, fp2, fp0, fp1, fp2);
7727 tcg_temp_free(fp0);
7728 tcg_temp_free(fp1);
7729 gen_store_fpr32(fp2, fd);
7730 tcg_temp_free(fp2);
7732 opn = "nmsub.s";
7733 break;
7734 case OPC_NMSUB_D:
7735 check_cop1x(ctx);
7736 check_cp1_registers(ctx, fd | fs | ft | fr);
7738 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7739 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7740 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7742 gen_load_fpr64(ctx, fp0, fs);
7743 gen_load_fpr64(ctx, fp1, ft);
7744 gen_load_fpr64(ctx, fp2, fr);
7745 tcg_gen_helper_1_3(do_float_nmulsub_d, fp2, fp0, fp1, fp2);
7746 tcg_temp_free(fp0);
7747 tcg_temp_free(fp1);
7748 gen_store_fpr64(ctx, fp2, fd);
7749 tcg_temp_free(fp2);
7751 opn = "nmsub.d";
7752 break;
7753 case OPC_NMSUB_PS:
7754 check_cp1_64bitmode(ctx);
7756 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7757 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7758 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7760 gen_load_fpr64(ctx, fp0, fs);
7761 gen_load_fpr64(ctx, fp1, ft);
7762 gen_load_fpr64(ctx, fp2, fr);
7763 tcg_gen_helper_1_3(do_float_nmulsub_ps, fp2, fp0, fp1, fp2);
7764 tcg_temp_free(fp0);
7765 tcg_temp_free(fp1);
7766 gen_store_fpr64(ctx, fp2, fd);
7767 tcg_temp_free(fp2);
7769 opn = "nmsub.ps";
7770 break;
7771 default:
7772 MIPS_INVAL(opn);
7773 generate_exception (ctx, EXCP_RI);
7774 return;
7776 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7777 fregnames[fs], fregnames[ft]);
7780 /* ISA extensions (ASEs) */
7781 /* MIPS16 extension to MIPS32 */
7782 /* SmartMIPS extension to MIPS32 */
7784 #if defined(TARGET_MIPS64)
7786 /* MDMX extension to MIPS64 */
7788 #endif
7790 static void decode_opc (CPUState *env, DisasContext *ctx)
7792 int32_t offset;
7793 int rs, rt, rd, sa;
7794 uint32_t op, op1, op2;
7795 int16_t imm;
7797 /* make sure instructions are on a word boundary */
7798 if (ctx->pc & 0x3) {
7799 env->CP0_BadVAddr = ctx->pc;
7800 generate_exception(ctx, EXCP_AdEL);
7801 return;
7804 /* Handle blikely not taken case */
7805 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7806 int l1 = gen_new_label();
7808 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7809 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
7811 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
7813 tcg_gen_movi_i32(r_tmp, ctx->hflags & ~MIPS_HFLAG_BMASK);
7814 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
7815 tcg_temp_free(r_tmp);
7817 gen_goto_tb(ctx, 1, ctx->pc + 4);
7818 gen_set_label(l1);
7820 op = MASK_OP_MAJOR(ctx->opcode);
7821 rs = (ctx->opcode >> 21) & 0x1f;
7822 rt = (ctx->opcode >> 16) & 0x1f;
7823 rd = (ctx->opcode >> 11) & 0x1f;
7824 sa = (ctx->opcode >> 6) & 0x1f;
7825 imm = (int16_t)ctx->opcode;
7826 switch (op) {
7827 case OPC_SPECIAL:
7828 op1 = MASK_SPECIAL(ctx->opcode);
7829 switch (op1) {
7830 case OPC_SLL: /* Arithmetic with immediate */
7831 case OPC_SRL ... OPC_SRA:
7832 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7833 break;
7834 case OPC_MOVZ ... OPC_MOVN:
7835 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7836 case OPC_SLLV: /* Arithmetic */
7837 case OPC_SRLV ... OPC_SRAV:
7838 case OPC_ADD ... OPC_NOR:
7839 case OPC_SLT ... OPC_SLTU:
7840 gen_arith(env, ctx, op1, rd, rs, rt);
7841 break;
7842 case OPC_MULT ... OPC_DIVU:
7843 if (sa) {
7844 check_insn(env, ctx, INSN_VR54XX);
7845 op1 = MASK_MUL_VR54XX(ctx->opcode);
7846 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7847 } else
7848 gen_muldiv(ctx, op1, rs, rt);
7849 break;
7850 case OPC_JR ... OPC_JALR:
7851 gen_compute_branch(ctx, op1, rs, rd, sa);
7852 return;
7853 case OPC_TGE ... OPC_TEQ: /* Traps */
7854 case OPC_TNE:
7855 gen_trap(ctx, op1, rs, rt, -1);
7856 break;
7857 case OPC_MFHI: /* Move from HI/LO */
7858 case OPC_MFLO:
7859 gen_HILO(ctx, op1, rd);
7860 break;
7861 case OPC_MTHI:
7862 case OPC_MTLO: /* Move to HI/LO */
7863 gen_HILO(ctx, op1, rs);
7864 break;
7865 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7866 #ifdef MIPS_STRICT_STANDARD
7867 MIPS_INVAL("PMON / selsl");
7868 generate_exception(ctx, EXCP_RI);
7869 #else
7870 tcg_gen_helper_0_i(do_pmon, sa);
7871 #endif
7872 break;
7873 case OPC_SYSCALL:
7874 generate_exception(ctx, EXCP_SYSCALL);
7875 break;
7876 case OPC_BREAK:
7877 generate_exception(ctx, EXCP_BREAK);
7878 break;
7879 case OPC_SPIM:
7880 #ifdef MIPS_STRICT_STANDARD
7881 MIPS_INVAL("SPIM");
7882 generate_exception(ctx, EXCP_RI);
7883 #else
7884 /* Implemented as RI exception for now. */
7885 MIPS_INVAL("spim (unofficial)");
7886 generate_exception(ctx, EXCP_RI);
7887 #endif
7888 break;
7889 case OPC_SYNC:
7890 /* Treat as NOP. */
7891 break;
7893 case OPC_MOVCI:
7894 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7895 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7896 save_cpu_state(ctx, 1);
7897 check_cp1_enabled(ctx);
7898 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7899 (ctx->opcode >> 16) & 1);
7900 } else {
7901 generate_exception_err(ctx, EXCP_CpU, 1);
7903 break;
7905 #if defined(TARGET_MIPS64)
7906 /* MIPS64 specific opcodes */
7907 case OPC_DSLL:
7908 case OPC_DSRL ... OPC_DSRA:
7909 case OPC_DSLL32:
7910 case OPC_DSRL32 ... OPC_DSRA32:
7911 check_insn(env, ctx, ISA_MIPS3);
7912 check_mips_64(ctx);
7913 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7914 break;
7915 case OPC_DSLLV:
7916 case OPC_DSRLV ... OPC_DSRAV:
7917 case OPC_DADD ... OPC_DSUBU:
7918 check_insn(env, ctx, ISA_MIPS3);
7919 check_mips_64(ctx);
7920 gen_arith(env, ctx, op1, rd, rs, rt);
7921 break;
7922 case OPC_DMULT ... OPC_DDIVU:
7923 check_insn(env, ctx, ISA_MIPS3);
7924 check_mips_64(ctx);
7925 gen_muldiv(ctx, op1, rs, rt);
7926 break;
7927 #endif
7928 default: /* Invalid */
7929 MIPS_INVAL("special");
7930 generate_exception(ctx, EXCP_RI);
7931 break;
7933 break;
7934 case OPC_SPECIAL2:
7935 op1 = MASK_SPECIAL2(ctx->opcode);
7936 switch (op1) {
7937 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7938 case OPC_MSUB ... OPC_MSUBU:
7939 check_insn(env, ctx, ISA_MIPS32);
7940 gen_muldiv(ctx, op1, rs, rt);
7941 break;
7942 case OPC_MUL:
7943 gen_arith(env, ctx, op1, rd, rs, rt);
7944 break;
7945 case OPC_CLZ ... OPC_CLO:
7946 check_insn(env, ctx, ISA_MIPS32);
7947 gen_cl(ctx, op1, rd, rs);
7948 break;
7949 case OPC_SDBBP:
7950 /* XXX: not clear which exception should be raised
7951 * when in debug mode...
7953 check_insn(env, ctx, ISA_MIPS32);
7954 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7955 generate_exception(ctx, EXCP_DBp);
7956 } else {
7957 generate_exception(ctx, EXCP_DBp);
7959 /* Treat as NOP. */
7960 break;
7961 #if defined(TARGET_MIPS64)
7962 case OPC_DCLZ ... OPC_DCLO:
7963 check_insn(env, ctx, ISA_MIPS64);
7964 check_mips_64(ctx);
7965 gen_cl(ctx, op1, rd, rs);
7966 break;
7967 #endif
7968 default: /* Invalid */
7969 MIPS_INVAL("special2");
7970 generate_exception(ctx, EXCP_RI);
7971 break;
7973 break;
7974 case OPC_SPECIAL3:
7975 op1 = MASK_SPECIAL3(ctx->opcode);
7976 switch (op1) {
7977 case OPC_EXT:
7978 case OPC_INS:
7979 check_insn(env, ctx, ISA_MIPS32R2);
7980 gen_bitops(ctx, op1, rt, rs, sa, rd);
7981 break;
7982 case OPC_BSHFL:
7983 check_insn(env, ctx, ISA_MIPS32R2);
7984 op2 = MASK_BSHFL(ctx->opcode);
7986 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7987 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
7989 switch (op2) {
7990 case OPC_WSBH:
7991 gen_load_gpr(t1, rt);
7992 tcg_gen_helper_1_1(do_wsbh, t0, t1);
7993 gen_store_gpr(t0, rd);
7994 break;
7995 case OPC_SEB:
7996 gen_load_gpr(t1, rt);
7997 tcg_gen_ext8s_tl(t0, t1);
7998 gen_store_gpr(t0, rd);
7999 break;
8000 case OPC_SEH:
8001 gen_load_gpr(t1, rt);
8002 tcg_gen_ext16s_tl(t0, t1);
8003 gen_store_gpr(t0, rd);
8004 break;
8005 default: /* Invalid */
8006 MIPS_INVAL("bshfl");
8007 generate_exception(ctx, EXCP_RI);
8008 break;
8010 tcg_temp_free(t0);
8011 tcg_temp_free(t1);
8013 break;
8014 case OPC_RDHWR:
8015 check_insn(env, ctx, ISA_MIPS32R2);
8017 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8019 switch (rd) {
8020 case 0:
8021 save_cpu_state(ctx, 1);
8022 tcg_gen_helper_1_0(do_rdhwr_cpunum, t0);
8023 break;
8024 case 1:
8025 save_cpu_state(ctx, 1);
8026 tcg_gen_helper_1_0(do_rdhwr_synci_step, t0);
8027 break;
8028 case 2:
8029 save_cpu_state(ctx, 1);
8030 tcg_gen_helper_1_0(do_rdhwr_cc, t0);
8031 break;
8032 case 3:
8033 save_cpu_state(ctx, 1);
8034 tcg_gen_helper_1_0(do_rdhwr_ccres, t0);
8035 break;
8036 case 29:
8037 if (env->user_mode_only) {
8038 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
8039 break;
8040 } else {
8041 /* XXX: Some CPUs implement this in hardware.
8042 Not supported yet. */
8044 default: /* Invalid */
8045 MIPS_INVAL("rdhwr");
8046 generate_exception(ctx, EXCP_RI);
8047 break;
8049 gen_store_gpr(t0, rt);
8050 tcg_temp_free(t0);
8052 break;
8053 case OPC_FORK:
8054 check_insn(env, ctx, ASE_MT);
8056 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8057 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
8059 gen_load_gpr(t0, rt);
8060 gen_load_gpr(t1, rs);
8061 tcg_gen_helper_0_2(do_fork, t0, t1);
8062 tcg_temp_free(t0);
8063 tcg_temp_free(t1);
8065 break;
8066 case OPC_YIELD:
8067 check_insn(env, ctx, ASE_MT);
8069 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8071 gen_load_gpr(t0, rs);
8072 tcg_gen_helper_1_1(do_yield, t0, t0);
8073 gen_store_gpr(t0, rd);
8074 tcg_temp_free(t0);
8076 break;
8077 #if defined(TARGET_MIPS64)
8078 case OPC_DEXTM ... OPC_DEXT:
8079 case OPC_DINSM ... OPC_DINS:
8080 check_insn(env, ctx, ISA_MIPS64R2);
8081 check_mips_64(ctx);
8082 gen_bitops(ctx, op1, rt, rs, sa, rd);
8083 break;
8084 case OPC_DBSHFL:
8085 check_insn(env, ctx, ISA_MIPS64R2);
8086 check_mips_64(ctx);
8087 op2 = MASK_DBSHFL(ctx->opcode);
8089 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8090 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
8092 switch (op2) {
8093 case OPC_DSBH:
8094 gen_load_gpr(t1, rt);
8095 tcg_gen_helper_1_1(do_dsbh, t0, t1);
8096 break;
8097 case OPC_DSHD:
8098 gen_load_gpr(t1, rt);
8099 tcg_gen_helper_1_1(do_dshd, t0, t1);
8100 break;
8101 default: /* Invalid */
8102 MIPS_INVAL("dbshfl");
8103 generate_exception(ctx, EXCP_RI);
8104 break;
8106 gen_store_gpr(t0, rd);
8107 tcg_temp_free(t0);
8108 tcg_temp_free(t1);
8110 break;
8111 #endif
8112 default: /* Invalid */
8113 MIPS_INVAL("special3");
8114 generate_exception(ctx, EXCP_RI);
8115 break;
8117 break;
8118 case OPC_REGIMM:
8119 op1 = MASK_REGIMM(ctx->opcode);
8120 switch (op1) {
8121 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
8122 case OPC_BLTZAL ... OPC_BGEZALL:
8123 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
8124 return;
8125 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
8126 case OPC_TNEI:
8127 gen_trap(ctx, op1, rs, -1, imm);
8128 break;
8129 case OPC_SYNCI:
8130 check_insn(env, ctx, ISA_MIPS32R2);
8131 /* Treat as NOP. */
8132 break;
8133 default: /* Invalid */
8134 MIPS_INVAL("regimm");
8135 generate_exception(ctx, EXCP_RI);
8136 break;
8138 break;
8139 case OPC_CP0:
8140 check_cp0_enabled(ctx);
8141 op1 = MASK_CP0(ctx->opcode);
8142 switch (op1) {
8143 case OPC_MFC0:
8144 case OPC_MTC0:
8145 case OPC_MFTR:
8146 case OPC_MTTR:
8147 #if defined(TARGET_MIPS64)
8148 case OPC_DMFC0:
8149 case OPC_DMTC0:
8150 #endif
8151 #ifndef CONFIG_USER_ONLY
8152 if (!env->user_mode_only)
8153 gen_cp0(env, ctx, op1, rt, rd);
8154 #endif /* !CONFIG_USER_ONLY */
8155 break;
8156 case OPC_C0_FIRST ... OPC_C0_LAST:
8157 #ifndef CONFIG_USER_ONLY
8158 if (!env->user_mode_only)
8159 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
8160 #endif /* !CONFIG_USER_ONLY */
8161 break;
8162 case OPC_MFMC0:
8163 #ifndef CONFIG_USER_ONLY
8164 if (!env->user_mode_only) {
8165 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8167 op2 = MASK_MFMC0(ctx->opcode);
8168 switch (op2) {
8169 case OPC_DMT:
8170 check_insn(env, ctx, ASE_MT);
8171 tcg_gen_helper_1_1(do_dmt, t0, t0);
8172 break;
8173 case OPC_EMT:
8174 check_insn(env, ctx, ASE_MT);
8175 tcg_gen_helper_1_1(do_emt, t0, t0);
8176 break;
8177 case OPC_DVPE:
8178 check_insn(env, ctx, ASE_MT);
8179 tcg_gen_helper_1_1(do_dvpe, t0, t0);
8180 break;
8181 case OPC_EVPE:
8182 check_insn(env, ctx, ASE_MT);
8183 tcg_gen_helper_1_1(do_evpe, t0, t0);
8184 break;
8185 case OPC_DI:
8186 check_insn(env, ctx, ISA_MIPS32R2);
8187 save_cpu_state(ctx, 1);
8188 tcg_gen_helper_1_0(do_di, t0);
8189 /* Stop translation as we may have switched the execution mode */
8190 ctx->bstate = BS_STOP;
8191 break;
8192 case OPC_EI:
8193 check_insn(env, ctx, ISA_MIPS32R2);
8194 save_cpu_state(ctx, 1);
8195 tcg_gen_helper_1_0(do_ei, t0);
8196 /* Stop translation as we may have switched the execution mode */
8197 ctx->bstate = BS_STOP;
8198 break;
8199 default: /* Invalid */
8200 MIPS_INVAL("mfmc0");
8201 generate_exception(ctx, EXCP_RI);
8202 break;
8204 gen_store_gpr(t0, rt);
8205 tcg_temp_free(t0);
8207 #endif /* !CONFIG_USER_ONLY */
8208 break;
8209 case OPC_RDPGPR:
8210 check_insn(env, ctx, ISA_MIPS32R2);
8211 gen_load_srsgpr(rt, rd);
8212 break;
8213 case OPC_WRPGPR:
8214 check_insn(env, ctx, ISA_MIPS32R2);
8215 gen_store_srsgpr(rt, rd);
8216 break;
8217 default:
8218 MIPS_INVAL("cp0");
8219 generate_exception(ctx, EXCP_RI);
8220 break;
8222 break;
8223 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
8224 gen_arith_imm(env, ctx, op, rt, rs, imm);
8225 break;
8226 case OPC_J ... OPC_JAL: /* Jump */
8227 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8228 gen_compute_branch(ctx, op, rs, rt, offset);
8229 return;
8230 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8231 case OPC_BEQL ... OPC_BGTZL:
8232 gen_compute_branch(ctx, op, rs, rt, imm << 2);
8233 return;
8234 case OPC_LB ... OPC_LWR: /* Load and stores */
8235 case OPC_SB ... OPC_SW:
8236 case OPC_SWR:
8237 case OPC_LL:
8238 case OPC_SC:
8239 gen_ldst(ctx, op, rt, rs, imm);
8240 break;
8241 case OPC_CACHE:
8242 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
8243 /* Treat as NOP. */
8244 break;
8245 case OPC_PREF:
8246 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8247 /* Treat as NOP. */
8248 break;
8250 /* Floating point (COP1). */
8251 case OPC_LWC1:
8252 case OPC_LDC1:
8253 case OPC_SWC1:
8254 case OPC_SDC1:
8255 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8256 save_cpu_state(ctx, 1);
8257 check_cp1_enabled(ctx);
8258 gen_flt_ldst(ctx, op, rt, rs, imm);
8259 } else {
8260 generate_exception_err(ctx, EXCP_CpU, 1);
8262 break;
8264 case OPC_CP1:
8265 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8266 save_cpu_state(ctx, 1);
8267 check_cp1_enabled(ctx);
8268 op1 = MASK_CP1(ctx->opcode);
8269 switch (op1) {
8270 case OPC_MFHC1:
8271 case OPC_MTHC1:
8272 check_insn(env, ctx, ISA_MIPS32R2);
8273 case OPC_MFC1:
8274 case OPC_CFC1:
8275 case OPC_MTC1:
8276 case OPC_CTC1:
8277 gen_cp1(ctx, op1, rt, rd);
8278 break;
8279 #if defined(TARGET_MIPS64)
8280 case OPC_DMFC1:
8281 case OPC_DMTC1:
8282 check_insn(env, ctx, ISA_MIPS3);
8283 gen_cp1(ctx, op1, rt, rd);
8284 break;
8285 #endif
8286 case OPC_BC1ANY2:
8287 case OPC_BC1ANY4:
8288 check_cop1x(ctx);
8289 check_insn(env, ctx, ASE_MIPS3D);
8290 /* fall through */
8291 case OPC_BC1:
8292 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8293 (rt >> 2) & 0x7, imm << 2);
8294 return;
8295 case OPC_S_FMT:
8296 case OPC_D_FMT:
8297 case OPC_W_FMT:
8298 case OPC_L_FMT:
8299 case OPC_PS_FMT:
8300 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8301 (imm >> 8) & 0x7);
8302 break;
8303 default:
8304 MIPS_INVAL("cp1");
8305 generate_exception (ctx, EXCP_RI);
8306 break;
8308 } else {
8309 generate_exception_err(ctx, EXCP_CpU, 1);
8311 break;
8313 /* COP2. */
8314 case OPC_LWC2:
8315 case OPC_LDC2:
8316 case OPC_SWC2:
8317 case OPC_SDC2:
8318 case OPC_CP2:
8319 /* COP2: Not implemented. */
8320 generate_exception_err(ctx, EXCP_CpU, 2);
8321 break;
8323 case OPC_CP3:
8324 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8325 save_cpu_state(ctx, 1);
8326 check_cp1_enabled(ctx);
8327 op1 = MASK_CP3(ctx->opcode);
8328 switch (op1) {
8329 case OPC_LWXC1:
8330 case OPC_LDXC1:
8331 case OPC_LUXC1:
8332 case OPC_SWXC1:
8333 case OPC_SDXC1:
8334 case OPC_SUXC1:
8335 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8336 break;
8337 case OPC_PREFX:
8338 /* Treat as NOP. */
8339 break;
8340 case OPC_ALNV_PS:
8341 case OPC_MADD_S:
8342 case OPC_MADD_D:
8343 case OPC_MADD_PS:
8344 case OPC_MSUB_S:
8345 case OPC_MSUB_D:
8346 case OPC_MSUB_PS:
8347 case OPC_NMADD_S:
8348 case OPC_NMADD_D:
8349 case OPC_NMADD_PS:
8350 case OPC_NMSUB_S:
8351 case OPC_NMSUB_D:
8352 case OPC_NMSUB_PS:
8353 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8354 break;
8355 default:
8356 MIPS_INVAL("cp3");
8357 generate_exception (ctx, EXCP_RI);
8358 break;
8360 } else {
8361 generate_exception_err(ctx, EXCP_CpU, 1);
8363 break;
8365 #if defined(TARGET_MIPS64)
8366 /* MIPS64 opcodes */
8367 case OPC_LWU:
8368 case OPC_LDL ... OPC_LDR:
8369 case OPC_SDL ... OPC_SDR:
8370 case OPC_LLD:
8371 case OPC_LD:
8372 case OPC_SCD:
8373 case OPC_SD:
8374 check_insn(env, ctx, ISA_MIPS3);
8375 check_mips_64(ctx);
8376 gen_ldst(ctx, op, rt, rs, imm);
8377 break;
8378 case OPC_DADDI ... OPC_DADDIU:
8379 check_insn(env, ctx, ISA_MIPS3);
8380 check_mips_64(ctx);
8381 gen_arith_imm(env, ctx, op, rt, rs, imm);
8382 break;
8383 #endif
8384 case OPC_JALX:
8385 check_insn(env, ctx, ASE_MIPS16);
8386 /* MIPS16: Not implemented. */
8387 case OPC_MDMX:
8388 check_insn(env, ctx, ASE_MDMX);
8389 /* MDMX: Not implemented. */
8390 default: /* Invalid */
8391 MIPS_INVAL("major opcode");
8392 generate_exception(ctx, EXCP_RI);
8393 break;
8395 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8396 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8397 /* Branches completion */
8398 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8399 ctx->bstate = BS_BRANCH;
8400 save_cpu_state(ctx, 0);
8401 /* FIXME: Need to clear can_do_io. */
8402 switch (hflags) {
8403 case MIPS_HFLAG_B:
8404 /* unconditional branch */
8405 MIPS_DEBUG("unconditional branch");
8406 gen_goto_tb(ctx, 0, ctx->btarget);
8407 break;
8408 case MIPS_HFLAG_BL:
8409 /* blikely taken case */
8410 MIPS_DEBUG("blikely branch taken");
8411 gen_goto_tb(ctx, 0, ctx->btarget);
8412 break;
8413 case MIPS_HFLAG_BC:
8414 /* Conditional branch */
8415 MIPS_DEBUG("conditional branch");
8417 int l1 = gen_new_label();
8419 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
8420 gen_goto_tb(ctx, 1, ctx->pc + 4);
8421 gen_set_label(l1);
8422 gen_goto_tb(ctx, 0, ctx->btarget);
8424 break;
8425 case MIPS_HFLAG_BR:
8426 /* unconditional branch to register */
8427 MIPS_DEBUG("branch to register");
8428 tcg_gen_mov_tl(cpu_PC, btarget);
8429 tcg_gen_exit_tb(0);
8430 break;
8431 default:
8432 MIPS_DEBUG("unknown branch");
8433 break;
8438 static inline void
8439 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8440 int search_pc)
8442 DisasContext ctx;
8443 target_ulong pc_start;
8444 uint16_t *gen_opc_end;
8445 int j, lj = -1;
8446 int num_insns;
8447 int max_insns;
8449 if (search_pc && loglevel)
8450 fprintf (logfile, "search pc %d\n", search_pc);
8452 pc_start = tb->pc;
8453 /* Leave some spare opc slots for branch handling. */
8454 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
8455 ctx.pc = pc_start;
8456 ctx.saved_pc = -1;
8457 ctx.tb = tb;
8458 ctx.bstate = BS_NONE;
8459 /* Restore delay slot state from the tb context. */
8460 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8461 restore_cpu_state(env, &ctx);
8462 if (env->user_mode_only)
8463 ctx.mem_idx = MIPS_HFLAG_UM;
8464 else
8465 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8466 num_insns = 0;
8467 max_insns = tb->cflags & CF_COUNT_MASK;
8468 if (max_insns == 0)
8469 max_insns = CF_COUNT_MASK;
8470 #ifdef DEBUG_DISAS
8471 if (loglevel & CPU_LOG_TB_CPU) {
8472 fprintf(logfile, "------------------------------------------------\n");
8473 /* FIXME: This may print out stale hflags from env... */
8474 cpu_dump_state(env, logfile, fprintf, 0);
8476 #endif
8477 #ifdef MIPS_DEBUG_DISAS
8478 if (loglevel & CPU_LOG_TB_IN_ASM)
8479 fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
8480 tb, ctx.mem_idx, ctx.hflags);
8481 #endif
8482 gen_icount_start();
8483 while (ctx.bstate == BS_NONE) {
8484 if (env->nb_breakpoints > 0) {
8485 for(j = 0; j < env->nb_breakpoints; j++) {
8486 if (env->breakpoints[j] == ctx.pc) {
8487 save_cpu_state(&ctx, 1);
8488 ctx.bstate = BS_BRANCH;
8489 tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
8490 /* Include the breakpoint location or the tb won't
8491 * be flushed when it must be. */
8492 ctx.pc += 4;
8493 goto done_generating;
8498 if (search_pc) {
8499 j = gen_opc_ptr - gen_opc_buf;
8500 if (lj < j) {
8501 lj++;
8502 while (lj < j)
8503 gen_opc_instr_start[lj++] = 0;
8505 gen_opc_pc[lj] = ctx.pc;
8506 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8507 gen_opc_instr_start[lj] = 1;
8508 gen_opc_icount[lj] = num_insns;
8510 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8511 gen_io_start();
8512 ctx.opcode = ldl_code(ctx.pc);
8513 decode_opc(env, &ctx);
8514 ctx.pc += 4;
8515 num_insns++;
8517 if (env->singlestep_enabled)
8518 break;
8520 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8521 break;
8523 if (gen_opc_ptr >= gen_opc_end)
8524 break;
8526 if (num_insns >= max_insns)
8527 break;
8528 #if defined (MIPS_SINGLE_STEP)
8529 break;
8530 #endif
8532 if (tb->cflags & CF_LAST_IO)
8533 gen_io_end();
8534 if (env->singlestep_enabled) {
8535 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
8536 tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
8537 } else {
8538 switch (ctx.bstate) {
8539 case BS_STOP:
8540 tcg_gen_helper_0_0(do_interrupt_restart);
8541 gen_goto_tb(&ctx, 0, ctx.pc);
8542 break;
8543 case BS_NONE:
8544 save_cpu_state(&ctx, 0);
8545 gen_goto_tb(&ctx, 0, ctx.pc);
8546 break;
8547 case BS_EXCP:
8548 tcg_gen_helper_0_0(do_interrupt_restart);
8549 tcg_gen_exit_tb(0);
8550 break;
8551 case BS_BRANCH:
8552 default:
8553 break;
8556 done_generating:
8557 gen_icount_end(tb, num_insns);
8558 *gen_opc_ptr = INDEX_op_end;
8559 if (search_pc) {
8560 j = gen_opc_ptr - gen_opc_buf;
8561 lj++;
8562 while (lj <= j)
8563 gen_opc_instr_start[lj++] = 0;
8564 } else {
8565 tb->size = ctx.pc - pc_start;
8566 tb->icount = num_insns;
8568 #ifdef DEBUG_DISAS
8569 #if defined MIPS_DEBUG_DISAS
8570 if (loglevel & CPU_LOG_TB_IN_ASM)
8571 fprintf(logfile, "\n");
8572 #endif
8573 if (loglevel & CPU_LOG_TB_IN_ASM) {
8574 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
8575 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
8576 fprintf(logfile, "\n");
8578 if (loglevel & CPU_LOG_TB_CPU) {
8579 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8581 #endif
8584 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8586 gen_intermediate_code_internal(env, tb, 0);
8589 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8591 gen_intermediate_code_internal(env, tb, 1);
8594 static void fpu_dump_state(CPUState *env, FILE *f,
8595 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8596 int flags)
8598 int i;
8599 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8601 #define printfpr(fp) \
8602 do { \
8603 if (is_fpu64) \
8604 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8605 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8606 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8607 else { \
8608 fpr_t tmp; \
8609 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8610 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8611 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8612 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8613 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8615 } while(0)
8618 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8619 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8620 get_float_exception_flags(&env->active_fpu.fp_status));
8621 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8622 fpu_fprintf(f, "%3s: ", fregnames[i]);
8623 printfpr(&env->active_fpu.fpr[i]);
8626 #undef printfpr
8629 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8630 /* Debug help: The architecture requires 32bit code to maintain proper
8631 sign-extended values on 64bit machines. */
8633 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8635 static void
8636 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8637 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8638 int flags)
8640 int i;
8642 if (!SIGN_EXT_P(env->active_tc.PC))
8643 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8644 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8645 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8646 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8647 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8648 if (!SIGN_EXT_P(env->btarget))
8649 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8651 for (i = 0; i < 32; i++) {
8652 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8653 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8656 if (!SIGN_EXT_P(env->CP0_EPC))
8657 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8658 if (!SIGN_EXT_P(env->CP0_LLAddr))
8659 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
8661 #endif
8663 void cpu_dump_state (CPUState *env, FILE *f,
8664 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8665 int flags)
8667 int i;
8669 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",
8670 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8671 env->hflags, env->btarget, env->bcond);
8672 for (i = 0; i < 32; i++) {
8673 if ((i & 3) == 0)
8674 cpu_fprintf(f, "GPR%02d:", i);
8675 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8676 if ((i & 3) == 3)
8677 cpu_fprintf(f, "\n");
8680 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8681 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8682 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8683 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
8684 if (env->hflags & MIPS_HFLAG_FPU)
8685 fpu_dump_state(env, f, cpu_fprintf, flags);
8686 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8687 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8688 #endif
8691 static void mips_tcg_init(void)
8693 int i;
8694 static int inited;
8696 /* Initialize various static tables. */
8697 if (inited)
8698 return;
8700 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
8701 for (i = 0; i < 32; i++)
8702 cpu_gpr[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8703 offsetof(CPUState, active_tc.gpr[i]),
8704 regnames[i]);
8705 cpu_PC = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8706 offsetof(CPUState, active_tc.PC), "PC");
8707 for (i = 0; i < MIPS_DSP_ACC; i++) {
8708 cpu_HI[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8709 offsetof(CPUState, active_tc.HI[i]),
8710 regnames_HI[i]);
8711 cpu_LO[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8712 offsetof(CPUState, active_tc.LO[i]),
8713 regnames_LO[i]);
8714 cpu_ACX[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8715 offsetof(CPUState, active_tc.ACX[i]),
8716 regnames_ACX[i]);
8718 cpu_dspctrl = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8719 offsetof(CPUState, active_tc.DSPControl),
8720 "DSPControl");
8721 bcond = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8722 offsetof(CPUState, bcond), "bcond");
8723 btarget = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8724 offsetof(CPUState, btarget), "btarget");
8725 for (i = 0; i < 32; i++)
8726 fpu_fpr32[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8727 offsetof(CPUState, active_fpu.fpr[i].w[FP_ENDIAN_IDX]),
8728 fregnames[i]);
8729 for (i = 0; i < 32; i++)
8730 fpu_fpr64[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
8731 offsetof(CPUState, active_fpu.fpr[i]),
8732 fregnames_64[i]);
8733 for (i = 0; i < 32; i++)
8734 fpu_fpr32h[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8735 offsetof(CPUState, active_fpu.fpr[i].w[!FP_ENDIAN_IDX]),
8736 fregnames_h[i]);
8737 fpu_fcr0 = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8738 offsetof(CPUState, active_fpu.fcr0),
8739 "fcr0");
8740 fpu_fcr31 = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8741 offsetof(CPUState, active_fpu.fcr31),
8742 "fcr31");
8744 /* register helpers */
8745 #undef DEF_HELPER
8746 #define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
8747 #include "helper.h"
8749 inited = 1;
8752 #include "translate_init.c"
8754 CPUMIPSState *cpu_mips_init (const char *cpu_model)
8756 CPUMIPSState *env;
8757 const mips_def_t *def;
8759 def = cpu_mips_find_by_name(cpu_model);
8760 if (!def)
8761 return NULL;
8762 env = qemu_mallocz(sizeof(CPUMIPSState));
8763 if (!env)
8764 return NULL;
8765 env->cpu_model = def;
8767 cpu_exec_init(env);
8768 env->cpu_model_str = cpu_model;
8769 mips_tcg_init();
8770 cpu_reset(env);
8771 return env;
8774 void cpu_reset (CPUMIPSState *env)
8776 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8778 tlb_flush(env, 1);
8780 /* Minimal init */
8781 #if defined(CONFIG_USER_ONLY)
8782 env->user_mode_only = 1;
8783 #endif
8784 if (env->user_mode_only) {
8785 env->hflags = MIPS_HFLAG_UM;
8786 } else {
8787 if (env->hflags & MIPS_HFLAG_BMASK) {
8788 /* If the exception was raised from a delay slot,
8789 come back to the jump. */
8790 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8791 } else {
8792 env->CP0_ErrorEPC = env->active_tc.PC;
8794 env->active_tc.PC = (int32_t)0xBFC00000;
8795 env->CP0_Wired = 0;
8796 /* SMP not implemented */
8797 env->CP0_EBase = 0x80000000;
8798 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8799 /* vectored interrupts not implemented, timer on int 7,
8800 no performance counters. */
8801 env->CP0_IntCtl = 0xe0000000;
8803 int i;
8805 for (i = 0; i < 7; i++) {
8806 env->CP0_WatchLo[i] = 0;
8807 env->CP0_WatchHi[i] = 0x80000000;
8809 env->CP0_WatchLo[7] = 0;
8810 env->CP0_WatchHi[7] = 0;
8812 /* Count register increments in debug mode, EJTAG version 1 */
8813 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8814 env->hflags = MIPS_HFLAG_CP0;
8816 env->exception_index = EXCP_NONE;
8817 cpu_mips_register(env, env->cpu_model);
8820 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8821 unsigned long searched_pc, int pc_pos, void *puc)
8823 env->active_tc.PC = gen_opc_pc[pc_pos];
8824 env->hflags &= ~MIPS_HFLAG_BMASK;
8825 env->hflags |= gen_opc_hflags[pc_pos];