target-mips: add gen_base_offset_addr
[qemu.git] / target-mips / translate.c
blobb43d3bd065e41093335aaceba10ad413524a296e
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_ROTR = OPC_SRL | (1 << 21),
132 OPC_SRA = 0x03 | OPC_SPECIAL,
133 OPC_SLLV = 0x04 | OPC_SPECIAL,
134 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
135 OPC_ROTRV = OPC_SRLV | (1 << 6),
136 OPC_SRAV = 0x07 | OPC_SPECIAL,
137 OPC_DSLLV = 0x14 | OPC_SPECIAL,
138 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
139 OPC_DROTRV = OPC_DSRLV | (1 << 6),
140 OPC_DSRAV = 0x17 | OPC_SPECIAL,
141 OPC_DSLL = 0x38 | OPC_SPECIAL,
142 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
143 OPC_DROTR = OPC_DSRL | (1 << 21),
144 OPC_DSRA = 0x3B | OPC_SPECIAL,
145 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
146 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
147 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
148 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
149 /* Multiplication / division */
150 OPC_MULT = 0x18 | OPC_SPECIAL,
151 OPC_MULTU = 0x19 | OPC_SPECIAL,
152 OPC_DIV = 0x1A | OPC_SPECIAL,
153 OPC_DIVU = 0x1B | OPC_SPECIAL,
154 OPC_DMULT = 0x1C | OPC_SPECIAL,
155 OPC_DMULTU = 0x1D | OPC_SPECIAL,
156 OPC_DDIV = 0x1E | OPC_SPECIAL,
157 OPC_DDIVU = 0x1F | OPC_SPECIAL,
158 /* 2 registers arithmetic / logic */
159 OPC_ADD = 0x20 | OPC_SPECIAL,
160 OPC_ADDU = 0x21 | OPC_SPECIAL,
161 OPC_SUB = 0x22 | OPC_SPECIAL,
162 OPC_SUBU = 0x23 | OPC_SPECIAL,
163 OPC_AND = 0x24 | OPC_SPECIAL,
164 OPC_OR = 0x25 | OPC_SPECIAL,
165 OPC_XOR = 0x26 | OPC_SPECIAL,
166 OPC_NOR = 0x27 | OPC_SPECIAL,
167 OPC_SLT = 0x2A | OPC_SPECIAL,
168 OPC_SLTU = 0x2B | OPC_SPECIAL,
169 OPC_DADD = 0x2C | OPC_SPECIAL,
170 OPC_DADDU = 0x2D | OPC_SPECIAL,
171 OPC_DSUB = 0x2E | OPC_SPECIAL,
172 OPC_DSUBU = 0x2F | OPC_SPECIAL,
173 /* Jumps */
174 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
175 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
176 /* Traps */
177 OPC_TGE = 0x30 | OPC_SPECIAL,
178 OPC_TGEU = 0x31 | OPC_SPECIAL,
179 OPC_TLT = 0x32 | OPC_SPECIAL,
180 OPC_TLTU = 0x33 | OPC_SPECIAL,
181 OPC_TEQ = 0x34 | OPC_SPECIAL,
182 OPC_TNE = 0x36 | OPC_SPECIAL,
183 /* HI / LO registers load & stores */
184 OPC_MFHI = 0x10 | OPC_SPECIAL,
185 OPC_MTHI = 0x11 | OPC_SPECIAL,
186 OPC_MFLO = 0x12 | OPC_SPECIAL,
187 OPC_MTLO = 0x13 | OPC_SPECIAL,
188 /* Conditional moves */
189 OPC_MOVZ = 0x0A | OPC_SPECIAL,
190 OPC_MOVN = 0x0B | OPC_SPECIAL,
192 OPC_MOVCI = 0x01 | OPC_SPECIAL,
194 /* Special */
195 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
196 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
197 OPC_BREAK = 0x0D | OPC_SPECIAL,
198 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
199 OPC_SYNC = 0x0F | OPC_SPECIAL,
201 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
202 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
203 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
204 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
205 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
206 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
207 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
210 /* Multiplication variants of the vr54xx. */
211 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
213 enum {
214 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
215 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
216 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
217 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
218 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
219 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
220 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
221 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
222 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
223 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
224 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
225 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
226 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
227 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
230 /* REGIMM (rt field) opcodes */
231 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
233 enum {
234 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
235 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
236 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
237 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
238 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
239 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
240 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
241 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
242 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
243 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
244 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
245 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
246 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
247 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
248 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
251 /* Special2 opcodes */
252 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
254 enum {
255 /* Multiply & xxx operations */
256 OPC_MADD = 0x00 | OPC_SPECIAL2,
257 OPC_MADDU = 0x01 | OPC_SPECIAL2,
258 OPC_MUL = 0x02 | OPC_SPECIAL2,
259 OPC_MSUB = 0x04 | OPC_SPECIAL2,
260 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
261 /* Misc */
262 OPC_CLZ = 0x20 | OPC_SPECIAL2,
263 OPC_CLO = 0x21 | OPC_SPECIAL2,
264 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
265 OPC_DCLO = 0x25 | OPC_SPECIAL2,
266 /* Special */
267 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
270 /* Special3 opcodes */
271 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
273 enum {
274 OPC_EXT = 0x00 | OPC_SPECIAL3,
275 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
276 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
277 OPC_DEXT = 0x03 | OPC_SPECIAL3,
278 OPC_INS = 0x04 | OPC_SPECIAL3,
279 OPC_DINSM = 0x05 | OPC_SPECIAL3,
280 OPC_DINSU = 0x06 | OPC_SPECIAL3,
281 OPC_DINS = 0x07 | OPC_SPECIAL3,
282 OPC_FORK = 0x08 | OPC_SPECIAL3,
283 OPC_YIELD = 0x09 | OPC_SPECIAL3,
284 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
285 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
286 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
289 /* BSHFL opcodes */
290 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
292 enum {
293 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
294 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
295 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
298 /* DBSHFL opcodes */
299 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
301 enum {
302 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
303 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
306 /* Coprocessor 0 (rs field) */
307 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
309 enum {
310 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
311 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
312 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
313 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
314 OPC_MFTR = (0x08 << 21) | OPC_CP0,
315 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
316 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
317 OPC_MTTR = (0x0C << 21) | OPC_CP0,
318 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
319 OPC_C0 = (0x10 << 21) | OPC_CP0,
320 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
321 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
324 /* MFMC0 opcodes */
325 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
327 enum {
328 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
329 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
330 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
331 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
332 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
333 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
336 /* Coprocessor 0 (with rs == C0) */
337 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
339 enum {
340 OPC_TLBR = 0x01 | OPC_C0,
341 OPC_TLBWI = 0x02 | OPC_C0,
342 OPC_TLBWR = 0x06 | OPC_C0,
343 OPC_TLBP = 0x08 | OPC_C0,
344 OPC_RFE = 0x10 | OPC_C0,
345 OPC_ERET = 0x18 | OPC_C0,
346 OPC_DERET = 0x1F | OPC_C0,
347 OPC_WAIT = 0x20 | OPC_C0,
350 /* Coprocessor 1 (rs field) */
351 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
353 enum {
354 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
355 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
356 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
357 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
358 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
359 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
360 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
361 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
362 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
363 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
364 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
365 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
366 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
367 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
368 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
369 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
370 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
371 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
374 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
375 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
377 enum {
378 OPC_BC1F = (0x00 << 16) | OPC_BC1,
379 OPC_BC1T = (0x01 << 16) | OPC_BC1,
380 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
381 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
384 enum {
385 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
386 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
389 enum {
390 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
391 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
394 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
396 enum {
397 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
398 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
399 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
400 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
401 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
402 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
403 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
404 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
405 OPC_BC2 = (0x08 << 21) | OPC_CP2,
408 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
410 enum {
411 OPC_LWXC1 = 0x00 | OPC_CP3,
412 OPC_LDXC1 = 0x01 | OPC_CP3,
413 OPC_LUXC1 = 0x05 | OPC_CP3,
414 OPC_SWXC1 = 0x08 | OPC_CP3,
415 OPC_SDXC1 = 0x09 | OPC_CP3,
416 OPC_SUXC1 = 0x0D | OPC_CP3,
417 OPC_PREFX = 0x0F | OPC_CP3,
418 OPC_ALNV_PS = 0x1E | OPC_CP3,
419 OPC_MADD_S = 0x20 | OPC_CP3,
420 OPC_MADD_D = 0x21 | OPC_CP3,
421 OPC_MADD_PS = 0x26 | OPC_CP3,
422 OPC_MSUB_S = 0x28 | OPC_CP3,
423 OPC_MSUB_D = 0x29 | OPC_CP3,
424 OPC_MSUB_PS = 0x2E | OPC_CP3,
425 OPC_NMADD_S = 0x30 | OPC_CP3,
426 OPC_NMADD_D = 0x31 | OPC_CP3,
427 OPC_NMADD_PS= 0x36 | OPC_CP3,
428 OPC_NMSUB_S = 0x38 | OPC_CP3,
429 OPC_NMSUB_D = 0x39 | OPC_CP3,
430 OPC_NMSUB_PS= 0x3E | OPC_CP3,
433 /* global register indices */
434 static TCGv_ptr cpu_env;
435 static TCGv cpu_gpr[32], cpu_PC;
436 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
437 static TCGv cpu_dspctrl, btarget, bcond;
438 static TCGv_i32 hflags;
439 static TCGv_i32 fpu_fcr0, fpu_fcr31;
441 #include "gen-icount.h"
443 #define gen_helper_0i(name, arg) do { \
444 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
445 gen_helper_##name(helper_tmp); \
446 tcg_temp_free_i32(helper_tmp); \
447 } while(0)
449 #define gen_helper_1i(name, arg1, arg2) do { \
450 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
451 gen_helper_##name(arg1, helper_tmp); \
452 tcg_temp_free_i32(helper_tmp); \
453 } while(0)
455 #define gen_helper_2i(name, arg1, arg2, arg3) do { \
456 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
457 gen_helper_##name(arg1, arg2, helper_tmp); \
458 tcg_temp_free_i32(helper_tmp); \
459 } while(0)
461 #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
462 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
463 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
464 tcg_temp_free_i32(helper_tmp); \
465 } while(0)
467 typedef struct DisasContext {
468 struct TranslationBlock *tb;
469 target_ulong pc, saved_pc;
470 uint32_t opcode;
471 int singlestep_enabled;
472 /* Routine used to access memory */
473 int mem_idx;
474 uint32_t hflags, saved_hflags;
475 int bstate;
476 target_ulong btarget;
477 } DisasContext;
479 enum {
480 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
481 * exception condition */
482 BS_STOP = 1, /* We want to stop translation for any reason */
483 BS_BRANCH = 2, /* We reached a branch condition */
484 BS_EXCP = 3, /* We reached an exception condition */
487 static const char *regnames[] =
488 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
489 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
490 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
491 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
493 static const char *regnames_HI[] =
494 { "HI0", "HI1", "HI2", "HI3", };
496 static const char *regnames_LO[] =
497 { "LO0", "LO1", "LO2", "LO3", };
499 static const char *regnames_ACX[] =
500 { "ACX0", "ACX1", "ACX2", "ACX3", };
502 static const char *fregnames[] =
503 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
504 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
505 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
506 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
508 #ifdef MIPS_DEBUG_DISAS
509 #define MIPS_DEBUG(fmt, ...) \
510 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
511 TARGET_FMT_lx ": %08x " fmt "\n", \
512 ctx->pc, ctx->opcode , ## __VA_ARGS__)
513 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
514 #else
515 #define MIPS_DEBUG(fmt, ...) do { } while(0)
516 #define LOG_DISAS(...) do { } while (0)
517 #endif
519 #define MIPS_INVAL(op) \
520 do { \
521 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
522 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
523 } while (0)
525 /* General purpose registers moves. */
526 static inline void gen_load_gpr (TCGv t, int reg)
528 if (reg == 0)
529 tcg_gen_movi_tl(t, 0);
530 else
531 tcg_gen_mov_tl(t, cpu_gpr[reg]);
534 static inline void gen_store_gpr (TCGv t, int reg)
536 if (reg != 0)
537 tcg_gen_mov_tl(cpu_gpr[reg], t);
540 /* Moves to/from ACX register. */
541 static inline void gen_load_ACX (TCGv t, int reg)
543 tcg_gen_mov_tl(t, cpu_ACX[reg]);
546 static inline void gen_store_ACX (TCGv t, int reg)
548 tcg_gen_mov_tl(cpu_ACX[reg], t);
551 /* Moves to/from shadow registers. */
552 static inline void gen_load_srsgpr (int from, int to)
554 TCGv t0 = tcg_temp_new();
556 if (from == 0)
557 tcg_gen_movi_tl(t0, 0);
558 else {
559 TCGv_i32 t2 = tcg_temp_new_i32();
560 TCGv_ptr addr = tcg_temp_new_ptr();
562 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
563 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
564 tcg_gen_andi_i32(t2, t2, 0xf);
565 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
566 tcg_gen_ext_i32_ptr(addr, t2);
567 tcg_gen_add_ptr(addr, cpu_env, addr);
569 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
570 tcg_temp_free_ptr(addr);
571 tcg_temp_free_i32(t2);
573 gen_store_gpr(t0, to);
574 tcg_temp_free(t0);
577 static inline void gen_store_srsgpr (int from, int to)
579 if (to != 0) {
580 TCGv t0 = tcg_temp_new();
581 TCGv_i32 t2 = tcg_temp_new_i32();
582 TCGv_ptr addr = tcg_temp_new_ptr();
584 gen_load_gpr(t0, from);
585 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
586 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
587 tcg_gen_andi_i32(t2, t2, 0xf);
588 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
589 tcg_gen_ext_i32_ptr(addr, t2);
590 tcg_gen_add_ptr(addr, cpu_env, addr);
592 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
593 tcg_temp_free_ptr(addr);
594 tcg_temp_free_i32(t2);
595 tcg_temp_free(t0);
599 /* Floating point register moves. */
600 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
602 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
605 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
607 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
610 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
612 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
615 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
617 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
620 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
622 if (ctx->hflags & MIPS_HFLAG_F64) {
623 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
624 } else {
625 TCGv_i32 t0 = tcg_temp_new_i32();
626 TCGv_i32 t1 = tcg_temp_new_i32();
627 gen_load_fpr32(t0, reg & ~1);
628 gen_load_fpr32(t1, reg | 1);
629 tcg_gen_concat_i32_i64(t, t0, t1);
630 tcg_temp_free_i32(t0);
631 tcg_temp_free_i32(t1);
635 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
637 if (ctx->hflags & MIPS_HFLAG_F64) {
638 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
639 } else {
640 TCGv_i64 t0 = tcg_temp_new_i64();
641 TCGv_i32 t1 = tcg_temp_new_i32();
642 tcg_gen_trunc_i64_i32(t1, t);
643 gen_store_fpr32(t1, reg & ~1);
644 tcg_gen_shri_i64(t0, t, 32);
645 tcg_gen_trunc_i64_i32(t1, t0);
646 gen_store_fpr32(t1, reg | 1);
647 tcg_temp_free_i32(t1);
648 tcg_temp_free_i64(t0);
652 static inline int get_fp_bit (int cc)
654 if (cc)
655 return 24 + cc;
656 else
657 return 23;
660 #define FOP_CONDS(type, fmt, bits) \
661 static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
662 TCGv_i##bits b, int cc) \
664 switch (n) { \
665 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
666 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
667 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
668 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
669 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
670 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
671 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
672 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
673 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
674 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
675 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
676 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
677 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
678 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
679 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
680 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
681 default: abort(); \
685 FOP_CONDS(, d, 64)
686 FOP_CONDS(abs, d, 64)
687 FOP_CONDS(, s, 32)
688 FOP_CONDS(abs, s, 32)
689 FOP_CONDS(, ps, 64)
690 FOP_CONDS(abs, ps, 64)
691 #undef FOP_CONDS
693 /* Tests */
694 #define OP_COND(name, cond) \
695 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, TCGv t1) \
697 int l1 = gen_new_label(); \
698 int l2 = gen_new_label(); \
700 tcg_gen_brcond_tl(cond, t0, t1, l1); \
701 tcg_gen_movi_tl(ret, 0); \
702 tcg_gen_br(l2); \
703 gen_set_label(l1); \
704 tcg_gen_movi_tl(ret, 1); \
705 gen_set_label(l2); \
707 OP_COND(eq, TCG_COND_EQ);
708 OP_COND(ne, TCG_COND_NE);
709 OP_COND(ge, TCG_COND_GE);
710 OP_COND(geu, TCG_COND_GEU);
711 OP_COND(lt, TCG_COND_LT);
712 OP_COND(ltu, TCG_COND_LTU);
713 #undef OP_COND
715 #define OP_CONDI(name, cond) \
716 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, target_ulong val) \
718 int l1 = gen_new_label(); \
719 int l2 = gen_new_label(); \
721 tcg_gen_brcondi_tl(cond, t0, val, l1); \
722 tcg_gen_movi_tl(ret, 0); \
723 tcg_gen_br(l2); \
724 gen_set_label(l1); \
725 tcg_gen_movi_tl(ret, 1); \
726 gen_set_label(l2); \
728 OP_CONDI(lti, TCG_COND_LT);
729 OP_CONDI(ltiu, TCG_COND_LTU);
730 #undef OP_CONDI
732 #define OP_CONDZ(name, cond) \
733 static inline void glue(gen_op_, name) (TCGv ret, TCGv t0) \
735 int l1 = gen_new_label(); \
736 int l2 = gen_new_label(); \
738 tcg_gen_brcondi_tl(cond, t0, 0, l1); \
739 tcg_gen_movi_tl(ret, 0); \
740 tcg_gen_br(l2); \
741 gen_set_label(l1); \
742 tcg_gen_movi_tl(ret, 1); \
743 gen_set_label(l2); \
745 OP_CONDZ(gez, TCG_COND_GE);
746 OP_CONDZ(gtz, TCG_COND_GT);
747 OP_CONDZ(lez, TCG_COND_LE);
748 OP_CONDZ(ltz, TCG_COND_LT);
749 #undef OP_CONDZ
751 static inline void gen_save_pc(target_ulong pc)
753 tcg_gen_movi_tl(cpu_PC, pc);
756 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
758 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
759 if (do_save_pc && ctx->pc != ctx->saved_pc) {
760 gen_save_pc(ctx->pc);
761 ctx->saved_pc = ctx->pc;
763 if (ctx->hflags != ctx->saved_hflags) {
764 tcg_gen_movi_i32(hflags, ctx->hflags);
765 ctx->saved_hflags = ctx->hflags;
766 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
767 case MIPS_HFLAG_BR:
768 break;
769 case MIPS_HFLAG_BC:
770 case MIPS_HFLAG_BL:
771 case MIPS_HFLAG_B:
772 tcg_gen_movi_tl(btarget, ctx->btarget);
773 break;
778 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
780 ctx->saved_hflags = ctx->hflags;
781 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
782 case MIPS_HFLAG_BR:
783 break;
784 case MIPS_HFLAG_BC:
785 case MIPS_HFLAG_BL:
786 case MIPS_HFLAG_B:
787 ctx->btarget = env->btarget;
788 break;
792 static inline void
793 generate_exception_err (DisasContext *ctx, int excp, int err)
795 TCGv_i32 texcp = tcg_const_i32(excp);
796 TCGv_i32 terr = tcg_const_i32(err);
797 save_cpu_state(ctx, 1);
798 gen_helper_raise_exception_err(texcp, terr);
799 tcg_temp_free_i32(terr);
800 tcg_temp_free_i32(texcp);
803 static inline void
804 generate_exception (DisasContext *ctx, int excp)
806 save_cpu_state(ctx, 1);
807 gen_helper_0i(raise_exception, excp);
810 /* Addresses computation */
811 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
813 tcg_gen_add_tl(ret, arg0, arg1);
815 #if defined(TARGET_MIPS64)
816 /* For compatibility with 32-bit code, data reference in user mode
817 with Status_UX = 0 should be casted to 32-bit and sign extended.
818 See the MIPS64 PRA manual, section 4.10. */
819 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
820 !(ctx->hflags & MIPS_HFLAG_UX)) {
821 tcg_gen_ext32s_i64(ret, ret);
823 #endif
826 static inline void check_cp0_enabled(DisasContext *ctx)
828 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
829 generate_exception_err(ctx, EXCP_CpU, 1);
832 static inline void check_cp1_enabled(DisasContext *ctx)
834 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
835 generate_exception_err(ctx, EXCP_CpU, 1);
838 /* Verify that the processor is running with COP1X instructions enabled.
839 This is associated with the nabla symbol in the MIPS32 and MIPS64
840 opcode tables. */
842 static inline void check_cop1x(DisasContext *ctx)
844 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
845 generate_exception(ctx, EXCP_RI);
848 /* Verify that the processor is running with 64-bit floating-point
849 operations enabled. */
851 static inline void check_cp1_64bitmode(DisasContext *ctx)
853 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
854 generate_exception(ctx, EXCP_RI);
858 * Verify if floating point register is valid; an operation is not defined
859 * if bit 0 of any register specification is set and the FR bit in the
860 * Status register equals zero, since the register numbers specify an
861 * even-odd pair of adjacent coprocessor general registers. When the FR bit
862 * in the Status register equals one, both even and odd register numbers
863 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
865 * Multiple 64 bit wide registers can be checked by calling
866 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
868 static inline void check_cp1_registers(DisasContext *ctx, int regs)
870 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
871 generate_exception(ctx, EXCP_RI);
874 /* This code generates a "reserved instruction" exception if the
875 CPU does not support the instruction set corresponding to flags. */
876 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
878 if (unlikely(!(env->insn_flags & flags)))
879 generate_exception(ctx, EXCP_RI);
882 /* This code generates a "reserved instruction" exception if 64-bit
883 instructions are not enabled. */
884 static inline void check_mips_64(DisasContext *ctx)
886 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
887 generate_exception(ctx, EXCP_RI);
890 /* load/store instructions. */
891 #define OP_LD(insn,fname) \
892 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
894 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
896 OP_LD(lb,ld8s);
897 OP_LD(lbu,ld8u);
898 OP_LD(lh,ld16s);
899 OP_LD(lhu,ld16u);
900 OP_LD(lw,ld32s);
901 #if defined(TARGET_MIPS64)
902 OP_LD(lwu,ld32u);
903 OP_LD(ld,ld64);
904 #endif
905 #undef OP_LD
907 #define OP_ST(insn,fname) \
908 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
910 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
912 OP_ST(sb,st8);
913 OP_ST(sh,st16);
914 OP_ST(sw,st32);
915 #if defined(TARGET_MIPS64)
916 OP_ST(sd,st64);
917 #endif
918 #undef OP_ST
920 #ifdef CONFIG_USER_ONLY
921 #define OP_LD_ATOMIC(insn,fname) \
922 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
924 TCGv t0 = tcg_temp_new(); \
925 tcg_gen_mov_tl(t0, arg1); \
926 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
927 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
928 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
929 tcg_temp_free(t0); \
931 #else
932 #define OP_LD_ATOMIC(insn,fname) \
933 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
935 gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
937 #endif
938 OP_LD_ATOMIC(ll,ld32s);
939 #if defined(TARGET_MIPS64)
940 OP_LD_ATOMIC(lld,ld64);
941 #endif
942 #undef OP_LD_ATOMIC
944 #ifdef CONFIG_USER_ONLY
945 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
946 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
948 TCGv t0 = tcg_temp_new(); \
949 int l1 = gen_new_label(); \
950 int l2 = gen_new_label(); \
952 tcg_gen_andi_tl(t0, arg2, almask); \
953 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
954 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
955 generate_exception(ctx, EXCP_AdES); \
956 gen_set_label(l1); \
957 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
958 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
959 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
960 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
961 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
962 gen_helper_0i(raise_exception, EXCP_SC); \
963 gen_set_label(l2); \
964 tcg_gen_movi_tl(t0, 0); \
965 gen_store_gpr(t0, rt); \
966 tcg_temp_free(t0); \
968 #else
969 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
970 static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
972 TCGv t0 = tcg_temp_new(); \
973 gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
974 gen_store_gpr(t0, rt); \
975 tcg_temp_free(t0); \
977 #endif
978 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
979 #if defined(TARGET_MIPS64)
980 OP_ST_ATOMIC(scd,st64,ld64,0x7);
981 #endif
982 #undef OP_ST_ATOMIC
984 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
985 int base, int16_t offset)
987 if (base == 0) {
988 tcg_gen_movi_tl(addr, offset);
989 } else if (offset == 0) {
990 gen_load_gpr(addr, base);
991 } else {
992 tcg_gen_movi_tl(addr, offset);
993 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
997 /* Load and store */
998 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
999 int base, int16_t offset)
1001 const char *opn = "ldst";
1002 TCGv t0 = tcg_temp_new();
1003 TCGv t1 = tcg_temp_new();
1005 gen_base_offset_addr(ctx, t0, base, offset);
1006 /* Don't do NOP if destination is zero: we must perform the actual
1007 memory access. */
1008 switch (opc) {
1009 #if defined(TARGET_MIPS64)
1010 case OPC_LWU:
1011 save_cpu_state(ctx, 0);
1012 op_ldst_lwu(t0, t0, ctx);
1013 gen_store_gpr(t0, rt);
1014 opn = "lwu";
1015 break;
1016 case OPC_LD:
1017 save_cpu_state(ctx, 0);
1018 op_ldst_ld(t0, t0, ctx);
1019 gen_store_gpr(t0, rt);
1020 opn = "ld";
1021 break;
1022 case OPC_LLD:
1023 save_cpu_state(ctx, 0);
1024 op_ldst_lld(t0, t0, ctx);
1025 gen_store_gpr(t0, rt);
1026 opn = "lld";
1027 break;
1028 case OPC_SD:
1029 save_cpu_state(ctx, 0);
1030 gen_load_gpr(t1, rt);
1031 op_ldst_sd(t1, t0, ctx);
1032 opn = "sd";
1033 break;
1034 case OPC_LDL:
1035 save_cpu_state(ctx, 1);
1036 gen_load_gpr(t1, rt);
1037 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1038 gen_store_gpr(t1, rt);
1039 opn = "ldl";
1040 break;
1041 case OPC_SDL:
1042 save_cpu_state(ctx, 1);
1043 gen_load_gpr(t1, rt);
1044 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1045 opn = "sdl";
1046 break;
1047 case OPC_LDR:
1048 save_cpu_state(ctx, 1);
1049 gen_load_gpr(t1, rt);
1050 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1051 gen_store_gpr(t1, rt);
1052 opn = "ldr";
1053 break;
1054 case OPC_SDR:
1055 save_cpu_state(ctx, 1);
1056 gen_load_gpr(t1, rt);
1057 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1058 opn = "sdr";
1059 break;
1060 #endif
1061 case OPC_LW:
1062 save_cpu_state(ctx, 0);
1063 op_ldst_lw(t0, t0, ctx);
1064 gen_store_gpr(t0, rt);
1065 opn = "lw";
1066 break;
1067 case OPC_SW:
1068 save_cpu_state(ctx, 0);
1069 gen_load_gpr(t1, rt);
1070 op_ldst_sw(t1, t0, ctx);
1071 opn = "sw";
1072 break;
1073 case OPC_LH:
1074 save_cpu_state(ctx, 0);
1075 op_ldst_lh(t0, t0, ctx);
1076 gen_store_gpr(t0, rt);
1077 opn = "lh";
1078 break;
1079 case OPC_SH:
1080 save_cpu_state(ctx, 0);
1081 gen_load_gpr(t1, rt);
1082 op_ldst_sh(t1, t0, ctx);
1083 opn = "sh";
1084 break;
1085 case OPC_LHU:
1086 save_cpu_state(ctx, 0);
1087 op_ldst_lhu(t0, t0, ctx);
1088 gen_store_gpr(t0, rt);
1089 opn = "lhu";
1090 break;
1091 case OPC_LB:
1092 save_cpu_state(ctx, 0);
1093 op_ldst_lb(t0, t0, ctx);
1094 gen_store_gpr(t0, rt);
1095 opn = "lb";
1096 break;
1097 case OPC_SB:
1098 save_cpu_state(ctx, 0);
1099 gen_load_gpr(t1, rt);
1100 op_ldst_sb(t1, t0, ctx);
1101 opn = "sb";
1102 break;
1103 case OPC_LBU:
1104 save_cpu_state(ctx, 0);
1105 op_ldst_lbu(t0, t0, ctx);
1106 gen_store_gpr(t0, rt);
1107 opn = "lbu";
1108 break;
1109 case OPC_LWL:
1110 save_cpu_state(ctx, 1);
1111 gen_load_gpr(t1, rt);
1112 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1113 gen_store_gpr(t1, rt);
1114 opn = "lwl";
1115 break;
1116 case OPC_SWL:
1117 save_cpu_state(ctx, 1);
1118 gen_load_gpr(t1, rt);
1119 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1120 opn = "swr";
1121 break;
1122 case OPC_LWR:
1123 save_cpu_state(ctx, 1);
1124 gen_load_gpr(t1, rt);
1125 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1126 gen_store_gpr(t1, rt);
1127 opn = "lwr";
1128 break;
1129 case OPC_SWR:
1130 save_cpu_state(ctx, 1);
1131 gen_load_gpr(t1, rt);
1132 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1133 opn = "swr";
1134 break;
1135 case OPC_LL:
1136 save_cpu_state(ctx, 1);
1137 op_ldst_ll(t0, t0, ctx);
1138 gen_store_gpr(t0, rt);
1139 opn = "ll";
1140 break;
1142 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1143 tcg_temp_free(t0);
1144 tcg_temp_free(t1);
1147 /* Store conditional */
1148 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1149 int base, int16_t offset)
1151 const char *opn = "st_cond";
1152 TCGv t0, t1;
1154 t0 = tcg_temp_local_new();
1156 gen_base_offset_addr(ctx, t0, base, offset);
1157 /* Don't do NOP if destination is zero: we must perform the actual
1158 memory access. */
1160 t1 = tcg_temp_local_new();
1161 gen_load_gpr(t1, rt);
1162 switch (opc) {
1163 #if defined(TARGET_MIPS64)
1164 case OPC_SCD:
1165 save_cpu_state(ctx, 0);
1166 op_ldst_scd(t1, t0, rt, ctx);
1167 opn = "scd";
1168 break;
1169 #endif
1170 case OPC_SC:
1171 save_cpu_state(ctx, 1);
1172 op_ldst_sc(t1, t0, rt, ctx);
1173 opn = "sc";
1174 break;
1176 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1177 tcg_temp_free(t1);
1178 tcg_temp_free(t0);
1181 /* Load and store */
1182 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1183 int base, int16_t offset)
1185 const char *opn = "flt_ldst";
1186 TCGv t0 = tcg_temp_new();
1188 gen_base_offset_addr(ctx, t0, base, offset);
1189 /* Don't do NOP if destination is zero: we must perform the actual
1190 memory access. */
1191 switch (opc) {
1192 case OPC_LWC1:
1194 TCGv_i32 fp0 = tcg_temp_new_i32();
1196 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1197 tcg_gen_trunc_tl_i32(fp0, t0);
1198 gen_store_fpr32(fp0, ft);
1199 tcg_temp_free_i32(fp0);
1201 opn = "lwc1";
1202 break;
1203 case OPC_SWC1:
1205 TCGv_i32 fp0 = tcg_temp_new_i32();
1206 TCGv t1 = tcg_temp_new();
1208 gen_load_fpr32(fp0, ft);
1209 tcg_gen_extu_i32_tl(t1, fp0);
1210 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1211 tcg_temp_free(t1);
1212 tcg_temp_free_i32(fp0);
1214 opn = "swc1";
1215 break;
1216 case OPC_LDC1:
1218 TCGv_i64 fp0 = tcg_temp_new_i64();
1220 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1221 gen_store_fpr64(ctx, fp0, ft);
1222 tcg_temp_free_i64(fp0);
1224 opn = "ldc1";
1225 break;
1226 case OPC_SDC1:
1228 TCGv_i64 fp0 = tcg_temp_new_i64();
1230 gen_load_fpr64(ctx, fp0, ft);
1231 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1232 tcg_temp_free_i64(fp0);
1234 opn = "sdc1";
1235 break;
1236 default:
1237 MIPS_INVAL(opn);
1238 generate_exception(ctx, EXCP_RI);
1239 goto out;
1241 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1242 out:
1243 tcg_temp_free(t0);
1246 /* Arithmetic with immediate operand */
1247 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1248 int rt, int rs, int16_t imm)
1250 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1251 const char *opn = "imm arith";
1253 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1254 /* If no destination, treat it as a NOP.
1255 For addi, we must generate the overflow exception when needed. */
1256 MIPS_DEBUG("NOP");
1257 return;
1259 switch (opc) {
1260 case OPC_ADDI:
1262 TCGv t0 = tcg_temp_local_new();
1263 TCGv t1 = tcg_temp_new();
1264 TCGv t2 = tcg_temp_new();
1265 int l1 = gen_new_label();
1267 gen_load_gpr(t1, rs);
1268 tcg_gen_addi_tl(t0, t1, uimm);
1269 tcg_gen_ext32s_tl(t0, t0);
1271 tcg_gen_xori_tl(t1, t1, ~uimm);
1272 tcg_gen_xori_tl(t2, t0, uimm);
1273 tcg_gen_and_tl(t1, t1, t2);
1274 tcg_temp_free(t2);
1275 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1276 tcg_temp_free(t1);
1277 /* operands of same sign, result different sign */
1278 generate_exception(ctx, EXCP_OVERFLOW);
1279 gen_set_label(l1);
1280 tcg_gen_ext32s_tl(t0, t0);
1281 gen_store_gpr(t0, rt);
1282 tcg_temp_free(t0);
1284 opn = "addi";
1285 break;
1286 case OPC_ADDIU:
1287 if (rs != 0) {
1288 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1289 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1290 } else {
1291 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1293 opn = "addiu";
1294 break;
1295 #if defined(TARGET_MIPS64)
1296 case OPC_DADDI:
1298 TCGv t0 = tcg_temp_local_new();
1299 TCGv t1 = tcg_temp_new();
1300 TCGv t2 = tcg_temp_new();
1301 int l1 = gen_new_label();
1303 gen_load_gpr(t1, rs);
1304 tcg_gen_addi_tl(t0, t1, uimm);
1306 tcg_gen_xori_tl(t1, t1, ~uimm);
1307 tcg_gen_xori_tl(t2, t0, uimm);
1308 tcg_gen_and_tl(t1, t1, t2);
1309 tcg_temp_free(t2);
1310 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1311 tcg_temp_free(t1);
1312 /* operands of same sign, result different sign */
1313 generate_exception(ctx, EXCP_OVERFLOW);
1314 gen_set_label(l1);
1315 gen_store_gpr(t0, rt);
1316 tcg_temp_free(t0);
1318 opn = "daddi";
1319 break;
1320 case OPC_DADDIU:
1321 if (rs != 0) {
1322 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1323 } else {
1324 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1326 opn = "daddiu";
1327 break;
1328 #endif
1330 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1333 /* Logic with immediate operand */
1334 static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1336 target_ulong uimm;
1337 const char *opn = "imm logic";
1339 if (rt == 0) {
1340 /* If no destination, treat it as a NOP. */
1341 MIPS_DEBUG("NOP");
1342 return;
1344 uimm = (uint16_t)imm;
1345 switch (opc) {
1346 case OPC_ANDI:
1347 if (likely(rs != 0))
1348 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1349 else
1350 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1351 opn = "andi";
1352 break;
1353 case OPC_ORI:
1354 if (rs != 0)
1355 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1356 else
1357 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1358 opn = "ori";
1359 break;
1360 case OPC_XORI:
1361 if (likely(rs != 0))
1362 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1363 else
1364 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1365 opn = "xori";
1366 break;
1367 case OPC_LUI:
1368 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1369 opn = "lui";
1370 break;
1372 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1375 /* Set on less than with immediate operand */
1376 static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1378 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1379 const char *opn = "imm arith";
1380 TCGv t0;
1382 if (rt == 0) {
1383 /* If no destination, treat it as a NOP. */
1384 MIPS_DEBUG("NOP");
1385 return;
1387 t0 = tcg_temp_new();
1388 gen_load_gpr(t0, rs);
1389 switch (opc) {
1390 case OPC_SLTI:
1391 gen_op_lti(cpu_gpr[rt], t0, uimm);
1392 opn = "slti";
1393 break;
1394 case OPC_SLTIU:
1395 gen_op_ltiu(cpu_gpr[rt], t0, uimm);
1396 opn = "sltiu";
1397 break;
1399 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1400 tcg_temp_free(t0);
1403 /* Shifts with immediate operand */
1404 static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1405 int rt, int rs, int16_t imm)
1407 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1408 const char *opn = "imm shift";
1409 TCGv t0;
1411 if (rt == 0) {
1412 /* If no destination, treat it as a NOP. */
1413 MIPS_DEBUG("NOP");
1414 return;
1417 t0 = tcg_temp_new();
1418 gen_load_gpr(t0, rs);
1419 switch (opc) {
1420 case OPC_SLL:
1421 tcg_gen_shli_tl(t0, t0, uimm);
1422 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1423 opn = "sll";
1424 break;
1425 case OPC_SRA:
1426 tcg_gen_ext32s_tl(t0, t0);
1427 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1428 opn = "sra";
1429 break;
1430 case OPC_SRL:
1431 if (uimm != 0) {
1432 tcg_gen_ext32u_tl(t0, t0);
1433 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1434 } else {
1435 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1437 opn = "srl";
1438 break;
1439 case OPC_ROTR:
1440 if (uimm != 0) {
1441 TCGv_i32 t1 = tcg_temp_new_i32();
1443 tcg_gen_trunc_tl_i32(t1, t0);
1444 tcg_gen_rotri_i32(t1, t1, uimm);
1445 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1446 tcg_temp_free_i32(t1);
1448 opn = "rotr";
1449 break;
1450 #if defined(TARGET_MIPS64)
1451 case OPC_DSLL:
1452 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1453 opn = "dsll";
1454 break;
1455 case OPC_DSRA:
1456 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1457 opn = "dsra";
1458 break;
1459 case OPC_DSRL:
1460 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1461 opn = "dsrl";
1462 break;
1463 case OPC_DROTR:
1464 if (uimm != 0) {
1465 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1467 opn = "drotr";
1468 break;
1469 case OPC_DSLL32:
1470 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1471 opn = "dsll32";
1472 break;
1473 case OPC_DSRA32:
1474 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1475 opn = "dsra32";
1476 break;
1477 case OPC_DSRL32:
1478 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1479 opn = "dsrl32";
1480 break;
1481 case OPC_DROTR32:
1482 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1483 opn = "drotr32";
1484 break;
1485 #endif
1487 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1488 tcg_temp_free(t0);
1491 /* Arithmetic */
1492 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1493 int rd, int rs, int rt)
1495 const char *opn = "arith";
1497 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1498 && opc != OPC_DADD && opc != OPC_DSUB) {
1499 /* If no destination, treat it as a NOP.
1500 For add & sub, we must generate the overflow exception when needed. */
1501 MIPS_DEBUG("NOP");
1502 return;
1505 switch (opc) {
1506 case OPC_ADD:
1508 TCGv t0 = tcg_temp_local_new();
1509 TCGv t1 = tcg_temp_new();
1510 TCGv t2 = tcg_temp_new();
1511 int l1 = gen_new_label();
1513 gen_load_gpr(t1, rs);
1514 gen_load_gpr(t2, rt);
1515 tcg_gen_add_tl(t0, t1, t2);
1516 tcg_gen_ext32s_tl(t0, t0);
1517 tcg_gen_xor_tl(t1, t1, t2);
1518 tcg_gen_not_tl(t1, t1);
1519 tcg_gen_xor_tl(t2, t0, t2);
1520 tcg_gen_and_tl(t1, t1, t2);
1521 tcg_temp_free(t2);
1522 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1523 tcg_temp_free(t1);
1524 /* operands of same sign, result different sign */
1525 generate_exception(ctx, EXCP_OVERFLOW);
1526 gen_set_label(l1);
1527 gen_store_gpr(t0, rd);
1528 tcg_temp_free(t0);
1530 opn = "add";
1531 break;
1532 case OPC_ADDU:
1533 if (rs != 0 && rt != 0) {
1534 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1535 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1536 } else if (rs == 0 && rt != 0) {
1537 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1538 } else if (rs != 0 && rt == 0) {
1539 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1540 } else {
1541 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1543 opn = "addu";
1544 break;
1545 case OPC_SUB:
1547 TCGv t0 = tcg_temp_local_new();
1548 TCGv t1 = tcg_temp_new();
1549 TCGv t2 = tcg_temp_new();
1550 int l1 = gen_new_label();
1552 gen_load_gpr(t1, rs);
1553 gen_load_gpr(t2, rt);
1554 tcg_gen_sub_tl(t0, t1, t2);
1555 tcg_gen_ext32s_tl(t0, t0);
1556 tcg_gen_xor_tl(t2, t1, t2);
1557 tcg_gen_xor_tl(t1, t0, t1);
1558 tcg_gen_and_tl(t1, t1, t2);
1559 tcg_temp_free(t2);
1560 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1561 tcg_temp_free(t1);
1562 /* operands of different sign, first operand and result different sign */
1563 generate_exception(ctx, EXCP_OVERFLOW);
1564 gen_set_label(l1);
1565 gen_store_gpr(t0, rd);
1566 tcg_temp_free(t0);
1568 opn = "sub";
1569 break;
1570 case OPC_SUBU:
1571 if (rs != 0 && rt != 0) {
1572 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1573 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1574 } else if (rs == 0 && rt != 0) {
1575 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1576 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1577 } else if (rs != 0 && rt == 0) {
1578 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1579 } else {
1580 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1582 opn = "subu";
1583 break;
1584 #if defined(TARGET_MIPS64)
1585 case OPC_DADD:
1587 TCGv t0 = tcg_temp_local_new();
1588 TCGv t1 = tcg_temp_new();
1589 TCGv t2 = tcg_temp_new();
1590 int l1 = gen_new_label();
1592 gen_load_gpr(t1, rs);
1593 gen_load_gpr(t2, rt);
1594 tcg_gen_add_tl(t0, t1, t2);
1595 tcg_gen_xor_tl(t1, t1, t2);
1596 tcg_gen_not_tl(t1, t1);
1597 tcg_gen_xor_tl(t2, t0, t2);
1598 tcg_gen_and_tl(t1, t1, t2);
1599 tcg_temp_free(t2);
1600 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1601 tcg_temp_free(t1);
1602 /* operands of same sign, result different sign */
1603 generate_exception(ctx, EXCP_OVERFLOW);
1604 gen_set_label(l1);
1605 gen_store_gpr(t0, rd);
1606 tcg_temp_free(t0);
1608 opn = "dadd";
1609 break;
1610 case OPC_DADDU:
1611 if (rs != 0 && rt != 0) {
1612 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1613 } else if (rs == 0 && rt != 0) {
1614 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1615 } else if (rs != 0 && rt == 0) {
1616 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1617 } else {
1618 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1620 opn = "daddu";
1621 break;
1622 case OPC_DSUB:
1624 TCGv t0 = tcg_temp_local_new();
1625 TCGv t1 = tcg_temp_new();
1626 TCGv t2 = tcg_temp_new();
1627 int l1 = gen_new_label();
1629 gen_load_gpr(t1, rs);
1630 gen_load_gpr(t2, rt);
1631 tcg_gen_sub_tl(t0, t1, t2);
1632 tcg_gen_xor_tl(t2, t1, t2);
1633 tcg_gen_xor_tl(t1, t0, t1);
1634 tcg_gen_and_tl(t1, t1, t2);
1635 tcg_temp_free(t2);
1636 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1637 tcg_temp_free(t1);
1638 /* operands of different sign, first operand and result different sign */
1639 generate_exception(ctx, EXCP_OVERFLOW);
1640 gen_set_label(l1);
1641 gen_store_gpr(t0, rd);
1642 tcg_temp_free(t0);
1644 opn = "dsub";
1645 break;
1646 case OPC_DSUBU:
1647 if (rs != 0 && rt != 0) {
1648 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1649 } else if (rs == 0 && rt != 0) {
1650 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1651 } else if (rs != 0 && rt == 0) {
1652 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1653 } else {
1654 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1656 opn = "dsubu";
1657 break;
1658 #endif
1659 case OPC_MUL:
1660 if (likely(rs != 0 && rt != 0)) {
1661 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1662 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1663 } else {
1664 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1666 opn = "mul";
1667 break;
1669 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1672 /* Conditional move */
1673 static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1675 const char *opn = "cond move";
1676 int l1;
1678 if (rd == 0) {
1679 /* If no destination, treat it as a NOP.
1680 For add & sub, we must generate the overflow exception when needed. */
1681 MIPS_DEBUG("NOP");
1682 return;
1685 l1 = gen_new_label();
1686 switch (opc) {
1687 case OPC_MOVN:
1688 if (likely(rt != 0))
1689 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1690 else
1691 tcg_gen_br(l1);
1692 opn = "movn";
1693 break;
1694 case OPC_MOVZ:
1695 if (likely(rt != 0))
1696 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1697 opn = "movz";
1698 break;
1700 if (rs != 0)
1701 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1702 else
1703 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1704 gen_set_label(l1);
1706 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1709 /* Logic */
1710 static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1712 const char *opn = "logic";
1714 if (rd == 0) {
1715 /* If no destination, treat it as a NOP. */
1716 MIPS_DEBUG("NOP");
1717 return;
1720 switch (opc) {
1721 case OPC_AND:
1722 if (likely(rs != 0 && rt != 0)) {
1723 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1724 } else {
1725 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1727 opn = "and";
1728 break;
1729 case OPC_NOR:
1730 if (rs != 0 && rt != 0) {
1731 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1732 } else if (rs == 0 && rt != 0) {
1733 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1734 } else if (rs != 0 && rt == 0) {
1735 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1736 } else {
1737 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1739 opn = "nor";
1740 break;
1741 case OPC_OR:
1742 if (likely(rs != 0 && rt != 0)) {
1743 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1744 } else if (rs == 0 && rt != 0) {
1745 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1746 } else if (rs != 0 && rt == 0) {
1747 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1748 } else {
1749 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1751 opn = "or";
1752 break;
1753 case OPC_XOR:
1754 if (likely(rs != 0 && rt != 0)) {
1755 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1756 } else if (rs == 0 && rt != 0) {
1757 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1758 } else if (rs != 0 && rt == 0) {
1759 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1760 } else {
1761 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1763 opn = "xor";
1764 break;
1766 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1769 /* Set on lower than */
1770 static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1772 const char *opn = "slt";
1773 TCGv t0, t1;
1775 if (rd == 0) {
1776 /* If no destination, treat it as a NOP. */
1777 MIPS_DEBUG("NOP");
1778 return;
1781 t0 = tcg_temp_new();
1782 t1 = tcg_temp_new();
1783 gen_load_gpr(t0, rs);
1784 gen_load_gpr(t1, rt);
1785 switch (opc) {
1786 case OPC_SLT:
1787 gen_op_lt(cpu_gpr[rd], t0, t1);
1788 opn = "slt";
1789 break;
1790 case OPC_SLTU:
1791 gen_op_ltu(cpu_gpr[rd], t0, t1);
1792 opn = "sltu";
1793 break;
1795 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1796 tcg_temp_free(t0);
1797 tcg_temp_free(t1);
1800 /* Shifts */
1801 static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1802 int rd, int rs, int rt)
1804 const char *opn = "shifts";
1805 TCGv t0, t1;
1807 if (rd == 0) {
1808 /* If no destination, treat it as a NOP.
1809 For add & sub, we must generate the overflow exception when needed. */
1810 MIPS_DEBUG("NOP");
1811 return;
1814 t0 = tcg_temp_new();
1815 t1 = tcg_temp_new();
1816 gen_load_gpr(t0, rs);
1817 gen_load_gpr(t1, rt);
1818 switch (opc) {
1819 case OPC_SLLV:
1820 tcg_gen_andi_tl(t0, t0, 0x1f);
1821 tcg_gen_shl_tl(t0, t1, t0);
1822 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1823 opn = "sllv";
1824 break;
1825 case OPC_SRAV:
1826 tcg_gen_ext32s_tl(t1, t1);
1827 tcg_gen_andi_tl(t0, t0, 0x1f);
1828 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1829 opn = "srav";
1830 break;
1831 case OPC_SRLV:
1832 tcg_gen_ext32u_tl(t1, t1);
1833 tcg_gen_andi_tl(t0, t0, 0x1f);
1834 tcg_gen_shr_tl(t0, t1, t0);
1835 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1836 opn = "srlv";
1837 break;
1838 case OPC_ROTRV:
1840 TCGv_i32 t2 = tcg_temp_new_i32();
1841 TCGv_i32 t3 = tcg_temp_new_i32();
1843 tcg_gen_trunc_tl_i32(t2, t0);
1844 tcg_gen_trunc_tl_i32(t3, t1);
1845 tcg_gen_andi_i32(t2, t2, 0x1f);
1846 tcg_gen_rotr_i32(t2, t3, t2);
1847 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1848 tcg_temp_free_i32(t2);
1849 tcg_temp_free_i32(t3);
1850 opn = "rotrv";
1852 break;
1853 #if defined(TARGET_MIPS64)
1854 case OPC_DSLLV:
1855 tcg_gen_andi_tl(t0, t0, 0x3f);
1856 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1857 opn = "dsllv";
1858 break;
1859 case OPC_DSRAV:
1860 tcg_gen_andi_tl(t0, t0, 0x3f);
1861 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1862 opn = "dsrav";
1863 break;
1864 case OPC_DSRLV:
1865 tcg_gen_andi_tl(t0, t0, 0x3f);
1866 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1867 opn = "dsrlv";
1868 break;
1869 case OPC_DROTRV:
1870 tcg_gen_andi_tl(t0, t0, 0x3f);
1871 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1872 opn = "drotrv";
1873 break;
1874 #endif
1876 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1877 tcg_temp_free(t0);
1878 tcg_temp_free(t1);
1881 /* Arithmetic on HI/LO registers */
1882 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1884 const char *opn = "hilo";
1886 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1887 /* Treat as NOP. */
1888 MIPS_DEBUG("NOP");
1889 return;
1891 switch (opc) {
1892 case OPC_MFHI:
1893 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1894 opn = "mfhi";
1895 break;
1896 case OPC_MFLO:
1897 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1898 opn = "mflo";
1899 break;
1900 case OPC_MTHI:
1901 if (reg != 0)
1902 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1903 else
1904 tcg_gen_movi_tl(cpu_HI[0], 0);
1905 opn = "mthi";
1906 break;
1907 case OPC_MTLO:
1908 if (reg != 0)
1909 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1910 else
1911 tcg_gen_movi_tl(cpu_LO[0], 0);
1912 opn = "mtlo";
1913 break;
1915 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1918 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1919 int rs, int rt)
1921 const char *opn = "mul/div";
1922 TCGv t0, t1;
1924 switch (opc) {
1925 case OPC_DIV:
1926 case OPC_DIVU:
1927 #if defined(TARGET_MIPS64)
1928 case OPC_DDIV:
1929 case OPC_DDIVU:
1930 #endif
1931 t0 = tcg_temp_local_new();
1932 t1 = tcg_temp_local_new();
1933 break;
1934 default:
1935 t0 = tcg_temp_new();
1936 t1 = tcg_temp_new();
1937 break;
1940 gen_load_gpr(t0, rs);
1941 gen_load_gpr(t1, rt);
1942 switch (opc) {
1943 case OPC_DIV:
1945 int l1 = gen_new_label();
1946 int l2 = gen_new_label();
1948 tcg_gen_ext32s_tl(t0, t0);
1949 tcg_gen_ext32s_tl(t1, t1);
1950 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1951 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
1952 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
1954 tcg_gen_mov_tl(cpu_LO[0], t0);
1955 tcg_gen_movi_tl(cpu_HI[0], 0);
1956 tcg_gen_br(l1);
1957 gen_set_label(l2);
1958 tcg_gen_div_tl(cpu_LO[0], t0, t1);
1959 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
1960 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1961 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1962 gen_set_label(l1);
1964 opn = "div";
1965 break;
1966 case OPC_DIVU:
1968 int l1 = gen_new_label();
1970 tcg_gen_ext32u_tl(t0, t0);
1971 tcg_gen_ext32u_tl(t1, t1);
1972 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1973 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
1974 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
1975 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1976 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
1977 gen_set_label(l1);
1979 opn = "divu";
1980 break;
1981 case OPC_MULT:
1983 TCGv_i64 t2 = tcg_temp_new_i64();
1984 TCGv_i64 t3 = tcg_temp_new_i64();
1986 tcg_gen_ext_tl_i64(t2, t0);
1987 tcg_gen_ext_tl_i64(t3, t1);
1988 tcg_gen_mul_i64(t2, t2, t3);
1989 tcg_temp_free_i64(t3);
1990 tcg_gen_trunc_i64_tl(t0, t2);
1991 tcg_gen_shri_i64(t2, t2, 32);
1992 tcg_gen_trunc_i64_tl(t1, t2);
1993 tcg_temp_free_i64(t2);
1994 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1995 tcg_gen_ext32s_tl(cpu_HI[0], t1);
1997 opn = "mult";
1998 break;
1999 case OPC_MULTU:
2001 TCGv_i64 t2 = tcg_temp_new_i64();
2002 TCGv_i64 t3 = tcg_temp_new_i64();
2004 tcg_gen_ext32u_tl(t0, t0);
2005 tcg_gen_ext32u_tl(t1, t1);
2006 tcg_gen_extu_tl_i64(t2, t0);
2007 tcg_gen_extu_tl_i64(t3, t1);
2008 tcg_gen_mul_i64(t2, t2, t3);
2009 tcg_temp_free_i64(t3);
2010 tcg_gen_trunc_i64_tl(t0, t2);
2011 tcg_gen_shri_i64(t2, t2, 32);
2012 tcg_gen_trunc_i64_tl(t1, t2);
2013 tcg_temp_free_i64(t2);
2014 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2015 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2017 opn = "multu";
2018 break;
2019 #if defined(TARGET_MIPS64)
2020 case OPC_DDIV:
2022 int l1 = gen_new_label();
2023 int l2 = gen_new_label();
2025 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2026 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2027 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2028 tcg_gen_mov_tl(cpu_LO[0], t0);
2029 tcg_gen_movi_tl(cpu_HI[0], 0);
2030 tcg_gen_br(l1);
2031 gen_set_label(l2);
2032 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2033 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2034 gen_set_label(l1);
2036 opn = "ddiv";
2037 break;
2038 case OPC_DDIVU:
2040 int l1 = gen_new_label();
2042 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2043 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2044 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2045 gen_set_label(l1);
2047 opn = "ddivu";
2048 break;
2049 case OPC_DMULT:
2050 gen_helper_dmult(t0, t1);
2051 opn = "dmult";
2052 break;
2053 case OPC_DMULTU:
2054 gen_helper_dmultu(t0, t1);
2055 opn = "dmultu";
2056 break;
2057 #endif
2058 case OPC_MADD:
2060 TCGv_i64 t2 = tcg_temp_new_i64();
2061 TCGv_i64 t3 = tcg_temp_new_i64();
2063 tcg_gen_ext_tl_i64(t2, t0);
2064 tcg_gen_ext_tl_i64(t3, t1);
2065 tcg_gen_mul_i64(t2, t2, t3);
2066 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2067 tcg_gen_add_i64(t2, t2, t3);
2068 tcg_temp_free_i64(t3);
2069 tcg_gen_trunc_i64_tl(t0, t2);
2070 tcg_gen_shri_i64(t2, t2, 32);
2071 tcg_gen_trunc_i64_tl(t1, t2);
2072 tcg_temp_free_i64(t2);
2073 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2074 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2076 opn = "madd";
2077 break;
2078 case OPC_MADDU:
2080 TCGv_i64 t2 = tcg_temp_new_i64();
2081 TCGv_i64 t3 = tcg_temp_new_i64();
2083 tcg_gen_ext32u_tl(t0, t0);
2084 tcg_gen_ext32u_tl(t1, t1);
2085 tcg_gen_extu_tl_i64(t2, t0);
2086 tcg_gen_extu_tl_i64(t3, t1);
2087 tcg_gen_mul_i64(t2, t2, t3);
2088 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2089 tcg_gen_add_i64(t2, t2, t3);
2090 tcg_temp_free_i64(t3);
2091 tcg_gen_trunc_i64_tl(t0, t2);
2092 tcg_gen_shri_i64(t2, t2, 32);
2093 tcg_gen_trunc_i64_tl(t1, t2);
2094 tcg_temp_free_i64(t2);
2095 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2096 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2098 opn = "maddu";
2099 break;
2100 case OPC_MSUB:
2102 TCGv_i64 t2 = tcg_temp_new_i64();
2103 TCGv_i64 t3 = tcg_temp_new_i64();
2105 tcg_gen_ext_tl_i64(t2, t0);
2106 tcg_gen_ext_tl_i64(t3, t1);
2107 tcg_gen_mul_i64(t2, t2, t3);
2108 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2109 tcg_gen_sub_i64(t2, t3, t2);
2110 tcg_temp_free_i64(t3);
2111 tcg_gen_trunc_i64_tl(t0, t2);
2112 tcg_gen_shri_i64(t2, t2, 32);
2113 tcg_gen_trunc_i64_tl(t1, t2);
2114 tcg_temp_free_i64(t2);
2115 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2116 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2118 opn = "msub";
2119 break;
2120 case OPC_MSUBU:
2122 TCGv_i64 t2 = tcg_temp_new_i64();
2123 TCGv_i64 t3 = tcg_temp_new_i64();
2125 tcg_gen_ext32u_tl(t0, t0);
2126 tcg_gen_ext32u_tl(t1, t1);
2127 tcg_gen_extu_tl_i64(t2, t0);
2128 tcg_gen_extu_tl_i64(t3, t1);
2129 tcg_gen_mul_i64(t2, t2, t3);
2130 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2131 tcg_gen_sub_i64(t2, t3, t2);
2132 tcg_temp_free_i64(t3);
2133 tcg_gen_trunc_i64_tl(t0, t2);
2134 tcg_gen_shri_i64(t2, t2, 32);
2135 tcg_gen_trunc_i64_tl(t1, t2);
2136 tcg_temp_free_i64(t2);
2137 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2138 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2140 opn = "msubu";
2141 break;
2142 default:
2143 MIPS_INVAL(opn);
2144 generate_exception(ctx, EXCP_RI);
2145 goto out;
2147 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2148 out:
2149 tcg_temp_free(t0);
2150 tcg_temp_free(t1);
2153 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2154 int rd, int rs, int rt)
2156 const char *opn = "mul vr54xx";
2157 TCGv t0 = tcg_temp_new();
2158 TCGv t1 = tcg_temp_new();
2160 gen_load_gpr(t0, rs);
2161 gen_load_gpr(t1, rt);
2163 switch (opc) {
2164 case OPC_VR54XX_MULS:
2165 gen_helper_muls(t0, t0, t1);
2166 opn = "muls";
2167 break;
2168 case OPC_VR54XX_MULSU:
2169 gen_helper_mulsu(t0, t0, t1);
2170 opn = "mulsu";
2171 break;
2172 case OPC_VR54XX_MACC:
2173 gen_helper_macc(t0, t0, t1);
2174 opn = "macc";
2175 break;
2176 case OPC_VR54XX_MACCU:
2177 gen_helper_maccu(t0, t0, t1);
2178 opn = "maccu";
2179 break;
2180 case OPC_VR54XX_MSAC:
2181 gen_helper_msac(t0, t0, t1);
2182 opn = "msac";
2183 break;
2184 case OPC_VR54XX_MSACU:
2185 gen_helper_msacu(t0, t0, t1);
2186 opn = "msacu";
2187 break;
2188 case OPC_VR54XX_MULHI:
2189 gen_helper_mulhi(t0, t0, t1);
2190 opn = "mulhi";
2191 break;
2192 case OPC_VR54XX_MULHIU:
2193 gen_helper_mulhiu(t0, t0, t1);
2194 opn = "mulhiu";
2195 break;
2196 case OPC_VR54XX_MULSHI:
2197 gen_helper_mulshi(t0, t0, t1);
2198 opn = "mulshi";
2199 break;
2200 case OPC_VR54XX_MULSHIU:
2201 gen_helper_mulshiu(t0, t0, t1);
2202 opn = "mulshiu";
2203 break;
2204 case OPC_VR54XX_MACCHI:
2205 gen_helper_macchi(t0, t0, t1);
2206 opn = "macchi";
2207 break;
2208 case OPC_VR54XX_MACCHIU:
2209 gen_helper_macchiu(t0, t0, t1);
2210 opn = "macchiu";
2211 break;
2212 case OPC_VR54XX_MSACHI:
2213 gen_helper_msachi(t0, t0, t1);
2214 opn = "msachi";
2215 break;
2216 case OPC_VR54XX_MSACHIU:
2217 gen_helper_msachiu(t0, t0, t1);
2218 opn = "msachiu";
2219 break;
2220 default:
2221 MIPS_INVAL("mul vr54xx");
2222 generate_exception(ctx, EXCP_RI);
2223 goto out;
2225 gen_store_gpr(t0, rd);
2226 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2228 out:
2229 tcg_temp_free(t0);
2230 tcg_temp_free(t1);
2233 static void gen_cl (DisasContext *ctx, uint32_t opc,
2234 int rd, int rs)
2236 const char *opn = "CLx";
2237 TCGv t0;
2239 if (rd == 0) {
2240 /* Treat as NOP. */
2241 MIPS_DEBUG("NOP");
2242 return;
2244 t0 = tcg_temp_new();
2245 gen_load_gpr(t0, rs);
2246 switch (opc) {
2247 case OPC_CLO:
2248 gen_helper_clo(cpu_gpr[rd], t0);
2249 opn = "clo";
2250 break;
2251 case OPC_CLZ:
2252 gen_helper_clz(cpu_gpr[rd], t0);
2253 opn = "clz";
2254 break;
2255 #if defined(TARGET_MIPS64)
2256 case OPC_DCLO:
2257 gen_helper_dclo(cpu_gpr[rd], t0);
2258 opn = "dclo";
2259 break;
2260 case OPC_DCLZ:
2261 gen_helper_dclz(cpu_gpr[rd], t0);
2262 opn = "dclz";
2263 break;
2264 #endif
2266 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2267 tcg_temp_free(t0);
2270 /* Traps */
2271 static void gen_trap (DisasContext *ctx, uint32_t opc,
2272 int rs, int rt, int16_t imm)
2274 int cond;
2275 TCGv t0 = tcg_temp_new();
2276 TCGv t1 = tcg_temp_new();
2278 cond = 0;
2279 /* Load needed operands */
2280 switch (opc) {
2281 case OPC_TEQ:
2282 case OPC_TGE:
2283 case OPC_TGEU:
2284 case OPC_TLT:
2285 case OPC_TLTU:
2286 case OPC_TNE:
2287 /* Compare two registers */
2288 if (rs != rt) {
2289 gen_load_gpr(t0, rs);
2290 gen_load_gpr(t1, rt);
2291 cond = 1;
2293 break;
2294 case OPC_TEQI:
2295 case OPC_TGEI:
2296 case OPC_TGEIU:
2297 case OPC_TLTI:
2298 case OPC_TLTIU:
2299 case OPC_TNEI:
2300 /* Compare register to immediate */
2301 if (rs != 0 || imm != 0) {
2302 gen_load_gpr(t0, rs);
2303 tcg_gen_movi_tl(t1, (int32_t)imm);
2304 cond = 1;
2306 break;
2308 if (cond == 0) {
2309 switch (opc) {
2310 case OPC_TEQ: /* rs == rs */
2311 case OPC_TEQI: /* r0 == 0 */
2312 case OPC_TGE: /* rs >= rs */
2313 case OPC_TGEI: /* r0 >= 0 */
2314 case OPC_TGEU: /* rs >= rs unsigned */
2315 case OPC_TGEIU: /* r0 >= 0 unsigned */
2316 /* Always trap */
2317 generate_exception(ctx, EXCP_TRAP);
2318 break;
2319 case OPC_TLT: /* rs < rs */
2320 case OPC_TLTI: /* r0 < 0 */
2321 case OPC_TLTU: /* rs < rs unsigned */
2322 case OPC_TLTIU: /* r0 < 0 unsigned */
2323 case OPC_TNE: /* rs != rs */
2324 case OPC_TNEI: /* r0 != 0 */
2325 /* Never trap: treat as NOP. */
2326 break;
2328 } else {
2329 int l1 = gen_new_label();
2331 switch (opc) {
2332 case OPC_TEQ:
2333 case OPC_TEQI:
2334 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2335 break;
2336 case OPC_TGE:
2337 case OPC_TGEI:
2338 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2339 break;
2340 case OPC_TGEU:
2341 case OPC_TGEIU:
2342 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2343 break;
2344 case OPC_TLT:
2345 case OPC_TLTI:
2346 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2347 break;
2348 case OPC_TLTU:
2349 case OPC_TLTIU:
2350 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2351 break;
2352 case OPC_TNE:
2353 case OPC_TNEI:
2354 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2355 break;
2357 generate_exception(ctx, EXCP_TRAP);
2358 gen_set_label(l1);
2360 tcg_temp_free(t0);
2361 tcg_temp_free(t1);
2364 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2366 TranslationBlock *tb;
2367 tb = ctx->tb;
2368 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2369 likely(!ctx->singlestep_enabled)) {
2370 tcg_gen_goto_tb(n);
2371 gen_save_pc(dest);
2372 tcg_gen_exit_tb((long)tb + n);
2373 } else {
2374 gen_save_pc(dest);
2375 if (ctx->singlestep_enabled) {
2376 save_cpu_state(ctx, 0);
2377 gen_helper_0i(raise_exception, EXCP_DEBUG);
2379 tcg_gen_exit_tb(0);
2383 /* Branches (before delay slot) */
2384 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2385 int insn_bytes,
2386 int rs, int rt, int32_t offset)
2388 target_ulong btgt = -1;
2389 int blink = 0;
2390 int bcond_compute = 0;
2391 TCGv t0 = tcg_temp_new();
2392 TCGv t1 = tcg_temp_new();
2394 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2395 #ifdef MIPS_DEBUG_DISAS
2396 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2397 #endif
2398 generate_exception(ctx, EXCP_RI);
2399 goto out;
2402 /* Load needed operands */
2403 switch (opc) {
2404 case OPC_BEQ:
2405 case OPC_BEQL:
2406 case OPC_BNE:
2407 case OPC_BNEL:
2408 /* Compare two registers */
2409 if (rs != rt) {
2410 gen_load_gpr(t0, rs);
2411 gen_load_gpr(t1, rt);
2412 bcond_compute = 1;
2414 btgt = ctx->pc + insn_bytes + offset;
2415 break;
2416 case OPC_BGEZ:
2417 case OPC_BGEZAL:
2418 case OPC_BGEZALL:
2419 case OPC_BGEZL:
2420 case OPC_BGTZ:
2421 case OPC_BGTZL:
2422 case OPC_BLEZ:
2423 case OPC_BLEZL:
2424 case OPC_BLTZ:
2425 case OPC_BLTZAL:
2426 case OPC_BLTZALL:
2427 case OPC_BLTZL:
2428 /* Compare to zero */
2429 if (rs != 0) {
2430 gen_load_gpr(t0, rs);
2431 bcond_compute = 1;
2433 btgt = ctx->pc + insn_bytes + offset;
2434 break;
2435 case OPC_J:
2436 case OPC_JAL:
2437 /* Jump to immediate */
2438 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
2439 break;
2440 case OPC_JR:
2441 case OPC_JALR:
2442 /* Jump to register */
2443 if (offset != 0 && offset != 16) {
2444 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2445 others are reserved. */
2446 MIPS_INVAL("jump hint");
2447 generate_exception(ctx, EXCP_RI);
2448 goto out;
2450 gen_load_gpr(btarget, rs);
2451 break;
2452 default:
2453 MIPS_INVAL("branch/jump");
2454 generate_exception(ctx, EXCP_RI);
2455 goto out;
2457 if (bcond_compute == 0) {
2458 /* No condition to be computed */
2459 switch (opc) {
2460 case OPC_BEQ: /* rx == rx */
2461 case OPC_BEQL: /* rx == rx likely */
2462 case OPC_BGEZ: /* 0 >= 0 */
2463 case OPC_BGEZL: /* 0 >= 0 likely */
2464 case OPC_BLEZ: /* 0 <= 0 */
2465 case OPC_BLEZL: /* 0 <= 0 likely */
2466 /* Always take */
2467 ctx->hflags |= MIPS_HFLAG_B;
2468 MIPS_DEBUG("balways");
2469 break;
2470 case OPC_BGEZAL: /* 0 >= 0 */
2471 case OPC_BGEZALL: /* 0 >= 0 likely */
2472 /* Always take and link */
2473 blink = 31;
2474 ctx->hflags |= MIPS_HFLAG_B;
2475 MIPS_DEBUG("balways and link");
2476 break;
2477 case OPC_BNE: /* rx != rx */
2478 case OPC_BGTZ: /* 0 > 0 */
2479 case OPC_BLTZ: /* 0 < 0 */
2480 /* Treat as NOP. */
2481 MIPS_DEBUG("bnever (NOP)");
2482 goto out;
2483 case OPC_BLTZAL: /* 0 < 0 */
2484 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2485 MIPS_DEBUG("bnever and link");
2486 goto out;
2487 case OPC_BLTZALL: /* 0 < 0 likely */
2488 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2489 /* Skip the instruction in the delay slot */
2490 MIPS_DEBUG("bnever, link and skip");
2491 ctx->pc += 4;
2492 goto out;
2493 case OPC_BNEL: /* rx != rx likely */
2494 case OPC_BGTZL: /* 0 > 0 likely */
2495 case OPC_BLTZL: /* 0 < 0 likely */
2496 /* Skip the instruction in the delay slot */
2497 MIPS_DEBUG("bnever and skip");
2498 ctx->pc += 4;
2499 goto out;
2500 case OPC_J:
2501 ctx->hflags |= MIPS_HFLAG_B;
2502 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2503 break;
2504 case OPC_JAL:
2505 blink = 31;
2506 ctx->hflags |= MIPS_HFLAG_B;
2507 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2508 break;
2509 case OPC_JR:
2510 ctx->hflags |= MIPS_HFLAG_BR;
2511 MIPS_DEBUG("jr %s", regnames[rs]);
2512 break;
2513 case OPC_JALR:
2514 blink = rt;
2515 ctx->hflags |= MIPS_HFLAG_BR;
2516 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2517 break;
2518 default:
2519 MIPS_INVAL("branch/jump");
2520 generate_exception(ctx, EXCP_RI);
2521 goto out;
2523 } else {
2524 switch (opc) {
2525 case OPC_BEQ:
2526 gen_op_eq(bcond, t0, t1);
2527 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2528 regnames[rs], regnames[rt], btgt);
2529 goto not_likely;
2530 case OPC_BEQL:
2531 gen_op_eq(bcond, t0, t1);
2532 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2533 regnames[rs], regnames[rt], btgt);
2534 goto likely;
2535 case OPC_BNE:
2536 gen_op_ne(bcond, t0, t1);
2537 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2538 regnames[rs], regnames[rt], btgt);
2539 goto not_likely;
2540 case OPC_BNEL:
2541 gen_op_ne(bcond, t0, t1);
2542 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2543 regnames[rs], regnames[rt], btgt);
2544 goto likely;
2545 case OPC_BGEZ:
2546 gen_op_gez(bcond, t0);
2547 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2548 goto not_likely;
2549 case OPC_BGEZL:
2550 gen_op_gez(bcond, t0);
2551 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2552 goto likely;
2553 case OPC_BGEZAL:
2554 gen_op_gez(bcond, t0);
2555 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2556 blink = 31;
2557 goto not_likely;
2558 case OPC_BGEZALL:
2559 gen_op_gez(bcond, t0);
2560 blink = 31;
2561 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2562 goto likely;
2563 case OPC_BGTZ:
2564 gen_op_gtz(bcond, t0);
2565 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2566 goto not_likely;
2567 case OPC_BGTZL:
2568 gen_op_gtz(bcond, t0);
2569 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2570 goto likely;
2571 case OPC_BLEZ:
2572 gen_op_lez(bcond, t0);
2573 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2574 goto not_likely;
2575 case OPC_BLEZL:
2576 gen_op_lez(bcond, t0);
2577 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2578 goto likely;
2579 case OPC_BLTZ:
2580 gen_op_ltz(bcond, t0);
2581 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2582 goto not_likely;
2583 case OPC_BLTZL:
2584 gen_op_ltz(bcond, t0);
2585 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2586 goto likely;
2587 case OPC_BLTZAL:
2588 gen_op_ltz(bcond, t0);
2589 blink = 31;
2590 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2591 not_likely:
2592 ctx->hflags |= MIPS_HFLAG_BC;
2593 break;
2594 case OPC_BLTZALL:
2595 gen_op_ltz(bcond, t0);
2596 blink = 31;
2597 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2598 likely:
2599 ctx->hflags |= MIPS_HFLAG_BL;
2600 break;
2601 default:
2602 MIPS_INVAL("conditional branch/jump");
2603 generate_exception(ctx, EXCP_RI);
2604 goto out;
2607 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2608 blink, ctx->hflags, btgt);
2610 ctx->btarget = btgt;
2611 if (blink > 0) {
2612 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8);
2615 out:
2616 tcg_temp_free(t0);
2617 tcg_temp_free(t1);
2620 /* special3 bitfield operations */
2621 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2622 int rs, int lsb, int msb)
2624 TCGv t0 = tcg_temp_new();
2625 TCGv t1 = tcg_temp_new();
2626 target_ulong mask;
2628 gen_load_gpr(t1, rs);
2629 switch (opc) {
2630 case OPC_EXT:
2631 if (lsb + msb > 31)
2632 goto fail;
2633 tcg_gen_shri_tl(t0, t1, lsb);
2634 if (msb != 31) {
2635 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2636 } else {
2637 tcg_gen_ext32s_tl(t0, t0);
2639 break;
2640 #if defined(TARGET_MIPS64)
2641 case OPC_DEXTM:
2642 tcg_gen_shri_tl(t0, t1, lsb);
2643 if (msb != 31) {
2644 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2646 break;
2647 case OPC_DEXTU:
2648 tcg_gen_shri_tl(t0, t1, lsb + 32);
2649 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2650 break;
2651 case OPC_DEXT:
2652 tcg_gen_shri_tl(t0, t1, lsb);
2653 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
2654 break;
2655 #endif
2656 case OPC_INS:
2657 if (lsb > msb)
2658 goto fail;
2659 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
2660 gen_load_gpr(t0, rt);
2661 tcg_gen_andi_tl(t0, t0, ~mask);
2662 tcg_gen_shli_tl(t1, t1, lsb);
2663 tcg_gen_andi_tl(t1, t1, mask);
2664 tcg_gen_or_tl(t0, t0, t1);
2665 tcg_gen_ext32s_tl(t0, t0);
2666 break;
2667 #if defined(TARGET_MIPS64)
2668 case OPC_DINSM:
2669 if (lsb > msb)
2670 goto fail;
2671 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
2672 gen_load_gpr(t0, rt);
2673 tcg_gen_andi_tl(t0, t0, ~mask);
2674 tcg_gen_shli_tl(t1, t1, lsb);
2675 tcg_gen_andi_tl(t1, t1, mask);
2676 tcg_gen_or_tl(t0, t0, t1);
2677 break;
2678 case OPC_DINSU:
2679 if (lsb > msb)
2680 goto fail;
2681 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2682 gen_load_gpr(t0, rt);
2683 tcg_gen_andi_tl(t0, t0, ~mask);
2684 tcg_gen_shli_tl(t1, t1, lsb + 32);
2685 tcg_gen_andi_tl(t1, t1, mask);
2686 tcg_gen_or_tl(t0, t0, t1);
2687 break;
2688 case OPC_DINS:
2689 if (lsb > msb)
2690 goto fail;
2691 gen_load_gpr(t0, rt);
2692 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2693 gen_load_gpr(t0, rt);
2694 tcg_gen_andi_tl(t0, t0, ~mask);
2695 tcg_gen_shli_tl(t1, t1, lsb);
2696 tcg_gen_andi_tl(t1, t1, mask);
2697 tcg_gen_or_tl(t0, t0, t1);
2698 break;
2699 #endif
2700 default:
2701 fail:
2702 MIPS_INVAL("bitops");
2703 generate_exception(ctx, EXCP_RI);
2704 tcg_temp_free(t0);
2705 tcg_temp_free(t1);
2706 return;
2708 gen_store_gpr(t0, rt);
2709 tcg_temp_free(t0);
2710 tcg_temp_free(t1);
2713 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2715 TCGv t0;
2717 if (rd == 0) {
2718 /* If no destination, treat it as a NOP. */
2719 MIPS_DEBUG("NOP");
2720 return;
2723 t0 = tcg_temp_new();
2724 gen_load_gpr(t0, rt);
2725 switch (op2) {
2726 case OPC_WSBH:
2728 TCGv t1 = tcg_temp_new();
2730 tcg_gen_shri_tl(t1, t0, 8);
2731 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2732 tcg_gen_shli_tl(t0, t0, 8);
2733 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2734 tcg_gen_or_tl(t0, t0, t1);
2735 tcg_temp_free(t1);
2736 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2738 break;
2739 case OPC_SEB:
2740 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
2741 break;
2742 case OPC_SEH:
2743 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
2744 break;
2745 #if defined(TARGET_MIPS64)
2746 case OPC_DSBH:
2748 TCGv t1 = tcg_temp_new();
2750 tcg_gen_shri_tl(t1, t0, 8);
2751 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2752 tcg_gen_shli_tl(t0, t0, 8);
2753 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2754 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2755 tcg_temp_free(t1);
2757 break;
2758 case OPC_DSHD:
2760 TCGv t1 = tcg_temp_new();
2762 tcg_gen_shri_tl(t1, t0, 16);
2763 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2764 tcg_gen_shli_tl(t0, t0, 16);
2765 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2766 tcg_gen_or_tl(t0, t0, t1);
2767 tcg_gen_shri_tl(t1, t0, 32);
2768 tcg_gen_shli_tl(t0, t0, 32);
2769 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2770 tcg_temp_free(t1);
2772 break;
2773 #endif
2774 default:
2775 MIPS_INVAL("bsfhl");
2776 generate_exception(ctx, EXCP_RI);
2777 tcg_temp_free(t0);
2778 return;
2780 tcg_temp_free(t0);
2783 #ifndef CONFIG_USER_ONLY
2784 /* CP0 (MMU and control) */
2785 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
2787 TCGv_i32 t0 = tcg_temp_new_i32();
2789 tcg_gen_ld_i32(t0, cpu_env, off);
2790 tcg_gen_ext_i32_tl(arg, t0);
2791 tcg_temp_free_i32(t0);
2794 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
2796 tcg_gen_ld_tl(arg, cpu_env, off);
2797 tcg_gen_ext32s_tl(arg, arg);
2800 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
2802 TCGv_i32 t0 = tcg_temp_new_i32();
2804 tcg_gen_trunc_tl_i32(t0, arg);
2805 tcg_gen_st_i32(t0, cpu_env, off);
2806 tcg_temp_free_i32(t0);
2809 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
2811 tcg_gen_ext32s_tl(arg, arg);
2812 tcg_gen_st_tl(arg, cpu_env, off);
2815 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
2817 const char *rn = "invalid";
2819 if (sel != 0)
2820 check_insn(env, ctx, ISA_MIPS32);
2822 switch (reg) {
2823 case 0:
2824 switch (sel) {
2825 case 0:
2826 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
2827 rn = "Index";
2828 break;
2829 case 1:
2830 check_insn(env, ctx, ASE_MT);
2831 gen_helper_mfc0_mvpcontrol(arg);
2832 rn = "MVPControl";
2833 break;
2834 case 2:
2835 check_insn(env, ctx, ASE_MT);
2836 gen_helper_mfc0_mvpconf0(arg);
2837 rn = "MVPConf0";
2838 break;
2839 case 3:
2840 check_insn(env, ctx, ASE_MT);
2841 gen_helper_mfc0_mvpconf1(arg);
2842 rn = "MVPConf1";
2843 break;
2844 default:
2845 goto die;
2847 break;
2848 case 1:
2849 switch (sel) {
2850 case 0:
2851 gen_helper_mfc0_random(arg);
2852 rn = "Random";
2853 break;
2854 case 1:
2855 check_insn(env, ctx, ASE_MT);
2856 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
2857 rn = "VPEControl";
2858 break;
2859 case 2:
2860 check_insn(env, ctx, ASE_MT);
2861 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
2862 rn = "VPEConf0";
2863 break;
2864 case 3:
2865 check_insn(env, ctx, ASE_MT);
2866 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
2867 rn = "VPEConf1";
2868 break;
2869 case 4:
2870 check_insn(env, ctx, ASE_MT);
2871 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
2872 rn = "YQMask";
2873 break;
2874 case 5:
2875 check_insn(env, ctx, ASE_MT);
2876 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
2877 rn = "VPESchedule";
2878 break;
2879 case 6:
2880 check_insn(env, ctx, ASE_MT);
2881 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
2882 rn = "VPEScheFBack";
2883 break;
2884 case 7:
2885 check_insn(env, ctx, ASE_MT);
2886 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
2887 rn = "VPEOpt";
2888 break;
2889 default:
2890 goto die;
2892 break;
2893 case 2:
2894 switch (sel) {
2895 case 0:
2896 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2897 tcg_gen_ext32s_tl(arg, arg);
2898 rn = "EntryLo0";
2899 break;
2900 case 1:
2901 check_insn(env, ctx, ASE_MT);
2902 gen_helper_mfc0_tcstatus(arg);
2903 rn = "TCStatus";
2904 break;
2905 case 2:
2906 check_insn(env, ctx, ASE_MT);
2907 gen_helper_mfc0_tcbind(arg);
2908 rn = "TCBind";
2909 break;
2910 case 3:
2911 check_insn(env, ctx, ASE_MT);
2912 gen_helper_mfc0_tcrestart(arg);
2913 rn = "TCRestart";
2914 break;
2915 case 4:
2916 check_insn(env, ctx, ASE_MT);
2917 gen_helper_mfc0_tchalt(arg);
2918 rn = "TCHalt";
2919 break;
2920 case 5:
2921 check_insn(env, ctx, ASE_MT);
2922 gen_helper_mfc0_tccontext(arg);
2923 rn = "TCContext";
2924 break;
2925 case 6:
2926 check_insn(env, ctx, ASE_MT);
2927 gen_helper_mfc0_tcschedule(arg);
2928 rn = "TCSchedule";
2929 break;
2930 case 7:
2931 check_insn(env, ctx, ASE_MT);
2932 gen_helper_mfc0_tcschefback(arg);
2933 rn = "TCScheFBack";
2934 break;
2935 default:
2936 goto die;
2938 break;
2939 case 3:
2940 switch (sel) {
2941 case 0:
2942 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2943 tcg_gen_ext32s_tl(arg, arg);
2944 rn = "EntryLo1";
2945 break;
2946 default:
2947 goto die;
2949 break;
2950 case 4:
2951 switch (sel) {
2952 case 0:
2953 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
2954 tcg_gen_ext32s_tl(arg, arg);
2955 rn = "Context";
2956 break;
2957 case 1:
2958 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2959 rn = "ContextConfig";
2960 // break;
2961 default:
2962 goto die;
2964 break;
2965 case 5:
2966 switch (sel) {
2967 case 0:
2968 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
2969 rn = "PageMask";
2970 break;
2971 case 1:
2972 check_insn(env, ctx, ISA_MIPS32R2);
2973 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
2974 rn = "PageGrain";
2975 break;
2976 default:
2977 goto die;
2979 break;
2980 case 6:
2981 switch (sel) {
2982 case 0:
2983 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
2984 rn = "Wired";
2985 break;
2986 case 1:
2987 check_insn(env, ctx, ISA_MIPS32R2);
2988 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
2989 rn = "SRSConf0";
2990 break;
2991 case 2:
2992 check_insn(env, ctx, ISA_MIPS32R2);
2993 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
2994 rn = "SRSConf1";
2995 break;
2996 case 3:
2997 check_insn(env, ctx, ISA_MIPS32R2);
2998 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
2999 rn = "SRSConf2";
3000 break;
3001 case 4:
3002 check_insn(env, ctx, ISA_MIPS32R2);
3003 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
3004 rn = "SRSConf3";
3005 break;
3006 case 5:
3007 check_insn(env, ctx, ISA_MIPS32R2);
3008 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
3009 rn = "SRSConf4";
3010 break;
3011 default:
3012 goto die;
3014 break;
3015 case 7:
3016 switch (sel) {
3017 case 0:
3018 check_insn(env, ctx, ISA_MIPS32R2);
3019 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
3020 rn = "HWREna";
3021 break;
3022 default:
3023 goto die;
3025 break;
3026 case 8:
3027 switch (sel) {
3028 case 0:
3029 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3030 tcg_gen_ext32s_tl(arg, arg);
3031 rn = "BadVAddr";
3032 break;
3033 default:
3034 goto die;
3036 break;
3037 case 9:
3038 switch (sel) {
3039 case 0:
3040 /* Mark as an IO operation because we read the time. */
3041 if (use_icount)
3042 gen_io_start();
3043 gen_helper_mfc0_count(arg);
3044 if (use_icount) {
3045 gen_io_end();
3046 ctx->bstate = BS_STOP;
3048 rn = "Count";
3049 break;
3050 /* 6,7 are implementation dependent */
3051 default:
3052 goto die;
3054 break;
3055 case 10:
3056 switch (sel) {
3057 case 0:
3058 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3059 tcg_gen_ext32s_tl(arg, arg);
3060 rn = "EntryHi";
3061 break;
3062 default:
3063 goto die;
3065 break;
3066 case 11:
3067 switch (sel) {
3068 case 0:
3069 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
3070 rn = "Compare";
3071 break;
3072 /* 6,7 are implementation dependent */
3073 default:
3074 goto die;
3076 break;
3077 case 12:
3078 switch (sel) {
3079 case 0:
3080 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
3081 rn = "Status";
3082 break;
3083 case 1:
3084 check_insn(env, ctx, ISA_MIPS32R2);
3085 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
3086 rn = "IntCtl";
3087 break;
3088 case 2:
3089 check_insn(env, ctx, ISA_MIPS32R2);
3090 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
3091 rn = "SRSCtl";
3092 break;
3093 case 3:
3094 check_insn(env, ctx, ISA_MIPS32R2);
3095 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
3096 rn = "SRSMap";
3097 break;
3098 default:
3099 goto die;
3101 break;
3102 case 13:
3103 switch (sel) {
3104 case 0:
3105 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
3106 rn = "Cause";
3107 break;
3108 default:
3109 goto die;
3111 break;
3112 case 14:
3113 switch (sel) {
3114 case 0:
3115 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3116 tcg_gen_ext32s_tl(arg, arg);
3117 rn = "EPC";
3118 break;
3119 default:
3120 goto die;
3122 break;
3123 case 15:
3124 switch (sel) {
3125 case 0:
3126 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
3127 rn = "PRid";
3128 break;
3129 case 1:
3130 check_insn(env, ctx, ISA_MIPS32R2);
3131 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
3132 rn = "EBase";
3133 break;
3134 default:
3135 goto die;
3137 break;
3138 case 16:
3139 switch (sel) {
3140 case 0:
3141 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
3142 rn = "Config";
3143 break;
3144 case 1:
3145 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
3146 rn = "Config1";
3147 break;
3148 case 2:
3149 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
3150 rn = "Config2";
3151 break;
3152 case 3:
3153 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
3154 rn = "Config3";
3155 break;
3156 /* 4,5 are reserved */
3157 /* 6,7 are implementation dependent */
3158 case 6:
3159 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
3160 rn = "Config6";
3161 break;
3162 case 7:
3163 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
3164 rn = "Config7";
3165 break;
3166 default:
3167 goto die;
3169 break;
3170 case 17:
3171 switch (sel) {
3172 case 0:
3173 gen_helper_mfc0_lladdr(arg);
3174 rn = "LLAddr";
3175 break;
3176 default:
3177 goto die;
3179 break;
3180 case 18:
3181 switch (sel) {
3182 case 0 ... 7:
3183 gen_helper_1i(mfc0_watchlo, arg, sel);
3184 rn = "WatchLo";
3185 break;
3186 default:
3187 goto die;
3189 break;
3190 case 19:
3191 switch (sel) {
3192 case 0 ...7:
3193 gen_helper_1i(mfc0_watchhi, arg, sel);
3194 rn = "WatchHi";
3195 break;
3196 default:
3197 goto die;
3199 break;
3200 case 20:
3201 switch (sel) {
3202 case 0:
3203 #if defined(TARGET_MIPS64)
3204 check_insn(env, ctx, ISA_MIPS3);
3205 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3206 tcg_gen_ext32s_tl(arg, arg);
3207 rn = "XContext";
3208 break;
3209 #endif
3210 default:
3211 goto die;
3213 break;
3214 case 21:
3215 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3216 switch (sel) {
3217 case 0:
3218 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
3219 rn = "Framemask";
3220 break;
3221 default:
3222 goto die;
3224 break;
3225 case 22:
3226 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3227 rn = "'Diagnostic"; /* implementation dependent */
3228 break;
3229 case 23:
3230 switch (sel) {
3231 case 0:
3232 gen_helper_mfc0_debug(arg); /* EJTAG support */
3233 rn = "Debug";
3234 break;
3235 case 1:
3236 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3237 rn = "TraceControl";
3238 // break;
3239 case 2:
3240 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3241 rn = "TraceControl2";
3242 // break;
3243 case 3:
3244 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3245 rn = "UserTraceData";
3246 // break;
3247 case 4:
3248 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3249 rn = "TraceBPC";
3250 // break;
3251 default:
3252 goto die;
3254 break;
3255 case 24:
3256 switch (sel) {
3257 case 0:
3258 /* EJTAG support */
3259 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3260 tcg_gen_ext32s_tl(arg, arg);
3261 rn = "DEPC";
3262 break;
3263 default:
3264 goto die;
3266 break;
3267 case 25:
3268 switch (sel) {
3269 case 0:
3270 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
3271 rn = "Performance0";
3272 break;
3273 case 1:
3274 // gen_helper_mfc0_performance1(arg);
3275 rn = "Performance1";
3276 // break;
3277 case 2:
3278 // gen_helper_mfc0_performance2(arg);
3279 rn = "Performance2";
3280 // break;
3281 case 3:
3282 // gen_helper_mfc0_performance3(arg);
3283 rn = "Performance3";
3284 // break;
3285 case 4:
3286 // gen_helper_mfc0_performance4(arg);
3287 rn = "Performance4";
3288 // break;
3289 case 5:
3290 // gen_helper_mfc0_performance5(arg);
3291 rn = "Performance5";
3292 // break;
3293 case 6:
3294 // gen_helper_mfc0_performance6(arg);
3295 rn = "Performance6";
3296 // break;
3297 case 7:
3298 // gen_helper_mfc0_performance7(arg);
3299 rn = "Performance7";
3300 // break;
3301 default:
3302 goto die;
3304 break;
3305 case 26:
3306 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3307 rn = "ECC";
3308 break;
3309 case 27:
3310 switch (sel) {
3311 case 0 ... 3:
3312 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3313 rn = "CacheErr";
3314 break;
3315 default:
3316 goto die;
3318 break;
3319 case 28:
3320 switch (sel) {
3321 case 0:
3322 case 2:
3323 case 4:
3324 case 6:
3325 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
3326 rn = "TagLo";
3327 break;
3328 case 1:
3329 case 3:
3330 case 5:
3331 case 7:
3332 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
3333 rn = "DataLo";
3334 break;
3335 default:
3336 goto die;
3338 break;
3339 case 29:
3340 switch (sel) {
3341 case 0:
3342 case 2:
3343 case 4:
3344 case 6:
3345 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
3346 rn = "TagHi";
3347 break;
3348 case 1:
3349 case 3:
3350 case 5:
3351 case 7:
3352 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
3353 rn = "DataHi";
3354 break;
3355 default:
3356 goto die;
3358 break;
3359 case 30:
3360 switch (sel) {
3361 case 0:
3362 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3363 tcg_gen_ext32s_tl(arg, arg);
3364 rn = "ErrorEPC";
3365 break;
3366 default:
3367 goto die;
3369 break;
3370 case 31:
3371 switch (sel) {
3372 case 0:
3373 /* EJTAG support */
3374 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
3375 rn = "DESAVE";
3376 break;
3377 default:
3378 goto die;
3380 break;
3381 default:
3382 goto die;
3384 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3385 return;
3387 die:
3388 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3389 generate_exception(ctx, EXCP_RI);
3392 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3394 const char *rn = "invalid";
3396 if (sel != 0)
3397 check_insn(env, ctx, ISA_MIPS32);
3399 if (use_icount)
3400 gen_io_start();
3402 switch (reg) {
3403 case 0:
3404 switch (sel) {
3405 case 0:
3406 gen_helper_mtc0_index(arg);
3407 rn = "Index";
3408 break;
3409 case 1:
3410 check_insn(env, ctx, ASE_MT);
3411 gen_helper_mtc0_mvpcontrol(arg);
3412 rn = "MVPControl";
3413 break;
3414 case 2:
3415 check_insn(env, ctx, ASE_MT);
3416 /* ignored */
3417 rn = "MVPConf0";
3418 break;
3419 case 3:
3420 check_insn(env, ctx, ASE_MT);
3421 /* ignored */
3422 rn = "MVPConf1";
3423 break;
3424 default:
3425 goto die;
3427 break;
3428 case 1:
3429 switch (sel) {
3430 case 0:
3431 /* ignored */
3432 rn = "Random";
3433 break;
3434 case 1:
3435 check_insn(env, ctx, ASE_MT);
3436 gen_helper_mtc0_vpecontrol(arg);
3437 rn = "VPEControl";
3438 break;
3439 case 2:
3440 check_insn(env, ctx, ASE_MT);
3441 gen_helper_mtc0_vpeconf0(arg);
3442 rn = "VPEConf0";
3443 break;
3444 case 3:
3445 check_insn(env, ctx, ASE_MT);
3446 gen_helper_mtc0_vpeconf1(arg);
3447 rn = "VPEConf1";
3448 break;
3449 case 4:
3450 check_insn(env, ctx, ASE_MT);
3451 gen_helper_mtc0_yqmask(arg);
3452 rn = "YQMask";
3453 break;
3454 case 5:
3455 check_insn(env, ctx, ASE_MT);
3456 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
3457 rn = "VPESchedule";
3458 break;
3459 case 6:
3460 check_insn(env, ctx, ASE_MT);
3461 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3462 rn = "VPEScheFBack";
3463 break;
3464 case 7:
3465 check_insn(env, ctx, ASE_MT);
3466 gen_helper_mtc0_vpeopt(arg);
3467 rn = "VPEOpt";
3468 break;
3469 default:
3470 goto die;
3472 break;
3473 case 2:
3474 switch (sel) {
3475 case 0:
3476 gen_helper_mtc0_entrylo0(arg);
3477 rn = "EntryLo0";
3478 break;
3479 case 1:
3480 check_insn(env, ctx, ASE_MT);
3481 gen_helper_mtc0_tcstatus(arg);
3482 rn = "TCStatus";
3483 break;
3484 case 2:
3485 check_insn(env, ctx, ASE_MT);
3486 gen_helper_mtc0_tcbind(arg);
3487 rn = "TCBind";
3488 break;
3489 case 3:
3490 check_insn(env, ctx, ASE_MT);
3491 gen_helper_mtc0_tcrestart(arg);
3492 rn = "TCRestart";
3493 break;
3494 case 4:
3495 check_insn(env, ctx, ASE_MT);
3496 gen_helper_mtc0_tchalt(arg);
3497 rn = "TCHalt";
3498 break;
3499 case 5:
3500 check_insn(env, ctx, ASE_MT);
3501 gen_helper_mtc0_tccontext(arg);
3502 rn = "TCContext";
3503 break;
3504 case 6:
3505 check_insn(env, ctx, ASE_MT);
3506 gen_helper_mtc0_tcschedule(arg);
3507 rn = "TCSchedule";
3508 break;
3509 case 7:
3510 check_insn(env, ctx, ASE_MT);
3511 gen_helper_mtc0_tcschefback(arg);
3512 rn = "TCScheFBack";
3513 break;
3514 default:
3515 goto die;
3517 break;
3518 case 3:
3519 switch (sel) {
3520 case 0:
3521 gen_helper_mtc0_entrylo1(arg);
3522 rn = "EntryLo1";
3523 break;
3524 default:
3525 goto die;
3527 break;
3528 case 4:
3529 switch (sel) {
3530 case 0:
3531 gen_helper_mtc0_context(arg);
3532 rn = "Context";
3533 break;
3534 case 1:
3535 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3536 rn = "ContextConfig";
3537 // break;
3538 default:
3539 goto die;
3541 break;
3542 case 5:
3543 switch (sel) {
3544 case 0:
3545 gen_helper_mtc0_pagemask(arg);
3546 rn = "PageMask";
3547 break;
3548 case 1:
3549 check_insn(env, ctx, ISA_MIPS32R2);
3550 gen_helper_mtc0_pagegrain(arg);
3551 rn = "PageGrain";
3552 break;
3553 default:
3554 goto die;
3556 break;
3557 case 6:
3558 switch (sel) {
3559 case 0:
3560 gen_helper_mtc0_wired(arg);
3561 rn = "Wired";
3562 break;
3563 case 1:
3564 check_insn(env, ctx, ISA_MIPS32R2);
3565 gen_helper_mtc0_srsconf0(arg);
3566 rn = "SRSConf0";
3567 break;
3568 case 2:
3569 check_insn(env, ctx, ISA_MIPS32R2);
3570 gen_helper_mtc0_srsconf1(arg);
3571 rn = "SRSConf1";
3572 break;
3573 case 3:
3574 check_insn(env, ctx, ISA_MIPS32R2);
3575 gen_helper_mtc0_srsconf2(arg);
3576 rn = "SRSConf2";
3577 break;
3578 case 4:
3579 check_insn(env, ctx, ISA_MIPS32R2);
3580 gen_helper_mtc0_srsconf3(arg);
3581 rn = "SRSConf3";
3582 break;
3583 case 5:
3584 check_insn(env, ctx, ISA_MIPS32R2);
3585 gen_helper_mtc0_srsconf4(arg);
3586 rn = "SRSConf4";
3587 break;
3588 default:
3589 goto die;
3591 break;
3592 case 7:
3593 switch (sel) {
3594 case 0:
3595 check_insn(env, ctx, ISA_MIPS32R2);
3596 gen_helper_mtc0_hwrena(arg);
3597 rn = "HWREna";
3598 break;
3599 default:
3600 goto die;
3602 break;
3603 case 8:
3604 /* ignored */
3605 rn = "BadVAddr";
3606 break;
3607 case 9:
3608 switch (sel) {
3609 case 0:
3610 gen_helper_mtc0_count(arg);
3611 rn = "Count";
3612 break;
3613 /* 6,7 are implementation dependent */
3614 default:
3615 goto die;
3617 break;
3618 case 10:
3619 switch (sel) {
3620 case 0:
3621 gen_helper_mtc0_entryhi(arg);
3622 rn = "EntryHi";
3623 break;
3624 default:
3625 goto die;
3627 break;
3628 case 11:
3629 switch (sel) {
3630 case 0:
3631 gen_helper_mtc0_compare(arg);
3632 rn = "Compare";
3633 break;
3634 /* 6,7 are implementation dependent */
3635 default:
3636 goto die;
3638 break;
3639 case 12:
3640 switch (sel) {
3641 case 0:
3642 save_cpu_state(ctx, 1);
3643 gen_helper_mtc0_status(arg);
3644 /* BS_STOP isn't good enough here, hflags may have changed. */
3645 gen_save_pc(ctx->pc + 4);
3646 ctx->bstate = BS_EXCP;
3647 rn = "Status";
3648 break;
3649 case 1:
3650 check_insn(env, ctx, ISA_MIPS32R2);
3651 gen_helper_mtc0_intctl(arg);
3652 /* Stop translation as we may have switched the execution mode */
3653 ctx->bstate = BS_STOP;
3654 rn = "IntCtl";
3655 break;
3656 case 2:
3657 check_insn(env, ctx, ISA_MIPS32R2);
3658 gen_helper_mtc0_srsctl(arg);
3659 /* Stop translation as we may have switched the execution mode */
3660 ctx->bstate = BS_STOP;
3661 rn = "SRSCtl";
3662 break;
3663 case 3:
3664 check_insn(env, ctx, ISA_MIPS32R2);
3665 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
3666 /* Stop translation as we may have switched the execution mode */
3667 ctx->bstate = BS_STOP;
3668 rn = "SRSMap";
3669 break;
3670 default:
3671 goto die;
3673 break;
3674 case 13:
3675 switch (sel) {
3676 case 0:
3677 save_cpu_state(ctx, 1);
3678 gen_helper_mtc0_cause(arg);
3679 rn = "Cause";
3680 break;
3681 default:
3682 goto die;
3684 break;
3685 case 14:
3686 switch (sel) {
3687 case 0:
3688 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
3689 rn = "EPC";
3690 break;
3691 default:
3692 goto die;
3694 break;
3695 case 15:
3696 switch (sel) {
3697 case 0:
3698 /* ignored */
3699 rn = "PRid";
3700 break;
3701 case 1:
3702 check_insn(env, ctx, ISA_MIPS32R2);
3703 gen_helper_mtc0_ebase(arg);
3704 rn = "EBase";
3705 break;
3706 default:
3707 goto die;
3709 break;
3710 case 16:
3711 switch (sel) {
3712 case 0:
3713 gen_helper_mtc0_config0(arg);
3714 rn = "Config";
3715 /* Stop translation as we may have switched the execution mode */
3716 ctx->bstate = BS_STOP;
3717 break;
3718 case 1:
3719 /* ignored, read only */
3720 rn = "Config1";
3721 break;
3722 case 2:
3723 gen_helper_mtc0_config2(arg);
3724 rn = "Config2";
3725 /* Stop translation as we may have switched the execution mode */
3726 ctx->bstate = BS_STOP;
3727 break;
3728 case 3:
3729 /* ignored, read only */
3730 rn = "Config3";
3731 break;
3732 /* 4,5 are reserved */
3733 /* 6,7 are implementation dependent */
3734 case 6:
3735 /* ignored */
3736 rn = "Config6";
3737 break;
3738 case 7:
3739 /* ignored */
3740 rn = "Config7";
3741 break;
3742 default:
3743 rn = "Invalid config selector";
3744 goto die;
3746 break;
3747 case 17:
3748 switch (sel) {
3749 case 0:
3750 gen_helper_mtc0_lladdr(arg);
3751 rn = "LLAddr";
3752 break;
3753 default:
3754 goto die;
3756 break;
3757 case 18:
3758 switch (sel) {
3759 case 0 ... 7:
3760 gen_helper_1i(mtc0_watchlo, arg, sel);
3761 rn = "WatchLo";
3762 break;
3763 default:
3764 goto die;
3766 break;
3767 case 19:
3768 switch (sel) {
3769 case 0 ... 7:
3770 gen_helper_1i(mtc0_watchhi, arg, sel);
3771 rn = "WatchHi";
3772 break;
3773 default:
3774 goto die;
3776 break;
3777 case 20:
3778 switch (sel) {
3779 case 0:
3780 #if defined(TARGET_MIPS64)
3781 check_insn(env, ctx, ISA_MIPS3);
3782 gen_helper_mtc0_xcontext(arg);
3783 rn = "XContext";
3784 break;
3785 #endif
3786 default:
3787 goto die;
3789 break;
3790 case 21:
3791 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3792 switch (sel) {
3793 case 0:
3794 gen_helper_mtc0_framemask(arg);
3795 rn = "Framemask";
3796 break;
3797 default:
3798 goto die;
3800 break;
3801 case 22:
3802 /* ignored */
3803 rn = "Diagnostic"; /* implementation dependent */
3804 break;
3805 case 23:
3806 switch (sel) {
3807 case 0:
3808 gen_helper_mtc0_debug(arg); /* EJTAG support */
3809 /* BS_STOP isn't good enough here, hflags may have changed. */
3810 gen_save_pc(ctx->pc + 4);
3811 ctx->bstate = BS_EXCP;
3812 rn = "Debug";
3813 break;
3814 case 1:
3815 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
3816 rn = "TraceControl";
3817 /* Stop translation as we may have switched the execution mode */
3818 ctx->bstate = BS_STOP;
3819 // break;
3820 case 2:
3821 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
3822 rn = "TraceControl2";
3823 /* Stop translation as we may have switched the execution mode */
3824 ctx->bstate = BS_STOP;
3825 // break;
3826 case 3:
3827 /* Stop translation as we may have switched the execution mode */
3828 ctx->bstate = BS_STOP;
3829 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
3830 rn = "UserTraceData";
3831 /* Stop translation as we may have switched the execution mode */
3832 ctx->bstate = BS_STOP;
3833 // break;
3834 case 4:
3835 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
3836 /* Stop translation as we may have switched the execution mode */
3837 ctx->bstate = BS_STOP;
3838 rn = "TraceBPC";
3839 // break;
3840 default:
3841 goto die;
3843 break;
3844 case 24:
3845 switch (sel) {
3846 case 0:
3847 /* EJTAG support */
3848 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
3849 rn = "DEPC";
3850 break;
3851 default:
3852 goto die;
3854 break;
3855 case 25:
3856 switch (sel) {
3857 case 0:
3858 gen_helper_mtc0_performance0(arg);
3859 rn = "Performance0";
3860 break;
3861 case 1:
3862 // gen_helper_mtc0_performance1(arg);
3863 rn = "Performance1";
3864 // break;
3865 case 2:
3866 // gen_helper_mtc0_performance2(arg);
3867 rn = "Performance2";
3868 // break;
3869 case 3:
3870 // gen_helper_mtc0_performance3(arg);
3871 rn = "Performance3";
3872 // break;
3873 case 4:
3874 // gen_helper_mtc0_performance4(arg);
3875 rn = "Performance4";
3876 // break;
3877 case 5:
3878 // gen_helper_mtc0_performance5(arg);
3879 rn = "Performance5";
3880 // break;
3881 case 6:
3882 // gen_helper_mtc0_performance6(arg);
3883 rn = "Performance6";
3884 // break;
3885 case 7:
3886 // gen_helper_mtc0_performance7(arg);
3887 rn = "Performance7";
3888 // break;
3889 default:
3890 goto die;
3892 break;
3893 case 26:
3894 /* ignored */
3895 rn = "ECC";
3896 break;
3897 case 27:
3898 switch (sel) {
3899 case 0 ... 3:
3900 /* ignored */
3901 rn = "CacheErr";
3902 break;
3903 default:
3904 goto die;
3906 break;
3907 case 28:
3908 switch (sel) {
3909 case 0:
3910 case 2:
3911 case 4:
3912 case 6:
3913 gen_helper_mtc0_taglo(arg);
3914 rn = "TagLo";
3915 break;
3916 case 1:
3917 case 3:
3918 case 5:
3919 case 7:
3920 gen_helper_mtc0_datalo(arg);
3921 rn = "DataLo";
3922 break;
3923 default:
3924 goto die;
3926 break;
3927 case 29:
3928 switch (sel) {
3929 case 0:
3930 case 2:
3931 case 4:
3932 case 6:
3933 gen_helper_mtc0_taghi(arg);
3934 rn = "TagHi";
3935 break;
3936 case 1:
3937 case 3:
3938 case 5:
3939 case 7:
3940 gen_helper_mtc0_datahi(arg);
3941 rn = "DataHi";
3942 break;
3943 default:
3944 rn = "invalid sel";
3945 goto die;
3947 break;
3948 case 30:
3949 switch (sel) {
3950 case 0:
3951 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
3952 rn = "ErrorEPC";
3953 break;
3954 default:
3955 goto die;
3957 break;
3958 case 31:
3959 switch (sel) {
3960 case 0:
3961 /* EJTAG support */
3962 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
3963 rn = "DESAVE";
3964 break;
3965 default:
3966 goto die;
3968 /* Stop translation as we may have switched the execution mode */
3969 ctx->bstate = BS_STOP;
3970 break;
3971 default:
3972 goto die;
3974 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
3975 /* For simplicity assume that all writes can cause interrupts. */
3976 if (use_icount) {
3977 gen_io_end();
3978 ctx->bstate = BS_STOP;
3980 return;
3982 die:
3983 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
3984 generate_exception(ctx, EXCP_RI);
3987 #if defined(TARGET_MIPS64)
3988 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3990 const char *rn = "invalid";
3992 if (sel != 0)
3993 check_insn(env, ctx, ISA_MIPS64);
3995 switch (reg) {
3996 case 0:
3997 switch (sel) {
3998 case 0:
3999 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
4000 rn = "Index";
4001 break;
4002 case 1:
4003 check_insn(env, ctx, ASE_MT);
4004 gen_helper_mfc0_mvpcontrol(arg);
4005 rn = "MVPControl";
4006 break;
4007 case 2:
4008 check_insn(env, ctx, ASE_MT);
4009 gen_helper_mfc0_mvpconf0(arg);
4010 rn = "MVPConf0";
4011 break;
4012 case 3:
4013 check_insn(env, ctx, ASE_MT);
4014 gen_helper_mfc0_mvpconf1(arg);
4015 rn = "MVPConf1";
4016 break;
4017 default:
4018 goto die;
4020 break;
4021 case 1:
4022 switch (sel) {
4023 case 0:
4024 gen_helper_mfc0_random(arg);
4025 rn = "Random";
4026 break;
4027 case 1:
4028 check_insn(env, ctx, ASE_MT);
4029 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
4030 rn = "VPEControl";
4031 break;
4032 case 2:
4033 check_insn(env, ctx, ASE_MT);
4034 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
4035 rn = "VPEConf0";
4036 break;
4037 case 3:
4038 check_insn(env, ctx, ASE_MT);
4039 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
4040 rn = "VPEConf1";
4041 break;
4042 case 4:
4043 check_insn(env, ctx, ASE_MT);
4044 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
4045 rn = "YQMask";
4046 break;
4047 case 5:
4048 check_insn(env, ctx, ASE_MT);
4049 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4050 rn = "VPESchedule";
4051 break;
4052 case 6:
4053 check_insn(env, ctx, ASE_MT);
4054 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4055 rn = "VPEScheFBack";
4056 break;
4057 case 7:
4058 check_insn(env, ctx, ASE_MT);
4059 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
4060 rn = "VPEOpt";
4061 break;
4062 default:
4063 goto die;
4065 break;
4066 case 2:
4067 switch (sel) {
4068 case 0:
4069 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4070 rn = "EntryLo0";
4071 break;
4072 case 1:
4073 check_insn(env, ctx, ASE_MT);
4074 gen_helper_mfc0_tcstatus(arg);
4075 rn = "TCStatus";
4076 break;
4077 case 2:
4078 check_insn(env, ctx, ASE_MT);
4079 gen_helper_mfc0_tcbind(arg);
4080 rn = "TCBind";
4081 break;
4082 case 3:
4083 check_insn(env, ctx, ASE_MT);
4084 gen_helper_dmfc0_tcrestart(arg);
4085 rn = "TCRestart";
4086 break;
4087 case 4:
4088 check_insn(env, ctx, ASE_MT);
4089 gen_helper_dmfc0_tchalt(arg);
4090 rn = "TCHalt";
4091 break;
4092 case 5:
4093 check_insn(env, ctx, ASE_MT);
4094 gen_helper_dmfc0_tccontext(arg);
4095 rn = "TCContext";
4096 break;
4097 case 6:
4098 check_insn(env, ctx, ASE_MT);
4099 gen_helper_dmfc0_tcschedule(arg);
4100 rn = "TCSchedule";
4101 break;
4102 case 7:
4103 check_insn(env, ctx, ASE_MT);
4104 gen_helper_dmfc0_tcschefback(arg);
4105 rn = "TCScheFBack";
4106 break;
4107 default:
4108 goto die;
4110 break;
4111 case 3:
4112 switch (sel) {
4113 case 0:
4114 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4115 rn = "EntryLo1";
4116 break;
4117 default:
4118 goto die;
4120 break;
4121 case 4:
4122 switch (sel) {
4123 case 0:
4124 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
4125 rn = "Context";
4126 break;
4127 case 1:
4128 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4129 rn = "ContextConfig";
4130 // break;
4131 default:
4132 goto die;
4134 break;
4135 case 5:
4136 switch (sel) {
4137 case 0:
4138 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
4139 rn = "PageMask";
4140 break;
4141 case 1:
4142 check_insn(env, ctx, ISA_MIPS32R2);
4143 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
4144 rn = "PageGrain";
4145 break;
4146 default:
4147 goto die;
4149 break;
4150 case 6:
4151 switch (sel) {
4152 case 0:
4153 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
4154 rn = "Wired";
4155 break;
4156 case 1:
4157 check_insn(env, ctx, ISA_MIPS32R2);
4158 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
4159 rn = "SRSConf0";
4160 break;
4161 case 2:
4162 check_insn(env, ctx, ISA_MIPS32R2);
4163 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
4164 rn = "SRSConf1";
4165 break;
4166 case 3:
4167 check_insn(env, ctx, ISA_MIPS32R2);
4168 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
4169 rn = "SRSConf2";
4170 break;
4171 case 4:
4172 check_insn(env, ctx, ISA_MIPS32R2);
4173 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
4174 rn = "SRSConf3";
4175 break;
4176 case 5:
4177 check_insn(env, ctx, ISA_MIPS32R2);
4178 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
4179 rn = "SRSConf4";
4180 break;
4181 default:
4182 goto die;
4184 break;
4185 case 7:
4186 switch (sel) {
4187 case 0:
4188 check_insn(env, ctx, ISA_MIPS32R2);
4189 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
4190 rn = "HWREna";
4191 break;
4192 default:
4193 goto die;
4195 break;
4196 case 8:
4197 switch (sel) {
4198 case 0:
4199 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4200 rn = "BadVAddr";
4201 break;
4202 default:
4203 goto die;
4205 break;
4206 case 9:
4207 switch (sel) {
4208 case 0:
4209 /* Mark as an IO operation because we read the time. */
4210 if (use_icount)
4211 gen_io_start();
4212 gen_helper_mfc0_count(arg);
4213 if (use_icount) {
4214 gen_io_end();
4215 ctx->bstate = BS_STOP;
4217 rn = "Count";
4218 break;
4219 /* 6,7 are implementation dependent */
4220 default:
4221 goto die;
4223 break;
4224 case 10:
4225 switch (sel) {
4226 case 0:
4227 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
4228 rn = "EntryHi";
4229 break;
4230 default:
4231 goto die;
4233 break;
4234 case 11:
4235 switch (sel) {
4236 case 0:
4237 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
4238 rn = "Compare";
4239 break;
4240 /* 6,7 are implementation dependent */
4241 default:
4242 goto die;
4244 break;
4245 case 12:
4246 switch (sel) {
4247 case 0:
4248 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
4249 rn = "Status";
4250 break;
4251 case 1:
4252 check_insn(env, ctx, ISA_MIPS32R2);
4253 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
4254 rn = "IntCtl";
4255 break;
4256 case 2:
4257 check_insn(env, ctx, ISA_MIPS32R2);
4258 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
4259 rn = "SRSCtl";
4260 break;
4261 case 3:
4262 check_insn(env, ctx, ISA_MIPS32R2);
4263 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
4264 rn = "SRSMap";
4265 break;
4266 default:
4267 goto die;
4269 break;
4270 case 13:
4271 switch (sel) {
4272 case 0:
4273 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
4274 rn = "Cause";
4275 break;
4276 default:
4277 goto die;
4279 break;
4280 case 14:
4281 switch (sel) {
4282 case 0:
4283 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4284 rn = "EPC";
4285 break;
4286 default:
4287 goto die;
4289 break;
4290 case 15:
4291 switch (sel) {
4292 case 0:
4293 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
4294 rn = "PRid";
4295 break;
4296 case 1:
4297 check_insn(env, ctx, ISA_MIPS32R2);
4298 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
4299 rn = "EBase";
4300 break;
4301 default:
4302 goto die;
4304 break;
4305 case 16:
4306 switch (sel) {
4307 case 0:
4308 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
4309 rn = "Config";
4310 break;
4311 case 1:
4312 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
4313 rn = "Config1";
4314 break;
4315 case 2:
4316 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
4317 rn = "Config2";
4318 break;
4319 case 3:
4320 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
4321 rn = "Config3";
4322 break;
4323 /* 6,7 are implementation dependent */
4324 case 6:
4325 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
4326 rn = "Config6";
4327 break;
4328 case 7:
4329 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
4330 rn = "Config7";
4331 break;
4332 default:
4333 goto die;
4335 break;
4336 case 17:
4337 switch (sel) {
4338 case 0:
4339 gen_helper_dmfc0_lladdr(arg);
4340 rn = "LLAddr";
4341 break;
4342 default:
4343 goto die;
4345 break;
4346 case 18:
4347 switch (sel) {
4348 case 0 ... 7:
4349 gen_helper_1i(dmfc0_watchlo, arg, sel);
4350 rn = "WatchLo";
4351 break;
4352 default:
4353 goto die;
4355 break;
4356 case 19:
4357 switch (sel) {
4358 case 0 ... 7:
4359 gen_helper_1i(mfc0_watchhi, arg, sel);
4360 rn = "WatchHi";
4361 break;
4362 default:
4363 goto die;
4365 break;
4366 case 20:
4367 switch (sel) {
4368 case 0:
4369 check_insn(env, ctx, ISA_MIPS3);
4370 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
4371 rn = "XContext";
4372 break;
4373 default:
4374 goto die;
4376 break;
4377 case 21:
4378 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4379 switch (sel) {
4380 case 0:
4381 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
4382 rn = "Framemask";
4383 break;
4384 default:
4385 goto die;
4387 break;
4388 case 22:
4389 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4390 rn = "'Diagnostic"; /* implementation dependent */
4391 break;
4392 case 23:
4393 switch (sel) {
4394 case 0:
4395 gen_helper_mfc0_debug(arg); /* EJTAG support */
4396 rn = "Debug";
4397 break;
4398 case 1:
4399 // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4400 rn = "TraceControl";
4401 // break;
4402 case 2:
4403 // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4404 rn = "TraceControl2";
4405 // break;
4406 case 3:
4407 // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4408 rn = "UserTraceData";
4409 // break;
4410 case 4:
4411 // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4412 rn = "TraceBPC";
4413 // break;
4414 default:
4415 goto die;
4417 break;
4418 case 24:
4419 switch (sel) {
4420 case 0:
4421 /* EJTAG support */
4422 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4423 rn = "DEPC";
4424 break;
4425 default:
4426 goto die;
4428 break;
4429 case 25:
4430 switch (sel) {
4431 case 0:
4432 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
4433 rn = "Performance0";
4434 break;
4435 case 1:
4436 // gen_helper_dmfc0_performance1(arg);
4437 rn = "Performance1";
4438 // break;
4439 case 2:
4440 // gen_helper_dmfc0_performance2(arg);
4441 rn = "Performance2";
4442 // break;
4443 case 3:
4444 // gen_helper_dmfc0_performance3(arg);
4445 rn = "Performance3";
4446 // break;
4447 case 4:
4448 // gen_helper_dmfc0_performance4(arg);
4449 rn = "Performance4";
4450 // break;
4451 case 5:
4452 // gen_helper_dmfc0_performance5(arg);
4453 rn = "Performance5";
4454 // break;
4455 case 6:
4456 // gen_helper_dmfc0_performance6(arg);
4457 rn = "Performance6";
4458 // break;
4459 case 7:
4460 // gen_helper_dmfc0_performance7(arg);
4461 rn = "Performance7";
4462 // break;
4463 default:
4464 goto die;
4466 break;
4467 case 26:
4468 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4469 rn = "ECC";
4470 break;
4471 case 27:
4472 switch (sel) {
4473 /* ignored */
4474 case 0 ... 3:
4475 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4476 rn = "CacheErr";
4477 break;
4478 default:
4479 goto die;
4481 break;
4482 case 28:
4483 switch (sel) {
4484 case 0:
4485 case 2:
4486 case 4:
4487 case 6:
4488 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
4489 rn = "TagLo";
4490 break;
4491 case 1:
4492 case 3:
4493 case 5:
4494 case 7:
4495 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
4496 rn = "DataLo";
4497 break;
4498 default:
4499 goto die;
4501 break;
4502 case 29:
4503 switch (sel) {
4504 case 0:
4505 case 2:
4506 case 4:
4507 case 6:
4508 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
4509 rn = "TagHi";
4510 break;
4511 case 1:
4512 case 3:
4513 case 5:
4514 case 7:
4515 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
4516 rn = "DataHi";
4517 break;
4518 default:
4519 goto die;
4521 break;
4522 case 30:
4523 switch (sel) {
4524 case 0:
4525 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4526 rn = "ErrorEPC";
4527 break;
4528 default:
4529 goto die;
4531 break;
4532 case 31:
4533 switch (sel) {
4534 case 0:
4535 /* EJTAG support */
4536 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
4537 rn = "DESAVE";
4538 break;
4539 default:
4540 goto die;
4542 break;
4543 default:
4544 goto die;
4546 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4547 return;
4549 die:
4550 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4551 generate_exception(ctx, EXCP_RI);
4554 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4556 const char *rn = "invalid";
4558 if (sel != 0)
4559 check_insn(env, ctx, ISA_MIPS64);
4561 if (use_icount)
4562 gen_io_start();
4564 switch (reg) {
4565 case 0:
4566 switch (sel) {
4567 case 0:
4568 gen_helper_mtc0_index(arg);
4569 rn = "Index";
4570 break;
4571 case 1:
4572 check_insn(env, ctx, ASE_MT);
4573 gen_helper_mtc0_mvpcontrol(arg);
4574 rn = "MVPControl";
4575 break;
4576 case 2:
4577 check_insn(env, ctx, ASE_MT);
4578 /* ignored */
4579 rn = "MVPConf0";
4580 break;
4581 case 3:
4582 check_insn(env, ctx, ASE_MT);
4583 /* ignored */
4584 rn = "MVPConf1";
4585 break;
4586 default:
4587 goto die;
4589 break;
4590 case 1:
4591 switch (sel) {
4592 case 0:
4593 /* ignored */
4594 rn = "Random";
4595 break;
4596 case 1:
4597 check_insn(env, ctx, ASE_MT);
4598 gen_helper_mtc0_vpecontrol(arg);
4599 rn = "VPEControl";
4600 break;
4601 case 2:
4602 check_insn(env, ctx, ASE_MT);
4603 gen_helper_mtc0_vpeconf0(arg);
4604 rn = "VPEConf0";
4605 break;
4606 case 3:
4607 check_insn(env, ctx, ASE_MT);
4608 gen_helper_mtc0_vpeconf1(arg);
4609 rn = "VPEConf1";
4610 break;
4611 case 4:
4612 check_insn(env, ctx, ASE_MT);
4613 gen_helper_mtc0_yqmask(arg);
4614 rn = "YQMask";
4615 break;
4616 case 5:
4617 check_insn(env, ctx, ASE_MT);
4618 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4619 rn = "VPESchedule";
4620 break;
4621 case 6:
4622 check_insn(env, ctx, ASE_MT);
4623 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4624 rn = "VPEScheFBack";
4625 break;
4626 case 7:
4627 check_insn(env, ctx, ASE_MT);
4628 gen_helper_mtc0_vpeopt(arg);
4629 rn = "VPEOpt";
4630 break;
4631 default:
4632 goto die;
4634 break;
4635 case 2:
4636 switch (sel) {
4637 case 0:
4638 gen_helper_mtc0_entrylo0(arg);
4639 rn = "EntryLo0";
4640 break;
4641 case 1:
4642 check_insn(env, ctx, ASE_MT);
4643 gen_helper_mtc0_tcstatus(arg);
4644 rn = "TCStatus";
4645 break;
4646 case 2:
4647 check_insn(env, ctx, ASE_MT);
4648 gen_helper_mtc0_tcbind(arg);
4649 rn = "TCBind";
4650 break;
4651 case 3:
4652 check_insn(env, ctx, ASE_MT);
4653 gen_helper_mtc0_tcrestart(arg);
4654 rn = "TCRestart";
4655 break;
4656 case 4:
4657 check_insn(env, ctx, ASE_MT);
4658 gen_helper_mtc0_tchalt(arg);
4659 rn = "TCHalt";
4660 break;
4661 case 5:
4662 check_insn(env, ctx, ASE_MT);
4663 gen_helper_mtc0_tccontext(arg);
4664 rn = "TCContext";
4665 break;
4666 case 6:
4667 check_insn(env, ctx, ASE_MT);
4668 gen_helper_mtc0_tcschedule(arg);
4669 rn = "TCSchedule";
4670 break;
4671 case 7:
4672 check_insn(env, ctx, ASE_MT);
4673 gen_helper_mtc0_tcschefback(arg);
4674 rn = "TCScheFBack";
4675 break;
4676 default:
4677 goto die;
4679 break;
4680 case 3:
4681 switch (sel) {
4682 case 0:
4683 gen_helper_mtc0_entrylo1(arg);
4684 rn = "EntryLo1";
4685 break;
4686 default:
4687 goto die;
4689 break;
4690 case 4:
4691 switch (sel) {
4692 case 0:
4693 gen_helper_mtc0_context(arg);
4694 rn = "Context";
4695 break;
4696 case 1:
4697 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
4698 rn = "ContextConfig";
4699 // break;
4700 default:
4701 goto die;
4703 break;
4704 case 5:
4705 switch (sel) {
4706 case 0:
4707 gen_helper_mtc0_pagemask(arg);
4708 rn = "PageMask";
4709 break;
4710 case 1:
4711 check_insn(env, ctx, ISA_MIPS32R2);
4712 gen_helper_mtc0_pagegrain(arg);
4713 rn = "PageGrain";
4714 break;
4715 default:
4716 goto die;
4718 break;
4719 case 6:
4720 switch (sel) {
4721 case 0:
4722 gen_helper_mtc0_wired(arg);
4723 rn = "Wired";
4724 break;
4725 case 1:
4726 check_insn(env, ctx, ISA_MIPS32R2);
4727 gen_helper_mtc0_srsconf0(arg);
4728 rn = "SRSConf0";
4729 break;
4730 case 2:
4731 check_insn(env, ctx, ISA_MIPS32R2);
4732 gen_helper_mtc0_srsconf1(arg);
4733 rn = "SRSConf1";
4734 break;
4735 case 3:
4736 check_insn(env, ctx, ISA_MIPS32R2);
4737 gen_helper_mtc0_srsconf2(arg);
4738 rn = "SRSConf2";
4739 break;
4740 case 4:
4741 check_insn(env, ctx, ISA_MIPS32R2);
4742 gen_helper_mtc0_srsconf3(arg);
4743 rn = "SRSConf3";
4744 break;
4745 case 5:
4746 check_insn(env, ctx, ISA_MIPS32R2);
4747 gen_helper_mtc0_srsconf4(arg);
4748 rn = "SRSConf4";
4749 break;
4750 default:
4751 goto die;
4753 break;
4754 case 7:
4755 switch (sel) {
4756 case 0:
4757 check_insn(env, ctx, ISA_MIPS32R2);
4758 gen_helper_mtc0_hwrena(arg);
4759 rn = "HWREna";
4760 break;
4761 default:
4762 goto die;
4764 break;
4765 case 8:
4766 /* ignored */
4767 rn = "BadVAddr";
4768 break;
4769 case 9:
4770 switch (sel) {
4771 case 0:
4772 gen_helper_mtc0_count(arg);
4773 rn = "Count";
4774 break;
4775 /* 6,7 are implementation dependent */
4776 default:
4777 goto die;
4779 /* Stop translation as we may have switched the execution mode */
4780 ctx->bstate = BS_STOP;
4781 break;
4782 case 10:
4783 switch (sel) {
4784 case 0:
4785 gen_helper_mtc0_entryhi(arg);
4786 rn = "EntryHi";
4787 break;
4788 default:
4789 goto die;
4791 break;
4792 case 11:
4793 switch (sel) {
4794 case 0:
4795 gen_helper_mtc0_compare(arg);
4796 rn = "Compare";
4797 break;
4798 /* 6,7 are implementation dependent */
4799 default:
4800 goto die;
4802 /* Stop translation as we may have switched the execution mode */
4803 ctx->bstate = BS_STOP;
4804 break;
4805 case 12:
4806 switch (sel) {
4807 case 0:
4808 save_cpu_state(ctx, 1);
4809 gen_helper_mtc0_status(arg);
4810 /* BS_STOP isn't good enough here, hflags may have changed. */
4811 gen_save_pc(ctx->pc + 4);
4812 ctx->bstate = BS_EXCP;
4813 rn = "Status";
4814 break;
4815 case 1:
4816 check_insn(env, ctx, ISA_MIPS32R2);
4817 gen_helper_mtc0_intctl(arg);
4818 /* Stop translation as we may have switched the execution mode */
4819 ctx->bstate = BS_STOP;
4820 rn = "IntCtl";
4821 break;
4822 case 2:
4823 check_insn(env, ctx, ISA_MIPS32R2);
4824 gen_helper_mtc0_srsctl(arg);
4825 /* Stop translation as we may have switched the execution mode */
4826 ctx->bstate = BS_STOP;
4827 rn = "SRSCtl";
4828 break;
4829 case 3:
4830 check_insn(env, ctx, ISA_MIPS32R2);
4831 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
4832 /* Stop translation as we may have switched the execution mode */
4833 ctx->bstate = BS_STOP;
4834 rn = "SRSMap";
4835 break;
4836 default:
4837 goto die;
4839 break;
4840 case 13:
4841 switch (sel) {
4842 case 0:
4843 save_cpu_state(ctx, 1);
4844 gen_helper_mtc0_cause(arg);
4845 rn = "Cause";
4846 break;
4847 default:
4848 goto die;
4850 break;
4851 case 14:
4852 switch (sel) {
4853 case 0:
4854 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4855 rn = "EPC";
4856 break;
4857 default:
4858 goto die;
4860 break;
4861 case 15:
4862 switch (sel) {
4863 case 0:
4864 /* ignored */
4865 rn = "PRid";
4866 break;
4867 case 1:
4868 check_insn(env, ctx, ISA_MIPS32R2);
4869 gen_helper_mtc0_ebase(arg);
4870 rn = "EBase";
4871 break;
4872 default:
4873 goto die;
4875 break;
4876 case 16:
4877 switch (sel) {
4878 case 0:
4879 gen_helper_mtc0_config0(arg);
4880 rn = "Config";
4881 /* Stop translation as we may have switched the execution mode */
4882 ctx->bstate = BS_STOP;
4883 break;
4884 case 1:
4885 /* ignored, read only */
4886 rn = "Config1";
4887 break;
4888 case 2:
4889 gen_helper_mtc0_config2(arg);
4890 rn = "Config2";
4891 /* Stop translation as we may have switched the execution mode */
4892 ctx->bstate = BS_STOP;
4893 break;
4894 case 3:
4895 /* ignored */
4896 rn = "Config3";
4897 break;
4898 /* 6,7 are implementation dependent */
4899 default:
4900 rn = "Invalid config selector";
4901 goto die;
4903 break;
4904 case 17:
4905 switch (sel) {
4906 case 0:
4907 gen_helper_mtc0_lladdr(arg);
4908 rn = "LLAddr";
4909 break;
4910 default:
4911 goto die;
4913 break;
4914 case 18:
4915 switch (sel) {
4916 case 0 ... 7:
4917 gen_helper_1i(mtc0_watchlo, arg, sel);
4918 rn = "WatchLo";
4919 break;
4920 default:
4921 goto die;
4923 break;
4924 case 19:
4925 switch (sel) {
4926 case 0 ... 7:
4927 gen_helper_1i(mtc0_watchhi, arg, sel);
4928 rn = "WatchHi";
4929 break;
4930 default:
4931 goto die;
4933 break;
4934 case 20:
4935 switch (sel) {
4936 case 0:
4937 check_insn(env, ctx, ISA_MIPS3);
4938 gen_helper_mtc0_xcontext(arg);
4939 rn = "XContext";
4940 break;
4941 default:
4942 goto die;
4944 break;
4945 case 21:
4946 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4947 switch (sel) {
4948 case 0:
4949 gen_helper_mtc0_framemask(arg);
4950 rn = "Framemask";
4951 break;
4952 default:
4953 goto die;
4955 break;
4956 case 22:
4957 /* ignored */
4958 rn = "Diagnostic"; /* implementation dependent */
4959 break;
4960 case 23:
4961 switch (sel) {
4962 case 0:
4963 gen_helper_mtc0_debug(arg); /* EJTAG support */
4964 /* BS_STOP isn't good enough here, hflags may have changed. */
4965 gen_save_pc(ctx->pc + 4);
4966 ctx->bstate = BS_EXCP;
4967 rn = "Debug";
4968 break;
4969 case 1:
4970 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
4971 /* Stop translation as we may have switched the execution mode */
4972 ctx->bstate = BS_STOP;
4973 rn = "TraceControl";
4974 // break;
4975 case 2:
4976 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
4977 /* Stop translation as we may have switched the execution mode */
4978 ctx->bstate = BS_STOP;
4979 rn = "TraceControl2";
4980 // break;
4981 case 3:
4982 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
4983 /* Stop translation as we may have switched the execution mode */
4984 ctx->bstate = BS_STOP;
4985 rn = "UserTraceData";
4986 // break;
4987 case 4:
4988 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
4989 /* Stop translation as we may have switched the execution mode */
4990 ctx->bstate = BS_STOP;
4991 rn = "TraceBPC";
4992 // break;
4993 default:
4994 goto die;
4996 break;
4997 case 24:
4998 switch (sel) {
4999 case 0:
5000 /* EJTAG support */
5001 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
5002 rn = "DEPC";
5003 break;
5004 default:
5005 goto die;
5007 break;
5008 case 25:
5009 switch (sel) {
5010 case 0:
5011 gen_helper_mtc0_performance0(arg);
5012 rn = "Performance0";
5013 break;
5014 case 1:
5015 // gen_helper_mtc0_performance1(arg);
5016 rn = "Performance1";
5017 // break;
5018 case 2:
5019 // gen_helper_mtc0_performance2(arg);
5020 rn = "Performance2";
5021 // break;
5022 case 3:
5023 // gen_helper_mtc0_performance3(arg);
5024 rn = "Performance3";
5025 // break;
5026 case 4:
5027 // gen_helper_mtc0_performance4(arg);
5028 rn = "Performance4";
5029 // break;
5030 case 5:
5031 // gen_helper_mtc0_performance5(arg);
5032 rn = "Performance5";
5033 // break;
5034 case 6:
5035 // gen_helper_mtc0_performance6(arg);
5036 rn = "Performance6";
5037 // break;
5038 case 7:
5039 // gen_helper_mtc0_performance7(arg);
5040 rn = "Performance7";
5041 // break;
5042 default:
5043 goto die;
5045 break;
5046 case 26:
5047 /* ignored */
5048 rn = "ECC";
5049 break;
5050 case 27:
5051 switch (sel) {
5052 case 0 ... 3:
5053 /* ignored */
5054 rn = "CacheErr";
5055 break;
5056 default:
5057 goto die;
5059 break;
5060 case 28:
5061 switch (sel) {
5062 case 0:
5063 case 2:
5064 case 4:
5065 case 6:
5066 gen_helper_mtc0_taglo(arg);
5067 rn = "TagLo";
5068 break;
5069 case 1:
5070 case 3:
5071 case 5:
5072 case 7:
5073 gen_helper_mtc0_datalo(arg);
5074 rn = "DataLo";
5075 break;
5076 default:
5077 goto die;
5079 break;
5080 case 29:
5081 switch (sel) {
5082 case 0:
5083 case 2:
5084 case 4:
5085 case 6:
5086 gen_helper_mtc0_taghi(arg);
5087 rn = "TagHi";
5088 break;
5089 case 1:
5090 case 3:
5091 case 5:
5092 case 7:
5093 gen_helper_mtc0_datahi(arg);
5094 rn = "DataHi";
5095 break;
5096 default:
5097 rn = "invalid sel";
5098 goto die;
5100 break;
5101 case 30:
5102 switch (sel) {
5103 case 0:
5104 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5105 rn = "ErrorEPC";
5106 break;
5107 default:
5108 goto die;
5110 break;
5111 case 31:
5112 switch (sel) {
5113 case 0:
5114 /* EJTAG support */
5115 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
5116 rn = "DESAVE";
5117 break;
5118 default:
5119 goto die;
5121 /* Stop translation as we may have switched the execution mode */
5122 ctx->bstate = BS_STOP;
5123 break;
5124 default:
5125 goto die;
5127 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5128 /* For simplicity assume that all writes can cause interrupts. */
5129 if (use_icount) {
5130 gen_io_end();
5131 ctx->bstate = BS_STOP;
5133 return;
5135 die:
5136 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5137 generate_exception(ctx, EXCP_RI);
5139 #endif /* TARGET_MIPS64 */
5141 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5142 int u, int sel, int h)
5144 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5145 TCGv t0 = tcg_temp_local_new();
5147 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5148 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5149 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5150 tcg_gen_movi_tl(t0, -1);
5151 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5152 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5153 tcg_gen_movi_tl(t0, -1);
5154 else if (u == 0) {
5155 switch (rt) {
5156 case 2:
5157 switch (sel) {
5158 case 1:
5159 gen_helper_mftc0_tcstatus(t0);
5160 break;
5161 case 2:
5162 gen_helper_mftc0_tcbind(t0);
5163 break;
5164 case 3:
5165 gen_helper_mftc0_tcrestart(t0);
5166 break;
5167 case 4:
5168 gen_helper_mftc0_tchalt(t0);
5169 break;
5170 case 5:
5171 gen_helper_mftc0_tccontext(t0);
5172 break;
5173 case 6:
5174 gen_helper_mftc0_tcschedule(t0);
5175 break;
5176 case 7:
5177 gen_helper_mftc0_tcschefback(t0);
5178 break;
5179 default:
5180 gen_mfc0(env, ctx, t0, rt, sel);
5181 break;
5183 break;
5184 case 10:
5185 switch (sel) {
5186 case 0:
5187 gen_helper_mftc0_entryhi(t0);
5188 break;
5189 default:
5190 gen_mfc0(env, ctx, t0, rt, sel);
5191 break;
5193 case 12:
5194 switch (sel) {
5195 case 0:
5196 gen_helper_mftc0_status(t0);
5197 break;
5198 default:
5199 gen_mfc0(env, ctx, t0, rt, sel);
5200 break;
5202 case 23:
5203 switch (sel) {
5204 case 0:
5205 gen_helper_mftc0_debug(t0);
5206 break;
5207 default:
5208 gen_mfc0(env, ctx, t0, rt, sel);
5209 break;
5211 break;
5212 default:
5213 gen_mfc0(env, ctx, t0, rt, sel);
5215 } else switch (sel) {
5216 /* GPR registers. */
5217 case 0:
5218 gen_helper_1i(mftgpr, t0, rt);
5219 break;
5220 /* Auxiliary CPU registers */
5221 case 1:
5222 switch (rt) {
5223 case 0:
5224 gen_helper_1i(mftlo, t0, 0);
5225 break;
5226 case 1:
5227 gen_helper_1i(mfthi, t0, 0);
5228 break;
5229 case 2:
5230 gen_helper_1i(mftacx, t0, 0);
5231 break;
5232 case 4:
5233 gen_helper_1i(mftlo, t0, 1);
5234 break;
5235 case 5:
5236 gen_helper_1i(mfthi, t0, 1);
5237 break;
5238 case 6:
5239 gen_helper_1i(mftacx, t0, 1);
5240 break;
5241 case 8:
5242 gen_helper_1i(mftlo, t0, 2);
5243 break;
5244 case 9:
5245 gen_helper_1i(mfthi, t0, 2);
5246 break;
5247 case 10:
5248 gen_helper_1i(mftacx, t0, 2);
5249 break;
5250 case 12:
5251 gen_helper_1i(mftlo, t0, 3);
5252 break;
5253 case 13:
5254 gen_helper_1i(mfthi, t0, 3);
5255 break;
5256 case 14:
5257 gen_helper_1i(mftacx, t0, 3);
5258 break;
5259 case 16:
5260 gen_helper_mftdsp(t0);
5261 break;
5262 default:
5263 goto die;
5265 break;
5266 /* Floating point (COP1). */
5267 case 2:
5268 /* XXX: For now we support only a single FPU context. */
5269 if (h == 0) {
5270 TCGv_i32 fp0 = tcg_temp_new_i32();
5272 gen_load_fpr32(fp0, rt);
5273 tcg_gen_ext_i32_tl(t0, fp0);
5274 tcg_temp_free_i32(fp0);
5275 } else {
5276 TCGv_i32 fp0 = tcg_temp_new_i32();
5278 gen_load_fpr32h(fp0, rt);
5279 tcg_gen_ext_i32_tl(t0, fp0);
5280 tcg_temp_free_i32(fp0);
5282 break;
5283 case 3:
5284 /* XXX: For now we support only a single FPU context. */
5285 gen_helper_1i(cfc1, t0, rt);
5286 break;
5287 /* COP2: Not implemented. */
5288 case 4:
5289 case 5:
5290 /* fall through */
5291 default:
5292 goto die;
5294 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5295 gen_store_gpr(t0, rd);
5296 tcg_temp_free(t0);
5297 return;
5299 die:
5300 tcg_temp_free(t0);
5301 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5302 generate_exception(ctx, EXCP_RI);
5305 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5306 int u, int sel, int h)
5308 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5309 TCGv t0 = tcg_temp_local_new();
5311 gen_load_gpr(t0, rt);
5312 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5313 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5314 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5315 /* NOP */ ;
5316 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5317 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5318 /* NOP */ ;
5319 else if (u == 0) {
5320 switch (rd) {
5321 case 2:
5322 switch (sel) {
5323 case 1:
5324 gen_helper_mttc0_tcstatus(t0);
5325 break;
5326 case 2:
5327 gen_helper_mttc0_tcbind(t0);
5328 break;
5329 case 3:
5330 gen_helper_mttc0_tcrestart(t0);
5331 break;
5332 case 4:
5333 gen_helper_mttc0_tchalt(t0);
5334 break;
5335 case 5:
5336 gen_helper_mttc0_tccontext(t0);
5337 break;
5338 case 6:
5339 gen_helper_mttc0_tcschedule(t0);
5340 break;
5341 case 7:
5342 gen_helper_mttc0_tcschefback(t0);
5343 break;
5344 default:
5345 gen_mtc0(env, ctx, t0, rd, sel);
5346 break;
5348 break;
5349 case 10:
5350 switch (sel) {
5351 case 0:
5352 gen_helper_mttc0_entryhi(t0);
5353 break;
5354 default:
5355 gen_mtc0(env, ctx, t0, rd, sel);
5356 break;
5358 case 12:
5359 switch (sel) {
5360 case 0:
5361 gen_helper_mttc0_status(t0);
5362 break;
5363 default:
5364 gen_mtc0(env, ctx, t0, rd, sel);
5365 break;
5367 case 23:
5368 switch (sel) {
5369 case 0:
5370 gen_helper_mttc0_debug(t0);
5371 break;
5372 default:
5373 gen_mtc0(env, ctx, t0, rd, sel);
5374 break;
5376 break;
5377 default:
5378 gen_mtc0(env, ctx, t0, rd, sel);
5380 } else switch (sel) {
5381 /* GPR registers. */
5382 case 0:
5383 gen_helper_1i(mttgpr, t0, rd);
5384 break;
5385 /* Auxiliary CPU registers */
5386 case 1:
5387 switch (rd) {
5388 case 0:
5389 gen_helper_1i(mttlo, t0, 0);
5390 break;
5391 case 1:
5392 gen_helper_1i(mtthi, t0, 0);
5393 break;
5394 case 2:
5395 gen_helper_1i(mttacx, t0, 0);
5396 break;
5397 case 4:
5398 gen_helper_1i(mttlo, t0, 1);
5399 break;
5400 case 5:
5401 gen_helper_1i(mtthi, t0, 1);
5402 break;
5403 case 6:
5404 gen_helper_1i(mttacx, t0, 1);
5405 break;
5406 case 8:
5407 gen_helper_1i(mttlo, t0, 2);
5408 break;
5409 case 9:
5410 gen_helper_1i(mtthi, t0, 2);
5411 break;
5412 case 10:
5413 gen_helper_1i(mttacx, t0, 2);
5414 break;
5415 case 12:
5416 gen_helper_1i(mttlo, t0, 3);
5417 break;
5418 case 13:
5419 gen_helper_1i(mtthi, t0, 3);
5420 break;
5421 case 14:
5422 gen_helper_1i(mttacx, t0, 3);
5423 break;
5424 case 16:
5425 gen_helper_mttdsp(t0);
5426 break;
5427 default:
5428 goto die;
5430 break;
5431 /* Floating point (COP1). */
5432 case 2:
5433 /* XXX: For now we support only a single FPU context. */
5434 if (h == 0) {
5435 TCGv_i32 fp0 = tcg_temp_new_i32();
5437 tcg_gen_trunc_tl_i32(fp0, t0);
5438 gen_store_fpr32(fp0, rd);
5439 tcg_temp_free_i32(fp0);
5440 } else {
5441 TCGv_i32 fp0 = tcg_temp_new_i32();
5443 tcg_gen_trunc_tl_i32(fp0, t0);
5444 gen_store_fpr32h(fp0, rd);
5445 tcg_temp_free_i32(fp0);
5447 break;
5448 case 3:
5449 /* XXX: For now we support only a single FPU context. */
5450 gen_helper_1i(ctc1, t0, rd);
5451 break;
5452 /* COP2: Not implemented. */
5453 case 4:
5454 case 5:
5455 /* fall through */
5456 default:
5457 goto die;
5459 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5460 tcg_temp_free(t0);
5461 return;
5463 die:
5464 tcg_temp_free(t0);
5465 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5466 generate_exception(ctx, EXCP_RI);
5469 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5471 const char *opn = "ldst";
5473 switch (opc) {
5474 case OPC_MFC0:
5475 if (rt == 0) {
5476 /* Treat as NOP. */
5477 return;
5479 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5480 opn = "mfc0";
5481 break;
5482 case OPC_MTC0:
5484 TCGv t0 = tcg_temp_new();
5486 gen_load_gpr(t0, rt);
5487 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5488 tcg_temp_free(t0);
5490 opn = "mtc0";
5491 break;
5492 #if defined(TARGET_MIPS64)
5493 case OPC_DMFC0:
5494 check_insn(env, ctx, ISA_MIPS3);
5495 if (rt == 0) {
5496 /* Treat as NOP. */
5497 return;
5499 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5500 opn = "dmfc0";
5501 break;
5502 case OPC_DMTC0:
5503 check_insn(env, ctx, ISA_MIPS3);
5505 TCGv t0 = tcg_temp_new();
5507 gen_load_gpr(t0, rt);
5508 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5509 tcg_temp_free(t0);
5511 opn = "dmtc0";
5512 break;
5513 #endif
5514 case OPC_MFTR:
5515 check_insn(env, ctx, ASE_MT);
5516 if (rd == 0) {
5517 /* Treat as NOP. */
5518 return;
5520 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5521 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5522 opn = "mftr";
5523 break;
5524 case OPC_MTTR:
5525 check_insn(env, ctx, ASE_MT);
5526 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5527 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5528 opn = "mttr";
5529 break;
5530 case OPC_TLBWI:
5531 opn = "tlbwi";
5532 if (!env->tlb->helper_tlbwi)
5533 goto die;
5534 gen_helper_tlbwi();
5535 break;
5536 case OPC_TLBWR:
5537 opn = "tlbwr";
5538 if (!env->tlb->helper_tlbwr)
5539 goto die;
5540 gen_helper_tlbwr();
5541 break;
5542 case OPC_TLBP:
5543 opn = "tlbp";
5544 if (!env->tlb->helper_tlbp)
5545 goto die;
5546 gen_helper_tlbp();
5547 break;
5548 case OPC_TLBR:
5549 opn = "tlbr";
5550 if (!env->tlb->helper_tlbr)
5551 goto die;
5552 gen_helper_tlbr();
5553 break;
5554 case OPC_ERET:
5555 opn = "eret";
5556 check_insn(env, ctx, ISA_MIPS2);
5557 gen_helper_eret();
5558 ctx->bstate = BS_EXCP;
5559 break;
5560 case OPC_DERET:
5561 opn = "deret";
5562 check_insn(env, ctx, ISA_MIPS32);
5563 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5564 MIPS_INVAL(opn);
5565 generate_exception(ctx, EXCP_RI);
5566 } else {
5567 gen_helper_deret();
5568 ctx->bstate = BS_EXCP;
5570 break;
5571 case OPC_WAIT:
5572 opn = "wait";
5573 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5574 /* If we get an exception, we want to restart at next instruction */
5575 ctx->pc += 4;
5576 save_cpu_state(ctx, 1);
5577 ctx->pc -= 4;
5578 gen_helper_wait();
5579 ctx->bstate = BS_EXCP;
5580 break;
5581 default:
5582 die:
5583 MIPS_INVAL(opn);
5584 generate_exception(ctx, EXCP_RI);
5585 return;
5587 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5589 #endif /* !CONFIG_USER_ONLY */
5591 /* CP1 Branches (before delay slot) */
5592 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5593 int32_t cc, int32_t offset)
5595 target_ulong btarget;
5596 const char *opn = "cp1 cond branch";
5597 TCGv_i32 t0 = tcg_temp_new_i32();
5599 if (cc != 0)
5600 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5602 btarget = ctx->pc + 4 + offset;
5604 switch (op) {
5605 case OPC_BC1F:
5606 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5607 tcg_gen_not_i32(t0, t0);
5608 tcg_gen_andi_i32(t0, t0, 1);
5609 tcg_gen_extu_i32_tl(bcond, t0);
5610 opn = "bc1f";
5611 goto not_likely;
5612 case OPC_BC1FL:
5613 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5614 tcg_gen_not_i32(t0, t0);
5615 tcg_gen_andi_i32(t0, t0, 1);
5616 tcg_gen_extu_i32_tl(bcond, t0);
5617 opn = "bc1fl";
5618 goto likely;
5619 case OPC_BC1T:
5620 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5621 tcg_gen_andi_i32(t0, t0, 1);
5622 tcg_gen_extu_i32_tl(bcond, t0);
5623 opn = "bc1t";
5624 goto not_likely;
5625 case OPC_BC1TL:
5626 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5627 tcg_gen_andi_i32(t0, t0, 1);
5628 tcg_gen_extu_i32_tl(bcond, t0);
5629 opn = "bc1tl";
5630 likely:
5631 ctx->hflags |= MIPS_HFLAG_BL;
5632 break;
5633 case OPC_BC1FANY2:
5635 TCGv_i32 t1 = tcg_temp_new_i32();
5636 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5637 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5638 tcg_gen_or_i32(t0, t0, t1);
5639 tcg_temp_free_i32(t1);
5640 tcg_gen_not_i32(t0, t0);
5641 tcg_gen_andi_i32(t0, t0, 1);
5642 tcg_gen_extu_i32_tl(bcond, t0);
5644 opn = "bc1any2f";
5645 goto not_likely;
5646 case OPC_BC1TANY2:
5648 TCGv_i32 t1 = tcg_temp_new_i32();
5649 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5650 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5651 tcg_gen_or_i32(t0, t0, t1);
5652 tcg_temp_free_i32(t1);
5653 tcg_gen_andi_i32(t0, t0, 1);
5654 tcg_gen_extu_i32_tl(bcond, t0);
5656 opn = "bc1any2t";
5657 goto not_likely;
5658 case OPC_BC1FANY4:
5660 TCGv_i32 t1 = tcg_temp_new_i32();
5661 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5662 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5663 tcg_gen_or_i32(t0, t0, t1);
5664 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5665 tcg_gen_or_i32(t0, t0, t1);
5666 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5667 tcg_gen_or_i32(t0, t0, t1);
5668 tcg_temp_free_i32(t1);
5669 tcg_gen_not_i32(t0, t0);
5670 tcg_gen_andi_i32(t0, t0, 1);
5671 tcg_gen_extu_i32_tl(bcond, t0);
5673 opn = "bc1any4f";
5674 goto not_likely;
5675 case OPC_BC1TANY4:
5677 TCGv_i32 t1 = tcg_temp_new_i32();
5678 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5679 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5680 tcg_gen_or_i32(t0, t0, t1);
5681 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5682 tcg_gen_or_i32(t0, t0, t1);
5683 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5684 tcg_gen_or_i32(t0, t0, t1);
5685 tcg_temp_free_i32(t1);
5686 tcg_gen_andi_i32(t0, t0, 1);
5687 tcg_gen_extu_i32_tl(bcond, t0);
5689 opn = "bc1any4t";
5690 not_likely:
5691 ctx->hflags |= MIPS_HFLAG_BC;
5692 break;
5693 default:
5694 MIPS_INVAL(opn);
5695 generate_exception (ctx, EXCP_RI);
5696 goto out;
5698 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
5699 ctx->hflags, btarget);
5700 ctx->btarget = btarget;
5702 out:
5703 tcg_temp_free_i32(t0);
5706 /* Coprocessor 1 (FPU) */
5708 #define FOP(func, fmt) (((fmt) << 21) | (func))
5710 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
5712 const char *opn = "cp1 move";
5713 TCGv t0 = tcg_temp_new();
5715 switch (opc) {
5716 case OPC_MFC1:
5718 TCGv_i32 fp0 = tcg_temp_new_i32();
5720 gen_load_fpr32(fp0, fs);
5721 tcg_gen_ext_i32_tl(t0, fp0);
5722 tcg_temp_free_i32(fp0);
5724 gen_store_gpr(t0, rt);
5725 opn = "mfc1";
5726 break;
5727 case OPC_MTC1:
5728 gen_load_gpr(t0, rt);
5730 TCGv_i32 fp0 = tcg_temp_new_i32();
5732 tcg_gen_trunc_tl_i32(fp0, t0);
5733 gen_store_fpr32(fp0, fs);
5734 tcg_temp_free_i32(fp0);
5736 opn = "mtc1";
5737 break;
5738 case OPC_CFC1:
5739 gen_helper_1i(cfc1, t0, fs);
5740 gen_store_gpr(t0, rt);
5741 opn = "cfc1";
5742 break;
5743 case OPC_CTC1:
5744 gen_load_gpr(t0, rt);
5745 gen_helper_1i(ctc1, t0, fs);
5746 opn = "ctc1";
5747 break;
5748 #if defined(TARGET_MIPS64)
5749 case OPC_DMFC1:
5750 gen_load_fpr64(ctx, t0, fs);
5751 gen_store_gpr(t0, rt);
5752 opn = "dmfc1";
5753 break;
5754 case OPC_DMTC1:
5755 gen_load_gpr(t0, rt);
5756 gen_store_fpr64(ctx, t0, fs);
5757 opn = "dmtc1";
5758 break;
5759 #endif
5760 case OPC_MFHC1:
5762 TCGv_i32 fp0 = tcg_temp_new_i32();
5764 gen_load_fpr32h(fp0, fs);
5765 tcg_gen_ext_i32_tl(t0, fp0);
5766 tcg_temp_free_i32(fp0);
5768 gen_store_gpr(t0, rt);
5769 opn = "mfhc1";
5770 break;
5771 case OPC_MTHC1:
5772 gen_load_gpr(t0, rt);
5774 TCGv_i32 fp0 = tcg_temp_new_i32();
5776 tcg_gen_trunc_tl_i32(fp0, t0);
5777 gen_store_fpr32h(fp0, fs);
5778 tcg_temp_free_i32(fp0);
5780 opn = "mthc1";
5781 break;
5782 default:
5783 MIPS_INVAL(opn);
5784 generate_exception (ctx, EXCP_RI);
5785 goto out;
5787 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
5789 out:
5790 tcg_temp_free(t0);
5793 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5795 int l1;
5796 TCGCond cond;
5797 TCGv_i32 t0;
5799 if (rd == 0) {
5800 /* Treat as NOP. */
5801 return;
5804 if (tf)
5805 cond = TCG_COND_EQ;
5806 else
5807 cond = TCG_COND_NE;
5809 l1 = gen_new_label();
5810 t0 = tcg_temp_new_i32();
5811 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5812 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5813 tcg_temp_free_i32(t0);
5814 if (rs == 0) {
5815 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5816 } else {
5817 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5819 gen_set_label(l1);
5822 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
5824 int cond;
5825 TCGv_i32 t0 = tcg_temp_new_i32();
5826 int l1 = gen_new_label();
5828 if (tf)
5829 cond = TCG_COND_EQ;
5830 else
5831 cond = TCG_COND_NE;
5833 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5834 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5835 gen_load_fpr32(t0, fs);
5836 gen_store_fpr32(t0, fd);
5837 gen_set_label(l1);
5838 tcg_temp_free_i32(t0);
5841 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
5843 int cond;
5844 TCGv_i32 t0 = tcg_temp_new_i32();
5845 TCGv_i64 fp0;
5846 int l1 = gen_new_label();
5848 if (tf)
5849 cond = TCG_COND_EQ;
5850 else
5851 cond = TCG_COND_NE;
5853 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5854 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5855 tcg_temp_free_i32(t0);
5856 fp0 = tcg_temp_new_i64();
5857 gen_load_fpr64(ctx, fp0, fs);
5858 gen_store_fpr64(ctx, fp0, fd);
5859 tcg_temp_free_i64(fp0);
5860 gen_set_label(l1);
5863 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
5865 int cond;
5866 TCGv_i32 t0 = tcg_temp_new_i32();
5867 int l1 = gen_new_label();
5868 int l2 = gen_new_label();
5870 if (tf)
5871 cond = TCG_COND_EQ;
5872 else
5873 cond = TCG_COND_NE;
5875 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
5876 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5877 gen_load_fpr32(t0, fs);
5878 gen_store_fpr32(t0, fd);
5879 gen_set_label(l1);
5881 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
5882 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5883 gen_load_fpr32h(t0, fs);
5884 gen_store_fpr32h(t0, fd);
5885 tcg_temp_free_i32(t0);
5886 gen_set_label(l2);
5890 static void gen_farith (DisasContext *ctx, uint32_t op1,
5891 int ft, int fs, int fd, int cc)
5893 const char *opn = "farith";
5894 const char *condnames[] = {
5895 "c.f",
5896 "c.un",
5897 "c.eq",
5898 "c.ueq",
5899 "c.olt",
5900 "c.ult",
5901 "c.ole",
5902 "c.ule",
5903 "c.sf",
5904 "c.ngle",
5905 "c.seq",
5906 "c.ngl",
5907 "c.lt",
5908 "c.nge",
5909 "c.le",
5910 "c.ngt",
5912 const char *condnames_abs[] = {
5913 "cabs.f",
5914 "cabs.un",
5915 "cabs.eq",
5916 "cabs.ueq",
5917 "cabs.olt",
5918 "cabs.ult",
5919 "cabs.ole",
5920 "cabs.ule",
5921 "cabs.sf",
5922 "cabs.ngle",
5923 "cabs.seq",
5924 "cabs.ngl",
5925 "cabs.lt",
5926 "cabs.nge",
5927 "cabs.le",
5928 "cabs.ngt",
5930 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
5931 uint32_t func = ctx->opcode & 0x3f;
5933 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5934 case FOP(0, 16):
5936 TCGv_i32 fp0 = tcg_temp_new_i32();
5937 TCGv_i32 fp1 = tcg_temp_new_i32();
5939 gen_load_fpr32(fp0, fs);
5940 gen_load_fpr32(fp1, ft);
5941 gen_helper_float_add_s(fp0, fp0, fp1);
5942 tcg_temp_free_i32(fp1);
5943 gen_store_fpr32(fp0, fd);
5944 tcg_temp_free_i32(fp0);
5946 opn = "add.s";
5947 optype = BINOP;
5948 break;
5949 case FOP(1, 16):
5951 TCGv_i32 fp0 = tcg_temp_new_i32();
5952 TCGv_i32 fp1 = tcg_temp_new_i32();
5954 gen_load_fpr32(fp0, fs);
5955 gen_load_fpr32(fp1, ft);
5956 gen_helper_float_sub_s(fp0, fp0, fp1);
5957 tcg_temp_free_i32(fp1);
5958 gen_store_fpr32(fp0, fd);
5959 tcg_temp_free_i32(fp0);
5961 opn = "sub.s";
5962 optype = BINOP;
5963 break;
5964 case FOP(2, 16):
5966 TCGv_i32 fp0 = tcg_temp_new_i32();
5967 TCGv_i32 fp1 = tcg_temp_new_i32();
5969 gen_load_fpr32(fp0, fs);
5970 gen_load_fpr32(fp1, ft);
5971 gen_helper_float_mul_s(fp0, fp0, fp1);
5972 tcg_temp_free_i32(fp1);
5973 gen_store_fpr32(fp0, fd);
5974 tcg_temp_free_i32(fp0);
5976 opn = "mul.s";
5977 optype = BINOP;
5978 break;
5979 case FOP(3, 16):
5981 TCGv_i32 fp0 = tcg_temp_new_i32();
5982 TCGv_i32 fp1 = tcg_temp_new_i32();
5984 gen_load_fpr32(fp0, fs);
5985 gen_load_fpr32(fp1, ft);
5986 gen_helper_float_div_s(fp0, fp0, fp1);
5987 tcg_temp_free_i32(fp1);
5988 gen_store_fpr32(fp0, fd);
5989 tcg_temp_free_i32(fp0);
5991 opn = "div.s";
5992 optype = BINOP;
5993 break;
5994 case FOP(4, 16):
5996 TCGv_i32 fp0 = tcg_temp_new_i32();
5998 gen_load_fpr32(fp0, fs);
5999 gen_helper_float_sqrt_s(fp0, fp0);
6000 gen_store_fpr32(fp0, fd);
6001 tcg_temp_free_i32(fp0);
6003 opn = "sqrt.s";
6004 break;
6005 case FOP(5, 16):
6007 TCGv_i32 fp0 = tcg_temp_new_i32();
6009 gen_load_fpr32(fp0, fs);
6010 gen_helper_float_abs_s(fp0, fp0);
6011 gen_store_fpr32(fp0, fd);
6012 tcg_temp_free_i32(fp0);
6014 opn = "abs.s";
6015 break;
6016 case FOP(6, 16):
6018 TCGv_i32 fp0 = tcg_temp_new_i32();
6020 gen_load_fpr32(fp0, fs);
6021 gen_store_fpr32(fp0, fd);
6022 tcg_temp_free_i32(fp0);
6024 opn = "mov.s";
6025 break;
6026 case FOP(7, 16):
6028 TCGv_i32 fp0 = tcg_temp_new_i32();
6030 gen_load_fpr32(fp0, fs);
6031 gen_helper_float_chs_s(fp0, fp0);
6032 gen_store_fpr32(fp0, fd);
6033 tcg_temp_free_i32(fp0);
6035 opn = "neg.s";
6036 break;
6037 case FOP(8, 16):
6038 check_cp1_64bitmode(ctx);
6040 TCGv_i32 fp32 = tcg_temp_new_i32();
6041 TCGv_i64 fp64 = tcg_temp_new_i64();
6043 gen_load_fpr32(fp32, fs);
6044 gen_helper_float_roundl_s(fp64, fp32);
6045 tcg_temp_free_i32(fp32);
6046 gen_store_fpr64(ctx, fp64, fd);
6047 tcg_temp_free_i64(fp64);
6049 opn = "round.l.s";
6050 break;
6051 case FOP(9, 16):
6052 check_cp1_64bitmode(ctx);
6054 TCGv_i32 fp32 = tcg_temp_new_i32();
6055 TCGv_i64 fp64 = tcg_temp_new_i64();
6057 gen_load_fpr32(fp32, fs);
6058 gen_helper_float_truncl_s(fp64, fp32);
6059 tcg_temp_free_i32(fp32);
6060 gen_store_fpr64(ctx, fp64, fd);
6061 tcg_temp_free_i64(fp64);
6063 opn = "trunc.l.s";
6064 break;
6065 case FOP(10, 16):
6066 check_cp1_64bitmode(ctx);
6068 TCGv_i32 fp32 = tcg_temp_new_i32();
6069 TCGv_i64 fp64 = tcg_temp_new_i64();
6071 gen_load_fpr32(fp32, fs);
6072 gen_helper_float_ceill_s(fp64, fp32);
6073 tcg_temp_free_i32(fp32);
6074 gen_store_fpr64(ctx, fp64, fd);
6075 tcg_temp_free_i64(fp64);
6077 opn = "ceil.l.s";
6078 break;
6079 case FOP(11, 16):
6080 check_cp1_64bitmode(ctx);
6082 TCGv_i32 fp32 = tcg_temp_new_i32();
6083 TCGv_i64 fp64 = tcg_temp_new_i64();
6085 gen_load_fpr32(fp32, fs);
6086 gen_helper_float_floorl_s(fp64, fp32);
6087 tcg_temp_free_i32(fp32);
6088 gen_store_fpr64(ctx, fp64, fd);
6089 tcg_temp_free_i64(fp64);
6091 opn = "floor.l.s";
6092 break;
6093 case FOP(12, 16):
6095 TCGv_i32 fp0 = tcg_temp_new_i32();
6097 gen_load_fpr32(fp0, fs);
6098 gen_helper_float_roundw_s(fp0, fp0);
6099 gen_store_fpr32(fp0, fd);
6100 tcg_temp_free_i32(fp0);
6102 opn = "round.w.s";
6103 break;
6104 case FOP(13, 16):
6106 TCGv_i32 fp0 = tcg_temp_new_i32();
6108 gen_load_fpr32(fp0, fs);
6109 gen_helper_float_truncw_s(fp0, fp0);
6110 gen_store_fpr32(fp0, fd);
6111 tcg_temp_free_i32(fp0);
6113 opn = "trunc.w.s";
6114 break;
6115 case FOP(14, 16):
6117 TCGv_i32 fp0 = tcg_temp_new_i32();
6119 gen_load_fpr32(fp0, fs);
6120 gen_helper_float_ceilw_s(fp0, fp0);
6121 gen_store_fpr32(fp0, fd);
6122 tcg_temp_free_i32(fp0);
6124 opn = "ceil.w.s";
6125 break;
6126 case FOP(15, 16):
6128 TCGv_i32 fp0 = tcg_temp_new_i32();
6130 gen_load_fpr32(fp0, fs);
6131 gen_helper_float_floorw_s(fp0, fp0);
6132 gen_store_fpr32(fp0, fd);
6133 tcg_temp_free_i32(fp0);
6135 opn = "floor.w.s";
6136 break;
6137 case FOP(17, 16):
6138 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6139 opn = "movcf.s";
6140 break;
6141 case FOP(18, 16):
6143 int l1 = gen_new_label();
6144 TCGv_i32 fp0;
6146 if (ft != 0) {
6147 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6149 fp0 = tcg_temp_new_i32();
6150 gen_load_fpr32(fp0, fs);
6151 gen_store_fpr32(fp0, fd);
6152 tcg_temp_free_i32(fp0);
6153 gen_set_label(l1);
6155 opn = "movz.s";
6156 break;
6157 case FOP(19, 16):
6159 int l1 = gen_new_label();
6160 TCGv_i32 fp0;
6162 if (ft != 0) {
6163 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6164 fp0 = tcg_temp_new_i32();
6165 gen_load_fpr32(fp0, fs);
6166 gen_store_fpr32(fp0, fd);
6167 tcg_temp_free_i32(fp0);
6168 gen_set_label(l1);
6171 opn = "movn.s";
6172 break;
6173 case FOP(21, 16):
6174 check_cop1x(ctx);
6176 TCGv_i32 fp0 = tcg_temp_new_i32();
6178 gen_load_fpr32(fp0, fs);
6179 gen_helper_float_recip_s(fp0, fp0);
6180 gen_store_fpr32(fp0, fd);
6181 tcg_temp_free_i32(fp0);
6183 opn = "recip.s";
6184 break;
6185 case FOP(22, 16):
6186 check_cop1x(ctx);
6188 TCGv_i32 fp0 = tcg_temp_new_i32();
6190 gen_load_fpr32(fp0, fs);
6191 gen_helper_float_rsqrt_s(fp0, fp0);
6192 gen_store_fpr32(fp0, fd);
6193 tcg_temp_free_i32(fp0);
6195 opn = "rsqrt.s";
6196 break;
6197 case FOP(28, 16):
6198 check_cp1_64bitmode(ctx);
6200 TCGv_i32 fp0 = tcg_temp_new_i32();
6201 TCGv_i32 fp1 = tcg_temp_new_i32();
6203 gen_load_fpr32(fp0, fs);
6204 gen_load_fpr32(fp1, fd);
6205 gen_helper_float_recip2_s(fp0, fp0, fp1);
6206 tcg_temp_free_i32(fp1);
6207 gen_store_fpr32(fp0, fd);
6208 tcg_temp_free_i32(fp0);
6210 opn = "recip2.s";
6211 break;
6212 case FOP(29, 16):
6213 check_cp1_64bitmode(ctx);
6215 TCGv_i32 fp0 = tcg_temp_new_i32();
6217 gen_load_fpr32(fp0, fs);
6218 gen_helper_float_recip1_s(fp0, fp0);
6219 gen_store_fpr32(fp0, fd);
6220 tcg_temp_free_i32(fp0);
6222 opn = "recip1.s";
6223 break;
6224 case FOP(30, 16):
6225 check_cp1_64bitmode(ctx);
6227 TCGv_i32 fp0 = tcg_temp_new_i32();
6229 gen_load_fpr32(fp0, fs);
6230 gen_helper_float_rsqrt1_s(fp0, fp0);
6231 gen_store_fpr32(fp0, fd);
6232 tcg_temp_free_i32(fp0);
6234 opn = "rsqrt1.s";
6235 break;
6236 case FOP(31, 16):
6237 check_cp1_64bitmode(ctx);
6239 TCGv_i32 fp0 = tcg_temp_new_i32();
6240 TCGv_i32 fp1 = tcg_temp_new_i32();
6242 gen_load_fpr32(fp0, fs);
6243 gen_load_fpr32(fp1, ft);
6244 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6245 tcg_temp_free_i32(fp1);
6246 gen_store_fpr32(fp0, fd);
6247 tcg_temp_free_i32(fp0);
6249 opn = "rsqrt2.s";
6250 break;
6251 case FOP(33, 16):
6252 check_cp1_registers(ctx, fd);
6254 TCGv_i32 fp32 = tcg_temp_new_i32();
6255 TCGv_i64 fp64 = tcg_temp_new_i64();
6257 gen_load_fpr32(fp32, fs);
6258 gen_helper_float_cvtd_s(fp64, fp32);
6259 tcg_temp_free_i32(fp32);
6260 gen_store_fpr64(ctx, fp64, fd);
6261 tcg_temp_free_i64(fp64);
6263 opn = "cvt.d.s";
6264 break;
6265 case FOP(36, 16):
6267 TCGv_i32 fp0 = tcg_temp_new_i32();
6269 gen_load_fpr32(fp0, fs);
6270 gen_helper_float_cvtw_s(fp0, fp0);
6271 gen_store_fpr32(fp0, fd);
6272 tcg_temp_free_i32(fp0);
6274 opn = "cvt.w.s";
6275 break;
6276 case FOP(37, 16):
6277 check_cp1_64bitmode(ctx);
6279 TCGv_i32 fp32 = tcg_temp_new_i32();
6280 TCGv_i64 fp64 = tcg_temp_new_i64();
6282 gen_load_fpr32(fp32, fs);
6283 gen_helper_float_cvtl_s(fp64, fp32);
6284 tcg_temp_free_i32(fp32);
6285 gen_store_fpr64(ctx, fp64, fd);
6286 tcg_temp_free_i64(fp64);
6288 opn = "cvt.l.s";
6289 break;
6290 case FOP(38, 16):
6291 check_cp1_64bitmode(ctx);
6293 TCGv_i64 fp64 = tcg_temp_new_i64();
6294 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6295 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6297 gen_load_fpr32(fp32_0, fs);
6298 gen_load_fpr32(fp32_1, ft);
6299 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6300 tcg_temp_free_i32(fp32_1);
6301 tcg_temp_free_i32(fp32_0);
6302 gen_store_fpr64(ctx, fp64, fd);
6303 tcg_temp_free_i64(fp64);
6305 opn = "cvt.ps.s";
6306 break;
6307 case FOP(48, 16):
6308 case FOP(49, 16):
6309 case FOP(50, 16):
6310 case FOP(51, 16):
6311 case FOP(52, 16):
6312 case FOP(53, 16):
6313 case FOP(54, 16):
6314 case FOP(55, 16):
6315 case FOP(56, 16):
6316 case FOP(57, 16):
6317 case FOP(58, 16):
6318 case FOP(59, 16):
6319 case FOP(60, 16):
6320 case FOP(61, 16):
6321 case FOP(62, 16):
6322 case FOP(63, 16):
6324 TCGv_i32 fp0 = tcg_temp_new_i32();
6325 TCGv_i32 fp1 = tcg_temp_new_i32();
6327 gen_load_fpr32(fp0, fs);
6328 gen_load_fpr32(fp1, ft);
6329 if (ctx->opcode & (1 << 6)) {
6330 check_cop1x(ctx);
6331 gen_cmpabs_s(func-48, fp0, fp1, cc);
6332 opn = condnames_abs[func-48];
6333 } else {
6334 gen_cmp_s(func-48, fp0, fp1, cc);
6335 opn = condnames[func-48];
6337 tcg_temp_free_i32(fp0);
6338 tcg_temp_free_i32(fp1);
6340 break;
6341 case FOP(0, 17):
6342 check_cp1_registers(ctx, fs | ft | fd);
6344 TCGv_i64 fp0 = tcg_temp_new_i64();
6345 TCGv_i64 fp1 = tcg_temp_new_i64();
6347 gen_load_fpr64(ctx, fp0, fs);
6348 gen_load_fpr64(ctx, fp1, ft);
6349 gen_helper_float_add_d(fp0, fp0, fp1);
6350 tcg_temp_free_i64(fp1);
6351 gen_store_fpr64(ctx, fp0, fd);
6352 tcg_temp_free_i64(fp0);
6354 opn = "add.d";
6355 optype = BINOP;
6356 break;
6357 case FOP(1, 17):
6358 check_cp1_registers(ctx, fs | ft | fd);
6360 TCGv_i64 fp0 = tcg_temp_new_i64();
6361 TCGv_i64 fp1 = tcg_temp_new_i64();
6363 gen_load_fpr64(ctx, fp0, fs);
6364 gen_load_fpr64(ctx, fp1, ft);
6365 gen_helper_float_sub_d(fp0, fp0, fp1);
6366 tcg_temp_free_i64(fp1);
6367 gen_store_fpr64(ctx, fp0, fd);
6368 tcg_temp_free_i64(fp0);
6370 opn = "sub.d";
6371 optype = BINOP;
6372 break;
6373 case FOP(2, 17):
6374 check_cp1_registers(ctx, fs | ft | fd);
6376 TCGv_i64 fp0 = tcg_temp_new_i64();
6377 TCGv_i64 fp1 = tcg_temp_new_i64();
6379 gen_load_fpr64(ctx, fp0, fs);
6380 gen_load_fpr64(ctx, fp1, ft);
6381 gen_helper_float_mul_d(fp0, fp0, fp1);
6382 tcg_temp_free_i64(fp1);
6383 gen_store_fpr64(ctx, fp0, fd);
6384 tcg_temp_free_i64(fp0);
6386 opn = "mul.d";
6387 optype = BINOP;
6388 break;
6389 case FOP(3, 17):
6390 check_cp1_registers(ctx, fs | ft | fd);
6392 TCGv_i64 fp0 = tcg_temp_new_i64();
6393 TCGv_i64 fp1 = tcg_temp_new_i64();
6395 gen_load_fpr64(ctx, fp0, fs);
6396 gen_load_fpr64(ctx, fp1, ft);
6397 gen_helper_float_div_d(fp0, fp0, fp1);
6398 tcg_temp_free_i64(fp1);
6399 gen_store_fpr64(ctx, fp0, fd);
6400 tcg_temp_free_i64(fp0);
6402 opn = "div.d";
6403 optype = BINOP;
6404 break;
6405 case FOP(4, 17):
6406 check_cp1_registers(ctx, fs | fd);
6408 TCGv_i64 fp0 = tcg_temp_new_i64();
6410 gen_load_fpr64(ctx, fp0, fs);
6411 gen_helper_float_sqrt_d(fp0, fp0);
6412 gen_store_fpr64(ctx, fp0, fd);
6413 tcg_temp_free_i64(fp0);
6415 opn = "sqrt.d";
6416 break;
6417 case FOP(5, 17):
6418 check_cp1_registers(ctx, fs | fd);
6420 TCGv_i64 fp0 = tcg_temp_new_i64();
6422 gen_load_fpr64(ctx, fp0, fs);
6423 gen_helper_float_abs_d(fp0, fp0);
6424 gen_store_fpr64(ctx, fp0, fd);
6425 tcg_temp_free_i64(fp0);
6427 opn = "abs.d";
6428 break;
6429 case FOP(6, 17):
6430 check_cp1_registers(ctx, fs | fd);
6432 TCGv_i64 fp0 = tcg_temp_new_i64();
6434 gen_load_fpr64(ctx, fp0, fs);
6435 gen_store_fpr64(ctx, fp0, fd);
6436 tcg_temp_free_i64(fp0);
6438 opn = "mov.d";
6439 break;
6440 case FOP(7, 17):
6441 check_cp1_registers(ctx, fs | fd);
6443 TCGv_i64 fp0 = tcg_temp_new_i64();
6445 gen_load_fpr64(ctx, fp0, fs);
6446 gen_helper_float_chs_d(fp0, fp0);
6447 gen_store_fpr64(ctx, fp0, fd);
6448 tcg_temp_free_i64(fp0);
6450 opn = "neg.d";
6451 break;
6452 case FOP(8, 17):
6453 check_cp1_64bitmode(ctx);
6455 TCGv_i64 fp0 = tcg_temp_new_i64();
6457 gen_load_fpr64(ctx, fp0, fs);
6458 gen_helper_float_roundl_d(fp0, fp0);
6459 gen_store_fpr64(ctx, fp0, fd);
6460 tcg_temp_free_i64(fp0);
6462 opn = "round.l.d";
6463 break;
6464 case FOP(9, 17):
6465 check_cp1_64bitmode(ctx);
6467 TCGv_i64 fp0 = tcg_temp_new_i64();
6469 gen_load_fpr64(ctx, fp0, fs);
6470 gen_helper_float_truncl_d(fp0, fp0);
6471 gen_store_fpr64(ctx, fp0, fd);
6472 tcg_temp_free_i64(fp0);
6474 opn = "trunc.l.d";
6475 break;
6476 case FOP(10, 17):
6477 check_cp1_64bitmode(ctx);
6479 TCGv_i64 fp0 = tcg_temp_new_i64();
6481 gen_load_fpr64(ctx, fp0, fs);
6482 gen_helper_float_ceill_d(fp0, fp0);
6483 gen_store_fpr64(ctx, fp0, fd);
6484 tcg_temp_free_i64(fp0);
6486 opn = "ceil.l.d";
6487 break;
6488 case FOP(11, 17):
6489 check_cp1_64bitmode(ctx);
6491 TCGv_i64 fp0 = tcg_temp_new_i64();
6493 gen_load_fpr64(ctx, fp0, fs);
6494 gen_helper_float_floorl_d(fp0, fp0);
6495 gen_store_fpr64(ctx, fp0, fd);
6496 tcg_temp_free_i64(fp0);
6498 opn = "floor.l.d";
6499 break;
6500 case FOP(12, 17):
6501 check_cp1_registers(ctx, fs);
6503 TCGv_i32 fp32 = tcg_temp_new_i32();
6504 TCGv_i64 fp64 = tcg_temp_new_i64();
6506 gen_load_fpr64(ctx, fp64, fs);
6507 gen_helper_float_roundw_d(fp32, fp64);
6508 tcg_temp_free_i64(fp64);
6509 gen_store_fpr32(fp32, fd);
6510 tcg_temp_free_i32(fp32);
6512 opn = "round.w.d";
6513 break;
6514 case FOP(13, 17):
6515 check_cp1_registers(ctx, fs);
6517 TCGv_i32 fp32 = tcg_temp_new_i32();
6518 TCGv_i64 fp64 = tcg_temp_new_i64();
6520 gen_load_fpr64(ctx, fp64, fs);
6521 gen_helper_float_truncw_d(fp32, fp64);
6522 tcg_temp_free_i64(fp64);
6523 gen_store_fpr32(fp32, fd);
6524 tcg_temp_free_i32(fp32);
6526 opn = "trunc.w.d";
6527 break;
6528 case FOP(14, 17):
6529 check_cp1_registers(ctx, fs);
6531 TCGv_i32 fp32 = tcg_temp_new_i32();
6532 TCGv_i64 fp64 = tcg_temp_new_i64();
6534 gen_load_fpr64(ctx, fp64, fs);
6535 gen_helper_float_ceilw_d(fp32, fp64);
6536 tcg_temp_free_i64(fp64);
6537 gen_store_fpr32(fp32, fd);
6538 tcg_temp_free_i32(fp32);
6540 opn = "ceil.w.d";
6541 break;
6542 case FOP(15, 17):
6543 check_cp1_registers(ctx, fs);
6545 TCGv_i32 fp32 = tcg_temp_new_i32();
6546 TCGv_i64 fp64 = tcg_temp_new_i64();
6548 gen_load_fpr64(ctx, fp64, fs);
6549 gen_helper_float_floorw_d(fp32, fp64);
6550 tcg_temp_free_i64(fp64);
6551 gen_store_fpr32(fp32, fd);
6552 tcg_temp_free_i32(fp32);
6554 opn = "floor.w.d";
6555 break;
6556 case FOP(17, 17):
6557 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6558 opn = "movcf.d";
6559 break;
6560 case FOP(18, 17):
6562 int l1 = gen_new_label();
6563 TCGv_i64 fp0;
6565 if (ft != 0) {
6566 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6568 fp0 = tcg_temp_new_i64();
6569 gen_load_fpr64(ctx, fp0, fs);
6570 gen_store_fpr64(ctx, fp0, fd);
6571 tcg_temp_free_i64(fp0);
6572 gen_set_label(l1);
6574 opn = "movz.d";
6575 break;
6576 case FOP(19, 17):
6578 int l1 = gen_new_label();
6579 TCGv_i64 fp0;
6581 if (ft != 0) {
6582 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6583 fp0 = tcg_temp_new_i64();
6584 gen_load_fpr64(ctx, fp0, fs);
6585 gen_store_fpr64(ctx, fp0, fd);
6586 tcg_temp_free_i64(fp0);
6587 gen_set_label(l1);
6590 opn = "movn.d";
6591 break;
6592 case FOP(21, 17):
6593 check_cp1_64bitmode(ctx);
6595 TCGv_i64 fp0 = tcg_temp_new_i64();
6597 gen_load_fpr64(ctx, fp0, fs);
6598 gen_helper_float_recip_d(fp0, fp0);
6599 gen_store_fpr64(ctx, fp0, fd);
6600 tcg_temp_free_i64(fp0);
6602 opn = "recip.d";
6603 break;
6604 case FOP(22, 17):
6605 check_cp1_64bitmode(ctx);
6607 TCGv_i64 fp0 = tcg_temp_new_i64();
6609 gen_load_fpr64(ctx, fp0, fs);
6610 gen_helper_float_rsqrt_d(fp0, fp0);
6611 gen_store_fpr64(ctx, fp0, fd);
6612 tcg_temp_free_i64(fp0);
6614 opn = "rsqrt.d";
6615 break;
6616 case FOP(28, 17):
6617 check_cp1_64bitmode(ctx);
6619 TCGv_i64 fp0 = tcg_temp_new_i64();
6620 TCGv_i64 fp1 = tcg_temp_new_i64();
6622 gen_load_fpr64(ctx, fp0, fs);
6623 gen_load_fpr64(ctx, fp1, ft);
6624 gen_helper_float_recip2_d(fp0, fp0, fp1);
6625 tcg_temp_free_i64(fp1);
6626 gen_store_fpr64(ctx, fp0, fd);
6627 tcg_temp_free_i64(fp0);
6629 opn = "recip2.d";
6630 break;
6631 case FOP(29, 17):
6632 check_cp1_64bitmode(ctx);
6634 TCGv_i64 fp0 = tcg_temp_new_i64();
6636 gen_load_fpr64(ctx, fp0, fs);
6637 gen_helper_float_recip1_d(fp0, fp0);
6638 gen_store_fpr64(ctx, fp0, fd);
6639 tcg_temp_free_i64(fp0);
6641 opn = "recip1.d";
6642 break;
6643 case FOP(30, 17):
6644 check_cp1_64bitmode(ctx);
6646 TCGv_i64 fp0 = tcg_temp_new_i64();
6648 gen_load_fpr64(ctx, fp0, fs);
6649 gen_helper_float_rsqrt1_d(fp0, fp0);
6650 gen_store_fpr64(ctx, fp0, fd);
6651 tcg_temp_free_i64(fp0);
6653 opn = "rsqrt1.d";
6654 break;
6655 case FOP(31, 17):
6656 check_cp1_64bitmode(ctx);
6658 TCGv_i64 fp0 = tcg_temp_new_i64();
6659 TCGv_i64 fp1 = tcg_temp_new_i64();
6661 gen_load_fpr64(ctx, fp0, fs);
6662 gen_load_fpr64(ctx, fp1, ft);
6663 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6664 tcg_temp_free_i64(fp1);
6665 gen_store_fpr64(ctx, fp0, fd);
6666 tcg_temp_free_i64(fp0);
6668 opn = "rsqrt2.d";
6669 break;
6670 case FOP(48, 17):
6671 case FOP(49, 17):
6672 case FOP(50, 17):
6673 case FOP(51, 17):
6674 case FOP(52, 17):
6675 case FOP(53, 17):
6676 case FOP(54, 17):
6677 case FOP(55, 17):
6678 case FOP(56, 17):
6679 case FOP(57, 17):
6680 case FOP(58, 17):
6681 case FOP(59, 17):
6682 case FOP(60, 17):
6683 case FOP(61, 17):
6684 case FOP(62, 17):
6685 case FOP(63, 17):
6687 TCGv_i64 fp0 = tcg_temp_new_i64();
6688 TCGv_i64 fp1 = tcg_temp_new_i64();
6690 gen_load_fpr64(ctx, fp0, fs);
6691 gen_load_fpr64(ctx, fp1, ft);
6692 if (ctx->opcode & (1 << 6)) {
6693 check_cop1x(ctx);
6694 check_cp1_registers(ctx, fs | ft);
6695 gen_cmpabs_d(func-48, fp0, fp1, cc);
6696 opn = condnames_abs[func-48];
6697 } else {
6698 check_cp1_registers(ctx, fs | ft);
6699 gen_cmp_d(func-48, fp0, fp1, cc);
6700 opn = condnames[func-48];
6702 tcg_temp_free_i64(fp0);
6703 tcg_temp_free_i64(fp1);
6705 break;
6706 case FOP(32, 17):
6707 check_cp1_registers(ctx, fs);
6709 TCGv_i32 fp32 = tcg_temp_new_i32();
6710 TCGv_i64 fp64 = tcg_temp_new_i64();
6712 gen_load_fpr64(ctx, fp64, fs);
6713 gen_helper_float_cvts_d(fp32, fp64);
6714 tcg_temp_free_i64(fp64);
6715 gen_store_fpr32(fp32, fd);
6716 tcg_temp_free_i32(fp32);
6718 opn = "cvt.s.d";
6719 break;
6720 case FOP(36, 17):
6721 check_cp1_registers(ctx, fs);
6723 TCGv_i32 fp32 = tcg_temp_new_i32();
6724 TCGv_i64 fp64 = tcg_temp_new_i64();
6726 gen_load_fpr64(ctx, fp64, fs);
6727 gen_helper_float_cvtw_d(fp32, fp64);
6728 tcg_temp_free_i64(fp64);
6729 gen_store_fpr32(fp32, fd);
6730 tcg_temp_free_i32(fp32);
6732 opn = "cvt.w.d";
6733 break;
6734 case FOP(37, 17):
6735 check_cp1_64bitmode(ctx);
6737 TCGv_i64 fp0 = tcg_temp_new_i64();
6739 gen_load_fpr64(ctx, fp0, fs);
6740 gen_helper_float_cvtl_d(fp0, fp0);
6741 gen_store_fpr64(ctx, fp0, fd);
6742 tcg_temp_free_i64(fp0);
6744 opn = "cvt.l.d";
6745 break;
6746 case FOP(32, 20):
6748 TCGv_i32 fp0 = tcg_temp_new_i32();
6750 gen_load_fpr32(fp0, fs);
6751 gen_helper_float_cvts_w(fp0, fp0);
6752 gen_store_fpr32(fp0, fd);
6753 tcg_temp_free_i32(fp0);
6755 opn = "cvt.s.w";
6756 break;
6757 case FOP(33, 20):
6758 check_cp1_registers(ctx, fd);
6760 TCGv_i32 fp32 = tcg_temp_new_i32();
6761 TCGv_i64 fp64 = tcg_temp_new_i64();
6763 gen_load_fpr32(fp32, fs);
6764 gen_helper_float_cvtd_w(fp64, fp32);
6765 tcg_temp_free_i32(fp32);
6766 gen_store_fpr64(ctx, fp64, fd);
6767 tcg_temp_free_i64(fp64);
6769 opn = "cvt.d.w";
6770 break;
6771 case FOP(32, 21):
6772 check_cp1_64bitmode(ctx);
6774 TCGv_i32 fp32 = tcg_temp_new_i32();
6775 TCGv_i64 fp64 = tcg_temp_new_i64();
6777 gen_load_fpr64(ctx, fp64, fs);
6778 gen_helper_float_cvts_l(fp32, fp64);
6779 tcg_temp_free_i64(fp64);
6780 gen_store_fpr32(fp32, fd);
6781 tcg_temp_free_i32(fp32);
6783 opn = "cvt.s.l";
6784 break;
6785 case FOP(33, 21):
6786 check_cp1_64bitmode(ctx);
6788 TCGv_i64 fp0 = tcg_temp_new_i64();
6790 gen_load_fpr64(ctx, fp0, fs);
6791 gen_helper_float_cvtd_l(fp0, fp0);
6792 gen_store_fpr64(ctx, fp0, fd);
6793 tcg_temp_free_i64(fp0);
6795 opn = "cvt.d.l";
6796 break;
6797 case FOP(38, 20):
6798 check_cp1_64bitmode(ctx);
6800 TCGv_i64 fp0 = tcg_temp_new_i64();
6802 gen_load_fpr64(ctx, fp0, fs);
6803 gen_helper_float_cvtps_pw(fp0, fp0);
6804 gen_store_fpr64(ctx, fp0, fd);
6805 tcg_temp_free_i64(fp0);
6807 opn = "cvt.ps.pw";
6808 break;
6809 case FOP(0, 22):
6810 check_cp1_64bitmode(ctx);
6812 TCGv_i64 fp0 = tcg_temp_new_i64();
6813 TCGv_i64 fp1 = tcg_temp_new_i64();
6815 gen_load_fpr64(ctx, fp0, fs);
6816 gen_load_fpr64(ctx, fp1, ft);
6817 gen_helper_float_add_ps(fp0, fp0, fp1);
6818 tcg_temp_free_i64(fp1);
6819 gen_store_fpr64(ctx, fp0, fd);
6820 tcg_temp_free_i64(fp0);
6822 opn = "add.ps";
6823 break;
6824 case FOP(1, 22):
6825 check_cp1_64bitmode(ctx);
6827 TCGv_i64 fp0 = tcg_temp_new_i64();
6828 TCGv_i64 fp1 = tcg_temp_new_i64();
6830 gen_load_fpr64(ctx, fp0, fs);
6831 gen_load_fpr64(ctx, fp1, ft);
6832 gen_helper_float_sub_ps(fp0, fp0, fp1);
6833 tcg_temp_free_i64(fp1);
6834 gen_store_fpr64(ctx, fp0, fd);
6835 tcg_temp_free_i64(fp0);
6837 opn = "sub.ps";
6838 break;
6839 case FOP(2, 22):
6840 check_cp1_64bitmode(ctx);
6842 TCGv_i64 fp0 = tcg_temp_new_i64();
6843 TCGv_i64 fp1 = tcg_temp_new_i64();
6845 gen_load_fpr64(ctx, fp0, fs);
6846 gen_load_fpr64(ctx, fp1, ft);
6847 gen_helper_float_mul_ps(fp0, fp0, fp1);
6848 tcg_temp_free_i64(fp1);
6849 gen_store_fpr64(ctx, fp0, fd);
6850 tcg_temp_free_i64(fp0);
6852 opn = "mul.ps";
6853 break;
6854 case FOP(5, 22):
6855 check_cp1_64bitmode(ctx);
6857 TCGv_i64 fp0 = tcg_temp_new_i64();
6859 gen_load_fpr64(ctx, fp0, fs);
6860 gen_helper_float_abs_ps(fp0, fp0);
6861 gen_store_fpr64(ctx, fp0, fd);
6862 tcg_temp_free_i64(fp0);
6864 opn = "abs.ps";
6865 break;
6866 case FOP(6, 22):
6867 check_cp1_64bitmode(ctx);
6869 TCGv_i64 fp0 = tcg_temp_new_i64();
6871 gen_load_fpr64(ctx, fp0, fs);
6872 gen_store_fpr64(ctx, fp0, fd);
6873 tcg_temp_free_i64(fp0);
6875 opn = "mov.ps";
6876 break;
6877 case FOP(7, 22):
6878 check_cp1_64bitmode(ctx);
6880 TCGv_i64 fp0 = tcg_temp_new_i64();
6882 gen_load_fpr64(ctx, fp0, fs);
6883 gen_helper_float_chs_ps(fp0, fp0);
6884 gen_store_fpr64(ctx, fp0, fd);
6885 tcg_temp_free_i64(fp0);
6887 opn = "neg.ps";
6888 break;
6889 case FOP(17, 22):
6890 check_cp1_64bitmode(ctx);
6891 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6892 opn = "movcf.ps";
6893 break;
6894 case FOP(18, 22):
6895 check_cp1_64bitmode(ctx);
6897 int l1 = gen_new_label();
6898 TCGv_i64 fp0;
6900 if (ft != 0)
6901 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6902 fp0 = tcg_temp_new_i64();
6903 gen_load_fpr64(ctx, fp0, fs);
6904 gen_store_fpr64(ctx, fp0, fd);
6905 tcg_temp_free_i64(fp0);
6906 gen_set_label(l1);
6908 opn = "movz.ps";
6909 break;
6910 case FOP(19, 22):
6911 check_cp1_64bitmode(ctx);
6913 int l1 = gen_new_label();
6914 TCGv_i64 fp0;
6916 if (ft != 0) {
6917 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6918 fp0 = tcg_temp_new_i64();
6919 gen_load_fpr64(ctx, fp0, fs);
6920 gen_store_fpr64(ctx, fp0, fd);
6921 tcg_temp_free_i64(fp0);
6922 gen_set_label(l1);
6925 opn = "movn.ps";
6926 break;
6927 case FOP(24, 22):
6928 check_cp1_64bitmode(ctx);
6930 TCGv_i64 fp0 = tcg_temp_new_i64();
6931 TCGv_i64 fp1 = tcg_temp_new_i64();
6933 gen_load_fpr64(ctx, fp0, ft);
6934 gen_load_fpr64(ctx, fp1, fs);
6935 gen_helper_float_addr_ps(fp0, fp0, fp1);
6936 tcg_temp_free_i64(fp1);
6937 gen_store_fpr64(ctx, fp0, fd);
6938 tcg_temp_free_i64(fp0);
6940 opn = "addr.ps";
6941 break;
6942 case FOP(26, 22):
6943 check_cp1_64bitmode(ctx);
6945 TCGv_i64 fp0 = tcg_temp_new_i64();
6946 TCGv_i64 fp1 = tcg_temp_new_i64();
6948 gen_load_fpr64(ctx, fp0, ft);
6949 gen_load_fpr64(ctx, fp1, fs);
6950 gen_helper_float_mulr_ps(fp0, fp0, fp1);
6951 tcg_temp_free_i64(fp1);
6952 gen_store_fpr64(ctx, fp0, fd);
6953 tcg_temp_free_i64(fp0);
6955 opn = "mulr.ps";
6956 break;
6957 case FOP(28, 22):
6958 check_cp1_64bitmode(ctx);
6960 TCGv_i64 fp0 = tcg_temp_new_i64();
6961 TCGv_i64 fp1 = tcg_temp_new_i64();
6963 gen_load_fpr64(ctx, fp0, fs);
6964 gen_load_fpr64(ctx, fp1, fd);
6965 gen_helper_float_recip2_ps(fp0, fp0, fp1);
6966 tcg_temp_free_i64(fp1);
6967 gen_store_fpr64(ctx, fp0, fd);
6968 tcg_temp_free_i64(fp0);
6970 opn = "recip2.ps";
6971 break;
6972 case FOP(29, 22):
6973 check_cp1_64bitmode(ctx);
6975 TCGv_i64 fp0 = tcg_temp_new_i64();
6977 gen_load_fpr64(ctx, fp0, fs);
6978 gen_helper_float_recip1_ps(fp0, fp0);
6979 gen_store_fpr64(ctx, fp0, fd);
6980 tcg_temp_free_i64(fp0);
6982 opn = "recip1.ps";
6983 break;
6984 case FOP(30, 22):
6985 check_cp1_64bitmode(ctx);
6987 TCGv_i64 fp0 = tcg_temp_new_i64();
6989 gen_load_fpr64(ctx, fp0, fs);
6990 gen_helper_float_rsqrt1_ps(fp0, fp0);
6991 gen_store_fpr64(ctx, fp0, fd);
6992 tcg_temp_free_i64(fp0);
6994 opn = "rsqrt1.ps";
6995 break;
6996 case FOP(31, 22):
6997 check_cp1_64bitmode(ctx);
6999 TCGv_i64 fp0 = tcg_temp_new_i64();
7000 TCGv_i64 fp1 = tcg_temp_new_i64();
7002 gen_load_fpr64(ctx, fp0, fs);
7003 gen_load_fpr64(ctx, fp1, ft);
7004 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7005 tcg_temp_free_i64(fp1);
7006 gen_store_fpr64(ctx, fp0, fd);
7007 tcg_temp_free_i64(fp0);
7009 opn = "rsqrt2.ps";
7010 break;
7011 case FOP(32, 22):
7012 check_cp1_64bitmode(ctx);
7014 TCGv_i32 fp0 = tcg_temp_new_i32();
7016 gen_load_fpr32h(fp0, fs);
7017 gen_helper_float_cvts_pu(fp0, fp0);
7018 gen_store_fpr32(fp0, fd);
7019 tcg_temp_free_i32(fp0);
7021 opn = "cvt.s.pu";
7022 break;
7023 case FOP(36, 22):
7024 check_cp1_64bitmode(ctx);
7026 TCGv_i64 fp0 = tcg_temp_new_i64();
7028 gen_load_fpr64(ctx, fp0, fs);
7029 gen_helper_float_cvtpw_ps(fp0, fp0);
7030 gen_store_fpr64(ctx, fp0, fd);
7031 tcg_temp_free_i64(fp0);
7033 opn = "cvt.pw.ps";
7034 break;
7035 case FOP(40, 22):
7036 check_cp1_64bitmode(ctx);
7038 TCGv_i32 fp0 = tcg_temp_new_i32();
7040 gen_load_fpr32(fp0, fs);
7041 gen_helper_float_cvts_pl(fp0, fp0);
7042 gen_store_fpr32(fp0, fd);
7043 tcg_temp_free_i32(fp0);
7045 opn = "cvt.s.pl";
7046 break;
7047 case FOP(44, 22):
7048 check_cp1_64bitmode(ctx);
7050 TCGv_i32 fp0 = tcg_temp_new_i32();
7051 TCGv_i32 fp1 = tcg_temp_new_i32();
7053 gen_load_fpr32(fp0, fs);
7054 gen_load_fpr32(fp1, ft);
7055 gen_store_fpr32h(fp0, fd);
7056 gen_store_fpr32(fp1, fd);
7057 tcg_temp_free_i32(fp0);
7058 tcg_temp_free_i32(fp1);
7060 opn = "pll.ps";
7061 break;
7062 case FOP(45, 22):
7063 check_cp1_64bitmode(ctx);
7065 TCGv_i32 fp0 = tcg_temp_new_i32();
7066 TCGv_i32 fp1 = tcg_temp_new_i32();
7068 gen_load_fpr32(fp0, fs);
7069 gen_load_fpr32h(fp1, ft);
7070 gen_store_fpr32(fp1, fd);
7071 gen_store_fpr32h(fp0, fd);
7072 tcg_temp_free_i32(fp0);
7073 tcg_temp_free_i32(fp1);
7075 opn = "plu.ps";
7076 break;
7077 case FOP(46, 22):
7078 check_cp1_64bitmode(ctx);
7080 TCGv_i32 fp0 = tcg_temp_new_i32();
7081 TCGv_i32 fp1 = tcg_temp_new_i32();
7083 gen_load_fpr32h(fp0, fs);
7084 gen_load_fpr32(fp1, ft);
7085 gen_store_fpr32(fp1, fd);
7086 gen_store_fpr32h(fp0, fd);
7087 tcg_temp_free_i32(fp0);
7088 tcg_temp_free_i32(fp1);
7090 opn = "pul.ps";
7091 break;
7092 case FOP(47, 22):
7093 check_cp1_64bitmode(ctx);
7095 TCGv_i32 fp0 = tcg_temp_new_i32();
7096 TCGv_i32 fp1 = tcg_temp_new_i32();
7098 gen_load_fpr32h(fp0, fs);
7099 gen_load_fpr32h(fp1, ft);
7100 gen_store_fpr32(fp1, fd);
7101 gen_store_fpr32h(fp0, fd);
7102 tcg_temp_free_i32(fp0);
7103 tcg_temp_free_i32(fp1);
7105 opn = "puu.ps";
7106 break;
7107 case FOP(48, 22):
7108 case FOP(49, 22):
7109 case FOP(50, 22):
7110 case FOP(51, 22):
7111 case FOP(52, 22):
7112 case FOP(53, 22):
7113 case FOP(54, 22):
7114 case FOP(55, 22):
7115 case FOP(56, 22):
7116 case FOP(57, 22):
7117 case FOP(58, 22):
7118 case FOP(59, 22):
7119 case FOP(60, 22):
7120 case FOP(61, 22):
7121 case FOP(62, 22):
7122 case FOP(63, 22):
7123 check_cp1_64bitmode(ctx);
7125 TCGv_i64 fp0 = tcg_temp_new_i64();
7126 TCGv_i64 fp1 = tcg_temp_new_i64();
7128 gen_load_fpr64(ctx, fp0, fs);
7129 gen_load_fpr64(ctx, fp1, ft);
7130 if (ctx->opcode & (1 << 6)) {
7131 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7132 opn = condnames_abs[func-48];
7133 } else {
7134 gen_cmp_ps(func-48, fp0, fp1, cc);
7135 opn = condnames[func-48];
7137 tcg_temp_free_i64(fp0);
7138 tcg_temp_free_i64(fp1);
7140 break;
7141 default:
7142 MIPS_INVAL(opn);
7143 generate_exception (ctx, EXCP_RI);
7144 return;
7146 switch (optype) {
7147 case BINOP:
7148 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7149 break;
7150 case CMPOP:
7151 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7152 break;
7153 default:
7154 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7155 break;
7159 /* Coprocessor 3 (FPU) */
7160 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7161 int fd, int fs, int base, int index)
7163 const char *opn = "extended float load/store";
7164 int store = 0;
7165 TCGv t0 = tcg_temp_new();
7167 if (base == 0) {
7168 gen_load_gpr(t0, index);
7169 } else if (index == 0) {
7170 gen_load_gpr(t0, base);
7171 } else {
7172 gen_load_gpr(t0, index);
7173 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
7175 /* Don't do NOP if destination is zero: we must perform the actual
7176 memory access. */
7177 save_cpu_state(ctx, 0);
7178 switch (opc) {
7179 case OPC_LWXC1:
7180 check_cop1x(ctx);
7182 TCGv_i32 fp0 = tcg_temp_new_i32();
7184 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7185 tcg_gen_trunc_tl_i32(fp0, t0);
7186 gen_store_fpr32(fp0, fd);
7187 tcg_temp_free_i32(fp0);
7189 opn = "lwxc1";
7190 break;
7191 case OPC_LDXC1:
7192 check_cop1x(ctx);
7193 check_cp1_registers(ctx, fd);
7195 TCGv_i64 fp0 = tcg_temp_new_i64();
7197 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7198 gen_store_fpr64(ctx, fp0, fd);
7199 tcg_temp_free_i64(fp0);
7201 opn = "ldxc1";
7202 break;
7203 case OPC_LUXC1:
7204 check_cp1_64bitmode(ctx);
7205 tcg_gen_andi_tl(t0, t0, ~0x7);
7207 TCGv_i64 fp0 = tcg_temp_new_i64();
7209 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7210 gen_store_fpr64(ctx, fp0, fd);
7211 tcg_temp_free_i64(fp0);
7213 opn = "luxc1";
7214 break;
7215 case OPC_SWXC1:
7216 check_cop1x(ctx);
7218 TCGv_i32 fp0 = tcg_temp_new_i32();
7219 TCGv t1 = tcg_temp_new();
7221 gen_load_fpr32(fp0, fs);
7222 tcg_gen_extu_i32_tl(t1, fp0);
7223 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7224 tcg_temp_free_i32(fp0);
7225 tcg_temp_free(t1);
7227 opn = "swxc1";
7228 store = 1;
7229 break;
7230 case OPC_SDXC1:
7231 check_cop1x(ctx);
7232 check_cp1_registers(ctx, fs);
7234 TCGv_i64 fp0 = tcg_temp_new_i64();
7236 gen_load_fpr64(ctx, fp0, fs);
7237 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7238 tcg_temp_free_i64(fp0);
7240 opn = "sdxc1";
7241 store = 1;
7242 break;
7243 case OPC_SUXC1:
7244 check_cp1_64bitmode(ctx);
7245 tcg_gen_andi_tl(t0, t0, ~0x7);
7247 TCGv_i64 fp0 = tcg_temp_new_i64();
7249 gen_load_fpr64(ctx, fp0, fs);
7250 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7251 tcg_temp_free_i64(fp0);
7253 opn = "suxc1";
7254 store = 1;
7255 break;
7257 tcg_temp_free(t0);
7258 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7259 regnames[index], regnames[base]);
7262 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7263 int fd, int fr, int fs, int ft)
7265 const char *opn = "flt3_arith";
7267 switch (opc) {
7268 case OPC_ALNV_PS:
7269 check_cp1_64bitmode(ctx);
7271 TCGv t0 = tcg_temp_local_new();
7272 TCGv_i32 fp = tcg_temp_new_i32();
7273 TCGv_i32 fph = tcg_temp_new_i32();
7274 int l1 = gen_new_label();
7275 int l2 = gen_new_label();
7277 gen_load_gpr(t0, fr);
7278 tcg_gen_andi_tl(t0, t0, 0x7);
7280 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7281 gen_load_fpr32(fp, fs);
7282 gen_load_fpr32h(fph, fs);
7283 gen_store_fpr32(fp, fd);
7284 gen_store_fpr32h(fph, fd);
7285 tcg_gen_br(l2);
7286 gen_set_label(l1);
7287 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7288 tcg_temp_free(t0);
7289 #ifdef TARGET_WORDS_BIGENDIAN
7290 gen_load_fpr32(fp, fs);
7291 gen_load_fpr32h(fph, ft);
7292 gen_store_fpr32h(fp, fd);
7293 gen_store_fpr32(fph, fd);
7294 #else
7295 gen_load_fpr32h(fph, fs);
7296 gen_load_fpr32(fp, ft);
7297 gen_store_fpr32(fph, fd);
7298 gen_store_fpr32h(fp, fd);
7299 #endif
7300 gen_set_label(l2);
7301 tcg_temp_free_i32(fp);
7302 tcg_temp_free_i32(fph);
7304 opn = "alnv.ps";
7305 break;
7306 case OPC_MADD_S:
7307 check_cop1x(ctx);
7309 TCGv_i32 fp0 = tcg_temp_new_i32();
7310 TCGv_i32 fp1 = tcg_temp_new_i32();
7311 TCGv_i32 fp2 = tcg_temp_new_i32();
7313 gen_load_fpr32(fp0, fs);
7314 gen_load_fpr32(fp1, ft);
7315 gen_load_fpr32(fp2, fr);
7316 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7317 tcg_temp_free_i32(fp0);
7318 tcg_temp_free_i32(fp1);
7319 gen_store_fpr32(fp2, fd);
7320 tcg_temp_free_i32(fp2);
7322 opn = "madd.s";
7323 break;
7324 case OPC_MADD_D:
7325 check_cop1x(ctx);
7326 check_cp1_registers(ctx, fd | fs | ft | fr);
7328 TCGv_i64 fp0 = tcg_temp_new_i64();
7329 TCGv_i64 fp1 = tcg_temp_new_i64();
7330 TCGv_i64 fp2 = tcg_temp_new_i64();
7332 gen_load_fpr64(ctx, fp0, fs);
7333 gen_load_fpr64(ctx, fp1, ft);
7334 gen_load_fpr64(ctx, fp2, fr);
7335 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7336 tcg_temp_free_i64(fp0);
7337 tcg_temp_free_i64(fp1);
7338 gen_store_fpr64(ctx, fp2, fd);
7339 tcg_temp_free_i64(fp2);
7341 opn = "madd.d";
7342 break;
7343 case OPC_MADD_PS:
7344 check_cp1_64bitmode(ctx);
7346 TCGv_i64 fp0 = tcg_temp_new_i64();
7347 TCGv_i64 fp1 = tcg_temp_new_i64();
7348 TCGv_i64 fp2 = tcg_temp_new_i64();
7350 gen_load_fpr64(ctx, fp0, fs);
7351 gen_load_fpr64(ctx, fp1, ft);
7352 gen_load_fpr64(ctx, fp2, fr);
7353 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7354 tcg_temp_free_i64(fp0);
7355 tcg_temp_free_i64(fp1);
7356 gen_store_fpr64(ctx, fp2, fd);
7357 tcg_temp_free_i64(fp2);
7359 opn = "madd.ps";
7360 break;
7361 case OPC_MSUB_S:
7362 check_cop1x(ctx);
7364 TCGv_i32 fp0 = tcg_temp_new_i32();
7365 TCGv_i32 fp1 = tcg_temp_new_i32();
7366 TCGv_i32 fp2 = tcg_temp_new_i32();
7368 gen_load_fpr32(fp0, fs);
7369 gen_load_fpr32(fp1, ft);
7370 gen_load_fpr32(fp2, fr);
7371 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7372 tcg_temp_free_i32(fp0);
7373 tcg_temp_free_i32(fp1);
7374 gen_store_fpr32(fp2, fd);
7375 tcg_temp_free_i32(fp2);
7377 opn = "msub.s";
7378 break;
7379 case OPC_MSUB_D:
7380 check_cop1x(ctx);
7381 check_cp1_registers(ctx, fd | fs | ft | fr);
7383 TCGv_i64 fp0 = tcg_temp_new_i64();
7384 TCGv_i64 fp1 = tcg_temp_new_i64();
7385 TCGv_i64 fp2 = tcg_temp_new_i64();
7387 gen_load_fpr64(ctx, fp0, fs);
7388 gen_load_fpr64(ctx, fp1, ft);
7389 gen_load_fpr64(ctx, fp2, fr);
7390 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7391 tcg_temp_free_i64(fp0);
7392 tcg_temp_free_i64(fp1);
7393 gen_store_fpr64(ctx, fp2, fd);
7394 tcg_temp_free_i64(fp2);
7396 opn = "msub.d";
7397 break;
7398 case OPC_MSUB_PS:
7399 check_cp1_64bitmode(ctx);
7401 TCGv_i64 fp0 = tcg_temp_new_i64();
7402 TCGv_i64 fp1 = tcg_temp_new_i64();
7403 TCGv_i64 fp2 = tcg_temp_new_i64();
7405 gen_load_fpr64(ctx, fp0, fs);
7406 gen_load_fpr64(ctx, fp1, ft);
7407 gen_load_fpr64(ctx, fp2, fr);
7408 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7409 tcg_temp_free_i64(fp0);
7410 tcg_temp_free_i64(fp1);
7411 gen_store_fpr64(ctx, fp2, fd);
7412 tcg_temp_free_i64(fp2);
7414 opn = "msub.ps";
7415 break;
7416 case OPC_NMADD_S:
7417 check_cop1x(ctx);
7419 TCGv_i32 fp0 = tcg_temp_new_i32();
7420 TCGv_i32 fp1 = tcg_temp_new_i32();
7421 TCGv_i32 fp2 = tcg_temp_new_i32();
7423 gen_load_fpr32(fp0, fs);
7424 gen_load_fpr32(fp1, ft);
7425 gen_load_fpr32(fp2, fr);
7426 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7427 tcg_temp_free_i32(fp0);
7428 tcg_temp_free_i32(fp1);
7429 gen_store_fpr32(fp2, fd);
7430 tcg_temp_free_i32(fp2);
7432 opn = "nmadd.s";
7433 break;
7434 case OPC_NMADD_D:
7435 check_cop1x(ctx);
7436 check_cp1_registers(ctx, fd | fs | ft | fr);
7438 TCGv_i64 fp0 = tcg_temp_new_i64();
7439 TCGv_i64 fp1 = tcg_temp_new_i64();
7440 TCGv_i64 fp2 = tcg_temp_new_i64();
7442 gen_load_fpr64(ctx, fp0, fs);
7443 gen_load_fpr64(ctx, fp1, ft);
7444 gen_load_fpr64(ctx, fp2, fr);
7445 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7446 tcg_temp_free_i64(fp0);
7447 tcg_temp_free_i64(fp1);
7448 gen_store_fpr64(ctx, fp2, fd);
7449 tcg_temp_free_i64(fp2);
7451 opn = "nmadd.d";
7452 break;
7453 case OPC_NMADD_PS:
7454 check_cp1_64bitmode(ctx);
7456 TCGv_i64 fp0 = tcg_temp_new_i64();
7457 TCGv_i64 fp1 = tcg_temp_new_i64();
7458 TCGv_i64 fp2 = tcg_temp_new_i64();
7460 gen_load_fpr64(ctx, fp0, fs);
7461 gen_load_fpr64(ctx, fp1, ft);
7462 gen_load_fpr64(ctx, fp2, fr);
7463 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7464 tcg_temp_free_i64(fp0);
7465 tcg_temp_free_i64(fp1);
7466 gen_store_fpr64(ctx, fp2, fd);
7467 tcg_temp_free_i64(fp2);
7469 opn = "nmadd.ps";
7470 break;
7471 case OPC_NMSUB_S:
7472 check_cop1x(ctx);
7474 TCGv_i32 fp0 = tcg_temp_new_i32();
7475 TCGv_i32 fp1 = tcg_temp_new_i32();
7476 TCGv_i32 fp2 = tcg_temp_new_i32();
7478 gen_load_fpr32(fp0, fs);
7479 gen_load_fpr32(fp1, ft);
7480 gen_load_fpr32(fp2, fr);
7481 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7482 tcg_temp_free_i32(fp0);
7483 tcg_temp_free_i32(fp1);
7484 gen_store_fpr32(fp2, fd);
7485 tcg_temp_free_i32(fp2);
7487 opn = "nmsub.s";
7488 break;
7489 case OPC_NMSUB_D:
7490 check_cop1x(ctx);
7491 check_cp1_registers(ctx, fd | fs | ft | fr);
7493 TCGv_i64 fp0 = tcg_temp_new_i64();
7494 TCGv_i64 fp1 = tcg_temp_new_i64();
7495 TCGv_i64 fp2 = tcg_temp_new_i64();
7497 gen_load_fpr64(ctx, fp0, fs);
7498 gen_load_fpr64(ctx, fp1, ft);
7499 gen_load_fpr64(ctx, fp2, fr);
7500 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7501 tcg_temp_free_i64(fp0);
7502 tcg_temp_free_i64(fp1);
7503 gen_store_fpr64(ctx, fp2, fd);
7504 tcg_temp_free_i64(fp2);
7506 opn = "nmsub.d";
7507 break;
7508 case OPC_NMSUB_PS:
7509 check_cp1_64bitmode(ctx);
7511 TCGv_i64 fp0 = tcg_temp_new_i64();
7512 TCGv_i64 fp1 = tcg_temp_new_i64();
7513 TCGv_i64 fp2 = tcg_temp_new_i64();
7515 gen_load_fpr64(ctx, fp0, fs);
7516 gen_load_fpr64(ctx, fp1, ft);
7517 gen_load_fpr64(ctx, fp2, fr);
7518 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7519 tcg_temp_free_i64(fp0);
7520 tcg_temp_free_i64(fp1);
7521 gen_store_fpr64(ctx, fp2, fd);
7522 tcg_temp_free_i64(fp2);
7524 opn = "nmsub.ps";
7525 break;
7526 default:
7527 MIPS_INVAL(opn);
7528 generate_exception (ctx, EXCP_RI);
7529 return;
7531 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7532 fregnames[fs], fregnames[ft]);
7535 /* ISA extensions (ASEs) */
7536 /* MIPS16 extension to MIPS32 */
7537 /* SmartMIPS extension to MIPS32 */
7539 #if defined(TARGET_MIPS64)
7541 /* MDMX extension to MIPS64 */
7543 #endif
7545 static void decode_opc (CPUState *env, DisasContext *ctx)
7547 int32_t offset;
7548 int rs, rt, rd, sa;
7549 uint32_t op, op1, op2;
7550 int16_t imm;
7552 /* make sure instructions are on a word boundary */
7553 if (ctx->pc & 0x3) {
7554 env->CP0_BadVAddr = ctx->pc;
7555 generate_exception(ctx, EXCP_AdEL);
7556 return;
7559 /* Handle blikely not taken case */
7560 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
7561 int l1 = gen_new_label();
7563 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
7564 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7565 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
7566 gen_goto_tb(ctx, 1, ctx->pc + 4);
7567 gen_set_label(l1);
7570 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
7571 tcg_gen_debug_insn_start(ctx->pc);
7573 op = MASK_OP_MAJOR(ctx->opcode);
7574 rs = (ctx->opcode >> 21) & 0x1f;
7575 rt = (ctx->opcode >> 16) & 0x1f;
7576 rd = (ctx->opcode >> 11) & 0x1f;
7577 sa = (ctx->opcode >> 6) & 0x1f;
7578 imm = (int16_t)ctx->opcode;
7579 switch (op) {
7580 case OPC_SPECIAL:
7581 op1 = MASK_SPECIAL(ctx->opcode);
7582 switch (op1) {
7583 case OPC_SLL: /* Shift with immediate */
7584 case OPC_SRA:
7585 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7586 break;
7587 case OPC_SRL:
7588 switch ((ctx->opcode >> 21) & 0x1f) {
7589 case 1:
7590 /* rotr is decoded as srl on non-R2 CPUs */
7591 if (env->insn_flags & ISA_MIPS32R2) {
7592 op1 = OPC_ROTR;
7594 /* Fallthrough */
7595 case 0:
7596 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7597 break;
7598 default:
7599 generate_exception(ctx, EXCP_RI);
7600 break;
7602 break;
7603 case OPC_MOVN: /* Conditional move */
7604 case OPC_MOVZ:
7605 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7606 gen_cond_move(env, op1, rd, rs, rt);
7607 break;
7608 case OPC_ADD ... OPC_SUBU:
7609 gen_arith(env, ctx, op1, rd, rs, rt);
7610 break;
7611 case OPC_SLLV: /* Shifts */
7612 case OPC_SRAV:
7613 gen_shift(env, ctx, op1, rd, rs, rt);
7614 break;
7615 case OPC_SRLV:
7616 switch ((ctx->opcode >> 6) & 0x1f) {
7617 case 1:
7618 /* rotrv is decoded as srlv on non-R2 CPUs */
7619 if (env->insn_flags & ISA_MIPS32R2) {
7620 op1 = OPC_ROTRV;
7622 /* Fallthrough */
7623 case 0:
7624 gen_shift(env, ctx, op1, rd, rs, rt);
7625 break;
7626 default:
7627 generate_exception(ctx, EXCP_RI);
7628 break;
7630 break;
7631 case OPC_SLT: /* Set on less than */
7632 case OPC_SLTU:
7633 gen_slt(env, op1, rd, rs, rt);
7634 break;
7635 case OPC_AND: /* Logic*/
7636 case OPC_OR:
7637 case OPC_NOR:
7638 case OPC_XOR:
7639 gen_logic(env, op1, rd, rs, rt);
7640 break;
7641 case OPC_MULT ... OPC_DIVU:
7642 if (sa) {
7643 check_insn(env, ctx, INSN_VR54XX);
7644 op1 = MASK_MUL_VR54XX(ctx->opcode);
7645 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7646 } else
7647 gen_muldiv(ctx, op1, rs, rt);
7648 break;
7649 case OPC_JR ... OPC_JALR:
7650 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
7651 return;
7652 case OPC_TGE ... OPC_TEQ: /* Traps */
7653 case OPC_TNE:
7654 gen_trap(ctx, op1, rs, rt, -1);
7655 break;
7656 case OPC_MFHI: /* Move from HI/LO */
7657 case OPC_MFLO:
7658 gen_HILO(ctx, op1, rd);
7659 break;
7660 case OPC_MTHI:
7661 case OPC_MTLO: /* Move to HI/LO */
7662 gen_HILO(ctx, op1, rs);
7663 break;
7664 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7665 #ifdef MIPS_STRICT_STANDARD
7666 MIPS_INVAL("PMON / selsl");
7667 generate_exception(ctx, EXCP_RI);
7668 #else
7669 gen_helper_0i(pmon, sa);
7670 #endif
7671 break;
7672 case OPC_SYSCALL:
7673 generate_exception(ctx, EXCP_SYSCALL);
7674 ctx->bstate = BS_STOP;
7675 break;
7676 case OPC_BREAK:
7677 generate_exception(ctx, EXCP_BREAK);
7678 break;
7679 case OPC_SPIM:
7680 #ifdef MIPS_STRICT_STANDARD
7681 MIPS_INVAL("SPIM");
7682 generate_exception(ctx, EXCP_RI);
7683 #else
7684 /* Implemented as RI exception for now. */
7685 MIPS_INVAL("spim (unofficial)");
7686 generate_exception(ctx, EXCP_RI);
7687 #endif
7688 break;
7689 case OPC_SYNC:
7690 /* Treat as NOP. */
7691 break;
7693 case OPC_MOVCI:
7694 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7695 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7696 check_cp1_enabled(ctx);
7697 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7698 (ctx->opcode >> 16) & 1);
7699 } else {
7700 generate_exception_err(ctx, EXCP_CpU, 1);
7702 break;
7704 #if defined(TARGET_MIPS64)
7705 /* MIPS64 specific opcodes */
7706 case OPC_DSLL:
7707 case OPC_DSRA:
7708 case OPC_DSLL32:
7709 case OPC_DSRA32:
7710 check_insn(env, ctx, ISA_MIPS3);
7711 check_mips_64(ctx);
7712 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7713 break;
7714 case OPC_DSRL:
7715 switch ((ctx->opcode >> 21) & 0x1f) {
7716 case 1:
7717 /* drotr is decoded as dsrl on non-R2 CPUs */
7718 if (env->insn_flags & ISA_MIPS32R2) {
7719 op1 = OPC_DROTR;
7721 /* Fallthrough */
7722 case 0:
7723 check_insn(env, ctx, ISA_MIPS3);
7724 check_mips_64(ctx);
7725 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7726 break;
7727 default:
7728 generate_exception(ctx, EXCP_RI);
7729 break;
7731 break;
7732 case OPC_DSRL32:
7733 switch ((ctx->opcode >> 21) & 0x1f) {
7734 case 1:
7735 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
7736 if (env->insn_flags & ISA_MIPS32R2) {
7737 op1 = OPC_DROTR32;
7739 /* Fallthrough */
7740 case 0:
7741 check_insn(env, ctx, ISA_MIPS3);
7742 check_mips_64(ctx);
7743 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7744 break;
7745 default:
7746 generate_exception(ctx, EXCP_RI);
7747 break;
7749 break;
7750 case OPC_DADD ... OPC_DSUBU:
7751 check_insn(env, ctx, ISA_MIPS3);
7752 check_mips_64(ctx);
7753 gen_arith(env, ctx, op1, rd, rs, rt);
7754 break;
7755 case OPC_DSLLV:
7756 case OPC_DSRAV:
7757 check_insn(env, ctx, ISA_MIPS3);
7758 check_mips_64(ctx);
7759 gen_shift(env, ctx, op1, rd, rs, rt);
7760 break;
7761 case OPC_DSRLV:
7762 switch ((ctx->opcode >> 6) & 0x1f) {
7763 case 1:
7764 /* drotrv is decoded as dsrlv on non-R2 CPUs */
7765 if (env->insn_flags & ISA_MIPS32R2) {
7766 op1 = OPC_DROTRV;
7768 /* Fallthrough */
7769 case 0:
7770 check_insn(env, ctx, ISA_MIPS3);
7771 check_mips_64(ctx);
7772 gen_shift(env, ctx, op1, rd, rs, rt);
7773 break;
7774 default:
7775 generate_exception(ctx, EXCP_RI);
7776 break;
7778 break;
7779 case OPC_DMULT ... OPC_DDIVU:
7780 check_insn(env, ctx, ISA_MIPS3);
7781 check_mips_64(ctx);
7782 gen_muldiv(ctx, op1, rs, rt);
7783 break;
7784 #endif
7785 default: /* Invalid */
7786 MIPS_INVAL("special");
7787 generate_exception(ctx, EXCP_RI);
7788 break;
7790 break;
7791 case OPC_SPECIAL2:
7792 op1 = MASK_SPECIAL2(ctx->opcode);
7793 switch (op1) {
7794 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7795 case OPC_MSUB ... OPC_MSUBU:
7796 check_insn(env, ctx, ISA_MIPS32);
7797 gen_muldiv(ctx, op1, rs, rt);
7798 break;
7799 case OPC_MUL:
7800 gen_arith(env, ctx, op1, rd, rs, rt);
7801 break;
7802 case OPC_CLO:
7803 case OPC_CLZ:
7804 check_insn(env, ctx, ISA_MIPS32);
7805 gen_cl(ctx, op1, rd, rs);
7806 break;
7807 case OPC_SDBBP:
7808 /* XXX: not clear which exception should be raised
7809 * when in debug mode...
7811 check_insn(env, ctx, ISA_MIPS32);
7812 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7813 generate_exception(ctx, EXCP_DBp);
7814 } else {
7815 generate_exception(ctx, EXCP_DBp);
7817 /* Treat as NOP. */
7818 break;
7819 #if defined(TARGET_MIPS64)
7820 case OPC_DCLO:
7821 case OPC_DCLZ:
7822 check_insn(env, ctx, ISA_MIPS64);
7823 check_mips_64(ctx);
7824 gen_cl(ctx, op1, rd, rs);
7825 break;
7826 #endif
7827 default: /* Invalid */
7828 MIPS_INVAL("special2");
7829 generate_exception(ctx, EXCP_RI);
7830 break;
7832 break;
7833 case OPC_SPECIAL3:
7834 op1 = MASK_SPECIAL3(ctx->opcode);
7835 switch (op1) {
7836 case OPC_EXT:
7837 case OPC_INS:
7838 check_insn(env, ctx, ISA_MIPS32R2);
7839 gen_bitops(ctx, op1, rt, rs, sa, rd);
7840 break;
7841 case OPC_BSHFL:
7842 check_insn(env, ctx, ISA_MIPS32R2);
7843 op2 = MASK_BSHFL(ctx->opcode);
7844 gen_bshfl(ctx, op2, rt, rd);
7845 break;
7846 case OPC_RDHWR:
7847 check_insn(env, ctx, ISA_MIPS32R2);
7849 TCGv t0 = tcg_temp_new();
7851 switch (rd) {
7852 case 0:
7853 save_cpu_state(ctx, 1);
7854 gen_helper_rdhwr_cpunum(t0);
7855 gen_store_gpr(t0, rt);
7856 break;
7857 case 1:
7858 save_cpu_state(ctx, 1);
7859 gen_helper_rdhwr_synci_step(t0);
7860 gen_store_gpr(t0, rt);
7861 break;
7862 case 2:
7863 save_cpu_state(ctx, 1);
7864 gen_helper_rdhwr_cc(t0);
7865 gen_store_gpr(t0, rt);
7866 break;
7867 case 3:
7868 save_cpu_state(ctx, 1);
7869 gen_helper_rdhwr_ccres(t0);
7870 gen_store_gpr(t0, rt);
7871 break;
7872 case 29:
7873 #if defined(CONFIG_USER_ONLY)
7874 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7875 gen_store_gpr(t0, rt);
7876 break;
7877 #else
7878 /* XXX: Some CPUs implement this in hardware.
7879 Not supported yet. */
7880 #endif
7881 default: /* Invalid */
7882 MIPS_INVAL("rdhwr");
7883 generate_exception(ctx, EXCP_RI);
7884 break;
7886 tcg_temp_free(t0);
7888 break;
7889 case OPC_FORK:
7890 check_insn(env, ctx, ASE_MT);
7892 TCGv t0 = tcg_temp_new();
7893 TCGv t1 = tcg_temp_new();
7895 gen_load_gpr(t0, rt);
7896 gen_load_gpr(t1, rs);
7897 gen_helper_fork(t0, t1);
7898 tcg_temp_free(t0);
7899 tcg_temp_free(t1);
7901 break;
7902 case OPC_YIELD:
7903 check_insn(env, ctx, ASE_MT);
7905 TCGv t0 = tcg_temp_new();
7907 save_cpu_state(ctx, 1);
7908 gen_load_gpr(t0, rs);
7909 gen_helper_yield(t0, t0);
7910 gen_store_gpr(t0, rd);
7911 tcg_temp_free(t0);
7913 break;
7914 #if defined(TARGET_MIPS64)
7915 case OPC_DEXTM ... OPC_DEXT:
7916 case OPC_DINSM ... OPC_DINS:
7917 check_insn(env, ctx, ISA_MIPS64R2);
7918 check_mips_64(ctx);
7919 gen_bitops(ctx, op1, rt, rs, sa, rd);
7920 break;
7921 case OPC_DBSHFL:
7922 check_insn(env, ctx, ISA_MIPS64R2);
7923 check_mips_64(ctx);
7924 op2 = MASK_DBSHFL(ctx->opcode);
7925 gen_bshfl(ctx, op2, rt, rd);
7926 break;
7927 #endif
7928 default: /* Invalid */
7929 MIPS_INVAL("special3");
7930 generate_exception(ctx, EXCP_RI);
7931 break;
7933 break;
7934 case OPC_REGIMM:
7935 op1 = MASK_REGIMM(ctx->opcode);
7936 switch (op1) {
7937 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7938 case OPC_BLTZAL ... OPC_BGEZALL:
7939 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
7940 return;
7941 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7942 case OPC_TNEI:
7943 gen_trap(ctx, op1, rs, -1, imm);
7944 break;
7945 case OPC_SYNCI:
7946 check_insn(env, ctx, ISA_MIPS32R2);
7947 /* Treat as NOP. */
7948 break;
7949 default: /* Invalid */
7950 MIPS_INVAL("regimm");
7951 generate_exception(ctx, EXCP_RI);
7952 break;
7954 break;
7955 case OPC_CP0:
7956 check_cp0_enabled(ctx);
7957 op1 = MASK_CP0(ctx->opcode);
7958 switch (op1) {
7959 case OPC_MFC0:
7960 case OPC_MTC0:
7961 case OPC_MFTR:
7962 case OPC_MTTR:
7963 #if defined(TARGET_MIPS64)
7964 case OPC_DMFC0:
7965 case OPC_DMTC0:
7966 #endif
7967 #ifndef CONFIG_USER_ONLY
7968 gen_cp0(env, ctx, op1, rt, rd);
7969 #endif /* !CONFIG_USER_ONLY */
7970 break;
7971 case OPC_C0_FIRST ... OPC_C0_LAST:
7972 #ifndef CONFIG_USER_ONLY
7973 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
7974 #endif /* !CONFIG_USER_ONLY */
7975 break;
7976 case OPC_MFMC0:
7977 #ifndef CONFIG_USER_ONLY
7979 TCGv t0 = tcg_temp_new();
7981 op2 = MASK_MFMC0(ctx->opcode);
7982 switch (op2) {
7983 case OPC_DMT:
7984 check_insn(env, ctx, ASE_MT);
7985 gen_helper_dmt(t0, t0);
7986 gen_store_gpr(t0, rt);
7987 break;
7988 case OPC_EMT:
7989 check_insn(env, ctx, ASE_MT);
7990 gen_helper_emt(t0, t0);
7991 gen_store_gpr(t0, rt);
7992 break;
7993 case OPC_DVPE:
7994 check_insn(env, ctx, ASE_MT);
7995 gen_helper_dvpe(t0, t0);
7996 gen_store_gpr(t0, rt);
7997 break;
7998 case OPC_EVPE:
7999 check_insn(env, ctx, ASE_MT);
8000 gen_helper_evpe(t0, t0);
8001 gen_store_gpr(t0, rt);
8002 break;
8003 case OPC_DI:
8004 check_insn(env, ctx, ISA_MIPS32R2);
8005 save_cpu_state(ctx, 1);
8006 gen_helper_di(t0);
8007 gen_store_gpr(t0, rt);
8008 /* Stop translation as we may have switched the execution mode */
8009 ctx->bstate = BS_STOP;
8010 break;
8011 case OPC_EI:
8012 check_insn(env, ctx, ISA_MIPS32R2);
8013 save_cpu_state(ctx, 1);
8014 gen_helper_ei(t0);
8015 gen_store_gpr(t0, rt);
8016 /* Stop translation as we may have switched the execution mode */
8017 ctx->bstate = BS_STOP;
8018 break;
8019 default: /* Invalid */
8020 MIPS_INVAL("mfmc0");
8021 generate_exception(ctx, EXCP_RI);
8022 break;
8024 tcg_temp_free(t0);
8026 #endif /* !CONFIG_USER_ONLY */
8027 break;
8028 case OPC_RDPGPR:
8029 check_insn(env, ctx, ISA_MIPS32R2);
8030 gen_load_srsgpr(rt, rd);
8031 break;
8032 case OPC_WRPGPR:
8033 check_insn(env, ctx, ISA_MIPS32R2);
8034 gen_store_srsgpr(rt, rd);
8035 break;
8036 default:
8037 MIPS_INVAL("cp0");
8038 generate_exception(ctx, EXCP_RI);
8039 break;
8041 break;
8042 case OPC_ADDI: /* Arithmetic with immediate opcode */
8043 case OPC_ADDIU:
8044 gen_arith_imm(env, ctx, op, rt, rs, imm);
8045 break;
8046 case OPC_SLTI: /* Set on less than with immediate opcode */
8047 case OPC_SLTIU:
8048 gen_slt_imm(env, op, rt, rs, imm);
8049 break;
8050 case OPC_ANDI: /* Arithmetic with immediate opcode */
8051 case OPC_LUI:
8052 case OPC_ORI:
8053 case OPC_XORI:
8054 gen_logic_imm(env, op, rt, rs, imm);
8055 break;
8056 case OPC_J ... OPC_JAL: /* Jump */
8057 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8058 gen_compute_branch(ctx, op, 4, rs, rt, offset);
8059 return;
8060 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8061 case OPC_BEQL ... OPC_BGTZL:
8062 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
8063 return;
8064 case OPC_LB ... OPC_LWR: /* Load and stores */
8065 case OPC_SB ... OPC_SW:
8066 case OPC_SWR:
8067 case OPC_LL:
8068 gen_ldst(ctx, op, rt, rs, imm);
8069 break;
8070 case OPC_SC:
8071 gen_st_cond(ctx, op, rt, rs, imm);
8072 break;
8073 case OPC_CACHE:
8074 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
8075 /* Treat as NOP. */
8076 break;
8077 case OPC_PREF:
8078 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
8079 /* Treat as NOP. */
8080 break;
8082 /* Floating point (COP1). */
8083 case OPC_LWC1:
8084 case OPC_LDC1:
8085 case OPC_SWC1:
8086 case OPC_SDC1:
8087 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8088 check_cp1_enabled(ctx);
8089 gen_flt_ldst(ctx, op, rt, rs, imm);
8090 } else {
8091 generate_exception_err(ctx, EXCP_CpU, 1);
8093 break;
8095 case OPC_CP1:
8096 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8097 check_cp1_enabled(ctx);
8098 op1 = MASK_CP1(ctx->opcode);
8099 switch (op1) {
8100 case OPC_MFHC1:
8101 case OPC_MTHC1:
8102 check_insn(env, ctx, ISA_MIPS32R2);
8103 case OPC_MFC1:
8104 case OPC_CFC1:
8105 case OPC_MTC1:
8106 case OPC_CTC1:
8107 gen_cp1(ctx, op1, rt, rd);
8108 break;
8109 #if defined(TARGET_MIPS64)
8110 case OPC_DMFC1:
8111 case OPC_DMTC1:
8112 check_insn(env, ctx, ISA_MIPS3);
8113 gen_cp1(ctx, op1, rt, rd);
8114 break;
8115 #endif
8116 case OPC_BC1ANY2:
8117 case OPC_BC1ANY4:
8118 check_cop1x(ctx);
8119 check_insn(env, ctx, ASE_MIPS3D);
8120 /* fall through */
8121 case OPC_BC1:
8122 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
8123 (rt >> 2) & 0x7, imm << 2);
8124 return;
8125 case OPC_S_FMT:
8126 case OPC_D_FMT:
8127 case OPC_W_FMT:
8128 case OPC_L_FMT:
8129 case OPC_PS_FMT:
8130 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8131 (imm >> 8) & 0x7);
8132 break;
8133 default:
8134 MIPS_INVAL("cp1");
8135 generate_exception (ctx, EXCP_RI);
8136 break;
8138 } else {
8139 generate_exception_err(ctx, EXCP_CpU, 1);
8141 break;
8143 /* COP2. */
8144 case OPC_LWC2:
8145 case OPC_LDC2:
8146 case OPC_SWC2:
8147 case OPC_SDC2:
8148 case OPC_CP2:
8149 /* COP2: Not implemented. */
8150 generate_exception_err(ctx, EXCP_CpU, 2);
8151 break;
8153 case OPC_CP3:
8154 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8155 check_cp1_enabled(ctx);
8156 op1 = MASK_CP3(ctx->opcode);
8157 switch (op1) {
8158 case OPC_LWXC1:
8159 case OPC_LDXC1:
8160 case OPC_LUXC1:
8161 case OPC_SWXC1:
8162 case OPC_SDXC1:
8163 case OPC_SUXC1:
8164 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
8165 break;
8166 case OPC_PREFX:
8167 /* Treat as NOP. */
8168 break;
8169 case OPC_ALNV_PS:
8170 case OPC_MADD_S:
8171 case OPC_MADD_D:
8172 case OPC_MADD_PS:
8173 case OPC_MSUB_S:
8174 case OPC_MSUB_D:
8175 case OPC_MSUB_PS:
8176 case OPC_NMADD_S:
8177 case OPC_NMADD_D:
8178 case OPC_NMADD_PS:
8179 case OPC_NMSUB_S:
8180 case OPC_NMSUB_D:
8181 case OPC_NMSUB_PS:
8182 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8183 break;
8184 default:
8185 MIPS_INVAL("cp3");
8186 generate_exception (ctx, EXCP_RI);
8187 break;
8189 } else {
8190 generate_exception_err(ctx, EXCP_CpU, 1);
8192 break;
8194 #if defined(TARGET_MIPS64)
8195 /* MIPS64 opcodes */
8196 case OPC_LWU:
8197 case OPC_LDL ... OPC_LDR:
8198 case OPC_SDL ... OPC_SDR:
8199 case OPC_LLD:
8200 case OPC_LD:
8201 case OPC_SD:
8202 check_insn(env, ctx, ISA_MIPS3);
8203 check_mips_64(ctx);
8204 gen_ldst(ctx, op, rt, rs, imm);
8205 break;
8206 case OPC_SCD:
8207 check_insn(env, ctx, ISA_MIPS3);
8208 check_mips_64(ctx);
8209 gen_st_cond(ctx, op, rt, rs, imm);
8210 break;
8211 case OPC_DADDI:
8212 case OPC_DADDIU:
8213 check_insn(env, ctx, ISA_MIPS3);
8214 check_mips_64(ctx);
8215 gen_arith_imm(env, ctx, op, rt, rs, imm);
8216 break;
8217 #endif
8218 case OPC_JALX:
8219 check_insn(env, ctx, ASE_MIPS16);
8220 /* MIPS16: Not implemented. */
8221 case OPC_MDMX:
8222 check_insn(env, ctx, ASE_MDMX);
8223 /* MDMX: Not implemented. */
8224 default: /* Invalid */
8225 MIPS_INVAL("major opcode");
8226 generate_exception(ctx, EXCP_RI);
8227 break;
8229 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8230 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8231 /* Branches completion */
8232 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8233 ctx->bstate = BS_BRANCH;
8234 save_cpu_state(ctx, 0);
8235 /* FIXME: Need to clear can_do_io. */
8236 switch (hflags) {
8237 case MIPS_HFLAG_B:
8238 /* unconditional branch */
8239 MIPS_DEBUG("unconditional branch");
8240 gen_goto_tb(ctx, 0, ctx->btarget);
8241 break;
8242 case MIPS_HFLAG_BL:
8243 /* blikely taken case */
8244 MIPS_DEBUG("blikely branch taken");
8245 gen_goto_tb(ctx, 0, ctx->btarget);
8246 break;
8247 case MIPS_HFLAG_BC:
8248 /* Conditional branch */
8249 MIPS_DEBUG("conditional branch");
8251 int l1 = gen_new_label();
8253 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8254 gen_goto_tb(ctx, 1, ctx->pc + 4);
8255 gen_set_label(l1);
8256 gen_goto_tb(ctx, 0, ctx->btarget);
8258 break;
8259 case MIPS_HFLAG_BR:
8260 /* unconditional branch to register */
8261 MIPS_DEBUG("branch to register");
8262 tcg_gen_mov_tl(cpu_PC, btarget);
8263 if (ctx->singlestep_enabled) {
8264 save_cpu_state(ctx, 0);
8265 gen_helper_0i(raise_exception, EXCP_DEBUG);
8267 tcg_gen_exit_tb(0);
8268 break;
8269 default:
8270 MIPS_DEBUG("unknown branch");
8271 break;
8276 static inline void
8277 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8278 int search_pc)
8280 DisasContext ctx;
8281 target_ulong pc_start;
8282 uint16_t *gen_opc_end;
8283 CPUBreakpoint *bp;
8284 int j, lj = -1;
8285 int num_insns;
8286 int max_insns;
8288 if (search_pc)
8289 qemu_log("search pc %d\n", search_pc);
8291 pc_start = tb->pc;
8292 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8293 ctx.pc = pc_start;
8294 ctx.saved_pc = -1;
8295 ctx.singlestep_enabled = env->singlestep_enabled;
8296 ctx.tb = tb;
8297 ctx.bstate = BS_NONE;
8298 /* Restore delay slot state from the tb context. */
8299 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
8300 restore_cpu_state(env, &ctx);
8301 #ifdef CONFIG_USER_ONLY
8302 ctx.mem_idx = MIPS_HFLAG_UM;
8303 #else
8304 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
8305 #endif
8306 num_insns = 0;
8307 max_insns = tb->cflags & CF_COUNT_MASK;
8308 if (max_insns == 0)
8309 max_insns = CF_COUNT_MASK;
8310 #ifdef DEBUG_DISAS
8311 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
8312 /* FIXME: This may print out stale hflags from env... */
8313 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
8314 #endif
8315 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
8316 gen_icount_start();
8317 while (ctx.bstate == BS_NONE) {
8318 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8319 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
8320 if (bp->pc == ctx.pc) {
8321 save_cpu_state(&ctx, 1);
8322 ctx.bstate = BS_BRANCH;
8323 gen_helper_0i(raise_exception, EXCP_DEBUG);
8324 /* Include the breakpoint location or the tb won't
8325 * be flushed when it must be. */
8326 ctx.pc += 4;
8327 goto done_generating;
8332 if (search_pc) {
8333 j = gen_opc_ptr - gen_opc_buf;
8334 if (lj < j) {
8335 lj++;
8336 while (lj < j)
8337 gen_opc_instr_start[lj++] = 0;
8339 gen_opc_pc[lj] = ctx.pc;
8340 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8341 gen_opc_instr_start[lj] = 1;
8342 gen_opc_icount[lj] = num_insns;
8344 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8345 gen_io_start();
8346 ctx.opcode = ldl_code(ctx.pc);
8347 decode_opc(env, &ctx);
8348 ctx.pc += 4;
8349 num_insns++;
8351 /* Execute a branch and its delay slot as a single instruction.
8352 This is what GDB expects and is consistent with what the
8353 hardware does (e.g. if a delay slot instruction faults, the
8354 reported PC is the PC of the branch). */
8355 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
8356 break;
8358 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8359 break;
8361 if (gen_opc_ptr >= gen_opc_end)
8362 break;
8364 if (num_insns >= max_insns)
8365 break;
8367 if (singlestep)
8368 break;
8370 if (tb->cflags & CF_LAST_IO)
8371 gen_io_end();
8372 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
8373 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
8374 gen_helper_0i(raise_exception, EXCP_DEBUG);
8375 } else {
8376 switch (ctx.bstate) {
8377 case BS_STOP:
8378 gen_helper_interrupt_restart();
8379 gen_goto_tb(&ctx, 0, ctx.pc);
8380 break;
8381 case BS_NONE:
8382 save_cpu_state(&ctx, 0);
8383 gen_goto_tb(&ctx, 0, ctx.pc);
8384 break;
8385 case BS_EXCP:
8386 gen_helper_interrupt_restart();
8387 tcg_gen_exit_tb(0);
8388 break;
8389 case BS_BRANCH:
8390 default:
8391 break;
8394 done_generating:
8395 gen_icount_end(tb, num_insns);
8396 *gen_opc_ptr = INDEX_op_end;
8397 if (search_pc) {
8398 j = gen_opc_ptr - gen_opc_buf;
8399 lj++;
8400 while (lj <= j)
8401 gen_opc_instr_start[lj++] = 0;
8402 } else {
8403 tb->size = ctx.pc - pc_start;
8404 tb->icount = num_insns;
8406 #ifdef DEBUG_DISAS
8407 LOG_DISAS("\n");
8408 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8409 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8410 log_target_disas(pc_start, ctx.pc - pc_start, 0);
8411 qemu_log("\n");
8413 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8414 #endif
8417 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
8419 gen_intermediate_code_internal(env, tb, 0);
8422 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
8424 gen_intermediate_code_internal(env, tb, 1);
8427 static void fpu_dump_state(CPUState *env, FILE *f,
8428 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8429 int flags)
8431 int i;
8432 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
8434 #define printfpr(fp) \
8435 do { \
8436 if (is_fpu64) \
8437 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8438 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8439 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8440 else { \
8441 fpr_t tmp; \
8442 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8443 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8444 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8445 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8446 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8448 } while(0)
8451 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
8452 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8453 get_float_exception_flags(&env->active_fpu.fp_status));
8454 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8455 fpu_fprintf(f, "%3s: ", fregnames[i]);
8456 printfpr(&env->active_fpu.fpr[i]);
8459 #undef printfpr
8462 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8463 /* Debug help: The architecture requires 32bit code to maintain proper
8464 sign-extended values on 64bit machines. */
8466 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8468 static void
8469 cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8470 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8471 int flags)
8473 int i;
8475 if (!SIGN_EXT_P(env->active_tc.PC))
8476 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8477 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8478 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8479 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8480 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
8481 if (!SIGN_EXT_P(env->btarget))
8482 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
8484 for (i = 0; i < 32; i++) {
8485 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8486 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
8489 if (!SIGN_EXT_P(env->CP0_EPC))
8490 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
8491 if (!SIGN_EXT_P(env->lladdr))
8492 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
8494 #endif
8496 void cpu_dump_state (CPUState *env, FILE *f,
8497 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8498 int flags)
8500 int i;
8502 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",
8503 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8504 env->hflags, env->btarget, env->bcond);
8505 for (i = 0; i < 32; i++) {
8506 if ((i & 3) == 0)
8507 cpu_fprintf(f, "GPR%02d:", i);
8508 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
8509 if ((i & 3) == 3)
8510 cpu_fprintf(f, "\n");
8513 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
8514 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
8515 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
8516 env->CP0_Config0, env->CP0_Config1, env->lladdr);
8517 if (env->hflags & MIPS_HFLAG_FPU)
8518 fpu_dump_state(env, f, cpu_fprintf, flags);
8519 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
8520 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8521 #endif
8524 static void mips_tcg_init(void)
8526 int i;
8527 static int inited;
8529 /* Initialize various static tables. */
8530 if (inited)
8531 return;
8533 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
8534 TCGV_UNUSED(cpu_gpr[0]);
8535 for (i = 1; i < 32; i++)
8536 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
8537 offsetof(CPUState, active_tc.gpr[i]),
8538 regnames[i]);
8539 cpu_PC = tcg_global_mem_new(TCG_AREG0,
8540 offsetof(CPUState, active_tc.PC), "PC");
8541 for (i = 0; i < MIPS_DSP_ACC; i++) {
8542 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
8543 offsetof(CPUState, active_tc.HI[i]),
8544 regnames_HI[i]);
8545 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
8546 offsetof(CPUState, active_tc.LO[i]),
8547 regnames_LO[i]);
8548 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
8549 offsetof(CPUState, active_tc.ACX[i]),
8550 regnames_ACX[i]);
8552 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
8553 offsetof(CPUState, active_tc.DSPControl),
8554 "DSPControl");
8555 bcond = tcg_global_mem_new(TCG_AREG0,
8556 offsetof(CPUState, bcond), "bcond");
8557 btarget = tcg_global_mem_new(TCG_AREG0,
8558 offsetof(CPUState, btarget), "btarget");
8559 hflags = tcg_global_mem_new_i32(TCG_AREG0,
8560 offsetof(CPUState, hflags), "hflags");
8562 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
8563 offsetof(CPUState, active_fpu.fcr0),
8564 "fcr0");
8565 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
8566 offsetof(CPUState, active_fpu.fcr31),
8567 "fcr31");
8569 /* register helpers */
8570 #define GEN_HELPER 2
8571 #include "helper.h"
8573 inited = 1;
8576 #include "translate_init.c"
8578 CPUMIPSState *cpu_mips_init (const char *cpu_model)
8580 CPUMIPSState *env;
8581 const mips_def_t *def;
8583 def = cpu_mips_find_by_name(cpu_model);
8584 if (!def)
8585 return NULL;
8586 env = qemu_mallocz(sizeof(CPUMIPSState));
8587 env->cpu_model = def;
8588 env->cpu_model_str = cpu_model;
8590 cpu_exec_init(env);
8591 #ifndef CONFIG_USER_ONLY
8592 mmu_init(env, def);
8593 #endif
8594 fpu_init(env, def);
8595 mvp_init(env, def);
8596 mips_tcg_init();
8597 cpu_reset(env);
8598 qemu_init_vcpu(env);
8599 return env;
8602 void cpu_reset (CPUMIPSState *env)
8604 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
8605 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
8606 log_cpu_state(env, 0);
8609 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8610 tlb_flush(env, 1);
8612 /* Reset registers to their default values */
8613 env->CP0_PRid = env->cpu_model->CP0_PRid;
8614 env->CP0_Config0 = env->cpu_model->CP0_Config0;
8615 #ifdef TARGET_WORDS_BIGENDIAN
8616 env->CP0_Config0 |= (1 << CP0C0_BE);
8617 #endif
8618 env->CP0_Config1 = env->cpu_model->CP0_Config1;
8619 env->CP0_Config2 = env->cpu_model->CP0_Config2;
8620 env->CP0_Config3 = env->cpu_model->CP0_Config3;
8621 env->CP0_Config6 = env->cpu_model->CP0_Config6;
8622 env->CP0_Config7 = env->cpu_model->CP0_Config7;
8623 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
8624 << env->cpu_model->CP0_LLAddr_shift;
8625 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
8626 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
8627 env->CCRes = env->cpu_model->CCRes;
8628 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
8629 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
8630 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
8631 env->current_tc = 0;
8632 env->SEGBITS = env->cpu_model->SEGBITS;
8633 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
8634 #if defined(TARGET_MIPS64)
8635 if (env->cpu_model->insn_flags & ISA_MIPS3) {
8636 env->SEGMask |= 3ULL << 62;
8638 #endif
8639 env->PABITS = env->cpu_model->PABITS;
8640 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
8641 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
8642 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
8643 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
8644 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
8645 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
8646 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
8647 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
8648 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
8649 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
8650 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
8651 env->insn_flags = env->cpu_model->insn_flags;
8653 #if defined(CONFIG_USER_ONLY)
8654 env->hflags = MIPS_HFLAG_UM;
8655 /* Enable access to the SYNCI_Step register. */
8656 env->CP0_HWREna |= (1 << 1);
8657 #else
8658 if (env->hflags & MIPS_HFLAG_BMASK) {
8659 /* If the exception was raised from a delay slot,
8660 come back to the jump. */
8661 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8662 } else {
8663 env->CP0_ErrorEPC = env->active_tc.PC;
8665 env->active_tc.PC = (int32_t)0xBFC00000;
8666 env->CP0_Random = env->tlb->nb_tlb - 1;
8667 env->tlb->tlb_in_use = env->tlb->nb_tlb;
8668 env->CP0_Wired = 0;
8669 /* SMP not implemented */
8670 env->CP0_EBase = 0x80000000;
8671 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8672 /* vectored interrupts not implemented, timer on int 7,
8673 no performance counters. */
8674 env->CP0_IntCtl = 0xe0000000;
8676 int i;
8678 for (i = 0; i < 7; i++) {
8679 env->CP0_WatchLo[i] = 0;
8680 env->CP0_WatchHi[i] = 0x80000000;
8682 env->CP0_WatchLo[7] = 0;
8683 env->CP0_WatchHi[7] = 0;
8685 /* Count register increments in debug mode, EJTAG version 1 */
8686 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8687 env->hflags = MIPS_HFLAG_CP0;
8688 #endif
8689 #if defined(TARGET_MIPS64)
8690 if (env->cpu_model->insn_flags & ISA_MIPS3) {
8691 env->hflags |= MIPS_HFLAG_64;
8693 #endif
8694 env->exception_index = EXCP_NONE;
8697 void gen_pc_load(CPUState *env, TranslationBlock *tb,
8698 unsigned long searched_pc, int pc_pos, void *puc)
8700 env->active_tc.PC = gen_opc_pc[pc_pos];
8701 env->hflags &= ~MIPS_HFLAG_BMASK;
8702 env->hflags |= gen_opc_hflags[pc_pos];