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