]> git.proxmox.com Git - qemu.git/blame - target-mips/translate.c
Change NIC registration to be consistent with other machines definitions.
[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
60aa19ab 614#ifdef TARGET_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) {
60aa19ab 663#ifdef TARGET_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;
60aa19ab 875#ifdef TARGET_MIPS64
7a387fff
TS
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;
60aa19ab 926#ifdef TARGET_MIPS64
7a387fff
TS
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;
60aa19ab 1006#ifdef TARGET_MIPS64
7a387fff
TS
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;
60aa19ab 1079#ifdef TARGET_MIPS64
7a387fff
TS
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;
60aa19ab 1171#ifdef TARGET_MIPS64
7a387fff
TS
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;
60aa19ab 1232#ifdef TARGET_MIPS64
7a387fff
TS
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,
38121543
TS
1378 "undefined branch in delay slot at PC " TARGET_FMT_lx "\n",
1379 ctx->pc);
3ad4bb2d
TS
1380 }
1381 MIPS_INVAL("branch/jump in bdelay slot");
1382 generate_exception(ctx, EXCP_RI);
1383 return;
1384 }
6af0bf9c 1385
6af0bf9c
FB
1386 /* Load needed operands */
1387 switch (opc) {
1388 case OPC_BEQ:
1389 case OPC_BEQL:
1390 case OPC_BNE:
1391 case OPC_BNEL:
1392 /* Compare two registers */
1393 if (rs != rt) {
1394 GEN_LOAD_REG_TN(T0, rs);
1395 GEN_LOAD_REG_TN(T1, rt);
1396 bcond = 1;
1397 }
1398 btarget = ctx->pc + 4 + offset;
1399 break;
1400 case OPC_BGEZ:
1401 case OPC_BGEZAL:
1402 case OPC_BGEZALL:
1403 case OPC_BGEZL:
1404 case OPC_BGTZ:
1405 case OPC_BGTZL:
1406 case OPC_BLEZ:
1407 case OPC_BLEZL:
1408 case OPC_BLTZ:
1409 case OPC_BLTZAL:
1410 case OPC_BLTZALL:
1411 case OPC_BLTZL:
1412 /* Compare to zero */
1413 if (rs != 0) {
1414 gen_op_load_gpr_T0(rs);
1415 bcond = 1;
1416 }
1417 btarget = ctx->pc + 4 + offset;
1418 break;
1419 case OPC_J:
1420 case OPC_JAL:
1421 /* Jump to immediate */
5dc4b744 1422 btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | offset;
6af0bf9c
FB
1423 break;
1424 case OPC_JR:
1425 case OPC_JALR:
1426 /* Jump to register */
7a387fff
TS
1427 if (offset != 0 && offset != 16) {
1428 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1429 others are reserved. */
6af0bf9c
FB
1430 generate_exception(ctx, EXCP_RI);
1431 return;
1432 }
1433 GEN_LOAD_REG_TN(T2, rs);
1434 break;
1435 default:
1436 MIPS_INVAL("branch/jump");
1437 generate_exception(ctx, EXCP_RI);
1438 return;
1439 }
1440 if (bcond == 0) {
1441 /* No condition to be computed */
1442 switch (opc) {
1443 case OPC_BEQ: /* rx == rx */
1444 case OPC_BEQL: /* rx == rx likely */
1445 case OPC_BGEZ: /* 0 >= 0 */
1446 case OPC_BGEZL: /* 0 >= 0 likely */
1447 case OPC_BLEZ: /* 0 <= 0 */
1448 case OPC_BLEZL: /* 0 <= 0 likely */
1449 /* Always take */
4ad40f36 1450 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
1451 MIPS_DEBUG("balways");
1452 break;
1453 case OPC_BGEZAL: /* 0 >= 0 */
1454 case OPC_BGEZALL: /* 0 >= 0 likely */
1455 /* Always take and link */
1456 blink = 31;
4ad40f36 1457 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
1458 MIPS_DEBUG("balways and link");
1459 break;
1460 case OPC_BNE: /* rx != rx */
1461 case OPC_BGTZ: /* 0 > 0 */
1462 case OPC_BLTZ: /* 0 < 0 */
6af0bf9c
FB
1463 /* Treated as NOP */
1464 MIPS_DEBUG("bnever (NOP)");
1465 return;
eeef26cd
FB
1466 case OPC_BLTZAL: /* 0 < 0 */
1467 gen_op_set_T0(ctx->pc + 8);
1468 gen_op_store_T0_gpr(31);
1469 return;
1470 case OPC_BLTZALL: /* 0 < 0 likely */
1471 gen_op_set_T0(ctx->pc + 8);
1472 gen_op_store_T0_gpr(31);
1473 gen_goto_tb(ctx, 0, ctx->pc + 4);
1474 return;
6af0bf9c
FB
1475 case OPC_BNEL: /* rx != rx likely */
1476 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
1477 case OPC_BLTZL: /* 0 < 0 likely */
1478 /* Skip the instruction in the delay slot */
1479 MIPS_DEBUG("bnever and skip");
6e256c93 1480 gen_goto_tb(ctx, 0, ctx->pc + 4);
6af0bf9c
FB
1481 return;
1482 case OPC_J:
4ad40f36 1483 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
1484 MIPS_DEBUG("j %08x", btarget);
1485 break;
1486 case OPC_JAL:
1487 blink = 31;
4ad40f36 1488 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
1489 MIPS_DEBUG("jal %08x", btarget);
1490 break;
1491 case OPC_JR:
4ad40f36 1492 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
1493 MIPS_DEBUG("jr %s", regnames[rs]);
1494 break;
1495 case OPC_JALR:
1496 blink = rt;
4ad40f36 1497 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
1498 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1499 break;
1500 default:
1501 MIPS_INVAL("branch/jump");
1502 generate_exception(ctx, EXCP_RI);
1503 return;
1504 }
1505 } else {
1506 switch (opc) {
1507 case OPC_BEQ:
1508 gen_op_eq();
1509 MIPS_DEBUG("beq %s, %s, %08x",
1510 regnames[rs], regnames[rt], btarget);
1511 goto not_likely;
1512 case OPC_BEQL:
1513 gen_op_eq();
1514 MIPS_DEBUG("beql %s, %s, %08x",
1515 regnames[rs], regnames[rt], btarget);
1516 goto likely;
1517 case OPC_BNE:
1518 gen_op_ne();
1519 MIPS_DEBUG("bne %s, %s, %08x",
1520 regnames[rs], regnames[rt], btarget);
1521 goto not_likely;
1522 case OPC_BNEL:
1523 gen_op_ne();
1524 MIPS_DEBUG("bnel %s, %s, %08x",
1525 regnames[rs], regnames[rt], btarget);
1526 goto likely;
1527 case OPC_BGEZ:
1528 gen_op_gez();
1529 MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
1530 goto not_likely;
1531 case OPC_BGEZL:
1532 gen_op_gez();
1533 MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
1534 goto likely;
1535 case OPC_BGEZAL:
1536 gen_op_gez();
1537 MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
1538 blink = 31;
1539 goto not_likely;
1540 case OPC_BGEZALL:
1541 gen_op_gez();
1542 blink = 31;
1543 MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
1544 goto likely;
1545 case OPC_BGTZ:
1546 gen_op_gtz();
1547 MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
1548 goto not_likely;
1549 case OPC_BGTZL:
1550 gen_op_gtz();
1551 MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
1552 goto likely;
1553 case OPC_BLEZ:
1554 gen_op_lez();
1555 MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
1556 goto not_likely;
1557 case OPC_BLEZL:
1558 gen_op_lez();
1559 MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
1560 goto likely;
1561 case OPC_BLTZ:
1562 gen_op_ltz();
1563 MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
1564 goto not_likely;
1565 case OPC_BLTZL:
1566 gen_op_ltz();
1567 MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
1568 goto likely;
1569 case OPC_BLTZAL:
1570 gen_op_ltz();
1571 blink = 31;
1572 MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1573 not_likely:
4ad40f36 1574 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
1575 break;
1576 case OPC_BLTZALL:
1577 gen_op_ltz();
1578 blink = 31;
1579 MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1580 likely:
4ad40f36 1581 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c
FB
1582 break;
1583 }
1584 gen_op_set_bcond();
1585 }
1586 MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1587 blink, ctx->hflags, btarget);
1588 ctx->btarget = btarget;
1589 if (blink > 0) {
1590 gen_op_set_T0(ctx->pc + 8);
1591 gen_op_store_T0_gpr(blink);
1592 }
1593 return;
1594}
1595
7a387fff
TS
1596/* special3 bitfield operations */
1597static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1598 int rs, int lsb, int msb)
1599{
1600 GEN_LOAD_REG_TN(T1, rs);
1601 switch (opc) {
1602 case OPC_EXT:
1603 if (lsb + msb > 31)
1604 goto fail;
1605 gen_op_ext(lsb, msb + 1);
1606 break;
1607 case OPC_DEXTM:
1608 if (lsb + msb > 63)
1609 goto fail;
1610 gen_op_ext(lsb, msb + 1 + 32);
1611 break;
1612 case OPC_DEXTU:
1613 if (lsb + msb > 63)
1614 goto fail;
1615 gen_op_ext(lsb + 32, msb + 1);
1616 break;
1617 case OPC_DEXT:
1618 gen_op_ext(lsb, msb + 1);
1619 break;
1620 case OPC_INS:
1621 if (lsb > msb)
1622 goto fail;
1623 GEN_LOAD_REG_TN(T2, rt);
1624 gen_op_ins(lsb, msb - lsb + 1);
1625 break;
1626 case OPC_DINSM:
1627 if (lsb > msb)
1628 goto fail;
1629 GEN_LOAD_REG_TN(T2, rt);
1630 gen_op_ins(lsb, msb - lsb + 1 + 32);
1631 break;
1632 case OPC_DINSU:
1633 if (lsb > msb)
1634 goto fail;
1635 GEN_LOAD_REG_TN(T2, rt);
1636 gen_op_ins(lsb + 32, msb - lsb + 1);
1637 break;
1638 case OPC_DINS:
1639 if (lsb > msb)
1640 goto fail;
1641 GEN_LOAD_REG_TN(T2, rt);
1642 gen_op_ins(lsb, msb - lsb + 1);
1643 break;
1644 default:
1645fail:
1646 MIPS_INVAL("bitops");
1647 generate_exception(ctx, EXCP_RI);
1648 return;
1649 }
1650 GEN_STORE_TN_REG(rt, T0);
1651}
1652
6af0bf9c 1653/* CP0 (MMU and control) */
873eb012
TS
1654static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
1655{
7a387fff 1656 const char *rn = "invalid";
873eb012 1657
873eb012
TS
1658 switch (reg) {
1659 case 0:
7a387fff
TS
1660 switch (sel) {
1661 case 0:
1662 gen_op_mfc0_index();
1663 rn = "Index";
1664 break;
1665 case 1:
1666// gen_op_mfc0_mvpcontrol(); /* MT ASE */
1667 rn = "MVPControl";
1668// break;
1669 case 2:
1670// gen_op_mfc0_mvpconf0(); /* MT ASE */
1671 rn = "MVPConf0";
1672// break;
1673 case 3:
1674// gen_op_mfc0_mvpconf1(); /* MT ASE */
1675 rn = "MVPConf1";
1676// break;
1677 default:
1678 goto die;
1679 }
873eb012
TS
1680 break;
1681 case 1:
7a387fff
TS
1682 switch (sel) {
1683 case 0:
1684 gen_op_mfc0_random();
1685 rn = "Random";
1686 break;
1687 case 1:
1688// gen_op_mfc0_vpecontrol(); /* MT ASE */
1689 rn = "VPEControl";
1690// break;
1691 case 2:
1692// gen_op_mfc0_vpeconf0(); /* MT ASE */
1693 rn = "VPEConf0";
1694// break;
1695 case 3:
1696// gen_op_mfc0_vpeconf1(); /* MT ASE */
1697 rn = "VPEConf1";
1698// break;
1699 case 4:
1700// gen_op_mfc0_YQMask(); /* MT ASE */
1701 rn = "YQMask";
1702// break;
1703 case 5:
1704// gen_op_mfc0_vpeschedule(); /* MT ASE */
1705 rn = "VPESchedule";
1706// break;
1707 case 6:
1708// gen_op_mfc0_vpeschefback(); /* MT ASE */
1709 rn = "VPEScheFBack";
1710// break;
1711 case 7:
1712// gen_op_mfc0_vpeopt(); /* MT ASE */
1713 rn = "VPEOpt";
1714// break;
1715 default:
1716 goto die;
1717 }
873eb012
TS
1718 break;
1719 case 2:
7a387fff
TS
1720 switch (sel) {
1721 case 0:
1722 gen_op_mfc0_entrylo0();
1723 rn = "EntryLo0";
1724 break;
1725 case 1:
1726// gen_op_mfc0_tcstatus(); /* MT ASE */
1727 rn = "TCStatus";
1728// break;
1729 case 2:
1730// gen_op_mfc0_tcbind(); /* MT ASE */
1731 rn = "TCBind";
1732// break;
1733 case 3:
1734// gen_op_mfc0_tcrestart(); /* MT ASE */
1735 rn = "TCRestart";
1736// break;
1737 case 4:
1738// gen_op_mfc0_tchalt(); /* MT ASE */
1739 rn = "TCHalt";
1740// break;
1741 case 5:
1742// gen_op_mfc0_tccontext(); /* MT ASE */
1743 rn = "TCContext";
1744// break;
1745 case 6:
1746// gen_op_mfc0_tcschedule(); /* MT ASE */
1747 rn = "TCSchedule";
1748// break;
1749 case 7:
1750// gen_op_mfc0_tcschefback(); /* MT ASE */
1751 rn = "TCScheFBack";
1752// break;
1753 default:
1754 goto die;
1755 }
873eb012
TS
1756 break;
1757 case 3:
7a387fff
TS
1758 switch (sel) {
1759 case 0:
1760 gen_op_mfc0_entrylo1();
1761 rn = "EntryLo1";
1762 break;
1763 default:
1764 goto die;
1765 }
873eb012
TS
1766 break;
1767 case 4:
7a387fff
TS
1768 switch (sel) {
1769 case 0:
1770 gen_op_mfc0_context();
1771 rn = "Context";
1772 break;
1773 case 1:
1774// gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
1775 rn = "ContextConfig";
1776// break;
1777 default:
1778 goto die;
1779 }
873eb012
TS
1780 break;
1781 case 5:
7a387fff
TS
1782 switch (sel) {
1783 case 0:
1784 gen_op_mfc0_pagemask();
1785 rn = "PageMask";
1786 break;
1787 case 1:
1788 gen_op_mfc0_pagegrain();
1789 rn = "PageGrain";
1790 break;
1791 default:
1792 goto die;
1793 }
873eb012
TS
1794 break;
1795 case 6:
7a387fff
TS
1796 switch (sel) {
1797 case 0:
1798 gen_op_mfc0_wired();
1799 rn = "Wired";
1800 break;
1801 case 1:
1802// gen_op_mfc0_srsconf0(); /* shadow registers */
1803 rn = "SRSConf0";
1804// break;
1805 case 2:
1806// gen_op_mfc0_srsconf1(); /* shadow registers */
1807 rn = "SRSConf1";
1808// break;
1809 case 3:
1810// gen_op_mfc0_srsconf2(); /* shadow registers */
1811 rn = "SRSConf2";
1812// break;
1813 case 4:
1814// gen_op_mfc0_srsconf3(); /* shadow registers */
1815 rn = "SRSConf3";
1816// break;
1817 case 5:
1818// gen_op_mfc0_srsconf4(); /* shadow registers */
1819 rn = "SRSConf4";
1820// break;
1821 default:
1822 goto die;
1823 }
873eb012 1824 break;
8c0fdd85 1825 case 7:
7a387fff
TS
1826 switch (sel) {
1827 case 0:
1828 gen_op_mfc0_hwrena();
1829 rn = "HWREna";
1830 break;
1831 default:
1832 goto die;
1833 }
8c0fdd85 1834 break;
873eb012 1835 case 8:
7a387fff
TS
1836 switch (sel) {
1837 case 0:
1838 gen_op_mfc0_badvaddr();
1839 rn = "BadVaddr";
1840 break;
1841 default:
1842 goto die;
1843 }
873eb012
TS
1844 break;
1845 case 9:
7a387fff
TS
1846 switch (sel) {
1847 case 0:
1848 gen_op_mfc0_count();
1849 rn = "Count";
1850 break;
1851 /* 6,7 are implementation dependent */
1852 default:
1853 goto die;
1854 }
873eb012
TS
1855 break;
1856 case 10:
7a387fff
TS
1857 switch (sel) {
1858 case 0:
1859 gen_op_mfc0_entryhi();
1860 rn = "EntryHi";
1861 break;
1862 default:
1863 goto die;
1864 }
873eb012
TS
1865 break;
1866 case 11:
7a387fff
TS
1867 switch (sel) {
1868 case 0:
1869 gen_op_mfc0_compare();
1870 rn = "Compare";
1871 break;
1872 /* 6,7 are implementation dependent */
1873 default:
1874 goto die;
1875 }
873eb012
TS
1876 break;
1877 case 12:
7a387fff
TS
1878 switch (sel) {
1879 case 0:
1880 gen_op_mfc0_status();
1881 rn = "Status";
1882 break;
1883 case 1:
1884 gen_op_mfc0_intctl();
1885 rn = "IntCtl";
1886 break;
1887 case 2:
1888 gen_op_mfc0_srsctl();
1889 rn = "SRSCtl";
1890 break;
1891 case 3:
1892// gen_op_mfc0_srsmap(); /* shadow registers */
1893 rn = "SRSMap";
1894// break;
1895 default:
1896 goto die;
1897 }
873eb012
TS
1898 break;
1899 case 13:
7a387fff
TS
1900 switch (sel) {
1901 case 0:
1902 gen_op_mfc0_cause();
1903 rn = "Cause";
1904 break;
1905 default:
1906 goto die;
1907 }
873eb012
TS
1908 break;
1909 case 14:
7a387fff
TS
1910 switch (sel) {
1911 case 0:
1912 gen_op_mfc0_epc();
1913 rn = "EPC";
1914 break;
1915 default:
1916 goto die;
1917 }
873eb012
TS
1918 break;
1919 case 15:
7a387fff
TS
1920 switch (sel) {
1921 case 0:
1922 gen_op_mfc0_prid();
1923 rn = "PRid";
1924 break;
1925 case 1:
1926 gen_op_mfc0_ebase();
1927 rn = "EBase";
1928 break;
1929 default:
1930 goto die;
1931 }
873eb012
TS
1932 break;
1933 case 16:
1934 switch (sel) {
1935 case 0:
e397ee33 1936 gen_op_mfc0_config0();
873eb012
TS
1937 rn = "Config";
1938 break;
1939 case 1:
e397ee33 1940 gen_op_mfc0_config1();
873eb012
TS
1941 rn = "Config1";
1942 break;
7a387fff 1943 case 2:
e397ee33 1944 gen_op_mfc0_config2();
7a387fff
TS
1945 rn = "Config2";
1946 break;
1947 case 3:
e397ee33 1948 gen_op_mfc0_config3();
7a387fff
TS
1949 rn = "Config3";
1950 break;
e397ee33
TS
1951 /* 4,5 are reserved */
1952 /* 6,7 are implementation dependent */
1953 case 6:
1954 gen_op_mfc0_config6();
1955 rn = "Config6";
1956 break;
1957 case 7:
1958 gen_op_mfc0_config7();
1959 rn = "Config7";
1960 break;
873eb012 1961 default:
873eb012
TS
1962 goto die;
1963 }
1964 break;
1965 case 17:
7a387fff
TS
1966 switch (sel) {
1967 case 0:
1968 gen_op_mfc0_lladdr();
1969 rn = "LLAddr";
1970 break;
1971 default:
1972 goto die;
1973 }
873eb012
TS
1974 break;
1975 case 18:
7a387fff
TS
1976 switch (sel) {
1977 case 0:
1978 gen_op_mfc0_watchlo0();
1979 rn = "WatchLo";
1980 break;
1981 case 1:
1982// gen_op_mfc0_watchlo1();
1983 rn = "WatchLo1";
1984// break;
1985 case 2:
1986// gen_op_mfc0_watchlo2();
1987 rn = "WatchLo2";
1988// break;
1989 case 3:
1990// gen_op_mfc0_watchlo3();
1991 rn = "WatchLo3";
1992// break;
1993 case 4:
1994// gen_op_mfc0_watchlo4();
1995 rn = "WatchLo4";
1996// break;
1997 case 5:
1998// gen_op_mfc0_watchlo5();
1999 rn = "WatchLo5";
2000// break;
2001 case 6:
2002// gen_op_mfc0_watchlo6();
2003 rn = "WatchLo6";
2004// break;
2005 case 7:
2006// gen_op_mfc0_watchlo7();
2007 rn = "WatchLo7";
2008// break;
2009 default:
2010 goto die;
2011 }
873eb012
TS
2012 break;
2013 case 19:
7a387fff
TS
2014 switch (sel) {
2015 case 0:
2016 gen_op_mfc0_watchhi0();
2017 rn = "WatchHi";
2018 break;
2019 case 1:
2020// gen_op_mfc0_watchhi1();
2021 rn = "WatchHi1";
2022// break;
2023 case 2:
2024// gen_op_mfc0_watchhi2();
2025 rn = "WatchHi2";
2026// break;
2027 case 3:
2028// gen_op_mfc0_watchhi3();
2029 rn = "WatchHi3";
2030// break;
2031 case 4:
2032// gen_op_mfc0_watchhi4();
2033 rn = "WatchHi4";
2034// break;
2035 case 5:
2036// gen_op_mfc0_watchhi5();
2037 rn = "WatchHi5";
2038// break;
2039 case 6:
2040// gen_op_mfc0_watchhi6();
2041 rn = "WatchHi6";
2042// break;
2043 case 7:
2044// gen_op_mfc0_watchhi7();
2045 rn = "WatchHi7";
2046// break;
2047 default:
2048 goto die;
2049 }
873eb012 2050 break;
8c0fdd85 2051 case 20:
7a387fff
TS
2052 switch (sel) {
2053 case 0:
2054 /* 64 bit MMU only */
2055 gen_op_mfc0_xcontext();
2056 rn = "XContext";
2057 break;
2058 default:
2059 goto die;
2060 }
8c0fdd85
TS
2061 break;
2062 case 21:
7a387fff
TS
2063 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2064 switch (sel) {
2065 case 0:
2066 gen_op_mfc0_framemask();
2067 rn = "Framemask";
2068 break;
2069 default:
2070 goto die;
2071 }
8c0fdd85
TS
2072 break;
2073 case 22:
7a387fff
TS
2074 /* ignored */
2075 rn = "'Diagnostic"; /* implementation dependent */
2076 break;
873eb012 2077 case 23:
7a387fff
TS
2078 switch (sel) {
2079 case 0:
2080 gen_op_mfc0_debug(); /* EJTAG support */
2081 rn = "Debug";
2082 break;
2083 case 1:
2084// gen_op_mfc0_tracecontrol(); /* PDtrace support */
2085 rn = "TraceControl";
2086// break;
2087 case 2:
2088// gen_op_mfc0_tracecontrol2(); /* PDtrace support */
2089 rn = "TraceControl2";
2090// break;
2091 case 3:
2092// gen_op_mfc0_usertracedata(); /* PDtrace support */
2093 rn = "UserTraceData";
2094// break;
2095 case 4:
2096// gen_op_mfc0_debug(); /* PDtrace support */
2097 rn = "TraceBPC";
2098// break;
2099 default:
2100 goto die;
2101 }
873eb012
TS
2102 break;
2103 case 24:
7a387fff
TS
2104 switch (sel) {
2105 case 0:
2106 gen_op_mfc0_depc(); /* EJTAG support */
2107 rn = "DEPC";
2108 break;
2109 default:
2110 goto die;
2111 }
873eb012 2112 break;
8c0fdd85 2113 case 25:
7a387fff
TS
2114 switch (sel) {
2115 case 0:
2116 gen_op_mfc0_performance0();
2117 rn = "Performance0";
2118 break;
2119 case 1:
2120// gen_op_mfc0_performance1();
2121 rn = "Performance1";
2122// break;
2123 case 2:
2124// gen_op_mfc0_performance2();
2125 rn = "Performance2";
2126// break;
2127 case 3:
2128// gen_op_mfc0_performance3();
2129 rn = "Performance3";
2130// break;
2131 case 4:
2132// gen_op_mfc0_performance4();
2133 rn = "Performance4";
2134// break;
2135 case 5:
2136// gen_op_mfc0_performance5();
2137 rn = "Performance5";
2138// break;
2139 case 6:
2140// gen_op_mfc0_performance6();
2141 rn = "Performance6";
2142// break;
2143 case 7:
2144// gen_op_mfc0_performance7();
2145 rn = "Performance7";
2146// break;
2147 default:
2148 goto die;
2149 }
8c0fdd85
TS
2150 break;
2151 case 26:
7a387fff
TS
2152 rn = "ECC";
2153 break;
8c0fdd85 2154 case 27:
7a387fff
TS
2155 switch (sel) {
2156 /* ignored */
2157 case 0 ... 3:
2158 rn = "CacheErr";
2159 break;
2160 default:
2161 goto die;
2162 }
8c0fdd85 2163 break;
873eb012
TS
2164 case 28:
2165 switch (sel) {
2166 case 0:
7a387fff
TS
2167 case 2:
2168 case 4:
2169 case 6:
873eb012
TS
2170 gen_op_mfc0_taglo();
2171 rn = "TagLo";
2172 break;
2173 case 1:
7a387fff
TS
2174 case 3:
2175 case 5:
2176 case 7:
873eb012
TS
2177 gen_op_mfc0_datalo();
2178 rn = "DataLo";
2179 break;
2180 default:
873eb012
TS
2181 goto die;
2182 }
2183 break;
8c0fdd85 2184 case 29:
7a387fff
TS
2185 switch (sel) {
2186 case 0:
2187 case 2:
2188 case 4:
2189 case 6:
2190 gen_op_mfc0_taghi();
2191 rn = "TagHi";
2192 break;
2193 case 1:
2194 case 3:
2195 case 5:
2196 case 7:
2197 gen_op_mfc0_datahi();
2198 rn = "DataHi";
2199 break;
2200 default:
2201 goto die;
2202 }
8c0fdd85 2203 break;
873eb012 2204 case 30:
7a387fff
TS
2205 switch (sel) {
2206 case 0:
2207 gen_op_mfc0_errorepc();
2208 rn = "ErrorEPC";
2209 break;
2210 default:
2211 goto die;
2212 }
873eb012
TS
2213 break;
2214 case 31:
7a387fff
TS
2215 switch (sel) {
2216 case 0:
2217 gen_op_mfc0_desave(); /* EJTAG support */
2218 rn = "DESAVE";
2219 break;
2220 default:
2221 goto die;
2222 }
873eb012
TS
2223 break;
2224 default:
873eb012
TS
2225 goto die;
2226 }
2227#if defined MIPS_DEBUG_DISAS
2228 if (loglevel & CPU_LOG_TB_IN_ASM) {
7a387fff
TS
2229 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2230 rn, reg, sel);
873eb012
TS
2231 }
2232#endif
2233 return;
2234
2235die:
2236#if defined MIPS_DEBUG_DISAS
2237 if (loglevel & CPU_LOG_TB_IN_ASM) {
7a387fff
TS
2238 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2239 rn, reg, sel);
873eb012
TS
2240 }
2241#endif
2242 generate_exception(ctx, EXCP_RI);
2243}
2244
8c0fdd85
TS
2245static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2246{
7a387fff
TS
2247 const char *rn = "invalid";
2248
8c0fdd85
TS
2249 switch (reg) {
2250 case 0:
7a387fff
TS
2251 switch (sel) {
2252 case 0:
2253 gen_op_mtc0_index();
2254 rn = "Index";
2255 break;
2256 case 1:
2257// gen_op_mtc0_mvpcontrol(); /* MT ASE */
2258 rn = "MVPControl";
2259// break;
2260 case 2:
2261// gen_op_mtc0_mvpconf0(); /* MT ASE */
2262 rn = "MVPConf0";
2263// break;
2264 case 3:
2265// gen_op_mtc0_mvpconf1(); /* MT ASE */
2266 rn = "MVPConf1";
2267// break;
2268 default:
2269 goto die;
2270 }
8c0fdd85
TS
2271 break;
2272 case 1:
7a387fff
TS
2273 switch (sel) {
2274 case 0:
2275 /* ignored */
2276 rn = "Random";
2277 break;
2278 case 1:
2279// gen_op_mtc0_vpecontrol(); /* MT ASE */
2280 rn = "VPEControl";
2281// break;
2282 case 2:
2283// gen_op_mtc0_vpeconf0(); /* MT ASE */
2284 rn = "VPEConf0";
2285// break;
2286 case 3:
2287// gen_op_mtc0_vpeconf1(); /* MT ASE */
2288 rn = "VPEConf1";
2289// break;
2290 case 4:
2291// gen_op_mtc0_YQMask(); /* MT ASE */
2292 rn = "YQMask";
2293// break;
2294 case 5:
2295// gen_op_mtc0_vpeschedule(); /* MT ASE */
2296 rn = "VPESchedule";
2297// break;
2298 case 6:
2299// gen_op_mtc0_vpeschefback(); /* MT ASE */
2300 rn = "VPEScheFBack";
2301// break;
2302 case 7:
2303// gen_op_mtc0_vpeopt(); /* MT ASE */
2304 rn = "VPEOpt";
2305// break;
2306 default:
2307 goto die;
2308 }
8c0fdd85
TS
2309 break;
2310 case 2:
7a387fff
TS
2311 switch (sel) {
2312 case 0:
2313 gen_op_mtc0_entrylo0();
2314 rn = "EntryLo0";
2315 break;
2316 case 1:
2317// gen_op_mtc0_tcstatus(); /* MT ASE */
2318 rn = "TCStatus";
2319// break;
2320 case 2:
2321// gen_op_mtc0_tcbind(); /* MT ASE */
2322 rn = "TCBind";
2323// break;
2324 case 3:
2325// gen_op_mtc0_tcrestart(); /* MT ASE */
2326 rn = "TCRestart";
2327// break;
2328 case 4:
2329// gen_op_mtc0_tchalt(); /* MT ASE */
2330 rn = "TCHalt";
2331// break;
2332 case 5:
2333// gen_op_mtc0_tccontext(); /* MT ASE */
2334 rn = "TCContext";
2335// break;
2336 case 6:
2337// gen_op_mtc0_tcschedule(); /* MT ASE */
2338 rn = "TCSchedule";
2339// break;
2340 case 7:
2341// gen_op_mtc0_tcschefback(); /* MT ASE */
2342 rn = "TCScheFBack";
2343// break;
2344 default:
2345 goto die;
2346 }
8c0fdd85
TS
2347 break;
2348 case 3:
7a387fff
TS
2349 switch (sel) {
2350 case 0:
2351 gen_op_mtc0_entrylo1();
2352 rn = "EntryLo1";
2353 break;
2354 default:
2355 goto die;
2356 }
8c0fdd85
TS
2357 break;
2358 case 4:
7a387fff
TS
2359 switch (sel) {
2360 case 0:
2361 gen_op_mtc0_context();
2362 rn = "Context";
2363 break;
2364 case 1:
2365// gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
2366 rn = "ContextConfig";
2367// break;
2368 default:
2369 goto die;
2370 }
8c0fdd85
TS
2371 break;
2372 case 5:
7a387fff
TS
2373 switch (sel) {
2374 case 0:
2375 gen_op_mtc0_pagemask();
2376 rn = "PageMask";
2377 break;
2378 case 1:
2379 gen_op_mtc0_pagegrain();
2380 rn = "PageGrain";
2381 break;
2382 default:
2383 goto die;
2384 }
8c0fdd85
TS
2385 break;
2386 case 6:
7a387fff
TS
2387 switch (sel) {
2388 case 0:
2389 gen_op_mtc0_wired();
2390 rn = "Wired";
2391 break;
2392 case 1:
2393// gen_op_mtc0_srsconf0(); /* shadow registers */
2394 rn = "SRSConf0";
2395// break;
2396 case 2:
2397// gen_op_mtc0_srsconf1(); /* shadow registers */
2398 rn = "SRSConf1";
2399// break;
2400 case 3:
2401// gen_op_mtc0_srsconf2(); /* shadow registers */
2402 rn = "SRSConf2";
2403// break;
2404 case 4:
2405// gen_op_mtc0_srsconf3(); /* shadow registers */
2406 rn = "SRSConf3";
2407// break;
2408 case 5:
2409// gen_op_mtc0_srsconf4(); /* shadow registers */
2410 rn = "SRSConf4";
2411// break;
2412 default:
2413 goto die;
2414 }
8c0fdd85
TS
2415 break;
2416 case 7:
7a387fff
TS
2417 switch (sel) {
2418 case 0:
2419 gen_op_mtc0_hwrena();
2420 rn = "HWREna";
2421 break;
2422 default:
2423 goto die;
2424 }
8c0fdd85
TS
2425 break;
2426 case 8:
7a387fff 2427 /* ignored */
8c0fdd85
TS
2428 rn = "BadVaddr";
2429 break;
2430 case 9:
7a387fff
TS
2431 switch (sel) {
2432 case 0:
2433 gen_op_mtc0_count();
2434 rn = "Count";
2435 break;
2436 /* 6,7 are implementation dependent */
2437 default:
2438 goto die;
2439 }
2440 /* Stop translation as we may have switched the execution mode */
2441 ctx->bstate = BS_STOP;
8c0fdd85
TS
2442 break;
2443 case 10:
7a387fff
TS
2444 switch (sel) {
2445 case 0:
2446 gen_op_mtc0_entryhi();
2447 rn = "EntryHi";
2448 break;
2449 default:
2450 goto die;
2451 }
8c0fdd85
TS
2452 break;
2453 case 11:
7a387fff
TS
2454 switch (sel) {
2455 case 0:
2456 gen_op_mtc0_compare();
2457 rn = "Compare";
2458 break;
2459 /* 6,7 are implementation dependent */
2460 default:
2461 goto die;
2462 }
2463 /* Stop translation as we may have switched the execution mode */
2464 ctx->bstate = BS_STOP;
8c0fdd85
TS
2465 break;
2466 case 12:
7a387fff
TS
2467 switch (sel) {
2468 case 0:
2469 gen_op_mtc0_status();
2470 rn = "Status";
2471 break;
2472 case 1:
2473 gen_op_mtc0_intctl();
2474 rn = "IntCtl";
2475 break;
2476 case 2:
2477 gen_op_mtc0_srsctl();
2478 rn = "SRSCtl";
2479 break;
2480 case 3:
2481// gen_op_mtc0_srsmap(); /* shadow registers */
2482 rn = "SRSMap";
2483// break;
2484 default:
2485 goto die;
2486 }
2487 /* Stop translation as we may have switched the execution mode */
2488 ctx->bstate = BS_STOP;
8c0fdd85
TS
2489 break;
2490 case 13:
7a387fff
TS
2491 switch (sel) {
2492 case 0:
2493 gen_op_mtc0_cause();
2494 rn = "Cause";
2495 break;
2496 default:
2497 goto die;
2498 }
2499 /* Stop translation as we may have switched the execution mode */
2500 ctx->bstate = BS_STOP;
8c0fdd85
TS
2501 break;
2502 case 14:
7a387fff
TS
2503 switch (sel) {
2504 case 0:
2505 gen_op_mtc0_epc();
2506 rn = "EPC";
2507 break;
2508 default:
2509 goto die;
2510 }
8c0fdd85
TS
2511 break;
2512 case 15:
7a387fff
TS
2513 switch (sel) {
2514 case 0:
2515 /* ignored */
2516 rn = "PRid";
2517 break;
2518 case 1:
2519 gen_op_mtc0_ebase();
2520 rn = "EBase";
2521 break;
2522 default:
2523 goto die;
2524 }
8c0fdd85
TS
2525 break;
2526 case 16:
2527 switch (sel) {
2528 case 0:
e397ee33 2529 gen_op_mtc0_config0();
7a387fff
TS
2530 rn = "Config";
2531 break;
2532 case 1:
e397ee33 2533 /* ignored, read only */
7a387fff
TS
2534 rn = "Config1";
2535 break;
2536 case 2:
e397ee33 2537 gen_op_mtc0_config2();
7a387fff 2538 rn = "Config2";
8c0fdd85 2539 break;
7a387fff 2540 case 3:
e397ee33 2541 /* ignored, read only */
7a387fff
TS
2542 rn = "Config3";
2543 break;
e397ee33
TS
2544 /* 4,5 are reserved */
2545 /* 6,7 are implementation dependent */
2546 case 6:
2547 /* ignored */
2548 rn = "Config6";
2549 break;
2550 case 7:
2551 /* ignored */
2552 rn = "Config7";
2553 break;
8c0fdd85
TS
2554 default:
2555 rn = "Invalid config selector";
2556 goto die;
2557 }
e397ee33
TS
2558 /* Stop translation as we may have switched the execution mode */
2559 ctx->bstate = BS_STOP;
8c0fdd85
TS
2560 break;
2561 case 17:
7a387fff
TS
2562 switch (sel) {
2563 case 0:
2564 /* ignored */
2565 rn = "LLAddr";
2566 break;
2567 default:
2568 goto die;
2569 }
8c0fdd85
TS
2570 break;
2571 case 18:
7a387fff
TS
2572 switch (sel) {
2573 case 0:
2574 gen_op_mtc0_watchlo0();
2575 rn = "WatchLo";
2576 break;
2577 case 1:
2578// gen_op_mtc0_watchlo1();
2579 rn = "WatchLo1";
2580// break;
2581 case 2:
2582// gen_op_mtc0_watchlo2();
2583 rn = "WatchLo2";
2584// break;
2585 case 3:
2586// gen_op_mtc0_watchlo3();
2587 rn = "WatchLo3";
2588// break;
2589 case 4:
2590// gen_op_mtc0_watchlo4();
2591 rn = "WatchLo4";
2592// break;
2593 case 5:
2594// gen_op_mtc0_watchlo5();
2595 rn = "WatchLo5";
2596// break;
2597 case 6:
2598// gen_op_mtc0_watchlo6();
2599 rn = "WatchLo6";
2600// break;
2601 case 7:
2602// gen_op_mtc0_watchlo7();
2603 rn = "WatchLo7";
2604// break;
2605 default:
2606 goto die;
2607 }
8c0fdd85
TS
2608 break;
2609 case 19:
7a387fff
TS
2610 switch (sel) {
2611 case 0:
2612 gen_op_mtc0_watchhi0();
2613 rn = "WatchHi";
2614 break;
2615 case 1:
2616// gen_op_mtc0_watchhi1();
2617 rn = "WatchHi1";
2618// break;
2619 case 2:
2620// gen_op_mtc0_watchhi2();
2621 rn = "WatchHi2";
2622// break;
2623 case 3:
2624// gen_op_mtc0_watchhi3();
2625 rn = "WatchHi3";
2626// break;
2627 case 4:
2628// gen_op_mtc0_watchhi4();
2629 rn = "WatchHi4";
2630// break;
2631 case 5:
2632// gen_op_mtc0_watchhi5();
2633 rn = "WatchHi5";
2634// break;
2635 case 6:
2636// gen_op_mtc0_watchhi6();
2637 rn = "WatchHi6";
2638// break;
2639 case 7:
2640// gen_op_mtc0_watchhi7();
2641 rn = "WatchHi7";
2642// break;
2643 default:
2644 goto die;
2645 }
8c0fdd85
TS
2646 break;
2647 case 20:
7a387fff
TS
2648 switch (sel) {
2649 case 0:
2650 /* 64 bit MMU only */
2651 gen_op_mtc0_xcontext();
2652 rn = "XContext";
2653 break;
2654 default:
2655 goto die;
2656 }
8c0fdd85
TS
2657 break;
2658 case 21:
7a387fff
TS
2659 /* Officially reserved, but sel 0 is used for R1x000 framemask */
2660 switch (sel) {
2661 case 0:
2662 gen_op_mtc0_framemask();
2663 rn = "Framemask";
2664 break;
2665 default:
2666 goto die;
2667 }
2668 break;
8c0fdd85 2669 case 22:
7a387fff
TS
2670 /* ignored */
2671 rn = "Diagnostic"; /* implementation dependent */
8c0fdd85
TS
2672 break;
2673 case 23:
7a387fff
TS
2674 switch (sel) {
2675 case 0:
2676 gen_op_mtc0_debug(); /* EJTAG support */
2677 rn = "Debug";
2678 break;
2679 case 1:
2680// gen_op_mtc0_tracecontrol(); /* PDtrace support */
2681 rn = "TraceControl";
2682// break;
2683 case 2:
2684// gen_op_mtc0_tracecontrol2(); /* PDtrace support */
2685 rn = "TraceControl2";
2686// break;
2687 case 3:
2688// gen_op_mtc0_usertracedata(); /* PDtrace support */
2689 rn = "UserTraceData";
2690// break;
2691 case 4:
2692// gen_op_mtc0_debug(); /* PDtrace support */
2693 rn = "TraceBPC";
2694// break;
2695 default:
2696 goto die;
2697 }
2698 /* Stop translation as we may have switched the execution mode */
2699 ctx->bstate = BS_STOP;
8c0fdd85
TS
2700 break;
2701 case 24:
7a387fff
TS
2702 switch (sel) {
2703 case 0:
2704 gen_op_mtc0_depc(); /* EJTAG support */
2705 rn = "DEPC";
2706 break;
2707 default:
2708 goto die;
2709 }
8c0fdd85
TS
2710 break;
2711 case 25:
7a387fff
TS
2712 switch (sel) {
2713 case 0:
2714 gen_op_mtc0_performance0();
2715 rn = "Performance0";
2716 break;
2717 case 1:
2718// gen_op_mtc0_performance1();
2719 rn = "Performance1";
2720// break;
2721 case 2:
2722// gen_op_mtc0_performance2();
2723 rn = "Performance2";
2724// break;
2725 case 3:
2726// gen_op_mtc0_performance3();
2727 rn = "Performance3";
2728// break;
2729 case 4:
2730// gen_op_mtc0_performance4();
2731 rn = "Performance4";
2732// break;
2733 case 5:
2734// gen_op_mtc0_performance5();
2735 rn = "Performance5";
2736// break;
2737 case 6:
2738// gen_op_mtc0_performance6();
2739 rn = "Performance6";
2740// break;
2741 case 7:
2742// gen_op_mtc0_performance7();
2743 rn = "Performance7";
2744// break;
2745 default:
2746 goto die;
2747 }
8c0fdd85
TS
2748 break;
2749 case 26:
7a387fff 2750 /* ignored */
8c0fdd85
TS
2751 rn = "ECC";
2752 break;
2753 case 27:
7a387fff
TS
2754 switch (sel) {
2755 case 0 ... 3:
2756 /* ignored */
2757 rn = "CacheErr";
2758 break;
2759 default:
2760 goto die;
2761 }
8c0fdd85
TS
2762 break;
2763 case 28:
2764 switch (sel) {
2765 case 0:
7a387fff
TS
2766 case 2:
2767 case 4:
2768 case 6:
8c0fdd85
TS
2769 gen_op_mtc0_taglo();
2770 rn = "TagLo";
2771 break;
7a387fff
TS
2772 case 1:
2773 case 3:
2774 case 5:
2775 case 7:
2776 gen_op_mtc0_datalo();
2777 rn = "DataLo";
2778 break;
8c0fdd85 2779 default:
8c0fdd85
TS
2780 goto die;
2781 }
2782 break;
2783 case 29:
7a387fff
TS
2784 switch (sel) {
2785 case 0:
2786 case 2:
2787 case 4:
2788 case 6:
2789 gen_op_mtc0_taghi();
2790 rn = "TagHi";
2791 break;
2792 case 1:
2793 case 3:
2794 case 5:
2795 case 7:
2796 gen_op_mtc0_datahi();
2797 rn = "DataHi";
2798 break;
2799 default:
2800 rn = "invalid sel";
2801 goto die;
2802 }
8c0fdd85
TS
2803 break;
2804 case 30:
7a387fff
TS
2805 switch (sel) {
2806 case 0:
2807 gen_op_mtc0_errorepc();
2808 rn = "ErrorEPC";
2809 break;
2810 default:
2811 goto die;
2812 }
8c0fdd85
TS
2813 break;
2814 case 31:
7a387fff
TS
2815 switch (sel) {
2816 case 0:
2817 gen_op_mtc0_desave(); /* EJTAG support */
2818 rn = "DESAVE";
2819 break;
2820 default:
2821 goto die;
2822 }
2823 /* Stop translation as we may have switched the execution mode */
2824 ctx->bstate = BS_STOP;
8c0fdd85
TS
2825 break;
2826 default:
8c0fdd85
TS
2827 goto die;
2828 }
2829#if defined MIPS_DEBUG_DISAS
2830 if (loglevel & CPU_LOG_TB_IN_ASM) {
7a387fff
TS
2831 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2832 rn, reg, sel);
8c0fdd85
TS
2833 }
2834#endif
2835 return;
2836
2837die:
2838#if defined MIPS_DEBUG_DISAS
2839 if (loglevel & CPU_LOG_TB_IN_ASM) {
7a387fff
TS
2840 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2841 rn, reg, sel);
8c0fdd85
TS
2842 }
2843#endif
2844 generate_exception(ctx, EXCP_RI);
2845}
2846
9c2149c8
TS
2847static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
2848{
2849 const char *rn = "invalid";
2850
2851 switch (reg) {
2852 case 0:
2853 switch (sel) {
2854 case 0:
2855 gen_op_mfc0_index();
2856 rn = "Index";
2857 break;
2858 case 1:
2859// gen_op_dmfc0_mvpcontrol(); /* MT ASE */
2860 rn = "MVPControl";
2861// break;
2862 case 2:
2863// gen_op_dmfc0_mvpconf0(); /* MT ASE */
2864 rn = "MVPConf0";
2865// break;
2866 case 3:
2867// gen_op_dmfc0_mvpconf1(); /* MT ASE */
2868 rn = "MVPConf1";
2869// break;
2870 default:
2871 goto die;
2872 }
2873 break;
2874 case 1:
2875 switch (sel) {
2876 case 0:
2877 gen_op_mfc0_random();
2878 rn = "Random";
2879 break;
2880 case 1:
2881// gen_op_dmfc0_vpecontrol(); /* MT ASE */
2882 rn = "VPEControl";
2883// break;
2884 case 2:
2885// gen_op_dmfc0_vpeconf0(); /* MT ASE */
2886 rn = "VPEConf0";
2887// break;
2888 case 3:
2889// gen_op_dmfc0_vpeconf1(); /* MT ASE */
2890 rn = "VPEConf1";
2891// break;
2892 case 4:
2893// gen_op_dmfc0_YQMask(); /* MT ASE */
2894 rn = "YQMask";
2895// break;
2896 case 5:
2897// gen_op_dmfc0_vpeschedule(); /* MT ASE */
2898 rn = "VPESchedule";
2899// break;
2900 case 6:
2901// gen_op_dmfc0_vpeschefback(); /* MT ASE */
2902 rn = "VPEScheFBack";
2903// break;
2904 case 7:
2905// gen_op_dmfc0_vpeopt(); /* MT ASE */
2906 rn = "VPEOpt";
2907// break;
2908 default:
2909 goto die;
2910 }
2911 break;
2912 case 2:
2913 switch (sel) {
2914 case 0:
2915 gen_op_dmfc0_entrylo0();
2916 rn = "EntryLo0";
2917 break;
2918 case 1:
2919// gen_op_dmfc0_tcstatus(); /* MT ASE */
2920 rn = "TCStatus";
2921// break;
2922 case 2:
2923// gen_op_dmfc0_tcbind(); /* MT ASE */
2924 rn = "TCBind";
2925// break;
2926 case 3:
2927// gen_op_dmfc0_tcrestart(); /* MT ASE */
2928 rn = "TCRestart";
2929// break;
2930 case 4:
2931// gen_op_dmfc0_tchalt(); /* MT ASE */
2932 rn = "TCHalt";
2933// break;
2934 case 5:
2935// gen_op_dmfc0_tccontext(); /* MT ASE */
2936 rn = "TCContext";
2937// break;
2938 case 6:
2939// gen_op_dmfc0_tcschedule(); /* MT ASE */
2940 rn = "TCSchedule";
2941// break;
2942 case 7:
2943// gen_op_dmfc0_tcschefback(); /* MT ASE */
2944 rn = "TCScheFBack";
2945// break;
2946 default:
2947 goto die;
2948 }
2949 break;
2950 case 3:
2951 switch (sel) {
2952 case 0:
2953 gen_op_dmfc0_entrylo1();
2954 rn = "EntryLo1";
2955 break;
2956 default:
2957 goto die;
2958 }
2959 break;
2960 case 4:
2961 switch (sel) {
2962 case 0:
2963 gen_op_dmfc0_context();
2964 rn = "Context";
2965 break;
2966 case 1:
2967// gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */
2968 rn = "ContextConfig";
2969// break;
2970 default:
2971 goto die;
2972 }
2973 break;
2974 case 5:
2975 switch (sel) {
2976 case 0:
2977 gen_op_mfc0_pagemask();
2978 rn = "PageMask";
2979 break;
2980 case 1:
2981 gen_op_mfc0_pagegrain();
2982 rn = "PageGrain";
2983 break;
2984 default:
2985 goto die;
2986 }
2987 break;
2988 case 6:
2989 switch (sel) {
2990 case 0:
2991 gen_op_mfc0_wired();
2992 rn = "Wired";
2993 break;
2994 case 1:
2995// gen_op_dmfc0_srsconf0(); /* shadow registers */
2996 rn = "SRSConf0";
2997// break;
2998 case 2:
2999// gen_op_dmfc0_srsconf1(); /* shadow registers */
3000 rn = "SRSConf1";
3001// break;
3002 case 3:
3003// gen_op_dmfc0_srsconf2(); /* shadow registers */
3004 rn = "SRSConf2";
3005// break;
3006 case 4:
3007// gen_op_dmfc0_srsconf3(); /* shadow registers */
3008 rn = "SRSConf3";
3009// break;
3010 case 5:
3011// gen_op_dmfc0_srsconf4(); /* shadow registers */
3012 rn = "SRSConf4";
3013// break;
3014 default:
3015 goto die;
3016 }
3017 break;
3018 case 7:
3019 switch (sel) {
3020 case 0:
3021 gen_op_mfc0_hwrena();
3022 rn = "HWREna";
3023 break;
3024 default:
3025 goto die;
3026 }
3027 break;
3028 case 8:
3029 switch (sel) {
3030 case 0:
3031 gen_op_dmfc0_badvaddr();
3032 rn = "BadVaddr";
3033 break;
3034 default:
3035 goto die;
3036 }
3037 break;
3038 case 9:
3039 switch (sel) {
3040 case 0:
3041 gen_op_mfc0_count();
3042 rn = "Count";
3043 break;
3044 /* 6,7 are implementation dependent */
3045 default:
3046 goto die;
3047 }
3048 break;
3049 case 10:
3050 switch (sel) {
3051 case 0:
3052 gen_op_dmfc0_entryhi();
3053 rn = "EntryHi";
3054 break;
3055 default:
3056 goto die;
3057 }
3058 break;
3059 case 11:
3060 switch (sel) {
3061 case 0:
3062 gen_op_mfc0_compare();
3063 rn = "Compare";
3064 break;
3065 /* 6,7 are implementation dependent */
3066 default:
3067 goto die;
3068 }
3069 break;
3070 case 12:
3071 switch (sel) {
3072 case 0:
3073 gen_op_mfc0_status();
3074 rn = "Status";
3075 break;
3076 case 1:
3077 gen_op_mfc0_intctl();
3078 rn = "IntCtl";
3079 break;
3080 case 2:
3081 gen_op_mfc0_srsctl();
3082 rn = "SRSCtl";
3083 break;
3084 case 3:
3085 gen_op_mfc0_srsmap(); /* shadow registers */
3086 rn = "SRSMap";
3087 break;
3088 default:
3089 goto die;
3090 }
3091 break;
3092 case 13:
3093 switch (sel) {
3094 case 0:
3095 gen_op_mfc0_cause();
3096 rn = "Cause";
3097 break;
3098 default:
3099 goto die;
3100 }
3101 break;
3102 case 14:
3103 switch (sel) {
3104 case 0:
3105 gen_op_dmfc0_epc();
3106 rn = "EPC";
3107 break;
3108 default:
3109 goto die;
3110 }
3111 break;
3112 case 15:
3113 switch (sel) {
3114 case 0:
3115 gen_op_mfc0_prid();
3116 rn = "PRid";
3117 break;
3118 case 1:
b29a0341 3119 gen_op_mfc0_ebase();
9c2149c8
TS
3120 rn = "EBase";
3121 break;
3122 default:
3123 goto die;
3124 }
3125 break;
3126 case 16:
3127 switch (sel) {
3128 case 0:
3129 gen_op_mfc0_config0();
3130 rn = "Config";
3131 break;
3132 case 1:
3133 gen_op_mfc0_config1();
3134 rn = "Config1";
3135 break;
3136 case 2:
3137 gen_op_mfc0_config2();
3138 rn = "Config2";
3139 break;
3140 case 3:
3141 gen_op_mfc0_config3();
3142 rn = "Config3";
3143 break;
3144 /* 6,7 are implementation dependent */
3145 default:
3146 goto die;
3147 }
3148 break;
3149 case 17:
3150 switch (sel) {
3151 case 0:
3152 gen_op_dmfc0_lladdr();
3153 rn = "LLAddr";
3154 break;
3155 default:
3156 goto die;
3157 }
3158 break;
3159 case 18:
3160 switch (sel) {
3161 case 0:
3162 gen_op_dmfc0_watchlo0();
3163 rn = "WatchLo";
3164 break;
3165 case 1:
3166// gen_op_dmfc0_watchlo1();
3167 rn = "WatchLo1";
3168// break;
3169 case 2:
3170// gen_op_dmfc0_watchlo2();
3171 rn = "WatchLo2";
3172// break;
3173 case 3:
3174// gen_op_dmfc0_watchlo3();
3175 rn = "WatchLo3";
3176// break;
3177 case 4:
3178// gen_op_dmfc0_watchlo4();
3179 rn = "WatchLo4";
3180// break;
3181 case 5:
3182// gen_op_dmfc0_watchlo5();
3183 rn = "WatchLo5";
3184// break;
3185 case 6:
3186// gen_op_dmfc0_watchlo6();
3187 rn = "WatchLo6";
3188// break;
3189 case 7:
3190// gen_op_dmfc0_watchlo7();
3191 rn = "WatchLo7";
3192// break;
3193 default:
3194 goto die;
3195 }
3196 break;
3197 case 19:
3198 switch (sel) {
3199 case 0:
3200 gen_op_mfc0_watchhi0();
3201 rn = "WatchHi";
3202 break;
3203 case 1:
3204// gen_op_mfc0_watchhi1();
3205 rn = "WatchHi1";
3206// break;
3207 case 2:
3208// gen_op_mfc0_watchhi2();
3209 rn = "WatchHi2";
3210// break;
3211 case 3:
3212// gen_op_mfc0_watchhi3();
3213 rn = "WatchHi3";
3214// break;
3215 case 4:
3216// gen_op_mfc0_watchhi4();
3217 rn = "WatchHi4";
3218// break;
3219 case 5:
3220// gen_op_mfc0_watchhi5();
3221 rn = "WatchHi5";
3222// break;
3223 case 6:
3224// gen_op_mfc0_watchhi6();
3225 rn = "WatchHi6";
3226// break;
3227 case 7:
3228// gen_op_mfc0_watchhi7();
3229 rn = "WatchHi7";
3230// break;
3231 default:
3232 goto die;
3233 }
3234 break;
3235 case 20:
3236 switch (sel) {
3237 case 0:
3238 /* 64 bit MMU only */
3239 gen_op_dmfc0_xcontext();
3240 rn = "XContext";
3241 break;
3242 default:
3243 goto die;
3244 }
3245 break;
3246 case 21:
3247 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3248 switch (sel) {
3249 case 0:
3250 gen_op_mfc0_framemask();
3251 rn = "Framemask";
3252 break;
3253 default:
3254 goto die;
3255 }
3256 break;
3257 case 22:
3258 /* ignored */
3259 rn = "'Diagnostic"; /* implementation dependent */
3260 break;
3261 case 23:
3262 switch (sel) {
3263 case 0:
3264 gen_op_mfc0_debug(); /* EJTAG support */
3265 rn = "Debug";
3266 break;
3267 case 1:
3268// gen_op_dmfc0_tracecontrol(); /* PDtrace support */
3269 rn = "TraceControl";
3270// break;
3271 case 2:
3272// gen_op_dmfc0_tracecontrol2(); /* PDtrace support */
3273 rn = "TraceControl2";
3274// break;
3275 case 3:
3276// gen_op_dmfc0_usertracedata(); /* PDtrace support */
3277 rn = "UserTraceData";
3278// break;
3279 case 4:
3280// gen_op_dmfc0_debug(); /* PDtrace support */
3281 rn = "TraceBPC";
3282// break;
3283 default:
3284 goto die;
3285 }
3286 break;
3287 case 24:
3288 switch (sel) {
3289 case 0:
3290 gen_op_dmfc0_depc(); /* EJTAG support */
3291 rn = "DEPC";
3292 break;
3293 default:
3294 goto die;
3295 }
3296 break;
3297 case 25:
3298 switch (sel) {
3299 case 0:
3300 gen_op_mfc0_performance0();
3301 rn = "Performance0";
3302 break;
3303 case 1:
3304// gen_op_dmfc0_performance1();
3305 rn = "Performance1";
3306// break;
3307 case 2:
3308// gen_op_dmfc0_performance2();
3309 rn = "Performance2";
3310// break;
3311 case 3:
3312// gen_op_dmfc0_performance3();
3313 rn = "Performance3";
3314// break;
3315 case 4:
3316// gen_op_dmfc0_performance4();
3317 rn = "Performance4";
3318// break;
3319 case 5:
3320// gen_op_dmfc0_performance5();
3321 rn = "Performance5";
3322// break;
3323 case 6:
3324// gen_op_dmfc0_performance6();
3325 rn = "Performance6";
3326// break;
3327 case 7:
3328// gen_op_dmfc0_performance7();
3329 rn = "Performance7";
3330// break;
3331 default:
3332 goto die;
3333 }
3334 break;
3335 case 26:
3336 rn = "ECC";
3337 break;
3338 case 27:
3339 switch (sel) {
3340 /* ignored */
3341 case 0 ... 3:
3342 rn = "CacheErr";
3343 break;
3344 default:
3345 goto die;
3346 }
3347 break;
3348 case 28:
3349 switch (sel) {
3350 case 0:
3351 case 2:
3352 case 4:
3353 case 6:
3354 gen_op_mfc0_taglo();
3355 rn = "TagLo";
3356 break;
3357 case 1:
3358 case 3:
3359 case 5:
3360 case 7:
3361 gen_op_mfc0_datalo();
3362 rn = "DataLo";
3363 break;
3364 default:
3365 goto die;
3366 }
3367 break;
3368 case 29:
3369 switch (sel) {
3370 case 0:
3371 case 2:
3372 case 4:
3373 case 6:
3374 gen_op_mfc0_taghi();
3375 rn = "TagHi";
3376 break;
3377 case 1:
3378 case 3:
3379 case 5:
3380 case 7:
3381 gen_op_mfc0_datahi();
3382 rn = "DataHi";
3383 break;
3384 default:
3385 goto die;
3386 }
3387 break;
3388 case 30:
3389 switch (sel) {
3390 case 0:
3391 gen_op_dmfc0_errorepc();
3392 rn = "ErrorEPC";
3393 break;
3394 default:
3395 goto die;
3396 }
3397 break;
3398 case 31:
3399 switch (sel) {
3400 case 0:
3401 gen_op_mfc0_desave(); /* EJTAG support */
3402 rn = "DESAVE";
3403 break;
3404 default:
3405 goto die;
3406 }
3407 break;
3408 default:
3409 goto die;
3410 }
3411#if defined MIPS_DEBUG_DISAS
3412 if (loglevel & CPU_LOG_TB_IN_ASM) {
3413 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3414 rn, reg, sel);
3415 }
3416#endif
3417 return;
3418
3419die:
3420#if defined MIPS_DEBUG_DISAS
3421 if (loglevel & CPU_LOG_TB_IN_ASM) {
3422 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3423 rn, reg, sel);
3424 }
3425#endif
3426 generate_exception(ctx, EXCP_RI);
3427}
3428
3429static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
3430{
3431 const char *rn = "invalid";
3432
3433 switch (reg) {
3434 case 0:
3435 switch (sel) {
3436 case 0:
3437 gen_op_mtc0_index();
3438 rn = "Index";
3439 break;
3440 case 1:
3441// gen_op_dmtc0_mvpcontrol(); /* MT ASE */
3442 rn = "MVPControl";
3443// break;
3444 case 2:
3445// gen_op_dmtc0_mvpconf0(); /* MT ASE */
3446 rn = "MVPConf0";
3447// break;
3448 case 3:
3449// gen_op_dmtc0_mvpconf1(); /* MT ASE */
3450 rn = "MVPConf1";
3451// break;
3452 default:
3453 goto die;
3454 }
3455 break;
3456 case 1:
3457 switch (sel) {
3458 case 0:
3459 /* ignored */
3460 rn = "Random";
3461 break;
3462 case 1:
3463// gen_op_dmtc0_vpecontrol(); /* MT ASE */
3464 rn = "VPEControl";
3465// break;
3466 case 2:
3467// gen_op_dmtc0_vpeconf0(); /* MT ASE */
3468 rn = "VPEConf0";
3469// break;
3470 case 3:
3471// gen_op_dmtc0_vpeconf1(); /* MT ASE */
3472 rn = "VPEConf1";
3473// break;
3474 case 4:
3475// gen_op_dmtc0_YQMask(); /* MT ASE */
3476 rn = "YQMask";
3477// break;
3478 case 5:
3479// gen_op_dmtc0_vpeschedule(); /* MT ASE */
3480 rn = "VPESchedule";
3481// break;
3482 case 6:
3483// gen_op_dmtc0_vpeschefback(); /* MT ASE */
3484 rn = "VPEScheFBack";
3485// break;
3486 case 7:
3487// gen_op_dmtc0_vpeopt(); /* MT ASE */
3488 rn = "VPEOpt";
3489// break;
3490 default:
3491 goto die;
3492 }
3493 break;
3494 case 2:
3495 switch (sel) {
3496 case 0:
3497 gen_op_dmtc0_entrylo0();
3498 rn = "EntryLo0";
3499 break;
3500 case 1:
3501// gen_op_dmtc0_tcstatus(); /* MT ASE */
3502 rn = "TCStatus";
3503// break;
3504 case 2:
3505// gen_op_dmtc0_tcbind(); /* MT ASE */
3506 rn = "TCBind";
3507// break;
3508 case 3:
3509// gen_op_dmtc0_tcrestart(); /* MT ASE */
3510 rn = "TCRestart";
3511// break;
3512 case 4:
3513// gen_op_dmtc0_tchalt(); /* MT ASE */
3514 rn = "TCHalt";
3515// break;
3516 case 5:
3517// gen_op_dmtc0_tccontext(); /* MT ASE */
3518 rn = "TCContext";
3519// break;
3520 case 6:
3521// gen_op_dmtc0_tcschedule(); /* MT ASE */
3522 rn = "TCSchedule";
3523// break;
3524 case 7:
3525// gen_op_dmtc0_tcschefback(); /* MT ASE */
3526 rn = "TCScheFBack";
3527// break;
3528 default:
3529 goto die;
3530 }
3531 break;
3532 case 3:
3533 switch (sel) {
3534 case 0:
3535 gen_op_dmtc0_entrylo1();
3536 rn = "EntryLo1";
3537 break;
3538 default:
3539 goto die;
3540 }
3541 break;
3542 case 4:
3543 switch (sel) {
3544 case 0:
3545 gen_op_dmtc0_context();
3546 rn = "Context";
3547 break;
3548 case 1:
3549// gen_op_dmtc0_contextconfig(); /* SmartMIPS ASE */
3550 rn = "ContextConfig";
3551// break;
3552 default:
3553 goto die;
3554 }
3555 break;
3556 case 5:
3557 switch (sel) {
3558 case 0:
3559 gen_op_mtc0_pagemask();
3560 rn = "PageMask";
3561 break;
3562 case 1:
3563 gen_op_mtc0_pagegrain();
3564 rn = "PageGrain";
3565 break;
3566 default:
3567 goto die;
3568 }
3569 break;
3570 case 6:
3571 switch (sel) {
3572 case 0:
3573 gen_op_mtc0_wired();
3574 rn = "Wired";
3575 break;
3576 case 1:
3577// gen_op_dmtc0_srsconf0(); /* shadow registers */
3578 rn = "SRSConf0";
3579// break;
3580 case 2:
3581// gen_op_dmtc0_srsconf1(); /* shadow registers */
3582 rn = "SRSConf1";
3583// break;
3584 case 3:
3585// gen_op_dmtc0_srsconf2(); /* shadow registers */
3586 rn = "SRSConf2";
3587// break;
3588 case 4:
3589// gen_op_dmtc0_srsconf3(); /* shadow registers */
3590 rn = "SRSConf3";
3591// break;
3592 case 5:
3593// gen_op_dmtc0_srsconf4(); /* shadow registers */
3594 rn = "SRSConf4";
3595// break;
3596 default:
3597 goto die;
3598 }
3599 break;
3600 case 7:
3601 switch (sel) {
3602 case 0:
3603 gen_op_mtc0_hwrena();
3604 rn = "HWREna";
3605 break;
3606 default:
3607 goto die;
3608 }
3609 break;
3610 case 8:
3611 /* ignored */
3612 rn = "BadVaddr";
3613 break;
3614 case 9:
3615 switch (sel) {
3616 case 0:
3617 gen_op_mtc0_count();
3618 rn = "Count";
3619 break;
3620 /* 6,7 are implementation dependent */
3621 default:
3622 goto die;
3623 }
3624 /* Stop translation as we may have switched the execution mode */
3625 ctx->bstate = BS_STOP;
3626 break;
3627 case 10:
3628 switch (sel) {
3629 case 0:
3630 gen_op_mtc0_entryhi();
3631 rn = "EntryHi";
3632 break;
3633 default:
3634 goto die;
3635 }
3636 break;
3637 case 11:
3638 switch (sel) {
3639 case 0:
3640 gen_op_mtc0_compare();
3641 rn = "Compare";
3642 break;
3643 /* 6,7 are implementation dependent */
3644 default:
3645 goto die;
3646 }
3647 /* Stop translation as we may have switched the execution mode */
3648 ctx->bstate = BS_STOP;
3649 break;
3650 case 12:
3651 switch (sel) {
3652 case 0:
3653 gen_op_mtc0_status();
3654 rn = "Status";
3655 break;
3656 case 1:
3657 gen_op_mtc0_intctl();
3658 rn = "IntCtl";
3659 break;
3660 case 2:
3661 gen_op_mtc0_srsctl();
3662 rn = "SRSCtl";
3663 break;
3664 case 3:
3665 gen_op_mtc0_srsmap(); /* shadow registers */
3666 rn = "SRSMap";
3667 break;
3668 default:
3669 goto die;
3670 }
3671 /* Stop translation as we may have switched the execution mode */
3672 ctx->bstate = BS_STOP;
3673 break;
3674 case 13:
3675 switch (sel) {
3676 case 0:
3677 gen_op_mtc0_cause();
3678 rn = "Cause";
3679 break;
3680 default:
3681 goto die;
3682 }
3683 /* Stop translation as we may have switched the execution mode */
3684 ctx->bstate = BS_STOP;
3685 break;
3686 case 14:
3687 switch (sel) {
3688 case 0:
3689 gen_op_dmtc0_epc();
3690 rn = "EPC";
3691 break;
3692 default:
3693 goto die;
3694 }
3695 break;
3696 case 15:
3697 switch (sel) {
3698 case 0:
3699 /* ignored */
3700 rn = "PRid";
3701 break;
3702 case 1:
b29a0341 3703 gen_op_mtc0_ebase();
9c2149c8
TS
3704 rn = "EBase";
3705 break;
3706 default:
3707 goto die;
3708 }
3709 break;
3710 case 16:
3711 switch (sel) {
3712 case 0:
3713 gen_op_mtc0_config0();
3714 rn = "Config";
3715 break;
3716 case 1:
3717 /* ignored */
3718 rn = "Config1";
3719 break;
3720 case 2:
3721 gen_op_mtc0_config2();
3722 rn = "Config2";
3723 break;
3724 case 3:
3725 /* ignored */
3726 rn = "Config3";
3727 break;
3728 /* 6,7 are implementation dependent */
3729 default:
3730 rn = "Invalid config selector";
3731 goto die;
3732 }
3733 /* Stop translation as we may have switched the execution mode */
3734 ctx->bstate = BS_STOP;
3735 break;
3736 case 17:
3737 switch (sel) {
3738 case 0:
3739 /* ignored */
3740 rn = "LLAddr";
3741 break;
3742 default:
3743 goto die;
3744 }
3745 break;
3746 case 18:
3747 switch (sel) {
3748 case 0:
3749 gen_op_dmtc0_watchlo0();
3750 rn = "WatchLo";
3751 break;
3752 case 1:
3753// gen_op_dmtc0_watchlo1();
3754 rn = "WatchLo1";
3755// break;
3756 case 2:
3757// gen_op_dmtc0_watchlo2();
3758 rn = "WatchLo2";
3759// break;
3760 case 3:
3761// gen_op_dmtc0_watchlo3();
3762 rn = "WatchLo3";
3763// break;
3764 case 4:
3765// gen_op_dmtc0_watchlo4();
3766 rn = "WatchLo4";
3767// break;
3768 case 5:
3769// gen_op_dmtc0_watchlo5();
3770 rn = "WatchLo5";
3771// break;
3772 case 6:
3773// gen_op_dmtc0_watchlo6();
3774 rn = "WatchLo6";
3775// break;
3776 case 7:
3777// gen_op_dmtc0_watchlo7();
3778 rn = "WatchLo7";
3779// break;
3780 default:
3781 goto die;
3782 }
3783 break;
3784 case 19:
3785 switch (sel) {
3786 case 0:
3787 gen_op_mtc0_watchhi0();
3788 rn = "WatchHi";
3789 break;
3790 case 1:
3791// gen_op_dmtc0_watchhi1();
3792 rn = "WatchHi1";
3793// break;
3794 case 2:
3795// gen_op_dmtc0_watchhi2();
3796 rn = "WatchHi2";
3797// break;
3798 case 3:
3799// gen_op_dmtc0_watchhi3();
3800 rn = "WatchHi3";
3801// break;
3802 case 4:
3803// gen_op_dmtc0_watchhi4();
3804 rn = "WatchHi4";
3805// break;
3806 case 5:
3807// gen_op_dmtc0_watchhi5();
3808 rn = "WatchHi5";
3809// break;
3810 case 6:
3811// gen_op_dmtc0_watchhi6();
3812 rn = "WatchHi6";
3813// break;
3814 case 7:
3815// gen_op_dmtc0_watchhi7();
3816 rn = "WatchHi7";
3817// break;
3818 default:
3819 goto die;
3820 }
3821 break;
3822 case 20:
3823 switch (sel) {
3824 case 0:
3825 /* 64 bit MMU only */
3826 gen_op_dmtc0_xcontext();
3827 rn = "XContext";
3828 break;
3829 default:
3830 goto die;
3831 }
3832 break;
3833 case 21:
3834 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3835 switch (sel) {
3836 case 0:
3837 gen_op_mtc0_framemask();
3838 rn = "Framemask";
3839 break;
3840 default:
3841 goto die;
3842 }
3843 break;
3844 case 22:
3845 /* ignored */
3846 rn = "Diagnostic"; /* implementation dependent */
3847 break;
3848 case 23:
3849 switch (sel) {
3850 case 0:
3851 gen_op_mtc0_debug(); /* EJTAG support */
3852 rn = "Debug";
3853 break;
3854 case 1:
3855// gen_op_dmtc0_tracecontrol(); /* PDtrace support */
3856 rn = "TraceControl";
3857// break;
3858 case 2:
3859// gen_op_dmtc0_tracecontrol2(); /* PDtrace support */
3860 rn = "TraceControl2";
3861// break;
3862 case 3:
3863// gen_op_dmtc0_usertracedata(); /* PDtrace support */
3864 rn = "UserTraceData";
3865// break;
3866 case 4:
3867// gen_op_dmtc0_debug(); /* PDtrace support */
3868 rn = "TraceBPC";
3869// break;
3870 default:
3871 goto die;
3872 }
3873 /* Stop translation as we may have switched the execution mode */
3874 ctx->bstate = BS_STOP;
3875 break;
3876 case 24:
3877 switch (sel) {
3878 case 0:
3879 gen_op_dmtc0_depc(); /* EJTAG support */
3880 rn = "DEPC";
3881 break;
3882 default:
3883 goto die;
3884 }
3885 break;
3886 case 25:
3887 switch (sel) {
3888 case 0:
3889 gen_op_mtc0_performance0();
3890 rn = "Performance0";
3891 break;
3892 case 1:
3893// gen_op_dmtc0_performance1();
3894 rn = "Performance1";
3895// break;
3896 case 2:
3897// gen_op_dmtc0_performance2();
3898 rn = "Performance2";
3899// break;
3900 case 3:
3901// gen_op_dmtc0_performance3();
3902 rn = "Performance3";
3903// break;
3904 case 4:
3905// gen_op_dmtc0_performance4();
3906 rn = "Performance4";
3907// break;
3908 case 5:
3909// gen_op_dmtc0_performance5();
3910 rn = "Performance5";
3911// break;
3912 case 6:
3913// gen_op_dmtc0_performance6();
3914 rn = "Performance6";
3915// break;
3916 case 7:
3917// gen_op_dmtc0_performance7();
3918 rn = "Performance7";
3919// break;
3920 default:
3921 goto die;
3922 }
3923 break;
3924 case 26:
3925 /* ignored */
3926 rn = "ECC";
3927 break;
3928 case 27:
3929 switch (sel) {
3930 case 0 ... 3:
3931 /* ignored */
3932 rn = "CacheErr";
3933 break;
3934 default:
3935 goto die;
3936 }
3937 break;
3938 case 28:
3939 switch (sel) {
3940 case 0:
3941 case 2:
3942 case 4:
3943 case 6:
3944 gen_op_mtc0_taglo();
3945 rn = "TagLo";
3946 break;
3947 case 1:
3948 case 3:
3949 case 5:
3950 case 7:
3951 gen_op_mtc0_datalo();
3952 rn = "DataLo";
3953 break;
3954 default:
3955 goto die;
3956 }
3957 break;
3958 case 29:
3959 switch (sel) {
3960 case 0:
3961 case 2:
3962 case 4:
3963 case 6:
3964 gen_op_mtc0_taghi();
3965 rn = "TagHi";
3966 break;
3967 case 1:
3968 case 3:
3969 case 5:
3970 case 7:
3971 gen_op_mtc0_datahi();
3972 rn = "DataHi";
3973 break;
3974 default:
3975 rn = "invalid sel";
3976 goto die;
3977 }
3978 break;
3979 case 30:
3980 switch (sel) {
3981 case 0:
3982 gen_op_dmtc0_errorepc();
3983 rn = "ErrorEPC";
3984 break;
3985 default:
3986 goto die;
3987 }
3988 break;
3989 case 31:
3990 switch (sel) {
3991 case 0:
3992 gen_op_mtc0_desave(); /* EJTAG support */
3993 rn = "DESAVE";
3994 break;
3995 default:
3996 goto die;
3997 }
3998 /* Stop translation as we may have switched the execution mode */
3999 ctx->bstate = BS_STOP;
4000 break;
4001 default:
4002 goto die;
4003 }
4004#if defined MIPS_DEBUG_DISAS
4005 if (loglevel & CPU_LOG_TB_IN_ASM) {
4006 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4007 rn, reg, sel);
4008 }
4009#endif
4010 return;
4011
4012die:
4013#if defined MIPS_DEBUG_DISAS
4014 if (loglevel & CPU_LOG_TB_IN_ASM) {
4015 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4016 rn, reg, sel);
4017 }
4018#endif
4019 generate_exception(ctx, EXCP_RI);
4020}
4021
7a387fff 4022static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 4023{
7a387fff 4024 const char *opn = "unk";
6af0bf9c 4025
6af0bf9c
FB
4026 switch (opc) {
4027 case OPC_MFC0:
4028 if (rt == 0) {
4029 /* Treat as NOP */
4030 return;
4031 }
873eb012 4032 gen_mfc0(ctx, rd, ctx->opcode & 0x7);
6af0bf9c
FB
4033 gen_op_store_T0_gpr(rt);
4034 opn = "mfc0";
4035 break;
4036 case OPC_MTC0:
4037 /* If we get an exception, we want to restart at next instruction */
9c2149c8 4038 /* XXX: breaks for mtc in delay slot */
6af0bf9c
FB
4039 ctx->pc += 4;
4040 save_cpu_state(ctx, 1);
4041 ctx->pc -= 4;
4042 GEN_LOAD_REG_TN(T0, rt);
8c0fdd85 4043 gen_mtc0(ctx, rd, ctx->opcode & 0x7);
6af0bf9c
FB
4044 opn = "mtc0";
4045 break;
9c2149c8
TS
4046 case OPC_DMFC0:
4047 if (rt == 0) {
4048 /* Treat as NOP */
4049 return;
4050 }
4051 gen_dmfc0(ctx, rd, ctx->opcode & 0x7);
4052 gen_op_store_T0_gpr(rt);
4053 opn = "dmfc0";
4054 break;
4055 case OPC_DMTC0:
4056 /* If we get an exception, we want to restart at next instruction */
4057 /* XXX: breaks for dmtc in delay slot */
4058 ctx->pc += 4;
4059 save_cpu_state(ctx, 1);
4060 ctx->pc -= 4;
4061 GEN_LOAD_REG_TN(T0, rt);
4062 gen_dmtc0(ctx, rd, ctx->opcode & 0x7);
4063 opn = "dmtc0";
4064 break;
6af0bf9c
FB
4065#if defined(MIPS_USES_R4K_TLB)
4066 case OPC_TLBWI:
4067 gen_op_tlbwi();
4068 opn = "tlbwi";
4069 break;
4070 case OPC_TLBWR:
4071 gen_op_tlbwr();
4072 opn = "tlbwr";
4073 break;
4074 case OPC_TLBP:
4075 gen_op_tlbp();
4076 opn = "tlbp";
4077 break;
4078 case OPC_TLBR:
4079 gen_op_tlbr();
4080 opn = "tlbr";
4081 break;
4082#endif
4083 case OPC_ERET:
4084 opn = "eret";
4085 save_cpu_state(ctx, 0);
4086 gen_op_eret();
4087 ctx->bstate = BS_EXCP;
4088 break;
4089 case OPC_DERET:
4090 opn = "deret";
4091 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
4092 generate_exception(ctx, EXCP_RI);
4093 } else {
4094 save_cpu_state(ctx, 0);
4095 gen_op_deret();
4096 ctx->bstate = BS_EXCP;
4097 }
4098 break;
4ad40f36
FB
4099 case OPC_WAIT:
4100 opn = "wait";
4101 /* If we get an exception, we want to restart at next instruction */
4102 ctx->pc += 4;
4103 save_cpu_state(ctx, 1);
4104 ctx->pc -= 4;
4105 gen_op_wait();
4106 ctx->bstate = BS_EXCP;
4107 break;
6af0bf9c
FB
4108 default:
4109 if (loglevel & CPU_LOG_TB_IN_ASM) {
4110 fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
4111 ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4112 ((ctx->opcode >> 16) & 0x1F));
4113 }
4114 generate_exception(ctx, EXCP_RI);
4115 return;
4116 }
4117 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
4118}
4119
6ea83fed 4120/* CP1 Branches (before delay slot) */
7a387fff 4121static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
6ea83fed
FB
4122 int32_t offset)
4123{
4124 target_ulong btarget;
4125
4126 btarget = ctx->pc + 4 + offset;
4127
7a387fff
TS
4128 switch (op) {
4129 case OPC_BC1F:
6ea83fed 4130 gen_op_bc1f();
3594c774 4131 MIPS_DEBUG("bc1f " TARGET_FMT_lx, btarget);
6ea83fed 4132 goto not_likely;
7a387fff 4133 case OPC_BC1FL:
6ea83fed 4134 gen_op_bc1f();
3594c774 4135 MIPS_DEBUG("bc1fl " TARGET_FMT_lx, btarget);
6ea83fed 4136 goto likely;
7a387fff 4137 case OPC_BC1T:
6ea83fed 4138 gen_op_bc1t();
3594c774 4139 MIPS_DEBUG("bc1t " TARGET_FMT_lx, btarget);
6ea83fed
FB
4140 not_likely:
4141 ctx->hflags |= MIPS_HFLAG_BC;
4142 break;
7a387fff 4143 case OPC_BC1TL:
6ea83fed 4144 gen_op_bc1t();
3594c774 4145 MIPS_DEBUG("bc1tl " TARGET_FMT_lx, btarget);
6ea83fed
FB
4146 likely:
4147 ctx->hflags |= MIPS_HFLAG_BL;
4148 break;
4149 default:
4150 MIPS_INVAL("cp1 branch/jump");
e397ee33 4151 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
4152 return;
4153 }
4154 gen_op_set_bcond();
4155
3594c774 4156 MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx,
6ea83fed
FB
4157 ctx->hflags, btarget);
4158 ctx->btarget = btarget;
4159
4160 return;
4161}
4162
6af0bf9c 4163/* Coprocessor 1 (FPU) */
7a387fff 4164static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 4165{
7a387fff 4166 const char *opn = "unk";
6ea83fed
FB
4167
4168 switch (opc) {
4169 case OPC_MFC1:
4170 GEN_LOAD_FREG_FTN(WT0, fs);
4171 gen_op_mfc1();
4172 GEN_STORE_TN_REG(rt, T0);
4173 opn = "mfc1";
4174 break;
4175 case OPC_MTC1:
4176 GEN_LOAD_REG_TN(T0, rt);
4177 gen_op_mtc1();
4178 GEN_STORE_FTN_FREG(fs, WT0);
4179 opn = "mtc1";
4180 break;
4181 case OPC_CFC1:
4182 if (fs != 0 && fs != 31) {
4183 MIPS_INVAL("cfc1 freg");
e397ee33 4184 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
4185 return;
4186 }
4187 GEN_LOAD_IMM_TN(T1, fs);
4188 gen_op_cfc1();
4189 GEN_STORE_TN_REG(rt, T0);
4190 opn = "cfc1";
4191 break;
4192 case OPC_CTC1:
7a387fff 4193 if (fs != 0 && fs != 31) {
6ea83fed 4194 MIPS_INVAL("ctc1 freg");
e397ee33 4195 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
4196 return;
4197 }
4198 GEN_LOAD_IMM_TN(T1, fs);
4199 GEN_LOAD_REG_TN(T0, rt);
4200 gen_op_ctc1();
4201 opn = "ctc1";
4202 break;
9c2149c8
TS
4203 case OPC_DMFC1:
4204 case OPC_DMTC1:
4205 /* Not implemented, fallthrough. */
6ea83fed
FB
4206 default:
4207 if (loglevel & CPU_LOG_TB_IN_ASM) {
4208 fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
4209 ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4210 ((ctx->opcode >> 16) & 0x1F));
4211 }
e397ee33 4212 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
4213 return;
4214 }
4215 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
4216}
4217
4218/* verify if floating point register is valid; an operation is not defined
4219 * if bit 0 of any register specification is set and the FR bit in the
4220 * Status register equals zero, since the register numbers specify an
4221 * even-odd pair of adjacent coprocessor general registers. When the FR bit
4222 * in the Status register equals one, both even and odd register numbers
00a709c7 4223 * are valid. This limitation exists only for 64 bit wide (d,l) registers.
6ea83fed 4224 *
00a709c7 4225 * Multiple 64 bit wide registers can be checked by calling
6ea83fed
FB
4226 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
4227 */
4228#define CHECK_FR(ctx, freg) do { \
4229 if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
e397ee33 4230 generate_exception (ctx, EXCP_RI); \
6ea83fed
FB
4231 return; \
4232 } \
4233 } while(0)
4234
4235#define FOP(func, fmt) (((fmt) << 21) | (func))
4236
7a387fff 4237static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
6ea83fed 4238{
7a387fff 4239 const char *opn = "unk";
6ea83fed
FB
4240 const char *condnames[] = {
4241 "c.f",
4242 "c.un",
4243 "c.eq",
4244 "c.ueq",
4245 "c.olt",
4246 "c.ult",
4247 "c.ole",
4248 "c.ule",
4249 "c.sf",
4250 "c.ngle",
4251 "c.seq",
4252 "c.ngl",
4253 "c.lt",
4254 "c.nge",
4255 "c.le",
4256 "c.ngt",
4257 };
4258 int binary = 0;
7a387fff
TS
4259 uint32_t func = ctx->opcode & 0x3f;
4260
6ea83fed
FB
4261 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
4262 case FOP(0, 17):
4263 CHECK_FR(ctx, fs | ft | fd);
4264 GEN_LOAD_FREG_FTN(DT0, fs);
4265 GEN_LOAD_FREG_FTN(DT1, ft);
4266 gen_op_float_add_d();
4267 GEN_STORE_FTN_FREG(fd, DT2);
4268 opn = "add.d";
4269 binary = 1;
4270 break;
4271 case FOP(1, 17):
4272 CHECK_FR(ctx, fs | ft | fd);
4273 GEN_LOAD_FREG_FTN(DT0, fs);
4274 GEN_LOAD_FREG_FTN(DT1, ft);
4275 gen_op_float_sub_d();
4276 GEN_STORE_FTN_FREG(fd, DT2);
4277 opn = "sub.d";
4278 binary = 1;
4279 break;
4280 case FOP(2, 17):
4281 CHECK_FR(ctx, fs | ft | fd);
4282 GEN_LOAD_FREG_FTN(DT0, fs);
4283 GEN_LOAD_FREG_FTN(DT1, ft);
4284 gen_op_float_mul_d();
4285 GEN_STORE_FTN_FREG(fd, DT2);
4286 opn = "mul.d";
4287 binary = 1;
4288 break;
4289 case FOP(3, 17):
4290 CHECK_FR(ctx, fs | ft | fd);
4291 GEN_LOAD_FREG_FTN(DT0, fs);
4292 GEN_LOAD_FREG_FTN(DT1, ft);
4293 gen_op_float_div_d();
4294 GEN_STORE_FTN_FREG(fd, DT2);
4295 opn = "div.d";
4296 binary = 1;
4297 break;
4298 case FOP(4, 17):
4299 CHECK_FR(ctx, fs | fd);
4300 GEN_LOAD_FREG_FTN(DT0, fs);
4301 gen_op_float_sqrt_d();
4302 GEN_STORE_FTN_FREG(fd, DT2);
4303 opn = "sqrt.d";
4304 break;
4305 case FOP(5, 17):
4306 CHECK_FR(ctx, fs | fd);
4307 GEN_LOAD_FREG_FTN(DT0, fs);
4308 gen_op_float_abs_d();
4309 GEN_STORE_FTN_FREG(fd, DT2);
4310 opn = "abs.d";
4311 break;
4312 case FOP(6, 17):
4313 CHECK_FR(ctx, fs | fd);
4314 GEN_LOAD_FREG_FTN(DT0, fs);
4315 gen_op_float_mov_d();
4316 GEN_STORE_FTN_FREG(fd, DT2);
4317 opn = "mov.d";
4318 break;
4319 case FOP(7, 17):
4320 CHECK_FR(ctx, fs | fd);
4321 GEN_LOAD_FREG_FTN(DT0, fs);
4322 gen_op_float_chs_d();
4323 GEN_STORE_FTN_FREG(fd, DT2);
4324 opn = "neg.d";
4325 break;
4326 /* 8 - round.l */
4327 /* 9 - trunc.l */
4328 /* 10 - ceil.l */
4329 /* 11 - floor.l */
4330 case FOP(12, 17):
00a709c7 4331 CHECK_FR(ctx, fs);
6ea83fed
FB
4332 GEN_LOAD_FREG_FTN(DT0, fs);
4333 gen_op_float_roundw_d();
4334 GEN_STORE_FTN_FREG(fd, WT2);
4335 opn = "round.w.d";
4336 break;
4337 case FOP(13, 17):
00a709c7 4338 CHECK_FR(ctx, fs);
6ea83fed
FB
4339 GEN_LOAD_FREG_FTN(DT0, fs);
4340 gen_op_float_truncw_d();
4341 GEN_STORE_FTN_FREG(fd, WT2);
4342 opn = "trunc.w.d";
4343 break;
4344 case FOP(14, 17):
00a709c7 4345 CHECK_FR(ctx, fs);
6ea83fed
FB
4346 GEN_LOAD_FREG_FTN(DT0, fs);
4347 gen_op_float_ceilw_d();
4348 GEN_STORE_FTN_FREG(fd, WT2);
4349 opn = "ceil.w.d";
4350 break;
4351 case FOP(15, 17):
00a709c7 4352 CHECK_FR(ctx, fs);
6ea83fed
FB
4353 GEN_LOAD_FREG_FTN(DT0, fs);
4354 gen_op_float_floorw_d();
4355 GEN_STORE_FTN_FREG(fd, WT2);
7a387fff 4356 opn = "floor.w.d";
6ea83fed 4357 break;
00a709c7
TS
4358 case FOP(33, 16):
4359 CHECK_FR(ctx, fd);
dd016883
FB
4360 GEN_LOAD_FREG_FTN(WT0, fs);
4361 gen_op_float_cvtd_s();
4362 GEN_STORE_FTN_FREG(fd, DT2);
4363 opn = "cvt.d.s";
4364 break;
00a709c7
TS
4365 case FOP(33, 20):
4366 CHECK_FR(ctx, fd);
6ea83fed
FB
4367 GEN_LOAD_FREG_FTN(WT0, fs);
4368 gen_op_float_cvtd_w();
4369 GEN_STORE_FTN_FREG(fd, DT2);
4370 opn = "cvt.d.w";
4371 break;
4372 case FOP(48, 17):
4373 case FOP(49, 17):
4374 case FOP(50, 17):
4375 case FOP(51, 17):
4376 case FOP(52, 17):
4377 case FOP(53, 17):
4378 case FOP(54, 17):
4379 case FOP(55, 17):
4380 case FOP(56, 17):
4381 case FOP(57, 17):
4382 case FOP(58, 17):
4383 case FOP(59, 17):
4384 case FOP(60, 17):
4385 case FOP(61, 17):
4386 case FOP(62, 17):
4387 case FOP(63, 17):
4388 CHECK_FR(ctx, fs | ft);
4389 GEN_LOAD_FREG_FTN(DT0, fs);
4390 GEN_LOAD_FREG_FTN(DT1, ft);
4391 gen_cmp_d(func-48);
4392 opn = condnames[func-48];
4393 break;
4394 case FOP(0, 16):
6ea83fed
FB
4395 GEN_LOAD_FREG_FTN(WT0, fs);
4396 GEN_LOAD_FREG_FTN(WT1, ft);
4397 gen_op_float_add_s();
4398 GEN_STORE_FTN_FREG(fd, WT2);
4399 opn = "add.s";
4400 binary = 1;
4401 break;
4402 case FOP(1, 16):
6ea83fed
FB
4403 GEN_LOAD_FREG_FTN(WT0, fs);
4404 GEN_LOAD_FREG_FTN(WT1, ft);
4405 gen_op_float_sub_s();
4406 GEN_STORE_FTN_FREG(fd, WT2);
4407 opn = "sub.s";
4408 binary = 1;
4409 break;
4410 case FOP(2, 16):
6ea83fed
FB
4411 GEN_LOAD_FREG_FTN(WT0, fs);
4412 GEN_LOAD_FREG_FTN(WT1, ft);
4413 gen_op_float_mul_s();
4414 GEN_STORE_FTN_FREG(fd, WT2);
4415 opn = "mul.s";
4416 binary = 1;
4417 break;
4418 case FOP(3, 16):
6ea83fed
FB
4419 GEN_LOAD_FREG_FTN(WT0, fs);
4420 GEN_LOAD_FREG_FTN(WT1, ft);
4421 gen_op_float_div_s();
4422 GEN_STORE_FTN_FREG(fd, WT2);
4423 opn = "div.s";
4424 binary = 1;
4425 break;
4426 case FOP(4, 16):
6ea83fed
FB
4427 GEN_LOAD_FREG_FTN(WT0, fs);
4428 gen_op_float_sqrt_s();
4429 GEN_STORE_FTN_FREG(fd, WT2);
4430 opn = "sqrt.s";
4431 break;
4432 case FOP(5, 16):
6ea83fed
FB
4433 GEN_LOAD_FREG_FTN(WT0, fs);
4434 gen_op_float_abs_s();
4435 GEN_STORE_FTN_FREG(fd, WT2);
4436 opn = "abs.s";
4437 break;
4438 case FOP(6, 16):
6ea83fed
FB
4439 GEN_LOAD_FREG_FTN(WT0, fs);
4440 gen_op_float_mov_s();
4441 GEN_STORE_FTN_FREG(fd, WT2);
4442 opn = "mov.s";
4443 break;
4444 case FOP(7, 16):
6ea83fed
FB
4445 GEN_LOAD_FREG_FTN(WT0, fs);
4446 gen_op_float_chs_s();
4447 GEN_STORE_FTN_FREG(fd, WT2);
4448 opn = "neg.s";
4449 break;
4450 case FOP(12, 16):
6ea83fed
FB
4451 GEN_LOAD_FREG_FTN(WT0, fs);
4452 gen_op_float_roundw_s();
4453 GEN_STORE_FTN_FREG(fd, WT2);
4454 opn = "round.w.s";
4455 break;
4456 case FOP(13, 16):
6ea83fed
FB
4457 GEN_LOAD_FREG_FTN(WT0, fs);
4458 gen_op_float_truncw_s();
4459 GEN_STORE_FTN_FREG(fd, WT2);
4460 opn = "trunc.w.s";
4461 break;
00a709c7
TS
4462 case FOP(32, 17):
4463 CHECK_FR(ctx, fs);
417f38f0 4464 GEN_LOAD_FREG_FTN(DT0, fs);
dd016883
FB
4465 gen_op_float_cvts_d();
4466 GEN_STORE_FTN_FREG(fd, WT2);
4467 opn = "cvt.s.d";
4468 break;
00a709c7 4469 case FOP(32, 20):
6ea83fed
FB
4470 GEN_LOAD_FREG_FTN(WT0, fs);
4471 gen_op_float_cvts_w();
4472 GEN_STORE_FTN_FREG(fd, WT2);
4473 opn = "cvt.s.w";
4474 break;
00a709c7 4475 case FOP(36, 16):
6ea83fed
FB
4476 GEN_LOAD_FREG_FTN(WT0, fs);
4477 gen_op_float_cvtw_s();
4478 GEN_STORE_FTN_FREG(fd, WT2);
4479 opn = "cvt.w.s";
4480 break;
00a709c7
TS
4481 case FOP(36, 17):
4482 CHECK_FR(ctx, fs);
417f38f0 4483 GEN_LOAD_FREG_FTN(DT0, fs);
6ea83fed
FB
4484 gen_op_float_cvtw_d();
4485 GEN_STORE_FTN_FREG(fd, WT2);
4486 opn = "cvt.w.d";
4487 break;
4488 case FOP(48, 16):
4489 case FOP(49, 16):
4490 case FOP(50, 16):
4491 case FOP(51, 16):
4492 case FOP(52, 16):
4493 case FOP(53, 16):
4494 case FOP(54, 16):
4495 case FOP(55, 16):
4496 case FOP(56, 16):
4497 case FOP(57, 16):
4498 case FOP(58, 16):
4499 case FOP(59, 16):
4500 case FOP(60, 16):
4501 case FOP(61, 16):
4502 case FOP(62, 16):
4503 case FOP(63, 16):
6ea83fed
FB
4504 GEN_LOAD_FREG_FTN(WT0, fs);
4505 GEN_LOAD_FREG_FTN(WT1, ft);
4506 gen_cmp_s(func-48);
4507 opn = condnames[func-48];
4508 break;
4509 default:
4510 if (loglevel & CPU_LOG_TB_IN_ASM) {
7a387fff 4511 fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
6ea83fed
FB
4512 ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4513 ((ctx->opcode >> 16) & 0x1F));
4514 }
e397ee33 4515 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
4516 return;
4517 }
4518 if (binary)
4519 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
4520 else
4521 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
4522}
6af0bf9c 4523
7a387fff
TS
4524static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4525{
4526 uint32_t ccbit;
4527
4528 if (cc)
4529 ccbit = 1 << (24 + cc);
4530 else
4531 ccbit = 1 << 23;
4532 if (!tf)
4533 gen_op_movf(ccbit, rd, rs);
4534 else
4535 gen_op_movt(ccbit, rd, rs);
4536}
4537
4538/* ISA extensions (ASEs) */
6af0bf9c
FB
4539/* MIPS16 extension to MIPS32 */
4540/* SmartMIPS extension to MIPS32 */
4541
60aa19ab 4542#ifdef TARGET_MIPS64
6af0bf9c
FB
4543/* Coprocessor 3 (FPU) */
4544
4545/* MDMX extension to MIPS64 */
4546/* MIPS-3D extension to MIPS64 */
4547
4548#endif
4549
c53be334
FB
4550static void gen_blikely(DisasContext *ctx)
4551{
eeef26cd
FB
4552 int l1;
4553 l1 = gen_new_label();
4554 gen_op_jnz_T2(l1);
4ad40f36 4555 gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
eeef26cd
FB
4556 gen_goto_tb(ctx, 1, ctx->pc + 4);
4557 gen_set_label(l1);
c53be334
FB
4558}
4559
36d23958 4560static void decode_opc (CPUState *env, DisasContext *ctx)
6af0bf9c
FB
4561{
4562 int32_t offset;
4563 int rs, rt, rd, sa;
7a387fff 4564 uint32_t op, op1, op2;
6af0bf9c
FB
4565 int16_t imm;
4566
d796321b
FB
4567 /* make sure instructions are on a word boundary */
4568 if (ctx->pc & 0x3) {
4569 generate_exception(ctx, EXCP_AdEL);
4570 return;
4571 }
4572
4ad40f36 4573 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
6af0bf9c 4574 /* Handle blikely not taken case */
3594c774 4575 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
c53be334 4576 gen_blikely(ctx);
6af0bf9c 4577 }
7a387fff
TS
4578 op = MASK_OP_MAJOR(ctx->opcode);
4579 rs = (ctx->opcode >> 21) & 0x1f;
4580 rt = (ctx->opcode >> 16) & 0x1f;
4581 rd = (ctx->opcode >> 11) & 0x1f;
4582 sa = (ctx->opcode >> 6) & 0x1f;
6af0bf9c
FB
4583 imm = (int16_t)ctx->opcode;
4584 switch (op) {
7a387fff
TS
4585 case OPC_SPECIAL:
4586 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 4587 switch (op1) {
7a387fff
TS
4588 case OPC_SLL: /* Arithmetic with immediate */
4589 case OPC_SRL ... OPC_SRA:
4590 gen_arith_imm(ctx, op1, rd, rt, sa);
4591 break;
4592 case OPC_SLLV: /* Arithmetic */
4593 case OPC_SRLV ... OPC_SRAV:
4594 case OPC_MOVZ ... OPC_MOVN:
4595 case OPC_ADD ... OPC_NOR:
4596 case OPC_SLT ... OPC_SLTU:
4597 gen_arith(ctx, op1, rd, rs, rt);
4598 break;
4599 case OPC_MULT ... OPC_DIVU:
4600 gen_muldiv(ctx, op1, rs, rt);
4601 break;
4602 case OPC_JR ... OPC_JALR:
4603 gen_compute_branch(ctx, op1, rs, rd, sa);
6af0bf9c 4604 return;
7a387fff
TS
4605 case OPC_TGE ... OPC_TEQ: /* Traps */
4606 case OPC_TNE:
4607 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 4608 break;
7a387fff
TS
4609 case OPC_MFHI: /* Move from HI/LO */
4610 case OPC_MFLO:
4611 gen_HILO(ctx, op1, rd);
6af0bf9c 4612 break;
7a387fff
TS
4613 case OPC_MTHI:
4614 case OPC_MTLO: /* Move to HI/LO */
4615 gen_HILO(ctx, op1, rs);
6af0bf9c 4616 break;
7a387fff
TS
4617 case OPC_PMON: /* Pmon entry point */
4618 gen_op_pmon(sa);
4619 break;
4620 case OPC_SYSCALL:
6af0bf9c 4621 generate_exception(ctx, EXCP_SYSCALL);
7a387fff 4622 ctx->bstate = BS_EXCP;
6af0bf9c 4623 break;
7a387fff 4624 case OPC_BREAK:
6af0bf9c
FB
4625 generate_exception(ctx, EXCP_BREAK);
4626 break;
7a387fff
TS
4627 case OPC_SPIM: /* SPIM ? */
4628 /* Implemented as RI exception for now. */
4629 MIPS_INVAL("spim (unofficial)");
4630 generate_exception(ctx, EXCP_RI);
6af0bf9c 4631 break;
7a387fff
TS
4632 case OPC_SYNC:
4633 /* Treat as a noop. */
6af0bf9c 4634 break;
4ad40f36 4635
7a387fff 4636 case OPC_MOVCI:
36d23958 4637 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 4638 save_cpu_state(ctx, 1);
36d23958
TS
4639 gen_op_cp1_enabled();
4640 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
4641 (ctx->opcode >> 16) & 1);
4642 } else {
e397ee33 4643 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 4644 }
4ad40f36
FB
4645 break;
4646
60aa19ab 4647#ifdef TARGET_MIPS64
7a387fff
TS
4648 /* MIPS64 specific opcodes */
4649 case OPC_DSLL:
4650 case OPC_DSRL ... OPC_DSRA:
4651 case OPC_DSLL32:
4652 case OPC_DSRL32 ... OPC_DSRA32:
4653 gen_arith_imm(ctx, op1, rd, rt, sa);
4654 break;
4655 case OPC_DSLLV:
4656 case OPC_DSRLV ... OPC_DSRAV:
4657 case OPC_DADD ... OPC_DSUBU:
4658 gen_arith(ctx, op1, rd, rs, rt);
4659 break;
4660 case OPC_DMULT ... OPC_DDIVU:
4661 gen_muldiv(ctx, op1, rs, rt);
4662 break;
6af0bf9c
FB
4663#endif
4664 default: /* Invalid */
4665 MIPS_INVAL("special");
4666 generate_exception(ctx, EXCP_RI);
4667 break;
4668 }
4669 break;
7a387fff
TS
4670 case OPC_SPECIAL2:
4671 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 4672 switch (op1) {
7a387fff
TS
4673 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
4674 case OPC_MSUB ... OPC_MSUBU:
4675 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 4676 break;
7a387fff
TS
4677 case OPC_MUL:
4678 gen_arith(ctx, op1, rd, rs, rt);
6af0bf9c 4679 break;
7a387fff
TS
4680 case OPC_CLZ ... OPC_CLO:
4681 gen_cl(ctx, op1, rd, rs);
6af0bf9c 4682 break;
7a387fff 4683 case OPC_SDBBP:
6af0bf9c
FB
4684 /* XXX: not clear which exception should be raised
4685 * when in debug mode...
4686 */
4687 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
4688 generate_exception(ctx, EXCP_DBp);
4689 } else {
4690 generate_exception(ctx, EXCP_DBp);
4691 }
4692 /* Treat as a noop */
4693 break;
60aa19ab 4694#ifdef TARGET_MIPS64
7a387fff
TS
4695 case OPC_DCLZ ... OPC_DCLO:
4696 gen_cl(ctx, op1, rd, rs);
4697 break;
4698#endif
6af0bf9c
FB
4699 default: /* Invalid */
4700 MIPS_INVAL("special2");
4701 generate_exception(ctx, EXCP_RI);
4702 break;
4703 }
4704 break;
7a387fff
TS
4705 case OPC_SPECIAL3:
4706 op1 = MASK_SPECIAL3(ctx->opcode);
6af0bf9c 4707 switch (op1) {
7a387fff
TS
4708 case OPC_EXT:
4709 case OPC_INS:
4710 gen_bitops(ctx, op1, rt, rs, sa, rd);
4711 break;
4712 case OPC_BSHFL:
4713 op2 = MASK_BSHFL(ctx->opcode);
4714 switch (op2) {
4715 case OPC_WSBH:
4716 GEN_LOAD_REG_TN(T1, rt);
4717 gen_op_wsbh();
4718 break;
4719 case OPC_SEB:
4720 GEN_LOAD_REG_TN(T1, rt);
4721 gen_op_seb();
4722 break;
4723 case OPC_SEH:
4724 GEN_LOAD_REG_TN(T1, rt);
4725 gen_op_seh();
4726 break;
4727 default: /* Invalid */
4728 MIPS_INVAL("bshfl");
4729 generate_exception(ctx, EXCP_RI);
4730 break;
4731 }
4732 GEN_STORE_TN_REG(rd, T0);
4733 break;
4734 case OPC_RDHWR:
4735 switch (rd) {
4736 case 0:
4737 gen_op_rdhwr_cpunum();
4738 break;
4739 case 1:
4740 gen_op_rdhwr_synci_step();
4741 break;
4742 case 2:
4743 gen_op_rdhwr_cc();
4744 break;
4745 case 3:
4746 gen_op_rdhwr_ccres();
4747 break;
6f5b89a0
TS
4748#if defined (CONFIG_USER_ONLY)
4749 case 29:
4750 gen_op_tls_value ();
4751 GEN_STORE_TN_REG(rt, T0);
4752 break;
4753#endif
7a387fff
TS
4754 default: /* Invalid */
4755 MIPS_INVAL("rdhwr");
4756 generate_exception(ctx, EXCP_RI);
4757 break;
4758 }
4759 GEN_STORE_TN_REG(rt, T0);
4760 break;
60aa19ab 4761#ifdef TARGET_MIPS64
7a387fff
TS
4762 case OPC_DEXTM ... OPC_DEXT:
4763 case OPC_DINSM ... OPC_DINS:
4764 gen_bitops(ctx, op1, rt, rs, sa, rd);
4765 break;
4766 case OPC_DBSHFL:
4767 op2 = MASK_DBSHFL(ctx->opcode);
4768 switch (op2) {
4769 case OPC_DSBH:
4770 GEN_LOAD_REG_TN(T1, rt);
4771 gen_op_dsbh();
4772 break;
4773 case OPC_DSHD:
4774 GEN_LOAD_REG_TN(T1, rt);
4775 gen_op_dshd();
4776 break;
4777 default: /* Invalid */
4778 MIPS_INVAL("dbshfl");
4779 generate_exception(ctx, EXCP_RI);
4780 break;
4781 }
4782 GEN_STORE_TN_REG(rd, T0);
4783#endif
4784 default: /* Invalid */
4785 MIPS_INVAL("special3");
4786 generate_exception(ctx, EXCP_RI);
4787 break;
4788 }
4789 break;
4790 case OPC_REGIMM:
4791 op1 = MASK_REGIMM(ctx->opcode);
4792 switch (op1) {
4793 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
4794 case OPC_BLTZAL ... OPC_BGEZALL:
4795 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
6af0bf9c 4796 return;
7a387fff
TS
4797 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
4798 case OPC_TNEI:
4799 gen_trap(ctx, op1, rs, -1, imm);
4800 break;
4801 case OPC_SYNCI:
24c7b0e3 4802 /* treat as noop */
6af0bf9c
FB
4803 break;
4804 default: /* Invalid */
4805 MIPS_INVAL("REGIMM");
4806 generate_exception(ctx, EXCP_RI);
4807 break;
4808 }
4809 break;
7a387fff 4810 case OPC_CP0:
24c7b0e3 4811 gen_op_cp0_enabled();
7a387fff 4812 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 4813 switch (op1) {
7a387fff
TS
4814 case OPC_MFC0:
4815 case OPC_MTC0:
60aa19ab 4816#ifdef TARGET_MIPS64
7a387fff
TS
4817 case OPC_DMFC0:
4818 case OPC_DMTC0:
4819#endif
4820 gen_cp0(ctx, op1, rt, rd);
4821 break;
4822 case OPC_C0_FIRST ... OPC_C0_LAST:
4823 gen_cp0(ctx, MASK_C0(ctx->opcode), rt, rd);
4824 break;
4825 case OPC_MFMC0:
4826 op2 = MASK_MFMC0(ctx->opcode);
4827 switch (op2) {
4828 case OPC_DI:
4829 gen_op_di();
4830 /* Stop translation as we may have switched the execution mode */
4831 ctx->bstate = BS_STOP;
4832 break;
4833 case OPC_EI:
4834 gen_op_ei();
4835 /* Stop translation as we may have switched the execution mode */
4836 ctx->bstate = BS_STOP;
4837 break;
4838 default: /* Invalid */
4839 MIPS_INVAL("MFMC0");
4840 generate_exception(ctx, EXCP_RI);
4841 break;
4842 }
4843 GEN_STORE_TN_REG(rt, T0);
6af0bf9c 4844 break;
7a387fff
TS
4845 case OPC_RDPGPR:
4846 case OPC_WRPGPR:
38121543
TS
4847 if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) {
4848 /* Shadow registers not implemented. */
4849 GEN_LOAD_REG_TN(T0, rt);
4850 GEN_STORE_TN_REG(rd, T0);
4851 } else
4852 generate_exception(ctx, EXCP_RI);
4853 break;
6af0bf9c 4854 default:
7a387fff 4855 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
4856 break;
4857 }
4858 break;
7a387fff
TS
4859 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
4860 gen_arith_imm(ctx, op, rt, rs, imm);
4861 break;
4862 case OPC_J ... OPC_JAL: /* Jump */
4863 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
4864 gen_compute_branch(ctx, op, rs, rt, offset);
4865 return;
4866 case OPC_BEQ ... OPC_BGTZ: /* Branch */
4867 case OPC_BEQL ... OPC_BGTZL:
4868 gen_compute_branch(ctx, op, rs, rt, imm << 2);
4869 return;
4870 case OPC_LB ... OPC_LWR: /* Load and stores */
4871 case OPC_SB ... OPC_SW:
4872 case OPC_SWR:
4873 case OPC_LL:
4874 case OPC_SC:
4875 gen_ldst(ctx, op, rt, rs, imm);
4876 break;
4877 case OPC_CACHE:
4878 /* Treat as a noop */
4879 break;
4880 case OPC_PREF:
6af0bf9c
FB
4881 /* Treat as a noop */
4882 break;
4ad40f36
FB
4883
4884 /* Floating point. */
7a387fff
TS
4885 case OPC_LWC1:
4886 case OPC_LDC1:
4887 case OPC_SWC1:
4888 case OPC_SDC1:
36d23958
TS
4889 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4890 save_cpu_state(ctx, 1);
4891 gen_op_cp1_enabled();
4892 gen_flt_ldst(ctx, op, rt, rs, imm);
4893 } else {
4894 generate_exception_err(ctx, EXCP_CpU, 1);
4895 }
6ea83fed
FB
4896 break;
4897
7a387fff 4898 case OPC_CP1:
36d23958
TS
4899 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4900 save_cpu_state(ctx, 1);
4901 gen_op_cp1_enabled();
4902 op1 = MASK_CP1(ctx->opcode);
4903 switch (op1) {
4904 case OPC_MFC1:
4905 case OPC_CFC1:
4906 case OPC_MTC1:
4907 case OPC_CTC1:
60aa19ab 4908#ifdef TARGET_MIPS64
36d23958
TS
4909 case OPC_DMFC1:
4910 case OPC_DMTC1:
9c2149c8 4911#endif
36d23958
TS
4912 gen_cp1(ctx, op1, rt, rd);
4913 break;
4914 case OPC_BC1:
4915 gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
4916 return;
4917 case OPC_S_FMT:
4918 case OPC_D_FMT:
4919 case OPC_W_FMT:
4920 case OPC_L_FMT:
4921 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
4922 break;
4923 default:
e397ee33 4924 generate_exception (ctx, EXCP_RI);
36d23958
TS
4925 break;
4926 }
4927 } else {
4928 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 4929 }
4ad40f36
FB
4930 break;
4931
4932 /* COP2. */
7a387fff
TS
4933 case OPC_LWC2:
4934 case OPC_LDC2:
4935 case OPC_SWC2:
4936 case OPC_SDC2:
4937 case OPC_CP2:
4938 /* COP2: Not implemented. */
4ad40f36
FB
4939 generate_exception_err(ctx, EXCP_CpU, 2);
4940 break;
4941
7a387fff 4942 case OPC_CP3:
36d23958 4943 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 4944 save_cpu_state(ctx, 1);
36d23958
TS
4945 gen_op_cp1_enabled();
4946 op1 = MASK_CP3(ctx->opcode);
4947 switch (op1) {
4948 /* Not implemented */
4949 default:
e397ee33 4950 generate_exception (ctx, EXCP_RI);
36d23958
TS
4951 break;
4952 }
4953 } else {
e397ee33 4954 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 4955 }
4ad40f36
FB
4956 break;
4957
60aa19ab 4958#ifdef TARGET_MIPS64
7a387fff
TS
4959 /* MIPS64 opcodes */
4960 case OPC_LWU:
4961 case OPC_LDL ... OPC_LDR:
4962 case OPC_SDL ... OPC_SDR:
4963 case OPC_LLD:
4964 case OPC_LD:
4965 case OPC_SCD:
4966 case OPC_SD:
4967 gen_ldst(ctx, op, rt, rs, imm);
4968 break;
4969 case OPC_DADDI ... OPC_DADDIU:
4970 gen_arith_imm(ctx, op, rt, rs, imm);
4971 break;
6af0bf9c 4972#endif
7a387fff
TS
4973#ifdef MIPS_HAS_MIPS16
4974 case OPC_JALX:
4975 /* MIPS16: Not implemented. */
4976#endif
4977#ifdef MIPS_HAS_MDMX
4978 case OPC_MDMX:
4979 /* MDMX: Not implemented. */
6af0bf9c 4980#endif
6af0bf9c
FB
4981 default: /* Invalid */
4982 MIPS_INVAL("");
4983 generate_exception(ctx, EXCP_RI);
4984 break;
4985 }
4ad40f36 4986 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6af0bf9c
FB
4987 int hflags = ctx->hflags;
4988 /* Branches completion */
4ad40f36 4989 ctx->hflags &= ~MIPS_HFLAG_BMASK;
6af0bf9c
FB
4990 ctx->bstate = BS_BRANCH;
4991 save_cpu_state(ctx, 0);
4992 switch (hflags & MIPS_HFLAG_BMASK) {
4993 case MIPS_HFLAG_B:
4994 /* unconditional branch */
4995 MIPS_DEBUG("unconditional branch");
6e256c93 4996 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
4997 break;
4998 case MIPS_HFLAG_BL:
4999 /* blikely taken case */
5000 MIPS_DEBUG("blikely branch taken");
6e256c93 5001 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
5002 break;
5003 case MIPS_HFLAG_BC:
5004 /* Conditional branch */
5005 MIPS_DEBUG("conditional branch");
c53be334
FB
5006 {
5007 int l1;
5008 l1 = gen_new_label();
5009 gen_op_jnz_T2(l1);
6e256c93 5010 gen_goto_tb(ctx, 1, ctx->pc + 4);
eeef26cd
FB
5011 gen_set_label(l1);
5012 gen_goto_tb(ctx, 0, ctx->btarget);
c53be334 5013 }
6af0bf9c
FB
5014 break;
5015 case MIPS_HFLAG_BR:
5016 /* unconditional branch to register */
5017 MIPS_DEBUG("branch to register");
5018 gen_op_breg();
5019 break;
5020 default:
5021 MIPS_DEBUG("unknown branch");
5022 break;
5023 }
5024 }
5025}
5026
820e00f2
TS
5027static inline int
5028gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5029 int search_pc)
6af0bf9c
FB
5030{
5031 DisasContext ctx, *ctxp = &ctx;
5032 target_ulong pc_start;
5033 uint16_t *gen_opc_end;
5034 int j, lj = -1;
5035
4ad40f36 5036 if (search_pc && loglevel)
6ea83fed 5037 fprintf (logfile, "search pc %d\n", search_pc);
4ad40f36 5038
6af0bf9c
FB
5039 pc_start = tb->pc;
5040 gen_opc_ptr = gen_opc_buf;
5041 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
5042 gen_opparam_ptr = gen_opparam_buf;
c53be334 5043 nb_gen_labels = 0;
6af0bf9c 5044 ctx.pc = pc_start;
4ad40f36 5045 ctx.saved_pc = -1;
6af0bf9c
FB
5046 ctx.tb = tb;
5047 ctx.bstate = BS_NONE;
4ad40f36
FB
5048 /* Restore delay slot state from the tb context. */
5049 ctx.hflags = tb->flags;
6af0bf9c
FB
5050 ctx.saved_hflags = ctx.hflags;
5051 if (ctx.hflags & MIPS_HFLAG_BR) {
5052 gen_op_restore_breg_target();
5053 } else if (ctx.hflags & MIPS_HFLAG_B) {
5054 ctx.btarget = env->btarget;
5055 } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
5056 /* If we are in the delay slot of a conditional branch,
5057 * restore the branch condition from env->bcond to T2
5058 */
5059 ctx.btarget = env->btarget;
5060 gen_op_restore_bcond();
5061 }
5062#if defined(CONFIG_USER_ONLY)
5063 ctx.mem_idx = 0;
5064#else
3d9fb9fe 5065 ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
6af0bf9c
FB
5066#endif
5067 ctx.CP0_Status = env->CP0_Status;
5068#ifdef DEBUG_DISAS
5069 if (loglevel & CPU_LOG_TB_CPU) {
5070 fprintf(logfile, "------------------------------------------------\n");
4ad40f36 5071 /* FIXME: This may print out stale hflags from env... */
6af0bf9c
FB
5072 cpu_dump_state(env, logfile, fprintf, 0);
5073 }
5074#endif
5075#if defined MIPS_DEBUG_DISAS
5076 if (loglevel & CPU_LOG_TB_IN_ASM)
4ad40f36
FB
5077 fprintf(logfile, "\ntb %p super %d cond %04x\n",
5078 tb, ctx.mem_idx, ctx.hflags);
6af0bf9c
FB
5079#endif
5080 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
4ad40f36
FB
5081 if (env->nb_breakpoints > 0) {
5082 for(j = 0; j < env->nb_breakpoints; j++) {
5083 if (env->breakpoints[j] == ctx.pc) {
5084 save_cpu_state(ctxp, 1);
5085 ctx.bstate = BS_BRANCH;
5086 gen_op_debug();
5087 goto done_generating;
5088 }
5089 }
5090 }
5091
6af0bf9c
FB
5092 if (search_pc) {
5093 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
5094 if (lj < j) {
5095 lj++;
5096 while (lj < j)
5097 gen_opc_instr_start[lj++] = 0;
6af0bf9c 5098 }
4ad40f36
FB
5099 gen_opc_pc[lj] = ctx.pc;
5100 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
5101 gen_opc_instr_start[lj] = 1;
6af0bf9c
FB
5102 }
5103 ctx.opcode = ldl_code(ctx.pc);
36d23958 5104 decode_opc(env, &ctx);
6af0bf9c 5105 ctx.pc += 4;
4ad40f36
FB
5106
5107 if (env->singlestep_enabled)
5108 break;
5109
6af0bf9c
FB
5110 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
5111 break;
4ad40f36 5112
6af0bf9c
FB
5113#if defined (MIPS_SINGLE_STEP)
5114 break;
5115#endif
5116 }
4ad40f36
FB
5117 if (env->singlestep_enabled) {
5118 save_cpu_state(ctxp, ctx.bstate == BS_NONE);
5119 gen_op_debug();
5120 goto done_generating;
5121 }
5122 else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
6af0bf9c 5123 save_cpu_state(ctxp, 0);
6e256c93 5124 gen_goto_tb(&ctx, 0, ctx.pc);
6af0bf9c
FB
5125 }
5126 gen_op_reset_T0();
5127 /* Generate the return instruction */
5128 gen_op_exit_tb();
4ad40f36 5129done_generating:
6af0bf9c
FB
5130 *gen_opc_ptr = INDEX_op_end;
5131 if (search_pc) {
5132 j = gen_opc_ptr - gen_opc_buf;
5133 lj++;
5134 while (lj <= j)
5135 gen_opc_instr_start[lj++] = 0;
5136 tb->size = 0;
5137 } else {
5138 tb->size = ctx.pc - pc_start;
5139 }
5140#ifdef DEBUG_DISAS
5141#if defined MIPS_DEBUG_DISAS
5142 if (loglevel & CPU_LOG_TB_IN_ASM)
5143 fprintf(logfile, "\n");
5144#endif
5145 if (loglevel & CPU_LOG_TB_IN_ASM) {
5146 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6ea83fed 5147 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
6af0bf9c
FB
5148 fprintf(logfile, "\n");
5149 }
5150 if (loglevel & CPU_LOG_TB_OP) {
5151 fprintf(logfile, "OP:\n");
5152 dump_ops(gen_opc_buf, gen_opparam_buf);
5153 fprintf(logfile, "\n");
5154 }
5155 if (loglevel & CPU_LOG_TB_CPU) {
5156 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
5157 }
5158#endif
5159
5160 return 0;
5161}
5162
5163int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
5164{
5165 return gen_intermediate_code_internal(env, tb, 0);
5166}
5167
5168int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
5169{
5170 return gen_intermediate_code_internal(env, tb, 1);
5171}
5172
6ea83fed
FB
5173void fpu_dump_state(CPUState *env, FILE *f,
5174 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
5175 int flags)
5176{
5177 int i;
5178
5179# define printfpr(fp) do { \
5180 fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
5181 (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
5182 } while(0)
5183
5184 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d\n",
5185 env->fcr0, env->fcr31,
7a387fff 5186 (env->CP0_Status & (1 << CP0St_FR)) != 0);
6ea83fed
FB
5187 fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
5188 fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
5189 fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
7a387fff
TS
5190 for(i = 0; i < 32; i += 2) {
5191 fpu_fprintf(f, "%s: ", fregnames[i]);
6ea83fed
FB
5192 printfpr(FPR(env, i));
5193 }
5194
5195#undef printfpr
5196}
5197
7a387fff 5198void dump_fpu (CPUState *env)
6ea83fed
FB
5199{
5200 if (loglevel) {
3594c774 5201 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
5202 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5203 fpu_dump_state(env, logfile, fprintf, 0);
5204 }
5205}
6ea83fed 5206
60aa19ab 5207#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
5208/* Debug help: The architecture requires 32bit code to maintain proper
5209 sign-extened values on 64bit machines. */
5210
5211#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
5212
5213void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
5214 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5215 int flags)
5216{
5217 int i;
5218
5219 if (!SIGN_EXT_P(env->PC))
3594c774 5220 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC);
c570fd16 5221 if (!SIGN_EXT_P(env->HI))
3594c774 5222 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI);
c570fd16 5223 if (!SIGN_EXT_P(env->LO))
3594c774 5224 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO);
c570fd16 5225 if (!SIGN_EXT_P(env->btarget))
3594c774 5226 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
5227
5228 for (i = 0; i < 32; i++) {
5229 if (!SIGN_EXT_P(env->gpr[i]))
3594c774 5230 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i]);
c570fd16
TS
5231 }
5232
5233 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 5234 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
c570fd16 5235 if (!SIGN_EXT_P(env->CP0_LLAddr))
3594c774 5236 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
c570fd16
TS
5237}
5238#endif
5239
6af0bf9c
FB
5240void cpu_dump_state (CPUState *env, FILE *f,
5241 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5242 int flags)
5243{
568b600d 5244 uint32_t c0_status;
6af0bf9c
FB
5245 int i;
5246
3594c774 5247 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
5248 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5249 for (i = 0; i < 32; i++) {
5250 if ((i & 3) == 0)
5251 cpu_fprintf(f, "GPR%02d:", i);
3594c774 5252 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i]);
6af0bf9c
FB
5253 if ((i & 3) == 3)
5254 cpu_fprintf(f, "\n");
5255 }
568b600d
FB
5256
5257 c0_status = env->CP0_Status;
568b600d 5258
3594c774 5259 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
568b600d 5260 c0_status, env->CP0_Cause, env->CP0_EPC);
3594c774 5261 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
6af0bf9c 5262 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
7a387fff
TS
5263 if (c0_status & (1 << CP0St_CU1))
5264 fpu_dump_state(env, f, cpu_fprintf, flags);
60aa19ab 5265#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
5266 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
5267#endif
6af0bf9c
FB
5268}
5269
5270CPUMIPSState *cpu_mips_init (void)
5271{
5272 CPUMIPSState *env;
5273
6af0bf9c
FB
5274 env = qemu_mallocz(sizeof(CPUMIPSState));
5275 if (!env)
5276 return NULL;
173d6cfe 5277 cpu_exec_init(env);
6ae81775
TS
5278 cpu_reset(env);
5279 return env;
5280}
5281
5282void cpu_reset (CPUMIPSState *env)
5283{
5284 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
5285
6af0bf9c 5286 tlb_flush(env, 1);
6ae81775 5287
6af0bf9c 5288 /* Minimal init */
ca7c2b1b 5289#if !defined(CONFIG_USER_ONLY)
aa328add
TS
5290 if (env->hflags & MIPS_HFLAG_BMASK) {
5291 /* If the exception was raised from a delay slot,
5292 * come back to the jump. */
5293 env->CP0_ErrorEPC = env->PC - 4;
5294 env->hflags &= ~MIPS_HFLAG_BMASK;
5295 } else {
5296 env->CP0_ErrorEPC = env->PC;
5297 }
24c7b0e3 5298 env->hflags = 0;
5dc4b744 5299 env->PC = (int32_t)0xBFC00000;
6af0bf9c 5300#if defined (MIPS_USES_R4K_TLB)
9c2149c8 5301 env->CP0_Random = MIPS_TLB_NB - 1;
814b9a47 5302 env->tlb_in_use = MIPS_TLB_NB;
6af0bf9c
FB
5303#endif
5304 env->CP0_Wired = 0;
7a387fff 5305 /* SMP not implemented */
b29a0341 5306 env->CP0_EBase = 0x80000000;
aa328add 5307 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
6af0bf9c 5308 env->CP0_WatchLo = 0;
6af0bf9c
FB
5309 /* Count register increments in debug mode, EJTAG version 1 */
5310 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
ca7c2b1b 5311#endif
6af0bf9c 5312 env->exception_index = EXCP_NONE;
eeef26cd
FB
5313#if defined(CONFIG_USER_ONLY)
5314 env->hflags |= MIPS_HFLAG_UM;
ca7c2b1b 5315 env->user_mode_only = 1;
6ea83fed 5316#endif
7a387fff
TS
5317 /* XXX some guesswork here, values are CPU specific */
5318 env->SYNCI_Step = 16;
5319 env->CCRes = 2;
6af0bf9c 5320}
33d68b5f
TS
5321
5322#include "translate_init.c"