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