]> git.proxmox.com Git - qemu.git/blob - target-mips/translate.c
06581f2cc6317ce63a5a48d10ba2a4b768590d5c
[qemu.git] / target-mips / translate.c
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
3 *
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <inttypes.h>
28
29 #include "cpu.h"
30 #include "exec-all.h"
31 #include "disas.h"
32
33 //#define MIPS_DEBUG_DISAS
34 //#define MIPS_DEBUG_SIGN_EXTENSIONS
35 //#define MIPS_SINGLE_STEP
36
37 #ifdef USE_DIRECT_JUMP
38 #define TBPARAM(x)
39 #else
40 #define TBPARAM(x) (long)(x)
41 #endif
42
43 enum {
44 #define DEF(s, n, copy_size) INDEX_op_ ## s,
45 #include "opc.h"
46 #undef DEF
47 NB_OPS,
48 };
49
50 static uint16_t *gen_opc_ptr;
51 static uint32_t *gen_opparam_ptr;
52
53 #include "gen-op.h"
54
55 /* MIPS major opcodes */
56 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
57
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),
131 };
132
133 /* MIPS special opcodes */
134 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
135
136 enum {
137 /* Shifts */
138 OPC_SLL = 0x00 | OPC_SPECIAL,
139 /* NOP is SLL r0, r0, 0 */
140 /* SSNOP is SLL r0, r0, 1 */
141 /* EHB is SLL r0, r0, 3 */
142 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
143 OPC_SRA = 0x03 | OPC_SPECIAL,
144 OPC_SLLV = 0x04 | OPC_SPECIAL,
145 OPC_SRLV = 0x06 | OPC_SPECIAL,
146 OPC_SRAV = 0x07 | OPC_SPECIAL,
147 OPC_DSLLV = 0x14 | OPC_SPECIAL,
148 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
149 OPC_DSRAV = 0x17 | OPC_SPECIAL,
150 OPC_DSLL = 0x38 | OPC_SPECIAL,
151 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
152 OPC_DSRA = 0x3B | OPC_SPECIAL,
153 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
154 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
155 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
156 /* Multiplication / division */
157 OPC_MULT = 0x18 | OPC_SPECIAL,
158 OPC_MULTU = 0x19 | OPC_SPECIAL,
159 OPC_DIV = 0x1A | OPC_SPECIAL,
160 OPC_DIVU = 0x1B | OPC_SPECIAL,
161 OPC_DMULT = 0x1C | OPC_SPECIAL,
162 OPC_DMULTU = 0x1D | OPC_SPECIAL,
163 OPC_DDIV = 0x1E | OPC_SPECIAL,
164 OPC_DDIVU = 0x1F | OPC_SPECIAL,
165 /* 2 registers arithmetic / logic */
166 OPC_ADD = 0x20 | OPC_SPECIAL,
167 OPC_ADDU = 0x21 | OPC_SPECIAL,
168 OPC_SUB = 0x22 | OPC_SPECIAL,
169 OPC_SUBU = 0x23 | OPC_SPECIAL,
170 OPC_AND = 0x24 | OPC_SPECIAL,
171 OPC_OR = 0x25 | OPC_SPECIAL,
172 OPC_XOR = 0x26 | OPC_SPECIAL,
173 OPC_NOR = 0x27 | OPC_SPECIAL,
174 OPC_SLT = 0x2A | OPC_SPECIAL,
175 OPC_SLTU = 0x2B | OPC_SPECIAL,
176 OPC_DADD = 0x2C | OPC_SPECIAL,
177 OPC_DADDU = 0x2D | OPC_SPECIAL,
178 OPC_DSUB = 0x2E | OPC_SPECIAL,
179 OPC_DSUBU = 0x2F | OPC_SPECIAL,
180 /* Jumps */
181 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
182 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
183 /* Traps */
184 OPC_TGE = 0x30 | OPC_SPECIAL,
185 OPC_TGEU = 0x31 | OPC_SPECIAL,
186 OPC_TLT = 0x32 | OPC_SPECIAL,
187 OPC_TLTU = 0x33 | OPC_SPECIAL,
188 OPC_TEQ = 0x34 | OPC_SPECIAL,
189 OPC_TNE = 0x36 | OPC_SPECIAL,
190 /* HI / LO registers load & stores */
191 OPC_MFHI = 0x10 | OPC_SPECIAL,
192 OPC_MTHI = 0x11 | OPC_SPECIAL,
193 OPC_MFLO = 0x12 | OPC_SPECIAL,
194 OPC_MTLO = 0x13 | OPC_SPECIAL,
195 /* Conditional moves */
196 OPC_MOVZ = 0x0A | OPC_SPECIAL,
197 OPC_MOVN = 0x0B | OPC_SPECIAL,
198
199 OPC_MOVCI = 0x01 | OPC_SPECIAL,
200
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,
207
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,
215 };
216
217 /* REGIMM (rt field) opcodes */
218 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
219
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,
236 };
237
238 /* Special2 opcodes */
239 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
240
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,
255 };
256
257 /* Special3 opcodes */
258 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
259
260 enum {
261 OPC_EXT = 0x00 | OPC_SPECIAL3,
262 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
263 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
264 OPC_DEXT = 0x03 | OPC_SPECIAL3,
265 OPC_INS = 0x04 | OPC_SPECIAL3,
266 OPC_DINSM = 0x05 | OPC_SPECIAL3,
267 OPC_DINSU = 0x06 | OPC_SPECIAL3,
268 OPC_DINS = 0x07 | OPC_SPECIAL3,
269 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
270 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
271 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
272 };
273
274 /* BSHFL opcodes */
275 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
276
277 enum {
278 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
279 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
280 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
281 };
282
283 /* DBSHFL opcodes */
284 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
285
286 enum {
287 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
288 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
289 };
290
291 /* Coprocessor 0 (rs field) */
292 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
293
294 enum {
295 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
296 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
297 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
298 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
299 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
300 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
301 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
302 OPC_C0 = (0x10 << 21) | OPC_CP0,
303 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
304 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
305 };
306
307 /* MFMC0 opcodes */
308 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
309
310 enum {
311 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
312 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
313 };
314
315 /* Coprocessor 0 (with rs == C0) */
316 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
317
318 enum {
319 OPC_TLBR = 0x01 | OPC_C0,
320 OPC_TLBWI = 0x02 | OPC_C0,
321 OPC_TLBWR = 0x06 | OPC_C0,
322 OPC_TLBP = 0x08 | OPC_C0,
323 OPC_RFE = 0x10 | OPC_C0,
324 OPC_ERET = 0x18 | OPC_C0,
325 OPC_DERET = 0x1F | OPC_C0,
326 OPC_WAIT = 0x20 | OPC_C0,
327 };
328
329 /* Coprocessor 1 (rs field) */
330 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
331
332 enum {
333 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
334 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
335 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
336 OPC_MFHCI = (0x03 << 21) | OPC_CP1,
337 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
338 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
339 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
340 OPC_MTHCI = (0x07 << 21) | OPC_CP1,
341 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
342 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
343 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
344 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
345 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
346 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
347 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
348 };
349
350 enum {
351 OPC_BC1F = (0x00 << 16) | OPC_BC1,
352 OPC_BC1T = (0x01 << 16) | OPC_BC1,
353 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
354 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
355 };
356
357 #define MASK_CP1_BCOND(op) MASK_CP1(op) | (op & (0x3 << 16))
358 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
359
360 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
361
362 enum {
363 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
364 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
365 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
366 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
367 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
368 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
369 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
370 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
371 OPC_BC2 = (0x08 << 21) | OPC_CP2,
372 };
373
374 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
375
376 enum {
377 OPC_LWXC1 = 0x00 | OPC_CP3,
378 OPC_LDXC1 = 0x01 | OPC_CP3,
379 OPC_LUXC1 = 0x05 | OPC_CP3,
380 OPC_SWXC1 = 0x08 | OPC_CP3,
381 OPC_SDXC1 = 0x09 | OPC_CP3,
382 OPC_SUXC1 = 0x0D | OPC_CP3,
383 OPC_PREFX = 0x0F | OPC_CP3,
384 OPC_ALNV_PS = 0x1E | OPC_CP3,
385 OPC_MADD_S = 0x20 | OPC_CP3,
386 OPC_MADD_D = 0x21 | OPC_CP3,
387 OPC_MADD_PS = 0x26 | OPC_CP3,
388 OPC_MSUB_S = 0x28 | OPC_CP3,
389 OPC_MSUB_D = 0x29 | OPC_CP3,
390 OPC_MSUB_PS = 0x2E | OPC_CP3,
391 OPC_NMADD_S = 0x30 | OPC_CP3,
392 OPC_NMADD_D = 0x32 | OPC_CP3,
393 OPC_NMADD_PS= 0x36 | OPC_CP3,
394 OPC_NMSUB_S = 0x38 | OPC_CP3,
395 OPC_NMSUB_D = 0x39 | OPC_CP3,
396 OPC_NMSUB_PS= 0x3E | OPC_CP3,
397 };
398
399
400 const unsigned char *regnames[] =
401 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
402 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
403 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
404 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
405
406 /* Warning: no function for r0 register (hard wired to zero) */
407 #define GEN32(func, NAME) \
408 static GenOpFunc *NAME ## _table [32] = { \
409 NULL, NAME ## 1, NAME ## 2, NAME ## 3, \
410 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
411 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
412 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
413 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
414 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
415 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
416 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
417 }; \
418 static inline void func(int n) \
419 { \
420 NAME ## _table[n](); \
421 }
422
423 /* General purpose registers moves */
424 GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
425 GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
426 GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
427
428 GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
429 GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
430
431 static const char *fregnames[] =
432 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
433 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
434 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
435 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
436
437 # define SFGEN32(func, NAME) \
438 static GenOpFunc *NAME ## _table [32] = { \
439 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
440 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
441 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
442 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
443 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
444 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
445 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
446 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
447 }; \
448 static inline void func(int n) \
449 { \
450 NAME ## _table[n](); \
451 }
452
453 # define DFGEN32(func, NAME) \
454 static GenOpFunc *NAME ## _table [32] = { \
455 NAME ## 0, 0, NAME ## 2, 0, \
456 NAME ## 4, 0, NAME ## 6, 0, \
457 NAME ## 8, 0, NAME ## 10, 0, \
458 NAME ## 12, 0, NAME ## 14, 0, \
459 NAME ## 16, 0, NAME ## 18, 0, \
460 NAME ## 20, 0, NAME ## 22, 0, \
461 NAME ## 24, 0, NAME ## 26, 0, \
462 NAME ## 28, 0, NAME ## 30, 0, \
463 }; \
464 static inline void func(int n) \
465 { \
466 NAME ## _table[n](); \
467 }
468
469 SFGEN32(gen_op_load_fpr_WT0, gen_op_load_fpr_WT0_fpr);
470 SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
471
472 SFGEN32(gen_op_load_fpr_WT1, gen_op_load_fpr_WT1_fpr);
473 SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
474
475 SFGEN32(gen_op_load_fpr_WT2, gen_op_load_fpr_WT2_fpr);
476 SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
477
478 DFGEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fpr);
479 DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
480
481 DFGEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fpr);
482 DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
483
484 DFGEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fpr);
485 DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
486
487 #define FOP_CONDS(fmt) \
488 static GenOpFunc * cond_ ## fmt ## _table[16] = { \
489 gen_op_cmp_ ## fmt ## _f, \
490 gen_op_cmp_ ## fmt ## _un, \
491 gen_op_cmp_ ## fmt ## _eq, \
492 gen_op_cmp_ ## fmt ## _ueq, \
493 gen_op_cmp_ ## fmt ## _olt, \
494 gen_op_cmp_ ## fmt ## _ult, \
495 gen_op_cmp_ ## fmt ## _ole, \
496 gen_op_cmp_ ## fmt ## _ule, \
497 gen_op_cmp_ ## fmt ## _sf, \
498 gen_op_cmp_ ## fmt ## _ngle, \
499 gen_op_cmp_ ## fmt ## _seq, \
500 gen_op_cmp_ ## fmt ## _ngl, \
501 gen_op_cmp_ ## fmt ## _lt, \
502 gen_op_cmp_ ## fmt ## _nge, \
503 gen_op_cmp_ ## fmt ## _le, \
504 gen_op_cmp_ ## fmt ## _ngt, \
505 }; \
506 static inline void gen_cmp_ ## fmt(int n) \
507 { \
508 cond_ ## fmt ## _table[n](); \
509 }
510
511 FOP_CONDS(d)
512 FOP_CONDS(s)
513
514 typedef struct DisasContext {
515 struct TranslationBlock *tb;
516 target_ulong pc, saved_pc;
517 uint32_t opcode;
518 /* Routine used to access memory */
519 int mem_idx;
520 uint32_t hflags, saved_hflags;
521 uint32_t CP0_Status;
522 int bstate;
523 target_ulong btarget;
524 } DisasContext;
525
526 enum {
527 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
528 * exception condition
529 */
530 BS_STOP = 1, /* We want to stop translation for any reason */
531 BS_BRANCH = 2, /* We reached a branch condition */
532 BS_EXCP = 3, /* We reached an exception condition */
533 };
534
535 #if defined MIPS_DEBUG_DISAS
536 #define MIPS_DEBUG(fmt, args...) \
537 do { \
538 if (loglevel & CPU_LOG_TB_IN_ASM) { \
539 fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n", \
540 ctx->pc, ctx->opcode , ##args); \
541 } \
542 } while (0)
543 #else
544 #define MIPS_DEBUG(fmt, args...) do { } while(0)
545 #endif
546
547 #define MIPS_INVAL(op) \
548 do { \
549 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
550 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
551 } while (0)
552
553 #define GEN_LOAD_REG_TN(Tn, Rn) \
554 do { \
555 if (Rn == 0) { \
556 glue(gen_op_reset_, Tn)(); \
557 } else { \
558 glue(gen_op_load_gpr_, Tn)(Rn); \
559 } \
560 } while (0)
561
562 #define GEN_LOAD_IMM_TN(Tn, Imm) \
563 do { \
564 if (Imm == 0) { \
565 glue(gen_op_reset_, Tn)(); \
566 } else { \
567 glue(gen_op_set_, Tn)(Imm); \
568 } \
569 } while (0)
570
571 #define GEN_STORE_TN_REG(Rn, Tn) \
572 do { \
573 if (Rn != 0) { \
574 glue(glue(gen_op_store_, Tn),_gpr)(Rn); \
575 } \
576 } while (0)
577
578 #define GEN_LOAD_FREG_FTN(FTn, Fn) \
579 do { \
580 glue(gen_op_load_fpr_, FTn)(Fn); \
581 } while (0)
582
583 #define GEN_STORE_FTN_FREG(Fn, FTn) \
584 do { \
585 glue(gen_op_store_fpr_, FTn)(Fn); \
586 } while (0)
587
588 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
589 {
590 #if defined MIPS_DEBUG_DISAS
591 if (loglevel & CPU_LOG_TB_IN_ASM) {
592 fprintf(logfile, "hflags %08x saved %08x\n",
593 ctx->hflags, ctx->saved_hflags);
594 }
595 #endif
596 if (do_save_pc && ctx->pc != ctx->saved_pc) {
597 gen_op_save_pc(ctx->pc);
598 ctx->saved_pc = ctx->pc;
599 }
600 if (ctx->hflags != ctx->saved_hflags) {
601 gen_op_save_state(ctx->hflags);
602 ctx->saved_hflags = ctx->hflags;
603 if (ctx->hflags & MIPS_HFLAG_BR) {
604 gen_op_save_breg_target();
605 } else if (ctx->hflags & MIPS_HFLAG_B) {
606 gen_op_save_btarget(ctx->btarget);
607 } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
608 gen_op_save_bcond();
609 gen_op_save_btarget(ctx->btarget);
610 }
611 }
612 }
613
614 static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
615 {
616 #if defined MIPS_DEBUG_DISAS
617 if (loglevel & CPU_LOG_TB_IN_ASM)
618 fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
619 #endif
620 save_cpu_state(ctx, 1);
621 if (err == 0)
622 gen_op_raise_exception(excp);
623 else
624 gen_op_raise_exception_err(excp, err);
625 ctx->bstate = BS_EXCP;
626 }
627
628 static inline void generate_exception (DisasContext *ctx, int excp)
629 {
630 generate_exception_err (ctx, excp, 0);
631 }
632
633 #if defined(CONFIG_USER_ONLY)
634 #define op_ldst(name) gen_op_##name##_raw()
635 #define OP_LD_TABLE(width)
636 #define OP_ST_TABLE(width)
637 #else
638 #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
639 #define OP_LD_TABLE(width) \
640 static GenOpFunc *gen_op_l##width[] = { \
641 &gen_op_l##width##_user, \
642 &gen_op_l##width##_kernel, \
643 }
644 #define OP_ST_TABLE(width) \
645 static GenOpFunc *gen_op_s##width[] = { \
646 &gen_op_s##width##_user, \
647 &gen_op_s##width##_kernel, \
648 }
649 #endif
650
651 #ifdef TARGET_MIPS64
652 OP_LD_TABLE(d);
653 OP_LD_TABLE(dl);
654 OP_LD_TABLE(dr);
655 OP_ST_TABLE(d);
656 OP_ST_TABLE(dl);
657 OP_ST_TABLE(dr);
658 OP_LD_TABLE(ld);
659 OP_ST_TABLE(cd);
660 #endif
661 OP_LD_TABLE(w);
662 OP_LD_TABLE(wu);
663 OP_LD_TABLE(wl);
664 OP_LD_TABLE(wr);
665 OP_ST_TABLE(w);
666 OP_ST_TABLE(wl);
667 OP_ST_TABLE(wr);
668 OP_LD_TABLE(h);
669 OP_LD_TABLE(hu);
670 OP_ST_TABLE(h);
671 OP_LD_TABLE(b);
672 OP_LD_TABLE(bu);
673 OP_ST_TABLE(b);
674 OP_LD_TABLE(l);
675 OP_ST_TABLE(c);
676 OP_LD_TABLE(wc1);
677 OP_ST_TABLE(wc1);
678 OP_LD_TABLE(dc1);
679 OP_ST_TABLE(dc1);
680
681 /* Load and store */
682 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
683 int base, int16_t offset)
684 {
685 const char *opn = "unk";
686
687 if (base == 0) {
688 GEN_LOAD_IMM_TN(T0, offset);
689 } else if (offset == 0) {
690 gen_op_load_gpr_T0(base);
691 } else {
692 gen_op_load_gpr_T0(base);
693 gen_op_set_T1(offset);
694 gen_op_add();
695 }
696 /* Don't do NOP if destination is zero: we must perform the actual
697 * memory access
698 */
699 switch (opc) {
700 #ifdef TARGET_MIPS64
701 case OPC_LD:
702 op_ldst(ld);
703 GEN_STORE_TN_REG(rt, T0);
704 opn = "ld";
705 break;
706 case OPC_LLD:
707 op_ldst(lld);
708 GEN_STORE_TN_REG(rt, T0);
709 opn = "lld";
710 break;
711 case OPC_SD:
712 GEN_LOAD_REG_TN(T1, rt);
713 op_ldst(sd);
714 opn = "sd";
715 break;
716 case OPC_SCD:
717 save_cpu_state(ctx, 1);
718 GEN_LOAD_REG_TN(T1, rt);
719 op_ldst(scd);
720 opn = "scd";
721 break;
722 case OPC_LDL:
723 op_ldst(ldl);
724 GEN_STORE_TN_REG(rt, T0);
725 opn = "ldl";
726 break;
727 case OPC_SDL:
728 GEN_LOAD_REG_TN(T1, rt);
729 op_ldst(sdl);
730 opn = "sdl";
731 break;
732 case OPC_LDR:
733 op_ldst(ldr);
734 GEN_STORE_TN_REG(rt, T0);
735 opn = "ldr";
736 break;
737 case OPC_SDR:
738 GEN_LOAD_REG_TN(T1, rt);
739 op_ldst(sdr);
740 opn = "sdr";
741 break;
742 #endif
743 case OPC_LW:
744 op_ldst(lw);
745 GEN_STORE_TN_REG(rt, T0);
746 opn = "lw";
747 break;
748 case OPC_LWU:
749 op_ldst(lwu);
750 GEN_STORE_TN_REG(rt, T0);
751 opn = "lwu";
752 break;
753 case OPC_SW:
754 GEN_LOAD_REG_TN(T1, rt);
755 op_ldst(sw);
756 opn = "sw";
757 break;
758 case OPC_LH:
759 op_ldst(lh);
760 GEN_STORE_TN_REG(rt, T0);
761 opn = "lh";
762 break;
763 case OPC_SH:
764 GEN_LOAD_REG_TN(T1, rt);
765 op_ldst(sh);
766 opn = "sh";
767 break;
768 case OPC_LHU:
769 op_ldst(lhu);
770 GEN_STORE_TN_REG(rt, T0);
771 opn = "lhu";
772 break;
773 case OPC_LB:
774 op_ldst(lb);
775 GEN_STORE_TN_REG(rt, T0);
776 opn = "lb";
777 break;
778 case OPC_SB:
779 GEN_LOAD_REG_TN(T1, rt);
780 op_ldst(sb);
781 opn = "sb";
782 break;
783 case OPC_LBU:
784 op_ldst(lbu);
785 GEN_STORE_TN_REG(rt, T0);
786 opn = "lbu";
787 break;
788 case OPC_LWL:
789 GEN_LOAD_REG_TN(T1, rt);
790 op_ldst(lwl);
791 GEN_STORE_TN_REG(rt, T0);
792 opn = "lwl";
793 break;
794 case OPC_SWL:
795 GEN_LOAD_REG_TN(T1, rt);
796 op_ldst(swl);
797 opn = "swr";
798 break;
799 case OPC_LWR:
800 GEN_LOAD_REG_TN(T1, rt);
801 op_ldst(lwr);
802 GEN_STORE_TN_REG(rt, T0);
803 opn = "lwr";
804 break;
805 case OPC_SWR:
806 GEN_LOAD_REG_TN(T1, rt);
807 op_ldst(swr);
808 opn = "swr";
809 break;
810 case OPC_LL:
811 op_ldst(ll);
812 GEN_STORE_TN_REG(rt, T0);
813 opn = "ll";
814 break;
815 case OPC_SC:
816 save_cpu_state(ctx, 1);
817 GEN_LOAD_REG_TN(T1, rt);
818 op_ldst(sc);
819 GEN_STORE_TN_REG(rt, T0);
820 opn = "sc";
821 break;
822 default:
823 MIPS_INVAL("load/store");
824 generate_exception(ctx, EXCP_RI);
825 return;
826 }
827 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
828 }
829
830 /* Load and store */
831 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
832 int base, int16_t offset)
833 {
834 const char *opn = "unk";
835
836 if (base == 0) {
837 GEN_LOAD_IMM_TN(T0, offset);
838 } else if (offset == 0) {
839 gen_op_load_gpr_T0(base);
840 } else {
841 gen_op_load_gpr_T0(base);
842 gen_op_set_T1(offset);
843 gen_op_add();
844 }
845 /* Don't do NOP if destination is zero: we must perform the actual
846 * memory access
847 */
848 switch (opc) {
849 case OPC_LWC1:
850 op_ldst(lwc1);
851 GEN_STORE_FTN_FREG(ft, WT0);
852 opn = "lwc1";
853 break;
854 case OPC_SWC1:
855 GEN_LOAD_FREG_FTN(WT0, ft);
856 op_ldst(swc1);
857 opn = "swc1";
858 break;
859 case OPC_LDC1:
860 op_ldst(ldc1);
861 GEN_STORE_FTN_FREG(ft, DT0);
862 opn = "ldc1";
863 break;
864 case OPC_SDC1:
865 GEN_LOAD_FREG_FTN(DT0, ft);
866 op_ldst(sdc1);
867 opn = "sdc1";
868 break;
869 default:
870 MIPS_INVAL("float load/store");
871 generate_exception(ctx, EXCP_RI);
872 return;
873 }
874 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
875 }
876
877 /* Arithmetic with immediate operand */
878 static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
879 int rs, int16_t imm)
880 {
881 uint32_t uimm;
882 const char *opn = "unk";
883
884 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
885 /* if no destination, treat it as a NOP
886 * For addi, we must generate the overflow exception when needed.
887 */
888 MIPS_DEBUG("NOP");
889 return;
890 }
891 uimm = (uint16_t)imm;
892 switch (opc) {
893 case OPC_ADDI:
894 case OPC_ADDIU:
895 #ifdef TARGET_MIPS64
896 case OPC_DADDI:
897 case OPC_DADDIU:
898 #endif
899 case OPC_SLTI:
900 case OPC_SLTIU:
901 uimm = (int32_t)imm; /* Sign extend to 32 bits */
902 /* Fall through. */
903 case OPC_ANDI:
904 case OPC_ORI:
905 case OPC_XORI:
906 GEN_LOAD_REG_TN(T0, rs);
907 GEN_LOAD_IMM_TN(T1, uimm);
908 break;
909 case OPC_LUI:
910 GEN_LOAD_IMM_TN(T0, uimm << 16);
911 break;
912 case OPC_SLL:
913 case OPC_SRA:
914 case OPC_SRL:
915 #ifdef TARGET_MIPS64
916 case OPC_DSLL:
917 case OPC_DSRA:
918 case OPC_DSRL:
919 case OPC_DSLL32:
920 case OPC_DSRA32:
921 case OPC_DSRL32:
922 #endif
923 uimm &= 0x1f;
924 GEN_LOAD_REG_TN(T0, rs);
925 GEN_LOAD_IMM_TN(T1, uimm);
926 break;
927 }
928 switch (opc) {
929 case OPC_ADDI:
930 save_cpu_state(ctx, 1);
931 gen_op_addo();
932 opn = "addi";
933 break;
934 case OPC_ADDIU:
935 gen_op_add();
936 opn = "addiu";
937 break;
938 #ifdef TARGET_MIPS64
939 case OPC_DADDI:
940 save_cpu_state(ctx, 1);
941 gen_op_daddo();
942 opn = "daddi";
943 break;
944 case OPC_DADDIU:
945 gen_op_dadd();
946 opn = "daddiu";
947 break;
948 #endif
949 case OPC_SLTI:
950 gen_op_lt();
951 opn = "slti";
952 break;
953 case OPC_SLTIU:
954 gen_op_ltu();
955 opn = "sltiu";
956 break;
957 case OPC_ANDI:
958 gen_op_and();
959 opn = "andi";
960 break;
961 case OPC_ORI:
962 gen_op_or();
963 opn = "ori";
964 break;
965 case OPC_XORI:
966 gen_op_xor();
967 opn = "xori";
968 break;
969 case OPC_LUI:
970 opn = "lui";
971 break;
972 case OPC_SLL:
973 gen_op_sll();
974 opn = "sll";
975 break;
976 case OPC_SRA:
977 gen_op_sra();
978 opn = "sra";
979 break;
980 case OPC_SRL:
981 switch ((ctx->opcode >> 21) & 0x1f) {
982 case 0:
983 gen_op_srl();
984 opn = "srl";
985 break;
986 case 1:
987 gen_op_rotr();
988 opn = "rotr";
989 break;
990 default:
991 MIPS_INVAL("invalid srl flag");
992 generate_exception(ctx, EXCP_RI);
993 break;
994 }
995 break;
996 #ifdef TARGET_MIPS64
997 case OPC_DSLL:
998 gen_op_dsll();
999 opn = "dsll";
1000 break;
1001 case OPC_DSRA:
1002 gen_op_dsra();
1003 opn = "dsra";
1004 break;
1005 case OPC_DSRL:
1006 switch ((ctx->opcode >> 21) & 0x1f) {
1007 case 0:
1008 gen_op_dsrl();
1009 opn = "dsrl";
1010 break;
1011 case 1:
1012 gen_op_drotr();
1013 opn = "drotr";
1014 break;
1015 default:
1016 MIPS_INVAL("invalid dsrl flag");
1017 generate_exception(ctx, EXCP_RI);
1018 break;
1019 }
1020 break;
1021 case OPC_DSLL32:
1022 gen_op_dsll32();
1023 opn = "dsll32";
1024 break;
1025 case OPC_DSRA32:
1026 gen_op_dsra32();
1027 opn = "dsra32";
1028 break;
1029 case OPC_DSRL32:
1030 switch ((ctx->opcode >> 21) & 0x1f) {
1031 case 0:
1032 gen_op_dsrl32();
1033 opn = "dsrl32";
1034 break;
1035 case 1:
1036 gen_op_drotr32();
1037 opn = "drotr32";
1038 break;
1039 default:
1040 MIPS_INVAL("invalid dsrl32 flag");
1041 generate_exception(ctx, EXCP_RI);
1042 break;
1043 }
1044 break;
1045 #endif
1046 default:
1047 MIPS_INVAL("imm arith");
1048 generate_exception(ctx, EXCP_RI);
1049 return;
1050 }
1051 GEN_STORE_TN_REG(rt, T0);
1052 MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);
1053 }
1054
1055 /* Arithmetic */
1056 static void gen_arith (DisasContext *ctx, uint32_t opc,
1057 int rd, int rs, int rt)
1058 {
1059 const char *opn = "unk";
1060
1061 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1062 && opc != OPC_DADD && opc != OPC_DSUB) {
1063 /* if no destination, treat it as a NOP
1064 * For add & sub, we must generate the overflow exception when needed.
1065 */
1066 MIPS_DEBUG("NOP");
1067 return;
1068 }
1069 GEN_LOAD_REG_TN(T0, rs);
1070 GEN_LOAD_REG_TN(T1, rt);
1071 switch (opc) {
1072 case OPC_ADD:
1073 save_cpu_state(ctx, 1);
1074 gen_op_addo();
1075 opn = "add";
1076 break;
1077 case OPC_ADDU:
1078 gen_op_add();
1079 opn = "addu";
1080 break;
1081 case OPC_SUB:
1082 save_cpu_state(ctx, 1);
1083 gen_op_subo();
1084 opn = "sub";
1085 break;
1086 case OPC_SUBU:
1087 gen_op_sub();
1088 opn = "subu";
1089 break;
1090 #ifdef TARGET_MIPS64
1091 case OPC_DADD:
1092 save_cpu_state(ctx, 1);
1093 gen_op_daddo();
1094 opn = "dadd";
1095 break;
1096 case OPC_DADDU:
1097 gen_op_dadd();
1098 opn = "daddu";
1099 break;
1100 case OPC_DSUB:
1101 save_cpu_state(ctx, 1);
1102 gen_op_dsubo();
1103 opn = "dsub";
1104 break;
1105 case OPC_DSUBU:
1106 gen_op_dsub();
1107 opn = "dsubu";
1108 break;
1109 #endif
1110 case OPC_SLT:
1111 gen_op_lt();
1112 opn = "slt";
1113 break;
1114 case OPC_SLTU:
1115 gen_op_ltu();
1116 opn = "sltu";
1117 break;
1118 case OPC_AND:
1119 gen_op_and();
1120 opn = "and";
1121 break;
1122 case OPC_NOR:
1123 gen_op_nor();
1124 opn = "nor";
1125 break;
1126 case OPC_OR:
1127 gen_op_or();
1128 opn = "or";
1129 break;
1130 case OPC_XOR:
1131 gen_op_xor();
1132 opn = "xor";
1133 break;
1134 case OPC_MUL:
1135 gen_op_mul();
1136 opn = "mul";
1137 break;
1138 case OPC_MOVN:
1139 gen_op_movn(rd);
1140 opn = "movn";
1141 goto print;
1142 case OPC_MOVZ:
1143 gen_op_movz(rd);
1144 opn = "movz";
1145 goto print;
1146 case OPC_SLLV:
1147 gen_op_sllv();
1148 opn = "sllv";
1149 break;
1150 case OPC_SRAV:
1151 gen_op_srav();
1152 opn = "srav";
1153 break;
1154 case OPC_SRLV:
1155 switch ((ctx->opcode >> 6) & 0x1f) {
1156 case 0:
1157 gen_op_srlv();
1158 opn = "srlv";
1159 break;
1160 case 1:
1161 gen_op_rotrv();
1162 opn = "rotrv";
1163 break;
1164 default:
1165 MIPS_INVAL("invalid srlv flag");
1166 generate_exception(ctx, EXCP_RI);
1167 break;
1168 }
1169 break;
1170 #ifdef TARGET_MIPS64
1171 case OPC_DSLLV:
1172 gen_op_dsllv();
1173 opn = "dsllv";
1174 break;
1175 case OPC_DSRAV:
1176 gen_op_dsrav();
1177 opn = "dsrav";
1178 break;
1179 case OPC_DSRLV:
1180 switch ((ctx->opcode >> 6) & 0x1f) {
1181 case 0:
1182 gen_op_dsrlv();
1183 opn = "dsrlv";
1184 break;
1185 case 1:
1186 gen_op_drotrv();
1187 opn = "drotrv";
1188 break;
1189 default:
1190 MIPS_INVAL("invalid dsrlv flag");
1191 generate_exception(ctx, EXCP_RI);
1192 break;
1193 }
1194 break;
1195 #endif
1196 default:
1197 MIPS_INVAL("arith");
1198 generate_exception(ctx, EXCP_RI);
1199 return;
1200 }
1201 GEN_STORE_TN_REG(rd, T0);
1202 print:
1203 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1204 }
1205
1206 /* Arithmetic on HI/LO registers */
1207 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1208 {
1209 const char *opn = "unk";
1210
1211 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1212 /* Treat as a NOP */
1213 MIPS_DEBUG("NOP");
1214 return;
1215 }
1216 switch (opc) {
1217 case OPC_MFHI:
1218 gen_op_load_HI();
1219 GEN_STORE_TN_REG(reg, T0);
1220 opn = "mfhi";
1221 break;
1222 case OPC_MFLO:
1223 gen_op_load_LO();
1224 GEN_STORE_TN_REG(reg, T0);
1225 opn = "mflo";
1226 break;
1227 case OPC_MTHI:
1228 GEN_LOAD_REG_TN(T0, reg);
1229 gen_op_store_HI();
1230 opn = "mthi";
1231 break;
1232 case OPC_MTLO:
1233 GEN_LOAD_REG_TN(T0, reg);
1234 gen_op_store_LO();
1235 opn = "mtlo";
1236 break;
1237 default:
1238 MIPS_INVAL("HILO");
1239 generate_exception(ctx, EXCP_RI);
1240 return;
1241 }
1242 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1243 }
1244
1245 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1246 int rs, int rt)
1247 {
1248 const char *opn = "unk";
1249
1250 GEN_LOAD_REG_TN(T0, rs);
1251 GEN_LOAD_REG_TN(T1, rt);
1252 switch (opc) {
1253 case OPC_DIV:
1254 gen_op_div();
1255 opn = "div";
1256 break;
1257 case OPC_DIVU:
1258 gen_op_divu();
1259 opn = "divu";
1260 break;
1261 case OPC_MULT:
1262 gen_op_mult();
1263 opn = "mult";
1264 break;
1265 case OPC_MULTU:
1266 gen_op_multu();
1267 opn = "multu";
1268 break;
1269 #ifdef TARGET_MIPS64
1270 case OPC_DDIV:
1271 gen_op_ddiv();
1272 opn = "ddiv";
1273 break;
1274 case OPC_DDIVU:
1275 gen_op_ddivu();
1276 opn = "ddivu";
1277 break;
1278 case OPC_DMULT:
1279 gen_op_dmult();
1280 opn = "dmult";
1281 break;
1282 case OPC_DMULTU:
1283 gen_op_dmultu();
1284 opn = "dmultu";
1285 break;
1286 #endif
1287 case OPC_MADD:
1288 gen_op_madd();
1289 opn = "madd";
1290 break;
1291 case OPC_MADDU:
1292 gen_op_maddu();
1293 opn = "maddu";
1294 break;
1295 case OPC_MSUB:
1296 gen_op_msub();
1297 opn = "msub";
1298 break;
1299 case OPC_MSUBU:
1300 gen_op_msubu();
1301 opn = "msubu";
1302 break;
1303 default:
1304 MIPS_INVAL("mul/div");
1305 generate_exception(ctx, EXCP_RI);
1306 return;
1307 }
1308 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1309 }
1310
1311 static void gen_cl (DisasContext *ctx, uint32_t opc,
1312 int rd, int rs)
1313 {
1314 const char *opn = "unk";
1315 if (rd == 0) {
1316 /* Treat as a NOP */
1317 MIPS_DEBUG("NOP");
1318 return;
1319 }
1320 GEN_LOAD_REG_TN(T0, rs);
1321 switch (opc) {
1322 case OPC_CLO:
1323 gen_op_clo();
1324 opn = "clo";
1325 break;
1326 case OPC_CLZ:
1327 gen_op_clz();
1328 opn = "clz";
1329 break;
1330 #ifdef TARGET_MIPS64
1331 case OPC_DCLO:
1332 gen_op_dclo();
1333 opn = "dclo";
1334 break;
1335 case OPC_DCLZ:
1336 gen_op_dclz();
1337 opn = "dclz";
1338 break;
1339 #endif
1340 default:
1341 MIPS_INVAL("CLx");
1342 generate_exception(ctx, EXCP_RI);
1343 return;
1344 }
1345 gen_op_store_T0_gpr(rd);
1346 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1347 }
1348
1349 /* Traps */
1350 static void gen_trap (DisasContext *ctx, uint32_t opc,
1351 int rs, int rt, int16_t imm)
1352 {
1353 int cond;
1354
1355 cond = 0;
1356 /* Load needed operands */
1357 switch (opc) {
1358 case OPC_TEQ:
1359 case OPC_TGE:
1360 case OPC_TGEU:
1361 case OPC_TLT:
1362 case OPC_TLTU:
1363 case OPC_TNE:
1364 /* Compare two registers */
1365 if (rs != rt) {
1366 GEN_LOAD_REG_TN(T0, rs);
1367 GEN_LOAD_REG_TN(T1, rt);
1368 cond = 1;
1369 }
1370 break;
1371 case OPC_TEQI:
1372 case OPC_TGEI:
1373 case OPC_TGEIU:
1374 case OPC_TLTI:
1375 case OPC_TLTIU:
1376 case OPC_TNEI:
1377 /* Compare register to immediate */
1378 if (rs != 0 || imm != 0) {
1379 GEN_LOAD_REG_TN(T0, rs);
1380 GEN_LOAD_IMM_TN(T1, (int32_t)imm);
1381 cond = 1;
1382 }
1383 break;
1384 }
1385 if (cond == 0) {
1386 switch (opc) {
1387 case OPC_TEQ: /* rs == rs */
1388 case OPC_TEQI: /* r0 == 0 */
1389 case OPC_TGE: /* rs >= rs */
1390 case OPC_TGEI: /* r0 >= 0 */
1391 case OPC_TGEU: /* rs >= rs unsigned */
1392 case OPC_TGEIU: /* r0 >= 0 unsigned */
1393 /* Always trap */
1394 gen_op_set_T0(1);
1395 break;
1396 case OPC_TLT: /* rs < rs */
1397 case OPC_TLTI: /* r0 < 0 */
1398 case OPC_TLTU: /* rs < rs unsigned */
1399 case OPC_TLTIU: /* r0 < 0 unsigned */
1400 case OPC_TNE: /* rs != rs */
1401 case OPC_TNEI: /* r0 != 0 */
1402 /* Never trap: treat as NOP */
1403 return;
1404 default:
1405 MIPS_INVAL("TRAP");
1406 generate_exception(ctx, EXCP_RI);
1407 return;
1408 }
1409 } else {
1410 switch (opc) {
1411 case OPC_TEQ:
1412 case OPC_TEQI:
1413 gen_op_eq();
1414 break;
1415 case OPC_TGE:
1416 case OPC_TGEI:
1417 gen_op_ge();
1418 break;
1419 case OPC_TGEU:
1420 case OPC_TGEIU:
1421 gen_op_geu();
1422 break;
1423 case OPC_TLT:
1424 case OPC_TLTI:
1425 gen_op_lt();
1426 break;
1427 case OPC_TLTU:
1428 case OPC_TLTIU:
1429 gen_op_ltu();
1430 break;
1431 case OPC_TNE:
1432 case OPC_TNEI:
1433 gen_op_ne();
1434 break;
1435 default:
1436 MIPS_INVAL("TRAP");
1437 generate_exception(ctx, EXCP_RI);
1438 return;
1439 }
1440 }
1441 save_cpu_state(ctx, 1);
1442 gen_op_trap();
1443 ctx->bstate = BS_STOP;
1444 }
1445
1446 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1447 {
1448 TranslationBlock *tb;
1449 tb = ctx->tb;
1450 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1451 if (n == 0)
1452 gen_op_goto_tb0(TBPARAM(tb));
1453 else
1454 gen_op_goto_tb1(TBPARAM(tb));
1455 gen_op_save_pc(dest);
1456 gen_op_set_T0((long)tb + n);
1457 } else {
1458 gen_op_save_pc(dest);
1459 gen_op_reset_T0();
1460 }
1461 gen_op_exit_tb();
1462 }
1463
1464 /* Branches (before delay slot) */
1465 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1466 int rs, int rt, int32_t offset)
1467 {
1468 target_ulong btarget = -1;
1469 int blink = 0;
1470 int bcond = 0;
1471
1472 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1473 if (loglevel & CPU_LOG_TB_IN_ASM) {
1474 fprintf(logfile,
1475 "undefined branch in delay slot at PC " TARGET_FMT_lx "\n",
1476 ctx->pc);
1477 }
1478 MIPS_INVAL("branch/jump in bdelay slot");
1479 generate_exception(ctx, EXCP_RI);
1480 return;
1481 }
1482
1483 /* Load needed operands */
1484 switch (opc) {
1485 case OPC_BEQ:
1486 case OPC_BEQL:
1487 case OPC_BNE:
1488 case OPC_BNEL:
1489 /* Compare two registers */
1490 if (rs != rt) {
1491 GEN_LOAD_REG_TN(T0, rs);
1492 GEN_LOAD_REG_TN(T1, rt);
1493 bcond = 1;
1494 }
1495 btarget = ctx->pc + 4 + offset;
1496 break;
1497 case OPC_BGEZ:
1498 case OPC_BGEZAL:
1499 case OPC_BGEZALL:
1500 case OPC_BGEZL:
1501 case OPC_BGTZ:
1502 case OPC_BGTZL:
1503 case OPC_BLEZ:
1504 case OPC_BLEZL:
1505 case OPC_BLTZ:
1506 case OPC_BLTZAL:
1507 case OPC_BLTZALL:
1508 case OPC_BLTZL:
1509 /* Compare to zero */
1510 if (rs != 0) {
1511 gen_op_load_gpr_T0(rs);
1512 bcond = 1;
1513 }
1514 btarget = ctx->pc + 4 + offset;
1515 break;
1516 case OPC_J:
1517 case OPC_JAL:
1518 /* Jump to immediate */
1519 btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | offset;
1520 break;
1521 case OPC_JR:
1522 case OPC_JALR:
1523 /* Jump to register */
1524 if (offset != 0 && offset != 16) {
1525 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1526 others are reserved. */
1527 generate_exception(ctx, EXCP_RI);
1528 return;
1529 }
1530 GEN_LOAD_REG_TN(T2, rs);
1531 break;
1532 default:
1533 MIPS_INVAL("branch/jump");
1534 generate_exception(ctx, EXCP_RI);
1535 return;
1536 }
1537 if (bcond == 0) {
1538 /* No condition to be computed */
1539 switch (opc) {
1540 case OPC_BEQ: /* rx == rx */
1541 case OPC_BEQL: /* rx == rx likely */
1542 case OPC_BGEZ: /* 0 >= 0 */
1543 case OPC_BGEZL: /* 0 >= 0 likely */
1544 case OPC_BLEZ: /* 0 <= 0 */
1545 case OPC_BLEZL: /* 0 <= 0 likely */
1546 /* Always take */
1547 ctx->hflags |= MIPS_HFLAG_B;
1548 MIPS_DEBUG("balways");
1549 break;
1550 case OPC_BGEZAL: /* 0 >= 0 */
1551 case OPC_BGEZALL: /* 0 >= 0 likely */
1552 /* Always take and link */
1553 blink = 31;
1554 ctx->hflags |= MIPS_HFLAG_B;
1555 MIPS_DEBUG("balways and link");
1556 break;
1557 case OPC_BNE: /* rx != rx */
1558 case OPC_BGTZ: /* 0 > 0 */
1559 case OPC_BLTZ: /* 0 < 0 */
1560 /* Treated as NOP */
1561 MIPS_DEBUG("bnever (NOP)");
1562 return;
1563 case OPC_BLTZAL: /* 0 < 0 */
1564 gen_op_set_T0(ctx->pc + 8);
1565 gen_op_store_T0_gpr(31);
1566 MIPS_DEBUG("bnever and link");
1567 return;
1568 case OPC_BLTZALL: /* 0 < 0 likely */
1569 gen_op_set_T0(ctx->pc + 8);
1570 gen_op_store_T0_gpr(31);
1571 /* Skip the instruction in the delay slot */
1572 MIPS_DEBUG("bnever, link and skip");
1573 ctx->pc += 4;
1574 return;
1575 case OPC_BNEL: /* rx != rx likely */
1576 case OPC_BGTZL: /* 0 > 0 likely */
1577 case OPC_BLTZL: /* 0 < 0 likely */
1578 /* Skip the instruction in the delay slot */
1579 MIPS_DEBUG("bnever and skip");
1580 ctx->pc += 4;
1581 return;
1582 case OPC_J:
1583 ctx->hflags |= MIPS_HFLAG_B;
1584 MIPS_DEBUG("j %08x", btarget);
1585 break;
1586 case OPC_JAL:
1587 blink = 31;
1588 ctx->hflags |= MIPS_HFLAG_B;
1589 MIPS_DEBUG("jal %08x", btarget);
1590 break;
1591 case OPC_JR:
1592 ctx->hflags |= MIPS_HFLAG_BR;
1593 MIPS_DEBUG("jr %s", regnames[rs]);
1594 break;
1595 case OPC_JALR:
1596 blink = rt;
1597 ctx->hflags |= MIPS_HFLAG_BR;
1598 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1599 break;
1600 default:
1601 MIPS_INVAL("branch/jump");
1602 generate_exception(ctx, EXCP_RI);
1603 return;
1604 }
1605 } else {
1606 switch (opc) {
1607 case OPC_BEQ:
1608 gen_op_eq();
1609 MIPS_DEBUG("beq %s, %s, %08x",
1610 regnames[rs], regnames[rt], btarget);
1611 goto not_likely;
1612 case OPC_BEQL:
1613 gen_op_eq();
1614 MIPS_DEBUG("beql %s, %s, %08x",
1615 regnames[rs], regnames[rt], btarget);
1616 goto likely;
1617 case OPC_BNE:
1618 gen_op_ne();
1619 MIPS_DEBUG("bne %s, %s, %08x",
1620 regnames[rs], regnames[rt], btarget);
1621 goto not_likely;
1622 case OPC_BNEL:
1623 gen_op_ne();
1624 MIPS_DEBUG("bnel %s, %s, %08x",
1625 regnames[rs], regnames[rt], btarget);
1626 goto likely;
1627 case OPC_BGEZ:
1628 gen_op_gez();
1629 MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
1630 goto not_likely;
1631 case OPC_BGEZL:
1632 gen_op_gez();
1633 MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
1634 goto likely;
1635 case OPC_BGEZAL:
1636 gen_op_gez();
1637 MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
1638 blink = 31;
1639 goto not_likely;
1640 case OPC_BGEZALL:
1641 gen_op_gez();
1642 blink = 31;
1643 MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
1644 goto likely;
1645 case OPC_BGTZ:
1646 gen_op_gtz();
1647 MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
1648 goto not_likely;
1649 case OPC_BGTZL:
1650 gen_op_gtz();
1651 MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
1652 goto likely;
1653 case OPC_BLEZ:
1654 gen_op_lez();
1655 MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
1656 goto not_likely;
1657 case OPC_BLEZL:
1658 gen_op_lez();
1659 MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
1660 goto likely;
1661 case OPC_BLTZ:
1662 gen_op_ltz();
1663 MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
1664 goto not_likely;
1665 case OPC_BLTZL:
1666 gen_op_ltz();
1667 MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
1668 goto likely;
1669 case OPC_BLTZAL:
1670 gen_op_ltz();
1671 blink = 31;
1672 MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1673 not_likely:
1674 ctx->hflags |= MIPS_HFLAG_BC;
1675 break;
1676 case OPC_BLTZALL:
1677 gen_op_ltz();
1678 blink = 31;
1679 MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1680 likely:
1681 ctx->hflags |= MIPS_HFLAG_BL;
1682 break;
1683 default:
1684 MIPS_INVAL("conditional branch/jump");
1685 generate_exception(ctx, EXCP_RI);
1686 return;
1687 }
1688 gen_op_set_bcond();
1689 }
1690 MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1691 blink, ctx->hflags, btarget);
1692 ctx->btarget = btarget;
1693 if (blink > 0) {
1694 gen_op_set_T0(ctx->pc + 8);
1695 gen_op_store_T0_gpr(blink);
1696 }
1697 }
1698
1699 /* special3 bitfield operations */
1700 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1701 int rs, int lsb, int msb)
1702 {
1703 GEN_LOAD_REG_TN(T1, rs);
1704 switch (opc) {
1705 case OPC_EXT:
1706 if (lsb + msb > 31)
1707 goto fail;
1708 gen_op_ext(lsb, msb + 1);
1709 break;
1710 case OPC_DEXTM:
1711 if (lsb + msb > 63)
1712 goto fail;
1713 gen_op_ext(lsb, msb + 1 + 32);
1714 break;
1715 case OPC_DEXTU:
1716 if (lsb + msb > 63)
1717 goto fail;
1718 gen_op_ext(lsb + 32, msb + 1);
1719 break;
1720 case OPC_DEXT:
1721 gen_op_ext(lsb, msb + 1);
1722 break;
1723 case OPC_INS:
1724 if (lsb > msb)
1725 goto fail;
1726 GEN_LOAD_REG_TN(T0, rt);
1727 gen_op_ins(lsb, msb - lsb + 1);
1728 break;
1729 case OPC_DINSM:
1730 if (lsb > msb)
1731 goto fail;
1732 GEN_LOAD_REG_TN(T0, rt);
1733 gen_op_ins(lsb, msb - lsb + 1 + 32);
1734 break;
1735 case OPC_DINSU:
1736 if (lsb > msb)
1737 goto fail;
1738 GEN_LOAD_REG_TN(T0, rt);
1739 gen_op_ins(lsb + 32, msb - lsb + 1);
1740 break;
1741 case OPC_DINS:
1742 if (lsb > msb)
1743 goto fail;
1744 GEN_LOAD_REG_TN(T0, rt);
1745 gen_op_ins(lsb, msb - lsb + 1);
1746 break;
1747 default:
1748 fail:
1749 MIPS_INVAL("bitops");
1750 generate_exception(ctx, EXCP_RI);
1751 return;
1752 }
1753 GEN_STORE_TN_REG(rt, T0);
1754 }
1755
1756 /* CP0 (MMU and control) */
1757 static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
1758 {
1759 const char *rn = "invalid";
1760
1761 switch (reg) {
1762 case 0:
1763 switch (sel) {
1764 case 0:
1765 gen_op_mfc0_index();
1766 rn = "Index";
1767 break;
1768 case 1:
1769 // gen_op_mfc0_mvpcontrol(); /* MT ASE */
1770 rn = "MVPControl";
1771 // break;
1772 case 2:
1773 // gen_op_mfc0_mvpconf0(); /* MT ASE */
1774 rn = "MVPConf0";
1775 // break;
1776 case 3:
1777 // gen_op_mfc0_mvpconf1(); /* MT ASE */
1778 rn = "MVPConf1";
1779 // break;
1780 default:
1781 goto die;
1782 }
1783 break;
1784 case 1:
1785 switch (sel) {
1786 case 0:
1787 gen_op_mfc0_random();
1788 rn = "Random";
1789 break;
1790 case 1:
1791 // gen_op_mfc0_vpecontrol(); /* MT ASE */
1792 rn = "VPEControl";
1793 // break;
1794 case 2:
1795 // gen_op_mfc0_vpeconf0(); /* MT ASE */
1796 rn = "VPEConf0";
1797 // break;
1798 case 3:
1799 // gen_op_mfc0_vpeconf1(); /* MT ASE */
1800 rn = "VPEConf1";
1801 // break;
1802 case 4:
1803 // gen_op_mfc0_YQMask(); /* MT ASE */
1804 rn = "YQMask";
1805 // break;
1806 case 5:
1807 // gen_op_mfc0_vpeschedule(); /* MT ASE */
1808 rn = "VPESchedule";
1809 // break;
1810 case 6:
1811 // gen_op_mfc0_vpeschefback(); /* MT ASE */
1812 rn = "VPEScheFBack";
1813 // break;
1814 case 7:
1815 // gen_op_mfc0_vpeopt(); /* MT ASE */
1816 rn = "VPEOpt";
1817 // break;
1818 default:
1819 goto die;
1820 }
1821 break;
1822 case 2:
1823 switch (sel) {
1824 case 0:
1825 gen_op_mfc0_entrylo0();
1826 rn = "EntryLo0";
1827 break;
1828 case 1:
1829 // gen_op_mfc0_tcstatus(); /* MT ASE */
1830 rn = "TCStatus";
1831 // break;
1832 case 2:
1833 // gen_op_mfc0_tcbind(); /* MT ASE */
1834 rn = "TCBind";
1835 // break;
1836 case 3:
1837 // gen_op_mfc0_tcrestart(); /* MT ASE */
1838 rn = "TCRestart";
1839 // break;
1840 case 4:
1841 // gen_op_mfc0_tchalt(); /* MT ASE */
1842 rn = "TCHalt";
1843 // break;
1844 case 5:
1845 // gen_op_mfc0_tccontext(); /* MT ASE */
1846 rn = "TCContext";
1847 // break;
1848 case 6:
1849 // gen_op_mfc0_tcschedule(); /* MT ASE */
1850 rn = "TCSchedule";
1851 // break;
1852 case 7:
1853 // gen_op_mfc0_tcschefback(); /* MT ASE */
1854 rn = "TCScheFBack";
1855 // break;
1856 default:
1857 goto die;
1858 }
1859 break;
1860 case 3:
1861 switch (sel) {
1862 case 0:
1863 gen_op_mfc0_entrylo1();
1864 rn = "EntryLo1";
1865 break;
1866 default:
1867 goto die;
1868 }
1869 break;
1870 case 4:
1871 switch (sel) {
1872 case 0:
1873 gen_op_mfc0_context();
1874 rn = "Context";
1875 break;
1876 case 1:
1877 // gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
1878 rn = "ContextConfig";
1879 // break;
1880 default:
1881 goto die;
1882 }
1883 break;
1884 case 5:
1885 switch (sel) {
1886 case 0:
1887 gen_op_mfc0_pagemask();
1888 rn = "PageMask";
1889 break;
1890 case 1:
1891 gen_op_mfc0_pagegrain();
1892 rn = "PageGrain";
1893 break;
1894 default:
1895 goto die;
1896 }
1897 break;
1898 case 6:
1899 switch (sel) {
1900 case 0:
1901 gen_op_mfc0_wired();
1902 rn = "Wired";
1903 break;
1904 case 1:
1905 // gen_op_mfc0_srsconf0(); /* shadow registers */
1906 rn = "SRSConf0";
1907 // break;
1908 case 2:
1909 // gen_op_mfc0_srsconf1(); /* shadow registers */
1910 rn = "SRSConf1";
1911 // break;
1912 case 3:
1913 // gen_op_mfc0_srsconf2(); /* shadow registers */
1914 rn = "SRSConf2";
1915 // break;
1916 case 4:
1917 // gen_op_mfc0_srsconf3(); /* shadow registers */
1918 rn = "SRSConf3";
1919 // break;
1920 case 5:
1921 // gen_op_mfc0_srsconf4(); /* shadow registers */
1922 rn = "SRSConf4";
1923 // break;
1924 default:
1925 goto die;
1926 }
1927 break;
1928 case 7:
1929 switch (sel) {
1930 case 0:
1931 gen_op_mfc0_hwrena();
1932 rn = "HWREna";
1933 break;
1934 default:
1935 goto die;
1936 }
1937 break;
1938 case 8:
1939 switch (sel) {
1940 case 0:
1941 gen_op_mfc0_badvaddr();
1942 rn = "BadVaddr";
1943 break;
1944 default:
1945 goto die;
1946 }
1947 break;
1948 case 9:
1949 switch (sel) {
1950 case 0:
1951 gen_op_mfc0_count();
1952 rn = "Count";
1953 break;
1954 /* 6,7 are implementation dependent */
1955 default:
1956 goto die;
1957 }
1958 break;
1959 case 10:
1960 switch (sel) {
1961 case 0:
1962 gen_op_mfc0_entryhi();
1963 rn = "EntryHi";
1964 break;
1965 default:
1966 goto die;
1967 }
1968 break;
1969 case 11:
1970 switch (sel) {
1971 case 0:
1972 gen_op_mfc0_compare();
1973 rn = "Compare";
1974 break;
1975 /* 6,7 are implementation dependent */
1976 default:
1977 goto die;
1978 }
1979 break;
1980 case 12:
1981 switch (sel) {
1982 case 0:
1983 gen_op_mfc0_status();
1984 rn = "Status";
1985 break;
1986 case 1:
1987 gen_op_mfc0_intctl();
1988 rn = "IntCtl";
1989 break;
1990 case 2:
1991 gen_op_mfc0_srsctl();
1992 rn = "SRSCtl";
1993 break;
1994 case 3:
1995 // gen_op_mfc0_srsmap(); /* shadow registers */
1996 rn = "SRSMap";
1997 // break;
1998 default:
1999 goto die;
2000 }
2001 break;
2002 case 13:
2003 switch (sel) {
2004 case 0:
2005 gen_op_mfc0_cause();
2006 rn = "Cause";
2007 break;
2008 default:
2009 goto die;
2010 }
2011 break;
2012 case 14:
2013 switch (sel) {
2014 case 0:
2015 gen_op_mfc0_epc();
2016 rn = "EPC";
2017 break;
2018 default:
2019 goto die;
2020 }
2021 break;
2022 case 15:
2023 switch (sel) {
2024 case 0:
2025 gen_op_mfc0_prid();
2026 rn = "PRid";
2027 break;
2028 case 1:
2029 gen_op_mfc0_ebase();
2030 rn = "EBase";
2031 break;
2032 default:
2033 goto die;
2034 }
2035 break;
2036 case 16:
2037 switch (sel) {
2038 case 0:
2039 gen_op_mfc0_config0();
2040 rn = "Config";
2041 break;
2042 case 1:
2043 gen_op_mfc0_config1();
2044 rn = "Config1";
2045 break;
2046 case 2:
2047 gen_op_mfc0_config2();
2048 rn = "Config2";
2049 break;
2050 case 3:
2051 gen_op_mfc0_config3();
2052 rn = "Config3";
2053 break;
2054 /* 4,5 are reserved */
2055 /* 6,7 are implementation dependent */
2056 case 6:
2057 gen_op_mfc0_config6();
2058 rn = "Config6";
2059 break;
2060 case 7:
2061 gen_op_mfc0_config7();
2062 rn = "Config7";
2063 break;
2064 default:
2065 goto die;
2066 }
2067 break;
2068 case 17:
2069 switch (sel) {
2070 case 0:
2071 gen_op_mfc0_lladdr();
2072 rn = "LLAddr";
2073 break;
2074 default:
2075 goto die;
2076 }
2077 break;
2078 case 18:
2079 switch (sel) {
2080 case 0:
2081 gen_op_mfc0_watchlo0();
2082 rn = "WatchLo";
2083 break;
2084 case 1:
2085 // gen_op_mfc0_watchlo1();
2086 rn = "WatchLo1";
2087 // break;
2088 case 2:
2089 // gen_op_mfc0_watchlo2();
2090 rn = "WatchLo2";
2091 // break;
2092 case 3:
2093 // gen_op_mfc0_watchlo3();
2094 rn = "WatchLo3";
2095 // break;
2096 case 4:
2097 // gen_op_mfc0_watchlo4();
2098 rn = "WatchLo4";
2099 // break;
2100 case 5:
2101 // gen_op_mfc0_watchlo5();
2102 rn = "WatchLo5";
2103 // break;
2104 case 6:
2105 // gen_op_mfc0_watchlo6();
2106 rn = "WatchLo6";
2107 // break;
2108 case 7:
2109 // gen_op_mfc0_watchlo7();
2110 rn = "WatchLo7";
2111 // break;
2112 default:
2113 goto die;
2114 }
2115 break;
2116 case 19:
2117 switch (sel) {
2118 case 0:
2119 gen_op_mfc0_watchhi0();
2120 rn = "WatchHi";
2121 break;
2122 case 1:
2123 // gen_op_mfc0_watchhi1();
2124 rn = "WatchHi1";
2125 // break;
2126 case 2:
2127 // gen_op_mfc0_watchhi2();
2128 rn = "WatchHi2";
2129 // break;
2130 case 3:
2131 // gen_op_mfc0_watchhi3();
2132 rn = "WatchHi3";
2133 // break;
2134 case 4:
2135 // gen_op_mfc0_watchhi4();
2136 rn = "WatchHi4";
2137 // break;
2138 case 5:
2139 // gen_op_mfc0_watchhi5();
2140 rn = "WatchHi5";
2141 // break;
2142 case 6:
2143 // gen_op_mfc0_watchhi6();
2144 rn = "WatchHi6";
2145 // break;
2146 case 7:
2147 // gen_op_mfc0_watchhi7();
2148 rn = "WatchHi7";
2149 // break;
2150 default:
2151 goto die;
2152 }
2153 break;
2154 case 20:
2155 switch (sel) {
2156 case 0:
2157 /* 64 bit MMU only */
2158 gen_op_mfc0_xcontext();
2159 rn = "XContext";
2160 break;
2161 default:
2162 goto die;
2163 }
2164 break;
2165 case 21:
2166 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2167 switch (sel) {
2168 case 0:
2169 gen_op_mfc0_framemask();
2170 rn = "Framemask";
2171 break;
2172 default:
2173 goto die;
2174 }
2175 break;
2176 case 22:
2177 /* ignored */
2178 rn = "'Diagnostic"; /* implementation dependent */
2179 break;
2180 case 23:
2181 switch (sel) {
2182 case 0:
2183 gen_op_mfc0_debug(); /* EJTAG support */
2184 rn = "Debug";
2185 break;
2186 case 1:
2187 // gen_op_mfc0_tracecontrol(); /* PDtrace support */
2188 rn = "TraceControl";
2189 // break;
2190 case 2:
2191 // gen_op_mfc0_tracecontrol2(); /* PDtrace support */
2192 rn = "TraceControl2";
2193 // break;
2194 case 3:
2195 // gen_op_mfc0_usertracedata(); /* PDtrace support */
2196 rn = "UserTraceData";
2197 // break;
2198 case 4:
2199 // gen_op_mfc0_debug(); /* PDtrace support */
2200 rn = "TraceBPC";
2201 // break;
2202 default:
2203 goto die;
2204 }
2205 break;
2206 case 24:
2207 switch (sel) {
2208 case 0:
2209 gen_op_mfc0_depc(); /* EJTAG support */
2210 rn = "DEPC";
2211 break;
2212 default:
2213 goto die;
2214 }
2215 break;
2216 case 25:
2217 switch (sel) {
2218 case 0:
2219 gen_op_mfc0_performance0();
2220 rn = "Performance0";
2221 break;
2222 case 1:
2223 // gen_op_mfc0_performance1();
2224 rn = "Performance1";
2225 // break;
2226 case 2:
2227 // gen_op_mfc0_performance2();
2228 rn = "Performance2";
2229 // break;
2230 case 3:
2231 // gen_op_mfc0_performance3();
2232 rn = "Performance3";
2233 // break;
2234 case 4:
2235 // gen_op_mfc0_performance4();
2236 rn = "Performance4";
2237 // break;
2238 case 5:
2239 // gen_op_mfc0_performance5();
2240 rn = "Performance5";
2241 // break;
2242 case 6:
2243 // gen_op_mfc0_performance6();
2244 rn = "Performance6";
2245 // break;
2246 case 7:
2247 // gen_op_mfc0_performance7();
2248 rn = "Performance7";
2249 // break;
2250 default:
2251 goto die;
2252 }
2253 break;
2254 case 26:
2255 rn = "ECC";
2256 break;
2257 case 27:
2258 switch (sel) {
2259 /* ignored */
2260 case 0 ... 3:
2261 rn = "CacheErr";
2262 break;
2263 default:
2264 goto die;
2265 }
2266 break;
2267 case 28:
2268 switch (sel) {
2269 case 0:
2270 case 2:
2271 case 4:
2272 case 6:
2273 gen_op_mfc0_taglo();
2274 rn = "TagLo";
2275 break;
2276 case 1:
2277 case 3:
2278 case 5:
2279 case 7:
2280 gen_op_mfc0_datalo();
2281 rn = "DataLo";
2282 break;
2283 default:
2284 goto die;
2285 }
2286 break;
2287 case 29:
2288 switch (sel) {
2289 case 0:
2290 case 2:
2291 case 4:
2292 case 6:
2293 gen_op_mfc0_taghi();
2294 rn = "TagHi";
2295 break;
2296 case 1:
2297 case 3:
2298 case 5:
2299 case 7:
2300 gen_op_mfc0_datahi();
2301 rn = "DataHi";
2302 break;
2303 default:
2304 goto die;
2305 }
2306 break;
2307 case 30:
2308 switch (sel) {
2309 case 0:
2310 gen_op_mfc0_errorepc();
2311 rn = "ErrorEPC";
2312 break;
2313 default:
2314 goto die;
2315 }
2316 break;
2317 case 31:
2318 switch (sel) {
2319 case 0:
2320 gen_op_mfc0_desave(); /* EJTAG support */
2321 rn = "DESAVE";
2322 break;
2323 default:
2324 goto die;
2325 }
2326 break;
2327 default:
2328 goto die;
2329 }
2330 #if defined MIPS_DEBUG_DISAS
2331 if (loglevel & CPU_LOG_TB_IN_ASM) {
2332 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2333 rn, reg, sel);
2334 }
2335 #endif
2336 return;
2337
2338 die:
2339 #if defined MIPS_DEBUG_DISAS
2340 if (loglevel & CPU_LOG_TB_IN_ASM) {
2341 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2342 rn, reg, sel);
2343 }
2344 #endif
2345 generate_exception(ctx, EXCP_RI);
2346 }
2347
2348 static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2349 {
2350 const char *rn = "invalid";
2351
2352 switch (reg) {
2353 case 0:
2354 switch (sel) {
2355 case 0:
2356 gen_op_mtc0_index();
2357 rn = "Index";
2358 break;
2359 case 1:
2360 // gen_op_mtc0_mvpcontrol(); /* MT ASE */
2361 rn = "MVPControl";
2362 // break;
2363 case 2:
2364 // gen_op_mtc0_mvpconf0(); /* MT ASE */
2365 rn = "MVPConf0";
2366 // break;
2367 case 3:
2368 // gen_op_mtc0_mvpconf1(); /* MT ASE */
2369 rn = "MVPConf1";
2370 // break;
2371 default:
2372 goto die;
2373 }
2374 break;
2375 case 1:
2376 switch (sel) {
2377 case 0:
2378 /* ignored */
2379 rn = "Random";
2380 break;
2381 case 1:
2382 // gen_op_mtc0_vpecontrol(); /* MT ASE */
2383 rn = "VPEControl";
2384 // break;
2385 case 2:
2386 // gen_op_mtc0_vpeconf0(); /* MT ASE */
2387 rn = "VPEConf0";
2388 // break;
2389 case 3:
2390 // gen_op_mtc0_vpeconf1(); /* MT ASE */
2391 rn = "VPEConf1";
2392 // break;
2393 case 4:
2394 // gen_op_mtc0_YQMask(); /* MT ASE */
2395 rn = "YQMask";
2396 // break;
2397 case 5:
2398 // gen_op_mtc0_vpeschedule(); /* MT ASE */
2399 rn = "VPESchedule";
2400 // break;
2401 case 6:
2402 // gen_op_mtc0_vpeschefback(); /* MT ASE */
2403 rn = "VPEScheFBack";
2404 // break;
2405 case 7:
2406 // gen_op_mtc0_vpeopt(); /* MT ASE */
2407 rn = "VPEOpt";
2408 // break;
2409 default:
2410 goto die;
2411 }
2412 break;
2413 case 2:
2414 switch (sel) {
2415 case 0:
2416 gen_op_mtc0_entrylo0();
2417 rn = "EntryLo0";
2418 break;
2419 case 1:
2420 // gen_op_mtc0_tcstatus(); /* MT ASE */
2421 rn = "TCStatus";
2422 // break;
2423 case 2:
2424 // gen_op_mtc0_tcbind(); /* MT ASE */
2425 rn = "TCBind";
2426 // break;
2427 case 3:
2428 // gen_op_mtc0_tcrestart(); /* MT ASE */
2429 rn = "TCRestart";
2430 // break;
2431 case 4:
2432 // gen_op_mtc0_tchalt(); /* MT ASE */
2433 rn = "TCHalt";
2434 // break;
2435 case 5:
2436 // gen_op_mtc0_tccontext(); /* MT ASE */
2437 rn = "TCContext";
2438 // break;
2439 case 6:
2440 // gen_op_mtc0_tcschedule(); /* MT ASE */
2441 rn = "TCSchedule";
2442 // break;
2443 case 7:
2444 // gen_op_mtc0_tcschefback(); /* MT ASE */
2445 rn = "TCScheFBack";
2446 // break;
2447 default:
2448 goto die;
2449 }
2450 break;
2451 case 3:
2452 switch (sel) {
2453 case 0:
2454 gen_op_mtc0_entrylo1();
2455 rn = "EntryLo1";
2456 break;
2457 default:
2458 goto die;
2459 }
2460 break;
2461 case 4:
2462 switch (sel) {
2463 case 0:
2464 gen_op_mtc0_context();
2465 rn = "Context";
2466 break;
2467 case 1:
2468 // gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
2469 rn = "ContextConfig";
2470 // break;
2471 default:
2472 goto die;
2473 }
2474 break;
2475 case 5:
2476 switch (sel) {
2477 case 0:
2478 gen_op_mtc0_pagemask();
2479 rn = "PageMask";
2480 break;
2481 case 1:
2482 gen_op_mtc0_pagegrain();
2483 rn = "PageGrain";
2484 break;
2485 default:
2486 goto die;
2487 }
2488 break;
2489 case 6:
2490 switch (sel) {
2491 case 0:
2492 gen_op_mtc0_wired();
2493 rn = "Wired";
2494 break;
2495 case 1:
2496 // gen_op_mtc0_srsconf0(); /* shadow registers */
2497 rn = "SRSConf0";
2498 // break;
2499 case 2:
2500 // gen_op_mtc0_srsconf1(); /* shadow registers */
2501 rn = "SRSConf1";
2502 // break;
2503 case 3:
2504 // gen_op_mtc0_srsconf2(); /* shadow registers */
2505 rn = "SRSConf2";
2506 // break;
2507 case 4:
2508 // gen_op_mtc0_srsconf3(); /* shadow registers */
2509 rn = "SRSConf3";
2510 // break;
2511 case 5:
2512 // gen_op_mtc0_srsconf4(); /* shadow registers */
2513 rn = "SRSConf4";
2514 // break;
2515 default:
2516 goto die;
2517 }
2518 break;
2519 case 7:
2520 switch (sel) {
2521 case 0:
2522 gen_op_mtc0_hwrena();
2523 rn = "HWREna";
2524 break;
2525 default:
2526 goto die;
2527 }
2528 break;
2529 case 8:
2530 /* ignored */
2531 rn = "BadVaddr";
2532 break;
2533 case 9:
2534 switch (sel) {
2535 case 0:
2536 gen_op_mtc0_count();
2537 rn = "Count";
2538 break;
2539 /* 6,7 are implementation dependent */
2540 default:
2541 goto die;
2542 }
2543 /* Stop translation as we may have switched the execution mode */
2544 ctx->bstate = BS_STOP;
2545 break;
2546 case 10:
2547 switch (sel) {
2548 case 0:
2549 gen_op_mtc0_entryhi();
2550 rn = "EntryHi";
2551 break;
2552 default:
2553 goto die;
2554 }
2555 break;
2556 case 11:
2557 switch (sel) {
2558 case 0:
2559 gen_op_mtc0_compare();
2560 rn = "Compare";
2561 break;
2562 /* 6,7 are implementation dependent */
2563 default:
2564 goto die;
2565 }
2566 /* Stop translation as we may have switched the execution mode */
2567 ctx->bstate = BS_STOP;
2568 break;
2569 case 12:
2570 switch (sel) {
2571 case 0:
2572 gen_op_mtc0_status();
2573 rn = "Status";
2574 break;
2575 case 1:
2576 gen_op_mtc0_intctl();
2577 rn = "IntCtl";
2578 break;
2579 case 2:
2580 gen_op_mtc0_srsctl();
2581 rn = "SRSCtl";
2582 break;
2583 case 3:
2584 // gen_op_mtc0_srsmap(); /* shadow registers */
2585 rn = "SRSMap";
2586 // break;
2587 default:
2588 goto die;
2589 }
2590 /* Stop translation as we may have switched the execution mode */
2591 ctx->bstate = BS_STOP;
2592 break;
2593 case 13:
2594 switch (sel) {
2595 case 0:
2596 gen_op_mtc0_cause();
2597 rn = "Cause";
2598 break;
2599 default:
2600 goto die;
2601 }
2602 /* Stop translation as we may have switched the execution mode */
2603 ctx->bstate = BS_STOP;
2604 break;
2605 case 14:
2606 switch (sel) {
2607 case 0:
2608 gen_op_mtc0_epc();
2609 rn = "EPC";
2610 break;
2611 default:
2612 goto die;
2613 }
2614 break;
2615 case 15:
2616 switch (sel) {
2617 case 0:
2618 /* ignored */
2619 rn = "PRid";
2620 break;
2621 case 1:
2622 gen_op_mtc0_ebase();
2623 rn = "EBase";
2624 break;
2625 default:
2626 goto die;
2627 }
2628 break;
2629 case 16:
2630 switch (sel) {
2631 case 0:
2632 gen_op_mtc0_config0();
2633 rn = "Config";
2634 /* Stop translation as we may have switched the execution mode */
2635 ctx->bstate = BS_STOP;
2636 break;
2637 case 1:
2638 /* ignored, read only */
2639 rn = "Config1";
2640 break;
2641 case 2:
2642 gen_op_mtc0_config2();
2643 rn = "Config2";
2644 /* Stop translation as we may have switched the execution mode */
2645 ctx->bstate = BS_STOP;
2646 break;
2647 case 3:
2648 /* ignored, read only */
2649 rn = "Config3";
2650 break;
2651 /* 4,5 are reserved */
2652 /* 6,7 are implementation dependent */
2653 case 6:
2654 /* ignored */
2655 rn = "Config6";
2656 break;
2657 case 7:
2658 /* ignored */
2659 rn = "Config7";
2660 break;
2661 default:
2662 rn = "Invalid config selector";
2663 goto die;
2664 }
2665 break;
2666 case 17:
2667 switch (sel) {
2668 case 0:
2669 /* ignored */
2670 rn = "LLAddr";
2671 break;
2672 default:
2673 goto die;
2674 }
2675 break;
2676 case 18:
2677 switch (sel) {
2678 case 0:
2679 gen_op_mtc0_watchlo0();
2680 rn = "WatchLo";
2681 break;
2682 case 1:
2683 // gen_op_mtc0_watchlo1();
2684 rn = "WatchLo1";
2685 // break;
2686 case 2:
2687 // gen_op_mtc0_watchlo2();
2688 rn = "WatchLo2";
2689 // break;
2690 case 3:
2691 // gen_op_mtc0_watchlo3();
2692 rn = "WatchLo3";
2693 // break;
2694 case 4:
2695 // gen_op_mtc0_watchlo4();
2696 rn = "WatchLo4";
2697 // break;
2698 case 5:
2699 // gen_op_mtc0_watchlo5();
2700 rn = "WatchLo5";
2701 // break;
2702 case 6:
2703 // gen_op_mtc0_watchlo6();
2704 rn = "WatchLo6";
2705 // break;
2706 case 7:
2707 // gen_op_mtc0_watchlo7();
2708 rn = "WatchLo7";
2709 // break;
2710 default:
2711 goto die;
2712 }
2713 break;
2714 case 19:
2715 switch (sel) {
2716 case 0:
2717 gen_op_mtc0_watchhi0();
2718 rn = "WatchHi";
2719 break;
2720 case 1:
2721 // gen_op_mtc0_watchhi1();
2722 rn = "WatchHi1";
2723 // break;
2724 case 2:
2725 // gen_op_mtc0_watchhi2();
2726 rn = "WatchHi2";
2727 // break;
2728 case 3:
2729 // gen_op_mtc0_watchhi3();
2730 rn = "WatchHi3";
2731 // break;
2732 case 4:
2733 // gen_op_mtc0_watchhi4();
2734 rn = "WatchHi4";
2735 // break;
2736 case 5:
2737 // gen_op_mtc0_watchhi5();
2738 rn = "WatchHi5";
2739 // break;
2740 case 6:
2741 // gen_op_mtc0_watchhi6();
2742 rn = "WatchHi6";
2743 // break;
2744 case 7:
2745 // gen_op_mtc0_watchhi7();
2746 rn = "WatchHi7";
2747 // break;
2748 default:
2749 goto die;
2750 }
2751 break;
2752 case 20:
2753 switch (sel) {
2754 case 0:
2755 /* 64 bit MMU only */
2756 /* Nothing writable in lower 32 bits */
2757 rn = "XContext";
2758 break;
2759 default:
2760 goto die;
2761 }
2762 break;
2763 case 21:
2764 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2765 switch (sel) {
2766 case 0:
2767 gen_op_mtc0_framemask();
2768 rn = "Framemask";
2769 break;
2770 default:
2771 goto die;
2772 }
2773 break;
2774 case 22:
2775 /* ignored */
2776 rn = "Diagnostic"; /* implementation dependent */
2777 break;
2778 case 23:
2779 switch (sel) {
2780 case 0:
2781 gen_op_mtc0_debug(); /* EJTAG support */
2782 rn = "Debug";
2783 break;
2784 case 1:
2785 // gen_op_mtc0_tracecontrol(); /* PDtrace support */
2786 rn = "TraceControl";
2787 // break;
2788 case 2:
2789 // gen_op_mtc0_tracecontrol2(); /* PDtrace support */
2790 rn = "TraceControl2";
2791 // break;
2792 case 3:
2793 // gen_op_mtc0_usertracedata(); /* PDtrace support */
2794 rn = "UserTraceData";
2795 // break;
2796 case 4:
2797 // gen_op_mtc0_debug(); /* PDtrace support */
2798 rn = "TraceBPC";
2799 // break;
2800 default:
2801 goto die;
2802 }
2803 /* Stop translation as we may have switched the execution mode */
2804 ctx->bstate = BS_STOP;
2805 break;
2806 case 24:
2807 switch (sel) {
2808 case 0:
2809 gen_op_mtc0_depc(); /* EJTAG support */
2810 rn = "DEPC";
2811 break;
2812 default:
2813 goto die;
2814 }
2815 break;
2816 case 25:
2817 switch (sel) {
2818 case 0:
2819 gen_op_mtc0_performance0();
2820 rn = "Performance0";
2821 break;
2822 case 1:
2823 // gen_op_mtc0_performance1();
2824 rn = "Performance1";
2825 // break;
2826 case 2:
2827 // gen_op_mtc0_performance2();
2828 rn = "Performance2";
2829 // break;
2830 case 3:
2831 // gen_op_mtc0_performance3();
2832 rn = "Performance3";
2833 // break;
2834 case 4:
2835 // gen_op_mtc0_performance4();
2836 rn = "Performance4";
2837 // break;
2838 case 5:
2839 // gen_op_mtc0_performance5();
2840 rn = "Performance5";
2841 // break;
2842 case 6:
2843 // gen_op_mtc0_performance6();
2844 rn = "Performance6";
2845 // break;
2846 case 7:
2847 // gen_op_mtc0_performance7();
2848 rn = "Performance7";
2849 // break;
2850 default:
2851 goto die;
2852 }
2853 break;
2854 case 26:
2855 /* ignored */
2856 rn = "ECC";
2857 break;
2858 case 27:
2859 switch (sel) {
2860 case 0 ... 3:
2861 /* ignored */
2862 rn = "CacheErr";
2863 break;
2864 default:
2865 goto die;
2866 }
2867 break;
2868 case 28:
2869 switch (sel) {
2870 case 0:
2871 case 2:
2872 case 4:
2873 case 6:
2874 gen_op_mtc0_taglo();
2875 rn = "TagLo";
2876 break;
2877 case 1:
2878 case 3:
2879 case 5:
2880 case 7:
2881 gen_op_mtc0_datalo();
2882 rn = "DataLo";
2883 break;
2884 default:
2885 goto die;
2886 }
2887 break;
2888 case 29:
2889 switch (sel) {
2890 case 0:
2891 case 2:
2892 case 4:
2893 case 6:
2894 gen_op_mtc0_taghi();
2895 rn = "TagHi";
2896 break;
2897 case 1:
2898 case 3:
2899 case 5:
2900 case 7:
2901 gen_op_mtc0_datahi();
2902 rn = "DataHi";
2903 break;
2904 default:
2905 rn = "invalid sel";
2906 goto die;
2907 }
2908 break;
2909 case 30:
2910 switch (sel) {
2911 case 0:
2912 gen_op_mtc0_errorepc();
2913 rn = "ErrorEPC";
2914 break;
2915 default:
2916 goto die;
2917 }
2918 break;
2919 case 31:
2920 switch (sel) {
2921 case 0:
2922 gen_op_mtc0_desave(); /* EJTAG support */
2923 rn = "DESAVE";
2924 break;
2925 default:
2926 goto die;
2927 }
2928 /* Stop translation as we may have switched the execution mode */
2929 ctx->bstate = BS_STOP;
2930 break;
2931 default:
2932 goto die;
2933 }
2934 #if defined MIPS_DEBUG_DISAS
2935 if (loglevel & CPU_LOG_TB_IN_ASM) {
2936 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2937 rn, reg, sel);
2938 }
2939 #endif
2940 return;
2941
2942 die:
2943 #if defined MIPS_DEBUG_DISAS
2944 if (loglevel & CPU_LOG_TB_IN_ASM) {
2945 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2946 rn, reg, sel);
2947 }
2948 #endif
2949 generate_exception(ctx, EXCP_RI);
2950 }
2951
2952 #ifdef TARGET_MIPS64
2953 static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
2954 {
2955 const char *rn = "invalid";
2956
2957 switch (reg) {
2958 case 0:
2959 switch (sel) {
2960 case 0:
2961 gen_op_mfc0_index();
2962 rn = "Index";
2963 break;
2964 case 1:
2965 // gen_op_dmfc0_mvpcontrol(); /* MT ASE */
2966 rn = "MVPControl";
2967 // break;
2968 case 2:
2969 // gen_op_dmfc0_mvpconf0(); /* MT ASE */
2970 rn = "MVPConf0";
2971 // break;
2972 case 3:
2973 // gen_op_dmfc0_mvpconf1(); /* MT ASE */
2974 rn = "MVPConf1";
2975 // break;
2976 default:
2977 goto die;
2978 }
2979 break;
2980 case 1:
2981 switch (sel) {
2982 case 0:
2983 gen_op_mfc0_random();
2984 rn = "Random";
2985 break;
2986 case 1:
2987 // gen_op_dmfc0_vpecontrol(); /* MT ASE */
2988 rn = "VPEControl";
2989 // break;
2990 case 2:
2991 // gen_op_dmfc0_vpeconf0(); /* MT ASE */
2992 rn = "VPEConf0";
2993 // break;
2994 case 3:
2995 // gen_op_dmfc0_vpeconf1(); /* MT ASE */
2996 rn = "VPEConf1";
2997 // break;
2998 case 4:
2999 // gen_op_dmfc0_YQMask(); /* MT ASE */
3000 rn = "YQMask";
3001 // break;
3002 case 5:
3003 // gen_op_dmfc0_vpeschedule(); /* MT ASE */
3004 rn = "VPESchedule";
3005 // break;
3006 case 6:
3007 // gen_op_dmfc0_vpeschefback(); /* MT ASE */
3008 rn = "VPEScheFBack";
3009 // break;
3010 case 7:
3011 // gen_op_dmfc0_vpeopt(); /* MT ASE */
3012 rn = "VPEOpt";
3013 // break;
3014 default:
3015 goto die;
3016 }
3017 break;
3018 case 2:
3019 switch (sel) {
3020 case 0:
3021 gen_op_dmfc0_entrylo0();
3022 rn = "EntryLo0";
3023 break;
3024 case 1:
3025 // gen_op_dmfc0_tcstatus(); /* MT ASE */
3026 rn = "TCStatus";
3027 // break;
3028 case 2:
3029 // gen_op_dmfc0_tcbind(); /* MT ASE */
3030 rn = "TCBind";
3031 // break;
3032 case 3:
3033 // gen_op_dmfc0_tcrestart(); /* MT ASE */
3034 rn = "TCRestart";
3035 // break;
3036 case 4:
3037 // gen_op_dmfc0_tchalt(); /* MT ASE */
3038 rn = "TCHalt";
3039 // break;
3040 case 5:
3041 // gen_op_dmfc0_tccontext(); /* MT ASE */
3042 rn = "TCContext";
3043 // break;
3044 case 6:
3045 // gen_op_dmfc0_tcschedule(); /* MT ASE */
3046 rn = "TCSchedule";
3047 // break;
3048 case 7:
3049 // gen_op_dmfc0_tcschefback(); /* MT ASE */
3050 rn = "TCScheFBack";
3051 // break;
3052 default:
3053 goto die;
3054 }
3055 break;
3056 case 3:
3057 switch (sel) {
3058 case 0:
3059 gen_op_dmfc0_entrylo1();
3060 rn = "EntryLo1";
3061 break;
3062 default:
3063 goto die;
3064 }
3065 break;
3066 case 4:
3067 switch (sel) {
3068 case 0:
3069 gen_op_dmfc0_context();
3070 rn = "Context";
3071 break;
3072 case 1:
3073 // gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */
3074 rn = "ContextConfig";
3075 // break;
3076 default:
3077 goto die;
3078 }
3079 break;
3080 case 5:
3081 switch (sel) {
3082 case 0:
3083 gen_op_mfc0_pagemask();
3084 rn = "PageMask";
3085 break;
3086 case 1:
3087 gen_op_mfc0_pagegrain();
3088 rn = "PageGrain";
3089 break;
3090 default:
3091 goto die;
3092 }
3093 break;
3094 case 6:
3095 switch (sel) {
3096 case 0:
3097 gen_op_mfc0_wired();
3098 rn = "Wired";
3099 break;
3100 case 1:
3101 // gen_op_dmfc0_srsconf0(); /* shadow registers */
3102 rn = "SRSConf0";
3103 // break;
3104 case 2:
3105 // gen_op_dmfc0_srsconf1(); /* shadow registers */
3106 rn = "SRSConf1";
3107 // break;
3108 case 3:
3109 // gen_op_dmfc0_srsconf2(); /* shadow registers */
3110 rn = "SRSConf2";
3111 // break;
3112 case 4:
3113 // gen_op_dmfc0_srsconf3(); /* shadow registers */
3114 rn = "SRSConf3";
3115 // break;
3116 case 5:
3117 // gen_op_dmfc0_srsconf4(); /* shadow registers */
3118 rn = "SRSConf4";
3119 // break;
3120 default:
3121 goto die;
3122 }
3123 break;
3124 case 7:
3125 switch (sel) {
3126 case 0:
3127 gen_op_mfc0_hwrena();
3128 rn = "HWREna";
3129 break;
3130 default:
3131 goto die;
3132 }
3133 break;
3134 case 8:
3135 switch (sel) {
3136 case 0:
3137 gen_op_dmfc0_badvaddr();
3138 rn = "BadVaddr";
3139 break;
3140 default:
3141 goto die;
3142 }
3143 break;
3144 case 9:
3145 switch (sel) {
3146 case 0:
3147 gen_op_mfc0_count();
3148 rn = "Count";
3149 break;
3150 /* 6,7 are implementation dependent */
3151 default:
3152 goto die;
3153 }
3154 break;
3155 case 10:
3156 switch (sel) {
3157 case 0:
3158 gen_op_dmfc0_entryhi();
3159 rn = "EntryHi";
3160 break;
3161 default:
3162 goto die;
3163 }
3164 break;
3165 case 11:
3166 switch (sel) {
3167 case 0:
3168 gen_op_mfc0_compare();
3169 rn = "Compare";
3170 break;
3171 /* 6,7 are implementation dependent */
3172 default:
3173 goto die;
3174 }
3175 break;
3176 case 12:
3177 switch (sel) {
3178 case 0:
3179 gen_op_mfc0_status();
3180 rn = "Status";
3181 break;
3182 case 1:
3183 gen_op_mfc0_intctl();
3184 rn = "IntCtl";
3185 break;
3186 case 2:
3187 gen_op_mfc0_srsctl();
3188 rn = "SRSCtl";
3189 break;
3190 case 3:
3191 gen_op_mfc0_srsmap(); /* shadow registers */
3192 rn = "SRSMap";
3193 break;
3194 default:
3195 goto die;
3196 }
3197 break;
3198 case 13:
3199 switch (sel) {
3200 case 0:
3201 gen_op_mfc0_cause();
3202 rn = "Cause";
3203 break;
3204 default:
3205 goto die;
3206 }
3207 break;
3208 case 14:
3209 switch (sel) {
3210 case 0:
3211 gen_op_dmfc0_epc();
3212 rn = "EPC";
3213 break;
3214 default:
3215 goto die;
3216 }
3217 break;
3218 case 15:
3219 switch (sel) {
3220 case 0:
3221 gen_op_mfc0_prid();
3222 rn = "PRid";
3223 break;
3224 case 1:
3225 gen_op_mfc0_ebase();
3226 rn = "EBase";
3227 break;
3228 default:
3229 goto die;
3230 }
3231 break;
3232 case 16:
3233 switch (sel) {
3234 case 0:
3235 gen_op_mfc0_config0();
3236 rn = "Config";
3237 break;
3238 case 1:
3239 gen_op_mfc0_config1();
3240 rn = "Config1";
3241 break;
3242 case 2:
3243 gen_op_mfc0_config2();
3244 rn = "Config2";
3245 break;
3246 case 3:
3247 gen_op_mfc0_config3();
3248 rn = "Config3";
3249 break;
3250 /* 6,7 are implementation dependent */
3251 default:
3252 goto die;
3253 }
3254 break;
3255 case 17:
3256 switch (sel) {
3257 case 0:
3258 gen_op_dmfc0_lladdr();
3259 rn = "LLAddr";
3260 break;
3261 default:
3262 goto die;
3263 }
3264 break;
3265 case 18:
3266 switch (sel) {
3267 case 0:
3268 gen_op_dmfc0_watchlo0();
3269 rn = "WatchLo";
3270 break;
3271 case 1:
3272 // gen_op_dmfc0_watchlo1();
3273 rn = "WatchLo1";
3274 // break;
3275 case 2:
3276 // gen_op_dmfc0_watchlo2();
3277 rn = "WatchLo2";
3278 // break;
3279 case 3:
3280 // gen_op_dmfc0_watchlo3();
3281 rn = "WatchLo3";
3282 // break;
3283 case 4:
3284 // gen_op_dmfc0_watchlo4();
3285 rn = "WatchLo4";
3286 // break;
3287 case 5:
3288 // gen_op_dmfc0_watchlo5();
3289 rn = "WatchLo5";
3290 // break;
3291 case 6:
3292 // gen_op_dmfc0_watchlo6();
3293 rn = "WatchLo6";
3294 // break;
3295 case 7:
3296 // gen_op_dmfc0_watchlo7();
3297 rn = "WatchLo7";
3298 // break;
3299 default:
3300 goto die;
3301 }
3302 break;
3303 case 19:
3304 switch (sel) {
3305 case 0:
3306 gen_op_mfc0_watchhi0();
3307 rn = "WatchHi";
3308 break;
3309 case 1:
3310 // gen_op_mfc0_watchhi1();
3311 rn = "WatchHi1";
3312 // break;
3313 case 2:
3314 // gen_op_mfc0_watchhi2();
3315 rn = "WatchHi2";
3316 // break;
3317 case 3:
3318 // gen_op_mfc0_watchhi3();
3319 rn = "WatchHi3";
3320 // break;
3321 case 4:
3322 // gen_op_mfc0_watchhi4();
3323 rn = "WatchHi4";
3324 // break;
3325 case 5:
3326 // gen_op_mfc0_watchhi5();
3327 rn = "WatchHi5";
3328 // break;
3329 case 6:
3330 // gen_op_mfc0_watchhi6();
3331 rn = "WatchHi6";
3332 // break;
3333 case 7:
3334 // gen_op_mfc0_watchhi7();
3335 rn = "WatchHi7";
3336 // break;
3337 default:
3338 goto die;
3339 }
3340 break;
3341 case 20:
3342 switch (sel) {
3343 case 0:
3344 /* 64 bit MMU only */
3345 gen_op_dmfc0_xcontext();
3346 rn = "XContext";
3347 break;
3348 default:
3349 goto die;
3350 }
3351 break;
3352 case 21:
3353 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3354 switch (sel) {
3355 case 0:
3356 gen_op_mfc0_framemask();
3357 rn = "Framemask";
3358 break;
3359 default:
3360 goto die;
3361 }
3362 break;
3363 case 22:
3364 /* ignored */
3365 rn = "'Diagnostic"; /* implementation dependent */
3366 break;
3367 case 23:
3368 switch (sel) {
3369 case 0:
3370 gen_op_mfc0_debug(); /* EJTAG support */
3371 rn = "Debug";
3372 break;
3373 case 1:
3374 // gen_op_dmfc0_tracecontrol(); /* PDtrace support */
3375 rn = "TraceControl";
3376 // break;
3377 case 2:
3378 // gen_op_dmfc0_tracecontrol2(); /* PDtrace support */
3379 rn = "TraceControl2";
3380 // break;
3381 case 3:
3382 // gen_op_dmfc0_usertracedata(); /* PDtrace support */
3383 rn = "UserTraceData";
3384 // break;
3385 case 4:
3386 // gen_op_dmfc0_debug(); /* PDtrace support */
3387 rn = "TraceBPC";
3388 // break;
3389 default:
3390 goto die;
3391 }
3392 break;
3393 case 24:
3394 switch (sel) {
3395 case 0:
3396 gen_op_dmfc0_depc(); /* EJTAG support */
3397 rn = "DEPC";
3398 break;
3399 default:
3400 goto die;
3401 }
3402 break;
3403 case 25:
3404 switch (sel) {
3405 case 0:
3406 gen_op_mfc0_performance0();
3407 rn = "Performance0";
3408 break;
3409 case 1:
3410 // gen_op_dmfc0_performance1();
3411 rn = "Performance1";
3412 // break;
3413 case 2:
3414 // gen_op_dmfc0_performance2();
3415 rn = "Performance2";
3416 // break;
3417 case 3:
3418 // gen_op_dmfc0_performance3();
3419 rn = "Performance3";
3420 // break;
3421 case 4:
3422 // gen_op_dmfc0_performance4();
3423 rn = "Performance4";
3424 // break;
3425 case 5:
3426 // gen_op_dmfc0_performance5();
3427 rn = "Performance5";
3428 // break;
3429 case 6:
3430 // gen_op_dmfc0_performance6();
3431 rn = "Performance6";
3432 // break;
3433 case 7:
3434 // gen_op_dmfc0_performance7();
3435 rn = "Performance7";
3436 // break;
3437 default:
3438 goto die;
3439 }
3440 break;
3441 case 26:
3442 rn = "ECC";
3443 break;
3444 case 27:
3445 switch (sel) {
3446 /* ignored */
3447 case 0 ... 3:
3448 rn = "CacheErr";
3449 break;
3450 default:
3451 goto die;
3452 }
3453 break;
3454 case 28:
3455 switch (sel) {
3456 case 0:
3457 case 2:
3458 case 4:
3459 case 6:
3460 gen_op_mfc0_taglo();
3461 rn = "TagLo";
3462 break;
3463 case 1:
3464 case 3:
3465 case 5:
3466 case 7:
3467 gen_op_mfc0_datalo();
3468 rn = "DataLo";
3469 break;
3470 default:
3471 goto die;
3472 }
3473 break;
3474 case 29:
3475 switch (sel) {
3476 case 0:
3477 case 2:
3478 case 4:
3479 case 6:
3480 gen_op_mfc0_taghi();
3481 rn = "TagHi";
3482 break;
3483 case 1:
3484 case 3:
3485 case 5:
3486 case 7:
3487 gen_op_mfc0_datahi();
3488 rn = "DataHi";
3489 break;
3490 default:
3491 goto die;
3492 }
3493 break;
3494 case 30:
3495 switch (sel) {
3496 case 0:
3497 gen_op_dmfc0_errorepc();
3498 rn = "ErrorEPC";
3499 break;
3500 default:
3501 goto die;
3502 }
3503 break;
3504 case 31:
3505 switch (sel) {
3506 case 0:
3507 gen_op_mfc0_desave(); /* EJTAG support */
3508 rn = "DESAVE";
3509 break;
3510 default:
3511 goto die;
3512 }
3513 break;
3514 default:
3515 goto die;
3516 }
3517 #if defined MIPS_DEBUG_DISAS
3518 if (loglevel & CPU_LOG_TB_IN_ASM) {
3519 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3520 rn, reg, sel);
3521 }
3522 #endif
3523 return;
3524
3525 die:
3526 #if defined MIPS_DEBUG_DISAS
3527 if (loglevel & CPU_LOG_TB_IN_ASM) {
3528 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3529 rn, reg, sel);
3530 }
3531 #endif
3532 generate_exception(ctx, EXCP_RI);
3533 }
3534
3535 static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
3536 {
3537 const char *rn = "invalid";
3538
3539 switch (reg) {
3540 case 0:
3541 switch (sel) {
3542 case 0:
3543 gen_op_mtc0_index();
3544 rn = "Index";
3545 break;
3546 case 1:
3547 // gen_op_dmtc0_mvpcontrol(); /* MT ASE */
3548 rn = "MVPControl";
3549 // break;
3550 case 2:
3551 // gen_op_dmtc0_mvpconf0(); /* MT ASE */
3552 rn = "MVPConf0";
3553 // break;
3554 case 3:
3555 // gen_op_dmtc0_mvpconf1(); /* MT ASE */
3556 rn = "MVPConf1";
3557 // break;
3558 default:
3559 goto die;
3560 }
3561 break;
3562 case 1:
3563 switch (sel) {
3564 case 0:
3565 /* ignored */
3566 rn = "Random";
3567 break;
3568 case 1:
3569 // gen_op_dmtc0_vpecontrol(); /* MT ASE */
3570 rn = "VPEControl";
3571 // break;
3572 case 2:
3573 // gen_op_dmtc0_vpeconf0(); /* MT ASE */
3574 rn = "VPEConf0";
3575 // break;
3576 case 3:
3577 // gen_op_dmtc0_vpeconf1(); /* MT ASE */
3578 rn = "VPEConf1";
3579 // break;
3580 case 4:
3581 // gen_op_dmtc0_YQMask(); /* MT ASE */
3582 rn = "YQMask";
3583 // break;
3584 case 5:
3585 // gen_op_dmtc0_vpeschedule(); /* MT ASE */
3586 rn = "VPESchedule";
3587 // break;
3588 case 6:
3589 // gen_op_dmtc0_vpeschefback(); /* MT ASE */
3590 rn = "VPEScheFBack";
3591 // break;
3592 case 7:
3593 // gen_op_dmtc0_vpeopt(); /* MT ASE */
3594 rn = "VPEOpt";
3595 // break;
3596 default:
3597 goto die;
3598 }
3599 break;
3600 case 2:
3601 switch (sel) {
3602 case 0:
3603 gen_op_dmtc0_entrylo0();
3604 rn = "EntryLo0";
3605 break;
3606 case 1:
3607 // gen_op_dmtc0_tcstatus(); /* MT ASE */
3608 rn = "TCStatus";
3609 // break;
3610 case 2:
3611 // gen_op_dmtc0_tcbind(); /* MT ASE */
3612 rn = "TCBind";
3613 // break;
3614 case 3:
3615 // gen_op_dmtc0_tcrestart(); /* MT ASE */
3616 rn = "TCRestart";
3617 // break;
3618 case 4:
3619 // gen_op_dmtc0_tchalt(); /* MT ASE */
3620 rn = "TCHalt";
3621 // break;
3622 case 5:
3623 // gen_op_dmtc0_tccontext(); /* MT ASE */
3624 rn = "TCContext";
3625 // break;
3626 case 6:
3627 // gen_op_dmtc0_tcschedule(); /* MT ASE */
3628 rn = "TCSchedule";
3629 // break;
3630 case 7:
3631 // gen_op_dmtc0_tcschefback(); /* MT ASE */
3632 rn = "TCScheFBack";
3633 // break;
3634 default:
3635 goto die;
3636 }
3637 break;
3638 case 3:
3639 switch (sel) {
3640 case 0:
3641 gen_op_dmtc0_entrylo1();
3642 rn = "EntryLo1";
3643 break;
3644 default:
3645 goto die;
3646 }
3647 break;
3648 case 4:
3649 switch (sel) {
3650 case 0:
3651 gen_op_dmtc0_context();
3652 rn = "Context";
3653 break;
3654 case 1:
3655 // gen_op_dmtc0_contextconfig(); /* SmartMIPS ASE */
3656 rn = "ContextConfig";
3657 // break;
3658 default:
3659 goto die;
3660 }
3661 break;
3662 case 5:
3663 switch (sel) {
3664 case 0:
3665 gen_op_mtc0_pagemask();
3666 rn = "PageMask";
3667 break;
3668 case 1:
3669 gen_op_mtc0_pagegrain();
3670 rn = "PageGrain";
3671 break;
3672 default:
3673 goto die;
3674 }
3675 break;
3676 case 6:
3677 switch (sel) {
3678 case 0:
3679 gen_op_mtc0_wired();
3680 rn = "Wired";
3681 break;
3682 case 1:
3683 // gen_op_dmtc0_srsconf0(); /* shadow registers */
3684 rn = "SRSConf0";
3685 // break;
3686 case 2:
3687 // gen_op_dmtc0_srsconf1(); /* shadow registers */
3688 rn = "SRSConf1";
3689 // break;
3690 case 3:
3691 // gen_op_dmtc0_srsconf2(); /* shadow registers */
3692 rn = "SRSConf2";
3693 // break;
3694 case 4:
3695 // gen_op_dmtc0_srsconf3(); /* shadow registers */
3696 rn = "SRSConf3";
3697 // break;
3698 case 5:
3699 // gen_op_dmtc0_srsconf4(); /* shadow registers */
3700 rn = "SRSConf4";
3701 // break;
3702 default:
3703 goto die;
3704 }
3705 break;
3706 case 7:
3707 switch (sel) {
3708 case 0:
3709 gen_op_mtc0_hwrena();
3710 rn = "HWREna";
3711 break;
3712 default:
3713 goto die;
3714 }
3715 break;
3716 case 8:
3717 /* ignored */
3718 rn = "BadVaddr";
3719 break;
3720 case 9:
3721 switch (sel) {
3722 case 0:
3723 gen_op_mtc0_count();
3724 rn = "Count";
3725 break;
3726 /* 6,7 are implementation dependent */
3727 default:
3728 goto die;
3729 }
3730 /* Stop translation as we may have switched the execution mode */
3731 ctx->bstate = BS_STOP;
3732 break;
3733 case 10:
3734 switch (sel) {
3735 case 0:
3736 gen_op_mtc0_entryhi();
3737 rn = "EntryHi";
3738 break;
3739 default:
3740 goto die;
3741 }
3742 break;
3743 case 11:
3744 switch (sel) {
3745 case 0:
3746 gen_op_mtc0_compare();
3747 rn = "Compare";
3748 break;
3749 /* 6,7 are implementation dependent */
3750 default:
3751 goto die;
3752 }
3753 /* Stop translation as we may have switched the execution mode */
3754 ctx->bstate = BS_STOP;
3755 break;
3756 case 12:
3757 switch (sel) {
3758 case 0:
3759 gen_op_mtc0_status();
3760 rn = "Status";
3761 break;
3762 case 1:
3763 gen_op_mtc0_intctl();
3764 rn = "IntCtl";
3765 break;
3766 case 2:
3767 gen_op_mtc0_srsctl();
3768 rn = "SRSCtl";
3769 break;
3770 case 3:
3771 gen_op_mtc0_srsmap(); /* shadow registers */
3772 rn = "SRSMap";
3773 break;
3774 default:
3775 goto die;
3776 }
3777 /* Stop translation as we may have switched the execution mode */
3778 ctx->bstate = BS_STOP;
3779 break;
3780 case 13:
3781 switch (sel) {
3782 case 0:
3783 gen_op_mtc0_cause();
3784 rn = "Cause";
3785 break;
3786 default:
3787 goto die;
3788 }
3789 /* Stop translation as we may have switched the execution mode */
3790 ctx->bstate = BS_STOP;
3791 break;
3792 case 14:
3793 switch (sel) {
3794 case 0:
3795 gen_op_dmtc0_epc();
3796 rn = "EPC";
3797 break;
3798 default:
3799 goto die;
3800 }
3801 break;
3802 case 15:
3803 switch (sel) {
3804 case 0:
3805 /* ignored */
3806 rn = "PRid";
3807 break;
3808 case 1:
3809 gen_op_mtc0_ebase();
3810 rn = "EBase";
3811 break;
3812 default:
3813 goto die;
3814 }
3815 break;
3816 case 16:
3817 switch (sel) {
3818 case 0:
3819 gen_op_mtc0_config0();
3820 rn = "Config";
3821 /* Stop translation as we may have switched the execution mode */
3822 ctx->bstate = BS_STOP;
3823 break;
3824 case 1:
3825 /* ignored */
3826 rn = "Config1";
3827 break;
3828 case 2:
3829 gen_op_mtc0_config2();
3830 rn = "Config2";
3831 /* Stop translation as we may have switched the execution mode */
3832 ctx->bstate = BS_STOP;
3833 break;
3834 case 3:
3835 /* ignored */
3836 rn = "Config3";
3837 break;
3838 /* 6,7 are implementation dependent */
3839 default:
3840 rn = "Invalid config selector";
3841 goto die;
3842 }
3843 break;
3844 case 17:
3845 switch (sel) {
3846 case 0:
3847 /* ignored */
3848 rn = "LLAddr";
3849 break;
3850 default:
3851 goto die;
3852 }
3853 break;
3854 case 18:
3855 switch (sel) {
3856 case 0:
3857 gen_op_dmtc0_watchlo0();
3858 rn = "WatchLo";
3859 break;
3860 case 1:
3861 // gen_op_dmtc0_watchlo1();
3862 rn = "WatchLo1";
3863 // break;
3864 case 2:
3865 // gen_op_dmtc0_watchlo2();
3866 rn = "WatchLo2";
3867 // break;
3868 case 3:
3869 // gen_op_dmtc0_watchlo3();
3870 rn = "WatchLo3";
3871 // break;
3872 case 4:
3873 // gen_op_dmtc0_watchlo4();
3874 rn = "WatchLo4";
3875 // break;
3876 case 5:
3877 // gen_op_dmtc0_watchlo5();
3878 rn = "WatchLo5";
3879 // break;
3880 case 6:
3881 // gen_op_dmtc0_watchlo6();
3882 rn = "WatchLo6";
3883 // break;
3884 case 7:
3885 // gen_op_dmtc0_watchlo7();
3886 rn = "WatchLo7";
3887 // break;
3888 default:
3889 goto die;
3890 }
3891 break;
3892 case 19:
3893 switch (sel) {
3894 case 0:
3895 gen_op_mtc0_watchhi0();
3896 rn = "WatchHi";
3897 break;
3898 case 1:
3899 // gen_op_dmtc0_watchhi1();
3900 rn = "WatchHi1";
3901 // break;
3902 case 2:
3903 // gen_op_dmtc0_watchhi2();
3904 rn = "WatchHi2";
3905 // break;
3906 case 3:
3907 // gen_op_dmtc0_watchhi3();
3908 rn = "WatchHi3";
3909 // break;
3910 case 4:
3911 // gen_op_dmtc0_watchhi4();
3912 rn = "WatchHi4";
3913 // break;
3914 case 5:
3915 // gen_op_dmtc0_watchhi5();
3916 rn = "WatchHi5";
3917 // break;
3918 case 6:
3919 // gen_op_dmtc0_watchhi6();
3920 rn = "WatchHi6";
3921 // break;
3922 case 7:
3923 // gen_op_dmtc0_watchhi7();
3924 rn = "WatchHi7";
3925 // break;
3926 default:
3927 goto die;
3928 }
3929 break;
3930 case 20:
3931 switch (sel) {
3932 case 0:
3933 /* 64 bit MMU only */
3934 gen_op_dmtc0_xcontext();
3935 rn = "XContext";
3936 break;
3937 default:
3938 goto die;
3939 }
3940 break;
3941 case 21:
3942 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3943 switch (sel) {
3944 case 0:
3945 gen_op_mtc0_framemask();
3946 rn = "Framemask";
3947 break;
3948 default:
3949 goto die;
3950 }
3951 break;
3952 case 22:
3953 /* ignored */
3954 rn = "Diagnostic"; /* implementation dependent */
3955 break;
3956 case 23:
3957 switch (sel) {
3958 case 0:
3959 gen_op_mtc0_debug(); /* EJTAG support */
3960 rn = "Debug";
3961 break;
3962 case 1:
3963 // gen_op_dmtc0_tracecontrol(); /* PDtrace support */
3964 rn = "TraceControl";
3965 // break;
3966 case 2:
3967 // gen_op_dmtc0_tracecontrol2(); /* PDtrace support */
3968 rn = "TraceControl2";
3969 // break;
3970 case 3:
3971 // gen_op_dmtc0_usertracedata(); /* PDtrace support */
3972 rn = "UserTraceData";
3973 // break;
3974 case 4:
3975 // gen_op_dmtc0_debug(); /* PDtrace support */
3976 rn = "TraceBPC";
3977 // break;
3978 default:
3979 goto die;
3980 }
3981 /* Stop translation as we may have switched the execution mode */
3982 ctx->bstate = BS_STOP;
3983 break;
3984 case 24:
3985 switch (sel) {
3986 case 0:
3987 gen_op_dmtc0_depc(); /* EJTAG support */
3988 rn = "DEPC";
3989 break;
3990 default:
3991 goto die;
3992 }
3993 break;
3994 case 25:
3995 switch (sel) {
3996 case 0:
3997 gen_op_mtc0_performance0();
3998 rn = "Performance0";
3999 break;
4000 case 1:
4001 // gen_op_dmtc0_performance1();
4002 rn = "Performance1";
4003 // break;
4004 case 2:
4005 // gen_op_dmtc0_performance2();
4006 rn = "Performance2";
4007 // break;
4008 case 3:
4009 // gen_op_dmtc0_performance3();
4010 rn = "Performance3";
4011 // break;
4012 case 4:
4013 // gen_op_dmtc0_performance4();
4014 rn = "Performance4";
4015 // break;
4016 case 5:
4017 // gen_op_dmtc0_performance5();
4018 rn = "Performance5";
4019 // break;
4020 case 6:
4021 // gen_op_dmtc0_performance6();
4022 rn = "Performance6";
4023 // break;
4024 case 7:
4025 // gen_op_dmtc0_performance7();
4026 rn = "Performance7";
4027 // break;
4028 default:
4029 goto die;
4030 }
4031 break;
4032 case 26:
4033 /* ignored */
4034 rn = "ECC";
4035 break;
4036 case 27:
4037 switch (sel) {
4038 case 0 ... 3:
4039 /* ignored */
4040 rn = "CacheErr";
4041 break;
4042 default:
4043 goto die;
4044 }
4045 break;
4046 case 28:
4047 switch (sel) {
4048 case 0:
4049 case 2:
4050 case 4:
4051 case 6:
4052 gen_op_mtc0_taglo();
4053 rn = "TagLo";
4054 break;
4055 case 1:
4056 case 3:
4057 case 5:
4058 case 7:
4059 gen_op_mtc0_datalo();
4060 rn = "DataLo";
4061 break;
4062 default:
4063 goto die;
4064 }
4065 break;
4066 case 29:
4067 switch (sel) {
4068 case 0:
4069 case 2:
4070 case 4:
4071 case 6:
4072 gen_op_mtc0_taghi();
4073 rn = "TagHi";
4074 break;
4075 case 1:
4076 case 3:
4077 case 5:
4078 case 7:
4079 gen_op_mtc0_datahi();
4080 rn = "DataHi";
4081 break;
4082 default:
4083 rn = "invalid sel";
4084 goto die;
4085 }
4086 break;
4087 case 30:
4088 switch (sel) {
4089 case 0:
4090 gen_op_dmtc0_errorepc();
4091 rn = "ErrorEPC";
4092 break;
4093 default:
4094 goto die;
4095 }
4096 break;
4097 case 31:
4098 switch (sel) {
4099 case 0:
4100 gen_op_mtc0_desave(); /* EJTAG support */
4101 rn = "DESAVE";
4102 break;
4103 default:
4104 goto die;
4105 }
4106 /* Stop translation as we may have switched the execution mode */
4107 ctx->bstate = BS_STOP;
4108 break;
4109 default:
4110 goto die;
4111 }
4112 #if defined MIPS_DEBUG_DISAS
4113 if (loglevel & CPU_LOG_TB_IN_ASM) {
4114 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4115 rn, reg, sel);
4116 }
4117 #endif
4118 return;
4119
4120 die:
4121 #if defined MIPS_DEBUG_DISAS
4122 if (loglevel & CPU_LOG_TB_IN_ASM) {
4123 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4124 rn, reg, sel);
4125 }
4126 #endif
4127 generate_exception(ctx, EXCP_RI);
4128 }
4129 #endif /* TARGET_MIPS64 */
4130
4131 static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
4132 {
4133 const char *opn = "unk";
4134
4135 switch (opc) {
4136 case OPC_MFC0:
4137 if (rt == 0) {
4138 /* Treat as NOP */
4139 return;
4140 }
4141 gen_mfc0(ctx, rd, ctx->opcode & 0x7);
4142 gen_op_store_T0_gpr(rt);
4143 opn = "mfc0";
4144 break;
4145 case OPC_MTC0:
4146 GEN_LOAD_REG_TN(T0, rt);
4147 gen_mtc0(ctx, rd, ctx->opcode & 0x7);
4148 opn = "mtc0";
4149 break;
4150 #ifdef TARGET_MIPS64
4151 case OPC_DMFC0:
4152 if (rt == 0) {
4153 /* Treat as NOP */
4154 return;
4155 }
4156 gen_dmfc0(ctx, rd, ctx->opcode & 0x7);
4157 gen_op_store_T0_gpr(rt);
4158 opn = "dmfc0";
4159 break;
4160 case OPC_DMTC0:
4161 GEN_LOAD_REG_TN(T0, rt);
4162 gen_dmtc0(ctx, rd, ctx->opcode & 0x7);
4163 opn = "dmtc0";
4164 break;
4165 #endif
4166 #if defined(MIPS_USES_R4K_TLB)
4167 case OPC_TLBWI:
4168 gen_op_tlbwi();
4169 opn = "tlbwi";
4170 break;
4171 case OPC_TLBWR:
4172 gen_op_tlbwr();
4173 opn = "tlbwr";
4174 break;
4175 case OPC_TLBP:
4176 gen_op_tlbp();
4177 opn = "tlbp";
4178 break;
4179 case OPC_TLBR:
4180 gen_op_tlbr();
4181 opn = "tlbr";
4182 break;
4183 #endif
4184 case OPC_ERET:
4185 opn = "eret";
4186 save_cpu_state(ctx, 0);
4187 gen_op_eret();
4188 ctx->bstate = BS_EXCP;
4189 break;
4190 case OPC_DERET:
4191 opn = "deret";
4192 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
4193 generate_exception(ctx, EXCP_RI);
4194 } else {
4195 save_cpu_state(ctx, 0);
4196 gen_op_deret();
4197 ctx->bstate = BS_EXCP;
4198 }
4199 break;
4200 case OPC_WAIT:
4201 opn = "wait";
4202 /* If we get an exception, we want to restart at next instruction */
4203 ctx->pc += 4;
4204 save_cpu_state(ctx, 1);
4205 ctx->pc -= 4;
4206 gen_op_wait();
4207 ctx->bstate = BS_EXCP;
4208 break;
4209 default:
4210 if (loglevel & CPU_LOG_TB_IN_ASM) {
4211 fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
4212 ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4213 ((ctx->opcode >> 16) & 0x1F));
4214 }
4215 generate_exception(ctx, EXCP_RI);
4216 return;
4217 }
4218 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
4219 }
4220
4221 /* CP1 Branches (before delay slot) */
4222 static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4223 int32_t offset)
4224 {
4225 target_ulong btarget;
4226
4227 btarget = ctx->pc + 4 + offset;
4228
4229 switch (op) {
4230 case OPC_BC1F:
4231 gen_op_bc1f();
4232 MIPS_DEBUG("bc1f " TARGET_FMT_lx, btarget);
4233 goto not_likely;
4234 case OPC_BC1FL:
4235 gen_op_bc1f();
4236 MIPS_DEBUG("bc1fl " TARGET_FMT_lx, btarget);
4237 goto likely;
4238 case OPC_BC1T:
4239 gen_op_bc1t();
4240 MIPS_DEBUG("bc1t " TARGET_FMT_lx, btarget);
4241 not_likely:
4242 ctx->hflags |= MIPS_HFLAG_BC;
4243 break;
4244 case OPC_BC1TL:
4245 gen_op_bc1t();
4246 MIPS_DEBUG("bc1tl " TARGET_FMT_lx, btarget);
4247 likely:
4248 ctx->hflags |= MIPS_HFLAG_BL;
4249 break;
4250 default:
4251 MIPS_INVAL("cp1 branch/jump");
4252 generate_exception (ctx, EXCP_RI);
4253 return;
4254 }
4255 gen_op_set_bcond();
4256
4257 MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx,
4258 ctx->hflags, btarget);
4259 ctx->btarget = btarget;
4260
4261 return;
4262 }
4263
4264 /* Coprocessor 1 (FPU) */
4265 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4266 {
4267 const char *opn = "unk";
4268
4269 switch (opc) {
4270 case OPC_MFC1:
4271 GEN_LOAD_FREG_FTN(WT0, fs);
4272 gen_op_mfc1();
4273 GEN_STORE_TN_REG(rt, T0);
4274 opn = "mfc1";
4275 break;
4276 case OPC_MTC1:
4277 GEN_LOAD_REG_TN(T0, rt);
4278 gen_op_mtc1();
4279 GEN_STORE_FTN_FREG(fs, WT0);
4280 opn = "mtc1";
4281 break;
4282 case OPC_CFC1:
4283 if (fs != 0 && fs != 31) {
4284 MIPS_INVAL("cfc1 freg");
4285 generate_exception (ctx, EXCP_RI);
4286 return;
4287 }
4288 GEN_LOAD_IMM_TN(T1, fs);
4289 gen_op_cfc1();
4290 GEN_STORE_TN_REG(rt, T0);
4291 opn = "cfc1";
4292 break;
4293 case OPC_CTC1:
4294 if (fs != 0 && fs != 31) {
4295 MIPS_INVAL("ctc1 freg");
4296 generate_exception (ctx, EXCP_RI);
4297 return;
4298 }
4299 GEN_LOAD_IMM_TN(T1, fs);
4300 GEN_LOAD_REG_TN(T0, rt);
4301 gen_op_ctc1();
4302 opn = "ctc1";
4303 break;
4304 case OPC_DMFC1:
4305 case OPC_DMTC1:
4306 /* Not implemented, fallthrough. */
4307 default:
4308 if (loglevel & CPU_LOG_TB_IN_ASM) {
4309 fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
4310 ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4311 ((ctx->opcode >> 16) & 0x1F));
4312 }
4313 generate_exception (ctx, EXCP_RI);
4314 return;
4315 }
4316 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
4317 }
4318
4319 /* verify if floating point register is valid; an operation is not defined
4320 * if bit 0 of any register specification is set and the FR bit in the
4321 * Status register equals zero, since the register numbers specify an
4322 * even-odd pair of adjacent coprocessor general registers. When the FR bit
4323 * in the Status register equals one, both even and odd register numbers
4324 * are valid. This limitation exists only for 64 bit wide (d,l) registers.
4325 *
4326 * Multiple 64 bit wide registers can be checked by calling
4327 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
4328 */
4329 #define CHECK_FR(ctx, freg) do { \
4330 if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
4331 generate_exception (ctx, EXCP_RI); \
4332 return; \
4333 } \
4334 } while(0)
4335
4336 #define FOP(func, fmt) (((fmt) << 21) | (func))
4337
4338 static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
4339 {
4340 const char *opn = "unk";
4341 const char *condnames[] = {
4342 "c.f",
4343 "c.un",
4344 "c.eq",
4345 "c.ueq",
4346 "c.olt",
4347 "c.ult",
4348 "c.ole",
4349 "c.ule",
4350 "c.sf",
4351 "c.ngle",
4352 "c.seq",
4353 "c.ngl",
4354 "c.lt",
4355 "c.nge",
4356 "c.le",
4357 "c.ngt",
4358 };
4359 int binary = 0;
4360 uint32_t func = ctx->opcode & 0x3f;
4361
4362 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
4363 case FOP(0, 17):
4364 CHECK_FR(ctx, fs | ft | fd);
4365 GEN_LOAD_FREG_FTN(DT0, fs);
4366 GEN_LOAD_FREG_FTN(DT1, ft);
4367 gen_op_float_add_d();
4368 GEN_STORE_FTN_FREG(fd, DT2);
4369 opn = "add.d";
4370 binary = 1;
4371 break;
4372 case FOP(1, 17):
4373 CHECK_FR(ctx, fs | ft | fd);
4374 GEN_LOAD_FREG_FTN(DT0, fs);
4375 GEN_LOAD_FREG_FTN(DT1, ft);
4376 gen_op_float_sub_d();
4377 GEN_STORE_FTN_FREG(fd, DT2);
4378 opn = "sub.d";
4379 binary = 1;
4380 break;
4381 case FOP(2, 17):
4382 CHECK_FR(ctx, fs | ft | fd);
4383 GEN_LOAD_FREG_FTN(DT0, fs);
4384 GEN_LOAD_FREG_FTN(DT1, ft);
4385 gen_op_float_mul_d();
4386 GEN_STORE_FTN_FREG(fd, DT2);
4387 opn = "mul.d";
4388 binary = 1;
4389 break;
4390 case FOP(3, 17):
4391 CHECK_FR(ctx, fs | ft | fd);
4392 GEN_LOAD_FREG_FTN(DT0, fs);
4393 GEN_LOAD_FREG_FTN(DT1, ft);
4394 gen_op_float_div_d();
4395 GEN_STORE_FTN_FREG(fd, DT2);
4396 opn = "div.d";
4397 binary = 1;
4398 break;
4399 case FOP(4, 17):
4400 CHECK_FR(ctx, fs | fd);
4401 GEN_LOAD_FREG_FTN(DT0, fs);
4402 gen_op_float_sqrt_d();
4403 GEN_STORE_FTN_FREG(fd, DT2);
4404 opn = "sqrt.d";
4405 break;
4406 case FOP(5, 17):
4407 CHECK_FR(ctx, fs | fd);
4408 GEN_LOAD_FREG_FTN(DT0, fs);
4409 gen_op_float_abs_d();
4410 GEN_STORE_FTN_FREG(fd, DT2);
4411 opn = "abs.d";
4412 break;
4413 case FOP(6, 17):
4414 CHECK_FR(ctx, fs | fd);
4415 GEN_LOAD_FREG_FTN(DT0, fs);
4416 gen_op_float_mov_d();
4417 GEN_STORE_FTN_FREG(fd, DT2);
4418 opn = "mov.d";
4419 break;
4420 case FOP(7, 17):
4421 CHECK_FR(ctx, fs | fd);
4422 GEN_LOAD_FREG_FTN(DT0, fs);
4423 gen_op_float_chs_d();
4424 GEN_STORE_FTN_FREG(fd, DT2);
4425 opn = "neg.d";
4426 break;
4427 /* 8 - round.l */
4428 /* 9 - trunc.l */
4429 /* 10 - ceil.l */
4430 /* 11 - floor.l */
4431 case FOP(12, 17):
4432 CHECK_FR(ctx, fs);
4433 GEN_LOAD_FREG_FTN(DT0, fs);
4434 gen_op_float_roundw_d();
4435 GEN_STORE_FTN_FREG(fd, WT2);
4436 opn = "round.w.d";
4437 break;
4438 case FOP(13, 17):
4439 CHECK_FR(ctx, fs);
4440 GEN_LOAD_FREG_FTN(DT0, fs);
4441 gen_op_float_truncw_d();
4442 GEN_STORE_FTN_FREG(fd, WT2);
4443 opn = "trunc.w.d";
4444 break;
4445 case FOP(14, 17):
4446 CHECK_FR(ctx, fs);
4447 GEN_LOAD_FREG_FTN(DT0, fs);
4448 gen_op_float_ceilw_d();
4449 GEN_STORE_FTN_FREG(fd, WT2);
4450 opn = "ceil.w.d";
4451 break;
4452 case FOP(15, 17):
4453 CHECK_FR(ctx, fs);
4454 GEN_LOAD_FREG_FTN(DT0, fs);
4455 gen_op_float_floorw_d();
4456 GEN_STORE_FTN_FREG(fd, WT2);
4457 opn = "floor.w.d";
4458 break;
4459 case FOP(33, 16):
4460 CHECK_FR(ctx, fd);
4461 GEN_LOAD_FREG_FTN(WT0, fs);
4462 gen_op_float_cvtd_s();
4463 GEN_STORE_FTN_FREG(fd, DT2);
4464 opn = "cvt.d.s";
4465 break;
4466 case FOP(33, 20):
4467 CHECK_FR(ctx, fd);
4468 GEN_LOAD_FREG_FTN(WT0, fs);
4469 gen_op_float_cvtd_w();
4470 GEN_STORE_FTN_FREG(fd, DT2);
4471 opn = "cvt.d.w";
4472 break;
4473 case FOP(48, 17):
4474 case FOP(49, 17):
4475 case FOP(50, 17):
4476 case FOP(51, 17):
4477 case FOP(52, 17):
4478 case FOP(53, 17):
4479 case FOP(54, 17):
4480 case FOP(55, 17):
4481 case FOP(56, 17):
4482 case FOP(57, 17):
4483 case FOP(58, 17):
4484 case FOP(59, 17):
4485 case FOP(60, 17):
4486 case FOP(61, 17):
4487 case FOP(62, 17):
4488 case FOP(63, 17):
4489 CHECK_FR(ctx, fs | ft);
4490 GEN_LOAD_FREG_FTN(DT0, fs);
4491 GEN_LOAD_FREG_FTN(DT1, ft);
4492 gen_cmp_d(func-48);
4493 opn = condnames[func-48];
4494 break;
4495 case FOP(0, 16):
4496 GEN_LOAD_FREG_FTN(WT0, fs);
4497 GEN_LOAD_FREG_FTN(WT1, ft);
4498 gen_op_float_add_s();
4499 GEN_STORE_FTN_FREG(fd, WT2);
4500 opn = "add.s";
4501 binary = 1;
4502 break;
4503 case FOP(1, 16):
4504 GEN_LOAD_FREG_FTN(WT0, fs);
4505 GEN_LOAD_FREG_FTN(WT1, ft);
4506 gen_op_float_sub_s();
4507 GEN_STORE_FTN_FREG(fd, WT2);
4508 opn = "sub.s";
4509 binary = 1;
4510 break;
4511 case FOP(2, 16):
4512 GEN_LOAD_FREG_FTN(WT0, fs);
4513 GEN_LOAD_FREG_FTN(WT1, ft);
4514 gen_op_float_mul_s();
4515 GEN_STORE_FTN_FREG(fd, WT2);
4516 opn = "mul.s";
4517 binary = 1;
4518 break;
4519 case FOP(3, 16):
4520 GEN_LOAD_FREG_FTN(WT0, fs);
4521 GEN_LOAD_FREG_FTN(WT1, ft);
4522 gen_op_float_div_s();
4523 GEN_STORE_FTN_FREG(fd, WT2);
4524 opn = "div.s";
4525 binary = 1;
4526 break;
4527 case FOP(4, 16):
4528 GEN_LOAD_FREG_FTN(WT0, fs);
4529 gen_op_float_sqrt_s();
4530 GEN_STORE_FTN_FREG(fd, WT2);
4531 opn = "sqrt.s";
4532 break;
4533 case FOP(5, 16):
4534 GEN_LOAD_FREG_FTN(WT0, fs);
4535 gen_op_float_abs_s();
4536 GEN_STORE_FTN_FREG(fd, WT2);
4537 opn = "abs.s";
4538 break;
4539 case FOP(6, 16):
4540 GEN_LOAD_FREG_FTN(WT0, fs);
4541 gen_op_float_mov_s();
4542 GEN_STORE_FTN_FREG(fd, WT2);
4543 opn = "mov.s";
4544 break;
4545 case FOP(7, 16):
4546 GEN_LOAD_FREG_FTN(WT0, fs);
4547 gen_op_float_chs_s();
4548 GEN_STORE_FTN_FREG(fd, WT2);
4549 opn = "neg.s";
4550 break;
4551 case FOP(12, 16):
4552 GEN_LOAD_FREG_FTN(WT0, fs);
4553 gen_op_float_roundw_s();
4554 GEN_STORE_FTN_FREG(fd, WT2);
4555 opn = "round.w.s";
4556 break;
4557 case FOP(13, 16):
4558 GEN_LOAD_FREG_FTN(WT0, fs);
4559 gen_op_float_truncw_s();
4560 GEN_STORE_FTN_FREG(fd, WT2);
4561 opn = "trunc.w.s";
4562 break;
4563 case FOP(32, 17):
4564 CHECK_FR(ctx, fs);
4565 GEN_LOAD_FREG_FTN(DT0, fs);
4566 gen_op_float_cvts_d();
4567 GEN_STORE_FTN_FREG(fd, WT2);
4568 opn = "cvt.s.d";
4569 break;
4570 case FOP(32, 20):
4571 GEN_LOAD_FREG_FTN(WT0, fs);
4572 gen_op_float_cvts_w();
4573 GEN_STORE_FTN_FREG(fd, WT2);
4574 opn = "cvt.s.w";
4575 break;
4576 case FOP(36, 16):
4577 GEN_LOAD_FREG_FTN(WT0, fs);
4578 gen_op_float_cvtw_s();
4579 GEN_STORE_FTN_FREG(fd, WT2);
4580 opn = "cvt.w.s";
4581 break;
4582 case FOP(36, 17):
4583 CHECK_FR(ctx, fs);
4584 GEN_LOAD_FREG_FTN(DT0, fs);
4585 gen_op_float_cvtw_d();
4586 GEN_STORE_FTN_FREG(fd, WT2);
4587 opn = "cvt.w.d";
4588 break;
4589 case FOP(48, 16):
4590 case FOP(49, 16):
4591 case FOP(50, 16):
4592 case FOP(51, 16):
4593 case FOP(52, 16):
4594 case FOP(53, 16):
4595 case FOP(54, 16):
4596 case FOP(55, 16):
4597 case FOP(56, 16):
4598 case FOP(57, 16):
4599 case FOP(58, 16):
4600 case FOP(59, 16):
4601 case FOP(60, 16):
4602 case FOP(61, 16):
4603 case FOP(62, 16):
4604 case FOP(63, 16):
4605 GEN_LOAD_FREG_FTN(WT0, fs);
4606 GEN_LOAD_FREG_FTN(WT1, ft);
4607 gen_cmp_s(func-48);
4608 opn = condnames[func-48];
4609 break;
4610 default:
4611 if (loglevel & CPU_LOG_TB_IN_ASM) {
4612 fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
4613 ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4614 ((ctx->opcode >> 16) & 0x1F));
4615 }
4616 generate_exception (ctx, EXCP_RI);
4617 return;
4618 }
4619 if (binary)
4620 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
4621 else
4622 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
4623 }
4624
4625 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4626 {
4627 uint32_t ccbit;
4628
4629 if (cc)
4630 ccbit = 1 << (24 + cc);
4631 else
4632 ccbit = 1 << 23;
4633 if (!tf)
4634 gen_op_movf(ccbit, rd, rs);
4635 else
4636 gen_op_movt(ccbit, rd, rs);
4637 }
4638
4639 /* ISA extensions (ASEs) */
4640 /* MIPS16 extension to MIPS32 */
4641 /* SmartMIPS extension to MIPS32 */
4642
4643 #ifdef TARGET_MIPS64
4644 /* Coprocessor 3 (FPU) */
4645
4646 /* MDMX extension to MIPS64 */
4647 /* MIPS-3D extension to MIPS64 */
4648
4649 #endif
4650
4651 static void gen_blikely(DisasContext *ctx)
4652 {
4653 int l1;
4654 l1 = gen_new_label();
4655 gen_op_jnz_T2(l1);
4656 gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
4657 gen_goto_tb(ctx, 1, ctx->pc + 4);
4658 gen_set_label(l1);
4659 }
4660
4661 static void decode_opc (CPUState *env, DisasContext *ctx)
4662 {
4663 int32_t offset;
4664 int rs, rt, rd, sa;
4665 uint32_t op, op1, op2;
4666 int16_t imm;
4667
4668 /* make sure instructions are on a word boundary */
4669 if (ctx->pc & 0x3) {
4670 env->CP0_BadVAddr = ctx->pc;
4671 generate_exception(ctx, EXCP_AdEL);
4672 return;
4673 }
4674
4675 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
4676 /* Handle blikely not taken case */
4677 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
4678 gen_blikely(ctx);
4679 }
4680 op = MASK_OP_MAJOR(ctx->opcode);
4681 rs = (ctx->opcode >> 21) & 0x1f;
4682 rt = (ctx->opcode >> 16) & 0x1f;
4683 rd = (ctx->opcode >> 11) & 0x1f;
4684 sa = (ctx->opcode >> 6) & 0x1f;
4685 imm = (int16_t)ctx->opcode;
4686 switch (op) {
4687 case OPC_SPECIAL:
4688 op1 = MASK_SPECIAL(ctx->opcode);
4689 switch (op1) {
4690 case OPC_SLL: /* Arithmetic with immediate */
4691 case OPC_SRL ... OPC_SRA:
4692 gen_arith_imm(ctx, op1, rd, rt, sa);
4693 break;
4694 case OPC_SLLV: /* Arithmetic */
4695 case OPC_SRLV ... OPC_SRAV:
4696 case OPC_MOVZ ... OPC_MOVN:
4697 case OPC_ADD ... OPC_NOR:
4698 case OPC_SLT ... OPC_SLTU:
4699 gen_arith(ctx, op1, rd, rs, rt);
4700 break;
4701 case OPC_MULT ... OPC_DIVU:
4702 gen_muldiv(ctx, op1, rs, rt);
4703 break;
4704 case OPC_JR ... OPC_JALR:
4705 gen_compute_branch(ctx, op1, rs, rd, sa);
4706 return;
4707 case OPC_TGE ... OPC_TEQ: /* Traps */
4708 case OPC_TNE:
4709 gen_trap(ctx, op1, rs, rt, -1);
4710 break;
4711 case OPC_MFHI: /* Move from HI/LO */
4712 case OPC_MFLO:
4713 gen_HILO(ctx, op1, rd);
4714 break;
4715 case OPC_MTHI:
4716 case OPC_MTLO: /* Move to HI/LO */
4717 gen_HILO(ctx, op1, rs);
4718 break;
4719 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
4720 #ifdef MIPS_STRICT_STANDARD
4721 MIPS_INVAL("PMON / selsl");
4722 generate_exception(ctx, EXCP_RI);
4723 #else
4724 gen_op_pmon(sa);
4725 #endif
4726 break;
4727 case OPC_SYSCALL:
4728 generate_exception(ctx, EXCP_SYSCALL);
4729 break;
4730 case OPC_BREAK:
4731 generate_exception(ctx, EXCP_BREAK);
4732 break;
4733 case OPC_SPIM:
4734 #ifdef MIPS_STRICT_STANDARD
4735 MIPS_INVAL("SPIM");
4736 generate_exception(ctx, EXCP_RI);
4737 #else
4738 /* Implemented as RI exception for now. */
4739 MIPS_INVAL("spim (unofficial)");
4740 generate_exception(ctx, EXCP_RI);
4741 #endif
4742 break;
4743 case OPC_SYNC:
4744 /* Treat as a noop. */
4745 break;
4746
4747 case OPC_MOVCI:
4748 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4749 save_cpu_state(ctx, 1);
4750 gen_op_cp1_enabled();
4751 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
4752 (ctx->opcode >> 16) & 1);
4753 } else {
4754 generate_exception_err(ctx, EXCP_CpU, 1);
4755 }
4756 break;
4757
4758 #ifdef TARGET_MIPS64
4759 /* MIPS64 specific opcodes */
4760 case OPC_DSLL:
4761 case OPC_DSRL ... OPC_DSRA:
4762 case OPC_DSLL32:
4763 case OPC_DSRL32 ... OPC_DSRA32:
4764 gen_arith_imm(ctx, op1, rd, rt, sa);
4765 break;
4766 case OPC_DSLLV:
4767 case OPC_DSRLV ... OPC_DSRAV:
4768 case OPC_DADD ... OPC_DSUBU:
4769 gen_arith(ctx, op1, rd, rs, rt);
4770 break;
4771 case OPC_DMULT ... OPC_DDIVU:
4772 gen_muldiv(ctx, op1, rs, rt);
4773 break;
4774 #endif
4775 default: /* Invalid */
4776 MIPS_INVAL("special");
4777 generate_exception(ctx, EXCP_RI);
4778 break;
4779 }
4780 break;
4781 case OPC_SPECIAL2:
4782 op1 = MASK_SPECIAL2(ctx->opcode);
4783 switch (op1) {
4784 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
4785 case OPC_MSUB ... OPC_MSUBU:
4786 gen_muldiv(ctx, op1, rs, rt);
4787 break;
4788 case OPC_MUL:
4789 gen_arith(ctx, op1, rd, rs, rt);
4790 break;
4791 case OPC_CLZ ... OPC_CLO:
4792 gen_cl(ctx, op1, rd, rs);
4793 break;
4794 case OPC_SDBBP:
4795 /* XXX: not clear which exception should be raised
4796 * when in debug mode...
4797 */
4798 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
4799 generate_exception(ctx, EXCP_DBp);
4800 } else {
4801 generate_exception(ctx, EXCP_DBp);
4802 }
4803 /* Treat as a noop */
4804 break;
4805 #ifdef TARGET_MIPS64
4806 case OPC_DCLZ ... OPC_DCLO:
4807 gen_cl(ctx, op1, rd, rs);
4808 break;
4809 #endif
4810 default: /* Invalid */
4811 MIPS_INVAL("special2");
4812 generate_exception(ctx, EXCP_RI);
4813 break;
4814 }
4815 break;
4816 case OPC_SPECIAL3:
4817 op1 = MASK_SPECIAL3(ctx->opcode);
4818 switch (op1) {
4819 case OPC_EXT:
4820 case OPC_INS:
4821 gen_bitops(ctx, op1, rt, rs, sa, rd);
4822 break;
4823 case OPC_BSHFL:
4824 op2 = MASK_BSHFL(ctx->opcode);
4825 switch (op2) {
4826 case OPC_WSBH:
4827 GEN_LOAD_REG_TN(T1, rt);
4828 gen_op_wsbh();
4829 break;
4830 case OPC_SEB:
4831 GEN_LOAD_REG_TN(T1, rt);
4832 gen_op_seb();
4833 break;
4834 case OPC_SEH:
4835 GEN_LOAD_REG_TN(T1, rt);
4836 gen_op_seh();
4837 break;
4838 default: /* Invalid */
4839 MIPS_INVAL("bshfl");
4840 generate_exception(ctx, EXCP_RI);
4841 break;
4842 }
4843 GEN_STORE_TN_REG(rd, T0);
4844 break;
4845 case OPC_RDHWR:
4846 switch (rd) {
4847 case 0:
4848 save_cpu_state(ctx, 1);
4849 gen_op_rdhwr_cpunum();
4850 break;
4851 case 1:
4852 save_cpu_state(ctx, 1);
4853 gen_op_rdhwr_synci_step();
4854 break;
4855 case 2:
4856 save_cpu_state(ctx, 1);
4857 gen_op_rdhwr_cc();
4858 break;
4859 case 3:
4860 save_cpu_state(ctx, 1);
4861 gen_op_rdhwr_ccres();
4862 break;
4863 case 29:
4864 #if defined (CONFIG_USER_ONLY)
4865 gen_op_tls_value ();
4866 break;
4867 #endif
4868 default: /* Invalid */
4869 MIPS_INVAL("rdhwr");
4870 generate_exception(ctx, EXCP_RI);
4871 break;
4872 }
4873 GEN_STORE_TN_REG(rt, T0);
4874 break;
4875 #ifdef TARGET_MIPS64
4876 case OPC_DEXTM ... OPC_DEXT:
4877 case OPC_DINSM ... OPC_DINS:
4878 gen_bitops(ctx, op1, rt, rs, sa, rd);
4879 break;
4880 case OPC_DBSHFL:
4881 op2 = MASK_DBSHFL(ctx->opcode);
4882 switch (op2) {
4883 case OPC_DSBH:
4884 GEN_LOAD_REG_TN(T1, rt);
4885 gen_op_dsbh();
4886 break;
4887 case OPC_DSHD:
4888 GEN_LOAD_REG_TN(T1, rt);
4889 gen_op_dshd();
4890 break;
4891 default: /* Invalid */
4892 MIPS_INVAL("dbshfl");
4893 generate_exception(ctx, EXCP_RI);
4894 break;
4895 }
4896 GEN_STORE_TN_REG(rd, T0);
4897 #endif
4898 default: /* Invalid */
4899 MIPS_INVAL("special3");
4900 generate_exception(ctx, EXCP_RI);
4901 break;
4902 }
4903 break;
4904 case OPC_REGIMM:
4905 op1 = MASK_REGIMM(ctx->opcode);
4906 switch (op1) {
4907 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
4908 case OPC_BLTZAL ... OPC_BGEZALL:
4909 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
4910 return;
4911 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
4912 case OPC_TNEI:
4913 gen_trap(ctx, op1, rs, -1, imm);
4914 break;
4915 case OPC_SYNCI:
4916 /* treat as noop */
4917 break;
4918 default: /* Invalid */
4919 MIPS_INVAL("REGIMM");
4920 generate_exception(ctx, EXCP_RI);
4921 break;
4922 }
4923 break;
4924 case OPC_CP0:
4925 save_cpu_state(ctx, 1);
4926 gen_op_cp0_enabled();
4927 op1 = MASK_CP0(ctx->opcode);
4928 switch (op1) {
4929 case OPC_MFC0:
4930 case OPC_MTC0:
4931 #ifdef TARGET_MIPS64
4932 case OPC_DMFC0:
4933 case OPC_DMTC0:
4934 #endif
4935 gen_cp0(ctx, op1, rt, rd);
4936 break;
4937 case OPC_C0_FIRST ... OPC_C0_LAST:
4938 gen_cp0(ctx, MASK_C0(ctx->opcode), rt, rd);
4939 break;
4940 case OPC_MFMC0:
4941 op2 = MASK_MFMC0(ctx->opcode);
4942 switch (op2) {
4943 case OPC_DI:
4944 gen_op_di();
4945 /* Stop translation as we may have switched the execution mode */
4946 ctx->bstate = BS_STOP;
4947 break;
4948 case OPC_EI:
4949 gen_op_ei();
4950 /* Stop translation as we may have switched the execution mode */
4951 ctx->bstate = BS_STOP;
4952 break;
4953 default: /* Invalid */
4954 MIPS_INVAL("MFMC0");
4955 generate_exception(ctx, EXCP_RI);
4956 break;
4957 }
4958 GEN_STORE_TN_REG(rt, T0);
4959 break;
4960 case OPC_RDPGPR:
4961 case OPC_WRPGPR:
4962 if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) {
4963 /* Shadow registers not implemented. */
4964 GEN_LOAD_REG_TN(T0, rt);
4965 GEN_STORE_TN_REG(rd, T0);
4966 } else
4967 generate_exception(ctx, EXCP_RI);
4968 break;
4969 default:
4970 generate_exception(ctx, EXCP_RI);
4971 break;
4972 }
4973 break;
4974 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
4975 gen_arith_imm(ctx, op, rt, rs, imm);
4976 break;
4977 case OPC_J ... OPC_JAL: /* Jump */
4978 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
4979 gen_compute_branch(ctx, op, rs, rt, offset);
4980 return;
4981 case OPC_BEQ ... OPC_BGTZ: /* Branch */
4982 case OPC_BEQL ... OPC_BGTZL:
4983 gen_compute_branch(ctx, op, rs, rt, imm << 2);
4984 return;
4985 case OPC_LB ... OPC_LWR: /* Load and stores */
4986 case OPC_SB ... OPC_SW:
4987 case OPC_SWR:
4988 case OPC_LL:
4989 case OPC_SC:
4990 gen_ldst(ctx, op, rt, rs, imm);
4991 break;
4992 case OPC_CACHE:
4993 /* Treat as a noop */
4994 break;
4995 case OPC_PREF:
4996 /* Treat as a noop */
4997 break;
4998
4999 /* Floating point. */
5000 case OPC_LWC1:
5001 case OPC_LDC1:
5002 case OPC_SWC1:
5003 case OPC_SDC1:
5004 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5005 save_cpu_state(ctx, 1);
5006 gen_op_cp1_enabled();
5007 gen_flt_ldst(ctx, op, rt, rs, imm);
5008 } else {
5009 generate_exception_err(ctx, EXCP_CpU, 1);
5010 }
5011 break;
5012
5013 case OPC_CP1:
5014 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5015 save_cpu_state(ctx, 1);
5016 gen_op_cp1_enabled();
5017 op1 = MASK_CP1(ctx->opcode);
5018 switch (op1) {
5019 case OPC_MFC1:
5020 case OPC_CFC1:
5021 case OPC_MTC1:
5022 case OPC_CTC1:
5023 #ifdef TARGET_MIPS64
5024 case OPC_DMFC1:
5025 case OPC_DMTC1:
5026 #endif
5027 gen_cp1(ctx, op1, rt, rd);
5028 break;
5029 case OPC_BC1:
5030 gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
5031 return;
5032 case OPC_S_FMT:
5033 case OPC_D_FMT:
5034 case OPC_W_FMT:
5035 case OPC_L_FMT:
5036 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
5037 break;
5038 default:
5039 generate_exception (ctx, EXCP_RI);
5040 break;
5041 }
5042 } else {
5043 generate_exception_err(ctx, EXCP_CpU, 1);
5044 }
5045 break;
5046
5047 /* COP2. */
5048 case OPC_LWC2:
5049 case OPC_LDC2:
5050 case OPC_SWC2:
5051 case OPC_SDC2:
5052 case OPC_CP2:
5053 /* COP2: Not implemented. */
5054 generate_exception_err(ctx, EXCP_CpU, 2);
5055 break;
5056
5057 case OPC_CP3:
5058 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5059 save_cpu_state(ctx, 1);
5060 gen_op_cp1_enabled();
5061 op1 = MASK_CP3(ctx->opcode);
5062 switch (op1) {
5063 case OPC_PREFX:
5064 /* treat as noop */
5065 break;
5066 /* Not implemented */
5067 default:
5068 generate_exception (ctx, EXCP_RI);
5069 break;
5070 }
5071 } else {
5072 generate_exception_err(ctx, EXCP_CpU, 1);
5073 }
5074 break;
5075
5076 #ifdef TARGET_MIPS64
5077 /* MIPS64 opcodes */
5078 case OPC_LWU:
5079 case OPC_LDL ... OPC_LDR:
5080 case OPC_SDL ... OPC_SDR:
5081 case OPC_LLD:
5082 case OPC_LD:
5083 case OPC_SCD:
5084 case OPC_SD:
5085 gen_ldst(ctx, op, rt, rs, imm);
5086 break;
5087 case OPC_DADDI ... OPC_DADDIU:
5088 gen_arith_imm(ctx, op, rt, rs, imm);
5089 break;
5090 #endif
5091 #ifdef MIPS_HAS_MIPS16
5092 case OPC_JALX:
5093 /* MIPS16: Not implemented. */
5094 #endif
5095 #ifdef MIPS_HAS_MDMX
5096 case OPC_MDMX:
5097 /* MDMX: Not implemented. */
5098 #endif
5099 default: /* Invalid */
5100 MIPS_INVAL("");
5101 generate_exception(ctx, EXCP_RI);
5102 break;
5103 }
5104 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5105 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
5106 /* Branches completion */
5107 ctx->hflags &= ~MIPS_HFLAG_BMASK;
5108 ctx->bstate = BS_BRANCH;
5109 save_cpu_state(ctx, 0);
5110 switch (hflags & MIPS_HFLAG_BMASK) {
5111 case MIPS_HFLAG_B:
5112 /* unconditional branch */
5113 MIPS_DEBUG("unconditional branch");
5114 gen_goto_tb(ctx, 0, ctx->btarget);
5115 break;
5116 case MIPS_HFLAG_BL:
5117 /* blikely taken case */
5118 MIPS_DEBUG("blikely branch taken");
5119 gen_goto_tb(ctx, 0, ctx->btarget);
5120 break;
5121 case MIPS_HFLAG_BC:
5122 /* Conditional branch */
5123 MIPS_DEBUG("conditional branch");
5124 {
5125 int l1;
5126 l1 = gen_new_label();
5127 gen_op_jnz_T2(l1);
5128 gen_goto_tb(ctx, 1, ctx->pc + 4);
5129 gen_set_label(l1);
5130 gen_goto_tb(ctx, 0, ctx->btarget);
5131 }
5132 break;
5133 case MIPS_HFLAG_BR:
5134 /* unconditional branch to register */
5135 MIPS_DEBUG("branch to register");
5136 gen_op_breg();
5137 break;
5138 default:
5139 MIPS_DEBUG("unknown branch");
5140 break;
5141 }
5142 }
5143 }
5144
5145 static inline int
5146 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5147 int search_pc)
5148 {
5149 DisasContext ctx, *ctxp = &ctx;
5150 target_ulong pc_start;
5151 uint16_t *gen_opc_end;
5152 int j, lj = -1;
5153
5154 if (search_pc && loglevel)
5155 fprintf (logfile, "search pc %d\n", search_pc);
5156
5157 pc_start = tb->pc;
5158 gen_opc_ptr = gen_opc_buf;
5159 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
5160 gen_opparam_ptr = gen_opparam_buf;
5161 nb_gen_labels = 0;
5162 ctx.pc = pc_start;
5163 ctx.saved_pc = -1;
5164 ctx.tb = tb;
5165 ctx.bstate = BS_NONE;
5166 /* Restore delay slot state from the tb context. */
5167 ctx.hflags = tb->flags;
5168 ctx.saved_hflags = ctx.hflags;
5169 if (ctx.hflags & MIPS_HFLAG_BR) {
5170 gen_op_restore_breg_target();
5171 } else if (ctx.hflags & MIPS_HFLAG_B) {
5172 ctx.btarget = env->btarget;
5173 } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
5174 /* If we are in the delay slot of a conditional branch,
5175 * restore the branch condition from env->bcond to T2
5176 */
5177 ctx.btarget = env->btarget;
5178 gen_op_restore_bcond();
5179 }
5180 #if defined(CONFIG_USER_ONLY)
5181 ctx.mem_idx = 0;
5182 #else
5183 ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
5184 #endif
5185 ctx.CP0_Status = env->CP0_Status;
5186 #ifdef DEBUG_DISAS
5187 if (loglevel & CPU_LOG_TB_CPU) {
5188 fprintf(logfile, "------------------------------------------------\n");
5189 /* FIXME: This may print out stale hflags from env... */
5190 cpu_dump_state(env, logfile, fprintf, 0);
5191 }
5192 #endif
5193 #if defined MIPS_DEBUG_DISAS
5194 if (loglevel & CPU_LOG_TB_IN_ASM)
5195 fprintf(logfile, "\ntb %p super %d cond %04x\n",
5196 tb, ctx.mem_idx, ctx.hflags);
5197 #endif
5198 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
5199 if (env->nb_breakpoints > 0) {
5200 for(j = 0; j < env->nb_breakpoints; j++) {
5201 if (env->breakpoints[j] == ctx.pc) {
5202 save_cpu_state(ctxp, 1);
5203 ctx.bstate = BS_BRANCH;
5204 gen_op_debug();
5205 goto done_generating;
5206 }
5207 }
5208 }
5209
5210 if (search_pc) {
5211 j = gen_opc_ptr - gen_opc_buf;
5212 if (lj < j) {
5213 lj++;
5214 while (lj < j)
5215 gen_opc_instr_start[lj++] = 0;
5216 }
5217 gen_opc_pc[lj] = ctx.pc;
5218 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
5219 gen_opc_instr_start[lj] = 1;
5220 }
5221 ctx.opcode = ldl_code(ctx.pc);
5222 decode_opc(env, &ctx);
5223 ctx.pc += 4;
5224
5225 if (env->singlestep_enabled)
5226 break;
5227
5228 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
5229 break;
5230
5231 #if defined (MIPS_SINGLE_STEP)
5232 break;
5233 #endif
5234 }
5235 if (env->singlestep_enabled) {
5236 save_cpu_state(ctxp, ctx.bstate == BS_NONE);
5237 gen_op_debug();
5238 } else {
5239 switch (ctx.bstate) {
5240 case BS_EXCP:
5241 gen_op_interrupt_restart();
5242 gen_op_reset_T0();
5243 /* Generate the return instruction. */
5244 gen_op_exit_tb();
5245 break;
5246 case BS_STOP:
5247 gen_op_interrupt_restart();
5248 /* Fall through. */
5249 case BS_NONE:
5250 save_cpu_state(ctxp, 0);
5251 gen_goto_tb(&ctx, 0, ctx.pc);
5252 break;
5253 case BS_BRANCH:
5254 default:
5255 gen_op_reset_T0();
5256 /* Generate the return instruction. */
5257 gen_op_exit_tb();
5258 break;
5259 }
5260 }
5261 done_generating:
5262 *gen_opc_ptr = INDEX_op_end;
5263 if (search_pc) {
5264 j = gen_opc_ptr - gen_opc_buf;
5265 lj++;
5266 while (lj <= j)
5267 gen_opc_instr_start[lj++] = 0;
5268 tb->size = 0;
5269 } else {
5270 tb->size = ctx.pc - pc_start;
5271 }
5272 #ifdef DEBUG_DISAS
5273 #if defined MIPS_DEBUG_DISAS
5274 if (loglevel & CPU_LOG_TB_IN_ASM)
5275 fprintf(logfile, "\n");
5276 #endif
5277 if (loglevel & CPU_LOG_TB_IN_ASM) {
5278 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
5279 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
5280 fprintf(logfile, "\n");
5281 }
5282 if (loglevel & CPU_LOG_TB_OP) {
5283 fprintf(logfile, "OP:\n");
5284 dump_ops(gen_opc_buf, gen_opparam_buf);
5285 fprintf(logfile, "\n");
5286 }
5287 if (loglevel & CPU_LOG_TB_CPU) {
5288 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
5289 }
5290 #endif
5291
5292 return 0;
5293 }
5294
5295 int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
5296 {
5297 return gen_intermediate_code_internal(env, tb, 0);
5298 }
5299
5300 int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
5301 {
5302 return gen_intermediate_code_internal(env, tb, 1);
5303 }
5304
5305 void fpu_dump_state(CPUState *env, FILE *f,
5306 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
5307 int flags)
5308 {
5309 int i;
5310
5311 # define printfpr(fp) do { \
5312 fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
5313 (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
5314 } while(0)
5315
5316 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d\n",
5317 env->fcr0, env->fcr31,
5318 (env->CP0_Status & (1 << CP0St_FR)) != 0);
5319 fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
5320 fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
5321 fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
5322 for(i = 0; i < 32; i += 2) {
5323 fpu_fprintf(f, "%s: ", fregnames[i]);
5324 printfpr(FPR(env, i));
5325 }
5326
5327 #undef printfpr
5328 }
5329
5330 void dump_fpu (CPUState *env)
5331 {
5332 if (loglevel) {
5333 fprintf(logfile, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
5334 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5335 fpu_dump_state(env, logfile, fprintf, 0);
5336 }
5337 }
5338
5339 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
5340 /* Debug help: The architecture requires 32bit code to maintain proper
5341 sign-extened values on 64bit machines. */
5342
5343 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
5344
5345 void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
5346 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5347 int flags)
5348 {
5349 int i;
5350
5351 if (!SIGN_EXT_P(env->PC))
5352 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC);
5353 if (!SIGN_EXT_P(env->HI))
5354 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI);
5355 if (!SIGN_EXT_P(env->LO))
5356 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO);
5357 if (!SIGN_EXT_P(env->btarget))
5358 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
5359
5360 for (i = 0; i < 32; i++) {
5361 if (!SIGN_EXT_P(env->gpr[i]))
5362 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i]);
5363 }
5364
5365 if (!SIGN_EXT_P(env->CP0_EPC))
5366 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5367 if (!SIGN_EXT_P(env->CP0_LLAddr))
5368 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
5369 }
5370 #endif
5371
5372 void cpu_dump_state (CPUState *env, FILE *f,
5373 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5374 int flags)
5375 {
5376 uint32_t c0_status;
5377 int i;
5378
5379 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",
5380 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5381 for (i = 0; i < 32; i++) {
5382 if ((i & 3) == 0)
5383 cpu_fprintf(f, "GPR%02d:", i);
5384 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i]);
5385 if ((i & 3) == 3)
5386 cpu_fprintf(f, "\n");
5387 }
5388
5389 c0_status = env->CP0_Status;
5390
5391 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5392 c0_status, env->CP0_Cause, env->CP0_EPC);
5393 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
5394 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
5395 if (c0_status & (1 << CP0St_CU1))
5396 fpu_dump_state(env, f, cpu_fprintf, flags);
5397 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
5398 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
5399 #endif
5400 }
5401
5402 CPUMIPSState *cpu_mips_init (void)
5403 {
5404 CPUMIPSState *env;
5405
5406 env = qemu_mallocz(sizeof(CPUMIPSState));
5407 if (!env)
5408 return NULL;
5409 cpu_exec_init(env);
5410 cpu_reset(env);
5411 return env;
5412 }
5413
5414 void cpu_reset (CPUMIPSState *env)
5415 {
5416 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
5417
5418 tlb_flush(env, 1);
5419
5420 /* Minimal init */
5421 #if !defined(CONFIG_USER_ONLY)
5422 if (env->hflags & MIPS_HFLAG_BMASK) {
5423 /* If the exception was raised from a delay slot,
5424 * come back to the jump. */
5425 env->CP0_ErrorEPC = env->PC - 4;
5426 env->hflags &= ~MIPS_HFLAG_BMASK;
5427 } else {
5428 env->CP0_ErrorEPC = env->PC;
5429 }
5430 env->hflags = 0;
5431 env->PC = (int32_t)0xBFC00000;
5432 env->CP0_Wired = 0;
5433 /* SMP not implemented */
5434 env->CP0_EBase = 0x80000000;
5435 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
5436 /* vectored interrupts not implemented, timer on int 7,
5437 no performance counters. */
5438 env->CP0_IntCtl = 0xe0000000;
5439 env->CP0_WatchLo = 0;
5440 env->CP0_WatchHi = 0;
5441 /* Count register increments in debug mode, EJTAG version 1 */
5442 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
5443 #endif
5444 env->exception_index = EXCP_NONE;
5445 #if defined(CONFIG_USER_ONLY)
5446 env->hflags |= MIPS_HFLAG_UM;
5447 env->user_mode_only = 1;
5448 #endif
5449 }
5450
5451 #include "translate_init.c"