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