target-mips: optimize gen_muldiv()
[qemu/qemu-JZ.git] / target-mips / translate.c
blob1b00be2387e916285b86a89f94cb6d329c86cc27
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 ACX register. */
608 static inline void gen_load_ACX (TCGv t, int reg)
610 tcg_gen_mov_tl(t, cpu_ACX[reg]);
613 static inline void gen_store_ACX (TCGv t, int reg)
615 tcg_gen_mov_tl(cpu_ACX[reg], t);
618 /* Moves to/from shadow registers. */
619 static inline void gen_load_srsgpr (int from, int to)
621 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
623 if (from == 0)
624 tcg_gen_movi_tl(r_tmp1, 0);
625 else {
626 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
628 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
629 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
630 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
631 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
632 tcg_gen_add_i32(r_tmp2, cpu_env, r_tmp2);
634 tcg_gen_ld_tl(r_tmp1, r_tmp2, sizeof(target_ulong) * from);
635 tcg_temp_free(r_tmp2);
637 gen_store_gpr(r_tmp1, to);
638 tcg_temp_free(r_tmp1);
641 static inline void gen_store_srsgpr (int from, int to)
643 if (to != 0) {
644 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
645 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
647 gen_load_gpr(r_tmp1, from);
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_st_tl(r_tmp1, r_tmp2, sizeof(target_ulong) * to);
655 tcg_temp_free(r_tmp1);
656 tcg_temp_free(r_tmp2);
660 /* Floating point register moves. */
661 static inline void gen_load_fpr32 (TCGv t, int reg)
663 tcg_gen_mov_i32(t, fpu_fpr32[reg]);
666 static inline void gen_store_fpr32 (TCGv t, int reg)
668 tcg_gen_mov_i32(fpu_fpr32[reg], t);
671 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv t, int reg)
673 if (ctx->hflags & MIPS_HFLAG_F64)
674 tcg_gen_mov_i64(t, fpu_fpr64[reg]);
675 else {
676 tcg_gen_concat_i32_i64(t, fpu_fpr32[reg & ~1], fpu_fpr32[reg | 1]);
680 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv t, int reg)
682 if (ctx->hflags & MIPS_HFLAG_F64)
683 tcg_gen_mov_i64(fpu_fpr64[reg], t);
684 else {
685 tcg_gen_trunc_i64_i32(fpu_fpr32[reg & ~1], t);
686 tcg_gen_shri_i64(t, t, 32);
687 tcg_gen_trunc_i64_i32(fpu_fpr32[reg | 1], t);
691 static inline void gen_load_fpr32h (TCGv t, int reg)
693 tcg_gen_mov_i32(t, fpu_fpr32h[reg]);
696 static inline void gen_store_fpr32h (TCGv t, int reg)
698 tcg_gen_mov_i32(fpu_fpr32h[reg], t);
701 static inline void get_fp_cond (TCGv t)
703 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
704 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
706 tcg_gen_shri_i32(r_tmp2, fpu_fcr31, 24);
707 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xfe);
708 tcg_gen_shri_i32(r_tmp1, fpu_fcr31, 23);
709 tcg_gen_andi_i32(r_tmp1, r_tmp1, 0x1);
710 tcg_gen_or_i32(t, r_tmp1, r_tmp2);
711 tcg_temp_free(r_tmp1);
712 tcg_temp_free(r_tmp2);
715 typedef void (fcmp_fun32)(uint32_t, uint32_t, int);
716 typedef void (fcmp_fun64)(uint64_t, uint64_t, int);
718 #define FOP_CONDS(fcmp_fun, type, fmt) \
719 static fcmp_fun * fcmp ## type ## _ ## fmt ## _table[16] = { \
720 do_cmp ## type ## _ ## fmt ## _f, \
721 do_cmp ## type ## _ ## fmt ## _un, \
722 do_cmp ## type ## _ ## fmt ## _eq, \
723 do_cmp ## type ## _ ## fmt ## _ueq, \
724 do_cmp ## type ## _ ## fmt ## _olt, \
725 do_cmp ## type ## _ ## fmt ## _ult, \
726 do_cmp ## type ## _ ## fmt ## _ole, \
727 do_cmp ## type ## _ ## fmt ## _ule, \
728 do_cmp ## type ## _ ## fmt ## _sf, \
729 do_cmp ## type ## _ ## fmt ## _ngle, \
730 do_cmp ## type ## _ ## fmt ## _seq, \
731 do_cmp ## type ## _ ## fmt ## _ngl, \
732 do_cmp ## type ## _ ## fmt ## _lt, \
733 do_cmp ## type ## _ ## fmt ## _nge, \
734 do_cmp ## type ## _ ## fmt ## _le, \
735 do_cmp ## type ## _ ## fmt ## _ngt, \
736 }; \
737 static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv a, TCGv b, int cc) \
739 tcg_gen_helper_0_2i(fcmp ## type ## _ ## fmt ## _table[n], a, b, cc); \
742 FOP_CONDS(fcmp_fun64, , d)
743 FOP_CONDS(fcmp_fun64, abs, d)
744 FOP_CONDS(fcmp_fun32, , s)
745 FOP_CONDS(fcmp_fun32, abs, s)
746 FOP_CONDS(fcmp_fun64, , ps)
747 FOP_CONDS(fcmp_fun64, abs, ps)
748 #undef FOP_CONDS
750 /* Tests */
751 #define OP_COND(name, cond) \
752 static inline void glue(gen_op_, name) (TCGv t0, TCGv t1) \
754 int l1 = gen_new_label(); \
755 int l2 = gen_new_label(); \
757 tcg_gen_brcond_tl(cond, t0, t1, l1); \
758 tcg_gen_movi_tl(t0, 0); \
759 tcg_gen_br(l2); \
760 gen_set_label(l1); \
761 tcg_gen_movi_tl(t0, 1); \
762 gen_set_label(l2); \
764 OP_COND(eq, TCG_COND_EQ);
765 OP_COND(ne, TCG_COND_NE);
766 OP_COND(ge, TCG_COND_GE);
767 OP_COND(geu, TCG_COND_GEU);
768 OP_COND(lt, TCG_COND_LT);
769 OP_COND(ltu, TCG_COND_LTU);
770 #undef OP_COND
772 #define OP_CONDI(name, cond) \
773 static inline void glue(gen_op_, name) (TCGv t, target_ulong val) \
775 int l1 = gen_new_label(); \
776 int l2 = gen_new_label(); \
778 tcg_gen_brcondi_tl(cond, t, val, l1); \
779 tcg_gen_movi_tl(t, 0); \
780 tcg_gen_br(l2); \
781 gen_set_label(l1); \
782 tcg_gen_movi_tl(t, 1); \
783 gen_set_label(l2); \
785 OP_CONDI(lti, TCG_COND_LT);
786 OP_CONDI(ltiu, TCG_COND_LTU);
787 #undef OP_CONDI
789 #define OP_CONDZ(name, cond) \
790 static inline void glue(gen_op_, name) (TCGv t) \
792 int l1 = gen_new_label(); \
793 int l2 = gen_new_label(); \
795 tcg_gen_brcondi_tl(cond, t, 0, l1); \
796 tcg_gen_movi_tl(t, 0); \
797 tcg_gen_br(l2); \
798 gen_set_label(l1); \
799 tcg_gen_movi_tl(t, 1); \
800 gen_set_label(l2); \
802 OP_CONDZ(gez, TCG_COND_GE);
803 OP_CONDZ(gtz, TCG_COND_GT);
804 OP_CONDZ(lez, TCG_COND_LE);
805 OP_CONDZ(ltz, TCG_COND_LT);
806 #undef OP_CONDZ
808 static inline void gen_save_pc(target_ulong pc)
810 tcg_gen_movi_tl(cpu_PC, pc);
813 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
815 #if defined MIPS_DEBUG_DISAS
816 if (loglevel & CPU_LOG_TB_IN_ASM) {
817 fprintf(logfile, "hflags %08x saved %08x\n",
818 ctx->hflags, ctx->saved_hflags);
820 #endif
821 if (do_save_pc && ctx->pc != ctx->saved_pc) {
822 gen_save_pc(ctx->pc);
823 ctx->saved_pc = ctx->pc;
825 if (ctx->hflags != ctx->saved_hflags) {
826 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
828 tcg_gen_movi_i32(r_tmp, ctx->hflags);
829 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
830 tcg_temp_free(r_tmp);
831 ctx->saved_hflags = ctx->hflags;
832 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
833 case MIPS_HFLAG_BR:
834 break;
835 case MIPS_HFLAG_BC:
836 case MIPS_HFLAG_BL:
837 case MIPS_HFLAG_B:
838 tcg_gen_movi_tl(btarget, ctx->btarget);
839 break;
844 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
846 ctx->saved_hflags = ctx->hflags;
847 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
848 case MIPS_HFLAG_BR:
849 break;
850 case MIPS_HFLAG_BC:
851 case MIPS_HFLAG_BL:
852 case MIPS_HFLAG_B:
853 ctx->btarget = env->btarget;
854 break;
858 static inline void
859 generate_exception_err (DisasContext *ctx, int excp, int err)
861 save_cpu_state(ctx, 1);
862 tcg_gen_helper_0_ii(do_raise_exception_err, excp, err);
863 tcg_gen_helper_0_0(do_interrupt_restart);
864 tcg_gen_exit_tb(0);
867 static inline void
868 generate_exception (DisasContext *ctx, int excp)
870 save_cpu_state(ctx, 1);
871 tcg_gen_helper_0_i(do_raise_exception, excp);
872 tcg_gen_helper_0_0(do_interrupt_restart);
873 tcg_gen_exit_tb(0);
876 /* Addresses computation */
877 static inline void gen_op_addr_add (DisasContext *ctx, TCGv t0, TCGv t1)
879 tcg_gen_add_tl(t0, t0, t1);
881 #if defined(TARGET_MIPS64)
882 /* For compatibility with 32-bit code, data reference in user mode
883 with Status_UX = 0 should be casted to 32-bit and sign extended.
884 See the MIPS64 PRA manual, section 4.10. */
885 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
886 !(ctx->hflags & MIPS_HFLAG_UX)) {
887 tcg_gen_ext32s_i64(t0, t0);
889 #endif
892 static inline void check_cp0_enabled(DisasContext *ctx)
894 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
895 generate_exception_err(ctx, EXCP_CpU, 1);
898 static inline void check_cp1_enabled(DisasContext *ctx)
900 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
901 generate_exception_err(ctx, EXCP_CpU, 1);
904 /* Verify that the processor is running with COP1X instructions enabled.
905 This is associated with the nabla symbol in the MIPS32 and MIPS64
906 opcode tables. */
908 static inline void check_cop1x(DisasContext *ctx)
910 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
911 generate_exception(ctx, EXCP_RI);
914 /* Verify that the processor is running with 64-bit floating-point
915 operations enabled. */
917 static inline void check_cp1_64bitmode(DisasContext *ctx)
919 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
920 generate_exception(ctx, EXCP_RI);
924 * Verify if floating point register is valid; an operation is not defined
925 * if bit 0 of any register specification is set and the FR bit in the
926 * Status register equals zero, since the register numbers specify an
927 * even-odd pair of adjacent coprocessor general registers. When the FR bit
928 * in the Status register equals one, both even and odd register numbers
929 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
931 * Multiple 64 bit wide registers can be checked by calling
932 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
934 static inline void check_cp1_registers(DisasContext *ctx, int regs)
936 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
937 generate_exception(ctx, EXCP_RI);
940 /* This code generates a "reserved instruction" exception if the
941 CPU does not support the instruction set corresponding to flags. */
942 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
944 if (unlikely(!(env->insn_flags & flags)))
945 generate_exception(ctx, EXCP_RI);
948 /* This code generates a "reserved instruction" exception if 64-bit
949 instructions are not enabled. */
950 static inline void check_mips_64(DisasContext *ctx)
952 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
953 generate_exception(ctx, EXCP_RI);
956 /* load/store instructions. */
957 #define OP_LD(insn,fname) \
958 static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx) \
960 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
962 OP_LD(lb,ld8s);
963 OP_LD(lbu,ld8u);
964 OP_LD(lh,ld16s);
965 OP_LD(lhu,ld16u);
966 OP_LD(lw,ld32s);
967 #if defined(TARGET_MIPS64)
968 OP_LD(lwu,ld32u);
969 OP_LD(ld,ld64);
970 #endif
971 #undef OP_LD
973 #define OP_ST(insn,fname) \
974 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
976 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
978 OP_ST(sb,st8);
979 OP_ST(sh,st16);
980 OP_ST(sw,st32);
981 #if defined(TARGET_MIPS64)
982 OP_ST(sd,st64);
983 #endif
984 #undef OP_ST
986 #define OP_LD_ATOMIC(insn,fname) \
987 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
989 tcg_gen_mov_tl(t1, t0); \
990 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
991 tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
993 OP_LD_ATOMIC(ll,ld32s);
994 #if defined(TARGET_MIPS64)
995 OP_LD_ATOMIC(lld,ld64);
996 #endif
997 #undef OP_LD_ATOMIC
999 #define OP_ST_ATOMIC(insn,fname,almask) \
1000 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
1002 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL); \
1003 int l1 = gen_new_label(); \
1004 int l2 = gen_new_label(); \
1005 int l3 = gen_new_label(); \
1007 tcg_gen_andi_tl(r_tmp, t0, almask); \
1008 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1); \
1009 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
1010 generate_exception(ctx, EXCP_AdES); \
1011 gen_set_label(l1); \
1012 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
1013 tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2); \
1014 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
1015 tcg_gen_movi_tl(t0, 1); \
1016 tcg_gen_br(l3); \
1017 gen_set_label(l2); \
1018 tcg_gen_movi_tl(t0, 0); \
1019 gen_set_label(l3); \
1020 tcg_temp_free(r_tmp); \
1022 OP_ST_ATOMIC(sc,st32,0x3);
1023 #if defined(TARGET_MIPS64)
1024 OP_ST_ATOMIC(scd,st64,0x7);
1025 #endif
1026 #undef OP_ST_ATOMIC
1028 /* Load and store */
1029 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
1030 int base, int16_t offset)
1032 const char *opn = "ldst";
1033 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1034 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1036 if (base == 0) {
1037 tcg_gen_movi_tl(t0, offset);
1038 } else if (offset == 0) {
1039 gen_load_gpr(t0, base);
1040 } else {
1041 gen_load_gpr(t0, base);
1042 tcg_gen_movi_tl(t1, offset);
1043 gen_op_addr_add(ctx, t0, t1);
1045 /* Don't do NOP if destination is zero: we must perform the actual
1046 memory access. */
1047 switch (opc) {
1048 #if defined(TARGET_MIPS64)
1049 case OPC_LWU:
1050 op_ldst_lwu(t0, ctx);
1051 gen_store_gpr(t0, rt);
1052 opn = "lwu";
1053 break;
1054 case OPC_LD:
1055 op_ldst_ld(t0, ctx);
1056 gen_store_gpr(t0, rt);
1057 opn = "ld";
1058 break;
1059 case OPC_LLD:
1060 op_ldst_lld(t0, t1, ctx);
1061 gen_store_gpr(t0, rt);
1062 opn = "lld";
1063 break;
1064 case OPC_SD:
1065 gen_load_gpr(t1, rt);
1066 op_ldst_sd(t0, t1, ctx);
1067 opn = "sd";
1068 break;
1069 case OPC_SCD:
1070 save_cpu_state(ctx, 1);
1071 gen_load_gpr(t1, rt);
1072 op_ldst_scd(t0, t1, ctx);
1073 gen_store_gpr(t0, rt);
1074 opn = "scd";
1075 break;
1076 case OPC_LDL:
1077 save_cpu_state(ctx, 1);
1078 gen_load_gpr(t1, rt);
1079 tcg_gen_helper_1_2i(do_ldl, t1, t0, t1, ctx->mem_idx);
1080 gen_store_gpr(t1, rt);
1081 opn = "ldl";
1082 break;
1083 case OPC_SDL:
1084 save_cpu_state(ctx, 1);
1085 gen_load_gpr(t1, rt);
1086 tcg_gen_helper_0_2i(do_sdl, t0, t1, ctx->mem_idx);
1087 opn = "sdl";
1088 break;
1089 case OPC_LDR:
1090 save_cpu_state(ctx, 1);
1091 gen_load_gpr(t1, rt);
1092 tcg_gen_helper_1_2i(do_ldr, t1, t0, t1, ctx->mem_idx);
1093 gen_store_gpr(t1, rt);
1094 opn = "ldr";
1095 break;
1096 case OPC_SDR:
1097 save_cpu_state(ctx, 1);
1098 gen_load_gpr(t1, rt);
1099 tcg_gen_helper_0_2i(do_sdr, t0, t1, ctx->mem_idx);
1100 opn = "sdr";
1101 break;
1102 #endif
1103 case OPC_LW:
1104 op_ldst_lw(t0, ctx);
1105 gen_store_gpr(t0, rt);
1106 opn = "lw";
1107 break;
1108 case OPC_SW:
1109 gen_load_gpr(t1, rt);
1110 op_ldst_sw(t0, t1, ctx);
1111 opn = "sw";
1112 break;
1113 case OPC_LH:
1114 op_ldst_lh(t0, ctx);
1115 gen_store_gpr(t0, rt);
1116 opn = "lh";
1117 break;
1118 case OPC_SH:
1119 gen_load_gpr(t1, rt);
1120 op_ldst_sh(t0, t1, ctx);
1121 opn = "sh";
1122 break;
1123 case OPC_LHU:
1124 op_ldst_lhu(t0, ctx);
1125 gen_store_gpr(t0, rt);
1126 opn = "lhu";
1127 break;
1128 case OPC_LB:
1129 op_ldst_lb(t0, ctx);
1130 gen_store_gpr(t0, rt);
1131 opn = "lb";
1132 break;
1133 case OPC_SB:
1134 gen_load_gpr(t1, rt);
1135 op_ldst_sb(t0, t1, ctx);
1136 opn = "sb";
1137 break;
1138 case OPC_LBU:
1139 op_ldst_lbu(t0, ctx);
1140 gen_store_gpr(t0, rt);
1141 opn = "lbu";
1142 break;
1143 case OPC_LWL:
1144 save_cpu_state(ctx, 1);
1145 gen_load_gpr(t1, rt);
1146 tcg_gen_helper_1_2i(do_lwl, t1, t0, t1, ctx->mem_idx);
1147 gen_store_gpr(t1, rt);
1148 opn = "lwl";
1149 break;
1150 case OPC_SWL:
1151 save_cpu_state(ctx, 1);
1152 gen_load_gpr(t1, rt);
1153 tcg_gen_helper_0_2i(do_swl, t0, t1, ctx->mem_idx);
1154 opn = "swr";
1155 break;
1156 case OPC_LWR:
1157 save_cpu_state(ctx, 1);
1158 gen_load_gpr(t1, rt);
1159 tcg_gen_helper_1_2i(do_lwr, t1, t0, t1, ctx->mem_idx);
1160 gen_store_gpr(t1, rt);
1161 opn = "lwr";
1162 break;
1163 case OPC_SWR:
1164 save_cpu_state(ctx, 1);
1165 gen_load_gpr(t1, rt);
1166 tcg_gen_helper_0_2i(do_swr, t0, t1, ctx->mem_idx);
1167 opn = "swr";
1168 break;
1169 case OPC_LL:
1170 op_ldst_ll(t0, t1, ctx);
1171 gen_store_gpr(t0, rt);
1172 opn = "ll";
1173 break;
1174 case OPC_SC:
1175 save_cpu_state(ctx, 1);
1176 gen_load_gpr(t1, rt);
1177 op_ldst_sc(t0, t1, ctx);
1178 gen_store_gpr(t0, rt);
1179 opn = "sc";
1180 break;
1181 default:
1182 MIPS_INVAL(opn);
1183 generate_exception(ctx, EXCP_RI);
1184 goto out;
1186 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1187 out:
1188 tcg_temp_free(t0);
1189 tcg_temp_free(t1);
1192 /* Load and store */
1193 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1194 int base, int16_t offset)
1196 const char *opn = "flt_ldst";
1197 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1199 if (base == 0) {
1200 tcg_gen_movi_tl(t0, offset);
1201 } else if (offset == 0) {
1202 gen_load_gpr(t0, base);
1203 } else {
1204 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1206 gen_load_gpr(t0, base);
1207 tcg_gen_movi_tl(t1, offset);
1208 gen_op_addr_add(ctx, t0, t1);
1209 tcg_temp_free(t1);
1211 /* Don't do NOP if destination is zero: we must perform the actual
1212 memory access. */
1213 switch (opc) {
1214 case OPC_LWC1:
1216 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
1218 tcg_gen_qemu_ld32s(fp0, t0, ctx->mem_idx);
1219 gen_store_fpr32(fp0, ft);
1220 tcg_temp_free(fp0);
1222 opn = "lwc1";
1223 break;
1224 case OPC_SWC1:
1226 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
1228 gen_load_fpr32(fp0, ft);
1229 tcg_gen_qemu_st32(fp0, t0, ctx->mem_idx);
1230 tcg_temp_free(fp0);
1232 opn = "swc1";
1233 break;
1234 case OPC_LDC1:
1236 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
1238 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1239 gen_store_fpr64(ctx, fp0, ft);
1240 tcg_temp_free(fp0);
1242 opn = "ldc1";
1243 break;
1244 case OPC_SDC1:
1246 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
1248 gen_load_fpr64(ctx, fp0, ft);
1249 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1250 tcg_temp_free(fp0);
1252 opn = "sdc1";
1253 break;
1254 default:
1255 MIPS_INVAL(opn);
1256 generate_exception(ctx, EXCP_RI);
1257 goto out;
1259 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1260 out:
1261 tcg_temp_free(t0);
1264 /* Arithmetic with immediate operand */
1265 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1266 int rt, int rs, int16_t imm)
1268 target_ulong uimm;
1269 const char *opn = "imm arith";
1270 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1272 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1273 /* If no destination, treat it as a NOP.
1274 For addi, we must generate the overflow exception when needed. */
1275 MIPS_DEBUG("NOP");
1276 goto out;
1278 uimm = (uint16_t)imm;
1279 switch (opc) {
1280 case OPC_ADDI:
1281 case OPC_ADDIU:
1282 #if defined(TARGET_MIPS64)
1283 case OPC_DADDI:
1284 case OPC_DADDIU:
1285 #endif
1286 case OPC_SLTI:
1287 case OPC_SLTIU:
1288 uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1289 /* Fall through. */
1290 case OPC_ANDI:
1291 case OPC_ORI:
1292 case OPC_XORI:
1293 gen_load_gpr(t0, rs);
1294 break;
1295 case OPC_LUI:
1296 tcg_gen_movi_tl(t0, imm << 16);
1297 break;
1298 case OPC_SLL:
1299 case OPC_SRA:
1300 case OPC_SRL:
1301 #if defined(TARGET_MIPS64)
1302 case OPC_DSLL:
1303 case OPC_DSRA:
1304 case OPC_DSRL:
1305 case OPC_DSLL32:
1306 case OPC_DSRA32:
1307 case OPC_DSRL32:
1308 #endif
1309 uimm &= 0x1f;
1310 gen_load_gpr(t0, rs);
1311 break;
1313 switch (opc) {
1314 case OPC_ADDI:
1316 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1317 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1318 int l1 = gen_new_label();
1320 save_cpu_state(ctx, 1);
1321 tcg_gen_ext32s_tl(r_tmp1, t0);
1322 tcg_gen_addi_tl(t0, r_tmp1, uimm);
1324 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
1325 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1326 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1327 tcg_temp_free(r_tmp2);
1328 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1329 /* operands of same sign, result different sign */
1330 generate_exception(ctx, EXCP_OVERFLOW);
1331 gen_set_label(l1);
1332 tcg_temp_free(r_tmp1);
1334 tcg_gen_ext32s_tl(t0, t0);
1336 opn = "addi";
1337 break;
1338 case OPC_ADDIU:
1339 tcg_gen_addi_tl(t0, t0, uimm);
1340 tcg_gen_ext32s_tl(t0, t0);
1341 opn = "addiu";
1342 break;
1343 #if defined(TARGET_MIPS64)
1344 case OPC_DADDI:
1346 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1347 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1348 int l1 = gen_new_label();
1350 save_cpu_state(ctx, 1);
1351 tcg_gen_mov_tl(r_tmp1, t0);
1352 tcg_gen_addi_tl(t0, t0, uimm);
1354 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
1355 tcg_gen_xori_tl(r_tmp2, t0, uimm);
1356 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1357 tcg_temp_free(r_tmp2);
1358 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1359 /* operands of same sign, result different sign */
1360 generate_exception(ctx, EXCP_OVERFLOW);
1361 gen_set_label(l1);
1362 tcg_temp_free(r_tmp1);
1364 opn = "daddi";
1365 break;
1366 case OPC_DADDIU:
1367 tcg_gen_addi_tl(t0, t0, uimm);
1368 opn = "daddiu";
1369 break;
1370 #endif
1371 case OPC_SLTI:
1372 gen_op_lti(t0, uimm);
1373 opn = "slti";
1374 break;
1375 case OPC_SLTIU:
1376 gen_op_ltiu(t0, uimm);
1377 opn = "sltiu";
1378 break;
1379 case OPC_ANDI:
1380 tcg_gen_andi_tl(t0, t0, uimm);
1381 opn = "andi";
1382 break;
1383 case OPC_ORI:
1384 tcg_gen_ori_tl(t0, t0, uimm);
1385 opn = "ori";
1386 break;
1387 case OPC_XORI:
1388 tcg_gen_xori_tl(t0, t0, uimm);
1389 opn = "xori";
1390 break;
1391 case OPC_LUI:
1392 opn = "lui";
1393 break;
1394 case OPC_SLL:
1395 tcg_gen_shli_tl(t0, t0, uimm);
1396 tcg_gen_ext32s_tl(t0, t0);
1397 opn = "sll";
1398 break;
1399 case OPC_SRA:
1400 tcg_gen_ext32s_tl(t0, t0);
1401 tcg_gen_sari_tl(t0, t0, uimm);
1402 opn = "sra";
1403 break;
1404 case OPC_SRL:
1405 switch ((ctx->opcode >> 21) & 0x1f) {
1406 case 0:
1407 if (uimm != 0) {
1408 tcg_gen_ext32u_tl(t0, t0);
1409 tcg_gen_shri_tl(t0, t0, uimm);
1410 } else {
1411 tcg_gen_ext32s_tl(t0, t0);
1413 opn = "srl";
1414 break;
1415 case 1:
1416 /* rotr is decoded as srl on non-R2 CPUs */
1417 if (env->insn_flags & ISA_MIPS32R2) {
1418 if (uimm != 0) {
1419 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1421 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1422 tcg_gen_rotri_i32(r_tmp1, r_tmp1, uimm);
1423 tcg_gen_ext_i32_tl(t0, r_tmp1);
1424 tcg_temp_free(r_tmp1);
1426 opn = "rotr";
1427 } else {
1428 if (uimm != 0) {
1429 tcg_gen_ext32u_tl(t0, t0);
1430 tcg_gen_shri_tl(t0, t0, uimm);
1431 } else {
1432 tcg_gen_ext32s_tl(t0, t0);
1434 opn = "srl";
1436 break;
1437 default:
1438 MIPS_INVAL("invalid srl flag");
1439 generate_exception(ctx, EXCP_RI);
1440 break;
1442 break;
1443 #if defined(TARGET_MIPS64)
1444 case OPC_DSLL:
1445 tcg_gen_shli_tl(t0, t0, uimm);
1446 opn = "dsll";
1447 break;
1448 case OPC_DSRA:
1449 tcg_gen_sari_tl(t0, t0, uimm);
1450 opn = "dsra";
1451 break;
1452 case OPC_DSRL:
1453 switch ((ctx->opcode >> 21) & 0x1f) {
1454 case 0:
1455 tcg_gen_shri_tl(t0, t0, uimm);
1456 opn = "dsrl";
1457 break;
1458 case 1:
1459 /* drotr is decoded as dsrl on non-R2 CPUs */
1460 if (env->insn_flags & ISA_MIPS32R2) {
1461 if (uimm != 0) {
1462 tcg_gen_rotri_tl(t0, t0, uimm);
1464 opn = "drotr";
1465 } else {
1466 tcg_gen_shri_tl(t0, t0, uimm);
1467 opn = "dsrl";
1469 break;
1470 default:
1471 MIPS_INVAL("invalid dsrl flag");
1472 generate_exception(ctx, EXCP_RI);
1473 break;
1475 break;
1476 case OPC_DSLL32:
1477 tcg_gen_shli_tl(t0, t0, uimm + 32);
1478 opn = "dsll32";
1479 break;
1480 case OPC_DSRA32:
1481 tcg_gen_sari_tl(t0, t0, uimm + 32);
1482 opn = "dsra32";
1483 break;
1484 case OPC_DSRL32:
1485 switch ((ctx->opcode >> 21) & 0x1f) {
1486 case 0:
1487 tcg_gen_shri_tl(t0, t0, uimm + 32);
1488 opn = "dsrl32";
1489 break;
1490 case 1:
1491 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1492 if (env->insn_flags & ISA_MIPS32R2) {
1493 tcg_gen_rotri_tl(t0, t0, uimm + 32);
1494 opn = "drotr32";
1495 } else {
1496 tcg_gen_shri_tl(t0, t0, uimm + 32);
1497 opn = "dsrl32";
1499 break;
1500 default:
1501 MIPS_INVAL("invalid dsrl32 flag");
1502 generate_exception(ctx, EXCP_RI);
1503 break;
1505 break;
1506 #endif
1507 default:
1508 MIPS_INVAL(opn);
1509 generate_exception(ctx, EXCP_RI);
1510 goto out;
1512 gen_store_gpr(t0, rt);
1513 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1514 out:
1515 tcg_temp_free(t0);
1518 /* Arithmetic */
1519 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1520 int rd, int rs, int rt)
1522 const char *opn = "arith";
1523 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1524 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1526 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1527 && opc != OPC_DADD && opc != OPC_DSUB) {
1528 /* If no destination, treat it as a NOP.
1529 For add & sub, we must generate the overflow exception when needed. */
1530 MIPS_DEBUG("NOP");
1531 goto out;
1533 gen_load_gpr(t0, rs);
1534 /* Specialcase the conventional move operation. */
1535 if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1536 || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1537 gen_store_gpr(t0, rd);
1538 goto out;
1540 gen_load_gpr(t1, rt);
1541 switch (opc) {
1542 case OPC_ADD:
1544 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1545 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1546 int l1 = gen_new_label();
1548 save_cpu_state(ctx, 1);
1549 tcg_gen_ext32s_tl(r_tmp1, t0);
1550 tcg_gen_ext32s_tl(r_tmp2, t1);
1551 tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
1553 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1554 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1555 tcg_gen_xor_tl(r_tmp2, t0, t1);
1556 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1557 tcg_temp_free(r_tmp2);
1558 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1559 /* operands of same sign, result different sign */
1560 generate_exception(ctx, EXCP_OVERFLOW);
1561 gen_set_label(l1);
1562 tcg_temp_free(r_tmp1);
1564 tcg_gen_ext32s_tl(t0, t0);
1566 opn = "add";
1567 break;
1568 case OPC_ADDU:
1569 tcg_gen_add_tl(t0, t0, t1);
1570 tcg_gen_ext32s_tl(t0, t0);
1571 opn = "addu";
1572 break;
1573 case OPC_SUB:
1575 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1576 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1577 int l1 = gen_new_label();
1579 save_cpu_state(ctx, 1);
1580 tcg_gen_ext32s_tl(r_tmp1, t0);
1581 tcg_gen_ext32s_tl(r_tmp2, t1);
1582 tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
1584 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1585 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1586 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1587 tcg_temp_free(r_tmp2);
1588 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1589 /* operands of different sign, first operand and result different sign */
1590 generate_exception(ctx, EXCP_OVERFLOW);
1591 gen_set_label(l1);
1592 tcg_temp_free(r_tmp1);
1594 tcg_gen_ext32s_tl(t0, t0);
1596 opn = "sub";
1597 break;
1598 case OPC_SUBU:
1599 tcg_gen_sub_tl(t0, t0, t1);
1600 tcg_gen_ext32s_tl(t0, t0);
1601 opn = "subu";
1602 break;
1603 #if defined(TARGET_MIPS64)
1604 case OPC_DADD:
1606 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1607 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1608 int l1 = gen_new_label();
1610 save_cpu_state(ctx, 1);
1611 tcg_gen_mov_tl(r_tmp1, t0);
1612 tcg_gen_add_tl(t0, t0, t1);
1614 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
1615 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
1616 tcg_gen_xor_tl(r_tmp2, t0, t1);
1617 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1618 tcg_temp_free(r_tmp2);
1619 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1620 /* operands of same sign, result different sign */
1621 generate_exception(ctx, EXCP_OVERFLOW);
1622 gen_set_label(l1);
1623 tcg_temp_free(r_tmp1);
1625 opn = "dadd";
1626 break;
1627 case OPC_DADDU:
1628 tcg_gen_add_tl(t0, t0, t1);
1629 opn = "daddu";
1630 break;
1631 case OPC_DSUB:
1633 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_TL);
1634 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_TL);
1635 int l1 = gen_new_label();
1637 save_cpu_state(ctx, 1);
1638 tcg_gen_mov_tl(r_tmp1, t0);
1639 tcg_gen_sub_tl(t0, t0, t1);
1641 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1642 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
1643 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
1644 tcg_temp_free(r_tmp2);
1645 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
1646 /* operands of different sign, first operand and result different sign */
1647 generate_exception(ctx, EXCP_OVERFLOW);
1648 gen_set_label(l1);
1649 tcg_temp_free(r_tmp1);
1651 opn = "dsub";
1652 break;
1653 case OPC_DSUBU:
1654 tcg_gen_sub_tl(t0, t0, t1);
1655 opn = "dsubu";
1656 break;
1657 #endif
1658 case OPC_SLT:
1659 gen_op_lt(t0, t1);
1660 opn = "slt";
1661 break;
1662 case OPC_SLTU:
1663 gen_op_ltu(t0, t1);
1664 opn = "sltu";
1665 break;
1666 case OPC_AND:
1667 tcg_gen_and_tl(t0, t0, t1);
1668 opn = "and";
1669 break;
1670 case OPC_NOR:
1671 tcg_gen_or_tl(t0, t0, t1);
1672 tcg_gen_not_tl(t0, t0);
1673 opn = "nor";
1674 break;
1675 case OPC_OR:
1676 tcg_gen_or_tl(t0, t0, t1);
1677 opn = "or";
1678 break;
1679 case OPC_XOR:
1680 tcg_gen_xor_tl(t0, t0, t1);
1681 opn = "xor";
1682 break;
1683 case OPC_MUL:
1684 tcg_gen_mul_tl(t0, t0, t1);
1685 tcg_gen_ext32s_tl(t0, t0);
1686 opn = "mul";
1687 break;
1688 case OPC_MOVN:
1690 int l1 = gen_new_label();
1692 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1693 gen_store_gpr(t0, rd);
1694 gen_set_label(l1);
1696 opn = "movn";
1697 goto print;
1698 case OPC_MOVZ:
1700 int l1 = gen_new_label();
1702 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
1703 gen_store_gpr(t0, rd);
1704 gen_set_label(l1);
1706 opn = "movz";
1707 goto print;
1708 case OPC_SLLV:
1709 tcg_gen_andi_tl(t0, t0, 0x1f);
1710 tcg_gen_shl_tl(t0, t1, t0);
1711 tcg_gen_ext32s_tl(t0, t0);
1712 opn = "sllv";
1713 break;
1714 case OPC_SRAV:
1715 tcg_gen_ext32s_tl(t1, t1);
1716 tcg_gen_andi_tl(t0, t0, 0x1f);
1717 tcg_gen_sar_tl(t0, t1, t0);
1718 opn = "srav";
1719 break;
1720 case OPC_SRLV:
1721 switch ((ctx->opcode >> 6) & 0x1f) {
1722 case 0:
1723 tcg_gen_ext32u_tl(t1, t1);
1724 tcg_gen_andi_tl(t0, t0, 0x1f);
1725 tcg_gen_shr_tl(t0, t1, t0);
1726 tcg_gen_ext32s_tl(t0, t0);
1727 opn = "srlv";
1728 break;
1729 case 1:
1730 /* rotrv is decoded as srlv on non-R2 CPUs */
1731 if (env->insn_flags & ISA_MIPS32R2) {
1732 int l1 = gen_new_label();
1733 int l2 = gen_new_label();
1735 tcg_gen_andi_tl(t0, t0, 0x1f);
1736 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1738 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1739 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1741 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1742 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1743 tcg_gen_rotr_i32(r_tmp1, r_tmp1, r_tmp2);
1744 tcg_temp_free(r_tmp1);
1745 tcg_temp_free(r_tmp2);
1746 tcg_gen_br(l2);
1748 gen_set_label(l1);
1749 tcg_gen_mov_tl(t0, t1);
1750 gen_set_label(l2);
1751 opn = "rotrv";
1752 } else {
1753 tcg_gen_ext32u_tl(t1, t1);
1754 tcg_gen_andi_tl(t0, t0, 0x1f);
1755 tcg_gen_shr_tl(t0, t1, t0);
1756 tcg_gen_ext32s_tl(t0, t0);
1757 opn = "srlv";
1759 break;
1760 default:
1761 MIPS_INVAL("invalid srlv flag");
1762 generate_exception(ctx, EXCP_RI);
1763 break;
1765 break;
1766 #if defined(TARGET_MIPS64)
1767 case OPC_DSLLV:
1768 tcg_gen_andi_tl(t0, t0, 0x3f);
1769 tcg_gen_shl_tl(t0, t1, t0);
1770 opn = "dsllv";
1771 break;
1772 case OPC_DSRAV:
1773 tcg_gen_andi_tl(t0, t0, 0x3f);
1774 tcg_gen_sar_tl(t0, t1, t0);
1775 opn = "dsrav";
1776 break;
1777 case OPC_DSRLV:
1778 switch ((ctx->opcode >> 6) & 0x1f) {
1779 case 0:
1780 tcg_gen_andi_tl(t0, t0, 0x3f);
1781 tcg_gen_shr_tl(t0, t1, t0);
1782 opn = "dsrlv";
1783 break;
1784 case 1:
1785 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1786 if (env->insn_flags & ISA_MIPS32R2) {
1787 int l1 = gen_new_label();
1788 int l2 = gen_new_label();
1790 tcg_gen_andi_tl(t0, t0, 0x3f);
1791 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
1793 tcg_gen_rotr_tl(t0, t1, t0);
1794 tcg_gen_br(l2);
1796 gen_set_label(l1);
1797 tcg_gen_mov_tl(t0, t1);
1798 gen_set_label(l2);
1799 opn = "drotrv";
1800 } else {
1801 tcg_gen_andi_tl(t0, t0, 0x3f);
1802 tcg_gen_shr_tl(t0, t1, t0);
1803 opn = "dsrlv";
1805 break;
1806 default:
1807 MIPS_INVAL("invalid dsrlv flag");
1808 generate_exception(ctx, EXCP_RI);
1809 break;
1811 break;
1812 #endif
1813 default:
1814 MIPS_INVAL(opn);
1815 generate_exception(ctx, EXCP_RI);
1816 goto out;
1818 gen_store_gpr(t0, rd);
1819 print:
1820 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1821 out:
1822 tcg_temp_free(t0);
1823 tcg_temp_free(t1);
1826 /* Arithmetic on HI/LO registers */
1827 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1829 const char *opn = "hilo";
1830 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1832 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1833 /* Treat as NOP. */
1834 MIPS_DEBUG("NOP");
1835 goto out;
1837 switch (opc) {
1838 case OPC_MFHI:
1839 tcg_gen_mov_tl(t0, cpu_HI[0]);
1840 gen_store_gpr(t0, reg);
1841 opn = "mfhi";
1842 break;
1843 case OPC_MFLO:
1844 tcg_gen_mov_tl(t0, cpu_LO[0]);
1845 gen_store_gpr(t0, reg);
1846 opn = "mflo";
1847 break;
1848 case OPC_MTHI:
1849 gen_load_gpr(t0, reg);
1850 tcg_gen_mov_tl(cpu_HI[0], t0);
1851 opn = "mthi";
1852 break;
1853 case OPC_MTLO:
1854 gen_load_gpr(t0, reg);
1855 tcg_gen_mov_tl(cpu_LO[0], t0);
1856 opn = "mtlo";
1857 break;
1858 default:
1859 MIPS_INVAL(opn);
1860 generate_exception(ctx, EXCP_RI);
1861 goto out;
1863 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1864 out:
1865 tcg_temp_free(t0);
1868 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1869 int rs, int rt)
1871 const char *opn = "mul/div";
1872 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
1873 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
1875 gen_load_gpr(t0, rs);
1876 gen_load_gpr(t1, rt);
1877 switch (opc) {
1878 case OPC_DIV:
1880 int l1 = gen_new_label();
1882 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1884 int l2 = gen_new_label();
1885 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
1886 TCGv r_tmp2 = tcg_temp_local_new(TCG_TYPE_I32);
1887 TCGv r_tmp3 = tcg_temp_local_new(TCG_TYPE_I32);
1889 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1890 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1891 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp1, -1 << 31, l2);
1892 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp2, -1, l2);
1893 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1894 tcg_gen_movi_tl(cpu_HI[0], 0);
1895 tcg_gen_br(l1);
1896 gen_set_label(l2);
1897 tcg_gen_div_i32(r_tmp3, r_tmp1, r_tmp2);
1898 tcg_gen_rem_i32(r_tmp2, r_tmp1, r_tmp2);
1899 tcg_gen_ext_i32_tl(cpu_LO[0], r_tmp3);
1900 tcg_gen_ext_i32_tl(cpu_HI[0], r_tmp2);
1901 tcg_temp_free(r_tmp1);
1902 tcg_temp_free(r_tmp2);
1903 tcg_temp_free(r_tmp3);
1905 gen_set_label(l1);
1907 opn = "div";
1908 break;
1909 case OPC_DIVU:
1911 int l1 = gen_new_label();
1913 tcg_gen_ext32s_tl(t1, t1);
1914 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1916 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
1917 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
1918 TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I32);
1920 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1921 tcg_gen_trunc_tl_i32(r_tmp2, t1);
1922 tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2);
1923 tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2);
1924 tcg_gen_ext_i32_tl(cpu_LO[0], r_tmp3);
1925 tcg_gen_ext_i32_tl(cpu_HI[0], r_tmp1);
1926 tcg_temp_free(r_tmp1);
1927 tcg_temp_free(r_tmp2);
1928 tcg_temp_free(r_tmp3);
1930 gen_set_label(l1);
1932 opn = "divu";
1933 break;
1934 case OPC_MULT:
1936 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
1937 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
1939 tcg_gen_ext_tl_i64(r_tmp1, t0);
1940 tcg_gen_ext_tl_i64(r_tmp2, t1);
1941 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
1942 tcg_temp_free(r_tmp2);
1943 tcg_gen_trunc_i64_tl(t0, r_tmp1);
1944 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
1945 tcg_gen_trunc_i64_tl(t1, r_tmp1);
1946 tcg_temp_free(r_tmp1);
1947 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1948 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1950 opn = "mult";
1951 break;
1952 case OPC_MULTU:
1954 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
1955 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
1957 tcg_gen_ext32u_tl(t0, t0);
1958 tcg_gen_ext32u_tl(t1, t1);
1959 tcg_gen_extu_tl_i64(r_tmp1, t0);
1960 tcg_gen_extu_tl_i64(r_tmp2, t1);
1961 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
1962 tcg_temp_free(r_tmp2);
1963 tcg_gen_trunc_i64_tl(t0, r_tmp1);
1964 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
1965 tcg_gen_trunc_i64_tl(t1, r_tmp1);
1966 tcg_temp_free(r_tmp1);
1967 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1968 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1970 opn = "multu";
1971 break;
1972 #if defined(TARGET_MIPS64)
1973 case OPC_DDIV:
1975 int l1 = gen_new_label();
1977 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1979 int l2 = gen_new_label();
1981 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
1982 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
1983 tcg_gen_mov_tl(cpu_LO[0], t0);
1984 tcg_gen_movi_tl(cpu_HI[0], 0);
1985 tcg_gen_br(l1);
1986 gen_set_label(l2);
1987 tcg_gen_div_i64(cpu_LO[0], t0, t1);
1988 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
1990 gen_set_label(l1);
1992 opn = "ddiv";
1993 break;
1994 case OPC_DDIVU:
1996 int l1 = gen_new_label();
1998 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1999 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2000 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2001 gen_set_label(l1);
2003 opn = "ddivu";
2004 break;
2005 case OPC_DMULT:
2006 tcg_gen_helper_0_2(do_dmult, t0, t1);
2007 opn = "dmult";
2008 break;
2009 case OPC_DMULTU:
2010 tcg_gen_helper_0_2(do_dmultu, t0, t1);
2011 opn = "dmultu";
2012 break;
2013 #endif
2014 case OPC_MADD:
2016 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2017 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2019 tcg_gen_ext_tl_i64(r_tmp1, t0);
2020 tcg_gen_ext_tl_i64(r_tmp2, t1);
2021 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2022 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
2023 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
2024 tcg_temp_free(r_tmp2);
2025 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2026 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2027 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2028 tcg_temp_free(r_tmp1);
2029 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2030 tcg_gen_ext32s_tl(cpu_LO[1], t1);
2032 opn = "madd";
2033 break;
2034 case OPC_MADDU:
2036 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2037 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2039 tcg_gen_ext32u_tl(t0, t0);
2040 tcg_gen_ext32u_tl(t1, t1);
2041 tcg_gen_extu_tl_i64(r_tmp1, t0);
2042 tcg_gen_extu_tl_i64(r_tmp2, t1);
2043 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2044 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
2045 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2);
2046 tcg_temp_free(r_tmp2);
2047 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2048 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2049 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2050 tcg_temp_free(r_tmp1);
2051 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2052 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2054 opn = "maddu";
2055 break;
2056 case OPC_MSUB:
2058 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2059 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2061 tcg_gen_ext_tl_i64(r_tmp1, t0);
2062 tcg_gen_ext_tl_i64(r_tmp2, t1);
2063 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2064 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
2065 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
2066 tcg_temp_free(r_tmp2);
2067 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2068 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2069 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2070 tcg_temp_free(r_tmp1);
2071 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2072 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2074 opn = "msub";
2075 break;
2076 case OPC_MSUBU:
2078 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64);
2079 TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
2081 tcg_gen_ext32u_tl(t0, t0);
2082 tcg_gen_ext32u_tl(t1, t1);
2083 tcg_gen_extu_tl_i64(r_tmp1, t0);
2084 tcg_gen_extu_tl_i64(r_tmp2, t1);
2085 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2);
2086 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]);
2087 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2);
2088 tcg_temp_free(r_tmp2);
2089 tcg_gen_trunc_i64_tl(t0, r_tmp1);
2090 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32);
2091 tcg_gen_trunc_i64_tl(t1, r_tmp1);
2092 tcg_temp_free(r_tmp1);
2093 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2094 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2096 opn = "msubu";
2097 break;
2098 default:
2099 MIPS_INVAL(opn);
2100 generate_exception(ctx, EXCP_RI);
2101 goto out;
2103 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2104 out:
2105 tcg_temp_free(t0);
2106 tcg_temp_free(t1);
2109 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2110 int rd, int rs, int rt)
2112 const char *opn = "mul vr54xx";
2113 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2114 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2116 gen_load_gpr(t0, rs);
2117 gen_load_gpr(t1, rt);
2119 switch (opc) {
2120 case OPC_VR54XX_MULS:
2121 tcg_gen_helper_1_2(do_muls, t0, t0, t1);
2122 opn = "muls";
2123 break;
2124 case OPC_VR54XX_MULSU:
2125 tcg_gen_helper_1_2(do_mulsu, t0, t0, t1);
2126 opn = "mulsu";
2127 break;
2128 case OPC_VR54XX_MACC:
2129 tcg_gen_helper_1_2(do_macc, t0, t0, t1);
2130 opn = "macc";
2131 break;
2132 case OPC_VR54XX_MACCU:
2133 tcg_gen_helper_1_2(do_maccu, t0, t0, t1);
2134 opn = "maccu";
2135 break;
2136 case OPC_VR54XX_MSAC:
2137 tcg_gen_helper_1_2(do_msac, t0, t0, t1);
2138 opn = "msac";
2139 break;
2140 case OPC_VR54XX_MSACU:
2141 tcg_gen_helper_1_2(do_msacu, t0, t0, t1);
2142 opn = "msacu";
2143 break;
2144 case OPC_VR54XX_MULHI:
2145 tcg_gen_helper_1_2(do_mulhi, t0, t0, t1);
2146 opn = "mulhi";
2147 break;
2148 case OPC_VR54XX_MULHIU:
2149 tcg_gen_helper_1_2(do_mulhiu, t0, t0, t1);
2150 opn = "mulhiu";
2151 break;
2152 case OPC_VR54XX_MULSHI:
2153 tcg_gen_helper_1_2(do_mulshi, t0, t0, t1);
2154 opn = "mulshi";
2155 break;
2156 case OPC_VR54XX_MULSHIU:
2157 tcg_gen_helper_1_2(do_mulshiu, t0, t0, t1);
2158 opn = "mulshiu";
2159 break;
2160 case OPC_VR54XX_MACCHI:
2161 tcg_gen_helper_1_2(do_macchi, t0, t0, t1);
2162 opn = "macchi";
2163 break;
2164 case OPC_VR54XX_MACCHIU:
2165 tcg_gen_helper_1_2(do_macchiu, t0, t0, t1);
2166 opn = "macchiu";
2167 break;
2168 case OPC_VR54XX_MSACHI:
2169 tcg_gen_helper_1_2(do_msachi, t0, t0, t1);
2170 opn = "msachi";
2171 break;
2172 case OPC_VR54XX_MSACHIU:
2173 tcg_gen_helper_1_2(do_msachiu, t0, t0, t1);
2174 opn = "msachiu";
2175 break;
2176 default:
2177 MIPS_INVAL("mul vr54xx");
2178 generate_exception(ctx, EXCP_RI);
2179 goto out;
2181 gen_store_gpr(t0, rd);
2182 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2184 out:
2185 tcg_temp_free(t0);
2186 tcg_temp_free(t1);
2189 static void gen_cl (DisasContext *ctx, uint32_t opc,
2190 int rd, int rs)
2192 const char *opn = "CLx";
2193 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2195 if (rd == 0) {
2196 /* Treat as NOP. */
2197 MIPS_DEBUG("NOP");
2198 goto out;
2200 gen_load_gpr(t0, rs);
2201 switch (opc) {
2202 case OPC_CLO:
2203 tcg_gen_helper_1_1(do_clo, t0, t0);
2204 opn = "clo";
2205 break;
2206 case OPC_CLZ:
2207 tcg_gen_helper_1_1(do_clz, t0, t0);
2208 opn = "clz";
2209 break;
2210 #if defined(TARGET_MIPS64)
2211 case OPC_DCLO:
2212 tcg_gen_helper_1_1(do_dclo, t0, t0);
2213 opn = "dclo";
2214 break;
2215 case OPC_DCLZ:
2216 tcg_gen_helper_1_1(do_dclz, t0, t0);
2217 opn = "dclz";
2218 break;
2219 #endif
2220 default:
2221 MIPS_INVAL(opn);
2222 generate_exception(ctx, EXCP_RI);
2223 goto out;
2225 gen_store_gpr(t0, rd);
2226 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2228 out:
2229 tcg_temp_free(t0);
2232 /* Traps */
2233 static void gen_trap (DisasContext *ctx, uint32_t opc,
2234 int rs, int rt, int16_t imm)
2236 int cond;
2237 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2238 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2240 cond = 0;
2241 /* Load needed operands */
2242 switch (opc) {
2243 case OPC_TEQ:
2244 case OPC_TGE:
2245 case OPC_TGEU:
2246 case OPC_TLT:
2247 case OPC_TLTU:
2248 case OPC_TNE:
2249 /* Compare two registers */
2250 if (rs != rt) {
2251 gen_load_gpr(t0, rs);
2252 gen_load_gpr(t1, rt);
2253 cond = 1;
2255 break;
2256 case OPC_TEQI:
2257 case OPC_TGEI:
2258 case OPC_TGEIU:
2259 case OPC_TLTI:
2260 case OPC_TLTIU:
2261 case OPC_TNEI:
2262 /* Compare register to immediate */
2263 if (rs != 0 || imm != 0) {
2264 gen_load_gpr(t0, rs);
2265 tcg_gen_movi_tl(t1, (int32_t)imm);
2266 cond = 1;
2268 break;
2270 if (cond == 0) {
2271 switch (opc) {
2272 case OPC_TEQ: /* rs == rs */
2273 case OPC_TEQI: /* r0 == 0 */
2274 case OPC_TGE: /* rs >= rs */
2275 case OPC_TGEI: /* r0 >= 0 */
2276 case OPC_TGEU: /* rs >= rs unsigned */
2277 case OPC_TGEIU: /* r0 >= 0 unsigned */
2278 /* Always trap */
2279 tcg_gen_movi_tl(t0, 1);
2280 break;
2281 case OPC_TLT: /* rs < rs */
2282 case OPC_TLTI: /* r0 < 0 */
2283 case OPC_TLTU: /* rs < rs unsigned */
2284 case OPC_TLTIU: /* r0 < 0 unsigned */
2285 case OPC_TNE: /* rs != rs */
2286 case OPC_TNEI: /* r0 != 0 */
2287 /* Never trap: treat as NOP. */
2288 goto out;
2289 default:
2290 MIPS_INVAL("trap");
2291 generate_exception(ctx, EXCP_RI);
2292 goto out;
2294 } else {
2295 switch (opc) {
2296 case OPC_TEQ:
2297 case OPC_TEQI:
2298 gen_op_eq(t0, t1);
2299 break;
2300 case OPC_TGE:
2301 case OPC_TGEI:
2302 gen_op_ge(t0, t1);
2303 break;
2304 case OPC_TGEU:
2305 case OPC_TGEIU:
2306 gen_op_geu(t0, t1);
2307 break;
2308 case OPC_TLT:
2309 case OPC_TLTI:
2310 gen_op_lt(t0, t1);
2311 break;
2312 case OPC_TLTU:
2313 case OPC_TLTIU:
2314 gen_op_ltu(t0, t1);
2315 break;
2316 case OPC_TNE:
2317 case OPC_TNEI:
2318 gen_op_ne(t0, t1);
2319 break;
2320 default:
2321 MIPS_INVAL("trap");
2322 generate_exception(ctx, EXCP_RI);
2323 goto out;
2326 save_cpu_state(ctx, 1);
2328 int l1 = gen_new_label();
2330 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2331 tcg_gen_helper_0_i(do_raise_exception, EXCP_TRAP);
2332 gen_set_label(l1);
2334 ctx->bstate = BS_STOP;
2335 out:
2336 tcg_temp_free(t0);
2337 tcg_temp_free(t1);
2340 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2342 TranslationBlock *tb;
2343 tb = ctx->tb;
2344 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2345 tcg_gen_goto_tb(n);
2346 gen_save_pc(dest);
2347 tcg_gen_exit_tb((long)tb + n);
2348 } else {
2349 gen_save_pc(dest);
2350 tcg_gen_exit_tb(0);
2354 /* Branches (before delay slot) */
2355 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2356 int rs, int rt, int32_t offset)
2358 target_ulong btgt = -1;
2359 int blink = 0;
2360 int bcond_compute = 0;
2361 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
2362 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
2364 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2365 #ifdef MIPS_DEBUG_DISAS
2366 if (loglevel & CPU_LOG_TB_IN_ASM) {
2367 fprintf(logfile,
2368 "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
2369 ctx->pc);
2371 #endif
2372 generate_exception(ctx, EXCP_RI);
2373 goto out;
2376 /* Load needed operands */
2377 switch (opc) {
2378 case OPC_BEQ:
2379 case OPC_BEQL:
2380 case OPC_BNE:
2381 case OPC_BNEL:
2382 /* Compare two registers */
2383 if (rs != rt) {
2384 gen_load_gpr(t0, rs);
2385 gen_load_gpr(t1, rt);
2386 bcond_compute = 1;
2388 btgt = ctx->pc + 4 + offset;
2389 break;
2390 case OPC_BGEZ:
2391 case OPC_BGEZAL:
2392 case OPC_BGEZALL:
2393 case OPC_BGEZL:
2394 case OPC_BGTZ:
2395 case OPC_BGTZL:
2396 case OPC_BLEZ:
2397 case OPC_BLEZL:
2398 case OPC_BLTZ:
2399 case OPC_BLTZAL:
2400 case OPC_BLTZALL:
2401 case OPC_BLTZL:
2402 /* Compare to zero */
2403 if (rs != 0) {
2404 gen_load_gpr(t0, rs);
2405 bcond_compute = 1;
2407 btgt = ctx->pc + 4 + offset;
2408 break;
2409 case OPC_J:
2410 case OPC_JAL:
2411 /* Jump to immediate */
2412 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2413 break;
2414 case OPC_JR:
2415 case OPC_JALR:
2416 /* Jump to register */
2417 if (offset != 0 && offset != 16) {
2418 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2419 others are reserved. */
2420 MIPS_INVAL("jump hint");
2421 generate_exception(ctx, EXCP_RI);
2422 goto out;
2424 gen_load_gpr(btarget, rs);
2425 break;
2426 default:
2427 MIPS_INVAL("branch/jump");
2428 generate_exception(ctx, EXCP_RI);
2429 goto out;
2431 if (bcond_compute == 0) {
2432 /* No condition to be computed */
2433 switch (opc) {
2434 case OPC_BEQ: /* rx == rx */
2435 case OPC_BEQL: /* rx == rx likely */
2436 case OPC_BGEZ: /* 0 >= 0 */
2437 case OPC_BGEZL: /* 0 >= 0 likely */
2438 case OPC_BLEZ: /* 0 <= 0 */
2439 case OPC_BLEZL: /* 0 <= 0 likely */
2440 /* Always take */
2441 ctx->hflags |= MIPS_HFLAG_B;
2442 MIPS_DEBUG("balways");
2443 break;
2444 case OPC_BGEZAL: /* 0 >= 0 */
2445 case OPC_BGEZALL: /* 0 >= 0 likely */
2446 /* Always take and link */
2447 blink = 31;
2448 ctx->hflags |= MIPS_HFLAG_B;
2449 MIPS_DEBUG("balways and link");
2450 break;
2451 case OPC_BNE: /* rx != rx */
2452 case OPC_BGTZ: /* 0 > 0 */
2453 case OPC_BLTZ: /* 0 < 0 */
2454 /* Treat as NOP. */
2455 MIPS_DEBUG("bnever (NOP)");
2456 goto out;
2457 case OPC_BLTZAL: /* 0 < 0 */
2458 tcg_gen_movi_tl(t0, ctx->pc + 8);
2459 gen_store_gpr(t0, 31);
2460 MIPS_DEBUG("bnever and link");
2461 goto out;
2462 case OPC_BLTZALL: /* 0 < 0 likely */
2463 tcg_gen_movi_tl(t0, ctx->pc + 8);
2464 gen_store_gpr(t0, 31);
2465 /* Skip the instruction in the delay slot */
2466 MIPS_DEBUG("bnever, link and skip");
2467 ctx->pc += 4;
2468 goto out;
2469 case OPC_BNEL: /* rx != rx likely */
2470 case OPC_BGTZL: /* 0 > 0 likely */
2471 case OPC_BLTZL: /* 0 < 0 likely */
2472 /* Skip the instruction in the delay slot */
2473 MIPS_DEBUG("bnever and skip");
2474 ctx->pc += 4;
2475 goto out;
2476 case OPC_J:
2477 ctx->hflags |= MIPS_HFLAG_B;
2478 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2479 break;
2480 case OPC_JAL:
2481 blink = 31;
2482 ctx->hflags |= MIPS_HFLAG_B;
2483 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2484 break;
2485 case OPC_JR:
2486 ctx->hflags |= MIPS_HFLAG_BR;
2487 MIPS_DEBUG("jr %s", regnames[rs]);
2488 break;
2489 case OPC_JALR:
2490 blink = rt;
2491 ctx->hflags |= MIPS_HFLAG_BR;
2492 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2493 break;
2494 default:
2495 MIPS_INVAL("branch/jump");
2496 generate_exception(ctx, EXCP_RI);
2497 goto out;
2499 } else {
2500 switch (opc) {
2501 case OPC_BEQ:
2502 gen_op_eq(t0, t1);
2503 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2504 regnames[rs], regnames[rt], btgt);
2505 goto not_likely;
2506 case OPC_BEQL:
2507 gen_op_eq(t0, t1);
2508 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2509 regnames[rs], regnames[rt], btgt);
2510 goto likely;
2511 case OPC_BNE:
2512 gen_op_ne(t0, t1);
2513 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2514 regnames[rs], regnames[rt], btgt);
2515 goto not_likely;
2516 case OPC_BNEL:
2517 gen_op_ne(t0, t1);
2518 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2519 regnames[rs], regnames[rt], btgt);
2520 goto likely;
2521 case OPC_BGEZ:
2522 gen_op_gez(t0);
2523 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2524 goto not_likely;
2525 case OPC_BGEZL:
2526 gen_op_gez(t0);
2527 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2528 goto likely;
2529 case OPC_BGEZAL:
2530 gen_op_gez(t0);
2531 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2532 blink = 31;
2533 goto not_likely;
2534 case OPC_BGEZALL:
2535 gen_op_gez(t0);
2536 blink = 31;
2537 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2538 goto likely;
2539 case OPC_BGTZ:
2540 gen_op_gtz(t0);
2541 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2542 goto not_likely;
2543 case OPC_BGTZL:
2544 gen_op_gtz(t0);
2545 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2546 goto likely;
2547 case OPC_BLEZ:
2548 gen_op_lez(t0);
2549 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2550 goto not_likely;
2551 case OPC_BLEZL:
2552 gen_op_lez(t0);
2553 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2554 goto likely;
2555 case OPC_BLTZ:
2556 gen_op_ltz(t0);
2557 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2558 goto not_likely;
2559 case OPC_BLTZL:
2560 gen_op_ltz(t0);
2561 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2562 goto likely;
2563 case OPC_BLTZAL:
2564 gen_op_ltz(t0);
2565 blink = 31;
2566 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2567 not_likely:
2568 ctx->hflags |= MIPS_HFLAG_BC;
2569 tcg_gen_trunc_tl_i32(bcond, t0);
2570 break;
2571 case OPC_BLTZALL:
2572 gen_op_ltz(t0);
2573 blink = 31;
2574 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2575 likely:
2576 ctx->hflags |= MIPS_HFLAG_BL;
2577 tcg_gen_trunc_tl_i32(bcond, t0);
2578 break;
2579 default:
2580 MIPS_INVAL("conditional branch/jump");
2581 generate_exception(ctx, EXCP_RI);
2582 goto out;
2585 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2586 blink, ctx->hflags, btgt);
2588 ctx->btarget = btgt;
2589 if (blink > 0) {
2590 tcg_gen_movi_tl(t0, ctx->pc + 8);
2591 gen_store_gpr(t0, blink);
2594 out:
2595 tcg_temp_free(t0);
2596 tcg_temp_free(t1);
2599 /* special3 bitfield operations */
2600 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2601 int rs, int lsb, int msb)
2603 TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
2604 TCGv t1 = tcg_temp_new(TCG_TYPE_TL);
2605 target_ulong mask;
2607 gen_load_gpr(t1, rs);
2608 switch (opc) {
2609 case OPC_EXT:
2610 if (lsb + msb > 31)
2611 goto fail;
2612 tcg_gen_shri_tl(t0, t1, lsb);
2613 if (msb != 31) {
2614 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2615 } else {
2616 tcg_gen_ext32s_tl(t0, t0);
2618 break;
2619 #if defined(TARGET_MIPS64)
2620 case OPC_DEXTM:
2621 tcg_gen_shri_tl(t0, t1, lsb);
2622 if (msb != 31) {
2623 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2625 break;
2626 case OPC_DEXTU:
2627 tcg_gen_shri_tl(t0, t1, lsb + 32);
2628 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2629 break;
2630 case OPC_DEXT:
2631 tcg_gen_shri_tl(t0, t1, lsb);
2632 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2633 break;
2634 #endif
2635 case OPC_INS:
2636 if (lsb > msb)
2637 goto fail;
2638 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2639 gen_load_gpr(t0, rt);
2640 tcg_gen_andi_tl(t0, t0, ~mask);
2641 tcg_gen_shli_tl(t1, t1, lsb);
2642 tcg_gen_andi_tl(t1, t1, mask);
2643 tcg_gen_or_tl(t0, t0, t1);
2644 tcg_gen_ext32s_tl(t0, t0);
2645 break;
2646 #if defined(TARGET_MIPS64)
2647 case OPC_DINSM:
2648 if (lsb > msb)
2649 goto fail;
2650 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2651 gen_load_gpr(t0, rt);
2652 tcg_gen_andi_tl(t0, t0, ~mask);
2653 tcg_gen_shli_tl(t1, t1, lsb);
2654 tcg_gen_andi_tl(t1, t1, mask);
2655 tcg_gen_or_tl(t0, t0, t1);
2656 break;
2657 case OPC_DINSU:
2658 if (lsb > msb)
2659 goto fail;
2660 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2661 gen_load_gpr(t0, rt);
2662 tcg_gen_andi_tl(t0, t0, ~mask);
2663 tcg_gen_shli_tl(t1, t1, lsb + 32);
2664 tcg_gen_andi_tl(t1, t1, mask);
2665 tcg_gen_or_tl(t0, t0, t1);
2666 break;
2667 case OPC_DINS:
2668 if (lsb > msb)
2669 goto fail;
2670 gen_load_gpr(t0, rt);
2671 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2672 gen_load_gpr(t0, rt);
2673 tcg_gen_andi_tl(t0, t0, ~mask);
2674 tcg_gen_shli_tl(t1, t1, lsb);
2675 tcg_gen_andi_tl(t1, t1, mask);
2676 tcg_gen_or_tl(t0, t0, t1);
2677 break;
2678 #endif
2679 default:
2680 fail:
2681 MIPS_INVAL("bitops");
2682 generate_exception(ctx, EXCP_RI);
2683 tcg_temp_free(t0);
2684 tcg_temp_free(t1);
2685 return;
2687 gen_store_gpr(t0, rt);
2688 tcg_temp_free(t0);
2689 tcg_temp_free(t1);
2692 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2694 TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
2695 TCGv t1 = tcg_temp_new(TCG_TYPE_TL);
2697 gen_load_gpr(t1, rt);
2698 switch (op2) {
2699 case OPC_WSBH:
2700 tcg_gen_shri_tl(t0, t1, 8);
2701 tcg_gen_andi_tl(t0, t0, 0x00FF00FF);
2702 tcg_gen_shli_tl(t1, t1, 8);
2703 tcg_gen_andi_tl(t1, t1, ~0x00FF00FF);
2704 tcg_gen_or_tl(t0, t0, t1);
2705 tcg_gen_ext32s_tl(t0, t0);
2706 break;
2707 case OPC_SEB:
2708 tcg_gen_ext8s_tl(t0, t1);
2709 break;
2710 case OPC_SEH:
2711 tcg_gen_ext16s_tl(t0, t1);
2712 break;
2713 #if defined(TARGET_MIPS64)
2714 case OPC_DSBH:
2715 gen_load_gpr(t1, rt);
2716 tcg_gen_shri_tl(t0, t1, 8);
2717 tcg_gen_andi_tl(t0, t0, 0x00FF00FF00FF00FFULL);
2718 tcg_gen_shli_tl(t1, t1, 8);
2719 tcg_gen_andi_tl(t1, t1, ~0x00FF00FF00FF00FFULL);
2720 tcg_gen_or_tl(t0, t0, t1);
2721 break;
2722 case OPC_DSHD:
2723 gen_load_gpr(t1, rt);
2724 tcg_gen_shri_tl(t0, t1, 16);
2725 tcg_gen_andi_tl(t0, t0, 0x0000FFFF0000FFFFULL);
2726 tcg_gen_shli_tl(t1, t1, 16);
2727 tcg_gen_andi_tl(t1, t1, ~0x0000FFFF0000FFFFULL);
2728 tcg_gen_or_tl(t1, t0, t1);
2729 tcg_gen_shri_tl(t0, t1, 32);
2730 tcg_gen_shli_tl(t1, t1, 32);
2731 tcg_gen_or_tl(t0, t0, t1);
2732 break;
2733 #endif
2734 default:
2735 MIPS_INVAL("bsfhl");
2736 generate_exception(ctx, EXCP_RI);
2737 tcg_temp_free(t0);
2738 tcg_temp_free(t1);
2739 return;
2741 gen_store_gpr(t0, rd);
2742 tcg_temp_free(t0);
2743 tcg_temp_free(t1);
2746 #ifndef CONFIG_USER_ONLY
2747 /* CP0 (MMU and control) */
2748 static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
2750 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
2752 tcg_gen_ld_i32(r_tmp, cpu_env, off);
2753 tcg_gen_ext_i32_tl(t, r_tmp);
2754 tcg_temp_free(r_tmp);
2757 static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
2759 tcg_gen_ld_tl(t, cpu_env, off);
2760 tcg_gen_ext32s_tl(t, t);
2763 static inline void gen_mtc0_store32 (TCGv t, target_ulong off)
2765 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
2767 tcg_gen_trunc_tl_i32(r_tmp, t);
2768 tcg_gen_st_i32(r_tmp, cpu_env, off);
2769 tcg_temp_free(r_tmp);
2772 static inline void gen_mtc0_store64 (TCGv t, target_ulong off)
2774 tcg_gen_ext32s_tl(t, t);
2775 tcg_gen_st_tl(t, cpu_env, off);
2778 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
2780 const char *rn = "invalid";
2782 if (sel != 0)
2783 check_insn(env, ctx, ISA_MIPS32);
2785 switch (reg) {
2786 case 0:
2787 switch (sel) {
2788 case 0:
2789 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
2790 rn = "Index";
2791 break;
2792 case 1:
2793 check_insn(env, ctx, ASE_MT);
2794 tcg_gen_helper_1_0(do_mfc0_mvpcontrol, t0);
2795 rn = "MVPControl";
2796 break;
2797 case 2:
2798 check_insn(env, ctx, ASE_MT);
2799 tcg_gen_helper_1_0(do_mfc0_mvpconf0, t0);
2800 rn = "MVPConf0";
2801 break;
2802 case 3:
2803 check_insn(env, ctx, ASE_MT);
2804 tcg_gen_helper_1_0(do_mfc0_mvpconf1, t0);
2805 rn = "MVPConf1";
2806 break;
2807 default:
2808 goto die;
2810 break;
2811 case 1:
2812 switch (sel) {
2813 case 0:
2814 tcg_gen_helper_1_0(do_mfc0_random, t0);
2815 rn = "Random";
2816 break;
2817 case 1:
2818 check_insn(env, ctx, ASE_MT);
2819 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
2820 rn = "VPEControl";
2821 break;
2822 case 2:
2823 check_insn(env, ctx, ASE_MT);
2824 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
2825 rn = "VPEConf0";
2826 break;
2827 case 3:
2828 check_insn(env, ctx, ASE_MT);
2829 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
2830 rn = "VPEConf1";
2831 break;
2832 case 4:
2833 check_insn(env, ctx, ASE_MT);
2834 gen_mfc0_load64(t0, offsetof(CPUState, CP0_YQMask));
2835 rn = "YQMask";
2836 break;
2837 case 5:
2838 check_insn(env, ctx, ASE_MT);
2839 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPESchedule));
2840 rn = "VPESchedule";
2841 break;
2842 case 6:
2843 check_insn(env, ctx, ASE_MT);
2844 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPEScheFBack));
2845 rn = "VPEScheFBack";
2846 break;
2847 case 7:
2848 check_insn(env, ctx, ASE_MT);
2849 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
2850 rn = "VPEOpt";
2851 break;
2852 default:
2853 goto die;
2855 break;
2856 case 2:
2857 switch (sel) {
2858 case 0:
2859 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2860 tcg_gen_ext32s_tl(t0, t0);
2861 rn = "EntryLo0";
2862 break;
2863 case 1:
2864 check_insn(env, ctx, ASE_MT);
2865 tcg_gen_helper_1_0(do_mfc0_tcstatus, t0);
2866 rn = "TCStatus";
2867 break;
2868 case 2:
2869 check_insn(env, ctx, ASE_MT);
2870 tcg_gen_helper_1_0(do_mfc0_tcbind, t0);
2871 rn = "TCBind";
2872 break;
2873 case 3:
2874 check_insn(env, ctx, ASE_MT);
2875 tcg_gen_helper_1_0(do_mfc0_tcrestart, t0);
2876 rn = "TCRestart";
2877 break;
2878 case 4:
2879 check_insn(env, ctx, ASE_MT);
2880 tcg_gen_helper_1_0(do_mfc0_tchalt, t0);
2881 rn = "TCHalt";
2882 break;
2883 case 5:
2884 check_insn(env, ctx, ASE_MT);
2885 tcg_gen_helper_1_0(do_mfc0_tccontext, t0);
2886 rn = "TCContext";
2887 break;
2888 case 6:
2889 check_insn(env, ctx, ASE_MT);
2890 tcg_gen_helper_1_0(do_mfc0_tcschedule, t0);
2891 rn = "TCSchedule";
2892 break;
2893 case 7:
2894 check_insn(env, ctx, ASE_MT);
2895 tcg_gen_helper_1_0(do_mfc0_tcschefback, t0);
2896 rn = "TCScheFBack";
2897 break;
2898 default:
2899 goto die;
2901 break;
2902 case 3:
2903 switch (sel) {
2904 case 0:
2905 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2906 tcg_gen_ext32s_tl(t0, t0);
2907 rn = "EntryLo1";
2908 break;
2909 default:
2910 goto die;
2912 break;
2913 case 4:
2914 switch (sel) {
2915 case 0:
2916 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
2917 tcg_gen_ext32s_tl(t0, t0);
2918 rn = "Context";
2919 break;
2920 case 1:
2921 // tcg_gen_helper_1_0(do_mfc0_contextconfig, t0); /* SmartMIPS ASE */
2922 rn = "ContextConfig";
2923 // break;
2924 default:
2925 goto die;
2927 break;
2928 case 5:
2929 switch (sel) {
2930 case 0:
2931 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
2932 rn = "PageMask";
2933 break;
2934 case 1:
2935 check_insn(env, ctx, ISA_MIPS32R2);
2936 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
2937 rn = "PageGrain";
2938 break;
2939 default:
2940 goto die;
2942 break;
2943 case 6:
2944 switch (sel) {
2945 case 0:
2946 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
2947 rn = "Wired";
2948 break;
2949 case 1:
2950 check_insn(env, ctx, ISA_MIPS32R2);
2951 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
2952 rn = "SRSConf0";
2953 break;
2954 case 2:
2955 check_insn(env, ctx, ISA_MIPS32R2);
2956 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
2957 rn = "SRSConf1";
2958 break;
2959 case 3:
2960 check_insn(env, ctx, ISA_MIPS32R2);
2961 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
2962 rn = "SRSConf2";
2963 break;
2964 case 4:
2965 check_insn(env, ctx, ISA_MIPS32R2);
2966 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
2967 rn = "SRSConf3";
2968 break;
2969 case 5:
2970 check_insn(env, ctx, ISA_MIPS32R2);
2971 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
2972 rn = "SRSConf4";
2973 break;
2974 default:
2975 goto die;
2977 break;
2978 case 7:
2979 switch (sel) {
2980 case 0:
2981 check_insn(env, ctx, ISA_MIPS32R2);
2982 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
2983 rn = "HWREna";
2984 break;
2985 default:
2986 goto die;
2988 break;
2989 case 8:
2990 switch (sel) {
2991 case 0:
2992 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
2993 tcg_gen_ext32s_tl(t0, t0);
2994 rn = "BadVAddr";
2995 break;
2996 default:
2997 goto die;
2999 break;
3000 case 9:
3001 switch (sel) {
3002 case 0:
3003 /* Mark as an IO operation because we read the time. */
3004 if (use_icount)
3005 gen_io_start();
3006 tcg_gen_helper_1_0(do_mfc0_count, t0);
3007 if (use_icount) {
3008 gen_io_end();
3009 ctx->bstate = BS_STOP;
3011 rn = "Count";
3012 break;
3013 /* 6,7 are implementation dependent */
3014 default:
3015 goto die;
3017 break;
3018 case 10:
3019 switch (sel) {
3020 case 0:
3021 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
3022 tcg_gen_ext32s_tl(t0, t0);
3023 rn = "EntryHi";
3024 break;
3025 default:
3026 goto die;
3028 break;
3029 case 11:
3030 switch (sel) {
3031 case 0:
3032 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
3033 rn = "Compare";
3034 break;
3035 /* 6,7 are implementation dependent */
3036 default:
3037 goto die;
3039 break;
3040 case 12:
3041 switch (sel) {
3042 case 0:
3043 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
3044 rn = "Status";
3045 break;
3046 case 1:
3047 check_insn(env, ctx, ISA_MIPS32R2);
3048 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
3049 rn = "IntCtl";
3050 break;
3051 case 2:
3052 check_insn(env, ctx, ISA_MIPS32R2);
3053 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
3054 rn = "SRSCtl";
3055 break;
3056 case 3:
3057 check_insn(env, ctx, ISA_MIPS32R2);
3058 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
3059 rn = "SRSMap";
3060 break;
3061 default:
3062 goto die;
3064 break;
3065 case 13:
3066 switch (sel) {
3067 case 0:
3068 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
3069 rn = "Cause";
3070 break;
3071 default:
3072 goto die;
3074 break;
3075 case 14:
3076 switch (sel) {
3077 case 0:
3078 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
3079 tcg_gen_ext32s_tl(t0, t0);
3080 rn = "EPC";
3081 break;
3082 default:
3083 goto die;
3085 break;
3086 case 15:
3087 switch (sel) {
3088 case 0:
3089 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
3090 rn = "PRid";
3091 break;
3092 case 1:
3093 check_insn(env, ctx, ISA_MIPS32R2);
3094 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
3095 rn = "EBase";
3096 break;
3097 default:
3098 goto die;
3100 break;
3101 case 16:
3102 switch (sel) {
3103 case 0:
3104 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
3105 rn = "Config";
3106 break;
3107 case 1:
3108 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
3109 rn = "Config1";
3110 break;
3111 case 2:
3112 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
3113 rn = "Config2";
3114 break;
3115 case 3:
3116 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
3117 rn = "Config3";
3118 break;
3119 /* 4,5 are reserved */
3120 /* 6,7 are implementation dependent */
3121 case 6:
3122 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
3123 rn = "Config6";
3124 break;
3125 case 7:
3126 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
3127 rn = "Config7";
3128 break;
3129 default:
3130 goto die;
3132 break;
3133 case 17:
3134 switch (sel) {
3135 case 0:
3136 tcg_gen_helper_1_0(do_mfc0_lladdr, t0);
3137 rn = "LLAddr";
3138 break;
3139 default:
3140 goto die;
3142 break;
3143 case 18:
3144 switch (sel) {
3145 case 0 ... 7:
3146 tcg_gen_helper_1_i(do_mfc0_watchlo, t0, sel);
3147 rn = "WatchLo";
3148 break;
3149 default:
3150 goto die;
3152 break;
3153 case 19:
3154 switch (sel) {
3155 case 0 ...7:
3156 tcg_gen_helper_1_i(do_mfc0_watchhi, t0, sel);
3157 rn = "WatchHi";
3158 break;
3159 default:
3160 goto die;
3162 break;
3163 case 20:
3164 switch (sel) {
3165 case 0:
3166 #if defined(TARGET_MIPS64)
3167 check_insn(env, ctx, ISA_MIPS3);
3168 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
3169 tcg_gen_ext32s_tl(t0, t0);
3170 rn = "XContext";
3171 break;
3172 #endif
3173 default:
3174 goto die;
3176 break;
3177 case 21:
3178 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3179 switch (sel) {
3180 case 0:
3181 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
3182 rn = "Framemask";
3183 break;
3184 default:
3185 goto die;
3187 break;
3188 case 22:
3189 /* ignored */
3190 rn = "'Diagnostic"; /* implementation dependent */
3191 break;
3192 case 23:
3193 switch (sel) {
3194 case 0:
3195 tcg_gen_helper_1_0(do_mfc0_debug, t0); /* EJTAG support */
3196 rn = "Debug";
3197 break;
3198 case 1:
3199 // tcg_gen_helper_1_0(do_mfc0_tracecontrol, t0); /* PDtrace support */
3200 rn = "TraceControl";
3201 // break;
3202 case 2:
3203 // tcg_gen_helper_1_0(do_mfc0_tracecontrol2, t0); /* PDtrace support */
3204 rn = "TraceControl2";
3205 // break;
3206 case 3:
3207 // tcg_gen_helper_1_0(do_mfc0_usertracedata, t0); /* PDtrace support */
3208 rn = "UserTraceData";
3209 // break;
3210 case 4:
3211 // tcg_gen_helper_1_0(do_mfc0_tracebpc, t0); /* PDtrace support */
3212 rn = "TraceBPC";
3213 // break;
3214 default:
3215 goto die;
3217 break;
3218 case 24:
3219 switch (sel) {
3220 case 0:
3221 /* EJTAG support */
3222 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
3223 tcg_gen_ext32s_tl(t0, t0);
3224 rn = "DEPC";
3225 break;
3226 default:
3227 goto die;
3229 break;
3230 case 25:
3231 switch (sel) {
3232 case 0:
3233 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
3234 rn = "Performance0";
3235 break;
3236 case 1:
3237 // tcg_gen_helper_1_0(do_mfc0_performance1, t0);
3238 rn = "Performance1";
3239 // break;
3240 case 2:
3241 // tcg_gen_helper_1_0(do_mfc0_performance2, t0);
3242 rn = "Performance2";
3243 // break;
3244 case 3:
3245 // tcg_gen_helper_1_0(do_mfc0_performance3, t0);
3246 rn = "Performance3";
3247 // break;
3248 case 4:
3249 // tcg_gen_helper_1_0(do_mfc0_performance4, t0);
3250 rn = "Performance4";
3251 // break;
3252 case 5:
3253 // tcg_gen_helper_1_0(do_mfc0_performance5, t0);
3254 rn = "Performance5";
3255 // break;
3256 case 6:
3257 // tcg_gen_helper_1_0(do_mfc0_performance6, t0);
3258 rn = "Performance6";
3259 // break;
3260 case 7:
3261 // tcg_gen_helper_1_0(do_mfc0_performance7, t0);
3262 rn = "Performance7";
3263 // break;
3264 default:
3265 goto die;
3267 break;
3268 case 26:
3269 rn = "ECC";
3270 break;
3271 case 27:
3272 switch (sel) {
3273 /* ignored */
3274 case 0 ... 3:
3275 rn = "CacheErr";
3276 break;
3277 default:
3278 goto die;
3280 break;
3281 case 28:
3282 switch (sel) {
3283 case 0:
3284 case 2:
3285 case 4:
3286 case 6:
3287 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
3288 rn = "TagLo";
3289 break;
3290 case 1:
3291 case 3:
3292 case 5:
3293 case 7:
3294 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
3295 rn = "DataLo";
3296 break;
3297 default:
3298 goto die;
3300 break;
3301 case 29:
3302 switch (sel) {
3303 case 0:
3304 case 2:
3305 case 4:
3306 case 6:
3307 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
3308 rn = "TagHi";
3309 break;
3310 case 1:
3311 case 3:
3312 case 5:
3313 case 7:
3314 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
3315 rn = "DataHi";
3316 break;
3317 default:
3318 goto die;
3320 break;
3321 case 30:
3322 switch (sel) {
3323 case 0:
3324 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3325 tcg_gen_ext32s_tl(t0, t0);
3326 rn = "ErrorEPC";
3327 break;
3328 default:
3329 goto die;
3331 break;
3332 case 31:
3333 switch (sel) {
3334 case 0:
3335 /* EJTAG support */
3336 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
3337 rn = "DESAVE";
3338 break;
3339 default:
3340 goto die;
3342 break;
3343 default:
3344 goto die;
3346 #if defined MIPS_DEBUG_DISAS
3347 if (loglevel & CPU_LOG_TB_IN_ASM) {
3348 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3349 rn, reg, sel);
3351 #endif
3352 return;
3354 die:
3355 #if defined MIPS_DEBUG_DISAS
3356 if (loglevel & CPU_LOG_TB_IN_ASM) {
3357 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3358 rn, reg, sel);
3360 #endif
3361 generate_exception(ctx, EXCP_RI);
3364 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
3366 const char *rn = "invalid";
3368 if (sel != 0)
3369 check_insn(env, ctx, ISA_MIPS32);
3371 if (use_icount)
3372 gen_io_start();
3374 switch (reg) {
3375 case 0:
3376 switch (sel) {
3377 case 0:
3378 tcg_gen_helper_0_1(do_mtc0_index, t0);
3379 rn = "Index";
3380 break;
3381 case 1:
3382 check_insn(env, ctx, ASE_MT);
3383 tcg_gen_helper_0_1(do_mtc0_mvpcontrol, t0);
3384 rn = "MVPControl";
3385 break;
3386 case 2:
3387 check_insn(env, ctx, ASE_MT);
3388 /* ignored */
3389 rn = "MVPConf0";
3390 break;
3391 case 3:
3392 check_insn(env, ctx, ASE_MT);
3393 /* ignored */
3394 rn = "MVPConf1";
3395 break;
3396 default:
3397 goto die;
3399 break;
3400 case 1:
3401 switch (sel) {
3402 case 0:
3403 /* ignored */
3404 rn = "Random";
3405 break;
3406 case 1:
3407 check_insn(env, ctx, ASE_MT);
3408 tcg_gen_helper_0_1(do_mtc0_vpecontrol, t0);
3409 rn = "VPEControl";
3410 break;
3411 case 2:
3412 check_insn(env, ctx, ASE_MT);
3413 tcg_gen_helper_0_1(do_mtc0_vpeconf0, t0);
3414 rn = "VPEConf0";
3415 break;
3416 case 3:
3417 check_insn(env, ctx, ASE_MT);
3418 tcg_gen_helper_0_1(do_mtc0_vpeconf1, t0);
3419 rn = "VPEConf1";
3420 break;
3421 case 4:
3422 check_insn(env, ctx, ASE_MT);
3423 tcg_gen_helper_0_1(do_mtc0_yqmask, t0);
3424 rn = "YQMask";
3425 break;
3426 case 5:
3427 check_insn(env, ctx, ASE_MT);
3428 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule));
3429 rn = "VPESchedule";
3430 break;
3431 case 6:
3432 check_insn(env, ctx, ASE_MT);
3433 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack));
3434 rn = "VPEScheFBack";
3435 break;
3436 case 7:
3437 check_insn(env, ctx, ASE_MT);
3438 tcg_gen_helper_0_1(do_mtc0_vpeopt, t0);
3439 rn = "VPEOpt";
3440 break;
3441 default:
3442 goto die;
3444 break;
3445 case 2:
3446 switch (sel) {
3447 case 0:
3448 tcg_gen_helper_0_1(do_mtc0_entrylo0, t0);
3449 rn = "EntryLo0";
3450 break;
3451 case 1:
3452 check_insn(env, ctx, ASE_MT);
3453 tcg_gen_helper_0_1(do_mtc0_tcstatus, t0);
3454 rn = "TCStatus";
3455 break;
3456 case 2:
3457 check_insn(env, ctx, ASE_MT);
3458 tcg_gen_helper_0_1(do_mtc0_tcbind, t0);
3459 rn = "TCBind";
3460 break;
3461 case 3:
3462 check_insn(env, ctx, ASE_MT);
3463 tcg_gen_helper_0_1(do_mtc0_tcrestart, t0);
3464 rn = "TCRestart";
3465 break;
3466 case 4:
3467 check_insn(env, ctx, ASE_MT);
3468 tcg_gen_helper_0_1(do_mtc0_tchalt, t0);
3469 rn = "TCHalt";
3470 break;
3471 case 5:
3472 check_insn(env, ctx, ASE_MT);
3473 tcg_gen_helper_0_1(do_mtc0_tccontext, t0);
3474 rn = "TCContext";
3475 break;
3476 case 6:
3477 check_insn(env, ctx, ASE_MT);
3478 tcg_gen_helper_0_1(do_mtc0_tcschedule, t0);
3479 rn = "TCSchedule";
3480 break;
3481 case 7:
3482 check_insn(env, ctx, ASE_MT);
3483 tcg_gen_helper_0_1(do_mtc0_tcschefback, t0);
3484 rn = "TCScheFBack";
3485 break;
3486 default:
3487 goto die;
3489 break;
3490 case 3:
3491 switch (sel) {
3492 case 0:
3493 tcg_gen_helper_0_1(do_mtc0_entrylo1, t0);
3494 rn = "EntryLo1";
3495 break;
3496 default:
3497 goto die;
3499 break;
3500 case 4:
3501 switch (sel) {
3502 case 0:
3503 tcg_gen_helper_0_1(do_mtc0_context, t0);
3504 rn = "Context";
3505 break;
3506 case 1:
3507 // tcg_gen_helper_0_1(do_mtc0_contextconfig, t0); /* SmartMIPS ASE */
3508 rn = "ContextConfig";
3509 // break;
3510 default:
3511 goto die;
3513 break;
3514 case 5:
3515 switch (sel) {
3516 case 0:
3517 tcg_gen_helper_0_1(do_mtc0_pagemask, t0);
3518 rn = "PageMask";
3519 break;
3520 case 1:
3521 check_insn(env, ctx, ISA_MIPS32R2);
3522 tcg_gen_helper_0_1(do_mtc0_pagegrain, t0);
3523 rn = "PageGrain";
3524 break;
3525 default:
3526 goto die;
3528 break;
3529 case 6:
3530 switch (sel) {
3531 case 0:
3532 tcg_gen_helper_0_1(do_mtc0_wired, t0);
3533 rn = "Wired";
3534 break;
3535 case 1:
3536 check_insn(env, ctx, ISA_MIPS32R2);
3537 tcg_gen_helper_0_1(do_mtc0_srsconf0, t0);
3538 rn = "SRSConf0";
3539 break;
3540 case 2:
3541 check_insn(env, ctx, ISA_MIPS32R2);
3542 tcg_gen_helper_0_1(do_mtc0_srsconf1, t0);
3543 rn = "SRSConf1";
3544 break;
3545 case 3:
3546 check_insn(env, ctx, ISA_MIPS32R2);
3547 tcg_gen_helper_0_1(do_mtc0_srsconf2, t0);
3548 rn = "SRSConf2";
3549 break;
3550 case 4:
3551 check_insn(env, ctx, ISA_MIPS32R2);
3552 tcg_gen_helper_0_1(do_mtc0_srsconf3, t0);
3553 rn = "SRSConf3";
3554 break;
3555 case 5:
3556 check_insn(env, ctx, ISA_MIPS32R2);
3557 tcg_gen_helper_0_1(do_mtc0_srsconf4, t0);
3558 rn = "SRSConf4";
3559 break;
3560 default:
3561 goto die;
3563 break;
3564 case 7:
3565 switch (sel) {
3566 case 0:
3567 check_insn(env, ctx, ISA_MIPS32R2);
3568 tcg_gen_helper_0_1(do_mtc0_hwrena, t0);
3569 rn = "HWREna";
3570 break;
3571 default:
3572 goto die;
3574 break;
3575 case 8:
3576 /* ignored */
3577 rn = "BadVAddr";
3578 break;
3579 case 9:
3580 switch (sel) {
3581 case 0:
3582 tcg_gen_helper_0_1(do_mtc0_count, t0);
3583 rn = "Count";
3584 break;
3585 /* 6,7 are implementation dependent */
3586 default:
3587 goto die;
3589 /* Stop translation as we may have switched the execution mode */
3590 ctx->bstate = BS_STOP;
3591 break;
3592 case 10:
3593 switch (sel) {
3594 case 0:
3595 tcg_gen_helper_0_1(do_mtc0_entryhi, t0);
3596 rn = "EntryHi";
3597 break;
3598 default:
3599 goto die;
3601 break;
3602 case 11:
3603 switch (sel) {
3604 case 0:
3605 tcg_gen_helper_0_1(do_mtc0_compare, t0);
3606 rn = "Compare";
3607 break;
3608 /* 6,7 are implementation dependent */
3609 default:
3610 goto die;
3612 /* Stop translation as we may have switched the execution mode */
3613 ctx->bstate = BS_STOP;
3614 break;
3615 case 12:
3616 switch (sel) {
3617 case 0:
3618 tcg_gen_helper_0_1(do_mtc0_status, t0);
3619 /* BS_STOP isn't good enough here, hflags may have changed. */
3620 gen_save_pc(ctx->pc + 4);
3621 ctx->bstate = BS_EXCP;
3622 rn = "Status";
3623 break;
3624 case 1:
3625 check_insn(env, ctx, ISA_MIPS32R2);
3626 tcg_gen_helper_0_1(do_mtc0_intctl, t0);
3627 /* Stop translation as we may have switched the execution mode */
3628 ctx->bstate = BS_STOP;
3629 rn = "IntCtl";
3630 break;
3631 case 2:
3632 check_insn(env, ctx, ISA_MIPS32R2);
3633 tcg_gen_helper_0_1(do_mtc0_srsctl, t0);
3634 /* Stop translation as we may have switched the execution mode */
3635 ctx->bstate = BS_STOP;
3636 rn = "SRSCtl";
3637 break;
3638 case 3:
3639 check_insn(env, ctx, ISA_MIPS32R2);
3640 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
3641 /* Stop translation as we may have switched the execution mode */
3642 ctx->bstate = BS_STOP;
3643 rn = "SRSMap";
3644 break;
3645 default:
3646 goto die;
3648 break;
3649 case 13:
3650 switch (sel) {
3651 case 0:
3652 tcg_gen_helper_0_1(do_mtc0_cause, t0);
3653 rn = "Cause";
3654 break;
3655 default:
3656 goto die;
3658 /* Stop translation as we may have switched the execution mode */
3659 ctx->bstate = BS_STOP;
3660 break;
3661 case 14:
3662 switch (sel) {
3663 case 0:
3664 gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC));
3665 rn = "EPC";
3666 break;
3667 default:
3668 goto die;
3670 break;
3671 case 15:
3672 switch (sel) {
3673 case 0:
3674 /* ignored */
3675 rn = "PRid";
3676 break;
3677 case 1:
3678 check_insn(env, ctx, ISA_MIPS32R2);
3679 tcg_gen_helper_0_1(do_mtc0_ebase, t0);
3680 rn = "EBase";
3681 break;
3682 default:
3683 goto die;
3685 break;
3686 case 16:
3687 switch (sel) {
3688 case 0:
3689 tcg_gen_helper_0_1(do_mtc0_config0, t0);
3690 rn = "Config";
3691 /* Stop translation as we may have switched the execution mode */
3692 ctx->bstate = BS_STOP;
3693 break;
3694 case 1:
3695 /* ignored, read only */
3696 rn = "Config1";
3697 break;
3698 case 2:
3699 tcg_gen_helper_0_1(do_mtc0_config2, t0);
3700 rn = "Config2";
3701 /* Stop translation as we may have switched the execution mode */
3702 ctx->bstate = BS_STOP;
3703 break;
3704 case 3:
3705 /* ignored, read only */
3706 rn = "Config3";
3707 break;
3708 /* 4,5 are reserved */
3709 /* 6,7 are implementation dependent */
3710 case 6:
3711 /* ignored */
3712 rn = "Config6";
3713 break;
3714 case 7:
3715 /* ignored */
3716 rn = "Config7";
3717 break;
3718 default:
3719 rn = "Invalid config selector";
3720 goto die;
3722 break;
3723 case 17:
3724 switch (sel) {
3725 case 0:
3726 /* ignored */
3727 rn = "LLAddr";
3728 break;
3729 default:
3730 goto die;
3732 break;
3733 case 18:
3734 switch (sel) {
3735 case 0 ... 7:
3736 tcg_gen_helper_0_1i(do_mtc0_watchlo, t0, sel);
3737 rn = "WatchLo";
3738 break;
3739 default:
3740 goto die;
3742 break;
3743 case 19:
3744 switch (sel) {
3745 case 0 ... 7:
3746 tcg_gen_helper_0_1i(do_mtc0_watchhi, t0, sel);
3747 rn = "WatchHi";
3748 break;
3749 default:
3750 goto die;
3752 break;
3753 case 20:
3754 switch (sel) {
3755 case 0:
3756 #if defined(TARGET_MIPS64)
3757 check_insn(env, ctx, ISA_MIPS3);
3758 tcg_gen_helper_0_1(do_mtc0_xcontext, t0);
3759 rn = "XContext";
3760 break;
3761 #endif
3762 default:
3763 goto die;
3765 break;
3766 case 21:
3767 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3768 switch (sel) {
3769 case 0:
3770 tcg_gen_helper_0_1(do_mtc0_framemask, t0);
3771 rn = "Framemask";
3772 break;
3773 default:
3774 goto die;
3776 break;
3777 case 22:
3778 /* ignored */
3779 rn = "Diagnostic"; /* implementation dependent */
3780 break;
3781 case 23:
3782 switch (sel) {
3783 case 0:
3784 tcg_gen_helper_0_1(do_mtc0_debug, t0); /* EJTAG support */
3785 /* BS_STOP isn't good enough here, hflags may have changed. */
3786 gen_save_pc(ctx->pc + 4);
3787 ctx->bstate = BS_EXCP;
3788 rn = "Debug";
3789 break;
3790 case 1:
3791 // tcg_gen_helper_0_1(do_mtc0_tracecontrol, t0); /* PDtrace support */
3792 rn = "TraceControl";
3793 /* Stop translation as we may have switched the execution mode */
3794 ctx->bstate = BS_STOP;
3795 // break;
3796 case 2:
3797 // tcg_gen_helper_0_1(do_mtc0_tracecontrol2, t0); /* PDtrace support */
3798 rn = "TraceControl2";
3799 /* Stop translation as we may have switched the execution mode */
3800 ctx->bstate = BS_STOP;
3801 // break;
3802 case 3:
3803 /* Stop translation as we may have switched the execution mode */
3804 ctx->bstate = BS_STOP;
3805 // tcg_gen_helper_0_1(do_mtc0_usertracedata, t0); /* PDtrace support */
3806 rn = "UserTraceData";
3807 /* Stop translation as we may have switched the execution mode */
3808 ctx->bstate = BS_STOP;
3809 // break;
3810 case 4:
3811 // tcg_gen_helper_0_1(do_mtc0_tracebpc, t0); /* PDtrace support */
3812 /* Stop translation as we may have switched the execution mode */
3813 ctx->bstate = BS_STOP;
3814 rn = "TraceBPC";
3815 // break;
3816 default:
3817 goto die;
3819 break;
3820 case 24:
3821 switch (sel) {
3822 case 0:
3823 /* EJTAG support */
3824 gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC));
3825 rn = "DEPC";
3826 break;
3827 default:
3828 goto die;
3830 break;
3831 case 25:
3832 switch (sel) {
3833 case 0:
3834 tcg_gen_helper_0_1(do_mtc0_performance0, t0);
3835 rn = "Performance0";
3836 break;
3837 case 1:
3838 // tcg_gen_helper_0_1(do_mtc0_performance1, t0);
3839 rn = "Performance1";
3840 // break;
3841 case 2:
3842 // tcg_gen_helper_0_1(do_mtc0_performance2, t0);
3843 rn = "Performance2";
3844 // break;
3845 case 3:
3846 // tcg_gen_helper_0_1(do_mtc0_performance3, t0);
3847 rn = "Performance3";
3848 // break;
3849 case 4:
3850 // tcg_gen_helper_0_1(do_mtc0_performance4, t0);
3851 rn = "Performance4";
3852 // break;
3853 case 5:
3854 // tcg_gen_helper_0_1(do_mtc0_performance5, t0);
3855 rn = "Performance5";
3856 // break;
3857 case 6:
3858 // tcg_gen_helper_0_1(do_mtc0_performance6, t0);
3859 rn = "Performance6";
3860 // break;
3861 case 7:
3862 // tcg_gen_helper_0_1(do_mtc0_performance7, t0);
3863 rn = "Performance7";
3864 // break;
3865 default:
3866 goto die;
3868 break;
3869 case 26:
3870 /* ignored */
3871 rn = "ECC";
3872 break;
3873 case 27:
3874 switch (sel) {
3875 case 0 ... 3:
3876 /* ignored */
3877 rn = "CacheErr";
3878 break;
3879 default:
3880 goto die;
3882 break;
3883 case 28:
3884 switch (sel) {
3885 case 0:
3886 case 2:
3887 case 4:
3888 case 6:
3889 tcg_gen_helper_0_1(do_mtc0_taglo, t0);
3890 rn = "TagLo";
3891 break;
3892 case 1:
3893 case 3:
3894 case 5:
3895 case 7:
3896 tcg_gen_helper_0_1(do_mtc0_datalo, t0);
3897 rn = "DataLo";
3898 break;
3899 default:
3900 goto die;
3902 break;
3903 case 29:
3904 switch (sel) {
3905 case 0:
3906 case 2:
3907 case 4:
3908 case 6:
3909 tcg_gen_helper_0_1(do_mtc0_taghi, t0);
3910 rn = "TagHi";
3911 break;
3912 case 1:
3913 case 3:
3914 case 5:
3915 case 7:
3916 tcg_gen_helper_0_1(do_mtc0_datahi, t0);
3917 rn = "DataHi";
3918 break;
3919 default:
3920 rn = "invalid sel";
3921 goto die;
3923 break;
3924 case 30:
3925 switch (sel) {
3926 case 0:
3927 gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC));
3928 rn = "ErrorEPC";
3929 break;
3930 default:
3931 goto die;
3933 break;
3934 case 31:
3935 switch (sel) {
3936 case 0:
3937 /* EJTAG support */
3938 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
3939 rn = "DESAVE";
3940 break;
3941 default:
3942 goto die;
3944 /* Stop translation as we may have switched the execution mode */
3945 ctx->bstate = BS_STOP;
3946 break;
3947 default:
3948 goto die;
3950 #if defined MIPS_DEBUG_DISAS
3951 if (loglevel & CPU_LOG_TB_IN_ASM) {
3952 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3953 rn, reg, sel);
3955 #endif
3956 /* For simplicity assume that all writes can cause interrupts. */
3957 if (use_icount) {
3958 gen_io_end();
3959 ctx->bstate = BS_STOP;
3961 return;
3963 die:
3964 #if defined MIPS_DEBUG_DISAS
3965 if (loglevel & CPU_LOG_TB_IN_ASM) {
3966 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3967 rn, reg, sel);
3969 #endif
3970 generate_exception(ctx, EXCP_RI);
3973 #if defined(TARGET_MIPS64)
3974 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
3976 const char *rn = "invalid";
3978 if (sel != 0)
3979 check_insn(env, ctx, ISA_MIPS64);
3981 switch (reg) {
3982 case 0:
3983 switch (sel) {
3984 case 0:
3985 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
3986 rn = "Index";
3987 break;
3988 case 1:
3989 check_insn(env, ctx, ASE_MT);
3990 tcg_gen_helper_1_0(do_mfc0_mvpcontrol, t0);
3991 rn = "MVPControl";
3992 break;
3993 case 2:
3994 check_insn(env, ctx, ASE_MT);
3995 tcg_gen_helper_1_0(do_mfc0_mvpconf0, t0);
3996 rn = "MVPConf0";
3997 break;
3998 case 3:
3999 check_insn(env, ctx, ASE_MT);
4000 tcg_gen_helper_1_0(do_mfc0_mvpconf1, t0);
4001 rn = "MVPConf1";
4002 break;
4003 default:
4004 goto die;
4006 break;
4007 case 1:
4008 switch (sel) {
4009 case 0:
4010 tcg_gen_helper_1_0(do_mfc0_random, t0);
4011 rn = "Random";
4012 break;
4013 case 1:
4014 check_insn(env, ctx, ASE_MT);
4015 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
4016 rn = "VPEControl";
4017 break;
4018 case 2:
4019 check_insn(env, ctx, ASE_MT);
4020 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
4021 rn = "VPEConf0";
4022 break;
4023 case 3:
4024 check_insn(env, ctx, ASE_MT);
4025 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
4026 rn = "VPEConf1";
4027 break;
4028 case 4:
4029 check_insn(env, ctx, ASE_MT);
4030 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask));
4031 rn = "YQMask";
4032 break;
4033 case 5:
4034 check_insn(env, ctx, ASE_MT);
4035 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4036 rn = "VPESchedule";
4037 break;
4038 case 6:
4039 check_insn(env, ctx, ASE_MT);
4040 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4041 rn = "VPEScheFBack";
4042 break;
4043 case 7:
4044 check_insn(env, ctx, ASE_MT);
4045 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
4046 rn = "VPEOpt";
4047 break;
4048 default:
4049 goto die;
4051 break;
4052 case 2:
4053 switch (sel) {
4054 case 0:
4055 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4056 rn = "EntryLo0";
4057 break;
4058 case 1:
4059 check_insn(env, ctx, ASE_MT);
4060 tcg_gen_helper_1_0(do_mfc0_tcstatus, t0);
4061 rn = "TCStatus";
4062 break;
4063 case 2:
4064 check_insn(env, ctx, ASE_MT);
4065 tcg_gen_helper_1_0(do_mfc0_tcbind, t0);
4066 rn = "TCBind";
4067 break;
4068 case 3:
4069 check_insn(env, ctx, ASE_MT);
4070 tcg_gen_helper_1_0(do_dmfc0_tcrestart, t0);
4071 rn = "TCRestart";
4072 break;
4073 case 4:
4074 check_insn(env, ctx, ASE_MT);
4075 tcg_gen_helper_1_0(do_dmfc0_tchalt, t0);
4076 rn = "TCHalt";
4077 break;
4078 case 5:
4079 check_insn(env, ctx, ASE_MT);
4080 tcg_gen_helper_1_0(do_dmfc0_tccontext, t0);
4081 rn = "TCContext";
4082 break;
4083 case 6:
4084 check_insn(env, ctx, ASE_MT);
4085 tcg_gen_helper_1_0(do_dmfc0_tcschedule, t0);
4086 rn = "TCSchedule";
4087 break;
4088 case 7:
4089 check_insn(env, ctx, ASE_MT);
4090 tcg_gen_helper_1_0(do_dmfc0_tcschefback, t0);
4091 rn = "TCScheFBack";
4092 break;
4093 default:
4094 goto die;
4096 break;
4097 case 3:
4098 switch (sel) {
4099 case 0:
4100 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4101 rn = "EntryLo1";
4102 break;
4103 default:
4104 goto die;
4106 break;
4107 case 4:
4108 switch (sel) {
4109 case 0:
4110 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
4111 rn = "Context";
4112 break;
4113 case 1:
4114 // tcg_gen_helper_1_0(do_dmfc0_contextconfig, t0); /* SmartMIPS ASE */
4115 rn = "ContextConfig";
4116 // break;
4117 default:
4118 goto die;
4120 break;
4121 case 5:
4122 switch (sel) {
4123 case 0:
4124 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
4125 rn = "PageMask";
4126 break;
4127 case 1:
4128 check_insn(env, ctx, ISA_MIPS32R2);
4129 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
4130 rn = "PageGrain";
4131 break;
4132 default:
4133 goto die;
4135 break;
4136 case 6:
4137 switch (sel) {
4138 case 0:
4139 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
4140 rn = "Wired";
4141 break;
4142 case 1:
4143 check_insn(env, ctx, ISA_MIPS32R2);
4144 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
4145 rn = "SRSConf0";
4146 break;
4147 case 2:
4148 check_insn(env, ctx, ISA_MIPS32R2);
4149 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
4150 rn = "SRSConf1";
4151 break;
4152 case 3:
4153 check_insn(env, ctx, ISA_MIPS32R2);
4154 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
4155 rn = "SRSConf2";
4156 break;
4157 case 4:
4158 check_insn(env, ctx, ISA_MIPS32R2);
4159 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
4160 rn = "SRSConf3";
4161 break;
4162 case 5:
4163 check_insn(env, ctx, ISA_MIPS32R2);
4164 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
4165 rn = "SRSConf4";
4166 break;
4167 default:
4168 goto die;
4170 break;
4171 case 7:
4172 switch (sel) {
4173 case 0:
4174 check_insn(env, ctx, ISA_MIPS32R2);
4175 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
4176 rn = "HWREna";
4177 break;
4178 default:
4179 goto die;
4181 break;
4182 case 8:
4183 switch (sel) {
4184 case 0:
4185 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4186 rn = "BadVAddr";
4187 break;
4188 default:
4189 goto die;
4191 break;
4192 case 9:
4193 switch (sel) {
4194 case 0:
4195 /* Mark as an IO operation because we read the time. */
4196 if (use_icount)
4197 gen_io_start();
4198 tcg_gen_helper_1_0(do_mfc0_count, t0);
4199 if (use_icount) {
4200 gen_io_end();
4201 ctx->bstate = BS_STOP;
4203 rn = "Count";
4204 break;
4205 /* 6,7 are implementation dependent */
4206 default:
4207 goto die;
4209 break;
4210 case 10:
4211 switch (sel) {
4212 case 0:
4213 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
4214 rn = "EntryHi";
4215 break;
4216 default:
4217 goto die;
4219 break;
4220 case 11:
4221 switch (sel) {
4222 case 0:
4223 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
4224 rn = "Compare";
4225 break;
4226 /* 6,7 are implementation dependent */
4227 default:
4228 goto die;
4230 break;
4231 case 12:
4232 switch (sel) {
4233 case 0:
4234 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
4235 rn = "Status";
4236 break;
4237 case 1:
4238 check_insn(env, ctx, ISA_MIPS32R2);
4239 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
4240 rn = "IntCtl";
4241 break;
4242 case 2:
4243 check_insn(env, ctx, ISA_MIPS32R2);
4244 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
4245 rn = "SRSCtl";
4246 break;
4247 case 3:
4248 check_insn(env, ctx, ISA_MIPS32R2);
4249 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
4250 rn = "SRSMap";
4251 break;
4252 default:
4253 goto die;
4255 break;
4256 case 13:
4257 switch (sel) {
4258 case 0:
4259 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
4260 rn = "Cause";
4261 break;
4262 default:
4263 goto die;
4265 break;
4266 case 14:
4267 switch (sel) {
4268 case 0:
4269 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4270 rn = "EPC";
4271 break;
4272 default:
4273 goto die;
4275 break;
4276 case 15:
4277 switch (sel) {
4278 case 0:
4279 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
4280 rn = "PRid";
4281 break;
4282 case 1:
4283 check_insn(env, ctx, ISA_MIPS32R2);
4284 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
4285 rn = "EBase";
4286 break;
4287 default:
4288 goto die;
4290 break;
4291 case 16:
4292 switch (sel) {
4293 case 0:
4294 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
4295 rn = "Config";
4296 break;
4297 case 1:
4298 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
4299 rn = "Config1";
4300 break;
4301 case 2:
4302 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
4303 rn = "Config2";
4304 break;
4305 case 3:
4306 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
4307 rn = "Config3";
4308 break;
4309 /* 6,7 are implementation dependent */
4310 case 6:
4311 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
4312 rn = "Config6";
4313 break;
4314 case 7:
4315 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
4316 rn = "Config7";
4317 break;
4318 default:
4319 goto die;
4321 break;
4322 case 17:
4323 switch (sel) {
4324 case 0:
4325 tcg_gen_helper_1_0(do_dmfc0_lladdr, t0);
4326 rn = "LLAddr";
4327 break;
4328 default:
4329 goto die;
4331 break;
4332 case 18:
4333 switch (sel) {
4334 case 0 ... 7:
4335 tcg_gen_helper_1_i(do_dmfc0_watchlo, t0, sel);
4336 rn = "WatchLo";
4337 break;
4338 default:
4339 goto die;
4341 break;
4342 case 19:
4343 switch (sel) {
4344 case 0 ... 7:
4345 tcg_gen_helper_1_i(do_mfc0_watchhi, t0, sel);
4346 rn = "WatchHi";
4347 break;
4348 default:
4349 goto die;
4351 break;
4352 case 20:
4353 switch (sel) {
4354 case 0:
4355 check_insn(env, ctx, ISA_MIPS3);
4356 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
4357 rn = "XContext";
4358 break;
4359 default:
4360 goto die;
4362 break;
4363 case 21:
4364 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4365 switch (sel) {
4366 case 0:
4367 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
4368 rn = "Framemask";
4369 break;
4370 default:
4371 goto die;
4373 break;
4374 case 22:
4375 /* ignored */
4376 rn = "'Diagnostic"; /* implementation dependent */
4377 break;
4378 case 23:
4379 switch (sel) {
4380 case 0:
4381 tcg_gen_helper_1_0(do_mfc0_debug, t0); /* EJTAG support */
4382 rn = "Debug";
4383 break;
4384 case 1:
4385 // tcg_gen_helper_1_0(do_dmfc0_tracecontrol, t0); /* PDtrace support */
4386 rn = "TraceControl";
4387 // break;
4388 case 2:
4389 // tcg_gen_helper_1_0(do_dmfc0_tracecontrol2, t0); /* PDtrace support */
4390 rn = "TraceControl2";
4391 // break;
4392 case 3:
4393 // tcg_gen_helper_1_0(do_dmfc0_usertracedata, t0); /* PDtrace support */
4394 rn = "UserTraceData";
4395 // break;
4396 case 4:
4397 // tcg_gen_helper_1_0(do_dmfc0_tracebpc, t0); /* PDtrace support */
4398 rn = "TraceBPC";
4399 // break;
4400 default:
4401 goto die;
4403 break;
4404 case 24:
4405 switch (sel) {
4406 case 0:
4407 /* EJTAG support */
4408 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
4409 rn = "DEPC";
4410 break;
4411 default:
4412 goto die;
4414 break;
4415 case 25:
4416 switch (sel) {
4417 case 0:
4418 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
4419 rn = "Performance0";
4420 break;
4421 case 1:
4422 // tcg_gen_helper_1_0(do_dmfc0_performance1, t0);
4423 rn = "Performance1";
4424 // break;
4425 case 2:
4426 // tcg_gen_helper_1_0(do_dmfc0_performance2, t0);
4427 rn = "Performance2";
4428 // break;
4429 case 3:
4430 // tcg_gen_helper_1_0(do_dmfc0_performance3, t0);
4431 rn = "Performance3";
4432 // break;
4433 case 4:
4434 // tcg_gen_helper_1_0(do_dmfc0_performance4, t0);
4435 rn = "Performance4";
4436 // break;
4437 case 5:
4438 // tcg_gen_helper_1_0(do_dmfc0_performance5, t0);
4439 rn = "Performance5";
4440 // break;
4441 case 6:
4442 // tcg_gen_helper_1_0(do_dmfc0_performance6, t0);
4443 rn = "Performance6";
4444 // break;
4445 case 7:
4446 // tcg_gen_helper_1_0(do_dmfc0_performance7, t0);
4447 rn = "Performance7";
4448 // break;
4449 default:
4450 goto die;
4452 break;
4453 case 26:
4454 rn = "ECC";
4455 break;
4456 case 27:
4457 switch (sel) {
4458 /* ignored */
4459 case 0 ... 3:
4460 rn = "CacheErr";
4461 break;
4462 default:
4463 goto die;
4465 break;
4466 case 28:
4467 switch (sel) {
4468 case 0:
4469 case 2:
4470 case 4:
4471 case 6:
4472 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
4473 rn = "TagLo";
4474 break;
4475 case 1:
4476 case 3:
4477 case 5:
4478 case 7:
4479 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
4480 rn = "DataLo";
4481 break;
4482 default:
4483 goto die;
4485 break;
4486 case 29:
4487 switch (sel) {
4488 case 0:
4489 case 2:
4490 case 4:
4491 case 6:
4492 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
4493 rn = "TagHi";
4494 break;
4495 case 1:
4496 case 3:
4497 case 5:
4498 case 7:
4499 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
4500 rn = "DataHi";
4501 break;
4502 default:
4503 goto die;
4505 break;
4506 case 30:
4507 switch (sel) {
4508 case 0:
4509 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4510 rn = "ErrorEPC";
4511 break;
4512 default:
4513 goto die;
4515 break;
4516 case 31:
4517 switch (sel) {
4518 case 0:
4519 /* EJTAG support */
4520 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
4521 rn = "DESAVE";
4522 break;
4523 default:
4524 goto die;
4526 break;
4527 default:
4528 goto die;
4530 #if defined MIPS_DEBUG_DISAS
4531 if (loglevel & CPU_LOG_TB_IN_ASM) {
4532 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4533 rn, reg, sel);
4535 #endif
4536 return;
4538 die:
4539 #if defined MIPS_DEBUG_DISAS
4540 if (loglevel & CPU_LOG_TB_IN_ASM) {
4541 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4542 rn, reg, sel);
4544 #endif
4545 generate_exception(ctx, EXCP_RI);
4548 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
4550 const char *rn = "invalid";
4552 if (sel != 0)
4553 check_insn(env, ctx, ISA_MIPS64);
4555 if (use_icount)
4556 gen_io_start();
4558 switch (reg) {
4559 case 0:
4560 switch (sel) {
4561 case 0:
4562 tcg_gen_helper_0_1(do_mtc0_index, t0);
4563 rn = "Index";
4564 break;
4565 case 1:
4566 check_insn(env, ctx, ASE_MT);
4567 tcg_gen_helper_0_1(do_mtc0_mvpcontrol, t0);
4568 rn = "MVPControl";
4569 break;
4570 case 2:
4571 check_insn(env, ctx, ASE_MT);
4572 /* ignored */
4573 rn = "MVPConf0";
4574 break;
4575 case 3:
4576 check_insn(env, ctx, ASE_MT);
4577 /* ignored */
4578 rn = "MVPConf1";
4579 break;
4580 default:
4581 goto die;
4583 break;
4584 case 1:
4585 switch (sel) {
4586 case 0:
4587 /* ignored */
4588 rn = "Random";
4589 break;
4590 case 1:
4591 check_insn(env, ctx, ASE_MT);
4592 tcg_gen_helper_0_1(do_mtc0_vpecontrol, t0);
4593 rn = "VPEControl";
4594 break;
4595 case 2:
4596 check_insn(env, ctx, ASE_MT);
4597 tcg_gen_helper_0_1(do_mtc0_vpeconf0, t0);
4598 rn = "VPEConf0";
4599 break;
4600 case 3:
4601 check_insn(env, ctx, ASE_MT);
4602 tcg_gen_helper_0_1(do_mtc0_vpeconf1, t0);
4603 rn = "VPEConf1";
4604 break;
4605 case 4:
4606 check_insn(env, ctx, ASE_MT);
4607 tcg_gen_helper_0_1(do_mtc0_yqmask, t0);
4608 rn = "YQMask";
4609 break;
4610 case 5:
4611 check_insn(env, ctx, ASE_MT);
4612 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4613 rn = "VPESchedule";
4614 break;
4615 case 6:
4616 check_insn(env, ctx, ASE_MT);
4617 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4618 rn = "VPEScheFBack";
4619 break;
4620 case 7:
4621 check_insn(env, ctx, ASE_MT);
4622 tcg_gen_helper_0_1(do_mtc0_vpeopt, t0);
4623 rn = "VPEOpt";
4624 break;
4625 default:
4626 goto die;
4628 break;
4629 case 2:
4630 switch (sel) {
4631 case 0:
4632 tcg_gen_helper_0_1(do_mtc0_entrylo0, t0);
4633 rn = "EntryLo0";
4634 break;
4635 case 1:
4636 check_insn(env, ctx, ASE_MT);
4637 tcg_gen_helper_0_1(do_mtc0_tcstatus, t0);
4638 rn = "TCStatus";
4639 break;
4640 case 2:
4641 check_insn(env, ctx, ASE_MT);
4642 tcg_gen_helper_0_1(do_mtc0_tcbind, t0);
4643 rn = "TCBind";
4644 break;
4645 case 3:
4646 check_insn(env, ctx, ASE_MT);
4647 tcg_gen_helper_0_1(do_mtc0_tcrestart, t0);
4648 rn = "TCRestart";
4649 break;
4650 case 4:
4651 check_insn(env, ctx, ASE_MT);
4652 tcg_gen_helper_0_1(do_mtc0_tchalt, t0);
4653 rn = "TCHalt";
4654 break;
4655 case 5:
4656 check_insn(env, ctx, ASE_MT);
4657 tcg_gen_helper_0_1(do_mtc0_tccontext, t0);
4658 rn = "TCContext";
4659 break;
4660 case 6:
4661 check_insn(env, ctx, ASE_MT);
4662 tcg_gen_helper_0_1(do_mtc0_tcschedule, t0);
4663 rn = "TCSchedule";
4664 break;
4665 case 7:
4666 check_insn(env, ctx, ASE_MT);
4667 tcg_gen_helper_0_1(do_mtc0_tcschefback, t0);
4668 rn = "TCScheFBack";
4669 break;
4670 default:
4671 goto die;
4673 break;
4674 case 3:
4675 switch (sel) {
4676 case 0:
4677 tcg_gen_helper_0_1(do_mtc0_entrylo1, t0);
4678 rn = "EntryLo1";
4679 break;
4680 default:
4681 goto die;
4683 break;
4684 case 4:
4685 switch (sel) {
4686 case 0:
4687 tcg_gen_helper_0_1(do_mtc0_context, t0);
4688 rn = "Context";
4689 break;
4690 case 1:
4691 // tcg_gen_helper_0_1(do_mtc0_contextconfig, t0); /* SmartMIPS ASE */
4692 rn = "ContextConfig";
4693 // break;
4694 default:
4695 goto die;
4697 break;
4698 case 5:
4699 switch (sel) {
4700 case 0:
4701 tcg_gen_helper_0_1(do_mtc0_pagemask, t0);
4702 rn = "PageMask";
4703 break;
4704 case 1:
4705 check_insn(env, ctx, ISA_MIPS32R2);
4706 tcg_gen_helper_0_1(do_mtc0_pagegrain, t0);
4707 rn = "PageGrain";
4708 break;
4709 default:
4710 goto die;
4712 break;
4713 case 6:
4714 switch (sel) {
4715 case 0:
4716 tcg_gen_helper_0_1(do_mtc0_wired, t0);
4717 rn = "Wired";
4718 break;
4719 case 1:
4720 check_insn(env, ctx, ISA_MIPS32R2);
4721 tcg_gen_helper_0_1(do_mtc0_srsconf0, t0);
4722 rn = "SRSConf0";
4723 break;
4724 case 2:
4725 check_insn(env, ctx, ISA_MIPS32R2);
4726 tcg_gen_helper_0_1(do_mtc0_srsconf1, t0);
4727 rn = "SRSConf1";
4728 break;
4729 case 3:
4730 check_insn(env, ctx, ISA_MIPS32R2);
4731 tcg_gen_helper_0_1(do_mtc0_srsconf2, t0);
4732 rn = "SRSConf2";
4733 break;
4734 case 4:
4735 check_insn(env, ctx, ISA_MIPS32R2);
4736 tcg_gen_helper_0_1(do_mtc0_srsconf3, t0);
4737 rn = "SRSConf3";
4738 break;
4739 case 5:
4740 check_insn(env, ctx, ISA_MIPS32R2);
4741 tcg_gen_helper_0_1(do_mtc0_srsconf4, t0);
4742 rn = "SRSConf4";
4743 break;
4744 default:
4745 goto die;
4747 break;
4748 case 7:
4749 switch (sel) {
4750 case 0:
4751 check_insn(env, ctx, ISA_MIPS32R2);
4752 tcg_gen_helper_0_1(do_mtc0_hwrena, t0);
4753 rn = "HWREna";
4754 break;
4755 default:
4756 goto die;
4758 break;
4759 case 8:
4760 /* ignored */
4761 rn = "BadVAddr";
4762 break;
4763 case 9:
4764 switch (sel) {
4765 case 0:
4766 tcg_gen_helper_0_1(do_mtc0_count, t0);
4767 rn = "Count";
4768 break;
4769 /* 6,7 are implementation dependent */
4770 default:
4771 goto die;
4773 /* Stop translation as we may have switched the execution mode */
4774 ctx->bstate = BS_STOP;
4775 break;
4776 case 10:
4777 switch (sel) {
4778 case 0:
4779 tcg_gen_helper_0_1(do_mtc0_entryhi, t0);
4780 rn = "EntryHi";
4781 break;
4782 default:
4783 goto die;
4785 break;
4786 case 11:
4787 switch (sel) {
4788 case 0:
4789 tcg_gen_helper_0_1(do_mtc0_compare, t0);
4790 rn = "Compare";
4791 break;
4792 /* 6,7 are implementation dependent */
4793 default:
4794 goto die;
4796 /* Stop translation as we may have switched the execution mode */
4797 ctx->bstate = BS_STOP;
4798 break;
4799 case 12:
4800 switch (sel) {
4801 case 0:
4802 tcg_gen_helper_0_1(do_mtc0_status, t0);
4803 /* BS_STOP isn't good enough here, hflags may have changed. */
4804 gen_save_pc(ctx->pc + 4);
4805 ctx->bstate = BS_EXCP;
4806 rn = "Status";
4807 break;
4808 case 1:
4809 check_insn(env, ctx, ISA_MIPS32R2);
4810 tcg_gen_helper_0_1(do_mtc0_intctl, t0);
4811 /* Stop translation as we may have switched the execution mode */
4812 ctx->bstate = BS_STOP;
4813 rn = "IntCtl";
4814 break;
4815 case 2:
4816 check_insn(env, ctx, ISA_MIPS32R2);
4817 tcg_gen_helper_0_1(do_mtc0_srsctl, t0);
4818 /* Stop translation as we may have switched the execution mode */
4819 ctx->bstate = BS_STOP;
4820 rn = "SRSCtl";
4821 break;
4822 case 3:
4823 check_insn(env, ctx, ISA_MIPS32R2);
4824 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
4825 /* Stop translation as we may have switched the execution mode */
4826 ctx->bstate = BS_STOP;
4827 rn = "SRSMap";
4828 break;
4829 default:
4830 goto die;
4832 break;
4833 case 13:
4834 switch (sel) {
4835 case 0:
4836 tcg_gen_helper_0_1(do_mtc0_cause, t0);
4837 rn = "Cause";
4838 break;
4839 default:
4840 goto die;
4842 /* Stop translation as we may have switched the execution mode */
4843 ctx->bstate = BS_STOP;
4844 break;
4845 case 14:
4846 switch (sel) {
4847 case 0:
4848 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
4849 rn = "EPC";
4850 break;
4851 default:
4852 goto die;
4854 break;
4855 case 15:
4856 switch (sel) {
4857 case 0:
4858 /* ignored */
4859 rn = "PRid";
4860 break;
4861 case 1:
4862 check_insn(env, ctx, ISA_MIPS32R2);
4863 tcg_gen_helper_0_1(do_mtc0_ebase, t0);
4864 rn = "EBase";
4865 break;
4866 default:
4867 goto die;
4869 break;
4870 case 16:
4871 switch (sel) {
4872 case 0:
4873 tcg_gen_helper_0_1(do_mtc0_config0, t0);
4874 rn = "Config";
4875 /* Stop translation as we may have switched the execution mode */
4876 ctx->bstate = BS_STOP;
4877 break;
4878 case 1:
4879 /* ignored */
4880 rn = "Config1";
4881 break;
4882 case 2:
4883 tcg_gen_helper_0_1(do_mtc0_config2, t0);
4884 rn = "Config2";
4885 /* Stop translation as we may have switched the execution mode */
4886 ctx->bstate = BS_STOP;
4887 break;
4888 case 3:
4889 /* ignored */
4890 rn = "Config3";
4891 break;
4892 /* 6,7 are implementation dependent */
4893 default:
4894 rn = "Invalid config selector";
4895 goto die;
4897 break;
4898 case 17:
4899 switch (sel) {
4900 case 0:
4901 /* ignored */
4902 rn = "LLAddr";
4903 break;
4904 default:
4905 goto die;
4907 break;
4908 case 18:
4909 switch (sel) {
4910 case 0 ... 7:
4911 tcg_gen_helper_0_1i(do_mtc0_watchlo, t0, sel);
4912 rn = "WatchLo";
4913 break;
4914 default:
4915 goto die;
4917 break;
4918 case 19:
4919 switch (sel) {
4920 case 0 ... 7:
4921 tcg_gen_helper_0_1i(do_mtc0_watchhi, t0, sel);
4922 rn = "WatchHi";
4923 break;
4924 default:
4925 goto die;
4927 break;
4928 case 20:
4929 switch (sel) {
4930 case 0:
4931 check_insn(env, ctx, ISA_MIPS3);
4932 tcg_gen_helper_0_1(do_mtc0_xcontext, t0);
4933 rn = "XContext";
4934 break;
4935 default:
4936 goto die;
4938 break;
4939 case 21:
4940 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4941 switch (sel) {
4942 case 0:
4943 tcg_gen_helper_0_1(do_mtc0_framemask, t0);
4944 rn = "Framemask";
4945 break;
4946 default:
4947 goto die;
4949 break;
4950 case 22:
4951 /* ignored */
4952 rn = "Diagnostic"; /* implementation dependent */
4953 break;
4954 case 23:
4955 switch (sel) {
4956 case 0:
4957 tcg_gen_helper_0_1(do_mtc0_debug, t0); /* EJTAG support */
4958 /* BS_STOP isn't good enough here, hflags may have changed. */
4959 gen_save_pc(ctx->pc + 4);
4960 ctx->bstate = BS_EXCP;
4961 rn = "Debug";
4962 break;
4963 case 1:
4964 // tcg_gen_helper_0_1(do_mtc0_tracecontrol, t0); /* PDtrace support */
4965 /* Stop translation as we may have switched the execution mode */
4966 ctx->bstate = BS_STOP;
4967 rn = "TraceControl";
4968 // break;
4969 case 2:
4970 // tcg_gen_helper_0_1(do_mtc0_tracecontrol2, t0); /* PDtrace support */
4971 /* Stop translation as we may have switched the execution mode */
4972 ctx->bstate = BS_STOP;
4973 rn = "TraceControl2";
4974 // break;
4975 case 3:
4976 // tcg_gen_helper_0_1(do_mtc0_usertracedata, t0); /* PDtrace support */
4977 /* Stop translation as we may have switched the execution mode */
4978 ctx->bstate = BS_STOP;
4979 rn = "UserTraceData";
4980 // break;
4981 case 4:
4982 // tcg_gen_helper_0_1(do_mtc0_tracebpc, t0); /* PDtrace support */
4983 /* Stop translation as we may have switched the execution mode */
4984 ctx->bstate = BS_STOP;
4985 rn = "TraceBPC";
4986 // break;
4987 default:
4988 goto die;
4990 break;
4991 case 24:
4992 switch (sel) {
4993 case 0:
4994 /* EJTAG support */
4995 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
4996 rn = "DEPC";
4997 break;
4998 default:
4999 goto die;
5001 break;
5002 case 25:
5003 switch (sel) {
5004 case 0:
5005 tcg_gen_helper_0_1(do_mtc0_performance0, t0);
5006 rn = "Performance0";
5007 break;
5008 case 1:
5009 // tcg_gen_helper_0_1(do_mtc0_performance1, t0);
5010 rn = "Performance1";
5011 // break;
5012 case 2:
5013 // tcg_gen_helper_0_1(do_mtc0_performance2, t0);
5014 rn = "Performance2";
5015 // break;
5016 case 3:
5017 // tcg_gen_helper_0_1(do_mtc0_performance3, t0);
5018 rn = "Performance3";
5019 // break;
5020 case 4:
5021 // tcg_gen_helper_0_1(do_mtc0_performance4, t0);
5022 rn = "Performance4";
5023 // break;
5024 case 5:
5025 // tcg_gen_helper_0_1(do_mtc0_performance5, t0);
5026 rn = "Performance5";
5027 // break;
5028 case 6:
5029 // tcg_gen_helper_0_1(do_mtc0_performance6, t0);
5030 rn = "Performance6";
5031 // break;
5032 case 7:
5033 // tcg_gen_helper_0_1(do_mtc0_performance7, t0);
5034 rn = "Performance7";
5035 // break;
5036 default:
5037 goto die;
5039 break;
5040 case 26:
5041 /* ignored */
5042 rn = "ECC";
5043 break;
5044 case 27:
5045 switch (sel) {
5046 case 0 ... 3:
5047 /* ignored */
5048 rn = "CacheErr";
5049 break;
5050 default:
5051 goto die;
5053 break;
5054 case 28:
5055 switch (sel) {
5056 case 0:
5057 case 2:
5058 case 4:
5059 case 6:
5060 tcg_gen_helper_0_1(do_mtc0_taglo, t0);
5061 rn = "TagLo";
5062 break;
5063 case 1:
5064 case 3:
5065 case 5:
5066 case 7:
5067 tcg_gen_helper_0_1(do_mtc0_datalo, t0);
5068 rn = "DataLo";
5069 break;
5070 default:
5071 goto die;
5073 break;
5074 case 29:
5075 switch (sel) {
5076 case 0:
5077 case 2:
5078 case 4:
5079 case 6:
5080 tcg_gen_helper_0_1(do_mtc0_taghi, t0);
5081 rn = "TagHi";
5082 break;
5083 case 1:
5084 case 3:
5085 case 5:
5086 case 7:
5087 tcg_gen_helper_0_1(do_mtc0_datahi, t0);
5088 rn = "DataHi";
5089 break;
5090 default:
5091 rn = "invalid sel";
5092 goto die;
5094 break;
5095 case 30:
5096 switch (sel) {
5097 case 0:
5098 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5099 rn = "ErrorEPC";
5100 break;
5101 default:
5102 goto die;
5104 break;
5105 case 31:
5106 switch (sel) {
5107 case 0:
5108 /* EJTAG support */
5109 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
5110 rn = "DESAVE";
5111 break;
5112 default:
5113 goto die;
5115 /* Stop translation as we may have switched the execution mode */
5116 ctx->bstate = BS_STOP;
5117 break;
5118 default:
5119 goto die;
5121 #if defined MIPS_DEBUG_DISAS
5122 if (loglevel & CPU_LOG_TB_IN_ASM) {
5123 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5124 rn, reg, sel);
5126 #endif
5127 /* For simplicity assume that all writes can cause interrupts. */
5128 if (use_icount) {
5129 gen_io_end();
5130 ctx->bstate = BS_STOP;
5132 return;
5134 die:
5135 #if defined MIPS_DEBUG_DISAS
5136 if (loglevel & CPU_LOG_TB_IN_ASM) {
5137 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5138 rn, reg, sel);
5140 #endif
5141 generate_exception(ctx, EXCP_RI);
5143 #endif /* TARGET_MIPS64 */
5145 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5146 int u, int sel, int h)
5148 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5149 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5151 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5152 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5153 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5154 tcg_gen_movi_tl(t0, -1);
5155 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5156 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5157 tcg_gen_movi_tl(t0, -1);
5158 else if (u == 0) {
5159 switch (rt) {
5160 case 2:
5161 switch (sel) {
5162 case 1:
5163 tcg_gen_helper_1_0(do_mftc0_tcstatus, t0);
5164 break;
5165 case 2:
5166 tcg_gen_helper_1_0(do_mftc0_tcbind, t0);
5167 break;
5168 case 3:
5169 tcg_gen_helper_1_0(do_mftc0_tcrestart, t0);
5170 break;
5171 case 4:
5172 tcg_gen_helper_1_0(do_mftc0_tchalt, t0);
5173 break;
5174 case 5:
5175 tcg_gen_helper_1_0(do_mftc0_tccontext, t0);
5176 break;
5177 case 6:
5178 tcg_gen_helper_1_0(do_mftc0_tcschedule, t0);
5179 break;
5180 case 7:
5181 tcg_gen_helper_1_0(do_mftc0_tcschefback, t0);
5182 break;
5183 default:
5184 gen_mfc0(env, ctx, t0, rt, sel);
5185 break;
5187 break;
5188 case 10:
5189 switch (sel) {
5190 case 0:
5191 tcg_gen_helper_1_0(do_mftc0_entryhi, t0);
5192 break;
5193 default:
5194 gen_mfc0(env, ctx, t0, rt, sel);
5195 break;
5197 case 12:
5198 switch (sel) {
5199 case 0:
5200 tcg_gen_helper_1_0(do_mftc0_status, t0);
5201 break;
5202 default:
5203 gen_mfc0(env, ctx, t0, rt, sel);
5204 break;
5206 case 23:
5207 switch (sel) {
5208 case 0:
5209 tcg_gen_helper_1_0(do_mftc0_debug, t0);
5210 break;
5211 default:
5212 gen_mfc0(env, ctx, t0, rt, sel);
5213 break;
5215 break;
5216 default:
5217 gen_mfc0(env, ctx, t0, rt, sel);
5219 } else switch (sel) {
5220 /* GPR registers. */
5221 case 0:
5222 tcg_gen_helper_1_i(do_mftgpr, t0, rt);
5223 break;
5224 /* Auxiliary CPU registers */
5225 case 1:
5226 switch (rt) {
5227 case 0:
5228 tcg_gen_helper_1_i(do_mftlo, t0, 0);
5229 break;
5230 case 1:
5231 tcg_gen_helper_1_i(do_mfthi, t0, 0);
5232 break;
5233 case 2:
5234 tcg_gen_helper_1_i(do_mftacx, t0, 0);
5235 break;
5236 case 4:
5237 tcg_gen_helper_1_i(do_mftlo, t0, 1);
5238 break;
5239 case 5:
5240 tcg_gen_helper_1_i(do_mfthi, t0, 1);
5241 break;
5242 case 6:
5243 tcg_gen_helper_1_i(do_mftacx, t0, 1);
5244 break;
5245 case 8:
5246 tcg_gen_helper_1_i(do_mftlo, t0, 2);
5247 break;
5248 case 9:
5249 tcg_gen_helper_1_i(do_mfthi, t0, 2);
5250 break;
5251 case 10:
5252 tcg_gen_helper_1_i(do_mftacx, t0, 2);
5253 break;
5254 case 12:
5255 tcg_gen_helper_1_i(do_mftlo, t0, 3);
5256 break;
5257 case 13:
5258 tcg_gen_helper_1_i(do_mfthi, t0, 3);
5259 break;
5260 case 14:
5261 tcg_gen_helper_1_i(do_mftacx, t0, 3);
5262 break;
5263 case 16:
5264 tcg_gen_helper_1_0(do_mftdsp, t0);
5265 break;
5266 default:
5267 goto die;
5269 break;
5270 /* Floating point (COP1). */
5271 case 2:
5272 /* XXX: For now we support only a single FPU context. */
5273 if (h == 0) {
5274 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5276 gen_load_fpr32(fp0, rt);
5277 tcg_gen_ext_i32_tl(t0, fp0);
5278 tcg_temp_free(fp0);
5279 } else {
5280 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5282 gen_load_fpr32h(fp0, rt);
5283 tcg_gen_ext_i32_tl(t0, fp0);
5284 tcg_temp_free(fp0);
5286 break;
5287 case 3:
5288 /* XXX: For now we support only a single FPU context. */
5289 tcg_gen_helper_1_1i(do_cfc1, t0, t0, rt);
5290 break;
5291 /* COP2: Not implemented. */
5292 case 4:
5293 case 5:
5294 /* fall through */
5295 default:
5296 goto die;
5298 #if defined MIPS_DEBUG_DISAS
5299 if (loglevel & CPU_LOG_TB_IN_ASM) {
5300 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5301 rt, u, sel, h);
5303 #endif
5304 gen_store_gpr(t0, rd);
5305 tcg_temp_free(t0);
5306 return;
5308 die:
5309 tcg_temp_free(t0);
5310 #if defined MIPS_DEBUG_DISAS
5311 if (loglevel & CPU_LOG_TB_IN_ASM) {
5312 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5313 rt, u, sel, h);
5315 #endif
5316 generate_exception(ctx, EXCP_RI);
5319 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5320 int u, int sel, int h)
5322 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5323 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5325 gen_load_gpr(t0, rt);
5326 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5327 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5328 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5329 /* NOP */ ;
5330 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5331 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5332 /* NOP */ ;
5333 else if (u == 0) {
5334 switch (rd) {
5335 case 2:
5336 switch (sel) {
5337 case 1:
5338 tcg_gen_helper_0_1(do_mttc0_tcstatus, t0);
5339 break;
5340 case 2:
5341 tcg_gen_helper_0_1(do_mttc0_tcbind, t0);
5342 break;
5343 case 3:
5344 tcg_gen_helper_0_1(do_mttc0_tcrestart, t0);
5345 break;
5346 case 4:
5347 tcg_gen_helper_0_1(do_mttc0_tchalt, t0);
5348 break;
5349 case 5:
5350 tcg_gen_helper_0_1(do_mttc0_tccontext, t0);
5351 break;
5352 case 6:
5353 tcg_gen_helper_0_1(do_mttc0_tcschedule, t0);
5354 break;
5355 case 7:
5356 tcg_gen_helper_0_1(do_mttc0_tcschefback, t0);
5357 break;
5358 default:
5359 gen_mtc0(env, ctx, t0, rd, sel);
5360 break;
5362 break;
5363 case 10:
5364 switch (sel) {
5365 case 0:
5366 tcg_gen_helper_0_1(do_mttc0_entryhi, t0);
5367 break;
5368 default:
5369 gen_mtc0(env, ctx, t0, rd, sel);
5370 break;
5372 case 12:
5373 switch (sel) {
5374 case 0:
5375 tcg_gen_helper_0_1(do_mttc0_status, t0);
5376 break;
5377 default:
5378 gen_mtc0(env, ctx, t0, rd, sel);
5379 break;
5381 case 23:
5382 switch (sel) {
5383 case 0:
5384 tcg_gen_helper_0_1(do_mttc0_debug, t0);
5385 break;
5386 default:
5387 gen_mtc0(env, ctx, t0, rd, sel);
5388 break;
5390 break;
5391 default:
5392 gen_mtc0(env, ctx, t0, rd, sel);
5394 } else switch (sel) {
5395 /* GPR registers. */
5396 case 0:
5397 tcg_gen_helper_0_1i(do_mttgpr, t0, rd);
5398 break;
5399 /* Auxiliary CPU registers */
5400 case 1:
5401 switch (rd) {
5402 case 0:
5403 tcg_gen_helper_0_1i(do_mttlo, t0, 0);
5404 break;
5405 case 1:
5406 tcg_gen_helper_0_1i(do_mtthi, t0, 0);
5407 break;
5408 case 2:
5409 tcg_gen_helper_0_1i(do_mttacx, t0, 0);
5410 break;
5411 case 4:
5412 tcg_gen_helper_0_1i(do_mttlo, t0, 1);
5413 break;
5414 case 5:
5415 tcg_gen_helper_0_1i(do_mtthi, t0, 1);
5416 break;
5417 case 6:
5418 tcg_gen_helper_0_1i(do_mttacx, t0, 1);
5419 break;
5420 case 8:
5421 tcg_gen_helper_0_1i(do_mttlo, t0, 2);
5422 break;
5423 case 9:
5424 tcg_gen_helper_0_1i(do_mtthi, t0, 2);
5425 break;
5426 case 10:
5427 tcg_gen_helper_0_1i(do_mttacx, t0, 2);
5428 break;
5429 case 12:
5430 tcg_gen_helper_0_1i(do_mttlo, t0, 3);
5431 break;
5432 case 13:
5433 tcg_gen_helper_0_1i(do_mtthi, t0, 3);
5434 break;
5435 case 14:
5436 tcg_gen_helper_0_1i(do_mttacx, t0, 3);
5437 break;
5438 case 16:
5439 tcg_gen_helper_0_1(do_mttdsp, t0);
5440 break;
5441 default:
5442 goto die;
5444 break;
5445 /* Floating point (COP1). */
5446 case 2:
5447 /* XXX: For now we support only a single FPU context. */
5448 if (h == 0) {
5449 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5451 tcg_gen_trunc_tl_i32(fp0, t0);
5452 gen_store_fpr32(fp0, rd);
5453 tcg_temp_free(fp0);
5454 } else {
5455 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5457 tcg_gen_trunc_tl_i32(fp0, t0);
5458 gen_store_fpr32h(fp0, rd);
5459 tcg_temp_free(fp0);
5461 break;
5462 case 3:
5463 /* XXX: For now we support only a single FPU context. */
5464 tcg_gen_helper_0_1i(do_ctc1, t0, rd);
5465 break;
5466 /* COP2: Not implemented. */
5467 case 4:
5468 case 5:
5469 /* fall through */
5470 default:
5471 goto die;
5473 #if defined MIPS_DEBUG_DISAS
5474 if (loglevel & CPU_LOG_TB_IN_ASM) {
5475 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5476 rd, u, sel, h);
5478 #endif
5479 tcg_temp_free(t0);
5480 return;
5482 die:
5483 tcg_temp_free(t0);
5484 #if defined MIPS_DEBUG_DISAS
5485 if (loglevel & CPU_LOG_TB_IN_ASM) {
5486 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5487 rd, u, sel, h);
5489 #endif
5490 generate_exception(ctx, EXCP_RI);
5493 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5495 const char *opn = "ldst";
5497 switch (opc) {
5498 case OPC_MFC0:
5499 if (rt == 0) {
5500 /* Treat as NOP. */
5501 return;
5504 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5506 gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5507 gen_store_gpr(t0, rt);
5508 tcg_temp_free(t0);
5510 opn = "mfc0";
5511 break;
5512 case OPC_MTC0:
5514 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5516 gen_load_gpr(t0, rt);
5517 save_cpu_state(ctx, 1);
5518 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5519 tcg_temp_free(t0);
5521 opn = "mtc0";
5522 break;
5523 #if defined(TARGET_MIPS64)
5524 case OPC_DMFC0:
5525 check_insn(env, ctx, ISA_MIPS3);
5526 if (rt == 0) {
5527 /* Treat as NOP. */
5528 return;
5531 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5533 gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5534 gen_store_gpr(t0, rt);
5535 tcg_temp_free(t0);
5537 opn = "dmfc0";
5538 break;
5539 case OPC_DMTC0:
5540 check_insn(env, ctx, ISA_MIPS3);
5542 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5544 gen_load_gpr(t0, rt);
5545 save_cpu_state(ctx, 1);
5546 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5547 tcg_temp_free(t0);
5549 opn = "dmtc0";
5550 break;
5551 #endif
5552 case OPC_MFTR:
5553 check_insn(env, ctx, ASE_MT);
5554 if (rd == 0) {
5555 /* Treat as NOP. */
5556 return;
5558 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5559 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5560 opn = "mftr";
5561 break;
5562 case OPC_MTTR:
5563 check_insn(env, ctx, ASE_MT);
5564 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5565 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5566 opn = "mttr";
5567 break;
5568 case OPC_TLBWI:
5569 opn = "tlbwi";
5570 if (!env->tlb->do_tlbwi)
5571 goto die;
5572 tcg_gen_helper_0_0(env->tlb->do_tlbwi);
5573 break;
5574 case OPC_TLBWR:
5575 opn = "tlbwr";
5576 if (!env->tlb->do_tlbwr)
5577 goto die;
5578 tcg_gen_helper_0_0(env->tlb->do_tlbwr);
5579 break;
5580 case OPC_TLBP:
5581 opn = "tlbp";
5582 if (!env->tlb->do_tlbp)
5583 goto die;
5584 tcg_gen_helper_0_0(env->tlb->do_tlbp);
5585 break;
5586 case OPC_TLBR:
5587 opn = "tlbr";
5588 if (!env->tlb->do_tlbr)
5589 goto die;
5590 tcg_gen_helper_0_0(env->tlb->do_tlbr);
5591 break;
5592 case OPC_ERET:
5593 opn = "eret";
5594 check_insn(env, ctx, ISA_MIPS2);
5595 save_cpu_state(ctx, 1);
5596 tcg_gen_helper_0_0(do_eret);
5597 ctx->bstate = BS_EXCP;
5598 break;
5599 case OPC_DERET:
5600 opn = "deret";
5601 check_insn(env, ctx, ISA_MIPS32);
5602 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5603 MIPS_INVAL(opn);
5604 generate_exception(ctx, EXCP_RI);
5605 } else {
5606 save_cpu_state(ctx, 1);
5607 tcg_gen_helper_0_0(do_deret);
5608 ctx->bstate = BS_EXCP;
5610 break;
5611 case OPC_WAIT:
5612 opn = "wait";
5613 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5614 /* If we get an exception, we want to restart at next instruction */
5615 ctx->pc += 4;
5616 save_cpu_state(ctx, 1);
5617 ctx->pc -= 4;
5618 tcg_gen_helper_0_0(do_wait);
5619 ctx->bstate = BS_EXCP;
5620 break;
5621 default:
5622 die:
5623 MIPS_INVAL(opn);
5624 generate_exception(ctx, EXCP_RI);
5625 return;
5627 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5629 #endif /* !CONFIG_USER_ONLY */
5631 /* CP1 Branches (before delay slot) */
5632 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5633 int32_t cc, int32_t offset)
5635 target_ulong btarget;
5636 const char *opn = "cp1 cond branch";
5637 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5638 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
5640 if (cc != 0)
5641 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5643 btarget = ctx->pc + 4 + offset;
5645 switch (op) {
5646 case OPC_BC1F:
5648 int l1 = gen_new_label();
5649 int l2 = gen_new_label();
5650 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5652 get_fp_cond(r_tmp1);
5653 tcg_gen_ext_i32_tl(t0, r_tmp1);
5654 tcg_temp_free(r_tmp1);
5655 tcg_gen_not_tl(t0, t0);
5656 tcg_gen_movi_tl(t1, 0x1 << cc);
5657 tcg_gen_and_tl(t0, t0, t1);
5658 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5659 tcg_gen_movi_tl(t0, 0);
5660 tcg_gen_br(l2);
5661 gen_set_label(l1);
5662 tcg_gen_movi_tl(t0, 1);
5663 gen_set_label(l2);
5665 opn = "bc1f";
5666 goto not_likely;
5667 case OPC_BC1FL:
5669 int l1 = gen_new_label();
5670 int l2 = gen_new_label();
5671 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5673 get_fp_cond(r_tmp1);
5674 tcg_gen_ext_i32_tl(t0, r_tmp1);
5675 tcg_temp_free(r_tmp1);
5676 tcg_gen_not_tl(t0, t0);
5677 tcg_gen_movi_tl(t1, 0x1 << cc);
5678 tcg_gen_and_tl(t0, t0, t1);
5679 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5680 tcg_gen_movi_tl(t0, 0);
5681 tcg_gen_br(l2);
5682 gen_set_label(l1);
5683 tcg_gen_movi_tl(t0, 1);
5684 gen_set_label(l2);
5686 opn = "bc1fl";
5687 goto likely;
5688 case OPC_BC1T:
5690 int l1 = gen_new_label();
5691 int l2 = gen_new_label();
5692 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5694 get_fp_cond(r_tmp1);
5695 tcg_gen_ext_i32_tl(t0, r_tmp1);
5696 tcg_temp_free(r_tmp1);
5697 tcg_gen_movi_tl(t1, 0x1 << cc);
5698 tcg_gen_and_tl(t0, t0, t1);
5699 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5700 tcg_gen_movi_tl(t0, 0);
5701 tcg_gen_br(l2);
5702 gen_set_label(l1);
5703 tcg_gen_movi_tl(t0, 1);
5704 gen_set_label(l2);
5706 opn = "bc1t";
5707 goto not_likely;
5708 case OPC_BC1TL:
5710 int l1 = gen_new_label();
5711 int l2 = gen_new_label();
5712 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5714 get_fp_cond(r_tmp1);
5715 tcg_gen_ext_i32_tl(t0, r_tmp1);
5716 tcg_temp_free(r_tmp1);
5717 tcg_gen_movi_tl(t1, 0x1 << cc);
5718 tcg_gen_and_tl(t0, t0, t1);
5719 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5720 tcg_gen_movi_tl(t0, 0);
5721 tcg_gen_br(l2);
5722 gen_set_label(l1);
5723 tcg_gen_movi_tl(t0, 1);
5724 gen_set_label(l2);
5726 opn = "bc1tl";
5727 likely:
5728 ctx->hflags |= MIPS_HFLAG_BL;
5729 tcg_gen_trunc_tl_i32(bcond, t0);
5730 break;
5731 case OPC_BC1FANY2:
5733 int l1 = gen_new_label();
5734 int l2 = gen_new_label();
5735 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5737 get_fp_cond(r_tmp1);
5738 tcg_gen_ext_i32_tl(t0, r_tmp1);
5739 tcg_temp_free(r_tmp1);
5740 tcg_gen_not_tl(t0, t0);
5741 tcg_gen_movi_tl(t1, 0x3 << cc);
5742 tcg_gen_and_tl(t0, t0, t1);
5743 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5744 tcg_gen_movi_tl(t0, 0);
5745 tcg_gen_br(l2);
5746 gen_set_label(l1);
5747 tcg_gen_movi_tl(t0, 1);
5748 gen_set_label(l2);
5750 opn = "bc1any2f";
5751 goto not_likely;
5752 case OPC_BC1TANY2:
5754 int l1 = gen_new_label();
5755 int l2 = gen_new_label();
5756 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5758 get_fp_cond(r_tmp1);
5759 tcg_gen_ext_i32_tl(t0, r_tmp1);
5760 tcg_temp_free(r_tmp1);
5761 tcg_gen_movi_tl(t1, 0x3 << cc);
5762 tcg_gen_and_tl(t0, t0, t1);
5763 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5764 tcg_gen_movi_tl(t0, 0);
5765 tcg_gen_br(l2);
5766 gen_set_label(l1);
5767 tcg_gen_movi_tl(t0, 1);
5768 gen_set_label(l2);
5770 opn = "bc1any2t";
5771 goto not_likely;
5772 case OPC_BC1FANY4:
5774 int l1 = gen_new_label();
5775 int l2 = gen_new_label();
5776 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5778 get_fp_cond(r_tmp1);
5779 tcg_gen_ext_i32_tl(t0, r_tmp1);
5780 tcg_temp_free(r_tmp1);
5781 tcg_gen_not_tl(t0, t0);
5782 tcg_gen_movi_tl(t1, 0xf << cc);
5783 tcg_gen_and_tl(t0, t0, t1);
5784 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5785 tcg_gen_movi_tl(t0, 0);
5786 tcg_gen_br(l2);
5787 gen_set_label(l1);
5788 tcg_gen_movi_tl(t0, 1);
5789 gen_set_label(l2);
5791 opn = "bc1any4f";
5792 goto not_likely;
5793 case OPC_BC1TANY4:
5795 int l1 = gen_new_label();
5796 int l2 = gen_new_label();
5797 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
5799 get_fp_cond(r_tmp1);
5800 tcg_gen_ext_i32_tl(t0, r_tmp1);
5801 tcg_temp_free(r_tmp1);
5802 tcg_gen_movi_tl(t1, 0xf << cc);
5803 tcg_gen_and_tl(t0, t0, t1);
5804 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
5805 tcg_gen_movi_tl(t0, 0);
5806 tcg_gen_br(l2);
5807 gen_set_label(l1);
5808 tcg_gen_movi_tl(t0, 1);
5809 gen_set_label(l2);
5811 opn = "bc1any4t";
5812 not_likely:
5813 ctx->hflags |= MIPS_HFLAG_BC;
5814 tcg_gen_trunc_tl_i32(bcond, t0);
5815 break;
5816 default:
5817 MIPS_INVAL(opn);
5818 generate_exception (ctx, EXCP_RI);
5819 goto out;
5821 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5822 ctx->hflags, btarget);
5823 ctx->btarget = btarget;
5825 out:
5826 tcg_temp_free(t0);
5827 tcg_temp_free(t1);
5830 /* Coprocessor 1 (FPU) */
5832 #define FOP(func, fmt) (((fmt) << 21) | (func))
5834 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5836 const char *opn = "cp1 move";
5837 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5839 switch (opc) {
5840 case OPC_MFC1:
5842 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5844 gen_load_fpr32(fp0, fs);
5845 tcg_gen_ext_i32_tl(t0, fp0);
5846 tcg_temp_free(fp0);
5848 gen_store_gpr(t0, rt);
5849 opn = "mfc1";
5850 break;
5851 case OPC_MTC1:
5852 gen_load_gpr(t0, rt);
5854 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5856 tcg_gen_trunc_tl_i32(fp0, t0);
5857 gen_store_fpr32(fp0, fs);
5858 tcg_temp_free(fp0);
5860 opn = "mtc1";
5861 break;
5862 case OPC_CFC1:
5863 tcg_gen_helper_1_i(do_cfc1, t0, fs);
5864 gen_store_gpr(t0, rt);
5865 opn = "cfc1";
5866 break;
5867 case OPC_CTC1:
5868 gen_load_gpr(t0, rt);
5869 tcg_gen_helper_0_1i(do_ctc1, t0, fs);
5870 opn = "ctc1";
5871 break;
5872 case OPC_DMFC1:
5874 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
5876 gen_load_fpr64(ctx, fp0, fs);
5877 tcg_gen_mov_tl(t0, fp0);
5878 tcg_temp_free(fp0);
5880 gen_store_gpr(t0, rt);
5881 opn = "dmfc1";
5882 break;
5883 case OPC_DMTC1:
5884 gen_load_gpr(t0, rt);
5886 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
5888 tcg_gen_mov_tl(fp0, t0);
5889 gen_store_fpr64(ctx, fp0, fs);
5890 tcg_temp_free(fp0);
5892 opn = "dmtc1";
5893 break;
5894 case OPC_MFHC1:
5896 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5898 gen_load_fpr32h(fp0, fs);
5899 tcg_gen_ext_i32_tl(t0, fp0);
5900 tcg_temp_free(fp0);
5902 gen_store_gpr(t0, rt);
5903 opn = "mfhc1";
5904 break;
5905 case OPC_MTHC1:
5906 gen_load_gpr(t0, rt);
5908 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5910 tcg_gen_trunc_tl_i32(fp0, t0);
5911 gen_store_fpr32h(fp0, fs);
5912 tcg_temp_free(fp0);
5914 opn = "mthc1";
5915 break;
5916 default:
5917 MIPS_INVAL(opn);
5918 generate_exception (ctx, EXCP_RI);
5919 goto out;
5921 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5923 out:
5924 tcg_temp_free(t0);
5927 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5929 int l1 = gen_new_label();
5930 uint32_t ccbit;
5931 TCGCond cond;
5932 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5933 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
5934 TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_I32);
5936 if (cc)
5937 ccbit = 1 << (24 + cc);
5938 else
5939 ccbit = 1 << 23;
5940 if (tf)
5941 cond = TCG_COND_EQ;
5942 else
5943 cond = TCG_COND_NE;
5945 gen_load_gpr(t0, rd);
5946 gen_load_gpr(t1, rs);
5947 tcg_gen_andi_i32(r_tmp, fpu_fcr31, ccbit);
5948 tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
5949 tcg_temp_free(r_tmp);
5951 tcg_gen_mov_tl(t0, t1);
5952 tcg_temp_free(t1);
5954 gen_set_label(l1);
5955 gen_store_gpr(t0, rd);
5956 tcg_temp_free(t0);
5959 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5961 uint32_t ccbit;
5962 int cond;
5963 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
5964 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
5965 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
5966 int l1 = gen_new_label();
5968 if (cc)
5969 ccbit = 1 << (24 + cc);
5970 else
5971 ccbit = 1 << 23;
5973 if (tf)
5974 cond = TCG_COND_EQ;
5975 else
5976 cond = TCG_COND_NE;
5978 gen_load_fpr32(fp0, fs);
5979 gen_load_fpr32(fp1, fd);
5980 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
5981 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
5982 tcg_gen_mov_i32(fp1, fp0);
5983 tcg_temp_free(fp0);
5984 gen_set_label(l1);
5985 tcg_temp_free(r_tmp1);
5986 gen_store_fpr32(fp1, fd);
5987 tcg_temp_free(fp1);
5990 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5992 uint32_t ccbit;
5993 int cond;
5994 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
5995 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
5996 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I64);
5997 int l1 = gen_new_label();
5999 if (cc)
6000 ccbit = 1 << (24 + cc);
6001 else
6002 ccbit = 1 << 23;
6004 if (tf)
6005 cond = TCG_COND_EQ;
6006 else
6007 cond = TCG_COND_NE;
6009 gen_load_fpr64(ctx, fp0, fs);
6010 gen_load_fpr64(ctx, fp1, fd);
6011 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
6012 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
6013 tcg_gen_mov_i64(fp1, fp0);
6014 tcg_temp_free(fp0);
6015 gen_set_label(l1);
6016 tcg_temp_free(r_tmp1);
6017 gen_store_fpr64(ctx, fp1, fd);
6018 tcg_temp_free(fp1);
6021 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6023 int cond;
6024 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
6025 TCGv r_tmp2 = tcg_temp_local_new(TCG_TYPE_I32);
6026 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6027 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
6028 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
6029 TCGv fph1 = tcg_temp_local_new(TCG_TYPE_I32);
6030 int l1 = gen_new_label();
6031 int l2 = gen_new_label();
6033 if (tf)
6034 cond = TCG_COND_EQ;
6035 else
6036 cond = TCG_COND_NE;
6038 gen_load_fpr32(fp0, fs);
6039 gen_load_fpr32h(fph0, fs);
6040 gen_load_fpr32(fp1, fd);
6041 gen_load_fpr32h(fph1, fd);
6042 get_fp_cond(r_tmp1);
6043 tcg_gen_shri_i32(r_tmp1, r_tmp1, cc);
6044 tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x1);
6045 tcg_gen_brcondi_i32(cond, r_tmp2, 0, l1);
6046 tcg_gen_mov_i32(fp1, fp0);
6047 tcg_temp_free(fp0);
6048 gen_set_label(l1);
6049 tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x2);
6050 tcg_gen_brcondi_i32(cond, r_tmp2, 0, l2);
6051 tcg_gen_mov_i32(fph1, fph0);
6052 tcg_temp_free(fph0);
6053 gen_set_label(l2);
6054 tcg_temp_free(r_tmp1);
6055 tcg_temp_free(r_tmp2);
6056 gen_store_fpr32(fp1, fd);
6057 gen_store_fpr32h(fph1, fd);
6058 tcg_temp_free(fp1);
6059 tcg_temp_free(fph1);
6063 static void gen_farith (DisasContext *ctx, uint32_t op1,
6064 int ft, int fs, int fd, int cc)
6066 const char *opn = "farith";
6067 const char *condnames[] = {
6068 "c.f",
6069 "c.un",
6070 "c.eq",
6071 "c.ueq",
6072 "c.olt",
6073 "c.ult",
6074 "c.ole",
6075 "c.ule",
6076 "c.sf",
6077 "c.ngle",
6078 "c.seq",
6079 "c.ngl",
6080 "c.lt",
6081 "c.nge",
6082 "c.le",
6083 "c.ngt",
6085 const char *condnames_abs[] = {
6086 "cabs.f",
6087 "cabs.un",
6088 "cabs.eq",
6089 "cabs.ueq",
6090 "cabs.olt",
6091 "cabs.ult",
6092 "cabs.ole",
6093 "cabs.ule",
6094 "cabs.sf",
6095 "cabs.ngle",
6096 "cabs.seq",
6097 "cabs.ngl",
6098 "cabs.lt",
6099 "cabs.nge",
6100 "cabs.le",
6101 "cabs.ngt",
6103 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6104 uint32_t func = ctx->opcode & 0x3f;
6106 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
6107 case FOP(0, 16):
6109 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6110 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6112 gen_load_fpr32(fp0, fs);
6113 gen_load_fpr32(fp1, ft);
6114 tcg_gen_helper_1_2(do_float_add_s, fp0, fp0, fp1);
6115 tcg_temp_free(fp1);
6116 gen_store_fpr32(fp0, fd);
6117 tcg_temp_free(fp0);
6119 opn = "add.s";
6120 optype = BINOP;
6121 break;
6122 case FOP(1, 16):
6124 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6125 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6127 gen_load_fpr32(fp0, fs);
6128 gen_load_fpr32(fp1, ft);
6129 tcg_gen_helper_1_2(do_float_sub_s, fp0, fp0, fp1);
6130 tcg_temp_free(fp1);
6131 gen_store_fpr32(fp0, fd);
6132 tcg_temp_free(fp0);
6134 opn = "sub.s";
6135 optype = BINOP;
6136 break;
6137 case FOP(2, 16):
6139 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6140 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6142 gen_load_fpr32(fp0, fs);
6143 gen_load_fpr32(fp1, ft);
6144 tcg_gen_helper_1_2(do_float_mul_s, fp0, fp0, fp1);
6145 tcg_temp_free(fp1);
6146 gen_store_fpr32(fp0, fd);
6147 tcg_temp_free(fp0);
6149 opn = "mul.s";
6150 optype = BINOP;
6151 break;
6152 case FOP(3, 16):
6154 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6155 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6157 gen_load_fpr32(fp0, fs);
6158 gen_load_fpr32(fp1, ft);
6159 tcg_gen_helper_1_2(do_float_div_s, fp0, fp0, fp1);
6160 tcg_temp_free(fp1);
6161 gen_store_fpr32(fp0, fd);
6162 tcg_temp_free(fp0);
6164 opn = "div.s";
6165 optype = BINOP;
6166 break;
6167 case FOP(4, 16):
6169 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6171 gen_load_fpr32(fp0, fs);
6172 tcg_gen_helper_1_1(do_float_sqrt_s, fp0, fp0);
6173 gen_store_fpr32(fp0, fd);
6174 tcg_temp_free(fp0);
6176 opn = "sqrt.s";
6177 break;
6178 case FOP(5, 16):
6180 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6182 gen_load_fpr32(fp0, fs);
6183 tcg_gen_helper_1_1(do_float_abs_s, fp0, fp0);
6184 gen_store_fpr32(fp0, fd);
6185 tcg_temp_free(fp0);
6187 opn = "abs.s";
6188 break;
6189 case FOP(6, 16):
6191 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6193 gen_load_fpr32(fp0, fs);
6194 gen_store_fpr32(fp0, fd);
6195 tcg_temp_free(fp0);
6197 opn = "mov.s";
6198 break;
6199 case FOP(7, 16):
6201 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6203 gen_load_fpr32(fp0, fs);
6204 tcg_gen_helper_1_1(do_float_chs_s, fp0, fp0);
6205 gen_store_fpr32(fp0, fd);
6206 tcg_temp_free(fp0);
6208 opn = "neg.s";
6209 break;
6210 case FOP(8, 16):
6211 check_cp1_64bitmode(ctx);
6213 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6214 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6216 gen_load_fpr32(fp32, fs);
6217 tcg_gen_helper_1_1(do_float_roundl_s, fp64, fp32);
6218 tcg_temp_free(fp32);
6219 gen_store_fpr64(ctx, fp64, fd);
6220 tcg_temp_free(fp64);
6222 opn = "round.l.s";
6223 break;
6224 case FOP(9, 16):
6225 check_cp1_64bitmode(ctx);
6227 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6228 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6230 gen_load_fpr32(fp32, fs);
6231 tcg_gen_helper_1_1(do_float_truncl_s, fp64, fp32);
6232 tcg_temp_free(fp32);
6233 gen_store_fpr64(ctx, fp64, fd);
6234 tcg_temp_free(fp64);
6236 opn = "trunc.l.s";
6237 break;
6238 case FOP(10, 16):
6239 check_cp1_64bitmode(ctx);
6241 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6242 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6244 gen_load_fpr32(fp32, fs);
6245 tcg_gen_helper_1_1(do_float_ceill_s, fp64, fp32);
6246 tcg_temp_free(fp32);
6247 gen_store_fpr64(ctx, fp64, fd);
6248 tcg_temp_free(fp64);
6250 opn = "ceil.l.s";
6251 break;
6252 case FOP(11, 16):
6253 check_cp1_64bitmode(ctx);
6255 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6256 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6258 gen_load_fpr32(fp32, fs);
6259 tcg_gen_helper_1_1(do_float_floorl_s, fp64, fp32);
6260 tcg_temp_free(fp32);
6261 gen_store_fpr64(ctx, fp64, fd);
6262 tcg_temp_free(fp64);
6264 opn = "floor.l.s";
6265 break;
6266 case FOP(12, 16):
6268 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6270 gen_load_fpr32(fp0, fs);
6271 tcg_gen_helper_1_1(do_float_roundw_s, fp0, fp0);
6272 gen_store_fpr32(fp0, fd);
6273 tcg_temp_free(fp0);
6275 opn = "round.w.s";
6276 break;
6277 case FOP(13, 16):
6279 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6281 gen_load_fpr32(fp0, fs);
6282 tcg_gen_helper_1_1(do_float_truncw_s, fp0, fp0);
6283 gen_store_fpr32(fp0, fd);
6284 tcg_temp_free(fp0);
6286 opn = "trunc.w.s";
6287 break;
6288 case FOP(14, 16):
6290 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6292 gen_load_fpr32(fp0, fs);
6293 tcg_gen_helper_1_1(do_float_ceilw_s, fp0, fp0);
6294 gen_store_fpr32(fp0, fd);
6295 tcg_temp_free(fp0);
6297 opn = "ceil.w.s";
6298 break;
6299 case FOP(15, 16):
6301 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6303 gen_load_fpr32(fp0, fs);
6304 tcg_gen_helper_1_1(do_float_floorw_s, fp0, fp0);
6305 gen_store_fpr32(fp0, fd);
6306 tcg_temp_free(fp0);
6308 opn = "floor.w.s";
6309 break;
6310 case FOP(17, 16):
6311 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6312 opn = "movcf.s";
6313 break;
6314 case FOP(18, 16):
6316 int l1 = gen_new_label();
6317 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6318 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6320 gen_load_gpr(t0, ft);
6321 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6322 tcg_temp_free(t0);
6323 gen_load_fpr32(fp0, fs);
6324 gen_store_fpr32(fp0, fd);
6325 tcg_temp_free(fp0);
6326 gen_set_label(l1);
6328 opn = "movz.s";
6329 break;
6330 case FOP(19, 16):
6332 int l1 = gen_new_label();
6333 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6334 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
6336 gen_load_gpr(t0, ft);
6337 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6338 tcg_temp_free(t0);
6339 gen_load_fpr32(fp0, fs);
6340 gen_store_fpr32(fp0, fd);
6341 tcg_temp_free(fp0);
6342 gen_set_label(l1);
6344 opn = "movn.s";
6345 break;
6346 case FOP(21, 16):
6347 check_cop1x(ctx);
6349 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6351 gen_load_fpr32(fp0, fs);
6352 tcg_gen_helper_1_1(do_float_recip_s, fp0, fp0);
6353 gen_store_fpr32(fp0, fd);
6354 tcg_temp_free(fp0);
6356 opn = "recip.s";
6357 break;
6358 case FOP(22, 16):
6359 check_cop1x(ctx);
6361 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6363 gen_load_fpr32(fp0, fs);
6364 tcg_gen_helper_1_1(do_float_rsqrt_s, fp0, fp0);
6365 gen_store_fpr32(fp0, fd);
6366 tcg_temp_free(fp0);
6368 opn = "rsqrt.s";
6369 break;
6370 case FOP(28, 16):
6371 check_cp1_64bitmode(ctx);
6373 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6374 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6376 gen_load_fpr32(fp0, fs);
6377 gen_load_fpr32(fp1, fd);
6378 tcg_gen_helper_1_2(do_float_recip2_s, fp0, fp0, fp1);
6379 tcg_temp_free(fp1);
6380 gen_store_fpr32(fp0, fd);
6381 tcg_temp_free(fp0);
6383 opn = "recip2.s";
6384 break;
6385 case FOP(29, 16):
6386 check_cp1_64bitmode(ctx);
6388 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6390 gen_load_fpr32(fp0, fs);
6391 tcg_gen_helper_1_1(do_float_recip1_s, fp0, fp0);
6392 gen_store_fpr32(fp0, fd);
6393 tcg_temp_free(fp0);
6395 opn = "recip1.s";
6396 break;
6397 case FOP(30, 16):
6398 check_cp1_64bitmode(ctx);
6400 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6402 gen_load_fpr32(fp0, fs);
6403 tcg_gen_helper_1_1(do_float_rsqrt1_s, fp0, fp0);
6404 gen_store_fpr32(fp0, fd);
6405 tcg_temp_free(fp0);
6407 opn = "rsqrt1.s";
6408 break;
6409 case FOP(31, 16):
6410 check_cp1_64bitmode(ctx);
6412 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6413 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6415 gen_load_fpr32(fp0, fs);
6416 gen_load_fpr32(fp1, ft);
6417 tcg_gen_helper_1_2(do_float_rsqrt2_s, fp0, fp0, fp1);
6418 tcg_temp_free(fp1);
6419 gen_store_fpr32(fp0, fd);
6420 tcg_temp_free(fp0);
6422 opn = "rsqrt2.s";
6423 break;
6424 case FOP(33, 16):
6425 check_cp1_registers(ctx, fd);
6427 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6428 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6430 gen_load_fpr32(fp32, fs);
6431 tcg_gen_helper_1_1(do_float_cvtd_s, fp64, fp32);
6432 tcg_temp_free(fp32);
6433 gen_store_fpr64(ctx, fp64, fd);
6434 tcg_temp_free(fp64);
6436 opn = "cvt.d.s";
6437 break;
6438 case FOP(36, 16):
6440 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6442 gen_load_fpr32(fp0, fs);
6443 tcg_gen_helper_1_1(do_float_cvtw_s, fp0, fp0);
6444 gen_store_fpr32(fp0, fd);
6445 tcg_temp_free(fp0);
6447 opn = "cvt.w.s";
6448 break;
6449 case FOP(37, 16):
6450 check_cp1_64bitmode(ctx);
6452 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6453 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6455 gen_load_fpr32(fp32, fs);
6456 tcg_gen_helper_1_1(do_float_cvtl_s, fp64, fp32);
6457 tcg_temp_free(fp32);
6458 gen_store_fpr64(ctx, fp64, fd);
6459 tcg_temp_free(fp64);
6461 opn = "cvt.l.s";
6462 break;
6463 case FOP(38, 16):
6464 check_cp1_64bitmode(ctx);
6466 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6467 TCGv fp32_0 = tcg_temp_new(TCG_TYPE_I32);
6468 TCGv fp32_1 = tcg_temp_new(TCG_TYPE_I32);
6470 gen_load_fpr32(fp32_0, fs);
6471 gen_load_fpr32(fp32_1, ft);
6472 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6473 tcg_temp_free(fp32_1);
6474 tcg_temp_free(fp32_0);
6475 gen_store_fpr64(ctx, fp64, fd);
6476 tcg_temp_free(fp64);
6478 opn = "cvt.ps.s";
6479 break;
6480 case FOP(48, 16):
6481 case FOP(49, 16):
6482 case FOP(50, 16):
6483 case FOP(51, 16):
6484 case FOP(52, 16):
6485 case FOP(53, 16):
6486 case FOP(54, 16):
6487 case FOP(55, 16):
6488 case FOP(56, 16):
6489 case FOP(57, 16):
6490 case FOP(58, 16):
6491 case FOP(59, 16):
6492 case FOP(60, 16):
6493 case FOP(61, 16):
6494 case FOP(62, 16):
6495 case FOP(63, 16):
6497 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6498 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6500 gen_load_fpr32(fp0, fs);
6501 gen_load_fpr32(fp1, ft);
6502 if (ctx->opcode & (1 << 6)) {
6503 check_cop1x(ctx);
6504 gen_cmpabs_s(func-48, fp0, fp1, cc);
6505 opn = condnames_abs[func-48];
6506 } else {
6507 gen_cmp_s(func-48, fp0, fp1, cc);
6508 opn = condnames[func-48];
6510 tcg_temp_free(fp0);
6511 tcg_temp_free(fp1);
6513 break;
6514 case FOP(0, 17):
6515 check_cp1_registers(ctx, fs | ft | fd);
6517 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6518 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6520 gen_load_fpr64(ctx, fp0, fs);
6521 gen_load_fpr64(ctx, fp1, ft);
6522 tcg_gen_helper_1_2(do_float_add_d, fp0, fp0, fp1);
6523 tcg_temp_free(fp1);
6524 gen_store_fpr64(ctx, fp0, fd);
6525 tcg_temp_free(fp0);
6527 opn = "add.d";
6528 optype = BINOP;
6529 break;
6530 case FOP(1, 17):
6531 check_cp1_registers(ctx, fs | ft | fd);
6533 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6534 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6536 gen_load_fpr64(ctx, fp0, fs);
6537 gen_load_fpr64(ctx, fp1, ft);
6538 tcg_gen_helper_1_2(do_float_sub_d, fp0, fp0, fp1);
6539 tcg_temp_free(fp1);
6540 gen_store_fpr64(ctx, fp0, fd);
6541 tcg_temp_free(fp0);
6543 opn = "sub.d";
6544 optype = BINOP;
6545 break;
6546 case FOP(2, 17):
6547 check_cp1_registers(ctx, fs | ft | fd);
6549 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6550 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6552 gen_load_fpr64(ctx, fp0, fs);
6553 gen_load_fpr64(ctx, fp1, ft);
6554 tcg_gen_helper_1_2(do_float_mul_d, fp0, fp0, fp1);
6555 tcg_temp_free(fp1);
6556 gen_store_fpr64(ctx, fp0, fd);
6557 tcg_temp_free(fp0);
6559 opn = "mul.d";
6560 optype = BINOP;
6561 break;
6562 case FOP(3, 17):
6563 check_cp1_registers(ctx, fs | ft | fd);
6565 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6566 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6568 gen_load_fpr64(ctx, fp0, fs);
6569 gen_load_fpr64(ctx, fp1, ft);
6570 tcg_gen_helper_1_2(do_float_div_d, fp0, fp0, fp1);
6571 tcg_temp_free(fp1);
6572 gen_store_fpr64(ctx, fp0, fd);
6573 tcg_temp_free(fp0);
6575 opn = "div.d";
6576 optype = BINOP;
6577 break;
6578 case FOP(4, 17):
6579 check_cp1_registers(ctx, fs | fd);
6581 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6583 gen_load_fpr64(ctx, fp0, fs);
6584 tcg_gen_helper_1_1(do_float_sqrt_d, fp0, fp0);
6585 gen_store_fpr64(ctx, fp0, fd);
6586 tcg_temp_free(fp0);
6588 opn = "sqrt.d";
6589 break;
6590 case FOP(5, 17):
6591 check_cp1_registers(ctx, fs | fd);
6593 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6595 gen_load_fpr64(ctx, fp0, fs);
6596 tcg_gen_helper_1_1(do_float_abs_d, fp0, fp0);
6597 gen_store_fpr64(ctx, fp0, fd);
6598 tcg_temp_free(fp0);
6600 opn = "abs.d";
6601 break;
6602 case FOP(6, 17):
6603 check_cp1_registers(ctx, fs | fd);
6605 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6607 gen_load_fpr64(ctx, fp0, fs);
6608 gen_store_fpr64(ctx, fp0, fd);
6609 tcg_temp_free(fp0);
6611 opn = "mov.d";
6612 break;
6613 case FOP(7, 17):
6614 check_cp1_registers(ctx, fs | fd);
6616 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6618 gen_load_fpr64(ctx, fp0, fs);
6619 tcg_gen_helper_1_1(do_float_chs_d, fp0, fp0);
6620 gen_store_fpr64(ctx, fp0, fd);
6621 tcg_temp_free(fp0);
6623 opn = "neg.d";
6624 break;
6625 case FOP(8, 17):
6626 check_cp1_64bitmode(ctx);
6628 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6630 gen_load_fpr64(ctx, fp0, fs);
6631 tcg_gen_helper_1_1(do_float_roundl_d, fp0, fp0);
6632 gen_store_fpr64(ctx, fp0, fd);
6633 tcg_temp_free(fp0);
6635 opn = "round.l.d";
6636 break;
6637 case FOP(9, 17):
6638 check_cp1_64bitmode(ctx);
6640 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6642 gen_load_fpr64(ctx, fp0, fs);
6643 tcg_gen_helper_1_1(do_float_truncl_d, fp0, fp0);
6644 gen_store_fpr64(ctx, fp0, fd);
6645 tcg_temp_free(fp0);
6647 opn = "trunc.l.d";
6648 break;
6649 case FOP(10, 17):
6650 check_cp1_64bitmode(ctx);
6652 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6654 gen_load_fpr64(ctx, fp0, fs);
6655 tcg_gen_helper_1_1(do_float_ceill_d, fp0, fp0);
6656 gen_store_fpr64(ctx, fp0, fd);
6657 tcg_temp_free(fp0);
6659 opn = "ceil.l.d";
6660 break;
6661 case FOP(11, 17):
6662 check_cp1_64bitmode(ctx);
6664 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6666 gen_load_fpr64(ctx, fp0, fs);
6667 tcg_gen_helper_1_1(do_float_floorl_d, fp0, fp0);
6668 gen_store_fpr64(ctx, fp0, fd);
6669 tcg_temp_free(fp0);
6671 opn = "floor.l.d";
6672 break;
6673 case FOP(12, 17):
6674 check_cp1_registers(ctx, fs);
6676 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6677 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6679 gen_load_fpr64(ctx, fp64, fs);
6680 tcg_gen_helper_1_1(do_float_roundw_d, fp32, fp64);
6681 tcg_temp_free(fp64);
6682 gen_store_fpr32(fp32, fd);
6683 tcg_temp_free(fp32);
6685 opn = "round.w.d";
6686 break;
6687 case FOP(13, 17):
6688 check_cp1_registers(ctx, fs);
6690 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6691 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6693 gen_load_fpr64(ctx, fp64, fs);
6694 tcg_gen_helper_1_1(do_float_truncw_d, fp32, fp64);
6695 tcg_temp_free(fp64);
6696 gen_store_fpr32(fp32, fd);
6697 tcg_temp_free(fp32);
6699 opn = "trunc.w.d";
6700 break;
6701 case FOP(14, 17):
6702 check_cp1_registers(ctx, fs);
6704 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6705 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6707 gen_load_fpr64(ctx, fp64, fs);
6708 tcg_gen_helper_1_1(do_float_ceilw_d, fp32, fp64);
6709 tcg_temp_free(fp64);
6710 gen_store_fpr32(fp32, fd);
6711 tcg_temp_free(fp32);
6713 opn = "ceil.w.d";
6714 break;
6715 case FOP(15, 17):
6716 check_cp1_registers(ctx, fs);
6718 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6719 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6721 gen_load_fpr64(ctx, fp64, fs);
6722 tcg_gen_helper_1_1(do_float_floorw_d, fp32, fp64);
6723 tcg_temp_free(fp64);
6724 gen_store_fpr32(fp32, fd);
6725 tcg_temp_free(fp32);
6727 opn = "floor.w.d";
6728 break;
6729 case FOP(17, 17):
6730 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6731 opn = "movcf.d";
6732 break;
6733 case FOP(18, 17):
6735 int l1 = gen_new_label();
6736 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6737 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
6739 gen_load_gpr(t0, ft);
6740 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
6741 tcg_temp_free(t0);
6742 gen_load_fpr64(ctx, fp0, fs);
6743 gen_store_fpr64(ctx, fp0, fd);
6744 tcg_temp_free(fp0);
6745 gen_set_label(l1);
6747 opn = "movz.d";
6748 break;
6749 case FOP(19, 17):
6751 int l1 = gen_new_label();
6752 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6753 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
6755 gen_load_gpr(t0, ft);
6756 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
6757 tcg_temp_free(t0);
6758 gen_load_fpr64(ctx, fp0, fs);
6759 gen_store_fpr64(ctx, fp0, fd);
6760 tcg_temp_free(fp0);
6761 gen_set_label(l1);
6763 opn = "movn.d";
6764 break;
6765 case FOP(21, 17):
6766 check_cp1_64bitmode(ctx);
6768 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6770 gen_load_fpr64(ctx, fp0, fs);
6771 tcg_gen_helper_1_1(do_float_recip_d, fp0, fp0);
6772 gen_store_fpr64(ctx, fp0, fd);
6773 tcg_temp_free(fp0);
6775 opn = "recip.d";
6776 break;
6777 case FOP(22, 17):
6778 check_cp1_64bitmode(ctx);
6780 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6782 gen_load_fpr64(ctx, fp0, fs);
6783 tcg_gen_helper_1_1(do_float_rsqrt_d, fp0, fp0);
6784 gen_store_fpr64(ctx, fp0, fd);
6785 tcg_temp_free(fp0);
6787 opn = "rsqrt.d";
6788 break;
6789 case FOP(28, 17):
6790 check_cp1_64bitmode(ctx);
6792 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6793 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6795 gen_load_fpr64(ctx, fp0, fs);
6796 gen_load_fpr64(ctx, fp1, ft);
6797 tcg_gen_helper_1_2(do_float_recip2_d, fp0, fp0, fp1);
6798 tcg_temp_free(fp1);
6799 gen_store_fpr64(ctx, fp0, fd);
6800 tcg_temp_free(fp0);
6802 opn = "recip2.d";
6803 break;
6804 case FOP(29, 17):
6805 check_cp1_64bitmode(ctx);
6807 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6809 gen_load_fpr64(ctx, fp0, fs);
6810 tcg_gen_helper_1_1(do_float_recip1_d, fp0, fp0);
6811 gen_store_fpr64(ctx, fp0, fd);
6812 tcg_temp_free(fp0);
6814 opn = "recip1.d";
6815 break;
6816 case FOP(30, 17):
6817 check_cp1_64bitmode(ctx);
6819 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6821 gen_load_fpr64(ctx, fp0, fs);
6822 tcg_gen_helper_1_1(do_float_rsqrt1_d, fp0, fp0);
6823 gen_store_fpr64(ctx, fp0, fd);
6824 tcg_temp_free(fp0);
6826 opn = "rsqrt1.d";
6827 break;
6828 case FOP(31, 17):
6829 check_cp1_64bitmode(ctx);
6831 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6832 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6834 gen_load_fpr64(ctx, fp0, fs);
6835 gen_load_fpr64(ctx, fp1, ft);
6836 tcg_gen_helper_1_2(do_float_rsqrt2_d, fp0, fp0, fp1);
6837 tcg_temp_free(fp1);
6838 gen_store_fpr64(ctx, fp0, fd);
6839 tcg_temp_free(fp0);
6841 opn = "rsqrt2.d";
6842 break;
6843 case FOP(48, 17):
6844 case FOP(49, 17):
6845 case FOP(50, 17):
6846 case FOP(51, 17):
6847 case FOP(52, 17):
6848 case FOP(53, 17):
6849 case FOP(54, 17):
6850 case FOP(55, 17):
6851 case FOP(56, 17):
6852 case FOP(57, 17):
6853 case FOP(58, 17):
6854 case FOP(59, 17):
6855 case FOP(60, 17):
6856 case FOP(61, 17):
6857 case FOP(62, 17):
6858 case FOP(63, 17):
6860 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6861 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6863 gen_load_fpr64(ctx, fp0, fs);
6864 gen_load_fpr64(ctx, fp1, ft);
6865 if (ctx->opcode & (1 << 6)) {
6866 check_cop1x(ctx);
6867 check_cp1_registers(ctx, fs | ft);
6868 gen_cmpabs_d(func-48, fp0, fp1, cc);
6869 opn = condnames_abs[func-48];
6870 } else {
6871 check_cp1_registers(ctx, fs | ft);
6872 gen_cmp_d(func-48, fp0, fp1, cc);
6873 opn = condnames[func-48];
6875 tcg_temp_free(fp0);
6876 tcg_temp_free(fp1);
6878 break;
6879 case FOP(32, 17):
6880 check_cp1_registers(ctx, fs);
6882 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6883 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6885 gen_load_fpr64(ctx, fp64, fs);
6886 tcg_gen_helper_1_1(do_float_cvts_d, fp32, fp64);
6887 tcg_temp_free(fp64);
6888 gen_store_fpr32(fp32, fd);
6889 tcg_temp_free(fp32);
6891 opn = "cvt.s.d";
6892 break;
6893 case FOP(36, 17):
6894 check_cp1_registers(ctx, fs);
6896 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6897 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6899 gen_load_fpr64(ctx, fp64, fs);
6900 tcg_gen_helper_1_1(do_float_cvtw_d, fp32, fp64);
6901 tcg_temp_free(fp64);
6902 gen_store_fpr32(fp32, fd);
6903 tcg_temp_free(fp32);
6905 opn = "cvt.w.d";
6906 break;
6907 case FOP(37, 17):
6908 check_cp1_64bitmode(ctx);
6910 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6912 gen_load_fpr64(ctx, fp0, fs);
6913 tcg_gen_helper_1_1(do_float_cvtl_d, fp0, fp0);
6914 gen_store_fpr64(ctx, fp0, fd);
6915 tcg_temp_free(fp0);
6917 opn = "cvt.l.d";
6918 break;
6919 case FOP(32, 20):
6921 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6923 gen_load_fpr32(fp0, fs);
6924 tcg_gen_helper_1_1(do_float_cvts_w, fp0, fp0);
6925 gen_store_fpr32(fp0, fd);
6926 tcg_temp_free(fp0);
6928 opn = "cvt.s.w";
6929 break;
6930 case FOP(33, 20):
6931 check_cp1_registers(ctx, fd);
6933 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6934 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6936 gen_load_fpr32(fp32, fs);
6937 tcg_gen_helper_1_1(do_float_cvtd_w, fp64, fp32);
6938 tcg_temp_free(fp32);
6939 gen_store_fpr64(ctx, fp64, fd);
6940 tcg_temp_free(fp64);
6942 opn = "cvt.d.w";
6943 break;
6944 case FOP(32, 21):
6945 check_cp1_64bitmode(ctx);
6947 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6948 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6950 gen_load_fpr64(ctx, fp64, fs);
6951 tcg_gen_helper_1_1(do_float_cvts_l, fp32, fp64);
6952 tcg_temp_free(fp64);
6953 gen_store_fpr32(fp32, fd);
6954 tcg_temp_free(fp32);
6956 opn = "cvt.s.l";
6957 break;
6958 case FOP(33, 21):
6959 check_cp1_64bitmode(ctx);
6961 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6963 gen_load_fpr64(ctx, fp0, fs);
6964 tcg_gen_helper_1_1(do_float_cvtd_l, fp0, fp0);
6965 gen_store_fpr64(ctx, fp0, fd);
6966 tcg_temp_free(fp0);
6968 opn = "cvt.d.l";
6969 break;
6970 case FOP(38, 20):
6971 check_cp1_64bitmode(ctx);
6973 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6975 gen_load_fpr64(ctx, fp0, fs);
6976 tcg_gen_helper_1_1(do_float_cvtps_pw, fp0, fp0);
6977 gen_store_fpr64(ctx, fp0, fd);
6978 tcg_temp_free(fp0);
6980 opn = "cvt.ps.pw";
6981 break;
6982 case FOP(0, 22):
6983 check_cp1_64bitmode(ctx);
6985 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6986 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6988 gen_load_fpr64(ctx, fp0, fs);
6989 gen_load_fpr64(ctx, fp1, ft);
6990 tcg_gen_helper_1_2(do_float_add_ps, fp0, fp0, fp1);
6991 tcg_temp_free(fp1);
6992 gen_store_fpr64(ctx, fp0, fd);
6993 tcg_temp_free(fp0);
6995 opn = "add.ps";
6996 break;
6997 case FOP(1, 22):
6998 check_cp1_64bitmode(ctx);
7000 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7001 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7003 gen_load_fpr64(ctx, fp0, fs);
7004 gen_load_fpr64(ctx, fp1, ft);
7005 tcg_gen_helper_1_2(do_float_sub_ps, fp0, fp0, fp1);
7006 tcg_temp_free(fp1);
7007 gen_store_fpr64(ctx, fp0, fd);
7008 tcg_temp_free(fp0);
7010 opn = "sub.ps";
7011 break;
7012 case FOP(2, 22):
7013 check_cp1_64bitmode(ctx);
7015 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7016 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7018 gen_load_fpr64(ctx, fp0, fs);
7019 gen_load_fpr64(ctx, fp1, ft);
7020 tcg_gen_helper_1_2(do_float_mul_ps, fp0, fp0, fp1);
7021 tcg_temp_free(fp1);
7022 gen_store_fpr64(ctx, fp0, fd);
7023 tcg_temp_free(fp0);
7025 opn = "mul.ps";
7026 break;
7027 case FOP(5, 22):
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_abs_ps, fp0, fp0);
7034 gen_store_fpr64(ctx, fp0, fd);
7035 tcg_temp_free(fp0);
7037 opn = "abs.ps";
7038 break;
7039 case FOP(6, 22):
7040 check_cp1_64bitmode(ctx);
7042 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7044 gen_load_fpr64(ctx, fp0, fs);
7045 gen_store_fpr64(ctx, fp0, fd);
7046 tcg_temp_free(fp0);
7048 opn = "mov.ps";
7049 break;
7050 case FOP(7, 22):
7051 check_cp1_64bitmode(ctx);
7053 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7055 gen_load_fpr64(ctx, fp0, fs);
7056 tcg_gen_helper_1_1(do_float_chs_ps, fp0, fp0);
7057 gen_store_fpr64(ctx, fp0, fd);
7058 tcg_temp_free(fp0);
7060 opn = "neg.ps";
7061 break;
7062 case FOP(17, 22):
7063 check_cp1_64bitmode(ctx);
7064 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7065 opn = "movcf.ps";
7066 break;
7067 case FOP(18, 22):
7068 check_cp1_64bitmode(ctx);
7070 int l1 = gen_new_label();
7071 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7072 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7073 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7075 gen_load_gpr(t0, ft);
7076 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7077 tcg_temp_free(t0);
7078 gen_load_fpr32(fp0, fs);
7079 gen_load_fpr32h(fph0, fs);
7080 gen_store_fpr32(fp0, fd);
7081 gen_store_fpr32h(fph0, fd);
7082 tcg_temp_free(fp0);
7083 tcg_temp_free(fph0);
7084 gen_set_label(l1);
7086 opn = "movz.ps";
7087 break;
7088 case FOP(19, 22):
7089 check_cp1_64bitmode(ctx);
7091 int l1 = gen_new_label();
7092 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7093 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7094 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7096 gen_load_gpr(t0, ft);
7097 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
7098 tcg_temp_free(t0);
7099 gen_load_fpr32(fp0, fs);
7100 gen_load_fpr32h(fph0, fs);
7101 gen_store_fpr32(fp0, fd);
7102 gen_store_fpr32h(fph0, fd);
7103 tcg_temp_free(fp0);
7104 tcg_temp_free(fph0);
7105 gen_set_label(l1);
7107 opn = "movn.ps";
7108 break;
7109 case FOP(24, 22):
7110 check_cp1_64bitmode(ctx);
7112 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7113 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7115 gen_load_fpr64(ctx, fp0, ft);
7116 gen_load_fpr64(ctx, fp1, fs);
7117 tcg_gen_helper_1_2(do_float_addr_ps, fp0, fp0, fp1);
7118 tcg_temp_free(fp1);
7119 gen_store_fpr64(ctx, fp0, fd);
7120 tcg_temp_free(fp0);
7122 opn = "addr.ps";
7123 break;
7124 case FOP(26, 22):
7125 check_cp1_64bitmode(ctx);
7127 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7128 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7130 gen_load_fpr64(ctx, fp0, ft);
7131 gen_load_fpr64(ctx, fp1, fs);
7132 tcg_gen_helper_1_2(do_float_mulr_ps, fp0, fp0, fp1);
7133 tcg_temp_free(fp1);
7134 gen_store_fpr64(ctx, fp0, fd);
7135 tcg_temp_free(fp0);
7137 opn = "mulr.ps";
7138 break;
7139 case FOP(28, 22):
7140 check_cp1_64bitmode(ctx);
7142 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7143 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7145 gen_load_fpr64(ctx, fp0, fs);
7146 gen_load_fpr64(ctx, fp1, fd);
7147 tcg_gen_helper_1_2(do_float_recip2_ps, fp0, fp0, fp1);
7148 tcg_temp_free(fp1);
7149 gen_store_fpr64(ctx, fp0, fd);
7150 tcg_temp_free(fp0);
7152 opn = "recip2.ps";
7153 break;
7154 case FOP(29, 22):
7155 check_cp1_64bitmode(ctx);
7157 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7159 gen_load_fpr64(ctx, fp0, fs);
7160 tcg_gen_helper_1_1(do_float_recip1_ps, fp0, fp0);
7161 gen_store_fpr64(ctx, fp0, fd);
7162 tcg_temp_free(fp0);
7164 opn = "recip1.ps";
7165 break;
7166 case FOP(30, 22):
7167 check_cp1_64bitmode(ctx);
7169 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7171 gen_load_fpr64(ctx, fp0, fs);
7172 tcg_gen_helper_1_1(do_float_rsqrt1_ps, fp0, fp0);
7173 gen_store_fpr64(ctx, fp0, fd);
7174 tcg_temp_free(fp0);
7176 opn = "rsqrt1.ps";
7177 break;
7178 case FOP(31, 22):
7179 check_cp1_64bitmode(ctx);
7181 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7182 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7184 gen_load_fpr64(ctx, fp0, fs);
7185 gen_load_fpr64(ctx, fp1, ft);
7186 tcg_gen_helper_1_2(do_float_rsqrt2_ps, fp0, fp0, fp1);
7187 tcg_temp_free(fp1);
7188 gen_store_fpr64(ctx, fp0, fd);
7189 tcg_temp_free(fp0);
7191 opn = "rsqrt2.ps";
7192 break;
7193 case FOP(32, 22):
7194 check_cp1_64bitmode(ctx);
7196 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7198 gen_load_fpr32h(fp0, fs);
7199 tcg_gen_helper_1_1(do_float_cvts_pu, fp0, fp0);
7200 gen_store_fpr32(fp0, fd);
7201 tcg_temp_free(fp0);
7203 opn = "cvt.s.pu";
7204 break;
7205 case FOP(36, 22):
7206 check_cp1_64bitmode(ctx);
7208 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7210 gen_load_fpr64(ctx, fp0, fs);
7211 tcg_gen_helper_1_1(do_float_cvtpw_ps, fp0, fp0);
7212 gen_store_fpr64(ctx, fp0, fd);
7213 tcg_temp_free(fp0);
7215 opn = "cvt.pw.ps";
7216 break;
7217 case FOP(40, 22):
7218 check_cp1_64bitmode(ctx);
7220 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7222 gen_load_fpr32(fp0, fs);
7223 tcg_gen_helper_1_1(do_float_cvts_pl, fp0, fp0);
7224 gen_store_fpr32(fp0, fd);
7225 tcg_temp_free(fp0);
7227 opn = "cvt.s.pl";
7228 break;
7229 case FOP(44, 22):
7230 check_cp1_64bitmode(ctx);
7232 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7233 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7235 gen_load_fpr32(fp0, fs);
7236 gen_load_fpr32(fp1, ft);
7237 gen_store_fpr32h(fp0, fd);
7238 gen_store_fpr32(fp1, fd);
7239 tcg_temp_free(fp0);
7240 tcg_temp_free(fp1);
7242 opn = "pll.ps";
7243 break;
7244 case FOP(45, 22):
7245 check_cp1_64bitmode(ctx);
7247 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7248 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7250 gen_load_fpr32(fp0, fs);
7251 gen_load_fpr32h(fp1, ft);
7252 gen_store_fpr32(fp1, fd);
7253 gen_store_fpr32h(fp0, fd);
7254 tcg_temp_free(fp0);
7255 tcg_temp_free(fp1);
7257 opn = "plu.ps";
7258 break;
7259 case FOP(46, 22):
7260 check_cp1_64bitmode(ctx);
7262 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7263 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7265 gen_load_fpr32h(fp0, fs);
7266 gen_load_fpr32(fp1, ft);
7267 gen_store_fpr32(fp1, fd);
7268 gen_store_fpr32h(fp0, fd);
7269 tcg_temp_free(fp0);
7270 tcg_temp_free(fp1);
7272 opn = "pul.ps";
7273 break;
7274 case FOP(47, 22):
7275 check_cp1_64bitmode(ctx);
7277 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7278 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7280 gen_load_fpr32h(fp0, fs);
7281 gen_load_fpr32h(fp1, ft);
7282 gen_store_fpr32(fp1, fd);
7283 gen_store_fpr32h(fp0, fd);
7284 tcg_temp_free(fp0);
7285 tcg_temp_free(fp1);
7287 opn = "puu.ps";
7288 break;
7289 case FOP(48, 22):
7290 case FOP(49, 22):
7291 case FOP(50, 22):
7292 case FOP(51, 22):
7293 case FOP(52, 22):
7294 case FOP(53, 22):
7295 case FOP(54, 22):
7296 case FOP(55, 22):
7297 case FOP(56, 22):
7298 case FOP(57, 22):
7299 case FOP(58, 22):
7300 case FOP(59, 22):
7301 case FOP(60, 22):
7302 case FOP(61, 22):
7303 case FOP(62, 22):
7304 case FOP(63, 22):
7305 check_cp1_64bitmode(ctx);
7307 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7308 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7310 gen_load_fpr64(ctx, fp0, fs);
7311 gen_load_fpr64(ctx, fp1, ft);
7312 if (ctx->opcode & (1 << 6)) {
7313 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7314 opn = condnames_abs[func-48];
7315 } else {
7316 gen_cmp_ps(func-48, fp0, fp1, cc);
7317 opn = condnames[func-48];
7319 tcg_temp_free(fp0);
7320 tcg_temp_free(fp1);
7322 break;
7323 default:
7324 MIPS_INVAL(opn);
7325 generate_exception (ctx, EXCP_RI);
7326 return;
7328 switch (optype) {
7329 case BINOP:
7330 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7331 break;
7332 case CMPOP:
7333 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7334 break;
7335 default:
7336 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7337 break;
7341 /* Coprocessor 3 (FPU) */
7342 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7343 int fd, int fs, int base, int index)
7345 const char *opn = "extended float load/store";
7346 int store = 0;
7347 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7348 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
7350 if (base == 0) {
7351 gen_load_gpr(t0, index);
7352 } else if (index == 0) {
7353 gen_load_gpr(t0, base);
7354 } else {
7355 gen_load_gpr(t0, base);
7356 gen_load_gpr(t1, index);
7357 gen_op_addr_add(ctx, t0, t1);
7359 /* Don't do NOP if destination is zero: we must perform the actual
7360 memory access. */
7361 switch (opc) {
7362 case OPC_LWXC1:
7363 check_cop1x(ctx);
7365 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7367 tcg_gen_qemu_ld32s(fp0, t0, ctx->mem_idx);
7368 gen_store_fpr32(fp0, fd);
7369 tcg_temp_free(fp0);
7371 opn = "lwxc1";
7372 break;
7373 case OPC_LDXC1:
7374 check_cop1x(ctx);
7375 check_cp1_registers(ctx, fd);
7377 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7379 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7380 gen_store_fpr64(ctx, fp0, fd);
7381 tcg_temp_free(fp0);
7383 opn = "ldxc1";
7384 break;
7385 case OPC_LUXC1:
7386 check_cp1_64bitmode(ctx);
7387 tcg_gen_andi_tl(t0, t0, ~0x7);
7389 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7391 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7392 gen_store_fpr64(ctx, fp0, fd);
7393 tcg_temp_free(fp0);
7395 opn = "luxc1";
7396 break;
7397 case OPC_SWXC1:
7398 check_cop1x(ctx);
7400 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7402 gen_load_fpr32(fp0, fs);
7403 tcg_gen_qemu_st32(fp0, t0, ctx->mem_idx);
7404 tcg_temp_free(fp0);
7406 opn = "swxc1";
7407 store = 1;
7408 break;
7409 case OPC_SDXC1:
7410 check_cop1x(ctx);
7411 check_cp1_registers(ctx, fs);
7413 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7415 gen_load_fpr64(ctx, fp0, fs);
7416 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7417 tcg_temp_free(fp0);
7419 opn = "sdxc1";
7420 store = 1;
7421 break;
7422 case OPC_SUXC1:
7423 check_cp1_64bitmode(ctx);
7424 tcg_gen_andi_tl(t0, t0, ~0x7);
7426 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7428 gen_load_fpr64(ctx, fp0, fs);
7429 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7430 tcg_temp_free(fp0);
7432 opn = "suxc1";
7433 store = 1;
7434 break;
7435 default:
7436 MIPS_INVAL(opn);
7437 generate_exception(ctx, EXCP_RI);
7438 tcg_temp_free(t0);
7439 tcg_temp_free(t1);
7440 return;
7442 tcg_temp_free(t0);
7443 tcg_temp_free(t1);
7444 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7445 regnames[index], regnames[base]);
7448 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7449 int fd, int fr, int fs, int ft)
7451 const char *opn = "flt3_arith";
7453 switch (opc) {
7454 case OPC_ALNV_PS:
7455 check_cp1_64bitmode(ctx);
7457 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7458 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7459 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7460 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
7461 TCGv fph1 = tcg_temp_local_new(TCG_TYPE_I32);
7462 int l1 = gen_new_label();
7463 int l2 = gen_new_label();
7465 gen_load_gpr(t0, fr);
7466 tcg_gen_andi_tl(t0, t0, 0x7);
7467 gen_load_fpr32(fp0, fs);
7468 gen_load_fpr32h(fph0, fs);
7469 gen_load_fpr32(fp1, ft);
7470 gen_load_fpr32h(fph1, ft);
7472 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7473 gen_store_fpr32(fp0, fd);
7474 gen_store_fpr32h(fph0, fd);
7475 tcg_gen_br(l2);
7476 gen_set_label(l1);
7477 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7478 tcg_temp_free(t0);
7479 #ifdef TARGET_WORDS_BIGENDIAN
7480 gen_store_fpr32(fph1, fd);
7481 gen_store_fpr32h(fp0, fd);
7482 #else
7483 gen_store_fpr32(fph0, fd);
7484 gen_store_fpr32h(fp1, fd);
7485 #endif
7486 gen_set_label(l2);
7487 tcg_temp_free(fp0);
7488 tcg_temp_free(fph0);
7489 tcg_temp_free(fp1);
7490 tcg_temp_free(fph1);
7492 opn = "alnv.ps";
7493 break;
7494 case OPC_MADD_S:
7495 check_cop1x(ctx);
7497 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7498 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7499 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7501 gen_load_fpr32(fp0, fs);
7502 gen_load_fpr32(fp1, ft);
7503 gen_load_fpr32(fp2, fr);
7504 tcg_gen_helper_1_3(do_float_muladd_s, fp2, fp0, fp1, fp2);
7505 tcg_temp_free(fp0);
7506 tcg_temp_free(fp1);
7507 gen_store_fpr32(fp2, fd);
7508 tcg_temp_free(fp2);
7510 opn = "madd.s";
7511 break;
7512 case OPC_MADD_D:
7513 check_cop1x(ctx);
7514 check_cp1_registers(ctx, fd | fs | ft | fr);
7516 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7517 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7518 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7520 gen_load_fpr64(ctx, fp0, fs);
7521 gen_load_fpr64(ctx, fp1, ft);
7522 gen_load_fpr64(ctx, fp2, fr);
7523 tcg_gen_helper_1_3(do_float_muladd_d, fp2, fp0, fp1, fp2);
7524 tcg_temp_free(fp0);
7525 tcg_temp_free(fp1);
7526 gen_store_fpr64(ctx, fp2, fd);
7527 tcg_temp_free(fp2);
7529 opn = "madd.d";
7530 break;
7531 case OPC_MADD_PS:
7532 check_cp1_64bitmode(ctx);
7534 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7535 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7536 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7538 gen_load_fpr64(ctx, fp0, fs);
7539 gen_load_fpr64(ctx, fp1, ft);
7540 gen_load_fpr64(ctx, fp2, fr);
7541 tcg_gen_helper_1_3(do_float_muladd_ps, fp2, fp0, fp1, fp2);
7542 tcg_temp_free(fp0);
7543 tcg_temp_free(fp1);
7544 gen_store_fpr64(ctx, fp2, fd);
7545 tcg_temp_free(fp2);
7547 opn = "madd.ps";
7548 break;
7549 case OPC_MSUB_S:
7550 check_cop1x(ctx);
7552 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7553 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7554 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7556 gen_load_fpr32(fp0, fs);
7557 gen_load_fpr32(fp1, ft);
7558 gen_load_fpr32(fp2, fr);
7559 tcg_gen_helper_1_3(do_float_mulsub_s, fp2, fp0, fp1, fp2);
7560 tcg_temp_free(fp0);
7561 tcg_temp_free(fp1);
7562 gen_store_fpr32(fp2, fd);
7563 tcg_temp_free(fp2);
7565 opn = "msub.s";
7566 break;
7567 case OPC_MSUB_D:
7568 check_cop1x(ctx);
7569 check_cp1_registers(ctx, fd | fs | ft | fr);
7571 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7572 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7573 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7575 gen_load_fpr64(ctx, fp0, fs);
7576 gen_load_fpr64(ctx, fp1, ft);
7577 gen_load_fpr64(ctx, fp2, fr);
7578 tcg_gen_helper_1_3(do_float_mulsub_d, fp2, fp0, fp1, fp2);
7579 tcg_temp_free(fp0);
7580 tcg_temp_free(fp1);
7581 gen_store_fpr64(ctx, fp2, fd);
7582 tcg_temp_free(fp2);
7584 opn = "msub.d";
7585 break;
7586 case OPC_MSUB_PS:
7587 check_cp1_64bitmode(ctx);
7589 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7590 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7591 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7593 gen_load_fpr64(ctx, fp0, fs);
7594 gen_load_fpr64(ctx, fp1, ft);
7595 gen_load_fpr64(ctx, fp2, fr);
7596 tcg_gen_helper_1_3(do_float_mulsub_ps, fp2, fp0, fp1, fp2);
7597 tcg_temp_free(fp0);
7598 tcg_temp_free(fp1);
7599 gen_store_fpr64(ctx, fp2, fd);
7600 tcg_temp_free(fp2);
7602 opn = "msub.ps";
7603 break;
7604 case OPC_NMADD_S:
7605 check_cop1x(ctx);
7607 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7608 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7609 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7611 gen_load_fpr32(fp0, fs);
7612 gen_load_fpr32(fp1, ft);
7613 gen_load_fpr32(fp2, fr);
7614 tcg_gen_helper_1_3(do_float_nmuladd_s, fp2, fp0, fp1, fp2);
7615 tcg_temp_free(fp0);
7616 tcg_temp_free(fp1);
7617 gen_store_fpr32(fp2, fd);
7618 tcg_temp_free(fp2);
7620 opn = "nmadd.s";
7621 break;
7622 case OPC_NMADD_D:
7623 check_cop1x(ctx);
7624 check_cp1_registers(ctx, fd | fs | ft | fr);
7626 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7627 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7628 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7630 gen_load_fpr64(ctx, fp0, fs);
7631 gen_load_fpr64(ctx, fp1, ft);
7632 gen_load_fpr64(ctx, fp2, fr);
7633 tcg_gen_helper_1_3(do_float_nmuladd_d, fp2, fp0, fp1, fp2);
7634 tcg_temp_free(fp0);
7635 tcg_temp_free(fp1);
7636 gen_store_fpr64(ctx, fp2, fd);
7637 tcg_temp_free(fp2);
7639 opn = "nmadd.d";
7640 break;
7641 case OPC_NMADD_PS:
7642 check_cp1_64bitmode(ctx);
7644 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7645 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7646 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7648 gen_load_fpr64(ctx, fp0, fs);
7649 gen_load_fpr64(ctx, fp1, ft);
7650 gen_load_fpr64(ctx, fp2, fr);
7651 tcg_gen_helper_1_3(do_float_nmuladd_ps, fp2, fp0, fp1, fp2);
7652 tcg_temp_free(fp0);
7653 tcg_temp_free(fp1);
7654 gen_store_fpr64(ctx, fp2, fd);
7655 tcg_temp_free(fp2);
7657 opn = "nmadd.ps";
7658 break;
7659 case OPC_NMSUB_S:
7660 check_cop1x(ctx);
7662 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7663 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7664 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7666 gen_load_fpr32(fp0, fs);
7667 gen_load_fpr32(fp1, ft);
7668 gen_load_fpr32(fp2, fr);
7669 tcg_gen_helper_1_3(do_float_nmulsub_s, fp2, fp0, fp1, fp2);
7670 tcg_temp_free(fp0);
7671 tcg_temp_free(fp1);
7672 gen_store_fpr32(fp2, fd);
7673 tcg_temp_free(fp2);
7675 opn = "nmsub.s";
7676 break;
7677 case OPC_NMSUB_D:
7678 check_cop1x(ctx);
7679 check_cp1_registers(ctx, fd | fs | ft | fr);
7681 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7682 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7683 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7685 gen_load_fpr64(ctx, fp0, fs);
7686 gen_load_fpr64(ctx, fp1, ft);
7687 gen_load_fpr64(ctx, fp2, fr);
7688 tcg_gen_helper_1_3(do_float_nmulsub_d, fp2, fp0, fp1, fp2);
7689 tcg_temp_free(fp0);
7690 tcg_temp_free(fp1);
7691 gen_store_fpr64(ctx, fp2, fd);
7692 tcg_temp_free(fp2);
7694 opn = "nmsub.d";
7695 break;
7696 case OPC_NMSUB_PS:
7697 check_cp1_64bitmode(ctx);
7699 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7700 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7701 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7703 gen_load_fpr64(ctx, fp0, fs);
7704 gen_load_fpr64(ctx, fp1, ft);
7705 gen_load_fpr64(ctx, fp2, fr);
7706 tcg_gen_helper_1_3(do_float_nmulsub_ps, fp2, fp0, fp1, fp2);
7707 tcg_temp_free(fp0);
7708 tcg_temp_free(fp1);
7709 gen_store_fpr64(ctx, fp2, fd);
7710 tcg_temp_free(fp2);
7712 opn = "nmsub.ps";
7713 break;
7714 default:
7715 MIPS_INVAL(opn);
7716 generate_exception (ctx, EXCP_RI);
7717 return;
7719 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7720 fregnames[fs], fregnames[ft]);
7723 /* ISA extensions (ASEs) */
7724 /* MIPS16 extension to MIPS32 */
7725 /* SmartMIPS extension to MIPS32 */
7727 #if defined(TARGET_MIPS64)
7729 /* MDMX extension to MIPS64 */
7731 #endif
7733 static void decode_opc (CPUState *env, DisasContext *ctx)
7735 int32_t offset;
7736 int rs, rt, rd, sa;
7737 uint32_t op, op1, op2;
7738 int16_t imm;
7740 /* make sure instructions are on a word boundary */
7741 if (ctx->pc & 0x3) {
7742 env->CP0_BadVAddr = ctx->pc;
7743 generate_exception(ctx, EXCP_AdEL);
7744 return;
7747 /* Handle blikely not taken case */
7748 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7749 int l1 = gen_new_label();
7751 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7752 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
7754 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
7756 tcg_gen_movi_i32(r_tmp, ctx->hflags & ~MIPS_HFLAG_BMASK);
7757 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
7758 tcg_temp_free(r_tmp);
7760 gen_goto_tb(ctx, 1, ctx->pc + 4);
7761 gen_set_label(l1);
7763 op = MASK_OP_MAJOR(ctx->opcode);
7764 rs = (ctx->opcode >> 21) & 0x1f;
7765 rt = (ctx->opcode >> 16) & 0x1f;
7766 rd = (ctx->opcode >> 11) & 0x1f;
7767 sa = (ctx->opcode >> 6) & 0x1f;
7768 imm = (int16_t)ctx->opcode;
7769 switch (op) {
7770 case OPC_SPECIAL:
7771 op1 = MASK_SPECIAL(ctx->opcode);
7772 switch (op1) {
7773 case OPC_SLL: /* Arithmetic with immediate */
7774 case OPC_SRL ... OPC_SRA:
7775 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7776 break;
7777 case OPC_MOVZ ... OPC_MOVN:
7778 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7779 case OPC_SLLV: /* Arithmetic */
7780 case OPC_SRLV ... OPC_SRAV:
7781 case OPC_ADD ... OPC_NOR:
7782 case OPC_SLT ... OPC_SLTU:
7783 gen_arith(env, ctx, op1, rd, rs, rt);
7784 break;
7785 case OPC_MULT ... OPC_DIVU:
7786 if (sa) {
7787 check_insn(env, ctx, INSN_VR54XX);
7788 op1 = MASK_MUL_VR54XX(ctx->opcode);
7789 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7790 } else
7791 gen_muldiv(ctx, op1, rs, rt);
7792 break;
7793 case OPC_JR ... OPC_JALR:
7794 gen_compute_branch(ctx, op1, rs, rd, sa);
7795 return;
7796 case OPC_TGE ... OPC_TEQ: /* Traps */
7797 case OPC_TNE:
7798 gen_trap(ctx, op1, rs, rt, -1);
7799 break;
7800 case OPC_MFHI: /* Move from HI/LO */
7801 case OPC_MFLO:
7802 gen_HILO(ctx, op1, rd);
7803 break;
7804 case OPC_MTHI:
7805 case OPC_MTLO: /* Move to HI/LO */
7806 gen_HILO(ctx, op1, rs);
7807 break;
7808 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7809 #ifdef MIPS_STRICT_STANDARD
7810 MIPS_INVAL("PMON / selsl");
7811 generate_exception(ctx, EXCP_RI);
7812 #else
7813 tcg_gen_helper_0_i(do_pmon, sa);
7814 #endif
7815 break;
7816 case OPC_SYSCALL:
7817 generate_exception(ctx, EXCP_SYSCALL);
7818 break;
7819 case OPC_BREAK:
7820 generate_exception(ctx, EXCP_BREAK);
7821 break;
7822 case OPC_SPIM:
7823 #ifdef MIPS_STRICT_STANDARD
7824 MIPS_INVAL("SPIM");
7825 generate_exception(ctx, EXCP_RI);
7826 #else
7827 /* Implemented as RI exception for now. */
7828 MIPS_INVAL("spim (unofficial)");
7829 generate_exception(ctx, EXCP_RI);
7830 #endif
7831 break;
7832 case OPC_SYNC:
7833 /* Treat as NOP. */
7834 break;
7836 case OPC_MOVCI:
7837 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7838 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7839 save_cpu_state(ctx, 1);
7840 check_cp1_enabled(ctx);
7841 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7842 (ctx->opcode >> 16) & 1);
7843 } else {
7844 generate_exception_err(ctx, EXCP_CpU, 1);
7846 break;
7848 #if defined(TARGET_MIPS64)
7849 /* MIPS64 specific opcodes */
7850 case OPC_DSLL:
7851 case OPC_DSRL ... OPC_DSRA:
7852 case OPC_DSLL32:
7853 case OPC_DSRL32 ... OPC_DSRA32:
7854 check_insn(env, ctx, ISA_MIPS3);
7855 check_mips_64(ctx);
7856 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7857 break;
7858 case OPC_DSLLV:
7859 case OPC_DSRLV ... OPC_DSRAV:
7860 case OPC_DADD ... OPC_DSUBU:
7861 check_insn(env, ctx, ISA_MIPS3);
7862 check_mips_64(ctx);
7863 gen_arith(env, ctx, op1, rd, rs, rt);
7864 break;
7865 case OPC_DMULT ... OPC_DDIVU:
7866 check_insn(env, ctx, ISA_MIPS3);
7867 check_mips_64(ctx);
7868 gen_muldiv(ctx, op1, rs, rt);
7869 break;
7870 #endif
7871 default: /* Invalid */
7872 MIPS_INVAL("special");
7873 generate_exception(ctx, EXCP_RI);
7874 break;
7876 break;
7877 case OPC_SPECIAL2:
7878 op1 = MASK_SPECIAL2(ctx->opcode);
7879 switch (op1) {
7880 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7881 case OPC_MSUB ... OPC_MSUBU:
7882 check_insn(env, ctx, ISA_MIPS32);
7883 gen_muldiv(ctx, op1, rs, rt);
7884 break;
7885 case OPC_MUL:
7886 gen_arith(env, ctx, op1, rd, rs, rt);
7887 break;
7888 case OPC_CLZ ... OPC_CLO:
7889 check_insn(env, ctx, ISA_MIPS32);
7890 gen_cl(ctx, op1, rd, rs);
7891 break;
7892 case OPC_SDBBP:
7893 /* XXX: not clear which exception should be raised
7894 * when in debug mode...
7896 check_insn(env, ctx, ISA_MIPS32);
7897 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7898 generate_exception(ctx, EXCP_DBp);
7899 } else {
7900 generate_exception(ctx, EXCP_DBp);
7902 /* Treat as NOP. */
7903 break;
7904 #if defined(TARGET_MIPS64)
7905 case OPC_DCLZ ... OPC_DCLO:
7906 check_insn(env, ctx, ISA_MIPS64);
7907 check_mips_64(ctx);
7908 gen_cl(ctx, op1, rd, rs);
7909 break;
7910 #endif
7911 default: /* Invalid */
7912 MIPS_INVAL("special2");
7913 generate_exception(ctx, EXCP_RI);
7914 break;
7916 break;
7917 case OPC_SPECIAL3:
7918 op1 = MASK_SPECIAL3(ctx->opcode);
7919 switch (op1) {
7920 case OPC_EXT:
7921 case OPC_INS:
7922 check_insn(env, ctx, ISA_MIPS32R2);
7923 gen_bitops(ctx, op1, rt, rs, sa, rd);
7924 break;
7925 case OPC_BSHFL:
7926 check_insn(env, ctx, ISA_MIPS32R2);
7927 op2 = MASK_BSHFL(ctx->opcode);
7928 gen_bshfl(ctx, op2, rt, rd);
7929 break;
7930 case OPC_RDHWR:
7931 check_insn(env, ctx, ISA_MIPS32R2);
7933 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7935 switch (rd) {
7936 case 0:
7937 save_cpu_state(ctx, 1);
7938 tcg_gen_helper_1_0(do_rdhwr_cpunum, t0);
7939 break;
7940 case 1:
7941 save_cpu_state(ctx, 1);
7942 tcg_gen_helper_1_0(do_rdhwr_synci_step, t0);
7943 break;
7944 case 2:
7945 save_cpu_state(ctx, 1);
7946 tcg_gen_helper_1_0(do_rdhwr_cc, t0);
7947 break;
7948 case 3:
7949 save_cpu_state(ctx, 1);
7950 tcg_gen_helper_1_0(do_rdhwr_ccres, t0);
7951 break;
7952 case 29:
7953 if (env->user_mode_only) {
7954 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7955 break;
7956 } else {
7957 /* XXX: Some CPUs implement this in hardware.
7958 Not supported yet. */
7960 default: /* Invalid */
7961 MIPS_INVAL("rdhwr");
7962 generate_exception(ctx, EXCP_RI);
7963 break;
7965 gen_store_gpr(t0, rt);
7966 tcg_temp_free(t0);
7968 break;
7969 case OPC_FORK:
7970 check_insn(env, ctx, ASE_MT);
7972 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7973 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
7975 gen_load_gpr(t0, rt);
7976 gen_load_gpr(t1, rs);
7977 tcg_gen_helper_0_2(do_fork, t0, t1);
7978 tcg_temp_free(t0);
7979 tcg_temp_free(t1);
7981 break;
7982 case OPC_YIELD:
7983 check_insn(env, ctx, ASE_MT);
7985 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7987 gen_load_gpr(t0, rs);
7988 tcg_gen_helper_1_1(do_yield, t0, t0);
7989 gen_store_gpr(t0, rd);
7990 tcg_temp_free(t0);
7992 break;
7993 #if defined(TARGET_MIPS64)
7994 case OPC_DEXTM ... OPC_DEXT:
7995 case OPC_DINSM ... OPC_DINS:
7996 check_insn(env, ctx, ISA_MIPS64R2);
7997 check_mips_64(ctx);
7998 gen_bitops(ctx, op1, rt, rs, sa, rd);
7999 break;
8000 case OPC_DBSHFL:
8001 check_insn(env, ctx, ISA_MIPS64R2);
8002 check_mips_64(ctx);
8003 op2 = MASK_DBSHFL(ctx->opcode);
8004 gen_bshfl(ctx, op2, rt, rd);
8005 break;
8006 #endif
8007 default: /* Invalid */
8008 MIPS_INVAL("special3");
8009 generate_exception(ctx, EXCP_RI);
8010 break;
8012 break;
8013 case OPC_REGIMM:
8014 op1 = MASK_REGIMM(ctx->opcode);
8015 switch (op1) {
8016 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
8017 case OPC_BLTZAL ... OPC_BGEZALL:
8018 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
8019 return;
8020 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
8021 case OPC_TNEI:
8022 gen_trap(ctx, op1, rs, -1, imm);
8023 break;
8024 case OPC_SYNCI:
8025 check_insn(env, ctx, ISA_MIPS32R2);
8026 /* Treat as NOP. */
8027 break;
8028 default: /* Invalid */
8029 MIPS_INVAL("regimm");
8030 generate_exception(ctx, EXCP_RI);
8031 break;
8033 break;
8034 case OPC_CP0:
8035 check_cp0_enabled(ctx);
8036 op1 = MASK_CP0(ctx->opcode);
8037 switch (op1) {
8038 case OPC_MFC0:
8039 case OPC_MTC0:
8040 case OPC_MFTR:
8041 case OPC_MTTR:
8042 #if defined(TARGET_MIPS64)
8043 case OPC_DMFC0:
8044 case OPC_DMTC0:
8045 #endif
8046 #ifndef CONFIG_USER_ONLY
8047 if (!env->user_mode_only)
8048 gen_cp0(env, ctx, op1, rt, rd);
8049 #endif /* !CONFIG_USER_ONLY */
8050 break;
8051 case OPC_C0_FIRST ... OPC_C0_LAST:
8052 #ifndef CONFIG_USER_ONLY
8053 if (!env->user_mode_only)
8054 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
8055 #endif /* !CONFIG_USER_ONLY */
8056 break;
8057 case OPC_MFMC0:
8058 #ifndef CONFIG_USER_ONLY
8059 if (!env->user_mode_only) {
8060 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8062 op2 = MASK_MFMC0(ctx->opcode);
8063 switch (op2) {
8064 case OPC_DMT:
8065 check_insn(env, ctx, ASE_MT);
8066 tcg_gen_helper_1_1(do_dmt, t0, t0);
8067 break;
8068 case OPC_EMT:
8069 check_insn(env, ctx, ASE_MT);
8070 tcg_gen_helper_1_1(do_emt, t0, t0);
8071 break;
8072 case OPC_DVPE:
8073 check_insn(env, ctx, ASE_MT);
8074 tcg_gen_helper_1_1(do_dvpe, t0, t0);
8075 break;
8076 case OPC_EVPE:
8077 check_insn(env, ctx, ASE_MT);
8078 tcg_gen_helper_1_1(do_evpe, t0, t0);
8079 break;
8080 case OPC_DI:
8081 check_insn(env, ctx, ISA_MIPS32R2);
8082 save_cpu_state(ctx, 1);
8083 tcg_gen_helper_1_0(do_di, t0);
8084 /* Stop translation as we may have switched the execution mode */
8085 ctx->bstate = BS_STOP;
8086 break;
8087 case OPC_EI:
8088 check_insn(env, ctx, ISA_MIPS32R2);
8089 save_cpu_state(ctx, 1);
8090 tcg_gen_helper_1_0(do_ei, t0);
8091 /* Stop translation as we may have switched the execution mode */
8092 ctx->bstate = BS_STOP;
8093 break;
8094 default: /* Invalid */
8095 MIPS_INVAL("mfmc0");
8096 generate_exception(ctx, EXCP_RI);
8097 break;
8099 gen_store_gpr(t0, rt);
8100 tcg_temp_free(t0);
8102 #endif /* !CONFIG_USER_ONLY */
8103 break;
8104 case OPC_RDPGPR:
8105 check_insn(env, ctx, ISA_MIPS32R2);
8106 gen_load_srsgpr(rt, rd);
8107 break;
8108 case OPC_WRPGPR:
8109 check_insn(env, ctx, ISA_MIPS32R2);
8110 gen_store_srsgpr(rt, rd);
8111 break;
8112 default:
8113 MIPS_INVAL("cp0");
8114 generate_exception(ctx, EXCP_RI);
8115 break;
8117 break;
8118 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
8119 gen_arith_imm(env, ctx, op, rt, rs, imm);
8120 break;
8121 case OPC_J ... OPC_JAL: /* Jump */
8122 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8123 gen_compute_branch(ctx, op, rs, rt, offset);
8124 return;
8125 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8126 case OPC_BEQL ... OPC_BGTZL:
8127 gen_compute_branch(ctx, op, rs, rt, imm << 2);
8128 return;
8129 case OPC_LB ... OPC_LWR: /* Load and stores */
8130 case OPC_SB ... OPC_SW:
8131 case OPC_SWR:
8132 case OPC_LL:
8133 case OPC_SC:
8134 gen_ldst(ctx, op, rt, rs, imm);
8135 break;
8136 case OPC_CACHE:
8137 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
8138 /* Treat as NOP. */
8139 break;
8140 case OPC_PREF:
8141 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8142 /* Treat as NOP. */
8143 break;
8145 /* Floating point (COP1). */
8146 case OPC_LWC1:
8147 case OPC_LDC1:
8148 case OPC_SWC1:
8149 case OPC_SDC1:
8150 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8151 save_cpu_state(ctx, 1);
8152 check_cp1_enabled(ctx);
8153 gen_flt_ldst(ctx, op, rt, rs, imm);
8154 } else {
8155 generate_exception_err(ctx, EXCP_CpU, 1);
8157 break;
8159 case OPC_CP1:
8160 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8161 save_cpu_state(ctx, 1);
8162 check_cp1_enabled(ctx);
8163 op1 = MASK_CP1(ctx->opcode);
8164 switch (op1) {
8165 case OPC_MFHC1:
8166 case OPC_MTHC1:
8167 check_insn(env, ctx, ISA_MIPS32R2);
8168 case OPC_MFC1:
8169 case OPC_CFC1:
8170 case OPC_MTC1:
8171 case OPC_CTC1:
8172 gen_cp1(ctx, op1, rt, rd);
8173 break;
8174 #if defined(TARGET_MIPS64)
8175 case OPC_DMFC1:
8176 case OPC_DMTC1:
8177 check_insn(env, ctx, ISA_MIPS3);
8178 gen_cp1(ctx, op1, rt, rd);
8179 break;
8180 #endif
8181 case OPC_BC1ANY2:
8182 case OPC_BC1ANY4:
8183 check_cop1x(ctx);
8184 check_insn(env, ctx, ASE_MIPS3D);
8185 /* fall through */
8186 case OPC_BC1:
8187 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8188 (rt >> 2) & 0x7, imm << 2);
8189 return;
8190 case OPC_S_FMT:
8191 case OPC_D_FMT:
8192 case OPC_W_FMT:
8193 case OPC_L_FMT:
8194 case OPC_PS_FMT:
8195 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8196 (imm >> 8) & 0x7);
8197 break;
8198 default:
8199 MIPS_INVAL("cp1");
8200 generate_exception (ctx, EXCP_RI);
8201 break;
8203 } else {
8204 generate_exception_err(ctx, EXCP_CpU, 1);
8206 break;
8208 /* COP2. */
8209 case OPC_LWC2:
8210 case OPC_LDC2:
8211 case OPC_SWC2:
8212 case OPC_SDC2:
8213 case OPC_CP2:
8214 /* COP2: Not implemented. */
8215 generate_exception_err(ctx, EXCP_CpU, 2);
8216 break;
8218 case OPC_CP3:
8219 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8220 save_cpu_state(ctx, 1);
8221 check_cp1_enabled(ctx);
8222 op1 = MASK_CP3(ctx->opcode);
8223 switch (op1) {
8224 case OPC_LWXC1:
8225 case OPC_LDXC1:
8226 case OPC_LUXC1:
8227 case OPC_SWXC1:
8228 case OPC_SDXC1:
8229 case OPC_SUXC1:
8230 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8231 break;
8232 case OPC_PREFX:
8233 /* Treat as NOP. */
8234 break;
8235 case OPC_ALNV_PS:
8236 case OPC_MADD_S:
8237 case OPC_MADD_D:
8238 case OPC_MADD_PS:
8239 case OPC_MSUB_S:
8240 case OPC_MSUB_D:
8241 case OPC_MSUB_PS:
8242 case OPC_NMADD_S:
8243 case OPC_NMADD_D:
8244 case OPC_NMADD_PS:
8245 case OPC_NMSUB_S:
8246 case OPC_NMSUB_D:
8247 case OPC_NMSUB_PS:
8248 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8249 break;
8250 default:
8251 MIPS_INVAL("cp3");
8252 generate_exception (ctx, EXCP_RI);
8253 break;
8255 } else {
8256 generate_exception_err(ctx, EXCP_CpU, 1);
8258 break;
8260 #if defined(TARGET_MIPS64)
8261 /* MIPS64 opcodes */
8262 case OPC_LWU:
8263 case OPC_LDL ... OPC_LDR:
8264 case OPC_SDL ... OPC_SDR:
8265 case OPC_LLD:
8266 case OPC_LD:
8267 case OPC_SCD:
8268 case OPC_SD:
8269 check_insn(env, ctx, ISA_MIPS3);
8270 check_mips_64(ctx);
8271 gen_ldst(ctx, op, rt, rs, imm);
8272 break;
8273 case OPC_DADDI ... OPC_DADDIU:
8274 check_insn(env, ctx, ISA_MIPS3);
8275 check_mips_64(ctx);
8276 gen_arith_imm(env, ctx, op, rt, rs, imm);
8277 break;
8278 #endif
8279 case OPC_JALX:
8280 check_insn(env, ctx, ASE_MIPS16);
8281 /* MIPS16: Not implemented. */
8282 case OPC_MDMX:
8283 check_insn(env, ctx, ASE_MDMX);
8284 /* MDMX: Not implemented. */
8285 default: /* Invalid */
8286 MIPS_INVAL("major opcode");
8287 generate_exception(ctx, EXCP_RI);
8288 break;
8290 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8291 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8292 /* Branches completion */
8293 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8294 ctx->bstate = BS_BRANCH;
8295 save_cpu_state(ctx, 0);
8296 /* FIXME: Need to clear can_do_io. */
8297 switch (hflags) {
8298 case MIPS_HFLAG_B:
8299 /* unconditional branch */
8300 MIPS_DEBUG("unconditional branch");
8301 gen_goto_tb(ctx, 0, ctx->btarget);
8302 break;
8303 case MIPS_HFLAG_BL:
8304 /* blikely taken case */
8305 MIPS_DEBUG("blikely branch taken");
8306 gen_goto_tb(ctx, 0, ctx->btarget);
8307 break;
8308 case MIPS_HFLAG_BC:
8309 /* Conditional branch */
8310 MIPS_DEBUG("conditional branch");
8312 int l1 = gen_new_label();
8314 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
8315 gen_goto_tb(ctx, 1, ctx->pc + 4);
8316 gen_set_label(l1);
8317 gen_goto_tb(ctx, 0, ctx->btarget);
8319 break;
8320 case MIPS_HFLAG_BR:
8321 /* unconditional branch to register */
8322 MIPS_DEBUG("branch to register");
8323 tcg_gen_mov_tl(cpu_PC, btarget);
8324 tcg_gen_exit_tb(0);
8325 break;
8326 default:
8327 MIPS_DEBUG("unknown branch");
8328 break;
8333 static inline void
8334 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8335 int search_pc)
8337 DisasContext ctx;
8338 target_ulong pc_start;
8339 uint16_t *gen_opc_end;
8340 int j, lj = -1;
8341 int num_insns;
8342 int max_insns;
8344 if (search_pc && loglevel)
8345 fprintf (logfile, "search pc %d\n", search_pc);
8347 pc_start = tb->pc;
8348 /* Leave some spare opc slots for branch handling. */
8349 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
8350 ctx.pc = pc_start;
8351 ctx.saved_pc = -1;
8352 ctx.tb = tb;
8353 ctx.bstate = BS_NONE;
8354 /* Restore delay slot state from the tb context. */
8355 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8356 restore_cpu_state(env, &ctx);
8357 if (env->user_mode_only)
8358 ctx.mem_idx = MIPS_HFLAG_UM;
8359 else
8360 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8361 num_insns = 0;
8362 max_insns = tb->cflags & CF_COUNT_MASK;
8363 if (max_insns == 0)
8364 max_insns = CF_COUNT_MASK;
8365 #ifdef DEBUG_DISAS
8366 if (loglevel & CPU_LOG_TB_CPU) {
8367 fprintf(logfile, "------------------------------------------------\n");
8368 /* FIXME: This may print out stale hflags from env... */
8369 cpu_dump_state(env, logfile, fprintf, 0);
8371 #endif
8372 #ifdef MIPS_DEBUG_DISAS
8373 if (loglevel & CPU_LOG_TB_IN_ASM)
8374 fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
8375 tb, ctx.mem_idx, ctx.hflags);
8376 #endif
8377 gen_icount_start();
8378 while (ctx.bstate == BS_NONE) {
8379 if (env->nb_breakpoints > 0) {
8380 for(j = 0; j < env->nb_breakpoints; j++) {
8381 if (env->breakpoints[j] == ctx.pc) {
8382 save_cpu_state(&ctx, 1);
8383 ctx.bstate = BS_BRANCH;
8384 tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
8385 /* Include the breakpoint location or the tb won't
8386 * be flushed when it must be. */
8387 ctx.pc += 4;
8388 goto done_generating;
8393 if (search_pc) {
8394 j = gen_opc_ptr - gen_opc_buf;
8395 if (lj < j) {
8396 lj++;
8397 while (lj < j)
8398 gen_opc_instr_start[lj++] = 0;
8400 gen_opc_pc[lj] = ctx.pc;
8401 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8402 gen_opc_instr_start[lj] = 1;
8403 gen_opc_icount[lj] = num_insns;
8405 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8406 gen_io_start();
8407 ctx.opcode = ldl_code(ctx.pc);
8408 decode_opc(env, &ctx);
8409 ctx.pc += 4;
8410 num_insns++;
8412 if (env->singlestep_enabled)
8413 break;
8415 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8416 break;
8418 if (gen_opc_ptr >= gen_opc_end)
8419 break;
8421 if (num_insns >= max_insns)
8422 break;
8423 #if defined (MIPS_SINGLE_STEP)
8424 break;
8425 #endif
8427 if (tb->cflags & CF_LAST_IO)
8428 gen_io_end();
8429 if (env->singlestep_enabled) {
8430 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
8431 tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
8432 } else {
8433 switch (ctx.bstate) {
8434 case BS_STOP:
8435 tcg_gen_helper_0_0(do_interrupt_restart);
8436 gen_goto_tb(&ctx, 0, ctx.pc);
8437 break;
8438 case BS_NONE:
8439 save_cpu_state(&ctx, 0);
8440 gen_goto_tb(&ctx, 0, ctx.pc);
8441 break;
8442 case BS_EXCP:
8443 tcg_gen_helper_0_0(do_interrupt_restart);
8444 tcg_gen_exit_tb(0);
8445 break;
8446 case BS_BRANCH:
8447 default:
8448 break;
8451 done_generating:
8452 gen_icount_end(tb, num_insns);
8453 *gen_opc_ptr = INDEX_op_end;
8454 if (search_pc) {
8455 j = gen_opc_ptr - gen_opc_buf;
8456 lj++;
8457 while (lj <= j)
8458 gen_opc_instr_start[lj++] = 0;
8459 } else {
8460 tb->size = ctx.pc - pc_start;
8461 tb->icount = num_insns;
8463 #ifdef DEBUG_DISAS
8464 #if defined MIPS_DEBUG_DISAS
8465 if (loglevel & CPU_LOG_TB_IN_ASM)
8466 fprintf(logfile, "\n");
8467 #endif
8468 if (loglevel & CPU_LOG_TB_IN_ASM) {
8469 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
8470 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
8471 fprintf(logfile, "\n");
8473 if (loglevel & CPU_LOG_TB_CPU) {
8474 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8476 #endif
8479 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8481 gen_intermediate_code_internal(env, tb, 0);
8484 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8486 gen_intermediate_code_internal(env, tb, 1);
8489 static void fpu_dump_state(CPUState *env, FILE *f,
8490 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8491 int flags)
8493 int i;
8494 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8496 #define printfpr(fp) \
8497 do { \
8498 if (is_fpu64) \
8499 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8500 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8501 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8502 else { \
8503 fpr_t tmp; \
8504 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8505 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8506 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8507 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8508 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8510 } while(0)
8513 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8514 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8515 get_float_exception_flags(&env->active_fpu.fp_status));
8516 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8517 fpu_fprintf(f, "%3s: ", fregnames[i]);
8518 printfpr(&env->active_fpu.fpr[i]);
8521 #undef printfpr
8524 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8525 /* Debug help: The architecture requires 32bit code to maintain proper
8526 sign-extended values on 64bit machines. */
8528 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8530 static void
8531 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8532 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8533 int flags)
8535 int i;
8537 if (!SIGN_EXT_P(env->active_tc.PC))
8538 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8539 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8540 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8541 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8542 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8543 if (!SIGN_EXT_P(env->btarget))
8544 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8546 for (i = 0; i < 32; i++) {
8547 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8548 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8551 if (!SIGN_EXT_P(env->CP0_EPC))
8552 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8553 if (!SIGN_EXT_P(env->CP0_LLAddr))
8554 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
8556 #endif
8558 void cpu_dump_state (CPUState *env, FILE *f,
8559 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8560 int flags)
8562 int i;
8564 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",
8565 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8566 env->hflags, env->btarget, env->bcond);
8567 for (i = 0; i < 32; i++) {
8568 if ((i & 3) == 0)
8569 cpu_fprintf(f, "GPR%02d:", i);
8570 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8571 if ((i & 3) == 3)
8572 cpu_fprintf(f, "\n");
8575 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8576 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8577 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8578 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
8579 if (env->hflags & MIPS_HFLAG_FPU)
8580 fpu_dump_state(env, f, cpu_fprintf, flags);
8581 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8582 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8583 #endif
8586 static void mips_tcg_init(void)
8588 int i;
8589 static int inited;
8591 /* Initialize various static tables. */
8592 if (inited)
8593 return;
8595 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
8596 for (i = 0; i < 32; i++)
8597 cpu_gpr[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8598 offsetof(CPUState, active_tc.gpr[i]),
8599 regnames[i]);
8600 cpu_PC = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8601 offsetof(CPUState, active_tc.PC), "PC");
8602 for (i = 0; i < MIPS_DSP_ACC; i++) {
8603 cpu_HI[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8604 offsetof(CPUState, active_tc.HI[i]),
8605 regnames_HI[i]);
8606 cpu_LO[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8607 offsetof(CPUState, active_tc.LO[i]),
8608 regnames_LO[i]);
8609 cpu_ACX[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8610 offsetof(CPUState, active_tc.ACX[i]),
8611 regnames_ACX[i]);
8613 cpu_dspctrl = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8614 offsetof(CPUState, active_tc.DSPControl),
8615 "DSPControl");
8616 bcond = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8617 offsetof(CPUState, bcond), "bcond");
8618 btarget = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8619 offsetof(CPUState, btarget), "btarget");
8620 for (i = 0; i < 32; i++)
8621 fpu_fpr32[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8622 offsetof(CPUState, active_fpu.fpr[i].w[FP_ENDIAN_IDX]),
8623 fregnames[i]);
8624 for (i = 0; i < 32; i++)
8625 fpu_fpr64[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
8626 offsetof(CPUState, active_fpu.fpr[i]),
8627 fregnames_64[i]);
8628 for (i = 0; i < 32; i++)
8629 fpu_fpr32h[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8630 offsetof(CPUState, active_fpu.fpr[i].w[!FP_ENDIAN_IDX]),
8631 fregnames_h[i]);
8632 fpu_fcr0 = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8633 offsetof(CPUState, active_fpu.fcr0),
8634 "fcr0");
8635 fpu_fcr31 = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8636 offsetof(CPUState, active_fpu.fcr31),
8637 "fcr31");
8639 /* register helpers */
8640 #undef DEF_HELPER
8641 #define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
8642 #include "helper.h"
8644 inited = 1;
8647 #include "translate_init.c"
8649 CPUMIPSState *cpu_mips_init (const char *cpu_model)
8651 CPUMIPSState *env;
8652 const mips_def_t *def;
8654 def = cpu_mips_find_by_name(cpu_model);
8655 if (!def)
8656 return NULL;
8657 env = qemu_mallocz(sizeof(CPUMIPSState));
8658 if (!env)
8659 return NULL;
8660 env->cpu_model = def;
8662 cpu_exec_init(env);
8663 env->cpu_model_str = cpu_model;
8664 mips_tcg_init();
8665 cpu_reset(env);
8666 return env;
8669 void cpu_reset (CPUMIPSState *env)
8671 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8673 tlb_flush(env, 1);
8675 /* Minimal init */
8676 #if defined(CONFIG_USER_ONLY)
8677 env->user_mode_only = 1;
8678 #endif
8679 if (env->user_mode_only) {
8680 env->hflags = MIPS_HFLAG_UM;
8681 } else {
8682 if (env->hflags & MIPS_HFLAG_BMASK) {
8683 /* If the exception was raised from a delay slot,
8684 come back to the jump. */
8685 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8686 } else {
8687 env->CP0_ErrorEPC = env->active_tc.PC;
8689 env->active_tc.PC = (int32_t)0xBFC00000;
8690 env->CP0_Wired = 0;
8691 /* SMP not implemented */
8692 env->CP0_EBase = 0x80000000;
8693 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8694 /* vectored interrupts not implemented, timer on int 7,
8695 no performance counters. */
8696 env->CP0_IntCtl = 0xe0000000;
8698 int i;
8700 for (i = 0; i < 7; i++) {
8701 env->CP0_WatchLo[i] = 0;
8702 env->CP0_WatchHi[i] = 0x80000000;
8704 env->CP0_WatchLo[7] = 0;
8705 env->CP0_WatchHi[7] = 0;
8707 /* Count register increments in debug mode, EJTAG version 1 */
8708 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8709 env->hflags = MIPS_HFLAG_CP0;
8711 env->exception_index = EXCP_NONE;
8712 cpu_mips_register(env, env->cpu_model);
8715 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8716 unsigned long searched_pc, int pc_pos, void *puc)
8718 env->active_tc.PC = gen_opc_pc[pc_pos];
8719 env->hflags &= ~MIPS_HFLAG_BMASK;
8720 env->hflags |= gen_opc_hflags[pc_pos];