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