More TCG updates for CRIS
[qemu/qemu-JZ.git] / target-mips / translate.c
blobeb8e09e09e21a9364f68e23e05adc85fe48e8e7d
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <inttypes.h>
29 #include "cpu.h"
30 #include "exec-all.h"
31 #include "disas.h"
32 #include "tcg-op.h"
33 #include "qemu-common.h"
35 //#define MIPS_DEBUG_DISAS
36 //#define MIPS_DEBUG_SIGN_EXTENSIONS
37 //#define MIPS_SINGLE_STEP
39 /* MIPS major opcodes */
40 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
42 enum {
43 /* indirect opcode tables */
44 OPC_SPECIAL = (0x00 << 26),
45 OPC_REGIMM = (0x01 << 26),
46 OPC_CP0 = (0x10 << 26),
47 OPC_CP1 = (0x11 << 26),
48 OPC_CP2 = (0x12 << 26),
49 OPC_CP3 = (0x13 << 26),
50 OPC_SPECIAL2 = (0x1C << 26),
51 OPC_SPECIAL3 = (0x1F << 26),
52 /* arithmetic with immediate */
53 OPC_ADDI = (0x08 << 26),
54 OPC_ADDIU = (0x09 << 26),
55 OPC_SLTI = (0x0A << 26),
56 OPC_SLTIU = (0x0B << 26),
57 OPC_ANDI = (0x0C << 26),
58 OPC_ORI = (0x0D << 26),
59 OPC_XORI = (0x0E << 26),
60 OPC_LUI = (0x0F << 26),
61 OPC_DADDI = (0x18 << 26),
62 OPC_DADDIU = (0x19 << 26),
63 /* Jump and branches */
64 OPC_J = (0x02 << 26),
65 OPC_JAL = (0x03 << 26),
66 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
67 OPC_BEQL = (0x14 << 26),
68 OPC_BNE = (0x05 << 26),
69 OPC_BNEL = (0x15 << 26),
70 OPC_BLEZ = (0x06 << 26),
71 OPC_BLEZL = (0x16 << 26),
72 OPC_BGTZ = (0x07 << 26),
73 OPC_BGTZL = (0x17 << 26),
74 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
75 /* Load and stores */
76 OPC_LDL = (0x1A << 26),
77 OPC_LDR = (0x1B << 26),
78 OPC_LB = (0x20 << 26),
79 OPC_LH = (0x21 << 26),
80 OPC_LWL = (0x22 << 26),
81 OPC_LW = (0x23 << 26),
82 OPC_LBU = (0x24 << 26),
83 OPC_LHU = (0x25 << 26),
84 OPC_LWR = (0x26 << 26),
85 OPC_LWU = (0x27 << 26),
86 OPC_SB = (0x28 << 26),
87 OPC_SH = (0x29 << 26),
88 OPC_SWL = (0x2A << 26),
89 OPC_SW = (0x2B << 26),
90 OPC_SDL = (0x2C << 26),
91 OPC_SDR = (0x2D << 26),
92 OPC_SWR = (0x2E << 26),
93 OPC_LL = (0x30 << 26),
94 OPC_LLD = (0x34 << 26),
95 OPC_LD = (0x37 << 26),
96 OPC_SC = (0x38 << 26),
97 OPC_SCD = (0x3C << 26),
98 OPC_SD = (0x3F << 26),
99 /* Floating point load/store */
100 OPC_LWC1 = (0x31 << 26),
101 OPC_LWC2 = (0x32 << 26),
102 OPC_LDC1 = (0x35 << 26),
103 OPC_LDC2 = (0x36 << 26),
104 OPC_SWC1 = (0x39 << 26),
105 OPC_SWC2 = (0x3A << 26),
106 OPC_SDC1 = (0x3D << 26),
107 OPC_SDC2 = (0x3E << 26),
108 /* MDMX ASE specific */
109 OPC_MDMX = (0x1E << 26),
110 /* Cache and prefetch */
111 OPC_CACHE = (0x2F << 26),
112 OPC_PREF = (0x33 << 26),
113 /* Reserved major opcode */
114 OPC_MAJOR3B_RESERVED = (0x3B << 26),
117 /* MIPS special opcodes */
118 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
120 enum {
121 /* Shifts */
122 OPC_SLL = 0x00 | OPC_SPECIAL,
123 /* NOP is SLL r0, r0, 0 */
124 /* SSNOP is SLL r0, r0, 1 */
125 /* EHB is SLL r0, r0, 3 */
126 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
127 OPC_SRA = 0x03 | OPC_SPECIAL,
128 OPC_SLLV = 0x04 | OPC_SPECIAL,
129 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
130 OPC_SRAV = 0x07 | OPC_SPECIAL,
131 OPC_DSLLV = 0x14 | OPC_SPECIAL,
132 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
133 OPC_DSRAV = 0x17 | OPC_SPECIAL,
134 OPC_DSLL = 0x38 | OPC_SPECIAL,
135 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
136 OPC_DSRA = 0x3B | OPC_SPECIAL,
137 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
138 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
139 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
140 /* Multiplication / division */
141 OPC_MULT = 0x18 | OPC_SPECIAL,
142 OPC_MULTU = 0x19 | OPC_SPECIAL,
143 OPC_DIV = 0x1A | OPC_SPECIAL,
144 OPC_DIVU = 0x1B | OPC_SPECIAL,
145 OPC_DMULT = 0x1C | OPC_SPECIAL,
146 OPC_DMULTU = 0x1D | OPC_SPECIAL,
147 OPC_DDIV = 0x1E | OPC_SPECIAL,
148 OPC_DDIVU = 0x1F | OPC_SPECIAL,
149 /* 2 registers arithmetic / logic */
150 OPC_ADD = 0x20 | OPC_SPECIAL,
151 OPC_ADDU = 0x21 | OPC_SPECIAL,
152 OPC_SUB = 0x22 | OPC_SPECIAL,
153 OPC_SUBU = 0x23 | OPC_SPECIAL,
154 OPC_AND = 0x24 | OPC_SPECIAL,
155 OPC_OR = 0x25 | OPC_SPECIAL,
156 OPC_XOR = 0x26 | OPC_SPECIAL,
157 OPC_NOR = 0x27 | OPC_SPECIAL,
158 OPC_SLT = 0x2A | OPC_SPECIAL,
159 OPC_SLTU = 0x2B | OPC_SPECIAL,
160 OPC_DADD = 0x2C | OPC_SPECIAL,
161 OPC_DADDU = 0x2D | OPC_SPECIAL,
162 OPC_DSUB = 0x2E | OPC_SPECIAL,
163 OPC_DSUBU = 0x2F | OPC_SPECIAL,
164 /* Jumps */
165 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
166 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
167 /* Traps */
168 OPC_TGE = 0x30 | OPC_SPECIAL,
169 OPC_TGEU = 0x31 | OPC_SPECIAL,
170 OPC_TLT = 0x32 | OPC_SPECIAL,
171 OPC_TLTU = 0x33 | OPC_SPECIAL,
172 OPC_TEQ = 0x34 | OPC_SPECIAL,
173 OPC_TNE = 0x36 | OPC_SPECIAL,
174 /* HI / LO registers load & stores */
175 OPC_MFHI = 0x10 | OPC_SPECIAL,
176 OPC_MTHI = 0x11 | OPC_SPECIAL,
177 OPC_MFLO = 0x12 | OPC_SPECIAL,
178 OPC_MTLO = 0x13 | OPC_SPECIAL,
179 /* Conditional moves */
180 OPC_MOVZ = 0x0A | OPC_SPECIAL,
181 OPC_MOVN = 0x0B | OPC_SPECIAL,
183 OPC_MOVCI = 0x01 | OPC_SPECIAL,
185 /* Special */
186 OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */
187 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
188 OPC_BREAK = 0x0D | OPC_SPECIAL,
189 OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */
190 OPC_SYNC = 0x0F | OPC_SPECIAL,
192 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
193 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
194 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
195 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
196 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
197 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
198 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
201 /* Multiplication variants of the vr54xx. */
202 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
204 enum {
205 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
206 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
207 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
208 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
209 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
210 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
211 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
212 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
213 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
214 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
215 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
216 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
217 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
218 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
221 /* REGIMM (rt field) opcodes */
222 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
224 enum {
225 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
226 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
227 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
228 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
229 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
230 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
231 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
232 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
233 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
234 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
235 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
236 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
237 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
238 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
239 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
242 /* Special2 opcodes */
243 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
245 enum {
246 /* Multiply & xxx operations */
247 OPC_MADD = 0x00 | OPC_SPECIAL2,
248 OPC_MADDU = 0x01 | OPC_SPECIAL2,
249 OPC_MUL = 0x02 | OPC_SPECIAL2,
250 OPC_MSUB = 0x04 | OPC_SPECIAL2,
251 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
252 /* Misc */
253 OPC_CLZ = 0x20 | OPC_SPECIAL2,
254 OPC_CLO = 0x21 | OPC_SPECIAL2,
255 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
256 OPC_DCLO = 0x25 | OPC_SPECIAL2,
257 /* Special */
258 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
261 /* Special3 opcodes */
262 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
264 enum {
265 OPC_EXT = 0x00 | OPC_SPECIAL3,
266 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
267 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
268 OPC_DEXT = 0x03 | OPC_SPECIAL3,
269 OPC_INS = 0x04 | OPC_SPECIAL3,
270 OPC_DINSM = 0x05 | OPC_SPECIAL3,
271 OPC_DINSU = 0x06 | OPC_SPECIAL3,
272 OPC_DINS = 0x07 | OPC_SPECIAL3,
273 OPC_FORK = 0x08 | OPC_SPECIAL3,
274 OPC_YIELD = 0x09 | OPC_SPECIAL3,
275 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
276 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
277 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
280 /* BSHFL opcodes */
281 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
283 enum {
284 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
285 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
286 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
289 /* DBSHFL opcodes */
290 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
292 enum {
293 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
294 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
297 /* Coprocessor 0 (rs field) */
298 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
300 enum {
301 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
302 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
303 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
304 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
305 OPC_MFTR = (0x08 << 21) | OPC_CP0,
306 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
307 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
308 OPC_MTTR = (0x0C << 21) | OPC_CP0,
309 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
310 OPC_C0 = (0x10 << 21) | OPC_CP0,
311 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
312 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
315 /* MFMC0 opcodes */
316 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
318 enum {
319 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
320 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
321 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
322 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
323 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
324 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
327 /* Coprocessor 0 (with rs == C0) */
328 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
330 enum {
331 OPC_TLBR = 0x01 | OPC_C0,
332 OPC_TLBWI = 0x02 | OPC_C0,
333 OPC_TLBWR = 0x06 | OPC_C0,
334 OPC_TLBP = 0x08 | OPC_C0,
335 OPC_RFE = 0x10 | OPC_C0,
336 OPC_ERET = 0x18 | OPC_C0,
337 OPC_DERET = 0x1F | OPC_C0,
338 OPC_WAIT = 0x20 | OPC_C0,
341 /* Coprocessor 1 (rs field) */
342 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
344 enum {
345 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
346 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
347 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
348 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
349 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
350 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
351 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
352 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
353 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
354 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
355 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
356 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
357 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
358 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
359 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
360 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
361 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
362 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
365 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
366 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
368 enum {
369 OPC_BC1F = (0x00 << 16) | OPC_BC1,
370 OPC_BC1T = (0x01 << 16) | OPC_BC1,
371 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
372 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
375 enum {
376 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
377 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
380 enum {
381 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
382 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
385 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
387 enum {
388 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
389 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
390 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
391 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
392 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
393 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
394 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
395 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
396 OPC_BC2 = (0x08 << 21) | OPC_CP2,
399 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
401 enum {
402 OPC_LWXC1 = 0x00 | OPC_CP3,
403 OPC_LDXC1 = 0x01 | OPC_CP3,
404 OPC_LUXC1 = 0x05 | OPC_CP3,
405 OPC_SWXC1 = 0x08 | OPC_CP3,
406 OPC_SDXC1 = 0x09 | OPC_CP3,
407 OPC_SUXC1 = 0x0D | OPC_CP3,
408 OPC_PREFX = 0x0F | OPC_CP3,
409 OPC_ALNV_PS = 0x1E | OPC_CP3,
410 OPC_MADD_S = 0x20 | OPC_CP3,
411 OPC_MADD_D = 0x21 | OPC_CP3,
412 OPC_MADD_PS = 0x26 | OPC_CP3,
413 OPC_MSUB_S = 0x28 | OPC_CP3,
414 OPC_MSUB_D = 0x29 | OPC_CP3,
415 OPC_MSUB_PS = 0x2E | OPC_CP3,
416 OPC_NMADD_S = 0x30 | OPC_CP3,
417 OPC_NMADD_D = 0x31 | OPC_CP3,
418 OPC_NMADD_PS= 0x36 | OPC_CP3,
419 OPC_NMSUB_S = 0x38 | OPC_CP3,
420 OPC_NMSUB_D = 0x39 | OPC_CP3,
421 OPC_NMSUB_PS= 0x3E | OPC_CP3,
424 /* global register indices */
425 static TCGv cpu_env, current_tc_regs, cpu_T[2];
427 const unsigned char *regnames[] =
428 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
429 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
430 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
431 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
433 /* Warning: no function for r0 register (hard wired to zero) */
434 #define GEN32(func, NAME) \
435 static GenOpFunc *NAME ## _table [32] = { \
436 NULL, NAME ## 1, NAME ## 2, NAME ## 3, \
437 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
438 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
439 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
440 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
441 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
442 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
443 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
444 }; \
445 static always_inline void func(int n) \
447 NAME ## _table[n](); \
450 /* General purpose registers moves */
451 GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
452 GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
454 GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
455 GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
457 /* Moves to/from shadow registers */
458 GEN32(gen_op_load_srsgpr_T0, gen_op_load_srsgpr_T0_gpr);
459 GEN32(gen_op_store_T0_srsgpr, gen_op_store_T0_srsgpr_gpr);
461 static const char *fregnames[] =
462 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
463 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
464 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
465 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
467 #define FGEN32(func, NAME) \
468 static GenOpFunc *NAME ## _table [32] = { \
469 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
470 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
471 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
472 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
473 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
474 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
475 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
476 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
477 }; \
478 static always_inline void func(int n) \
480 NAME ## _table[n](); \
483 FGEN32(gen_op_load_fpr_WT0, gen_op_load_fpr_WT0_fpr);
484 FGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
486 FGEN32(gen_op_load_fpr_WT1, gen_op_load_fpr_WT1_fpr);
487 FGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
489 FGEN32(gen_op_load_fpr_WT2, gen_op_load_fpr_WT2_fpr);
490 FGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
492 FGEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fpr);
493 FGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
495 FGEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fpr);
496 FGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
498 FGEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fpr);
499 FGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
501 FGEN32(gen_op_load_fpr_WTH0, gen_op_load_fpr_WTH0_fpr);
502 FGEN32(gen_op_store_fpr_WTH0, gen_op_store_fpr_WTH0_fpr);
504 FGEN32(gen_op_load_fpr_WTH1, gen_op_load_fpr_WTH1_fpr);
505 FGEN32(gen_op_store_fpr_WTH1, gen_op_store_fpr_WTH1_fpr);
507 FGEN32(gen_op_load_fpr_WTH2, gen_op_load_fpr_WTH2_fpr);
508 FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr);
510 #define FOP_CONDS(type, fmt) \
511 static GenOpFunc1 * gen_op_cmp ## type ## _ ## fmt ## _table[16] = { \
512 gen_op_cmp ## type ## _ ## fmt ## _f, \
513 gen_op_cmp ## type ## _ ## fmt ## _un, \
514 gen_op_cmp ## type ## _ ## fmt ## _eq, \
515 gen_op_cmp ## type ## _ ## fmt ## _ueq, \
516 gen_op_cmp ## type ## _ ## fmt ## _olt, \
517 gen_op_cmp ## type ## _ ## fmt ## _ult, \
518 gen_op_cmp ## type ## _ ## fmt ## _ole, \
519 gen_op_cmp ## type ## _ ## fmt ## _ule, \
520 gen_op_cmp ## type ## _ ## fmt ## _sf, \
521 gen_op_cmp ## type ## _ ## fmt ## _ngle, \
522 gen_op_cmp ## type ## _ ## fmt ## _seq, \
523 gen_op_cmp ## type ## _ ## fmt ## _ngl, \
524 gen_op_cmp ## type ## _ ## fmt ## _lt, \
525 gen_op_cmp ## type ## _ ## fmt ## _nge, \
526 gen_op_cmp ## type ## _ ## fmt ## _le, \
527 gen_op_cmp ## type ## _ ## fmt ## _ngt, \
528 }; \
529 static always_inline void gen_cmp ## type ## _ ## fmt(int n, long cc) \
531 gen_op_cmp ## type ## _ ## fmt ## _table[n](cc); \
534 FOP_CONDS(, d)
535 FOP_CONDS(abs, d)
536 FOP_CONDS(, s)
537 FOP_CONDS(abs, s)
538 FOP_CONDS(, ps)
539 FOP_CONDS(abs, ps)
541 typedef struct DisasContext {
542 struct TranslationBlock *tb;
543 target_ulong pc, saved_pc;
544 uint32_t opcode;
545 uint32_t fp_status;
546 /* Routine used to access memory */
547 int mem_idx;
548 uint32_t hflags, saved_hflags;
549 int bstate;
550 target_ulong btarget;
551 void *last_T0_store;
552 int last_T0_gpr;
553 } DisasContext;
555 enum {
556 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
557 * exception condition
559 BS_STOP = 1, /* We want to stop translation for any reason */
560 BS_BRANCH = 2, /* We reached a branch condition */
561 BS_EXCP = 3, /* We reached an exception condition */
564 #ifdef MIPS_DEBUG_DISAS
565 #define MIPS_DEBUG(fmt, args...) \
566 do { \
567 if (loglevel & CPU_LOG_TB_IN_ASM) { \
568 fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n", \
569 ctx->pc, ctx->opcode , ##args); \
571 } while (0)
572 #else
573 #define MIPS_DEBUG(fmt, args...) do { } while(0)
574 #endif
576 #define MIPS_INVAL(op) \
577 do { \
578 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
579 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
580 } while (0)
582 #define GEN_LOAD_REG_T0(Rn) \
583 do { \
584 if (Rn == 0) { \
585 gen_op_reset_T0(); \
586 } else { \
587 if (ctx->glue(last_T0, _store) != gen_opc_ptr \
588 || ctx->glue(last_T0, _gpr) != Rn) { \
589 gen_op_load_gpr_T0(Rn); \
592 } while (0)
594 #define GEN_LOAD_REG_T1(Rn) \
595 do { \
596 if (Rn == 0) { \
597 gen_op_reset_T1(); \
598 } else { \
599 gen_op_load_gpr_T1(Rn); \
601 } while (0)
603 #define GEN_LOAD_SRSREG_TN(Tn, Rn) \
604 do { \
605 if (Rn == 0) { \
606 glue(gen_op_reset_, Tn)(); \
607 } else { \
608 glue(gen_op_load_srsgpr_, Tn)(Rn); \
610 } while (0)
612 #if defined(TARGET_MIPS64)
613 #define GEN_LOAD_IMM_TN(Tn, Imm) \
614 do { \
615 if (Imm == 0) { \
616 glue(gen_op_reset_, Tn)(); \
617 } else if ((int32_t)Imm == Imm) { \
618 glue(gen_op_set_, Tn)(Imm); \
619 } else { \
620 glue(gen_op_set64_, Tn)(((uint64_t)Imm) >> 32, (uint32_t)Imm); \
622 } while (0)
623 #else
624 #define GEN_LOAD_IMM_TN(Tn, Imm) \
625 do { \
626 if (Imm == 0) { \
627 glue(gen_op_reset_, Tn)(); \
628 } else { \
629 glue(gen_op_set_, Tn)(Imm); \
631 } while (0)
632 #endif
634 #define GEN_STORE_T0_REG(Rn) \
635 do { \
636 if (Rn != 0) { \
637 glue(gen_op_store_T0,_gpr)(Rn); \
638 ctx->glue(last_T0,_store) = gen_opc_ptr; \
639 ctx->glue(last_T0,_gpr) = Rn; \
641 } while (0)
643 #define GEN_STORE_T1_REG(Rn) \
644 do { \
645 if (Rn != 0) \
646 glue(gen_op_store_T1,_gpr)(Rn); \
647 } while (0)
649 #define GEN_STORE_TN_SRSREG(Rn, Tn) \
650 do { \
651 if (Rn != 0) { \
652 glue(glue(gen_op_store_, Tn),_srsgpr)(Rn); \
654 } while (0)
656 #define GEN_LOAD_FREG_FTN(FTn, Fn) \
657 do { \
658 glue(gen_op_load_fpr_, FTn)(Fn); \
659 } while (0)
661 #define GEN_STORE_FTN_FREG(Fn, FTn) \
662 do { \
663 glue(gen_op_store_fpr_, FTn)(Fn); \
664 } while (0)
666 static always_inline void gen_save_pc(target_ulong pc)
668 #if defined(TARGET_MIPS64)
669 if (pc == (int32_t)pc) {
670 gen_op_save_pc(pc);
671 } else {
672 gen_op_save_pc64(pc >> 32, (uint32_t)pc);
674 #else
675 gen_op_save_pc(pc);
676 #endif
679 static always_inline void gen_save_btarget(target_ulong btarget)
681 #if defined(TARGET_MIPS64)
682 if (btarget == (int32_t)btarget) {
683 gen_op_save_btarget(btarget);
684 } else {
685 gen_op_save_btarget64(btarget >> 32, (uint32_t)btarget);
687 #else
688 gen_op_save_btarget(btarget);
689 #endif
692 static always_inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
694 #if defined MIPS_DEBUG_DISAS
695 if (loglevel & CPU_LOG_TB_IN_ASM) {
696 fprintf(logfile, "hflags %08x saved %08x\n",
697 ctx->hflags, ctx->saved_hflags);
699 #endif
700 if (do_save_pc && ctx->pc != ctx->saved_pc) {
701 gen_save_pc(ctx->pc);
702 ctx->saved_pc = ctx->pc;
704 if (ctx->hflags != ctx->saved_hflags) {
705 gen_op_save_state(ctx->hflags);
706 ctx->saved_hflags = ctx->hflags;
707 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
708 case MIPS_HFLAG_BR:
709 break;
710 case MIPS_HFLAG_BC:
711 case MIPS_HFLAG_BL:
712 case MIPS_HFLAG_B:
713 gen_save_btarget(ctx->btarget);
714 break;
719 static always_inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
721 ctx->saved_hflags = ctx->hflags;
722 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
723 case MIPS_HFLAG_BR:
724 break;
725 case MIPS_HFLAG_BC:
726 case MIPS_HFLAG_BL:
727 case MIPS_HFLAG_B:
728 ctx->btarget = env->btarget;
729 break;
733 static always_inline void generate_exception_err (DisasContext *ctx, int excp, int err)
735 #if defined MIPS_DEBUG_DISAS
736 if (loglevel & CPU_LOG_TB_IN_ASM)
737 fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
738 #endif
739 save_cpu_state(ctx, 1);
740 if (err == 0)
741 gen_op_raise_exception(excp);
742 else
743 gen_op_raise_exception_err(excp, err);
744 ctx->bstate = BS_EXCP;
747 static always_inline void generate_exception (DisasContext *ctx, int excp)
749 generate_exception_err (ctx, excp, 0);
752 static always_inline void check_cp0_enabled(DisasContext *ctx)
754 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
755 generate_exception_err(ctx, EXCP_CpU, 1);
758 static always_inline void check_cp1_enabled(DisasContext *ctx)
760 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
761 generate_exception_err(ctx, EXCP_CpU, 1);
764 /* Verify that the processor is running with COP1X instructions enabled.
765 This is associated with the nabla symbol in the MIPS32 and MIPS64
766 opcode tables. */
768 static always_inline void check_cop1x(DisasContext *ctx)
770 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
771 generate_exception(ctx, EXCP_RI);
774 /* Verify that the processor is running with 64-bit floating-point
775 operations enabled. */
777 static always_inline void check_cp1_64bitmode(DisasContext *ctx)
779 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
780 generate_exception(ctx, EXCP_RI);
784 * Verify if floating point register is valid; an operation is not defined
785 * if bit 0 of any register specification is set and the FR bit in the
786 * Status register equals zero, since the register numbers specify an
787 * even-odd pair of adjacent coprocessor general registers. When the FR bit
788 * in the Status register equals one, both even and odd register numbers
789 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
791 * Multiple 64 bit wide registers can be checked by calling
792 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
794 void check_cp1_registers(DisasContext *ctx, int regs)
796 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
797 generate_exception(ctx, EXCP_RI);
800 /* This code generates a "reserved instruction" exception if the
801 CPU does not support the instruction set corresponding to flags. */
802 static always_inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
804 if (unlikely(!(env->insn_flags & flags)))
805 generate_exception(ctx, EXCP_RI);
808 /* This code generates a "reserved instruction" exception if 64-bit
809 instructions are not enabled. */
810 static always_inline void check_mips_64(DisasContext *ctx)
812 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
813 generate_exception(ctx, EXCP_RI);
816 #if defined(CONFIG_USER_ONLY)
817 #define op_ldst(name) gen_op_##name##_raw()
818 #define OP_LD_TABLE(width)
819 #define OP_ST_TABLE(width)
820 #else
821 #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
822 #define OP_LD_TABLE(width) \
823 static GenOpFunc *gen_op_l##width[] = { \
824 &gen_op_l##width##_kernel, \
825 &gen_op_l##width##_super, \
826 &gen_op_l##width##_user, \
828 #define OP_ST_TABLE(width) \
829 static GenOpFunc *gen_op_s##width[] = { \
830 &gen_op_s##width##_kernel, \
831 &gen_op_s##width##_super, \
832 &gen_op_s##width##_user, \
834 #endif
836 #if defined(TARGET_MIPS64)
837 OP_LD_TABLE(d);
838 OP_LD_TABLE(dl);
839 OP_LD_TABLE(dr);
840 OP_ST_TABLE(d);
841 OP_ST_TABLE(dl);
842 OP_ST_TABLE(dr);
843 OP_LD_TABLE(ld);
844 OP_ST_TABLE(cd);
845 OP_LD_TABLE(wu);
846 #endif
847 OP_LD_TABLE(w);
848 OP_LD_TABLE(wl);
849 OP_LD_TABLE(wr);
850 OP_ST_TABLE(w);
851 OP_ST_TABLE(wl);
852 OP_ST_TABLE(wr);
853 OP_LD_TABLE(h);
854 OP_LD_TABLE(hu);
855 OP_ST_TABLE(h);
856 OP_LD_TABLE(b);
857 OP_LD_TABLE(bu);
858 OP_ST_TABLE(b);
859 OP_LD_TABLE(l);
860 OP_ST_TABLE(c);
861 OP_LD_TABLE(wc1);
862 OP_ST_TABLE(wc1);
863 OP_LD_TABLE(dc1);
864 OP_ST_TABLE(dc1);
865 OP_LD_TABLE(uxc1);
866 OP_ST_TABLE(uxc1);
868 /* Load and store */
869 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
870 int base, int16_t offset)
872 const char *opn = "ldst";
874 if (base == 0) {
875 GEN_LOAD_IMM_TN(T0, offset);
876 } else if (offset == 0) {
877 gen_op_load_gpr_T0(base);
878 } else {
879 gen_op_load_gpr_T0(base);
880 gen_op_set_T1(offset);
881 gen_op_addr_add();
883 /* Don't do NOP if destination is zero: we must perform the actual
884 memory access. */
885 switch (opc) {
886 #if defined(TARGET_MIPS64)
887 case OPC_LWU:
888 op_ldst(lwu);
889 GEN_STORE_T0_REG(rt);
890 opn = "lwu";
891 break;
892 case OPC_LD:
893 op_ldst(ld);
894 GEN_STORE_T0_REG(rt);
895 opn = "ld";
896 break;
897 case OPC_LLD:
898 op_ldst(lld);
899 GEN_STORE_T0_REG(rt);
900 opn = "lld";
901 break;
902 case OPC_SD:
903 GEN_LOAD_REG_T1(rt);
904 op_ldst(sd);
905 opn = "sd";
906 break;
907 case OPC_SCD:
908 save_cpu_state(ctx, 1);
909 GEN_LOAD_REG_T1(rt);
910 op_ldst(scd);
911 GEN_STORE_T0_REG(rt);
912 opn = "scd";
913 break;
914 case OPC_LDL:
915 GEN_LOAD_REG_T1(rt);
916 op_ldst(ldl);
917 GEN_STORE_T1_REG(rt);
918 opn = "ldl";
919 break;
920 case OPC_SDL:
921 GEN_LOAD_REG_T1(rt);
922 op_ldst(sdl);
923 opn = "sdl";
924 break;
925 case OPC_LDR:
926 GEN_LOAD_REG_T1(rt);
927 op_ldst(ldr);
928 GEN_STORE_T1_REG(rt);
929 opn = "ldr";
930 break;
931 case OPC_SDR:
932 GEN_LOAD_REG_T1(rt);
933 op_ldst(sdr);
934 opn = "sdr";
935 break;
936 #endif
937 case OPC_LW:
938 op_ldst(lw);
939 GEN_STORE_T0_REG(rt);
940 opn = "lw";
941 break;
942 case OPC_SW:
943 GEN_LOAD_REG_T1(rt);
944 op_ldst(sw);
945 opn = "sw";
946 break;
947 case OPC_LH:
948 op_ldst(lh);
949 GEN_STORE_T0_REG(rt);
950 opn = "lh";
951 break;
952 case OPC_SH:
953 GEN_LOAD_REG_T1(rt);
954 op_ldst(sh);
955 opn = "sh";
956 break;
957 case OPC_LHU:
958 op_ldst(lhu);
959 GEN_STORE_T0_REG(rt);
960 opn = "lhu";
961 break;
962 case OPC_LB:
963 op_ldst(lb);
964 GEN_STORE_T0_REG(rt);
965 opn = "lb";
966 break;
967 case OPC_SB:
968 GEN_LOAD_REG_T1(rt);
969 op_ldst(sb);
970 opn = "sb";
971 break;
972 case OPC_LBU:
973 op_ldst(lbu);
974 GEN_STORE_T0_REG(rt);
975 opn = "lbu";
976 break;
977 case OPC_LWL:
978 GEN_LOAD_REG_T1(rt);
979 op_ldst(lwl);
980 GEN_STORE_T1_REG(rt);
981 opn = "lwl";
982 break;
983 case OPC_SWL:
984 GEN_LOAD_REG_T1(rt);
985 op_ldst(swl);
986 opn = "swr";
987 break;
988 case OPC_LWR:
989 GEN_LOAD_REG_T1(rt);
990 op_ldst(lwr);
991 GEN_STORE_T1_REG(rt);
992 opn = "lwr";
993 break;
994 case OPC_SWR:
995 GEN_LOAD_REG_T1(rt);
996 op_ldst(swr);
997 opn = "swr";
998 break;
999 case OPC_LL:
1000 op_ldst(ll);
1001 GEN_STORE_T0_REG(rt);
1002 opn = "ll";
1003 break;
1004 case OPC_SC:
1005 save_cpu_state(ctx, 1);
1006 GEN_LOAD_REG_T1(rt);
1007 op_ldst(sc);
1008 GEN_STORE_T0_REG(rt);
1009 opn = "sc";
1010 break;
1011 default:
1012 MIPS_INVAL(opn);
1013 generate_exception(ctx, EXCP_RI);
1014 return;
1016 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1019 /* Load and store */
1020 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1021 int base, int16_t offset)
1023 const char *opn = "flt_ldst";
1025 if (base == 0) {
1026 GEN_LOAD_IMM_TN(T0, offset);
1027 } else if (offset == 0) {
1028 gen_op_load_gpr_T0(base);
1029 } else {
1030 gen_op_load_gpr_T0(base);
1031 gen_op_set_T1(offset);
1032 gen_op_addr_add();
1034 /* Don't do NOP if destination is zero: we must perform the actual
1035 memory access. */
1036 switch (opc) {
1037 case OPC_LWC1:
1038 op_ldst(lwc1);
1039 GEN_STORE_FTN_FREG(ft, WT0);
1040 opn = "lwc1";
1041 break;
1042 case OPC_SWC1:
1043 GEN_LOAD_FREG_FTN(WT0, ft);
1044 op_ldst(swc1);
1045 opn = "swc1";
1046 break;
1047 case OPC_LDC1:
1048 op_ldst(ldc1);
1049 GEN_STORE_FTN_FREG(ft, DT0);
1050 opn = "ldc1";
1051 break;
1052 case OPC_SDC1:
1053 GEN_LOAD_FREG_FTN(DT0, ft);
1054 op_ldst(sdc1);
1055 opn = "sdc1";
1056 break;
1057 default:
1058 MIPS_INVAL(opn);
1059 generate_exception(ctx, EXCP_RI);
1060 return;
1062 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1065 /* Arithmetic with immediate operand */
1066 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1067 int rt, int rs, int16_t imm)
1069 target_ulong uimm;
1070 const char *opn = "imm arith";
1072 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1073 /* If no destination, treat it as a NOP.
1074 For addi, we must generate the overflow exception when needed. */
1075 MIPS_DEBUG("NOP");
1076 return;
1078 uimm = (uint16_t)imm;
1079 switch (opc) {
1080 case OPC_ADDI:
1081 case OPC_ADDIU:
1082 #if defined(TARGET_MIPS64)
1083 case OPC_DADDI:
1084 case OPC_DADDIU:
1085 #endif
1086 case OPC_SLTI:
1087 case OPC_SLTIU:
1088 uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1089 /* Fall through. */
1090 case OPC_ANDI:
1091 case OPC_ORI:
1092 case OPC_XORI:
1093 GEN_LOAD_REG_T0(rs);
1094 GEN_LOAD_IMM_TN(T1, uimm);
1095 break;
1096 case OPC_LUI:
1097 GEN_LOAD_IMM_TN(T0, imm << 16);
1098 break;
1099 case OPC_SLL:
1100 case OPC_SRA:
1101 case OPC_SRL:
1102 #if defined(TARGET_MIPS64)
1103 case OPC_DSLL:
1104 case OPC_DSRA:
1105 case OPC_DSRL:
1106 case OPC_DSLL32:
1107 case OPC_DSRA32:
1108 case OPC_DSRL32:
1109 #endif
1110 uimm &= 0x1f;
1111 GEN_LOAD_REG_T0(rs);
1112 GEN_LOAD_IMM_TN(T1, uimm);
1113 break;
1115 switch (opc) {
1116 case OPC_ADDI:
1117 save_cpu_state(ctx, 1);
1118 gen_op_addo();
1119 opn = "addi";
1120 break;
1121 case OPC_ADDIU:
1122 gen_op_add();
1123 opn = "addiu";
1124 break;
1125 #if defined(TARGET_MIPS64)
1126 case OPC_DADDI:
1127 save_cpu_state(ctx, 1);
1128 gen_op_daddo();
1129 opn = "daddi";
1130 break;
1131 case OPC_DADDIU:
1132 gen_op_dadd();
1133 opn = "daddiu";
1134 break;
1135 #endif
1136 case OPC_SLTI:
1137 gen_op_lt();
1138 opn = "slti";
1139 break;
1140 case OPC_SLTIU:
1141 gen_op_ltu();
1142 opn = "sltiu";
1143 break;
1144 case OPC_ANDI:
1145 gen_op_and();
1146 opn = "andi";
1147 break;
1148 case OPC_ORI:
1149 gen_op_or();
1150 opn = "ori";
1151 break;
1152 case OPC_XORI:
1153 gen_op_xor();
1154 opn = "xori";
1155 break;
1156 case OPC_LUI:
1157 opn = "lui";
1158 break;
1159 case OPC_SLL:
1160 gen_op_sll();
1161 opn = "sll";
1162 break;
1163 case OPC_SRA:
1164 gen_op_sra();
1165 opn = "sra";
1166 break;
1167 case OPC_SRL:
1168 switch ((ctx->opcode >> 21) & 0x1f) {
1169 case 0:
1170 gen_op_srl();
1171 opn = "srl";
1172 break;
1173 case 1:
1174 /* rotr is decoded as srl on non-R2 CPUs */
1175 if (env->insn_flags & ISA_MIPS32R2) {
1176 gen_op_rotr();
1177 opn = "rotr";
1178 } else {
1179 gen_op_srl();
1180 opn = "srl";
1182 break;
1183 default:
1184 MIPS_INVAL("invalid srl flag");
1185 generate_exception(ctx, EXCP_RI);
1186 break;
1188 break;
1189 #if defined(TARGET_MIPS64)
1190 case OPC_DSLL:
1191 gen_op_dsll();
1192 opn = "dsll";
1193 break;
1194 case OPC_DSRA:
1195 gen_op_dsra();
1196 opn = "dsra";
1197 break;
1198 case OPC_DSRL:
1199 switch ((ctx->opcode >> 21) & 0x1f) {
1200 case 0:
1201 gen_op_dsrl();
1202 opn = "dsrl";
1203 break;
1204 case 1:
1205 /* drotr is decoded as dsrl on non-R2 CPUs */
1206 if (env->insn_flags & ISA_MIPS32R2) {
1207 gen_op_drotr();
1208 opn = "drotr";
1209 } else {
1210 gen_op_dsrl();
1211 opn = "dsrl";
1213 break;
1214 default:
1215 MIPS_INVAL("invalid dsrl flag");
1216 generate_exception(ctx, EXCP_RI);
1217 break;
1219 break;
1220 case OPC_DSLL32:
1221 gen_op_dsll32();
1222 opn = "dsll32";
1223 break;
1224 case OPC_DSRA32:
1225 gen_op_dsra32();
1226 opn = "dsra32";
1227 break;
1228 case OPC_DSRL32:
1229 switch ((ctx->opcode >> 21) & 0x1f) {
1230 case 0:
1231 gen_op_dsrl32();
1232 opn = "dsrl32";
1233 break;
1234 case 1:
1235 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1236 if (env->insn_flags & ISA_MIPS32R2) {
1237 gen_op_drotr32();
1238 opn = "drotr32";
1239 } else {
1240 gen_op_dsrl32();
1241 opn = "dsrl32";
1243 break;
1244 default:
1245 MIPS_INVAL("invalid dsrl32 flag");
1246 generate_exception(ctx, EXCP_RI);
1247 break;
1249 break;
1250 #endif
1251 default:
1252 MIPS_INVAL(opn);
1253 generate_exception(ctx, EXCP_RI);
1254 return;
1256 GEN_STORE_T0_REG(rt);
1257 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1260 /* Arithmetic */
1261 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1262 int rd, int rs, int rt)
1264 const char *opn = "arith";
1266 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1267 && opc != OPC_DADD && opc != OPC_DSUB) {
1268 /* If no destination, treat it as a NOP.
1269 For add & sub, we must generate the overflow exception when needed. */
1270 MIPS_DEBUG("NOP");
1271 return;
1273 GEN_LOAD_REG_T0(rs);
1274 /* Specialcase the conventional move operation. */
1275 if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1276 || opc == OPC_SUBU || opc == OPC_DSUBU)) {
1277 GEN_STORE_T0_REG(rd);
1278 return;
1280 GEN_LOAD_REG_T1(rt);
1281 switch (opc) {
1282 case OPC_ADD:
1283 save_cpu_state(ctx, 1);
1284 gen_op_addo();
1285 opn = "add";
1286 break;
1287 case OPC_ADDU:
1288 gen_op_add();
1289 opn = "addu";
1290 break;
1291 case OPC_SUB:
1292 save_cpu_state(ctx, 1);
1293 gen_op_subo();
1294 opn = "sub";
1295 break;
1296 case OPC_SUBU:
1297 gen_op_sub();
1298 opn = "subu";
1299 break;
1300 #if defined(TARGET_MIPS64)
1301 case OPC_DADD:
1302 save_cpu_state(ctx, 1);
1303 gen_op_daddo();
1304 opn = "dadd";
1305 break;
1306 case OPC_DADDU:
1307 gen_op_dadd();
1308 opn = "daddu";
1309 break;
1310 case OPC_DSUB:
1311 save_cpu_state(ctx, 1);
1312 gen_op_dsubo();
1313 opn = "dsub";
1314 break;
1315 case OPC_DSUBU:
1316 gen_op_dsub();
1317 opn = "dsubu";
1318 break;
1319 #endif
1320 case OPC_SLT:
1321 gen_op_lt();
1322 opn = "slt";
1323 break;
1324 case OPC_SLTU:
1325 gen_op_ltu();
1326 opn = "sltu";
1327 break;
1328 case OPC_AND:
1329 gen_op_and();
1330 opn = "and";
1331 break;
1332 case OPC_NOR:
1333 gen_op_nor();
1334 opn = "nor";
1335 break;
1336 case OPC_OR:
1337 gen_op_or();
1338 opn = "or";
1339 break;
1340 case OPC_XOR:
1341 gen_op_xor();
1342 opn = "xor";
1343 break;
1344 case OPC_MUL:
1345 gen_op_mul();
1346 opn = "mul";
1347 break;
1348 case OPC_MOVN:
1349 gen_op_movn(rd);
1350 opn = "movn";
1351 goto print;
1352 case OPC_MOVZ:
1353 gen_op_movz(rd);
1354 opn = "movz";
1355 goto print;
1356 case OPC_SLLV:
1357 gen_op_sllv();
1358 opn = "sllv";
1359 break;
1360 case OPC_SRAV:
1361 gen_op_srav();
1362 opn = "srav";
1363 break;
1364 case OPC_SRLV:
1365 switch ((ctx->opcode >> 6) & 0x1f) {
1366 case 0:
1367 gen_op_srlv();
1368 opn = "srlv";
1369 break;
1370 case 1:
1371 /* rotrv is decoded as srlv on non-R2 CPUs */
1372 if (env->insn_flags & ISA_MIPS32R2) {
1373 gen_op_rotrv();
1374 opn = "rotrv";
1375 } else {
1376 gen_op_srlv();
1377 opn = "srlv";
1379 break;
1380 default:
1381 MIPS_INVAL("invalid srlv flag");
1382 generate_exception(ctx, EXCP_RI);
1383 break;
1385 break;
1386 #if defined(TARGET_MIPS64)
1387 case OPC_DSLLV:
1388 gen_op_dsllv();
1389 opn = "dsllv";
1390 break;
1391 case OPC_DSRAV:
1392 gen_op_dsrav();
1393 opn = "dsrav";
1394 break;
1395 case OPC_DSRLV:
1396 switch ((ctx->opcode >> 6) & 0x1f) {
1397 case 0:
1398 gen_op_dsrlv();
1399 opn = "dsrlv";
1400 break;
1401 case 1:
1402 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1403 if (env->insn_flags & ISA_MIPS32R2) {
1404 gen_op_drotrv();
1405 opn = "drotrv";
1406 } else {
1407 gen_op_dsrlv();
1408 opn = "dsrlv";
1410 break;
1411 default:
1412 MIPS_INVAL("invalid dsrlv flag");
1413 generate_exception(ctx, EXCP_RI);
1414 break;
1416 break;
1417 #endif
1418 default:
1419 MIPS_INVAL(opn);
1420 generate_exception(ctx, EXCP_RI);
1421 return;
1423 GEN_STORE_T0_REG(rd);
1424 print:
1425 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1428 /* Arithmetic on HI/LO registers */
1429 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1431 const char *opn = "hilo";
1433 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1434 /* Treat as NOP. */
1435 MIPS_DEBUG("NOP");
1436 return;
1438 switch (opc) {
1439 case OPC_MFHI:
1440 gen_op_load_HI(0);
1441 GEN_STORE_T0_REG(reg);
1442 opn = "mfhi";
1443 break;
1444 case OPC_MFLO:
1445 gen_op_load_LO(0);
1446 GEN_STORE_T0_REG(reg);
1447 opn = "mflo";
1448 break;
1449 case OPC_MTHI:
1450 GEN_LOAD_REG_T0(reg);
1451 gen_op_store_HI(0);
1452 opn = "mthi";
1453 break;
1454 case OPC_MTLO:
1455 GEN_LOAD_REG_T0(reg);
1456 gen_op_store_LO(0);
1457 opn = "mtlo";
1458 break;
1459 default:
1460 MIPS_INVAL(opn);
1461 generate_exception(ctx, EXCP_RI);
1462 return;
1464 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1467 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1468 int rs, int rt)
1470 const char *opn = "mul/div";
1472 GEN_LOAD_REG_T0(rs);
1473 GEN_LOAD_REG_T1(rt);
1474 switch (opc) {
1475 case OPC_DIV:
1476 gen_op_div();
1477 opn = "div";
1478 break;
1479 case OPC_DIVU:
1480 gen_op_divu();
1481 opn = "divu";
1482 break;
1483 case OPC_MULT:
1484 gen_op_mult();
1485 opn = "mult";
1486 break;
1487 case OPC_MULTU:
1488 gen_op_multu();
1489 opn = "multu";
1490 break;
1491 #if defined(TARGET_MIPS64)
1492 case OPC_DDIV:
1493 gen_op_ddiv();
1494 opn = "ddiv";
1495 break;
1496 case OPC_DDIVU:
1497 gen_op_ddivu();
1498 opn = "ddivu";
1499 break;
1500 case OPC_DMULT:
1501 gen_op_dmult();
1502 opn = "dmult";
1503 break;
1504 case OPC_DMULTU:
1505 gen_op_dmultu();
1506 opn = "dmultu";
1507 break;
1508 #endif
1509 case OPC_MADD:
1510 gen_op_madd();
1511 opn = "madd";
1512 break;
1513 case OPC_MADDU:
1514 gen_op_maddu();
1515 opn = "maddu";
1516 break;
1517 case OPC_MSUB:
1518 gen_op_msub();
1519 opn = "msub";
1520 break;
1521 case OPC_MSUBU:
1522 gen_op_msubu();
1523 opn = "msubu";
1524 break;
1525 default:
1526 MIPS_INVAL(opn);
1527 generate_exception(ctx, EXCP_RI);
1528 return;
1530 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1533 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
1534 int rd, int rs, int rt)
1536 const char *opn = "mul vr54xx";
1538 GEN_LOAD_REG_T0(rs);
1539 GEN_LOAD_REG_T1(rt);
1541 switch (opc) {
1542 case OPC_VR54XX_MULS:
1543 gen_op_muls();
1544 opn = "muls";
1545 break;
1546 case OPC_VR54XX_MULSU:
1547 gen_op_mulsu();
1548 opn = "mulsu";
1549 break;
1550 case OPC_VR54XX_MACC:
1551 gen_op_macc();
1552 opn = "macc";
1553 break;
1554 case OPC_VR54XX_MACCU:
1555 gen_op_maccu();
1556 opn = "maccu";
1557 break;
1558 case OPC_VR54XX_MSAC:
1559 gen_op_msac();
1560 opn = "msac";
1561 break;
1562 case OPC_VR54XX_MSACU:
1563 gen_op_msacu();
1564 opn = "msacu";
1565 break;
1566 case OPC_VR54XX_MULHI:
1567 gen_op_mulhi();
1568 opn = "mulhi";
1569 break;
1570 case OPC_VR54XX_MULHIU:
1571 gen_op_mulhiu();
1572 opn = "mulhiu";
1573 break;
1574 case OPC_VR54XX_MULSHI:
1575 gen_op_mulshi();
1576 opn = "mulshi";
1577 break;
1578 case OPC_VR54XX_MULSHIU:
1579 gen_op_mulshiu();
1580 opn = "mulshiu";
1581 break;
1582 case OPC_VR54XX_MACCHI:
1583 gen_op_macchi();
1584 opn = "macchi";
1585 break;
1586 case OPC_VR54XX_MACCHIU:
1587 gen_op_macchiu();
1588 opn = "macchiu";
1589 break;
1590 case OPC_VR54XX_MSACHI:
1591 gen_op_msachi();
1592 opn = "msachi";
1593 break;
1594 case OPC_VR54XX_MSACHIU:
1595 gen_op_msachiu();
1596 opn = "msachiu";
1597 break;
1598 default:
1599 MIPS_INVAL("mul vr54xx");
1600 generate_exception(ctx, EXCP_RI);
1601 return;
1603 GEN_STORE_T0_REG(rd);
1604 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1607 static void gen_cl (DisasContext *ctx, uint32_t opc,
1608 int rd, int rs)
1610 const char *opn = "CLx";
1611 if (rd == 0) {
1612 /* Treat as NOP. */
1613 MIPS_DEBUG("NOP");
1614 return;
1616 GEN_LOAD_REG_T0(rs);
1617 switch (opc) {
1618 case OPC_CLO:
1619 gen_op_clo();
1620 opn = "clo";
1621 break;
1622 case OPC_CLZ:
1623 gen_op_clz();
1624 opn = "clz";
1625 break;
1626 #if defined(TARGET_MIPS64)
1627 case OPC_DCLO:
1628 gen_op_dclo();
1629 opn = "dclo";
1630 break;
1631 case OPC_DCLZ:
1632 gen_op_dclz();
1633 opn = "dclz";
1634 break;
1635 #endif
1636 default:
1637 MIPS_INVAL(opn);
1638 generate_exception(ctx, EXCP_RI);
1639 return;
1641 gen_op_store_T0_gpr(rd);
1642 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1645 /* Traps */
1646 static void gen_trap (DisasContext *ctx, uint32_t opc,
1647 int rs, int rt, int16_t imm)
1649 int cond;
1651 cond = 0;
1652 /* Load needed operands */
1653 switch (opc) {
1654 case OPC_TEQ:
1655 case OPC_TGE:
1656 case OPC_TGEU:
1657 case OPC_TLT:
1658 case OPC_TLTU:
1659 case OPC_TNE:
1660 /* Compare two registers */
1661 if (rs != rt) {
1662 GEN_LOAD_REG_T0(rs);
1663 GEN_LOAD_REG_T1(rt);
1664 cond = 1;
1666 break;
1667 case OPC_TEQI:
1668 case OPC_TGEI:
1669 case OPC_TGEIU:
1670 case OPC_TLTI:
1671 case OPC_TLTIU:
1672 case OPC_TNEI:
1673 /* Compare register to immediate */
1674 if (rs != 0 || imm != 0) {
1675 GEN_LOAD_REG_T0(rs);
1676 GEN_LOAD_IMM_TN(T1, (int32_t)imm);
1677 cond = 1;
1679 break;
1681 if (cond == 0) {
1682 switch (opc) {
1683 case OPC_TEQ: /* rs == rs */
1684 case OPC_TEQI: /* r0 == 0 */
1685 case OPC_TGE: /* rs >= rs */
1686 case OPC_TGEI: /* r0 >= 0 */
1687 case OPC_TGEU: /* rs >= rs unsigned */
1688 case OPC_TGEIU: /* r0 >= 0 unsigned */
1689 /* Always trap */
1690 gen_op_set_T0(1);
1691 break;
1692 case OPC_TLT: /* rs < rs */
1693 case OPC_TLTI: /* r0 < 0 */
1694 case OPC_TLTU: /* rs < rs unsigned */
1695 case OPC_TLTIU: /* r0 < 0 unsigned */
1696 case OPC_TNE: /* rs != rs */
1697 case OPC_TNEI: /* r0 != 0 */
1698 /* Never trap: treat as NOP. */
1699 return;
1700 default:
1701 MIPS_INVAL("trap");
1702 generate_exception(ctx, EXCP_RI);
1703 return;
1705 } else {
1706 switch (opc) {
1707 case OPC_TEQ:
1708 case OPC_TEQI:
1709 gen_op_eq();
1710 break;
1711 case OPC_TGE:
1712 case OPC_TGEI:
1713 gen_op_ge();
1714 break;
1715 case OPC_TGEU:
1716 case OPC_TGEIU:
1717 gen_op_geu();
1718 break;
1719 case OPC_TLT:
1720 case OPC_TLTI:
1721 gen_op_lt();
1722 break;
1723 case OPC_TLTU:
1724 case OPC_TLTIU:
1725 gen_op_ltu();
1726 break;
1727 case OPC_TNE:
1728 case OPC_TNEI:
1729 gen_op_ne();
1730 break;
1731 default:
1732 MIPS_INVAL("trap");
1733 generate_exception(ctx, EXCP_RI);
1734 return;
1737 save_cpu_state(ctx, 1);
1738 gen_op_trap();
1739 ctx->bstate = BS_STOP;
1742 static always_inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1744 TranslationBlock *tb;
1745 tb = ctx->tb;
1746 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1747 tcg_gen_goto_tb(n);
1748 gen_save_pc(dest);
1749 tcg_gen_exit_tb((long)tb + n);
1750 } else {
1751 gen_save_pc(dest);
1752 tcg_gen_exit_tb(0);
1756 static inline void tcg_gen_set_bcond(void)
1758 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, bcond));
1761 static inline void tcg_gen_jnz_bcond(int label)
1763 int r_tmp = tcg_temp_new(TCG_TYPE_TL);
1765 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, bcond));
1766 tcg_gen_brcond_tl(TCG_COND_NE, r_tmp, tcg_const_i32(0), label);
1769 /* Branches (before delay slot) */
1770 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1771 int rs, int rt, int32_t offset)
1773 target_ulong btarget = -1;
1774 int blink = 0;
1775 int bcond = 0;
1777 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1778 #ifdef MIPS_DEBUG_DISAS
1779 if (loglevel & CPU_LOG_TB_IN_ASM) {
1780 fprintf(logfile,
1781 "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
1782 ctx->pc);
1784 #endif
1785 generate_exception(ctx, EXCP_RI);
1786 return;
1789 /* Load needed operands */
1790 switch (opc) {
1791 case OPC_BEQ:
1792 case OPC_BEQL:
1793 case OPC_BNE:
1794 case OPC_BNEL:
1795 /* Compare two registers */
1796 if (rs != rt) {
1797 GEN_LOAD_REG_T0(rs);
1798 GEN_LOAD_REG_T1(rt);
1799 bcond = 1;
1801 btarget = ctx->pc + 4 + offset;
1802 break;
1803 case OPC_BGEZ:
1804 case OPC_BGEZAL:
1805 case OPC_BGEZALL:
1806 case OPC_BGEZL:
1807 case OPC_BGTZ:
1808 case OPC_BGTZL:
1809 case OPC_BLEZ:
1810 case OPC_BLEZL:
1811 case OPC_BLTZ:
1812 case OPC_BLTZAL:
1813 case OPC_BLTZALL:
1814 case OPC_BLTZL:
1815 /* Compare to zero */
1816 if (rs != 0) {
1817 gen_op_load_gpr_T0(rs);
1818 bcond = 1;
1820 btarget = ctx->pc + 4 + offset;
1821 break;
1822 case OPC_J:
1823 case OPC_JAL:
1824 /* Jump to immediate */
1825 btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
1826 break;
1827 case OPC_JR:
1828 case OPC_JALR:
1829 /* Jump to register */
1830 if (offset != 0 && offset != 16) {
1831 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1832 others are reserved. */
1833 MIPS_INVAL("jump hint");
1834 generate_exception(ctx, EXCP_RI);
1835 return;
1837 GEN_LOAD_REG_T1(rs);
1838 gen_op_save_breg_target();
1839 break;
1840 default:
1841 MIPS_INVAL("branch/jump");
1842 generate_exception(ctx, EXCP_RI);
1843 return;
1845 if (bcond == 0) {
1846 /* No condition to be computed */
1847 switch (opc) {
1848 case OPC_BEQ: /* rx == rx */
1849 case OPC_BEQL: /* rx == rx likely */
1850 case OPC_BGEZ: /* 0 >= 0 */
1851 case OPC_BGEZL: /* 0 >= 0 likely */
1852 case OPC_BLEZ: /* 0 <= 0 */
1853 case OPC_BLEZL: /* 0 <= 0 likely */
1854 /* Always take */
1855 ctx->hflags |= MIPS_HFLAG_B;
1856 MIPS_DEBUG("balways");
1857 break;
1858 case OPC_BGEZAL: /* 0 >= 0 */
1859 case OPC_BGEZALL: /* 0 >= 0 likely */
1860 /* Always take and link */
1861 blink = 31;
1862 ctx->hflags |= MIPS_HFLAG_B;
1863 MIPS_DEBUG("balways and link");
1864 break;
1865 case OPC_BNE: /* rx != rx */
1866 case OPC_BGTZ: /* 0 > 0 */
1867 case OPC_BLTZ: /* 0 < 0 */
1868 /* Treat as NOP. */
1869 MIPS_DEBUG("bnever (NOP)");
1870 return;
1871 case OPC_BLTZAL: /* 0 < 0 */
1872 GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
1873 gen_op_store_T0_gpr(31);
1874 MIPS_DEBUG("bnever and link");
1875 return;
1876 case OPC_BLTZALL: /* 0 < 0 likely */
1877 GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
1878 gen_op_store_T0_gpr(31);
1879 /* Skip the instruction in the delay slot */
1880 MIPS_DEBUG("bnever, link and skip");
1881 ctx->pc += 4;
1882 return;
1883 case OPC_BNEL: /* rx != rx likely */
1884 case OPC_BGTZL: /* 0 > 0 likely */
1885 case OPC_BLTZL: /* 0 < 0 likely */
1886 /* Skip the instruction in the delay slot */
1887 MIPS_DEBUG("bnever and skip");
1888 ctx->pc += 4;
1889 return;
1890 case OPC_J:
1891 ctx->hflags |= MIPS_HFLAG_B;
1892 MIPS_DEBUG("j " TARGET_FMT_lx, btarget);
1893 break;
1894 case OPC_JAL:
1895 blink = 31;
1896 ctx->hflags |= MIPS_HFLAG_B;
1897 MIPS_DEBUG("jal " TARGET_FMT_lx, btarget);
1898 break;
1899 case OPC_JR:
1900 ctx->hflags |= MIPS_HFLAG_BR;
1901 MIPS_DEBUG("jr %s", regnames[rs]);
1902 break;
1903 case OPC_JALR:
1904 blink = rt;
1905 ctx->hflags |= MIPS_HFLAG_BR;
1906 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1907 break;
1908 default:
1909 MIPS_INVAL("branch/jump");
1910 generate_exception(ctx, EXCP_RI);
1911 return;
1913 } else {
1914 switch (opc) {
1915 case OPC_BEQ:
1916 gen_op_eq();
1917 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
1918 regnames[rs], regnames[rt], btarget);
1919 goto not_likely;
1920 case OPC_BEQL:
1921 gen_op_eq();
1922 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
1923 regnames[rs], regnames[rt], btarget);
1924 goto likely;
1925 case OPC_BNE:
1926 gen_op_ne();
1927 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
1928 regnames[rs], regnames[rt], btarget);
1929 goto not_likely;
1930 case OPC_BNEL:
1931 gen_op_ne();
1932 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
1933 regnames[rs], regnames[rt], btarget);
1934 goto likely;
1935 case OPC_BGEZ:
1936 gen_op_gez();
1937 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btarget);
1938 goto not_likely;
1939 case OPC_BGEZL:
1940 gen_op_gez();
1941 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1942 goto likely;
1943 case OPC_BGEZAL:
1944 gen_op_gez();
1945 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btarget);
1946 blink = 31;
1947 goto not_likely;
1948 case OPC_BGEZALL:
1949 gen_op_gez();
1950 blink = 31;
1951 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btarget);
1952 goto likely;
1953 case OPC_BGTZ:
1954 gen_op_gtz();
1955 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btarget);
1956 goto not_likely;
1957 case OPC_BGTZL:
1958 gen_op_gtz();
1959 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1960 goto likely;
1961 case OPC_BLEZ:
1962 gen_op_lez();
1963 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btarget);
1964 goto not_likely;
1965 case OPC_BLEZL:
1966 gen_op_lez();
1967 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1968 goto likely;
1969 case OPC_BLTZ:
1970 gen_op_ltz();
1971 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btarget);
1972 goto not_likely;
1973 case OPC_BLTZL:
1974 gen_op_ltz();
1975 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1976 goto likely;
1977 case OPC_BLTZAL:
1978 gen_op_ltz();
1979 blink = 31;
1980 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btarget);
1981 not_likely:
1982 ctx->hflags |= MIPS_HFLAG_BC;
1983 tcg_gen_set_bcond();
1984 break;
1985 case OPC_BLTZALL:
1986 gen_op_ltz();
1987 blink = 31;
1988 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btarget);
1989 likely:
1990 ctx->hflags |= MIPS_HFLAG_BL;
1991 tcg_gen_set_bcond();
1992 break;
1993 default:
1994 MIPS_INVAL("conditional branch/jump");
1995 generate_exception(ctx, EXCP_RI);
1996 return;
1999 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2000 blink, ctx->hflags, btarget);
2002 ctx->btarget = btarget;
2003 if (blink > 0) {
2004 GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
2005 gen_op_store_T0_gpr(blink);
2009 /* special3 bitfield operations */
2010 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2011 int rs, int lsb, int msb)
2013 GEN_LOAD_REG_T1(rs);
2014 switch (opc) {
2015 case OPC_EXT:
2016 if (lsb + msb > 31)
2017 goto fail;
2018 gen_op_ext(lsb, msb + 1);
2019 break;
2020 #if defined(TARGET_MIPS64)
2021 case OPC_DEXTM:
2022 if (lsb + msb > 63)
2023 goto fail;
2024 gen_op_dext(lsb, msb + 1 + 32);
2025 break;
2026 case OPC_DEXTU:
2027 if (lsb + msb > 63)
2028 goto fail;
2029 gen_op_dext(lsb + 32, msb + 1);
2030 break;
2031 case OPC_DEXT:
2032 if (lsb + msb > 63)
2033 goto fail;
2034 gen_op_dext(lsb, msb + 1);
2035 break;
2036 #endif
2037 case OPC_INS:
2038 if (lsb > msb)
2039 goto fail;
2040 GEN_LOAD_REG_T0(rt);
2041 gen_op_ins(lsb, msb - lsb + 1);
2042 break;
2043 #if defined(TARGET_MIPS64)
2044 case OPC_DINSM:
2045 if (lsb > msb)
2046 goto fail;
2047 GEN_LOAD_REG_T0(rt);
2048 gen_op_dins(lsb, msb - lsb + 1 + 32);
2049 break;
2050 case OPC_DINSU:
2051 if (lsb > msb)
2052 goto fail;
2053 GEN_LOAD_REG_T0(rt);
2054 gen_op_dins(lsb + 32, msb - lsb + 1);
2055 break;
2056 case OPC_DINS:
2057 if (lsb > msb)
2058 goto fail;
2059 GEN_LOAD_REG_T0(rt);
2060 gen_op_dins(lsb, msb - lsb + 1);
2061 break;
2062 #endif
2063 default:
2064 fail:
2065 MIPS_INVAL("bitops");
2066 generate_exception(ctx, EXCP_RI);
2067 return;
2069 GEN_STORE_T0_REG(rt);
2072 /* CP0 (MMU and control) */
2073 static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
2075 const char *rn = "invalid";
2077 if (sel != 0)
2078 check_insn(env, ctx, ISA_MIPS32);
2080 switch (reg) {
2081 case 0:
2082 switch (sel) {
2083 case 0:
2084 gen_op_mfc0_index();
2085 rn = "Index";
2086 break;
2087 case 1:
2088 check_insn(env, ctx, ASE_MT);
2089 gen_op_mfc0_mvpcontrol();
2090 rn = "MVPControl";
2091 break;
2092 case 2:
2093 check_insn(env, ctx, ASE_MT);
2094 gen_op_mfc0_mvpconf0();
2095 rn = "MVPConf0";
2096 break;
2097 case 3:
2098 check_insn(env, ctx, ASE_MT);
2099 gen_op_mfc0_mvpconf1();
2100 rn = "MVPConf1";
2101 break;
2102 default:
2103 goto die;
2105 break;
2106 case 1:
2107 switch (sel) {
2108 case 0:
2109 gen_op_mfc0_random();
2110 rn = "Random";
2111 break;
2112 case 1:
2113 check_insn(env, ctx, ASE_MT);
2114 gen_op_mfc0_vpecontrol();
2115 rn = "VPEControl";
2116 break;
2117 case 2:
2118 check_insn(env, ctx, ASE_MT);
2119 gen_op_mfc0_vpeconf0();
2120 rn = "VPEConf0";
2121 break;
2122 case 3:
2123 check_insn(env, ctx, ASE_MT);
2124 gen_op_mfc0_vpeconf1();
2125 rn = "VPEConf1";
2126 break;
2127 case 4:
2128 check_insn(env, ctx, ASE_MT);
2129 gen_op_mfc0_yqmask();
2130 rn = "YQMask";
2131 break;
2132 case 5:
2133 check_insn(env, ctx, ASE_MT);
2134 gen_op_mfc0_vpeschedule();
2135 rn = "VPESchedule";
2136 break;
2137 case 6:
2138 check_insn(env, ctx, ASE_MT);
2139 gen_op_mfc0_vpeschefback();
2140 rn = "VPEScheFBack";
2141 break;
2142 case 7:
2143 check_insn(env, ctx, ASE_MT);
2144 gen_op_mfc0_vpeopt();
2145 rn = "VPEOpt";
2146 break;
2147 default:
2148 goto die;
2150 break;
2151 case 2:
2152 switch (sel) {
2153 case 0:
2154 gen_op_mfc0_entrylo0();
2155 rn = "EntryLo0";
2156 break;
2157 case 1:
2158 check_insn(env, ctx, ASE_MT);
2159 gen_op_mfc0_tcstatus();
2160 rn = "TCStatus";
2161 break;
2162 case 2:
2163 check_insn(env, ctx, ASE_MT);
2164 gen_op_mfc0_tcbind();
2165 rn = "TCBind";
2166 break;
2167 case 3:
2168 check_insn(env, ctx, ASE_MT);
2169 gen_op_mfc0_tcrestart();
2170 rn = "TCRestart";
2171 break;
2172 case 4:
2173 check_insn(env, ctx, ASE_MT);
2174 gen_op_mfc0_tchalt();
2175 rn = "TCHalt";
2176 break;
2177 case 5:
2178 check_insn(env, ctx, ASE_MT);
2179 gen_op_mfc0_tccontext();
2180 rn = "TCContext";
2181 break;
2182 case 6:
2183 check_insn(env, ctx, ASE_MT);
2184 gen_op_mfc0_tcschedule();
2185 rn = "TCSchedule";
2186 break;
2187 case 7:
2188 check_insn(env, ctx, ASE_MT);
2189 gen_op_mfc0_tcschefback();
2190 rn = "TCScheFBack";
2191 break;
2192 default:
2193 goto die;
2195 break;
2196 case 3:
2197 switch (sel) {
2198 case 0:
2199 gen_op_mfc0_entrylo1();
2200 rn = "EntryLo1";
2201 break;
2202 default:
2203 goto die;
2205 break;
2206 case 4:
2207 switch (sel) {
2208 case 0:
2209 gen_op_mfc0_context();
2210 rn = "Context";
2211 break;
2212 case 1:
2213 // gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
2214 rn = "ContextConfig";
2215 // break;
2216 default:
2217 goto die;
2219 break;
2220 case 5:
2221 switch (sel) {
2222 case 0:
2223 gen_op_mfc0_pagemask();
2224 rn = "PageMask";
2225 break;
2226 case 1:
2227 check_insn(env, ctx, ISA_MIPS32R2);
2228 gen_op_mfc0_pagegrain();
2229 rn = "PageGrain";
2230 break;
2231 default:
2232 goto die;
2234 break;
2235 case 6:
2236 switch (sel) {
2237 case 0:
2238 gen_op_mfc0_wired();
2239 rn = "Wired";
2240 break;
2241 case 1:
2242 check_insn(env, ctx, ISA_MIPS32R2);
2243 gen_op_mfc0_srsconf0();
2244 rn = "SRSConf0";
2245 break;
2246 case 2:
2247 check_insn(env, ctx, ISA_MIPS32R2);
2248 gen_op_mfc0_srsconf1();
2249 rn = "SRSConf1";
2250 break;
2251 case 3:
2252 check_insn(env, ctx, ISA_MIPS32R2);
2253 gen_op_mfc0_srsconf2();
2254 rn = "SRSConf2";
2255 break;
2256 case 4:
2257 check_insn(env, ctx, ISA_MIPS32R2);
2258 gen_op_mfc0_srsconf3();
2259 rn = "SRSConf3";
2260 break;
2261 case 5:
2262 check_insn(env, ctx, ISA_MIPS32R2);
2263 gen_op_mfc0_srsconf4();
2264 rn = "SRSConf4";
2265 break;
2266 default:
2267 goto die;
2269 break;
2270 case 7:
2271 switch (sel) {
2272 case 0:
2273 check_insn(env, ctx, ISA_MIPS32R2);
2274 gen_op_mfc0_hwrena();
2275 rn = "HWREna";
2276 break;
2277 default:
2278 goto die;
2280 break;
2281 case 8:
2282 switch (sel) {
2283 case 0:
2284 gen_op_mfc0_badvaddr();
2285 rn = "BadVaddr";
2286 break;
2287 default:
2288 goto die;
2290 break;
2291 case 9:
2292 switch (sel) {
2293 case 0:
2294 gen_op_mfc0_count();
2295 rn = "Count";
2296 break;
2297 /* 6,7 are implementation dependent */
2298 default:
2299 goto die;
2301 break;
2302 case 10:
2303 switch (sel) {
2304 case 0:
2305 gen_op_mfc0_entryhi();
2306 rn = "EntryHi";
2307 break;
2308 default:
2309 goto die;
2311 break;
2312 case 11:
2313 switch (sel) {
2314 case 0:
2315 gen_op_mfc0_compare();
2316 rn = "Compare";
2317 break;
2318 /* 6,7 are implementation dependent */
2319 default:
2320 goto die;
2322 break;
2323 case 12:
2324 switch (sel) {
2325 case 0:
2326 gen_op_mfc0_status();
2327 rn = "Status";
2328 break;
2329 case 1:
2330 check_insn(env, ctx, ISA_MIPS32R2);
2331 gen_op_mfc0_intctl();
2332 rn = "IntCtl";
2333 break;
2334 case 2:
2335 check_insn(env, ctx, ISA_MIPS32R2);
2336 gen_op_mfc0_srsctl();
2337 rn = "SRSCtl";
2338 break;
2339 case 3:
2340 check_insn(env, ctx, ISA_MIPS32R2);
2341 gen_op_mfc0_srsmap();
2342 rn = "SRSMap";
2343 break;
2344 default:
2345 goto die;
2347 break;
2348 case 13:
2349 switch (sel) {
2350 case 0:
2351 gen_op_mfc0_cause();
2352 rn = "Cause";
2353 break;
2354 default:
2355 goto die;
2357 break;
2358 case 14:
2359 switch (sel) {
2360 case 0:
2361 gen_op_mfc0_epc();
2362 rn = "EPC";
2363 break;
2364 default:
2365 goto die;
2367 break;
2368 case 15:
2369 switch (sel) {
2370 case 0:
2371 gen_op_mfc0_prid();
2372 rn = "PRid";
2373 break;
2374 case 1:
2375 check_insn(env, ctx, ISA_MIPS32R2);
2376 gen_op_mfc0_ebase();
2377 rn = "EBase";
2378 break;
2379 default:
2380 goto die;
2382 break;
2383 case 16:
2384 switch (sel) {
2385 case 0:
2386 gen_op_mfc0_config0();
2387 rn = "Config";
2388 break;
2389 case 1:
2390 gen_op_mfc0_config1();
2391 rn = "Config1";
2392 break;
2393 case 2:
2394 gen_op_mfc0_config2();
2395 rn = "Config2";
2396 break;
2397 case 3:
2398 gen_op_mfc0_config3();
2399 rn = "Config3";
2400 break;
2401 /* 4,5 are reserved */
2402 /* 6,7 are implementation dependent */
2403 case 6:
2404 gen_op_mfc0_config6();
2405 rn = "Config6";
2406 break;
2407 case 7:
2408 gen_op_mfc0_config7();
2409 rn = "Config7";
2410 break;
2411 default:
2412 goto die;
2414 break;
2415 case 17:
2416 switch (sel) {
2417 case 0:
2418 gen_op_mfc0_lladdr();
2419 rn = "LLAddr";
2420 break;
2421 default:
2422 goto die;
2424 break;
2425 case 18:
2426 switch (sel) {
2427 case 0 ... 7:
2428 gen_op_mfc0_watchlo(sel);
2429 rn = "WatchLo";
2430 break;
2431 default:
2432 goto die;
2434 break;
2435 case 19:
2436 switch (sel) {
2437 case 0 ...7:
2438 gen_op_mfc0_watchhi(sel);
2439 rn = "WatchHi";
2440 break;
2441 default:
2442 goto die;
2444 break;
2445 case 20:
2446 switch (sel) {
2447 case 0:
2448 #if defined(TARGET_MIPS64)
2449 check_insn(env, ctx, ISA_MIPS3);
2450 gen_op_mfc0_xcontext();
2451 rn = "XContext";
2452 break;
2453 #endif
2454 default:
2455 goto die;
2457 break;
2458 case 21:
2459 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2460 switch (sel) {
2461 case 0:
2462 gen_op_mfc0_framemask();
2463 rn = "Framemask";
2464 break;
2465 default:
2466 goto die;
2468 break;
2469 case 22:
2470 /* ignored */
2471 rn = "'Diagnostic"; /* implementation dependent */
2472 break;
2473 case 23:
2474 switch (sel) {
2475 case 0:
2476 gen_op_mfc0_debug(); /* EJTAG support */
2477 rn = "Debug";
2478 break;
2479 case 1:
2480 // gen_op_mfc0_tracecontrol(); /* PDtrace support */
2481 rn = "TraceControl";
2482 // break;
2483 case 2:
2484 // gen_op_mfc0_tracecontrol2(); /* PDtrace support */
2485 rn = "TraceControl2";
2486 // break;
2487 case 3:
2488 // gen_op_mfc0_usertracedata(); /* PDtrace support */
2489 rn = "UserTraceData";
2490 // break;
2491 case 4:
2492 // gen_op_mfc0_debug(); /* PDtrace support */
2493 rn = "TraceBPC";
2494 // break;
2495 default:
2496 goto die;
2498 break;
2499 case 24:
2500 switch (sel) {
2501 case 0:
2502 gen_op_mfc0_depc(); /* EJTAG support */
2503 rn = "DEPC";
2504 break;
2505 default:
2506 goto die;
2508 break;
2509 case 25:
2510 switch (sel) {
2511 case 0:
2512 gen_op_mfc0_performance0();
2513 rn = "Performance0";
2514 break;
2515 case 1:
2516 // gen_op_mfc0_performance1();
2517 rn = "Performance1";
2518 // break;
2519 case 2:
2520 // gen_op_mfc0_performance2();
2521 rn = "Performance2";
2522 // break;
2523 case 3:
2524 // gen_op_mfc0_performance3();
2525 rn = "Performance3";
2526 // break;
2527 case 4:
2528 // gen_op_mfc0_performance4();
2529 rn = "Performance4";
2530 // break;
2531 case 5:
2532 // gen_op_mfc0_performance5();
2533 rn = "Performance5";
2534 // break;
2535 case 6:
2536 // gen_op_mfc0_performance6();
2537 rn = "Performance6";
2538 // break;
2539 case 7:
2540 // gen_op_mfc0_performance7();
2541 rn = "Performance7";
2542 // break;
2543 default:
2544 goto die;
2546 break;
2547 case 26:
2548 rn = "ECC";
2549 break;
2550 case 27:
2551 switch (sel) {
2552 /* ignored */
2553 case 0 ... 3:
2554 rn = "CacheErr";
2555 break;
2556 default:
2557 goto die;
2559 break;
2560 case 28:
2561 switch (sel) {
2562 case 0:
2563 case 2:
2564 case 4:
2565 case 6:
2566 gen_op_mfc0_taglo();
2567 rn = "TagLo";
2568 break;
2569 case 1:
2570 case 3:
2571 case 5:
2572 case 7:
2573 gen_op_mfc0_datalo();
2574 rn = "DataLo";
2575 break;
2576 default:
2577 goto die;
2579 break;
2580 case 29:
2581 switch (sel) {
2582 case 0:
2583 case 2:
2584 case 4:
2585 case 6:
2586 gen_op_mfc0_taghi();
2587 rn = "TagHi";
2588 break;
2589 case 1:
2590 case 3:
2591 case 5:
2592 case 7:
2593 gen_op_mfc0_datahi();
2594 rn = "DataHi";
2595 break;
2596 default:
2597 goto die;
2599 break;
2600 case 30:
2601 switch (sel) {
2602 case 0:
2603 gen_op_mfc0_errorepc();
2604 rn = "ErrorEPC";
2605 break;
2606 default:
2607 goto die;
2609 break;
2610 case 31:
2611 switch (sel) {
2612 case 0:
2613 gen_op_mfc0_desave(); /* EJTAG support */
2614 rn = "DESAVE";
2615 break;
2616 default:
2617 goto die;
2619 break;
2620 default:
2621 goto die;
2623 #if defined MIPS_DEBUG_DISAS
2624 if (loglevel & CPU_LOG_TB_IN_ASM) {
2625 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2626 rn, reg, sel);
2628 #endif
2629 return;
2631 die:
2632 #if defined MIPS_DEBUG_DISAS
2633 if (loglevel & CPU_LOG_TB_IN_ASM) {
2634 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2635 rn, reg, sel);
2637 #endif
2638 generate_exception(ctx, EXCP_RI);
2641 static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
2643 const char *rn = "invalid";
2645 if (sel != 0)
2646 check_insn(env, ctx, ISA_MIPS32);
2648 switch (reg) {
2649 case 0:
2650 switch (sel) {
2651 case 0:
2652 gen_op_mtc0_index();
2653 rn = "Index";
2654 break;
2655 case 1:
2656 check_insn(env, ctx, ASE_MT);
2657 gen_op_mtc0_mvpcontrol();
2658 rn = "MVPControl";
2659 break;
2660 case 2:
2661 check_insn(env, ctx, ASE_MT);
2662 /* ignored */
2663 rn = "MVPConf0";
2664 break;
2665 case 3:
2666 check_insn(env, ctx, ASE_MT);
2667 /* ignored */
2668 rn = "MVPConf1";
2669 break;
2670 default:
2671 goto die;
2673 break;
2674 case 1:
2675 switch (sel) {
2676 case 0:
2677 /* ignored */
2678 rn = "Random";
2679 break;
2680 case 1:
2681 check_insn(env, ctx, ASE_MT);
2682 gen_op_mtc0_vpecontrol();
2683 rn = "VPEControl";
2684 break;
2685 case 2:
2686 check_insn(env, ctx, ASE_MT);
2687 gen_op_mtc0_vpeconf0();
2688 rn = "VPEConf0";
2689 break;
2690 case 3:
2691 check_insn(env, ctx, ASE_MT);
2692 gen_op_mtc0_vpeconf1();
2693 rn = "VPEConf1";
2694 break;
2695 case 4:
2696 check_insn(env, ctx, ASE_MT);
2697 gen_op_mtc0_yqmask();
2698 rn = "YQMask";
2699 break;
2700 case 5:
2701 check_insn(env, ctx, ASE_MT);
2702 gen_op_mtc0_vpeschedule();
2703 rn = "VPESchedule";
2704 break;
2705 case 6:
2706 check_insn(env, ctx, ASE_MT);
2707 gen_op_mtc0_vpeschefback();
2708 rn = "VPEScheFBack";
2709 break;
2710 case 7:
2711 check_insn(env, ctx, ASE_MT);
2712 gen_op_mtc0_vpeopt();
2713 rn = "VPEOpt";
2714 break;
2715 default:
2716 goto die;
2718 break;
2719 case 2:
2720 switch (sel) {
2721 case 0:
2722 gen_op_mtc0_entrylo0();
2723 rn = "EntryLo0";
2724 break;
2725 case 1:
2726 check_insn(env, ctx, ASE_MT);
2727 gen_op_mtc0_tcstatus();
2728 rn = "TCStatus";
2729 break;
2730 case 2:
2731 check_insn(env, ctx, ASE_MT);
2732 gen_op_mtc0_tcbind();
2733 rn = "TCBind";
2734 break;
2735 case 3:
2736 check_insn(env, ctx, ASE_MT);
2737 gen_op_mtc0_tcrestart();
2738 rn = "TCRestart";
2739 break;
2740 case 4:
2741 check_insn(env, ctx, ASE_MT);
2742 gen_op_mtc0_tchalt();
2743 rn = "TCHalt";
2744 break;
2745 case 5:
2746 check_insn(env, ctx, ASE_MT);
2747 gen_op_mtc0_tccontext();
2748 rn = "TCContext";
2749 break;
2750 case 6:
2751 check_insn(env, ctx, ASE_MT);
2752 gen_op_mtc0_tcschedule();
2753 rn = "TCSchedule";
2754 break;
2755 case 7:
2756 check_insn(env, ctx, ASE_MT);
2757 gen_op_mtc0_tcschefback();
2758 rn = "TCScheFBack";
2759 break;
2760 default:
2761 goto die;
2763 break;
2764 case 3:
2765 switch (sel) {
2766 case 0:
2767 gen_op_mtc0_entrylo1();
2768 rn = "EntryLo1";
2769 break;
2770 default:
2771 goto die;
2773 break;
2774 case 4:
2775 switch (sel) {
2776 case 0:
2777 gen_op_mtc0_context();
2778 rn = "Context";
2779 break;
2780 case 1:
2781 // gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
2782 rn = "ContextConfig";
2783 // break;
2784 default:
2785 goto die;
2787 break;
2788 case 5:
2789 switch (sel) {
2790 case 0:
2791 gen_op_mtc0_pagemask();
2792 rn = "PageMask";
2793 break;
2794 case 1:
2795 check_insn(env, ctx, ISA_MIPS32R2);
2796 gen_op_mtc0_pagegrain();
2797 rn = "PageGrain";
2798 break;
2799 default:
2800 goto die;
2802 break;
2803 case 6:
2804 switch (sel) {
2805 case 0:
2806 gen_op_mtc0_wired();
2807 rn = "Wired";
2808 break;
2809 case 1:
2810 check_insn(env, ctx, ISA_MIPS32R2);
2811 gen_op_mtc0_srsconf0();
2812 rn = "SRSConf0";
2813 break;
2814 case 2:
2815 check_insn(env, ctx, ISA_MIPS32R2);
2816 gen_op_mtc0_srsconf1();
2817 rn = "SRSConf1";
2818 break;
2819 case 3:
2820 check_insn(env, ctx, ISA_MIPS32R2);
2821 gen_op_mtc0_srsconf2();
2822 rn = "SRSConf2";
2823 break;
2824 case 4:
2825 check_insn(env, ctx, ISA_MIPS32R2);
2826 gen_op_mtc0_srsconf3();
2827 rn = "SRSConf3";
2828 break;
2829 case 5:
2830 check_insn(env, ctx, ISA_MIPS32R2);
2831 gen_op_mtc0_srsconf4();
2832 rn = "SRSConf4";
2833 break;
2834 default:
2835 goto die;
2837 break;
2838 case 7:
2839 switch (sel) {
2840 case 0:
2841 check_insn(env, ctx, ISA_MIPS32R2);
2842 gen_op_mtc0_hwrena();
2843 rn = "HWREna";
2844 break;
2845 default:
2846 goto die;
2848 break;
2849 case 8:
2850 /* ignored */
2851 rn = "BadVaddr";
2852 break;
2853 case 9:
2854 switch (sel) {
2855 case 0:
2856 gen_op_mtc0_count();
2857 rn = "Count";
2858 break;
2859 /* 6,7 are implementation dependent */
2860 default:
2861 goto die;
2863 /* Stop translation as we may have switched the execution mode */
2864 ctx->bstate = BS_STOP;
2865 break;
2866 case 10:
2867 switch (sel) {
2868 case 0:
2869 gen_op_mtc0_entryhi();
2870 rn = "EntryHi";
2871 break;
2872 default:
2873 goto die;
2875 break;
2876 case 11:
2877 switch (sel) {
2878 case 0:
2879 gen_op_mtc0_compare();
2880 rn = "Compare";
2881 break;
2882 /* 6,7 are implementation dependent */
2883 default:
2884 goto die;
2886 /* Stop translation as we may have switched the execution mode */
2887 ctx->bstate = BS_STOP;
2888 break;
2889 case 12:
2890 switch (sel) {
2891 case 0:
2892 gen_op_mtc0_status();
2893 /* BS_STOP isn't good enough here, hflags may have changed. */
2894 gen_save_pc(ctx->pc + 4);
2895 ctx->bstate = BS_EXCP;
2896 rn = "Status";
2897 break;
2898 case 1:
2899 check_insn(env, ctx, ISA_MIPS32R2);
2900 gen_op_mtc0_intctl();
2901 /* Stop translation as we may have switched the execution mode */
2902 ctx->bstate = BS_STOP;
2903 rn = "IntCtl";
2904 break;
2905 case 2:
2906 check_insn(env, ctx, ISA_MIPS32R2);
2907 gen_op_mtc0_srsctl();
2908 /* Stop translation as we may have switched the execution mode */
2909 ctx->bstate = BS_STOP;
2910 rn = "SRSCtl";
2911 break;
2912 case 3:
2913 check_insn(env, ctx, ISA_MIPS32R2);
2914 gen_op_mtc0_srsmap();
2915 /* Stop translation as we may have switched the execution mode */
2916 ctx->bstate = BS_STOP;
2917 rn = "SRSMap";
2918 break;
2919 default:
2920 goto die;
2922 break;
2923 case 13:
2924 switch (sel) {
2925 case 0:
2926 gen_op_mtc0_cause();
2927 rn = "Cause";
2928 break;
2929 default:
2930 goto die;
2932 /* Stop translation as we may have switched the execution mode */
2933 ctx->bstate = BS_STOP;
2934 break;
2935 case 14:
2936 switch (sel) {
2937 case 0:
2938 gen_op_mtc0_epc();
2939 rn = "EPC";
2940 break;
2941 default:
2942 goto die;
2944 break;
2945 case 15:
2946 switch (sel) {
2947 case 0:
2948 /* ignored */
2949 rn = "PRid";
2950 break;
2951 case 1:
2952 check_insn(env, ctx, ISA_MIPS32R2);
2953 gen_op_mtc0_ebase();
2954 rn = "EBase";
2955 break;
2956 default:
2957 goto die;
2959 break;
2960 case 16:
2961 switch (sel) {
2962 case 0:
2963 gen_op_mtc0_config0();
2964 rn = "Config";
2965 /* Stop translation as we may have switched the execution mode */
2966 ctx->bstate = BS_STOP;
2967 break;
2968 case 1:
2969 /* ignored, read only */
2970 rn = "Config1";
2971 break;
2972 case 2:
2973 gen_op_mtc0_config2();
2974 rn = "Config2";
2975 /* Stop translation as we may have switched the execution mode */
2976 ctx->bstate = BS_STOP;
2977 break;
2978 case 3:
2979 /* ignored, read only */
2980 rn = "Config3";
2981 break;
2982 /* 4,5 are reserved */
2983 /* 6,7 are implementation dependent */
2984 case 6:
2985 /* ignored */
2986 rn = "Config6";
2987 break;
2988 case 7:
2989 /* ignored */
2990 rn = "Config7";
2991 break;
2992 default:
2993 rn = "Invalid config selector";
2994 goto die;
2996 break;
2997 case 17:
2998 switch (sel) {
2999 case 0:
3000 /* ignored */
3001 rn = "LLAddr";
3002 break;
3003 default:
3004 goto die;
3006 break;
3007 case 18:
3008 switch (sel) {
3009 case 0 ... 7:
3010 gen_op_mtc0_watchlo(sel);
3011 rn = "WatchLo";
3012 break;
3013 default:
3014 goto die;
3016 break;
3017 case 19:
3018 switch (sel) {
3019 case 0 ... 7:
3020 gen_op_mtc0_watchhi(sel);
3021 rn = "WatchHi";
3022 break;
3023 default:
3024 goto die;
3026 break;
3027 case 20:
3028 switch (sel) {
3029 case 0:
3030 #if defined(TARGET_MIPS64)
3031 check_insn(env, ctx, ISA_MIPS3);
3032 gen_op_mtc0_xcontext();
3033 rn = "XContext";
3034 break;
3035 #endif
3036 default:
3037 goto die;
3039 break;
3040 case 21:
3041 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3042 switch (sel) {
3043 case 0:
3044 gen_op_mtc0_framemask();
3045 rn = "Framemask";
3046 break;
3047 default:
3048 goto die;
3050 break;
3051 case 22:
3052 /* ignored */
3053 rn = "Diagnostic"; /* implementation dependent */
3054 break;
3055 case 23:
3056 switch (sel) {
3057 case 0:
3058 gen_op_mtc0_debug(); /* EJTAG support */
3059 /* BS_STOP isn't good enough here, hflags may have changed. */
3060 gen_save_pc(ctx->pc + 4);
3061 ctx->bstate = BS_EXCP;
3062 rn = "Debug";
3063 break;
3064 case 1:
3065 // gen_op_mtc0_tracecontrol(); /* PDtrace support */
3066 rn = "TraceControl";
3067 /* Stop translation as we may have switched the execution mode */
3068 ctx->bstate = BS_STOP;
3069 // break;
3070 case 2:
3071 // gen_op_mtc0_tracecontrol2(); /* PDtrace support */
3072 rn = "TraceControl2";
3073 /* Stop translation as we may have switched the execution mode */
3074 ctx->bstate = BS_STOP;
3075 // break;
3076 case 3:
3077 /* Stop translation as we may have switched the execution mode */
3078 ctx->bstate = BS_STOP;
3079 // gen_op_mtc0_usertracedata(); /* PDtrace support */
3080 rn = "UserTraceData";
3081 /* Stop translation as we may have switched the execution mode */
3082 ctx->bstate = BS_STOP;
3083 // break;
3084 case 4:
3085 // gen_op_mtc0_debug(); /* PDtrace support */
3086 /* Stop translation as we may have switched the execution mode */
3087 ctx->bstate = BS_STOP;
3088 rn = "TraceBPC";
3089 // break;
3090 default:
3091 goto die;
3093 break;
3094 case 24:
3095 switch (sel) {
3096 case 0:
3097 gen_op_mtc0_depc(); /* EJTAG support */
3098 rn = "DEPC";
3099 break;
3100 default:
3101 goto die;
3103 break;
3104 case 25:
3105 switch (sel) {
3106 case 0:
3107 gen_op_mtc0_performance0();
3108 rn = "Performance0";
3109 break;
3110 case 1:
3111 // gen_op_mtc0_performance1();
3112 rn = "Performance1";
3113 // break;
3114 case 2:
3115 // gen_op_mtc0_performance2();
3116 rn = "Performance2";
3117 // break;
3118 case 3:
3119 // gen_op_mtc0_performance3();
3120 rn = "Performance3";
3121 // break;
3122 case 4:
3123 // gen_op_mtc0_performance4();
3124 rn = "Performance4";
3125 // break;
3126 case 5:
3127 // gen_op_mtc0_performance5();
3128 rn = "Performance5";
3129 // break;
3130 case 6:
3131 // gen_op_mtc0_performance6();
3132 rn = "Performance6";
3133 // break;
3134 case 7:
3135 // gen_op_mtc0_performance7();
3136 rn = "Performance7";
3137 // break;
3138 default:
3139 goto die;
3141 break;
3142 case 26:
3143 /* ignored */
3144 rn = "ECC";
3145 break;
3146 case 27:
3147 switch (sel) {
3148 case 0 ... 3:
3149 /* ignored */
3150 rn = "CacheErr";
3151 break;
3152 default:
3153 goto die;
3155 break;
3156 case 28:
3157 switch (sel) {
3158 case 0:
3159 case 2:
3160 case 4:
3161 case 6:
3162 gen_op_mtc0_taglo();
3163 rn = "TagLo";
3164 break;
3165 case 1:
3166 case 3:
3167 case 5:
3168 case 7:
3169 gen_op_mtc0_datalo();
3170 rn = "DataLo";
3171 break;
3172 default:
3173 goto die;
3175 break;
3176 case 29:
3177 switch (sel) {
3178 case 0:
3179 case 2:
3180 case 4:
3181 case 6:
3182 gen_op_mtc0_taghi();
3183 rn = "TagHi";
3184 break;
3185 case 1:
3186 case 3:
3187 case 5:
3188 case 7:
3189 gen_op_mtc0_datahi();
3190 rn = "DataHi";
3191 break;
3192 default:
3193 rn = "invalid sel";
3194 goto die;
3196 break;
3197 case 30:
3198 switch (sel) {
3199 case 0:
3200 gen_op_mtc0_errorepc();
3201 rn = "ErrorEPC";
3202 break;
3203 default:
3204 goto die;
3206 break;
3207 case 31:
3208 switch (sel) {
3209 case 0:
3210 gen_op_mtc0_desave(); /* EJTAG support */
3211 rn = "DESAVE";
3212 break;
3213 default:
3214 goto die;
3216 /* Stop translation as we may have switched the execution mode */
3217 ctx->bstate = BS_STOP;
3218 break;
3219 default:
3220 goto die;
3222 #if defined MIPS_DEBUG_DISAS
3223 if (loglevel & CPU_LOG_TB_IN_ASM) {
3224 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3225 rn, reg, sel);
3227 #endif
3228 return;
3230 die:
3231 #if defined MIPS_DEBUG_DISAS
3232 if (loglevel & CPU_LOG_TB_IN_ASM) {
3233 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3234 rn, reg, sel);
3236 #endif
3237 generate_exception(ctx, EXCP_RI);
3240 #if defined(TARGET_MIPS64)
3241 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
3243 const char *rn = "invalid";
3245 if (sel != 0)
3246 check_insn(env, ctx, ISA_MIPS64);
3248 switch (reg) {
3249 case 0:
3250 switch (sel) {
3251 case 0:
3252 gen_op_mfc0_index();
3253 rn = "Index";
3254 break;
3255 case 1:
3256 check_insn(env, ctx, ASE_MT);
3257 gen_op_mfc0_mvpcontrol();
3258 rn = "MVPControl";
3259 break;
3260 case 2:
3261 check_insn(env, ctx, ASE_MT);
3262 gen_op_mfc0_mvpconf0();
3263 rn = "MVPConf0";
3264 break;
3265 case 3:
3266 check_insn(env, ctx, ASE_MT);
3267 gen_op_mfc0_mvpconf1();
3268 rn = "MVPConf1";
3269 break;
3270 default:
3271 goto die;
3273 break;
3274 case 1:
3275 switch (sel) {
3276 case 0:
3277 gen_op_mfc0_random();
3278 rn = "Random";
3279 break;
3280 case 1:
3281 check_insn(env, ctx, ASE_MT);
3282 gen_op_mfc0_vpecontrol();
3283 rn = "VPEControl";
3284 break;
3285 case 2:
3286 check_insn(env, ctx, ASE_MT);
3287 gen_op_mfc0_vpeconf0();
3288 rn = "VPEConf0";
3289 break;
3290 case 3:
3291 check_insn(env, ctx, ASE_MT);
3292 gen_op_mfc0_vpeconf1();
3293 rn = "VPEConf1";
3294 break;
3295 case 4:
3296 check_insn(env, ctx, ASE_MT);
3297 gen_op_dmfc0_yqmask();
3298 rn = "YQMask";
3299 break;
3300 case 5:
3301 check_insn(env, ctx, ASE_MT);
3302 gen_op_dmfc0_vpeschedule();
3303 rn = "VPESchedule";
3304 break;
3305 case 6:
3306 check_insn(env, ctx, ASE_MT);
3307 gen_op_dmfc0_vpeschefback();
3308 rn = "VPEScheFBack";
3309 break;
3310 case 7:
3311 check_insn(env, ctx, ASE_MT);
3312 gen_op_mfc0_vpeopt();
3313 rn = "VPEOpt";
3314 break;
3315 default:
3316 goto die;
3318 break;
3319 case 2:
3320 switch (sel) {
3321 case 0:
3322 gen_op_dmfc0_entrylo0();
3323 rn = "EntryLo0";
3324 break;
3325 case 1:
3326 check_insn(env, ctx, ASE_MT);
3327 gen_op_mfc0_tcstatus();
3328 rn = "TCStatus";
3329 break;
3330 case 2:
3331 check_insn(env, ctx, ASE_MT);
3332 gen_op_mfc0_tcbind();
3333 rn = "TCBind";
3334 break;
3335 case 3:
3336 check_insn(env, ctx, ASE_MT);
3337 gen_op_dmfc0_tcrestart();
3338 rn = "TCRestart";
3339 break;
3340 case 4:
3341 check_insn(env, ctx, ASE_MT);
3342 gen_op_dmfc0_tchalt();
3343 rn = "TCHalt";
3344 break;
3345 case 5:
3346 check_insn(env, ctx, ASE_MT);
3347 gen_op_dmfc0_tccontext();
3348 rn = "TCContext";
3349 break;
3350 case 6:
3351 check_insn(env, ctx, ASE_MT);
3352 gen_op_dmfc0_tcschedule();
3353 rn = "TCSchedule";
3354 break;
3355 case 7:
3356 check_insn(env, ctx, ASE_MT);
3357 gen_op_dmfc0_tcschefback();
3358 rn = "TCScheFBack";
3359 break;
3360 default:
3361 goto die;
3363 break;
3364 case 3:
3365 switch (sel) {
3366 case 0:
3367 gen_op_dmfc0_entrylo1();
3368 rn = "EntryLo1";
3369 break;
3370 default:
3371 goto die;
3373 break;
3374 case 4:
3375 switch (sel) {
3376 case 0:
3377 gen_op_dmfc0_context();
3378 rn = "Context";
3379 break;
3380 case 1:
3381 // gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */
3382 rn = "ContextConfig";
3383 // break;
3384 default:
3385 goto die;
3387 break;
3388 case 5:
3389 switch (sel) {
3390 case 0:
3391 gen_op_mfc0_pagemask();
3392 rn = "PageMask";
3393 break;
3394 case 1:
3395 check_insn(env, ctx, ISA_MIPS32R2);
3396 gen_op_mfc0_pagegrain();
3397 rn = "PageGrain";
3398 break;
3399 default:
3400 goto die;
3402 break;
3403 case 6:
3404 switch (sel) {
3405 case 0:
3406 gen_op_mfc0_wired();
3407 rn = "Wired";
3408 break;
3409 case 1:
3410 check_insn(env, ctx, ISA_MIPS32R2);
3411 gen_op_mfc0_srsconf0();
3412 rn = "SRSConf0";
3413 break;
3414 case 2:
3415 check_insn(env, ctx, ISA_MIPS32R2);
3416 gen_op_mfc0_srsconf1();
3417 rn = "SRSConf1";
3418 break;
3419 case 3:
3420 check_insn(env, ctx, ISA_MIPS32R2);
3421 gen_op_mfc0_srsconf2();
3422 rn = "SRSConf2";
3423 break;
3424 case 4:
3425 check_insn(env, ctx, ISA_MIPS32R2);
3426 gen_op_mfc0_srsconf3();
3427 rn = "SRSConf3";
3428 break;
3429 case 5:
3430 check_insn(env, ctx, ISA_MIPS32R2);
3431 gen_op_mfc0_srsconf4();
3432 rn = "SRSConf4";
3433 break;
3434 default:
3435 goto die;
3437 break;
3438 case 7:
3439 switch (sel) {
3440 case 0:
3441 check_insn(env, ctx, ISA_MIPS32R2);
3442 gen_op_mfc0_hwrena();
3443 rn = "HWREna";
3444 break;
3445 default:
3446 goto die;
3448 break;
3449 case 8:
3450 switch (sel) {
3451 case 0:
3452 gen_op_dmfc0_badvaddr();
3453 rn = "BadVaddr";
3454 break;
3455 default:
3456 goto die;
3458 break;
3459 case 9:
3460 switch (sel) {
3461 case 0:
3462 gen_op_mfc0_count();
3463 rn = "Count";
3464 break;
3465 /* 6,7 are implementation dependent */
3466 default:
3467 goto die;
3469 break;
3470 case 10:
3471 switch (sel) {
3472 case 0:
3473 gen_op_dmfc0_entryhi();
3474 rn = "EntryHi";
3475 break;
3476 default:
3477 goto die;
3479 break;
3480 case 11:
3481 switch (sel) {
3482 case 0:
3483 gen_op_mfc0_compare();
3484 rn = "Compare";
3485 break;
3486 /* 6,7 are implementation dependent */
3487 default:
3488 goto die;
3490 break;
3491 case 12:
3492 switch (sel) {
3493 case 0:
3494 gen_op_mfc0_status();
3495 rn = "Status";
3496 break;
3497 case 1:
3498 check_insn(env, ctx, ISA_MIPS32R2);
3499 gen_op_mfc0_intctl();
3500 rn = "IntCtl";
3501 break;
3502 case 2:
3503 check_insn(env, ctx, ISA_MIPS32R2);
3504 gen_op_mfc0_srsctl();
3505 rn = "SRSCtl";
3506 break;
3507 case 3:
3508 check_insn(env, ctx, ISA_MIPS32R2);
3509 gen_op_mfc0_srsmap();
3510 rn = "SRSMap";
3511 break;
3512 default:
3513 goto die;
3515 break;
3516 case 13:
3517 switch (sel) {
3518 case 0:
3519 gen_op_mfc0_cause();
3520 rn = "Cause";
3521 break;
3522 default:
3523 goto die;
3525 break;
3526 case 14:
3527 switch (sel) {
3528 case 0:
3529 gen_op_dmfc0_epc();
3530 rn = "EPC";
3531 break;
3532 default:
3533 goto die;
3535 break;
3536 case 15:
3537 switch (sel) {
3538 case 0:
3539 gen_op_mfc0_prid();
3540 rn = "PRid";
3541 break;
3542 case 1:
3543 check_insn(env, ctx, ISA_MIPS32R2);
3544 gen_op_mfc0_ebase();
3545 rn = "EBase";
3546 break;
3547 default:
3548 goto die;
3550 break;
3551 case 16:
3552 switch (sel) {
3553 case 0:
3554 gen_op_mfc0_config0();
3555 rn = "Config";
3556 break;
3557 case 1:
3558 gen_op_mfc0_config1();
3559 rn = "Config1";
3560 break;
3561 case 2:
3562 gen_op_mfc0_config2();
3563 rn = "Config2";
3564 break;
3565 case 3:
3566 gen_op_mfc0_config3();
3567 rn = "Config3";
3568 break;
3569 /* 6,7 are implementation dependent */
3570 default:
3571 goto die;
3573 break;
3574 case 17:
3575 switch (sel) {
3576 case 0:
3577 gen_op_dmfc0_lladdr();
3578 rn = "LLAddr";
3579 break;
3580 default:
3581 goto die;
3583 break;
3584 case 18:
3585 switch (sel) {
3586 case 0 ... 7:
3587 gen_op_dmfc0_watchlo(sel);
3588 rn = "WatchLo";
3589 break;
3590 default:
3591 goto die;
3593 break;
3594 case 19:
3595 switch (sel) {
3596 case 0 ... 7:
3597 gen_op_mfc0_watchhi(sel);
3598 rn = "WatchHi";
3599 break;
3600 default:
3601 goto die;
3603 break;
3604 case 20:
3605 switch (sel) {
3606 case 0:
3607 check_insn(env, ctx, ISA_MIPS3);
3608 gen_op_dmfc0_xcontext();
3609 rn = "XContext";
3610 break;
3611 default:
3612 goto die;
3614 break;
3615 case 21:
3616 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3617 switch (sel) {
3618 case 0:
3619 gen_op_mfc0_framemask();
3620 rn = "Framemask";
3621 break;
3622 default:
3623 goto die;
3625 break;
3626 case 22:
3627 /* ignored */
3628 rn = "'Diagnostic"; /* implementation dependent */
3629 break;
3630 case 23:
3631 switch (sel) {
3632 case 0:
3633 gen_op_mfc0_debug(); /* EJTAG support */
3634 rn = "Debug";
3635 break;
3636 case 1:
3637 // gen_op_dmfc0_tracecontrol(); /* PDtrace support */
3638 rn = "TraceControl";
3639 // break;
3640 case 2:
3641 // gen_op_dmfc0_tracecontrol2(); /* PDtrace support */
3642 rn = "TraceControl2";
3643 // break;
3644 case 3:
3645 // gen_op_dmfc0_usertracedata(); /* PDtrace support */
3646 rn = "UserTraceData";
3647 // break;
3648 case 4:
3649 // gen_op_dmfc0_debug(); /* PDtrace support */
3650 rn = "TraceBPC";
3651 // break;
3652 default:
3653 goto die;
3655 break;
3656 case 24:
3657 switch (sel) {
3658 case 0:
3659 gen_op_dmfc0_depc(); /* EJTAG support */
3660 rn = "DEPC";
3661 break;
3662 default:
3663 goto die;
3665 break;
3666 case 25:
3667 switch (sel) {
3668 case 0:
3669 gen_op_mfc0_performance0();
3670 rn = "Performance0";
3671 break;
3672 case 1:
3673 // gen_op_dmfc0_performance1();
3674 rn = "Performance1";
3675 // break;
3676 case 2:
3677 // gen_op_dmfc0_performance2();
3678 rn = "Performance2";
3679 // break;
3680 case 3:
3681 // gen_op_dmfc0_performance3();
3682 rn = "Performance3";
3683 // break;
3684 case 4:
3685 // gen_op_dmfc0_performance4();
3686 rn = "Performance4";
3687 // break;
3688 case 5:
3689 // gen_op_dmfc0_performance5();
3690 rn = "Performance5";
3691 // break;
3692 case 6:
3693 // gen_op_dmfc0_performance6();
3694 rn = "Performance6";
3695 // break;
3696 case 7:
3697 // gen_op_dmfc0_performance7();
3698 rn = "Performance7";
3699 // break;
3700 default:
3701 goto die;
3703 break;
3704 case 26:
3705 rn = "ECC";
3706 break;
3707 case 27:
3708 switch (sel) {
3709 /* ignored */
3710 case 0 ... 3:
3711 rn = "CacheErr";
3712 break;
3713 default:
3714 goto die;
3716 break;
3717 case 28:
3718 switch (sel) {
3719 case 0:
3720 case 2:
3721 case 4:
3722 case 6:
3723 gen_op_mfc0_taglo();
3724 rn = "TagLo";
3725 break;
3726 case 1:
3727 case 3:
3728 case 5:
3729 case 7:
3730 gen_op_mfc0_datalo();
3731 rn = "DataLo";
3732 break;
3733 default:
3734 goto die;
3736 break;
3737 case 29:
3738 switch (sel) {
3739 case 0:
3740 case 2:
3741 case 4:
3742 case 6:
3743 gen_op_mfc0_taghi();
3744 rn = "TagHi";
3745 break;
3746 case 1:
3747 case 3:
3748 case 5:
3749 case 7:
3750 gen_op_mfc0_datahi();
3751 rn = "DataHi";
3752 break;
3753 default:
3754 goto die;
3756 break;
3757 case 30:
3758 switch (sel) {
3759 case 0:
3760 gen_op_dmfc0_errorepc();
3761 rn = "ErrorEPC";
3762 break;
3763 default:
3764 goto die;
3766 break;
3767 case 31:
3768 switch (sel) {
3769 case 0:
3770 gen_op_mfc0_desave(); /* EJTAG support */
3771 rn = "DESAVE";
3772 break;
3773 default:
3774 goto die;
3776 break;
3777 default:
3778 goto die;
3780 #if defined MIPS_DEBUG_DISAS
3781 if (loglevel & CPU_LOG_TB_IN_ASM) {
3782 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3783 rn, reg, sel);
3785 #endif
3786 return;
3788 die:
3789 #if defined MIPS_DEBUG_DISAS
3790 if (loglevel & CPU_LOG_TB_IN_ASM) {
3791 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3792 rn, reg, sel);
3794 #endif
3795 generate_exception(ctx, EXCP_RI);
3798 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
3800 const char *rn = "invalid";
3802 if (sel != 0)
3803 check_insn(env, ctx, ISA_MIPS64);
3805 switch (reg) {
3806 case 0:
3807 switch (sel) {
3808 case 0:
3809 gen_op_mtc0_index();
3810 rn = "Index";
3811 break;
3812 case 1:
3813 check_insn(env, ctx, ASE_MT);
3814 gen_op_mtc0_mvpcontrol();
3815 rn = "MVPControl";
3816 break;
3817 case 2:
3818 check_insn(env, ctx, ASE_MT);
3819 /* ignored */
3820 rn = "MVPConf0";
3821 break;
3822 case 3:
3823 check_insn(env, ctx, ASE_MT);
3824 /* ignored */
3825 rn = "MVPConf1";
3826 break;
3827 default:
3828 goto die;
3830 break;
3831 case 1:
3832 switch (sel) {
3833 case 0:
3834 /* ignored */
3835 rn = "Random";
3836 break;
3837 case 1:
3838 check_insn(env, ctx, ASE_MT);
3839 gen_op_mtc0_vpecontrol();
3840 rn = "VPEControl";
3841 break;
3842 case 2:
3843 check_insn(env, ctx, ASE_MT);
3844 gen_op_mtc0_vpeconf0();
3845 rn = "VPEConf0";
3846 break;
3847 case 3:
3848 check_insn(env, ctx, ASE_MT);
3849 gen_op_mtc0_vpeconf1();
3850 rn = "VPEConf1";
3851 break;
3852 case 4:
3853 check_insn(env, ctx, ASE_MT);
3854 gen_op_mtc0_yqmask();
3855 rn = "YQMask";
3856 break;
3857 case 5:
3858 check_insn(env, ctx, ASE_MT);
3859 gen_op_mtc0_vpeschedule();
3860 rn = "VPESchedule";
3861 break;
3862 case 6:
3863 check_insn(env, ctx, ASE_MT);
3864 gen_op_mtc0_vpeschefback();
3865 rn = "VPEScheFBack";
3866 break;
3867 case 7:
3868 check_insn(env, ctx, ASE_MT);
3869 gen_op_mtc0_vpeopt();
3870 rn = "VPEOpt";
3871 break;
3872 default:
3873 goto die;
3875 break;
3876 case 2:
3877 switch (sel) {
3878 case 0:
3879 gen_op_mtc0_entrylo0();
3880 rn = "EntryLo0";
3881 break;
3882 case 1:
3883 check_insn(env, ctx, ASE_MT);
3884 gen_op_mtc0_tcstatus();
3885 rn = "TCStatus";
3886 break;
3887 case 2:
3888 check_insn(env, ctx, ASE_MT);
3889 gen_op_mtc0_tcbind();
3890 rn = "TCBind";
3891 break;
3892 case 3:
3893 check_insn(env, ctx, ASE_MT);
3894 gen_op_mtc0_tcrestart();
3895 rn = "TCRestart";
3896 break;
3897 case 4:
3898 check_insn(env, ctx, ASE_MT);
3899 gen_op_mtc0_tchalt();
3900 rn = "TCHalt";
3901 break;
3902 case 5:
3903 check_insn(env, ctx, ASE_MT);
3904 gen_op_mtc0_tccontext();
3905 rn = "TCContext";
3906 break;
3907 case 6:
3908 check_insn(env, ctx, ASE_MT);
3909 gen_op_mtc0_tcschedule();
3910 rn = "TCSchedule";
3911 break;
3912 case 7:
3913 check_insn(env, ctx, ASE_MT);
3914 gen_op_mtc0_tcschefback();
3915 rn = "TCScheFBack";
3916 break;
3917 default:
3918 goto die;
3920 break;
3921 case 3:
3922 switch (sel) {
3923 case 0:
3924 gen_op_mtc0_entrylo1();
3925 rn = "EntryLo1";
3926 break;
3927 default:
3928 goto die;
3930 break;
3931 case 4:
3932 switch (sel) {
3933 case 0:
3934 gen_op_mtc0_context();
3935 rn = "Context";
3936 break;
3937 case 1:
3938 // gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
3939 rn = "ContextConfig";
3940 // break;
3941 default:
3942 goto die;
3944 break;
3945 case 5:
3946 switch (sel) {
3947 case 0:
3948 gen_op_mtc0_pagemask();
3949 rn = "PageMask";
3950 break;
3951 case 1:
3952 check_insn(env, ctx, ISA_MIPS32R2);
3953 gen_op_mtc0_pagegrain();
3954 rn = "PageGrain";
3955 break;
3956 default:
3957 goto die;
3959 break;
3960 case 6:
3961 switch (sel) {
3962 case 0:
3963 gen_op_mtc0_wired();
3964 rn = "Wired";
3965 break;
3966 case 1:
3967 check_insn(env, ctx, ISA_MIPS32R2);
3968 gen_op_mtc0_srsconf0();
3969 rn = "SRSConf0";
3970 break;
3971 case 2:
3972 check_insn(env, ctx, ISA_MIPS32R2);
3973 gen_op_mtc0_srsconf1();
3974 rn = "SRSConf1";
3975 break;
3976 case 3:
3977 check_insn(env, ctx, ISA_MIPS32R2);
3978 gen_op_mtc0_srsconf2();
3979 rn = "SRSConf2";
3980 break;
3981 case 4:
3982 check_insn(env, ctx, ISA_MIPS32R2);
3983 gen_op_mtc0_srsconf3();
3984 rn = "SRSConf3";
3985 break;
3986 case 5:
3987 check_insn(env, ctx, ISA_MIPS32R2);
3988 gen_op_mtc0_srsconf4();
3989 rn = "SRSConf4";
3990 break;
3991 default:
3992 goto die;
3994 break;
3995 case 7:
3996 switch (sel) {
3997 case 0:
3998 check_insn(env, ctx, ISA_MIPS32R2);
3999 gen_op_mtc0_hwrena();
4000 rn = "HWREna";
4001 break;
4002 default:
4003 goto die;
4005 break;
4006 case 8:
4007 /* ignored */
4008 rn = "BadVaddr";
4009 break;
4010 case 9:
4011 switch (sel) {
4012 case 0:
4013 gen_op_mtc0_count();
4014 rn = "Count";
4015 break;
4016 /* 6,7 are implementation dependent */
4017 default:
4018 goto die;
4020 /* Stop translation as we may have switched the execution mode */
4021 ctx->bstate = BS_STOP;
4022 break;
4023 case 10:
4024 switch (sel) {
4025 case 0:
4026 gen_op_mtc0_entryhi();
4027 rn = "EntryHi";
4028 break;
4029 default:
4030 goto die;
4032 break;
4033 case 11:
4034 switch (sel) {
4035 case 0:
4036 gen_op_mtc0_compare();
4037 rn = "Compare";
4038 break;
4039 /* 6,7 are implementation dependent */
4040 default:
4041 goto die;
4043 /* Stop translation as we may have switched the execution mode */
4044 ctx->bstate = BS_STOP;
4045 break;
4046 case 12:
4047 switch (sel) {
4048 case 0:
4049 gen_op_mtc0_status();
4050 /* BS_STOP isn't good enough here, hflags may have changed. */
4051 gen_save_pc(ctx->pc + 4);
4052 ctx->bstate = BS_EXCP;
4053 rn = "Status";
4054 break;
4055 case 1:
4056 check_insn(env, ctx, ISA_MIPS32R2);
4057 gen_op_mtc0_intctl();
4058 /* Stop translation as we may have switched the execution mode */
4059 ctx->bstate = BS_STOP;
4060 rn = "IntCtl";
4061 break;
4062 case 2:
4063 check_insn(env, ctx, ISA_MIPS32R2);
4064 gen_op_mtc0_srsctl();
4065 /* Stop translation as we may have switched the execution mode */
4066 ctx->bstate = BS_STOP;
4067 rn = "SRSCtl";
4068 break;
4069 case 3:
4070 check_insn(env, ctx, ISA_MIPS32R2);
4071 gen_op_mtc0_srsmap();
4072 /* Stop translation as we may have switched the execution mode */
4073 ctx->bstate = BS_STOP;
4074 rn = "SRSMap";
4075 break;
4076 default:
4077 goto die;
4079 break;
4080 case 13:
4081 switch (sel) {
4082 case 0:
4083 gen_op_mtc0_cause();
4084 rn = "Cause";
4085 break;
4086 default:
4087 goto die;
4089 /* Stop translation as we may have switched the execution mode */
4090 ctx->bstate = BS_STOP;
4091 break;
4092 case 14:
4093 switch (sel) {
4094 case 0:
4095 gen_op_mtc0_epc();
4096 rn = "EPC";
4097 break;
4098 default:
4099 goto die;
4101 break;
4102 case 15:
4103 switch (sel) {
4104 case 0:
4105 /* ignored */
4106 rn = "PRid";
4107 break;
4108 case 1:
4109 check_insn(env, ctx, ISA_MIPS32R2);
4110 gen_op_mtc0_ebase();
4111 rn = "EBase";
4112 break;
4113 default:
4114 goto die;
4116 break;
4117 case 16:
4118 switch (sel) {
4119 case 0:
4120 gen_op_mtc0_config0();
4121 rn = "Config";
4122 /* Stop translation as we may have switched the execution mode */
4123 ctx->bstate = BS_STOP;
4124 break;
4125 case 1:
4126 /* ignored */
4127 rn = "Config1";
4128 break;
4129 case 2:
4130 gen_op_mtc0_config2();
4131 rn = "Config2";
4132 /* Stop translation as we may have switched the execution mode */
4133 ctx->bstate = BS_STOP;
4134 break;
4135 case 3:
4136 /* ignored */
4137 rn = "Config3";
4138 break;
4139 /* 6,7 are implementation dependent */
4140 default:
4141 rn = "Invalid config selector";
4142 goto die;
4144 break;
4145 case 17:
4146 switch (sel) {
4147 case 0:
4148 /* ignored */
4149 rn = "LLAddr";
4150 break;
4151 default:
4152 goto die;
4154 break;
4155 case 18:
4156 switch (sel) {
4157 case 0 ... 7:
4158 gen_op_mtc0_watchlo(sel);
4159 rn = "WatchLo";
4160 break;
4161 default:
4162 goto die;
4164 break;
4165 case 19:
4166 switch (sel) {
4167 case 0 ... 7:
4168 gen_op_mtc0_watchhi(sel);
4169 rn = "WatchHi";
4170 break;
4171 default:
4172 goto die;
4174 break;
4175 case 20:
4176 switch (sel) {
4177 case 0:
4178 check_insn(env, ctx, ISA_MIPS3);
4179 gen_op_mtc0_xcontext();
4180 rn = "XContext";
4181 break;
4182 default:
4183 goto die;
4185 break;
4186 case 21:
4187 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4188 switch (sel) {
4189 case 0:
4190 gen_op_mtc0_framemask();
4191 rn = "Framemask";
4192 break;
4193 default:
4194 goto die;
4196 break;
4197 case 22:
4198 /* ignored */
4199 rn = "Diagnostic"; /* implementation dependent */
4200 break;
4201 case 23:
4202 switch (sel) {
4203 case 0:
4204 gen_op_mtc0_debug(); /* EJTAG support */
4205 /* BS_STOP isn't good enough here, hflags may have changed. */
4206 gen_save_pc(ctx->pc + 4);
4207 ctx->bstate = BS_EXCP;
4208 rn = "Debug";
4209 break;
4210 case 1:
4211 // gen_op_mtc0_tracecontrol(); /* PDtrace support */
4212 /* Stop translation as we may have switched the execution mode */
4213 ctx->bstate = BS_STOP;
4214 rn = "TraceControl";
4215 // break;
4216 case 2:
4217 // gen_op_mtc0_tracecontrol2(); /* PDtrace support */
4218 /* Stop translation as we may have switched the execution mode */
4219 ctx->bstate = BS_STOP;
4220 rn = "TraceControl2";
4221 // break;
4222 case 3:
4223 // gen_op_mtc0_usertracedata(); /* PDtrace support */
4224 /* Stop translation as we may have switched the execution mode */
4225 ctx->bstate = BS_STOP;
4226 rn = "UserTraceData";
4227 // break;
4228 case 4:
4229 // gen_op_mtc0_debug(); /* PDtrace support */
4230 /* Stop translation as we may have switched the execution mode */
4231 ctx->bstate = BS_STOP;
4232 rn = "TraceBPC";
4233 // break;
4234 default:
4235 goto die;
4237 break;
4238 case 24:
4239 switch (sel) {
4240 case 0:
4241 gen_op_mtc0_depc(); /* EJTAG support */
4242 rn = "DEPC";
4243 break;
4244 default:
4245 goto die;
4247 break;
4248 case 25:
4249 switch (sel) {
4250 case 0:
4251 gen_op_mtc0_performance0();
4252 rn = "Performance0";
4253 break;
4254 case 1:
4255 // gen_op_mtc0_performance1();
4256 rn = "Performance1";
4257 // break;
4258 case 2:
4259 // gen_op_mtc0_performance2();
4260 rn = "Performance2";
4261 // break;
4262 case 3:
4263 // gen_op_mtc0_performance3();
4264 rn = "Performance3";
4265 // break;
4266 case 4:
4267 // gen_op_mtc0_performance4();
4268 rn = "Performance4";
4269 // break;
4270 case 5:
4271 // gen_op_mtc0_performance5();
4272 rn = "Performance5";
4273 // break;
4274 case 6:
4275 // gen_op_mtc0_performance6();
4276 rn = "Performance6";
4277 // break;
4278 case 7:
4279 // gen_op_mtc0_performance7();
4280 rn = "Performance7";
4281 // break;
4282 default:
4283 goto die;
4285 break;
4286 case 26:
4287 /* ignored */
4288 rn = "ECC";
4289 break;
4290 case 27:
4291 switch (sel) {
4292 case 0 ... 3:
4293 /* ignored */
4294 rn = "CacheErr";
4295 break;
4296 default:
4297 goto die;
4299 break;
4300 case 28:
4301 switch (sel) {
4302 case 0:
4303 case 2:
4304 case 4:
4305 case 6:
4306 gen_op_mtc0_taglo();
4307 rn = "TagLo";
4308 break;
4309 case 1:
4310 case 3:
4311 case 5:
4312 case 7:
4313 gen_op_mtc0_datalo();
4314 rn = "DataLo";
4315 break;
4316 default:
4317 goto die;
4319 break;
4320 case 29:
4321 switch (sel) {
4322 case 0:
4323 case 2:
4324 case 4:
4325 case 6:
4326 gen_op_mtc0_taghi();
4327 rn = "TagHi";
4328 break;
4329 case 1:
4330 case 3:
4331 case 5:
4332 case 7:
4333 gen_op_mtc0_datahi();
4334 rn = "DataHi";
4335 break;
4336 default:
4337 rn = "invalid sel";
4338 goto die;
4340 break;
4341 case 30:
4342 switch (sel) {
4343 case 0:
4344 gen_op_mtc0_errorepc();
4345 rn = "ErrorEPC";
4346 break;
4347 default:
4348 goto die;
4350 break;
4351 case 31:
4352 switch (sel) {
4353 case 0:
4354 gen_op_mtc0_desave(); /* EJTAG support */
4355 rn = "DESAVE";
4356 break;
4357 default:
4358 goto die;
4360 /* Stop translation as we may have switched the execution mode */
4361 ctx->bstate = BS_STOP;
4362 break;
4363 default:
4364 goto die;
4366 #if defined MIPS_DEBUG_DISAS
4367 if (loglevel & CPU_LOG_TB_IN_ASM) {
4368 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4369 rn, reg, sel);
4371 #endif
4372 return;
4374 die:
4375 #if defined MIPS_DEBUG_DISAS
4376 if (loglevel & CPU_LOG_TB_IN_ASM) {
4377 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4378 rn, reg, sel);
4380 #endif
4381 generate_exception(ctx, EXCP_RI);
4383 #endif /* TARGET_MIPS64 */
4385 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt,
4386 int u, int sel, int h)
4388 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
4390 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
4391 ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) !=
4392 (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE))))
4393 gen_op_set_T0(-1);
4394 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
4395 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
4396 gen_op_set_T0(-1);
4397 else if (u == 0) {
4398 switch (rt) {
4399 case 2:
4400 switch (sel) {
4401 case 1:
4402 gen_op_mftc0_tcstatus();
4403 break;
4404 case 2:
4405 gen_op_mftc0_tcbind();
4406 break;
4407 case 3:
4408 gen_op_mftc0_tcrestart();
4409 break;
4410 case 4:
4411 gen_op_mftc0_tchalt();
4412 break;
4413 case 5:
4414 gen_op_mftc0_tccontext();
4415 break;
4416 case 6:
4417 gen_op_mftc0_tcschedule();
4418 break;
4419 case 7:
4420 gen_op_mftc0_tcschefback();
4421 break;
4422 default:
4423 gen_mfc0(env, ctx, rt, sel);
4424 break;
4426 break;
4427 case 10:
4428 switch (sel) {
4429 case 0:
4430 gen_op_mftc0_entryhi();
4431 break;
4432 default:
4433 gen_mfc0(env, ctx, rt, sel);
4434 break;
4436 case 12:
4437 switch (sel) {
4438 case 0:
4439 gen_op_mftc0_status();
4440 break;
4441 default:
4442 gen_mfc0(env, ctx, rt, sel);
4443 break;
4445 case 23:
4446 switch (sel) {
4447 case 0:
4448 gen_op_mftc0_debug();
4449 break;
4450 default:
4451 gen_mfc0(env, ctx, rt, sel);
4452 break;
4454 break;
4455 default:
4456 gen_mfc0(env, ctx, rt, sel);
4458 } else switch (sel) {
4459 /* GPR registers. */
4460 case 0:
4461 gen_op_mftgpr(rt);
4462 break;
4463 /* Auxiliary CPU registers */
4464 case 1:
4465 switch (rt) {
4466 case 0:
4467 gen_op_mftlo(0);
4468 break;
4469 case 1:
4470 gen_op_mfthi(0);
4471 break;
4472 case 2:
4473 gen_op_mftacx(0);
4474 break;
4475 case 4:
4476 gen_op_mftlo(1);
4477 break;
4478 case 5:
4479 gen_op_mfthi(1);
4480 break;
4481 case 6:
4482 gen_op_mftacx(1);
4483 break;
4484 case 8:
4485 gen_op_mftlo(2);
4486 break;
4487 case 9:
4488 gen_op_mfthi(2);
4489 break;
4490 case 10:
4491 gen_op_mftacx(2);
4492 break;
4493 case 12:
4494 gen_op_mftlo(3);
4495 break;
4496 case 13:
4497 gen_op_mfthi(3);
4498 break;
4499 case 14:
4500 gen_op_mftacx(3);
4501 break;
4502 case 16:
4503 gen_op_mftdsp();
4504 break;
4505 default:
4506 goto die;
4508 break;
4509 /* Floating point (COP1). */
4510 case 2:
4511 /* XXX: For now we support only a single FPU context. */
4512 if (h == 0) {
4513 GEN_LOAD_FREG_FTN(WT0, rt);
4514 gen_op_mfc1();
4515 } else {
4516 GEN_LOAD_FREG_FTN(WTH0, rt);
4517 gen_op_mfhc1();
4519 break;
4520 case 3:
4521 /* XXX: For now we support only a single FPU context. */
4522 gen_op_cfc1(rt);
4523 break;
4524 /* COP2: Not implemented. */
4525 case 4:
4526 case 5:
4527 /* fall through */
4528 default:
4529 goto die;
4531 #if defined MIPS_DEBUG_DISAS
4532 if (loglevel & CPU_LOG_TB_IN_ASM) {
4533 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
4534 rt, u, sel, h);
4536 #endif
4537 return;
4539 die:
4540 #if defined MIPS_DEBUG_DISAS
4541 if (loglevel & CPU_LOG_TB_IN_ASM) {
4542 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
4543 rt, u, sel, h);
4545 #endif
4546 generate_exception(ctx, EXCP_RI);
4549 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd,
4550 int u, int sel, int h)
4552 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
4554 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
4555 ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) !=
4556 (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE))))
4557 /* NOP */ ;
4558 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
4559 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
4560 /* NOP */ ;
4561 else if (u == 0) {
4562 switch (rd) {
4563 case 2:
4564 switch (sel) {
4565 case 1:
4566 gen_op_mttc0_tcstatus();
4567 break;
4568 case 2:
4569 gen_op_mttc0_tcbind();
4570 break;
4571 case 3:
4572 gen_op_mttc0_tcrestart();
4573 break;
4574 case 4:
4575 gen_op_mttc0_tchalt();
4576 break;
4577 case 5:
4578 gen_op_mttc0_tccontext();
4579 break;
4580 case 6:
4581 gen_op_mttc0_tcschedule();
4582 break;
4583 case 7:
4584 gen_op_mttc0_tcschefback();
4585 break;
4586 default:
4587 gen_mtc0(env, ctx, rd, sel);
4588 break;
4590 break;
4591 case 10:
4592 switch (sel) {
4593 case 0:
4594 gen_op_mttc0_entryhi();
4595 break;
4596 default:
4597 gen_mtc0(env, ctx, rd, sel);
4598 break;
4600 case 12:
4601 switch (sel) {
4602 case 0:
4603 gen_op_mttc0_status();
4604 break;
4605 default:
4606 gen_mtc0(env, ctx, rd, sel);
4607 break;
4609 case 23:
4610 switch (sel) {
4611 case 0:
4612 gen_op_mttc0_debug();
4613 break;
4614 default:
4615 gen_mtc0(env, ctx, rd, sel);
4616 break;
4618 break;
4619 default:
4620 gen_mtc0(env, ctx, rd, sel);
4622 } else switch (sel) {
4623 /* GPR registers. */
4624 case 0:
4625 gen_op_mttgpr(rd);
4626 break;
4627 /* Auxiliary CPU registers */
4628 case 1:
4629 switch (rd) {
4630 case 0:
4631 gen_op_mttlo(0);
4632 break;
4633 case 1:
4634 gen_op_mtthi(0);
4635 break;
4636 case 2:
4637 gen_op_mttacx(0);
4638 break;
4639 case 4:
4640 gen_op_mttlo(1);
4641 break;
4642 case 5:
4643 gen_op_mtthi(1);
4644 break;
4645 case 6:
4646 gen_op_mttacx(1);
4647 break;
4648 case 8:
4649 gen_op_mttlo(2);
4650 break;
4651 case 9:
4652 gen_op_mtthi(2);
4653 break;
4654 case 10:
4655 gen_op_mttacx(2);
4656 break;
4657 case 12:
4658 gen_op_mttlo(3);
4659 break;
4660 case 13:
4661 gen_op_mtthi(3);
4662 break;
4663 case 14:
4664 gen_op_mttacx(3);
4665 break;
4666 case 16:
4667 gen_op_mttdsp();
4668 break;
4669 default:
4670 goto die;
4672 break;
4673 /* Floating point (COP1). */
4674 case 2:
4675 /* XXX: For now we support only a single FPU context. */
4676 if (h == 0) {
4677 gen_op_mtc1();
4678 GEN_STORE_FTN_FREG(rd, WT0);
4679 } else {
4680 gen_op_mthc1();
4681 GEN_STORE_FTN_FREG(rd, WTH0);
4683 break;
4684 case 3:
4685 /* XXX: For now we support only a single FPU context. */
4686 gen_op_ctc1(rd);
4687 break;
4688 /* COP2: Not implemented. */
4689 case 4:
4690 case 5:
4691 /* fall through */
4692 default:
4693 goto die;
4695 #if defined MIPS_DEBUG_DISAS
4696 if (loglevel & CPU_LOG_TB_IN_ASM) {
4697 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
4698 rd, u, sel, h);
4700 #endif
4701 return;
4703 die:
4704 #if defined MIPS_DEBUG_DISAS
4705 if (loglevel & CPU_LOG_TB_IN_ASM) {
4706 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
4707 rd, u, sel, h);
4709 #endif
4710 generate_exception(ctx, EXCP_RI);
4713 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
4715 const char *opn = "ldst";
4717 switch (opc) {
4718 case OPC_MFC0:
4719 if (rt == 0) {
4720 /* Treat as NOP. */
4721 return;
4723 gen_mfc0(env, ctx, rd, ctx->opcode & 0x7);
4724 gen_op_store_T0_gpr(rt);
4725 opn = "mfc0";
4726 break;
4727 case OPC_MTC0:
4728 GEN_LOAD_REG_T0(rt);
4729 save_cpu_state(ctx, 1);
4730 gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
4731 opn = "mtc0";
4732 break;
4733 #if defined(TARGET_MIPS64)
4734 case OPC_DMFC0:
4735 check_insn(env, ctx, ISA_MIPS3);
4736 if (rt == 0) {
4737 /* Treat as NOP. */
4738 return;
4740 gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7);
4741 gen_op_store_T0_gpr(rt);
4742 opn = "dmfc0";
4743 break;
4744 case OPC_DMTC0:
4745 check_insn(env, ctx, ISA_MIPS3);
4746 GEN_LOAD_REG_T0(rt);
4747 save_cpu_state(ctx, 1);
4748 gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
4749 opn = "dmtc0";
4750 break;
4751 #endif
4752 case OPC_MFTR:
4753 check_insn(env, ctx, ASE_MT);
4754 if (rd == 0) {
4755 /* Treat as NOP. */
4756 return;
4758 gen_mftr(env, ctx, rt, (ctx->opcode >> 5) & 1,
4759 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
4760 gen_op_store_T0_gpr(rd);
4761 opn = "mftr";
4762 break;
4763 case OPC_MTTR:
4764 check_insn(env, ctx, ASE_MT);
4765 GEN_LOAD_REG_T0(rt);
4766 gen_mttr(env, ctx, rd, (ctx->opcode >> 5) & 1,
4767 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
4768 opn = "mttr";
4769 break;
4770 case OPC_TLBWI:
4771 opn = "tlbwi";
4772 if (!env->tlb->do_tlbwi)
4773 goto die;
4774 gen_op_tlbwi();
4775 break;
4776 case OPC_TLBWR:
4777 opn = "tlbwr";
4778 if (!env->tlb->do_tlbwr)
4779 goto die;
4780 gen_op_tlbwr();
4781 break;
4782 case OPC_TLBP:
4783 opn = "tlbp";
4784 if (!env->tlb->do_tlbp)
4785 goto die;
4786 gen_op_tlbp();
4787 break;
4788 case OPC_TLBR:
4789 opn = "tlbr";
4790 if (!env->tlb->do_tlbr)
4791 goto die;
4792 gen_op_tlbr();
4793 break;
4794 case OPC_ERET:
4795 opn = "eret";
4796 check_insn(env, ctx, ISA_MIPS2);
4797 save_cpu_state(ctx, 1);
4798 gen_op_eret();
4799 ctx->bstate = BS_EXCP;
4800 break;
4801 case OPC_DERET:
4802 opn = "deret";
4803 check_insn(env, ctx, ISA_MIPS32);
4804 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
4805 MIPS_INVAL(opn);
4806 generate_exception(ctx, EXCP_RI);
4807 } else {
4808 save_cpu_state(ctx, 1);
4809 gen_op_deret();
4810 ctx->bstate = BS_EXCP;
4812 break;
4813 case OPC_WAIT:
4814 opn = "wait";
4815 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
4816 /* If we get an exception, we want to restart at next instruction */
4817 ctx->pc += 4;
4818 save_cpu_state(ctx, 1);
4819 ctx->pc -= 4;
4820 gen_op_wait();
4821 ctx->bstate = BS_EXCP;
4822 break;
4823 default:
4824 die:
4825 MIPS_INVAL(opn);
4826 generate_exception(ctx, EXCP_RI);
4827 return;
4829 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
4832 /* CP1 Branches (before delay slot) */
4833 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
4834 int32_t cc, int32_t offset)
4836 target_ulong btarget;
4837 const char *opn = "cp1 cond branch";
4839 if (cc != 0)
4840 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
4842 btarget = ctx->pc + 4 + offset;
4844 switch (op) {
4845 case OPC_BC1F:
4846 gen_op_bc1f(cc);
4847 opn = "bc1f";
4848 goto not_likely;
4849 case OPC_BC1FL:
4850 gen_op_bc1f(cc);
4851 opn = "bc1fl";
4852 goto likely;
4853 case OPC_BC1T:
4854 gen_op_bc1t(cc);
4855 opn = "bc1t";
4856 goto not_likely;
4857 case OPC_BC1TL:
4858 gen_op_bc1t(cc);
4859 opn = "bc1tl";
4860 likely:
4861 ctx->hflags |= MIPS_HFLAG_BL;
4862 tcg_gen_set_bcond();
4863 break;
4864 case OPC_BC1FANY2:
4865 gen_op_bc1any2f(cc);
4866 opn = "bc1any2f";
4867 goto not_likely;
4868 case OPC_BC1TANY2:
4869 gen_op_bc1any2t(cc);
4870 opn = "bc1any2t";
4871 goto not_likely;
4872 case OPC_BC1FANY4:
4873 gen_op_bc1any4f(cc);
4874 opn = "bc1any4f";
4875 goto not_likely;
4876 case OPC_BC1TANY4:
4877 gen_op_bc1any4t(cc);
4878 opn = "bc1any4t";
4879 not_likely:
4880 ctx->hflags |= MIPS_HFLAG_BC;
4881 tcg_gen_set_bcond();
4882 break;
4883 default:
4884 MIPS_INVAL(opn);
4885 generate_exception (ctx, EXCP_RI);
4886 return;
4888 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
4889 ctx->hflags, btarget);
4890 ctx->btarget = btarget;
4893 /* Coprocessor 1 (FPU) */
4895 #define FOP(func, fmt) (((fmt) << 21) | (func))
4897 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4899 const char *opn = "cp1 move";
4901 switch (opc) {
4902 case OPC_MFC1:
4903 GEN_LOAD_FREG_FTN(WT0, fs);
4904 gen_op_mfc1();
4905 GEN_STORE_T0_REG(rt);
4906 opn = "mfc1";
4907 break;
4908 case OPC_MTC1:
4909 GEN_LOAD_REG_T0(rt);
4910 gen_op_mtc1();
4911 GEN_STORE_FTN_FREG(fs, WT0);
4912 opn = "mtc1";
4913 break;
4914 case OPC_CFC1:
4915 gen_op_cfc1(fs);
4916 GEN_STORE_T0_REG(rt);
4917 opn = "cfc1";
4918 break;
4919 case OPC_CTC1:
4920 GEN_LOAD_REG_T0(rt);
4921 gen_op_ctc1(fs);
4922 opn = "ctc1";
4923 break;
4924 case OPC_DMFC1:
4925 GEN_LOAD_FREG_FTN(DT0, fs);
4926 gen_op_dmfc1();
4927 GEN_STORE_T0_REG(rt);
4928 opn = "dmfc1";
4929 break;
4930 case OPC_DMTC1:
4931 GEN_LOAD_REG_T0(rt);
4932 gen_op_dmtc1();
4933 GEN_STORE_FTN_FREG(fs, DT0);
4934 opn = "dmtc1";
4935 break;
4936 case OPC_MFHC1:
4937 GEN_LOAD_FREG_FTN(WTH0, fs);
4938 gen_op_mfhc1();
4939 GEN_STORE_T0_REG(rt);
4940 opn = "mfhc1";
4941 break;
4942 case OPC_MTHC1:
4943 GEN_LOAD_REG_T0(rt);
4944 gen_op_mthc1();
4945 GEN_STORE_FTN_FREG(fs, WTH0);
4946 opn = "mthc1";
4947 break;
4948 default:
4949 MIPS_INVAL(opn);
4950 generate_exception (ctx, EXCP_RI);
4951 return;
4953 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
4956 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4958 uint32_t ccbit;
4960 GEN_LOAD_REG_T0(rd);
4961 GEN_LOAD_REG_T1(rs);
4962 if (cc) {
4963 ccbit = 1 << (24 + cc);
4964 } else
4965 ccbit = 1 << 23;
4966 if (!tf)
4967 gen_op_movf(ccbit);
4968 else
4969 gen_op_movt(ccbit);
4970 GEN_STORE_T0_REG(rd);
4973 #define GEN_MOVCF(fmt) \
4974 static void glue(gen_movcf_, fmt) (DisasContext *ctx, int cc, int tf) \
4976 uint32_t ccbit; \
4978 if (cc) { \
4979 ccbit = 1 << (24 + cc); \
4980 } else \
4981 ccbit = 1 << 23; \
4982 if (!tf) \
4983 glue(gen_op_float_movf_, fmt)(ccbit); \
4984 else \
4985 glue(gen_op_float_movt_, fmt)(ccbit); \
4987 GEN_MOVCF(d);
4988 GEN_MOVCF(s);
4989 GEN_MOVCF(ps);
4990 #undef GEN_MOVCF
4992 static void gen_farith (DisasContext *ctx, uint32_t op1,
4993 int ft, int fs, int fd, int cc)
4995 const char *opn = "farith";
4996 const char *condnames[] = {
4997 "c.f",
4998 "c.un",
4999 "c.eq",
5000 "c.ueq",
5001 "c.olt",
5002 "c.ult",
5003 "c.ole",
5004 "c.ule",
5005 "c.sf",
5006 "c.ngle",
5007 "c.seq",
5008 "c.ngl",
5009 "c.lt",
5010 "c.nge",
5011 "c.le",
5012 "c.ngt",
5014 const char *condnames_abs[] = {
5015 "cabs.f",
5016 "cabs.un",
5017 "cabs.eq",
5018 "cabs.ueq",
5019 "cabs.olt",
5020 "cabs.ult",
5021 "cabs.ole",
5022 "cabs.ule",
5023 "cabs.sf",
5024 "cabs.ngle",
5025 "cabs.seq",
5026 "cabs.ngl",
5027 "cabs.lt",
5028 "cabs.nge",
5029 "cabs.le",
5030 "cabs.ngt",
5032 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
5033 uint32_t func = ctx->opcode & 0x3f;
5035 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5036 case FOP(0, 16):
5037 GEN_LOAD_FREG_FTN(WT0, fs);
5038 GEN_LOAD_FREG_FTN(WT1, ft);
5039 gen_op_float_add_s();
5040 GEN_STORE_FTN_FREG(fd, WT2);
5041 opn = "add.s";
5042 optype = BINOP;
5043 break;
5044 case FOP(1, 16):
5045 GEN_LOAD_FREG_FTN(WT0, fs);
5046 GEN_LOAD_FREG_FTN(WT1, ft);
5047 gen_op_float_sub_s();
5048 GEN_STORE_FTN_FREG(fd, WT2);
5049 opn = "sub.s";
5050 optype = BINOP;
5051 break;
5052 case FOP(2, 16):
5053 GEN_LOAD_FREG_FTN(WT0, fs);
5054 GEN_LOAD_FREG_FTN(WT1, ft);
5055 gen_op_float_mul_s();
5056 GEN_STORE_FTN_FREG(fd, WT2);
5057 opn = "mul.s";
5058 optype = BINOP;
5059 break;
5060 case FOP(3, 16):
5061 GEN_LOAD_FREG_FTN(WT0, fs);
5062 GEN_LOAD_FREG_FTN(WT1, ft);
5063 gen_op_float_div_s();
5064 GEN_STORE_FTN_FREG(fd, WT2);
5065 opn = "div.s";
5066 optype = BINOP;
5067 break;
5068 case FOP(4, 16):
5069 GEN_LOAD_FREG_FTN(WT0, fs);
5070 gen_op_float_sqrt_s();
5071 GEN_STORE_FTN_FREG(fd, WT2);
5072 opn = "sqrt.s";
5073 break;
5074 case FOP(5, 16):
5075 GEN_LOAD_FREG_FTN(WT0, fs);
5076 gen_op_float_abs_s();
5077 GEN_STORE_FTN_FREG(fd, WT2);
5078 opn = "abs.s";
5079 break;
5080 case FOP(6, 16):
5081 GEN_LOAD_FREG_FTN(WT0, fs);
5082 gen_op_float_mov_s();
5083 GEN_STORE_FTN_FREG(fd, WT2);
5084 opn = "mov.s";
5085 break;
5086 case FOP(7, 16):
5087 GEN_LOAD_FREG_FTN(WT0, fs);
5088 gen_op_float_chs_s();
5089 GEN_STORE_FTN_FREG(fd, WT2);
5090 opn = "neg.s";
5091 break;
5092 case FOP(8, 16):
5093 check_cp1_64bitmode(ctx);
5094 GEN_LOAD_FREG_FTN(WT0, fs);
5095 gen_op_float_roundl_s();
5096 GEN_STORE_FTN_FREG(fd, DT2);
5097 opn = "round.l.s";
5098 break;
5099 case FOP(9, 16):
5100 check_cp1_64bitmode(ctx);
5101 GEN_LOAD_FREG_FTN(WT0, fs);
5102 gen_op_float_truncl_s();
5103 GEN_STORE_FTN_FREG(fd, DT2);
5104 opn = "trunc.l.s";
5105 break;
5106 case FOP(10, 16):
5107 check_cp1_64bitmode(ctx);
5108 GEN_LOAD_FREG_FTN(WT0, fs);
5109 gen_op_float_ceill_s();
5110 GEN_STORE_FTN_FREG(fd, DT2);
5111 opn = "ceil.l.s";
5112 break;
5113 case FOP(11, 16):
5114 check_cp1_64bitmode(ctx);
5115 GEN_LOAD_FREG_FTN(WT0, fs);
5116 gen_op_float_floorl_s();
5117 GEN_STORE_FTN_FREG(fd, DT2);
5118 opn = "floor.l.s";
5119 break;
5120 case FOP(12, 16):
5121 GEN_LOAD_FREG_FTN(WT0, fs);
5122 gen_op_float_roundw_s();
5123 GEN_STORE_FTN_FREG(fd, WT2);
5124 opn = "round.w.s";
5125 break;
5126 case FOP(13, 16):
5127 GEN_LOAD_FREG_FTN(WT0, fs);
5128 gen_op_float_truncw_s();
5129 GEN_STORE_FTN_FREG(fd, WT2);
5130 opn = "trunc.w.s";
5131 break;
5132 case FOP(14, 16):
5133 GEN_LOAD_FREG_FTN(WT0, fs);
5134 gen_op_float_ceilw_s();
5135 GEN_STORE_FTN_FREG(fd, WT2);
5136 opn = "ceil.w.s";
5137 break;
5138 case FOP(15, 16):
5139 GEN_LOAD_FREG_FTN(WT0, fs);
5140 gen_op_float_floorw_s();
5141 GEN_STORE_FTN_FREG(fd, WT2);
5142 opn = "floor.w.s";
5143 break;
5144 case FOP(17, 16):
5145 GEN_LOAD_REG_T0(ft);
5146 GEN_LOAD_FREG_FTN(WT0, fs);
5147 GEN_LOAD_FREG_FTN(WT2, fd);
5148 gen_movcf_s(ctx, (ft >> 2) & 0x7, ft & 0x1);
5149 GEN_STORE_FTN_FREG(fd, WT2);
5150 opn = "movcf.s";
5151 break;
5152 case FOP(18, 16):
5153 GEN_LOAD_REG_T0(ft);
5154 GEN_LOAD_FREG_FTN(WT0, fs);
5155 GEN_LOAD_FREG_FTN(WT2, fd);
5156 gen_op_float_movz_s();
5157 GEN_STORE_FTN_FREG(fd, WT2);
5158 opn = "movz.s";
5159 break;
5160 case FOP(19, 16):
5161 GEN_LOAD_REG_T0(ft);
5162 GEN_LOAD_FREG_FTN(WT0, fs);
5163 GEN_LOAD_FREG_FTN(WT2, fd);
5164 gen_op_float_movn_s();
5165 GEN_STORE_FTN_FREG(fd, WT2);
5166 opn = "movn.s";
5167 break;
5168 case FOP(21, 16):
5169 check_cop1x(ctx);
5170 GEN_LOAD_FREG_FTN(WT0, fs);
5171 gen_op_float_recip_s();
5172 GEN_STORE_FTN_FREG(fd, WT2);
5173 opn = "recip.s";
5174 break;
5175 case FOP(22, 16):
5176 check_cop1x(ctx);
5177 GEN_LOAD_FREG_FTN(WT0, fs);
5178 gen_op_float_rsqrt_s();
5179 GEN_STORE_FTN_FREG(fd, WT2);
5180 opn = "rsqrt.s";
5181 break;
5182 case FOP(28, 16):
5183 check_cp1_64bitmode(ctx);
5184 GEN_LOAD_FREG_FTN(WT0, fs);
5185 GEN_LOAD_FREG_FTN(WT2, fd);
5186 gen_op_float_recip2_s();
5187 GEN_STORE_FTN_FREG(fd, WT2);
5188 opn = "recip2.s";
5189 break;
5190 case FOP(29, 16):
5191 check_cp1_64bitmode(ctx);
5192 GEN_LOAD_FREG_FTN(WT0, fs);
5193 gen_op_float_recip1_s();
5194 GEN_STORE_FTN_FREG(fd, WT2);
5195 opn = "recip1.s";
5196 break;
5197 case FOP(30, 16):
5198 check_cp1_64bitmode(ctx);
5199 GEN_LOAD_FREG_FTN(WT0, fs);
5200 gen_op_float_rsqrt1_s();
5201 GEN_STORE_FTN_FREG(fd, WT2);
5202 opn = "rsqrt1.s";
5203 break;
5204 case FOP(31, 16):
5205 check_cp1_64bitmode(ctx);
5206 GEN_LOAD_FREG_FTN(WT0, fs);
5207 GEN_LOAD_FREG_FTN(WT2, ft);
5208 gen_op_float_rsqrt2_s();
5209 GEN_STORE_FTN_FREG(fd, WT2);
5210 opn = "rsqrt2.s";
5211 break;
5212 case FOP(33, 16):
5213 check_cp1_registers(ctx, fd);
5214 GEN_LOAD_FREG_FTN(WT0, fs);
5215 gen_op_float_cvtd_s();
5216 GEN_STORE_FTN_FREG(fd, DT2);
5217 opn = "cvt.d.s";
5218 break;
5219 case FOP(36, 16):
5220 GEN_LOAD_FREG_FTN(WT0, fs);
5221 gen_op_float_cvtw_s();
5222 GEN_STORE_FTN_FREG(fd, WT2);
5223 opn = "cvt.w.s";
5224 break;
5225 case FOP(37, 16):
5226 check_cp1_64bitmode(ctx);
5227 GEN_LOAD_FREG_FTN(WT0, fs);
5228 gen_op_float_cvtl_s();
5229 GEN_STORE_FTN_FREG(fd, DT2);
5230 opn = "cvt.l.s";
5231 break;
5232 case FOP(38, 16):
5233 check_cp1_64bitmode(ctx);
5234 GEN_LOAD_FREG_FTN(WT1, fs);
5235 GEN_LOAD_FREG_FTN(WT0, ft);
5236 gen_op_float_cvtps_s();
5237 GEN_STORE_FTN_FREG(fd, DT2);
5238 opn = "cvt.ps.s";
5239 break;
5240 case FOP(48, 16):
5241 case FOP(49, 16):
5242 case FOP(50, 16):
5243 case FOP(51, 16):
5244 case FOP(52, 16):
5245 case FOP(53, 16):
5246 case FOP(54, 16):
5247 case FOP(55, 16):
5248 case FOP(56, 16):
5249 case FOP(57, 16):
5250 case FOP(58, 16):
5251 case FOP(59, 16):
5252 case FOP(60, 16):
5253 case FOP(61, 16):
5254 case FOP(62, 16):
5255 case FOP(63, 16):
5256 GEN_LOAD_FREG_FTN(WT0, fs);
5257 GEN_LOAD_FREG_FTN(WT1, ft);
5258 if (ctx->opcode & (1 << 6)) {
5259 check_cop1x(ctx);
5260 gen_cmpabs_s(func-48, cc);
5261 opn = condnames_abs[func-48];
5262 } else {
5263 gen_cmp_s(func-48, cc);
5264 opn = condnames[func-48];
5266 break;
5267 case FOP(0, 17):
5268 check_cp1_registers(ctx, fs | ft | fd);
5269 GEN_LOAD_FREG_FTN(DT0, fs);
5270 GEN_LOAD_FREG_FTN(DT1, ft);
5271 gen_op_float_add_d();
5272 GEN_STORE_FTN_FREG(fd, DT2);
5273 opn = "add.d";
5274 optype = BINOP;
5275 break;
5276 case FOP(1, 17):
5277 check_cp1_registers(ctx, fs | ft | fd);
5278 GEN_LOAD_FREG_FTN(DT0, fs);
5279 GEN_LOAD_FREG_FTN(DT1, ft);
5280 gen_op_float_sub_d();
5281 GEN_STORE_FTN_FREG(fd, DT2);
5282 opn = "sub.d";
5283 optype = BINOP;
5284 break;
5285 case FOP(2, 17):
5286 check_cp1_registers(ctx, fs | ft | fd);
5287 GEN_LOAD_FREG_FTN(DT0, fs);
5288 GEN_LOAD_FREG_FTN(DT1, ft);
5289 gen_op_float_mul_d();
5290 GEN_STORE_FTN_FREG(fd, DT2);
5291 opn = "mul.d";
5292 optype = BINOP;
5293 break;
5294 case FOP(3, 17):
5295 check_cp1_registers(ctx, fs | ft | fd);
5296 GEN_LOAD_FREG_FTN(DT0, fs);
5297 GEN_LOAD_FREG_FTN(DT1, ft);
5298 gen_op_float_div_d();
5299 GEN_STORE_FTN_FREG(fd, DT2);
5300 opn = "div.d";
5301 optype = BINOP;
5302 break;
5303 case FOP(4, 17):
5304 check_cp1_registers(ctx, fs | fd);
5305 GEN_LOAD_FREG_FTN(DT0, fs);
5306 gen_op_float_sqrt_d();
5307 GEN_STORE_FTN_FREG(fd, DT2);
5308 opn = "sqrt.d";
5309 break;
5310 case FOP(5, 17):
5311 check_cp1_registers(ctx, fs | fd);
5312 GEN_LOAD_FREG_FTN(DT0, fs);
5313 gen_op_float_abs_d();
5314 GEN_STORE_FTN_FREG(fd, DT2);
5315 opn = "abs.d";
5316 break;
5317 case FOP(6, 17):
5318 check_cp1_registers(ctx, fs | fd);
5319 GEN_LOAD_FREG_FTN(DT0, fs);
5320 gen_op_float_mov_d();
5321 GEN_STORE_FTN_FREG(fd, DT2);
5322 opn = "mov.d";
5323 break;
5324 case FOP(7, 17):
5325 check_cp1_registers(ctx, fs | fd);
5326 GEN_LOAD_FREG_FTN(DT0, fs);
5327 gen_op_float_chs_d();
5328 GEN_STORE_FTN_FREG(fd, DT2);
5329 opn = "neg.d";
5330 break;
5331 case FOP(8, 17):
5332 check_cp1_64bitmode(ctx);
5333 GEN_LOAD_FREG_FTN(DT0, fs);
5334 gen_op_float_roundl_d();
5335 GEN_STORE_FTN_FREG(fd, DT2);
5336 opn = "round.l.d";
5337 break;
5338 case FOP(9, 17):
5339 check_cp1_64bitmode(ctx);
5340 GEN_LOAD_FREG_FTN(DT0, fs);
5341 gen_op_float_truncl_d();
5342 GEN_STORE_FTN_FREG(fd, DT2);
5343 opn = "trunc.l.d";
5344 break;
5345 case FOP(10, 17):
5346 check_cp1_64bitmode(ctx);
5347 GEN_LOAD_FREG_FTN(DT0, fs);
5348 gen_op_float_ceill_d();
5349 GEN_STORE_FTN_FREG(fd, DT2);
5350 opn = "ceil.l.d";
5351 break;
5352 case FOP(11, 17):
5353 check_cp1_64bitmode(ctx);
5354 GEN_LOAD_FREG_FTN(DT0, fs);
5355 gen_op_float_floorl_d();
5356 GEN_STORE_FTN_FREG(fd, DT2);
5357 opn = "floor.l.d";
5358 break;
5359 case FOP(12, 17):
5360 check_cp1_registers(ctx, fs);
5361 GEN_LOAD_FREG_FTN(DT0, fs);
5362 gen_op_float_roundw_d();
5363 GEN_STORE_FTN_FREG(fd, WT2);
5364 opn = "round.w.d";
5365 break;
5366 case FOP(13, 17):
5367 check_cp1_registers(ctx, fs);
5368 GEN_LOAD_FREG_FTN(DT0, fs);
5369 gen_op_float_truncw_d();
5370 GEN_STORE_FTN_FREG(fd, WT2);
5371 opn = "trunc.w.d";
5372 break;
5373 case FOP(14, 17):
5374 check_cp1_registers(ctx, fs);
5375 GEN_LOAD_FREG_FTN(DT0, fs);
5376 gen_op_float_ceilw_d();
5377 GEN_STORE_FTN_FREG(fd, WT2);
5378 opn = "ceil.w.d";
5379 break;
5380 case FOP(15, 17):
5381 check_cp1_registers(ctx, fs);
5382 GEN_LOAD_FREG_FTN(DT0, fs);
5383 gen_op_float_floorw_d();
5384 GEN_STORE_FTN_FREG(fd, WT2);
5385 opn = "floor.w.d";
5386 break;
5387 case FOP(17, 17):
5388 GEN_LOAD_REG_T0(ft);
5389 GEN_LOAD_FREG_FTN(DT0, fs);
5390 GEN_LOAD_FREG_FTN(DT2, fd);
5391 gen_movcf_d(ctx, (ft >> 2) & 0x7, ft & 0x1);
5392 GEN_STORE_FTN_FREG(fd, DT2);
5393 opn = "movcf.d";
5394 break;
5395 case FOP(18, 17):
5396 GEN_LOAD_REG_T0(ft);
5397 GEN_LOAD_FREG_FTN(DT0, fs);
5398 GEN_LOAD_FREG_FTN(DT2, fd);
5399 gen_op_float_movz_d();
5400 GEN_STORE_FTN_FREG(fd, DT2);
5401 opn = "movz.d";
5402 break;
5403 case FOP(19, 17):
5404 GEN_LOAD_REG_T0(ft);
5405 GEN_LOAD_FREG_FTN(DT0, fs);
5406 GEN_LOAD_FREG_FTN(DT2, fd);
5407 gen_op_float_movn_d();
5408 GEN_STORE_FTN_FREG(fd, DT2);
5409 opn = "movn.d";
5410 break;
5411 case FOP(21, 17):
5412 check_cp1_64bitmode(ctx);
5413 GEN_LOAD_FREG_FTN(DT0, fs);
5414 gen_op_float_recip_d();
5415 GEN_STORE_FTN_FREG(fd, DT2);
5416 opn = "recip.d";
5417 break;
5418 case FOP(22, 17):
5419 check_cp1_64bitmode(ctx);
5420 GEN_LOAD_FREG_FTN(DT0, fs);
5421 gen_op_float_rsqrt_d();
5422 GEN_STORE_FTN_FREG(fd, DT2);
5423 opn = "rsqrt.d";
5424 break;
5425 case FOP(28, 17):
5426 check_cp1_64bitmode(ctx);
5427 GEN_LOAD_FREG_FTN(DT0, fs);
5428 GEN_LOAD_FREG_FTN(DT2, ft);
5429 gen_op_float_recip2_d();
5430 GEN_STORE_FTN_FREG(fd, DT2);
5431 opn = "recip2.d";
5432 break;
5433 case FOP(29, 17):
5434 check_cp1_64bitmode(ctx);
5435 GEN_LOAD_FREG_FTN(DT0, fs);
5436 gen_op_float_recip1_d();
5437 GEN_STORE_FTN_FREG(fd, DT2);
5438 opn = "recip1.d";
5439 break;
5440 case FOP(30, 17):
5441 check_cp1_64bitmode(ctx);
5442 GEN_LOAD_FREG_FTN(DT0, fs);
5443 gen_op_float_rsqrt1_d();
5444 GEN_STORE_FTN_FREG(fd, DT2);
5445 opn = "rsqrt1.d";
5446 break;
5447 case FOP(31, 17):
5448 check_cp1_64bitmode(ctx);
5449 GEN_LOAD_FREG_FTN(DT0, fs);
5450 GEN_LOAD_FREG_FTN(DT2, ft);
5451 gen_op_float_rsqrt2_d();
5452 GEN_STORE_FTN_FREG(fd, DT2);
5453 opn = "rsqrt2.d";
5454 break;
5455 case FOP(48, 17):
5456 case FOP(49, 17):
5457 case FOP(50, 17):
5458 case FOP(51, 17):
5459 case FOP(52, 17):
5460 case FOP(53, 17):
5461 case FOP(54, 17):
5462 case FOP(55, 17):
5463 case FOP(56, 17):
5464 case FOP(57, 17):
5465 case FOP(58, 17):
5466 case FOP(59, 17):
5467 case FOP(60, 17):
5468 case FOP(61, 17):
5469 case FOP(62, 17):
5470 case FOP(63, 17):
5471 GEN_LOAD_FREG_FTN(DT0, fs);
5472 GEN_LOAD_FREG_FTN(DT1, ft);
5473 if (ctx->opcode & (1 << 6)) {
5474 check_cop1x(ctx);
5475 check_cp1_registers(ctx, fs | ft);
5476 gen_cmpabs_d(func-48, cc);
5477 opn = condnames_abs[func-48];
5478 } else {
5479 check_cp1_registers(ctx, fs | ft);
5480 gen_cmp_d(func-48, cc);
5481 opn = condnames[func-48];
5483 break;
5484 case FOP(32, 17):
5485 check_cp1_registers(ctx, fs);
5486 GEN_LOAD_FREG_FTN(DT0, fs);
5487 gen_op_float_cvts_d();
5488 GEN_STORE_FTN_FREG(fd, WT2);
5489 opn = "cvt.s.d";
5490 break;
5491 case FOP(36, 17):
5492 check_cp1_registers(ctx, fs);
5493 GEN_LOAD_FREG_FTN(DT0, fs);
5494 gen_op_float_cvtw_d();
5495 GEN_STORE_FTN_FREG(fd, WT2);
5496 opn = "cvt.w.d";
5497 break;
5498 case FOP(37, 17):
5499 check_cp1_64bitmode(ctx);
5500 GEN_LOAD_FREG_FTN(DT0, fs);
5501 gen_op_float_cvtl_d();
5502 GEN_STORE_FTN_FREG(fd, DT2);
5503 opn = "cvt.l.d";
5504 break;
5505 case FOP(32, 20):
5506 GEN_LOAD_FREG_FTN(WT0, fs);
5507 gen_op_float_cvts_w();
5508 GEN_STORE_FTN_FREG(fd, WT2);
5509 opn = "cvt.s.w";
5510 break;
5511 case FOP(33, 20):
5512 check_cp1_registers(ctx, fd);
5513 GEN_LOAD_FREG_FTN(WT0, fs);
5514 gen_op_float_cvtd_w();
5515 GEN_STORE_FTN_FREG(fd, DT2);
5516 opn = "cvt.d.w";
5517 break;
5518 case FOP(32, 21):
5519 check_cp1_64bitmode(ctx);
5520 GEN_LOAD_FREG_FTN(DT0, fs);
5521 gen_op_float_cvts_l();
5522 GEN_STORE_FTN_FREG(fd, WT2);
5523 opn = "cvt.s.l";
5524 break;
5525 case FOP(33, 21):
5526 check_cp1_64bitmode(ctx);
5527 GEN_LOAD_FREG_FTN(DT0, fs);
5528 gen_op_float_cvtd_l();
5529 GEN_STORE_FTN_FREG(fd, DT2);
5530 opn = "cvt.d.l";
5531 break;
5532 case FOP(38, 20):
5533 check_cp1_64bitmode(ctx);
5534 GEN_LOAD_FREG_FTN(WT0, fs);
5535 GEN_LOAD_FREG_FTN(WTH0, fs);
5536 gen_op_float_cvtps_pw();
5537 GEN_STORE_FTN_FREG(fd, WT2);
5538 GEN_STORE_FTN_FREG(fd, WTH2);
5539 opn = "cvt.ps.pw";
5540 break;
5541 case FOP(0, 22):
5542 check_cp1_64bitmode(ctx);
5543 GEN_LOAD_FREG_FTN(WT0, fs);
5544 GEN_LOAD_FREG_FTN(WTH0, fs);
5545 GEN_LOAD_FREG_FTN(WT1, ft);
5546 GEN_LOAD_FREG_FTN(WTH1, ft);
5547 gen_op_float_add_ps();
5548 GEN_STORE_FTN_FREG(fd, WT2);
5549 GEN_STORE_FTN_FREG(fd, WTH2);
5550 opn = "add.ps";
5551 break;
5552 case FOP(1, 22):
5553 check_cp1_64bitmode(ctx);
5554 GEN_LOAD_FREG_FTN(WT0, fs);
5555 GEN_LOAD_FREG_FTN(WTH0, fs);
5556 GEN_LOAD_FREG_FTN(WT1, ft);
5557 GEN_LOAD_FREG_FTN(WTH1, ft);
5558 gen_op_float_sub_ps();
5559 GEN_STORE_FTN_FREG(fd, WT2);
5560 GEN_STORE_FTN_FREG(fd, WTH2);
5561 opn = "sub.ps";
5562 break;
5563 case FOP(2, 22):
5564 check_cp1_64bitmode(ctx);
5565 GEN_LOAD_FREG_FTN(WT0, fs);
5566 GEN_LOAD_FREG_FTN(WTH0, fs);
5567 GEN_LOAD_FREG_FTN(WT1, ft);
5568 GEN_LOAD_FREG_FTN(WTH1, ft);
5569 gen_op_float_mul_ps();
5570 GEN_STORE_FTN_FREG(fd, WT2);
5571 GEN_STORE_FTN_FREG(fd, WTH2);
5572 opn = "mul.ps";
5573 break;
5574 case FOP(5, 22):
5575 check_cp1_64bitmode(ctx);
5576 GEN_LOAD_FREG_FTN(WT0, fs);
5577 GEN_LOAD_FREG_FTN(WTH0, fs);
5578 gen_op_float_abs_ps();
5579 GEN_STORE_FTN_FREG(fd, WT2);
5580 GEN_STORE_FTN_FREG(fd, WTH2);
5581 opn = "abs.ps";
5582 break;
5583 case FOP(6, 22):
5584 check_cp1_64bitmode(ctx);
5585 GEN_LOAD_FREG_FTN(WT0, fs);
5586 GEN_LOAD_FREG_FTN(WTH0, fs);
5587 gen_op_float_mov_ps();
5588 GEN_STORE_FTN_FREG(fd, WT2);
5589 GEN_STORE_FTN_FREG(fd, WTH2);
5590 opn = "mov.ps";
5591 break;
5592 case FOP(7, 22):
5593 check_cp1_64bitmode(ctx);
5594 GEN_LOAD_FREG_FTN(WT0, fs);
5595 GEN_LOAD_FREG_FTN(WTH0, fs);
5596 gen_op_float_chs_ps();
5597 GEN_STORE_FTN_FREG(fd, WT2);
5598 GEN_STORE_FTN_FREG(fd, WTH2);
5599 opn = "neg.ps";
5600 break;
5601 case FOP(17, 22):
5602 check_cp1_64bitmode(ctx);
5603 GEN_LOAD_REG_T0(ft);
5604 GEN_LOAD_FREG_FTN(WT0, fs);
5605 GEN_LOAD_FREG_FTN(WTH0, fs);
5606 GEN_LOAD_FREG_FTN(WT2, fd);
5607 GEN_LOAD_FREG_FTN(WTH2, fd);
5608 gen_movcf_ps(ctx, (ft >> 2) & 0x7, ft & 0x1);
5609 GEN_STORE_FTN_FREG(fd, WT2);
5610 GEN_STORE_FTN_FREG(fd, WTH2);
5611 opn = "movcf.ps";
5612 break;
5613 case FOP(18, 22):
5614 check_cp1_64bitmode(ctx);
5615 GEN_LOAD_REG_T0(ft);
5616 GEN_LOAD_FREG_FTN(WT0, fs);
5617 GEN_LOAD_FREG_FTN(WTH0, fs);
5618 GEN_LOAD_FREG_FTN(WT2, fd);
5619 GEN_LOAD_FREG_FTN(WTH2, fd);
5620 gen_op_float_movz_ps();
5621 GEN_STORE_FTN_FREG(fd, WT2);
5622 GEN_STORE_FTN_FREG(fd, WTH2);
5623 opn = "movz.ps";
5624 break;
5625 case FOP(19, 22):
5626 check_cp1_64bitmode(ctx);
5627 GEN_LOAD_REG_T0(ft);
5628 GEN_LOAD_FREG_FTN(WT0, fs);
5629 GEN_LOAD_FREG_FTN(WTH0, fs);
5630 GEN_LOAD_FREG_FTN(WT2, fd);
5631 GEN_LOAD_FREG_FTN(WTH2, fd);
5632 gen_op_float_movn_ps();
5633 GEN_STORE_FTN_FREG(fd, WT2);
5634 GEN_STORE_FTN_FREG(fd, WTH2);
5635 opn = "movn.ps";
5636 break;
5637 case FOP(24, 22):
5638 check_cp1_64bitmode(ctx);
5639 GEN_LOAD_FREG_FTN(WT0, ft);
5640 GEN_LOAD_FREG_FTN(WTH0, ft);
5641 GEN_LOAD_FREG_FTN(WT1, fs);
5642 GEN_LOAD_FREG_FTN(WTH1, fs);
5643 gen_op_float_addr_ps();
5644 GEN_STORE_FTN_FREG(fd, WT2);
5645 GEN_STORE_FTN_FREG(fd, WTH2);
5646 opn = "addr.ps";
5647 break;
5648 case FOP(26, 22):
5649 check_cp1_64bitmode(ctx);
5650 GEN_LOAD_FREG_FTN(WT0, ft);
5651 GEN_LOAD_FREG_FTN(WTH0, ft);
5652 GEN_LOAD_FREG_FTN(WT1, fs);
5653 GEN_LOAD_FREG_FTN(WTH1, fs);
5654 gen_op_float_mulr_ps();
5655 GEN_STORE_FTN_FREG(fd, WT2);
5656 GEN_STORE_FTN_FREG(fd, WTH2);
5657 opn = "mulr.ps";
5658 break;
5659 case FOP(28, 22):
5660 check_cp1_64bitmode(ctx);
5661 GEN_LOAD_FREG_FTN(WT0, fs);
5662 GEN_LOAD_FREG_FTN(WTH0, fs);
5663 GEN_LOAD_FREG_FTN(WT2, fd);
5664 GEN_LOAD_FREG_FTN(WTH2, fd);
5665 gen_op_float_recip2_ps();
5666 GEN_STORE_FTN_FREG(fd, WT2);
5667 GEN_STORE_FTN_FREG(fd, WTH2);
5668 opn = "recip2.ps";
5669 break;
5670 case FOP(29, 22):
5671 check_cp1_64bitmode(ctx);
5672 GEN_LOAD_FREG_FTN(WT0, fs);
5673 GEN_LOAD_FREG_FTN(WTH0, fs);
5674 gen_op_float_recip1_ps();
5675 GEN_STORE_FTN_FREG(fd, WT2);
5676 GEN_STORE_FTN_FREG(fd, WTH2);
5677 opn = "recip1.ps";
5678 break;
5679 case FOP(30, 22):
5680 check_cp1_64bitmode(ctx);
5681 GEN_LOAD_FREG_FTN(WT0, fs);
5682 GEN_LOAD_FREG_FTN(WTH0, fs);
5683 gen_op_float_rsqrt1_ps();
5684 GEN_STORE_FTN_FREG(fd, WT2);
5685 GEN_STORE_FTN_FREG(fd, WTH2);
5686 opn = "rsqrt1.ps";
5687 break;
5688 case FOP(31, 22):
5689 check_cp1_64bitmode(ctx);
5690 GEN_LOAD_FREG_FTN(WT0, fs);
5691 GEN_LOAD_FREG_FTN(WTH0, fs);
5692 GEN_LOAD_FREG_FTN(WT2, ft);
5693 GEN_LOAD_FREG_FTN(WTH2, ft);
5694 gen_op_float_rsqrt2_ps();
5695 GEN_STORE_FTN_FREG(fd, WT2);
5696 GEN_STORE_FTN_FREG(fd, WTH2);
5697 opn = "rsqrt2.ps";
5698 break;
5699 case FOP(32, 22):
5700 check_cp1_64bitmode(ctx);
5701 GEN_LOAD_FREG_FTN(WTH0, fs);
5702 gen_op_float_cvts_pu();
5703 GEN_STORE_FTN_FREG(fd, WT2);
5704 opn = "cvt.s.pu";
5705 break;
5706 case FOP(36, 22):
5707 check_cp1_64bitmode(ctx);
5708 GEN_LOAD_FREG_FTN(WT0, fs);
5709 GEN_LOAD_FREG_FTN(WTH0, fs);
5710 gen_op_float_cvtpw_ps();
5711 GEN_STORE_FTN_FREG(fd, WT2);
5712 GEN_STORE_FTN_FREG(fd, WTH2);
5713 opn = "cvt.pw.ps";
5714 break;
5715 case FOP(40, 22):
5716 check_cp1_64bitmode(ctx);
5717 GEN_LOAD_FREG_FTN(WT0, fs);
5718 gen_op_float_cvts_pl();
5719 GEN_STORE_FTN_FREG(fd, WT2);
5720 opn = "cvt.s.pl";
5721 break;
5722 case FOP(44, 22):
5723 check_cp1_64bitmode(ctx);
5724 GEN_LOAD_FREG_FTN(WT0, fs);
5725 GEN_LOAD_FREG_FTN(WT1, ft);
5726 gen_op_float_pll_ps();
5727 GEN_STORE_FTN_FREG(fd, DT2);
5728 opn = "pll.ps";
5729 break;
5730 case FOP(45, 22):
5731 check_cp1_64bitmode(ctx);
5732 GEN_LOAD_FREG_FTN(WT0, fs);
5733 GEN_LOAD_FREG_FTN(WTH1, ft);
5734 gen_op_float_plu_ps();
5735 GEN_STORE_FTN_FREG(fd, DT2);
5736 opn = "plu.ps";
5737 break;
5738 case FOP(46, 22):
5739 check_cp1_64bitmode(ctx);
5740 GEN_LOAD_FREG_FTN(WTH0, fs);
5741 GEN_LOAD_FREG_FTN(WT1, ft);
5742 gen_op_float_pul_ps();
5743 GEN_STORE_FTN_FREG(fd, DT2);
5744 opn = "pul.ps";
5745 break;
5746 case FOP(47, 22):
5747 check_cp1_64bitmode(ctx);
5748 GEN_LOAD_FREG_FTN(WTH0, fs);
5749 GEN_LOAD_FREG_FTN(WTH1, ft);
5750 gen_op_float_puu_ps();
5751 GEN_STORE_FTN_FREG(fd, DT2);
5752 opn = "puu.ps";
5753 break;
5754 case FOP(48, 22):
5755 case FOP(49, 22):
5756 case FOP(50, 22):
5757 case FOP(51, 22):
5758 case FOP(52, 22):
5759 case FOP(53, 22):
5760 case FOP(54, 22):
5761 case FOP(55, 22):
5762 case FOP(56, 22):
5763 case FOP(57, 22):
5764 case FOP(58, 22):
5765 case FOP(59, 22):
5766 case FOP(60, 22):
5767 case FOP(61, 22):
5768 case FOP(62, 22):
5769 case FOP(63, 22):
5770 check_cp1_64bitmode(ctx);
5771 GEN_LOAD_FREG_FTN(WT0, fs);
5772 GEN_LOAD_FREG_FTN(WTH0, fs);
5773 GEN_LOAD_FREG_FTN(WT1, ft);
5774 GEN_LOAD_FREG_FTN(WTH1, ft);
5775 if (ctx->opcode & (1 << 6)) {
5776 gen_cmpabs_ps(func-48, cc);
5777 opn = condnames_abs[func-48];
5778 } else {
5779 gen_cmp_ps(func-48, cc);
5780 opn = condnames[func-48];
5782 break;
5783 default:
5784 MIPS_INVAL(opn);
5785 generate_exception (ctx, EXCP_RI);
5786 return;
5788 switch (optype) {
5789 case BINOP:
5790 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5791 break;
5792 case CMPOP:
5793 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
5794 break;
5795 default:
5796 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5797 break;
5801 /* Coprocessor 3 (FPU) */
5802 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
5803 int fd, int fs, int base, int index)
5805 const char *opn = "extended float load/store";
5806 int store = 0;
5808 if (base == 0) {
5809 if (index == 0)
5810 gen_op_reset_T0();
5811 else
5812 GEN_LOAD_REG_T0(index);
5813 } else if (index == 0) {
5814 GEN_LOAD_REG_T0(base);
5815 } else {
5816 GEN_LOAD_REG_T0(base);
5817 GEN_LOAD_REG_T1(index);
5818 gen_op_addr_add();
5820 /* Don't do NOP if destination is zero: we must perform the actual
5821 memory access. */
5822 switch (opc) {
5823 case OPC_LWXC1:
5824 check_cop1x(ctx);
5825 op_ldst(lwc1);
5826 GEN_STORE_FTN_FREG(fd, WT0);
5827 opn = "lwxc1";
5828 break;
5829 case OPC_LDXC1:
5830 check_cop1x(ctx);
5831 check_cp1_registers(ctx, fd);
5832 op_ldst(ldc1);
5833 GEN_STORE_FTN_FREG(fd, DT0);
5834 opn = "ldxc1";
5835 break;
5836 case OPC_LUXC1:
5837 check_cp1_64bitmode(ctx);
5838 op_ldst(luxc1);
5839 GEN_STORE_FTN_FREG(fd, DT0);
5840 opn = "luxc1";
5841 break;
5842 case OPC_SWXC1:
5843 check_cop1x(ctx);
5844 GEN_LOAD_FREG_FTN(WT0, fs);
5845 op_ldst(swc1);
5846 opn = "swxc1";
5847 store = 1;
5848 break;
5849 case OPC_SDXC1:
5850 check_cop1x(ctx);
5851 check_cp1_registers(ctx, fs);
5852 GEN_LOAD_FREG_FTN(DT0, fs);
5853 op_ldst(sdc1);
5854 opn = "sdxc1";
5855 store = 1;
5856 break;
5857 case OPC_SUXC1:
5858 check_cp1_64bitmode(ctx);
5859 GEN_LOAD_FREG_FTN(DT0, fs);
5860 op_ldst(suxc1);
5861 opn = "suxc1";
5862 store = 1;
5863 break;
5864 default:
5865 MIPS_INVAL(opn);
5866 generate_exception(ctx, EXCP_RI);
5867 return;
5869 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
5870 regnames[index], regnames[base]);
5873 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5874 int fd, int fr, int fs, int ft)
5876 const char *opn = "flt3_arith";
5878 switch (opc) {
5879 case OPC_ALNV_PS:
5880 check_cp1_64bitmode(ctx);
5881 GEN_LOAD_REG_T0(fr);
5882 GEN_LOAD_FREG_FTN(DT0, fs);
5883 GEN_LOAD_FREG_FTN(DT1, ft);
5884 gen_op_float_alnv_ps();
5885 GEN_STORE_FTN_FREG(fd, DT2);
5886 opn = "alnv.ps";
5887 break;
5888 case OPC_MADD_S:
5889 check_cop1x(ctx);
5890 GEN_LOAD_FREG_FTN(WT0, fs);
5891 GEN_LOAD_FREG_FTN(WT1, ft);
5892 GEN_LOAD_FREG_FTN(WT2, fr);
5893 gen_op_float_muladd_s();
5894 GEN_STORE_FTN_FREG(fd, WT2);
5895 opn = "madd.s";
5896 break;
5897 case OPC_MADD_D:
5898 check_cop1x(ctx);
5899 check_cp1_registers(ctx, fd | fs | ft | fr);
5900 GEN_LOAD_FREG_FTN(DT0, fs);
5901 GEN_LOAD_FREG_FTN(DT1, ft);
5902 GEN_LOAD_FREG_FTN(DT2, fr);
5903 gen_op_float_muladd_d();
5904 GEN_STORE_FTN_FREG(fd, DT2);
5905 opn = "madd.d";
5906 break;
5907 case OPC_MADD_PS:
5908 check_cp1_64bitmode(ctx);
5909 GEN_LOAD_FREG_FTN(WT0, fs);
5910 GEN_LOAD_FREG_FTN(WTH0, fs);
5911 GEN_LOAD_FREG_FTN(WT1, ft);
5912 GEN_LOAD_FREG_FTN(WTH1, ft);
5913 GEN_LOAD_FREG_FTN(WT2, fr);
5914 GEN_LOAD_FREG_FTN(WTH2, fr);
5915 gen_op_float_muladd_ps();
5916 GEN_STORE_FTN_FREG(fd, WT2);
5917 GEN_STORE_FTN_FREG(fd, WTH2);
5918 opn = "madd.ps";
5919 break;
5920 case OPC_MSUB_S:
5921 check_cop1x(ctx);
5922 GEN_LOAD_FREG_FTN(WT0, fs);
5923 GEN_LOAD_FREG_FTN(WT1, ft);
5924 GEN_LOAD_FREG_FTN(WT2, fr);
5925 gen_op_float_mulsub_s();
5926 GEN_STORE_FTN_FREG(fd, WT2);
5927 opn = "msub.s";
5928 break;
5929 case OPC_MSUB_D:
5930 check_cop1x(ctx);
5931 check_cp1_registers(ctx, fd | fs | ft | fr);
5932 GEN_LOAD_FREG_FTN(DT0, fs);
5933 GEN_LOAD_FREG_FTN(DT1, ft);
5934 GEN_LOAD_FREG_FTN(DT2, fr);
5935 gen_op_float_mulsub_d();
5936 GEN_STORE_FTN_FREG(fd, DT2);
5937 opn = "msub.d";
5938 break;
5939 case OPC_MSUB_PS:
5940 check_cp1_64bitmode(ctx);
5941 GEN_LOAD_FREG_FTN(WT0, fs);
5942 GEN_LOAD_FREG_FTN(WTH0, fs);
5943 GEN_LOAD_FREG_FTN(WT1, ft);
5944 GEN_LOAD_FREG_FTN(WTH1, ft);
5945 GEN_LOAD_FREG_FTN(WT2, fr);
5946 GEN_LOAD_FREG_FTN(WTH2, fr);
5947 gen_op_float_mulsub_ps();
5948 GEN_STORE_FTN_FREG(fd, WT2);
5949 GEN_STORE_FTN_FREG(fd, WTH2);
5950 opn = "msub.ps";
5951 break;
5952 case OPC_NMADD_S:
5953 check_cop1x(ctx);
5954 GEN_LOAD_FREG_FTN(WT0, fs);
5955 GEN_LOAD_FREG_FTN(WT1, ft);
5956 GEN_LOAD_FREG_FTN(WT2, fr);
5957 gen_op_float_nmuladd_s();
5958 GEN_STORE_FTN_FREG(fd, WT2);
5959 opn = "nmadd.s";
5960 break;
5961 case OPC_NMADD_D:
5962 check_cop1x(ctx);
5963 check_cp1_registers(ctx, fd | fs | ft | fr);
5964 GEN_LOAD_FREG_FTN(DT0, fs);
5965 GEN_LOAD_FREG_FTN(DT1, ft);
5966 GEN_LOAD_FREG_FTN(DT2, fr);
5967 gen_op_float_nmuladd_d();
5968 GEN_STORE_FTN_FREG(fd, DT2);
5969 opn = "nmadd.d";
5970 break;
5971 case OPC_NMADD_PS:
5972 check_cp1_64bitmode(ctx);
5973 GEN_LOAD_FREG_FTN(WT0, fs);
5974 GEN_LOAD_FREG_FTN(WTH0, fs);
5975 GEN_LOAD_FREG_FTN(WT1, ft);
5976 GEN_LOAD_FREG_FTN(WTH1, ft);
5977 GEN_LOAD_FREG_FTN(WT2, fr);
5978 GEN_LOAD_FREG_FTN(WTH2, fr);
5979 gen_op_float_nmuladd_ps();
5980 GEN_STORE_FTN_FREG(fd, WT2);
5981 GEN_STORE_FTN_FREG(fd, WTH2);
5982 opn = "nmadd.ps";
5983 break;
5984 case OPC_NMSUB_S:
5985 check_cop1x(ctx);
5986 GEN_LOAD_FREG_FTN(WT0, fs);
5987 GEN_LOAD_FREG_FTN(WT1, ft);
5988 GEN_LOAD_FREG_FTN(WT2, fr);
5989 gen_op_float_nmulsub_s();
5990 GEN_STORE_FTN_FREG(fd, WT2);
5991 opn = "nmsub.s";
5992 break;
5993 case OPC_NMSUB_D:
5994 check_cop1x(ctx);
5995 check_cp1_registers(ctx, fd | fs | ft | fr);
5996 GEN_LOAD_FREG_FTN(DT0, fs);
5997 GEN_LOAD_FREG_FTN(DT1, ft);
5998 GEN_LOAD_FREG_FTN(DT2, fr);
5999 gen_op_float_nmulsub_d();
6000 GEN_STORE_FTN_FREG(fd, DT2);
6001 opn = "nmsub.d";
6002 break;
6003 case OPC_NMSUB_PS:
6004 check_cp1_64bitmode(ctx);
6005 GEN_LOAD_FREG_FTN(WT0, fs);
6006 GEN_LOAD_FREG_FTN(WTH0, fs);
6007 GEN_LOAD_FREG_FTN(WT1, ft);
6008 GEN_LOAD_FREG_FTN(WTH1, ft);
6009 GEN_LOAD_FREG_FTN(WT2, fr);
6010 GEN_LOAD_FREG_FTN(WTH2, fr);
6011 gen_op_float_nmulsub_ps();
6012 GEN_STORE_FTN_FREG(fd, WT2);
6013 GEN_STORE_FTN_FREG(fd, WTH2);
6014 opn = "nmsub.ps";
6015 break;
6016 default:
6017 MIPS_INVAL(opn);
6018 generate_exception (ctx, EXCP_RI);
6019 return;
6021 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
6022 fregnames[fs], fregnames[ft]);
6025 /* ISA extensions (ASEs) */
6026 /* MIPS16 extension to MIPS32 */
6027 /* SmartMIPS extension to MIPS32 */
6029 #if defined(TARGET_MIPS64)
6031 /* MDMX extension to MIPS64 */
6033 #endif
6035 static void decode_opc (CPUState *env, DisasContext *ctx)
6037 int32_t offset;
6038 int rs, rt, rd, sa;
6039 uint32_t op, op1, op2;
6040 int16_t imm;
6042 /* make sure instructions are on a word boundary */
6043 if (ctx->pc & 0x3) {
6044 env->CP0_BadVAddr = ctx->pc;
6045 generate_exception(ctx, EXCP_AdEL);
6046 return;
6049 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
6050 int l1;
6051 /* Handle blikely not taken case */
6052 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
6053 l1 = gen_new_label();
6054 tcg_gen_jnz_bcond(l1);
6055 gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
6056 gen_goto_tb(ctx, 1, ctx->pc + 4);
6057 gen_set_label(l1);
6059 op = MASK_OP_MAJOR(ctx->opcode);
6060 rs = (ctx->opcode >> 21) & 0x1f;
6061 rt = (ctx->opcode >> 16) & 0x1f;
6062 rd = (ctx->opcode >> 11) & 0x1f;
6063 sa = (ctx->opcode >> 6) & 0x1f;
6064 imm = (int16_t)ctx->opcode;
6065 switch (op) {
6066 case OPC_SPECIAL:
6067 op1 = MASK_SPECIAL(ctx->opcode);
6068 switch (op1) {
6069 case OPC_SLL: /* Arithmetic with immediate */
6070 case OPC_SRL ... OPC_SRA:
6071 gen_arith_imm(env, ctx, op1, rd, rt, sa);
6072 break;
6073 case OPC_MOVZ ... OPC_MOVN:
6074 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6075 case OPC_SLLV: /* Arithmetic */
6076 case OPC_SRLV ... OPC_SRAV:
6077 case OPC_ADD ... OPC_NOR:
6078 case OPC_SLT ... OPC_SLTU:
6079 gen_arith(env, ctx, op1, rd, rs, rt);
6080 break;
6081 case OPC_MULT ... OPC_DIVU:
6082 if (sa) {
6083 check_insn(env, ctx, INSN_VR54XX);
6084 op1 = MASK_MUL_VR54XX(ctx->opcode);
6085 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
6086 } else
6087 gen_muldiv(ctx, op1, rs, rt);
6088 break;
6089 case OPC_JR ... OPC_JALR:
6090 gen_compute_branch(ctx, op1, rs, rd, sa);
6091 return;
6092 case OPC_TGE ... OPC_TEQ: /* Traps */
6093 case OPC_TNE:
6094 gen_trap(ctx, op1, rs, rt, -1);
6095 break;
6096 case OPC_MFHI: /* Move from HI/LO */
6097 case OPC_MFLO:
6098 gen_HILO(ctx, op1, rd);
6099 break;
6100 case OPC_MTHI:
6101 case OPC_MTLO: /* Move to HI/LO */
6102 gen_HILO(ctx, op1, rs);
6103 break;
6104 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
6105 #ifdef MIPS_STRICT_STANDARD
6106 MIPS_INVAL("PMON / selsl");
6107 generate_exception(ctx, EXCP_RI);
6108 #else
6109 gen_op_pmon(sa);
6110 #endif
6111 break;
6112 case OPC_SYSCALL:
6113 generate_exception(ctx, EXCP_SYSCALL);
6114 break;
6115 case OPC_BREAK:
6116 generate_exception(ctx, EXCP_BREAK);
6117 break;
6118 case OPC_SPIM:
6119 #ifdef MIPS_STRICT_STANDARD
6120 MIPS_INVAL("SPIM");
6121 generate_exception(ctx, EXCP_RI);
6122 #else
6123 /* Implemented as RI exception for now. */
6124 MIPS_INVAL("spim (unofficial)");
6125 generate_exception(ctx, EXCP_RI);
6126 #endif
6127 break;
6128 case OPC_SYNC:
6129 /* Treat as NOP. */
6130 break;
6132 case OPC_MOVCI:
6133 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6134 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
6135 save_cpu_state(ctx, 1);
6136 check_cp1_enabled(ctx);
6137 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
6138 (ctx->opcode >> 16) & 1);
6139 } else {
6140 generate_exception_err(ctx, EXCP_CpU, 1);
6142 break;
6144 #if defined(TARGET_MIPS64)
6145 /* MIPS64 specific opcodes */
6146 case OPC_DSLL:
6147 case OPC_DSRL ... OPC_DSRA:
6148 case OPC_DSLL32:
6149 case OPC_DSRL32 ... OPC_DSRA32:
6150 check_insn(env, ctx, ISA_MIPS3);
6151 check_mips_64(ctx);
6152 gen_arith_imm(env, ctx, op1, rd, rt, sa);
6153 break;
6154 case OPC_DSLLV:
6155 case OPC_DSRLV ... OPC_DSRAV:
6156 case OPC_DADD ... OPC_DSUBU:
6157 check_insn(env, ctx, ISA_MIPS3);
6158 check_mips_64(ctx);
6159 gen_arith(env, ctx, op1, rd, rs, rt);
6160 break;
6161 case OPC_DMULT ... OPC_DDIVU:
6162 check_insn(env, ctx, ISA_MIPS3);
6163 check_mips_64(ctx);
6164 gen_muldiv(ctx, op1, rs, rt);
6165 break;
6166 #endif
6167 default: /* Invalid */
6168 MIPS_INVAL("special");
6169 generate_exception(ctx, EXCP_RI);
6170 break;
6172 break;
6173 case OPC_SPECIAL2:
6174 op1 = MASK_SPECIAL2(ctx->opcode);
6175 switch (op1) {
6176 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
6177 case OPC_MSUB ... OPC_MSUBU:
6178 check_insn(env, ctx, ISA_MIPS32);
6179 gen_muldiv(ctx, op1, rs, rt);
6180 break;
6181 case OPC_MUL:
6182 gen_arith(env, ctx, op1, rd, rs, rt);
6183 break;
6184 case OPC_CLZ ... OPC_CLO:
6185 check_insn(env, ctx, ISA_MIPS32);
6186 gen_cl(ctx, op1, rd, rs);
6187 break;
6188 case OPC_SDBBP:
6189 /* XXX: not clear which exception should be raised
6190 * when in debug mode...
6192 check_insn(env, ctx, ISA_MIPS32);
6193 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
6194 generate_exception(ctx, EXCP_DBp);
6195 } else {
6196 generate_exception(ctx, EXCP_DBp);
6198 /* Treat as NOP. */
6199 break;
6200 #if defined(TARGET_MIPS64)
6201 case OPC_DCLZ ... OPC_DCLO:
6202 check_insn(env, ctx, ISA_MIPS64);
6203 check_mips_64(ctx);
6204 gen_cl(ctx, op1, rd, rs);
6205 break;
6206 #endif
6207 default: /* Invalid */
6208 MIPS_INVAL("special2");
6209 generate_exception(ctx, EXCP_RI);
6210 break;
6212 break;
6213 case OPC_SPECIAL3:
6214 op1 = MASK_SPECIAL3(ctx->opcode);
6215 switch (op1) {
6216 case OPC_EXT:
6217 case OPC_INS:
6218 check_insn(env, ctx, ISA_MIPS32R2);
6219 gen_bitops(ctx, op1, rt, rs, sa, rd);
6220 break;
6221 case OPC_BSHFL:
6222 check_insn(env, ctx, ISA_MIPS32R2);
6223 op2 = MASK_BSHFL(ctx->opcode);
6224 switch (op2) {
6225 case OPC_WSBH:
6226 GEN_LOAD_REG_T1(rt);
6227 gen_op_wsbh();
6228 break;
6229 case OPC_SEB:
6230 GEN_LOAD_REG_T1(rt);
6231 gen_op_seb();
6232 break;
6233 case OPC_SEH:
6234 GEN_LOAD_REG_T1(rt);
6235 gen_op_seh();
6236 break;
6237 default: /* Invalid */
6238 MIPS_INVAL("bshfl");
6239 generate_exception(ctx, EXCP_RI);
6240 break;
6242 GEN_STORE_T0_REG(rd);
6243 break;
6244 case OPC_RDHWR:
6245 check_insn(env, ctx, ISA_MIPS32R2);
6246 switch (rd) {
6247 case 0:
6248 save_cpu_state(ctx, 1);
6249 gen_op_rdhwr_cpunum();
6250 break;
6251 case 1:
6252 save_cpu_state(ctx, 1);
6253 gen_op_rdhwr_synci_step();
6254 break;
6255 case 2:
6256 save_cpu_state(ctx, 1);
6257 gen_op_rdhwr_cc();
6258 break;
6259 case 3:
6260 save_cpu_state(ctx, 1);
6261 gen_op_rdhwr_ccres();
6262 break;
6263 case 29:
6264 #if defined (CONFIG_USER_ONLY)
6265 gen_op_tls_value();
6266 break;
6267 #endif
6268 default: /* Invalid */
6269 MIPS_INVAL("rdhwr");
6270 generate_exception(ctx, EXCP_RI);
6271 break;
6273 GEN_STORE_T0_REG(rt);
6274 break;
6275 case OPC_FORK:
6276 check_insn(env, ctx, ASE_MT);
6277 GEN_LOAD_REG_T0(rt);
6278 GEN_LOAD_REG_T1(rs);
6279 gen_op_fork();
6280 break;
6281 case OPC_YIELD:
6282 check_insn(env, ctx, ASE_MT);
6283 GEN_LOAD_REG_T0(rs);
6284 gen_op_yield();
6285 GEN_STORE_T0_REG(rd);
6286 break;
6287 #if defined(TARGET_MIPS64)
6288 case OPC_DEXTM ... OPC_DEXT:
6289 case OPC_DINSM ... OPC_DINS:
6290 check_insn(env, ctx, ISA_MIPS64R2);
6291 check_mips_64(ctx);
6292 gen_bitops(ctx, op1, rt, rs, sa, rd);
6293 break;
6294 case OPC_DBSHFL:
6295 check_insn(env, ctx, ISA_MIPS64R2);
6296 check_mips_64(ctx);
6297 op2 = MASK_DBSHFL(ctx->opcode);
6298 switch (op2) {
6299 case OPC_DSBH:
6300 GEN_LOAD_REG_T1(rt);
6301 gen_op_dsbh();
6302 break;
6303 case OPC_DSHD:
6304 GEN_LOAD_REG_T1(rt);
6305 gen_op_dshd();
6306 break;
6307 default: /* Invalid */
6308 MIPS_INVAL("dbshfl");
6309 generate_exception(ctx, EXCP_RI);
6310 break;
6312 GEN_STORE_T0_REG(rd);
6313 break;
6314 #endif
6315 default: /* Invalid */
6316 MIPS_INVAL("special3");
6317 generate_exception(ctx, EXCP_RI);
6318 break;
6320 break;
6321 case OPC_REGIMM:
6322 op1 = MASK_REGIMM(ctx->opcode);
6323 switch (op1) {
6324 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
6325 case OPC_BLTZAL ... OPC_BGEZALL:
6326 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
6327 return;
6328 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
6329 case OPC_TNEI:
6330 gen_trap(ctx, op1, rs, -1, imm);
6331 break;
6332 case OPC_SYNCI:
6333 check_insn(env, ctx, ISA_MIPS32R2);
6334 /* Treat as NOP. */
6335 break;
6336 default: /* Invalid */
6337 MIPS_INVAL("regimm");
6338 generate_exception(ctx, EXCP_RI);
6339 break;
6341 break;
6342 case OPC_CP0:
6343 check_cp0_enabled(ctx);
6344 op1 = MASK_CP0(ctx->opcode);
6345 switch (op1) {
6346 case OPC_MFC0:
6347 case OPC_MTC0:
6348 case OPC_MFTR:
6349 case OPC_MTTR:
6350 #if defined(TARGET_MIPS64)
6351 case OPC_DMFC0:
6352 case OPC_DMTC0:
6353 #endif
6354 gen_cp0(env, ctx, op1, rt, rd);
6355 break;
6356 case OPC_C0_FIRST ... OPC_C0_LAST:
6357 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
6358 break;
6359 case OPC_MFMC0:
6360 op2 = MASK_MFMC0(ctx->opcode);
6361 switch (op2) {
6362 case OPC_DMT:
6363 check_insn(env, ctx, ASE_MT);
6364 gen_op_dmt();
6365 break;
6366 case OPC_EMT:
6367 check_insn(env, ctx, ASE_MT);
6368 gen_op_emt();
6369 break;
6370 case OPC_DVPE:
6371 check_insn(env, ctx, ASE_MT);
6372 gen_op_dvpe();
6373 break;
6374 case OPC_EVPE:
6375 check_insn(env, ctx, ASE_MT);
6376 gen_op_evpe();
6377 break;
6378 case OPC_DI:
6379 check_insn(env, ctx, ISA_MIPS32R2);
6380 save_cpu_state(ctx, 1);
6381 gen_op_di();
6382 /* Stop translation as we may have switched the execution mode */
6383 ctx->bstate = BS_STOP;
6384 break;
6385 case OPC_EI:
6386 check_insn(env, ctx, ISA_MIPS32R2);
6387 save_cpu_state(ctx, 1);
6388 gen_op_ei();
6389 /* Stop translation as we may have switched the execution mode */
6390 ctx->bstate = BS_STOP;
6391 break;
6392 default: /* Invalid */
6393 MIPS_INVAL("mfmc0");
6394 generate_exception(ctx, EXCP_RI);
6395 break;
6397 GEN_STORE_T0_REG(rt);
6398 break;
6399 case OPC_RDPGPR:
6400 check_insn(env, ctx, ISA_MIPS32R2);
6401 GEN_LOAD_SRSREG_TN(T0, rt);
6402 GEN_STORE_T0_REG(rd);
6403 break;
6404 case OPC_WRPGPR:
6405 check_insn(env, ctx, ISA_MIPS32R2);
6406 GEN_LOAD_REG_T0(rt);
6407 GEN_STORE_TN_SRSREG(rd, T0);
6408 break;
6409 default:
6410 MIPS_INVAL("cp0");
6411 generate_exception(ctx, EXCP_RI);
6412 break;
6414 break;
6415 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
6416 gen_arith_imm(env, ctx, op, rt, rs, imm);
6417 break;
6418 case OPC_J ... OPC_JAL: /* Jump */
6419 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
6420 gen_compute_branch(ctx, op, rs, rt, offset);
6421 return;
6422 case OPC_BEQ ... OPC_BGTZ: /* Branch */
6423 case OPC_BEQL ... OPC_BGTZL:
6424 gen_compute_branch(ctx, op, rs, rt, imm << 2);
6425 return;
6426 case OPC_LB ... OPC_LWR: /* Load and stores */
6427 case OPC_SB ... OPC_SW:
6428 case OPC_SWR:
6429 case OPC_LL:
6430 case OPC_SC:
6431 gen_ldst(ctx, op, rt, rs, imm);
6432 break;
6433 case OPC_CACHE:
6434 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
6435 /* Treat as NOP. */
6436 break;
6437 case OPC_PREF:
6438 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6439 /* Treat as NOP. */
6440 break;
6442 /* Floating point (COP1). */
6443 case OPC_LWC1:
6444 case OPC_LDC1:
6445 case OPC_SWC1:
6446 case OPC_SDC1:
6447 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
6448 save_cpu_state(ctx, 1);
6449 check_cp1_enabled(ctx);
6450 gen_flt_ldst(ctx, op, rt, rs, imm);
6451 } else {
6452 generate_exception_err(ctx, EXCP_CpU, 1);
6454 break;
6456 case OPC_CP1:
6457 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
6458 save_cpu_state(ctx, 1);
6459 check_cp1_enabled(ctx);
6460 op1 = MASK_CP1(ctx->opcode);
6461 switch (op1) {
6462 case OPC_MFHC1:
6463 case OPC_MTHC1:
6464 check_insn(env, ctx, ISA_MIPS32R2);
6465 case OPC_MFC1:
6466 case OPC_CFC1:
6467 case OPC_MTC1:
6468 case OPC_CTC1:
6469 gen_cp1(ctx, op1, rt, rd);
6470 break;
6471 #if defined(TARGET_MIPS64)
6472 case OPC_DMFC1:
6473 case OPC_DMTC1:
6474 check_insn(env, ctx, ISA_MIPS3);
6475 gen_cp1(ctx, op1, rt, rd);
6476 break;
6477 #endif
6478 case OPC_BC1ANY2:
6479 case OPC_BC1ANY4:
6480 check_cop1x(ctx);
6481 check_insn(env, ctx, ASE_MIPS3D);
6482 /* fall through */
6483 case OPC_BC1:
6484 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
6485 (rt >> 2) & 0x7, imm << 2);
6486 return;
6487 case OPC_S_FMT:
6488 case OPC_D_FMT:
6489 case OPC_W_FMT:
6490 case OPC_L_FMT:
6491 case OPC_PS_FMT:
6492 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
6493 (imm >> 8) & 0x7);
6494 break;
6495 default:
6496 MIPS_INVAL("cp1");
6497 generate_exception (ctx, EXCP_RI);
6498 break;
6500 } else {
6501 generate_exception_err(ctx, EXCP_CpU, 1);
6503 break;
6505 /* COP2. */
6506 case OPC_LWC2:
6507 case OPC_LDC2:
6508 case OPC_SWC2:
6509 case OPC_SDC2:
6510 case OPC_CP2:
6511 /* COP2: Not implemented. */
6512 generate_exception_err(ctx, EXCP_CpU, 2);
6513 break;
6515 case OPC_CP3:
6516 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
6517 save_cpu_state(ctx, 1);
6518 check_cp1_enabled(ctx);
6519 op1 = MASK_CP3(ctx->opcode);
6520 switch (op1) {
6521 case OPC_LWXC1:
6522 case OPC_LDXC1:
6523 case OPC_LUXC1:
6524 case OPC_SWXC1:
6525 case OPC_SDXC1:
6526 case OPC_SUXC1:
6527 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
6528 break;
6529 case OPC_PREFX:
6530 /* Treat as NOP. */
6531 break;
6532 case OPC_ALNV_PS:
6533 case OPC_MADD_S:
6534 case OPC_MADD_D:
6535 case OPC_MADD_PS:
6536 case OPC_MSUB_S:
6537 case OPC_MSUB_D:
6538 case OPC_MSUB_PS:
6539 case OPC_NMADD_S:
6540 case OPC_NMADD_D:
6541 case OPC_NMADD_PS:
6542 case OPC_NMSUB_S:
6543 case OPC_NMSUB_D:
6544 case OPC_NMSUB_PS:
6545 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
6546 break;
6547 default:
6548 MIPS_INVAL("cp3");
6549 generate_exception (ctx, EXCP_RI);
6550 break;
6552 } else {
6553 generate_exception_err(ctx, EXCP_CpU, 1);
6555 break;
6557 #if defined(TARGET_MIPS64)
6558 /* MIPS64 opcodes */
6559 case OPC_LWU:
6560 case OPC_LDL ... OPC_LDR:
6561 case OPC_SDL ... OPC_SDR:
6562 case OPC_LLD:
6563 case OPC_LD:
6564 case OPC_SCD:
6565 case OPC_SD:
6566 check_insn(env, ctx, ISA_MIPS3);
6567 check_mips_64(ctx);
6568 gen_ldst(ctx, op, rt, rs, imm);
6569 break;
6570 case OPC_DADDI ... OPC_DADDIU:
6571 check_insn(env, ctx, ISA_MIPS3);
6572 check_mips_64(ctx);
6573 gen_arith_imm(env, ctx, op, rt, rs, imm);
6574 break;
6575 #endif
6576 case OPC_JALX:
6577 check_insn(env, ctx, ASE_MIPS16);
6578 /* MIPS16: Not implemented. */
6579 case OPC_MDMX:
6580 check_insn(env, ctx, ASE_MDMX);
6581 /* MDMX: Not implemented. */
6582 default: /* Invalid */
6583 MIPS_INVAL("major opcode");
6584 generate_exception(ctx, EXCP_RI);
6585 break;
6587 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6588 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
6589 /* Branches completion */
6590 ctx->hflags &= ~MIPS_HFLAG_BMASK;
6591 ctx->bstate = BS_BRANCH;
6592 save_cpu_state(ctx, 0);
6593 switch (hflags) {
6594 case MIPS_HFLAG_B:
6595 /* unconditional branch */
6596 MIPS_DEBUG("unconditional branch");
6597 gen_goto_tb(ctx, 0, ctx->btarget);
6598 break;
6599 case MIPS_HFLAG_BL:
6600 /* blikely taken case */
6601 MIPS_DEBUG("blikely branch taken");
6602 gen_goto_tb(ctx, 0, ctx->btarget);
6603 break;
6604 case MIPS_HFLAG_BC:
6605 /* Conditional branch */
6606 MIPS_DEBUG("conditional branch");
6608 int l1;
6609 l1 = gen_new_label();
6610 tcg_gen_jnz_bcond(l1);
6611 gen_goto_tb(ctx, 1, ctx->pc + 4);
6612 gen_set_label(l1);
6613 gen_goto_tb(ctx, 0, ctx->btarget);
6615 break;
6616 case MIPS_HFLAG_BR:
6617 /* unconditional branch to register */
6618 MIPS_DEBUG("branch to register");
6619 gen_op_breg();
6620 tcg_gen_exit_tb(0);
6621 break;
6622 default:
6623 MIPS_DEBUG("unknown branch");
6624 break;
6629 static always_inline int
6630 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
6631 int search_pc)
6633 DisasContext ctx;
6634 target_ulong pc_start;
6635 uint16_t *gen_opc_end;
6636 int j, lj = -1;
6638 if (search_pc && loglevel)
6639 fprintf (logfile, "search pc %d\n", search_pc);
6641 pc_start = tb->pc;
6642 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6643 ctx.pc = pc_start;
6644 ctx.saved_pc = -1;
6645 ctx.tb = tb;
6646 ctx.bstate = BS_NONE;
6647 /* Restore delay slot state from the tb context. */
6648 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
6649 restore_cpu_state(env, &ctx);
6650 #if defined(CONFIG_USER_ONLY)
6651 ctx.mem_idx = MIPS_HFLAG_UM;
6652 #else
6653 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
6654 #endif
6655 #ifdef DEBUG_DISAS
6656 if (loglevel & CPU_LOG_TB_CPU) {
6657 fprintf(logfile, "------------------------------------------------\n");
6658 /* FIXME: This may print out stale hflags from env... */
6659 cpu_dump_state(env, logfile, fprintf, 0);
6661 #endif
6662 #ifdef MIPS_DEBUG_DISAS
6663 if (loglevel & CPU_LOG_TB_IN_ASM)
6664 fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
6665 tb, ctx.mem_idx, ctx.hflags);
6666 #endif
6667 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
6668 if (env->nb_breakpoints > 0) {
6669 for(j = 0; j < env->nb_breakpoints; j++) {
6670 if (env->breakpoints[j] == ctx.pc) {
6671 save_cpu_state(&ctx, 1);
6672 ctx.bstate = BS_BRANCH;
6673 gen_op_debug();
6674 /* Include the breakpoint location or the tb won't
6675 * be flushed when it must be. */
6676 ctx.pc += 4;
6677 goto done_generating;
6682 if (search_pc) {
6683 j = gen_opc_ptr - gen_opc_buf;
6684 if (lj < j) {
6685 lj++;
6686 while (lj < j)
6687 gen_opc_instr_start[lj++] = 0;
6689 gen_opc_pc[lj] = ctx.pc;
6690 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
6691 gen_opc_instr_start[lj] = 1;
6693 ctx.opcode = ldl_code(ctx.pc);
6694 decode_opc(env, &ctx);
6695 ctx.pc += 4;
6697 if (env->singlestep_enabled)
6698 break;
6700 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
6701 break;
6703 #if defined (MIPS_SINGLE_STEP)
6704 break;
6705 #endif
6707 if (env->singlestep_enabled) {
6708 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
6709 gen_op_debug();
6710 } else {
6711 switch (ctx.bstate) {
6712 case BS_STOP:
6713 gen_op_interrupt_restart();
6714 gen_goto_tb(&ctx, 0, ctx.pc);
6715 break;
6716 case BS_NONE:
6717 save_cpu_state(&ctx, 0);
6718 gen_goto_tb(&ctx, 0, ctx.pc);
6719 break;
6720 case BS_EXCP:
6721 gen_op_interrupt_restart();
6722 tcg_gen_exit_tb(0);
6723 break;
6724 case BS_BRANCH:
6725 default:
6726 break;
6729 done_generating:
6730 ctx.last_T0_store = NULL;
6731 *gen_opc_ptr = INDEX_op_end;
6732 if (search_pc) {
6733 j = gen_opc_ptr - gen_opc_buf;
6734 lj++;
6735 while (lj <= j)
6736 gen_opc_instr_start[lj++] = 0;
6737 } else {
6738 tb->size = ctx.pc - pc_start;
6740 #ifdef DEBUG_DISAS
6741 #if defined MIPS_DEBUG_DISAS
6742 if (loglevel & CPU_LOG_TB_IN_ASM)
6743 fprintf(logfile, "\n");
6744 #endif
6745 if (loglevel & CPU_LOG_TB_IN_ASM) {
6746 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6747 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
6748 fprintf(logfile, "\n");
6750 if (loglevel & CPU_LOG_TB_CPU) {
6751 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
6753 #endif
6755 return 0;
6758 int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6760 return gen_intermediate_code_internal(env, tb, 0);
6763 int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6765 return gen_intermediate_code_internal(env, tb, 1);
6768 void fpu_dump_state(CPUState *env, FILE *f,
6769 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
6770 int flags)
6772 int i;
6773 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
6775 #define printfpr(fp) \
6776 do { \
6777 if (is_fpu64) \
6778 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
6779 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
6780 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
6781 else { \
6782 fpr_t tmp; \
6783 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
6784 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
6785 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
6786 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
6787 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
6789 } while(0)
6792 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
6793 env->fpu->fcr0, env->fpu->fcr31, is_fpu64, env->fpu->fp_status,
6794 get_float_exception_flags(&env->fpu->fp_status));
6795 fpu_fprintf(f, "FT0: "); printfpr(&env->fpu->ft0);
6796 fpu_fprintf(f, "FT1: "); printfpr(&env->fpu->ft1);
6797 fpu_fprintf(f, "FT2: "); printfpr(&env->fpu->ft2);
6798 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
6799 fpu_fprintf(f, "%3s: ", fregnames[i]);
6800 printfpr(&env->fpu->fpr[i]);
6803 #undef printfpr
6806 void dump_fpu (CPUState *env)
6808 if (loglevel) {
6809 fprintf(logfile, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
6810 env->PC[env->current_tc], env->HI[env->current_tc][0], env->LO[env->current_tc][0], env->hflags, env->btarget, env->bcond);
6811 fpu_dump_state(env, logfile, fprintf, 0);
6815 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
6816 /* Debug help: The architecture requires 32bit code to maintain proper
6817 sign-extened values on 64bit machines. */
6819 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
6821 void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
6822 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6823 int flags)
6825 int i;
6827 if (!SIGN_EXT_P(env->PC[env->current_tc]))
6828 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC[env->current_tc]);
6829 if (!SIGN_EXT_P(env->HI[env->current_tc][0]))
6830 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI[env->current_tc][0]);
6831 if (!SIGN_EXT_P(env->LO[env->current_tc][0]))
6832 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO[env->current_tc][0]);
6833 if (!SIGN_EXT_P(env->btarget))
6834 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
6836 for (i = 0; i < 32; i++) {
6837 if (!SIGN_EXT_P(env->gpr[env->current_tc][i]))
6838 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[env->current_tc][i]);
6841 if (!SIGN_EXT_P(env->CP0_EPC))
6842 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
6843 if (!SIGN_EXT_P(env->CP0_LLAddr))
6844 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
6846 #endif
6848 void cpu_dump_state (CPUState *env, FILE *f,
6849 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6850 int flags)
6852 int i;
6854 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",
6855 env->PC[env->current_tc], env->HI[env->current_tc], env->LO[env->current_tc], env->hflags, env->btarget, env->bcond);
6856 for (i = 0; i < 32; i++) {
6857 if ((i & 3) == 0)
6858 cpu_fprintf(f, "GPR%02d:", i);
6859 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[env->current_tc][i]);
6860 if ((i & 3) == 3)
6861 cpu_fprintf(f, "\n");
6864 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
6865 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
6866 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
6867 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
6868 if (env->hflags & MIPS_HFLAG_FPU)
6869 fpu_dump_state(env, f, cpu_fprintf, flags);
6870 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
6871 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
6872 #endif
6875 static void mips_tcg_init(void)
6877 static int inited;
6879 /* Initialize various static tables. */
6880 if (inited)
6881 return;
6883 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
6884 current_tc_regs = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG1, "current_tc_regs");
6885 #if TARGET_LONG_BITS > HOST_LONG_BITS
6886 cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL,
6887 TCG_AREG0, offsetof(CPUState, t0), "T0");
6888 cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
6889 TCG_AREG0, offsetof(CPUState, t1), "T1");
6890 #else
6891 cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T0");
6892 cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "T1");
6893 #endif
6895 inited = 1;
6898 #include "translate_init.c"
6900 CPUMIPSState *cpu_mips_init (const char *cpu_model)
6902 CPUMIPSState *env;
6903 const mips_def_t *def;
6905 def = cpu_mips_find_by_name(cpu_model);
6906 if (!def)
6907 return NULL;
6908 env = qemu_mallocz(sizeof(CPUMIPSState));
6909 if (!env)
6910 return NULL;
6911 env->cpu_model = def;
6913 cpu_exec_init(env);
6914 env->cpu_model_str = cpu_model;
6915 mips_tcg_init();
6916 cpu_reset(env);
6917 return env;
6920 void cpu_reset (CPUMIPSState *env)
6922 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
6924 tlb_flush(env, 1);
6926 /* Minimal init */
6927 #if !defined(CONFIG_USER_ONLY)
6928 if (env->hflags & MIPS_HFLAG_BMASK) {
6929 /* If the exception was raised from a delay slot,
6930 * come back to the jump. */
6931 env->CP0_ErrorEPC = env->PC[env->current_tc] - 4;
6932 } else {
6933 env->CP0_ErrorEPC = env->PC[env->current_tc];
6935 env->PC[env->current_tc] = (int32_t)0xBFC00000;
6936 env->CP0_Wired = 0;
6937 /* SMP not implemented */
6938 env->CP0_EBase = 0x80000000;
6939 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
6940 /* vectored interrupts not implemented, timer on int 7,
6941 no performance counters. */
6942 env->CP0_IntCtl = 0xe0000000;
6944 int i;
6946 for (i = 0; i < 7; i++) {
6947 env->CP0_WatchLo[i] = 0;
6948 env->CP0_WatchHi[i] = 0x80000000;
6950 env->CP0_WatchLo[7] = 0;
6951 env->CP0_WatchHi[7] = 0;
6953 /* Count register increments in debug mode, EJTAG version 1 */
6954 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
6955 #endif
6956 env->exception_index = EXCP_NONE;
6957 #if defined(CONFIG_USER_ONLY)
6958 env->hflags = MIPS_HFLAG_UM;
6959 env->user_mode_only = 1;
6960 #else
6961 env->hflags = MIPS_HFLAG_CP0;
6962 #endif
6963 cpu_mips_register(env, env->cpu_model);
6966 void gen_pc_load(CPUState *env, TranslationBlock *tb,
6967 unsigned long searched_pc, int pc_pos, void *puc)
6969 env->PC[env->current_tc] = gen_opc_pc[pc_pos];
6970 env->hflags &= ~MIPS_HFLAG_BMASK;
6971 env->hflags |= gen_opc_hflags[pc_pos];