Statistics
| Branch: | Revision:

root / target-mips / translate.c @ edcdd562

History | View | Annotate | Download (360.9 kB)

1 6af0bf9c bellard
/*
2 6af0bf9c bellard
 *  MIPS32 emulation for qemu: main translation routines.
3 5fafdf24 ths
 *
4 6af0bf9c bellard
 *  Copyright (c) 2004-2005 Jocelyn Mayer
5 6ea83fed bellard
 *  Copyright (c) 2006 Marius Groeger (FPU operations)
6 bb8a53ad ths
 *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 3c824109 Nathan Froyd
 *  Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 6af0bf9c bellard
 *
9 6af0bf9c bellard
 * This library is free software; you can redistribute it and/or
10 6af0bf9c bellard
 * modify it under the terms of the GNU Lesser General Public
11 6af0bf9c bellard
 * License as published by the Free Software Foundation; either
12 6af0bf9c bellard
 * version 2 of the License, or (at your option) any later version.
13 6af0bf9c bellard
 *
14 6af0bf9c bellard
 * This library is distributed in the hope that it will be useful,
15 6af0bf9c bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 6af0bf9c bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 6af0bf9c bellard
 * Lesser General Public License for more details.
18 6af0bf9c bellard
 *
19 6af0bf9c bellard
 * You should have received a copy of the GNU Lesser General Public
20 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 6af0bf9c bellard
 */
22 6af0bf9c bellard
23 6af0bf9c bellard
#include <stdarg.h>
24 6af0bf9c bellard
#include <stdlib.h>
25 6af0bf9c bellard
#include <stdio.h>
26 6af0bf9c bellard
#include <string.h>
27 6af0bf9c bellard
#include <inttypes.h>
28 6af0bf9c bellard
29 6af0bf9c bellard
#include "cpu.h"
30 6af0bf9c bellard
#include "exec-all.h"
31 6af0bf9c bellard
#include "disas.h"
32 57fec1fe bellard
#include "tcg-op.h"
33 ca10f867 aurel32
#include "qemu-common.h"
34 6af0bf9c bellard
35 a7812ae4 pbrook
#include "helper.h"
36 a7812ae4 pbrook
#define GEN_HELPER 1
37 a7812ae4 pbrook
#include "helper.h"
38 a7812ae4 pbrook
39 eeef26cd bellard
//#define MIPS_DEBUG_DISAS
40 c570fd16 ths
//#define MIPS_DEBUG_SIGN_EXTENSIONS
41 6af0bf9c bellard
42 7a387fff ths
/* MIPS major opcodes */
43 7a387fff ths
#define MASK_OP_MAJOR(op)  (op & (0x3F << 26))
44 e37e863f bellard
45 e37e863f bellard
enum {
46 e37e863f bellard
    /* indirect opcode tables */
47 7a387fff ths
    OPC_SPECIAL  = (0x00 << 26),
48 7a387fff ths
    OPC_REGIMM   = (0x01 << 26),
49 7a387fff ths
    OPC_CP0      = (0x10 << 26),
50 7a387fff ths
    OPC_CP1      = (0x11 << 26),
51 7a387fff ths
    OPC_CP2      = (0x12 << 26),
52 7a387fff ths
    OPC_CP3      = (0x13 << 26),
53 7a387fff ths
    OPC_SPECIAL2 = (0x1C << 26),
54 7a387fff ths
    OPC_SPECIAL3 = (0x1F << 26),
55 e37e863f bellard
    /* arithmetic with immediate */
56 7a387fff ths
    OPC_ADDI     = (0x08 << 26),
57 7a387fff ths
    OPC_ADDIU    = (0x09 << 26),
58 7a387fff ths
    OPC_SLTI     = (0x0A << 26),
59 7a387fff ths
    OPC_SLTIU    = (0x0B << 26),
60 324d9e32 aurel32
    /* logic with immediate */
61 7a387fff ths
    OPC_ANDI     = (0x0C << 26),
62 7a387fff ths
    OPC_ORI      = (0x0D << 26),
63 7a387fff ths
    OPC_XORI     = (0x0E << 26),
64 7a387fff ths
    OPC_LUI      = (0x0F << 26),
65 324d9e32 aurel32
    /* arithmetic with immediate */
66 7a387fff ths
    OPC_DADDI    = (0x18 << 26),
67 7a387fff ths
    OPC_DADDIU   = (0x19 << 26),
68 e37e863f bellard
    /* Jump and branches */
69 7a387fff ths
    OPC_J        = (0x02 << 26),
70 7a387fff ths
    OPC_JAL      = (0x03 << 26),
71 620e48f6 Nathan Froyd
    OPC_JALS     = OPC_JAL | 0x5,
72 7a387fff ths
    OPC_BEQ      = (0x04 << 26),  /* Unconditional if rs = rt = 0 (B) */
73 7a387fff ths
    OPC_BEQL     = (0x14 << 26),
74 7a387fff ths
    OPC_BNE      = (0x05 << 26),
75 7a387fff ths
    OPC_BNEL     = (0x15 << 26),
76 7a387fff ths
    OPC_BLEZ     = (0x06 << 26),
77 7a387fff ths
    OPC_BLEZL    = (0x16 << 26),
78 7a387fff ths
    OPC_BGTZ     = (0x07 << 26),
79 7a387fff ths
    OPC_BGTZL    = (0x17 << 26),
80 7a387fff ths
    OPC_JALX     = (0x1D << 26),  /* MIPS 16 only */
81 620e48f6 Nathan Froyd
    OPC_JALXS    = OPC_JALX | 0x5,
82 e37e863f bellard
    /* Load and stores */
83 7a387fff ths
    OPC_LDL      = (0x1A << 26),
84 7a387fff ths
    OPC_LDR      = (0x1B << 26),
85 7a387fff ths
    OPC_LB       = (0x20 << 26),
86 7a387fff ths
    OPC_LH       = (0x21 << 26),
87 7a387fff ths
    OPC_LWL      = (0x22 << 26),
88 7a387fff ths
    OPC_LW       = (0x23 << 26),
89 364d4831 Nathan Froyd
    OPC_LWPC     = OPC_LW | 0x5,
90 7a387fff ths
    OPC_LBU      = (0x24 << 26),
91 7a387fff ths
    OPC_LHU      = (0x25 << 26),
92 7a387fff ths
    OPC_LWR      = (0x26 << 26),
93 7a387fff ths
    OPC_LWU      = (0x27 << 26),
94 7a387fff ths
    OPC_SB       = (0x28 << 26),
95 7a387fff ths
    OPC_SH       = (0x29 << 26),
96 7a387fff ths
    OPC_SWL      = (0x2A << 26),
97 7a387fff ths
    OPC_SW       = (0x2B << 26),
98 7a387fff ths
    OPC_SDL      = (0x2C << 26),
99 7a387fff ths
    OPC_SDR      = (0x2D << 26),
100 7a387fff ths
    OPC_SWR      = (0x2E << 26),
101 7a387fff ths
    OPC_LL       = (0x30 << 26),
102 7a387fff ths
    OPC_LLD      = (0x34 << 26),
103 7a387fff ths
    OPC_LD       = (0x37 << 26),
104 364d4831 Nathan Froyd
    OPC_LDPC     = OPC_LD | 0x5,
105 7a387fff ths
    OPC_SC       = (0x38 << 26),
106 7a387fff ths
    OPC_SCD      = (0x3C << 26),
107 7a387fff ths
    OPC_SD       = (0x3F << 26),
108 e37e863f bellard
    /* Floating point load/store */
109 7a387fff ths
    OPC_LWC1     = (0x31 << 26),
110 7a387fff ths
    OPC_LWC2     = (0x32 << 26),
111 7a387fff ths
    OPC_LDC1     = (0x35 << 26),
112 7a387fff ths
    OPC_LDC2     = (0x36 << 26),
113 7a387fff ths
    OPC_SWC1     = (0x39 << 26),
114 7a387fff ths
    OPC_SWC2     = (0x3A << 26),
115 7a387fff ths
    OPC_SDC1     = (0x3D << 26),
116 7a387fff ths
    OPC_SDC2     = (0x3E << 26),
117 7a387fff ths
    /* MDMX ASE specific */
118 7a387fff ths
    OPC_MDMX     = (0x1E << 26),
119 e37e863f bellard
    /* Cache and prefetch */
120 7a387fff ths
    OPC_CACHE    = (0x2F << 26),
121 7a387fff ths
    OPC_PREF     = (0x33 << 26),
122 7a387fff ths
    /* Reserved major opcode */
123 7a387fff ths
    OPC_MAJOR3B_RESERVED = (0x3B << 26),
124 e37e863f bellard
};
125 e37e863f bellard
126 e37e863f bellard
/* MIPS special opcodes */
127 7a387fff ths
#define MASK_SPECIAL(op)   MASK_OP_MAJOR(op) | (op & 0x3F)
128 7a387fff ths
129 e37e863f bellard
enum {
130 e37e863f bellard
    /* Shifts */
131 7a387fff ths
    OPC_SLL      = 0x00 | OPC_SPECIAL,
132 e37e863f bellard
    /* NOP is SLL r0, r0, 0   */
133 e37e863f bellard
    /* SSNOP is SLL r0, r0, 1 */
134 7a387fff ths
    /* EHB is SLL r0, r0, 3 */
135 7a387fff ths
    OPC_SRL      = 0x02 | OPC_SPECIAL, /* also ROTR */
136 ea63e2c3 Nathan Froyd
    OPC_ROTR     = OPC_SRL | (1 << 21),
137 7a387fff ths
    OPC_SRA      = 0x03 | OPC_SPECIAL,
138 7a387fff ths
    OPC_SLLV     = 0x04 | OPC_SPECIAL,
139 e189e748 ths
    OPC_SRLV     = 0x06 | OPC_SPECIAL, /* also ROTRV */
140 ea63e2c3 Nathan Froyd
    OPC_ROTRV    = OPC_SRLV | (1 << 6),
141 7a387fff ths
    OPC_SRAV     = 0x07 | OPC_SPECIAL,
142 7a387fff ths
    OPC_DSLLV    = 0x14 | OPC_SPECIAL,
143 7a387fff ths
    OPC_DSRLV    = 0x16 | OPC_SPECIAL, /* also DROTRV */
144 ea63e2c3 Nathan Froyd
    OPC_DROTRV   = OPC_DSRLV | (1 << 6),
145 7a387fff ths
    OPC_DSRAV    = 0x17 | OPC_SPECIAL,
146 7a387fff ths
    OPC_DSLL     = 0x38 | OPC_SPECIAL,
147 7a387fff ths
    OPC_DSRL     = 0x3A | OPC_SPECIAL, /* also DROTR */
148 ea63e2c3 Nathan Froyd
    OPC_DROTR    = OPC_DSRL | (1 << 21),
149 7a387fff ths
    OPC_DSRA     = 0x3B | OPC_SPECIAL,
150 7a387fff ths
    OPC_DSLL32   = 0x3C | OPC_SPECIAL,
151 7a387fff ths
    OPC_DSRL32   = 0x3E | OPC_SPECIAL, /* also DROTR32 */
152 ea63e2c3 Nathan Froyd
    OPC_DROTR32  = OPC_DSRL32 | (1 << 21),
153 7a387fff ths
    OPC_DSRA32   = 0x3F | OPC_SPECIAL,
154 e37e863f bellard
    /* Multiplication / division */
155 7a387fff ths
    OPC_MULT     = 0x18 | OPC_SPECIAL,
156 7a387fff ths
    OPC_MULTU    = 0x19 | OPC_SPECIAL,
157 7a387fff ths
    OPC_DIV      = 0x1A | OPC_SPECIAL,
158 7a387fff ths
    OPC_DIVU     = 0x1B | OPC_SPECIAL,
159 7a387fff ths
    OPC_DMULT    = 0x1C | OPC_SPECIAL,
160 7a387fff ths
    OPC_DMULTU   = 0x1D | OPC_SPECIAL,
161 7a387fff ths
    OPC_DDIV     = 0x1E | OPC_SPECIAL,
162 7a387fff ths
    OPC_DDIVU    = 0x1F | OPC_SPECIAL,
163 e37e863f bellard
    /* 2 registers arithmetic / logic */
164 7a387fff ths
    OPC_ADD      = 0x20 | OPC_SPECIAL,
165 7a387fff ths
    OPC_ADDU     = 0x21 | OPC_SPECIAL,
166 7a387fff ths
    OPC_SUB      = 0x22 | OPC_SPECIAL,
167 7a387fff ths
    OPC_SUBU     = 0x23 | OPC_SPECIAL,
168 7a387fff ths
    OPC_AND      = 0x24 | OPC_SPECIAL,
169 7a387fff ths
    OPC_OR       = 0x25 | OPC_SPECIAL,
170 7a387fff ths
    OPC_XOR      = 0x26 | OPC_SPECIAL,
171 7a387fff ths
    OPC_NOR      = 0x27 | OPC_SPECIAL,
172 7a387fff ths
    OPC_SLT      = 0x2A | OPC_SPECIAL,
173 7a387fff ths
    OPC_SLTU     = 0x2B | OPC_SPECIAL,
174 7a387fff ths
    OPC_DADD     = 0x2C | OPC_SPECIAL,
175 7a387fff ths
    OPC_DADDU    = 0x2D | OPC_SPECIAL,
176 7a387fff ths
    OPC_DSUB     = 0x2E | OPC_SPECIAL,
177 7a387fff ths
    OPC_DSUBU    = 0x2F | OPC_SPECIAL,
178 e37e863f bellard
    /* Jumps */
179 7a387fff ths
    OPC_JR       = 0x08 | OPC_SPECIAL, /* Also JR.HB */
180 7a387fff ths
    OPC_JALR     = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
181 364d4831 Nathan Froyd
    OPC_JALRC    = OPC_JALR | (0x5 << 6),
182 620e48f6 Nathan Froyd
    OPC_JALRS    = 0x10 | OPC_SPECIAL | (0x5 << 6),
183 e37e863f bellard
    /* Traps */
184 7a387fff ths
    OPC_TGE      = 0x30 | OPC_SPECIAL,
185 7a387fff ths
    OPC_TGEU     = 0x31 | OPC_SPECIAL,
186 7a387fff ths
    OPC_TLT      = 0x32 | OPC_SPECIAL,
187 7a387fff ths
    OPC_TLTU     = 0x33 | OPC_SPECIAL,
188 7a387fff ths
    OPC_TEQ      = 0x34 | OPC_SPECIAL,
189 7a387fff ths
    OPC_TNE      = 0x36 | OPC_SPECIAL,
190 e37e863f bellard
    /* HI / LO registers load & stores */
191 7a387fff ths
    OPC_MFHI     = 0x10 | OPC_SPECIAL,
192 7a387fff ths
    OPC_MTHI     = 0x11 | OPC_SPECIAL,
193 7a387fff ths
    OPC_MFLO     = 0x12 | OPC_SPECIAL,
194 7a387fff ths
    OPC_MTLO     = 0x13 | OPC_SPECIAL,
195 e37e863f bellard
    /* Conditional moves */
196 7a387fff ths
    OPC_MOVZ     = 0x0A | OPC_SPECIAL,
197 7a387fff ths
    OPC_MOVN     = 0x0B | OPC_SPECIAL,
198 e37e863f bellard
199 7a387fff ths
    OPC_MOVCI    = 0x01 | OPC_SPECIAL,
200 e37e863f bellard
201 e37e863f bellard
    /* Special */
202 a0d700e4 Stefan Weil
    OPC_PMON     = 0x05 | OPC_SPECIAL, /* unofficial */
203 7a387fff ths
    OPC_SYSCALL  = 0x0C | OPC_SPECIAL,
204 7a387fff ths
    OPC_BREAK    = 0x0D | OPC_SPECIAL,
205 a0d700e4 Stefan Weil
    OPC_SPIM     = 0x0E | OPC_SPECIAL, /* unofficial */
206 7a387fff ths
    OPC_SYNC     = 0x0F | OPC_SPECIAL,
207 7a387fff ths
208 7a387fff ths
    OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
209 7a387fff ths
    OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
210 7a387fff ths
    OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
211 7a387fff ths
    OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
212 7a387fff ths
    OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
213 7a387fff ths
    OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
214 7a387fff ths
    OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
215 7a387fff ths
};
216 7a387fff ths
217 e9c71dd1 ths
/* Multiplication variants of the vr54xx. */
218 e9c71dd1 ths
#define MASK_MUL_VR54XX(op)   MASK_SPECIAL(op) | (op & (0x1F << 6))
219 e9c71dd1 ths
220 e9c71dd1 ths
enum {
221 e9c71dd1 ths
    OPC_VR54XX_MULS    = (0x03 << 6) | OPC_MULT,
222 e9c71dd1 ths
    OPC_VR54XX_MULSU   = (0x03 << 6) | OPC_MULTU,
223 e9c71dd1 ths
    OPC_VR54XX_MACC    = (0x05 << 6) | OPC_MULT,
224 e9c71dd1 ths
    OPC_VR54XX_MACCU   = (0x05 << 6) | OPC_MULTU,
225 e9c71dd1 ths
    OPC_VR54XX_MSAC    = (0x07 << 6) | OPC_MULT,
226 e9c71dd1 ths
    OPC_VR54XX_MSACU   = (0x07 << 6) | OPC_MULTU,
227 e9c71dd1 ths
    OPC_VR54XX_MULHI   = (0x09 << 6) | OPC_MULT,
228 e9c71dd1 ths
    OPC_VR54XX_MULHIU  = (0x09 << 6) | OPC_MULTU,
229 e9c71dd1 ths
    OPC_VR54XX_MULSHI  = (0x0B << 6) | OPC_MULT,
230 e9c71dd1 ths
    OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
231 e9c71dd1 ths
    OPC_VR54XX_MACCHI  = (0x0D << 6) | OPC_MULT,
232 e9c71dd1 ths
    OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
233 e9c71dd1 ths
    OPC_VR54XX_MSACHI  = (0x0F << 6) | OPC_MULT,
234 e9c71dd1 ths
    OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
235 e9c71dd1 ths
};
236 e9c71dd1 ths
237 7a387fff ths
/* REGIMM (rt field) opcodes */
238 7a387fff ths
#define MASK_REGIMM(op)    MASK_OP_MAJOR(op) | (op & (0x1F << 16))
239 7a387fff ths
240 7a387fff ths
enum {
241 7a387fff ths
    OPC_BLTZ     = (0x00 << 16) | OPC_REGIMM,
242 7a387fff ths
    OPC_BLTZL    = (0x02 << 16) | OPC_REGIMM,
243 7a387fff ths
    OPC_BGEZ     = (0x01 << 16) | OPC_REGIMM,
244 7a387fff ths
    OPC_BGEZL    = (0x03 << 16) | OPC_REGIMM,
245 7a387fff ths
    OPC_BLTZAL   = (0x10 << 16) | OPC_REGIMM,
246 3c824109 Nathan Froyd
    OPC_BLTZALS  = OPC_BLTZAL | 0x5, /* microMIPS */
247 7a387fff ths
    OPC_BLTZALL  = (0x12 << 16) | OPC_REGIMM,
248 7a387fff ths
    OPC_BGEZAL   = (0x11 << 16) | OPC_REGIMM,
249 3c824109 Nathan Froyd
    OPC_BGEZALS  = OPC_BGEZAL | 0x5, /* microMIPS */
250 7a387fff ths
    OPC_BGEZALL  = (0x13 << 16) | OPC_REGIMM,
251 7a387fff ths
    OPC_TGEI     = (0x08 << 16) | OPC_REGIMM,
252 7a387fff ths
    OPC_TGEIU    = (0x09 << 16) | OPC_REGIMM,
253 7a387fff ths
    OPC_TLTI     = (0x0A << 16) | OPC_REGIMM,
254 7a387fff ths
    OPC_TLTIU    = (0x0B << 16) | OPC_REGIMM,
255 7a387fff ths
    OPC_TEQI     = (0x0C << 16) | OPC_REGIMM,
256 7a387fff ths
    OPC_TNEI     = (0x0E << 16) | OPC_REGIMM,
257 7a387fff ths
    OPC_SYNCI    = (0x1F << 16) | OPC_REGIMM,
258 e37e863f bellard
};
259 e37e863f bellard
260 7a387fff ths
/* Special2 opcodes */
261 7a387fff ths
#define MASK_SPECIAL2(op)  MASK_OP_MAJOR(op) | (op & 0x3F)
262 7a387fff ths
263 e37e863f bellard
enum {
264 7a387fff ths
    /* Multiply & xxx operations */
265 7a387fff ths
    OPC_MADD     = 0x00 | OPC_SPECIAL2,
266 7a387fff ths
    OPC_MADDU    = 0x01 | OPC_SPECIAL2,
267 7a387fff ths
    OPC_MUL      = 0x02 | OPC_SPECIAL2,
268 7a387fff ths
    OPC_MSUB     = 0x04 | OPC_SPECIAL2,
269 7a387fff ths
    OPC_MSUBU    = 0x05 | OPC_SPECIAL2,
270 161f85e6 Aurelien Jarno
    /* Loongson 2F */
271 161f85e6 Aurelien Jarno
    OPC_MULT_G_2F   = 0x10 | OPC_SPECIAL2,
272 161f85e6 Aurelien Jarno
    OPC_DMULT_G_2F  = 0x11 | OPC_SPECIAL2,
273 161f85e6 Aurelien Jarno
    OPC_MULTU_G_2F  = 0x12 | OPC_SPECIAL2,
274 161f85e6 Aurelien Jarno
    OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
275 161f85e6 Aurelien Jarno
    OPC_DIV_G_2F    = 0x14 | OPC_SPECIAL2,
276 161f85e6 Aurelien Jarno
    OPC_DDIV_G_2F   = 0x15 | OPC_SPECIAL2,
277 161f85e6 Aurelien Jarno
    OPC_DIVU_G_2F   = 0x16 | OPC_SPECIAL2,
278 161f85e6 Aurelien Jarno
    OPC_DDIVU_G_2F  = 0x17 | OPC_SPECIAL2,
279 161f85e6 Aurelien Jarno
    OPC_MOD_G_2F    = 0x1c | OPC_SPECIAL2,
280 161f85e6 Aurelien Jarno
    OPC_DMOD_G_2F   = 0x1d | OPC_SPECIAL2,
281 161f85e6 Aurelien Jarno
    OPC_MODU_G_2F   = 0x1e | OPC_SPECIAL2,
282 161f85e6 Aurelien Jarno
    OPC_DMODU_G_2F  = 0x1f | OPC_SPECIAL2,
283 e37e863f bellard
    /* Misc */
284 7a387fff ths
    OPC_CLZ      = 0x20 | OPC_SPECIAL2,
285 7a387fff ths
    OPC_CLO      = 0x21 | OPC_SPECIAL2,
286 7a387fff ths
    OPC_DCLZ     = 0x24 | OPC_SPECIAL2,
287 7a387fff ths
    OPC_DCLO     = 0x25 | OPC_SPECIAL2,
288 e37e863f bellard
    /* Special */
289 7a387fff ths
    OPC_SDBBP    = 0x3F | OPC_SPECIAL2,
290 7a387fff ths
};
291 7a387fff ths
292 7a387fff ths
/* Special3 opcodes */
293 7a387fff ths
#define MASK_SPECIAL3(op)  MASK_OP_MAJOR(op) | (op & 0x3F)
294 7a387fff ths
295 7a387fff ths
enum {
296 7a387fff ths
    OPC_EXT      = 0x00 | OPC_SPECIAL3,
297 7a387fff ths
    OPC_DEXTM    = 0x01 | OPC_SPECIAL3,
298 7a387fff ths
    OPC_DEXTU    = 0x02 | OPC_SPECIAL3,
299 7a387fff ths
    OPC_DEXT     = 0x03 | OPC_SPECIAL3,
300 7a387fff ths
    OPC_INS      = 0x04 | OPC_SPECIAL3,
301 7a387fff ths
    OPC_DINSM    = 0x05 | OPC_SPECIAL3,
302 7a387fff ths
    OPC_DINSU    = 0x06 | OPC_SPECIAL3,
303 7a387fff ths
    OPC_DINS     = 0x07 | OPC_SPECIAL3,
304 ead9360e ths
    OPC_FORK     = 0x08 | OPC_SPECIAL3,
305 ead9360e ths
    OPC_YIELD    = 0x09 | OPC_SPECIAL3,
306 7a387fff ths
    OPC_BSHFL    = 0x20 | OPC_SPECIAL3,
307 7a387fff ths
    OPC_DBSHFL   = 0x24 | OPC_SPECIAL3,
308 7a387fff ths
    OPC_RDHWR    = 0x3B | OPC_SPECIAL3,
309 161f85e6 Aurelien Jarno
310 161f85e6 Aurelien Jarno
    /* Loongson 2E */
311 161f85e6 Aurelien Jarno
    OPC_MULT_G_2E   = 0x18 | OPC_SPECIAL3,
312 161f85e6 Aurelien Jarno
    OPC_MULTU_G_2E  = 0x19 | OPC_SPECIAL3,
313 161f85e6 Aurelien Jarno
    OPC_DIV_G_2E    = 0x1A | OPC_SPECIAL3,
314 161f85e6 Aurelien Jarno
    OPC_DIVU_G_2E   = 0x1B | OPC_SPECIAL3,
315 161f85e6 Aurelien Jarno
    OPC_DMULT_G_2E  = 0x1C | OPC_SPECIAL3,
316 161f85e6 Aurelien Jarno
    OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
317 161f85e6 Aurelien Jarno
    OPC_DDIV_G_2E   = 0x1E | OPC_SPECIAL3,
318 161f85e6 Aurelien Jarno
    OPC_DDIVU_G_2E  = 0x1F | OPC_SPECIAL3,
319 161f85e6 Aurelien Jarno
    OPC_MOD_G_2E    = 0x22 | OPC_SPECIAL3,
320 161f85e6 Aurelien Jarno
    OPC_MODU_G_2E   = 0x23 | OPC_SPECIAL3,
321 161f85e6 Aurelien Jarno
    OPC_DMOD_G_2E   = 0x26 | OPC_SPECIAL3,
322 161f85e6 Aurelien Jarno
    OPC_DMODU_G_2E  = 0x27 | OPC_SPECIAL3,
323 e37e863f bellard
};
324 e37e863f bellard
325 7a387fff ths
/* BSHFL opcodes */
326 7a387fff ths
#define MASK_BSHFL(op)     MASK_SPECIAL3(op) | (op & (0x1F << 6))
327 7a387fff ths
328 e37e863f bellard
enum {
329 7a387fff ths
    OPC_WSBH     = (0x02 << 6) | OPC_BSHFL,
330 7a387fff ths
    OPC_SEB      = (0x10 << 6) | OPC_BSHFL,
331 7a387fff ths
    OPC_SEH      = (0x18 << 6) | OPC_BSHFL,
332 e37e863f bellard
};
333 e37e863f bellard
334 7a387fff ths
/* DBSHFL opcodes */
335 7a387fff ths
#define MASK_DBSHFL(op)    MASK_SPECIAL3(op) | (op & (0x1F << 6))
336 7a387fff ths
337 e37e863f bellard
enum {
338 7a387fff ths
    OPC_DSBH     = (0x02 << 6) | OPC_DBSHFL,
339 7a387fff ths
    OPC_DSHD     = (0x05 << 6) | OPC_DBSHFL,
340 e37e863f bellard
};
341 e37e863f bellard
342 7a387fff ths
/* Coprocessor 0 (rs field) */
343 7a387fff ths
#define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
344 7a387fff ths
345 6ea83fed bellard
enum {
346 7a387fff ths
    OPC_MFC0     = (0x00 << 21) | OPC_CP0,
347 7a387fff ths
    OPC_DMFC0    = (0x01 << 21) | OPC_CP0,
348 7a387fff ths
    OPC_MTC0     = (0x04 << 21) | OPC_CP0,
349 7a387fff ths
    OPC_DMTC0    = (0x05 << 21) | OPC_CP0,
350 ead9360e ths
    OPC_MFTR     = (0x08 << 21) | OPC_CP0,
351 7a387fff ths
    OPC_RDPGPR   = (0x0A << 21) | OPC_CP0,
352 7a387fff ths
    OPC_MFMC0    = (0x0B << 21) | OPC_CP0,
353 ead9360e ths
    OPC_MTTR     = (0x0C << 21) | OPC_CP0,
354 7a387fff ths
    OPC_WRPGPR   = (0x0E << 21) | OPC_CP0,
355 7a387fff ths
    OPC_C0       = (0x10 << 21) | OPC_CP0,
356 7a387fff ths
    OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
357 7a387fff ths
    OPC_C0_LAST  = (0x1F << 21) | OPC_CP0,
358 6ea83fed bellard
};
359 7a387fff ths
360 7a387fff ths
/* MFMC0 opcodes */
361 b48cfdff ths
#define MASK_MFMC0(op)     MASK_CP0(op) | (op & 0xFFFF)
362 7a387fff ths
363 7a387fff ths
enum {
364 ead9360e ths
    OPC_DMT      = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
365 ead9360e ths
    OPC_EMT      = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
366 ead9360e ths
    OPC_DVPE     = 0x01 | (0 << 5) | OPC_MFMC0,
367 ead9360e ths
    OPC_EVPE     = 0x01 | (1 << 5) | OPC_MFMC0,
368 7a387fff ths
    OPC_DI       = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
369 7a387fff ths
    OPC_EI       = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
370 7a387fff ths
};
371 7a387fff ths
372 7a387fff ths
/* Coprocessor 0 (with rs == C0) */
373 7a387fff ths
#define MASK_C0(op)        MASK_CP0(op) | (op & 0x3F)
374 7a387fff ths
375 7a387fff ths
enum {
376 7a387fff ths
    OPC_TLBR     = 0x01 | OPC_C0,
377 7a387fff ths
    OPC_TLBWI    = 0x02 | OPC_C0,
378 7a387fff ths
    OPC_TLBWR    = 0x06 | OPC_C0,
379 7a387fff ths
    OPC_TLBP     = 0x08 | OPC_C0,
380 7a387fff ths
    OPC_RFE      = 0x10 | OPC_C0,
381 7a387fff ths
    OPC_ERET     = 0x18 | OPC_C0,
382 7a387fff ths
    OPC_DERET    = 0x1F | OPC_C0,
383 7a387fff ths
    OPC_WAIT     = 0x20 | OPC_C0,
384 7a387fff ths
};
385 7a387fff ths
386 7a387fff ths
/* Coprocessor 1 (rs field) */
387 7a387fff ths
#define MASK_CP1(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
388 7a387fff ths
389 bf4120ad Nathan Froyd
/* Values for the fmt field in FP instructions */
390 bf4120ad Nathan Froyd
enum {
391 bf4120ad Nathan Froyd
    /* 0 - 15 are reserved */
392 e459440a Aurelien Jarno
    FMT_S = 16,          /* single fp */
393 e459440a Aurelien Jarno
    FMT_D = 17,          /* double fp */
394 e459440a Aurelien Jarno
    FMT_E = 18,          /* extended fp */
395 e459440a Aurelien Jarno
    FMT_Q = 19,          /* quad fp */
396 e459440a Aurelien Jarno
    FMT_W = 20,          /* 32-bit fixed */
397 e459440a Aurelien Jarno
    FMT_L = 21,          /* 64-bit fixed */
398 e459440a Aurelien Jarno
    FMT_PS = 22,         /* paired single fp */
399 bf4120ad Nathan Froyd
    /* 23 - 31 are reserved */
400 bf4120ad Nathan Froyd
};
401 bf4120ad Nathan Froyd
402 7a387fff ths
enum {
403 7a387fff ths
    OPC_MFC1     = (0x00 << 21) | OPC_CP1,
404 7a387fff ths
    OPC_DMFC1    = (0x01 << 21) | OPC_CP1,
405 7a387fff ths
    OPC_CFC1     = (0x02 << 21) | OPC_CP1,
406 5a5012ec ths
    OPC_MFHC1    = (0x03 << 21) | OPC_CP1,
407 7a387fff ths
    OPC_MTC1     = (0x04 << 21) | OPC_CP1,
408 7a387fff ths
    OPC_DMTC1    = (0x05 << 21) | OPC_CP1,
409 7a387fff ths
    OPC_CTC1     = (0x06 << 21) | OPC_CP1,
410 5a5012ec ths
    OPC_MTHC1    = (0x07 << 21) | OPC_CP1,
411 7a387fff ths
    OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
412 5a5012ec ths
    OPC_BC1ANY2  = (0x09 << 21) | OPC_CP1,
413 5a5012ec ths
    OPC_BC1ANY4  = (0x0A << 21) | OPC_CP1,
414 e459440a Aurelien Jarno
    OPC_S_FMT    = (FMT_S << 21) | OPC_CP1,
415 e459440a Aurelien Jarno
    OPC_D_FMT    = (FMT_D << 21) | OPC_CP1,
416 e459440a Aurelien Jarno
    OPC_E_FMT    = (FMT_E << 21) | OPC_CP1,
417 e459440a Aurelien Jarno
    OPC_Q_FMT    = (FMT_Q << 21) | OPC_CP1,
418 e459440a Aurelien Jarno
    OPC_W_FMT    = (FMT_W << 21) | OPC_CP1,
419 e459440a Aurelien Jarno
    OPC_L_FMT    = (FMT_L << 21) | OPC_CP1,
420 e459440a Aurelien Jarno
    OPC_PS_FMT   = (FMT_PS << 21) | OPC_CP1,
421 7a387fff ths
};
422 7a387fff ths
423 5a5012ec ths
#define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)
424 5a5012ec ths
#define MASK_BC1(op)            MASK_CP1(op) | (op & (0x3 << 16))
425 5a5012ec ths
426 7a387fff ths
enum {
427 7a387fff ths
    OPC_BC1F     = (0x00 << 16) | OPC_BC1,
428 7a387fff ths
    OPC_BC1T     = (0x01 << 16) | OPC_BC1,
429 7a387fff ths
    OPC_BC1FL    = (0x02 << 16) | OPC_BC1,
430 7a387fff ths
    OPC_BC1TL    = (0x03 << 16) | OPC_BC1,
431 7a387fff ths
};
432 7a387fff ths
433 5a5012ec ths
enum {
434 5a5012ec ths
    OPC_BC1FANY2     = (0x00 << 16) | OPC_BC1ANY2,
435 5a5012ec ths
    OPC_BC1TANY2     = (0x01 << 16) | OPC_BC1ANY2,
436 5a5012ec ths
};
437 5a5012ec ths
438 5a5012ec ths
enum {
439 5a5012ec ths
    OPC_BC1FANY4     = (0x00 << 16) | OPC_BC1ANY4,
440 5a5012ec ths
    OPC_BC1TANY4     = (0x01 << 16) | OPC_BC1ANY4,
441 5a5012ec ths
};
442 7a387fff ths
443 7a387fff ths
#define MASK_CP2(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
444 e0c84da7 ths
445 e0c84da7 ths
enum {
446 e0c84da7 ths
    OPC_MFC2    = (0x00 << 21) | OPC_CP2,
447 e0c84da7 ths
    OPC_DMFC2   = (0x01 << 21) | OPC_CP2,
448 e0c84da7 ths
    OPC_CFC2    = (0x02 << 21) | OPC_CP2,
449 e0c84da7 ths
    OPC_MFHC2   = (0x03 << 21) | OPC_CP2,
450 e0c84da7 ths
    OPC_MTC2    = (0x04 << 21) | OPC_CP2,
451 e0c84da7 ths
    OPC_DMTC2   = (0x05 << 21) | OPC_CP2,
452 e0c84da7 ths
    OPC_CTC2    = (0x06 << 21) | OPC_CP2,
453 e0c84da7 ths
    OPC_MTHC2   = (0x07 << 21) | OPC_CP2,
454 e0c84da7 ths
    OPC_BC2     = (0x08 << 21) | OPC_CP2,
455 e0c84da7 ths
};
456 e0c84da7 ths
457 e0c84da7 ths
#define MASK_CP3(op)       MASK_OP_MAJOR(op) | (op & 0x3F)
458 e0c84da7 ths
459 e0c84da7 ths
enum {
460 e0c84da7 ths
    OPC_LWXC1   = 0x00 | OPC_CP3,
461 e0c84da7 ths
    OPC_LDXC1   = 0x01 | OPC_CP3,
462 e0c84da7 ths
    OPC_LUXC1   = 0x05 | OPC_CP3,
463 e0c84da7 ths
    OPC_SWXC1   = 0x08 | OPC_CP3,
464 e0c84da7 ths
    OPC_SDXC1   = 0x09 | OPC_CP3,
465 e0c84da7 ths
    OPC_SUXC1   = 0x0D | OPC_CP3,
466 e0c84da7 ths
    OPC_PREFX   = 0x0F | OPC_CP3,
467 e0c84da7 ths
    OPC_ALNV_PS = 0x1E | OPC_CP3,
468 e0c84da7 ths
    OPC_MADD_S  = 0x20 | OPC_CP3,
469 e0c84da7 ths
    OPC_MADD_D  = 0x21 | OPC_CP3,
470 e0c84da7 ths
    OPC_MADD_PS = 0x26 | OPC_CP3,
471 e0c84da7 ths
    OPC_MSUB_S  = 0x28 | OPC_CP3,
472 e0c84da7 ths
    OPC_MSUB_D  = 0x29 | OPC_CP3,
473 e0c84da7 ths
    OPC_MSUB_PS = 0x2E | OPC_CP3,
474 e0c84da7 ths
    OPC_NMADD_S = 0x30 | OPC_CP3,
475 fbcc6828 ths
    OPC_NMADD_D = 0x31 | OPC_CP3,
476 e0c84da7 ths
    OPC_NMADD_PS= 0x36 | OPC_CP3,
477 e0c84da7 ths
    OPC_NMSUB_S = 0x38 | OPC_CP3,
478 e0c84da7 ths
    OPC_NMSUB_D = 0x39 | OPC_CP3,
479 e0c84da7 ths
    OPC_NMSUB_PS= 0x3E | OPC_CP3,
480 e0c84da7 ths
};
481 e0c84da7 ths
482 39454628 ths
/* global register indices */
483 a7812ae4 pbrook
static TCGv_ptr cpu_env;
484 a7812ae4 pbrook
static TCGv cpu_gpr[32], cpu_PC;
485 4b2eb8d2 ths
static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
486 41db4607 aurel32
static TCGv cpu_dspctrl, btarget, bcond;
487 41db4607 aurel32
static TCGv_i32 hflags;
488 a7812ae4 pbrook
static TCGv_i32 fpu_fcr0, fpu_fcr31;
489 aa0bf00b ths
490 1a7ff922 Paolo Bonzini
static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
491 1a7ff922 Paolo Bonzini
492 2e70f6ef pbrook
#include "gen-icount.h"
493 2e70f6ef pbrook
494 a7812ae4 pbrook
#define gen_helper_0i(name, arg) do {                             \
495 a7812ae4 pbrook
    TCGv_i32 helper_tmp = tcg_const_i32(arg);                     \
496 a7812ae4 pbrook
    gen_helper_##name(helper_tmp);                                \
497 a7812ae4 pbrook
    tcg_temp_free_i32(helper_tmp);                                \
498 a7812ae4 pbrook
    } while(0)
499 be24bb4f ths
500 a7812ae4 pbrook
#define gen_helper_1i(name, arg1, arg2) do {                      \
501 a7812ae4 pbrook
    TCGv_i32 helper_tmp = tcg_const_i32(arg2);                    \
502 a7812ae4 pbrook
    gen_helper_##name(arg1, helper_tmp);                          \
503 a7812ae4 pbrook
    tcg_temp_free_i32(helper_tmp);                                \
504 a7812ae4 pbrook
    } while(0)
505 be24bb4f ths
506 a7812ae4 pbrook
#define gen_helper_2i(name, arg1, arg2, arg3) do {                \
507 a7812ae4 pbrook
    TCGv_i32 helper_tmp = tcg_const_i32(arg3);                    \
508 a7812ae4 pbrook
    gen_helper_##name(arg1, arg2, helper_tmp);                    \
509 a7812ae4 pbrook
    tcg_temp_free_i32(helper_tmp);                                \
510 a7812ae4 pbrook
    } while(0)
511 be24bb4f ths
512 a7812ae4 pbrook
#define gen_helper_3i(name, arg1, arg2, arg3, arg4) do {          \
513 a7812ae4 pbrook
    TCGv_i32 helper_tmp = tcg_const_i32(arg4);                    \
514 a7812ae4 pbrook
    gen_helper_##name(arg1, arg2, arg3, helper_tmp);              \
515 a7812ae4 pbrook
    tcg_temp_free_i32(helper_tmp);                                \
516 a7812ae4 pbrook
    } while(0)
517 c239529e ths
518 8e9ade68 ths
typedef struct DisasContext {
519 8e9ade68 ths
    struct TranslationBlock *tb;
520 8e9ade68 ths
    target_ulong pc, saved_pc;
521 8e9ade68 ths
    uint32_t opcode;
522 7b270ef2 Nathan Froyd
    int singlestep_enabled;
523 8e9ade68 ths
    /* Routine used to access memory */
524 8e9ade68 ths
    int mem_idx;
525 8e9ade68 ths
    uint32_t hflags, saved_hflags;
526 8e9ade68 ths
    int bstate;
527 8e9ade68 ths
    target_ulong btarget;
528 8e9ade68 ths
} DisasContext;
529 8e9ade68 ths
530 8e9ade68 ths
enum {
531 8e9ade68 ths
    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
532 d077b6f7 ths
                      * exception condition */
533 8e9ade68 ths
    BS_STOP     = 1, /* We want to stop translation for any reason */
534 8e9ade68 ths
    BS_BRANCH   = 2, /* We reached a branch condition     */
535 8e9ade68 ths
    BS_EXCP     = 3, /* We reached an exception condition */
536 8e9ade68 ths
};
537 8e9ade68 ths
538 8e9ade68 ths
static const char *regnames[] =
539 6af0bf9c bellard
    { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
540 6af0bf9c bellard
      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
541 6af0bf9c bellard
      "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
542 6af0bf9c bellard
      "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
543 6af0bf9c bellard
544 4b2eb8d2 ths
static const char *regnames_HI[] =
545 4b2eb8d2 ths
    { "HI0", "HI1", "HI2", "HI3", };
546 4b2eb8d2 ths
547 4b2eb8d2 ths
static const char *regnames_LO[] =
548 4b2eb8d2 ths
    { "LO0", "LO1", "LO2", "LO3", };
549 4b2eb8d2 ths
550 4b2eb8d2 ths
static const char *regnames_ACX[] =
551 4b2eb8d2 ths
    { "ACX0", "ACX1", "ACX2", "ACX3", };
552 4b2eb8d2 ths
553 8e9ade68 ths
static const char *fregnames[] =
554 8e9ade68 ths
    { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
555 8e9ade68 ths
      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
556 8e9ade68 ths
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
557 8e9ade68 ths
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
558 958fb4a9 ths
559 8e9ade68 ths
#ifdef MIPS_DEBUG_DISAS
560 001faf32 Blue Swirl
#define MIPS_DEBUG(fmt, ...)                         \
561 93fcfe39 aliguori
        qemu_log_mask(CPU_LOG_TB_IN_ASM,                \
562 93fcfe39 aliguori
                       TARGET_FMT_lx ": %08x " fmt "\n", \
563 001faf32 Blue Swirl
                       ctx->pc, ctx->opcode , ## __VA_ARGS__)
564 93fcfe39 aliguori
#define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
565 8e9ade68 ths
#else
566 001faf32 Blue Swirl
#define MIPS_DEBUG(fmt, ...) do { } while(0)
567 d12d51d5 aliguori
#define LOG_DISAS(...) do { } while (0)
568 8e9ade68 ths
#endif
569 958fb4a9 ths
570 8e9ade68 ths
#define MIPS_INVAL(op)                                                        \
571 8e9ade68 ths
do {                                                                          \
572 8e9ade68 ths
    MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
573 8e9ade68 ths
               ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
574 8e9ade68 ths
} while (0)
575 ead9360e ths
576 8e9ade68 ths
/* General purpose registers moves. */
577 8e9ade68 ths
static inline void gen_load_gpr (TCGv t, int reg)
578 aaa9128a ths
{
579 8e9ade68 ths
    if (reg == 0)
580 8e9ade68 ths
        tcg_gen_movi_tl(t, 0);
581 8e9ade68 ths
    else
582 4b2eb8d2 ths
        tcg_gen_mov_tl(t, cpu_gpr[reg]);
583 aaa9128a ths
}
584 aaa9128a ths
585 8e9ade68 ths
static inline void gen_store_gpr (TCGv t, int reg)
586 aaa9128a ths
{
587 8e9ade68 ths
    if (reg != 0)
588 4b2eb8d2 ths
        tcg_gen_mov_tl(cpu_gpr[reg], t);
589 aaa9128a ths
}
590 aaa9128a ths
591 b10fa3c9 aurel32
/* Moves to/from ACX register.  */
592 4b2eb8d2 ths
static inline void gen_load_ACX (TCGv t, int reg)
593 893f9865 ths
{
594 4b2eb8d2 ths
    tcg_gen_mov_tl(t, cpu_ACX[reg]);
595 893f9865 ths
}
596 893f9865 ths
597 4b2eb8d2 ths
static inline void gen_store_ACX (TCGv t, int reg)
598 893f9865 ths
{
599 4b2eb8d2 ths
    tcg_gen_mov_tl(cpu_ACX[reg], t);
600 893f9865 ths
}
601 893f9865 ths
602 8e9ade68 ths
/* Moves to/from shadow registers. */
603 be24bb4f ths
static inline void gen_load_srsgpr (int from, int to)
604 aaa9128a ths
{
605 d9bea114 aurel32
    TCGv t0 = tcg_temp_new();
606 be24bb4f ths
607 be24bb4f ths
    if (from == 0)
608 d9bea114 aurel32
        tcg_gen_movi_tl(t0, 0);
609 8e9ade68 ths
    else {
610 d9bea114 aurel32
        TCGv_i32 t2 = tcg_temp_new_i32();
611 a7812ae4 pbrook
        TCGv_ptr addr = tcg_temp_new_ptr();
612 aaa9128a ths
613 d9bea114 aurel32
        tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
614 d9bea114 aurel32
        tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
615 d9bea114 aurel32
        tcg_gen_andi_i32(t2, t2, 0xf);
616 d9bea114 aurel32
        tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
617 d9bea114 aurel32
        tcg_gen_ext_i32_ptr(addr, t2);
618 a7812ae4 pbrook
        tcg_gen_add_ptr(addr, cpu_env, addr);
619 aaa9128a ths
620 d9bea114 aurel32
        tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
621 a7812ae4 pbrook
        tcg_temp_free_ptr(addr);
622 d9bea114 aurel32
        tcg_temp_free_i32(t2);
623 8e9ade68 ths
    }
624 d9bea114 aurel32
    gen_store_gpr(t0, to);
625 d9bea114 aurel32
    tcg_temp_free(t0);
626 aaa9128a ths
}
627 aaa9128a ths
628 be24bb4f ths
static inline void gen_store_srsgpr (int from, int to)
629 aaa9128a ths
{
630 be24bb4f ths
    if (to != 0) {
631 d9bea114 aurel32
        TCGv t0 = tcg_temp_new();
632 d9bea114 aurel32
        TCGv_i32 t2 = tcg_temp_new_i32();
633 a7812ae4 pbrook
        TCGv_ptr addr = tcg_temp_new_ptr();
634 be24bb4f ths
635 d9bea114 aurel32
        gen_load_gpr(t0, from);
636 d9bea114 aurel32
        tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
637 d9bea114 aurel32
        tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
638 d9bea114 aurel32
        tcg_gen_andi_i32(t2, t2, 0xf);
639 d9bea114 aurel32
        tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
640 d9bea114 aurel32
        tcg_gen_ext_i32_ptr(addr, t2);
641 a7812ae4 pbrook
        tcg_gen_add_ptr(addr, cpu_env, addr);
642 be24bb4f ths
643 d9bea114 aurel32
        tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
644 a7812ae4 pbrook
        tcg_temp_free_ptr(addr);
645 d9bea114 aurel32
        tcg_temp_free_i32(t2);
646 d9bea114 aurel32
        tcg_temp_free(t0);
647 8e9ade68 ths
    }
648 aaa9128a ths
}
649 aaa9128a ths
650 aaa9128a ths
/* Floating point register moves. */
651 a7812ae4 pbrook
static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
652 aa0bf00b ths
{
653 6d066274 aurel32
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
654 6ea83fed bellard
}
655 6ea83fed bellard
656 a7812ae4 pbrook
static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
657 aa0bf00b ths
{
658 6d066274 aurel32
    tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
659 6d066274 aurel32
}
660 6d066274 aurel32
661 6d066274 aurel32
static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
662 6d066274 aurel32
{
663 6d066274 aurel32
    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
664 6d066274 aurel32
}
665 6d066274 aurel32
666 6d066274 aurel32
static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
667 6d066274 aurel32
{
668 6d066274 aurel32
    tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
669 aa0bf00b ths
}
670 6ea83fed bellard
671 a7812ae4 pbrook
static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
672 aa0bf00b ths
{
673 f364515c aurel32
    if (ctx->hflags & MIPS_HFLAG_F64) {
674 6d066274 aurel32
        tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
675 f364515c aurel32
    } else {
676 6d066274 aurel32
        TCGv_i32 t0 = tcg_temp_new_i32();
677 6d066274 aurel32
        TCGv_i32 t1 = tcg_temp_new_i32();
678 6d066274 aurel32
        gen_load_fpr32(t0, reg & ~1);
679 6d066274 aurel32
        gen_load_fpr32(t1, reg | 1);
680 6d066274 aurel32
        tcg_gen_concat_i32_i64(t, t0, t1);
681 6d066274 aurel32
        tcg_temp_free_i32(t0);
682 6d066274 aurel32
        tcg_temp_free_i32(t1);
683 aa0bf00b ths
    }
684 aa0bf00b ths
}
685 6ea83fed bellard
686 a7812ae4 pbrook
static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
687 aa0bf00b ths
{
688 f364515c aurel32
    if (ctx->hflags & MIPS_HFLAG_F64) {
689 6d066274 aurel32
        tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
690 f364515c aurel32
    } else {
691 6d066274 aurel32
        TCGv_i64 t0 = tcg_temp_new_i64();
692 6d066274 aurel32
        TCGv_i32 t1 = tcg_temp_new_i32();
693 6d066274 aurel32
        tcg_gen_trunc_i64_i32(t1, t);
694 6d066274 aurel32
        gen_store_fpr32(t1, reg & ~1);
695 6d066274 aurel32
        tcg_gen_shri_i64(t0, t, 32);
696 6d066274 aurel32
        tcg_gen_trunc_i64_i32(t1, t0);
697 6d066274 aurel32
        gen_store_fpr32(t1, reg | 1);
698 6d066274 aurel32
        tcg_temp_free_i32(t1);
699 6d066274 aurel32
        tcg_temp_free_i64(t0);
700 aa0bf00b ths
    }
701 aa0bf00b ths
}
702 6ea83fed bellard
703 d94536f4 aurel32
static inline int get_fp_bit (int cc)
704 a16336e4 ths
{
705 d94536f4 aurel32
    if (cc)
706 d94536f4 aurel32
        return 24 + cc;
707 d94536f4 aurel32
    else
708 d94536f4 aurel32
        return 23;
709 a16336e4 ths
}
710 a16336e4 ths
711 30898801 ths
/* Tests */
712 8e9ade68 ths
static inline void gen_save_pc(target_ulong pc)
713 8e9ade68 ths
{
714 1eb75d4a aurel32
    tcg_gen_movi_tl(cpu_PC, pc);
715 8e9ade68 ths
}
716 30898801 ths
717 356265ae ths
static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
718 6af0bf9c bellard
{
719 d12d51d5 aliguori
    LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
720 6af0bf9c bellard
    if (do_save_pc && ctx->pc != ctx->saved_pc) {
721 9b9e4393 ths
        gen_save_pc(ctx->pc);
722 6af0bf9c bellard
        ctx->saved_pc = ctx->pc;
723 6af0bf9c bellard
    }
724 6af0bf9c bellard
    if (ctx->hflags != ctx->saved_hflags) {
725 41db4607 aurel32
        tcg_gen_movi_i32(hflags, ctx->hflags);
726 6af0bf9c bellard
        ctx->saved_hflags = ctx->hflags;
727 364d4831 Nathan Froyd
        switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
728 5a5012ec ths
        case MIPS_HFLAG_BR:
729 5a5012ec ths
            break;
730 5a5012ec ths
        case MIPS_HFLAG_BC:
731 5a5012ec ths
        case MIPS_HFLAG_BL:
732 5a5012ec ths
        case MIPS_HFLAG_B:
733 d077b6f7 ths
            tcg_gen_movi_tl(btarget, ctx->btarget);
734 5a5012ec ths
            break;
735 6af0bf9c bellard
        }
736 6af0bf9c bellard
    }
737 6af0bf9c bellard
}
738 6af0bf9c bellard
739 356265ae ths
static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
740 5a5012ec ths
{
741 fd4a04eb ths
    ctx->saved_hflags = ctx->hflags;
742 364d4831 Nathan Froyd
    switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
743 fd4a04eb ths
    case MIPS_HFLAG_BR:
744 fd4a04eb ths
        break;
745 fd4a04eb ths
    case MIPS_HFLAG_BC:
746 fd4a04eb ths
    case MIPS_HFLAG_BL:
747 39454628 ths
    case MIPS_HFLAG_B:
748 fd4a04eb ths
        ctx->btarget = env->btarget;
749 fd4a04eb ths
        break;
750 5a5012ec ths
    }
751 5a5012ec ths
}
752 5a5012ec ths
753 356265ae ths
static inline void
754 48d38ca5 ths
generate_exception_err (DisasContext *ctx, int excp, int err)
755 aaa9128a ths
{
756 a7812ae4 pbrook
    TCGv_i32 texcp = tcg_const_i32(excp);
757 a7812ae4 pbrook
    TCGv_i32 terr = tcg_const_i32(err);
758 aaa9128a ths
    save_cpu_state(ctx, 1);
759 a7812ae4 pbrook
    gen_helper_raise_exception_err(texcp, terr);
760 a7812ae4 pbrook
    tcg_temp_free_i32(terr);
761 a7812ae4 pbrook
    tcg_temp_free_i32(texcp);
762 aaa9128a ths
}
763 aaa9128a ths
764 356265ae ths
static inline void
765 48d38ca5 ths
generate_exception (DisasContext *ctx, int excp)
766 aaa9128a ths
{
767 6af0bf9c bellard
    save_cpu_state(ctx, 1);
768 a7812ae4 pbrook
    gen_helper_0i(raise_exception, excp);
769 6af0bf9c bellard
}
770 6af0bf9c bellard
771 48d38ca5 ths
/* Addresses computation */
772 941694d0 Aurelien Jarno
static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
773 4ad40f36 bellard
{
774 941694d0 Aurelien Jarno
    tcg_gen_add_tl(ret, arg0, arg1);
775 48d38ca5 ths
776 48d38ca5 ths
#if defined(TARGET_MIPS64)
777 48d38ca5 ths
    /* For compatibility with 32-bit code, data reference in user mode
778 48d38ca5 ths
       with Status_UX = 0 should be casted to 32-bit and sign extended.
779 48d38ca5 ths
       See the MIPS64 PRA manual, section 4.10. */
780 2623c1ec aurel32
    if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
781 2623c1ec aurel32
        !(ctx->hflags & MIPS_HFLAG_UX)) {
782 941694d0 Aurelien Jarno
        tcg_gen_ext32s_i64(ret, ret);
783 48d38ca5 ths
    }
784 48d38ca5 ths
#endif
785 4ad40f36 bellard
}
786 4ad40f36 bellard
787 356265ae ths
static inline void check_cp0_enabled(DisasContext *ctx)
788 387a8fe5 ths
{
789 fe253235 ths
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
790 c2c65dab Nathan Froyd
        generate_exception_err(ctx, EXCP_CpU, 0);
791 387a8fe5 ths
}
792 387a8fe5 ths
793 356265ae ths
static inline void check_cp1_enabled(DisasContext *ctx)
794 5e755519 ths
{
795 fe253235 ths
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
796 5e755519 ths
        generate_exception_err(ctx, EXCP_CpU, 1);
797 5e755519 ths
}
798 5e755519 ths
799 b8aa4598 ths
/* Verify that the processor is running with COP1X instructions enabled.
800 b8aa4598 ths
   This is associated with the nabla symbol in the MIPS32 and MIPS64
801 b8aa4598 ths
   opcode tables.  */
802 b8aa4598 ths
803 356265ae ths
static inline void check_cop1x(DisasContext *ctx)
804 b8aa4598 ths
{
805 b8aa4598 ths
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
806 b8aa4598 ths
        generate_exception(ctx, EXCP_RI);
807 b8aa4598 ths
}
808 b8aa4598 ths
809 b8aa4598 ths
/* Verify that the processor is running with 64-bit floating-point
810 b8aa4598 ths
   operations enabled.  */
811 b8aa4598 ths
812 356265ae ths
static inline void check_cp1_64bitmode(DisasContext *ctx)
813 5e755519 ths
{
814 b8aa4598 ths
    if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
815 5e755519 ths
        generate_exception(ctx, EXCP_RI);
816 5e755519 ths
}
817 5e755519 ths
818 5e755519 ths
/*
819 5e755519 ths
 * Verify if floating point register is valid; an operation is not defined
820 5e755519 ths
 * if bit 0 of any register specification is set and the FR bit in the
821 5e755519 ths
 * Status register equals zero, since the register numbers specify an
822 5e755519 ths
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
823 5e755519 ths
 * in the Status register equals one, both even and odd register numbers
824 5e755519 ths
 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
825 5e755519 ths
 *
826 5e755519 ths
 * Multiple 64 bit wide registers can be checked by calling
827 5e755519 ths
 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
828 5e755519 ths
 */
829 356265ae ths
static inline void check_cp1_registers(DisasContext *ctx, int regs)
830 5e755519 ths
{
831 fe253235 ths
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
832 5e755519 ths
        generate_exception(ctx, EXCP_RI);
833 5e755519 ths
}
834 5e755519 ths
835 3a95e3a7 ths
/* This code generates a "reserved instruction" exception if the
836 e189e748 ths
   CPU does not support the instruction set corresponding to flags. */
837 356265ae ths
static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
838 3a95e3a7 ths
{
839 e189e748 ths
    if (unlikely(!(env->insn_flags & flags)))
840 3a95e3a7 ths
        generate_exception(ctx, EXCP_RI);
841 3a95e3a7 ths
}
842 3a95e3a7 ths
843 e189e748 ths
/* This code generates a "reserved instruction" exception if 64-bit
844 e189e748 ths
   instructions are not enabled. */
845 356265ae ths
static inline void check_mips_64(DisasContext *ctx)
846 e189e748 ths
{
847 fe253235 ths
    if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
848 e189e748 ths
        generate_exception(ctx, EXCP_RI);
849 e189e748 ths
}
850 e189e748 ths
851 8153667c Nathan Froyd
/* Define small wrappers for gen_load_fpr* so that we have a uniform
852 8153667c Nathan Froyd
   calling interface for 32 and 64-bit FPRs.  No sense in changing
853 8153667c Nathan Froyd
   all callers for gen_load_fpr32 when we need the CTX parameter for
854 8153667c Nathan Froyd
   this one use.  */
855 8153667c Nathan Froyd
#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
856 8153667c Nathan Froyd
#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
857 8153667c Nathan Froyd
#define FOP_CONDS(type, abs, fmt, ifmt, bits)                                 \
858 8153667c Nathan Froyd
static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n,      \
859 8153667c Nathan Froyd
                                               int ft, int fs, int cc)        \
860 8153667c Nathan Froyd
{                                                                             \
861 8153667c Nathan Froyd
    TCGv_i##bits fp0 = tcg_temp_new_i##bits ();                               \
862 8153667c Nathan Froyd
    TCGv_i##bits fp1 = tcg_temp_new_i##bits ();                               \
863 8153667c Nathan Froyd
    switch (ifmt) {                                                           \
864 8153667c Nathan Froyd
    case FMT_PS:                                                              \
865 8153667c Nathan Froyd
        check_cp1_64bitmode(ctx);                                             \
866 8153667c Nathan Froyd
        break;                                                                \
867 8153667c Nathan Froyd
    case FMT_D:                                                               \
868 8153667c Nathan Froyd
        if (abs) {                                                            \
869 8153667c Nathan Froyd
            check_cop1x(ctx);                                                 \
870 8153667c Nathan Froyd
        }                                                                     \
871 8153667c Nathan Froyd
        check_cp1_registers(ctx, fs | ft);                                    \
872 8153667c Nathan Froyd
        break;                                                                \
873 8153667c Nathan Froyd
    case FMT_S:                                                               \
874 8153667c Nathan Froyd
        if (abs) {                                                            \
875 8153667c Nathan Froyd
            check_cop1x(ctx);                                                 \
876 8153667c Nathan Froyd
        }                                                                     \
877 8153667c Nathan Froyd
        break;                                                                \
878 8153667c Nathan Froyd
    }                                                                         \
879 8153667c Nathan Froyd
    gen_ldcmp_fpr##bits (ctx, fp0, fs);                                       \
880 8153667c Nathan Froyd
    gen_ldcmp_fpr##bits (ctx, fp1, ft);                                       \
881 8153667c Nathan Froyd
    switch (n) {                                                              \
882 8153667c Nathan Froyd
    case  0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc);    break;\
883 8153667c Nathan Froyd
    case  1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc);   break;\
884 8153667c Nathan Froyd
    case  2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc);   break;\
885 8153667c Nathan Froyd
    case  3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc);  break;\
886 8153667c Nathan Froyd
    case  4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc);  break;\
887 8153667c Nathan Froyd
    case  5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc);  break;\
888 8153667c Nathan Froyd
    case  6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc);  break;\
889 8153667c Nathan Froyd
    case  7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc);  break;\
890 8153667c Nathan Froyd
    case  8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc);   break;\
891 8153667c Nathan Froyd
    case  9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
892 8153667c Nathan Froyd
    case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc);  break;\
893 8153667c Nathan Froyd
    case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc);  break;\
894 8153667c Nathan Froyd
    case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc);   break;\
895 8153667c Nathan Froyd
    case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc);  break;\
896 8153667c Nathan Froyd
    case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc);   break;\
897 8153667c Nathan Froyd
    case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc);  break;\
898 8153667c Nathan Froyd
    default: abort();                                                         \
899 8153667c Nathan Froyd
    }                                                                         \
900 8153667c Nathan Froyd
    tcg_temp_free_i##bits (fp0);                                              \
901 8153667c Nathan Froyd
    tcg_temp_free_i##bits (fp1);                                              \
902 8153667c Nathan Froyd
}
903 8153667c Nathan Froyd
904 8153667c Nathan Froyd
FOP_CONDS(, 0, d, FMT_D, 64)
905 8153667c Nathan Froyd
FOP_CONDS(abs, 1, d, FMT_D, 64)
906 8153667c Nathan Froyd
FOP_CONDS(, 0, s, FMT_S, 32)
907 8153667c Nathan Froyd
FOP_CONDS(abs, 1, s, FMT_S, 32)
908 8153667c Nathan Froyd
FOP_CONDS(, 0, ps, FMT_PS, 64)
909 8153667c Nathan Froyd
FOP_CONDS(abs, 1, ps, FMT_PS, 64)
910 8153667c Nathan Froyd
#undef FOP_CONDS
911 8153667c Nathan Froyd
#undef gen_ldcmp_fpr32
912 8153667c Nathan Froyd
#undef gen_ldcmp_fpr64
913 8153667c Nathan Froyd
914 958fb4a9 ths
/* load/store instructions. */
915 d9bea114 aurel32
#define OP_LD(insn,fname)                                                 \
916 5c13fdfd Aurelien Jarno
static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx)   \
917 d9bea114 aurel32
{                                                                         \
918 d9bea114 aurel32
    tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx);                        \
919 aaa9128a ths
}
920 aaa9128a ths
OP_LD(lb,ld8s);
921 aaa9128a ths
OP_LD(lbu,ld8u);
922 aaa9128a ths
OP_LD(lh,ld16s);
923 aaa9128a ths
OP_LD(lhu,ld16u);
924 aaa9128a ths
OP_LD(lw,ld32s);
925 aaa9128a ths
#if defined(TARGET_MIPS64)
926 aaa9128a ths
OP_LD(lwu,ld32u);
927 aaa9128a ths
OP_LD(ld,ld64);
928 aaa9128a ths
#endif
929 aaa9128a ths
#undef OP_LD
930 aaa9128a ths
931 d9bea114 aurel32
#define OP_ST(insn,fname)                                                  \
932 5c13fdfd Aurelien Jarno
static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx)   \
933 d9bea114 aurel32
{                                                                          \
934 d9bea114 aurel32
    tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx);                        \
935 aaa9128a ths
}
936 aaa9128a ths
OP_ST(sb,st8);
937 aaa9128a ths
OP_ST(sh,st16);
938 aaa9128a ths
OP_ST(sw,st32);
939 aaa9128a ths
#if defined(TARGET_MIPS64)
940 aaa9128a ths
OP_ST(sd,st64);
941 aaa9128a ths
#endif
942 aaa9128a ths
#undef OP_ST
943 aaa9128a ths
944 e7139c44 Aurelien Jarno
#ifdef CONFIG_USER_ONLY
945 d9bea114 aurel32
#define OP_LD_ATOMIC(insn,fname)                                           \
946 5c13fdfd Aurelien Jarno
static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx)    \
947 d9bea114 aurel32
{                                                                          \
948 d9bea114 aurel32
    TCGv t0 = tcg_temp_new();                                              \
949 d9bea114 aurel32
    tcg_gen_mov_tl(t0, arg1);                                              \
950 d9bea114 aurel32
    tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx);                         \
951 e7139c44 Aurelien Jarno
    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr));                \
952 590bc601 Paul Brook
    tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval));                \
953 d9bea114 aurel32
    tcg_temp_free(t0);                                                     \
954 aaa9128a ths
}
955 e7139c44 Aurelien Jarno
#else
956 e7139c44 Aurelien Jarno
#define OP_LD_ATOMIC(insn,fname)                                           \
957 5c13fdfd Aurelien Jarno
static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx)    \
958 e7139c44 Aurelien Jarno
{                                                                          \
959 e7139c44 Aurelien Jarno
    gen_helper_2i(insn, ret, arg1, ctx->mem_idx);                          \
960 e7139c44 Aurelien Jarno
}
961 e7139c44 Aurelien Jarno
#endif
962 aaa9128a ths
OP_LD_ATOMIC(ll,ld32s);
963 aaa9128a ths
#if defined(TARGET_MIPS64)
964 aaa9128a ths
OP_LD_ATOMIC(lld,ld64);
965 aaa9128a ths
#endif
966 aaa9128a ths
#undef OP_LD_ATOMIC
967 aaa9128a ths
968 590bc601 Paul Brook
#ifdef CONFIG_USER_ONLY
969 590bc601 Paul Brook
#define OP_ST_ATOMIC(insn,fname,ldname,almask)                               \
970 5c13fdfd Aurelien Jarno
static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
971 590bc601 Paul Brook
{                                                                            \
972 590bc601 Paul Brook
    TCGv t0 = tcg_temp_new();                                                \
973 590bc601 Paul Brook
    int l1 = gen_new_label();                                                \
974 590bc601 Paul Brook
    int l2 = gen_new_label();                                                \
975 590bc601 Paul Brook
                                                                             \
976 590bc601 Paul Brook
    tcg_gen_andi_tl(t0, arg2, almask);                                       \
977 590bc601 Paul Brook
    tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);                              \
978 590bc601 Paul Brook
    tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr));          \
979 590bc601 Paul Brook
    generate_exception(ctx, EXCP_AdES);                                      \
980 590bc601 Paul Brook
    gen_set_label(l1);                                                       \
981 e7139c44 Aurelien Jarno
    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr));                  \
982 590bc601 Paul Brook
    tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2);                            \
983 590bc601 Paul Brook
    tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20));                        \
984 590bc601 Paul Brook
    tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg));                   \
985 590bc601 Paul Brook
    tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval));              \
986 590bc601 Paul Brook
    gen_helper_0i(raise_exception, EXCP_SC);                                 \
987 590bc601 Paul Brook
    gen_set_label(l2);                                                       \
988 590bc601 Paul Brook
    tcg_gen_movi_tl(t0, 0);                                                  \
989 590bc601 Paul Brook
    gen_store_gpr(t0, rt);                                                   \
990 590bc601 Paul Brook
    tcg_temp_free(t0);                                                       \
991 590bc601 Paul Brook
}
992 590bc601 Paul Brook
#else
993 590bc601 Paul Brook
#define OP_ST_ATOMIC(insn,fname,ldname,almask)                               \
994 5c13fdfd Aurelien Jarno
static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
995 590bc601 Paul Brook
{                                                                            \
996 590bc601 Paul Brook
    TCGv t0 = tcg_temp_new();                                                \
997 e7139c44 Aurelien Jarno
    gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx);                       \
998 590bc601 Paul Brook
    gen_store_gpr(t0, rt);                                                   \
999 590bc601 Paul Brook
    tcg_temp_free(t0);                                                       \
1000 590bc601 Paul Brook
}
1001 590bc601 Paul Brook
#endif
1002 590bc601 Paul Brook
OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1003 aaa9128a ths
#if defined(TARGET_MIPS64)
1004 590bc601 Paul Brook
OP_ST_ATOMIC(scd,st64,ld64,0x7);
1005 aaa9128a ths
#endif
1006 aaa9128a ths
#undef OP_ST_ATOMIC
1007 aaa9128a ths
1008 662d7485 Nathan Froyd
static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1009 662d7485 Nathan Froyd
                                  int base, int16_t offset)
1010 662d7485 Nathan Froyd
{
1011 662d7485 Nathan Froyd
    if (base == 0) {
1012 662d7485 Nathan Froyd
        tcg_gen_movi_tl(addr, offset);
1013 662d7485 Nathan Froyd
    } else if (offset == 0) {
1014 662d7485 Nathan Froyd
        gen_load_gpr(addr, base);
1015 662d7485 Nathan Froyd
    } else {
1016 662d7485 Nathan Froyd
        tcg_gen_movi_tl(addr, offset);
1017 662d7485 Nathan Froyd
        gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1018 662d7485 Nathan Froyd
    }
1019 662d7485 Nathan Froyd
}
1020 662d7485 Nathan Froyd
1021 364d4831 Nathan Froyd
static target_ulong pc_relative_pc (DisasContext *ctx)
1022 364d4831 Nathan Froyd
{
1023 364d4831 Nathan Froyd
    target_ulong pc = ctx->pc;
1024 364d4831 Nathan Froyd
1025 364d4831 Nathan Froyd
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
1026 364d4831 Nathan Froyd
        int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1027 364d4831 Nathan Froyd
1028 364d4831 Nathan Froyd
        pc -= branch_bytes;
1029 364d4831 Nathan Froyd
    }
1030 364d4831 Nathan Froyd
1031 364d4831 Nathan Froyd
    pc &= ~(target_ulong)3;
1032 364d4831 Nathan Froyd
    return pc;
1033 364d4831 Nathan Froyd
}
1034 364d4831 Nathan Froyd
1035 5c13fdfd Aurelien Jarno
/* Load */
1036 afa88c3a Aurelien Jarno
static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
1037 afa88c3a Aurelien Jarno
                    int rt, int base, int16_t offset)
1038 6af0bf9c bellard
{
1039 5c13fdfd Aurelien Jarno
    const char *opn = "ld";
1040 afa88c3a Aurelien Jarno
    TCGv t0, t1;
1041 afa88c3a Aurelien Jarno
1042 afa88c3a Aurelien Jarno
    if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1043 afa88c3a Aurelien Jarno
        /* Loongson CPU uses a load to zero register for prefetch.
1044 afa88c3a Aurelien Jarno
           We emulate it as a NOP. On other CPU we must perform the
1045 afa88c3a Aurelien Jarno
           actual memory access. */
1046 afa88c3a Aurelien Jarno
        MIPS_DEBUG("NOP");
1047 afa88c3a Aurelien Jarno
        return;
1048 afa88c3a Aurelien Jarno
    }
1049 6af0bf9c bellard
1050 afa88c3a Aurelien Jarno
    t0 = tcg_temp_new();
1051 afa88c3a Aurelien Jarno
    t1 = tcg_temp_new();
1052 662d7485 Nathan Froyd
    gen_base_offset_addr(ctx, t0, base, offset);
1053 afa88c3a Aurelien Jarno
1054 6af0bf9c bellard
    switch (opc) {
1055 d26bc211 ths
#if defined(TARGET_MIPS64)
1056 6e473128 ths
    case OPC_LWU:
1057 d66c7132 aurel32
        save_cpu_state(ctx, 0);
1058 5c13fdfd Aurelien Jarno
        op_ld_lwu(t0, t0, ctx);
1059 78723684 ths
        gen_store_gpr(t0, rt);
1060 6e473128 ths
        opn = "lwu";
1061 6e473128 ths
        break;
1062 6af0bf9c bellard
    case OPC_LD:
1063 d66c7132 aurel32
        save_cpu_state(ctx, 0);
1064 5c13fdfd Aurelien Jarno
        op_ld_ld(t0, t0, ctx);
1065 78723684 ths
        gen_store_gpr(t0, rt);
1066 6af0bf9c bellard
        opn = "ld";
1067 6af0bf9c bellard
        break;
1068 7a387fff ths
    case OPC_LLD:
1069 d66c7132 aurel32
        save_cpu_state(ctx, 0);
1070 5c13fdfd Aurelien Jarno
        op_ld_lld(t0, t0, ctx);
1071 78723684 ths
        gen_store_gpr(t0, rt);
1072 7a387fff ths
        opn = "lld";
1073 7a387fff ths
        break;
1074 6af0bf9c bellard
    case OPC_LDL:
1075 c8c2227e ths
        save_cpu_state(ctx, 1);
1076 78723684 ths
        gen_load_gpr(t1, rt);
1077 d9bea114 aurel32
        gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1078 78723684 ths
        gen_store_gpr(t1, rt);
1079 6af0bf9c bellard
        opn = "ldl";
1080 6af0bf9c bellard
        break;
1081 6af0bf9c bellard
    case OPC_LDR:
1082 c8c2227e ths
        save_cpu_state(ctx, 1);
1083 78723684 ths
        gen_load_gpr(t1, rt);
1084 d9bea114 aurel32
        gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1085 78723684 ths
        gen_store_gpr(t1, rt);
1086 6af0bf9c bellard
        opn = "ldr";
1087 6af0bf9c bellard
        break;
1088 364d4831 Nathan Froyd
    case OPC_LDPC:
1089 364d4831 Nathan Froyd
        save_cpu_state(ctx, 1);
1090 364d4831 Nathan Froyd
        tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1091 364d4831 Nathan Froyd
        gen_op_addr_add(ctx, t0, t0, t1);
1092 5c13fdfd Aurelien Jarno
        op_ld_ld(t0, t0, ctx);
1093 364d4831 Nathan Froyd
        gen_store_gpr(t0, rt);
1094 5c13fdfd Aurelien Jarno
        opn = "ldpc";
1095 364d4831 Nathan Froyd
        break;
1096 6af0bf9c bellard
#endif
1097 364d4831 Nathan Froyd
    case OPC_LWPC:
1098 364d4831 Nathan Froyd
        save_cpu_state(ctx, 1);
1099 364d4831 Nathan Froyd
        tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1100 364d4831 Nathan Froyd
        gen_op_addr_add(ctx, t0, t0, t1);
1101 5c13fdfd Aurelien Jarno
        op_ld_lw(t0, t0, ctx);
1102 364d4831 Nathan Froyd
        gen_store_gpr(t0, rt);
1103 5c13fdfd Aurelien Jarno
        opn = "lwpc";
1104 364d4831 Nathan Froyd
        break;
1105 6af0bf9c bellard
    case OPC_LW:
1106 d66c7132 aurel32
        save_cpu_state(ctx, 0);
1107 5c13fdfd Aurelien Jarno
        op_ld_lw(t0, t0, ctx);
1108 78723684 ths
        gen_store_gpr(t0, rt);
1109 6af0bf9c bellard
        opn = "lw";
1110 6af0bf9c bellard
        break;
1111 6af0bf9c bellard
    case OPC_LH:
1112 d66c7132 aurel32
        save_cpu_state(ctx, 0);
1113 5c13fdfd Aurelien Jarno
        op_ld_lh(t0, t0, ctx);
1114 78723684 ths
        gen_store_gpr(t0, rt);
1115 6af0bf9c bellard
        opn = "lh";
1116 6af0bf9c bellard
        break;
1117 6af0bf9c bellard
    case OPC_LHU:
1118 d66c7132 aurel32
        save_cpu_state(ctx, 0);
1119 5c13fdfd Aurelien Jarno
        op_ld_lhu(t0, t0, ctx);
1120 78723684 ths
        gen_store_gpr(t0, rt);
1121 6af0bf9c bellard
        opn = "lhu";
1122 6af0bf9c bellard
        break;
1123 6af0bf9c bellard
    case OPC_LB:
1124 d66c7132 aurel32
        save_cpu_state(ctx, 0);
1125 5c13fdfd Aurelien Jarno
        op_ld_lb(t0, t0, ctx);
1126 78723684 ths
        gen_store_gpr(t0, rt);
1127 6af0bf9c bellard
        opn = "lb";
1128 6af0bf9c bellard
        break;
1129 6af0bf9c bellard
    case OPC_LBU:
1130 d66c7132 aurel32
        save_cpu_state(ctx, 0);
1131 5c13fdfd Aurelien Jarno
        op_ld_lbu(t0, t0, ctx);
1132 78723684 ths
        gen_store_gpr(t0, rt);
1133 6af0bf9c bellard
        opn = "lbu";
1134 6af0bf9c bellard
        break;
1135 6af0bf9c bellard
    case OPC_LWL:
1136 c8c2227e ths
        save_cpu_state(ctx, 1);
1137 6958549d aurel32
        gen_load_gpr(t1, rt);
1138 d9bea114 aurel32
        gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1139 78723684 ths
        gen_store_gpr(t1, rt);
1140 6af0bf9c bellard
        opn = "lwl";
1141 6af0bf9c bellard
        break;
1142 6af0bf9c bellard
    case OPC_LWR:
1143 c8c2227e ths
        save_cpu_state(ctx, 1);
1144 6958549d aurel32
        gen_load_gpr(t1, rt);
1145 d9bea114 aurel32
        gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1146 78723684 ths
        gen_store_gpr(t1, rt);
1147 6af0bf9c bellard
        opn = "lwr";
1148 6af0bf9c bellard
        break;
1149 6af0bf9c bellard
    case OPC_LL:
1150 e7139c44 Aurelien Jarno
        save_cpu_state(ctx, 1);
1151 5c13fdfd Aurelien Jarno
        op_ld_ll(t0, t0, ctx);
1152 78723684 ths
        gen_store_gpr(t0, rt);
1153 6af0bf9c bellard
        opn = "ll";
1154 6af0bf9c bellard
        break;
1155 d66c7132 aurel32
    }
1156 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1157 d66c7132 aurel32
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1158 d66c7132 aurel32
    tcg_temp_free(t0);
1159 d66c7132 aurel32
    tcg_temp_free(t1);
1160 d66c7132 aurel32
}
1161 d66c7132 aurel32
1162 5c13fdfd Aurelien Jarno
/* Store */
1163 5c13fdfd Aurelien Jarno
static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1164 5c13fdfd Aurelien Jarno
                    int base, int16_t offset)
1165 5c13fdfd Aurelien Jarno
{
1166 5c13fdfd Aurelien Jarno
    const char *opn = "st";
1167 5c13fdfd Aurelien Jarno
    TCGv t0 = tcg_temp_new();
1168 5c13fdfd Aurelien Jarno
    TCGv t1 = tcg_temp_new();
1169 5c13fdfd Aurelien Jarno
1170 5c13fdfd Aurelien Jarno
    gen_base_offset_addr(ctx, t0, base, offset);
1171 5c13fdfd Aurelien Jarno
    gen_load_gpr(t1, rt);
1172 5c13fdfd Aurelien Jarno
    switch (opc) {
1173 5c13fdfd Aurelien Jarno
#if defined(TARGET_MIPS64)
1174 5c13fdfd Aurelien Jarno
    case OPC_SD:
1175 5c13fdfd Aurelien Jarno
        save_cpu_state(ctx, 0);
1176 5c13fdfd Aurelien Jarno
        op_st_sd(t1, t0, ctx);
1177 5c13fdfd Aurelien Jarno
        opn = "sd";
1178 5c13fdfd Aurelien Jarno
        break;
1179 5c13fdfd Aurelien Jarno
    case OPC_SDL:
1180 5c13fdfd Aurelien Jarno
        save_cpu_state(ctx, 1);
1181 5c13fdfd Aurelien Jarno
        gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1182 5c13fdfd Aurelien Jarno
        opn = "sdl";
1183 5c13fdfd Aurelien Jarno
        break;
1184 5c13fdfd Aurelien Jarno
    case OPC_SDR:
1185 5c13fdfd Aurelien Jarno
        save_cpu_state(ctx, 1);
1186 5c13fdfd Aurelien Jarno
        gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1187 5c13fdfd Aurelien Jarno
        opn = "sdr";
1188 5c13fdfd Aurelien Jarno
        break;
1189 5c13fdfd Aurelien Jarno
#endif
1190 5c13fdfd Aurelien Jarno
    case OPC_SW:
1191 5c13fdfd Aurelien Jarno
        save_cpu_state(ctx, 0);
1192 5c13fdfd Aurelien Jarno
        op_st_sw(t1, t0, ctx);
1193 5c13fdfd Aurelien Jarno
        opn = "sw";
1194 5c13fdfd Aurelien Jarno
        break;
1195 5c13fdfd Aurelien Jarno
    case OPC_SH:
1196 5c13fdfd Aurelien Jarno
        save_cpu_state(ctx, 0);
1197 5c13fdfd Aurelien Jarno
        op_st_sh(t1, t0, ctx);
1198 5c13fdfd Aurelien Jarno
        opn = "sh";
1199 5c13fdfd Aurelien Jarno
        break;
1200 5c13fdfd Aurelien Jarno
    case OPC_SB:
1201 5c13fdfd Aurelien Jarno
        save_cpu_state(ctx, 0);
1202 5c13fdfd Aurelien Jarno
        op_st_sb(t1, t0, ctx);
1203 5c13fdfd Aurelien Jarno
        opn = "sb";
1204 5c13fdfd Aurelien Jarno
        break;
1205 5c13fdfd Aurelien Jarno
    case OPC_SWL:
1206 5c13fdfd Aurelien Jarno
        save_cpu_state(ctx, 1);
1207 5c13fdfd Aurelien Jarno
        gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1208 5c13fdfd Aurelien Jarno
        opn = "swl";
1209 5c13fdfd Aurelien Jarno
        break;
1210 5c13fdfd Aurelien Jarno
    case OPC_SWR:
1211 5c13fdfd Aurelien Jarno
        save_cpu_state(ctx, 1);
1212 5c13fdfd Aurelien Jarno
        gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1213 5c13fdfd Aurelien Jarno
        opn = "swr";
1214 5c13fdfd Aurelien Jarno
        break;
1215 5c13fdfd Aurelien Jarno
    }
1216 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1217 5c13fdfd Aurelien Jarno
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1218 5c13fdfd Aurelien Jarno
    tcg_temp_free(t0);
1219 5c13fdfd Aurelien Jarno
    tcg_temp_free(t1);
1220 5c13fdfd Aurelien Jarno
}
1221 5c13fdfd Aurelien Jarno
1222 5c13fdfd Aurelien Jarno
1223 d66c7132 aurel32
/* Store conditional */
1224 d66c7132 aurel32
static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1225 d66c7132 aurel32
                         int base, int16_t offset)
1226 d66c7132 aurel32
{
1227 d66c7132 aurel32
    const char *opn = "st_cond";
1228 d66c7132 aurel32
    TCGv t0, t1;
1229 d66c7132 aurel32
1230 d66c7132 aurel32
    t0 = tcg_temp_local_new();
1231 d66c7132 aurel32
1232 662d7485 Nathan Froyd
    gen_base_offset_addr(ctx, t0, base, offset);
1233 d66c7132 aurel32
    /* Don't do NOP if destination is zero: we must perform the actual
1234 d66c7132 aurel32
       memory access. */
1235 d66c7132 aurel32
1236 d66c7132 aurel32
    t1 = tcg_temp_local_new();
1237 d66c7132 aurel32
    gen_load_gpr(t1, rt);
1238 d66c7132 aurel32
    switch (opc) {
1239 d66c7132 aurel32
#if defined(TARGET_MIPS64)
1240 d66c7132 aurel32
    case OPC_SCD:
1241 d66c7132 aurel32
        save_cpu_state(ctx, 0);
1242 5c13fdfd Aurelien Jarno
        op_st_scd(t1, t0, rt, ctx);
1243 d66c7132 aurel32
        opn = "scd";
1244 d66c7132 aurel32
        break;
1245 d66c7132 aurel32
#endif
1246 6af0bf9c bellard
    case OPC_SC:
1247 e7139c44 Aurelien Jarno
        save_cpu_state(ctx, 1);
1248 5c13fdfd Aurelien Jarno
        op_st_sc(t1, t0, rt, ctx);
1249 6af0bf9c bellard
        opn = "sc";
1250 6af0bf9c bellard
        break;
1251 6af0bf9c bellard
    }
1252 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1253 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1254 78723684 ths
    tcg_temp_free(t1);
1255 d66c7132 aurel32
    tcg_temp_free(t0);
1256 6af0bf9c bellard
}
1257 6af0bf9c bellard
1258 6ea83fed bellard
/* Load and store */
1259 7a387fff ths
static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1260 356265ae ths
                          int base, int16_t offset)
1261 6ea83fed bellard
{
1262 923617a3 ths
    const char *opn = "flt_ldst";
1263 4e2474d6 aurel32
    TCGv t0 = tcg_temp_new();
1264 6ea83fed bellard
1265 662d7485 Nathan Froyd
    gen_base_offset_addr(ctx, t0, base, offset);
1266 6ea83fed bellard
    /* Don't do NOP if destination is zero: we must perform the actual
1267 ead9360e ths
       memory access. */
1268 6ea83fed bellard
    switch (opc) {
1269 6ea83fed bellard
    case OPC_LWC1:
1270 b6d96bed ths
        {
1271 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
1272 b6d96bed ths
1273 c407df81 aurel32
            tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1274 c407df81 aurel32
            tcg_gen_trunc_tl_i32(fp0, t0);
1275 b6d96bed ths
            gen_store_fpr32(fp0, ft);
1276 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
1277 b6d96bed ths
        }
1278 6ea83fed bellard
        opn = "lwc1";
1279 6ea83fed bellard
        break;
1280 6ea83fed bellard
    case OPC_SWC1:
1281 b6d96bed ths
        {
1282 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
1283 a7812ae4 pbrook
            TCGv t1 = tcg_temp_new();
1284 b6d96bed ths
1285 b6d96bed ths
            gen_load_fpr32(fp0, ft);
1286 a7812ae4 pbrook
            tcg_gen_extu_i32_tl(t1, fp0);
1287 a7812ae4 pbrook
            tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1288 a7812ae4 pbrook
            tcg_temp_free(t1);
1289 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
1290 b6d96bed ths
        }
1291 6ea83fed bellard
        opn = "swc1";
1292 6ea83fed bellard
        break;
1293 6ea83fed bellard
    case OPC_LDC1:
1294 b6d96bed ths
        {
1295 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
1296 b6d96bed ths
1297 b6d96bed ths
            tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1298 b6d96bed ths
            gen_store_fpr64(ctx, fp0, ft);
1299 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
1300 b6d96bed ths
        }
1301 6ea83fed bellard
        opn = "ldc1";
1302 6ea83fed bellard
        break;
1303 6ea83fed bellard
    case OPC_SDC1:
1304 b6d96bed ths
        {
1305 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
1306 b6d96bed ths
1307 b6d96bed ths
            gen_load_fpr64(ctx, fp0, ft);
1308 b6d96bed ths
            tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1309 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
1310 b6d96bed ths
        }
1311 6ea83fed bellard
        opn = "sdc1";
1312 6ea83fed bellard
        break;
1313 6ea83fed bellard
    default:
1314 923617a3 ths
        MIPS_INVAL(opn);
1315 e397ee33 ths
        generate_exception(ctx, EXCP_RI);
1316 78723684 ths
        goto out;
1317 6ea83fed bellard
    }
1318 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1319 6ea83fed bellard
    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1320 78723684 ths
 out:
1321 78723684 ths
    tcg_temp_free(t0);
1322 6ea83fed bellard
}
1323 6ea83fed bellard
1324 26ebe468 Nathan Froyd
static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
1325 26ebe468 Nathan Froyd
                          uint32_t op, int rt, int rs, int16_t imm)
1326 26ebe468 Nathan Froyd
{
1327 26ebe468 Nathan Froyd
    if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1328 26ebe468 Nathan Froyd
        check_cp1_enabled(ctx);
1329 26ebe468 Nathan Froyd
        gen_flt_ldst(ctx, op, rt, rs, imm);
1330 26ebe468 Nathan Froyd
    } else {
1331 26ebe468 Nathan Froyd
        generate_exception_err(ctx, EXCP_CpU, 1);
1332 26ebe468 Nathan Froyd
    }
1333 26ebe468 Nathan Froyd
}
1334 26ebe468 Nathan Froyd
1335 6af0bf9c bellard
/* Arithmetic with immediate operand */
1336 e189e748 ths
static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1337 e189e748 ths
                           int rt, int rs, int16_t imm)
1338 6af0bf9c bellard
{
1339 324d9e32 aurel32
    target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1340 923617a3 ths
    const char *opn = "imm arith";
1341 6af0bf9c bellard
1342 7a387fff ths
    if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1343 ead9360e ths
        /* If no destination, treat it as a NOP.
1344 ead9360e ths
           For addi, we must generate the overflow exception when needed. */
1345 6af0bf9c bellard
        MIPS_DEBUG("NOP");
1346 324d9e32 aurel32
        return;
1347 6af0bf9c bellard
    }
1348 6af0bf9c bellard
    switch (opc) {
1349 6af0bf9c bellard
    case OPC_ADDI:
1350 48d38ca5 ths
        {
1351 324d9e32 aurel32
            TCGv t0 = tcg_temp_local_new();
1352 324d9e32 aurel32
            TCGv t1 = tcg_temp_new();
1353 324d9e32 aurel32
            TCGv t2 = tcg_temp_new();
1354 48d38ca5 ths
            int l1 = gen_new_label();
1355 48d38ca5 ths
1356 324d9e32 aurel32
            gen_load_gpr(t1, rs);
1357 324d9e32 aurel32
            tcg_gen_addi_tl(t0, t1, uimm);
1358 324d9e32 aurel32
            tcg_gen_ext32s_tl(t0, t0);
1359 48d38ca5 ths
1360 324d9e32 aurel32
            tcg_gen_xori_tl(t1, t1, ~uimm);
1361 324d9e32 aurel32
            tcg_gen_xori_tl(t2, t0, uimm);
1362 324d9e32 aurel32
            tcg_gen_and_tl(t1, t1, t2);
1363 324d9e32 aurel32
            tcg_temp_free(t2);
1364 324d9e32 aurel32
            tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1365 324d9e32 aurel32
            tcg_temp_free(t1);
1366 48d38ca5 ths
            /* operands of same sign, result different sign */
1367 48d38ca5 ths
            generate_exception(ctx, EXCP_OVERFLOW);
1368 48d38ca5 ths
            gen_set_label(l1);
1369 78723684 ths
            tcg_gen_ext32s_tl(t0, t0);
1370 324d9e32 aurel32
            gen_store_gpr(t0, rt);
1371 324d9e32 aurel32
            tcg_temp_free(t0);
1372 48d38ca5 ths
        }
1373 6af0bf9c bellard
        opn = "addi";
1374 6af0bf9c bellard
        break;
1375 6af0bf9c bellard
    case OPC_ADDIU:
1376 324d9e32 aurel32
        if (rs != 0) {
1377 324d9e32 aurel32
            tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1378 324d9e32 aurel32
            tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1379 324d9e32 aurel32
        } else {
1380 324d9e32 aurel32
            tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1381 324d9e32 aurel32
        }
1382 6af0bf9c bellard
        opn = "addiu";
1383 6af0bf9c bellard
        break;
1384 d26bc211 ths
#if defined(TARGET_MIPS64)
1385 7a387fff ths
    case OPC_DADDI:
1386 48d38ca5 ths
        {
1387 324d9e32 aurel32
            TCGv t0 = tcg_temp_local_new();
1388 324d9e32 aurel32
            TCGv t1 = tcg_temp_new();
1389 324d9e32 aurel32
            TCGv t2 = tcg_temp_new();
1390 48d38ca5 ths
            int l1 = gen_new_label();
1391 48d38ca5 ths
1392 324d9e32 aurel32
            gen_load_gpr(t1, rs);
1393 324d9e32 aurel32
            tcg_gen_addi_tl(t0, t1, uimm);
1394 48d38ca5 ths
1395 324d9e32 aurel32
            tcg_gen_xori_tl(t1, t1, ~uimm);
1396 324d9e32 aurel32
            tcg_gen_xori_tl(t2, t0, uimm);
1397 324d9e32 aurel32
            tcg_gen_and_tl(t1, t1, t2);
1398 324d9e32 aurel32
            tcg_temp_free(t2);
1399 324d9e32 aurel32
            tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1400 324d9e32 aurel32
            tcg_temp_free(t1);
1401 48d38ca5 ths
            /* operands of same sign, result different sign */
1402 48d38ca5 ths
            generate_exception(ctx, EXCP_OVERFLOW);
1403 48d38ca5 ths
            gen_set_label(l1);
1404 324d9e32 aurel32
            gen_store_gpr(t0, rt);
1405 324d9e32 aurel32
            tcg_temp_free(t0);
1406 48d38ca5 ths
        }
1407 7a387fff ths
        opn = "daddi";
1408 7a387fff ths
        break;
1409 7a387fff ths
    case OPC_DADDIU:
1410 324d9e32 aurel32
        if (rs != 0) {
1411 324d9e32 aurel32
            tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1412 324d9e32 aurel32
        } else {
1413 324d9e32 aurel32
            tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1414 324d9e32 aurel32
        }
1415 7a387fff ths
        opn = "daddiu";
1416 7a387fff ths
        break;
1417 7a387fff ths
#endif
1418 324d9e32 aurel32
    }
1419 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1420 324d9e32 aurel32
    MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1421 324d9e32 aurel32
}
1422 324d9e32 aurel32
1423 324d9e32 aurel32
/* Logic with immediate operand */
1424 324d9e32 aurel32
static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1425 324d9e32 aurel32
{
1426 324d9e32 aurel32
    target_ulong uimm;
1427 324d9e32 aurel32
    const char *opn = "imm logic";
1428 324d9e32 aurel32
1429 324d9e32 aurel32
    if (rt == 0) {
1430 324d9e32 aurel32
        /* If no destination, treat it as a NOP. */
1431 324d9e32 aurel32
        MIPS_DEBUG("NOP");
1432 324d9e32 aurel32
        return;
1433 324d9e32 aurel32
    }
1434 324d9e32 aurel32
    uimm = (uint16_t)imm;
1435 324d9e32 aurel32
    switch (opc) {
1436 6af0bf9c bellard
    case OPC_ANDI:
1437 324d9e32 aurel32
        if (likely(rs != 0))
1438 324d9e32 aurel32
            tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1439 324d9e32 aurel32
        else
1440 324d9e32 aurel32
            tcg_gen_movi_tl(cpu_gpr[rt], 0);
1441 6af0bf9c bellard
        opn = "andi";
1442 6af0bf9c bellard
        break;
1443 6af0bf9c bellard
    case OPC_ORI:
1444 324d9e32 aurel32
        if (rs != 0)
1445 324d9e32 aurel32
            tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1446 324d9e32 aurel32
        else
1447 324d9e32 aurel32
            tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1448 6af0bf9c bellard
        opn = "ori";
1449 6af0bf9c bellard
        break;
1450 6af0bf9c bellard
    case OPC_XORI:
1451 324d9e32 aurel32
        if (likely(rs != 0))
1452 324d9e32 aurel32
            tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1453 324d9e32 aurel32
        else
1454 324d9e32 aurel32
            tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1455 6af0bf9c bellard
        opn = "xori";
1456 6af0bf9c bellard
        break;
1457 6af0bf9c bellard
    case OPC_LUI:
1458 324d9e32 aurel32
        tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1459 6af0bf9c bellard
        opn = "lui";
1460 6af0bf9c bellard
        break;
1461 324d9e32 aurel32
    }
1462 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1463 324d9e32 aurel32
    MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1464 324d9e32 aurel32
}
1465 324d9e32 aurel32
1466 324d9e32 aurel32
/* Set on less than with immediate operand */
1467 324d9e32 aurel32
static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1468 324d9e32 aurel32
{
1469 324d9e32 aurel32
    target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1470 324d9e32 aurel32
    const char *opn = "imm arith";
1471 324d9e32 aurel32
    TCGv t0;
1472 324d9e32 aurel32
1473 324d9e32 aurel32
    if (rt == 0) {
1474 324d9e32 aurel32
        /* If no destination, treat it as a NOP. */
1475 324d9e32 aurel32
        MIPS_DEBUG("NOP");
1476 324d9e32 aurel32
        return;
1477 324d9e32 aurel32
    }
1478 324d9e32 aurel32
    t0 = tcg_temp_new();
1479 324d9e32 aurel32
    gen_load_gpr(t0, rs);
1480 324d9e32 aurel32
    switch (opc) {
1481 324d9e32 aurel32
    case OPC_SLTI:
1482 e68dd28f Aurelien Jarno
        tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1483 324d9e32 aurel32
        opn = "slti";
1484 324d9e32 aurel32
        break;
1485 324d9e32 aurel32
    case OPC_SLTIU:
1486 e68dd28f Aurelien Jarno
        tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1487 324d9e32 aurel32
        opn = "sltiu";
1488 324d9e32 aurel32
        break;
1489 324d9e32 aurel32
    }
1490 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1491 324d9e32 aurel32
    MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1492 324d9e32 aurel32
    tcg_temp_free(t0);
1493 324d9e32 aurel32
}
1494 324d9e32 aurel32
1495 324d9e32 aurel32
/* Shifts with immediate operand */
1496 324d9e32 aurel32
static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1497 324d9e32 aurel32
                          int rt, int rs, int16_t imm)
1498 324d9e32 aurel32
{
1499 324d9e32 aurel32
    target_ulong uimm = ((uint16_t)imm) & 0x1f;
1500 324d9e32 aurel32
    const char *opn = "imm shift";
1501 324d9e32 aurel32
    TCGv t0;
1502 324d9e32 aurel32
1503 324d9e32 aurel32
    if (rt == 0) {
1504 324d9e32 aurel32
        /* If no destination, treat it as a NOP. */
1505 324d9e32 aurel32
        MIPS_DEBUG("NOP");
1506 324d9e32 aurel32
        return;
1507 324d9e32 aurel32
    }
1508 324d9e32 aurel32
1509 324d9e32 aurel32
    t0 = tcg_temp_new();
1510 324d9e32 aurel32
    gen_load_gpr(t0, rs);
1511 324d9e32 aurel32
    switch (opc) {
1512 6af0bf9c bellard
    case OPC_SLL:
1513 78723684 ths
        tcg_gen_shli_tl(t0, t0, uimm);
1514 324d9e32 aurel32
        tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1515 6af0bf9c bellard
        opn = "sll";
1516 6af0bf9c bellard
        break;
1517 6af0bf9c bellard
    case OPC_SRA:
1518 324d9e32 aurel32
        tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1519 6af0bf9c bellard
        opn = "sra";
1520 6af0bf9c bellard
        break;
1521 6af0bf9c bellard
    case OPC_SRL:
1522 ea63e2c3 Nathan Froyd
        if (uimm != 0) {
1523 ea63e2c3 Nathan Froyd
            tcg_gen_ext32u_tl(t0, t0);
1524 ea63e2c3 Nathan Froyd
            tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1525 ea63e2c3 Nathan Froyd
        } else {
1526 ea63e2c3 Nathan Froyd
            tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1527 5a63bcb2 ths
        }
1528 ea63e2c3 Nathan Froyd
        opn = "srl";
1529 ea63e2c3 Nathan Froyd
        break;
1530 ea63e2c3 Nathan Froyd
    case OPC_ROTR:
1531 ea63e2c3 Nathan Froyd
        if (uimm != 0) {
1532 ea63e2c3 Nathan Froyd
            TCGv_i32 t1 = tcg_temp_new_i32();
1533 ea63e2c3 Nathan Froyd
1534 ea63e2c3 Nathan Froyd
            tcg_gen_trunc_tl_i32(t1, t0);
1535 ea63e2c3 Nathan Froyd
            tcg_gen_rotri_i32(t1, t1, uimm);
1536 ea63e2c3 Nathan Froyd
            tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1537 ea63e2c3 Nathan Froyd
            tcg_temp_free_i32(t1);
1538 3399e30f Nathan Froyd
        } else {
1539 3399e30f Nathan Froyd
            tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1540 ea63e2c3 Nathan Froyd
        }
1541 ea63e2c3 Nathan Froyd
        opn = "rotr";
1542 7a387fff ths
        break;
1543 d26bc211 ths
#if defined(TARGET_MIPS64)
1544 7a387fff ths
    case OPC_DSLL:
1545 324d9e32 aurel32
        tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1546 7a387fff ths
        opn = "dsll";
1547 7a387fff ths
        break;
1548 7a387fff ths
    case OPC_DSRA:
1549 324d9e32 aurel32
        tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1550 7a387fff ths
        opn = "dsra";
1551 7a387fff ths
        break;
1552 7a387fff ths
    case OPC_DSRL:
1553 ea63e2c3 Nathan Froyd
        tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1554 ea63e2c3 Nathan Froyd
        opn = "dsrl";
1555 ea63e2c3 Nathan Froyd
        break;
1556 ea63e2c3 Nathan Froyd
    case OPC_DROTR:
1557 ea63e2c3 Nathan Froyd
        if (uimm != 0) {
1558 ea63e2c3 Nathan Froyd
            tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1559 3399e30f Nathan Froyd
        } else {
1560 3399e30f Nathan Froyd
            tcg_gen_mov_tl(cpu_gpr[rt], t0);
1561 5a63bcb2 ths
        }
1562 ea63e2c3 Nathan Froyd
        opn = "drotr";
1563 7a387fff ths
        break;
1564 7a387fff ths
    case OPC_DSLL32:
1565 324d9e32 aurel32
        tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1566 7a387fff ths
        opn = "dsll32";
1567 7a387fff ths
        break;
1568 7a387fff ths
    case OPC_DSRA32:
1569 324d9e32 aurel32
        tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1570 7a387fff ths
        opn = "dsra32";
1571 7a387fff ths
        break;
1572 7a387fff ths
    case OPC_DSRL32:
1573 ea63e2c3 Nathan Froyd
        tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1574 ea63e2c3 Nathan Froyd
        opn = "dsrl32";
1575 ea63e2c3 Nathan Froyd
        break;
1576 ea63e2c3 Nathan Froyd
    case OPC_DROTR32:
1577 ea63e2c3 Nathan Froyd
        tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1578 ea63e2c3 Nathan Froyd
        opn = "drotr32";
1579 6af0bf9c bellard
        break;
1580 7a387fff ths
#endif
1581 6af0bf9c bellard
    }
1582 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1583 93b12ccc ths
    MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1584 78723684 ths
    tcg_temp_free(t0);
1585 6af0bf9c bellard
}
1586 6af0bf9c bellard
1587 6af0bf9c bellard
/* Arithmetic */
1588 e189e748 ths
static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
1589 6af0bf9c bellard
                       int rd, int rs, int rt)
1590 6af0bf9c bellard
{
1591 923617a3 ths
    const char *opn = "arith";
1592 6af0bf9c bellard
1593 7a387fff ths
    if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1594 7a387fff ths
       && opc != OPC_DADD && opc != OPC_DSUB) {
1595 ead9360e ths
        /* If no destination, treat it as a NOP.
1596 ead9360e ths
           For add & sub, we must generate the overflow exception when needed. */
1597 6af0bf9c bellard
        MIPS_DEBUG("NOP");
1598 460f00c4 aurel32
        return;
1599 185f0762 ths
    }
1600 460f00c4 aurel32
1601 6af0bf9c bellard
    switch (opc) {
1602 6af0bf9c bellard
    case OPC_ADD:
1603 48d38ca5 ths
        {
1604 460f00c4 aurel32
            TCGv t0 = tcg_temp_local_new();
1605 460f00c4 aurel32
            TCGv t1 = tcg_temp_new();
1606 460f00c4 aurel32
            TCGv t2 = tcg_temp_new();
1607 48d38ca5 ths
            int l1 = gen_new_label();
1608 48d38ca5 ths
1609 460f00c4 aurel32
            gen_load_gpr(t1, rs);
1610 460f00c4 aurel32
            gen_load_gpr(t2, rt);
1611 460f00c4 aurel32
            tcg_gen_add_tl(t0, t1, t2);
1612 460f00c4 aurel32
            tcg_gen_ext32s_tl(t0, t0);
1613 460f00c4 aurel32
            tcg_gen_xor_tl(t1, t1, t2);
1614 460f00c4 aurel32
            tcg_gen_xor_tl(t2, t0, t2);
1615 deb4203d Aurelien Jarno
            tcg_gen_andc_tl(t1, t2, t1);
1616 460f00c4 aurel32
            tcg_temp_free(t2);
1617 460f00c4 aurel32
            tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1618 460f00c4 aurel32
            tcg_temp_free(t1);
1619 48d38ca5 ths
            /* operands of same sign, result different sign */
1620 48d38ca5 ths
            generate_exception(ctx, EXCP_OVERFLOW);
1621 48d38ca5 ths
            gen_set_label(l1);
1622 460f00c4 aurel32
            gen_store_gpr(t0, rd);
1623 460f00c4 aurel32
            tcg_temp_free(t0);
1624 48d38ca5 ths
        }
1625 6af0bf9c bellard
        opn = "add";
1626 6af0bf9c bellard
        break;
1627 6af0bf9c bellard
    case OPC_ADDU:
1628 460f00c4 aurel32
        if (rs != 0 && rt != 0) {
1629 460f00c4 aurel32
            tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1630 460f00c4 aurel32
            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1631 460f00c4 aurel32
        } else if (rs == 0 && rt != 0) {
1632 460f00c4 aurel32
            tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1633 460f00c4 aurel32
        } else if (rs != 0 && rt == 0) {
1634 460f00c4 aurel32
            tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1635 460f00c4 aurel32
        } else {
1636 460f00c4 aurel32
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
1637 460f00c4 aurel32
        }
1638 6af0bf9c bellard
        opn = "addu";
1639 6af0bf9c bellard
        break;
1640 6af0bf9c bellard
    case OPC_SUB:
1641 48d38ca5 ths
        {
1642 460f00c4 aurel32
            TCGv t0 = tcg_temp_local_new();
1643 460f00c4 aurel32
            TCGv t1 = tcg_temp_new();
1644 460f00c4 aurel32
            TCGv t2 = tcg_temp_new();
1645 48d38ca5 ths
            int l1 = gen_new_label();
1646 48d38ca5 ths
1647 460f00c4 aurel32
            gen_load_gpr(t1, rs);
1648 460f00c4 aurel32
            gen_load_gpr(t2, rt);
1649 460f00c4 aurel32
            tcg_gen_sub_tl(t0, t1, t2);
1650 460f00c4 aurel32
            tcg_gen_ext32s_tl(t0, t0);
1651 460f00c4 aurel32
            tcg_gen_xor_tl(t2, t1, t2);
1652 460f00c4 aurel32
            tcg_gen_xor_tl(t1, t0, t1);
1653 460f00c4 aurel32
            tcg_gen_and_tl(t1, t1, t2);
1654 460f00c4 aurel32
            tcg_temp_free(t2);
1655 460f00c4 aurel32
            tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1656 460f00c4 aurel32
            tcg_temp_free(t1);
1657 31e3104f Aurelien Jarno
            /* operands of different sign, first operand and result different sign */
1658 48d38ca5 ths
            generate_exception(ctx, EXCP_OVERFLOW);
1659 48d38ca5 ths
            gen_set_label(l1);
1660 460f00c4 aurel32
            gen_store_gpr(t0, rd);
1661 460f00c4 aurel32
            tcg_temp_free(t0);
1662 48d38ca5 ths
        }
1663 6af0bf9c bellard
        opn = "sub";
1664 6af0bf9c bellard
        break;
1665 6af0bf9c bellard
    case OPC_SUBU:
1666 460f00c4 aurel32
        if (rs != 0 && rt != 0) {
1667 460f00c4 aurel32
            tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1668 460f00c4 aurel32
            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1669 460f00c4 aurel32
        } else if (rs == 0 && rt != 0) {
1670 460f00c4 aurel32
            tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1671 6bb72b18 Aurelien Jarno
            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1672 460f00c4 aurel32
        } else if (rs != 0 && rt == 0) {
1673 460f00c4 aurel32
            tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1674 460f00c4 aurel32
        } else {
1675 460f00c4 aurel32
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
1676 460f00c4 aurel32
        }
1677 6af0bf9c bellard
        opn = "subu";
1678 6af0bf9c bellard
        break;
1679 d26bc211 ths
#if defined(TARGET_MIPS64)
1680 7a387fff ths
    case OPC_DADD:
1681 48d38ca5 ths
        {
1682 460f00c4 aurel32
            TCGv t0 = tcg_temp_local_new();
1683 460f00c4 aurel32
            TCGv t1 = tcg_temp_new();
1684 460f00c4 aurel32
            TCGv t2 = tcg_temp_new();
1685 48d38ca5 ths
            int l1 = gen_new_label();
1686 48d38ca5 ths
1687 460f00c4 aurel32
            gen_load_gpr(t1, rs);
1688 460f00c4 aurel32
            gen_load_gpr(t2, rt);
1689 460f00c4 aurel32
            tcg_gen_add_tl(t0, t1, t2);
1690 460f00c4 aurel32
            tcg_gen_xor_tl(t1, t1, t2);
1691 460f00c4 aurel32
            tcg_gen_xor_tl(t2, t0, t2);
1692 deb4203d Aurelien Jarno
            tcg_gen_andc_tl(t1, t2, t1);
1693 460f00c4 aurel32
            tcg_temp_free(t2);
1694 460f00c4 aurel32
            tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1695 460f00c4 aurel32
            tcg_temp_free(t1);
1696 48d38ca5 ths
            /* operands of same sign, result different sign */
1697 48d38ca5 ths
            generate_exception(ctx, EXCP_OVERFLOW);
1698 48d38ca5 ths
            gen_set_label(l1);
1699 460f00c4 aurel32
            gen_store_gpr(t0, rd);
1700 460f00c4 aurel32
            tcg_temp_free(t0);
1701 48d38ca5 ths
        }
1702 7a387fff ths
        opn = "dadd";
1703 7a387fff ths
        break;
1704 7a387fff ths
    case OPC_DADDU:
1705 460f00c4 aurel32
        if (rs != 0 && rt != 0) {
1706 460f00c4 aurel32
            tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1707 460f00c4 aurel32
        } else if (rs == 0 && rt != 0) {
1708 460f00c4 aurel32
            tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1709 460f00c4 aurel32
        } else if (rs != 0 && rt == 0) {
1710 460f00c4 aurel32
            tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1711 460f00c4 aurel32
        } else {
1712 460f00c4 aurel32
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
1713 460f00c4 aurel32
        }
1714 7a387fff ths
        opn = "daddu";
1715 7a387fff ths
        break;
1716 7a387fff ths
    case OPC_DSUB:
1717 48d38ca5 ths
        {
1718 460f00c4 aurel32
            TCGv t0 = tcg_temp_local_new();
1719 460f00c4 aurel32
            TCGv t1 = tcg_temp_new();
1720 460f00c4 aurel32
            TCGv t2 = tcg_temp_new();
1721 48d38ca5 ths
            int l1 = gen_new_label();
1722 48d38ca5 ths
1723 460f00c4 aurel32
            gen_load_gpr(t1, rs);
1724 460f00c4 aurel32
            gen_load_gpr(t2, rt);
1725 460f00c4 aurel32
            tcg_gen_sub_tl(t0, t1, t2);
1726 460f00c4 aurel32
            tcg_gen_xor_tl(t2, t1, t2);
1727 460f00c4 aurel32
            tcg_gen_xor_tl(t1, t0, t1);
1728 460f00c4 aurel32
            tcg_gen_and_tl(t1, t1, t2);
1729 460f00c4 aurel32
            tcg_temp_free(t2);
1730 460f00c4 aurel32
            tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1731 460f00c4 aurel32
            tcg_temp_free(t1);
1732 31e3104f Aurelien Jarno
            /* operands of different sign, first operand and result different sign */
1733 48d38ca5 ths
            generate_exception(ctx, EXCP_OVERFLOW);
1734 48d38ca5 ths
            gen_set_label(l1);
1735 460f00c4 aurel32
            gen_store_gpr(t0, rd);
1736 460f00c4 aurel32
            tcg_temp_free(t0);
1737 48d38ca5 ths
        }
1738 7a387fff ths
        opn = "dsub";
1739 7a387fff ths
        break;
1740 7a387fff ths
    case OPC_DSUBU:
1741 460f00c4 aurel32
        if (rs != 0 && rt != 0) {
1742 460f00c4 aurel32
            tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1743 460f00c4 aurel32
        } else if (rs == 0 && rt != 0) {
1744 460f00c4 aurel32
            tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1745 460f00c4 aurel32
        } else if (rs != 0 && rt == 0) {
1746 460f00c4 aurel32
            tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1747 460f00c4 aurel32
        } else {
1748 460f00c4 aurel32
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
1749 460f00c4 aurel32
        }
1750 7a387fff ths
        opn = "dsubu";
1751 7a387fff ths
        break;
1752 7a387fff ths
#endif
1753 460f00c4 aurel32
    case OPC_MUL:
1754 460f00c4 aurel32
        if (likely(rs != 0 && rt != 0)) {
1755 460f00c4 aurel32
            tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1756 460f00c4 aurel32
            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1757 460f00c4 aurel32
        } else {
1758 460f00c4 aurel32
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
1759 460f00c4 aurel32
        }
1760 460f00c4 aurel32
        opn = "mul";
1761 6af0bf9c bellard
        break;
1762 460f00c4 aurel32
    }
1763 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1764 460f00c4 aurel32
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1765 460f00c4 aurel32
}
1766 460f00c4 aurel32
1767 460f00c4 aurel32
/* Conditional move */
1768 460f00c4 aurel32
static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1769 460f00c4 aurel32
{
1770 460f00c4 aurel32
    const char *opn = "cond move";
1771 460f00c4 aurel32
    int l1;
1772 460f00c4 aurel32
1773 460f00c4 aurel32
    if (rd == 0) {
1774 460f00c4 aurel32
        /* If no destination, treat it as a NOP.
1775 460f00c4 aurel32
           For add & sub, we must generate the overflow exception when needed. */
1776 460f00c4 aurel32
        MIPS_DEBUG("NOP");
1777 460f00c4 aurel32
        return;
1778 460f00c4 aurel32
    }
1779 460f00c4 aurel32
1780 460f00c4 aurel32
    l1 = gen_new_label();
1781 460f00c4 aurel32
    switch (opc) {
1782 460f00c4 aurel32
    case OPC_MOVN:
1783 460f00c4 aurel32
        if (likely(rt != 0))
1784 460f00c4 aurel32
            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1785 460f00c4 aurel32
        else
1786 460f00c4 aurel32
            tcg_gen_br(l1);
1787 460f00c4 aurel32
        opn = "movn";
1788 6af0bf9c bellard
        break;
1789 460f00c4 aurel32
    case OPC_MOVZ:
1790 460f00c4 aurel32
        if (likely(rt != 0))
1791 460f00c4 aurel32
            tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1792 460f00c4 aurel32
        opn = "movz";
1793 460f00c4 aurel32
        break;
1794 460f00c4 aurel32
    }
1795 460f00c4 aurel32
    if (rs != 0)
1796 460f00c4 aurel32
        tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1797 460f00c4 aurel32
    else
1798 460f00c4 aurel32
        tcg_gen_movi_tl(cpu_gpr[rd], 0);
1799 460f00c4 aurel32
    gen_set_label(l1);
1800 460f00c4 aurel32
1801 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1802 460f00c4 aurel32
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1803 460f00c4 aurel32
}
1804 460f00c4 aurel32
1805 460f00c4 aurel32
/* Logic */
1806 460f00c4 aurel32
static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1807 460f00c4 aurel32
{
1808 460f00c4 aurel32
    const char *opn = "logic";
1809 460f00c4 aurel32
1810 460f00c4 aurel32
    if (rd == 0) {
1811 460f00c4 aurel32
        /* If no destination, treat it as a NOP. */
1812 460f00c4 aurel32
        MIPS_DEBUG("NOP");
1813 460f00c4 aurel32
        return;
1814 460f00c4 aurel32
    }
1815 460f00c4 aurel32
1816 460f00c4 aurel32
    switch (opc) {
1817 6af0bf9c bellard
    case OPC_AND:
1818 460f00c4 aurel32
        if (likely(rs != 0 && rt != 0)) {
1819 460f00c4 aurel32
            tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1820 460f00c4 aurel32
        } else {
1821 460f00c4 aurel32
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
1822 460f00c4 aurel32
        }
1823 6af0bf9c bellard
        opn = "and";
1824 6af0bf9c bellard
        break;
1825 6af0bf9c bellard
    case OPC_NOR:
1826 460f00c4 aurel32
        if (rs != 0 && rt != 0) {
1827 460f00c4 aurel32
            tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1828 460f00c4 aurel32
        } else if (rs == 0 && rt != 0) {
1829 460f00c4 aurel32
            tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1830 460f00c4 aurel32
        } else if (rs != 0 && rt == 0) {
1831 460f00c4 aurel32
            tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1832 460f00c4 aurel32
        } else {
1833 460f00c4 aurel32
            tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1834 460f00c4 aurel32
        }
1835 6af0bf9c bellard
        opn = "nor";
1836 6af0bf9c bellard
        break;
1837 6af0bf9c bellard
    case OPC_OR:
1838 460f00c4 aurel32
        if (likely(rs != 0 && rt != 0)) {
1839 460f00c4 aurel32
            tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1840 460f00c4 aurel32
        } else if (rs == 0 && rt != 0) {
1841 460f00c4 aurel32
            tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1842 460f00c4 aurel32
        } else if (rs != 0 && rt == 0) {
1843 460f00c4 aurel32
            tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1844 460f00c4 aurel32
        } else {
1845 460f00c4 aurel32
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
1846 460f00c4 aurel32
        }
1847 6af0bf9c bellard
        opn = "or";
1848 6af0bf9c bellard
        break;
1849 6af0bf9c bellard
    case OPC_XOR:
1850 460f00c4 aurel32
        if (likely(rs != 0 && rt != 0)) {
1851 460f00c4 aurel32
            tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1852 460f00c4 aurel32
        } else if (rs == 0 && rt != 0) {
1853 460f00c4 aurel32
            tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1854 460f00c4 aurel32
        } else if (rs != 0 && rt == 0) {
1855 460f00c4 aurel32
            tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1856 460f00c4 aurel32
        } else {
1857 460f00c4 aurel32
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
1858 460f00c4 aurel32
        }
1859 6af0bf9c bellard
        opn = "xor";
1860 6af0bf9c bellard
        break;
1861 460f00c4 aurel32
    }
1862 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1863 460f00c4 aurel32
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1864 460f00c4 aurel32
}
1865 460f00c4 aurel32
1866 460f00c4 aurel32
/* Set on lower than */
1867 460f00c4 aurel32
static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1868 460f00c4 aurel32
{
1869 460f00c4 aurel32
    const char *opn = "slt";
1870 460f00c4 aurel32
    TCGv t0, t1;
1871 460f00c4 aurel32
1872 460f00c4 aurel32
    if (rd == 0) {
1873 460f00c4 aurel32
        /* If no destination, treat it as a NOP. */
1874 460f00c4 aurel32
        MIPS_DEBUG("NOP");
1875 460f00c4 aurel32
        return;
1876 460f00c4 aurel32
    }
1877 460f00c4 aurel32
1878 460f00c4 aurel32
    t0 = tcg_temp_new();
1879 460f00c4 aurel32
    t1 = tcg_temp_new();
1880 460f00c4 aurel32
    gen_load_gpr(t0, rs);
1881 460f00c4 aurel32
    gen_load_gpr(t1, rt);
1882 460f00c4 aurel32
    switch (opc) {
1883 460f00c4 aurel32
    case OPC_SLT:
1884 e68dd28f Aurelien Jarno
        tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
1885 460f00c4 aurel32
        opn = "slt";
1886 6af0bf9c bellard
        break;
1887 460f00c4 aurel32
    case OPC_SLTU:
1888 e68dd28f Aurelien Jarno
        tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
1889 460f00c4 aurel32
        opn = "sltu";
1890 460f00c4 aurel32
        break;
1891 460f00c4 aurel32
    }
1892 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1893 460f00c4 aurel32
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1894 460f00c4 aurel32
    tcg_temp_free(t0);
1895 460f00c4 aurel32
    tcg_temp_free(t1);
1896 460f00c4 aurel32
}
1897 20c4c97c ths
1898 460f00c4 aurel32
/* Shifts */
1899 460f00c4 aurel32
static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1900 460f00c4 aurel32
                       int rd, int rs, int rt)
1901 460f00c4 aurel32
{
1902 460f00c4 aurel32
    const char *opn = "shifts";
1903 460f00c4 aurel32
    TCGv t0, t1;
1904 20c4c97c ths
1905 460f00c4 aurel32
    if (rd == 0) {
1906 460f00c4 aurel32
        /* If no destination, treat it as a NOP.
1907 460f00c4 aurel32
           For add & sub, we must generate the overflow exception when needed. */
1908 460f00c4 aurel32
        MIPS_DEBUG("NOP");
1909 460f00c4 aurel32
        return;
1910 460f00c4 aurel32
    }
1911 460f00c4 aurel32
1912 460f00c4 aurel32
    t0 = tcg_temp_new();
1913 460f00c4 aurel32
    t1 = tcg_temp_new();
1914 460f00c4 aurel32
    gen_load_gpr(t0, rs);
1915 460f00c4 aurel32
    gen_load_gpr(t1, rt);
1916 460f00c4 aurel32
    switch (opc) {
1917 6af0bf9c bellard
    case OPC_SLLV:
1918 78723684 ths
        tcg_gen_andi_tl(t0, t0, 0x1f);
1919 78723684 ths
        tcg_gen_shl_tl(t0, t1, t0);
1920 460f00c4 aurel32
        tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1921 6af0bf9c bellard
        opn = "sllv";
1922 6af0bf9c bellard
        break;
1923 6af0bf9c bellard
    case OPC_SRAV:
1924 78723684 ths
        tcg_gen_andi_tl(t0, t0, 0x1f);
1925 460f00c4 aurel32
        tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1926 6af0bf9c bellard
        opn = "srav";
1927 6af0bf9c bellard
        break;
1928 6af0bf9c bellard
    case OPC_SRLV:
1929 ea63e2c3 Nathan Froyd
        tcg_gen_ext32u_tl(t1, t1);
1930 ea63e2c3 Nathan Froyd
        tcg_gen_andi_tl(t0, t0, 0x1f);
1931 ea63e2c3 Nathan Froyd
        tcg_gen_shr_tl(t0, t1, t0);
1932 ea63e2c3 Nathan Froyd
        tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1933 ea63e2c3 Nathan Froyd
        opn = "srlv";
1934 ea63e2c3 Nathan Froyd
        break;
1935 ea63e2c3 Nathan Froyd
    case OPC_ROTRV:
1936 ea63e2c3 Nathan Froyd
        {
1937 ea63e2c3 Nathan Froyd
            TCGv_i32 t2 = tcg_temp_new_i32();
1938 ea63e2c3 Nathan Froyd
            TCGv_i32 t3 = tcg_temp_new_i32();
1939 ea63e2c3 Nathan Froyd
1940 ea63e2c3 Nathan Froyd
            tcg_gen_trunc_tl_i32(t2, t0);
1941 ea63e2c3 Nathan Froyd
            tcg_gen_trunc_tl_i32(t3, t1);
1942 ea63e2c3 Nathan Froyd
            tcg_gen_andi_i32(t2, t2, 0x1f);
1943 ea63e2c3 Nathan Froyd
            tcg_gen_rotr_i32(t2, t3, t2);
1944 ea63e2c3 Nathan Froyd
            tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1945 ea63e2c3 Nathan Froyd
            tcg_temp_free_i32(t2);
1946 ea63e2c3 Nathan Froyd
            tcg_temp_free_i32(t3);
1947 ea63e2c3 Nathan Froyd
            opn = "rotrv";
1948 5a63bcb2 ths
        }
1949 7a387fff ths
        break;
1950 d26bc211 ths
#if defined(TARGET_MIPS64)
1951 7a387fff ths
    case OPC_DSLLV:
1952 78723684 ths
        tcg_gen_andi_tl(t0, t0, 0x3f);
1953 460f00c4 aurel32
        tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1954 7a387fff ths
        opn = "dsllv";
1955 7a387fff ths
        break;
1956 7a387fff ths
    case OPC_DSRAV:
1957 78723684 ths
        tcg_gen_andi_tl(t0, t0, 0x3f);
1958 460f00c4 aurel32
        tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1959 7a387fff ths
        opn = "dsrav";
1960 7a387fff ths
        break;
1961 7a387fff ths
    case OPC_DSRLV:
1962 ea63e2c3 Nathan Froyd
        tcg_gen_andi_tl(t0, t0, 0x3f);
1963 ea63e2c3 Nathan Froyd
        tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1964 ea63e2c3 Nathan Froyd
        opn = "dsrlv";
1965 ea63e2c3 Nathan Froyd
        break;
1966 ea63e2c3 Nathan Froyd
    case OPC_DROTRV:
1967 ea63e2c3 Nathan Froyd
        tcg_gen_andi_tl(t0, t0, 0x3f);
1968 ea63e2c3 Nathan Froyd
        tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1969 ea63e2c3 Nathan Froyd
        opn = "drotrv";
1970 6af0bf9c bellard
        break;
1971 7a387fff ths
#endif
1972 6af0bf9c bellard
    }
1973 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
1974 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1975 78723684 ths
    tcg_temp_free(t0);
1976 78723684 ths
    tcg_temp_free(t1);
1977 6af0bf9c bellard
}
1978 6af0bf9c bellard
1979 6af0bf9c bellard
/* Arithmetic on HI/LO registers */
1980 7a387fff ths
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1981 6af0bf9c bellard
{
1982 923617a3 ths
    const char *opn = "hilo";
1983 6af0bf9c bellard
1984 6af0bf9c bellard
    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1985 ead9360e ths
        /* Treat as NOP. */
1986 6af0bf9c bellard
        MIPS_DEBUG("NOP");
1987 a1f6684d aurel32
        return;
1988 6af0bf9c bellard
    }
1989 6af0bf9c bellard
    switch (opc) {
1990 6af0bf9c bellard
    case OPC_MFHI:
1991 a1f6684d aurel32
        tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1992 6af0bf9c bellard
        opn = "mfhi";
1993 6af0bf9c bellard
        break;
1994 6af0bf9c bellard
    case OPC_MFLO:
1995 a1f6684d aurel32
        tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1996 6af0bf9c bellard
        opn = "mflo";
1997 6af0bf9c bellard
        break;
1998 6af0bf9c bellard
    case OPC_MTHI:
1999 a1f6684d aurel32
        if (reg != 0)
2000 a1f6684d aurel32
            tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
2001 a1f6684d aurel32
        else
2002 a1f6684d aurel32
            tcg_gen_movi_tl(cpu_HI[0], 0);
2003 6af0bf9c bellard
        opn = "mthi";
2004 6af0bf9c bellard
        break;
2005 6af0bf9c bellard
    case OPC_MTLO:
2006 a1f6684d aurel32
        if (reg != 0)
2007 a1f6684d aurel32
            tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2008 a1f6684d aurel32
        else
2009 a1f6684d aurel32
            tcg_gen_movi_tl(cpu_LO[0], 0);
2010 6af0bf9c bellard
        opn = "mtlo";
2011 6af0bf9c bellard
        break;
2012 6af0bf9c bellard
    }
2013 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
2014 6af0bf9c bellard
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
2015 6af0bf9c bellard
}
2016 6af0bf9c bellard
2017 7a387fff ths
static void gen_muldiv (DisasContext *ctx, uint32_t opc,
2018 6af0bf9c bellard
                        int rs, int rt)
2019 6af0bf9c bellard
{
2020 923617a3 ths
    const char *opn = "mul/div";
2021 d45f89f4 aurel32
    TCGv t0, t1;
2022 d45f89f4 aurel32
2023 d45f89f4 aurel32
    switch (opc) {
2024 d45f89f4 aurel32
    case OPC_DIV:
2025 d45f89f4 aurel32
    case OPC_DIVU:
2026 d45f89f4 aurel32
#if defined(TARGET_MIPS64)
2027 d45f89f4 aurel32
    case OPC_DDIV:
2028 d45f89f4 aurel32
    case OPC_DDIVU:
2029 d45f89f4 aurel32
#endif
2030 d45f89f4 aurel32
        t0 = tcg_temp_local_new();
2031 d45f89f4 aurel32
        t1 = tcg_temp_local_new();
2032 d45f89f4 aurel32
        break;
2033 d45f89f4 aurel32
    default:
2034 d45f89f4 aurel32
        t0 = tcg_temp_new();
2035 d45f89f4 aurel32
        t1 = tcg_temp_new();
2036 d45f89f4 aurel32
        break;
2037 d45f89f4 aurel32
    }
2038 6af0bf9c bellard
2039 78723684 ths
    gen_load_gpr(t0, rs);
2040 78723684 ths
    gen_load_gpr(t1, rt);
2041 6af0bf9c bellard
    switch (opc) {
2042 6af0bf9c bellard
    case OPC_DIV:
2043 48d38ca5 ths
        {
2044 48d38ca5 ths
            int l1 = gen_new_label();
2045 d45f89f4 aurel32
            int l2 = gen_new_label();
2046 48d38ca5 ths
2047 d45f89f4 aurel32
            tcg_gen_ext32s_tl(t0, t0);
2048 d45f89f4 aurel32
            tcg_gen_ext32s_tl(t1, t1);
2049 78723684 ths
            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2050 d45f89f4 aurel32
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2051 d45f89f4 aurel32
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2052 d45f89f4 aurel32
2053 d45f89f4 aurel32
            tcg_gen_mov_tl(cpu_LO[0], t0);
2054 d45f89f4 aurel32
            tcg_gen_movi_tl(cpu_HI[0], 0);
2055 d45f89f4 aurel32
            tcg_gen_br(l1);
2056 d45f89f4 aurel32
            gen_set_label(l2);
2057 d45f89f4 aurel32
            tcg_gen_div_tl(cpu_LO[0], t0, t1);
2058 d45f89f4 aurel32
            tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2059 d45f89f4 aurel32
            tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2060 d45f89f4 aurel32
            tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2061 48d38ca5 ths
            gen_set_label(l1);
2062 48d38ca5 ths
        }
2063 6af0bf9c bellard
        opn = "div";
2064 6af0bf9c bellard
        break;
2065 6af0bf9c bellard
    case OPC_DIVU:
2066 48d38ca5 ths
        {
2067 48d38ca5 ths
            int l1 = gen_new_label();
2068 48d38ca5 ths
2069 0c0ed03b aurel32
            tcg_gen_ext32u_tl(t0, t0);
2070 0c0ed03b aurel32
            tcg_gen_ext32u_tl(t1, t1);
2071 78723684 ths
            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2072 d45f89f4 aurel32
            tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2073 d45f89f4 aurel32
            tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2074 d45f89f4 aurel32
            tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2075 d45f89f4 aurel32
            tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2076 48d38ca5 ths
            gen_set_label(l1);
2077 48d38ca5 ths
        }
2078 6af0bf9c bellard
        opn = "divu";
2079 6af0bf9c bellard
        break;
2080 6af0bf9c bellard
    case OPC_MULT:
2081 214c465f ths
        {
2082 d45f89f4 aurel32
            TCGv_i64 t2 = tcg_temp_new_i64();
2083 d45f89f4 aurel32
            TCGv_i64 t3 = tcg_temp_new_i64();
2084 d45f89f4 aurel32
2085 d45f89f4 aurel32
            tcg_gen_ext_tl_i64(t2, t0);
2086 d45f89f4 aurel32
            tcg_gen_ext_tl_i64(t3, t1);
2087 d45f89f4 aurel32
            tcg_gen_mul_i64(t2, t2, t3);
2088 d45f89f4 aurel32
            tcg_temp_free_i64(t3);
2089 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t0, t2);
2090 d45f89f4 aurel32
            tcg_gen_shri_i64(t2, t2, 32);
2091 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t1, t2);
2092 d45f89f4 aurel32
            tcg_temp_free_i64(t2);
2093 b10fa3c9 aurel32
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
2094 b10fa3c9 aurel32
            tcg_gen_ext32s_tl(cpu_HI[0], t1);
2095 214c465f ths
        }
2096 6af0bf9c bellard
        opn = "mult";
2097 6af0bf9c bellard
        break;
2098 6af0bf9c bellard
    case OPC_MULTU:
2099 214c465f ths
        {
2100 d45f89f4 aurel32
            TCGv_i64 t2 = tcg_temp_new_i64();
2101 d45f89f4 aurel32
            TCGv_i64 t3 = tcg_temp_new_i64();
2102 214c465f ths
2103 78723684 ths
            tcg_gen_ext32u_tl(t0, t0);
2104 78723684 ths
            tcg_gen_ext32u_tl(t1, t1);
2105 d45f89f4 aurel32
            tcg_gen_extu_tl_i64(t2, t0);
2106 d45f89f4 aurel32
            tcg_gen_extu_tl_i64(t3, t1);
2107 d45f89f4 aurel32
            tcg_gen_mul_i64(t2, t2, t3);
2108 d45f89f4 aurel32
            tcg_temp_free_i64(t3);
2109 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t0, t2);
2110 d45f89f4 aurel32
            tcg_gen_shri_i64(t2, t2, 32);
2111 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t1, t2);
2112 d45f89f4 aurel32
            tcg_temp_free_i64(t2);
2113 b10fa3c9 aurel32
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
2114 b10fa3c9 aurel32
            tcg_gen_ext32s_tl(cpu_HI[0], t1);
2115 214c465f ths
        }
2116 6af0bf9c bellard
        opn = "multu";
2117 6af0bf9c bellard
        break;
2118 d26bc211 ths
#if defined(TARGET_MIPS64)
2119 7a387fff ths
    case OPC_DDIV:
2120 48d38ca5 ths
        {
2121 48d38ca5 ths
            int l1 = gen_new_label();
2122 d45f89f4 aurel32
            int l2 = gen_new_label();
2123 48d38ca5 ths
2124 78723684 ths
            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2125 d45f89f4 aurel32
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2126 d45f89f4 aurel32
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2127 d45f89f4 aurel32
            tcg_gen_mov_tl(cpu_LO[0], t0);
2128 d45f89f4 aurel32
            tcg_gen_movi_tl(cpu_HI[0], 0);
2129 d45f89f4 aurel32
            tcg_gen_br(l1);
2130 d45f89f4 aurel32
            gen_set_label(l2);
2131 d45f89f4 aurel32
            tcg_gen_div_i64(cpu_LO[0], t0, t1);
2132 d45f89f4 aurel32
            tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2133 48d38ca5 ths
            gen_set_label(l1);
2134 48d38ca5 ths
        }
2135 7a387fff ths
        opn = "ddiv";
2136 7a387fff ths
        break;
2137 7a387fff ths
    case OPC_DDIVU:
2138 48d38ca5 ths
        {
2139 48d38ca5 ths
            int l1 = gen_new_label();
2140 48d38ca5 ths
2141 78723684 ths
            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2142 b10fa3c9 aurel32
            tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2143 b10fa3c9 aurel32
            tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2144 48d38ca5 ths
            gen_set_label(l1);
2145 48d38ca5 ths
        }
2146 7a387fff ths
        opn = "ddivu";
2147 7a387fff ths
        break;
2148 7a387fff ths
    case OPC_DMULT:
2149 a7812ae4 pbrook
        gen_helper_dmult(t0, t1);
2150 7a387fff ths
        opn = "dmult";
2151 7a387fff ths
        break;
2152 7a387fff ths
    case OPC_DMULTU:
2153 a7812ae4 pbrook
        gen_helper_dmultu(t0, t1);
2154 7a387fff ths
        opn = "dmultu";
2155 7a387fff ths
        break;
2156 7a387fff ths
#endif
2157 6af0bf9c bellard
    case OPC_MADD:
2158 214c465f ths
        {
2159 d45f89f4 aurel32
            TCGv_i64 t2 = tcg_temp_new_i64();
2160 d45f89f4 aurel32
            TCGv_i64 t3 = tcg_temp_new_i64();
2161 d45f89f4 aurel32
2162 d45f89f4 aurel32
            tcg_gen_ext_tl_i64(t2, t0);
2163 d45f89f4 aurel32
            tcg_gen_ext_tl_i64(t3, t1);
2164 d45f89f4 aurel32
            tcg_gen_mul_i64(t2, t2, t3);
2165 d45f89f4 aurel32
            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2166 d45f89f4 aurel32
            tcg_gen_add_i64(t2, t2, t3);
2167 d45f89f4 aurel32
            tcg_temp_free_i64(t3);
2168 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t0, t2);
2169 d45f89f4 aurel32
            tcg_gen_shri_i64(t2, t2, 32);
2170 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t1, t2);
2171 d45f89f4 aurel32
            tcg_temp_free_i64(t2);
2172 b10fa3c9 aurel32
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
2173 98070ce0 Nathan Froyd
            tcg_gen_ext32s_tl(cpu_HI[0], t1);
2174 214c465f ths
        }
2175 6af0bf9c bellard
        opn = "madd";
2176 6af0bf9c bellard
        break;
2177 6af0bf9c bellard
    case OPC_MADDU:
2178 214c465f ths
       {
2179 d45f89f4 aurel32
            TCGv_i64 t2 = tcg_temp_new_i64();
2180 d45f89f4 aurel32
            TCGv_i64 t3 = tcg_temp_new_i64();
2181 214c465f ths
2182 78723684 ths
            tcg_gen_ext32u_tl(t0, t0);
2183 78723684 ths
            tcg_gen_ext32u_tl(t1, t1);
2184 d45f89f4 aurel32
            tcg_gen_extu_tl_i64(t2, t0);
2185 d45f89f4 aurel32
            tcg_gen_extu_tl_i64(t3, t1);
2186 d45f89f4 aurel32
            tcg_gen_mul_i64(t2, t2, t3);
2187 d45f89f4 aurel32
            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2188 d45f89f4 aurel32
            tcg_gen_add_i64(t2, t2, t3);
2189 d45f89f4 aurel32
            tcg_temp_free_i64(t3);
2190 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t0, t2);
2191 d45f89f4 aurel32
            tcg_gen_shri_i64(t2, t2, 32);
2192 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t1, t2);
2193 d45f89f4 aurel32
            tcg_temp_free_i64(t2);
2194 b10fa3c9 aurel32
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
2195 b10fa3c9 aurel32
            tcg_gen_ext32s_tl(cpu_HI[0], t1);
2196 214c465f ths
        }
2197 6af0bf9c bellard
        opn = "maddu";
2198 6af0bf9c bellard
        break;
2199 6af0bf9c bellard
    case OPC_MSUB:
2200 214c465f ths
        {
2201 d45f89f4 aurel32
            TCGv_i64 t2 = tcg_temp_new_i64();
2202 d45f89f4 aurel32
            TCGv_i64 t3 = tcg_temp_new_i64();
2203 d45f89f4 aurel32
2204 d45f89f4 aurel32
            tcg_gen_ext_tl_i64(t2, t0);
2205 d45f89f4 aurel32
            tcg_gen_ext_tl_i64(t3, t1);
2206 d45f89f4 aurel32
            tcg_gen_mul_i64(t2, t2, t3);
2207 d45f89f4 aurel32
            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2208 98070ce0 Nathan Froyd
            tcg_gen_sub_i64(t2, t3, t2);
2209 d45f89f4 aurel32
            tcg_temp_free_i64(t3);
2210 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t0, t2);
2211 d45f89f4 aurel32
            tcg_gen_shri_i64(t2, t2, 32);
2212 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t1, t2);
2213 d45f89f4 aurel32
            tcg_temp_free_i64(t2);
2214 b10fa3c9 aurel32
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
2215 b10fa3c9 aurel32
            tcg_gen_ext32s_tl(cpu_HI[0], t1);
2216 214c465f ths
        }
2217 6af0bf9c bellard
        opn = "msub";
2218 6af0bf9c bellard
        break;
2219 6af0bf9c bellard
    case OPC_MSUBU:
2220 214c465f ths
        {
2221 d45f89f4 aurel32
            TCGv_i64 t2 = tcg_temp_new_i64();
2222 d45f89f4 aurel32
            TCGv_i64 t3 = tcg_temp_new_i64();
2223 214c465f ths
2224 78723684 ths
            tcg_gen_ext32u_tl(t0, t0);
2225 78723684 ths
            tcg_gen_ext32u_tl(t1, t1);
2226 d45f89f4 aurel32
            tcg_gen_extu_tl_i64(t2, t0);
2227 d45f89f4 aurel32
            tcg_gen_extu_tl_i64(t3, t1);
2228 d45f89f4 aurel32
            tcg_gen_mul_i64(t2, t2, t3);
2229 d45f89f4 aurel32
            tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2230 98070ce0 Nathan Froyd
            tcg_gen_sub_i64(t2, t3, t2);
2231 d45f89f4 aurel32
            tcg_temp_free_i64(t3);
2232 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t0, t2);
2233 d45f89f4 aurel32
            tcg_gen_shri_i64(t2, t2, 32);
2234 d45f89f4 aurel32
            tcg_gen_trunc_i64_tl(t1, t2);
2235 d45f89f4 aurel32
            tcg_temp_free_i64(t2);
2236 b10fa3c9 aurel32
            tcg_gen_ext32s_tl(cpu_LO[0], t0);
2237 b10fa3c9 aurel32
            tcg_gen_ext32s_tl(cpu_HI[0], t1);
2238 214c465f ths
        }
2239 6af0bf9c bellard
        opn = "msubu";
2240 6af0bf9c bellard
        break;
2241 6af0bf9c bellard
    default:
2242 923617a3 ths
        MIPS_INVAL(opn);
2243 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
2244 78723684 ths
        goto out;
2245 6af0bf9c bellard
    }
2246 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
2247 6af0bf9c bellard
    MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2248 78723684 ths
 out:
2249 78723684 ths
    tcg_temp_free(t0);
2250 78723684 ths
    tcg_temp_free(t1);
2251 6af0bf9c bellard
}
2252 6af0bf9c bellard
2253 e9c71dd1 ths
static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2254 e9c71dd1 ths
                            int rd, int rs, int rt)
2255 e9c71dd1 ths
{
2256 e9c71dd1 ths
    const char *opn = "mul vr54xx";
2257 f157bfe1 aurel32
    TCGv t0 = tcg_temp_new();
2258 f157bfe1 aurel32
    TCGv t1 = tcg_temp_new();
2259 e9c71dd1 ths
2260 6c5c1e20 ths
    gen_load_gpr(t0, rs);
2261 6c5c1e20 ths
    gen_load_gpr(t1, rt);
2262 e9c71dd1 ths
2263 e9c71dd1 ths
    switch (opc) {
2264 e9c71dd1 ths
    case OPC_VR54XX_MULS:
2265 a7812ae4 pbrook
        gen_helper_muls(t0, t0, t1);
2266 e9c71dd1 ths
        opn = "muls";
2267 6958549d aurel32
        break;
2268 e9c71dd1 ths
    case OPC_VR54XX_MULSU:
2269 a7812ae4 pbrook
        gen_helper_mulsu(t0, t0, t1);
2270 e9c71dd1 ths
        opn = "mulsu";
2271 6958549d aurel32
        break;
2272 e9c71dd1 ths
    case OPC_VR54XX_MACC:
2273 a7812ae4 pbrook
        gen_helper_macc(t0, t0, t1);
2274 e9c71dd1 ths
        opn = "macc";
2275 6958549d aurel32
        break;
2276 e9c71dd1 ths
    case OPC_VR54XX_MACCU:
2277 a7812ae4 pbrook
        gen_helper_maccu(t0, t0, t1);
2278 e9c71dd1 ths
        opn = "maccu";
2279 6958549d aurel32
        break;
2280 e9c71dd1 ths
    case OPC_VR54XX_MSAC:
2281 a7812ae4 pbrook
        gen_helper_msac(t0, t0, t1);
2282 e9c71dd1 ths
        opn = "msac";
2283 6958549d aurel32
        break;
2284 e9c71dd1 ths
    case OPC_VR54XX_MSACU:
2285 a7812ae4 pbrook
        gen_helper_msacu(t0, t0, t1);
2286 e9c71dd1 ths
        opn = "msacu";
2287 6958549d aurel32
        break;
2288 e9c71dd1 ths
    case OPC_VR54XX_MULHI:
2289 a7812ae4 pbrook
        gen_helper_mulhi(t0, t0, t1);
2290 e9c71dd1 ths
        opn = "mulhi";
2291 6958549d aurel32
        break;
2292 e9c71dd1 ths
    case OPC_VR54XX_MULHIU:
2293 a7812ae4 pbrook
        gen_helper_mulhiu(t0, t0, t1);
2294 e9c71dd1 ths
        opn = "mulhiu";
2295 6958549d aurel32
        break;
2296 e9c71dd1 ths
    case OPC_VR54XX_MULSHI:
2297 a7812ae4 pbrook
        gen_helper_mulshi(t0, t0, t1);
2298 e9c71dd1 ths
        opn = "mulshi";
2299 6958549d aurel32
        break;
2300 e9c71dd1 ths
    case OPC_VR54XX_MULSHIU:
2301 a7812ae4 pbrook
        gen_helper_mulshiu(t0, t0, t1);
2302 e9c71dd1 ths
        opn = "mulshiu";
2303 6958549d aurel32
        break;
2304 e9c71dd1 ths
    case OPC_VR54XX_MACCHI:
2305 a7812ae4 pbrook
        gen_helper_macchi(t0, t0, t1);
2306 e9c71dd1 ths
        opn = "macchi";
2307 6958549d aurel32
        break;
2308 e9c71dd1 ths
    case OPC_VR54XX_MACCHIU:
2309 a7812ae4 pbrook
        gen_helper_macchiu(t0, t0, t1);
2310 e9c71dd1 ths
        opn = "macchiu";
2311 6958549d aurel32
        break;
2312 e9c71dd1 ths
    case OPC_VR54XX_MSACHI:
2313 a7812ae4 pbrook
        gen_helper_msachi(t0, t0, t1);
2314 e9c71dd1 ths
        opn = "msachi";
2315 6958549d aurel32
        break;
2316 e9c71dd1 ths
    case OPC_VR54XX_MSACHIU:
2317 a7812ae4 pbrook
        gen_helper_msachiu(t0, t0, t1);
2318 e9c71dd1 ths
        opn = "msachiu";
2319 6958549d aurel32
        break;
2320 e9c71dd1 ths
    default:
2321 e9c71dd1 ths
        MIPS_INVAL("mul vr54xx");
2322 e9c71dd1 ths
        generate_exception(ctx, EXCP_RI);
2323 6c5c1e20 ths
        goto out;
2324 e9c71dd1 ths
    }
2325 6c5c1e20 ths
    gen_store_gpr(t0, rd);
2326 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
2327 e9c71dd1 ths
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2328 6c5c1e20 ths
2329 6c5c1e20 ths
 out:
2330 6c5c1e20 ths
    tcg_temp_free(t0);
2331 6c5c1e20 ths
    tcg_temp_free(t1);
2332 e9c71dd1 ths
}
2333 e9c71dd1 ths
2334 7a387fff ths
static void gen_cl (DisasContext *ctx, uint32_t opc,
2335 6af0bf9c bellard
                    int rd, int rs)
2336 6af0bf9c bellard
{
2337 923617a3 ths
    const char *opn = "CLx";
2338 20e1fb52 aurel32
    TCGv t0;
2339 6c5c1e20 ths
2340 6af0bf9c bellard
    if (rd == 0) {
2341 ead9360e ths
        /* Treat as NOP. */
2342 6af0bf9c bellard
        MIPS_DEBUG("NOP");
2343 20e1fb52 aurel32
        return;
2344 6af0bf9c bellard
    }
2345 20e1fb52 aurel32
    t0 = tcg_temp_new();
2346 6c5c1e20 ths
    gen_load_gpr(t0, rs);
2347 6af0bf9c bellard
    switch (opc) {
2348 6af0bf9c bellard
    case OPC_CLO:
2349 20e1fb52 aurel32
        gen_helper_clo(cpu_gpr[rd], t0);
2350 6af0bf9c bellard
        opn = "clo";
2351 6af0bf9c bellard
        break;
2352 6af0bf9c bellard
    case OPC_CLZ:
2353 20e1fb52 aurel32
        gen_helper_clz(cpu_gpr[rd], t0);
2354 6af0bf9c bellard
        opn = "clz";
2355 6af0bf9c bellard
        break;
2356 d26bc211 ths
#if defined(TARGET_MIPS64)
2357 7a387fff ths
    case OPC_DCLO:
2358 20e1fb52 aurel32
        gen_helper_dclo(cpu_gpr[rd], t0);
2359 7a387fff ths
        opn = "dclo";
2360 7a387fff ths
        break;
2361 7a387fff ths
    case OPC_DCLZ:
2362 20e1fb52 aurel32
        gen_helper_dclz(cpu_gpr[rd], t0);
2363 7a387fff ths
        opn = "dclz";
2364 7a387fff ths
        break;
2365 7a387fff ths
#endif
2366 6af0bf9c bellard
    }
2367 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
2368 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2369 6c5c1e20 ths
    tcg_temp_free(t0);
2370 6af0bf9c bellard
}
2371 6af0bf9c bellard
2372 161f85e6 Aurelien Jarno
/* Godson integer instructions */
2373 161f85e6 Aurelien Jarno
static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
2374 161f85e6 Aurelien Jarno
                                int rd, int rs, int rt)
2375 161f85e6 Aurelien Jarno
{
2376 161f85e6 Aurelien Jarno
    const char *opn = "loongson";
2377 161f85e6 Aurelien Jarno
    TCGv t0, t1;
2378 161f85e6 Aurelien Jarno
2379 161f85e6 Aurelien Jarno
    if (rd == 0) {
2380 161f85e6 Aurelien Jarno
        /* Treat as NOP. */
2381 161f85e6 Aurelien Jarno
        MIPS_DEBUG("NOP");
2382 161f85e6 Aurelien Jarno
        return;
2383 161f85e6 Aurelien Jarno
    }
2384 161f85e6 Aurelien Jarno
2385 161f85e6 Aurelien Jarno
    switch (opc) {
2386 161f85e6 Aurelien Jarno
    case OPC_MULT_G_2E:
2387 161f85e6 Aurelien Jarno
    case OPC_MULT_G_2F:
2388 161f85e6 Aurelien Jarno
    case OPC_MULTU_G_2E:
2389 161f85e6 Aurelien Jarno
    case OPC_MULTU_G_2F:
2390 161f85e6 Aurelien Jarno
#if defined(TARGET_MIPS64)
2391 161f85e6 Aurelien Jarno
    case OPC_DMULT_G_2E:
2392 161f85e6 Aurelien Jarno
    case OPC_DMULT_G_2F:
2393 161f85e6 Aurelien Jarno
    case OPC_DMULTU_G_2E:
2394 161f85e6 Aurelien Jarno
    case OPC_DMULTU_G_2F:
2395 161f85e6 Aurelien Jarno
#endif
2396 161f85e6 Aurelien Jarno
        t0 = tcg_temp_new();
2397 161f85e6 Aurelien Jarno
        t1 = tcg_temp_new();
2398 161f85e6 Aurelien Jarno
        break;
2399 161f85e6 Aurelien Jarno
    default:
2400 161f85e6 Aurelien Jarno
        t0 = tcg_temp_local_new();
2401 161f85e6 Aurelien Jarno
        t1 = tcg_temp_local_new();
2402 161f85e6 Aurelien Jarno
        break;
2403 161f85e6 Aurelien Jarno
    }
2404 161f85e6 Aurelien Jarno
2405 161f85e6 Aurelien Jarno
    gen_load_gpr(t0, rs);
2406 161f85e6 Aurelien Jarno
    gen_load_gpr(t1, rt);
2407 161f85e6 Aurelien Jarno
2408 161f85e6 Aurelien Jarno
    switch (opc) {
2409 161f85e6 Aurelien Jarno
    case OPC_MULT_G_2E:
2410 161f85e6 Aurelien Jarno
    case OPC_MULT_G_2F:
2411 161f85e6 Aurelien Jarno
        tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2412 161f85e6 Aurelien Jarno
        tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2413 161f85e6 Aurelien Jarno
        opn = "mult.g";
2414 161f85e6 Aurelien Jarno
        break;
2415 161f85e6 Aurelien Jarno
    case OPC_MULTU_G_2E:
2416 161f85e6 Aurelien Jarno
    case OPC_MULTU_G_2F:
2417 161f85e6 Aurelien Jarno
        tcg_gen_ext32u_tl(t0, t0);
2418 161f85e6 Aurelien Jarno
        tcg_gen_ext32u_tl(t1, t1);
2419 161f85e6 Aurelien Jarno
        tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2420 161f85e6 Aurelien Jarno
        tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2421 161f85e6 Aurelien Jarno
        opn = "multu.g";
2422 161f85e6 Aurelien Jarno
        break;
2423 161f85e6 Aurelien Jarno
    case OPC_DIV_G_2E:
2424 161f85e6 Aurelien Jarno
    case OPC_DIV_G_2F:
2425 161f85e6 Aurelien Jarno
        {
2426 161f85e6 Aurelien Jarno
            int l1 = gen_new_label();
2427 161f85e6 Aurelien Jarno
            int l2 = gen_new_label();
2428 161f85e6 Aurelien Jarno
            int l3 = gen_new_label();
2429 161f85e6 Aurelien Jarno
            tcg_gen_ext32s_tl(t0, t0);
2430 161f85e6 Aurelien Jarno
            tcg_gen_ext32s_tl(t1, t1);
2431 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2432 161f85e6 Aurelien Jarno
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
2433 161f85e6 Aurelien Jarno
            tcg_gen_br(l3);
2434 161f85e6 Aurelien Jarno
            gen_set_label(l1);
2435 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2436 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2437 161f85e6 Aurelien Jarno
            tcg_gen_mov_tl(cpu_gpr[rd], t0);
2438 161f85e6 Aurelien Jarno
            tcg_gen_br(l3);
2439 161f85e6 Aurelien Jarno
            gen_set_label(l2);
2440 161f85e6 Aurelien Jarno
            tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2441 161f85e6 Aurelien Jarno
            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2442 161f85e6 Aurelien Jarno
            gen_set_label(l3);
2443 161f85e6 Aurelien Jarno
        }
2444 161f85e6 Aurelien Jarno
        opn = "div.g";
2445 161f85e6 Aurelien Jarno
        break;
2446 161f85e6 Aurelien Jarno
    case OPC_DIVU_G_2E:
2447 161f85e6 Aurelien Jarno
    case OPC_DIVU_G_2F:
2448 161f85e6 Aurelien Jarno
        {
2449 161f85e6 Aurelien Jarno
            int l1 = gen_new_label();
2450 161f85e6 Aurelien Jarno
            int l2 = gen_new_label();
2451 161f85e6 Aurelien Jarno
            tcg_gen_ext32u_tl(t0, t0);
2452 161f85e6 Aurelien Jarno
            tcg_gen_ext32u_tl(t1, t1);
2453 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2454 161f85e6 Aurelien Jarno
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
2455 161f85e6 Aurelien Jarno
            tcg_gen_br(l2);
2456 161f85e6 Aurelien Jarno
            gen_set_label(l1);
2457 161f85e6 Aurelien Jarno
            tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2458 161f85e6 Aurelien Jarno
            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2459 161f85e6 Aurelien Jarno
            gen_set_label(l2);
2460 161f85e6 Aurelien Jarno
        }
2461 161f85e6 Aurelien Jarno
        opn = "divu.g";
2462 161f85e6 Aurelien Jarno
        break;
2463 161f85e6 Aurelien Jarno
    case OPC_MOD_G_2E:
2464 161f85e6 Aurelien Jarno
    case OPC_MOD_G_2F:
2465 161f85e6 Aurelien Jarno
        {
2466 161f85e6 Aurelien Jarno
            int l1 = gen_new_label();
2467 161f85e6 Aurelien Jarno
            int l2 = gen_new_label();
2468 161f85e6 Aurelien Jarno
            int l3 = gen_new_label();
2469 161f85e6 Aurelien Jarno
            tcg_gen_ext32u_tl(t0, t0);
2470 161f85e6 Aurelien Jarno
            tcg_gen_ext32u_tl(t1, t1);
2471 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2472 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2473 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2474 161f85e6 Aurelien Jarno
            gen_set_label(l1);
2475 161f85e6 Aurelien Jarno
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
2476 161f85e6 Aurelien Jarno
            tcg_gen_br(l3);
2477 161f85e6 Aurelien Jarno
            gen_set_label(l2);
2478 161f85e6 Aurelien Jarno
            tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2479 161f85e6 Aurelien Jarno
            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2480 161f85e6 Aurelien Jarno
            gen_set_label(l3);
2481 161f85e6 Aurelien Jarno
        }
2482 161f85e6 Aurelien Jarno
        opn = "mod.g";
2483 161f85e6 Aurelien Jarno
        break;
2484 161f85e6 Aurelien Jarno
    case OPC_MODU_G_2E:
2485 161f85e6 Aurelien Jarno
    case OPC_MODU_G_2F:
2486 161f85e6 Aurelien Jarno
        {
2487 161f85e6 Aurelien Jarno
            int l1 = gen_new_label();
2488 161f85e6 Aurelien Jarno
            int l2 = gen_new_label();
2489 161f85e6 Aurelien Jarno
            tcg_gen_ext32u_tl(t0, t0);
2490 161f85e6 Aurelien Jarno
            tcg_gen_ext32u_tl(t1, t1);
2491 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2492 161f85e6 Aurelien Jarno
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
2493 161f85e6 Aurelien Jarno
            tcg_gen_br(l2);
2494 161f85e6 Aurelien Jarno
            gen_set_label(l1);
2495 161f85e6 Aurelien Jarno
            tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2496 161f85e6 Aurelien Jarno
            tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2497 161f85e6 Aurelien Jarno
            gen_set_label(l2);
2498 161f85e6 Aurelien Jarno
        }
2499 161f85e6 Aurelien Jarno
        opn = "modu.g";
2500 161f85e6 Aurelien Jarno
        break;
2501 161f85e6 Aurelien Jarno
#if defined(TARGET_MIPS64)
2502 161f85e6 Aurelien Jarno
    case OPC_DMULT_G_2E:
2503 161f85e6 Aurelien Jarno
    case OPC_DMULT_G_2F:
2504 161f85e6 Aurelien Jarno
        tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2505 161f85e6 Aurelien Jarno
        opn = "dmult.g";
2506 161f85e6 Aurelien Jarno
        break;
2507 161f85e6 Aurelien Jarno
    case OPC_DMULTU_G_2E:
2508 161f85e6 Aurelien Jarno
    case OPC_DMULTU_G_2F:
2509 161f85e6 Aurelien Jarno
        tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2510 161f85e6 Aurelien Jarno
        opn = "dmultu.g";
2511 161f85e6 Aurelien Jarno
        break;
2512 161f85e6 Aurelien Jarno
    case OPC_DDIV_G_2E:
2513 161f85e6 Aurelien Jarno
    case OPC_DDIV_G_2F:
2514 161f85e6 Aurelien Jarno
        {
2515 161f85e6 Aurelien Jarno
            int l1 = gen_new_label();
2516 161f85e6 Aurelien Jarno
            int l2 = gen_new_label();
2517 161f85e6 Aurelien Jarno
            int l3 = gen_new_label();
2518 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2519 161f85e6 Aurelien Jarno
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
2520 161f85e6 Aurelien Jarno
            tcg_gen_br(l3);
2521 161f85e6 Aurelien Jarno
            gen_set_label(l1);
2522 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2523 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2524 161f85e6 Aurelien Jarno
            tcg_gen_mov_tl(cpu_gpr[rd], t0);
2525 161f85e6 Aurelien Jarno
            tcg_gen_br(l3);
2526 161f85e6 Aurelien Jarno
            gen_set_label(l2);
2527 161f85e6 Aurelien Jarno
            tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2528 161f85e6 Aurelien Jarno
            gen_set_label(l3);
2529 161f85e6 Aurelien Jarno
        }
2530 161f85e6 Aurelien Jarno
        opn = "ddiv.g";
2531 161f85e6 Aurelien Jarno
        break;
2532 161f85e6 Aurelien Jarno
    case OPC_DDIVU_G_2E:
2533 161f85e6 Aurelien Jarno
    case OPC_DDIVU_G_2F:
2534 161f85e6 Aurelien Jarno
        {
2535 161f85e6 Aurelien Jarno
            int l1 = gen_new_label();
2536 161f85e6 Aurelien Jarno
            int l2 = gen_new_label();
2537 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2538 161f85e6 Aurelien Jarno
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
2539 161f85e6 Aurelien Jarno
            tcg_gen_br(l2);
2540 161f85e6 Aurelien Jarno
            gen_set_label(l1);
2541 161f85e6 Aurelien Jarno
            tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2542 161f85e6 Aurelien Jarno
            gen_set_label(l2);
2543 161f85e6 Aurelien Jarno
        }
2544 161f85e6 Aurelien Jarno
        opn = "ddivu.g";
2545 161f85e6 Aurelien Jarno
        break;
2546 161f85e6 Aurelien Jarno
    case OPC_DMOD_G_2E:
2547 161f85e6 Aurelien Jarno
    case OPC_DMOD_G_2F:
2548 161f85e6 Aurelien Jarno
        {
2549 161f85e6 Aurelien Jarno
            int l1 = gen_new_label();
2550 161f85e6 Aurelien Jarno
            int l2 = gen_new_label();
2551 161f85e6 Aurelien Jarno
            int l3 = gen_new_label();
2552 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2553 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2554 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2555 161f85e6 Aurelien Jarno
            gen_set_label(l1);
2556 161f85e6 Aurelien Jarno
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
2557 161f85e6 Aurelien Jarno
            tcg_gen_br(l3);
2558 161f85e6 Aurelien Jarno
            gen_set_label(l2);
2559 161f85e6 Aurelien Jarno
            tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2560 161f85e6 Aurelien Jarno
            gen_set_label(l3);
2561 161f85e6 Aurelien Jarno
        }
2562 161f85e6 Aurelien Jarno
        opn = "dmod.g";
2563 161f85e6 Aurelien Jarno
        break;
2564 161f85e6 Aurelien Jarno
    case OPC_DMODU_G_2E:
2565 161f85e6 Aurelien Jarno
    case OPC_DMODU_G_2F:
2566 161f85e6 Aurelien Jarno
        {
2567 161f85e6 Aurelien Jarno
            int l1 = gen_new_label();
2568 161f85e6 Aurelien Jarno
            int l2 = gen_new_label();
2569 161f85e6 Aurelien Jarno
            tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2570 161f85e6 Aurelien Jarno
            tcg_gen_movi_tl(cpu_gpr[rd], 0);
2571 161f85e6 Aurelien Jarno
            tcg_gen_br(l2);
2572 161f85e6 Aurelien Jarno
            gen_set_label(l1);
2573 161f85e6 Aurelien Jarno
            tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2574 161f85e6 Aurelien Jarno
            gen_set_label(l2);
2575 161f85e6 Aurelien Jarno
        }
2576 161f85e6 Aurelien Jarno
        opn = "dmodu.g";
2577 161f85e6 Aurelien Jarno
        break;
2578 161f85e6 Aurelien Jarno
#endif
2579 161f85e6 Aurelien Jarno
    }
2580 161f85e6 Aurelien Jarno
2581 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
2582 161f85e6 Aurelien Jarno
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2583 161f85e6 Aurelien Jarno
    tcg_temp_free(t0);
2584 161f85e6 Aurelien Jarno
    tcg_temp_free(t1);
2585 161f85e6 Aurelien Jarno
}
2586 161f85e6 Aurelien Jarno
2587 6af0bf9c bellard
/* Traps */
2588 7a387fff ths
static void gen_trap (DisasContext *ctx, uint32_t opc,
2589 6af0bf9c bellard
                      int rs, int rt, int16_t imm)
2590 6af0bf9c bellard
{
2591 6af0bf9c bellard
    int cond;
2592 cdc0faa6 aurel32
    TCGv t0 = tcg_temp_new();
2593 1ba74fb8 aurel32
    TCGv t1 = tcg_temp_new();
2594 6af0bf9c bellard
2595 6af0bf9c bellard
    cond = 0;
2596 6af0bf9c bellard
    /* Load needed operands */
2597 6af0bf9c bellard
    switch (opc) {
2598 6af0bf9c bellard
    case OPC_TEQ:
2599 6af0bf9c bellard
    case OPC_TGE:
2600 6af0bf9c bellard
    case OPC_TGEU:
2601 6af0bf9c bellard
    case OPC_TLT:
2602 6af0bf9c bellard
    case OPC_TLTU:
2603 6af0bf9c bellard
    case OPC_TNE:
2604 6af0bf9c bellard
        /* Compare two registers */
2605 6af0bf9c bellard
        if (rs != rt) {
2606 be24bb4f ths
            gen_load_gpr(t0, rs);
2607 be24bb4f ths
            gen_load_gpr(t1, rt);
2608 6af0bf9c bellard
            cond = 1;
2609 6af0bf9c bellard
        }
2610 179e32bb ths
        break;
2611 6af0bf9c bellard
    case OPC_TEQI:
2612 6af0bf9c bellard
    case OPC_TGEI:
2613 6af0bf9c bellard
    case OPC_TGEIU:
2614 6af0bf9c bellard
    case OPC_TLTI:
2615 6af0bf9c bellard
    case OPC_TLTIU:
2616 6af0bf9c bellard
    case OPC_TNEI:
2617 6af0bf9c bellard
        /* Compare register to immediate */
2618 6af0bf9c bellard
        if (rs != 0 || imm != 0) {
2619 be24bb4f ths
            gen_load_gpr(t0, rs);
2620 be24bb4f ths
            tcg_gen_movi_tl(t1, (int32_t)imm);
2621 6af0bf9c bellard
            cond = 1;
2622 6af0bf9c bellard
        }
2623 6af0bf9c bellard
        break;
2624 6af0bf9c bellard
    }
2625 6af0bf9c bellard
    if (cond == 0) {
2626 6af0bf9c bellard
        switch (opc) {
2627 6af0bf9c bellard
        case OPC_TEQ:   /* rs == rs */
2628 6af0bf9c bellard
        case OPC_TEQI:  /* r0 == 0  */
2629 6af0bf9c bellard
        case OPC_TGE:   /* rs >= rs */
2630 6af0bf9c bellard
        case OPC_TGEI:  /* r0 >= 0  */
2631 6af0bf9c bellard
        case OPC_TGEU:  /* rs >= rs unsigned */
2632 6af0bf9c bellard
        case OPC_TGEIU: /* r0 >= 0  unsigned */
2633 6af0bf9c bellard
            /* Always trap */
2634 cdc0faa6 aurel32
            generate_exception(ctx, EXCP_TRAP);
2635 6af0bf9c bellard
            break;
2636 6af0bf9c bellard
        case OPC_TLT:   /* rs < rs           */
2637 6af0bf9c bellard
        case OPC_TLTI:  /* r0 < 0            */
2638 6af0bf9c bellard
        case OPC_TLTU:  /* rs < rs unsigned  */
2639 6af0bf9c bellard
        case OPC_TLTIU: /* r0 < 0  unsigned  */
2640 6af0bf9c bellard
        case OPC_TNE:   /* rs != rs          */
2641 6af0bf9c bellard
        case OPC_TNEI:  /* r0 != 0           */
2642 ead9360e ths
            /* Never trap: treat as NOP. */
2643 cdc0faa6 aurel32
            break;
2644 6af0bf9c bellard
        }
2645 6af0bf9c bellard
    } else {
2646 cdc0faa6 aurel32
        int l1 = gen_new_label();
2647 cdc0faa6 aurel32
2648 6af0bf9c bellard
        switch (opc) {
2649 6af0bf9c bellard
        case OPC_TEQ:
2650 6af0bf9c bellard
        case OPC_TEQI:
2651 cdc0faa6 aurel32
            tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2652 6af0bf9c bellard
            break;
2653 6af0bf9c bellard
        case OPC_TGE:
2654 6af0bf9c bellard
        case OPC_TGEI:
2655 cdc0faa6 aurel32
            tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2656 6af0bf9c bellard
            break;
2657 6af0bf9c bellard
        case OPC_TGEU:
2658 6af0bf9c bellard
        case OPC_TGEIU:
2659 cdc0faa6 aurel32
            tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2660 6af0bf9c bellard
            break;
2661 6af0bf9c bellard
        case OPC_TLT:
2662 6af0bf9c bellard
        case OPC_TLTI:
2663 cdc0faa6 aurel32
            tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2664 6af0bf9c bellard
            break;
2665 6af0bf9c bellard
        case OPC_TLTU:
2666 6af0bf9c bellard
        case OPC_TLTIU:
2667 cdc0faa6 aurel32
            tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2668 6af0bf9c bellard
            break;
2669 6af0bf9c bellard
        case OPC_TNE:
2670 6af0bf9c bellard
        case OPC_TNEI:
2671 cdc0faa6 aurel32
            tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2672 6af0bf9c bellard
            break;
2673 6af0bf9c bellard
        }
2674 cdc0faa6 aurel32
        generate_exception(ctx, EXCP_TRAP);
2675 08ba7963 ths
        gen_set_label(l1);
2676 08ba7963 ths
    }
2677 be24bb4f ths
    tcg_temp_free(t0);
2678 be24bb4f ths
    tcg_temp_free(t1);
2679 6af0bf9c bellard
}
2680 6af0bf9c bellard
2681 356265ae ths
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2682 c53be334 bellard
{
2683 6e256c93 bellard
    TranslationBlock *tb;
2684 6e256c93 bellard
    tb = ctx->tb;
2685 7b270ef2 Nathan Froyd
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2686 7b270ef2 Nathan Froyd
        likely(!ctx->singlestep_enabled)) {
2687 57fec1fe bellard
        tcg_gen_goto_tb(n);
2688 9b9e4393 ths
        gen_save_pc(dest);
2689 57fec1fe bellard
        tcg_gen_exit_tb((long)tb + n);
2690 6e256c93 bellard
    } else {
2691 9b9e4393 ths
        gen_save_pc(dest);
2692 7b270ef2 Nathan Froyd
        if (ctx->singlestep_enabled) {
2693 7b270ef2 Nathan Froyd
            save_cpu_state(ctx, 0);
2694 7b270ef2 Nathan Froyd
            gen_helper_0i(raise_exception, EXCP_DEBUG);
2695 7b270ef2 Nathan Froyd
        }
2696 57fec1fe bellard
        tcg_gen_exit_tb(0);
2697 6e256c93 bellard
    }
2698 c53be334 bellard
}
2699 c53be334 bellard
2700 6af0bf9c bellard
/* Branches (before delay slot) */
2701 7a387fff ths
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2702 7dca4ad0 Nathan Froyd
                                int insn_bytes,
2703 6af0bf9c bellard
                                int rs, int rt, int32_t offset)
2704 6af0bf9c bellard
{
2705 d077b6f7 ths
    target_ulong btgt = -1;
2706 3ad4bb2d ths
    int blink = 0;
2707 2fdbad25 aurel32
    int bcond_compute = 0;
2708 1ba74fb8 aurel32
    TCGv t0 = tcg_temp_new();
2709 1ba74fb8 aurel32
    TCGv t1 = tcg_temp_new();
2710 3ad4bb2d ths
2711 3ad4bb2d ths
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
2712 923617a3 ths
#ifdef MIPS_DEBUG_DISAS
2713 d12d51d5 aliguori
        LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2714 923617a3 ths
#endif
2715 3ad4bb2d ths
        generate_exception(ctx, EXCP_RI);
2716 6c5c1e20 ths
        goto out;
2717 3ad4bb2d ths
    }
2718 6af0bf9c bellard
2719 6af0bf9c bellard
    /* Load needed operands */
2720 6af0bf9c bellard
    switch (opc) {
2721 6af0bf9c bellard
    case OPC_BEQ:
2722 6af0bf9c bellard
    case OPC_BEQL:
2723 6af0bf9c bellard
    case OPC_BNE:
2724 6af0bf9c bellard
    case OPC_BNEL:
2725 6af0bf9c bellard
        /* Compare two registers */
2726 6af0bf9c bellard
        if (rs != rt) {
2727 6c5c1e20 ths
            gen_load_gpr(t0, rs);
2728 6c5c1e20 ths
            gen_load_gpr(t1, rt);
2729 2fdbad25 aurel32
            bcond_compute = 1;
2730 6af0bf9c bellard
        }
2731 7dca4ad0 Nathan Froyd
        btgt = ctx->pc + insn_bytes + offset;
2732 6af0bf9c bellard
        break;
2733 6af0bf9c bellard
    case OPC_BGEZ:
2734 6af0bf9c bellard
    case OPC_BGEZAL:
2735 3c824109 Nathan Froyd
    case OPC_BGEZALS:
2736 6af0bf9c bellard
    case OPC_BGEZALL:
2737 6af0bf9c bellard
    case OPC_BGEZL:
2738 6af0bf9c bellard
    case OPC_BGTZ:
2739 6af0bf9c bellard
    case OPC_BGTZL:
2740 6af0bf9c bellard
    case OPC_BLEZ:
2741 6af0bf9c bellard
    case OPC_BLEZL:
2742 6af0bf9c bellard
    case OPC_BLTZ:
2743 6af0bf9c bellard
    case OPC_BLTZAL:
2744 3c824109 Nathan Froyd
    case OPC_BLTZALS:
2745 6af0bf9c bellard
    case OPC_BLTZALL:
2746 6af0bf9c bellard
    case OPC_BLTZL:
2747 6af0bf9c bellard
        /* Compare to zero */
2748 6af0bf9c bellard
        if (rs != 0) {
2749 6c5c1e20 ths
            gen_load_gpr(t0, rs);
2750 2fdbad25 aurel32
            bcond_compute = 1;
2751 6af0bf9c bellard
        }
2752 7dca4ad0 Nathan Froyd
        btgt = ctx->pc + insn_bytes + offset;
2753 6af0bf9c bellard
        break;
2754 6af0bf9c bellard
    case OPC_J:
2755 6af0bf9c bellard
    case OPC_JAL:
2756 364d4831 Nathan Froyd
    case OPC_JALX:
2757 620e48f6 Nathan Froyd
    case OPC_JALS:
2758 620e48f6 Nathan Froyd
    case OPC_JALXS:
2759 6af0bf9c bellard
        /* Jump to immediate */
2760 7dca4ad0 Nathan Froyd
        btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
2761 6af0bf9c bellard
        break;
2762 6af0bf9c bellard
    case OPC_JR:
2763 6af0bf9c bellard
    case OPC_JALR:
2764 364d4831 Nathan Froyd
    case OPC_JALRC:
2765 620e48f6 Nathan Froyd
    case OPC_JALRS:
2766 6af0bf9c bellard
        /* Jump to register */
2767 7a387fff ths
        if (offset != 0 && offset != 16) {
2768 7a387fff ths
            /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2769 cbeb0857 ths
               others are reserved. */
2770 923617a3 ths
            MIPS_INVAL("jump hint");
2771 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
2772 6c5c1e20 ths
            goto out;
2773 6af0bf9c bellard
        }
2774 d077b6f7 ths
        gen_load_gpr(btarget, rs);
2775 6af0bf9c bellard
        break;
2776 6af0bf9c bellard
    default:
2777 6af0bf9c bellard
        MIPS_INVAL("branch/jump");
2778 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
2779 6c5c1e20 ths
        goto out;
2780 6af0bf9c bellard
    }
2781 2fdbad25 aurel32
    if (bcond_compute == 0) {
2782 6af0bf9c bellard
        /* No condition to be computed */
2783 6af0bf9c bellard
        switch (opc) {
2784 6af0bf9c bellard
        case OPC_BEQ:     /* rx == rx        */
2785 6af0bf9c bellard
        case OPC_BEQL:    /* rx == rx likely */
2786 6af0bf9c bellard
        case OPC_BGEZ:    /* 0 >= 0          */
2787 6af0bf9c bellard
        case OPC_BGEZL:   /* 0 >= 0 likely   */
2788 6af0bf9c bellard
        case OPC_BLEZ:    /* 0 <= 0          */
2789 6af0bf9c bellard
        case OPC_BLEZL:   /* 0 <= 0 likely   */
2790 6af0bf9c bellard
            /* Always take */
2791 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
2792 6af0bf9c bellard
            MIPS_DEBUG("balways");
2793 6af0bf9c bellard
            break;
2794 3c824109 Nathan Froyd
        case OPC_BGEZALS:
2795 6af0bf9c bellard
        case OPC_BGEZAL:  /* 0 >= 0          */
2796 6af0bf9c bellard
        case OPC_BGEZALL: /* 0 >= 0 likely   */
2797 3c824109 Nathan Froyd
            ctx->hflags |= (opc == OPC_BGEZALS
2798 3c824109 Nathan Froyd
                            ? MIPS_HFLAG_BDS16
2799 3c824109 Nathan Froyd
                            : MIPS_HFLAG_BDS32);
2800 6af0bf9c bellard
            /* Always take and link */
2801 6af0bf9c bellard
            blink = 31;
2802 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
2803 6af0bf9c bellard
            MIPS_DEBUG("balways and link");
2804 6af0bf9c bellard
            break;
2805 6af0bf9c bellard
        case OPC_BNE:     /* rx != rx        */
2806 6af0bf9c bellard
        case OPC_BGTZ:    /* 0 > 0           */
2807 6af0bf9c bellard
        case OPC_BLTZ:    /* 0 < 0           */
2808 ead9360e ths
            /* Treat as NOP. */
2809 6af0bf9c bellard
            MIPS_DEBUG("bnever (NOP)");
2810 6c5c1e20 ths
            goto out;
2811 3c824109 Nathan Froyd
        case OPC_BLTZALS:
2812 eeef26cd bellard
        case OPC_BLTZAL:  /* 0 < 0           */
2813 3c824109 Nathan Froyd
            ctx->hflags |= (opc == OPC_BLTZALS
2814 3c824109 Nathan Froyd
                            ? MIPS_HFLAG_BDS16
2815 3c824109 Nathan Froyd
                            : MIPS_HFLAG_BDS32);
2816 3c824109 Nathan Froyd
            /* Handle as an unconditional branch to get correct delay
2817 3c824109 Nathan Froyd
               slot checking.  */
2818 3c824109 Nathan Froyd
            blink = 31;
2819 3c824109 Nathan Froyd
            btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
2820 3c824109 Nathan Froyd
            ctx->hflags |= MIPS_HFLAG_B;
2821 9898128f ths
            MIPS_DEBUG("bnever and link");
2822 3c824109 Nathan Froyd
            break;
2823 eeef26cd bellard
        case OPC_BLTZALL: /* 0 < 0 likely */
2824 1ba74fb8 aurel32
            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2825 9898128f ths
            /* Skip the instruction in the delay slot */
2826 9898128f ths
            MIPS_DEBUG("bnever, link and skip");
2827 9898128f ths
            ctx->pc += 4;
2828 6c5c1e20 ths
            goto out;
2829 6af0bf9c bellard
        case OPC_BNEL:    /* rx != rx likely */
2830 6af0bf9c bellard
        case OPC_BGTZL:   /* 0 > 0 likely */
2831 6af0bf9c bellard
        case OPC_BLTZL:   /* 0 < 0 likely */
2832 6af0bf9c bellard
            /* Skip the instruction in the delay slot */
2833 6af0bf9c bellard
            MIPS_DEBUG("bnever and skip");
2834 9898128f ths
            ctx->pc += 4;
2835 6c5c1e20 ths
            goto out;
2836 6af0bf9c bellard
        case OPC_J:
2837 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
2838 d077b6f7 ths
            MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2839 6af0bf9c bellard
            break;
2840 620e48f6 Nathan Froyd
        case OPC_JALXS:
2841 364d4831 Nathan Froyd
        case OPC_JALX:
2842 364d4831 Nathan Froyd
            ctx->hflags |= MIPS_HFLAG_BX;
2843 364d4831 Nathan Froyd
            /* Fallthrough */
2844 620e48f6 Nathan Froyd
        case OPC_JALS:
2845 6af0bf9c bellard
        case OPC_JAL:
2846 6af0bf9c bellard
            blink = 31;
2847 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
2848 620e48f6 Nathan Froyd
            ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
2849 364d4831 Nathan Froyd
                            ? MIPS_HFLAG_BDS16
2850 364d4831 Nathan Froyd
                            : MIPS_HFLAG_BDS32);
2851 d077b6f7 ths
            MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2852 6af0bf9c bellard
            break;
2853 6af0bf9c bellard
        case OPC_JR:
2854 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BR;
2855 620e48f6 Nathan Froyd
            if (insn_bytes == 4)
2856 620e48f6 Nathan Froyd
                ctx->hflags |= MIPS_HFLAG_BDS32;
2857 6af0bf9c bellard
            MIPS_DEBUG("jr %s", regnames[rs]);
2858 6af0bf9c bellard
            break;
2859 620e48f6 Nathan Froyd
        case OPC_JALRS:
2860 6af0bf9c bellard
        case OPC_JALR:
2861 364d4831 Nathan Froyd
        case OPC_JALRC:
2862 6af0bf9c bellard
            blink = rt;
2863 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BR;
2864 620e48f6 Nathan Froyd
            ctx->hflags |= (opc == OPC_JALRS
2865 620e48f6 Nathan Froyd
                            ? MIPS_HFLAG_BDS16
2866 620e48f6 Nathan Froyd
                            : MIPS_HFLAG_BDS32);
2867 6af0bf9c bellard
            MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2868 6af0bf9c bellard
            break;
2869 6af0bf9c bellard
        default:
2870 6af0bf9c bellard
            MIPS_INVAL("branch/jump");
2871 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
2872 6c5c1e20 ths
            goto out;
2873 6af0bf9c bellard
        }
2874 6af0bf9c bellard
    } else {
2875 6af0bf9c bellard
        switch (opc) {
2876 6af0bf9c bellard
        case OPC_BEQ:
2877 e68dd28f Aurelien Jarno
            tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2878 923617a3 ths
            MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2879 d077b6f7 ths
                       regnames[rs], regnames[rt], btgt);
2880 6af0bf9c bellard
            goto not_likely;
2881 6af0bf9c bellard
        case OPC_BEQL:
2882 e68dd28f Aurelien Jarno
            tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2883 923617a3 ths
            MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2884 d077b6f7 ths
                       regnames[rs], regnames[rt], btgt);
2885 6af0bf9c bellard
            goto likely;
2886 6af0bf9c bellard
        case OPC_BNE:
2887 e68dd28f Aurelien Jarno
            tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2888 923617a3 ths
            MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2889 d077b6f7 ths
                       regnames[rs], regnames[rt], btgt);
2890 6af0bf9c bellard
            goto not_likely;
2891 6af0bf9c bellard
        case OPC_BNEL:
2892 e68dd28f Aurelien Jarno
            tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2893 923617a3 ths
            MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2894 d077b6f7 ths
                       regnames[rs], regnames[rt], btgt);
2895 6af0bf9c bellard
            goto likely;
2896 6af0bf9c bellard
        case OPC_BGEZ:
2897 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2898 d077b6f7 ths
            MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2899 6af0bf9c bellard
            goto not_likely;
2900 6af0bf9c bellard
        case OPC_BGEZL:
2901 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2902 d077b6f7 ths
            MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2903 6af0bf9c bellard
            goto likely;
2904 3c824109 Nathan Froyd
        case OPC_BGEZALS:
2905 6af0bf9c bellard
        case OPC_BGEZAL:
2906 3c824109 Nathan Froyd
            ctx->hflags |= (opc == OPC_BGEZALS
2907 3c824109 Nathan Froyd
                            ? MIPS_HFLAG_BDS16
2908 3c824109 Nathan Froyd
                            : MIPS_HFLAG_BDS32);
2909 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2910 d077b6f7 ths
            MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2911 6af0bf9c bellard
            blink = 31;
2912 6af0bf9c bellard
            goto not_likely;
2913 6af0bf9c bellard
        case OPC_BGEZALL:
2914 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2915 6af0bf9c bellard
            blink = 31;
2916 d077b6f7 ths
            MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2917 6af0bf9c bellard
            goto likely;
2918 6af0bf9c bellard
        case OPC_BGTZ:
2919 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2920 d077b6f7 ths
            MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2921 6af0bf9c bellard
            goto not_likely;
2922 6af0bf9c bellard
        case OPC_BGTZL:
2923 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2924 d077b6f7 ths
            MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2925 6af0bf9c bellard
            goto likely;
2926 6af0bf9c bellard
        case OPC_BLEZ:
2927 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2928 d077b6f7 ths
            MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2929 6af0bf9c bellard
            goto not_likely;
2930 6af0bf9c bellard
        case OPC_BLEZL:
2931 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2932 d077b6f7 ths
            MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2933 6af0bf9c bellard
            goto likely;
2934 6af0bf9c bellard
        case OPC_BLTZ:
2935 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2936 d077b6f7 ths
            MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2937 6af0bf9c bellard
            goto not_likely;
2938 6af0bf9c bellard
        case OPC_BLTZL:
2939 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2940 d077b6f7 ths
            MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2941 6af0bf9c bellard
            goto likely;
2942 3c824109 Nathan Froyd
        case OPC_BLTZALS:
2943 6af0bf9c bellard
        case OPC_BLTZAL:
2944 3c824109 Nathan Froyd
            ctx->hflags |= (opc == OPC_BLTZALS
2945 3c824109 Nathan Froyd
                            ? MIPS_HFLAG_BDS16
2946 3c824109 Nathan Froyd
                            : MIPS_HFLAG_BDS32);
2947 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2948 6af0bf9c bellard
            blink = 31;
2949 d077b6f7 ths
            MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2950 6af0bf9c bellard
        not_likely:
2951 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BC;
2952 6af0bf9c bellard
            break;
2953 6af0bf9c bellard
        case OPC_BLTZALL:
2954 e68dd28f Aurelien Jarno
            tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2955 6af0bf9c bellard
            blink = 31;
2956 d077b6f7 ths
            MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2957 6af0bf9c bellard
        likely:
2958 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BL;
2959 6af0bf9c bellard
            break;
2960 c53f4a62 ths
        default:
2961 c53f4a62 ths
            MIPS_INVAL("conditional branch/jump");
2962 c53f4a62 ths
            generate_exception(ctx, EXCP_RI);
2963 6c5c1e20 ths
            goto out;
2964 6af0bf9c bellard
        }
2965 6af0bf9c bellard
    }
2966 923617a3 ths
    MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2967 d077b6f7 ths
               blink, ctx->hflags, btgt);
2968 9b9e4393 ths
2969 d077b6f7 ths
    ctx->btarget = btgt;
2970 6af0bf9c bellard
    if (blink > 0) {
2971 364d4831 Nathan Froyd
        int post_delay = insn_bytes;
2972 364d4831 Nathan Froyd
        int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2973 364d4831 Nathan Froyd
2974 364d4831 Nathan Froyd
        if (opc != OPC_JALRC)
2975 364d4831 Nathan Froyd
            post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2976 364d4831 Nathan Froyd
2977 364d4831 Nathan Froyd
        tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
2978 6af0bf9c bellard
    }
2979 6c5c1e20 ths
2980 6c5c1e20 ths
 out:
2981 364d4831 Nathan Froyd
    if (insn_bytes == 2)
2982 364d4831 Nathan Froyd
        ctx->hflags |= MIPS_HFLAG_B16;
2983 6c5c1e20 ths
    tcg_temp_free(t0);
2984 6c5c1e20 ths
    tcg_temp_free(t1);
2985 6af0bf9c bellard
}
2986 6af0bf9c bellard
2987 7a387fff ths
/* special3 bitfield operations */
2988 7a387fff ths
static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2989 356265ae ths
                        int rs, int lsb, int msb)
2990 7a387fff ths
{
2991 a7812ae4 pbrook
    TCGv t0 = tcg_temp_new();
2992 a7812ae4 pbrook
    TCGv t1 = tcg_temp_new();
2993 505ad7c2 aurel32
    target_ulong mask;
2994 6c5c1e20 ths
2995 6c5c1e20 ths
    gen_load_gpr(t1, rs);
2996 7a387fff ths
    switch (opc) {
2997 7a387fff ths
    case OPC_EXT:
2998 7a387fff ths
        if (lsb + msb > 31)
2999 7a387fff ths
            goto fail;
3000 505ad7c2 aurel32
        tcg_gen_shri_tl(t0, t1, lsb);
3001 505ad7c2 aurel32
        if (msb != 31) {
3002 505ad7c2 aurel32
            tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3003 505ad7c2 aurel32
        } else {
3004 505ad7c2 aurel32
            tcg_gen_ext32s_tl(t0, t0);
3005 505ad7c2 aurel32
        }
3006 7a387fff ths
        break;
3007 c6d6dd7c ths
#if defined(TARGET_MIPS64)
3008 7a387fff ths
    case OPC_DEXTM:
3009 505ad7c2 aurel32
        tcg_gen_shri_tl(t0, t1, lsb);
3010 505ad7c2 aurel32
        if (msb != 31) {
3011 505ad7c2 aurel32
            tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3012 505ad7c2 aurel32
        }
3013 7a387fff ths
        break;
3014 7a387fff ths
    case OPC_DEXTU:
3015 505ad7c2 aurel32
        tcg_gen_shri_tl(t0, t1, lsb + 32);
3016 505ad7c2 aurel32
        tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3017 7a387fff ths
        break;
3018 7a387fff ths
    case OPC_DEXT:
3019 505ad7c2 aurel32
        tcg_gen_shri_tl(t0, t1, lsb);
3020 505ad7c2 aurel32
        tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3021 7a387fff ths
        break;
3022 c6d6dd7c ths
#endif
3023 7a387fff ths
    case OPC_INS:
3024 7a387fff ths
        if (lsb > msb)
3025 7a387fff ths
            goto fail;
3026 505ad7c2 aurel32
        mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
3027 6c5c1e20 ths
        gen_load_gpr(t0, rt);
3028 505ad7c2 aurel32
        tcg_gen_andi_tl(t0, t0, ~mask);
3029 505ad7c2 aurel32
        tcg_gen_shli_tl(t1, t1, lsb);
3030 505ad7c2 aurel32
        tcg_gen_andi_tl(t1, t1, mask);
3031 505ad7c2 aurel32
        tcg_gen_or_tl(t0, t0, t1);
3032 505ad7c2 aurel32
        tcg_gen_ext32s_tl(t0, t0);
3033 7a387fff ths
        break;
3034 c6d6dd7c ths
#if defined(TARGET_MIPS64)
3035 7a387fff ths
    case OPC_DINSM:
3036 7a387fff ths
        if (lsb > msb)
3037 7a387fff ths
            goto fail;
3038 505ad7c2 aurel32
        mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
3039 6c5c1e20 ths
        gen_load_gpr(t0, rt);
3040 505ad7c2 aurel32
        tcg_gen_andi_tl(t0, t0, ~mask);
3041 505ad7c2 aurel32
        tcg_gen_shli_tl(t1, t1, lsb);
3042 505ad7c2 aurel32
        tcg_gen_andi_tl(t1, t1, mask);
3043 505ad7c2 aurel32
        tcg_gen_or_tl(t0, t0, t1);
3044 7a387fff ths
        break;
3045 7a387fff ths
    case OPC_DINSU:
3046 7a387fff ths
        if (lsb > msb)
3047 7a387fff ths
            goto fail;
3048 6fbab869 Aurelien Jarno
        mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
3049 6c5c1e20 ths
        gen_load_gpr(t0, rt);
3050 505ad7c2 aurel32
        tcg_gen_andi_tl(t0, t0, ~mask);
3051 505ad7c2 aurel32
        tcg_gen_shli_tl(t1, t1, lsb + 32);
3052 505ad7c2 aurel32
        tcg_gen_andi_tl(t1, t1, mask);
3053 505ad7c2 aurel32
        tcg_gen_or_tl(t0, t0, t1);
3054 7a387fff ths
        break;
3055 7a387fff ths
    case OPC_DINS:
3056 7a387fff ths
        if (lsb > msb)
3057 7a387fff ths
            goto fail;
3058 6c5c1e20 ths
        gen_load_gpr(t0, rt);
3059 505ad7c2 aurel32
        mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3060 505ad7c2 aurel32
        gen_load_gpr(t0, rt);
3061 505ad7c2 aurel32
        tcg_gen_andi_tl(t0, t0, ~mask);
3062 505ad7c2 aurel32
        tcg_gen_shli_tl(t1, t1, lsb);
3063 505ad7c2 aurel32
        tcg_gen_andi_tl(t1, t1, mask);
3064 505ad7c2 aurel32
        tcg_gen_or_tl(t0, t0, t1);
3065 7a387fff ths
        break;
3066 c6d6dd7c ths
#endif
3067 7a387fff ths
    default:
3068 7a387fff ths
fail:
3069 7a387fff ths
        MIPS_INVAL("bitops");
3070 7a387fff ths
        generate_exception(ctx, EXCP_RI);
3071 6c5c1e20 ths
        tcg_temp_free(t0);
3072 6c5c1e20 ths
        tcg_temp_free(t1);
3073 7a387fff ths
        return;
3074 7a387fff ths
    }
3075 6c5c1e20 ths
    gen_store_gpr(t0, rt);
3076 6c5c1e20 ths
    tcg_temp_free(t0);
3077 6c5c1e20 ths
    tcg_temp_free(t1);
3078 7a387fff ths
}
3079 7a387fff ths
3080 49bcf33c aurel32
static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3081 49bcf33c aurel32
{
3082 3a55fa47 aurel32
    TCGv t0;
3083 49bcf33c aurel32
3084 3a55fa47 aurel32
    if (rd == 0) {
3085 3a55fa47 aurel32
        /* If no destination, treat it as a NOP. */
3086 3a55fa47 aurel32
        MIPS_DEBUG("NOP");
3087 3a55fa47 aurel32
        return;
3088 3a55fa47 aurel32
    }
3089 3a55fa47 aurel32
3090 3a55fa47 aurel32
    t0 = tcg_temp_new();
3091 3a55fa47 aurel32
    gen_load_gpr(t0, rt);
3092 49bcf33c aurel32
    switch (op2) {
3093 49bcf33c aurel32
    case OPC_WSBH:
3094 3a55fa47 aurel32
        {
3095 3a55fa47 aurel32
            TCGv t1 = tcg_temp_new();
3096 3a55fa47 aurel32
3097 3a55fa47 aurel32
            tcg_gen_shri_tl(t1, t0, 8);
3098 3a55fa47 aurel32
            tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3099 3a55fa47 aurel32
            tcg_gen_shli_tl(t0, t0, 8);
3100 3a55fa47 aurel32
            tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3101 3a55fa47 aurel32
            tcg_gen_or_tl(t0, t0, t1);
3102 3a55fa47 aurel32
            tcg_temp_free(t1);
3103 3a55fa47 aurel32
            tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3104 3a55fa47 aurel32
        }
3105 49bcf33c aurel32
        break;
3106 49bcf33c aurel32
    case OPC_SEB:
3107 3a55fa47 aurel32
        tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
3108 49bcf33c aurel32
        break;
3109 49bcf33c aurel32
    case OPC_SEH:
3110 3a55fa47 aurel32
        tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
3111 49bcf33c aurel32
        break;
3112 49bcf33c aurel32
#if defined(TARGET_MIPS64)
3113 49bcf33c aurel32
    case OPC_DSBH:
3114 3a55fa47 aurel32
        {
3115 3a55fa47 aurel32
            TCGv t1 = tcg_temp_new();
3116 3a55fa47 aurel32
3117 3a55fa47 aurel32
            tcg_gen_shri_tl(t1, t0, 8);
3118 3a55fa47 aurel32
            tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3119 3a55fa47 aurel32
            tcg_gen_shli_tl(t0, t0, 8);
3120 3a55fa47 aurel32
            tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3121 3a55fa47 aurel32
            tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3122 3a55fa47 aurel32
            tcg_temp_free(t1);
3123 3a55fa47 aurel32
        }
3124 49bcf33c aurel32
        break;
3125 49bcf33c aurel32
    case OPC_DSHD:
3126 3a55fa47 aurel32
        {
3127 3a55fa47 aurel32
            TCGv t1 = tcg_temp_new();
3128 3a55fa47 aurel32
3129 3a55fa47 aurel32
            tcg_gen_shri_tl(t1, t0, 16);
3130 3a55fa47 aurel32
            tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3131 3a55fa47 aurel32
            tcg_gen_shli_tl(t0, t0, 16);
3132 3a55fa47 aurel32
            tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3133 3a55fa47 aurel32
            tcg_gen_or_tl(t0, t0, t1);
3134 3a55fa47 aurel32
            tcg_gen_shri_tl(t1, t0, 32);
3135 3a55fa47 aurel32
            tcg_gen_shli_tl(t0, t0, 32);
3136 3a55fa47 aurel32
            tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3137 3a55fa47 aurel32
            tcg_temp_free(t1);
3138 3a55fa47 aurel32
        }
3139 49bcf33c aurel32
        break;
3140 49bcf33c aurel32
#endif
3141 49bcf33c aurel32
    default:
3142 49bcf33c aurel32
        MIPS_INVAL("bsfhl");
3143 49bcf33c aurel32
        generate_exception(ctx, EXCP_RI);
3144 49bcf33c aurel32
        tcg_temp_free(t0);
3145 49bcf33c aurel32
        return;
3146 49bcf33c aurel32
    }
3147 49bcf33c aurel32
    tcg_temp_free(t0);
3148 49bcf33c aurel32
}
3149 49bcf33c aurel32
3150 f1aa6320 ths
#ifndef CONFIG_USER_ONLY
3151 0eaef5aa ths
/* CP0 (MMU and control) */
3152 d9bea114 aurel32
static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
3153 4f57689a ths
{
3154 d9bea114 aurel32
    TCGv_i32 t0 = tcg_temp_new_i32();
3155 4f57689a ths
3156 d9bea114 aurel32
    tcg_gen_ld_i32(t0, cpu_env, off);
3157 d9bea114 aurel32
    tcg_gen_ext_i32_tl(arg, t0);
3158 d9bea114 aurel32
    tcg_temp_free_i32(t0);
3159 4f57689a ths
}
3160 4f57689a ths
3161 d9bea114 aurel32
static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
3162 4f57689a ths
{
3163 d9bea114 aurel32
    tcg_gen_ld_tl(arg, cpu_env, off);
3164 d9bea114 aurel32
    tcg_gen_ext32s_tl(arg, arg);
3165 4f57689a ths
}
3166 4f57689a ths
3167 d9bea114 aurel32
static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
3168 f1aa6320 ths
{
3169 d9bea114 aurel32
    TCGv_i32 t0 = tcg_temp_new_i32();
3170 f1aa6320 ths
3171 d9bea114 aurel32
    tcg_gen_trunc_tl_i32(t0, arg);
3172 d9bea114 aurel32
    tcg_gen_st_i32(t0, cpu_env, off);
3173 d9bea114 aurel32
    tcg_temp_free_i32(t0);
3174 f1aa6320 ths
}
3175 f1aa6320 ths
3176 d9bea114 aurel32
static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
3177 f1aa6320 ths
{
3178 d9bea114 aurel32
    tcg_gen_ext32s_tl(arg, arg);
3179 d9bea114 aurel32
    tcg_gen_st_tl(arg, cpu_env, off);
3180 f1aa6320 ths
}
3181 f1aa6320 ths
3182 d9bea114 aurel32
static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3183 873eb012 ths
{
3184 7a387fff ths
    const char *rn = "invalid";
3185 873eb012 ths
3186 e189e748 ths
    if (sel != 0)
3187 e189e748 ths
        check_insn(env, ctx, ISA_MIPS32);
3188 e189e748 ths
3189 873eb012 ths
    switch (reg) {
3190 873eb012 ths
    case 0:
3191 7a387fff ths
        switch (sel) {
3192 7a387fff ths
        case 0:
3193 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
3194 7a387fff ths
            rn = "Index";
3195 7a387fff ths
            break;
3196 7a387fff ths
        case 1:
3197 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3198 d9bea114 aurel32
            gen_helper_mfc0_mvpcontrol(arg);
3199 7a387fff ths
            rn = "MVPControl";
3200 ead9360e ths
            break;
3201 7a387fff ths
        case 2:
3202 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3203 d9bea114 aurel32
            gen_helper_mfc0_mvpconf0(arg);
3204 7a387fff ths
            rn = "MVPConf0";
3205 ead9360e ths
            break;
3206 7a387fff ths
        case 3:
3207 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3208 d9bea114 aurel32
            gen_helper_mfc0_mvpconf1(arg);
3209 7a387fff ths
            rn = "MVPConf1";
3210 ead9360e ths
            break;
3211 7a387fff ths
        default:
3212 7a387fff ths
            goto die;
3213 7a387fff ths
        }
3214 873eb012 ths
        break;
3215 873eb012 ths
    case 1:
3216 7a387fff ths
        switch (sel) {
3217 7a387fff ths
        case 0:
3218 d9bea114 aurel32
            gen_helper_mfc0_random(arg);
3219 7a387fff ths
            rn = "Random";
3220 2423f660 ths
            break;
3221 7a387fff ths
        case 1:
3222 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3223 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
3224 7a387fff ths
            rn = "VPEControl";
3225 ead9360e ths
            break;
3226 7a387fff ths
        case 2:
3227 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3228 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
3229 7a387fff ths
            rn = "VPEConf0";
3230 ead9360e ths
            break;
3231 7a387fff ths
        case 3:
3232 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3233 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
3234 7a387fff ths
            rn = "VPEConf1";
3235 ead9360e ths
            break;
3236 7a387fff ths
        case 4:
3237 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3238 d9bea114 aurel32
            gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
3239 7a387fff ths
            rn = "YQMask";
3240 ead9360e ths
            break;
3241 7a387fff ths
        case 5:
3242 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3243 d9bea114 aurel32
            gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
3244 7a387fff ths
            rn = "VPESchedule";
3245 ead9360e ths
            break;
3246 7a387fff ths
        case 6:
3247 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3248 d9bea114 aurel32
            gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3249 7a387fff ths
            rn = "VPEScheFBack";
3250 ead9360e ths
            break;
3251 7a387fff ths
        case 7:
3252 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3253 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
3254 7a387fff ths
            rn = "VPEOpt";
3255 ead9360e ths
            break;
3256 7a387fff ths
        default:
3257 7a387fff ths
            goto die;
3258 7a387fff ths
        }
3259 873eb012 ths
        break;
3260 873eb012 ths
    case 2:
3261 7a387fff ths
        switch (sel) {
3262 7a387fff ths
        case 0:
3263 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
3264 d9bea114 aurel32
            tcg_gen_ext32s_tl(arg, arg);
3265 2423f660 ths
            rn = "EntryLo0";
3266 2423f660 ths
            break;
3267 7a387fff ths
        case 1:
3268 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3269 d9bea114 aurel32
            gen_helper_mfc0_tcstatus(arg);
3270 2423f660 ths
            rn = "TCStatus";
3271 ead9360e ths
            break;
3272 7a387fff ths
        case 2:
3273 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3274 d9bea114 aurel32
            gen_helper_mfc0_tcbind(arg);
3275 2423f660 ths
            rn = "TCBind";
3276 ead9360e ths
            break;
3277 7a387fff ths
        case 3:
3278 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3279 d9bea114 aurel32
            gen_helper_mfc0_tcrestart(arg);
3280 2423f660 ths
            rn = "TCRestart";
3281 ead9360e ths
            break;
3282 7a387fff ths
        case 4:
3283 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3284 d9bea114 aurel32
            gen_helper_mfc0_tchalt(arg);
3285 2423f660 ths
            rn = "TCHalt";
3286 ead9360e ths
            break;
3287 7a387fff ths
        case 5:
3288 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3289 d9bea114 aurel32
            gen_helper_mfc0_tccontext(arg);
3290 2423f660 ths
            rn = "TCContext";
3291 ead9360e ths
            break;
3292 7a387fff ths
        case 6:
3293 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3294 d9bea114 aurel32
            gen_helper_mfc0_tcschedule(arg);
3295 2423f660 ths
            rn = "TCSchedule";
3296 ead9360e ths
            break;
3297 7a387fff ths
        case 7:
3298 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3299 d9bea114 aurel32
            gen_helper_mfc0_tcschefback(arg);
3300 2423f660 ths
            rn = "TCScheFBack";
3301 ead9360e ths
            break;
3302 7a387fff ths
        default:
3303 7a387fff ths
            goto die;
3304 7a387fff ths
        }
3305 873eb012 ths
        break;
3306 873eb012 ths
    case 3:
3307 7a387fff ths
        switch (sel) {
3308 7a387fff ths
        case 0:
3309 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
3310 d9bea114 aurel32
            tcg_gen_ext32s_tl(arg, arg);
3311 2423f660 ths
            rn = "EntryLo1";
3312 2423f660 ths
            break;
3313 7a387fff ths
        default:
3314 7a387fff ths
            goto die;
3315 1579a72e ths
        }
3316 873eb012 ths
        break;
3317 873eb012 ths
    case 4:
3318 7a387fff ths
        switch (sel) {
3319 7a387fff ths
        case 0:
3320 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
3321 d9bea114 aurel32
            tcg_gen_ext32s_tl(arg, arg);
3322 2423f660 ths
            rn = "Context";
3323 2423f660 ths
            break;
3324 7a387fff ths
        case 1:
3325 d9bea114 aurel32
//            gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3326 2423f660 ths
            rn = "ContextConfig";
3327 2423f660 ths
//            break;
3328 7a387fff ths
        default:
3329 7a387fff ths
            goto die;
3330 1579a72e ths
        }
3331 873eb012 ths
        break;
3332 873eb012 ths
    case 5:
3333 7a387fff ths
        switch (sel) {
3334 7a387fff ths
        case 0:
3335 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
3336 2423f660 ths
            rn = "PageMask";
3337 2423f660 ths
            break;
3338 7a387fff ths
        case 1:
3339 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3340 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
3341 2423f660 ths
            rn = "PageGrain";
3342 2423f660 ths
            break;
3343 7a387fff ths
        default:
3344 7a387fff ths
            goto die;
3345 1579a72e ths
        }
3346 873eb012 ths
        break;
3347 873eb012 ths
    case 6:
3348 7a387fff ths
        switch (sel) {
3349 7a387fff ths
        case 0:
3350 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
3351 2423f660 ths
            rn = "Wired";
3352 2423f660 ths
            break;
3353 7a387fff ths
        case 1:
3354 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3355 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
3356 2423f660 ths
            rn = "SRSConf0";
3357 ead9360e ths
            break;
3358 7a387fff ths
        case 2:
3359 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3360 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
3361 2423f660 ths
            rn = "SRSConf1";
3362 ead9360e ths
            break;
3363 7a387fff ths
        case 3:
3364 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3365 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
3366 2423f660 ths
            rn = "SRSConf2";
3367 ead9360e ths
            break;
3368 7a387fff ths
        case 4:
3369 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3370 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
3371 2423f660 ths
            rn = "SRSConf3";
3372 ead9360e ths
            break;
3373 7a387fff ths
        case 5:
3374 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3375 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
3376 2423f660 ths
            rn = "SRSConf4";
3377 ead9360e ths
            break;
3378 7a387fff ths
        default:
3379 7a387fff ths
            goto die;
3380 1579a72e ths
        }
3381 873eb012 ths
        break;
3382 8c0fdd85 ths
    case 7:
3383 7a387fff ths
        switch (sel) {
3384 7a387fff ths
        case 0:
3385 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3386 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
3387 2423f660 ths
            rn = "HWREna";
3388 2423f660 ths
            break;
3389 7a387fff ths
        default:
3390 7a387fff ths
            goto die;
3391 1579a72e ths
        }
3392 8c0fdd85 ths
        break;
3393 873eb012 ths
    case 8:
3394 7a387fff ths
        switch (sel) {
3395 7a387fff ths
        case 0:
3396 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3397 d9bea114 aurel32
            tcg_gen_ext32s_tl(arg, arg);
3398 f0b3f3ae ths
            rn = "BadVAddr";
3399 2423f660 ths
            break;
3400 7a387fff ths
        default:
3401 7a387fff ths
            goto die;
3402 7a387fff ths
       }
3403 873eb012 ths
        break;
3404 873eb012 ths
    case 9:
3405 7a387fff ths
        switch (sel) {
3406 7a387fff ths
        case 0:
3407 2e70f6ef pbrook
            /* Mark as an IO operation because we read the time.  */
3408 2e70f6ef pbrook
            if (use_icount)
3409 2e70f6ef pbrook
                gen_io_start();
3410 d9bea114 aurel32
            gen_helper_mfc0_count(arg);
3411 2e70f6ef pbrook
            if (use_icount) {
3412 2e70f6ef pbrook
                gen_io_end();
3413 2e70f6ef pbrook
                ctx->bstate = BS_STOP;
3414 2e70f6ef pbrook
            }
3415 2423f660 ths
            rn = "Count";
3416 2423f660 ths
            break;
3417 2423f660 ths
        /* 6,7 are implementation dependent */
3418 7a387fff ths
        default:
3419 7a387fff ths
            goto die;
3420 2423f660 ths
        }
3421 873eb012 ths
        break;
3422 873eb012 ths
    case 10:
3423 7a387fff ths
        switch (sel) {
3424 7a387fff ths
        case 0:
3425 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3426 d9bea114 aurel32
            tcg_gen_ext32s_tl(arg, arg);
3427 2423f660 ths
            rn = "EntryHi";
3428 2423f660 ths
            break;
3429 7a387fff ths
        default:
3430 7a387fff ths
            goto die;
3431 1579a72e ths
        }
3432 873eb012 ths
        break;
3433 873eb012 ths
    case 11:
3434 7a387fff ths
        switch (sel) {
3435 7a387fff ths
        case 0:
3436 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
3437 2423f660 ths
            rn = "Compare";
3438 2423f660 ths
            break;
3439 2423f660 ths
        /* 6,7 are implementation dependent */
3440 7a387fff ths
        default:
3441 7a387fff ths
            goto die;
3442 2423f660 ths
        }
3443 873eb012 ths
        break;
3444 873eb012 ths
    case 12:
3445 7a387fff ths
        switch (sel) {
3446 7a387fff ths
        case 0:
3447 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
3448 2423f660 ths
            rn = "Status";
3449 2423f660 ths
            break;
3450 7a387fff ths
        case 1:
3451 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3452 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
3453 2423f660 ths
            rn = "IntCtl";
3454 2423f660 ths
            break;
3455 7a387fff ths
        case 2:
3456 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3457 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
3458 2423f660 ths
            rn = "SRSCtl";
3459 2423f660 ths
            break;
3460 7a387fff ths
        case 3:
3461 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3462 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
3463 2423f660 ths
            rn = "SRSMap";
3464 fd88b6ab ths
            break;
3465 7a387fff ths
        default:
3466 7a387fff ths
            goto die;
3467 7a387fff ths
       }
3468 873eb012 ths
        break;
3469 873eb012 ths
    case 13:
3470 7a387fff ths
        switch (sel) {
3471 7a387fff ths
        case 0:
3472 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
3473 2423f660 ths
            rn = "Cause";
3474 2423f660 ths
            break;
3475 7a387fff ths
        default:
3476 7a387fff ths
            goto die;
3477 7a387fff ths
       }
3478 873eb012 ths
        break;
3479 873eb012 ths
    case 14:
3480 7a387fff ths
        switch (sel) {
3481 7a387fff ths
        case 0:
3482 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3483 d9bea114 aurel32
            tcg_gen_ext32s_tl(arg, arg);
3484 2423f660 ths
            rn = "EPC";
3485 2423f660 ths
            break;
3486 7a387fff ths
        default:
3487 7a387fff ths
            goto die;
3488 1579a72e ths
        }
3489 873eb012 ths
        break;
3490 873eb012 ths
    case 15:
3491 7a387fff ths
        switch (sel) {
3492 7a387fff ths
        case 0:
3493 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
3494 2423f660 ths
            rn = "PRid";
3495 2423f660 ths
            break;
3496 7a387fff ths
        case 1:
3497 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3498 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
3499 2423f660 ths
            rn = "EBase";
3500 2423f660 ths
            break;
3501 7a387fff ths
        default:
3502 7a387fff ths
            goto die;
3503 7a387fff ths
       }
3504 873eb012 ths
        break;
3505 873eb012 ths
    case 16:
3506 873eb012 ths
        switch (sel) {
3507 873eb012 ths
        case 0:
3508 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
3509 873eb012 ths
            rn = "Config";
3510 873eb012 ths
            break;
3511 873eb012 ths
        case 1:
3512 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
3513 873eb012 ths
            rn = "Config1";
3514 873eb012 ths
            break;
3515 7a387fff ths
        case 2:
3516 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
3517 7a387fff ths
            rn = "Config2";
3518 7a387fff ths
            break;
3519 7a387fff ths
        case 3:
3520 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
3521 7a387fff ths
            rn = "Config3";
3522 7a387fff ths
            break;
3523 e397ee33 ths
        /* 4,5 are reserved */
3524 e397ee33 ths
        /* 6,7 are implementation dependent */
3525 e397ee33 ths
        case 6:
3526 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
3527 e397ee33 ths
            rn = "Config6";
3528 e397ee33 ths
            break;
3529 e397ee33 ths
        case 7:
3530 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
3531 e397ee33 ths
            rn = "Config7";
3532 e397ee33 ths
            break;
3533 873eb012 ths
        default:
3534 873eb012 ths
            goto die;
3535 873eb012 ths
        }
3536 873eb012 ths
        break;
3537 873eb012 ths
    case 17:
3538 7a387fff ths
        switch (sel) {
3539 7a387fff ths
        case 0:
3540 d9bea114 aurel32
            gen_helper_mfc0_lladdr(arg);
3541 2423f660 ths
            rn = "LLAddr";
3542 2423f660 ths
            break;
3543 7a387fff ths
        default:
3544 7a387fff ths
            goto die;
3545 7a387fff ths
        }
3546 873eb012 ths
        break;
3547 873eb012 ths
    case 18:
3548 7a387fff ths
        switch (sel) {
3549 fd88b6ab ths
        case 0 ... 7:
3550 d9bea114 aurel32
            gen_helper_1i(mfc0_watchlo, arg, sel);
3551 2423f660 ths
            rn = "WatchLo";
3552 2423f660 ths
            break;
3553 7a387fff ths
        default:
3554 7a387fff ths
            goto die;
3555 7a387fff ths
        }
3556 873eb012 ths
        break;
3557 873eb012 ths
    case 19:
3558 7a387fff ths
        switch (sel) {
3559 fd88b6ab ths
        case 0 ...7:
3560 d9bea114 aurel32
            gen_helper_1i(mfc0_watchhi, arg, sel);
3561 2423f660 ths
            rn = "WatchHi";
3562 2423f660 ths
            break;
3563 7a387fff ths
        default:
3564 7a387fff ths
            goto die;
3565 7a387fff ths
        }
3566 873eb012 ths
        break;
3567 8c0fdd85 ths
    case 20:
3568 7a387fff ths
        switch (sel) {
3569 7a387fff ths
        case 0:
3570 d26bc211 ths
#if defined(TARGET_MIPS64)
3571 e189e748 ths
            check_insn(env, ctx, ISA_MIPS3);
3572 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3573 d9bea114 aurel32
            tcg_gen_ext32s_tl(arg, arg);
3574 2423f660 ths
            rn = "XContext";
3575 2423f660 ths
            break;
3576 703eaf37 ths
#endif
3577 7a387fff ths
        default:
3578 7a387fff ths
            goto die;
3579 7a387fff ths
        }
3580 8c0fdd85 ths
        break;
3581 8c0fdd85 ths
    case 21:
3582 7a387fff ths
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
3583 7a387fff ths
        switch (sel) {
3584 7a387fff ths
        case 0:
3585 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
3586 2423f660 ths
            rn = "Framemask";
3587 2423f660 ths
            break;
3588 7a387fff ths
        default:
3589 7a387fff ths
            goto die;
3590 7a387fff ths
        }
3591 8c0fdd85 ths
        break;
3592 8c0fdd85 ths
    case 22:
3593 d9bea114 aurel32
        tcg_gen_movi_tl(arg, 0); /* unimplemented */
3594 2423f660 ths
        rn = "'Diagnostic"; /* implementation dependent */
3595 2423f660 ths
        break;
3596 873eb012 ths
    case 23:
3597 7a387fff ths
        switch (sel) {
3598 7a387fff ths
        case 0:
3599 d9bea114 aurel32
            gen_helper_mfc0_debug(arg); /* EJTAG support */
3600 2423f660 ths
            rn = "Debug";
3601 2423f660 ths
            break;
3602 7a387fff ths
        case 1:
3603 d9bea114 aurel32
//            gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3604 2423f660 ths
            rn = "TraceControl";
3605 2423f660 ths
//            break;
3606 7a387fff ths
        case 2:
3607 d9bea114 aurel32
//            gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3608 2423f660 ths
            rn = "TraceControl2";
3609 2423f660 ths
//            break;
3610 7a387fff ths
        case 3:
3611 d9bea114 aurel32
//            gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3612 2423f660 ths
            rn = "UserTraceData";
3613 2423f660 ths
//            break;
3614 7a387fff ths
        case 4:
3615 d9bea114 aurel32
//            gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3616 2423f660 ths
            rn = "TraceBPC";
3617 2423f660 ths
//            break;
3618 7a387fff ths
        default:
3619 7a387fff ths
            goto die;
3620 7a387fff ths
        }
3621 873eb012 ths
        break;
3622 873eb012 ths
    case 24:
3623 7a387fff ths
        switch (sel) {
3624 7a387fff ths
        case 0:
3625 f0b3f3ae ths
            /* EJTAG support */
3626 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3627 d9bea114 aurel32
            tcg_gen_ext32s_tl(arg, arg);
3628 2423f660 ths
            rn = "DEPC";
3629 2423f660 ths
            break;
3630 7a387fff ths
        default:
3631 7a387fff ths
            goto die;
3632 7a387fff ths
        }
3633 873eb012 ths
        break;
3634 8c0fdd85 ths
    case 25:
3635 7a387fff ths
        switch (sel) {
3636 7a387fff ths
        case 0:
3637 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
3638 2423f660 ths
            rn = "Performance0";
3639 7a387fff ths
            break;
3640 7a387fff ths
        case 1:
3641 d9bea114 aurel32
//            gen_helper_mfc0_performance1(arg);
3642 2423f660 ths
            rn = "Performance1";
3643 2423f660 ths
//            break;
3644 7a387fff ths
        case 2:
3645 d9bea114 aurel32
//            gen_helper_mfc0_performance2(arg);
3646 2423f660 ths
            rn = "Performance2";
3647 2423f660 ths
//            break;
3648 7a387fff ths
        case 3:
3649 d9bea114 aurel32
//            gen_helper_mfc0_performance3(arg);
3650 2423f660 ths
            rn = "Performance3";
3651 2423f660 ths
//            break;
3652 7a387fff ths
        case 4:
3653 d9bea114 aurel32
//            gen_helper_mfc0_performance4(arg);
3654 2423f660 ths
            rn = "Performance4";
3655 2423f660 ths
//            break;
3656 7a387fff ths
        case 5:
3657 d9bea114 aurel32
//            gen_helper_mfc0_performance5(arg);
3658 2423f660 ths
            rn = "Performance5";
3659 2423f660 ths
//            break;
3660 7a387fff ths
        case 6:
3661 d9bea114 aurel32
//            gen_helper_mfc0_performance6(arg);
3662 2423f660 ths
            rn = "Performance6";
3663 2423f660 ths
//            break;
3664 7a387fff ths
        case 7:
3665 d9bea114 aurel32
//            gen_helper_mfc0_performance7(arg);
3666 2423f660 ths
            rn = "Performance7";
3667 2423f660 ths
//            break;
3668 7a387fff ths
        default:
3669 7a387fff ths
            goto die;
3670 7a387fff ths
        }
3671 8c0fdd85 ths
        break;
3672 8c0fdd85 ths
    case 26:
3673 d9bea114 aurel32
        tcg_gen_movi_tl(arg, 0); /* unimplemented */
3674 da80682b aurel32
        rn = "ECC";
3675 da80682b aurel32
        break;
3676 8c0fdd85 ths
    case 27:
3677 7a387fff ths
        switch (sel) {
3678 7a387fff ths
        case 0 ... 3:
3679 d9bea114 aurel32
            tcg_gen_movi_tl(arg, 0); /* unimplemented */
3680 2423f660 ths
            rn = "CacheErr";
3681 2423f660 ths
            break;
3682 7a387fff ths
        default:
3683 7a387fff ths
            goto die;
3684 7a387fff ths
        }
3685 8c0fdd85 ths
        break;
3686 873eb012 ths
    case 28:
3687 873eb012 ths
        switch (sel) {
3688 873eb012 ths
        case 0:
3689 7a387fff ths
        case 2:
3690 7a387fff ths
        case 4:
3691 7a387fff ths
        case 6:
3692 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
3693 873eb012 ths
            rn = "TagLo";
3694 873eb012 ths
            break;
3695 873eb012 ths
        case 1:
3696 7a387fff ths
        case 3:
3697 7a387fff ths
        case 5:
3698 7a387fff ths
        case 7:
3699 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
3700 873eb012 ths
            rn = "DataLo";
3701 873eb012 ths
            break;
3702 873eb012 ths
        default:
3703 873eb012 ths
            goto die;
3704 873eb012 ths
        }
3705 873eb012 ths
        break;
3706 8c0fdd85 ths
    case 29:
3707 7a387fff ths
        switch (sel) {
3708 7a387fff ths
        case 0:
3709 7a387fff ths
        case 2:
3710 7a387fff ths
        case 4:
3711 7a387fff ths
        case 6:
3712 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
3713 7a387fff ths
            rn = "TagHi";
3714 7a387fff ths
            break;
3715 7a387fff ths
        case 1:
3716 7a387fff ths
        case 3:
3717 7a387fff ths
        case 5:
3718 7a387fff ths
        case 7:
3719 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
3720 7a387fff ths
            rn = "DataHi";
3721 7a387fff ths
            break;
3722 7a387fff ths
        default:
3723 7a387fff ths
            goto die;
3724 7a387fff ths
        }
3725 8c0fdd85 ths
        break;
3726 873eb012 ths
    case 30:
3727 7a387fff ths
        switch (sel) {
3728 7a387fff ths
        case 0:
3729 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3730 d9bea114 aurel32
            tcg_gen_ext32s_tl(arg, arg);
3731 2423f660 ths
            rn = "ErrorEPC";
3732 2423f660 ths
            break;
3733 7a387fff ths
        default:
3734 7a387fff ths
            goto die;
3735 7a387fff ths
        }
3736 873eb012 ths
        break;
3737 873eb012 ths
    case 31:
3738 7a387fff ths
        switch (sel) {
3739 7a387fff ths
        case 0:
3740 f0b3f3ae ths
            /* EJTAG support */
3741 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
3742 2423f660 ths
            rn = "DESAVE";
3743 2423f660 ths
            break;
3744 7a387fff ths
        default:
3745 7a387fff ths
            goto die;
3746 7a387fff ths
        }
3747 873eb012 ths
        break;
3748 873eb012 ths
    default:
3749 873eb012 ths
       goto die;
3750 873eb012 ths
    }
3751 2abf314d Blue Swirl
    (void)rn; /* avoid a compiler warning */
3752 d12d51d5 aliguori
    LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3753 873eb012 ths
    return;
3754 873eb012 ths
3755 873eb012 ths
die:
3756 d12d51d5 aliguori
    LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3757 873eb012 ths
    generate_exception(ctx, EXCP_RI);
3758 873eb012 ths
}
3759 873eb012 ths
3760 d9bea114 aurel32
static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3761 8c0fdd85 ths
{
3762 7a387fff ths
    const char *rn = "invalid";
3763 7a387fff ths
3764 e189e748 ths
    if (sel != 0)
3765 e189e748 ths
        check_insn(env, ctx, ISA_MIPS32);
3766 e189e748 ths
3767 2e70f6ef pbrook
    if (use_icount)
3768 2e70f6ef pbrook
        gen_io_start();
3769 2e70f6ef pbrook
3770 8c0fdd85 ths
    switch (reg) {
3771 8c0fdd85 ths
    case 0:
3772 7a387fff ths
        switch (sel) {
3773 7a387fff ths
        case 0:
3774 d9bea114 aurel32
            gen_helper_mtc0_index(arg);
3775 7a387fff ths
            rn = "Index";
3776 7a387fff ths
            break;
3777 7a387fff ths
        case 1:
3778 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3779 d9bea114 aurel32
            gen_helper_mtc0_mvpcontrol(arg);
3780 7a387fff ths
            rn = "MVPControl";
3781 ead9360e ths
            break;
3782 7a387fff ths
        case 2:
3783 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3784 ead9360e ths
            /* ignored */
3785 7a387fff ths
            rn = "MVPConf0";
3786 ead9360e ths
            break;
3787 7a387fff ths
        case 3:
3788 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3789 ead9360e ths
            /* ignored */
3790 7a387fff ths
            rn = "MVPConf1";
3791 ead9360e ths
            break;
3792 7a387fff ths
        default:
3793 7a387fff ths
            goto die;
3794 7a387fff ths
        }
3795 8c0fdd85 ths
        break;
3796 8c0fdd85 ths
    case 1:
3797 7a387fff ths
        switch (sel) {
3798 7a387fff ths
        case 0:
3799 2423f660 ths
            /* ignored */
3800 7a387fff ths
            rn = "Random";
3801 2423f660 ths
            break;
3802 7a387fff ths
        case 1:
3803 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3804 d9bea114 aurel32
            gen_helper_mtc0_vpecontrol(arg);
3805 7a387fff ths
            rn = "VPEControl";
3806 ead9360e ths
            break;
3807 7a387fff ths
        case 2:
3808 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3809 d9bea114 aurel32
            gen_helper_mtc0_vpeconf0(arg);
3810 7a387fff ths
            rn = "VPEConf0";
3811 ead9360e ths
            break;
3812 7a387fff ths
        case 3:
3813 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3814 d9bea114 aurel32
            gen_helper_mtc0_vpeconf1(arg);
3815 7a387fff ths
            rn = "VPEConf1";
3816 ead9360e ths
            break;
3817 7a387fff ths
        case 4:
3818 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3819 d9bea114 aurel32
            gen_helper_mtc0_yqmask(arg);
3820 7a387fff ths
            rn = "YQMask";
3821 ead9360e ths
            break;
3822 7a387fff ths
        case 5:
3823 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3824 d9bea114 aurel32
            gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
3825 7a387fff ths
            rn = "VPESchedule";
3826 ead9360e ths
            break;
3827 7a387fff ths
        case 6:
3828 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3829 d9bea114 aurel32
            gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
3830 7a387fff ths
            rn = "VPEScheFBack";
3831 ead9360e ths
            break;
3832 7a387fff ths
        case 7:
3833 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3834 d9bea114 aurel32
            gen_helper_mtc0_vpeopt(arg);
3835 7a387fff ths
            rn = "VPEOpt";
3836 ead9360e ths
            break;
3837 7a387fff ths
        default:
3838 7a387fff ths
            goto die;
3839 7a387fff ths
        }
3840 8c0fdd85 ths
        break;
3841 8c0fdd85 ths
    case 2:
3842 7a387fff ths
        switch (sel) {
3843 7a387fff ths
        case 0:
3844 d9bea114 aurel32
            gen_helper_mtc0_entrylo0(arg);
3845 2423f660 ths
            rn = "EntryLo0";
3846 2423f660 ths
            break;
3847 7a387fff ths
        case 1:
3848 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3849 d9bea114 aurel32
            gen_helper_mtc0_tcstatus(arg);
3850 2423f660 ths
            rn = "TCStatus";
3851 ead9360e ths
            break;
3852 7a387fff ths
        case 2:
3853 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3854 d9bea114 aurel32
            gen_helper_mtc0_tcbind(arg);
3855 2423f660 ths
            rn = "TCBind";
3856 ead9360e ths
            break;
3857 7a387fff ths
        case 3:
3858 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3859 d9bea114 aurel32
            gen_helper_mtc0_tcrestart(arg);
3860 2423f660 ths
            rn = "TCRestart";
3861 ead9360e ths
            break;
3862 7a387fff ths
        case 4:
3863 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3864 d9bea114 aurel32
            gen_helper_mtc0_tchalt(arg);
3865 2423f660 ths
            rn = "TCHalt";
3866 ead9360e ths
            break;
3867 7a387fff ths
        case 5:
3868 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3869 d9bea114 aurel32
            gen_helper_mtc0_tccontext(arg);
3870 2423f660 ths
            rn = "TCContext";
3871 ead9360e ths
            break;
3872 7a387fff ths
        case 6:
3873 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3874 d9bea114 aurel32
            gen_helper_mtc0_tcschedule(arg);
3875 2423f660 ths
            rn = "TCSchedule";
3876 ead9360e ths
            break;
3877 7a387fff ths
        case 7:
3878 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
3879 d9bea114 aurel32
            gen_helper_mtc0_tcschefback(arg);
3880 2423f660 ths
            rn = "TCScheFBack";
3881 ead9360e ths
            break;
3882 7a387fff ths
        default:
3883 7a387fff ths
            goto die;
3884 7a387fff ths
        }
3885 8c0fdd85 ths
        break;
3886 8c0fdd85 ths
    case 3:
3887 7a387fff ths
        switch (sel) {
3888 7a387fff ths
        case 0:
3889 d9bea114 aurel32
            gen_helper_mtc0_entrylo1(arg);
3890 2423f660 ths
            rn = "EntryLo1";
3891 2423f660 ths
            break;
3892 7a387fff ths
        default:
3893 7a387fff ths
            goto die;
3894 876d4b07 ths
        }
3895 8c0fdd85 ths
        break;
3896 8c0fdd85 ths
    case 4:
3897 7a387fff ths
        switch (sel) {
3898 7a387fff ths
        case 0:
3899 d9bea114 aurel32
            gen_helper_mtc0_context(arg);
3900 2423f660 ths
            rn = "Context";
3901 2423f660 ths
            break;
3902 7a387fff ths
        case 1:
3903 d9bea114 aurel32
//            gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3904 2423f660 ths
            rn = "ContextConfig";
3905 2423f660 ths
//            break;
3906 7a387fff ths
        default:
3907 7a387fff ths
            goto die;
3908 876d4b07 ths
        }
3909 8c0fdd85 ths
        break;
3910 8c0fdd85 ths
    case 5:
3911 7a387fff ths
        switch (sel) {
3912 7a387fff ths
        case 0:
3913 d9bea114 aurel32
            gen_helper_mtc0_pagemask(arg);
3914 2423f660 ths
            rn = "PageMask";
3915 2423f660 ths
            break;
3916 7a387fff ths
        case 1:
3917 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3918 d9bea114 aurel32
            gen_helper_mtc0_pagegrain(arg);
3919 2423f660 ths
            rn = "PageGrain";
3920 2423f660 ths
            break;
3921 7a387fff ths
        default:
3922 7a387fff ths
            goto die;
3923 876d4b07 ths
        }
3924 8c0fdd85 ths
        break;
3925 8c0fdd85 ths
    case 6:
3926 7a387fff ths
        switch (sel) {
3927 7a387fff ths
        case 0:
3928 d9bea114 aurel32
            gen_helper_mtc0_wired(arg);
3929 2423f660 ths
            rn = "Wired";
3930 2423f660 ths
            break;
3931 7a387fff ths
        case 1:
3932 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3933 d9bea114 aurel32
            gen_helper_mtc0_srsconf0(arg);
3934 2423f660 ths
            rn = "SRSConf0";
3935 ead9360e ths
            break;
3936 7a387fff ths
        case 2:
3937 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3938 d9bea114 aurel32
            gen_helper_mtc0_srsconf1(arg);
3939 2423f660 ths
            rn = "SRSConf1";
3940 ead9360e ths
            break;
3941 7a387fff ths
        case 3:
3942 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3943 d9bea114 aurel32
            gen_helper_mtc0_srsconf2(arg);
3944 2423f660 ths
            rn = "SRSConf2";
3945 ead9360e ths
            break;
3946 7a387fff ths
        case 4:
3947 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3948 d9bea114 aurel32
            gen_helper_mtc0_srsconf3(arg);
3949 2423f660 ths
            rn = "SRSConf3";
3950 ead9360e ths
            break;
3951 7a387fff ths
        case 5:
3952 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3953 d9bea114 aurel32
            gen_helper_mtc0_srsconf4(arg);
3954 2423f660 ths
            rn = "SRSConf4";
3955 ead9360e ths
            break;
3956 7a387fff ths
        default:
3957 7a387fff ths
            goto die;
3958 876d4b07 ths
        }
3959 8c0fdd85 ths
        break;
3960 8c0fdd85 ths
    case 7:
3961 7a387fff ths
        switch (sel) {
3962 7a387fff ths
        case 0:
3963 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
3964 d9bea114 aurel32
            gen_helper_mtc0_hwrena(arg);
3965 2423f660 ths
            rn = "HWREna";
3966 2423f660 ths
            break;
3967 7a387fff ths
        default:
3968 7a387fff ths
            goto die;
3969 876d4b07 ths
        }
3970 8c0fdd85 ths
        break;
3971 8c0fdd85 ths
    case 8:
3972 7a387fff ths
        /* ignored */
3973 f0b3f3ae ths
        rn = "BadVAddr";
3974 8c0fdd85 ths
        break;
3975 8c0fdd85 ths
    case 9:
3976 7a387fff ths
        switch (sel) {
3977 7a387fff ths
        case 0:
3978 d9bea114 aurel32
            gen_helper_mtc0_count(arg);
3979 2423f660 ths
            rn = "Count";
3980 2423f660 ths
            break;
3981 876d4b07 ths
        /* 6,7 are implementation dependent */
3982 7a387fff ths
        default:
3983 7a387fff ths
            goto die;
3984 876d4b07 ths
        }
3985 8c0fdd85 ths
        break;
3986 8c0fdd85 ths
    case 10:
3987 7a387fff ths
        switch (sel) {
3988 7a387fff ths
        case 0:
3989 d9bea114 aurel32
            gen_helper_mtc0_entryhi(arg);
3990 2423f660 ths
            rn = "EntryHi";
3991 2423f660 ths
            break;
3992 7a387fff ths
        default:
3993 7a387fff ths
            goto die;
3994 876d4b07 ths
        }
3995 8c0fdd85 ths
        break;
3996 8c0fdd85 ths
    case 11:
3997 7a387fff ths
        switch (sel) {
3998 7a387fff ths
        case 0:
3999 d9bea114 aurel32
            gen_helper_mtc0_compare(arg);
4000 2423f660 ths
            rn = "Compare";
4001 2423f660 ths
            break;
4002 2423f660 ths
        /* 6,7 are implementation dependent */
4003 7a387fff ths
        default:
4004 7a387fff ths
            goto die;
4005 876d4b07 ths
        }
4006 8c0fdd85 ths
        break;
4007 8c0fdd85 ths
    case 12:
4008 7a387fff ths
        switch (sel) {
4009 7a387fff ths
        case 0:
4010 867abc7e aurel32
            save_cpu_state(ctx, 1);
4011 d9bea114 aurel32
            gen_helper_mtc0_status(arg);
4012 8487327a ths
            /* BS_STOP isn't good enough here, hflags may have changed. */
4013 8487327a ths
            gen_save_pc(ctx->pc + 4);
4014 8487327a ths
            ctx->bstate = BS_EXCP;
4015 2423f660 ths
            rn = "Status";
4016 2423f660 ths
            break;
4017 7a387fff ths
        case 1:
4018 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4019 d9bea114 aurel32
            gen_helper_mtc0_intctl(arg);
4020 8487327a ths
            /* Stop translation as we may have switched the execution mode */
4021 8487327a ths
            ctx->bstate = BS_STOP;
4022 2423f660 ths
            rn = "IntCtl";
4023 2423f660 ths
            break;
4024 7a387fff ths
        case 2:
4025 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4026 d9bea114 aurel32
            gen_helper_mtc0_srsctl(arg);
4027 8487327a ths
            /* Stop translation as we may have switched the execution mode */
4028 8487327a ths
            ctx->bstate = BS_STOP;
4029 2423f660 ths
            rn = "SRSCtl";
4030 2423f660 ths
            break;
4031 7a387fff ths
        case 3:
4032 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4033 d9bea114 aurel32
            gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
4034 8487327a ths
            /* Stop translation as we may have switched the execution mode */
4035 8487327a ths
            ctx->bstate = BS_STOP;
4036 2423f660 ths
            rn = "SRSMap";
4037 fd88b6ab ths
            break;
4038 7a387fff ths
        default:
4039 7a387fff ths
            goto die;
4040 876d4b07 ths
        }
4041 8c0fdd85 ths
        break;
4042 8c0fdd85 ths
    case 13:
4043 7a387fff ths
        switch (sel) {
4044 7a387fff ths
        case 0:
4045 867abc7e aurel32
            save_cpu_state(ctx, 1);
4046 d9bea114 aurel32
            gen_helper_mtc0_cause(arg);
4047 2423f660 ths
            rn = "Cause";
4048 2423f660 ths
            break;
4049 7a387fff ths
        default:
4050 7a387fff ths
            goto die;
4051 876d4b07 ths
        }
4052 8c0fdd85 ths
        break;
4053 8c0fdd85 ths
    case 14:
4054 7a387fff ths
        switch (sel) {
4055 7a387fff ths
        case 0:
4056 d9bea114 aurel32
            gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
4057 2423f660 ths
            rn = "EPC";
4058 2423f660 ths
            break;
4059 7a387fff ths
        default:
4060 7a387fff ths
            goto die;
4061 876d4b07 ths
        }
4062 8c0fdd85 ths
        break;
4063 8c0fdd85 ths
    case 15:
4064 7a387fff ths
        switch (sel) {
4065 7a387fff ths
        case 0:
4066 2423f660 ths
            /* ignored */
4067 2423f660 ths
            rn = "PRid";
4068 2423f660 ths
            break;
4069 7a387fff ths
        case 1:
4070 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4071 d9bea114 aurel32
            gen_helper_mtc0_ebase(arg);
4072 2423f660 ths
            rn = "EBase";
4073 2423f660 ths
            break;
4074 7a387fff ths
        default:
4075 7a387fff ths
            goto die;
4076 1579a72e ths
        }
4077 8c0fdd85 ths
        break;
4078 8c0fdd85 ths
    case 16:
4079 8c0fdd85 ths
        switch (sel) {
4080 8c0fdd85 ths
        case 0:
4081 d9bea114 aurel32
            gen_helper_mtc0_config0(arg);
4082 7a387fff ths
            rn = "Config";
4083 2423f660 ths
            /* Stop translation as we may have switched the execution mode */
4084 2423f660 ths
            ctx->bstate = BS_STOP;
4085 7a387fff ths
            break;
4086 7a387fff ths
        case 1:
4087 e397ee33 ths
            /* ignored, read only */
4088 7a387fff ths
            rn = "Config1";
4089 7a387fff ths
            break;
4090 7a387fff ths
        case 2:
4091 d9bea114 aurel32
            gen_helper_mtc0_config2(arg);
4092 7a387fff ths
            rn = "Config2";
4093 2423f660 ths
            /* Stop translation as we may have switched the execution mode */
4094 2423f660 ths
            ctx->bstate = BS_STOP;
4095 8c0fdd85 ths
            break;
4096 7a387fff ths
        case 3:
4097 e397ee33 ths
            /* ignored, read only */
4098 7a387fff ths
            rn = "Config3";
4099 7a387fff ths
            break;
4100 e397ee33 ths
        /* 4,5 are reserved */
4101 e397ee33 ths
        /* 6,7 are implementation dependent */
4102 e397ee33 ths
        case 6:
4103 e397ee33 ths
            /* ignored */
4104 e397ee33 ths
            rn = "Config6";
4105 e397ee33 ths
            break;
4106 e397ee33 ths
        case 7:
4107 e397ee33 ths
            /* ignored */
4108 e397ee33 ths
            rn = "Config7";
4109 e397ee33 ths
            break;
4110 8c0fdd85 ths
        default:
4111 8c0fdd85 ths
            rn = "Invalid config selector";
4112 8c0fdd85 ths
            goto die;
4113 8c0fdd85 ths
        }
4114 8c0fdd85 ths
        break;
4115 8c0fdd85 ths
    case 17:
4116 7a387fff ths
        switch (sel) {
4117 7a387fff ths
        case 0:
4118 2a6e32dd Aurelien Jarno
            gen_helper_mtc0_lladdr(arg);
4119 2423f660 ths
            rn = "LLAddr";
4120 2423f660 ths
            break;
4121 7a387fff ths
        default:
4122 7a387fff ths
            goto die;
4123 7a387fff ths
        }
4124 8c0fdd85 ths
        break;
4125 8c0fdd85 ths
    case 18:
4126 7a387fff ths
        switch (sel) {
4127 fd88b6ab ths
        case 0 ... 7:
4128 d9bea114 aurel32
            gen_helper_1i(mtc0_watchlo, arg, sel);
4129 2423f660 ths
            rn = "WatchLo";
4130 2423f660 ths
            break;
4131 7a387fff ths
        default:
4132 7a387fff ths
            goto die;
4133 7a387fff ths
        }
4134 8c0fdd85 ths
        break;
4135 8c0fdd85 ths
    case 19:
4136 7a387fff ths
        switch (sel) {
4137 fd88b6ab ths
        case 0 ... 7:
4138 d9bea114 aurel32
            gen_helper_1i(mtc0_watchhi, arg, sel);
4139 2423f660 ths
            rn = "WatchHi";
4140 2423f660 ths
            break;
4141 7a387fff ths
        default:
4142 7a387fff ths
            goto die;
4143 7a387fff ths
        }
4144 8c0fdd85 ths
        break;
4145 8c0fdd85 ths
    case 20:
4146 7a387fff ths
        switch (sel) {
4147 7a387fff ths
        case 0:
4148 d26bc211 ths
#if defined(TARGET_MIPS64)
4149 e189e748 ths
            check_insn(env, ctx, ISA_MIPS3);
4150 d9bea114 aurel32
            gen_helper_mtc0_xcontext(arg);
4151 2423f660 ths
            rn = "XContext";
4152 2423f660 ths
            break;
4153 703eaf37 ths
#endif
4154 7a387fff ths
        default:
4155 7a387fff ths
            goto die;
4156 7a387fff ths
        }
4157 8c0fdd85 ths
        break;
4158 8c0fdd85 ths
    case 21:
4159 7a387fff ths
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
4160 7a387fff ths
        switch (sel) {
4161 7a387fff ths
        case 0:
4162 d9bea114 aurel32
            gen_helper_mtc0_framemask(arg);
4163 2423f660 ths
            rn = "Framemask";
4164 2423f660 ths
            break;
4165 7a387fff ths
        default:
4166 7a387fff ths
            goto die;
4167 7a387fff ths
        }
4168 7a387fff ths
        break;
4169 8c0fdd85 ths
    case 22:
4170 7a387fff ths
        /* ignored */
4171 7a387fff ths
        rn = "Diagnostic"; /* implementation dependent */
4172 2423f660 ths
        break;
4173 8c0fdd85 ths
    case 23:
4174 7a387fff ths
        switch (sel) {
4175 7a387fff ths
        case 0:
4176 d9bea114 aurel32
            gen_helper_mtc0_debug(arg); /* EJTAG support */
4177 8487327a ths
            /* BS_STOP isn't good enough here, hflags may have changed. */
4178 8487327a ths
            gen_save_pc(ctx->pc + 4);
4179 8487327a ths
            ctx->bstate = BS_EXCP;
4180 2423f660 ths
            rn = "Debug";
4181 2423f660 ths
            break;
4182 7a387fff ths
        case 1:
4183 d9bea114 aurel32
//            gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
4184 2423f660 ths
            rn = "TraceControl";
4185 8487327a ths
            /* Stop translation as we may have switched the execution mode */
4186 8487327a ths
            ctx->bstate = BS_STOP;
4187 2423f660 ths
//            break;
4188 7a387fff ths
        case 2:
4189 d9bea114 aurel32
//            gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
4190 2423f660 ths
            rn = "TraceControl2";
4191 8487327a ths
            /* Stop translation as we may have switched the execution mode */
4192 8487327a ths
            ctx->bstate = BS_STOP;
4193 2423f660 ths
//            break;
4194 7a387fff ths
        case 3:
4195 8487327a ths
            /* Stop translation as we may have switched the execution mode */
4196 8487327a ths
            ctx->bstate = BS_STOP;
4197 d9bea114 aurel32
//            gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
4198 2423f660 ths
            rn = "UserTraceData";
4199 8487327a ths
            /* Stop translation as we may have switched the execution mode */
4200 8487327a ths
            ctx->bstate = BS_STOP;
4201 2423f660 ths
//            break;
4202 7a387fff ths
        case 4:
4203 d9bea114 aurel32
//            gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
4204 8487327a ths
            /* Stop translation as we may have switched the execution mode */
4205 8487327a ths
            ctx->bstate = BS_STOP;
4206 2423f660 ths
            rn = "TraceBPC";
4207 2423f660 ths
//            break;
4208 7a387fff ths
        default:
4209 7a387fff ths
            goto die;
4210 7a387fff ths
        }
4211 8c0fdd85 ths
        break;
4212 8c0fdd85 ths
    case 24:
4213 7a387fff ths
        switch (sel) {
4214 7a387fff ths
        case 0:
4215 f1aa6320 ths
            /* EJTAG support */
4216 d9bea114 aurel32
            gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
4217 2423f660 ths
            rn = "DEPC";
4218 2423f660 ths
            break;
4219 7a387fff ths
        default:
4220 7a387fff ths
            goto die;
4221 7a387fff ths
        }
4222 8c0fdd85 ths
        break;
4223 8c0fdd85 ths
    case 25:
4224 7a387fff ths
        switch (sel) {
4225 7a387fff ths
        case 0:
4226 d9bea114 aurel32
            gen_helper_mtc0_performance0(arg);
4227 2423f660 ths
            rn = "Performance0";
4228 2423f660 ths
            break;
4229 7a387fff ths
        case 1:
4230 d9bea114 aurel32
//            gen_helper_mtc0_performance1(arg);
4231 2423f660 ths
            rn = "Performance1";
4232 2423f660 ths
//            break;
4233 7a387fff ths
        case 2:
4234 d9bea114 aurel32
//            gen_helper_mtc0_performance2(arg);
4235 2423f660 ths
            rn = "Performance2";
4236 2423f660 ths
//            break;
4237 7a387fff ths
        case 3:
4238 d9bea114 aurel32
//            gen_helper_mtc0_performance3(arg);
4239 2423f660 ths
            rn = "Performance3";
4240 2423f660 ths
//            break;
4241 7a387fff ths
        case 4:
4242 d9bea114 aurel32
//            gen_helper_mtc0_performance4(arg);
4243 2423f660 ths
            rn = "Performance4";
4244 2423f660 ths
//            break;
4245 7a387fff ths
        case 5:
4246 d9bea114 aurel32
//            gen_helper_mtc0_performance5(arg);
4247 2423f660 ths
            rn = "Performance5";
4248 2423f660 ths
//            break;
4249 7a387fff ths
        case 6:
4250 d9bea114 aurel32
//            gen_helper_mtc0_performance6(arg);
4251 2423f660 ths
            rn = "Performance6";
4252 2423f660 ths
//            break;
4253 7a387fff ths
        case 7:
4254 d9bea114 aurel32
//            gen_helper_mtc0_performance7(arg);
4255 2423f660 ths
            rn = "Performance7";
4256 2423f660 ths
//            break;
4257 7a387fff ths
        default:
4258 7a387fff ths
            goto die;
4259 7a387fff ths
        }
4260 8c0fdd85 ths
       break;
4261 8c0fdd85 ths
    case 26:
4262 2423f660 ths
        /* ignored */
4263 8c0fdd85 ths
        rn = "ECC";
4264 2423f660 ths
        break;
4265 8c0fdd85 ths
    case 27:
4266 7a387fff ths
        switch (sel) {
4267 7a387fff ths
        case 0 ... 3:
4268 2423f660 ths
            /* ignored */
4269 2423f660 ths
            rn = "CacheErr";
4270 2423f660 ths
            break;
4271 7a387fff ths
        default:
4272 7a387fff ths
            goto die;
4273 7a387fff ths
        }
4274 8c0fdd85 ths
       break;
4275 8c0fdd85 ths
    case 28:
4276 8c0fdd85 ths
        switch (sel) {
4277 8c0fdd85 ths
        case 0:
4278 7a387fff ths
        case 2:
4279 7a387fff ths
        case 4:
4280 7a387fff ths
        case 6:
4281 d9bea114 aurel32
            gen_helper_mtc0_taglo(arg);
4282 8c0fdd85 ths
            rn = "TagLo";
4283 8c0fdd85 ths
            break;
4284 7a387fff ths
        case 1:
4285 7a387fff ths
        case 3:
4286 7a387fff ths
        case 5:
4287 7a387fff ths
        case 7:
4288 d9bea114 aurel32
            gen_helper_mtc0_datalo(arg);
4289 7a387fff ths
            rn = "DataLo";
4290 7a387fff ths
            break;
4291 8c0fdd85 ths
        default:
4292 8c0fdd85 ths
            goto die;
4293 8c0fdd85 ths
        }
4294 8c0fdd85 ths
        break;
4295 8c0fdd85 ths
    case 29:
4296 7a387fff ths
        switch (sel) {
4297 7a387fff ths
        case 0:
4298 7a387fff ths
        case 2:
4299 7a387fff ths
        case 4:
4300 7a387fff ths
        case 6:
4301 d9bea114 aurel32
            gen_helper_mtc0_taghi(arg);
4302 7a387fff ths
            rn = "TagHi";
4303 7a387fff ths
            break;
4304 7a387fff ths
        case 1:
4305 7a387fff ths
        case 3:
4306 7a387fff ths
        case 5:
4307 7a387fff ths
        case 7:
4308 d9bea114 aurel32
            gen_helper_mtc0_datahi(arg);
4309 7a387fff ths
            rn = "DataHi";
4310 7a387fff ths
            break;
4311 7a387fff ths
        default:
4312 7a387fff ths
            rn = "invalid sel";
4313 7a387fff ths
            goto die;
4314 7a387fff ths
        }
4315 8c0fdd85 ths
       break;
4316 8c0fdd85 ths
    case 30:
4317 7a387fff ths
        switch (sel) {
4318 7a387fff ths
        case 0:
4319 d9bea114 aurel32
            gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
4320 2423f660 ths
            rn = "ErrorEPC";
4321 2423f660 ths
            break;
4322 7a387fff ths
        default:
4323 7a387fff ths
            goto die;
4324 7a387fff ths
        }
4325 8c0fdd85 ths
        break;
4326 8c0fdd85 ths
    case 31:
4327 7a387fff ths
        switch (sel) {
4328 7a387fff ths
        case 0:
4329 f1aa6320 ths
            /* EJTAG support */
4330 d9bea114 aurel32
            gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
4331 2423f660 ths
            rn = "DESAVE";
4332 2423f660 ths
            break;
4333 7a387fff ths
        default:
4334 7a387fff ths
            goto die;
4335 7a387fff ths
        }
4336 2423f660 ths
        /* Stop translation as we may have switched the execution mode */
4337 2423f660 ths
        ctx->bstate = BS_STOP;
4338 8c0fdd85 ths
        break;
4339 8c0fdd85 ths
    default:
4340 8c0fdd85 ths
       goto die;
4341 8c0fdd85 ths
    }
4342 2abf314d Blue Swirl
    (void)rn; /* avoid a compiler warning */
4343 d12d51d5 aliguori
    LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4344 bf20dc07 ths
    /* For simplicity assume that all writes can cause interrupts.  */
4345 2e70f6ef pbrook
    if (use_icount) {
4346 2e70f6ef pbrook
        gen_io_end();
4347 2e70f6ef pbrook
        ctx->bstate = BS_STOP;
4348 2e70f6ef pbrook
    }
4349 8c0fdd85 ths
    return;
4350 8c0fdd85 ths
4351 8c0fdd85 ths
die:
4352 d12d51d5 aliguori
    LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4353 8c0fdd85 ths
    generate_exception(ctx, EXCP_RI);
4354 8c0fdd85 ths
}
4355 8c0fdd85 ths
4356 d26bc211 ths
#if defined(TARGET_MIPS64)
4357 d9bea114 aurel32
static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4358 9c2149c8 ths
{
4359 9c2149c8 ths
    const char *rn = "invalid";
4360 9c2149c8 ths
4361 e189e748 ths
    if (sel != 0)
4362 e189e748 ths
        check_insn(env, ctx, ISA_MIPS64);
4363 e189e748 ths
4364 9c2149c8 ths
    switch (reg) {
4365 9c2149c8 ths
    case 0:
4366 9c2149c8 ths
        switch (sel) {
4367 9c2149c8 ths
        case 0:
4368 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
4369 9c2149c8 ths
            rn = "Index";
4370 9c2149c8 ths
            break;
4371 9c2149c8 ths
        case 1:
4372 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4373 d9bea114 aurel32
            gen_helper_mfc0_mvpcontrol(arg);
4374 9c2149c8 ths
            rn = "MVPControl";
4375 ead9360e ths
            break;
4376 9c2149c8 ths
        case 2:
4377 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4378 d9bea114 aurel32
            gen_helper_mfc0_mvpconf0(arg);
4379 9c2149c8 ths
            rn = "MVPConf0";
4380 ead9360e ths
            break;
4381 9c2149c8 ths
        case 3:
4382 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4383 d9bea114 aurel32
            gen_helper_mfc0_mvpconf1(arg);
4384 9c2149c8 ths
            rn = "MVPConf1";
4385 ead9360e ths
            break;
4386 9c2149c8 ths
        default:
4387 9c2149c8 ths
            goto die;
4388 9c2149c8 ths
        }
4389 9c2149c8 ths
        break;
4390 9c2149c8 ths
    case 1:
4391 9c2149c8 ths
        switch (sel) {
4392 9c2149c8 ths
        case 0:
4393 d9bea114 aurel32
            gen_helper_mfc0_random(arg);
4394 9c2149c8 ths
            rn = "Random";
4395 2423f660 ths
            break;
4396 9c2149c8 ths
        case 1:
4397 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4398 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
4399 9c2149c8 ths
            rn = "VPEControl";
4400 ead9360e ths
            break;
4401 9c2149c8 ths
        case 2:
4402 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4403 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
4404 9c2149c8 ths
            rn = "VPEConf0";
4405 ead9360e ths
            break;
4406 9c2149c8 ths
        case 3:
4407 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4408 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
4409 9c2149c8 ths
            rn = "VPEConf1";
4410 ead9360e ths
            break;
4411 9c2149c8 ths
        case 4:
4412 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4413 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
4414 9c2149c8 ths
            rn = "YQMask";
4415 ead9360e ths
            break;
4416 9c2149c8 ths
        case 5:
4417 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4418 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4419 9c2149c8 ths
            rn = "VPESchedule";
4420 ead9360e ths
            break;
4421 9c2149c8 ths
        case 6:
4422 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4423 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4424 9c2149c8 ths
            rn = "VPEScheFBack";
4425 ead9360e ths
            break;
4426 9c2149c8 ths
        case 7:
4427 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4428 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
4429 9c2149c8 ths
            rn = "VPEOpt";
4430 ead9360e ths
            break;
4431 9c2149c8 ths
        default:
4432 9c2149c8 ths
            goto die;
4433 9c2149c8 ths
        }
4434 9c2149c8 ths
        break;
4435 9c2149c8 ths
    case 2:
4436 9c2149c8 ths
        switch (sel) {
4437 9c2149c8 ths
        case 0:
4438 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
4439 2423f660 ths
            rn = "EntryLo0";
4440 2423f660 ths
            break;
4441 9c2149c8 ths
        case 1:
4442 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4443 d9bea114 aurel32
            gen_helper_mfc0_tcstatus(arg);
4444 2423f660 ths
            rn = "TCStatus";
4445 ead9360e ths
            break;
4446 9c2149c8 ths
        case 2:
4447 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4448 d9bea114 aurel32
            gen_helper_mfc0_tcbind(arg);
4449 2423f660 ths
            rn = "TCBind";
4450 ead9360e ths
            break;
4451 9c2149c8 ths
        case 3:
4452 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4453 d9bea114 aurel32
            gen_helper_dmfc0_tcrestart(arg);
4454 2423f660 ths
            rn = "TCRestart";
4455 ead9360e ths
            break;
4456 9c2149c8 ths
        case 4:
4457 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4458 d9bea114 aurel32
            gen_helper_dmfc0_tchalt(arg);
4459 2423f660 ths
            rn = "TCHalt";
4460 ead9360e ths
            break;
4461 9c2149c8 ths
        case 5:
4462 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4463 d9bea114 aurel32
            gen_helper_dmfc0_tccontext(arg);
4464 2423f660 ths
            rn = "TCContext";
4465 ead9360e ths
            break;
4466 9c2149c8 ths
        case 6:
4467 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4468 d9bea114 aurel32
            gen_helper_dmfc0_tcschedule(arg);
4469 2423f660 ths
            rn = "TCSchedule";
4470 ead9360e ths
            break;
4471 9c2149c8 ths
        case 7:
4472 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4473 d9bea114 aurel32
            gen_helper_dmfc0_tcschefback(arg);
4474 2423f660 ths
            rn = "TCScheFBack";
4475 ead9360e ths
            break;
4476 9c2149c8 ths
        default:
4477 9c2149c8 ths
            goto die;
4478 9c2149c8 ths
        }
4479 9c2149c8 ths
        break;
4480 9c2149c8 ths
    case 3:
4481 9c2149c8 ths
        switch (sel) {
4482 9c2149c8 ths
        case 0:
4483 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
4484 2423f660 ths
            rn = "EntryLo1";
4485 2423f660 ths
            break;
4486 9c2149c8 ths
        default:
4487 9c2149c8 ths
            goto die;
4488 1579a72e ths
        }
4489 9c2149c8 ths
        break;
4490 9c2149c8 ths
    case 4:
4491 9c2149c8 ths
        switch (sel) {
4492 9c2149c8 ths
        case 0:
4493 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
4494 2423f660 ths
            rn = "Context";
4495 2423f660 ths
            break;
4496 9c2149c8 ths
        case 1:
4497 d9bea114 aurel32
//            gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4498 2423f660 ths
            rn = "ContextConfig";
4499 2423f660 ths
//            break;
4500 9c2149c8 ths
        default:
4501 9c2149c8 ths
            goto die;
4502 876d4b07 ths
        }
4503 9c2149c8 ths
        break;
4504 9c2149c8 ths
    case 5:
4505 9c2149c8 ths
        switch (sel) {
4506 9c2149c8 ths
        case 0:
4507 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
4508 2423f660 ths
            rn = "PageMask";
4509 2423f660 ths
            break;
4510 9c2149c8 ths
        case 1:
4511 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4512 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
4513 2423f660 ths
            rn = "PageGrain";
4514 2423f660 ths
            break;
4515 9c2149c8 ths
        default:
4516 9c2149c8 ths
            goto die;
4517 876d4b07 ths
        }
4518 9c2149c8 ths
        break;
4519 9c2149c8 ths
    case 6:
4520 9c2149c8 ths
        switch (sel) {
4521 9c2149c8 ths
        case 0:
4522 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
4523 2423f660 ths
            rn = "Wired";
4524 2423f660 ths
            break;
4525 9c2149c8 ths
        case 1:
4526 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4527 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
4528 2423f660 ths
            rn = "SRSConf0";
4529 ead9360e ths
            break;
4530 9c2149c8 ths
        case 2:
4531 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4532 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
4533 2423f660 ths
            rn = "SRSConf1";
4534 ead9360e ths
            break;
4535 9c2149c8 ths
        case 3:
4536 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4537 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
4538 2423f660 ths
            rn = "SRSConf2";
4539 ead9360e ths
            break;
4540 9c2149c8 ths
        case 4:
4541 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4542 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
4543 2423f660 ths
            rn = "SRSConf3";
4544 ead9360e ths
            break;
4545 9c2149c8 ths
        case 5:
4546 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4547 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
4548 2423f660 ths
            rn = "SRSConf4";
4549 ead9360e ths
            break;
4550 9c2149c8 ths
        default:
4551 9c2149c8 ths
            goto die;
4552 876d4b07 ths
        }
4553 9c2149c8 ths
        break;
4554 9c2149c8 ths
    case 7:
4555 9c2149c8 ths
        switch (sel) {
4556 9c2149c8 ths
        case 0:
4557 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4558 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
4559 2423f660 ths
            rn = "HWREna";
4560 2423f660 ths
            break;
4561 9c2149c8 ths
        default:
4562 9c2149c8 ths
            goto die;
4563 876d4b07 ths
        }
4564 9c2149c8 ths
        break;
4565 9c2149c8 ths
    case 8:
4566 9c2149c8 ths
        switch (sel) {
4567 9c2149c8 ths
        case 0:
4568 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
4569 f0b3f3ae ths
            rn = "BadVAddr";
4570 2423f660 ths
            break;
4571 9c2149c8 ths
        default:
4572 9c2149c8 ths
            goto die;
4573 876d4b07 ths
        }
4574 9c2149c8 ths
        break;
4575 9c2149c8 ths
    case 9:
4576 9c2149c8 ths
        switch (sel) {
4577 9c2149c8 ths
        case 0:
4578 2e70f6ef pbrook
            /* Mark as an IO operation because we read the time.  */
4579 2e70f6ef pbrook
            if (use_icount)
4580 2e70f6ef pbrook
                gen_io_start();
4581 d9bea114 aurel32
            gen_helper_mfc0_count(arg);
4582 2e70f6ef pbrook
            if (use_icount) {
4583 2e70f6ef pbrook
                gen_io_end();
4584 2e70f6ef pbrook
                ctx->bstate = BS_STOP;
4585 2e70f6ef pbrook
            }
4586 2423f660 ths
            rn = "Count";
4587 2423f660 ths
            break;
4588 2423f660 ths
        /* 6,7 are implementation dependent */
4589 9c2149c8 ths
        default:
4590 9c2149c8 ths
            goto die;
4591 876d4b07 ths
        }
4592 9c2149c8 ths
        break;
4593 9c2149c8 ths
    case 10:
4594 9c2149c8 ths
        switch (sel) {
4595 9c2149c8 ths
        case 0:
4596 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
4597 2423f660 ths
            rn = "EntryHi";
4598 2423f660 ths
            break;
4599 9c2149c8 ths
        default:
4600 9c2149c8 ths
            goto die;
4601 876d4b07 ths
        }
4602 9c2149c8 ths
        break;
4603 9c2149c8 ths
    case 11:
4604 9c2149c8 ths
        switch (sel) {
4605 9c2149c8 ths
        case 0:
4606 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
4607 2423f660 ths
            rn = "Compare";
4608 2423f660 ths
            break;
4609 876d4b07 ths
        /* 6,7 are implementation dependent */
4610 9c2149c8 ths
        default:
4611 9c2149c8 ths
            goto die;
4612 876d4b07 ths
        }
4613 9c2149c8 ths
        break;
4614 9c2149c8 ths
    case 12:
4615 9c2149c8 ths
        switch (sel) {
4616 9c2149c8 ths
        case 0:
4617 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
4618 2423f660 ths
            rn = "Status";
4619 2423f660 ths
            break;
4620 9c2149c8 ths
        case 1:
4621 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4622 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
4623 2423f660 ths
            rn = "IntCtl";
4624 2423f660 ths
            break;
4625 9c2149c8 ths
        case 2:
4626 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4627 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
4628 2423f660 ths
            rn = "SRSCtl";
4629 2423f660 ths
            break;
4630 9c2149c8 ths
        case 3:
4631 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4632 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
4633 2423f660 ths
            rn = "SRSMap";
4634 2423f660 ths
            break;
4635 9c2149c8 ths
        default:
4636 9c2149c8 ths
            goto die;
4637 876d4b07 ths
        }
4638 9c2149c8 ths
        break;
4639 9c2149c8 ths
    case 13:
4640 9c2149c8 ths
        switch (sel) {
4641 9c2149c8 ths
        case 0:
4642 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
4643 2423f660 ths
            rn = "Cause";
4644 2423f660 ths
            break;
4645 9c2149c8 ths
        default:
4646 9c2149c8 ths
            goto die;
4647 876d4b07 ths
        }
4648 9c2149c8 ths
        break;
4649 9c2149c8 ths
    case 14:
4650 9c2149c8 ths
        switch (sel) {
4651 9c2149c8 ths
        case 0:
4652 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
4653 2423f660 ths
            rn = "EPC";
4654 2423f660 ths
            break;
4655 9c2149c8 ths
        default:
4656 9c2149c8 ths
            goto die;
4657 876d4b07 ths
        }
4658 9c2149c8 ths
        break;
4659 9c2149c8 ths
    case 15:
4660 9c2149c8 ths
        switch (sel) {
4661 9c2149c8 ths
        case 0:
4662 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
4663 2423f660 ths
            rn = "PRid";
4664 2423f660 ths
            break;
4665 9c2149c8 ths
        case 1:
4666 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
4667 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
4668 2423f660 ths
            rn = "EBase";
4669 2423f660 ths
            break;
4670 9c2149c8 ths
        default:
4671 9c2149c8 ths
            goto die;
4672 876d4b07 ths
        }
4673 9c2149c8 ths
        break;
4674 9c2149c8 ths
    case 16:
4675 9c2149c8 ths
        switch (sel) {
4676 9c2149c8 ths
        case 0:
4677 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
4678 9c2149c8 ths
            rn = "Config";
4679 9c2149c8 ths
            break;
4680 9c2149c8 ths
        case 1:
4681 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
4682 9c2149c8 ths
            rn = "Config1";
4683 9c2149c8 ths
            break;
4684 9c2149c8 ths
        case 2:
4685 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
4686 9c2149c8 ths
            rn = "Config2";
4687 9c2149c8 ths
            break;
4688 9c2149c8 ths
        case 3:
4689 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
4690 9c2149c8 ths
            rn = "Config3";
4691 9c2149c8 ths
            break;
4692 9c2149c8 ths
       /* 6,7 are implementation dependent */
4693 f0b3f3ae ths
        case 6:
4694 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
4695 f0b3f3ae ths
            rn = "Config6";
4696 f0b3f3ae ths
            break;
4697 f0b3f3ae ths
        case 7:
4698 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
4699 f0b3f3ae ths
            rn = "Config7";
4700 f0b3f3ae ths
            break;
4701 9c2149c8 ths
        default:
4702 9c2149c8 ths
            goto die;
4703 9c2149c8 ths
        }
4704 9c2149c8 ths
        break;
4705 9c2149c8 ths
    case 17:
4706 9c2149c8 ths
        switch (sel) {
4707 9c2149c8 ths
        case 0:
4708 d9bea114 aurel32
            gen_helper_dmfc0_lladdr(arg);
4709 2423f660 ths
            rn = "LLAddr";
4710 2423f660 ths
            break;
4711 9c2149c8 ths
        default:
4712 9c2149c8 ths
            goto die;
4713 9c2149c8 ths
        }
4714 9c2149c8 ths
        break;
4715 9c2149c8 ths
    case 18:
4716 9c2149c8 ths
        switch (sel) {
4717 fd88b6ab ths
        case 0 ... 7:
4718 d9bea114 aurel32
            gen_helper_1i(dmfc0_watchlo, arg, sel);
4719 2423f660 ths
            rn = "WatchLo";
4720 2423f660 ths
            break;
4721 9c2149c8 ths
        default:
4722 9c2149c8 ths
            goto die;
4723 9c2149c8 ths
        }
4724 9c2149c8 ths
        break;
4725 9c2149c8 ths
    case 19:
4726 9c2149c8 ths
        switch (sel) {
4727 fd88b6ab ths
        case 0 ... 7:
4728 d9bea114 aurel32
            gen_helper_1i(mfc0_watchhi, arg, sel);
4729 2423f660 ths
            rn = "WatchHi";
4730 2423f660 ths
            break;
4731 9c2149c8 ths
        default:
4732 9c2149c8 ths
            goto die;
4733 9c2149c8 ths
        }
4734 9c2149c8 ths
        break;
4735 9c2149c8 ths
    case 20:
4736 9c2149c8 ths
        switch (sel) {
4737 9c2149c8 ths
        case 0:
4738 e189e748 ths
            check_insn(env, ctx, ISA_MIPS3);
4739 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
4740 2423f660 ths
            rn = "XContext";
4741 2423f660 ths
            break;
4742 9c2149c8 ths
        default:
4743 9c2149c8 ths
            goto die;
4744 9c2149c8 ths
        }
4745 9c2149c8 ths
        break;
4746 9c2149c8 ths
    case 21:
4747 9c2149c8 ths
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
4748 9c2149c8 ths
        switch (sel) {
4749 9c2149c8 ths
        case 0:
4750 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
4751 2423f660 ths
            rn = "Framemask";
4752 2423f660 ths
            break;
4753 9c2149c8 ths
        default:
4754 9c2149c8 ths
            goto die;
4755 9c2149c8 ths
        }
4756 9c2149c8 ths
        break;
4757 9c2149c8 ths
    case 22:
4758 d9bea114 aurel32
        tcg_gen_movi_tl(arg, 0); /* unimplemented */
4759 2423f660 ths
        rn = "'Diagnostic"; /* implementation dependent */
4760 2423f660 ths
        break;
4761 9c2149c8 ths
    case 23:
4762 9c2149c8 ths
        switch (sel) {
4763 9c2149c8 ths
        case 0:
4764 d9bea114 aurel32
            gen_helper_mfc0_debug(arg); /* EJTAG support */
4765 2423f660 ths
            rn = "Debug";
4766 2423f660 ths
            break;
4767 9c2149c8 ths
        case 1:
4768 d9bea114 aurel32
//            gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4769 2423f660 ths
            rn = "TraceControl";
4770 2423f660 ths
//            break;
4771 9c2149c8 ths
        case 2:
4772 d9bea114 aurel32
//            gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4773 2423f660 ths
            rn = "TraceControl2";
4774 2423f660 ths
//            break;
4775 9c2149c8 ths
        case 3:
4776 d9bea114 aurel32
//            gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4777 2423f660 ths
            rn = "UserTraceData";
4778 2423f660 ths
//            break;
4779 9c2149c8 ths
        case 4:
4780 d9bea114 aurel32
//            gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4781 2423f660 ths
            rn = "TraceBPC";
4782 2423f660 ths
//            break;
4783 9c2149c8 ths
        default:
4784 9c2149c8 ths
            goto die;
4785 9c2149c8 ths
        }
4786 9c2149c8 ths
        break;
4787 9c2149c8 ths
    case 24:
4788 9c2149c8 ths
        switch (sel) {
4789 9c2149c8 ths
        case 0:
4790 f0b3f3ae ths
            /* EJTAG support */
4791 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
4792 2423f660 ths
            rn = "DEPC";
4793 2423f660 ths
            break;
4794 9c2149c8 ths
        default:
4795 9c2149c8 ths
            goto die;
4796 9c2149c8 ths
        }
4797 9c2149c8 ths
        break;
4798 9c2149c8 ths
    case 25:
4799 9c2149c8 ths
        switch (sel) {
4800 9c2149c8 ths
        case 0:
4801 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
4802 2423f660 ths
            rn = "Performance0";
4803 9c2149c8 ths
            break;
4804 9c2149c8 ths
        case 1:
4805 d9bea114 aurel32
//            gen_helper_dmfc0_performance1(arg);
4806 2423f660 ths
            rn = "Performance1";
4807 2423f660 ths
//            break;
4808 9c2149c8 ths
        case 2:
4809 d9bea114 aurel32
//            gen_helper_dmfc0_performance2(arg);
4810 2423f660 ths
            rn = "Performance2";
4811 2423f660 ths
//            break;
4812 9c2149c8 ths
        case 3:
4813 d9bea114 aurel32
//            gen_helper_dmfc0_performance3(arg);
4814 2423f660 ths
            rn = "Performance3";
4815 2423f660 ths
//            break;
4816 9c2149c8 ths
        case 4:
4817 d9bea114 aurel32
//            gen_helper_dmfc0_performance4(arg);
4818 2423f660 ths
            rn = "Performance4";
4819 2423f660 ths
//            break;
4820 9c2149c8 ths
        case 5:
4821 d9bea114 aurel32
//            gen_helper_dmfc0_performance5(arg);
4822 2423f660 ths
            rn = "Performance5";
4823 2423f660 ths
//            break;
4824 9c2149c8 ths
        case 6:
4825 d9bea114 aurel32
//            gen_helper_dmfc0_performance6(arg);
4826 2423f660 ths
            rn = "Performance6";
4827 2423f660 ths
//            break;
4828 9c2149c8 ths
        case 7:
4829 d9bea114 aurel32
//            gen_helper_dmfc0_performance7(arg);
4830 2423f660 ths
            rn = "Performance7";
4831 2423f660 ths
//            break;
4832 9c2149c8 ths
        default:
4833 9c2149c8 ths
            goto die;
4834 9c2149c8 ths
        }
4835 9c2149c8 ths
        break;
4836 9c2149c8 ths
    case 26:
4837 d9bea114 aurel32
        tcg_gen_movi_tl(arg, 0); /* unimplemented */
4838 da80682b aurel32
        rn = "ECC";
4839 da80682b aurel32
        break;
4840 9c2149c8 ths
    case 27:
4841 9c2149c8 ths
        switch (sel) {
4842 9c2149c8 ths
        /* ignored */
4843 9c2149c8 ths
        case 0 ... 3:
4844 d9bea114 aurel32
            tcg_gen_movi_tl(arg, 0); /* unimplemented */
4845 2423f660 ths
            rn = "CacheErr";
4846 2423f660 ths
            break;
4847 9c2149c8 ths
        default:
4848 9c2149c8 ths
            goto die;
4849 9c2149c8 ths
        }
4850 9c2149c8 ths
        break;
4851 9c2149c8 ths
    case 28:
4852 9c2149c8 ths
        switch (sel) {
4853 9c2149c8 ths
        case 0:
4854 9c2149c8 ths
        case 2:
4855 9c2149c8 ths
        case 4:
4856 9c2149c8 ths
        case 6:
4857 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
4858 9c2149c8 ths
            rn = "TagLo";
4859 9c2149c8 ths
            break;
4860 9c2149c8 ths
        case 1:
4861 9c2149c8 ths
        case 3:
4862 9c2149c8 ths
        case 5:
4863 9c2149c8 ths
        case 7:
4864 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
4865 9c2149c8 ths
            rn = "DataLo";
4866 9c2149c8 ths
            break;
4867 9c2149c8 ths
        default:
4868 9c2149c8 ths
            goto die;
4869 9c2149c8 ths
        }
4870 9c2149c8 ths
        break;
4871 9c2149c8 ths
    case 29:
4872 9c2149c8 ths
        switch (sel) {
4873 9c2149c8 ths
        case 0:
4874 9c2149c8 ths
        case 2:
4875 9c2149c8 ths
        case 4:
4876 9c2149c8 ths
        case 6:
4877 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
4878 9c2149c8 ths
            rn = "TagHi";
4879 9c2149c8 ths
            break;
4880 9c2149c8 ths
        case 1:
4881 9c2149c8 ths
        case 3:
4882 9c2149c8 ths
        case 5:
4883 9c2149c8 ths
        case 7:
4884 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
4885 9c2149c8 ths
            rn = "DataHi";
4886 9c2149c8 ths
            break;
4887 9c2149c8 ths
        default:
4888 9c2149c8 ths
            goto die;
4889 9c2149c8 ths
        }
4890 9c2149c8 ths
        break;
4891 9c2149c8 ths
    case 30:
4892 9c2149c8 ths
        switch (sel) {
4893 9c2149c8 ths
        case 0:
4894 d9bea114 aurel32
            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
4895 2423f660 ths
            rn = "ErrorEPC";
4896 2423f660 ths
            break;
4897 9c2149c8 ths
        default:
4898 9c2149c8 ths
            goto die;
4899 9c2149c8 ths
        }
4900 9c2149c8 ths
        break;
4901 9c2149c8 ths
    case 31:
4902 9c2149c8 ths
        switch (sel) {
4903 9c2149c8 ths
        case 0:
4904 f0b3f3ae ths
            /* EJTAG support */
4905 d9bea114 aurel32
            gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
4906 2423f660 ths
            rn = "DESAVE";
4907 2423f660 ths
            break;
4908 9c2149c8 ths
        default:
4909 9c2149c8 ths
            goto die;
4910 9c2149c8 ths
        }
4911 9c2149c8 ths
        break;
4912 9c2149c8 ths
    default:
4913 876d4b07 ths
        goto die;
4914 9c2149c8 ths
    }
4915 2abf314d Blue Swirl
    (void)rn; /* avoid a compiler warning */
4916 d12d51d5 aliguori
    LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4917 9c2149c8 ths
    return;
4918 9c2149c8 ths
4919 9c2149c8 ths
die:
4920 d12d51d5 aliguori
    LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4921 9c2149c8 ths
    generate_exception(ctx, EXCP_RI);
4922 9c2149c8 ths
}
4923 9c2149c8 ths
4924 d9bea114 aurel32
static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4925 9c2149c8 ths
{
4926 9c2149c8 ths
    const char *rn = "invalid";
4927 9c2149c8 ths
4928 e189e748 ths
    if (sel != 0)
4929 e189e748 ths
        check_insn(env, ctx, ISA_MIPS64);
4930 e189e748 ths
4931 2e70f6ef pbrook
    if (use_icount)
4932 2e70f6ef pbrook
        gen_io_start();
4933 2e70f6ef pbrook
4934 9c2149c8 ths
    switch (reg) {
4935 9c2149c8 ths
    case 0:
4936 9c2149c8 ths
        switch (sel) {
4937 9c2149c8 ths
        case 0:
4938 d9bea114 aurel32
            gen_helper_mtc0_index(arg);
4939 9c2149c8 ths
            rn = "Index";
4940 9c2149c8 ths
            break;
4941 9c2149c8 ths
        case 1:
4942 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4943 d9bea114 aurel32
            gen_helper_mtc0_mvpcontrol(arg);
4944 9c2149c8 ths
            rn = "MVPControl";
4945 ead9360e ths
            break;
4946 9c2149c8 ths
        case 2:
4947 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4948 ead9360e ths
            /* ignored */
4949 9c2149c8 ths
            rn = "MVPConf0";
4950 ead9360e ths
            break;
4951 9c2149c8 ths
        case 3:
4952 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4953 ead9360e ths
            /* ignored */
4954 9c2149c8 ths
            rn = "MVPConf1";
4955 ead9360e ths
            break;
4956 9c2149c8 ths
        default:
4957 9c2149c8 ths
            goto die;
4958 9c2149c8 ths
        }
4959 9c2149c8 ths
        break;
4960 9c2149c8 ths
    case 1:
4961 9c2149c8 ths
        switch (sel) {
4962 9c2149c8 ths
        case 0:
4963 2423f660 ths
            /* ignored */
4964 9c2149c8 ths
            rn = "Random";
4965 2423f660 ths
            break;
4966 9c2149c8 ths
        case 1:
4967 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4968 d9bea114 aurel32
            gen_helper_mtc0_vpecontrol(arg);
4969 9c2149c8 ths
            rn = "VPEControl";
4970 ead9360e ths
            break;
4971 9c2149c8 ths
        case 2:
4972 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4973 d9bea114 aurel32
            gen_helper_mtc0_vpeconf0(arg);
4974 9c2149c8 ths
            rn = "VPEConf0";
4975 ead9360e ths
            break;
4976 9c2149c8 ths
        case 3:
4977 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4978 d9bea114 aurel32
            gen_helper_mtc0_vpeconf1(arg);
4979 9c2149c8 ths
            rn = "VPEConf1";
4980 ead9360e ths
            break;
4981 9c2149c8 ths
        case 4:
4982 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4983 d9bea114 aurel32
            gen_helper_mtc0_yqmask(arg);
4984 9c2149c8 ths
            rn = "YQMask";
4985 ead9360e ths
            break;
4986 9c2149c8 ths
        case 5:
4987 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4988 d9bea114 aurel32
            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
4989 9c2149c8 ths
            rn = "VPESchedule";
4990 ead9360e ths
            break;
4991 9c2149c8 ths
        case 6:
4992 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4993 d9bea114 aurel32
            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
4994 9c2149c8 ths
            rn = "VPEScheFBack";
4995 ead9360e ths
            break;
4996 9c2149c8 ths
        case 7:
4997 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
4998 d9bea114 aurel32
            gen_helper_mtc0_vpeopt(arg);
4999 9c2149c8 ths
            rn = "VPEOpt";
5000 ead9360e ths
            break;
5001 9c2149c8 ths
        default:
5002 9c2149c8 ths
            goto die;
5003 9c2149c8 ths
        }
5004 9c2149c8 ths
        break;
5005 9c2149c8 ths
    case 2:
5006 9c2149c8 ths
        switch (sel) {
5007 9c2149c8 ths
        case 0:
5008 d9bea114 aurel32
            gen_helper_mtc0_entrylo0(arg);
5009 2423f660 ths
            rn = "EntryLo0";
5010 2423f660 ths
            break;
5011 9c2149c8 ths
        case 1:
5012 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
5013 d9bea114 aurel32
            gen_helper_mtc0_tcstatus(arg);
5014 2423f660 ths
            rn = "TCStatus";
5015 ead9360e ths
            break;
5016 9c2149c8 ths
        case 2:
5017 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
5018 d9bea114 aurel32
            gen_helper_mtc0_tcbind(arg);
5019 2423f660 ths
            rn = "TCBind";
5020 ead9360e ths
            break;
5021 9c2149c8 ths
        case 3:
5022 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
5023 d9bea114 aurel32
            gen_helper_mtc0_tcrestart(arg);
5024 2423f660 ths
            rn = "TCRestart";
5025 ead9360e ths
            break;
5026 9c2149c8 ths
        case 4:
5027 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
5028 d9bea114 aurel32
            gen_helper_mtc0_tchalt(arg);
5029 2423f660 ths
            rn = "TCHalt";
5030 ead9360e ths
            break;
5031 9c2149c8 ths
        case 5:
5032 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
5033 d9bea114 aurel32
            gen_helper_mtc0_tccontext(arg);
5034 2423f660 ths
            rn = "TCContext";
5035 ead9360e ths
            break;
5036 9c2149c8 ths
        case 6:
5037 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
5038 d9bea114 aurel32
            gen_helper_mtc0_tcschedule(arg);
5039 2423f660 ths
            rn = "TCSchedule";
5040 ead9360e ths
            break;
5041 9c2149c8 ths
        case 7:
5042 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
5043 d9bea114 aurel32
            gen_helper_mtc0_tcschefback(arg);
5044 2423f660 ths
            rn = "TCScheFBack";
5045 ead9360e ths
            break;
5046 9c2149c8 ths
        default:
5047 9c2149c8 ths
            goto die;
5048 9c2149c8 ths
        }
5049 9c2149c8 ths
        break;
5050 9c2149c8 ths
    case 3:
5051 9c2149c8 ths
        switch (sel) {
5052 9c2149c8 ths
        case 0:
5053 d9bea114 aurel32
            gen_helper_mtc0_entrylo1(arg);
5054 2423f660 ths
            rn = "EntryLo1";
5055 2423f660 ths
            break;
5056 9c2149c8 ths
        default:
5057 9c2149c8 ths
            goto die;
5058 876d4b07 ths
        }
5059 9c2149c8 ths
        break;
5060 9c2149c8 ths
    case 4:
5061 9c2149c8 ths
        switch (sel) {
5062 9c2149c8 ths
        case 0:
5063 d9bea114 aurel32
            gen_helper_mtc0_context(arg);
5064 2423f660 ths
            rn = "Context";
5065 2423f660 ths
            break;
5066 9c2149c8 ths
        case 1:
5067 d9bea114 aurel32
//           gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
5068 2423f660 ths
            rn = "ContextConfig";
5069 2423f660 ths
//           break;
5070 9c2149c8 ths
        default:
5071 9c2149c8 ths
            goto die;
5072 876d4b07 ths
        }
5073 9c2149c8 ths
        break;
5074 9c2149c8 ths
    case 5:
5075 9c2149c8 ths
        switch (sel) {
5076 9c2149c8 ths
        case 0:
5077 d9bea114 aurel32
            gen_helper_mtc0_pagemask(arg);
5078 2423f660 ths
            rn = "PageMask";
5079 2423f660 ths
            break;
5080 9c2149c8 ths
        case 1:
5081 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
5082 d9bea114 aurel32
            gen_helper_mtc0_pagegrain(arg);
5083 2423f660 ths
            rn = "PageGrain";
5084 2423f660 ths
            break;
5085 9c2149c8 ths
        default:
5086 9c2149c8 ths
            goto die;
5087 876d4b07 ths
        }
5088 9c2149c8 ths
        break;
5089 9c2149c8 ths
    case 6:
5090 9c2149c8 ths
        switch (sel) {
5091 9c2149c8 ths
        case 0:
5092 d9bea114 aurel32
            gen_helper_mtc0_wired(arg);
5093 2423f660 ths
            rn = "Wired";
5094 2423f660 ths
            break;
5095 9c2149c8 ths
        case 1:
5096 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
5097 d9bea114 aurel32
            gen_helper_mtc0_srsconf0(arg);
5098 2423f660 ths
            rn = "SRSConf0";
5099 ead9360e ths
            break;
5100 9c2149c8 ths
        case 2:
5101 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
5102 d9bea114 aurel32
            gen_helper_mtc0_srsconf1(arg);
5103 2423f660 ths
            rn = "SRSConf1";
5104 ead9360e ths
            break;
5105 9c2149c8 ths
        case 3:
5106 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
5107 d9bea114 aurel32
            gen_helper_mtc0_srsconf2(arg);
5108 2423f660 ths
            rn = "SRSConf2";
5109 ead9360e ths
            break;
5110 9c2149c8 ths
        case 4:
5111 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
5112 d9bea114 aurel32
            gen_helper_mtc0_srsconf3(arg);
5113 2423f660 ths
            rn = "SRSConf3";
5114 ead9360e ths
            break;
5115 9c2149c8 ths
        case 5:
5116 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
5117 d9bea114 aurel32
            gen_helper_mtc0_srsconf4(arg);
5118 2423f660 ths
            rn = "SRSConf4";
5119 ead9360e ths
            break;
5120 9c2149c8 ths
        default:
5121 9c2149c8 ths
            goto die;
5122 876d4b07 ths
        }
5123 9c2149c8 ths
        break;
5124 9c2149c8 ths
    case 7:
5125 9c2149c8 ths
        switch (sel) {
5126 9c2149c8 ths
        case 0:
5127 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
5128 d9bea114 aurel32
            gen_helper_mtc0_hwrena(arg);
5129 2423f660 ths
            rn = "HWREna";
5130 2423f660 ths
            break;
5131 9c2149c8 ths
        default:
5132 9c2149c8 ths
            goto die;
5133 876d4b07 ths
        }
5134 9c2149c8 ths
        break;
5135 9c2149c8 ths
    case 8:
5136 9c2149c8 ths
        /* ignored */
5137 f0b3f3ae ths
        rn = "BadVAddr";
5138 9c2149c8 ths
        break;
5139 9c2149c8 ths
    case 9:
5140 9c2149c8 ths
        switch (sel) {
5141 9c2149c8 ths
        case 0:
5142 d9bea114 aurel32
            gen_helper_mtc0_count(arg);
5143 2423f660 ths
            rn = "Count";
5144 2423f660 ths
            break;
5145 876d4b07 ths
        /* 6,7 are implementation dependent */
5146 9c2149c8 ths
        default:
5147 9c2149c8 ths
            goto die;
5148 876d4b07 ths
        }
5149 876d4b07 ths
        /* Stop translation as we may have switched the execution mode */
5150 876d4b07 ths
        ctx->bstate = BS_STOP;
5151 9c2149c8 ths
        break;
5152 9c2149c8 ths
    case 10:
5153 9c2149c8 ths
        switch (sel) {
5154 9c2149c8 ths
        case 0:
5155 d9bea114 aurel32
            gen_helper_mtc0_entryhi(arg);
5156 2423f660 ths
            rn = "EntryHi";
5157 2423f660 ths
            break;
5158 9c2149c8 ths
        default:
5159 9c2149c8 ths
            goto die;
5160 876d4b07 ths
        }
5161 9c2149c8 ths
        break;
5162 9c2149c8 ths
    case 11:
5163 9c2149c8 ths
        switch (sel) {
5164 9c2149c8 ths
        case 0:
5165 d9bea114 aurel32
            gen_helper_mtc0_compare(arg);
5166 2423f660 ths
            rn = "Compare";
5167 2423f660 ths
            break;
5168 876d4b07 ths
        /* 6,7 are implementation dependent */
5169 9c2149c8 ths
        default:
5170 9c2149c8 ths
            goto die;
5171 876d4b07 ths
        }
5172 de9a95f0 aurel32
        /* Stop translation as we may have switched the execution mode */
5173 de9a95f0 aurel32
        ctx->bstate = BS_STOP;
5174 9c2149c8 ths
        break;
5175 9c2149c8 ths
    case 12:
5176 9c2149c8 ths
        switch (sel) {
5177 9c2149c8 ths
        case 0:
5178 867abc7e aurel32
            save_cpu_state(ctx, 1);
5179 d9bea114 aurel32
            gen_helper_mtc0_status(arg);
5180 8487327a ths
            /* BS_STOP isn't good enough here, hflags may have changed. */
5181 8487327a ths
            gen_save_pc(ctx->pc + 4);
5182 8487327a ths
            ctx->bstate = BS_EXCP;
5183 2423f660 ths
            rn = "Status";
5184 2423f660 ths
            break;
5185 9c2149c8 ths
        case 1:
5186 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
5187 d9bea114 aurel32
            gen_helper_mtc0_intctl(arg);
5188 8487327a ths
            /* Stop translation as we may have switched the execution mode */
5189 8487327a ths
            ctx->bstate = BS_STOP;
5190 2423f660 ths
            rn = "IntCtl";
5191 2423f660 ths
            break;
5192 9c2149c8 ths
        case 2:
5193 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
5194 d9bea114 aurel32
            gen_helper_mtc0_srsctl(arg);
5195 8487327a ths
            /* Stop translation as we may have switched the execution mode */
5196 8487327a ths
            ctx->bstate = BS_STOP;
5197 2423f660 ths
            rn = "SRSCtl";
5198 2423f660 ths
            break;
5199 9c2149c8 ths
        case 3:
5200 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
5201 d9bea114 aurel32
            gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
5202 8487327a ths
            /* Stop translation as we may have switched the execution mode */
5203 8487327a ths
            ctx->bstate = BS_STOP;
5204 2423f660 ths
            rn = "SRSMap";
5205 2423f660 ths
            break;
5206 2423f660 ths
        default:
5207 9c2149c8 ths
            goto die;
5208 876d4b07 ths
        }
5209 9c2149c8 ths
        break;
5210 9c2149c8 ths
    case 13:
5211 9c2149c8 ths
        switch (sel) {
5212 9c2149c8 ths
        case 0:
5213 867abc7e aurel32
            save_cpu_state(ctx, 1);
5214 5dc5d9f0 Aurelien Jarno
            /* Mark as an IO operation because we may trigger a software
5215 5dc5d9f0 Aurelien Jarno
               interrupt.  */
5216 5dc5d9f0 Aurelien Jarno
            if (use_icount) {
5217 5dc5d9f0 Aurelien Jarno
                gen_io_start();
5218 5dc5d9f0 Aurelien Jarno
            }
5219 d9bea114 aurel32
            gen_helper_mtc0_cause(arg);
5220 5dc5d9f0 Aurelien Jarno
            if (use_icount) {
5221 5dc5d9f0 Aurelien Jarno
                gen_io_end();
5222 5dc5d9f0 Aurelien Jarno
            }
5223 5dc5d9f0 Aurelien Jarno
            /* Stop translation as we may have triggered an intetrupt */
5224 5dc5d9f0 Aurelien Jarno
            ctx->bstate = BS_STOP;
5225 2423f660 ths
            rn = "Cause";
5226 2423f660 ths
            break;
5227 9c2149c8 ths
        default:
5228 9c2149c8 ths
            goto die;
5229 876d4b07 ths
        }
5230 9c2149c8 ths
        break;
5231 9c2149c8 ths
    case 14:
5232 9c2149c8 ths
        switch (sel) {
5233 9c2149c8 ths
        case 0:
5234 d9bea114 aurel32
            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
5235 2423f660 ths
            rn = "EPC";
5236 2423f660 ths
            break;
5237 9c2149c8 ths
        default:
5238 9c2149c8 ths
            goto die;
5239 876d4b07 ths
        }
5240 9c2149c8 ths
        break;
5241 9c2149c8 ths
    case 15:
5242 9c2149c8 ths
        switch (sel) {
5243 9c2149c8 ths
        case 0:
5244 2423f660 ths
            /* ignored */
5245 2423f660 ths
            rn = "PRid";
5246 2423f660 ths
            break;
5247 9c2149c8 ths
        case 1:
5248 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
5249 d9bea114 aurel32
            gen_helper_mtc0_ebase(arg);
5250 2423f660 ths
            rn = "EBase";
5251 2423f660 ths
            break;
5252 9c2149c8 ths
        default:
5253 9c2149c8 ths
            goto die;
5254 876d4b07 ths
        }
5255 9c2149c8 ths
        break;
5256 9c2149c8 ths
    case 16:
5257 9c2149c8 ths
        switch (sel) {
5258 9c2149c8 ths
        case 0:
5259 d9bea114 aurel32
            gen_helper_mtc0_config0(arg);
5260 9c2149c8 ths
            rn = "Config";
5261 2423f660 ths
            /* Stop translation as we may have switched the execution mode */
5262 2423f660 ths
            ctx->bstate = BS_STOP;
5263 9c2149c8 ths
            break;
5264 9c2149c8 ths
        case 1:
5265 1fc7bf6e aurel32
            /* ignored, read only */
5266 9c2149c8 ths
            rn = "Config1";
5267 9c2149c8 ths
            break;
5268 9c2149c8 ths
        case 2:
5269 d9bea114 aurel32
            gen_helper_mtc0_config2(arg);
5270 9c2149c8 ths
            rn = "Config2";
5271 2423f660 ths
            /* Stop translation as we may have switched the execution mode */
5272 2423f660 ths
            ctx->bstate = BS_STOP;
5273 9c2149c8 ths
            break;
5274 9c2149c8 ths
        case 3:
5275 2423f660 ths
            /* ignored */
5276 9c2149c8 ths
            rn = "Config3";
5277 9c2149c8 ths
            break;
5278 9c2149c8 ths
        /* 6,7 are implementation dependent */
5279 9c2149c8 ths
        default:
5280 9c2149c8 ths
            rn = "Invalid config selector";
5281 9c2149c8 ths
            goto die;
5282 9c2149c8 ths
        }
5283 9c2149c8 ths
        break;
5284 9c2149c8 ths
    case 17:
5285 9c2149c8 ths
        switch (sel) {
5286 9c2149c8 ths
        case 0:
5287 2a6e32dd Aurelien Jarno
            gen_helper_mtc0_lladdr(arg);
5288 2423f660 ths
            rn = "LLAddr";
5289 2423f660 ths
            break;
5290 9c2149c8 ths
        default:
5291 9c2149c8 ths
            goto die;
5292 9c2149c8 ths
        }
5293 9c2149c8 ths
        break;
5294 9c2149c8 ths
    case 18:
5295 9c2149c8 ths
        switch (sel) {
5296 fd88b6ab ths
        case 0 ... 7:
5297 d9bea114 aurel32
            gen_helper_1i(mtc0_watchlo, arg, sel);
5298 2423f660 ths
            rn = "WatchLo";
5299 2423f660 ths
            break;
5300 9c2149c8 ths
        default:
5301 9c2149c8 ths
            goto die;
5302 9c2149c8 ths
        }
5303 9c2149c8 ths
        break;
5304 9c2149c8 ths
    case 19:
5305 9c2149c8 ths
        switch (sel) {
5306 fd88b6ab ths
        case 0 ... 7:
5307 d9bea114 aurel32
            gen_helper_1i(mtc0_watchhi, arg, sel);
5308 2423f660 ths
            rn = "WatchHi";
5309 2423f660 ths
            break;
5310 9c2149c8 ths
        default:
5311 9c2149c8 ths
            goto die;
5312 9c2149c8 ths
        }
5313 9c2149c8 ths
        break;
5314 9c2149c8 ths
    case 20:
5315 9c2149c8 ths
        switch (sel) {
5316 9c2149c8 ths
        case 0:
5317 e189e748 ths
            check_insn(env, ctx, ISA_MIPS3);
5318 d9bea114 aurel32
            gen_helper_mtc0_xcontext(arg);
5319 2423f660 ths
            rn = "XContext";
5320 2423f660 ths
            break;
5321 9c2149c8 ths
        default:
5322 9c2149c8 ths
            goto die;
5323 9c2149c8 ths
        }
5324 9c2149c8 ths
        break;
5325 9c2149c8 ths
    case 21:
5326 9c2149c8 ths
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
5327 9c2149c8 ths
        switch (sel) {
5328 9c2149c8 ths
        case 0:
5329 d9bea114 aurel32
            gen_helper_mtc0_framemask(arg);
5330 2423f660 ths
            rn = "Framemask";
5331 2423f660 ths
            break;
5332 9c2149c8 ths
        default:
5333 9c2149c8 ths
            goto die;
5334 9c2149c8 ths
        }
5335 9c2149c8 ths
        break;
5336 9c2149c8 ths
    case 22:
5337 9c2149c8 ths
        /* ignored */
5338 9c2149c8 ths
        rn = "Diagnostic"; /* implementation dependent */
5339 876d4b07 ths
        break;
5340 9c2149c8 ths
    case 23:
5341 9c2149c8 ths
        switch (sel) {
5342 9c2149c8 ths
        case 0:
5343 d9bea114 aurel32
            gen_helper_mtc0_debug(arg); /* EJTAG support */
5344 8487327a ths
            /* BS_STOP isn't good enough here, hflags may have changed. */
5345 8487327a ths
            gen_save_pc(ctx->pc + 4);
5346 8487327a ths
            ctx->bstate = BS_EXCP;
5347 2423f660 ths
            rn = "Debug";
5348 2423f660 ths
            break;
5349 9c2149c8 ths
        case 1:
5350 d9bea114 aurel32
//            gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
5351 8487327a ths
            /* Stop translation as we may have switched the execution mode */
5352 8487327a ths
            ctx->bstate = BS_STOP;
5353 2423f660 ths
            rn = "TraceControl";
5354 2423f660 ths
//            break;
5355 9c2149c8 ths
        case 2:
5356 d9bea114 aurel32
//            gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
5357 8487327a ths
            /* Stop translation as we may have switched the execution mode */
5358 8487327a ths
            ctx->bstate = BS_STOP;
5359 2423f660 ths
            rn = "TraceControl2";
5360 2423f660 ths
//            break;
5361 9c2149c8 ths
        case 3:
5362 d9bea114 aurel32
//            gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
5363 8487327a ths
            /* Stop translation as we may have switched the execution mode */
5364 8487327a ths
            ctx->bstate = BS_STOP;
5365 2423f660 ths
            rn = "UserTraceData";
5366 2423f660 ths
//            break;
5367 9c2149c8 ths
        case 4:
5368 d9bea114 aurel32
//            gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
5369 8487327a ths
            /* Stop translation as we may have switched the execution mode */
5370 8487327a ths
            ctx->bstate = BS_STOP;
5371 2423f660 ths
            rn = "TraceBPC";
5372 2423f660 ths
//            break;
5373 9c2149c8 ths
        default:
5374 9c2149c8 ths
            goto die;
5375 9c2149c8 ths
        }
5376 9c2149c8 ths
        break;
5377 9c2149c8 ths
    case 24:
5378 9c2149c8 ths
        switch (sel) {
5379 9c2149c8 ths
        case 0:
5380 f1aa6320 ths
            /* EJTAG support */
5381 d9bea114 aurel32
            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
5382 2423f660 ths
            rn = "DEPC";
5383 2423f660 ths
            break;
5384 9c2149c8 ths
        default:
5385 9c2149c8 ths
            goto die;
5386 9c2149c8 ths
        }
5387 9c2149c8 ths
        break;
5388 9c2149c8 ths
    case 25:
5389 9c2149c8 ths
        switch (sel) {
5390 9c2149c8 ths
        case 0:
5391 d9bea114 aurel32
            gen_helper_mtc0_performance0(arg);
5392 2423f660 ths
            rn = "Performance0";
5393 2423f660 ths
            break;
5394 9c2149c8 ths
        case 1:
5395 d9bea114 aurel32
//            gen_helper_mtc0_performance1(arg);
5396 2423f660 ths
            rn = "Performance1";
5397 2423f660 ths
//            break;
5398 9c2149c8 ths
        case 2:
5399 d9bea114 aurel32
//            gen_helper_mtc0_performance2(arg);
5400 2423f660 ths
            rn = "Performance2";
5401 2423f660 ths
//            break;
5402 9c2149c8 ths
        case 3:
5403 d9bea114 aurel32
//            gen_helper_mtc0_performance3(arg);
5404 2423f660 ths
            rn = "Performance3";
5405 2423f660 ths
//            break;
5406 9c2149c8 ths
        case 4:
5407 d9bea114 aurel32
//            gen_helper_mtc0_performance4(arg);
5408 2423f660 ths
            rn = "Performance4";
5409 2423f660 ths
//            break;
5410 9c2149c8 ths
        case 5:
5411 d9bea114 aurel32
//            gen_helper_mtc0_performance5(arg);
5412 2423f660 ths
            rn = "Performance5";
5413 2423f660 ths
//            break;
5414 9c2149c8 ths
        case 6:
5415 d9bea114 aurel32
//            gen_helper_mtc0_performance6(arg);
5416 2423f660 ths
            rn = "Performance6";
5417 2423f660 ths
//            break;
5418 9c2149c8 ths
        case 7:
5419 d9bea114 aurel32
//            gen_helper_mtc0_performance7(arg);
5420 2423f660 ths
            rn = "Performance7";
5421 2423f660 ths
//            break;
5422 9c2149c8 ths
        default:
5423 9c2149c8 ths
            goto die;
5424 9c2149c8 ths
        }
5425 876d4b07 ths
        break;
5426 9c2149c8 ths
    case 26:
5427 876d4b07 ths
        /* ignored */
5428 9c2149c8 ths
        rn = "ECC";
5429 876d4b07 ths
        break;
5430 9c2149c8 ths
    case 27:
5431 9c2149c8 ths
        switch (sel) {
5432 9c2149c8 ths
        case 0 ... 3:
5433 2423f660 ths
            /* ignored */
5434 2423f660 ths
            rn = "CacheErr";
5435 2423f660 ths
            break;
5436 9c2149c8 ths
        default:
5437 9c2149c8 ths
            goto die;
5438 9c2149c8 ths
        }
5439 876d4b07 ths
        break;
5440 9c2149c8 ths
    case 28:
5441 9c2149c8 ths
        switch (sel) {
5442 9c2149c8 ths
        case 0:
5443 9c2149c8 ths
        case 2:
5444 9c2149c8 ths
        case 4:
5445 9c2149c8 ths
        case 6:
5446 d9bea114 aurel32
            gen_helper_mtc0_taglo(arg);
5447 9c2149c8 ths
            rn = "TagLo";
5448 9c2149c8 ths
            break;
5449 9c2149c8 ths
        case 1:
5450 9c2149c8 ths
        case 3:
5451 9c2149c8 ths
        case 5:
5452 9c2149c8 ths
        case 7:
5453 d9bea114 aurel32
            gen_helper_mtc0_datalo(arg);
5454 9c2149c8 ths
            rn = "DataLo";
5455 9c2149c8 ths
            break;
5456 9c2149c8 ths
        default:
5457 9c2149c8 ths
            goto die;
5458 9c2149c8 ths
        }
5459 9c2149c8 ths
        break;
5460 9c2149c8 ths
    case 29:
5461 9c2149c8 ths
        switch (sel) {
5462 9c2149c8 ths
        case 0:
5463 9c2149c8 ths
        case 2:
5464 9c2149c8 ths
        case 4:
5465 9c2149c8 ths
        case 6:
5466 d9bea114 aurel32
            gen_helper_mtc0_taghi(arg);
5467 9c2149c8 ths
            rn = "TagHi";
5468 9c2149c8 ths
            break;
5469 9c2149c8 ths
        case 1:
5470 9c2149c8 ths
        case 3:
5471 9c2149c8 ths
        case 5:
5472 9c2149c8 ths
        case 7:
5473 d9bea114 aurel32
            gen_helper_mtc0_datahi(arg);
5474 9c2149c8 ths
            rn = "DataHi";
5475 9c2149c8 ths
            break;
5476 9c2149c8 ths
        default:
5477 9c2149c8 ths
            rn = "invalid sel";
5478 9c2149c8 ths
            goto die;
5479 9c2149c8 ths
        }
5480 876d4b07 ths
        break;
5481 9c2149c8 ths
    case 30:
5482 9c2149c8 ths
        switch (sel) {
5483 9c2149c8 ths
        case 0:
5484 d9bea114 aurel32
            tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
5485 2423f660 ths
            rn = "ErrorEPC";
5486 2423f660 ths
            break;
5487 9c2149c8 ths
        default:
5488 9c2149c8 ths
            goto die;
5489 9c2149c8 ths
        }
5490 9c2149c8 ths
        break;
5491 9c2149c8 ths
    case 31:
5492 9c2149c8 ths
        switch (sel) {
5493 9c2149c8 ths
        case 0:
5494 f1aa6320 ths
            /* EJTAG support */
5495 d9bea114 aurel32
            gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
5496 2423f660 ths
            rn = "DESAVE";
5497 2423f660 ths
            break;
5498 9c2149c8 ths
        default:
5499 9c2149c8 ths
            goto die;
5500 9c2149c8 ths
        }
5501 876d4b07 ths
        /* Stop translation as we may have switched the execution mode */
5502 876d4b07 ths
        ctx->bstate = BS_STOP;
5503 9c2149c8 ths
        break;
5504 9c2149c8 ths
    default:
5505 876d4b07 ths
        goto die;
5506 9c2149c8 ths
    }
5507 2abf314d Blue Swirl
    (void)rn; /* avoid a compiler warning */
5508 d12d51d5 aliguori
    LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5509 bf20dc07 ths
    /* For simplicity assume that all writes can cause interrupts.  */
5510 2e70f6ef pbrook
    if (use_icount) {
5511 2e70f6ef pbrook
        gen_io_end();
5512 2e70f6ef pbrook
        ctx->bstate = BS_STOP;
5513 2e70f6ef pbrook
    }
5514 9c2149c8 ths
    return;
5515 9c2149c8 ths
5516 9c2149c8 ths
die:
5517 d12d51d5 aliguori
    LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5518 9c2149c8 ths
    generate_exception(ctx, EXCP_RI);
5519 9c2149c8 ths
}
5520 d26bc211 ths
#endif /* TARGET_MIPS64 */
5521 9c2149c8 ths
5522 6c5c1e20 ths
static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
5523 ead9360e ths
                     int u, int sel, int h)
5524 ead9360e ths
{
5525 ead9360e ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5526 a7812ae4 pbrook
    TCGv t0 = tcg_temp_local_new();
5527 ead9360e ths
5528 ead9360e ths
    if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5529 b5dc7732 ths
        ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5530 b5dc7732 ths
         (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5531 1a3fd9c3 ths
        tcg_gen_movi_tl(t0, -1);
5532 ead9360e ths
    else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5533 ead9360e ths
             (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5534 1a3fd9c3 ths
        tcg_gen_movi_tl(t0, -1);
5535 ead9360e ths
    else if (u == 0) {
5536 ead9360e ths
        switch (rt) {
5537 ead9360e ths
        case 2:
5538 ead9360e ths
            switch (sel) {
5539 ead9360e ths
            case 1:
5540 a7812ae4 pbrook
                gen_helper_mftc0_tcstatus(t0);
5541 ead9360e ths
                break;
5542 ead9360e ths
            case 2:
5543 a7812ae4 pbrook
                gen_helper_mftc0_tcbind(t0);
5544 ead9360e ths
                break;
5545 ead9360e ths
            case 3:
5546 a7812ae4 pbrook
                gen_helper_mftc0_tcrestart(t0);
5547 ead9360e ths
                break;
5548 ead9360e ths
            case 4:
5549 a7812ae4 pbrook
                gen_helper_mftc0_tchalt(t0);
5550 ead9360e ths
                break;
5551 ead9360e ths
            case 5:
5552 a7812ae4 pbrook
                gen_helper_mftc0_tccontext(t0);
5553 ead9360e ths
                break;
5554 ead9360e ths
            case 6:
5555 a7812ae4 pbrook
                gen_helper_mftc0_tcschedule(t0);
5556 ead9360e ths
                break;
5557 ead9360e ths
            case 7:
5558 a7812ae4 pbrook
                gen_helper_mftc0_tcschefback(t0);
5559 ead9360e ths
                break;
5560 ead9360e ths
            default:
5561 1a3fd9c3 ths
                gen_mfc0(env, ctx, t0, rt, sel);
5562 ead9360e ths
                break;
5563 ead9360e ths
            }
5564 ead9360e ths
            break;
5565 ead9360e ths
        case 10:
5566 ead9360e ths
            switch (sel) {
5567 ead9360e ths
            case 0:
5568 a7812ae4 pbrook
                gen_helper_mftc0_entryhi(t0);
5569 ead9360e ths
                break;
5570 ead9360e ths
            default:
5571 1a3fd9c3 ths
                gen_mfc0(env, ctx, t0, rt, sel);
5572 ead9360e ths
                break;
5573 ead9360e ths
            }
5574 ead9360e ths
        case 12:
5575 ead9360e ths
            switch (sel) {
5576 ead9360e ths
            case 0:
5577 a7812ae4 pbrook
                gen_helper_mftc0_status(t0);
5578 ead9360e ths
                break;
5579 ead9360e ths
            default:
5580 1a3fd9c3 ths
                gen_mfc0(env, ctx, t0, rt, sel);
5581 ead9360e ths
                break;
5582 ead9360e ths
            }
5583 ead9360e ths
        case 23:
5584 ead9360e ths
            switch (sel) {
5585 ead9360e ths
            case 0:
5586 a7812ae4 pbrook
                gen_helper_mftc0_debug(t0);
5587 ead9360e ths
                break;
5588 ead9360e ths
            default:
5589 1a3fd9c3 ths
                gen_mfc0(env, ctx, t0, rt, sel);
5590 ead9360e ths
                break;
5591 ead9360e ths
            }
5592 ead9360e ths
            break;
5593 ead9360e ths
        default:
5594 1a3fd9c3 ths
            gen_mfc0(env, ctx, t0, rt, sel);
5595 ead9360e ths
        }
5596 ead9360e ths
    } else switch (sel) {
5597 ead9360e ths
    /* GPR registers. */
5598 ead9360e ths
    case 0:
5599 a7812ae4 pbrook
        gen_helper_1i(mftgpr, t0, rt);
5600 ead9360e ths
        break;
5601 ead9360e ths
    /* Auxiliary CPU registers */
5602 ead9360e ths
    case 1:
5603 ead9360e ths
        switch (rt) {
5604 ead9360e ths
        case 0:
5605 a7812ae4 pbrook
            gen_helper_1i(mftlo, t0, 0);
5606 ead9360e ths
            break;
5607 ead9360e ths
        case 1:
5608 a7812ae4 pbrook
            gen_helper_1i(mfthi, t0, 0);
5609 ead9360e ths
            break;
5610 ead9360e ths
        case 2:
5611 a7812ae4 pbrook
            gen_helper_1i(mftacx, t0, 0);
5612 ead9360e ths
            break;
5613 ead9360e ths
        case 4:
5614 a7812ae4 pbrook
            gen_helper_1i(mftlo, t0, 1);
5615 ead9360e ths
            break;
5616 ead9360e ths
        case 5:
5617 a7812ae4 pbrook
            gen_helper_1i(mfthi, t0, 1);
5618 ead9360e ths
            break;
5619 ead9360e ths
        case 6:
5620 a7812ae4 pbrook
            gen_helper_1i(mftacx, t0, 1);
5621 ead9360e ths
            break;
5622 ead9360e ths
        case 8:
5623 a7812ae4 pbrook
            gen_helper_1i(mftlo, t0, 2);
5624 ead9360e ths
            break;
5625 ead9360e ths
        case 9:
5626 a7812ae4 pbrook
            gen_helper_1i(mfthi, t0, 2);
5627 ead9360e ths
            break;
5628 ead9360e ths
        case 10:
5629 a7812ae4 pbrook
            gen_helper_1i(mftacx, t0, 2);
5630 ead9360e ths
            break;
5631 ead9360e ths
        case 12:
5632 a7812ae4 pbrook
            gen_helper_1i(mftlo, t0, 3);
5633 ead9360e ths
            break;
5634 ead9360e ths
        case 13:
5635 a7812ae4 pbrook
            gen_helper_1i(mfthi, t0, 3);
5636 ead9360e ths
            break;
5637 ead9360e ths
        case 14:
5638 a7812ae4 pbrook
            gen_helper_1i(mftacx, t0, 3);
5639 ead9360e ths
            break;
5640 ead9360e ths
        case 16:
5641 a7812ae4 pbrook
            gen_helper_mftdsp(t0);
5642 ead9360e ths
            break;
5643 ead9360e ths
        default:
5644 ead9360e ths
            goto die;
5645 ead9360e ths
        }
5646 ead9360e ths
        break;
5647 ead9360e ths
    /* Floating point (COP1). */
5648 ead9360e ths
    case 2:
5649 ead9360e ths
        /* XXX: For now we support only a single FPU context. */
5650 ead9360e ths
        if (h == 0) {
5651 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
5652 b6d96bed ths
5653 b6d96bed ths
            gen_load_fpr32(fp0, rt);
5654 b6d96bed ths
            tcg_gen_ext_i32_tl(t0, fp0);
5655 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
5656 ead9360e ths
        } else {
5657 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
5658 b6d96bed ths
5659 b6d96bed ths
            gen_load_fpr32h(fp0, rt);
5660 b6d96bed ths
            tcg_gen_ext_i32_tl(t0, fp0);
5661 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
5662 ead9360e ths
        }
5663 ead9360e ths
        break;
5664 ead9360e ths
    case 3:
5665 ead9360e ths
        /* XXX: For now we support only a single FPU context. */
5666 a7812ae4 pbrook
        gen_helper_1i(cfc1, t0, rt);
5667 ead9360e ths
        break;
5668 ead9360e ths
    /* COP2: Not implemented. */
5669 ead9360e ths
    case 4:
5670 ead9360e ths
    case 5:
5671 ead9360e ths
        /* fall through */
5672 ead9360e ths
    default:
5673 ead9360e ths
        goto die;
5674 ead9360e ths
    }
5675 d12d51d5 aliguori
    LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5676 1a3fd9c3 ths
    gen_store_gpr(t0, rd);
5677 1a3fd9c3 ths
    tcg_temp_free(t0);
5678 ead9360e ths
    return;
5679 ead9360e ths
5680 ead9360e ths
die:
5681 1a3fd9c3 ths
    tcg_temp_free(t0);
5682 d12d51d5 aliguori
    LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5683 ead9360e ths
    generate_exception(ctx, EXCP_RI);
5684 ead9360e ths
}
5685 ead9360e ths
5686 6c5c1e20 ths
static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
5687 ead9360e ths
                     int u, int sel, int h)
5688 ead9360e ths
{
5689 ead9360e ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5690 a7812ae4 pbrook
    TCGv t0 = tcg_temp_local_new();
5691 ead9360e ths
5692 1a3fd9c3 ths
    gen_load_gpr(t0, rt);
5693 ead9360e ths
    if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5694 b5dc7732 ths
        ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5695 b5dc7732 ths
         (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5696 ead9360e ths
        /* NOP */ ;
5697 ead9360e ths
    else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5698 ead9360e ths
             (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5699 ead9360e ths
        /* NOP */ ;
5700 ead9360e ths
    else if (u == 0) {
5701 ead9360e ths
        switch (rd) {
5702 ead9360e ths
        case 2:
5703 ead9360e ths
            switch (sel) {
5704 ead9360e ths
            case 1:
5705 a7812ae4 pbrook
                gen_helper_mttc0_tcstatus(t0);
5706 ead9360e ths
                break;
5707 ead9360e ths
            case 2:
5708 a7812ae4 pbrook
                gen_helper_mttc0_tcbind(t0);
5709 ead9360e ths
                break;
5710 ead9360e ths
            case 3:
5711 a7812ae4 pbrook
                gen_helper_mttc0_tcrestart(t0);
5712 ead9360e ths
                break;
5713 ead9360e ths
            case 4:
5714 a7812ae4 pbrook
                gen_helper_mttc0_tchalt(t0);
5715 ead9360e ths
                break;
5716 ead9360e ths
            case 5:
5717 a7812ae4 pbrook
                gen_helper_mttc0_tccontext(t0);
5718 ead9360e ths
                break;
5719 ead9360e ths
            case 6:
5720 a7812ae4 pbrook
                gen_helper_mttc0_tcschedule(t0);
5721 ead9360e ths
                break;
5722 ead9360e ths
            case 7:
5723 a7812ae4 pbrook
                gen_helper_mttc0_tcschefback(t0);
5724 ead9360e ths
                break;
5725 ead9360e ths
            default:
5726 1a3fd9c3 ths
                gen_mtc0(env, ctx, t0, rd, sel);
5727 ead9360e ths
                break;
5728 ead9360e ths
            }
5729 ead9360e ths
            break;
5730 ead9360e ths
        case 10:
5731 ead9360e ths
            switch (sel) {
5732 ead9360e ths
            case 0:
5733 a7812ae4 pbrook
                gen_helper_mttc0_entryhi(t0);
5734 ead9360e ths
                break;
5735 ead9360e ths
            default:
5736 1a3fd9c3 ths
                gen_mtc0(env, ctx, t0, rd, sel);
5737 ead9360e ths
                break;
5738 ead9360e ths
            }
5739 ead9360e ths
        case 12:
5740 ead9360e ths
            switch (sel) {
5741 ead9360e ths
            case 0:
5742 a7812ae4 pbrook
                gen_helper_mttc0_status(t0);
5743 ead9360e ths
                break;
5744 ead9360e ths
            default:
5745 1a3fd9c3 ths
                gen_mtc0(env, ctx, t0, rd, sel);
5746 ead9360e ths
                break;
5747 ead9360e ths
            }
5748 ead9360e ths
        case 23:
5749 ead9360e ths
            switch (sel) {
5750 ead9360e ths
            case 0:
5751 a7812ae4 pbrook
                gen_helper_mttc0_debug(t0);
5752 ead9360e ths
                break;
5753 ead9360e ths
            default:
5754 1a3fd9c3 ths
                gen_mtc0(env, ctx, t0, rd, sel);
5755 ead9360e ths
                break;
5756 ead9360e ths
            }
5757 ead9360e ths
            break;
5758 ead9360e ths
        default:
5759 1a3fd9c3 ths
            gen_mtc0(env, ctx, t0, rd, sel);
5760 ead9360e ths
        }
5761 ead9360e ths
    } else switch (sel) {
5762 ead9360e ths
    /* GPR registers. */
5763 ead9360e ths
    case 0:
5764 a7812ae4 pbrook
        gen_helper_1i(mttgpr, t0, rd);
5765 ead9360e ths
        break;
5766 ead9360e ths
    /* Auxiliary CPU registers */
5767 ead9360e ths
    case 1:
5768 ead9360e ths
        switch (rd) {
5769 ead9360e ths
        case 0:
5770 a7812ae4 pbrook
            gen_helper_1i(mttlo, t0, 0);
5771 ead9360e ths
            break;
5772 ead9360e ths
        case 1:
5773 a7812ae4 pbrook
            gen_helper_1i(mtthi, t0, 0);
5774 ead9360e ths
            break;
5775 ead9360e ths
        case 2:
5776 a7812ae4 pbrook
            gen_helper_1i(mttacx, t0, 0);
5777 ead9360e ths
            break;
5778 ead9360e ths
        case 4:
5779 a7812ae4 pbrook
            gen_helper_1i(mttlo, t0, 1);
5780 ead9360e ths
            break;
5781 ead9360e ths
        case 5:
5782 a7812ae4 pbrook
            gen_helper_1i(mtthi, t0, 1);
5783 ead9360e ths
            break;
5784 ead9360e ths
        case 6:
5785 a7812ae4 pbrook
            gen_helper_1i(mttacx, t0, 1);
5786 ead9360e ths
            break;
5787 ead9360e ths
        case 8:
5788 a7812ae4 pbrook
            gen_helper_1i(mttlo, t0, 2);
5789 ead9360e ths
            break;
5790 ead9360e ths
        case 9:
5791 a7812ae4 pbrook
            gen_helper_1i(mtthi, t0, 2);
5792 ead9360e ths
            break;
5793 ead9360e ths
        case 10:
5794 a7812ae4 pbrook
            gen_helper_1i(mttacx, t0, 2);
5795 ead9360e ths
            break;
5796 ead9360e ths
        case 12:
5797 a7812ae4 pbrook
            gen_helper_1i(mttlo, t0, 3);
5798 ead9360e ths
            break;
5799 ead9360e ths
        case 13:
5800 a7812ae4 pbrook
            gen_helper_1i(mtthi, t0, 3);
5801 ead9360e ths
            break;
5802 ead9360e ths
        case 14:
5803 a7812ae4 pbrook
            gen_helper_1i(mttacx, t0, 3);
5804 ead9360e ths
            break;
5805 ead9360e ths
        case 16:
5806 a7812ae4 pbrook
            gen_helper_mttdsp(t0);
5807 ead9360e ths
            break;
5808 ead9360e ths
        default:
5809 ead9360e ths
            goto die;
5810 ead9360e ths
        }
5811 ead9360e ths
        break;
5812 ead9360e ths
    /* Floating point (COP1). */
5813 ead9360e ths
    case 2:
5814 ead9360e ths
        /* XXX: For now we support only a single FPU context. */
5815 ead9360e ths
        if (h == 0) {
5816 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
5817 b6d96bed ths
5818 b6d96bed ths
            tcg_gen_trunc_tl_i32(fp0, t0);
5819 b6d96bed ths
            gen_store_fpr32(fp0, rd);
5820 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
5821 ead9360e ths
        } else {
5822 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
5823 b6d96bed ths
5824 b6d96bed ths
            tcg_gen_trunc_tl_i32(fp0, t0);
5825 b6d96bed ths
            gen_store_fpr32h(fp0, rd);
5826 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
5827 ead9360e ths
        }
5828 ead9360e ths
        break;
5829 ead9360e ths
    case 3:
5830 ead9360e ths
        /* XXX: For now we support only a single FPU context. */
5831 a7812ae4 pbrook
        gen_helper_1i(ctc1, t0, rd);
5832 ead9360e ths
        break;
5833 ead9360e ths
    /* COP2: Not implemented. */
5834 ead9360e ths
    case 4:
5835 ead9360e ths
    case 5:
5836 ead9360e ths
        /* fall through */
5837 ead9360e ths
    default:
5838 ead9360e ths
        goto die;
5839 ead9360e ths
    }
5840 d12d51d5 aliguori
    LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5841 1a3fd9c3 ths
    tcg_temp_free(t0);
5842 ead9360e ths
    return;
5843 ead9360e ths
5844 ead9360e ths
die:
5845 1a3fd9c3 ths
    tcg_temp_free(t0);
5846 d12d51d5 aliguori
    LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5847 ead9360e ths
    generate_exception(ctx, EXCP_RI);
5848 ead9360e ths
}
5849 ead9360e ths
5850 29929e34 ths
static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5851 6af0bf9c bellard
{
5852 287c4b84 ths
    const char *opn = "ldst";
5853 6af0bf9c bellard
5854 6af0bf9c bellard
    switch (opc) {
5855 6af0bf9c bellard
    case OPC_MFC0:
5856 6af0bf9c bellard
        if (rt == 0) {
5857 ead9360e ths
            /* Treat as NOP. */
5858 6af0bf9c bellard
            return;
5859 6af0bf9c bellard
        }
5860 1fc7bf6e aurel32
        gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5861 6af0bf9c bellard
        opn = "mfc0";
5862 6af0bf9c bellard
        break;
5863 6af0bf9c bellard
    case OPC_MTC0:
5864 1a3fd9c3 ths
        {
5865 1fc7bf6e aurel32
            TCGv t0 = tcg_temp_new();
5866 1a3fd9c3 ths
5867 1a3fd9c3 ths
            gen_load_gpr(t0, rt);
5868 1a3fd9c3 ths
            gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5869 1a3fd9c3 ths
            tcg_temp_free(t0);
5870 1a3fd9c3 ths
        }
5871 6af0bf9c bellard
        opn = "mtc0";
5872 6af0bf9c bellard
        break;
5873 d26bc211 ths
#if defined(TARGET_MIPS64)
5874 9c2149c8 ths
    case OPC_DMFC0:
5875 e189e748 ths
        check_insn(env, ctx, ISA_MIPS3);
5876 9c2149c8 ths
        if (rt == 0) {
5877 ead9360e ths
            /* Treat as NOP. */
5878 9c2149c8 ths
            return;
5879 9c2149c8 ths
        }
5880 1fc7bf6e aurel32
        gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5881 9c2149c8 ths
        opn = "dmfc0";
5882 9c2149c8 ths
        break;
5883 9c2149c8 ths
    case OPC_DMTC0:
5884 e189e748 ths
        check_insn(env, ctx, ISA_MIPS3);
5885 1a3fd9c3 ths
        {
5886 1fc7bf6e aurel32
            TCGv t0 = tcg_temp_new();
5887 1a3fd9c3 ths
5888 1a3fd9c3 ths
            gen_load_gpr(t0, rt);
5889 1a3fd9c3 ths
            gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5890 1a3fd9c3 ths
            tcg_temp_free(t0);
5891 1a3fd9c3 ths
        }
5892 9c2149c8 ths
        opn = "dmtc0";
5893 9c2149c8 ths
        break;
5894 534ce69f ths
#endif
5895 ead9360e ths
    case OPC_MFTR:
5896 7385ac0b ths
        check_insn(env, ctx, ASE_MT);
5897 ead9360e ths
        if (rd == 0) {
5898 ead9360e ths
            /* Treat as NOP. */
5899 ead9360e ths
            return;
5900 ead9360e ths
        }
5901 6c5c1e20 ths
        gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5902 ead9360e ths
                 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5903 ead9360e ths
        opn = "mftr";
5904 ead9360e ths
        break;
5905 ead9360e ths
    case OPC_MTTR:
5906 7385ac0b ths
        check_insn(env, ctx, ASE_MT);
5907 6c5c1e20 ths
        gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5908 ead9360e ths
                 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5909 ead9360e ths
        opn = "mttr";
5910 ead9360e ths
        break;
5911 6af0bf9c bellard
    case OPC_TLBWI:
5912 6af0bf9c bellard
        opn = "tlbwi";
5913 c01fccd2 aurel32
        if (!env->tlb->helper_tlbwi)
5914 29929e34 ths
            goto die;
5915 a7812ae4 pbrook
        gen_helper_tlbwi();
5916 6af0bf9c bellard
        break;
5917 6af0bf9c bellard
    case OPC_TLBWR:
5918 6af0bf9c bellard
        opn = "tlbwr";
5919 c01fccd2 aurel32
        if (!env->tlb->helper_tlbwr)
5920 29929e34 ths
            goto die;
5921 a7812ae4 pbrook
        gen_helper_tlbwr();
5922 6af0bf9c bellard
        break;
5923 6af0bf9c bellard
    case OPC_TLBP:
5924 6af0bf9c bellard
        opn = "tlbp";
5925 c01fccd2 aurel32
        if (!env->tlb->helper_tlbp)
5926 29929e34 ths
            goto die;
5927 a7812ae4 pbrook
        gen_helper_tlbp();
5928 6af0bf9c bellard
        break;
5929 6af0bf9c bellard
    case OPC_TLBR:
5930 6af0bf9c bellard
        opn = "tlbr";
5931 c01fccd2 aurel32
        if (!env->tlb->helper_tlbr)
5932 29929e34 ths
            goto die;
5933 a7812ae4 pbrook
        gen_helper_tlbr();
5934 6af0bf9c bellard
        break;
5935 6af0bf9c bellard
    case OPC_ERET:
5936 6af0bf9c bellard
        opn = "eret";
5937 e189e748 ths
        check_insn(env, ctx, ISA_MIPS2);
5938 a7812ae4 pbrook
        gen_helper_eret();
5939 6af0bf9c bellard
        ctx->bstate = BS_EXCP;
5940 6af0bf9c bellard
        break;
5941 6af0bf9c bellard
    case OPC_DERET:
5942 6af0bf9c bellard
        opn = "deret";
5943 e189e748 ths
        check_insn(env, ctx, ISA_MIPS32);
5944 6af0bf9c bellard
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5945 923617a3 ths
            MIPS_INVAL(opn);
5946 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
5947 6af0bf9c bellard
        } else {
5948 a7812ae4 pbrook
            gen_helper_deret();
5949 6af0bf9c bellard
            ctx->bstate = BS_EXCP;
5950 6af0bf9c bellard
        }
5951 6af0bf9c bellard
        break;
5952 4ad40f36 bellard
    case OPC_WAIT:
5953 4ad40f36 bellard
        opn = "wait";
5954 e189e748 ths
        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
5955 4ad40f36 bellard
        /* If we get an exception, we want to restart at next instruction */
5956 4ad40f36 bellard
        ctx->pc += 4;
5957 4ad40f36 bellard
        save_cpu_state(ctx, 1);
5958 4ad40f36 bellard
        ctx->pc -= 4;
5959 a7812ae4 pbrook
        gen_helper_wait();
5960 4ad40f36 bellard
        ctx->bstate = BS_EXCP;
5961 4ad40f36 bellard
        break;
5962 6af0bf9c bellard
    default:
5963 29929e34 ths
 die:
5964 923617a3 ths
        MIPS_INVAL(opn);
5965 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
5966 6af0bf9c bellard
        return;
5967 6af0bf9c bellard
    }
5968 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
5969 6af0bf9c bellard
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5970 6af0bf9c bellard
}
5971 f1aa6320 ths
#endif /* !CONFIG_USER_ONLY */
5972 6af0bf9c bellard
5973 6ea83fed bellard
/* CP1 Branches (before delay slot) */
5974 e189e748 ths
static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5975 5a5012ec ths
                                 int32_t cc, int32_t offset)
5976 6ea83fed bellard
{
5977 6ea83fed bellard
    target_ulong btarget;
5978 923617a3 ths
    const char *opn = "cp1 cond branch";
5979 a7812ae4 pbrook
    TCGv_i32 t0 = tcg_temp_new_i32();
5980 6ea83fed bellard
5981 e189e748 ths
    if (cc != 0)
5982 e189e748 ths
        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5983 e189e748 ths
5984 6ea83fed bellard
    btarget = ctx->pc + 4 + offset;
5985 6ea83fed bellard
5986 7a387fff ths
    switch (op) {
5987 7a387fff ths
    case OPC_BC1F:
5988 d94536f4 aurel32
        tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5989 d94536f4 aurel32
        tcg_gen_not_i32(t0, t0);
5990 d94536f4 aurel32
        tcg_gen_andi_i32(t0, t0, 1);
5991 d94536f4 aurel32
        tcg_gen_extu_i32_tl(bcond, t0);
5992 923617a3 ths
        opn = "bc1f";
5993 6ea83fed bellard
        goto not_likely;
5994 7a387fff ths
    case OPC_BC1FL:
5995 d94536f4 aurel32
        tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5996 d94536f4 aurel32
        tcg_gen_not_i32(t0, t0);
5997 d94536f4 aurel32
        tcg_gen_andi_i32(t0, t0, 1);
5998 d94536f4 aurel32
        tcg_gen_extu_i32_tl(bcond, t0);
5999 923617a3 ths
        opn = "bc1fl";
6000 6ea83fed bellard
        goto likely;
6001 7a387fff ths
    case OPC_BC1T:
6002 d94536f4 aurel32
        tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6003 d94536f4 aurel32
        tcg_gen_andi_i32(t0, t0, 1);
6004 d94536f4 aurel32
        tcg_gen_extu_i32_tl(bcond, t0);
6005 923617a3 ths
        opn = "bc1t";
6006 5a5012ec ths
        goto not_likely;
6007 7a387fff ths
    case OPC_BC1TL:
6008 d94536f4 aurel32
        tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6009 d94536f4 aurel32
        tcg_gen_andi_i32(t0, t0, 1);
6010 d94536f4 aurel32
        tcg_gen_extu_i32_tl(bcond, t0);
6011 923617a3 ths
        opn = "bc1tl";
6012 6ea83fed bellard
    likely:
6013 6ea83fed bellard
        ctx->hflags |= MIPS_HFLAG_BL;
6014 6ea83fed bellard
        break;
6015 5a5012ec ths
    case OPC_BC1FANY2:
6016 a16336e4 ths
        {
6017 d94536f4 aurel32
            TCGv_i32 t1 = tcg_temp_new_i32();
6018 d94536f4 aurel32
            tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6019 d94536f4 aurel32
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6020 deb4203d Aurelien Jarno
            tcg_gen_nor_i32(t0, t0, t1);
6021 d94536f4 aurel32
            tcg_temp_free_i32(t1);
6022 d94536f4 aurel32
            tcg_gen_andi_i32(t0, t0, 1);
6023 d94536f4 aurel32
            tcg_gen_extu_i32_tl(bcond, t0);
6024 a16336e4 ths
        }
6025 fd4a04eb ths
        opn = "bc1any2f";
6026 5a5012ec ths
        goto not_likely;
6027 5a5012ec ths
    case OPC_BC1TANY2:
6028 a16336e4 ths
        {
6029 d94536f4 aurel32
            TCGv_i32 t1 = tcg_temp_new_i32();
6030 d94536f4 aurel32
            tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6031 d94536f4 aurel32
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6032 d94536f4 aurel32
            tcg_gen_or_i32(t0, t0, t1);
6033 d94536f4 aurel32
            tcg_temp_free_i32(t1);
6034 d94536f4 aurel32
            tcg_gen_andi_i32(t0, t0, 1);
6035 d94536f4 aurel32
            tcg_gen_extu_i32_tl(bcond, t0);
6036 a16336e4 ths
        }
6037 fd4a04eb ths
        opn = "bc1any2t";
6038 5a5012ec ths
        goto not_likely;
6039 5a5012ec ths
    case OPC_BC1FANY4:
6040 a16336e4 ths
        {
6041 d94536f4 aurel32
            TCGv_i32 t1 = tcg_temp_new_i32();
6042 d94536f4 aurel32
            tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6043 d94536f4 aurel32
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6044 d94536f4 aurel32
            tcg_gen_or_i32(t0, t0, t1);
6045 d94536f4 aurel32
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6046 d94536f4 aurel32
            tcg_gen_or_i32(t0, t0, t1);
6047 d94536f4 aurel32
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6048 deb4203d Aurelien Jarno
            tcg_gen_nor_i32(t0, t0, t1);
6049 d94536f4 aurel32
            tcg_temp_free_i32(t1);
6050 d94536f4 aurel32
            tcg_gen_andi_i32(t0, t0, 1);
6051 d94536f4 aurel32
            tcg_gen_extu_i32_tl(bcond, t0);
6052 a16336e4 ths
        }
6053 fd4a04eb ths
        opn = "bc1any4f";
6054 5a5012ec ths
        goto not_likely;
6055 5a5012ec ths
    case OPC_BC1TANY4:
6056 a16336e4 ths
        {
6057 d94536f4 aurel32
            TCGv_i32 t1 = tcg_temp_new_i32();
6058 d94536f4 aurel32
            tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6059 d94536f4 aurel32
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6060 d94536f4 aurel32
            tcg_gen_or_i32(t0, t0, t1);
6061 d94536f4 aurel32
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6062 d94536f4 aurel32
            tcg_gen_or_i32(t0, t0, t1);
6063 d94536f4 aurel32
            tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6064 d94536f4 aurel32
            tcg_gen_or_i32(t0, t0, t1);
6065 d94536f4 aurel32
            tcg_temp_free_i32(t1);
6066 d94536f4 aurel32
            tcg_gen_andi_i32(t0, t0, 1);
6067 d94536f4 aurel32
            tcg_gen_extu_i32_tl(bcond, t0);
6068 a16336e4 ths
        }
6069 fd4a04eb ths
        opn = "bc1any4t";
6070 5a5012ec ths
    not_likely:
6071 5a5012ec ths
        ctx->hflags |= MIPS_HFLAG_BC;
6072 5a5012ec ths
        break;
6073 5a5012ec ths
    default:
6074 923617a3 ths
        MIPS_INVAL(opn);
6075 e397ee33 ths
        generate_exception (ctx, EXCP_RI);
6076 6c5c1e20 ths
        goto out;
6077 6ea83fed bellard
    }
6078 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
6079 923617a3 ths
    MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6080 6ea83fed bellard
               ctx->hflags, btarget);
6081 6ea83fed bellard
    ctx->btarget = btarget;
6082 6c5c1e20 ths
6083 6c5c1e20 ths
 out:
6084 a7812ae4 pbrook
    tcg_temp_free_i32(t0);
6085 6ea83fed bellard
}
6086 6ea83fed bellard
6087 6af0bf9c bellard
/* Coprocessor 1 (FPU) */
6088 5a5012ec ths
6089 5a5012ec ths
#define FOP(func, fmt) (((fmt) << 21) | (func))
6090 5a5012ec ths
6091 bf4120ad Nathan Froyd
enum fopcode {
6092 bf4120ad Nathan Froyd
    OPC_ADD_S = FOP(0, FMT_S),
6093 bf4120ad Nathan Froyd
    OPC_SUB_S = FOP(1, FMT_S),
6094 bf4120ad Nathan Froyd
    OPC_MUL_S = FOP(2, FMT_S),
6095 bf4120ad Nathan Froyd
    OPC_DIV_S = FOP(3, FMT_S),
6096 bf4120ad Nathan Froyd
    OPC_SQRT_S = FOP(4, FMT_S),
6097 bf4120ad Nathan Froyd
    OPC_ABS_S = FOP(5, FMT_S),
6098 bf4120ad Nathan Froyd
    OPC_MOV_S = FOP(6, FMT_S),
6099 bf4120ad Nathan Froyd
    OPC_NEG_S = FOP(7, FMT_S),
6100 bf4120ad Nathan Froyd
    OPC_ROUND_L_S = FOP(8, FMT_S),
6101 bf4120ad Nathan Froyd
    OPC_TRUNC_L_S = FOP(9, FMT_S),
6102 bf4120ad Nathan Froyd
    OPC_CEIL_L_S = FOP(10, FMT_S),
6103 bf4120ad Nathan Froyd
    OPC_FLOOR_L_S = FOP(11, FMT_S),
6104 bf4120ad Nathan Froyd
    OPC_ROUND_W_S = FOP(12, FMT_S),
6105 bf4120ad Nathan Froyd
    OPC_TRUNC_W_S = FOP(13, FMT_S),
6106 bf4120ad Nathan Froyd
    OPC_CEIL_W_S = FOP(14, FMT_S),
6107 bf4120ad Nathan Froyd
    OPC_FLOOR_W_S = FOP(15, FMT_S),
6108 bf4120ad Nathan Froyd
    OPC_MOVCF_S = FOP(17, FMT_S),
6109 bf4120ad Nathan Froyd
    OPC_MOVZ_S = FOP(18, FMT_S),
6110 bf4120ad Nathan Froyd
    OPC_MOVN_S = FOP(19, FMT_S),
6111 bf4120ad Nathan Froyd
    OPC_RECIP_S = FOP(21, FMT_S),
6112 bf4120ad Nathan Froyd
    OPC_RSQRT_S = FOP(22, FMT_S),
6113 bf4120ad Nathan Froyd
    OPC_RECIP2_S = FOP(28, FMT_S),
6114 bf4120ad Nathan Froyd
    OPC_RECIP1_S = FOP(29, FMT_S),
6115 bf4120ad Nathan Froyd
    OPC_RSQRT1_S = FOP(30, FMT_S),
6116 bf4120ad Nathan Froyd
    OPC_RSQRT2_S = FOP(31, FMT_S),
6117 bf4120ad Nathan Froyd
    OPC_CVT_D_S = FOP(33, FMT_S),
6118 bf4120ad Nathan Froyd
    OPC_CVT_W_S = FOP(36, FMT_S),
6119 bf4120ad Nathan Froyd
    OPC_CVT_L_S = FOP(37, FMT_S),
6120 bf4120ad Nathan Froyd
    OPC_CVT_PS_S = FOP(38, FMT_S),
6121 bf4120ad Nathan Froyd
    OPC_CMP_F_S = FOP (48, FMT_S),
6122 bf4120ad Nathan Froyd
    OPC_CMP_UN_S = FOP (49, FMT_S),
6123 bf4120ad Nathan Froyd
    OPC_CMP_EQ_S = FOP (50, FMT_S),
6124 bf4120ad Nathan Froyd
    OPC_CMP_UEQ_S = FOP (51, FMT_S),
6125 bf4120ad Nathan Froyd
    OPC_CMP_OLT_S = FOP (52, FMT_S),
6126 bf4120ad Nathan Froyd
    OPC_CMP_ULT_S = FOP (53, FMT_S),
6127 bf4120ad Nathan Froyd
    OPC_CMP_OLE_S = FOP (54, FMT_S),
6128 bf4120ad Nathan Froyd
    OPC_CMP_ULE_S = FOP (55, FMT_S),
6129 bf4120ad Nathan Froyd
    OPC_CMP_SF_S = FOP (56, FMT_S),
6130 bf4120ad Nathan Froyd
    OPC_CMP_NGLE_S = FOP (57, FMT_S),
6131 bf4120ad Nathan Froyd
    OPC_CMP_SEQ_S = FOP (58, FMT_S),
6132 bf4120ad Nathan Froyd
    OPC_CMP_NGL_S = FOP (59, FMT_S),
6133 bf4120ad Nathan Froyd
    OPC_CMP_LT_S = FOP (60, FMT_S),
6134 bf4120ad Nathan Froyd
    OPC_CMP_NGE_S = FOP (61, FMT_S),
6135 bf4120ad Nathan Froyd
    OPC_CMP_LE_S = FOP (62, FMT_S),
6136 bf4120ad Nathan Froyd
    OPC_CMP_NGT_S = FOP (63, FMT_S),
6137 bf4120ad Nathan Froyd
6138 bf4120ad Nathan Froyd
    OPC_ADD_D = FOP(0, FMT_D),
6139 bf4120ad Nathan Froyd
    OPC_SUB_D = FOP(1, FMT_D),
6140 bf4120ad Nathan Froyd
    OPC_MUL_D = FOP(2, FMT_D),
6141 bf4120ad Nathan Froyd
    OPC_DIV_D = FOP(3, FMT_D),
6142 bf4120ad Nathan Froyd
    OPC_SQRT_D = FOP(4, FMT_D),
6143 bf4120ad Nathan Froyd
    OPC_ABS_D = FOP(5, FMT_D),
6144 bf4120ad Nathan Froyd
    OPC_MOV_D = FOP(6, FMT_D),
6145 bf4120ad Nathan Froyd
    OPC_NEG_D = FOP(7, FMT_D),
6146 bf4120ad Nathan Froyd
    OPC_ROUND_L_D = FOP(8, FMT_D),
6147 bf4120ad Nathan Froyd
    OPC_TRUNC_L_D = FOP(9, FMT_D),
6148 bf4120ad Nathan Froyd
    OPC_CEIL_L_D = FOP(10, FMT_D),
6149 bf4120ad Nathan Froyd
    OPC_FLOOR_L_D = FOP(11, FMT_D),
6150 bf4120ad Nathan Froyd
    OPC_ROUND_W_D = FOP(12, FMT_D),
6151 bf4120ad Nathan Froyd
    OPC_TRUNC_W_D = FOP(13, FMT_D),
6152 bf4120ad Nathan Froyd
    OPC_CEIL_W_D = FOP(14, FMT_D),
6153 bf4120ad Nathan Froyd
    OPC_FLOOR_W_D = FOP(15, FMT_D),
6154 bf4120ad Nathan Froyd
    OPC_MOVCF_D = FOP(17, FMT_D),
6155 bf4120ad Nathan Froyd
    OPC_MOVZ_D = FOP(18, FMT_D),
6156 bf4120ad Nathan Froyd
    OPC_MOVN_D = FOP(19, FMT_D),
6157 bf4120ad Nathan Froyd
    OPC_RECIP_D = FOP(21, FMT_D),
6158 bf4120ad Nathan Froyd
    OPC_RSQRT_D = FOP(22, FMT_D),
6159 bf4120ad Nathan Froyd
    OPC_RECIP2_D = FOP(28, FMT_D),
6160 bf4120ad Nathan Froyd
    OPC_RECIP1_D = FOP(29, FMT_D),
6161 bf4120ad Nathan Froyd
    OPC_RSQRT1_D = FOP(30, FMT_D),
6162 bf4120ad Nathan Froyd
    OPC_RSQRT2_D = FOP(31, FMT_D),
6163 bf4120ad Nathan Froyd
    OPC_CVT_S_D = FOP(32, FMT_D),
6164 bf4120ad Nathan Froyd
    OPC_CVT_W_D = FOP(36, FMT_D),
6165 bf4120ad Nathan Froyd
    OPC_CVT_L_D = FOP(37, FMT_D),
6166 bf4120ad Nathan Froyd
    OPC_CMP_F_D = FOP (48, FMT_D),
6167 bf4120ad Nathan Froyd
    OPC_CMP_UN_D = FOP (49, FMT_D),
6168 bf4120ad Nathan Froyd
    OPC_CMP_EQ_D = FOP (50, FMT_D),
6169 bf4120ad Nathan Froyd
    OPC_CMP_UEQ_D = FOP (51, FMT_D),
6170 bf4120ad Nathan Froyd
    OPC_CMP_OLT_D = FOP (52, FMT_D),
6171 bf4120ad Nathan Froyd
    OPC_CMP_ULT_D = FOP (53, FMT_D),
6172 bf4120ad Nathan Froyd
    OPC_CMP_OLE_D = FOP (54, FMT_D),
6173 bf4120ad Nathan Froyd
    OPC_CMP_ULE_D = FOP (55, FMT_D),
6174 bf4120ad Nathan Froyd
    OPC_CMP_SF_D = FOP (56, FMT_D),
6175 bf4120ad Nathan Froyd
    OPC_CMP_NGLE_D = FOP (57, FMT_D),
6176 bf4120ad Nathan Froyd
    OPC_CMP_SEQ_D = FOP (58, FMT_D),
6177 bf4120ad Nathan Froyd
    OPC_CMP_NGL_D = FOP (59, FMT_D),
6178 bf4120ad Nathan Froyd
    OPC_CMP_LT_D = FOP (60, FMT_D),
6179 bf4120ad Nathan Froyd
    OPC_CMP_NGE_D = FOP (61, FMT_D),
6180 bf4120ad Nathan Froyd
    OPC_CMP_LE_D = FOP (62, FMT_D),
6181 bf4120ad Nathan Froyd
    OPC_CMP_NGT_D = FOP (63, FMT_D),
6182 bf4120ad Nathan Froyd
6183 bf4120ad Nathan Froyd
    OPC_CVT_S_W = FOP(32, FMT_W),
6184 bf4120ad Nathan Froyd
    OPC_CVT_D_W = FOP(33, FMT_W),
6185 bf4120ad Nathan Froyd
    OPC_CVT_S_L = FOP(32, FMT_L),
6186 bf4120ad Nathan Froyd
    OPC_CVT_D_L = FOP(33, FMT_L),
6187 bf4120ad Nathan Froyd
    OPC_CVT_PS_PW = FOP(38, FMT_W),
6188 bf4120ad Nathan Froyd
6189 bf4120ad Nathan Froyd
    OPC_ADD_PS = FOP(0, FMT_PS),
6190 bf4120ad Nathan Froyd
    OPC_SUB_PS = FOP(1, FMT_PS),
6191 bf4120ad Nathan Froyd
    OPC_MUL_PS = FOP(2, FMT_PS),
6192 bf4120ad Nathan Froyd
    OPC_DIV_PS = FOP(3, FMT_PS),
6193 bf4120ad Nathan Froyd
    OPC_ABS_PS = FOP(5, FMT_PS),
6194 bf4120ad Nathan Froyd
    OPC_MOV_PS = FOP(6, FMT_PS),
6195 bf4120ad Nathan Froyd
    OPC_NEG_PS = FOP(7, FMT_PS),
6196 bf4120ad Nathan Froyd
    OPC_MOVCF_PS = FOP(17, FMT_PS),
6197 bf4120ad Nathan Froyd
    OPC_MOVZ_PS = FOP(18, FMT_PS),
6198 bf4120ad Nathan Froyd
    OPC_MOVN_PS = FOP(19, FMT_PS),
6199 bf4120ad Nathan Froyd
    OPC_ADDR_PS = FOP(24, FMT_PS),
6200 bf4120ad Nathan Froyd
    OPC_MULR_PS = FOP(26, FMT_PS),
6201 bf4120ad Nathan Froyd
    OPC_RECIP2_PS = FOP(28, FMT_PS),
6202 bf4120ad Nathan Froyd
    OPC_RECIP1_PS = FOP(29, FMT_PS),
6203 bf4120ad Nathan Froyd
    OPC_RSQRT1_PS = FOP(30, FMT_PS),
6204 bf4120ad Nathan Froyd
    OPC_RSQRT2_PS = FOP(31, FMT_PS),
6205 bf4120ad Nathan Froyd
6206 bf4120ad Nathan Froyd
    OPC_CVT_S_PU = FOP(32, FMT_PS),
6207 bf4120ad Nathan Froyd
    OPC_CVT_PW_PS = FOP(36, FMT_PS),
6208 bf4120ad Nathan Froyd
    OPC_CVT_S_PL = FOP(40, FMT_PS),
6209 bf4120ad Nathan Froyd
    OPC_PLL_PS = FOP(44, FMT_PS),
6210 bf4120ad Nathan Froyd
    OPC_PLU_PS = FOP(45, FMT_PS),
6211 bf4120ad Nathan Froyd
    OPC_PUL_PS = FOP(46, FMT_PS),
6212 bf4120ad Nathan Froyd
    OPC_PUU_PS = FOP(47, FMT_PS),
6213 bf4120ad Nathan Froyd
    OPC_CMP_F_PS = FOP (48, FMT_PS),
6214 bf4120ad Nathan Froyd
    OPC_CMP_UN_PS = FOP (49, FMT_PS),
6215 bf4120ad Nathan Froyd
    OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6216 bf4120ad Nathan Froyd
    OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6217 bf4120ad Nathan Froyd
    OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6218 bf4120ad Nathan Froyd
    OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6219 bf4120ad Nathan Froyd
    OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6220 bf4120ad Nathan Froyd
    OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6221 bf4120ad Nathan Froyd
    OPC_CMP_SF_PS = FOP (56, FMT_PS),
6222 bf4120ad Nathan Froyd
    OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6223 bf4120ad Nathan Froyd
    OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6224 bf4120ad Nathan Froyd
    OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6225 bf4120ad Nathan Froyd
    OPC_CMP_LT_PS = FOP (60, FMT_PS),
6226 bf4120ad Nathan Froyd
    OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6227 bf4120ad Nathan Froyd
    OPC_CMP_LE_PS = FOP (62, FMT_PS),
6228 bf4120ad Nathan Froyd
    OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6229 bf4120ad Nathan Froyd
};
6230 bf4120ad Nathan Froyd
6231 7a387fff ths
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6232 6ea83fed bellard
{
6233 923617a3 ths
    const char *opn = "cp1 move";
6234 72c3a3ee aurel32
    TCGv t0 = tcg_temp_new();
6235 6ea83fed bellard
6236 6ea83fed bellard
    switch (opc) {
6237 6ea83fed bellard
    case OPC_MFC1:
6238 b6d96bed ths
        {
6239 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6240 b6d96bed ths
6241 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6242 b6d96bed ths
            tcg_gen_ext_i32_tl(t0, fp0);
6243 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6244 6958549d aurel32
        }
6245 6c5c1e20 ths
        gen_store_gpr(t0, rt);
6246 6ea83fed bellard
        opn = "mfc1";
6247 6ea83fed bellard
        break;
6248 6ea83fed bellard
    case OPC_MTC1:
6249 6c5c1e20 ths
        gen_load_gpr(t0, rt);
6250 b6d96bed ths
        {
6251 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6252 b6d96bed ths
6253 b6d96bed ths
            tcg_gen_trunc_tl_i32(fp0, t0);
6254 b6d96bed ths
            gen_store_fpr32(fp0, fs);
6255 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6256 6958549d aurel32
        }
6257 6ea83fed bellard
        opn = "mtc1";
6258 6ea83fed bellard
        break;
6259 6ea83fed bellard
    case OPC_CFC1:
6260 a7812ae4 pbrook
        gen_helper_1i(cfc1, t0, fs);
6261 6c5c1e20 ths
        gen_store_gpr(t0, rt);
6262 6ea83fed bellard
        opn = "cfc1";
6263 6ea83fed bellard
        break;
6264 6ea83fed bellard
    case OPC_CTC1:
6265 6c5c1e20 ths
        gen_load_gpr(t0, rt);
6266 a7812ae4 pbrook
        gen_helper_1i(ctc1, t0, fs);
6267 6ea83fed bellard
        opn = "ctc1";
6268 6ea83fed bellard
        break;
6269 72c3a3ee aurel32
#if defined(TARGET_MIPS64)
6270 9c2149c8 ths
    case OPC_DMFC1:
6271 72c3a3ee aurel32
        gen_load_fpr64(ctx, t0, fs);
6272 6c5c1e20 ths
        gen_store_gpr(t0, rt);
6273 5a5012ec ths
        opn = "dmfc1";
6274 5a5012ec ths
        break;
6275 9c2149c8 ths
    case OPC_DMTC1:
6276 6c5c1e20 ths
        gen_load_gpr(t0, rt);
6277 72c3a3ee aurel32
        gen_store_fpr64(ctx, t0, fs);
6278 5a5012ec ths
        opn = "dmtc1";
6279 5a5012ec ths
        break;
6280 72c3a3ee aurel32
#endif
6281 5a5012ec ths
    case OPC_MFHC1:
6282 b6d96bed ths
        {
6283 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6284 b6d96bed ths
6285 b6d96bed ths
            gen_load_fpr32h(fp0, fs);
6286 b6d96bed ths
            tcg_gen_ext_i32_tl(t0, fp0);
6287 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6288 6958549d aurel32
        }
6289 6c5c1e20 ths
        gen_store_gpr(t0, rt);
6290 5a5012ec ths
        opn = "mfhc1";
6291 5a5012ec ths
        break;
6292 5a5012ec ths
    case OPC_MTHC1:
6293 6c5c1e20 ths
        gen_load_gpr(t0, rt);
6294 b6d96bed ths
        {
6295 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6296 b6d96bed ths
6297 b6d96bed ths
            tcg_gen_trunc_tl_i32(fp0, t0);
6298 b6d96bed ths
            gen_store_fpr32h(fp0, fs);
6299 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6300 6958549d aurel32
        }
6301 5a5012ec ths
        opn = "mthc1";
6302 5a5012ec ths
        break;
6303 6ea83fed bellard
    default:
6304 923617a3 ths
        MIPS_INVAL(opn);
6305 e397ee33 ths
        generate_exception (ctx, EXCP_RI);
6306 6c5c1e20 ths
        goto out;
6307 6ea83fed bellard
    }
6308 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
6309 6ea83fed bellard
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6310 6c5c1e20 ths
6311 6c5c1e20 ths
 out:
6312 6c5c1e20 ths
    tcg_temp_free(t0);
6313 6ea83fed bellard
}
6314 6ea83fed bellard
6315 5a5012ec ths
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6316 5a5012ec ths
{
6317 af58f9ca aurel32
    int l1;
6318 e214b9bb ths
    TCGCond cond;
6319 af58f9ca aurel32
    TCGv_i32 t0;
6320 af58f9ca aurel32
6321 af58f9ca aurel32
    if (rd == 0) {
6322 af58f9ca aurel32
        /* Treat as NOP. */
6323 af58f9ca aurel32
        return;
6324 af58f9ca aurel32
    }
6325 6ea83fed bellard
6326 e214b9bb ths
    if (tf)
6327 e214b9bb ths
        cond = TCG_COND_EQ;
6328 27848470 ths
    else
6329 27848470 ths
        cond = TCG_COND_NE;
6330 27848470 ths
6331 af58f9ca aurel32
    l1 = gen_new_label();
6332 af58f9ca aurel32
    t0 = tcg_temp_new_i32();
6333 fa31af0e Nathan Froyd
    tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6334 af58f9ca aurel32
    tcg_gen_brcondi_i32(cond, t0, 0, l1);
6335 a4e8338d aurel32
    tcg_temp_free_i32(t0);
6336 af58f9ca aurel32
    if (rs == 0) {
6337 af58f9ca aurel32
        tcg_gen_movi_tl(cpu_gpr[rd], 0);
6338 af58f9ca aurel32
    } else {
6339 af58f9ca aurel32
        tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6340 af58f9ca aurel32
    }
6341 e214b9bb ths
    gen_set_label(l1);
6342 5a5012ec ths
}
6343 5a5012ec ths
6344 b6d96bed ths
static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6345 a16336e4 ths
{
6346 a16336e4 ths
    int cond;
6347 cbc37b28 aurel32
    TCGv_i32 t0 = tcg_temp_new_i32();
6348 a16336e4 ths
    int l1 = gen_new_label();
6349 a16336e4 ths
6350 a16336e4 ths
    if (tf)
6351 a16336e4 ths
        cond = TCG_COND_EQ;
6352 a16336e4 ths
    else
6353 a16336e4 ths
        cond = TCG_COND_NE;
6354 a16336e4 ths
6355 fa31af0e Nathan Froyd
    tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6356 cbc37b28 aurel32
    tcg_gen_brcondi_i32(cond, t0, 0, l1);
6357 cbc37b28 aurel32
    gen_load_fpr32(t0, fs);
6358 cbc37b28 aurel32
    gen_store_fpr32(t0, fd);
6359 a16336e4 ths
    gen_set_label(l1);
6360 cbc37b28 aurel32
    tcg_temp_free_i32(t0);
6361 5a5012ec ths
}
6362 a16336e4 ths
6363 b6d96bed ths
static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6364 a16336e4 ths
{
6365 a16336e4 ths
    int cond;
6366 cbc37b28 aurel32
    TCGv_i32 t0 = tcg_temp_new_i32();
6367 cbc37b28 aurel32
    TCGv_i64 fp0;
6368 a16336e4 ths
    int l1 = gen_new_label();
6369 a16336e4 ths
6370 a16336e4 ths
    if (tf)
6371 a16336e4 ths
        cond = TCG_COND_EQ;
6372 a16336e4 ths
    else
6373 a16336e4 ths
        cond = TCG_COND_NE;
6374 a16336e4 ths
6375 fa31af0e Nathan Froyd
    tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6376 cbc37b28 aurel32
    tcg_gen_brcondi_i32(cond, t0, 0, l1);
6377 a4e8338d aurel32
    tcg_temp_free_i32(t0);
6378 11f94258 aurel32
    fp0 = tcg_temp_new_i64();
6379 9bf3eb2c aurel32
    gen_load_fpr64(ctx, fp0, fs);
6380 9bf3eb2c aurel32
    gen_store_fpr64(ctx, fp0, fd);
6381 a7812ae4 pbrook
    tcg_temp_free_i64(fp0);
6382 cbc37b28 aurel32
    gen_set_label(l1);
6383 a16336e4 ths
}
6384 a16336e4 ths
6385 b6d96bed ths
static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6386 a16336e4 ths
{
6387 a16336e4 ths
    int cond;
6388 cbc37b28 aurel32
    TCGv_i32 t0 = tcg_temp_new_i32();
6389 a16336e4 ths
    int l1 = gen_new_label();
6390 a16336e4 ths
    int l2 = gen_new_label();
6391 a16336e4 ths
6392 a16336e4 ths
    if (tf)
6393 a16336e4 ths
        cond = TCG_COND_EQ;
6394 a16336e4 ths
    else
6395 a16336e4 ths
        cond = TCG_COND_NE;
6396 a16336e4 ths
6397 fa31af0e Nathan Froyd
    tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6398 cbc37b28 aurel32
    tcg_gen_brcondi_i32(cond, t0, 0, l1);
6399 cbc37b28 aurel32
    gen_load_fpr32(t0, fs);
6400 cbc37b28 aurel32
    gen_store_fpr32(t0, fd);
6401 a16336e4 ths
    gen_set_label(l1);
6402 9bf3eb2c aurel32
6403 fa31af0e Nathan Froyd
    tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
6404 cbc37b28 aurel32
    tcg_gen_brcondi_i32(cond, t0, 0, l2);
6405 cbc37b28 aurel32
    gen_load_fpr32h(t0, fs);
6406 cbc37b28 aurel32
    gen_store_fpr32h(t0, fd);
6407 52a0e9eb aurel32
    tcg_temp_free_i32(t0);
6408 a16336e4 ths
    gen_set_label(l2);
6409 a16336e4 ths
}
6410 a16336e4 ths
6411 6ea83fed bellard
6412 bf4120ad Nathan Froyd
static void gen_farith (DisasContext *ctx, enum fopcode op1,
6413 5e755519 ths
                        int ft, int fs, int fd, int cc)
6414 6ea83fed bellard
{
6415 923617a3 ths
    const char *opn = "farith";
6416 6ea83fed bellard
    const char *condnames[] = {
6417 6ea83fed bellard
            "c.f",
6418 6ea83fed bellard
            "c.un",
6419 6ea83fed bellard
            "c.eq",
6420 6ea83fed bellard
            "c.ueq",
6421 6ea83fed bellard
            "c.olt",
6422 6ea83fed bellard
            "c.ult",
6423 6ea83fed bellard
            "c.ole",
6424 6ea83fed bellard
            "c.ule",
6425 6ea83fed bellard
            "c.sf",
6426 6ea83fed bellard
            "c.ngle",
6427 6ea83fed bellard
            "c.seq",
6428 6ea83fed bellard
            "c.ngl",
6429 6ea83fed bellard
            "c.lt",
6430 6ea83fed bellard
            "c.nge",
6431 6ea83fed bellard
            "c.le",
6432 6ea83fed bellard
            "c.ngt",
6433 6ea83fed bellard
    };
6434 5a1e8ffb ths
    const char *condnames_abs[] = {
6435 5a1e8ffb ths
            "cabs.f",
6436 5a1e8ffb ths
            "cabs.un",
6437 5a1e8ffb ths
            "cabs.eq",
6438 5a1e8ffb ths
            "cabs.ueq",
6439 5a1e8ffb ths
            "cabs.olt",
6440 5a1e8ffb ths
            "cabs.ult",
6441 5a1e8ffb ths
            "cabs.ole",
6442 5a1e8ffb ths
            "cabs.ule",
6443 5a1e8ffb ths
            "cabs.sf",
6444 5a1e8ffb ths
            "cabs.ngle",
6445 5a1e8ffb ths
            "cabs.seq",
6446 5a1e8ffb ths
            "cabs.ngl",
6447 5a1e8ffb ths
            "cabs.lt",
6448 5a1e8ffb ths
            "cabs.nge",
6449 5a1e8ffb ths
            "cabs.le",
6450 5a1e8ffb ths
            "cabs.ngt",
6451 5a1e8ffb ths
    };
6452 5a1e8ffb ths
    enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6453 7a387fff ths
    uint32_t func = ctx->opcode & 0x3f;
6454 7a387fff ths
6455 bf4120ad Nathan Froyd
    switch (op1) {
6456 bf4120ad Nathan Froyd
    case OPC_ADD_S:
6457 b6d96bed ths
        {
6458 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6459 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
6460 b6d96bed ths
6461 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6462 b6d96bed ths
            gen_load_fpr32(fp1, ft);
6463 a7812ae4 pbrook
            gen_helper_float_add_s(fp0, fp0, fp1);
6464 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
6465 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6466 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6467 b6d96bed ths
        }
6468 5a5012ec ths
        opn = "add.s";
6469 5a1e8ffb ths
        optype = BINOP;
6470 5a5012ec ths
        break;
6471 bf4120ad Nathan Froyd
    case OPC_SUB_S:
6472 b6d96bed ths
        {
6473 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6474 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
6475 b6d96bed ths
6476 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6477 b6d96bed ths
            gen_load_fpr32(fp1, ft);
6478 a7812ae4 pbrook
            gen_helper_float_sub_s(fp0, fp0, fp1);
6479 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
6480 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6481 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6482 b6d96bed ths
        }
6483 5a5012ec ths
        opn = "sub.s";
6484 5a1e8ffb ths
        optype = BINOP;
6485 5a5012ec ths
        break;
6486 bf4120ad Nathan Froyd
    case OPC_MUL_S:
6487 b6d96bed ths
        {
6488 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6489 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
6490 b6d96bed ths
6491 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6492 b6d96bed ths
            gen_load_fpr32(fp1, ft);
6493 a7812ae4 pbrook
            gen_helper_float_mul_s(fp0, fp0, fp1);
6494 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
6495 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6496 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6497 b6d96bed ths
        }
6498 5a5012ec ths
        opn = "mul.s";
6499 5a1e8ffb ths
        optype = BINOP;
6500 5a5012ec ths
        break;
6501 bf4120ad Nathan Froyd
    case OPC_DIV_S:
6502 b6d96bed ths
        {
6503 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6504 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
6505 b6d96bed ths
6506 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6507 b6d96bed ths
            gen_load_fpr32(fp1, ft);
6508 a7812ae4 pbrook
            gen_helper_float_div_s(fp0, fp0, fp1);
6509 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
6510 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6511 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6512 b6d96bed ths
        }
6513 5a5012ec ths
        opn = "div.s";
6514 5a1e8ffb ths
        optype = BINOP;
6515 5a5012ec ths
        break;
6516 bf4120ad Nathan Froyd
    case OPC_SQRT_S:
6517 b6d96bed ths
        {
6518 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6519 b6d96bed ths
6520 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6521 a7812ae4 pbrook
            gen_helper_float_sqrt_s(fp0, fp0);
6522 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6523 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6524 b6d96bed ths
        }
6525 5a5012ec ths
        opn = "sqrt.s";
6526 5a5012ec ths
        break;
6527 bf4120ad Nathan Froyd
    case OPC_ABS_S:
6528 b6d96bed ths
        {
6529 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6530 b6d96bed ths
6531 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6532 a7812ae4 pbrook
            gen_helper_float_abs_s(fp0, fp0);
6533 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6534 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6535 b6d96bed ths
        }
6536 5a5012ec ths
        opn = "abs.s";
6537 5a5012ec ths
        break;
6538 bf4120ad Nathan Froyd
    case OPC_MOV_S:
6539 b6d96bed ths
        {
6540 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6541 b6d96bed ths
6542 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6543 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6544 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6545 b6d96bed ths
        }
6546 5a5012ec ths
        opn = "mov.s";
6547 5a5012ec ths
        break;
6548 bf4120ad Nathan Froyd
    case OPC_NEG_S:
6549 b6d96bed ths
        {
6550 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6551 b6d96bed ths
6552 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6553 a7812ae4 pbrook
            gen_helper_float_chs_s(fp0, fp0);
6554 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6555 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6556 b6d96bed ths
        }
6557 5a5012ec ths
        opn = "neg.s";
6558 5a5012ec ths
        break;
6559 bf4120ad Nathan Froyd
    case OPC_ROUND_L_S:
6560 5e755519 ths
        check_cp1_64bitmode(ctx);
6561 b6d96bed ths
        {
6562 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
6563 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
6564 b6d96bed ths
6565 b6d96bed ths
            gen_load_fpr32(fp32, fs);
6566 a7812ae4 pbrook
            gen_helper_float_roundl_s(fp64, fp32);
6567 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
6568 b6d96bed ths
            gen_store_fpr64(ctx, fp64, fd);
6569 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
6570 b6d96bed ths
        }
6571 5a5012ec ths
        opn = "round.l.s";
6572 5a5012ec ths
        break;
6573 bf4120ad Nathan Froyd
    case OPC_TRUNC_L_S:
6574 5e755519 ths
        check_cp1_64bitmode(ctx);
6575 b6d96bed ths
        {
6576 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
6577 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
6578 b6d96bed ths
6579 b6d96bed ths
            gen_load_fpr32(fp32, fs);
6580 a7812ae4 pbrook
            gen_helper_float_truncl_s(fp64, fp32);
6581 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
6582 b6d96bed ths
            gen_store_fpr64(ctx, fp64, fd);
6583 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
6584 b6d96bed ths
        }
6585 5a5012ec ths
        opn = "trunc.l.s";
6586 5a5012ec ths
        break;
6587 bf4120ad Nathan Froyd
    case OPC_CEIL_L_S:
6588 5e755519 ths
        check_cp1_64bitmode(ctx);
6589 b6d96bed ths
        {
6590 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
6591 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
6592 b6d96bed ths
6593 b6d96bed ths
            gen_load_fpr32(fp32, fs);
6594 a7812ae4 pbrook
            gen_helper_float_ceill_s(fp64, fp32);
6595 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
6596 b6d96bed ths
            gen_store_fpr64(ctx, fp64, fd);
6597 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
6598 b6d96bed ths
        }
6599 5a5012ec ths
        opn = "ceil.l.s";
6600 5a5012ec ths
        break;
6601 bf4120ad Nathan Froyd
    case OPC_FLOOR_L_S:
6602 5e755519 ths
        check_cp1_64bitmode(ctx);
6603 b6d96bed ths
        {
6604 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
6605 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
6606 b6d96bed ths
6607 b6d96bed ths
            gen_load_fpr32(fp32, fs);
6608 a7812ae4 pbrook
            gen_helper_float_floorl_s(fp64, fp32);
6609 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
6610 b6d96bed ths
            gen_store_fpr64(ctx, fp64, fd);
6611 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
6612 b6d96bed ths
        }
6613 5a5012ec ths
        opn = "floor.l.s";
6614 5a5012ec ths
        break;
6615 bf4120ad Nathan Froyd
    case OPC_ROUND_W_S:
6616 b6d96bed ths
        {
6617 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6618 b6d96bed ths
6619 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6620 a7812ae4 pbrook
            gen_helper_float_roundw_s(fp0, fp0);
6621 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6622 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6623 b6d96bed ths
        }
6624 5a5012ec ths
        opn = "round.w.s";
6625 5a5012ec ths
        break;
6626 bf4120ad Nathan Froyd
    case OPC_TRUNC_W_S:
6627 b6d96bed ths
        {
6628 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6629 b6d96bed ths
6630 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6631 a7812ae4 pbrook
            gen_helper_float_truncw_s(fp0, fp0);
6632 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6633 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6634 b6d96bed ths
        }
6635 5a5012ec ths
        opn = "trunc.w.s";
6636 5a5012ec ths
        break;
6637 bf4120ad Nathan Froyd
    case OPC_CEIL_W_S:
6638 b6d96bed ths
        {
6639 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6640 b6d96bed ths
6641 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6642 a7812ae4 pbrook
            gen_helper_float_ceilw_s(fp0, fp0);
6643 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6644 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6645 b6d96bed ths
        }
6646 5a5012ec ths
        opn = "ceil.w.s";
6647 5a5012ec ths
        break;
6648 bf4120ad Nathan Froyd
    case OPC_FLOOR_W_S:
6649 b6d96bed ths
        {
6650 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6651 b6d96bed ths
6652 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6653 a7812ae4 pbrook
            gen_helper_float_floorw_s(fp0, fp0);
6654 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6655 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6656 b6d96bed ths
        }
6657 5a5012ec ths
        opn = "floor.w.s";
6658 5a5012ec ths
        break;
6659 bf4120ad Nathan Froyd
    case OPC_MOVCF_S:
6660 b6d96bed ths
        gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6661 5a5012ec ths
        opn = "movcf.s";
6662 5a5012ec ths
        break;
6663 bf4120ad Nathan Froyd
    case OPC_MOVZ_S:
6664 a16336e4 ths
        {
6665 a16336e4 ths
            int l1 = gen_new_label();
6666 c9297f4d aurel32
            TCGv_i32 fp0;
6667 a16336e4 ths
6668 c9297f4d aurel32
            if (ft != 0) {
6669 c9297f4d aurel32
                tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6670 c9297f4d aurel32
            }
6671 c9297f4d aurel32
            fp0 = tcg_temp_new_i32();
6672 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6673 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6674 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6675 a16336e4 ths
            gen_set_label(l1);
6676 a16336e4 ths
        }
6677 5a5012ec ths
        opn = "movz.s";
6678 5a5012ec ths
        break;
6679 bf4120ad Nathan Froyd
    case OPC_MOVN_S:
6680 a16336e4 ths
        {
6681 a16336e4 ths
            int l1 = gen_new_label();
6682 c9297f4d aurel32
            TCGv_i32 fp0;
6683 c9297f4d aurel32
6684 c9297f4d aurel32
            if (ft != 0) {
6685 c9297f4d aurel32
                tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6686 c9297f4d aurel32
                fp0 = tcg_temp_new_i32();
6687 c9297f4d aurel32
                gen_load_fpr32(fp0, fs);
6688 c9297f4d aurel32
                gen_store_fpr32(fp0, fd);
6689 c9297f4d aurel32
                tcg_temp_free_i32(fp0);
6690 c9297f4d aurel32
                gen_set_label(l1);
6691 c9297f4d aurel32
            }
6692 a16336e4 ths
        }
6693 5a5012ec ths
        opn = "movn.s";
6694 5a5012ec ths
        break;
6695 bf4120ad Nathan Froyd
    case OPC_RECIP_S:
6696 b8aa4598 ths
        check_cop1x(ctx);
6697 b6d96bed ths
        {
6698 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6699 b6d96bed ths
6700 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6701 a7812ae4 pbrook
            gen_helper_float_recip_s(fp0, fp0);
6702 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6703 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6704 b6d96bed ths
        }
6705 57fa1fb3 ths
        opn = "recip.s";
6706 57fa1fb3 ths
        break;
6707 bf4120ad Nathan Froyd
    case OPC_RSQRT_S:
6708 b8aa4598 ths
        check_cop1x(ctx);
6709 b6d96bed ths
        {
6710 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6711 b6d96bed ths
6712 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6713 a7812ae4 pbrook
            gen_helper_float_rsqrt_s(fp0, fp0);
6714 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6715 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6716 b6d96bed ths
        }
6717 57fa1fb3 ths
        opn = "rsqrt.s";
6718 57fa1fb3 ths
        break;
6719 bf4120ad Nathan Froyd
    case OPC_RECIP2_S:
6720 5e755519 ths
        check_cp1_64bitmode(ctx);
6721 b6d96bed ths
        {
6722 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6723 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
6724 b6d96bed ths
6725 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6726 b6d96bed ths
            gen_load_fpr32(fp1, fd);
6727 a7812ae4 pbrook
            gen_helper_float_recip2_s(fp0, fp0, fp1);
6728 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
6729 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6730 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6731 b6d96bed ths
        }
6732 57fa1fb3 ths
        opn = "recip2.s";
6733 57fa1fb3 ths
        break;
6734 bf4120ad Nathan Froyd
    case OPC_RECIP1_S:
6735 5e755519 ths
        check_cp1_64bitmode(ctx);
6736 b6d96bed ths
        {
6737 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6738 b6d96bed ths
6739 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6740 a7812ae4 pbrook
            gen_helper_float_recip1_s(fp0, fp0);
6741 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6742 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6743 b6d96bed ths
        }
6744 57fa1fb3 ths
        opn = "recip1.s";
6745 57fa1fb3 ths
        break;
6746 bf4120ad Nathan Froyd
    case OPC_RSQRT1_S:
6747 5e755519 ths
        check_cp1_64bitmode(ctx);
6748 b6d96bed ths
        {
6749 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6750 b6d96bed ths
6751 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6752 a7812ae4 pbrook
            gen_helper_float_rsqrt1_s(fp0, fp0);
6753 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6754 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6755 b6d96bed ths
        }
6756 57fa1fb3 ths
        opn = "rsqrt1.s";
6757 57fa1fb3 ths
        break;
6758 bf4120ad Nathan Froyd
    case OPC_RSQRT2_S:
6759 5e755519 ths
        check_cp1_64bitmode(ctx);
6760 b6d96bed ths
        {
6761 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6762 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
6763 b6d96bed ths
6764 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6765 b6d96bed ths
            gen_load_fpr32(fp1, ft);
6766 a7812ae4 pbrook
            gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6767 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
6768 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6769 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6770 b6d96bed ths
        }
6771 57fa1fb3 ths
        opn = "rsqrt2.s";
6772 57fa1fb3 ths
        break;
6773 bf4120ad Nathan Froyd
    case OPC_CVT_D_S:
6774 5e755519 ths
        check_cp1_registers(ctx, fd);
6775 b6d96bed ths
        {
6776 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
6777 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
6778 b6d96bed ths
6779 b6d96bed ths
            gen_load_fpr32(fp32, fs);
6780 a7812ae4 pbrook
            gen_helper_float_cvtd_s(fp64, fp32);
6781 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
6782 b6d96bed ths
            gen_store_fpr64(ctx, fp64, fd);
6783 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
6784 b6d96bed ths
        }
6785 5a5012ec ths
        opn = "cvt.d.s";
6786 5a5012ec ths
        break;
6787 bf4120ad Nathan Froyd
    case OPC_CVT_W_S:
6788 b6d96bed ths
        {
6789 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
6790 b6d96bed ths
6791 b6d96bed ths
            gen_load_fpr32(fp0, fs);
6792 a7812ae4 pbrook
            gen_helper_float_cvtw_s(fp0, fp0);
6793 b6d96bed ths
            gen_store_fpr32(fp0, fd);
6794 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
6795 b6d96bed ths
        }
6796 5a5012ec ths
        opn = "cvt.w.s";
6797 5a5012ec ths
        break;
6798 bf4120ad Nathan Froyd
    case OPC_CVT_L_S:
6799 5e755519 ths
        check_cp1_64bitmode(ctx);
6800 b6d96bed ths
        {
6801 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
6802 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
6803 b6d96bed ths
6804 b6d96bed ths
            gen_load_fpr32(fp32, fs);
6805 a7812ae4 pbrook
            gen_helper_float_cvtl_s(fp64, fp32);
6806 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
6807 b6d96bed ths
            gen_store_fpr64(ctx, fp64, fd);
6808 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
6809 b6d96bed ths
        }
6810 5a5012ec ths
        opn = "cvt.l.s";
6811 5a5012ec ths
        break;
6812 bf4120ad Nathan Froyd
    case OPC_CVT_PS_S:
6813 5e755519 ths
        check_cp1_64bitmode(ctx);
6814 b6d96bed ths
        {
6815 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
6816 a7812ae4 pbrook
            TCGv_i32 fp32_0 = tcg_temp_new_i32();
6817 a7812ae4 pbrook
            TCGv_i32 fp32_1 = tcg_temp_new_i32();
6818 b6d96bed ths
6819 b6d96bed ths
            gen_load_fpr32(fp32_0, fs);
6820 b6d96bed ths
            gen_load_fpr32(fp32_1, ft);
6821 36aa55dc pbrook
            tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6822 a7812ae4 pbrook
            tcg_temp_free_i32(fp32_1);
6823 a7812ae4 pbrook
            tcg_temp_free_i32(fp32_0);
6824 36aa55dc pbrook
            gen_store_fpr64(ctx, fp64, fd);
6825 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
6826 b6d96bed ths
        }
6827 5a5012ec ths
        opn = "cvt.ps.s";
6828 5a5012ec ths
        break;
6829 bf4120ad Nathan Froyd
    case OPC_CMP_F_S:
6830 bf4120ad Nathan Froyd
    case OPC_CMP_UN_S:
6831 bf4120ad Nathan Froyd
    case OPC_CMP_EQ_S:
6832 bf4120ad Nathan Froyd
    case OPC_CMP_UEQ_S:
6833 bf4120ad Nathan Froyd
    case OPC_CMP_OLT_S:
6834 bf4120ad Nathan Froyd
    case OPC_CMP_ULT_S:
6835 bf4120ad Nathan Froyd
    case OPC_CMP_OLE_S:
6836 bf4120ad Nathan Froyd
    case OPC_CMP_ULE_S:
6837 bf4120ad Nathan Froyd
    case OPC_CMP_SF_S:
6838 bf4120ad Nathan Froyd
    case OPC_CMP_NGLE_S:
6839 bf4120ad Nathan Froyd
    case OPC_CMP_SEQ_S:
6840 bf4120ad Nathan Froyd
    case OPC_CMP_NGL_S:
6841 bf4120ad Nathan Froyd
    case OPC_CMP_LT_S:
6842 bf4120ad Nathan Froyd
    case OPC_CMP_NGE_S:
6843 bf4120ad Nathan Froyd
    case OPC_CMP_LE_S:
6844 bf4120ad Nathan Froyd
    case OPC_CMP_NGT_S:
6845 8153667c Nathan Froyd
        if (ctx->opcode & (1 << 6)) {
6846 8153667c Nathan Froyd
            gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6847 8153667c Nathan Froyd
            opn = condnames_abs[func-48];
6848 8153667c Nathan Froyd
        } else {
6849 8153667c Nathan Froyd
            gen_cmp_s(ctx, func-48, ft, fs, cc);
6850 8153667c Nathan Froyd
            opn = condnames[func-48];
6851 5a1e8ffb ths
        }
6852 5a5012ec ths
        break;
6853 bf4120ad Nathan Froyd
    case OPC_ADD_D:
6854 5e755519 ths
        check_cp1_registers(ctx, fs | ft | fd);
6855 b6d96bed ths
        {
6856 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
6857 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
6858 b6d96bed ths
6859 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
6860 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
6861 a7812ae4 pbrook
            gen_helper_float_add_d(fp0, fp0, fp1);
6862 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
6863 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
6864 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
6865 b6d96bed ths
        }
6866 6ea83fed bellard
        opn = "add.d";
6867 5a1e8ffb ths
        optype = BINOP;
6868 6ea83fed bellard
        break;
6869 bf4120ad Nathan Froyd
    case OPC_SUB_D:
6870 5e755519 ths
        check_cp1_registers(ctx, fs | ft | fd);
6871 b6d96bed ths
        {
6872 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
6873 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
6874 b6d96bed ths
6875 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
6876 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
6877 a7812ae4 pbrook
            gen_helper_float_sub_d(fp0, fp0, fp1);
6878 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
6879 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
6880 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
6881 b6d96bed ths
        }
6882 6ea83fed bellard
        opn = "sub.d";
6883 5a1e8ffb ths
        optype = BINOP;
6884 6ea83fed bellard
        break;
6885 bf4120ad Nathan Froyd
    case OPC_MUL_D:
6886 5e755519 ths
        check_cp1_registers(ctx, fs | ft | fd);
6887 b6d96bed ths
        {
6888 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
6889 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
6890 b6d96bed ths
6891 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
6892 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
6893 a7812ae4 pbrook
            gen_helper_float_mul_d(fp0, fp0, fp1);
6894 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
6895 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
6896 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
6897 b6d96bed ths
        }
6898 6ea83fed bellard
        opn = "mul.d";
6899 5a1e8ffb ths
        optype = BINOP;
6900 6ea83fed bellard
        break;
6901 bf4120ad Nathan Froyd
    case OPC_DIV_D:
6902 5e755519 ths
        check_cp1_registers(ctx, fs | ft | fd);
6903 b6d96bed ths
        {
6904 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
6905 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
6906 b6d96bed ths
6907 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
6908 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
6909 a7812ae4 pbrook
            gen_helper_float_div_d(fp0, fp0, fp1);
6910 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
6911 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
6912 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
6913 b6d96bed ths
        }
6914 6ea83fed bellard
        opn = "div.d";
6915 5a1e8ffb ths
        optype = BINOP;
6916 6ea83fed bellard
        break;
6917 bf4120ad Nathan Froyd
    case OPC_SQRT_D:
6918 5e755519 ths
        check_cp1_registers(ctx, fs | fd);
6919 b6d96bed ths
        {
6920 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
6921 b6d96bed ths
6922 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
6923 a7812ae4 pbrook
            gen_helper_float_sqrt_d(fp0, fp0);
6924 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
6925 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
6926 b6d96bed ths
        }
6927 6ea83fed bellard
        opn = "sqrt.d";
6928 6ea83fed bellard
        break;
6929 bf4120ad Nathan Froyd
    case OPC_ABS_D:
6930 5e755519 ths
        check_cp1_registers(ctx, fs | fd);
6931 b6d96bed ths
        {
6932 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
6933 b6d96bed ths
6934 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
6935 a7812ae4 pbrook
            gen_helper_float_abs_d(fp0, fp0);
6936 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
6937 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
6938 b6d96bed ths
        }
6939 6ea83fed bellard
        opn = "abs.d";
6940 6ea83fed bellard
        break;
6941 bf4120ad Nathan Froyd
    case OPC_MOV_D:
6942 5e755519 ths
        check_cp1_registers(ctx, fs | fd);
6943 b6d96bed ths
        {
6944 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
6945 b6d96bed ths
6946 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
6947 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
6948 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
6949 b6d96bed ths
        }
6950 6ea83fed bellard
        opn = "mov.d";
6951 6ea83fed bellard
        break;
6952 bf4120ad Nathan Froyd
    case OPC_NEG_D:
6953 5e755519 ths
        check_cp1_registers(ctx, fs | fd);
6954 b6d96bed ths
        {
6955 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
6956 b6d96bed ths
6957 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
6958 a7812ae4 pbrook
            gen_helper_float_chs_d(fp0, fp0);
6959 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
6960 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
6961 b6d96bed ths
        }
6962 6ea83fed bellard
        opn = "neg.d";
6963 6ea83fed bellard
        break;
6964 bf4120ad Nathan Froyd
    case OPC_ROUND_L_D:
6965 5e755519 ths
        check_cp1_64bitmode(ctx);
6966 b6d96bed ths
        {
6967 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
6968 b6d96bed ths
6969 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
6970 a7812ae4 pbrook
            gen_helper_float_roundl_d(fp0, fp0);
6971 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
6972 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
6973 b6d96bed ths
        }
6974 5a5012ec ths
        opn = "round.l.d";
6975 5a5012ec ths
        break;
6976 bf4120ad Nathan Froyd
    case OPC_TRUNC_L_D:
6977 5e755519 ths
        check_cp1_64bitmode(ctx);
6978 b6d96bed ths
        {
6979 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
6980 b6d96bed ths
6981 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
6982 a7812ae4 pbrook
            gen_helper_float_truncl_d(fp0, fp0);
6983 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
6984 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
6985 b6d96bed ths
        }
6986 5a5012ec ths
        opn = "trunc.l.d";
6987 5a5012ec ths
        break;
6988 bf4120ad Nathan Froyd
    case OPC_CEIL_L_D:
6989 5e755519 ths
        check_cp1_64bitmode(ctx);
6990 b6d96bed ths
        {
6991 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
6992 b6d96bed ths
6993 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
6994 a7812ae4 pbrook
            gen_helper_float_ceill_d(fp0, fp0);
6995 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
6996 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
6997 b6d96bed ths
        }
6998 5a5012ec ths
        opn = "ceil.l.d";
6999 5a5012ec ths
        break;
7000 bf4120ad Nathan Froyd
    case OPC_FLOOR_L_D:
7001 5e755519 ths
        check_cp1_64bitmode(ctx);
7002 b6d96bed ths
        {
7003 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7004 b6d96bed ths
7005 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7006 a7812ae4 pbrook
            gen_helper_float_floorl_d(fp0, fp0);
7007 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7008 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7009 b6d96bed ths
        }
7010 5a5012ec ths
        opn = "floor.l.d";
7011 5a5012ec ths
        break;
7012 bf4120ad Nathan Froyd
    case OPC_ROUND_W_D:
7013 5e755519 ths
        check_cp1_registers(ctx, fs);
7014 b6d96bed ths
        {
7015 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
7016 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
7017 b6d96bed ths
7018 b6d96bed ths
            gen_load_fpr64(ctx, fp64, fs);
7019 a7812ae4 pbrook
            gen_helper_float_roundw_d(fp32, fp64);
7020 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
7021 b6d96bed ths
            gen_store_fpr32(fp32, fd);
7022 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
7023 b6d96bed ths
        }
7024 6ea83fed bellard
        opn = "round.w.d";
7025 6ea83fed bellard
        break;
7026 bf4120ad Nathan Froyd
    case OPC_TRUNC_W_D:
7027 5e755519 ths
        check_cp1_registers(ctx, fs);
7028 b6d96bed ths
        {
7029 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
7030 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
7031 b6d96bed ths
7032 b6d96bed ths
            gen_load_fpr64(ctx, fp64, fs);
7033 a7812ae4 pbrook
            gen_helper_float_truncw_d(fp32, fp64);
7034 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
7035 b6d96bed ths
            gen_store_fpr32(fp32, fd);
7036 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
7037 b6d96bed ths
        }
7038 6ea83fed bellard
        opn = "trunc.w.d";
7039 6ea83fed bellard
        break;
7040 bf4120ad Nathan Froyd
    case OPC_CEIL_W_D:
7041 5e755519 ths
        check_cp1_registers(ctx, fs);
7042 b6d96bed ths
        {
7043 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
7044 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
7045 b6d96bed ths
7046 b6d96bed ths
            gen_load_fpr64(ctx, fp64, fs);
7047 a7812ae4 pbrook
            gen_helper_float_ceilw_d(fp32, fp64);
7048 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
7049 b6d96bed ths
            gen_store_fpr32(fp32, fd);
7050 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
7051 b6d96bed ths
        }
7052 6ea83fed bellard
        opn = "ceil.w.d";
7053 6ea83fed bellard
        break;
7054 bf4120ad Nathan Froyd
    case OPC_FLOOR_W_D:
7055 5e755519 ths
        check_cp1_registers(ctx, fs);
7056 b6d96bed ths
        {
7057 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
7058 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
7059 b6d96bed ths
7060 b6d96bed ths
            gen_load_fpr64(ctx, fp64, fs);
7061 a7812ae4 pbrook
            gen_helper_float_floorw_d(fp32, fp64);
7062 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
7063 b6d96bed ths
            gen_store_fpr32(fp32, fd);
7064 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
7065 b6d96bed ths
        }
7066 7a387fff ths
        opn = "floor.w.d";
7067 6ea83fed bellard
        break;
7068 bf4120ad Nathan Froyd
    case OPC_MOVCF_D:
7069 b6d96bed ths
        gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7070 5a5012ec ths
        opn = "movcf.d";
7071 dd016883 bellard
        break;
7072 bf4120ad Nathan Froyd
    case OPC_MOVZ_D:
7073 a16336e4 ths
        {
7074 a16336e4 ths
            int l1 = gen_new_label();
7075 c9297f4d aurel32
            TCGv_i64 fp0;
7076 a16336e4 ths
7077 c9297f4d aurel32
            if (ft != 0) {
7078 c9297f4d aurel32
                tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7079 c9297f4d aurel32
            }
7080 c9297f4d aurel32
            fp0 = tcg_temp_new_i64();
7081 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7082 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7083 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7084 a16336e4 ths
            gen_set_label(l1);
7085 a16336e4 ths
        }
7086 5a5012ec ths
        opn = "movz.d";
7087 5a5012ec ths
        break;
7088 bf4120ad Nathan Froyd
    case OPC_MOVN_D:
7089 a16336e4 ths
        {
7090 a16336e4 ths
            int l1 = gen_new_label();
7091 c9297f4d aurel32
            TCGv_i64 fp0;
7092 c9297f4d aurel32
7093 c9297f4d aurel32
            if (ft != 0) {
7094 c9297f4d aurel32
                tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7095 c9297f4d aurel32
                fp0 = tcg_temp_new_i64();
7096 c9297f4d aurel32
                gen_load_fpr64(ctx, fp0, fs);
7097 c9297f4d aurel32
                gen_store_fpr64(ctx, fp0, fd);
7098 c9297f4d aurel32
                tcg_temp_free_i64(fp0);
7099 c9297f4d aurel32
                gen_set_label(l1);
7100 c9297f4d aurel32
            }
7101 a16336e4 ths
        }
7102 5a5012ec ths
        opn = "movn.d";
7103 6ea83fed bellard
        break;
7104 bf4120ad Nathan Froyd
    case OPC_RECIP_D:
7105 b8aa4598 ths
        check_cp1_64bitmode(ctx);
7106 b6d96bed ths
        {
7107 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7108 b6d96bed ths
7109 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7110 a7812ae4 pbrook
            gen_helper_float_recip_d(fp0, fp0);
7111 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7112 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7113 b6d96bed ths
        }
7114 57fa1fb3 ths
        opn = "recip.d";
7115 57fa1fb3 ths
        break;
7116 bf4120ad Nathan Froyd
    case OPC_RSQRT_D:
7117 b8aa4598 ths
        check_cp1_64bitmode(ctx);
7118 b6d96bed ths
        {
7119 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7120 b6d96bed ths
7121 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7122 a7812ae4 pbrook
            gen_helper_float_rsqrt_d(fp0, fp0);
7123 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7124 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7125 b6d96bed ths
        }
7126 57fa1fb3 ths
        opn = "rsqrt.d";
7127 57fa1fb3 ths
        break;
7128 bf4120ad Nathan Froyd
    case OPC_RECIP2_D:
7129 5e755519 ths
        check_cp1_64bitmode(ctx);
7130 b6d96bed ths
        {
7131 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7132 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7133 b6d96bed ths
7134 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7135 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7136 a7812ae4 pbrook
            gen_helper_float_recip2_d(fp0, fp0, fp1);
7137 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7138 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7139 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7140 b6d96bed ths
        }
7141 57fa1fb3 ths
        opn = "recip2.d";
7142 57fa1fb3 ths
        break;
7143 bf4120ad Nathan Froyd
    case OPC_RECIP1_D:
7144 5e755519 ths
        check_cp1_64bitmode(ctx);
7145 b6d96bed ths
        {
7146 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7147 b6d96bed ths
7148 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7149 a7812ae4 pbrook
            gen_helper_float_recip1_d(fp0, fp0);
7150 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7151 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7152 b6d96bed ths
        }
7153 57fa1fb3 ths
        opn = "recip1.d";
7154 57fa1fb3 ths
        break;
7155 bf4120ad Nathan Froyd
    case OPC_RSQRT1_D:
7156 5e755519 ths
        check_cp1_64bitmode(ctx);
7157 b6d96bed ths
        {
7158 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7159 b6d96bed ths
7160 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7161 a7812ae4 pbrook
            gen_helper_float_rsqrt1_d(fp0, fp0);
7162 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7163 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7164 b6d96bed ths
        }
7165 57fa1fb3 ths
        opn = "rsqrt1.d";
7166 57fa1fb3 ths
        break;
7167 bf4120ad Nathan Froyd
    case OPC_RSQRT2_D:
7168 5e755519 ths
        check_cp1_64bitmode(ctx);
7169 b6d96bed ths
        {
7170 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7171 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7172 b6d96bed ths
7173 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7174 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7175 a7812ae4 pbrook
            gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
7176 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7177 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7178 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7179 b6d96bed ths
        }
7180 57fa1fb3 ths
        opn = "rsqrt2.d";
7181 57fa1fb3 ths
        break;
7182 bf4120ad Nathan Froyd
    case OPC_CMP_F_D:
7183 bf4120ad Nathan Froyd
    case OPC_CMP_UN_D:
7184 bf4120ad Nathan Froyd
    case OPC_CMP_EQ_D:
7185 bf4120ad Nathan Froyd
    case OPC_CMP_UEQ_D:
7186 bf4120ad Nathan Froyd
    case OPC_CMP_OLT_D:
7187 bf4120ad Nathan Froyd
    case OPC_CMP_ULT_D:
7188 bf4120ad Nathan Froyd
    case OPC_CMP_OLE_D:
7189 bf4120ad Nathan Froyd
    case OPC_CMP_ULE_D:
7190 bf4120ad Nathan Froyd
    case OPC_CMP_SF_D:
7191 bf4120ad Nathan Froyd
    case OPC_CMP_NGLE_D:
7192 bf4120ad Nathan Froyd
    case OPC_CMP_SEQ_D:
7193 bf4120ad Nathan Froyd
    case OPC_CMP_NGL_D:
7194 bf4120ad Nathan Froyd
    case OPC_CMP_LT_D:
7195 bf4120ad Nathan Froyd
    case OPC_CMP_NGE_D:
7196 bf4120ad Nathan Froyd
    case OPC_CMP_LE_D:
7197 bf4120ad Nathan Froyd
    case OPC_CMP_NGT_D:
7198 8153667c Nathan Froyd
        if (ctx->opcode & (1 << 6)) {
7199 8153667c Nathan Froyd
            gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7200 8153667c Nathan Froyd
            opn = condnames_abs[func-48];
7201 8153667c Nathan Froyd
        } else {
7202 8153667c Nathan Froyd
            gen_cmp_d(ctx, func-48, ft, fs, cc);
7203 8153667c Nathan Froyd
            opn = condnames[func-48];
7204 5a1e8ffb ths
        }
7205 6ea83fed bellard
        break;
7206 bf4120ad Nathan Froyd
    case OPC_CVT_S_D:
7207 5e755519 ths
        check_cp1_registers(ctx, fs);
7208 b6d96bed ths
        {
7209 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
7210 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
7211 b6d96bed ths
7212 b6d96bed ths
            gen_load_fpr64(ctx, fp64, fs);
7213 a7812ae4 pbrook
            gen_helper_float_cvts_d(fp32, fp64);
7214 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
7215 b6d96bed ths
            gen_store_fpr32(fp32, fd);
7216 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
7217 b6d96bed ths
        }
7218 5a5012ec ths
        opn = "cvt.s.d";
7219 5a5012ec ths
        break;
7220 bf4120ad Nathan Froyd
    case OPC_CVT_W_D:
7221 5e755519 ths
        check_cp1_registers(ctx, fs);
7222 b6d96bed ths
        {
7223 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
7224 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
7225 b6d96bed ths
7226 b6d96bed ths
            gen_load_fpr64(ctx, fp64, fs);
7227 a7812ae4 pbrook
            gen_helper_float_cvtw_d(fp32, fp64);
7228 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
7229 b6d96bed ths
            gen_store_fpr32(fp32, fd);
7230 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
7231 b6d96bed ths
        }
7232 5a5012ec ths
        opn = "cvt.w.d";
7233 5a5012ec ths
        break;
7234 bf4120ad Nathan Froyd
    case OPC_CVT_L_D:
7235 5e755519 ths
        check_cp1_64bitmode(ctx);
7236 b6d96bed ths
        {
7237 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7238 b6d96bed ths
7239 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7240 a7812ae4 pbrook
            gen_helper_float_cvtl_d(fp0, fp0);
7241 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7242 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7243 b6d96bed ths
        }
7244 5a5012ec ths
        opn = "cvt.l.d";
7245 5a5012ec ths
        break;
7246 bf4120ad Nathan Froyd
    case OPC_CVT_S_W:
7247 b6d96bed ths
        {
7248 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7249 b6d96bed ths
7250 b6d96bed ths
            gen_load_fpr32(fp0, fs);
7251 a7812ae4 pbrook
            gen_helper_float_cvts_w(fp0, fp0);
7252 b6d96bed ths
            gen_store_fpr32(fp0, fd);
7253 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7254 b6d96bed ths
        }
7255 5a5012ec ths
        opn = "cvt.s.w";
7256 6ea83fed bellard
        break;
7257 bf4120ad Nathan Froyd
    case OPC_CVT_D_W:
7258 5e755519 ths
        check_cp1_registers(ctx, fd);
7259 b6d96bed ths
        {
7260 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
7261 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
7262 b6d96bed ths
7263 b6d96bed ths
            gen_load_fpr32(fp32, fs);
7264 a7812ae4 pbrook
            gen_helper_float_cvtd_w(fp64, fp32);
7265 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
7266 b6d96bed ths
            gen_store_fpr64(ctx, fp64, fd);
7267 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
7268 b6d96bed ths
        }
7269 5a5012ec ths
        opn = "cvt.d.w";
7270 5a5012ec ths
        break;
7271 bf4120ad Nathan Froyd
    case OPC_CVT_S_L:
7272 5e755519 ths
        check_cp1_64bitmode(ctx);
7273 b6d96bed ths
        {
7274 a7812ae4 pbrook
            TCGv_i32 fp32 = tcg_temp_new_i32();
7275 a7812ae4 pbrook
            TCGv_i64 fp64 = tcg_temp_new_i64();
7276 b6d96bed ths
7277 b6d96bed ths
            gen_load_fpr64(ctx, fp64, fs);
7278 a7812ae4 pbrook
            gen_helper_float_cvts_l(fp32, fp64);
7279 a7812ae4 pbrook
            tcg_temp_free_i64(fp64);
7280 b6d96bed ths
            gen_store_fpr32(fp32, fd);
7281 a7812ae4 pbrook
            tcg_temp_free_i32(fp32);
7282 b6d96bed ths
        }
7283 5a5012ec ths
        opn = "cvt.s.l";
7284 5a5012ec ths
        break;
7285 bf4120ad Nathan Froyd
    case OPC_CVT_D_L:
7286 5e755519 ths
        check_cp1_64bitmode(ctx);
7287 b6d96bed ths
        {
7288 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7289 b6d96bed ths
7290 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7291 a7812ae4 pbrook
            gen_helper_float_cvtd_l(fp0, fp0);
7292 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7293 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7294 b6d96bed ths
        }
7295 5a5012ec ths
        opn = "cvt.d.l";
7296 5a5012ec ths
        break;
7297 bf4120ad Nathan Froyd
    case OPC_CVT_PS_PW:
7298 5e755519 ths
        check_cp1_64bitmode(ctx);
7299 b6d96bed ths
        {
7300 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7301 b6d96bed ths
7302 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7303 a7812ae4 pbrook
            gen_helper_float_cvtps_pw(fp0, fp0);
7304 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7305 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7306 b6d96bed ths
        }
7307 5a5012ec ths
        opn = "cvt.ps.pw";
7308 5a5012ec ths
        break;
7309 bf4120ad Nathan Froyd
    case OPC_ADD_PS:
7310 5e755519 ths
        check_cp1_64bitmode(ctx);
7311 b6d96bed ths
        {
7312 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7313 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7314 b6d96bed ths
7315 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7316 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7317 a7812ae4 pbrook
            gen_helper_float_add_ps(fp0, fp0, fp1);
7318 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7319 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7320 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7321 b6d96bed ths
        }
7322 5a5012ec ths
        opn = "add.ps";
7323 6ea83fed bellard
        break;
7324 bf4120ad Nathan Froyd
    case OPC_SUB_PS:
7325 5e755519 ths
        check_cp1_64bitmode(ctx);
7326 b6d96bed ths
        {
7327 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7328 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7329 b6d96bed ths
7330 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7331 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7332 a7812ae4 pbrook
            gen_helper_float_sub_ps(fp0, fp0, fp1);
7333 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7334 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7335 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7336 b6d96bed ths
        }
7337 5a5012ec ths
        opn = "sub.ps";
7338 6ea83fed bellard
        break;
7339 bf4120ad Nathan Froyd
    case OPC_MUL_PS:
7340 5e755519 ths
        check_cp1_64bitmode(ctx);
7341 b6d96bed ths
        {
7342 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7343 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7344 b6d96bed ths
7345 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7346 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7347 a7812ae4 pbrook
            gen_helper_float_mul_ps(fp0, fp0, fp1);
7348 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7349 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7350 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7351 b6d96bed ths
        }
7352 5a5012ec ths
        opn = "mul.ps";
7353 6ea83fed bellard
        break;
7354 bf4120ad Nathan Froyd
    case OPC_ABS_PS:
7355 5e755519 ths
        check_cp1_64bitmode(ctx);
7356 b6d96bed ths
        {
7357 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7358 b6d96bed ths
7359 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7360 a7812ae4 pbrook
            gen_helper_float_abs_ps(fp0, fp0);
7361 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7362 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7363 b6d96bed ths
        }
7364 5a5012ec ths
        opn = "abs.ps";
7365 6ea83fed bellard
        break;
7366 bf4120ad Nathan Froyd
    case OPC_MOV_PS:
7367 5e755519 ths
        check_cp1_64bitmode(ctx);
7368 b6d96bed ths
        {
7369 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7370 b6d96bed ths
7371 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7372 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7373 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7374 b6d96bed ths
        }
7375 5a5012ec ths
        opn = "mov.ps";
7376 6ea83fed bellard
        break;
7377 bf4120ad Nathan Froyd
    case OPC_NEG_PS:
7378 5e755519 ths
        check_cp1_64bitmode(ctx);
7379 b6d96bed ths
        {
7380 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7381 b6d96bed ths
7382 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7383 a7812ae4 pbrook
            gen_helper_float_chs_ps(fp0, fp0);
7384 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7385 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7386 b6d96bed ths
        }
7387 5a5012ec ths
        opn = "neg.ps";
7388 6ea83fed bellard
        break;
7389 bf4120ad Nathan Froyd
    case OPC_MOVCF_PS:
7390 5e755519 ths
        check_cp1_64bitmode(ctx);
7391 b6d96bed ths
        gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7392 5a5012ec ths
        opn = "movcf.ps";
7393 6ea83fed bellard
        break;
7394 bf4120ad Nathan Froyd
    case OPC_MOVZ_PS:
7395 5e755519 ths
        check_cp1_64bitmode(ctx);
7396 a16336e4 ths
        {
7397 a16336e4 ths
            int l1 = gen_new_label();
7398 30a3848b aurel32
            TCGv_i64 fp0;
7399 a16336e4 ths
7400 c9297f4d aurel32
            if (ft != 0)
7401 c9297f4d aurel32
                tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7402 c9297f4d aurel32
            fp0 = tcg_temp_new_i64();
7403 c9297f4d aurel32
            gen_load_fpr64(ctx, fp0, fs);
7404 c9297f4d aurel32
            gen_store_fpr64(ctx, fp0, fd);
7405 c9297f4d aurel32
            tcg_temp_free_i64(fp0);
7406 a16336e4 ths
            gen_set_label(l1);
7407 a16336e4 ths
        }
7408 5a5012ec ths
        opn = "movz.ps";
7409 6ea83fed bellard
        break;
7410 bf4120ad Nathan Froyd
    case OPC_MOVN_PS:
7411 5e755519 ths
        check_cp1_64bitmode(ctx);
7412 a16336e4 ths
        {
7413 a16336e4 ths
            int l1 = gen_new_label();
7414 30a3848b aurel32
            TCGv_i64 fp0;
7415 c9297f4d aurel32
7416 c9297f4d aurel32
            if (ft != 0) {
7417 c9297f4d aurel32
                tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7418 c9297f4d aurel32
                fp0 = tcg_temp_new_i64();
7419 c9297f4d aurel32
                gen_load_fpr64(ctx, fp0, fs);
7420 c9297f4d aurel32
                gen_store_fpr64(ctx, fp0, fd);
7421 c9297f4d aurel32
                tcg_temp_free_i64(fp0);
7422 c9297f4d aurel32
                gen_set_label(l1);
7423 c9297f4d aurel32
            }
7424 a16336e4 ths
        }
7425 5a5012ec ths
        opn = "movn.ps";
7426 6ea83fed bellard
        break;
7427 bf4120ad Nathan Froyd
    case OPC_ADDR_PS:
7428 5e755519 ths
        check_cp1_64bitmode(ctx);
7429 b6d96bed ths
        {
7430 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7431 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7432 b6d96bed ths
7433 b6d96bed ths
            gen_load_fpr64(ctx, fp0, ft);
7434 b6d96bed ths
            gen_load_fpr64(ctx, fp1, fs);
7435 a7812ae4 pbrook
            gen_helper_float_addr_ps(fp0, fp0, fp1);
7436 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7437 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7438 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7439 b6d96bed ths
        }
7440 fbcc6828 ths
        opn = "addr.ps";
7441 fbcc6828 ths
        break;
7442 bf4120ad Nathan Froyd
    case OPC_MULR_PS:
7443 5e755519 ths
        check_cp1_64bitmode(ctx);
7444 b6d96bed ths
        {
7445 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7446 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7447 b6d96bed ths
7448 b6d96bed ths
            gen_load_fpr64(ctx, fp0, ft);
7449 b6d96bed ths
            gen_load_fpr64(ctx, fp1, fs);
7450 a7812ae4 pbrook
            gen_helper_float_mulr_ps(fp0, fp0, fp1);
7451 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7452 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7453 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7454 b6d96bed ths
        }
7455 57fa1fb3 ths
        opn = "mulr.ps";
7456 57fa1fb3 ths
        break;
7457 bf4120ad Nathan Froyd
    case OPC_RECIP2_PS:
7458 5e755519 ths
        check_cp1_64bitmode(ctx);
7459 b6d96bed ths
        {
7460 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7461 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7462 b6d96bed ths
7463 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7464 b6d96bed ths
            gen_load_fpr64(ctx, fp1, fd);
7465 a7812ae4 pbrook
            gen_helper_float_recip2_ps(fp0, fp0, fp1);
7466 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7467 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7468 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7469 b6d96bed ths
        }
7470 57fa1fb3 ths
        opn = "recip2.ps";
7471 57fa1fb3 ths
        break;
7472 bf4120ad Nathan Froyd
    case OPC_RECIP1_PS:
7473 5e755519 ths
        check_cp1_64bitmode(ctx);
7474 b6d96bed ths
        {
7475 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7476 b6d96bed ths
7477 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7478 a7812ae4 pbrook
            gen_helper_float_recip1_ps(fp0, fp0);
7479 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7480 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7481 b6d96bed ths
        }
7482 57fa1fb3 ths
        opn = "recip1.ps";
7483 57fa1fb3 ths
        break;
7484 bf4120ad Nathan Froyd
    case OPC_RSQRT1_PS:
7485 5e755519 ths
        check_cp1_64bitmode(ctx);
7486 b6d96bed ths
        {
7487 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7488 b6d96bed ths
7489 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7490 a7812ae4 pbrook
            gen_helper_float_rsqrt1_ps(fp0, fp0);
7491 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7492 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7493 b6d96bed ths
        }
7494 57fa1fb3 ths
        opn = "rsqrt1.ps";
7495 57fa1fb3 ths
        break;
7496 bf4120ad Nathan Froyd
    case OPC_RSQRT2_PS:
7497 5e755519 ths
        check_cp1_64bitmode(ctx);
7498 b6d96bed ths
        {
7499 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7500 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7501 b6d96bed ths
7502 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7503 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7504 a7812ae4 pbrook
            gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7505 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7506 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7507 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7508 b6d96bed ths
        }
7509 57fa1fb3 ths
        opn = "rsqrt2.ps";
7510 57fa1fb3 ths
        break;
7511 bf4120ad Nathan Froyd
    case OPC_CVT_S_PU:
7512 5e755519 ths
        check_cp1_64bitmode(ctx);
7513 b6d96bed ths
        {
7514 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7515 b6d96bed ths
7516 b6d96bed ths
            gen_load_fpr32h(fp0, fs);
7517 a7812ae4 pbrook
            gen_helper_float_cvts_pu(fp0, fp0);
7518 b6d96bed ths
            gen_store_fpr32(fp0, fd);
7519 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7520 b6d96bed ths
        }
7521 5a5012ec ths
        opn = "cvt.s.pu";
7522 dd016883 bellard
        break;
7523 bf4120ad Nathan Froyd
    case OPC_CVT_PW_PS:
7524 5e755519 ths
        check_cp1_64bitmode(ctx);
7525 b6d96bed ths
        {
7526 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7527 b6d96bed ths
7528 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7529 a7812ae4 pbrook
            gen_helper_float_cvtpw_ps(fp0, fp0);
7530 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7531 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7532 b6d96bed ths
        }
7533 5a5012ec ths
        opn = "cvt.pw.ps";
7534 6ea83fed bellard
        break;
7535 bf4120ad Nathan Froyd
    case OPC_CVT_S_PL:
7536 5e755519 ths
        check_cp1_64bitmode(ctx);
7537 b6d96bed ths
        {
7538 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7539 b6d96bed ths
7540 b6d96bed ths
            gen_load_fpr32(fp0, fs);
7541 a7812ae4 pbrook
            gen_helper_float_cvts_pl(fp0, fp0);
7542 b6d96bed ths
            gen_store_fpr32(fp0, fd);
7543 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7544 b6d96bed ths
        }
7545 5a5012ec ths
        opn = "cvt.s.pl";
7546 6ea83fed bellard
        break;
7547 bf4120ad Nathan Froyd
    case OPC_PLL_PS:
7548 5e755519 ths
        check_cp1_64bitmode(ctx);
7549 b6d96bed ths
        {
7550 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7551 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
7552 b6d96bed ths
7553 b6d96bed ths
            gen_load_fpr32(fp0, fs);
7554 b6d96bed ths
            gen_load_fpr32(fp1, ft);
7555 b6d96bed ths
            gen_store_fpr32h(fp0, fd);
7556 b6d96bed ths
            gen_store_fpr32(fp1, fd);
7557 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7558 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
7559 b6d96bed ths
        }
7560 5a5012ec ths
        opn = "pll.ps";
7561 6ea83fed bellard
        break;
7562 bf4120ad Nathan Froyd
    case OPC_PLU_PS:
7563 5e755519 ths
        check_cp1_64bitmode(ctx);
7564 b6d96bed ths
        {
7565 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7566 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
7567 b6d96bed ths
7568 b6d96bed ths
            gen_load_fpr32(fp0, fs);
7569 b6d96bed ths
            gen_load_fpr32h(fp1, ft);
7570 b6d96bed ths
            gen_store_fpr32(fp1, fd);
7571 b6d96bed ths
            gen_store_fpr32h(fp0, fd);
7572 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7573 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
7574 b6d96bed ths
        }
7575 5a5012ec ths
        opn = "plu.ps";
7576 5a5012ec ths
        break;
7577 bf4120ad Nathan Froyd
    case OPC_PUL_PS:
7578 5e755519 ths
        check_cp1_64bitmode(ctx);
7579 b6d96bed ths
        {
7580 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7581 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
7582 b6d96bed ths
7583 b6d96bed ths
            gen_load_fpr32h(fp0, fs);
7584 b6d96bed ths
            gen_load_fpr32(fp1, ft);
7585 b6d96bed ths
            gen_store_fpr32(fp1, fd);
7586 b6d96bed ths
            gen_store_fpr32h(fp0, fd);
7587 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7588 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
7589 b6d96bed ths
        }
7590 5a5012ec ths
        opn = "pul.ps";
7591 5a5012ec ths
        break;
7592 bf4120ad Nathan Froyd
    case OPC_PUU_PS:
7593 5e755519 ths
        check_cp1_64bitmode(ctx);
7594 b6d96bed ths
        {
7595 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7596 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
7597 b6d96bed ths
7598 b6d96bed ths
            gen_load_fpr32h(fp0, fs);
7599 b6d96bed ths
            gen_load_fpr32h(fp1, ft);
7600 b6d96bed ths
            gen_store_fpr32(fp1, fd);
7601 b6d96bed ths
            gen_store_fpr32h(fp0, fd);
7602 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7603 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
7604 b6d96bed ths
        }
7605 5a5012ec ths
        opn = "puu.ps";
7606 5a5012ec ths
        break;
7607 bf4120ad Nathan Froyd
    case OPC_CMP_F_PS:
7608 bf4120ad Nathan Froyd
    case OPC_CMP_UN_PS:
7609 bf4120ad Nathan Froyd
    case OPC_CMP_EQ_PS:
7610 bf4120ad Nathan Froyd
    case OPC_CMP_UEQ_PS:
7611 bf4120ad Nathan Froyd
    case OPC_CMP_OLT_PS:
7612 bf4120ad Nathan Froyd
    case OPC_CMP_ULT_PS:
7613 bf4120ad Nathan Froyd
    case OPC_CMP_OLE_PS:
7614 bf4120ad Nathan Froyd
    case OPC_CMP_ULE_PS:
7615 bf4120ad Nathan Froyd
    case OPC_CMP_SF_PS:
7616 bf4120ad Nathan Froyd
    case OPC_CMP_NGLE_PS:
7617 bf4120ad Nathan Froyd
    case OPC_CMP_SEQ_PS:
7618 bf4120ad Nathan Froyd
    case OPC_CMP_NGL_PS:
7619 bf4120ad Nathan Froyd
    case OPC_CMP_LT_PS:
7620 bf4120ad Nathan Froyd
    case OPC_CMP_NGE_PS:
7621 bf4120ad Nathan Froyd
    case OPC_CMP_LE_PS:
7622 bf4120ad Nathan Froyd
    case OPC_CMP_NGT_PS:
7623 8153667c Nathan Froyd
        if (ctx->opcode & (1 << 6)) {
7624 8153667c Nathan Froyd
            gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7625 8153667c Nathan Froyd
            opn = condnames_abs[func-48];
7626 8153667c Nathan Froyd
        } else {
7627 8153667c Nathan Froyd
            gen_cmp_ps(ctx, func-48, ft, fs, cc);
7628 8153667c Nathan Froyd
            opn = condnames[func-48];
7629 5a1e8ffb ths
        }
7630 6ea83fed bellard
        break;
7631 5a5012ec ths
    default:
7632 923617a3 ths
        MIPS_INVAL(opn);
7633 e397ee33 ths
        generate_exception (ctx, EXCP_RI);
7634 6ea83fed bellard
        return;
7635 6ea83fed bellard
    }
7636 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
7637 5a1e8ffb ths
    switch (optype) {
7638 5a1e8ffb ths
    case BINOP:
7639 6ea83fed bellard
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7640 5a1e8ffb ths
        break;
7641 5a1e8ffb ths
    case CMPOP:
7642 5a1e8ffb ths
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7643 5a1e8ffb ths
        break;
7644 5a1e8ffb ths
    default:
7645 6ea83fed bellard
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7646 5a1e8ffb ths
        break;
7647 5a1e8ffb ths
    }
7648 6ea83fed bellard
}
7649 6af0bf9c bellard
7650 5a5012ec ths
/* Coprocessor 3 (FPU) */
7651 5e755519 ths
static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7652 5e755519 ths
                           int fd, int fs, int base, int index)
7653 7a387fff ths
{
7654 923617a3 ths
    const char *opn = "extended float load/store";
7655 93b12ccc ths
    int store = 0;
7656 4e2474d6 aurel32
    TCGv t0 = tcg_temp_new();
7657 7a387fff ths
7658 93b12ccc ths
    if (base == 0) {
7659 6c5c1e20 ths
        gen_load_gpr(t0, index);
7660 93b12ccc ths
    } else if (index == 0) {
7661 6c5c1e20 ths
        gen_load_gpr(t0, base);
7662 93b12ccc ths
    } else {
7663 e9203484 aurel32
        gen_load_gpr(t0, index);
7664 941694d0 Aurelien Jarno
        gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
7665 93b12ccc ths
    }
7666 5a5012ec ths
    /* Don't do NOP if destination is zero: we must perform the actual
7667 ead9360e ths
       memory access. */
7668 4e2474d6 aurel32
    save_cpu_state(ctx, 0);
7669 5a5012ec ths
    switch (opc) {
7670 5a5012ec ths
    case OPC_LWXC1:
7671 8c0ab41f aurel32
        check_cop1x(ctx);
7672 b6d96bed ths
        {
7673 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7674 b6d96bed ths
7675 585c88d5 aurel32
            tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7676 585c88d5 aurel32
            tcg_gen_trunc_tl_i32(fp0, t0);
7677 b6d96bed ths
            gen_store_fpr32(fp0, fd);
7678 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7679 b6d96bed ths
        }
7680 5a5012ec ths
        opn = "lwxc1";
7681 5a5012ec ths
        break;
7682 5a5012ec ths
    case OPC_LDXC1:
7683 8c0ab41f aurel32
        check_cop1x(ctx);
7684 8c0ab41f aurel32
        check_cp1_registers(ctx, fd);
7685 b6d96bed ths
        {
7686 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7687 b6d96bed ths
7688 b6d96bed ths
            tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7689 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7690 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7691 b6d96bed ths
        }
7692 5a5012ec ths
        opn = "ldxc1";
7693 5a5012ec ths
        break;
7694 5a5012ec ths
    case OPC_LUXC1:
7695 8c0ab41f aurel32
        check_cp1_64bitmode(ctx);
7696 6c5c1e20 ths
        tcg_gen_andi_tl(t0, t0, ~0x7);
7697 b6d96bed ths
        {
7698 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7699 b6d96bed ths
7700 b6d96bed ths
            tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7701 b6d96bed ths
            gen_store_fpr64(ctx, fp0, fd);
7702 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7703 b6d96bed ths
        }
7704 5a5012ec ths
        opn = "luxc1";
7705 5a5012ec ths
        break;
7706 5a5012ec ths
    case OPC_SWXC1:
7707 8c0ab41f aurel32
        check_cop1x(ctx);
7708 b6d96bed ths
        {
7709 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7710 585c88d5 aurel32
            TCGv t1 = tcg_temp_new();
7711 b6d96bed ths
7712 b6d96bed ths
            gen_load_fpr32(fp0, fs);
7713 a7812ae4 pbrook
            tcg_gen_extu_i32_tl(t1, fp0);
7714 a7812ae4 pbrook
            tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7715 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7716 a6035857 aurel32
            tcg_temp_free(t1);
7717 b6d96bed ths
        }
7718 5a5012ec ths
        opn = "swxc1";
7719 93b12ccc ths
        store = 1;
7720 5a5012ec ths
        break;
7721 5a5012ec ths
    case OPC_SDXC1:
7722 8c0ab41f aurel32
        check_cop1x(ctx);
7723 8c0ab41f aurel32
        check_cp1_registers(ctx, fs);
7724 b6d96bed ths
        {
7725 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7726 b6d96bed ths
7727 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7728 b6d96bed ths
            tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7729 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7730 b6d96bed ths
        }
7731 5a5012ec ths
        opn = "sdxc1";
7732 93b12ccc ths
        store = 1;
7733 5a5012ec ths
        break;
7734 5a5012ec ths
    case OPC_SUXC1:
7735 8c0ab41f aurel32
        check_cp1_64bitmode(ctx);
7736 6c5c1e20 ths
        tcg_gen_andi_tl(t0, t0, ~0x7);
7737 b6d96bed ths
        {
7738 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7739 b6d96bed ths
7740 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7741 b6d96bed ths
            tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7742 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7743 b6d96bed ths
        }
7744 5a5012ec ths
        opn = "suxc1";
7745 93b12ccc ths
        store = 1;
7746 5a5012ec ths
        break;
7747 5a5012ec ths
    }
7748 6c5c1e20 ths
    tcg_temp_free(t0);
7749 2abf314d Blue Swirl
    (void)opn; (void)store; /* avoid compiler warnings */
7750 93b12ccc ths
    MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7751 93b12ccc ths
               regnames[index], regnames[base]);
7752 5a5012ec ths
}
7753 5a5012ec ths
7754 5e755519 ths
static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7755 5e755519 ths
                            int fd, int fr, int fs, int ft)
7756 5a5012ec ths
{
7757 923617a3 ths
    const char *opn = "flt3_arith";
7758 5a5012ec ths
7759 5a5012ec ths
    switch (opc) {
7760 5a5012ec ths
    case OPC_ALNV_PS:
7761 b8aa4598 ths
        check_cp1_64bitmode(ctx);
7762 a16336e4 ths
        {
7763 a7812ae4 pbrook
            TCGv t0 = tcg_temp_local_new();
7764 c905fdac aurel32
            TCGv_i32 fp = tcg_temp_new_i32();
7765 c905fdac aurel32
            TCGv_i32 fph = tcg_temp_new_i32();
7766 a16336e4 ths
            int l1 = gen_new_label();
7767 a16336e4 ths
            int l2 = gen_new_label();
7768 a16336e4 ths
7769 6c5c1e20 ths
            gen_load_gpr(t0, fr);
7770 6c5c1e20 ths
            tcg_gen_andi_tl(t0, t0, 0x7);
7771 6c5c1e20 ths
7772 6c5c1e20 ths
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7773 c905fdac aurel32
            gen_load_fpr32(fp, fs);
7774 c905fdac aurel32
            gen_load_fpr32h(fph, fs);
7775 c905fdac aurel32
            gen_store_fpr32(fp, fd);
7776 c905fdac aurel32
            gen_store_fpr32h(fph, fd);
7777 a16336e4 ths
            tcg_gen_br(l2);
7778 a16336e4 ths
            gen_set_label(l1);
7779 6c5c1e20 ths
            tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7780 6c5c1e20 ths
            tcg_temp_free(t0);
7781 a16336e4 ths
#ifdef TARGET_WORDS_BIGENDIAN
7782 c905fdac aurel32
            gen_load_fpr32(fp, fs);
7783 c905fdac aurel32
            gen_load_fpr32h(fph, ft);
7784 c905fdac aurel32
            gen_store_fpr32h(fp, fd);
7785 c905fdac aurel32
            gen_store_fpr32(fph, fd);
7786 a16336e4 ths
#else
7787 c905fdac aurel32
            gen_load_fpr32h(fph, fs);
7788 c905fdac aurel32
            gen_load_fpr32(fp, ft);
7789 c905fdac aurel32
            gen_store_fpr32(fph, fd);
7790 c905fdac aurel32
            gen_store_fpr32h(fp, fd);
7791 a16336e4 ths
#endif
7792 a16336e4 ths
            gen_set_label(l2);
7793 c905fdac aurel32
            tcg_temp_free_i32(fp);
7794 c905fdac aurel32
            tcg_temp_free_i32(fph);
7795 a16336e4 ths
        }
7796 5a5012ec ths
        opn = "alnv.ps";
7797 5a5012ec ths
        break;
7798 5a5012ec ths
    case OPC_MADD_S:
7799 b8aa4598 ths
        check_cop1x(ctx);
7800 b6d96bed ths
        {
7801 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7802 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
7803 a7812ae4 pbrook
            TCGv_i32 fp2 = tcg_temp_new_i32();
7804 b6d96bed ths
7805 b6d96bed ths
            gen_load_fpr32(fp0, fs);
7806 b6d96bed ths
            gen_load_fpr32(fp1, ft);
7807 b6d96bed ths
            gen_load_fpr32(fp2, fr);
7808 a7812ae4 pbrook
            gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7809 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7810 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
7811 b6d96bed ths
            gen_store_fpr32(fp2, fd);
7812 a7812ae4 pbrook
            tcg_temp_free_i32(fp2);
7813 b6d96bed ths
        }
7814 5a5012ec ths
        opn = "madd.s";
7815 5a5012ec ths
        break;
7816 5a5012ec ths
    case OPC_MADD_D:
7817 b8aa4598 ths
        check_cop1x(ctx);
7818 b8aa4598 ths
        check_cp1_registers(ctx, fd | fs | ft | fr);
7819 b6d96bed ths
        {
7820 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7821 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7822 a7812ae4 pbrook
            TCGv_i64 fp2 = tcg_temp_new_i64();
7823 b6d96bed ths
7824 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7825 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7826 b6d96bed ths
            gen_load_fpr64(ctx, fp2, fr);
7827 a7812ae4 pbrook
            gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7828 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7829 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7830 b6d96bed ths
            gen_store_fpr64(ctx, fp2, fd);
7831 a7812ae4 pbrook
            tcg_temp_free_i64(fp2);
7832 b6d96bed ths
        }
7833 5a5012ec ths
        opn = "madd.d";
7834 5a5012ec ths
        break;
7835 5a5012ec ths
    case OPC_MADD_PS:
7836 b8aa4598 ths
        check_cp1_64bitmode(ctx);
7837 b6d96bed ths
        {
7838 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7839 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7840 a7812ae4 pbrook
            TCGv_i64 fp2 = tcg_temp_new_i64();
7841 b6d96bed ths
7842 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7843 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7844 b6d96bed ths
            gen_load_fpr64(ctx, fp2, fr);
7845 a7812ae4 pbrook
            gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7846 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7847 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7848 b6d96bed ths
            gen_store_fpr64(ctx, fp2, fd);
7849 a7812ae4 pbrook
            tcg_temp_free_i64(fp2);
7850 b6d96bed ths
        }
7851 5a5012ec ths
        opn = "madd.ps";
7852 5a5012ec ths
        break;
7853 5a5012ec ths
    case OPC_MSUB_S:
7854 b8aa4598 ths
        check_cop1x(ctx);
7855 b6d96bed ths
        {
7856 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7857 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
7858 a7812ae4 pbrook
            TCGv_i32 fp2 = tcg_temp_new_i32();
7859 b6d96bed ths
7860 b6d96bed ths
            gen_load_fpr32(fp0, fs);
7861 b6d96bed ths
            gen_load_fpr32(fp1, ft);
7862 b6d96bed ths
            gen_load_fpr32(fp2, fr);
7863 a7812ae4 pbrook
            gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7864 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7865 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
7866 b6d96bed ths
            gen_store_fpr32(fp2, fd);
7867 a7812ae4 pbrook
            tcg_temp_free_i32(fp2);
7868 b6d96bed ths
        }
7869 5a5012ec ths
        opn = "msub.s";
7870 5a5012ec ths
        break;
7871 5a5012ec ths
    case OPC_MSUB_D:
7872 b8aa4598 ths
        check_cop1x(ctx);
7873 b8aa4598 ths
        check_cp1_registers(ctx, fd | fs | ft | fr);
7874 b6d96bed ths
        {
7875 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7876 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7877 a7812ae4 pbrook
            TCGv_i64 fp2 = tcg_temp_new_i64();
7878 b6d96bed ths
7879 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7880 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7881 b6d96bed ths
            gen_load_fpr64(ctx, fp2, fr);
7882 a7812ae4 pbrook
            gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7883 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7884 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7885 b6d96bed ths
            gen_store_fpr64(ctx, fp2, fd);
7886 a7812ae4 pbrook
            tcg_temp_free_i64(fp2);
7887 b6d96bed ths
        }
7888 5a5012ec ths
        opn = "msub.d";
7889 5a5012ec ths
        break;
7890 5a5012ec ths
    case OPC_MSUB_PS:
7891 b8aa4598 ths
        check_cp1_64bitmode(ctx);
7892 b6d96bed ths
        {
7893 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7894 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7895 a7812ae4 pbrook
            TCGv_i64 fp2 = tcg_temp_new_i64();
7896 b6d96bed ths
7897 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7898 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7899 b6d96bed ths
            gen_load_fpr64(ctx, fp2, fr);
7900 a7812ae4 pbrook
            gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7901 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7902 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7903 b6d96bed ths
            gen_store_fpr64(ctx, fp2, fd);
7904 a7812ae4 pbrook
            tcg_temp_free_i64(fp2);
7905 b6d96bed ths
        }
7906 5a5012ec ths
        opn = "msub.ps";
7907 5a5012ec ths
        break;
7908 5a5012ec ths
    case OPC_NMADD_S:
7909 b8aa4598 ths
        check_cop1x(ctx);
7910 b6d96bed ths
        {
7911 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7912 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
7913 a7812ae4 pbrook
            TCGv_i32 fp2 = tcg_temp_new_i32();
7914 b6d96bed ths
7915 b6d96bed ths
            gen_load_fpr32(fp0, fs);
7916 b6d96bed ths
            gen_load_fpr32(fp1, ft);
7917 b6d96bed ths
            gen_load_fpr32(fp2, fr);
7918 a7812ae4 pbrook
            gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7919 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7920 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
7921 b6d96bed ths
            gen_store_fpr32(fp2, fd);
7922 a7812ae4 pbrook
            tcg_temp_free_i32(fp2);
7923 b6d96bed ths
        }
7924 5a5012ec ths
        opn = "nmadd.s";
7925 5a5012ec ths
        break;
7926 5a5012ec ths
    case OPC_NMADD_D:
7927 b8aa4598 ths
        check_cop1x(ctx);
7928 b8aa4598 ths
        check_cp1_registers(ctx, fd | fs | ft | fr);
7929 b6d96bed ths
        {
7930 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7931 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7932 a7812ae4 pbrook
            TCGv_i64 fp2 = tcg_temp_new_i64();
7933 b6d96bed ths
7934 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7935 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7936 b6d96bed ths
            gen_load_fpr64(ctx, fp2, fr);
7937 a7812ae4 pbrook
            gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7938 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7939 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7940 b6d96bed ths
            gen_store_fpr64(ctx, fp2, fd);
7941 a7812ae4 pbrook
            tcg_temp_free_i64(fp2);
7942 b6d96bed ths
        }
7943 5a5012ec ths
        opn = "nmadd.d";
7944 5a5012ec ths
        break;
7945 5a5012ec ths
    case OPC_NMADD_PS:
7946 b8aa4598 ths
        check_cp1_64bitmode(ctx);
7947 b6d96bed ths
        {
7948 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7949 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7950 a7812ae4 pbrook
            TCGv_i64 fp2 = tcg_temp_new_i64();
7951 b6d96bed ths
7952 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7953 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7954 b6d96bed ths
            gen_load_fpr64(ctx, fp2, fr);
7955 a7812ae4 pbrook
            gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7956 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7957 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7958 b6d96bed ths
            gen_store_fpr64(ctx, fp2, fd);
7959 a7812ae4 pbrook
            tcg_temp_free_i64(fp2);
7960 b6d96bed ths
        }
7961 5a5012ec ths
        opn = "nmadd.ps";
7962 5a5012ec ths
        break;
7963 5a5012ec ths
    case OPC_NMSUB_S:
7964 b8aa4598 ths
        check_cop1x(ctx);
7965 b6d96bed ths
        {
7966 a7812ae4 pbrook
            TCGv_i32 fp0 = tcg_temp_new_i32();
7967 a7812ae4 pbrook
            TCGv_i32 fp1 = tcg_temp_new_i32();
7968 a7812ae4 pbrook
            TCGv_i32 fp2 = tcg_temp_new_i32();
7969 b6d96bed ths
7970 b6d96bed ths
            gen_load_fpr32(fp0, fs);
7971 b6d96bed ths
            gen_load_fpr32(fp1, ft);
7972 b6d96bed ths
            gen_load_fpr32(fp2, fr);
7973 a7812ae4 pbrook
            gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7974 a7812ae4 pbrook
            tcg_temp_free_i32(fp0);
7975 a7812ae4 pbrook
            tcg_temp_free_i32(fp1);
7976 b6d96bed ths
            gen_store_fpr32(fp2, fd);
7977 a7812ae4 pbrook
            tcg_temp_free_i32(fp2);
7978 b6d96bed ths
        }
7979 5a5012ec ths
        opn = "nmsub.s";
7980 5a5012ec ths
        break;
7981 5a5012ec ths
    case OPC_NMSUB_D:
7982 b8aa4598 ths
        check_cop1x(ctx);
7983 b8aa4598 ths
        check_cp1_registers(ctx, fd | fs | ft | fr);
7984 b6d96bed ths
        {
7985 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
7986 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
7987 a7812ae4 pbrook
            TCGv_i64 fp2 = tcg_temp_new_i64();
7988 b6d96bed ths
7989 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
7990 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
7991 b6d96bed ths
            gen_load_fpr64(ctx, fp2, fr);
7992 a7812ae4 pbrook
            gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7993 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
7994 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
7995 b6d96bed ths
            gen_store_fpr64(ctx, fp2, fd);
7996 a7812ae4 pbrook
            tcg_temp_free_i64(fp2);
7997 b6d96bed ths
        }
7998 5a5012ec ths
        opn = "nmsub.d";
7999 5a5012ec ths
        break;
8000 5a5012ec ths
    case OPC_NMSUB_PS:
8001 b8aa4598 ths
        check_cp1_64bitmode(ctx);
8002 b6d96bed ths
        {
8003 a7812ae4 pbrook
            TCGv_i64 fp0 = tcg_temp_new_i64();
8004 a7812ae4 pbrook
            TCGv_i64 fp1 = tcg_temp_new_i64();
8005 a7812ae4 pbrook
            TCGv_i64 fp2 = tcg_temp_new_i64();
8006 b6d96bed ths
8007 b6d96bed ths
            gen_load_fpr64(ctx, fp0, fs);
8008 b6d96bed ths
            gen_load_fpr64(ctx, fp1, ft);
8009 b6d96bed ths
            gen_load_fpr64(ctx, fp2, fr);
8010 a7812ae4 pbrook
            gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
8011 a7812ae4 pbrook
            tcg_temp_free_i64(fp0);
8012 a7812ae4 pbrook
            tcg_temp_free_i64(fp1);
8013 b6d96bed ths
            gen_store_fpr64(ctx, fp2, fd);
8014 a7812ae4 pbrook
            tcg_temp_free_i64(fp2);
8015 b6d96bed ths
        }
8016 5a5012ec ths
        opn = "nmsub.ps";
8017 5a5012ec ths
        break;
8018 923617a3 ths
    default:
8019 923617a3 ths
        MIPS_INVAL(opn);
8020 5a5012ec ths
        generate_exception (ctx, EXCP_RI);
8021 5a5012ec ths
        return;
8022 5a5012ec ths
    }
8023 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
8024 5a5012ec ths
    MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8025 5a5012ec ths
               fregnames[fs], fregnames[ft]);
8026 7a387fff ths
}
8027 7a387fff ths
8028 26ebe468 Nathan Froyd
static void
8029 26ebe468 Nathan Froyd
gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
8030 26ebe468 Nathan Froyd
{
8031 26ebe468 Nathan Froyd
    TCGv t0;
8032 26ebe468 Nathan Froyd
8033 26ebe468 Nathan Froyd
    check_insn(env, ctx, ISA_MIPS32R2);
8034 26ebe468 Nathan Froyd
    t0 = tcg_temp_new();
8035 26ebe468 Nathan Froyd
8036 26ebe468 Nathan Froyd
    switch (rd) {
8037 26ebe468 Nathan Froyd
    case 0:
8038 26ebe468 Nathan Froyd
        save_cpu_state(ctx, 1);
8039 26ebe468 Nathan Froyd
        gen_helper_rdhwr_cpunum(t0);
8040 26ebe468 Nathan Froyd
        gen_store_gpr(t0, rt);
8041 26ebe468 Nathan Froyd
        break;
8042 26ebe468 Nathan Froyd
    case 1:
8043 26ebe468 Nathan Froyd
        save_cpu_state(ctx, 1);
8044 26ebe468 Nathan Froyd
        gen_helper_rdhwr_synci_step(t0);
8045 26ebe468 Nathan Froyd
        gen_store_gpr(t0, rt);
8046 26ebe468 Nathan Froyd
        break;
8047 26ebe468 Nathan Froyd
    case 2:
8048 26ebe468 Nathan Froyd
        save_cpu_state(ctx, 1);
8049 26ebe468 Nathan Froyd
        gen_helper_rdhwr_cc(t0);
8050 26ebe468 Nathan Froyd
        gen_store_gpr(t0, rt);
8051 26ebe468 Nathan Froyd
        break;
8052 26ebe468 Nathan Froyd
    case 3:
8053 26ebe468 Nathan Froyd
        save_cpu_state(ctx, 1);
8054 26ebe468 Nathan Froyd
        gen_helper_rdhwr_ccres(t0);
8055 26ebe468 Nathan Froyd
        gen_store_gpr(t0, rt);
8056 26ebe468 Nathan Froyd
        break;
8057 26ebe468 Nathan Froyd
    case 29:
8058 26ebe468 Nathan Froyd
#if defined(CONFIG_USER_ONLY)
8059 26ebe468 Nathan Froyd
        tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
8060 26ebe468 Nathan Froyd
        gen_store_gpr(t0, rt);
8061 26ebe468 Nathan Froyd
        break;
8062 26ebe468 Nathan Froyd
#else
8063 26ebe468 Nathan Froyd
        /* XXX: Some CPUs implement this in hardware.
8064 26ebe468 Nathan Froyd
           Not supported yet. */
8065 26ebe468 Nathan Froyd
#endif
8066 26ebe468 Nathan Froyd
    default:            /* Invalid */
8067 26ebe468 Nathan Froyd
        MIPS_INVAL("rdhwr");
8068 26ebe468 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
8069 26ebe468 Nathan Froyd
        break;
8070 26ebe468 Nathan Froyd
    }
8071 26ebe468 Nathan Froyd
    tcg_temp_free(t0);
8072 26ebe468 Nathan Froyd
}
8073 26ebe468 Nathan Froyd
8074 c9602061 Nathan Froyd
static void handle_delay_slot (CPUState *env, DisasContext *ctx,
8075 c9602061 Nathan Froyd
                               int insn_bytes)
8076 c9602061 Nathan Froyd
{
8077 c9602061 Nathan Froyd
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
8078 364d4831 Nathan Froyd
        int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8079 c9602061 Nathan Froyd
        /* Branches completion */
8080 c9602061 Nathan Froyd
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
8081 c9602061 Nathan Froyd
        ctx->bstate = BS_BRANCH;
8082 c9602061 Nathan Froyd
        save_cpu_state(ctx, 0);
8083 c9602061 Nathan Froyd
        /* FIXME: Need to clear can_do_io.  */
8084 364d4831 Nathan Froyd
        switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
8085 c9602061 Nathan Froyd
        case MIPS_HFLAG_B:
8086 c9602061 Nathan Froyd
            /* unconditional branch */
8087 c9602061 Nathan Froyd
            MIPS_DEBUG("unconditional branch");
8088 364d4831 Nathan Froyd
            if (proc_hflags & MIPS_HFLAG_BX) {
8089 364d4831 Nathan Froyd
                tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8090 364d4831 Nathan Froyd
            }
8091 c9602061 Nathan Froyd
            gen_goto_tb(ctx, 0, ctx->btarget);
8092 c9602061 Nathan Froyd
            break;
8093 c9602061 Nathan Froyd
        case MIPS_HFLAG_BL:
8094 c9602061 Nathan Froyd
            /* blikely taken case */
8095 c9602061 Nathan Froyd
            MIPS_DEBUG("blikely branch taken");
8096 c9602061 Nathan Froyd
            gen_goto_tb(ctx, 0, ctx->btarget);
8097 c9602061 Nathan Froyd
            break;
8098 c9602061 Nathan Froyd
        case MIPS_HFLAG_BC:
8099 c9602061 Nathan Froyd
            /* Conditional branch */
8100 c9602061 Nathan Froyd
            MIPS_DEBUG("conditional branch");
8101 c9602061 Nathan Froyd
            {
8102 c9602061 Nathan Froyd
                int l1 = gen_new_label();
8103 c9602061 Nathan Froyd
8104 c9602061 Nathan Froyd
                tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8105 c9602061 Nathan Froyd
                gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8106 c9602061 Nathan Froyd
                gen_set_label(l1);
8107 c9602061 Nathan Froyd
                gen_goto_tb(ctx, 0, ctx->btarget);
8108 c9602061 Nathan Froyd
            }
8109 c9602061 Nathan Froyd
            break;
8110 c9602061 Nathan Froyd
        case MIPS_HFLAG_BR:
8111 c9602061 Nathan Froyd
            /* unconditional branch to register */
8112 c9602061 Nathan Froyd
            MIPS_DEBUG("branch to register");
8113 3c824109 Nathan Froyd
            if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
8114 364d4831 Nathan Froyd
                TCGv t0 = tcg_temp_new();
8115 364d4831 Nathan Froyd
                TCGv_i32 t1 = tcg_temp_new_i32();
8116 364d4831 Nathan Froyd
8117 364d4831 Nathan Froyd
                tcg_gen_andi_tl(t0, btarget, 0x1);
8118 364d4831 Nathan Froyd
                tcg_gen_trunc_tl_i32(t1, t0);
8119 364d4831 Nathan Froyd
                tcg_temp_free(t0);
8120 364d4831 Nathan Froyd
                tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8121 364d4831 Nathan Froyd
                tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8122 364d4831 Nathan Froyd
                tcg_gen_or_i32(hflags, hflags, t1);
8123 364d4831 Nathan Froyd
                tcg_temp_free_i32(t1);
8124 364d4831 Nathan Froyd
8125 364d4831 Nathan Froyd
                tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8126 364d4831 Nathan Froyd
            } else {
8127 364d4831 Nathan Froyd
                tcg_gen_mov_tl(cpu_PC, btarget);
8128 364d4831 Nathan Froyd
            }
8129 c9602061 Nathan Froyd
            if (ctx->singlestep_enabled) {
8130 c9602061 Nathan Froyd
                save_cpu_state(ctx, 0);
8131 c9602061 Nathan Froyd
                gen_helper_0i(raise_exception, EXCP_DEBUG);
8132 c9602061 Nathan Froyd
            }
8133 c9602061 Nathan Froyd
            tcg_gen_exit_tb(0);
8134 c9602061 Nathan Froyd
            break;
8135 c9602061 Nathan Froyd
        default:
8136 c9602061 Nathan Froyd
            MIPS_DEBUG("unknown branch");
8137 c9602061 Nathan Froyd
            break;
8138 c9602061 Nathan Froyd
        }
8139 c9602061 Nathan Froyd
    }
8140 c9602061 Nathan Froyd
}
8141 c9602061 Nathan Froyd
8142 7a387fff ths
/* ISA extensions (ASEs) */
8143 6af0bf9c bellard
/* MIPS16 extension to MIPS32 */
8144 6ea219d0 Nathan Froyd
8145 6ea219d0 Nathan Froyd
/* MIPS16 major opcodes */
8146 6ea219d0 Nathan Froyd
enum {
8147 6ea219d0 Nathan Froyd
  M16_OPC_ADDIUSP = 0x00,
8148 6ea219d0 Nathan Froyd
  M16_OPC_ADDIUPC = 0x01,
8149 6ea219d0 Nathan Froyd
  M16_OPC_B = 0x02,
8150 6ea219d0 Nathan Froyd
  M16_OPC_JAL = 0x03,
8151 6ea219d0 Nathan Froyd
  M16_OPC_BEQZ = 0x04,
8152 6ea219d0 Nathan Froyd
  M16_OPC_BNEQZ = 0x05,
8153 6ea219d0 Nathan Froyd
  M16_OPC_SHIFT = 0x06,
8154 6ea219d0 Nathan Froyd
  M16_OPC_LD = 0x07,
8155 6ea219d0 Nathan Froyd
  M16_OPC_RRIA = 0x08,
8156 6ea219d0 Nathan Froyd
  M16_OPC_ADDIU8 = 0x09,
8157 6ea219d0 Nathan Froyd
  M16_OPC_SLTI = 0x0a,
8158 6ea219d0 Nathan Froyd
  M16_OPC_SLTIU = 0x0b,
8159 6ea219d0 Nathan Froyd
  M16_OPC_I8 = 0x0c,
8160 6ea219d0 Nathan Froyd
  M16_OPC_LI = 0x0d,
8161 6ea219d0 Nathan Froyd
  M16_OPC_CMPI = 0x0e,
8162 6ea219d0 Nathan Froyd
  M16_OPC_SD = 0x0f,
8163 6ea219d0 Nathan Froyd
  M16_OPC_LB = 0x10,
8164 6ea219d0 Nathan Froyd
  M16_OPC_LH = 0x11,
8165 6ea219d0 Nathan Froyd
  M16_OPC_LWSP = 0x12,
8166 6ea219d0 Nathan Froyd
  M16_OPC_LW = 0x13,
8167 6ea219d0 Nathan Froyd
  M16_OPC_LBU = 0x14,
8168 6ea219d0 Nathan Froyd
  M16_OPC_LHU = 0x15,
8169 6ea219d0 Nathan Froyd
  M16_OPC_LWPC = 0x16,
8170 6ea219d0 Nathan Froyd
  M16_OPC_LWU = 0x17,
8171 6ea219d0 Nathan Froyd
  M16_OPC_SB = 0x18,
8172 6ea219d0 Nathan Froyd
  M16_OPC_SH = 0x19,
8173 6ea219d0 Nathan Froyd
  M16_OPC_SWSP = 0x1a,
8174 6ea219d0 Nathan Froyd
  M16_OPC_SW = 0x1b,
8175 6ea219d0 Nathan Froyd
  M16_OPC_RRR = 0x1c,
8176 6ea219d0 Nathan Froyd
  M16_OPC_RR = 0x1d,
8177 6ea219d0 Nathan Froyd
  M16_OPC_EXTEND = 0x1e,
8178 6ea219d0 Nathan Froyd
  M16_OPC_I64 = 0x1f
8179 6ea219d0 Nathan Froyd
};
8180 6ea219d0 Nathan Froyd
8181 6ea219d0 Nathan Froyd
/* I8 funct field */
8182 6ea219d0 Nathan Froyd
enum {
8183 6ea219d0 Nathan Froyd
  I8_BTEQZ = 0x0,
8184 6ea219d0 Nathan Froyd
  I8_BTNEZ = 0x1,
8185 6ea219d0 Nathan Froyd
  I8_SWRASP = 0x2,
8186 6ea219d0 Nathan Froyd
  I8_ADJSP = 0x3,
8187 6ea219d0 Nathan Froyd
  I8_SVRS = 0x4,
8188 6ea219d0 Nathan Froyd
  I8_MOV32R = 0x5,
8189 6ea219d0 Nathan Froyd
  I8_MOVR32 = 0x7
8190 6ea219d0 Nathan Froyd
};
8191 6ea219d0 Nathan Froyd
8192 6ea219d0 Nathan Froyd
/* RRR f field */
8193 6ea219d0 Nathan Froyd
enum {
8194 6ea219d0 Nathan Froyd
  RRR_DADDU = 0x0,
8195 6ea219d0 Nathan Froyd
  RRR_ADDU = 0x1,
8196 6ea219d0 Nathan Froyd
  RRR_DSUBU = 0x2,
8197 6ea219d0 Nathan Froyd
  RRR_SUBU = 0x3
8198 6ea219d0 Nathan Froyd
};
8199 6ea219d0 Nathan Froyd
8200 6ea219d0 Nathan Froyd
/* RR funct field */
8201 6ea219d0 Nathan Froyd
enum {
8202 6ea219d0 Nathan Froyd
  RR_JR = 0x00,
8203 6ea219d0 Nathan Froyd
  RR_SDBBP = 0x01,
8204 6ea219d0 Nathan Froyd
  RR_SLT = 0x02,
8205 6ea219d0 Nathan Froyd
  RR_SLTU = 0x03,
8206 6ea219d0 Nathan Froyd
  RR_SLLV = 0x04,
8207 6ea219d0 Nathan Froyd
  RR_BREAK = 0x05,
8208 6ea219d0 Nathan Froyd
  RR_SRLV = 0x06,
8209 6ea219d0 Nathan Froyd
  RR_SRAV = 0x07,
8210 6ea219d0 Nathan Froyd
  RR_DSRL = 0x08,
8211 6ea219d0 Nathan Froyd
  RR_CMP = 0x0a,
8212 6ea219d0 Nathan Froyd
  RR_NEG = 0x0b,
8213 6ea219d0 Nathan Froyd
  RR_AND = 0x0c,
8214 6ea219d0 Nathan Froyd
  RR_OR = 0x0d,
8215 6ea219d0 Nathan Froyd
  RR_XOR = 0x0e,
8216 6ea219d0 Nathan Froyd
  RR_NOT = 0x0f,
8217 6ea219d0 Nathan Froyd
  RR_MFHI = 0x10,
8218 6ea219d0 Nathan Froyd
  RR_CNVT = 0x11,
8219 6ea219d0 Nathan Froyd
  RR_MFLO = 0x12,
8220 6ea219d0 Nathan Froyd
  RR_DSRA = 0x13,
8221 6ea219d0 Nathan Froyd
  RR_DSLLV = 0x14,
8222 6ea219d0 Nathan Froyd
  RR_DSRLV = 0x16,
8223 6ea219d0 Nathan Froyd
  RR_DSRAV = 0x17,
8224 6ea219d0 Nathan Froyd
  RR_MULT = 0x18,
8225 6ea219d0 Nathan Froyd
  RR_MULTU = 0x19,
8226 6ea219d0 Nathan Froyd
  RR_DIV = 0x1a,
8227 6ea219d0 Nathan Froyd
  RR_DIVU = 0x1b,
8228 6ea219d0 Nathan Froyd
  RR_DMULT = 0x1c,
8229 6ea219d0 Nathan Froyd
  RR_DMULTU = 0x1d,
8230 6ea219d0 Nathan Froyd
  RR_DDIV = 0x1e,
8231 6ea219d0 Nathan Froyd
  RR_DDIVU = 0x1f
8232 6ea219d0 Nathan Froyd
};
8233 6ea219d0 Nathan Froyd
8234 6ea219d0 Nathan Froyd
/* I64 funct field */
8235 6ea219d0 Nathan Froyd
enum {
8236 6ea219d0 Nathan Froyd
  I64_LDSP = 0x0,
8237 6ea219d0 Nathan Froyd
  I64_SDSP = 0x1,
8238 6ea219d0 Nathan Froyd
  I64_SDRASP = 0x2,
8239 6ea219d0 Nathan Froyd
  I64_DADJSP = 0x3,
8240 6ea219d0 Nathan Froyd
  I64_LDPC = 0x4,
8241 364d4831 Nathan Froyd
  I64_DADDIU5 = 0x5,
8242 6ea219d0 Nathan Froyd
  I64_DADDIUPC = 0x6,
8243 6ea219d0 Nathan Froyd
  I64_DADDIUSP = 0x7
8244 6ea219d0 Nathan Froyd
};
8245 6ea219d0 Nathan Froyd
8246 6ea219d0 Nathan Froyd
/* RR ry field for CNVT */
8247 6ea219d0 Nathan Froyd
enum {
8248 6ea219d0 Nathan Froyd
  RR_RY_CNVT_ZEB = 0x0,
8249 6ea219d0 Nathan Froyd
  RR_RY_CNVT_ZEH = 0x1,
8250 6ea219d0 Nathan Froyd
  RR_RY_CNVT_ZEW = 0x2,
8251 6ea219d0 Nathan Froyd
  RR_RY_CNVT_SEB = 0x4,
8252 6ea219d0 Nathan Froyd
  RR_RY_CNVT_SEH = 0x5,
8253 6ea219d0 Nathan Froyd
  RR_RY_CNVT_SEW = 0x6,
8254 6ea219d0 Nathan Froyd
};
8255 6ea219d0 Nathan Froyd
8256 364d4831 Nathan Froyd
static int xlat (int r)
8257 364d4831 Nathan Froyd
{
8258 364d4831 Nathan Froyd
  static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8259 364d4831 Nathan Froyd
8260 364d4831 Nathan Froyd
  return map[r];
8261 364d4831 Nathan Froyd
}
8262 364d4831 Nathan Froyd
8263 364d4831 Nathan Froyd
static void gen_mips16_save (DisasContext *ctx,
8264 364d4831 Nathan Froyd
                             int xsregs, int aregs,
8265 364d4831 Nathan Froyd
                             int do_ra, int do_s0, int do_s1,
8266 364d4831 Nathan Froyd
                             int framesize)
8267 364d4831 Nathan Froyd
{
8268 364d4831 Nathan Froyd
    TCGv t0 = tcg_temp_new();
8269 364d4831 Nathan Froyd
    TCGv t1 = tcg_temp_new();
8270 364d4831 Nathan Froyd
    int args, astatic;
8271 364d4831 Nathan Froyd
8272 364d4831 Nathan Froyd
    switch (aregs) {
8273 364d4831 Nathan Froyd
    case 0:
8274 364d4831 Nathan Froyd
    case 1:
8275 364d4831 Nathan Froyd
    case 2:
8276 364d4831 Nathan Froyd
    case 3:
8277 364d4831 Nathan Froyd
    case 11:
8278 364d4831 Nathan Froyd
        args = 0;
8279 364d4831 Nathan Froyd
        break;
8280 364d4831 Nathan Froyd
    case 4:
8281 364d4831 Nathan Froyd
    case 5:
8282 364d4831 Nathan Froyd
    case 6:
8283 364d4831 Nathan Froyd
    case 7:
8284 364d4831 Nathan Froyd
        args = 1;
8285 364d4831 Nathan Froyd
        break;
8286 364d4831 Nathan Froyd
    case 8:
8287 364d4831 Nathan Froyd
    case 9:
8288 364d4831 Nathan Froyd
    case 10:
8289 364d4831 Nathan Froyd
        args = 2;
8290 364d4831 Nathan Froyd
        break;
8291 364d4831 Nathan Froyd
    case 12:
8292 364d4831 Nathan Froyd
    case 13:
8293 364d4831 Nathan Froyd
        args = 3;
8294 364d4831 Nathan Froyd
        break;
8295 364d4831 Nathan Froyd
    case 14:
8296 364d4831 Nathan Froyd
        args = 4;
8297 364d4831 Nathan Froyd
        break;
8298 364d4831 Nathan Froyd
    default:
8299 364d4831 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
8300 364d4831 Nathan Froyd
        return;
8301 364d4831 Nathan Froyd
    }
8302 364d4831 Nathan Froyd
8303 364d4831 Nathan Froyd
    switch (args) {
8304 364d4831 Nathan Froyd
    case 4:
8305 364d4831 Nathan Froyd
        gen_base_offset_addr(ctx, t0, 29, 12);
8306 364d4831 Nathan Froyd
        gen_load_gpr(t1, 7);
8307 5c13fdfd Aurelien Jarno
        op_st_sw(t1, t0, ctx);
8308 364d4831 Nathan Froyd
        /* Fall through */
8309 364d4831 Nathan Froyd
    case 3:
8310 364d4831 Nathan Froyd
        gen_base_offset_addr(ctx, t0, 29, 8);
8311 364d4831 Nathan Froyd
        gen_load_gpr(t1, 6);
8312 5c13fdfd Aurelien Jarno
        op_st_sw(t1, t0, ctx);
8313 364d4831 Nathan Froyd
        /* Fall through */
8314 364d4831 Nathan Froyd
    case 2:
8315 364d4831 Nathan Froyd
        gen_base_offset_addr(ctx, t0, 29, 4);
8316 364d4831 Nathan Froyd
        gen_load_gpr(t1, 5);
8317 5c13fdfd Aurelien Jarno
        op_st_sw(t1, t0, ctx);
8318 364d4831 Nathan Froyd
        /* Fall through */
8319 364d4831 Nathan Froyd
    case 1:
8320 364d4831 Nathan Froyd
        gen_base_offset_addr(ctx, t0, 29, 0);
8321 364d4831 Nathan Froyd
        gen_load_gpr(t1, 4);
8322 5c13fdfd Aurelien Jarno
        op_st_sw(t1, t0, ctx);
8323 364d4831 Nathan Froyd
    }
8324 364d4831 Nathan Froyd
8325 364d4831 Nathan Froyd
    gen_load_gpr(t0, 29);
8326 364d4831 Nathan Froyd
8327 364d4831 Nathan Froyd
#define DECR_AND_STORE(reg) do {                \
8328 364d4831 Nathan Froyd
        tcg_gen_subi_tl(t0, t0, 4);             \
8329 364d4831 Nathan Froyd
        gen_load_gpr(t1, reg);                  \
8330 5c13fdfd Aurelien Jarno
        op_st_sw(t1, t0, ctx);                  \
8331 364d4831 Nathan Froyd
    } while (0)
8332 364d4831 Nathan Froyd
8333 364d4831 Nathan Froyd
    if (do_ra) {
8334 364d4831 Nathan Froyd
        DECR_AND_STORE(31);
8335 364d4831 Nathan Froyd
    }
8336 364d4831 Nathan Froyd
8337 364d4831 Nathan Froyd
    switch (xsregs) {
8338 364d4831 Nathan Froyd
    case 7:
8339 364d4831 Nathan Froyd
        DECR_AND_STORE(30);
8340 364d4831 Nathan Froyd
        /* Fall through */
8341 364d4831 Nathan Froyd
    case 6:
8342 364d4831 Nathan Froyd
        DECR_AND_STORE(23);
8343 364d4831 Nathan Froyd
        /* Fall through */
8344 364d4831 Nathan Froyd
    case 5:
8345 364d4831 Nathan Froyd
        DECR_AND_STORE(22);
8346 364d4831 Nathan Froyd
        /* Fall through */
8347 364d4831 Nathan Froyd
    case 4:
8348 364d4831 Nathan Froyd
        DECR_AND_STORE(21);
8349 364d4831 Nathan Froyd
        /* Fall through */
8350 364d4831 Nathan Froyd
    case 3:
8351 364d4831 Nathan Froyd
        DECR_AND_STORE(20);
8352 364d4831 Nathan Froyd
        /* Fall through */
8353 364d4831 Nathan Froyd
    case 2:
8354 364d4831 Nathan Froyd
        DECR_AND_STORE(19);
8355 364d4831 Nathan Froyd
        /* Fall through */
8356 364d4831 Nathan Froyd
    case 1:
8357 364d4831 Nathan Froyd
        DECR_AND_STORE(18);
8358 364d4831 Nathan Froyd
    }
8359 364d4831 Nathan Froyd
8360 364d4831 Nathan Froyd
    if (do_s1) {
8361 364d4831 Nathan Froyd
        DECR_AND_STORE(17);
8362 364d4831 Nathan Froyd
    }
8363 364d4831 Nathan Froyd
    if (do_s0) {
8364 364d4831 Nathan Froyd
        DECR_AND_STORE(16);
8365 364d4831 Nathan Froyd
    }
8366 364d4831 Nathan Froyd
8367 364d4831 Nathan Froyd
    switch (aregs) {
8368 364d4831 Nathan Froyd
    case 0:
8369 364d4831 Nathan Froyd
    case 4:
8370 364d4831 Nathan Froyd
    case 8:
8371 364d4831 Nathan Froyd
    case 12:
8372 364d4831 Nathan Froyd
    case 14:
8373 364d4831 Nathan Froyd
        astatic = 0;
8374 364d4831 Nathan Froyd
        break;
8375 364d4831 Nathan Froyd
    case 1:
8376 364d4831 Nathan Froyd
    case 5:
8377 364d4831 Nathan Froyd
    case 9:
8378 364d4831 Nathan Froyd
    case 13:
8379 364d4831 Nathan Froyd
        astatic = 1;
8380 364d4831 Nathan Froyd
        break;
8381 364d4831 Nathan Froyd
    case 2:
8382 364d4831 Nathan Froyd
    case 6:
8383 364d4831 Nathan Froyd
    case 10:
8384 364d4831 Nathan Froyd
        astatic = 2;
8385 364d4831 Nathan Froyd
        break;
8386 364d4831 Nathan Froyd
    case 3:
8387 364d4831 Nathan Froyd
    case 7:
8388 364d4831 Nathan Froyd
        astatic = 3;
8389 364d4831 Nathan Froyd
        break;
8390 364d4831 Nathan Froyd
    case 11:
8391 364d4831 Nathan Froyd
        astatic = 4;
8392 364d4831 Nathan Froyd
        break;
8393 364d4831 Nathan Froyd
    default:
8394 364d4831 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
8395 364d4831 Nathan Froyd
        return;
8396 364d4831 Nathan Froyd
    }
8397 364d4831 Nathan Froyd
8398 364d4831 Nathan Froyd
    if (astatic > 0) {
8399 364d4831 Nathan Froyd
        DECR_AND_STORE(7);
8400 364d4831 Nathan Froyd
        if (astatic > 1) {
8401 364d4831 Nathan Froyd
            DECR_AND_STORE(6);
8402 364d4831 Nathan Froyd
            if (astatic > 2) {
8403 364d4831 Nathan Froyd
                DECR_AND_STORE(5);
8404 364d4831 Nathan Froyd
                if (astatic > 3) {
8405 364d4831 Nathan Froyd
                    DECR_AND_STORE(4);
8406 364d4831 Nathan Froyd
                }
8407 364d4831 Nathan Froyd
            }
8408 364d4831 Nathan Froyd
        }
8409 364d4831 Nathan Froyd
    }
8410 364d4831 Nathan Froyd
#undef DECR_AND_STORE
8411 364d4831 Nathan Froyd
8412 364d4831 Nathan Froyd
    tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8413 364d4831 Nathan Froyd
    tcg_temp_free(t0);
8414 364d4831 Nathan Froyd
    tcg_temp_free(t1);
8415 364d4831 Nathan Froyd
}
8416 364d4831 Nathan Froyd
8417 364d4831 Nathan Froyd
static void gen_mips16_restore (DisasContext *ctx,
8418 364d4831 Nathan Froyd
                                int xsregs, int aregs,
8419 364d4831 Nathan Froyd
                                int do_ra, int do_s0, int do_s1,
8420 364d4831 Nathan Froyd
                                int framesize)
8421 364d4831 Nathan Froyd
{
8422 364d4831 Nathan Froyd
    int astatic;
8423 364d4831 Nathan Froyd
    TCGv t0 = tcg_temp_new();
8424 364d4831 Nathan Froyd
    TCGv t1 = tcg_temp_new();
8425 364d4831 Nathan Froyd
8426 364d4831 Nathan Froyd
    tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8427 364d4831 Nathan Froyd
8428 364d4831 Nathan Froyd
#define DECR_AND_LOAD(reg) do {                 \
8429 364d4831 Nathan Froyd
        tcg_gen_subi_tl(t0, t0, 4);             \
8430 5c13fdfd Aurelien Jarno
        op_ld_lw(t1, t0, ctx);                  \
8431 364d4831 Nathan Froyd
        gen_store_gpr(t1, reg);                 \
8432 364d4831 Nathan Froyd
    } while (0)
8433 364d4831 Nathan Froyd
8434 364d4831 Nathan Froyd
    if (do_ra) {
8435 364d4831 Nathan Froyd
        DECR_AND_LOAD(31);
8436 364d4831 Nathan Froyd
    }
8437 364d4831 Nathan Froyd
8438 364d4831 Nathan Froyd
    switch (xsregs) {
8439 364d4831 Nathan Froyd
    case 7:
8440 364d4831 Nathan Froyd
        DECR_AND_LOAD(30);
8441 364d4831 Nathan Froyd
        /* Fall through */
8442 364d4831 Nathan Froyd
    case 6:
8443 364d4831 Nathan Froyd
        DECR_AND_LOAD(23);
8444 364d4831 Nathan Froyd
        /* Fall through */
8445 364d4831 Nathan Froyd
    case 5:
8446 364d4831 Nathan Froyd
        DECR_AND_LOAD(22);
8447 364d4831 Nathan Froyd
        /* Fall through */
8448 364d4831 Nathan Froyd
    case 4:
8449 364d4831 Nathan Froyd
        DECR_AND_LOAD(21);
8450 364d4831 Nathan Froyd
        /* Fall through */
8451 364d4831 Nathan Froyd
    case 3:
8452 364d4831 Nathan Froyd
        DECR_AND_LOAD(20);
8453 364d4831 Nathan Froyd
        /* Fall through */
8454 364d4831 Nathan Froyd
    case 2:
8455 364d4831 Nathan Froyd
        DECR_AND_LOAD(19);
8456 364d4831 Nathan Froyd
        /* Fall through */
8457 364d4831 Nathan Froyd
    case 1:
8458 364d4831 Nathan Froyd
        DECR_AND_LOAD(18);
8459 364d4831 Nathan Froyd
    }
8460 364d4831 Nathan Froyd
8461 364d4831 Nathan Froyd
    if (do_s1) {
8462 364d4831 Nathan Froyd
        DECR_AND_LOAD(17);
8463 364d4831 Nathan Froyd
    }
8464 364d4831 Nathan Froyd
    if (do_s0) {
8465 364d4831 Nathan Froyd
        DECR_AND_LOAD(16);
8466 364d4831 Nathan Froyd
    }
8467 364d4831 Nathan Froyd
8468 364d4831 Nathan Froyd
    switch (aregs) {
8469 364d4831 Nathan Froyd
    case 0:
8470 364d4831 Nathan Froyd
    case 4:
8471 364d4831 Nathan Froyd
    case 8:
8472 364d4831 Nathan Froyd
    case 12:
8473 364d4831 Nathan Froyd
    case 14:
8474 364d4831 Nathan Froyd
        astatic = 0;
8475 364d4831 Nathan Froyd
        break;
8476 364d4831 Nathan Froyd
    case 1:
8477 364d4831 Nathan Froyd
    case 5:
8478 364d4831 Nathan Froyd
    case 9:
8479 364d4831 Nathan Froyd
    case 13:
8480 364d4831 Nathan Froyd
        astatic = 1;
8481 364d4831 Nathan Froyd
        break;
8482 364d4831 Nathan Froyd
    case 2:
8483 364d4831 Nathan Froyd
    case 6:
8484 364d4831 Nathan Froyd
    case 10:
8485 364d4831 Nathan Froyd
        astatic = 2;
8486 364d4831 Nathan Froyd
        break;
8487 364d4831 Nathan Froyd
    case 3:
8488 364d4831 Nathan Froyd
    case 7:
8489 364d4831 Nathan Froyd
        astatic = 3;
8490 364d4831 Nathan Froyd
        break;
8491 364d4831 Nathan Froyd
    case 11:
8492 364d4831 Nathan Froyd
        astatic = 4;
8493 364d4831 Nathan Froyd
        break;
8494 364d4831 Nathan Froyd
    default:
8495 364d4831 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
8496 364d4831 Nathan Froyd
        return;
8497 364d4831 Nathan Froyd
    }
8498 364d4831 Nathan Froyd
8499 364d4831 Nathan Froyd
    if (astatic > 0) {
8500 364d4831 Nathan Froyd
        DECR_AND_LOAD(7);
8501 364d4831 Nathan Froyd
        if (astatic > 1) {
8502 364d4831 Nathan Froyd
            DECR_AND_LOAD(6);
8503 364d4831 Nathan Froyd
            if (astatic > 2) {
8504 364d4831 Nathan Froyd
                DECR_AND_LOAD(5);
8505 364d4831 Nathan Froyd
                if (astatic > 3) {
8506 364d4831 Nathan Froyd
                    DECR_AND_LOAD(4);
8507 364d4831 Nathan Froyd
                }
8508 364d4831 Nathan Froyd
            }
8509 364d4831 Nathan Froyd
        }
8510 364d4831 Nathan Froyd
    }
8511 364d4831 Nathan Froyd
#undef DECR_AND_LOAD
8512 364d4831 Nathan Froyd
8513 364d4831 Nathan Froyd
    tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8514 364d4831 Nathan Froyd
    tcg_temp_free(t0);
8515 364d4831 Nathan Froyd
    tcg_temp_free(t1);
8516 364d4831 Nathan Froyd
}
8517 364d4831 Nathan Froyd
8518 364d4831 Nathan Froyd
static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8519 364d4831 Nathan Froyd
                         int is_64_bit, int extended)
8520 364d4831 Nathan Froyd
{
8521 364d4831 Nathan Froyd
    TCGv t0;
8522 364d4831 Nathan Froyd
8523 364d4831 Nathan Froyd
    if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8524 364d4831 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
8525 364d4831 Nathan Froyd
        return;
8526 364d4831 Nathan Froyd
    }
8527 364d4831 Nathan Froyd
8528 364d4831 Nathan Froyd
    t0 = tcg_temp_new();
8529 364d4831 Nathan Froyd
8530 364d4831 Nathan Froyd
    tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8531 364d4831 Nathan Froyd
    tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8532 364d4831 Nathan Froyd
    if (!is_64_bit) {
8533 364d4831 Nathan Froyd
        tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8534 364d4831 Nathan Froyd
    }
8535 364d4831 Nathan Froyd
8536 364d4831 Nathan Froyd
    tcg_temp_free(t0);
8537 364d4831 Nathan Froyd
}
8538 364d4831 Nathan Froyd
8539 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
8540 364d4831 Nathan Froyd
static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
8541 364d4831 Nathan Froyd
                               int ry, int funct, int16_t offset,
8542 364d4831 Nathan Froyd
                               int extended)
8543 364d4831 Nathan Froyd
{
8544 364d4831 Nathan Froyd
    switch (funct) {
8545 364d4831 Nathan Froyd
    case I64_LDSP:
8546 364d4831 Nathan Froyd
        check_mips_64(ctx);
8547 364d4831 Nathan Froyd
        offset = extended ? offset : offset << 3;
8548 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LD, ry, 29, offset);
8549 364d4831 Nathan Froyd
        break;
8550 364d4831 Nathan Froyd
    case I64_SDSP:
8551 364d4831 Nathan Froyd
        check_mips_64(ctx);
8552 364d4831 Nathan Froyd
        offset = extended ? offset : offset << 3;
8553 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SD, ry, 29, offset);
8554 364d4831 Nathan Froyd
        break;
8555 364d4831 Nathan Froyd
    case I64_SDRASP:
8556 364d4831 Nathan Froyd
        check_mips_64(ctx);
8557 364d4831 Nathan Froyd
        offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8558 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SD, 31, 29, offset);
8559 364d4831 Nathan Froyd
        break;
8560 364d4831 Nathan Froyd
    case I64_DADJSP:
8561 364d4831 Nathan Froyd
        check_mips_64(ctx);
8562 364d4831 Nathan Froyd
        offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8563 364d4831 Nathan Froyd
        gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8564 364d4831 Nathan Froyd
        break;
8565 364d4831 Nathan Froyd
    case I64_LDPC:
8566 364d4831 Nathan Froyd
        if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8567 364d4831 Nathan Froyd
            generate_exception(ctx, EXCP_RI);
8568 364d4831 Nathan Froyd
        } else {
8569 364d4831 Nathan Froyd
            offset = extended ? offset : offset << 3;
8570 afa88c3a Aurelien Jarno
            gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
8571 364d4831 Nathan Froyd
        }
8572 364d4831 Nathan Froyd
        break;
8573 364d4831 Nathan Froyd
    case I64_DADDIU5:
8574 364d4831 Nathan Froyd
        check_mips_64(ctx);
8575 364d4831 Nathan Froyd
        offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8576 364d4831 Nathan Froyd
        gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8577 364d4831 Nathan Froyd
        break;
8578 364d4831 Nathan Froyd
    case I64_DADDIUPC:
8579 364d4831 Nathan Froyd
        check_mips_64(ctx);
8580 364d4831 Nathan Froyd
        offset = extended ? offset : offset << 2;
8581 364d4831 Nathan Froyd
        gen_addiupc(ctx, ry, offset, 1, extended);
8582 364d4831 Nathan Froyd
        break;
8583 364d4831 Nathan Froyd
    case I64_DADDIUSP:
8584 364d4831 Nathan Froyd
        check_mips_64(ctx);
8585 364d4831 Nathan Froyd
        offset = extended ? offset : offset << 2;
8586 364d4831 Nathan Froyd
        gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8587 364d4831 Nathan Froyd
        break;
8588 364d4831 Nathan Froyd
    }
8589 364d4831 Nathan Froyd
}
8590 364d4831 Nathan Froyd
#endif
8591 364d4831 Nathan Froyd
8592 364d4831 Nathan Froyd
static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8593 364d4831 Nathan Froyd
                                       int *is_branch)
8594 364d4831 Nathan Froyd
{
8595 364d4831 Nathan Froyd
    int extend = lduw_code(ctx->pc + 2);
8596 364d4831 Nathan Froyd
    int op, rx, ry, funct, sa;
8597 364d4831 Nathan Froyd
    int16_t imm, offset;
8598 364d4831 Nathan Froyd
8599 364d4831 Nathan Froyd
    ctx->opcode = (ctx->opcode << 16) | extend;
8600 364d4831 Nathan Froyd
    op = (ctx->opcode >> 11) & 0x1f;
8601 364d4831 Nathan Froyd
    sa = (ctx->opcode >> 22) & 0x1f;
8602 364d4831 Nathan Froyd
    funct = (ctx->opcode >> 8) & 0x7;
8603 364d4831 Nathan Froyd
    rx = xlat((ctx->opcode >> 8) & 0x7);
8604 364d4831 Nathan Froyd
    ry = xlat((ctx->opcode >> 5) & 0x7);
8605 364d4831 Nathan Froyd
    offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8606 364d4831 Nathan Froyd
                              | ((ctx->opcode >> 21) & 0x3f) << 5
8607 364d4831 Nathan Froyd
                              | (ctx->opcode & 0x1f));
8608 364d4831 Nathan Froyd
8609 364d4831 Nathan Froyd
    /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8610 364d4831 Nathan Froyd
       counterparts.  */
8611 364d4831 Nathan Froyd
    switch (op) {
8612 364d4831 Nathan Froyd
    case M16_OPC_ADDIUSP:
8613 364d4831 Nathan Froyd
        gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8614 364d4831 Nathan Froyd
        break;
8615 364d4831 Nathan Froyd
    case M16_OPC_ADDIUPC:
8616 364d4831 Nathan Froyd
        gen_addiupc(ctx, rx, imm, 0, 1);
8617 364d4831 Nathan Froyd
        break;
8618 364d4831 Nathan Froyd
    case M16_OPC_B:
8619 364d4831 Nathan Froyd
        gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8620 364d4831 Nathan Froyd
        /* No delay slot, so just process as a normal instruction */
8621 364d4831 Nathan Froyd
        break;
8622 364d4831 Nathan Froyd
    case M16_OPC_BEQZ:
8623 364d4831 Nathan Froyd
        gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8624 364d4831 Nathan Froyd
        /* No delay slot, so just process as a normal instruction */
8625 364d4831 Nathan Froyd
        break;
8626 364d4831 Nathan Froyd
    case M16_OPC_BNEQZ:
8627 364d4831 Nathan Froyd
        gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8628 364d4831 Nathan Froyd
        /* No delay slot, so just process as a normal instruction */
8629 364d4831 Nathan Froyd
        break;
8630 364d4831 Nathan Froyd
    case M16_OPC_SHIFT:
8631 364d4831 Nathan Froyd
        switch (ctx->opcode & 0x3) {
8632 364d4831 Nathan Froyd
        case 0x0:
8633 364d4831 Nathan Froyd
            gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8634 364d4831 Nathan Froyd
            break;
8635 364d4831 Nathan Froyd
        case 0x1:
8636 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
8637 364d4831 Nathan Froyd
            check_mips_64(ctx);
8638 364d4831 Nathan Froyd
            gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8639 364d4831 Nathan Froyd
#else
8640 364d4831 Nathan Froyd
            generate_exception(ctx, EXCP_RI);
8641 364d4831 Nathan Froyd
#endif
8642 364d4831 Nathan Froyd
            break;
8643 364d4831 Nathan Froyd
        case 0x2:
8644 364d4831 Nathan Froyd
            gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8645 364d4831 Nathan Froyd
            break;
8646 364d4831 Nathan Froyd
        case 0x3:
8647 364d4831 Nathan Froyd
            gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8648 364d4831 Nathan Froyd
            break;
8649 364d4831 Nathan Froyd
        }
8650 364d4831 Nathan Froyd
        break;
8651 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
8652 364d4831 Nathan Froyd
    case M16_OPC_LD:
8653 364d4831 Nathan Froyd
            check_mips_64(ctx);
8654 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LD, ry, rx, offset);
8655 364d4831 Nathan Froyd
        break;
8656 364d4831 Nathan Froyd
#endif
8657 364d4831 Nathan Froyd
    case M16_OPC_RRIA:
8658 364d4831 Nathan Froyd
        imm = ctx->opcode & 0xf;
8659 364d4831 Nathan Froyd
        imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8660 364d4831 Nathan Froyd
        imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8661 364d4831 Nathan Froyd
        imm = (int16_t) (imm << 1) >> 1;
8662 364d4831 Nathan Froyd
        if ((ctx->opcode >> 4) & 0x1) {
8663 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
8664 364d4831 Nathan Froyd
            check_mips_64(ctx);
8665 364d4831 Nathan Froyd
            gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8666 364d4831 Nathan Froyd
#else
8667 364d4831 Nathan Froyd
            generate_exception(ctx, EXCP_RI);
8668 364d4831 Nathan Froyd
#endif
8669 364d4831 Nathan Froyd
        } else {
8670 364d4831 Nathan Froyd
            gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8671 364d4831 Nathan Froyd
        }
8672 364d4831 Nathan Froyd
        break;
8673 364d4831 Nathan Froyd
    case M16_OPC_ADDIU8:
8674 364d4831 Nathan Froyd
        gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8675 364d4831 Nathan Froyd
        break;
8676 364d4831 Nathan Froyd
    case M16_OPC_SLTI:
8677 364d4831 Nathan Froyd
        gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8678 364d4831 Nathan Froyd
        break;
8679 364d4831 Nathan Froyd
    case M16_OPC_SLTIU:
8680 364d4831 Nathan Froyd
        gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8681 364d4831 Nathan Froyd
        break;
8682 364d4831 Nathan Froyd
    case M16_OPC_I8:
8683 364d4831 Nathan Froyd
        switch (funct) {
8684 364d4831 Nathan Froyd
        case I8_BTEQZ:
8685 364d4831 Nathan Froyd
            gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8686 364d4831 Nathan Froyd
            break;
8687 364d4831 Nathan Froyd
        case I8_BTNEZ:
8688 364d4831 Nathan Froyd
            gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8689 364d4831 Nathan Froyd
            break;
8690 364d4831 Nathan Froyd
        case I8_SWRASP:
8691 5c13fdfd Aurelien Jarno
            gen_st(ctx, OPC_SW, 31, 29, imm);
8692 364d4831 Nathan Froyd
            break;
8693 364d4831 Nathan Froyd
        case I8_ADJSP:
8694 364d4831 Nathan Froyd
            gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8695 364d4831 Nathan Froyd
            break;
8696 364d4831 Nathan Froyd
        case I8_SVRS:
8697 364d4831 Nathan Froyd
            {
8698 364d4831 Nathan Froyd
                int xsregs = (ctx->opcode >> 24) & 0x7;
8699 364d4831 Nathan Froyd
                int aregs = (ctx->opcode >> 16) & 0xf;
8700 364d4831 Nathan Froyd
                int do_ra = (ctx->opcode >> 6) & 0x1;
8701 364d4831 Nathan Froyd
                int do_s0 = (ctx->opcode >> 5) & 0x1;
8702 364d4831 Nathan Froyd
                int do_s1 = (ctx->opcode >> 4) & 0x1;
8703 364d4831 Nathan Froyd
                int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8704 364d4831 Nathan Froyd
                                 | (ctx->opcode & 0xf)) << 3;
8705 364d4831 Nathan Froyd
8706 364d4831 Nathan Froyd
                if (ctx->opcode & (1 << 7)) {
8707 364d4831 Nathan Froyd
                    gen_mips16_save(ctx, xsregs, aregs,
8708 364d4831 Nathan Froyd
                                    do_ra, do_s0, do_s1,
8709 364d4831 Nathan Froyd
                                    framesize);
8710 364d4831 Nathan Froyd
                } else {
8711 364d4831 Nathan Froyd
                    gen_mips16_restore(ctx, xsregs, aregs,
8712 364d4831 Nathan Froyd
                                       do_ra, do_s0, do_s1,
8713 364d4831 Nathan Froyd
                                       framesize);
8714 364d4831 Nathan Froyd
                }
8715 364d4831 Nathan Froyd
            }
8716 364d4831 Nathan Froyd
            break;
8717 364d4831 Nathan Froyd
        default:
8718 364d4831 Nathan Froyd
            generate_exception(ctx, EXCP_RI);
8719 364d4831 Nathan Froyd
            break;
8720 364d4831 Nathan Froyd
        }
8721 364d4831 Nathan Froyd
        break;
8722 364d4831 Nathan Froyd
    case M16_OPC_LI:
8723 364d4831 Nathan Froyd
        tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8724 364d4831 Nathan Froyd
        break;
8725 364d4831 Nathan Froyd
    case M16_OPC_CMPI:
8726 364d4831 Nathan Froyd
        tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8727 364d4831 Nathan Froyd
        break;
8728 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
8729 364d4831 Nathan Froyd
    case M16_OPC_SD:
8730 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SD, ry, rx, offset);
8731 364d4831 Nathan Froyd
        break;
8732 364d4831 Nathan Froyd
#endif
8733 364d4831 Nathan Froyd
    case M16_OPC_LB:
8734 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8735 364d4831 Nathan Froyd
        break;
8736 364d4831 Nathan Froyd
    case M16_OPC_LH:
8737 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LH, ry, rx, offset);
8738 364d4831 Nathan Froyd
        break;
8739 364d4831 Nathan Froyd
    case M16_OPC_LWSP:
8740 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LW, rx, 29, offset);
8741 364d4831 Nathan Froyd
        break;
8742 364d4831 Nathan Froyd
    case M16_OPC_LW:
8743 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LW, ry, rx, offset);
8744 364d4831 Nathan Froyd
        break;
8745 364d4831 Nathan Froyd
    case M16_OPC_LBU:
8746 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
8747 364d4831 Nathan Froyd
        break;
8748 364d4831 Nathan Froyd
    case M16_OPC_LHU:
8749 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
8750 364d4831 Nathan Froyd
        break;
8751 364d4831 Nathan Froyd
    case M16_OPC_LWPC:
8752 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
8753 364d4831 Nathan Froyd
        break;
8754 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
8755 364d4831 Nathan Froyd
    case M16_OPC_LWU:
8756 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
8757 364d4831 Nathan Froyd
        break;
8758 364d4831 Nathan Froyd
#endif
8759 364d4831 Nathan Froyd
    case M16_OPC_SB:
8760 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SB, ry, rx, offset);
8761 364d4831 Nathan Froyd
        break;
8762 364d4831 Nathan Froyd
    case M16_OPC_SH:
8763 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SH, ry, rx, offset);
8764 364d4831 Nathan Froyd
        break;
8765 364d4831 Nathan Froyd
    case M16_OPC_SWSP:
8766 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SW, rx, 29, offset);
8767 364d4831 Nathan Froyd
        break;
8768 364d4831 Nathan Froyd
    case M16_OPC_SW:
8769 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SW, ry, rx, offset);
8770 364d4831 Nathan Froyd
        break;
8771 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
8772 364d4831 Nathan Froyd
    case M16_OPC_I64:
8773 364d4831 Nathan Froyd
        decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8774 364d4831 Nathan Froyd
        break;
8775 364d4831 Nathan Froyd
#endif
8776 364d4831 Nathan Froyd
    default:
8777 364d4831 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
8778 364d4831 Nathan Froyd
        break;
8779 364d4831 Nathan Froyd
    }
8780 364d4831 Nathan Froyd
8781 364d4831 Nathan Froyd
    return 4;
8782 364d4831 Nathan Froyd
}
8783 364d4831 Nathan Froyd
8784 364d4831 Nathan Froyd
static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8785 364d4831 Nathan Froyd
                              int *is_branch)
8786 364d4831 Nathan Froyd
{
8787 364d4831 Nathan Froyd
    int rx, ry;
8788 364d4831 Nathan Froyd
    int sa;
8789 364d4831 Nathan Froyd
    int op, cnvt_op, op1, offset;
8790 364d4831 Nathan Froyd
    int funct;
8791 364d4831 Nathan Froyd
    int n_bytes;
8792 364d4831 Nathan Froyd
8793 364d4831 Nathan Froyd
    op = (ctx->opcode >> 11) & 0x1f;
8794 364d4831 Nathan Froyd
    sa = (ctx->opcode >> 2) & 0x7;
8795 364d4831 Nathan Froyd
    sa = sa == 0 ? 8 : sa;
8796 364d4831 Nathan Froyd
    rx = xlat((ctx->opcode >> 8) & 0x7);
8797 364d4831 Nathan Froyd
    cnvt_op = (ctx->opcode >> 5) & 0x7;
8798 364d4831 Nathan Froyd
    ry = xlat((ctx->opcode >> 5) & 0x7);
8799 364d4831 Nathan Froyd
    op1 = offset = ctx->opcode & 0x1f;
8800 364d4831 Nathan Froyd
8801 364d4831 Nathan Froyd
    n_bytes = 2;
8802 364d4831 Nathan Froyd
8803 364d4831 Nathan Froyd
    switch (op) {
8804 364d4831 Nathan Froyd
    case M16_OPC_ADDIUSP:
8805 364d4831 Nathan Froyd
        {
8806 364d4831 Nathan Froyd
            int16_t imm = ((uint8_t) ctx->opcode) << 2;
8807 364d4831 Nathan Froyd
8808 364d4831 Nathan Froyd
            gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8809 364d4831 Nathan Froyd
        }
8810 364d4831 Nathan Froyd
        break;
8811 364d4831 Nathan Froyd
    case M16_OPC_ADDIUPC:
8812 364d4831 Nathan Froyd
        gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8813 364d4831 Nathan Froyd
        break;
8814 364d4831 Nathan Froyd
    case M16_OPC_B:
8815 364d4831 Nathan Froyd
        offset = (ctx->opcode & 0x7ff) << 1;
8816 364d4831 Nathan Froyd
        offset = (int16_t)(offset << 4) >> 4;
8817 364d4831 Nathan Froyd
        gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8818 364d4831 Nathan Froyd
        /* No delay slot, so just process as a normal instruction */
8819 364d4831 Nathan Froyd
        break;
8820 364d4831 Nathan Froyd
    case M16_OPC_JAL:
8821 364d4831 Nathan Froyd
        offset = lduw_code(ctx->pc + 2);
8822 364d4831 Nathan Froyd
        offset = (((ctx->opcode & 0x1f) << 21)
8823 364d4831 Nathan Froyd
                  | ((ctx->opcode >> 5) & 0x1f) << 16
8824 364d4831 Nathan Froyd
                  | offset) << 2;
8825 620e48f6 Nathan Froyd
        op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
8826 364d4831 Nathan Froyd
        gen_compute_branch(ctx, op, 4, rx, ry, offset);
8827 364d4831 Nathan Froyd
        n_bytes = 4;
8828 364d4831 Nathan Froyd
        *is_branch = 1;
8829 364d4831 Nathan Froyd
        break;
8830 364d4831 Nathan Froyd
    case M16_OPC_BEQZ:
8831 364d4831 Nathan Froyd
        gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8832 364d4831 Nathan Froyd
        /* No delay slot, so just process as a normal instruction */
8833 364d4831 Nathan Froyd
        break;
8834 364d4831 Nathan Froyd
    case M16_OPC_BNEQZ:
8835 364d4831 Nathan Froyd
        gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8836 364d4831 Nathan Froyd
        /* No delay slot, so just process as a normal instruction */
8837 364d4831 Nathan Froyd
        break;
8838 364d4831 Nathan Froyd
    case M16_OPC_SHIFT:
8839 364d4831 Nathan Froyd
        switch (ctx->opcode & 0x3) {
8840 364d4831 Nathan Froyd
        case 0x0:
8841 364d4831 Nathan Froyd
            gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8842 364d4831 Nathan Froyd
            break;
8843 364d4831 Nathan Froyd
        case 0x1:
8844 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
8845 364d4831 Nathan Froyd
            check_mips_64(ctx);
8846 364d4831 Nathan Froyd
            gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8847 364d4831 Nathan Froyd
#else
8848 364d4831 Nathan Froyd
            generate_exception(ctx, EXCP_RI);
8849 364d4831 Nathan Froyd
#endif
8850 364d4831 Nathan Froyd
            break;
8851 364d4831 Nathan Froyd
        case 0x2:
8852 364d4831 Nathan Froyd
            gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8853 364d4831 Nathan Froyd
            break;
8854 364d4831 Nathan Froyd
        case 0x3:
8855 364d4831 Nathan Froyd
            gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8856 364d4831 Nathan Froyd
            break;
8857 364d4831 Nathan Froyd
        }
8858 364d4831 Nathan Froyd
        break;
8859 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
8860 364d4831 Nathan Froyd
    case M16_OPC_LD:
8861 364d4831 Nathan Froyd
        check_mips_64(ctx);
8862 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
8863 364d4831 Nathan Froyd
        break;
8864 364d4831 Nathan Froyd
#endif
8865 364d4831 Nathan Froyd
    case M16_OPC_RRIA:
8866 364d4831 Nathan Froyd
        {
8867 364d4831 Nathan Froyd
            int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8868 364d4831 Nathan Froyd
8869 364d4831 Nathan Froyd
            if ((ctx->opcode >> 4) & 1) {
8870 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
8871 364d4831 Nathan Froyd
                check_mips_64(ctx);
8872 364d4831 Nathan Froyd
                gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8873 364d4831 Nathan Froyd
#else
8874 364d4831 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
8875 364d4831 Nathan Froyd
#endif
8876 364d4831 Nathan Froyd
            } else {
8877 364d4831 Nathan Froyd
                gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8878 364d4831 Nathan Froyd
            }
8879 364d4831 Nathan Froyd
        }
8880 364d4831 Nathan Froyd
        break;
8881 364d4831 Nathan Froyd
    case M16_OPC_ADDIU8:
8882 364d4831 Nathan Froyd
        {
8883 364d4831 Nathan Froyd
            int16_t imm = (int8_t) ctx->opcode;
8884 364d4831 Nathan Froyd
8885 364d4831 Nathan Froyd
            gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8886 364d4831 Nathan Froyd
        }
8887 364d4831 Nathan Froyd
        break;
8888 364d4831 Nathan Froyd
    case M16_OPC_SLTI:
8889 364d4831 Nathan Froyd
        {
8890 364d4831 Nathan Froyd
            int16_t imm = (uint8_t) ctx->opcode;
8891 364d4831 Nathan Froyd
8892 364d4831 Nathan Froyd
            gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8893 364d4831 Nathan Froyd
        }
8894 364d4831 Nathan Froyd
        break;
8895 364d4831 Nathan Froyd
    case M16_OPC_SLTIU:
8896 364d4831 Nathan Froyd
        {
8897 364d4831 Nathan Froyd
            int16_t imm = (uint8_t) ctx->opcode;
8898 364d4831 Nathan Froyd
8899 364d4831 Nathan Froyd
            gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8900 364d4831 Nathan Froyd
        }
8901 364d4831 Nathan Froyd
        break;
8902 364d4831 Nathan Froyd
    case M16_OPC_I8:
8903 364d4831 Nathan Froyd
        {
8904 364d4831 Nathan Froyd
            int reg32;
8905 364d4831 Nathan Froyd
8906 364d4831 Nathan Froyd
            funct = (ctx->opcode >> 8) & 0x7;
8907 364d4831 Nathan Froyd
            switch (funct) {
8908 364d4831 Nathan Froyd
            case I8_BTEQZ:
8909 364d4831 Nathan Froyd
                gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8910 364d4831 Nathan Froyd
                                   ((int8_t)ctx->opcode) << 1);
8911 364d4831 Nathan Froyd
                break;
8912 364d4831 Nathan Froyd
            case I8_BTNEZ:
8913 364d4831 Nathan Froyd
                gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8914 364d4831 Nathan Froyd
                                   ((int8_t)ctx->opcode) << 1);
8915 364d4831 Nathan Froyd
                break;
8916 364d4831 Nathan Froyd
            case I8_SWRASP:
8917 5c13fdfd Aurelien Jarno
                gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
8918 364d4831 Nathan Froyd
                break;
8919 364d4831 Nathan Froyd
            case I8_ADJSP:
8920 364d4831 Nathan Froyd
                gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
8921 364d4831 Nathan Froyd
                              ((int8_t)ctx->opcode) << 3);
8922 364d4831 Nathan Froyd
                break;
8923 364d4831 Nathan Froyd
            case I8_SVRS:
8924 364d4831 Nathan Froyd
                {
8925 364d4831 Nathan Froyd
                    int do_ra = ctx->opcode & (1 << 6);
8926 364d4831 Nathan Froyd
                    int do_s0 = ctx->opcode & (1 << 5);
8927 364d4831 Nathan Froyd
                    int do_s1 = ctx->opcode & (1 << 4);
8928 364d4831 Nathan Froyd
                    int framesize = ctx->opcode & 0xf;
8929 364d4831 Nathan Froyd
8930 364d4831 Nathan Froyd
                    if (framesize == 0) {
8931 364d4831 Nathan Froyd
                        framesize = 128;
8932 364d4831 Nathan Froyd
                    } else {
8933 364d4831 Nathan Froyd
                        framesize = framesize << 3;
8934 364d4831 Nathan Froyd
                    }
8935 364d4831 Nathan Froyd
8936 364d4831 Nathan Froyd
                    if (ctx->opcode & (1 << 7)) {
8937 364d4831 Nathan Froyd
                        gen_mips16_save(ctx, 0, 0,
8938 364d4831 Nathan Froyd
                                        do_ra, do_s0, do_s1, framesize);
8939 364d4831 Nathan Froyd
                    } else {
8940 364d4831 Nathan Froyd
                        gen_mips16_restore(ctx, 0, 0,
8941 364d4831 Nathan Froyd
                                           do_ra, do_s0, do_s1, framesize);
8942 364d4831 Nathan Froyd
                    }
8943 364d4831 Nathan Froyd
                }
8944 364d4831 Nathan Froyd
                break;
8945 364d4831 Nathan Froyd
            case I8_MOV32R:
8946 364d4831 Nathan Froyd
                {
8947 364d4831 Nathan Froyd
                    int rz = xlat(ctx->opcode & 0x7);
8948 364d4831 Nathan Froyd
8949 364d4831 Nathan Froyd
                    reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
8950 364d4831 Nathan Froyd
                        ((ctx->opcode >> 5) & 0x7);
8951 364d4831 Nathan Froyd
                    gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
8952 364d4831 Nathan Froyd
                }
8953 364d4831 Nathan Froyd
                break;
8954 364d4831 Nathan Froyd
            case I8_MOVR32:
8955 364d4831 Nathan Froyd
                reg32 = ctx->opcode & 0x1f;
8956 364d4831 Nathan Froyd
                gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
8957 364d4831 Nathan Froyd
                break;
8958 364d4831 Nathan Froyd
            default:
8959 364d4831 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
8960 364d4831 Nathan Froyd
                break;
8961 364d4831 Nathan Froyd
            }
8962 364d4831 Nathan Froyd
        }
8963 364d4831 Nathan Froyd
        break;
8964 364d4831 Nathan Froyd
    case M16_OPC_LI:
8965 364d4831 Nathan Froyd
        {
8966 364d4831 Nathan Froyd
            int16_t imm = (uint8_t) ctx->opcode;
8967 364d4831 Nathan Froyd
8968 364d4831 Nathan Froyd
            gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
8969 364d4831 Nathan Froyd
        }
8970 364d4831 Nathan Froyd
        break;
8971 364d4831 Nathan Froyd
    case M16_OPC_CMPI:
8972 364d4831 Nathan Froyd
        {
8973 364d4831 Nathan Froyd
            int16_t imm = (uint8_t) ctx->opcode;
8974 364d4831 Nathan Froyd
8975 364d4831 Nathan Froyd
            gen_logic_imm(env, OPC_XORI, 24, rx, imm);
8976 364d4831 Nathan Froyd
        }
8977 364d4831 Nathan Froyd
        break;
8978 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
8979 364d4831 Nathan Froyd
    case M16_OPC_SD:
8980 364d4831 Nathan Froyd
        check_mips_64(ctx);
8981 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SD, ry, rx, offset << 3);
8982 364d4831 Nathan Froyd
        break;
8983 364d4831 Nathan Froyd
#endif
8984 364d4831 Nathan Froyd
    case M16_OPC_LB:
8985 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8986 364d4831 Nathan Froyd
        break;
8987 364d4831 Nathan Froyd
    case M16_OPC_LH:
8988 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
8989 364d4831 Nathan Froyd
        break;
8990 364d4831 Nathan Froyd
    case M16_OPC_LWSP:
8991 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8992 364d4831 Nathan Froyd
        break;
8993 364d4831 Nathan Froyd
    case M16_OPC_LW:
8994 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
8995 364d4831 Nathan Froyd
        break;
8996 364d4831 Nathan Froyd
    case M16_OPC_LBU:
8997 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
8998 364d4831 Nathan Froyd
        break;
8999 364d4831 Nathan Froyd
    case M16_OPC_LHU:
9000 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
9001 364d4831 Nathan Froyd
        break;
9002 364d4831 Nathan Froyd
    case M16_OPC_LWPC:
9003 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
9004 364d4831 Nathan Froyd
        break;
9005 364d4831 Nathan Froyd
#if defined (TARGET_MIPS64)
9006 364d4831 Nathan Froyd
    case M16_OPC_LWU:
9007 364d4831 Nathan Froyd
        check_mips_64(ctx);
9008 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
9009 364d4831 Nathan Froyd
        break;
9010 364d4831 Nathan Froyd
#endif
9011 364d4831 Nathan Froyd
    case M16_OPC_SB:
9012 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SB, ry, rx, offset);
9013 364d4831 Nathan Froyd
        break;
9014 364d4831 Nathan Froyd
    case M16_OPC_SH:
9015 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SH, ry, rx, offset << 1);
9016 364d4831 Nathan Froyd
        break;
9017 364d4831 Nathan Froyd
    case M16_OPC_SWSP:
9018 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9019 364d4831 Nathan Froyd
        break;
9020 364d4831 Nathan Froyd
    case M16_OPC_SW:
9021 5c13fdfd Aurelien Jarno
        gen_st(ctx, OPC_SW, ry, rx, offset << 2);
9022 364d4831 Nathan Froyd
        break;
9023 364d4831 Nathan Froyd
    case M16_OPC_RRR:
9024 364d4831 Nathan Froyd
        {
9025 364d4831 Nathan Froyd
            int rz = xlat((ctx->opcode >> 2) & 0x7);
9026 364d4831 Nathan Froyd
            int mips32_op;
9027 364d4831 Nathan Froyd
9028 364d4831 Nathan Froyd
            switch (ctx->opcode & 0x3) {
9029 364d4831 Nathan Froyd
            case RRR_ADDU:
9030 364d4831 Nathan Froyd
                mips32_op = OPC_ADDU;
9031 364d4831 Nathan Froyd
                break;
9032 364d4831 Nathan Froyd
            case RRR_SUBU:
9033 364d4831 Nathan Froyd
                mips32_op = OPC_SUBU;
9034 364d4831 Nathan Froyd
                break;
9035 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
9036 364d4831 Nathan Froyd
            case RRR_DADDU:
9037 364d4831 Nathan Froyd
                mips32_op = OPC_DADDU;
9038 364d4831 Nathan Froyd
                check_mips_64(ctx);
9039 364d4831 Nathan Froyd
                break;
9040 364d4831 Nathan Froyd
            case RRR_DSUBU:
9041 364d4831 Nathan Froyd
                mips32_op = OPC_DSUBU;
9042 364d4831 Nathan Froyd
                check_mips_64(ctx);
9043 364d4831 Nathan Froyd
                break;
9044 364d4831 Nathan Froyd
#endif
9045 364d4831 Nathan Froyd
            default:
9046 364d4831 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
9047 364d4831 Nathan Froyd
                goto done;
9048 364d4831 Nathan Froyd
            }
9049 364d4831 Nathan Froyd
9050 364d4831 Nathan Froyd
            gen_arith(env, ctx, mips32_op, rz, rx, ry);
9051 364d4831 Nathan Froyd
        done:
9052 364d4831 Nathan Froyd
            ;
9053 364d4831 Nathan Froyd
        }
9054 364d4831 Nathan Froyd
        break;
9055 364d4831 Nathan Froyd
    case M16_OPC_RR:
9056 364d4831 Nathan Froyd
        switch (op1) {
9057 364d4831 Nathan Froyd
        case RR_JR:
9058 364d4831 Nathan Froyd
            {
9059 364d4831 Nathan Froyd
                int nd = (ctx->opcode >> 7) & 0x1;
9060 364d4831 Nathan Froyd
                int link = (ctx->opcode >> 6) & 0x1;
9061 364d4831 Nathan Froyd
                int ra = (ctx->opcode >> 5) & 0x1;
9062 364d4831 Nathan Froyd
9063 364d4831 Nathan Froyd
                if (link) {
9064 620e48f6 Nathan Froyd
                    op = nd ? OPC_JALRC : OPC_JALRS;
9065 364d4831 Nathan Froyd
                } else {
9066 364d4831 Nathan Froyd
                    op = OPC_JR;
9067 364d4831 Nathan Froyd
                }
9068 364d4831 Nathan Froyd
9069 364d4831 Nathan Froyd
                gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9070 364d4831 Nathan Froyd
                if (!nd) {
9071 364d4831 Nathan Froyd
                    *is_branch = 1;
9072 364d4831 Nathan Froyd
                }
9073 364d4831 Nathan Froyd
            }
9074 364d4831 Nathan Froyd
            break;
9075 364d4831 Nathan Froyd
        case RR_SDBBP:
9076 364d4831 Nathan Froyd
            /* XXX: not clear which exception should be raised
9077 364d4831 Nathan Froyd
             *      when in debug mode...
9078 364d4831 Nathan Froyd
             */
9079 364d4831 Nathan Froyd
            check_insn(env, ctx, ISA_MIPS32);
9080 364d4831 Nathan Froyd
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9081 364d4831 Nathan Froyd
                generate_exception(ctx, EXCP_DBp);
9082 364d4831 Nathan Froyd
            } else {
9083 364d4831 Nathan Froyd
                generate_exception(ctx, EXCP_DBp);
9084 364d4831 Nathan Froyd
            }
9085 364d4831 Nathan Froyd
            break;
9086 364d4831 Nathan Froyd
        case RR_SLT:
9087 364d4831 Nathan Froyd
            gen_slt(env, OPC_SLT, 24, rx, ry);
9088 364d4831 Nathan Froyd
            break;
9089 364d4831 Nathan Froyd
        case RR_SLTU:
9090 364d4831 Nathan Froyd
            gen_slt(env, OPC_SLTU, 24, rx, ry);
9091 364d4831 Nathan Froyd
            break;
9092 364d4831 Nathan Froyd
        case RR_BREAK:
9093 364d4831 Nathan Froyd
            generate_exception(ctx, EXCP_BREAK);
9094 364d4831 Nathan Froyd
            break;
9095 364d4831 Nathan Froyd
        case RR_SLLV:
9096 364d4831 Nathan Froyd
            gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9097 364d4831 Nathan Froyd
            break;
9098 364d4831 Nathan Froyd
        case RR_SRLV:
9099 364d4831 Nathan Froyd
            gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9100 364d4831 Nathan Froyd
            break;
9101 364d4831 Nathan Froyd
        case RR_SRAV:
9102 364d4831 Nathan Froyd
            gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9103 364d4831 Nathan Froyd
            break;
9104 364d4831 Nathan Froyd
#if defined (TARGET_MIPS64)
9105 364d4831 Nathan Froyd
        case RR_DSRL:
9106 364d4831 Nathan Froyd
            check_mips_64(ctx);
9107 364d4831 Nathan Froyd
            gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9108 364d4831 Nathan Froyd
            break;
9109 364d4831 Nathan Froyd
#endif
9110 364d4831 Nathan Froyd
        case RR_CMP:
9111 364d4831 Nathan Froyd
            gen_logic(env, OPC_XOR, 24, rx, ry);
9112 364d4831 Nathan Froyd
            break;
9113 364d4831 Nathan Froyd
        case RR_NEG:
9114 364d4831 Nathan Froyd
            gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9115 364d4831 Nathan Froyd
            break;
9116 364d4831 Nathan Froyd
        case RR_AND:
9117 364d4831 Nathan Froyd
            gen_logic(env, OPC_AND, rx, rx, ry);
9118 364d4831 Nathan Froyd
            break;
9119 364d4831 Nathan Froyd
        case RR_OR:
9120 364d4831 Nathan Froyd
            gen_logic(env, OPC_OR, rx, rx, ry);
9121 364d4831 Nathan Froyd
            break;
9122 364d4831 Nathan Froyd
        case RR_XOR:
9123 364d4831 Nathan Froyd
            gen_logic(env, OPC_XOR, rx, rx, ry);
9124 364d4831 Nathan Froyd
            break;
9125 364d4831 Nathan Froyd
        case RR_NOT:
9126 364d4831 Nathan Froyd
            gen_logic(env, OPC_NOR, rx, ry, 0);
9127 364d4831 Nathan Froyd
            break;
9128 364d4831 Nathan Froyd
        case RR_MFHI:
9129 364d4831 Nathan Froyd
            gen_HILO(ctx, OPC_MFHI, rx);
9130 364d4831 Nathan Froyd
            break;
9131 364d4831 Nathan Froyd
        case RR_CNVT:
9132 364d4831 Nathan Froyd
            switch (cnvt_op) {
9133 364d4831 Nathan Froyd
            case RR_RY_CNVT_ZEB:
9134 364d4831 Nathan Froyd
                tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9135 364d4831 Nathan Froyd
                break;
9136 364d4831 Nathan Froyd
            case RR_RY_CNVT_ZEH:
9137 364d4831 Nathan Froyd
                tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9138 364d4831 Nathan Froyd
                break;
9139 364d4831 Nathan Froyd
            case RR_RY_CNVT_SEB:
9140 364d4831 Nathan Froyd
                tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9141 364d4831 Nathan Froyd
                break;
9142 364d4831 Nathan Froyd
            case RR_RY_CNVT_SEH:
9143 364d4831 Nathan Froyd
                tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9144 364d4831 Nathan Froyd
                break;
9145 364d4831 Nathan Froyd
#if defined (TARGET_MIPS64)
9146 364d4831 Nathan Froyd
            case RR_RY_CNVT_ZEW:
9147 364d4831 Nathan Froyd
                check_mips_64(ctx);
9148 364d4831 Nathan Froyd
                tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9149 364d4831 Nathan Froyd
                break;
9150 364d4831 Nathan Froyd
            case RR_RY_CNVT_SEW:
9151 364d4831 Nathan Froyd
                check_mips_64(ctx);
9152 364d4831 Nathan Froyd
                tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9153 364d4831 Nathan Froyd
                break;
9154 364d4831 Nathan Froyd
#endif
9155 364d4831 Nathan Froyd
            default:
9156 364d4831 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
9157 364d4831 Nathan Froyd
                break;
9158 364d4831 Nathan Froyd
            }
9159 364d4831 Nathan Froyd
            break;
9160 364d4831 Nathan Froyd
        case RR_MFLO:
9161 364d4831 Nathan Froyd
            gen_HILO(ctx, OPC_MFLO, rx);
9162 364d4831 Nathan Froyd
            break;
9163 364d4831 Nathan Froyd
#if defined (TARGET_MIPS64)
9164 364d4831 Nathan Froyd
        case RR_DSRA:
9165 364d4831 Nathan Froyd
            check_mips_64(ctx);
9166 364d4831 Nathan Froyd
            gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9167 364d4831 Nathan Froyd
            break;
9168 364d4831 Nathan Froyd
        case RR_DSLLV:
9169 364d4831 Nathan Froyd
            check_mips_64(ctx);
9170 364d4831 Nathan Froyd
            gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9171 364d4831 Nathan Froyd
            break;
9172 364d4831 Nathan Froyd
        case RR_DSRLV:
9173 364d4831 Nathan Froyd
            check_mips_64(ctx);
9174 364d4831 Nathan Froyd
            gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9175 364d4831 Nathan Froyd
            break;
9176 364d4831 Nathan Froyd
        case RR_DSRAV:
9177 364d4831 Nathan Froyd
            check_mips_64(ctx);
9178 364d4831 Nathan Froyd
            gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9179 364d4831 Nathan Froyd
            break;
9180 364d4831 Nathan Froyd
#endif
9181 364d4831 Nathan Froyd
        case RR_MULT:
9182 364d4831 Nathan Froyd
            gen_muldiv(ctx, OPC_MULT, rx, ry);
9183 364d4831 Nathan Froyd
            break;
9184 364d4831 Nathan Froyd
        case RR_MULTU:
9185 364d4831 Nathan Froyd
            gen_muldiv(ctx, OPC_MULTU, rx, ry);
9186 364d4831 Nathan Froyd
            break;
9187 364d4831 Nathan Froyd
        case RR_DIV:
9188 364d4831 Nathan Froyd
            gen_muldiv(ctx, OPC_DIV, rx, ry);
9189 364d4831 Nathan Froyd
            break;
9190 364d4831 Nathan Froyd
        case RR_DIVU:
9191 364d4831 Nathan Froyd
            gen_muldiv(ctx, OPC_DIVU, rx, ry);
9192 364d4831 Nathan Froyd
            break;
9193 364d4831 Nathan Froyd
#if defined (TARGET_MIPS64)
9194 364d4831 Nathan Froyd
        case RR_DMULT:
9195 364d4831 Nathan Froyd
            check_mips_64(ctx);
9196 364d4831 Nathan Froyd
            gen_muldiv(ctx, OPC_DMULT, rx, ry);
9197 364d4831 Nathan Froyd
            break;
9198 364d4831 Nathan Froyd
        case RR_DMULTU:
9199 364d4831 Nathan Froyd
            check_mips_64(ctx);
9200 364d4831 Nathan Froyd
            gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9201 364d4831 Nathan Froyd
            break;
9202 364d4831 Nathan Froyd
        case RR_DDIV:
9203 364d4831 Nathan Froyd
            check_mips_64(ctx);
9204 364d4831 Nathan Froyd
            gen_muldiv(ctx, OPC_DDIV, rx, ry);
9205 364d4831 Nathan Froyd
            break;
9206 364d4831 Nathan Froyd
        case RR_DDIVU:
9207 364d4831 Nathan Froyd
            check_mips_64(ctx);
9208 364d4831 Nathan Froyd
            gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9209 364d4831 Nathan Froyd
            break;
9210 364d4831 Nathan Froyd
#endif
9211 364d4831 Nathan Froyd
        default:
9212 364d4831 Nathan Froyd
            generate_exception(ctx, EXCP_RI);
9213 364d4831 Nathan Froyd
            break;
9214 364d4831 Nathan Froyd
        }
9215 364d4831 Nathan Froyd
        break;
9216 364d4831 Nathan Froyd
    case M16_OPC_EXTEND:
9217 364d4831 Nathan Froyd
        decode_extended_mips16_opc(env, ctx, is_branch);
9218 364d4831 Nathan Froyd
        n_bytes = 4;
9219 364d4831 Nathan Froyd
        break;
9220 364d4831 Nathan Froyd
#if defined(TARGET_MIPS64)
9221 364d4831 Nathan Froyd
    case M16_OPC_I64:
9222 364d4831 Nathan Froyd
        funct = (ctx->opcode >> 8) & 0x7;
9223 364d4831 Nathan Froyd
        decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9224 364d4831 Nathan Froyd
        break;
9225 364d4831 Nathan Froyd
#endif
9226 364d4831 Nathan Froyd
    default:
9227 364d4831 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
9228 364d4831 Nathan Froyd
        break;
9229 364d4831 Nathan Froyd
    }
9230 364d4831 Nathan Froyd
9231 364d4831 Nathan Froyd
    return n_bytes;
9232 364d4831 Nathan Froyd
}
9233 364d4831 Nathan Froyd
9234 3c824109 Nathan Froyd
/* microMIPS extension to MIPS32 */
9235 6af0bf9c bellard
9236 3c824109 Nathan Froyd
/* microMIPS32 major opcodes */
9237 6af0bf9c bellard
9238 3c824109 Nathan Froyd
enum {
9239 3c824109 Nathan Froyd
    POOL32A = 0x00,
9240 3c824109 Nathan Froyd
    POOL16A = 0x01,
9241 3c824109 Nathan Froyd
    LBU16 = 0x02,
9242 3c824109 Nathan Froyd
    MOVE16 = 0x03,
9243 3c824109 Nathan Froyd
    ADDI32 = 0x04,
9244 3c824109 Nathan Froyd
    LBU32 = 0x05,
9245 3c824109 Nathan Froyd
    SB32 = 0x06,
9246 3c824109 Nathan Froyd
    LB32 = 0x07,
9247 3c824109 Nathan Froyd
9248 3c824109 Nathan Froyd
    POOL32B = 0x08,
9249 3c824109 Nathan Froyd
    POOL16B = 0x09,
9250 3c824109 Nathan Froyd
    LHU16 = 0x0a,
9251 3c824109 Nathan Froyd
    ANDI16 = 0x0b,
9252 3c824109 Nathan Froyd
    ADDIU32 = 0x0c,
9253 3c824109 Nathan Froyd
    LHU32 = 0x0d,
9254 3c824109 Nathan Froyd
    SH32 = 0x0e,
9255 3c824109 Nathan Froyd
    LH32 = 0x0f,
9256 3c824109 Nathan Froyd
9257 3c824109 Nathan Froyd
    POOL32I = 0x10,
9258 3c824109 Nathan Froyd
    POOL16C = 0x11,
9259 3c824109 Nathan Froyd
    LWSP16 = 0x12,
9260 3c824109 Nathan Froyd
    POOL16D = 0x13,
9261 3c824109 Nathan Froyd
    ORI32 = 0x14,
9262 3c824109 Nathan Froyd
    POOL32F = 0x15,
9263 3c824109 Nathan Froyd
    POOL32S = 0x16,
9264 3c824109 Nathan Froyd
    DADDIU32 = 0x17,
9265 3c824109 Nathan Froyd
9266 3c824109 Nathan Froyd
    POOL32C = 0x18,
9267 3c824109 Nathan Froyd
    LWGP16 = 0x19,
9268 3c824109 Nathan Froyd
    LW16 = 0x1a,
9269 3c824109 Nathan Froyd
    POOL16E = 0x1b,
9270 3c824109 Nathan Froyd
    XORI32 = 0x1c,
9271 3c824109 Nathan Froyd
    JALS32 = 0x1d,
9272 3c824109 Nathan Froyd
    ADDIUPC = 0x1e,
9273 3c824109 Nathan Froyd
    POOL48A = 0x1f,
9274 3c824109 Nathan Froyd
9275 3c824109 Nathan Froyd
    /* 0x20 is reserved */
9276 3c824109 Nathan Froyd
    RES_20 = 0x20,
9277 3c824109 Nathan Froyd
    POOL16F = 0x21,
9278 3c824109 Nathan Froyd
    SB16 = 0x22,
9279 3c824109 Nathan Froyd
    BEQZ16 = 0x23,
9280 3c824109 Nathan Froyd
    SLTI32 = 0x24,
9281 3c824109 Nathan Froyd
    BEQ32 = 0x25,
9282 3c824109 Nathan Froyd
    SWC132 = 0x26,
9283 3c824109 Nathan Froyd
    LWC132 = 0x27,
9284 3c824109 Nathan Froyd
9285 3c824109 Nathan Froyd
    /* 0x28 and 0x29 are reserved */
9286 3c824109 Nathan Froyd
    RES_28 = 0x28,
9287 3c824109 Nathan Froyd
    RES_29 = 0x29,
9288 3c824109 Nathan Froyd
    SH16 = 0x2a,
9289 3c824109 Nathan Froyd
    BNEZ16 = 0x2b,
9290 3c824109 Nathan Froyd
    SLTIU32 = 0x2c,
9291 3c824109 Nathan Froyd
    BNE32 = 0x2d,
9292 3c824109 Nathan Froyd
    SDC132 = 0x2e,
9293 3c824109 Nathan Froyd
    LDC132 = 0x2f,
9294 3c824109 Nathan Froyd
9295 3c824109 Nathan Froyd
    /* 0x30 and 0x31 are reserved */
9296 3c824109 Nathan Froyd
    RES_30 = 0x30,
9297 3c824109 Nathan Froyd
    RES_31 = 0x31,
9298 3c824109 Nathan Froyd
    SWSP16 = 0x32,
9299 3c824109 Nathan Froyd
    B16 = 0x33,
9300 3c824109 Nathan Froyd
    ANDI32 = 0x34,
9301 3c824109 Nathan Froyd
    J32 = 0x35,
9302 3c824109 Nathan Froyd
    SD32 = 0x36,
9303 3c824109 Nathan Froyd
    LD32 = 0x37,
9304 3c824109 Nathan Froyd
9305 3c824109 Nathan Froyd
    /* 0x38 and 0x39 are reserved */
9306 3c824109 Nathan Froyd
    RES_38 = 0x38,
9307 3c824109 Nathan Froyd
    RES_39 = 0x39,
9308 3c824109 Nathan Froyd
    SW16 = 0x3a,
9309 3c824109 Nathan Froyd
    LI16 = 0x3b,
9310 3c824109 Nathan Froyd
    JALX32 = 0x3c,
9311 3c824109 Nathan Froyd
    JAL32 = 0x3d,
9312 3c824109 Nathan Froyd
    SW32 = 0x3e,
9313 3c824109 Nathan Froyd
    LW32 = 0x3f
9314 3c824109 Nathan Froyd
};
9315 3c824109 Nathan Froyd
9316 3c824109 Nathan Froyd
/* POOL32A encoding of minor opcode field */
9317 3c824109 Nathan Froyd
9318 3c824109 Nathan Froyd
enum {
9319 3c824109 Nathan Froyd
    /* These opcodes are distinguished only by bits 9..6; those bits are
9320 3c824109 Nathan Froyd
     * what are recorded below. */
9321 3c824109 Nathan Froyd
    SLL32 = 0x0,
9322 3c824109 Nathan Froyd
    SRL32 = 0x1,
9323 3c824109 Nathan Froyd
    SRA = 0x2,
9324 3c824109 Nathan Froyd
    ROTR = 0x3,
9325 3c824109 Nathan Froyd
9326 3c824109 Nathan Froyd
    SLLV = 0x0,
9327 3c824109 Nathan Froyd
    SRLV = 0x1,
9328 3c824109 Nathan Froyd
    SRAV = 0x2,
9329 3c824109 Nathan Froyd
    ROTRV = 0x3,
9330 3c824109 Nathan Froyd
    ADD = 0x4,
9331 3c824109 Nathan Froyd
    ADDU32 = 0x5,
9332 3c824109 Nathan Froyd
    SUB = 0x6,
9333 3c824109 Nathan Froyd
    SUBU32 = 0x7,
9334 3c824109 Nathan Froyd
    MUL = 0x8,
9335 3c824109 Nathan Froyd
    AND = 0x9,
9336 3c824109 Nathan Froyd
    OR32 = 0xa,
9337 3c824109 Nathan Froyd
    NOR = 0xb,
9338 3c824109 Nathan Froyd
    XOR32 = 0xc,
9339 3c824109 Nathan Froyd
    SLT = 0xd,
9340 3c824109 Nathan Froyd
    SLTU = 0xe,
9341 3c824109 Nathan Froyd
9342 3c824109 Nathan Froyd
    MOVN = 0x0,
9343 3c824109 Nathan Froyd
    MOVZ = 0x1,
9344 3c824109 Nathan Froyd
    LWXS = 0x4,
9345 3c824109 Nathan Froyd
9346 3c824109 Nathan Froyd
    /* The following can be distinguished by their lower 6 bits. */
9347 3c824109 Nathan Froyd
    INS = 0x0c,
9348 3c824109 Nathan Froyd
    EXT = 0x2c,
9349 3c824109 Nathan Froyd
    POOL32AXF = 0x3c
9350 3c824109 Nathan Froyd
};
9351 3c824109 Nathan Froyd
9352 3c824109 Nathan Froyd
/* POOL32AXF encoding of minor opcode field extension */
9353 3c824109 Nathan Froyd
9354 3c824109 Nathan Froyd
enum {
9355 3c824109 Nathan Froyd
    /* bits 11..6 */
9356 3c824109 Nathan Froyd
    TEQ = 0x00,
9357 3c824109 Nathan Froyd
    TGE = 0x08,
9358 3c824109 Nathan Froyd
    TGEU = 0x10,
9359 3c824109 Nathan Froyd
    TLT = 0x20,
9360 3c824109 Nathan Froyd
    TLTU = 0x28,
9361 3c824109 Nathan Froyd
    TNE = 0x30,
9362 3c824109 Nathan Froyd
9363 3c824109 Nathan Froyd
    MFC0 = 0x03,
9364 3c824109 Nathan Froyd
    MTC0 = 0x0b,
9365 3c824109 Nathan Froyd
9366 3c824109 Nathan Froyd
    /* bits 13..12 for 0x01 */
9367 3c824109 Nathan Froyd
    MFHI_ACC = 0x0,
9368 3c824109 Nathan Froyd
    MFLO_ACC = 0x1,
9369 3c824109 Nathan Froyd
    MTHI_ACC = 0x2,
9370 3c824109 Nathan Froyd
    MTLO_ACC = 0x3,
9371 3c824109 Nathan Froyd
9372 3c824109 Nathan Froyd
    /* bits 13..12 for 0x2a */
9373 3c824109 Nathan Froyd
    MADD_ACC = 0x0,
9374 3c824109 Nathan Froyd
    MADDU_ACC = 0x1,
9375 3c824109 Nathan Froyd
    MSUB_ACC = 0x2,
9376 3c824109 Nathan Froyd
    MSUBU_ACC = 0x3,
9377 3c824109 Nathan Froyd
9378 3c824109 Nathan Froyd
    /* bits 13..12 for 0x32 */
9379 3c824109 Nathan Froyd
    MULT_ACC = 0x0,
9380 3c824109 Nathan Froyd
    MULTU_ACC = 0x0,
9381 3c824109 Nathan Froyd
9382 3c824109 Nathan Froyd
    /* bits 15..12 for 0x2c */
9383 3c824109 Nathan Froyd
    SEB = 0x2,
9384 3c824109 Nathan Froyd
    SEH = 0x3,
9385 3c824109 Nathan Froyd
    CLO = 0x4,
9386 3c824109 Nathan Froyd
    CLZ = 0x5,
9387 3c824109 Nathan Froyd
    RDHWR = 0x6,
9388 3c824109 Nathan Froyd
    WSBH = 0x7,
9389 3c824109 Nathan Froyd
    MULT = 0x8,
9390 3c824109 Nathan Froyd
    MULTU = 0x9,
9391 3c824109 Nathan Froyd
    DIV = 0xa,
9392 3c824109 Nathan Froyd
    DIVU = 0xb,
9393 3c824109 Nathan Froyd
    MADD = 0xc,
9394 3c824109 Nathan Froyd
    MADDU = 0xd,
9395 3c824109 Nathan Froyd
    MSUB = 0xe,
9396 3c824109 Nathan Froyd
    MSUBU = 0xf,
9397 3c824109 Nathan Froyd
9398 3c824109 Nathan Froyd
    /* bits 15..12 for 0x34 */
9399 3c824109 Nathan Froyd
    MFC2 = 0x4,
9400 3c824109 Nathan Froyd
    MTC2 = 0x5,
9401 3c824109 Nathan Froyd
    MFHC2 = 0x8,
9402 3c824109 Nathan Froyd
    MTHC2 = 0x9,
9403 3c824109 Nathan Froyd
    CFC2 = 0xc,
9404 3c824109 Nathan Froyd
    CTC2 = 0xd,
9405 3c824109 Nathan Froyd
9406 3c824109 Nathan Froyd
    /* bits 15..12 for 0x3c */
9407 3c824109 Nathan Froyd
    JALR = 0x0,
9408 3c824109 Nathan Froyd
    JR = 0x0,                   /* alias */
9409 3c824109 Nathan Froyd
    JALR_HB = 0x1,
9410 3c824109 Nathan Froyd
    JALRS = 0x4,
9411 3c824109 Nathan Froyd
    JALRS_HB = 0x5,
9412 3c824109 Nathan Froyd
9413 3c824109 Nathan Froyd
    /* bits 15..12 for 0x05 */
9414 3c824109 Nathan Froyd
    RDPGPR = 0xe,
9415 3c824109 Nathan Froyd
    WRPGPR = 0xf,
9416 3c824109 Nathan Froyd
9417 3c824109 Nathan Froyd
    /* bits 15..12 for 0x0d */
9418 3c824109 Nathan Froyd
    TLBP = 0x0,
9419 3c824109 Nathan Froyd
    TLBR = 0x1,
9420 3c824109 Nathan Froyd
    TLBWI = 0x2,
9421 3c824109 Nathan Froyd
    TLBWR = 0x3,
9422 3c824109 Nathan Froyd
    WAIT = 0x9,
9423 3c824109 Nathan Froyd
    IRET = 0xd,
9424 3c824109 Nathan Froyd
    DERET = 0xe,
9425 3c824109 Nathan Froyd
    ERET = 0xf,
9426 3c824109 Nathan Froyd
9427 3c824109 Nathan Froyd
    /* bits 15..12 for 0x15 */
9428 3c824109 Nathan Froyd
    DMT = 0x0,
9429 3c824109 Nathan Froyd
    DVPE = 0x1,
9430 3c824109 Nathan Froyd
    EMT = 0x2,
9431 3c824109 Nathan Froyd
    EVPE = 0x3,
9432 3c824109 Nathan Froyd
9433 3c824109 Nathan Froyd
    /* bits 15..12 for 0x1d */
9434 3c824109 Nathan Froyd
    DI = 0x4,
9435 3c824109 Nathan Froyd
    EI = 0x5,
9436 3c824109 Nathan Froyd
9437 3c824109 Nathan Froyd
    /* bits 15..12 for 0x2d */
9438 3c824109 Nathan Froyd
    SYNC = 0x6,
9439 3c824109 Nathan Froyd
    SYSCALL = 0x8,
9440 3c824109 Nathan Froyd
    SDBBP = 0xd,
9441 3c824109 Nathan Froyd
9442 3c824109 Nathan Froyd
    /* bits 15..12 for 0x35 */
9443 3c824109 Nathan Froyd
    MFHI32 = 0x0,
9444 3c824109 Nathan Froyd
    MFLO32 = 0x1,
9445 3c824109 Nathan Froyd
    MTHI32 = 0x2,
9446 3c824109 Nathan Froyd
    MTLO32 = 0x3,
9447 3c824109 Nathan Froyd
};
9448 3c824109 Nathan Froyd
9449 3c824109 Nathan Froyd
/* POOL32B encoding of minor opcode field (bits 15..12) */
9450 3c824109 Nathan Froyd
9451 3c824109 Nathan Froyd
enum {
9452 3c824109 Nathan Froyd
    LWC2 = 0x0,
9453 3c824109 Nathan Froyd
    LWP = 0x1,
9454 3c824109 Nathan Froyd
    LDP = 0x4,
9455 3c824109 Nathan Froyd
    LWM32 = 0x5,
9456 3c824109 Nathan Froyd
    CACHE = 0x6,
9457 3c824109 Nathan Froyd
    LDM = 0x7,
9458 3c824109 Nathan Froyd
    SWC2 = 0x8,
9459 3c824109 Nathan Froyd
    SWP = 0x9,
9460 3c824109 Nathan Froyd
    SDP = 0xc,
9461 3c824109 Nathan Froyd
    SWM32 = 0xd,
9462 3c824109 Nathan Froyd
    SDM = 0xf
9463 3c824109 Nathan Froyd
};
9464 3c824109 Nathan Froyd
9465 3c824109 Nathan Froyd
/* POOL32C encoding of minor opcode field (bits 15..12) */
9466 3c824109 Nathan Froyd
9467 3c824109 Nathan Froyd
enum {
9468 3c824109 Nathan Froyd
    LWL = 0x0,
9469 3c824109 Nathan Froyd
    SWL = 0x8,
9470 3c824109 Nathan Froyd
    LWR = 0x1,
9471 3c824109 Nathan Froyd
    SWR = 0x9,
9472 3c824109 Nathan Froyd
    PREF = 0x2,
9473 3c824109 Nathan Froyd
    /* 0xa is reserved */
9474 3c824109 Nathan Froyd
    LL = 0x3,
9475 3c824109 Nathan Froyd
    SC = 0xb,
9476 3c824109 Nathan Froyd
    LDL = 0x4,
9477 3c824109 Nathan Froyd
    SDL = 0xc,
9478 3c824109 Nathan Froyd
    LDR = 0x5,
9479 3c824109 Nathan Froyd
    SDR = 0xd,
9480 3c824109 Nathan Froyd
    /* 0x6 is reserved */
9481 3c824109 Nathan Froyd
    LWU = 0xe,
9482 3c824109 Nathan Froyd
    LLD = 0x7,
9483 3c824109 Nathan Froyd
    SCD = 0xf
9484 3c824109 Nathan Froyd
};
9485 3c824109 Nathan Froyd
9486 3c824109 Nathan Froyd
/* POOL32F encoding of minor opcode field (bits 5..0) */
9487 3c824109 Nathan Froyd
9488 3c824109 Nathan Froyd
enum {
9489 3c824109 Nathan Froyd
    /* These are the bit 7..6 values */
9490 3c824109 Nathan Froyd
    ADD_FMT = 0x0,
9491 3c824109 Nathan Froyd
    MOVN_FMT = 0x0,
9492 3c824109 Nathan Froyd
9493 3c824109 Nathan Froyd
    SUB_FMT = 0x1,
9494 3c824109 Nathan Froyd
    MOVZ_FMT = 0x1,
9495 3c824109 Nathan Froyd
9496 3c824109 Nathan Froyd
    MUL_FMT = 0x2,
9497 3c824109 Nathan Froyd
9498 3c824109 Nathan Froyd
    DIV_FMT = 0x3,
9499 3c824109 Nathan Froyd
9500 3c824109 Nathan Froyd
    /* These are the bit 8..6 values */
9501 3c824109 Nathan Froyd
    RSQRT2_FMT = 0x0,
9502 3c824109 Nathan Froyd
    MOVF_FMT = 0x0,
9503 3c824109 Nathan Froyd
9504 3c824109 Nathan Froyd
    LWXC1 = 0x1,
9505 3c824109 Nathan Froyd
    MOVT_FMT = 0x1,
9506 3c824109 Nathan Froyd
9507 3c824109 Nathan Froyd
    PLL_PS = 0x2,
9508 3c824109 Nathan Froyd
    SWXC1 = 0x2,
9509 3c824109 Nathan Froyd
9510 3c824109 Nathan Froyd
    PLU_PS = 0x3,
9511 3c824109 Nathan Froyd
    LDXC1 = 0x3,
9512 3c824109 Nathan Froyd
9513 3c824109 Nathan Froyd
    PUL_PS = 0x4,
9514 3c824109 Nathan Froyd
    SDXC1 = 0x4,
9515 3c824109 Nathan Froyd
    RECIP2_FMT = 0x4,
9516 3c824109 Nathan Froyd
9517 3c824109 Nathan Froyd
    PUU_PS = 0x5,
9518 3c824109 Nathan Froyd
    LUXC1 = 0x5,
9519 3c824109 Nathan Froyd
9520 3c824109 Nathan Froyd
    CVT_PS_S = 0x6,
9521 3c824109 Nathan Froyd
    SUXC1 = 0x6,
9522 3c824109 Nathan Froyd
    ADDR_PS = 0x6,
9523 3c824109 Nathan Froyd
    PREFX = 0x6,
9524 3c824109 Nathan Froyd
9525 3c824109 Nathan Froyd
    MULR_PS = 0x7,
9526 3c824109 Nathan Froyd
9527 3c824109 Nathan Froyd
    MADD_S = 0x01,
9528 3c824109 Nathan Froyd
    MADD_D = 0x09,
9529 3c824109 Nathan Froyd
    MADD_PS = 0x11,
9530 3c824109 Nathan Froyd
    ALNV_PS = 0x19,
9531 3c824109 Nathan Froyd
    MSUB_S = 0x21,
9532 3c824109 Nathan Froyd
    MSUB_D = 0x29,
9533 3c824109 Nathan Froyd
    MSUB_PS = 0x31,
9534 3c824109 Nathan Froyd
9535 3c824109 Nathan Froyd
    NMADD_S = 0x02,
9536 3c824109 Nathan Froyd
    NMADD_D = 0x0a,
9537 3c824109 Nathan Froyd
    NMADD_PS = 0x12,
9538 3c824109 Nathan Froyd
    NMSUB_S = 0x22,
9539 3c824109 Nathan Froyd
    NMSUB_D = 0x2a,
9540 3c824109 Nathan Froyd
    NMSUB_PS = 0x32,
9541 3c824109 Nathan Froyd
9542 3c824109 Nathan Froyd
    POOL32FXF = 0x3b,
9543 3c824109 Nathan Froyd
9544 3c824109 Nathan Froyd
    CABS_COND_FMT = 0x1c,              /* MIPS3D */
9545 3c824109 Nathan Froyd
    C_COND_FMT = 0x3c
9546 3c824109 Nathan Froyd
};
9547 3c824109 Nathan Froyd
9548 3c824109 Nathan Froyd
/* POOL32Fxf encoding of minor opcode extension field */
9549 3c824109 Nathan Froyd
9550 3c824109 Nathan Froyd
enum {
9551 3c824109 Nathan Froyd
    CVT_L = 0x04,
9552 3c824109 Nathan Froyd
    RSQRT_FMT = 0x08,
9553 3c824109 Nathan Froyd
    FLOOR_L = 0x0c,
9554 3c824109 Nathan Froyd
    CVT_PW_PS = 0x1c,
9555 3c824109 Nathan Froyd
    CVT_W = 0x24,
9556 3c824109 Nathan Froyd
    SQRT_FMT = 0x28,
9557 3c824109 Nathan Froyd
    FLOOR_W = 0x2c,
9558 3c824109 Nathan Froyd
    CVT_PS_PW = 0x3c,
9559 3c824109 Nathan Froyd
    CFC1 = 0x40,
9560 3c824109 Nathan Froyd
    RECIP_FMT = 0x48,
9561 3c824109 Nathan Froyd
    CEIL_L = 0x4c,
9562 3c824109 Nathan Froyd
    CTC1 = 0x60,
9563 3c824109 Nathan Froyd
    CEIL_W = 0x6c,
9564 3c824109 Nathan Froyd
    MFC1 = 0x80,
9565 3c824109 Nathan Froyd
    CVT_S_PL = 0x84,
9566 3c824109 Nathan Froyd
    TRUNC_L = 0x8c,
9567 3c824109 Nathan Froyd
    MTC1 = 0xa0,
9568 3c824109 Nathan Froyd
    CVT_S_PU = 0xa4,
9569 3c824109 Nathan Froyd
    TRUNC_W = 0xac,
9570 3c824109 Nathan Froyd
    MFHC1 = 0xc0,
9571 3c824109 Nathan Froyd
    ROUND_L = 0xcc,
9572 3c824109 Nathan Froyd
    MTHC1 = 0xe0,
9573 3c824109 Nathan Froyd
    ROUND_W = 0xec,
9574 3c824109 Nathan Froyd
9575 3c824109 Nathan Froyd
    MOV_FMT = 0x01,
9576 3c824109 Nathan Froyd
    MOVF = 0x05,
9577 3c824109 Nathan Froyd
    ABS_FMT = 0x0d,
9578 3c824109 Nathan Froyd
    RSQRT1_FMT = 0x1d,
9579 3c824109 Nathan Froyd
    MOVT = 0x25,
9580 3c824109 Nathan Froyd
    NEG_FMT = 0x2d,
9581 3c824109 Nathan Froyd
    CVT_D = 0x4d,
9582 3c824109 Nathan Froyd
    RECIP1_FMT = 0x5d,
9583 3c824109 Nathan Froyd
    CVT_S = 0x6d
9584 3c824109 Nathan Froyd
};
9585 3c824109 Nathan Froyd
9586 3c824109 Nathan Froyd
/* POOL32I encoding of minor opcode field (bits 25..21) */
9587 3c824109 Nathan Froyd
9588 3c824109 Nathan Froyd
enum {
9589 3c824109 Nathan Froyd
    BLTZ = 0x00,
9590 3c824109 Nathan Froyd
    BLTZAL = 0x01,
9591 3c824109 Nathan Froyd
    BGEZ = 0x02,
9592 3c824109 Nathan Froyd
    BGEZAL = 0x03,
9593 3c824109 Nathan Froyd
    BLEZ = 0x04,
9594 3c824109 Nathan Froyd
    BNEZC = 0x05,
9595 3c824109 Nathan Froyd
    BGTZ = 0x06,
9596 3c824109 Nathan Froyd
    BEQZC = 0x07,
9597 3c824109 Nathan Froyd
    TLTI = 0x08,
9598 3c824109 Nathan Froyd
    TGEI = 0x09,
9599 3c824109 Nathan Froyd
    TLTIU = 0x0a,
9600 3c824109 Nathan Froyd
    TGEIU = 0x0b,
9601 3c824109 Nathan Froyd
    TNEI = 0x0c,
9602 3c824109 Nathan Froyd
    LUI = 0x0d,
9603 3c824109 Nathan Froyd
    TEQI = 0x0e,
9604 3c824109 Nathan Froyd
    SYNCI = 0x10,
9605 3c824109 Nathan Froyd
    BLTZALS = 0x11,
9606 3c824109 Nathan Froyd
    BGEZALS = 0x13,
9607 3c824109 Nathan Froyd
    BC2F = 0x14,
9608 3c824109 Nathan Froyd
    BC2T = 0x15,
9609 3c824109 Nathan Froyd
    BPOSGE64 = 0x1a,
9610 3c824109 Nathan Froyd
    BPOSGE32 = 0x1b,
9611 3c824109 Nathan Froyd
    /* These overlap and are distinguished by bit16 of the instruction */
9612 3c824109 Nathan Froyd
    BC1F = 0x1c,
9613 3c824109 Nathan Froyd
    BC1T = 0x1d,
9614 3c824109 Nathan Froyd
    BC1ANY2F = 0x1c,
9615 3c824109 Nathan Froyd
    BC1ANY2T = 0x1d,
9616 3c824109 Nathan Froyd
    BC1ANY4F = 0x1e,
9617 3c824109 Nathan Froyd
    BC1ANY4T = 0x1f
9618 3c824109 Nathan Froyd
};
9619 3c824109 Nathan Froyd
9620 3c824109 Nathan Froyd
/* POOL16A encoding of minor opcode field */
9621 3c824109 Nathan Froyd
9622 3c824109 Nathan Froyd
enum {
9623 3c824109 Nathan Froyd
    ADDU16 = 0x0,
9624 3c824109 Nathan Froyd
    SUBU16 = 0x1
9625 3c824109 Nathan Froyd
};
9626 3c824109 Nathan Froyd
9627 3c824109 Nathan Froyd
/* POOL16B encoding of minor opcode field */
9628 3c824109 Nathan Froyd
9629 3c824109 Nathan Froyd
enum {
9630 3c824109 Nathan Froyd
    SLL16 = 0x0,
9631 3c824109 Nathan Froyd
    SRL16 = 0x1
9632 3c824109 Nathan Froyd
};
9633 3c824109 Nathan Froyd
9634 3c824109 Nathan Froyd
/* POOL16C encoding of minor opcode field */
9635 3c824109 Nathan Froyd
9636 3c824109 Nathan Froyd
enum {
9637 3c824109 Nathan Froyd
    NOT16 = 0x00,
9638 3c824109 Nathan Froyd
    XOR16 = 0x04,
9639 3c824109 Nathan Froyd
    AND16 = 0x08,
9640 3c824109 Nathan Froyd
    OR16 = 0x0c,
9641 3c824109 Nathan Froyd
    LWM16 = 0x10,
9642 3c824109 Nathan Froyd
    SWM16 = 0x14,
9643 3c824109 Nathan Froyd
    JR16 = 0x18,
9644 3c824109 Nathan Froyd
    JRC16 = 0x1a,
9645 3c824109 Nathan Froyd
    JALR16 = 0x1c,
9646 3c824109 Nathan Froyd
    JALR16S = 0x1e,
9647 3c824109 Nathan Froyd
    MFHI16 = 0x20,
9648 3c824109 Nathan Froyd
    MFLO16 = 0x24,
9649 3c824109 Nathan Froyd
    BREAK16 = 0x28,
9650 3c824109 Nathan Froyd
    SDBBP16 = 0x2c,
9651 3c824109 Nathan Froyd
    JRADDIUSP = 0x30
9652 3c824109 Nathan Froyd
};
9653 3c824109 Nathan Froyd
9654 3c824109 Nathan Froyd
/* POOL16D encoding of minor opcode field */
9655 3c824109 Nathan Froyd
9656 3c824109 Nathan Froyd
enum {
9657 3c824109 Nathan Froyd
    ADDIUS5 = 0x0,
9658 3c824109 Nathan Froyd
    ADDIUSP = 0x1
9659 3c824109 Nathan Froyd
};
9660 3c824109 Nathan Froyd
9661 3c824109 Nathan Froyd
/* POOL16E encoding of minor opcode field */
9662 3c824109 Nathan Froyd
9663 3c824109 Nathan Froyd
enum {
9664 3c824109 Nathan Froyd
    ADDIUR2 = 0x0,
9665 3c824109 Nathan Froyd
    ADDIUR1SP = 0x1
9666 3c824109 Nathan Froyd
};
9667 3c824109 Nathan Froyd
9668 3c824109 Nathan Froyd
static int mmreg (int r)
9669 3c824109 Nathan Froyd
{
9670 3c824109 Nathan Froyd
    static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9671 3c824109 Nathan Froyd
9672 3c824109 Nathan Froyd
    return map[r];
9673 3c824109 Nathan Froyd
}
9674 3c824109 Nathan Froyd
9675 3c824109 Nathan Froyd
/* Used for 16-bit store instructions.  */
9676 3c824109 Nathan Froyd
static int mmreg2 (int r)
9677 3c824109 Nathan Froyd
{
9678 3c824109 Nathan Froyd
    static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
9679 3c824109 Nathan Froyd
9680 3c824109 Nathan Froyd
    return map[r];
9681 3c824109 Nathan Froyd
}
9682 3c824109 Nathan Froyd
9683 3c824109 Nathan Froyd
#define uMIPS_RD(op) ((op >> 7) & 0x7)
9684 3c824109 Nathan Froyd
#define uMIPS_RS(op) ((op >> 4) & 0x7)
9685 3c824109 Nathan Froyd
#define uMIPS_RS2(op) uMIPS_RS(op)
9686 3c824109 Nathan Froyd
#define uMIPS_RS1(op) ((op >> 1) & 0x7)
9687 3c824109 Nathan Froyd
#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
9688 3c824109 Nathan Froyd
#define uMIPS_RS5(op) (op & 0x1f)
9689 3c824109 Nathan Froyd
9690 3c824109 Nathan Froyd
/* Signed immediate */
9691 3c824109 Nathan Froyd
#define SIMM(op, start, width)                                          \
9692 3c824109 Nathan Froyd
    ((int32_t)(((op >> start) & ((~0U) >> (32-width)))                 \
9693 3c824109 Nathan Froyd
               << (32-width))                                           \
9694 3c824109 Nathan Froyd
     >> (32-width))
9695 3c824109 Nathan Froyd
/* Zero-extended immediate */
9696 3c824109 Nathan Froyd
#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
9697 3c824109 Nathan Froyd
9698 3c824109 Nathan Froyd
static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
9699 3c824109 Nathan Froyd
{
9700 3c824109 Nathan Froyd
    int rd = mmreg(uMIPS_RD(ctx->opcode));
9701 3c824109 Nathan Froyd
9702 3c824109 Nathan Froyd
    gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
9703 3c824109 Nathan Froyd
}
9704 3c824109 Nathan Froyd
9705 3c824109 Nathan Froyd
static void gen_addiur2 (CPUState *env, DisasContext *ctx)
9706 3c824109 Nathan Froyd
{
9707 3c824109 Nathan Froyd
    static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
9708 3c824109 Nathan Froyd
    int rd = mmreg(uMIPS_RD(ctx->opcode));
9709 3c824109 Nathan Froyd
    int rs = mmreg(uMIPS_RS(ctx->opcode));
9710 3c824109 Nathan Froyd
9711 3c824109 Nathan Froyd
    gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
9712 3c824109 Nathan Froyd
}
9713 3c824109 Nathan Froyd
9714 3c824109 Nathan Froyd
static void gen_addiusp (CPUState *env, DisasContext *ctx)
9715 3c824109 Nathan Froyd
{
9716 3c824109 Nathan Froyd
    int encoded = ZIMM(ctx->opcode, 1, 9);
9717 3c824109 Nathan Froyd
    int decoded;
9718 3c824109 Nathan Froyd
9719 3c824109 Nathan Froyd
    if (encoded <= 1) {
9720 3c824109 Nathan Froyd
        decoded = 256 + encoded;
9721 3c824109 Nathan Froyd
    } else if (encoded <= 255) {
9722 3c824109 Nathan Froyd
        decoded = encoded;
9723 3c824109 Nathan Froyd
    } else if (encoded <= 509) {
9724 3c824109 Nathan Froyd
        decoded = encoded - 512;
9725 3c824109 Nathan Froyd
    } else {
9726 3c824109 Nathan Froyd
        decoded = encoded - 768;
9727 3c824109 Nathan Froyd
    }
9728 3c824109 Nathan Froyd
9729 3c824109 Nathan Froyd
    gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
9730 3c824109 Nathan Froyd
}
9731 3c824109 Nathan Froyd
9732 3c824109 Nathan Froyd
static void gen_addius5 (CPUState *env, DisasContext *ctx)
9733 3c824109 Nathan Froyd
{
9734 3c824109 Nathan Froyd
    int imm = SIMM(ctx->opcode, 1, 4);
9735 3c824109 Nathan Froyd
    int rd = (ctx->opcode >> 5) & 0x1f;
9736 3c824109 Nathan Froyd
9737 3c824109 Nathan Froyd
    gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
9738 3c824109 Nathan Froyd
}
9739 3c824109 Nathan Froyd
9740 3c824109 Nathan Froyd
static void gen_andi16 (CPUState *env, DisasContext *ctx)
9741 3c824109 Nathan Froyd
{
9742 3c824109 Nathan Froyd
    static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
9743 3c824109 Nathan Froyd
                                 31, 32, 63, 64, 255, 32768, 65535 };
9744 3c824109 Nathan Froyd
    int rd = mmreg(uMIPS_RD(ctx->opcode));
9745 3c824109 Nathan Froyd
    int rs = mmreg(uMIPS_RS(ctx->opcode));
9746 3c824109 Nathan Froyd
    int encoded = ZIMM(ctx->opcode, 0, 4);
9747 3c824109 Nathan Froyd
9748 3c824109 Nathan Froyd
    gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
9749 3c824109 Nathan Froyd
}
9750 3c824109 Nathan Froyd
9751 3c824109 Nathan Froyd
static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
9752 3c824109 Nathan Froyd
                               int base, int16_t offset)
9753 3c824109 Nathan Froyd
{
9754 3c824109 Nathan Froyd
    TCGv t0, t1;
9755 3c824109 Nathan Froyd
    TCGv_i32 t2;
9756 3c824109 Nathan Froyd
9757 3c824109 Nathan Froyd
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
9758 3c824109 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
9759 3c824109 Nathan Froyd
        return;
9760 3c824109 Nathan Froyd
    }
9761 3c824109 Nathan Froyd
9762 3c824109 Nathan Froyd
    t0 = tcg_temp_new();
9763 3c824109 Nathan Froyd
9764 3c824109 Nathan Froyd
    gen_base_offset_addr(ctx, t0, base, offset);
9765 3c824109 Nathan Froyd
9766 3c824109 Nathan Froyd
    t1 = tcg_const_tl(reglist);
9767 3c824109 Nathan Froyd
    t2 = tcg_const_i32(ctx->mem_idx);
9768 6af0bf9c bellard
9769 3c824109 Nathan Froyd
    save_cpu_state(ctx, 1);
9770 3c824109 Nathan Froyd
    switch (opc) {
9771 3c824109 Nathan Froyd
    case LWM32:
9772 3c824109 Nathan Froyd
        gen_helper_lwm(t0, t1, t2);
9773 3c824109 Nathan Froyd
        break;
9774 3c824109 Nathan Froyd
    case SWM32:
9775 3c824109 Nathan Froyd
        gen_helper_swm(t0, t1, t2);
9776 3c824109 Nathan Froyd
        break;
9777 3c824109 Nathan Froyd
#ifdef TARGET_MIPS64
9778 3c824109 Nathan Froyd
    case LDM:
9779 3c824109 Nathan Froyd
        gen_helper_ldm(t0, t1, t2);
9780 3c824109 Nathan Froyd
        break;
9781 3c824109 Nathan Froyd
    case SDM:
9782 3c824109 Nathan Froyd
        gen_helper_sdm(t0, t1, t2);
9783 3c824109 Nathan Froyd
        break;
9784 6af0bf9c bellard
#endif
9785 3c824109 Nathan Froyd
    }
9786 3c824109 Nathan Froyd
    MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
9787 3c824109 Nathan Froyd
    tcg_temp_free(t0);
9788 33087598 Stefan Weil
    tcg_temp_free(t1);
9789 3c824109 Nathan Froyd
    tcg_temp_free_i32(t2);
9790 3c824109 Nathan Froyd
}
9791 6af0bf9c bellard
9792 3c824109 Nathan Froyd
9793 3c824109 Nathan Froyd
static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
9794 6af0bf9c bellard
{
9795 3c824109 Nathan Froyd
    int rd = mmreg((ctx->opcode >> 3) & 0x7);
9796 3c824109 Nathan Froyd
    int rs = mmreg(ctx->opcode & 0x7);
9797 3c824109 Nathan Froyd
    int opc;
9798 6af0bf9c bellard
9799 3c824109 Nathan Froyd
    switch (((ctx->opcode) >> 4) & 0x3f) {
9800 3c824109 Nathan Froyd
    case NOT16 + 0:
9801 3c824109 Nathan Froyd
    case NOT16 + 1:
9802 3c824109 Nathan Froyd
    case NOT16 + 2:
9803 3c824109 Nathan Froyd
    case NOT16 + 3:
9804 3c824109 Nathan Froyd
        gen_logic(env, OPC_NOR, rd, rs, 0);
9805 3c824109 Nathan Froyd
        break;
9806 3c824109 Nathan Froyd
    case XOR16 + 0:
9807 3c824109 Nathan Froyd
    case XOR16 + 1:
9808 3c824109 Nathan Froyd
    case XOR16 + 2:
9809 3c824109 Nathan Froyd
    case XOR16 + 3:
9810 3c824109 Nathan Froyd
        gen_logic(env, OPC_XOR, rd, rd, rs);
9811 3c824109 Nathan Froyd
        break;
9812 3c824109 Nathan Froyd
    case AND16 + 0:
9813 3c824109 Nathan Froyd
    case AND16 + 1:
9814 3c824109 Nathan Froyd
    case AND16 + 2:
9815 3c824109 Nathan Froyd
    case AND16 + 3:
9816 3c824109 Nathan Froyd
        gen_logic(env, OPC_AND, rd, rd, rs);
9817 3c824109 Nathan Froyd
        break;
9818 3c824109 Nathan Froyd
    case OR16 + 0:
9819 3c824109 Nathan Froyd
    case OR16 + 1:
9820 3c824109 Nathan Froyd
    case OR16 + 2:
9821 3c824109 Nathan Froyd
    case OR16 + 3:
9822 3c824109 Nathan Froyd
        gen_logic(env, OPC_OR, rd, rd, rs);
9823 3c824109 Nathan Froyd
        break;
9824 3c824109 Nathan Froyd
    case LWM16 + 0:
9825 3c824109 Nathan Froyd
    case LWM16 + 1:
9826 3c824109 Nathan Froyd
    case LWM16 + 2:
9827 3c824109 Nathan Froyd
    case LWM16 + 3:
9828 3c824109 Nathan Froyd
        {
9829 3c824109 Nathan Froyd
            static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9830 3c824109 Nathan Froyd
            int offset = ZIMM(ctx->opcode, 0, 4);
9831 3c824109 Nathan Froyd
9832 3c824109 Nathan Froyd
            gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
9833 3c824109 Nathan Froyd
                              29, offset << 2);
9834 3c824109 Nathan Froyd
        }
9835 3c824109 Nathan Froyd
        break;
9836 3c824109 Nathan Froyd
    case SWM16 + 0:
9837 3c824109 Nathan Froyd
    case SWM16 + 1:
9838 3c824109 Nathan Froyd
    case SWM16 + 2:
9839 3c824109 Nathan Froyd
    case SWM16 + 3:
9840 3c824109 Nathan Froyd
        {
9841 3c824109 Nathan Froyd
            static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9842 3c824109 Nathan Froyd
            int offset = ZIMM(ctx->opcode, 0, 4);
9843 3c824109 Nathan Froyd
9844 3c824109 Nathan Froyd
            gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
9845 3c824109 Nathan Froyd
                              29, offset << 2);
9846 3c824109 Nathan Froyd
        }
9847 3c824109 Nathan Froyd
        break;
9848 3c824109 Nathan Froyd
    case JR16 + 0:
9849 3c824109 Nathan Froyd
    case JR16 + 1:
9850 3c824109 Nathan Froyd
        {
9851 3c824109 Nathan Froyd
            int reg = ctx->opcode & 0x1f;
9852 3c824109 Nathan Froyd
9853 3c824109 Nathan Froyd
            gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9854 3c824109 Nathan Froyd
        }
9855 3c824109 Nathan Froyd
        *is_branch = 1;
9856 3c824109 Nathan Froyd
        break;
9857 3c824109 Nathan Froyd
    case JRC16 + 0:
9858 3c824109 Nathan Froyd
    case JRC16 + 1:
9859 3c824109 Nathan Froyd
        {
9860 3c824109 Nathan Froyd
            int reg = ctx->opcode & 0x1f;
9861 3c824109 Nathan Froyd
9862 3c824109 Nathan Froyd
            gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9863 3c824109 Nathan Froyd
            /* Let normal delay slot handling in our caller take us
9864 3c824109 Nathan Froyd
               to the branch target.  */
9865 3c824109 Nathan Froyd
        }
9866 3c824109 Nathan Froyd
        break;
9867 3c824109 Nathan Froyd
    case JALR16 + 0:
9868 3c824109 Nathan Froyd
    case JALR16 + 1:
9869 3c824109 Nathan Froyd
        opc = OPC_JALR;
9870 3c824109 Nathan Froyd
        goto do_jalr;
9871 3c824109 Nathan Froyd
    case JALR16S + 0:
9872 3c824109 Nathan Froyd
    case JALR16S + 1:
9873 3c824109 Nathan Froyd
        opc = OPC_JALRS;
9874 3c824109 Nathan Froyd
    do_jalr:
9875 3c824109 Nathan Froyd
        {
9876 3c824109 Nathan Froyd
            int reg = ctx->opcode & 0x1f;
9877 3c824109 Nathan Froyd
9878 3c824109 Nathan Froyd
            gen_compute_branch(ctx, opc, 2, reg, 31, 0);
9879 3c824109 Nathan Froyd
        }
9880 3c824109 Nathan Froyd
        *is_branch = 1;
9881 3c824109 Nathan Froyd
        break;
9882 3c824109 Nathan Froyd
    case MFHI16 + 0:
9883 3c824109 Nathan Froyd
    case MFHI16 + 1:
9884 3c824109 Nathan Froyd
        gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
9885 3c824109 Nathan Froyd
        break;
9886 3c824109 Nathan Froyd
    case MFLO16 + 0:
9887 3c824109 Nathan Froyd
    case MFLO16 + 1:
9888 3c824109 Nathan Froyd
        gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
9889 3c824109 Nathan Froyd
        break;
9890 3c824109 Nathan Froyd
    case BREAK16:
9891 3c824109 Nathan Froyd
        generate_exception(ctx, EXCP_BREAK);
9892 3c824109 Nathan Froyd
        break;
9893 3c824109 Nathan Froyd
    case SDBBP16:
9894 3c824109 Nathan Froyd
        /* XXX: not clear which exception should be raised
9895 3c824109 Nathan Froyd
         *      when in debug mode...
9896 3c824109 Nathan Froyd
         */
9897 3c824109 Nathan Froyd
        check_insn(env, ctx, ISA_MIPS32);
9898 3c824109 Nathan Froyd
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9899 3c824109 Nathan Froyd
            generate_exception(ctx, EXCP_DBp);
9900 3c824109 Nathan Froyd
        } else {
9901 3c824109 Nathan Froyd
            generate_exception(ctx, EXCP_DBp);
9902 3c824109 Nathan Froyd
        }
9903 3c824109 Nathan Froyd
        break;
9904 3c824109 Nathan Froyd
    case JRADDIUSP + 0:
9905 3c824109 Nathan Froyd
    case JRADDIUSP + 1:
9906 3c824109 Nathan Froyd
        {
9907 3c824109 Nathan Froyd
            int imm = ZIMM(ctx->opcode, 0, 5);
9908 3c824109 Nathan Froyd
9909 3c824109 Nathan Froyd
            gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
9910 3c824109 Nathan Froyd
            gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
9911 3c824109 Nathan Froyd
            /* Let normal delay slot handling in our caller take us
9912 3c824109 Nathan Froyd
               to the branch target.  */
9913 3c824109 Nathan Froyd
        }
9914 3c824109 Nathan Froyd
        break;
9915 3c824109 Nathan Froyd
    default:
9916 3c824109 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
9917 3c824109 Nathan Froyd
        break;
9918 3c824109 Nathan Froyd
    }
9919 3c824109 Nathan Froyd
}
9920 3c824109 Nathan Froyd
9921 3c824109 Nathan Froyd
static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
9922 3c824109 Nathan Froyd
{
9923 3c824109 Nathan Froyd
    TCGv t0 = tcg_temp_new();
9924 3c824109 Nathan Froyd
    TCGv t1 = tcg_temp_new();
9925 3c824109 Nathan Froyd
9926 3c824109 Nathan Froyd
    gen_load_gpr(t0, base);
9927 3c824109 Nathan Froyd
9928 3c824109 Nathan Froyd
    if (index != 0) {
9929 3c824109 Nathan Froyd
        gen_load_gpr(t1, index);
9930 3c824109 Nathan Froyd
        tcg_gen_shli_tl(t1, t1, 2);
9931 3c824109 Nathan Froyd
        gen_op_addr_add(ctx, t0, t1, t0);
9932 3c824109 Nathan Froyd
    }
9933 3c824109 Nathan Froyd
9934 3c824109 Nathan Froyd
    save_cpu_state(ctx, 0);
9935 5c13fdfd Aurelien Jarno
    op_ld_lw(t1, t0, ctx);
9936 3c824109 Nathan Froyd
    gen_store_gpr(t1, rd);
9937 3c824109 Nathan Froyd
9938 3c824109 Nathan Froyd
    tcg_temp_free(t0);
9939 3c824109 Nathan Froyd
    tcg_temp_free(t1);
9940 3c824109 Nathan Froyd
}
9941 3c824109 Nathan Froyd
9942 3c824109 Nathan Froyd
static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
9943 3c824109 Nathan Froyd
                           int base, int16_t offset)
9944 3c824109 Nathan Froyd
{
9945 3c824109 Nathan Froyd
    const char *opn = "ldst_pair";
9946 3c824109 Nathan Froyd
    TCGv t0, t1;
9947 3c824109 Nathan Froyd
9948 3c824109 Nathan Froyd
    if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
9949 3c824109 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
9950 d796321b bellard
        return;
9951 d796321b bellard
    }
9952 d796321b bellard
9953 3c824109 Nathan Froyd
    t0 = tcg_temp_new();
9954 3c824109 Nathan Froyd
    t1 = tcg_temp_new();
9955 8e9ade68 ths
9956 3c824109 Nathan Froyd
    gen_base_offset_addr(ctx, t0, base, offset);
9957 3c824109 Nathan Froyd
9958 3c824109 Nathan Froyd
    switch (opc) {
9959 3c824109 Nathan Froyd
    case LWP:
9960 3c824109 Nathan Froyd
        save_cpu_state(ctx, 0);
9961 5c13fdfd Aurelien Jarno
        op_ld_lw(t1, t0, ctx);
9962 3c824109 Nathan Froyd
        gen_store_gpr(t1, rd);
9963 3c824109 Nathan Froyd
        tcg_gen_movi_tl(t1, 4);
9964 3c824109 Nathan Froyd
        gen_op_addr_add(ctx, t0, t0, t1);
9965 5c13fdfd Aurelien Jarno
        op_ld_lw(t1, t0, ctx);
9966 3c824109 Nathan Froyd
        gen_store_gpr(t1, rd+1);
9967 3c824109 Nathan Froyd
        opn = "lwp";
9968 3c824109 Nathan Froyd
        break;
9969 3c824109 Nathan Froyd
    case SWP:
9970 3c824109 Nathan Froyd
        save_cpu_state(ctx, 1);
9971 3c824109 Nathan Froyd
        gen_load_gpr(t1, rd);
9972 5c13fdfd Aurelien Jarno
        op_st_sw(t1, t0, ctx);
9973 3c824109 Nathan Froyd
        tcg_gen_movi_tl(t1, 4);
9974 3c824109 Nathan Froyd
        gen_op_addr_add(ctx, t0, t0, t1);
9975 3c824109 Nathan Froyd
        gen_load_gpr(t1, rd+1);
9976 5c13fdfd Aurelien Jarno
        op_st_sw(t1, t0, ctx);
9977 3c824109 Nathan Froyd
        opn = "swp";
9978 3c824109 Nathan Froyd
        break;
9979 3c824109 Nathan Froyd
#ifdef TARGET_MIPS64
9980 3c824109 Nathan Froyd
    case LDP:
9981 3c824109 Nathan Froyd
        save_cpu_state(ctx, 0);
9982 5c13fdfd Aurelien Jarno
        op_ld_ld(t1, t0, ctx);
9983 3c824109 Nathan Froyd
        gen_store_gpr(t1, rd);
9984 3c824109 Nathan Froyd
        tcg_gen_movi_tl(t1, 8);
9985 3c824109 Nathan Froyd
        gen_op_addr_add(ctx, t0, t0, t1);
9986 5c13fdfd Aurelien Jarno
        op_ld_ld(t1, t0, ctx);
9987 3c824109 Nathan Froyd
        gen_store_gpr(t1, rd+1);
9988 3c824109 Nathan Froyd
        opn = "ldp";
9989 3c824109 Nathan Froyd
        break;
9990 3c824109 Nathan Froyd
    case SDP:
9991 3c824109 Nathan Froyd
        save_cpu_state(ctx, 1);
9992 3c824109 Nathan Froyd
        gen_load_gpr(t1, rd);
9993 5c13fdfd Aurelien Jarno
        op_st_sd(t1, t0, ctx);
9994 3c824109 Nathan Froyd
        tcg_gen_movi_tl(t1, 8);
9995 3c824109 Nathan Froyd
        gen_op_addr_add(ctx, t0, t0, t1);
9996 3c824109 Nathan Froyd
        gen_load_gpr(t1, rd+1);
9997 5c13fdfd Aurelien Jarno
        op_st_sd(t1, t0, ctx);
9998 3c824109 Nathan Froyd
        opn = "sdp";
9999 3c824109 Nathan Froyd
        break;
10000 3c824109 Nathan Froyd
#endif
10001 6af0bf9c bellard
    }
10002 2abf314d Blue Swirl
    (void)opn; /* avoid a compiler warning */
10003 3c824109 Nathan Froyd
    MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10004 3c824109 Nathan Froyd
    tcg_temp_free(t0);
10005 3c824109 Nathan Froyd
    tcg_temp_free(t1);
10006 3c824109 Nathan Froyd
}
10007 618b0fe9 Aurelien Jarno
10008 3c824109 Nathan Froyd
static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
10009 3c824109 Nathan Froyd
                           int *is_branch)
10010 3c824109 Nathan Froyd
{
10011 3c824109 Nathan Froyd
    int extension = (ctx->opcode >> 6) & 0x3f;
10012 3c824109 Nathan Froyd
    int minor = (ctx->opcode >> 12) & 0xf;
10013 3c824109 Nathan Froyd
    uint32_t mips32_op;
10014 3c824109 Nathan Froyd
10015 3c824109 Nathan Froyd
    switch (extension) {
10016 3c824109 Nathan Froyd
    case TEQ:
10017 3c824109 Nathan Froyd
        mips32_op = OPC_TEQ;
10018 3c824109 Nathan Froyd
        goto do_trap;
10019 3c824109 Nathan Froyd
    case TGE:
10020 3c824109 Nathan Froyd
        mips32_op = OPC_TGE;
10021 3c824109 Nathan Froyd
        goto do_trap;
10022 3c824109 Nathan Froyd
    case TGEU:
10023 3c824109 Nathan Froyd
        mips32_op = OPC_TGEU;
10024 3c824109 Nathan Froyd
        goto do_trap;
10025 3c824109 Nathan Froyd
    case TLT:
10026 3c824109 Nathan Froyd
        mips32_op = OPC_TLT;
10027 3c824109 Nathan Froyd
        goto do_trap;
10028 3c824109 Nathan Froyd
    case TLTU:
10029 3c824109 Nathan Froyd
        mips32_op = OPC_TLTU;
10030 3c824109 Nathan Froyd
        goto do_trap;
10031 3c824109 Nathan Froyd
    case TNE:
10032 3c824109 Nathan Froyd
        mips32_op = OPC_TNE;
10033 3c824109 Nathan Froyd
    do_trap:
10034 3c824109 Nathan Froyd
        gen_trap(ctx, mips32_op, rs, rt, -1);
10035 3c824109 Nathan Froyd
        break;
10036 3c824109 Nathan Froyd
#ifndef CONFIG_USER_ONLY
10037 3c824109 Nathan Froyd
    case MFC0:
10038 3c824109 Nathan Froyd
    case MFC0 + 32:
10039 3c824109 Nathan Froyd
        if (rt == 0) {
10040 3c824109 Nathan Froyd
            /* Treat as NOP. */
10041 3c824109 Nathan Froyd
            break;
10042 3c824109 Nathan Froyd
        }
10043 3c824109 Nathan Froyd
        gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10044 3c824109 Nathan Froyd
        break;
10045 3c824109 Nathan Froyd
    case MTC0:
10046 3c824109 Nathan Froyd
    case MTC0 + 32:
10047 3c824109 Nathan Froyd
        {
10048 3c824109 Nathan Froyd
            TCGv t0 = tcg_temp_new();
10049 618b0fe9 Aurelien Jarno
10050 3c824109 Nathan Froyd
            gen_load_gpr(t0, rt);
10051 3c824109 Nathan Froyd
            gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10052 3c824109 Nathan Froyd
            tcg_temp_free(t0);
10053 3c824109 Nathan Froyd
        }
10054 3c824109 Nathan Froyd
        break;
10055 3c824109 Nathan Froyd
#endif
10056 3c824109 Nathan Froyd
    case 0x2c:
10057 3c824109 Nathan Froyd
        switch (minor) {
10058 3c824109 Nathan Froyd
        case SEB:
10059 3c824109 Nathan Froyd
            gen_bshfl(ctx, OPC_SEB, rs, rt);
10060 3c824109 Nathan Froyd
            break;
10061 3c824109 Nathan Froyd
        case SEH:
10062 3c824109 Nathan Froyd
            gen_bshfl(ctx, OPC_SEH, rs, rt);
10063 3c824109 Nathan Froyd
            break;
10064 3c824109 Nathan Froyd
        case CLO:
10065 3c824109 Nathan Froyd
            mips32_op = OPC_CLO;
10066 3c824109 Nathan Froyd
            goto do_cl;
10067 3c824109 Nathan Froyd
        case CLZ:
10068 3c824109 Nathan Froyd
            mips32_op = OPC_CLZ;
10069 3c824109 Nathan Froyd
        do_cl:
10070 3c824109 Nathan Froyd
            check_insn(env, ctx, ISA_MIPS32);
10071 3c824109 Nathan Froyd
            gen_cl(ctx, mips32_op, rt, rs);
10072 3c824109 Nathan Froyd
            break;
10073 3c824109 Nathan Froyd
        case RDHWR:
10074 3c824109 Nathan Froyd
            gen_rdhwr(env, ctx, rt, rs);
10075 3c824109 Nathan Froyd
            break;
10076 3c824109 Nathan Froyd
        case WSBH:
10077 3c824109 Nathan Froyd
            gen_bshfl(ctx, OPC_WSBH, rs, rt);
10078 3c824109 Nathan Froyd
            break;
10079 3c824109 Nathan Froyd
        case MULT:
10080 3c824109 Nathan Froyd
            mips32_op = OPC_MULT;
10081 3c824109 Nathan Froyd
            goto do_muldiv;
10082 3c824109 Nathan Froyd
        case MULTU:
10083 3c824109 Nathan Froyd
            mips32_op = OPC_MULTU;
10084 3c824109 Nathan Froyd
            goto do_muldiv;
10085 3c824109 Nathan Froyd
        case DIV:
10086 3c824109 Nathan Froyd
            mips32_op = OPC_DIV;
10087 3c824109 Nathan Froyd
            goto do_muldiv;
10088 3c824109 Nathan Froyd
        case DIVU:
10089 3c824109 Nathan Froyd
            mips32_op = OPC_DIVU;
10090 3c824109 Nathan Froyd
            goto do_muldiv;
10091 3c824109 Nathan Froyd
        case MADD:
10092 3c824109 Nathan Froyd
            mips32_op = OPC_MADD;
10093 3c824109 Nathan Froyd
            goto do_muldiv;
10094 3c824109 Nathan Froyd
        case MADDU:
10095 3c824109 Nathan Froyd
            mips32_op = OPC_MADDU;
10096 3c824109 Nathan Froyd
            goto do_muldiv;
10097 3c824109 Nathan Froyd
        case MSUB:
10098 3c824109 Nathan Froyd
            mips32_op = OPC_MSUB;
10099 3c824109 Nathan Froyd
            goto do_muldiv;
10100 3c824109 Nathan Froyd
        case MSUBU:
10101 3c824109 Nathan Froyd
            mips32_op = OPC_MSUBU;
10102 3c824109 Nathan Froyd
        do_muldiv:
10103 3c824109 Nathan Froyd
            check_insn(env, ctx, ISA_MIPS32);
10104 3c824109 Nathan Froyd
            gen_muldiv(ctx, mips32_op, rs, rt);
10105 3c824109 Nathan Froyd
            break;
10106 3c824109 Nathan Froyd
        default:
10107 3c824109 Nathan Froyd
            goto pool32axf_invalid;
10108 3c824109 Nathan Froyd
        }
10109 3c824109 Nathan Froyd
        break;
10110 3c824109 Nathan Froyd
    case 0x34:
10111 3c824109 Nathan Froyd
        switch (minor) {
10112 3c824109 Nathan Froyd
        case MFC2:
10113 3c824109 Nathan Froyd
        case MTC2:
10114 3c824109 Nathan Froyd
        case MFHC2:
10115 3c824109 Nathan Froyd
        case MTHC2:
10116 3c824109 Nathan Froyd
        case CFC2:
10117 3c824109 Nathan Froyd
        case CTC2:
10118 3c824109 Nathan Froyd
            generate_exception_err(ctx, EXCP_CpU, 2);
10119 3c824109 Nathan Froyd
            break;
10120 3c824109 Nathan Froyd
        default:
10121 3c824109 Nathan Froyd
            goto pool32axf_invalid;
10122 3c824109 Nathan Froyd
        }
10123 3c824109 Nathan Froyd
        break;
10124 3c824109 Nathan Froyd
    case 0x3c:
10125 3c824109 Nathan Froyd
        switch (minor) {
10126 3c824109 Nathan Froyd
        case JALR:
10127 3c824109 Nathan Froyd
        case JALR_HB:
10128 3c824109 Nathan Froyd
            gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10129 3c824109 Nathan Froyd
            *is_branch = 1;
10130 3c824109 Nathan Froyd
            break;
10131 3c824109 Nathan Froyd
        case JALRS:
10132 3c824109 Nathan Froyd
        case JALRS_HB:
10133 3c824109 Nathan Froyd
            gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10134 3c824109 Nathan Froyd
            *is_branch = 1;
10135 3c824109 Nathan Froyd
            break;
10136 3c824109 Nathan Froyd
        default:
10137 3c824109 Nathan Froyd
            goto pool32axf_invalid;
10138 3c824109 Nathan Froyd
        }
10139 3c824109 Nathan Froyd
        break;
10140 3c824109 Nathan Froyd
    case 0x05:
10141 3c824109 Nathan Froyd
        switch (minor) {
10142 3c824109 Nathan Froyd
        case RDPGPR:
10143 3c824109 Nathan Froyd
            check_insn(env, ctx, ISA_MIPS32R2);
10144 3c824109 Nathan Froyd
            gen_load_srsgpr(rt, rs);
10145 3c824109 Nathan Froyd
            break;
10146 3c824109 Nathan Froyd
        case WRPGPR:
10147 3c824109 Nathan Froyd
            check_insn(env, ctx, ISA_MIPS32R2);
10148 3c824109 Nathan Froyd
            gen_store_srsgpr(rt, rs);
10149 3c824109 Nathan Froyd
            break;
10150 3c824109 Nathan Froyd
        default:
10151 3c824109 Nathan Froyd
            goto pool32axf_invalid;
10152 3c824109 Nathan Froyd
        }
10153 3c824109 Nathan Froyd
        break;
10154 3c824109 Nathan Froyd
#ifndef CONFIG_USER_ONLY
10155 3c824109 Nathan Froyd
    case 0x0d:
10156 3c824109 Nathan Froyd
        switch (minor) {
10157 3c824109 Nathan Froyd
        case TLBP:
10158 3c824109 Nathan Froyd
            mips32_op = OPC_TLBP;
10159 3c824109 Nathan Froyd
            goto do_cp0;
10160 3c824109 Nathan Froyd
        case TLBR:
10161 3c824109 Nathan Froyd
            mips32_op = OPC_TLBR;
10162 3c824109 Nathan Froyd
            goto do_cp0;
10163 3c824109 Nathan Froyd
        case TLBWI:
10164 3c824109 Nathan Froyd
            mips32_op = OPC_TLBWI;
10165 3c824109 Nathan Froyd
            goto do_cp0;
10166 3c824109 Nathan Froyd
        case TLBWR:
10167 3c824109 Nathan Froyd
            mips32_op = OPC_TLBWR;
10168 3c824109 Nathan Froyd
            goto do_cp0;
10169 3c824109 Nathan Froyd
        case WAIT:
10170 3c824109 Nathan Froyd
            mips32_op = OPC_WAIT;
10171 3c824109 Nathan Froyd
            goto do_cp0;
10172 3c824109 Nathan Froyd
        case DERET:
10173 3c824109 Nathan Froyd
            mips32_op = OPC_DERET;
10174 3c824109 Nathan Froyd
            goto do_cp0;
10175 3c824109 Nathan Froyd
        case ERET:
10176 3c824109 Nathan Froyd
            mips32_op = OPC_ERET;
10177 3c824109 Nathan Froyd
        do_cp0:
10178 3c824109 Nathan Froyd
            gen_cp0(env, ctx, mips32_op, rt, rs);
10179 3c824109 Nathan Froyd
            break;
10180 3c824109 Nathan Froyd
        default:
10181 3c824109 Nathan Froyd
            goto pool32axf_invalid;
10182 3c824109 Nathan Froyd
        }
10183 3c824109 Nathan Froyd
        break;
10184 3c824109 Nathan Froyd
    case 0x1d:
10185 3c824109 Nathan Froyd
        switch (minor) {
10186 3c824109 Nathan Froyd
        case DI:
10187 3c824109 Nathan Froyd
            {
10188 3c824109 Nathan Froyd
                TCGv t0 = tcg_temp_new();
10189 3c824109 Nathan Froyd
10190 3c824109 Nathan Froyd
                save_cpu_state(ctx, 1);
10191 3c824109 Nathan Froyd
                gen_helper_di(t0);
10192 3c824109 Nathan Froyd
                gen_store_gpr(t0, rs);
10193 3c824109 Nathan Froyd
                /* Stop translation as we may have switched the execution mode */
10194 3c824109 Nathan Froyd
                ctx->bstate = BS_STOP;
10195 3c824109 Nathan Froyd
                tcg_temp_free(t0);
10196 3c824109 Nathan Froyd
            }
10197 3c824109 Nathan Froyd
            break;
10198 3c824109 Nathan Froyd
        case EI:
10199 3c824109 Nathan Froyd
            {
10200 3c824109 Nathan Froyd
                TCGv t0 = tcg_temp_new();
10201 3c824109 Nathan Froyd
10202 3c824109 Nathan Froyd
                save_cpu_state(ctx, 1);
10203 3c824109 Nathan Froyd
                gen_helper_ei(t0);
10204 3c824109 Nathan Froyd
                gen_store_gpr(t0, rs);
10205 3c824109 Nathan Froyd
                /* Stop translation as we may have switched the execution mode */
10206 3c824109 Nathan Froyd
                ctx->bstate = BS_STOP;
10207 3c824109 Nathan Froyd
                tcg_temp_free(t0);
10208 3c824109 Nathan Froyd
            }
10209 3c824109 Nathan Froyd
            break;
10210 3c824109 Nathan Froyd
        default:
10211 3c824109 Nathan Froyd
            goto pool32axf_invalid;
10212 3c824109 Nathan Froyd
        }
10213 3c824109 Nathan Froyd
        break;
10214 3c824109 Nathan Froyd
#endif
10215 3c824109 Nathan Froyd
    case 0x2d:
10216 3c824109 Nathan Froyd
        switch (minor) {
10217 3c824109 Nathan Froyd
        case SYNC:
10218 3c824109 Nathan Froyd
            /* NOP */
10219 3c824109 Nathan Froyd
            break;
10220 3c824109 Nathan Froyd
        case SYSCALL:
10221 3c824109 Nathan Froyd
            generate_exception(ctx, EXCP_SYSCALL);
10222 3c824109 Nathan Froyd
            ctx->bstate = BS_STOP;
10223 3c824109 Nathan Froyd
            break;
10224 3c824109 Nathan Froyd
        case SDBBP:
10225 3c824109 Nathan Froyd
            check_insn(env, ctx, ISA_MIPS32);
10226 3c824109 Nathan Froyd
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10227 3c824109 Nathan Froyd
                generate_exception(ctx, EXCP_DBp);
10228 3c824109 Nathan Froyd
            } else {
10229 3c824109 Nathan Froyd
                generate_exception(ctx, EXCP_DBp);
10230 3c824109 Nathan Froyd
            }
10231 3c824109 Nathan Froyd
            break;
10232 3c824109 Nathan Froyd
        default:
10233 3c824109 Nathan Froyd
            goto pool32axf_invalid;
10234 3c824109 Nathan Froyd
        }
10235 3c824109 Nathan Froyd
        break;
10236 3c824109 Nathan Froyd
    case 0x35:
10237 3c824109 Nathan Froyd
        switch (minor) {
10238 3c824109 Nathan Froyd
        case MFHI32:
10239 3c824109 Nathan Froyd
            gen_HILO(ctx, OPC_MFHI, rs);
10240 3c824109 Nathan Froyd
            break;
10241 3c824109 Nathan Froyd
        case MFLO32:
10242 3c824109 Nathan Froyd
            gen_HILO(ctx, OPC_MFLO, rs);
10243 3c824109 Nathan Froyd
            break;
10244 3c824109 Nathan Froyd
        case MTHI32:
10245 3c824109 Nathan Froyd
            gen_HILO(ctx, OPC_MTHI, rs);
10246 3c824109 Nathan Froyd
            break;
10247 3c824109 Nathan Froyd
        case MTLO32:
10248 3c824109 Nathan Froyd
            gen_HILO(ctx, OPC_MTLO, rs);
10249 3c824109 Nathan Froyd
            break;
10250 3c824109 Nathan Froyd
        default:
10251 3c824109 Nathan Froyd
            goto pool32axf_invalid;
10252 3c824109 Nathan Froyd
        }
10253 3c824109 Nathan Froyd
        break;
10254 3c824109 Nathan Froyd
    default:
10255 3c824109 Nathan Froyd
    pool32axf_invalid:
10256 3c824109 Nathan Froyd
        MIPS_INVAL("pool32axf");
10257 3c824109 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
10258 3c824109 Nathan Froyd
        break;
10259 3c824109 Nathan Froyd
    }
10260 3c824109 Nathan Froyd
}
10261 3c824109 Nathan Froyd
10262 3c824109 Nathan Froyd
/* Values for microMIPS fmt field.  Variable-width, depending on which
10263 3c824109 Nathan Froyd
   formats the instruction supports.  */
10264 3c824109 Nathan Froyd
10265 3c824109 Nathan Froyd
enum {
10266 3c824109 Nathan Froyd
    FMT_SD_S = 0,
10267 3c824109 Nathan Froyd
    FMT_SD_D = 1,
10268 3c824109 Nathan Froyd
10269 3c824109 Nathan Froyd
    FMT_SDPS_S = 0,
10270 3c824109 Nathan Froyd
    FMT_SDPS_D = 1,
10271 3c824109 Nathan Froyd
    FMT_SDPS_PS = 2,
10272 3c824109 Nathan Froyd
10273 3c824109 Nathan Froyd
    FMT_SWL_S = 0,
10274 3c824109 Nathan Froyd
    FMT_SWL_W = 1,
10275 3c824109 Nathan Froyd
    FMT_SWL_L = 2,
10276 3c824109 Nathan Froyd
10277 3c824109 Nathan Froyd
    FMT_DWL_D = 0,
10278 3c824109 Nathan Froyd
    FMT_DWL_W = 1,
10279 3c824109 Nathan Froyd
    FMT_DWL_L = 2
10280 3c824109 Nathan Froyd
};
10281 3c824109 Nathan Froyd
10282 3c824109 Nathan Froyd
static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
10283 3c824109 Nathan Froyd
{
10284 3c824109 Nathan Froyd
    int extension = (ctx->opcode >> 6) & 0x3ff;
10285 3c824109 Nathan Froyd
    uint32_t mips32_op;
10286 3c824109 Nathan Froyd
10287 3c824109 Nathan Froyd
#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10288 3c824109 Nathan Froyd
#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10289 3c824109 Nathan Froyd
#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10290 3c824109 Nathan Froyd
10291 3c824109 Nathan Froyd
    switch (extension) {
10292 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CFC1, 0):
10293 3c824109 Nathan Froyd
        mips32_op = OPC_CFC1;
10294 3c824109 Nathan Froyd
        goto do_cp1;
10295 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CTC1, 0):
10296 3c824109 Nathan Froyd
        mips32_op = OPC_CTC1;
10297 3c824109 Nathan Froyd
        goto do_cp1;
10298 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(MFC1, 0):
10299 3c824109 Nathan Froyd
        mips32_op = OPC_MFC1;
10300 3c824109 Nathan Froyd
        goto do_cp1;
10301 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(MTC1, 0):
10302 3c824109 Nathan Froyd
        mips32_op = OPC_MTC1;
10303 3c824109 Nathan Froyd
        goto do_cp1;
10304 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(MFHC1, 0):
10305 3c824109 Nathan Froyd
        mips32_op = OPC_MFHC1;
10306 3c824109 Nathan Froyd
        goto do_cp1;
10307 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(MTHC1, 0):
10308 3c824109 Nathan Froyd
        mips32_op = OPC_MTHC1;
10309 3c824109 Nathan Froyd
    do_cp1:
10310 3c824109 Nathan Froyd
        gen_cp1(ctx, mips32_op, rt, rs);
10311 3c824109 Nathan Froyd
        break;
10312 3c824109 Nathan Froyd
10313 3c824109 Nathan Froyd
        /* Reciprocal square root */
10314 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10315 3c824109 Nathan Froyd
        mips32_op = OPC_RSQRT_S;
10316 3c824109 Nathan Froyd
        goto do_unaryfp;
10317 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10318 3c824109 Nathan Froyd
        mips32_op = OPC_RSQRT_D;
10319 3c824109 Nathan Froyd
        goto do_unaryfp;
10320 3c824109 Nathan Froyd
10321 3c824109 Nathan Froyd
        /* Square root */
10322 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10323 3c824109 Nathan Froyd
        mips32_op = OPC_SQRT_S;
10324 3c824109 Nathan Froyd
        goto do_unaryfp;
10325 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10326 3c824109 Nathan Froyd
        mips32_op = OPC_SQRT_D;
10327 3c824109 Nathan Froyd
        goto do_unaryfp;
10328 3c824109 Nathan Froyd
10329 3c824109 Nathan Froyd
        /* Reciprocal */
10330 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10331 3c824109 Nathan Froyd
        mips32_op = OPC_RECIP_S;
10332 3c824109 Nathan Froyd
        goto do_unaryfp;
10333 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10334 3c824109 Nathan Froyd
        mips32_op = OPC_RECIP_D;
10335 3c824109 Nathan Froyd
        goto do_unaryfp;
10336 3c824109 Nathan Froyd
10337 3c824109 Nathan Froyd
        /* Floor */
10338 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10339 3c824109 Nathan Froyd
        mips32_op = OPC_FLOOR_L_S;
10340 3c824109 Nathan Froyd
        goto do_unaryfp;
10341 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10342 3c824109 Nathan Froyd
        mips32_op = OPC_FLOOR_L_D;
10343 3c824109 Nathan Froyd
        goto do_unaryfp;
10344 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10345 3c824109 Nathan Froyd
        mips32_op = OPC_FLOOR_W_S;
10346 3c824109 Nathan Froyd
        goto do_unaryfp;
10347 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10348 3c824109 Nathan Froyd
        mips32_op = OPC_FLOOR_W_D;
10349 3c824109 Nathan Froyd
        goto do_unaryfp;
10350 3c824109 Nathan Froyd
10351 3c824109 Nathan Froyd
        /* Ceiling */
10352 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10353 3c824109 Nathan Froyd
        mips32_op = OPC_CEIL_L_S;
10354 3c824109 Nathan Froyd
        goto do_unaryfp;
10355 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10356 3c824109 Nathan Froyd
        mips32_op = OPC_CEIL_L_D;
10357 3c824109 Nathan Froyd
        goto do_unaryfp;
10358 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10359 3c824109 Nathan Froyd
        mips32_op = OPC_CEIL_W_S;
10360 3c824109 Nathan Froyd
        goto do_unaryfp;
10361 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10362 3c824109 Nathan Froyd
        mips32_op = OPC_CEIL_W_D;
10363 3c824109 Nathan Froyd
        goto do_unaryfp;
10364 3c824109 Nathan Froyd
10365 3c824109 Nathan Froyd
        /* Truncation */
10366 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10367 3c824109 Nathan Froyd
        mips32_op = OPC_TRUNC_L_S;
10368 3c824109 Nathan Froyd
        goto do_unaryfp;
10369 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10370 3c824109 Nathan Froyd
        mips32_op = OPC_TRUNC_L_D;
10371 3c824109 Nathan Froyd
        goto do_unaryfp;
10372 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10373 3c824109 Nathan Froyd
        mips32_op = OPC_TRUNC_W_S;
10374 3c824109 Nathan Froyd
        goto do_unaryfp;
10375 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10376 3c824109 Nathan Froyd
        mips32_op = OPC_TRUNC_W_D;
10377 3c824109 Nathan Froyd
        goto do_unaryfp;
10378 3c824109 Nathan Froyd
10379 3c824109 Nathan Froyd
        /* Round */
10380 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10381 3c824109 Nathan Froyd
        mips32_op = OPC_ROUND_L_S;
10382 3c824109 Nathan Froyd
        goto do_unaryfp;
10383 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10384 3c824109 Nathan Froyd
        mips32_op = OPC_ROUND_L_D;
10385 3c824109 Nathan Froyd
        goto do_unaryfp;
10386 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10387 3c824109 Nathan Froyd
        mips32_op = OPC_ROUND_W_S;
10388 3c824109 Nathan Froyd
        goto do_unaryfp;
10389 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10390 3c824109 Nathan Froyd
        mips32_op = OPC_ROUND_W_D;
10391 3c824109 Nathan Froyd
        goto do_unaryfp;
10392 3c824109 Nathan Froyd
10393 3c824109 Nathan Froyd
        /* Integer to floating-point conversion */
10394 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10395 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_L_S;
10396 3c824109 Nathan Froyd
        goto do_unaryfp;
10397 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10398 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_L_D;
10399 3c824109 Nathan Froyd
        goto do_unaryfp;
10400 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10401 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_W_S;
10402 3c824109 Nathan Froyd
        goto do_unaryfp;
10403 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10404 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_W_D;
10405 3c824109 Nathan Froyd
        goto do_unaryfp;
10406 3c824109 Nathan Froyd
10407 3c824109 Nathan Froyd
        /* Paired-foo conversions */
10408 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10409 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_S_PL;
10410 3c824109 Nathan Froyd
        goto do_unaryfp;
10411 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10412 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_S_PU;
10413 3c824109 Nathan Froyd
        goto do_unaryfp;
10414 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10415 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_PW_PS;
10416 3c824109 Nathan Froyd
        goto do_unaryfp;
10417 3c824109 Nathan Froyd
    case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10418 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_PS_PW;
10419 3c824109 Nathan Froyd
        goto do_unaryfp;
10420 3c824109 Nathan Froyd
10421 3c824109 Nathan Froyd
        /* Floating-point moves */
10422 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10423 3c824109 Nathan Froyd
        mips32_op = OPC_MOV_S;
10424 3c824109 Nathan Froyd
        goto do_unaryfp;
10425 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10426 3c824109 Nathan Froyd
        mips32_op = OPC_MOV_D;
10427 3c824109 Nathan Froyd
        goto do_unaryfp;
10428 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10429 3c824109 Nathan Froyd
        mips32_op = OPC_MOV_PS;
10430 3c824109 Nathan Froyd
        goto do_unaryfp;
10431 3c824109 Nathan Froyd
10432 3c824109 Nathan Froyd
        /* Absolute value */
10433 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10434 3c824109 Nathan Froyd
        mips32_op = OPC_ABS_S;
10435 3c824109 Nathan Froyd
        goto do_unaryfp;
10436 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10437 3c824109 Nathan Froyd
        mips32_op = OPC_ABS_D;
10438 3c824109 Nathan Froyd
        goto do_unaryfp;
10439 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10440 3c824109 Nathan Froyd
        mips32_op = OPC_ABS_PS;
10441 3c824109 Nathan Froyd
        goto do_unaryfp;
10442 3c824109 Nathan Froyd
10443 3c824109 Nathan Froyd
        /* Negation */
10444 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10445 3c824109 Nathan Froyd
        mips32_op = OPC_NEG_S;
10446 3c824109 Nathan Froyd
        goto do_unaryfp;
10447 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10448 3c824109 Nathan Froyd
        mips32_op = OPC_NEG_D;
10449 3c824109 Nathan Froyd
        goto do_unaryfp;
10450 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10451 3c824109 Nathan Froyd
        mips32_op = OPC_NEG_PS;
10452 3c824109 Nathan Froyd
        goto do_unaryfp;
10453 3c824109 Nathan Froyd
10454 3c824109 Nathan Froyd
        /* Reciprocal square root step */
10455 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10456 3c824109 Nathan Froyd
        mips32_op = OPC_RSQRT1_S;
10457 3c824109 Nathan Froyd
        goto do_unaryfp;
10458 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10459 3c824109 Nathan Froyd
        mips32_op = OPC_RSQRT1_D;
10460 3c824109 Nathan Froyd
        goto do_unaryfp;
10461 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10462 3c824109 Nathan Froyd
        mips32_op = OPC_RSQRT1_PS;
10463 3c824109 Nathan Froyd
        goto do_unaryfp;
10464 3c824109 Nathan Froyd
10465 3c824109 Nathan Froyd
        /* Reciprocal step */
10466 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10467 3c824109 Nathan Froyd
        mips32_op = OPC_RECIP1_S;
10468 3c824109 Nathan Froyd
        goto do_unaryfp;
10469 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10470 3c824109 Nathan Froyd
        mips32_op = OPC_RECIP1_S;
10471 3c824109 Nathan Froyd
        goto do_unaryfp;
10472 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10473 3c824109 Nathan Froyd
        mips32_op = OPC_RECIP1_PS;
10474 3c824109 Nathan Froyd
        goto do_unaryfp;
10475 3c824109 Nathan Froyd
10476 3c824109 Nathan Froyd
        /* Conversions from double */
10477 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10478 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_D_S;
10479 3c824109 Nathan Froyd
        goto do_unaryfp;
10480 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10481 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_D_W;
10482 3c824109 Nathan Froyd
        goto do_unaryfp;
10483 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10484 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_D_L;
10485 3c824109 Nathan Froyd
        goto do_unaryfp;
10486 3c824109 Nathan Froyd
10487 3c824109 Nathan Froyd
        /* Conversions from single */
10488 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10489 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_S_D;
10490 3c824109 Nathan Froyd
        goto do_unaryfp;
10491 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10492 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_S_W;
10493 3c824109 Nathan Froyd
        goto do_unaryfp;
10494 3c824109 Nathan Froyd
    case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10495 3c824109 Nathan Froyd
        mips32_op = OPC_CVT_S_L;
10496 3c824109 Nathan Froyd
    do_unaryfp:
10497 3c824109 Nathan Froyd
        gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10498 3c824109 Nathan Froyd
        break;
10499 3c824109 Nathan Froyd
10500 3c824109 Nathan Froyd
        /* Conditional moves on floating-point codes */
10501 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVT, 0):
10502 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVT, 1):
10503 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVT, 2):
10504 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVT, 3):
10505 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVT, 4):
10506 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVT, 5):
10507 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVT, 6):
10508 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVT, 7):
10509 3c824109 Nathan Froyd
        gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
10510 3c824109 Nathan Froyd
        break;
10511 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVF, 0):
10512 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVF, 1):
10513 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVF, 2):
10514 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVF, 3):
10515 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVF, 4):
10516 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVF, 5):
10517 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVF, 6):
10518 3c824109 Nathan Froyd
    case COND_FLOAT_MOV(MOVF, 7):
10519 3c824109 Nathan Froyd
        gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
10520 3c824109 Nathan Froyd
        break;
10521 3c824109 Nathan Froyd
    default:
10522 3c824109 Nathan Froyd
        MIPS_INVAL("pool32fxf");
10523 3c824109 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
10524 3c824109 Nathan Froyd
        break;
10525 3c824109 Nathan Froyd
    }
10526 3c824109 Nathan Froyd
}
10527 3c824109 Nathan Froyd
10528 3c824109 Nathan Froyd
static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
10529 3c824109 Nathan Froyd
                                    uint16_t insn_hw1, int *is_branch)
10530 3c824109 Nathan Froyd
{
10531 3c824109 Nathan Froyd
    int32_t offset;
10532 3c824109 Nathan Froyd
    uint16_t insn;
10533 3c824109 Nathan Froyd
    int rt, rs, rd, rr;
10534 3c824109 Nathan Froyd
    int16_t imm;
10535 3c824109 Nathan Froyd
    uint32_t op, minor, mips32_op;
10536 3c824109 Nathan Froyd
    uint32_t cond, fmt, cc;
10537 3c824109 Nathan Froyd
10538 3c824109 Nathan Froyd
    insn = lduw_code(ctx->pc + 2);
10539 3c824109 Nathan Froyd
    ctx->opcode = (ctx->opcode << 16) | insn;
10540 3c824109 Nathan Froyd
10541 3c824109 Nathan Froyd
    rt = (ctx->opcode >> 21) & 0x1f;
10542 3c824109 Nathan Froyd
    rs = (ctx->opcode >> 16) & 0x1f;
10543 3c824109 Nathan Froyd
    rd = (ctx->opcode >> 11) & 0x1f;
10544 3c824109 Nathan Froyd
    rr = (ctx->opcode >> 6) & 0x1f;
10545 3c824109 Nathan Froyd
    imm = (int16_t) ctx->opcode;
10546 3c824109 Nathan Froyd
10547 3c824109 Nathan Froyd
    op = (ctx->opcode >> 26) & 0x3f;
10548 3c824109 Nathan Froyd
    switch (op) {
10549 3c824109 Nathan Froyd
    case POOL32A:
10550 3c824109 Nathan Froyd
        minor = ctx->opcode & 0x3f;
10551 3c824109 Nathan Froyd
        switch (minor) {
10552 3c824109 Nathan Froyd
        case 0x00:
10553 3c824109 Nathan Froyd
            minor = (ctx->opcode >> 6) & 0xf;
10554 3c824109 Nathan Froyd
            switch (minor) {
10555 3c824109 Nathan Froyd
            case SLL32:
10556 3c824109 Nathan Froyd
                mips32_op = OPC_SLL;
10557 3c824109 Nathan Froyd
                goto do_shifti;
10558 3c824109 Nathan Froyd
            case SRA:
10559 3c824109 Nathan Froyd
                mips32_op = OPC_SRA;
10560 3c824109 Nathan Froyd
                goto do_shifti;
10561 3c824109 Nathan Froyd
            case SRL32:
10562 3c824109 Nathan Froyd
                mips32_op = OPC_SRL;
10563 3c824109 Nathan Froyd
                goto do_shifti;
10564 3c824109 Nathan Froyd
            case ROTR:
10565 3c824109 Nathan Froyd
                mips32_op = OPC_ROTR;
10566 3c824109 Nathan Froyd
            do_shifti:
10567 3c824109 Nathan Froyd
                gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
10568 3c824109 Nathan Froyd
                break;
10569 3c824109 Nathan Froyd
            default:
10570 3c824109 Nathan Froyd
                goto pool32a_invalid;
10571 3c824109 Nathan Froyd
            }
10572 3c824109 Nathan Froyd
            break;
10573 3c824109 Nathan Froyd
        case 0x10:
10574 3c824109 Nathan Froyd
            minor = (ctx->opcode >> 6) & 0xf;
10575 3c824109 Nathan Froyd
            switch (minor) {
10576 3c824109 Nathan Froyd
                /* Arithmetic */
10577 3c824109 Nathan Froyd
            case ADD:
10578 3c824109 Nathan Froyd
                mips32_op = OPC_ADD;
10579 3c824109 Nathan Froyd
                goto do_arith;
10580 3c824109 Nathan Froyd
            case ADDU32:
10581 3c824109 Nathan Froyd
                mips32_op = OPC_ADDU;
10582 3c824109 Nathan Froyd
                goto do_arith;
10583 3c824109 Nathan Froyd
            case SUB:
10584 3c824109 Nathan Froyd
                mips32_op = OPC_SUB;
10585 3c824109 Nathan Froyd
                goto do_arith;
10586 3c824109 Nathan Froyd
            case SUBU32:
10587 3c824109 Nathan Froyd
                mips32_op = OPC_SUBU;
10588 3c824109 Nathan Froyd
                goto do_arith;
10589 3c824109 Nathan Froyd
            case MUL:
10590 3c824109 Nathan Froyd
                mips32_op = OPC_MUL;
10591 3c824109 Nathan Froyd
            do_arith:
10592 3c824109 Nathan Froyd
                gen_arith(env, ctx, mips32_op, rd, rs, rt);
10593 3c824109 Nathan Froyd
                break;
10594 3c824109 Nathan Froyd
                /* Shifts */
10595 3c824109 Nathan Froyd
            case SLLV:
10596 3c824109 Nathan Froyd
                mips32_op = OPC_SLLV;
10597 3c824109 Nathan Froyd
                goto do_shift;
10598 3c824109 Nathan Froyd
            case SRLV:
10599 3c824109 Nathan Froyd
                mips32_op = OPC_SRLV;
10600 3c824109 Nathan Froyd
                goto do_shift;
10601 3c824109 Nathan Froyd
            case SRAV:
10602 3c824109 Nathan Froyd
                mips32_op = OPC_SRAV;
10603 3c824109 Nathan Froyd
                goto do_shift;
10604 3c824109 Nathan Froyd
            case ROTRV:
10605 3c824109 Nathan Froyd
                mips32_op = OPC_ROTRV;
10606 3c824109 Nathan Froyd
            do_shift:
10607 3c824109 Nathan Froyd
                gen_shift(env, ctx, mips32_op, rd, rs, rt);
10608 3c824109 Nathan Froyd
                break;
10609 3c824109 Nathan Froyd
                /* Logical operations */
10610 3c824109 Nathan Froyd
            case AND:
10611 3c824109 Nathan Froyd
                mips32_op = OPC_AND;
10612 3c824109 Nathan Froyd
                goto do_logic;
10613 3c824109 Nathan Froyd
            case OR32:
10614 3c824109 Nathan Froyd
                mips32_op = OPC_OR;
10615 3c824109 Nathan Froyd
                goto do_logic;
10616 3c824109 Nathan Froyd
            case NOR:
10617 3c824109 Nathan Froyd
                mips32_op = OPC_NOR;
10618 3c824109 Nathan Froyd
                goto do_logic;
10619 3c824109 Nathan Froyd
            case XOR32:
10620 3c824109 Nathan Froyd
                mips32_op = OPC_XOR;
10621 3c824109 Nathan Froyd
            do_logic:
10622 3c824109 Nathan Froyd
                gen_logic(env, mips32_op, rd, rs, rt);
10623 3c824109 Nathan Froyd
                break;
10624 3c824109 Nathan Froyd
                /* Set less than */
10625 3c824109 Nathan Froyd
            case SLT:
10626 3c824109 Nathan Froyd
                mips32_op = OPC_SLT;
10627 3c824109 Nathan Froyd
                goto do_slt;
10628 3c824109 Nathan Froyd
            case SLTU:
10629 3c824109 Nathan Froyd
                mips32_op = OPC_SLTU;
10630 3c824109 Nathan Froyd
            do_slt:
10631 3c824109 Nathan Froyd
                gen_slt(env, mips32_op, rd, rs, rt);
10632 3c824109 Nathan Froyd
                break;
10633 3c824109 Nathan Froyd
            default:
10634 3c824109 Nathan Froyd
                goto pool32a_invalid;
10635 3c824109 Nathan Froyd
            }
10636 3c824109 Nathan Froyd
            break;
10637 3c824109 Nathan Froyd
        case 0x18:
10638 3c824109 Nathan Froyd
            minor = (ctx->opcode >> 6) & 0xf;
10639 3c824109 Nathan Froyd
            switch (minor) {
10640 3c824109 Nathan Froyd
                /* Conditional moves */
10641 3c824109 Nathan Froyd
            case MOVN:
10642 3c824109 Nathan Froyd
                mips32_op = OPC_MOVN;
10643 3c824109 Nathan Froyd
                goto do_cmov;
10644 3c824109 Nathan Froyd
            case MOVZ:
10645 3c824109 Nathan Froyd
                mips32_op = OPC_MOVZ;
10646 3c824109 Nathan Froyd
            do_cmov:
10647 3c824109 Nathan Froyd
                gen_cond_move(env, mips32_op, rd, rs, rt);
10648 3c824109 Nathan Froyd
                break;
10649 3c824109 Nathan Froyd
            case LWXS:
10650 3c824109 Nathan Froyd
                gen_ldxs(ctx, rs, rt, rd);
10651 3c824109 Nathan Froyd
                break;
10652 3c824109 Nathan Froyd
            default:
10653 3c824109 Nathan Froyd
                goto pool32a_invalid;
10654 3c824109 Nathan Froyd
            }
10655 3c824109 Nathan Froyd
            break;
10656 3c824109 Nathan Froyd
        case INS:
10657 3c824109 Nathan Froyd
            gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
10658 3c824109 Nathan Froyd
            return;
10659 3c824109 Nathan Froyd
        case EXT:
10660 3c824109 Nathan Froyd
            gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
10661 3c824109 Nathan Froyd
            return;
10662 3c824109 Nathan Froyd
        case POOL32AXF:
10663 3c824109 Nathan Froyd
            gen_pool32axf(env, ctx, rt, rs, is_branch);
10664 3c824109 Nathan Froyd
            break;
10665 3c824109 Nathan Froyd
        case 0x07:
10666 3c824109 Nathan Froyd
            generate_exception(ctx, EXCP_BREAK);
10667 3c824109 Nathan Froyd
            break;
10668 3c824109 Nathan Froyd
        default:
10669 3c824109 Nathan Froyd
        pool32a_invalid:
10670 3c824109 Nathan Froyd
                MIPS_INVAL("pool32a");
10671 3c824109 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
10672 3c824109 Nathan Froyd
                break;
10673 3c824109 Nathan Froyd
        }
10674 3c824109 Nathan Froyd
        break;
10675 3c824109 Nathan Froyd
    case POOL32B:
10676 3c824109 Nathan Froyd
        minor = (ctx->opcode >> 12) & 0xf;
10677 3c824109 Nathan Froyd
        switch (minor) {
10678 3c824109 Nathan Froyd
        case CACHE:
10679 3c824109 Nathan Froyd
            /* Treat as no-op. */
10680 3c824109 Nathan Froyd
            break;
10681 3c824109 Nathan Froyd
        case LWC2:
10682 3c824109 Nathan Froyd
        case SWC2:
10683 3c824109 Nathan Froyd
            /* COP2: Not implemented. */
10684 3c824109 Nathan Froyd
            generate_exception_err(ctx, EXCP_CpU, 2);
10685 3c824109 Nathan Froyd
            break;
10686 3c824109 Nathan Froyd
        case LWP:
10687 3c824109 Nathan Froyd
        case SWP:
10688 3c824109 Nathan Froyd
#ifdef TARGET_MIPS64
10689 3c824109 Nathan Froyd
        case LDP:
10690 3c824109 Nathan Froyd
        case SDP:
10691 3c824109 Nathan Froyd
#endif
10692 3c824109 Nathan Froyd
            gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10693 3c824109 Nathan Froyd
            break;
10694 3c824109 Nathan Froyd
        case LWM32:
10695 3c824109 Nathan Froyd
        case SWM32:
10696 3c824109 Nathan Froyd
#ifdef TARGET_MIPS64
10697 3c824109 Nathan Froyd
        case LDM:
10698 3c824109 Nathan Froyd
        case SDM:
10699 3c824109 Nathan Froyd
#endif
10700 3c824109 Nathan Froyd
            gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10701 3c824109 Nathan Froyd
            break;
10702 3c824109 Nathan Froyd
        default:
10703 3c824109 Nathan Froyd
            MIPS_INVAL("pool32b");
10704 3c824109 Nathan Froyd
            generate_exception(ctx, EXCP_RI);
10705 3c824109 Nathan Froyd
            break;
10706 3c824109 Nathan Froyd
        }
10707 3c824109 Nathan Froyd
        break;
10708 3c824109 Nathan Froyd
    case POOL32F:
10709 3c824109 Nathan Froyd
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
10710 3c824109 Nathan Froyd
            minor = ctx->opcode & 0x3f;
10711 3c824109 Nathan Froyd
            check_cp1_enabled(ctx);
10712 3c824109 Nathan Froyd
            switch (minor) {
10713 3c824109 Nathan Froyd
            case ALNV_PS:
10714 3c824109 Nathan Froyd
                mips32_op = OPC_ALNV_PS;
10715 3c824109 Nathan Froyd
                goto do_madd;
10716 3c824109 Nathan Froyd
            case MADD_S:
10717 3c824109 Nathan Froyd
                mips32_op = OPC_MADD_S;
10718 3c824109 Nathan Froyd
                goto do_madd;
10719 3c824109 Nathan Froyd
            case MADD_D:
10720 3c824109 Nathan Froyd
                mips32_op = OPC_MADD_D;
10721 3c824109 Nathan Froyd
                goto do_madd;
10722 3c824109 Nathan Froyd
            case MADD_PS:
10723 3c824109 Nathan Froyd
                mips32_op = OPC_MADD_PS;
10724 3c824109 Nathan Froyd
                goto do_madd;
10725 3c824109 Nathan Froyd
            case MSUB_S:
10726 3c824109 Nathan Froyd
                mips32_op = OPC_MSUB_S;
10727 3c824109 Nathan Froyd
                goto do_madd;
10728 3c824109 Nathan Froyd
            case MSUB_D:
10729 3c824109 Nathan Froyd
                mips32_op = OPC_MSUB_D;
10730 3c824109 Nathan Froyd
                goto do_madd;
10731 3c824109 Nathan Froyd
            case MSUB_PS:
10732 3c824109 Nathan Froyd
                mips32_op = OPC_MSUB_PS;
10733 3c824109 Nathan Froyd
                goto do_madd;
10734 3c824109 Nathan Froyd
            case NMADD_S:
10735 3c824109 Nathan Froyd
                mips32_op = OPC_NMADD_S;
10736 3c824109 Nathan Froyd
                goto do_madd;
10737 3c824109 Nathan Froyd
            case NMADD_D:
10738 3c824109 Nathan Froyd
                mips32_op = OPC_NMADD_D;
10739 3c824109 Nathan Froyd
                goto do_madd;
10740 3c824109 Nathan Froyd
            case NMADD_PS:
10741 3c824109 Nathan Froyd
                mips32_op = OPC_NMADD_PS;
10742 3c824109 Nathan Froyd
                goto do_madd;
10743 3c824109 Nathan Froyd
            case NMSUB_S:
10744 3c824109 Nathan Froyd
                mips32_op = OPC_NMSUB_S;
10745 3c824109 Nathan Froyd
                goto do_madd;
10746 3c824109 Nathan Froyd
            case NMSUB_D:
10747 3c824109 Nathan Froyd
                mips32_op = OPC_NMSUB_D;
10748 3c824109 Nathan Froyd
                goto do_madd;
10749 3c824109 Nathan Froyd
            case NMSUB_PS:
10750 3c824109 Nathan Froyd
                mips32_op = OPC_NMSUB_PS;
10751 3c824109 Nathan Froyd
            do_madd:
10752 3c824109 Nathan Froyd
                gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
10753 3c824109 Nathan Froyd
                break;
10754 3c824109 Nathan Froyd
            case CABS_COND_FMT:
10755 3c824109 Nathan Froyd
                cond = (ctx->opcode >> 6) & 0xf;
10756 3c824109 Nathan Froyd
                cc = (ctx->opcode >> 13) & 0x7;
10757 3c824109 Nathan Froyd
                fmt = (ctx->opcode >> 10) & 0x3;
10758 3c824109 Nathan Froyd
                switch (fmt) {
10759 3c824109 Nathan Froyd
                case 0x0:
10760 3c824109 Nathan Froyd
                    gen_cmpabs_s(ctx, cond, rt, rs, cc);
10761 3c824109 Nathan Froyd
                    break;
10762 3c824109 Nathan Froyd
                case 0x1:
10763 3c824109 Nathan Froyd
                    gen_cmpabs_d(ctx, cond, rt, rs, cc);
10764 3c824109 Nathan Froyd
                    break;
10765 3c824109 Nathan Froyd
                case 0x2:
10766 3c824109 Nathan Froyd
                    gen_cmpabs_ps(ctx, cond, rt, rs, cc);
10767 3c824109 Nathan Froyd
                    break;
10768 3c824109 Nathan Froyd
                default:
10769 3c824109 Nathan Froyd
                    goto pool32f_invalid;
10770 3c824109 Nathan Froyd
                }
10771 3c824109 Nathan Froyd
                break;
10772 3c824109 Nathan Froyd
            case C_COND_FMT:
10773 3c824109 Nathan Froyd
                cond = (ctx->opcode >> 6) & 0xf;
10774 3c824109 Nathan Froyd
                cc = (ctx->opcode >> 13) & 0x7;
10775 3c824109 Nathan Froyd
                fmt = (ctx->opcode >> 10) & 0x3;
10776 3c824109 Nathan Froyd
                switch (fmt) {
10777 3c824109 Nathan Froyd
                case 0x0:
10778 3c824109 Nathan Froyd
                    gen_cmp_s(ctx, cond, rt, rs, cc);
10779 3c824109 Nathan Froyd
                    break;
10780 3c824109 Nathan Froyd
                case 0x1:
10781 3c824109 Nathan Froyd
                    gen_cmp_d(ctx, cond, rt, rs, cc);
10782 3c824109 Nathan Froyd
                    break;
10783 3c824109 Nathan Froyd
                case 0x2:
10784 3c824109 Nathan Froyd
                    gen_cmp_ps(ctx, cond, rt, rs, cc);
10785 3c824109 Nathan Froyd
                    break;
10786 3c824109 Nathan Froyd
                default:
10787 3c824109 Nathan Froyd
                    goto pool32f_invalid;
10788 3c824109 Nathan Froyd
                }
10789 3c824109 Nathan Froyd
                break;
10790 3c824109 Nathan Froyd
            case POOL32FXF:
10791 3c824109 Nathan Froyd
                gen_pool32fxf(env, ctx, rt, rs);
10792 3c824109 Nathan Froyd
                break;
10793 3c824109 Nathan Froyd
            case 0x00:
10794 3c824109 Nathan Froyd
                /* PLL foo */
10795 3c824109 Nathan Froyd
                switch ((ctx->opcode >> 6) & 0x7) {
10796 3c824109 Nathan Froyd
                case PLL_PS:
10797 3c824109 Nathan Froyd
                    mips32_op = OPC_PLL_PS;
10798 3c824109 Nathan Froyd
                    goto do_ps;
10799 3c824109 Nathan Froyd
                case PLU_PS:
10800 3c824109 Nathan Froyd
                    mips32_op = OPC_PLU_PS;
10801 3c824109 Nathan Froyd
                    goto do_ps;
10802 3c824109 Nathan Froyd
                case PUL_PS:
10803 3c824109 Nathan Froyd
                    mips32_op = OPC_PUL_PS;
10804 3c824109 Nathan Froyd
                    goto do_ps;
10805 3c824109 Nathan Froyd
                case PUU_PS:
10806 3c824109 Nathan Froyd
                    mips32_op = OPC_PUU_PS;
10807 3c824109 Nathan Froyd
                    goto do_ps;
10808 3c824109 Nathan Froyd
                case CVT_PS_S:
10809 3c824109 Nathan Froyd
                    mips32_op = OPC_CVT_PS_S;
10810 3c824109 Nathan Froyd
                do_ps:
10811 3c824109 Nathan Froyd
                    gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10812 3c824109 Nathan Froyd
                    break;
10813 3c824109 Nathan Froyd
                default:
10814 3c824109 Nathan Froyd
                    goto pool32f_invalid;
10815 3c824109 Nathan Froyd
                }
10816 3c824109 Nathan Froyd
                break;
10817 3c824109 Nathan Froyd
            case 0x08:
10818 3c824109 Nathan Froyd
                /* [LS][WDU]XC1 */
10819 3c824109 Nathan Froyd
                switch ((ctx->opcode >> 6) & 0x7) {
10820 3c824109 Nathan Froyd
                case LWXC1:
10821 3c824109 Nathan Froyd
                    mips32_op = OPC_LWXC1;
10822 3c824109 Nathan Froyd
                    goto do_ldst_cp1;
10823 3c824109 Nathan Froyd
                case SWXC1:
10824 3c824109 Nathan Froyd
                    mips32_op = OPC_SWXC1;
10825 3c824109 Nathan Froyd
                    goto do_ldst_cp1;
10826 3c824109 Nathan Froyd
                case LDXC1:
10827 3c824109 Nathan Froyd
                    mips32_op = OPC_LDXC1;
10828 3c824109 Nathan Froyd
                    goto do_ldst_cp1;
10829 3c824109 Nathan Froyd
                case SDXC1:
10830 3c824109 Nathan Froyd
                    mips32_op = OPC_SDXC1;
10831 3c824109 Nathan Froyd
                    goto do_ldst_cp1;
10832 3c824109 Nathan Froyd
                case LUXC1:
10833 3c824109 Nathan Froyd
                    mips32_op = OPC_LUXC1;
10834 3c824109 Nathan Froyd
                    goto do_ldst_cp1;
10835 3c824109 Nathan Froyd
                case SUXC1:
10836 3c824109 Nathan Froyd
                    mips32_op = OPC_SUXC1;
10837 3c824109 Nathan Froyd
                do_ldst_cp1:
10838 3c824109 Nathan Froyd
                    gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
10839 3c824109 Nathan Froyd
                    break;
10840 3c824109 Nathan Froyd
                default:
10841 3c824109 Nathan Froyd
                    goto pool32f_invalid;
10842 3c824109 Nathan Froyd
                }
10843 3c824109 Nathan Froyd
                break;
10844 3c824109 Nathan Froyd
            case 0x18:
10845 3c824109 Nathan Froyd
                /* 3D insns */
10846 3c824109 Nathan Froyd
                fmt = (ctx->opcode >> 9) & 0x3;
10847 3c824109 Nathan Froyd
                switch ((ctx->opcode >> 6) & 0x7) {
10848 3c824109 Nathan Froyd
                case RSQRT2_FMT:
10849 3c824109 Nathan Froyd
                    switch (fmt) {
10850 3c824109 Nathan Froyd
                    case FMT_SDPS_S:
10851 3c824109 Nathan Froyd
                        mips32_op = OPC_RSQRT2_S;
10852 3c824109 Nathan Froyd
                        goto do_3d;
10853 3c824109 Nathan Froyd
                    case FMT_SDPS_D:
10854 3c824109 Nathan Froyd
                        mips32_op = OPC_RSQRT2_D;
10855 3c824109 Nathan Froyd
                        goto do_3d;
10856 3c824109 Nathan Froyd
                    case FMT_SDPS_PS:
10857 3c824109 Nathan Froyd
                        mips32_op = OPC_RSQRT2_PS;
10858 3c824109 Nathan Froyd
                        goto do_3d;
10859 3c824109 Nathan Froyd
                    default:
10860 3c824109 Nathan Froyd
                        goto pool32f_invalid;
10861 3c824109 Nathan Froyd
                    }
10862 3c824109 Nathan Froyd
                    break;
10863 3c824109 Nathan Froyd
                case RECIP2_FMT:
10864 3c824109 Nathan Froyd
                    switch (fmt) {
10865 3c824109 Nathan Froyd
                    case FMT_SDPS_S:
10866 3c824109 Nathan Froyd
                        mips32_op = OPC_RECIP2_S;
10867 3c824109 Nathan Froyd
                        goto do_3d;
10868 3c824109 Nathan Froyd
                    case FMT_SDPS_D:
10869 3c824109 Nathan Froyd
                        mips32_op = OPC_RECIP2_D;
10870 3c824109 Nathan Froyd
                        goto do_3d;
10871 3c824109 Nathan Froyd
                    case FMT_SDPS_PS:
10872 3c824109 Nathan Froyd
                        mips32_op = OPC_RECIP2_PS;
10873 3c824109 Nathan Froyd
                        goto do_3d;
10874 3c824109 Nathan Froyd
                    default:
10875 3c824109 Nathan Froyd
                        goto pool32f_invalid;
10876 3c824109 Nathan Froyd
                    }
10877 3c824109 Nathan Froyd
                    break;
10878 3c824109 Nathan Froyd
                case ADDR_PS:
10879 3c824109 Nathan Froyd
                    mips32_op = OPC_ADDR_PS;
10880 3c824109 Nathan Froyd
                    goto do_3d;
10881 3c824109 Nathan Froyd
                case MULR_PS:
10882 3c824109 Nathan Froyd
                    mips32_op = OPC_MULR_PS;
10883 3c824109 Nathan Froyd
                do_3d:
10884 3c824109 Nathan Froyd
                    gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10885 3c824109 Nathan Froyd
                    break;
10886 3c824109 Nathan Froyd
                default:
10887 3c824109 Nathan Froyd
                    goto pool32f_invalid;
10888 3c824109 Nathan Froyd
                }
10889 3c824109 Nathan Froyd
                break;
10890 3c824109 Nathan Froyd
            case 0x20:
10891 3c824109 Nathan Froyd
                /* MOV[FT].fmt and PREFX */
10892 3c824109 Nathan Froyd
                cc = (ctx->opcode >> 13) & 0x7;
10893 3c824109 Nathan Froyd
                fmt = (ctx->opcode >> 9) & 0x3;
10894 3c824109 Nathan Froyd
                switch ((ctx->opcode >> 6) & 0x7) {
10895 3c824109 Nathan Froyd
                case MOVF_FMT:
10896 3c824109 Nathan Froyd
                    switch (fmt) {
10897 3c824109 Nathan Froyd
                    case FMT_SDPS_S:
10898 3c824109 Nathan Froyd
                        gen_movcf_s(rs, rt, cc, 0);
10899 3c824109 Nathan Froyd
                        break;
10900 3c824109 Nathan Froyd
                    case FMT_SDPS_D:
10901 3c824109 Nathan Froyd
                        gen_movcf_d(ctx, rs, rt, cc, 0);
10902 3c824109 Nathan Froyd
                        break;
10903 3c824109 Nathan Froyd
                    case FMT_SDPS_PS:
10904 3c824109 Nathan Froyd
                        gen_movcf_ps(rs, rt, cc, 0);
10905 3c824109 Nathan Froyd
                        break;
10906 3c824109 Nathan Froyd
                    default:
10907 3c824109 Nathan Froyd
                        goto pool32f_invalid;
10908 3c824109 Nathan Froyd
                    }
10909 3c824109 Nathan Froyd
                    break;
10910 3c824109 Nathan Froyd
                case MOVT_FMT:
10911 3c824109 Nathan Froyd
                    switch (fmt) {
10912 3c824109 Nathan Froyd
                    case FMT_SDPS_S:
10913 3c824109 Nathan Froyd
                        gen_movcf_s(rs, rt, cc, 1);
10914 3c824109 Nathan Froyd
                        break;
10915 3c824109 Nathan Froyd
                    case FMT_SDPS_D:
10916 3c824109 Nathan Froyd
                        gen_movcf_d(ctx, rs, rt, cc, 1);
10917 3c824109 Nathan Froyd
                        break;
10918 3c824109 Nathan Froyd
                    case FMT_SDPS_PS:
10919 3c824109 Nathan Froyd
                        gen_movcf_ps(rs, rt, cc, 1);
10920 3c824109 Nathan Froyd
                        break;
10921 3c824109 Nathan Froyd
                    default:
10922 3c824109 Nathan Froyd
                        goto pool32f_invalid;
10923 3c824109 Nathan Froyd
                    }
10924 3c824109 Nathan Froyd
                    break;
10925 3c824109 Nathan Froyd
                case PREFX:
10926 3c824109 Nathan Froyd
                    break;
10927 3c824109 Nathan Froyd
                default:
10928 3c824109 Nathan Froyd
                    goto pool32f_invalid;
10929 3c824109 Nathan Froyd
                }
10930 3c824109 Nathan Froyd
                break;
10931 3c824109 Nathan Froyd
#define FINSN_3ARG_SDPS(prfx)                           \
10932 3c824109 Nathan Froyd
                switch ((ctx->opcode >> 8) & 0x3) {     \
10933 3c824109 Nathan Froyd
                case FMT_SDPS_S:                        \
10934 3c824109 Nathan Froyd
                    mips32_op = OPC_##prfx##_S;         \
10935 3c824109 Nathan Froyd
                    goto do_fpop;                       \
10936 3c824109 Nathan Froyd
                case FMT_SDPS_D:                        \
10937 3c824109 Nathan Froyd
                    mips32_op = OPC_##prfx##_D;         \
10938 3c824109 Nathan Froyd
                    goto do_fpop;                       \
10939 3c824109 Nathan Froyd
                case FMT_SDPS_PS:                       \
10940 3c824109 Nathan Froyd
                    mips32_op = OPC_##prfx##_PS;        \
10941 3c824109 Nathan Froyd
                    goto do_fpop;                       \
10942 3c824109 Nathan Froyd
                default:                                \
10943 3c824109 Nathan Froyd
                    goto pool32f_invalid;               \
10944 3c824109 Nathan Froyd
                }
10945 3c824109 Nathan Froyd
            case 0x30:
10946 3c824109 Nathan Froyd
                /* regular FP ops */
10947 3c824109 Nathan Froyd
                switch ((ctx->opcode >> 6) & 0x3) {
10948 3c824109 Nathan Froyd
                case ADD_FMT:
10949 3c824109 Nathan Froyd
                    FINSN_3ARG_SDPS(ADD);
10950 3c824109 Nathan Froyd
                    break;
10951 3c824109 Nathan Froyd
                case SUB_FMT:
10952 3c824109 Nathan Froyd
                    FINSN_3ARG_SDPS(SUB);
10953 3c824109 Nathan Froyd
                    break;
10954 3c824109 Nathan Froyd
                case MUL_FMT:
10955 3c824109 Nathan Froyd
                    FINSN_3ARG_SDPS(MUL);
10956 3c824109 Nathan Froyd
                    break;
10957 3c824109 Nathan Froyd
                case DIV_FMT:
10958 3c824109 Nathan Froyd
                    fmt = (ctx->opcode >> 8) & 0x3;
10959 3c824109 Nathan Froyd
                    if (fmt == 1) {
10960 3c824109 Nathan Froyd
                        mips32_op = OPC_DIV_D;
10961 3c824109 Nathan Froyd
                    } else if (fmt == 0) {
10962 3c824109 Nathan Froyd
                        mips32_op = OPC_DIV_S;
10963 3c824109 Nathan Froyd
                    } else {
10964 3c824109 Nathan Froyd
                        goto pool32f_invalid;
10965 3c824109 Nathan Froyd
                    }
10966 3c824109 Nathan Froyd
                    goto do_fpop;
10967 3c824109 Nathan Froyd
                default:
10968 3c824109 Nathan Froyd
                    goto pool32f_invalid;
10969 3c824109 Nathan Froyd
                }
10970 3c824109 Nathan Froyd
                break;
10971 3c824109 Nathan Froyd
            case 0x38:
10972 3c824109 Nathan Froyd
                /* cmovs */
10973 3c824109 Nathan Froyd
                switch ((ctx->opcode >> 6) & 0x3) {
10974 3c824109 Nathan Froyd
                case MOVN_FMT:
10975 3c824109 Nathan Froyd
                    FINSN_3ARG_SDPS(MOVN);
10976 3c824109 Nathan Froyd
                    break;
10977 3c824109 Nathan Froyd
                case MOVZ_FMT:
10978 3c824109 Nathan Froyd
                    FINSN_3ARG_SDPS(MOVZ);
10979 3c824109 Nathan Froyd
                    break;
10980 3c824109 Nathan Froyd
                default:
10981 3c824109 Nathan Froyd
                    goto pool32f_invalid;
10982 3c824109 Nathan Froyd
                }
10983 3c824109 Nathan Froyd
                break;
10984 3c824109 Nathan Froyd
            do_fpop:
10985 3c824109 Nathan Froyd
                gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10986 3c824109 Nathan Froyd
                break;
10987 3c824109 Nathan Froyd
            default:
10988 3c824109 Nathan Froyd
            pool32f_invalid:
10989 3c824109 Nathan Froyd
                MIPS_INVAL("pool32f");
10990 3c824109 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
10991 3c824109 Nathan Froyd
                break;
10992 3c824109 Nathan Froyd
            }
10993 3c824109 Nathan Froyd
        } else {
10994 3c824109 Nathan Froyd
            generate_exception_err(ctx, EXCP_CpU, 1);
10995 3c824109 Nathan Froyd
        }
10996 3c824109 Nathan Froyd
        break;
10997 3c824109 Nathan Froyd
    case POOL32I:
10998 3c824109 Nathan Froyd
        minor = (ctx->opcode >> 21) & 0x1f;
10999 3c824109 Nathan Froyd
        switch (minor) {
11000 3c824109 Nathan Froyd
        case BLTZ:
11001 3c824109 Nathan Froyd
            mips32_op = OPC_BLTZ;
11002 3c824109 Nathan Froyd
            goto do_branch;
11003 3c824109 Nathan Froyd
        case BLTZAL:
11004 3c824109 Nathan Froyd
            mips32_op = OPC_BLTZAL;
11005 3c824109 Nathan Froyd
            goto do_branch;
11006 3c824109 Nathan Froyd
        case BLTZALS:
11007 3c824109 Nathan Froyd
            mips32_op = OPC_BLTZALS;
11008 3c824109 Nathan Froyd
            goto do_branch;
11009 3c824109 Nathan Froyd
        case BGEZ:
11010 3c824109 Nathan Froyd
            mips32_op = OPC_BGEZ;
11011 3c824109 Nathan Froyd
            goto do_branch;
11012 3c824109 Nathan Froyd
        case BGEZAL:
11013 3c824109 Nathan Froyd
            mips32_op = OPC_BGEZAL;
11014 3c824109 Nathan Froyd
            goto do_branch;
11015 3c824109 Nathan Froyd
        case BGEZALS:
11016 3c824109 Nathan Froyd
            mips32_op = OPC_BGEZALS;
11017 3c824109 Nathan Froyd
            goto do_branch;
11018 3c824109 Nathan Froyd
        case BLEZ:
11019 3c824109 Nathan Froyd
            mips32_op = OPC_BLEZ;
11020 3c824109 Nathan Froyd
            goto do_branch;
11021 3c824109 Nathan Froyd
        case BGTZ:
11022 3c824109 Nathan Froyd
            mips32_op = OPC_BGTZ;
11023 3c824109 Nathan Froyd
        do_branch:
11024 3c824109 Nathan Froyd
            gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11025 3c824109 Nathan Froyd
            *is_branch = 1;
11026 3c824109 Nathan Froyd
            break;
11027 3c824109 Nathan Froyd
11028 3c824109 Nathan Froyd
            /* Traps */
11029 3c824109 Nathan Froyd
        case TLTI:
11030 3c824109 Nathan Froyd
            mips32_op = OPC_TLTI;
11031 3c824109 Nathan Froyd
            goto do_trapi;
11032 3c824109 Nathan Froyd
        case TGEI:
11033 3c824109 Nathan Froyd
            mips32_op = OPC_TGEI;
11034 3c824109 Nathan Froyd
            goto do_trapi;
11035 3c824109 Nathan Froyd
        case TLTIU:
11036 3c824109 Nathan Froyd
            mips32_op = OPC_TLTIU;
11037 3c824109 Nathan Froyd
            goto do_trapi;
11038 3c824109 Nathan Froyd
        case TGEIU:
11039 3c824109 Nathan Froyd
            mips32_op = OPC_TGEIU;
11040 3c824109 Nathan Froyd
            goto do_trapi;
11041 3c824109 Nathan Froyd
        case TNEI:
11042 3c824109 Nathan Froyd
            mips32_op = OPC_TNEI;
11043 3c824109 Nathan Froyd
            goto do_trapi;
11044 3c824109 Nathan Froyd
        case TEQI:
11045 3c824109 Nathan Froyd
            mips32_op = OPC_TEQI;
11046 3c824109 Nathan Froyd
        do_trapi:
11047 3c824109 Nathan Froyd
            gen_trap(ctx, mips32_op, rs, -1, imm);
11048 3c824109 Nathan Froyd
            break;
11049 3c824109 Nathan Froyd
11050 3c824109 Nathan Froyd
        case BNEZC:
11051 3c824109 Nathan Froyd
        case BEQZC:
11052 3c824109 Nathan Froyd
            gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11053 3c824109 Nathan Froyd
                               4, rs, 0, imm << 1);
11054 3c824109 Nathan Froyd
            /* Compact branches don't have a delay slot, so just let
11055 3c824109 Nathan Froyd
               the normal delay slot handling take us to the branch
11056 3c824109 Nathan Froyd
               target. */
11057 3c824109 Nathan Froyd
            break;
11058 3c824109 Nathan Froyd
        case LUI:
11059 3c824109 Nathan Froyd
            gen_logic_imm(env, OPC_LUI, rs, -1, imm);
11060 3c824109 Nathan Froyd
            break;
11061 3c824109 Nathan Froyd
        case SYNCI:
11062 3c824109 Nathan Froyd
            break;
11063 3c824109 Nathan Froyd
        case BC2F:
11064 3c824109 Nathan Froyd
        case BC2T:
11065 3c824109 Nathan Froyd
            /* COP2: Not implemented. */
11066 3c824109 Nathan Froyd
            generate_exception_err(ctx, EXCP_CpU, 2);
11067 3c824109 Nathan Froyd
            break;
11068 3c824109 Nathan Froyd
        case BC1F:
11069 3c824109 Nathan Froyd
            mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11070 3c824109 Nathan Froyd
            goto do_cp1branch;
11071 3c824109 Nathan Froyd
        case BC1T:
11072 3c824109 Nathan Froyd
            mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11073 3c824109 Nathan Froyd
            goto do_cp1branch;
11074 3c824109 Nathan Froyd
        case BC1ANY4F:
11075 3c824109 Nathan Froyd
            mips32_op = OPC_BC1FANY4;
11076 3c824109 Nathan Froyd
            goto do_cp1mips3d;
11077 3c824109 Nathan Froyd
        case BC1ANY4T:
11078 3c824109 Nathan Froyd
            mips32_op = OPC_BC1TANY4;
11079 3c824109 Nathan Froyd
        do_cp1mips3d:
11080 3c824109 Nathan Froyd
            check_cop1x(ctx);
11081 3c824109 Nathan Froyd
            check_insn(env, ctx, ASE_MIPS3D);
11082 3c824109 Nathan Froyd
            /* Fall through */
11083 3c824109 Nathan Froyd
        do_cp1branch:
11084 3c824109 Nathan Froyd
            gen_compute_branch1(env, ctx, mips32_op,
11085 3c824109 Nathan Froyd
                                (ctx->opcode >> 18) & 0x7, imm << 1);
11086 3c824109 Nathan Froyd
            *is_branch = 1;
11087 3c824109 Nathan Froyd
            break;
11088 3c824109 Nathan Froyd
        case BPOSGE64:
11089 3c824109 Nathan Froyd
        case BPOSGE32:
11090 3c824109 Nathan Froyd
            /* MIPS DSP: not implemented */
11091 3c824109 Nathan Froyd
            /* Fall through */
11092 3c824109 Nathan Froyd
        default:
11093 3c824109 Nathan Froyd
            MIPS_INVAL("pool32i");
11094 3c824109 Nathan Froyd
            generate_exception(ctx, EXCP_RI);
11095 3c824109 Nathan Froyd
            break;
11096 3c824109 Nathan Froyd
        }
11097 3c824109 Nathan Froyd
        break;
11098 3c824109 Nathan Froyd
    case POOL32C:
11099 3c824109 Nathan Froyd
        minor = (ctx->opcode >> 12) & 0xf;
11100 3c824109 Nathan Froyd
        switch (minor) {
11101 3c824109 Nathan Froyd
        case LWL:
11102 3c824109 Nathan Froyd
            mips32_op = OPC_LWL;
11103 5c13fdfd Aurelien Jarno
            goto do_ld_lr;
11104 3c824109 Nathan Froyd
        case SWL:
11105 3c824109 Nathan Froyd
            mips32_op = OPC_SWL;
11106 5c13fdfd Aurelien Jarno
            goto do_st_lr;
11107 3c824109 Nathan Froyd
        case LWR:
11108 3c824109 Nathan Froyd
            mips32_op = OPC_LWR;
11109 5c13fdfd Aurelien Jarno
            goto do_ld_lr;
11110 3c824109 Nathan Froyd
        case SWR:
11111 3c824109 Nathan Froyd
            mips32_op = OPC_SWR;
11112 5c13fdfd Aurelien Jarno
            goto do_st_lr;
11113 3c824109 Nathan Froyd
#if defined(TARGET_MIPS64)
11114 3c824109 Nathan Froyd
        case LDL:
11115 3c824109 Nathan Froyd
            mips32_op = OPC_LDL;
11116 5c13fdfd Aurelien Jarno
            goto do_ld_lr;
11117 3c824109 Nathan Froyd
        case SDL:
11118 3c824109 Nathan Froyd
            mips32_op = OPC_SDL;
11119 5c13fdfd Aurelien Jarno
            goto do_st_lr;
11120 3c824109 Nathan Froyd
        case LDR:
11121 3c824109 Nathan Froyd
            mips32_op = OPC_LDR;
11122 5c13fdfd Aurelien Jarno
            goto do_ld_lr;
11123 3c824109 Nathan Froyd
        case SDR:
11124 3c824109 Nathan Froyd
            mips32_op = OPC_SDR;
11125 5c13fdfd Aurelien Jarno
            goto do_st_lr;
11126 3c824109 Nathan Froyd
        case LWU:
11127 3c824109 Nathan Froyd
            mips32_op = OPC_LWU;
11128 5c13fdfd Aurelien Jarno
            goto do_ld_lr;
11129 3c824109 Nathan Froyd
        case LLD:
11130 3c824109 Nathan Froyd
            mips32_op = OPC_LLD;
11131 5c13fdfd Aurelien Jarno
            goto do_ld_lr;
11132 3c824109 Nathan Froyd
#endif
11133 3c824109 Nathan Froyd
        case LL:
11134 3c824109 Nathan Froyd
            mips32_op = OPC_LL;
11135 5c13fdfd Aurelien Jarno
            goto do_ld_lr;
11136 5c13fdfd Aurelien Jarno
        do_ld_lr:
11137 afa88c3a Aurelien Jarno
            gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11138 5c13fdfd Aurelien Jarno
            break;
11139 5c13fdfd Aurelien Jarno
        do_st_lr:
11140 5c13fdfd Aurelien Jarno
            gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11141 3c824109 Nathan Froyd
            break;
11142 3c824109 Nathan Froyd
        case SC:
11143 3c824109 Nathan Froyd
            gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11144 3c824109 Nathan Froyd
            break;
11145 3c824109 Nathan Froyd
#if defined(TARGET_MIPS64)
11146 3c824109 Nathan Froyd
        case SCD:
11147 3c824109 Nathan Froyd
            gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11148 3c824109 Nathan Froyd
            break;
11149 3c824109 Nathan Froyd
#endif
11150 3c824109 Nathan Froyd
        case PREF:
11151 3c824109 Nathan Froyd
            /* Treat as no-op */
11152 3c824109 Nathan Froyd
            break;
11153 3c824109 Nathan Froyd
        default:
11154 3c824109 Nathan Froyd
            MIPS_INVAL("pool32c");
11155 3c824109 Nathan Froyd
            generate_exception(ctx, EXCP_RI);
11156 3c824109 Nathan Froyd
            break;
11157 3c824109 Nathan Froyd
        }
11158 3c824109 Nathan Froyd
        break;
11159 3c824109 Nathan Froyd
    case ADDI32:
11160 3c824109 Nathan Froyd
        mips32_op = OPC_ADDI;
11161 3c824109 Nathan Froyd
        goto do_addi;
11162 3c824109 Nathan Froyd
    case ADDIU32:
11163 3c824109 Nathan Froyd
        mips32_op = OPC_ADDIU;
11164 3c824109 Nathan Froyd
    do_addi:
11165 3c824109 Nathan Froyd
        gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11166 3c824109 Nathan Froyd
        break;
11167 3c824109 Nathan Froyd
11168 3c824109 Nathan Froyd
        /* Logical operations */
11169 3c824109 Nathan Froyd
    case ORI32:
11170 3c824109 Nathan Froyd
        mips32_op = OPC_ORI;
11171 3c824109 Nathan Froyd
        goto do_logici;
11172 3c824109 Nathan Froyd
    case XORI32:
11173 3c824109 Nathan Froyd
        mips32_op = OPC_XORI;
11174 3c824109 Nathan Froyd
        goto do_logici;
11175 3c824109 Nathan Froyd
    case ANDI32:
11176 3c824109 Nathan Froyd
        mips32_op = OPC_ANDI;
11177 3c824109 Nathan Froyd
    do_logici:
11178 3c824109 Nathan Froyd
        gen_logic_imm(env, mips32_op, rt, rs, imm);
11179 3c824109 Nathan Froyd
        break;
11180 3c824109 Nathan Froyd
11181 3c824109 Nathan Froyd
        /* Set less than immediate */
11182 3c824109 Nathan Froyd
    case SLTI32:
11183 3c824109 Nathan Froyd
        mips32_op = OPC_SLTI;
11184 3c824109 Nathan Froyd
        goto do_slti;
11185 3c824109 Nathan Froyd
    case SLTIU32:
11186 3c824109 Nathan Froyd
        mips32_op = OPC_SLTIU;
11187 3c824109 Nathan Froyd
    do_slti:
11188 3c824109 Nathan Froyd
        gen_slt_imm(env, mips32_op, rt, rs, imm);
11189 3c824109 Nathan Froyd
        break;
11190 3c824109 Nathan Froyd
    case JALX32:
11191 3c824109 Nathan Froyd
        offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11192 3c824109 Nathan Froyd
        gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11193 3c824109 Nathan Froyd
        *is_branch = 1;
11194 3c824109 Nathan Froyd
        break;
11195 3c824109 Nathan Froyd
    case JALS32:
11196 3c824109 Nathan Froyd
        offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11197 3c824109 Nathan Froyd
        gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11198 3c824109 Nathan Froyd
        *is_branch = 1;
11199 3c824109 Nathan Froyd
        break;
11200 3c824109 Nathan Froyd
    case BEQ32:
11201 3c824109 Nathan Froyd
        gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11202 3c824109 Nathan Froyd
        *is_branch = 1;
11203 3c824109 Nathan Froyd
        break;
11204 3c824109 Nathan Froyd
    case BNE32:
11205 3c824109 Nathan Froyd
        gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11206 3c824109 Nathan Froyd
        *is_branch = 1;
11207 3c824109 Nathan Froyd
        break;
11208 3c824109 Nathan Froyd
    case J32:
11209 3c824109 Nathan Froyd
        gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11210 3c824109 Nathan Froyd
                           (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11211 3c824109 Nathan Froyd
        *is_branch = 1;
11212 3c824109 Nathan Froyd
        break;
11213 3c824109 Nathan Froyd
    case JAL32:
11214 3c824109 Nathan Froyd
        gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11215 3c824109 Nathan Froyd
                           (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11216 3c824109 Nathan Froyd
        *is_branch = 1;
11217 3c824109 Nathan Froyd
        break;
11218 3c824109 Nathan Froyd
        /* Floating point (COP1) */
11219 3c824109 Nathan Froyd
    case LWC132:
11220 3c824109 Nathan Froyd
        mips32_op = OPC_LWC1;
11221 3c824109 Nathan Froyd
        goto do_cop1;
11222 3c824109 Nathan Froyd
    case LDC132:
11223 3c824109 Nathan Froyd
        mips32_op = OPC_LDC1;
11224 3c824109 Nathan Froyd
        goto do_cop1;
11225 3c824109 Nathan Froyd
    case SWC132:
11226 3c824109 Nathan Froyd
        mips32_op = OPC_SWC1;
11227 3c824109 Nathan Froyd
        goto do_cop1;
11228 3c824109 Nathan Froyd
    case SDC132:
11229 3c824109 Nathan Froyd
        mips32_op = OPC_SDC1;
11230 3c824109 Nathan Froyd
    do_cop1:
11231 3c824109 Nathan Froyd
        gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11232 3c824109 Nathan Froyd
        break;
11233 3c824109 Nathan Froyd
    case ADDIUPC:
11234 3c824109 Nathan Froyd
        {
11235 3c824109 Nathan Froyd
            int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11236 3c824109 Nathan Froyd
            int offset = SIMM(ctx->opcode, 0, 23) << 2;
11237 3c824109 Nathan Froyd
11238 3c824109 Nathan Froyd
            gen_addiupc(ctx, reg, offset, 0, 0);
11239 3c824109 Nathan Froyd
        }
11240 3c824109 Nathan Froyd
        break;
11241 3c824109 Nathan Froyd
        /* Loads and stores */
11242 3c824109 Nathan Froyd
    case LB32:
11243 3c824109 Nathan Froyd
        mips32_op = OPC_LB;
11244 5c13fdfd Aurelien Jarno
        goto do_ld;
11245 3c824109 Nathan Froyd
    case LBU32:
11246 3c824109 Nathan Froyd
        mips32_op = OPC_LBU;
11247 5c13fdfd Aurelien Jarno
        goto do_ld;
11248 3c824109 Nathan Froyd
    case LH32:
11249 3c824109 Nathan Froyd
        mips32_op = OPC_LH;
11250 5c13fdfd Aurelien Jarno
        goto do_ld;
11251 3c824109 Nathan Froyd
    case LHU32:
11252 3c824109 Nathan Froyd
        mips32_op = OPC_LHU;
11253 5c13fdfd Aurelien Jarno
        goto do_ld;
11254 3c824109 Nathan Froyd
    case LW32:
11255 3c824109 Nathan Froyd
        mips32_op = OPC_LW;
11256 5c13fdfd Aurelien Jarno
        goto do_ld;
11257 3c824109 Nathan Froyd
#ifdef TARGET_MIPS64
11258 3c824109 Nathan Froyd
    case LD32:
11259 3c824109 Nathan Froyd
        mips32_op = OPC_LD;
11260 5c13fdfd Aurelien Jarno
        goto do_ld;
11261 3c824109 Nathan Froyd
    case SD32:
11262 3c824109 Nathan Froyd
        mips32_op = OPC_SD;
11263 5c13fdfd Aurelien Jarno
        goto do_st;
11264 3c824109 Nathan Froyd
#endif
11265 3c824109 Nathan Froyd
    case SB32:
11266 3c824109 Nathan Froyd
        mips32_op = OPC_SB;
11267 5c13fdfd Aurelien Jarno
        goto do_st;
11268 3c824109 Nathan Froyd
    case SH32:
11269 3c824109 Nathan Froyd
        mips32_op = OPC_SH;
11270 5c13fdfd Aurelien Jarno
        goto do_st;
11271 3c824109 Nathan Froyd
    case SW32:
11272 3c824109 Nathan Froyd
        mips32_op = OPC_SW;
11273 5c13fdfd Aurelien Jarno
        goto do_st;
11274 5c13fdfd Aurelien Jarno
    do_ld:
11275 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, mips32_op, rt, rs, imm);
11276 5c13fdfd Aurelien Jarno
        break;
11277 5c13fdfd Aurelien Jarno
    do_st:
11278 5c13fdfd Aurelien Jarno
        gen_st(ctx, mips32_op, rt, rs, imm);
11279 3c824109 Nathan Froyd
        break;
11280 3c824109 Nathan Froyd
    default:
11281 3c824109 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
11282 3c824109 Nathan Froyd
        break;
11283 3c824109 Nathan Froyd
    }
11284 3c824109 Nathan Froyd
}
11285 3c824109 Nathan Froyd
11286 3c824109 Nathan Froyd
static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11287 3c824109 Nathan Froyd
{
11288 3c824109 Nathan Froyd
    uint32_t op;
11289 3c824109 Nathan Froyd
11290 3c824109 Nathan Froyd
    /* make sure instructions are on a halfword boundary */
11291 3c824109 Nathan Froyd
    if (ctx->pc & 0x1) {
11292 3c824109 Nathan Froyd
        env->CP0_BadVAddr = ctx->pc;
11293 3c824109 Nathan Froyd
        generate_exception(ctx, EXCP_AdEL);
11294 3c824109 Nathan Froyd
        ctx->bstate = BS_STOP;
11295 3c824109 Nathan Froyd
        return 2;
11296 3c824109 Nathan Froyd
    }
11297 3c824109 Nathan Froyd
11298 3c824109 Nathan Froyd
    op = (ctx->opcode >> 10) & 0x3f;
11299 3c824109 Nathan Froyd
    /* Enforce properly-sized instructions in a delay slot */
11300 3c824109 Nathan Froyd
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
11301 3c824109 Nathan Froyd
        int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11302 3c824109 Nathan Froyd
11303 3c824109 Nathan Froyd
        switch (op) {
11304 3c824109 Nathan Froyd
        case POOL32A:
11305 3c824109 Nathan Froyd
        case POOL32B:
11306 3c824109 Nathan Froyd
        case POOL32I:
11307 3c824109 Nathan Froyd
        case POOL32C:
11308 3c824109 Nathan Froyd
        case ADDI32:
11309 3c824109 Nathan Froyd
        case ADDIU32:
11310 3c824109 Nathan Froyd
        case ORI32:
11311 3c824109 Nathan Froyd
        case XORI32:
11312 3c824109 Nathan Froyd
        case SLTI32:
11313 3c824109 Nathan Froyd
        case SLTIU32:
11314 3c824109 Nathan Froyd
        case ANDI32:
11315 3c824109 Nathan Froyd
        case JALX32:
11316 3c824109 Nathan Froyd
        case LBU32:
11317 3c824109 Nathan Froyd
        case LHU32:
11318 3c824109 Nathan Froyd
        case POOL32F:
11319 3c824109 Nathan Froyd
        case JALS32:
11320 3c824109 Nathan Froyd
        case BEQ32:
11321 3c824109 Nathan Froyd
        case BNE32:
11322 3c824109 Nathan Froyd
        case J32:
11323 3c824109 Nathan Froyd
        case JAL32:
11324 3c824109 Nathan Froyd
        case SB32:
11325 3c824109 Nathan Froyd
        case SH32:
11326 3c824109 Nathan Froyd
        case POOL32S:
11327 3c824109 Nathan Froyd
        case ADDIUPC:
11328 3c824109 Nathan Froyd
        case SWC132:
11329 3c824109 Nathan Froyd
        case SDC132:
11330 3c824109 Nathan Froyd
        case SD32:
11331 3c824109 Nathan Froyd
        case SW32:
11332 3c824109 Nathan Froyd
        case LB32:
11333 3c824109 Nathan Froyd
        case LH32:
11334 3c824109 Nathan Froyd
        case DADDIU32:
11335 3c824109 Nathan Froyd
        case POOL48A:           /* ??? */
11336 3c824109 Nathan Froyd
        case LWC132:
11337 3c824109 Nathan Froyd
        case LDC132:
11338 3c824109 Nathan Froyd
        case LD32:
11339 3c824109 Nathan Froyd
        case LW32:
11340 3c824109 Nathan Froyd
            if (bits & MIPS_HFLAG_BDS16) {
11341 3c824109 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
11342 3c824109 Nathan Froyd
                /* Just stop translation; the user is confused.  */
11343 3c824109 Nathan Froyd
                ctx->bstate = BS_STOP;
11344 3c824109 Nathan Froyd
                return 2;
11345 3c824109 Nathan Froyd
            }
11346 3c824109 Nathan Froyd
            break;
11347 3c824109 Nathan Froyd
        case POOL16A:
11348 3c824109 Nathan Froyd
        case POOL16B:
11349 3c824109 Nathan Froyd
        case POOL16C:
11350 3c824109 Nathan Froyd
        case LWGP16:
11351 3c824109 Nathan Froyd
        case POOL16F:
11352 3c824109 Nathan Froyd
        case LBU16:
11353 3c824109 Nathan Froyd
        case LHU16:
11354 3c824109 Nathan Froyd
        case LWSP16:
11355 3c824109 Nathan Froyd
        case LW16:
11356 3c824109 Nathan Froyd
        case SB16:
11357 3c824109 Nathan Froyd
        case SH16:
11358 3c824109 Nathan Froyd
        case SWSP16:
11359 3c824109 Nathan Froyd
        case SW16:
11360 3c824109 Nathan Froyd
        case MOVE16:
11361 3c824109 Nathan Froyd
        case ANDI16:
11362 3c824109 Nathan Froyd
        case POOL16D:
11363 3c824109 Nathan Froyd
        case POOL16E:
11364 3c824109 Nathan Froyd
        case BEQZ16:
11365 3c824109 Nathan Froyd
        case BNEZ16:
11366 3c824109 Nathan Froyd
        case B16:
11367 3c824109 Nathan Froyd
        case LI16:
11368 3c824109 Nathan Froyd
            if (bits & MIPS_HFLAG_BDS32) {
11369 3c824109 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
11370 3c824109 Nathan Froyd
                /* Just stop translation; the user is confused.  */
11371 3c824109 Nathan Froyd
                ctx->bstate = BS_STOP;
11372 3c824109 Nathan Froyd
                return 2;
11373 3c824109 Nathan Froyd
            }
11374 3c824109 Nathan Froyd
            break;
11375 3c824109 Nathan Froyd
        default:
11376 3c824109 Nathan Froyd
            break;
11377 3c824109 Nathan Froyd
        }
11378 3c824109 Nathan Froyd
    }
11379 3c824109 Nathan Froyd
    switch (op) {
11380 3c824109 Nathan Froyd
    case POOL16A:
11381 3c824109 Nathan Froyd
        {
11382 3c824109 Nathan Froyd
            int rd = mmreg(uMIPS_RD(ctx->opcode));
11383 3c824109 Nathan Froyd
            int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11384 3c824109 Nathan Froyd
            int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11385 3c824109 Nathan Froyd
            uint32_t opc = 0;
11386 3c824109 Nathan Froyd
11387 3c824109 Nathan Froyd
            switch (ctx->opcode & 0x1) {
11388 3c824109 Nathan Froyd
            case ADDU16:
11389 3c824109 Nathan Froyd
                opc = OPC_ADDU;
11390 3c824109 Nathan Froyd
                break;
11391 3c824109 Nathan Froyd
            case SUBU16:
11392 3c824109 Nathan Froyd
                opc = OPC_SUBU;
11393 3c824109 Nathan Froyd
                break;
11394 3c824109 Nathan Froyd
            }
11395 3c824109 Nathan Froyd
11396 3c824109 Nathan Froyd
            gen_arith(env, ctx, opc, rd, rs1, rs2);
11397 3c824109 Nathan Froyd
        }
11398 3c824109 Nathan Froyd
        break;
11399 3c824109 Nathan Froyd
    case POOL16B:
11400 3c824109 Nathan Froyd
        {
11401 3c824109 Nathan Froyd
            int rd = mmreg(uMIPS_RD(ctx->opcode));
11402 3c824109 Nathan Froyd
            int rs = mmreg(uMIPS_RS(ctx->opcode));
11403 3c824109 Nathan Froyd
            int amount = (ctx->opcode >> 1) & 0x7;
11404 3c824109 Nathan Froyd
            uint32_t opc = 0;
11405 3c824109 Nathan Froyd
            amount = amount == 0 ? 8 : amount;
11406 3c824109 Nathan Froyd
11407 3c824109 Nathan Froyd
            switch (ctx->opcode & 0x1) {
11408 3c824109 Nathan Froyd
            case SLL16:
11409 3c824109 Nathan Froyd
                opc = OPC_SLL;
11410 3c824109 Nathan Froyd
                break;
11411 3c824109 Nathan Froyd
            case SRL16:
11412 3c824109 Nathan Froyd
                opc = OPC_SRL;
11413 3c824109 Nathan Froyd
                break;
11414 3c824109 Nathan Froyd
            }
11415 3c824109 Nathan Froyd
11416 3c824109 Nathan Froyd
            gen_shift_imm(env, ctx, opc, rd, rs, amount);
11417 3c824109 Nathan Froyd
        }
11418 3c824109 Nathan Froyd
        break;
11419 3c824109 Nathan Froyd
    case POOL16C:
11420 3c824109 Nathan Froyd
        gen_pool16c_insn(env, ctx, is_branch);
11421 3c824109 Nathan Froyd
        break;
11422 3c824109 Nathan Froyd
    case LWGP16:
11423 3c824109 Nathan Froyd
        {
11424 3c824109 Nathan Froyd
            int rd = mmreg(uMIPS_RD(ctx->opcode));
11425 3c824109 Nathan Froyd
            int rb = 28;            /* GP */
11426 3c824109 Nathan Froyd
            int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11427 3c824109 Nathan Froyd
11428 afa88c3a Aurelien Jarno
            gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11429 3c824109 Nathan Froyd
        }
11430 3c824109 Nathan Froyd
        break;
11431 3c824109 Nathan Froyd
    case POOL16F:
11432 3c824109 Nathan Froyd
        if (ctx->opcode & 1) {
11433 3c824109 Nathan Froyd
            generate_exception(ctx, EXCP_RI);
11434 3c824109 Nathan Froyd
        } else {
11435 3c824109 Nathan Froyd
            /* MOVEP */
11436 3c824109 Nathan Froyd
            int enc_dest = uMIPS_RD(ctx->opcode);
11437 3c824109 Nathan Froyd
            int enc_rt = uMIPS_RS2(ctx->opcode);
11438 3c824109 Nathan Froyd
            int enc_rs = uMIPS_RS1(ctx->opcode);
11439 3c824109 Nathan Froyd
            int rd, rs, re, rt;
11440 3c824109 Nathan Froyd
            static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11441 3c824109 Nathan Froyd
            static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11442 3c824109 Nathan Froyd
            static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11443 3c824109 Nathan Froyd
11444 3c824109 Nathan Froyd
            rd = rd_enc[enc_dest];
11445 3c824109 Nathan Froyd
            re = re_enc[enc_dest];
11446 3c824109 Nathan Froyd
            rs = rs_rt_enc[enc_rs];
11447 3c824109 Nathan Froyd
            rt = rs_rt_enc[enc_rt];
11448 3c824109 Nathan Froyd
11449 3c824109 Nathan Froyd
            gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11450 3c824109 Nathan Froyd
            gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11451 3c824109 Nathan Froyd
        }
11452 3c824109 Nathan Froyd
        break;
11453 3c824109 Nathan Froyd
    case LBU16:
11454 3c824109 Nathan Froyd
        {
11455 3c824109 Nathan Froyd
            int rd = mmreg(uMIPS_RD(ctx->opcode));
11456 3c824109 Nathan Froyd
            int rb = mmreg(uMIPS_RS(ctx->opcode));
11457 3c824109 Nathan Froyd
            int16_t offset = ZIMM(ctx->opcode, 0, 4);
11458 3c824109 Nathan Froyd
            offset = (offset == 0xf ? -1 : offset);
11459 3c824109 Nathan Froyd
11460 afa88c3a Aurelien Jarno
            gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
11461 3c824109 Nathan Froyd
        }
11462 3c824109 Nathan Froyd
        break;
11463 3c824109 Nathan Froyd
    case LHU16:
11464 3c824109 Nathan Froyd
        {
11465 3c824109 Nathan Froyd
            int rd = mmreg(uMIPS_RD(ctx->opcode));
11466 3c824109 Nathan Froyd
            int rb = mmreg(uMIPS_RS(ctx->opcode));
11467 3c824109 Nathan Froyd
            int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11468 3c824109 Nathan Froyd
11469 afa88c3a Aurelien Jarno
            gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
11470 3c824109 Nathan Froyd
        }
11471 3c824109 Nathan Froyd
        break;
11472 3c824109 Nathan Froyd
    case LWSP16:
11473 3c824109 Nathan Froyd
        {
11474 3c824109 Nathan Froyd
            int rd = (ctx->opcode >> 5) & 0x1f;
11475 3c824109 Nathan Froyd
            int rb = 29;            /* SP */
11476 3c824109 Nathan Froyd
            int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11477 3c824109 Nathan Froyd
11478 afa88c3a Aurelien Jarno
            gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11479 3c824109 Nathan Froyd
        }
11480 3c824109 Nathan Froyd
        break;
11481 3c824109 Nathan Froyd
    case LW16:
11482 3c824109 Nathan Froyd
        {
11483 3c824109 Nathan Froyd
            int rd = mmreg(uMIPS_RD(ctx->opcode));
11484 3c824109 Nathan Froyd
            int rb = mmreg(uMIPS_RS(ctx->opcode));
11485 3c824109 Nathan Froyd
            int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11486 3c824109 Nathan Froyd
11487 afa88c3a Aurelien Jarno
            gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11488 3c824109 Nathan Froyd
        }
11489 3c824109 Nathan Froyd
        break;
11490 3c824109 Nathan Froyd
    case SB16:
11491 3c824109 Nathan Froyd
        {
11492 3c824109 Nathan Froyd
            int rd = mmreg2(uMIPS_RD(ctx->opcode));
11493 3c824109 Nathan Froyd
            int rb = mmreg(uMIPS_RS(ctx->opcode));
11494 3c824109 Nathan Froyd
            int16_t offset = ZIMM(ctx->opcode, 0, 4);
11495 3c824109 Nathan Froyd
11496 5c13fdfd Aurelien Jarno
            gen_st(ctx, OPC_SB, rd, rb, offset);
11497 3c824109 Nathan Froyd
        }
11498 3c824109 Nathan Froyd
        break;
11499 3c824109 Nathan Froyd
    case SH16:
11500 3c824109 Nathan Froyd
        {
11501 3c824109 Nathan Froyd
            int rd = mmreg2(uMIPS_RD(ctx->opcode));
11502 3c824109 Nathan Froyd
            int rb = mmreg(uMIPS_RS(ctx->opcode));
11503 3c824109 Nathan Froyd
            int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11504 3c824109 Nathan Froyd
11505 5c13fdfd Aurelien Jarno
            gen_st(ctx, OPC_SH, rd, rb, offset);
11506 3c824109 Nathan Froyd
        }
11507 3c824109 Nathan Froyd
        break;
11508 3c824109 Nathan Froyd
    case SWSP16:
11509 3c824109 Nathan Froyd
        {
11510 3c824109 Nathan Froyd
            int rd = (ctx->opcode >> 5) & 0x1f;
11511 3c824109 Nathan Froyd
            int rb = 29;            /* SP */
11512 3c824109 Nathan Froyd
            int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11513 3c824109 Nathan Froyd
11514 5c13fdfd Aurelien Jarno
            gen_st(ctx, OPC_SW, rd, rb, offset);
11515 3c824109 Nathan Froyd
        }
11516 3c824109 Nathan Froyd
        break;
11517 3c824109 Nathan Froyd
    case SW16:
11518 3c824109 Nathan Froyd
        {
11519 3c824109 Nathan Froyd
            int rd = mmreg2(uMIPS_RD(ctx->opcode));
11520 3c824109 Nathan Froyd
            int rb = mmreg(uMIPS_RS(ctx->opcode));
11521 3c824109 Nathan Froyd
            int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11522 3c824109 Nathan Froyd
11523 5c13fdfd Aurelien Jarno
            gen_st(ctx, OPC_SW, rd, rb, offset);
11524 3c824109 Nathan Froyd
        }
11525 3c824109 Nathan Froyd
        break;
11526 3c824109 Nathan Froyd
    case MOVE16:
11527 3c824109 Nathan Froyd
        {
11528 3c824109 Nathan Froyd
            int rd = uMIPS_RD5(ctx->opcode);
11529 3c824109 Nathan Froyd
            int rs = uMIPS_RS5(ctx->opcode);
11530 3c824109 Nathan Froyd
11531 3c824109 Nathan Froyd
            gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11532 3c824109 Nathan Froyd
        }
11533 3c824109 Nathan Froyd
        break;
11534 3c824109 Nathan Froyd
    case ANDI16:
11535 3c824109 Nathan Froyd
        gen_andi16(env, ctx);
11536 3c824109 Nathan Froyd
        break;
11537 3c824109 Nathan Froyd
    case POOL16D:
11538 3c824109 Nathan Froyd
        switch (ctx->opcode & 0x1) {
11539 3c824109 Nathan Froyd
        case ADDIUS5:
11540 3c824109 Nathan Froyd
            gen_addius5(env, ctx);
11541 3c824109 Nathan Froyd
            break;
11542 3c824109 Nathan Froyd
        case ADDIUSP:
11543 3c824109 Nathan Froyd
            gen_addiusp(env, ctx);
11544 3c824109 Nathan Froyd
            break;
11545 3c824109 Nathan Froyd
        }
11546 3c824109 Nathan Froyd
        break;
11547 3c824109 Nathan Froyd
    case POOL16E:
11548 3c824109 Nathan Froyd
        switch (ctx->opcode & 0x1) {
11549 3c824109 Nathan Froyd
        case ADDIUR2:
11550 3c824109 Nathan Froyd
            gen_addiur2(env, ctx);
11551 3c824109 Nathan Froyd
            break;
11552 3c824109 Nathan Froyd
        case ADDIUR1SP:
11553 3c824109 Nathan Froyd
            gen_addiur1sp(env, ctx);
11554 3c824109 Nathan Froyd
            break;
11555 3c824109 Nathan Froyd
        }
11556 3c824109 Nathan Froyd
        break;
11557 3c824109 Nathan Froyd
    case B16:
11558 3c824109 Nathan Froyd
        gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
11559 3c824109 Nathan Froyd
                           SIMM(ctx->opcode, 0, 10) << 1);
11560 3c824109 Nathan Froyd
        *is_branch = 1;
11561 3c824109 Nathan Froyd
        break;
11562 3c824109 Nathan Froyd
    case BNEZ16:
11563 3c824109 Nathan Froyd
    case BEQZ16:
11564 3c824109 Nathan Froyd
        gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
11565 3c824109 Nathan Froyd
                           mmreg(uMIPS_RD(ctx->opcode)),
11566 3c824109 Nathan Froyd
                           0, SIMM(ctx->opcode, 0, 7) << 1);
11567 3c824109 Nathan Froyd
        *is_branch = 1;
11568 3c824109 Nathan Froyd
        break;
11569 3c824109 Nathan Froyd
    case LI16:
11570 3c824109 Nathan Froyd
        {
11571 3c824109 Nathan Froyd
            int reg = mmreg(uMIPS_RD(ctx->opcode));
11572 3c824109 Nathan Froyd
            int imm = ZIMM(ctx->opcode, 0, 7);
11573 3c824109 Nathan Froyd
11574 3c824109 Nathan Froyd
            imm = (imm == 0x7f ? -1 : imm);
11575 3c824109 Nathan Froyd
            tcg_gen_movi_tl(cpu_gpr[reg], imm);
11576 3c824109 Nathan Froyd
        }
11577 3c824109 Nathan Froyd
        break;
11578 3c824109 Nathan Froyd
    case RES_20:
11579 3c824109 Nathan Froyd
    case RES_28:
11580 3c824109 Nathan Froyd
    case RES_29:
11581 3c824109 Nathan Froyd
    case RES_30:
11582 3c824109 Nathan Froyd
    case RES_31:
11583 3c824109 Nathan Froyd
    case RES_38:
11584 3c824109 Nathan Froyd
    case RES_39:
11585 3c824109 Nathan Froyd
        generate_exception(ctx, EXCP_RI);
11586 3c824109 Nathan Froyd
        break;
11587 3c824109 Nathan Froyd
    default:
11588 3c824109 Nathan Froyd
        decode_micromips32_opc (env, ctx, op, is_branch);
11589 3c824109 Nathan Froyd
        return 4;
11590 3c824109 Nathan Froyd
    }
11591 3c824109 Nathan Froyd
11592 3c824109 Nathan Froyd
    return 2;
11593 3c824109 Nathan Froyd
}
11594 3c824109 Nathan Froyd
11595 3c824109 Nathan Froyd
/* SmartMIPS extension to MIPS32 */
11596 3c824109 Nathan Froyd
11597 3c824109 Nathan Froyd
#if defined(TARGET_MIPS64)
11598 3c824109 Nathan Froyd
11599 3c824109 Nathan Froyd
/* MDMX extension to MIPS64 */
11600 3c824109 Nathan Froyd
11601 3c824109 Nathan Froyd
#endif
11602 3c824109 Nathan Froyd
11603 3c824109 Nathan Froyd
static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
11604 3c824109 Nathan Froyd
{
11605 3c824109 Nathan Froyd
    int32_t offset;
11606 3c824109 Nathan Froyd
    int rs, rt, rd, sa;
11607 3c824109 Nathan Froyd
    uint32_t op, op1, op2;
11608 3c824109 Nathan Froyd
    int16_t imm;
11609 3c824109 Nathan Froyd
11610 3c824109 Nathan Froyd
    /* make sure instructions are on a word boundary */
11611 3c824109 Nathan Froyd
    if (ctx->pc & 0x3) {
11612 3c824109 Nathan Froyd
        env->CP0_BadVAddr = ctx->pc;
11613 3c824109 Nathan Froyd
        generate_exception(ctx, EXCP_AdEL);
11614 3c824109 Nathan Froyd
        return;
11615 3c824109 Nathan Froyd
    }
11616 3c824109 Nathan Froyd
11617 3c824109 Nathan Froyd
    /* Handle blikely not taken case */
11618 3c824109 Nathan Froyd
    if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
11619 3c824109 Nathan Froyd
        int l1 = gen_new_label();
11620 3c824109 Nathan Froyd
11621 3c824109 Nathan Froyd
        MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
11622 3c824109 Nathan Froyd
        tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11623 3c824109 Nathan Froyd
        tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
11624 3c824109 Nathan Froyd
        gen_goto_tb(ctx, 1, ctx->pc + 4);
11625 3c824109 Nathan Froyd
        gen_set_label(l1);
11626 3c824109 Nathan Froyd
    }
11627 3c824109 Nathan Froyd
11628 3c824109 Nathan Froyd
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11629 3c824109 Nathan Froyd
        tcg_gen_debug_insn_start(ctx->pc);
11630 3c824109 Nathan Froyd
11631 3c824109 Nathan Froyd
    op = MASK_OP_MAJOR(ctx->opcode);
11632 3c824109 Nathan Froyd
    rs = (ctx->opcode >> 21) & 0x1f;
11633 3c824109 Nathan Froyd
    rt = (ctx->opcode >> 16) & 0x1f;
11634 3c824109 Nathan Froyd
    rd = (ctx->opcode >> 11) & 0x1f;
11635 3c824109 Nathan Froyd
    sa = (ctx->opcode >> 6) & 0x1f;
11636 3c824109 Nathan Froyd
    imm = (int16_t)ctx->opcode;
11637 3c824109 Nathan Froyd
    switch (op) {
11638 7a387fff ths
    case OPC_SPECIAL:
11639 7a387fff ths
        op1 = MASK_SPECIAL(ctx->opcode);
11640 6af0bf9c bellard
        switch (op1) {
11641 324d9e32 aurel32
        case OPC_SLL:          /* Shift with immediate */
11642 324d9e32 aurel32
        case OPC_SRA:
11643 324d9e32 aurel32
            gen_shift_imm(env, ctx, op1, rd, rt, sa);
11644 7a387fff ths
            break;
11645 ea63e2c3 Nathan Froyd
        case OPC_SRL:
11646 ea63e2c3 Nathan Froyd
            switch ((ctx->opcode >> 21) & 0x1f) {
11647 ea63e2c3 Nathan Froyd
            case 1:
11648 ea63e2c3 Nathan Froyd
                /* rotr is decoded as srl on non-R2 CPUs */
11649 ea63e2c3 Nathan Froyd
                if (env->insn_flags & ISA_MIPS32R2) {
11650 ea63e2c3 Nathan Froyd
                    op1 = OPC_ROTR;
11651 ea63e2c3 Nathan Froyd
                }
11652 ea63e2c3 Nathan Froyd
                /* Fallthrough */
11653 ea63e2c3 Nathan Froyd
            case 0:
11654 ea63e2c3 Nathan Froyd
                gen_shift_imm(env, ctx, op1, rd, rt, sa);
11655 ea63e2c3 Nathan Froyd
                break;
11656 ea63e2c3 Nathan Froyd
            default:
11657 ea63e2c3 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
11658 ea63e2c3 Nathan Froyd
                break;
11659 ea63e2c3 Nathan Froyd
            }
11660 ea63e2c3 Nathan Froyd
            break;
11661 460f00c4 aurel32
        case OPC_MOVN:         /* Conditional move */
11662 460f00c4 aurel32
        case OPC_MOVZ:
11663 aa8f4009 Aurelien Jarno
            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
11664 aa8f4009 Aurelien Jarno
                                 INSN_LOONGSON2E | INSN_LOONGSON2F);
11665 460f00c4 aurel32
            gen_cond_move(env, op1, rd, rs, rt);
11666 460f00c4 aurel32
            break;
11667 460f00c4 aurel32
        case OPC_ADD ... OPC_SUBU:
11668 e189e748 ths
            gen_arith(env, ctx, op1, rd, rs, rt);
11669 7a387fff ths
            break;
11670 460f00c4 aurel32
        case OPC_SLLV:         /* Shifts */
11671 460f00c4 aurel32
        case OPC_SRAV:
11672 460f00c4 aurel32
            gen_shift(env, ctx, op1, rd, rs, rt);
11673 460f00c4 aurel32
            break;
11674 ea63e2c3 Nathan Froyd
        case OPC_SRLV:
11675 ea63e2c3 Nathan Froyd
            switch ((ctx->opcode >> 6) & 0x1f) {
11676 ea63e2c3 Nathan Froyd
            case 1:
11677 ea63e2c3 Nathan Froyd
                /* rotrv is decoded as srlv on non-R2 CPUs */
11678 ea63e2c3 Nathan Froyd
                if (env->insn_flags & ISA_MIPS32R2) {
11679 ea63e2c3 Nathan Froyd
                    op1 = OPC_ROTRV;
11680 ea63e2c3 Nathan Froyd
                }
11681 ea63e2c3 Nathan Froyd
                /* Fallthrough */
11682 ea63e2c3 Nathan Froyd
            case 0:
11683 ea63e2c3 Nathan Froyd
                gen_shift(env, ctx, op1, rd, rs, rt);
11684 ea63e2c3 Nathan Froyd
                break;
11685 ea63e2c3 Nathan Froyd
            default:
11686 ea63e2c3 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
11687 ea63e2c3 Nathan Froyd
                break;
11688 ea63e2c3 Nathan Froyd
            }
11689 ea63e2c3 Nathan Froyd
            break;
11690 460f00c4 aurel32
        case OPC_SLT:          /* Set on less than */
11691 460f00c4 aurel32
        case OPC_SLTU:
11692 460f00c4 aurel32
            gen_slt(env, op1, rd, rs, rt);
11693 460f00c4 aurel32
            break;
11694 460f00c4 aurel32
        case OPC_AND:          /* Logic*/
11695 460f00c4 aurel32
        case OPC_OR:
11696 460f00c4 aurel32
        case OPC_NOR:
11697 460f00c4 aurel32
        case OPC_XOR:
11698 460f00c4 aurel32
            gen_logic(env, op1, rd, rs, rt);
11699 460f00c4 aurel32
            break;
11700 7a387fff ths
        case OPC_MULT ... OPC_DIVU:
11701 e9c71dd1 ths
            if (sa) {
11702 e9c71dd1 ths
                check_insn(env, ctx, INSN_VR54XX);
11703 e9c71dd1 ths
                op1 = MASK_MUL_VR54XX(ctx->opcode);
11704 e9c71dd1 ths
                gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11705 e9c71dd1 ths
            } else
11706 e9c71dd1 ths
                gen_muldiv(ctx, op1, rs, rt);
11707 7a387fff ths
            break;
11708 7a387fff ths
        case OPC_JR ... OPC_JALR:
11709 7dca4ad0 Nathan Froyd
            gen_compute_branch(ctx, op1, 4, rs, rd, sa);
11710 c9602061 Nathan Froyd
            *is_branch = 1;
11711 c9602061 Nathan Froyd
            break;
11712 7a387fff ths
        case OPC_TGE ... OPC_TEQ: /* Traps */
11713 7a387fff ths
        case OPC_TNE:
11714 7a387fff ths
            gen_trap(ctx, op1, rs, rt, -1);
11715 6af0bf9c bellard
            break;
11716 7a387fff ths
        case OPC_MFHI:          /* Move from HI/LO */
11717 7a387fff ths
        case OPC_MFLO:
11718 7a387fff ths
            gen_HILO(ctx, op1, rd);
11719 6af0bf9c bellard
            break;
11720 7a387fff ths
        case OPC_MTHI:
11721 7a387fff ths
        case OPC_MTLO:          /* Move to HI/LO */
11722 7a387fff ths
            gen_HILO(ctx, op1, rs);
11723 6af0bf9c bellard
            break;
11724 b48cfdff ths
        case OPC_PMON:          /* Pmon entry point, also R4010 selsl */
11725 b48cfdff ths
#ifdef MIPS_STRICT_STANDARD
11726 b48cfdff ths
            MIPS_INVAL("PMON / selsl");
11727 b48cfdff ths
            generate_exception(ctx, EXCP_RI);
11728 b48cfdff ths
#else
11729 a7812ae4 pbrook
            gen_helper_0i(pmon, sa);
11730 b48cfdff ths
#endif
11731 7a387fff ths
            break;
11732 7a387fff ths
        case OPC_SYSCALL:
11733 6af0bf9c bellard
            generate_exception(ctx, EXCP_SYSCALL);
11734 8e0f950d pbrook
            ctx->bstate = BS_STOP;
11735 6af0bf9c bellard
            break;
11736 7a387fff ths
        case OPC_BREAK:
11737 6af0bf9c bellard
            generate_exception(ctx, EXCP_BREAK);
11738 6af0bf9c bellard
            break;
11739 b48cfdff ths
        case OPC_SPIM:
11740 b48cfdff ths
#ifdef MIPS_STRICT_STANDARD
11741 b48cfdff ths
            MIPS_INVAL("SPIM");
11742 b48cfdff ths
            generate_exception(ctx, EXCP_RI);
11743 b48cfdff ths
#else
11744 7a387fff ths
           /* Implemented as RI exception for now. */
11745 7a387fff ths
            MIPS_INVAL("spim (unofficial)");
11746 7a387fff ths
            generate_exception(ctx, EXCP_RI);
11747 b48cfdff ths
#endif
11748 6af0bf9c bellard
            break;
11749 7a387fff ths
        case OPC_SYNC:
11750 ead9360e ths
            /* Treat as NOP. */
11751 6af0bf9c bellard
            break;
11752 4ad40f36 bellard
11753 7a387fff ths
        case OPC_MOVCI:
11754 e189e748 ths
            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
11755 36d23958 ths
            if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11756 5e755519 ths
                check_cp1_enabled(ctx);
11757 36d23958 ths
                gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11758 36d23958 ths
                          (ctx->opcode >> 16) & 1);
11759 36d23958 ths
            } else {
11760 e397ee33 ths
                generate_exception_err(ctx, EXCP_CpU, 1);
11761 36d23958 ths
            }
11762 4ad40f36 bellard
            break;
11763 4ad40f36 bellard
11764 d26bc211 ths
#if defined(TARGET_MIPS64)
11765 7a387fff ths
       /* MIPS64 specific opcodes */
11766 7a387fff ths
        case OPC_DSLL:
11767 324d9e32 aurel32
        case OPC_DSRA:
11768 7a387fff ths
        case OPC_DSLL32:
11769 324d9e32 aurel32
        case OPC_DSRA32:
11770 e189e748 ths
            check_insn(env, ctx, ISA_MIPS3);
11771 e189e748 ths
            check_mips_64(ctx);
11772 324d9e32 aurel32
            gen_shift_imm(env, ctx, op1, rd, rt, sa);
11773 7a387fff ths
            break;
11774 ea63e2c3 Nathan Froyd
        case OPC_DSRL:
11775 ea63e2c3 Nathan Froyd
            switch ((ctx->opcode >> 21) & 0x1f) {
11776 ea63e2c3 Nathan Froyd
            case 1:
11777 ea63e2c3 Nathan Froyd
                /* drotr is decoded as dsrl on non-R2 CPUs */
11778 ea63e2c3 Nathan Froyd
                if (env->insn_flags & ISA_MIPS32R2) {
11779 ea63e2c3 Nathan Froyd
                    op1 = OPC_DROTR;
11780 ea63e2c3 Nathan Froyd
                }
11781 ea63e2c3 Nathan Froyd
                /* Fallthrough */
11782 ea63e2c3 Nathan Froyd
            case 0:
11783 ea63e2c3 Nathan Froyd
                check_insn(env, ctx, ISA_MIPS3);
11784 ea63e2c3 Nathan Froyd
                check_mips_64(ctx);
11785 ea63e2c3 Nathan Froyd
                gen_shift_imm(env, ctx, op1, rd, rt, sa);
11786 ea63e2c3 Nathan Froyd
                break;
11787 ea63e2c3 Nathan Froyd
            default:
11788 ea63e2c3 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
11789 ea63e2c3 Nathan Froyd
                break;
11790 ea63e2c3 Nathan Froyd
            }
11791 ea63e2c3 Nathan Froyd
            break;
11792 ea63e2c3 Nathan Froyd
        case OPC_DSRL32:
11793 ea63e2c3 Nathan Froyd
            switch ((ctx->opcode >> 21) & 0x1f) {
11794 ea63e2c3 Nathan Froyd
            case 1:
11795 ea63e2c3 Nathan Froyd
                /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
11796 ea63e2c3 Nathan Froyd
                if (env->insn_flags & ISA_MIPS32R2) {
11797 ea63e2c3 Nathan Froyd
                    op1 = OPC_DROTR32;
11798 ea63e2c3 Nathan Froyd
                }
11799 ea63e2c3 Nathan Froyd
                /* Fallthrough */
11800 ea63e2c3 Nathan Froyd
            case 0:
11801 ea63e2c3 Nathan Froyd
                check_insn(env, ctx, ISA_MIPS3);
11802 ea63e2c3 Nathan Froyd
                check_mips_64(ctx);
11803 ea63e2c3 Nathan Froyd
                gen_shift_imm(env, ctx, op1, rd, rt, sa);
11804 ea63e2c3 Nathan Froyd
                break;
11805 ea63e2c3 Nathan Froyd
            default:
11806 ea63e2c3 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
11807 ea63e2c3 Nathan Froyd
                break;
11808 ea63e2c3 Nathan Froyd
            }
11809 ea63e2c3 Nathan Froyd
            break;
11810 7a387fff ths
        case OPC_DADD ... OPC_DSUBU:
11811 e189e748 ths
            check_insn(env, ctx, ISA_MIPS3);
11812 e189e748 ths
            check_mips_64(ctx);
11813 e189e748 ths
            gen_arith(env, ctx, op1, rd, rs, rt);
11814 7a387fff ths
            break;
11815 460f00c4 aurel32
        case OPC_DSLLV:
11816 460f00c4 aurel32
        case OPC_DSRAV:
11817 460f00c4 aurel32
            check_insn(env, ctx, ISA_MIPS3);
11818 460f00c4 aurel32
            check_mips_64(ctx);
11819 460f00c4 aurel32
            gen_shift(env, ctx, op1, rd, rs, rt);
11820 460f00c4 aurel32
            break;
11821 ea63e2c3 Nathan Froyd
        case OPC_DSRLV:
11822 ea63e2c3 Nathan Froyd
            switch ((ctx->opcode >> 6) & 0x1f) {
11823 ea63e2c3 Nathan Froyd
            case 1:
11824 ea63e2c3 Nathan Froyd
                /* drotrv is decoded as dsrlv on non-R2 CPUs */
11825 ea63e2c3 Nathan Froyd
                if (env->insn_flags & ISA_MIPS32R2) {
11826 ea63e2c3 Nathan Froyd
                    op1 = OPC_DROTRV;
11827 ea63e2c3 Nathan Froyd
                }
11828 ea63e2c3 Nathan Froyd
                /* Fallthrough */
11829 ea63e2c3 Nathan Froyd
            case 0:
11830 ea63e2c3 Nathan Froyd
                check_insn(env, ctx, ISA_MIPS3);
11831 ea63e2c3 Nathan Froyd
                check_mips_64(ctx);
11832 ea63e2c3 Nathan Froyd
                gen_shift(env, ctx, op1, rd, rs, rt);
11833 ea63e2c3 Nathan Froyd
                break;
11834 ea63e2c3 Nathan Froyd
            default:
11835 ea63e2c3 Nathan Froyd
                generate_exception(ctx, EXCP_RI);
11836 ea63e2c3 Nathan Froyd
                break;
11837 ea63e2c3 Nathan Froyd
            }
11838 ea63e2c3 Nathan Froyd
            break;
11839 7a387fff ths
        case OPC_DMULT ... OPC_DDIVU:
11840 e189e748 ths
            check_insn(env, ctx, ISA_MIPS3);
11841 e189e748 ths
            check_mips_64(ctx);
11842 7a387fff ths
            gen_muldiv(ctx, op1, rs, rt);
11843 7a387fff ths
            break;
11844 6af0bf9c bellard
#endif
11845 6af0bf9c bellard
        default:            /* Invalid */
11846 6af0bf9c bellard
            MIPS_INVAL("special");
11847 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
11848 6af0bf9c bellard
            break;
11849 6af0bf9c bellard
        }
11850 6af0bf9c bellard
        break;
11851 7a387fff ths
    case OPC_SPECIAL2:
11852 7a387fff ths
        op1 = MASK_SPECIAL2(ctx->opcode);
11853 6af0bf9c bellard
        switch (op1) {
11854 7a387fff ths
        case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11855 7a387fff ths
        case OPC_MSUB ... OPC_MSUBU:
11856 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32);
11857 7a387fff ths
            gen_muldiv(ctx, op1, rs, rt);
11858 6af0bf9c bellard
            break;
11859 7a387fff ths
        case OPC_MUL:
11860 e189e748 ths
            gen_arith(env, ctx, op1, rd, rs, rt);
11861 6af0bf9c bellard
            break;
11862 20e1fb52 aurel32
        case OPC_CLO:
11863 20e1fb52 aurel32
        case OPC_CLZ:
11864 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32);
11865 7a387fff ths
            gen_cl(ctx, op1, rd, rs);
11866 6af0bf9c bellard
            break;
11867 7a387fff ths
        case OPC_SDBBP:
11868 6af0bf9c bellard
            /* XXX: not clear which exception should be raised
11869 6af0bf9c bellard
             *      when in debug mode...
11870 6af0bf9c bellard
             */
11871 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32);
11872 6af0bf9c bellard
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11873 6af0bf9c bellard
                generate_exception(ctx, EXCP_DBp);
11874 6af0bf9c bellard
            } else {
11875 6af0bf9c bellard
                generate_exception(ctx, EXCP_DBp);
11876 6af0bf9c bellard
            }
11877 ead9360e ths
            /* Treat as NOP. */
11878 6af0bf9c bellard
            break;
11879 161f85e6 Aurelien Jarno
        case OPC_DIV_G_2F:
11880 161f85e6 Aurelien Jarno
        case OPC_DIVU_G_2F:
11881 161f85e6 Aurelien Jarno
        case OPC_MULT_G_2F:
11882 161f85e6 Aurelien Jarno
        case OPC_MULTU_G_2F:
11883 161f85e6 Aurelien Jarno
        case OPC_MOD_G_2F:
11884 161f85e6 Aurelien Jarno
        case OPC_MODU_G_2F:
11885 161f85e6 Aurelien Jarno
            check_insn(env, ctx, INSN_LOONGSON2F);
11886 161f85e6 Aurelien Jarno
            gen_loongson_integer(ctx, op1, rd, rs, rt);
11887 161f85e6 Aurelien Jarno
            break;
11888 d26bc211 ths
#if defined(TARGET_MIPS64)
11889 20e1fb52 aurel32
        case OPC_DCLO:
11890 20e1fb52 aurel32
        case OPC_DCLZ:
11891 e189e748 ths
            check_insn(env, ctx, ISA_MIPS64);
11892 e189e748 ths
            check_mips_64(ctx);
11893 7a387fff ths
            gen_cl(ctx, op1, rd, rs);
11894 7a387fff ths
            break;
11895 161f85e6 Aurelien Jarno
        case OPC_DMULT_G_2F:
11896 161f85e6 Aurelien Jarno
        case OPC_DMULTU_G_2F:
11897 161f85e6 Aurelien Jarno
        case OPC_DDIV_G_2F:
11898 161f85e6 Aurelien Jarno
        case OPC_DDIVU_G_2F:
11899 161f85e6 Aurelien Jarno
        case OPC_DMOD_G_2F:
11900 161f85e6 Aurelien Jarno
        case OPC_DMODU_G_2F:
11901 161f85e6 Aurelien Jarno
            check_insn(env, ctx, INSN_LOONGSON2F);
11902 161f85e6 Aurelien Jarno
            gen_loongson_integer(ctx, op1, rd, rs, rt);
11903 161f85e6 Aurelien Jarno
            break;
11904 7a387fff ths
#endif
11905 6af0bf9c bellard
        default:            /* Invalid */
11906 6af0bf9c bellard
            MIPS_INVAL("special2");
11907 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
11908 6af0bf9c bellard
            break;
11909 6af0bf9c bellard
        }
11910 6af0bf9c bellard
        break;
11911 7a387fff ths
    case OPC_SPECIAL3:
11912 2b0233ab ths
        op1 = MASK_SPECIAL3(ctx->opcode);
11913 2b0233ab ths
        switch (op1) {
11914 2b0233ab ths
        case OPC_EXT:
11915 2b0233ab ths
        case OPC_INS:
11916 2b0233ab ths
            check_insn(env, ctx, ISA_MIPS32R2);
11917 2b0233ab ths
            gen_bitops(ctx, op1, rt, rs, sa, rd);
11918 2b0233ab ths
            break;
11919 2b0233ab ths
        case OPC_BSHFL:
11920 2b0233ab ths
            check_insn(env, ctx, ISA_MIPS32R2);
11921 2b0233ab ths
            op2 = MASK_BSHFL(ctx->opcode);
11922 49bcf33c aurel32
            gen_bshfl(ctx, op2, rt, rd);
11923 7a387fff ths
            break;
11924 1579a72e ths
        case OPC_RDHWR:
11925 26ebe468 Nathan Froyd
            gen_rdhwr(env, ctx, rt, rd);
11926 1579a72e ths
            break;
11927 ead9360e ths
        case OPC_FORK:
11928 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
11929 6c5c1e20 ths
            {
11930 35fbce2c aurel32
                TCGv t0 = tcg_temp_new();
11931 35fbce2c aurel32
                TCGv t1 = tcg_temp_new();
11932 6c5c1e20 ths
11933 6c5c1e20 ths
                gen_load_gpr(t0, rt);
11934 6c5c1e20 ths
                gen_load_gpr(t1, rs);
11935 a7812ae4 pbrook
                gen_helper_fork(t0, t1);
11936 6c5c1e20 ths
                tcg_temp_free(t0);
11937 6c5c1e20 ths
                tcg_temp_free(t1);
11938 6c5c1e20 ths
            }
11939 ead9360e ths
            break;
11940 ead9360e ths
        case OPC_YIELD:
11941 7385ac0b ths
            check_insn(env, ctx, ASE_MT);
11942 6c5c1e20 ths
            {
11943 35fbce2c aurel32
                TCGv t0 = tcg_temp_new();
11944 6c5c1e20 ths
11945 35fbce2c aurel32
                save_cpu_state(ctx, 1);
11946 6c5c1e20 ths
                gen_load_gpr(t0, rs);
11947 a7812ae4 pbrook
                gen_helper_yield(t0, t0);
11948 6c5c1e20 ths
                gen_store_gpr(t0, rd);
11949 6c5c1e20 ths
                tcg_temp_free(t0);
11950 6c5c1e20 ths
            }
11951 ead9360e ths
            break;
11952 161f85e6 Aurelien Jarno
        case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
11953 161f85e6 Aurelien Jarno
        case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
11954 161f85e6 Aurelien Jarno
        case OPC_MOD_G_2E ... OPC_MODU_G_2E:
11955 161f85e6 Aurelien Jarno
            check_insn(env, ctx, INSN_LOONGSON2E);
11956 161f85e6 Aurelien Jarno
            gen_loongson_integer(ctx, op1, rd, rs, rt);
11957 161f85e6 Aurelien Jarno
            break;
11958 d26bc211 ths
#if defined(TARGET_MIPS64)
11959 1579a72e ths
        case OPC_DEXTM ... OPC_DEXT:
11960 1579a72e ths
        case OPC_DINSM ... OPC_DINS:
11961 e189e748 ths
            check_insn(env, ctx, ISA_MIPS64R2);
11962 e189e748 ths
            check_mips_64(ctx);
11963 1579a72e ths
            gen_bitops(ctx, op1, rt, rs, sa, rd);
11964 7a387fff ths
            break;
11965 1579a72e ths
        case OPC_DBSHFL:
11966 e189e748 ths
            check_insn(env, ctx, ISA_MIPS64R2);
11967 e189e748 ths
            check_mips_64(ctx);
11968 1579a72e ths
            op2 = MASK_DBSHFL(ctx->opcode);
11969 49bcf33c aurel32
            gen_bshfl(ctx, op2, rt, rd);
11970 c6d6dd7c ths
            break;
11971 161f85e6 Aurelien Jarno
        case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
11972 161f85e6 Aurelien Jarno
        case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
11973 161f85e6 Aurelien Jarno
        case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
11974 161f85e6 Aurelien Jarno
            check_insn(env, ctx, INSN_LOONGSON2E);
11975 161f85e6 Aurelien Jarno
            gen_loongson_integer(ctx, op1, rd, rs, rt);
11976 161f85e6 Aurelien Jarno
            break;
11977 7a387fff ths
#endif
11978 7a387fff ths
        default:            /* Invalid */
11979 7a387fff ths
            MIPS_INVAL("special3");
11980 7a387fff ths
            generate_exception(ctx, EXCP_RI);
11981 7a387fff ths
            break;
11982 7a387fff ths
        }
11983 7a387fff ths
        break;
11984 7a387fff ths
    case OPC_REGIMM:
11985 7a387fff ths
        op1 = MASK_REGIMM(ctx->opcode);
11986 7a387fff ths
        switch (op1) {
11987 7a387fff ths
        case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
11988 7a387fff ths
        case OPC_BLTZAL ... OPC_BGEZALL:
11989 7dca4ad0 Nathan Froyd
            gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
11990 c9602061 Nathan Froyd
            *is_branch = 1;
11991 c9602061 Nathan Froyd
            break;
11992 7a387fff ths
        case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
11993 7a387fff ths
        case OPC_TNEI:
11994 7a387fff ths
            gen_trap(ctx, op1, rs, -1, imm);
11995 7a387fff ths
            break;
11996 7a387fff ths
        case OPC_SYNCI:
11997 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
11998 ead9360e ths
            /* Treat as NOP. */
11999 6af0bf9c bellard
            break;
12000 6af0bf9c bellard
        default:            /* Invalid */
12001 923617a3 ths
            MIPS_INVAL("regimm");
12002 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
12003 6af0bf9c bellard
            break;
12004 6af0bf9c bellard
        }
12005 6af0bf9c bellard
        break;
12006 7a387fff ths
    case OPC_CP0:
12007 387a8fe5 ths
        check_cp0_enabled(ctx);
12008 7a387fff ths
        op1 = MASK_CP0(ctx->opcode);
12009 6af0bf9c bellard
        switch (op1) {
12010 7a387fff ths
        case OPC_MFC0:
12011 7a387fff ths
        case OPC_MTC0:
12012 ead9360e ths
        case OPC_MFTR:
12013 ead9360e ths
        case OPC_MTTR:
12014 d26bc211 ths
#if defined(TARGET_MIPS64)
12015 7a387fff ths
        case OPC_DMFC0:
12016 7a387fff ths
        case OPC_DMTC0:
12017 7a387fff ths
#endif
12018 f1aa6320 ths
#ifndef CONFIG_USER_ONLY
12019 932e71cd aurel32
            gen_cp0(env, ctx, op1, rt, rd);
12020 0eaef5aa ths
#endif /* !CONFIG_USER_ONLY */
12021 7a387fff ths
            break;
12022 7a387fff ths
        case OPC_C0_FIRST ... OPC_C0_LAST:
12023 f1aa6320 ths
#ifndef CONFIG_USER_ONLY
12024 932e71cd aurel32
            gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
12025 0eaef5aa ths
#endif /* !CONFIG_USER_ONLY */
12026 7a387fff ths
            break;
12027 7a387fff ths
        case OPC_MFMC0:
12028 8706c382 ths
#ifndef CONFIG_USER_ONLY
12029 932e71cd aurel32
            {
12030 35fbce2c aurel32
                TCGv t0 = tcg_temp_new();
12031 6c5c1e20 ths
12032 0eaef5aa ths
                op2 = MASK_MFMC0(ctx->opcode);
12033 6c5c1e20 ths
                switch (op2) {
12034 6c5c1e20 ths
                case OPC_DMT:
12035 6c5c1e20 ths
                    check_insn(env, ctx, ASE_MT);
12036 a7812ae4 pbrook
                    gen_helper_dmt(t0, t0);
12037 35fbce2c aurel32
                    gen_store_gpr(t0, rt);
12038 6c5c1e20 ths
                    break;
12039 6c5c1e20 ths
                case OPC_EMT:
12040 6c5c1e20 ths
                    check_insn(env, ctx, ASE_MT);
12041 a7812ae4 pbrook
                    gen_helper_emt(t0, t0);
12042 35fbce2c aurel32
                    gen_store_gpr(t0, rt);
12043 da80682b aurel32
                    break;
12044 6c5c1e20 ths
                case OPC_DVPE:
12045 6c5c1e20 ths
                    check_insn(env, ctx, ASE_MT);
12046 a7812ae4 pbrook
                    gen_helper_dvpe(t0, t0);
12047 35fbce2c aurel32
                    gen_store_gpr(t0, rt);
12048 6c5c1e20 ths
                    break;
12049 6c5c1e20 ths
                case OPC_EVPE:
12050 6c5c1e20 ths
                    check_insn(env, ctx, ASE_MT);
12051 a7812ae4 pbrook
                    gen_helper_evpe(t0, t0);
12052 35fbce2c aurel32
                    gen_store_gpr(t0, rt);
12053 6c5c1e20 ths
                    break;
12054 6c5c1e20 ths
                case OPC_DI:
12055 6c5c1e20 ths
                    check_insn(env, ctx, ISA_MIPS32R2);
12056 867abc7e aurel32
                    save_cpu_state(ctx, 1);
12057 a7812ae4 pbrook
                    gen_helper_di(t0);
12058 35fbce2c aurel32
                    gen_store_gpr(t0, rt);
12059 6c5c1e20 ths
                    /* Stop translation as we may have switched the execution mode */
12060 6c5c1e20 ths
                    ctx->bstate = BS_STOP;
12061 6c5c1e20 ths
                    break;
12062 6c5c1e20 ths
                case OPC_EI:
12063 6c5c1e20 ths
                    check_insn(env, ctx, ISA_MIPS32R2);
12064 867abc7e aurel32
                    save_cpu_state(ctx, 1);
12065 a7812ae4 pbrook
                    gen_helper_ei(t0);
12066 35fbce2c aurel32
                    gen_store_gpr(t0, rt);
12067 6c5c1e20 ths
                    /* Stop translation as we may have switched the execution mode */
12068 6c5c1e20 ths
                    ctx->bstate = BS_STOP;
12069 6c5c1e20 ths
                    break;
12070 6c5c1e20 ths
                default:            /* Invalid */
12071 6c5c1e20 ths
                    MIPS_INVAL("mfmc0");
12072 6c5c1e20 ths
                    generate_exception(ctx, EXCP_RI);
12073 6c5c1e20 ths
                    break;
12074 6c5c1e20 ths
                }
12075 6c5c1e20 ths
                tcg_temp_free(t0);
12076 7a387fff ths
            }
12077 0eaef5aa ths
#endif /* !CONFIG_USER_ONLY */
12078 6af0bf9c bellard
            break;
12079 7a387fff ths
        case OPC_RDPGPR:
12080 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
12081 be24bb4f ths
            gen_load_srsgpr(rt, rd);
12082 ead9360e ths
            break;
12083 7a387fff ths
        case OPC_WRPGPR:
12084 e189e748 ths
            check_insn(env, ctx, ISA_MIPS32R2);
12085 be24bb4f ths
            gen_store_srsgpr(rt, rd);
12086 38121543 ths
            break;
12087 6af0bf9c bellard
        default:
12088 923617a3 ths
            MIPS_INVAL("cp0");
12089 7a387fff ths
            generate_exception(ctx, EXCP_RI);
12090 6af0bf9c bellard
            break;
12091 6af0bf9c bellard
        }
12092 6af0bf9c bellard
        break;
12093 324d9e32 aurel32
    case OPC_ADDI: /* Arithmetic with immediate opcode */
12094 324d9e32 aurel32
    case OPC_ADDIU:
12095 e189e748 ths
         gen_arith_imm(env, ctx, op, rt, rs, imm);
12096 7a387fff ths
         break;
12097 324d9e32 aurel32
    case OPC_SLTI: /* Set on less than with immediate opcode */
12098 324d9e32 aurel32
    case OPC_SLTIU:
12099 324d9e32 aurel32
         gen_slt_imm(env, op, rt, rs, imm);
12100 324d9e32 aurel32
         break;
12101 324d9e32 aurel32
    case OPC_ANDI: /* Arithmetic with immediate opcode */
12102 324d9e32 aurel32
    case OPC_LUI:
12103 324d9e32 aurel32
    case OPC_ORI:
12104 324d9e32 aurel32
    case OPC_XORI:
12105 324d9e32 aurel32
         gen_logic_imm(env, op, rt, rs, imm);
12106 324d9e32 aurel32
         break;
12107 7a387fff ths
    case OPC_J ... OPC_JAL: /* Jump */
12108 7a387fff ths
         offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12109 7dca4ad0 Nathan Froyd
         gen_compute_branch(ctx, op, 4, rs, rt, offset);
12110 c9602061 Nathan Froyd
         *is_branch = 1;
12111 c9602061 Nathan Froyd
         break;
12112 7a387fff ths
    case OPC_BEQ ... OPC_BGTZ: /* Branch */
12113 7a387fff ths
    case OPC_BEQL ... OPC_BGTZL:
12114 7dca4ad0 Nathan Froyd
         gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
12115 c9602061 Nathan Froyd
         *is_branch = 1;
12116 c9602061 Nathan Froyd
         break;
12117 7a387fff ths
    case OPC_LB ... OPC_LWR: /* Load and stores */
12118 5c13fdfd Aurelien Jarno
    case OPC_LL:
12119 afa88c3a Aurelien Jarno
         gen_ld(env, ctx, op, rt, rs, imm);
12120 5c13fdfd Aurelien Jarno
         break;
12121 7a387fff ths
    case OPC_SB ... OPC_SW:
12122 7a387fff ths
    case OPC_SWR:
12123 5c13fdfd Aurelien Jarno
         gen_st(ctx, op, rt, rs, imm);
12124 7a387fff ths
         break;
12125 d66c7132 aurel32
    case OPC_SC:
12126 d66c7132 aurel32
         gen_st_cond(ctx, op, rt, rs, imm);
12127 d66c7132 aurel32
         break;
12128 7a387fff ths
    case OPC_CACHE:
12129 e189e748 ths
        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
12130 ead9360e ths
        /* Treat as NOP. */
12131 34ae7b51 ths
        break;
12132 7a387fff ths
    case OPC_PREF:
12133 e189e748 ths
        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
12134 ead9360e ths
        /* Treat as NOP. */
12135 6af0bf9c bellard
        break;
12136 4ad40f36 bellard
12137 923617a3 ths
    /* Floating point (COP1). */
12138 7a387fff ths
    case OPC_LWC1:
12139 7a387fff ths
    case OPC_LDC1:
12140 7a387fff ths
    case OPC_SWC1:
12141 7a387fff ths
    case OPC_SDC1:
12142 26ebe468 Nathan Froyd
        gen_cop1_ldst(env, ctx, op, rt, rs, imm);
12143 6ea83fed bellard
        break;
12144 6ea83fed bellard
12145 7a387fff ths
    case OPC_CP1:
12146 36d23958 ths
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12147 5e755519 ths
            check_cp1_enabled(ctx);
12148 36d23958 ths
            op1 = MASK_CP1(ctx->opcode);
12149 36d23958 ths
            switch (op1) {
12150 3a95e3a7 ths
            case OPC_MFHC1:
12151 3a95e3a7 ths
            case OPC_MTHC1:
12152 e189e748 ths
                check_insn(env, ctx, ISA_MIPS32R2);
12153 36d23958 ths
            case OPC_MFC1:
12154 36d23958 ths
            case OPC_CFC1:
12155 36d23958 ths
            case OPC_MTC1:
12156 36d23958 ths
            case OPC_CTC1:
12157 e189e748 ths
                gen_cp1(ctx, op1, rt, rd);
12158 e189e748 ths
                break;
12159 d26bc211 ths
#if defined(TARGET_MIPS64)
12160 36d23958 ths
            case OPC_DMFC1:
12161 36d23958 ths
            case OPC_DMTC1:
12162 e189e748 ths
                check_insn(env, ctx, ISA_MIPS3);
12163 36d23958 ths
                gen_cp1(ctx, op1, rt, rd);
12164 36d23958 ths
                break;
12165 e189e748 ths
#endif
12166 fbcc6828 ths
            case OPC_BC1ANY2:
12167 fbcc6828 ths
            case OPC_BC1ANY4:
12168 b8aa4598 ths
                check_cop1x(ctx);
12169 7385ac0b ths
                check_insn(env, ctx, ASE_MIPS3D);
12170 d8a5950a ths
                /* fall through */
12171 d8a5950a ths
            case OPC_BC1:
12172 e189e748 ths
                gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
12173 5a5012ec ths
                                    (rt >> 2) & 0x7, imm << 2);
12174 c9602061 Nathan Froyd
                *is_branch = 1;
12175 c9602061 Nathan Froyd
                break;
12176 36d23958 ths
            case OPC_S_FMT:
12177 36d23958 ths
            case OPC_D_FMT:
12178 36d23958 ths
            case OPC_W_FMT:
12179 36d23958 ths
            case OPC_L_FMT:
12180 5a5012ec ths
            case OPC_PS_FMT:
12181 bf4120ad Nathan Froyd
                gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
12182 5a5012ec ths
                           (imm >> 8) & 0x7);
12183 36d23958 ths
                break;
12184 36d23958 ths
            default:
12185 923617a3 ths
                MIPS_INVAL("cp1");
12186 e397ee33 ths
                generate_exception (ctx, EXCP_RI);
12187 36d23958 ths
                break;
12188 36d23958 ths
            }
12189 36d23958 ths
        } else {
12190 36d23958 ths
            generate_exception_err(ctx, EXCP_CpU, 1);
12191 6ea83fed bellard
        }
12192 4ad40f36 bellard
        break;
12193 4ad40f36 bellard
12194 4ad40f36 bellard
    /* COP2.  */
12195 7a387fff ths
    case OPC_LWC2:
12196 7a387fff ths
    case OPC_LDC2:
12197 7a387fff ths
    case OPC_SWC2:
12198 7a387fff ths
    case OPC_SDC2:
12199 7a387fff ths
    case OPC_CP2:
12200 7a387fff ths
        /* COP2: Not implemented. */
12201 4ad40f36 bellard
        generate_exception_err(ctx, EXCP_CpU, 2);
12202 4ad40f36 bellard
        break;
12203 4ad40f36 bellard
12204 7a387fff ths
    case OPC_CP3:
12205 36d23958 ths
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12206 5e755519 ths
            check_cp1_enabled(ctx);
12207 36d23958 ths
            op1 = MASK_CP3(ctx->opcode);
12208 36d23958 ths
            switch (op1) {
12209 5a5012ec ths
            case OPC_LWXC1:
12210 5a5012ec ths
            case OPC_LDXC1:
12211 5a5012ec ths
            case OPC_LUXC1:
12212 5a5012ec ths
            case OPC_SWXC1:
12213 5a5012ec ths
            case OPC_SDXC1:
12214 5a5012ec ths
            case OPC_SUXC1:
12215 93b12ccc ths
                gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
12216 5a5012ec ths
                break;
12217 e0c84da7 ths
            case OPC_PREFX:
12218 ead9360e ths
                /* Treat as NOP. */
12219 e0c84da7 ths
                break;
12220 5a5012ec ths
            case OPC_ALNV_PS:
12221 5a5012ec ths
            case OPC_MADD_S:
12222 5a5012ec ths
            case OPC_MADD_D:
12223 5a5012ec ths
            case OPC_MADD_PS:
12224 5a5012ec ths
            case OPC_MSUB_S:
12225 5a5012ec ths
            case OPC_MSUB_D:
12226 5a5012ec ths
            case OPC_MSUB_PS:
12227 5a5012ec ths
            case OPC_NMADD_S:
12228 5a5012ec ths
            case OPC_NMADD_D:
12229 5a5012ec ths
            case OPC_NMADD_PS:
12230 5a5012ec ths
            case OPC_NMSUB_S:
12231 5a5012ec ths
            case OPC_NMSUB_D:
12232 5a5012ec ths
            case OPC_NMSUB_PS:
12233 5a5012ec ths
                gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12234 5a5012ec ths
                break;
12235 36d23958 ths
            default:
12236 923617a3 ths
                MIPS_INVAL("cp3");
12237 e397ee33 ths
                generate_exception (ctx, EXCP_RI);
12238 36d23958 ths
                break;
12239 36d23958 ths
            }
12240 36d23958 ths
        } else {
12241 e397ee33 ths
            generate_exception_err(ctx, EXCP_CpU, 1);
12242 7a387fff ths
        }
12243 4ad40f36 bellard
        break;
12244 4ad40f36 bellard
12245 d26bc211 ths
#if defined(TARGET_MIPS64)
12246 7a387fff ths
    /* MIPS64 opcodes */
12247 7a387fff ths
    case OPC_LWU:
12248 7a387fff ths
    case OPC_LDL ... OPC_LDR:
12249 7a387fff ths
    case OPC_LLD:
12250 7a387fff ths
    case OPC_LD:
12251 5c13fdfd Aurelien Jarno
        check_insn(env, ctx, ISA_MIPS3);
12252 5c13fdfd Aurelien Jarno
        check_mips_64(ctx);
12253 afa88c3a Aurelien Jarno
        gen_ld(env, ctx, op, rt, rs, imm);
12254 5c13fdfd Aurelien Jarno
        break;
12255 5c13fdfd Aurelien Jarno
    case OPC_SDL ... OPC_SDR:
12256 7a387fff ths
    case OPC_SD:
12257 e189e748 ths
        check_insn(env, ctx, ISA_MIPS3);
12258 e189e748 ths
        check_mips_64(ctx);
12259 5c13fdfd Aurelien Jarno
        gen_st(ctx, op, rt, rs, imm);
12260 7a387fff ths
        break;
12261 d66c7132 aurel32
    case OPC_SCD:
12262 d66c7132 aurel32
        check_insn(env, ctx, ISA_MIPS3);
12263 d66c7132 aurel32
        check_mips_64(ctx);
12264 d66c7132 aurel32
        gen_st_cond(ctx, op, rt, rs, imm);
12265 d66c7132 aurel32
        break;
12266 324d9e32 aurel32
    case OPC_DADDI:
12267 324d9e32 aurel32
    case OPC_DADDIU:
12268 e189e748 ths
        check_insn(env, ctx, ISA_MIPS3);
12269 e189e748 ths
        check_mips_64(ctx);
12270 e189e748 ths
        gen_arith_imm(env, ctx, op, rt, rs, imm);
12271 7a387fff ths
        break;
12272 6af0bf9c bellard
#endif
12273 7a387fff ths
    case OPC_JALX:
12274 3c824109 Nathan Froyd
        check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
12275 364d4831 Nathan Froyd
        offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12276 364d4831 Nathan Froyd
        gen_compute_branch(ctx, op, 4, rs, rt, offset);
12277 364d4831 Nathan Froyd
        *is_branch = 1;
12278 364d4831 Nathan Froyd
        break;
12279 7a387fff ths
    case OPC_MDMX:
12280 e189e748 ths
        check_insn(env, ctx, ASE_MDMX);
12281 7a387fff ths
        /* MDMX: Not implemented. */
12282 6af0bf9c bellard
    default:            /* Invalid */
12283 923617a3 ths
        MIPS_INVAL("major opcode");
12284 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
12285 6af0bf9c bellard
        break;
12286 6af0bf9c bellard
    }
12287 6af0bf9c bellard
}
12288 6af0bf9c bellard
12289 2cfc5f17 ths
static inline void
12290 820e00f2 ths
gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
12291 820e00f2 ths
                                int search_pc)
12292 6af0bf9c bellard
{
12293 278d0702 ths
    DisasContext ctx;
12294 6af0bf9c bellard
    target_ulong pc_start;
12295 6af0bf9c bellard
    uint16_t *gen_opc_end;
12296 a1d1bb31 aliguori
    CPUBreakpoint *bp;
12297 6af0bf9c bellard
    int j, lj = -1;
12298 2e70f6ef pbrook
    int num_insns;
12299 2e70f6ef pbrook
    int max_insns;
12300 c9602061 Nathan Froyd
    int insn_bytes;
12301 c9602061 Nathan Froyd
    int is_branch;
12302 6af0bf9c bellard
12303 93fcfe39 aliguori
    if (search_pc)
12304 93fcfe39 aliguori
        qemu_log("search pc %d\n", search_pc);
12305 4ad40f36 bellard
12306 6af0bf9c bellard
    pc_start = tb->pc;
12307 d42320c2 Aurelien Jarno
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
12308 6af0bf9c bellard
    ctx.pc = pc_start;
12309 4ad40f36 bellard
    ctx.saved_pc = -1;
12310 7b270ef2 Nathan Froyd
    ctx.singlestep_enabled = env->singlestep_enabled;
12311 6af0bf9c bellard
    ctx.tb = tb;
12312 6af0bf9c bellard
    ctx.bstate = BS_NONE;
12313 4ad40f36 bellard
    /* Restore delay slot state from the tb context.  */
12314 c068688b j_mayer
    ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
12315 fd4a04eb ths
    restore_cpu_state(env, &ctx);
12316 932e71cd aurel32
#ifdef CONFIG_USER_ONLY
12317 0eaef5aa ths
        ctx.mem_idx = MIPS_HFLAG_UM;
12318 932e71cd aurel32
#else
12319 0eaef5aa ths
        ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
12320 932e71cd aurel32
#endif
12321 2e70f6ef pbrook
    num_insns = 0;
12322 2e70f6ef pbrook
    max_insns = tb->cflags & CF_COUNT_MASK;
12323 2e70f6ef pbrook
    if (max_insns == 0)
12324 2e70f6ef pbrook
        max_insns = CF_COUNT_MASK;
12325 d12d51d5 aliguori
    LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
12326 2e70f6ef pbrook
    gen_icount_start();
12327 faf7aaa9 ths
    while (ctx.bstate == BS_NONE) {
12328 72cf2d4f Blue Swirl
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12329 72cf2d4f Blue Swirl
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
12330 a1d1bb31 aliguori
                if (bp->pc == ctx.pc) {
12331 278d0702 ths
                    save_cpu_state(&ctx, 1);
12332 4ad40f36 bellard
                    ctx.bstate = BS_BRANCH;
12333 a7812ae4 pbrook
                    gen_helper_0i(raise_exception, EXCP_DEBUG);
12334 ce62e5ba ths
                    /* Include the breakpoint location or the tb won't
12335 ce62e5ba ths
                     * be flushed when it must be.  */
12336 ce62e5ba ths
                    ctx.pc += 4;
12337 4ad40f36 bellard
                    goto done_generating;
12338 4ad40f36 bellard
                }
12339 4ad40f36 bellard
            }
12340 4ad40f36 bellard
        }
12341 4ad40f36 bellard
12342 6af0bf9c bellard
        if (search_pc) {
12343 6af0bf9c bellard
            j = gen_opc_ptr - gen_opc_buf;
12344 6af0bf9c bellard
            if (lj < j) {
12345 6af0bf9c bellard
                lj++;
12346 6af0bf9c bellard
                while (lj < j)
12347 6af0bf9c bellard
                    gen_opc_instr_start[lj++] = 0;
12348 6af0bf9c bellard
            }
12349 4ad40f36 bellard
            gen_opc_pc[lj] = ctx.pc;
12350 4ad40f36 bellard
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12351 4ad40f36 bellard
            gen_opc_instr_start[lj] = 1;
12352 2e70f6ef pbrook
            gen_opc_icount[lj] = num_insns;
12353 6af0bf9c bellard
        }
12354 2e70f6ef pbrook
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12355 2e70f6ef pbrook
            gen_io_start();
12356 c9602061 Nathan Froyd
12357 c9602061 Nathan Froyd
        is_branch = 0;
12358 364d4831 Nathan Froyd
        if (!(ctx.hflags & MIPS_HFLAG_M16)) {
12359 c9602061 Nathan Froyd
            ctx.opcode = ldl_code(ctx.pc);
12360 c9602061 Nathan Froyd
            insn_bytes = 4;
12361 c9602061 Nathan Froyd
            decode_opc(env, &ctx, &is_branch);
12362 3c824109 Nathan Froyd
        } else if (env->insn_flags & ASE_MICROMIPS) {
12363 3c824109 Nathan Froyd
            ctx.opcode = lduw_code(ctx.pc);
12364 3c824109 Nathan Froyd
            insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
12365 364d4831 Nathan Froyd
        } else if (env->insn_flags & ASE_MIPS16) {
12366 364d4831 Nathan Froyd
            ctx.opcode = lduw_code(ctx.pc);
12367 364d4831 Nathan Froyd
            insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
12368 c9602061 Nathan Froyd
        } else {
12369 c9602061 Nathan Froyd
            generate_exception(&ctx, EXCP_RI);
12370 3c824109 Nathan Froyd
            ctx.bstate = BS_STOP;
12371 c9602061 Nathan Froyd
            break;
12372 c9602061 Nathan Froyd
        }
12373 c9602061 Nathan Froyd
        if (!is_branch) {
12374 c9602061 Nathan Froyd
            handle_delay_slot(env, &ctx, insn_bytes);
12375 c9602061 Nathan Froyd
        }
12376 c9602061 Nathan Froyd
        ctx.pc += insn_bytes;
12377 c9602061 Nathan Froyd
12378 2e70f6ef pbrook
        num_insns++;
12379 4ad40f36 bellard
12380 7b270ef2 Nathan Froyd
        /* Execute a branch and its delay slot as a single instruction.
12381 7b270ef2 Nathan Froyd
           This is what GDB expects and is consistent with what the
12382 7b270ef2 Nathan Froyd
           hardware does (e.g. if a delay slot instruction faults, the
12383 7b270ef2 Nathan Froyd
           reported PC is the PC of the branch).  */
12384 7b270ef2 Nathan Froyd
        if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
12385 4ad40f36 bellard
            break;
12386 4ad40f36 bellard
12387 6af0bf9c bellard
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12388 6af0bf9c bellard
            break;
12389 4ad40f36 bellard
12390 faf7aaa9 ths
        if (gen_opc_ptr >= gen_opc_end)
12391 faf7aaa9 ths
            break;
12392 faf7aaa9 ths
12393 2e70f6ef pbrook
        if (num_insns >= max_insns)
12394 2e70f6ef pbrook
            break;
12395 1b530a6d aurel32
12396 1b530a6d aurel32
        if (singlestep)
12397 1b530a6d aurel32
            break;
12398 6af0bf9c bellard
    }
12399 2e70f6ef pbrook
    if (tb->cflags & CF_LAST_IO)
12400 2e70f6ef pbrook
        gen_io_end();
12401 7b270ef2 Nathan Froyd
    if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
12402 278d0702 ths
        save_cpu_state(&ctx, ctx.bstate == BS_NONE);
12403 a7812ae4 pbrook
        gen_helper_0i(raise_exception, EXCP_DEBUG);
12404 16c00cb2 ths
    } else {
12405 6958549d aurel32
        switch (ctx.bstate) {
12406 16c00cb2 ths
        case BS_STOP:
12407 df1561e2 ths
            gen_goto_tb(&ctx, 0, ctx.pc);
12408 df1561e2 ths
            break;
12409 16c00cb2 ths
        case BS_NONE:
12410 278d0702 ths
            save_cpu_state(&ctx, 0);
12411 16c00cb2 ths
            gen_goto_tb(&ctx, 0, ctx.pc);
12412 16c00cb2 ths
            break;
12413 5a5012ec ths
        case BS_EXCP:
12414 57fec1fe bellard
            tcg_gen_exit_tb(0);
12415 16c00cb2 ths
            break;
12416 5a5012ec ths
        case BS_BRANCH:
12417 5a5012ec ths
        default:
12418 5a5012ec ths
            break;
12419 6958549d aurel32
        }
12420 6af0bf9c bellard
    }
12421 4ad40f36 bellard
done_generating:
12422 2e70f6ef pbrook
    gen_icount_end(tb, num_insns);
12423 6af0bf9c bellard
    *gen_opc_ptr = INDEX_op_end;
12424 6af0bf9c bellard
    if (search_pc) {
12425 6af0bf9c bellard
        j = gen_opc_ptr - gen_opc_buf;
12426 6af0bf9c bellard
        lj++;
12427 6af0bf9c bellard
        while (lj <= j)
12428 6af0bf9c bellard
            gen_opc_instr_start[lj++] = 0;
12429 6af0bf9c bellard
    } else {
12430 6af0bf9c bellard
        tb->size = ctx.pc - pc_start;
12431 2e70f6ef pbrook
        tb->icount = num_insns;
12432 6af0bf9c bellard
    }
12433 6af0bf9c bellard
#ifdef DEBUG_DISAS
12434 d12d51d5 aliguori
    LOG_DISAS("\n");
12435 8fec2b8c aliguori
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
12436 93fcfe39 aliguori
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
12437 93fcfe39 aliguori
        log_target_disas(pc_start, ctx.pc - pc_start, 0);
12438 93fcfe39 aliguori
        qemu_log("\n");
12439 6af0bf9c bellard
    }
12440 6af0bf9c bellard
#endif
12441 6af0bf9c bellard
}
12442 6af0bf9c bellard
12443 2cfc5f17 ths
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
12444 6af0bf9c bellard
{
12445 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 0);
12446 6af0bf9c bellard
}
12447 6af0bf9c bellard
12448 2cfc5f17 ths
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
12449 6af0bf9c bellard
{
12450 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 1);
12451 6af0bf9c bellard
}
12452 6af0bf9c bellard
12453 9a78eead Stefan Weil
static void fpu_dump_state(CPUState *env, FILE *f, fprintf_function fpu_fprintf,
12454 8706c382 ths
                           int flags)
12455 6ea83fed bellard
{
12456 6ea83fed bellard
    int i;
12457 5e755519 ths
    int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
12458 5a5012ec ths
12459 2a5612e6 Stefan Weil
#define printfpr(fp)                                                    \
12460 2a5612e6 Stefan Weil
    do {                                                                \
12461 2a5612e6 Stefan Weil
        if (is_fpu64)                                                   \
12462 2a5612e6 Stefan Weil
            fpu_fprintf(f, "w:%08x d:%016" PRIx64                       \
12463 2a5612e6 Stefan Weil
                        " fd:%13g fs:%13g psu: %13g\n",                 \
12464 2a5612e6 Stefan Weil
                        (fp)->w[FP_ENDIAN_IDX], (fp)->d,                \
12465 2a5612e6 Stefan Weil
                        (double)(fp)->fd,                               \
12466 2a5612e6 Stefan Weil
                        (double)(fp)->fs[FP_ENDIAN_IDX],                \
12467 2a5612e6 Stefan Weil
                        (double)(fp)->fs[!FP_ENDIAN_IDX]);              \
12468 2a5612e6 Stefan Weil
        else {                                                          \
12469 2a5612e6 Stefan Weil
            fpr_t tmp;                                                  \
12470 2a5612e6 Stefan Weil
            tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX];              \
12471 2a5612e6 Stefan Weil
            tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX];       \
12472 2a5612e6 Stefan Weil
            fpu_fprintf(f, "w:%08x d:%016" PRIx64                       \
12473 2a5612e6 Stefan Weil
                        " fd:%13g fs:%13g psu:%13g\n",                  \
12474 2a5612e6 Stefan Weil
                        tmp.w[FP_ENDIAN_IDX], tmp.d,                    \
12475 2a5612e6 Stefan Weil
                        (double)tmp.fd,                                 \
12476 2a5612e6 Stefan Weil
                        (double)tmp.fs[FP_ENDIAN_IDX],                  \
12477 2a5612e6 Stefan Weil
                        (double)tmp.fs[!FP_ENDIAN_IDX]);                \
12478 2a5612e6 Stefan Weil
        }                                                               \
12479 6ea83fed bellard
    } while(0)
12480 6ea83fed bellard
12481 5a5012ec ths
12482 9a78eead Stefan Weil
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d  fp_status 0x%02x\n",
12483 9a78eead Stefan Weil
                env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
12484 f01be154 ths
                get_float_exception_flags(&env->active_fpu.fp_status));
12485 5a5012ec ths
    for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12486 5a5012ec ths
        fpu_fprintf(f, "%3s: ", fregnames[i]);
12487 f01be154 ths
        printfpr(&env->active_fpu.fpr[i]);
12488 6ea83fed bellard
    }
12489 6ea83fed bellard
12490 6ea83fed bellard
#undef printfpr
12491 6ea83fed bellard
}
12492 6ea83fed bellard
12493 d26bc211 ths
#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
12494 c570fd16 ths
/* Debug help: The architecture requires 32bit code to maintain proper
12495 c7e8a937 ths
   sign-extended values on 64bit machines.  */
12496 c570fd16 ths
12497 c570fd16 ths
#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12498 c570fd16 ths
12499 8706c382 ths
static void
12500 8706c382 ths
cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
12501 9a78eead Stefan Weil
                                fprintf_function cpu_fprintf,
12502 8706c382 ths
                                int flags)
12503 c570fd16 ths
{
12504 c570fd16 ths
    int i;
12505 c570fd16 ths
12506 b5dc7732 ths
    if (!SIGN_EXT_P(env->active_tc.PC))
12507 b5dc7732 ths
        cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12508 b5dc7732 ths
    if (!SIGN_EXT_P(env->active_tc.HI[0]))
12509 b5dc7732 ths
        cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12510 b5dc7732 ths
    if (!SIGN_EXT_P(env->active_tc.LO[0]))
12511 b5dc7732 ths
        cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
12512 c570fd16 ths
    if (!SIGN_EXT_P(env->btarget))
12513 3594c774 ths
        cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
12514 c570fd16 ths
12515 c570fd16 ths
    for (i = 0; i < 32; i++) {
12516 b5dc7732 ths
        if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12517 b5dc7732 ths
            cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
12518 c570fd16 ths
    }
12519 c570fd16 ths
12520 c570fd16 ths
    if (!SIGN_EXT_P(env->CP0_EPC))
12521 3594c774 ths
        cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
12522 5499b6ff Aurelien Jarno
    if (!SIGN_EXT_P(env->lladdr))
12523 5499b6ff Aurelien Jarno
        cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
12524 c570fd16 ths
}
12525 c570fd16 ths
#endif
12526 c570fd16 ths
12527 9a78eead Stefan Weil
void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
12528 6af0bf9c bellard
                     int flags)
12529 6af0bf9c bellard
{
12530 6af0bf9c bellard
    int i;
12531 3b46e624 ths
12532 a7200c9f Stefan Weil
    cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
12533 a7200c9f Stefan Weil
                " LO=0x" TARGET_FMT_lx " ds %04x "
12534 a7200c9f Stefan Weil
                TARGET_FMT_lx " " TARGET_FMT_ld "\n",
12535 3d5be870 ths
                env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12536 3d5be870 ths
                env->hflags, env->btarget, env->bcond);
12537 6af0bf9c bellard
    for (i = 0; i < 32; i++) {
12538 6af0bf9c bellard
        if ((i & 3) == 0)
12539 6af0bf9c bellard
            cpu_fprintf(f, "GPR%02d:", i);
12540 b5dc7732 ths
        cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
12541 6af0bf9c bellard
        if ((i & 3) == 3)
12542 6af0bf9c bellard
            cpu_fprintf(f, "\n");
12543 6af0bf9c bellard
    }
12544 568b600d bellard
12545 3594c774 ths
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TARGET_FMT_lx "\n",
12546 5e755519 ths
                env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
12547 3594c774 ths
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
12548 5499b6ff Aurelien Jarno
                env->CP0_Config0, env->CP0_Config1, env->lladdr);
12549 5e755519 ths
    if (env->hflags & MIPS_HFLAG_FPU)
12550 7a387fff ths
        fpu_dump_state(env, f, cpu_fprintf, flags);
12551 d26bc211 ths
#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
12552 c570fd16 ths
    cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
12553 c570fd16 ths
#endif
12554 6af0bf9c bellard
}
12555 6af0bf9c bellard
12556 39454628 ths
static void mips_tcg_init(void)
12557 39454628 ths
{
12558 f01be154 ths
    int i;
12559 39454628 ths
    static int inited;
12560 39454628 ths
12561 39454628 ths
    /* Initialize various static tables. */
12562 39454628 ths
    if (inited)
12563 6958549d aurel32
        return;
12564 39454628 ths
12565 a7812ae4 pbrook
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
12566 f2c94b92 aurel32
    TCGV_UNUSED(cpu_gpr[0]);
12567 bb928dbe aurel32
    for (i = 1; i < 32; i++)
12568 a7812ae4 pbrook
        cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
12569 4b2eb8d2 ths
                                        offsetof(CPUState, active_tc.gpr[i]),
12570 4b2eb8d2 ths
                                        regnames[i]);
12571 a7812ae4 pbrook
    cpu_PC = tcg_global_mem_new(TCG_AREG0,
12572 4b2eb8d2 ths
                                offsetof(CPUState, active_tc.PC), "PC");
12573 4b2eb8d2 ths
    for (i = 0; i < MIPS_DSP_ACC; i++) {
12574 a7812ae4 pbrook
        cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
12575 4b2eb8d2 ths
                                       offsetof(CPUState, active_tc.HI[i]),
12576 4b2eb8d2 ths
                                       regnames_HI[i]);
12577 a7812ae4 pbrook
        cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
12578 4b2eb8d2 ths
                                       offsetof(CPUState, active_tc.LO[i]),
12579 4b2eb8d2 ths
                                       regnames_LO[i]);
12580 a7812ae4 pbrook
        cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
12581 4b2eb8d2 ths
                                        offsetof(CPUState, active_tc.ACX[i]),
12582 4b2eb8d2 ths
                                        regnames_ACX[i]);
12583 4b2eb8d2 ths
    }
12584 a7812ae4 pbrook
    cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
12585 4b2eb8d2 ths
                                     offsetof(CPUState, active_tc.DSPControl),
12586 4b2eb8d2 ths
                                     "DSPControl");
12587 1ba74fb8 aurel32
    bcond = tcg_global_mem_new(TCG_AREG0,
12588 1ba74fb8 aurel32
                               offsetof(CPUState, bcond), "bcond");
12589 a7812ae4 pbrook
    btarget = tcg_global_mem_new(TCG_AREG0,
12590 d077b6f7 ths
                                 offsetof(CPUState, btarget), "btarget");
12591 41db4607 aurel32
    hflags = tcg_global_mem_new_i32(TCG_AREG0,
12592 41db4607 aurel32
                                    offsetof(CPUState, hflags), "hflags");
12593 41db4607 aurel32
12594 a7812ae4 pbrook
    fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
12595 a7812ae4 pbrook
                                      offsetof(CPUState, active_fpu.fcr0),
12596 a7812ae4 pbrook
                                      "fcr0");
12597 a7812ae4 pbrook
    fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
12598 a7812ae4 pbrook
                                       offsetof(CPUState, active_fpu.fcr31),
12599 a7812ae4 pbrook
                                       "fcr31");
12600 39454628 ths
12601 7dd9e556 ths
    /* register helpers */
12602 a7812ae4 pbrook
#define GEN_HELPER 2
12603 7dd9e556 ths
#include "helper.h"
12604 7dd9e556 ths
12605 39454628 ths
    inited = 1;
12606 39454628 ths
}
12607 39454628 ths
12608 aaed909a bellard
#include "translate_init.c"
12609 aaed909a bellard
12610 aaed909a bellard
CPUMIPSState *cpu_mips_init (const char *cpu_model)
12611 6af0bf9c bellard
{
12612 6af0bf9c bellard
    CPUMIPSState *env;
12613 c227f099 Anthony Liguori
    const mips_def_t *def;
12614 6af0bf9c bellard
12615 aaed909a bellard
    def = cpu_mips_find_by_name(cpu_model);
12616 aaed909a bellard
    if (!def)
12617 aaed909a bellard
        return NULL;
12618 6af0bf9c bellard
    env = qemu_mallocz(sizeof(CPUMIPSState));
12619 aaed909a bellard
    env->cpu_model = def;
12620 51cc2e78 Blue Swirl
    env->cpu_model_str = cpu_model;
12621 aaed909a bellard
12622 173d6cfe bellard
    cpu_exec_init(env);
12623 51cc2e78 Blue Swirl
#ifndef CONFIG_USER_ONLY
12624 51cc2e78 Blue Swirl
    mmu_init(env, def);
12625 51cc2e78 Blue Swirl
#endif
12626 51cc2e78 Blue Swirl
    fpu_init(env, def);
12627 51cc2e78 Blue Swirl
    mvp_init(env, def);
12628 39454628 ths
    mips_tcg_init();
12629 6ae81775 ths
    cpu_reset(env);
12630 0bf46a40 aliguori
    qemu_init_vcpu(env);
12631 6ae81775 ths
    return env;
12632 6ae81775 ths
}
12633 6ae81775 ths
12634 6ae81775 ths
void cpu_reset (CPUMIPSState *env)
12635 6ae81775 ths
{
12636 eca1bdf4 aliguori
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12637 eca1bdf4 aliguori
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12638 eca1bdf4 aliguori
        log_cpu_state(env, 0);
12639 eca1bdf4 aliguori
    }
12640 eca1bdf4 aliguori
12641 6ae81775 ths
    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
12642 6af0bf9c bellard
    tlb_flush(env, 1);
12643 6ae81775 ths
12644 51cc2e78 Blue Swirl
    /* Reset registers to their default values */
12645 51cc2e78 Blue Swirl
    env->CP0_PRid = env->cpu_model->CP0_PRid;
12646 51cc2e78 Blue Swirl
    env->CP0_Config0 = env->cpu_model->CP0_Config0;
12647 51cc2e78 Blue Swirl
#ifdef TARGET_WORDS_BIGENDIAN
12648 51cc2e78 Blue Swirl
    env->CP0_Config0 |= (1 << CP0C0_BE);
12649 51cc2e78 Blue Swirl
#endif
12650 51cc2e78 Blue Swirl
    env->CP0_Config1 = env->cpu_model->CP0_Config1;
12651 51cc2e78 Blue Swirl
    env->CP0_Config2 = env->cpu_model->CP0_Config2;
12652 51cc2e78 Blue Swirl
    env->CP0_Config3 = env->cpu_model->CP0_Config3;
12653 51cc2e78 Blue Swirl
    env->CP0_Config6 = env->cpu_model->CP0_Config6;
12654 51cc2e78 Blue Swirl
    env->CP0_Config7 = env->cpu_model->CP0_Config7;
12655 2a6e32dd Aurelien Jarno
    env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12656 2a6e32dd Aurelien Jarno
                                 << env->cpu_model->CP0_LLAddr_shift;
12657 2a6e32dd Aurelien Jarno
    env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
12658 51cc2e78 Blue Swirl
    env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12659 51cc2e78 Blue Swirl
    env->CCRes = env->cpu_model->CCRes;
12660 51cc2e78 Blue Swirl
    env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12661 51cc2e78 Blue Swirl
    env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12662 51cc2e78 Blue Swirl
    env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12663 51cc2e78 Blue Swirl
    env->current_tc = 0;
12664 51cc2e78 Blue Swirl
    env->SEGBITS = env->cpu_model->SEGBITS;
12665 51cc2e78 Blue Swirl
    env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12666 51cc2e78 Blue Swirl
#if defined(TARGET_MIPS64)
12667 51cc2e78 Blue Swirl
    if (env->cpu_model->insn_flags & ISA_MIPS3) {
12668 51cc2e78 Blue Swirl
        env->SEGMask |= 3ULL << 62;
12669 51cc2e78 Blue Swirl
    }
12670 51cc2e78 Blue Swirl
#endif
12671 51cc2e78 Blue Swirl
    env->PABITS = env->cpu_model->PABITS;
12672 51cc2e78 Blue Swirl
    env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12673 51cc2e78 Blue Swirl
    env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12674 51cc2e78 Blue Swirl
    env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12675 51cc2e78 Blue Swirl
    env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12676 51cc2e78 Blue Swirl
    env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12677 51cc2e78 Blue Swirl
    env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12678 51cc2e78 Blue Swirl
    env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12679 51cc2e78 Blue Swirl
    env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12680 51cc2e78 Blue Swirl
    env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12681 51cc2e78 Blue Swirl
    env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12682 51cc2e78 Blue Swirl
    env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
12683 51cc2e78 Blue Swirl
    env->insn_flags = env->cpu_model->insn_flags;
12684 51cc2e78 Blue Swirl
12685 0eaef5aa ths
#if defined(CONFIG_USER_ONLY)
12686 932e71cd aurel32
    env->hflags = MIPS_HFLAG_UM;
12687 df357f0e pbrook
    /* Enable access to the SYNCI_Step register.  */
12688 df357f0e pbrook
    env->CP0_HWREna |= (1 << 1);
12689 91a75935 Nathan Froyd
    if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12690 91a75935 Nathan Froyd
        env->hflags |= MIPS_HFLAG_FPU;
12691 91a75935 Nathan Froyd
    }
12692 91a75935 Nathan Froyd
#ifdef TARGET_MIPS64
12693 91a75935 Nathan Froyd
    if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
12694 91a75935 Nathan Froyd
        env->hflags |= MIPS_HFLAG_F64;
12695 91a75935 Nathan Froyd
    }
12696 91a75935 Nathan Froyd
#endif
12697 932e71cd aurel32
#else
12698 932e71cd aurel32
    if (env->hflags & MIPS_HFLAG_BMASK) {
12699 932e71cd aurel32
        /* If the exception was raised from a delay slot,
12700 932e71cd aurel32
           come back to the jump.  */
12701 932e71cd aurel32
        env->CP0_ErrorEPC = env->active_tc.PC - 4;
12702 aa328add ths
    } else {
12703 932e71cd aurel32
        env->CP0_ErrorEPC = env->active_tc.PC;
12704 932e71cd aurel32
    }
12705 932e71cd aurel32
    env->active_tc.PC = (int32_t)0xBFC00000;
12706 51cc2e78 Blue Swirl
    env->CP0_Random = env->tlb->nb_tlb - 1;
12707 51cc2e78 Blue Swirl
    env->tlb->tlb_in_use = env->tlb->nb_tlb;
12708 932e71cd aurel32
    env->CP0_Wired = 0;
12709 671b0f36 Hervé Poussineau
    env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
12710 932e71cd aurel32
    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
12711 932e71cd aurel32
    /* vectored interrupts not implemented, timer on int 7,
12712 932e71cd aurel32
       no performance counters. */
12713 932e71cd aurel32
    env->CP0_IntCtl = 0xe0000000;
12714 932e71cd aurel32
    {
12715 932e71cd aurel32
        int i;
12716 932e71cd aurel32
12717 932e71cd aurel32
        for (i = 0; i < 7; i++) {
12718 932e71cd aurel32
            env->CP0_WatchLo[i] = 0;
12719 932e71cd aurel32
            env->CP0_WatchHi[i] = 0x80000000;
12720 fd88b6ab ths
        }
12721 932e71cd aurel32
        env->CP0_WatchLo[7] = 0;
12722 932e71cd aurel32
        env->CP0_WatchHi[7] = 0;
12723 fd88b6ab ths
    }
12724 932e71cd aurel32
    /* Count register increments in debug mode, EJTAG version 1 */
12725 932e71cd aurel32
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
12726 932e71cd aurel32
    env->hflags = MIPS_HFLAG_CP0;
12727 932e71cd aurel32
#endif
12728 51cc2e78 Blue Swirl
#if defined(TARGET_MIPS64)
12729 51cc2e78 Blue Swirl
    if (env->cpu_model->insn_flags & ISA_MIPS3) {
12730 51cc2e78 Blue Swirl
        env->hflags |= MIPS_HFLAG_64;
12731 51cc2e78 Blue Swirl
    }
12732 51cc2e78 Blue Swirl
#endif
12733 6af0bf9c bellard
    env->exception_index = EXCP_NONE;
12734 6af0bf9c bellard
}
12735 d2856f1a aurel32
12736 d2856f1a aurel32
void gen_pc_load(CPUState *env, TranslationBlock *tb,
12737 d2856f1a aurel32
                unsigned long searched_pc, int pc_pos, void *puc)
12738 d2856f1a aurel32
{
12739 b5dc7732 ths
    env->active_tc.PC = gen_opc_pc[pc_pos];
12740 d2856f1a aurel32
    env->hflags &= ~MIPS_HFLAG_BMASK;
12741 d2856f1a aurel32
    env->hflags |= gen_opc_hflags[pc_pos];
12742 d2856f1a aurel32
}