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