Commit 4c9649a967e45bc3086d2e752871878e08d6cdf2
1 parent
6fa4cea9
Alpha architecture emulation core.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2597 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
10 changed files
with
5869 additions
and
0 deletions
target-alpha/cpu.h
0 → 100644
1 | +/* | ||
2 | + * Alpha emulation cpu definitions for qemu. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Jocelyn Mayer | ||
5 | + * | ||
6 | + * This library is free software; you can redistribute it and/or | ||
7 | + * modify it under the terms of the GNU Lesser General Public | ||
8 | + * License as published by the Free Software Foundation; either | ||
9 | + * version 2 of the License, or (at your option) any later version. | ||
10 | + * | ||
11 | + * This library is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | + * Lesser General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public | ||
17 | + * License along with this library; if not, write to the Free Software | ||
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | + */ | ||
20 | + | ||
21 | +#if !defined (__CPU_ALPHA_H__) | ||
22 | +#define __CPU_ALPHA_H__ | ||
23 | + | ||
24 | +#include "config.h" | ||
25 | + | ||
26 | +#define TARGET_LONG_BITS 64 | ||
27 | + | ||
28 | +#include "cpu-defs.h" | ||
29 | + | ||
30 | + | ||
31 | +#include <setjmp.h> | ||
32 | + | ||
33 | +#include "softfloat.h" | ||
34 | + | ||
35 | +/* XXX: put this in a common place */ | ||
36 | +#define likely(x) __builtin_expect(!!(x), 1) | ||
37 | +#define unlikely(x) __builtin_expect(!!(x), 0) | ||
38 | + | ||
39 | +#define TARGET_HAS_ICE 1 | ||
40 | + | ||
41 | +#define ELF_MACHINE EM_ALPHA | ||
42 | + | ||
43 | +#define ICACHE_LINE_SIZE 32 | ||
44 | +#define DCACHE_LINE_SIZE 32 | ||
45 | + | ||
46 | +#define TARGET_PAGE_BITS 12 | ||
47 | + | ||
48 | +#define VA_BITS 43 | ||
49 | + | ||
50 | +/* Alpha major type */ | ||
51 | +enum { | ||
52 | + ALPHA_EV3 = 1, | ||
53 | + ALPHA_EV4 = 2, | ||
54 | + ALPHA_SIM = 3, | ||
55 | + ALPHA_LCA = 4, | ||
56 | + ALPHA_EV5 = 5, /* 21164 */ | ||
57 | + ALPHA_EV45 = 6, /* 21064A */ | ||
58 | + ALPHA_EV56 = 7, /* 21164A */ | ||
59 | +}; | ||
60 | + | ||
61 | +/* EV4 minor type */ | ||
62 | +enum { | ||
63 | + ALPHA_EV4_2 = 0, | ||
64 | + ALPHA_EV4_3 = 1, | ||
65 | +}; | ||
66 | + | ||
67 | +/* LCA minor type */ | ||
68 | +enum { | ||
69 | + ALPHA_LCA_1 = 1, /* 21066 */ | ||
70 | + ALPHA_LCA_2 = 2, /* 20166 */ | ||
71 | + ALPHA_LCA_3 = 3, /* 21068 */ | ||
72 | + ALPHA_LCA_4 = 4, /* 21068 */ | ||
73 | + ALPHA_LCA_5 = 5, /* 21066A */ | ||
74 | + ALPHA_LCA_6 = 6, /* 21068A */ | ||
75 | +}; | ||
76 | + | ||
77 | +/* EV5 minor type */ | ||
78 | +enum { | ||
79 | + ALPHA_EV5_1 = 1, /* Rev BA, CA */ | ||
80 | + ALPHA_EV5_2 = 2, /* Rev DA, EA */ | ||
81 | + ALPHA_EV5_3 = 3, /* Pass 3 */ | ||
82 | + ALPHA_EV5_4 = 4, /* Pass 3.2 */ | ||
83 | + ALPHA_EV5_5 = 5, /* Pass 4 */ | ||
84 | +}; | ||
85 | + | ||
86 | +/* EV45 minor type */ | ||
87 | +enum { | ||
88 | + ALPHA_EV45_1 = 1, /* Pass 1 */ | ||
89 | + ALPHA_EV45_2 = 2, /* Pass 1.1 */ | ||
90 | + ALPHA_EV45_3 = 3, /* Pass 2 */ | ||
91 | +}; | ||
92 | + | ||
93 | +/* EV56 minor type */ | ||
94 | +enum { | ||
95 | + ALPHA_EV56_1 = 1, /* Pass 1 */ | ||
96 | + ALPHA_EV56_2 = 2, /* Pass 2 */ | ||
97 | +}; | ||
98 | + | ||
99 | +enum { | ||
100 | + IMPLVER_2106x = 0, /* EV4, EV45 & LCA45 */ | ||
101 | + IMPLVER_21164 = 1, /* EV5, EV56 & PCA45 */ | ||
102 | + IMPLVER_21264 = 2, /* EV6, EV67 & EV68x */ | ||
103 | + IMPLVER_21364 = 3, /* EV7 & EV79 */ | ||
104 | +}; | ||
105 | + | ||
106 | +enum { | ||
107 | + AMASK_BWX = 0x00000001, | ||
108 | + AMASK_FIX = 0x00000002, | ||
109 | + AMASK_CIX = 0x00000004, | ||
110 | + AMASK_MVI = 0x00000100, | ||
111 | + AMASK_TRAP = 0x00000200, | ||
112 | + AMASK_PREFETCH = 0x00001000, | ||
113 | +}; | ||
114 | + | ||
115 | +enum { | ||
116 | + VAX_ROUND_NORMAL = 0, | ||
117 | + VAX_ROUND_CHOPPED, | ||
118 | +}; | ||
119 | + | ||
120 | +enum { | ||
121 | + IEEE_ROUND_NORMAL = 0, | ||
122 | + IEEE_ROUND_DYNAMIC, | ||
123 | + IEEE_ROUND_PLUS, | ||
124 | + IEEE_ROUND_MINUS, | ||
125 | + IEEE_ROUND_CHOPPED, | ||
126 | +}; | ||
127 | + | ||
128 | +/* IEEE floating-point operations encoding */ | ||
129 | +/* Trap mode */ | ||
130 | +enum { | ||
131 | + FP_TRAP_I = 0x0, | ||
132 | + FP_TRAP_U = 0x1, | ||
133 | + FP_TRAP_S = 0x4, | ||
134 | + FP_TRAP_SU = 0x5, | ||
135 | + FP_TRAP_SUI = 0x7, | ||
136 | +}; | ||
137 | + | ||
138 | +/* Rounding mode */ | ||
139 | +enum { | ||
140 | + FP_ROUND_CHOPPED = 0x0, | ||
141 | + FP_ROUND_MINUS = 0x1, | ||
142 | + FP_ROUND_NORMAL = 0x2, | ||
143 | + FP_ROUND_DYNAMIC = 0x3, | ||
144 | +}; | ||
145 | + | ||
146 | +/* Internal processor registers */ | ||
147 | +/* XXX: TOFIX: most of those registers are implementation dependant */ | ||
148 | +enum { | ||
149 | + /* Ebox IPRs */ | ||
150 | + IPR_CC = 0xC0, | ||
151 | + IPR_CC_CTL = 0xC1, | ||
152 | + IPR_VA = 0xC2, | ||
153 | + IPR_VA_CTL = 0xC4, | ||
154 | + IPR_VA_FORM = 0xC3, | ||
155 | + /* Ibox IPRs */ | ||
156 | + IPR_ITB_TAG = 0x00, | ||
157 | + IPR_ITB_PTE = 0x01, | ||
158 | + IPT_ITB_IAP = 0x02, | ||
159 | + IPT_ITB_IA = 0x03, | ||
160 | + IPT_ITB_IS = 0x04, | ||
161 | + IPR_PMPC = 0x05, | ||
162 | + IPR_EXC_ADDR = 0x06, | ||
163 | + IPR_IVA_FORM = 0x07, | ||
164 | + IPR_CM = 0x09, | ||
165 | + IPR_IER = 0x0A, | ||
166 | + IPR_SIRR = 0x0C, | ||
167 | + IPR_ISUM = 0x0D, | ||
168 | + IPR_HW_INT_CLR = 0x0E, | ||
169 | + IPR_EXC_SUM = 0x0F, | ||
170 | + IPR_PAL_BASE = 0x10, | ||
171 | + IPR_I_CTL = 0x11, | ||
172 | + IPR_I_STAT = 0x16, | ||
173 | + IPR_IC_FLUSH = 0x13, | ||
174 | + IPR_IC_FLUSH_ASM = 0x12, | ||
175 | + IPR_CLR_MAP = 0x15, | ||
176 | + IPR_SLEEP = 0x17, | ||
177 | + IPR_PCTX = 0x40, | ||
178 | + IPR_PCTR_CTL = 0x14, | ||
179 | + /* Mbox IPRs */ | ||
180 | + IPR_DTB_TAG0 = 0x20, | ||
181 | + IPR_DTB_TAG1 = 0xA0, | ||
182 | + IPR_DTB_PTE0 = 0x21, | ||
183 | + IPR_DTB_PTE1 = 0xA1, | ||
184 | + IPR_DTB_ALTMODE = 0xA6, | ||
185 | + IPR_DTB_IAP = 0xA2, | ||
186 | + IPR_DTB_IA = 0xA3, | ||
187 | + IPR_DTB_IS0 = 0x24, | ||
188 | + IPR_DTB_IS1 = 0xA4, | ||
189 | + IPR_DTB_ASN0 = 0x25, | ||
190 | + IPR_DTB_ASN1 = 0xA5, | ||
191 | + IPR_MM_STAT = 0x27, | ||
192 | + IPR_M_CTL = 0x28, | ||
193 | + IPR_DC_CTL = 0x29, | ||
194 | + IPR_DC_STAT = 0x2A, | ||
195 | + /* Cbox IPRs */ | ||
196 | + IPR_C_DATA = 0x2B, | ||
197 | + IPR_C_SHIFT = 0x2C, | ||
198 | + | ||
199 | + IPR_ASN, | ||
200 | + IPR_ASTEN, | ||
201 | + IPR_ASTSR, | ||
202 | + IPR_DATFX, | ||
203 | + IPR_ESP, | ||
204 | + IPR_FEN, | ||
205 | + IPR_IPIR, | ||
206 | + IPR_IPL, | ||
207 | + IPR_KSP, | ||
208 | + IPR_MCES, | ||
209 | + IPR_PERFMON, | ||
210 | + IPR_PCBB, | ||
211 | + IPR_PRBR, | ||
212 | + IPR_PTBR, | ||
213 | + IPR_SCBB, | ||
214 | + IPR_SISR, | ||
215 | + IPR_SSP, | ||
216 | + IPR_SYSPTBR, | ||
217 | + IPR_TBCHK, | ||
218 | + IPR_TBIA, | ||
219 | + IPR_TBIAP, | ||
220 | + IPR_TBIS, | ||
221 | + IPR_TBISD, | ||
222 | + IPR_TBISI, | ||
223 | + IPR_USP, | ||
224 | + IPR_VIRBND, | ||
225 | + IPR_VPTB, | ||
226 | + IPR_WHAMI, | ||
227 | + IPR_ALT_MODE, | ||
228 | + IPR_LAST, | ||
229 | +}; | ||
230 | + | ||
231 | +typedef struct CPUAlphaState CPUAlphaState; | ||
232 | + | ||
233 | +typedef struct pal_handler_t pal_handler_t; | ||
234 | +struct pal_handler_t { | ||
235 | + /* Reset */ | ||
236 | + void (*reset)(CPUAlphaState *env); | ||
237 | + /* Uncorrectable hardware error */ | ||
238 | + void (*machine_check)(CPUAlphaState *env); | ||
239 | + /* Arithmetic exception */ | ||
240 | + void (*arithmetic)(CPUAlphaState *env); | ||
241 | + /* Interrupt / correctable hardware error */ | ||
242 | + void (*interrupt)(CPUAlphaState *env); | ||
243 | + /* Data fault */ | ||
244 | + void (*dfault)(CPUAlphaState *env); | ||
245 | + /* DTB miss pal */ | ||
246 | + void (*dtb_miss_pal)(CPUAlphaState *env); | ||
247 | + /* DTB miss native */ | ||
248 | + void (*dtb_miss_native)(CPUAlphaState *env); | ||
249 | + /* Unaligned access */ | ||
250 | + void (*unalign)(CPUAlphaState *env); | ||
251 | + /* ITB miss */ | ||
252 | + void (*itb_miss)(CPUAlphaState *env); | ||
253 | + /* Instruction stream access violation */ | ||
254 | + void (*itb_acv)(CPUAlphaState *env); | ||
255 | + /* Reserved or privileged opcode */ | ||
256 | + void (*opcdec)(CPUAlphaState *env); | ||
257 | + /* Floating point exception */ | ||
258 | + void (*fen)(CPUAlphaState *env); | ||
259 | + /* Call pal instruction */ | ||
260 | + void (*call_pal)(CPUAlphaState *env, uint32_t palcode); | ||
261 | +}; | ||
262 | + | ||
263 | +struct CPUAlphaState { | ||
264 | + uint64_t ir[31]; | ||
265 | + float64 fir[31]; | ||
266 | + float_status fp_status; | ||
267 | + uint64_t fpcr; | ||
268 | + uint64_t pc; | ||
269 | + uint64_t lock; | ||
270 | + uint32_t pcc[2]; | ||
271 | + uint64_t ipr[IPR_LAST]; | ||
272 | + uint64_t ps; | ||
273 | + uint64_t unique; | ||
274 | + int saved_mode; /* Used for HW_LD / HW_ST */ | ||
275 | + | ||
276 | + /* */ | ||
277 | + double ft0, ft1, ft2; | ||
278 | + | ||
279 | + /* Those resources are used only in Qemu core */ | ||
280 | + CPU_COMMON | ||
281 | + | ||
282 | + jmp_buf jmp_env; | ||
283 | + int user_mode_only; /* user mode only simulation */ | ||
284 | + uint32_t hflags; | ||
285 | + int halted; | ||
286 | + | ||
287 | + int exception_index; | ||
288 | + int error_code; | ||
289 | + int interrupt_request; | ||
290 | + | ||
291 | + uint32_t features; | ||
292 | + uint32_t amask; | ||
293 | + int implver; | ||
294 | + pal_handler_t *pal_handler; | ||
295 | +}; | ||
296 | + | ||
297 | +#include "cpu-all.h" | ||
298 | + | ||
299 | +enum { | ||
300 | + FEATURE_ASN = 0x00000001, | ||
301 | + FEATURE_SPS = 0x00000002, | ||
302 | + FEATURE_VIRBND = 0x00000004, | ||
303 | + FEATURE_TBCHK = 0x00000008, | ||
304 | +}; | ||
305 | + | ||
306 | +enum { | ||
307 | + EXCP_RESET = 0x0000, | ||
308 | + EXCP_MCHK = 0x0020, | ||
309 | + EXCP_ARITH = 0x0060, | ||
310 | + EXCP_HW_INTERRUPT = 0x00E0, | ||
311 | + EXCP_DFAULT = 0x01E0, | ||
312 | + EXCP_DTB_MISS_PAL = 0x09E0, | ||
313 | + EXCP_ITB_MISS = 0x03E0, | ||
314 | + EXCP_ITB_ACV = 0x07E0, | ||
315 | + EXCP_DTB_MISS_NATIVE = 0x08E0, | ||
316 | + EXCP_UNALIGN = 0x11E0, | ||
317 | + EXCP_OPCDEC = 0x13E0, | ||
318 | + EXCP_FEN = 0x17E0, | ||
319 | + EXCP_CALL_PAL = 0x2000, | ||
320 | + EXCP_CALL_PALP = 0x3000, | ||
321 | + EXCP_CALL_PALE = 0x4000, | ||
322 | + /* Pseudo exception for console */ | ||
323 | + EXCP_CONSOLE_DISPATCH = 0x4001, | ||
324 | + EXCP_CONSOLE_FIXUP = 0x4002, | ||
325 | +}; | ||
326 | + | ||
327 | +/* Arithmetic exception */ | ||
328 | +enum { | ||
329 | + EXCP_ARITH_OVERFLOW, | ||
330 | +}; | ||
331 | + | ||
332 | +enum { | ||
333 | + PALCODE_CALL = 0x00000000, | ||
334 | + PALCODE_LD = 0x01000000, | ||
335 | + PALCODE_ST = 0x02000000, | ||
336 | + PALCODE_MFPR = 0x03000000, | ||
337 | + PALCODE_MTPR = 0x04000000, | ||
338 | + PALCODE_REI = 0x05000000, | ||
339 | + PALCODE_INIT = 0xF0000000, | ||
340 | +}; | ||
341 | + | ||
342 | +enum { | ||
343 | + IR_V0 = 0, | ||
344 | + IR_T0 = 1, | ||
345 | + IR_T1 = 2, | ||
346 | + IR_T2 = 3, | ||
347 | + IR_T3 = 4, | ||
348 | + IR_T4 = 5, | ||
349 | + IR_T5 = 6, | ||
350 | + IR_T6 = 7, | ||
351 | + IR_T7 = 8, | ||
352 | + IR_S0 = 9, | ||
353 | + IR_S1 = 10, | ||
354 | + IR_S2 = 11, | ||
355 | + IR_S3 = 12, | ||
356 | + IR_S4 = 13, | ||
357 | + IR_S5 = 14, | ||
358 | + IR_S6 = 15, | ||
359 | +#define IR_FP IR_S6 | ||
360 | + IR_A0 = 16, | ||
361 | + IR_A1 = 17, | ||
362 | + IR_A2 = 18, | ||
363 | + IR_A3 = 19, | ||
364 | + IR_A4 = 20, | ||
365 | + IR_A5 = 21, | ||
366 | + IR_T8 = 22, | ||
367 | + IR_T9 = 23, | ||
368 | + IR_T10 = 24, | ||
369 | + IR_T11 = 25, | ||
370 | + IR_RA = 26, | ||
371 | + IR_T12 = 27, | ||
372 | +#define IR_PV IR_T12 | ||
373 | + IR_AT = 28, | ||
374 | + IR_GP = 29, | ||
375 | + IR_SP = 30, | ||
376 | + IR_ZERO = 31, | ||
377 | +}; | ||
378 | + | ||
379 | +int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp); | ||
380 | +int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp); | ||
381 | +void cpu_loop_exit (void); | ||
382 | +void pal_init (CPUState *env); | ||
383 | +void call_pal (CPUState *env, int palcode); | ||
384 | + | ||
385 | +#endif /* !defined (__CPU_ALPHA_H__) */ |
target-alpha/exec.h
0 → 100644
1 | +/* | ||
2 | + * Alpha emulation cpu run-time definitions for qemu. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Jocelyn Mayer | ||
5 | + * | ||
6 | + * This library is free software; you can redistribute it and/or | ||
7 | + * modify it under the terms of the GNU Lesser General Public | ||
8 | + * License as published by the Free Software Foundation; either | ||
9 | + * version 2 of the License, or (at your option) any later version. | ||
10 | + * | ||
11 | + * This library is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | + * Lesser General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public | ||
17 | + * License along with this library; if not, write to the Free Software | ||
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | + */ | ||
20 | + | ||
21 | +#if !defined (__ALPHA_EXEC_H__) | ||
22 | +#define __ALPHA_EXEC_H__ | ||
23 | + | ||
24 | +#include "config.h" | ||
25 | + | ||
26 | +#include "dyngen-exec.h" | ||
27 | + | ||
28 | +#define TARGET_LONG_BITS 64 | ||
29 | + | ||
30 | +register struct CPUAlphaState *env asm(AREG0); | ||
31 | + | ||
32 | +#if TARGET_LONG_BITS > HOST_LONG_BITS | ||
33 | + | ||
34 | +/* no registers can be used */ | ||
35 | +#define T0 (env->t0) | ||
36 | +#define T1 (env->t1) | ||
37 | +#define T2 (env->t2) | ||
38 | + | ||
39 | +#else | ||
40 | + | ||
41 | +register uint64_t T0 asm(AREG1); | ||
42 | +register uint64_t T1 asm(AREG2); | ||
43 | +register uint64_t T2 asm(AREG3); | ||
44 | + | ||
45 | +#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */ | ||
46 | + | ||
47 | +#define PARAM(n) ((uint64_t)PARAM##n) | ||
48 | +#define SPARAM(n) ((int32_t)PARAM##n) | ||
49 | +#define FT0 (env->ft0) | ||
50 | +#define FT1 (env->ft1) | ||
51 | +#define FT2 (env->ft2) | ||
52 | +#define FP_STATUS (env->fp_status) | ||
53 | + | ||
54 | +#if defined (DEBUG_OP) | ||
55 | +#define RETURN() __asm__ __volatile__("nop" : : : "memory"); | ||
56 | +#else | ||
57 | +#define RETURN() __asm__ __volatile__("" : : : "memory"); | ||
58 | +#endif | ||
59 | + | ||
60 | +#include "cpu.h" | ||
61 | +#include "exec-all.h" | ||
62 | + | ||
63 | +#if !defined(CONFIG_USER_ONLY) | ||
64 | +#include "softmmu_exec.h" | ||
65 | +#endif /* !defined(CONFIG_USER_ONLY) */ | ||
66 | + | ||
67 | +static inline void env_to_regs(void) | ||
68 | +{ | ||
69 | +} | ||
70 | + | ||
71 | +static inline void regs_to_env(void) | ||
72 | +{ | ||
73 | +} | ||
74 | + | ||
75 | +int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw, | ||
76 | + int is_user, int is_softmmu); | ||
77 | +int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp); | ||
78 | +int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp); | ||
79 | + | ||
80 | +void do_interrupt (CPUState *env); | ||
81 | + | ||
82 | +#endif /* !defined (__ALPHA_EXEC_H__) */ |
target-alpha/helper.c
0 → 100644
1 | +/* | ||
2 | + * Alpha emulation cpu helpers for qemu. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Jocelyn Mayer | ||
5 | + * | ||
6 | + * This library is free software; you can redistribute it and/or | ||
7 | + * modify it under the terms of the GNU Lesser General Public | ||
8 | + * License as published by the Free Software Foundation; either | ||
9 | + * version 2 of the License, or (at your option) any later version. | ||
10 | + * | ||
11 | + * This library is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | + * Lesser General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public | ||
17 | + * License along with this library; if not, write to the Free Software | ||
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | + */ | ||
20 | + | ||
21 | +#include <stdint.h> | ||
22 | +#include <stdlib.h> | ||
23 | +#include <stdio.h> | ||
24 | + | ||
25 | +#include "cpu.h" | ||
26 | +#include "exec-all.h" | ||
27 | + | ||
28 | +#if defined(CONFIG_USER_ONLY) | ||
29 | + | ||
30 | +int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
31 | + int is_user, int is_softmmu) | ||
32 | +{ | ||
33 | + if (rw == 2) | ||
34 | + env->exception_index = EXCP_ITB_MISS; | ||
35 | + else | ||
36 | + env->exception_index = EXCP_DFAULT; | ||
37 | + env->ipr[IPR_EXC_ADDR] = address; | ||
38 | + | ||
39 | + return 1; | ||
40 | +} | ||
41 | + | ||
42 | +target_ulong cpu_get_phys_page_debug (CPUState *env, target_ulong addr) | ||
43 | +{ | ||
44 | + return addr; | ||
45 | +} | ||
46 | + | ||
47 | +void do_interrupt (CPUState *env) | ||
48 | +{ | ||
49 | + env->exception_index = -1; | ||
50 | +} | ||
51 | + | ||
52 | +#else | ||
53 | + | ||
54 | +target_ulong cpu_get_phys_page_debug (CPUState *env, target_ulong addr) | ||
55 | +{ | ||
56 | + return -1; | ||
57 | +} | ||
58 | + | ||
59 | +int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
60 | + int is_user, int is_softmmu) | ||
61 | +{ | ||
62 | + uint32_t opc; | ||
63 | + | ||
64 | + if (rw == 2) { | ||
65 | + /* Instruction translation buffer miss */ | ||
66 | + env->exception_index = EXCP_ITB_MISS; | ||
67 | + } else { | ||
68 | + if (env->ipr[IPR_EXC_ADDR] & 1) | ||
69 | + env->exception_index = EXCP_DTB_MISS_PAL; | ||
70 | + else | ||
71 | + env->exception_index = EXCP_DTB_MISS_NATIVE; | ||
72 | + opc = (ldl_code(env->pc) >> 21) << 4; | ||
73 | + if (rw) { | ||
74 | + opc |= 0x9; | ||
75 | + } else { | ||
76 | + opc |= 0x4; | ||
77 | + } | ||
78 | + env->ipr[IPR_MM_STAT] = opc; | ||
79 | + } | ||
80 | + | ||
81 | + return 1; | ||
82 | +} | ||
83 | + | ||
84 | +int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp) | ||
85 | +{ | ||
86 | + uint64_t hwpcb; | ||
87 | + int ret = 0; | ||
88 | + | ||
89 | + hwpcb = env->ipr[IPR_PCBB]; | ||
90 | + switch (iprn) { | ||
91 | + case IPR_ASN: | ||
92 | + if (env->features & FEATURE_ASN) | ||
93 | + *valp = env->ipr[IPR_ASN]; | ||
94 | + else | ||
95 | + *valp = 0; | ||
96 | + break; | ||
97 | + case IPR_ASTEN: | ||
98 | + *valp = ((int64_t)(env->ipr[IPR_ASTEN] << 60)) >> 60; | ||
99 | + break; | ||
100 | + case IPR_ASTSR: | ||
101 | + *valp = ((int64_t)(env->ipr[IPR_ASTSR] << 60)) >> 60; | ||
102 | + break; | ||
103 | + case IPR_DATFX: | ||
104 | + /* Write only */ | ||
105 | + ret = -1; | ||
106 | + break; | ||
107 | + case IPR_ESP: | ||
108 | + if (env->features & FEATURE_SPS) | ||
109 | + *valp = env->ipr[IPR_ESP]; | ||
110 | + else | ||
111 | + *valp = ldq_raw(hwpcb + 8); | ||
112 | + break; | ||
113 | + case IPR_FEN: | ||
114 | + *valp = ((int64_t)(env->ipr[IPR_FEN] << 63)) >> 63; | ||
115 | + break; | ||
116 | + case IPR_IPIR: | ||
117 | + /* Write-only */ | ||
118 | + ret = -1; | ||
119 | + break; | ||
120 | + case IPR_IPL: | ||
121 | + *valp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59; | ||
122 | + break; | ||
123 | + case IPR_KSP: | ||
124 | + if (!(env->ipr[IPR_EXC_ADDR] & 1)) { | ||
125 | + ret = -1; | ||
126 | + } else { | ||
127 | + if (env->features & FEATURE_SPS) | ||
128 | + *valp = env->ipr[IPR_KSP]; | ||
129 | + else | ||
130 | + *valp = ldq_raw(hwpcb + 0); | ||
131 | + } | ||
132 | + break; | ||
133 | + case IPR_MCES: | ||
134 | + *valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59; | ||
135 | + break; | ||
136 | + case IPR_PERFMON: | ||
137 | + /* Implementation specific */ | ||
138 | + *valp = 0; | ||
139 | + break; | ||
140 | + case IPR_PCBB: | ||
141 | + *valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16; | ||
142 | + break; | ||
143 | + case IPR_PRBR: | ||
144 | + *valp = env->ipr[IPR_PRBR]; | ||
145 | + break; | ||
146 | + case IPR_PTBR: | ||
147 | + *valp = env->ipr[IPR_PTBR]; | ||
148 | + break; | ||
149 | + case IPR_SCBB: | ||
150 | + *valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]); | ||
151 | + break; | ||
152 | + case IPR_SIRR: | ||
153 | + /* Write-only */ | ||
154 | + ret = -1; | ||
155 | + break; | ||
156 | + case IPR_SISR: | ||
157 | + *valp = (int64_t)((int16_t)env->ipr[IPR_SISR]); | ||
158 | + case IPR_SSP: | ||
159 | + if (env->features & FEATURE_SPS) | ||
160 | + *valp = env->ipr[IPR_SSP]; | ||
161 | + else | ||
162 | + *valp = ldq_raw(hwpcb + 16); | ||
163 | + break; | ||
164 | + case IPR_SYSPTBR: | ||
165 | + if (env->features & FEATURE_VIRBND) | ||
166 | + *valp = env->ipr[IPR_SYSPTBR]; | ||
167 | + else | ||
168 | + ret = -1; | ||
169 | + break; | ||
170 | + case IPR_TBCHK: | ||
171 | + if ((env->features & FEATURE_TBCHK)) { | ||
172 | + /* XXX: TODO */ | ||
173 | + *valp = 0; | ||
174 | + ret = -1; | ||
175 | + } else { | ||
176 | + ret = -1; | ||
177 | + } | ||
178 | + break; | ||
179 | + case IPR_TBIA: | ||
180 | + /* Write-only */ | ||
181 | + ret = -1; | ||
182 | + break; | ||
183 | + case IPR_TBIAP: | ||
184 | + /* Write-only */ | ||
185 | + ret = -1; | ||
186 | + break; | ||
187 | + case IPR_TBIS: | ||
188 | + /* Write-only */ | ||
189 | + ret = -1; | ||
190 | + break; | ||
191 | + case IPR_TBISD: | ||
192 | + /* Write-only */ | ||
193 | + ret = -1; | ||
194 | + break; | ||
195 | + case IPR_TBISI: | ||
196 | + /* Write-only */ | ||
197 | + ret = -1; | ||
198 | + break; | ||
199 | + case IPR_USP: | ||
200 | + if (env->features & FEATURE_SPS) | ||
201 | + *valp = env->ipr[IPR_USP]; | ||
202 | + else | ||
203 | + *valp = ldq_raw(hwpcb + 24); | ||
204 | + break; | ||
205 | + case IPR_VIRBND: | ||
206 | + if (env->features & FEATURE_VIRBND) | ||
207 | + *valp = env->ipr[IPR_VIRBND]; | ||
208 | + else | ||
209 | + ret = -1; | ||
210 | + break; | ||
211 | + case IPR_VPTB: | ||
212 | + *valp = env->ipr[IPR_VPTB]; | ||
213 | + break; | ||
214 | + case IPR_WHAMI: | ||
215 | + *valp = env->ipr[IPR_WHAMI]; | ||
216 | + break; | ||
217 | + default: | ||
218 | + /* Invalid */ | ||
219 | + ret = -1; | ||
220 | + break; | ||
221 | + } | ||
222 | + | ||
223 | + return ret; | ||
224 | +} | ||
225 | + | ||
226 | +int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp) | ||
227 | +{ | ||
228 | + uint64_t hwpcb, tmp64; | ||
229 | + uint8_t tmp8; | ||
230 | + int ret = 0; | ||
231 | + | ||
232 | + hwpcb = env->ipr[IPR_PCBB]; | ||
233 | + switch (iprn) { | ||
234 | + case IPR_ASN: | ||
235 | + /* Read-only */ | ||
236 | + ret = -1; | ||
237 | + break; | ||
238 | + case IPR_ASTEN: | ||
239 | + tmp8 = ((int8_t)(env->ipr[IPR_ASTEN] << 4)) >> 4; | ||
240 | + *oldvalp = tmp8; | ||
241 | + tmp8 &= val & 0xF; | ||
242 | + tmp8 |= (val >> 4) & 0xF; | ||
243 | + env->ipr[IPR_ASTEN] &= ~0xF; | ||
244 | + env->ipr[IPR_ASTEN] |= tmp8; | ||
245 | + ret = 1; | ||
246 | + break; | ||
247 | + case IPR_ASTSR: | ||
248 | + tmp8 = ((int8_t)(env->ipr[IPR_ASTSR] << 4)) >> 4; | ||
249 | + *oldvalp = tmp8; | ||
250 | + tmp8 &= val & 0xF; | ||
251 | + tmp8 |= (val >> 4) & 0xF; | ||
252 | + env->ipr[IPR_ASTSR] &= ~0xF; | ||
253 | + env->ipr[IPR_ASTSR] |= tmp8; | ||
254 | + ret = 1; | ||
255 | + case IPR_DATFX: | ||
256 | + env->ipr[IPR_DATFX] &= ~0x1; | ||
257 | + env->ipr[IPR_DATFX] |= val & 1; | ||
258 | + tmp64 = ldq_raw(hwpcb + 56); | ||
259 | + tmp64 &= ~0x8000000000000000ULL; | ||
260 | + tmp64 |= (val & 1) << 63; | ||
261 | + stq_raw(hwpcb + 56, tmp64); | ||
262 | + break; | ||
263 | + case IPR_ESP: | ||
264 | + if (env->features & FEATURE_SPS) | ||
265 | + env->ipr[IPR_ESP] = val; | ||
266 | + else | ||
267 | + stq_raw(hwpcb + 8, val); | ||
268 | + break; | ||
269 | + case IPR_FEN: | ||
270 | + env->ipr[IPR_FEN] = val & 1; | ||
271 | + tmp64 = ldq_raw(hwpcb + 56); | ||
272 | + tmp64 &= ~1; | ||
273 | + tmp64 |= val & 1; | ||
274 | + stq_raw(hwpcb + 56, tmp64); | ||
275 | + break; | ||
276 | + case IPR_IPIR: | ||
277 | + /* XXX: TODO: Send IRQ to CPU #ir[16] */ | ||
278 | + break; | ||
279 | + case IPR_IPL: | ||
280 | + *oldvalp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59; | ||
281 | + env->ipr[IPR_IPL] &= ~0x1F; | ||
282 | + env->ipr[IPR_IPL] |= val & 0x1F; | ||
283 | + /* XXX: may issue an interrupt or ASR _now_ */ | ||
284 | + ret = 1; | ||
285 | + break; | ||
286 | + case IPR_KSP: | ||
287 | + if (!(env->ipr[IPR_EXC_ADDR] & 1)) { | ||
288 | + ret = -1; | ||
289 | + } else { | ||
290 | + if (env->features & FEATURE_SPS) | ||
291 | + env->ipr[IPR_KSP] = val; | ||
292 | + else | ||
293 | + stq_raw(hwpcb + 0, val); | ||
294 | + } | ||
295 | + break; | ||
296 | + case IPR_MCES: | ||
297 | + env->ipr[IPR_MCES] &= ~((val & 0x7) | 0x18); | ||
298 | + env->ipr[IPR_MCES] |= val & 0x18; | ||
299 | + break; | ||
300 | + case IPR_PERFMON: | ||
301 | + /* Implementation specific */ | ||
302 | + *oldvalp = 0; | ||
303 | + ret = 1; | ||
304 | + break; | ||
305 | + case IPR_PCBB: | ||
306 | + /* Read-only */ | ||
307 | + ret = -1; | ||
308 | + break; | ||
309 | + case IPR_PRBR: | ||
310 | + env->ipr[IPR_PRBR] = val; | ||
311 | + break; | ||
312 | + case IPR_PTBR: | ||
313 | + /* Read-only */ | ||
314 | + ret = -1; | ||
315 | + break; | ||
316 | + case IPR_SCBB: | ||
317 | + env->ipr[IPR_SCBB] = (uint32_t)val; | ||
318 | + break; | ||
319 | + case IPR_SIRR: | ||
320 | + if (val & 0xF) { | ||
321 | + env->ipr[IPR_SISR] |= 1 << (val & 0xF); | ||
322 | + /* XXX: request a software interrupt _now_ */ | ||
323 | + } | ||
324 | + break; | ||
325 | + case IPR_SISR: | ||
326 | + /* Read-only */ | ||
327 | + ret = -1; | ||
328 | + break; | ||
329 | + case IPR_SSP: | ||
330 | + if (env->features & FEATURE_SPS) | ||
331 | + env->ipr[IPR_SSP] = val; | ||
332 | + else | ||
333 | + stq_raw(hwpcb + 16, val); | ||
334 | + break; | ||
335 | + case IPR_SYSPTBR: | ||
336 | + if (env->features & FEATURE_VIRBND) | ||
337 | + env->ipr[IPR_SYSPTBR] = val; | ||
338 | + else | ||
339 | + ret = -1; | ||
340 | + case IPR_TBCHK: | ||
341 | + /* Read-only */ | ||
342 | + ret = -1; | ||
343 | + break; | ||
344 | + case IPR_TBIA: | ||
345 | + tlb_flush(env, 1); | ||
346 | + break; | ||
347 | + case IPR_TBIAP: | ||
348 | + tlb_flush(env, 1); | ||
349 | + break; | ||
350 | + case IPR_TBIS: | ||
351 | + tlb_flush_page(env, val); | ||
352 | + break; | ||
353 | + case IPR_TBISD: | ||
354 | + tlb_flush_page(env, val); | ||
355 | + break; | ||
356 | + case IPR_TBISI: | ||
357 | + tlb_flush_page(env, val); | ||
358 | + break; | ||
359 | + case IPR_USP: | ||
360 | + if (env->features & FEATURE_SPS) | ||
361 | + env->ipr[IPR_USP] = val; | ||
362 | + else | ||
363 | + stq_raw(hwpcb + 24, val); | ||
364 | + break; | ||
365 | + case IPR_VIRBND: | ||
366 | + if (env->features & FEATURE_VIRBND) | ||
367 | + env->ipr[IPR_VIRBND] = val; | ||
368 | + else | ||
369 | + ret = -1; | ||
370 | + break; | ||
371 | + case IPR_VPTB: | ||
372 | + env->ipr[IPR_VPTB] = val; | ||
373 | + break; | ||
374 | + case IPR_WHAMI: | ||
375 | + /* Read-only */ | ||
376 | + ret = -1; | ||
377 | + break; | ||
378 | + default: | ||
379 | + /* Invalid */ | ||
380 | + ret = -1; | ||
381 | + break; | ||
382 | + } | ||
383 | + | ||
384 | + return ret; | ||
385 | +} | ||
386 | + | ||
387 | +void do_interrupt (CPUState *env) | ||
388 | +{ | ||
389 | + int excp; | ||
390 | + | ||
391 | + env->ipr[IPR_EXC_ADDR] = env->pc | 1; | ||
392 | + excp = env->exception_index; | ||
393 | + env->exception_index = 0; | ||
394 | + env->error_code = 0; | ||
395 | + /* XXX: disable interrupts and memory mapping */ | ||
396 | + if (env->ipr[IPR_PAL_BASE] != -1ULL) { | ||
397 | + /* We use native PALcode */ | ||
398 | + env->pc = env->ipr[IPR_PAL_BASE] + excp; | ||
399 | + } else { | ||
400 | + /* We use emulated PALcode */ | ||
401 | + call_pal(env); | ||
402 | + /* Emulate REI */ | ||
403 | + env->pc = env->ipr[IPR_EXC_ADDR] & ~7; | ||
404 | + env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1; | ||
405 | + /* XXX: re-enable interrupts and memory mapping */ | ||
406 | + } | ||
407 | +} | ||
408 | +#endif | ||
409 | + | ||
410 | +void cpu_dump_state (CPUState *env, FILE *f, | ||
411 | + int (*cpu_fprintf)(FILE *f, const char *fmt, ...), | ||
412 | + int flags) | ||
413 | +{ | ||
414 | + static unsigned char *linux_reg_names[] = { | ||
415 | + "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ", | ||
416 | + "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ", | ||
417 | + "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ", | ||
418 | + "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero", | ||
419 | + }; | ||
420 | + int i; | ||
421 | + | ||
422 | + cpu_fprintf(f, " PC " TARGET_FMT_lx " PS " TARGET_FMT_lx "\n", | ||
423 | + env->pc, env->ps); | ||
424 | + for (i = 0; i < 31; i++) { | ||
425 | + cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i, | ||
426 | + linux_reg_names[i], env->ir[i]); | ||
427 | + if ((i % 3) == 2) | ||
428 | + cpu_fprintf(f, "\n"); | ||
429 | + } | ||
430 | + cpu_fprintf(f, "\n"); | ||
431 | + for (i = 0; i < 31; i++) { | ||
432 | + cpu_fprintf(f, "FIR%02d " TARGET_FMT_lx " ", i, | ||
433 | + *((uint64_t *)(&env->fir[i]))); | ||
434 | + if ((i % 3) == 2) | ||
435 | + cpu_fprintf(f, "\n"); | ||
436 | + } | ||
437 | + cpu_fprintf(f, "FT " TARGET_FMT_lx " " TARGET_FMT_lx " " TARGET_FMT_lx, | ||
438 | + *((uint64_t *)(&env->ft0)), *((uint64_t *)(&env->ft1)), | ||
439 | + *((uint64_t *)(&env->ft2))); | ||
440 | + cpu_fprintf(f, "\nMEM " TARGET_FMT_lx " %d %d\n", | ||
441 | + ldq_raw(0x000000004007df60ULL), | ||
442 | + (uint8_t *)(&env->ft0), (uint8_t *)(&env->fir[0])); | ||
443 | +} | ||
444 | + | ||
445 | +void cpu_dump_EA (target_ulong EA) | ||
446 | +{ | ||
447 | + FILE *f; | ||
448 | + | ||
449 | + if (logfile) | ||
450 | + f = logfile; | ||
451 | + else | ||
452 | + f = stdout; | ||
453 | + fprintf(f, "Memory access at address " TARGET_FMT_lx "\n", EA); | ||
454 | +} |
target-alpha/op.c
0 → 100644
1 | +/* | ||
2 | + * Alpha emulation cpu micro-operations for qemu. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Jocelyn Mayer | ||
5 | + * | ||
6 | + * This library is free software; you can redistribute it and/or | ||
7 | + * modify it under the terms of the GNU Lesser General Public | ||
8 | + * License as published by the Free Software Foundation; either | ||
9 | + * version 2 of the License, or (at your option) any later version. | ||
10 | + * | ||
11 | + * This library is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | + * Lesser General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public | ||
17 | + * License along with this library; if not, write to the Free Software | ||
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | + */ | ||
20 | + | ||
21 | +#define DEBUG_OP | ||
22 | + | ||
23 | +#include "config.h" | ||
24 | +#include "exec.h" | ||
25 | + | ||
26 | +#include "op_helper.h" | ||
27 | + | ||
28 | +#define REG 0 | ||
29 | +#include "op_template.h" | ||
30 | + | ||
31 | +#define REG 1 | ||
32 | +#include "op_template.h" | ||
33 | + | ||
34 | +#define REG 2 | ||
35 | +#include "op_template.h" | ||
36 | + | ||
37 | +#define REG 3 | ||
38 | +#include "op_template.h" | ||
39 | + | ||
40 | +#define REG 4 | ||
41 | +#include "op_template.h" | ||
42 | + | ||
43 | +#define REG 5 | ||
44 | +#include "op_template.h" | ||
45 | + | ||
46 | +#define REG 6 | ||
47 | +#include "op_template.h" | ||
48 | + | ||
49 | +#define REG 7 | ||
50 | +#include "op_template.h" | ||
51 | + | ||
52 | +#define REG 8 | ||
53 | +#include "op_template.h" | ||
54 | + | ||
55 | +#define REG 9 | ||
56 | +#include "op_template.h" | ||
57 | + | ||
58 | +#define REG 10 | ||
59 | +#include "op_template.h" | ||
60 | + | ||
61 | +#define REG 11 | ||
62 | +#include "op_template.h" | ||
63 | + | ||
64 | +#define REG 12 | ||
65 | +#include "op_template.h" | ||
66 | + | ||
67 | +#define REG 13 | ||
68 | +#include "op_template.h" | ||
69 | + | ||
70 | +#define REG 14 | ||
71 | +#include "op_template.h" | ||
72 | + | ||
73 | +#define REG 15 | ||
74 | +#include "op_template.h" | ||
75 | + | ||
76 | +#define REG 16 | ||
77 | +#include "op_template.h" | ||
78 | + | ||
79 | +#define REG 17 | ||
80 | +#include "op_template.h" | ||
81 | + | ||
82 | +#define REG 18 | ||
83 | +#include "op_template.h" | ||
84 | + | ||
85 | +#define REG 19 | ||
86 | +#include "op_template.h" | ||
87 | + | ||
88 | +#define REG 20 | ||
89 | +#include "op_template.h" | ||
90 | + | ||
91 | +#define REG 21 | ||
92 | +#include "op_template.h" | ||
93 | + | ||
94 | +#define REG 22 | ||
95 | +#include "op_template.h" | ||
96 | + | ||
97 | +#define REG 23 | ||
98 | +#include "op_template.h" | ||
99 | + | ||
100 | +#define REG 24 | ||
101 | +#include "op_template.h" | ||
102 | + | ||
103 | +#define REG 25 | ||
104 | +#include "op_template.h" | ||
105 | + | ||
106 | +#define REG 26 | ||
107 | +#include "op_template.h" | ||
108 | + | ||
109 | +#define REG 27 | ||
110 | +#include "op_template.h" | ||
111 | + | ||
112 | +#define REG 28 | ||
113 | +#include "op_template.h" | ||
114 | + | ||
115 | +#define REG 29 | ||
116 | +#include "op_template.h" | ||
117 | + | ||
118 | +#define REG 30 | ||
119 | +#include "op_template.h" | ||
120 | + | ||
121 | +#define REG 31 | ||
122 | +#include "op_template.h" | ||
123 | + | ||
124 | +/* Debug stuff */ | ||
125 | +void OPPROTO op_no_op (void) | ||
126 | +{ | ||
127 | +#if !defined (DEBUG_OP) | ||
128 | + __asm__ __volatile__("nop" : : : "memory"); | ||
129 | +#endif | ||
130 | + RETURN(); | ||
131 | +} | ||
132 | + | ||
133 | +void OPPROTO op_tb_flush (void) | ||
134 | +{ | ||
135 | + helper_tb_flush(); | ||
136 | + RETURN(); | ||
137 | +} | ||
138 | + | ||
139 | +/* Load and stores */ | ||
140 | +#define MEMSUFFIX _raw | ||
141 | +#include "op_mem.h" | ||
142 | +#if !defined(CONFIG_USER_ONLY) | ||
143 | +#define MEMSUFFIX _user | ||
144 | +#include "op_mem.h" | ||
145 | +#define MEMSUFFIX _kernel | ||
146 | +#include "op_mem.h" | ||
147 | +/* Those are used for supervisor, executive and pal modes */ | ||
148 | +#define MEMSUFFIX _data | ||
149 | +#include "op_mem.h" | ||
150 | +#endif | ||
151 | + | ||
152 | +/* Special operation for load and store */ | ||
153 | +void OPPROTO op_n7 (void) | ||
154 | +{ | ||
155 | + T0 &= ~(uint64_t)0x7; | ||
156 | + RETURN(); | ||
157 | +} | ||
158 | + | ||
159 | +/* Misc */ | ||
160 | +void OPPROTO op_excp (void) | ||
161 | +{ | ||
162 | + helper_excp(PARAM(1), PARAM(2)); | ||
163 | + RETURN(); | ||
164 | +} | ||
165 | + | ||
166 | +void OPPROTO op_load_amask (void) | ||
167 | +{ | ||
168 | + helper_amask(); | ||
169 | + RETURN(); | ||
170 | +} | ||
171 | + | ||
172 | +void OPPROTO op_load_pcc (void) | ||
173 | +{ | ||
174 | + helper_load_pcc(); | ||
175 | + RETURN(); | ||
176 | +} | ||
177 | + | ||
178 | +void OPPROTO op_load_implver (void) | ||
179 | +{ | ||
180 | + helper_load_implver(); | ||
181 | + RETURN(); | ||
182 | +} | ||
183 | + | ||
184 | +void OPPROTO op_load_fpcr (void) | ||
185 | +{ | ||
186 | + helper_load_fpcr(); | ||
187 | + RETURN(); | ||
188 | +} | ||
189 | + | ||
190 | +void OPPROTO op_store_fpcr (void) | ||
191 | +{ | ||
192 | + helper_store_fpcr(); | ||
193 | + RETURN(); | ||
194 | +} | ||
195 | + | ||
196 | +void OPPROTO op_load_irf (void) | ||
197 | +{ | ||
198 | + helper_load_irf(); | ||
199 | + RETURN(); | ||
200 | +} | ||
201 | + | ||
202 | +void OPPROTO op_set_irf (void) | ||
203 | +{ | ||
204 | + helper_set_irf(); | ||
205 | + RETURN(); | ||
206 | +} | ||
207 | + | ||
208 | +void OPPROTO op_clear_irf (void) | ||
209 | +{ | ||
210 | + helper_clear_irf(); | ||
211 | + RETURN(); | ||
212 | +} | ||
213 | + | ||
214 | +void OPPROTO op_exit_tb (void) | ||
215 | +{ | ||
216 | + EXIT_TB(); | ||
217 | +} | ||
218 | + | ||
219 | +/* Arithmetic */ | ||
220 | +void OPPROTO op_addq (void) | ||
221 | +{ | ||
222 | + T0 += T1; | ||
223 | + RETURN(); | ||
224 | +} | ||
225 | + | ||
226 | +void OPPROTO op_addqv (void) | ||
227 | +{ | ||
228 | + helper_addqv(); | ||
229 | + RETURN(); | ||
230 | +} | ||
231 | + | ||
232 | +void OPPROTO op_addl (void) | ||
233 | +{ | ||
234 | + T0 = (int64_t)((int32_t)(T0 + T1)); | ||
235 | + RETURN(); | ||
236 | +} | ||
237 | + | ||
238 | +void OPPROTO op_addlv (void) | ||
239 | +{ | ||
240 | + helper_addlv(); | ||
241 | + RETURN(); | ||
242 | +} | ||
243 | + | ||
244 | +void OPPROTO op_subq (void) | ||
245 | +{ | ||
246 | + T0 -= T1; | ||
247 | + RETURN(); | ||
248 | +} | ||
249 | + | ||
250 | +void OPPROTO op_subqv (void) | ||
251 | +{ | ||
252 | + helper_subqv(); | ||
253 | + RETURN(); | ||
254 | +} | ||
255 | + | ||
256 | +void OPPROTO op_subl (void) | ||
257 | +{ | ||
258 | + T0 = (int64_t)((int32_t)(T0 - T1)); | ||
259 | + RETURN(); | ||
260 | +} | ||
261 | + | ||
262 | +void OPPROTO op_sublv (void) | ||
263 | +{ | ||
264 | + helper_sublv(); | ||
265 | + RETURN(); | ||
266 | +} | ||
267 | + | ||
268 | +void OPPROTO op_s4 (void) | ||
269 | +{ | ||
270 | + T0 <<= 2; | ||
271 | + RETURN(); | ||
272 | +} | ||
273 | + | ||
274 | +void OPPROTO op_s8 (void) | ||
275 | +{ | ||
276 | + T0 <<= 3; | ||
277 | + RETURN(); | ||
278 | +} | ||
279 | + | ||
280 | +void OPPROTO op_mull (void) | ||
281 | +{ | ||
282 | + T0 = (int64_t)((int32_t)T0 * (int32_t)T1); | ||
283 | + RETURN(); | ||
284 | +} | ||
285 | + | ||
286 | +void OPPROTO op_mullv (void) | ||
287 | +{ | ||
288 | + helper_mullv(); | ||
289 | + RETURN(); | ||
290 | +} | ||
291 | + | ||
292 | +void OPPROTO op_mulq (void) | ||
293 | +{ | ||
294 | + T0 *= T1; | ||
295 | + RETURN(); | ||
296 | +} | ||
297 | + | ||
298 | +void OPPROTO op_mulqv (void) | ||
299 | +{ | ||
300 | + helper_mulqv(); | ||
301 | + RETURN(); | ||
302 | +} | ||
303 | + | ||
304 | +void OPPROTO op_umulh (void) | ||
305 | +{ | ||
306 | + helper_umulh(); | ||
307 | + RETURN(); | ||
308 | +} | ||
309 | + | ||
310 | +/* Logical */ | ||
311 | +void OPPROTO op_and (void) | ||
312 | +{ | ||
313 | + T0 &= T1; | ||
314 | + RETURN(); | ||
315 | +} | ||
316 | + | ||
317 | +void OPPROTO op_bic (void) | ||
318 | +{ | ||
319 | + T0 &= ~T1; | ||
320 | + RETURN(); | ||
321 | +} | ||
322 | + | ||
323 | +void OPPROTO op_bis (void) | ||
324 | +{ | ||
325 | + T0 |= T1; | ||
326 | + RETURN(); | ||
327 | +} | ||
328 | + | ||
329 | +void OPPROTO op_eqv (void) | ||
330 | +{ | ||
331 | + T0 ^= ~T1; | ||
332 | + RETURN(); | ||
333 | +} | ||
334 | + | ||
335 | +void OPPROTO op_ornot (void) | ||
336 | +{ | ||
337 | + T0 |= ~T1; | ||
338 | + RETURN(); | ||
339 | +} | ||
340 | + | ||
341 | +void OPPROTO op_xor (void) | ||
342 | +{ | ||
343 | + T0 ^= T1; | ||
344 | + RETURN(); | ||
345 | +} | ||
346 | + | ||
347 | +void OPPROTO op_sll (void) | ||
348 | +{ | ||
349 | + T0 <<= T1; | ||
350 | + RETURN(); | ||
351 | +} | ||
352 | + | ||
353 | +void OPPROTO op_srl (void) | ||
354 | +{ | ||
355 | + T0 >>= T1; | ||
356 | + RETURN(); | ||
357 | +} | ||
358 | + | ||
359 | +void OPPROTO op_sra (void) | ||
360 | +{ | ||
361 | + T0 = (int64_t)T0 >> T1; | ||
362 | + RETURN(); | ||
363 | +} | ||
364 | + | ||
365 | +void OPPROTO op_sextb (void) | ||
366 | +{ | ||
367 | + T0 = (int64_t)((int8_t)T0); | ||
368 | + RETURN(); | ||
369 | +} | ||
370 | + | ||
371 | +void OPPROTO op_sextw (void) | ||
372 | +{ | ||
373 | + T0 = (int64_t)((int16_t)T0); | ||
374 | + RETURN(); | ||
375 | + | ||
376 | +} | ||
377 | + | ||
378 | +void OPPROTO op_ctpop (void) | ||
379 | +{ | ||
380 | + helper_ctpop(); | ||
381 | + RETURN(); | ||
382 | +} | ||
383 | + | ||
384 | +void OPPROTO op_ctlz (void) | ||
385 | +{ | ||
386 | + helper_ctlz(); | ||
387 | + RETURN(); | ||
388 | +} | ||
389 | + | ||
390 | +void OPPROTO op_cttz (void) | ||
391 | +{ | ||
392 | + helper_cttz(); | ||
393 | + RETURN(); | ||
394 | +} | ||
395 | + | ||
396 | +void OPPROTO op_mskbl (void) | ||
397 | +{ | ||
398 | + helper_mskbl(); | ||
399 | + RETURN(); | ||
400 | +} | ||
401 | + | ||
402 | +void OPPROTO op_extbl (void) | ||
403 | +{ | ||
404 | + helper_extbl(); | ||
405 | + RETURN(); | ||
406 | +} | ||
407 | + | ||
408 | +void OPPROTO op_insbl (void) | ||
409 | +{ | ||
410 | + helper_insbl(); | ||
411 | + RETURN(); | ||
412 | +} | ||
413 | + | ||
414 | +void OPPROTO op_mskwl (void) | ||
415 | +{ | ||
416 | + helper_mskwl(); | ||
417 | + RETURN(); | ||
418 | +} | ||
419 | + | ||
420 | +void OPPROTO op_extwl (void) | ||
421 | +{ | ||
422 | + helper_extwl(); | ||
423 | + RETURN(); | ||
424 | +} | ||
425 | + | ||
426 | +void OPPROTO op_inswl (void) | ||
427 | +{ | ||
428 | + helper_inswl(); | ||
429 | + RETURN(); | ||
430 | +} | ||
431 | + | ||
432 | +void OPPROTO op_mskll (void) | ||
433 | +{ | ||
434 | + helper_mskll(); | ||
435 | + RETURN(); | ||
436 | +} | ||
437 | + | ||
438 | +void OPPROTO op_extll (void) | ||
439 | +{ | ||
440 | + helper_extll(); | ||
441 | + RETURN(); | ||
442 | +} | ||
443 | + | ||
444 | +void OPPROTO op_insll (void) | ||
445 | +{ | ||
446 | + helper_insll(); | ||
447 | + RETURN(); | ||
448 | +} | ||
449 | + | ||
450 | +void OPPROTO op_zap (void) | ||
451 | +{ | ||
452 | + helper_zap(); | ||
453 | + RETURN(); | ||
454 | +} | ||
455 | + | ||
456 | +void OPPROTO op_zapnot (void) | ||
457 | +{ | ||
458 | + helper_zapnot(); | ||
459 | + RETURN(); | ||
460 | +} | ||
461 | + | ||
462 | +void OPPROTO op_mskql (void) | ||
463 | +{ | ||
464 | + helper_mskql(); | ||
465 | + RETURN(); | ||
466 | +} | ||
467 | + | ||
468 | +void OPPROTO op_extql (void) | ||
469 | +{ | ||
470 | + helper_extql(); | ||
471 | + RETURN(); | ||
472 | +} | ||
473 | + | ||
474 | +void OPPROTO op_insql (void) | ||
475 | +{ | ||
476 | + helper_insql(); | ||
477 | + RETURN(); | ||
478 | +} | ||
479 | + | ||
480 | +void OPPROTO op_mskwh (void) | ||
481 | +{ | ||
482 | + helper_mskwh(); | ||
483 | + RETURN(); | ||
484 | +} | ||
485 | + | ||
486 | +void OPPROTO op_inswh (void) | ||
487 | +{ | ||
488 | + helper_inswh(); | ||
489 | + RETURN(); | ||
490 | +} | ||
491 | + | ||
492 | +void OPPROTO op_extwh (void) | ||
493 | +{ | ||
494 | + helper_extwh(); | ||
495 | + RETURN(); | ||
496 | +} | ||
497 | + | ||
498 | +void OPPROTO op_msklh (void) | ||
499 | +{ | ||
500 | + helper_msklh(); | ||
501 | + RETURN(); | ||
502 | +} | ||
503 | + | ||
504 | +void OPPROTO op_inslh (void) | ||
505 | +{ | ||
506 | + helper_inslh(); | ||
507 | + RETURN(); | ||
508 | +} | ||
509 | + | ||
510 | +void OPPROTO op_extlh (void) | ||
511 | +{ | ||
512 | + helper_extlh(); | ||
513 | + RETURN(); | ||
514 | +} | ||
515 | + | ||
516 | +void OPPROTO op_mskqh (void) | ||
517 | +{ | ||
518 | + helper_mskqh(); | ||
519 | + RETURN(); | ||
520 | +} | ||
521 | + | ||
522 | +void OPPROTO op_insqh (void) | ||
523 | +{ | ||
524 | + helper_insqh(); | ||
525 | + RETURN(); | ||
526 | +} | ||
527 | + | ||
528 | +void OPPROTO op_extqh (void) | ||
529 | +{ | ||
530 | + helper_extqh(); | ||
531 | + RETURN(); | ||
532 | +} | ||
533 | + | ||
534 | +/* Tests */ | ||
535 | +void OPPROTO op_cmpult (void) | ||
536 | +{ | ||
537 | + if (T0 < T1) | ||
538 | + T0 = 1; | ||
539 | + else | ||
540 | + T0 = 0; | ||
541 | + RETURN(); | ||
542 | +} | ||
543 | + | ||
544 | +void OPPROTO op_cmpule (void) | ||
545 | +{ | ||
546 | + if (T0 <= T1) | ||
547 | + T0 = 1; | ||
548 | + else | ||
549 | + T0 = 0; | ||
550 | + RETURN(); | ||
551 | +} | ||
552 | + | ||
553 | +void OPPROTO op_cmpeq (void) | ||
554 | +{ | ||
555 | + if (T0 == T1) | ||
556 | + T0 = 1; | ||
557 | + else | ||
558 | + T0 = 0; | ||
559 | + RETURN(); | ||
560 | +} | ||
561 | + | ||
562 | +void OPPROTO op_cmplt (void) | ||
563 | +{ | ||
564 | + if ((int64_t)T0 < (int64_t)T1) | ||
565 | + T0 = 1; | ||
566 | + else | ||
567 | + T0 = 0; | ||
568 | + RETURN(); | ||
569 | +} | ||
570 | + | ||
571 | +void OPPROTO op_cmple (void) | ||
572 | +{ | ||
573 | + if ((int64_t)T0 <= (int64_t)T1) | ||
574 | + T0 = 1; | ||
575 | + else | ||
576 | + T0 = 0; | ||
577 | + RETURN(); | ||
578 | +} | ||
579 | + | ||
580 | +void OPPROTO op_cmpbge (void) | ||
581 | +{ | ||
582 | + helper_cmpbge(); | ||
583 | + RETURN(); | ||
584 | +} | ||
585 | + | ||
586 | +void OPPROTO op_cmpeqz (void) | ||
587 | +{ | ||
588 | + if (T0 == 0) | ||
589 | + T0 = 1; | ||
590 | + else | ||
591 | + T0 = 0; | ||
592 | + RETURN(); | ||
593 | +} | ||
594 | + | ||
595 | +void OPPROTO op_cmpnez (void) | ||
596 | +{ | ||
597 | + if (T0 != 0) | ||
598 | + T0 = 1; | ||
599 | + else | ||
600 | + T0 = 0; | ||
601 | + RETURN(); | ||
602 | +} | ||
603 | + | ||
604 | +void OPPROTO op_cmpltz (void) | ||
605 | +{ | ||
606 | + if ((int64_t)T0 < 0) | ||
607 | + T0 = 1; | ||
608 | + else | ||
609 | + T0 = 0; | ||
610 | + RETURN(); | ||
611 | +} | ||
612 | + | ||
613 | +void OPPROTO op_cmplez (void) | ||
614 | +{ | ||
615 | + if ((int64_t)T0 <= 0) | ||
616 | + T0 = 1; | ||
617 | + else | ||
618 | + T0 = 0; | ||
619 | + RETURN(); | ||
620 | +} | ||
621 | + | ||
622 | +void OPPROTO op_cmpgtz (void) | ||
623 | +{ | ||
624 | + if ((int64_t)T0 > 0) | ||
625 | + T0 = 1; | ||
626 | + else | ||
627 | + T0 = 0; | ||
628 | + RETURN(); | ||
629 | +} | ||
630 | + | ||
631 | +void OPPROTO op_cmpgez (void) | ||
632 | +{ | ||
633 | + if ((int64_t)T0 >= 0) | ||
634 | + T0 = 1; | ||
635 | + else | ||
636 | + T0 = 0; | ||
637 | + RETURN(); | ||
638 | +} | ||
639 | + | ||
640 | +void OPPROTO op_cmplbs (void) | ||
641 | +{ | ||
642 | + T0 &= 1; | ||
643 | + RETURN(); | ||
644 | +} | ||
645 | + | ||
646 | +void OPPROTO op_cmplbc (void) | ||
647 | +{ | ||
648 | + T0 = (~T0) & 1; | ||
649 | + RETURN(); | ||
650 | +} | ||
651 | + | ||
652 | +/* Branches */ | ||
653 | +void OPPROTO op_branch (void) | ||
654 | +{ | ||
655 | + env->pc = T0 & ~3; | ||
656 | + RETURN(); | ||
657 | +} | ||
658 | + | ||
659 | +void OPPROTO op_addq1 (void) | ||
660 | +{ | ||
661 | + T1 += T0; | ||
662 | + RETURN(); | ||
663 | +} | ||
664 | + | ||
665 | +#if 0 // Qemu does not know how to do this... | ||
666 | +void OPPROTO op_bcond (void) | ||
667 | +{ | ||
668 | + if (T0) | ||
669 | + env->pc = T1 & ~3; | ||
670 | + else | ||
671 | + env->pc = PARAM(1); | ||
672 | + RETURN(); | ||
673 | +} | ||
674 | +#else | ||
675 | +void OPPROTO op_bcond (void) | ||
676 | +{ | ||
677 | + if (T0) | ||
678 | + env->pc = T1 & ~3; | ||
679 | + else | ||
680 | + env->pc = ((uint64_t)PARAM(1) << 32) | (uint64_t)PARAM(2); | ||
681 | + RETURN(); | ||
682 | +} | ||
683 | +#endif | ||
684 | + | ||
685 | +#if 0 // Qemu does not know how to do this... | ||
686 | +void OPPROTO op_update_pc (void) | ||
687 | +{ | ||
688 | + env->pc = PARAM(1); | ||
689 | + RETURN(); | ||
690 | +} | ||
691 | +#else | ||
692 | +void OPPROTO op_update_pc (void) | ||
693 | +{ | ||
694 | + env->pc = ((uint64_t)PARAM(1) << 32) | (uint64_t)PARAM(2); | ||
695 | + RETURN(); | ||
696 | +} | ||
697 | +#endif | ||
698 | + | ||
699 | +/* Optimization for 32 bits hosts architectures */ | ||
700 | +void OPPROTO op_update_pc32 (void) | ||
701 | +{ | ||
702 | + env->pc = (uint64_t)PARAM(1); | ||
703 | + RETURN(); | ||
704 | +} | ||
705 | + | ||
706 | +/* IEEE floating point arithmetic */ | ||
707 | +/* S floating (single) */ | ||
708 | +void OPPROTO op_adds (void) | ||
709 | +{ | ||
710 | + FT0 = float32_add(FT0, FT1, &FP_STATUS); | ||
711 | + RETURN(); | ||
712 | +} | ||
713 | + | ||
714 | +void OPPROTO op_subs (void) | ||
715 | +{ | ||
716 | + FT0 = float32_sub(FT0, FT1, &FP_STATUS); | ||
717 | + RETURN(); | ||
718 | +} | ||
719 | + | ||
720 | +void OPPROTO op_muls (void) | ||
721 | +{ | ||
722 | + FT0 = float32_mul(FT0, FT1, &FP_STATUS); | ||
723 | + RETURN(); | ||
724 | +} | ||
725 | + | ||
726 | +void OPPROTO op_divs (void) | ||
727 | +{ | ||
728 | + FT0 = float32_div(FT0, FT1, &FP_STATUS); | ||
729 | + RETURN(); | ||
730 | +} | ||
731 | + | ||
732 | +void OPPROTO op_sqrts (void) | ||
733 | +{ | ||
734 | + helper_sqrts(); | ||
735 | + RETURN(); | ||
736 | +} | ||
737 | + | ||
738 | +void OPPROTO op_cpys (void) | ||
739 | +{ | ||
740 | + helper_cpys(); | ||
741 | + RETURN(); | ||
742 | +} | ||
743 | + | ||
744 | +void OPPROTO op_cpysn (void) | ||
745 | +{ | ||
746 | + helper_cpysn(); | ||
747 | + RETURN(); | ||
748 | +} | ||
749 | + | ||
750 | +void OPPROTO op_cpyse (void) | ||
751 | +{ | ||
752 | + helper_cpyse(); | ||
753 | + RETURN(); | ||
754 | +} | ||
755 | + | ||
756 | +void OPPROTO op_itofs (void) | ||
757 | +{ | ||
758 | + helper_itofs(); | ||
759 | + RETURN(); | ||
760 | +} | ||
761 | + | ||
762 | +void OPPROTO op_ftois (void) | ||
763 | +{ | ||
764 | + helper_ftois(); | ||
765 | + RETURN(); | ||
766 | +} | ||
767 | + | ||
768 | +/* T floating (double) */ | ||
769 | +void OPPROTO op_addt (void) | ||
770 | +{ | ||
771 | + FT0 = float64_add(FT0, FT1, &FP_STATUS); | ||
772 | + RETURN(); | ||
773 | +} | ||
774 | + | ||
775 | +void OPPROTO op_subt (void) | ||
776 | +{ | ||
777 | + FT0 = float64_sub(FT0, FT1, &FP_STATUS); | ||
778 | + RETURN(); | ||
779 | +} | ||
780 | + | ||
781 | +void OPPROTO op_mult (void) | ||
782 | +{ | ||
783 | + FT0 = float64_mul(FT0, FT1, &FP_STATUS); | ||
784 | + RETURN(); | ||
785 | +} | ||
786 | + | ||
787 | +void OPPROTO op_divt (void) | ||
788 | +{ | ||
789 | + FT0 = float64_div(FT0, FT1, &FP_STATUS); | ||
790 | + RETURN(); | ||
791 | +} | ||
792 | + | ||
793 | +void OPPROTO op_sqrtt (void) | ||
794 | +{ | ||
795 | + helper_sqrtt(); | ||
796 | + RETURN(); | ||
797 | +} | ||
798 | + | ||
799 | +void OPPROTO op_cmptun (void) | ||
800 | +{ | ||
801 | + helper_cmptun(); | ||
802 | + RETURN(); | ||
803 | +} | ||
804 | + | ||
805 | +void OPPROTO op_cmpteq (void) | ||
806 | +{ | ||
807 | + helper_cmpteq(); | ||
808 | + RETURN(); | ||
809 | +} | ||
810 | + | ||
811 | +void OPPROTO op_cmptle (void) | ||
812 | +{ | ||
813 | + helper_cmptle(); | ||
814 | + RETURN(); | ||
815 | +} | ||
816 | + | ||
817 | +void OPPROTO op_cmptlt (void) | ||
818 | +{ | ||
819 | + helper_cmptlt(); | ||
820 | + RETURN(); | ||
821 | +} | ||
822 | + | ||
823 | +void OPPROTO op_itoft (void) | ||
824 | +{ | ||
825 | + helper_itoft(); | ||
826 | + RETURN(); | ||
827 | +} | ||
828 | + | ||
829 | +void OPPROTO op_ftoit (void) | ||
830 | +{ | ||
831 | + helper_ftoit(); | ||
832 | + RETURN(); | ||
833 | +} | ||
834 | + | ||
835 | +/* VAX floating point arithmetic */ | ||
836 | +/* F floating */ | ||
837 | +void OPPROTO op_addf (void) | ||
838 | +{ | ||
839 | + helper_addf(); | ||
840 | + RETURN(); | ||
841 | +} | ||
842 | + | ||
843 | +void OPPROTO op_subf (void) | ||
844 | +{ | ||
845 | + helper_subf(); | ||
846 | + RETURN(); | ||
847 | +} | ||
848 | + | ||
849 | +void OPPROTO op_mulf (void) | ||
850 | +{ | ||
851 | + helper_mulf(); | ||
852 | + RETURN(); | ||
853 | +} | ||
854 | + | ||
855 | +void OPPROTO op_divf (void) | ||
856 | +{ | ||
857 | + helper_divf(); | ||
858 | + RETURN(); | ||
859 | +} | ||
860 | + | ||
861 | +void OPPROTO op_sqrtf (void) | ||
862 | +{ | ||
863 | + helper_sqrtf(); | ||
864 | + RETURN(); | ||
865 | +} | ||
866 | + | ||
867 | +void OPPROTO op_cmpfeq (void) | ||
868 | +{ | ||
869 | + helper_cmpfeq(); | ||
870 | + RETURN(); | ||
871 | +} | ||
872 | + | ||
873 | +void OPPROTO op_cmpfne (void) | ||
874 | +{ | ||
875 | + helper_cmpfne(); | ||
876 | + RETURN(); | ||
877 | +} | ||
878 | + | ||
879 | +void OPPROTO op_cmpflt (void) | ||
880 | +{ | ||
881 | + helper_cmpflt(); | ||
882 | + RETURN(); | ||
883 | +} | ||
884 | + | ||
885 | +void OPPROTO op_cmpfle (void) | ||
886 | +{ | ||
887 | + helper_cmpfle(); | ||
888 | + RETURN(); | ||
889 | +} | ||
890 | + | ||
891 | +void OPPROTO op_cmpfgt (void) | ||
892 | +{ | ||
893 | + helper_cmpfgt(); | ||
894 | + RETURN(); | ||
895 | +} | ||
896 | + | ||
897 | +void OPPROTO op_cmpfge (void) | ||
898 | +{ | ||
899 | + helper_cmpfge(); | ||
900 | + RETURN(); | ||
901 | +} | ||
902 | + | ||
903 | +void OPPROTO op_itoff (void) | ||
904 | +{ | ||
905 | + helper_itoff(); | ||
906 | + RETURN(); | ||
907 | +} | ||
908 | + | ||
909 | +/* G floating */ | ||
910 | +void OPPROTO op_addg (void) | ||
911 | +{ | ||
912 | + helper_addg(); | ||
913 | + RETURN(); | ||
914 | +} | ||
915 | + | ||
916 | +void OPPROTO op_subg (void) | ||
917 | +{ | ||
918 | + helper_subg(); | ||
919 | + RETURN(); | ||
920 | +} | ||
921 | + | ||
922 | +void OPPROTO op_mulg (void) | ||
923 | +{ | ||
924 | + helper_mulg(); | ||
925 | + RETURN(); | ||
926 | +} | ||
927 | + | ||
928 | +void OPPROTO op_divg (void) | ||
929 | +{ | ||
930 | + helper_divg(); | ||
931 | + RETURN(); | ||
932 | +} | ||
933 | + | ||
934 | +void OPPROTO op_sqrtg (void) | ||
935 | +{ | ||
936 | + helper_sqrtg(); | ||
937 | + RETURN(); | ||
938 | +} | ||
939 | + | ||
940 | +void OPPROTO op_cmpgeq (void) | ||
941 | +{ | ||
942 | + helper_cmpgeq(); | ||
943 | + RETURN(); | ||
944 | +} | ||
945 | + | ||
946 | +void OPPROTO op_cmpglt (void) | ||
947 | +{ | ||
948 | + helper_cmpglt(); | ||
949 | + RETURN(); | ||
950 | +} | ||
951 | + | ||
952 | +void OPPROTO op_cmpgle (void) | ||
953 | +{ | ||
954 | + helper_cmpgle(); | ||
955 | + RETURN(); | ||
956 | +} | ||
957 | + | ||
958 | +/* Floating point format conversion */ | ||
959 | +void OPPROTO op_cvtst (void) | ||
960 | +{ | ||
961 | + FT0 = (float)FT0; | ||
962 | + RETURN(); | ||
963 | +} | ||
964 | + | ||
965 | +void OPPROTO op_cvtqs (void) | ||
966 | +{ | ||
967 | + helper_cvtqs(); | ||
968 | + RETURN(); | ||
969 | +} | ||
970 | + | ||
971 | +void OPPROTO op_cvtts (void) | ||
972 | +{ | ||
973 | + FT0 = (float)FT0; | ||
974 | + RETURN(); | ||
975 | +} | ||
976 | + | ||
977 | +void OPPROTO op_cvttq (void) | ||
978 | +{ | ||
979 | + helper_cvttq(); | ||
980 | + RETURN(); | ||
981 | +} | ||
982 | + | ||
983 | +void OPPROTO op_cvtqt (void) | ||
984 | +{ | ||
985 | + helper_cvtqt(); | ||
986 | + RETURN(); | ||
987 | +} | ||
988 | + | ||
989 | +void OPPROTO op_cvtqf (void) | ||
990 | +{ | ||
991 | + helper_cvtqf(); | ||
992 | + RETURN(); | ||
993 | +} | ||
994 | + | ||
995 | +void OPPROTO op_cvtgf (void) | ||
996 | +{ | ||
997 | + helper_cvtgf(); | ||
998 | + RETURN(); | ||
999 | +} | ||
1000 | + | ||
1001 | +void OPPROTO op_cvtgd (void) | ||
1002 | +{ | ||
1003 | + helper_cvtgd(); | ||
1004 | + RETURN(); | ||
1005 | +} | ||
1006 | + | ||
1007 | +void OPPROTO op_cvtgq (void) | ||
1008 | +{ | ||
1009 | + helper_cvtgq(); | ||
1010 | + RETURN(); | ||
1011 | +} | ||
1012 | + | ||
1013 | +void OPPROTO op_cvtqg (void) | ||
1014 | +{ | ||
1015 | + helper_cvtqg(); | ||
1016 | + RETURN(); | ||
1017 | +} | ||
1018 | + | ||
1019 | +void OPPROTO op_cvtdg (void) | ||
1020 | +{ | ||
1021 | + helper_cvtdg(); | ||
1022 | + RETURN(); | ||
1023 | +} | ||
1024 | + | ||
1025 | +void OPPROTO op_cvtlq (void) | ||
1026 | +{ | ||
1027 | + helper_cvtlq(); | ||
1028 | + RETURN(); | ||
1029 | +} | ||
1030 | + | ||
1031 | +void OPPROTO op_cvtql (void) | ||
1032 | +{ | ||
1033 | + helper_cvtql(); | ||
1034 | + RETURN(); | ||
1035 | +} | ||
1036 | + | ||
1037 | +void OPPROTO op_cvtqlv (void) | ||
1038 | +{ | ||
1039 | + helper_cvtqlv(); | ||
1040 | + RETURN(); | ||
1041 | +} | ||
1042 | + | ||
1043 | +void OPPROTO op_cvtqlsv (void) | ||
1044 | +{ | ||
1045 | + helper_cvtqlsv(); | ||
1046 | + RETURN(); | ||
1047 | +} | ||
1048 | + | ||
1049 | +/* PALcode support special instructions */ | ||
1050 | +#if !defined (CONFIG_USER_ONLY) | ||
1051 | +void OPPROTO op_hw_rei (void) | ||
1052 | +{ | ||
1053 | + env->pc = env->ipr[IPR_EXC_ADDR] & ~3; | ||
1054 | + env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1; | ||
1055 | + /* XXX: re-enable interrupts and memory mapping */ | ||
1056 | + RETURN(); | ||
1057 | +} | ||
1058 | + | ||
1059 | +void OPPROTO op_hw_ret (void) | ||
1060 | +{ | ||
1061 | + env->pc = T0 & ~3; | ||
1062 | + env->ipr[IPR_EXC_ADDR] = T0 & 1; | ||
1063 | + /* XXX: re-enable interrupts and memory mapping */ | ||
1064 | + RETURN(); | ||
1065 | +} | ||
1066 | + | ||
1067 | +void OPPROTO op_mfpr (void) | ||
1068 | +{ | ||
1069 | + helper_mfpr(PARAM(1)); | ||
1070 | + RETURN(); | ||
1071 | +} | ||
1072 | + | ||
1073 | +void OPPROTO op_mtpr (void) | ||
1074 | +{ | ||
1075 | + helper_mtpr(PARAM(1)); | ||
1076 | + RETURN(); | ||
1077 | +} | ||
1078 | + | ||
1079 | +void OPPROTO op_set_alt_mode (void) | ||
1080 | +{ | ||
1081 | + env->saved_mode = env->ps & 0xC; | ||
1082 | + env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC); | ||
1083 | + RETURN(); | ||
1084 | +} | ||
1085 | + | ||
1086 | +void OPPROTO op_restore_mode (void) | ||
1087 | +{ | ||
1088 | + env->ps = (env->ps & ~0xC) | env->saved_mode; | ||
1089 | + RETURN(); | ||
1090 | +} | ||
1091 | + | ||
1092 | +void OPPROTO op_ld_phys_to_virt (void) | ||
1093 | +{ | ||
1094 | + helper_ld_phys_to_virt(); | ||
1095 | + RETURN(); | ||
1096 | +} | ||
1097 | + | ||
1098 | +void OPPROTO op_st_phys_to_virt (void) | ||
1099 | +{ | ||
1100 | + helper_st_phys_to_virt(); | ||
1101 | + RETURN(); | ||
1102 | +} | ||
1103 | +#endif /* !defined (CONFIG_USER_ONLY) */ |
target-alpha/op_helper.c
0 → 100644
1 | +/* | ||
2 | + * Alpha emulation cpu micro-operations helpers for qemu. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Jocelyn Mayer | ||
5 | + * | ||
6 | + * This library is free software; you can redistribute it and/or | ||
7 | + * modify it under the terms of the GNU Lesser General Public | ||
8 | + * License as published by the Free Software Foundation; either | ||
9 | + * version 2 of the License, or (at your option) any later version. | ||
10 | + * | ||
11 | + * This library is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | + * Lesser General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public | ||
17 | + * License along with this library; if not, write to the Free Software | ||
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | + */ | ||
20 | + | ||
21 | +#include "exec.h" | ||
22 | +#include "softfloat.h" | ||
23 | + | ||
24 | +#include "op_helper.h" | ||
25 | + | ||
26 | +#define MEMSUFFIX _raw | ||
27 | +#include "op_helper_mem.h" | ||
28 | + | ||
29 | +#if !defined(CONFIG_USER_ONLY) | ||
30 | +#define MEMSUFFIX _user | ||
31 | +#include "op_helper_mem.h" | ||
32 | + | ||
33 | +#define MEMSUFFIX _kernel | ||
34 | +#include "op_helper_mem.h" | ||
35 | + | ||
36 | +/* Those are used for supervisor and executive modes */ | ||
37 | +#define MEMSUFFIX _data | ||
38 | +#include "op_helper_mem.h" | ||
39 | +#endif | ||
40 | + | ||
41 | +void helper_tb_flush (void) | ||
42 | +{ | ||
43 | + tlb_flush(env, 1); | ||
44 | +} | ||
45 | + | ||
46 | +void cpu_dump_EA (target_ulong EA); | ||
47 | +void helper_print_mem_EA (target_ulong EA) | ||
48 | +{ | ||
49 | + cpu_dump_EA(EA); | ||
50 | +} | ||
51 | + | ||
52 | +/*****************************************************************************/ | ||
53 | +/* Exceptions processing helpers */ | ||
54 | +void helper_excp (uint32_t excp, uint32_t error) | ||
55 | +{ | ||
56 | + env->exception_index = excp; | ||
57 | + env->error_code = error; | ||
58 | + cpu_loop_exit(); | ||
59 | +} | ||
60 | + | ||
61 | +void helper_amask (void) | ||
62 | +{ | ||
63 | + switch (env->implver) { | ||
64 | + case IMPLVER_2106x: | ||
65 | + /* EV4, EV45, LCA, LCA45 & EV5 */ | ||
66 | + break; | ||
67 | + case IMPLVER_21164: | ||
68 | + case IMPLVER_21264: | ||
69 | + case IMPLVER_21364: | ||
70 | + T0 &= ~env->amask; | ||
71 | + break; | ||
72 | + } | ||
73 | +} | ||
74 | + | ||
75 | +void helper_load_pcc (void) | ||
76 | +{ | ||
77 | + /* XXX: TODO */ | ||
78 | + T0 = 0; | ||
79 | +} | ||
80 | + | ||
81 | +void helper_load_implver (void) | ||
82 | +{ | ||
83 | + T0 = env->implver; | ||
84 | +} | ||
85 | + | ||
86 | +void helper_load_fpcr (void) | ||
87 | +{ | ||
88 | + T0 = 0; | ||
89 | +#ifdef CONFIG_SOFTFLOAT | ||
90 | + T0 |= env->fp_status.float_exception_flags << 52; | ||
91 | + if (env->fp_status.float_exception_flags) | ||
92 | + T0 |= 1ULL << 63; | ||
93 | + env->ipr[IPR_EXC_SUM] &= ~0x3E: | ||
94 | + env->ipr[IPR_EXC_SUM] |= env->fp_status.float_exception_flags << 1; | ||
95 | +#endif | ||
96 | + switch (env->fp_status.float_rounding_mode) { | ||
97 | + case float_round_nearest_even: | ||
98 | + T0 |= 2ULL << 58; | ||
99 | + break; | ||
100 | + case float_round_down: | ||
101 | + T0 |= 1ULL << 58; | ||
102 | + break; | ||
103 | + case float_round_up: | ||
104 | + T0 |= 3ULL << 58; | ||
105 | + break; | ||
106 | + case float_round_to_zero: | ||
107 | + break; | ||
108 | + } | ||
109 | +} | ||
110 | + | ||
111 | +void helper_store_fpcr (void) | ||
112 | +{ | ||
113 | +#ifdef CONFIG_SOFTFLOAT | ||
114 | + set_float_exception_flags((T0 >> 52) & 0x3F, &FP_STATUS); | ||
115 | +#endif | ||
116 | + switch ((T0 >> 58) & 3) { | ||
117 | + case 0: | ||
118 | + set_float_rounding_mode(float_round_to_zero, &FP_STATUS); | ||
119 | + break; | ||
120 | + case 1: | ||
121 | + set_float_rounding_mode(float_round_down, &FP_STATUS); | ||
122 | + break; | ||
123 | + case 2: | ||
124 | + set_float_rounding_mode(float_round_nearest_even, &FP_STATUS); | ||
125 | + break; | ||
126 | + case 3: | ||
127 | + set_float_rounding_mode(float_round_up, &FP_STATUS); | ||
128 | + break; | ||
129 | + } | ||
130 | +} | ||
131 | + | ||
132 | +void helper_load_irf (void) | ||
133 | +{ | ||
134 | + /* XXX: TODO */ | ||
135 | + T0 = 0; | ||
136 | +} | ||
137 | + | ||
138 | +void helper_set_irf (void) | ||
139 | +{ | ||
140 | + /* XXX: TODO */ | ||
141 | +} | ||
142 | + | ||
143 | +void helper_clear_irf (void) | ||
144 | +{ | ||
145 | + /* XXX: TODO */ | ||
146 | +} | ||
147 | + | ||
148 | +void helper_addqv (void) | ||
149 | +{ | ||
150 | + T2 = T0; | ||
151 | + T0 += T1; | ||
152 | + if (unlikely((T2 ^ T1 ^ (-1ULL)) & (T2 ^ T0) & (1ULL << 63))) { | ||
153 | + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); | ||
154 | + } | ||
155 | +} | ||
156 | + | ||
157 | +void helper_addlv (void) | ||
158 | +{ | ||
159 | + T2 = T0; | ||
160 | + T0 = (uint32_t)(T0 + T1); | ||
161 | + if (unlikely((T2 ^ T1 ^ (-1UL)) & (T2 ^ T0) & (1UL << 31))) { | ||
162 | + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); | ||
163 | + } | ||
164 | +} | ||
165 | + | ||
166 | +void helper_subqv (void) | ||
167 | +{ | ||
168 | + T2 = T0; | ||
169 | + T0 -= T1; | ||
170 | + if (unlikely(((~T2) ^ T0 ^ (-1ULL)) & ((~T2) ^ T1) & (1ULL << 63))) { | ||
171 | + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); | ||
172 | + } | ||
173 | +} | ||
174 | + | ||
175 | +void helper_sublv (void) | ||
176 | +{ | ||
177 | + T2 = T0; | ||
178 | + T0 = (uint32_t)(T0 - T1); | ||
179 | + if (unlikely(((~T2) ^ T0 ^ (-1UL)) & ((~T2) ^ T1) & (1UL << 31))) { | ||
180 | + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); | ||
181 | + } | ||
182 | +} | ||
183 | + | ||
184 | +void helper_mullv (void) | ||
185 | +{ | ||
186 | + int64_t res = (int64_t)T0 * (int64_t)T1; | ||
187 | + | ||
188 | + if (unlikely((int32_t)res != res)) { | ||
189 | + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); | ||
190 | + } | ||
191 | + T0 = (int64_t)((int32_t)res); | ||
192 | +} | ||
193 | + | ||
194 | +void helper_mulqv () | ||
195 | +{ | ||
196 | + uint64_t res, tmp0, tmp1; | ||
197 | + | ||
198 | + res = (T0 >> 32) * (T1 >> 32); | ||
199 | + tmp0 = ((T0 & 0xFFFFFFFF) * (T1 >> 32)) + | ||
200 | + ((T0 >> 32) * (T1 & 0xFFFFFFFF)); | ||
201 | + tmp1 = (T0 & 0xFFFFFFFF) * (T1 & 0xFFFFFFFF); | ||
202 | + tmp0 += tmp1 >> 32; | ||
203 | + res += tmp0 >> 32; | ||
204 | + T0 *= T1; | ||
205 | + if (unlikely(res != 0)) { | ||
206 | + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); | ||
207 | + } | ||
208 | +} | ||
209 | + | ||
210 | +void helper_umulh (void) | ||
211 | +{ | ||
212 | + uint64_t tmp0, tmp1; | ||
213 | + | ||
214 | + tmp0 = ((T0 & 0xFFFFFFFF) * (T1 >> 32)) + | ||
215 | + ((T0 >> 32) * (T1 & 0xFFFFFFFF)); | ||
216 | + tmp1 = (T0 & 0xFFFFFFFF) * (T1 & 0xFFFFFFFF); | ||
217 | + tmp0 += tmp1 >> 32; | ||
218 | + T0 = (T0 >> 32) * (T0 >> 32); | ||
219 | + T0 += tmp0 >> 32; | ||
220 | +} | ||
221 | + | ||
222 | +void helper_ctpop (void) | ||
223 | +{ | ||
224 | + int n; | ||
225 | + | ||
226 | + for (n = 0; T0 != 0; n++) | ||
227 | + T0 = T0 ^ (T0 - 1); | ||
228 | + T0 = n; | ||
229 | +} | ||
230 | + | ||
231 | +void helper_ctlz (void) | ||
232 | +{ | ||
233 | + uint32_t op32; | ||
234 | + int n; | ||
235 | + | ||
236 | + n = 0; | ||
237 | + if (!(T0 & 0xFFFFFFFF00000000ULL)) { | ||
238 | + n += 32; | ||
239 | + T0 <<= 32; | ||
240 | + } | ||
241 | + /* Make it easier for 32 bits hosts */ | ||
242 | + op32 = T0 >> 32; | ||
243 | + if (!(op32 & 0xFFFF0000UL)) { | ||
244 | + n += 16; | ||
245 | + op32 <<= 16; | ||
246 | + } | ||
247 | + if (!(op32 & 0xFF000000UL)) { | ||
248 | + n += 8; | ||
249 | + op32 <<= 8; | ||
250 | + } | ||
251 | + if (!(op32 & 0xF0000000UL)) { | ||
252 | + n += 4; | ||
253 | + op32 <<= 4; | ||
254 | + } | ||
255 | + if (!(op32 & 0xC0000000UL)) { | ||
256 | + n += 2; | ||
257 | + op32 <<= 2; | ||
258 | + } | ||
259 | + if (!(op32 & 0x80000000UL)) { | ||
260 | + n++; | ||
261 | + op32 <<= 1; | ||
262 | + } | ||
263 | + if (!(op32 & 0x80000000UL)) { | ||
264 | + n++; | ||
265 | + } | ||
266 | + T0 = n; | ||
267 | +} | ||
268 | + | ||
269 | +void helper_cttz (void) | ||
270 | +{ | ||
271 | + uint32_t op32; | ||
272 | + int n; | ||
273 | + | ||
274 | + n = 0; | ||
275 | + if (!(T0 & 0x00000000FFFFFFFFULL)) { | ||
276 | + n += 32; | ||
277 | + T0 >>= 32; | ||
278 | + } | ||
279 | + /* Make it easier for 32 bits hosts */ | ||
280 | + op32 = T0; | ||
281 | + if (!(op32 & 0x0000FFFFUL)) { | ||
282 | + n += 16; | ||
283 | + op32 >>= 16; | ||
284 | + } | ||
285 | + if (!(op32 & 0x000000FFUL)) { | ||
286 | + n += 8; | ||
287 | + op32 >>= 8; | ||
288 | + } | ||
289 | + if (!(op32 & 0x0000000FUL)) { | ||
290 | + n += 4; | ||
291 | + op32 >>= 4; | ||
292 | + } | ||
293 | + if (!(op32 & 0x00000003UL)) { | ||
294 | + n += 2; | ||
295 | + op32 >>= 2; | ||
296 | + } | ||
297 | + if (!(op32 & 0x00000001UL)) { | ||
298 | + n++; | ||
299 | + op32 >>= 1; | ||
300 | + } | ||
301 | + if (!(op32 & 0x00000001UL)) { | ||
302 | + n++; | ||
303 | + } | ||
304 | + T0 = n; | ||
305 | +} | ||
306 | + | ||
307 | +static inline uint64_t byte_zap (uint64_t op, uint8_t mskb) | ||
308 | +{ | ||
309 | + uint64_t mask; | ||
310 | + | ||
311 | + mask = 0; | ||
312 | + mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL; | ||
313 | + mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL; | ||
314 | + mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL; | ||
315 | + mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL; | ||
316 | + mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL; | ||
317 | + mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL; | ||
318 | + mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL; | ||
319 | + mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL; | ||
320 | + | ||
321 | + return op & ~mask; | ||
322 | +} | ||
323 | + | ||
324 | +void helper_mskbl (void) | ||
325 | +{ | ||
326 | + T0 = byte_zap(T0, 0x01 << (T1 & 7)); | ||
327 | +} | ||
328 | + | ||
329 | +void helper_extbl (void) | ||
330 | +{ | ||
331 | + T0 >>= (T1 & 7) * 8; | ||
332 | + T0 = byte_zap(T0, 0xFE); | ||
333 | +} | ||
334 | + | ||
335 | +void helper_insbl (void) | ||
336 | +{ | ||
337 | + T0 <<= (T1 & 7) * 8; | ||
338 | + T0 = byte_zap(T0, ~(0x01 << (T1 & 7))); | ||
339 | +} | ||
340 | + | ||
341 | +void helper_mskwl (void) | ||
342 | +{ | ||
343 | + T0 = byte_zap(T0, 0x03 << (T1 & 7)); | ||
344 | +} | ||
345 | + | ||
346 | +void helper_extwl (void) | ||
347 | +{ | ||
348 | + T0 >>= (T1 & 7) * 8; | ||
349 | + T0 = byte_zap(T0, 0xFC); | ||
350 | +} | ||
351 | + | ||
352 | +void helper_inswl (void) | ||
353 | +{ | ||
354 | + T0 <<= (T1 & 7) * 8; | ||
355 | + T0 = byte_zap(T0, ~(0x03 << (T1 & 7))); | ||
356 | +} | ||
357 | + | ||
358 | +void helper_mskll (void) | ||
359 | +{ | ||
360 | + T0 = byte_zap(T0, 0x0F << (T1 & 7)); | ||
361 | +} | ||
362 | + | ||
363 | +void helper_extll (void) | ||
364 | +{ | ||
365 | + T0 >>= (T1 & 7) * 8; | ||
366 | + T0 = byte_zap(T0, 0xF0); | ||
367 | +} | ||
368 | + | ||
369 | +void helper_insll (void) | ||
370 | +{ | ||
371 | + T0 <<= (T1 & 7) * 8; | ||
372 | + T0 = byte_zap(T0, ~(0x0F << (T1 & 7))); | ||
373 | +} | ||
374 | + | ||
375 | +void helper_zap (void) | ||
376 | +{ | ||
377 | + T0 = byte_zap(T0, T1); | ||
378 | +} | ||
379 | + | ||
380 | +void helper_zapnot (void) | ||
381 | +{ | ||
382 | + T0 = byte_zap(T0, ~T1); | ||
383 | +} | ||
384 | + | ||
385 | +void helper_mskql (void) | ||
386 | +{ | ||
387 | + T0 = byte_zap(T0, 0xFF << (T1 & 7)); | ||
388 | +} | ||
389 | + | ||
390 | +void helper_extql (void) | ||
391 | +{ | ||
392 | + T0 >>= (T1 & 7) * 8; | ||
393 | + T0 = byte_zap(T0, 0x00); | ||
394 | +} | ||
395 | + | ||
396 | +void helper_insql (void) | ||
397 | +{ | ||
398 | + T0 <<= (T1 & 7) * 8; | ||
399 | + T0 = byte_zap(T0, ~(0xFF << (T1 & 7))); | ||
400 | +} | ||
401 | + | ||
402 | +void helper_mskwh (void) | ||
403 | +{ | ||
404 | + T0 = byte_zap(T0, (0x03 << (T1 & 7)) >> 8); | ||
405 | +} | ||
406 | + | ||
407 | +void helper_inswh (void) | ||
408 | +{ | ||
409 | + T0 >>= 64 - ((T1 & 7) * 8); | ||
410 | + T0 = byte_zap(T0, ~((0x03 << (T1 & 7)) >> 8)); | ||
411 | +} | ||
412 | + | ||
413 | +void helper_extwh (void) | ||
414 | +{ | ||
415 | + T0 <<= 64 - ((T1 & 7) * 8); | ||
416 | + T0 = byte_zap(T0, ~0x07); | ||
417 | +} | ||
418 | + | ||
419 | +void helper_msklh (void) | ||
420 | +{ | ||
421 | + T0 = byte_zap(T0, (0x0F << (T1 & 7)) >> 8); | ||
422 | +} | ||
423 | + | ||
424 | +void helper_inslh (void) | ||
425 | +{ | ||
426 | + T0 >>= 64 - ((T1 & 7) * 8); | ||
427 | + T0 = byte_zap(T0, ~((0x0F << (T1 & 7)) >> 8)); | ||
428 | +} | ||
429 | + | ||
430 | +void helper_extlh (void) | ||
431 | +{ | ||
432 | + T0 <<= 64 - ((T1 & 7) * 8); | ||
433 | + T0 = byte_zap(T0, ~0x0F); | ||
434 | +} | ||
435 | + | ||
436 | +void helper_mskqh (void) | ||
437 | +{ | ||
438 | + T0 = byte_zap(T0, (0xFF << (T1 & 7)) >> 8); | ||
439 | +} | ||
440 | + | ||
441 | +void helper_insqh (void) | ||
442 | +{ | ||
443 | + T0 >>= 64 - ((T1 & 7) * 8); | ||
444 | + T0 = byte_zap(T0, ~((0xFF << (T1 & 7)) >> 8)); | ||
445 | +} | ||
446 | + | ||
447 | +void helper_extqh (void) | ||
448 | +{ | ||
449 | + T0 <<= 64 - ((T1 & 7) * 8); | ||
450 | + T0 = byte_zap(T0, 0x00); | ||
451 | +} | ||
452 | + | ||
453 | +void helper_cmpbge (void) | ||
454 | +{ | ||
455 | + uint8_t opa, opb, res; | ||
456 | + int i; | ||
457 | + | ||
458 | + res = 0; | ||
459 | + for (i = 0; i < 7; i++) { | ||
460 | + opa = T0 >> (i * 8); | ||
461 | + opb = T1 >> (i * 8); | ||
462 | + if (opa >= opb) | ||
463 | + res |= 1 << i; | ||
464 | + } | ||
465 | + T0 = res; | ||
466 | +} | ||
467 | + | ||
468 | +void helper_cmov_fir (int freg) | ||
469 | +{ | ||
470 | + if (FT0 != 0) | ||
471 | + env->fir[freg] = FT1; | ||
472 | +} | ||
473 | + | ||
474 | +void helper_sqrts (void) | ||
475 | +{ | ||
476 | + FT0 = float32_sqrt(FT0, &FP_STATUS); | ||
477 | +} | ||
478 | + | ||
479 | +void helper_cpys (void) | ||
480 | +{ | ||
481 | + union { | ||
482 | + double d; | ||
483 | + uint64_t i; | ||
484 | + } p, q, r; | ||
485 | + | ||
486 | + p.d = FT0; | ||
487 | + q.d = FT1; | ||
488 | + r.i = p.i & 0x8000000000000000ULL; | ||
489 | + r.i |= q.i & ~0x8000000000000000ULL; | ||
490 | + FT0 = r.d; | ||
491 | +} | ||
492 | + | ||
493 | +void helper_cpysn (void) | ||
494 | +{ | ||
495 | + union { | ||
496 | + double d; | ||
497 | + uint64_t i; | ||
498 | + } p, q, r; | ||
499 | + | ||
500 | + p.d = FT0; | ||
501 | + q.d = FT1; | ||
502 | + r.i = (~p.i) & 0x8000000000000000ULL; | ||
503 | + r.i |= q.i & ~0x8000000000000000ULL; | ||
504 | + FT0 = r.d; | ||
505 | +} | ||
506 | + | ||
507 | +void helper_cpyse (void) | ||
508 | +{ | ||
509 | + union { | ||
510 | + double d; | ||
511 | + uint64_t i; | ||
512 | + } p, q, r; | ||
513 | + | ||
514 | + p.d = FT0; | ||
515 | + q.d = FT1; | ||
516 | + r.i = p.i & 0xFFF0000000000000ULL; | ||
517 | + r.i |= q.i & ~0xFFF0000000000000ULL; | ||
518 | + FT0 = r.d; | ||
519 | +} | ||
520 | + | ||
521 | +void helper_itofs (void) | ||
522 | +{ | ||
523 | + union { | ||
524 | + double d; | ||
525 | + uint64_t i; | ||
526 | + } p; | ||
527 | + | ||
528 | + p.d = FT0; | ||
529 | + FT0 = int64_to_float32(p.i, &FP_STATUS); | ||
530 | +} | ||
531 | + | ||
532 | +void helper_ftois (void) | ||
533 | +{ | ||
534 | + union { | ||
535 | + double d; | ||
536 | + uint64_t i; | ||
537 | + } p; | ||
538 | + | ||
539 | + p.i = float32_to_int64(FT0, &FP_STATUS); | ||
540 | + FT0 = p.d; | ||
541 | +} | ||
542 | + | ||
543 | +void helper_sqrtt (void) | ||
544 | +{ | ||
545 | + FT0 = float64_sqrt(FT0, &FP_STATUS); | ||
546 | +} | ||
547 | + | ||
548 | +void helper_cmptun (void) | ||
549 | +{ | ||
550 | + union { | ||
551 | + double d; | ||
552 | + uint64_t i; | ||
553 | + } p; | ||
554 | + | ||
555 | + p.i = 0; | ||
556 | + if (float64_is_nan(FT0) || float64_is_nan(FT1)) | ||
557 | + p.i = 0x4000000000000000ULL; | ||
558 | + FT0 = p.d; | ||
559 | +} | ||
560 | + | ||
561 | +void helper_cmpteq (void) | ||
562 | +{ | ||
563 | + union { | ||
564 | + double d; | ||
565 | + uint64_t i; | ||
566 | + } p; | ||
567 | + | ||
568 | + p.i = 0; | ||
569 | + if (float64_eq(FT0, FT1, &FP_STATUS)) | ||
570 | + p.i = 0x4000000000000000ULL; | ||
571 | + FT0 = p.d; | ||
572 | +} | ||
573 | + | ||
574 | +void helper_cmptle (void) | ||
575 | +{ | ||
576 | + union { | ||
577 | + double d; | ||
578 | + uint64_t i; | ||
579 | + } p; | ||
580 | + | ||
581 | + p.i = 0; | ||
582 | + if (float64_le(FT0, FT1, &FP_STATUS)) | ||
583 | + p.i = 0x4000000000000000ULL; | ||
584 | + FT0 = p.d; | ||
585 | +} | ||
586 | + | ||
587 | +void helper_cmptlt (void) | ||
588 | +{ | ||
589 | + union { | ||
590 | + double d; | ||
591 | + uint64_t i; | ||
592 | + } p; | ||
593 | + | ||
594 | + p.i = 0; | ||
595 | + if (float64_lt(FT0, FT1, &FP_STATUS)) | ||
596 | + p.i = 0x4000000000000000ULL; | ||
597 | + FT0 = p.d; | ||
598 | +} | ||
599 | + | ||
600 | +void helper_itoft (void) | ||
601 | +{ | ||
602 | + union { | ||
603 | + double d; | ||
604 | + uint64_t i; | ||
605 | + } p; | ||
606 | + | ||
607 | + p.d = FT0; | ||
608 | + FT0 = int64_to_float64(p.i, &FP_STATUS); | ||
609 | +} | ||
610 | + | ||
611 | +void helper_ftoit (void) | ||
612 | +{ | ||
613 | + union { | ||
614 | + double d; | ||
615 | + uint64_t i; | ||
616 | + } p; | ||
617 | + | ||
618 | + p.i = float64_to_int64(FT0, &FP_STATUS); | ||
619 | + FT0 = p.d; | ||
620 | +} | ||
621 | + | ||
622 | +static int vaxf_is_valid (float ff) | ||
623 | +{ | ||
624 | + union { | ||
625 | + float f; | ||
626 | + uint32_t i; | ||
627 | + } p; | ||
628 | + uint32_t exp, mant; | ||
629 | + | ||
630 | + p.f = ff; | ||
631 | + exp = (p.i >> 23) & 0xFF; | ||
632 | + mant = p.i & 0x007FFFFF; | ||
633 | + if (exp == 0 && ((p.i & 0x80000000) || mant != 0)) { | ||
634 | + /* Reserved operands / Dirty zero */ | ||
635 | + return 0; | ||
636 | + } | ||
637 | + | ||
638 | + return 1; | ||
639 | +} | ||
640 | + | ||
641 | +static float vaxf_to_ieee32 (float ff) | ||
642 | +{ | ||
643 | + union { | ||
644 | + float f; | ||
645 | + uint32_t i; | ||
646 | + } p; | ||
647 | + uint32_t exp; | ||
648 | + | ||
649 | + p.f = ff; | ||
650 | + exp = (p.i >> 23) & 0xFF; | ||
651 | + if (exp < 3) { | ||
652 | + /* Underflow */ | ||
653 | + p.f = 0.0; | ||
654 | + } else { | ||
655 | + p.f *= 0.25; | ||
656 | + } | ||
657 | + | ||
658 | + return p.f; | ||
659 | +} | ||
660 | + | ||
661 | +static float ieee32_to_vaxf (float fi) | ||
662 | +{ | ||
663 | + union { | ||
664 | + float f; | ||
665 | + uint32_t i; | ||
666 | + } p; | ||
667 | + uint32_t exp, mant; | ||
668 | + | ||
669 | + p.f = fi; | ||
670 | + exp = (p.i >> 23) & 0xFF; | ||
671 | + mant = p.i & 0x007FFFFF; | ||
672 | + if (exp == 255) { | ||
673 | + /* NaN or infinity */ | ||
674 | + p.i = 1; | ||
675 | + } else if (exp == 0) { | ||
676 | + if (mant == 0) { | ||
677 | + /* Zero */ | ||
678 | + p.i = 0; | ||
679 | + } else { | ||
680 | + /* Denormalized */ | ||
681 | + p.f *= 2.0; | ||
682 | + } | ||
683 | + } else { | ||
684 | + if (exp >= 253) { | ||
685 | + /* Overflow */ | ||
686 | + p.i = 1; | ||
687 | + } else { | ||
688 | + p.f *= 4.0; | ||
689 | + } | ||
690 | + } | ||
691 | + | ||
692 | + return p.f; | ||
693 | +} | ||
694 | + | ||
695 | +void helper_addf (void) | ||
696 | +{ | ||
697 | + float ft0, ft1, ft2; | ||
698 | + | ||
699 | + if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) { | ||
700 | + /* XXX: TODO */ | ||
701 | + } | ||
702 | + ft0 = vaxf_to_ieee32(FT0); | ||
703 | + ft1 = vaxf_to_ieee32(FT1); | ||
704 | + ft2 = float32_add(ft0, ft1, &FP_STATUS); | ||
705 | + FT0 = ieee32_to_vaxf(ft2); | ||
706 | +} | ||
707 | + | ||
708 | +void helper_subf (void) | ||
709 | +{ | ||
710 | + float ft0, ft1, ft2; | ||
711 | + | ||
712 | + if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) { | ||
713 | + /* XXX: TODO */ | ||
714 | + } | ||
715 | + ft0 = vaxf_to_ieee32(FT0); | ||
716 | + ft1 = vaxf_to_ieee32(FT1); | ||
717 | + ft2 = float32_sub(ft0, ft1, &FP_STATUS); | ||
718 | + FT0 = ieee32_to_vaxf(ft2); | ||
719 | +} | ||
720 | + | ||
721 | +void helper_mulf (void) | ||
722 | +{ | ||
723 | + float ft0, ft1, ft2; | ||
724 | + | ||
725 | + if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) { | ||
726 | + /* XXX: TODO */ | ||
727 | + } | ||
728 | + ft0 = vaxf_to_ieee32(FT0); | ||
729 | + ft1 = vaxf_to_ieee32(FT1); | ||
730 | + ft2 = float32_mul(ft0, ft1, &FP_STATUS); | ||
731 | + FT0 = ieee32_to_vaxf(ft2); | ||
732 | +} | ||
733 | + | ||
734 | +void helper_divf (void) | ||
735 | +{ | ||
736 | + float ft0, ft1, ft2; | ||
737 | + | ||
738 | + if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) { | ||
739 | + /* XXX: TODO */ | ||
740 | + } | ||
741 | + ft0 = vaxf_to_ieee32(FT0); | ||
742 | + ft1 = vaxf_to_ieee32(FT1); | ||
743 | + ft2 = float32_div(ft0, ft1, &FP_STATUS); | ||
744 | + FT0 = ieee32_to_vaxf(ft2); | ||
745 | +} | ||
746 | + | ||
747 | +void helper_sqrtf (void) | ||
748 | +{ | ||
749 | + float ft0, ft1; | ||
750 | + | ||
751 | + if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) { | ||
752 | + /* XXX: TODO */ | ||
753 | + } | ||
754 | + ft0 = vaxf_to_ieee32(FT0); | ||
755 | + ft1 = float32_sqrt(ft0, &FP_STATUS); | ||
756 | + FT0 = ieee32_to_vaxf(ft1); | ||
757 | +} | ||
758 | + | ||
759 | +void helper_itoff (void) | ||
760 | +{ | ||
761 | + /* XXX: TODO */ | ||
762 | +} | ||
763 | + | ||
764 | +static int vaxg_is_valid (double ff) | ||
765 | +{ | ||
766 | + union { | ||
767 | + double f; | ||
768 | + uint64_t i; | ||
769 | + } p; | ||
770 | + uint64_t exp, mant; | ||
771 | + | ||
772 | + p.f = ff; | ||
773 | + exp = (p.i >> 52) & 0x7FF; | ||
774 | + mant = p.i & 0x000FFFFFFFFFFFFFULL; | ||
775 | + if (exp == 0 && ((p.i & 0x8000000000000000ULL) || mant != 0)) { | ||
776 | + /* Reserved operands / Dirty zero */ | ||
777 | + return 0; | ||
778 | + } | ||
779 | + | ||
780 | + return 1; | ||
781 | +} | ||
782 | + | ||
783 | +static double vaxg_to_ieee64 (double fg) | ||
784 | +{ | ||
785 | + union { | ||
786 | + double f; | ||
787 | + uint64_t i; | ||
788 | + } p; | ||
789 | + uint32_t exp; | ||
790 | + | ||
791 | + p.f = fg; | ||
792 | + exp = (p.i >> 52) & 0x7FF; | ||
793 | + if (exp < 3) { | ||
794 | + /* Underflow */ | ||
795 | + p.f = 0.0; | ||
796 | + } else { | ||
797 | + p.f *= 0.25; | ||
798 | + } | ||
799 | + | ||
800 | + return p.f; | ||
801 | +} | ||
802 | + | ||
803 | +static double ieee64_to_vaxg (double fi) | ||
804 | +{ | ||
805 | + union { | ||
806 | + double f; | ||
807 | + uint64_t i; | ||
808 | + } p; | ||
809 | + uint64_t mant; | ||
810 | + uint32_t exp; | ||
811 | + | ||
812 | + p.f = fi; | ||
813 | + exp = (p.i >> 52) & 0x7FF; | ||
814 | + mant = p.i & 0x000FFFFFFFFFFFFFULL; | ||
815 | + if (exp == 255) { | ||
816 | + /* NaN or infinity */ | ||
817 | + p.i = 1; /* VAX dirty zero */ | ||
818 | + } else if (exp == 0) { | ||
819 | + if (mant == 0) { | ||
820 | + /* Zero */ | ||
821 | + p.i = 0; | ||
822 | + } else { | ||
823 | + /* Denormalized */ | ||
824 | + p.f *= 2.0; | ||
825 | + } | ||
826 | + } else { | ||
827 | + if (exp >= 2045) { | ||
828 | + /* Overflow */ | ||
829 | + p.i = 1; /* VAX dirty zero */ | ||
830 | + } else { | ||
831 | + p.f *= 4.0; | ||
832 | + } | ||
833 | + } | ||
834 | + | ||
835 | + return p.f; | ||
836 | +} | ||
837 | + | ||
838 | +void helper_addg (void) | ||
839 | +{ | ||
840 | + double ft0, ft1, ft2; | ||
841 | + | ||
842 | + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { | ||
843 | + /* XXX: TODO */ | ||
844 | + } | ||
845 | + ft0 = vaxg_to_ieee64(FT0); | ||
846 | + ft1 = vaxg_to_ieee64(FT1); | ||
847 | + ft2 = float64_add(ft0, ft1, &FP_STATUS); | ||
848 | + FT0 = ieee64_to_vaxg(ft2); | ||
849 | +} | ||
850 | + | ||
851 | +void helper_subg (void) | ||
852 | +{ | ||
853 | + double ft0, ft1, ft2; | ||
854 | + | ||
855 | + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { | ||
856 | + /* XXX: TODO */ | ||
857 | + } | ||
858 | + ft0 = vaxg_to_ieee64(FT0); | ||
859 | + ft1 = vaxg_to_ieee64(FT1); | ||
860 | + ft2 = float64_sub(ft0, ft1, &FP_STATUS); | ||
861 | + FT0 = ieee64_to_vaxg(ft2); | ||
862 | +} | ||
863 | + | ||
864 | +void helper_mulg (void) | ||
865 | +{ | ||
866 | + double ft0, ft1, ft2; | ||
867 | + | ||
868 | + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { | ||
869 | + /* XXX: TODO */ | ||
870 | + } | ||
871 | + ft0 = vaxg_to_ieee64(FT0); | ||
872 | + ft1 = vaxg_to_ieee64(FT1); | ||
873 | + ft2 = float64_mul(ft0, ft1, &FP_STATUS); | ||
874 | + FT0 = ieee64_to_vaxg(ft2); | ||
875 | +} | ||
876 | + | ||
877 | +void helper_divg (void) | ||
878 | +{ | ||
879 | + double ft0, ft1, ft2; | ||
880 | + | ||
881 | + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { | ||
882 | + /* XXX: TODO */ | ||
883 | + } | ||
884 | + ft0 = vaxg_to_ieee64(FT0); | ||
885 | + ft1 = vaxg_to_ieee64(FT1); | ||
886 | + ft2 = float64_div(ft0, ft1, &FP_STATUS); | ||
887 | + FT0 = ieee64_to_vaxg(ft2); | ||
888 | +} | ||
889 | + | ||
890 | +void helper_sqrtg (void) | ||
891 | +{ | ||
892 | + double ft0, ft1; | ||
893 | + | ||
894 | + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { | ||
895 | + /* XXX: TODO */ | ||
896 | + } | ||
897 | + ft0 = vaxg_to_ieee64(FT0); | ||
898 | + ft1 = float64_sqrt(ft0, &FP_STATUS); | ||
899 | + FT0 = ieee64_to_vaxg(ft1); | ||
900 | +} | ||
901 | + | ||
902 | +void helper_cmpgeq (void) | ||
903 | +{ | ||
904 | + union { | ||
905 | + double d; | ||
906 | + uint64_t u; | ||
907 | + } p; | ||
908 | + double ft0, ft1; | ||
909 | + | ||
910 | + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { | ||
911 | + /* XXX: TODO */ | ||
912 | + } | ||
913 | + ft0 = vaxg_to_ieee64(FT0); | ||
914 | + ft1 = vaxg_to_ieee64(FT1); | ||
915 | + p.u = 0; | ||
916 | + if (float64_eq(ft0, ft1, &FP_STATUS)) | ||
917 | + p.u = 0x4000000000000000ULL; | ||
918 | + FT0 = p.d; | ||
919 | +} | ||
920 | + | ||
921 | +void helper_cmpglt (void) | ||
922 | +{ | ||
923 | + union { | ||
924 | + double d; | ||
925 | + uint64_t u; | ||
926 | + } p; | ||
927 | + double ft0, ft1; | ||
928 | + | ||
929 | + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { | ||
930 | + /* XXX: TODO */ | ||
931 | + } | ||
932 | + ft0 = vaxg_to_ieee64(FT0); | ||
933 | + ft1 = vaxg_to_ieee64(FT1); | ||
934 | + p.u = 0; | ||
935 | + if (float64_lt(ft0, ft1, &FP_STATUS)) | ||
936 | + p.u = 0x4000000000000000ULL; | ||
937 | + FT0 = p.d; | ||
938 | +} | ||
939 | + | ||
940 | +void helper_cmpgle (void) | ||
941 | +{ | ||
942 | + union { | ||
943 | + double d; | ||
944 | + uint64_t u; | ||
945 | + } p; | ||
946 | + double ft0, ft1; | ||
947 | + | ||
948 | + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) { | ||
949 | + /* XXX: TODO */ | ||
950 | + } | ||
951 | + ft0 = vaxg_to_ieee64(FT0); | ||
952 | + ft1 = vaxg_to_ieee64(FT1); | ||
953 | + p.u = 0; | ||
954 | + if (float64_le(ft0, ft1, &FP_STATUS)) | ||
955 | + p.u = 0x4000000000000000ULL; | ||
956 | + FT0 = p.d; | ||
957 | +} | ||
958 | + | ||
959 | +void helper_cvtqs (void) | ||
960 | +{ | ||
961 | + union { | ||
962 | + double d; | ||
963 | + uint64_t u; | ||
964 | + } p; | ||
965 | + | ||
966 | + p.d = FT0; | ||
967 | + FT0 = (float)p.u; | ||
968 | +} | ||
969 | + | ||
970 | +void helper_cvttq (void) | ||
971 | +{ | ||
972 | + union { | ||
973 | + double d; | ||
974 | + uint64_t u; | ||
975 | + } p; | ||
976 | + | ||
977 | + p.u = FT0; | ||
978 | + FT0 = p.d; | ||
979 | +} | ||
980 | + | ||
981 | +void helper_cvtqt (void) | ||
982 | +{ | ||
983 | + union { | ||
984 | + double d; | ||
985 | + uint64_t u; | ||
986 | + } p; | ||
987 | + | ||
988 | + p.d = FT0; | ||
989 | + FT0 = p.u; | ||
990 | +} | ||
991 | + | ||
992 | +void helper_cvtqf (void) | ||
993 | +{ | ||
994 | + union { | ||
995 | + double d; | ||
996 | + uint64_t u; | ||
997 | + } p; | ||
998 | + | ||
999 | + p.d = FT0; | ||
1000 | + FT0 = ieee32_to_vaxf(p.u); | ||
1001 | +} | ||
1002 | + | ||
1003 | +void helper_cvtgf (void) | ||
1004 | +{ | ||
1005 | + double ft0; | ||
1006 | + | ||
1007 | + ft0 = vaxg_to_ieee64(FT0); | ||
1008 | + FT0 = ieee32_to_vaxf(ft0); | ||
1009 | +} | ||
1010 | + | ||
1011 | +void helper_cvtgd (void) | ||
1012 | +{ | ||
1013 | + /* XXX: TODO */ | ||
1014 | +} | ||
1015 | + | ||
1016 | +void helper_cvtgq (void) | ||
1017 | +{ | ||
1018 | + union { | ||
1019 | + double d; | ||
1020 | + uint64_t u; | ||
1021 | + } p; | ||
1022 | + | ||
1023 | + p.u = vaxg_to_ieee64(FT0); | ||
1024 | + FT0 = p.d; | ||
1025 | +} | ||
1026 | + | ||
1027 | +void helper_cvtqg (void) | ||
1028 | +{ | ||
1029 | + union { | ||
1030 | + double d; | ||
1031 | + uint64_t u; | ||
1032 | + } p; | ||
1033 | + | ||
1034 | + p.d = FT0; | ||
1035 | + FT0 = ieee64_to_vaxg(p.u); | ||
1036 | +} | ||
1037 | + | ||
1038 | +void helper_cvtdg (void) | ||
1039 | +{ | ||
1040 | + /* XXX: TODO */ | ||
1041 | +} | ||
1042 | + | ||
1043 | +void helper_cvtlq (void) | ||
1044 | +{ | ||
1045 | + union { | ||
1046 | + double d; | ||
1047 | + uint64_t u; | ||
1048 | + } p, q; | ||
1049 | + | ||
1050 | + p.d = FT0; | ||
1051 | + q.u = (p.u >> 29) & 0x3FFFFFFF; | ||
1052 | + q.u |= (p.u >> 32); | ||
1053 | + q.u = (int64_t)((int32_t)q.u); | ||
1054 | + FT0 = q.d; | ||
1055 | +} | ||
1056 | + | ||
1057 | +static inline void __helper_cvtql (int s, int v) | ||
1058 | +{ | ||
1059 | + union { | ||
1060 | + double d; | ||
1061 | + uint64_t u; | ||
1062 | + } p, q; | ||
1063 | + | ||
1064 | + p.d = FT0; | ||
1065 | + q.u = ((uint64_t)(p.u & 0xC0000000)) << 32; | ||
1066 | + q.u |= ((uint64_t)(p.u & 0x7FFFFFFF)) << 29; | ||
1067 | + FT0 = q.d; | ||
1068 | + if (v && (int64_t)((int32_t)p.u) != (int64_t)p.u) { | ||
1069 | + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); | ||
1070 | + } | ||
1071 | + if (s) { | ||
1072 | + /* TODO */ | ||
1073 | + } | ||
1074 | +} | ||
1075 | + | ||
1076 | +void helper_cvtql (void) | ||
1077 | +{ | ||
1078 | + __helper_cvtql(0, 0); | ||
1079 | +} | ||
1080 | + | ||
1081 | +void helper_cvtqlv (void) | ||
1082 | +{ | ||
1083 | + __helper_cvtql(0, 1); | ||
1084 | +} | ||
1085 | + | ||
1086 | +void helper_cvtqlsv (void) | ||
1087 | +{ | ||
1088 | + __helper_cvtql(1, 1); | ||
1089 | +} | ||
1090 | + | ||
1091 | +void helper_cmpfeq (void) | ||
1092 | +{ | ||
1093 | + if (float64_eq(FT0, FT1, &FP_STATUS)) | ||
1094 | + T0 = 1; | ||
1095 | + else | ||
1096 | + T0 = 0; | ||
1097 | +} | ||
1098 | + | ||
1099 | +void helper_cmpfne (void) | ||
1100 | +{ | ||
1101 | + if (float64_eq(FT0, FT1, &FP_STATUS)) | ||
1102 | + T0 = 0; | ||
1103 | + else | ||
1104 | + T0 = 1; | ||
1105 | +} | ||
1106 | + | ||
1107 | +void helper_cmpflt (void) | ||
1108 | +{ | ||
1109 | + if (float64_lt(FT0, FT1, &FP_STATUS)) | ||
1110 | + T0 = 1; | ||
1111 | + else | ||
1112 | + T0 = 0; | ||
1113 | +} | ||
1114 | + | ||
1115 | +void helper_cmpfle (void) | ||
1116 | +{ | ||
1117 | + if (float64_lt(FT0, FT1, &FP_STATUS)) | ||
1118 | + T0 = 1; | ||
1119 | + else | ||
1120 | + T0 = 0; | ||
1121 | +} | ||
1122 | + | ||
1123 | +void helper_cmpfgt (void) | ||
1124 | +{ | ||
1125 | + if (float64_le(FT0, FT1, &FP_STATUS)) | ||
1126 | + T0 = 0; | ||
1127 | + else | ||
1128 | + T0 = 1; | ||
1129 | +} | ||
1130 | + | ||
1131 | +void helper_cmpfge (void) | ||
1132 | +{ | ||
1133 | + if (float64_lt(FT0, FT1, &FP_STATUS)) | ||
1134 | + T0 = 0; | ||
1135 | + else | ||
1136 | + T0 = 1; | ||
1137 | +} | ||
1138 | + | ||
1139 | +#if !defined (CONFIG_USER_ONLY) | ||
1140 | +void helper_mfpr (int iprn) | ||
1141 | +{ | ||
1142 | + uint64_t val; | ||
1143 | + | ||
1144 | + if (cpu_alpha_mfpr(env, iprn, &val) == 0) | ||
1145 | + T0 = val; | ||
1146 | +} | ||
1147 | + | ||
1148 | +void helper_mtpr (int iprn) | ||
1149 | +{ | ||
1150 | + cpu_alpha_mtpr(env, iprn, T0, NULL); | ||
1151 | +} | ||
1152 | +#endif | ||
1153 | + | ||
1154 | +/*****************************************************************************/ | ||
1155 | +/* Softmmu support */ | ||
1156 | +#if !defined (CONFIG_USER_ONLY) | ||
1157 | + | ||
1158 | +#define GETPC() (__builtin_return_address(0)) | ||
1159 | + | ||
1160 | +/* XXX: the two following helpers are pure hacks. | ||
1161 | + * Hopefully, we emulate the PALcode, then we should never see | ||
1162 | + * HW_LD / HW_ST instructions. | ||
1163 | + */ | ||
1164 | +void helper_ld_phys_to_virt (void) | ||
1165 | +{ | ||
1166 | + uint64_t tlb_addr, physaddr; | ||
1167 | + int index, is_user; | ||
1168 | + void *retaddr; | ||
1169 | + | ||
1170 | + is_user = (env->ps >> 3) & 3; | ||
1171 | + index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); | ||
1172 | + redo: | ||
1173 | + tlb_addr = env->tlb_table[is_user][index].addr_read; | ||
1174 | + if ((T0 & TARGET_PAGE_MASK) == | ||
1175 | + (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { | ||
1176 | + physaddr = T0 + env->tlb_table[is_user][index].addend; | ||
1177 | + } else { | ||
1178 | + /* the page is not in the TLB : fill it */ | ||
1179 | + retaddr = GETPC(); | ||
1180 | + tlb_fill(T0, 0, is_user, retaddr); | ||
1181 | + goto redo; | ||
1182 | + } | ||
1183 | + T0 = physaddr; | ||
1184 | +} | ||
1185 | + | ||
1186 | +void helper_st_phys_to_virt (void) | ||
1187 | +{ | ||
1188 | + uint64_t tlb_addr, physaddr; | ||
1189 | + int index, is_user; | ||
1190 | + void *retaddr; | ||
1191 | + | ||
1192 | + is_user = (env->ps >> 3) & 3; | ||
1193 | + index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); | ||
1194 | + redo: | ||
1195 | + tlb_addr = env->tlb_table[is_user][index].addr_write; | ||
1196 | + if ((T0 & TARGET_PAGE_MASK) == | ||
1197 | + (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { | ||
1198 | + physaddr = T0 + env->tlb_table[is_user][index].addend; | ||
1199 | + } else { | ||
1200 | + /* the page is not in the TLB : fill it */ | ||
1201 | + retaddr = GETPC(); | ||
1202 | + tlb_fill(T0, 1, is_user, retaddr); | ||
1203 | + goto redo; | ||
1204 | + } | ||
1205 | + T0 = physaddr; | ||
1206 | +} | ||
1207 | + | ||
1208 | +#define MMUSUFFIX _mmu | ||
1209 | + | ||
1210 | +#define SHIFT 0 | ||
1211 | +#include "softmmu_template.h" | ||
1212 | + | ||
1213 | +#define SHIFT 1 | ||
1214 | +#include "softmmu_template.h" | ||
1215 | + | ||
1216 | +#define SHIFT 2 | ||
1217 | +#include "softmmu_template.h" | ||
1218 | + | ||
1219 | +#define SHIFT 3 | ||
1220 | +#include "softmmu_template.h" | ||
1221 | + | ||
1222 | +/* try to fill the TLB and return an exception if error. If retaddr is | ||
1223 | + NULL, it means that the function was called in C code (i.e. not | ||
1224 | + from generated code or from helper.c) */ | ||
1225 | +/* XXX: fix it to restore all registers */ | ||
1226 | +void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) | ||
1227 | +{ | ||
1228 | + TranslationBlock *tb; | ||
1229 | + CPUState *saved_env; | ||
1230 | + target_phys_addr_t pc; | ||
1231 | + int ret; | ||
1232 | + | ||
1233 | + /* XXX: hack to restore env in all cases, even if not called from | ||
1234 | + generated code */ | ||
1235 | + saved_env = env; | ||
1236 | + env = cpu_single_env; | ||
1237 | + ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, is_user, 1); | ||
1238 | + if (!likely(ret == 0)) { | ||
1239 | + if (likely(retaddr)) { | ||
1240 | + /* now we have a real cpu fault */ | ||
1241 | + pc = (target_phys_addr_t)retaddr; | ||
1242 | + tb = tb_find_pc(pc); | ||
1243 | + if (likely(tb)) { | ||
1244 | + /* the PC is inside the translated code. It means that we have | ||
1245 | + a virtual CPU fault */ | ||
1246 | + cpu_restore_state(tb, env, pc, NULL); | ||
1247 | + } | ||
1248 | + } | ||
1249 | + /* Exception index and error code are already set */ | ||
1250 | + cpu_loop_exit(); | ||
1251 | + } | ||
1252 | + env = saved_env; | ||
1253 | +} | ||
1254 | + | ||
1255 | +#endif |
target-alpha/op_helper.h
0 → 100644
1 | +/* | ||
2 | + * Alpha emulation cpu micro-operations helpers definitions for qemu. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Jocelyn Mayer | ||
5 | + * | ||
6 | + * This library is free software; you can redistribute it and/or | ||
7 | + * modify it under the terms of the GNU Lesser General Public | ||
8 | + * License as published by the Free Software Foundation; either | ||
9 | + * version 2 of the License, or (at your option) any later version. | ||
10 | + * | ||
11 | + * This library is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | + * Lesser General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public | ||
17 | + * License along with this library; if not, write to the Free Software | ||
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | + */ | ||
20 | + | ||
21 | +void helper_call_pal (uint32_t palcode); | ||
22 | +void helper_excp (uint32_t excp, uint32_t error); | ||
23 | +void helper_amask (void); | ||
24 | +void helper_load_pcc (void); | ||
25 | +void helper_load_implver (void); | ||
26 | +void helper_load_fpcr (void); | ||
27 | +void helper_store_fpcr (void); | ||
28 | +void helper_load_irf (void); | ||
29 | +void helper_set_irf (void); | ||
30 | +void helper_clear_irf (void); | ||
31 | +void helper_addqv (void); | ||
32 | +void helper_addlv (void); | ||
33 | +void helper_subqv (void); | ||
34 | +void helper_sublv (void); | ||
35 | +void helper_mullv (void); | ||
36 | +void helper_mulqv (void); | ||
37 | +void helper_umulh (void); | ||
38 | +void helper_ctpop (void); | ||
39 | +void helper_ctlz (void); | ||
40 | +void helper_cttz (void); | ||
41 | +void helper_mskbl (void); | ||
42 | +void helper_extbl (void); | ||
43 | +void helper_insbl (void); | ||
44 | +void helper_mskwl (void); | ||
45 | +void helper_extwl (void); | ||
46 | +void helper_inswl (void); | ||
47 | +void helper_mskll (void); | ||
48 | +void helper_extll (void); | ||
49 | +void helper_insll (void); | ||
50 | +void helper_zap (void); | ||
51 | +void helper_zapnot (void); | ||
52 | +void helper_mskql (void); | ||
53 | +void helper_extql (void); | ||
54 | +void helper_insql (void); | ||
55 | +void helper_mskwh (void); | ||
56 | +void helper_inswh (void); | ||
57 | +void helper_extwh (void); | ||
58 | +void helper_msklh (void); | ||
59 | +void helper_inslh (void); | ||
60 | +void helper_extlh (void); | ||
61 | +void helper_mskqh (void); | ||
62 | +void helper_insqh (void); | ||
63 | +void helper_extqh (void); | ||
64 | +void helper_cmpbge (void); | ||
65 | +void helper_cmov_fir (int freg); | ||
66 | + | ||
67 | +double helper_ldff_raw (target_ulong ea); | ||
68 | +void helper_stff_raw (target_ulong ea, double op); | ||
69 | +double helper_ldfg_raw (target_ulong ea); | ||
70 | +void helper_stfg_raw (target_ulong ea, double op); | ||
71 | +#if !defined(CONFIG_USER_ONLY) | ||
72 | +double helper_ldff_user (target_ulong ea); | ||
73 | +void helper_stff_user (target_ulong ea, double op); | ||
74 | +double helper_ldff_kernel (target_ulong ea); | ||
75 | +void helper_stff_kernel (target_ulong ea, double op); | ||
76 | +double helper_ldff_data (target_ulong ea); | ||
77 | +void helper_stff_data (target_ulong ea, double op); | ||
78 | +double helper_ldfg_user (target_ulong ea); | ||
79 | +void helper_stfg_user (target_ulong ea, double op); | ||
80 | +double helper_ldfg_kernel (target_ulong ea); | ||
81 | +void helper_stfg_kernel (target_ulong ea, double op); | ||
82 | +double helper_ldfg_data (target_ulong ea); | ||
83 | +void helper_stfg_data (target_ulong ea, double op); | ||
84 | +#endif | ||
85 | + | ||
86 | +void helper_sqrts (void); | ||
87 | +void helper_cpys (void); | ||
88 | +void helper_cpysn (void); | ||
89 | +void helper_cpyse (void); | ||
90 | +void helper_itofs (void); | ||
91 | +void helper_ftois (void); | ||
92 | + | ||
93 | +void helper_sqrtt (void); | ||
94 | +void helper_cmptun (void); | ||
95 | +void helper_cmpteq (void); | ||
96 | +void helper_cmptle (void); | ||
97 | +void helper_cmptlt (void); | ||
98 | +void helper_itoft (void); | ||
99 | +void helper_ftoit (void); | ||
100 | + | ||
101 | +void helper_addf (void); | ||
102 | +void helper_subf (void); | ||
103 | +void helper_mulf (void); | ||
104 | +void helper_divf (void); | ||
105 | +void helper_sqrtf (void); | ||
106 | +void helper_cmpfeq (void); | ||
107 | +void helper_cmpfne (void); | ||
108 | +void helper_cmpflt (void); | ||
109 | +void helper_cmpfle (void); | ||
110 | +void helper_cmpfgt (void); | ||
111 | +void helper_cmpfge (void); | ||
112 | +void helper_itoff (void); | ||
113 | + | ||
114 | +void helper_addg (void); | ||
115 | +void helper_subg (void); | ||
116 | +void helper_mulg (void); | ||
117 | +void helper_divg (void); | ||
118 | +void helper_sqrtg (void); | ||
119 | +void helper_cmpgeq (void); | ||
120 | +void helper_cmpglt (void); | ||
121 | +void helper_cmpgle (void); | ||
122 | + | ||
123 | +void helper_cvtqs (void); | ||
124 | +void helper_cvttq (void); | ||
125 | +void helper_cvtqt (void); | ||
126 | +void helper_cvtqf (void); | ||
127 | +void helper_cvtgf (void); | ||
128 | +void helper_cvtgd (void); | ||
129 | +void helper_cvtgq (void); | ||
130 | +void helper_cvtqg (void); | ||
131 | +void helper_cvtdg (void); | ||
132 | +void helper_cvtlq (void); | ||
133 | +void helper_cvtql (void); | ||
134 | +void helper_cvtqlv (void); | ||
135 | +void helper_cvtqlsv (void); | ||
136 | + | ||
137 | +void helper_mfpr (int iprn); | ||
138 | +void helper_mtpr (int iprn); | ||
139 | +void helper_ld_phys_to_virt (void); | ||
140 | +void helper_st_phys_to_virt (void); | ||
141 | +void helper_tb_flush (void); |
target-alpha/op_helper_mem.h
0 → 100644
1 | +/* | ||
2 | + * Alpha emulation cpu micro-operations helpers for memory accesses for qemu. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Jocelyn Mayer | ||
5 | + * | ||
6 | + * This library is free software; you can redistribute it and/or | ||
7 | + * modify it under the terms of the GNU Lesser General Public | ||
8 | + * License as published by the Free Software Foundation; either | ||
9 | + * version 2 of the License, or (at your option) any later version. | ||
10 | + * | ||
11 | + * This library is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | + * Lesser General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public | ||
17 | + * License along with this library; if not, write to the Free Software | ||
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | + */ | ||
20 | + | ||
21 | +/* XXX: TODO */ | ||
22 | +double glue(helper_ldff, MEMSUFFIX) (target_ulong ea) | ||
23 | +{ | ||
24 | + return 0; | ||
25 | +} | ||
26 | + | ||
27 | +void glue(helper_stff, MEMSUFFIX) (target_ulong ea, double op) | ||
28 | +{ | ||
29 | +} | ||
30 | + | ||
31 | +double glue(helper_ldfg, MEMSUFFIX) (target_ulong ea) | ||
32 | +{ | ||
33 | + return 0; | ||
34 | +} | ||
35 | + | ||
36 | +void glue(helper_stfg, MEMSUFFIX) (target_ulong ea, double op) | ||
37 | +{ | ||
38 | +} | ||
39 | + | ||
40 | +#undef MEMSUFFIX |
target-alpha/op_mem.h
0 → 100644
1 | +/* | ||
2 | + * Alpha emulation cpu micro-operations for memory accesses for qemu. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Jocelyn Mayer | ||
5 | + * | ||
6 | + * This library is free software; you can redistribute it and/or | ||
7 | + * modify it under the terms of the GNU Lesser General Public | ||
8 | + * License as published by the Free Software Foundation; either | ||
9 | + * version 2 of the License, or (at your option) any later version. | ||
10 | + * | ||
11 | + * This library is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | + * Lesser General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public | ||
17 | + * License along with this library; if not, write to the Free Software | ||
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | + */ | ||
20 | + | ||
21 | +#define DEBUG_MEM_ACCESSES | ||
22 | +#if defined (DEBUG_MEM_ACCESSES) | ||
23 | +void helper_print_mem_EA (target_ulong EA); | ||
24 | +#define print_mem_EA(EA) do { helper_print_mem_EA(EA); } while (0) | ||
25 | +#else | ||
26 | +#define print_mem_EA(EA) do { } while (0) | ||
27 | +#endif | ||
28 | + | ||
29 | +static inline uint32_t glue(ldl_l, MEMSUFFIX) (target_ulong EA) | ||
30 | +{ | ||
31 | + env->lock = EA; | ||
32 | + | ||
33 | + return glue(ldl, MEMSUFFIX)(EA); | ||
34 | +} | ||
35 | + | ||
36 | +static inline uint32_t glue(ldq_l, MEMSUFFIX) (target_ulong EA) | ||
37 | +{ | ||
38 | + env->lock = EA; | ||
39 | + | ||
40 | + return glue(ldq, MEMSUFFIX)(EA); | ||
41 | +} | ||
42 | + | ||
43 | +static inline void glue(stl_c, MEMSUFFIX) (target_ulong EA, uint32_t data) | ||
44 | +{ | ||
45 | + if (EA == env->lock) { | ||
46 | + glue(stl, MEMSUFFIX)(EA, data); | ||
47 | + T0 = 0; | ||
48 | + } else { | ||
49 | + T0 = 1; | ||
50 | + } | ||
51 | + env->lock = -1; | ||
52 | +} | ||
53 | + | ||
54 | +static inline void glue(stq_c, MEMSUFFIX) (target_ulong EA, uint64_t data) | ||
55 | +{ | ||
56 | + if (EA == env->lock) { | ||
57 | + glue(stq, MEMSUFFIX)(EA, data); | ||
58 | + T0 = 0; | ||
59 | + } else { | ||
60 | + T0 = 1; | ||
61 | + } | ||
62 | + env->lock = -1; | ||
63 | +} | ||
64 | + | ||
65 | +#define ALPHA_LD_OP(name, op) \ | ||
66 | +void OPPROTO glue(glue(op_ld, name), MEMSUFFIX) (void) \ | ||
67 | +{ \ | ||
68 | + print_mem_EA(T0); \ | ||
69 | + T1 = glue(op, MEMSUFFIX)(T0); \ | ||
70 | + RETURN(); \ | ||
71 | +} | ||
72 | + | ||
73 | +#define ALPHA_ST_OP(name, op) \ | ||
74 | +void OPPROTO glue(glue(op_st, name), MEMSUFFIX) (void) \ | ||
75 | +{ \ | ||
76 | + print_mem_EA(T0); \ | ||
77 | + glue(op, MEMSUFFIX)(T0, T1); \ | ||
78 | + RETURN(); \ | ||
79 | +} | ||
80 | + | ||
81 | +ALPHA_LD_OP(bu, ldub); | ||
82 | +ALPHA_ST_OP(b, stb); | ||
83 | +ALPHA_LD_OP(wu, lduw); | ||
84 | +ALPHA_ST_OP(w, stw); | ||
85 | +ALPHA_LD_OP(l, ldl); | ||
86 | +ALPHA_ST_OP(l, stl); | ||
87 | +ALPHA_LD_OP(q, ldq); | ||
88 | +ALPHA_ST_OP(q, stq); | ||
89 | + | ||
90 | +ALPHA_LD_OP(q_u, ldq); | ||
91 | +ALPHA_ST_OP(q_u, stq); | ||
92 | + | ||
93 | +ALPHA_LD_OP(l_l, ldl_l); | ||
94 | +ALPHA_LD_OP(q_l, ldq_l); | ||
95 | +ALPHA_ST_OP(l_c, stl_c); | ||
96 | +ALPHA_ST_OP(q_c, stq_c); | ||
97 | + | ||
98 | +#define ALPHA_LDF_OP(name, op) \ | ||
99 | +void OPPROTO glue(glue(op_ld, name), MEMSUFFIX) (void) \ | ||
100 | +{ \ | ||
101 | + print_mem_EA(T0); \ | ||
102 | + FT1 = glue(op, MEMSUFFIX)(T0); \ | ||
103 | + RETURN(); \ | ||
104 | +} | ||
105 | + | ||
106 | +#define ALPHA_STF_OP(name, op) \ | ||
107 | +void OPPROTO glue(glue(op_st, name), MEMSUFFIX) (void) \ | ||
108 | +{ \ | ||
109 | + print_mem_EA(T0); \ | ||
110 | + glue(op, MEMSUFFIX)(T0, FT1); \ | ||
111 | + RETURN(); \ | ||
112 | +} | ||
113 | + | ||
114 | +ALPHA_LDF_OP(t, ldfq); | ||
115 | +ALPHA_STF_OP(t, stfq); | ||
116 | +ALPHA_LDF_OP(s, ldfl); | ||
117 | +ALPHA_STF_OP(s, stfl); | ||
118 | + | ||
119 | +/* VAX floating point */ | ||
120 | +ALPHA_LDF_OP(f, helper_ldff); | ||
121 | +ALPHA_STF_OP(f, helper_stff); | ||
122 | +ALPHA_LDF_OP(g, helper_ldfg); | ||
123 | +ALPHA_STF_OP(g, helper_stfg); | ||
124 | + | ||
125 | +#undef MEMSUFFIX |
target-alpha/op_template.h
0 → 100644
1 | +/* | ||
2 | + * Alpha emulation cpu micro-operations templates for qemu. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Jocelyn Mayer | ||
5 | + * | ||
6 | + * This library is free software; you can redistribute it and/or | ||
7 | + * modify it under the terms of the GNU Lesser General Public | ||
8 | + * License as published by the Free Software Foundation; either | ||
9 | + * version 2 of the License, or (at your option) any later version. | ||
10 | + * | ||
11 | + * This library is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | + * Lesser General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public | ||
17 | + * License along with this library; if not, write to the Free Software | ||
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | + */ | ||
20 | + | ||
21 | +/* Optimized constant loads */ | ||
22 | +#if REG < 3 | ||
23 | +void OPPROTO glue(op_reset_T, REG) (void) | ||
24 | +{ | ||
25 | + glue(T, REG) = 0; | ||
26 | + RETURN(); | ||
27 | +} | ||
28 | + | ||
29 | +void OPPROTO glue(op_reset_FT, REG) (void) | ||
30 | +{ | ||
31 | + glue(FT, REG) = 0; | ||
32 | + RETURN(); | ||
33 | +} | ||
34 | + | ||
35 | +/* XXX: This can be great on most RISC machines */ | ||
36 | +#if !defined(__i386__) && !defined(__x86_64__) | ||
37 | +void OPPROTO glue(op_set_s16_T, REG) (void) | ||
38 | +{ | ||
39 | + glue(T, REG) = (int16_t)PARAM(1); | ||
40 | + RETURN(); | ||
41 | +} | ||
42 | + | ||
43 | +void OPPROTO glue(op_set_u16_T, REG) (void) | ||
44 | +{ | ||
45 | + glue(T, REG) = (uint16_t)PARAM(1); | ||
46 | + RETURN(); | ||
47 | +} | ||
48 | +#endif | ||
49 | + | ||
50 | +void OPPROTO glue(op_set_s32_T, REG) (void) | ||
51 | +{ | ||
52 | + glue(T, REG) = (int32_t)PARAM(1); | ||
53 | + RETURN(); | ||
54 | +} | ||
55 | + | ||
56 | +void OPPROTO glue(op_set_u32_T, REG) (void) | ||
57 | +{ | ||
58 | + glue(T, REG) = (uint32_t)PARAM(1); | ||
59 | + RETURN(); | ||
60 | +} | ||
61 | + | ||
62 | +#if 0 // Qemu does not know how to do this... | ||
63 | +void OPPROTO glue(op_set_64_T, REG) (void) | ||
64 | +{ | ||
65 | + glue(T, REG) = (int64_t)PARAM(1); | ||
66 | + RETURN(); | ||
67 | +} | ||
68 | +#else | ||
69 | +void OPPROTO glue(op_set_64_T, REG) (void) | ||
70 | +{ | ||
71 | + glue(T, REG) = ((int64_t)PARAM(1) << 32) | (int64_t)PARAM(2); | ||
72 | + RETURN(); | ||
73 | +} | ||
74 | +#endif | ||
75 | + | ||
76 | +#endif /* REG < 3 */ | ||
77 | + | ||
78 | +/* Fixed-point register moves */ | ||
79 | +#if REG < 31 | ||
80 | +void OPPROTO glue(op_load_T0_ir, REG) (void) | ||
81 | +{ | ||
82 | + T0 = env->ir[REG]; | ||
83 | + RETURN(); | ||
84 | +} | ||
85 | + | ||
86 | +void OPPROTO glue(op_load_T1_ir, REG) (void) | ||
87 | +{ | ||
88 | + T1 = env->ir[REG]; | ||
89 | + RETURN(); | ||
90 | +} | ||
91 | + | ||
92 | +void OPPROTO glue(op_load_T2_ir, REG) (void) | ||
93 | +{ | ||
94 | + T2 = env->ir[REG]; | ||
95 | + RETURN(); | ||
96 | +} | ||
97 | + | ||
98 | +void OPPROTO glue(op_store_T0_ir, REG) (void) | ||
99 | +{ | ||
100 | + env->ir[REG] = T0; | ||
101 | + RETURN(); | ||
102 | +} | ||
103 | + | ||
104 | +void OPPROTO glue(op_store_T1_ir, REG) (void) | ||
105 | +{ | ||
106 | + env->ir[REG] = T1; | ||
107 | + RETURN(); | ||
108 | +} | ||
109 | + | ||
110 | +void OPPROTO glue(op_store_T2_ir, REG) (void) | ||
111 | +{ | ||
112 | + env->ir[REG] = T2; | ||
113 | + RETURN(); | ||
114 | +} | ||
115 | + | ||
116 | +void OPPROTO glue(op_cmov_ir, REG) (void) | ||
117 | +{ | ||
118 | + if (T0) | ||
119 | + env->ir[REG] = T1; | ||
120 | + RETURN(); | ||
121 | +} | ||
122 | + | ||
123 | +/* floating point registers moves */ | ||
124 | +void OPPROTO glue(op_load_FT0_fir, REG) (void) | ||
125 | +{ | ||
126 | + FT0 = env->fir[REG]; | ||
127 | + RETURN(); | ||
128 | +} | ||
129 | + | ||
130 | +void OPPROTO glue(op_load_FT1_fir, REG) (void) | ||
131 | +{ | ||
132 | + FT1 = env->fir[REG]; | ||
133 | + RETURN(); | ||
134 | +} | ||
135 | + | ||
136 | +void OPPROTO glue(op_load_FT2_fir, REG) (void) | ||
137 | +{ | ||
138 | + FT2 = env->fir[REG]; | ||
139 | + RETURN(); | ||
140 | +} | ||
141 | + | ||
142 | +void OPPROTO glue(op_store_FT0_fir, REG) (void) | ||
143 | +{ | ||
144 | + env->fir[REG] = FT0; | ||
145 | + RETURN(); | ||
146 | +} | ||
147 | + | ||
148 | +void OPPROTO glue(op_store_FT1_fir, REG) (void) | ||
149 | +{ | ||
150 | + env->fir[REG] = FT1; | ||
151 | + RETURN(); | ||
152 | +} | ||
153 | + | ||
154 | +void OPPROTO glue(op_store_FT2_fir, REG) (void) | ||
155 | +{ | ||
156 | + env->fir[REG] = FT2; | ||
157 | + RETURN(); | ||
158 | +} | ||
159 | + | ||
160 | +void OPPROTO glue(op_cmov_fir, REG) (void) | ||
161 | +{ | ||
162 | + helper_cmov_fir(REG); | ||
163 | + RETURN(); | ||
164 | +} | ||
165 | +#endif /* REG < 31 */ | ||
166 | + | ||
167 | +#undef REG |
target-alpha/translate.c
0 → 100644
1 | +/* | ||
2 | + * Alpha emulation cpu translation for qemu. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Jocelyn Mayer | ||
5 | + * | ||
6 | + * This library is free software; you can redistribute it and/or | ||
7 | + * modify it under the terms of the GNU Lesser General Public | ||
8 | + * License as published by the Free Software Foundation; either | ||
9 | + * version 2 of the License, or (at your option) any later version. | ||
10 | + * | ||
11 | + * This library is distributed in the hope that it will be useful, | ||
12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | + * Lesser General Public License for more details. | ||
15 | + * | ||
16 | + * You should have received a copy of the GNU Lesser General Public | ||
17 | + * License along with this library; if not, write to the Free Software | ||
18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | + */ | ||
20 | + | ||
21 | +#include <stdint.h> | ||
22 | +#include <stdlib.h> | ||
23 | +#include <stdio.h> | ||
24 | + | ||
25 | +#include "cpu.h" | ||
26 | +#include "exec-all.h" | ||
27 | +#include "disas.h" | ||
28 | + | ||
29 | +#define DO_SINGLE_STEP | ||
30 | +#define GENERATE_NOP | ||
31 | +#define ALPHA_DEBUG_DISAS | ||
32 | +#define DO_TB_FLUSH | ||
33 | + | ||
34 | +typedef struct DisasContext DisasContext; | ||
35 | +struct DisasContext { | ||
36 | + uint64_t pc; | ||
37 | + int mem_idx; | ||
38 | +#if !defined (CONFIG_USER_ONLY) | ||
39 | + int pal_mode; | ||
40 | +#endif | ||
41 | + uint32_t amask; | ||
42 | +}; | ||
43 | + | ||
44 | +#ifdef USE_DIRECT_JUMP | ||
45 | +#define TBPARAM(x) | ||
46 | +#else | ||
47 | +#define TBPARAM(x) (long)(x) | ||
48 | +#endif | ||
49 | + | ||
50 | +enum { | ||
51 | +#define DEF(s, n, copy_size) INDEX_op_ ## s, | ||
52 | +#include "opc.h" | ||
53 | +#undef DEF | ||
54 | + NB_OPS, | ||
55 | +}; | ||
56 | + | ||
57 | +static uint16_t *gen_opc_ptr; | ||
58 | +static uint32_t *gen_opparam_ptr; | ||
59 | + | ||
60 | +#include "gen-op.h" | ||
61 | + | ||
62 | +static inline void gen_op_nop (void) | ||
63 | +{ | ||
64 | +#if defined(GENERATE_NOP) | ||
65 | + gen_op_no_op(); | ||
66 | +#endif | ||
67 | +} | ||
68 | + | ||
69 | +#define GEN32(func, NAME) \ | ||
70 | +static GenOpFunc *NAME ## _table [32] = { \ | ||
71 | +NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \ | ||
72 | +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \ | ||
73 | +NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \ | ||
74 | +NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \ | ||
75 | +NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \ | ||
76 | +NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \ | ||
77 | +NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \ | ||
78 | +NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \ | ||
79 | +}; \ | ||
80 | +static inline void func(int n) \ | ||
81 | +{ \ | ||
82 | + NAME ## _table[n](); \ | ||
83 | +} | ||
84 | + | ||
85 | +/* IR moves */ | ||
86 | +/* Special hacks for ir31 */ | ||
87 | +#define gen_op_load_T0_ir31 gen_op_reset_T0 | ||
88 | +#define gen_op_load_T1_ir31 gen_op_reset_T1 | ||
89 | +#define gen_op_load_T2_ir31 gen_op_reset_T2 | ||
90 | +#define gen_op_store_T0_ir31 gen_op_nop | ||
91 | +#define gen_op_store_T1_ir31 gen_op_nop | ||
92 | +#define gen_op_store_T2_ir31 gen_op_nop | ||
93 | +#define gen_op_cmov_ir31 gen_op_nop | ||
94 | +GEN32(gen_op_load_T0_ir, gen_op_load_T0_ir); | ||
95 | +GEN32(gen_op_load_T1_ir, gen_op_load_T1_ir); | ||
96 | +GEN32(gen_op_load_T2_ir, gen_op_load_T2_ir); | ||
97 | +GEN32(gen_op_store_T0_ir, gen_op_store_T0_ir); | ||
98 | +GEN32(gen_op_store_T1_ir, gen_op_store_T1_ir); | ||
99 | +GEN32(gen_op_store_T2_ir, gen_op_store_T2_ir); | ||
100 | +GEN32(gen_op_cmov_ir, gen_op_cmov_ir); | ||
101 | + | ||
102 | +static inline void gen_load_ir (DisasContext *ctx, int irn, int Tn) | ||
103 | +{ | ||
104 | + switch (Tn) { | ||
105 | + case 0: | ||
106 | + gen_op_load_T0_ir(irn); | ||
107 | + break; | ||
108 | + case 1: | ||
109 | + gen_op_load_T1_ir(irn); | ||
110 | + break; | ||
111 | + case 2: | ||
112 | + gen_op_load_T2_ir(irn); | ||
113 | + break; | ||
114 | + } | ||
115 | +} | ||
116 | + | ||
117 | +static inline void gen_store_ir (DisasContext *ctx, int irn, int Tn) | ||
118 | +{ | ||
119 | + switch (Tn) { | ||
120 | + case 0: | ||
121 | + gen_op_store_T0_ir(irn); | ||
122 | + break; | ||
123 | + case 1: | ||
124 | + gen_op_store_T1_ir(irn); | ||
125 | + break; | ||
126 | + case 2: | ||
127 | + gen_op_store_T2_ir(irn); | ||
128 | + break; | ||
129 | + } | ||
130 | +} | ||
131 | + | ||
132 | +/* FIR moves */ | ||
133 | +/* Special hacks for fir31 */ | ||
134 | +#define gen_op_load_FT0_fir31 gen_op_reset_FT0 | ||
135 | +#define gen_op_load_FT1_fir31 gen_op_reset_FT1 | ||
136 | +#define gen_op_load_FT2_fir31 gen_op_reset_FT2 | ||
137 | +#define gen_op_store_FT0_fir31 gen_op_nop | ||
138 | +#define gen_op_store_FT1_fir31 gen_op_nop | ||
139 | +#define gen_op_store_FT2_fir31 gen_op_nop | ||
140 | +#define gen_op_cmov_fir31 gen_op_nop | ||
141 | +GEN32(gen_op_load_FT0_fir, gen_op_load_FT0_fir); | ||
142 | +GEN32(gen_op_load_FT1_fir, gen_op_load_FT1_fir); | ||
143 | +GEN32(gen_op_load_FT2_fir, gen_op_load_FT2_fir); | ||
144 | +GEN32(gen_op_store_FT0_fir, gen_op_store_FT0_fir); | ||
145 | +GEN32(gen_op_store_FT1_fir, gen_op_store_FT1_fir); | ||
146 | +GEN32(gen_op_store_FT2_fir, gen_op_store_FT2_fir); | ||
147 | +GEN32(gen_op_cmov_fir, gen_op_cmov_fir); | ||
148 | + | ||
149 | +static inline void gen_load_fir (DisasContext *ctx, int firn, int Tn) | ||
150 | +{ | ||
151 | + switch (Tn) { | ||
152 | + case 0: | ||
153 | + gen_op_load_FT0_fir(firn); | ||
154 | + break; | ||
155 | + case 1: | ||
156 | + gen_op_load_FT1_fir(firn); | ||
157 | + break; | ||
158 | + case 2: | ||
159 | + gen_op_load_FT2_fir(firn); | ||
160 | + break; | ||
161 | + } | ||
162 | +} | ||
163 | + | ||
164 | +static inline void gen_store_fir (DisasContext *ctx, int firn, int Tn) | ||
165 | +{ | ||
166 | + switch (Tn) { | ||
167 | + case 0: | ||
168 | + gen_op_store_FT0_fir(firn); | ||
169 | + break; | ||
170 | + case 1: | ||
171 | + gen_op_store_FT1_fir(firn); | ||
172 | + break; | ||
173 | + case 2: | ||
174 | + gen_op_store_FT2_fir(firn); | ||
175 | + break; | ||
176 | + } | ||
177 | +} | ||
178 | + | ||
179 | +/* Memory moves */ | ||
180 | +#if defined(CONFIG_USER_ONLY) | ||
181 | +#define OP_LD_TABLE(width) \ | ||
182 | +static GenOpFunc *gen_op_ld##width[] = { \ | ||
183 | + &gen_op_ld##width##_raw, \ | ||
184 | +} | ||
185 | +#define OP_ST_TABLE(width) \ | ||
186 | +static GenOpFunc *gen_op_st##width[] = { \ | ||
187 | + &gen_op_st##width##_raw, \ | ||
188 | +} | ||
189 | +#else | ||
190 | +#define OP_LD_TABLE(width) \ | ||
191 | +static GenOpFunc *gen_op_ld##width[] = { \ | ||
192 | + &gen_op_ld##width##_kernel, \ | ||
193 | + &gen_op_ld##width##_user, /* executive */ \ | ||
194 | + &gen_op_ld##width##_data, /* supervisor */ \ | ||
195 | + &gen_op_ld##width##_data, /* user */ \ | ||
196 | +} | ||
197 | +#define OP_ST_TABLE(width) \ | ||
198 | +static GenOpFunc *gen_op_st##width[] = { \ | ||
199 | + &gen_op_st##width##_kernel, \ | ||
200 | + &gen_op_st##width##_user, /* executive */ \ | ||
201 | + &gen_op_st##width##_data, /* supervisor */ \ | ||
202 | + &gen_op_st##width##_data, /* user */ \ | ||
203 | +} | ||
204 | +#endif | ||
205 | + | ||
206 | +#define GEN_LD(width) \ | ||
207 | +OP_LD_TABLE(width); \ | ||
208 | +static void gen_ld##width (DisasContext *ctx) \ | ||
209 | +{ \ | ||
210 | + (*gen_op_ld##width[ctx->mem_idx])(); \ | ||
211 | +} | ||
212 | + | ||
213 | +#define GEN_ST(width) \ | ||
214 | +OP_ST_TABLE(width); \ | ||
215 | +static void gen_st##width (DisasContext *ctx) \ | ||
216 | +{ \ | ||
217 | + (*gen_op_st##width[ctx->mem_idx])(); \ | ||
218 | +} | ||
219 | + | ||
220 | +GEN_LD(bu); | ||
221 | +GEN_ST(b); | ||
222 | +GEN_LD(wu); | ||
223 | +GEN_ST(w); | ||
224 | +GEN_LD(l); | ||
225 | +GEN_ST(l); | ||
226 | +GEN_LD(q); | ||
227 | +GEN_ST(q); | ||
228 | +GEN_LD(q_u); | ||
229 | +GEN_ST(q_u); | ||
230 | +GEN_LD(l_l); | ||
231 | +GEN_ST(l_c); | ||
232 | +GEN_LD(q_l); | ||
233 | +GEN_ST(q_c); | ||
234 | + | ||
235 | +GEN_LD(f); | ||
236 | +GEN_ST(f); | ||
237 | +GEN_LD(g); | ||
238 | +GEN_ST(g); | ||
239 | +GEN_LD(s); | ||
240 | +GEN_ST(s); | ||
241 | +GEN_LD(t); | ||
242 | +GEN_ST(t); | ||
243 | + | ||
244 | +#if defined(__i386__) || defined(__x86_64__) | ||
245 | +static inline void gen_op_set_s16_T0 (int16_t imm) | ||
246 | +{ | ||
247 | + gen_op_set_s32_T0((int32_t)imm); | ||
248 | +} | ||
249 | + | ||
250 | +static inline void gen_op_set_s16_T1 (int16_t imm) | ||
251 | +{ | ||
252 | + gen_op_set_s32_T1((int32_t)imm); | ||
253 | +} | ||
254 | + | ||
255 | +static inline void gen_op_set_u16_T0 (uint16_t imm) | ||
256 | +{ | ||
257 | + gen_op_set_s32_T0((uint32_t)imm); | ||
258 | +} | ||
259 | + | ||
260 | +static inline void gen_op_set_u16_T1 (uint16_t imm) | ||
261 | +{ | ||
262 | + gen_op_set_s32_T1((uint32_t)imm); | ||
263 | +} | ||
264 | +#endif | ||
265 | + | ||
266 | +static inline void gen_set_sT0 (DisasContext *ctx, int64_t imm) | ||
267 | +{ | ||
268 | + int32_t imm32; | ||
269 | + int16_t imm16; | ||
270 | + | ||
271 | + imm32 = imm; | ||
272 | + if (imm32 == imm) { | ||
273 | + imm16 = imm; | ||
274 | + if (imm16 == imm) { | ||
275 | + if (imm == 0) { | ||
276 | + gen_op_reset_T0(); | ||
277 | + } else { | ||
278 | + gen_op_set_s16_T0(imm16); | ||
279 | + } | ||
280 | + } else { | ||
281 | + gen_op_set_s32_T0(imm32); | ||
282 | + } | ||
283 | + } else { | ||
284 | +#if 0 // Qemu does not know how to do this... | ||
285 | + gen_op_set_64_T0(imm); | ||
286 | +#else | ||
287 | + gen_op_set_64_T0(imm >> 32, imm); | ||
288 | +#endif | ||
289 | + } | ||
290 | +} | ||
291 | + | ||
292 | +static inline void gen_set_sT1 (DisasContext *ctx, int64_t imm) | ||
293 | +{ | ||
294 | + int32_t imm32; | ||
295 | + int16_t imm16; | ||
296 | + | ||
297 | + imm32 = imm; | ||
298 | + if (imm32 == imm) { | ||
299 | + imm16 = imm; | ||
300 | + if (imm16 == imm) { | ||
301 | + if (imm == 0) { | ||
302 | + gen_op_reset_T1(); | ||
303 | + } else { | ||
304 | + gen_op_set_s16_T1(imm16); | ||
305 | + } | ||
306 | + } else { | ||
307 | + gen_op_set_s32_T1(imm32); | ||
308 | + } | ||
309 | + } else { | ||
310 | +#if 0 // Qemu does not know how to do this... | ||
311 | + gen_op_set_64_T1(imm); | ||
312 | +#else | ||
313 | + gen_op_set_64_T1(imm >> 32, imm); | ||
314 | +#endif | ||
315 | + } | ||
316 | +} | ||
317 | + | ||
318 | +static inline void gen_set_uT0 (DisasContext *ctx, uint64_t imm) | ||
319 | +{ | ||
320 | + if (!(imm >> 32)) { | ||
321 | + if ((!imm >> 16)) { | ||
322 | + if (imm == 0) | ||
323 | + gen_op_reset_T0(); | ||
324 | + else | ||
325 | + gen_op_set_u16_T0(imm); | ||
326 | + } else { | ||
327 | + gen_op_set_u32_T0(imm); | ||
328 | + } | ||
329 | + } else { | ||
330 | +#if 0 // Qemu does not know how to do this... | ||
331 | + gen_op_set_64_T0(imm); | ||
332 | +#else | ||
333 | + gen_op_set_64_T0(imm >> 32, imm); | ||
334 | +#endif | ||
335 | + } | ||
336 | +} | ||
337 | + | ||
338 | +static inline void gen_set_uT1 (DisasContext *ctx, uint64_t imm) | ||
339 | +{ | ||
340 | + if (!(imm >> 32)) { | ||
341 | + if ((!imm >> 16)) { | ||
342 | + if (imm == 0) | ||
343 | + gen_op_reset_T1(); | ||
344 | + else | ||
345 | + gen_op_set_u16_T1(imm); | ||
346 | + } else { | ||
347 | + gen_op_set_u32_T1(imm); | ||
348 | + } | ||
349 | + } else { | ||
350 | +#if 0 // Qemu does not know how to do this... | ||
351 | + gen_op_set_64_T1(imm); | ||
352 | +#else | ||
353 | + gen_op_set_64_T1(imm >> 32, imm); | ||
354 | +#endif | ||
355 | + } | ||
356 | +} | ||
357 | + | ||
358 | +static inline void gen_update_pc (DisasContext *ctx) | ||
359 | +{ | ||
360 | + if (!(ctx->pc >> 32)) { | ||
361 | + gen_op_update_pc32(ctx->pc); | ||
362 | + } else { | ||
363 | +#if 0 // Qemu does not know how to do this... | ||
364 | + gen_op_update_pc(ctx->pc); | ||
365 | +#else | ||
366 | + gen_op_update_pc(ctx->pc >> 32, ctx->pc); | ||
367 | +#endif | ||
368 | + } | ||
369 | +} | ||
370 | + | ||
371 | +static inline void _gen_op_bcond (DisasContext *ctx) | ||
372 | +{ | ||
373 | +#if 0 // Qemu does not know how to do this... | ||
374 | + gen_op_bcond(ctx->pc); | ||
375 | +#else | ||
376 | + gen_op_bcond(ctx->pc >> 32, ctx->pc); | ||
377 | +#endif | ||
378 | +} | ||
379 | + | ||
380 | +static inline void gen_excp (DisasContext *ctx, int exception, int error_code) | ||
381 | +{ | ||
382 | + gen_update_pc(ctx); | ||
383 | + gen_op_excp(exception, error_code); | ||
384 | +} | ||
385 | + | ||
386 | +static inline void gen_invalid (DisasContext *ctx) | ||
387 | +{ | ||
388 | + gen_excp(ctx, EXCP_OPCDEC, 0); | ||
389 | +} | ||
390 | + | ||
391 | +static void gen_load_mem (DisasContext *ctx, | ||
392 | + void (*gen_load_op)(DisasContext *ctx), | ||
393 | + int ra, int rb, int32_t disp16, int clear) | ||
394 | +{ | ||
395 | + if (ra == 31 && disp16 == 0) { | ||
396 | + /* UNOP */ | ||
397 | + gen_op_nop(); | ||
398 | + } else { | ||
399 | + gen_load_ir(ctx, rb, 0); | ||
400 | + if (disp16 != 0) { | ||
401 | + gen_set_sT1(ctx, disp16); | ||
402 | + gen_op_addq(); | ||
403 | + } | ||
404 | + if (clear) | ||
405 | + gen_op_n7(); | ||
406 | + (*gen_load_op)(ctx); | ||
407 | + gen_store_ir(ctx, ra, 1); | ||
408 | + } | ||
409 | +} | ||
410 | + | ||
411 | +static void gen_store_mem (DisasContext *ctx, | ||
412 | + void (*gen_store_op)(DisasContext *ctx), | ||
413 | + int ra, int rb, int32_t disp16, int clear) | ||
414 | +{ | ||
415 | + gen_load_ir(ctx, rb, 0); | ||
416 | + if (disp16 != 0) { | ||
417 | + gen_set_sT1(ctx, disp16); | ||
418 | + gen_op_addq(); | ||
419 | + } | ||
420 | + if (clear) | ||
421 | + gen_op_n7(); | ||
422 | + gen_load_ir(ctx, ra, 1); | ||
423 | + (*gen_store_op)(ctx); | ||
424 | +} | ||
425 | + | ||
426 | +static void gen_load_fmem (DisasContext *ctx, | ||
427 | + void (*gen_load_fop)(DisasContext *ctx), | ||
428 | + int ra, int rb, int32_t disp16) | ||
429 | +{ | ||
430 | + gen_load_ir(ctx, rb, 0); | ||
431 | + if (disp16 != 0) { | ||
432 | + gen_set_sT1(ctx, disp16); | ||
433 | + gen_op_addq(); | ||
434 | + } | ||
435 | + (*gen_load_fop)(ctx); | ||
436 | + gen_store_fir(ctx, ra, 1); | ||
437 | +} | ||
438 | + | ||
439 | +static void gen_store_fmem (DisasContext *ctx, | ||
440 | + void (*gen_store_fop)(DisasContext *ctx), | ||
441 | + int ra, int rb, int32_t disp16) | ||
442 | +{ | ||
443 | + gen_load_ir(ctx, rb, 0); | ||
444 | + if (disp16 != 0) { | ||
445 | + gen_set_sT1(ctx, disp16); | ||
446 | + gen_op_addq(); | ||
447 | + } | ||
448 | + gen_load_fir(ctx, ra, 1); | ||
449 | + (*gen_store_fop)(ctx); | ||
450 | +} | ||
451 | + | ||
452 | +static void gen_bcond (DisasContext *ctx, void (*gen_test_op)(void), | ||
453 | + int ra, int32_t disp16) | ||
454 | +{ | ||
455 | + if (disp16 != 0) { | ||
456 | + gen_set_uT0(ctx, ctx->pc); | ||
457 | + gen_set_sT1(ctx, disp16 << 2); | ||
458 | + gen_op_addq1(); | ||
459 | + } else { | ||
460 | + gen_set_uT1(ctx, ctx->pc); | ||
461 | + } | ||
462 | + gen_load_ir(ctx, ra, 0); | ||
463 | + (*gen_test_op)(); | ||
464 | + _gen_op_bcond(ctx); | ||
465 | +} | ||
466 | + | ||
467 | +static void gen_fbcond (DisasContext *ctx, void (*gen_test_op)(void), | ||
468 | + int ra, int32_t disp16) | ||
469 | +{ | ||
470 | + if (disp16 != 0) { | ||
471 | + gen_set_uT0(ctx, ctx->pc); | ||
472 | + gen_set_sT1(ctx, disp16 << 2); | ||
473 | + gen_op_addq1(); | ||
474 | + } else { | ||
475 | + gen_set_uT1(ctx, ctx->pc); | ||
476 | + } | ||
477 | + gen_load_fir(ctx, ra, 0); | ||
478 | + (*gen_test_op)(); | ||
479 | + _gen_op_bcond(ctx); | ||
480 | +} | ||
481 | + | ||
482 | +static void gen_arith2 (DisasContext *ctx, void (*gen_arith_op)(void), | ||
483 | + int rb, int rc, int islit, int8_t lit) | ||
484 | +{ | ||
485 | + if (islit) | ||
486 | + gen_set_sT0(ctx, lit); | ||
487 | + else | ||
488 | + gen_load_ir(ctx, rb, 0); | ||
489 | + (*gen_arith_op)(); | ||
490 | + gen_store_ir(ctx, rc, 0); | ||
491 | +} | ||
492 | + | ||
493 | +static void gen_arith3 (DisasContext *ctx, void (*gen_arith_op)(void), | ||
494 | + int ra, int rb, int rc, int islit, int8_t lit) | ||
495 | +{ | ||
496 | + gen_load_ir(ctx, ra, 0); | ||
497 | + if (islit) | ||
498 | + gen_set_sT1(ctx, lit); | ||
499 | + else | ||
500 | + gen_load_ir(ctx, rb, 1); | ||
501 | + (*gen_arith_op)(); | ||
502 | + gen_store_ir(ctx, rc, 0); | ||
503 | +} | ||
504 | + | ||
505 | +static void gen_cmov (DisasContext *ctx, void (*gen_test_op)(void), | ||
506 | + int ra, int rb, int rc, int islit, int8_t lit) | ||
507 | +{ | ||
508 | + gen_load_ir(ctx, ra, 1); | ||
509 | + if (islit) | ||
510 | + gen_set_sT0(ctx, lit); | ||
511 | + else | ||
512 | + gen_load_ir(ctx, rb, 0); | ||
513 | + (*gen_test_op)(); | ||
514 | + gen_op_cmov_ir(rc); | ||
515 | +} | ||
516 | + | ||
517 | +static void gen_farith2 (DisasContext *ctx, void (*gen_arith_fop)(void), | ||
518 | + int rb, int rc) | ||
519 | +{ | ||
520 | + gen_load_fir(ctx, rb, 0); | ||
521 | + (*gen_arith_fop)(); | ||
522 | + gen_store_fir(ctx, rc, 0); | ||
523 | +} | ||
524 | + | ||
525 | +static void gen_farith3 (DisasContext *ctx, void (*gen_arith_fop)(void), | ||
526 | + int ra, int rb, int rc) | ||
527 | +{ | ||
528 | + gen_load_fir(ctx, ra, 0); | ||
529 | + gen_load_fir(ctx, rb, 1); | ||
530 | + (*gen_arith_fop)(); | ||
531 | + gen_store_fir(ctx, rc, 0); | ||
532 | +} | ||
533 | + | ||
534 | +static void gen_fcmov (DisasContext *ctx, void (*gen_test_fop)(void), | ||
535 | + int ra, int rb, int rc) | ||
536 | +{ | ||
537 | + gen_load_fir(ctx, ra, 0); | ||
538 | + gen_load_fir(ctx, rb, 1); | ||
539 | + (*gen_test_fop)(); | ||
540 | + gen_op_cmov_fir(rc); | ||
541 | +} | ||
542 | + | ||
543 | +static void gen_fti (DisasContext *ctx, void (*gen_move_fop)(void), | ||
544 | + int ra, int rc) | ||
545 | +{ | ||
546 | + gen_load_fir(ctx, rc, 0); | ||
547 | + (*gen_move_fop)(); | ||
548 | + gen_store_ir(ctx, ra, 0); | ||
549 | +} | ||
550 | + | ||
551 | +static void gen_itf (DisasContext *ctx, void (*gen_move_fop)(void), | ||
552 | + int ra, int rc) | ||
553 | +{ | ||
554 | + gen_load_ir(ctx, ra, 0); | ||
555 | + (*gen_move_fop)(); | ||
556 | + gen_store_fir(ctx, rc, 0); | ||
557 | +} | ||
558 | + | ||
559 | +static void gen_s4addl (void) | ||
560 | +{ | ||
561 | + gen_op_s4(); | ||
562 | + gen_op_addl(); | ||
563 | +} | ||
564 | + | ||
565 | +static void gen_s4subl (void) | ||
566 | +{ | ||
567 | + gen_op_s4(); | ||
568 | + gen_op_subl(); | ||
569 | +} | ||
570 | + | ||
571 | +static void gen_s8addl (void) | ||
572 | +{ | ||
573 | + gen_op_s8(); | ||
574 | + gen_op_addl(); | ||
575 | +} | ||
576 | + | ||
577 | +static void gen_s8subl (void) | ||
578 | +{ | ||
579 | + gen_op_s8(); | ||
580 | + gen_op_subl(); | ||
581 | +} | ||
582 | + | ||
583 | +static void gen_s4addq (void) | ||
584 | +{ | ||
585 | + gen_op_s4(); | ||
586 | + gen_op_addq(); | ||
587 | +} | ||
588 | + | ||
589 | +static void gen_s4subq (void) | ||
590 | +{ | ||
591 | + gen_op_s4(); | ||
592 | + gen_op_subq(); | ||
593 | +} | ||
594 | + | ||
595 | +static void gen_s8addq (void) | ||
596 | +{ | ||
597 | + gen_op_s8(); | ||
598 | + gen_op_addq(); | ||
599 | +} | ||
600 | + | ||
601 | +static void gen_s8subq (void) | ||
602 | +{ | ||
603 | + gen_op_s8(); | ||
604 | + gen_op_subq(); | ||
605 | +} | ||
606 | + | ||
607 | +static void gen_amask (void) | ||
608 | +{ | ||
609 | + gen_op_load_amask(); | ||
610 | + gen_op_bic(); | ||
611 | +} | ||
612 | + | ||
613 | +static int translate_one (DisasContext *ctx, uint32_t insn) | ||
614 | +{ | ||
615 | + uint32_t palcode; | ||
616 | + int32_t disp21, disp16, disp12; | ||
617 | + uint16_t fn11, fn16; | ||
618 | + uint8_t opc, ra, rb, rc, sbz, fpfn, fn7, fn2, islit; | ||
619 | + int8_t lit; | ||
620 | + int ret; | ||
621 | + | ||
622 | + /* Decode all instruction fields */ | ||
623 | + opc = insn >> 26; | ||
624 | + ra = (insn >> 21) & 0x1F; | ||
625 | + rb = (insn >> 16) & 0x1F; | ||
626 | + rc = insn & 0x1F; | ||
627 | + sbz = (insn >> 13) & 0x07; | ||
628 | + islit = (insn >> 12) & 1; | ||
629 | + lit = (insn >> 13) & 0xFF; | ||
630 | + palcode = insn & 0x03FFFFFF; | ||
631 | + disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11; | ||
632 | + disp16 = (int16_t)(insn & 0x0000FFFF); | ||
633 | + disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20; | ||
634 | + fn16 = insn & 0x0000FFFF; | ||
635 | + fn11 = (insn >> 5) & 0x000007FF; | ||
636 | + fpfn = fn11 & 0x3F; | ||
637 | + fn7 = (insn >> 5) & 0x0000007F; | ||
638 | + fn2 = (insn >> 5) & 0x00000003; | ||
639 | + ret = 0; | ||
640 | +#if defined ALPHA_DEBUG_DISAS | ||
641 | + if (logfile != NULL) { | ||
642 | + fprintf(logfile, "opc %02x ra %d rb %d rc %d disp16 %04x\n", | ||
643 | + opc, ra, rb, rc, disp16); | ||
644 | + } | ||
645 | +#endif | ||
646 | + switch (opc) { | ||
647 | + case 0x00: | ||
648 | + /* CALL_PAL */ | ||
649 | + if (palcode >= 0x80 && palcode < 0xC0) { | ||
650 | + /* Unprivileged PAL call */ | ||
651 | + gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x1F) << 6), 0); | ||
652 | +#if !defined (CONFIG_USER_ONLY) | ||
653 | + } else if (palcode < 0x40) { | ||
654 | + /* Privileged PAL code */ | ||
655 | + if (ctx->mem_idx & 1) | ||
656 | + goto invalid_opc; | ||
657 | + else | ||
658 | + gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x1F) << 6), 0); | ||
659 | +#endif | ||
660 | + } else { | ||
661 | + /* Invalid PAL call */ | ||
662 | + goto invalid_opc; | ||
663 | + } | ||
664 | + ret = 3; | ||
665 | + break; | ||
666 | + case 0x01: | ||
667 | + /* OPC01 */ | ||
668 | + goto invalid_opc; | ||
669 | + case 0x02: | ||
670 | + /* OPC02 */ | ||
671 | + goto invalid_opc; | ||
672 | + case 0x03: | ||
673 | + /* OPC03 */ | ||
674 | + goto invalid_opc; | ||
675 | + case 0x04: | ||
676 | + /* OPC04 */ | ||
677 | + goto invalid_opc; | ||
678 | + case 0x05: | ||
679 | + /* OPC05 */ | ||
680 | + goto invalid_opc; | ||
681 | + case 0x06: | ||
682 | + /* OPC06 */ | ||
683 | + goto invalid_opc; | ||
684 | + case 0x07: | ||
685 | + /* OPC07 */ | ||
686 | + goto invalid_opc; | ||
687 | + case 0x08: | ||
688 | + /* LDA */ | ||
689 | + gen_load_ir(ctx, rb, 0); | ||
690 | + gen_set_sT1(ctx, disp16); | ||
691 | + gen_op_addq(); | ||
692 | + gen_store_ir(ctx, ra, 0); | ||
693 | + break; | ||
694 | + case 0x09: | ||
695 | + /* LDAH */ | ||
696 | + gen_load_ir(ctx, rb, 0); | ||
697 | + gen_set_sT1(ctx, disp16 << 16); | ||
698 | + gen_op_addq(); | ||
699 | + gen_store_ir(ctx, ra, 0); | ||
700 | + break; | ||
701 | + case 0x0A: | ||
702 | + /* LDBU */ | ||
703 | + if (!(ctx->amask & AMASK_BWX)) | ||
704 | + goto invalid_opc; | ||
705 | + gen_load_mem(ctx, &gen_ldbu, ra, rb, disp16, 0); | ||
706 | + break; | ||
707 | + case 0x0B: | ||
708 | + /* LDQ_U */ | ||
709 | + gen_load_mem(ctx, &gen_ldq_u, ra, rb, disp16, 1); | ||
710 | + break; | ||
711 | + case 0x0C: | ||
712 | + /* LDWU */ | ||
713 | + if (!(ctx->amask & AMASK_BWX)) | ||
714 | + goto invalid_opc; | ||
715 | + gen_load_mem(ctx, &gen_ldwu, ra, rb, disp16, 0); | ||
716 | + break; | ||
717 | + case 0x0D: | ||
718 | + /* STW */ | ||
719 | + if (!(ctx->amask & AMASK_BWX)) | ||
720 | + goto invalid_opc; | ||
721 | + gen_store_mem(ctx, &gen_stw, ra, rb, disp16, 0); | ||
722 | + break; | ||
723 | + case 0x0E: | ||
724 | + /* STB */ | ||
725 | + if (!(ctx->amask & AMASK_BWX)) | ||
726 | + goto invalid_opc; | ||
727 | + gen_store_mem(ctx, &gen_stb, ra, rb, disp16, 0); | ||
728 | + break; | ||
729 | + case 0x0F: | ||
730 | + /* STQ_U */ | ||
731 | + gen_store_mem(ctx, &gen_stq_u, ra, rb, disp16, 1); | ||
732 | + break; | ||
733 | + case 0x10: | ||
734 | + switch (fn7) { | ||
735 | + case 0x00: | ||
736 | + /* ADDL */ | ||
737 | + gen_arith3(ctx, &gen_op_addl, ra, rb, rc, islit, lit); | ||
738 | + break; | ||
739 | + case 0x02: | ||
740 | + /* S4ADDL */ | ||
741 | + gen_arith3(ctx, &gen_s4addl, ra, rb, rc, islit, lit); | ||
742 | + break; | ||
743 | + case 0x09: | ||
744 | + /* SUBL */ | ||
745 | + gen_arith3(ctx, &gen_op_subl, ra, rb, rc, islit, lit); | ||
746 | + break; | ||
747 | + case 0x0B: | ||
748 | + /* S4SUBL */ | ||
749 | + gen_arith3(ctx, &gen_s4subl, ra, rb, rc, islit, lit); | ||
750 | + break; | ||
751 | + case 0x0F: | ||
752 | + /* CMPBGE */ | ||
753 | + gen_arith3(ctx, &gen_op_cmpbge, ra, rb, rc, islit, lit); | ||
754 | + break; | ||
755 | + case 0x12: | ||
756 | + /* S8ADDL */ | ||
757 | + gen_arith3(ctx, &gen_s8addl, ra, rb, rc, islit, lit); | ||
758 | + break; | ||
759 | + case 0x1B: | ||
760 | + /* S8SUBL */ | ||
761 | + gen_arith3(ctx, &gen_s8subl, ra, rb, rc, islit, lit); | ||
762 | + break; | ||
763 | + case 0x1D: | ||
764 | + /* CMPULT */ | ||
765 | + gen_arith3(ctx, &gen_op_cmpult, ra, rb, rc, islit, lit); | ||
766 | + break; | ||
767 | + case 0x20: | ||
768 | + /* ADDQ */ | ||
769 | + gen_arith3(ctx, &gen_op_addq, ra, rb, rc, islit, lit); | ||
770 | + break; | ||
771 | + case 0x22: | ||
772 | + /* S4ADDQ */ | ||
773 | + gen_arith3(ctx, &gen_s4addq, ra, rb, rc, islit, lit); | ||
774 | + break; | ||
775 | + case 0x29: | ||
776 | + /* SUBQ */ | ||
777 | + gen_arith3(ctx, &gen_op_subq, ra, rb, rc, islit, lit); | ||
778 | + break; | ||
779 | + case 0x2B: | ||
780 | + /* S4SUBQ */ | ||
781 | + gen_arith3(ctx, &gen_s4subq, ra, rb, rc, islit, lit); | ||
782 | + break; | ||
783 | + case 0x2D: | ||
784 | + /* CMPEQ */ | ||
785 | + gen_arith3(ctx, &gen_op_cmpeq, ra, rb, rc, islit, lit); | ||
786 | + break; | ||
787 | + case 0x32: | ||
788 | + /* S8ADDQ */ | ||
789 | + gen_arith3(ctx, &gen_s8addq, ra, rb, rc, islit, lit); | ||
790 | + break; | ||
791 | + case 0x3B: | ||
792 | + /* S8SUBQ */ | ||
793 | + gen_arith3(ctx, &gen_s8subq, ra, rb, rc, islit, lit); | ||
794 | + break; | ||
795 | + case 0x3D: | ||
796 | + /* CMPULE */ | ||
797 | + gen_arith3(ctx, &gen_op_cmpule, ra, rb, rc, islit, lit); | ||
798 | + break; | ||
799 | + case 0x40: | ||
800 | + /* ADDL/V */ | ||
801 | + gen_arith3(ctx, &gen_op_addlv, ra, rb, rc, islit, lit); | ||
802 | + break; | ||
803 | + case 0x49: | ||
804 | + /* SUBL/V */ | ||
805 | + gen_arith3(ctx, &gen_op_sublv, ra, rb, rc, islit, lit); | ||
806 | + break; | ||
807 | + case 0x4D: | ||
808 | + /* CMPLT */ | ||
809 | + gen_arith3(ctx, &gen_op_cmplt, ra, rb, rc, islit, lit); | ||
810 | + break; | ||
811 | + case 0x60: | ||
812 | + /* ADDQ/V */ | ||
813 | + gen_arith3(ctx, &gen_op_addqv, ra, rb, rc, islit, lit); | ||
814 | + break; | ||
815 | + case 0x69: | ||
816 | + /* SUBQ/V */ | ||
817 | + gen_arith3(ctx, &gen_op_subqv, ra, rb, rc, islit, lit); | ||
818 | + break; | ||
819 | + case 0x6D: | ||
820 | + /* CMPLE */ | ||
821 | + gen_arith3(ctx, &gen_op_cmple, ra, rb, rc, islit, lit); | ||
822 | + break; | ||
823 | + default: | ||
824 | + goto invalid_opc; | ||
825 | + } | ||
826 | + break; | ||
827 | + case 0x11: | ||
828 | + switch (fn7) { | ||
829 | + case 0x00: | ||
830 | + /* AND */ | ||
831 | + gen_arith3(ctx, &gen_op_and, ra, rb, rc, islit, lit); | ||
832 | + break; | ||
833 | + case 0x08: | ||
834 | + /* BIC */ | ||
835 | + gen_arith3(ctx, &gen_op_bic, ra, rb, rc, islit, lit); | ||
836 | + break; | ||
837 | + case 0x14: | ||
838 | + /* CMOVLBS */ | ||
839 | + gen_cmov(ctx, &gen_op_cmplbs, ra, rb, rc, islit, lit); | ||
840 | + break; | ||
841 | + case 0x16: | ||
842 | + /* CMOVLBC */ | ||
843 | + gen_cmov(ctx, &gen_op_cmplbc, ra, rb, rc, islit, lit); | ||
844 | + break; | ||
845 | + case 0x20: | ||
846 | + /* BIS */ | ||
847 | + if (ra == rb || ra == 31 || rb == 31) { | ||
848 | + if (ra == 31 && rc == 31) { | ||
849 | + /* NOP */ | ||
850 | + gen_op_nop(); | ||
851 | + } else { | ||
852 | + /* MOV */ | ||
853 | + gen_load_ir(ctx, rb, 0); | ||
854 | + gen_store_ir(ctx, rc, 0); | ||
855 | + } | ||
856 | + } else { | ||
857 | + gen_arith3(ctx, &gen_op_bis, ra, rb, rc, islit, lit); | ||
858 | + } | ||
859 | + break; | ||
860 | + case 0x24: | ||
861 | + /* CMOVEQ */ | ||
862 | + gen_cmov(ctx, &gen_op_cmpeqz, ra, rb, rc, islit, lit); | ||
863 | + break; | ||
864 | + case 0x26: | ||
865 | + /* CMOVNE */ | ||
866 | + gen_cmov(ctx, &gen_op_cmpnez, ra, rb, rc, islit, lit); | ||
867 | + break; | ||
868 | + case 0x28: | ||
869 | + /* ORNOT */ | ||
870 | + gen_arith3(ctx, &gen_op_ornot, ra, rb, rc, islit, lit); | ||
871 | + break; | ||
872 | + case 0x40: | ||
873 | + /* XOR */ | ||
874 | + gen_arith3(ctx, &gen_op_xor, ra, rb, rc, islit, lit); | ||
875 | + break; | ||
876 | + case 0x44: | ||
877 | + /* CMOVLT */ | ||
878 | + gen_cmov(ctx, &gen_op_cmpltz, ra, rb, rc, islit, lit); | ||
879 | + break; | ||
880 | + case 0x46: | ||
881 | + /* CMOVGE */ | ||
882 | + gen_cmov(ctx, &gen_op_cmpgez, ra, rb, rc, islit, lit); | ||
883 | + break; | ||
884 | + case 0x48: | ||
885 | + /* EQV */ | ||
886 | + gen_arith3(ctx, &gen_op_eqv, ra, rb, rc, islit, lit); | ||
887 | + break; | ||
888 | + case 0x61: | ||
889 | + /* AMASK */ | ||
890 | + gen_arith2(ctx, &gen_amask, rb, rc, islit, lit); | ||
891 | + break; | ||
892 | + case 0x64: | ||
893 | + /* CMOVLE */ | ||
894 | + gen_cmov(ctx, &gen_op_cmplez, ra, rb, rc, islit, lit); | ||
895 | + break; | ||
896 | + case 0x66: | ||
897 | + /* CMOVGT */ | ||
898 | + gen_cmov(ctx, &gen_op_cmpgtz, ra, rb, rc, islit, lit); | ||
899 | + break; | ||
900 | + case 0x6C: | ||
901 | + /* IMPLVER */ | ||
902 | + gen_op_load_implver(); | ||
903 | + gen_store_ir(ctx, rc, 0); | ||
904 | + break; | ||
905 | + default: | ||
906 | + goto invalid_opc; | ||
907 | + } | ||
908 | + break; | ||
909 | + case 0x12: | ||
910 | + switch (fn7) { | ||
911 | + case 0x02: | ||
912 | + /* MSKBL */ | ||
913 | + gen_arith3(ctx, &gen_op_mskbl, ra, rb, rc, islit, lit); | ||
914 | + break; | ||
915 | + case 0x06: | ||
916 | + /* EXTBL */ | ||
917 | + gen_arith3(ctx, &gen_op_extbl, ra, rb, rc, islit, lit); | ||
918 | + break; | ||
919 | + case 0x0B: | ||
920 | + /* INSBL */ | ||
921 | + gen_arith3(ctx, &gen_op_insbl, ra, rb, rc, islit, lit); | ||
922 | + break; | ||
923 | + case 0x12: | ||
924 | + /* MSKWL */ | ||
925 | + gen_arith3(ctx, &gen_op_mskwl, ra, rb, rc, islit, lit); | ||
926 | + break; | ||
927 | + case 0x16: | ||
928 | + /* EXTWL */ | ||
929 | + gen_arith3(ctx, &gen_op_extwl, ra, rb, rc, islit, lit); | ||
930 | + break; | ||
931 | + case 0x1B: | ||
932 | + /* INSWL */ | ||
933 | + gen_arith3(ctx, &gen_op_inswl, ra, rb, rc, islit, lit); | ||
934 | + break; | ||
935 | + case 0x22: | ||
936 | + /* MSKLL */ | ||
937 | + gen_arith3(ctx, &gen_op_mskll, ra, rb, rc, islit, lit); | ||
938 | + break; | ||
939 | + case 0x26: | ||
940 | + /* EXTLL */ | ||
941 | + gen_arith3(ctx, &gen_op_extll, ra, rb, rc, islit, lit); | ||
942 | + break; | ||
943 | + case 0x2B: | ||
944 | + /* INSLL */ | ||
945 | + gen_arith3(ctx, &gen_op_insll, ra, rb, rc, islit, lit); | ||
946 | + break; | ||
947 | + case 0x30: | ||
948 | + /* ZAP */ | ||
949 | + gen_arith3(ctx, &gen_op_zap, ra, rb, rc, islit, lit); | ||
950 | + break; | ||
951 | + case 0x31: | ||
952 | + /* ZAPNOT */ | ||
953 | + gen_arith3(ctx, &gen_op_zapnot, ra, rb, rc, islit, lit); | ||
954 | + break; | ||
955 | + case 0x32: | ||
956 | + /* MSKQL */ | ||
957 | + gen_arith3(ctx, &gen_op_mskql, ra, rb, rc, islit, lit); | ||
958 | + break; | ||
959 | + case 0x34: | ||
960 | + /* SRL */ | ||
961 | + gen_arith3(ctx, &gen_op_srl, ra, rb, rc, islit, lit); | ||
962 | + break; | ||
963 | + case 0x36: | ||
964 | + /* EXTQL */ | ||
965 | + gen_arith3(ctx, &gen_op_extql, ra, rb, rc, islit, lit); | ||
966 | + break; | ||
967 | + case 0x39: | ||
968 | + /* SLL */ | ||
969 | + gen_arith3(ctx, &gen_op_sll, ra, rb, rc, islit, lit); | ||
970 | + break; | ||
971 | + case 0x3B: | ||
972 | + /* INSQL */ | ||
973 | + gen_arith3(ctx, &gen_op_insql, ra, rb, rc, islit, lit); | ||
974 | + break; | ||
975 | + case 0x3C: | ||
976 | + /* SRA */ | ||
977 | + gen_arith3(ctx, &gen_op_sra, ra, rb, rc, islit, lit); | ||
978 | + break; | ||
979 | + case 0x52: | ||
980 | + /* MSKWH */ | ||
981 | + gen_arith3(ctx, &gen_op_mskwh, ra, rb, rc, islit, lit); | ||
982 | + break; | ||
983 | + case 0x57: | ||
984 | + /* INSWH */ | ||
985 | + gen_arith3(ctx, &gen_op_inswh, ra, rb, rc, islit, lit); | ||
986 | + break; | ||
987 | + case 0x5A: | ||
988 | + /* EXTWH */ | ||
989 | + gen_arith3(ctx, &gen_op_extwh, ra, rb, rc, islit, lit); | ||
990 | + break; | ||
991 | + case 0x62: | ||
992 | + /* MSKLH */ | ||
993 | + gen_arith3(ctx, &gen_op_msklh, ra, rb, rc, islit, lit); | ||
994 | + break; | ||
995 | + case 0x67: | ||
996 | + /* INSLH */ | ||
997 | + gen_arith3(ctx, &gen_op_inslh, ra, rb, rc, islit, lit); | ||
998 | + break; | ||
999 | + case 0x6A: | ||
1000 | + /* EXTLH */ | ||
1001 | + gen_arith3(ctx, &gen_op_extlh, ra, rb, rc, islit, lit); | ||
1002 | + break; | ||
1003 | + case 0x72: | ||
1004 | + /* MSKQH */ | ||
1005 | + gen_arith3(ctx, &gen_op_mskqh, ra, rb, rc, islit, lit); | ||
1006 | + break; | ||
1007 | + case 0x77: | ||
1008 | + /* INSQH */ | ||
1009 | + gen_arith3(ctx, &gen_op_insqh, ra, rb, rc, islit, lit); | ||
1010 | + break; | ||
1011 | + case 0x7A: | ||
1012 | + /* EXTQH */ | ||
1013 | + gen_arith3(ctx, &gen_op_extqh, ra, rb, rc, islit, lit); | ||
1014 | + break; | ||
1015 | + default: | ||
1016 | + goto invalid_opc; | ||
1017 | + } | ||
1018 | + break; | ||
1019 | + case 0x13: | ||
1020 | + switch (fn7) { | ||
1021 | + case 0x00: | ||
1022 | + /* MULL */ | ||
1023 | + gen_arith3(ctx, &gen_op_mull, ra, rb, rc, islit, lit); | ||
1024 | + break; | ||
1025 | + case 0x20: | ||
1026 | + /* MULQ */ | ||
1027 | + gen_arith3(ctx, &gen_op_mulq, ra, rb, rc, islit, lit); | ||
1028 | + break; | ||
1029 | + case 0x30: | ||
1030 | + /* UMULH */ | ||
1031 | + gen_arith3(ctx, &gen_op_umulh, ra, rb, rc, islit, lit); | ||
1032 | + break; | ||
1033 | + case 0x40: | ||
1034 | + /* MULL/V */ | ||
1035 | + gen_arith3(ctx, &gen_op_mullv, ra, rb, rc, islit, lit); | ||
1036 | + break; | ||
1037 | + case 0x60: | ||
1038 | + /* MULQ/V */ | ||
1039 | + gen_arith3(ctx, &gen_op_mulqv, ra, rb, rc, islit, lit); | ||
1040 | + break; | ||
1041 | + default: | ||
1042 | + goto invalid_opc; | ||
1043 | + } | ||
1044 | + break; | ||
1045 | + case 0x14: | ||
1046 | + switch (fpfn) { /* f11 & 0x3F */ | ||
1047 | + case 0x04: | ||
1048 | + /* ITOFS */ | ||
1049 | + if (!(ctx->amask & AMASK_FIX)) | ||
1050 | + goto invalid_opc; | ||
1051 | + gen_itf(ctx, &gen_op_itofs, ra, rc); | ||
1052 | + break; | ||
1053 | + case 0x0A: | ||
1054 | + /* SQRTF */ | ||
1055 | + if (!(ctx->amask & AMASK_FIX)) | ||
1056 | + goto invalid_opc; | ||
1057 | + gen_farith2(ctx, &gen_op_sqrtf, rb, rc); | ||
1058 | + break; | ||
1059 | + case 0x0B: | ||
1060 | + /* SQRTS */ | ||
1061 | + if (!(ctx->amask & AMASK_FIX)) | ||
1062 | + goto invalid_opc; | ||
1063 | + gen_farith2(ctx, &gen_op_sqrts, rb, rc); | ||
1064 | + break; | ||
1065 | + case 0x14: | ||
1066 | + /* ITOFF */ | ||
1067 | + if (!(ctx->amask & AMASK_FIX)) | ||
1068 | + goto invalid_opc; | ||
1069 | +#if 0 // TODO | ||
1070 | + gen_itf(ctx, &gen_op_itoff, ra, rc); | ||
1071 | +#else | ||
1072 | + goto invalid_opc; | ||
1073 | +#endif | ||
1074 | + break; | ||
1075 | + case 0x24: | ||
1076 | + /* ITOFT */ | ||
1077 | + if (!(ctx->amask & AMASK_FIX)) | ||
1078 | + goto invalid_opc; | ||
1079 | + gen_itf(ctx, &gen_op_itoft, ra, rc); | ||
1080 | + break; | ||
1081 | + case 0x2A: | ||
1082 | + /* SQRTG */ | ||
1083 | + if (!(ctx->amask & AMASK_FIX)) | ||
1084 | + goto invalid_opc; | ||
1085 | + gen_farith2(ctx, &gen_op_sqrtg, rb, rc); | ||
1086 | + break; | ||
1087 | + case 0x02B: | ||
1088 | + /* SQRTT */ | ||
1089 | + if (!(ctx->amask & AMASK_FIX)) | ||
1090 | + goto invalid_opc; | ||
1091 | + gen_farith2(ctx, &gen_op_sqrtt, rb, rc); | ||
1092 | + break; | ||
1093 | + default: | ||
1094 | + goto invalid_opc; | ||
1095 | + } | ||
1096 | + break; | ||
1097 | + case 0x15: | ||
1098 | + /* VAX floating point */ | ||
1099 | + /* XXX: rounding mode and trap are ignored (!) */ | ||
1100 | + switch (fpfn) { /* f11 & 0x3F */ | ||
1101 | + case 0x00: | ||
1102 | + /* ADDF */ | ||
1103 | + gen_farith3(ctx, &gen_op_addf, ra, rb, rc); | ||
1104 | + break; | ||
1105 | + case 0x01: | ||
1106 | + /* SUBF */ | ||
1107 | + gen_farith3(ctx, &gen_op_subf, ra, rb, rc); | ||
1108 | + break; | ||
1109 | + case 0x02: | ||
1110 | + /* MULF */ | ||
1111 | + gen_farith3(ctx, &gen_op_mulf, ra, rb, rc); | ||
1112 | + break; | ||
1113 | + case 0x03: | ||
1114 | + /* DIVF */ | ||
1115 | + gen_farith3(ctx, &gen_op_divf, ra, rb, rc); | ||
1116 | + break; | ||
1117 | + case 0x1E: | ||
1118 | + /* CVTDG */ | ||
1119 | +#if 0 // TODO | ||
1120 | + gen_farith2(ctx, &gen_op_cvtdg, rb, rc); | ||
1121 | +#else | ||
1122 | + goto invalid_opc; | ||
1123 | +#endif | ||
1124 | + break; | ||
1125 | + case 0x20: | ||
1126 | + /* ADDG */ | ||
1127 | + gen_farith3(ctx, &gen_op_addg, ra, rb, rc); | ||
1128 | + break; | ||
1129 | + case 0x21: | ||
1130 | + /* SUBG */ | ||
1131 | + gen_farith3(ctx, &gen_op_subg, ra, rb, rc); | ||
1132 | + break; | ||
1133 | + case 0x22: | ||
1134 | + /* MULG */ | ||
1135 | + gen_farith3(ctx, &gen_op_mulg, ra, rb, rc); | ||
1136 | + break; | ||
1137 | + case 0x23: | ||
1138 | + /* DIVG */ | ||
1139 | + gen_farith3(ctx, &gen_op_divg, ra, rb, rc); | ||
1140 | + break; | ||
1141 | + case 0x25: | ||
1142 | + /* CMPGEQ */ | ||
1143 | + gen_farith3(ctx, &gen_op_cmpgeq, ra, rb, rc); | ||
1144 | + break; | ||
1145 | + case 0x26: | ||
1146 | + /* CMPGLT */ | ||
1147 | + gen_farith3(ctx, &gen_op_cmpglt, ra, rb, rc); | ||
1148 | + break; | ||
1149 | + case 0x27: | ||
1150 | + /* CMPGLE */ | ||
1151 | + gen_farith3(ctx, &gen_op_cmpgle, ra, rb, rc); | ||
1152 | + break; | ||
1153 | + case 0x2C: | ||
1154 | + /* CVTGF */ | ||
1155 | + gen_farith2(ctx, &gen_op_cvtgf, rb, rc); | ||
1156 | + break; | ||
1157 | + case 0x2D: | ||
1158 | + /* CVTGD */ | ||
1159 | +#if 0 // TODO | ||
1160 | + gen_farith2(ctx, &gen_op_cvtgd, rb, rc); | ||
1161 | +#else | ||
1162 | + goto invalid_opc; | ||
1163 | +#endif | ||
1164 | + break; | ||
1165 | + case 0x2F: | ||
1166 | + /* CVTGQ */ | ||
1167 | + gen_farith2(ctx, &gen_op_cvtgq, rb, rc); | ||
1168 | + break; | ||
1169 | + case 0x3C: | ||
1170 | + /* CVTQF */ | ||
1171 | + gen_farith2(ctx, &gen_op_cvtqf, rb, rc); | ||
1172 | + break; | ||
1173 | + case 0x3E: | ||
1174 | + /* CVTQG */ | ||
1175 | + gen_farith2(ctx, &gen_op_cvtqg, rb, rc); | ||
1176 | + break; | ||
1177 | + default: | ||
1178 | + goto invalid_opc; | ||
1179 | + } | ||
1180 | + break; | ||
1181 | + case 0x16: | ||
1182 | + /* IEEE floating-point */ | ||
1183 | + /* XXX: rounding mode and traps are ignored (!) */ | ||
1184 | + switch (fpfn) { /* f11 & 0x3F */ | ||
1185 | + case 0x00: | ||
1186 | + /* ADDS */ | ||
1187 | + gen_farith3(ctx, &gen_op_adds, ra, rb, rc); | ||
1188 | + break; | ||
1189 | + case 0x01: | ||
1190 | + /* SUBS */ | ||
1191 | + gen_farith3(ctx, &gen_op_subs, ra, rb, rc); | ||
1192 | + break; | ||
1193 | + case 0x02: | ||
1194 | + /* MULS */ | ||
1195 | + gen_farith3(ctx, &gen_op_muls, ra, rb, rc); | ||
1196 | + break; | ||
1197 | + case 0x03: | ||
1198 | + /* DIVS */ | ||
1199 | + gen_farith3(ctx, &gen_op_divs, ra, rb, rc); | ||
1200 | + break; | ||
1201 | + case 0x20: | ||
1202 | + /* ADDT */ | ||
1203 | + gen_farith3(ctx, &gen_op_addt, ra, rb, rc); | ||
1204 | + break; | ||
1205 | + case 0x21: | ||
1206 | + /* SUBT */ | ||
1207 | + gen_farith3(ctx, &gen_op_subt, ra, rb, rc); | ||
1208 | + break; | ||
1209 | + case 0x22: | ||
1210 | + /* MULT */ | ||
1211 | + gen_farith3(ctx, &gen_op_mult, ra, rb, rc); | ||
1212 | + break; | ||
1213 | + case 0x23: | ||
1214 | + /* DIVT */ | ||
1215 | + gen_farith3(ctx, &gen_op_divt, ra, rb, rc); | ||
1216 | + break; | ||
1217 | + case 0x24: | ||
1218 | + /* CMPTUN */ | ||
1219 | + gen_farith3(ctx, &gen_op_cmptun, ra, rb, rc); | ||
1220 | + break; | ||
1221 | + case 0x25: | ||
1222 | + /* CMPTEQ */ | ||
1223 | + gen_farith3(ctx, &gen_op_cmpteq, ra, rb, rc); | ||
1224 | + break; | ||
1225 | + case 0x26: | ||
1226 | + /* CMPTLT */ | ||
1227 | + gen_farith3(ctx, &gen_op_cmptlt, ra, rb, rc); | ||
1228 | + break; | ||
1229 | + case 0x27: | ||
1230 | + /* CMPTLE */ | ||
1231 | + gen_farith3(ctx, &gen_op_cmptle, ra, rb, rc); | ||
1232 | + break; | ||
1233 | + case 0x2C: | ||
1234 | + /* XXX: incorrect */ | ||
1235 | + if (fn11 == 0x2AC) { | ||
1236 | + /* CVTST */ | ||
1237 | + gen_farith2(ctx, &gen_op_cvtst, rb, rc); | ||
1238 | + } else { | ||
1239 | + /* CVTTS */ | ||
1240 | + gen_farith2(ctx, &gen_op_cvtts, rb, rc); | ||
1241 | + } | ||
1242 | + break; | ||
1243 | + case 0x2F: | ||
1244 | + /* CVTTQ */ | ||
1245 | + gen_farith2(ctx, &gen_op_cvttq, rb, rc); | ||
1246 | + break; | ||
1247 | + case 0x3C: | ||
1248 | + /* CVTQS */ | ||
1249 | + gen_farith2(ctx, &gen_op_cvtqs, rb, rc); | ||
1250 | + break; | ||
1251 | + case 0x3E: | ||
1252 | + /* CVTQT */ | ||
1253 | + gen_farith2(ctx, &gen_op_cvtqt, rb, rc); | ||
1254 | + break; | ||
1255 | + default: | ||
1256 | + goto invalid_opc; | ||
1257 | + } | ||
1258 | + break; | ||
1259 | + case 0x17: | ||
1260 | + switch (fn11) { | ||
1261 | + case 0x010: | ||
1262 | + /* CVTLQ */ | ||
1263 | + gen_farith2(ctx, &gen_op_cvtlq, rb, rc); | ||
1264 | + break; | ||
1265 | + case 0x020: | ||
1266 | + /* CPYS */ | ||
1267 | + if (ra == rb) { | ||
1268 | + if (ra == 31 && rc == 31) { | ||
1269 | + /* FNOP */ | ||
1270 | + gen_op_nop(); | ||
1271 | + } else { | ||
1272 | + /* FMOV */ | ||
1273 | + gen_load_fir(ctx, rb, 0); | ||
1274 | + gen_store_fir(ctx, rc, 0); | ||
1275 | + } | ||
1276 | + } else { | ||
1277 | + gen_farith3(ctx, &gen_op_cpys, ra, rb, rc); | ||
1278 | + } | ||
1279 | + break; | ||
1280 | + case 0x021: | ||
1281 | + /* CPYSN */ | ||
1282 | + gen_farith2(ctx, &gen_op_cpysn, rb, rc); | ||
1283 | + break; | ||
1284 | + case 0x022: | ||
1285 | + /* CPYSE */ | ||
1286 | + gen_farith2(ctx, &gen_op_cpyse, rb, rc); | ||
1287 | + break; | ||
1288 | + case 0x024: | ||
1289 | + /* MT_FPCR */ | ||
1290 | + gen_load_fir(ctx, ra, 0); | ||
1291 | + gen_op_store_fpcr(); | ||
1292 | + break; | ||
1293 | + case 0x025: | ||
1294 | + /* MF_FPCR */ | ||
1295 | + gen_op_load_fpcr(); | ||
1296 | + gen_store_fir(ctx, ra, 0); | ||
1297 | + break; | ||
1298 | + case 0x02A: | ||
1299 | + /* FCMOVEQ */ | ||
1300 | + gen_fcmov(ctx, &gen_op_cmpfeq, ra, rb, rc); | ||
1301 | + break; | ||
1302 | + case 0x02B: | ||
1303 | + /* FCMOVNE */ | ||
1304 | + gen_fcmov(ctx, &gen_op_cmpfne, ra, rb, rc); | ||
1305 | + break; | ||
1306 | + case 0x02C: | ||
1307 | + /* FCMOVLT */ | ||
1308 | + gen_fcmov(ctx, &gen_op_cmpflt, ra, rb, rc); | ||
1309 | + break; | ||
1310 | + case 0x02D: | ||
1311 | + /* FCMOVGE */ | ||
1312 | + gen_fcmov(ctx, &gen_op_cmpfge, ra, rb, rc); | ||
1313 | + break; | ||
1314 | + case 0x02E: | ||
1315 | + /* FCMOVLE */ | ||
1316 | + gen_fcmov(ctx, &gen_op_cmpfle, ra, rb, rc); | ||
1317 | + break; | ||
1318 | + case 0x02F: | ||
1319 | + /* FCMOVGT */ | ||
1320 | + gen_fcmov(ctx, &gen_op_cmpfgt, ra, rb, rc); | ||
1321 | + break; | ||
1322 | + case 0x030: | ||
1323 | + /* CVTQL */ | ||
1324 | + gen_farith2(ctx, &gen_op_cvtql, rb, rc); | ||
1325 | + break; | ||
1326 | + case 0x130: | ||
1327 | + /* CVTQL/V */ | ||
1328 | + gen_farith2(ctx, &gen_op_cvtqlv, rb, rc); | ||
1329 | + break; | ||
1330 | + case 0x530: | ||
1331 | + /* CVTQL/SV */ | ||
1332 | + gen_farith2(ctx, &gen_op_cvtqlsv, rb, rc); | ||
1333 | + break; | ||
1334 | + default: | ||
1335 | + goto invalid_opc; | ||
1336 | + } | ||
1337 | + break; | ||
1338 | + case 0x18: | ||
1339 | + switch ((uint16_t)disp16) { | ||
1340 | + case 0x0000: | ||
1341 | + /* TRAPB */ | ||
1342 | + /* No-op. Just exit from the current tb */ | ||
1343 | + ret = 2; | ||
1344 | + break; | ||
1345 | + case 0x0400: | ||
1346 | + /* EXCB */ | ||
1347 | + /* No-op. Just exit from the current tb */ | ||
1348 | + ret = 2; | ||
1349 | + break; | ||
1350 | + case 0x4000: | ||
1351 | + /* MB */ | ||
1352 | + /* No-op */ | ||
1353 | + break; | ||
1354 | + case 0x4400: | ||
1355 | + /* WMB */ | ||
1356 | + /* No-op */ | ||
1357 | + break; | ||
1358 | + case 0x8000: | ||
1359 | + /* FETCH */ | ||
1360 | + /* No-op */ | ||
1361 | + break; | ||
1362 | + case 0xA000: | ||
1363 | + /* FETCH_M */ | ||
1364 | + /* No-op */ | ||
1365 | + break; | ||
1366 | + case 0xC000: | ||
1367 | + /* RPCC */ | ||
1368 | + gen_op_load_pcc(); | ||
1369 | + gen_store_ir(ctx, ra, 0); | ||
1370 | + break; | ||
1371 | + case 0xE000: | ||
1372 | + /* RC */ | ||
1373 | + gen_op_load_irf(); | ||
1374 | + gen_store_ir(ctx, ra, 0); | ||
1375 | + gen_op_clear_irf(); | ||
1376 | + break; | ||
1377 | + case 0xE800: | ||
1378 | + /* ECB */ | ||
1379 | + /* XXX: TODO: evict tb cache at address rb */ | ||
1380 | +#if 0 | ||
1381 | + ret = 2; | ||
1382 | +#else | ||
1383 | + goto invalid_opc; | ||
1384 | +#endif | ||
1385 | + break; | ||
1386 | + case 0xF000: | ||
1387 | + /* RS */ | ||
1388 | + gen_op_load_irf(); | ||
1389 | + gen_store_ir(ctx, ra, 0); | ||
1390 | + gen_op_set_irf(); | ||
1391 | + break; | ||
1392 | + case 0xF800: | ||
1393 | + /* WH64 */ | ||
1394 | + /* No-op */ | ||
1395 | + break; | ||
1396 | + default: | ||
1397 | + goto invalid_opc; | ||
1398 | + } | ||
1399 | + break; | ||
1400 | + case 0x19: | ||
1401 | + /* HW_MFPR (PALcode) */ | ||
1402 | +#if defined (CONFIG_USER_ONLY) | ||
1403 | + goto invalid_opc; | ||
1404 | +#else | ||
1405 | + if (!ctx->pal_mode) | ||
1406 | + goto invalid_opc; | ||
1407 | + gen_op_mfpr(insn & 0xFF); | ||
1408 | + gen_store_ir(ctx, ra, 0); | ||
1409 | + break; | ||
1410 | +#endif | ||
1411 | + case 0x1A: | ||
1412 | + gen_load_ir(ctx, rb, 0); | ||
1413 | + if (ra != 31) { | ||
1414 | + gen_set_uT1(ctx, ctx->pc); | ||
1415 | + gen_store_ir(ctx, ra, 1); | ||
1416 | + } | ||
1417 | + gen_op_branch(); | ||
1418 | + /* Those four jumps only differ by the branch prediction hint */ | ||
1419 | + switch (fn2) { | ||
1420 | + case 0x0: | ||
1421 | + /* JMP */ | ||
1422 | + break; | ||
1423 | + case 0x1: | ||
1424 | + /* JSR */ | ||
1425 | + break; | ||
1426 | + case 0x2: | ||
1427 | + /* RET */ | ||
1428 | + break; | ||
1429 | + case 0x3: | ||
1430 | + /* JSR_COROUTINE */ | ||
1431 | + break; | ||
1432 | + } | ||
1433 | + ret = 1; | ||
1434 | + break; | ||
1435 | + case 0x1B: | ||
1436 | + /* HW_LD (PALcode) */ | ||
1437 | +#if defined (CONFIG_USER_ONLY) | ||
1438 | + goto invalid_opc; | ||
1439 | +#else | ||
1440 | + if (!ctx->pal_mode) | ||
1441 | + goto invalid_opc; | ||
1442 | + gen_load_ir(ctx, rb, 0); | ||
1443 | + gen_set_sT1(ctx, disp12); | ||
1444 | + gen_op_addq(); | ||
1445 | + switch ((insn >> 12) & 0xF) { | ||
1446 | + case 0x0: | ||
1447 | + /* Longword physical access */ | ||
1448 | + gen_op_ldl_raw(); | ||
1449 | + break; | ||
1450 | + case 0x1: | ||
1451 | + /* Quadword physical access */ | ||
1452 | + gen_op_ldq_raw(); | ||
1453 | + break; | ||
1454 | + case 0x2: | ||
1455 | + /* Longword physical access with lock */ | ||
1456 | + gen_op_ldl_l_raw(); | ||
1457 | + break; | ||
1458 | + case 0x3: | ||
1459 | + /* Quadword physical access with lock */ | ||
1460 | + gen_op_ldq_l_raw(); | ||
1461 | + break; | ||
1462 | + case 0x4: | ||
1463 | + /* Longword virtual PTE fetch */ | ||
1464 | + gen_op_ldl_kernel(); | ||
1465 | + break; | ||
1466 | + case 0x5: | ||
1467 | + /* Quadword virtual PTE fetch */ | ||
1468 | + gen_op_ldq_kernel(); | ||
1469 | + break; | ||
1470 | + case 0x6: | ||
1471 | + /* Invalid */ | ||
1472 | + goto invalid_opc; | ||
1473 | + case 0x7: | ||
1474 | + /* Invalid */ | ||
1475 | + goto invalid_opc; | ||
1476 | + case 0x8: | ||
1477 | + /* Longword virtual access */ | ||
1478 | + gen_op_ld_phys_to_virt(); | ||
1479 | + gen_op_ldl_raw(); | ||
1480 | + break; | ||
1481 | + case 0x9: | ||
1482 | + /* Quadword virtual access */ | ||
1483 | + gen_op_ld_phys_to_virt(); | ||
1484 | + gen_op_ldq_raw(); | ||
1485 | + break; | ||
1486 | + case 0xA: | ||
1487 | + /* Longword virtual access with protection check */ | ||
1488 | + gen_ldl(ctx); | ||
1489 | + break; | ||
1490 | + case 0xB: | ||
1491 | + /* Quadword virtual access with protection check */ | ||
1492 | + gen_ldq(ctx); | ||
1493 | + break; | ||
1494 | + case 0xC: | ||
1495 | + /* Longword virtual access with altenate access mode */ | ||
1496 | + gen_op_set_alt_mode(); | ||
1497 | + gen_op_ld_phys_to_virt(); | ||
1498 | + gen_op_ldl_raw(); | ||
1499 | + gen_op_restore_mode(); | ||
1500 | + break; | ||
1501 | + case 0xD: | ||
1502 | + /* Quadword virtual access with altenate access mode */ | ||
1503 | + gen_op_set_alt_mode(); | ||
1504 | + gen_op_ld_phys_to_virt(); | ||
1505 | + gen_op_ldq_raw(); | ||
1506 | + gen_op_restore_mode(); | ||
1507 | + break; | ||
1508 | + case 0xE: | ||
1509 | + /* Longword virtual access with alternate access mode and | ||
1510 | + * protection checks | ||
1511 | + */ | ||
1512 | + gen_op_set_alt_mode(); | ||
1513 | + gen_op_ldl_data(); | ||
1514 | + gen_op_restore_mode(); | ||
1515 | + break; | ||
1516 | + case 0xF: | ||
1517 | + /* Quadword virtual access with alternate access mode and | ||
1518 | + * protection checks | ||
1519 | + */ | ||
1520 | + gen_op_set_alt_mode(); | ||
1521 | + gen_op_ldq_data(); | ||
1522 | + gen_op_restore_mode(); | ||
1523 | + break; | ||
1524 | + } | ||
1525 | + gen_store_ir(ctx, ra, 1); | ||
1526 | + break; | ||
1527 | +#endif | ||
1528 | + case 0x1C: | ||
1529 | + switch (fn7) { | ||
1530 | + case 0x00: | ||
1531 | + /* SEXTB */ | ||
1532 | + if (!(ctx->amask & AMASK_BWX)) | ||
1533 | + goto invalid_opc; | ||
1534 | + gen_arith2(ctx, &gen_op_sextb, rb, rc, islit, lit); | ||
1535 | + break; | ||
1536 | + case 0x01: | ||
1537 | + /* SEXTW */ | ||
1538 | + if (!(ctx->amask & AMASK_BWX)) | ||
1539 | + goto invalid_opc; | ||
1540 | + gen_arith2(ctx, &gen_op_sextw, rb, rc, islit, lit); | ||
1541 | + break; | ||
1542 | + case 0x30: | ||
1543 | + /* CTPOP */ | ||
1544 | + if (!(ctx->amask & AMASK_CIX)) | ||
1545 | + goto invalid_opc; | ||
1546 | + gen_arith2(ctx, &gen_op_ctpop, rb, rc, 0, 0); | ||
1547 | + break; | ||
1548 | + case 0x31: | ||
1549 | + /* PERR */ | ||
1550 | + if (!(ctx->amask & AMASK_MVI)) | ||
1551 | + goto invalid_opc; | ||
1552 | + /* XXX: TODO */ | ||
1553 | + goto invalid_opc; | ||
1554 | + break; | ||
1555 | + case 0x32: | ||
1556 | + /* CTLZ */ | ||
1557 | + if (!(ctx->amask & AMASK_CIX)) | ||
1558 | + goto invalid_opc; | ||
1559 | + gen_arith2(ctx, &gen_op_ctlz, rb, rc, 0, 0); | ||
1560 | + break; | ||
1561 | + case 0x33: | ||
1562 | + /* CTTZ */ | ||
1563 | + if (!(ctx->amask & AMASK_CIX)) | ||
1564 | + goto invalid_opc; | ||
1565 | + gen_arith2(ctx, &gen_op_cttz, rb, rc, 0, 0); | ||
1566 | + break; | ||
1567 | + case 0x34: | ||
1568 | + /* UNPKBW */ | ||
1569 | + if (!(ctx->amask & AMASK_MVI)) | ||
1570 | + goto invalid_opc; | ||
1571 | + /* XXX: TODO */ | ||
1572 | + goto invalid_opc; | ||
1573 | + break; | ||
1574 | + case 0x35: | ||
1575 | + /* UNPKWL */ | ||
1576 | + if (!(ctx->amask & AMASK_MVI)) | ||
1577 | + goto invalid_opc; | ||
1578 | + /* XXX: TODO */ | ||
1579 | + goto invalid_opc; | ||
1580 | + break; | ||
1581 | + case 0x36: | ||
1582 | + /* PKWB */ | ||
1583 | + if (!(ctx->amask & AMASK_MVI)) | ||
1584 | + goto invalid_opc; | ||
1585 | + /* XXX: TODO */ | ||
1586 | + goto invalid_opc; | ||
1587 | + break; | ||
1588 | + case 0x37: | ||
1589 | + /* PKLB */ | ||
1590 | + if (!(ctx->amask & AMASK_MVI)) | ||
1591 | + goto invalid_opc; | ||
1592 | + /* XXX: TODO */ | ||
1593 | + goto invalid_opc; | ||
1594 | + break; | ||
1595 | + case 0x38: | ||
1596 | + /* MINSB8 */ | ||
1597 | + if (!(ctx->amask & AMASK_MVI)) | ||
1598 | + goto invalid_opc; | ||
1599 | + /* XXX: TODO */ | ||
1600 | + goto invalid_opc; | ||
1601 | + break; | ||
1602 | + case 0x39: | ||
1603 | + /* MINSW4 */ | ||
1604 | + if (!(ctx->amask & AMASK_MVI)) | ||
1605 | + goto invalid_opc; | ||
1606 | + /* XXX: TODO */ | ||
1607 | + goto invalid_opc; | ||
1608 | + break; | ||
1609 | + case 0x3A: | ||
1610 | + /* MINUB8 */ | ||
1611 | + if (!(ctx->amask & AMASK_MVI)) | ||
1612 | + goto invalid_opc; | ||
1613 | + /* XXX: TODO */ | ||
1614 | + goto invalid_opc; | ||
1615 | + break; | ||
1616 | + case 0x3B: | ||
1617 | + /* MINUW4 */ | ||
1618 | + if (!(ctx->amask & AMASK_MVI)) | ||
1619 | + goto invalid_opc; | ||
1620 | + /* XXX: TODO */ | ||
1621 | + goto invalid_opc; | ||
1622 | + break; | ||
1623 | + case 0x3C: | ||
1624 | + /* MAXUB8 */ | ||
1625 | + if (!(ctx->amask & AMASK_MVI)) | ||
1626 | + goto invalid_opc; | ||
1627 | + /* XXX: TODO */ | ||
1628 | + goto invalid_opc; | ||
1629 | + break; | ||
1630 | + case 0x3D: | ||
1631 | + /* MAXUW4 */ | ||
1632 | + if (!(ctx->amask & AMASK_MVI)) | ||
1633 | + goto invalid_opc; | ||
1634 | + /* XXX: TODO */ | ||
1635 | + goto invalid_opc; | ||
1636 | + break; | ||
1637 | + case 0x3E: | ||
1638 | + /* MAXSB8 */ | ||
1639 | + if (!(ctx->amask & AMASK_MVI)) | ||
1640 | + goto invalid_opc; | ||
1641 | + /* XXX: TODO */ | ||
1642 | + goto invalid_opc; | ||
1643 | + break; | ||
1644 | + case 0x3F: | ||
1645 | + /* MAXSW4 */ | ||
1646 | + if (!(ctx->amask & AMASK_MVI)) | ||
1647 | + goto invalid_opc; | ||
1648 | + /* XXX: TODO */ | ||
1649 | + goto invalid_opc; | ||
1650 | + break; | ||
1651 | + case 0x70: | ||
1652 | + /* FTOIT */ | ||
1653 | + if (!(ctx->amask & AMASK_FIX)) | ||
1654 | + goto invalid_opc; | ||
1655 | + gen_fti(ctx, &gen_op_ftoit, ra, rb); | ||
1656 | + break; | ||
1657 | + case 0x78: | ||
1658 | + /* FTOIS */ | ||
1659 | + if (!(ctx->amask & AMASK_FIX)) | ||
1660 | + goto invalid_opc; | ||
1661 | + gen_fti(ctx, &gen_op_ftois, ra, rb); | ||
1662 | + break; | ||
1663 | + default: | ||
1664 | + goto invalid_opc; | ||
1665 | + } | ||
1666 | + break; | ||
1667 | + case 0x1D: | ||
1668 | + /* HW_MTPR (PALcode) */ | ||
1669 | +#if defined (CONFIG_USER_ONLY) | ||
1670 | + goto invalid_opc; | ||
1671 | +#else | ||
1672 | + if (!ctx->pal_mode) | ||
1673 | + goto invalid_opc; | ||
1674 | + gen_load_ir(ctx, ra, 0); | ||
1675 | + gen_op_mtpr(insn & 0xFF); | ||
1676 | + ret = 2; | ||
1677 | + break; | ||
1678 | +#endif | ||
1679 | + case 0x1E: | ||
1680 | + /* HW_REI (PALcode) */ | ||
1681 | +#if defined (CONFIG_USER_ONLY) | ||
1682 | + goto invalid_opc; | ||
1683 | +#else | ||
1684 | + if (!ctx->pal_mode) | ||
1685 | + goto invalid_opc; | ||
1686 | + if (rb == 31) { | ||
1687 | + /* "Old" alpha */ | ||
1688 | + gen_op_hw_rei(); | ||
1689 | + } else { | ||
1690 | + gen_load_ir(ctx, rb, 0); | ||
1691 | + gen_set_uT1(ctx, (((int64_t)insn << 51) >> 51)); | ||
1692 | + gen_op_addq(); | ||
1693 | + gen_op_hw_ret(); | ||
1694 | + } | ||
1695 | + ret = 2; | ||
1696 | + break; | ||
1697 | +#endif | ||
1698 | + case 0x1F: | ||
1699 | + /* HW_ST (PALcode) */ | ||
1700 | +#if defined (CONFIG_USER_ONLY) | ||
1701 | + goto invalid_opc; | ||
1702 | +#else | ||
1703 | + if (!ctx->pal_mode) | ||
1704 | + goto invalid_opc; | ||
1705 | + gen_load_ir(ctx, rb, 0); | ||
1706 | + gen_set_sT1(ctx, disp12); | ||
1707 | + gen_op_addq(); | ||
1708 | + gen_load_ir(ctx, ra, 1); | ||
1709 | + switch ((insn >> 12) & 0xF) { | ||
1710 | + case 0x0: | ||
1711 | + /* Longword physical access */ | ||
1712 | + gen_op_stl_raw(); | ||
1713 | + break; | ||
1714 | + case 0x1: | ||
1715 | + /* Quadword physical access */ | ||
1716 | + gen_op_stq_raw(); | ||
1717 | + break; | ||
1718 | + case 0x2: | ||
1719 | + /* Longword physical access with lock */ | ||
1720 | + gen_op_stl_c_raw(); | ||
1721 | + break; | ||
1722 | + case 0x3: | ||
1723 | + /* Quadword physical access with lock */ | ||
1724 | + gen_op_stq_c_raw(); | ||
1725 | + break; | ||
1726 | + case 0x4: | ||
1727 | + /* Longword virtual access */ | ||
1728 | + gen_op_st_phys_to_virt(); | ||
1729 | + gen_op_stl_raw(); | ||
1730 | + break; | ||
1731 | + case 0x5: | ||
1732 | + /* Quadword virtual access */ | ||
1733 | + gen_op_st_phys_to_virt(); | ||
1734 | + gen_op_stq_raw(); | ||
1735 | + break; | ||
1736 | + case 0x6: | ||
1737 | + /* Invalid */ | ||
1738 | + goto invalid_opc; | ||
1739 | + case 0x7: | ||
1740 | + /* Invalid */ | ||
1741 | + goto invalid_opc; | ||
1742 | + case 0x8: | ||
1743 | + /* Invalid */ | ||
1744 | + goto invalid_opc; | ||
1745 | + case 0x9: | ||
1746 | + /* Invalid */ | ||
1747 | + goto invalid_opc; | ||
1748 | + case 0xA: | ||
1749 | + /* Invalid */ | ||
1750 | + goto invalid_opc; | ||
1751 | + case 0xB: | ||
1752 | + /* Invalid */ | ||
1753 | + goto invalid_opc; | ||
1754 | + case 0xC: | ||
1755 | + /* Longword virtual access with alternate access mode */ | ||
1756 | + gen_op_set_alt_mode(); | ||
1757 | + gen_op_st_phys_to_virt(); | ||
1758 | + gen_op_ldl_raw(); | ||
1759 | + gen_op_restore_mode(); | ||
1760 | + break; | ||
1761 | + case 0xD: | ||
1762 | + /* Quadword virtual access with alternate access mode */ | ||
1763 | + gen_op_set_alt_mode(); | ||
1764 | + gen_op_st_phys_to_virt(); | ||
1765 | + gen_op_ldq_raw(); | ||
1766 | + gen_op_restore_mode(); | ||
1767 | + break; | ||
1768 | + case 0xE: | ||
1769 | + /* Invalid */ | ||
1770 | + goto invalid_opc; | ||
1771 | + case 0xF: | ||
1772 | + /* Invalid */ | ||
1773 | + goto invalid_opc; | ||
1774 | + } | ||
1775 | + ret = 2; | ||
1776 | + break; | ||
1777 | +#endif | ||
1778 | + case 0x20: | ||
1779 | + /* LDF */ | ||
1780 | +#if 0 // TODO | ||
1781 | + gen_load_fmem(ctx, &gen_ldf, ra, rb, disp16); | ||
1782 | +#else | ||
1783 | + goto invalid_opc; | ||
1784 | +#endif | ||
1785 | + break; | ||
1786 | + case 0x21: | ||
1787 | + /* LDG */ | ||
1788 | +#if 0 // TODO | ||
1789 | + gen_load_fmem(ctx, &gen_ldg, ra, rb, disp16); | ||
1790 | +#else | ||
1791 | + goto invalid_opc; | ||
1792 | +#endif | ||
1793 | + break; | ||
1794 | + case 0x22: | ||
1795 | + /* LDS */ | ||
1796 | + gen_load_fmem(ctx, &gen_lds, ra, rb, disp16); | ||
1797 | + break; | ||
1798 | + case 0x23: | ||
1799 | + /* LDT */ | ||
1800 | + gen_load_fmem(ctx, &gen_ldt, ra, rb, disp16); | ||
1801 | + break; | ||
1802 | + case 0x24: | ||
1803 | + /* STF */ | ||
1804 | +#if 0 // TODO | ||
1805 | + gen_store_fmem(ctx, &gen_stf, ra, rb, disp16); | ||
1806 | +#else | ||
1807 | + goto invalid_opc; | ||
1808 | +#endif | ||
1809 | + break; | ||
1810 | + case 0x25: | ||
1811 | + /* STG */ | ||
1812 | +#if 0 // TODO | ||
1813 | + gen_store_fmem(ctx, &gen_stg, ra, rb, disp16); | ||
1814 | +#else | ||
1815 | + goto invalid_opc; | ||
1816 | +#endif | ||
1817 | + break; | ||
1818 | + case 0x26: | ||
1819 | + /* STS */ | ||
1820 | + gen_store_fmem(ctx, &gen_sts, ra, rb, disp16); | ||
1821 | + break; | ||
1822 | + case 0x27: | ||
1823 | + /* STT */ | ||
1824 | + gen_store_fmem(ctx, &gen_stt, ra, rb, disp16); | ||
1825 | + break; | ||
1826 | + case 0x28: | ||
1827 | + /* LDL */ | ||
1828 | + gen_load_mem(ctx, &gen_ldl, ra, rb, disp16, 0); | ||
1829 | + break; | ||
1830 | + case 0x29: | ||
1831 | + /* LDQ */ | ||
1832 | + gen_load_mem(ctx, &gen_ldq, ra, rb, disp16, 0); | ||
1833 | + break; | ||
1834 | + case 0x2A: | ||
1835 | + /* LDL_L */ | ||
1836 | + gen_load_mem(ctx, &gen_ldl_l, ra, rb, disp16, 0); | ||
1837 | + break; | ||
1838 | + case 0x2B: | ||
1839 | + /* LDQ_L */ | ||
1840 | + gen_load_mem(ctx, &gen_ldq_l, ra, rb, disp16, 0); | ||
1841 | + break; | ||
1842 | + case 0x2C: | ||
1843 | + /* STL */ | ||
1844 | + gen_store_mem(ctx, &gen_stl, ra, rb, disp16, 0); | ||
1845 | + break; | ||
1846 | + case 0x2D: | ||
1847 | + /* STQ */ | ||
1848 | + gen_store_mem(ctx, &gen_stq, ra, rb, disp16, 0); | ||
1849 | + break; | ||
1850 | + case 0x2E: | ||
1851 | + /* STL_C */ | ||
1852 | + gen_store_mem(ctx, &gen_stl_c, ra, rb, disp16, 0); | ||
1853 | + break; | ||
1854 | + case 0x2F: | ||
1855 | + /* STQ_C */ | ||
1856 | + gen_store_mem(ctx, &gen_stq_c, ra, rb, disp16, 0); | ||
1857 | + break; | ||
1858 | + case 0x30: | ||
1859 | + /* BR */ | ||
1860 | + gen_set_uT0(ctx, ctx->pc); | ||
1861 | + gen_store_ir(ctx, ra, 0); | ||
1862 | + if (disp21 != 0) { | ||
1863 | + gen_set_sT1(ctx, disp21 << 2); | ||
1864 | + gen_op_addq(); | ||
1865 | + } | ||
1866 | + gen_op_branch(); | ||
1867 | + ret = 1; | ||
1868 | + break; | ||
1869 | + case 0x31: | ||
1870 | + /* FBEQ */ | ||
1871 | + gen_fbcond(ctx, &gen_op_cmpfeq, ra, disp16); | ||
1872 | + ret = 1; | ||
1873 | + break; | ||
1874 | + case 0x32: | ||
1875 | + /* FBLT */ | ||
1876 | + gen_fbcond(ctx, &gen_op_cmpflt, ra, disp16); | ||
1877 | + ret = 1; | ||
1878 | + break; | ||
1879 | + case 0x33: | ||
1880 | + /* FBLE */ | ||
1881 | + gen_fbcond(ctx, &gen_op_cmpfle, ra, disp16); | ||
1882 | + ret = 1; | ||
1883 | + break; | ||
1884 | + case 0x34: | ||
1885 | + /* BSR */ | ||
1886 | + gen_set_uT0(ctx, ctx->pc); | ||
1887 | + gen_store_ir(ctx, ra, 0); | ||
1888 | + if (disp21 != 0) { | ||
1889 | + gen_set_sT1(ctx, disp21 << 2); | ||
1890 | + gen_op_addq(); | ||
1891 | + } | ||
1892 | + gen_op_branch(); | ||
1893 | + ret = 1; | ||
1894 | + break; | ||
1895 | + case 0x35: | ||
1896 | + /* FBNE */ | ||
1897 | + gen_fbcond(ctx, &gen_op_cmpfne, ra, disp16); | ||
1898 | + ret = 1; | ||
1899 | + break; | ||
1900 | + case 0x36: | ||
1901 | + /* FBGE */ | ||
1902 | + gen_fbcond(ctx, &gen_op_cmpfge, ra, disp16); | ||
1903 | + ret = 1; | ||
1904 | + break; | ||
1905 | + case 0x37: | ||
1906 | + /* FBGT */ | ||
1907 | + gen_fbcond(ctx, &gen_op_cmpfgt, ra, disp16); | ||
1908 | + ret = 1; | ||
1909 | + break; | ||
1910 | + case 0x38: | ||
1911 | + /* BLBC */ | ||
1912 | + gen_bcond(ctx, &gen_op_cmplbc, ra, disp16); | ||
1913 | + ret = 1; | ||
1914 | + break; | ||
1915 | + case 0x39: | ||
1916 | + /* BEQ */ | ||
1917 | + gen_bcond(ctx, &gen_op_cmpeqz, ra, disp16); | ||
1918 | + ret = 1; | ||
1919 | + break; | ||
1920 | + case 0x3A: | ||
1921 | + /* BLT */ | ||
1922 | + gen_bcond(ctx, &gen_op_cmpltz, ra, disp16); | ||
1923 | + ret = 1; | ||
1924 | + break; | ||
1925 | + case 0x3B: | ||
1926 | + /* BLE */ | ||
1927 | + gen_bcond(ctx, &gen_op_cmplez, ra, disp16); | ||
1928 | + ret = 1; | ||
1929 | + break; | ||
1930 | + case 0x3C: | ||
1931 | + /* BLBS */ | ||
1932 | + gen_bcond(ctx, &gen_op_cmplbs, ra, disp16); | ||
1933 | + ret = 1; | ||
1934 | + break; | ||
1935 | + case 0x3D: | ||
1936 | + /* BNE */ | ||
1937 | + gen_bcond(ctx, &gen_op_cmpnez, ra, disp16); | ||
1938 | + ret = 1; | ||
1939 | + break; | ||
1940 | + case 0x3E: | ||
1941 | + /* BGE */ | ||
1942 | + gen_bcond(ctx, &gen_op_cmpgez, ra, disp16); | ||
1943 | + ret = 1; | ||
1944 | + break; | ||
1945 | + case 0x3F: | ||
1946 | + /* BGT */ | ||
1947 | + gen_bcond(ctx, &gen_op_cmpgtz, ra, disp16); | ||
1948 | + ret = 1; | ||
1949 | + break; | ||
1950 | + invalid_opc: | ||
1951 | + gen_invalid(ctx); | ||
1952 | + ret = 3; | ||
1953 | + break; | ||
1954 | + } | ||
1955 | + | ||
1956 | + return ret; | ||
1957 | +} | ||
1958 | + | ||
1959 | +int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, | ||
1960 | + int search_pc) | ||
1961 | +{ | ||
1962 | +#if defined ALPHA_DEBUG_DISAS | ||
1963 | + static int insn_count; | ||
1964 | +#endif | ||
1965 | + DisasContext ctx, *ctxp = &ctx; | ||
1966 | + target_ulong pc_start; | ||
1967 | + uint32_t insn; | ||
1968 | + uint16_t *gen_opc_end; | ||
1969 | + int j, lj = -1; | ||
1970 | + int ret; | ||
1971 | + | ||
1972 | + pc_start = tb->pc; | ||
1973 | + gen_opc_ptr = gen_opc_buf; | ||
1974 | + gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; | ||
1975 | + gen_opparam_ptr = gen_opparam_buf; | ||
1976 | + nb_gen_labels = 0; | ||
1977 | + ctx.pc = pc_start; | ||
1978 | + ctx.amask = env->amask; | ||
1979 | +#if defined (CONFIG_USER_ONLY) | ||
1980 | + ctx.mem_idx = 0; | ||
1981 | +#else | ||
1982 | + ctx.mem_idx = ((env->ps >> 3) & 3); | ||
1983 | + ctx.pal_mode = env->ipr[IPR_EXC_ADDR] & 1; | ||
1984 | +#endif | ||
1985 | + for (ret = 0; ret == 0;) { | ||
1986 | + if (env->nb_breakpoints > 0) { | ||
1987 | + for(j = 0; j < env->nb_breakpoints; j++) { | ||
1988 | + if (env->breakpoints[j] == ctx.pc) { | ||
1989 | + gen_excp(&ctx, EXCP_DEBUG, 0); | ||
1990 | + break; | ||
1991 | + } | ||
1992 | + } | ||
1993 | + } | ||
1994 | + if (search_pc) { | ||
1995 | + j = gen_opc_ptr - gen_opc_buf; | ||
1996 | + if (lj < j) { | ||
1997 | + lj++; | ||
1998 | + while (lj < j) | ||
1999 | + gen_opc_instr_start[lj++] = 0; | ||
2000 | + gen_opc_pc[lj] = ctx.pc; | ||
2001 | + gen_opc_instr_start[lj] = 1; | ||
2002 | + } | ||
2003 | + } | ||
2004 | +#if defined ALPHA_DEBUG_DISAS | ||
2005 | + insn_count++; | ||
2006 | + if (logfile != NULL) { | ||
2007 | + fprintf(logfile, "pc %016lx mem_idx\n", ctx.pc, ctx.mem_idx); | ||
2008 | + } | ||
2009 | +#endif | ||
2010 | + insn = ldl_code(ctx.pc); | ||
2011 | +#if defined ALPHA_DEBUG_DISAS | ||
2012 | + insn_count++; | ||
2013 | + if (logfile != NULL) { | ||
2014 | + fprintf(logfile, "opcode %08x %d\n", insn, insn_count); | ||
2015 | + } | ||
2016 | +#endif | ||
2017 | + ctx.pc += 4; | ||
2018 | + ret = translate_one(ctxp, insn); | ||
2019 | + if (ret != 0) | ||
2020 | + break; | ||
2021 | + /* if we reach a page boundary or are single stepping, stop | ||
2022 | + * generation | ||
2023 | + */ | ||
2024 | + if (((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) || | ||
2025 | + (env->singlestep_enabled)) { | ||
2026 | + break; | ||
2027 | + } | ||
2028 | +#if defined (DO_SINGLE_STEP) | ||
2029 | + break; | ||
2030 | +#endif | ||
2031 | + } | ||
2032 | + if (ret != 1 && ret != 3) { | ||
2033 | + gen_update_pc(&ctx); | ||
2034 | + } | ||
2035 | + gen_op_reset_T0(); | ||
2036 | +#if defined (DO_TB_FLUSH) | ||
2037 | + gen_op_tb_flush(); | ||
2038 | +#endif | ||
2039 | + /* Generate the return instruction */ | ||
2040 | + gen_op_exit_tb(); | ||
2041 | + *gen_opc_ptr = INDEX_op_end; | ||
2042 | + if (search_pc) { | ||
2043 | + j = gen_opc_ptr - gen_opc_buf; | ||
2044 | + lj++; | ||
2045 | + while (lj <= j) | ||
2046 | + gen_opc_instr_start[lj++] = 0; | ||
2047 | + tb->size = 0; | ||
2048 | + } else { | ||
2049 | + tb->size = ctx.pc - pc_start; | ||
2050 | + } | ||
2051 | +#if defined ALPHA_DEBUG_DISAS | ||
2052 | + if (loglevel & CPU_LOG_TB_CPU) { | ||
2053 | + cpu_dump_state(env, logfile, fprintf, 0); | ||
2054 | + } | ||
2055 | + if (loglevel & CPU_LOG_TB_IN_ASM) { | ||
2056 | + fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); | ||
2057 | + target_disas(logfile, pc_start, ctx.pc - pc_start, 1); | ||
2058 | + fprintf(logfile, "\n"); | ||
2059 | + } | ||
2060 | + if (loglevel & CPU_LOG_TB_OP) { | ||
2061 | + fprintf(logfile, "OP:\n"); | ||
2062 | + dump_ops(gen_opc_buf, gen_opparam_buf); | ||
2063 | + fprintf(logfile, "\n"); | ||
2064 | + } | ||
2065 | +#endif | ||
2066 | + | ||
2067 | + return 0; | ||
2068 | +} | ||
2069 | + | ||
2070 | +int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb) | ||
2071 | +{ | ||
2072 | + return gen_intermediate_code_internal(env, tb, 0); | ||
2073 | +} | ||
2074 | + | ||
2075 | +int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) | ||
2076 | +{ | ||
2077 | + return gen_intermediate_code_internal(env, tb, 1); | ||
2078 | +} | ||
2079 | + | ||
2080 | +CPUAlphaState * cpu_alpha_init (void) | ||
2081 | +{ | ||
2082 | + CPUAlphaState *env; | ||
2083 | + uint64_t hwpcb; | ||
2084 | + | ||
2085 | + env = qemu_mallocz(sizeof(CPUAlphaState)); | ||
2086 | + if (!env) | ||
2087 | + return NULL; | ||
2088 | + cpu_exec_init(env); | ||
2089 | + tlb_flush(env, 1); | ||
2090 | + /* XXX: should not be hardcoded */ | ||
2091 | + env->implver = IMPLVER_2106x; | ||
2092 | + env->ps = 0x1F00; | ||
2093 | +#if defined (CONFIG_USER_ONLY) | ||
2094 | + env->ps |= 1 << 3; | ||
2095 | +#endif | ||
2096 | + pal_init(env); | ||
2097 | + /* Initialize IPR */ | ||
2098 | + hwpcb = env->ipr[IPR_PCBB]; | ||
2099 | + env->ipr[IPR_ASN] = 0; | ||
2100 | + env->ipr[IPR_ASTEN] = 0; | ||
2101 | + env->ipr[IPR_ASTSR] = 0; | ||
2102 | + env->ipr[IPR_DATFX] = 0; | ||
2103 | + /* XXX: fix this */ | ||
2104 | + // env->ipr[IPR_ESP] = ldq_raw(hwpcb + 8); | ||
2105 | + // env->ipr[IPR_KSP] = ldq_raw(hwpcb + 0); | ||
2106 | + // env->ipr[IPR_SSP] = ldq_raw(hwpcb + 16); | ||
2107 | + // env->ipr[IPR_USP] = ldq_raw(hwpcb + 24); | ||
2108 | + env->ipr[IPR_FEN] = 0; | ||
2109 | + env->ipr[IPR_IPL] = 31; | ||
2110 | + env->ipr[IPR_MCES] = 0; | ||
2111 | + env->ipr[IPR_PERFMON] = 0; /* Implementation specific */ | ||
2112 | + // env->ipr[IPR_PTBR] = ldq_raw(hwpcb + 32); | ||
2113 | + env->ipr[IPR_SISR] = 0; | ||
2114 | + env->ipr[IPR_VIRBND] = -1ULL; | ||
2115 | + | ||
2116 | + return env; | ||
2117 | +} |