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