|
1 /* |
|
2 * MIPS32 emulation for qemu: main translation routines. |
|
3 * |
|
4 * Copyright (c) 2004-2005 Jocelyn Mayer |
|
5 * Copyright (c) 2006 Marius Groeger (FPU operations) |
|
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) |
|
7 * |
|
8 * This library is free software; you can redistribute it and/or |
|
9 * modify it under the terms of the GNU Lesser General Public |
|
10 * License as published by the Free Software Foundation; either |
|
11 * version 2 of the License, or (at your option) any later version. |
|
12 * |
|
13 * This library is distributed in the hope that it will be useful, |
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
16 * Lesser General Public License for more details. |
|
17 * |
|
18 * You should have received a copy of the GNU Lesser General Public |
|
19 * License along with this library; if not, write to the Free Software |
|
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
21 */ |
|
22 |
|
23 #include <stdarg.h> |
|
24 #include <stdlib.h> |
|
25 #include <stdio.h> |
|
26 #include <string.h> |
|
27 #include <inttypes.h> |
|
28 |
|
29 #include "cpu.h" |
|
30 #include "exec-all.h" |
|
31 #include "disas.h" |
|
32 #include "tcg-op.h" |
|
33 #include "qemu-common.h" |
|
34 |
|
35 #include "helper.h" |
|
36 #define GEN_HELPER 1 |
|
37 #include "helper.h" |
|
38 |
|
39 //#define MIPS_DEBUG_DISAS |
|
40 //#define MIPS_DEBUG_SIGN_EXTENSIONS |
|
41 //#define MIPS_SINGLE_STEP |
|
42 |
|
43 /* MIPS major opcodes */ |
|
44 #define MASK_OP_MAJOR(op) (op & (0x3F << 26)) |
|
45 |
|
46 enum { |
|
47 /* indirect opcode tables */ |
|
48 OPC_SPECIAL = (0x00 << 26), |
|
49 OPC_REGIMM = (0x01 << 26), |
|
50 OPC_CP0 = (0x10 << 26), |
|
51 OPC_CP1 = (0x11 << 26), |
|
52 OPC_CP2 = (0x12 << 26), |
|
53 OPC_CP3 = (0x13 << 26), |
|
54 OPC_SPECIAL2 = (0x1C << 26), |
|
55 OPC_SPECIAL3 = (0x1F << 26), |
|
56 /* arithmetic with immediate */ |
|
57 OPC_ADDI = (0x08 << 26), |
|
58 OPC_ADDIU = (0x09 << 26), |
|
59 OPC_SLTI = (0x0A << 26), |
|
60 OPC_SLTIU = (0x0B << 26), |
|
61 OPC_ANDI = (0x0C << 26), |
|
62 OPC_ORI = (0x0D << 26), |
|
63 OPC_XORI = (0x0E << 26), |
|
64 OPC_LUI = (0x0F << 26), |
|
65 OPC_DADDI = (0x18 << 26), |
|
66 OPC_DADDIU = (0x19 << 26), |
|
67 /* Jump and branches */ |
|
68 OPC_J = (0x02 << 26), |
|
69 OPC_JAL = (0x03 << 26), |
|
70 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */ |
|
71 OPC_BEQL = (0x14 << 26), |
|
72 OPC_BNE = (0x05 << 26), |
|
73 OPC_BNEL = (0x15 << 26), |
|
74 OPC_BLEZ = (0x06 << 26), |
|
75 OPC_BLEZL = (0x16 << 26), |
|
76 OPC_BGTZ = (0x07 << 26), |
|
77 OPC_BGTZL = (0x17 << 26), |
|
78 OPC_JALX = (0x1D << 26), /* MIPS 16 only */ |
|
79 /* Load and stores */ |
|
80 OPC_LDL = (0x1A << 26), |
|
81 OPC_LDR = (0x1B << 26), |
|
82 OPC_LB = (0x20 << 26), |
|
83 OPC_LH = (0x21 << 26), |
|
84 OPC_LWL = (0x22 << 26), |
|
85 OPC_LW = (0x23 << 26), |
|
86 OPC_LBU = (0x24 << 26), |
|
87 OPC_LHU = (0x25 << 26), |
|
88 OPC_LWR = (0x26 << 26), |
|
89 OPC_LWU = (0x27 << 26), |
|
90 OPC_SB = (0x28 << 26), |
|
91 OPC_SH = (0x29 << 26), |
|
92 OPC_SWL = (0x2A << 26), |
|
93 OPC_SW = (0x2B << 26), |
|
94 OPC_SDL = (0x2C << 26), |
|
95 OPC_SDR = (0x2D << 26), |
|
96 OPC_SWR = (0x2E << 26), |
|
97 OPC_LL = (0x30 << 26), |
|
98 OPC_LLD = (0x34 << 26), |
|
99 OPC_LD = (0x37 << 26), |
|
100 OPC_SC = (0x38 << 26), |
|
101 OPC_SCD = (0x3C << 26), |
|
102 OPC_SD = (0x3F << 26), |
|
103 /* Floating point load/store */ |
|
104 OPC_LWC1 = (0x31 << 26), |
|
105 OPC_LWC2 = (0x32 << 26), |
|
106 OPC_LDC1 = (0x35 << 26), |
|
107 OPC_LDC2 = (0x36 << 26), |
|
108 OPC_SWC1 = (0x39 << 26), |
|
109 OPC_SWC2 = (0x3A << 26), |
|
110 OPC_SDC1 = (0x3D << 26), |
|
111 OPC_SDC2 = (0x3E << 26), |
|
112 /* MDMX ASE specific */ |
|
113 OPC_MDMX = (0x1E << 26), |
|
114 /* Cache and prefetch */ |
|
115 OPC_CACHE = (0x2F << 26), |
|
116 OPC_PREF = (0x33 << 26), |
|
117 /* Reserved major opcode */ |
|
118 OPC_MAJOR3B_RESERVED = (0x3B << 26), |
|
119 }; |
|
120 |
|
121 /* MIPS special opcodes */ |
|
122 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F) |
|
123 |
|
124 enum { |
|
125 /* Shifts */ |
|
126 OPC_SLL = 0x00 | OPC_SPECIAL, |
|
127 /* NOP is SLL r0, r0, 0 */ |
|
128 /* SSNOP is SLL r0, r0, 1 */ |
|
129 /* EHB is SLL r0, r0, 3 */ |
|
130 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */ |
|
131 OPC_SRA = 0x03 | OPC_SPECIAL, |
|
132 OPC_SLLV = 0x04 | OPC_SPECIAL, |
|
133 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */ |
|
134 OPC_SRAV = 0x07 | OPC_SPECIAL, |
|
135 OPC_DSLLV = 0x14 | OPC_SPECIAL, |
|
136 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */ |
|
137 OPC_DSRAV = 0x17 | OPC_SPECIAL, |
|
138 OPC_DSLL = 0x38 | OPC_SPECIAL, |
|
139 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */ |
|
140 OPC_DSRA = 0x3B | OPC_SPECIAL, |
|
141 OPC_DSLL32 = 0x3C | OPC_SPECIAL, |
|
142 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */ |
|
143 OPC_DSRA32 = 0x3F | OPC_SPECIAL, |
|
144 /* Multiplication / division */ |
|
145 OPC_MULT = 0x18 | OPC_SPECIAL, |
|
146 OPC_MULTU = 0x19 | OPC_SPECIAL, |
|
147 OPC_DIV = 0x1A | OPC_SPECIAL, |
|
148 OPC_DIVU = 0x1B | OPC_SPECIAL, |
|
149 OPC_DMULT = 0x1C | OPC_SPECIAL, |
|
150 OPC_DMULTU = 0x1D | OPC_SPECIAL, |
|
151 OPC_DDIV = 0x1E | OPC_SPECIAL, |
|
152 OPC_DDIVU = 0x1F | OPC_SPECIAL, |
|
153 /* 2 registers arithmetic / logic */ |
|
154 OPC_ADD = 0x20 | OPC_SPECIAL, |
|
155 OPC_ADDU = 0x21 | OPC_SPECIAL, |
|
156 OPC_SUB = 0x22 | OPC_SPECIAL, |
|
157 OPC_SUBU = 0x23 | OPC_SPECIAL, |
|
158 OPC_AND = 0x24 | OPC_SPECIAL, |
|
159 OPC_OR = 0x25 | OPC_SPECIAL, |
|
160 OPC_XOR = 0x26 | OPC_SPECIAL, |
|
161 OPC_NOR = 0x27 | OPC_SPECIAL, |
|
162 OPC_SLT = 0x2A | OPC_SPECIAL, |
|
163 OPC_SLTU = 0x2B | OPC_SPECIAL, |
|
164 OPC_DADD = 0x2C | OPC_SPECIAL, |
|
165 OPC_DADDU = 0x2D | OPC_SPECIAL, |
|
166 OPC_DSUB = 0x2E | OPC_SPECIAL, |
|
167 OPC_DSUBU = 0x2F | OPC_SPECIAL, |
|
168 /* Jumps */ |
|
169 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */ |
|
170 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */ |
|
171 /* Traps */ |
|
172 OPC_TGE = 0x30 | OPC_SPECIAL, |
|
173 OPC_TGEU = 0x31 | OPC_SPECIAL, |
|
174 OPC_TLT = 0x32 | OPC_SPECIAL, |
|
175 OPC_TLTU = 0x33 | OPC_SPECIAL, |
|
176 OPC_TEQ = 0x34 | OPC_SPECIAL, |
|
177 OPC_TNE = 0x36 | OPC_SPECIAL, |
|
178 /* HI / LO registers load & stores */ |
|
179 OPC_MFHI = 0x10 | OPC_SPECIAL, |
|
180 OPC_MTHI = 0x11 | OPC_SPECIAL, |
|
181 OPC_MFLO = 0x12 | OPC_SPECIAL, |
|
182 OPC_MTLO = 0x13 | OPC_SPECIAL, |
|
183 /* Conditional moves */ |
|
184 OPC_MOVZ = 0x0A | OPC_SPECIAL, |
|
185 OPC_MOVN = 0x0B | OPC_SPECIAL, |
|
186 |
|
187 OPC_MOVCI = 0x01 | OPC_SPECIAL, |
|
188 |
|
189 /* Special */ |
|
190 OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */ |
|
191 OPC_SYSCALL = 0x0C | OPC_SPECIAL, |
|
192 OPC_BREAK = 0x0D | OPC_SPECIAL, |
|
193 OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */ |
|
194 OPC_SYNC = 0x0F | OPC_SPECIAL, |
|
195 |
|
196 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL, |
|
197 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL, |
|
198 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL, |
|
199 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL, |
|
200 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL, |
|
201 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL, |
|
202 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL, |
|
203 }; |
|
204 |
|
205 /* Multiplication variants of the vr54xx. */ |
|
206 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6)) |
|
207 |
|
208 enum { |
|
209 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT, |
|
210 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU, |
|
211 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT, |
|
212 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU, |
|
213 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT, |
|
214 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU, |
|
215 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT, |
|
216 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU, |
|
217 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT, |
|
218 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU, |
|
219 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT, |
|
220 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU, |
|
221 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT, |
|
222 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU, |
|
223 }; |
|
224 |
|
225 /* REGIMM (rt field) opcodes */ |
|
226 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16)) |
|
227 |
|
228 enum { |
|
229 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM, |
|
230 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM, |
|
231 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM, |
|
232 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM, |
|
233 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM, |
|
234 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM, |
|
235 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM, |
|
236 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM, |
|
237 OPC_TGEI = (0x08 << 16) | OPC_REGIMM, |
|
238 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM, |
|
239 OPC_TLTI = (0x0A << 16) | OPC_REGIMM, |
|
240 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM, |
|
241 OPC_TEQI = (0x0C << 16) | OPC_REGIMM, |
|
242 OPC_TNEI = (0x0E << 16) | OPC_REGIMM, |
|
243 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM, |
|
244 }; |
|
245 |
|
246 /* Special2 opcodes */ |
|
247 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F) |
|
248 |
|
249 enum { |
|
250 /* Multiply & xxx operations */ |
|
251 OPC_MADD = 0x00 | OPC_SPECIAL2, |
|
252 OPC_MADDU = 0x01 | OPC_SPECIAL2, |
|
253 OPC_MUL = 0x02 | OPC_SPECIAL2, |
|
254 OPC_MSUB = 0x04 | OPC_SPECIAL2, |
|
255 OPC_MSUBU = 0x05 | OPC_SPECIAL2, |
|
256 /* Misc */ |
|
257 OPC_CLZ = 0x20 | OPC_SPECIAL2, |
|
258 OPC_CLO = 0x21 | OPC_SPECIAL2, |
|
259 OPC_DCLZ = 0x24 | OPC_SPECIAL2, |
|
260 OPC_DCLO = 0x25 | OPC_SPECIAL2, |
|
261 /* Special */ |
|
262 OPC_SDBBP = 0x3F | OPC_SPECIAL2, |
|
263 }; |
|
264 |
|
265 /* Special3 opcodes */ |
|
266 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F) |
|
267 |
|
268 enum { |
|
269 OPC_EXT = 0x00 | OPC_SPECIAL3, |
|
270 OPC_DEXTM = 0x01 | OPC_SPECIAL3, |
|
271 OPC_DEXTU = 0x02 | OPC_SPECIAL3, |
|
272 OPC_DEXT = 0x03 | OPC_SPECIAL3, |
|
273 OPC_INS = 0x04 | OPC_SPECIAL3, |
|
274 OPC_DINSM = 0x05 | OPC_SPECIAL3, |
|
275 OPC_DINSU = 0x06 | OPC_SPECIAL3, |
|
276 OPC_DINS = 0x07 | OPC_SPECIAL3, |
|
277 OPC_FORK = 0x08 | OPC_SPECIAL3, |
|
278 OPC_YIELD = 0x09 | OPC_SPECIAL3, |
|
279 OPC_BSHFL = 0x20 | OPC_SPECIAL3, |
|
280 OPC_DBSHFL = 0x24 | OPC_SPECIAL3, |
|
281 OPC_RDHWR = 0x3B | OPC_SPECIAL3, |
|
282 }; |
|
283 |
|
284 /* BSHFL opcodes */ |
|
285 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6)) |
|
286 |
|
287 enum { |
|
288 OPC_WSBH = (0x02 << 6) | OPC_BSHFL, |
|
289 OPC_SEB = (0x10 << 6) | OPC_BSHFL, |
|
290 OPC_SEH = (0x18 << 6) | OPC_BSHFL, |
|
291 }; |
|
292 |
|
293 /* DBSHFL opcodes */ |
|
294 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6)) |
|
295 |
|
296 enum { |
|
297 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL, |
|
298 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL, |
|
299 }; |
|
300 |
|
301 /* Coprocessor 0 (rs field) */ |
|
302 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) |
|
303 |
|
304 enum { |
|
305 OPC_MFC0 = (0x00 << 21) | OPC_CP0, |
|
306 OPC_DMFC0 = (0x01 << 21) | OPC_CP0, |
|
307 OPC_MTC0 = (0x04 << 21) | OPC_CP0, |
|
308 OPC_DMTC0 = (0x05 << 21) | OPC_CP0, |
|
309 OPC_MFTR = (0x08 << 21) | OPC_CP0, |
|
310 OPC_RDPGPR = (0x0A << 21) | OPC_CP0, |
|
311 OPC_MFMC0 = (0x0B << 21) | OPC_CP0, |
|
312 OPC_MTTR = (0x0C << 21) | OPC_CP0, |
|
313 OPC_WRPGPR = (0x0E << 21) | OPC_CP0, |
|
314 OPC_C0 = (0x10 << 21) | OPC_CP0, |
|
315 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0, |
|
316 OPC_C0_LAST = (0x1F << 21) | OPC_CP0, |
|
317 }; |
|
318 |
|
319 /* MFMC0 opcodes */ |
|
320 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF) |
|
321 |
|
322 enum { |
|
323 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0, |
|
324 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0, |
|
325 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0, |
|
326 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0, |
|
327 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0, |
|
328 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0, |
|
329 }; |
|
330 |
|
331 /* Coprocessor 0 (with rs == C0) */ |
|
332 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F) |
|
333 |
|
334 enum { |
|
335 OPC_TLBR = 0x01 | OPC_C0, |
|
336 OPC_TLBWI = 0x02 | OPC_C0, |
|
337 OPC_TLBWR = 0x06 | OPC_C0, |
|
338 OPC_TLBP = 0x08 | OPC_C0, |
|
339 OPC_RFE = 0x10 | OPC_C0, |
|
340 OPC_ERET = 0x18 | OPC_C0, |
|
341 OPC_DERET = 0x1F | OPC_C0, |
|
342 OPC_WAIT = 0x20 | OPC_C0, |
|
343 }; |
|
344 |
|
345 /* Coprocessor 1 (rs field) */ |
|
346 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) |
|
347 |
|
348 enum { |
|
349 OPC_MFC1 = (0x00 << 21) | OPC_CP1, |
|
350 OPC_DMFC1 = (0x01 << 21) | OPC_CP1, |
|
351 OPC_CFC1 = (0x02 << 21) | OPC_CP1, |
|
352 OPC_MFHC1 = (0x03 << 21) | OPC_CP1, |
|
353 OPC_MTC1 = (0x04 << 21) | OPC_CP1, |
|
354 OPC_DMTC1 = (0x05 << 21) | OPC_CP1, |
|
355 OPC_CTC1 = (0x06 << 21) | OPC_CP1, |
|
356 OPC_MTHC1 = (0x07 << 21) | OPC_CP1, |
|
357 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */ |
|
358 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1, |
|
359 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1, |
|
360 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */ |
|
361 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */ |
|
362 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */ |
|
363 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */ |
|
364 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */ |
|
365 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */ |
|
366 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */ |
|
367 }; |
|
368 |
|
369 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F) |
|
370 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16)) |
|
371 |
|
372 enum { |
|
373 OPC_BC1F = (0x00 << 16) | OPC_BC1, |
|
374 OPC_BC1T = (0x01 << 16) | OPC_BC1, |
|
375 OPC_BC1FL = (0x02 << 16) | OPC_BC1, |
|
376 OPC_BC1TL = (0x03 << 16) | OPC_BC1, |
|
377 }; |
|
378 |
|
379 enum { |
|
380 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2, |
|
381 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2, |
|
382 }; |
|
383 |
|
384 enum { |
|
385 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4, |
|
386 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4, |
|
387 }; |
|
388 |
|
389 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) |
|
390 |
|
391 enum { |
|
392 OPC_MFC2 = (0x00 << 21) | OPC_CP2, |
|
393 OPC_DMFC2 = (0x01 << 21) | OPC_CP2, |
|
394 OPC_CFC2 = (0x02 << 21) | OPC_CP2, |
|
395 OPC_MFHC2 = (0x03 << 21) | OPC_CP2, |
|
396 OPC_MTC2 = (0x04 << 21) | OPC_CP2, |
|
397 OPC_DMTC2 = (0x05 << 21) | OPC_CP2, |
|
398 OPC_CTC2 = (0x06 << 21) | OPC_CP2, |
|
399 OPC_MTHC2 = (0x07 << 21) | OPC_CP2, |
|
400 OPC_BC2 = (0x08 << 21) | OPC_CP2, |
|
401 }; |
|
402 |
|
403 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F) |
|
404 |
|
405 enum { |
|
406 OPC_LWXC1 = 0x00 | OPC_CP3, |
|
407 OPC_LDXC1 = 0x01 | OPC_CP3, |
|
408 OPC_LUXC1 = 0x05 | OPC_CP3, |
|
409 OPC_SWXC1 = 0x08 | OPC_CP3, |
|
410 OPC_SDXC1 = 0x09 | OPC_CP3, |
|
411 OPC_SUXC1 = 0x0D | OPC_CP3, |
|
412 OPC_PREFX = 0x0F | OPC_CP3, |
|
413 OPC_ALNV_PS = 0x1E | OPC_CP3, |
|
414 OPC_MADD_S = 0x20 | OPC_CP3, |
|
415 OPC_MADD_D = 0x21 | OPC_CP3, |
|
416 OPC_MADD_PS = 0x26 | OPC_CP3, |
|
417 OPC_MSUB_S = 0x28 | OPC_CP3, |
|
418 OPC_MSUB_D = 0x29 | OPC_CP3, |
|
419 OPC_MSUB_PS = 0x2E | OPC_CP3, |
|
420 OPC_NMADD_S = 0x30 | OPC_CP3, |
|
421 OPC_NMADD_D = 0x31 | OPC_CP3, |
|
422 OPC_NMADD_PS= 0x36 | OPC_CP3, |
|
423 OPC_NMSUB_S = 0x38 | OPC_CP3, |
|
424 OPC_NMSUB_D = 0x39 | OPC_CP3, |
|
425 OPC_NMSUB_PS= 0x3E | OPC_CP3, |
|
426 }; |
|
427 |
|
428 /* global register indices */ |
|
429 static TCGv_ptr cpu_env; |
|
430 static TCGv cpu_gpr[32], cpu_PC; |
|
431 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC]; |
|
432 static TCGv cpu_dspctrl, btarget; |
|
433 static TCGv_i32 bcond; |
|
434 static TCGv_i32 fpu_fpr32[32], fpu_fpr32h[32]; |
|
435 static TCGv_i64 fpu_fpr64[32]; |
|
436 static TCGv_i32 fpu_fcr0, fpu_fcr31; |
|
437 |
|
438 #include "gen-icount.h" |
|
439 |
|
440 #define gen_helper_0i(name, arg) do { \ |
|
441 TCGv_i32 helper_tmp = tcg_const_i32(arg); \ |
|
442 gen_helper_##name(helper_tmp); \ |
|
443 tcg_temp_free_i32(helper_tmp); \ |
|
444 } while(0) |
|
445 |
|
446 #define gen_helper_1i(name, arg1, arg2) do { \ |
|
447 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \ |
|
448 gen_helper_##name(arg1, helper_tmp); \ |
|
449 tcg_temp_free_i32(helper_tmp); \ |
|
450 } while(0) |
|
451 |
|
452 #define gen_helper_2i(name, arg1, arg2, arg3) do { \ |
|
453 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \ |
|
454 gen_helper_##name(arg1, arg2, helper_tmp); \ |
|
455 tcg_temp_free_i32(helper_tmp); \ |
|
456 } while(0) |
|
457 |
|
458 #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \ |
|
459 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \ |
|
460 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \ |
|
461 tcg_temp_free_i32(helper_tmp); \ |
|
462 } while(0) |
|
463 |
|
464 typedef struct DisasContext { |
|
465 struct TranslationBlock *tb; |
|
466 target_ulong pc, saved_pc; |
|
467 uint32_t opcode; |
|
468 /* Routine used to access memory */ |
|
469 int mem_idx; |
|
470 uint32_t hflags, saved_hflags; |
|
471 int bstate; |
|
472 target_ulong btarget; |
|
473 } DisasContext; |
|
474 |
|
475 enum { |
|
476 BS_NONE = 0, /* We go out of the TB without reaching a branch or an |
|
477 * exception condition */ |
|
478 BS_STOP = 1, /* We want to stop translation for any reason */ |
|
479 BS_BRANCH = 2, /* We reached a branch condition */ |
|
480 BS_EXCP = 3, /* We reached an exception condition */ |
|
481 }; |
|
482 |
|
483 static const char *regnames[] = |
|
484 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", |
|
485 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", |
|
486 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", |
|
487 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", }; |
|
488 |
|
489 static const char *regnames_HI[] = |
|
490 { "HI0", "HI1", "HI2", "HI3", }; |
|
491 |
|
492 static const char *regnames_LO[] = |
|
493 { "LO0", "LO1", "LO2", "LO3", }; |
|
494 |
|
495 static const char *regnames_ACX[] = |
|
496 { "ACX0", "ACX1", "ACX2", "ACX3", }; |
|
497 |
|
498 static const char *fregnames[] = |
|
499 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", |
|
500 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", |
|
501 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", |
|
502 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", }; |
|
503 |
|
504 static const char *fregnames_64[] = |
|
505 { "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", |
|
506 "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", |
|
507 "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", |
|
508 "F24", "F25", "F26", "F27", "F28", "F29", "F30", "F31", }; |
|
509 |
|
510 static const char *fregnames_h[] = |
|
511 { "h0", "h1", "h2", "h3", "h4", "h5", "h6", "h7", |
|
512 "h8", "h9", "h10", "h11", "h12", "h13", "h14", "h15", |
|
513 "h16", "h17", "h18", "h19", "h20", "h21", "h22", "h23", |
|
514 "h24", "h25", "h26", "h27", "h28", "h29", "h30", "h31", }; |
|
515 |
|
516 #ifdef MIPS_DEBUG_DISAS |
|
517 #define MIPS_DEBUG(fmt, args...) \ |
|
518 do { \ |
|
519 if (loglevel & CPU_LOG_TB_IN_ASM) { \ |
|
520 fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n", \ |
|
521 ctx->pc, ctx->opcode , ##args); \ |
|
522 } \ |
|
523 } while (0) |
|
524 #else |
|
525 #define MIPS_DEBUG(fmt, args...) do { } while(0) |
|
526 #endif |
|
527 |
|
528 #define MIPS_INVAL(op) \ |
|
529 do { \ |
|
530 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \ |
|
531 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \ |
|
532 } while (0) |
|
533 |
|
534 /* General purpose registers moves. */ |
|
535 static inline void gen_load_gpr (TCGv t, int reg) |
|
536 { |
|
537 if (reg == 0) |
|
538 tcg_gen_movi_tl(t, 0); |
|
539 else |
|
540 tcg_gen_mov_tl(t, cpu_gpr[reg]); |
|
541 } |
|
542 |
|
543 static inline void gen_store_gpr (TCGv t, int reg) |
|
544 { |
|
545 if (reg != 0) |
|
546 tcg_gen_mov_tl(cpu_gpr[reg], t); |
|
547 } |
|
548 |
|
549 /* Moves to/from ACX register. */ |
|
550 static inline void gen_load_ACX (TCGv t, int reg) |
|
551 { |
|
552 tcg_gen_mov_tl(t, cpu_ACX[reg]); |
|
553 } |
|
554 |
|
555 static inline void gen_store_ACX (TCGv t, int reg) |
|
556 { |
|
557 tcg_gen_mov_tl(cpu_ACX[reg], t); |
|
558 } |
|
559 |
|
560 /* Moves to/from shadow registers. */ |
|
561 static inline void gen_load_srsgpr (int from, int to) |
|
562 { |
|
563 TCGv r_tmp1 = tcg_temp_new(); |
|
564 |
|
565 if (from == 0) |
|
566 tcg_gen_movi_tl(r_tmp1, 0); |
|
567 else { |
|
568 TCGv_i32 r_tmp2 = tcg_temp_new_i32(); |
|
569 TCGv_ptr addr = tcg_temp_new_ptr(); |
|
570 |
|
571 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl)); |
|
572 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS); |
|
573 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf); |
|
574 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32); |
|
575 tcg_gen_ext_i32_ptr(addr, r_tmp2); |
|
576 tcg_gen_add_ptr(addr, cpu_env, addr); |
|
577 |
|
578 tcg_gen_ld_tl(r_tmp1, addr, sizeof(target_ulong) * from); |
|
579 tcg_temp_free_ptr(addr); |
|
580 tcg_temp_free_i32(r_tmp2); |
|
581 } |
|
582 gen_store_gpr(r_tmp1, to); |
|
583 tcg_temp_free(r_tmp1); |
|
584 } |
|
585 |
|
586 static inline void gen_store_srsgpr (int from, int to) |
|
587 { |
|
588 if (to != 0) { |
|
589 TCGv r_tmp1 = tcg_temp_new(); |
|
590 TCGv_i32 r_tmp2 = tcg_temp_new_i32(); |
|
591 TCGv_ptr addr = tcg_temp_new_ptr(); |
|
592 |
|
593 gen_load_gpr(r_tmp1, from); |
|
594 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl)); |
|
595 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS); |
|
596 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf); |
|
597 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32); |
|
598 tcg_gen_ext_i32_ptr(addr, r_tmp2); |
|
599 tcg_gen_add_ptr(addr, cpu_env, addr); |
|
600 |
|
601 tcg_gen_st_tl(r_tmp1, addr, sizeof(target_ulong) * to); |
|
602 tcg_temp_free_ptr(addr); |
|
603 tcg_temp_free_i32(r_tmp2); |
|
604 tcg_temp_free(r_tmp1); |
|
605 } |
|
606 } |
|
607 |
|
608 /* Floating point register moves. */ |
|
609 static inline void gen_load_fpr32 (TCGv_i32 t, int reg) |
|
610 { |
|
611 tcg_gen_mov_i32(t, fpu_fpr32[reg]); |
|
612 } |
|
613 |
|
614 static inline void gen_store_fpr32 (TCGv_i32 t, int reg) |
|
615 { |
|
616 tcg_gen_mov_i32(fpu_fpr32[reg], t); |
|
617 } |
|
618 |
|
619 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg) |
|
620 { |
|
621 if (ctx->hflags & MIPS_HFLAG_F64) |
|
622 tcg_gen_mov_i64(t, fpu_fpr64[reg]); |
|
623 else { |
|
624 tcg_gen_concat_i32_i64(t, fpu_fpr32[reg & ~1], fpu_fpr32[reg | 1]); |
|
625 } |
|
626 } |
|
627 |
|
628 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg) |
|
629 { |
|
630 if (ctx->hflags & MIPS_HFLAG_F64) |
|
631 tcg_gen_mov_i64(fpu_fpr64[reg], t); |
|
632 else { |
|
633 tcg_gen_trunc_i64_i32(fpu_fpr32[reg & ~1], t); |
|
634 tcg_gen_shri_i64(t, t, 32); |
|
635 tcg_gen_trunc_i64_i32(fpu_fpr32[reg | 1], t); |
|
636 } |
|
637 } |
|
638 |
|
639 static inline void gen_load_fpr32h (TCGv_i32 t, int reg) |
|
640 { |
|
641 tcg_gen_mov_i32(t, fpu_fpr32h[reg]); |
|
642 } |
|
643 |
|
644 static inline void gen_store_fpr32h (TCGv_i32 t, int reg) |
|
645 { |
|
646 tcg_gen_mov_i32(fpu_fpr32h[reg], t); |
|
647 } |
|
648 |
|
649 static inline void get_fp_cond (TCGv_i32 t) |
|
650 { |
|
651 TCGv_i32 r_tmp1 = tcg_temp_new_i32(); |
|
652 TCGv_i32 r_tmp2 = tcg_temp_new_i32(); |
|
653 |
|
654 tcg_gen_shri_i32(r_tmp2, fpu_fcr31, 24); |
|
655 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xfe); |
|
656 tcg_gen_shri_i32(r_tmp1, fpu_fcr31, 23); |
|
657 tcg_gen_andi_i32(r_tmp1, r_tmp1, 0x1); |
|
658 tcg_gen_or_i32(t, r_tmp1, r_tmp2); |
|
659 tcg_temp_free_i32(r_tmp1); |
|
660 tcg_temp_free_i32(r_tmp2); |
|
661 } |
|
662 |
|
663 #define FOP_CONDS(type, fmt, bits) \ |
|
664 static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \ |
|
665 TCGv_i##bits b, int cc) \ |
|
666 { \ |
|
667 switch (n) { \ |
|
668 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\ |
|
669 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\ |
|
670 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\ |
|
671 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\ |
|
672 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\ |
|
673 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\ |
|
674 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\ |
|
675 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\ |
|
676 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\ |
|
677 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\ |
|
678 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\ |
|
679 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\ |
|
680 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\ |
|
681 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\ |
|
682 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\ |
|
683 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\ |
|
684 default: abort(); \ |
|
685 } \ |
|
686 } |
|
687 |
|
688 FOP_CONDS(, d, 64) |
|
689 FOP_CONDS(abs, d, 64) |
|
690 FOP_CONDS(, s, 32) |
|
691 FOP_CONDS(abs, s, 32) |
|
692 FOP_CONDS(, ps, 64) |
|
693 FOP_CONDS(abs, ps, 64) |
|
694 #undef FOP_CONDS |
|
695 |
|
696 /* Tests */ |
|
697 #define OP_COND(name, cond) \ |
|
698 static inline void glue(gen_op_, name) (TCGv t0, TCGv t1) \ |
|
699 { \ |
|
700 int l1 = gen_new_label(); \ |
|
701 int l2 = gen_new_label(); \ |
|
702 \ |
|
703 tcg_gen_brcond_tl(cond, t0, t1, l1); \ |
|
704 tcg_gen_movi_tl(t0, 0); \ |
|
705 tcg_gen_br(l2); \ |
|
706 gen_set_label(l1); \ |
|
707 tcg_gen_movi_tl(t0, 1); \ |
|
708 gen_set_label(l2); \ |
|
709 } |
|
710 OP_COND(eq, TCG_COND_EQ); |
|
711 OP_COND(ne, TCG_COND_NE); |
|
712 OP_COND(ge, TCG_COND_GE); |
|
713 OP_COND(geu, TCG_COND_GEU); |
|
714 OP_COND(lt, TCG_COND_LT); |
|
715 OP_COND(ltu, TCG_COND_LTU); |
|
716 #undef OP_COND |
|
717 |
|
718 #define OP_CONDI(name, cond) \ |
|
719 static inline void glue(gen_op_, name) (TCGv t, target_ulong val) \ |
|
720 { \ |
|
721 int l1 = gen_new_label(); \ |
|
722 int l2 = gen_new_label(); \ |
|
723 \ |
|
724 tcg_gen_brcondi_tl(cond, t, val, l1); \ |
|
725 tcg_gen_movi_tl(t, 0); \ |
|
726 tcg_gen_br(l2); \ |
|
727 gen_set_label(l1); \ |
|
728 tcg_gen_movi_tl(t, 1); \ |
|
729 gen_set_label(l2); \ |
|
730 } |
|
731 OP_CONDI(lti, TCG_COND_LT); |
|
732 OP_CONDI(ltiu, TCG_COND_LTU); |
|
733 #undef OP_CONDI |
|
734 |
|
735 #define OP_CONDZ(name, cond) \ |
|
736 static inline void glue(gen_op_, name) (TCGv t) \ |
|
737 { \ |
|
738 int l1 = gen_new_label(); \ |
|
739 int l2 = gen_new_label(); \ |
|
740 \ |
|
741 tcg_gen_brcondi_tl(cond, t, 0, l1); \ |
|
742 tcg_gen_movi_tl(t, 0); \ |
|
743 tcg_gen_br(l2); \ |
|
744 gen_set_label(l1); \ |
|
745 tcg_gen_movi_tl(t, 1); \ |
|
746 gen_set_label(l2); \ |
|
747 } |
|
748 OP_CONDZ(gez, TCG_COND_GE); |
|
749 OP_CONDZ(gtz, TCG_COND_GT); |
|
750 OP_CONDZ(lez, TCG_COND_LE); |
|
751 OP_CONDZ(ltz, TCG_COND_LT); |
|
752 #undef OP_CONDZ |
|
753 |
|
754 static inline void gen_save_pc(target_ulong pc) |
|
755 { |
|
756 tcg_gen_movi_tl(cpu_PC, pc); |
|
757 } |
|
758 |
|
759 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc) |
|
760 { |
|
761 #if defined MIPS_DEBUG_DISAS |
|
762 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
763 fprintf(logfile, "hflags %08x saved %08x\n", |
|
764 ctx->hflags, ctx->saved_hflags); |
|
765 } |
|
766 #endif |
|
767 if (do_save_pc && ctx->pc != ctx->saved_pc) { |
|
768 gen_save_pc(ctx->pc); |
|
769 ctx->saved_pc = ctx->pc; |
|
770 } |
|
771 if (ctx->hflags != ctx->saved_hflags) { |
|
772 TCGv_i32 r_tmp = tcg_temp_new_i32(); |
|
773 |
|
774 tcg_gen_movi_i32(r_tmp, ctx->hflags); |
|
775 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags)); |
|
776 tcg_temp_free_i32(r_tmp); |
|
777 ctx->saved_hflags = ctx->hflags; |
|
778 switch (ctx->hflags & MIPS_HFLAG_BMASK) { |
|
779 case MIPS_HFLAG_BR: |
|
780 break; |
|
781 case MIPS_HFLAG_BC: |
|
782 case MIPS_HFLAG_BL: |
|
783 case MIPS_HFLAG_B: |
|
784 tcg_gen_movi_tl(btarget, ctx->btarget); |
|
785 break; |
|
786 } |
|
787 } |
|
788 } |
|
789 |
|
790 static inline void restore_cpu_state (CPUState *env, DisasContext *ctx) |
|
791 { |
|
792 ctx->saved_hflags = ctx->hflags; |
|
793 switch (ctx->hflags & MIPS_HFLAG_BMASK) { |
|
794 case MIPS_HFLAG_BR: |
|
795 break; |
|
796 case MIPS_HFLAG_BC: |
|
797 case MIPS_HFLAG_BL: |
|
798 case MIPS_HFLAG_B: |
|
799 ctx->btarget = env->btarget; |
|
800 break; |
|
801 } |
|
802 } |
|
803 |
|
804 static inline void |
|
805 generate_exception_err (DisasContext *ctx, int excp, int err) |
|
806 { |
|
807 TCGv_i32 texcp = tcg_const_i32(excp); |
|
808 TCGv_i32 terr = tcg_const_i32(err); |
|
809 save_cpu_state(ctx, 1); |
|
810 gen_helper_raise_exception_err(texcp, terr); |
|
811 tcg_temp_free_i32(terr); |
|
812 tcg_temp_free_i32(texcp); |
|
813 gen_helper_interrupt_restart(); |
|
814 tcg_gen_exit_tb(0); |
|
815 } |
|
816 |
|
817 static inline void |
|
818 generate_exception (DisasContext *ctx, int excp) |
|
819 { |
|
820 save_cpu_state(ctx, 1); |
|
821 gen_helper_0i(raise_exception, excp); |
|
822 gen_helper_interrupt_restart(); |
|
823 tcg_gen_exit_tb(0); |
|
824 } |
|
825 |
|
826 /* Addresses computation */ |
|
827 static inline void gen_op_addr_add (DisasContext *ctx, TCGv t0, TCGv t1) |
|
828 { |
|
829 tcg_gen_add_tl(t0, t0, t1); |
|
830 |
|
831 #if defined(TARGET_MIPS64) |
|
832 /* For compatibility with 32-bit code, data reference in user mode |
|
833 with Status_UX = 0 should be casted to 32-bit and sign extended. |
|
834 See the MIPS64 PRA manual, section 4.10. */ |
|
835 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) && |
|
836 !(ctx->hflags & MIPS_HFLAG_UX)) { |
|
837 tcg_gen_ext32s_i64(t0, t0); |
|
838 } |
|
839 #endif |
|
840 } |
|
841 |
|
842 static inline void check_cp0_enabled(DisasContext *ctx) |
|
843 { |
|
844 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) |
|
845 generate_exception_err(ctx, EXCP_CpU, 1); |
|
846 } |
|
847 |
|
848 static inline void check_cp1_enabled(DisasContext *ctx) |
|
849 { |
|
850 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) |
|
851 generate_exception_err(ctx, EXCP_CpU, 1); |
|
852 } |
|
853 |
|
854 /* Verify that the processor is running with COP1X instructions enabled. |
|
855 This is associated with the nabla symbol in the MIPS32 and MIPS64 |
|
856 opcode tables. */ |
|
857 |
|
858 static inline void check_cop1x(DisasContext *ctx) |
|
859 { |
|
860 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) |
|
861 generate_exception(ctx, EXCP_RI); |
|
862 } |
|
863 |
|
864 /* Verify that the processor is running with 64-bit floating-point |
|
865 operations enabled. */ |
|
866 |
|
867 static inline void check_cp1_64bitmode(DisasContext *ctx) |
|
868 { |
|
869 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) |
|
870 generate_exception(ctx, EXCP_RI); |
|
871 } |
|
872 |
|
873 /* |
|
874 * Verify if floating point register is valid; an operation is not defined |
|
875 * if bit 0 of any register specification is set and the FR bit in the |
|
876 * Status register equals zero, since the register numbers specify an |
|
877 * even-odd pair of adjacent coprocessor general registers. When the FR bit |
|
878 * in the Status register equals one, both even and odd register numbers |
|
879 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers. |
|
880 * |
|
881 * Multiple 64 bit wide registers can be checked by calling |
|
882 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN); |
|
883 */ |
|
884 static inline void check_cp1_registers(DisasContext *ctx, int regs) |
|
885 { |
|
886 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) |
|
887 generate_exception(ctx, EXCP_RI); |
|
888 } |
|
889 |
|
890 /* This code generates a "reserved instruction" exception if the |
|
891 CPU does not support the instruction set corresponding to flags. */ |
|
892 static inline void check_insn(CPUState *env, DisasContext *ctx, int flags) |
|
893 { |
|
894 if (unlikely(!(env->insn_flags & flags))) |
|
895 generate_exception(ctx, EXCP_RI); |
|
896 } |
|
897 |
|
898 /* This code generates a "reserved instruction" exception if 64-bit |
|
899 instructions are not enabled. */ |
|
900 static inline void check_mips_64(DisasContext *ctx) |
|
901 { |
|
902 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) |
|
903 generate_exception(ctx, EXCP_RI); |
|
904 } |
|
905 |
|
906 /* load/store instructions. */ |
|
907 #define OP_LD(insn,fname) \ |
|
908 static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx) \ |
|
909 { \ |
|
910 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \ |
|
911 } |
|
912 OP_LD(lb,ld8s); |
|
913 OP_LD(lbu,ld8u); |
|
914 OP_LD(lh,ld16s); |
|
915 OP_LD(lhu,ld16u); |
|
916 OP_LD(lw,ld32s); |
|
917 #if defined(TARGET_MIPS64) |
|
918 OP_LD(lwu,ld32u); |
|
919 OP_LD(ld,ld64); |
|
920 #endif |
|
921 #undef OP_LD |
|
922 |
|
923 #define OP_ST(insn,fname) \ |
|
924 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ |
|
925 { \ |
|
926 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \ |
|
927 } |
|
928 OP_ST(sb,st8); |
|
929 OP_ST(sh,st16); |
|
930 OP_ST(sw,st32); |
|
931 #if defined(TARGET_MIPS64) |
|
932 OP_ST(sd,st64); |
|
933 #endif |
|
934 #undef OP_ST |
|
935 |
|
936 #define OP_LD_ATOMIC(insn,fname) \ |
|
937 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ |
|
938 { \ |
|
939 tcg_gen_mov_tl(t1, t0); \ |
|
940 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \ |
|
941 tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, CP0_LLAddr)); \ |
|
942 } |
|
943 OP_LD_ATOMIC(ll,ld32s); |
|
944 #if defined(TARGET_MIPS64) |
|
945 OP_LD_ATOMIC(lld,ld64); |
|
946 #endif |
|
947 #undef OP_LD_ATOMIC |
|
948 |
|
949 #define OP_ST_ATOMIC(insn,fname,almask) \ |
|
950 static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ |
|
951 { \ |
|
952 TCGv r_tmp = tcg_temp_local_new(); \ |
|
953 int l1 = gen_new_label(); \ |
|
954 int l2 = gen_new_label(); \ |
|
955 int l3 = gen_new_label(); \ |
|
956 \ |
|
957 tcg_gen_andi_tl(r_tmp, t0, almask); \ |
|
958 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1); \ |
|
959 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \ |
|
960 generate_exception(ctx, EXCP_AdES); \ |
|
961 gen_set_label(l1); \ |
|
962 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \ |
|
963 tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2); \ |
|
964 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \ |
|
965 tcg_gen_movi_tl(t0, 1); \ |
|
966 tcg_gen_br(l3); \ |
|
967 gen_set_label(l2); \ |
|
968 tcg_gen_movi_tl(t0, 0); \ |
|
969 gen_set_label(l3); \ |
|
970 tcg_temp_free(r_tmp); \ |
|
971 } |
|
972 OP_ST_ATOMIC(sc,st32,0x3); |
|
973 #if defined(TARGET_MIPS64) |
|
974 OP_ST_ATOMIC(scd,st64,0x7); |
|
975 #endif |
|
976 #undef OP_ST_ATOMIC |
|
977 |
|
978 /* Load and store */ |
|
979 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, |
|
980 int base, int16_t offset) |
|
981 { |
|
982 const char *opn = "ldst"; |
|
983 TCGv t0 = tcg_temp_local_new(); |
|
984 TCGv t1 = tcg_temp_local_new(); |
|
985 |
|
986 if (base == 0) { |
|
987 tcg_gen_movi_tl(t0, offset); |
|
988 } else if (offset == 0) { |
|
989 gen_load_gpr(t0, base); |
|
990 } else { |
|
991 gen_load_gpr(t0, base); |
|
992 tcg_gen_movi_tl(t1, offset); |
|
993 gen_op_addr_add(ctx, t0, t1); |
|
994 } |
|
995 /* Don't do NOP if destination is zero: we must perform the actual |
|
996 memory access. */ |
|
997 switch (opc) { |
|
998 #if defined(TARGET_MIPS64) |
|
999 case OPC_LWU: |
|
1000 op_ldst_lwu(t0, ctx); |
|
1001 gen_store_gpr(t0, rt); |
|
1002 opn = "lwu"; |
|
1003 break; |
|
1004 case OPC_LD: |
|
1005 op_ldst_ld(t0, ctx); |
|
1006 gen_store_gpr(t0, rt); |
|
1007 opn = "ld"; |
|
1008 break; |
|
1009 case OPC_LLD: |
|
1010 op_ldst_lld(t0, t1, ctx); |
|
1011 gen_store_gpr(t0, rt); |
|
1012 opn = "lld"; |
|
1013 break; |
|
1014 case OPC_SD: |
|
1015 gen_load_gpr(t1, rt); |
|
1016 op_ldst_sd(t0, t1, ctx); |
|
1017 opn = "sd"; |
|
1018 break; |
|
1019 case OPC_SCD: |
|
1020 save_cpu_state(ctx, 1); |
|
1021 gen_load_gpr(t1, rt); |
|
1022 op_ldst_scd(t0, t1, ctx); |
|
1023 gen_store_gpr(t0, rt); |
|
1024 opn = "scd"; |
|
1025 break; |
|
1026 case OPC_LDL: |
|
1027 save_cpu_state(ctx, 1); |
|
1028 gen_load_gpr(t1, rt); |
|
1029 gen_helper_3i(ldl, t1, t0, t1, ctx->mem_idx); |
|
1030 gen_store_gpr(t1, rt); |
|
1031 opn = "ldl"; |
|
1032 break; |
|
1033 case OPC_SDL: |
|
1034 save_cpu_state(ctx, 1); |
|
1035 gen_load_gpr(t1, rt); |
|
1036 gen_helper_2i(sdl, t0, t1, ctx->mem_idx); |
|
1037 opn = "sdl"; |
|
1038 break; |
|
1039 case OPC_LDR: |
|
1040 save_cpu_state(ctx, 1); |
|
1041 gen_load_gpr(t1, rt); |
|
1042 gen_helper_3i(ldr, t1, t0, t1, ctx->mem_idx); |
|
1043 gen_store_gpr(t1, rt); |
|
1044 opn = "ldr"; |
|
1045 break; |
|
1046 case OPC_SDR: |
|
1047 save_cpu_state(ctx, 1); |
|
1048 gen_load_gpr(t1, rt); |
|
1049 gen_helper_2i(sdr, t0, t1, ctx->mem_idx); |
|
1050 opn = "sdr"; |
|
1051 break; |
|
1052 #endif |
|
1053 case OPC_LW: |
|
1054 op_ldst_lw(t0, ctx); |
|
1055 gen_store_gpr(t0, rt); |
|
1056 opn = "lw"; |
|
1057 break; |
|
1058 case OPC_SW: |
|
1059 gen_load_gpr(t1, rt); |
|
1060 op_ldst_sw(t0, t1, ctx); |
|
1061 opn = "sw"; |
|
1062 break; |
|
1063 case OPC_LH: |
|
1064 op_ldst_lh(t0, ctx); |
|
1065 gen_store_gpr(t0, rt); |
|
1066 opn = "lh"; |
|
1067 break; |
|
1068 case OPC_SH: |
|
1069 gen_load_gpr(t1, rt); |
|
1070 op_ldst_sh(t0, t1, ctx); |
|
1071 opn = "sh"; |
|
1072 break; |
|
1073 case OPC_LHU: |
|
1074 op_ldst_lhu(t0, ctx); |
|
1075 gen_store_gpr(t0, rt); |
|
1076 opn = "lhu"; |
|
1077 break; |
|
1078 case OPC_LB: |
|
1079 op_ldst_lb(t0, ctx); |
|
1080 gen_store_gpr(t0, rt); |
|
1081 opn = "lb"; |
|
1082 break; |
|
1083 case OPC_SB: |
|
1084 gen_load_gpr(t1, rt); |
|
1085 op_ldst_sb(t0, t1, ctx); |
|
1086 opn = "sb"; |
|
1087 break; |
|
1088 case OPC_LBU: |
|
1089 op_ldst_lbu(t0, ctx); |
|
1090 gen_store_gpr(t0, rt); |
|
1091 opn = "lbu"; |
|
1092 break; |
|
1093 case OPC_LWL: |
|
1094 save_cpu_state(ctx, 1); |
|
1095 gen_load_gpr(t1, rt); |
|
1096 gen_helper_3i(lwl, t1, t0, t1, ctx->mem_idx); |
|
1097 gen_store_gpr(t1, rt); |
|
1098 opn = "lwl"; |
|
1099 break; |
|
1100 case OPC_SWL: |
|
1101 save_cpu_state(ctx, 1); |
|
1102 gen_load_gpr(t1, rt); |
|
1103 gen_helper_2i(swl, t0, t1, ctx->mem_idx); |
|
1104 opn = "swr"; |
|
1105 break; |
|
1106 case OPC_LWR: |
|
1107 save_cpu_state(ctx, 1); |
|
1108 gen_load_gpr(t1, rt); |
|
1109 gen_helper_3i(lwr, t1, t0, t1, ctx->mem_idx); |
|
1110 gen_store_gpr(t1, rt); |
|
1111 opn = "lwr"; |
|
1112 break; |
|
1113 case OPC_SWR: |
|
1114 save_cpu_state(ctx, 1); |
|
1115 gen_load_gpr(t1, rt); |
|
1116 gen_helper_2i(swr, t0, t1, ctx->mem_idx); |
|
1117 opn = "swr"; |
|
1118 break; |
|
1119 case OPC_LL: |
|
1120 op_ldst_ll(t0, t1, ctx); |
|
1121 gen_store_gpr(t0, rt); |
|
1122 opn = "ll"; |
|
1123 break; |
|
1124 case OPC_SC: |
|
1125 save_cpu_state(ctx, 1); |
|
1126 gen_load_gpr(t1, rt); |
|
1127 op_ldst_sc(t0, t1, ctx); |
|
1128 gen_store_gpr(t0, rt); |
|
1129 opn = "sc"; |
|
1130 break; |
|
1131 default: |
|
1132 MIPS_INVAL(opn); |
|
1133 generate_exception(ctx, EXCP_RI); |
|
1134 goto out; |
|
1135 } |
|
1136 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); |
|
1137 out: |
|
1138 tcg_temp_free(t0); |
|
1139 tcg_temp_free(t1); |
|
1140 } |
|
1141 |
|
1142 /* Load and store */ |
|
1143 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, |
|
1144 int base, int16_t offset) |
|
1145 { |
|
1146 const char *opn = "flt_ldst"; |
|
1147 TCGv t0 = tcg_temp_local_new(); |
|
1148 |
|
1149 if (base == 0) { |
|
1150 tcg_gen_movi_tl(t0, offset); |
|
1151 } else if (offset == 0) { |
|
1152 gen_load_gpr(t0, base); |
|
1153 } else { |
|
1154 TCGv t1 = tcg_temp_local_new(); |
|
1155 |
|
1156 gen_load_gpr(t0, base); |
|
1157 tcg_gen_movi_tl(t1, offset); |
|
1158 gen_op_addr_add(ctx, t0, t1); |
|
1159 tcg_temp_free(t1); |
|
1160 } |
|
1161 /* Don't do NOP if destination is zero: we must perform the actual |
|
1162 memory access. */ |
|
1163 switch (opc) { |
|
1164 case OPC_LWC1: |
|
1165 { |
|
1166 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
1167 TCGv t1 = tcg_temp_new(); |
|
1168 |
|
1169 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx); |
|
1170 tcg_gen_trunc_tl_i32(fp0, t1); |
|
1171 gen_store_fpr32(fp0, ft); |
|
1172 tcg_temp_free(t1); |
|
1173 tcg_temp_free_i32(fp0); |
|
1174 } |
|
1175 opn = "lwc1"; |
|
1176 break; |
|
1177 case OPC_SWC1: |
|
1178 { |
|
1179 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
1180 TCGv t1 = tcg_temp_new(); |
|
1181 |
|
1182 gen_load_fpr32(fp0, ft); |
|
1183 tcg_gen_extu_i32_tl(t1, fp0); |
|
1184 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx); |
|
1185 tcg_temp_free(t1); |
|
1186 tcg_temp_free_i32(fp0); |
|
1187 } |
|
1188 opn = "swc1"; |
|
1189 break; |
|
1190 case OPC_LDC1: |
|
1191 { |
|
1192 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
1193 |
|
1194 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx); |
|
1195 gen_store_fpr64(ctx, fp0, ft); |
|
1196 tcg_temp_free_i64(fp0); |
|
1197 } |
|
1198 opn = "ldc1"; |
|
1199 break; |
|
1200 case OPC_SDC1: |
|
1201 { |
|
1202 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
1203 |
|
1204 gen_load_fpr64(ctx, fp0, ft); |
|
1205 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx); |
|
1206 tcg_temp_free_i64(fp0); |
|
1207 } |
|
1208 opn = "sdc1"; |
|
1209 break; |
|
1210 default: |
|
1211 MIPS_INVAL(opn); |
|
1212 generate_exception(ctx, EXCP_RI); |
|
1213 goto out; |
|
1214 } |
|
1215 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]); |
|
1216 out: |
|
1217 tcg_temp_free(t0); |
|
1218 } |
|
1219 |
|
1220 /* Arithmetic with immediate operand */ |
|
1221 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, |
|
1222 int rt, int rs, int16_t imm) |
|
1223 { |
|
1224 target_ulong uimm; |
|
1225 const char *opn = "imm arith"; |
|
1226 TCGv t0 = tcg_temp_local_new(); |
|
1227 |
|
1228 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) { |
|
1229 /* If no destination, treat it as a NOP. |
|
1230 For addi, we must generate the overflow exception when needed. */ |
|
1231 MIPS_DEBUG("NOP"); |
|
1232 goto out; |
|
1233 } |
|
1234 uimm = (uint16_t)imm; |
|
1235 switch (opc) { |
|
1236 case OPC_ADDI: |
|
1237 case OPC_ADDIU: |
|
1238 #if defined(TARGET_MIPS64) |
|
1239 case OPC_DADDI: |
|
1240 case OPC_DADDIU: |
|
1241 #endif |
|
1242 case OPC_SLTI: |
|
1243 case OPC_SLTIU: |
|
1244 uimm = (target_long)imm; /* Sign extend to 32/64 bits */ |
|
1245 /* Fall through. */ |
|
1246 case OPC_ANDI: |
|
1247 case OPC_ORI: |
|
1248 case OPC_XORI: |
|
1249 gen_load_gpr(t0, rs); |
|
1250 break; |
|
1251 case OPC_LUI: |
|
1252 tcg_gen_movi_tl(t0, imm << 16); |
|
1253 break; |
|
1254 case OPC_SLL: |
|
1255 case OPC_SRA: |
|
1256 case OPC_SRL: |
|
1257 #if defined(TARGET_MIPS64) |
|
1258 case OPC_DSLL: |
|
1259 case OPC_DSRA: |
|
1260 case OPC_DSRL: |
|
1261 case OPC_DSLL32: |
|
1262 case OPC_DSRA32: |
|
1263 case OPC_DSRL32: |
|
1264 #endif |
|
1265 uimm &= 0x1f; |
|
1266 gen_load_gpr(t0, rs); |
|
1267 break; |
|
1268 } |
|
1269 switch (opc) { |
|
1270 case OPC_ADDI: |
|
1271 { |
|
1272 TCGv r_tmp1 = tcg_temp_new(); |
|
1273 TCGv r_tmp2 = tcg_temp_new(); |
|
1274 int l1 = gen_new_label(); |
|
1275 |
|
1276 save_cpu_state(ctx, 1); |
|
1277 tcg_gen_ext32s_tl(r_tmp1, t0); |
|
1278 tcg_gen_addi_tl(t0, r_tmp1, uimm); |
|
1279 |
|
1280 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm); |
|
1281 tcg_gen_xori_tl(r_tmp2, t0, uimm); |
|
1282 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); |
|
1283 tcg_temp_free(r_tmp2); |
|
1284 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1); |
|
1285 /* operands of same sign, result different sign */ |
|
1286 generate_exception(ctx, EXCP_OVERFLOW); |
|
1287 gen_set_label(l1); |
|
1288 tcg_temp_free(r_tmp1); |
|
1289 |
|
1290 tcg_gen_ext32s_tl(t0, t0); |
|
1291 } |
|
1292 opn = "addi"; |
|
1293 break; |
|
1294 case OPC_ADDIU: |
|
1295 tcg_gen_addi_tl(t0, t0, uimm); |
|
1296 tcg_gen_ext32s_tl(t0, t0); |
|
1297 opn = "addiu"; |
|
1298 break; |
|
1299 #if defined(TARGET_MIPS64) |
|
1300 case OPC_DADDI: |
|
1301 { |
|
1302 TCGv r_tmp1 = tcg_temp_new(); |
|
1303 TCGv r_tmp2 = tcg_temp_new(); |
|
1304 int l1 = gen_new_label(); |
|
1305 |
|
1306 save_cpu_state(ctx, 1); |
|
1307 tcg_gen_mov_tl(r_tmp1, t0); |
|
1308 tcg_gen_addi_tl(t0, t0, uimm); |
|
1309 |
|
1310 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm); |
|
1311 tcg_gen_xori_tl(r_tmp2, t0, uimm); |
|
1312 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); |
|
1313 tcg_temp_free(r_tmp2); |
|
1314 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1); |
|
1315 /* operands of same sign, result different sign */ |
|
1316 generate_exception(ctx, EXCP_OVERFLOW); |
|
1317 gen_set_label(l1); |
|
1318 tcg_temp_free(r_tmp1); |
|
1319 } |
|
1320 opn = "daddi"; |
|
1321 break; |
|
1322 case OPC_DADDIU: |
|
1323 tcg_gen_addi_tl(t0, t0, uimm); |
|
1324 opn = "daddiu"; |
|
1325 break; |
|
1326 #endif |
|
1327 case OPC_SLTI: |
|
1328 gen_op_lti(t0, uimm); |
|
1329 opn = "slti"; |
|
1330 break; |
|
1331 case OPC_SLTIU: |
|
1332 gen_op_ltiu(t0, uimm); |
|
1333 opn = "sltiu"; |
|
1334 break; |
|
1335 case OPC_ANDI: |
|
1336 tcg_gen_andi_tl(t0, t0, uimm); |
|
1337 opn = "andi"; |
|
1338 break; |
|
1339 case OPC_ORI: |
|
1340 tcg_gen_ori_tl(t0, t0, uimm); |
|
1341 opn = "ori"; |
|
1342 break; |
|
1343 case OPC_XORI: |
|
1344 tcg_gen_xori_tl(t0, t0, uimm); |
|
1345 opn = "xori"; |
|
1346 break; |
|
1347 case OPC_LUI: |
|
1348 opn = "lui"; |
|
1349 break; |
|
1350 case OPC_SLL: |
|
1351 tcg_gen_shli_tl(t0, t0, uimm); |
|
1352 tcg_gen_ext32s_tl(t0, t0); |
|
1353 opn = "sll"; |
|
1354 break; |
|
1355 case OPC_SRA: |
|
1356 tcg_gen_ext32s_tl(t0, t0); |
|
1357 tcg_gen_sari_tl(t0, t0, uimm); |
|
1358 opn = "sra"; |
|
1359 break; |
|
1360 case OPC_SRL: |
|
1361 switch ((ctx->opcode >> 21) & 0x1f) { |
|
1362 case 0: |
|
1363 if (uimm != 0) { |
|
1364 tcg_gen_ext32u_tl(t0, t0); |
|
1365 tcg_gen_shri_tl(t0, t0, uimm); |
|
1366 } else { |
|
1367 tcg_gen_ext32s_tl(t0, t0); |
|
1368 } |
|
1369 opn = "srl"; |
|
1370 break; |
|
1371 case 1: |
|
1372 /* rotr is decoded as srl on non-R2 CPUs */ |
|
1373 if (env->insn_flags & ISA_MIPS32R2) { |
|
1374 if (uimm != 0) { |
|
1375 TCGv_i32 r_tmp1 = tcg_temp_new_i32(); |
|
1376 |
|
1377 tcg_gen_trunc_tl_i32(r_tmp1, t0); |
|
1378 tcg_gen_rotri_i32(r_tmp1, r_tmp1, uimm); |
|
1379 tcg_gen_ext_i32_tl(t0, r_tmp1); |
|
1380 tcg_temp_free_i32(r_tmp1); |
|
1381 } |
|
1382 opn = "rotr"; |
|
1383 } else { |
|
1384 if (uimm != 0) { |
|
1385 tcg_gen_ext32u_tl(t0, t0); |
|
1386 tcg_gen_shri_tl(t0, t0, uimm); |
|
1387 } else { |
|
1388 tcg_gen_ext32s_tl(t0, t0); |
|
1389 } |
|
1390 opn = "srl"; |
|
1391 } |
|
1392 break; |
|
1393 default: |
|
1394 MIPS_INVAL("invalid srl flag"); |
|
1395 generate_exception(ctx, EXCP_RI); |
|
1396 break; |
|
1397 } |
|
1398 break; |
|
1399 #if defined(TARGET_MIPS64) |
|
1400 case OPC_DSLL: |
|
1401 tcg_gen_shli_tl(t0, t0, uimm); |
|
1402 opn = "dsll"; |
|
1403 break; |
|
1404 case OPC_DSRA: |
|
1405 tcg_gen_sari_tl(t0, t0, uimm); |
|
1406 opn = "dsra"; |
|
1407 break; |
|
1408 case OPC_DSRL: |
|
1409 switch ((ctx->opcode >> 21) & 0x1f) { |
|
1410 case 0: |
|
1411 tcg_gen_shri_tl(t0, t0, uimm); |
|
1412 opn = "dsrl"; |
|
1413 break; |
|
1414 case 1: |
|
1415 /* drotr is decoded as dsrl on non-R2 CPUs */ |
|
1416 if (env->insn_flags & ISA_MIPS32R2) { |
|
1417 if (uimm != 0) { |
|
1418 tcg_gen_rotri_tl(t0, t0, uimm); |
|
1419 } |
|
1420 opn = "drotr"; |
|
1421 } else { |
|
1422 tcg_gen_shri_tl(t0, t0, uimm); |
|
1423 opn = "dsrl"; |
|
1424 } |
|
1425 break; |
|
1426 default: |
|
1427 MIPS_INVAL("invalid dsrl flag"); |
|
1428 generate_exception(ctx, EXCP_RI); |
|
1429 break; |
|
1430 } |
|
1431 break; |
|
1432 case OPC_DSLL32: |
|
1433 tcg_gen_shli_tl(t0, t0, uimm + 32); |
|
1434 opn = "dsll32"; |
|
1435 break; |
|
1436 case OPC_DSRA32: |
|
1437 tcg_gen_sari_tl(t0, t0, uimm + 32); |
|
1438 opn = "dsra32"; |
|
1439 break; |
|
1440 case OPC_DSRL32: |
|
1441 switch ((ctx->opcode >> 21) & 0x1f) { |
|
1442 case 0: |
|
1443 tcg_gen_shri_tl(t0, t0, uimm + 32); |
|
1444 opn = "dsrl32"; |
|
1445 break; |
|
1446 case 1: |
|
1447 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */ |
|
1448 if (env->insn_flags & ISA_MIPS32R2) { |
|
1449 tcg_gen_rotri_tl(t0, t0, uimm + 32); |
|
1450 opn = "drotr32"; |
|
1451 } else { |
|
1452 tcg_gen_shri_tl(t0, t0, uimm + 32); |
|
1453 opn = "dsrl32"; |
|
1454 } |
|
1455 break; |
|
1456 default: |
|
1457 MIPS_INVAL("invalid dsrl32 flag"); |
|
1458 generate_exception(ctx, EXCP_RI); |
|
1459 break; |
|
1460 } |
|
1461 break; |
|
1462 #endif |
|
1463 default: |
|
1464 MIPS_INVAL(opn); |
|
1465 generate_exception(ctx, EXCP_RI); |
|
1466 goto out; |
|
1467 } |
|
1468 gen_store_gpr(t0, rt); |
|
1469 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); |
|
1470 out: |
|
1471 tcg_temp_free(t0); |
|
1472 } |
|
1473 |
|
1474 /* Arithmetic */ |
|
1475 static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, |
|
1476 int rd, int rs, int rt) |
|
1477 { |
|
1478 const char *opn = "arith"; |
|
1479 TCGv t0 = tcg_temp_local_new(); |
|
1480 TCGv t1 = tcg_temp_local_new(); |
|
1481 |
|
1482 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB |
|
1483 && opc != OPC_DADD && opc != OPC_DSUB) { |
|
1484 /* If no destination, treat it as a NOP. |
|
1485 For add & sub, we must generate the overflow exception when needed. */ |
|
1486 MIPS_DEBUG("NOP"); |
|
1487 goto out; |
|
1488 } |
|
1489 gen_load_gpr(t0, rs); |
|
1490 /* Specialcase the conventional move operation. */ |
|
1491 if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU |
|
1492 || opc == OPC_SUBU || opc == OPC_DSUBU)) { |
|
1493 gen_store_gpr(t0, rd); |
|
1494 goto out; |
|
1495 } |
|
1496 gen_load_gpr(t1, rt); |
|
1497 switch (opc) { |
|
1498 case OPC_ADD: |
|
1499 { |
|
1500 TCGv r_tmp1 = tcg_temp_new(); |
|
1501 TCGv r_tmp2 = tcg_temp_new(); |
|
1502 int l1 = gen_new_label(); |
|
1503 |
|
1504 save_cpu_state(ctx, 1); |
|
1505 tcg_gen_ext32s_tl(r_tmp1, t0); |
|
1506 tcg_gen_ext32s_tl(r_tmp2, t1); |
|
1507 tcg_gen_add_tl(t0, r_tmp1, r_tmp2); |
|
1508 |
|
1509 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1); |
|
1510 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1); |
|
1511 tcg_gen_xor_tl(r_tmp2, t0, t1); |
|
1512 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); |
|
1513 tcg_temp_free(r_tmp2); |
|
1514 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1); |
|
1515 /* operands of same sign, result different sign */ |
|
1516 generate_exception(ctx, EXCP_OVERFLOW); |
|
1517 gen_set_label(l1); |
|
1518 tcg_temp_free(r_tmp1); |
|
1519 |
|
1520 tcg_gen_ext32s_tl(t0, t0); |
|
1521 } |
|
1522 opn = "add"; |
|
1523 break; |
|
1524 case OPC_ADDU: |
|
1525 tcg_gen_add_tl(t0, t0, t1); |
|
1526 tcg_gen_ext32s_tl(t0, t0); |
|
1527 opn = "addu"; |
|
1528 break; |
|
1529 case OPC_SUB: |
|
1530 { |
|
1531 TCGv r_tmp1 = tcg_temp_new(); |
|
1532 TCGv r_tmp2 = tcg_temp_new(); |
|
1533 int l1 = gen_new_label(); |
|
1534 |
|
1535 save_cpu_state(ctx, 1); |
|
1536 tcg_gen_ext32s_tl(r_tmp1, t0); |
|
1537 tcg_gen_ext32s_tl(r_tmp2, t1); |
|
1538 tcg_gen_sub_tl(t0, r_tmp1, r_tmp2); |
|
1539 |
|
1540 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1); |
|
1541 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0); |
|
1542 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); |
|
1543 tcg_temp_free(r_tmp2); |
|
1544 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1); |
|
1545 /* operands of different sign, first operand and result different sign */ |
|
1546 generate_exception(ctx, EXCP_OVERFLOW); |
|
1547 gen_set_label(l1); |
|
1548 tcg_temp_free(r_tmp1); |
|
1549 |
|
1550 tcg_gen_ext32s_tl(t0, t0); |
|
1551 } |
|
1552 opn = "sub"; |
|
1553 break; |
|
1554 case OPC_SUBU: |
|
1555 tcg_gen_sub_tl(t0, t0, t1); |
|
1556 tcg_gen_ext32s_tl(t0, t0); |
|
1557 opn = "subu"; |
|
1558 break; |
|
1559 #if defined(TARGET_MIPS64) |
|
1560 case OPC_DADD: |
|
1561 { |
|
1562 TCGv r_tmp1 = tcg_temp_new(); |
|
1563 TCGv r_tmp2 = tcg_temp_new(); |
|
1564 int l1 = gen_new_label(); |
|
1565 |
|
1566 save_cpu_state(ctx, 1); |
|
1567 tcg_gen_mov_tl(r_tmp1, t0); |
|
1568 tcg_gen_add_tl(t0, t0, t1); |
|
1569 |
|
1570 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1); |
|
1571 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1); |
|
1572 tcg_gen_xor_tl(r_tmp2, t0, t1); |
|
1573 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); |
|
1574 tcg_temp_free(r_tmp2); |
|
1575 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1); |
|
1576 /* operands of same sign, result different sign */ |
|
1577 generate_exception(ctx, EXCP_OVERFLOW); |
|
1578 gen_set_label(l1); |
|
1579 tcg_temp_free(r_tmp1); |
|
1580 } |
|
1581 opn = "dadd"; |
|
1582 break; |
|
1583 case OPC_DADDU: |
|
1584 tcg_gen_add_tl(t0, t0, t1); |
|
1585 opn = "daddu"; |
|
1586 break; |
|
1587 case OPC_DSUB: |
|
1588 { |
|
1589 TCGv r_tmp1 = tcg_temp_new(); |
|
1590 TCGv r_tmp2 = tcg_temp_new(); |
|
1591 int l1 = gen_new_label(); |
|
1592 |
|
1593 save_cpu_state(ctx, 1); |
|
1594 tcg_gen_mov_tl(r_tmp1, t0); |
|
1595 tcg_gen_sub_tl(t0, t0, t1); |
|
1596 |
|
1597 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1); |
|
1598 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0); |
|
1599 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2); |
|
1600 tcg_temp_free(r_tmp2); |
|
1601 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1); |
|
1602 /* operands of different sign, first operand and result different sign */ |
|
1603 generate_exception(ctx, EXCP_OVERFLOW); |
|
1604 gen_set_label(l1); |
|
1605 tcg_temp_free(r_tmp1); |
|
1606 } |
|
1607 opn = "dsub"; |
|
1608 break; |
|
1609 case OPC_DSUBU: |
|
1610 tcg_gen_sub_tl(t0, t0, t1); |
|
1611 opn = "dsubu"; |
|
1612 break; |
|
1613 #endif |
|
1614 case OPC_SLT: |
|
1615 gen_op_lt(t0, t1); |
|
1616 opn = "slt"; |
|
1617 break; |
|
1618 case OPC_SLTU: |
|
1619 gen_op_ltu(t0, t1); |
|
1620 opn = "sltu"; |
|
1621 break; |
|
1622 case OPC_AND: |
|
1623 tcg_gen_and_tl(t0, t0, t1); |
|
1624 opn = "and"; |
|
1625 break; |
|
1626 case OPC_NOR: |
|
1627 tcg_gen_or_tl(t0, t0, t1); |
|
1628 tcg_gen_not_tl(t0, t0); |
|
1629 opn = "nor"; |
|
1630 break; |
|
1631 case OPC_OR: |
|
1632 tcg_gen_or_tl(t0, t0, t1); |
|
1633 opn = "or"; |
|
1634 break; |
|
1635 case OPC_XOR: |
|
1636 tcg_gen_xor_tl(t0, t0, t1); |
|
1637 opn = "xor"; |
|
1638 break; |
|
1639 case OPC_MUL: |
|
1640 tcg_gen_mul_tl(t0, t0, t1); |
|
1641 tcg_gen_ext32s_tl(t0, t0); |
|
1642 opn = "mul"; |
|
1643 break; |
|
1644 case OPC_MOVN: |
|
1645 { |
|
1646 int l1 = gen_new_label(); |
|
1647 |
|
1648 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); |
|
1649 gen_store_gpr(t0, rd); |
|
1650 gen_set_label(l1); |
|
1651 } |
|
1652 opn = "movn"; |
|
1653 goto print; |
|
1654 case OPC_MOVZ: |
|
1655 { |
|
1656 int l1 = gen_new_label(); |
|
1657 |
|
1658 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); |
|
1659 gen_store_gpr(t0, rd); |
|
1660 gen_set_label(l1); |
|
1661 } |
|
1662 opn = "movz"; |
|
1663 goto print; |
|
1664 case OPC_SLLV: |
|
1665 tcg_gen_andi_tl(t0, t0, 0x1f); |
|
1666 tcg_gen_shl_tl(t0, t1, t0); |
|
1667 tcg_gen_ext32s_tl(t0, t0); |
|
1668 opn = "sllv"; |
|
1669 break; |
|
1670 case OPC_SRAV: |
|
1671 tcg_gen_ext32s_tl(t1, t1); |
|
1672 tcg_gen_andi_tl(t0, t0, 0x1f); |
|
1673 tcg_gen_sar_tl(t0, t1, t0); |
|
1674 opn = "srav"; |
|
1675 break; |
|
1676 case OPC_SRLV: |
|
1677 switch ((ctx->opcode >> 6) & 0x1f) { |
|
1678 case 0: |
|
1679 tcg_gen_ext32u_tl(t1, t1); |
|
1680 tcg_gen_andi_tl(t0, t0, 0x1f); |
|
1681 tcg_gen_shr_tl(t0, t1, t0); |
|
1682 tcg_gen_ext32s_tl(t0, t0); |
|
1683 opn = "srlv"; |
|
1684 break; |
|
1685 case 1: |
|
1686 /* rotrv is decoded as srlv on non-R2 CPUs */ |
|
1687 if (env->insn_flags & ISA_MIPS32R2) { |
|
1688 int l1 = gen_new_label(); |
|
1689 int l2 = gen_new_label(); |
|
1690 |
|
1691 tcg_gen_andi_tl(t0, t0, 0x1f); |
|
1692 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); |
|
1693 { |
|
1694 TCGv_i32 r_tmp1 = tcg_temp_new_i32(); |
|
1695 TCGv_i32 r_tmp2 = tcg_temp_new_i32(); |
|
1696 |
|
1697 tcg_gen_trunc_tl_i32(r_tmp1, t0); |
|
1698 tcg_gen_trunc_tl_i32(r_tmp2, t1); |
|
1699 tcg_gen_rotr_i32(r_tmp1, r_tmp1, r_tmp2); |
|
1700 tcg_temp_free_i32(r_tmp1); |
|
1701 tcg_temp_free_i32(r_tmp2); |
|
1702 tcg_gen_br(l2); |
|
1703 } |
|
1704 gen_set_label(l1); |
|
1705 tcg_gen_mov_tl(t0, t1); |
|
1706 gen_set_label(l2); |
|
1707 opn = "rotrv"; |
|
1708 } else { |
|
1709 tcg_gen_ext32u_tl(t1, t1); |
|
1710 tcg_gen_andi_tl(t0, t0, 0x1f); |
|
1711 tcg_gen_shr_tl(t0, t1, t0); |
|
1712 tcg_gen_ext32s_tl(t0, t0); |
|
1713 opn = "srlv"; |
|
1714 } |
|
1715 break; |
|
1716 default: |
|
1717 MIPS_INVAL("invalid srlv flag"); |
|
1718 generate_exception(ctx, EXCP_RI); |
|
1719 break; |
|
1720 } |
|
1721 break; |
|
1722 #if defined(TARGET_MIPS64) |
|
1723 case OPC_DSLLV: |
|
1724 tcg_gen_andi_tl(t0, t0, 0x3f); |
|
1725 tcg_gen_shl_tl(t0, t1, t0); |
|
1726 opn = "dsllv"; |
|
1727 break; |
|
1728 case OPC_DSRAV: |
|
1729 tcg_gen_andi_tl(t0, t0, 0x3f); |
|
1730 tcg_gen_sar_tl(t0, t1, t0); |
|
1731 opn = "dsrav"; |
|
1732 break; |
|
1733 case OPC_DSRLV: |
|
1734 switch ((ctx->opcode >> 6) & 0x1f) { |
|
1735 case 0: |
|
1736 tcg_gen_andi_tl(t0, t0, 0x3f); |
|
1737 tcg_gen_shr_tl(t0, t1, t0); |
|
1738 opn = "dsrlv"; |
|
1739 break; |
|
1740 case 1: |
|
1741 /* drotrv is decoded as dsrlv on non-R2 CPUs */ |
|
1742 if (env->insn_flags & ISA_MIPS32R2) { |
|
1743 int l1 = gen_new_label(); |
|
1744 int l2 = gen_new_label(); |
|
1745 |
|
1746 tcg_gen_andi_tl(t0, t0, 0x3f); |
|
1747 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); |
|
1748 { |
|
1749 tcg_gen_rotr_tl(t0, t1, t0); |
|
1750 tcg_gen_br(l2); |
|
1751 } |
|
1752 gen_set_label(l1); |
|
1753 tcg_gen_mov_tl(t0, t1); |
|
1754 gen_set_label(l2); |
|
1755 opn = "drotrv"; |
|
1756 } else { |
|
1757 tcg_gen_andi_tl(t0, t0, 0x3f); |
|
1758 tcg_gen_shr_tl(t0, t1, t0); |
|
1759 opn = "dsrlv"; |
|
1760 } |
|
1761 break; |
|
1762 default: |
|
1763 MIPS_INVAL("invalid dsrlv flag"); |
|
1764 generate_exception(ctx, EXCP_RI); |
|
1765 break; |
|
1766 } |
|
1767 break; |
|
1768 #endif |
|
1769 default: |
|
1770 MIPS_INVAL(opn); |
|
1771 generate_exception(ctx, EXCP_RI); |
|
1772 goto out; |
|
1773 } |
|
1774 gen_store_gpr(t0, rd); |
|
1775 print: |
|
1776 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); |
|
1777 out: |
|
1778 tcg_temp_free(t0); |
|
1779 tcg_temp_free(t1); |
|
1780 } |
|
1781 |
|
1782 /* Arithmetic on HI/LO registers */ |
|
1783 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg) |
|
1784 { |
|
1785 const char *opn = "hilo"; |
|
1786 TCGv t0 = tcg_temp_local_new(); |
|
1787 |
|
1788 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) { |
|
1789 /* Treat as NOP. */ |
|
1790 MIPS_DEBUG("NOP"); |
|
1791 goto out; |
|
1792 } |
|
1793 switch (opc) { |
|
1794 case OPC_MFHI: |
|
1795 tcg_gen_mov_tl(t0, cpu_HI[0]); |
|
1796 gen_store_gpr(t0, reg); |
|
1797 opn = "mfhi"; |
|
1798 break; |
|
1799 case OPC_MFLO: |
|
1800 tcg_gen_mov_tl(t0, cpu_LO[0]); |
|
1801 gen_store_gpr(t0, reg); |
|
1802 opn = "mflo"; |
|
1803 break; |
|
1804 case OPC_MTHI: |
|
1805 gen_load_gpr(t0, reg); |
|
1806 tcg_gen_mov_tl(cpu_HI[0], t0); |
|
1807 opn = "mthi"; |
|
1808 break; |
|
1809 case OPC_MTLO: |
|
1810 gen_load_gpr(t0, reg); |
|
1811 tcg_gen_mov_tl(cpu_LO[0], t0); |
|
1812 opn = "mtlo"; |
|
1813 break; |
|
1814 default: |
|
1815 MIPS_INVAL(opn); |
|
1816 generate_exception(ctx, EXCP_RI); |
|
1817 goto out; |
|
1818 } |
|
1819 MIPS_DEBUG("%s %s", opn, regnames[reg]); |
|
1820 out: |
|
1821 tcg_temp_free(t0); |
|
1822 } |
|
1823 |
|
1824 static void gen_muldiv (DisasContext *ctx, uint32_t opc, |
|
1825 int rs, int rt) |
|
1826 { |
|
1827 const char *opn = "mul/div"; |
|
1828 TCGv t0 = tcg_temp_local_new(); |
|
1829 TCGv t1 = tcg_temp_local_new(); |
|
1830 |
|
1831 gen_load_gpr(t0, rs); |
|
1832 gen_load_gpr(t1, rt); |
|
1833 switch (opc) { |
|
1834 case OPC_DIV: |
|
1835 { |
|
1836 int l1 = gen_new_label(); |
|
1837 |
|
1838 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); |
|
1839 { |
|
1840 int l2 = gen_new_label(); |
|
1841 TCGv_i32 r_tmp1 = tcg_temp_local_new_i32(); |
|
1842 TCGv_i32 r_tmp2 = tcg_temp_local_new_i32(); |
|
1843 TCGv_i32 r_tmp3 = tcg_temp_local_new_i32(); |
|
1844 |
|
1845 tcg_gen_trunc_tl_i32(r_tmp1, t0); |
|
1846 tcg_gen_trunc_tl_i32(r_tmp2, t1); |
|
1847 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp1, -1 << 31, l2); |
|
1848 tcg_gen_brcondi_i32(TCG_COND_NE, r_tmp2, -1, l2); |
|
1849 tcg_gen_ext32s_tl(cpu_LO[0], t0); |
|
1850 tcg_gen_movi_tl(cpu_HI[0], 0); |
|
1851 tcg_gen_br(l1); |
|
1852 gen_set_label(l2); |
|
1853 tcg_gen_div_i32(r_tmp3, r_tmp1, r_tmp2); |
|
1854 tcg_gen_rem_i32(r_tmp2, r_tmp1, r_tmp2); |
|
1855 tcg_gen_ext_i32_tl(cpu_LO[0], r_tmp3); |
|
1856 tcg_gen_ext_i32_tl(cpu_HI[0], r_tmp2); |
|
1857 tcg_temp_free_i32(r_tmp1); |
|
1858 tcg_temp_free_i32(r_tmp2); |
|
1859 tcg_temp_free_i32(r_tmp3); |
|
1860 } |
|
1861 gen_set_label(l1); |
|
1862 } |
|
1863 opn = "div"; |
|
1864 break; |
|
1865 case OPC_DIVU: |
|
1866 { |
|
1867 int l1 = gen_new_label(); |
|
1868 |
|
1869 tcg_gen_ext32s_tl(t1, t1); |
|
1870 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); |
|
1871 { |
|
1872 TCGv_i32 r_tmp1 = tcg_temp_new_i32(); |
|
1873 TCGv_i32 r_tmp2 = tcg_temp_new_i32(); |
|
1874 TCGv_i32 r_tmp3 = tcg_temp_new_i32(); |
|
1875 |
|
1876 tcg_gen_trunc_tl_i32(r_tmp1, t0); |
|
1877 tcg_gen_trunc_tl_i32(r_tmp2, t1); |
|
1878 tcg_gen_divu_i32(r_tmp3, r_tmp1, r_tmp2); |
|
1879 tcg_gen_remu_i32(r_tmp1, r_tmp1, r_tmp2); |
|
1880 tcg_gen_ext_i32_tl(cpu_LO[0], r_tmp3); |
|
1881 tcg_gen_ext_i32_tl(cpu_HI[0], r_tmp1); |
|
1882 tcg_temp_free_i32(r_tmp1); |
|
1883 tcg_temp_free_i32(r_tmp2); |
|
1884 tcg_temp_free_i32(r_tmp3); |
|
1885 } |
|
1886 gen_set_label(l1); |
|
1887 } |
|
1888 opn = "divu"; |
|
1889 break; |
|
1890 case OPC_MULT: |
|
1891 { |
|
1892 TCGv_i64 r_tmp1 = tcg_temp_new_i64(); |
|
1893 TCGv_i64 r_tmp2 = tcg_temp_new_i64(); |
|
1894 |
|
1895 tcg_gen_ext_tl_i64(r_tmp1, t0); |
|
1896 tcg_gen_ext_tl_i64(r_tmp2, t1); |
|
1897 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); |
|
1898 tcg_temp_free_i64(r_tmp2); |
|
1899 tcg_gen_trunc_i64_tl(t0, r_tmp1); |
|
1900 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); |
|
1901 tcg_gen_trunc_i64_tl(t1, r_tmp1); |
|
1902 tcg_temp_free_i64(r_tmp1); |
|
1903 tcg_gen_ext32s_tl(cpu_LO[0], t0); |
|
1904 tcg_gen_ext32s_tl(cpu_HI[0], t1); |
|
1905 } |
|
1906 opn = "mult"; |
|
1907 break; |
|
1908 case OPC_MULTU: |
|
1909 { |
|
1910 TCGv_i64 r_tmp1 = tcg_temp_new_i64(); |
|
1911 TCGv_i64 r_tmp2 = tcg_temp_new_i64(); |
|
1912 |
|
1913 tcg_gen_ext32u_tl(t0, t0); |
|
1914 tcg_gen_ext32u_tl(t1, t1); |
|
1915 tcg_gen_extu_tl_i64(r_tmp1, t0); |
|
1916 tcg_gen_extu_tl_i64(r_tmp2, t1); |
|
1917 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); |
|
1918 tcg_temp_free_i64(r_tmp2); |
|
1919 tcg_gen_trunc_i64_tl(t0, r_tmp1); |
|
1920 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); |
|
1921 tcg_gen_trunc_i64_tl(t1, r_tmp1); |
|
1922 tcg_temp_free_i64(r_tmp1); |
|
1923 tcg_gen_ext32s_tl(cpu_LO[0], t0); |
|
1924 tcg_gen_ext32s_tl(cpu_HI[0], t1); |
|
1925 } |
|
1926 opn = "multu"; |
|
1927 break; |
|
1928 #if defined(TARGET_MIPS64) |
|
1929 case OPC_DDIV: |
|
1930 { |
|
1931 int l1 = gen_new_label(); |
|
1932 |
|
1933 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); |
|
1934 { |
|
1935 int l2 = gen_new_label(); |
|
1936 |
|
1937 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2); |
|
1938 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2); |
|
1939 tcg_gen_mov_tl(cpu_LO[0], t0); |
|
1940 tcg_gen_movi_tl(cpu_HI[0], 0); |
|
1941 tcg_gen_br(l1); |
|
1942 gen_set_label(l2); |
|
1943 tcg_gen_div_i64(cpu_LO[0], t0, t1); |
|
1944 tcg_gen_rem_i64(cpu_HI[0], t0, t1); |
|
1945 } |
|
1946 gen_set_label(l1); |
|
1947 } |
|
1948 opn = "ddiv"; |
|
1949 break; |
|
1950 case OPC_DDIVU: |
|
1951 { |
|
1952 int l1 = gen_new_label(); |
|
1953 |
|
1954 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); |
|
1955 tcg_gen_divu_i64(cpu_LO[0], t0, t1); |
|
1956 tcg_gen_remu_i64(cpu_HI[0], t0, t1); |
|
1957 gen_set_label(l1); |
|
1958 } |
|
1959 opn = "ddivu"; |
|
1960 break; |
|
1961 case OPC_DMULT: |
|
1962 gen_helper_dmult(t0, t1); |
|
1963 opn = "dmult"; |
|
1964 break; |
|
1965 case OPC_DMULTU: |
|
1966 gen_helper_dmultu(t0, t1); |
|
1967 opn = "dmultu"; |
|
1968 break; |
|
1969 #endif |
|
1970 case OPC_MADD: |
|
1971 { |
|
1972 TCGv_i64 r_tmp1 = tcg_temp_new_i64(); |
|
1973 TCGv_i64 r_tmp2 = tcg_temp_new_i64(); |
|
1974 |
|
1975 tcg_gen_ext_tl_i64(r_tmp1, t0); |
|
1976 tcg_gen_ext_tl_i64(r_tmp2, t1); |
|
1977 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); |
|
1978 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]); |
|
1979 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2); |
|
1980 tcg_temp_free_i64(r_tmp2); |
|
1981 tcg_gen_trunc_i64_tl(t0, r_tmp1); |
|
1982 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); |
|
1983 tcg_gen_trunc_i64_tl(t1, r_tmp1); |
|
1984 tcg_temp_free_i64(r_tmp1); |
|
1985 tcg_gen_ext32s_tl(cpu_LO[0], t0); |
|
1986 tcg_gen_ext32s_tl(cpu_LO[1], t1); |
|
1987 } |
|
1988 opn = "madd"; |
|
1989 break; |
|
1990 case OPC_MADDU: |
|
1991 { |
|
1992 TCGv_i64 r_tmp1 = tcg_temp_new_i64(); |
|
1993 TCGv_i64 r_tmp2 = tcg_temp_new_i64(); |
|
1994 |
|
1995 tcg_gen_ext32u_tl(t0, t0); |
|
1996 tcg_gen_ext32u_tl(t1, t1); |
|
1997 tcg_gen_extu_tl_i64(r_tmp1, t0); |
|
1998 tcg_gen_extu_tl_i64(r_tmp2, t1); |
|
1999 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); |
|
2000 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]); |
|
2001 tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2); |
|
2002 tcg_temp_free_i64(r_tmp2); |
|
2003 tcg_gen_trunc_i64_tl(t0, r_tmp1); |
|
2004 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); |
|
2005 tcg_gen_trunc_i64_tl(t1, r_tmp1); |
|
2006 tcg_temp_free_i64(r_tmp1); |
|
2007 tcg_gen_ext32s_tl(cpu_LO[0], t0); |
|
2008 tcg_gen_ext32s_tl(cpu_HI[0], t1); |
|
2009 } |
|
2010 opn = "maddu"; |
|
2011 break; |
|
2012 case OPC_MSUB: |
|
2013 { |
|
2014 TCGv_i64 r_tmp1 = tcg_temp_new_i64(); |
|
2015 TCGv_i64 r_tmp2 = tcg_temp_new_i64(); |
|
2016 |
|
2017 tcg_gen_ext_tl_i64(r_tmp1, t0); |
|
2018 tcg_gen_ext_tl_i64(r_tmp2, t1); |
|
2019 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); |
|
2020 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]); |
|
2021 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2); |
|
2022 tcg_temp_free_i64(r_tmp2); |
|
2023 tcg_gen_trunc_i64_tl(t0, r_tmp1); |
|
2024 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); |
|
2025 tcg_gen_trunc_i64_tl(t1, r_tmp1); |
|
2026 tcg_temp_free_i64(r_tmp1); |
|
2027 tcg_gen_ext32s_tl(cpu_LO[0], t0); |
|
2028 tcg_gen_ext32s_tl(cpu_HI[0], t1); |
|
2029 } |
|
2030 opn = "msub"; |
|
2031 break; |
|
2032 case OPC_MSUBU: |
|
2033 { |
|
2034 TCGv_i64 r_tmp1 = tcg_temp_new_i64(); |
|
2035 TCGv_i64 r_tmp2 = tcg_temp_new_i64(); |
|
2036 |
|
2037 tcg_gen_ext32u_tl(t0, t0); |
|
2038 tcg_gen_ext32u_tl(t1, t1); |
|
2039 tcg_gen_extu_tl_i64(r_tmp1, t0); |
|
2040 tcg_gen_extu_tl_i64(r_tmp2, t1); |
|
2041 tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); |
|
2042 tcg_gen_concat_tl_i64(r_tmp2, cpu_LO[0], cpu_HI[0]); |
|
2043 tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2); |
|
2044 tcg_temp_free_i64(r_tmp2); |
|
2045 tcg_gen_trunc_i64_tl(t0, r_tmp1); |
|
2046 tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); |
|
2047 tcg_gen_trunc_i64_tl(t1, r_tmp1); |
|
2048 tcg_temp_free_i64(r_tmp1); |
|
2049 tcg_gen_ext32s_tl(cpu_LO[0], t0); |
|
2050 tcg_gen_ext32s_tl(cpu_HI[0], t1); |
|
2051 } |
|
2052 opn = "msubu"; |
|
2053 break; |
|
2054 default: |
|
2055 MIPS_INVAL(opn); |
|
2056 generate_exception(ctx, EXCP_RI); |
|
2057 goto out; |
|
2058 } |
|
2059 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]); |
|
2060 out: |
|
2061 tcg_temp_free(t0); |
|
2062 tcg_temp_free(t1); |
|
2063 } |
|
2064 |
|
2065 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc, |
|
2066 int rd, int rs, int rt) |
|
2067 { |
|
2068 const char *opn = "mul vr54xx"; |
|
2069 TCGv t0 = tcg_temp_local_new(); |
|
2070 TCGv t1 = tcg_temp_local_new(); |
|
2071 |
|
2072 gen_load_gpr(t0, rs); |
|
2073 gen_load_gpr(t1, rt); |
|
2074 |
|
2075 switch (opc) { |
|
2076 case OPC_VR54XX_MULS: |
|
2077 gen_helper_muls(t0, t0, t1); |
|
2078 opn = "muls"; |
|
2079 break; |
|
2080 case OPC_VR54XX_MULSU: |
|
2081 gen_helper_mulsu(t0, t0, t1); |
|
2082 opn = "mulsu"; |
|
2083 break; |
|
2084 case OPC_VR54XX_MACC: |
|
2085 gen_helper_macc(t0, t0, t1); |
|
2086 opn = "macc"; |
|
2087 break; |
|
2088 case OPC_VR54XX_MACCU: |
|
2089 gen_helper_maccu(t0, t0, t1); |
|
2090 opn = "maccu"; |
|
2091 break; |
|
2092 case OPC_VR54XX_MSAC: |
|
2093 gen_helper_msac(t0, t0, t1); |
|
2094 opn = "msac"; |
|
2095 break; |
|
2096 case OPC_VR54XX_MSACU: |
|
2097 gen_helper_msacu(t0, t0, t1); |
|
2098 opn = "msacu"; |
|
2099 break; |
|
2100 case OPC_VR54XX_MULHI: |
|
2101 gen_helper_mulhi(t0, t0, t1); |
|
2102 opn = "mulhi"; |
|
2103 break; |
|
2104 case OPC_VR54XX_MULHIU: |
|
2105 gen_helper_mulhiu(t0, t0, t1); |
|
2106 opn = "mulhiu"; |
|
2107 break; |
|
2108 case OPC_VR54XX_MULSHI: |
|
2109 gen_helper_mulshi(t0, t0, t1); |
|
2110 opn = "mulshi"; |
|
2111 break; |
|
2112 case OPC_VR54XX_MULSHIU: |
|
2113 gen_helper_mulshiu(t0, t0, t1); |
|
2114 opn = "mulshiu"; |
|
2115 break; |
|
2116 case OPC_VR54XX_MACCHI: |
|
2117 gen_helper_macchi(t0, t0, t1); |
|
2118 opn = "macchi"; |
|
2119 break; |
|
2120 case OPC_VR54XX_MACCHIU: |
|
2121 gen_helper_macchiu(t0, t0, t1); |
|
2122 opn = "macchiu"; |
|
2123 break; |
|
2124 case OPC_VR54XX_MSACHI: |
|
2125 gen_helper_msachi(t0, t0, t1); |
|
2126 opn = "msachi"; |
|
2127 break; |
|
2128 case OPC_VR54XX_MSACHIU: |
|
2129 gen_helper_msachiu(t0, t0, t1); |
|
2130 opn = "msachiu"; |
|
2131 break; |
|
2132 default: |
|
2133 MIPS_INVAL("mul vr54xx"); |
|
2134 generate_exception(ctx, EXCP_RI); |
|
2135 goto out; |
|
2136 } |
|
2137 gen_store_gpr(t0, rd); |
|
2138 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); |
|
2139 |
|
2140 out: |
|
2141 tcg_temp_free(t0); |
|
2142 tcg_temp_free(t1); |
|
2143 } |
|
2144 |
|
2145 static void gen_cl (DisasContext *ctx, uint32_t opc, |
|
2146 int rd, int rs) |
|
2147 { |
|
2148 const char *opn = "CLx"; |
|
2149 TCGv t0 = tcg_temp_local_new(); |
|
2150 |
|
2151 if (rd == 0) { |
|
2152 /* Treat as NOP. */ |
|
2153 MIPS_DEBUG("NOP"); |
|
2154 goto out; |
|
2155 } |
|
2156 gen_load_gpr(t0, rs); |
|
2157 switch (opc) { |
|
2158 case OPC_CLO: |
|
2159 gen_helper_clo(t0, t0); |
|
2160 opn = "clo"; |
|
2161 break; |
|
2162 case OPC_CLZ: |
|
2163 gen_helper_clz(t0, t0); |
|
2164 opn = "clz"; |
|
2165 break; |
|
2166 #if defined(TARGET_MIPS64) |
|
2167 case OPC_DCLO: |
|
2168 gen_helper_dclo(t0, t0); |
|
2169 opn = "dclo"; |
|
2170 break; |
|
2171 case OPC_DCLZ: |
|
2172 gen_helper_dclz(t0, t0); |
|
2173 opn = "dclz"; |
|
2174 break; |
|
2175 #endif |
|
2176 default: |
|
2177 MIPS_INVAL(opn); |
|
2178 generate_exception(ctx, EXCP_RI); |
|
2179 goto out; |
|
2180 } |
|
2181 gen_store_gpr(t0, rd); |
|
2182 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]); |
|
2183 |
|
2184 out: |
|
2185 tcg_temp_free(t0); |
|
2186 } |
|
2187 |
|
2188 /* Traps */ |
|
2189 static void gen_trap (DisasContext *ctx, uint32_t opc, |
|
2190 int rs, int rt, int16_t imm) |
|
2191 { |
|
2192 int cond; |
|
2193 TCGv t0 = tcg_temp_local_new(); |
|
2194 TCGv t1 = tcg_temp_local_new(); |
|
2195 |
|
2196 cond = 0; |
|
2197 /* Load needed operands */ |
|
2198 switch (opc) { |
|
2199 case OPC_TEQ: |
|
2200 case OPC_TGE: |
|
2201 case OPC_TGEU: |
|
2202 case OPC_TLT: |
|
2203 case OPC_TLTU: |
|
2204 case OPC_TNE: |
|
2205 /* Compare two registers */ |
|
2206 if (rs != rt) { |
|
2207 gen_load_gpr(t0, rs); |
|
2208 gen_load_gpr(t1, rt); |
|
2209 cond = 1; |
|
2210 } |
|
2211 break; |
|
2212 case OPC_TEQI: |
|
2213 case OPC_TGEI: |
|
2214 case OPC_TGEIU: |
|
2215 case OPC_TLTI: |
|
2216 case OPC_TLTIU: |
|
2217 case OPC_TNEI: |
|
2218 /* Compare register to immediate */ |
|
2219 if (rs != 0 || imm != 0) { |
|
2220 gen_load_gpr(t0, rs); |
|
2221 tcg_gen_movi_tl(t1, (int32_t)imm); |
|
2222 cond = 1; |
|
2223 } |
|
2224 break; |
|
2225 } |
|
2226 if (cond == 0) { |
|
2227 switch (opc) { |
|
2228 case OPC_TEQ: /* rs == rs */ |
|
2229 case OPC_TEQI: /* r0 == 0 */ |
|
2230 case OPC_TGE: /* rs >= rs */ |
|
2231 case OPC_TGEI: /* r0 >= 0 */ |
|
2232 case OPC_TGEU: /* rs >= rs unsigned */ |
|
2233 case OPC_TGEIU: /* r0 >= 0 unsigned */ |
|
2234 /* Always trap */ |
|
2235 tcg_gen_movi_tl(t0, 1); |
|
2236 break; |
|
2237 case OPC_TLT: /* rs < rs */ |
|
2238 case OPC_TLTI: /* r0 < 0 */ |
|
2239 case OPC_TLTU: /* rs < rs unsigned */ |
|
2240 case OPC_TLTIU: /* r0 < 0 unsigned */ |
|
2241 case OPC_TNE: /* rs != rs */ |
|
2242 case OPC_TNEI: /* r0 != 0 */ |
|
2243 /* Never trap: treat as NOP. */ |
|
2244 goto out; |
|
2245 default: |
|
2246 MIPS_INVAL("trap"); |
|
2247 generate_exception(ctx, EXCP_RI); |
|
2248 goto out; |
|
2249 } |
|
2250 } else { |
|
2251 switch (opc) { |
|
2252 case OPC_TEQ: |
|
2253 case OPC_TEQI: |
|
2254 gen_op_eq(t0, t1); |
|
2255 break; |
|
2256 case OPC_TGE: |
|
2257 case OPC_TGEI: |
|
2258 gen_op_ge(t0, t1); |
|
2259 break; |
|
2260 case OPC_TGEU: |
|
2261 case OPC_TGEIU: |
|
2262 gen_op_geu(t0, t1); |
|
2263 break; |
|
2264 case OPC_TLT: |
|
2265 case OPC_TLTI: |
|
2266 gen_op_lt(t0, t1); |
|
2267 break; |
|
2268 case OPC_TLTU: |
|
2269 case OPC_TLTIU: |
|
2270 gen_op_ltu(t0, t1); |
|
2271 break; |
|
2272 case OPC_TNE: |
|
2273 case OPC_TNEI: |
|
2274 gen_op_ne(t0, t1); |
|
2275 break; |
|
2276 default: |
|
2277 MIPS_INVAL("trap"); |
|
2278 generate_exception(ctx, EXCP_RI); |
|
2279 goto out; |
|
2280 } |
|
2281 } |
|
2282 save_cpu_state(ctx, 1); |
|
2283 { |
|
2284 int l1 = gen_new_label(); |
|
2285 |
|
2286 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); |
|
2287 gen_helper_0i(raise_exception, EXCP_TRAP); |
|
2288 gen_set_label(l1); |
|
2289 } |
|
2290 ctx->bstate = BS_STOP; |
|
2291 out: |
|
2292 tcg_temp_free(t0); |
|
2293 tcg_temp_free(t1); |
|
2294 } |
|
2295 |
|
2296 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) |
|
2297 { |
|
2298 TranslationBlock *tb; |
|
2299 tb = ctx->tb; |
|
2300 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { |
|
2301 tcg_gen_goto_tb(n); |
|
2302 gen_save_pc(dest); |
|
2303 tcg_gen_exit_tb((long)tb + n); |
|
2304 } else { |
|
2305 gen_save_pc(dest); |
|
2306 tcg_gen_exit_tb(0); |
|
2307 } |
|
2308 } |
|
2309 |
|
2310 /* Branches (before delay slot) */ |
|
2311 static void gen_compute_branch (DisasContext *ctx, uint32_t opc, |
|
2312 int rs, int rt, int32_t offset) |
|
2313 { |
|
2314 target_ulong btgt = -1; |
|
2315 int blink = 0; |
|
2316 int bcond_compute = 0; |
|
2317 TCGv t0 = tcg_temp_local_new(); |
|
2318 TCGv t1 = tcg_temp_local_new(); |
|
2319 |
|
2320 if (ctx->hflags & MIPS_HFLAG_BMASK) { |
|
2321 #ifdef MIPS_DEBUG_DISAS |
|
2322 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
2323 fprintf(logfile, |
|
2324 "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", |
|
2325 ctx->pc); |
|
2326 } |
|
2327 #endif |
|
2328 generate_exception(ctx, EXCP_RI); |
|
2329 goto out; |
|
2330 } |
|
2331 |
|
2332 /* Load needed operands */ |
|
2333 switch (opc) { |
|
2334 case OPC_BEQ: |
|
2335 case OPC_BEQL: |
|
2336 case OPC_BNE: |
|
2337 case OPC_BNEL: |
|
2338 /* Compare two registers */ |
|
2339 if (rs != rt) { |
|
2340 gen_load_gpr(t0, rs); |
|
2341 gen_load_gpr(t1, rt); |
|
2342 bcond_compute = 1; |
|
2343 } |
|
2344 btgt = ctx->pc + 4 + offset; |
|
2345 break; |
|
2346 case OPC_BGEZ: |
|
2347 case OPC_BGEZAL: |
|
2348 case OPC_BGEZALL: |
|
2349 case OPC_BGEZL: |
|
2350 case OPC_BGTZ: |
|
2351 case OPC_BGTZL: |
|
2352 case OPC_BLEZ: |
|
2353 case OPC_BLEZL: |
|
2354 case OPC_BLTZ: |
|
2355 case OPC_BLTZAL: |
|
2356 case OPC_BLTZALL: |
|
2357 case OPC_BLTZL: |
|
2358 /* Compare to zero */ |
|
2359 if (rs != 0) { |
|
2360 gen_load_gpr(t0, rs); |
|
2361 bcond_compute = 1; |
|
2362 } |
|
2363 btgt = ctx->pc + 4 + offset; |
|
2364 break; |
|
2365 case OPC_J: |
|
2366 case OPC_JAL: |
|
2367 /* Jump to immediate */ |
|
2368 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset; |
|
2369 break; |
|
2370 case OPC_JR: |
|
2371 case OPC_JALR: |
|
2372 /* Jump to register */ |
|
2373 if (offset != 0 && offset != 16) { |
|
2374 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the |
|
2375 others are reserved. */ |
|
2376 MIPS_INVAL("jump hint"); |
|
2377 generate_exception(ctx, EXCP_RI); |
|
2378 goto out; |
|
2379 } |
|
2380 gen_load_gpr(btarget, rs); |
|
2381 break; |
|
2382 default: |
|
2383 MIPS_INVAL("branch/jump"); |
|
2384 generate_exception(ctx, EXCP_RI); |
|
2385 goto out; |
|
2386 } |
|
2387 if (bcond_compute == 0) { |
|
2388 /* No condition to be computed */ |
|
2389 switch (opc) { |
|
2390 case OPC_BEQ: /* rx == rx */ |
|
2391 case OPC_BEQL: /* rx == rx likely */ |
|
2392 case OPC_BGEZ: /* 0 >= 0 */ |
|
2393 case OPC_BGEZL: /* 0 >= 0 likely */ |
|
2394 case OPC_BLEZ: /* 0 <= 0 */ |
|
2395 case OPC_BLEZL: /* 0 <= 0 likely */ |
|
2396 /* Always take */ |
|
2397 ctx->hflags |= MIPS_HFLAG_B; |
|
2398 MIPS_DEBUG("balways"); |
|
2399 break; |
|
2400 case OPC_BGEZAL: /* 0 >= 0 */ |
|
2401 case OPC_BGEZALL: /* 0 >= 0 likely */ |
|
2402 /* Always take and link */ |
|
2403 blink = 31; |
|
2404 ctx->hflags |= MIPS_HFLAG_B; |
|
2405 MIPS_DEBUG("balways and link"); |
|
2406 break; |
|
2407 case OPC_BNE: /* rx != rx */ |
|
2408 case OPC_BGTZ: /* 0 > 0 */ |
|
2409 case OPC_BLTZ: /* 0 < 0 */ |
|
2410 /* Treat as NOP. */ |
|
2411 MIPS_DEBUG("bnever (NOP)"); |
|
2412 goto out; |
|
2413 case OPC_BLTZAL: /* 0 < 0 */ |
|
2414 tcg_gen_movi_tl(t0, ctx->pc + 8); |
|
2415 gen_store_gpr(t0, 31); |
|
2416 MIPS_DEBUG("bnever and link"); |
|
2417 goto out; |
|
2418 case OPC_BLTZALL: /* 0 < 0 likely */ |
|
2419 tcg_gen_movi_tl(t0, ctx->pc + 8); |
|
2420 gen_store_gpr(t0, 31); |
|
2421 /* Skip the instruction in the delay slot */ |
|
2422 MIPS_DEBUG("bnever, link and skip"); |
|
2423 ctx->pc += 4; |
|
2424 goto out; |
|
2425 case OPC_BNEL: /* rx != rx likely */ |
|
2426 case OPC_BGTZL: /* 0 > 0 likely */ |
|
2427 case OPC_BLTZL: /* 0 < 0 likely */ |
|
2428 /* Skip the instruction in the delay slot */ |
|
2429 MIPS_DEBUG("bnever and skip"); |
|
2430 ctx->pc += 4; |
|
2431 goto out; |
|
2432 case OPC_J: |
|
2433 ctx->hflags |= MIPS_HFLAG_B; |
|
2434 MIPS_DEBUG("j " TARGET_FMT_lx, btgt); |
|
2435 break; |
|
2436 case OPC_JAL: |
|
2437 blink = 31; |
|
2438 ctx->hflags |= MIPS_HFLAG_B; |
|
2439 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt); |
|
2440 break; |
|
2441 case OPC_JR: |
|
2442 ctx->hflags |= MIPS_HFLAG_BR; |
|
2443 MIPS_DEBUG("jr %s", regnames[rs]); |
|
2444 break; |
|
2445 case OPC_JALR: |
|
2446 blink = rt; |
|
2447 ctx->hflags |= MIPS_HFLAG_BR; |
|
2448 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]); |
|
2449 break; |
|
2450 default: |
|
2451 MIPS_INVAL("branch/jump"); |
|
2452 generate_exception(ctx, EXCP_RI); |
|
2453 goto out; |
|
2454 } |
|
2455 } else { |
|
2456 switch (opc) { |
|
2457 case OPC_BEQ: |
|
2458 gen_op_eq(t0, t1); |
|
2459 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx, |
|
2460 regnames[rs], regnames[rt], btgt); |
|
2461 goto not_likely; |
|
2462 case OPC_BEQL: |
|
2463 gen_op_eq(t0, t1); |
|
2464 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx, |
|
2465 regnames[rs], regnames[rt], btgt); |
|
2466 goto likely; |
|
2467 case OPC_BNE: |
|
2468 gen_op_ne(t0, t1); |
|
2469 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx, |
|
2470 regnames[rs], regnames[rt], btgt); |
|
2471 goto not_likely; |
|
2472 case OPC_BNEL: |
|
2473 gen_op_ne(t0, t1); |
|
2474 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx, |
|
2475 regnames[rs], regnames[rt], btgt); |
|
2476 goto likely; |
|
2477 case OPC_BGEZ: |
|
2478 gen_op_gez(t0); |
|
2479 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2480 goto not_likely; |
|
2481 case OPC_BGEZL: |
|
2482 gen_op_gez(t0); |
|
2483 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2484 goto likely; |
|
2485 case OPC_BGEZAL: |
|
2486 gen_op_gez(t0); |
|
2487 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2488 blink = 31; |
|
2489 goto not_likely; |
|
2490 case OPC_BGEZALL: |
|
2491 gen_op_gez(t0); |
|
2492 blink = 31; |
|
2493 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2494 goto likely; |
|
2495 case OPC_BGTZ: |
|
2496 gen_op_gtz(t0); |
|
2497 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2498 goto not_likely; |
|
2499 case OPC_BGTZL: |
|
2500 gen_op_gtz(t0); |
|
2501 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2502 goto likely; |
|
2503 case OPC_BLEZ: |
|
2504 gen_op_lez(t0); |
|
2505 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2506 goto not_likely; |
|
2507 case OPC_BLEZL: |
|
2508 gen_op_lez(t0); |
|
2509 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2510 goto likely; |
|
2511 case OPC_BLTZ: |
|
2512 gen_op_ltz(t0); |
|
2513 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2514 goto not_likely; |
|
2515 case OPC_BLTZL: |
|
2516 gen_op_ltz(t0); |
|
2517 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2518 goto likely; |
|
2519 case OPC_BLTZAL: |
|
2520 gen_op_ltz(t0); |
|
2521 blink = 31; |
|
2522 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2523 not_likely: |
|
2524 ctx->hflags |= MIPS_HFLAG_BC; |
|
2525 tcg_gen_trunc_tl_i32(bcond, t0); |
|
2526 break; |
|
2527 case OPC_BLTZALL: |
|
2528 gen_op_ltz(t0); |
|
2529 blink = 31; |
|
2530 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt); |
|
2531 likely: |
|
2532 ctx->hflags |= MIPS_HFLAG_BL; |
|
2533 tcg_gen_trunc_tl_i32(bcond, t0); |
|
2534 break; |
|
2535 default: |
|
2536 MIPS_INVAL("conditional branch/jump"); |
|
2537 generate_exception(ctx, EXCP_RI); |
|
2538 goto out; |
|
2539 } |
|
2540 } |
|
2541 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx, |
|
2542 blink, ctx->hflags, btgt); |
|
2543 |
|
2544 ctx->btarget = btgt; |
|
2545 if (blink > 0) { |
|
2546 tcg_gen_movi_tl(t0, ctx->pc + 8); |
|
2547 gen_store_gpr(t0, blink); |
|
2548 } |
|
2549 |
|
2550 out: |
|
2551 tcg_temp_free(t0); |
|
2552 tcg_temp_free(t1); |
|
2553 } |
|
2554 |
|
2555 /* special3 bitfield operations */ |
|
2556 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, |
|
2557 int rs, int lsb, int msb) |
|
2558 { |
|
2559 TCGv t0 = tcg_temp_new(); |
|
2560 TCGv t1 = tcg_temp_new(); |
|
2561 target_ulong mask; |
|
2562 |
|
2563 gen_load_gpr(t1, rs); |
|
2564 switch (opc) { |
|
2565 case OPC_EXT: |
|
2566 if (lsb + msb > 31) |
|
2567 goto fail; |
|
2568 tcg_gen_shri_tl(t0, t1, lsb); |
|
2569 if (msb != 31) { |
|
2570 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1); |
|
2571 } else { |
|
2572 tcg_gen_ext32s_tl(t0, t0); |
|
2573 } |
|
2574 break; |
|
2575 #if defined(TARGET_MIPS64) |
|
2576 case OPC_DEXTM: |
|
2577 tcg_gen_shri_tl(t0, t1, lsb); |
|
2578 if (msb != 31) { |
|
2579 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1); |
|
2580 } |
|
2581 break; |
|
2582 case OPC_DEXTU: |
|
2583 tcg_gen_shri_tl(t0, t1, lsb + 32); |
|
2584 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1); |
|
2585 break; |
|
2586 case OPC_DEXT: |
|
2587 tcg_gen_shri_tl(t0, t1, lsb); |
|
2588 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1); |
|
2589 break; |
|
2590 #endif |
|
2591 case OPC_INS: |
|
2592 if (lsb > msb) |
|
2593 goto fail; |
|
2594 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb; |
|
2595 gen_load_gpr(t0, rt); |
|
2596 tcg_gen_andi_tl(t0, t0, ~mask); |
|
2597 tcg_gen_shli_tl(t1, t1, lsb); |
|
2598 tcg_gen_andi_tl(t1, t1, mask); |
|
2599 tcg_gen_or_tl(t0, t0, t1); |
|
2600 tcg_gen_ext32s_tl(t0, t0); |
|
2601 break; |
|
2602 #if defined(TARGET_MIPS64) |
|
2603 case OPC_DINSM: |
|
2604 if (lsb > msb) |
|
2605 goto fail; |
|
2606 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb; |
|
2607 gen_load_gpr(t0, rt); |
|
2608 tcg_gen_andi_tl(t0, t0, ~mask); |
|
2609 tcg_gen_shli_tl(t1, t1, lsb); |
|
2610 tcg_gen_andi_tl(t1, t1, mask); |
|
2611 tcg_gen_or_tl(t0, t0, t1); |
|
2612 break; |
|
2613 case OPC_DINSU: |
|
2614 if (lsb > msb) |
|
2615 goto fail; |
|
2616 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb; |
|
2617 gen_load_gpr(t0, rt); |
|
2618 tcg_gen_andi_tl(t0, t0, ~mask); |
|
2619 tcg_gen_shli_tl(t1, t1, lsb + 32); |
|
2620 tcg_gen_andi_tl(t1, t1, mask); |
|
2621 tcg_gen_or_tl(t0, t0, t1); |
|
2622 break; |
|
2623 case OPC_DINS: |
|
2624 if (lsb > msb) |
|
2625 goto fail; |
|
2626 gen_load_gpr(t0, rt); |
|
2627 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb; |
|
2628 gen_load_gpr(t0, rt); |
|
2629 tcg_gen_andi_tl(t0, t0, ~mask); |
|
2630 tcg_gen_shli_tl(t1, t1, lsb); |
|
2631 tcg_gen_andi_tl(t1, t1, mask); |
|
2632 tcg_gen_or_tl(t0, t0, t1); |
|
2633 break; |
|
2634 #endif |
|
2635 default: |
|
2636 fail: |
|
2637 MIPS_INVAL("bitops"); |
|
2638 generate_exception(ctx, EXCP_RI); |
|
2639 tcg_temp_free(t0); |
|
2640 tcg_temp_free(t1); |
|
2641 return; |
|
2642 } |
|
2643 gen_store_gpr(t0, rt); |
|
2644 tcg_temp_free(t0); |
|
2645 tcg_temp_free(t1); |
|
2646 } |
|
2647 |
|
2648 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd) |
|
2649 { |
|
2650 TCGv t0 = tcg_temp_new(); |
|
2651 TCGv t1 = tcg_temp_new(); |
|
2652 |
|
2653 gen_load_gpr(t1, rt); |
|
2654 switch (op2) { |
|
2655 case OPC_WSBH: |
|
2656 tcg_gen_shri_tl(t0, t1, 8); |
|
2657 tcg_gen_andi_tl(t0, t0, 0x00FF00FF); |
|
2658 tcg_gen_shli_tl(t1, t1, 8); |
|
2659 tcg_gen_andi_tl(t1, t1, ~0x00FF00FF); |
|
2660 tcg_gen_or_tl(t0, t0, t1); |
|
2661 tcg_gen_ext32s_tl(t0, t0); |
|
2662 break; |
|
2663 case OPC_SEB: |
|
2664 tcg_gen_ext8s_tl(t0, t1); |
|
2665 break; |
|
2666 case OPC_SEH: |
|
2667 tcg_gen_ext16s_tl(t0, t1); |
|
2668 break; |
|
2669 #if defined(TARGET_MIPS64) |
|
2670 case OPC_DSBH: |
|
2671 gen_load_gpr(t1, rt); |
|
2672 tcg_gen_shri_tl(t0, t1, 8); |
|
2673 tcg_gen_andi_tl(t0, t0, 0x00FF00FF00FF00FFULL); |
|
2674 tcg_gen_shli_tl(t1, t1, 8); |
|
2675 tcg_gen_andi_tl(t1, t1, ~0x00FF00FF00FF00FFULL); |
|
2676 tcg_gen_or_tl(t0, t0, t1); |
|
2677 break; |
|
2678 case OPC_DSHD: |
|
2679 gen_load_gpr(t1, rt); |
|
2680 tcg_gen_shri_tl(t0, t1, 16); |
|
2681 tcg_gen_andi_tl(t0, t0, 0x0000FFFF0000FFFFULL); |
|
2682 tcg_gen_shli_tl(t1, t1, 16); |
|
2683 tcg_gen_andi_tl(t1, t1, ~0x0000FFFF0000FFFFULL); |
|
2684 tcg_gen_or_tl(t1, t0, t1); |
|
2685 tcg_gen_shri_tl(t0, t1, 32); |
|
2686 tcg_gen_shli_tl(t1, t1, 32); |
|
2687 tcg_gen_or_tl(t0, t0, t1); |
|
2688 break; |
|
2689 #endif |
|
2690 default: |
|
2691 MIPS_INVAL("bsfhl"); |
|
2692 generate_exception(ctx, EXCP_RI); |
|
2693 tcg_temp_free(t0); |
|
2694 tcg_temp_free(t1); |
|
2695 return; |
|
2696 } |
|
2697 gen_store_gpr(t0, rd); |
|
2698 tcg_temp_free(t0); |
|
2699 tcg_temp_free(t1); |
|
2700 } |
|
2701 |
|
2702 #ifndef CONFIG_USER_ONLY |
|
2703 /* CP0 (MMU and control) */ |
|
2704 static inline void gen_mfc0_load32 (TCGv t, target_ulong off) |
|
2705 { |
|
2706 TCGv_i32 r_tmp = tcg_temp_new_i32(); |
|
2707 |
|
2708 tcg_gen_ld_i32(r_tmp, cpu_env, off); |
|
2709 tcg_gen_ext_i32_tl(t, r_tmp); |
|
2710 tcg_temp_free_i32(r_tmp); |
|
2711 } |
|
2712 |
|
2713 static inline void gen_mfc0_load64 (TCGv t, target_ulong off) |
|
2714 { |
|
2715 tcg_gen_ld_tl(t, cpu_env, off); |
|
2716 tcg_gen_ext32s_tl(t, t); |
|
2717 } |
|
2718 |
|
2719 static inline void gen_mtc0_store32 (TCGv t, target_ulong off) |
|
2720 { |
|
2721 TCGv_i32 r_tmp = tcg_temp_new_i32(); |
|
2722 |
|
2723 tcg_gen_trunc_tl_i32(r_tmp, t); |
|
2724 tcg_gen_st_i32(r_tmp, cpu_env, off); |
|
2725 tcg_temp_free_i32(r_tmp); |
|
2726 } |
|
2727 |
|
2728 static inline void gen_mtc0_store64 (TCGv t, target_ulong off) |
|
2729 { |
|
2730 tcg_gen_ext32s_tl(t, t); |
|
2731 tcg_gen_st_tl(t, cpu_env, off); |
|
2732 } |
|
2733 |
|
2734 static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel) |
|
2735 { |
|
2736 const char *rn = "invalid"; |
|
2737 |
|
2738 if (sel != 0) |
|
2739 check_insn(env, ctx, ISA_MIPS32); |
|
2740 |
|
2741 switch (reg) { |
|
2742 case 0: |
|
2743 switch (sel) { |
|
2744 case 0: |
|
2745 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index)); |
|
2746 rn = "Index"; |
|
2747 break; |
|
2748 case 1: |
|
2749 check_insn(env, ctx, ASE_MT); |
|
2750 gen_helper_mfc0_mvpcontrol(t0); |
|
2751 rn = "MVPControl"; |
|
2752 break; |
|
2753 case 2: |
|
2754 check_insn(env, ctx, ASE_MT); |
|
2755 gen_helper_mfc0_mvpconf0(t0); |
|
2756 rn = "MVPConf0"; |
|
2757 break; |
|
2758 case 3: |
|
2759 check_insn(env, ctx, ASE_MT); |
|
2760 gen_helper_mfc0_mvpconf1(t0); |
|
2761 rn = "MVPConf1"; |
|
2762 break; |
|
2763 default: |
|
2764 goto die; |
|
2765 } |
|
2766 break; |
|
2767 case 1: |
|
2768 switch (sel) { |
|
2769 case 0: |
|
2770 gen_helper_mfc0_random(t0); |
|
2771 rn = "Random"; |
|
2772 break; |
|
2773 case 1: |
|
2774 check_insn(env, ctx, ASE_MT); |
|
2775 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl)); |
|
2776 rn = "VPEControl"; |
|
2777 break; |
|
2778 case 2: |
|
2779 check_insn(env, ctx, ASE_MT); |
|
2780 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0)); |
|
2781 rn = "VPEConf0"; |
|
2782 break; |
|
2783 case 3: |
|
2784 check_insn(env, ctx, ASE_MT); |
|
2785 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1)); |
|
2786 rn = "VPEConf1"; |
|
2787 break; |
|
2788 case 4: |
|
2789 check_insn(env, ctx, ASE_MT); |
|
2790 gen_mfc0_load64(t0, offsetof(CPUState, CP0_YQMask)); |
|
2791 rn = "YQMask"; |
|
2792 break; |
|
2793 case 5: |
|
2794 check_insn(env, ctx, ASE_MT); |
|
2795 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPESchedule)); |
|
2796 rn = "VPESchedule"; |
|
2797 break; |
|
2798 case 6: |
|
2799 check_insn(env, ctx, ASE_MT); |
|
2800 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPEScheFBack)); |
|
2801 rn = "VPEScheFBack"; |
|
2802 break; |
|
2803 case 7: |
|
2804 check_insn(env, ctx, ASE_MT); |
|
2805 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt)); |
|
2806 rn = "VPEOpt"; |
|
2807 break; |
|
2808 default: |
|
2809 goto die; |
|
2810 } |
|
2811 break; |
|
2812 case 2: |
|
2813 switch (sel) { |
|
2814 case 0: |
|
2815 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0)); |
|
2816 tcg_gen_ext32s_tl(t0, t0); |
|
2817 rn = "EntryLo0"; |
|
2818 break; |
|
2819 case 1: |
|
2820 check_insn(env, ctx, ASE_MT); |
|
2821 gen_helper_mfc0_tcstatus(t0); |
|
2822 rn = "TCStatus"; |
|
2823 break; |
|
2824 case 2: |
|
2825 check_insn(env, ctx, ASE_MT); |
|
2826 gen_helper_mfc0_tcbind(t0); |
|
2827 rn = "TCBind"; |
|
2828 break; |
|
2829 case 3: |
|
2830 check_insn(env, ctx, ASE_MT); |
|
2831 gen_helper_mfc0_tcrestart(t0); |
|
2832 rn = "TCRestart"; |
|
2833 break; |
|
2834 case 4: |
|
2835 check_insn(env, ctx, ASE_MT); |
|
2836 gen_helper_mfc0_tchalt(t0); |
|
2837 rn = "TCHalt"; |
|
2838 break; |
|
2839 case 5: |
|
2840 check_insn(env, ctx, ASE_MT); |
|
2841 gen_helper_mfc0_tccontext(t0); |
|
2842 rn = "TCContext"; |
|
2843 break; |
|
2844 case 6: |
|
2845 check_insn(env, ctx, ASE_MT); |
|
2846 gen_helper_mfc0_tcschedule(t0); |
|
2847 rn = "TCSchedule"; |
|
2848 break; |
|
2849 case 7: |
|
2850 check_insn(env, ctx, ASE_MT); |
|
2851 gen_helper_mfc0_tcschefback(t0); |
|
2852 rn = "TCScheFBack"; |
|
2853 break; |
|
2854 default: |
|
2855 goto die; |
|
2856 } |
|
2857 break; |
|
2858 case 3: |
|
2859 switch (sel) { |
|
2860 case 0: |
|
2861 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1)); |
|
2862 tcg_gen_ext32s_tl(t0, t0); |
|
2863 rn = "EntryLo1"; |
|
2864 break; |
|
2865 default: |
|
2866 goto die; |
|
2867 } |
|
2868 break; |
|
2869 case 4: |
|
2870 switch (sel) { |
|
2871 case 0: |
|
2872 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context)); |
|
2873 tcg_gen_ext32s_tl(t0, t0); |
|
2874 rn = "Context"; |
|
2875 break; |
|
2876 case 1: |
|
2877 // gen_helper_mfc0_contextconfig(t0); /* SmartMIPS ASE */ |
|
2878 rn = "ContextConfig"; |
|
2879 // break; |
|
2880 default: |
|
2881 goto die; |
|
2882 } |
|
2883 break; |
|
2884 case 5: |
|
2885 switch (sel) { |
|
2886 case 0: |
|
2887 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask)); |
|
2888 rn = "PageMask"; |
|
2889 break; |
|
2890 case 1: |
|
2891 check_insn(env, ctx, ISA_MIPS32R2); |
|
2892 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain)); |
|
2893 rn = "PageGrain"; |
|
2894 break; |
|
2895 default: |
|
2896 goto die; |
|
2897 } |
|
2898 break; |
|
2899 case 6: |
|
2900 switch (sel) { |
|
2901 case 0: |
|
2902 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired)); |
|
2903 rn = "Wired"; |
|
2904 break; |
|
2905 case 1: |
|
2906 check_insn(env, ctx, ISA_MIPS32R2); |
|
2907 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0)); |
|
2908 rn = "SRSConf0"; |
|
2909 break; |
|
2910 case 2: |
|
2911 check_insn(env, ctx, ISA_MIPS32R2); |
|
2912 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1)); |
|
2913 rn = "SRSConf1"; |
|
2914 break; |
|
2915 case 3: |
|
2916 check_insn(env, ctx, ISA_MIPS32R2); |
|
2917 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2)); |
|
2918 rn = "SRSConf2"; |
|
2919 break; |
|
2920 case 4: |
|
2921 check_insn(env, ctx, ISA_MIPS32R2); |
|
2922 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3)); |
|
2923 rn = "SRSConf3"; |
|
2924 break; |
|
2925 case 5: |
|
2926 check_insn(env, ctx, ISA_MIPS32R2); |
|
2927 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4)); |
|
2928 rn = "SRSConf4"; |
|
2929 break; |
|
2930 default: |
|
2931 goto die; |
|
2932 } |
|
2933 break; |
|
2934 case 7: |
|
2935 switch (sel) { |
|
2936 case 0: |
|
2937 check_insn(env, ctx, ISA_MIPS32R2); |
|
2938 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna)); |
|
2939 rn = "HWREna"; |
|
2940 break; |
|
2941 default: |
|
2942 goto die; |
|
2943 } |
|
2944 break; |
|
2945 case 8: |
|
2946 switch (sel) { |
|
2947 case 0: |
|
2948 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr)); |
|
2949 tcg_gen_ext32s_tl(t0, t0); |
|
2950 rn = "BadVAddr"; |
|
2951 break; |
|
2952 default: |
|
2953 goto die; |
|
2954 } |
|
2955 break; |
|
2956 case 9: |
|
2957 switch (sel) { |
|
2958 case 0: |
|
2959 /* Mark as an IO operation because we read the time. */ |
|
2960 if (use_icount) |
|
2961 gen_io_start(); |
|
2962 gen_helper_mfc0_count(t0); |
|
2963 if (use_icount) { |
|
2964 gen_io_end(); |
|
2965 ctx->bstate = BS_STOP; |
|
2966 } |
|
2967 rn = "Count"; |
|
2968 break; |
|
2969 /* 6,7 are implementation dependent */ |
|
2970 default: |
|
2971 goto die; |
|
2972 } |
|
2973 break; |
|
2974 case 10: |
|
2975 switch (sel) { |
|
2976 case 0: |
|
2977 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi)); |
|
2978 tcg_gen_ext32s_tl(t0, t0); |
|
2979 rn = "EntryHi"; |
|
2980 break; |
|
2981 default: |
|
2982 goto die; |
|
2983 } |
|
2984 break; |
|
2985 case 11: |
|
2986 switch (sel) { |
|
2987 case 0: |
|
2988 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare)); |
|
2989 rn = "Compare"; |
|
2990 break; |
|
2991 /* 6,7 are implementation dependent */ |
|
2992 default: |
|
2993 goto die; |
|
2994 } |
|
2995 break; |
|
2996 case 12: |
|
2997 switch (sel) { |
|
2998 case 0: |
|
2999 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status)); |
|
3000 rn = "Status"; |
|
3001 break; |
|
3002 case 1: |
|
3003 check_insn(env, ctx, ISA_MIPS32R2); |
|
3004 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl)); |
|
3005 rn = "IntCtl"; |
|
3006 break; |
|
3007 case 2: |
|
3008 check_insn(env, ctx, ISA_MIPS32R2); |
|
3009 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl)); |
|
3010 rn = "SRSCtl"; |
|
3011 break; |
|
3012 case 3: |
|
3013 check_insn(env, ctx, ISA_MIPS32R2); |
|
3014 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap)); |
|
3015 rn = "SRSMap"; |
|
3016 break; |
|
3017 default: |
|
3018 goto die; |
|
3019 } |
|
3020 break; |
|
3021 case 13: |
|
3022 switch (sel) { |
|
3023 case 0: |
|
3024 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause)); |
|
3025 rn = "Cause"; |
|
3026 break; |
|
3027 default: |
|
3028 goto die; |
|
3029 } |
|
3030 break; |
|
3031 case 14: |
|
3032 switch (sel) { |
|
3033 case 0: |
|
3034 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC)); |
|
3035 tcg_gen_ext32s_tl(t0, t0); |
|
3036 rn = "EPC"; |
|
3037 break; |
|
3038 default: |
|
3039 goto die; |
|
3040 } |
|
3041 break; |
|
3042 case 15: |
|
3043 switch (sel) { |
|
3044 case 0: |
|
3045 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid)); |
|
3046 rn = "PRid"; |
|
3047 break; |
|
3048 case 1: |
|
3049 check_insn(env, ctx, ISA_MIPS32R2); |
|
3050 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase)); |
|
3051 rn = "EBase"; |
|
3052 break; |
|
3053 default: |
|
3054 goto die; |
|
3055 } |
|
3056 break; |
|
3057 case 16: |
|
3058 switch (sel) { |
|
3059 case 0: |
|
3060 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0)); |
|
3061 rn = "Config"; |
|
3062 break; |
|
3063 case 1: |
|
3064 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1)); |
|
3065 rn = "Config1"; |
|
3066 break; |
|
3067 case 2: |
|
3068 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2)); |
|
3069 rn = "Config2"; |
|
3070 break; |
|
3071 case 3: |
|
3072 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3)); |
|
3073 rn = "Config3"; |
|
3074 break; |
|
3075 /* 4,5 are reserved */ |
|
3076 /* 6,7 are implementation dependent */ |
|
3077 case 6: |
|
3078 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6)); |
|
3079 rn = "Config6"; |
|
3080 break; |
|
3081 case 7: |
|
3082 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7)); |
|
3083 rn = "Config7"; |
|
3084 break; |
|
3085 default: |
|
3086 goto die; |
|
3087 } |
|
3088 break; |
|
3089 case 17: |
|
3090 switch (sel) { |
|
3091 case 0: |
|
3092 gen_helper_mfc0_lladdr(t0); |
|
3093 rn = "LLAddr"; |
|
3094 break; |
|
3095 default: |
|
3096 goto die; |
|
3097 } |
|
3098 break; |
|
3099 case 18: |
|
3100 switch (sel) { |
|
3101 case 0 ... 7: |
|
3102 gen_helper_1i(mfc0_watchlo, t0, sel); |
|
3103 rn = "WatchLo"; |
|
3104 break; |
|
3105 default: |
|
3106 goto die; |
|
3107 } |
|
3108 break; |
|
3109 case 19: |
|
3110 switch (sel) { |
|
3111 case 0 ...7: |
|
3112 gen_helper_1i(mfc0_watchhi, t0, sel); |
|
3113 rn = "WatchHi"; |
|
3114 break; |
|
3115 default: |
|
3116 goto die; |
|
3117 } |
|
3118 break; |
|
3119 case 20: |
|
3120 switch (sel) { |
|
3121 case 0: |
|
3122 #if defined(TARGET_MIPS64) |
|
3123 check_insn(env, ctx, ISA_MIPS3); |
|
3124 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext)); |
|
3125 tcg_gen_ext32s_tl(t0, t0); |
|
3126 rn = "XContext"; |
|
3127 break; |
|
3128 #endif |
|
3129 default: |
|
3130 goto die; |
|
3131 } |
|
3132 break; |
|
3133 case 21: |
|
3134 /* Officially reserved, but sel 0 is used for R1x000 framemask */ |
|
3135 switch (sel) { |
|
3136 case 0: |
|
3137 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask)); |
|
3138 rn = "Framemask"; |
|
3139 break; |
|
3140 default: |
|
3141 goto die; |
|
3142 } |
|
3143 break; |
|
3144 case 22: |
|
3145 tcg_gen_movi_tl(t0, 0); /* unimplemented */ |
|
3146 rn = "'Diagnostic"; /* implementation dependent */ |
|
3147 break; |
|
3148 case 23: |
|
3149 switch (sel) { |
|
3150 case 0: |
|
3151 gen_helper_mfc0_debug(t0); /* EJTAG support */ |
|
3152 rn = "Debug"; |
|
3153 break; |
|
3154 case 1: |
|
3155 // gen_helper_mfc0_tracecontrol(t0); /* PDtrace support */ |
|
3156 rn = "TraceControl"; |
|
3157 // break; |
|
3158 case 2: |
|
3159 // gen_helper_mfc0_tracecontrol2(t0); /* PDtrace support */ |
|
3160 rn = "TraceControl2"; |
|
3161 // break; |
|
3162 case 3: |
|
3163 // gen_helper_mfc0_usertracedata(t0); /* PDtrace support */ |
|
3164 rn = "UserTraceData"; |
|
3165 // break; |
|
3166 case 4: |
|
3167 // gen_helper_mfc0_tracebpc(t0); /* PDtrace support */ |
|
3168 rn = "TraceBPC"; |
|
3169 // break; |
|
3170 default: |
|
3171 goto die; |
|
3172 } |
|
3173 break; |
|
3174 case 24: |
|
3175 switch (sel) { |
|
3176 case 0: |
|
3177 /* EJTAG support */ |
|
3178 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC)); |
|
3179 tcg_gen_ext32s_tl(t0, t0); |
|
3180 rn = "DEPC"; |
|
3181 break; |
|
3182 default: |
|
3183 goto die; |
|
3184 } |
|
3185 break; |
|
3186 case 25: |
|
3187 switch (sel) { |
|
3188 case 0: |
|
3189 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0)); |
|
3190 rn = "Performance0"; |
|
3191 break; |
|
3192 case 1: |
|
3193 // gen_helper_mfc0_performance1(t0); |
|
3194 rn = "Performance1"; |
|
3195 // break; |
|
3196 case 2: |
|
3197 // gen_helper_mfc0_performance2(t0); |
|
3198 rn = "Performance2"; |
|
3199 // break; |
|
3200 case 3: |
|
3201 // gen_helper_mfc0_performance3(t0); |
|
3202 rn = "Performance3"; |
|
3203 // break; |
|
3204 case 4: |
|
3205 // gen_helper_mfc0_performance4(t0); |
|
3206 rn = "Performance4"; |
|
3207 // break; |
|
3208 case 5: |
|
3209 // gen_helper_mfc0_performance5(t0); |
|
3210 rn = "Performance5"; |
|
3211 // break; |
|
3212 case 6: |
|
3213 // gen_helper_mfc0_performance6(t0); |
|
3214 rn = "Performance6"; |
|
3215 // break; |
|
3216 case 7: |
|
3217 // gen_helper_mfc0_performance7(t0); |
|
3218 rn = "Performance7"; |
|
3219 // break; |
|
3220 default: |
|
3221 goto die; |
|
3222 } |
|
3223 break; |
|
3224 case 26: |
|
3225 tcg_gen_movi_tl(t0, 0); /* unimplemented */ |
|
3226 rn = "ECC"; |
|
3227 break; |
|
3228 case 27: |
|
3229 switch (sel) { |
|
3230 case 0 ... 3: |
|
3231 tcg_gen_movi_tl(t0, 0); /* unimplemented */ |
|
3232 rn = "CacheErr"; |
|
3233 break; |
|
3234 default: |
|
3235 goto die; |
|
3236 } |
|
3237 break; |
|
3238 case 28: |
|
3239 switch (sel) { |
|
3240 case 0: |
|
3241 case 2: |
|
3242 case 4: |
|
3243 case 6: |
|
3244 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo)); |
|
3245 rn = "TagLo"; |
|
3246 break; |
|
3247 case 1: |
|
3248 case 3: |
|
3249 case 5: |
|
3250 case 7: |
|
3251 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo)); |
|
3252 rn = "DataLo"; |
|
3253 break; |
|
3254 default: |
|
3255 goto die; |
|
3256 } |
|
3257 break; |
|
3258 case 29: |
|
3259 switch (sel) { |
|
3260 case 0: |
|
3261 case 2: |
|
3262 case 4: |
|
3263 case 6: |
|
3264 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi)); |
|
3265 rn = "TagHi"; |
|
3266 break; |
|
3267 case 1: |
|
3268 case 3: |
|
3269 case 5: |
|
3270 case 7: |
|
3271 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi)); |
|
3272 rn = "DataHi"; |
|
3273 break; |
|
3274 default: |
|
3275 goto die; |
|
3276 } |
|
3277 break; |
|
3278 case 30: |
|
3279 switch (sel) { |
|
3280 case 0: |
|
3281 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC)); |
|
3282 tcg_gen_ext32s_tl(t0, t0); |
|
3283 rn = "ErrorEPC"; |
|
3284 break; |
|
3285 default: |
|
3286 goto die; |
|
3287 } |
|
3288 break; |
|
3289 case 31: |
|
3290 switch (sel) { |
|
3291 case 0: |
|
3292 /* EJTAG support */ |
|
3293 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE)); |
|
3294 rn = "DESAVE"; |
|
3295 break; |
|
3296 default: |
|
3297 goto die; |
|
3298 } |
|
3299 break; |
|
3300 default: |
|
3301 goto die; |
|
3302 } |
|
3303 #if defined MIPS_DEBUG_DISAS |
|
3304 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
3305 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n", |
|
3306 rn, reg, sel); |
|
3307 } |
|
3308 #endif |
|
3309 return; |
|
3310 |
|
3311 die: |
|
3312 #if defined MIPS_DEBUG_DISAS |
|
3313 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
3314 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n", |
|
3315 rn, reg, sel); |
|
3316 } |
|
3317 #endif |
|
3318 generate_exception(ctx, EXCP_RI); |
|
3319 } |
|
3320 |
|
3321 static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel) |
|
3322 { |
|
3323 const char *rn = "invalid"; |
|
3324 |
|
3325 if (sel != 0) |
|
3326 check_insn(env, ctx, ISA_MIPS32); |
|
3327 |
|
3328 if (use_icount) |
|
3329 gen_io_start(); |
|
3330 |
|
3331 switch (reg) { |
|
3332 case 0: |
|
3333 switch (sel) { |
|
3334 case 0: |
|
3335 gen_helper_mtc0_index(t0); |
|
3336 rn = "Index"; |
|
3337 break; |
|
3338 case 1: |
|
3339 check_insn(env, ctx, ASE_MT); |
|
3340 gen_helper_mtc0_mvpcontrol(t0); |
|
3341 rn = "MVPControl"; |
|
3342 break; |
|
3343 case 2: |
|
3344 check_insn(env, ctx, ASE_MT); |
|
3345 /* ignored */ |
|
3346 rn = "MVPConf0"; |
|
3347 break; |
|
3348 case 3: |
|
3349 check_insn(env, ctx, ASE_MT); |
|
3350 /* ignored */ |
|
3351 rn = "MVPConf1"; |
|
3352 break; |
|
3353 default: |
|
3354 goto die; |
|
3355 } |
|
3356 break; |
|
3357 case 1: |
|
3358 switch (sel) { |
|
3359 case 0: |
|
3360 /* ignored */ |
|
3361 rn = "Random"; |
|
3362 break; |
|
3363 case 1: |
|
3364 check_insn(env, ctx, ASE_MT); |
|
3365 gen_helper_mtc0_vpecontrol(t0); |
|
3366 rn = "VPEControl"; |
|
3367 break; |
|
3368 case 2: |
|
3369 check_insn(env, ctx, ASE_MT); |
|
3370 gen_helper_mtc0_vpeconf0(t0); |
|
3371 rn = "VPEConf0"; |
|
3372 break; |
|
3373 case 3: |
|
3374 check_insn(env, ctx, ASE_MT); |
|
3375 gen_helper_mtc0_vpeconf1(t0); |
|
3376 rn = "VPEConf1"; |
|
3377 break; |
|
3378 case 4: |
|
3379 check_insn(env, ctx, ASE_MT); |
|
3380 gen_helper_mtc0_yqmask(t0); |
|
3381 rn = "YQMask"; |
|
3382 break; |
|
3383 case 5: |
|
3384 check_insn(env, ctx, ASE_MT); |
|
3385 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule)); |
|
3386 rn = "VPESchedule"; |
|
3387 break; |
|
3388 case 6: |
|
3389 check_insn(env, ctx, ASE_MT); |
|
3390 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack)); |
|
3391 rn = "VPEScheFBack"; |
|
3392 break; |
|
3393 case 7: |
|
3394 check_insn(env, ctx, ASE_MT); |
|
3395 gen_helper_mtc0_vpeopt(t0); |
|
3396 rn = "VPEOpt"; |
|
3397 break; |
|
3398 default: |
|
3399 goto die; |
|
3400 } |
|
3401 break; |
|
3402 case 2: |
|
3403 switch (sel) { |
|
3404 case 0: |
|
3405 gen_helper_mtc0_entrylo0(t0); |
|
3406 rn = "EntryLo0"; |
|
3407 break; |
|
3408 case 1: |
|
3409 check_insn(env, ctx, ASE_MT); |
|
3410 gen_helper_mtc0_tcstatus(t0); |
|
3411 rn = "TCStatus"; |
|
3412 break; |
|
3413 case 2: |
|
3414 check_insn(env, ctx, ASE_MT); |
|
3415 gen_helper_mtc0_tcbind(t0); |
|
3416 rn = "TCBind"; |
|
3417 break; |
|
3418 case 3: |
|
3419 check_insn(env, ctx, ASE_MT); |
|
3420 gen_helper_mtc0_tcrestart(t0); |
|
3421 rn = "TCRestart"; |
|
3422 break; |
|
3423 case 4: |
|
3424 check_insn(env, ctx, ASE_MT); |
|
3425 gen_helper_mtc0_tchalt(t0); |
|
3426 rn = "TCHalt"; |
|
3427 break; |
|
3428 case 5: |
|
3429 check_insn(env, ctx, ASE_MT); |
|
3430 gen_helper_mtc0_tccontext(t0); |
|
3431 rn = "TCContext"; |
|
3432 break; |
|
3433 case 6: |
|
3434 check_insn(env, ctx, ASE_MT); |
|
3435 gen_helper_mtc0_tcschedule(t0); |
|
3436 rn = "TCSchedule"; |
|
3437 break; |
|
3438 case 7: |
|
3439 check_insn(env, ctx, ASE_MT); |
|
3440 gen_helper_mtc0_tcschefback(t0); |
|
3441 rn = "TCScheFBack"; |
|
3442 break; |
|
3443 default: |
|
3444 goto die; |
|
3445 } |
|
3446 break; |
|
3447 case 3: |
|
3448 switch (sel) { |
|
3449 case 0: |
|
3450 gen_helper_mtc0_entrylo1(t0); |
|
3451 rn = "EntryLo1"; |
|
3452 break; |
|
3453 default: |
|
3454 goto die; |
|
3455 } |
|
3456 break; |
|
3457 case 4: |
|
3458 switch (sel) { |
|
3459 case 0: |
|
3460 gen_helper_mtc0_context(t0); |
|
3461 rn = "Context"; |
|
3462 break; |
|
3463 case 1: |
|
3464 // gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */ |
|
3465 rn = "ContextConfig"; |
|
3466 // break; |
|
3467 default: |
|
3468 goto die; |
|
3469 } |
|
3470 break; |
|
3471 case 5: |
|
3472 switch (sel) { |
|
3473 case 0: |
|
3474 gen_helper_mtc0_pagemask(t0); |
|
3475 rn = "PageMask"; |
|
3476 break; |
|
3477 case 1: |
|
3478 check_insn(env, ctx, ISA_MIPS32R2); |
|
3479 gen_helper_mtc0_pagegrain(t0); |
|
3480 rn = "PageGrain"; |
|
3481 break; |
|
3482 default: |
|
3483 goto die; |
|
3484 } |
|
3485 break; |
|
3486 case 6: |
|
3487 switch (sel) { |
|
3488 case 0: |
|
3489 gen_helper_mtc0_wired(t0); |
|
3490 rn = "Wired"; |
|
3491 break; |
|
3492 case 1: |
|
3493 check_insn(env, ctx, ISA_MIPS32R2); |
|
3494 gen_helper_mtc0_srsconf0(t0); |
|
3495 rn = "SRSConf0"; |
|
3496 break; |
|
3497 case 2: |
|
3498 check_insn(env, ctx, ISA_MIPS32R2); |
|
3499 gen_helper_mtc0_srsconf1(t0); |
|
3500 rn = "SRSConf1"; |
|
3501 break; |
|
3502 case 3: |
|
3503 check_insn(env, ctx, ISA_MIPS32R2); |
|
3504 gen_helper_mtc0_srsconf2(t0); |
|
3505 rn = "SRSConf2"; |
|
3506 break; |
|
3507 case 4: |
|
3508 check_insn(env, ctx, ISA_MIPS32R2); |
|
3509 gen_helper_mtc0_srsconf3(t0); |
|
3510 rn = "SRSConf3"; |
|
3511 break; |
|
3512 case 5: |
|
3513 check_insn(env, ctx, ISA_MIPS32R2); |
|
3514 gen_helper_mtc0_srsconf4(t0); |
|
3515 rn = "SRSConf4"; |
|
3516 break; |
|
3517 default: |
|
3518 goto die; |
|
3519 } |
|
3520 break; |
|
3521 case 7: |
|
3522 switch (sel) { |
|
3523 case 0: |
|
3524 check_insn(env, ctx, ISA_MIPS32R2); |
|
3525 gen_helper_mtc0_hwrena(t0); |
|
3526 rn = "HWREna"; |
|
3527 break; |
|
3528 default: |
|
3529 goto die; |
|
3530 } |
|
3531 break; |
|
3532 case 8: |
|
3533 /* ignored */ |
|
3534 rn = "BadVAddr"; |
|
3535 break; |
|
3536 case 9: |
|
3537 switch (sel) { |
|
3538 case 0: |
|
3539 gen_helper_mtc0_count(t0); |
|
3540 rn = "Count"; |
|
3541 break; |
|
3542 /* 6,7 are implementation dependent */ |
|
3543 default: |
|
3544 goto die; |
|
3545 } |
|
3546 /* Stop translation as we may have switched the execution mode */ |
|
3547 ctx->bstate = BS_STOP; |
|
3548 break; |
|
3549 case 10: |
|
3550 switch (sel) { |
|
3551 case 0: |
|
3552 gen_helper_mtc0_entryhi(t0); |
|
3553 rn = "EntryHi"; |
|
3554 break; |
|
3555 default: |
|
3556 goto die; |
|
3557 } |
|
3558 break; |
|
3559 case 11: |
|
3560 switch (sel) { |
|
3561 case 0: |
|
3562 gen_helper_mtc0_compare(t0); |
|
3563 rn = "Compare"; |
|
3564 break; |
|
3565 /* 6,7 are implementation dependent */ |
|
3566 default: |
|
3567 goto die; |
|
3568 } |
|
3569 /* Stop translation as we may have switched the execution mode */ |
|
3570 ctx->bstate = BS_STOP; |
|
3571 break; |
|
3572 case 12: |
|
3573 switch (sel) { |
|
3574 case 0: |
|
3575 gen_helper_mtc0_status(t0); |
|
3576 /* BS_STOP isn't good enough here, hflags may have changed. */ |
|
3577 gen_save_pc(ctx->pc + 4); |
|
3578 ctx->bstate = BS_EXCP; |
|
3579 rn = "Status"; |
|
3580 break; |
|
3581 case 1: |
|
3582 check_insn(env, ctx, ISA_MIPS32R2); |
|
3583 gen_helper_mtc0_intctl(t0); |
|
3584 /* Stop translation as we may have switched the execution mode */ |
|
3585 ctx->bstate = BS_STOP; |
|
3586 rn = "IntCtl"; |
|
3587 break; |
|
3588 case 2: |
|
3589 check_insn(env, ctx, ISA_MIPS32R2); |
|
3590 gen_helper_mtc0_srsctl(t0); |
|
3591 /* Stop translation as we may have switched the execution mode */ |
|
3592 ctx->bstate = BS_STOP; |
|
3593 rn = "SRSCtl"; |
|
3594 break; |
|
3595 case 3: |
|
3596 check_insn(env, ctx, ISA_MIPS32R2); |
|
3597 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap)); |
|
3598 /* Stop translation as we may have switched the execution mode */ |
|
3599 ctx->bstate = BS_STOP; |
|
3600 rn = "SRSMap"; |
|
3601 break; |
|
3602 default: |
|
3603 goto die; |
|
3604 } |
|
3605 break; |
|
3606 case 13: |
|
3607 switch (sel) { |
|
3608 case 0: |
|
3609 gen_helper_mtc0_cause(t0); |
|
3610 rn = "Cause"; |
|
3611 break; |
|
3612 default: |
|
3613 goto die; |
|
3614 } |
|
3615 /* Stop translation as we may have switched the execution mode */ |
|
3616 ctx->bstate = BS_STOP; |
|
3617 break; |
|
3618 case 14: |
|
3619 switch (sel) { |
|
3620 case 0: |
|
3621 gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC)); |
|
3622 rn = "EPC"; |
|
3623 break; |
|
3624 default: |
|
3625 goto die; |
|
3626 } |
|
3627 break; |
|
3628 case 15: |
|
3629 switch (sel) { |
|
3630 case 0: |
|
3631 /* ignored */ |
|
3632 rn = "PRid"; |
|
3633 break; |
|
3634 case 1: |
|
3635 check_insn(env, ctx, ISA_MIPS32R2); |
|
3636 gen_helper_mtc0_ebase(t0); |
|
3637 rn = "EBase"; |
|
3638 break; |
|
3639 default: |
|
3640 goto die; |
|
3641 } |
|
3642 break; |
|
3643 case 16: |
|
3644 switch (sel) { |
|
3645 case 0: |
|
3646 gen_helper_mtc0_config0(t0); |
|
3647 rn = "Config"; |
|
3648 /* Stop translation as we may have switched the execution mode */ |
|
3649 ctx->bstate = BS_STOP; |
|
3650 break; |
|
3651 case 1: |
|
3652 /* ignored, read only */ |
|
3653 rn = "Config1"; |
|
3654 break; |
|
3655 case 2: |
|
3656 gen_helper_mtc0_config2(t0); |
|
3657 rn = "Config2"; |
|
3658 /* Stop translation as we may have switched the execution mode */ |
|
3659 ctx->bstate = BS_STOP; |
|
3660 break; |
|
3661 case 3: |
|
3662 /* ignored, read only */ |
|
3663 rn = "Config3"; |
|
3664 break; |
|
3665 /* 4,5 are reserved */ |
|
3666 /* 6,7 are implementation dependent */ |
|
3667 case 6: |
|
3668 /* ignored */ |
|
3669 rn = "Config6"; |
|
3670 break; |
|
3671 case 7: |
|
3672 /* ignored */ |
|
3673 rn = "Config7"; |
|
3674 break; |
|
3675 default: |
|
3676 rn = "Invalid config selector"; |
|
3677 goto die; |
|
3678 } |
|
3679 break; |
|
3680 case 17: |
|
3681 switch (sel) { |
|
3682 case 0: |
|
3683 /* ignored */ |
|
3684 rn = "LLAddr"; |
|
3685 break; |
|
3686 default: |
|
3687 goto die; |
|
3688 } |
|
3689 break; |
|
3690 case 18: |
|
3691 switch (sel) { |
|
3692 case 0 ... 7: |
|
3693 gen_helper_1i(mtc0_watchlo, t0, sel); |
|
3694 rn = "WatchLo"; |
|
3695 break; |
|
3696 default: |
|
3697 goto die; |
|
3698 } |
|
3699 break; |
|
3700 case 19: |
|
3701 switch (sel) { |
|
3702 case 0 ... 7: |
|
3703 gen_helper_1i(mtc0_watchhi, t0, sel); |
|
3704 rn = "WatchHi"; |
|
3705 break; |
|
3706 default: |
|
3707 goto die; |
|
3708 } |
|
3709 break; |
|
3710 case 20: |
|
3711 switch (sel) { |
|
3712 case 0: |
|
3713 #if defined(TARGET_MIPS64) |
|
3714 check_insn(env, ctx, ISA_MIPS3); |
|
3715 gen_helper_mtc0_xcontext(t0); |
|
3716 rn = "XContext"; |
|
3717 break; |
|
3718 #endif |
|
3719 default: |
|
3720 goto die; |
|
3721 } |
|
3722 break; |
|
3723 case 21: |
|
3724 /* Officially reserved, but sel 0 is used for R1x000 framemask */ |
|
3725 switch (sel) { |
|
3726 case 0: |
|
3727 gen_helper_mtc0_framemask(t0); |
|
3728 rn = "Framemask"; |
|
3729 break; |
|
3730 default: |
|
3731 goto die; |
|
3732 } |
|
3733 break; |
|
3734 case 22: |
|
3735 /* ignored */ |
|
3736 rn = "Diagnostic"; /* implementation dependent */ |
|
3737 break; |
|
3738 case 23: |
|
3739 switch (sel) { |
|
3740 case 0: |
|
3741 gen_helper_mtc0_debug(t0); /* EJTAG support */ |
|
3742 /* BS_STOP isn't good enough here, hflags may have changed. */ |
|
3743 gen_save_pc(ctx->pc + 4); |
|
3744 ctx->bstate = BS_EXCP; |
|
3745 rn = "Debug"; |
|
3746 break; |
|
3747 case 1: |
|
3748 // gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */ |
|
3749 rn = "TraceControl"; |
|
3750 /* Stop translation as we may have switched the execution mode */ |
|
3751 ctx->bstate = BS_STOP; |
|
3752 // break; |
|
3753 case 2: |
|
3754 // gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */ |
|
3755 rn = "TraceControl2"; |
|
3756 /* Stop translation as we may have switched the execution mode */ |
|
3757 ctx->bstate = BS_STOP; |
|
3758 // break; |
|
3759 case 3: |
|
3760 /* Stop translation as we may have switched the execution mode */ |
|
3761 ctx->bstate = BS_STOP; |
|
3762 // gen_helper_mtc0_usertracedata(t0); /* PDtrace support */ |
|
3763 rn = "UserTraceData"; |
|
3764 /* Stop translation as we may have switched the execution mode */ |
|
3765 ctx->bstate = BS_STOP; |
|
3766 // break; |
|
3767 case 4: |
|
3768 // gen_helper_mtc0_tracebpc(t0); /* PDtrace support */ |
|
3769 /* Stop translation as we may have switched the execution mode */ |
|
3770 ctx->bstate = BS_STOP; |
|
3771 rn = "TraceBPC"; |
|
3772 // break; |
|
3773 default: |
|
3774 goto die; |
|
3775 } |
|
3776 break; |
|
3777 case 24: |
|
3778 switch (sel) { |
|
3779 case 0: |
|
3780 /* EJTAG support */ |
|
3781 gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC)); |
|
3782 rn = "DEPC"; |
|
3783 break; |
|
3784 default: |
|
3785 goto die; |
|
3786 } |
|
3787 break; |
|
3788 case 25: |
|
3789 switch (sel) { |
|
3790 case 0: |
|
3791 gen_helper_mtc0_performance0(t0); |
|
3792 rn = "Performance0"; |
|
3793 break; |
|
3794 case 1: |
|
3795 // gen_helper_mtc0_performance1(t0); |
|
3796 rn = "Performance1"; |
|
3797 // break; |
|
3798 case 2: |
|
3799 // gen_helper_mtc0_performance2(t0); |
|
3800 rn = "Performance2"; |
|
3801 // break; |
|
3802 case 3: |
|
3803 // gen_helper_mtc0_performance3(t0); |
|
3804 rn = "Performance3"; |
|
3805 // break; |
|
3806 case 4: |
|
3807 // gen_helper_mtc0_performance4(t0); |
|
3808 rn = "Performance4"; |
|
3809 // break; |
|
3810 case 5: |
|
3811 // gen_helper_mtc0_performance5(t0); |
|
3812 rn = "Performance5"; |
|
3813 // break; |
|
3814 case 6: |
|
3815 // gen_helper_mtc0_performance6(t0); |
|
3816 rn = "Performance6"; |
|
3817 // break; |
|
3818 case 7: |
|
3819 // gen_helper_mtc0_performance7(t0); |
|
3820 rn = "Performance7"; |
|
3821 // break; |
|
3822 default: |
|
3823 goto die; |
|
3824 } |
|
3825 break; |
|
3826 case 26: |
|
3827 /* ignored */ |
|
3828 rn = "ECC"; |
|
3829 break; |
|
3830 case 27: |
|
3831 switch (sel) { |
|
3832 case 0 ... 3: |
|
3833 /* ignored */ |
|
3834 rn = "CacheErr"; |
|
3835 break; |
|
3836 default: |
|
3837 goto die; |
|
3838 } |
|
3839 break; |
|
3840 case 28: |
|
3841 switch (sel) { |
|
3842 case 0: |
|
3843 case 2: |
|
3844 case 4: |
|
3845 case 6: |
|
3846 gen_helper_mtc0_taglo(t0); |
|
3847 rn = "TagLo"; |
|
3848 break; |
|
3849 case 1: |
|
3850 case 3: |
|
3851 case 5: |
|
3852 case 7: |
|
3853 gen_helper_mtc0_datalo(t0); |
|
3854 rn = "DataLo"; |
|
3855 break; |
|
3856 default: |
|
3857 goto die; |
|
3858 } |
|
3859 break; |
|
3860 case 29: |
|
3861 switch (sel) { |
|
3862 case 0: |
|
3863 case 2: |
|
3864 case 4: |
|
3865 case 6: |
|
3866 gen_helper_mtc0_taghi(t0); |
|
3867 rn = "TagHi"; |
|
3868 break; |
|
3869 case 1: |
|
3870 case 3: |
|
3871 case 5: |
|
3872 case 7: |
|
3873 gen_helper_mtc0_datahi(t0); |
|
3874 rn = "DataHi"; |
|
3875 break; |
|
3876 default: |
|
3877 rn = "invalid sel"; |
|
3878 goto die; |
|
3879 } |
|
3880 break; |
|
3881 case 30: |
|
3882 switch (sel) { |
|
3883 case 0: |
|
3884 gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC)); |
|
3885 rn = "ErrorEPC"; |
|
3886 break; |
|
3887 default: |
|
3888 goto die; |
|
3889 } |
|
3890 break; |
|
3891 case 31: |
|
3892 switch (sel) { |
|
3893 case 0: |
|
3894 /* EJTAG support */ |
|
3895 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE)); |
|
3896 rn = "DESAVE"; |
|
3897 break; |
|
3898 default: |
|
3899 goto die; |
|
3900 } |
|
3901 /* Stop translation as we may have switched the execution mode */ |
|
3902 ctx->bstate = BS_STOP; |
|
3903 break; |
|
3904 default: |
|
3905 goto die; |
|
3906 } |
|
3907 #if defined MIPS_DEBUG_DISAS |
|
3908 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
3909 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n", |
|
3910 rn, reg, sel); |
|
3911 } |
|
3912 #endif |
|
3913 /* For simplicity assume that all writes can cause interrupts. */ |
|
3914 if (use_icount) { |
|
3915 gen_io_end(); |
|
3916 ctx->bstate = BS_STOP; |
|
3917 } |
|
3918 return; |
|
3919 |
|
3920 die: |
|
3921 #if defined MIPS_DEBUG_DISAS |
|
3922 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
3923 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n", |
|
3924 rn, reg, sel); |
|
3925 } |
|
3926 #endif |
|
3927 generate_exception(ctx, EXCP_RI); |
|
3928 } |
|
3929 |
|
3930 #if defined(TARGET_MIPS64) |
|
3931 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel) |
|
3932 { |
|
3933 const char *rn = "invalid"; |
|
3934 |
|
3935 if (sel != 0) |
|
3936 check_insn(env, ctx, ISA_MIPS64); |
|
3937 |
|
3938 switch (reg) { |
|
3939 case 0: |
|
3940 switch (sel) { |
|
3941 case 0: |
|
3942 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index)); |
|
3943 rn = "Index"; |
|
3944 break; |
|
3945 case 1: |
|
3946 check_insn(env, ctx, ASE_MT); |
|
3947 gen_helper_mfc0_mvpcontrol(t0); |
|
3948 rn = "MVPControl"; |
|
3949 break; |
|
3950 case 2: |
|
3951 check_insn(env, ctx, ASE_MT); |
|
3952 gen_helper_mfc0_mvpconf0(t0); |
|
3953 rn = "MVPConf0"; |
|
3954 break; |
|
3955 case 3: |
|
3956 check_insn(env, ctx, ASE_MT); |
|
3957 gen_helper_mfc0_mvpconf1(t0); |
|
3958 rn = "MVPConf1"; |
|
3959 break; |
|
3960 default: |
|
3961 goto die; |
|
3962 } |
|
3963 break; |
|
3964 case 1: |
|
3965 switch (sel) { |
|
3966 case 0: |
|
3967 gen_helper_mfc0_random(t0); |
|
3968 rn = "Random"; |
|
3969 break; |
|
3970 case 1: |
|
3971 check_insn(env, ctx, ASE_MT); |
|
3972 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl)); |
|
3973 rn = "VPEControl"; |
|
3974 break; |
|
3975 case 2: |
|
3976 check_insn(env, ctx, ASE_MT); |
|
3977 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0)); |
|
3978 rn = "VPEConf0"; |
|
3979 break; |
|
3980 case 3: |
|
3981 check_insn(env, ctx, ASE_MT); |
|
3982 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1)); |
|
3983 rn = "VPEConf1"; |
|
3984 break; |
|
3985 case 4: |
|
3986 check_insn(env, ctx, ASE_MT); |
|
3987 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask)); |
|
3988 rn = "YQMask"; |
|
3989 break; |
|
3990 case 5: |
|
3991 check_insn(env, ctx, ASE_MT); |
|
3992 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule)); |
|
3993 rn = "VPESchedule"; |
|
3994 break; |
|
3995 case 6: |
|
3996 check_insn(env, ctx, ASE_MT); |
|
3997 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack)); |
|
3998 rn = "VPEScheFBack"; |
|
3999 break; |
|
4000 case 7: |
|
4001 check_insn(env, ctx, ASE_MT); |
|
4002 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt)); |
|
4003 rn = "VPEOpt"; |
|
4004 break; |
|
4005 default: |
|
4006 goto die; |
|
4007 } |
|
4008 break; |
|
4009 case 2: |
|
4010 switch (sel) { |
|
4011 case 0: |
|
4012 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0)); |
|
4013 rn = "EntryLo0"; |
|
4014 break; |
|
4015 case 1: |
|
4016 check_insn(env, ctx, ASE_MT); |
|
4017 gen_helper_mfc0_tcstatus(t0); |
|
4018 rn = "TCStatus"; |
|
4019 break; |
|
4020 case 2: |
|
4021 check_insn(env, ctx, ASE_MT); |
|
4022 gen_helper_mfc0_tcbind(t0); |
|
4023 rn = "TCBind"; |
|
4024 break; |
|
4025 case 3: |
|
4026 check_insn(env, ctx, ASE_MT); |
|
4027 gen_helper_dmfc0_tcrestart(t0); |
|
4028 rn = "TCRestart"; |
|
4029 break; |
|
4030 case 4: |
|
4031 check_insn(env, ctx, ASE_MT); |
|
4032 gen_helper_dmfc0_tchalt(t0); |
|
4033 rn = "TCHalt"; |
|
4034 break; |
|
4035 case 5: |
|
4036 check_insn(env, ctx, ASE_MT); |
|
4037 gen_helper_dmfc0_tccontext(t0); |
|
4038 rn = "TCContext"; |
|
4039 break; |
|
4040 case 6: |
|
4041 check_insn(env, ctx, ASE_MT); |
|
4042 gen_helper_dmfc0_tcschedule(t0); |
|
4043 rn = "TCSchedule"; |
|
4044 break; |
|
4045 case 7: |
|
4046 check_insn(env, ctx, ASE_MT); |
|
4047 gen_helper_dmfc0_tcschefback(t0); |
|
4048 rn = "TCScheFBack"; |
|
4049 break; |
|
4050 default: |
|
4051 goto die; |
|
4052 } |
|
4053 break; |
|
4054 case 3: |
|
4055 switch (sel) { |
|
4056 case 0: |
|
4057 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1)); |
|
4058 rn = "EntryLo1"; |
|
4059 break; |
|
4060 default: |
|
4061 goto die; |
|
4062 } |
|
4063 break; |
|
4064 case 4: |
|
4065 switch (sel) { |
|
4066 case 0: |
|
4067 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context)); |
|
4068 rn = "Context"; |
|
4069 break; |
|
4070 case 1: |
|
4071 // gen_helper_dmfc0_contextconfig(t0); /* SmartMIPS ASE */ |
|
4072 rn = "ContextConfig"; |
|
4073 // break; |
|
4074 default: |
|
4075 goto die; |
|
4076 } |
|
4077 break; |
|
4078 case 5: |
|
4079 switch (sel) { |
|
4080 case 0: |
|
4081 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask)); |
|
4082 rn = "PageMask"; |
|
4083 break; |
|
4084 case 1: |
|
4085 check_insn(env, ctx, ISA_MIPS32R2); |
|
4086 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain)); |
|
4087 rn = "PageGrain"; |
|
4088 break; |
|
4089 default: |
|
4090 goto die; |
|
4091 } |
|
4092 break; |
|
4093 case 6: |
|
4094 switch (sel) { |
|
4095 case 0: |
|
4096 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired)); |
|
4097 rn = "Wired"; |
|
4098 break; |
|
4099 case 1: |
|
4100 check_insn(env, ctx, ISA_MIPS32R2); |
|
4101 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0)); |
|
4102 rn = "SRSConf0"; |
|
4103 break; |
|
4104 case 2: |
|
4105 check_insn(env, ctx, ISA_MIPS32R2); |
|
4106 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1)); |
|
4107 rn = "SRSConf1"; |
|
4108 break; |
|
4109 case 3: |
|
4110 check_insn(env, ctx, ISA_MIPS32R2); |
|
4111 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2)); |
|
4112 rn = "SRSConf2"; |
|
4113 break; |
|
4114 case 4: |
|
4115 check_insn(env, ctx, ISA_MIPS32R2); |
|
4116 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3)); |
|
4117 rn = "SRSConf3"; |
|
4118 break; |
|
4119 case 5: |
|
4120 check_insn(env, ctx, ISA_MIPS32R2); |
|
4121 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4)); |
|
4122 rn = "SRSConf4"; |
|
4123 break; |
|
4124 default: |
|
4125 goto die; |
|
4126 } |
|
4127 break; |
|
4128 case 7: |
|
4129 switch (sel) { |
|
4130 case 0: |
|
4131 check_insn(env, ctx, ISA_MIPS32R2); |
|
4132 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna)); |
|
4133 rn = "HWREna"; |
|
4134 break; |
|
4135 default: |
|
4136 goto die; |
|
4137 } |
|
4138 break; |
|
4139 case 8: |
|
4140 switch (sel) { |
|
4141 case 0: |
|
4142 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr)); |
|
4143 rn = "BadVAddr"; |
|
4144 break; |
|
4145 default: |
|
4146 goto die; |
|
4147 } |
|
4148 break; |
|
4149 case 9: |
|
4150 switch (sel) { |
|
4151 case 0: |
|
4152 /* Mark as an IO operation because we read the time. */ |
|
4153 if (use_icount) |
|
4154 gen_io_start(); |
|
4155 gen_helper_mfc0_count(t0); |
|
4156 if (use_icount) { |
|
4157 gen_io_end(); |
|
4158 ctx->bstate = BS_STOP; |
|
4159 } |
|
4160 rn = "Count"; |
|
4161 break; |
|
4162 /* 6,7 are implementation dependent */ |
|
4163 default: |
|
4164 goto die; |
|
4165 } |
|
4166 break; |
|
4167 case 10: |
|
4168 switch (sel) { |
|
4169 case 0: |
|
4170 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi)); |
|
4171 rn = "EntryHi"; |
|
4172 break; |
|
4173 default: |
|
4174 goto die; |
|
4175 } |
|
4176 break; |
|
4177 case 11: |
|
4178 switch (sel) { |
|
4179 case 0: |
|
4180 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare)); |
|
4181 rn = "Compare"; |
|
4182 break; |
|
4183 /* 6,7 are implementation dependent */ |
|
4184 default: |
|
4185 goto die; |
|
4186 } |
|
4187 break; |
|
4188 case 12: |
|
4189 switch (sel) { |
|
4190 case 0: |
|
4191 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status)); |
|
4192 rn = "Status"; |
|
4193 break; |
|
4194 case 1: |
|
4195 check_insn(env, ctx, ISA_MIPS32R2); |
|
4196 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl)); |
|
4197 rn = "IntCtl"; |
|
4198 break; |
|
4199 case 2: |
|
4200 check_insn(env, ctx, ISA_MIPS32R2); |
|
4201 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl)); |
|
4202 rn = "SRSCtl"; |
|
4203 break; |
|
4204 case 3: |
|
4205 check_insn(env, ctx, ISA_MIPS32R2); |
|
4206 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap)); |
|
4207 rn = "SRSMap"; |
|
4208 break; |
|
4209 default: |
|
4210 goto die; |
|
4211 } |
|
4212 break; |
|
4213 case 13: |
|
4214 switch (sel) { |
|
4215 case 0: |
|
4216 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause)); |
|
4217 rn = "Cause"; |
|
4218 break; |
|
4219 default: |
|
4220 goto die; |
|
4221 } |
|
4222 break; |
|
4223 case 14: |
|
4224 switch (sel) { |
|
4225 case 0: |
|
4226 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC)); |
|
4227 rn = "EPC"; |
|
4228 break; |
|
4229 default: |
|
4230 goto die; |
|
4231 } |
|
4232 break; |
|
4233 case 15: |
|
4234 switch (sel) { |
|
4235 case 0: |
|
4236 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid)); |
|
4237 rn = "PRid"; |
|
4238 break; |
|
4239 case 1: |
|
4240 check_insn(env, ctx, ISA_MIPS32R2); |
|
4241 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase)); |
|
4242 rn = "EBase"; |
|
4243 break; |
|
4244 default: |
|
4245 goto die; |
|
4246 } |
|
4247 break; |
|
4248 case 16: |
|
4249 switch (sel) { |
|
4250 case 0: |
|
4251 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0)); |
|
4252 rn = "Config"; |
|
4253 break; |
|
4254 case 1: |
|
4255 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1)); |
|
4256 rn = "Config1"; |
|
4257 break; |
|
4258 case 2: |
|
4259 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2)); |
|
4260 rn = "Config2"; |
|
4261 break; |
|
4262 case 3: |
|
4263 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3)); |
|
4264 rn = "Config3"; |
|
4265 break; |
|
4266 /* 6,7 are implementation dependent */ |
|
4267 case 6: |
|
4268 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6)); |
|
4269 rn = "Config6"; |
|
4270 break; |
|
4271 case 7: |
|
4272 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7)); |
|
4273 rn = "Config7"; |
|
4274 break; |
|
4275 default: |
|
4276 goto die; |
|
4277 } |
|
4278 break; |
|
4279 case 17: |
|
4280 switch (sel) { |
|
4281 case 0: |
|
4282 gen_helper_dmfc0_lladdr(t0); |
|
4283 rn = "LLAddr"; |
|
4284 break; |
|
4285 default: |
|
4286 goto die; |
|
4287 } |
|
4288 break; |
|
4289 case 18: |
|
4290 switch (sel) { |
|
4291 case 0 ... 7: |
|
4292 gen_helper_1i(dmfc0_watchlo, t0, sel); |
|
4293 rn = "WatchLo"; |
|
4294 break; |
|
4295 default: |
|
4296 goto die; |
|
4297 } |
|
4298 break; |
|
4299 case 19: |
|
4300 switch (sel) { |
|
4301 case 0 ... 7: |
|
4302 gen_helper_1i(mfc0_watchhi, t0, sel); |
|
4303 rn = "WatchHi"; |
|
4304 break; |
|
4305 default: |
|
4306 goto die; |
|
4307 } |
|
4308 break; |
|
4309 case 20: |
|
4310 switch (sel) { |
|
4311 case 0: |
|
4312 check_insn(env, ctx, ISA_MIPS3); |
|
4313 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext)); |
|
4314 rn = "XContext"; |
|
4315 break; |
|
4316 default: |
|
4317 goto die; |
|
4318 } |
|
4319 break; |
|
4320 case 21: |
|
4321 /* Officially reserved, but sel 0 is used for R1x000 framemask */ |
|
4322 switch (sel) { |
|
4323 case 0: |
|
4324 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask)); |
|
4325 rn = "Framemask"; |
|
4326 break; |
|
4327 default: |
|
4328 goto die; |
|
4329 } |
|
4330 break; |
|
4331 case 22: |
|
4332 tcg_gen_movi_tl(t0, 0); /* unimplemented */ |
|
4333 rn = "'Diagnostic"; /* implementation dependent */ |
|
4334 break; |
|
4335 case 23: |
|
4336 switch (sel) { |
|
4337 case 0: |
|
4338 gen_helper_mfc0_debug(t0); /* EJTAG support */ |
|
4339 rn = "Debug"; |
|
4340 break; |
|
4341 case 1: |
|
4342 // gen_helper_dmfc0_tracecontrol(t0); /* PDtrace support */ |
|
4343 rn = "TraceControl"; |
|
4344 // break; |
|
4345 case 2: |
|
4346 // gen_helper_dmfc0_tracecontrol2(t0); /* PDtrace support */ |
|
4347 rn = "TraceControl2"; |
|
4348 // break; |
|
4349 case 3: |
|
4350 // gen_helper_dmfc0_usertracedata(t0); /* PDtrace support */ |
|
4351 rn = "UserTraceData"; |
|
4352 // break; |
|
4353 case 4: |
|
4354 // gen_helper_dmfc0_tracebpc(t0); /* PDtrace support */ |
|
4355 rn = "TraceBPC"; |
|
4356 // break; |
|
4357 default: |
|
4358 goto die; |
|
4359 } |
|
4360 break; |
|
4361 case 24: |
|
4362 switch (sel) { |
|
4363 case 0: |
|
4364 /* EJTAG support */ |
|
4365 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC)); |
|
4366 rn = "DEPC"; |
|
4367 break; |
|
4368 default: |
|
4369 goto die; |
|
4370 } |
|
4371 break; |
|
4372 case 25: |
|
4373 switch (sel) { |
|
4374 case 0: |
|
4375 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0)); |
|
4376 rn = "Performance0"; |
|
4377 break; |
|
4378 case 1: |
|
4379 // gen_helper_dmfc0_performance1(t0); |
|
4380 rn = "Performance1"; |
|
4381 // break; |
|
4382 case 2: |
|
4383 // gen_helper_dmfc0_performance2(t0); |
|
4384 rn = "Performance2"; |
|
4385 // break; |
|
4386 case 3: |
|
4387 // gen_helper_dmfc0_performance3(t0); |
|
4388 rn = "Performance3"; |
|
4389 // break; |
|
4390 case 4: |
|
4391 // gen_helper_dmfc0_performance4(t0); |
|
4392 rn = "Performance4"; |
|
4393 // break; |
|
4394 case 5: |
|
4395 // gen_helper_dmfc0_performance5(t0); |
|
4396 rn = "Performance5"; |
|
4397 // break; |
|
4398 case 6: |
|
4399 // gen_helper_dmfc0_performance6(t0); |
|
4400 rn = "Performance6"; |
|
4401 // break; |
|
4402 case 7: |
|
4403 // gen_helper_dmfc0_performance7(t0); |
|
4404 rn = "Performance7"; |
|
4405 // break; |
|
4406 default: |
|
4407 goto die; |
|
4408 } |
|
4409 break; |
|
4410 case 26: |
|
4411 tcg_gen_movi_tl(t0, 0); /* unimplemented */ |
|
4412 rn = "ECC"; |
|
4413 break; |
|
4414 case 27: |
|
4415 switch (sel) { |
|
4416 /* ignored */ |
|
4417 case 0 ... 3: |
|
4418 tcg_gen_movi_tl(t0, 0); /* unimplemented */ |
|
4419 rn = "CacheErr"; |
|
4420 break; |
|
4421 default: |
|
4422 goto die; |
|
4423 } |
|
4424 break; |
|
4425 case 28: |
|
4426 switch (sel) { |
|
4427 case 0: |
|
4428 case 2: |
|
4429 case 4: |
|
4430 case 6: |
|
4431 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo)); |
|
4432 rn = "TagLo"; |
|
4433 break; |
|
4434 case 1: |
|
4435 case 3: |
|
4436 case 5: |
|
4437 case 7: |
|
4438 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo)); |
|
4439 rn = "DataLo"; |
|
4440 break; |
|
4441 default: |
|
4442 goto die; |
|
4443 } |
|
4444 break; |
|
4445 case 29: |
|
4446 switch (sel) { |
|
4447 case 0: |
|
4448 case 2: |
|
4449 case 4: |
|
4450 case 6: |
|
4451 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi)); |
|
4452 rn = "TagHi"; |
|
4453 break; |
|
4454 case 1: |
|
4455 case 3: |
|
4456 case 5: |
|
4457 case 7: |
|
4458 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi)); |
|
4459 rn = "DataHi"; |
|
4460 break; |
|
4461 default: |
|
4462 goto die; |
|
4463 } |
|
4464 break; |
|
4465 case 30: |
|
4466 switch (sel) { |
|
4467 case 0: |
|
4468 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC)); |
|
4469 rn = "ErrorEPC"; |
|
4470 break; |
|
4471 default: |
|
4472 goto die; |
|
4473 } |
|
4474 break; |
|
4475 case 31: |
|
4476 switch (sel) { |
|
4477 case 0: |
|
4478 /* EJTAG support */ |
|
4479 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE)); |
|
4480 rn = "DESAVE"; |
|
4481 break; |
|
4482 default: |
|
4483 goto die; |
|
4484 } |
|
4485 break; |
|
4486 default: |
|
4487 goto die; |
|
4488 } |
|
4489 #if defined MIPS_DEBUG_DISAS |
|
4490 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
4491 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n", |
|
4492 rn, reg, sel); |
|
4493 } |
|
4494 #endif |
|
4495 return; |
|
4496 |
|
4497 die: |
|
4498 #if defined MIPS_DEBUG_DISAS |
|
4499 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
4500 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n", |
|
4501 rn, reg, sel); |
|
4502 } |
|
4503 #endif |
|
4504 generate_exception(ctx, EXCP_RI); |
|
4505 } |
|
4506 |
|
4507 static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel) |
|
4508 { |
|
4509 const char *rn = "invalid"; |
|
4510 |
|
4511 if (sel != 0) |
|
4512 check_insn(env, ctx, ISA_MIPS64); |
|
4513 |
|
4514 if (use_icount) |
|
4515 gen_io_start(); |
|
4516 |
|
4517 switch (reg) { |
|
4518 case 0: |
|
4519 switch (sel) { |
|
4520 case 0: |
|
4521 gen_helper_mtc0_index(t0); |
|
4522 rn = "Index"; |
|
4523 break; |
|
4524 case 1: |
|
4525 check_insn(env, ctx, ASE_MT); |
|
4526 gen_helper_mtc0_mvpcontrol(t0); |
|
4527 rn = "MVPControl"; |
|
4528 break; |
|
4529 case 2: |
|
4530 check_insn(env, ctx, ASE_MT); |
|
4531 /* ignored */ |
|
4532 rn = "MVPConf0"; |
|
4533 break; |
|
4534 case 3: |
|
4535 check_insn(env, ctx, ASE_MT); |
|
4536 /* ignored */ |
|
4537 rn = "MVPConf1"; |
|
4538 break; |
|
4539 default: |
|
4540 goto die; |
|
4541 } |
|
4542 break; |
|
4543 case 1: |
|
4544 switch (sel) { |
|
4545 case 0: |
|
4546 /* ignored */ |
|
4547 rn = "Random"; |
|
4548 break; |
|
4549 case 1: |
|
4550 check_insn(env, ctx, ASE_MT); |
|
4551 gen_helper_mtc0_vpecontrol(t0); |
|
4552 rn = "VPEControl"; |
|
4553 break; |
|
4554 case 2: |
|
4555 check_insn(env, ctx, ASE_MT); |
|
4556 gen_helper_mtc0_vpeconf0(t0); |
|
4557 rn = "VPEConf0"; |
|
4558 break; |
|
4559 case 3: |
|
4560 check_insn(env, ctx, ASE_MT); |
|
4561 gen_helper_mtc0_vpeconf1(t0); |
|
4562 rn = "VPEConf1"; |
|
4563 break; |
|
4564 case 4: |
|
4565 check_insn(env, ctx, ASE_MT); |
|
4566 gen_helper_mtc0_yqmask(t0); |
|
4567 rn = "YQMask"; |
|
4568 break; |
|
4569 case 5: |
|
4570 check_insn(env, ctx, ASE_MT); |
|
4571 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule)); |
|
4572 rn = "VPESchedule"; |
|
4573 break; |
|
4574 case 6: |
|
4575 check_insn(env, ctx, ASE_MT); |
|
4576 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack)); |
|
4577 rn = "VPEScheFBack"; |
|
4578 break; |
|
4579 case 7: |
|
4580 check_insn(env, ctx, ASE_MT); |
|
4581 gen_helper_mtc0_vpeopt(t0); |
|
4582 rn = "VPEOpt"; |
|
4583 break; |
|
4584 default: |
|
4585 goto die; |
|
4586 } |
|
4587 break; |
|
4588 case 2: |
|
4589 switch (sel) { |
|
4590 case 0: |
|
4591 gen_helper_mtc0_entrylo0(t0); |
|
4592 rn = "EntryLo0"; |
|
4593 break; |
|
4594 case 1: |
|
4595 check_insn(env, ctx, ASE_MT); |
|
4596 gen_helper_mtc0_tcstatus(t0); |
|
4597 rn = "TCStatus"; |
|
4598 break; |
|
4599 case 2: |
|
4600 check_insn(env, ctx, ASE_MT); |
|
4601 gen_helper_mtc0_tcbind(t0); |
|
4602 rn = "TCBind"; |
|
4603 break; |
|
4604 case 3: |
|
4605 check_insn(env, ctx, ASE_MT); |
|
4606 gen_helper_mtc0_tcrestart(t0); |
|
4607 rn = "TCRestart"; |
|
4608 break; |
|
4609 case 4: |
|
4610 check_insn(env, ctx, ASE_MT); |
|
4611 gen_helper_mtc0_tchalt(t0); |
|
4612 rn = "TCHalt"; |
|
4613 break; |
|
4614 case 5: |
|
4615 check_insn(env, ctx, ASE_MT); |
|
4616 gen_helper_mtc0_tccontext(t0); |
|
4617 rn = "TCContext"; |
|
4618 break; |
|
4619 case 6: |
|
4620 check_insn(env, ctx, ASE_MT); |
|
4621 gen_helper_mtc0_tcschedule(t0); |
|
4622 rn = "TCSchedule"; |
|
4623 break; |
|
4624 case 7: |
|
4625 check_insn(env, ctx, ASE_MT); |
|
4626 gen_helper_mtc0_tcschefback(t0); |
|
4627 rn = "TCScheFBack"; |
|
4628 break; |
|
4629 default: |
|
4630 goto die; |
|
4631 } |
|
4632 break; |
|
4633 case 3: |
|
4634 switch (sel) { |
|
4635 case 0: |
|
4636 gen_helper_mtc0_entrylo1(t0); |
|
4637 rn = "EntryLo1"; |
|
4638 break; |
|
4639 default: |
|
4640 goto die; |
|
4641 } |
|
4642 break; |
|
4643 case 4: |
|
4644 switch (sel) { |
|
4645 case 0: |
|
4646 gen_helper_mtc0_context(t0); |
|
4647 rn = "Context"; |
|
4648 break; |
|
4649 case 1: |
|
4650 // gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */ |
|
4651 rn = "ContextConfig"; |
|
4652 // break; |
|
4653 default: |
|
4654 goto die; |
|
4655 } |
|
4656 break; |
|
4657 case 5: |
|
4658 switch (sel) { |
|
4659 case 0: |
|
4660 gen_helper_mtc0_pagemask(t0); |
|
4661 rn = "PageMask"; |
|
4662 break; |
|
4663 case 1: |
|
4664 check_insn(env, ctx, ISA_MIPS32R2); |
|
4665 gen_helper_mtc0_pagegrain(t0); |
|
4666 rn = "PageGrain"; |
|
4667 break; |
|
4668 default: |
|
4669 goto die; |
|
4670 } |
|
4671 break; |
|
4672 case 6: |
|
4673 switch (sel) { |
|
4674 case 0: |
|
4675 gen_helper_mtc0_wired(t0); |
|
4676 rn = "Wired"; |
|
4677 break; |
|
4678 case 1: |
|
4679 check_insn(env, ctx, ISA_MIPS32R2); |
|
4680 gen_helper_mtc0_srsconf0(t0); |
|
4681 rn = "SRSConf0"; |
|
4682 break; |
|
4683 case 2: |
|
4684 check_insn(env, ctx, ISA_MIPS32R2); |
|
4685 gen_helper_mtc0_srsconf1(t0); |
|
4686 rn = "SRSConf1"; |
|
4687 break; |
|
4688 case 3: |
|
4689 check_insn(env, ctx, ISA_MIPS32R2); |
|
4690 gen_helper_mtc0_srsconf2(t0); |
|
4691 rn = "SRSConf2"; |
|
4692 break; |
|
4693 case 4: |
|
4694 check_insn(env, ctx, ISA_MIPS32R2); |
|
4695 gen_helper_mtc0_srsconf3(t0); |
|
4696 rn = "SRSConf3"; |
|
4697 break; |
|
4698 case 5: |
|
4699 check_insn(env, ctx, ISA_MIPS32R2); |
|
4700 gen_helper_mtc0_srsconf4(t0); |
|
4701 rn = "SRSConf4"; |
|
4702 break; |
|
4703 default: |
|
4704 goto die; |
|
4705 } |
|
4706 break; |
|
4707 case 7: |
|
4708 switch (sel) { |
|
4709 case 0: |
|
4710 check_insn(env, ctx, ISA_MIPS32R2); |
|
4711 gen_helper_mtc0_hwrena(t0); |
|
4712 rn = "HWREna"; |
|
4713 break; |
|
4714 default: |
|
4715 goto die; |
|
4716 } |
|
4717 break; |
|
4718 case 8: |
|
4719 /* ignored */ |
|
4720 rn = "BadVAddr"; |
|
4721 break; |
|
4722 case 9: |
|
4723 switch (sel) { |
|
4724 case 0: |
|
4725 gen_helper_mtc0_count(t0); |
|
4726 rn = "Count"; |
|
4727 break; |
|
4728 /* 6,7 are implementation dependent */ |
|
4729 default: |
|
4730 goto die; |
|
4731 } |
|
4732 /* Stop translation as we may have switched the execution mode */ |
|
4733 ctx->bstate = BS_STOP; |
|
4734 break; |
|
4735 case 10: |
|
4736 switch (sel) { |
|
4737 case 0: |
|
4738 gen_helper_mtc0_entryhi(t0); |
|
4739 rn = "EntryHi"; |
|
4740 break; |
|
4741 default: |
|
4742 goto die; |
|
4743 } |
|
4744 break; |
|
4745 case 11: |
|
4746 switch (sel) { |
|
4747 case 0: |
|
4748 gen_helper_mtc0_compare(t0); |
|
4749 rn = "Compare"; |
|
4750 break; |
|
4751 /* 6,7 are implementation dependent */ |
|
4752 default: |
|
4753 goto die; |
|
4754 } |
|
4755 /* Stop translation as we may have switched the execution mode */ |
|
4756 ctx->bstate = BS_STOP; |
|
4757 break; |
|
4758 case 12: |
|
4759 switch (sel) { |
|
4760 case 0: |
|
4761 gen_helper_mtc0_status(t0); |
|
4762 /* BS_STOP isn't good enough here, hflags may have changed. */ |
|
4763 gen_save_pc(ctx->pc + 4); |
|
4764 ctx->bstate = BS_EXCP; |
|
4765 rn = "Status"; |
|
4766 break; |
|
4767 case 1: |
|
4768 check_insn(env, ctx, ISA_MIPS32R2); |
|
4769 gen_helper_mtc0_intctl(t0); |
|
4770 /* Stop translation as we may have switched the execution mode */ |
|
4771 ctx->bstate = BS_STOP; |
|
4772 rn = "IntCtl"; |
|
4773 break; |
|
4774 case 2: |
|
4775 check_insn(env, ctx, ISA_MIPS32R2); |
|
4776 gen_helper_mtc0_srsctl(t0); |
|
4777 /* Stop translation as we may have switched the execution mode */ |
|
4778 ctx->bstate = BS_STOP; |
|
4779 rn = "SRSCtl"; |
|
4780 break; |
|
4781 case 3: |
|
4782 check_insn(env, ctx, ISA_MIPS32R2); |
|
4783 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap)); |
|
4784 /* Stop translation as we may have switched the execution mode */ |
|
4785 ctx->bstate = BS_STOP; |
|
4786 rn = "SRSMap"; |
|
4787 break; |
|
4788 default: |
|
4789 goto die; |
|
4790 } |
|
4791 break; |
|
4792 case 13: |
|
4793 switch (sel) { |
|
4794 case 0: |
|
4795 gen_helper_mtc0_cause(t0); |
|
4796 rn = "Cause"; |
|
4797 break; |
|
4798 default: |
|
4799 goto die; |
|
4800 } |
|
4801 /* Stop translation as we may have switched the execution mode */ |
|
4802 ctx->bstate = BS_STOP; |
|
4803 break; |
|
4804 case 14: |
|
4805 switch (sel) { |
|
4806 case 0: |
|
4807 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC)); |
|
4808 rn = "EPC"; |
|
4809 break; |
|
4810 default: |
|
4811 goto die; |
|
4812 } |
|
4813 break; |
|
4814 case 15: |
|
4815 switch (sel) { |
|
4816 case 0: |
|
4817 /* ignored */ |
|
4818 rn = "PRid"; |
|
4819 break; |
|
4820 case 1: |
|
4821 check_insn(env, ctx, ISA_MIPS32R2); |
|
4822 gen_helper_mtc0_ebase(t0); |
|
4823 rn = "EBase"; |
|
4824 break; |
|
4825 default: |
|
4826 goto die; |
|
4827 } |
|
4828 break; |
|
4829 case 16: |
|
4830 switch (sel) { |
|
4831 case 0: |
|
4832 gen_helper_mtc0_config0(t0); |
|
4833 rn = "Config"; |
|
4834 /* Stop translation as we may have switched the execution mode */ |
|
4835 ctx->bstate = BS_STOP; |
|
4836 break; |
|
4837 case 1: |
|
4838 /* ignored */ |
|
4839 rn = "Config1"; |
|
4840 break; |
|
4841 case 2: |
|
4842 gen_helper_mtc0_config2(t0); |
|
4843 rn = "Config2"; |
|
4844 /* Stop translation as we may have switched the execution mode */ |
|
4845 ctx->bstate = BS_STOP; |
|
4846 break; |
|
4847 case 3: |
|
4848 /* ignored */ |
|
4849 rn = "Config3"; |
|
4850 break; |
|
4851 /* 6,7 are implementation dependent */ |
|
4852 default: |
|
4853 rn = "Invalid config selector"; |
|
4854 goto die; |
|
4855 } |
|
4856 break; |
|
4857 case 17: |
|
4858 switch (sel) { |
|
4859 case 0: |
|
4860 /* ignored */ |
|
4861 rn = "LLAddr"; |
|
4862 break; |
|
4863 default: |
|
4864 goto die; |
|
4865 } |
|
4866 break; |
|
4867 case 18: |
|
4868 switch (sel) { |
|
4869 case 0 ... 7: |
|
4870 gen_helper_1i(mtc0_watchlo, t0, sel); |
|
4871 rn = "WatchLo"; |
|
4872 break; |
|
4873 default: |
|
4874 goto die; |
|
4875 } |
|
4876 break; |
|
4877 case 19: |
|
4878 switch (sel) { |
|
4879 case 0 ... 7: |
|
4880 gen_helper_1i(mtc0_watchhi, t0, sel); |
|
4881 rn = "WatchHi"; |
|
4882 break; |
|
4883 default: |
|
4884 goto die; |
|
4885 } |
|
4886 break; |
|
4887 case 20: |
|
4888 switch (sel) { |
|
4889 case 0: |
|
4890 check_insn(env, ctx, ISA_MIPS3); |
|
4891 gen_helper_mtc0_xcontext(t0); |
|
4892 rn = "XContext"; |
|
4893 break; |
|
4894 default: |
|
4895 goto die; |
|
4896 } |
|
4897 break; |
|
4898 case 21: |
|
4899 /* Officially reserved, but sel 0 is used for R1x000 framemask */ |
|
4900 switch (sel) { |
|
4901 case 0: |
|
4902 gen_helper_mtc0_framemask(t0); |
|
4903 rn = "Framemask"; |
|
4904 break; |
|
4905 default: |
|
4906 goto die; |
|
4907 } |
|
4908 break; |
|
4909 case 22: |
|
4910 /* ignored */ |
|
4911 rn = "Diagnostic"; /* implementation dependent */ |
|
4912 break; |
|
4913 case 23: |
|
4914 switch (sel) { |
|
4915 case 0: |
|
4916 gen_helper_mtc0_debug(t0); /* EJTAG support */ |
|
4917 /* BS_STOP isn't good enough here, hflags may have changed. */ |
|
4918 gen_save_pc(ctx->pc + 4); |
|
4919 ctx->bstate = BS_EXCP; |
|
4920 rn = "Debug"; |
|
4921 break; |
|
4922 case 1: |
|
4923 // gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */ |
|
4924 /* Stop translation as we may have switched the execution mode */ |
|
4925 ctx->bstate = BS_STOP; |
|
4926 rn = "TraceControl"; |
|
4927 // break; |
|
4928 case 2: |
|
4929 // gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */ |
|
4930 /* Stop translation as we may have switched the execution mode */ |
|
4931 ctx->bstate = BS_STOP; |
|
4932 rn = "TraceControl2"; |
|
4933 // break; |
|
4934 case 3: |
|
4935 // gen_helper_mtc0_usertracedata(t0); /* PDtrace support */ |
|
4936 /* Stop translation as we may have switched the execution mode */ |
|
4937 ctx->bstate = BS_STOP; |
|
4938 rn = "UserTraceData"; |
|
4939 // break; |
|
4940 case 4: |
|
4941 // gen_helper_mtc0_tracebpc(t0); /* PDtrace support */ |
|
4942 /* Stop translation as we may have switched the execution mode */ |
|
4943 ctx->bstate = BS_STOP; |
|
4944 rn = "TraceBPC"; |
|
4945 // break; |
|
4946 default: |
|
4947 goto die; |
|
4948 } |
|
4949 break; |
|
4950 case 24: |
|
4951 switch (sel) { |
|
4952 case 0: |
|
4953 /* EJTAG support */ |
|
4954 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC)); |
|
4955 rn = "DEPC"; |
|
4956 break; |
|
4957 default: |
|
4958 goto die; |
|
4959 } |
|
4960 break; |
|
4961 case 25: |
|
4962 switch (sel) { |
|
4963 case 0: |
|
4964 gen_helper_mtc0_performance0(t0); |
|
4965 rn = "Performance0"; |
|
4966 break; |
|
4967 case 1: |
|
4968 // gen_helper_mtc0_performance1(t0); |
|
4969 rn = "Performance1"; |
|
4970 // break; |
|
4971 case 2: |
|
4972 // gen_helper_mtc0_performance2(t0); |
|
4973 rn = "Performance2"; |
|
4974 // break; |
|
4975 case 3: |
|
4976 // gen_helper_mtc0_performance3(t0); |
|
4977 rn = "Performance3"; |
|
4978 // break; |
|
4979 case 4: |
|
4980 // gen_helper_mtc0_performance4(t0); |
|
4981 rn = "Performance4"; |
|
4982 // break; |
|
4983 case 5: |
|
4984 // gen_helper_mtc0_performance5(t0); |
|
4985 rn = "Performance5"; |
|
4986 // break; |
|
4987 case 6: |
|
4988 // gen_helper_mtc0_performance6(t0); |
|
4989 rn = "Performance6"; |
|
4990 // break; |
|
4991 case 7: |
|
4992 // gen_helper_mtc0_performance7(t0); |
|
4993 rn = "Performance7"; |
|
4994 // break; |
|
4995 default: |
|
4996 goto die; |
|
4997 } |
|
4998 break; |
|
4999 case 26: |
|
5000 /* ignored */ |
|
5001 rn = "ECC"; |
|
5002 break; |
|
5003 case 27: |
|
5004 switch (sel) { |
|
5005 case 0 ... 3: |
|
5006 /* ignored */ |
|
5007 rn = "CacheErr"; |
|
5008 break; |
|
5009 default: |
|
5010 goto die; |
|
5011 } |
|
5012 break; |
|
5013 case 28: |
|
5014 switch (sel) { |
|
5015 case 0: |
|
5016 case 2: |
|
5017 case 4: |
|
5018 case 6: |
|
5019 gen_helper_mtc0_taglo(t0); |
|
5020 rn = "TagLo"; |
|
5021 break; |
|
5022 case 1: |
|
5023 case 3: |
|
5024 case 5: |
|
5025 case 7: |
|
5026 gen_helper_mtc0_datalo(t0); |
|
5027 rn = "DataLo"; |
|
5028 break; |
|
5029 default: |
|
5030 goto die; |
|
5031 } |
|
5032 break; |
|
5033 case 29: |
|
5034 switch (sel) { |
|
5035 case 0: |
|
5036 case 2: |
|
5037 case 4: |
|
5038 case 6: |
|
5039 gen_helper_mtc0_taghi(t0); |
|
5040 rn = "TagHi"; |
|
5041 break; |
|
5042 case 1: |
|
5043 case 3: |
|
5044 case 5: |
|
5045 case 7: |
|
5046 gen_helper_mtc0_datahi(t0); |
|
5047 rn = "DataHi"; |
|
5048 break; |
|
5049 default: |
|
5050 rn = "invalid sel"; |
|
5051 goto die; |
|
5052 } |
|
5053 break; |
|
5054 case 30: |
|
5055 switch (sel) { |
|
5056 case 0: |
|
5057 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC)); |
|
5058 rn = "ErrorEPC"; |
|
5059 break; |
|
5060 default: |
|
5061 goto die; |
|
5062 } |
|
5063 break; |
|
5064 case 31: |
|
5065 switch (sel) { |
|
5066 case 0: |
|
5067 /* EJTAG support */ |
|
5068 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE)); |
|
5069 rn = "DESAVE"; |
|
5070 break; |
|
5071 default: |
|
5072 goto die; |
|
5073 } |
|
5074 /* Stop translation as we may have switched the execution mode */ |
|
5075 ctx->bstate = BS_STOP; |
|
5076 break; |
|
5077 default: |
|
5078 goto die; |
|
5079 } |
|
5080 #if defined MIPS_DEBUG_DISAS |
|
5081 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
5082 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n", |
|
5083 rn, reg, sel); |
|
5084 } |
|
5085 #endif |
|
5086 /* For simplicity assume that all writes can cause interrupts. */ |
|
5087 if (use_icount) { |
|
5088 gen_io_end(); |
|
5089 ctx->bstate = BS_STOP; |
|
5090 } |
|
5091 return; |
|
5092 |
|
5093 die: |
|
5094 #if defined MIPS_DEBUG_DISAS |
|
5095 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
5096 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n", |
|
5097 rn, reg, sel); |
|
5098 } |
|
5099 #endif |
|
5100 generate_exception(ctx, EXCP_RI); |
|
5101 } |
|
5102 #endif /* TARGET_MIPS64 */ |
|
5103 |
|
5104 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd, |
|
5105 int u, int sel, int h) |
|
5106 { |
|
5107 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); |
|
5108 TCGv t0 = tcg_temp_local_new(); |
|
5109 |
|
5110 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 && |
|
5111 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) != |
|
5112 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) |
|
5113 tcg_gen_movi_tl(t0, -1); |
|
5114 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) > |
|
5115 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) |
|
5116 tcg_gen_movi_tl(t0, -1); |
|
5117 else if (u == 0) { |
|
5118 switch (rt) { |
|
5119 case 2: |
|
5120 switch (sel) { |
|
5121 case 1: |
|
5122 gen_helper_mftc0_tcstatus(t0); |
|
5123 break; |
|
5124 case 2: |
|
5125 gen_helper_mftc0_tcbind(t0); |
|
5126 break; |
|
5127 case 3: |
|
5128 gen_helper_mftc0_tcrestart(t0); |
|
5129 break; |
|
5130 case 4: |
|
5131 gen_helper_mftc0_tchalt(t0); |
|
5132 break; |
|
5133 case 5: |
|
5134 gen_helper_mftc0_tccontext(t0); |
|
5135 break; |
|
5136 case 6: |
|
5137 gen_helper_mftc0_tcschedule(t0); |
|
5138 break; |
|
5139 case 7: |
|
5140 gen_helper_mftc0_tcschefback(t0); |
|
5141 break; |
|
5142 default: |
|
5143 gen_mfc0(env, ctx, t0, rt, sel); |
|
5144 break; |
|
5145 } |
|
5146 break; |
|
5147 case 10: |
|
5148 switch (sel) { |
|
5149 case 0: |
|
5150 gen_helper_mftc0_entryhi(t0); |
|
5151 break; |
|
5152 default: |
|
5153 gen_mfc0(env, ctx, t0, rt, sel); |
|
5154 break; |
|
5155 } |
|
5156 case 12: |
|
5157 switch (sel) { |
|
5158 case 0: |
|
5159 gen_helper_mftc0_status(t0); |
|
5160 break; |
|
5161 default: |
|
5162 gen_mfc0(env, ctx, t0, rt, sel); |
|
5163 break; |
|
5164 } |
|
5165 case 23: |
|
5166 switch (sel) { |
|
5167 case 0: |
|
5168 gen_helper_mftc0_debug(t0); |
|
5169 break; |
|
5170 default: |
|
5171 gen_mfc0(env, ctx, t0, rt, sel); |
|
5172 break; |
|
5173 } |
|
5174 break; |
|
5175 default: |
|
5176 gen_mfc0(env, ctx, t0, rt, sel); |
|
5177 } |
|
5178 } else switch (sel) { |
|
5179 /* GPR registers. */ |
|
5180 case 0: |
|
5181 gen_helper_1i(mftgpr, t0, rt); |
|
5182 break; |
|
5183 /* Auxiliary CPU registers */ |
|
5184 case 1: |
|
5185 switch (rt) { |
|
5186 case 0: |
|
5187 gen_helper_1i(mftlo, t0, 0); |
|
5188 break; |
|
5189 case 1: |
|
5190 gen_helper_1i(mfthi, t0, 0); |
|
5191 break; |
|
5192 case 2: |
|
5193 gen_helper_1i(mftacx, t0, 0); |
|
5194 break; |
|
5195 case 4: |
|
5196 gen_helper_1i(mftlo, t0, 1); |
|
5197 break; |
|
5198 case 5: |
|
5199 gen_helper_1i(mfthi, t0, 1); |
|
5200 break; |
|
5201 case 6: |
|
5202 gen_helper_1i(mftacx, t0, 1); |
|
5203 break; |
|
5204 case 8: |
|
5205 gen_helper_1i(mftlo, t0, 2); |
|
5206 break; |
|
5207 case 9: |
|
5208 gen_helper_1i(mfthi, t0, 2); |
|
5209 break; |
|
5210 case 10: |
|
5211 gen_helper_1i(mftacx, t0, 2); |
|
5212 break; |
|
5213 case 12: |
|
5214 gen_helper_1i(mftlo, t0, 3); |
|
5215 break; |
|
5216 case 13: |
|
5217 gen_helper_1i(mfthi, t0, 3); |
|
5218 break; |
|
5219 case 14: |
|
5220 gen_helper_1i(mftacx, t0, 3); |
|
5221 break; |
|
5222 case 16: |
|
5223 gen_helper_mftdsp(t0); |
|
5224 break; |
|
5225 default: |
|
5226 goto die; |
|
5227 } |
|
5228 break; |
|
5229 /* Floating point (COP1). */ |
|
5230 case 2: |
|
5231 /* XXX: For now we support only a single FPU context. */ |
|
5232 if (h == 0) { |
|
5233 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
5234 |
|
5235 gen_load_fpr32(fp0, rt); |
|
5236 tcg_gen_ext_i32_tl(t0, fp0); |
|
5237 tcg_temp_free_i32(fp0); |
|
5238 } else { |
|
5239 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
5240 |
|
5241 gen_load_fpr32h(fp0, rt); |
|
5242 tcg_gen_ext_i32_tl(t0, fp0); |
|
5243 tcg_temp_free_i32(fp0); |
|
5244 } |
|
5245 break; |
|
5246 case 3: |
|
5247 /* XXX: For now we support only a single FPU context. */ |
|
5248 gen_helper_1i(cfc1, t0, rt); |
|
5249 break; |
|
5250 /* COP2: Not implemented. */ |
|
5251 case 4: |
|
5252 case 5: |
|
5253 /* fall through */ |
|
5254 default: |
|
5255 goto die; |
|
5256 } |
|
5257 #if defined MIPS_DEBUG_DISAS |
|
5258 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
5259 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n", |
|
5260 rt, u, sel, h); |
|
5261 } |
|
5262 #endif |
|
5263 gen_store_gpr(t0, rd); |
|
5264 tcg_temp_free(t0); |
|
5265 return; |
|
5266 |
|
5267 die: |
|
5268 tcg_temp_free(t0); |
|
5269 #if defined MIPS_DEBUG_DISAS |
|
5270 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
5271 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n", |
|
5272 rt, u, sel, h); |
|
5273 } |
|
5274 #endif |
|
5275 generate_exception(ctx, EXCP_RI); |
|
5276 } |
|
5277 |
|
5278 static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt, |
|
5279 int u, int sel, int h) |
|
5280 { |
|
5281 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); |
|
5282 TCGv t0 = tcg_temp_local_new(); |
|
5283 |
|
5284 gen_load_gpr(t0, rt); |
|
5285 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 && |
|
5286 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) != |
|
5287 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) |
|
5288 /* NOP */ ; |
|
5289 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) > |
|
5290 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) |
|
5291 /* NOP */ ; |
|
5292 else if (u == 0) { |
|
5293 switch (rd) { |
|
5294 case 2: |
|
5295 switch (sel) { |
|
5296 case 1: |
|
5297 gen_helper_mttc0_tcstatus(t0); |
|
5298 break; |
|
5299 case 2: |
|
5300 gen_helper_mttc0_tcbind(t0); |
|
5301 break; |
|
5302 case 3: |
|
5303 gen_helper_mttc0_tcrestart(t0); |
|
5304 break; |
|
5305 case 4: |
|
5306 gen_helper_mttc0_tchalt(t0); |
|
5307 break; |
|
5308 case 5: |
|
5309 gen_helper_mttc0_tccontext(t0); |
|
5310 break; |
|
5311 case 6: |
|
5312 gen_helper_mttc0_tcschedule(t0); |
|
5313 break; |
|
5314 case 7: |
|
5315 gen_helper_mttc0_tcschefback(t0); |
|
5316 break; |
|
5317 default: |
|
5318 gen_mtc0(env, ctx, t0, rd, sel); |
|
5319 break; |
|
5320 } |
|
5321 break; |
|
5322 case 10: |
|
5323 switch (sel) { |
|
5324 case 0: |
|
5325 gen_helper_mttc0_entryhi(t0); |
|
5326 break; |
|
5327 default: |
|
5328 gen_mtc0(env, ctx, t0, rd, sel); |
|
5329 break; |
|
5330 } |
|
5331 case 12: |
|
5332 switch (sel) { |
|
5333 case 0: |
|
5334 gen_helper_mttc0_status(t0); |
|
5335 break; |
|
5336 default: |
|
5337 gen_mtc0(env, ctx, t0, rd, sel); |
|
5338 break; |
|
5339 } |
|
5340 case 23: |
|
5341 switch (sel) { |
|
5342 case 0: |
|
5343 gen_helper_mttc0_debug(t0); |
|
5344 break; |
|
5345 default: |
|
5346 gen_mtc0(env, ctx, t0, rd, sel); |
|
5347 break; |
|
5348 } |
|
5349 break; |
|
5350 default: |
|
5351 gen_mtc0(env, ctx, t0, rd, sel); |
|
5352 } |
|
5353 } else switch (sel) { |
|
5354 /* GPR registers. */ |
|
5355 case 0: |
|
5356 gen_helper_1i(mttgpr, t0, rd); |
|
5357 break; |
|
5358 /* Auxiliary CPU registers */ |
|
5359 case 1: |
|
5360 switch (rd) { |
|
5361 case 0: |
|
5362 gen_helper_1i(mttlo, t0, 0); |
|
5363 break; |
|
5364 case 1: |
|
5365 gen_helper_1i(mtthi, t0, 0); |
|
5366 break; |
|
5367 case 2: |
|
5368 gen_helper_1i(mttacx, t0, 0); |
|
5369 break; |
|
5370 case 4: |
|
5371 gen_helper_1i(mttlo, t0, 1); |
|
5372 break; |
|
5373 case 5: |
|
5374 gen_helper_1i(mtthi, t0, 1); |
|
5375 break; |
|
5376 case 6: |
|
5377 gen_helper_1i(mttacx, t0, 1); |
|
5378 break; |
|
5379 case 8: |
|
5380 gen_helper_1i(mttlo, t0, 2); |
|
5381 break; |
|
5382 case 9: |
|
5383 gen_helper_1i(mtthi, t0, 2); |
|
5384 break; |
|
5385 case 10: |
|
5386 gen_helper_1i(mttacx, t0, 2); |
|
5387 break; |
|
5388 case 12: |
|
5389 gen_helper_1i(mttlo, t0, 3); |
|
5390 break; |
|
5391 case 13: |
|
5392 gen_helper_1i(mtthi, t0, 3); |
|
5393 break; |
|
5394 case 14: |
|
5395 gen_helper_1i(mttacx, t0, 3); |
|
5396 break; |
|
5397 case 16: |
|
5398 gen_helper_mttdsp(t0); |
|
5399 break; |
|
5400 default: |
|
5401 goto die; |
|
5402 } |
|
5403 break; |
|
5404 /* Floating point (COP1). */ |
|
5405 case 2: |
|
5406 /* XXX: For now we support only a single FPU context. */ |
|
5407 if (h == 0) { |
|
5408 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
5409 |
|
5410 tcg_gen_trunc_tl_i32(fp0, t0); |
|
5411 gen_store_fpr32(fp0, rd); |
|
5412 tcg_temp_free_i32(fp0); |
|
5413 } else { |
|
5414 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
5415 |
|
5416 tcg_gen_trunc_tl_i32(fp0, t0); |
|
5417 gen_store_fpr32h(fp0, rd); |
|
5418 tcg_temp_free_i32(fp0); |
|
5419 } |
|
5420 break; |
|
5421 case 3: |
|
5422 /* XXX: For now we support only a single FPU context. */ |
|
5423 gen_helper_1i(ctc1, t0, rd); |
|
5424 break; |
|
5425 /* COP2: Not implemented. */ |
|
5426 case 4: |
|
5427 case 5: |
|
5428 /* fall through */ |
|
5429 default: |
|
5430 goto die; |
|
5431 } |
|
5432 #if defined MIPS_DEBUG_DISAS |
|
5433 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
5434 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n", |
|
5435 rd, u, sel, h); |
|
5436 } |
|
5437 #endif |
|
5438 tcg_temp_free(t0); |
|
5439 return; |
|
5440 |
|
5441 die: |
|
5442 tcg_temp_free(t0); |
|
5443 #if defined MIPS_DEBUG_DISAS |
|
5444 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
5445 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n", |
|
5446 rd, u, sel, h); |
|
5447 } |
|
5448 #endif |
|
5449 generate_exception(ctx, EXCP_RI); |
|
5450 } |
|
5451 |
|
5452 static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd) |
|
5453 { |
|
5454 const char *opn = "ldst"; |
|
5455 |
|
5456 switch (opc) { |
|
5457 case OPC_MFC0: |
|
5458 if (rt == 0) { |
|
5459 /* Treat as NOP. */ |
|
5460 return; |
|
5461 } |
|
5462 { |
|
5463 TCGv t0 = tcg_temp_local_new(); |
|
5464 |
|
5465 gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7); |
|
5466 gen_store_gpr(t0, rt); |
|
5467 tcg_temp_free(t0); |
|
5468 } |
|
5469 opn = "mfc0"; |
|
5470 break; |
|
5471 case OPC_MTC0: |
|
5472 { |
|
5473 TCGv t0 = tcg_temp_local_new(); |
|
5474 |
|
5475 gen_load_gpr(t0, rt); |
|
5476 save_cpu_state(ctx, 1); |
|
5477 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7); |
|
5478 tcg_temp_free(t0); |
|
5479 } |
|
5480 opn = "mtc0"; |
|
5481 break; |
|
5482 #if defined(TARGET_MIPS64) |
|
5483 case OPC_DMFC0: |
|
5484 check_insn(env, ctx, ISA_MIPS3); |
|
5485 if (rt == 0) { |
|
5486 /* Treat as NOP. */ |
|
5487 return; |
|
5488 } |
|
5489 { |
|
5490 TCGv t0 = tcg_temp_local_new(); |
|
5491 |
|
5492 gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7); |
|
5493 gen_store_gpr(t0, rt); |
|
5494 tcg_temp_free(t0); |
|
5495 } |
|
5496 opn = "dmfc0"; |
|
5497 break; |
|
5498 case OPC_DMTC0: |
|
5499 check_insn(env, ctx, ISA_MIPS3); |
|
5500 { |
|
5501 TCGv t0 = tcg_temp_local_new(); |
|
5502 |
|
5503 gen_load_gpr(t0, rt); |
|
5504 save_cpu_state(ctx, 1); |
|
5505 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7); |
|
5506 tcg_temp_free(t0); |
|
5507 } |
|
5508 opn = "dmtc0"; |
|
5509 break; |
|
5510 #endif |
|
5511 case OPC_MFTR: |
|
5512 check_insn(env, ctx, ASE_MT); |
|
5513 if (rd == 0) { |
|
5514 /* Treat as NOP. */ |
|
5515 return; |
|
5516 } |
|
5517 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1, |
|
5518 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1); |
|
5519 opn = "mftr"; |
|
5520 break; |
|
5521 case OPC_MTTR: |
|
5522 check_insn(env, ctx, ASE_MT); |
|
5523 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1, |
|
5524 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1); |
|
5525 opn = "mttr"; |
|
5526 break; |
|
5527 case OPC_TLBWI: |
|
5528 opn = "tlbwi"; |
|
5529 if (!env->tlb->do_tlbwi) |
|
5530 goto die; |
|
5531 gen_helper_tlbwi(); |
|
5532 break; |
|
5533 case OPC_TLBWR: |
|
5534 opn = "tlbwr"; |
|
5535 if (!env->tlb->do_tlbwr) |
|
5536 goto die; |
|
5537 gen_helper_tlbwr(); |
|
5538 break; |
|
5539 case OPC_TLBP: |
|
5540 opn = "tlbp"; |
|
5541 if (!env->tlb->do_tlbp) |
|
5542 goto die; |
|
5543 gen_helper_tlbp(); |
|
5544 break; |
|
5545 case OPC_TLBR: |
|
5546 opn = "tlbr"; |
|
5547 if (!env->tlb->do_tlbr) |
|
5548 goto die; |
|
5549 gen_helper_tlbr(); |
|
5550 break; |
|
5551 case OPC_ERET: |
|
5552 opn = "eret"; |
|
5553 check_insn(env, ctx, ISA_MIPS2); |
|
5554 save_cpu_state(ctx, 1); |
|
5555 gen_helper_eret(); |
|
5556 ctx->bstate = BS_EXCP; |
|
5557 break; |
|
5558 case OPC_DERET: |
|
5559 opn = "deret"; |
|
5560 check_insn(env, ctx, ISA_MIPS32); |
|
5561 if (!(ctx->hflags & MIPS_HFLAG_DM)) { |
|
5562 MIPS_INVAL(opn); |
|
5563 generate_exception(ctx, EXCP_RI); |
|
5564 } else { |
|
5565 save_cpu_state(ctx, 1); |
|
5566 gen_helper_deret(); |
|
5567 ctx->bstate = BS_EXCP; |
|
5568 } |
|
5569 break; |
|
5570 case OPC_WAIT: |
|
5571 opn = "wait"; |
|
5572 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32); |
|
5573 /* If we get an exception, we want to restart at next instruction */ |
|
5574 ctx->pc += 4; |
|
5575 save_cpu_state(ctx, 1); |
|
5576 ctx->pc -= 4; |
|
5577 gen_helper_wait(); |
|
5578 ctx->bstate = BS_EXCP; |
|
5579 break; |
|
5580 default: |
|
5581 die: |
|
5582 MIPS_INVAL(opn); |
|
5583 generate_exception(ctx, EXCP_RI); |
|
5584 return; |
|
5585 } |
|
5586 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd); |
|
5587 } |
|
5588 #endif /* !CONFIG_USER_ONLY */ |
|
5589 |
|
5590 /* CP1 Branches (before delay slot) */ |
|
5591 static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op, |
|
5592 int32_t cc, int32_t offset) |
|
5593 { |
|
5594 target_ulong btarget; |
|
5595 const char *opn = "cp1 cond branch"; |
|
5596 TCGv_i32 t0 = tcg_temp_new_i32(); |
|
5597 |
|
5598 if (cc != 0) |
|
5599 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32); |
|
5600 |
|
5601 btarget = ctx->pc + 4 + offset; |
|
5602 |
|
5603 switch (op) { |
|
5604 case OPC_BC1F: |
|
5605 { |
|
5606 int l1 = gen_new_label(); |
|
5607 int l2 = gen_new_label(); |
|
5608 |
|
5609 get_fp_cond(t0); |
|
5610 tcg_gen_andi_i32(t0, t0, 0x1 << cc); |
|
5611 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1); |
|
5612 tcg_gen_movi_i32(bcond, 0); |
|
5613 tcg_gen_br(l2); |
|
5614 gen_set_label(l1); |
|
5615 tcg_gen_movi_i32(bcond, 1); |
|
5616 gen_set_label(l2); |
|
5617 } |
|
5618 opn = "bc1f"; |
|
5619 goto not_likely; |
|
5620 case OPC_BC1FL: |
|
5621 { |
|
5622 int l1 = gen_new_label(); |
|
5623 int l2 = gen_new_label(); |
|
5624 |
|
5625 get_fp_cond(t0); |
|
5626 tcg_gen_andi_i32(t0, t0, 0x1 << cc); |
|
5627 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1); |
|
5628 tcg_gen_movi_i32(bcond, 0); |
|
5629 tcg_gen_br(l2); |
|
5630 gen_set_label(l1); |
|
5631 tcg_gen_movi_i32(bcond, 1); |
|
5632 gen_set_label(l2); |
|
5633 } |
|
5634 opn = "bc1fl"; |
|
5635 goto likely; |
|
5636 case OPC_BC1T: |
|
5637 { |
|
5638 int l1 = gen_new_label(); |
|
5639 int l2 = gen_new_label(); |
|
5640 |
|
5641 get_fp_cond(t0); |
|
5642 tcg_gen_andi_i32(t0, t0, 0x1 << cc); |
|
5643 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1); |
|
5644 tcg_gen_movi_i32(bcond, 0); |
|
5645 tcg_gen_br(l2); |
|
5646 gen_set_label(l1); |
|
5647 tcg_gen_movi_i32(bcond, 1); |
|
5648 gen_set_label(l2); |
|
5649 } |
|
5650 opn = "bc1t"; |
|
5651 goto not_likely; |
|
5652 case OPC_BC1TL: |
|
5653 { |
|
5654 int l1 = gen_new_label(); |
|
5655 int l2 = gen_new_label(); |
|
5656 |
|
5657 get_fp_cond(t0); |
|
5658 tcg_gen_andi_i32(t0, t0, 0x1 << cc); |
|
5659 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1); |
|
5660 tcg_gen_movi_i32(bcond, 0); |
|
5661 tcg_gen_br(l2); |
|
5662 gen_set_label(l1); |
|
5663 tcg_gen_movi_i32(bcond, 1); |
|
5664 gen_set_label(l2); |
|
5665 } |
|
5666 opn = "bc1tl"; |
|
5667 likely: |
|
5668 ctx->hflags |= MIPS_HFLAG_BL; |
|
5669 break; |
|
5670 case OPC_BC1FANY2: |
|
5671 { |
|
5672 int l1 = gen_new_label(); |
|
5673 int l2 = gen_new_label(); |
|
5674 |
|
5675 get_fp_cond(t0); |
|
5676 tcg_gen_andi_i32(t0, t0, 0x3 << cc); |
|
5677 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1); |
|
5678 tcg_gen_movi_i32(bcond, 0); |
|
5679 tcg_gen_br(l2); |
|
5680 gen_set_label(l1); |
|
5681 tcg_gen_movi_i32(bcond, 1); |
|
5682 gen_set_label(l2); |
|
5683 } |
|
5684 opn = "bc1any2f"; |
|
5685 goto not_likely; |
|
5686 case OPC_BC1TANY2: |
|
5687 { |
|
5688 int l1 = gen_new_label(); |
|
5689 int l2 = gen_new_label(); |
|
5690 |
|
5691 get_fp_cond(t0); |
|
5692 tcg_gen_andi_i32(t0, t0, 0x3 << cc); |
|
5693 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1); |
|
5694 tcg_gen_movi_i32(bcond, 0); |
|
5695 tcg_gen_br(l2); |
|
5696 gen_set_label(l1); |
|
5697 tcg_gen_movi_i32(bcond, 1); |
|
5698 gen_set_label(l2); |
|
5699 } |
|
5700 opn = "bc1any2t"; |
|
5701 goto not_likely; |
|
5702 case OPC_BC1FANY4: |
|
5703 { |
|
5704 int l1 = gen_new_label(); |
|
5705 int l2 = gen_new_label(); |
|
5706 |
|
5707 get_fp_cond(t0); |
|
5708 tcg_gen_andi_i32(t0, t0, 0xf << cc); |
|
5709 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1); |
|
5710 tcg_gen_movi_i32(bcond, 0); |
|
5711 tcg_gen_br(l2); |
|
5712 gen_set_label(l1); |
|
5713 tcg_gen_movi_i32(bcond, 1); |
|
5714 gen_set_label(l2); |
|
5715 } |
|
5716 opn = "bc1any4f"; |
|
5717 goto not_likely; |
|
5718 case OPC_BC1TANY4: |
|
5719 { |
|
5720 int l1 = gen_new_label(); |
|
5721 int l2 = gen_new_label(); |
|
5722 |
|
5723 get_fp_cond(t0); |
|
5724 tcg_gen_andi_i32(t0, t0, 0xf << cc); |
|
5725 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1); |
|
5726 tcg_gen_movi_i32(bcond, 0); |
|
5727 tcg_gen_br(l2); |
|
5728 gen_set_label(l1); |
|
5729 tcg_gen_movi_i32(bcond, 1); |
|
5730 gen_set_label(l2); |
|
5731 } |
|
5732 opn = "bc1any4t"; |
|
5733 not_likely: |
|
5734 ctx->hflags |= MIPS_HFLAG_BC; |
|
5735 break; |
|
5736 default: |
|
5737 MIPS_INVAL(opn); |
|
5738 generate_exception (ctx, EXCP_RI); |
|
5739 goto out; |
|
5740 } |
|
5741 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn, |
|
5742 ctx->hflags, btarget); |
|
5743 ctx->btarget = btarget; |
|
5744 |
|
5745 out: |
|
5746 tcg_temp_free_i32(t0); |
|
5747 } |
|
5748 |
|
5749 /* Coprocessor 1 (FPU) */ |
|
5750 |
|
5751 #define FOP(func, fmt) (((fmt) << 21) | (func)) |
|
5752 |
|
5753 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) |
|
5754 { |
|
5755 const char *opn = "cp1 move"; |
|
5756 TCGv t0 = tcg_temp_local_new(); |
|
5757 |
|
5758 switch (opc) { |
|
5759 case OPC_MFC1: |
|
5760 { |
|
5761 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
5762 |
|
5763 gen_load_fpr32(fp0, fs); |
|
5764 tcg_gen_ext_i32_tl(t0, fp0); |
|
5765 tcg_temp_free_i32(fp0); |
|
5766 } |
|
5767 gen_store_gpr(t0, rt); |
|
5768 opn = "mfc1"; |
|
5769 break; |
|
5770 case OPC_MTC1: |
|
5771 gen_load_gpr(t0, rt); |
|
5772 { |
|
5773 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
5774 |
|
5775 tcg_gen_trunc_tl_i32(fp0, t0); |
|
5776 gen_store_fpr32(fp0, fs); |
|
5777 tcg_temp_free_i32(fp0); |
|
5778 } |
|
5779 opn = "mtc1"; |
|
5780 break; |
|
5781 case OPC_CFC1: |
|
5782 gen_helper_1i(cfc1, t0, fs); |
|
5783 gen_store_gpr(t0, rt); |
|
5784 opn = "cfc1"; |
|
5785 break; |
|
5786 case OPC_CTC1: |
|
5787 gen_load_gpr(t0, rt); |
|
5788 gen_helper_1i(ctc1, t0, fs); |
|
5789 opn = "ctc1"; |
|
5790 break; |
|
5791 case OPC_DMFC1: |
|
5792 { |
|
5793 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
5794 |
|
5795 gen_load_fpr64(ctx, fp0, fs); |
|
5796 tcg_gen_trunc_i64_tl(t0, fp0); |
|
5797 tcg_temp_free_i64(fp0); |
|
5798 } |
|
5799 gen_store_gpr(t0, rt); |
|
5800 opn = "dmfc1"; |
|
5801 break; |
|
5802 case OPC_DMTC1: |
|
5803 gen_load_gpr(t0, rt); |
|
5804 { |
|
5805 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
5806 |
|
5807 tcg_gen_extu_tl_i64(fp0, t0); |
|
5808 gen_store_fpr64(ctx, fp0, fs); |
|
5809 tcg_temp_free_i64(fp0); |
|
5810 } |
|
5811 opn = "dmtc1"; |
|
5812 break; |
|
5813 case OPC_MFHC1: |
|
5814 { |
|
5815 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
5816 |
|
5817 gen_load_fpr32h(fp0, fs); |
|
5818 tcg_gen_ext_i32_tl(t0, fp0); |
|
5819 tcg_temp_free_i32(fp0); |
|
5820 } |
|
5821 gen_store_gpr(t0, rt); |
|
5822 opn = "mfhc1"; |
|
5823 break; |
|
5824 case OPC_MTHC1: |
|
5825 gen_load_gpr(t0, rt); |
|
5826 { |
|
5827 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
5828 |
|
5829 tcg_gen_trunc_tl_i32(fp0, t0); |
|
5830 gen_store_fpr32h(fp0, fs); |
|
5831 tcg_temp_free_i32(fp0); |
|
5832 } |
|
5833 opn = "mthc1"; |
|
5834 break; |
|
5835 default: |
|
5836 MIPS_INVAL(opn); |
|
5837 generate_exception (ctx, EXCP_RI); |
|
5838 goto out; |
|
5839 } |
|
5840 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]); |
|
5841 |
|
5842 out: |
|
5843 tcg_temp_free(t0); |
|
5844 } |
|
5845 |
|
5846 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf) |
|
5847 { |
|
5848 int l1 = gen_new_label(); |
|
5849 uint32_t ccbit; |
|
5850 TCGCond cond; |
|
5851 TCGv t0 = tcg_temp_local_new(); |
|
5852 TCGv_i32 r_tmp = tcg_temp_new_i32(); |
|
5853 |
|
5854 if (cc) |
|
5855 ccbit = 1 << (24 + cc); |
|
5856 else |
|
5857 ccbit = 1 << 23; |
|
5858 if (tf) |
|
5859 cond = TCG_COND_EQ; |
|
5860 else |
|
5861 cond = TCG_COND_NE; |
|
5862 |
|
5863 gen_load_gpr(t0, rd); |
|
5864 tcg_gen_andi_i32(r_tmp, fpu_fcr31, ccbit); |
|
5865 tcg_gen_brcondi_i32(cond, r_tmp, 0, l1); |
|
5866 tcg_temp_free_i32(r_tmp); |
|
5867 gen_load_gpr(t0, rs); |
|
5868 gen_set_label(l1); |
|
5869 gen_store_gpr(t0, rd); |
|
5870 tcg_temp_free(t0); |
|
5871 } |
|
5872 |
|
5873 static inline void gen_movcf_s (int fs, int fd, int cc, int tf) |
|
5874 { |
|
5875 uint32_t ccbit; |
|
5876 int cond; |
|
5877 TCGv_i32 r_tmp1 = tcg_temp_new_i32(); |
|
5878 TCGv_i32 fp0 = tcg_temp_local_new_i32(); |
|
5879 int l1 = gen_new_label(); |
|
5880 |
|
5881 if (cc) |
|
5882 ccbit = 1 << (24 + cc); |
|
5883 else |
|
5884 ccbit = 1 << 23; |
|
5885 |
|
5886 if (tf) |
|
5887 cond = TCG_COND_EQ; |
|
5888 else |
|
5889 cond = TCG_COND_NE; |
|
5890 |
|
5891 gen_load_fpr32(fp0, fd); |
|
5892 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit); |
|
5893 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1); |
|
5894 tcg_temp_free_i32(r_tmp1); |
|
5895 gen_load_fpr32(fp0, fs); |
|
5896 gen_set_label(l1); |
|
5897 gen_store_fpr32(fp0, fd); |
|
5898 tcg_temp_free_i32(fp0); |
|
5899 } |
|
5900 |
|
5901 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf) |
|
5902 { |
|
5903 uint32_t ccbit; |
|
5904 int cond; |
|
5905 TCGv_i32 r_tmp1 = tcg_temp_new_i32(); |
|
5906 TCGv_i64 fp0 = tcg_temp_local_new_i64(); |
|
5907 int l1 = gen_new_label(); |
|
5908 |
|
5909 if (cc) |
|
5910 ccbit = 1 << (24 + cc); |
|
5911 else |
|
5912 ccbit = 1 << 23; |
|
5913 |
|
5914 if (tf) |
|
5915 cond = TCG_COND_EQ; |
|
5916 else |
|
5917 cond = TCG_COND_NE; |
|
5918 |
|
5919 gen_load_fpr64(ctx, fp0, fd); |
|
5920 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit); |
|
5921 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1); |
|
5922 tcg_temp_free_i32(r_tmp1); |
|
5923 gen_load_fpr64(ctx, fp0, fs); |
|
5924 gen_set_label(l1); |
|
5925 gen_store_fpr64(ctx, fp0, fd); |
|
5926 tcg_temp_free_i64(fp0); |
|
5927 } |
|
5928 |
|
5929 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf) |
|
5930 { |
|
5931 uint32_t ccbit1, ccbit2; |
|
5932 int cond; |
|
5933 TCGv_i32 r_tmp1 = tcg_temp_new_i32(); |
|
5934 TCGv_i32 fp0 = tcg_temp_local_new_i32(); |
|
5935 int l1 = gen_new_label(); |
|
5936 int l2 = gen_new_label(); |
|
5937 |
|
5938 if (cc) { |
|
5939 ccbit1 = 1 << (24 + cc); |
|
5940 ccbit2 = 1 << (25 + cc); |
|
5941 } else { |
|
5942 ccbit1 = 1 << 23; |
|
5943 ccbit2 = 1 << 25; |
|
5944 } |
|
5945 |
|
5946 if (tf) |
|
5947 cond = TCG_COND_EQ; |
|
5948 else |
|
5949 cond = TCG_COND_NE; |
|
5950 |
|
5951 gen_load_fpr32(fp0, fd); |
|
5952 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit1); |
|
5953 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1); |
|
5954 gen_load_fpr32(fp0, fs); |
|
5955 gen_set_label(l1); |
|
5956 gen_store_fpr32(fp0, fd); |
|
5957 |
|
5958 gen_load_fpr32h(fp0, fd); |
|
5959 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit2); |
|
5960 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l2); |
|
5961 gen_load_fpr32h(fp0, fs); |
|
5962 gen_set_label(l2); |
|
5963 gen_store_fpr32h(fp0, fd); |
|
5964 |
|
5965 tcg_temp_free_i32(r_tmp1); |
|
5966 tcg_temp_free_i32(fp0); |
|
5967 } |
|
5968 |
|
5969 |
|
5970 static void gen_farith (DisasContext *ctx, uint32_t op1, |
|
5971 int ft, int fs, int fd, int cc) |
|
5972 { |
|
5973 const char *opn = "farith"; |
|
5974 const char *condnames[] = { |
|
5975 "c.f", |
|
5976 "c.un", |
|
5977 "c.eq", |
|
5978 "c.ueq", |
|
5979 "c.olt", |
|
5980 "c.ult", |
|
5981 "c.ole", |
|
5982 "c.ule", |
|
5983 "c.sf", |
|
5984 "c.ngle", |
|
5985 "c.seq", |
|
5986 "c.ngl", |
|
5987 "c.lt", |
|
5988 "c.nge", |
|
5989 "c.le", |
|
5990 "c.ngt", |
|
5991 }; |
|
5992 const char *condnames_abs[] = { |
|
5993 "cabs.f", |
|
5994 "cabs.un", |
|
5995 "cabs.eq", |
|
5996 "cabs.ueq", |
|
5997 "cabs.olt", |
|
5998 "cabs.ult", |
|
5999 "cabs.ole", |
|
6000 "cabs.ule", |
|
6001 "cabs.sf", |
|
6002 "cabs.ngle", |
|
6003 "cabs.seq", |
|
6004 "cabs.ngl", |
|
6005 "cabs.lt", |
|
6006 "cabs.nge", |
|
6007 "cabs.le", |
|
6008 "cabs.ngt", |
|
6009 }; |
|
6010 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP; |
|
6011 uint32_t func = ctx->opcode & 0x3f; |
|
6012 |
|
6013 switch (ctx->opcode & FOP(0x3f, 0x1f)) { |
|
6014 case FOP(0, 16): |
|
6015 { |
|
6016 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6017 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
6018 |
|
6019 gen_load_fpr32(fp0, fs); |
|
6020 gen_load_fpr32(fp1, ft); |
|
6021 gen_helper_float_add_s(fp0, fp0, fp1); |
|
6022 tcg_temp_free_i32(fp1); |
|
6023 gen_store_fpr32(fp0, fd); |
|
6024 tcg_temp_free_i32(fp0); |
|
6025 } |
|
6026 opn = "add.s"; |
|
6027 optype = BINOP; |
|
6028 break; |
|
6029 case FOP(1, 16): |
|
6030 { |
|
6031 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6032 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
6033 |
|
6034 gen_load_fpr32(fp0, fs); |
|
6035 gen_load_fpr32(fp1, ft); |
|
6036 gen_helper_float_sub_s(fp0, fp0, fp1); |
|
6037 tcg_temp_free_i32(fp1); |
|
6038 gen_store_fpr32(fp0, fd); |
|
6039 tcg_temp_free_i32(fp0); |
|
6040 } |
|
6041 opn = "sub.s"; |
|
6042 optype = BINOP; |
|
6043 break; |
|
6044 case FOP(2, 16): |
|
6045 { |
|
6046 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6047 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
6048 |
|
6049 gen_load_fpr32(fp0, fs); |
|
6050 gen_load_fpr32(fp1, ft); |
|
6051 gen_helper_float_mul_s(fp0, fp0, fp1); |
|
6052 tcg_temp_free_i32(fp1); |
|
6053 gen_store_fpr32(fp0, fd); |
|
6054 tcg_temp_free_i32(fp0); |
|
6055 } |
|
6056 opn = "mul.s"; |
|
6057 optype = BINOP; |
|
6058 break; |
|
6059 case FOP(3, 16): |
|
6060 { |
|
6061 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6062 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
6063 |
|
6064 gen_load_fpr32(fp0, fs); |
|
6065 gen_load_fpr32(fp1, ft); |
|
6066 gen_helper_float_div_s(fp0, fp0, fp1); |
|
6067 tcg_temp_free_i32(fp1); |
|
6068 gen_store_fpr32(fp0, fd); |
|
6069 tcg_temp_free_i32(fp0); |
|
6070 } |
|
6071 opn = "div.s"; |
|
6072 optype = BINOP; |
|
6073 break; |
|
6074 case FOP(4, 16): |
|
6075 { |
|
6076 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6077 |
|
6078 gen_load_fpr32(fp0, fs); |
|
6079 gen_helper_float_sqrt_s(fp0, fp0); |
|
6080 gen_store_fpr32(fp0, fd); |
|
6081 tcg_temp_free_i32(fp0); |
|
6082 } |
|
6083 opn = "sqrt.s"; |
|
6084 break; |
|
6085 case FOP(5, 16): |
|
6086 { |
|
6087 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6088 |
|
6089 gen_load_fpr32(fp0, fs); |
|
6090 gen_helper_float_abs_s(fp0, fp0); |
|
6091 gen_store_fpr32(fp0, fd); |
|
6092 tcg_temp_free_i32(fp0); |
|
6093 } |
|
6094 opn = "abs.s"; |
|
6095 break; |
|
6096 case FOP(6, 16): |
|
6097 { |
|
6098 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6099 |
|
6100 gen_load_fpr32(fp0, fs); |
|
6101 gen_store_fpr32(fp0, fd); |
|
6102 tcg_temp_free_i32(fp0); |
|
6103 } |
|
6104 opn = "mov.s"; |
|
6105 break; |
|
6106 case FOP(7, 16): |
|
6107 { |
|
6108 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6109 |
|
6110 gen_load_fpr32(fp0, fs); |
|
6111 gen_helper_float_chs_s(fp0, fp0); |
|
6112 gen_store_fpr32(fp0, fd); |
|
6113 tcg_temp_free_i32(fp0); |
|
6114 } |
|
6115 opn = "neg.s"; |
|
6116 break; |
|
6117 case FOP(8, 16): |
|
6118 check_cp1_64bitmode(ctx); |
|
6119 { |
|
6120 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6121 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6122 |
|
6123 gen_load_fpr32(fp32, fs); |
|
6124 gen_helper_float_roundl_s(fp64, fp32); |
|
6125 tcg_temp_free_i32(fp32); |
|
6126 gen_store_fpr64(ctx, fp64, fd); |
|
6127 tcg_temp_free_i64(fp64); |
|
6128 } |
|
6129 opn = "round.l.s"; |
|
6130 break; |
|
6131 case FOP(9, 16): |
|
6132 check_cp1_64bitmode(ctx); |
|
6133 { |
|
6134 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6135 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6136 |
|
6137 gen_load_fpr32(fp32, fs); |
|
6138 gen_helper_float_truncl_s(fp64, fp32); |
|
6139 tcg_temp_free_i32(fp32); |
|
6140 gen_store_fpr64(ctx, fp64, fd); |
|
6141 tcg_temp_free_i64(fp64); |
|
6142 } |
|
6143 opn = "trunc.l.s"; |
|
6144 break; |
|
6145 case FOP(10, 16): |
|
6146 check_cp1_64bitmode(ctx); |
|
6147 { |
|
6148 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6149 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6150 |
|
6151 gen_load_fpr32(fp32, fs); |
|
6152 gen_helper_float_ceill_s(fp64, fp32); |
|
6153 tcg_temp_free_i32(fp32); |
|
6154 gen_store_fpr64(ctx, fp64, fd); |
|
6155 tcg_temp_free_i64(fp64); |
|
6156 } |
|
6157 opn = "ceil.l.s"; |
|
6158 break; |
|
6159 case FOP(11, 16): |
|
6160 check_cp1_64bitmode(ctx); |
|
6161 { |
|
6162 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6163 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6164 |
|
6165 gen_load_fpr32(fp32, fs); |
|
6166 gen_helper_float_floorl_s(fp64, fp32); |
|
6167 tcg_temp_free_i32(fp32); |
|
6168 gen_store_fpr64(ctx, fp64, fd); |
|
6169 tcg_temp_free_i64(fp64); |
|
6170 } |
|
6171 opn = "floor.l.s"; |
|
6172 break; |
|
6173 case FOP(12, 16): |
|
6174 { |
|
6175 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6176 |
|
6177 gen_load_fpr32(fp0, fs); |
|
6178 gen_helper_float_roundw_s(fp0, fp0); |
|
6179 gen_store_fpr32(fp0, fd); |
|
6180 tcg_temp_free_i32(fp0); |
|
6181 } |
|
6182 opn = "round.w.s"; |
|
6183 break; |
|
6184 case FOP(13, 16): |
|
6185 { |
|
6186 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6187 |
|
6188 gen_load_fpr32(fp0, fs); |
|
6189 gen_helper_float_truncw_s(fp0, fp0); |
|
6190 gen_store_fpr32(fp0, fd); |
|
6191 tcg_temp_free_i32(fp0); |
|
6192 } |
|
6193 opn = "trunc.w.s"; |
|
6194 break; |
|
6195 case FOP(14, 16): |
|
6196 { |
|
6197 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6198 |
|
6199 gen_load_fpr32(fp0, fs); |
|
6200 gen_helper_float_ceilw_s(fp0, fp0); |
|
6201 gen_store_fpr32(fp0, fd); |
|
6202 tcg_temp_free_i32(fp0); |
|
6203 } |
|
6204 opn = "ceil.w.s"; |
|
6205 break; |
|
6206 case FOP(15, 16): |
|
6207 { |
|
6208 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6209 |
|
6210 gen_load_fpr32(fp0, fs); |
|
6211 gen_helper_float_floorw_s(fp0, fp0); |
|
6212 gen_store_fpr32(fp0, fd); |
|
6213 tcg_temp_free_i32(fp0); |
|
6214 } |
|
6215 opn = "floor.w.s"; |
|
6216 break; |
|
6217 case FOP(17, 16): |
|
6218 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1); |
|
6219 opn = "movcf.s"; |
|
6220 break; |
|
6221 case FOP(18, 16): |
|
6222 { |
|
6223 int l1 = gen_new_label(); |
|
6224 TCGv t0 = tcg_temp_new(); |
|
6225 TCGv_i32 fp0 = tcg_temp_local_new_i32(); |
|
6226 |
|
6227 gen_load_gpr(t0, ft); |
|
6228 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1); |
|
6229 gen_load_fpr32(fp0, fs); |
|
6230 gen_store_fpr32(fp0, fd); |
|
6231 tcg_temp_free_i32(fp0); |
|
6232 gen_set_label(l1); |
|
6233 tcg_temp_free(t0); |
|
6234 } |
|
6235 opn = "movz.s"; |
|
6236 break; |
|
6237 case FOP(19, 16): |
|
6238 { |
|
6239 int l1 = gen_new_label(); |
|
6240 TCGv t0 = tcg_temp_new(); |
|
6241 TCGv_i32 fp0 = tcg_temp_local_new_i32(); |
|
6242 |
|
6243 gen_load_gpr(t0, ft); |
|
6244 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); |
|
6245 gen_load_fpr32(fp0, fs); |
|
6246 gen_store_fpr32(fp0, fd); |
|
6247 tcg_temp_free_i32(fp0); |
|
6248 gen_set_label(l1); |
|
6249 tcg_temp_free(t0); |
|
6250 } |
|
6251 opn = "movn.s"; |
|
6252 break; |
|
6253 case FOP(21, 16): |
|
6254 check_cop1x(ctx); |
|
6255 { |
|
6256 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6257 |
|
6258 gen_load_fpr32(fp0, fs); |
|
6259 gen_helper_float_recip_s(fp0, fp0); |
|
6260 gen_store_fpr32(fp0, fd); |
|
6261 tcg_temp_free_i32(fp0); |
|
6262 } |
|
6263 opn = "recip.s"; |
|
6264 break; |
|
6265 case FOP(22, 16): |
|
6266 check_cop1x(ctx); |
|
6267 { |
|
6268 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6269 |
|
6270 gen_load_fpr32(fp0, fs); |
|
6271 gen_helper_float_rsqrt_s(fp0, fp0); |
|
6272 gen_store_fpr32(fp0, fd); |
|
6273 tcg_temp_free_i32(fp0); |
|
6274 } |
|
6275 opn = "rsqrt.s"; |
|
6276 break; |
|
6277 case FOP(28, 16): |
|
6278 check_cp1_64bitmode(ctx); |
|
6279 { |
|
6280 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6281 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
6282 |
|
6283 gen_load_fpr32(fp0, fs); |
|
6284 gen_load_fpr32(fp1, fd); |
|
6285 gen_helper_float_recip2_s(fp0, fp0, fp1); |
|
6286 tcg_temp_free_i32(fp1); |
|
6287 gen_store_fpr32(fp0, fd); |
|
6288 tcg_temp_free_i32(fp0); |
|
6289 } |
|
6290 opn = "recip2.s"; |
|
6291 break; |
|
6292 case FOP(29, 16): |
|
6293 check_cp1_64bitmode(ctx); |
|
6294 { |
|
6295 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6296 |
|
6297 gen_load_fpr32(fp0, fs); |
|
6298 gen_helper_float_recip1_s(fp0, fp0); |
|
6299 gen_store_fpr32(fp0, fd); |
|
6300 tcg_temp_free_i32(fp0); |
|
6301 } |
|
6302 opn = "recip1.s"; |
|
6303 break; |
|
6304 case FOP(30, 16): |
|
6305 check_cp1_64bitmode(ctx); |
|
6306 { |
|
6307 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6308 |
|
6309 gen_load_fpr32(fp0, fs); |
|
6310 gen_helper_float_rsqrt1_s(fp0, fp0); |
|
6311 gen_store_fpr32(fp0, fd); |
|
6312 tcg_temp_free_i32(fp0); |
|
6313 } |
|
6314 opn = "rsqrt1.s"; |
|
6315 break; |
|
6316 case FOP(31, 16): |
|
6317 check_cp1_64bitmode(ctx); |
|
6318 { |
|
6319 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6320 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
6321 |
|
6322 gen_load_fpr32(fp0, fs); |
|
6323 gen_load_fpr32(fp1, ft); |
|
6324 gen_helper_float_rsqrt2_s(fp0, fp0, fp1); |
|
6325 tcg_temp_free_i32(fp1); |
|
6326 gen_store_fpr32(fp0, fd); |
|
6327 tcg_temp_free_i32(fp0); |
|
6328 } |
|
6329 opn = "rsqrt2.s"; |
|
6330 break; |
|
6331 case FOP(33, 16): |
|
6332 check_cp1_registers(ctx, fd); |
|
6333 { |
|
6334 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6335 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6336 |
|
6337 gen_load_fpr32(fp32, fs); |
|
6338 gen_helper_float_cvtd_s(fp64, fp32); |
|
6339 tcg_temp_free_i32(fp32); |
|
6340 gen_store_fpr64(ctx, fp64, fd); |
|
6341 tcg_temp_free_i64(fp64); |
|
6342 } |
|
6343 opn = "cvt.d.s"; |
|
6344 break; |
|
6345 case FOP(36, 16): |
|
6346 { |
|
6347 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6348 |
|
6349 gen_load_fpr32(fp0, fs); |
|
6350 gen_helper_float_cvtw_s(fp0, fp0); |
|
6351 gen_store_fpr32(fp0, fd); |
|
6352 tcg_temp_free_i32(fp0); |
|
6353 } |
|
6354 opn = "cvt.w.s"; |
|
6355 break; |
|
6356 case FOP(37, 16): |
|
6357 check_cp1_64bitmode(ctx); |
|
6358 { |
|
6359 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6360 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6361 |
|
6362 gen_load_fpr32(fp32, fs); |
|
6363 gen_helper_float_cvtl_s(fp64, fp32); |
|
6364 tcg_temp_free_i32(fp32); |
|
6365 gen_store_fpr64(ctx, fp64, fd); |
|
6366 tcg_temp_free_i64(fp64); |
|
6367 } |
|
6368 opn = "cvt.l.s"; |
|
6369 break; |
|
6370 case FOP(38, 16): |
|
6371 check_cp1_64bitmode(ctx); |
|
6372 { |
|
6373 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6374 TCGv_i32 fp32_0 = tcg_temp_new_i32(); |
|
6375 TCGv_i32 fp32_1 = tcg_temp_new_i32(); |
|
6376 |
|
6377 gen_load_fpr32(fp32_0, fs); |
|
6378 gen_load_fpr32(fp32_1, ft); |
|
6379 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1); |
|
6380 tcg_temp_free_i32(fp32_1); |
|
6381 tcg_temp_free_i32(fp32_0); |
|
6382 gen_store_fpr64(ctx, fp64, fd); |
|
6383 tcg_temp_free_i64(fp64); |
|
6384 } |
|
6385 opn = "cvt.ps.s"; |
|
6386 break; |
|
6387 case FOP(48, 16): |
|
6388 case FOP(49, 16): |
|
6389 case FOP(50, 16): |
|
6390 case FOP(51, 16): |
|
6391 case FOP(52, 16): |
|
6392 case FOP(53, 16): |
|
6393 case FOP(54, 16): |
|
6394 case FOP(55, 16): |
|
6395 case FOP(56, 16): |
|
6396 case FOP(57, 16): |
|
6397 case FOP(58, 16): |
|
6398 case FOP(59, 16): |
|
6399 case FOP(60, 16): |
|
6400 case FOP(61, 16): |
|
6401 case FOP(62, 16): |
|
6402 case FOP(63, 16): |
|
6403 { |
|
6404 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6405 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
6406 |
|
6407 gen_load_fpr32(fp0, fs); |
|
6408 gen_load_fpr32(fp1, ft); |
|
6409 if (ctx->opcode & (1 << 6)) { |
|
6410 check_cop1x(ctx); |
|
6411 gen_cmpabs_s(func-48, fp0, fp1, cc); |
|
6412 opn = condnames_abs[func-48]; |
|
6413 } else { |
|
6414 gen_cmp_s(func-48, fp0, fp1, cc); |
|
6415 opn = condnames[func-48]; |
|
6416 } |
|
6417 tcg_temp_free_i32(fp0); |
|
6418 tcg_temp_free_i32(fp1); |
|
6419 } |
|
6420 break; |
|
6421 case FOP(0, 17): |
|
6422 check_cp1_registers(ctx, fs | ft | fd); |
|
6423 { |
|
6424 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6425 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
6426 |
|
6427 gen_load_fpr64(ctx, fp0, fs); |
|
6428 gen_load_fpr64(ctx, fp1, ft); |
|
6429 gen_helper_float_add_d(fp0, fp0, fp1); |
|
6430 tcg_temp_free_i64(fp1); |
|
6431 gen_store_fpr64(ctx, fp0, fd); |
|
6432 tcg_temp_free_i64(fp0); |
|
6433 } |
|
6434 opn = "add.d"; |
|
6435 optype = BINOP; |
|
6436 break; |
|
6437 case FOP(1, 17): |
|
6438 check_cp1_registers(ctx, fs | ft | fd); |
|
6439 { |
|
6440 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6441 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
6442 |
|
6443 gen_load_fpr64(ctx, fp0, fs); |
|
6444 gen_load_fpr64(ctx, fp1, ft); |
|
6445 gen_helper_float_sub_d(fp0, fp0, fp1); |
|
6446 tcg_temp_free_i64(fp1); |
|
6447 gen_store_fpr64(ctx, fp0, fd); |
|
6448 tcg_temp_free_i64(fp0); |
|
6449 } |
|
6450 opn = "sub.d"; |
|
6451 optype = BINOP; |
|
6452 break; |
|
6453 case FOP(2, 17): |
|
6454 check_cp1_registers(ctx, fs | ft | fd); |
|
6455 { |
|
6456 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6457 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
6458 |
|
6459 gen_load_fpr64(ctx, fp0, fs); |
|
6460 gen_load_fpr64(ctx, fp1, ft); |
|
6461 gen_helper_float_mul_d(fp0, fp0, fp1); |
|
6462 tcg_temp_free_i64(fp1); |
|
6463 gen_store_fpr64(ctx, fp0, fd); |
|
6464 tcg_temp_free_i64(fp0); |
|
6465 } |
|
6466 opn = "mul.d"; |
|
6467 optype = BINOP; |
|
6468 break; |
|
6469 case FOP(3, 17): |
|
6470 check_cp1_registers(ctx, fs | ft | fd); |
|
6471 { |
|
6472 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6473 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
6474 |
|
6475 gen_load_fpr64(ctx, fp0, fs); |
|
6476 gen_load_fpr64(ctx, fp1, ft); |
|
6477 gen_helper_float_div_d(fp0, fp0, fp1); |
|
6478 tcg_temp_free_i64(fp1); |
|
6479 gen_store_fpr64(ctx, fp0, fd); |
|
6480 tcg_temp_free_i64(fp0); |
|
6481 } |
|
6482 opn = "div.d"; |
|
6483 optype = BINOP; |
|
6484 break; |
|
6485 case FOP(4, 17): |
|
6486 check_cp1_registers(ctx, fs | fd); |
|
6487 { |
|
6488 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6489 |
|
6490 gen_load_fpr64(ctx, fp0, fs); |
|
6491 gen_helper_float_sqrt_d(fp0, fp0); |
|
6492 gen_store_fpr64(ctx, fp0, fd); |
|
6493 tcg_temp_free_i64(fp0); |
|
6494 } |
|
6495 opn = "sqrt.d"; |
|
6496 break; |
|
6497 case FOP(5, 17): |
|
6498 check_cp1_registers(ctx, fs | fd); |
|
6499 { |
|
6500 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6501 |
|
6502 gen_load_fpr64(ctx, fp0, fs); |
|
6503 gen_helper_float_abs_d(fp0, fp0); |
|
6504 gen_store_fpr64(ctx, fp0, fd); |
|
6505 tcg_temp_free_i64(fp0); |
|
6506 } |
|
6507 opn = "abs.d"; |
|
6508 break; |
|
6509 case FOP(6, 17): |
|
6510 check_cp1_registers(ctx, fs | fd); |
|
6511 { |
|
6512 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6513 |
|
6514 gen_load_fpr64(ctx, fp0, fs); |
|
6515 gen_store_fpr64(ctx, fp0, fd); |
|
6516 tcg_temp_free_i64(fp0); |
|
6517 } |
|
6518 opn = "mov.d"; |
|
6519 break; |
|
6520 case FOP(7, 17): |
|
6521 check_cp1_registers(ctx, fs | fd); |
|
6522 { |
|
6523 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6524 |
|
6525 gen_load_fpr64(ctx, fp0, fs); |
|
6526 gen_helper_float_chs_d(fp0, fp0); |
|
6527 gen_store_fpr64(ctx, fp0, fd); |
|
6528 tcg_temp_free_i64(fp0); |
|
6529 } |
|
6530 opn = "neg.d"; |
|
6531 break; |
|
6532 case FOP(8, 17): |
|
6533 check_cp1_64bitmode(ctx); |
|
6534 { |
|
6535 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6536 |
|
6537 gen_load_fpr64(ctx, fp0, fs); |
|
6538 gen_helper_float_roundl_d(fp0, fp0); |
|
6539 gen_store_fpr64(ctx, fp0, fd); |
|
6540 tcg_temp_free_i64(fp0); |
|
6541 } |
|
6542 opn = "round.l.d"; |
|
6543 break; |
|
6544 case FOP(9, 17): |
|
6545 check_cp1_64bitmode(ctx); |
|
6546 { |
|
6547 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6548 |
|
6549 gen_load_fpr64(ctx, fp0, fs); |
|
6550 gen_helper_float_truncl_d(fp0, fp0); |
|
6551 gen_store_fpr64(ctx, fp0, fd); |
|
6552 tcg_temp_free_i64(fp0); |
|
6553 } |
|
6554 opn = "trunc.l.d"; |
|
6555 break; |
|
6556 case FOP(10, 17): |
|
6557 check_cp1_64bitmode(ctx); |
|
6558 { |
|
6559 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6560 |
|
6561 gen_load_fpr64(ctx, fp0, fs); |
|
6562 gen_helper_float_ceill_d(fp0, fp0); |
|
6563 gen_store_fpr64(ctx, fp0, fd); |
|
6564 tcg_temp_free_i64(fp0); |
|
6565 } |
|
6566 opn = "ceil.l.d"; |
|
6567 break; |
|
6568 case FOP(11, 17): |
|
6569 check_cp1_64bitmode(ctx); |
|
6570 { |
|
6571 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6572 |
|
6573 gen_load_fpr64(ctx, fp0, fs); |
|
6574 gen_helper_float_floorl_d(fp0, fp0); |
|
6575 gen_store_fpr64(ctx, fp0, fd); |
|
6576 tcg_temp_free_i64(fp0); |
|
6577 } |
|
6578 opn = "floor.l.d"; |
|
6579 break; |
|
6580 case FOP(12, 17): |
|
6581 check_cp1_registers(ctx, fs); |
|
6582 { |
|
6583 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6584 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6585 |
|
6586 gen_load_fpr64(ctx, fp64, fs); |
|
6587 gen_helper_float_roundw_d(fp32, fp64); |
|
6588 tcg_temp_free_i64(fp64); |
|
6589 gen_store_fpr32(fp32, fd); |
|
6590 tcg_temp_free_i32(fp32); |
|
6591 } |
|
6592 opn = "round.w.d"; |
|
6593 break; |
|
6594 case FOP(13, 17): |
|
6595 check_cp1_registers(ctx, fs); |
|
6596 { |
|
6597 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6598 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6599 |
|
6600 gen_load_fpr64(ctx, fp64, fs); |
|
6601 gen_helper_float_truncw_d(fp32, fp64); |
|
6602 tcg_temp_free_i64(fp64); |
|
6603 gen_store_fpr32(fp32, fd); |
|
6604 tcg_temp_free_i32(fp32); |
|
6605 } |
|
6606 opn = "trunc.w.d"; |
|
6607 break; |
|
6608 case FOP(14, 17): |
|
6609 check_cp1_registers(ctx, fs); |
|
6610 { |
|
6611 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6612 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6613 |
|
6614 gen_load_fpr64(ctx, fp64, fs); |
|
6615 gen_helper_float_ceilw_d(fp32, fp64); |
|
6616 tcg_temp_free_i64(fp64); |
|
6617 gen_store_fpr32(fp32, fd); |
|
6618 tcg_temp_free_i32(fp32); |
|
6619 } |
|
6620 opn = "ceil.w.d"; |
|
6621 break; |
|
6622 case FOP(15, 17): |
|
6623 check_cp1_registers(ctx, fs); |
|
6624 { |
|
6625 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6626 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6627 |
|
6628 gen_load_fpr64(ctx, fp64, fs); |
|
6629 gen_helper_float_floorw_d(fp32, fp64); |
|
6630 tcg_temp_free_i64(fp64); |
|
6631 gen_store_fpr32(fp32, fd); |
|
6632 tcg_temp_free_i32(fp32); |
|
6633 } |
|
6634 opn = "floor.w.d"; |
|
6635 break; |
|
6636 case FOP(17, 17): |
|
6637 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1); |
|
6638 opn = "movcf.d"; |
|
6639 break; |
|
6640 case FOP(18, 17): |
|
6641 { |
|
6642 int l1 = gen_new_label(); |
|
6643 TCGv t0 = tcg_temp_new(); |
|
6644 TCGv_i64 fp0 = tcg_temp_local_new_i64(); |
|
6645 |
|
6646 gen_load_gpr(t0, ft); |
|
6647 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1); |
|
6648 gen_load_fpr64(ctx, fp0, fs); |
|
6649 gen_store_fpr64(ctx, fp0, fd); |
|
6650 tcg_temp_free_i64(fp0); |
|
6651 gen_set_label(l1); |
|
6652 tcg_temp_free(t0); |
|
6653 } |
|
6654 opn = "movz.d"; |
|
6655 break; |
|
6656 case FOP(19, 17): |
|
6657 { |
|
6658 int l1 = gen_new_label(); |
|
6659 TCGv t0 = tcg_temp_new(); |
|
6660 TCGv_i64 fp0 = tcg_temp_local_new_i64(); |
|
6661 |
|
6662 gen_load_gpr(t0, ft); |
|
6663 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); |
|
6664 gen_load_fpr64(ctx, fp0, fs); |
|
6665 gen_store_fpr64(ctx, fp0, fd); |
|
6666 tcg_temp_free_i64(fp0); |
|
6667 gen_set_label(l1); |
|
6668 tcg_temp_free(t0); |
|
6669 } |
|
6670 opn = "movn.d"; |
|
6671 break; |
|
6672 case FOP(21, 17): |
|
6673 check_cp1_64bitmode(ctx); |
|
6674 { |
|
6675 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6676 |
|
6677 gen_load_fpr64(ctx, fp0, fs); |
|
6678 gen_helper_float_recip_d(fp0, fp0); |
|
6679 gen_store_fpr64(ctx, fp0, fd); |
|
6680 tcg_temp_free_i64(fp0); |
|
6681 } |
|
6682 opn = "recip.d"; |
|
6683 break; |
|
6684 case FOP(22, 17): |
|
6685 check_cp1_64bitmode(ctx); |
|
6686 { |
|
6687 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6688 |
|
6689 gen_load_fpr64(ctx, fp0, fs); |
|
6690 gen_helper_float_rsqrt_d(fp0, fp0); |
|
6691 gen_store_fpr64(ctx, fp0, fd); |
|
6692 tcg_temp_free_i64(fp0); |
|
6693 } |
|
6694 opn = "rsqrt.d"; |
|
6695 break; |
|
6696 case FOP(28, 17): |
|
6697 check_cp1_64bitmode(ctx); |
|
6698 { |
|
6699 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6700 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
6701 |
|
6702 gen_load_fpr64(ctx, fp0, fs); |
|
6703 gen_load_fpr64(ctx, fp1, ft); |
|
6704 gen_helper_float_recip2_d(fp0, fp0, fp1); |
|
6705 tcg_temp_free_i64(fp1); |
|
6706 gen_store_fpr64(ctx, fp0, fd); |
|
6707 tcg_temp_free_i64(fp0); |
|
6708 } |
|
6709 opn = "recip2.d"; |
|
6710 break; |
|
6711 case FOP(29, 17): |
|
6712 check_cp1_64bitmode(ctx); |
|
6713 { |
|
6714 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6715 |
|
6716 gen_load_fpr64(ctx, fp0, fs); |
|
6717 gen_helper_float_recip1_d(fp0, fp0); |
|
6718 gen_store_fpr64(ctx, fp0, fd); |
|
6719 tcg_temp_free_i64(fp0); |
|
6720 } |
|
6721 opn = "recip1.d"; |
|
6722 break; |
|
6723 case FOP(30, 17): |
|
6724 check_cp1_64bitmode(ctx); |
|
6725 { |
|
6726 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6727 |
|
6728 gen_load_fpr64(ctx, fp0, fs); |
|
6729 gen_helper_float_rsqrt1_d(fp0, fp0); |
|
6730 gen_store_fpr64(ctx, fp0, fd); |
|
6731 tcg_temp_free_i64(fp0); |
|
6732 } |
|
6733 opn = "rsqrt1.d"; |
|
6734 break; |
|
6735 case FOP(31, 17): |
|
6736 check_cp1_64bitmode(ctx); |
|
6737 { |
|
6738 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6739 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
6740 |
|
6741 gen_load_fpr64(ctx, fp0, fs); |
|
6742 gen_load_fpr64(ctx, fp1, ft); |
|
6743 gen_helper_float_rsqrt2_d(fp0, fp0, fp1); |
|
6744 tcg_temp_free_i64(fp1); |
|
6745 gen_store_fpr64(ctx, fp0, fd); |
|
6746 tcg_temp_free_i64(fp0); |
|
6747 } |
|
6748 opn = "rsqrt2.d"; |
|
6749 break; |
|
6750 case FOP(48, 17): |
|
6751 case FOP(49, 17): |
|
6752 case FOP(50, 17): |
|
6753 case FOP(51, 17): |
|
6754 case FOP(52, 17): |
|
6755 case FOP(53, 17): |
|
6756 case FOP(54, 17): |
|
6757 case FOP(55, 17): |
|
6758 case FOP(56, 17): |
|
6759 case FOP(57, 17): |
|
6760 case FOP(58, 17): |
|
6761 case FOP(59, 17): |
|
6762 case FOP(60, 17): |
|
6763 case FOP(61, 17): |
|
6764 case FOP(62, 17): |
|
6765 case FOP(63, 17): |
|
6766 { |
|
6767 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6768 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
6769 |
|
6770 gen_load_fpr64(ctx, fp0, fs); |
|
6771 gen_load_fpr64(ctx, fp1, ft); |
|
6772 if (ctx->opcode & (1 << 6)) { |
|
6773 check_cop1x(ctx); |
|
6774 check_cp1_registers(ctx, fs | ft); |
|
6775 gen_cmpabs_d(func-48, fp0, fp1, cc); |
|
6776 opn = condnames_abs[func-48]; |
|
6777 } else { |
|
6778 check_cp1_registers(ctx, fs | ft); |
|
6779 gen_cmp_d(func-48, fp0, fp1, cc); |
|
6780 opn = condnames[func-48]; |
|
6781 } |
|
6782 tcg_temp_free_i64(fp0); |
|
6783 tcg_temp_free_i64(fp1); |
|
6784 } |
|
6785 break; |
|
6786 case FOP(32, 17): |
|
6787 check_cp1_registers(ctx, fs); |
|
6788 { |
|
6789 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6790 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6791 |
|
6792 gen_load_fpr64(ctx, fp64, fs); |
|
6793 gen_helper_float_cvts_d(fp32, fp64); |
|
6794 tcg_temp_free_i64(fp64); |
|
6795 gen_store_fpr32(fp32, fd); |
|
6796 tcg_temp_free_i32(fp32); |
|
6797 } |
|
6798 opn = "cvt.s.d"; |
|
6799 break; |
|
6800 case FOP(36, 17): |
|
6801 check_cp1_registers(ctx, fs); |
|
6802 { |
|
6803 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6804 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6805 |
|
6806 gen_load_fpr64(ctx, fp64, fs); |
|
6807 gen_helper_float_cvtw_d(fp32, fp64); |
|
6808 tcg_temp_free_i64(fp64); |
|
6809 gen_store_fpr32(fp32, fd); |
|
6810 tcg_temp_free_i32(fp32); |
|
6811 } |
|
6812 opn = "cvt.w.d"; |
|
6813 break; |
|
6814 case FOP(37, 17): |
|
6815 check_cp1_64bitmode(ctx); |
|
6816 { |
|
6817 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6818 |
|
6819 gen_load_fpr64(ctx, fp0, fs); |
|
6820 gen_helper_float_cvtl_d(fp0, fp0); |
|
6821 gen_store_fpr64(ctx, fp0, fd); |
|
6822 tcg_temp_free_i64(fp0); |
|
6823 } |
|
6824 opn = "cvt.l.d"; |
|
6825 break; |
|
6826 case FOP(32, 20): |
|
6827 { |
|
6828 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
6829 |
|
6830 gen_load_fpr32(fp0, fs); |
|
6831 gen_helper_float_cvts_w(fp0, fp0); |
|
6832 gen_store_fpr32(fp0, fd); |
|
6833 tcg_temp_free_i32(fp0); |
|
6834 } |
|
6835 opn = "cvt.s.w"; |
|
6836 break; |
|
6837 case FOP(33, 20): |
|
6838 check_cp1_registers(ctx, fd); |
|
6839 { |
|
6840 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6841 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6842 |
|
6843 gen_load_fpr32(fp32, fs); |
|
6844 gen_helper_float_cvtd_w(fp64, fp32); |
|
6845 tcg_temp_free_i32(fp32); |
|
6846 gen_store_fpr64(ctx, fp64, fd); |
|
6847 tcg_temp_free_i64(fp64); |
|
6848 } |
|
6849 opn = "cvt.d.w"; |
|
6850 break; |
|
6851 case FOP(32, 21): |
|
6852 check_cp1_64bitmode(ctx); |
|
6853 { |
|
6854 TCGv_i32 fp32 = tcg_temp_new_i32(); |
|
6855 TCGv_i64 fp64 = tcg_temp_new_i64(); |
|
6856 |
|
6857 gen_load_fpr64(ctx, fp64, fs); |
|
6858 gen_helper_float_cvts_l(fp32, fp64); |
|
6859 tcg_temp_free_i64(fp64); |
|
6860 gen_store_fpr32(fp32, fd); |
|
6861 tcg_temp_free_i32(fp32); |
|
6862 } |
|
6863 opn = "cvt.s.l"; |
|
6864 break; |
|
6865 case FOP(33, 21): |
|
6866 check_cp1_64bitmode(ctx); |
|
6867 { |
|
6868 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6869 |
|
6870 gen_load_fpr64(ctx, fp0, fs); |
|
6871 gen_helper_float_cvtd_l(fp0, fp0); |
|
6872 gen_store_fpr64(ctx, fp0, fd); |
|
6873 tcg_temp_free_i64(fp0); |
|
6874 } |
|
6875 opn = "cvt.d.l"; |
|
6876 break; |
|
6877 case FOP(38, 20): |
|
6878 check_cp1_64bitmode(ctx); |
|
6879 { |
|
6880 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6881 |
|
6882 gen_load_fpr64(ctx, fp0, fs); |
|
6883 gen_helper_float_cvtps_pw(fp0, fp0); |
|
6884 gen_store_fpr64(ctx, fp0, fd); |
|
6885 tcg_temp_free_i64(fp0); |
|
6886 } |
|
6887 opn = "cvt.ps.pw"; |
|
6888 break; |
|
6889 case FOP(0, 22): |
|
6890 check_cp1_64bitmode(ctx); |
|
6891 { |
|
6892 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6893 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
6894 |
|
6895 gen_load_fpr64(ctx, fp0, fs); |
|
6896 gen_load_fpr64(ctx, fp1, ft); |
|
6897 gen_helper_float_add_ps(fp0, fp0, fp1); |
|
6898 tcg_temp_free_i64(fp1); |
|
6899 gen_store_fpr64(ctx, fp0, fd); |
|
6900 tcg_temp_free_i64(fp0); |
|
6901 } |
|
6902 opn = "add.ps"; |
|
6903 break; |
|
6904 case FOP(1, 22): |
|
6905 check_cp1_64bitmode(ctx); |
|
6906 { |
|
6907 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6908 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
6909 |
|
6910 gen_load_fpr64(ctx, fp0, fs); |
|
6911 gen_load_fpr64(ctx, fp1, ft); |
|
6912 gen_helper_float_sub_ps(fp0, fp0, fp1); |
|
6913 tcg_temp_free_i64(fp1); |
|
6914 gen_store_fpr64(ctx, fp0, fd); |
|
6915 tcg_temp_free_i64(fp0); |
|
6916 } |
|
6917 opn = "sub.ps"; |
|
6918 break; |
|
6919 case FOP(2, 22): |
|
6920 check_cp1_64bitmode(ctx); |
|
6921 { |
|
6922 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6923 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
6924 |
|
6925 gen_load_fpr64(ctx, fp0, fs); |
|
6926 gen_load_fpr64(ctx, fp1, ft); |
|
6927 gen_helper_float_mul_ps(fp0, fp0, fp1); |
|
6928 tcg_temp_free_i64(fp1); |
|
6929 gen_store_fpr64(ctx, fp0, fd); |
|
6930 tcg_temp_free_i64(fp0); |
|
6931 } |
|
6932 opn = "mul.ps"; |
|
6933 break; |
|
6934 case FOP(5, 22): |
|
6935 check_cp1_64bitmode(ctx); |
|
6936 { |
|
6937 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6938 |
|
6939 gen_load_fpr64(ctx, fp0, fs); |
|
6940 gen_helper_float_abs_ps(fp0, fp0); |
|
6941 gen_store_fpr64(ctx, fp0, fd); |
|
6942 tcg_temp_free_i64(fp0); |
|
6943 } |
|
6944 opn = "abs.ps"; |
|
6945 break; |
|
6946 case FOP(6, 22): |
|
6947 check_cp1_64bitmode(ctx); |
|
6948 { |
|
6949 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6950 |
|
6951 gen_load_fpr64(ctx, fp0, fs); |
|
6952 gen_store_fpr64(ctx, fp0, fd); |
|
6953 tcg_temp_free_i64(fp0); |
|
6954 } |
|
6955 opn = "mov.ps"; |
|
6956 break; |
|
6957 case FOP(7, 22): |
|
6958 check_cp1_64bitmode(ctx); |
|
6959 { |
|
6960 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
6961 |
|
6962 gen_load_fpr64(ctx, fp0, fs); |
|
6963 gen_helper_float_chs_ps(fp0, fp0); |
|
6964 gen_store_fpr64(ctx, fp0, fd); |
|
6965 tcg_temp_free_i64(fp0); |
|
6966 } |
|
6967 opn = "neg.ps"; |
|
6968 break; |
|
6969 case FOP(17, 22): |
|
6970 check_cp1_64bitmode(ctx); |
|
6971 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1); |
|
6972 opn = "movcf.ps"; |
|
6973 break; |
|
6974 case FOP(18, 22): |
|
6975 check_cp1_64bitmode(ctx); |
|
6976 { |
|
6977 int l1 = gen_new_label(); |
|
6978 TCGv t0 = tcg_temp_new(); |
|
6979 TCGv_i32 fp0 = tcg_temp_local_new_i32(); |
|
6980 TCGv_i32 fph0 = tcg_temp_local_new_i32(); |
|
6981 |
|
6982 gen_load_gpr(t0, ft); |
|
6983 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1); |
|
6984 gen_load_fpr32(fp0, fs); |
|
6985 gen_load_fpr32h(fph0, fs); |
|
6986 gen_store_fpr32(fp0, fd); |
|
6987 gen_store_fpr32h(fph0, fd); |
|
6988 tcg_temp_free_i32(fp0); |
|
6989 tcg_temp_free_i32(fph0); |
|
6990 gen_set_label(l1); |
|
6991 tcg_temp_free(t0); |
|
6992 } |
|
6993 opn = "movz.ps"; |
|
6994 break; |
|
6995 case FOP(19, 22): |
|
6996 check_cp1_64bitmode(ctx); |
|
6997 { |
|
6998 int l1 = gen_new_label(); |
|
6999 TCGv t0 = tcg_temp_new(); |
|
7000 TCGv_i32 fp0 = tcg_temp_local_new_i32(); |
|
7001 TCGv_i32 fph0 = tcg_temp_local_new_i32(); |
|
7002 |
|
7003 gen_load_gpr(t0, ft); |
|
7004 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); |
|
7005 gen_load_fpr32(fp0, fs); |
|
7006 gen_load_fpr32h(fph0, fs); |
|
7007 gen_store_fpr32(fp0, fd); |
|
7008 gen_store_fpr32h(fph0, fd); |
|
7009 tcg_temp_free_i32(fp0); |
|
7010 tcg_temp_free_i32(fph0); |
|
7011 gen_set_label(l1); |
|
7012 tcg_temp_free(t0); |
|
7013 } |
|
7014 opn = "movn.ps"; |
|
7015 break; |
|
7016 case FOP(24, 22): |
|
7017 check_cp1_64bitmode(ctx); |
|
7018 { |
|
7019 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7020 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7021 |
|
7022 gen_load_fpr64(ctx, fp0, ft); |
|
7023 gen_load_fpr64(ctx, fp1, fs); |
|
7024 gen_helper_float_addr_ps(fp0, fp0, fp1); |
|
7025 tcg_temp_free_i64(fp1); |
|
7026 gen_store_fpr64(ctx, fp0, fd); |
|
7027 tcg_temp_free_i64(fp0); |
|
7028 } |
|
7029 opn = "addr.ps"; |
|
7030 break; |
|
7031 case FOP(26, 22): |
|
7032 check_cp1_64bitmode(ctx); |
|
7033 { |
|
7034 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7035 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7036 |
|
7037 gen_load_fpr64(ctx, fp0, ft); |
|
7038 gen_load_fpr64(ctx, fp1, fs); |
|
7039 gen_helper_float_mulr_ps(fp0, fp0, fp1); |
|
7040 tcg_temp_free_i64(fp1); |
|
7041 gen_store_fpr64(ctx, fp0, fd); |
|
7042 tcg_temp_free_i64(fp0); |
|
7043 } |
|
7044 opn = "mulr.ps"; |
|
7045 break; |
|
7046 case FOP(28, 22): |
|
7047 check_cp1_64bitmode(ctx); |
|
7048 { |
|
7049 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7050 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7051 |
|
7052 gen_load_fpr64(ctx, fp0, fs); |
|
7053 gen_load_fpr64(ctx, fp1, fd); |
|
7054 gen_helper_float_recip2_ps(fp0, fp0, fp1); |
|
7055 tcg_temp_free_i64(fp1); |
|
7056 gen_store_fpr64(ctx, fp0, fd); |
|
7057 tcg_temp_free_i64(fp0); |
|
7058 } |
|
7059 opn = "recip2.ps"; |
|
7060 break; |
|
7061 case FOP(29, 22): |
|
7062 check_cp1_64bitmode(ctx); |
|
7063 { |
|
7064 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7065 |
|
7066 gen_load_fpr64(ctx, fp0, fs); |
|
7067 gen_helper_float_recip1_ps(fp0, fp0); |
|
7068 gen_store_fpr64(ctx, fp0, fd); |
|
7069 tcg_temp_free_i64(fp0); |
|
7070 } |
|
7071 opn = "recip1.ps"; |
|
7072 break; |
|
7073 case FOP(30, 22): |
|
7074 check_cp1_64bitmode(ctx); |
|
7075 { |
|
7076 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7077 |
|
7078 gen_load_fpr64(ctx, fp0, fs); |
|
7079 gen_helper_float_rsqrt1_ps(fp0, fp0); |
|
7080 gen_store_fpr64(ctx, fp0, fd); |
|
7081 tcg_temp_free_i64(fp0); |
|
7082 } |
|
7083 opn = "rsqrt1.ps"; |
|
7084 break; |
|
7085 case FOP(31, 22): |
|
7086 check_cp1_64bitmode(ctx); |
|
7087 { |
|
7088 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7089 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7090 |
|
7091 gen_load_fpr64(ctx, fp0, fs); |
|
7092 gen_load_fpr64(ctx, fp1, ft); |
|
7093 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1); |
|
7094 tcg_temp_free_i64(fp1); |
|
7095 gen_store_fpr64(ctx, fp0, fd); |
|
7096 tcg_temp_free_i64(fp0); |
|
7097 } |
|
7098 opn = "rsqrt2.ps"; |
|
7099 break; |
|
7100 case FOP(32, 22): |
|
7101 check_cp1_64bitmode(ctx); |
|
7102 { |
|
7103 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7104 |
|
7105 gen_load_fpr32h(fp0, fs); |
|
7106 gen_helper_float_cvts_pu(fp0, fp0); |
|
7107 gen_store_fpr32(fp0, fd); |
|
7108 tcg_temp_free_i32(fp0); |
|
7109 } |
|
7110 opn = "cvt.s.pu"; |
|
7111 break; |
|
7112 case FOP(36, 22): |
|
7113 check_cp1_64bitmode(ctx); |
|
7114 { |
|
7115 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7116 |
|
7117 gen_load_fpr64(ctx, fp0, fs); |
|
7118 gen_helper_float_cvtpw_ps(fp0, fp0); |
|
7119 gen_store_fpr64(ctx, fp0, fd); |
|
7120 tcg_temp_free_i64(fp0); |
|
7121 } |
|
7122 opn = "cvt.pw.ps"; |
|
7123 break; |
|
7124 case FOP(40, 22): |
|
7125 check_cp1_64bitmode(ctx); |
|
7126 { |
|
7127 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7128 |
|
7129 gen_load_fpr32(fp0, fs); |
|
7130 gen_helper_float_cvts_pl(fp0, fp0); |
|
7131 gen_store_fpr32(fp0, fd); |
|
7132 tcg_temp_free_i32(fp0); |
|
7133 } |
|
7134 opn = "cvt.s.pl"; |
|
7135 break; |
|
7136 case FOP(44, 22): |
|
7137 check_cp1_64bitmode(ctx); |
|
7138 { |
|
7139 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7140 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
7141 |
|
7142 gen_load_fpr32(fp0, fs); |
|
7143 gen_load_fpr32(fp1, ft); |
|
7144 gen_store_fpr32h(fp0, fd); |
|
7145 gen_store_fpr32(fp1, fd); |
|
7146 tcg_temp_free_i32(fp0); |
|
7147 tcg_temp_free_i32(fp1); |
|
7148 } |
|
7149 opn = "pll.ps"; |
|
7150 break; |
|
7151 case FOP(45, 22): |
|
7152 check_cp1_64bitmode(ctx); |
|
7153 { |
|
7154 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7155 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
7156 |
|
7157 gen_load_fpr32(fp0, fs); |
|
7158 gen_load_fpr32h(fp1, ft); |
|
7159 gen_store_fpr32(fp1, fd); |
|
7160 gen_store_fpr32h(fp0, fd); |
|
7161 tcg_temp_free_i32(fp0); |
|
7162 tcg_temp_free_i32(fp1); |
|
7163 } |
|
7164 opn = "plu.ps"; |
|
7165 break; |
|
7166 case FOP(46, 22): |
|
7167 check_cp1_64bitmode(ctx); |
|
7168 { |
|
7169 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7170 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
7171 |
|
7172 gen_load_fpr32h(fp0, fs); |
|
7173 gen_load_fpr32(fp1, ft); |
|
7174 gen_store_fpr32(fp1, fd); |
|
7175 gen_store_fpr32h(fp0, fd); |
|
7176 tcg_temp_free_i32(fp0); |
|
7177 tcg_temp_free_i32(fp1); |
|
7178 } |
|
7179 opn = "pul.ps"; |
|
7180 break; |
|
7181 case FOP(47, 22): |
|
7182 check_cp1_64bitmode(ctx); |
|
7183 { |
|
7184 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7185 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
7186 |
|
7187 gen_load_fpr32h(fp0, fs); |
|
7188 gen_load_fpr32h(fp1, ft); |
|
7189 gen_store_fpr32(fp1, fd); |
|
7190 gen_store_fpr32h(fp0, fd); |
|
7191 tcg_temp_free_i32(fp0); |
|
7192 tcg_temp_free_i32(fp1); |
|
7193 } |
|
7194 opn = "puu.ps"; |
|
7195 break; |
|
7196 case FOP(48, 22): |
|
7197 case FOP(49, 22): |
|
7198 case FOP(50, 22): |
|
7199 case FOP(51, 22): |
|
7200 case FOP(52, 22): |
|
7201 case FOP(53, 22): |
|
7202 case FOP(54, 22): |
|
7203 case FOP(55, 22): |
|
7204 case FOP(56, 22): |
|
7205 case FOP(57, 22): |
|
7206 case FOP(58, 22): |
|
7207 case FOP(59, 22): |
|
7208 case FOP(60, 22): |
|
7209 case FOP(61, 22): |
|
7210 case FOP(62, 22): |
|
7211 case FOP(63, 22): |
|
7212 check_cp1_64bitmode(ctx); |
|
7213 { |
|
7214 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7215 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7216 |
|
7217 gen_load_fpr64(ctx, fp0, fs); |
|
7218 gen_load_fpr64(ctx, fp1, ft); |
|
7219 if (ctx->opcode & (1 << 6)) { |
|
7220 gen_cmpabs_ps(func-48, fp0, fp1, cc); |
|
7221 opn = condnames_abs[func-48]; |
|
7222 } else { |
|
7223 gen_cmp_ps(func-48, fp0, fp1, cc); |
|
7224 opn = condnames[func-48]; |
|
7225 } |
|
7226 tcg_temp_free_i64(fp0); |
|
7227 tcg_temp_free_i64(fp1); |
|
7228 } |
|
7229 break; |
|
7230 default: |
|
7231 MIPS_INVAL(opn); |
|
7232 generate_exception (ctx, EXCP_RI); |
|
7233 return; |
|
7234 } |
|
7235 switch (optype) { |
|
7236 case BINOP: |
|
7237 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]); |
|
7238 break; |
|
7239 case CMPOP: |
|
7240 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]); |
|
7241 break; |
|
7242 default: |
|
7243 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]); |
|
7244 break; |
|
7245 } |
|
7246 } |
|
7247 |
|
7248 /* Coprocessor 3 (FPU) */ |
|
7249 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, |
|
7250 int fd, int fs, int base, int index) |
|
7251 { |
|
7252 const char *opn = "extended float load/store"; |
|
7253 int store = 0; |
|
7254 TCGv t0 = tcg_temp_local_new(); |
|
7255 TCGv t1 = tcg_temp_local_new(); |
|
7256 |
|
7257 if (base == 0) { |
|
7258 gen_load_gpr(t0, index); |
|
7259 } else if (index == 0) { |
|
7260 gen_load_gpr(t0, base); |
|
7261 } else { |
|
7262 gen_load_gpr(t0, base); |
|
7263 gen_load_gpr(t1, index); |
|
7264 gen_op_addr_add(ctx, t0, t1); |
|
7265 } |
|
7266 /* Don't do NOP if destination is zero: we must perform the actual |
|
7267 memory access. */ |
|
7268 switch (opc) { |
|
7269 case OPC_LWXC1: |
|
7270 check_cop1x(ctx); |
|
7271 { |
|
7272 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7273 |
|
7274 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx); |
|
7275 tcg_gen_trunc_tl_i32(fp0, t1); |
|
7276 gen_store_fpr32(fp0, fd); |
|
7277 tcg_temp_free_i32(fp0); |
|
7278 } |
|
7279 opn = "lwxc1"; |
|
7280 break; |
|
7281 case OPC_LDXC1: |
|
7282 check_cop1x(ctx); |
|
7283 check_cp1_registers(ctx, fd); |
|
7284 { |
|
7285 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7286 |
|
7287 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx); |
|
7288 gen_store_fpr64(ctx, fp0, fd); |
|
7289 tcg_temp_free_i64(fp0); |
|
7290 } |
|
7291 opn = "ldxc1"; |
|
7292 break; |
|
7293 case OPC_LUXC1: |
|
7294 check_cp1_64bitmode(ctx); |
|
7295 tcg_gen_andi_tl(t0, t0, ~0x7); |
|
7296 { |
|
7297 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7298 |
|
7299 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx); |
|
7300 gen_store_fpr64(ctx, fp0, fd); |
|
7301 tcg_temp_free_i64(fp0); |
|
7302 } |
|
7303 opn = "luxc1"; |
|
7304 break; |
|
7305 case OPC_SWXC1: |
|
7306 check_cop1x(ctx); |
|
7307 { |
|
7308 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7309 |
|
7310 gen_load_fpr32(fp0, fs); |
|
7311 tcg_gen_extu_i32_tl(t1, fp0); |
|
7312 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx); |
|
7313 tcg_temp_free_i32(fp0); |
|
7314 } |
|
7315 opn = "swxc1"; |
|
7316 store = 1; |
|
7317 break; |
|
7318 case OPC_SDXC1: |
|
7319 check_cop1x(ctx); |
|
7320 check_cp1_registers(ctx, fs); |
|
7321 { |
|
7322 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7323 |
|
7324 gen_load_fpr64(ctx, fp0, fs); |
|
7325 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx); |
|
7326 tcg_temp_free_i64(fp0); |
|
7327 } |
|
7328 opn = "sdxc1"; |
|
7329 store = 1; |
|
7330 break; |
|
7331 case OPC_SUXC1: |
|
7332 check_cp1_64bitmode(ctx); |
|
7333 tcg_gen_andi_tl(t0, t0, ~0x7); |
|
7334 { |
|
7335 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7336 |
|
7337 gen_load_fpr64(ctx, fp0, fs); |
|
7338 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx); |
|
7339 tcg_temp_free_i64(fp0); |
|
7340 } |
|
7341 opn = "suxc1"; |
|
7342 store = 1; |
|
7343 break; |
|
7344 default: |
|
7345 MIPS_INVAL(opn); |
|
7346 generate_exception(ctx, EXCP_RI); |
|
7347 tcg_temp_free(t0); |
|
7348 tcg_temp_free(t1); |
|
7349 return; |
|
7350 } |
|
7351 tcg_temp_free(t0); |
|
7352 tcg_temp_free(t1); |
|
7353 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd], |
|
7354 regnames[index], regnames[base]); |
|
7355 } |
|
7356 |
|
7357 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, |
|
7358 int fd, int fr, int fs, int ft) |
|
7359 { |
|
7360 const char *opn = "flt3_arith"; |
|
7361 |
|
7362 switch (opc) { |
|
7363 case OPC_ALNV_PS: |
|
7364 check_cp1_64bitmode(ctx); |
|
7365 { |
|
7366 TCGv t0 = tcg_temp_local_new(); |
|
7367 TCGv_i32 fp0 = tcg_temp_local_new_i32(); |
|
7368 TCGv_i32 fph0 = tcg_temp_local_new_i32(); |
|
7369 TCGv_i32 fp1 = tcg_temp_local_new_i32(); |
|
7370 TCGv_i32 fph1 = tcg_temp_local_new_i32(); |
|
7371 int l1 = gen_new_label(); |
|
7372 int l2 = gen_new_label(); |
|
7373 |
|
7374 gen_load_gpr(t0, fr); |
|
7375 tcg_gen_andi_tl(t0, t0, 0x7); |
|
7376 gen_load_fpr32(fp0, fs); |
|
7377 gen_load_fpr32h(fph0, fs); |
|
7378 gen_load_fpr32(fp1, ft); |
|
7379 gen_load_fpr32h(fph1, ft); |
|
7380 |
|
7381 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1); |
|
7382 gen_store_fpr32(fp0, fd); |
|
7383 gen_store_fpr32h(fph0, fd); |
|
7384 tcg_gen_br(l2); |
|
7385 gen_set_label(l1); |
|
7386 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2); |
|
7387 tcg_temp_free(t0); |
|
7388 #ifdef TARGET_WORDS_BIGENDIAN |
|
7389 gen_store_fpr32(fph1, fd); |
|
7390 gen_store_fpr32h(fp0, fd); |
|
7391 #else |
|
7392 gen_store_fpr32(fph0, fd); |
|
7393 gen_store_fpr32h(fp1, fd); |
|
7394 #endif |
|
7395 gen_set_label(l2); |
|
7396 tcg_temp_free_i32(fp0); |
|
7397 tcg_temp_free_i32(fph0); |
|
7398 tcg_temp_free_i32(fp1); |
|
7399 tcg_temp_free_i32(fph1); |
|
7400 } |
|
7401 opn = "alnv.ps"; |
|
7402 break; |
|
7403 case OPC_MADD_S: |
|
7404 check_cop1x(ctx); |
|
7405 { |
|
7406 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7407 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
7408 TCGv_i32 fp2 = tcg_temp_new_i32(); |
|
7409 |
|
7410 gen_load_fpr32(fp0, fs); |
|
7411 gen_load_fpr32(fp1, ft); |
|
7412 gen_load_fpr32(fp2, fr); |
|
7413 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2); |
|
7414 tcg_temp_free_i32(fp0); |
|
7415 tcg_temp_free_i32(fp1); |
|
7416 gen_store_fpr32(fp2, fd); |
|
7417 tcg_temp_free_i32(fp2); |
|
7418 } |
|
7419 opn = "madd.s"; |
|
7420 break; |
|
7421 case OPC_MADD_D: |
|
7422 check_cop1x(ctx); |
|
7423 check_cp1_registers(ctx, fd | fs | ft | fr); |
|
7424 { |
|
7425 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7426 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7427 TCGv_i64 fp2 = tcg_temp_new_i64(); |
|
7428 |
|
7429 gen_load_fpr64(ctx, fp0, fs); |
|
7430 gen_load_fpr64(ctx, fp1, ft); |
|
7431 gen_load_fpr64(ctx, fp2, fr); |
|
7432 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2); |
|
7433 tcg_temp_free_i64(fp0); |
|
7434 tcg_temp_free_i64(fp1); |
|
7435 gen_store_fpr64(ctx, fp2, fd); |
|
7436 tcg_temp_free_i64(fp2); |
|
7437 } |
|
7438 opn = "madd.d"; |
|
7439 break; |
|
7440 case OPC_MADD_PS: |
|
7441 check_cp1_64bitmode(ctx); |
|
7442 { |
|
7443 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7444 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7445 TCGv_i64 fp2 = tcg_temp_new_i64(); |
|
7446 |
|
7447 gen_load_fpr64(ctx, fp0, fs); |
|
7448 gen_load_fpr64(ctx, fp1, ft); |
|
7449 gen_load_fpr64(ctx, fp2, fr); |
|
7450 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2); |
|
7451 tcg_temp_free_i64(fp0); |
|
7452 tcg_temp_free_i64(fp1); |
|
7453 gen_store_fpr64(ctx, fp2, fd); |
|
7454 tcg_temp_free_i64(fp2); |
|
7455 } |
|
7456 opn = "madd.ps"; |
|
7457 break; |
|
7458 case OPC_MSUB_S: |
|
7459 check_cop1x(ctx); |
|
7460 { |
|
7461 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7462 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
7463 TCGv_i32 fp2 = tcg_temp_new_i32(); |
|
7464 |
|
7465 gen_load_fpr32(fp0, fs); |
|
7466 gen_load_fpr32(fp1, ft); |
|
7467 gen_load_fpr32(fp2, fr); |
|
7468 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2); |
|
7469 tcg_temp_free_i32(fp0); |
|
7470 tcg_temp_free_i32(fp1); |
|
7471 gen_store_fpr32(fp2, fd); |
|
7472 tcg_temp_free_i32(fp2); |
|
7473 } |
|
7474 opn = "msub.s"; |
|
7475 break; |
|
7476 case OPC_MSUB_D: |
|
7477 check_cop1x(ctx); |
|
7478 check_cp1_registers(ctx, fd | fs | ft | fr); |
|
7479 { |
|
7480 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7481 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7482 TCGv_i64 fp2 = tcg_temp_new_i64(); |
|
7483 |
|
7484 gen_load_fpr64(ctx, fp0, fs); |
|
7485 gen_load_fpr64(ctx, fp1, ft); |
|
7486 gen_load_fpr64(ctx, fp2, fr); |
|
7487 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2); |
|
7488 tcg_temp_free_i64(fp0); |
|
7489 tcg_temp_free_i64(fp1); |
|
7490 gen_store_fpr64(ctx, fp2, fd); |
|
7491 tcg_temp_free_i64(fp2); |
|
7492 } |
|
7493 opn = "msub.d"; |
|
7494 break; |
|
7495 case OPC_MSUB_PS: |
|
7496 check_cp1_64bitmode(ctx); |
|
7497 { |
|
7498 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7499 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7500 TCGv_i64 fp2 = tcg_temp_new_i64(); |
|
7501 |
|
7502 gen_load_fpr64(ctx, fp0, fs); |
|
7503 gen_load_fpr64(ctx, fp1, ft); |
|
7504 gen_load_fpr64(ctx, fp2, fr); |
|
7505 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2); |
|
7506 tcg_temp_free_i64(fp0); |
|
7507 tcg_temp_free_i64(fp1); |
|
7508 gen_store_fpr64(ctx, fp2, fd); |
|
7509 tcg_temp_free_i64(fp2); |
|
7510 } |
|
7511 opn = "msub.ps"; |
|
7512 break; |
|
7513 case OPC_NMADD_S: |
|
7514 check_cop1x(ctx); |
|
7515 { |
|
7516 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7517 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
7518 TCGv_i32 fp2 = tcg_temp_new_i32(); |
|
7519 |
|
7520 gen_load_fpr32(fp0, fs); |
|
7521 gen_load_fpr32(fp1, ft); |
|
7522 gen_load_fpr32(fp2, fr); |
|
7523 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2); |
|
7524 tcg_temp_free_i32(fp0); |
|
7525 tcg_temp_free_i32(fp1); |
|
7526 gen_store_fpr32(fp2, fd); |
|
7527 tcg_temp_free_i32(fp2); |
|
7528 } |
|
7529 opn = "nmadd.s"; |
|
7530 break; |
|
7531 case OPC_NMADD_D: |
|
7532 check_cop1x(ctx); |
|
7533 check_cp1_registers(ctx, fd | fs | ft | fr); |
|
7534 { |
|
7535 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7536 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7537 TCGv_i64 fp2 = tcg_temp_new_i64(); |
|
7538 |
|
7539 gen_load_fpr64(ctx, fp0, fs); |
|
7540 gen_load_fpr64(ctx, fp1, ft); |
|
7541 gen_load_fpr64(ctx, fp2, fr); |
|
7542 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2); |
|
7543 tcg_temp_free_i64(fp0); |
|
7544 tcg_temp_free_i64(fp1); |
|
7545 gen_store_fpr64(ctx, fp2, fd); |
|
7546 tcg_temp_free_i64(fp2); |
|
7547 } |
|
7548 opn = "nmadd.d"; |
|
7549 break; |
|
7550 case OPC_NMADD_PS: |
|
7551 check_cp1_64bitmode(ctx); |
|
7552 { |
|
7553 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7554 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7555 TCGv_i64 fp2 = tcg_temp_new_i64(); |
|
7556 |
|
7557 gen_load_fpr64(ctx, fp0, fs); |
|
7558 gen_load_fpr64(ctx, fp1, ft); |
|
7559 gen_load_fpr64(ctx, fp2, fr); |
|
7560 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2); |
|
7561 tcg_temp_free_i64(fp0); |
|
7562 tcg_temp_free_i64(fp1); |
|
7563 gen_store_fpr64(ctx, fp2, fd); |
|
7564 tcg_temp_free_i64(fp2); |
|
7565 } |
|
7566 opn = "nmadd.ps"; |
|
7567 break; |
|
7568 case OPC_NMSUB_S: |
|
7569 check_cop1x(ctx); |
|
7570 { |
|
7571 TCGv_i32 fp0 = tcg_temp_new_i32(); |
|
7572 TCGv_i32 fp1 = tcg_temp_new_i32(); |
|
7573 TCGv_i32 fp2 = tcg_temp_new_i32(); |
|
7574 |
|
7575 gen_load_fpr32(fp0, fs); |
|
7576 gen_load_fpr32(fp1, ft); |
|
7577 gen_load_fpr32(fp2, fr); |
|
7578 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2); |
|
7579 tcg_temp_free_i32(fp0); |
|
7580 tcg_temp_free_i32(fp1); |
|
7581 gen_store_fpr32(fp2, fd); |
|
7582 tcg_temp_free_i32(fp2); |
|
7583 } |
|
7584 opn = "nmsub.s"; |
|
7585 break; |
|
7586 case OPC_NMSUB_D: |
|
7587 check_cop1x(ctx); |
|
7588 check_cp1_registers(ctx, fd | fs | ft | fr); |
|
7589 { |
|
7590 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7591 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7592 TCGv_i64 fp2 = tcg_temp_new_i64(); |
|
7593 |
|
7594 gen_load_fpr64(ctx, fp0, fs); |
|
7595 gen_load_fpr64(ctx, fp1, ft); |
|
7596 gen_load_fpr64(ctx, fp2, fr); |
|
7597 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2); |
|
7598 tcg_temp_free_i64(fp0); |
|
7599 tcg_temp_free_i64(fp1); |
|
7600 gen_store_fpr64(ctx, fp2, fd); |
|
7601 tcg_temp_free_i64(fp2); |
|
7602 } |
|
7603 opn = "nmsub.d"; |
|
7604 break; |
|
7605 case OPC_NMSUB_PS: |
|
7606 check_cp1_64bitmode(ctx); |
|
7607 { |
|
7608 TCGv_i64 fp0 = tcg_temp_new_i64(); |
|
7609 TCGv_i64 fp1 = tcg_temp_new_i64(); |
|
7610 TCGv_i64 fp2 = tcg_temp_new_i64(); |
|
7611 |
|
7612 gen_load_fpr64(ctx, fp0, fs); |
|
7613 gen_load_fpr64(ctx, fp1, ft); |
|
7614 gen_load_fpr64(ctx, fp2, fr); |
|
7615 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2); |
|
7616 tcg_temp_free_i64(fp0); |
|
7617 tcg_temp_free_i64(fp1); |
|
7618 gen_store_fpr64(ctx, fp2, fd); |
|
7619 tcg_temp_free_i64(fp2); |
|
7620 } |
|
7621 opn = "nmsub.ps"; |
|
7622 break; |
|
7623 default: |
|
7624 MIPS_INVAL(opn); |
|
7625 generate_exception (ctx, EXCP_RI); |
|
7626 return; |
|
7627 } |
|
7628 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr], |
|
7629 fregnames[fs], fregnames[ft]); |
|
7630 } |
|
7631 |
|
7632 /* ISA extensions (ASEs) */ |
|
7633 /* MIPS16 extension to MIPS32 */ |
|
7634 /* SmartMIPS extension to MIPS32 */ |
|
7635 |
|
7636 #if defined(TARGET_MIPS64) |
|
7637 |
|
7638 /* MDMX extension to MIPS64 */ |
|
7639 |
|
7640 #endif |
|
7641 |
|
7642 static void decode_opc (CPUState *env, DisasContext *ctx) |
|
7643 { |
|
7644 int32_t offset; |
|
7645 int rs, rt, rd, sa; |
|
7646 uint32_t op, op1, op2; |
|
7647 int16_t imm; |
|
7648 |
|
7649 /* make sure instructions are on a word boundary */ |
|
7650 if (ctx->pc & 0x3) { |
|
7651 env->CP0_BadVAddr = ctx->pc; |
|
7652 generate_exception(ctx, EXCP_AdEL); |
|
7653 return; |
|
7654 } |
|
7655 |
|
7656 /* Handle blikely not taken case */ |
|
7657 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) { |
|
7658 int l1 = gen_new_label(); |
|
7659 |
|
7660 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4); |
|
7661 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1); |
|
7662 { |
|
7663 TCGv_i32 r_tmp = tcg_temp_new_i32(); |
|
7664 |
|
7665 tcg_gen_movi_i32(r_tmp, ctx->hflags & ~MIPS_HFLAG_BMASK); |
|
7666 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags)); |
|
7667 tcg_temp_free_i32(r_tmp); |
|
7668 } |
|
7669 gen_goto_tb(ctx, 1, ctx->pc + 4); |
|
7670 gen_set_label(l1); |
|
7671 } |
|
7672 op = MASK_OP_MAJOR(ctx->opcode); |
|
7673 rs = (ctx->opcode >> 21) & 0x1f; |
|
7674 rt = (ctx->opcode >> 16) & 0x1f; |
|
7675 rd = (ctx->opcode >> 11) & 0x1f; |
|
7676 sa = (ctx->opcode >> 6) & 0x1f; |
|
7677 imm = (int16_t)ctx->opcode; |
|
7678 switch (op) { |
|
7679 case OPC_SPECIAL: |
|
7680 op1 = MASK_SPECIAL(ctx->opcode); |
|
7681 switch (op1) { |
|
7682 case OPC_SLL: /* Arithmetic with immediate */ |
|
7683 case OPC_SRL ... OPC_SRA: |
|
7684 gen_arith_imm(env, ctx, op1, rd, rt, sa); |
|
7685 break; |
|
7686 case OPC_MOVZ ... OPC_MOVN: |
|
7687 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32); |
|
7688 case OPC_SLLV: /* Arithmetic */ |
|
7689 case OPC_SRLV ... OPC_SRAV: |
|
7690 case OPC_ADD ... OPC_NOR: |
|
7691 case OPC_SLT ... OPC_SLTU: |
|
7692 gen_arith(env, ctx, op1, rd, rs, rt); |
|
7693 break; |
|
7694 case OPC_MULT ... OPC_DIVU: |
|
7695 if (sa) { |
|
7696 check_insn(env, ctx, INSN_VR54XX); |
|
7697 op1 = MASK_MUL_VR54XX(ctx->opcode); |
|
7698 gen_mul_vr54xx(ctx, op1, rd, rs, rt); |
|
7699 } else |
|
7700 gen_muldiv(ctx, op1, rs, rt); |
|
7701 break; |
|
7702 case OPC_JR ... OPC_JALR: |
|
7703 gen_compute_branch(ctx, op1, rs, rd, sa); |
|
7704 return; |
|
7705 case OPC_TGE ... OPC_TEQ: /* Traps */ |
|
7706 case OPC_TNE: |
|
7707 gen_trap(ctx, op1, rs, rt, -1); |
|
7708 break; |
|
7709 case OPC_MFHI: /* Move from HI/LO */ |
|
7710 case OPC_MFLO: |
|
7711 gen_HILO(ctx, op1, rd); |
|
7712 break; |
|
7713 case OPC_MTHI: |
|
7714 case OPC_MTLO: /* Move to HI/LO */ |
|
7715 gen_HILO(ctx, op1, rs); |
|
7716 break; |
|
7717 case OPC_PMON: /* Pmon entry point, also R4010 selsl */ |
|
7718 #ifdef MIPS_STRICT_STANDARD |
|
7719 MIPS_INVAL("PMON / selsl"); |
|
7720 generate_exception(ctx, EXCP_RI); |
|
7721 #else |
|
7722 gen_helper_0i(pmon, sa); |
|
7723 #endif |
|
7724 break; |
|
7725 case OPC_SYSCALL: |
|
7726 generate_exception(ctx, EXCP_SYSCALL); |
|
7727 break; |
|
7728 case OPC_BREAK: |
|
7729 generate_exception(ctx, EXCP_BREAK); |
|
7730 break; |
|
7731 case OPC_SPIM: |
|
7732 #ifdef MIPS_STRICT_STANDARD |
|
7733 MIPS_INVAL("SPIM"); |
|
7734 generate_exception(ctx, EXCP_RI); |
|
7735 #else |
|
7736 /* Implemented as RI exception for now. */ |
|
7737 MIPS_INVAL("spim (unofficial)"); |
|
7738 generate_exception(ctx, EXCP_RI); |
|
7739 #endif |
|
7740 break; |
|
7741 case OPC_SYNC: |
|
7742 /* Treat as NOP. */ |
|
7743 break; |
|
7744 |
|
7745 case OPC_MOVCI: |
|
7746 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32); |
|
7747 if (env->CP0_Config1 & (1 << CP0C1_FP)) { |
|
7748 save_cpu_state(ctx, 1); |
|
7749 check_cp1_enabled(ctx); |
|
7750 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7, |
|
7751 (ctx->opcode >> 16) & 1); |
|
7752 } else { |
|
7753 generate_exception_err(ctx, EXCP_CpU, 1); |
|
7754 } |
|
7755 break; |
|
7756 |
|
7757 #if defined(TARGET_MIPS64) |
|
7758 /* MIPS64 specific opcodes */ |
|
7759 case OPC_DSLL: |
|
7760 case OPC_DSRL ... OPC_DSRA: |
|
7761 case OPC_DSLL32: |
|
7762 case OPC_DSRL32 ... OPC_DSRA32: |
|
7763 check_insn(env, ctx, ISA_MIPS3); |
|
7764 check_mips_64(ctx); |
|
7765 gen_arith_imm(env, ctx, op1, rd, rt, sa); |
|
7766 break; |
|
7767 case OPC_DSLLV: |
|
7768 case OPC_DSRLV ... OPC_DSRAV: |
|
7769 case OPC_DADD ... OPC_DSUBU: |
|
7770 check_insn(env, ctx, ISA_MIPS3); |
|
7771 check_mips_64(ctx); |
|
7772 gen_arith(env, ctx, op1, rd, rs, rt); |
|
7773 break; |
|
7774 case OPC_DMULT ... OPC_DDIVU: |
|
7775 check_insn(env, ctx, ISA_MIPS3); |
|
7776 check_mips_64(ctx); |
|
7777 gen_muldiv(ctx, op1, rs, rt); |
|
7778 break; |
|
7779 #endif |
|
7780 default: /* Invalid */ |
|
7781 MIPS_INVAL("special"); |
|
7782 generate_exception(ctx, EXCP_RI); |
|
7783 break; |
|
7784 } |
|
7785 break; |
|
7786 case OPC_SPECIAL2: |
|
7787 op1 = MASK_SPECIAL2(ctx->opcode); |
|
7788 switch (op1) { |
|
7789 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */ |
|
7790 case OPC_MSUB ... OPC_MSUBU: |
|
7791 check_insn(env, ctx, ISA_MIPS32); |
|
7792 gen_muldiv(ctx, op1, rs, rt); |
|
7793 break; |
|
7794 case OPC_MUL: |
|
7795 gen_arith(env, ctx, op1, rd, rs, rt); |
|
7796 break; |
|
7797 case OPC_CLZ ... OPC_CLO: |
|
7798 check_insn(env, ctx, ISA_MIPS32); |
|
7799 gen_cl(ctx, op1, rd, rs); |
|
7800 break; |
|
7801 case OPC_SDBBP: |
|
7802 /* XXX: not clear which exception should be raised |
|
7803 * when in debug mode... |
|
7804 */ |
|
7805 check_insn(env, ctx, ISA_MIPS32); |
|
7806 if (!(ctx->hflags & MIPS_HFLAG_DM)) { |
|
7807 generate_exception(ctx, EXCP_DBp); |
|
7808 } else { |
|
7809 generate_exception(ctx, EXCP_DBp); |
|
7810 } |
|
7811 /* Treat as NOP. */ |
|
7812 break; |
|
7813 #if defined(TARGET_MIPS64) |
|
7814 case OPC_DCLZ ... OPC_DCLO: |
|
7815 check_insn(env, ctx, ISA_MIPS64); |
|
7816 check_mips_64(ctx); |
|
7817 gen_cl(ctx, op1, rd, rs); |
|
7818 break; |
|
7819 #endif |
|
7820 default: /* Invalid */ |
|
7821 MIPS_INVAL("special2"); |
|
7822 generate_exception(ctx, EXCP_RI); |
|
7823 break; |
|
7824 } |
|
7825 break; |
|
7826 case OPC_SPECIAL3: |
|
7827 op1 = MASK_SPECIAL3(ctx->opcode); |
|
7828 switch (op1) { |
|
7829 case OPC_EXT: |
|
7830 case OPC_INS: |
|
7831 check_insn(env, ctx, ISA_MIPS32R2); |
|
7832 gen_bitops(ctx, op1, rt, rs, sa, rd); |
|
7833 break; |
|
7834 case OPC_BSHFL: |
|
7835 check_insn(env, ctx, ISA_MIPS32R2); |
|
7836 op2 = MASK_BSHFL(ctx->opcode); |
|
7837 gen_bshfl(ctx, op2, rt, rd); |
|
7838 break; |
|
7839 case OPC_RDHWR: |
|
7840 check_insn(env, ctx, ISA_MIPS32R2); |
|
7841 { |
|
7842 TCGv t0 = tcg_temp_local_new(); |
|
7843 |
|
7844 switch (rd) { |
|
7845 case 0: |
|
7846 save_cpu_state(ctx, 1); |
|
7847 gen_helper_rdhwr_cpunum(t0); |
|
7848 break; |
|
7849 case 1: |
|
7850 save_cpu_state(ctx, 1); |
|
7851 gen_helper_rdhwr_synci_step(t0); |
|
7852 break; |
|
7853 case 2: |
|
7854 save_cpu_state(ctx, 1); |
|
7855 gen_helper_rdhwr_cc(t0); |
|
7856 break; |
|
7857 case 3: |
|
7858 save_cpu_state(ctx, 1); |
|
7859 gen_helper_rdhwr_ccres(t0); |
|
7860 break; |
|
7861 case 29: |
|
7862 if (env->user_mode_only) { |
|
7863 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value)); |
|
7864 break; |
|
7865 } else { |
|
7866 /* XXX: Some CPUs implement this in hardware. |
|
7867 Not supported yet. */ |
|
7868 } |
|
7869 default: /* Invalid */ |
|
7870 MIPS_INVAL("rdhwr"); |
|
7871 generate_exception(ctx, EXCP_RI); |
|
7872 break; |
|
7873 } |
|
7874 gen_store_gpr(t0, rt); |
|
7875 tcg_temp_free(t0); |
|
7876 } |
|
7877 break; |
|
7878 case OPC_FORK: |
|
7879 check_insn(env, ctx, ASE_MT); |
|
7880 { |
|
7881 TCGv t0 = tcg_temp_local_new(); |
|
7882 TCGv t1 = tcg_temp_local_new(); |
|
7883 |
|
7884 gen_load_gpr(t0, rt); |
|
7885 gen_load_gpr(t1, rs); |
|
7886 gen_helper_fork(t0, t1); |
|
7887 tcg_temp_free(t0); |
|
7888 tcg_temp_free(t1); |
|
7889 } |
|
7890 break; |
|
7891 case OPC_YIELD: |
|
7892 check_insn(env, ctx, ASE_MT); |
|
7893 { |
|
7894 TCGv t0 = tcg_temp_local_new(); |
|
7895 |
|
7896 gen_load_gpr(t0, rs); |
|
7897 gen_helper_yield(t0, t0); |
|
7898 gen_store_gpr(t0, rd); |
|
7899 tcg_temp_free(t0); |
|
7900 } |
|
7901 break; |
|
7902 #if defined(TARGET_MIPS64) |
|
7903 case OPC_DEXTM ... OPC_DEXT: |
|
7904 case OPC_DINSM ... OPC_DINS: |
|
7905 check_insn(env, ctx, ISA_MIPS64R2); |
|
7906 check_mips_64(ctx); |
|
7907 gen_bitops(ctx, op1, rt, rs, sa, rd); |
|
7908 break; |
|
7909 case OPC_DBSHFL: |
|
7910 check_insn(env, ctx, ISA_MIPS64R2); |
|
7911 check_mips_64(ctx); |
|
7912 op2 = MASK_DBSHFL(ctx->opcode); |
|
7913 gen_bshfl(ctx, op2, rt, rd); |
|
7914 break; |
|
7915 #endif |
|
7916 default: /* Invalid */ |
|
7917 MIPS_INVAL("special3"); |
|
7918 generate_exception(ctx, EXCP_RI); |
|
7919 break; |
|
7920 } |
|
7921 break; |
|
7922 case OPC_REGIMM: |
|
7923 op1 = MASK_REGIMM(ctx->opcode); |
|
7924 switch (op1) { |
|
7925 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */ |
|
7926 case OPC_BLTZAL ... OPC_BGEZALL: |
|
7927 gen_compute_branch(ctx, op1, rs, -1, imm << 2); |
|
7928 return; |
|
7929 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */ |
|
7930 case OPC_TNEI: |
|
7931 gen_trap(ctx, op1, rs, -1, imm); |
|
7932 break; |
|
7933 case OPC_SYNCI: |
|
7934 check_insn(env, ctx, ISA_MIPS32R2); |
|
7935 /* Treat as NOP. */ |
|
7936 break; |
|
7937 default: /* Invalid */ |
|
7938 MIPS_INVAL("regimm"); |
|
7939 generate_exception(ctx, EXCP_RI); |
|
7940 break; |
|
7941 } |
|
7942 break; |
|
7943 case OPC_CP0: |
|
7944 check_cp0_enabled(ctx); |
|
7945 op1 = MASK_CP0(ctx->opcode); |
|
7946 switch (op1) { |
|
7947 case OPC_MFC0: |
|
7948 case OPC_MTC0: |
|
7949 case OPC_MFTR: |
|
7950 case OPC_MTTR: |
|
7951 #if defined(TARGET_MIPS64) |
|
7952 case OPC_DMFC0: |
|
7953 case OPC_DMTC0: |
|
7954 #endif |
|
7955 #ifndef CONFIG_USER_ONLY |
|
7956 if (!env->user_mode_only) |
|
7957 gen_cp0(env, ctx, op1, rt, rd); |
|
7958 #endif /* !CONFIG_USER_ONLY */ |
|
7959 break; |
|
7960 case OPC_C0_FIRST ... OPC_C0_LAST: |
|
7961 #ifndef CONFIG_USER_ONLY |
|
7962 if (!env->user_mode_only) |
|
7963 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd); |
|
7964 #endif /* !CONFIG_USER_ONLY */ |
|
7965 break; |
|
7966 case OPC_MFMC0: |
|
7967 #ifndef CONFIG_USER_ONLY |
|
7968 if (!env->user_mode_only) { |
|
7969 TCGv t0 = tcg_temp_local_new(); |
|
7970 |
|
7971 op2 = MASK_MFMC0(ctx->opcode); |
|
7972 switch (op2) { |
|
7973 case OPC_DMT: |
|
7974 check_insn(env, ctx, ASE_MT); |
|
7975 gen_helper_dmt(t0, t0); |
|
7976 break; |
|
7977 case OPC_EMT: |
|
7978 check_insn(env, ctx, ASE_MT); |
|
7979 gen_helper_emt(t0, t0); |
|
7980 break; |
|
7981 case OPC_DVPE: |
|
7982 check_insn(env, ctx, ASE_MT); |
|
7983 gen_helper_dvpe(t0, t0); |
|
7984 break; |
|
7985 case OPC_EVPE: |
|
7986 check_insn(env, ctx, ASE_MT); |
|
7987 gen_helper_evpe(t0, t0); |
|
7988 break; |
|
7989 case OPC_DI: |
|
7990 check_insn(env, ctx, ISA_MIPS32R2); |
|
7991 save_cpu_state(ctx, 1); |
|
7992 gen_helper_di(t0); |
|
7993 /* Stop translation as we may have switched the execution mode */ |
|
7994 ctx->bstate = BS_STOP; |
|
7995 break; |
|
7996 case OPC_EI: |
|
7997 check_insn(env, ctx, ISA_MIPS32R2); |
|
7998 save_cpu_state(ctx, 1); |
|
7999 gen_helper_ei(t0); |
|
8000 /* Stop translation as we may have switched the execution mode */ |
|
8001 ctx->bstate = BS_STOP; |
|
8002 break; |
|
8003 default: /* Invalid */ |
|
8004 MIPS_INVAL("mfmc0"); |
|
8005 generate_exception(ctx, EXCP_RI); |
|
8006 break; |
|
8007 } |
|
8008 gen_store_gpr(t0, rt); |
|
8009 tcg_temp_free(t0); |
|
8010 } |
|
8011 #endif /* !CONFIG_USER_ONLY */ |
|
8012 break; |
|
8013 case OPC_RDPGPR: |
|
8014 check_insn(env, ctx, ISA_MIPS32R2); |
|
8015 gen_load_srsgpr(rt, rd); |
|
8016 break; |
|
8017 case OPC_WRPGPR: |
|
8018 check_insn(env, ctx, ISA_MIPS32R2); |
|
8019 gen_store_srsgpr(rt, rd); |
|
8020 break; |
|
8021 default: |
|
8022 MIPS_INVAL("cp0"); |
|
8023 generate_exception(ctx, EXCP_RI); |
|
8024 break; |
|
8025 } |
|
8026 break; |
|
8027 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */ |
|
8028 gen_arith_imm(env, ctx, op, rt, rs, imm); |
|
8029 break; |
|
8030 case OPC_J ... OPC_JAL: /* Jump */ |
|
8031 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; |
|
8032 gen_compute_branch(ctx, op, rs, rt, offset); |
|
8033 return; |
|
8034 case OPC_BEQ ... OPC_BGTZ: /* Branch */ |
|
8035 case OPC_BEQL ... OPC_BGTZL: |
|
8036 gen_compute_branch(ctx, op, rs, rt, imm << 2); |
|
8037 return; |
|
8038 case OPC_LB ... OPC_LWR: /* Load and stores */ |
|
8039 case OPC_SB ... OPC_SW: |
|
8040 case OPC_SWR: |
|
8041 case OPC_LL: |
|
8042 case OPC_SC: |
|
8043 gen_ldst(ctx, op, rt, rs, imm); |
|
8044 break; |
|
8045 case OPC_CACHE: |
|
8046 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32); |
|
8047 /* Treat as NOP. */ |
|
8048 break; |
|
8049 case OPC_PREF: |
|
8050 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32); |
|
8051 /* Treat as NOP. */ |
|
8052 break; |
|
8053 |
|
8054 /* Floating point (COP1). */ |
|
8055 case OPC_LWC1: |
|
8056 case OPC_LDC1: |
|
8057 case OPC_SWC1: |
|
8058 case OPC_SDC1: |
|
8059 if (env->CP0_Config1 & (1 << CP0C1_FP)) { |
|
8060 save_cpu_state(ctx, 1); |
|
8061 check_cp1_enabled(ctx); |
|
8062 gen_flt_ldst(ctx, op, rt, rs, imm); |
|
8063 } else { |
|
8064 generate_exception_err(ctx, EXCP_CpU, 1); |
|
8065 } |
|
8066 break; |
|
8067 |
|
8068 case OPC_CP1: |
|
8069 if (env->CP0_Config1 & (1 << CP0C1_FP)) { |
|
8070 save_cpu_state(ctx, 1); |
|
8071 check_cp1_enabled(ctx); |
|
8072 op1 = MASK_CP1(ctx->opcode); |
|
8073 switch (op1) { |
|
8074 case OPC_MFHC1: |
|
8075 case OPC_MTHC1: |
|
8076 check_insn(env, ctx, ISA_MIPS32R2); |
|
8077 case OPC_MFC1: |
|
8078 case OPC_CFC1: |
|
8079 case OPC_MTC1: |
|
8080 case OPC_CTC1: |
|
8081 gen_cp1(ctx, op1, rt, rd); |
|
8082 break; |
|
8083 #if defined(TARGET_MIPS64) |
|
8084 case OPC_DMFC1: |
|
8085 case OPC_DMTC1: |
|
8086 check_insn(env, ctx, ISA_MIPS3); |
|
8087 gen_cp1(ctx, op1, rt, rd); |
|
8088 break; |
|
8089 #endif |
|
8090 case OPC_BC1ANY2: |
|
8091 case OPC_BC1ANY4: |
|
8092 check_cop1x(ctx); |
|
8093 check_insn(env, ctx, ASE_MIPS3D); |
|
8094 /* fall through */ |
|
8095 case OPC_BC1: |
|
8096 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode), |
|
8097 (rt >> 2) & 0x7, imm << 2); |
|
8098 return; |
|
8099 case OPC_S_FMT: |
|
8100 case OPC_D_FMT: |
|
8101 case OPC_W_FMT: |
|
8102 case OPC_L_FMT: |
|
8103 case OPC_PS_FMT: |
|
8104 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa, |
|
8105 (imm >> 8) & 0x7); |
|
8106 break; |
|
8107 default: |
|
8108 MIPS_INVAL("cp1"); |
|
8109 generate_exception (ctx, EXCP_RI); |
|
8110 break; |
|
8111 } |
|
8112 } else { |
|
8113 generate_exception_err(ctx, EXCP_CpU, 1); |
|
8114 } |
|
8115 break; |
|
8116 |
|
8117 /* COP2. */ |
|
8118 case OPC_LWC2: |
|
8119 case OPC_LDC2: |
|
8120 case OPC_SWC2: |
|
8121 case OPC_SDC2: |
|
8122 case OPC_CP2: |
|
8123 /* COP2: Not implemented. */ |
|
8124 generate_exception_err(ctx, EXCP_CpU, 2); |
|
8125 break; |
|
8126 |
|
8127 case OPC_CP3: |
|
8128 if (env->CP0_Config1 & (1 << CP0C1_FP)) { |
|
8129 save_cpu_state(ctx, 1); |
|
8130 check_cp1_enabled(ctx); |
|
8131 op1 = MASK_CP3(ctx->opcode); |
|
8132 switch (op1) { |
|
8133 case OPC_LWXC1: |
|
8134 case OPC_LDXC1: |
|
8135 case OPC_LUXC1: |
|
8136 case OPC_SWXC1: |
|
8137 case OPC_SDXC1: |
|
8138 case OPC_SUXC1: |
|
8139 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt); |
|
8140 break; |
|
8141 case OPC_PREFX: |
|
8142 /* Treat as NOP. */ |
|
8143 break; |
|
8144 case OPC_ALNV_PS: |
|
8145 case OPC_MADD_S: |
|
8146 case OPC_MADD_D: |
|
8147 case OPC_MADD_PS: |
|
8148 case OPC_MSUB_S: |
|
8149 case OPC_MSUB_D: |
|
8150 case OPC_MSUB_PS: |
|
8151 case OPC_NMADD_S: |
|
8152 case OPC_NMADD_D: |
|
8153 case OPC_NMADD_PS: |
|
8154 case OPC_NMSUB_S: |
|
8155 case OPC_NMSUB_D: |
|
8156 case OPC_NMSUB_PS: |
|
8157 gen_flt3_arith(ctx, op1, sa, rs, rd, rt); |
|
8158 break; |
|
8159 default: |
|
8160 MIPS_INVAL("cp3"); |
|
8161 generate_exception (ctx, EXCP_RI); |
|
8162 break; |
|
8163 } |
|
8164 } else { |
|
8165 generate_exception_err(ctx, EXCP_CpU, 1); |
|
8166 } |
|
8167 break; |
|
8168 |
|
8169 #if defined(TARGET_MIPS64) |
|
8170 /* MIPS64 opcodes */ |
|
8171 case OPC_LWU: |
|
8172 case OPC_LDL ... OPC_LDR: |
|
8173 case OPC_SDL ... OPC_SDR: |
|
8174 case OPC_LLD: |
|
8175 case OPC_LD: |
|
8176 case OPC_SCD: |
|
8177 case OPC_SD: |
|
8178 check_insn(env, ctx, ISA_MIPS3); |
|
8179 check_mips_64(ctx); |
|
8180 gen_ldst(ctx, op, rt, rs, imm); |
|
8181 break; |
|
8182 case OPC_DADDI ... OPC_DADDIU: |
|
8183 check_insn(env, ctx, ISA_MIPS3); |
|
8184 check_mips_64(ctx); |
|
8185 gen_arith_imm(env, ctx, op, rt, rs, imm); |
|
8186 break; |
|
8187 #endif |
|
8188 case OPC_JALX: |
|
8189 check_insn(env, ctx, ASE_MIPS16); |
|
8190 /* MIPS16: Not implemented. */ |
|
8191 case OPC_MDMX: |
|
8192 check_insn(env, ctx, ASE_MDMX); |
|
8193 /* MDMX: Not implemented. */ |
|
8194 default: /* Invalid */ |
|
8195 MIPS_INVAL("major opcode"); |
|
8196 generate_exception(ctx, EXCP_RI); |
|
8197 break; |
|
8198 } |
|
8199 if (ctx->hflags & MIPS_HFLAG_BMASK) { |
|
8200 int hflags = ctx->hflags & MIPS_HFLAG_BMASK; |
|
8201 /* Branches completion */ |
|
8202 ctx->hflags &= ~MIPS_HFLAG_BMASK; |
|
8203 ctx->bstate = BS_BRANCH; |
|
8204 save_cpu_state(ctx, 0); |
|
8205 /* FIXME: Need to clear can_do_io. */ |
|
8206 switch (hflags) { |
|
8207 case MIPS_HFLAG_B: |
|
8208 /* unconditional branch */ |
|
8209 MIPS_DEBUG("unconditional branch"); |
|
8210 gen_goto_tb(ctx, 0, ctx->btarget); |
|
8211 break; |
|
8212 case MIPS_HFLAG_BL: |
|
8213 /* blikely taken case */ |
|
8214 MIPS_DEBUG("blikely branch taken"); |
|
8215 gen_goto_tb(ctx, 0, ctx->btarget); |
|
8216 break; |
|
8217 case MIPS_HFLAG_BC: |
|
8218 /* Conditional branch */ |
|
8219 MIPS_DEBUG("conditional branch"); |
|
8220 { |
|
8221 int l1 = gen_new_label(); |
|
8222 |
|
8223 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1); |
|
8224 gen_goto_tb(ctx, 1, ctx->pc + 4); |
|
8225 gen_set_label(l1); |
|
8226 gen_goto_tb(ctx, 0, ctx->btarget); |
|
8227 } |
|
8228 break; |
|
8229 case MIPS_HFLAG_BR: |
|
8230 /* unconditional branch to register */ |
|
8231 MIPS_DEBUG("branch to register"); |
|
8232 tcg_gen_mov_tl(cpu_PC, btarget); |
|
8233 tcg_gen_exit_tb(0); |
|
8234 break; |
|
8235 default: |
|
8236 MIPS_DEBUG("unknown branch"); |
|
8237 break; |
|
8238 } |
|
8239 } |
|
8240 } |
|
8241 |
|
8242 static inline void |
|
8243 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, |
|
8244 int search_pc) |
|
8245 { |
|
8246 DisasContext ctx; |
|
8247 target_ulong pc_start; |
|
8248 uint16_t *gen_opc_end; |
|
8249 CPUBreakpoint *bp; |
|
8250 int j, lj = -1; |
|
8251 int num_insns; |
|
8252 int max_insns; |
|
8253 |
|
8254 if (search_pc && loglevel) |
|
8255 fprintf (logfile, "search pc %d\n", search_pc); |
|
8256 |
|
8257 pc_start = tb->pc; |
|
8258 /* Leave some spare opc slots for branch handling. */ |
|
8259 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16; |
|
8260 ctx.pc = pc_start; |
|
8261 ctx.saved_pc = -1; |
|
8262 ctx.tb = tb; |
|
8263 ctx.bstate = BS_NONE; |
|
8264 /* Restore delay slot state from the tb context. */ |
|
8265 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */ |
|
8266 restore_cpu_state(env, &ctx); |
|
8267 if (env->user_mode_only) |
|
8268 ctx.mem_idx = MIPS_HFLAG_UM; |
|
8269 else |
|
8270 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU; |
|
8271 num_insns = 0; |
|
8272 max_insns = tb->cflags & CF_COUNT_MASK; |
|
8273 if (max_insns == 0) |
|
8274 max_insns = CF_COUNT_MASK; |
|
8275 #ifdef DEBUG_DISAS |
|
8276 if (loglevel & CPU_LOG_TB_CPU) { |
|
8277 fprintf(logfile, "------------------------------------------------\n"); |
|
8278 /* FIXME: This may print out stale hflags from env... */ |
|
8279 cpu_dump_state(env, logfile, fprintf, 0); |
|
8280 } |
|
8281 #endif |
|
8282 #ifdef MIPS_DEBUG_DISAS |
|
8283 if (loglevel & CPU_LOG_TB_IN_ASM) |
|
8284 fprintf(logfile, "\ntb %p idx %d hflags %04x\n", |
|
8285 tb, ctx.mem_idx, ctx.hflags); |
|
8286 #endif |
|
8287 gen_icount_start(); |
|
8288 while (ctx.bstate == BS_NONE) { |
|
8289 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { |
|
8290 TAILQ_FOREACH(bp, &env->breakpoints, entry) { |
|
8291 if (bp->pc == ctx.pc) { |
|
8292 save_cpu_state(&ctx, 1); |
|
8293 ctx.bstate = BS_BRANCH; |
|
8294 gen_helper_0i(raise_exception, EXCP_DEBUG); |
|
8295 /* Include the breakpoint location or the tb won't |
|
8296 * be flushed when it must be. */ |
|
8297 ctx.pc += 4; |
|
8298 goto done_generating; |
|
8299 } |
|
8300 } |
|
8301 } |
|
8302 |
|
8303 if (search_pc) { |
|
8304 j = gen_opc_ptr - gen_opc_buf; |
|
8305 if (lj < j) { |
|
8306 lj++; |
|
8307 while (lj < j) |
|
8308 gen_opc_instr_start[lj++] = 0; |
|
8309 } |
|
8310 gen_opc_pc[lj] = ctx.pc; |
|
8311 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK; |
|
8312 gen_opc_instr_start[lj] = 1; |
|
8313 gen_opc_icount[lj] = num_insns; |
|
8314 } |
|
8315 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) |
|
8316 gen_io_start(); |
|
8317 ctx.opcode = ldl_code(ctx.pc); |
|
8318 decode_opc(env, &ctx); |
|
8319 ctx.pc += 4; |
|
8320 num_insns++; |
|
8321 |
|
8322 if (env->singlestep_enabled) |
|
8323 break; |
|
8324 |
|
8325 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) |
|
8326 break; |
|
8327 |
|
8328 if (gen_opc_ptr >= gen_opc_end) |
|
8329 break; |
|
8330 |
|
8331 if (num_insns >= max_insns) |
|
8332 break; |
|
8333 #if defined (MIPS_SINGLE_STEP) |
|
8334 break; |
|
8335 #endif |
|
8336 } |
|
8337 if (tb->cflags & CF_LAST_IO) |
|
8338 gen_io_end(); |
|
8339 if (env->singlestep_enabled) { |
|
8340 save_cpu_state(&ctx, ctx.bstate == BS_NONE); |
|
8341 gen_helper_0i(raise_exception, EXCP_DEBUG); |
|
8342 } else { |
|
8343 switch (ctx.bstate) { |
|
8344 case BS_STOP: |
|
8345 gen_helper_interrupt_restart(); |
|
8346 gen_goto_tb(&ctx, 0, ctx.pc); |
|
8347 break; |
|
8348 case BS_NONE: |
|
8349 save_cpu_state(&ctx, 0); |
|
8350 gen_goto_tb(&ctx, 0, ctx.pc); |
|
8351 break; |
|
8352 case BS_EXCP: |
|
8353 gen_helper_interrupt_restart(); |
|
8354 tcg_gen_exit_tb(0); |
|
8355 break; |
|
8356 case BS_BRANCH: |
|
8357 default: |
|
8358 break; |
|
8359 } |
|
8360 } |
|
8361 done_generating: |
|
8362 gen_icount_end(tb, num_insns); |
|
8363 *gen_opc_ptr = INDEX_op_end; |
|
8364 if (search_pc) { |
|
8365 j = gen_opc_ptr - gen_opc_buf; |
|
8366 lj++; |
|
8367 while (lj <= j) |
|
8368 gen_opc_instr_start[lj++] = 0; |
|
8369 } else { |
|
8370 tb->size = ctx.pc - pc_start; |
|
8371 tb->icount = num_insns; |
|
8372 } |
|
8373 #ifdef DEBUG_DISAS |
|
8374 #if defined MIPS_DEBUG_DISAS |
|
8375 if (loglevel & CPU_LOG_TB_IN_ASM) |
|
8376 fprintf(logfile, "\n"); |
|
8377 #endif |
|
8378 if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
8379 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); |
|
8380 target_disas(logfile, pc_start, ctx.pc - pc_start, 0); |
|
8381 fprintf(logfile, "\n"); |
|
8382 } |
|
8383 if (loglevel & CPU_LOG_TB_CPU) { |
|
8384 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags); |
|
8385 } |
|
8386 #endif |
|
8387 } |
|
8388 |
|
8389 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb) |
|
8390 { |
|
8391 gen_intermediate_code_internal(env, tb, 0); |
|
8392 } |
|
8393 |
|
8394 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) |
|
8395 { |
|
8396 gen_intermediate_code_internal(env, tb, 1); |
|
8397 } |
|
8398 |
|
8399 static void fpu_dump_state(CPUState *env, FILE *f, |
|
8400 int (*fpu_fprintf)(FILE *f, const char *fmt, ...), |
|
8401 int flags) |
|
8402 { |
|
8403 int i; |
|
8404 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64); |
|
8405 |
|
8406 #define printfpr(fp) \ |
|
8407 do { \ |
|
8408 if (is_fpu64) \ |
|
8409 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \ |
|
8410 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \ |
|
8411 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \ |
|
8412 else { \ |
|
8413 fpr_t tmp; \ |
|
8414 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \ |
|
8415 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \ |
|
8416 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \ |
|
8417 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \ |
|
8418 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \ |
|
8419 } \ |
|
8420 } while(0) |
|
8421 |
|
8422 |
|
8423 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n", |
|
8424 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status, |
|
8425 get_float_exception_flags(&env->active_fpu.fp_status)); |
|
8426 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) { |
|
8427 fpu_fprintf(f, "%3s: ", fregnames[i]); |
|
8428 printfpr(&env->active_fpu.fpr[i]); |
|
8429 } |
|
8430 |
|
8431 #undef printfpr |
|
8432 } |
|
8433 |
|
8434 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS) |
|
8435 /* Debug help: The architecture requires 32bit code to maintain proper |
|
8436 sign-extended values on 64bit machines. */ |
|
8437 |
|
8438 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff)) |
|
8439 |
|
8440 static void |
|
8441 cpu_mips_check_sign_extensions (CPUState *env, FILE *f, |
|
8442 int (*cpu_fprintf)(FILE *f, const char *fmt, ...), |
|
8443 int flags) |
|
8444 { |
|
8445 int i; |
|
8446 |
|
8447 if (!SIGN_EXT_P(env->active_tc.PC)) |
|
8448 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC); |
|
8449 if (!SIGN_EXT_P(env->active_tc.HI[0])) |
|
8450 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]); |
|
8451 if (!SIGN_EXT_P(env->active_tc.LO[0])) |
|
8452 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]); |
|
8453 if (!SIGN_EXT_P(env->btarget)) |
|
8454 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget); |
|
8455 |
|
8456 for (i = 0; i < 32; i++) { |
|
8457 if (!SIGN_EXT_P(env->active_tc.gpr[i])) |
|
8458 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]); |
|
8459 } |
|
8460 |
|
8461 if (!SIGN_EXT_P(env->CP0_EPC)) |
|
8462 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC); |
|
8463 if (!SIGN_EXT_P(env->CP0_LLAddr)) |
|
8464 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr); |
|
8465 } |
|
8466 #endif |
|
8467 |
|
8468 void cpu_dump_state (CPUState *env, FILE *f, |
|
8469 int (*cpu_fprintf)(FILE *f, const char *fmt, ...), |
|
8470 int flags) |
|
8471 { |
|
8472 int i; |
|
8473 |
|
8474 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n", |
|
8475 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0], |
|
8476 env->hflags, env->btarget, env->bcond); |
|
8477 for (i = 0; i < 32; i++) { |
|
8478 if ((i & 3) == 0) |
|
8479 cpu_fprintf(f, "GPR%02d:", i); |
|
8480 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]); |
|
8481 if ((i & 3) == 3) |
|
8482 cpu_fprintf(f, "\n"); |
|
8483 } |
|
8484 |
|
8485 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n", |
|
8486 env->CP0_Status, env->CP0_Cause, env->CP0_EPC); |
|
8487 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n", |
|
8488 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr); |
|
8489 if (env->hflags & MIPS_HFLAG_FPU) |
|
8490 fpu_dump_state(env, f, cpu_fprintf, flags); |
|
8491 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS) |
|
8492 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags); |
|
8493 #endif |
|
8494 } |
|
8495 |
|
8496 static void mips_tcg_init(void) |
|
8497 { |
|
8498 int i; |
|
8499 static int inited; |
|
8500 |
|
8501 /* Initialize various static tables. */ |
|
8502 if (inited) |
|
8503 return; |
|
8504 |
|
8505 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); |
|
8506 for (i = 0; i < 32; i++) |
|
8507 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0, |
|
8508 offsetof(CPUState, active_tc.gpr[i]), |
|
8509 regnames[i]); |
|
8510 cpu_PC = tcg_global_mem_new(TCG_AREG0, |
|
8511 offsetof(CPUState, active_tc.PC), "PC"); |
|
8512 for (i = 0; i < MIPS_DSP_ACC; i++) { |
|
8513 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0, |
|
8514 offsetof(CPUState, active_tc.HI[i]), |
|
8515 regnames_HI[i]); |
|
8516 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0, |
|
8517 offsetof(CPUState, active_tc.LO[i]), |
|
8518 regnames_LO[i]); |
|
8519 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0, |
|
8520 offsetof(CPUState, active_tc.ACX[i]), |
|
8521 regnames_ACX[i]); |
|
8522 } |
|
8523 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0, |
|
8524 offsetof(CPUState, active_tc.DSPControl), |
|
8525 "DSPControl"); |
|
8526 bcond = tcg_global_mem_new_i32(TCG_AREG0, |
|
8527 offsetof(CPUState, bcond), "bcond"); |
|
8528 btarget = tcg_global_mem_new(TCG_AREG0, |
|
8529 offsetof(CPUState, btarget), "btarget"); |
|
8530 for (i = 0; i < 32; i++) |
|
8531 fpu_fpr32[i] = tcg_global_mem_new_i32(TCG_AREG0, |
|
8532 offsetof(CPUState, active_fpu.fpr[i].w[FP_ENDIAN_IDX]), |
|
8533 fregnames[i]); |
|
8534 for (i = 0; i < 32; i++) |
|
8535 fpu_fpr64[i] = tcg_global_mem_new_i64(TCG_AREG0, |
|
8536 offsetof(CPUState, active_fpu.fpr[i]), |
|
8537 fregnames_64[i]); |
|
8538 for (i = 0; i < 32; i++) |
|
8539 fpu_fpr32h[i] = tcg_global_mem_new_i32(TCG_AREG0, |
|
8540 offsetof(CPUState, active_fpu.fpr[i].w[!FP_ENDIAN_IDX]), |
|
8541 fregnames_h[i]); |
|
8542 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0, |
|
8543 offsetof(CPUState, active_fpu.fcr0), |
|
8544 "fcr0"); |
|
8545 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0, |
|
8546 offsetof(CPUState, active_fpu.fcr31), |
|
8547 "fcr31"); |
|
8548 |
|
8549 /* register helpers */ |
|
8550 #define GEN_HELPER 2 |
|
8551 #include "helper.h" |
|
8552 |
|
8553 inited = 1; |
|
8554 } |
|
8555 |
|
8556 #include "translate_init.c" |
|
8557 |
|
8558 CPUMIPSState *cpu_mips_init (const char *cpu_model) |
|
8559 { |
|
8560 CPUMIPSState *env; |
|
8561 const mips_def_t *def; |
|
8562 |
|
8563 def = cpu_mips_find_by_name(cpu_model); |
|
8564 if (!def) |
|
8565 return NULL; |
|
8566 env = qemu_mallocz(sizeof(CPUMIPSState)); |
|
8567 if (!env) |
|
8568 return NULL; |
|
8569 env->cpu_model = def; |
|
8570 |
|
8571 cpu_exec_init(env); |
|
8572 env->cpu_model_str = cpu_model; |
|
8573 mips_tcg_init(); |
|
8574 cpu_reset(env); |
|
8575 return env; |
|
8576 } |
|
8577 |
|
8578 void cpu_reset (CPUMIPSState *env) |
|
8579 { |
|
8580 memset(env, 0, offsetof(CPUMIPSState, breakpoints)); |
|
8581 |
|
8582 tlb_flush(env, 1); |
|
8583 |
|
8584 /* Minimal init */ |
|
8585 #if defined(CONFIG_USER_ONLY) |
|
8586 env->user_mode_only = 1; |
|
8587 #endif |
|
8588 if (env->user_mode_only) { |
|
8589 env->hflags = MIPS_HFLAG_UM; |
|
8590 } else { |
|
8591 if (env->hflags & MIPS_HFLAG_BMASK) { |
|
8592 /* If the exception was raised from a delay slot, |
|
8593 come back to the jump. */ |
|
8594 env->CP0_ErrorEPC = env->active_tc.PC - 4; |
|
8595 } else { |
|
8596 env->CP0_ErrorEPC = env->active_tc.PC; |
|
8597 } |
|
8598 env->active_tc.PC = (int32_t)0xBFC00000; |
|
8599 env->CP0_Wired = 0; |
|
8600 /* SMP not implemented */ |
|
8601 env->CP0_EBase = 0x80000000; |
|
8602 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); |
|
8603 /* vectored interrupts not implemented, timer on int 7, |
|
8604 no performance counters. */ |
|
8605 env->CP0_IntCtl = 0xe0000000; |
|
8606 { |
|
8607 int i; |
|
8608 |
|
8609 for (i = 0; i < 7; i++) { |
|
8610 env->CP0_WatchLo[i] = 0; |
|
8611 env->CP0_WatchHi[i] = 0x80000000; |
|
8612 } |
|
8613 env->CP0_WatchLo[7] = 0; |
|
8614 env->CP0_WatchHi[7] = 0; |
|
8615 } |
|
8616 /* Count register increments in debug mode, EJTAG version 1 */ |
|
8617 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); |
|
8618 env->hflags = MIPS_HFLAG_CP0; |
|
8619 } |
|
8620 env->exception_index = EXCP_NONE; |
|
8621 cpu_mips_register(env, env->cpu_model); |
|
8622 } |
|
8623 |
|
8624 void gen_pc_load(CPUState *env, TranslationBlock *tb, |
|
8625 unsigned long searched_pc, int pc_pos, void *puc) |
|
8626 { |
|
8627 env->active_tc.PC = gen_opc_pc[pc_pos]; |
|
8628 env->hflags &= ~MIPS_HFLAG_BMASK; |
|
8629 env->hflags |= gen_opc_hflags[pc_pos]; |
|
8630 } |