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