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