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