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