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