Disable 64-bit instructions on 32-bit CPU, by Aurelien Jarno.
[qemu/dscho.git] / target-mips / translate.c
blob07dca145954e47f01a9f08b468cd2165d7f97099
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
3 *
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,
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 /* REGIMM (rt field) opcodes */
218 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
220 enum {
221 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
222 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
223 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
224 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
225 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
226 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
227 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
228 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
229 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
230 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
231 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
232 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
233 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
234 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
235 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
238 /* Special2 opcodes */
239 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
241 enum {
242 /* Multiply & xxx operations */
243 OPC_MADD = 0x00 | OPC_SPECIAL2,
244 OPC_MADDU = 0x01 | OPC_SPECIAL2,
245 OPC_MUL = 0x02 | OPC_SPECIAL2,
246 OPC_MSUB = 0x04 | OPC_SPECIAL2,
247 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
248 /* Misc */
249 OPC_CLZ = 0x20 | OPC_SPECIAL2,
250 OPC_CLO = 0x21 | OPC_SPECIAL2,
251 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
252 OPC_DCLO = 0x25 | OPC_SPECIAL2,
253 /* Special */
254 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
257 /* Special3 opcodes */
258 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
260 enum {
261 OPC_EXT = 0x00 | OPC_SPECIAL3,
262 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
263 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
264 OPC_DEXT = 0x03 | OPC_SPECIAL3,
265 OPC_INS = 0x04 | OPC_SPECIAL3,
266 OPC_DINSM = 0x05 | OPC_SPECIAL3,
267 OPC_DINSU = 0x06 | OPC_SPECIAL3,
268 OPC_DINS = 0x07 | OPC_SPECIAL3,
269 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
270 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
271 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
274 /* BSHFL opcodes */
275 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
277 enum {
278 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
279 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
280 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
283 /* DBSHFL opcodes */
284 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
286 enum {
287 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
288 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
291 /* Coprocessor 0 (rs field) */
292 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
294 enum {
295 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
296 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
297 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
298 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
299 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
300 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
301 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
302 OPC_C0 = (0x10 << 21) | OPC_CP0,
303 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
304 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
307 /* MFMC0 opcodes */
308 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
310 enum {
311 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
312 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
315 /* Coprocessor 0 (with rs == C0) */
316 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
318 enum {
319 OPC_TLBR = 0x01 | OPC_C0,
320 OPC_TLBWI = 0x02 | OPC_C0,
321 OPC_TLBWR = 0x06 | OPC_C0,
322 OPC_TLBP = 0x08 | OPC_C0,
323 OPC_RFE = 0x10 | OPC_C0,
324 OPC_ERET = 0x18 | OPC_C0,
325 OPC_DERET = 0x1F | OPC_C0,
326 OPC_WAIT = 0x20 | OPC_C0,
329 /* Coprocessor 1 (rs field) */
330 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
332 enum {
333 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
334 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
335 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
336 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
337 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
338 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
339 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
340 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
341 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
342 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
343 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
344 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
345 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
346 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
347 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
348 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
349 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
350 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
353 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
354 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
356 enum {
357 OPC_BC1F = (0x00 << 16) | OPC_BC1,
358 OPC_BC1T = (0x01 << 16) | OPC_BC1,
359 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
360 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
363 enum {
364 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
365 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
368 enum {
369 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
370 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
373 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
375 enum {
376 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
377 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
378 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
379 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
380 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
381 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
382 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
383 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
384 OPC_BC2 = (0x08 << 21) | OPC_CP2,
387 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
389 enum {
390 OPC_LWXC1 = 0x00 | OPC_CP3,
391 OPC_LDXC1 = 0x01 | OPC_CP3,
392 OPC_LUXC1 = 0x05 | OPC_CP3,
393 OPC_SWXC1 = 0x08 | OPC_CP3,
394 OPC_SDXC1 = 0x09 | OPC_CP3,
395 OPC_SUXC1 = 0x0D | OPC_CP3,
396 OPC_PREFX = 0x0F | OPC_CP3,
397 OPC_ALNV_PS = 0x1E | OPC_CP3,
398 OPC_MADD_S = 0x20 | OPC_CP3,
399 OPC_MADD_D = 0x21 | OPC_CP3,
400 OPC_MADD_PS = 0x26 | OPC_CP3,
401 OPC_MSUB_S = 0x28 | OPC_CP3,
402 OPC_MSUB_D = 0x29 | OPC_CP3,
403 OPC_MSUB_PS = 0x2E | OPC_CP3,
404 OPC_NMADD_S = 0x30 | OPC_CP3,
405 OPC_NMADD_D = 0x31 | OPC_CP3,
406 OPC_NMADD_PS= 0x36 | OPC_CP3,
407 OPC_NMSUB_S = 0x38 | OPC_CP3,
408 OPC_NMSUB_D = 0x39 | OPC_CP3,
409 OPC_NMSUB_PS= 0x3E | OPC_CP3,
413 const unsigned char *regnames[] =
414 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
415 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
416 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
417 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
419 /* Warning: no function for r0 register (hard wired to zero) */
420 #define GEN32(func, NAME) \
421 static GenOpFunc *NAME ## _table [32] = { \
422 NULL, NAME ## 1, NAME ## 2, NAME ## 3, \
423 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
424 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
425 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
426 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
427 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
428 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
429 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
430 }; \
431 static inline void func(int n) \
433 NAME ## _table[n](); \
436 /* General purpose registers moves */
437 GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
438 GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
439 GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
441 GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
442 GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
444 static const char *fregnames[] =
445 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
446 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
447 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
448 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
450 #define FGEN32(func, NAME) \
451 static GenOpFunc *NAME ## _table [32] = { \
452 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
453 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
454 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
455 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
456 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
457 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
458 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
459 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
460 }; \
461 static inline void func(int n) \
463 NAME ## _table[n](); \
466 FGEN32(gen_op_load_fpr_WT0, gen_op_load_fpr_WT0_fpr);
467 FGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
469 FGEN32(gen_op_load_fpr_WT1, gen_op_load_fpr_WT1_fpr);
470 FGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
472 FGEN32(gen_op_load_fpr_WT2, gen_op_load_fpr_WT2_fpr);
473 FGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
475 FGEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fpr);
476 FGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
478 FGEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fpr);
479 FGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
481 FGEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fpr);
482 FGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
484 FGEN32(gen_op_load_fpr_WTH0, gen_op_load_fpr_WTH0_fpr);
485 FGEN32(gen_op_store_fpr_WTH0, gen_op_store_fpr_WTH0_fpr);
487 FGEN32(gen_op_load_fpr_WTH1, gen_op_load_fpr_WTH1_fpr);
488 FGEN32(gen_op_store_fpr_WTH1, gen_op_store_fpr_WTH1_fpr);
490 FGEN32(gen_op_load_fpr_WTH2, gen_op_load_fpr_WTH2_fpr);
491 FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr);
493 #define FOP_CONDS(type, fmt) \
494 static GenOpFunc1 * gen_op_cmp ## type ## _ ## fmt ## _table[16] = { \
495 gen_op_cmp ## type ## _ ## fmt ## _f, \
496 gen_op_cmp ## type ## _ ## fmt ## _un, \
497 gen_op_cmp ## type ## _ ## fmt ## _eq, \
498 gen_op_cmp ## type ## _ ## fmt ## _ueq, \
499 gen_op_cmp ## type ## _ ## fmt ## _olt, \
500 gen_op_cmp ## type ## _ ## fmt ## _ult, \
501 gen_op_cmp ## type ## _ ## fmt ## _ole, \
502 gen_op_cmp ## type ## _ ## fmt ## _ule, \
503 gen_op_cmp ## type ## _ ## fmt ## _sf, \
504 gen_op_cmp ## type ## _ ## fmt ## _ngle, \
505 gen_op_cmp ## type ## _ ## fmt ## _seq, \
506 gen_op_cmp ## type ## _ ## fmt ## _ngl, \
507 gen_op_cmp ## type ## _ ## fmt ## _lt, \
508 gen_op_cmp ## type ## _ ## fmt ## _nge, \
509 gen_op_cmp ## type ## _ ## fmt ## _le, \
510 gen_op_cmp ## type ## _ ## fmt ## _ngt, \
511 }; \
512 static inline void gen_cmp ## type ## _ ## fmt(int n, long cc) \
514 gen_op_cmp ## type ## _ ## fmt ## _table[n](cc); \
517 FOP_CONDS(, d)
518 FOP_CONDS(abs, d)
519 FOP_CONDS(, s)
520 FOP_CONDS(abs, s)
521 FOP_CONDS(, ps)
522 FOP_CONDS(abs, ps)
524 typedef struct DisasContext {
525 struct TranslationBlock *tb;
526 target_ulong pc, saved_pc;
527 uint32_t opcode;
528 uint32_t fp_status;
529 /* Routine used to access memory */
530 int mem_idx;
531 uint32_t hflags, saved_hflags;
532 int bstate;
533 target_ulong btarget;
534 } DisasContext;
536 enum {
537 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
538 * exception condition
540 BS_STOP = 1, /* We want to stop translation for any reason */
541 BS_BRANCH = 2, /* We reached a branch condition */
542 BS_EXCP = 3, /* We reached an exception condition */
545 #ifdef MIPS_DEBUG_DISAS
546 #define MIPS_DEBUG(fmt, args...) \
547 do { \
548 if (loglevel & CPU_LOG_TB_IN_ASM) { \
549 fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n", \
550 ctx->pc, ctx->opcode , ##args); \
552 } while (0)
553 #else
554 #define MIPS_DEBUG(fmt, args...) do { } while(0)
555 #endif
557 #define MIPS_INVAL(op) \
558 do { \
559 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
560 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
561 } while (0)
563 #define GEN_LOAD_REG_TN(Tn, Rn) \
564 do { \
565 if (Rn == 0) { \
566 glue(gen_op_reset_, Tn)(); \
567 } else { \
568 glue(gen_op_load_gpr_, Tn)(Rn); \
570 } while (0)
572 #ifdef TARGET_MIPS64
573 #define GEN_LOAD_IMM_TN(Tn, Imm) \
574 do { \
575 if (Imm == 0) { \
576 glue(gen_op_reset_, Tn)(); \
577 } else if ((int32_t)Imm == Imm) { \
578 glue(gen_op_set_, Tn)(Imm); \
579 } else { \
580 glue(gen_op_set64_, Tn)(((uint64_t)Imm) >> 32, (uint32_t)Imm); \
582 } while (0)
583 #else
584 #define GEN_LOAD_IMM_TN(Tn, Imm) \
585 do { \
586 if (Imm == 0) { \
587 glue(gen_op_reset_, Tn)(); \
588 } else { \
589 glue(gen_op_set_, Tn)(Imm); \
591 } while (0)
592 #endif
594 #define GEN_STORE_TN_REG(Rn, Tn) \
595 do { \
596 if (Rn != 0) { \
597 glue(glue(gen_op_store_, Tn),_gpr)(Rn); \
599 } while (0)
601 #define GEN_LOAD_FREG_FTN(FTn, Fn) \
602 do { \
603 glue(gen_op_load_fpr_, FTn)(Fn); \
604 } while (0)
606 #define GEN_STORE_FTN_FREG(Fn, FTn) \
607 do { \
608 glue(gen_op_store_fpr_, FTn)(Fn); \
609 } while (0)
611 static inline void gen_save_pc(target_ulong pc)
613 #ifdef TARGET_MIPS64
614 if (pc == (int32_t)pc) {
615 gen_op_save_pc(pc);
616 } else {
617 gen_op_save_pc64(pc >> 32, (uint32_t)pc);
619 #else
620 gen_op_save_pc(pc);
621 #endif
624 static inline void gen_save_btarget(target_ulong btarget)
626 #ifdef TARGET_MIPS64
627 if (btarget == (int32_t)btarget) {
628 gen_op_save_btarget(btarget);
629 } else {
630 gen_op_save_btarget64(btarget >> 32, (uint32_t)btarget);
632 #else
633 gen_op_save_btarget(btarget);
634 #endif
637 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
639 #if defined MIPS_DEBUG_DISAS
640 if (loglevel & CPU_LOG_TB_IN_ASM) {
641 fprintf(logfile, "hflags %08x saved %08x\n",
642 ctx->hflags, ctx->saved_hflags);
644 #endif
645 if (do_save_pc && ctx->pc != ctx->saved_pc) {
646 gen_save_pc(ctx->pc);
647 ctx->saved_pc = ctx->pc;
649 if (ctx->hflags != ctx->saved_hflags) {
650 gen_op_save_state(ctx->hflags);
651 ctx->saved_hflags = ctx->hflags;
652 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
653 case MIPS_HFLAG_BR:
654 gen_op_save_breg_target();
655 break;
656 case MIPS_HFLAG_BC:
657 gen_op_save_bcond();
658 /* fall through */
659 case MIPS_HFLAG_BL:
660 /* bcond was already saved by the BL insn */
661 /* fall through */
662 case MIPS_HFLAG_B:
663 gen_save_btarget(ctx->btarget);
664 break;
669 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
671 ctx->saved_hflags = ctx->hflags;
672 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
673 case MIPS_HFLAG_BR:
674 gen_op_restore_breg_target();
675 break;
676 case MIPS_HFLAG_B:
677 ctx->btarget = env->btarget;
678 break;
679 case MIPS_HFLAG_BC:
680 case MIPS_HFLAG_BL:
681 ctx->btarget = env->btarget;
682 gen_op_restore_bcond();
683 break;
687 static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
689 #if defined MIPS_DEBUG_DISAS
690 if (loglevel & CPU_LOG_TB_IN_ASM)
691 fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
692 #endif
693 save_cpu_state(ctx, 1);
694 if (err == 0)
695 gen_op_raise_exception(excp);
696 else
697 gen_op_raise_exception_err(excp, err);
698 ctx->bstate = BS_EXCP;
701 static inline void generate_exception (DisasContext *ctx, int excp)
703 generate_exception_err (ctx, excp, 0);
706 static inline void check_cp1_enabled(DisasContext *ctx)
708 if (!(ctx->hflags & MIPS_HFLAG_FPU))
709 generate_exception_err(ctx, EXCP_CpU, 1);
712 static inline void check_cp1_64bitmode(DisasContext *ctx)
714 if (!(ctx->hflags & MIPS_HFLAG_F64))
715 generate_exception(ctx, EXCP_RI);
719 * Verify if floating point register is valid; an operation is not defined
720 * if bit 0 of any register specification is set and the FR bit in the
721 * Status register equals zero, since the register numbers specify an
722 * even-odd pair of adjacent coprocessor general registers. When the FR bit
723 * in the Status register equals one, both even and odd register numbers
724 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
726 * Multiple 64 bit wide registers can be checked by calling
727 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
729 void check_cp1_registers(DisasContext *ctx, int regs)
731 if (!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))
732 generate_exception(ctx, EXCP_RI);
735 /* This code generates a "reserved instruction" exception if the
736 CPU is not a MIPS R2 (or higher) CPU. */
737 static inline void check_mips_r2(CPUState *env, DisasContext *ctx)
739 if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) < (1 << CP0C0_AR))
740 generate_exception(ctx, EXCP_RI);
743 #if defined(CONFIG_USER_ONLY)
744 #define op_ldst(name) gen_op_##name##_raw()
745 #define OP_LD_TABLE(width)
746 #define OP_ST_TABLE(width)
747 #else
748 #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
749 #define OP_LD_TABLE(width) \
750 static GenOpFunc *gen_op_l##width[] = { \
751 &gen_op_l##width##_user, \
752 &gen_op_l##width##_kernel, \
754 #define OP_ST_TABLE(width) \
755 static GenOpFunc *gen_op_s##width[] = { \
756 &gen_op_s##width##_user, \
757 &gen_op_s##width##_kernel, \
759 #endif
761 #ifdef TARGET_MIPS64
762 OP_LD_TABLE(d);
763 OP_LD_TABLE(dl);
764 OP_LD_TABLE(dr);
765 OP_ST_TABLE(d);
766 OP_ST_TABLE(dl);
767 OP_ST_TABLE(dr);
768 OP_LD_TABLE(ld);
769 OP_ST_TABLE(cd);
770 OP_LD_TABLE(wu);
771 #endif
772 OP_LD_TABLE(w);
773 OP_LD_TABLE(wl);
774 OP_LD_TABLE(wr);
775 OP_ST_TABLE(w);
776 OP_ST_TABLE(wl);
777 OP_ST_TABLE(wr);
778 OP_LD_TABLE(h);
779 OP_LD_TABLE(hu);
780 OP_ST_TABLE(h);
781 OP_LD_TABLE(b);
782 OP_LD_TABLE(bu);
783 OP_ST_TABLE(b);
784 OP_LD_TABLE(l);
785 OP_ST_TABLE(c);
786 OP_LD_TABLE(wc1);
787 OP_ST_TABLE(wc1);
788 OP_LD_TABLE(dc1);
789 OP_ST_TABLE(dc1);
790 OP_LD_TABLE(uxc1);
791 OP_ST_TABLE(uxc1);
793 /* Load and store */
794 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
795 int base, int16_t offset)
797 const char *opn = "ldst";
799 if (base == 0) {
800 GEN_LOAD_IMM_TN(T0, offset);
801 } else if (offset == 0) {
802 gen_op_load_gpr_T0(base);
803 } else {
804 gen_op_load_gpr_T0(base);
805 gen_op_set_T1(offset);
806 gen_op_addr_add();
808 /* Don't do NOP if destination is zero: we must perform the actual
809 * memory access
811 switch (opc) {
812 #ifdef TARGET_MIPS64
813 case OPC_LWU:
814 op_ldst(lwu);
815 GEN_STORE_TN_REG(rt, T0);
816 opn = "lwu";
817 break;
818 case OPC_LD:
819 op_ldst(ld);
820 GEN_STORE_TN_REG(rt, T0);
821 opn = "ld";
822 break;
823 case OPC_LLD:
824 op_ldst(lld);
825 GEN_STORE_TN_REG(rt, T0);
826 opn = "lld";
827 break;
828 case OPC_SD:
829 GEN_LOAD_REG_TN(T1, rt);
830 op_ldst(sd);
831 opn = "sd";
832 break;
833 case OPC_SCD:
834 save_cpu_state(ctx, 1);
835 GEN_LOAD_REG_TN(T1, rt);
836 op_ldst(scd);
837 GEN_STORE_TN_REG(rt, T0);
838 opn = "scd";
839 break;
840 case OPC_LDL:
841 GEN_LOAD_REG_TN(T1, rt);
842 op_ldst(ldl);
843 GEN_STORE_TN_REG(rt, T0);
844 opn = "ldl";
845 break;
846 case OPC_SDL:
847 GEN_LOAD_REG_TN(T1, rt);
848 op_ldst(sdl);
849 opn = "sdl";
850 break;
851 case OPC_LDR:
852 GEN_LOAD_REG_TN(T1, rt);
853 op_ldst(ldr);
854 GEN_STORE_TN_REG(rt, T0);
855 opn = "ldr";
856 break;
857 case OPC_SDR:
858 GEN_LOAD_REG_TN(T1, rt);
859 op_ldst(sdr);
860 opn = "sdr";
861 break;
862 #endif
863 case OPC_LW:
864 op_ldst(lw);
865 GEN_STORE_TN_REG(rt, T0);
866 opn = "lw";
867 break;
868 case OPC_SW:
869 GEN_LOAD_REG_TN(T1, rt);
870 op_ldst(sw);
871 opn = "sw";
872 break;
873 case OPC_LH:
874 op_ldst(lh);
875 GEN_STORE_TN_REG(rt, T0);
876 opn = "lh";
877 break;
878 case OPC_SH:
879 GEN_LOAD_REG_TN(T1, rt);
880 op_ldst(sh);
881 opn = "sh";
882 break;
883 case OPC_LHU:
884 op_ldst(lhu);
885 GEN_STORE_TN_REG(rt, T0);
886 opn = "lhu";
887 break;
888 case OPC_LB:
889 op_ldst(lb);
890 GEN_STORE_TN_REG(rt, T0);
891 opn = "lb";
892 break;
893 case OPC_SB:
894 GEN_LOAD_REG_TN(T1, rt);
895 op_ldst(sb);
896 opn = "sb";
897 break;
898 case OPC_LBU:
899 op_ldst(lbu);
900 GEN_STORE_TN_REG(rt, T0);
901 opn = "lbu";
902 break;
903 case OPC_LWL:
904 GEN_LOAD_REG_TN(T1, rt);
905 op_ldst(lwl);
906 GEN_STORE_TN_REG(rt, T0);
907 opn = "lwl";
908 break;
909 case OPC_SWL:
910 GEN_LOAD_REG_TN(T1, rt);
911 op_ldst(swl);
912 opn = "swr";
913 break;
914 case OPC_LWR:
915 GEN_LOAD_REG_TN(T1, rt);
916 op_ldst(lwr);
917 GEN_STORE_TN_REG(rt, T0);
918 opn = "lwr";
919 break;
920 case OPC_SWR:
921 GEN_LOAD_REG_TN(T1, rt);
922 op_ldst(swr);
923 opn = "swr";
924 break;
925 case OPC_LL:
926 op_ldst(ll);
927 GEN_STORE_TN_REG(rt, T0);
928 opn = "ll";
929 break;
930 case OPC_SC:
931 save_cpu_state(ctx, 1);
932 GEN_LOAD_REG_TN(T1, rt);
933 op_ldst(sc);
934 GEN_STORE_TN_REG(rt, T0);
935 opn = "sc";
936 break;
937 default:
938 MIPS_INVAL(opn);
939 generate_exception(ctx, EXCP_RI);
940 return;
942 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
945 /* Load and store */
946 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
947 int base, int16_t offset)
949 const char *opn = "flt_ldst";
951 if (base == 0) {
952 GEN_LOAD_IMM_TN(T0, offset);
953 } else if (offset == 0) {
954 gen_op_load_gpr_T0(base);
955 } else {
956 gen_op_load_gpr_T0(base);
957 gen_op_set_T1(offset);
958 gen_op_addr_add();
960 /* Don't do NOP if destination is zero: we must perform the actual
961 * memory access
963 switch (opc) {
964 case OPC_LWC1:
965 op_ldst(lwc1);
966 GEN_STORE_FTN_FREG(ft, WT0);
967 opn = "lwc1";
968 break;
969 case OPC_SWC1:
970 GEN_LOAD_FREG_FTN(WT0, ft);
971 op_ldst(swc1);
972 opn = "swc1";
973 break;
974 case OPC_LDC1:
975 op_ldst(ldc1);
976 GEN_STORE_FTN_FREG(ft, DT0);
977 opn = "ldc1";
978 break;
979 case OPC_SDC1:
980 GEN_LOAD_FREG_FTN(DT0, ft);
981 op_ldst(sdc1);
982 opn = "sdc1";
983 break;
984 default:
985 MIPS_INVAL(opn);
986 generate_exception(ctx, EXCP_RI);
987 return;
989 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
992 /* Arithmetic with immediate operand */
993 static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
994 int rs, int16_t imm)
996 target_ulong uimm;
997 const char *opn = "imm arith";
999 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1000 /* if no destination, treat it as a NOP
1001 * For addi, we must generate the overflow exception when needed.
1003 MIPS_DEBUG("NOP");
1004 return;
1006 uimm = (uint16_t)imm;
1007 switch (opc) {
1008 case OPC_ADDI:
1009 case OPC_ADDIU:
1010 #ifdef TARGET_MIPS64
1011 case OPC_DADDI:
1012 case OPC_DADDIU:
1013 #endif
1014 case OPC_SLTI:
1015 case OPC_SLTIU:
1016 uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1017 /* Fall through. */
1018 case OPC_ANDI:
1019 case OPC_ORI:
1020 case OPC_XORI:
1021 GEN_LOAD_REG_TN(T0, rs);
1022 GEN_LOAD_IMM_TN(T1, uimm);
1023 break;
1024 case OPC_LUI:
1025 GEN_LOAD_IMM_TN(T0, imm << 16);
1026 break;
1027 case OPC_SLL:
1028 case OPC_SRA:
1029 case OPC_SRL:
1030 #ifdef TARGET_MIPS64
1031 case OPC_DSLL:
1032 case OPC_DSRA:
1033 case OPC_DSRL:
1034 case OPC_DSLL32:
1035 case OPC_DSRA32:
1036 case OPC_DSRL32:
1037 #endif
1038 uimm &= 0x1f;
1039 GEN_LOAD_REG_TN(T0, rs);
1040 GEN_LOAD_IMM_TN(T1, uimm);
1041 break;
1043 switch (opc) {
1044 case OPC_ADDI:
1045 save_cpu_state(ctx, 1);
1046 gen_op_addo();
1047 opn = "addi";
1048 break;
1049 case OPC_ADDIU:
1050 gen_op_add();
1051 opn = "addiu";
1052 break;
1053 #ifdef TARGET_MIPS64
1054 case OPC_DADDI:
1055 save_cpu_state(ctx, 1);
1056 gen_op_daddo();
1057 opn = "daddi";
1058 break;
1059 case OPC_DADDIU:
1060 gen_op_dadd();
1061 opn = "daddiu";
1062 break;
1063 #endif
1064 case OPC_SLTI:
1065 gen_op_lt();
1066 opn = "slti";
1067 break;
1068 case OPC_SLTIU:
1069 gen_op_ltu();
1070 opn = "sltiu";
1071 break;
1072 case OPC_ANDI:
1073 gen_op_and();
1074 opn = "andi";
1075 break;
1076 case OPC_ORI:
1077 gen_op_or();
1078 opn = "ori";
1079 break;
1080 case OPC_XORI:
1081 gen_op_xor();
1082 opn = "xori";
1083 break;
1084 case OPC_LUI:
1085 opn = "lui";
1086 break;
1087 case OPC_SLL:
1088 gen_op_sll();
1089 opn = "sll";
1090 break;
1091 case OPC_SRA:
1092 gen_op_sra();
1093 opn = "sra";
1094 break;
1095 case OPC_SRL:
1096 switch ((ctx->opcode >> 21) & 0x1f) {
1097 case 0:
1098 gen_op_srl();
1099 opn = "srl";
1100 break;
1101 case 1:
1102 gen_op_rotr();
1103 opn = "rotr";
1104 break;
1105 default:
1106 MIPS_INVAL("invalid srl flag");
1107 generate_exception(ctx, EXCP_RI);
1108 break;
1110 break;
1111 #ifdef TARGET_MIPS64
1112 case OPC_DSLL:
1113 gen_op_dsll();
1114 opn = "dsll";
1115 break;
1116 case OPC_DSRA:
1117 gen_op_dsra();
1118 opn = "dsra";
1119 break;
1120 case OPC_DSRL:
1121 switch ((ctx->opcode >> 21) & 0x1f) {
1122 case 0:
1123 gen_op_dsrl();
1124 opn = "dsrl";
1125 break;
1126 case 1:
1127 gen_op_drotr();
1128 opn = "drotr";
1129 break;
1130 default:
1131 MIPS_INVAL("invalid dsrl flag");
1132 generate_exception(ctx, EXCP_RI);
1133 break;
1135 break;
1136 case OPC_DSLL32:
1137 gen_op_dsll32();
1138 opn = "dsll32";
1139 break;
1140 case OPC_DSRA32:
1141 gen_op_dsra32();
1142 opn = "dsra32";
1143 break;
1144 case OPC_DSRL32:
1145 switch ((ctx->opcode >> 21) & 0x1f) {
1146 case 0:
1147 gen_op_dsrl32();
1148 opn = "dsrl32";
1149 break;
1150 case 1:
1151 gen_op_drotr32();
1152 opn = "drotr32";
1153 break;
1154 default:
1155 MIPS_INVAL("invalid dsrl32 flag");
1156 generate_exception(ctx, EXCP_RI);
1157 break;
1159 break;
1160 #endif
1161 default:
1162 MIPS_INVAL(opn);
1163 generate_exception(ctx, EXCP_RI);
1164 return;
1166 GEN_STORE_TN_REG(rt, T0);
1167 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1170 /* Arithmetic */
1171 static void gen_arith (DisasContext *ctx, uint32_t opc,
1172 int rd, int rs, int rt)
1174 const char *opn = "arith";
1176 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1177 && opc != OPC_DADD && opc != OPC_DSUB) {
1178 /* if no destination, treat it as a NOP
1179 * For add & sub, we must generate the overflow exception when needed.
1181 MIPS_DEBUG("NOP");
1182 return;
1184 GEN_LOAD_REG_TN(T0, rs);
1185 GEN_LOAD_REG_TN(T1, rt);
1186 switch (opc) {
1187 case OPC_ADD:
1188 save_cpu_state(ctx, 1);
1189 gen_op_addo();
1190 opn = "add";
1191 break;
1192 case OPC_ADDU:
1193 gen_op_add();
1194 opn = "addu";
1195 break;
1196 case OPC_SUB:
1197 save_cpu_state(ctx, 1);
1198 gen_op_subo();
1199 opn = "sub";
1200 break;
1201 case OPC_SUBU:
1202 gen_op_sub();
1203 opn = "subu";
1204 break;
1205 #ifdef TARGET_MIPS64
1206 case OPC_DADD:
1207 save_cpu_state(ctx, 1);
1208 gen_op_daddo();
1209 opn = "dadd";
1210 break;
1211 case OPC_DADDU:
1212 gen_op_dadd();
1213 opn = "daddu";
1214 break;
1215 case OPC_DSUB:
1216 save_cpu_state(ctx, 1);
1217 gen_op_dsubo();
1218 opn = "dsub";
1219 break;
1220 case OPC_DSUBU:
1221 gen_op_dsub();
1222 opn = "dsubu";
1223 break;
1224 #endif
1225 case OPC_SLT:
1226 gen_op_lt();
1227 opn = "slt";
1228 break;
1229 case OPC_SLTU:
1230 gen_op_ltu();
1231 opn = "sltu";
1232 break;
1233 case OPC_AND:
1234 gen_op_and();
1235 opn = "and";
1236 break;
1237 case OPC_NOR:
1238 gen_op_nor();
1239 opn = "nor";
1240 break;
1241 case OPC_OR:
1242 gen_op_or();
1243 opn = "or";
1244 break;
1245 case OPC_XOR:
1246 gen_op_xor();
1247 opn = "xor";
1248 break;
1249 case OPC_MUL:
1250 gen_op_mul();
1251 opn = "mul";
1252 break;
1253 case OPC_MOVN:
1254 gen_op_movn(rd);
1255 opn = "movn";
1256 goto print;
1257 case OPC_MOVZ:
1258 gen_op_movz(rd);
1259 opn = "movz";
1260 goto print;
1261 case OPC_SLLV:
1262 gen_op_sllv();
1263 opn = "sllv";
1264 break;
1265 case OPC_SRAV:
1266 gen_op_srav();
1267 opn = "srav";
1268 break;
1269 case OPC_SRLV:
1270 switch ((ctx->opcode >> 6) & 0x1f) {
1271 case 0:
1272 gen_op_srlv();
1273 opn = "srlv";
1274 break;
1275 case 1:
1276 gen_op_rotrv();
1277 opn = "rotrv";
1278 break;
1279 default:
1280 MIPS_INVAL("invalid srlv flag");
1281 generate_exception(ctx, EXCP_RI);
1282 break;
1284 break;
1285 #ifdef TARGET_MIPS64
1286 case OPC_DSLLV:
1287 gen_op_dsllv();
1288 opn = "dsllv";
1289 break;
1290 case OPC_DSRAV:
1291 gen_op_dsrav();
1292 opn = "dsrav";
1293 break;
1294 case OPC_DSRLV:
1295 switch ((ctx->opcode >> 6) & 0x1f) {
1296 case 0:
1297 gen_op_dsrlv();
1298 opn = "dsrlv";
1299 break;
1300 case 1:
1301 gen_op_drotrv();
1302 opn = "drotrv";
1303 break;
1304 default:
1305 MIPS_INVAL("invalid dsrlv flag");
1306 generate_exception(ctx, EXCP_RI);
1307 break;
1309 break;
1310 #endif
1311 default:
1312 MIPS_INVAL(opn);
1313 generate_exception(ctx, EXCP_RI);
1314 return;
1316 GEN_STORE_TN_REG(rd, T0);
1317 print:
1318 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1321 /* Arithmetic on HI/LO registers */
1322 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1324 const char *opn = "hilo";
1326 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1327 /* Treat as a NOP */
1328 MIPS_DEBUG("NOP");
1329 return;
1331 switch (opc) {
1332 case OPC_MFHI:
1333 gen_op_load_HI();
1334 GEN_STORE_TN_REG(reg, T0);
1335 opn = "mfhi";
1336 break;
1337 case OPC_MFLO:
1338 gen_op_load_LO();
1339 GEN_STORE_TN_REG(reg, T0);
1340 opn = "mflo";
1341 break;
1342 case OPC_MTHI:
1343 GEN_LOAD_REG_TN(T0, reg);
1344 gen_op_store_HI();
1345 opn = "mthi";
1346 break;
1347 case OPC_MTLO:
1348 GEN_LOAD_REG_TN(T0, reg);
1349 gen_op_store_LO();
1350 opn = "mtlo";
1351 break;
1352 default:
1353 MIPS_INVAL(opn);
1354 generate_exception(ctx, EXCP_RI);
1355 return;
1357 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1360 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1361 int rs, int rt)
1363 const char *opn = "mul/div";
1365 GEN_LOAD_REG_TN(T0, rs);
1366 GEN_LOAD_REG_TN(T1, rt);
1367 switch (opc) {
1368 case OPC_DIV:
1369 gen_op_div();
1370 opn = "div";
1371 break;
1372 case OPC_DIVU:
1373 gen_op_divu();
1374 opn = "divu";
1375 break;
1376 case OPC_MULT:
1377 gen_op_mult();
1378 opn = "mult";
1379 break;
1380 case OPC_MULTU:
1381 gen_op_multu();
1382 opn = "multu";
1383 break;
1384 #ifdef TARGET_MIPS64
1385 case OPC_DDIV:
1386 gen_op_ddiv();
1387 opn = "ddiv";
1388 break;
1389 case OPC_DDIVU:
1390 gen_op_ddivu();
1391 opn = "ddivu";
1392 break;
1393 case OPC_DMULT:
1394 gen_op_dmult();
1395 opn = "dmult";
1396 break;
1397 case OPC_DMULTU:
1398 gen_op_dmultu();
1399 opn = "dmultu";
1400 break;
1401 #endif
1402 case OPC_MADD:
1403 gen_op_madd();
1404 opn = "madd";
1405 break;
1406 case OPC_MADDU:
1407 gen_op_maddu();
1408 opn = "maddu";
1409 break;
1410 case OPC_MSUB:
1411 gen_op_msub();
1412 opn = "msub";
1413 break;
1414 case OPC_MSUBU:
1415 gen_op_msubu();
1416 opn = "msubu";
1417 break;
1418 default:
1419 MIPS_INVAL(opn);
1420 generate_exception(ctx, EXCP_RI);
1421 return;
1423 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1426 static void gen_cl (DisasContext *ctx, uint32_t opc,
1427 int rd, int rs)
1429 const char *opn = "CLx";
1430 if (rd == 0) {
1431 /* Treat as a NOP */
1432 MIPS_DEBUG("NOP");
1433 return;
1435 GEN_LOAD_REG_TN(T0, rs);
1436 switch (opc) {
1437 case OPC_CLO:
1438 gen_op_clo();
1439 opn = "clo";
1440 break;
1441 case OPC_CLZ:
1442 gen_op_clz();
1443 opn = "clz";
1444 break;
1445 #ifdef TARGET_MIPS64
1446 case OPC_DCLO:
1447 gen_op_dclo();
1448 opn = "dclo";
1449 break;
1450 case OPC_DCLZ:
1451 gen_op_dclz();
1452 opn = "dclz";
1453 break;
1454 #endif
1455 default:
1456 MIPS_INVAL(opn);
1457 generate_exception(ctx, EXCP_RI);
1458 return;
1460 gen_op_store_T0_gpr(rd);
1461 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1464 /* Traps */
1465 static void gen_trap (DisasContext *ctx, uint32_t opc,
1466 int rs, int rt, int16_t imm)
1468 int cond;
1470 cond = 0;
1471 /* Load needed operands */
1472 switch (opc) {
1473 case OPC_TEQ:
1474 case OPC_TGE:
1475 case OPC_TGEU:
1476 case OPC_TLT:
1477 case OPC_TLTU:
1478 case OPC_TNE:
1479 /* Compare two registers */
1480 if (rs != rt) {
1481 GEN_LOAD_REG_TN(T0, rs);
1482 GEN_LOAD_REG_TN(T1, rt);
1483 cond = 1;
1485 break;
1486 case OPC_TEQI:
1487 case OPC_TGEI:
1488 case OPC_TGEIU:
1489 case OPC_TLTI:
1490 case OPC_TLTIU:
1491 case OPC_TNEI:
1492 /* Compare register to immediate */
1493 if (rs != 0 || imm != 0) {
1494 GEN_LOAD_REG_TN(T0, rs);
1495 GEN_LOAD_IMM_TN(T1, (int32_t)imm);
1496 cond = 1;
1498 break;
1500 if (cond == 0) {
1501 switch (opc) {
1502 case OPC_TEQ: /* rs == rs */
1503 case OPC_TEQI: /* r0 == 0 */
1504 case OPC_TGE: /* rs >= rs */
1505 case OPC_TGEI: /* r0 >= 0 */
1506 case OPC_TGEU: /* rs >= rs unsigned */
1507 case OPC_TGEIU: /* r0 >= 0 unsigned */
1508 /* Always trap */
1509 gen_op_set_T0(1);
1510 break;
1511 case OPC_TLT: /* rs < rs */
1512 case OPC_TLTI: /* r0 < 0 */
1513 case OPC_TLTU: /* rs < rs unsigned */
1514 case OPC_TLTIU: /* r0 < 0 unsigned */
1515 case OPC_TNE: /* rs != rs */
1516 case OPC_TNEI: /* r0 != 0 */
1517 /* Never trap: treat as NOP */
1518 return;
1519 default:
1520 MIPS_INVAL("trap");
1521 generate_exception(ctx, EXCP_RI);
1522 return;
1524 } else {
1525 switch (opc) {
1526 case OPC_TEQ:
1527 case OPC_TEQI:
1528 gen_op_eq();
1529 break;
1530 case OPC_TGE:
1531 case OPC_TGEI:
1532 gen_op_ge();
1533 break;
1534 case OPC_TGEU:
1535 case OPC_TGEIU:
1536 gen_op_geu();
1537 break;
1538 case OPC_TLT:
1539 case OPC_TLTI:
1540 gen_op_lt();
1541 break;
1542 case OPC_TLTU:
1543 case OPC_TLTIU:
1544 gen_op_ltu();
1545 break;
1546 case OPC_TNE:
1547 case OPC_TNEI:
1548 gen_op_ne();
1549 break;
1550 default:
1551 MIPS_INVAL("trap");
1552 generate_exception(ctx, EXCP_RI);
1553 return;
1556 save_cpu_state(ctx, 1);
1557 gen_op_trap();
1558 ctx->bstate = BS_STOP;
1561 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1563 TranslationBlock *tb;
1564 tb = ctx->tb;
1565 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1566 if (n == 0)
1567 gen_op_goto_tb0(TBPARAM(tb));
1568 else
1569 gen_op_goto_tb1(TBPARAM(tb));
1570 gen_save_pc(dest);
1571 gen_op_set_T0((long)tb + n);
1572 } else {
1573 gen_save_pc(dest);
1574 gen_op_reset_T0();
1576 gen_op_exit_tb();
1579 /* Branches (before delay slot) */
1580 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1581 int rs, int rt, int32_t offset)
1583 target_ulong btarget = -1;
1584 int blink = 0;
1585 int bcond = 0;
1587 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1588 #ifdef MIPS_DEBUG_DISAS
1589 if (loglevel & CPU_LOG_TB_IN_ASM) {
1590 fprintf(logfile,
1591 "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
1592 ctx->pc);
1594 #endif
1595 generate_exception(ctx, EXCP_RI);
1596 return;
1599 /* Load needed operands */
1600 switch (opc) {
1601 case OPC_BEQ:
1602 case OPC_BEQL:
1603 case OPC_BNE:
1604 case OPC_BNEL:
1605 /* Compare two registers */
1606 if (rs != rt) {
1607 GEN_LOAD_REG_TN(T0, rs);
1608 GEN_LOAD_REG_TN(T1, rt);
1609 bcond = 1;
1611 btarget = ctx->pc + 4 + offset;
1612 break;
1613 case OPC_BGEZ:
1614 case OPC_BGEZAL:
1615 case OPC_BGEZALL:
1616 case OPC_BGEZL:
1617 case OPC_BGTZ:
1618 case OPC_BGTZL:
1619 case OPC_BLEZ:
1620 case OPC_BLEZL:
1621 case OPC_BLTZ:
1622 case OPC_BLTZAL:
1623 case OPC_BLTZALL:
1624 case OPC_BLTZL:
1625 /* Compare to zero */
1626 if (rs != 0) {
1627 gen_op_load_gpr_T0(rs);
1628 bcond = 1;
1630 btarget = ctx->pc + 4 + offset;
1631 break;
1632 case OPC_J:
1633 case OPC_JAL:
1634 /* Jump to immediate */
1635 btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
1636 break;
1637 case OPC_JR:
1638 case OPC_JALR:
1639 /* Jump to register */
1640 if (offset != 0 && offset != 16) {
1641 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1642 others are reserved. */
1643 MIPS_INVAL("jump hint");
1644 generate_exception(ctx, EXCP_RI);
1645 return;
1647 GEN_LOAD_REG_TN(T2, rs);
1648 break;
1649 default:
1650 MIPS_INVAL("branch/jump");
1651 generate_exception(ctx, EXCP_RI);
1652 return;
1654 if (bcond == 0) {
1655 /* No condition to be computed */
1656 switch (opc) {
1657 case OPC_BEQ: /* rx == rx */
1658 case OPC_BEQL: /* rx == rx likely */
1659 case OPC_BGEZ: /* 0 >= 0 */
1660 case OPC_BGEZL: /* 0 >= 0 likely */
1661 case OPC_BLEZ: /* 0 <= 0 */
1662 case OPC_BLEZL: /* 0 <= 0 likely */
1663 /* Always take */
1664 ctx->hflags |= MIPS_HFLAG_B;
1665 MIPS_DEBUG("balways");
1666 break;
1667 case OPC_BGEZAL: /* 0 >= 0 */
1668 case OPC_BGEZALL: /* 0 >= 0 likely */
1669 /* Always take and link */
1670 blink = 31;
1671 ctx->hflags |= MIPS_HFLAG_B;
1672 MIPS_DEBUG("balways and link");
1673 break;
1674 case OPC_BNE: /* rx != rx */
1675 case OPC_BGTZ: /* 0 > 0 */
1676 case OPC_BLTZ: /* 0 < 0 */
1677 /* Treated as NOP */
1678 MIPS_DEBUG("bnever (NOP)");
1679 return;
1680 case OPC_BLTZAL: /* 0 < 0 */
1681 GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
1682 gen_op_store_T0_gpr(31);
1683 MIPS_DEBUG("bnever and link");
1684 return;
1685 case OPC_BLTZALL: /* 0 < 0 likely */
1686 GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
1687 gen_op_store_T0_gpr(31);
1688 /* Skip the instruction in the delay slot */
1689 MIPS_DEBUG("bnever, link and skip");
1690 ctx->pc += 4;
1691 return;
1692 case OPC_BNEL: /* rx != rx likely */
1693 case OPC_BGTZL: /* 0 > 0 likely */
1694 case OPC_BLTZL: /* 0 < 0 likely */
1695 /* Skip the instruction in the delay slot */
1696 MIPS_DEBUG("bnever and skip");
1697 ctx->pc += 4;
1698 return;
1699 case OPC_J:
1700 ctx->hflags |= MIPS_HFLAG_B;
1701 MIPS_DEBUG("j " TARGET_FMT_lx, btarget);
1702 break;
1703 case OPC_JAL:
1704 blink = 31;
1705 ctx->hflags |= MIPS_HFLAG_B;
1706 MIPS_DEBUG("jal " TARGET_FMT_lx, btarget);
1707 break;
1708 case OPC_JR:
1709 ctx->hflags |= MIPS_HFLAG_BR;
1710 MIPS_DEBUG("jr %s", regnames[rs]);
1711 break;
1712 case OPC_JALR:
1713 blink = rt;
1714 ctx->hflags |= MIPS_HFLAG_BR;
1715 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1716 break;
1717 default:
1718 MIPS_INVAL("branch/jump");
1719 generate_exception(ctx, EXCP_RI);
1720 return;
1722 } else {
1723 switch (opc) {
1724 case OPC_BEQ:
1725 gen_op_eq();
1726 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
1727 regnames[rs], regnames[rt], btarget);
1728 goto not_likely;
1729 case OPC_BEQL:
1730 gen_op_eq();
1731 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
1732 regnames[rs], regnames[rt], btarget);
1733 goto likely;
1734 case OPC_BNE:
1735 gen_op_ne();
1736 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
1737 regnames[rs], regnames[rt], btarget);
1738 goto not_likely;
1739 case OPC_BNEL:
1740 gen_op_ne();
1741 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
1742 regnames[rs], regnames[rt], btarget);
1743 goto likely;
1744 case OPC_BGEZ:
1745 gen_op_gez();
1746 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btarget);
1747 goto not_likely;
1748 case OPC_BGEZL:
1749 gen_op_gez();
1750 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1751 goto likely;
1752 case OPC_BGEZAL:
1753 gen_op_gez();
1754 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btarget);
1755 blink = 31;
1756 goto not_likely;
1757 case OPC_BGEZALL:
1758 gen_op_gez();
1759 blink = 31;
1760 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btarget);
1761 goto likely;
1762 case OPC_BGTZ:
1763 gen_op_gtz();
1764 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btarget);
1765 goto not_likely;
1766 case OPC_BGTZL:
1767 gen_op_gtz();
1768 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1769 goto likely;
1770 case OPC_BLEZ:
1771 gen_op_lez();
1772 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btarget);
1773 goto not_likely;
1774 case OPC_BLEZL:
1775 gen_op_lez();
1776 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1777 goto likely;
1778 case OPC_BLTZ:
1779 gen_op_ltz();
1780 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btarget);
1781 goto not_likely;
1782 case OPC_BLTZL:
1783 gen_op_ltz();
1784 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btarget);
1785 goto likely;
1786 case OPC_BLTZAL:
1787 gen_op_ltz();
1788 blink = 31;
1789 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btarget);
1790 not_likely:
1791 ctx->hflags |= MIPS_HFLAG_BC;
1792 gen_op_set_bcond();
1793 break;
1794 case OPC_BLTZALL:
1795 gen_op_ltz();
1796 blink = 31;
1797 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btarget);
1798 likely:
1799 ctx->hflags |= MIPS_HFLAG_BL;
1800 gen_op_set_bcond();
1801 gen_op_save_bcond();
1802 break;
1803 default:
1804 MIPS_INVAL("conditional branch/jump");
1805 generate_exception(ctx, EXCP_RI);
1806 return;
1809 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
1810 blink, ctx->hflags, btarget);
1812 ctx->btarget = btarget;
1813 if (blink > 0) {
1814 GEN_LOAD_IMM_TN(T0, ctx->pc + 8);
1815 gen_op_store_T0_gpr(blink);
1819 /* special3 bitfield operations */
1820 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1821 int rs, int lsb, int msb)
1823 GEN_LOAD_REG_TN(T1, rs);
1824 switch (opc) {
1825 case OPC_EXT:
1826 if (lsb + msb > 31)
1827 goto fail;
1828 gen_op_ext(lsb, msb + 1);
1829 break;
1830 case OPC_DEXTM:
1831 if (lsb + msb > 63)
1832 goto fail;
1833 gen_op_ext(lsb, msb + 1 + 32);
1834 break;
1835 case OPC_DEXTU:
1836 if (lsb + msb > 63)
1837 goto fail;
1838 gen_op_ext(lsb + 32, msb + 1);
1839 break;
1840 case OPC_DEXT:
1841 gen_op_ext(lsb, msb + 1);
1842 break;
1843 case OPC_INS:
1844 if (lsb > msb)
1845 goto fail;
1846 GEN_LOAD_REG_TN(T0, rt);
1847 gen_op_ins(lsb, msb - lsb + 1);
1848 break;
1849 case OPC_DINSM:
1850 if (lsb > msb)
1851 goto fail;
1852 GEN_LOAD_REG_TN(T0, rt);
1853 gen_op_ins(lsb, msb - lsb + 1 + 32);
1854 break;
1855 case OPC_DINSU:
1856 if (lsb > msb)
1857 goto fail;
1858 GEN_LOAD_REG_TN(T0, rt);
1859 gen_op_ins(lsb + 32, msb - lsb + 1);
1860 break;
1861 case OPC_DINS:
1862 if (lsb > msb)
1863 goto fail;
1864 GEN_LOAD_REG_TN(T0, rt);
1865 gen_op_ins(lsb, msb - lsb + 1);
1866 break;
1867 default:
1868 fail:
1869 MIPS_INVAL("bitops");
1870 generate_exception(ctx, EXCP_RI);
1871 return;
1873 GEN_STORE_TN_REG(rt, T0);
1876 /* CP0 (MMU and control) */
1877 static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
1879 const char *rn = "invalid";
1881 switch (reg) {
1882 case 0:
1883 switch (sel) {
1884 case 0:
1885 gen_op_mfc0_index();
1886 rn = "Index";
1887 break;
1888 case 1:
1889 // gen_op_mfc0_mvpcontrol(); /* MT ASE */
1890 rn = "MVPControl";
1891 // break;
1892 case 2:
1893 // gen_op_mfc0_mvpconf0(); /* MT ASE */
1894 rn = "MVPConf0";
1895 // break;
1896 case 3:
1897 // gen_op_mfc0_mvpconf1(); /* MT ASE */
1898 rn = "MVPConf1";
1899 // break;
1900 default:
1901 goto die;
1903 break;
1904 case 1:
1905 switch (sel) {
1906 case 0:
1907 gen_op_mfc0_random();
1908 rn = "Random";
1909 break;
1910 case 1:
1911 // gen_op_mfc0_vpecontrol(); /* MT ASE */
1912 rn = "VPEControl";
1913 // break;
1914 case 2:
1915 // gen_op_mfc0_vpeconf0(); /* MT ASE */
1916 rn = "VPEConf0";
1917 // break;
1918 case 3:
1919 // gen_op_mfc0_vpeconf1(); /* MT ASE */
1920 rn = "VPEConf1";
1921 // break;
1922 case 4:
1923 // gen_op_mfc0_YQMask(); /* MT ASE */
1924 rn = "YQMask";
1925 // break;
1926 case 5:
1927 // gen_op_mfc0_vpeschedule(); /* MT ASE */
1928 rn = "VPESchedule";
1929 // break;
1930 case 6:
1931 // gen_op_mfc0_vpeschefback(); /* MT ASE */
1932 rn = "VPEScheFBack";
1933 // break;
1934 case 7:
1935 // gen_op_mfc0_vpeopt(); /* MT ASE */
1936 rn = "VPEOpt";
1937 // break;
1938 default:
1939 goto die;
1941 break;
1942 case 2:
1943 switch (sel) {
1944 case 0:
1945 gen_op_mfc0_entrylo0();
1946 rn = "EntryLo0";
1947 break;
1948 case 1:
1949 // gen_op_mfc0_tcstatus(); /* MT ASE */
1950 rn = "TCStatus";
1951 // break;
1952 case 2:
1953 // gen_op_mfc0_tcbind(); /* MT ASE */
1954 rn = "TCBind";
1955 // break;
1956 case 3:
1957 // gen_op_mfc0_tcrestart(); /* MT ASE */
1958 rn = "TCRestart";
1959 // break;
1960 case 4:
1961 // gen_op_mfc0_tchalt(); /* MT ASE */
1962 rn = "TCHalt";
1963 // break;
1964 case 5:
1965 // gen_op_mfc0_tccontext(); /* MT ASE */
1966 rn = "TCContext";
1967 // break;
1968 case 6:
1969 // gen_op_mfc0_tcschedule(); /* MT ASE */
1970 rn = "TCSchedule";
1971 // break;
1972 case 7:
1973 // gen_op_mfc0_tcschefback(); /* MT ASE */
1974 rn = "TCScheFBack";
1975 // break;
1976 default:
1977 goto die;
1979 break;
1980 case 3:
1981 switch (sel) {
1982 case 0:
1983 gen_op_mfc0_entrylo1();
1984 rn = "EntryLo1";
1985 break;
1986 default:
1987 goto die;
1989 break;
1990 case 4:
1991 switch (sel) {
1992 case 0:
1993 gen_op_mfc0_context();
1994 rn = "Context";
1995 break;
1996 case 1:
1997 // gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
1998 rn = "ContextConfig";
1999 // break;
2000 default:
2001 goto die;
2003 break;
2004 case 5:
2005 switch (sel) {
2006 case 0:
2007 gen_op_mfc0_pagemask();
2008 rn = "PageMask";
2009 break;
2010 case 1:
2011 check_mips_r2(env, ctx);
2012 gen_op_mfc0_pagegrain();
2013 rn = "PageGrain";
2014 break;
2015 default:
2016 goto die;
2018 break;
2019 case 6:
2020 switch (sel) {
2021 case 0:
2022 gen_op_mfc0_wired();
2023 rn = "Wired";
2024 break;
2025 case 1:
2026 // gen_op_mfc0_srsconf0(); /* shadow registers */
2027 rn = "SRSConf0";
2028 // break;
2029 case 2:
2030 // gen_op_mfc0_srsconf1(); /* shadow registers */
2031 rn = "SRSConf1";
2032 // break;
2033 case 3:
2034 // gen_op_mfc0_srsconf2(); /* shadow registers */
2035 rn = "SRSConf2";
2036 // break;
2037 case 4:
2038 // gen_op_mfc0_srsconf3(); /* shadow registers */
2039 rn = "SRSConf3";
2040 // break;
2041 case 5:
2042 // gen_op_mfc0_srsconf4(); /* shadow registers */
2043 rn = "SRSConf4";
2044 // break;
2045 default:
2046 goto die;
2048 break;
2049 case 7:
2050 switch (sel) {
2051 case 0:
2052 check_mips_r2(env, ctx);
2053 gen_op_mfc0_hwrena();
2054 rn = "HWREna";
2055 break;
2056 default:
2057 goto die;
2059 break;
2060 case 8:
2061 switch (sel) {
2062 case 0:
2063 gen_op_mfc0_badvaddr();
2064 rn = "BadVaddr";
2065 break;
2066 default:
2067 goto die;
2069 break;
2070 case 9:
2071 switch (sel) {
2072 case 0:
2073 gen_op_mfc0_count();
2074 rn = "Count";
2075 break;
2076 /* 6,7 are implementation dependent */
2077 default:
2078 goto die;
2080 break;
2081 case 10:
2082 switch (sel) {
2083 case 0:
2084 gen_op_mfc0_entryhi();
2085 rn = "EntryHi";
2086 break;
2087 default:
2088 goto die;
2090 break;
2091 case 11:
2092 switch (sel) {
2093 case 0:
2094 gen_op_mfc0_compare();
2095 rn = "Compare";
2096 break;
2097 /* 6,7 are implementation dependent */
2098 default:
2099 goto die;
2101 break;
2102 case 12:
2103 switch (sel) {
2104 case 0:
2105 gen_op_mfc0_status();
2106 rn = "Status";
2107 break;
2108 case 1:
2109 check_mips_r2(env, ctx);
2110 gen_op_mfc0_intctl();
2111 rn = "IntCtl";
2112 break;
2113 case 2:
2114 check_mips_r2(env, ctx);
2115 gen_op_mfc0_srsctl();
2116 rn = "SRSCtl";
2117 break;
2118 case 3:
2119 check_mips_r2(env, ctx);
2120 gen_op_mfc0_srsmap();
2121 rn = "SRSMap";
2122 break;
2123 default:
2124 goto die;
2126 break;
2127 case 13:
2128 switch (sel) {
2129 case 0:
2130 gen_op_mfc0_cause();
2131 rn = "Cause";
2132 break;
2133 default:
2134 goto die;
2136 break;
2137 case 14:
2138 switch (sel) {
2139 case 0:
2140 gen_op_mfc0_epc();
2141 rn = "EPC";
2142 break;
2143 default:
2144 goto die;
2146 break;
2147 case 15:
2148 switch (sel) {
2149 case 0:
2150 gen_op_mfc0_prid();
2151 rn = "PRid";
2152 break;
2153 case 1:
2154 check_mips_r2(env, ctx);
2155 gen_op_mfc0_ebase();
2156 rn = "EBase";
2157 break;
2158 default:
2159 goto die;
2161 break;
2162 case 16:
2163 switch (sel) {
2164 case 0:
2165 gen_op_mfc0_config0();
2166 rn = "Config";
2167 break;
2168 case 1:
2169 gen_op_mfc0_config1();
2170 rn = "Config1";
2171 break;
2172 case 2:
2173 gen_op_mfc0_config2();
2174 rn = "Config2";
2175 break;
2176 case 3:
2177 gen_op_mfc0_config3();
2178 rn = "Config3";
2179 break;
2180 /* 4,5 are reserved */
2181 /* 6,7 are implementation dependent */
2182 case 6:
2183 gen_op_mfc0_config6();
2184 rn = "Config6";
2185 break;
2186 case 7:
2187 gen_op_mfc0_config7();
2188 rn = "Config7";
2189 break;
2190 default:
2191 goto die;
2193 break;
2194 case 17:
2195 switch (sel) {
2196 case 0:
2197 gen_op_mfc0_lladdr();
2198 rn = "LLAddr";
2199 break;
2200 default:
2201 goto die;
2203 break;
2204 case 18:
2205 switch (sel) {
2206 case 0 ... 7:
2207 gen_op_mfc0_watchlo(sel);
2208 rn = "WatchLo";
2209 break;
2210 default:
2211 goto die;
2213 break;
2214 case 19:
2215 switch (sel) {
2216 case 0 ...7:
2217 gen_op_mfc0_watchhi(sel);
2218 rn = "WatchHi";
2219 break;
2220 default:
2221 goto die;
2223 break;
2224 case 20:
2225 switch (sel) {
2226 case 0:
2227 #ifdef TARGET_MIPS64
2228 if (!(ctx->hflags & MIPS_HFLAG_64))
2229 goto die;
2230 gen_op_mfc0_xcontext();
2231 rn = "XContext";
2232 break;
2233 #endif
2234 default:
2235 goto die;
2237 break;
2238 case 21:
2239 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2240 switch (sel) {
2241 case 0:
2242 gen_op_mfc0_framemask();
2243 rn = "Framemask";
2244 break;
2245 default:
2246 goto die;
2248 break;
2249 case 22:
2250 /* ignored */
2251 rn = "'Diagnostic"; /* implementation dependent */
2252 break;
2253 case 23:
2254 switch (sel) {
2255 case 0:
2256 gen_op_mfc0_debug(); /* EJTAG support */
2257 rn = "Debug";
2258 break;
2259 case 1:
2260 // gen_op_mfc0_tracecontrol(); /* PDtrace support */
2261 rn = "TraceControl";
2262 // break;
2263 case 2:
2264 // gen_op_mfc0_tracecontrol2(); /* PDtrace support */
2265 rn = "TraceControl2";
2266 // break;
2267 case 3:
2268 // gen_op_mfc0_usertracedata(); /* PDtrace support */
2269 rn = "UserTraceData";
2270 // break;
2271 case 4:
2272 // gen_op_mfc0_debug(); /* PDtrace support */
2273 rn = "TraceBPC";
2274 // break;
2275 default:
2276 goto die;
2278 break;
2279 case 24:
2280 switch (sel) {
2281 case 0:
2282 gen_op_mfc0_depc(); /* EJTAG support */
2283 rn = "DEPC";
2284 break;
2285 default:
2286 goto die;
2288 break;
2289 case 25:
2290 switch (sel) {
2291 case 0:
2292 gen_op_mfc0_performance0();
2293 rn = "Performance0";
2294 break;
2295 case 1:
2296 // gen_op_mfc0_performance1();
2297 rn = "Performance1";
2298 // break;
2299 case 2:
2300 // gen_op_mfc0_performance2();
2301 rn = "Performance2";
2302 // break;
2303 case 3:
2304 // gen_op_mfc0_performance3();
2305 rn = "Performance3";
2306 // break;
2307 case 4:
2308 // gen_op_mfc0_performance4();
2309 rn = "Performance4";
2310 // break;
2311 case 5:
2312 // gen_op_mfc0_performance5();
2313 rn = "Performance5";
2314 // break;
2315 case 6:
2316 // gen_op_mfc0_performance6();
2317 rn = "Performance6";
2318 // break;
2319 case 7:
2320 // gen_op_mfc0_performance7();
2321 rn = "Performance7";
2322 // break;
2323 default:
2324 goto die;
2326 break;
2327 case 26:
2328 rn = "ECC";
2329 break;
2330 case 27:
2331 switch (sel) {
2332 /* ignored */
2333 case 0 ... 3:
2334 rn = "CacheErr";
2335 break;
2336 default:
2337 goto die;
2339 break;
2340 case 28:
2341 switch (sel) {
2342 case 0:
2343 case 2:
2344 case 4:
2345 case 6:
2346 gen_op_mfc0_taglo();
2347 rn = "TagLo";
2348 break;
2349 case 1:
2350 case 3:
2351 case 5:
2352 case 7:
2353 gen_op_mfc0_datalo();
2354 rn = "DataLo";
2355 break;
2356 default:
2357 goto die;
2359 break;
2360 case 29:
2361 switch (sel) {
2362 case 0:
2363 case 2:
2364 case 4:
2365 case 6:
2366 gen_op_mfc0_taghi();
2367 rn = "TagHi";
2368 break;
2369 case 1:
2370 case 3:
2371 case 5:
2372 case 7:
2373 gen_op_mfc0_datahi();
2374 rn = "DataHi";
2375 break;
2376 default:
2377 goto die;
2379 break;
2380 case 30:
2381 switch (sel) {
2382 case 0:
2383 gen_op_mfc0_errorepc();
2384 rn = "ErrorEPC";
2385 break;
2386 default:
2387 goto die;
2389 break;
2390 case 31:
2391 switch (sel) {
2392 case 0:
2393 gen_op_mfc0_desave(); /* EJTAG support */
2394 rn = "DESAVE";
2395 break;
2396 default:
2397 goto die;
2399 break;
2400 default:
2401 goto die;
2403 #if defined MIPS_DEBUG_DISAS
2404 if (loglevel & CPU_LOG_TB_IN_ASM) {
2405 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2406 rn, reg, sel);
2408 #endif
2409 return;
2411 die:
2412 #if defined MIPS_DEBUG_DISAS
2413 if (loglevel & CPU_LOG_TB_IN_ASM) {
2414 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2415 rn, reg, sel);
2417 #endif
2418 generate_exception(ctx, EXCP_RI);
2421 static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
2423 const char *rn = "invalid";
2425 switch (reg) {
2426 case 0:
2427 switch (sel) {
2428 case 0:
2429 gen_op_mtc0_index();
2430 rn = "Index";
2431 break;
2432 case 1:
2433 // gen_op_mtc0_mvpcontrol(); /* MT ASE */
2434 rn = "MVPControl";
2435 // break;
2436 case 2:
2437 // gen_op_mtc0_mvpconf0(); /* MT ASE */
2438 rn = "MVPConf0";
2439 // break;
2440 case 3:
2441 // gen_op_mtc0_mvpconf1(); /* MT ASE */
2442 rn = "MVPConf1";
2443 // break;
2444 default:
2445 goto die;
2447 break;
2448 case 1:
2449 switch (sel) {
2450 case 0:
2451 /* ignored */
2452 rn = "Random";
2453 break;
2454 case 1:
2455 // gen_op_mtc0_vpecontrol(); /* MT ASE */
2456 rn = "VPEControl";
2457 // break;
2458 case 2:
2459 // gen_op_mtc0_vpeconf0(); /* MT ASE */
2460 rn = "VPEConf0";
2461 // break;
2462 case 3:
2463 // gen_op_mtc0_vpeconf1(); /* MT ASE */
2464 rn = "VPEConf1";
2465 // break;
2466 case 4:
2467 // gen_op_mtc0_YQMask(); /* MT ASE */
2468 rn = "YQMask";
2469 // break;
2470 case 5:
2471 // gen_op_mtc0_vpeschedule(); /* MT ASE */
2472 rn = "VPESchedule";
2473 // break;
2474 case 6:
2475 // gen_op_mtc0_vpeschefback(); /* MT ASE */
2476 rn = "VPEScheFBack";
2477 // break;
2478 case 7:
2479 // gen_op_mtc0_vpeopt(); /* MT ASE */
2480 rn = "VPEOpt";
2481 // break;
2482 default:
2483 goto die;
2485 break;
2486 case 2:
2487 switch (sel) {
2488 case 0:
2489 gen_op_mtc0_entrylo0();
2490 rn = "EntryLo0";
2491 break;
2492 case 1:
2493 // gen_op_mtc0_tcstatus(); /* MT ASE */
2494 rn = "TCStatus";
2495 // break;
2496 case 2:
2497 // gen_op_mtc0_tcbind(); /* MT ASE */
2498 rn = "TCBind";
2499 // break;
2500 case 3:
2501 // gen_op_mtc0_tcrestart(); /* MT ASE */
2502 rn = "TCRestart";
2503 // break;
2504 case 4:
2505 // gen_op_mtc0_tchalt(); /* MT ASE */
2506 rn = "TCHalt";
2507 // break;
2508 case 5:
2509 // gen_op_mtc0_tccontext(); /* MT ASE */
2510 rn = "TCContext";
2511 // break;
2512 case 6:
2513 // gen_op_mtc0_tcschedule(); /* MT ASE */
2514 rn = "TCSchedule";
2515 // break;
2516 case 7:
2517 // gen_op_mtc0_tcschefback(); /* MT ASE */
2518 rn = "TCScheFBack";
2519 // break;
2520 default:
2521 goto die;
2523 break;
2524 case 3:
2525 switch (sel) {
2526 case 0:
2527 gen_op_mtc0_entrylo1();
2528 rn = "EntryLo1";
2529 break;
2530 default:
2531 goto die;
2533 break;
2534 case 4:
2535 switch (sel) {
2536 case 0:
2537 gen_op_mtc0_context();
2538 rn = "Context";
2539 break;
2540 case 1:
2541 // gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
2542 rn = "ContextConfig";
2543 // break;
2544 default:
2545 goto die;
2547 break;
2548 case 5:
2549 switch (sel) {
2550 case 0:
2551 gen_op_mtc0_pagemask();
2552 rn = "PageMask";
2553 break;
2554 case 1:
2555 check_mips_r2(env, ctx);
2556 gen_op_mtc0_pagegrain();
2557 rn = "PageGrain";
2558 break;
2559 default:
2560 goto die;
2562 break;
2563 case 6:
2564 switch (sel) {
2565 case 0:
2566 gen_op_mtc0_wired();
2567 rn = "Wired";
2568 break;
2569 case 1:
2570 // gen_op_mtc0_srsconf0(); /* shadow registers */
2571 rn = "SRSConf0";
2572 // break;
2573 case 2:
2574 // gen_op_mtc0_srsconf1(); /* shadow registers */
2575 rn = "SRSConf1";
2576 // break;
2577 case 3:
2578 // gen_op_mtc0_srsconf2(); /* shadow registers */
2579 rn = "SRSConf2";
2580 // break;
2581 case 4:
2582 // gen_op_mtc0_srsconf3(); /* shadow registers */
2583 rn = "SRSConf3";
2584 // break;
2585 case 5:
2586 // gen_op_mtc0_srsconf4(); /* shadow registers */
2587 rn = "SRSConf4";
2588 // break;
2589 default:
2590 goto die;
2592 break;
2593 case 7:
2594 switch (sel) {
2595 case 0:
2596 check_mips_r2(env, ctx);
2597 gen_op_mtc0_hwrena();
2598 rn = "HWREna";
2599 break;
2600 default:
2601 goto die;
2603 break;
2604 case 8:
2605 /* ignored */
2606 rn = "BadVaddr";
2607 break;
2608 case 9:
2609 switch (sel) {
2610 case 0:
2611 gen_op_mtc0_count();
2612 rn = "Count";
2613 break;
2614 /* 6,7 are implementation dependent */
2615 default:
2616 goto die;
2618 /* Stop translation as we may have switched the execution mode */
2619 ctx->bstate = BS_STOP;
2620 break;
2621 case 10:
2622 switch (sel) {
2623 case 0:
2624 gen_op_mtc0_entryhi();
2625 rn = "EntryHi";
2626 break;
2627 default:
2628 goto die;
2630 break;
2631 case 11:
2632 switch (sel) {
2633 case 0:
2634 gen_op_mtc0_compare();
2635 rn = "Compare";
2636 break;
2637 /* 6,7 are implementation dependent */
2638 default:
2639 goto die;
2641 /* Stop translation as we may have switched the execution mode */
2642 ctx->bstate = BS_STOP;
2643 break;
2644 case 12:
2645 switch (sel) {
2646 case 0:
2647 gen_op_mtc0_status();
2648 /* BS_STOP isn't good enough here, hflags may have changed. */
2649 gen_save_pc(ctx->pc + 4);
2650 ctx->bstate = BS_EXCP;
2651 rn = "Status";
2652 break;
2653 case 1:
2654 check_mips_r2(env, ctx);
2655 gen_op_mtc0_intctl();
2656 /* Stop translation as we may have switched the execution mode */
2657 ctx->bstate = BS_STOP;
2658 rn = "IntCtl";
2659 break;
2660 case 2:
2661 check_mips_r2(env, ctx);
2662 gen_op_mtc0_srsctl();
2663 /* Stop translation as we may have switched the execution mode */
2664 ctx->bstate = BS_STOP;
2665 rn = "SRSCtl";
2666 break;
2667 case 3:
2668 check_mips_r2(env, ctx);
2669 gen_op_mtc0_srsmap();
2670 /* Stop translation as we may have switched the execution mode */
2671 ctx->bstate = BS_STOP;
2672 rn = "SRSMap";
2673 break;
2674 default:
2675 goto die;
2677 break;
2678 case 13:
2679 switch (sel) {
2680 case 0:
2681 gen_op_mtc0_cause();
2682 rn = "Cause";
2683 break;
2684 default:
2685 goto die;
2687 /* Stop translation as we may have switched the execution mode */
2688 ctx->bstate = BS_STOP;
2689 break;
2690 case 14:
2691 switch (sel) {
2692 case 0:
2693 gen_op_mtc0_epc();
2694 rn = "EPC";
2695 break;
2696 default:
2697 goto die;
2699 break;
2700 case 15:
2701 switch (sel) {
2702 case 0:
2703 /* ignored */
2704 rn = "PRid";
2705 break;
2706 case 1:
2707 check_mips_r2(env, ctx);
2708 gen_op_mtc0_ebase();
2709 rn = "EBase";
2710 break;
2711 default:
2712 goto die;
2714 break;
2715 case 16:
2716 switch (sel) {
2717 case 0:
2718 gen_op_mtc0_config0();
2719 rn = "Config";
2720 /* Stop translation as we may have switched the execution mode */
2721 ctx->bstate = BS_STOP;
2722 break;
2723 case 1:
2724 /* ignored, read only */
2725 rn = "Config1";
2726 break;
2727 case 2:
2728 gen_op_mtc0_config2();
2729 rn = "Config2";
2730 /* Stop translation as we may have switched the execution mode */
2731 ctx->bstate = BS_STOP;
2732 break;
2733 case 3:
2734 /* ignored, read only */
2735 rn = "Config3";
2736 break;
2737 /* 4,5 are reserved */
2738 /* 6,7 are implementation dependent */
2739 case 6:
2740 /* ignored */
2741 rn = "Config6";
2742 break;
2743 case 7:
2744 /* ignored */
2745 rn = "Config7";
2746 break;
2747 default:
2748 rn = "Invalid config selector";
2749 goto die;
2751 break;
2752 case 17:
2753 switch (sel) {
2754 case 0:
2755 /* ignored */
2756 rn = "LLAddr";
2757 break;
2758 default:
2759 goto die;
2761 break;
2762 case 18:
2763 switch (sel) {
2764 case 0 ... 7:
2765 gen_op_mtc0_watchlo(sel);
2766 rn = "WatchLo";
2767 break;
2768 default:
2769 goto die;
2771 break;
2772 case 19:
2773 switch (sel) {
2774 case 0 ... 7:
2775 gen_op_mtc0_watchhi(sel);
2776 rn = "WatchHi";
2777 break;
2778 default:
2779 goto die;
2781 break;
2782 case 20:
2783 switch (sel) {
2784 case 0:
2785 #ifdef TARGET_MIPS64
2786 if (!(ctx->hflags & MIPS_HFLAG_64))
2787 goto die;
2788 gen_op_mtc0_xcontext();
2789 rn = "XContext";
2790 break;
2791 #endif
2792 default:
2793 goto die;
2795 break;
2796 case 21:
2797 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2798 switch (sel) {
2799 case 0:
2800 gen_op_mtc0_framemask();
2801 rn = "Framemask";
2802 break;
2803 default:
2804 goto die;
2806 break;
2807 case 22:
2808 /* ignored */
2809 rn = "Diagnostic"; /* implementation dependent */
2810 break;
2811 case 23:
2812 switch (sel) {
2813 case 0:
2814 gen_op_mtc0_debug(); /* EJTAG support */
2815 /* BS_STOP isn't good enough here, hflags may have changed. */
2816 gen_save_pc(ctx->pc + 4);
2817 ctx->bstate = BS_EXCP;
2818 rn = "Debug";
2819 break;
2820 case 1:
2821 // gen_op_mtc0_tracecontrol(); /* PDtrace support */
2822 rn = "TraceControl";
2823 /* Stop translation as we may have switched the execution mode */
2824 ctx->bstate = BS_STOP;
2825 // break;
2826 case 2:
2827 // gen_op_mtc0_tracecontrol2(); /* PDtrace support */
2828 rn = "TraceControl2";
2829 /* Stop translation as we may have switched the execution mode */
2830 ctx->bstate = BS_STOP;
2831 // break;
2832 case 3:
2833 /* Stop translation as we may have switched the execution mode */
2834 ctx->bstate = BS_STOP;
2835 // gen_op_mtc0_usertracedata(); /* PDtrace support */
2836 rn = "UserTraceData";
2837 /* Stop translation as we may have switched the execution mode */
2838 ctx->bstate = BS_STOP;
2839 // break;
2840 case 4:
2841 // gen_op_mtc0_debug(); /* PDtrace support */
2842 /* Stop translation as we may have switched the execution mode */
2843 ctx->bstate = BS_STOP;
2844 rn = "TraceBPC";
2845 // break;
2846 default:
2847 goto die;
2849 break;
2850 case 24:
2851 switch (sel) {
2852 case 0:
2853 gen_op_mtc0_depc(); /* EJTAG support */
2854 rn = "DEPC";
2855 break;
2856 default:
2857 goto die;
2859 break;
2860 case 25:
2861 switch (sel) {
2862 case 0:
2863 gen_op_mtc0_performance0();
2864 rn = "Performance0";
2865 break;
2866 case 1:
2867 // gen_op_mtc0_performance1();
2868 rn = "Performance1";
2869 // break;
2870 case 2:
2871 // gen_op_mtc0_performance2();
2872 rn = "Performance2";
2873 // break;
2874 case 3:
2875 // gen_op_mtc0_performance3();
2876 rn = "Performance3";
2877 // break;
2878 case 4:
2879 // gen_op_mtc0_performance4();
2880 rn = "Performance4";
2881 // break;
2882 case 5:
2883 // gen_op_mtc0_performance5();
2884 rn = "Performance5";
2885 // break;
2886 case 6:
2887 // gen_op_mtc0_performance6();
2888 rn = "Performance6";
2889 // break;
2890 case 7:
2891 // gen_op_mtc0_performance7();
2892 rn = "Performance7";
2893 // break;
2894 default:
2895 goto die;
2897 break;
2898 case 26:
2899 /* ignored */
2900 rn = "ECC";
2901 break;
2902 case 27:
2903 switch (sel) {
2904 case 0 ... 3:
2905 /* ignored */
2906 rn = "CacheErr";
2907 break;
2908 default:
2909 goto die;
2911 break;
2912 case 28:
2913 switch (sel) {
2914 case 0:
2915 case 2:
2916 case 4:
2917 case 6:
2918 gen_op_mtc0_taglo();
2919 rn = "TagLo";
2920 break;
2921 case 1:
2922 case 3:
2923 case 5:
2924 case 7:
2925 gen_op_mtc0_datalo();
2926 rn = "DataLo";
2927 break;
2928 default:
2929 goto die;
2931 break;
2932 case 29:
2933 switch (sel) {
2934 case 0:
2935 case 2:
2936 case 4:
2937 case 6:
2938 gen_op_mtc0_taghi();
2939 rn = "TagHi";
2940 break;
2941 case 1:
2942 case 3:
2943 case 5:
2944 case 7:
2945 gen_op_mtc0_datahi();
2946 rn = "DataHi";
2947 break;
2948 default:
2949 rn = "invalid sel";
2950 goto die;
2952 break;
2953 case 30:
2954 switch (sel) {
2955 case 0:
2956 gen_op_mtc0_errorepc();
2957 rn = "ErrorEPC";
2958 break;
2959 default:
2960 goto die;
2962 break;
2963 case 31:
2964 switch (sel) {
2965 case 0:
2966 gen_op_mtc0_desave(); /* EJTAG support */
2967 rn = "DESAVE";
2968 break;
2969 default:
2970 goto die;
2972 /* Stop translation as we may have switched the execution mode */
2973 ctx->bstate = BS_STOP;
2974 break;
2975 default:
2976 goto die;
2978 #if defined MIPS_DEBUG_DISAS
2979 if (loglevel & CPU_LOG_TB_IN_ASM) {
2980 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2981 rn, reg, sel);
2983 #endif
2984 return;
2986 die:
2987 #if defined MIPS_DEBUG_DISAS
2988 if (loglevel & CPU_LOG_TB_IN_ASM) {
2989 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2990 rn, reg, sel);
2992 #endif
2993 generate_exception(ctx, EXCP_RI);
2996 #ifdef TARGET_MIPS64
2997 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
2999 const char *rn = "invalid";
3001 switch (reg) {
3002 case 0:
3003 switch (sel) {
3004 case 0:
3005 gen_op_mfc0_index();
3006 rn = "Index";
3007 break;
3008 case 1:
3009 // gen_op_dmfc0_mvpcontrol(); /* MT ASE */
3010 rn = "MVPControl";
3011 // break;
3012 case 2:
3013 // gen_op_dmfc0_mvpconf0(); /* MT ASE */
3014 rn = "MVPConf0";
3015 // break;
3016 case 3:
3017 // gen_op_dmfc0_mvpconf1(); /* MT ASE */
3018 rn = "MVPConf1";
3019 // break;
3020 default:
3021 goto die;
3023 break;
3024 case 1:
3025 switch (sel) {
3026 case 0:
3027 gen_op_mfc0_random();
3028 rn = "Random";
3029 break;
3030 case 1:
3031 // gen_op_dmfc0_vpecontrol(); /* MT ASE */
3032 rn = "VPEControl";
3033 // break;
3034 case 2:
3035 // gen_op_dmfc0_vpeconf0(); /* MT ASE */
3036 rn = "VPEConf0";
3037 // break;
3038 case 3:
3039 // gen_op_dmfc0_vpeconf1(); /* MT ASE */
3040 rn = "VPEConf1";
3041 // break;
3042 case 4:
3043 // gen_op_dmfc0_YQMask(); /* MT ASE */
3044 rn = "YQMask";
3045 // break;
3046 case 5:
3047 // gen_op_dmfc0_vpeschedule(); /* MT ASE */
3048 rn = "VPESchedule";
3049 // break;
3050 case 6:
3051 // gen_op_dmfc0_vpeschefback(); /* MT ASE */
3052 rn = "VPEScheFBack";
3053 // break;
3054 case 7:
3055 // gen_op_dmfc0_vpeopt(); /* MT ASE */
3056 rn = "VPEOpt";
3057 // break;
3058 default:
3059 goto die;
3061 break;
3062 case 2:
3063 switch (sel) {
3064 case 0:
3065 gen_op_dmfc0_entrylo0();
3066 rn = "EntryLo0";
3067 break;
3068 case 1:
3069 // gen_op_dmfc0_tcstatus(); /* MT ASE */
3070 rn = "TCStatus";
3071 // break;
3072 case 2:
3073 // gen_op_dmfc0_tcbind(); /* MT ASE */
3074 rn = "TCBind";
3075 // break;
3076 case 3:
3077 // gen_op_dmfc0_tcrestart(); /* MT ASE */
3078 rn = "TCRestart";
3079 // break;
3080 case 4:
3081 // gen_op_dmfc0_tchalt(); /* MT ASE */
3082 rn = "TCHalt";
3083 // break;
3084 case 5:
3085 // gen_op_dmfc0_tccontext(); /* MT ASE */
3086 rn = "TCContext";
3087 // break;
3088 case 6:
3089 // gen_op_dmfc0_tcschedule(); /* MT ASE */
3090 rn = "TCSchedule";
3091 // break;
3092 case 7:
3093 // gen_op_dmfc0_tcschefback(); /* MT ASE */
3094 rn = "TCScheFBack";
3095 // break;
3096 default:
3097 goto die;
3099 break;
3100 case 3:
3101 switch (sel) {
3102 case 0:
3103 gen_op_dmfc0_entrylo1();
3104 rn = "EntryLo1";
3105 break;
3106 default:
3107 goto die;
3109 break;
3110 case 4:
3111 switch (sel) {
3112 case 0:
3113 gen_op_dmfc0_context();
3114 rn = "Context";
3115 break;
3116 case 1:
3117 // gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */
3118 rn = "ContextConfig";
3119 // break;
3120 default:
3121 goto die;
3123 break;
3124 case 5:
3125 switch (sel) {
3126 case 0:
3127 gen_op_mfc0_pagemask();
3128 rn = "PageMask";
3129 break;
3130 case 1:
3131 check_mips_r2(env, ctx);
3132 gen_op_mfc0_pagegrain();
3133 rn = "PageGrain";
3134 break;
3135 default:
3136 goto die;
3138 break;
3139 case 6:
3140 switch (sel) {
3141 case 0:
3142 gen_op_mfc0_wired();
3143 rn = "Wired";
3144 break;
3145 case 1:
3146 // gen_op_dmfc0_srsconf0(); /* shadow registers */
3147 rn = "SRSConf0";
3148 // break;
3149 case 2:
3150 // gen_op_dmfc0_srsconf1(); /* shadow registers */
3151 rn = "SRSConf1";
3152 // break;
3153 case 3:
3154 // gen_op_dmfc0_srsconf2(); /* shadow registers */
3155 rn = "SRSConf2";
3156 // break;
3157 case 4:
3158 // gen_op_dmfc0_srsconf3(); /* shadow registers */
3159 rn = "SRSConf3";
3160 // break;
3161 case 5:
3162 // gen_op_dmfc0_srsconf4(); /* shadow registers */
3163 rn = "SRSConf4";
3164 // break;
3165 default:
3166 goto die;
3168 break;
3169 case 7:
3170 switch (sel) {
3171 case 0:
3172 check_mips_r2(env, ctx);
3173 gen_op_mfc0_hwrena();
3174 rn = "HWREna";
3175 break;
3176 default:
3177 goto die;
3179 break;
3180 case 8:
3181 switch (sel) {
3182 case 0:
3183 gen_op_dmfc0_badvaddr();
3184 rn = "BadVaddr";
3185 break;
3186 default:
3187 goto die;
3189 break;
3190 case 9:
3191 switch (sel) {
3192 case 0:
3193 gen_op_mfc0_count();
3194 rn = "Count";
3195 break;
3196 /* 6,7 are implementation dependent */
3197 default:
3198 goto die;
3200 break;
3201 case 10:
3202 switch (sel) {
3203 case 0:
3204 gen_op_dmfc0_entryhi();
3205 rn = "EntryHi";
3206 break;
3207 default:
3208 goto die;
3210 break;
3211 case 11:
3212 switch (sel) {
3213 case 0:
3214 gen_op_mfc0_compare();
3215 rn = "Compare";
3216 break;
3217 /* 6,7 are implementation dependent */
3218 default:
3219 goto die;
3221 break;
3222 case 12:
3223 switch (sel) {
3224 case 0:
3225 gen_op_mfc0_status();
3226 rn = "Status";
3227 break;
3228 case 1:
3229 check_mips_r2(env, ctx);
3230 gen_op_mfc0_intctl();
3231 rn = "IntCtl";
3232 break;
3233 case 2:
3234 check_mips_r2(env, ctx);
3235 gen_op_mfc0_srsctl();
3236 rn = "SRSCtl";
3237 break;
3238 case 3:
3239 check_mips_r2(env, ctx);
3240 gen_op_mfc0_srsmap(); /* shadow registers */
3241 rn = "SRSMap";
3242 break;
3243 default:
3244 goto die;
3246 break;
3247 case 13:
3248 switch (sel) {
3249 case 0:
3250 gen_op_mfc0_cause();
3251 rn = "Cause";
3252 break;
3253 default:
3254 goto die;
3256 break;
3257 case 14:
3258 switch (sel) {
3259 case 0:
3260 gen_op_dmfc0_epc();
3261 rn = "EPC";
3262 break;
3263 default:
3264 goto die;
3266 break;
3267 case 15:
3268 switch (sel) {
3269 case 0:
3270 gen_op_mfc0_prid();
3271 rn = "PRid";
3272 break;
3273 case 1:
3274 check_mips_r2(env, ctx);
3275 gen_op_mfc0_ebase();
3276 rn = "EBase";
3277 break;
3278 default:
3279 goto die;
3281 break;
3282 case 16:
3283 switch (sel) {
3284 case 0:
3285 gen_op_mfc0_config0();
3286 rn = "Config";
3287 break;
3288 case 1:
3289 gen_op_mfc0_config1();
3290 rn = "Config1";
3291 break;
3292 case 2:
3293 gen_op_mfc0_config2();
3294 rn = "Config2";
3295 break;
3296 case 3:
3297 gen_op_mfc0_config3();
3298 rn = "Config3";
3299 break;
3300 /* 6,7 are implementation dependent */
3301 default:
3302 goto die;
3304 break;
3305 case 17:
3306 switch (sel) {
3307 case 0:
3308 gen_op_dmfc0_lladdr();
3309 rn = "LLAddr";
3310 break;
3311 default:
3312 goto die;
3314 break;
3315 case 18:
3316 switch (sel) {
3317 case 0 ... 7:
3318 gen_op_dmfc0_watchlo(sel);
3319 rn = "WatchLo";
3320 break;
3321 default:
3322 goto die;
3324 break;
3325 case 19:
3326 switch (sel) {
3327 case 0 ... 7:
3328 gen_op_mfc0_watchhi(sel);
3329 rn = "WatchHi";
3330 break;
3331 default:
3332 goto die;
3334 break;
3335 case 20:
3336 switch (sel) {
3337 case 0:
3338 gen_op_dmfc0_xcontext();
3339 rn = "XContext";
3340 break;
3341 default:
3342 goto die;
3344 break;
3345 case 21:
3346 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3347 switch (sel) {
3348 case 0:
3349 gen_op_mfc0_framemask();
3350 rn = "Framemask";
3351 break;
3352 default:
3353 goto die;
3355 break;
3356 case 22:
3357 /* ignored */
3358 rn = "'Diagnostic"; /* implementation dependent */
3359 break;
3360 case 23:
3361 switch (sel) {
3362 case 0:
3363 gen_op_mfc0_debug(); /* EJTAG support */
3364 rn = "Debug";
3365 break;
3366 case 1:
3367 // gen_op_dmfc0_tracecontrol(); /* PDtrace support */
3368 rn = "TraceControl";
3369 // break;
3370 case 2:
3371 // gen_op_dmfc0_tracecontrol2(); /* PDtrace support */
3372 rn = "TraceControl2";
3373 // break;
3374 case 3:
3375 // gen_op_dmfc0_usertracedata(); /* PDtrace support */
3376 rn = "UserTraceData";
3377 // break;
3378 case 4:
3379 // gen_op_dmfc0_debug(); /* PDtrace support */
3380 rn = "TraceBPC";
3381 // break;
3382 default:
3383 goto die;
3385 break;
3386 case 24:
3387 switch (sel) {
3388 case 0:
3389 gen_op_dmfc0_depc(); /* EJTAG support */
3390 rn = "DEPC";
3391 break;
3392 default:
3393 goto die;
3395 break;
3396 case 25:
3397 switch (sel) {
3398 case 0:
3399 gen_op_mfc0_performance0();
3400 rn = "Performance0";
3401 break;
3402 case 1:
3403 // gen_op_dmfc0_performance1();
3404 rn = "Performance1";
3405 // break;
3406 case 2:
3407 // gen_op_dmfc0_performance2();
3408 rn = "Performance2";
3409 // break;
3410 case 3:
3411 // gen_op_dmfc0_performance3();
3412 rn = "Performance3";
3413 // break;
3414 case 4:
3415 // gen_op_dmfc0_performance4();
3416 rn = "Performance4";
3417 // break;
3418 case 5:
3419 // gen_op_dmfc0_performance5();
3420 rn = "Performance5";
3421 // break;
3422 case 6:
3423 // gen_op_dmfc0_performance6();
3424 rn = "Performance6";
3425 // break;
3426 case 7:
3427 // gen_op_dmfc0_performance7();
3428 rn = "Performance7";
3429 // break;
3430 default:
3431 goto die;
3433 break;
3434 case 26:
3435 rn = "ECC";
3436 break;
3437 case 27:
3438 switch (sel) {
3439 /* ignored */
3440 case 0 ... 3:
3441 rn = "CacheErr";
3442 break;
3443 default:
3444 goto die;
3446 break;
3447 case 28:
3448 switch (sel) {
3449 case 0:
3450 case 2:
3451 case 4:
3452 case 6:
3453 gen_op_mfc0_taglo();
3454 rn = "TagLo";
3455 break;
3456 case 1:
3457 case 3:
3458 case 5:
3459 case 7:
3460 gen_op_mfc0_datalo();
3461 rn = "DataLo";
3462 break;
3463 default:
3464 goto die;
3466 break;
3467 case 29:
3468 switch (sel) {
3469 case 0:
3470 case 2:
3471 case 4:
3472 case 6:
3473 gen_op_mfc0_taghi();
3474 rn = "TagHi";
3475 break;
3476 case 1:
3477 case 3:
3478 case 5:
3479 case 7:
3480 gen_op_mfc0_datahi();
3481 rn = "DataHi";
3482 break;
3483 default:
3484 goto die;
3486 break;
3487 case 30:
3488 switch (sel) {
3489 case 0:
3490 gen_op_dmfc0_errorepc();
3491 rn = "ErrorEPC";
3492 break;
3493 default:
3494 goto die;
3496 break;
3497 case 31:
3498 switch (sel) {
3499 case 0:
3500 gen_op_mfc0_desave(); /* EJTAG support */
3501 rn = "DESAVE";
3502 break;
3503 default:
3504 goto die;
3506 break;
3507 default:
3508 goto die;
3510 #if defined MIPS_DEBUG_DISAS
3511 if (loglevel & CPU_LOG_TB_IN_ASM) {
3512 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3513 rn, reg, sel);
3515 #endif
3516 return;
3518 die:
3519 #if defined MIPS_DEBUG_DISAS
3520 if (loglevel & CPU_LOG_TB_IN_ASM) {
3521 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3522 rn, reg, sel);
3524 #endif
3525 generate_exception(ctx, EXCP_RI);
3528 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
3530 const char *rn = "invalid";
3532 switch (reg) {
3533 case 0:
3534 switch (sel) {
3535 case 0:
3536 gen_op_mtc0_index();
3537 rn = "Index";
3538 break;
3539 case 1:
3540 // gen_op_mtc0_mvpcontrol(); /* MT ASE */
3541 rn = "MVPControl";
3542 // break;
3543 case 2:
3544 // gen_op_mtc0_mvpconf0(); /* MT ASE */
3545 rn = "MVPConf0";
3546 // break;
3547 case 3:
3548 // gen_op_mtc0_mvpconf1(); /* MT ASE */
3549 rn = "MVPConf1";
3550 // break;
3551 default:
3552 goto die;
3554 break;
3555 case 1:
3556 switch (sel) {
3557 case 0:
3558 /* ignored */
3559 rn = "Random";
3560 break;
3561 case 1:
3562 // gen_op_mtc0_vpecontrol(); /* MT ASE */
3563 rn = "VPEControl";
3564 // break;
3565 case 2:
3566 // gen_op_mtc0_vpeconf0(); /* MT ASE */
3567 rn = "VPEConf0";
3568 // break;
3569 case 3:
3570 // gen_op_mtc0_vpeconf1(); /* MT ASE */
3571 rn = "VPEConf1";
3572 // break;
3573 case 4:
3574 // gen_op_mtc0_YQMask(); /* MT ASE */
3575 rn = "YQMask";
3576 // break;
3577 case 5:
3578 // gen_op_mtc0_vpeschedule(); /* MT ASE */
3579 rn = "VPESchedule";
3580 // break;
3581 case 6:
3582 // gen_op_mtc0_vpeschefback(); /* MT ASE */
3583 rn = "VPEScheFBack";
3584 // break;
3585 case 7:
3586 // gen_op_mtc0_vpeopt(); /* MT ASE */
3587 rn = "VPEOpt";
3588 // break;
3589 default:
3590 goto die;
3592 break;
3593 case 2:
3594 switch (sel) {
3595 case 0:
3596 gen_op_mtc0_entrylo0();
3597 rn = "EntryLo0";
3598 break;
3599 case 1:
3600 // gen_op_mtc0_tcstatus(); /* MT ASE */
3601 rn = "TCStatus";
3602 // break;
3603 case 2:
3604 // gen_op_mtc0_tcbind(); /* MT ASE */
3605 rn = "TCBind";
3606 // break;
3607 case 3:
3608 // gen_op_mtc0_tcrestart(); /* MT ASE */
3609 rn = "TCRestart";
3610 // break;
3611 case 4:
3612 // gen_op_mtc0_tchalt(); /* MT ASE */
3613 rn = "TCHalt";
3614 // break;
3615 case 5:
3616 // gen_op_mtc0_tccontext(); /* MT ASE */
3617 rn = "TCContext";
3618 // break;
3619 case 6:
3620 // gen_op_mtc0_tcschedule(); /* MT ASE */
3621 rn = "TCSchedule";
3622 // break;
3623 case 7:
3624 // gen_op_mtc0_tcschefback(); /* MT ASE */
3625 rn = "TCScheFBack";
3626 // break;
3627 default:
3628 goto die;
3630 break;
3631 case 3:
3632 switch (sel) {
3633 case 0:
3634 gen_op_mtc0_entrylo1();
3635 rn = "EntryLo1";
3636 break;
3637 default:
3638 goto die;
3640 break;
3641 case 4:
3642 switch (sel) {
3643 case 0:
3644 gen_op_mtc0_context();
3645 rn = "Context";
3646 break;
3647 case 1:
3648 // gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
3649 rn = "ContextConfig";
3650 // break;
3651 default:
3652 goto die;
3654 break;
3655 case 5:
3656 switch (sel) {
3657 case 0:
3658 gen_op_mtc0_pagemask();
3659 rn = "PageMask";
3660 break;
3661 case 1:
3662 check_mips_r2(env, ctx);
3663 gen_op_mtc0_pagegrain();
3664 rn = "PageGrain";
3665 break;
3666 default:
3667 goto die;
3669 break;
3670 case 6:
3671 switch (sel) {
3672 case 0:
3673 gen_op_mtc0_wired();
3674 rn = "Wired";
3675 break;
3676 case 1:
3677 // gen_op_mtc0_srsconf0(); /* shadow registers */
3678 rn = "SRSConf0";
3679 // break;
3680 case 2:
3681 // gen_op_mtc0_srsconf1(); /* shadow registers */
3682 rn = "SRSConf1";
3683 // break;
3684 case 3:
3685 // gen_op_mtc0_srsconf2(); /* shadow registers */
3686 rn = "SRSConf2";
3687 // break;
3688 case 4:
3689 // gen_op_mtc0_srsconf3(); /* shadow registers */
3690 rn = "SRSConf3";
3691 // break;
3692 case 5:
3693 // gen_op_mtc0_srsconf4(); /* shadow registers */
3694 rn = "SRSConf4";
3695 // break;
3696 default:
3697 goto die;
3699 break;
3700 case 7:
3701 switch (sel) {
3702 case 0:
3703 check_mips_r2(env, ctx);
3704 gen_op_mtc0_hwrena();
3705 rn = "HWREna";
3706 break;
3707 default:
3708 goto die;
3710 break;
3711 case 8:
3712 /* ignored */
3713 rn = "BadVaddr";
3714 break;
3715 case 9:
3716 switch (sel) {
3717 case 0:
3718 gen_op_mtc0_count();
3719 rn = "Count";
3720 break;
3721 /* 6,7 are implementation dependent */
3722 default:
3723 goto die;
3725 /* Stop translation as we may have switched the execution mode */
3726 ctx->bstate = BS_STOP;
3727 break;
3728 case 10:
3729 switch (sel) {
3730 case 0:
3731 gen_op_mtc0_entryhi();
3732 rn = "EntryHi";
3733 break;
3734 default:
3735 goto die;
3737 break;
3738 case 11:
3739 switch (sel) {
3740 case 0:
3741 gen_op_mtc0_compare();
3742 rn = "Compare";
3743 break;
3744 /* 6,7 are implementation dependent */
3745 default:
3746 goto die;
3748 /* Stop translation as we may have switched the execution mode */
3749 ctx->bstate = BS_STOP;
3750 break;
3751 case 12:
3752 switch (sel) {
3753 case 0:
3754 gen_op_mtc0_status();
3755 /* BS_STOP isn't good enough here, hflags may have changed. */
3756 gen_save_pc(ctx->pc + 4);
3757 ctx->bstate = BS_EXCP;
3758 rn = "Status";
3759 break;
3760 case 1:
3761 check_mips_r2(env, ctx);
3762 gen_op_mtc0_intctl();
3763 /* Stop translation as we may have switched the execution mode */
3764 ctx->bstate = BS_STOP;
3765 rn = "IntCtl";
3766 break;
3767 case 2:
3768 check_mips_r2(env, ctx);
3769 gen_op_mtc0_srsctl();
3770 /* Stop translation as we may have switched the execution mode */
3771 ctx->bstate = BS_STOP;
3772 rn = "SRSCtl";
3773 break;
3774 case 3:
3775 check_mips_r2(env, ctx);
3776 gen_op_mtc0_srsmap();
3777 /* Stop translation as we may have switched the execution mode */
3778 ctx->bstate = BS_STOP;
3779 rn = "SRSMap";
3780 break;
3781 default:
3782 goto die;
3784 break;
3785 case 13:
3786 switch (sel) {
3787 case 0:
3788 gen_op_mtc0_cause();
3789 rn = "Cause";
3790 break;
3791 default:
3792 goto die;
3794 /* Stop translation as we may have switched the execution mode */
3795 ctx->bstate = BS_STOP;
3796 break;
3797 case 14:
3798 switch (sel) {
3799 case 0:
3800 gen_op_mtc0_epc();
3801 rn = "EPC";
3802 break;
3803 default:
3804 goto die;
3806 break;
3807 case 15:
3808 switch (sel) {
3809 case 0:
3810 /* ignored */
3811 rn = "PRid";
3812 break;
3813 case 1:
3814 check_mips_r2(env, ctx);
3815 gen_op_mtc0_ebase();
3816 rn = "EBase";
3817 break;
3818 default:
3819 goto die;
3821 break;
3822 case 16:
3823 switch (sel) {
3824 case 0:
3825 gen_op_mtc0_config0();
3826 rn = "Config";
3827 /* Stop translation as we may have switched the execution mode */
3828 ctx->bstate = BS_STOP;
3829 break;
3830 case 1:
3831 /* ignored */
3832 rn = "Config1";
3833 break;
3834 case 2:
3835 gen_op_mtc0_config2();
3836 rn = "Config2";
3837 /* Stop translation as we may have switched the execution mode */
3838 ctx->bstate = BS_STOP;
3839 break;
3840 case 3:
3841 /* ignored */
3842 rn = "Config3";
3843 break;
3844 /* 6,7 are implementation dependent */
3845 default:
3846 rn = "Invalid config selector";
3847 goto die;
3849 break;
3850 case 17:
3851 switch (sel) {
3852 case 0:
3853 /* ignored */
3854 rn = "LLAddr";
3855 break;
3856 default:
3857 goto die;
3859 break;
3860 case 18:
3861 switch (sel) {
3862 case 0 ... 7:
3863 gen_op_mtc0_watchlo(sel);
3864 rn = "WatchLo";
3865 break;
3866 default:
3867 goto die;
3869 break;
3870 case 19:
3871 switch (sel) {
3872 case 0 ... 7:
3873 gen_op_mtc0_watchhi(sel);
3874 rn = "WatchHi";
3875 break;
3876 default:
3877 goto die;
3879 break;
3880 case 20:
3881 switch (sel) {
3882 case 0:
3883 gen_op_mtc0_xcontext();
3884 rn = "XContext";
3885 break;
3886 default:
3887 goto die;
3889 break;
3890 case 21:
3891 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3892 switch (sel) {
3893 case 0:
3894 gen_op_mtc0_framemask();
3895 rn = "Framemask";
3896 break;
3897 default:
3898 goto die;
3900 break;
3901 case 22:
3902 /* ignored */
3903 rn = "Diagnostic"; /* implementation dependent */
3904 break;
3905 case 23:
3906 switch (sel) {
3907 case 0:
3908 gen_op_mtc0_debug(); /* EJTAG support */
3909 /* BS_STOP isn't good enough here, hflags may have changed. */
3910 gen_save_pc(ctx->pc + 4);
3911 ctx->bstate = BS_EXCP;
3912 rn = "Debug";
3913 break;
3914 case 1:
3915 // gen_op_mtc0_tracecontrol(); /* PDtrace support */
3916 /* Stop translation as we may have switched the execution mode */
3917 ctx->bstate = BS_STOP;
3918 rn = "TraceControl";
3919 // break;
3920 case 2:
3921 // gen_op_mtc0_tracecontrol2(); /* PDtrace support */
3922 /* Stop translation as we may have switched the execution mode */
3923 ctx->bstate = BS_STOP;
3924 rn = "TraceControl2";
3925 // break;
3926 case 3:
3927 // gen_op_mtc0_usertracedata(); /* PDtrace support */
3928 /* Stop translation as we may have switched the execution mode */
3929 ctx->bstate = BS_STOP;
3930 rn = "UserTraceData";
3931 // break;
3932 case 4:
3933 // gen_op_mtc0_debug(); /* PDtrace support */
3934 /* Stop translation as we may have switched the execution mode */
3935 ctx->bstate = BS_STOP;
3936 rn = "TraceBPC";
3937 // break;
3938 default:
3939 goto die;
3941 break;
3942 case 24:
3943 switch (sel) {
3944 case 0:
3945 gen_op_mtc0_depc(); /* EJTAG support */
3946 rn = "DEPC";
3947 break;
3948 default:
3949 goto die;
3951 break;
3952 case 25:
3953 switch (sel) {
3954 case 0:
3955 gen_op_mtc0_performance0();
3956 rn = "Performance0";
3957 break;
3958 case 1:
3959 // gen_op_mtc0_performance1();
3960 rn = "Performance1";
3961 // break;
3962 case 2:
3963 // gen_op_mtc0_performance2();
3964 rn = "Performance2";
3965 // break;
3966 case 3:
3967 // gen_op_mtc0_performance3();
3968 rn = "Performance3";
3969 // break;
3970 case 4:
3971 // gen_op_mtc0_performance4();
3972 rn = "Performance4";
3973 // break;
3974 case 5:
3975 // gen_op_mtc0_performance5();
3976 rn = "Performance5";
3977 // break;
3978 case 6:
3979 // gen_op_mtc0_performance6();
3980 rn = "Performance6";
3981 // break;
3982 case 7:
3983 // gen_op_mtc0_performance7();
3984 rn = "Performance7";
3985 // break;
3986 default:
3987 goto die;
3989 break;
3990 case 26:
3991 /* ignored */
3992 rn = "ECC";
3993 break;
3994 case 27:
3995 switch (sel) {
3996 case 0 ... 3:
3997 /* ignored */
3998 rn = "CacheErr";
3999 break;
4000 default:
4001 goto die;
4003 break;
4004 case 28:
4005 switch (sel) {
4006 case 0:
4007 case 2:
4008 case 4:
4009 case 6:
4010 gen_op_mtc0_taglo();
4011 rn = "TagLo";
4012 break;
4013 case 1:
4014 case 3:
4015 case 5:
4016 case 7:
4017 gen_op_mtc0_datalo();
4018 rn = "DataLo";
4019 break;
4020 default:
4021 goto die;
4023 break;
4024 case 29:
4025 switch (sel) {
4026 case 0:
4027 case 2:
4028 case 4:
4029 case 6:
4030 gen_op_mtc0_taghi();
4031 rn = "TagHi";
4032 break;
4033 case 1:
4034 case 3:
4035 case 5:
4036 case 7:
4037 gen_op_mtc0_datahi();
4038 rn = "DataHi";
4039 break;
4040 default:
4041 rn = "invalid sel";
4042 goto die;
4044 break;
4045 case 30:
4046 switch (sel) {
4047 case 0:
4048 gen_op_mtc0_errorepc();
4049 rn = "ErrorEPC";
4050 break;
4051 default:
4052 goto die;
4054 break;
4055 case 31:
4056 switch (sel) {
4057 case 0:
4058 gen_op_mtc0_desave(); /* EJTAG support */
4059 rn = "DESAVE";
4060 break;
4061 default:
4062 goto die;
4064 /* Stop translation as we may have switched the execution mode */
4065 ctx->bstate = BS_STOP;
4066 break;
4067 default:
4068 goto die;
4070 #if defined MIPS_DEBUG_DISAS
4071 if (loglevel & CPU_LOG_TB_IN_ASM) {
4072 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4073 rn, reg, sel);
4075 #endif
4076 return;
4078 die:
4079 #if defined MIPS_DEBUG_DISAS
4080 if (loglevel & CPU_LOG_TB_IN_ASM) {
4081 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4082 rn, reg, sel);
4084 #endif
4085 generate_exception(ctx, EXCP_RI);
4087 #endif /* TARGET_MIPS64 */
4089 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
4091 const char *opn = "ldst";
4093 switch (opc) {
4094 case OPC_MFC0:
4095 if (rt == 0) {
4096 /* Treat as NOP */
4097 return;
4099 gen_mfc0(env, ctx, rd, ctx->opcode & 0x7);
4100 gen_op_store_T0_gpr(rt);
4101 opn = "mfc0";
4102 break;
4103 case OPC_MTC0:
4104 GEN_LOAD_REG_TN(T0, rt);
4105 gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
4106 opn = "mtc0";
4107 break;
4108 #ifdef TARGET_MIPS64
4109 case OPC_DMFC0:
4110 if (!(ctx->hflags & MIPS_HFLAG_64))
4111 generate_exception(ctx, EXCP_RI);
4112 if (rt == 0) {
4113 /* Treat as NOP */
4114 return;
4116 gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7);
4117 gen_op_store_T0_gpr(rt);
4118 opn = "dmfc0";
4119 break;
4120 case OPC_DMTC0:
4121 if (!(ctx->hflags & MIPS_HFLAG_64))
4122 generate_exception(ctx, EXCP_RI);
4123 GEN_LOAD_REG_TN(T0, rt);
4124 gen_dmtc0(env,ctx, rd, ctx->opcode & 0x7);
4125 opn = "dmtc0";
4126 break;
4127 #endif
4128 case OPC_TLBWI:
4129 opn = "tlbwi";
4130 if (!env->do_tlbwi)
4131 goto die;
4132 gen_op_tlbwi();
4133 break;
4134 case OPC_TLBWR:
4135 opn = "tlbwr";
4136 if (!env->do_tlbwr)
4137 goto die;
4138 gen_op_tlbwr();
4139 break;
4140 case OPC_TLBP:
4141 opn = "tlbp";
4142 if (!env->do_tlbp)
4143 goto die;
4144 gen_op_tlbp();
4145 break;
4146 case OPC_TLBR:
4147 opn = "tlbr";
4148 if (!env->do_tlbr)
4149 goto die;
4150 gen_op_tlbr();
4151 break;
4152 case OPC_ERET:
4153 opn = "eret";
4154 gen_op_eret();
4155 ctx->bstate = BS_EXCP;
4156 break;
4157 case OPC_DERET:
4158 opn = "deret";
4159 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
4160 MIPS_INVAL(opn);
4161 generate_exception(ctx, EXCP_RI);
4162 } else {
4163 gen_op_deret();
4164 ctx->bstate = BS_EXCP;
4166 break;
4167 case OPC_WAIT:
4168 opn = "wait";
4169 /* If we get an exception, we want to restart at next instruction */
4170 ctx->pc += 4;
4171 save_cpu_state(ctx, 1);
4172 ctx->pc -= 4;
4173 gen_op_wait();
4174 ctx->bstate = BS_EXCP;
4175 break;
4176 default:
4177 die:
4178 MIPS_INVAL(opn);
4179 generate_exception(ctx, EXCP_RI);
4180 return;
4182 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
4185 /* CP1 Branches (before delay slot) */
4186 static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4187 int32_t cc, int32_t offset)
4189 target_ulong btarget;
4190 const char *opn = "cp1 cond branch";
4192 btarget = ctx->pc + 4 + offset;
4194 switch (op) {
4195 case OPC_BC1F:
4196 gen_op_bc1f(cc);
4197 opn = "bc1f";
4198 goto not_likely;
4199 case OPC_BC1FL:
4200 gen_op_bc1f(cc);
4201 opn = "bc1fl";
4202 goto likely;
4203 case OPC_BC1T:
4204 gen_op_bc1t(cc);
4205 opn = "bc1t";
4206 goto not_likely;
4207 case OPC_BC1TL:
4208 gen_op_bc1t(cc);
4209 opn = "bc1tl";
4210 likely:
4211 ctx->hflags |= MIPS_HFLAG_BL;
4212 gen_op_set_bcond();
4213 gen_op_save_bcond();
4214 break;
4215 case OPC_BC1FANY2:
4216 gen_op_bc1any2f(cc);
4217 opn = "bc1any2f";
4218 goto not_likely;
4219 case OPC_BC1TANY2:
4220 gen_op_bc1any2t(cc);
4221 opn = "bc1any2t";
4222 goto not_likely;
4223 case OPC_BC1FANY4:
4224 gen_op_bc1any4f(cc);
4225 opn = "bc1any4f";
4226 goto not_likely;
4227 case OPC_BC1TANY4:
4228 gen_op_bc1any4t(cc);
4229 opn = "bc1any4t";
4230 not_likely:
4231 ctx->hflags |= MIPS_HFLAG_BC;
4232 gen_op_set_bcond();
4233 break;
4234 default:
4235 MIPS_INVAL(opn);
4236 generate_exception (ctx, EXCP_RI);
4237 return;
4239 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
4240 ctx->hflags, btarget);
4241 ctx->btarget = btarget;
4244 /* Coprocessor 1 (FPU) */
4246 #define FOP(func, fmt) (((fmt) << 21) | (func))
4248 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4250 const char *opn = "cp1 move";
4252 switch (opc) {
4253 case OPC_MFC1:
4254 GEN_LOAD_FREG_FTN(WT0, fs);
4255 gen_op_mfc1();
4256 GEN_STORE_TN_REG(rt, T0);
4257 opn = "mfc1";
4258 break;
4259 case OPC_MTC1:
4260 GEN_LOAD_REG_TN(T0, rt);
4261 gen_op_mtc1();
4262 GEN_STORE_FTN_FREG(fs, WT0);
4263 opn = "mtc1";
4264 break;
4265 case OPC_CFC1:
4266 GEN_LOAD_IMM_TN(T1, fs);
4267 gen_op_cfc1();
4268 GEN_STORE_TN_REG(rt, T0);
4269 opn = "cfc1";
4270 break;
4271 case OPC_CTC1:
4272 GEN_LOAD_IMM_TN(T1, fs);
4273 GEN_LOAD_REG_TN(T0, rt);
4274 gen_op_ctc1();
4275 opn = "ctc1";
4276 break;
4277 case OPC_DMFC1:
4278 GEN_LOAD_FREG_FTN(DT0, fs);
4279 gen_op_dmfc1();
4280 GEN_STORE_TN_REG(rt, T0);
4281 opn = "dmfc1";
4282 break;
4283 case OPC_DMTC1:
4284 GEN_LOAD_REG_TN(T0, rt);
4285 gen_op_dmtc1();
4286 GEN_STORE_FTN_FREG(fs, DT0);
4287 opn = "dmtc1";
4288 break;
4289 case OPC_MFHC1:
4290 GEN_LOAD_FREG_FTN(WTH0, fs);
4291 gen_op_mfhc1();
4292 GEN_STORE_TN_REG(rt, T0);
4293 opn = "mfhc1";
4294 break;
4295 case OPC_MTHC1:
4296 GEN_LOAD_REG_TN(T0, rt);
4297 gen_op_mthc1();
4298 GEN_STORE_FTN_FREG(fs, WTH0);
4299 opn = "mthc1";
4300 break;
4301 default:
4302 MIPS_INVAL(opn);
4303 generate_exception (ctx, EXCP_RI);
4304 return;
4306 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
4309 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4311 uint32_t ccbit;
4313 GEN_LOAD_REG_TN(T0, rd);
4314 GEN_LOAD_REG_TN(T1, rs);
4315 if (cc) {
4316 ccbit = 1 << (24 + cc);
4317 } else
4318 ccbit = 1 << 23;
4319 if (!tf)
4320 gen_op_movf(ccbit);
4321 else
4322 gen_op_movt(ccbit);
4323 GEN_STORE_TN_REG(rd, T0);
4326 #define GEN_MOVCF(fmt) \
4327 static void glue(gen_movcf_, fmt) (DisasContext *ctx, int cc, int tf) \
4329 uint32_t ccbit; \
4331 if (cc) { \
4332 ccbit = 1 << (24 + cc); \
4333 } else \
4334 ccbit = 1 << 23; \
4335 if (!tf) \
4336 glue(gen_op_float_movf_, fmt)(ccbit); \
4337 else \
4338 glue(gen_op_float_movt_, fmt)(ccbit); \
4340 GEN_MOVCF(d);
4341 GEN_MOVCF(s);
4342 GEN_MOVCF(ps);
4343 #undef GEN_MOVCF
4345 static void gen_farith (DisasContext *ctx, uint32_t op1,
4346 int ft, int fs, int fd, int cc)
4348 const char *opn = "farith";
4349 const char *condnames[] = {
4350 "c.f",
4351 "c.un",
4352 "c.eq",
4353 "c.ueq",
4354 "c.olt",
4355 "c.ult",
4356 "c.ole",
4357 "c.ule",
4358 "c.sf",
4359 "c.ngle",
4360 "c.seq",
4361 "c.ngl",
4362 "c.lt",
4363 "c.nge",
4364 "c.le",
4365 "c.ngt",
4367 const char *condnames_abs[] = {
4368 "cabs.f",
4369 "cabs.un",
4370 "cabs.eq",
4371 "cabs.ueq",
4372 "cabs.olt",
4373 "cabs.ult",
4374 "cabs.ole",
4375 "cabs.ule",
4376 "cabs.sf",
4377 "cabs.ngle",
4378 "cabs.seq",
4379 "cabs.ngl",
4380 "cabs.lt",
4381 "cabs.nge",
4382 "cabs.le",
4383 "cabs.ngt",
4385 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
4386 uint32_t func = ctx->opcode & 0x3f;
4388 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
4389 case FOP(0, 16):
4390 GEN_LOAD_FREG_FTN(WT0, fs);
4391 GEN_LOAD_FREG_FTN(WT1, ft);
4392 gen_op_float_add_s();
4393 GEN_STORE_FTN_FREG(fd, WT2);
4394 opn = "add.s";
4395 optype = BINOP;
4396 break;
4397 case FOP(1, 16):
4398 GEN_LOAD_FREG_FTN(WT0, fs);
4399 GEN_LOAD_FREG_FTN(WT1, ft);
4400 gen_op_float_sub_s();
4401 GEN_STORE_FTN_FREG(fd, WT2);
4402 opn = "sub.s";
4403 optype = BINOP;
4404 break;
4405 case FOP(2, 16):
4406 GEN_LOAD_FREG_FTN(WT0, fs);
4407 GEN_LOAD_FREG_FTN(WT1, ft);
4408 gen_op_float_mul_s();
4409 GEN_STORE_FTN_FREG(fd, WT2);
4410 opn = "mul.s";
4411 optype = BINOP;
4412 break;
4413 case FOP(3, 16):
4414 GEN_LOAD_FREG_FTN(WT0, fs);
4415 GEN_LOAD_FREG_FTN(WT1, ft);
4416 gen_op_float_div_s();
4417 GEN_STORE_FTN_FREG(fd, WT2);
4418 opn = "div.s";
4419 optype = BINOP;
4420 break;
4421 case FOP(4, 16):
4422 GEN_LOAD_FREG_FTN(WT0, fs);
4423 gen_op_float_sqrt_s();
4424 GEN_STORE_FTN_FREG(fd, WT2);
4425 opn = "sqrt.s";
4426 break;
4427 case FOP(5, 16):
4428 GEN_LOAD_FREG_FTN(WT0, fs);
4429 gen_op_float_abs_s();
4430 GEN_STORE_FTN_FREG(fd, WT2);
4431 opn = "abs.s";
4432 break;
4433 case FOP(6, 16):
4434 GEN_LOAD_FREG_FTN(WT0, fs);
4435 gen_op_float_mov_s();
4436 GEN_STORE_FTN_FREG(fd, WT2);
4437 opn = "mov.s";
4438 break;
4439 case FOP(7, 16):
4440 GEN_LOAD_FREG_FTN(WT0, fs);
4441 gen_op_float_chs_s();
4442 GEN_STORE_FTN_FREG(fd, WT2);
4443 opn = "neg.s";
4444 break;
4445 case FOP(8, 16):
4446 check_cp1_64bitmode(ctx);
4447 GEN_LOAD_FREG_FTN(WT0, fs);
4448 gen_op_float_roundl_s();
4449 GEN_STORE_FTN_FREG(fd, DT2);
4450 opn = "round.l.s";
4451 break;
4452 case FOP(9, 16):
4453 check_cp1_64bitmode(ctx);
4454 GEN_LOAD_FREG_FTN(WT0, fs);
4455 gen_op_float_truncl_s();
4456 GEN_STORE_FTN_FREG(fd, DT2);
4457 opn = "trunc.l.s";
4458 break;
4459 case FOP(10, 16):
4460 check_cp1_64bitmode(ctx);
4461 GEN_LOAD_FREG_FTN(WT0, fs);
4462 gen_op_float_ceill_s();
4463 GEN_STORE_FTN_FREG(fd, DT2);
4464 opn = "ceil.l.s";
4465 break;
4466 case FOP(11, 16):
4467 check_cp1_64bitmode(ctx);
4468 GEN_LOAD_FREG_FTN(WT0, fs);
4469 gen_op_float_floorl_s();
4470 GEN_STORE_FTN_FREG(fd, DT2);
4471 opn = "floor.l.s";
4472 break;
4473 case FOP(12, 16):
4474 GEN_LOAD_FREG_FTN(WT0, fs);
4475 gen_op_float_roundw_s();
4476 GEN_STORE_FTN_FREG(fd, WT2);
4477 opn = "round.w.s";
4478 break;
4479 case FOP(13, 16):
4480 GEN_LOAD_FREG_FTN(WT0, fs);
4481 gen_op_float_truncw_s();
4482 GEN_STORE_FTN_FREG(fd, WT2);
4483 opn = "trunc.w.s";
4484 break;
4485 case FOP(14, 16):
4486 GEN_LOAD_FREG_FTN(WT0, fs);
4487 gen_op_float_ceilw_s();
4488 GEN_STORE_FTN_FREG(fd, WT2);
4489 opn = "ceil.w.s";
4490 break;
4491 case FOP(15, 16):
4492 GEN_LOAD_FREG_FTN(WT0, fs);
4493 gen_op_float_floorw_s();
4494 GEN_STORE_FTN_FREG(fd, WT2);
4495 opn = "floor.w.s";
4496 break;
4497 case FOP(17, 16):
4498 GEN_LOAD_REG_TN(T0, ft);
4499 GEN_LOAD_FREG_FTN(WT0, fs);
4500 GEN_LOAD_FREG_FTN(WT2, fd);
4501 gen_movcf_s(ctx, (ft >> 2) & 0x7, ft & 0x1);
4502 GEN_STORE_FTN_FREG(fd, WT2);
4503 opn = "movcf.s";
4504 break;
4505 case FOP(18, 16):
4506 GEN_LOAD_REG_TN(T0, ft);
4507 GEN_LOAD_FREG_FTN(WT0, fs);
4508 GEN_LOAD_FREG_FTN(WT2, fd);
4509 gen_op_float_movz_s();
4510 GEN_STORE_FTN_FREG(fd, WT2);
4511 opn = "movz.s";
4512 break;
4513 case FOP(19, 16):
4514 GEN_LOAD_REG_TN(T0, ft);
4515 GEN_LOAD_FREG_FTN(WT0, fs);
4516 GEN_LOAD_FREG_FTN(WT2, fd);
4517 gen_op_float_movn_s();
4518 GEN_STORE_FTN_FREG(fd, WT2);
4519 opn = "movn.s";
4520 break;
4521 case FOP(21, 16):
4522 GEN_LOAD_FREG_FTN(WT0, fs);
4523 gen_op_float_recip_s();
4524 GEN_STORE_FTN_FREG(fd, WT2);
4525 opn = "recip.s";
4526 break;
4527 case FOP(22, 16):
4528 GEN_LOAD_FREG_FTN(WT0, fs);
4529 gen_op_float_rsqrt_s();
4530 GEN_STORE_FTN_FREG(fd, WT2);
4531 opn = "rsqrt.s";
4532 break;
4533 case FOP(28, 16):
4534 check_cp1_64bitmode(ctx);
4535 GEN_LOAD_FREG_FTN(WT0, fs);
4536 GEN_LOAD_FREG_FTN(WT2, fd);
4537 gen_op_float_recip2_s();
4538 GEN_STORE_FTN_FREG(fd, WT2);
4539 opn = "recip2.s";
4540 break;
4541 case FOP(29, 16):
4542 check_cp1_64bitmode(ctx);
4543 GEN_LOAD_FREG_FTN(WT0, fs);
4544 gen_op_float_recip1_s();
4545 GEN_STORE_FTN_FREG(fd, WT2);
4546 opn = "recip1.s";
4547 break;
4548 case FOP(30, 16):
4549 check_cp1_64bitmode(ctx);
4550 GEN_LOAD_FREG_FTN(WT0, fs);
4551 gen_op_float_rsqrt1_s();
4552 GEN_STORE_FTN_FREG(fd, WT2);
4553 opn = "rsqrt1.s";
4554 break;
4555 case FOP(31, 16):
4556 check_cp1_64bitmode(ctx);
4557 GEN_LOAD_FREG_FTN(WT0, fs);
4558 GEN_LOAD_FREG_FTN(WT2, ft);
4559 gen_op_float_rsqrt2_s();
4560 GEN_STORE_FTN_FREG(fd, WT2);
4561 opn = "rsqrt2.s";
4562 break;
4563 case FOP(33, 16):
4564 check_cp1_registers(ctx, fd);
4565 GEN_LOAD_FREG_FTN(WT0, fs);
4566 gen_op_float_cvtd_s();
4567 GEN_STORE_FTN_FREG(fd, DT2);
4568 opn = "cvt.d.s";
4569 break;
4570 case FOP(36, 16):
4571 GEN_LOAD_FREG_FTN(WT0, fs);
4572 gen_op_float_cvtw_s();
4573 GEN_STORE_FTN_FREG(fd, WT2);
4574 opn = "cvt.w.s";
4575 break;
4576 case FOP(37, 16):
4577 check_cp1_64bitmode(ctx);
4578 GEN_LOAD_FREG_FTN(WT0, fs);
4579 gen_op_float_cvtl_s();
4580 GEN_STORE_FTN_FREG(fd, DT2);
4581 opn = "cvt.l.s";
4582 break;
4583 case FOP(38, 16):
4584 check_cp1_64bitmode(ctx);
4585 GEN_LOAD_FREG_FTN(WT1, fs);
4586 GEN_LOAD_FREG_FTN(WT0, ft);
4587 gen_op_float_cvtps_s();
4588 GEN_STORE_FTN_FREG(fd, DT2);
4589 opn = "cvt.ps.s";
4590 break;
4591 case FOP(48, 16):
4592 case FOP(49, 16):
4593 case FOP(50, 16):
4594 case FOP(51, 16):
4595 case FOP(52, 16):
4596 case FOP(53, 16):
4597 case FOP(54, 16):
4598 case FOP(55, 16):
4599 case FOP(56, 16):
4600 case FOP(57, 16):
4601 case FOP(58, 16):
4602 case FOP(59, 16):
4603 case FOP(60, 16):
4604 case FOP(61, 16):
4605 case FOP(62, 16):
4606 case FOP(63, 16):
4607 GEN_LOAD_FREG_FTN(WT0, fs);
4608 GEN_LOAD_FREG_FTN(WT1, ft);
4609 if (ctx->opcode & (1 << 6)) {
4610 check_cp1_64bitmode(ctx);
4611 gen_cmpabs_s(func-48, cc);
4612 opn = condnames_abs[func-48];
4613 } else {
4614 gen_cmp_s(func-48, cc);
4615 opn = condnames[func-48];
4617 break;
4618 case FOP(0, 17):
4619 check_cp1_registers(ctx, fs | ft | fd);
4620 GEN_LOAD_FREG_FTN(DT0, fs);
4621 GEN_LOAD_FREG_FTN(DT1, ft);
4622 gen_op_float_add_d();
4623 GEN_STORE_FTN_FREG(fd, DT2);
4624 opn = "add.d";
4625 optype = BINOP;
4626 break;
4627 case FOP(1, 17):
4628 check_cp1_registers(ctx, fs | ft | fd);
4629 GEN_LOAD_FREG_FTN(DT0, fs);
4630 GEN_LOAD_FREG_FTN(DT1, ft);
4631 gen_op_float_sub_d();
4632 GEN_STORE_FTN_FREG(fd, DT2);
4633 opn = "sub.d";
4634 optype = BINOP;
4635 break;
4636 case FOP(2, 17):
4637 check_cp1_registers(ctx, fs | ft | fd);
4638 GEN_LOAD_FREG_FTN(DT0, fs);
4639 GEN_LOAD_FREG_FTN(DT1, ft);
4640 gen_op_float_mul_d();
4641 GEN_STORE_FTN_FREG(fd, DT2);
4642 opn = "mul.d";
4643 optype = BINOP;
4644 break;
4645 case FOP(3, 17):
4646 check_cp1_registers(ctx, fs | ft | fd);
4647 GEN_LOAD_FREG_FTN(DT0, fs);
4648 GEN_LOAD_FREG_FTN(DT1, ft);
4649 gen_op_float_div_d();
4650 GEN_STORE_FTN_FREG(fd, DT2);
4651 opn = "div.d";
4652 optype = BINOP;
4653 break;
4654 case FOP(4, 17):
4655 check_cp1_registers(ctx, fs | fd);
4656 GEN_LOAD_FREG_FTN(DT0, fs);
4657 gen_op_float_sqrt_d();
4658 GEN_STORE_FTN_FREG(fd, DT2);
4659 opn = "sqrt.d";
4660 break;
4661 case FOP(5, 17):
4662 check_cp1_registers(ctx, fs | fd);
4663 GEN_LOAD_FREG_FTN(DT0, fs);
4664 gen_op_float_abs_d();
4665 GEN_STORE_FTN_FREG(fd, DT2);
4666 opn = "abs.d";
4667 break;
4668 case FOP(6, 17):
4669 check_cp1_registers(ctx, fs | fd);
4670 GEN_LOAD_FREG_FTN(DT0, fs);
4671 gen_op_float_mov_d();
4672 GEN_STORE_FTN_FREG(fd, DT2);
4673 opn = "mov.d";
4674 break;
4675 case FOP(7, 17):
4676 check_cp1_registers(ctx, fs | fd);
4677 GEN_LOAD_FREG_FTN(DT0, fs);
4678 gen_op_float_chs_d();
4679 GEN_STORE_FTN_FREG(fd, DT2);
4680 opn = "neg.d";
4681 break;
4682 case FOP(8, 17):
4683 check_cp1_64bitmode(ctx);
4684 GEN_LOAD_FREG_FTN(DT0, fs);
4685 gen_op_float_roundl_d();
4686 GEN_STORE_FTN_FREG(fd, DT2);
4687 opn = "round.l.d";
4688 break;
4689 case FOP(9, 17):
4690 check_cp1_64bitmode(ctx);
4691 GEN_LOAD_FREG_FTN(DT0, fs);
4692 gen_op_float_truncl_d();
4693 GEN_STORE_FTN_FREG(fd, DT2);
4694 opn = "trunc.l.d";
4695 break;
4696 case FOP(10, 17):
4697 check_cp1_64bitmode(ctx);
4698 GEN_LOAD_FREG_FTN(DT0, fs);
4699 gen_op_float_ceill_d();
4700 GEN_STORE_FTN_FREG(fd, DT2);
4701 opn = "ceil.l.d";
4702 break;
4703 case FOP(11, 17):
4704 check_cp1_64bitmode(ctx);
4705 GEN_LOAD_FREG_FTN(DT0, fs);
4706 gen_op_float_floorl_d();
4707 GEN_STORE_FTN_FREG(fd, DT2);
4708 opn = "floor.l.d";
4709 break;
4710 case FOP(12, 17):
4711 check_cp1_registers(ctx, fs);
4712 GEN_LOAD_FREG_FTN(DT0, fs);
4713 gen_op_float_roundw_d();
4714 GEN_STORE_FTN_FREG(fd, WT2);
4715 opn = "round.w.d";
4716 break;
4717 case FOP(13, 17):
4718 check_cp1_registers(ctx, fs);
4719 GEN_LOAD_FREG_FTN(DT0, fs);
4720 gen_op_float_truncw_d();
4721 GEN_STORE_FTN_FREG(fd, WT2);
4722 opn = "trunc.w.d";
4723 break;
4724 case FOP(14, 17):
4725 check_cp1_registers(ctx, fs);
4726 GEN_LOAD_FREG_FTN(DT0, fs);
4727 gen_op_float_ceilw_d();
4728 GEN_STORE_FTN_FREG(fd, WT2);
4729 opn = "ceil.w.d";
4730 break;
4731 case FOP(15, 17):
4732 check_cp1_registers(ctx, fs);
4733 GEN_LOAD_FREG_FTN(DT0, fs);
4734 gen_op_float_floorw_d();
4735 GEN_STORE_FTN_FREG(fd, WT2);
4736 opn = "floor.w.d";
4737 break;
4738 case FOP(17, 17):
4739 GEN_LOAD_REG_TN(T0, ft);
4740 GEN_LOAD_FREG_FTN(DT0, fs);
4741 GEN_LOAD_FREG_FTN(DT2, fd);
4742 gen_movcf_d(ctx, (ft >> 2) & 0x7, ft & 0x1);
4743 GEN_STORE_FTN_FREG(fd, DT2);
4744 opn = "movcf.d";
4745 break;
4746 case FOP(18, 17):
4747 GEN_LOAD_REG_TN(T0, ft);
4748 GEN_LOAD_FREG_FTN(DT0, fs);
4749 GEN_LOAD_FREG_FTN(DT2, fd);
4750 gen_op_float_movz_d();
4751 GEN_STORE_FTN_FREG(fd, DT2);
4752 opn = "movz.d";
4753 break;
4754 case FOP(19, 17):
4755 GEN_LOAD_REG_TN(T0, ft);
4756 GEN_LOAD_FREG_FTN(DT0, fs);
4757 GEN_LOAD_FREG_FTN(DT2, fd);
4758 gen_op_float_movn_d();
4759 GEN_STORE_FTN_FREG(fd, DT2);
4760 opn = "movn.d";
4761 break;
4762 case FOP(21, 17):
4763 check_cp1_registers(ctx, fs | fd);
4764 GEN_LOAD_FREG_FTN(DT0, fs);
4765 gen_op_float_recip_d();
4766 GEN_STORE_FTN_FREG(fd, DT2);
4767 opn = "recip.d";
4768 break;
4769 case FOP(22, 17):
4770 check_cp1_registers(ctx, fs | fd);
4771 GEN_LOAD_FREG_FTN(DT0, fs);
4772 gen_op_float_rsqrt_d();
4773 GEN_STORE_FTN_FREG(fd, DT2);
4774 opn = "rsqrt.d";
4775 break;
4776 case FOP(28, 17):
4777 check_cp1_64bitmode(ctx);
4778 GEN_LOAD_FREG_FTN(DT0, fs);
4779 GEN_LOAD_FREG_FTN(DT2, ft);
4780 gen_op_float_recip2_d();
4781 GEN_STORE_FTN_FREG(fd, DT2);
4782 opn = "recip2.d";
4783 break;
4784 case FOP(29, 17):
4785 check_cp1_64bitmode(ctx);
4786 GEN_LOAD_FREG_FTN(DT0, fs);
4787 gen_op_float_recip1_d();
4788 GEN_STORE_FTN_FREG(fd, DT2);
4789 opn = "recip1.d";
4790 break;
4791 case FOP(30, 17):
4792 check_cp1_64bitmode(ctx);
4793 GEN_LOAD_FREG_FTN(DT0, fs);
4794 gen_op_float_rsqrt1_d();
4795 GEN_STORE_FTN_FREG(fd, DT2);
4796 opn = "rsqrt1.d";
4797 break;
4798 case FOP(31, 17):
4799 check_cp1_64bitmode(ctx);
4800 GEN_LOAD_FREG_FTN(DT0, fs);
4801 GEN_LOAD_FREG_FTN(DT2, ft);
4802 gen_op_float_rsqrt2_d();
4803 GEN_STORE_FTN_FREG(fd, DT2);
4804 opn = "rsqrt2.d";
4805 break;
4806 case FOP(48, 17):
4807 case FOP(49, 17):
4808 case FOP(50, 17):
4809 case FOP(51, 17):
4810 case FOP(52, 17):
4811 case FOP(53, 17):
4812 case FOP(54, 17):
4813 case FOP(55, 17):
4814 case FOP(56, 17):
4815 case FOP(57, 17):
4816 case FOP(58, 17):
4817 case FOP(59, 17):
4818 case FOP(60, 17):
4819 case FOP(61, 17):
4820 case FOP(62, 17):
4821 case FOP(63, 17):
4822 GEN_LOAD_FREG_FTN(DT0, fs);
4823 GEN_LOAD_FREG_FTN(DT1, ft);
4824 if (ctx->opcode & (1 << 6)) {
4825 check_cp1_64bitmode(ctx);
4826 gen_cmpabs_d(func-48, cc);
4827 opn = condnames_abs[func-48];
4828 } else {
4829 check_cp1_registers(ctx, fs | ft);
4830 gen_cmp_d(func-48, cc);
4831 opn = condnames[func-48];
4833 break;
4834 case FOP(32, 17):
4835 check_cp1_registers(ctx, fs);
4836 GEN_LOAD_FREG_FTN(DT0, fs);
4837 gen_op_float_cvts_d();
4838 GEN_STORE_FTN_FREG(fd, WT2);
4839 opn = "cvt.s.d";
4840 break;
4841 case FOP(36, 17):
4842 check_cp1_registers(ctx, fs);
4843 GEN_LOAD_FREG_FTN(DT0, fs);
4844 gen_op_float_cvtw_d();
4845 GEN_STORE_FTN_FREG(fd, WT2);
4846 opn = "cvt.w.d";
4847 break;
4848 case FOP(37, 17):
4849 check_cp1_64bitmode(ctx);
4850 GEN_LOAD_FREG_FTN(DT0, fs);
4851 gen_op_float_cvtl_d();
4852 GEN_STORE_FTN_FREG(fd, DT2);
4853 opn = "cvt.l.d";
4854 break;
4855 case FOP(32, 20):
4856 GEN_LOAD_FREG_FTN(WT0, fs);
4857 gen_op_float_cvts_w();
4858 GEN_STORE_FTN_FREG(fd, WT2);
4859 opn = "cvt.s.w";
4860 break;
4861 case FOP(33, 20):
4862 check_cp1_registers(ctx, fd);
4863 GEN_LOAD_FREG_FTN(WT0, fs);
4864 gen_op_float_cvtd_w();
4865 GEN_STORE_FTN_FREG(fd, DT2);
4866 opn = "cvt.d.w";
4867 break;
4868 case FOP(32, 21):
4869 check_cp1_64bitmode(ctx);
4870 GEN_LOAD_FREG_FTN(DT0, fs);
4871 gen_op_float_cvts_l();
4872 GEN_STORE_FTN_FREG(fd, WT2);
4873 opn = "cvt.s.l";
4874 break;
4875 case FOP(33, 21):
4876 check_cp1_64bitmode(ctx);
4877 GEN_LOAD_FREG_FTN(DT0, fs);
4878 gen_op_float_cvtd_l();
4879 GEN_STORE_FTN_FREG(fd, DT2);
4880 opn = "cvt.d.l";
4881 break;
4882 case FOP(38, 20):
4883 case FOP(38, 21):
4884 check_cp1_64bitmode(ctx);
4885 GEN_LOAD_FREG_FTN(WT0, fs);
4886 GEN_LOAD_FREG_FTN(WTH0, fs);
4887 gen_op_float_cvtps_pw();
4888 GEN_STORE_FTN_FREG(fd, WT2);
4889 GEN_STORE_FTN_FREG(fd, WTH2);
4890 opn = "cvt.ps.pw";
4891 break;
4892 case FOP(0, 22):
4893 check_cp1_64bitmode(ctx);
4894 GEN_LOAD_FREG_FTN(WT0, fs);
4895 GEN_LOAD_FREG_FTN(WTH0, fs);
4896 GEN_LOAD_FREG_FTN(WT1, ft);
4897 GEN_LOAD_FREG_FTN(WTH1, ft);
4898 gen_op_float_add_ps();
4899 GEN_STORE_FTN_FREG(fd, WT2);
4900 GEN_STORE_FTN_FREG(fd, WTH2);
4901 opn = "add.ps";
4902 break;
4903 case FOP(1, 22):
4904 check_cp1_64bitmode(ctx);
4905 GEN_LOAD_FREG_FTN(WT0, fs);
4906 GEN_LOAD_FREG_FTN(WTH0, fs);
4907 GEN_LOAD_FREG_FTN(WT1, ft);
4908 GEN_LOAD_FREG_FTN(WTH1, ft);
4909 gen_op_float_sub_ps();
4910 GEN_STORE_FTN_FREG(fd, WT2);
4911 GEN_STORE_FTN_FREG(fd, WTH2);
4912 opn = "sub.ps";
4913 break;
4914 case FOP(2, 22):
4915 check_cp1_64bitmode(ctx);
4916 GEN_LOAD_FREG_FTN(WT0, fs);
4917 GEN_LOAD_FREG_FTN(WTH0, fs);
4918 GEN_LOAD_FREG_FTN(WT1, ft);
4919 GEN_LOAD_FREG_FTN(WTH1, ft);
4920 gen_op_float_mul_ps();
4921 GEN_STORE_FTN_FREG(fd, WT2);
4922 GEN_STORE_FTN_FREG(fd, WTH2);
4923 opn = "mul.ps";
4924 break;
4925 case FOP(5, 22):
4926 check_cp1_64bitmode(ctx);
4927 GEN_LOAD_FREG_FTN(WT0, fs);
4928 GEN_LOAD_FREG_FTN(WTH0, fs);
4929 gen_op_float_abs_ps();
4930 GEN_STORE_FTN_FREG(fd, WT2);
4931 GEN_STORE_FTN_FREG(fd, WTH2);
4932 opn = "abs.ps";
4933 break;
4934 case FOP(6, 22):
4935 check_cp1_64bitmode(ctx);
4936 GEN_LOAD_FREG_FTN(WT0, fs);
4937 GEN_LOAD_FREG_FTN(WTH0, fs);
4938 gen_op_float_mov_ps();
4939 GEN_STORE_FTN_FREG(fd, WT2);
4940 GEN_STORE_FTN_FREG(fd, WTH2);
4941 opn = "mov.ps";
4942 break;
4943 case FOP(7, 22):
4944 check_cp1_64bitmode(ctx);
4945 GEN_LOAD_FREG_FTN(WT0, fs);
4946 GEN_LOAD_FREG_FTN(WTH0, fs);
4947 gen_op_float_chs_ps();
4948 GEN_STORE_FTN_FREG(fd, WT2);
4949 GEN_STORE_FTN_FREG(fd, WTH2);
4950 opn = "neg.ps";
4951 break;
4952 case FOP(17, 22):
4953 check_cp1_64bitmode(ctx);
4954 GEN_LOAD_REG_TN(T0, ft);
4955 GEN_LOAD_FREG_FTN(WT0, fs);
4956 GEN_LOAD_FREG_FTN(WTH0, fs);
4957 GEN_LOAD_FREG_FTN(WT2, fd);
4958 GEN_LOAD_FREG_FTN(WTH2, fd);
4959 gen_movcf_ps(ctx, (ft >> 2) & 0x7, ft & 0x1);
4960 GEN_STORE_FTN_FREG(fd, WT2);
4961 GEN_STORE_FTN_FREG(fd, WTH2);
4962 opn = "movcf.ps";
4963 break;
4964 case FOP(18, 22):
4965 check_cp1_64bitmode(ctx);
4966 GEN_LOAD_REG_TN(T0, ft);
4967 GEN_LOAD_FREG_FTN(WT0, fs);
4968 GEN_LOAD_FREG_FTN(WTH0, fs);
4969 GEN_LOAD_FREG_FTN(WT2, fd);
4970 GEN_LOAD_FREG_FTN(WTH2, fd);
4971 gen_op_float_movz_ps();
4972 GEN_STORE_FTN_FREG(fd, WT2);
4973 GEN_STORE_FTN_FREG(fd, WTH2);
4974 opn = "movz.ps";
4975 break;
4976 case FOP(19, 22):
4977 check_cp1_64bitmode(ctx);
4978 GEN_LOAD_REG_TN(T0, ft);
4979 GEN_LOAD_FREG_FTN(WT0, fs);
4980 GEN_LOAD_FREG_FTN(WTH0, fs);
4981 GEN_LOAD_FREG_FTN(WT2, fd);
4982 GEN_LOAD_FREG_FTN(WTH2, fd);
4983 gen_op_float_movn_ps();
4984 GEN_STORE_FTN_FREG(fd, WT2);
4985 GEN_STORE_FTN_FREG(fd, WTH2);
4986 opn = "movn.ps";
4987 break;
4988 case FOP(24, 22):
4989 check_cp1_64bitmode(ctx);
4990 GEN_LOAD_FREG_FTN(WT0, ft);
4991 GEN_LOAD_FREG_FTN(WTH0, ft);
4992 GEN_LOAD_FREG_FTN(WT1, fs);
4993 GEN_LOAD_FREG_FTN(WTH1, fs);
4994 gen_op_float_addr_ps();
4995 GEN_STORE_FTN_FREG(fd, WT2);
4996 GEN_STORE_FTN_FREG(fd, WTH2);
4997 opn = "addr.ps";
4998 break;
4999 case FOP(26, 22):
5000 check_cp1_64bitmode(ctx);
5001 GEN_LOAD_FREG_FTN(WT0, ft);
5002 GEN_LOAD_FREG_FTN(WTH0, ft);
5003 GEN_LOAD_FREG_FTN(WT1, fs);
5004 GEN_LOAD_FREG_FTN(WTH1, fs);
5005 gen_op_float_mulr_ps();
5006 GEN_STORE_FTN_FREG(fd, WT2);
5007 GEN_STORE_FTN_FREG(fd, WTH2);
5008 opn = "mulr.ps";
5009 break;
5010 case FOP(28, 22):
5011 check_cp1_64bitmode(ctx);
5012 GEN_LOAD_FREG_FTN(WT0, fs);
5013 GEN_LOAD_FREG_FTN(WTH0, fs);
5014 GEN_LOAD_FREG_FTN(WT2, fd);
5015 GEN_LOAD_FREG_FTN(WTH2, fd);
5016 gen_op_float_recip2_ps();
5017 GEN_STORE_FTN_FREG(fd, WT2);
5018 GEN_STORE_FTN_FREG(fd, WTH2);
5019 opn = "recip2.ps";
5020 break;
5021 case FOP(29, 22):
5022 check_cp1_64bitmode(ctx);
5023 GEN_LOAD_FREG_FTN(WT0, fs);
5024 GEN_LOAD_FREG_FTN(WTH0, fs);
5025 gen_op_float_recip1_ps();
5026 GEN_STORE_FTN_FREG(fd, WT2);
5027 GEN_STORE_FTN_FREG(fd, WTH2);
5028 opn = "recip1.ps";
5029 break;
5030 case FOP(30, 22):
5031 check_cp1_64bitmode(ctx);
5032 GEN_LOAD_FREG_FTN(WT0, fs);
5033 GEN_LOAD_FREG_FTN(WTH0, fs);
5034 gen_op_float_rsqrt1_ps();
5035 GEN_STORE_FTN_FREG(fd, WT2);
5036 GEN_STORE_FTN_FREG(fd, WTH2);
5037 opn = "rsqrt1.ps";
5038 break;
5039 case FOP(31, 22):
5040 check_cp1_64bitmode(ctx);
5041 GEN_LOAD_FREG_FTN(WT0, fs);
5042 GEN_LOAD_FREG_FTN(WTH0, fs);
5043 GEN_LOAD_FREG_FTN(WT2, ft);
5044 GEN_LOAD_FREG_FTN(WTH2, ft);
5045 gen_op_float_rsqrt2_ps();
5046 GEN_STORE_FTN_FREG(fd, WT2);
5047 GEN_STORE_FTN_FREG(fd, WTH2);
5048 opn = "rsqrt2.ps";
5049 break;
5050 case FOP(32, 22):
5051 check_cp1_64bitmode(ctx);
5052 GEN_LOAD_FREG_FTN(WTH0, fs);
5053 gen_op_float_cvts_pu();
5054 GEN_STORE_FTN_FREG(fd, WT2);
5055 opn = "cvt.s.pu";
5056 break;
5057 case FOP(36, 22):
5058 check_cp1_64bitmode(ctx);
5059 GEN_LOAD_FREG_FTN(WT0, fs);
5060 GEN_LOAD_FREG_FTN(WTH0, fs);
5061 gen_op_float_cvtpw_ps();
5062 GEN_STORE_FTN_FREG(fd, WT2);
5063 GEN_STORE_FTN_FREG(fd, WTH2);
5064 opn = "cvt.pw.ps";
5065 break;
5066 case FOP(40, 22):
5067 check_cp1_64bitmode(ctx);
5068 GEN_LOAD_FREG_FTN(WT0, fs);
5069 gen_op_float_cvts_pl();
5070 GEN_STORE_FTN_FREG(fd, WT2);
5071 opn = "cvt.s.pl";
5072 break;
5073 case FOP(44, 22):
5074 check_cp1_64bitmode(ctx);
5075 GEN_LOAD_FREG_FTN(WT0, fs);
5076 GEN_LOAD_FREG_FTN(WT1, ft);
5077 gen_op_float_pll_ps();
5078 GEN_STORE_FTN_FREG(fd, DT2);
5079 opn = "pll.ps";
5080 break;
5081 case FOP(45, 22):
5082 check_cp1_64bitmode(ctx);
5083 GEN_LOAD_FREG_FTN(WT0, fs);
5084 GEN_LOAD_FREG_FTN(WTH1, ft);
5085 gen_op_float_plu_ps();
5086 GEN_STORE_FTN_FREG(fd, DT2);
5087 opn = "plu.ps";
5088 break;
5089 case FOP(46, 22):
5090 check_cp1_64bitmode(ctx);
5091 GEN_LOAD_FREG_FTN(WTH0, fs);
5092 GEN_LOAD_FREG_FTN(WT1, ft);
5093 gen_op_float_pul_ps();
5094 GEN_STORE_FTN_FREG(fd, DT2);
5095 opn = "pul.ps";
5096 break;
5097 case FOP(47, 22):
5098 check_cp1_64bitmode(ctx);
5099 GEN_LOAD_FREG_FTN(WTH0, fs);
5100 GEN_LOAD_FREG_FTN(WTH1, ft);
5101 gen_op_float_puu_ps();
5102 GEN_STORE_FTN_FREG(fd, DT2);
5103 opn = "puu.ps";
5104 break;
5105 case FOP(48, 22):
5106 case FOP(49, 22):
5107 case FOP(50, 22):
5108 case FOP(51, 22):
5109 case FOP(52, 22):
5110 case FOP(53, 22):
5111 case FOP(54, 22):
5112 case FOP(55, 22):
5113 case FOP(56, 22):
5114 case FOP(57, 22):
5115 case FOP(58, 22):
5116 case FOP(59, 22):
5117 case FOP(60, 22):
5118 case FOP(61, 22):
5119 case FOP(62, 22):
5120 case FOP(63, 22):
5121 check_cp1_64bitmode(ctx);
5122 GEN_LOAD_FREG_FTN(WT0, fs);
5123 GEN_LOAD_FREG_FTN(WTH0, fs);
5124 GEN_LOAD_FREG_FTN(WT1, ft);
5125 GEN_LOAD_FREG_FTN(WTH1, ft);
5126 if (ctx->opcode & (1 << 6)) {
5127 gen_cmpabs_ps(func-48, cc);
5128 opn = condnames_abs[func-48];
5129 } else {
5130 gen_cmp_ps(func-48, cc);
5131 opn = condnames[func-48];
5133 break;
5134 default:
5135 MIPS_INVAL(opn);
5136 generate_exception (ctx, EXCP_RI);
5137 return;
5139 switch (optype) {
5140 case BINOP:
5141 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5142 break;
5143 case CMPOP:
5144 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
5145 break;
5146 default:
5147 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5148 break;
5152 /* Coprocessor 3 (FPU) */
5153 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
5154 int fd, int fs, int base, int index)
5156 const char *opn = "extended float load/store";
5157 int store = 0;
5159 /* All of those work only on 64bit FPUs. */
5160 check_cp1_64bitmode(ctx);
5161 if (base == 0) {
5162 if (index == 0)
5163 gen_op_reset_T0();
5164 else
5165 GEN_LOAD_REG_TN(T0, index);
5166 } else if (index == 0) {
5167 GEN_LOAD_REG_TN(T0, base);
5168 } else {
5169 GEN_LOAD_REG_TN(T0, base);
5170 GEN_LOAD_REG_TN(T1, index);
5171 gen_op_addr_add();
5173 /* Don't do NOP if destination is zero: we must perform the actual
5174 * memory access
5176 switch (opc) {
5177 case OPC_LWXC1:
5178 op_ldst(lwc1);
5179 GEN_STORE_FTN_FREG(fd, WT0);
5180 opn = "lwxc1";
5181 break;
5182 case OPC_LDXC1:
5183 op_ldst(ldc1);
5184 GEN_STORE_FTN_FREG(fd, DT0);
5185 opn = "ldxc1";
5186 break;
5187 case OPC_LUXC1:
5188 op_ldst(luxc1);
5189 GEN_STORE_FTN_FREG(fd, DT0);
5190 opn = "luxc1";
5191 break;
5192 case OPC_SWXC1:
5193 GEN_LOAD_FREG_FTN(WT0, fs);
5194 op_ldst(swc1);
5195 opn = "swxc1";
5196 store = 1;
5197 break;
5198 case OPC_SDXC1:
5199 GEN_LOAD_FREG_FTN(DT0, fs);
5200 op_ldst(sdc1);
5201 opn = "sdxc1";
5202 store = 1;
5203 break;
5204 case OPC_SUXC1:
5205 GEN_LOAD_FREG_FTN(DT0, fs);
5206 op_ldst(suxc1);
5207 opn = "suxc1";
5208 store = 1;
5209 break;
5210 default:
5211 MIPS_INVAL(opn);
5212 generate_exception(ctx, EXCP_RI);
5213 return;
5215 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
5216 regnames[index], regnames[base]);
5219 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5220 int fd, int fr, int fs, int ft)
5222 const char *opn = "flt3_arith";
5224 /* All of those work only on 64bit FPUs. */
5225 check_cp1_64bitmode(ctx);
5226 switch (opc) {
5227 case OPC_ALNV_PS:
5228 GEN_LOAD_REG_TN(T0, fr);
5229 GEN_LOAD_FREG_FTN(DT0, fs);
5230 GEN_LOAD_FREG_FTN(DT1, ft);
5231 gen_op_float_alnv_ps();
5232 GEN_STORE_FTN_FREG(fd, DT2);
5233 opn = "alnv.ps";
5234 break;
5235 case OPC_MADD_S:
5236 GEN_LOAD_FREG_FTN(WT0, fs);
5237 GEN_LOAD_FREG_FTN(WT1, ft);
5238 GEN_LOAD_FREG_FTN(WT2, fr);
5239 gen_op_float_muladd_s();
5240 GEN_STORE_FTN_FREG(fd, WT2);
5241 opn = "madd.s";
5242 break;
5243 case OPC_MADD_D:
5244 GEN_LOAD_FREG_FTN(DT0, fs);
5245 GEN_LOAD_FREG_FTN(DT1, ft);
5246 GEN_LOAD_FREG_FTN(DT2, fr);
5247 gen_op_float_muladd_d();
5248 GEN_STORE_FTN_FREG(fd, DT2);
5249 opn = "madd.d";
5250 break;
5251 case OPC_MADD_PS:
5252 GEN_LOAD_FREG_FTN(WT0, fs);
5253 GEN_LOAD_FREG_FTN(WTH0, fs);
5254 GEN_LOAD_FREG_FTN(WT1, ft);
5255 GEN_LOAD_FREG_FTN(WTH1, ft);
5256 GEN_LOAD_FREG_FTN(WT2, fr);
5257 GEN_LOAD_FREG_FTN(WTH2, fr);
5258 gen_op_float_muladd_ps();
5259 GEN_STORE_FTN_FREG(fd, WT2);
5260 GEN_STORE_FTN_FREG(fd, WTH2);
5261 opn = "madd.ps";
5262 break;
5263 case OPC_MSUB_S:
5264 GEN_LOAD_FREG_FTN(WT0, fs);
5265 GEN_LOAD_FREG_FTN(WT1, ft);
5266 GEN_LOAD_FREG_FTN(WT2, fr);
5267 gen_op_float_mulsub_s();
5268 GEN_STORE_FTN_FREG(fd, WT2);
5269 opn = "msub.s";
5270 break;
5271 case OPC_MSUB_D:
5272 GEN_LOAD_FREG_FTN(DT0, fs);
5273 GEN_LOAD_FREG_FTN(DT1, ft);
5274 GEN_LOAD_FREG_FTN(DT2, fr);
5275 gen_op_float_mulsub_d();
5276 GEN_STORE_FTN_FREG(fd, DT2);
5277 opn = "msub.d";
5278 break;
5279 case OPC_MSUB_PS:
5280 GEN_LOAD_FREG_FTN(WT0, fs);
5281 GEN_LOAD_FREG_FTN(WTH0, fs);
5282 GEN_LOAD_FREG_FTN(WT1, ft);
5283 GEN_LOAD_FREG_FTN(WTH1, ft);
5284 GEN_LOAD_FREG_FTN(WT2, fr);
5285 GEN_LOAD_FREG_FTN(WTH2, fr);
5286 gen_op_float_mulsub_ps();
5287 GEN_STORE_FTN_FREG(fd, WT2);
5288 GEN_STORE_FTN_FREG(fd, WTH2);
5289 opn = "msub.ps";
5290 break;
5291 case OPC_NMADD_S:
5292 GEN_LOAD_FREG_FTN(WT0, fs);
5293 GEN_LOAD_FREG_FTN(WT1, ft);
5294 GEN_LOAD_FREG_FTN(WT2, fr);
5295 gen_op_float_nmuladd_s();
5296 GEN_STORE_FTN_FREG(fd, WT2);
5297 opn = "nmadd.s";
5298 break;
5299 case OPC_NMADD_D:
5300 GEN_LOAD_FREG_FTN(DT0, fs);
5301 GEN_LOAD_FREG_FTN(DT1, ft);
5302 GEN_LOAD_FREG_FTN(DT2, fr);
5303 gen_op_float_nmuladd_d();
5304 GEN_STORE_FTN_FREG(fd, DT2);
5305 opn = "nmadd.d";
5306 break;
5307 case OPC_NMADD_PS:
5308 GEN_LOAD_FREG_FTN(WT0, fs);
5309 GEN_LOAD_FREG_FTN(WTH0, fs);
5310 GEN_LOAD_FREG_FTN(WT1, ft);
5311 GEN_LOAD_FREG_FTN(WTH1, ft);
5312 GEN_LOAD_FREG_FTN(WT2, fr);
5313 GEN_LOAD_FREG_FTN(WTH2, fr);
5314 gen_op_float_nmuladd_ps();
5315 GEN_STORE_FTN_FREG(fd, WT2);
5316 GEN_STORE_FTN_FREG(fd, WTH2);
5317 opn = "nmadd.ps";
5318 break;
5319 case OPC_NMSUB_S:
5320 GEN_LOAD_FREG_FTN(WT0, fs);
5321 GEN_LOAD_FREG_FTN(WT1, ft);
5322 GEN_LOAD_FREG_FTN(WT2, fr);
5323 gen_op_float_nmulsub_s();
5324 GEN_STORE_FTN_FREG(fd, WT2);
5325 opn = "nmsub.s";
5326 break;
5327 case OPC_NMSUB_D:
5328 GEN_LOAD_FREG_FTN(DT0, fs);
5329 GEN_LOAD_FREG_FTN(DT1, ft);
5330 GEN_LOAD_FREG_FTN(DT2, fr);
5331 gen_op_float_nmulsub_d();
5332 GEN_STORE_FTN_FREG(fd, DT2);
5333 opn = "nmsub.d";
5334 break;
5335 case OPC_NMSUB_PS:
5336 GEN_LOAD_FREG_FTN(WT0, fs);
5337 GEN_LOAD_FREG_FTN(WTH0, fs);
5338 GEN_LOAD_FREG_FTN(WT1, ft);
5339 GEN_LOAD_FREG_FTN(WTH1, ft);
5340 GEN_LOAD_FREG_FTN(WT2, fr);
5341 GEN_LOAD_FREG_FTN(WTH2, fr);
5342 gen_op_float_nmulsub_ps();
5343 GEN_STORE_FTN_FREG(fd, WT2);
5344 GEN_STORE_FTN_FREG(fd, WTH2);
5345 opn = "nmsub.ps";
5346 break;
5347 default:
5348 MIPS_INVAL(opn);
5349 generate_exception (ctx, EXCP_RI);
5350 return;
5352 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
5353 fregnames[fs], fregnames[ft]);
5356 /* ISA extensions (ASEs) */
5357 /* MIPS16 extension to MIPS32 */
5358 /* SmartMIPS extension to MIPS32 */
5360 #ifdef TARGET_MIPS64
5362 /* MDMX extension to MIPS64 */
5363 /* MIPS-3D extension to MIPS64 */
5365 #endif
5367 static void decode_opc (CPUState *env, DisasContext *ctx)
5369 int32_t offset;
5370 int rs, rt, rd, sa;
5371 uint32_t op, op1, op2;
5372 int16_t imm;
5374 /* make sure instructions are on a word boundary */
5375 if (ctx->pc & 0x3) {
5376 env->CP0_BadVAddr = ctx->pc;
5377 generate_exception(ctx, EXCP_AdEL);
5378 return;
5381 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
5382 int l1;
5383 /* Handle blikely not taken case */
5384 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
5385 l1 = gen_new_label();
5386 gen_op_jnz_T2(l1);
5387 gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
5388 gen_goto_tb(ctx, 1, ctx->pc + 4);
5389 gen_set_label(l1);
5391 op = MASK_OP_MAJOR(ctx->opcode);
5392 rs = (ctx->opcode >> 21) & 0x1f;
5393 rt = (ctx->opcode >> 16) & 0x1f;
5394 rd = (ctx->opcode >> 11) & 0x1f;
5395 sa = (ctx->opcode >> 6) & 0x1f;
5396 imm = (int16_t)ctx->opcode;
5397 switch (op) {
5398 case OPC_SPECIAL:
5399 op1 = MASK_SPECIAL(ctx->opcode);
5400 switch (op1) {
5401 case OPC_SLL: /* Arithmetic with immediate */
5402 case OPC_SRL ... OPC_SRA:
5403 gen_arith_imm(ctx, op1, rd, rt, sa);
5404 break;
5405 case OPC_SLLV: /* Arithmetic */
5406 case OPC_SRLV ... OPC_SRAV:
5407 case OPC_MOVZ ... OPC_MOVN:
5408 case OPC_ADD ... OPC_NOR:
5409 case OPC_SLT ... OPC_SLTU:
5410 gen_arith(ctx, op1, rd, rs, rt);
5411 break;
5412 case OPC_MULT ... OPC_DIVU:
5413 gen_muldiv(ctx, op1, rs, rt);
5414 break;
5415 case OPC_JR ... OPC_JALR:
5416 gen_compute_branch(ctx, op1, rs, rd, sa);
5417 return;
5418 case OPC_TGE ... OPC_TEQ: /* Traps */
5419 case OPC_TNE:
5420 gen_trap(ctx, op1, rs, rt, -1);
5421 break;
5422 case OPC_MFHI: /* Move from HI/LO */
5423 case OPC_MFLO:
5424 gen_HILO(ctx, op1, rd);
5425 break;
5426 case OPC_MTHI:
5427 case OPC_MTLO: /* Move to HI/LO */
5428 gen_HILO(ctx, op1, rs);
5429 break;
5430 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
5431 #ifdef MIPS_STRICT_STANDARD
5432 MIPS_INVAL("PMON / selsl");
5433 generate_exception(ctx, EXCP_RI);
5434 #else
5435 gen_op_pmon(sa);
5436 #endif
5437 break;
5438 case OPC_SYSCALL:
5439 generate_exception(ctx, EXCP_SYSCALL);
5440 break;
5441 case OPC_BREAK:
5442 /* XXX: Hack to work around wrong handling of self-modifying code. */
5443 ctx->pc += 4;
5444 save_cpu_state(ctx, 1);
5445 ctx->pc -= 4;
5446 generate_exception(ctx, EXCP_BREAK);
5447 break;
5448 case OPC_SPIM:
5449 #ifdef MIPS_STRICT_STANDARD
5450 MIPS_INVAL("SPIM");
5451 generate_exception(ctx, EXCP_RI);
5452 #else
5453 /* Implemented as RI exception for now. */
5454 MIPS_INVAL("spim (unofficial)");
5455 generate_exception(ctx, EXCP_RI);
5456 #endif
5457 break;
5458 case OPC_SYNC:
5459 /* Treat as a noop. */
5460 break;
5462 case OPC_MOVCI:
5463 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5464 save_cpu_state(ctx, 1);
5465 check_cp1_enabled(ctx);
5466 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
5467 (ctx->opcode >> 16) & 1);
5468 } else {
5469 generate_exception_err(ctx, EXCP_CpU, 1);
5471 break;
5473 #ifdef TARGET_MIPS64
5474 /* MIPS64 specific opcodes */
5475 case OPC_DSLL:
5476 case OPC_DSRL ... OPC_DSRA:
5477 case OPC_DSLL32:
5478 case OPC_DSRL32 ... OPC_DSRA32:
5479 if (!(ctx->hflags & MIPS_HFLAG_64))
5480 generate_exception(ctx, EXCP_RI);
5481 gen_arith_imm(ctx, op1, rd, rt, sa);
5482 break;
5483 case OPC_DSLLV:
5484 case OPC_DSRLV ... OPC_DSRAV:
5485 case OPC_DADD ... OPC_DSUBU:
5486 if (!(ctx->hflags & MIPS_HFLAG_64))
5487 generate_exception(ctx, EXCP_RI);
5488 gen_arith(ctx, op1, rd, rs, rt);
5489 break;
5490 case OPC_DMULT ... OPC_DDIVU:
5491 if (!(ctx->hflags & MIPS_HFLAG_64))
5492 generate_exception(ctx, EXCP_RI);
5493 gen_muldiv(ctx, op1, rs, rt);
5494 break;
5495 #endif
5496 default: /* Invalid */
5497 MIPS_INVAL("special");
5498 generate_exception(ctx, EXCP_RI);
5499 break;
5501 break;
5502 case OPC_SPECIAL2:
5503 op1 = MASK_SPECIAL2(ctx->opcode);
5504 switch (op1) {
5505 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
5506 case OPC_MSUB ... OPC_MSUBU:
5507 gen_muldiv(ctx, op1, rs, rt);
5508 break;
5509 case OPC_MUL:
5510 gen_arith(ctx, op1, rd, rs, rt);
5511 break;
5512 case OPC_CLZ ... OPC_CLO:
5513 gen_cl(ctx, op1, rd, rs);
5514 break;
5515 case OPC_SDBBP:
5516 /* XXX: not clear which exception should be raised
5517 * when in debug mode...
5519 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5520 generate_exception(ctx, EXCP_DBp);
5521 } else {
5522 generate_exception(ctx, EXCP_DBp);
5524 /* Treat as a noop */
5525 break;
5526 #ifdef TARGET_MIPS64
5527 case OPC_DCLZ ... OPC_DCLO:
5528 if (!(ctx->hflags & MIPS_HFLAG_64))
5529 generate_exception(ctx, EXCP_RI);
5530 gen_cl(ctx, op1, rd, rs);
5531 break;
5532 #endif
5533 default: /* Invalid */
5534 MIPS_INVAL("special2");
5535 generate_exception(ctx, EXCP_RI);
5536 break;
5538 break;
5539 case OPC_SPECIAL3:
5540 check_mips_r2(env, ctx);
5541 op1 = MASK_SPECIAL3(ctx->opcode);
5542 switch (op1) {
5543 case OPC_EXT:
5544 case OPC_INS:
5545 gen_bitops(ctx, op1, rt, rs, sa, rd);
5546 break;
5547 case OPC_BSHFL:
5548 op2 = MASK_BSHFL(ctx->opcode);
5549 switch (op2) {
5550 case OPC_WSBH:
5551 GEN_LOAD_REG_TN(T1, rt);
5552 gen_op_wsbh();
5553 break;
5554 case OPC_SEB:
5555 GEN_LOAD_REG_TN(T1, rt);
5556 gen_op_seb();
5557 break;
5558 case OPC_SEH:
5559 GEN_LOAD_REG_TN(T1, rt);
5560 gen_op_seh();
5561 break;
5562 default: /* Invalid */
5563 MIPS_INVAL("bshfl");
5564 generate_exception(ctx, EXCP_RI);
5565 break;
5567 GEN_STORE_TN_REG(rd, T0);
5568 break;
5569 case OPC_RDHWR:
5570 switch (rd) {
5571 case 0:
5572 save_cpu_state(ctx, 1);
5573 gen_op_rdhwr_cpunum();
5574 break;
5575 case 1:
5576 save_cpu_state(ctx, 1);
5577 gen_op_rdhwr_synci_step();
5578 break;
5579 case 2:
5580 save_cpu_state(ctx, 1);
5581 gen_op_rdhwr_cc();
5582 break;
5583 case 3:
5584 save_cpu_state(ctx, 1);
5585 gen_op_rdhwr_ccres();
5586 break;
5587 case 29:
5588 #if defined (CONFIG_USER_ONLY)
5589 gen_op_tls_value ();
5590 break;
5591 #endif
5592 default: /* Invalid */
5593 MIPS_INVAL("rdhwr");
5594 generate_exception(ctx, EXCP_RI);
5595 break;
5597 GEN_STORE_TN_REG(rt, T0);
5598 break;
5599 #ifdef TARGET_MIPS64
5600 case OPC_DEXTM ... OPC_DEXT:
5601 case OPC_DINSM ... OPC_DINS:
5602 if (!(ctx->hflags & MIPS_HFLAG_64))
5603 generate_exception(ctx, EXCP_RI);
5604 gen_bitops(ctx, op1, rt, rs, sa, rd);
5605 break;
5606 case OPC_DBSHFL:
5607 if (!(ctx->hflags & MIPS_HFLAG_64))
5608 generate_exception(ctx, EXCP_RI);
5609 op2 = MASK_DBSHFL(ctx->opcode);
5610 switch (op2) {
5611 case OPC_DSBH:
5612 GEN_LOAD_REG_TN(T1, rt);
5613 gen_op_dsbh();
5614 break;
5615 case OPC_DSHD:
5616 GEN_LOAD_REG_TN(T1, rt);
5617 gen_op_dshd();
5618 break;
5619 default: /* Invalid */
5620 MIPS_INVAL("dbshfl");
5621 generate_exception(ctx, EXCP_RI);
5622 break;
5624 GEN_STORE_TN_REG(rd, T0);
5625 #endif
5626 default: /* Invalid */
5627 MIPS_INVAL("special3");
5628 generate_exception(ctx, EXCP_RI);
5629 break;
5631 break;
5632 case OPC_REGIMM:
5633 op1 = MASK_REGIMM(ctx->opcode);
5634 switch (op1) {
5635 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
5636 case OPC_BLTZAL ... OPC_BGEZALL:
5637 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
5638 return;
5639 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
5640 case OPC_TNEI:
5641 gen_trap(ctx, op1, rs, -1, imm);
5642 break;
5643 case OPC_SYNCI:
5644 check_mips_r2(env, ctx);
5645 /* treat as noop */
5646 break;
5647 default: /* Invalid */
5648 MIPS_INVAL("regimm");
5649 generate_exception(ctx, EXCP_RI);
5650 break;
5652 break;
5653 case OPC_CP0:
5654 save_cpu_state(ctx, 1);
5655 gen_op_cp0_enabled();
5656 op1 = MASK_CP0(ctx->opcode);
5657 switch (op1) {
5658 case OPC_MFC0:
5659 case OPC_MTC0:
5660 #ifdef TARGET_MIPS64
5661 case OPC_DMFC0:
5662 case OPC_DMTC0:
5663 #endif
5664 gen_cp0(env, ctx, op1, rt, rd);
5665 break;
5666 case OPC_C0_FIRST ... OPC_C0_LAST:
5667 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
5668 break;
5669 case OPC_MFMC0:
5670 check_mips_r2(env, ctx);
5671 op2 = MASK_MFMC0(ctx->opcode);
5672 switch (op2) {
5673 case OPC_DI:
5674 gen_op_di();
5675 /* Stop translation as we may have switched the execution mode */
5676 ctx->bstate = BS_STOP;
5677 break;
5678 case OPC_EI:
5679 gen_op_ei();
5680 /* Stop translation as we may have switched the execution mode */
5681 ctx->bstate = BS_STOP;
5682 break;
5683 default: /* Invalid */
5684 MIPS_INVAL("mfmc0");
5685 generate_exception(ctx, EXCP_RI);
5686 break;
5688 GEN_STORE_TN_REG(rt, T0);
5689 break;
5690 case OPC_RDPGPR:
5691 case OPC_WRPGPR:
5692 check_mips_r2(env, ctx);
5693 /* Shadow registers not implemented. */
5694 GEN_LOAD_REG_TN(T0, rt);
5695 GEN_STORE_TN_REG(rd, T0);
5696 break;
5697 default:
5698 MIPS_INVAL("cp0");
5699 generate_exception(ctx, EXCP_RI);
5700 break;
5702 break;
5703 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
5704 gen_arith_imm(ctx, op, rt, rs, imm);
5705 break;
5706 case OPC_J ... OPC_JAL: /* Jump */
5707 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
5708 gen_compute_branch(ctx, op, rs, rt, offset);
5709 return;
5710 case OPC_BEQ ... OPC_BGTZ: /* Branch */
5711 case OPC_BEQL ... OPC_BGTZL:
5712 gen_compute_branch(ctx, op, rs, rt, imm << 2);
5713 return;
5714 case OPC_LB ... OPC_LWR: /* Load and stores */
5715 case OPC_SB ... OPC_SW:
5716 case OPC_SWR:
5717 case OPC_LL:
5718 case OPC_SC:
5719 gen_ldst(ctx, op, rt, rs, imm);
5720 break;
5721 case OPC_CACHE:
5722 /* Treat as a noop */
5723 break;
5724 case OPC_PREF:
5725 /* Treat as a noop */
5726 break;
5728 /* Floating point (COP1). */
5729 case OPC_LWC1:
5730 case OPC_LDC1:
5731 case OPC_SWC1:
5732 case OPC_SDC1:
5733 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5734 save_cpu_state(ctx, 1);
5735 check_cp1_enabled(ctx);
5736 gen_flt_ldst(ctx, op, rt, rs, imm);
5737 } else {
5738 generate_exception_err(ctx, EXCP_CpU, 1);
5740 break;
5742 case OPC_CP1:
5743 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5744 save_cpu_state(ctx, 1);
5745 check_cp1_enabled(ctx);
5746 op1 = MASK_CP1(ctx->opcode);
5747 switch (op1) {
5748 case OPC_MFHC1:
5749 case OPC_MTHC1:
5750 check_mips_r2(env, ctx);
5751 case OPC_MFC1:
5752 case OPC_CFC1:
5753 case OPC_MTC1:
5754 case OPC_CTC1:
5755 #ifdef TARGET_MIPS64
5756 case OPC_DMFC1:
5757 case OPC_DMTC1:
5758 #endif
5759 gen_cp1(ctx, op1, rt, rd);
5760 break;
5761 case OPC_BC1:
5762 case OPC_BC1ANY2:
5763 case OPC_BC1ANY4:
5764 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5765 (rt >> 2) & 0x7, imm << 2);
5766 return;
5767 case OPC_S_FMT:
5768 case OPC_D_FMT:
5769 case OPC_W_FMT:
5770 case OPC_L_FMT:
5771 case OPC_PS_FMT:
5772 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
5773 (imm >> 8) & 0x7);
5774 break;
5775 default:
5776 MIPS_INVAL("cp1");
5777 generate_exception (ctx, EXCP_RI);
5778 break;
5780 } else {
5781 generate_exception_err(ctx, EXCP_CpU, 1);
5783 break;
5785 /* COP2. */
5786 case OPC_LWC2:
5787 case OPC_LDC2:
5788 case OPC_SWC2:
5789 case OPC_SDC2:
5790 case OPC_CP2:
5791 /* COP2: Not implemented. */
5792 generate_exception_err(ctx, EXCP_CpU, 2);
5793 break;
5795 case OPC_CP3:
5796 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5797 save_cpu_state(ctx, 1);
5798 check_cp1_enabled(ctx);
5799 op1 = MASK_CP3(ctx->opcode);
5800 switch (op1) {
5801 case OPC_LWXC1:
5802 case OPC_LDXC1:
5803 case OPC_LUXC1:
5804 case OPC_SWXC1:
5805 case OPC_SDXC1:
5806 case OPC_SUXC1:
5807 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5808 break;
5809 case OPC_PREFX:
5810 /* treat as noop */
5811 break;
5812 case OPC_ALNV_PS:
5813 case OPC_MADD_S:
5814 case OPC_MADD_D:
5815 case OPC_MADD_PS:
5816 case OPC_MSUB_S:
5817 case OPC_MSUB_D:
5818 case OPC_MSUB_PS:
5819 case OPC_NMADD_S:
5820 case OPC_NMADD_D:
5821 case OPC_NMADD_PS:
5822 case OPC_NMSUB_S:
5823 case OPC_NMSUB_D:
5824 case OPC_NMSUB_PS:
5825 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
5826 break;
5827 default:
5828 MIPS_INVAL("cp3");
5829 generate_exception (ctx, EXCP_RI);
5830 break;
5832 } else {
5833 generate_exception_err(ctx, EXCP_CpU, 1);
5835 break;
5837 #ifdef TARGET_MIPS64
5838 /* MIPS64 opcodes */
5839 case OPC_LWU:
5840 case OPC_LDL ... OPC_LDR:
5841 case OPC_SDL ... OPC_SDR:
5842 case OPC_LLD:
5843 case OPC_LD:
5844 case OPC_SCD:
5845 case OPC_SD:
5846 if (!(ctx->hflags & MIPS_HFLAG_64))
5847 generate_exception(ctx, EXCP_RI);
5848 gen_ldst(ctx, op, rt, rs, imm);
5849 break;
5850 case OPC_DADDI ... OPC_DADDIU:
5851 if (!(ctx->hflags & MIPS_HFLAG_64))
5852 generate_exception(ctx, EXCP_RI);
5853 gen_arith_imm(ctx, op, rt, rs, imm);
5854 break;
5855 #endif
5856 #ifdef MIPS_HAS_MIPS16
5857 case OPC_JALX:
5858 /* MIPS16: Not implemented. */
5859 #endif
5860 #ifdef MIPS_HAS_MDMX
5861 case OPC_MDMX:
5862 /* MDMX: Not implemented. */
5863 #endif
5864 default: /* Invalid */
5865 MIPS_INVAL("major opcode");
5866 generate_exception(ctx, EXCP_RI);
5867 break;
5869 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5870 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
5871 /* Branches completion */
5872 ctx->hflags &= ~MIPS_HFLAG_BMASK;
5873 ctx->bstate = BS_BRANCH;
5874 save_cpu_state(ctx, 0);
5875 switch (hflags) {
5876 case MIPS_HFLAG_B:
5877 /* unconditional branch */
5878 MIPS_DEBUG("unconditional branch");
5879 gen_goto_tb(ctx, 0, ctx->btarget);
5880 break;
5881 case MIPS_HFLAG_BL:
5882 /* blikely taken case */
5883 MIPS_DEBUG("blikely branch taken");
5884 gen_goto_tb(ctx, 0, ctx->btarget);
5885 break;
5886 case MIPS_HFLAG_BC:
5887 /* Conditional branch */
5888 MIPS_DEBUG("conditional branch");
5890 int l1;
5891 l1 = gen_new_label();
5892 gen_op_jnz_T2(l1);
5893 gen_goto_tb(ctx, 1, ctx->pc + 4);
5894 gen_set_label(l1);
5895 gen_goto_tb(ctx, 0, ctx->btarget);
5897 break;
5898 case MIPS_HFLAG_BR:
5899 /* unconditional branch to register */
5900 MIPS_DEBUG("branch to register");
5901 gen_op_breg();
5902 gen_op_reset_T0();
5903 gen_op_exit_tb();
5904 break;
5905 default:
5906 MIPS_DEBUG("unknown branch");
5907 break;
5912 static inline int
5913 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5914 int search_pc)
5916 DisasContext ctx;
5917 target_ulong pc_start;
5918 uint16_t *gen_opc_end;
5919 int j, lj = -1;
5921 if (search_pc && loglevel)
5922 fprintf (logfile, "search pc %d\n", search_pc);
5924 pc_start = tb->pc;
5925 gen_opc_ptr = gen_opc_buf;
5926 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
5927 gen_opparam_ptr = gen_opparam_buf;
5928 nb_gen_labels = 0;
5929 ctx.pc = pc_start;
5930 ctx.saved_pc = -1;
5931 ctx.tb = tb;
5932 ctx.bstate = BS_NONE;
5933 /* Restore delay slot state from the tb context. */
5934 ctx.hflags = tb->flags;
5935 restore_cpu_state(env, &ctx);
5936 #if defined(CONFIG_USER_ONLY)
5937 ctx.mem_idx = 0;
5938 #else
5939 ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
5940 #endif
5941 #ifdef DEBUG_DISAS
5942 if (loglevel & CPU_LOG_TB_CPU) {
5943 fprintf(logfile, "------------------------------------------------\n");
5944 /* FIXME: This may print out stale hflags from env... */
5945 cpu_dump_state(env, logfile, fprintf, 0);
5947 #endif
5948 #ifdef MIPS_DEBUG_DISAS
5949 if (loglevel & CPU_LOG_TB_IN_ASM)
5950 fprintf(logfile, "\ntb %p super %d cond %04x\n",
5951 tb, ctx.mem_idx, ctx.hflags);
5952 #endif
5953 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
5954 if (env->nb_breakpoints > 0) {
5955 for(j = 0; j < env->nb_breakpoints; j++) {
5956 if (env->breakpoints[j] == ctx.pc) {
5957 save_cpu_state(&ctx, 1);
5958 ctx.bstate = BS_BRANCH;
5959 gen_op_debug();
5960 goto done_generating;
5965 if (search_pc) {
5966 j = gen_opc_ptr - gen_opc_buf;
5967 if (lj < j) {
5968 lj++;
5969 while (lj < j)
5970 gen_opc_instr_start[lj++] = 0;
5972 gen_opc_pc[lj] = ctx.pc;
5973 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
5974 gen_opc_instr_start[lj] = 1;
5976 ctx.opcode = ldl_code(ctx.pc);
5977 decode_opc(env, &ctx);
5978 ctx.pc += 4;
5980 if (env->singlestep_enabled)
5981 break;
5983 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
5984 break;
5986 #if defined (MIPS_SINGLE_STEP)
5987 break;
5988 #endif
5990 if (env->singlestep_enabled) {
5991 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
5992 gen_op_debug();
5993 } else {
5994 switch (ctx.bstate) {
5995 case BS_STOP:
5996 gen_op_interrupt_restart();
5997 gen_goto_tb(&ctx, 0, ctx.pc);
5998 break;
5999 case BS_NONE:
6000 save_cpu_state(&ctx, 0);
6001 gen_goto_tb(&ctx, 0, ctx.pc);
6002 break;
6003 case BS_EXCP:
6004 gen_op_interrupt_restart();
6005 gen_op_reset_T0();
6006 gen_op_exit_tb();
6007 break;
6008 case BS_BRANCH:
6009 default:
6010 break;
6013 done_generating:
6014 *gen_opc_ptr = INDEX_op_end;
6015 if (search_pc) {
6016 j = gen_opc_ptr - gen_opc_buf;
6017 lj++;
6018 while (lj <= j)
6019 gen_opc_instr_start[lj++] = 0;
6020 tb->size = 0;
6021 } else {
6022 tb->size = ctx.pc - pc_start;
6024 #ifdef DEBUG_DISAS
6025 #if defined MIPS_DEBUG_DISAS
6026 if (loglevel & CPU_LOG_TB_IN_ASM)
6027 fprintf(logfile, "\n");
6028 #endif
6029 if (loglevel & CPU_LOG_TB_IN_ASM) {
6030 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6031 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
6032 fprintf(logfile, "\n");
6034 if (loglevel & CPU_LOG_TB_OP) {
6035 fprintf(logfile, "OP:\n");
6036 dump_ops(gen_opc_buf, gen_opparam_buf);
6037 fprintf(logfile, "\n");
6039 if (loglevel & CPU_LOG_TB_CPU) {
6040 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
6042 #endif
6044 return 0;
6047 int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6049 return gen_intermediate_code_internal(env, tb, 0);
6052 int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6054 return gen_intermediate_code_internal(env, tb, 1);
6057 void fpu_dump_state(CPUState *env, FILE *f,
6058 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
6059 int flags)
6061 int i;
6062 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
6064 #define printfpr(fp) \
6065 do { \
6066 if (is_fpu64) \
6067 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
6068 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
6069 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
6070 else { \
6071 fpr_t tmp; \
6072 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
6073 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
6074 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
6075 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
6076 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
6078 } while(0)
6081 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
6082 env->fcr0, env->fcr31, is_fpu64, env->fp_status, get_float_exception_flags(&env->fp_status));
6083 fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
6084 fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
6085 fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
6086 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
6087 fpu_fprintf(f, "%3s: ", fregnames[i]);
6088 printfpr(&env->fpr[i]);
6091 #undef printfpr
6094 void dump_fpu (CPUState *env)
6096 if (loglevel) {
6097 fprintf(logfile, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
6098 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
6099 fpu_dump_state(env, logfile, fprintf, 0);
6103 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
6104 /* Debug help: The architecture requires 32bit code to maintain proper
6105 sign-extened values on 64bit machines. */
6107 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
6109 void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
6110 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6111 int flags)
6113 int i;
6115 if (!SIGN_EXT_P(env->PC))
6116 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC);
6117 if (!SIGN_EXT_P(env->HI))
6118 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI);
6119 if (!SIGN_EXT_P(env->LO))
6120 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO);
6121 if (!SIGN_EXT_P(env->btarget))
6122 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
6124 for (i = 0; i < 32; i++) {
6125 if (!SIGN_EXT_P(env->gpr[i]))
6126 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i]);
6129 if (!SIGN_EXT_P(env->CP0_EPC))
6130 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
6131 if (!SIGN_EXT_P(env->CP0_LLAddr))
6132 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
6134 #endif
6136 void cpu_dump_state (CPUState *env, FILE *f,
6137 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6138 int flags)
6140 int i;
6142 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",
6143 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
6144 for (i = 0; i < 32; i++) {
6145 if ((i & 3) == 0)
6146 cpu_fprintf(f, "GPR%02d:", i);
6147 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i]);
6148 if ((i & 3) == 3)
6149 cpu_fprintf(f, "\n");
6152 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
6153 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
6154 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
6155 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
6156 if (env->hflags & MIPS_HFLAG_FPU)
6157 fpu_dump_state(env, f, cpu_fprintf, flags);
6158 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
6159 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
6160 #endif
6163 CPUMIPSState *cpu_mips_init (void)
6165 CPUMIPSState *env;
6167 env = qemu_mallocz(sizeof(CPUMIPSState));
6168 if (!env)
6169 return NULL;
6170 cpu_exec_init(env);
6171 cpu_reset(env);
6172 return env;
6175 void cpu_reset (CPUMIPSState *env)
6177 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
6179 tlb_flush(env, 1);
6181 /* Minimal init */
6182 #if !defined(CONFIG_USER_ONLY)
6183 if (env->hflags & MIPS_HFLAG_BMASK) {
6184 /* If the exception was raised from a delay slot,
6185 * come back to the jump. */
6186 env->CP0_ErrorEPC = env->PC - 4;
6187 } else {
6188 env->CP0_ErrorEPC = env->PC;
6190 env->hflags = 0;
6191 env->PC = (int32_t)0xBFC00000;
6192 env->CP0_Wired = 0;
6193 /* SMP not implemented */
6194 env->CP0_EBase = 0x80000000;
6195 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
6196 /* vectored interrupts not implemented, timer on int 7,
6197 no performance counters. */
6198 env->CP0_IntCtl = 0xe0000000;
6200 int i;
6202 for (i = 0; i < 7; i++) {
6203 env->CP0_WatchLo[i] = 0;
6204 env->CP0_WatchHi[i] = 0x80000000;
6206 env->CP0_WatchLo[7] = 0;
6207 env->CP0_WatchHi[7] = 0;
6209 /* Count register increments in debug mode, EJTAG version 1 */
6210 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
6211 #endif
6212 env->exception_index = EXCP_NONE;
6213 #if defined(CONFIG_USER_ONLY)
6214 env->hflags |= MIPS_HFLAG_UM;
6215 env->user_mode_only = 1;
6216 #endif
6219 #include "translate_init.c"