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