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