ide: cmd646 ->unit has just the value that we want
[qemu.git] / target-mips / translate.c
blob58f483fa0a0dddd1be35e77b1bcc79a314b29fb5
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, see <http://www.gnu.org/licenses/>.
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <inttypes.h>
28 #include "cpu.h"
29 #include "exec-all.h"
30 #include "disas.h"
31 #include "tcg-op.h"
32 #include "qemu-common.h"
34 #include "helper.h"
35 #define GEN_HELPER 1
36 #include "helper.h"
38 //#define MIPS_DEBUG_DISAS
39 //#define MIPS_DEBUG_SIGN_EXTENSIONS
41 /* MIPS major opcodes */
42 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
44 enum {
45 /* indirect opcode tables */
46 OPC_SPECIAL = (0x00 << 26),
47 OPC_REGIMM = (0x01 << 26),
48 OPC_CP0 = (0x10 << 26),
49 OPC_CP1 = (0x11 << 26),
50 OPC_CP2 = (0x12 << 26),
51 OPC_CP3 = (0x13 << 26),
52 OPC_SPECIAL2 = (0x1C << 26),
53 OPC_SPECIAL3 = (0x1F << 26),
54 /* arithmetic with immediate */
55 OPC_ADDI = (0x08 << 26),
56 OPC_ADDIU = (0x09 << 26),
57 OPC_SLTI = (0x0A << 26),
58 OPC_SLTIU = (0x0B << 26),
59 /* logic with immediate */
60 OPC_ANDI = (0x0C << 26),
61 OPC_ORI = (0x0D << 26),
62 OPC_XORI = (0x0E << 26),
63 OPC_LUI = (0x0F << 26),
64 /* arithmetic with immediate */
65 OPC_DADDI = (0x18 << 26),
66 OPC_DADDIU = (0x19 << 26),
67 /* Jump and branches */
68 OPC_J = (0x02 << 26),
69 OPC_JAL = (0x03 << 26),
70 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
71 OPC_BEQL = (0x14 << 26),
72 OPC_BNE = (0x05 << 26),
73 OPC_BNEL = (0x15 << 26),
74 OPC_BLEZ = (0x06 << 26),
75 OPC_BLEZL = (0x16 << 26),
76 OPC_BGTZ = (0x07 << 26),
77 OPC_BGTZL = (0x17 << 26),
78 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
79 /* Load and stores */
80 OPC_LDL = (0x1A << 26),
81 OPC_LDR = (0x1B << 26),
82 OPC_LB = (0x20 << 26),
83 OPC_LH = (0x21 << 26),
84 OPC_LWL = (0x22 << 26),
85 OPC_LW = (0x23 << 26),
86 OPC_LBU = (0x24 << 26),
87 OPC_LHU = (0x25 << 26),
88 OPC_LWR = (0x26 << 26),
89 OPC_LWU = (0x27 << 26),
90 OPC_SB = (0x28 << 26),
91 OPC_SH = (0x29 << 26),
92 OPC_SWL = (0x2A << 26),
93 OPC_SW = (0x2B << 26),
94 OPC_SDL = (0x2C << 26),
95 OPC_SDR = (0x2D << 26),
96 OPC_SWR = (0x2E << 26),
97 OPC_LL = (0x30 << 26),
98 OPC_LLD = (0x34 << 26),
99 OPC_LD = (0x37 << 26),
100 OPC_SC = (0x38 << 26),
101 OPC_SCD = (0x3C << 26),
102 OPC_SD = (0x3F << 26),
103 /* Floating point load/store */
104 OPC_LWC1 = (0x31 << 26),
105 OPC_LWC2 = (0x32 << 26),
106 OPC_LDC1 = (0x35 << 26),
107 OPC_LDC2 = (0x36 << 26),
108 OPC_SWC1 = (0x39 << 26),
109 OPC_SWC2 = (0x3A << 26),
110 OPC_SDC1 = (0x3D << 26),
111 OPC_SDC2 = (0x3E << 26),
112 /* MDMX ASE specific */
113 OPC_MDMX = (0x1E << 26),
114 /* Cache and prefetch */
115 OPC_CACHE = (0x2F << 26),
116 OPC_PREF = (0x33 << 26),
117 /* Reserved major opcode */
118 OPC_MAJOR3B_RESERVED = (0x3B << 26),
121 /* MIPS special opcodes */
122 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
124 enum {
125 /* Shifts */
126 OPC_SLL = 0x00 | OPC_SPECIAL,
127 /* NOP is SLL r0, r0, 0 */
128 /* SSNOP is SLL r0, r0, 1 */
129 /* EHB is SLL r0, r0, 3 */
130 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
131 OPC_SRA = 0x03 | OPC_SPECIAL,
132 OPC_SLLV = 0x04 | OPC_SPECIAL,
133 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
134 OPC_SRAV = 0x07 | OPC_SPECIAL,
135 OPC_DSLLV = 0x14 | OPC_SPECIAL,
136 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
137 OPC_DSRAV = 0x17 | OPC_SPECIAL,
138 OPC_DSLL = 0x38 | OPC_SPECIAL,
139 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
140 OPC_DSRA = 0x3B | OPC_SPECIAL,
141 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
142 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
143 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
144 /* Multiplication / division */
145 OPC_MULT = 0x18 | OPC_SPECIAL,
146 OPC_MULTU = 0x19 | OPC_SPECIAL,
147 OPC_DIV = 0x1A | OPC_SPECIAL,
148 OPC_DIVU = 0x1B | OPC_SPECIAL,
149 OPC_DMULT = 0x1C | OPC_SPECIAL,
150 OPC_DMULTU = 0x1D | OPC_SPECIAL,
151 OPC_DDIV = 0x1E | OPC_SPECIAL,
152 OPC_DDIVU = 0x1F | OPC_SPECIAL,
153 /* 2 registers arithmetic / logic */
154 OPC_ADD = 0x20 | OPC_SPECIAL,
155 OPC_ADDU = 0x21 | OPC_SPECIAL,
156 OPC_SUB = 0x22 | OPC_SPECIAL,
157 OPC_SUBU = 0x23 | OPC_SPECIAL,
158 OPC_AND = 0x24 | OPC_SPECIAL,
159 OPC_OR = 0x25 | OPC_SPECIAL,
160 OPC_XOR = 0x26 | OPC_SPECIAL,
161 OPC_NOR = 0x27 | OPC_SPECIAL,
162 OPC_SLT = 0x2A | OPC_SPECIAL,
163 OPC_SLTU = 0x2B | OPC_SPECIAL,
164 OPC_DADD = 0x2C | OPC_SPECIAL,
165 OPC_DADDU = 0x2D | OPC_SPECIAL,
166 OPC_DSUB = 0x2E | OPC_SPECIAL,
167 OPC_DSUBU = 0x2F | OPC_SPECIAL,
168 /* Jumps */
169 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
170 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
171 /* Traps */
172 OPC_TGE = 0x30 | OPC_SPECIAL,
173 OPC_TGEU = 0x31 | OPC_SPECIAL,
174 OPC_TLT = 0x32 | OPC_SPECIAL,
175 OPC_TLTU = 0x33 | OPC_SPECIAL,
176 OPC_TEQ = 0x34 | OPC_SPECIAL,
177 OPC_TNE = 0x36 | OPC_SPECIAL,
178 /* HI / LO registers load & stores */
179 OPC_MFHI = 0x10 | OPC_SPECIAL,
180 OPC_MTHI = 0x11 | OPC_SPECIAL,
181 OPC_MFLO = 0x12 | OPC_SPECIAL,
182 OPC_MTLO = 0x13 | OPC_SPECIAL,
183 /* Conditional moves */
184 OPC_MOVZ = 0x0A | OPC_SPECIAL,
185 OPC_MOVN = 0x0B | OPC_SPECIAL,
187 OPC_MOVCI = 0x01 | OPC_SPECIAL,
189 /* Special */
190 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
191 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
192 OPC_BREAK = 0x0D | OPC_SPECIAL,
193 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
194 OPC_SYNC = 0x0F | OPC_SPECIAL,
196 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
197 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
198 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
199 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
200 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
201 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
202 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
205 /* Multiplication variants of the vr54xx. */
206 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
208 enum {
209 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
210 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
211 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
212 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
213 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
214 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
215 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
216 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
217 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
218 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
219 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
220 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
221 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
222 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
225 /* REGIMM (rt field) opcodes */
226 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
228 enum {
229 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
230 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
231 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
232 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
233 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
234 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
235 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
236 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
237 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
238 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
239 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
240 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
241 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
242 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
243 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
246 /* Special2 opcodes */
247 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
249 enum {
250 /* Multiply & xxx operations */
251 OPC_MADD = 0x00 | OPC_SPECIAL2,
252 OPC_MADDU = 0x01 | OPC_SPECIAL2,
253 OPC_MUL = 0x02 | OPC_SPECIAL2,
254 OPC_MSUB = 0x04 | OPC_SPECIAL2,
255 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
256 /* Misc */
257 OPC_CLZ = 0x20 | OPC_SPECIAL2,
258 OPC_CLO = 0x21 | OPC_SPECIAL2,
259 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
260 OPC_DCLO = 0x25 | OPC_SPECIAL2,
261 /* Special */
262 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
265 /* Special3 opcodes */
266 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
268 enum {
269 OPC_EXT = 0x00 | OPC_SPECIAL3,
270 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
271 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
272 OPC_DEXT = 0x03 | OPC_SPECIAL3,
273 OPC_INS = 0x04 | OPC_SPECIAL3,
274 OPC_DINSM = 0x05 | OPC_SPECIAL3,
275 OPC_DINSU = 0x06 | OPC_SPECIAL3,
276 OPC_DINS = 0x07 | OPC_SPECIAL3,
277 OPC_FORK = 0x08 | OPC_SPECIAL3,
278 OPC_YIELD = 0x09 | OPC_SPECIAL3,
279 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
280 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
281 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
284 /* BSHFL opcodes */
285 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
287 enum {
288 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
289 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
290 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
293 /* DBSHFL opcodes */
294 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
296 enum {
297 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
298 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
301 /* Coprocessor 0 (rs field) */
302 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
304 enum {
305 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
306 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
307 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
308 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
309 OPC_MFTR = (0x08 << 21) | OPC_CP0,
310 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
311 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
312 OPC_MTTR = (0x0C << 21) | OPC_CP0,
313 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
314 OPC_C0 = (0x10 << 21) | OPC_CP0,
315 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
316 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
319 /* MFMC0 opcodes */
320 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
322 enum {
323 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
324 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
325 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
326 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
327 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
328 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
331 /* Coprocessor 0 (with rs == C0) */
332 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
334 enum {
335 OPC_TLBR = 0x01 | OPC_C0,
336 OPC_TLBWI = 0x02 | OPC_C0,
337 OPC_TLBWR = 0x06 | OPC_C0,
338 OPC_TLBP = 0x08 | OPC_C0,
339 OPC_RFE = 0x10 | OPC_C0,
340 OPC_ERET = 0x18 | OPC_C0,
341 OPC_DERET = 0x1F | OPC_C0,
342 OPC_WAIT = 0x20 | OPC_C0,
345 /* Coprocessor 1 (rs field) */
346 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
348 enum {
349 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
350 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
351 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
352 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
353 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
354 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
355 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
356 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
357 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
358 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
359 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
360 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
361 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
362 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
363 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
364 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
365 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
366 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
369 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
370 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
372 enum {
373 OPC_BC1F = (0x00 << 16) | OPC_BC1,
374 OPC_BC1T = (0x01 << 16) | OPC_BC1,
375 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
376 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
379 enum {
380 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
381 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
384 enum {
385 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
386 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
389 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
391 enum {
392 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
393 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
394 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
395 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
396 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
397 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
398 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
399 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
400 OPC_BC2 = (0x08 << 21) | OPC_CP2,
403 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
405 enum {
406 OPC_LWXC1 = 0x00 | OPC_CP3,
407 OPC_LDXC1 = 0x01 | OPC_CP3,
408 OPC_LUXC1 = 0x05 | OPC_CP3,
409 OPC_SWXC1 = 0x08 | OPC_CP3,
410 OPC_SDXC1 = 0x09 | OPC_CP3,
411 OPC_SUXC1 = 0x0D | OPC_CP3,
412 OPC_PREFX = 0x0F | OPC_CP3,
413 OPC_ALNV_PS = 0x1E | OPC_CP3,
414 OPC_MADD_S = 0x20 | OPC_CP3,
415 OPC_MADD_D = 0x21 | OPC_CP3,
416 OPC_MADD_PS = 0x26 | OPC_CP3,
417 OPC_MSUB_S = 0x28 | OPC_CP3,
418 OPC_MSUB_D = 0x29 | OPC_CP3,
419 OPC_MSUB_PS = 0x2E | OPC_CP3,
420 OPC_NMADD_S = 0x30 | OPC_CP3,
421 OPC_NMADD_D = 0x31 | OPC_CP3,
422 OPC_NMADD_PS= 0x36 | OPC_CP3,
423 OPC_NMSUB_S = 0x38 | OPC_CP3,
424 OPC_NMSUB_D = 0x39 | OPC_CP3,
425 OPC_NMSUB_PS= 0x3E | OPC_CP3,
428 /* global register indices */
429 static TCGv_ptr cpu_env;
430 static TCGv cpu_gpr[32], cpu_PC;
431 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
432 static TCGv cpu_dspctrl, btarget, bcond;
433 static TCGv_i32 hflags;
434 static TCGv_i32 fpu_fcr0, fpu_fcr31;
436 #include "gen-icount.h"
438 #define gen_helper_0i(name, arg) do { \
439 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
440 gen_helper_##name(helper_tmp); \
441 tcg_temp_free_i32(helper_tmp); \
442 } while(0)
444 #define gen_helper_1i(name, arg1, arg2) do { \
445 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
446 gen_helper_##name(arg1, helper_tmp); \
447 tcg_temp_free_i32(helper_tmp); \
448 } while(0)
450 #define gen_helper_2i(name, arg1, arg2, arg3) do { \
451 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
452 gen_helper_##name(arg1, arg2, helper_tmp); \
453 tcg_temp_free_i32(helper_tmp); \
454 } while(0)
456 #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
457 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
458 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
459 tcg_temp_free_i32(helper_tmp); \
460 } while(0)
462 typedef struct DisasContext {
463 struct TranslationBlock *tb;
464 target_ulong pc, saved_pc;
465 uint32_t opcode;
466 int singlestep_enabled;
467 /* Routine used to access memory */
468 int mem_idx;
469 uint32_t hflags, saved_hflags;
470 int bstate;
471 target_ulong btarget;
472 } DisasContext;
474 enum {
475 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
476 * exception condition */
477 BS_STOP = 1, /* We want to stop translation for any reason */
478 BS_BRANCH = 2, /* We reached a branch condition */
479 BS_EXCP = 3, /* We reached an exception condition */
482 static const char *regnames[] =
483 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
484 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
485 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
486 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
488 static const char *regnames_HI[] =
489 { "HI0", "HI1", "HI2", "HI3", };
491 static const char *regnames_LO[] =
492 { "LO0", "LO1", "LO2", "LO3", };
494 static const char *regnames_ACX[] =
495 { "ACX0", "ACX1", "ACX2", "ACX3", };
497 static const char *fregnames[] =
498 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
499 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
500 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
501 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
503 #ifdef MIPS_DEBUG_DISAS
504 #define MIPS_DEBUG(fmt, ...) \
505 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
506 TARGET_FMT_lx ": %08x " fmt "\n", \
507 ctx->pc, ctx->opcode , ## __VA_ARGS__)
508 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
509 #else
510 #define MIPS_DEBUG(fmt, ...) do { } while(0)
511 #define LOG_DISAS(...) do { } while (0)
512 #endif
514 #define MIPS_INVAL(op) \
515 do { \
516 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
517 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
518 } while (0)
520 /* General purpose registers moves. */
521 static inline void gen_load_gpr (TCGv t, int reg)
523 if (reg == 0)
524 tcg_gen_movi_tl(t, 0);
525 else
526 tcg_gen_mov_tl(t, cpu_gpr[reg]);
529 static inline void gen_store_gpr (TCGv t, int reg)
531 if (reg != 0)
532 tcg_gen_mov_tl(cpu_gpr[reg], t);
535 /* Moves to/from ACX register. */
536 static inline void gen_load_ACX (TCGv t, int reg)
538 tcg_gen_mov_tl(t, cpu_ACX[reg]);
541 static inline void gen_store_ACX (TCGv t, int reg)
543 tcg_gen_mov_tl(cpu_ACX[reg], t);
546 /* Moves to/from shadow registers. */
547 static inline void gen_load_srsgpr (int from, int to)
549 TCGv t0 = tcg_temp_new();
551 if (from == 0)
552 tcg_gen_movi_tl(t0, 0);
553 else {
554 TCGv_i32 t2 = tcg_temp_new_i32();
555 TCGv_ptr addr = tcg_temp_new_ptr();
557 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
558 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
559 tcg_gen_andi_i32(t2, t2, 0xf);
560 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
561 tcg_gen_ext_i32_ptr(addr, t2);
562 tcg_gen_add_ptr(addr, cpu_env, addr);
564 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
565 tcg_temp_free_ptr(addr);
566 tcg_temp_free_i32(t2);
568 gen_store_gpr(t0, to);
569 tcg_temp_free(t0);
572 static inline void gen_store_srsgpr (int from, int to)
574 if (to != 0) {
575 TCGv t0 = tcg_temp_new();
576 TCGv_i32 t2 = tcg_temp_new_i32();
577 TCGv_ptr addr = tcg_temp_new_ptr();
579 gen_load_gpr(t0, from);
580 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
581 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
582 tcg_gen_andi_i32(t2, t2, 0xf);
583 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
584 tcg_gen_ext_i32_ptr(addr, t2);
585 tcg_gen_add_ptr(addr, cpu_env, addr);
587 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
588 tcg_temp_free_ptr(addr);
589 tcg_temp_free_i32(t2);
590 tcg_temp_free(t0);
594 /* Floating point register moves. */
595 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
597 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
600 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
602 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
605 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
607 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
610 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
612 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
615 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
617 if (ctx->hflags & MIPS_HFLAG_F64) {
618 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
619 } else {
620 TCGv_i32 t0 = tcg_temp_new_i32();
621 TCGv_i32 t1 = tcg_temp_new_i32();
622 gen_load_fpr32(t0, reg & ~1);
623 gen_load_fpr32(t1, reg | 1);
624 tcg_gen_concat_i32_i64(t, t0, t1);
625 tcg_temp_free_i32(t0);
626 tcg_temp_free_i32(t1);
630 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
632 if (ctx->hflags & MIPS_HFLAG_F64) {
633 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
634 } else {
635 TCGv_i64 t0 = tcg_temp_new_i64();
636 TCGv_i32 t1 = tcg_temp_new_i32();
637 tcg_gen_trunc_i64_i32(t1, t);
638 gen_store_fpr32(t1, reg & ~1);
639 tcg_gen_shri_i64(t0, t, 32);
640 tcg_gen_trunc_i64_i32(t1, t0);
641 gen_store_fpr32(t1, reg | 1);
642 tcg_temp_free_i32(t1);
643 tcg_temp_free_i64(t0);
647 static inline int get_fp_bit (int cc)
649 if (cc)
650 return 24 + cc;
651 else
652 return 23;
655 #define FOP_CONDS(type, fmt, bits) \
656 static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
657 TCGv_i##bits b, int cc) \
659 switch (n) { \
660 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
661 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
662 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
663 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
664 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
665 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
666 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
667 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
668 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
669 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
670 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
671 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
672 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
673 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
674 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
675 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
676 default: abort(); \
680 FOP_CONDS(, d, 64)
681 FOP_CONDS(abs, d, 64)
682 FOP_CONDS(, s, 32)
683 FOP_CONDS(abs, s, 32)
684 FOP_CONDS(, ps, 64)
685 FOP_CONDS(abs, ps, 64)
686 #undef FOP_CONDS
688 /* Tests */
689 #define OP_COND(name, cond) \
690 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, TCGv t1) \
692 int l1 = gen_new_label(); \
693 int l2 = gen_new_label(); \
695 tcg_gen_brcond_tl(cond, t0, t1, l1); \
696 tcg_gen_movi_tl(ret, 0); \
697 tcg_gen_br(l2); \
698 gen_set_label(l1); \
699 tcg_gen_movi_tl(ret, 1); \
700 gen_set_label(l2); \
702 OP_COND(eq, TCG_COND_EQ);
703 OP_COND(ne, TCG_COND_NE);
704 OP_COND(ge, TCG_COND_GE);
705 OP_COND(geu, TCG_COND_GEU);
706 OP_COND(lt, TCG_COND_LT);
707 OP_COND(ltu, TCG_COND_LTU);
708 #undef OP_COND
710 #define OP_CONDI(name, cond) \
711 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, target_ulong val) \
713 int l1 = gen_new_label(); \
714 int l2 = gen_new_label(); \
716 tcg_gen_brcondi_tl(cond, t0, val, l1); \
717 tcg_gen_movi_tl(ret, 0); \
718 tcg_gen_br(l2); \
719 gen_set_label(l1); \
720 tcg_gen_movi_tl(ret, 1); \
721 gen_set_label(l2); \
723 OP_CONDI(lti, TCG_COND_LT);
724 OP_CONDI(ltiu, TCG_COND_LTU);
725 #undef OP_CONDI
727 #define OP_CONDZ(name, cond) \
728 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0) \
730 int l1 = gen_new_label(); \
731 int l2 = gen_new_label(); \
733 tcg_gen_brcondi_tl(cond, t0, 0, l1); \
734 tcg_gen_movi_tl(ret, 0); \
735 tcg_gen_br(l2); \
736 gen_set_label(l1); \
737 tcg_gen_movi_tl(ret, 1); \
738 gen_set_label(l2); \
740 OP_CONDZ(gez, TCG_COND_GE);
741 OP_CONDZ(gtz, TCG_COND_GT);
742 OP_CONDZ(lez, TCG_COND_LE);
743 OP_CONDZ(ltz, TCG_COND_LT);
744 #undef OP_CONDZ
746 static inline void gen_save_pc(target_ulong pc)
748 tcg_gen_movi_tl(cpu_PC, pc);
751 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
753 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
754 if (do_save_pc && ctx->pc != ctx->saved_pc) {
755 gen_save_pc(ctx->pc);
756 ctx->saved_pc = ctx->pc;
758 if (ctx->hflags != ctx->saved_hflags) {
759 tcg_gen_movi_i32(hflags, ctx->hflags);
760 ctx->saved_hflags = ctx->hflags;
761 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
762 case MIPS_HFLAG_BR:
763 break;
764 case MIPS_HFLAG_BC:
765 case MIPS_HFLAG_BL:
766 case MIPS_HFLAG_B:
767 tcg_gen_movi_tl(btarget, ctx->btarget);
768 break;
773 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
775 ctx->saved_hflags = ctx->hflags;
776 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
777 case MIPS_HFLAG_BR:
778 break;
779 case MIPS_HFLAG_BC:
780 case MIPS_HFLAG_BL:
781 case MIPS_HFLAG_B:
782 ctx->btarget = env->btarget;
783 break;
787 static inline void
788 generate_exception_err (DisasContext *ctx, int excp, int err)
790 TCGv_i32 texcp = tcg_const_i32(excp);
791 TCGv_i32 terr = tcg_const_i32(err);
792 save_cpu_state(ctx, 1);
793 gen_helper_raise_exception_err(texcp, terr);
794 tcg_temp_free_i32(terr);
795 tcg_temp_free_i32(texcp);
798 static inline void
799 generate_exception (DisasContext *ctx, int excp)
801 save_cpu_state(ctx, 1);
802 gen_helper_0i(raise_exception, excp);
805 /* Addresses computation */
806 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
808 tcg_gen_add_tl(ret, arg0, arg1);
810 #if defined(TARGET_MIPS64)
811 /* For compatibility with 32-bit code, data reference in user mode
812 with Status_UX = 0 should be casted to 32-bit and sign extended.
813 See the MIPS64 PRA manual, section 4.10. */
814 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
815 !(ctx->hflags & MIPS_HFLAG_UX)) {
816 tcg_gen_ext32s_i64(ret, ret);
818 #endif
821 static inline void check_cp0_enabled(DisasContext *ctx)
823 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
824 generate_exception_err(ctx, EXCP_CpU, 1);
827 static inline void check_cp1_enabled(DisasContext *ctx)
829 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
830 generate_exception_err(ctx, EXCP_CpU, 1);
833 /* Verify that the processor is running with COP1X instructions enabled.
834 This is associated with the nabla symbol in the MIPS32 and MIPS64
835 opcode tables. */
837 static inline void check_cop1x(DisasContext *ctx)
839 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
840 generate_exception(ctx, EXCP_RI);
843 /* Verify that the processor is running with 64-bit floating-point
844 operations enabled. */
846 static inline void check_cp1_64bitmode(DisasContext *ctx)
848 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
849 generate_exception(ctx, EXCP_RI);
853 * Verify if floating point register is valid; an operation is not defined
854 * if bit 0 of any register specification is set and the FR bit in the
855 * Status register equals zero, since the register numbers specify an
856 * even-odd pair of adjacent coprocessor general registers. When the FR bit
857 * in the Status register equals one, both even and odd register numbers
858 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
860 * Multiple 64 bit wide registers can be checked by calling
861 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
863 static inline void check_cp1_registers(DisasContext *ctx, int regs)
865 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
866 generate_exception(ctx, EXCP_RI);
869 /* This code generates a "reserved instruction" exception if the
870 CPU does not support the instruction set corresponding to flags. */
871 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
873 if (unlikely(!(env->insn_flags & flags)))
874 generate_exception(ctx, EXCP_RI);
877 /* This code generates a "reserved instruction" exception if 64-bit
878 instructions are not enabled. */
879 static inline void check_mips_64(DisasContext *ctx)
881 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
882 generate_exception(ctx, EXCP_RI);
885 /* load/store instructions. */
886 #define OP_LD(insn,fname) \
887 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
889 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
891 OP_LD(lb,ld8s);
892 OP_LD(lbu,ld8u);
893 OP_LD(lh,ld16s);
894 OP_LD(lhu,ld16u);
895 OP_LD(lw,ld32s);
896 #if defined(TARGET_MIPS64)
897 OP_LD(lwu,ld32u);
898 OP_LD(ld,ld64);
899 #endif
900 #undef OP_LD
902 #define OP_ST(insn,fname) \
903 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
905 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
907 OP_ST(sb,st8);
908 OP_ST(sh,st16);
909 OP_ST(sw,st32);
910 #if defined(TARGET_MIPS64)
911 OP_ST(sd,st64);
912 #endif
913 #undef OP_ST
915 #define OP_LD_ATOMIC(insn,fname) \
916 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
918 TCGv t0 = tcg_temp_new(); \
919 tcg_gen_mov_tl(t0, arg1); \
920 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
921 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
922 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
923 tcg_temp_free(t0); \
925 OP_LD_ATOMIC(ll,ld32s);
926 #if defined(TARGET_MIPS64)
927 OP_LD_ATOMIC(lld,ld64);
928 #endif
929 #undef OP_LD_ATOMIC
931 #ifdef CONFIG_USER_ONLY
932 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
933 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
935 TCGv t0 = tcg_temp_new(); \
936 int l1 = gen_new_label(); \
937 int l2 = gen_new_label(); \
939 tcg_gen_andi_tl(t0, arg2, almask); \
940 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
941 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
942 generate_exception(ctx, EXCP_AdES); \
943 gen_set_label(l1); \
944 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
945 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
946 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
947 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
948 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
949 gen_helper_0i(raise_exception, EXCP_SC); \
950 gen_set_label(l2); \
951 tcg_gen_movi_tl(t0, 0); \
952 gen_store_gpr(t0, rt); \
953 tcg_temp_free(t0); \
955 #else
956 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
957 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
959 TCGv t0 = tcg_temp_new(); \
960 TCGv t1 = tcg_temp_new(); \
961 int l1 = gen_new_label(); \
962 int l2 = gen_new_label(); \
963 int l3 = gen_new_label(); \
965 tcg_gen_andi_tl(t0, arg2, almask); \
966 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
967 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
968 generate_exception(ctx, EXCP_AdES); \
969 gen_set_label(l1); \
970 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
971 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
972 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, llval)); \
973 tcg_gen_qemu_##ldname(t1, arg2, ctx->mem_idx); \
974 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l2); \
975 tcg_temp_free(t1); \
976 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
977 tcg_gen_movi_tl(t0, 1); \
978 gen_store_gpr(t0, rt); \
979 tcg_gen_br(l3); \
980 gen_set_label(l2); \
981 tcg_gen_movi_tl(t0, 0); \
982 gen_store_gpr(t0, rt); \
983 gen_set_label(l3); \
984 tcg_temp_free(t0); \
986 #endif
988 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
989 #if defined(TARGET_MIPS64)
990 OP_ST_ATOMIC(scd,st64,ld64,0x7);
991 #endif
992 #undef OP_ST_ATOMIC
994 /* Load and store */
995 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
996 int base, int16_t offset)
998 const char *opn = "ldst";
999 TCGv t0 = tcg_temp_new();
1000 TCGv t1 = tcg_temp_new();
1002 if (base == 0) {
1003 tcg_gen_movi_tl(t0, offset);
1004 } else if (offset == 0) {
1005 gen_load_gpr(t0, base);
1006 } else {
1007 tcg_gen_movi_tl(t0, offset);
1008 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
1010 /* Don't do NOP if destination is zero: we must perform the actual
1011 memory access. */
1012 switch (opc) {
1013 #if defined(TARGET_MIPS64)
1014 case OPC_LWU:
1015 save_cpu_state(ctx, 0);
1016 op_ldst_lwu(t0, t0, ctx);
1017 gen_store_gpr(t0, rt);
1018 opn = "lwu";
1019 break;
1020 case OPC_LD:
1021 save_cpu_state(ctx, 0);
1022 op_ldst_ld(t0, t0, ctx);
1023 gen_store_gpr(t0, rt);
1024 opn = "ld";
1025 break;
1026 case OPC_LLD:
1027 save_cpu_state(ctx, 0);
1028 op_ldst_lld(t0, t0, ctx);
1029 gen_store_gpr(t0, rt);
1030 opn = "lld";
1031 break;
1032 case OPC_SD:
1033 save_cpu_state(ctx, 0);
1034 gen_load_gpr(t1, rt);
1035 op_ldst_sd(t1, t0, ctx);
1036 opn = "sd";
1037 break;
1038 case OPC_LDL:
1039 save_cpu_state(ctx, 1);
1040 gen_load_gpr(t1, rt);
1041 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1042 gen_store_gpr(t1, rt);
1043 opn = "ldl";
1044 break;
1045 case OPC_SDL:
1046 save_cpu_state(ctx, 1);
1047 gen_load_gpr(t1, rt);
1048 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1049 opn = "sdl";
1050 break;
1051 case OPC_LDR:
1052 save_cpu_state(ctx, 1);
1053 gen_load_gpr(t1, rt);
1054 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1055 gen_store_gpr(t1, rt);
1056 opn = "ldr";
1057 break;
1058 case OPC_SDR:
1059 save_cpu_state(ctx, 1);
1060 gen_load_gpr(t1, rt);
1061 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1062 opn = "sdr";
1063 break;
1064 #endif
1065 case OPC_LW:
1066 save_cpu_state(ctx, 0);
1067 op_ldst_lw(t0, t0, ctx);
1068 gen_store_gpr(t0, rt);
1069 opn = "lw";
1070 break;
1071 case OPC_SW:
1072 save_cpu_state(ctx, 0);
1073 gen_load_gpr(t1, rt);
1074 op_ldst_sw(t1, t0, ctx);
1075 opn = "sw";
1076 break;
1077 case OPC_LH:
1078 save_cpu_state(ctx, 0);
1079 op_ldst_lh(t0, t0, ctx);
1080 gen_store_gpr(t0, rt);
1081 opn = "lh";
1082 break;
1083 case OPC_SH:
1084 save_cpu_state(ctx, 0);
1085 gen_load_gpr(t1, rt);
1086 op_ldst_sh(t1, t0, ctx);
1087 opn = "sh";
1088 break;
1089 case OPC_LHU:
1090 save_cpu_state(ctx, 0);
1091 op_ldst_lhu(t0, t0, ctx);
1092 gen_store_gpr(t0, rt);
1093 opn = "lhu";
1094 break;
1095 case OPC_LB:
1096 save_cpu_state(ctx, 0);
1097 op_ldst_lb(t0, t0, ctx);
1098 gen_store_gpr(t0, rt);
1099 opn = "lb";
1100 break;
1101 case OPC_SB:
1102 save_cpu_state(ctx, 0);
1103 gen_load_gpr(t1, rt);
1104 op_ldst_sb(t1, t0, ctx);
1105 opn = "sb";
1106 break;
1107 case OPC_LBU:
1108 save_cpu_state(ctx, 0);
1109 op_ldst_lbu(t0, t0, ctx);
1110 gen_store_gpr(t0, rt);
1111 opn = "lbu";
1112 break;
1113 case OPC_LWL:
1114 save_cpu_state(ctx, 1);
1115 gen_load_gpr(t1, rt);
1116 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1117 gen_store_gpr(t1, rt);
1118 opn = "lwl";
1119 break;
1120 case OPC_SWL:
1121 save_cpu_state(ctx, 1);
1122 gen_load_gpr(t1, rt);
1123 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1124 opn = "swr";
1125 break;
1126 case OPC_LWR:
1127 save_cpu_state(ctx, 1);
1128 gen_load_gpr(t1, rt);
1129 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1130 gen_store_gpr(t1, rt);
1131 opn = "lwr";
1132 break;
1133 case OPC_SWR:
1134 save_cpu_state(ctx, 1);
1135 gen_load_gpr(t1, rt);
1136 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1137 opn = "swr";
1138 break;
1139 case OPC_LL:
1140 save_cpu_state(ctx, 0);
1141 op_ldst_ll(t0, t0, ctx);
1142 gen_store_gpr(t0, rt);
1143 opn = "ll";
1144 break;
1146 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1147 tcg_temp_free(t0);
1148 tcg_temp_free(t1);
1151 /* Store conditional */
1152 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1153 int base, int16_t offset)
1155 const char *opn = "st_cond";
1156 TCGv t0, t1;
1158 t0 = tcg_temp_local_new();
1160 if (base == 0) {
1161 tcg_gen_movi_tl(t0, offset);
1162 } else if (offset == 0) {
1163 gen_load_gpr(t0, base);
1164 } else {
1165 tcg_gen_movi_tl(t0, offset);
1166 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
1168 /* Don't do NOP if destination is zero: we must perform the actual
1169 memory access. */
1171 t1 = tcg_temp_local_new();
1172 gen_load_gpr(t1, rt);
1173 switch (opc) {
1174 #if defined(TARGET_MIPS64)
1175 case OPC_SCD:
1176 save_cpu_state(ctx, 0);
1177 op_ldst_scd(t1, t0, rt, ctx);
1178 opn = "scd";
1179 break;
1180 #endif
1181 case OPC_SC:
1182 save_cpu_state(ctx, 0);
1183 op_ldst_sc(t1, t0, rt, ctx);
1184 opn = "sc";
1185 break;
1187 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1188 tcg_temp_free(t1);
1189 tcg_temp_free(t0);
1192 /* Load and store */
1193 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1194 int base, int16_t offset)
1196 const char *opn = "flt_ldst";
1197 TCGv t0 = tcg_temp_new();
1199 if (base == 0) {
1200 tcg_gen_movi_tl(t0, offset);
1201 } else if (offset == 0) {
1202 gen_load_gpr(t0, base);
1203 } else {
1204 tcg_gen_movi_tl(t0, offset);
1205 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
1207 /* Don't do NOP if destination is zero: we must perform the actual
1208 memory access. */
1209 switch (opc) {
1210 case OPC_LWC1:
1212 TCGv_i32 fp0 = tcg_temp_new_i32();
1214 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1215 tcg_gen_trunc_tl_i32(fp0, t0);
1216 gen_store_fpr32(fp0, ft);
1217 tcg_temp_free_i32(fp0);
1219 opn = "lwc1";
1220 break;
1221 case OPC_SWC1:
1223 TCGv_i32 fp0 = tcg_temp_new_i32();
1224 TCGv t1 = tcg_temp_new();
1226 gen_load_fpr32(fp0, ft);
1227 tcg_gen_extu_i32_tl(t1, fp0);
1228 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1229 tcg_temp_free(t1);
1230 tcg_temp_free_i32(fp0);
1232 opn = "swc1";
1233 break;
1234 case OPC_LDC1:
1236 TCGv_i64 fp0 = tcg_temp_new_i64();
1238 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1239 gen_store_fpr64(ctx, fp0, ft);
1240 tcg_temp_free_i64(fp0);
1242 opn = "ldc1";
1243 break;
1244 case OPC_SDC1:
1246 TCGv_i64 fp0 = tcg_temp_new_i64();
1248 gen_load_fpr64(ctx, fp0, ft);
1249 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1250 tcg_temp_free_i64(fp0);
1252 opn = "sdc1";
1253 break;
1254 default:
1255 MIPS_INVAL(opn);
1256 generate_exception(ctx, EXCP_RI);
1257 goto out;
1259 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1260 out:
1261 tcg_temp_free(t0);
1264 /* Arithmetic with immediate operand */
1265 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1266 int rt, int rs, int16_t imm)
1268 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1269 const char *opn = "imm arith";
1271 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1272 /* If no destination, treat it as a NOP.
1273 For addi, we must generate the overflow exception when needed. */
1274 MIPS_DEBUG("NOP");
1275 return;
1277 switch (opc) {
1278 case OPC_ADDI:
1280 TCGv t0 = tcg_temp_local_new();
1281 TCGv t1 = tcg_temp_new();
1282 TCGv t2 = tcg_temp_new();
1283 int l1 = gen_new_label();
1285 gen_load_gpr(t1, rs);
1286 tcg_gen_addi_tl(t0, t1, uimm);
1287 tcg_gen_ext32s_tl(t0, t0);
1289 tcg_gen_xori_tl(t1, t1, ~uimm);
1290 tcg_gen_xori_tl(t2, t0, uimm);
1291 tcg_gen_and_tl(t1, t1, t2);
1292 tcg_temp_free(t2);
1293 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1294 tcg_temp_free(t1);
1295 /* operands of same sign, result different sign */
1296 generate_exception(ctx, EXCP_OVERFLOW);
1297 gen_set_label(l1);
1298 tcg_gen_ext32s_tl(t0, t0);
1299 gen_store_gpr(t0, rt);
1300 tcg_temp_free(t0);
1302 opn = "addi";
1303 break;
1304 case OPC_ADDIU:
1305 if (rs != 0) {
1306 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1307 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1308 } else {
1309 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1311 opn = "addiu";
1312 break;
1313 #if defined(TARGET_MIPS64)
1314 case OPC_DADDI:
1316 TCGv t0 = tcg_temp_local_new();
1317 TCGv t1 = tcg_temp_new();
1318 TCGv t2 = tcg_temp_new();
1319 int l1 = gen_new_label();
1321 gen_load_gpr(t1, rs);
1322 tcg_gen_addi_tl(t0, t1, uimm);
1324 tcg_gen_xori_tl(t1, t1, ~uimm);
1325 tcg_gen_xori_tl(t2, t0, uimm);
1326 tcg_gen_and_tl(t1, t1, t2);
1327 tcg_temp_free(t2);
1328 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1329 tcg_temp_free(t1);
1330 /* operands of same sign, result different sign */
1331 generate_exception(ctx, EXCP_OVERFLOW);
1332 gen_set_label(l1);
1333 gen_store_gpr(t0, rt);
1334 tcg_temp_free(t0);
1336 opn = "daddi";
1337 break;
1338 case OPC_DADDIU:
1339 if (rs != 0) {
1340 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1341 } else {
1342 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1344 opn = "daddiu";
1345 break;
1346 #endif
1348 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1351 /* Logic with immediate operand */
1352 static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1354 target_ulong uimm;
1355 const char *opn = "imm logic";
1357 if (rt == 0) {
1358 /* If no destination, treat it as a NOP. */
1359 MIPS_DEBUG("NOP");
1360 return;
1362 uimm = (uint16_t)imm;
1363 switch (opc) {
1364 case OPC_ANDI:
1365 if (likely(rs != 0))
1366 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1367 else
1368 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1369 opn = "andi";
1370 break;
1371 case OPC_ORI:
1372 if (rs != 0)
1373 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1374 else
1375 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1376 opn = "ori";
1377 break;
1378 case OPC_XORI:
1379 if (likely(rs != 0))
1380 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1381 else
1382 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1383 opn = "xori";
1384 break;
1385 case OPC_LUI:
1386 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1387 opn = "lui";
1388 break;
1390 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1393 /* Set on less than with immediate operand */
1394 static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1396 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1397 const char *opn = "imm arith";
1398 TCGv t0;
1400 if (rt == 0) {
1401 /* If no destination, treat it as a NOP. */
1402 MIPS_DEBUG("NOP");
1403 return;
1405 t0 = tcg_temp_new();
1406 gen_load_gpr(t0, rs);
1407 switch (opc) {
1408 case OPC_SLTI:
1409 gen_op_lti(cpu_gpr[rt], t0, uimm);
1410 opn = "slti";
1411 break;
1412 case OPC_SLTIU:
1413 gen_op_ltiu(cpu_gpr[rt], t0, uimm);
1414 opn = "sltiu";
1415 break;
1417 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1418 tcg_temp_free(t0);
1421 /* Shifts with immediate operand */
1422 static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1423 int rt, int rs, int16_t imm)
1425 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1426 const char *opn = "imm shift";
1427 TCGv t0;
1429 if (rt == 0) {
1430 /* If no destination, treat it as a NOP. */
1431 MIPS_DEBUG("NOP");
1432 return;
1435 t0 = tcg_temp_new();
1436 gen_load_gpr(t0, rs);
1437 switch (opc) {
1438 case OPC_SLL:
1439 tcg_gen_shli_tl(t0, t0, uimm);
1440 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1441 opn = "sll";
1442 break;
1443 case OPC_SRA:
1444 tcg_gen_ext32s_tl(t0, t0);
1445 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1446 opn = "sra";
1447 break;
1448 case OPC_SRL:
1449 switch ((ctx->opcode >> 21) & 0x1f) {
1450 case 0:
1451 if (uimm != 0) {
1452 tcg_gen_ext32u_tl(t0, t0);
1453 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1454 } else {
1455 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1457 opn = "srl";
1458 break;
1459 case 1:
1460 /* rotr is decoded as srl on non-R2 CPUs */
1461 if (env->insn_flags & ISA_MIPS32R2) {
1462 if (uimm != 0) {
1463 TCGv_i32 t1 = tcg_temp_new_i32();
1465 tcg_gen_trunc_tl_i32(t1, t0);
1466 tcg_gen_rotri_i32(t1, t1, uimm);
1467 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1468 tcg_temp_free_i32(t1);
1470 opn = "rotr";
1471 } else {
1472 if (uimm != 0) {
1473 tcg_gen_ext32u_tl(t0, t0);
1474 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1475 } else {
1476 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1478 opn = "srl";
1480 break;
1481 default:
1482 MIPS_INVAL("invalid srl flag");
1483 generate_exception(ctx, EXCP_RI);
1484 break;
1486 break;
1487 #if defined(TARGET_MIPS64)
1488 case OPC_DSLL:
1489 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1490 opn = "dsll";
1491 break;
1492 case OPC_DSRA:
1493 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1494 opn = "dsra";
1495 break;
1496 case OPC_DSRL:
1497 switch ((ctx->opcode >> 21) & 0x1f) {
1498 case 0:
1499 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1500 opn = "dsrl";
1501 break;
1502 case 1:
1503 /* drotr is decoded as dsrl on non-R2 CPUs */
1504 if (env->insn_flags & ISA_MIPS32R2) {
1505 if (uimm != 0) {
1506 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1508 opn = "drotr";
1509 } else {
1510 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1511 opn = "dsrl";
1513 break;
1514 default:
1515 MIPS_INVAL("invalid dsrl flag");
1516 generate_exception(ctx, EXCP_RI);
1517 break;
1519 break;
1520 case OPC_DSLL32:
1521 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1522 opn = "dsll32";
1523 break;
1524 case OPC_DSRA32:
1525 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1526 opn = "dsra32";
1527 break;
1528 case OPC_DSRL32:
1529 switch ((ctx->opcode >> 21) & 0x1f) {
1530 case 0:
1531 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1532 opn = "dsrl32";
1533 break;
1534 case 1:
1535 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1536 if (env->insn_flags & ISA_MIPS32R2) {
1537 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1538 opn = "drotr32";
1539 } else {
1540 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1541 opn = "dsrl32";
1543 break;
1544 default:
1545 MIPS_INVAL("invalid dsrl32 flag");
1546 generate_exception(ctx, EXCP_RI);
1547 break;
1549 break;
1550 #endif
1552 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1553 tcg_temp_free(t0);
1556 /* Arithmetic */
1557 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1558 int rd, int rs, int rt)
1560 const char *opn = "arith";
1562 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1563 && opc != OPC_DADD && opc != OPC_DSUB) {
1564 /* If no destination, treat it as a NOP.
1565 For add & sub, we must generate the overflow exception when needed. */
1566 MIPS_DEBUG("NOP");
1567 return;
1570 switch (opc) {
1571 case OPC_ADD:
1573 TCGv t0 = tcg_temp_local_new();
1574 TCGv t1 = tcg_temp_new();
1575 TCGv t2 = tcg_temp_new();
1576 int l1 = gen_new_label();
1578 gen_load_gpr(t1, rs);
1579 gen_load_gpr(t2, rt);
1580 tcg_gen_add_tl(t0, t1, t2);
1581 tcg_gen_ext32s_tl(t0, t0);
1582 tcg_gen_xor_tl(t1, t1, t2);
1583 tcg_gen_not_tl(t1, t1);
1584 tcg_gen_xor_tl(t2, t0, t2);
1585 tcg_gen_and_tl(t1, t1, t2);
1586 tcg_temp_free(t2);
1587 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1588 tcg_temp_free(t1);
1589 /* operands of same sign, result different sign */
1590 generate_exception(ctx, EXCP_OVERFLOW);
1591 gen_set_label(l1);
1592 gen_store_gpr(t0, rd);
1593 tcg_temp_free(t0);
1595 opn = "add";
1596 break;
1597 case OPC_ADDU:
1598 if (rs != 0 && rt != 0) {
1599 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1600 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1601 } else if (rs == 0 && rt != 0) {
1602 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1603 } else if (rs != 0 && rt == 0) {
1604 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1605 } else {
1606 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1608 opn = "addu";
1609 break;
1610 case OPC_SUB:
1612 TCGv t0 = tcg_temp_local_new();
1613 TCGv t1 = tcg_temp_new();
1614 TCGv t2 = tcg_temp_new();
1615 int l1 = gen_new_label();
1617 gen_load_gpr(t1, rs);
1618 gen_load_gpr(t2, rt);
1619 tcg_gen_sub_tl(t0, t1, t2);
1620 tcg_gen_ext32s_tl(t0, t0);
1621 tcg_gen_xor_tl(t2, t1, t2);
1622 tcg_gen_xor_tl(t1, t0, t1);
1623 tcg_gen_and_tl(t1, t1, t2);
1624 tcg_temp_free(t2);
1625 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1626 tcg_temp_free(t1);
1627 /* operands of different sign, first operand and result different sign */
1628 generate_exception(ctx, EXCP_OVERFLOW);
1629 gen_set_label(l1);
1630 gen_store_gpr(t0, rd);
1631 tcg_temp_free(t0);
1633 opn = "sub";
1634 break;
1635 case OPC_SUBU:
1636 if (rs != 0 && rt != 0) {
1637 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1638 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1639 } else if (rs == 0 && rt != 0) {
1640 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1641 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1642 } else if (rs != 0 && rt == 0) {
1643 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1644 } else {
1645 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1647 opn = "subu";
1648 break;
1649 #if defined(TARGET_MIPS64)
1650 case OPC_DADD:
1652 TCGv t0 = tcg_temp_local_new();
1653 TCGv t1 = tcg_temp_new();
1654 TCGv t2 = tcg_temp_new();
1655 int l1 = gen_new_label();
1657 gen_load_gpr(t1, rs);
1658 gen_load_gpr(t2, rt);
1659 tcg_gen_add_tl(t0, t1, t2);
1660 tcg_gen_xor_tl(t1, t1, t2);
1661 tcg_gen_not_tl(t1, t1);
1662 tcg_gen_xor_tl(t2, t0, t2);
1663 tcg_gen_and_tl(t1, t1, t2);
1664 tcg_temp_free(t2);
1665 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1666 tcg_temp_free(t1);
1667 /* operands of same sign, result different sign */
1668 generate_exception(ctx, EXCP_OVERFLOW);
1669 gen_set_label(l1);
1670 gen_store_gpr(t0, rd);
1671 tcg_temp_free(t0);
1673 opn = "dadd";
1674 break;
1675 case OPC_DADDU:
1676 if (rs != 0 && rt != 0) {
1677 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1678 } else if (rs == 0 && rt != 0) {
1679 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1680 } else if (rs != 0 && rt == 0) {
1681 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1682 } else {
1683 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1685 opn = "daddu";
1686 break;
1687 case OPC_DSUB:
1689 TCGv t0 = tcg_temp_local_new();
1690 TCGv t1 = tcg_temp_new();
1691 TCGv t2 = tcg_temp_new();
1692 int l1 = gen_new_label();
1694 gen_load_gpr(t1, rs);
1695 gen_load_gpr(t2, rt);
1696 tcg_gen_sub_tl(t0, t1, t2);
1697 tcg_gen_xor_tl(t2, t1, t2);
1698 tcg_gen_xor_tl(t1, t0, t1);
1699 tcg_gen_and_tl(t1, t1, t2);
1700 tcg_temp_free(t2);
1701 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1702 tcg_temp_free(t1);
1703 /* operands of different sign, first operand and result different sign */
1704 generate_exception(ctx, EXCP_OVERFLOW);
1705 gen_set_label(l1);
1706 gen_store_gpr(t0, rd);
1707 tcg_temp_free(t0);
1709 opn = "dsub";
1710 break;
1711 case OPC_DSUBU:
1712 if (rs != 0 && rt != 0) {
1713 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1714 } else if (rs == 0 && rt != 0) {
1715 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1716 } else if (rs != 0 && rt == 0) {
1717 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1718 } else {
1719 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1721 opn = "dsubu";
1722 break;
1723 #endif
1724 case OPC_MUL:
1725 if (likely(rs != 0 && rt != 0)) {
1726 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1727 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1728 } else {
1729 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1731 opn = "mul";
1732 break;
1734 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1737 /* Conditional move */
1738 static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1740 const char *opn = "cond move";
1741 int l1;
1743 if (rd == 0) {
1744 /* If no destination, treat it as a NOP.
1745 For add & sub, we must generate the overflow exception when needed. */
1746 MIPS_DEBUG("NOP");
1747 return;
1750 l1 = gen_new_label();
1751 switch (opc) {
1752 case OPC_MOVN:
1753 if (likely(rt != 0))
1754 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1755 else
1756 tcg_gen_br(l1);
1757 opn = "movn";
1758 break;
1759 case OPC_MOVZ:
1760 if (likely(rt != 0))
1761 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1762 opn = "movz";
1763 break;
1765 if (rs != 0)
1766 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1767 else
1768 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1769 gen_set_label(l1);
1771 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1774 /* Logic */
1775 static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1777 const char *opn = "logic";
1779 if (rd == 0) {
1780 /* If no destination, treat it as a NOP. */
1781 MIPS_DEBUG("NOP");
1782 return;
1785 switch (opc) {
1786 case OPC_AND:
1787 if (likely(rs != 0 && rt != 0)) {
1788 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1789 } else {
1790 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1792 opn = "and";
1793 break;
1794 case OPC_NOR:
1795 if (rs != 0 && rt != 0) {
1796 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1797 } else if (rs == 0 && rt != 0) {
1798 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1799 } else if (rs != 0 && rt == 0) {
1800 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1801 } else {
1802 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1804 opn = "nor";
1805 break;
1806 case OPC_OR:
1807 if (likely(rs != 0 && rt != 0)) {
1808 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1809 } else if (rs == 0 && rt != 0) {
1810 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1811 } else if (rs != 0 && rt == 0) {
1812 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1813 } else {
1814 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1816 opn = "or";
1817 break;
1818 case OPC_XOR:
1819 if (likely(rs != 0 && rt != 0)) {
1820 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1821 } else if (rs == 0 && rt != 0) {
1822 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1823 } else if (rs != 0 && rt == 0) {
1824 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1825 } else {
1826 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1828 opn = "xor";
1829 break;
1831 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1834 /* Set on lower than */
1835 static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1837 const char *opn = "slt";
1838 TCGv t0, t1;
1840 if (rd == 0) {
1841 /* If no destination, treat it as a NOP. */
1842 MIPS_DEBUG("NOP");
1843 return;
1846 t0 = tcg_temp_new();
1847 t1 = tcg_temp_new();
1848 gen_load_gpr(t0, rs);
1849 gen_load_gpr(t1, rt);
1850 switch (opc) {
1851 case OPC_SLT:
1852 gen_op_lt(cpu_gpr[rd], t0, t1);
1853 opn = "slt";
1854 break;
1855 case OPC_SLTU:
1856 gen_op_ltu(cpu_gpr[rd], t0, t1);
1857 opn = "sltu";
1858 break;
1860 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1861 tcg_temp_free(t0);
1862 tcg_temp_free(t1);
1865 /* Shifts */
1866 static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1867 int rd, int rs, int rt)
1869 const char *opn = "shifts";
1870 TCGv t0, t1;
1872 if (rd == 0) {
1873 /* If no destination, treat it as a NOP.
1874 For add & sub, we must generate the overflow exception when needed. */
1875 MIPS_DEBUG("NOP");
1876 return;
1879 t0 = tcg_temp_new();
1880 t1 = tcg_temp_new();
1881 gen_load_gpr(t0, rs);
1882 gen_load_gpr(t1, rt);
1883 switch (opc) {
1884 case OPC_SLLV:
1885 tcg_gen_andi_tl(t0, t0, 0x1f);
1886 tcg_gen_shl_tl(t0, t1, t0);
1887 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1888 opn = "sllv";
1889 break;
1890 case OPC_SRAV:
1891 tcg_gen_ext32s_tl(t1, t1);
1892 tcg_gen_andi_tl(t0, t0, 0x1f);
1893 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1894 opn = "srav";
1895 break;
1896 case OPC_SRLV:
1897 switch ((ctx->opcode >> 6) & 0x1f) {
1898 case 0:
1899 tcg_gen_ext32u_tl(t1, t1);
1900 tcg_gen_andi_tl(t0, t0, 0x1f);
1901 tcg_gen_shr_tl(t0, t1, t0);
1902 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1903 opn = "srlv";
1904 break;
1905 case 1:
1906 /* rotrv is decoded as srlv on non-R2 CPUs */
1907 if (env->insn_flags & ISA_MIPS32R2) {
1908 TCGv_i32 t2 = tcg_temp_new_i32();
1909 TCGv_i32 t3 = tcg_temp_new_i32();
1911 tcg_gen_trunc_tl_i32(t2, t0);
1912 tcg_gen_trunc_tl_i32(t3, t1);
1913 tcg_gen_andi_i32(t2, t2, 0x1f);
1914 tcg_gen_rotr_i32(t2, t3, t2);
1915 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1916 tcg_temp_free_i32(t2);
1917 tcg_temp_free_i32(t3);
1918 opn = "rotrv";
1919 } else {
1920 tcg_gen_ext32u_tl(t1, t1);
1921 tcg_gen_andi_tl(t0, t0, 0x1f);
1922 tcg_gen_shr_tl(t0, t1, t0);
1923 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1924 opn = "srlv";
1926 break;
1927 default:
1928 MIPS_INVAL("invalid srlv flag");
1929 generate_exception(ctx, EXCP_RI);
1930 break;
1932 break;
1933 #if defined(TARGET_MIPS64)
1934 case OPC_DSLLV:
1935 tcg_gen_andi_tl(t0, t0, 0x3f);
1936 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1937 opn = "dsllv";
1938 break;
1939 case OPC_DSRAV:
1940 tcg_gen_andi_tl(t0, t0, 0x3f);
1941 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1942 opn = "dsrav";
1943 break;
1944 case OPC_DSRLV:
1945 switch ((ctx->opcode >> 6) & 0x1f) {
1946 case 0:
1947 tcg_gen_andi_tl(t0, t0, 0x3f);
1948 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1949 opn = "dsrlv";
1950 break;
1951 case 1:
1952 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1953 if (env->insn_flags & ISA_MIPS32R2) {
1954 tcg_gen_andi_tl(t0, t0, 0x3f);
1955 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1956 opn = "drotrv";
1957 } else {
1958 tcg_gen_andi_tl(t0, t0, 0x3f);
1959 tcg_gen_shr_tl(t0, t1, t0);
1960 opn = "dsrlv";
1962 break;
1963 default:
1964 MIPS_INVAL("invalid dsrlv flag");
1965 generate_exception(ctx, EXCP_RI);
1966 break;
1968 break;
1969 #endif
1971 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1972 tcg_temp_free(t0);
1973 tcg_temp_free(t1);
1976 /* Arithmetic on HI/LO registers */
1977 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1979 const char *opn = "hilo";
1981 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1982 /* Treat as NOP. */
1983 MIPS_DEBUG("NOP");
1984 return;
1986 switch (opc) {
1987 case OPC_MFHI:
1988 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1989 opn = "mfhi";
1990 break;
1991 case OPC_MFLO:
1992 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1993 opn = "mflo";
1994 break;
1995 case OPC_MTHI:
1996 if (reg != 0)
1997 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1998 else
1999 tcg_gen_movi_tl(cpu_HI[0], 0);
2000 opn = "mthi";
2001 break;
2002 case OPC_MTLO:
2003 if (reg != 0)
2004 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2005 else
2006 tcg_gen_movi_tl(cpu_LO[0], 0);
2007 opn = "mtlo";
2008 break;
2010 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2013 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
2014 int rs, int rt)
2016 const char *opn = "mul/div";
2017 TCGv t0, t1;
2019 switch (opc) {
2020 case OPC_DIV:
2021 case OPC_DIVU:
2022 #if defined(TARGET_MIPS64)
2023 case OPC_DDIV:
2024 case OPC_DDIVU:
2025 #endif
2026 t0 = tcg_temp_local_new();
2027 t1 = tcg_temp_local_new();
2028 break;
2029 default:
2030 t0 = tcg_temp_new();
2031 t1 = tcg_temp_new();
2032 break;
2035 gen_load_gpr(t0, rs);
2036 gen_load_gpr(t1, rt);
2037 switch (opc) {
2038 case OPC_DIV:
2040 int l1 = gen_new_label();
2041 int l2 = gen_new_label();
2043 tcg_gen_ext32s_tl(t0, t0);
2044 tcg_gen_ext32s_tl(t1, t1);
2045 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2046 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2047 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2049 tcg_gen_mov_tl(cpu_LO[0], t0);
2050 tcg_gen_movi_tl(cpu_HI[0], 0);
2051 tcg_gen_br(l1);
2052 gen_set_label(l2);
2053 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2054 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2055 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2056 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2057 gen_set_label(l1);
2059 opn = "div";
2060 break;
2061 case OPC_DIVU:
2063 int l1 = gen_new_label();
2065 tcg_gen_ext32u_tl(t0, t0);
2066 tcg_gen_ext32u_tl(t1, t1);
2067 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2068 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2069 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2070 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2071 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2072 gen_set_label(l1);
2074 opn = "divu";
2075 break;
2076 case OPC_MULT:
2078 TCGv_i64 t2 = tcg_temp_new_i64();
2079 TCGv_i64 t3 = tcg_temp_new_i64();
2081 tcg_gen_ext_tl_i64(t2, t0);
2082 tcg_gen_ext_tl_i64(t3, t1);
2083 tcg_gen_mul_i64(t2, t2, t3);
2084 tcg_temp_free_i64(t3);
2085 tcg_gen_trunc_i64_tl(t0, t2);
2086 tcg_gen_shri_i64(t2, t2, 32);
2087 tcg_gen_trunc_i64_tl(t1, t2);
2088 tcg_temp_free_i64(t2);
2089 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2090 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2092 opn = "mult";
2093 break;
2094 case OPC_MULTU:
2096 TCGv_i64 t2 = tcg_temp_new_i64();
2097 TCGv_i64 t3 = tcg_temp_new_i64();
2099 tcg_gen_ext32u_tl(t0, t0);
2100 tcg_gen_ext32u_tl(t1, t1);
2101 tcg_gen_extu_tl_i64(t2, t0);
2102 tcg_gen_extu_tl_i64(t3, t1);
2103 tcg_gen_mul_i64(t2, t2, t3);
2104 tcg_temp_free_i64(t3);
2105 tcg_gen_trunc_i64_tl(t0, t2);
2106 tcg_gen_shri_i64(t2, t2, 32);
2107 tcg_gen_trunc_i64_tl(t1, t2);
2108 tcg_temp_free_i64(t2);
2109 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2110 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2112 opn = "multu";
2113 break;
2114 #if defined(TARGET_MIPS64)
2115 case OPC_DDIV:
2117 int l1 = gen_new_label();
2118 int l2 = gen_new_label();
2120 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2121 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2122 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2123 tcg_gen_mov_tl(cpu_LO[0], t0);
2124 tcg_gen_movi_tl(cpu_HI[0], 0);
2125 tcg_gen_br(l1);
2126 gen_set_label(l2);
2127 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2128 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2129 gen_set_label(l1);
2131 opn = "ddiv";
2132 break;
2133 case OPC_DDIVU:
2135 int l1 = gen_new_label();
2137 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2138 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2139 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2140 gen_set_label(l1);
2142 opn = "ddivu";
2143 break;
2144 case OPC_DMULT:
2145 gen_helper_dmult(t0, t1);
2146 opn = "dmult";
2147 break;
2148 case OPC_DMULTU:
2149 gen_helper_dmultu(t0, t1);
2150 opn = "dmultu";
2151 break;
2152 #endif
2153 case OPC_MADD:
2155 TCGv_i64 t2 = tcg_temp_new_i64();
2156 TCGv_i64 t3 = tcg_temp_new_i64();
2158 tcg_gen_ext_tl_i64(t2, t0);
2159 tcg_gen_ext_tl_i64(t3, t1);
2160 tcg_gen_mul_i64(t2, t2, t3);
2161 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2162 tcg_gen_add_i64(t2, t2, t3);
2163 tcg_temp_free_i64(t3);
2164 tcg_gen_trunc_i64_tl(t0, t2);
2165 tcg_gen_shri_i64(t2, t2, 32);
2166 tcg_gen_trunc_i64_tl(t1, t2);
2167 tcg_temp_free_i64(t2);
2168 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2169 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2171 opn = "madd";
2172 break;
2173 case OPC_MADDU:
2175 TCGv_i64 t2 = tcg_temp_new_i64();
2176 TCGv_i64 t3 = tcg_temp_new_i64();
2178 tcg_gen_ext32u_tl(t0, t0);
2179 tcg_gen_ext32u_tl(t1, t1);
2180 tcg_gen_extu_tl_i64(t2, t0);
2181 tcg_gen_extu_tl_i64(t3, t1);
2182 tcg_gen_mul_i64(t2, t2, t3);
2183 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2184 tcg_gen_add_i64(t2, t2, t3);
2185 tcg_temp_free_i64(t3);
2186 tcg_gen_trunc_i64_tl(t0, t2);
2187 tcg_gen_shri_i64(t2, t2, 32);
2188 tcg_gen_trunc_i64_tl(t1, t2);
2189 tcg_temp_free_i64(t2);
2190 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2191 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2193 opn = "maddu";
2194 break;
2195 case OPC_MSUB:
2197 TCGv_i64 t2 = tcg_temp_new_i64();
2198 TCGv_i64 t3 = tcg_temp_new_i64();
2200 tcg_gen_ext_tl_i64(t2, t0);
2201 tcg_gen_ext_tl_i64(t3, t1);
2202 tcg_gen_mul_i64(t2, t2, t3);
2203 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2204 tcg_gen_sub_i64(t2, t3, t2);
2205 tcg_temp_free_i64(t3);
2206 tcg_gen_trunc_i64_tl(t0, t2);
2207 tcg_gen_shri_i64(t2, t2, 32);
2208 tcg_gen_trunc_i64_tl(t1, t2);
2209 tcg_temp_free_i64(t2);
2210 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2211 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2213 opn = "msub";
2214 break;
2215 case OPC_MSUBU:
2217 TCGv_i64 t2 = tcg_temp_new_i64();
2218 TCGv_i64 t3 = tcg_temp_new_i64();
2220 tcg_gen_ext32u_tl(t0, t0);
2221 tcg_gen_ext32u_tl(t1, t1);
2222 tcg_gen_extu_tl_i64(t2, t0);
2223 tcg_gen_extu_tl_i64(t3, t1);
2224 tcg_gen_mul_i64(t2, t2, t3);
2225 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2226 tcg_gen_sub_i64(t2, t3, t2);
2227 tcg_temp_free_i64(t3);
2228 tcg_gen_trunc_i64_tl(t0, t2);
2229 tcg_gen_shri_i64(t2, t2, 32);
2230 tcg_gen_trunc_i64_tl(t1, t2);
2231 tcg_temp_free_i64(t2);
2232 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2233 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2235 opn = "msubu";
2236 break;
2237 default:
2238 MIPS_INVAL(opn);
2239 generate_exception(ctx, EXCP_RI);
2240 goto out;
2242 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2243 out:
2244 tcg_temp_free(t0);
2245 tcg_temp_free(t1);
2248 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2249 int rd, int rs, int rt)
2251 const char *opn = "mul vr54xx";
2252 TCGv t0 = tcg_temp_new();
2253 TCGv t1 = tcg_temp_new();
2255 gen_load_gpr(t0, rs);
2256 gen_load_gpr(t1, rt);
2258 switch (opc) {
2259 case OPC_VR54XX_MULS:
2260 gen_helper_muls(t0, t0, t1);
2261 opn = "muls";
2262 break;
2263 case OPC_VR54XX_MULSU:
2264 gen_helper_mulsu(t0, t0, t1);
2265 opn = "mulsu";
2266 break;
2267 case OPC_VR54XX_MACC:
2268 gen_helper_macc(t0, t0, t1);
2269 opn = "macc";
2270 break;
2271 case OPC_VR54XX_MACCU:
2272 gen_helper_maccu(t0, t0, t1);
2273 opn = "maccu";
2274 break;
2275 case OPC_VR54XX_MSAC:
2276 gen_helper_msac(t0, t0, t1);
2277 opn = "msac";
2278 break;
2279 case OPC_VR54XX_MSACU:
2280 gen_helper_msacu(t0, t0, t1);
2281 opn = "msacu";
2282 break;
2283 case OPC_VR54XX_MULHI:
2284 gen_helper_mulhi(t0, t0, t1);
2285 opn = "mulhi";
2286 break;
2287 case OPC_VR54XX_MULHIU:
2288 gen_helper_mulhiu(t0, t0, t1);
2289 opn = "mulhiu";
2290 break;
2291 case OPC_VR54XX_MULSHI:
2292 gen_helper_mulshi(t0, t0, t1);
2293 opn = "mulshi";
2294 break;
2295 case OPC_VR54XX_MULSHIU:
2296 gen_helper_mulshiu(t0, t0, t1);
2297 opn = "mulshiu";
2298 break;
2299 case OPC_VR54XX_MACCHI:
2300 gen_helper_macchi(t0, t0, t1);
2301 opn = "macchi";
2302 break;
2303 case OPC_VR54XX_MACCHIU:
2304 gen_helper_macchiu(t0, t0, t1);
2305 opn = "macchiu";
2306 break;
2307 case OPC_VR54XX_MSACHI:
2308 gen_helper_msachi(t0, t0, t1);
2309 opn = "msachi";
2310 break;
2311 case OPC_VR54XX_MSACHIU:
2312 gen_helper_msachiu(t0, t0, t1);
2313 opn = "msachiu";
2314 break;
2315 default:
2316 MIPS_INVAL("mul vr54xx");
2317 generate_exception(ctx, EXCP_RI);
2318 goto out;
2320 gen_store_gpr(t0, rd);
2321 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2323 out:
2324 tcg_temp_free(t0);
2325 tcg_temp_free(t1);
2328 static void gen_cl (DisasContext *ctx, uint32_t opc,
2329 int rd, int rs)
2331 const char *opn = "CLx";
2332 TCGv t0;
2334 if (rd == 0) {
2335 /* Treat as NOP. */
2336 MIPS_DEBUG("NOP");
2337 return;
2339 t0 = tcg_temp_new();
2340 gen_load_gpr(t0, rs);
2341 switch (opc) {
2342 case OPC_CLO:
2343 gen_helper_clo(cpu_gpr[rd], t0);
2344 opn = "clo";
2345 break;
2346 case OPC_CLZ:
2347 gen_helper_clz(cpu_gpr[rd], t0);
2348 opn = "clz";
2349 break;
2350 #if defined(TARGET_MIPS64)
2351 case OPC_DCLO:
2352 gen_helper_dclo(cpu_gpr[rd], t0);
2353 opn = "dclo";
2354 break;
2355 case OPC_DCLZ:
2356 gen_helper_dclz(cpu_gpr[rd], t0);
2357 opn = "dclz";
2358 break;
2359 #endif
2361 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2362 tcg_temp_free(t0);
2365 /* Traps */
2366 static void gen_trap (DisasContext *ctx, uint32_t opc,
2367 int rs, int rt, int16_t imm)
2369 int cond;
2370 TCGv t0 = tcg_temp_new();
2371 TCGv t1 = tcg_temp_new();
2373 cond = 0;
2374 /* Load needed operands */
2375 switch (opc) {
2376 case OPC_TEQ:
2377 case OPC_TGE:
2378 case OPC_TGEU:
2379 case OPC_TLT:
2380 case OPC_TLTU:
2381 case OPC_TNE:
2382 /* Compare two registers */
2383 if (rs != rt) {
2384 gen_load_gpr(t0, rs);
2385 gen_load_gpr(t1, rt);
2386 cond = 1;
2388 break;
2389 case OPC_TEQI:
2390 case OPC_TGEI:
2391 case OPC_TGEIU:
2392 case OPC_TLTI:
2393 case OPC_TLTIU:
2394 case OPC_TNEI:
2395 /* Compare register to immediate */
2396 if (rs != 0 || imm != 0) {
2397 gen_load_gpr(t0, rs);
2398 tcg_gen_movi_tl(t1, (int32_t)imm);
2399 cond = 1;
2401 break;
2403 if (cond == 0) {
2404 switch (opc) {
2405 case OPC_TEQ: /* rs == rs */
2406 case OPC_TEQI: /* r0 == 0 */
2407 case OPC_TGE: /* rs >= rs */
2408 case OPC_TGEI: /* r0 >= 0 */
2409 case OPC_TGEU: /* rs >= rs unsigned */
2410 case OPC_TGEIU: /* r0 >= 0 unsigned */
2411 /* Always trap */
2412 generate_exception(ctx, EXCP_TRAP);
2413 break;
2414 case OPC_TLT: /* rs < rs */
2415 case OPC_TLTI: /* r0 < 0 */
2416 case OPC_TLTU: /* rs < rs unsigned */
2417 case OPC_TLTIU: /* r0 < 0 unsigned */
2418 case OPC_TNE: /* rs != rs */
2419 case OPC_TNEI: /* r0 != 0 */
2420 /* Never trap: treat as NOP. */
2421 break;
2423 } else {
2424 int l1 = gen_new_label();
2426 switch (opc) {
2427 case OPC_TEQ:
2428 case OPC_TEQI:
2429 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2430 break;
2431 case OPC_TGE:
2432 case OPC_TGEI:
2433 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2434 break;
2435 case OPC_TGEU:
2436 case OPC_TGEIU:
2437 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2438 break;
2439 case OPC_TLT:
2440 case OPC_TLTI:
2441 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2442 break;
2443 case OPC_TLTU:
2444 case OPC_TLTIU:
2445 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2446 break;
2447 case OPC_TNE:
2448 case OPC_TNEI:
2449 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2450 break;
2452 generate_exception(ctx, EXCP_TRAP);
2453 gen_set_label(l1);
2455 tcg_temp_free(t0);
2456 tcg_temp_free(t1);
2459 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2461 TranslationBlock *tb;
2462 tb = ctx->tb;
2463 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2464 likely(!ctx->singlestep_enabled)) {
2465 tcg_gen_goto_tb(n);
2466 gen_save_pc(dest);
2467 tcg_gen_exit_tb((long)tb + n);
2468 } else {
2469 gen_save_pc(dest);
2470 if (ctx->singlestep_enabled) {
2471 save_cpu_state(ctx, 0);
2472 gen_helper_0i(raise_exception, EXCP_DEBUG);
2474 tcg_gen_exit_tb(0);
2478 /* Branches (before delay slot) */
2479 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2480 int rs, int rt, int32_t offset)
2482 target_ulong btgt = -1;
2483 int blink = 0;
2484 int bcond_compute = 0;
2485 TCGv t0 = tcg_temp_new();
2486 TCGv t1 = tcg_temp_new();
2488 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2489 #ifdef MIPS_DEBUG_DISAS
2490 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2491 #endif
2492 generate_exception(ctx, EXCP_RI);
2493 goto out;
2496 /* Load needed operands */
2497 switch (opc) {
2498 case OPC_BEQ:
2499 case OPC_BEQL:
2500 case OPC_BNE:
2501 case OPC_BNEL:
2502 /* Compare two registers */
2503 if (rs != rt) {
2504 gen_load_gpr(t0, rs);
2505 gen_load_gpr(t1, rt);
2506 bcond_compute = 1;
2508 btgt = ctx->pc + 4 + offset;
2509 break;
2510 case OPC_BGEZ:
2511 case OPC_BGEZAL:
2512 case OPC_BGEZALL:
2513 case OPC_BGEZL:
2514 case OPC_BGTZ:
2515 case OPC_BGTZL:
2516 case OPC_BLEZ:
2517 case OPC_BLEZL:
2518 case OPC_BLTZ:
2519 case OPC_BLTZAL:
2520 case OPC_BLTZALL:
2521 case OPC_BLTZL:
2522 /* Compare to zero */
2523 if (rs != 0) {
2524 gen_load_gpr(t0, rs);
2525 bcond_compute = 1;
2527 btgt = ctx->pc + 4 + offset;
2528 break;
2529 case OPC_J:
2530 case OPC_JAL:
2531 /* Jump to immediate */
2532 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
2533 break;
2534 case OPC_JR:
2535 case OPC_JALR:
2536 /* Jump to register */
2537 if (offset != 0 && offset != 16) {
2538 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2539 others are reserved. */
2540 MIPS_INVAL("jump hint");
2541 generate_exception(ctx, EXCP_RI);
2542 goto out;
2544 gen_load_gpr(btarget, rs);
2545 break;
2546 default:
2547 MIPS_INVAL("branch/jump");
2548 generate_exception(ctx, EXCP_RI);
2549 goto out;
2551 if (bcond_compute == 0) {
2552 /* No condition to be computed */
2553 switch (opc) {
2554 case OPC_BEQ: /* rx == rx */
2555 case OPC_BEQL: /* rx == rx likely */
2556 case OPC_BGEZ: /* 0 >= 0 */
2557 case OPC_BGEZL: /* 0 >= 0 likely */
2558 case OPC_BLEZ: /* 0 <= 0 */
2559 case OPC_BLEZL: /* 0 <= 0 likely */
2560 /* Always take */
2561 ctx->hflags |= MIPS_HFLAG_B;
2562 MIPS_DEBUG("balways");
2563 break;
2564 case OPC_BGEZAL: /* 0 >= 0 */
2565 case OPC_BGEZALL: /* 0 >= 0 likely */
2566 /* Always take and link */
2567 blink = 31;
2568 ctx->hflags |= MIPS_HFLAG_B;
2569 MIPS_DEBUG("balways and link");
2570 break;
2571 case OPC_BNE: /* rx != rx */
2572 case OPC_BGTZ: /* 0 > 0 */
2573 case OPC_BLTZ: /* 0 < 0 */
2574 /* Treat as NOP. */
2575 MIPS_DEBUG("bnever (NOP)");
2576 goto out;
2577 case OPC_BLTZAL: /* 0 < 0 */
2578 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2579 MIPS_DEBUG("bnever and link");
2580 goto out;
2581 case OPC_BLTZALL: /* 0 < 0 likely */
2582 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2583 /* Skip the instruction in the delay slot */
2584 MIPS_DEBUG("bnever, link and skip");
2585 ctx->pc += 4;
2586 goto out;
2587 case OPC_BNEL: /* rx != rx likely */
2588 case OPC_BGTZL: /* 0 > 0 likely */
2589 case OPC_BLTZL: /* 0 < 0 likely */
2590 /* Skip the instruction in the delay slot */
2591 MIPS_DEBUG("bnever and skip");
2592 ctx->pc += 4;
2593 goto out;
2594 case OPC_J:
2595 ctx->hflags |= MIPS_HFLAG_B;
2596 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2597 break;
2598 case OPC_JAL:
2599 blink = 31;
2600 ctx->hflags |= MIPS_HFLAG_B;
2601 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2602 break;
2603 case OPC_JR:
2604 ctx->hflags |= MIPS_HFLAG_BR;
2605 MIPS_DEBUG("jr %s", regnames[rs]);
2606 break;
2607 case OPC_JALR:
2608 blink = rt;
2609 ctx->hflags |= MIPS_HFLAG_BR;
2610 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2611 break;
2612 default:
2613 MIPS_INVAL("branch/jump");
2614 generate_exception(ctx, EXCP_RI);
2615 goto out;
2617 } else {
2618 switch (opc) {
2619 case OPC_BEQ:
2620 gen_op_eq(bcond, t0, t1);
2621 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2622 regnames[rs], regnames[rt], btgt);
2623 goto not_likely;
2624 case OPC_BEQL:
2625 gen_op_eq(bcond, t0, t1);
2626 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2627 regnames[rs], regnames[rt], btgt);
2628 goto likely;
2629 case OPC_BNE:
2630 gen_op_ne(bcond, t0, t1);
2631 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2632 regnames[rs], regnames[rt], btgt);
2633 goto not_likely;
2634 case OPC_BNEL:
2635 gen_op_ne(bcond, t0, t1);
2636 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2637 regnames[rs], regnames[rt], btgt);
2638 goto likely;
2639 case OPC_BGEZ:
2640 gen_op_gez(bcond, t0);
2641 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2642 goto not_likely;
2643 case OPC_BGEZL:
2644 gen_op_gez(bcond, t0);
2645 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2646 goto likely;
2647 case OPC_BGEZAL:
2648 gen_op_gez(bcond, t0);
2649 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2650 blink = 31;
2651 goto not_likely;
2652 case OPC_BGEZALL:
2653 gen_op_gez(bcond, t0);
2654 blink = 31;
2655 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2656 goto likely;
2657 case OPC_BGTZ:
2658 gen_op_gtz(bcond, t0);
2659 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2660 goto not_likely;
2661 case OPC_BGTZL:
2662 gen_op_gtz(bcond, t0);
2663 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2664 goto likely;
2665 case OPC_BLEZ:
2666 gen_op_lez(bcond, t0);
2667 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2668 goto not_likely;
2669 case OPC_BLEZL:
2670 gen_op_lez(bcond, t0);
2671 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2672 goto likely;
2673 case OPC_BLTZ:
2674 gen_op_ltz(bcond, t0);
2675 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2676 goto not_likely;
2677 case OPC_BLTZL:
2678 gen_op_ltz(bcond, t0);
2679 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2680 goto likely;
2681 case OPC_BLTZAL:
2682 gen_op_ltz(bcond, t0);
2683 blink = 31;
2684 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2685 not_likely:
2686 ctx->hflags |= MIPS_HFLAG_BC;
2687 break;
2688 case OPC_BLTZALL:
2689 gen_op_ltz(bcond, t0);
2690 blink = 31;
2691 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2692 likely:
2693 ctx->hflags |= MIPS_HFLAG_BL;
2694 break;
2695 default:
2696 MIPS_INVAL("conditional branch/jump");
2697 generate_exception(ctx, EXCP_RI);
2698 goto out;
2701 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2702 blink, ctx->hflags, btgt);
2704 ctx->btarget = btgt;
2705 if (blink > 0) {
2706 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8);
2709 out:
2710 tcg_temp_free(t0);
2711 tcg_temp_free(t1);
2714 /* special3 bitfield operations */
2715 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2716 int rs, int lsb, int msb)
2718 TCGv t0 = tcg_temp_new();
2719 TCGv t1 = tcg_temp_new();
2720 target_ulong mask;
2722 gen_load_gpr(t1, rs);
2723 switch (opc) {
2724 case OPC_EXT:
2725 if (lsb + msb > 31)
2726 goto fail;
2727 tcg_gen_shri_tl(t0, t1, lsb);
2728 if (msb != 31) {
2729 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2730 } else {
2731 tcg_gen_ext32s_tl(t0, t0);
2733 break;
2734 #if defined(TARGET_MIPS64)
2735 case OPC_DEXTM:
2736 tcg_gen_shri_tl(t0, t1, lsb);
2737 if (msb != 31) {
2738 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2740 break;
2741 case OPC_DEXTU:
2742 tcg_gen_shri_tl(t0, t1, lsb + 32);
2743 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2744 break;
2745 case OPC_DEXT:
2746 tcg_gen_shri_tl(t0, t1, lsb);
2747 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2748 break;
2749 #endif
2750 case OPC_INS:
2751 if (lsb > msb)
2752 goto fail;
2753 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2754 gen_load_gpr(t0, rt);
2755 tcg_gen_andi_tl(t0, t0, ~mask);
2756 tcg_gen_shli_tl(t1, t1, lsb);
2757 tcg_gen_andi_tl(t1, t1, mask);
2758 tcg_gen_or_tl(t0, t0, t1);
2759 tcg_gen_ext32s_tl(t0, t0);
2760 break;
2761 #if defined(TARGET_MIPS64)
2762 case OPC_DINSM:
2763 if (lsb > msb)
2764 goto fail;
2765 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2766 gen_load_gpr(t0, rt);
2767 tcg_gen_andi_tl(t0, t0, ~mask);
2768 tcg_gen_shli_tl(t1, t1, lsb);
2769 tcg_gen_andi_tl(t1, t1, mask);
2770 tcg_gen_or_tl(t0, t0, t1);
2771 break;
2772 case OPC_DINSU:
2773 if (lsb > msb)
2774 goto fail;
2775 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2776 gen_load_gpr(t0, rt);
2777 tcg_gen_andi_tl(t0, t0, ~mask);
2778 tcg_gen_shli_tl(t1, t1, lsb + 32);
2779 tcg_gen_andi_tl(t1, t1, mask);
2780 tcg_gen_or_tl(t0, t0, t1);
2781 break;
2782 case OPC_DINS:
2783 if (lsb > msb)
2784 goto fail;
2785 gen_load_gpr(t0, rt);
2786 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2787 gen_load_gpr(t0, rt);
2788 tcg_gen_andi_tl(t0, t0, ~mask);
2789 tcg_gen_shli_tl(t1, t1, lsb);
2790 tcg_gen_andi_tl(t1, t1, mask);
2791 tcg_gen_or_tl(t0, t0, t1);
2792 break;
2793 #endif
2794 default:
2795 fail:
2796 MIPS_INVAL("bitops");
2797 generate_exception(ctx, EXCP_RI);
2798 tcg_temp_free(t0);
2799 tcg_temp_free(t1);
2800 return;
2802 gen_store_gpr(t0, rt);
2803 tcg_temp_free(t0);
2804 tcg_temp_free(t1);
2807 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2809 TCGv t0;
2811 if (rd == 0) {
2812 /* If no destination, treat it as a NOP. */
2813 MIPS_DEBUG("NOP");
2814 return;
2817 t0 = tcg_temp_new();
2818 gen_load_gpr(t0, rt);
2819 switch (op2) {
2820 case OPC_WSBH:
2822 TCGv t1 = tcg_temp_new();
2824 tcg_gen_shri_tl(t1, t0, 8);
2825 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2826 tcg_gen_shli_tl(t0, t0, 8);
2827 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2828 tcg_gen_or_tl(t0, t0, t1);
2829 tcg_temp_free(t1);
2830 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2832 break;
2833 case OPC_SEB:
2834 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2835 break;
2836 case OPC_SEH:
2837 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2838 break;
2839 #if defined(TARGET_MIPS64)
2840 case OPC_DSBH:
2842 TCGv t1 = tcg_temp_new();
2844 tcg_gen_shri_tl(t1, t0, 8);
2845 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2846 tcg_gen_shli_tl(t0, t0, 8);
2847 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2848 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2849 tcg_temp_free(t1);
2851 break;
2852 case OPC_DSHD:
2854 TCGv t1 = tcg_temp_new();
2856 tcg_gen_shri_tl(t1, t0, 16);
2857 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2858 tcg_gen_shli_tl(t0, t0, 16);
2859 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2860 tcg_gen_or_tl(t0, t0, t1);
2861 tcg_gen_shri_tl(t1, t0, 32);
2862 tcg_gen_shli_tl(t0, t0, 32);
2863 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2864 tcg_temp_free(t1);
2866 break;
2867 #endif
2868 default:
2869 MIPS_INVAL("bsfhl");
2870 generate_exception(ctx, EXCP_RI);
2871 tcg_temp_free(t0);
2872 return;
2874 tcg_temp_free(t0);
2877 #ifndef CONFIG_USER_ONLY
2878 /* CP0 (MMU and control) */
2879 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
2881 TCGv_i32 t0 = tcg_temp_new_i32();
2883 tcg_gen_ld_i32(t0, cpu_env, off);
2884 tcg_gen_ext_i32_tl(arg, t0);
2885 tcg_temp_free_i32(t0);
2888 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
2890 tcg_gen_ld_tl(arg, cpu_env, off);
2891 tcg_gen_ext32s_tl(arg, arg);
2894 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
2896 TCGv_i32 t0 = tcg_temp_new_i32();
2898 tcg_gen_trunc_tl_i32(t0, arg);
2899 tcg_gen_st_i32(t0, cpu_env, off);
2900 tcg_temp_free_i32(t0);
2903 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
2905 tcg_gen_ext32s_tl(arg, arg);
2906 tcg_gen_st_tl(arg, cpu_env, off);
2909 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
2911 const char *rn = "invalid";
2913 if (sel != 0)
2914 check_insn(env, ctx, ISA_MIPS32);
2916 switch (reg) {
2917 case 0:
2918 switch (sel) {
2919 case 0:
2920 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
2921 rn = "Index";
2922 break;
2923 case 1:
2924 check_insn(env, ctx, ASE_MT);
2925 gen_helper_mfc0_mvpcontrol(arg);
2926 rn = "MVPControl";
2927 break;
2928 case 2:
2929 check_insn(env, ctx, ASE_MT);
2930 gen_helper_mfc0_mvpconf0(arg);
2931 rn = "MVPConf0";
2932 break;
2933 case 3:
2934 check_insn(env, ctx, ASE_MT);
2935 gen_helper_mfc0_mvpconf1(arg);
2936 rn = "MVPConf1";
2937 break;
2938 default:
2939 goto die;
2941 break;
2942 case 1:
2943 switch (sel) {
2944 case 0:
2945 gen_helper_mfc0_random(arg);
2946 rn = "Random";
2947 break;
2948 case 1:
2949 check_insn(env, ctx, ASE_MT);
2950 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
2951 rn = "VPEControl";
2952 break;
2953 case 2:
2954 check_insn(env, ctx, ASE_MT);
2955 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
2956 rn = "VPEConf0";
2957 break;
2958 case 3:
2959 check_insn(env, ctx, ASE_MT);
2960 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
2961 rn = "VPEConf1";
2962 break;
2963 case 4:
2964 check_insn(env, ctx, ASE_MT);
2965 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
2966 rn = "YQMask";
2967 break;
2968 case 5:
2969 check_insn(env, ctx, ASE_MT);
2970 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
2971 rn = "VPESchedule";
2972 break;
2973 case 6:
2974 check_insn(env, ctx, ASE_MT);
2975 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
2976 rn = "VPEScheFBack";
2977 break;
2978 case 7:
2979 check_insn(env, ctx, ASE_MT);
2980 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
2981 rn = "VPEOpt";
2982 break;
2983 default:
2984 goto die;
2986 break;
2987 case 2:
2988 switch (sel) {
2989 case 0:
2990 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2991 tcg_gen_ext32s_tl(arg, arg);
2992 rn = "EntryLo0";
2993 break;
2994 case 1:
2995 check_insn(env, ctx, ASE_MT);
2996 gen_helper_mfc0_tcstatus(arg);
2997 rn = "TCStatus";
2998 break;
2999 case 2:
3000 check_insn(env, ctx, ASE_MT);
3001 gen_helper_mfc0_tcbind(arg);
3002 rn = "TCBind";
3003 break;
3004 case 3:
3005 check_insn(env, ctx, ASE_MT);
3006 gen_helper_mfc0_tcrestart(arg);
3007 rn = "TCRestart";
3008 break;
3009 case 4:
3010 check_insn(env, ctx, ASE_MT);
3011 gen_helper_mfc0_tchalt(arg);
3012 rn = "TCHalt";
3013 break;
3014 case 5:
3015 check_insn(env, ctx, ASE_MT);
3016 gen_helper_mfc0_tccontext(arg);
3017 rn = "TCContext";
3018 break;
3019 case 6:
3020 check_insn(env, ctx, ASE_MT);
3021 gen_helper_mfc0_tcschedule(arg);
3022 rn = "TCSchedule";
3023 break;
3024 case 7:
3025 check_insn(env, ctx, ASE_MT);
3026 gen_helper_mfc0_tcschefback(arg);
3027 rn = "TCScheFBack";
3028 break;
3029 default:
3030 goto die;
3032 break;
3033 case 3:
3034 switch (sel) {
3035 case 0:
3036 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
3037 tcg_gen_ext32s_tl(arg, arg);
3038 rn = "EntryLo1";
3039 break;
3040 default:
3041 goto die;
3043 break;
3044 case 4:
3045 switch (sel) {
3046 case 0:
3047 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3048 tcg_gen_ext32s_tl(arg, arg);
3049 rn = "Context";
3050 break;
3051 case 1:
3052 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3053 rn = "ContextConfig";
3054 // break;
3055 default:
3056 goto die;
3058 break;
3059 case 5:
3060 switch (sel) {
3061 case 0:
3062 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
3063 rn = "PageMask";
3064 break;
3065 case 1:
3066 check_insn(env, ctx, ISA_MIPS32R2);
3067 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
3068 rn = "PageGrain";
3069 break;
3070 default:
3071 goto die;
3073 break;
3074 case 6:
3075 switch (sel) {
3076 case 0:
3077 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
3078 rn = "Wired";
3079 break;
3080 case 1:
3081 check_insn(env, ctx, ISA_MIPS32R2);
3082 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
3083 rn = "SRSConf0";
3084 break;
3085 case 2:
3086 check_insn(env, ctx, ISA_MIPS32R2);
3087 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
3088 rn = "SRSConf1";
3089 break;
3090 case 3:
3091 check_insn(env, ctx, ISA_MIPS32R2);
3092 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
3093 rn = "SRSConf2";
3094 break;
3095 case 4:
3096 check_insn(env, ctx, ISA_MIPS32R2);
3097 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
3098 rn = "SRSConf3";
3099 break;
3100 case 5:
3101 check_insn(env, ctx, ISA_MIPS32R2);
3102 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
3103 rn = "SRSConf4";
3104 break;
3105 default:
3106 goto die;
3108 break;
3109 case 7:
3110 switch (sel) {
3111 case 0:
3112 check_insn(env, ctx, ISA_MIPS32R2);
3113 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
3114 rn = "HWREna";
3115 break;
3116 default:
3117 goto die;
3119 break;
3120 case 8:
3121 switch (sel) {
3122 case 0:
3123 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3124 tcg_gen_ext32s_tl(arg, arg);
3125 rn = "BadVAddr";
3126 break;
3127 default:
3128 goto die;
3130 break;
3131 case 9:
3132 switch (sel) {
3133 case 0:
3134 /* Mark as an IO operation because we read the time. */
3135 if (use_icount)
3136 gen_io_start();
3137 gen_helper_mfc0_count(arg);
3138 if (use_icount) {
3139 gen_io_end();
3140 ctx->bstate = BS_STOP;
3142 rn = "Count";
3143 break;
3144 /* 6,7 are implementation dependent */
3145 default:
3146 goto die;
3148 break;
3149 case 10:
3150 switch (sel) {
3151 case 0:
3152 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3153 tcg_gen_ext32s_tl(arg, arg);
3154 rn = "EntryHi";
3155 break;
3156 default:
3157 goto die;
3159 break;
3160 case 11:
3161 switch (sel) {
3162 case 0:
3163 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
3164 rn = "Compare";
3165 break;
3166 /* 6,7 are implementation dependent */
3167 default:
3168 goto die;
3170 break;
3171 case 12:
3172 switch (sel) {
3173 case 0:
3174 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
3175 rn = "Status";
3176 break;
3177 case 1:
3178 check_insn(env, ctx, ISA_MIPS32R2);
3179 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
3180 rn = "IntCtl";
3181 break;
3182 case 2:
3183 check_insn(env, ctx, ISA_MIPS32R2);
3184 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
3185 rn = "SRSCtl";
3186 break;
3187 case 3:
3188 check_insn(env, ctx, ISA_MIPS32R2);
3189 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
3190 rn = "SRSMap";
3191 break;
3192 default:
3193 goto die;
3195 break;
3196 case 13:
3197 switch (sel) {
3198 case 0:
3199 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
3200 rn = "Cause";
3201 break;
3202 default:
3203 goto die;
3205 break;
3206 case 14:
3207 switch (sel) {
3208 case 0:
3209 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3210 tcg_gen_ext32s_tl(arg, arg);
3211 rn = "EPC";
3212 break;
3213 default:
3214 goto die;
3216 break;
3217 case 15:
3218 switch (sel) {
3219 case 0:
3220 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
3221 rn = "PRid";
3222 break;
3223 case 1:
3224 check_insn(env, ctx, ISA_MIPS32R2);
3225 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
3226 rn = "EBase";
3227 break;
3228 default:
3229 goto die;
3231 break;
3232 case 16:
3233 switch (sel) {
3234 case 0:
3235 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
3236 rn = "Config";
3237 break;
3238 case 1:
3239 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
3240 rn = "Config1";
3241 break;
3242 case 2:
3243 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
3244 rn = "Config2";
3245 break;
3246 case 3:
3247 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
3248 rn = "Config3";
3249 break;
3250 /* 4,5 are reserved */
3251 /* 6,7 are implementation dependent */
3252 case 6:
3253 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
3254 rn = "Config6";
3255 break;
3256 case 7:
3257 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
3258 rn = "Config7";
3259 break;
3260 default:
3261 goto die;
3263 break;
3264 case 17:
3265 switch (sel) {
3266 case 0:
3267 gen_helper_mfc0_lladdr(arg);
3268 rn = "LLAddr";
3269 break;
3270 default:
3271 goto die;
3273 break;
3274 case 18:
3275 switch (sel) {
3276 case 0 ... 7:
3277 gen_helper_1i(mfc0_watchlo, arg, sel);
3278 rn = "WatchLo";
3279 break;
3280 default:
3281 goto die;
3283 break;
3284 case 19:
3285 switch (sel) {
3286 case 0 ...7:
3287 gen_helper_1i(mfc0_watchhi, arg, sel);
3288 rn = "WatchHi";
3289 break;
3290 default:
3291 goto die;
3293 break;
3294 case 20:
3295 switch (sel) {
3296 case 0:
3297 #if defined(TARGET_MIPS64)
3298 check_insn(env, ctx, ISA_MIPS3);
3299 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3300 tcg_gen_ext32s_tl(arg, arg);
3301 rn = "XContext";
3302 break;
3303 #endif
3304 default:
3305 goto die;
3307 break;
3308 case 21:
3309 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3310 switch (sel) {
3311 case 0:
3312 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
3313 rn = "Framemask";
3314 break;
3315 default:
3316 goto die;
3318 break;
3319 case 22:
3320 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3321 rn = "'Diagnostic"; /* implementation dependent */
3322 break;
3323 case 23:
3324 switch (sel) {
3325 case 0:
3326 gen_helper_mfc0_debug(arg); /* EJTAG support */
3327 rn = "Debug";
3328 break;
3329 case 1:
3330 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3331 rn = "TraceControl";
3332 // break;
3333 case 2:
3334 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3335 rn = "TraceControl2";
3336 // break;
3337 case 3:
3338 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3339 rn = "UserTraceData";
3340 // break;
3341 case 4:
3342 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3343 rn = "TraceBPC";
3344 // break;
3345 default:
3346 goto die;
3348 break;
3349 case 24:
3350 switch (sel) {
3351 case 0:
3352 /* EJTAG support */
3353 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3354 tcg_gen_ext32s_tl(arg, arg);
3355 rn = "DEPC";
3356 break;
3357 default:
3358 goto die;
3360 break;
3361 case 25:
3362 switch (sel) {
3363 case 0:
3364 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
3365 rn = "Performance0";
3366 break;
3367 case 1:
3368 // gen_helper_mfc0_performance1(arg);
3369 rn = "Performance1";
3370 // break;
3371 case 2:
3372 // gen_helper_mfc0_performance2(arg);
3373 rn = "Performance2";
3374 // break;
3375 case 3:
3376 // gen_helper_mfc0_performance3(arg);
3377 rn = "Performance3";
3378 // break;
3379 case 4:
3380 // gen_helper_mfc0_performance4(arg);
3381 rn = "Performance4";
3382 // break;
3383 case 5:
3384 // gen_helper_mfc0_performance5(arg);
3385 rn = "Performance5";
3386 // break;
3387 case 6:
3388 // gen_helper_mfc0_performance6(arg);
3389 rn = "Performance6";
3390 // break;
3391 case 7:
3392 // gen_helper_mfc0_performance7(arg);
3393 rn = "Performance7";
3394 // break;
3395 default:
3396 goto die;
3398 break;
3399 case 26:
3400 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3401 rn = "ECC";
3402 break;
3403 case 27:
3404 switch (sel) {
3405 case 0 ... 3:
3406 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3407 rn = "CacheErr";
3408 break;
3409 default:
3410 goto die;
3412 break;
3413 case 28:
3414 switch (sel) {
3415 case 0:
3416 case 2:
3417 case 4:
3418 case 6:
3419 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
3420 rn = "TagLo";
3421 break;
3422 case 1:
3423 case 3:
3424 case 5:
3425 case 7:
3426 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
3427 rn = "DataLo";
3428 break;
3429 default:
3430 goto die;
3432 break;
3433 case 29:
3434 switch (sel) {
3435 case 0:
3436 case 2:
3437 case 4:
3438 case 6:
3439 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
3440 rn = "TagHi";
3441 break;
3442 case 1:
3443 case 3:
3444 case 5:
3445 case 7:
3446 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
3447 rn = "DataHi";
3448 break;
3449 default:
3450 goto die;
3452 break;
3453 case 30:
3454 switch (sel) {
3455 case 0:
3456 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3457 tcg_gen_ext32s_tl(arg, arg);
3458 rn = "ErrorEPC";
3459 break;
3460 default:
3461 goto die;
3463 break;
3464 case 31:
3465 switch (sel) {
3466 case 0:
3467 /* EJTAG support */
3468 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
3469 rn = "DESAVE";
3470 break;
3471 default:
3472 goto die;
3474 break;
3475 default:
3476 goto die;
3478 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3479 return;
3481 die:
3482 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3483 generate_exception(ctx, EXCP_RI);
3486 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3488 const char *rn = "invalid";
3490 if (sel != 0)
3491 check_insn(env, ctx, ISA_MIPS32);
3493 if (use_icount)
3494 gen_io_start();
3496 switch (reg) {
3497 case 0:
3498 switch (sel) {
3499 case 0:
3500 gen_helper_mtc0_index(arg);
3501 rn = "Index";
3502 break;
3503 case 1:
3504 check_insn(env, ctx, ASE_MT);
3505 gen_helper_mtc0_mvpcontrol(arg);
3506 rn = "MVPControl";
3507 break;
3508 case 2:
3509 check_insn(env, ctx, ASE_MT);
3510 /* ignored */
3511 rn = "MVPConf0";
3512 break;
3513 case 3:
3514 check_insn(env, ctx, ASE_MT);
3515 /* ignored */
3516 rn = "MVPConf1";
3517 break;
3518 default:
3519 goto die;
3521 break;
3522 case 1:
3523 switch (sel) {
3524 case 0:
3525 /* ignored */
3526 rn = "Random";
3527 break;
3528 case 1:
3529 check_insn(env, ctx, ASE_MT);
3530 gen_helper_mtc0_vpecontrol(arg);
3531 rn = "VPEControl";
3532 break;
3533 case 2:
3534 check_insn(env, ctx, ASE_MT);
3535 gen_helper_mtc0_vpeconf0(arg);
3536 rn = "VPEConf0";
3537 break;
3538 case 3:
3539 check_insn(env, ctx, ASE_MT);
3540 gen_helper_mtc0_vpeconf1(arg);
3541 rn = "VPEConf1";
3542 break;
3543 case 4:
3544 check_insn(env, ctx, ASE_MT);
3545 gen_helper_mtc0_yqmask(arg);
3546 rn = "YQMask";
3547 break;
3548 case 5:
3549 check_insn(env, ctx, ASE_MT);
3550 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
3551 rn = "VPESchedule";
3552 break;
3553 case 6:
3554 check_insn(env, ctx, ASE_MT);
3555 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3556 rn = "VPEScheFBack";
3557 break;
3558 case 7:
3559 check_insn(env, ctx, ASE_MT);
3560 gen_helper_mtc0_vpeopt(arg);
3561 rn = "VPEOpt";
3562 break;
3563 default:
3564 goto die;
3566 break;
3567 case 2:
3568 switch (sel) {
3569 case 0:
3570 gen_helper_mtc0_entrylo0(arg);
3571 rn = "EntryLo0";
3572 break;
3573 case 1:
3574 check_insn(env, ctx, ASE_MT);
3575 gen_helper_mtc0_tcstatus(arg);
3576 rn = "TCStatus";
3577 break;
3578 case 2:
3579 check_insn(env, ctx, ASE_MT);
3580 gen_helper_mtc0_tcbind(arg);
3581 rn = "TCBind";
3582 break;
3583 case 3:
3584 check_insn(env, ctx, ASE_MT);
3585 gen_helper_mtc0_tcrestart(arg);
3586 rn = "TCRestart";
3587 break;
3588 case 4:
3589 check_insn(env, ctx, ASE_MT);
3590 gen_helper_mtc0_tchalt(arg);
3591 rn = "TCHalt";
3592 break;
3593 case 5:
3594 check_insn(env, ctx, ASE_MT);
3595 gen_helper_mtc0_tccontext(arg);
3596 rn = "TCContext";
3597 break;
3598 case 6:
3599 check_insn(env, ctx, ASE_MT);
3600 gen_helper_mtc0_tcschedule(arg);
3601 rn = "TCSchedule";
3602 break;
3603 case 7:
3604 check_insn(env, ctx, ASE_MT);
3605 gen_helper_mtc0_tcschefback(arg);
3606 rn = "TCScheFBack";
3607 break;
3608 default:
3609 goto die;
3611 break;
3612 case 3:
3613 switch (sel) {
3614 case 0:
3615 gen_helper_mtc0_entrylo1(arg);
3616 rn = "EntryLo1";
3617 break;
3618 default:
3619 goto die;
3621 break;
3622 case 4:
3623 switch (sel) {
3624 case 0:
3625 gen_helper_mtc0_context(arg);
3626 rn = "Context";
3627 break;
3628 case 1:
3629 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3630 rn = "ContextConfig";
3631 // break;
3632 default:
3633 goto die;
3635 break;
3636 case 5:
3637 switch (sel) {
3638 case 0:
3639 gen_helper_mtc0_pagemask(arg);
3640 rn = "PageMask";
3641 break;
3642 case 1:
3643 check_insn(env, ctx, ISA_MIPS32R2);
3644 gen_helper_mtc0_pagegrain(arg);
3645 rn = "PageGrain";
3646 break;
3647 default:
3648 goto die;
3650 break;
3651 case 6:
3652 switch (sel) {
3653 case 0:
3654 gen_helper_mtc0_wired(arg);
3655 rn = "Wired";
3656 break;
3657 case 1:
3658 check_insn(env, ctx, ISA_MIPS32R2);
3659 gen_helper_mtc0_srsconf0(arg);
3660 rn = "SRSConf0";
3661 break;
3662 case 2:
3663 check_insn(env, ctx, ISA_MIPS32R2);
3664 gen_helper_mtc0_srsconf1(arg);
3665 rn = "SRSConf1";
3666 break;
3667 case 3:
3668 check_insn(env, ctx, ISA_MIPS32R2);
3669 gen_helper_mtc0_srsconf2(arg);
3670 rn = "SRSConf2";
3671 break;
3672 case 4:
3673 check_insn(env, ctx, ISA_MIPS32R2);
3674 gen_helper_mtc0_srsconf3(arg);
3675 rn = "SRSConf3";
3676 break;
3677 case 5:
3678 check_insn(env, ctx, ISA_MIPS32R2);
3679 gen_helper_mtc0_srsconf4(arg);
3680 rn = "SRSConf4";
3681 break;
3682 default:
3683 goto die;
3685 break;
3686 case 7:
3687 switch (sel) {
3688 case 0:
3689 check_insn(env, ctx, ISA_MIPS32R2);
3690 gen_helper_mtc0_hwrena(arg);
3691 rn = "HWREna";
3692 break;
3693 default:
3694 goto die;
3696 break;
3697 case 8:
3698 /* ignored */
3699 rn = "BadVAddr";
3700 break;
3701 case 9:
3702 switch (sel) {
3703 case 0:
3704 gen_helper_mtc0_count(arg);
3705 rn = "Count";
3706 break;
3707 /* 6,7 are implementation dependent */
3708 default:
3709 goto die;
3711 break;
3712 case 10:
3713 switch (sel) {
3714 case 0:
3715 gen_helper_mtc0_entryhi(arg);
3716 rn = "EntryHi";
3717 break;
3718 default:
3719 goto die;
3721 break;
3722 case 11:
3723 switch (sel) {
3724 case 0:
3725 gen_helper_mtc0_compare(arg);
3726 rn = "Compare";
3727 break;
3728 /* 6,7 are implementation dependent */
3729 default:
3730 goto die;
3732 break;
3733 case 12:
3734 switch (sel) {
3735 case 0:
3736 save_cpu_state(ctx, 1);
3737 gen_helper_mtc0_status(arg);
3738 /* BS_STOP isn't good enough here, hflags may have changed. */
3739 gen_save_pc(ctx->pc + 4);
3740 ctx->bstate = BS_EXCP;
3741 rn = "Status";
3742 break;
3743 case 1:
3744 check_insn(env, ctx, ISA_MIPS32R2);
3745 gen_helper_mtc0_intctl(arg);
3746 /* Stop translation as we may have switched the execution mode */
3747 ctx->bstate = BS_STOP;
3748 rn = "IntCtl";
3749 break;
3750 case 2:
3751 check_insn(env, ctx, ISA_MIPS32R2);
3752 gen_helper_mtc0_srsctl(arg);
3753 /* Stop translation as we may have switched the execution mode */
3754 ctx->bstate = BS_STOP;
3755 rn = "SRSCtl";
3756 break;
3757 case 3:
3758 check_insn(env, ctx, ISA_MIPS32R2);
3759 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
3760 /* Stop translation as we may have switched the execution mode */
3761 ctx->bstate = BS_STOP;
3762 rn = "SRSMap";
3763 break;
3764 default:
3765 goto die;
3767 break;
3768 case 13:
3769 switch (sel) {
3770 case 0:
3771 save_cpu_state(ctx, 1);
3772 gen_helper_mtc0_cause(arg);
3773 rn = "Cause";
3774 break;
3775 default:
3776 goto die;
3778 break;
3779 case 14:
3780 switch (sel) {
3781 case 0:
3782 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
3783 rn = "EPC";
3784 break;
3785 default:
3786 goto die;
3788 break;
3789 case 15:
3790 switch (sel) {
3791 case 0:
3792 /* ignored */
3793 rn = "PRid";
3794 break;
3795 case 1:
3796 check_insn(env, ctx, ISA_MIPS32R2);
3797 gen_helper_mtc0_ebase(arg);
3798 rn = "EBase";
3799 break;
3800 default:
3801 goto die;
3803 break;
3804 case 16:
3805 switch (sel) {
3806 case 0:
3807 gen_helper_mtc0_config0(arg);
3808 rn = "Config";
3809 /* Stop translation as we may have switched the execution mode */
3810 ctx->bstate = BS_STOP;
3811 break;
3812 case 1:
3813 /* ignored, read only */
3814 rn = "Config1";
3815 break;
3816 case 2:
3817 gen_helper_mtc0_config2(arg);
3818 rn = "Config2";
3819 /* Stop translation as we may have switched the execution mode */
3820 ctx->bstate = BS_STOP;
3821 break;
3822 case 3:
3823 /* ignored, read only */
3824 rn = "Config3";
3825 break;
3826 /* 4,5 are reserved */
3827 /* 6,7 are implementation dependent */
3828 case 6:
3829 /* ignored */
3830 rn = "Config6";
3831 break;
3832 case 7:
3833 /* ignored */
3834 rn = "Config7";
3835 break;
3836 default:
3837 rn = "Invalid config selector";
3838 goto die;
3840 break;
3841 case 17:
3842 switch (sel) {
3843 case 0:
3844 /* ignored */
3845 rn = "LLAddr";
3846 break;
3847 default:
3848 goto die;
3850 break;
3851 case 18:
3852 switch (sel) {
3853 case 0 ... 7:
3854 gen_helper_1i(mtc0_watchlo, arg, sel);
3855 rn = "WatchLo";
3856 break;
3857 default:
3858 goto die;
3860 break;
3861 case 19:
3862 switch (sel) {
3863 case 0 ... 7:
3864 gen_helper_1i(mtc0_watchhi, arg, sel);
3865 rn = "WatchHi";
3866 break;
3867 default:
3868 goto die;
3870 break;
3871 case 20:
3872 switch (sel) {
3873 case 0:
3874 #if defined(TARGET_MIPS64)
3875 check_insn(env, ctx, ISA_MIPS3);
3876 gen_helper_mtc0_xcontext(arg);
3877 rn = "XContext";
3878 break;
3879 #endif
3880 default:
3881 goto die;
3883 break;
3884 case 21:
3885 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3886 switch (sel) {
3887 case 0:
3888 gen_helper_mtc0_framemask(arg);
3889 rn = "Framemask";
3890 break;
3891 default:
3892 goto die;
3894 break;
3895 case 22:
3896 /* ignored */
3897 rn = "Diagnostic"; /* implementation dependent */
3898 break;
3899 case 23:
3900 switch (sel) {
3901 case 0:
3902 gen_helper_mtc0_debug(arg); /* EJTAG support */
3903 /* BS_STOP isn't good enough here, hflags may have changed. */
3904 gen_save_pc(ctx->pc + 4);
3905 ctx->bstate = BS_EXCP;
3906 rn = "Debug";
3907 break;
3908 case 1:
3909 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
3910 rn = "TraceControl";
3911 /* Stop translation as we may have switched the execution mode */
3912 ctx->bstate = BS_STOP;
3913 // break;
3914 case 2:
3915 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
3916 rn = "TraceControl2";
3917 /* Stop translation as we may have switched the execution mode */
3918 ctx->bstate = BS_STOP;
3919 // break;
3920 case 3:
3921 /* Stop translation as we may have switched the execution mode */
3922 ctx->bstate = BS_STOP;
3923 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
3924 rn = "UserTraceData";
3925 /* Stop translation as we may have switched the execution mode */
3926 ctx->bstate = BS_STOP;
3927 // break;
3928 case 4:
3929 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
3930 /* Stop translation as we may have switched the execution mode */
3931 ctx->bstate = BS_STOP;
3932 rn = "TraceBPC";
3933 // break;
3934 default:
3935 goto die;
3937 break;
3938 case 24:
3939 switch (sel) {
3940 case 0:
3941 /* EJTAG support */
3942 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
3943 rn = "DEPC";
3944 break;
3945 default:
3946 goto die;
3948 break;
3949 case 25:
3950 switch (sel) {
3951 case 0:
3952 gen_helper_mtc0_performance0(arg);
3953 rn = "Performance0";
3954 break;
3955 case 1:
3956 // gen_helper_mtc0_performance1(arg);
3957 rn = "Performance1";
3958 // break;
3959 case 2:
3960 // gen_helper_mtc0_performance2(arg);
3961 rn = "Performance2";
3962 // break;
3963 case 3:
3964 // gen_helper_mtc0_performance3(arg);
3965 rn = "Performance3";
3966 // break;
3967 case 4:
3968 // gen_helper_mtc0_performance4(arg);
3969 rn = "Performance4";
3970 // break;
3971 case 5:
3972 // gen_helper_mtc0_performance5(arg);
3973 rn = "Performance5";
3974 // break;
3975 case 6:
3976 // gen_helper_mtc0_performance6(arg);
3977 rn = "Performance6";
3978 // break;
3979 case 7:
3980 // gen_helper_mtc0_performance7(arg);
3981 rn = "Performance7";
3982 // break;
3983 default:
3984 goto die;
3986 break;
3987 case 26:
3988 /* ignored */
3989 rn = "ECC";
3990 break;
3991 case 27:
3992 switch (sel) {
3993 case 0 ... 3:
3994 /* ignored */
3995 rn = "CacheErr";
3996 break;
3997 default:
3998 goto die;
4000 break;
4001 case 28:
4002 switch (sel) {
4003 case 0:
4004 case 2:
4005 case 4:
4006 case 6:
4007 gen_helper_mtc0_taglo(arg);
4008 rn = "TagLo";
4009 break;
4010 case 1:
4011 case 3:
4012 case 5:
4013 case 7:
4014 gen_helper_mtc0_datalo(arg);
4015 rn = "DataLo";
4016 break;
4017 default:
4018 goto die;
4020 break;
4021 case 29:
4022 switch (sel) {
4023 case 0:
4024 case 2:
4025 case 4:
4026 case 6:
4027 gen_helper_mtc0_taghi(arg);
4028 rn = "TagHi";
4029 break;
4030 case 1:
4031 case 3:
4032 case 5:
4033 case 7:
4034 gen_helper_mtc0_datahi(arg);
4035 rn = "DataHi";
4036 break;
4037 default:
4038 rn = "invalid sel";
4039 goto die;
4041 break;
4042 case 30:
4043 switch (sel) {
4044 case 0:
4045 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
4046 rn = "ErrorEPC";
4047 break;
4048 default:
4049 goto die;
4051 break;
4052 case 31:
4053 switch (sel) {
4054 case 0:
4055 /* EJTAG support */
4056 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
4057 rn = "DESAVE";
4058 break;
4059 default:
4060 goto die;
4062 /* Stop translation as we may have switched the execution mode */
4063 ctx->bstate = BS_STOP;
4064 break;
4065 default:
4066 goto die;
4068 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4069 /* For simplicity assume that all writes can cause interrupts. */
4070 if (use_icount) {
4071 gen_io_end();
4072 ctx->bstate = BS_STOP;
4074 return;
4076 die:
4077 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4078 generate_exception(ctx, EXCP_RI);
4081 #if defined(TARGET_MIPS64)
4082 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4084 const char *rn = "invalid";
4086 if (sel != 0)
4087 check_insn(env, ctx, ISA_MIPS64);
4089 switch (reg) {
4090 case 0:
4091 switch (sel) {
4092 case 0:
4093 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
4094 rn = "Index";
4095 break;
4096 case 1:
4097 check_insn(env, ctx, ASE_MT);
4098 gen_helper_mfc0_mvpcontrol(arg);
4099 rn = "MVPControl";
4100 break;
4101 case 2:
4102 check_insn(env, ctx, ASE_MT);
4103 gen_helper_mfc0_mvpconf0(arg);
4104 rn = "MVPConf0";
4105 break;
4106 case 3:
4107 check_insn(env, ctx, ASE_MT);
4108 gen_helper_mfc0_mvpconf1(arg);
4109 rn = "MVPConf1";
4110 break;
4111 default:
4112 goto die;
4114 break;
4115 case 1:
4116 switch (sel) {
4117 case 0:
4118 gen_helper_mfc0_random(arg);
4119 rn = "Random";
4120 break;
4121 case 1:
4122 check_insn(env, ctx, ASE_MT);
4123 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
4124 rn = "VPEControl";
4125 break;
4126 case 2:
4127 check_insn(env, ctx, ASE_MT);
4128 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
4129 rn = "VPEConf0";
4130 break;
4131 case 3:
4132 check_insn(env, ctx, ASE_MT);
4133 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
4134 rn = "VPEConf1";
4135 break;
4136 case 4:
4137 check_insn(env, ctx, ASE_MT);
4138 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
4139 rn = "YQMask";
4140 break;
4141 case 5:
4142 check_insn(env, ctx, ASE_MT);
4143 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4144 rn = "VPESchedule";
4145 break;
4146 case 6:
4147 check_insn(env, ctx, ASE_MT);
4148 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4149 rn = "VPEScheFBack";
4150 break;
4151 case 7:
4152 check_insn(env, ctx, ASE_MT);
4153 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
4154 rn = "VPEOpt";
4155 break;
4156 default:
4157 goto die;
4159 break;
4160 case 2:
4161 switch (sel) {
4162 case 0:
4163 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4164 rn = "EntryLo0";
4165 break;
4166 case 1:
4167 check_insn(env, ctx, ASE_MT);
4168 gen_helper_mfc0_tcstatus(arg);
4169 rn = "TCStatus";
4170 break;
4171 case 2:
4172 check_insn(env, ctx, ASE_MT);
4173 gen_helper_mfc0_tcbind(arg);
4174 rn = "TCBind";
4175 break;
4176 case 3:
4177 check_insn(env, ctx, ASE_MT);
4178 gen_helper_dmfc0_tcrestart(arg);
4179 rn = "TCRestart";
4180 break;
4181 case 4:
4182 check_insn(env, ctx, ASE_MT);
4183 gen_helper_dmfc0_tchalt(arg);
4184 rn = "TCHalt";
4185 break;
4186 case 5:
4187 check_insn(env, ctx, ASE_MT);
4188 gen_helper_dmfc0_tccontext(arg);
4189 rn = "TCContext";
4190 break;
4191 case 6:
4192 check_insn(env, ctx, ASE_MT);
4193 gen_helper_dmfc0_tcschedule(arg);
4194 rn = "TCSchedule";
4195 break;
4196 case 7:
4197 check_insn(env, ctx, ASE_MT);
4198 gen_helper_dmfc0_tcschefback(arg);
4199 rn = "TCScheFBack";
4200 break;
4201 default:
4202 goto die;
4204 break;
4205 case 3:
4206 switch (sel) {
4207 case 0:
4208 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4209 rn = "EntryLo1";
4210 break;
4211 default:
4212 goto die;
4214 break;
4215 case 4:
4216 switch (sel) {
4217 case 0:
4218 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
4219 rn = "Context";
4220 break;
4221 case 1:
4222 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4223 rn = "ContextConfig";
4224 // break;
4225 default:
4226 goto die;
4228 break;
4229 case 5:
4230 switch (sel) {
4231 case 0:
4232 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
4233 rn = "PageMask";
4234 break;
4235 case 1:
4236 check_insn(env, ctx, ISA_MIPS32R2);
4237 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
4238 rn = "PageGrain";
4239 break;
4240 default:
4241 goto die;
4243 break;
4244 case 6:
4245 switch (sel) {
4246 case 0:
4247 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
4248 rn = "Wired";
4249 break;
4250 case 1:
4251 check_insn(env, ctx, ISA_MIPS32R2);
4252 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
4253 rn = "SRSConf0";
4254 break;
4255 case 2:
4256 check_insn(env, ctx, ISA_MIPS32R2);
4257 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
4258 rn = "SRSConf1";
4259 break;
4260 case 3:
4261 check_insn(env, ctx, ISA_MIPS32R2);
4262 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
4263 rn = "SRSConf2";
4264 break;
4265 case 4:
4266 check_insn(env, ctx, ISA_MIPS32R2);
4267 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
4268 rn = "SRSConf3";
4269 break;
4270 case 5:
4271 check_insn(env, ctx, ISA_MIPS32R2);
4272 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
4273 rn = "SRSConf4";
4274 break;
4275 default:
4276 goto die;
4278 break;
4279 case 7:
4280 switch (sel) {
4281 case 0:
4282 check_insn(env, ctx, ISA_MIPS32R2);
4283 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
4284 rn = "HWREna";
4285 break;
4286 default:
4287 goto die;
4289 break;
4290 case 8:
4291 switch (sel) {
4292 case 0:
4293 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4294 rn = "BadVAddr";
4295 break;
4296 default:
4297 goto die;
4299 break;
4300 case 9:
4301 switch (sel) {
4302 case 0:
4303 /* Mark as an IO operation because we read the time. */
4304 if (use_icount)
4305 gen_io_start();
4306 gen_helper_mfc0_count(arg);
4307 if (use_icount) {
4308 gen_io_end();
4309 ctx->bstate = BS_STOP;
4311 rn = "Count";
4312 break;
4313 /* 6,7 are implementation dependent */
4314 default:
4315 goto die;
4317 break;
4318 case 10:
4319 switch (sel) {
4320 case 0:
4321 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
4322 rn = "EntryHi";
4323 break;
4324 default:
4325 goto die;
4327 break;
4328 case 11:
4329 switch (sel) {
4330 case 0:
4331 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
4332 rn = "Compare";
4333 break;
4334 /* 6,7 are implementation dependent */
4335 default:
4336 goto die;
4338 break;
4339 case 12:
4340 switch (sel) {
4341 case 0:
4342 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
4343 rn = "Status";
4344 break;
4345 case 1:
4346 check_insn(env, ctx, ISA_MIPS32R2);
4347 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
4348 rn = "IntCtl";
4349 break;
4350 case 2:
4351 check_insn(env, ctx, ISA_MIPS32R2);
4352 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
4353 rn = "SRSCtl";
4354 break;
4355 case 3:
4356 check_insn(env, ctx, ISA_MIPS32R2);
4357 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
4358 rn = "SRSMap";
4359 break;
4360 default:
4361 goto die;
4363 break;
4364 case 13:
4365 switch (sel) {
4366 case 0:
4367 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
4368 rn = "Cause";
4369 break;
4370 default:
4371 goto die;
4373 break;
4374 case 14:
4375 switch (sel) {
4376 case 0:
4377 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4378 rn = "EPC";
4379 break;
4380 default:
4381 goto die;
4383 break;
4384 case 15:
4385 switch (sel) {
4386 case 0:
4387 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
4388 rn = "PRid";
4389 break;
4390 case 1:
4391 check_insn(env, ctx, ISA_MIPS32R2);
4392 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
4393 rn = "EBase";
4394 break;
4395 default:
4396 goto die;
4398 break;
4399 case 16:
4400 switch (sel) {
4401 case 0:
4402 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
4403 rn = "Config";
4404 break;
4405 case 1:
4406 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
4407 rn = "Config1";
4408 break;
4409 case 2:
4410 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
4411 rn = "Config2";
4412 break;
4413 case 3:
4414 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
4415 rn = "Config3";
4416 break;
4417 /* 6,7 are implementation dependent */
4418 case 6:
4419 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
4420 rn = "Config6";
4421 break;
4422 case 7:
4423 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
4424 rn = "Config7";
4425 break;
4426 default:
4427 goto die;
4429 break;
4430 case 17:
4431 switch (sel) {
4432 case 0:
4433 gen_helper_dmfc0_lladdr(arg);
4434 rn = "LLAddr";
4435 break;
4436 default:
4437 goto die;
4439 break;
4440 case 18:
4441 switch (sel) {
4442 case 0 ... 7:
4443 gen_helper_1i(dmfc0_watchlo, arg, sel);
4444 rn = "WatchLo";
4445 break;
4446 default:
4447 goto die;
4449 break;
4450 case 19:
4451 switch (sel) {
4452 case 0 ... 7:
4453 gen_helper_1i(mfc0_watchhi, arg, sel);
4454 rn = "WatchHi";
4455 break;
4456 default:
4457 goto die;
4459 break;
4460 case 20:
4461 switch (sel) {
4462 case 0:
4463 check_insn(env, ctx, ISA_MIPS3);
4464 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
4465 rn = "XContext";
4466 break;
4467 default:
4468 goto die;
4470 break;
4471 case 21:
4472 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4473 switch (sel) {
4474 case 0:
4475 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
4476 rn = "Framemask";
4477 break;
4478 default:
4479 goto die;
4481 break;
4482 case 22:
4483 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4484 rn = "'Diagnostic"; /* implementation dependent */
4485 break;
4486 case 23:
4487 switch (sel) {
4488 case 0:
4489 gen_helper_mfc0_debug(arg); /* EJTAG support */
4490 rn = "Debug";
4491 break;
4492 case 1:
4493 // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4494 rn = "TraceControl";
4495 // break;
4496 case 2:
4497 // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4498 rn = "TraceControl2";
4499 // break;
4500 case 3:
4501 // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4502 rn = "UserTraceData";
4503 // break;
4504 case 4:
4505 // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4506 rn = "TraceBPC";
4507 // break;
4508 default:
4509 goto die;
4511 break;
4512 case 24:
4513 switch (sel) {
4514 case 0:
4515 /* EJTAG support */
4516 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4517 rn = "DEPC";
4518 break;
4519 default:
4520 goto die;
4522 break;
4523 case 25:
4524 switch (sel) {
4525 case 0:
4526 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
4527 rn = "Performance0";
4528 break;
4529 case 1:
4530 // gen_helper_dmfc0_performance1(arg);
4531 rn = "Performance1";
4532 // break;
4533 case 2:
4534 // gen_helper_dmfc0_performance2(arg);
4535 rn = "Performance2";
4536 // break;
4537 case 3:
4538 // gen_helper_dmfc0_performance3(arg);
4539 rn = "Performance3";
4540 // break;
4541 case 4:
4542 // gen_helper_dmfc0_performance4(arg);
4543 rn = "Performance4";
4544 // break;
4545 case 5:
4546 // gen_helper_dmfc0_performance5(arg);
4547 rn = "Performance5";
4548 // break;
4549 case 6:
4550 // gen_helper_dmfc0_performance6(arg);
4551 rn = "Performance6";
4552 // break;
4553 case 7:
4554 // gen_helper_dmfc0_performance7(arg);
4555 rn = "Performance7";
4556 // break;
4557 default:
4558 goto die;
4560 break;
4561 case 26:
4562 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4563 rn = "ECC";
4564 break;
4565 case 27:
4566 switch (sel) {
4567 /* ignored */
4568 case 0 ... 3:
4569 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4570 rn = "CacheErr";
4571 break;
4572 default:
4573 goto die;
4575 break;
4576 case 28:
4577 switch (sel) {
4578 case 0:
4579 case 2:
4580 case 4:
4581 case 6:
4582 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
4583 rn = "TagLo";
4584 break;
4585 case 1:
4586 case 3:
4587 case 5:
4588 case 7:
4589 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
4590 rn = "DataLo";
4591 break;
4592 default:
4593 goto die;
4595 break;
4596 case 29:
4597 switch (sel) {
4598 case 0:
4599 case 2:
4600 case 4:
4601 case 6:
4602 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
4603 rn = "TagHi";
4604 break;
4605 case 1:
4606 case 3:
4607 case 5:
4608 case 7:
4609 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
4610 rn = "DataHi";
4611 break;
4612 default:
4613 goto die;
4615 break;
4616 case 30:
4617 switch (sel) {
4618 case 0:
4619 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4620 rn = "ErrorEPC";
4621 break;
4622 default:
4623 goto die;
4625 break;
4626 case 31:
4627 switch (sel) {
4628 case 0:
4629 /* EJTAG support */
4630 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
4631 rn = "DESAVE";
4632 break;
4633 default:
4634 goto die;
4636 break;
4637 default:
4638 goto die;
4640 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4641 return;
4643 die:
4644 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4645 generate_exception(ctx, EXCP_RI);
4648 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4650 const char *rn = "invalid";
4652 if (sel != 0)
4653 check_insn(env, ctx, ISA_MIPS64);
4655 if (use_icount)
4656 gen_io_start();
4658 switch (reg) {
4659 case 0:
4660 switch (sel) {
4661 case 0:
4662 gen_helper_mtc0_index(arg);
4663 rn = "Index";
4664 break;
4665 case 1:
4666 check_insn(env, ctx, ASE_MT);
4667 gen_helper_mtc0_mvpcontrol(arg);
4668 rn = "MVPControl";
4669 break;
4670 case 2:
4671 check_insn(env, ctx, ASE_MT);
4672 /* ignored */
4673 rn = "MVPConf0";
4674 break;
4675 case 3:
4676 check_insn(env, ctx, ASE_MT);
4677 /* ignored */
4678 rn = "MVPConf1";
4679 break;
4680 default:
4681 goto die;
4683 break;
4684 case 1:
4685 switch (sel) {
4686 case 0:
4687 /* ignored */
4688 rn = "Random";
4689 break;
4690 case 1:
4691 check_insn(env, ctx, ASE_MT);
4692 gen_helper_mtc0_vpecontrol(arg);
4693 rn = "VPEControl";
4694 break;
4695 case 2:
4696 check_insn(env, ctx, ASE_MT);
4697 gen_helper_mtc0_vpeconf0(arg);
4698 rn = "VPEConf0";
4699 break;
4700 case 3:
4701 check_insn(env, ctx, ASE_MT);
4702 gen_helper_mtc0_vpeconf1(arg);
4703 rn = "VPEConf1";
4704 break;
4705 case 4:
4706 check_insn(env, ctx, ASE_MT);
4707 gen_helper_mtc0_yqmask(arg);
4708 rn = "YQMask";
4709 break;
4710 case 5:
4711 check_insn(env, ctx, ASE_MT);
4712 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4713 rn = "VPESchedule";
4714 break;
4715 case 6:
4716 check_insn(env, ctx, ASE_MT);
4717 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4718 rn = "VPEScheFBack";
4719 break;
4720 case 7:
4721 check_insn(env, ctx, ASE_MT);
4722 gen_helper_mtc0_vpeopt(arg);
4723 rn = "VPEOpt";
4724 break;
4725 default:
4726 goto die;
4728 break;
4729 case 2:
4730 switch (sel) {
4731 case 0:
4732 gen_helper_mtc0_entrylo0(arg);
4733 rn = "EntryLo0";
4734 break;
4735 case 1:
4736 check_insn(env, ctx, ASE_MT);
4737 gen_helper_mtc0_tcstatus(arg);
4738 rn = "TCStatus";
4739 break;
4740 case 2:
4741 check_insn(env, ctx, ASE_MT);
4742 gen_helper_mtc0_tcbind(arg);
4743 rn = "TCBind";
4744 break;
4745 case 3:
4746 check_insn(env, ctx, ASE_MT);
4747 gen_helper_mtc0_tcrestart(arg);
4748 rn = "TCRestart";
4749 break;
4750 case 4:
4751 check_insn(env, ctx, ASE_MT);
4752 gen_helper_mtc0_tchalt(arg);
4753 rn = "TCHalt";
4754 break;
4755 case 5:
4756 check_insn(env, ctx, ASE_MT);
4757 gen_helper_mtc0_tccontext(arg);
4758 rn = "TCContext";
4759 break;
4760 case 6:
4761 check_insn(env, ctx, ASE_MT);
4762 gen_helper_mtc0_tcschedule(arg);
4763 rn = "TCSchedule";
4764 break;
4765 case 7:
4766 check_insn(env, ctx, ASE_MT);
4767 gen_helper_mtc0_tcschefback(arg);
4768 rn = "TCScheFBack";
4769 break;
4770 default:
4771 goto die;
4773 break;
4774 case 3:
4775 switch (sel) {
4776 case 0:
4777 gen_helper_mtc0_entrylo1(arg);
4778 rn = "EntryLo1";
4779 break;
4780 default:
4781 goto die;
4783 break;
4784 case 4:
4785 switch (sel) {
4786 case 0:
4787 gen_helper_mtc0_context(arg);
4788 rn = "Context";
4789 break;
4790 case 1:
4791 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
4792 rn = "ContextConfig";
4793 // break;
4794 default:
4795 goto die;
4797 break;
4798 case 5:
4799 switch (sel) {
4800 case 0:
4801 gen_helper_mtc0_pagemask(arg);
4802 rn = "PageMask";
4803 break;
4804 case 1:
4805 check_insn(env, ctx, ISA_MIPS32R2);
4806 gen_helper_mtc0_pagegrain(arg);
4807 rn = "PageGrain";
4808 break;
4809 default:
4810 goto die;
4812 break;
4813 case 6:
4814 switch (sel) {
4815 case 0:
4816 gen_helper_mtc0_wired(arg);
4817 rn = "Wired";
4818 break;
4819 case 1:
4820 check_insn(env, ctx, ISA_MIPS32R2);
4821 gen_helper_mtc0_srsconf0(arg);
4822 rn = "SRSConf0";
4823 break;
4824 case 2:
4825 check_insn(env, ctx, ISA_MIPS32R2);
4826 gen_helper_mtc0_srsconf1(arg);
4827 rn = "SRSConf1";
4828 break;
4829 case 3:
4830 check_insn(env, ctx, ISA_MIPS32R2);
4831 gen_helper_mtc0_srsconf2(arg);
4832 rn = "SRSConf2";
4833 break;
4834 case 4:
4835 check_insn(env, ctx, ISA_MIPS32R2);
4836 gen_helper_mtc0_srsconf3(arg);
4837 rn = "SRSConf3";
4838 break;
4839 case 5:
4840 check_insn(env, ctx, ISA_MIPS32R2);
4841 gen_helper_mtc0_srsconf4(arg);
4842 rn = "SRSConf4";
4843 break;
4844 default:
4845 goto die;
4847 break;
4848 case 7:
4849 switch (sel) {
4850 case 0:
4851 check_insn(env, ctx, ISA_MIPS32R2);
4852 gen_helper_mtc0_hwrena(arg);
4853 rn = "HWREna";
4854 break;
4855 default:
4856 goto die;
4858 break;
4859 case 8:
4860 /* ignored */
4861 rn = "BadVAddr";
4862 break;
4863 case 9:
4864 switch (sel) {
4865 case 0:
4866 gen_helper_mtc0_count(arg);
4867 rn = "Count";
4868 break;
4869 /* 6,7 are implementation dependent */
4870 default:
4871 goto die;
4873 /* Stop translation as we may have switched the execution mode */
4874 ctx->bstate = BS_STOP;
4875 break;
4876 case 10:
4877 switch (sel) {
4878 case 0:
4879 gen_helper_mtc0_entryhi(arg);
4880 rn = "EntryHi";
4881 break;
4882 default:
4883 goto die;
4885 break;
4886 case 11:
4887 switch (sel) {
4888 case 0:
4889 gen_helper_mtc0_compare(arg);
4890 rn = "Compare";
4891 break;
4892 /* 6,7 are implementation dependent */
4893 default:
4894 goto die;
4896 /* Stop translation as we may have switched the execution mode */
4897 ctx->bstate = BS_STOP;
4898 break;
4899 case 12:
4900 switch (sel) {
4901 case 0:
4902 save_cpu_state(ctx, 1);
4903 gen_helper_mtc0_status(arg);
4904 /* BS_STOP isn't good enough here, hflags may have changed. */
4905 gen_save_pc(ctx->pc + 4);
4906 ctx->bstate = BS_EXCP;
4907 rn = "Status";
4908 break;
4909 case 1:
4910 check_insn(env, ctx, ISA_MIPS32R2);
4911 gen_helper_mtc0_intctl(arg);
4912 /* Stop translation as we may have switched the execution mode */
4913 ctx->bstate = BS_STOP;
4914 rn = "IntCtl";
4915 break;
4916 case 2:
4917 check_insn(env, ctx, ISA_MIPS32R2);
4918 gen_helper_mtc0_srsctl(arg);
4919 /* Stop translation as we may have switched the execution mode */
4920 ctx->bstate = BS_STOP;
4921 rn = "SRSCtl";
4922 break;
4923 case 3:
4924 check_insn(env, ctx, ISA_MIPS32R2);
4925 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
4926 /* Stop translation as we may have switched the execution mode */
4927 ctx->bstate = BS_STOP;
4928 rn = "SRSMap";
4929 break;
4930 default:
4931 goto die;
4933 break;
4934 case 13:
4935 switch (sel) {
4936 case 0:
4937 save_cpu_state(ctx, 1);
4938 gen_helper_mtc0_cause(arg);
4939 rn = "Cause";
4940 break;
4941 default:
4942 goto die;
4944 break;
4945 case 14:
4946 switch (sel) {
4947 case 0:
4948 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4949 rn = "EPC";
4950 break;
4951 default:
4952 goto die;
4954 break;
4955 case 15:
4956 switch (sel) {
4957 case 0:
4958 /* ignored */
4959 rn = "PRid";
4960 break;
4961 case 1:
4962 check_insn(env, ctx, ISA_MIPS32R2);
4963 gen_helper_mtc0_ebase(arg);
4964 rn = "EBase";
4965 break;
4966 default:
4967 goto die;
4969 break;
4970 case 16:
4971 switch (sel) {
4972 case 0:
4973 gen_helper_mtc0_config0(arg);
4974 rn = "Config";
4975 /* Stop translation as we may have switched the execution mode */
4976 ctx->bstate = BS_STOP;
4977 break;
4978 case 1:
4979 /* ignored, read only */
4980 rn = "Config1";
4981 break;
4982 case 2:
4983 gen_helper_mtc0_config2(arg);
4984 rn = "Config2";
4985 /* Stop translation as we may have switched the execution mode */
4986 ctx->bstate = BS_STOP;
4987 break;
4988 case 3:
4989 /* ignored */
4990 rn = "Config3";
4991 break;
4992 /* 6,7 are implementation dependent */
4993 default:
4994 rn = "Invalid config selector";
4995 goto die;
4997 break;
4998 case 17:
4999 switch (sel) {
5000 case 0:
5001 /* ignored */
5002 rn = "LLAddr";
5003 break;
5004 default:
5005 goto die;
5007 break;
5008 case 18:
5009 switch (sel) {
5010 case 0 ... 7:
5011 gen_helper_1i(mtc0_watchlo, arg, sel);
5012 rn = "WatchLo";
5013 break;
5014 default:
5015 goto die;
5017 break;
5018 case 19:
5019 switch (sel) {
5020 case 0 ... 7:
5021 gen_helper_1i(mtc0_watchhi, arg, sel);
5022 rn = "WatchHi";
5023 break;
5024 default:
5025 goto die;
5027 break;
5028 case 20:
5029 switch (sel) {
5030 case 0:
5031 check_insn(env, ctx, ISA_MIPS3);
5032 gen_helper_mtc0_xcontext(arg);
5033 rn = "XContext";
5034 break;
5035 default:
5036 goto die;
5038 break;
5039 case 21:
5040 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5041 switch (sel) {
5042 case 0:
5043 gen_helper_mtc0_framemask(arg);
5044 rn = "Framemask";
5045 break;
5046 default:
5047 goto die;
5049 break;
5050 case 22:
5051 /* ignored */
5052 rn = "Diagnostic"; /* implementation dependent */
5053 break;
5054 case 23:
5055 switch (sel) {
5056 case 0:
5057 gen_helper_mtc0_debug(arg); /* EJTAG support */
5058 /* BS_STOP isn't good enough here, hflags may have changed. */
5059 gen_save_pc(ctx->pc + 4);
5060 ctx->bstate = BS_EXCP;
5061 rn = "Debug";
5062 break;
5063 case 1:
5064 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
5065 /* Stop translation as we may have switched the execution mode */
5066 ctx->bstate = BS_STOP;
5067 rn = "TraceControl";
5068 // break;
5069 case 2:
5070 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
5071 /* Stop translation as we may have switched the execution mode */
5072 ctx->bstate = BS_STOP;
5073 rn = "TraceControl2";
5074 // break;
5075 case 3:
5076 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
5077 /* Stop translation as we may have switched the execution mode */
5078 ctx->bstate = BS_STOP;
5079 rn = "UserTraceData";
5080 // break;
5081 case 4:
5082 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
5083 /* Stop translation as we may have switched the execution mode */
5084 ctx->bstate = BS_STOP;
5085 rn = "TraceBPC";
5086 // break;
5087 default:
5088 goto die;
5090 break;
5091 case 24:
5092 switch (sel) {
5093 case 0:
5094 /* EJTAG support */
5095 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
5096 rn = "DEPC";
5097 break;
5098 default:
5099 goto die;
5101 break;
5102 case 25:
5103 switch (sel) {
5104 case 0:
5105 gen_helper_mtc0_performance0(arg);
5106 rn = "Performance0";
5107 break;
5108 case 1:
5109 // gen_helper_mtc0_performance1(arg);
5110 rn = "Performance1";
5111 // break;
5112 case 2:
5113 // gen_helper_mtc0_performance2(arg);
5114 rn = "Performance2";
5115 // break;
5116 case 3:
5117 // gen_helper_mtc0_performance3(arg);
5118 rn = "Performance3";
5119 // break;
5120 case 4:
5121 // gen_helper_mtc0_performance4(arg);
5122 rn = "Performance4";
5123 // break;
5124 case 5:
5125 // gen_helper_mtc0_performance5(arg);
5126 rn = "Performance5";
5127 // break;
5128 case 6:
5129 // gen_helper_mtc0_performance6(arg);
5130 rn = "Performance6";
5131 // break;
5132 case 7:
5133 // gen_helper_mtc0_performance7(arg);
5134 rn = "Performance7";
5135 // break;
5136 default:
5137 goto die;
5139 break;
5140 case 26:
5141 /* ignored */
5142 rn = "ECC";
5143 break;
5144 case 27:
5145 switch (sel) {
5146 case 0 ... 3:
5147 /* ignored */
5148 rn = "CacheErr";
5149 break;
5150 default:
5151 goto die;
5153 break;
5154 case 28:
5155 switch (sel) {
5156 case 0:
5157 case 2:
5158 case 4:
5159 case 6:
5160 gen_helper_mtc0_taglo(arg);
5161 rn = "TagLo";
5162 break;
5163 case 1:
5164 case 3:
5165 case 5:
5166 case 7:
5167 gen_helper_mtc0_datalo(arg);
5168 rn = "DataLo";
5169 break;
5170 default:
5171 goto die;
5173 break;
5174 case 29:
5175 switch (sel) {
5176 case 0:
5177 case 2:
5178 case 4:
5179 case 6:
5180 gen_helper_mtc0_taghi(arg);
5181 rn = "TagHi";
5182 break;
5183 case 1:
5184 case 3:
5185 case 5:
5186 case 7:
5187 gen_helper_mtc0_datahi(arg);
5188 rn = "DataHi";
5189 break;
5190 default:
5191 rn = "invalid sel";
5192 goto die;
5194 break;
5195 case 30:
5196 switch (sel) {
5197 case 0:
5198 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5199 rn = "ErrorEPC";
5200 break;
5201 default:
5202 goto die;
5204 break;
5205 case 31:
5206 switch (sel) {
5207 case 0:
5208 /* EJTAG support */
5209 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
5210 rn = "DESAVE";
5211 break;
5212 default:
5213 goto die;
5215 /* Stop translation as we may have switched the execution mode */
5216 ctx->bstate = BS_STOP;
5217 break;
5218 default:
5219 goto die;
5221 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5222 /* For simplicity assume that all writes can cause interrupts. */
5223 if (use_icount) {
5224 gen_io_end();
5225 ctx->bstate = BS_STOP;
5227 return;
5229 die:
5230 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5231 generate_exception(ctx, EXCP_RI);
5233 #endif /* TARGET_MIPS64 */
5235 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5236 int u, int sel, int h)
5238 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5239 TCGv t0 = tcg_temp_local_new();
5241 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5242 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5243 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5244 tcg_gen_movi_tl(t0, -1);
5245 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5246 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5247 tcg_gen_movi_tl(t0, -1);
5248 else if (u == 0) {
5249 switch (rt) {
5250 case 2:
5251 switch (sel) {
5252 case 1:
5253 gen_helper_mftc0_tcstatus(t0);
5254 break;
5255 case 2:
5256 gen_helper_mftc0_tcbind(t0);
5257 break;
5258 case 3:
5259 gen_helper_mftc0_tcrestart(t0);
5260 break;
5261 case 4:
5262 gen_helper_mftc0_tchalt(t0);
5263 break;
5264 case 5:
5265 gen_helper_mftc0_tccontext(t0);
5266 break;
5267 case 6:
5268 gen_helper_mftc0_tcschedule(t0);
5269 break;
5270 case 7:
5271 gen_helper_mftc0_tcschefback(t0);
5272 break;
5273 default:
5274 gen_mfc0(env, ctx, t0, rt, sel);
5275 break;
5277 break;
5278 case 10:
5279 switch (sel) {
5280 case 0:
5281 gen_helper_mftc0_entryhi(t0);
5282 break;
5283 default:
5284 gen_mfc0(env, ctx, t0, rt, sel);
5285 break;
5287 case 12:
5288 switch (sel) {
5289 case 0:
5290 gen_helper_mftc0_status(t0);
5291 break;
5292 default:
5293 gen_mfc0(env, ctx, t0, rt, sel);
5294 break;
5296 case 23:
5297 switch (sel) {
5298 case 0:
5299 gen_helper_mftc0_debug(t0);
5300 break;
5301 default:
5302 gen_mfc0(env, ctx, t0, rt, sel);
5303 break;
5305 break;
5306 default:
5307 gen_mfc0(env, ctx, t0, rt, sel);
5309 } else switch (sel) {
5310 /* GPR registers. */
5311 case 0:
5312 gen_helper_1i(mftgpr, t0, rt);
5313 break;
5314 /* Auxiliary CPU registers */
5315 case 1:
5316 switch (rt) {
5317 case 0:
5318 gen_helper_1i(mftlo, t0, 0);
5319 break;
5320 case 1:
5321 gen_helper_1i(mfthi, t0, 0);
5322 break;
5323 case 2:
5324 gen_helper_1i(mftacx, t0, 0);
5325 break;
5326 case 4:
5327 gen_helper_1i(mftlo, t0, 1);
5328 break;
5329 case 5:
5330 gen_helper_1i(mfthi, t0, 1);
5331 break;
5332 case 6:
5333 gen_helper_1i(mftacx, t0, 1);
5334 break;
5335 case 8:
5336 gen_helper_1i(mftlo, t0, 2);
5337 break;
5338 case 9:
5339 gen_helper_1i(mfthi, t0, 2);
5340 break;
5341 case 10:
5342 gen_helper_1i(mftacx, t0, 2);
5343 break;
5344 case 12:
5345 gen_helper_1i(mftlo, t0, 3);
5346 break;
5347 case 13:
5348 gen_helper_1i(mfthi, t0, 3);
5349 break;
5350 case 14:
5351 gen_helper_1i(mftacx, t0, 3);
5352 break;
5353 case 16:
5354 gen_helper_mftdsp(t0);
5355 break;
5356 default:
5357 goto die;
5359 break;
5360 /* Floating point (COP1). */
5361 case 2:
5362 /* XXX: For now we support only a single FPU context. */
5363 if (h == 0) {
5364 TCGv_i32 fp0 = tcg_temp_new_i32();
5366 gen_load_fpr32(fp0, rt);
5367 tcg_gen_ext_i32_tl(t0, fp0);
5368 tcg_temp_free_i32(fp0);
5369 } else {
5370 TCGv_i32 fp0 = tcg_temp_new_i32();
5372 gen_load_fpr32h(fp0, rt);
5373 tcg_gen_ext_i32_tl(t0, fp0);
5374 tcg_temp_free_i32(fp0);
5376 break;
5377 case 3:
5378 /* XXX: For now we support only a single FPU context. */
5379 gen_helper_1i(cfc1, t0, rt);
5380 break;
5381 /* COP2: Not implemented. */
5382 case 4:
5383 case 5:
5384 /* fall through */
5385 default:
5386 goto die;
5388 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5389 gen_store_gpr(t0, rd);
5390 tcg_temp_free(t0);
5391 return;
5393 die:
5394 tcg_temp_free(t0);
5395 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5396 generate_exception(ctx, EXCP_RI);
5399 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5400 int u, int sel, int h)
5402 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5403 TCGv t0 = tcg_temp_local_new();
5405 gen_load_gpr(t0, rt);
5406 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5407 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5408 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5409 /* NOP */ ;
5410 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5411 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5412 /* NOP */ ;
5413 else if (u == 0) {
5414 switch (rd) {
5415 case 2:
5416 switch (sel) {
5417 case 1:
5418 gen_helper_mttc0_tcstatus(t0);
5419 break;
5420 case 2:
5421 gen_helper_mttc0_tcbind(t0);
5422 break;
5423 case 3:
5424 gen_helper_mttc0_tcrestart(t0);
5425 break;
5426 case 4:
5427 gen_helper_mttc0_tchalt(t0);
5428 break;
5429 case 5:
5430 gen_helper_mttc0_tccontext(t0);
5431 break;
5432 case 6:
5433 gen_helper_mttc0_tcschedule(t0);
5434 break;
5435 case 7:
5436 gen_helper_mttc0_tcschefback(t0);
5437 break;
5438 default:
5439 gen_mtc0(env, ctx, t0, rd, sel);
5440 break;
5442 break;
5443 case 10:
5444 switch (sel) {
5445 case 0:
5446 gen_helper_mttc0_entryhi(t0);
5447 break;
5448 default:
5449 gen_mtc0(env, ctx, t0, rd, sel);
5450 break;
5452 case 12:
5453 switch (sel) {
5454 case 0:
5455 gen_helper_mttc0_status(t0);
5456 break;
5457 default:
5458 gen_mtc0(env, ctx, t0, rd, sel);
5459 break;
5461 case 23:
5462 switch (sel) {
5463 case 0:
5464 gen_helper_mttc0_debug(t0);
5465 break;
5466 default:
5467 gen_mtc0(env, ctx, t0, rd, sel);
5468 break;
5470 break;
5471 default:
5472 gen_mtc0(env, ctx, t0, rd, sel);
5474 } else switch (sel) {
5475 /* GPR registers. */
5476 case 0:
5477 gen_helper_1i(mttgpr, t0, rd);
5478 break;
5479 /* Auxiliary CPU registers */
5480 case 1:
5481 switch (rd) {
5482 case 0:
5483 gen_helper_1i(mttlo, t0, 0);
5484 break;
5485 case 1:
5486 gen_helper_1i(mtthi, t0, 0);
5487 break;
5488 case 2:
5489 gen_helper_1i(mttacx, t0, 0);
5490 break;
5491 case 4:
5492 gen_helper_1i(mttlo, t0, 1);
5493 break;
5494 case 5:
5495 gen_helper_1i(mtthi, t0, 1);
5496 break;
5497 case 6:
5498 gen_helper_1i(mttacx, t0, 1);
5499 break;
5500 case 8:
5501 gen_helper_1i(mttlo, t0, 2);
5502 break;
5503 case 9:
5504 gen_helper_1i(mtthi, t0, 2);
5505 break;
5506 case 10:
5507 gen_helper_1i(mttacx, t0, 2);
5508 break;
5509 case 12:
5510 gen_helper_1i(mttlo, t0, 3);
5511 break;
5512 case 13:
5513 gen_helper_1i(mtthi, t0, 3);
5514 break;
5515 case 14:
5516 gen_helper_1i(mttacx, t0, 3);
5517 break;
5518 case 16:
5519 gen_helper_mttdsp(t0);
5520 break;
5521 default:
5522 goto die;
5524 break;
5525 /* Floating point (COP1). */
5526 case 2:
5527 /* XXX: For now we support only a single FPU context. */
5528 if (h == 0) {
5529 TCGv_i32 fp0 = tcg_temp_new_i32();
5531 tcg_gen_trunc_tl_i32(fp0, t0);
5532 gen_store_fpr32(fp0, rd);
5533 tcg_temp_free_i32(fp0);
5534 } else {
5535 TCGv_i32 fp0 = tcg_temp_new_i32();
5537 tcg_gen_trunc_tl_i32(fp0, t0);
5538 gen_store_fpr32h(fp0, rd);
5539 tcg_temp_free_i32(fp0);
5541 break;
5542 case 3:
5543 /* XXX: For now we support only a single FPU context. */
5544 gen_helper_1i(ctc1, t0, rd);
5545 break;
5546 /* COP2: Not implemented. */
5547 case 4:
5548 case 5:
5549 /* fall through */
5550 default:
5551 goto die;
5553 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5554 tcg_temp_free(t0);
5555 return;
5557 die:
5558 tcg_temp_free(t0);
5559 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5560 generate_exception(ctx, EXCP_RI);
5563 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5565 const char *opn = "ldst";
5567 switch (opc) {
5568 case OPC_MFC0:
5569 if (rt == 0) {
5570 /* Treat as NOP. */
5571 return;
5573 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5574 opn = "mfc0";
5575 break;
5576 case OPC_MTC0:
5578 TCGv t0 = tcg_temp_new();
5580 gen_load_gpr(t0, rt);
5581 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5582 tcg_temp_free(t0);
5584 opn = "mtc0";
5585 break;
5586 #if defined(TARGET_MIPS64)
5587 case OPC_DMFC0:
5588 check_insn(env, ctx, ISA_MIPS3);
5589 if (rt == 0) {
5590 /* Treat as NOP. */
5591 return;
5593 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5594 opn = "dmfc0";
5595 break;
5596 case OPC_DMTC0:
5597 check_insn(env, ctx, ISA_MIPS3);
5599 TCGv t0 = tcg_temp_new();
5601 gen_load_gpr(t0, rt);
5602 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5603 tcg_temp_free(t0);
5605 opn = "dmtc0";
5606 break;
5607 #endif
5608 case OPC_MFTR:
5609 check_insn(env, ctx, ASE_MT);
5610 if (rd == 0) {
5611 /* Treat as NOP. */
5612 return;
5614 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5615 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5616 opn = "mftr";
5617 break;
5618 case OPC_MTTR:
5619 check_insn(env, ctx, ASE_MT);
5620 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5621 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5622 opn = "mttr";
5623 break;
5624 case OPC_TLBWI:
5625 opn = "tlbwi";
5626 if (!env->tlb->helper_tlbwi)
5627 goto die;
5628 gen_helper_tlbwi();
5629 break;
5630 case OPC_TLBWR:
5631 opn = "tlbwr";
5632 if (!env->tlb->helper_tlbwr)
5633 goto die;
5634 gen_helper_tlbwr();
5635 break;
5636 case OPC_TLBP:
5637 opn = "tlbp";
5638 if (!env->tlb->helper_tlbp)
5639 goto die;
5640 gen_helper_tlbp();
5641 break;
5642 case OPC_TLBR:
5643 opn = "tlbr";
5644 if (!env->tlb->helper_tlbr)
5645 goto die;
5646 gen_helper_tlbr();
5647 break;
5648 case OPC_ERET:
5649 opn = "eret";
5650 check_insn(env, ctx, ISA_MIPS2);
5651 gen_helper_eret();
5652 ctx->bstate = BS_EXCP;
5653 break;
5654 case OPC_DERET:
5655 opn = "deret";
5656 check_insn(env, ctx, ISA_MIPS32);
5657 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5658 MIPS_INVAL(opn);
5659 generate_exception(ctx, EXCP_RI);
5660 } else {
5661 gen_helper_deret();
5662 ctx->bstate = BS_EXCP;
5664 break;
5665 case OPC_WAIT:
5666 opn = "wait";
5667 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5668 /* If we get an exception, we want to restart at next instruction */
5669 ctx->pc += 4;
5670 save_cpu_state(ctx, 1);
5671 ctx->pc -= 4;
5672 gen_helper_wait();
5673 ctx->bstate = BS_EXCP;
5674 break;
5675 default:
5676 die:
5677 MIPS_INVAL(opn);
5678 generate_exception(ctx, EXCP_RI);
5679 return;
5681 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5683 #endif /* !CONFIG_USER_ONLY */
5685 /* CP1 Branches (before delay slot) */
5686 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5687 int32_t cc, int32_t offset)
5689 target_ulong btarget;
5690 const char *opn = "cp1 cond branch";
5691 TCGv_i32 t0 = tcg_temp_new_i32();
5693 if (cc != 0)
5694 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5696 btarget = ctx->pc + 4 + offset;
5698 switch (op) {
5699 case OPC_BC1F:
5700 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5701 tcg_gen_not_i32(t0, t0);
5702 tcg_gen_andi_i32(t0, t0, 1);
5703 tcg_gen_extu_i32_tl(bcond, t0);
5704 opn = "bc1f";
5705 goto not_likely;
5706 case OPC_BC1FL:
5707 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5708 tcg_gen_not_i32(t0, t0);
5709 tcg_gen_andi_i32(t0, t0, 1);
5710 tcg_gen_extu_i32_tl(bcond, t0);
5711 opn = "bc1fl";
5712 goto likely;
5713 case OPC_BC1T:
5714 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5715 tcg_gen_andi_i32(t0, t0, 1);
5716 tcg_gen_extu_i32_tl(bcond, t0);
5717 opn = "bc1t";
5718 goto not_likely;
5719 case OPC_BC1TL:
5720 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5721 tcg_gen_andi_i32(t0, t0, 1);
5722 tcg_gen_extu_i32_tl(bcond, t0);
5723 opn = "bc1tl";
5724 likely:
5725 ctx->hflags |= MIPS_HFLAG_BL;
5726 break;
5727 case OPC_BC1FANY2:
5729 TCGv_i32 t1 = tcg_temp_new_i32();
5730 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5731 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5732 tcg_gen_or_i32(t0, t0, t1);
5733 tcg_temp_free_i32(t1);
5734 tcg_gen_not_i32(t0, t0);
5735 tcg_gen_andi_i32(t0, t0, 1);
5736 tcg_gen_extu_i32_tl(bcond, t0);
5738 opn = "bc1any2f";
5739 goto not_likely;
5740 case OPC_BC1TANY2:
5742 TCGv_i32 t1 = tcg_temp_new_i32();
5743 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5744 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5745 tcg_gen_or_i32(t0, t0, t1);
5746 tcg_temp_free_i32(t1);
5747 tcg_gen_andi_i32(t0, t0, 1);
5748 tcg_gen_extu_i32_tl(bcond, t0);
5750 opn = "bc1any2t";
5751 goto not_likely;
5752 case OPC_BC1FANY4:
5754 TCGv_i32 t1 = tcg_temp_new_i32();
5755 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5756 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5757 tcg_gen_or_i32(t0, t0, t1);
5758 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5759 tcg_gen_or_i32(t0, t0, t1);
5760 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5761 tcg_gen_or_i32(t0, t0, t1);
5762 tcg_temp_free_i32(t1);
5763 tcg_gen_not_i32(t0, t0);
5764 tcg_gen_andi_i32(t0, t0, 1);
5765 tcg_gen_extu_i32_tl(bcond, t0);
5767 opn = "bc1any4f";
5768 goto not_likely;
5769 case OPC_BC1TANY4:
5771 TCGv_i32 t1 = tcg_temp_new_i32();
5772 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5773 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5774 tcg_gen_or_i32(t0, t0, t1);
5775 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5776 tcg_gen_or_i32(t0, t0, t1);
5777 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5778 tcg_gen_or_i32(t0, t0, t1);
5779 tcg_temp_free_i32(t1);
5780 tcg_gen_andi_i32(t0, t0, 1);
5781 tcg_gen_extu_i32_tl(bcond, t0);
5783 opn = "bc1any4t";
5784 not_likely:
5785 ctx->hflags |= MIPS_HFLAG_BC;
5786 break;
5787 default:
5788 MIPS_INVAL(opn);
5789 generate_exception (ctx, EXCP_RI);
5790 goto out;
5792 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5793 ctx->hflags, btarget);
5794 ctx->btarget = btarget;
5796 out:
5797 tcg_temp_free_i32(t0);
5800 /* Coprocessor 1 (FPU) */
5802 #define FOP(func, fmt) (((fmt) << 21) | (func))
5804 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5806 const char *opn = "cp1 move";
5807 TCGv t0 = tcg_temp_new();
5809 switch (opc) {
5810 case OPC_MFC1:
5812 TCGv_i32 fp0 = tcg_temp_new_i32();
5814 gen_load_fpr32(fp0, fs);
5815 tcg_gen_ext_i32_tl(t0, fp0);
5816 tcg_temp_free_i32(fp0);
5818 gen_store_gpr(t0, rt);
5819 opn = "mfc1";
5820 break;
5821 case OPC_MTC1:
5822 gen_load_gpr(t0, rt);
5824 TCGv_i32 fp0 = tcg_temp_new_i32();
5826 tcg_gen_trunc_tl_i32(fp0, t0);
5827 gen_store_fpr32(fp0, fs);
5828 tcg_temp_free_i32(fp0);
5830 opn = "mtc1";
5831 break;
5832 case OPC_CFC1:
5833 gen_helper_1i(cfc1, t0, fs);
5834 gen_store_gpr(t0, rt);
5835 opn = "cfc1";
5836 break;
5837 case OPC_CTC1:
5838 gen_load_gpr(t0, rt);
5839 gen_helper_1i(ctc1, t0, fs);
5840 opn = "ctc1";
5841 break;
5842 #if defined(TARGET_MIPS64)
5843 case OPC_DMFC1:
5844 gen_load_fpr64(ctx, t0, fs);
5845 gen_store_gpr(t0, rt);
5846 opn = "dmfc1";
5847 break;
5848 case OPC_DMTC1:
5849 gen_load_gpr(t0, rt);
5850 gen_store_fpr64(ctx, t0, fs);
5851 opn = "dmtc1";
5852 break;
5853 #endif
5854 case OPC_MFHC1:
5856 TCGv_i32 fp0 = tcg_temp_new_i32();
5858 gen_load_fpr32h(fp0, fs);
5859 tcg_gen_ext_i32_tl(t0, fp0);
5860 tcg_temp_free_i32(fp0);
5862 gen_store_gpr(t0, rt);
5863 opn = "mfhc1";
5864 break;
5865 case OPC_MTHC1:
5866 gen_load_gpr(t0, rt);
5868 TCGv_i32 fp0 = tcg_temp_new_i32();
5870 tcg_gen_trunc_tl_i32(fp0, t0);
5871 gen_store_fpr32h(fp0, fs);
5872 tcg_temp_free_i32(fp0);
5874 opn = "mthc1";
5875 break;
5876 default:
5877 MIPS_INVAL(opn);
5878 generate_exception (ctx, EXCP_RI);
5879 goto out;
5881 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5883 out:
5884 tcg_temp_free(t0);
5887 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5889 int l1;
5890 TCGCond cond;
5891 TCGv_i32 t0;
5893 if (rd == 0) {
5894 /* Treat as NOP. */
5895 return;
5898 if (tf)
5899 cond = TCG_COND_EQ;
5900 else
5901 cond = TCG_COND_NE;
5903 l1 = gen_new_label();
5904 t0 = tcg_temp_new_i32();
5905 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5906 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5907 tcg_temp_free_i32(t0);
5908 if (rs == 0) {
5909 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5910 } else {
5911 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5913 gen_set_label(l1);
5916 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5918 int cond;
5919 TCGv_i32 t0 = tcg_temp_new_i32();
5920 int l1 = gen_new_label();
5922 if (tf)
5923 cond = TCG_COND_EQ;
5924 else
5925 cond = TCG_COND_NE;
5927 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5928 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5929 gen_load_fpr32(t0, fs);
5930 gen_store_fpr32(t0, fd);
5931 gen_set_label(l1);
5932 tcg_temp_free_i32(t0);
5935 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5937 int cond;
5938 TCGv_i32 t0 = tcg_temp_new_i32();
5939 TCGv_i64 fp0;
5940 int l1 = gen_new_label();
5942 if (tf)
5943 cond = TCG_COND_EQ;
5944 else
5945 cond = TCG_COND_NE;
5947 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5948 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5949 tcg_temp_free_i32(t0);
5950 fp0 = tcg_temp_new_i64();
5951 gen_load_fpr64(ctx, fp0, fs);
5952 gen_store_fpr64(ctx, fp0, fd);
5953 tcg_temp_free_i64(fp0);
5954 gen_set_label(l1);
5957 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5959 int cond;
5960 TCGv_i32 t0 = tcg_temp_new_i32();
5961 int l1 = gen_new_label();
5962 int l2 = gen_new_label();
5964 if (tf)
5965 cond = TCG_COND_EQ;
5966 else
5967 cond = TCG_COND_NE;
5969 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5970 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5971 gen_load_fpr32(t0, fs);
5972 gen_store_fpr32(t0, fd);
5973 gen_set_label(l1);
5975 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
5976 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5977 gen_load_fpr32h(t0, fs);
5978 gen_store_fpr32h(t0, fd);
5979 tcg_temp_free_i32(t0);
5980 gen_set_label(l2);
5984 static void gen_farith (DisasContext *ctx, uint32_t op1,
5985 int ft, int fs, int fd, int cc)
5987 const char *opn = "farith";
5988 const char *condnames[] = {
5989 "c.f",
5990 "c.un",
5991 "c.eq",
5992 "c.ueq",
5993 "c.olt",
5994 "c.ult",
5995 "c.ole",
5996 "c.ule",
5997 "c.sf",
5998 "c.ngle",
5999 "c.seq",
6000 "c.ngl",
6001 "c.lt",
6002 "c.nge",
6003 "c.le",
6004 "c.ngt",
6006 const char *condnames_abs[] = {
6007 "cabs.f",
6008 "cabs.un",
6009 "cabs.eq",
6010 "cabs.ueq",
6011 "cabs.olt",
6012 "cabs.ult",
6013 "cabs.ole",
6014 "cabs.ule",
6015 "cabs.sf",
6016 "cabs.ngle",
6017 "cabs.seq",
6018 "cabs.ngl",
6019 "cabs.lt",
6020 "cabs.nge",
6021 "cabs.le",
6022 "cabs.ngt",
6024 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6025 uint32_t func = ctx->opcode & 0x3f;
6027 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
6028 case FOP(0, 16):
6030 TCGv_i32 fp0 = tcg_temp_new_i32();
6031 TCGv_i32 fp1 = tcg_temp_new_i32();
6033 gen_load_fpr32(fp0, fs);
6034 gen_load_fpr32(fp1, ft);
6035 gen_helper_float_add_s(fp0, fp0, fp1);
6036 tcg_temp_free_i32(fp1);
6037 gen_store_fpr32(fp0, fd);
6038 tcg_temp_free_i32(fp0);
6040 opn = "add.s";
6041 optype = BINOP;
6042 break;
6043 case FOP(1, 16):
6045 TCGv_i32 fp0 = tcg_temp_new_i32();
6046 TCGv_i32 fp1 = tcg_temp_new_i32();
6048 gen_load_fpr32(fp0, fs);
6049 gen_load_fpr32(fp1, ft);
6050 gen_helper_float_sub_s(fp0, fp0, fp1);
6051 tcg_temp_free_i32(fp1);
6052 gen_store_fpr32(fp0, fd);
6053 tcg_temp_free_i32(fp0);
6055 opn = "sub.s";
6056 optype = BINOP;
6057 break;
6058 case FOP(2, 16):
6060 TCGv_i32 fp0 = tcg_temp_new_i32();
6061 TCGv_i32 fp1 = tcg_temp_new_i32();
6063 gen_load_fpr32(fp0, fs);
6064 gen_load_fpr32(fp1, ft);
6065 gen_helper_float_mul_s(fp0, fp0, fp1);
6066 tcg_temp_free_i32(fp1);
6067 gen_store_fpr32(fp0, fd);
6068 tcg_temp_free_i32(fp0);
6070 opn = "mul.s";
6071 optype = BINOP;
6072 break;
6073 case FOP(3, 16):
6075 TCGv_i32 fp0 = tcg_temp_new_i32();
6076 TCGv_i32 fp1 = tcg_temp_new_i32();
6078 gen_load_fpr32(fp0, fs);
6079 gen_load_fpr32(fp1, ft);
6080 gen_helper_float_div_s(fp0, fp0, fp1);
6081 tcg_temp_free_i32(fp1);
6082 gen_store_fpr32(fp0, fd);
6083 tcg_temp_free_i32(fp0);
6085 opn = "div.s";
6086 optype = BINOP;
6087 break;
6088 case FOP(4, 16):
6090 TCGv_i32 fp0 = tcg_temp_new_i32();
6092 gen_load_fpr32(fp0, fs);
6093 gen_helper_float_sqrt_s(fp0, fp0);
6094 gen_store_fpr32(fp0, fd);
6095 tcg_temp_free_i32(fp0);
6097 opn = "sqrt.s";
6098 break;
6099 case FOP(5, 16):
6101 TCGv_i32 fp0 = tcg_temp_new_i32();
6103 gen_load_fpr32(fp0, fs);
6104 gen_helper_float_abs_s(fp0, fp0);
6105 gen_store_fpr32(fp0, fd);
6106 tcg_temp_free_i32(fp0);
6108 opn = "abs.s";
6109 break;
6110 case FOP(6, 16):
6112 TCGv_i32 fp0 = tcg_temp_new_i32();
6114 gen_load_fpr32(fp0, fs);
6115 gen_store_fpr32(fp0, fd);
6116 tcg_temp_free_i32(fp0);
6118 opn = "mov.s";
6119 break;
6120 case FOP(7, 16):
6122 TCGv_i32 fp0 = tcg_temp_new_i32();
6124 gen_load_fpr32(fp0, fs);
6125 gen_helper_float_chs_s(fp0, fp0);
6126 gen_store_fpr32(fp0, fd);
6127 tcg_temp_free_i32(fp0);
6129 opn = "neg.s";
6130 break;
6131 case FOP(8, 16):
6132 check_cp1_64bitmode(ctx);
6134 TCGv_i32 fp32 = tcg_temp_new_i32();
6135 TCGv_i64 fp64 = tcg_temp_new_i64();
6137 gen_load_fpr32(fp32, fs);
6138 gen_helper_float_roundl_s(fp64, fp32);
6139 tcg_temp_free_i32(fp32);
6140 gen_store_fpr64(ctx, fp64, fd);
6141 tcg_temp_free_i64(fp64);
6143 opn = "round.l.s";
6144 break;
6145 case FOP(9, 16):
6146 check_cp1_64bitmode(ctx);
6148 TCGv_i32 fp32 = tcg_temp_new_i32();
6149 TCGv_i64 fp64 = tcg_temp_new_i64();
6151 gen_load_fpr32(fp32, fs);
6152 gen_helper_float_truncl_s(fp64, fp32);
6153 tcg_temp_free_i32(fp32);
6154 gen_store_fpr64(ctx, fp64, fd);
6155 tcg_temp_free_i64(fp64);
6157 opn = "trunc.l.s";
6158 break;
6159 case FOP(10, 16):
6160 check_cp1_64bitmode(ctx);
6162 TCGv_i32 fp32 = tcg_temp_new_i32();
6163 TCGv_i64 fp64 = tcg_temp_new_i64();
6165 gen_load_fpr32(fp32, fs);
6166 gen_helper_float_ceill_s(fp64, fp32);
6167 tcg_temp_free_i32(fp32);
6168 gen_store_fpr64(ctx, fp64, fd);
6169 tcg_temp_free_i64(fp64);
6171 opn = "ceil.l.s";
6172 break;
6173 case FOP(11, 16):
6174 check_cp1_64bitmode(ctx);
6176 TCGv_i32 fp32 = tcg_temp_new_i32();
6177 TCGv_i64 fp64 = tcg_temp_new_i64();
6179 gen_load_fpr32(fp32, fs);
6180 gen_helper_float_floorl_s(fp64, fp32);
6181 tcg_temp_free_i32(fp32);
6182 gen_store_fpr64(ctx, fp64, fd);
6183 tcg_temp_free_i64(fp64);
6185 opn = "floor.l.s";
6186 break;
6187 case FOP(12, 16):
6189 TCGv_i32 fp0 = tcg_temp_new_i32();
6191 gen_load_fpr32(fp0, fs);
6192 gen_helper_float_roundw_s(fp0, fp0);
6193 gen_store_fpr32(fp0, fd);
6194 tcg_temp_free_i32(fp0);
6196 opn = "round.w.s";
6197 break;
6198 case FOP(13, 16):
6200 TCGv_i32 fp0 = tcg_temp_new_i32();
6202 gen_load_fpr32(fp0, fs);
6203 gen_helper_float_truncw_s(fp0, fp0);
6204 gen_store_fpr32(fp0, fd);
6205 tcg_temp_free_i32(fp0);
6207 opn = "trunc.w.s";
6208 break;
6209 case FOP(14, 16):
6211 TCGv_i32 fp0 = tcg_temp_new_i32();
6213 gen_load_fpr32(fp0, fs);
6214 gen_helper_float_ceilw_s(fp0, fp0);
6215 gen_store_fpr32(fp0, fd);
6216 tcg_temp_free_i32(fp0);
6218 opn = "ceil.w.s";
6219 break;
6220 case FOP(15, 16):
6222 TCGv_i32 fp0 = tcg_temp_new_i32();
6224 gen_load_fpr32(fp0, fs);
6225 gen_helper_float_floorw_s(fp0, fp0);
6226 gen_store_fpr32(fp0, fd);
6227 tcg_temp_free_i32(fp0);
6229 opn = "floor.w.s";
6230 break;
6231 case FOP(17, 16):
6232 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6233 opn = "movcf.s";
6234 break;
6235 case FOP(18, 16):
6237 int l1 = gen_new_label();
6238 TCGv_i32 fp0;
6240 if (ft != 0) {
6241 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6243 fp0 = tcg_temp_new_i32();
6244 gen_load_fpr32(fp0, fs);
6245 gen_store_fpr32(fp0, fd);
6246 tcg_temp_free_i32(fp0);
6247 gen_set_label(l1);
6249 opn = "movz.s";
6250 break;
6251 case FOP(19, 16):
6253 int l1 = gen_new_label();
6254 TCGv_i32 fp0;
6256 if (ft != 0) {
6257 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6258 fp0 = tcg_temp_new_i32();
6259 gen_load_fpr32(fp0, fs);
6260 gen_store_fpr32(fp0, fd);
6261 tcg_temp_free_i32(fp0);
6262 gen_set_label(l1);
6265 opn = "movn.s";
6266 break;
6267 case FOP(21, 16):
6268 check_cop1x(ctx);
6270 TCGv_i32 fp0 = tcg_temp_new_i32();
6272 gen_load_fpr32(fp0, fs);
6273 gen_helper_float_recip_s(fp0, fp0);
6274 gen_store_fpr32(fp0, fd);
6275 tcg_temp_free_i32(fp0);
6277 opn = "recip.s";
6278 break;
6279 case FOP(22, 16):
6280 check_cop1x(ctx);
6282 TCGv_i32 fp0 = tcg_temp_new_i32();
6284 gen_load_fpr32(fp0, fs);
6285 gen_helper_float_rsqrt_s(fp0, fp0);
6286 gen_store_fpr32(fp0, fd);
6287 tcg_temp_free_i32(fp0);
6289 opn = "rsqrt.s";
6290 break;
6291 case FOP(28, 16):
6292 check_cp1_64bitmode(ctx);
6294 TCGv_i32 fp0 = tcg_temp_new_i32();
6295 TCGv_i32 fp1 = tcg_temp_new_i32();
6297 gen_load_fpr32(fp0, fs);
6298 gen_load_fpr32(fp1, fd);
6299 gen_helper_float_recip2_s(fp0, fp0, fp1);
6300 tcg_temp_free_i32(fp1);
6301 gen_store_fpr32(fp0, fd);
6302 tcg_temp_free_i32(fp0);
6304 opn = "recip2.s";
6305 break;
6306 case FOP(29, 16):
6307 check_cp1_64bitmode(ctx);
6309 TCGv_i32 fp0 = tcg_temp_new_i32();
6311 gen_load_fpr32(fp0, fs);
6312 gen_helper_float_recip1_s(fp0, fp0);
6313 gen_store_fpr32(fp0, fd);
6314 tcg_temp_free_i32(fp0);
6316 opn = "recip1.s";
6317 break;
6318 case FOP(30, 16):
6319 check_cp1_64bitmode(ctx);
6321 TCGv_i32 fp0 = tcg_temp_new_i32();
6323 gen_load_fpr32(fp0, fs);
6324 gen_helper_float_rsqrt1_s(fp0, fp0);
6325 gen_store_fpr32(fp0, fd);
6326 tcg_temp_free_i32(fp0);
6328 opn = "rsqrt1.s";
6329 break;
6330 case FOP(31, 16):
6331 check_cp1_64bitmode(ctx);
6333 TCGv_i32 fp0 = tcg_temp_new_i32();
6334 TCGv_i32 fp1 = tcg_temp_new_i32();
6336 gen_load_fpr32(fp0, fs);
6337 gen_load_fpr32(fp1, ft);
6338 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6339 tcg_temp_free_i32(fp1);
6340 gen_store_fpr32(fp0, fd);
6341 tcg_temp_free_i32(fp0);
6343 opn = "rsqrt2.s";
6344 break;
6345 case FOP(33, 16):
6346 check_cp1_registers(ctx, fd);
6348 TCGv_i32 fp32 = tcg_temp_new_i32();
6349 TCGv_i64 fp64 = tcg_temp_new_i64();
6351 gen_load_fpr32(fp32, fs);
6352 gen_helper_float_cvtd_s(fp64, fp32);
6353 tcg_temp_free_i32(fp32);
6354 gen_store_fpr64(ctx, fp64, fd);
6355 tcg_temp_free_i64(fp64);
6357 opn = "cvt.d.s";
6358 break;
6359 case FOP(36, 16):
6361 TCGv_i32 fp0 = tcg_temp_new_i32();
6363 gen_load_fpr32(fp0, fs);
6364 gen_helper_float_cvtw_s(fp0, fp0);
6365 gen_store_fpr32(fp0, fd);
6366 tcg_temp_free_i32(fp0);
6368 opn = "cvt.w.s";
6369 break;
6370 case FOP(37, 16):
6371 check_cp1_64bitmode(ctx);
6373 TCGv_i32 fp32 = tcg_temp_new_i32();
6374 TCGv_i64 fp64 = tcg_temp_new_i64();
6376 gen_load_fpr32(fp32, fs);
6377 gen_helper_float_cvtl_s(fp64, fp32);
6378 tcg_temp_free_i32(fp32);
6379 gen_store_fpr64(ctx, fp64, fd);
6380 tcg_temp_free_i64(fp64);
6382 opn = "cvt.l.s";
6383 break;
6384 case FOP(38, 16):
6385 check_cp1_64bitmode(ctx);
6387 TCGv_i64 fp64 = tcg_temp_new_i64();
6388 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6389 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6391 gen_load_fpr32(fp32_0, fs);
6392 gen_load_fpr32(fp32_1, ft);
6393 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6394 tcg_temp_free_i32(fp32_1);
6395 tcg_temp_free_i32(fp32_0);
6396 gen_store_fpr64(ctx, fp64, fd);
6397 tcg_temp_free_i64(fp64);
6399 opn = "cvt.ps.s";
6400 break;
6401 case FOP(48, 16):
6402 case FOP(49, 16):
6403 case FOP(50, 16):
6404 case FOP(51, 16):
6405 case FOP(52, 16):
6406 case FOP(53, 16):
6407 case FOP(54, 16):
6408 case FOP(55, 16):
6409 case FOP(56, 16):
6410 case FOP(57, 16):
6411 case FOP(58, 16):
6412 case FOP(59, 16):
6413 case FOP(60, 16):
6414 case FOP(61, 16):
6415 case FOP(62, 16):
6416 case FOP(63, 16):
6418 TCGv_i32 fp0 = tcg_temp_new_i32();
6419 TCGv_i32 fp1 = tcg_temp_new_i32();
6421 gen_load_fpr32(fp0, fs);
6422 gen_load_fpr32(fp1, ft);
6423 if (ctx->opcode & (1 << 6)) {
6424 check_cop1x(ctx);
6425 gen_cmpabs_s(func-48, fp0, fp1, cc);
6426 opn = condnames_abs[func-48];
6427 } else {
6428 gen_cmp_s(func-48, fp0, fp1, cc);
6429 opn = condnames[func-48];
6431 tcg_temp_free_i32(fp0);
6432 tcg_temp_free_i32(fp1);
6434 break;
6435 case FOP(0, 17):
6436 check_cp1_registers(ctx, fs | ft | fd);
6438 TCGv_i64 fp0 = tcg_temp_new_i64();
6439 TCGv_i64 fp1 = tcg_temp_new_i64();
6441 gen_load_fpr64(ctx, fp0, fs);
6442 gen_load_fpr64(ctx, fp1, ft);
6443 gen_helper_float_add_d(fp0, fp0, fp1);
6444 tcg_temp_free_i64(fp1);
6445 gen_store_fpr64(ctx, fp0, fd);
6446 tcg_temp_free_i64(fp0);
6448 opn = "add.d";
6449 optype = BINOP;
6450 break;
6451 case FOP(1, 17):
6452 check_cp1_registers(ctx, fs | ft | fd);
6454 TCGv_i64 fp0 = tcg_temp_new_i64();
6455 TCGv_i64 fp1 = tcg_temp_new_i64();
6457 gen_load_fpr64(ctx, fp0, fs);
6458 gen_load_fpr64(ctx, fp1, ft);
6459 gen_helper_float_sub_d(fp0, fp0, fp1);
6460 tcg_temp_free_i64(fp1);
6461 gen_store_fpr64(ctx, fp0, fd);
6462 tcg_temp_free_i64(fp0);
6464 opn = "sub.d";
6465 optype = BINOP;
6466 break;
6467 case FOP(2, 17):
6468 check_cp1_registers(ctx, fs | ft | fd);
6470 TCGv_i64 fp0 = tcg_temp_new_i64();
6471 TCGv_i64 fp1 = tcg_temp_new_i64();
6473 gen_load_fpr64(ctx, fp0, fs);
6474 gen_load_fpr64(ctx, fp1, ft);
6475 gen_helper_float_mul_d(fp0, fp0, fp1);
6476 tcg_temp_free_i64(fp1);
6477 gen_store_fpr64(ctx, fp0, fd);
6478 tcg_temp_free_i64(fp0);
6480 opn = "mul.d";
6481 optype = BINOP;
6482 break;
6483 case FOP(3, 17):
6484 check_cp1_registers(ctx, fs | ft | fd);
6486 TCGv_i64 fp0 = tcg_temp_new_i64();
6487 TCGv_i64 fp1 = tcg_temp_new_i64();
6489 gen_load_fpr64(ctx, fp0, fs);
6490 gen_load_fpr64(ctx, fp1, ft);
6491 gen_helper_float_div_d(fp0, fp0, fp1);
6492 tcg_temp_free_i64(fp1);
6493 gen_store_fpr64(ctx, fp0, fd);
6494 tcg_temp_free_i64(fp0);
6496 opn = "div.d";
6497 optype = BINOP;
6498 break;
6499 case FOP(4, 17):
6500 check_cp1_registers(ctx, fs | fd);
6502 TCGv_i64 fp0 = tcg_temp_new_i64();
6504 gen_load_fpr64(ctx, fp0, fs);
6505 gen_helper_float_sqrt_d(fp0, fp0);
6506 gen_store_fpr64(ctx, fp0, fd);
6507 tcg_temp_free_i64(fp0);
6509 opn = "sqrt.d";
6510 break;
6511 case FOP(5, 17):
6512 check_cp1_registers(ctx, fs | fd);
6514 TCGv_i64 fp0 = tcg_temp_new_i64();
6516 gen_load_fpr64(ctx, fp0, fs);
6517 gen_helper_float_abs_d(fp0, fp0);
6518 gen_store_fpr64(ctx, fp0, fd);
6519 tcg_temp_free_i64(fp0);
6521 opn = "abs.d";
6522 break;
6523 case FOP(6, 17):
6524 check_cp1_registers(ctx, fs | fd);
6526 TCGv_i64 fp0 = tcg_temp_new_i64();
6528 gen_load_fpr64(ctx, fp0, fs);
6529 gen_store_fpr64(ctx, fp0, fd);
6530 tcg_temp_free_i64(fp0);
6532 opn = "mov.d";
6533 break;
6534 case FOP(7, 17):
6535 check_cp1_registers(ctx, fs | fd);
6537 TCGv_i64 fp0 = tcg_temp_new_i64();
6539 gen_load_fpr64(ctx, fp0, fs);
6540 gen_helper_float_chs_d(fp0, fp0);
6541 gen_store_fpr64(ctx, fp0, fd);
6542 tcg_temp_free_i64(fp0);
6544 opn = "neg.d";
6545 break;
6546 case FOP(8, 17):
6547 check_cp1_64bitmode(ctx);
6549 TCGv_i64 fp0 = tcg_temp_new_i64();
6551 gen_load_fpr64(ctx, fp0, fs);
6552 gen_helper_float_roundl_d(fp0, fp0);
6553 gen_store_fpr64(ctx, fp0, fd);
6554 tcg_temp_free_i64(fp0);
6556 opn = "round.l.d";
6557 break;
6558 case FOP(9, 17):
6559 check_cp1_64bitmode(ctx);
6561 TCGv_i64 fp0 = tcg_temp_new_i64();
6563 gen_load_fpr64(ctx, fp0, fs);
6564 gen_helper_float_truncl_d(fp0, fp0);
6565 gen_store_fpr64(ctx, fp0, fd);
6566 tcg_temp_free_i64(fp0);
6568 opn = "trunc.l.d";
6569 break;
6570 case FOP(10, 17):
6571 check_cp1_64bitmode(ctx);
6573 TCGv_i64 fp0 = tcg_temp_new_i64();
6575 gen_load_fpr64(ctx, fp0, fs);
6576 gen_helper_float_ceill_d(fp0, fp0);
6577 gen_store_fpr64(ctx, fp0, fd);
6578 tcg_temp_free_i64(fp0);
6580 opn = "ceil.l.d";
6581 break;
6582 case FOP(11, 17):
6583 check_cp1_64bitmode(ctx);
6585 TCGv_i64 fp0 = tcg_temp_new_i64();
6587 gen_load_fpr64(ctx, fp0, fs);
6588 gen_helper_float_floorl_d(fp0, fp0);
6589 gen_store_fpr64(ctx, fp0, fd);
6590 tcg_temp_free_i64(fp0);
6592 opn = "floor.l.d";
6593 break;
6594 case FOP(12, 17):
6595 check_cp1_registers(ctx, fs);
6597 TCGv_i32 fp32 = tcg_temp_new_i32();
6598 TCGv_i64 fp64 = tcg_temp_new_i64();
6600 gen_load_fpr64(ctx, fp64, fs);
6601 gen_helper_float_roundw_d(fp32, fp64);
6602 tcg_temp_free_i64(fp64);
6603 gen_store_fpr32(fp32, fd);
6604 tcg_temp_free_i32(fp32);
6606 opn = "round.w.d";
6607 break;
6608 case FOP(13, 17):
6609 check_cp1_registers(ctx, fs);
6611 TCGv_i32 fp32 = tcg_temp_new_i32();
6612 TCGv_i64 fp64 = tcg_temp_new_i64();
6614 gen_load_fpr64(ctx, fp64, fs);
6615 gen_helper_float_truncw_d(fp32, fp64);
6616 tcg_temp_free_i64(fp64);
6617 gen_store_fpr32(fp32, fd);
6618 tcg_temp_free_i32(fp32);
6620 opn = "trunc.w.d";
6621 break;
6622 case FOP(14, 17):
6623 check_cp1_registers(ctx, fs);
6625 TCGv_i32 fp32 = tcg_temp_new_i32();
6626 TCGv_i64 fp64 = tcg_temp_new_i64();
6628 gen_load_fpr64(ctx, fp64, fs);
6629 gen_helper_float_ceilw_d(fp32, fp64);
6630 tcg_temp_free_i64(fp64);
6631 gen_store_fpr32(fp32, fd);
6632 tcg_temp_free_i32(fp32);
6634 opn = "ceil.w.d";
6635 break;
6636 case FOP(15, 17):
6637 check_cp1_registers(ctx, fs);
6639 TCGv_i32 fp32 = tcg_temp_new_i32();
6640 TCGv_i64 fp64 = tcg_temp_new_i64();
6642 gen_load_fpr64(ctx, fp64, fs);
6643 gen_helper_float_floorw_d(fp32, fp64);
6644 tcg_temp_free_i64(fp64);
6645 gen_store_fpr32(fp32, fd);
6646 tcg_temp_free_i32(fp32);
6648 opn = "floor.w.d";
6649 break;
6650 case FOP(17, 17):
6651 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6652 opn = "movcf.d";
6653 break;
6654 case FOP(18, 17):
6656 int l1 = gen_new_label();
6657 TCGv_i64 fp0;
6659 if (ft != 0) {
6660 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6662 fp0 = tcg_temp_new_i64();
6663 gen_load_fpr64(ctx, fp0, fs);
6664 gen_store_fpr64(ctx, fp0, fd);
6665 tcg_temp_free_i64(fp0);
6666 gen_set_label(l1);
6668 opn = "movz.d";
6669 break;
6670 case FOP(19, 17):
6672 int l1 = gen_new_label();
6673 TCGv_i64 fp0;
6675 if (ft != 0) {
6676 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6677 fp0 = tcg_temp_new_i64();
6678 gen_load_fpr64(ctx, fp0, fs);
6679 gen_store_fpr64(ctx, fp0, fd);
6680 tcg_temp_free_i64(fp0);
6681 gen_set_label(l1);
6684 opn = "movn.d";
6685 break;
6686 case FOP(21, 17):
6687 check_cp1_64bitmode(ctx);
6689 TCGv_i64 fp0 = tcg_temp_new_i64();
6691 gen_load_fpr64(ctx, fp0, fs);
6692 gen_helper_float_recip_d(fp0, fp0);
6693 gen_store_fpr64(ctx, fp0, fd);
6694 tcg_temp_free_i64(fp0);
6696 opn = "recip.d";
6697 break;
6698 case FOP(22, 17):
6699 check_cp1_64bitmode(ctx);
6701 TCGv_i64 fp0 = tcg_temp_new_i64();
6703 gen_load_fpr64(ctx, fp0, fs);
6704 gen_helper_float_rsqrt_d(fp0, fp0);
6705 gen_store_fpr64(ctx, fp0, fd);
6706 tcg_temp_free_i64(fp0);
6708 opn = "rsqrt.d";
6709 break;
6710 case FOP(28, 17):
6711 check_cp1_64bitmode(ctx);
6713 TCGv_i64 fp0 = tcg_temp_new_i64();
6714 TCGv_i64 fp1 = tcg_temp_new_i64();
6716 gen_load_fpr64(ctx, fp0, fs);
6717 gen_load_fpr64(ctx, fp1, ft);
6718 gen_helper_float_recip2_d(fp0, fp0, fp1);
6719 tcg_temp_free_i64(fp1);
6720 gen_store_fpr64(ctx, fp0, fd);
6721 tcg_temp_free_i64(fp0);
6723 opn = "recip2.d";
6724 break;
6725 case FOP(29, 17):
6726 check_cp1_64bitmode(ctx);
6728 TCGv_i64 fp0 = tcg_temp_new_i64();
6730 gen_load_fpr64(ctx, fp0, fs);
6731 gen_helper_float_recip1_d(fp0, fp0);
6732 gen_store_fpr64(ctx, fp0, fd);
6733 tcg_temp_free_i64(fp0);
6735 opn = "recip1.d";
6736 break;
6737 case FOP(30, 17):
6738 check_cp1_64bitmode(ctx);
6740 TCGv_i64 fp0 = tcg_temp_new_i64();
6742 gen_load_fpr64(ctx, fp0, fs);
6743 gen_helper_float_rsqrt1_d(fp0, fp0);
6744 gen_store_fpr64(ctx, fp0, fd);
6745 tcg_temp_free_i64(fp0);
6747 opn = "rsqrt1.d";
6748 break;
6749 case FOP(31, 17):
6750 check_cp1_64bitmode(ctx);
6752 TCGv_i64 fp0 = tcg_temp_new_i64();
6753 TCGv_i64 fp1 = tcg_temp_new_i64();
6755 gen_load_fpr64(ctx, fp0, fs);
6756 gen_load_fpr64(ctx, fp1, ft);
6757 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6758 tcg_temp_free_i64(fp1);
6759 gen_store_fpr64(ctx, fp0, fd);
6760 tcg_temp_free_i64(fp0);
6762 opn = "rsqrt2.d";
6763 break;
6764 case FOP(48, 17):
6765 case FOP(49, 17):
6766 case FOP(50, 17):
6767 case FOP(51, 17):
6768 case FOP(52, 17):
6769 case FOP(53, 17):
6770 case FOP(54, 17):
6771 case FOP(55, 17):
6772 case FOP(56, 17):
6773 case FOP(57, 17):
6774 case FOP(58, 17):
6775 case FOP(59, 17):
6776 case FOP(60, 17):
6777 case FOP(61, 17):
6778 case FOP(62, 17):
6779 case FOP(63, 17):
6781 TCGv_i64 fp0 = tcg_temp_new_i64();
6782 TCGv_i64 fp1 = tcg_temp_new_i64();
6784 gen_load_fpr64(ctx, fp0, fs);
6785 gen_load_fpr64(ctx, fp1, ft);
6786 if (ctx->opcode & (1 << 6)) {
6787 check_cop1x(ctx);
6788 check_cp1_registers(ctx, fs | ft);
6789 gen_cmpabs_d(func-48, fp0, fp1, cc);
6790 opn = condnames_abs[func-48];
6791 } else {
6792 check_cp1_registers(ctx, fs | ft);
6793 gen_cmp_d(func-48, fp0, fp1, cc);
6794 opn = condnames[func-48];
6796 tcg_temp_free_i64(fp0);
6797 tcg_temp_free_i64(fp1);
6799 break;
6800 case FOP(32, 17):
6801 check_cp1_registers(ctx, fs);
6803 TCGv_i32 fp32 = tcg_temp_new_i32();
6804 TCGv_i64 fp64 = tcg_temp_new_i64();
6806 gen_load_fpr64(ctx, fp64, fs);
6807 gen_helper_float_cvts_d(fp32, fp64);
6808 tcg_temp_free_i64(fp64);
6809 gen_store_fpr32(fp32, fd);
6810 tcg_temp_free_i32(fp32);
6812 opn = "cvt.s.d";
6813 break;
6814 case FOP(36, 17):
6815 check_cp1_registers(ctx, fs);
6817 TCGv_i32 fp32 = tcg_temp_new_i32();
6818 TCGv_i64 fp64 = tcg_temp_new_i64();
6820 gen_load_fpr64(ctx, fp64, fs);
6821 gen_helper_float_cvtw_d(fp32, fp64);
6822 tcg_temp_free_i64(fp64);
6823 gen_store_fpr32(fp32, fd);
6824 tcg_temp_free_i32(fp32);
6826 opn = "cvt.w.d";
6827 break;
6828 case FOP(37, 17):
6829 check_cp1_64bitmode(ctx);
6831 TCGv_i64 fp0 = tcg_temp_new_i64();
6833 gen_load_fpr64(ctx, fp0, fs);
6834 gen_helper_float_cvtl_d(fp0, fp0);
6835 gen_store_fpr64(ctx, fp0, fd);
6836 tcg_temp_free_i64(fp0);
6838 opn = "cvt.l.d";
6839 break;
6840 case FOP(32, 20):
6842 TCGv_i32 fp0 = tcg_temp_new_i32();
6844 gen_load_fpr32(fp0, fs);
6845 gen_helper_float_cvts_w(fp0, fp0);
6846 gen_store_fpr32(fp0, fd);
6847 tcg_temp_free_i32(fp0);
6849 opn = "cvt.s.w";
6850 break;
6851 case FOP(33, 20):
6852 check_cp1_registers(ctx, fd);
6854 TCGv_i32 fp32 = tcg_temp_new_i32();
6855 TCGv_i64 fp64 = tcg_temp_new_i64();
6857 gen_load_fpr32(fp32, fs);
6858 gen_helper_float_cvtd_w(fp64, fp32);
6859 tcg_temp_free_i32(fp32);
6860 gen_store_fpr64(ctx, fp64, fd);
6861 tcg_temp_free_i64(fp64);
6863 opn = "cvt.d.w";
6864 break;
6865 case FOP(32, 21):
6866 check_cp1_64bitmode(ctx);
6868 TCGv_i32 fp32 = tcg_temp_new_i32();
6869 TCGv_i64 fp64 = tcg_temp_new_i64();
6871 gen_load_fpr64(ctx, fp64, fs);
6872 gen_helper_float_cvts_l(fp32, fp64);
6873 tcg_temp_free_i64(fp64);
6874 gen_store_fpr32(fp32, fd);
6875 tcg_temp_free_i32(fp32);
6877 opn = "cvt.s.l";
6878 break;
6879 case FOP(33, 21):
6880 check_cp1_64bitmode(ctx);
6882 TCGv_i64 fp0 = tcg_temp_new_i64();
6884 gen_load_fpr64(ctx, fp0, fs);
6885 gen_helper_float_cvtd_l(fp0, fp0);
6886 gen_store_fpr64(ctx, fp0, fd);
6887 tcg_temp_free_i64(fp0);
6889 opn = "cvt.d.l";
6890 break;
6891 case FOP(38, 20):
6892 check_cp1_64bitmode(ctx);
6894 TCGv_i64 fp0 = tcg_temp_new_i64();
6896 gen_load_fpr64(ctx, fp0, fs);
6897 gen_helper_float_cvtps_pw(fp0, fp0);
6898 gen_store_fpr64(ctx, fp0, fd);
6899 tcg_temp_free_i64(fp0);
6901 opn = "cvt.ps.pw";
6902 break;
6903 case FOP(0, 22):
6904 check_cp1_64bitmode(ctx);
6906 TCGv_i64 fp0 = tcg_temp_new_i64();
6907 TCGv_i64 fp1 = tcg_temp_new_i64();
6909 gen_load_fpr64(ctx, fp0, fs);
6910 gen_load_fpr64(ctx, fp1, ft);
6911 gen_helper_float_add_ps(fp0, fp0, fp1);
6912 tcg_temp_free_i64(fp1);
6913 gen_store_fpr64(ctx, fp0, fd);
6914 tcg_temp_free_i64(fp0);
6916 opn = "add.ps";
6917 break;
6918 case FOP(1, 22):
6919 check_cp1_64bitmode(ctx);
6921 TCGv_i64 fp0 = tcg_temp_new_i64();
6922 TCGv_i64 fp1 = tcg_temp_new_i64();
6924 gen_load_fpr64(ctx, fp0, fs);
6925 gen_load_fpr64(ctx, fp1, ft);
6926 gen_helper_float_sub_ps(fp0, fp0, fp1);
6927 tcg_temp_free_i64(fp1);
6928 gen_store_fpr64(ctx, fp0, fd);
6929 tcg_temp_free_i64(fp0);
6931 opn = "sub.ps";
6932 break;
6933 case FOP(2, 22):
6934 check_cp1_64bitmode(ctx);
6936 TCGv_i64 fp0 = tcg_temp_new_i64();
6937 TCGv_i64 fp1 = tcg_temp_new_i64();
6939 gen_load_fpr64(ctx, fp0, fs);
6940 gen_load_fpr64(ctx, fp1, ft);
6941 gen_helper_float_mul_ps(fp0, fp0, fp1);
6942 tcg_temp_free_i64(fp1);
6943 gen_store_fpr64(ctx, fp0, fd);
6944 tcg_temp_free_i64(fp0);
6946 opn = "mul.ps";
6947 break;
6948 case FOP(5, 22):
6949 check_cp1_64bitmode(ctx);
6951 TCGv_i64 fp0 = tcg_temp_new_i64();
6953 gen_load_fpr64(ctx, fp0, fs);
6954 gen_helper_float_abs_ps(fp0, fp0);
6955 gen_store_fpr64(ctx, fp0, fd);
6956 tcg_temp_free_i64(fp0);
6958 opn = "abs.ps";
6959 break;
6960 case FOP(6, 22):
6961 check_cp1_64bitmode(ctx);
6963 TCGv_i64 fp0 = tcg_temp_new_i64();
6965 gen_load_fpr64(ctx, fp0, fs);
6966 gen_store_fpr64(ctx, fp0, fd);
6967 tcg_temp_free_i64(fp0);
6969 opn = "mov.ps";
6970 break;
6971 case FOP(7, 22):
6972 check_cp1_64bitmode(ctx);
6974 TCGv_i64 fp0 = tcg_temp_new_i64();
6976 gen_load_fpr64(ctx, fp0, fs);
6977 gen_helper_float_chs_ps(fp0, fp0);
6978 gen_store_fpr64(ctx, fp0, fd);
6979 tcg_temp_free_i64(fp0);
6981 opn = "neg.ps";
6982 break;
6983 case FOP(17, 22):
6984 check_cp1_64bitmode(ctx);
6985 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6986 opn = "movcf.ps";
6987 break;
6988 case FOP(18, 22):
6989 check_cp1_64bitmode(ctx);
6991 int l1 = gen_new_label();
6992 TCGv_i64 fp0;
6994 if (ft != 0)
6995 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6996 fp0 = tcg_temp_new_i64();
6997 gen_load_fpr64(ctx, fp0, fs);
6998 gen_store_fpr64(ctx, fp0, fd);
6999 tcg_temp_free_i64(fp0);
7000 gen_set_label(l1);
7002 opn = "movz.ps";
7003 break;
7004 case FOP(19, 22):
7005 check_cp1_64bitmode(ctx);
7007 int l1 = gen_new_label();
7008 TCGv_i64 fp0;
7010 if (ft != 0) {
7011 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7012 fp0 = tcg_temp_new_i64();
7013 gen_load_fpr64(ctx, fp0, fs);
7014 gen_store_fpr64(ctx, fp0, fd);
7015 tcg_temp_free_i64(fp0);
7016 gen_set_label(l1);
7019 opn = "movn.ps";
7020 break;
7021 case FOP(24, 22):
7022 check_cp1_64bitmode(ctx);
7024 TCGv_i64 fp0 = tcg_temp_new_i64();
7025 TCGv_i64 fp1 = tcg_temp_new_i64();
7027 gen_load_fpr64(ctx, fp0, ft);
7028 gen_load_fpr64(ctx, fp1, fs);
7029 gen_helper_float_addr_ps(fp0, fp0, fp1);
7030 tcg_temp_free_i64(fp1);
7031 gen_store_fpr64(ctx, fp0, fd);
7032 tcg_temp_free_i64(fp0);
7034 opn = "addr.ps";
7035 break;
7036 case FOP(26, 22):
7037 check_cp1_64bitmode(ctx);
7039 TCGv_i64 fp0 = tcg_temp_new_i64();
7040 TCGv_i64 fp1 = tcg_temp_new_i64();
7042 gen_load_fpr64(ctx, fp0, ft);
7043 gen_load_fpr64(ctx, fp1, fs);
7044 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7045 tcg_temp_free_i64(fp1);
7046 gen_store_fpr64(ctx, fp0, fd);
7047 tcg_temp_free_i64(fp0);
7049 opn = "mulr.ps";
7050 break;
7051 case FOP(28, 22):
7052 check_cp1_64bitmode(ctx);
7054 TCGv_i64 fp0 = tcg_temp_new_i64();
7055 TCGv_i64 fp1 = tcg_temp_new_i64();
7057 gen_load_fpr64(ctx, fp0, fs);
7058 gen_load_fpr64(ctx, fp1, fd);
7059 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7060 tcg_temp_free_i64(fp1);
7061 gen_store_fpr64(ctx, fp0, fd);
7062 tcg_temp_free_i64(fp0);
7064 opn = "recip2.ps";
7065 break;
7066 case FOP(29, 22):
7067 check_cp1_64bitmode(ctx);
7069 TCGv_i64 fp0 = tcg_temp_new_i64();
7071 gen_load_fpr64(ctx, fp0, fs);
7072 gen_helper_float_recip1_ps(fp0, fp0);
7073 gen_store_fpr64(ctx, fp0, fd);
7074 tcg_temp_free_i64(fp0);
7076 opn = "recip1.ps";
7077 break;
7078 case FOP(30, 22):
7079 check_cp1_64bitmode(ctx);
7081 TCGv_i64 fp0 = tcg_temp_new_i64();
7083 gen_load_fpr64(ctx, fp0, fs);
7084 gen_helper_float_rsqrt1_ps(fp0, fp0);
7085 gen_store_fpr64(ctx, fp0, fd);
7086 tcg_temp_free_i64(fp0);
7088 opn = "rsqrt1.ps";
7089 break;
7090 case FOP(31, 22):
7091 check_cp1_64bitmode(ctx);
7093 TCGv_i64 fp0 = tcg_temp_new_i64();
7094 TCGv_i64 fp1 = tcg_temp_new_i64();
7096 gen_load_fpr64(ctx, fp0, fs);
7097 gen_load_fpr64(ctx, fp1, ft);
7098 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7099 tcg_temp_free_i64(fp1);
7100 gen_store_fpr64(ctx, fp0, fd);
7101 tcg_temp_free_i64(fp0);
7103 opn = "rsqrt2.ps";
7104 break;
7105 case FOP(32, 22):
7106 check_cp1_64bitmode(ctx);
7108 TCGv_i32 fp0 = tcg_temp_new_i32();
7110 gen_load_fpr32h(fp0, fs);
7111 gen_helper_float_cvts_pu(fp0, fp0);
7112 gen_store_fpr32(fp0, fd);
7113 tcg_temp_free_i32(fp0);
7115 opn = "cvt.s.pu";
7116 break;
7117 case FOP(36, 22):
7118 check_cp1_64bitmode(ctx);
7120 TCGv_i64 fp0 = tcg_temp_new_i64();
7122 gen_load_fpr64(ctx, fp0, fs);
7123 gen_helper_float_cvtpw_ps(fp0, fp0);
7124 gen_store_fpr64(ctx, fp0, fd);
7125 tcg_temp_free_i64(fp0);
7127 opn = "cvt.pw.ps";
7128 break;
7129 case FOP(40, 22):
7130 check_cp1_64bitmode(ctx);
7132 TCGv_i32 fp0 = tcg_temp_new_i32();
7134 gen_load_fpr32(fp0, fs);
7135 gen_helper_float_cvts_pl(fp0, fp0);
7136 gen_store_fpr32(fp0, fd);
7137 tcg_temp_free_i32(fp0);
7139 opn = "cvt.s.pl";
7140 break;
7141 case FOP(44, 22):
7142 check_cp1_64bitmode(ctx);
7144 TCGv_i32 fp0 = tcg_temp_new_i32();
7145 TCGv_i32 fp1 = tcg_temp_new_i32();
7147 gen_load_fpr32(fp0, fs);
7148 gen_load_fpr32(fp1, ft);
7149 gen_store_fpr32h(fp0, fd);
7150 gen_store_fpr32(fp1, fd);
7151 tcg_temp_free_i32(fp0);
7152 tcg_temp_free_i32(fp1);
7154 opn = "pll.ps";
7155 break;
7156 case FOP(45, 22):
7157 check_cp1_64bitmode(ctx);
7159 TCGv_i32 fp0 = tcg_temp_new_i32();
7160 TCGv_i32 fp1 = tcg_temp_new_i32();
7162 gen_load_fpr32(fp0, fs);
7163 gen_load_fpr32h(fp1, ft);
7164 gen_store_fpr32(fp1, fd);
7165 gen_store_fpr32h(fp0, fd);
7166 tcg_temp_free_i32(fp0);
7167 tcg_temp_free_i32(fp1);
7169 opn = "plu.ps";
7170 break;
7171 case FOP(46, 22):
7172 check_cp1_64bitmode(ctx);
7174 TCGv_i32 fp0 = tcg_temp_new_i32();
7175 TCGv_i32 fp1 = tcg_temp_new_i32();
7177 gen_load_fpr32h(fp0, fs);
7178 gen_load_fpr32(fp1, ft);
7179 gen_store_fpr32(fp1, fd);
7180 gen_store_fpr32h(fp0, fd);
7181 tcg_temp_free_i32(fp0);
7182 tcg_temp_free_i32(fp1);
7184 opn = "pul.ps";
7185 break;
7186 case FOP(47, 22):
7187 check_cp1_64bitmode(ctx);
7189 TCGv_i32 fp0 = tcg_temp_new_i32();
7190 TCGv_i32 fp1 = tcg_temp_new_i32();
7192 gen_load_fpr32h(fp0, fs);
7193 gen_load_fpr32h(fp1, ft);
7194 gen_store_fpr32(fp1, fd);
7195 gen_store_fpr32h(fp0, fd);
7196 tcg_temp_free_i32(fp0);
7197 tcg_temp_free_i32(fp1);
7199 opn = "puu.ps";
7200 break;
7201 case FOP(48, 22):
7202 case FOP(49, 22):
7203 case FOP(50, 22):
7204 case FOP(51, 22):
7205 case FOP(52, 22):
7206 case FOP(53, 22):
7207 case FOP(54, 22):
7208 case FOP(55, 22):
7209 case FOP(56, 22):
7210 case FOP(57, 22):
7211 case FOP(58, 22):
7212 case FOP(59, 22):
7213 case FOP(60, 22):
7214 case FOP(61, 22):
7215 case FOP(62, 22):
7216 case FOP(63, 22):
7217 check_cp1_64bitmode(ctx);
7219 TCGv_i64 fp0 = tcg_temp_new_i64();
7220 TCGv_i64 fp1 = tcg_temp_new_i64();
7222 gen_load_fpr64(ctx, fp0, fs);
7223 gen_load_fpr64(ctx, fp1, ft);
7224 if (ctx->opcode & (1 << 6)) {
7225 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7226 opn = condnames_abs[func-48];
7227 } else {
7228 gen_cmp_ps(func-48, fp0, fp1, cc);
7229 opn = condnames[func-48];
7231 tcg_temp_free_i64(fp0);
7232 tcg_temp_free_i64(fp1);
7234 break;
7235 default:
7236 MIPS_INVAL(opn);
7237 generate_exception (ctx, EXCP_RI);
7238 return;
7240 switch (optype) {
7241 case BINOP:
7242 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7243 break;
7244 case CMPOP:
7245 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7246 break;
7247 default:
7248 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7249 break;
7253 /* Coprocessor 3 (FPU) */
7254 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7255 int fd, int fs, int base, int index)
7257 const char *opn = "extended float load/store";
7258 int store = 0;
7259 TCGv t0 = tcg_temp_new();
7261 if (base == 0) {
7262 gen_load_gpr(t0, index);
7263 } else if (index == 0) {
7264 gen_load_gpr(t0, base);
7265 } else {
7266 gen_load_gpr(t0, index);
7267 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
7269 /* Don't do NOP if destination is zero: we must perform the actual
7270 memory access. */
7271 save_cpu_state(ctx, 0);
7272 switch (opc) {
7273 case OPC_LWXC1:
7274 check_cop1x(ctx);
7276 TCGv_i32 fp0 = tcg_temp_new_i32();
7278 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7279 tcg_gen_trunc_tl_i32(fp0, t0);
7280 gen_store_fpr32(fp0, fd);
7281 tcg_temp_free_i32(fp0);
7283 opn = "lwxc1";
7284 break;
7285 case OPC_LDXC1:
7286 check_cop1x(ctx);
7287 check_cp1_registers(ctx, fd);
7289 TCGv_i64 fp0 = tcg_temp_new_i64();
7291 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7292 gen_store_fpr64(ctx, fp0, fd);
7293 tcg_temp_free_i64(fp0);
7295 opn = "ldxc1";
7296 break;
7297 case OPC_LUXC1:
7298 check_cp1_64bitmode(ctx);
7299 tcg_gen_andi_tl(t0, t0, ~0x7);
7301 TCGv_i64 fp0 = tcg_temp_new_i64();
7303 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7304 gen_store_fpr64(ctx, fp0, fd);
7305 tcg_temp_free_i64(fp0);
7307 opn = "luxc1";
7308 break;
7309 case OPC_SWXC1:
7310 check_cop1x(ctx);
7312 TCGv_i32 fp0 = tcg_temp_new_i32();
7313 TCGv t1 = tcg_temp_new();
7315 gen_load_fpr32(fp0, fs);
7316 tcg_gen_extu_i32_tl(t1, fp0);
7317 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7318 tcg_temp_free_i32(fp0);
7319 tcg_temp_free(t1);
7321 opn = "swxc1";
7322 store = 1;
7323 break;
7324 case OPC_SDXC1:
7325 check_cop1x(ctx);
7326 check_cp1_registers(ctx, fs);
7328 TCGv_i64 fp0 = tcg_temp_new_i64();
7330 gen_load_fpr64(ctx, fp0, fs);
7331 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7332 tcg_temp_free_i64(fp0);
7334 opn = "sdxc1";
7335 store = 1;
7336 break;
7337 case OPC_SUXC1:
7338 check_cp1_64bitmode(ctx);
7339 tcg_gen_andi_tl(t0, t0, ~0x7);
7341 TCGv_i64 fp0 = tcg_temp_new_i64();
7343 gen_load_fpr64(ctx, fp0, fs);
7344 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7345 tcg_temp_free_i64(fp0);
7347 opn = "suxc1";
7348 store = 1;
7349 break;
7351 tcg_temp_free(t0);
7352 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7353 regnames[index], regnames[base]);
7356 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7357 int fd, int fr, int fs, int ft)
7359 const char *opn = "flt3_arith";
7361 switch (opc) {
7362 case OPC_ALNV_PS:
7363 check_cp1_64bitmode(ctx);
7365 TCGv t0 = tcg_temp_local_new();
7366 TCGv_i32 fp = tcg_temp_new_i32();
7367 TCGv_i32 fph = tcg_temp_new_i32();
7368 int l1 = gen_new_label();
7369 int l2 = gen_new_label();
7371 gen_load_gpr(t0, fr);
7372 tcg_gen_andi_tl(t0, t0, 0x7);
7374 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7375 gen_load_fpr32(fp, fs);
7376 gen_load_fpr32h(fph, fs);
7377 gen_store_fpr32(fp, fd);
7378 gen_store_fpr32h(fph, fd);
7379 tcg_gen_br(l2);
7380 gen_set_label(l1);
7381 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7382 tcg_temp_free(t0);
7383 #ifdef TARGET_WORDS_BIGENDIAN
7384 gen_load_fpr32(fp, fs);
7385 gen_load_fpr32h(fph, ft);
7386 gen_store_fpr32h(fp, fd);
7387 gen_store_fpr32(fph, fd);
7388 #else
7389 gen_load_fpr32h(fph, fs);
7390 gen_load_fpr32(fp, ft);
7391 gen_store_fpr32(fph, fd);
7392 gen_store_fpr32h(fp, fd);
7393 #endif
7394 gen_set_label(l2);
7395 tcg_temp_free_i32(fp);
7396 tcg_temp_free_i32(fph);
7398 opn = "alnv.ps";
7399 break;
7400 case OPC_MADD_S:
7401 check_cop1x(ctx);
7403 TCGv_i32 fp0 = tcg_temp_new_i32();
7404 TCGv_i32 fp1 = tcg_temp_new_i32();
7405 TCGv_i32 fp2 = tcg_temp_new_i32();
7407 gen_load_fpr32(fp0, fs);
7408 gen_load_fpr32(fp1, ft);
7409 gen_load_fpr32(fp2, fr);
7410 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7411 tcg_temp_free_i32(fp0);
7412 tcg_temp_free_i32(fp1);
7413 gen_store_fpr32(fp2, fd);
7414 tcg_temp_free_i32(fp2);
7416 opn = "madd.s";
7417 break;
7418 case OPC_MADD_D:
7419 check_cop1x(ctx);
7420 check_cp1_registers(ctx, fd | fs | ft | fr);
7422 TCGv_i64 fp0 = tcg_temp_new_i64();
7423 TCGv_i64 fp1 = tcg_temp_new_i64();
7424 TCGv_i64 fp2 = tcg_temp_new_i64();
7426 gen_load_fpr64(ctx, fp0, fs);
7427 gen_load_fpr64(ctx, fp1, ft);
7428 gen_load_fpr64(ctx, fp2, fr);
7429 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7430 tcg_temp_free_i64(fp0);
7431 tcg_temp_free_i64(fp1);
7432 gen_store_fpr64(ctx, fp2, fd);
7433 tcg_temp_free_i64(fp2);
7435 opn = "madd.d";
7436 break;
7437 case OPC_MADD_PS:
7438 check_cp1_64bitmode(ctx);
7440 TCGv_i64 fp0 = tcg_temp_new_i64();
7441 TCGv_i64 fp1 = tcg_temp_new_i64();
7442 TCGv_i64 fp2 = tcg_temp_new_i64();
7444 gen_load_fpr64(ctx, fp0, fs);
7445 gen_load_fpr64(ctx, fp1, ft);
7446 gen_load_fpr64(ctx, fp2, fr);
7447 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7448 tcg_temp_free_i64(fp0);
7449 tcg_temp_free_i64(fp1);
7450 gen_store_fpr64(ctx, fp2, fd);
7451 tcg_temp_free_i64(fp2);
7453 opn = "madd.ps";
7454 break;
7455 case OPC_MSUB_S:
7456 check_cop1x(ctx);
7458 TCGv_i32 fp0 = tcg_temp_new_i32();
7459 TCGv_i32 fp1 = tcg_temp_new_i32();
7460 TCGv_i32 fp2 = tcg_temp_new_i32();
7462 gen_load_fpr32(fp0, fs);
7463 gen_load_fpr32(fp1, ft);
7464 gen_load_fpr32(fp2, fr);
7465 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7466 tcg_temp_free_i32(fp0);
7467 tcg_temp_free_i32(fp1);
7468 gen_store_fpr32(fp2, fd);
7469 tcg_temp_free_i32(fp2);
7471 opn = "msub.s";
7472 break;
7473 case OPC_MSUB_D:
7474 check_cop1x(ctx);
7475 check_cp1_registers(ctx, fd | fs | ft | fr);
7477 TCGv_i64 fp0 = tcg_temp_new_i64();
7478 TCGv_i64 fp1 = tcg_temp_new_i64();
7479 TCGv_i64 fp2 = tcg_temp_new_i64();
7481 gen_load_fpr64(ctx, fp0, fs);
7482 gen_load_fpr64(ctx, fp1, ft);
7483 gen_load_fpr64(ctx, fp2, fr);
7484 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7485 tcg_temp_free_i64(fp0);
7486 tcg_temp_free_i64(fp1);
7487 gen_store_fpr64(ctx, fp2, fd);
7488 tcg_temp_free_i64(fp2);
7490 opn = "msub.d";
7491 break;
7492 case OPC_MSUB_PS:
7493 check_cp1_64bitmode(ctx);
7495 TCGv_i64 fp0 = tcg_temp_new_i64();
7496 TCGv_i64 fp1 = tcg_temp_new_i64();
7497 TCGv_i64 fp2 = tcg_temp_new_i64();
7499 gen_load_fpr64(ctx, fp0, fs);
7500 gen_load_fpr64(ctx, fp1, ft);
7501 gen_load_fpr64(ctx, fp2, fr);
7502 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7503 tcg_temp_free_i64(fp0);
7504 tcg_temp_free_i64(fp1);
7505 gen_store_fpr64(ctx, fp2, fd);
7506 tcg_temp_free_i64(fp2);
7508 opn = "msub.ps";
7509 break;
7510 case OPC_NMADD_S:
7511 check_cop1x(ctx);
7513 TCGv_i32 fp0 = tcg_temp_new_i32();
7514 TCGv_i32 fp1 = tcg_temp_new_i32();
7515 TCGv_i32 fp2 = tcg_temp_new_i32();
7517 gen_load_fpr32(fp0, fs);
7518 gen_load_fpr32(fp1, ft);
7519 gen_load_fpr32(fp2, fr);
7520 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7521 tcg_temp_free_i32(fp0);
7522 tcg_temp_free_i32(fp1);
7523 gen_store_fpr32(fp2, fd);
7524 tcg_temp_free_i32(fp2);
7526 opn = "nmadd.s";
7527 break;
7528 case OPC_NMADD_D:
7529 check_cop1x(ctx);
7530 check_cp1_registers(ctx, fd | fs | ft | fr);
7532 TCGv_i64 fp0 = tcg_temp_new_i64();
7533 TCGv_i64 fp1 = tcg_temp_new_i64();
7534 TCGv_i64 fp2 = tcg_temp_new_i64();
7536 gen_load_fpr64(ctx, fp0, fs);
7537 gen_load_fpr64(ctx, fp1, ft);
7538 gen_load_fpr64(ctx, fp2, fr);
7539 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7540 tcg_temp_free_i64(fp0);
7541 tcg_temp_free_i64(fp1);
7542 gen_store_fpr64(ctx, fp2, fd);
7543 tcg_temp_free_i64(fp2);
7545 opn = "nmadd.d";
7546 break;
7547 case OPC_NMADD_PS:
7548 check_cp1_64bitmode(ctx);
7550 TCGv_i64 fp0 = tcg_temp_new_i64();
7551 TCGv_i64 fp1 = tcg_temp_new_i64();
7552 TCGv_i64 fp2 = tcg_temp_new_i64();
7554 gen_load_fpr64(ctx, fp0, fs);
7555 gen_load_fpr64(ctx, fp1, ft);
7556 gen_load_fpr64(ctx, fp2, fr);
7557 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7558 tcg_temp_free_i64(fp0);
7559 tcg_temp_free_i64(fp1);
7560 gen_store_fpr64(ctx, fp2, fd);
7561 tcg_temp_free_i64(fp2);
7563 opn = "nmadd.ps";
7564 break;
7565 case OPC_NMSUB_S:
7566 check_cop1x(ctx);
7568 TCGv_i32 fp0 = tcg_temp_new_i32();
7569 TCGv_i32 fp1 = tcg_temp_new_i32();
7570 TCGv_i32 fp2 = tcg_temp_new_i32();
7572 gen_load_fpr32(fp0, fs);
7573 gen_load_fpr32(fp1, ft);
7574 gen_load_fpr32(fp2, fr);
7575 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7576 tcg_temp_free_i32(fp0);
7577 tcg_temp_free_i32(fp1);
7578 gen_store_fpr32(fp2, fd);
7579 tcg_temp_free_i32(fp2);
7581 opn = "nmsub.s";
7582 break;
7583 case OPC_NMSUB_D:
7584 check_cop1x(ctx);
7585 check_cp1_registers(ctx, fd | fs | ft | fr);
7587 TCGv_i64 fp0 = tcg_temp_new_i64();
7588 TCGv_i64 fp1 = tcg_temp_new_i64();
7589 TCGv_i64 fp2 = tcg_temp_new_i64();
7591 gen_load_fpr64(ctx, fp0, fs);
7592 gen_load_fpr64(ctx, fp1, ft);
7593 gen_load_fpr64(ctx, fp2, fr);
7594 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7595 tcg_temp_free_i64(fp0);
7596 tcg_temp_free_i64(fp1);
7597 gen_store_fpr64(ctx, fp2, fd);
7598 tcg_temp_free_i64(fp2);
7600 opn = "nmsub.d";
7601 break;
7602 case OPC_NMSUB_PS:
7603 check_cp1_64bitmode(ctx);
7605 TCGv_i64 fp0 = tcg_temp_new_i64();
7606 TCGv_i64 fp1 = tcg_temp_new_i64();
7607 TCGv_i64 fp2 = tcg_temp_new_i64();
7609 gen_load_fpr64(ctx, fp0, fs);
7610 gen_load_fpr64(ctx, fp1, ft);
7611 gen_load_fpr64(ctx, fp2, fr);
7612 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7613 tcg_temp_free_i64(fp0);
7614 tcg_temp_free_i64(fp1);
7615 gen_store_fpr64(ctx, fp2, fd);
7616 tcg_temp_free_i64(fp2);
7618 opn = "nmsub.ps";
7619 break;
7620 default:
7621 MIPS_INVAL(opn);
7622 generate_exception (ctx, EXCP_RI);
7623 return;
7625 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7626 fregnames[fs], fregnames[ft]);
7629 /* ISA extensions (ASEs) */
7630 /* MIPS16 extension to MIPS32 */
7631 /* SmartMIPS extension to MIPS32 */
7633 #if defined(TARGET_MIPS64)
7635 /* MDMX extension to MIPS64 */
7637 #endif
7639 static void decode_opc (CPUState *env, DisasContext *ctx)
7641 int32_t offset;
7642 int rs, rt, rd, sa;
7643 uint32_t op, op1, op2;
7644 int16_t imm;
7646 /* make sure instructions are on a word boundary */
7647 if (ctx->pc & 0x3) {
7648 env->CP0_BadVAddr = ctx->pc;
7649 generate_exception(ctx, EXCP_AdEL);
7650 return;
7653 /* Handle blikely not taken case */
7654 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7655 int l1 = gen_new_label();
7657 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7658 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7659 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
7660 gen_goto_tb(ctx, 1, ctx->pc + 4);
7661 gen_set_label(l1);
7664 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
7665 tcg_gen_debug_insn_start(ctx->pc);
7667 op = MASK_OP_MAJOR(ctx->opcode);
7668 rs = (ctx->opcode >> 21) & 0x1f;
7669 rt = (ctx->opcode >> 16) & 0x1f;
7670 rd = (ctx->opcode >> 11) & 0x1f;
7671 sa = (ctx->opcode >> 6) & 0x1f;
7672 imm = (int16_t)ctx->opcode;
7673 switch (op) {
7674 case OPC_SPECIAL:
7675 op1 = MASK_SPECIAL(ctx->opcode);
7676 switch (op1) {
7677 case OPC_SLL: /* Shift with immediate */
7678 case OPC_SRA:
7679 case OPC_SRL:
7680 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7681 break;
7682 case OPC_MOVN: /* Conditional move */
7683 case OPC_MOVZ:
7684 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7685 gen_cond_move(env, op1, rd, rs, rt);
7686 break;
7687 case OPC_ADD ... OPC_SUBU:
7688 gen_arith(env, ctx, op1, rd, rs, rt);
7689 break;
7690 case OPC_SLLV: /* Shifts */
7691 case OPC_SRLV:
7692 case OPC_SRAV:
7693 gen_shift(env, ctx, op1, rd, rs, rt);
7694 break;
7695 case OPC_SLT: /* Set on less than */
7696 case OPC_SLTU:
7697 gen_slt(env, op1, rd, rs, rt);
7698 break;
7699 case OPC_AND: /* Logic*/
7700 case OPC_OR:
7701 case OPC_NOR:
7702 case OPC_XOR:
7703 gen_logic(env, op1, rd, rs, rt);
7704 break;
7705 case OPC_MULT ... OPC_DIVU:
7706 if (sa) {
7707 check_insn(env, ctx, INSN_VR54XX);
7708 op1 = MASK_MUL_VR54XX(ctx->opcode);
7709 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7710 } else
7711 gen_muldiv(ctx, op1, rs, rt);
7712 break;
7713 case OPC_JR ... OPC_JALR:
7714 gen_compute_branch(ctx, op1, rs, rd, sa);
7715 return;
7716 case OPC_TGE ... OPC_TEQ: /* Traps */
7717 case OPC_TNE:
7718 gen_trap(ctx, op1, rs, rt, -1);
7719 break;
7720 case OPC_MFHI: /* Move from HI/LO */
7721 case OPC_MFLO:
7722 gen_HILO(ctx, op1, rd);
7723 break;
7724 case OPC_MTHI:
7725 case OPC_MTLO: /* Move to HI/LO */
7726 gen_HILO(ctx, op1, rs);
7727 break;
7728 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7729 #ifdef MIPS_STRICT_STANDARD
7730 MIPS_INVAL("PMON / selsl");
7731 generate_exception(ctx, EXCP_RI);
7732 #else
7733 gen_helper_0i(pmon, sa);
7734 #endif
7735 break;
7736 case OPC_SYSCALL:
7737 generate_exception(ctx, EXCP_SYSCALL);
7738 ctx->bstate = BS_STOP;
7739 break;
7740 case OPC_BREAK:
7741 generate_exception(ctx, EXCP_BREAK);
7742 break;
7743 case OPC_SPIM:
7744 #ifdef MIPS_STRICT_STANDARD
7745 MIPS_INVAL("SPIM");
7746 generate_exception(ctx, EXCP_RI);
7747 #else
7748 /* Implemented as RI exception for now. */
7749 MIPS_INVAL("spim (unofficial)");
7750 generate_exception(ctx, EXCP_RI);
7751 #endif
7752 break;
7753 case OPC_SYNC:
7754 /* Treat as NOP. */
7755 break;
7757 case OPC_MOVCI:
7758 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7759 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7760 check_cp1_enabled(ctx);
7761 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7762 (ctx->opcode >> 16) & 1);
7763 } else {
7764 generate_exception_err(ctx, EXCP_CpU, 1);
7766 break;
7768 #if defined(TARGET_MIPS64)
7769 /* MIPS64 specific opcodes */
7770 case OPC_DSLL:
7771 case OPC_DSRA:
7772 case OPC_DSRL:
7773 case OPC_DSLL32:
7774 case OPC_DSRA32:
7775 case OPC_DSRL32:
7776 check_insn(env, ctx, ISA_MIPS3);
7777 check_mips_64(ctx);
7778 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7779 break;
7780 case OPC_DADD ... OPC_DSUBU:
7781 check_insn(env, ctx, ISA_MIPS3);
7782 check_mips_64(ctx);
7783 gen_arith(env, ctx, op1, rd, rs, rt);
7784 break;
7785 case OPC_DSLLV:
7786 case OPC_DSRAV:
7787 case OPC_DSRLV:
7788 check_insn(env, ctx, ISA_MIPS3);
7789 check_mips_64(ctx);
7790 gen_shift(env, ctx, op1, rd, rs, rt);
7791 break;
7792 case OPC_DMULT ... OPC_DDIVU:
7793 check_insn(env, ctx, ISA_MIPS3);
7794 check_mips_64(ctx);
7795 gen_muldiv(ctx, op1, rs, rt);
7796 break;
7797 #endif
7798 default: /* Invalid */
7799 MIPS_INVAL("special");
7800 generate_exception(ctx, EXCP_RI);
7801 break;
7803 break;
7804 case OPC_SPECIAL2:
7805 op1 = MASK_SPECIAL2(ctx->opcode);
7806 switch (op1) {
7807 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7808 case OPC_MSUB ... OPC_MSUBU:
7809 check_insn(env, ctx, ISA_MIPS32);
7810 gen_muldiv(ctx, op1, rs, rt);
7811 break;
7812 case OPC_MUL:
7813 gen_arith(env, ctx, op1, rd, rs, rt);
7814 break;
7815 case OPC_CLO:
7816 case OPC_CLZ:
7817 check_insn(env, ctx, ISA_MIPS32);
7818 gen_cl(ctx, op1, rd, rs);
7819 break;
7820 case OPC_SDBBP:
7821 /* XXX: not clear which exception should be raised
7822 * when in debug mode...
7824 check_insn(env, ctx, ISA_MIPS32);
7825 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7826 generate_exception(ctx, EXCP_DBp);
7827 } else {
7828 generate_exception(ctx, EXCP_DBp);
7830 /* Treat as NOP. */
7831 break;
7832 #if defined(TARGET_MIPS64)
7833 case OPC_DCLO:
7834 case OPC_DCLZ:
7835 check_insn(env, ctx, ISA_MIPS64);
7836 check_mips_64(ctx);
7837 gen_cl(ctx, op1, rd, rs);
7838 break;
7839 #endif
7840 default: /* Invalid */
7841 MIPS_INVAL("special2");
7842 generate_exception(ctx, EXCP_RI);
7843 break;
7845 break;
7846 case OPC_SPECIAL3:
7847 op1 = MASK_SPECIAL3(ctx->opcode);
7848 switch (op1) {
7849 case OPC_EXT:
7850 case OPC_INS:
7851 check_insn(env, ctx, ISA_MIPS32R2);
7852 gen_bitops(ctx, op1, rt, rs, sa, rd);
7853 break;
7854 case OPC_BSHFL:
7855 check_insn(env, ctx, ISA_MIPS32R2);
7856 op2 = MASK_BSHFL(ctx->opcode);
7857 gen_bshfl(ctx, op2, rt, rd);
7858 break;
7859 case OPC_RDHWR:
7860 check_insn(env, ctx, ISA_MIPS32R2);
7862 TCGv t0 = tcg_temp_new();
7864 switch (rd) {
7865 case 0:
7866 save_cpu_state(ctx, 1);
7867 gen_helper_rdhwr_cpunum(t0);
7868 gen_store_gpr(t0, rt);
7869 break;
7870 case 1:
7871 save_cpu_state(ctx, 1);
7872 gen_helper_rdhwr_synci_step(t0);
7873 gen_store_gpr(t0, rt);
7874 break;
7875 case 2:
7876 save_cpu_state(ctx, 1);
7877 gen_helper_rdhwr_cc(t0);
7878 gen_store_gpr(t0, rt);
7879 break;
7880 case 3:
7881 save_cpu_state(ctx, 1);
7882 gen_helper_rdhwr_ccres(t0);
7883 gen_store_gpr(t0, rt);
7884 break;
7885 case 29:
7886 #if defined(CONFIG_USER_ONLY)
7887 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7888 gen_store_gpr(t0, rt);
7889 break;
7890 #else
7891 /* XXX: Some CPUs implement this in hardware.
7892 Not supported yet. */
7893 #endif
7894 default: /* Invalid */
7895 MIPS_INVAL("rdhwr");
7896 generate_exception(ctx, EXCP_RI);
7897 break;
7899 tcg_temp_free(t0);
7901 break;
7902 case OPC_FORK:
7903 check_insn(env, ctx, ASE_MT);
7905 TCGv t0 = tcg_temp_new();
7906 TCGv t1 = tcg_temp_new();
7908 gen_load_gpr(t0, rt);
7909 gen_load_gpr(t1, rs);
7910 gen_helper_fork(t0, t1);
7911 tcg_temp_free(t0);
7912 tcg_temp_free(t1);
7914 break;
7915 case OPC_YIELD:
7916 check_insn(env, ctx, ASE_MT);
7918 TCGv t0 = tcg_temp_new();
7920 save_cpu_state(ctx, 1);
7921 gen_load_gpr(t0, rs);
7922 gen_helper_yield(t0, t0);
7923 gen_store_gpr(t0, rd);
7924 tcg_temp_free(t0);
7926 break;
7927 #if defined(TARGET_MIPS64)
7928 case OPC_DEXTM ... OPC_DEXT:
7929 case OPC_DINSM ... OPC_DINS:
7930 check_insn(env, ctx, ISA_MIPS64R2);
7931 check_mips_64(ctx);
7932 gen_bitops(ctx, op1, rt, rs, sa, rd);
7933 break;
7934 case OPC_DBSHFL:
7935 check_insn(env, ctx, ISA_MIPS64R2);
7936 check_mips_64(ctx);
7937 op2 = MASK_DBSHFL(ctx->opcode);
7938 gen_bshfl(ctx, op2, rt, rd);
7939 break;
7940 #endif
7941 default: /* Invalid */
7942 MIPS_INVAL("special3");
7943 generate_exception(ctx, EXCP_RI);
7944 break;
7946 break;
7947 case OPC_REGIMM:
7948 op1 = MASK_REGIMM(ctx->opcode);
7949 switch (op1) {
7950 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7951 case OPC_BLTZAL ... OPC_BGEZALL:
7952 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
7953 return;
7954 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7955 case OPC_TNEI:
7956 gen_trap(ctx, op1, rs, -1, imm);
7957 break;
7958 case OPC_SYNCI:
7959 check_insn(env, ctx, ISA_MIPS32R2);
7960 /* Treat as NOP. */
7961 break;
7962 default: /* Invalid */
7963 MIPS_INVAL("regimm");
7964 generate_exception(ctx, EXCP_RI);
7965 break;
7967 break;
7968 case OPC_CP0:
7969 check_cp0_enabled(ctx);
7970 op1 = MASK_CP0(ctx->opcode);
7971 switch (op1) {
7972 case OPC_MFC0:
7973 case OPC_MTC0:
7974 case OPC_MFTR:
7975 case OPC_MTTR:
7976 #if defined(TARGET_MIPS64)
7977 case OPC_DMFC0:
7978 case OPC_DMTC0:
7979 #endif
7980 #ifndef CONFIG_USER_ONLY
7981 gen_cp0(env, ctx, op1, rt, rd);
7982 #endif /* !CONFIG_USER_ONLY */
7983 break;
7984 case OPC_C0_FIRST ... OPC_C0_LAST:
7985 #ifndef CONFIG_USER_ONLY
7986 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
7987 #endif /* !CONFIG_USER_ONLY */
7988 break;
7989 case OPC_MFMC0:
7990 #ifndef CONFIG_USER_ONLY
7992 TCGv t0 = tcg_temp_new();
7994 op2 = MASK_MFMC0(ctx->opcode);
7995 switch (op2) {
7996 case OPC_DMT:
7997 check_insn(env, ctx, ASE_MT);
7998 gen_helper_dmt(t0, t0);
7999 gen_store_gpr(t0, rt);
8000 break;
8001 case OPC_EMT:
8002 check_insn(env, ctx, ASE_MT);
8003 gen_helper_emt(t0, t0);
8004 gen_store_gpr(t0, rt);
8005 break;
8006 case OPC_DVPE:
8007 check_insn(env, ctx, ASE_MT);
8008 gen_helper_dvpe(t0, t0);
8009 gen_store_gpr(t0, rt);
8010 break;
8011 case OPC_EVPE:
8012 check_insn(env, ctx, ASE_MT);
8013 gen_helper_evpe(t0, t0);
8014 gen_store_gpr(t0, rt);
8015 break;
8016 case OPC_DI:
8017 check_insn(env, ctx, ISA_MIPS32R2);
8018 save_cpu_state(ctx, 1);
8019 gen_helper_di(t0);
8020 gen_store_gpr(t0, rt);
8021 /* Stop translation as we may have switched the execution mode */
8022 ctx->bstate = BS_STOP;
8023 break;
8024 case OPC_EI:
8025 check_insn(env, ctx, ISA_MIPS32R2);
8026 save_cpu_state(ctx, 1);
8027 gen_helper_ei(t0);
8028 gen_store_gpr(t0, rt);
8029 /* Stop translation as we may have switched the execution mode */
8030 ctx->bstate = BS_STOP;
8031 break;
8032 default: /* Invalid */
8033 MIPS_INVAL("mfmc0");
8034 generate_exception(ctx, EXCP_RI);
8035 break;
8037 tcg_temp_free(t0);
8039 #endif /* !CONFIG_USER_ONLY */
8040 break;
8041 case OPC_RDPGPR:
8042 check_insn(env, ctx, ISA_MIPS32R2);
8043 gen_load_srsgpr(rt, rd);
8044 break;
8045 case OPC_WRPGPR:
8046 check_insn(env, ctx, ISA_MIPS32R2);
8047 gen_store_srsgpr(rt, rd);
8048 break;
8049 default:
8050 MIPS_INVAL("cp0");
8051 generate_exception(ctx, EXCP_RI);
8052 break;
8054 break;
8055 case OPC_ADDI: /* Arithmetic with immediate opcode */
8056 case OPC_ADDIU:
8057 gen_arith_imm(env, ctx, op, rt, rs, imm);
8058 break;
8059 case OPC_SLTI: /* Set on less than with immediate opcode */
8060 case OPC_SLTIU:
8061 gen_slt_imm(env, op, rt, rs, imm);
8062 break;
8063 case OPC_ANDI: /* Arithmetic with immediate opcode */
8064 case OPC_LUI:
8065 case OPC_ORI:
8066 case OPC_XORI:
8067 gen_logic_imm(env, op, rt, rs, imm);
8068 break;
8069 case OPC_J ... OPC_JAL: /* Jump */
8070 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8071 gen_compute_branch(ctx, op, rs, rt, offset);
8072 return;
8073 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8074 case OPC_BEQL ... OPC_BGTZL:
8075 gen_compute_branch(ctx, op, rs, rt, imm << 2);
8076 return;
8077 case OPC_LB ... OPC_LWR: /* Load and stores */
8078 case OPC_SB ... OPC_SW:
8079 case OPC_SWR:
8080 case OPC_LL:
8081 gen_ldst(ctx, op, rt, rs, imm);
8082 break;
8083 case OPC_SC:
8084 gen_st_cond(ctx, op, rt, rs, imm);
8085 break;
8086 case OPC_CACHE:
8087 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
8088 /* Treat as NOP. */
8089 break;
8090 case OPC_PREF:
8091 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8092 /* Treat as NOP. */
8093 break;
8095 /* Floating point (COP1). */
8096 case OPC_LWC1:
8097 case OPC_LDC1:
8098 case OPC_SWC1:
8099 case OPC_SDC1:
8100 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8101 check_cp1_enabled(ctx);
8102 gen_flt_ldst(ctx, op, rt, rs, imm);
8103 } else {
8104 generate_exception_err(ctx, EXCP_CpU, 1);
8106 break;
8108 case OPC_CP1:
8109 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8110 check_cp1_enabled(ctx);
8111 op1 = MASK_CP1(ctx->opcode);
8112 switch (op1) {
8113 case OPC_MFHC1:
8114 case OPC_MTHC1:
8115 check_insn(env, ctx, ISA_MIPS32R2);
8116 case OPC_MFC1:
8117 case OPC_CFC1:
8118 case OPC_MTC1:
8119 case OPC_CTC1:
8120 gen_cp1(ctx, op1, rt, rd);
8121 break;
8122 #if defined(TARGET_MIPS64)
8123 case OPC_DMFC1:
8124 case OPC_DMTC1:
8125 check_insn(env, ctx, ISA_MIPS3);
8126 gen_cp1(ctx, op1, rt, rd);
8127 break;
8128 #endif
8129 case OPC_BC1ANY2:
8130 case OPC_BC1ANY4:
8131 check_cop1x(ctx);
8132 check_insn(env, ctx, ASE_MIPS3D);
8133 /* fall through */
8134 case OPC_BC1:
8135 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8136 (rt >> 2) & 0x7, imm << 2);
8137 return;
8138 case OPC_S_FMT:
8139 case OPC_D_FMT:
8140 case OPC_W_FMT:
8141 case OPC_L_FMT:
8142 case OPC_PS_FMT:
8143 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8144 (imm >> 8) & 0x7);
8145 break;
8146 default:
8147 MIPS_INVAL("cp1");
8148 generate_exception (ctx, EXCP_RI);
8149 break;
8151 } else {
8152 generate_exception_err(ctx, EXCP_CpU, 1);
8154 break;
8156 /* COP2. */
8157 case OPC_LWC2:
8158 case OPC_LDC2:
8159 case OPC_SWC2:
8160 case OPC_SDC2:
8161 case OPC_CP2:
8162 /* COP2: Not implemented. */
8163 generate_exception_err(ctx, EXCP_CpU, 2);
8164 break;
8166 case OPC_CP3:
8167 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8168 check_cp1_enabled(ctx);
8169 op1 = MASK_CP3(ctx->opcode);
8170 switch (op1) {
8171 case OPC_LWXC1:
8172 case OPC_LDXC1:
8173 case OPC_LUXC1:
8174 case OPC_SWXC1:
8175 case OPC_SDXC1:
8176 case OPC_SUXC1:
8177 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8178 break;
8179 case OPC_PREFX:
8180 /* Treat as NOP. */
8181 break;
8182 case OPC_ALNV_PS:
8183 case OPC_MADD_S:
8184 case OPC_MADD_D:
8185 case OPC_MADD_PS:
8186 case OPC_MSUB_S:
8187 case OPC_MSUB_D:
8188 case OPC_MSUB_PS:
8189 case OPC_NMADD_S:
8190 case OPC_NMADD_D:
8191 case OPC_NMADD_PS:
8192 case OPC_NMSUB_S:
8193 case OPC_NMSUB_D:
8194 case OPC_NMSUB_PS:
8195 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8196 break;
8197 default:
8198 MIPS_INVAL("cp3");
8199 generate_exception (ctx, EXCP_RI);
8200 break;
8202 } else {
8203 generate_exception_err(ctx, EXCP_CpU, 1);
8205 break;
8207 #if defined(TARGET_MIPS64)
8208 /* MIPS64 opcodes */
8209 case OPC_LWU:
8210 case OPC_LDL ... OPC_LDR:
8211 case OPC_SDL ... OPC_SDR:
8212 case OPC_LLD:
8213 case OPC_LD:
8214 case OPC_SD:
8215 check_insn(env, ctx, ISA_MIPS3);
8216 check_mips_64(ctx);
8217 gen_ldst(ctx, op, rt, rs, imm);
8218 break;
8219 case OPC_SCD:
8220 check_insn(env, ctx, ISA_MIPS3);
8221 check_mips_64(ctx);
8222 gen_st_cond(ctx, op, rt, rs, imm);
8223 break;
8224 case OPC_DADDI:
8225 case OPC_DADDIU:
8226 check_insn(env, ctx, ISA_MIPS3);
8227 check_mips_64(ctx);
8228 gen_arith_imm(env, ctx, op, rt, rs, imm);
8229 break;
8230 #endif
8231 case OPC_JALX:
8232 check_insn(env, ctx, ASE_MIPS16);
8233 /* MIPS16: Not implemented. */
8234 case OPC_MDMX:
8235 check_insn(env, ctx, ASE_MDMX);
8236 /* MDMX: Not implemented. */
8237 default: /* Invalid */
8238 MIPS_INVAL("major opcode");
8239 generate_exception(ctx, EXCP_RI);
8240 break;
8242 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8243 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8244 /* Branches completion */
8245 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8246 ctx->bstate = BS_BRANCH;
8247 save_cpu_state(ctx, 0);
8248 /* FIXME: Need to clear can_do_io. */
8249 switch (hflags) {
8250 case MIPS_HFLAG_B:
8251 /* unconditional branch */
8252 MIPS_DEBUG("unconditional branch");
8253 gen_goto_tb(ctx, 0, ctx->btarget);
8254 break;
8255 case MIPS_HFLAG_BL:
8256 /* blikely taken case */
8257 MIPS_DEBUG("blikely branch taken");
8258 gen_goto_tb(ctx, 0, ctx->btarget);
8259 break;
8260 case MIPS_HFLAG_BC:
8261 /* Conditional branch */
8262 MIPS_DEBUG("conditional branch");
8264 int l1 = gen_new_label();
8266 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8267 gen_goto_tb(ctx, 1, ctx->pc + 4);
8268 gen_set_label(l1);
8269 gen_goto_tb(ctx, 0, ctx->btarget);
8271 break;
8272 case MIPS_HFLAG_BR:
8273 /* unconditional branch to register */
8274 MIPS_DEBUG("branch to register");
8275 tcg_gen_mov_tl(cpu_PC, btarget);
8276 if (ctx->singlestep_enabled) {
8277 save_cpu_state(ctx, 0);
8278 gen_helper_0i(raise_exception, EXCP_DEBUG);
8280 tcg_gen_exit_tb(0);
8281 break;
8282 default:
8283 MIPS_DEBUG("unknown branch");
8284 break;
8289 static inline void
8290 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8291 int search_pc)
8293 DisasContext ctx;
8294 target_ulong pc_start;
8295 uint16_t *gen_opc_end;
8296 CPUBreakpoint *bp;
8297 int j, lj = -1;
8298 int num_insns;
8299 int max_insns;
8301 if (search_pc)
8302 qemu_log("search pc %d\n", search_pc);
8304 pc_start = tb->pc;
8305 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8306 ctx.pc = pc_start;
8307 ctx.saved_pc = -1;
8308 ctx.singlestep_enabled = env->singlestep_enabled;
8309 ctx.tb = tb;
8310 ctx.bstate = BS_NONE;
8311 /* Restore delay slot state from the tb context. */
8312 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8313 restore_cpu_state(env, &ctx);
8314 #ifdef CONFIG_USER_ONLY
8315 ctx.mem_idx = MIPS_HFLAG_UM;
8316 #else
8317 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8318 #endif
8319 num_insns = 0;
8320 max_insns = tb->cflags & CF_COUNT_MASK;
8321 if (max_insns == 0)
8322 max_insns = CF_COUNT_MASK;
8323 #ifdef DEBUG_DISAS
8324 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
8325 /* FIXME: This may print out stale hflags from env... */
8326 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
8327 #endif
8328 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
8329 gen_icount_start();
8330 while (ctx.bstate == BS_NONE) {
8331 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8332 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
8333 if (bp->pc == ctx.pc) {
8334 save_cpu_state(&ctx, 1);
8335 ctx.bstate = BS_BRANCH;
8336 gen_helper_0i(raise_exception, EXCP_DEBUG);
8337 /* Include the breakpoint location or the tb won't
8338 * be flushed when it must be. */
8339 ctx.pc += 4;
8340 goto done_generating;
8345 if (search_pc) {
8346 j = gen_opc_ptr - gen_opc_buf;
8347 if (lj < j) {
8348 lj++;
8349 while (lj < j)
8350 gen_opc_instr_start[lj++] = 0;
8352 gen_opc_pc[lj] = ctx.pc;
8353 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8354 gen_opc_instr_start[lj] = 1;
8355 gen_opc_icount[lj] = num_insns;
8357 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8358 gen_io_start();
8359 ctx.opcode = ldl_code(ctx.pc);
8360 decode_opc(env, &ctx);
8361 ctx.pc += 4;
8362 num_insns++;
8364 /* Execute a branch and its delay slot as a single instruction.
8365 This is what GDB expects and is consistent with what the
8366 hardware does (e.g. if a delay slot instruction faults, the
8367 reported PC is the PC of the branch). */
8368 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
8369 break;
8371 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8372 break;
8374 if (gen_opc_ptr >= gen_opc_end)
8375 break;
8377 if (num_insns >= max_insns)
8378 break;
8380 if (singlestep)
8381 break;
8383 if (tb->cflags & CF_LAST_IO)
8384 gen_io_end();
8385 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
8386 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
8387 gen_helper_0i(raise_exception, EXCP_DEBUG);
8388 } else {
8389 switch (ctx.bstate) {
8390 case BS_STOP:
8391 gen_helper_interrupt_restart();
8392 gen_goto_tb(&ctx, 0, ctx.pc);
8393 break;
8394 case BS_NONE:
8395 save_cpu_state(&ctx, 0);
8396 gen_goto_tb(&ctx, 0, ctx.pc);
8397 break;
8398 case BS_EXCP:
8399 gen_helper_interrupt_restart();
8400 tcg_gen_exit_tb(0);
8401 break;
8402 case BS_BRANCH:
8403 default:
8404 break;
8407 done_generating:
8408 gen_icount_end(tb, num_insns);
8409 *gen_opc_ptr = INDEX_op_end;
8410 if (search_pc) {
8411 j = gen_opc_ptr - gen_opc_buf;
8412 lj++;
8413 while (lj <= j)
8414 gen_opc_instr_start[lj++] = 0;
8415 } else {
8416 tb->size = ctx.pc - pc_start;
8417 tb->icount = num_insns;
8419 #ifdef DEBUG_DISAS
8420 LOG_DISAS("\n");
8421 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8422 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8423 log_target_disas(pc_start, ctx.pc - pc_start, 0);
8424 qemu_log("\n");
8426 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8427 #endif
8430 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8432 gen_intermediate_code_internal(env, tb, 0);
8435 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8437 gen_intermediate_code_internal(env, tb, 1);
8440 static void fpu_dump_state(CPUState *env, FILE *f,
8441 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8442 int flags)
8444 int i;
8445 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8447 #define printfpr(fp) \
8448 do { \
8449 if (is_fpu64) \
8450 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8451 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8452 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8453 else { \
8454 fpr_t tmp; \
8455 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8456 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8457 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8458 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8459 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8461 } while(0)
8464 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8465 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8466 get_float_exception_flags(&env->active_fpu.fp_status));
8467 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8468 fpu_fprintf(f, "%3s: ", fregnames[i]);
8469 printfpr(&env->active_fpu.fpr[i]);
8472 #undef printfpr
8475 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8476 /* Debug help: The architecture requires 32bit code to maintain proper
8477 sign-extended values on 64bit machines. */
8479 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8481 static void
8482 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8483 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8484 int flags)
8486 int i;
8488 if (!SIGN_EXT_P(env->active_tc.PC))
8489 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8490 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8491 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8492 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8493 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8494 if (!SIGN_EXT_P(env->btarget))
8495 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8497 for (i = 0; i < 32; i++) {
8498 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8499 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8502 if (!SIGN_EXT_P(env->CP0_EPC))
8503 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8504 if (!SIGN_EXT_P(env->CP0_LLAddr))
8505 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
8507 #endif
8509 void cpu_dump_state (CPUState *env, FILE *f,
8510 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8511 int flags)
8513 int i;
8515 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",
8516 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8517 env->hflags, env->btarget, env->bcond);
8518 for (i = 0; i < 32; i++) {
8519 if ((i & 3) == 0)
8520 cpu_fprintf(f, "GPR%02d:", i);
8521 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8522 if ((i & 3) == 3)
8523 cpu_fprintf(f, "\n");
8526 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8527 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8528 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8529 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
8530 if (env->hflags & MIPS_HFLAG_FPU)
8531 fpu_dump_state(env, f, cpu_fprintf, flags);
8532 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8533 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8534 #endif
8537 static void mips_tcg_init(void)
8539 int i;
8540 static int inited;
8542 /* Initialize various static tables. */
8543 if (inited)
8544 return;
8546 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8547 TCGV_UNUSED(cpu_gpr[0]);
8548 for (i = 1; i < 32; i++)
8549 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
8550 offsetof(CPUState, active_tc.gpr[i]),
8551 regnames[i]);
8552 cpu_PC = tcg_global_mem_new(TCG_AREG0,
8553 offsetof(CPUState, active_tc.PC), "PC");
8554 for (i = 0; i < MIPS_DSP_ACC; i++) {
8555 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
8556 offsetof(CPUState, active_tc.HI[i]),
8557 regnames_HI[i]);
8558 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
8559 offsetof(CPUState, active_tc.LO[i]),
8560 regnames_LO[i]);
8561 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
8562 offsetof(CPUState, active_tc.ACX[i]),
8563 regnames_ACX[i]);
8565 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
8566 offsetof(CPUState, active_tc.DSPControl),
8567 "DSPControl");
8568 bcond = tcg_global_mem_new(TCG_AREG0,
8569 offsetof(CPUState, bcond), "bcond");
8570 btarget = tcg_global_mem_new(TCG_AREG0,
8571 offsetof(CPUState, btarget), "btarget");
8572 hflags = tcg_global_mem_new_i32(TCG_AREG0,
8573 offsetof(CPUState, hflags), "hflags");
8575 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
8576 offsetof(CPUState, active_fpu.fcr0),
8577 "fcr0");
8578 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
8579 offsetof(CPUState, active_fpu.fcr31),
8580 "fcr31");
8582 /* register helpers */
8583 #define GEN_HELPER 2
8584 #include "helper.h"
8586 inited = 1;
8589 #include "translate_init.c"
8591 CPUMIPSState *cpu_mips_init (const char *cpu_model)
8593 CPUMIPSState *env;
8594 const mips_def_t *def;
8596 def = cpu_mips_find_by_name(cpu_model);
8597 if (!def)
8598 return NULL;
8599 env = qemu_mallocz(sizeof(CPUMIPSState));
8600 env->cpu_model = def;
8602 cpu_exec_init(env);
8603 env->cpu_model_str = cpu_model;
8604 mips_tcg_init();
8605 cpu_reset(env);
8606 qemu_init_vcpu(env);
8607 return env;
8610 void cpu_reset (CPUMIPSState *env)
8612 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
8613 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
8614 log_cpu_state(env, 0);
8617 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8619 tlb_flush(env, 1);
8621 /* Minimal init */
8622 #if defined(CONFIG_USER_ONLY)
8623 env->hflags = MIPS_HFLAG_UM;
8624 /* Enable access to the SYNCI_Step register. */
8625 env->CP0_HWREna |= (1 << 1);
8626 #else
8627 if (env->hflags & MIPS_HFLAG_BMASK) {
8628 /* If the exception was raised from a delay slot,
8629 come back to the jump. */
8630 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8631 } else {
8632 env->CP0_ErrorEPC = env->active_tc.PC;
8634 env->active_tc.PC = (int32_t)0xBFC00000;
8635 env->CP0_Wired = 0;
8636 /* SMP not implemented */
8637 env->CP0_EBase = 0x80000000;
8638 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8639 /* vectored interrupts not implemented, timer on int 7,
8640 no performance counters. */
8641 env->CP0_IntCtl = 0xe0000000;
8643 int i;
8645 for (i = 0; i < 7; i++) {
8646 env->CP0_WatchLo[i] = 0;
8647 env->CP0_WatchHi[i] = 0x80000000;
8649 env->CP0_WatchLo[7] = 0;
8650 env->CP0_WatchHi[7] = 0;
8652 /* Count register increments in debug mode, EJTAG version 1 */
8653 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8654 env->hflags = MIPS_HFLAG_CP0;
8655 #endif
8656 env->exception_index = EXCP_NONE;
8657 cpu_mips_register(env, env->cpu_model);
8660 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8661 unsigned long searched_pc, int pc_pos, void *puc)
8663 env->active_tc.PC = gen_opc_pc[pc_pos];
8664 env->hflags &= ~MIPS_HFLAG_BMASK;
8665 env->hflags |= gen_opc_hflags[pc_pos];