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