blob: a961159d5d8004ae2698b6dce2b473e589b183b5 [file] [log] [blame]
j_mayer4c9649a2007-04-05 06:58:33 +00001/*
2 * Alpha emulation cpu translation for qemu.
ths5fafdf22007-09-16 21:08:06 +00003 *
j_mayer4c9649a2007-04-05 06:58:33 +00004 * 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
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
j_mayer4c9649a2007-04-05 06:58:33 +000018 */
19
20#include <stdint.h>
21#include <stdlib.h>
22#include <stdio.h>
23
24#include "cpu.h"
j_mayer4c9649a2007-04-05 06:58:33 +000025#include "disas.h"
aurel32ae8ecd42008-09-16 22:44:02 +000026#include "host-utils.h"
bellard57fec1f2008-02-01 10:50:11 +000027#include "tcg-op.h"
aurel32ca10f862008-04-11 21:35:42 +000028#include "qemu-common.h"
j_mayer4c9649a2007-04-05 06:58:33 +000029
pbrooka7812ae2008-11-17 14:43:54 +000030#include "helper.h"
31#define GEN_HELPER 1
32#include "helper.h"
33
Richard Henderson19188122009-12-09 15:44:08 -080034#undef ALPHA_DEBUG_DISAS
Richard Hendersonf24518b2010-01-04 14:27:23 -080035#define CONFIG_SOFTFLOAT_INLINE
aliguorid12d51d2009-01-15 21:48:06 +000036
37#ifdef ALPHA_DEBUG_DISAS
Richard Henderson806991d2009-12-10 12:54:04 -080038# define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
aliguorid12d51d2009-01-15 21:48:06 +000039#else
40# define LOG_DISAS(...) do { } while (0)
41#endif
42
j_mayer4c9649a2007-04-05 06:58:33 +000043typedef struct DisasContext DisasContext;
44struct DisasContext {
Richard Henderson4af70372010-03-16 15:10:49 -070045 struct TranslationBlock *tb;
46 CPUAlphaState *env;
j_mayer4c9649a2007-04-05 06:58:33 +000047 uint64_t pc;
48 int mem_idx;
Richard Hendersonf24518b2010-01-04 14:27:23 -080049
50 /* Current rounding mode for this TB. */
51 int tb_rm;
52 /* Current flush-to-zero setting for this TB. */
53 int tb_ftz;
j_mayer4c9649a2007-04-05 06:58:33 +000054};
55
Richard Henderson4af70372010-03-16 15:10:49 -070056/* Return values from translate_one, indicating the state of the TB.
57 Note that zero indicates that we are not exiting the TB. */
58
59typedef enum {
60 NO_EXIT,
61
62 /* We have emitted one or more goto_tb. No fixup required. */
63 EXIT_GOTO_TB,
64
65 /* We are not using a goto_tb (for whatever reason), but have updated
66 the PC (for whatever reason), so there's no need to do it again on
67 exiting the TB. */
68 EXIT_PC_UPDATED,
69
70 /* We are exiting the TB, but have neither emitted a goto_tb, nor
71 updated the PC for the next instruction to be executed. */
Richard Henderson8aa3fa22010-04-07 13:32:50 -070072 EXIT_PC_STALE,
73
74 /* We are ending the TB with a noreturn function call, e.g. longjmp.
75 No following code will be executed. */
76 EXIT_NORETURN,
Richard Henderson4af70372010-03-16 15:10:49 -070077} ExitStatus;
78
aurel3237610352008-09-04 04:36:00 +000079/* global register indexes */
pbrooka7812ae2008-11-17 14:43:54 +000080static TCGv_ptr cpu_env;
aurel32496cb5b2008-09-04 04:35:40 +000081static TCGv cpu_ir[31];
aurel32f18cd222008-09-29 17:21:28 +000082static TCGv cpu_fir[31];
aurel32496cb5b2008-09-04 04:35:40 +000083static TCGv cpu_pc;
Richard Henderson6910b8f2010-04-07 15:42:26 -070084static TCGv cpu_lock_addr;
85static TCGv cpu_lock_st_addr;
86static TCGv cpu_lock_value;
Richard Henderson2ace7e52011-05-23 13:09:00 -070087static TCGv cpu_unique;
88#ifndef CONFIG_USER_ONLY
89static TCGv cpu_sysval;
90static TCGv cpu_usp;
Richard Hendersonab471ad2009-12-11 09:38:23 -080091#endif
aurel32496cb5b2008-09-04 04:35:40 +000092
aurel3237610352008-09-04 04:36:00 +000093/* register names */
aurel32f18cd222008-09-29 17:21:28 +000094static char cpu_reg_names[10*4+21*5 + 10*5+21*6];
pbrook2e70f6e2008-06-29 01:03:05 +000095
96#include "gen-icount.h"
97
blueswir1a5f1b962008-08-17 20:21:51 +000098static void alpha_translate_init(void)
pbrook2e70f6e2008-06-29 01:03:05 +000099{
aurel32496cb5b2008-09-04 04:35:40 +0000100 int i;
101 char *p;
pbrook2e70f6e2008-06-29 01:03:05 +0000102 static int done_init = 0;
aurel32496cb5b2008-09-04 04:35:40 +0000103
pbrook2e70f6e2008-06-29 01:03:05 +0000104 if (done_init)
105 return;
aurel32496cb5b2008-09-04 04:35:40 +0000106
pbrooka7812ae2008-11-17 14:43:54 +0000107 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
aurel32496cb5b2008-09-04 04:35:40 +0000108
109 p = cpu_reg_names;
110 for (i = 0; i < 31; i++) {
111 sprintf(p, "ir%d", i);
pbrooka7812ae2008-11-17 14:43:54 +0000112 cpu_ir[i] = tcg_global_mem_new_i64(TCG_AREG0,
113 offsetof(CPUState, ir[i]), p);
aurel326ba8dcd2008-09-16 22:44:17 +0000114 p += (i < 10) ? 4 : 5;
aurel32f18cd222008-09-29 17:21:28 +0000115
116 sprintf(p, "fir%d", i);
pbrooka7812ae2008-11-17 14:43:54 +0000117 cpu_fir[i] = tcg_global_mem_new_i64(TCG_AREG0,
118 offsetof(CPUState, fir[i]), p);
aurel32f18cd222008-09-29 17:21:28 +0000119 p += (i < 10) ? 5 : 6;
aurel32496cb5b2008-09-04 04:35:40 +0000120 }
121
pbrooka7812ae2008-11-17 14:43:54 +0000122 cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
123 offsetof(CPUState, pc), "pc");
aurel32496cb5b2008-09-04 04:35:40 +0000124
Richard Henderson6910b8f2010-04-07 15:42:26 -0700125 cpu_lock_addr = tcg_global_mem_new_i64(TCG_AREG0,
126 offsetof(CPUState, lock_addr),
127 "lock_addr");
128 cpu_lock_st_addr = tcg_global_mem_new_i64(TCG_AREG0,
129 offsetof(CPUState, lock_st_addr),
130 "lock_st_addr");
131 cpu_lock_value = tcg_global_mem_new_i64(TCG_AREG0,
132 offsetof(CPUState, lock_value),
133 "lock_value");
aurel32f4ed8672008-09-30 06:45:34 +0000134
Richard Henderson2ace7e52011-05-23 13:09:00 -0700135 cpu_unique = tcg_global_mem_new_i64(TCG_AREG0,
136 offsetof(CPUState, unique), "unique");
137#ifndef CONFIG_USER_ONLY
138 cpu_sysval = tcg_global_mem_new_i64(TCG_AREG0,
139 offsetof(CPUState, sysval), "sysval");
140 cpu_usp = tcg_global_mem_new_i64(TCG_AREG0,
141 offsetof(CPUState, usp), "usp");
Richard Hendersonab471ad2009-12-11 09:38:23 -0800142#endif
143
aurel32496cb5b2008-09-04 04:35:40 +0000144 /* register helpers */
pbrooka7812ae2008-11-17 14:43:54 +0000145#define GEN_HELPER 2
aurel32496cb5b2008-09-04 04:35:40 +0000146#include "helper.h"
147
pbrook2e70f6e2008-06-29 01:03:05 +0000148 done_init = 1;
149}
150
Richard Hendersonbf1b03f2011-04-25 12:52:57 -0700151static void gen_excp_1(int exception, int error_code)
j_mayer4c9649a2007-04-05 06:58:33 +0000152{
pbrooka7812ae2008-11-17 14:43:54 +0000153 TCGv_i32 tmp1, tmp2;
aurel326ad02592008-09-18 00:02:17 +0000154
aurel326ad02592008-09-18 00:02:17 +0000155 tmp1 = tcg_const_i32(exception);
156 tmp2 = tcg_const_i32(error_code);
pbrooka7812ae2008-11-17 14:43:54 +0000157 gen_helper_excp(tmp1, tmp2);
158 tcg_temp_free_i32(tmp2);
159 tcg_temp_free_i32(tmp1);
Richard Hendersonbf1b03f2011-04-25 12:52:57 -0700160}
Richard Henderson8aa3fa22010-04-07 13:32:50 -0700161
Richard Hendersonbf1b03f2011-04-25 12:52:57 -0700162static ExitStatus gen_excp(DisasContext *ctx, int exception, int error_code)
163{
164 tcg_gen_movi_i64(cpu_pc, ctx->pc);
165 gen_excp_1(exception, error_code);
Richard Henderson8aa3fa22010-04-07 13:32:50 -0700166 return EXIT_NORETURN;
j_mayer4c9649a2007-04-05 06:58:33 +0000167}
168
Richard Henderson8aa3fa22010-04-07 13:32:50 -0700169static inline ExitStatus gen_invalid(DisasContext *ctx)
j_mayer4c9649a2007-04-05 06:58:33 +0000170{
Richard Henderson8aa3fa22010-04-07 13:32:50 -0700171 return gen_excp(ctx, EXCP_OPCDEC, 0);
j_mayer4c9649a2007-04-05 06:58:33 +0000172}
173
Blue Swirl636aa202009-08-16 09:06:54 +0000174static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
aurel32f18cd222008-09-29 17:21:28 +0000175{
pbrooka7812ae2008-11-17 14:43:54 +0000176 TCGv tmp = tcg_temp_new();
177 TCGv_i32 tmp32 = tcg_temp_new_i32();
aurel32f18cd222008-09-29 17:21:28 +0000178 tcg_gen_qemu_ld32u(tmp, t1, flags);
pbrooka7812ae2008-11-17 14:43:54 +0000179 tcg_gen_trunc_i64_i32(tmp32, tmp);
180 gen_helper_memory_to_f(t0, tmp32);
181 tcg_temp_free_i32(tmp32);
aurel32f18cd222008-09-29 17:21:28 +0000182 tcg_temp_free(tmp);
183}
184
Blue Swirl636aa202009-08-16 09:06:54 +0000185static inline void gen_qemu_ldg(TCGv t0, TCGv t1, int flags)
aurel32f18cd222008-09-29 17:21:28 +0000186{
pbrooka7812ae2008-11-17 14:43:54 +0000187 TCGv tmp = tcg_temp_new();
aurel32f18cd222008-09-29 17:21:28 +0000188 tcg_gen_qemu_ld64(tmp, t1, flags);
pbrooka7812ae2008-11-17 14:43:54 +0000189 gen_helper_memory_to_g(t0, tmp);
aurel32f18cd222008-09-29 17:21:28 +0000190 tcg_temp_free(tmp);
191}
192
Blue Swirl636aa202009-08-16 09:06:54 +0000193static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
aurel32f18cd222008-09-29 17:21:28 +0000194{
pbrooka7812ae2008-11-17 14:43:54 +0000195 TCGv tmp = tcg_temp_new();
196 TCGv_i32 tmp32 = tcg_temp_new_i32();
aurel32f18cd222008-09-29 17:21:28 +0000197 tcg_gen_qemu_ld32u(tmp, t1, flags);
pbrooka7812ae2008-11-17 14:43:54 +0000198 tcg_gen_trunc_i64_i32(tmp32, tmp);
199 gen_helper_memory_to_s(t0, tmp32);
200 tcg_temp_free_i32(tmp32);
aurel32f18cd222008-09-29 17:21:28 +0000201 tcg_temp_free(tmp);
202}
203
Blue Swirl636aa202009-08-16 09:06:54 +0000204static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
aurel32f4ed8672008-09-30 06:45:34 +0000205{
aurel32f4ed8672008-09-30 06:45:34 +0000206 tcg_gen_qemu_ld32s(t0, t1, flags);
Richard Henderson6910b8f2010-04-07 15:42:26 -0700207 tcg_gen_mov_i64(cpu_lock_addr, t1);
208 tcg_gen_mov_i64(cpu_lock_value, t0);
aurel32f4ed8672008-09-30 06:45:34 +0000209}
210
Blue Swirl636aa202009-08-16 09:06:54 +0000211static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
aurel32f4ed8672008-09-30 06:45:34 +0000212{
aurel32f4ed8672008-09-30 06:45:34 +0000213 tcg_gen_qemu_ld64(t0, t1, flags);
Richard Henderson6910b8f2010-04-07 15:42:26 -0700214 tcg_gen_mov_i64(cpu_lock_addr, t1);
215 tcg_gen_mov_i64(cpu_lock_value, t0);
aurel32f4ed8672008-09-30 06:45:34 +0000216}
217
Blue Swirl636aa202009-08-16 09:06:54 +0000218static inline void gen_load_mem(DisasContext *ctx,
219 void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1,
220 int flags),
221 int ra, int rb, int32_t disp16, int fp,
222 int clear)
aurel32023d8ca2008-09-29 17:21:17 +0000223{
Richard Henderson6910b8f2010-04-07 15:42:26 -0700224 TCGv addr, va;
aurel32023d8ca2008-09-29 17:21:17 +0000225
Richard Henderson6910b8f2010-04-07 15:42:26 -0700226 /* LDQ_U with ra $31 is UNOP. Other various loads are forms of
227 prefetches, which we can treat as nops. No worries about
228 missed exceptions here. */
229 if (unlikely(ra == 31)) {
aurel32023d8ca2008-09-29 17:21:17 +0000230 return;
Richard Henderson6910b8f2010-04-07 15:42:26 -0700231 }
aurel32023d8ca2008-09-29 17:21:17 +0000232
pbrooka7812ae2008-11-17 14:43:54 +0000233 addr = tcg_temp_new();
aurel32023d8ca2008-09-29 17:21:17 +0000234 if (rb != 31) {
235 tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
Richard Henderson6910b8f2010-04-07 15:42:26 -0700236 if (clear) {
aurel32023d8ca2008-09-29 17:21:17 +0000237 tcg_gen_andi_i64(addr, addr, ~0x7);
Richard Henderson6910b8f2010-04-07 15:42:26 -0700238 }
aurel32023d8ca2008-09-29 17:21:17 +0000239 } else {
Richard Henderson6910b8f2010-04-07 15:42:26 -0700240 if (clear) {
aurel32023d8ca2008-09-29 17:21:17 +0000241 disp16 &= ~0x7;
Richard Henderson6910b8f2010-04-07 15:42:26 -0700242 }
aurel32023d8ca2008-09-29 17:21:17 +0000243 tcg_gen_movi_i64(addr, disp16);
244 }
Richard Henderson6910b8f2010-04-07 15:42:26 -0700245
246 va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
247 tcg_gen_qemu_load(va, addr, ctx->mem_idx);
248
aurel32023d8ca2008-09-29 17:21:17 +0000249 tcg_temp_free(addr);
250}
251
Blue Swirl636aa202009-08-16 09:06:54 +0000252static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
aurel32f18cd222008-09-29 17:21:28 +0000253{
pbrooka7812ae2008-11-17 14:43:54 +0000254 TCGv_i32 tmp32 = tcg_temp_new_i32();
255 TCGv tmp = tcg_temp_new();
256 gen_helper_f_to_memory(tmp32, t0);
257 tcg_gen_extu_i32_i64(tmp, tmp32);
aurel32f18cd222008-09-29 17:21:28 +0000258 tcg_gen_qemu_st32(tmp, t1, flags);
259 tcg_temp_free(tmp);
pbrooka7812ae2008-11-17 14:43:54 +0000260 tcg_temp_free_i32(tmp32);
aurel32f18cd222008-09-29 17:21:28 +0000261}
262
Blue Swirl636aa202009-08-16 09:06:54 +0000263static inline void gen_qemu_stg(TCGv t0, TCGv t1, int flags)
aurel32f18cd222008-09-29 17:21:28 +0000264{
pbrooka7812ae2008-11-17 14:43:54 +0000265 TCGv tmp = tcg_temp_new();
266 gen_helper_g_to_memory(tmp, t0);
aurel32f18cd222008-09-29 17:21:28 +0000267 tcg_gen_qemu_st64(tmp, t1, flags);
268 tcg_temp_free(tmp);
269}
270
Blue Swirl636aa202009-08-16 09:06:54 +0000271static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
aurel32f18cd222008-09-29 17:21:28 +0000272{
pbrooka7812ae2008-11-17 14:43:54 +0000273 TCGv_i32 tmp32 = tcg_temp_new_i32();
274 TCGv tmp = tcg_temp_new();
275 gen_helper_s_to_memory(tmp32, t0);
276 tcg_gen_extu_i32_i64(tmp, tmp32);
aurel32f18cd222008-09-29 17:21:28 +0000277 tcg_gen_qemu_st32(tmp, t1, flags);
278 tcg_temp_free(tmp);
pbrooka7812ae2008-11-17 14:43:54 +0000279 tcg_temp_free_i32(tmp32);
aurel32f18cd222008-09-29 17:21:28 +0000280}
281
Blue Swirl636aa202009-08-16 09:06:54 +0000282static inline void gen_store_mem(DisasContext *ctx,
283 void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
284 int flags),
285 int ra, int rb, int32_t disp16, int fp,
Richard Henderson6910b8f2010-04-07 15:42:26 -0700286 int clear)
aurel32023d8ca2008-09-29 17:21:17 +0000287{
Richard Henderson6910b8f2010-04-07 15:42:26 -0700288 TCGv addr, va;
289
290 addr = tcg_temp_new();
aurel32023d8ca2008-09-29 17:21:17 +0000291 if (rb != 31) {
292 tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
Richard Henderson6910b8f2010-04-07 15:42:26 -0700293 if (clear) {
aurel32023d8ca2008-09-29 17:21:17 +0000294 tcg_gen_andi_i64(addr, addr, ~0x7);
Richard Henderson6910b8f2010-04-07 15:42:26 -0700295 }
aurel32023d8ca2008-09-29 17:21:17 +0000296 } else {
Richard Henderson6910b8f2010-04-07 15:42:26 -0700297 if (clear) {
aurel32023d8ca2008-09-29 17:21:17 +0000298 disp16 &= ~0x7;
Richard Henderson6910b8f2010-04-07 15:42:26 -0700299 }
aurel32023d8ca2008-09-29 17:21:17 +0000300 tcg_gen_movi_i64(addr, disp16);
301 }
Richard Henderson6910b8f2010-04-07 15:42:26 -0700302
303 if (ra == 31) {
304 va = tcg_const_i64(0);
aurel32f18cd222008-09-29 17:21:28 +0000305 } else {
Richard Henderson6910b8f2010-04-07 15:42:26 -0700306 va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
aurel32023d8ca2008-09-29 17:21:17 +0000307 }
Richard Henderson6910b8f2010-04-07 15:42:26 -0700308 tcg_gen_qemu_store(va, addr, ctx->mem_idx);
309
aurel32023d8ca2008-09-29 17:21:17 +0000310 tcg_temp_free(addr);
Richard Henderson6910b8f2010-04-07 15:42:26 -0700311 if (ra == 31) {
312 tcg_temp_free(va);
313 }
314}
315
316static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
317 int32_t disp16, int quad)
318{
319 TCGv addr;
320
321 if (ra == 31) {
322 /* ??? Don't bother storing anything. The user can't tell
323 the difference, since the zero register always reads zero. */
324 return NO_EXIT;
325 }
326
327#if defined(CONFIG_USER_ONLY)
328 addr = cpu_lock_st_addr;
329#else
Richard Hendersone52458f2011-05-20 13:07:25 -0700330 addr = tcg_temp_local_new();
Richard Henderson6910b8f2010-04-07 15:42:26 -0700331#endif
332
333 if (rb != 31) {
334 tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
335 } else {
336 tcg_gen_movi_i64(addr, disp16);
337 }
338
339#if defined(CONFIG_USER_ONLY)
340 /* ??? This is handled via a complicated version of compare-and-swap
341 in the cpu_loop. Hopefully one day we'll have a real CAS opcode
342 in TCG so that this isn't necessary. */
343 return gen_excp(ctx, quad ? EXCP_STQ_C : EXCP_STL_C, ra);
344#else
345 /* ??? In system mode we are never multi-threaded, so CAS can be
346 implemented via a non-atomic load-compare-store sequence. */
347 {
348 int lab_fail, lab_done;
349 TCGv val;
350
351 lab_fail = gen_new_label();
352 lab_done = gen_new_label();
Richard Hendersone52458f2011-05-20 13:07:25 -0700353 tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
Richard Henderson6910b8f2010-04-07 15:42:26 -0700354
355 val = tcg_temp_new();
356 if (quad) {
357 tcg_gen_qemu_ld64(val, addr, ctx->mem_idx);
358 } else {
359 tcg_gen_qemu_ld32s(val, addr, ctx->mem_idx);
360 }
Richard Hendersone52458f2011-05-20 13:07:25 -0700361 tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
Richard Henderson6910b8f2010-04-07 15:42:26 -0700362
363 if (quad) {
364 tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
365 } else {
366 tcg_gen_qemu_st32(cpu_ir[ra], addr, ctx->mem_idx);
367 }
368 tcg_gen_movi_i64(cpu_ir[ra], 1);
369 tcg_gen_br(lab_done);
370
371 gen_set_label(lab_fail);
372 tcg_gen_movi_i64(cpu_ir[ra], 0);
373
374 gen_set_label(lab_done);
375 tcg_gen_movi_i64(cpu_lock_addr, -1);
376
377 tcg_temp_free(addr);
378 return NO_EXIT;
379 }
380#endif
aurel32023d8ca2008-09-29 17:21:17 +0000381}
382
Richard Henderson4af70372010-03-16 15:10:49 -0700383static int use_goto_tb(DisasContext *ctx, uint64_t dest)
j_mayer4c9649a2007-04-05 06:58:33 +0000384{
Richard Henderson4af70372010-03-16 15:10:49 -0700385 /* Check for the dest on the same page as the start of the TB. We
386 also want to suppress goto_tb in the case of single-steping and IO. */
387 return (((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0
388 && !ctx->env->singlestep_enabled
389 && !(ctx->tb->cflags & CF_LAST_IO));
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800390}
391
Richard Henderson4af70372010-03-16 15:10:49 -0700392static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800393{
Richard Henderson4af70372010-03-16 15:10:49 -0700394 uint64_t dest = ctx->pc + (disp << 2);
395
396 if (ra != 31) {
397 tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
398 }
399
400 /* Notice branch-to-next; used to initialize RA with the PC. */
401 if (disp == 0) {
402 return 0;
403 } else if (use_goto_tb(ctx, dest)) {
404 tcg_gen_goto_tb(0);
405 tcg_gen_movi_i64(cpu_pc, dest);
Stefan Weil4b4a72e2011-04-02 13:36:31 +0200406 tcg_gen_exit_tb((tcg_target_long)ctx->tb);
Richard Henderson4af70372010-03-16 15:10:49 -0700407 return EXIT_GOTO_TB;
408 } else {
409 tcg_gen_movi_i64(cpu_pc, dest);
410 return EXIT_PC_UPDATED;
411 }
412}
413
414static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
415 TCGv cmp, int32_t disp)
416{
417 uint64_t dest = ctx->pc + (disp << 2);
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800418 int lab_true = gen_new_label();
419
Richard Henderson4af70372010-03-16 15:10:49 -0700420 if (use_goto_tb(ctx, dest)) {
421 tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
422
423 tcg_gen_goto_tb(0);
424 tcg_gen_movi_i64(cpu_pc, ctx->pc);
Stefan Weil4b4a72e2011-04-02 13:36:31 +0200425 tcg_gen_exit_tb((tcg_target_long)ctx->tb);
Richard Henderson4af70372010-03-16 15:10:49 -0700426
427 gen_set_label(lab_true);
428 tcg_gen_goto_tb(1);
429 tcg_gen_movi_i64(cpu_pc, dest);
Stefan Weil4b4a72e2011-04-02 13:36:31 +0200430 tcg_gen_exit_tb((tcg_target_long)ctx->tb + 1);
Richard Henderson4af70372010-03-16 15:10:49 -0700431
432 return EXIT_GOTO_TB;
aurel329c295042008-09-17 22:04:44 +0000433 } else {
Richard Henderson4af70372010-03-16 15:10:49 -0700434 int lab_over = gen_new_label();
435
436 /* ??? Consider using either
437 movi pc, next
438 addi tmp, pc, disp
439 movcond pc, cond, 0, tmp, pc
440 or
441 setcond tmp, cond, 0
442 movi pc, next
443 neg tmp, tmp
444 andi tmp, tmp, disp
445 add pc, pc, tmp
446 The current diamond subgraph surely isn't efficient. */
447
448 tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
449 tcg_gen_movi_i64(cpu_pc, ctx->pc);
450 tcg_gen_br(lab_over);
451 gen_set_label(lab_true);
452 tcg_gen_movi_i64(cpu_pc, dest);
453 gen_set_label(lab_over);
454
455 return EXIT_PC_UPDATED;
aurel329c295042008-09-17 22:04:44 +0000456 }
j_mayer4c9649a2007-04-05 06:58:33 +0000457}
458
Richard Henderson4af70372010-03-16 15:10:49 -0700459static ExitStatus gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
460 int32_t disp, int mask)
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800461{
Richard Henderson4af70372010-03-16 15:10:49 -0700462 TCGv cmp_tmp;
463
464 if (unlikely(ra == 31)) {
465 cmp_tmp = tcg_const_i64(0);
466 } else {
467 cmp_tmp = tcg_temp_new();
468 if (mask) {
469 tcg_gen_andi_i64(cmp_tmp, cpu_ir[ra], 1);
470 } else {
471 tcg_gen_mov_i64(cmp_tmp, cpu_ir[ra]);
472 }
473 }
474
475 return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
476}
477
478/* Fold -0.0 for comparison with COND. */
479
480static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
481{
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800482 uint64_t mzero = 1ull << 63;
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800483
484 switch (cond) {
485 case TCG_COND_LE:
486 case TCG_COND_GT:
487 /* For <= or >, the -0.0 value directly compares the way we want. */
Richard Henderson4af70372010-03-16 15:10:49 -0700488 tcg_gen_mov_i64(dest, src);
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800489 break;
490
491 case TCG_COND_EQ:
492 case TCG_COND_NE:
493 /* For == or !=, we can simply mask off the sign bit and compare. */
Richard Henderson4af70372010-03-16 15:10:49 -0700494 tcg_gen_andi_i64(dest, src, mzero - 1);
pbrooka7812ae2008-11-17 14:43:54 +0000495 break;
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800496
497 case TCG_COND_GE:
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800498 case TCG_COND_LT:
Richard Henderson4af70372010-03-16 15:10:49 -0700499 /* For >= or <, map -0.0 to +0.0 via comparison and mask. */
500 tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero);
501 tcg_gen_neg_i64(dest, dest);
502 tcg_gen_and_i64(dest, dest, src);
pbrooka7812ae2008-11-17 14:43:54 +0000503 break;
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800504
pbrooka7812ae2008-11-17 14:43:54 +0000505 default:
506 abort();
aurel32f18cd222008-09-29 17:21:28 +0000507 }
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800508}
509
Richard Henderson4af70372010-03-16 15:10:49 -0700510static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
511 int32_t disp)
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800512{
Richard Henderson4af70372010-03-16 15:10:49 -0700513 TCGv cmp_tmp;
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800514
515 if (unlikely(ra == 31)) {
516 /* Very uncommon case, but easier to optimize it to an integer
517 comparison than continuing with the floating point comparison. */
Richard Henderson4af70372010-03-16 15:10:49 -0700518 return gen_bcond(ctx, cond, ra, disp, 0);
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800519 }
520
Richard Henderson4af70372010-03-16 15:10:49 -0700521 cmp_tmp = tcg_temp_new();
522 gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
523 return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
j_mayer4c9649a2007-04-05 06:58:33 +0000524}
525
Richard Hendersonbbe1dab2010-03-16 14:44:44 -0700526static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
Richard Henderson4af70372010-03-16 15:10:49 -0700527 int islit, uint8_t lit, int mask)
j_mayer4c9649a2007-04-05 06:58:33 +0000528{
Richard Hendersonbbe1dab2010-03-16 14:44:44 -0700529 TCGCond inv_cond = tcg_invert_cond(cond);
aurel329c295042008-09-17 22:04:44 +0000530 int l1;
531
532 if (unlikely(rc == 31))
533 return;
534
535 l1 = gen_new_label();
536
537 if (ra != 31) {
538 if (mask) {
pbrooka7812ae2008-11-17 14:43:54 +0000539 TCGv tmp = tcg_temp_new();
aurel329c295042008-09-17 22:04:44 +0000540 tcg_gen_andi_i64(tmp, cpu_ir[ra], 1);
541 tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
542 tcg_temp_free(tmp);
543 } else
544 tcg_gen_brcondi_i64(inv_cond, cpu_ir[ra], 0, l1);
545 } else {
546 /* Very uncommon case - Do not bother to optimize. */
547 TCGv tmp = tcg_const_i64(0);
548 tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
549 tcg_temp_free(tmp);
550 }
551
aurel3229d26d22008-09-05 19:07:53 +0000552 if (islit)
aurel329c295042008-09-17 22:04:44 +0000553 tcg_gen_movi_i64(cpu_ir[rc], lit);
aurel3229d26d22008-09-05 19:07:53 +0000554 else
aurel32dfaa8582008-09-18 10:11:26 +0000555 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
aurel329c295042008-09-17 22:04:44 +0000556 gen_set_label(l1);
j_mayer4c9649a2007-04-05 06:58:33 +0000557}
558
Richard Hendersonbbe1dab2010-03-16 14:44:44 -0700559static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800560{
Richard Henderson4af70372010-03-16 15:10:49 -0700561 TCGv cmp_tmp;
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800562 int l1;
563
Richard Henderson4af70372010-03-16 15:10:49 -0700564 if (unlikely(rc == 31)) {
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800565 return;
Richard Henderson4af70372010-03-16 15:10:49 -0700566 }
567
568 cmp_tmp = tcg_temp_new();
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800569 if (unlikely(ra == 31)) {
Richard Henderson4af70372010-03-16 15:10:49 -0700570 tcg_gen_movi_i64(cmp_tmp, 0);
571 } else {
572 gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800573 }
574
575 l1 = gen_new_label();
Richard Henderson4af70372010-03-16 15:10:49 -0700576 tcg_gen_brcondi_i64(tcg_invert_cond(cond), cmp_tmp, 0, l1);
577 tcg_temp_free(cmp_tmp);
Richard Hendersondbb30fe2009-12-13 17:46:17 -0800578
579 if (rb != 31)
580 tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]);
581 else
582 tcg_gen_movi_i64(cpu_fir[rc], 0);
583 gen_set_label(l1);
584}
585
Richard Hendersonf24518b2010-01-04 14:27:23 -0800586#define QUAL_RM_N 0x080 /* Round mode nearest even */
587#define QUAL_RM_C 0x000 /* Round mode chopped */
588#define QUAL_RM_M 0x040 /* Round mode minus infinity */
589#define QUAL_RM_D 0x0c0 /* Round mode dynamic */
590#define QUAL_RM_MASK 0x0c0
591
592#define QUAL_U 0x100 /* Underflow enable (fp output) */
593#define QUAL_V 0x100 /* Overflow enable (int output) */
594#define QUAL_S 0x400 /* Software completion enable */
595#define QUAL_I 0x200 /* Inexact detection enable */
596
597static void gen_qual_roundmode(DisasContext *ctx, int fn11)
598{
599 TCGv_i32 tmp;
600
601 fn11 &= QUAL_RM_MASK;
602 if (fn11 == ctx->tb_rm) {
603 return;
604 }
605 ctx->tb_rm = fn11;
606
607 tmp = tcg_temp_new_i32();
608 switch (fn11) {
609 case QUAL_RM_N:
610 tcg_gen_movi_i32(tmp, float_round_nearest_even);
611 break;
612 case QUAL_RM_C:
613 tcg_gen_movi_i32(tmp, float_round_to_zero);
614 break;
615 case QUAL_RM_M:
616 tcg_gen_movi_i32(tmp, float_round_down);
617 break;
618 case QUAL_RM_D:
619 tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUState, fpcr_dyn_round));
620 break;
621 }
622
623#if defined(CONFIG_SOFTFLOAT_INLINE)
624 /* ??? The "softfloat.h" interface is to call set_float_rounding_mode.
625 With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
626 sets the one field. */
627 tcg_gen_st8_i32(tmp, cpu_env,
628 offsetof(CPUState, fp_status.float_rounding_mode));
629#else
630 gen_helper_setroundmode(tmp);
631#endif
632
633 tcg_temp_free_i32(tmp);
pbrooka7812ae2008-11-17 14:43:54 +0000634}
Richard Hendersonf24518b2010-01-04 14:27:23 -0800635
636static void gen_qual_flushzero(DisasContext *ctx, int fn11)
637{
638 TCGv_i32 tmp;
639
640 fn11 &= QUAL_U;
641 if (fn11 == ctx->tb_ftz) {
642 return;
643 }
644 ctx->tb_ftz = fn11;
645
646 tmp = tcg_temp_new_i32();
647 if (fn11) {
648 /* Underflow is enabled, use the FPCR setting. */
649 tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUState, fpcr_flush_to_zero));
650 } else {
651 /* Underflow is disabled, force flush-to-zero. */
652 tcg_gen_movi_i32(tmp, 1);
653 }
654
655#if defined(CONFIG_SOFTFLOAT_INLINE)
656 tcg_gen_st8_i32(tmp, cpu_env,
657 offsetof(CPUState, fp_status.flush_to_zero));
658#else
659 gen_helper_setflushzero(tmp);
660#endif
661
662 tcg_temp_free_i32(tmp);
663}
664
665static TCGv gen_ieee_input(int reg, int fn11, int is_cmp)
666{
667 TCGv val = tcg_temp_new();
668 if (reg == 31) {
669 tcg_gen_movi_i64(val, 0);
670 } else if (fn11 & QUAL_S) {
671 gen_helper_ieee_input_s(val, cpu_fir[reg]);
672 } else if (is_cmp) {
673 gen_helper_ieee_input_cmp(val, cpu_fir[reg]);
674 } else {
675 gen_helper_ieee_input(val, cpu_fir[reg]);
676 }
677 return val;
678}
679
680static void gen_fp_exc_clear(void)
681{
682#if defined(CONFIG_SOFTFLOAT_INLINE)
683 TCGv_i32 zero = tcg_const_i32(0);
684 tcg_gen_st8_i32(zero, cpu_env,
685 offsetof(CPUState, fp_status.float_exception_flags));
686 tcg_temp_free_i32(zero);
687#else
688 gen_helper_fp_exc_clear();
689#endif
690}
691
692static void gen_fp_exc_raise_ignore(int rc, int fn11, int ignore)
693{
694 /* ??? We ought to be able to do something with imprecise exceptions.
695 E.g. notice we're still in the trap shadow of something within the
696 TB and do not generate the code to signal the exception; end the TB
697 when an exception is forced to arrive, either by consumption of a
698 register value or TRAPB or EXCB. */
699 TCGv_i32 exc = tcg_temp_new_i32();
700 TCGv_i32 reg;
701
702#if defined(CONFIG_SOFTFLOAT_INLINE)
703 tcg_gen_ld8u_i32(exc, cpu_env,
704 offsetof(CPUState, fp_status.float_exception_flags));
705#else
706 gen_helper_fp_exc_get(exc);
707#endif
708
709 if (ignore) {
710 tcg_gen_andi_i32(exc, exc, ~ignore);
711 }
712
713 /* ??? Pass in the regno of the destination so that the helper can
714 set EXC_MASK, which contains a bitmask of destination registers
715 that have caused arithmetic traps. A simple userspace emulation
716 does not require this. We do need it for a guest kernel's entArith,
717 or if we were to do something clever with imprecise exceptions. */
718 reg = tcg_const_i32(rc + 32);
719
720 if (fn11 & QUAL_S) {
721 gen_helper_fp_exc_raise_s(exc, reg);
722 } else {
723 gen_helper_fp_exc_raise(exc, reg);
724 }
725
726 tcg_temp_free_i32(reg);
727 tcg_temp_free_i32(exc);
728}
729
730static inline void gen_fp_exc_raise(int rc, int fn11)
731{
732 gen_fp_exc_raise_ignore(rc, fn11, fn11 & QUAL_I ? 0 : float_flag_inexact);
733}
734
Richard Henderson593f17e2010-04-07 10:17:24 -0700735static void gen_fcvtlq(int rb, int rc)
736{
737 if (unlikely(rc == 31)) {
738 return;
739 }
740 if (unlikely(rb == 31)) {
741 tcg_gen_movi_i64(cpu_fir[rc], 0);
742 } else {
743 TCGv tmp = tcg_temp_new();
744
745 /* The arithmetic right shift here, plus the sign-extended mask below
746 yields a sign-extended result without an explicit ext32s_i64. */
747 tcg_gen_sari_i64(tmp, cpu_fir[rb], 32);
748 tcg_gen_shri_i64(cpu_fir[rc], cpu_fir[rb], 29);
749 tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000);
750 tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rc], 0x3fffffff);
751 tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
752
753 tcg_temp_free(tmp);
754 }
755}
756
Richard Henderson735cf452010-03-19 15:55:40 -0700757static void gen_fcvtql(int rb, int rc)
758{
759 if (unlikely(rc == 31)) {
760 return;
761 }
762 if (unlikely(rb == 31)) {
763 tcg_gen_movi_i64(cpu_fir[rc], 0);
764 } else {
765 TCGv tmp = tcg_temp_new();
766
767 tcg_gen_andi_i64(tmp, cpu_fir[rb], 0xC0000000);
768 tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rb], 0x3FFFFFFF);
769 tcg_gen_shli_i64(tmp, tmp, 32);
770 tcg_gen_shli_i64(cpu_fir[rc], cpu_fir[rc], 29);
771 tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
772
773 tcg_temp_free(tmp);
774 }
775}
776
777static void gen_fcvtql_v(DisasContext *ctx, int rb, int rc)
778{
779 if (rb != 31) {
780 int lab = gen_new_label();
781 TCGv tmp = tcg_temp_new();
782
783 tcg_gen_ext32s_i64(tmp, cpu_fir[rb]);
784 tcg_gen_brcond_i64(TCG_COND_EQ, tmp, cpu_fir[rb], lab);
785 gen_excp(ctx, EXCP_ARITH, EXC_M_IOV);
786
787 gen_set_label(lab);
788 }
789 gen_fcvtql(rb, rc);
790}
791
Richard Hendersonf24518b2010-01-04 14:27:23 -0800792#define FARITH2(name) \
793static inline void glue(gen_f, name)(int rb, int rc) \
794{ \
795 if (unlikely(rc == 31)) { \
796 return; \
797 } \
798 if (rb != 31) { \
799 gen_helper_ ## name (cpu_fir[rc], cpu_fir[rb]); \
800 } else { \
801 TCGv tmp = tcg_const_i64(0); \
802 gen_helper_ ## name (cpu_fir[rc], tmp); \
803 tcg_temp_free(tmp); \
804 } \
805}
Richard Hendersonf24518b2010-01-04 14:27:23 -0800806
807/* ??? VAX instruction qualifiers ignored. */
pbrooka7812ae2008-11-17 14:43:54 +0000808FARITH2(sqrtf)
809FARITH2(sqrtg)
pbrooka7812ae2008-11-17 14:43:54 +0000810FARITH2(cvtgf)
811FARITH2(cvtgq)
812FARITH2(cvtqf)
813FARITH2(cvtqg)
aurel32f18cd222008-09-29 17:21:28 +0000814
Richard Hendersonf24518b2010-01-04 14:27:23 -0800815static void gen_ieee_arith2(DisasContext *ctx, void (*helper)(TCGv, TCGv),
816 int rb, int rc, int fn11)
817{
818 TCGv vb;
819
820 /* ??? This is wrong: the instruction is not a nop, it still may
821 raise exceptions. */
822 if (unlikely(rc == 31)) {
823 return;
824 }
825
826 gen_qual_roundmode(ctx, fn11);
827 gen_qual_flushzero(ctx, fn11);
828 gen_fp_exc_clear();
829
830 vb = gen_ieee_input(rb, fn11, 0);
831 helper(cpu_fir[rc], vb);
832 tcg_temp_free(vb);
833
834 gen_fp_exc_raise(rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +0000835}
836
Richard Hendersonf24518b2010-01-04 14:27:23 -0800837#define IEEE_ARITH2(name) \
838static inline void glue(gen_f, name)(DisasContext *ctx, \
839 int rb, int rc, int fn11) \
840{ \
841 gen_ieee_arith2(ctx, gen_helper_##name, rb, rc, fn11); \
842}
843IEEE_ARITH2(sqrts)
844IEEE_ARITH2(sqrtt)
845IEEE_ARITH2(cvtst)
846IEEE_ARITH2(cvtts)
847
848static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
849{
850 TCGv vb;
851 int ignore = 0;
852
853 /* ??? This is wrong: the instruction is not a nop, it still may
854 raise exceptions. */
855 if (unlikely(rc == 31)) {
856 return;
857 }
858
859 /* No need to set flushzero, since we have an integer output. */
860 gen_fp_exc_clear();
861 vb = gen_ieee_input(rb, fn11, 0);
862
863 /* Almost all integer conversions use cropped rounding, and most
864 also do not have integer overflow enabled. Special case that. */
865 switch (fn11) {
866 case QUAL_RM_C:
867 gen_helper_cvttq_c(cpu_fir[rc], vb);
868 break;
869 case QUAL_V | QUAL_RM_C:
870 case QUAL_S | QUAL_V | QUAL_RM_C:
871 ignore = float_flag_inexact;
872 /* FALLTHRU */
873 case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C:
874 gen_helper_cvttq_svic(cpu_fir[rc], vb);
875 break;
876 default:
877 gen_qual_roundmode(ctx, fn11);
878 gen_helper_cvttq(cpu_fir[rc], vb);
879 ignore |= (fn11 & QUAL_V ? 0 : float_flag_overflow);
880 ignore |= (fn11 & QUAL_I ? 0 : float_flag_inexact);
881 break;
882 }
883 tcg_temp_free(vb);
884
885 gen_fp_exc_raise_ignore(rc, fn11, ignore);
886}
887
888static void gen_ieee_intcvt(DisasContext *ctx, void (*helper)(TCGv, TCGv),
889 int rb, int rc, int fn11)
890{
891 TCGv vb;
892
893 /* ??? This is wrong: the instruction is not a nop, it still may
894 raise exceptions. */
895 if (unlikely(rc == 31)) {
896 return;
897 }
898
899 gen_qual_roundmode(ctx, fn11);
900
901 if (rb == 31) {
902 vb = tcg_const_i64(0);
903 } else {
904 vb = cpu_fir[rb];
905 }
906
907 /* The only exception that can be raised by integer conversion
908 is inexact. Thus we only need to worry about exceptions when
909 inexact handling is requested. */
910 if (fn11 & QUAL_I) {
911 gen_fp_exc_clear();
912 helper(cpu_fir[rc], vb);
913 gen_fp_exc_raise(rc, fn11);
914 } else {
915 helper(cpu_fir[rc], vb);
916 }
917
918 if (rb == 31) {
919 tcg_temp_free(vb);
920 }
921}
922
923#define IEEE_INTCVT(name) \
924static inline void glue(gen_f, name)(DisasContext *ctx, \
925 int rb, int rc, int fn11) \
926{ \
927 gen_ieee_intcvt(ctx, gen_helper_##name, rb, rc, fn11); \
928}
929IEEE_INTCVT(cvtqs)
930IEEE_INTCVT(cvtqt)
931
Richard Hendersondc96be42010-04-12 16:12:20 -0700932static void gen_cpys_internal(int ra, int rb, int rc, int inv_a, uint64_t mask)
933{
934 TCGv va, vb, vmask;
935 int za = 0, zb = 0;
936
937 if (unlikely(rc == 31)) {
938 return;
939 }
940
941 vmask = tcg_const_i64(mask);
942
943 TCGV_UNUSED_I64(va);
944 if (ra == 31) {
945 if (inv_a) {
946 va = vmask;
947 } else {
948 za = 1;
949 }
950 } else {
951 va = tcg_temp_new_i64();
952 tcg_gen_mov_i64(va, cpu_fir[ra]);
953 if (inv_a) {
954 tcg_gen_andc_i64(va, vmask, va);
955 } else {
956 tcg_gen_and_i64(va, va, vmask);
957 }
958 }
959
960 TCGV_UNUSED_I64(vb);
961 if (rb == 31) {
962 zb = 1;
963 } else {
964 vb = tcg_temp_new_i64();
965 tcg_gen_andc_i64(vb, cpu_fir[rb], vmask);
966 }
967
968 switch (za << 1 | zb) {
969 case 0 | 0:
970 tcg_gen_or_i64(cpu_fir[rc], va, vb);
971 break;
972 case 0 | 1:
973 tcg_gen_mov_i64(cpu_fir[rc], va);
974 break;
975 case 2 | 0:
976 tcg_gen_mov_i64(cpu_fir[rc], vb);
977 break;
978 case 2 | 1:
979 tcg_gen_movi_i64(cpu_fir[rc], 0);
980 break;
981 }
982
983 tcg_temp_free(vmask);
984 if (ra != 31) {
985 tcg_temp_free(va);
986 }
987 if (rb != 31) {
988 tcg_temp_free(vb);
989 }
990}
991
992static inline void gen_fcpys(int ra, int rb, int rc)
993{
994 gen_cpys_internal(ra, rb, rc, 0, 0x8000000000000000ULL);
995}
996
997static inline void gen_fcpysn(int ra, int rb, int rc)
998{
999 gen_cpys_internal(ra, rb, rc, 1, 0x8000000000000000ULL);
1000}
1001
1002static inline void gen_fcpyse(int ra, int rb, int rc)
1003{
1004 gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
1005}
1006
Richard Hendersonf24518b2010-01-04 14:27:23 -08001007#define FARITH3(name) \
1008static inline void glue(gen_f, name)(int ra, int rb, int rc) \
1009{ \
1010 TCGv va, vb; \
1011 \
1012 if (unlikely(rc == 31)) { \
1013 return; \
1014 } \
1015 if (ra == 31) { \
1016 va = tcg_const_i64(0); \
1017 } else { \
1018 va = cpu_fir[ra]; \
1019 } \
1020 if (rb == 31) { \
1021 vb = tcg_const_i64(0); \
1022 } else { \
1023 vb = cpu_fir[rb]; \
1024 } \
1025 \
1026 gen_helper_ ## name (cpu_fir[rc], va, vb); \
1027 \
1028 if (ra == 31) { \
1029 tcg_temp_free(va); \
1030 } \
1031 if (rb == 31) { \
1032 tcg_temp_free(vb); \
1033 } \
1034}
Richard Hendersonf24518b2010-01-04 14:27:23 -08001035
1036/* ??? VAX instruction qualifiers ignored. */
pbrooka7812ae2008-11-17 14:43:54 +00001037FARITH3(addf)
1038FARITH3(subf)
1039FARITH3(mulf)
1040FARITH3(divf)
1041FARITH3(addg)
1042FARITH3(subg)
1043FARITH3(mulg)
1044FARITH3(divg)
1045FARITH3(cmpgeq)
1046FARITH3(cmpglt)
1047FARITH3(cmpgle)
Richard Hendersonf24518b2010-01-04 14:27:23 -08001048
1049static void gen_ieee_arith3(DisasContext *ctx,
1050 void (*helper)(TCGv, TCGv, TCGv),
1051 int ra, int rb, int rc, int fn11)
1052{
1053 TCGv va, vb;
1054
1055 /* ??? This is wrong: the instruction is not a nop, it still may
1056 raise exceptions. */
1057 if (unlikely(rc == 31)) {
1058 return;
1059 }
1060
1061 gen_qual_roundmode(ctx, fn11);
1062 gen_qual_flushzero(ctx, fn11);
1063 gen_fp_exc_clear();
1064
1065 va = gen_ieee_input(ra, fn11, 0);
1066 vb = gen_ieee_input(rb, fn11, 0);
1067 helper(cpu_fir[rc], va, vb);
1068 tcg_temp_free(va);
1069 tcg_temp_free(vb);
1070
1071 gen_fp_exc_raise(rc, fn11);
1072}
1073
1074#define IEEE_ARITH3(name) \
1075static inline void glue(gen_f, name)(DisasContext *ctx, \
1076 int ra, int rb, int rc, int fn11) \
1077{ \
1078 gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc, fn11); \
1079}
1080IEEE_ARITH3(adds)
1081IEEE_ARITH3(subs)
1082IEEE_ARITH3(muls)
1083IEEE_ARITH3(divs)
1084IEEE_ARITH3(addt)
1085IEEE_ARITH3(subt)
1086IEEE_ARITH3(mult)
1087IEEE_ARITH3(divt)
1088
1089static void gen_ieee_compare(DisasContext *ctx,
1090 void (*helper)(TCGv, TCGv, TCGv),
1091 int ra, int rb, int rc, int fn11)
1092{
1093 TCGv va, vb;
1094
1095 /* ??? This is wrong: the instruction is not a nop, it still may
1096 raise exceptions. */
1097 if (unlikely(rc == 31)) {
1098 return;
1099 }
1100
1101 gen_fp_exc_clear();
1102
1103 va = gen_ieee_input(ra, fn11, 1);
1104 vb = gen_ieee_input(rb, fn11, 1);
1105 helper(cpu_fir[rc], va, vb);
1106 tcg_temp_free(va);
1107 tcg_temp_free(vb);
1108
1109 gen_fp_exc_raise(rc, fn11);
1110}
1111
1112#define IEEE_CMP3(name) \
1113static inline void glue(gen_f, name)(DisasContext *ctx, \
1114 int ra, int rb, int rc, int fn11) \
1115{ \
1116 gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc, fn11); \
1117}
1118IEEE_CMP3(cmptun)
1119IEEE_CMP3(cmpteq)
1120IEEE_CMP3(cmptlt)
1121IEEE_CMP3(cmptle)
aurel32f18cd222008-09-29 17:21:28 +00001122
Richard Henderson248c42f2009-12-11 10:39:56 -08001123static inline uint64_t zapnot_mask(uint8_t lit)
1124{
1125 uint64_t mask = 0;
1126 int i;
1127
1128 for (i = 0; i < 8; ++i) {
1129 if ((lit >> i) & 1)
1130 mask |= 0xffull << (i * 8);
1131 }
1132 return mask;
1133}
1134
Richard Henderson87d98f92009-12-10 13:43:58 -08001135/* Implement zapnot with an immediate operand, which expands to some
1136 form of immediate AND. This is a basic building block in the
1137 definition of many of the other byte manipulation instructions. */
Richard Henderson248c42f2009-12-11 10:39:56 -08001138static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
Richard Henderson87d98f92009-12-10 13:43:58 -08001139{
Richard Henderson87d98f92009-12-10 13:43:58 -08001140 switch (lit) {
1141 case 0x00:
Richard Henderson248c42f2009-12-11 10:39:56 -08001142 tcg_gen_movi_i64(dest, 0);
Richard Henderson87d98f92009-12-10 13:43:58 -08001143 break;
1144 case 0x01:
Richard Henderson248c42f2009-12-11 10:39:56 -08001145 tcg_gen_ext8u_i64(dest, src);
Richard Henderson87d98f92009-12-10 13:43:58 -08001146 break;
1147 case 0x03:
Richard Henderson248c42f2009-12-11 10:39:56 -08001148 tcg_gen_ext16u_i64(dest, src);
Richard Henderson87d98f92009-12-10 13:43:58 -08001149 break;
1150 case 0x0f:
Richard Henderson248c42f2009-12-11 10:39:56 -08001151 tcg_gen_ext32u_i64(dest, src);
Richard Henderson87d98f92009-12-10 13:43:58 -08001152 break;
1153 case 0xff:
Richard Henderson248c42f2009-12-11 10:39:56 -08001154 tcg_gen_mov_i64(dest, src);
Richard Henderson87d98f92009-12-10 13:43:58 -08001155 break;
1156 default:
Richard Henderson248c42f2009-12-11 10:39:56 -08001157 tcg_gen_andi_i64 (dest, src, zapnot_mask (lit));
Richard Henderson87d98f92009-12-10 13:43:58 -08001158 break;
1159 }
1160}
1161
1162static inline void gen_zapnot(int ra, int rb, int rc, int islit, uint8_t lit)
1163{
1164 if (unlikely(rc == 31))
1165 return;
1166 else if (unlikely(ra == 31))
1167 tcg_gen_movi_i64(cpu_ir[rc], 0);
1168 else if (islit)
Richard Henderson248c42f2009-12-11 10:39:56 -08001169 gen_zapnoti(cpu_ir[rc], cpu_ir[ra], lit);
Richard Henderson87d98f92009-12-10 13:43:58 -08001170 else
1171 gen_helper_zapnot (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1172}
1173
1174static inline void gen_zap(int ra, int rb, int rc, int islit, uint8_t lit)
1175{
1176 if (unlikely(rc == 31))
1177 return;
1178 else if (unlikely(ra == 31))
1179 tcg_gen_movi_i64(cpu_ir[rc], 0);
1180 else if (islit)
Richard Henderson248c42f2009-12-11 10:39:56 -08001181 gen_zapnoti(cpu_ir[rc], cpu_ir[ra], ~lit);
Richard Henderson87d98f92009-12-10 13:43:58 -08001182 else
1183 gen_helper_zap (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1184}
1185
1186
Richard Henderson248c42f2009-12-11 10:39:56 -08001187/* EXTWH, EXTLH, EXTQH */
Richard Hendersonffec44f2009-12-11 11:58:29 -08001188static void gen_ext_h(int ra, int rb, int rc, int islit,
1189 uint8_t lit, uint8_t byte_mask)
aurel32b3249f62008-09-17 22:04:52 +00001190{
1191 if (unlikely(rc == 31))
1192 return;
Richard Henderson377a43b2009-12-10 14:00:18 -08001193 else if (unlikely(ra == 31))
1194 tcg_gen_movi_i64(cpu_ir[rc], 0);
1195 else {
aurel32dfaa8582008-09-18 10:11:26 +00001196 if (islit) {
Richard Henderson377a43b2009-12-10 14:00:18 -08001197 lit = (64 - (lit & 7) * 8) & 0x3f;
1198 tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit);
aurel32fe2b2692008-09-29 17:21:37 +00001199 } else {
Richard Henderson377a43b2009-12-10 14:00:18 -08001200 TCGv tmp1 = tcg_temp_new();
aurel32b3249f62008-09-17 22:04:52 +00001201 tcg_gen_andi_i64(tmp1, cpu_ir[rb], 7);
1202 tcg_gen_shli_i64(tmp1, tmp1, 3);
Vince Weaverdbf95802009-09-17 15:28:52 -04001203 tcg_gen_neg_i64(tmp1, tmp1);
1204 tcg_gen_andi_i64(tmp1, tmp1, 0x3f);
aurel32dfaa8582008-09-18 10:11:26 +00001205 tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], tmp1);
aurel32b3249f62008-09-17 22:04:52 +00001206 tcg_temp_free(tmp1);
aurel32dfaa8582008-09-18 10:11:26 +00001207 }
Richard Henderson248c42f2009-12-11 10:39:56 -08001208 gen_zapnoti(cpu_ir[rc], cpu_ir[rc], byte_mask);
Richard Henderson377a43b2009-12-10 14:00:18 -08001209 }
aurel32b3249f62008-09-17 22:04:52 +00001210}
1211
Richard Henderson248c42f2009-12-11 10:39:56 -08001212/* EXTBL, EXTWL, EXTLL, EXTQL */
Richard Hendersonffec44f2009-12-11 11:58:29 -08001213static void gen_ext_l(int ra, int rb, int rc, int islit,
1214 uint8_t lit, uint8_t byte_mask)
aurel32b3249f62008-09-17 22:04:52 +00001215{
1216 if (unlikely(rc == 31))
1217 return;
Richard Henderson377a43b2009-12-10 14:00:18 -08001218 else if (unlikely(ra == 31))
1219 tcg_gen_movi_i64(cpu_ir[rc], 0);
1220 else {
aurel32dfaa8582008-09-18 10:11:26 +00001221 if (islit) {
Richard Henderson377a43b2009-12-10 14:00:18 -08001222 tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], (lit & 7) * 8);
aurel32dfaa8582008-09-18 10:11:26 +00001223 } else {
pbrooka7812ae2008-11-17 14:43:54 +00001224 TCGv tmp = tcg_temp_new();
aurel32b3249f62008-09-17 22:04:52 +00001225 tcg_gen_andi_i64(tmp, cpu_ir[rb], 7);
1226 tcg_gen_shli_i64(tmp, tmp, 3);
aurel32dfaa8582008-09-18 10:11:26 +00001227 tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], tmp);
aurel32b3249f62008-09-17 22:04:52 +00001228 tcg_temp_free(tmp);
aurel32fe2b2692008-09-29 17:21:37 +00001229 }
Richard Henderson248c42f2009-12-11 10:39:56 -08001230 gen_zapnoti(cpu_ir[rc], cpu_ir[rc], byte_mask);
1231 }
1232}
1233
Richard Henderson50eb6e52009-12-11 16:31:29 -08001234/* INSWH, INSLH, INSQH */
1235static void gen_ins_h(int ra, int rb, int rc, int islit,
1236 uint8_t lit, uint8_t byte_mask)
1237{
1238 if (unlikely(rc == 31))
1239 return;
1240 else if (unlikely(ra == 31) || (islit && (lit & 7) == 0))
1241 tcg_gen_movi_i64(cpu_ir[rc], 0);
1242 else {
1243 TCGv tmp = tcg_temp_new();
1244
1245 /* The instruction description has us left-shift the byte mask
1246 and extract bits <15:8> and apply that zap at the end. This
1247 is equivalent to simply performing the zap first and shifting
1248 afterward. */
1249 gen_zapnoti (tmp, cpu_ir[ra], byte_mask);
1250
1251 if (islit) {
1252 /* Note that we have handled the lit==0 case above. */
1253 tcg_gen_shri_i64 (cpu_ir[rc], tmp, 64 - (lit & 7) * 8);
1254 } else {
1255 TCGv shift = tcg_temp_new();
1256
1257 /* If (B & 7) == 0, we need to shift by 64 and leave a zero.
1258 Do this portably by splitting the shift into two parts:
1259 shift_count-1 and 1. Arrange for the -1 by using
1260 ones-complement instead of twos-complement in the negation:
1261 ~((B & 7) * 8) & 63. */
1262
1263 tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1264 tcg_gen_shli_i64(shift, shift, 3);
1265 tcg_gen_not_i64(shift, shift);
1266 tcg_gen_andi_i64(shift, shift, 0x3f);
1267
1268 tcg_gen_shr_i64(cpu_ir[rc], tmp, shift);
1269 tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[rc], 1);
1270 tcg_temp_free(shift);
1271 }
1272 tcg_temp_free(tmp);
1273 }
1274}
1275
Richard Henderson248c42f2009-12-11 10:39:56 -08001276/* INSBL, INSWL, INSLL, INSQL */
Richard Hendersonffec44f2009-12-11 11:58:29 -08001277static void gen_ins_l(int ra, int rb, int rc, int islit,
1278 uint8_t lit, uint8_t byte_mask)
Richard Henderson248c42f2009-12-11 10:39:56 -08001279{
1280 if (unlikely(rc == 31))
1281 return;
1282 else if (unlikely(ra == 31))
1283 tcg_gen_movi_i64(cpu_ir[rc], 0);
1284 else {
1285 TCGv tmp = tcg_temp_new();
1286
1287 /* The instruction description has us left-shift the byte mask
1288 the same number of byte slots as the data and apply the zap
1289 at the end. This is equivalent to simply performing the zap
1290 first and shifting afterward. */
1291 gen_zapnoti (tmp, cpu_ir[ra], byte_mask);
1292
1293 if (islit) {
1294 tcg_gen_shli_i64(cpu_ir[rc], tmp, (lit & 7) * 8);
1295 } else {
1296 TCGv shift = tcg_temp_new();
1297 tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1298 tcg_gen_shli_i64(shift, shift, 3);
1299 tcg_gen_shl_i64(cpu_ir[rc], tmp, shift);
1300 tcg_temp_free(shift);
1301 }
1302 tcg_temp_free(tmp);
Richard Henderson377a43b2009-12-10 14:00:18 -08001303 }
aurel32b3249f62008-09-17 22:04:52 +00001304}
1305
Richard Hendersonffec44f2009-12-11 11:58:29 -08001306/* MSKWH, MSKLH, MSKQH */
1307static void gen_msk_h(int ra, int rb, int rc, int islit,
1308 uint8_t lit, uint8_t byte_mask)
1309{
1310 if (unlikely(rc == 31))
1311 return;
1312 else if (unlikely(ra == 31))
1313 tcg_gen_movi_i64(cpu_ir[rc], 0);
1314 else if (islit) {
1315 gen_zapnoti (cpu_ir[rc], cpu_ir[ra], ~((byte_mask << (lit & 7)) >> 8));
1316 } else {
1317 TCGv shift = tcg_temp_new();
1318 TCGv mask = tcg_temp_new();
1319
1320 /* The instruction description is as above, where the byte_mask
1321 is shifted left, and then we extract bits <15:8>. This can be
1322 emulated with a right-shift on the expanded byte mask. This
1323 requires extra care because for an input <2:0> == 0 we need a
1324 shift of 64 bits in order to generate a zero. This is done by
1325 splitting the shift into two parts, the variable shift - 1
1326 followed by a constant 1 shift. The code we expand below is
1327 equivalent to ~((B & 7) * 8) & 63. */
1328
1329 tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1330 tcg_gen_shli_i64(shift, shift, 3);
1331 tcg_gen_not_i64(shift, shift);
1332 tcg_gen_andi_i64(shift, shift, 0x3f);
1333 tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
1334 tcg_gen_shr_i64(mask, mask, shift);
1335 tcg_gen_shri_i64(mask, mask, 1);
1336
1337 tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], mask);
1338
1339 tcg_temp_free(mask);
1340 tcg_temp_free(shift);
1341 }
1342}
1343
Richard Henderson14ab1632009-12-11 11:51:45 -08001344/* MSKBL, MSKWL, MSKLL, MSKQL */
Richard Hendersonffec44f2009-12-11 11:58:29 -08001345static void gen_msk_l(int ra, int rb, int rc, int islit,
1346 uint8_t lit, uint8_t byte_mask)
Richard Henderson14ab1632009-12-11 11:51:45 -08001347{
1348 if (unlikely(rc == 31))
1349 return;
1350 else if (unlikely(ra == 31))
1351 tcg_gen_movi_i64(cpu_ir[rc], 0);
1352 else if (islit) {
1353 gen_zapnoti (cpu_ir[rc], cpu_ir[ra], ~(byte_mask << (lit & 7)));
1354 } else {
1355 TCGv shift = tcg_temp_new();
1356 TCGv mask = tcg_temp_new();
1357
1358 tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1359 tcg_gen_shli_i64(shift, shift, 3);
1360 tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
1361 tcg_gen_shl_i64(mask, mask, shift);
1362
1363 tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], mask);
1364
1365 tcg_temp_free(mask);
1366 tcg_temp_free(shift);
1367 }
1368}
1369
aurel3204acd302008-09-18 13:45:14 +00001370/* Code to call arith3 helpers */
pbrooka7812ae2008-11-17 14:43:54 +00001371#define ARITH3(name) \
Blue Swirl636aa202009-08-16 09:06:54 +00001372static inline void glue(gen_, name)(int ra, int rb, int rc, int islit,\
1373 uint8_t lit) \
pbrooka7812ae2008-11-17 14:43:54 +00001374{ \
1375 if (unlikely(rc == 31)) \
1376 return; \
1377 \
1378 if (ra != 31) { \
1379 if (islit) { \
1380 TCGv tmp = tcg_const_i64(lit); \
1381 gen_helper_ ## name(cpu_ir[rc], cpu_ir[ra], tmp); \
1382 tcg_temp_free(tmp); \
1383 } else \
1384 gen_helper_ ## name (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); \
1385 } else { \
1386 TCGv tmp1 = tcg_const_i64(0); \
1387 if (islit) { \
1388 TCGv tmp2 = tcg_const_i64(lit); \
1389 gen_helper_ ## name (cpu_ir[rc], tmp1, tmp2); \
1390 tcg_temp_free(tmp2); \
1391 } else \
1392 gen_helper_ ## name (cpu_ir[rc], tmp1, cpu_ir[rb]); \
1393 tcg_temp_free(tmp1); \
1394 } \
aurel32b3249f62008-09-17 22:04:52 +00001395}
pbrooka7812ae2008-11-17 14:43:54 +00001396ARITH3(cmpbge)
1397ARITH3(addlv)
1398ARITH3(sublv)
1399ARITH3(addqv)
1400ARITH3(subqv)
pbrooka7812ae2008-11-17 14:43:54 +00001401ARITH3(umulh)
1402ARITH3(mullv)
1403ARITH3(mulqv)
Richard Henderson13e4df92009-12-10 12:04:42 -08001404ARITH3(minub8)
1405ARITH3(minsb8)
1406ARITH3(minuw4)
1407ARITH3(minsw4)
1408ARITH3(maxub8)
1409ARITH3(maxsb8)
1410ARITH3(maxuw4)
1411ARITH3(maxsw4)
1412ARITH3(perr)
1413
1414#define MVIOP2(name) \
1415static inline void glue(gen_, name)(int rb, int rc) \
1416{ \
1417 if (unlikely(rc == 31)) \
1418 return; \
1419 if (unlikely(rb == 31)) \
1420 tcg_gen_movi_i64(cpu_ir[rc], 0); \
1421 else \
1422 gen_helper_ ## name (cpu_ir[rc], cpu_ir[rb]); \
1423}
1424MVIOP2(pklb)
1425MVIOP2(pkwb)
1426MVIOP2(unpkbl)
1427MVIOP2(unpkbw)
aurel32b3249f62008-09-17 22:04:52 +00001428
Richard Henderson9e059602010-03-16 13:04:34 -07001429static void gen_cmp(TCGCond cond, int ra, int rb, int rc,
1430 int islit, uint8_t lit)
aurel3201ff9cc2008-09-18 09:24:25 +00001431{
Richard Henderson9e059602010-03-16 13:04:34 -07001432 TCGv va, vb;
aurel3201ff9cc2008-09-18 09:24:25 +00001433
Richard Henderson9e059602010-03-16 13:04:34 -07001434 if (unlikely(rc == 31)) {
Richard Henderson13e4df92009-12-10 12:04:42 -08001435 return;
Richard Henderson9e059602010-03-16 13:04:34 -07001436 }
aurel3201ff9cc2008-09-18 09:24:25 +00001437
Richard Henderson9e059602010-03-16 13:04:34 -07001438 if (ra == 31) {
1439 va = tcg_const_i64(0);
1440 } else {
1441 va = cpu_ir[ra];
1442 }
1443 if (islit) {
1444 vb = tcg_const_i64(lit);
1445 } else {
1446 vb = cpu_ir[rb];
1447 }
aurel3201ff9cc2008-09-18 09:24:25 +00001448
Richard Henderson9e059602010-03-16 13:04:34 -07001449 tcg_gen_setcond_i64(cond, cpu_ir[rc], va, vb);
aurel3201ff9cc2008-09-18 09:24:25 +00001450
Richard Henderson9e059602010-03-16 13:04:34 -07001451 if (ra == 31) {
1452 tcg_temp_free(va);
1453 }
1454 if (islit) {
1455 tcg_temp_free(vb);
1456 }
aurel3201ff9cc2008-09-18 09:24:25 +00001457}
1458
Richard Hendersonac316ca2010-04-12 16:14:54 -07001459static void gen_rx(int ra, int set)
1460{
1461 TCGv_i32 tmp;
1462
1463 if (ra != 31) {
1464 tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, offsetof(CPUState, intr_flag));
1465 }
1466
1467 tmp = tcg_const_i32(set);
1468 tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUState, intr_flag));
1469 tcg_temp_free_i32(tmp);
1470}
1471
Richard Henderson2ace7e52011-05-23 13:09:00 -07001472static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
1473{
1474 /* We're emulating OSF/1 PALcode. Many of these are trivial access
1475 to internal cpu registers. */
1476
1477 /* Unprivileged PAL call */
1478 if (palcode >= 0x80 && palcode < 0xC0) {
1479 switch (palcode) {
1480 case 0x86:
1481 /* IMB */
1482 /* No-op inside QEMU. */
1483 break;
1484 case 0x9E:
1485 /* RDUNIQUE */
1486 tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_unique);
1487 break;
1488 case 0x9F:
1489 /* WRUNIQUE */
1490 tcg_gen_mov_i64(cpu_unique, cpu_ir[IR_A0]);
1491 break;
1492 default:
1493 return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0xbf);
1494 }
1495 return NO_EXIT;
1496 }
1497
1498#ifndef CONFIG_USER_ONLY
1499 /* Privileged PAL code */
1500 if (palcode < 0x40 && (ctx->tb->flags & TB_FLAGS_USER_MODE) == 0) {
1501 switch (palcode) {
1502 case 0x01:
1503 /* CFLUSH */
1504 /* No-op inside QEMU. */
1505 break;
1506 case 0x02:
1507 /* DRAINA */
1508 /* No-op inside QEMU. */
1509 break;
1510 case 0x2D:
1511 /* WRVPTPTR */
1512 tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env, offsetof(CPUState, vptptr));
1513 break;
1514 case 0x31:
1515 /* WRVAL */
1516 tcg_gen_mov_i64(cpu_sysval, cpu_ir[IR_A0]);
1517 break;
1518 case 0x32:
1519 /* RDVAL */
1520 tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_sysval);
1521 break;
1522
1523 case 0x35: {
1524 /* SWPIPL */
1525 TCGv tmp;
1526
1527 /* Note that we already know we're in kernel mode, so we know
1528 that PS only contains the 3 IPL bits. */
1529 tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env, offsetof(CPUState, ps));
1530
1531 /* But make sure and store only the 3 IPL bits from the user. */
1532 tmp = tcg_temp_new();
1533 tcg_gen_andi_i64(tmp, cpu_ir[IR_A0], PS_INT_MASK);
1534 tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUState, ps));
1535 tcg_temp_free(tmp);
1536 break;
1537 }
1538
1539 case 0x36:
1540 /* RDPS */
1541 tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env, offsetof(CPUState, ps));
1542 break;
1543 case 0x38:
1544 /* WRUSP */
1545 tcg_gen_mov_i64(cpu_usp, cpu_ir[IR_A0]);
1546 break;
1547 case 0x3A:
1548 /* RDUSP */
1549 tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_usp);
1550 break;
1551 case 0x3C:
1552 /* WHAMI */
1553 tcg_gen_ld32s_i64(cpu_ir[IR_V0], cpu_env,
1554 offsetof(CPUState, cpu_index));
1555 break;
1556
1557 default:
1558 return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0x3f);
1559 }
1560 return NO_EXIT;
1561 }
1562#endif
1563
1564 return gen_invalid(ctx);
1565}
1566
Richard Henderson26b46092011-05-23 12:12:29 -07001567#ifndef CONFIG_USER_ONLY
1568
1569#define PR_BYTE 0x100000
1570#define PR_LONG 0x200000
1571
1572static int cpu_pr_data(int pr)
1573{
1574 switch (pr) {
1575 case 0: return offsetof(CPUAlphaState, ps) | PR_BYTE;
1576 case 1: return offsetof(CPUAlphaState, fen) | PR_BYTE;
1577 case 2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
1578 case 3: return offsetof(CPUAlphaState, trap_arg0);
1579 case 4: return offsetof(CPUAlphaState, trap_arg1);
1580 case 5: return offsetof(CPUAlphaState, trap_arg2);
1581 case 6: return offsetof(CPUAlphaState, exc_addr);
1582 case 7: return offsetof(CPUAlphaState, palbr);
1583 case 8: return offsetof(CPUAlphaState, ptbr);
1584 case 9: return offsetof(CPUAlphaState, vptptr);
1585 case 10: return offsetof(CPUAlphaState, unique);
1586 case 11: return offsetof(CPUAlphaState, sysval);
1587 case 12: return offsetof(CPUAlphaState, usp);
1588
1589 case 32 ... 39:
1590 return offsetof(CPUAlphaState, shadow[pr - 32]);
1591 case 40 ... 63:
1592 return offsetof(CPUAlphaState, scratch[pr - 40]);
Richard Hendersonc781cf92011-04-28 10:40:08 -07001593
1594 case 251:
1595 return offsetof(CPUAlphaState, alarm_expire);
Richard Henderson26b46092011-05-23 12:12:29 -07001596 }
1597 return 0;
1598}
1599
Richard Hendersonc781cf92011-04-28 10:40:08 -07001600static ExitStatus gen_mfpr(int ra, int regno)
Richard Henderson26b46092011-05-23 12:12:29 -07001601{
1602 int data = cpu_pr_data(regno);
1603
1604 /* In our emulated PALcode, these processor registers have no
1605 side effects from reading. */
1606 if (ra == 31) {
Richard Hendersonc781cf92011-04-28 10:40:08 -07001607 return NO_EXIT;
1608 }
1609
1610 if (regno == 250) {
1611 /* WALL_TIME */
1612 if (use_icount) {
1613 gen_io_start();
1614 gen_helper_get_time(cpu_ir[ra]);
1615 gen_io_end();
1616 return EXIT_PC_STALE;
1617 } else {
1618 gen_helper_get_time(cpu_ir[ra]);
1619 return NO_EXIT;
1620 }
Richard Henderson26b46092011-05-23 12:12:29 -07001621 }
1622
1623 /* The basic registers are data only, and unknown registers
1624 are read-zero, write-ignore. */
1625 if (data == 0) {
1626 tcg_gen_movi_i64(cpu_ir[ra], 0);
1627 } else if (data & PR_BYTE) {
1628 tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, data & ~PR_BYTE);
1629 } else if (data & PR_LONG) {
1630 tcg_gen_ld32s_i64(cpu_ir[ra], cpu_env, data & ~PR_LONG);
1631 } else {
1632 tcg_gen_ld_i64(cpu_ir[ra], cpu_env, data);
1633 }
Richard Hendersonc781cf92011-04-28 10:40:08 -07001634 return NO_EXIT;
Richard Henderson26b46092011-05-23 12:12:29 -07001635}
1636
Richard Hendersonbc242702011-04-21 18:58:09 -07001637static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
Richard Henderson26b46092011-05-23 12:12:29 -07001638{
1639 TCGv tmp;
Richard Hendersonbc242702011-04-21 18:58:09 -07001640 int data;
Richard Henderson26b46092011-05-23 12:12:29 -07001641
1642 if (rb == 31) {
1643 tmp = tcg_const_i64(0);
1644 } else {
1645 tmp = cpu_ir[rb];
1646 }
1647
Richard Hendersonbc242702011-04-21 18:58:09 -07001648 switch (regno) {
1649 case 255:
Richard Henderson3b4fefd2011-04-18 20:01:20 -07001650 /* TBIA */
1651 gen_helper_tbia();
Richard Hendersonbc242702011-04-21 18:58:09 -07001652 break;
1653
1654 case 254:
Richard Henderson3b4fefd2011-04-18 20:01:20 -07001655 /* TBIS */
1656 gen_helper_tbis(tmp);
Richard Hendersonbc242702011-04-21 18:58:09 -07001657 break;
1658
1659 case 253:
1660 /* WAIT */
1661 tmp = tcg_const_i64(1);
1662 tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUState, halted));
1663 return gen_excp(ctx, EXCP_HLT, 0);
1664
Richard Henderson034ebc22011-04-27 09:22:52 -07001665 case 252:
1666 /* HALT */
1667 gen_helper_halt(tmp);
1668 return EXIT_PC_STALE;
1669
Richard Hendersonc781cf92011-04-28 10:40:08 -07001670 case 251:
1671 /* ALARM */
1672 gen_helper_set_alarm(tmp);
1673 break;
1674
Richard Hendersonbc242702011-04-21 18:58:09 -07001675 default:
Richard Henderson3b4fefd2011-04-18 20:01:20 -07001676 /* The basic registers are data only, and unknown registers
1677 are read-zero, write-ignore. */
Richard Hendersonbc242702011-04-21 18:58:09 -07001678 data = cpu_pr_data(regno);
Richard Henderson3b4fefd2011-04-18 20:01:20 -07001679 if (data != 0) {
1680 if (data & PR_BYTE) {
1681 tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE);
1682 } else if (data & PR_LONG) {
1683 tcg_gen_st32_i64(tmp, cpu_env, data & ~PR_LONG);
1684 } else {
1685 tcg_gen_st_i64(tmp, cpu_env, data);
1686 }
Richard Henderson26b46092011-05-23 12:12:29 -07001687 }
Richard Hendersonbc242702011-04-21 18:58:09 -07001688 break;
Richard Henderson26b46092011-05-23 12:12:29 -07001689 }
1690
1691 if (rb == 31) {
1692 tcg_temp_free(tmp);
1693 }
Richard Hendersonbc242702011-04-21 18:58:09 -07001694
1695 return NO_EXIT;
Richard Henderson26b46092011-05-23 12:12:29 -07001696}
1697#endif /* !USER_ONLY*/
1698
Richard Henderson4af70372010-03-16 15:10:49 -07001699static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
j_mayer4c9649a2007-04-05 06:58:33 +00001700{
1701 uint32_t palcode;
Michael S. Tsirkinefa64352011-06-14 20:06:06 +03001702 int32_t disp21, disp16;
1703#ifndef CONFIG_USER_ONLY
1704 int32_t disp12;
1705#endif
Blue Swirlf88fe4e2010-04-25 20:30:17 +00001706 uint16_t fn11;
Michael S. Tsirkinb6fb1472011-06-14 18:06:40 +03001707 uint8_t opc, ra, rb, rc, fpfn, fn7, islit, real_islit;
aurel32adf3c8b2008-09-18 09:17:13 +00001708 uint8_t lit;
Richard Henderson4af70372010-03-16 15:10:49 -07001709 ExitStatus ret;
j_mayer4c9649a2007-04-05 06:58:33 +00001710
1711 /* Decode all instruction fields */
1712 opc = insn >> 26;
1713 ra = (insn >> 21) & 0x1F;
1714 rb = (insn >> 16) & 0x1F;
1715 rc = insn & 0x1F;
Richard Henderson13e4df92009-12-10 12:04:42 -08001716 real_islit = islit = (insn >> 12) & 1;
aurel32dfaa8582008-09-18 10:11:26 +00001717 if (rb == 31 && !islit) {
1718 islit = 1;
1719 lit = 0;
1720 } else
1721 lit = (insn >> 13) & 0xFF;
j_mayer4c9649a2007-04-05 06:58:33 +00001722 palcode = insn & 0x03FFFFFF;
1723 disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
1724 disp16 = (int16_t)(insn & 0x0000FFFF);
Michael S. Tsirkinefa64352011-06-14 20:06:06 +03001725#ifndef CONFIG_USER_ONLY
j_mayer4c9649a2007-04-05 06:58:33 +00001726 disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20;
Michael S. Tsirkinefa64352011-06-14 20:06:06 +03001727#endif
j_mayer4c9649a2007-04-05 06:58:33 +00001728 fn11 = (insn >> 5) & 0x000007FF;
1729 fpfn = fn11 & 0x3F;
1730 fn7 = (insn >> 5) & 0x0000007F;
Richard Henderson806991d2009-12-10 12:54:04 -08001731 LOG_DISAS("opc %02x ra %2d rb %2d rc %2d disp16 %6d\n",
aliguorid12d51d2009-01-15 21:48:06 +00001732 opc, ra, rb, rc, disp16);
Richard Henderson806991d2009-12-10 12:54:04 -08001733
Richard Henderson4af70372010-03-16 15:10:49 -07001734 ret = NO_EXIT;
j_mayer4c9649a2007-04-05 06:58:33 +00001735 switch (opc) {
1736 case 0x00:
1737 /* CALL_PAL */
Richard Henderson2ace7e52011-05-23 13:09:00 -07001738 ret = gen_call_pal(ctx, palcode);
1739 break;
j_mayer4c9649a2007-04-05 06:58:33 +00001740 case 0x01:
1741 /* OPC01 */
1742 goto invalid_opc;
1743 case 0x02:
1744 /* OPC02 */
1745 goto invalid_opc;
1746 case 0x03:
1747 /* OPC03 */
1748 goto invalid_opc;
1749 case 0x04:
1750 /* OPC04 */
1751 goto invalid_opc;
1752 case 0x05:
1753 /* OPC05 */
1754 goto invalid_opc;
1755 case 0x06:
1756 /* OPC06 */
1757 goto invalid_opc;
1758 case 0x07:
1759 /* OPC07 */
1760 goto invalid_opc;
1761 case 0x08:
1762 /* LDA */
aurel321ef4ef42008-09-16 22:44:25 +00001763 if (likely(ra != 31)) {
aurel32496cb5b2008-09-04 04:35:40 +00001764 if (rb != 31)
aurel3237610352008-09-04 04:36:00 +00001765 tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16);
1766 else
1767 tcg_gen_movi_i64(cpu_ir[ra], disp16);
aurel32496cb5b2008-09-04 04:35:40 +00001768 }
j_mayer4c9649a2007-04-05 06:58:33 +00001769 break;
1770 case 0x09:
1771 /* LDAH */
aurel321ef4ef42008-09-16 22:44:25 +00001772 if (likely(ra != 31)) {
aurel32496cb5b2008-09-04 04:35:40 +00001773 if (rb != 31)
aurel3237610352008-09-04 04:36:00 +00001774 tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16 << 16);
1775 else
1776 tcg_gen_movi_i64(cpu_ir[ra], disp16 << 16);
aurel32496cb5b2008-09-04 04:35:40 +00001777 }
j_mayer4c9649a2007-04-05 06:58:33 +00001778 break;
1779 case 0x0A:
1780 /* LDBU */
Richard Hendersona18ad892011-05-23 12:30:22 -07001781 if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
1782 gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
1783 break;
1784 }
1785 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00001786 case 0x0B:
1787 /* LDQ_U */
aurel32f18cd222008-09-29 17:21:28 +00001788 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
j_mayer4c9649a2007-04-05 06:58:33 +00001789 break;
1790 case 0x0C:
1791 /* LDWU */
Richard Hendersona18ad892011-05-23 12:30:22 -07001792 if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
1793 gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
1794 break;
1795 }
1796 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00001797 case 0x0D:
1798 /* STW */
Richard Henderson6910b8f2010-04-07 15:42:26 -07001799 gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00001800 break;
1801 case 0x0E:
1802 /* STB */
Richard Henderson6910b8f2010-04-07 15:42:26 -07001803 gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00001804 break;
1805 case 0x0F:
1806 /* STQ_U */
Richard Henderson6910b8f2010-04-07 15:42:26 -07001807 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
j_mayer4c9649a2007-04-05 06:58:33 +00001808 break;
1809 case 0x10:
1810 switch (fn7) {
1811 case 0x00:
1812 /* ADDL */
aurel3230c71832008-09-16 22:44:10 +00001813 if (likely(rc != 31)) {
1814 if (ra != 31) {
1815 if (islit) {
1816 tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
1817 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
aurel32dfaa8582008-09-18 10:11:26 +00001818 } else {
aurel3230c71832008-09-16 22:44:10 +00001819 tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1820 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
aurel32dfaa8582008-09-18 10:11:26 +00001821 }
aurel3230c71832008-09-16 22:44:10 +00001822 } else {
1823 if (islit)
aurel32dfaa8582008-09-18 10:11:26 +00001824 tcg_gen_movi_i64(cpu_ir[rc], lit);
aurel3230c71832008-09-16 22:44:10 +00001825 else
aurel32dfaa8582008-09-18 10:11:26 +00001826 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00001827 }
1828 }
j_mayer4c9649a2007-04-05 06:58:33 +00001829 break;
1830 case 0x02:
1831 /* S4ADDL */
aurel3230c71832008-09-16 22:44:10 +00001832 if (likely(rc != 31)) {
1833 if (ra != 31) {
pbrooka7812ae2008-11-17 14:43:54 +00001834 TCGv tmp = tcg_temp_new();
aurel32dfaa8582008-09-18 10:11:26 +00001835 tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1836 if (islit)
1837 tcg_gen_addi_i64(tmp, tmp, lit);
1838 else
1839 tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
1840 tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1841 tcg_temp_free(tmp);
aurel3230c71832008-09-16 22:44:10 +00001842 } else {
1843 if (islit)
1844 tcg_gen_movi_i64(cpu_ir[rc], lit);
aurel3230c71832008-09-16 22:44:10 +00001845 else
aurel32dfaa8582008-09-18 10:11:26 +00001846 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00001847 }
1848 }
j_mayer4c9649a2007-04-05 06:58:33 +00001849 break;
1850 case 0x09:
1851 /* SUBL */
aurel3230c71832008-09-16 22:44:10 +00001852 if (likely(rc != 31)) {
1853 if (ra != 31) {
aurel32dfaa8582008-09-18 10:11:26 +00001854 if (islit)
aurel3230c71832008-09-16 22:44:10 +00001855 tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
aurel32dfaa8582008-09-18 10:11:26 +00001856 else
aurel3230c71832008-09-16 22:44:10 +00001857 tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
aurel32dfaa8582008-09-18 10:11:26 +00001858 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
aurel3230c71832008-09-16 22:44:10 +00001859 } else {
1860 if (islit)
1861 tcg_gen_movi_i64(cpu_ir[rc], -lit);
aurel32dfaa8582008-09-18 10:11:26 +00001862 else {
aurel3230c71832008-09-16 22:44:10 +00001863 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
1864 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
aurel3230c71832008-09-16 22:44:10 +00001865 }
1866 }
j_mayer4c9649a2007-04-05 06:58:33 +00001867 break;
1868 case 0x0B:
1869 /* S4SUBL */
aurel3230c71832008-09-16 22:44:10 +00001870 if (likely(rc != 31)) {
1871 if (ra != 31) {
pbrooka7812ae2008-11-17 14:43:54 +00001872 TCGv tmp = tcg_temp_new();
aurel32dfaa8582008-09-18 10:11:26 +00001873 tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1874 if (islit)
1875 tcg_gen_subi_i64(tmp, tmp, lit);
1876 else
1877 tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
1878 tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1879 tcg_temp_free(tmp);
aurel3230c71832008-09-16 22:44:10 +00001880 } else {
1881 if (islit)
1882 tcg_gen_movi_i64(cpu_ir[rc], -lit);
aurel32dfaa8582008-09-18 10:11:26 +00001883 else {
aurel3230c71832008-09-16 22:44:10 +00001884 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
1885 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
aurel32dfaa8582008-09-18 10:11:26 +00001886 }
aurel3230c71832008-09-16 22:44:10 +00001887 }
1888 }
j_mayer4c9649a2007-04-05 06:58:33 +00001889 break;
1890 case 0x0F:
1891 /* CMPBGE */
pbrooka7812ae2008-11-17 14:43:54 +00001892 gen_cmpbge(ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00001893 break;
1894 case 0x12:
1895 /* S8ADDL */
aurel3230c71832008-09-16 22:44:10 +00001896 if (likely(rc != 31)) {
1897 if (ra != 31) {
pbrooka7812ae2008-11-17 14:43:54 +00001898 TCGv tmp = tcg_temp_new();
aurel32dfaa8582008-09-18 10:11:26 +00001899 tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
1900 if (islit)
1901 tcg_gen_addi_i64(tmp, tmp, lit);
1902 else
1903 tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
1904 tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1905 tcg_temp_free(tmp);
aurel3230c71832008-09-16 22:44:10 +00001906 } else {
1907 if (islit)
1908 tcg_gen_movi_i64(cpu_ir[rc], lit);
aurel3230c71832008-09-16 22:44:10 +00001909 else
aurel32dfaa8582008-09-18 10:11:26 +00001910 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00001911 }
1912 }
j_mayer4c9649a2007-04-05 06:58:33 +00001913 break;
1914 case 0x1B:
1915 /* S8SUBL */
aurel3230c71832008-09-16 22:44:10 +00001916 if (likely(rc != 31)) {
1917 if (ra != 31) {
pbrooka7812ae2008-11-17 14:43:54 +00001918 TCGv tmp = tcg_temp_new();
aurel32dfaa8582008-09-18 10:11:26 +00001919 tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
1920 if (islit)
1921 tcg_gen_subi_i64(tmp, tmp, lit);
1922 else
1923 tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
1924 tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1925 tcg_temp_free(tmp);
aurel3230c71832008-09-16 22:44:10 +00001926 } else {
1927 if (islit)
1928 tcg_gen_movi_i64(cpu_ir[rc], -lit);
aurel32dfaa8582008-09-18 10:11:26 +00001929 else
aurel3230c71832008-09-16 22:44:10 +00001930 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
1931 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
aurel32dfaa8582008-09-18 10:11:26 +00001932 }
aurel3230c71832008-09-16 22:44:10 +00001933 }
1934 }
j_mayer4c9649a2007-04-05 06:58:33 +00001935 break;
1936 case 0x1D:
1937 /* CMPULT */
aurel3201ff9cc2008-09-18 09:24:25 +00001938 gen_cmp(TCG_COND_LTU, ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00001939 break;
1940 case 0x20:
1941 /* ADDQ */
aurel3230c71832008-09-16 22:44:10 +00001942 if (likely(rc != 31)) {
1943 if (ra != 31) {
1944 if (islit)
1945 tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
aurel3230c71832008-09-16 22:44:10 +00001946 else
aurel32dfaa8582008-09-18 10:11:26 +00001947 tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00001948 } else {
1949 if (islit)
1950 tcg_gen_movi_i64(cpu_ir[rc], lit);
aurel3230c71832008-09-16 22:44:10 +00001951 else
aurel32dfaa8582008-09-18 10:11:26 +00001952 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00001953 }
1954 }
j_mayer4c9649a2007-04-05 06:58:33 +00001955 break;
1956 case 0x22:
1957 /* S4ADDQ */
aurel3230c71832008-09-16 22:44:10 +00001958 if (likely(rc != 31)) {
1959 if (ra != 31) {
pbrooka7812ae2008-11-17 14:43:54 +00001960 TCGv tmp = tcg_temp_new();
aurel32dfaa8582008-09-18 10:11:26 +00001961 tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1962 if (islit)
1963 tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
1964 else
1965 tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
1966 tcg_temp_free(tmp);
aurel3230c71832008-09-16 22:44:10 +00001967 } else {
1968 if (islit)
1969 tcg_gen_movi_i64(cpu_ir[rc], lit);
aurel3230c71832008-09-16 22:44:10 +00001970 else
aurel32dfaa8582008-09-18 10:11:26 +00001971 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00001972 }
1973 }
j_mayer4c9649a2007-04-05 06:58:33 +00001974 break;
1975 case 0x29:
1976 /* SUBQ */
aurel3230c71832008-09-16 22:44:10 +00001977 if (likely(rc != 31)) {
1978 if (ra != 31) {
1979 if (islit)
1980 tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
aurel3230c71832008-09-16 22:44:10 +00001981 else
aurel32dfaa8582008-09-18 10:11:26 +00001982 tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00001983 } else {
1984 if (islit)
1985 tcg_gen_movi_i64(cpu_ir[rc], -lit);
aurel3230c71832008-09-16 22:44:10 +00001986 else
aurel32dfaa8582008-09-18 10:11:26 +00001987 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00001988 }
1989 }
j_mayer4c9649a2007-04-05 06:58:33 +00001990 break;
1991 case 0x2B:
1992 /* S4SUBQ */
aurel3230c71832008-09-16 22:44:10 +00001993 if (likely(rc != 31)) {
1994 if (ra != 31) {
pbrooka7812ae2008-11-17 14:43:54 +00001995 TCGv tmp = tcg_temp_new();
aurel32dfaa8582008-09-18 10:11:26 +00001996 tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1997 if (islit)
1998 tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
1999 else
2000 tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
2001 tcg_temp_free(tmp);
aurel3230c71832008-09-16 22:44:10 +00002002 } else {
2003 if (islit)
2004 tcg_gen_movi_i64(cpu_ir[rc], -lit);
aurel3230c71832008-09-16 22:44:10 +00002005 else
aurel32dfaa8582008-09-18 10:11:26 +00002006 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00002007 }
2008 }
j_mayer4c9649a2007-04-05 06:58:33 +00002009 break;
2010 case 0x2D:
2011 /* CMPEQ */
aurel3201ff9cc2008-09-18 09:24:25 +00002012 gen_cmp(TCG_COND_EQ, ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002013 break;
2014 case 0x32:
2015 /* S8ADDQ */
aurel3230c71832008-09-16 22:44:10 +00002016 if (likely(rc != 31)) {
2017 if (ra != 31) {
pbrooka7812ae2008-11-17 14:43:54 +00002018 TCGv tmp = tcg_temp_new();
aurel32dfaa8582008-09-18 10:11:26 +00002019 tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
2020 if (islit)
2021 tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
2022 else
2023 tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
2024 tcg_temp_free(tmp);
aurel3230c71832008-09-16 22:44:10 +00002025 } else {
2026 if (islit)
2027 tcg_gen_movi_i64(cpu_ir[rc], lit);
aurel3230c71832008-09-16 22:44:10 +00002028 else
aurel32dfaa8582008-09-18 10:11:26 +00002029 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00002030 }
2031 }
j_mayer4c9649a2007-04-05 06:58:33 +00002032 break;
2033 case 0x3B:
2034 /* S8SUBQ */
aurel3230c71832008-09-16 22:44:10 +00002035 if (likely(rc != 31)) {
2036 if (ra != 31) {
pbrooka7812ae2008-11-17 14:43:54 +00002037 TCGv tmp = tcg_temp_new();
aurel32dfaa8582008-09-18 10:11:26 +00002038 tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
2039 if (islit)
2040 tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
2041 else
2042 tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
2043 tcg_temp_free(tmp);
aurel3230c71832008-09-16 22:44:10 +00002044 } else {
2045 if (islit)
2046 tcg_gen_movi_i64(cpu_ir[rc], -lit);
aurel3230c71832008-09-16 22:44:10 +00002047 else
aurel32dfaa8582008-09-18 10:11:26 +00002048 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00002049 }
2050 }
j_mayer4c9649a2007-04-05 06:58:33 +00002051 break;
2052 case 0x3D:
2053 /* CMPULE */
aurel3201ff9cc2008-09-18 09:24:25 +00002054 gen_cmp(TCG_COND_LEU, ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002055 break;
2056 case 0x40:
2057 /* ADDL/V */
pbrooka7812ae2008-11-17 14:43:54 +00002058 gen_addlv(ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002059 break;
2060 case 0x49:
2061 /* SUBL/V */
pbrooka7812ae2008-11-17 14:43:54 +00002062 gen_sublv(ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002063 break;
2064 case 0x4D:
2065 /* CMPLT */
aurel3201ff9cc2008-09-18 09:24:25 +00002066 gen_cmp(TCG_COND_LT, ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002067 break;
2068 case 0x60:
2069 /* ADDQ/V */
pbrooka7812ae2008-11-17 14:43:54 +00002070 gen_addqv(ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002071 break;
2072 case 0x69:
2073 /* SUBQ/V */
pbrooka7812ae2008-11-17 14:43:54 +00002074 gen_subqv(ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002075 break;
2076 case 0x6D:
2077 /* CMPLE */
aurel3201ff9cc2008-09-18 09:24:25 +00002078 gen_cmp(TCG_COND_LE, ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002079 break;
2080 default:
2081 goto invalid_opc;
2082 }
2083 break;
2084 case 0x11:
2085 switch (fn7) {
2086 case 0x00:
2087 /* AND */
aurel3230c71832008-09-16 22:44:10 +00002088 if (likely(rc != 31)) {
aurel32dfaa8582008-09-18 10:11:26 +00002089 if (ra == 31)
aurel3230c71832008-09-16 22:44:10 +00002090 tcg_gen_movi_i64(cpu_ir[rc], 0);
2091 else if (islit)
2092 tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], lit);
2093 else
2094 tcg_gen_and_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2095 }
j_mayer4c9649a2007-04-05 06:58:33 +00002096 break;
2097 case 0x08:
2098 /* BIC */
aurel3230c71832008-09-16 22:44:10 +00002099 if (likely(rc != 31)) {
2100 if (ra != 31) {
2101 if (islit)
2102 tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
aurel321b581c42008-10-21 11:29:11 +00002103 else
2104 tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00002105 } else
2106 tcg_gen_movi_i64(cpu_ir[rc], 0);
2107 }
j_mayer4c9649a2007-04-05 06:58:33 +00002108 break;
2109 case 0x14:
2110 /* CMOVLBS */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002111 gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 1);
j_mayer4c9649a2007-04-05 06:58:33 +00002112 break;
2113 case 0x16:
2114 /* CMOVLBC */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002115 gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
j_mayer4c9649a2007-04-05 06:58:33 +00002116 break;
2117 case 0x20:
2118 /* BIS */
aurel3230c71832008-09-16 22:44:10 +00002119 if (likely(rc != 31)) {
2120 if (ra != 31) {
2121 if (islit)
2122 tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], lit);
aurel328bb6e982008-09-30 06:45:44 +00002123 else
aurel3230c71832008-09-16 22:44:10 +00002124 tcg_gen_or_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
j_mayer4c9649a2007-04-05 06:58:33 +00002125 } else {
aurel3230c71832008-09-16 22:44:10 +00002126 if (islit)
2127 tcg_gen_movi_i64(cpu_ir[rc], lit);
aurel3230c71832008-09-16 22:44:10 +00002128 else
aurel32dfaa8582008-09-18 10:11:26 +00002129 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
j_mayer4c9649a2007-04-05 06:58:33 +00002130 }
j_mayer4c9649a2007-04-05 06:58:33 +00002131 }
2132 break;
2133 case 0x24:
2134 /* CMOVEQ */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002135 gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00002136 break;
2137 case 0x26:
2138 /* CMOVNE */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002139 gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00002140 break;
2141 case 0x28:
2142 /* ORNOT */
aurel3230c71832008-09-16 22:44:10 +00002143 if (likely(rc != 31)) {
aurel32dfaa8582008-09-18 10:11:26 +00002144 if (ra != 31) {
aurel3230c71832008-09-16 22:44:10 +00002145 if (islit)
2146 tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
aurel321b581c42008-10-21 11:29:11 +00002147 else
2148 tcg_gen_orc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00002149 } else {
2150 if (islit)
2151 tcg_gen_movi_i64(cpu_ir[rc], ~lit);
2152 else
2153 tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
2154 }
2155 }
j_mayer4c9649a2007-04-05 06:58:33 +00002156 break;
2157 case 0x40:
2158 /* XOR */
aurel3230c71832008-09-16 22:44:10 +00002159 if (likely(rc != 31)) {
2160 if (ra != 31) {
2161 if (islit)
2162 tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], lit);
aurel3230c71832008-09-16 22:44:10 +00002163 else
aurel32dfaa8582008-09-18 10:11:26 +00002164 tcg_gen_xor_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00002165 } else {
2166 if (islit)
2167 tcg_gen_movi_i64(cpu_ir[rc], lit);
aurel3230c71832008-09-16 22:44:10 +00002168 else
aurel32dfaa8582008-09-18 10:11:26 +00002169 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00002170 }
2171 }
j_mayer4c9649a2007-04-05 06:58:33 +00002172 break;
2173 case 0x44:
2174 /* CMOVLT */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002175 gen_cmov(TCG_COND_LT, ra, rb, rc, islit, lit, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00002176 break;
2177 case 0x46:
2178 /* CMOVGE */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002179 gen_cmov(TCG_COND_GE, ra, rb, rc, islit, lit, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00002180 break;
2181 case 0x48:
2182 /* EQV */
aurel3230c71832008-09-16 22:44:10 +00002183 if (likely(rc != 31)) {
2184 if (ra != 31) {
2185 if (islit)
2186 tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
aurel321b581c42008-10-21 11:29:11 +00002187 else
2188 tcg_gen_eqv_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00002189 } else {
2190 if (islit)
2191 tcg_gen_movi_i64(cpu_ir[rc], ~lit);
aurel3230c71832008-09-16 22:44:10 +00002192 else
aurel32dfaa8582008-09-18 10:11:26 +00002193 tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
aurel3230c71832008-09-16 22:44:10 +00002194 }
2195 }
j_mayer4c9649a2007-04-05 06:58:33 +00002196 break;
2197 case 0x61:
2198 /* AMASK */
aurel32ae8ecd42008-09-16 22:44:02 +00002199 if (likely(rc != 31)) {
Richard Hendersona18ad892011-05-23 12:30:22 -07002200 uint64_t amask = ctx->tb->flags >> TB_FLAGS_AMASK_SHIFT;
2201
2202 if (islit) {
2203 tcg_gen_movi_i64(cpu_ir[rc], lit & ~amask);
2204 } else {
2205 tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[rb], ~amask);
aurel321a1f7db2009-04-10 21:27:48 +00002206 }
aurel32ae8ecd42008-09-16 22:44:02 +00002207 }
j_mayer4c9649a2007-04-05 06:58:33 +00002208 break;
2209 case 0x64:
2210 /* CMOVLE */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002211 gen_cmov(TCG_COND_LE, ra, rb, rc, islit, lit, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00002212 break;
2213 case 0x66:
2214 /* CMOVGT */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002215 gen_cmov(TCG_COND_GT, ra, rb, rc, islit, lit, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00002216 break;
2217 case 0x6C:
2218 /* IMPLVER */
aurel3237610352008-09-04 04:36:00 +00002219 if (rc != 31)
aurel3285790952009-04-10 21:27:31 +00002220 tcg_gen_movi_i64(cpu_ir[rc], ctx->env->implver);
j_mayer4c9649a2007-04-05 06:58:33 +00002221 break;
2222 default:
2223 goto invalid_opc;
2224 }
2225 break;
2226 case 0x12:
2227 switch (fn7) {
2228 case 0x02:
2229 /* MSKBL */
Richard Henderson14ab1632009-12-11 11:51:45 -08002230 gen_msk_l(ra, rb, rc, islit, lit, 0x01);
j_mayer4c9649a2007-04-05 06:58:33 +00002231 break;
2232 case 0x06:
2233 /* EXTBL */
Richard Henderson377a43b2009-12-10 14:00:18 -08002234 gen_ext_l(ra, rb, rc, islit, lit, 0x01);
j_mayer4c9649a2007-04-05 06:58:33 +00002235 break;
2236 case 0x0B:
2237 /* INSBL */
Richard Henderson248c42f2009-12-11 10:39:56 -08002238 gen_ins_l(ra, rb, rc, islit, lit, 0x01);
j_mayer4c9649a2007-04-05 06:58:33 +00002239 break;
2240 case 0x12:
2241 /* MSKWL */
Richard Henderson14ab1632009-12-11 11:51:45 -08002242 gen_msk_l(ra, rb, rc, islit, lit, 0x03);
j_mayer4c9649a2007-04-05 06:58:33 +00002243 break;
2244 case 0x16:
2245 /* EXTWL */
Richard Henderson377a43b2009-12-10 14:00:18 -08002246 gen_ext_l(ra, rb, rc, islit, lit, 0x03);
j_mayer4c9649a2007-04-05 06:58:33 +00002247 break;
2248 case 0x1B:
2249 /* INSWL */
Richard Henderson248c42f2009-12-11 10:39:56 -08002250 gen_ins_l(ra, rb, rc, islit, lit, 0x03);
j_mayer4c9649a2007-04-05 06:58:33 +00002251 break;
2252 case 0x22:
2253 /* MSKLL */
Richard Henderson14ab1632009-12-11 11:51:45 -08002254 gen_msk_l(ra, rb, rc, islit, lit, 0x0f);
j_mayer4c9649a2007-04-05 06:58:33 +00002255 break;
2256 case 0x26:
2257 /* EXTLL */
Richard Henderson377a43b2009-12-10 14:00:18 -08002258 gen_ext_l(ra, rb, rc, islit, lit, 0x0f);
j_mayer4c9649a2007-04-05 06:58:33 +00002259 break;
2260 case 0x2B:
2261 /* INSLL */
Richard Henderson248c42f2009-12-11 10:39:56 -08002262 gen_ins_l(ra, rb, rc, islit, lit, 0x0f);
j_mayer4c9649a2007-04-05 06:58:33 +00002263 break;
2264 case 0x30:
2265 /* ZAP */
pbrooka7812ae2008-11-17 14:43:54 +00002266 gen_zap(ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002267 break;
2268 case 0x31:
2269 /* ZAPNOT */
pbrooka7812ae2008-11-17 14:43:54 +00002270 gen_zapnot(ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002271 break;
2272 case 0x32:
2273 /* MSKQL */
Richard Henderson14ab1632009-12-11 11:51:45 -08002274 gen_msk_l(ra, rb, rc, islit, lit, 0xff);
j_mayer4c9649a2007-04-05 06:58:33 +00002275 break;
2276 case 0x34:
2277 /* SRL */
aurel3230c71832008-09-16 22:44:10 +00002278 if (likely(rc != 31)) {
2279 if (ra != 31) {
2280 if (islit)
2281 tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
aurel32dfaa8582008-09-18 10:11:26 +00002282 else {
pbrooka7812ae2008-11-17 14:43:54 +00002283 TCGv shift = tcg_temp_new();
aurel3230c71832008-09-16 22:44:10 +00002284 tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
2285 tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], shift);
2286 tcg_temp_free(shift);
aurel32dfaa8582008-09-18 10:11:26 +00002287 }
aurel3230c71832008-09-16 22:44:10 +00002288 } else
2289 tcg_gen_movi_i64(cpu_ir[rc], 0);
2290 }
j_mayer4c9649a2007-04-05 06:58:33 +00002291 break;
2292 case 0x36:
2293 /* EXTQL */
Richard Henderson377a43b2009-12-10 14:00:18 -08002294 gen_ext_l(ra, rb, rc, islit, lit, 0xff);
j_mayer4c9649a2007-04-05 06:58:33 +00002295 break;
2296 case 0x39:
2297 /* SLL */
aurel3230c71832008-09-16 22:44:10 +00002298 if (likely(rc != 31)) {
2299 if (ra != 31) {
2300 if (islit)
2301 tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
aurel32dfaa8582008-09-18 10:11:26 +00002302 else {
pbrooka7812ae2008-11-17 14:43:54 +00002303 TCGv shift = tcg_temp_new();
aurel3230c71832008-09-16 22:44:10 +00002304 tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
2305 tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], shift);
2306 tcg_temp_free(shift);
aurel32dfaa8582008-09-18 10:11:26 +00002307 }
aurel3230c71832008-09-16 22:44:10 +00002308 } else
2309 tcg_gen_movi_i64(cpu_ir[rc], 0);
2310 }
j_mayer4c9649a2007-04-05 06:58:33 +00002311 break;
2312 case 0x3B:
2313 /* INSQL */
Richard Henderson248c42f2009-12-11 10:39:56 -08002314 gen_ins_l(ra, rb, rc, islit, lit, 0xff);
j_mayer4c9649a2007-04-05 06:58:33 +00002315 break;
2316 case 0x3C:
2317 /* SRA */
aurel3230c71832008-09-16 22:44:10 +00002318 if (likely(rc != 31)) {
2319 if (ra != 31) {
2320 if (islit)
2321 tcg_gen_sari_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
aurel32dfaa8582008-09-18 10:11:26 +00002322 else {
pbrooka7812ae2008-11-17 14:43:54 +00002323 TCGv shift = tcg_temp_new();
aurel3230c71832008-09-16 22:44:10 +00002324 tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
2325 tcg_gen_sar_i64(cpu_ir[rc], cpu_ir[ra], shift);
2326 tcg_temp_free(shift);
aurel32dfaa8582008-09-18 10:11:26 +00002327 }
aurel3230c71832008-09-16 22:44:10 +00002328 } else
2329 tcg_gen_movi_i64(cpu_ir[rc], 0);
2330 }
j_mayer4c9649a2007-04-05 06:58:33 +00002331 break;
2332 case 0x52:
2333 /* MSKWH */
Richard Hendersonffec44f2009-12-11 11:58:29 -08002334 gen_msk_h(ra, rb, rc, islit, lit, 0x03);
j_mayer4c9649a2007-04-05 06:58:33 +00002335 break;
2336 case 0x57:
2337 /* INSWH */
Richard Henderson50eb6e52009-12-11 16:31:29 -08002338 gen_ins_h(ra, rb, rc, islit, lit, 0x03);
j_mayer4c9649a2007-04-05 06:58:33 +00002339 break;
2340 case 0x5A:
2341 /* EXTWH */
Richard Henderson377a43b2009-12-10 14:00:18 -08002342 gen_ext_h(ra, rb, rc, islit, lit, 0x03);
j_mayer4c9649a2007-04-05 06:58:33 +00002343 break;
2344 case 0x62:
2345 /* MSKLH */
Richard Hendersonffec44f2009-12-11 11:58:29 -08002346 gen_msk_h(ra, rb, rc, islit, lit, 0x0f);
j_mayer4c9649a2007-04-05 06:58:33 +00002347 break;
2348 case 0x67:
2349 /* INSLH */
Richard Henderson50eb6e52009-12-11 16:31:29 -08002350 gen_ins_h(ra, rb, rc, islit, lit, 0x0f);
j_mayer4c9649a2007-04-05 06:58:33 +00002351 break;
2352 case 0x6A:
2353 /* EXTLH */
Richard Henderson377a43b2009-12-10 14:00:18 -08002354 gen_ext_h(ra, rb, rc, islit, lit, 0x0f);
j_mayer4c9649a2007-04-05 06:58:33 +00002355 break;
2356 case 0x72:
2357 /* MSKQH */
Richard Hendersonffec44f2009-12-11 11:58:29 -08002358 gen_msk_h(ra, rb, rc, islit, lit, 0xff);
j_mayer4c9649a2007-04-05 06:58:33 +00002359 break;
2360 case 0x77:
2361 /* INSQH */
Richard Henderson50eb6e52009-12-11 16:31:29 -08002362 gen_ins_h(ra, rb, rc, islit, lit, 0xff);
j_mayer4c9649a2007-04-05 06:58:33 +00002363 break;
2364 case 0x7A:
2365 /* EXTQH */
Richard Henderson377a43b2009-12-10 14:00:18 -08002366 gen_ext_h(ra, rb, rc, islit, lit, 0xff);
j_mayer4c9649a2007-04-05 06:58:33 +00002367 break;
2368 default:
2369 goto invalid_opc;
2370 }
2371 break;
2372 case 0x13:
2373 switch (fn7) {
2374 case 0x00:
2375 /* MULL */
aurel3230c71832008-09-16 22:44:10 +00002376 if (likely(rc != 31)) {
aurel32dfaa8582008-09-18 10:11:26 +00002377 if (ra == 31)
aurel3230c71832008-09-16 22:44:10 +00002378 tcg_gen_movi_i64(cpu_ir[rc], 0);
2379 else {
2380 if (islit)
2381 tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
2382 else
2383 tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2384 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
2385 }
2386 }
j_mayer4c9649a2007-04-05 06:58:33 +00002387 break;
2388 case 0x20:
2389 /* MULQ */
aurel3230c71832008-09-16 22:44:10 +00002390 if (likely(rc != 31)) {
aurel32dfaa8582008-09-18 10:11:26 +00002391 if (ra == 31)
aurel3230c71832008-09-16 22:44:10 +00002392 tcg_gen_movi_i64(cpu_ir[rc], 0);
2393 else if (islit)
2394 tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
2395 else
2396 tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2397 }
j_mayer4c9649a2007-04-05 06:58:33 +00002398 break;
2399 case 0x30:
2400 /* UMULH */
pbrooka7812ae2008-11-17 14:43:54 +00002401 gen_umulh(ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002402 break;
2403 case 0x40:
2404 /* MULL/V */
pbrooka7812ae2008-11-17 14:43:54 +00002405 gen_mullv(ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002406 break;
2407 case 0x60:
2408 /* MULQ/V */
pbrooka7812ae2008-11-17 14:43:54 +00002409 gen_mulqv(ra, rb, rc, islit, lit);
j_mayer4c9649a2007-04-05 06:58:33 +00002410 break;
2411 default:
2412 goto invalid_opc;
2413 }
2414 break;
2415 case 0x14:
Richard Hendersonf24518b2010-01-04 14:27:23 -08002416 switch (fpfn) { /* fn11 & 0x3F */
j_mayer4c9649a2007-04-05 06:58:33 +00002417 case 0x04:
2418 /* ITOFS */
Richard Hendersona18ad892011-05-23 12:30:22 -07002419 if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
j_mayer4c9649a2007-04-05 06:58:33 +00002420 goto invalid_opc;
Richard Hendersona18ad892011-05-23 12:30:22 -07002421 }
aurel32f18cd222008-09-29 17:21:28 +00002422 if (likely(rc != 31)) {
2423 if (ra != 31) {
pbrooka7812ae2008-11-17 14:43:54 +00002424 TCGv_i32 tmp = tcg_temp_new_i32();
aurel32f18cd222008-09-29 17:21:28 +00002425 tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
pbrooka7812ae2008-11-17 14:43:54 +00002426 gen_helper_memory_to_s(cpu_fir[rc], tmp);
2427 tcg_temp_free_i32(tmp);
aurel32f18cd222008-09-29 17:21:28 +00002428 } else
2429 tcg_gen_movi_i64(cpu_fir[rc], 0);
2430 }
j_mayer4c9649a2007-04-05 06:58:33 +00002431 break;
2432 case 0x0A:
2433 /* SQRTF */
Richard Hendersona18ad892011-05-23 12:30:22 -07002434 if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
2435 gen_fsqrtf(rb, rc);
2436 break;
2437 }
2438 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002439 case 0x0B:
2440 /* SQRTS */
Richard Hendersona18ad892011-05-23 12:30:22 -07002441 if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
2442 gen_fsqrts(ctx, rb, rc, fn11);
2443 break;
2444 }
2445 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002446 case 0x14:
2447 /* ITOFF */
Richard Hendersona18ad892011-05-23 12:30:22 -07002448 if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
j_mayer4c9649a2007-04-05 06:58:33 +00002449 goto invalid_opc;
Richard Hendersona18ad892011-05-23 12:30:22 -07002450 }
aurel32f18cd222008-09-29 17:21:28 +00002451 if (likely(rc != 31)) {
2452 if (ra != 31) {
pbrooka7812ae2008-11-17 14:43:54 +00002453 TCGv_i32 tmp = tcg_temp_new_i32();
aurel32f18cd222008-09-29 17:21:28 +00002454 tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
pbrooka7812ae2008-11-17 14:43:54 +00002455 gen_helper_memory_to_f(cpu_fir[rc], tmp);
2456 tcg_temp_free_i32(tmp);
aurel32f18cd222008-09-29 17:21:28 +00002457 } else
2458 tcg_gen_movi_i64(cpu_fir[rc], 0);
2459 }
j_mayer4c9649a2007-04-05 06:58:33 +00002460 break;
2461 case 0x24:
2462 /* ITOFT */
Richard Hendersona18ad892011-05-23 12:30:22 -07002463 if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
j_mayer4c9649a2007-04-05 06:58:33 +00002464 goto invalid_opc;
Richard Hendersona18ad892011-05-23 12:30:22 -07002465 }
aurel32f18cd222008-09-29 17:21:28 +00002466 if (likely(rc != 31)) {
2467 if (ra != 31)
2468 tcg_gen_mov_i64(cpu_fir[rc], cpu_ir[ra]);
2469 else
2470 tcg_gen_movi_i64(cpu_fir[rc], 0);
2471 }
j_mayer4c9649a2007-04-05 06:58:33 +00002472 break;
2473 case 0x2A:
2474 /* SQRTG */
Richard Hendersona18ad892011-05-23 12:30:22 -07002475 if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
2476 gen_fsqrtg(rb, rc);
2477 break;
2478 }
2479 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002480 case 0x02B:
2481 /* SQRTT */
Richard Hendersona18ad892011-05-23 12:30:22 -07002482 if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
2483 gen_fsqrtt(ctx, rb, rc, fn11);
2484 break;
2485 }
2486 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002487 default:
2488 goto invalid_opc;
2489 }
2490 break;
2491 case 0x15:
2492 /* VAX floating point */
2493 /* XXX: rounding mode and trap are ignored (!) */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002494 switch (fpfn) { /* fn11 & 0x3F */
j_mayer4c9649a2007-04-05 06:58:33 +00002495 case 0x00:
2496 /* ADDF */
pbrooka7812ae2008-11-17 14:43:54 +00002497 gen_faddf(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002498 break;
2499 case 0x01:
2500 /* SUBF */
pbrooka7812ae2008-11-17 14:43:54 +00002501 gen_fsubf(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002502 break;
2503 case 0x02:
2504 /* MULF */
pbrooka7812ae2008-11-17 14:43:54 +00002505 gen_fmulf(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002506 break;
2507 case 0x03:
2508 /* DIVF */
pbrooka7812ae2008-11-17 14:43:54 +00002509 gen_fdivf(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002510 break;
2511 case 0x1E:
2512 /* CVTDG */
2513#if 0 // TODO
pbrooka7812ae2008-11-17 14:43:54 +00002514 gen_fcvtdg(rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002515#else
2516 goto invalid_opc;
2517#endif
2518 break;
2519 case 0x20:
2520 /* ADDG */
pbrooka7812ae2008-11-17 14:43:54 +00002521 gen_faddg(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002522 break;
2523 case 0x21:
2524 /* SUBG */
pbrooka7812ae2008-11-17 14:43:54 +00002525 gen_fsubg(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002526 break;
2527 case 0x22:
2528 /* MULG */
pbrooka7812ae2008-11-17 14:43:54 +00002529 gen_fmulg(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002530 break;
2531 case 0x23:
2532 /* DIVG */
pbrooka7812ae2008-11-17 14:43:54 +00002533 gen_fdivg(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002534 break;
2535 case 0x25:
2536 /* CMPGEQ */
pbrooka7812ae2008-11-17 14:43:54 +00002537 gen_fcmpgeq(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002538 break;
2539 case 0x26:
2540 /* CMPGLT */
pbrooka7812ae2008-11-17 14:43:54 +00002541 gen_fcmpglt(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002542 break;
2543 case 0x27:
2544 /* CMPGLE */
pbrooka7812ae2008-11-17 14:43:54 +00002545 gen_fcmpgle(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002546 break;
2547 case 0x2C:
2548 /* CVTGF */
pbrooka7812ae2008-11-17 14:43:54 +00002549 gen_fcvtgf(rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002550 break;
2551 case 0x2D:
2552 /* CVTGD */
2553#if 0 // TODO
pbrooka7812ae2008-11-17 14:43:54 +00002554 gen_fcvtgd(rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002555#else
2556 goto invalid_opc;
2557#endif
2558 break;
2559 case 0x2F:
2560 /* CVTGQ */
pbrooka7812ae2008-11-17 14:43:54 +00002561 gen_fcvtgq(rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002562 break;
2563 case 0x3C:
2564 /* CVTQF */
pbrooka7812ae2008-11-17 14:43:54 +00002565 gen_fcvtqf(rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002566 break;
2567 case 0x3E:
2568 /* CVTQG */
pbrooka7812ae2008-11-17 14:43:54 +00002569 gen_fcvtqg(rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002570 break;
2571 default:
2572 goto invalid_opc;
2573 }
2574 break;
2575 case 0x16:
2576 /* IEEE floating-point */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002577 switch (fpfn) { /* fn11 & 0x3F */
j_mayer4c9649a2007-04-05 06:58:33 +00002578 case 0x00:
2579 /* ADDS */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002580 gen_fadds(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002581 break;
2582 case 0x01:
2583 /* SUBS */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002584 gen_fsubs(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002585 break;
2586 case 0x02:
2587 /* MULS */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002588 gen_fmuls(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002589 break;
2590 case 0x03:
2591 /* DIVS */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002592 gen_fdivs(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002593 break;
2594 case 0x20:
2595 /* ADDT */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002596 gen_faddt(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002597 break;
2598 case 0x21:
2599 /* SUBT */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002600 gen_fsubt(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002601 break;
2602 case 0x22:
2603 /* MULT */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002604 gen_fmult(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002605 break;
2606 case 0x23:
2607 /* DIVT */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002608 gen_fdivt(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002609 break;
2610 case 0x24:
2611 /* CMPTUN */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002612 gen_fcmptun(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002613 break;
2614 case 0x25:
2615 /* CMPTEQ */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002616 gen_fcmpteq(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002617 break;
2618 case 0x26:
2619 /* CMPTLT */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002620 gen_fcmptlt(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002621 break;
2622 case 0x27:
2623 /* CMPTLE */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002624 gen_fcmptle(ctx, ra, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002625 break;
2626 case 0x2C:
aurel32a74b4d22008-11-11 13:54:54 +00002627 if (fn11 == 0x2AC || fn11 == 0x6AC) {
j_mayer4c9649a2007-04-05 06:58:33 +00002628 /* CVTST */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002629 gen_fcvtst(ctx, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002630 } else {
2631 /* CVTTS */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002632 gen_fcvtts(ctx, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002633 }
2634 break;
2635 case 0x2F:
2636 /* CVTTQ */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002637 gen_fcvttq(ctx, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002638 break;
2639 case 0x3C:
2640 /* CVTQS */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002641 gen_fcvtqs(ctx, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002642 break;
2643 case 0x3E:
2644 /* CVTQT */
Richard Hendersonf24518b2010-01-04 14:27:23 -08002645 gen_fcvtqt(ctx, rb, rc, fn11);
j_mayer4c9649a2007-04-05 06:58:33 +00002646 break;
2647 default:
2648 goto invalid_opc;
2649 }
2650 break;
2651 case 0x17:
2652 switch (fn11) {
2653 case 0x010:
2654 /* CVTLQ */
pbrooka7812ae2008-11-17 14:43:54 +00002655 gen_fcvtlq(rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002656 break;
2657 case 0x020:
aurel32f18cd222008-09-29 17:21:28 +00002658 if (likely(rc != 31)) {
Richard Hendersona06d48d2009-12-11 13:21:02 -08002659 if (ra == rb) {
j_mayer4c9649a2007-04-05 06:58:33 +00002660 /* FMOV */
Richard Hendersona06d48d2009-12-11 13:21:02 -08002661 if (ra == 31)
2662 tcg_gen_movi_i64(cpu_fir[rc], 0);
2663 else
2664 tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[ra]);
2665 } else {
aurel32f18cd222008-09-29 17:21:28 +00002666 /* CPYS */
pbrooka7812ae2008-11-17 14:43:54 +00002667 gen_fcpys(ra, rb, rc);
Richard Hendersona06d48d2009-12-11 13:21:02 -08002668 }
j_mayer4c9649a2007-04-05 06:58:33 +00002669 }
2670 break;
2671 case 0x021:
2672 /* CPYSN */
pbrooka7812ae2008-11-17 14:43:54 +00002673 gen_fcpysn(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002674 break;
2675 case 0x022:
2676 /* CPYSE */
pbrooka7812ae2008-11-17 14:43:54 +00002677 gen_fcpyse(ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002678 break;
2679 case 0x024:
2680 /* MT_FPCR */
aurel32f18cd222008-09-29 17:21:28 +00002681 if (likely(ra != 31))
pbrooka7812ae2008-11-17 14:43:54 +00002682 gen_helper_store_fpcr(cpu_fir[ra]);
aurel32f18cd222008-09-29 17:21:28 +00002683 else {
2684 TCGv tmp = tcg_const_i64(0);
pbrooka7812ae2008-11-17 14:43:54 +00002685 gen_helper_store_fpcr(tmp);
aurel32f18cd222008-09-29 17:21:28 +00002686 tcg_temp_free(tmp);
2687 }
j_mayer4c9649a2007-04-05 06:58:33 +00002688 break;
2689 case 0x025:
2690 /* MF_FPCR */
aurel32f18cd222008-09-29 17:21:28 +00002691 if (likely(ra != 31))
pbrooka7812ae2008-11-17 14:43:54 +00002692 gen_helper_load_fpcr(cpu_fir[ra]);
j_mayer4c9649a2007-04-05 06:58:33 +00002693 break;
2694 case 0x02A:
2695 /* FCMOVEQ */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002696 gen_fcmov(TCG_COND_EQ, ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002697 break;
2698 case 0x02B:
2699 /* FCMOVNE */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002700 gen_fcmov(TCG_COND_NE, ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002701 break;
2702 case 0x02C:
2703 /* FCMOVLT */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002704 gen_fcmov(TCG_COND_LT, ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002705 break;
2706 case 0x02D:
2707 /* FCMOVGE */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002708 gen_fcmov(TCG_COND_GE, ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002709 break;
2710 case 0x02E:
2711 /* FCMOVLE */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002712 gen_fcmov(TCG_COND_LE, ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002713 break;
2714 case 0x02F:
2715 /* FCMOVGT */
Richard Hendersonbbe1dab2010-03-16 14:44:44 -07002716 gen_fcmov(TCG_COND_GT, ra, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002717 break;
2718 case 0x030:
2719 /* CVTQL */
pbrooka7812ae2008-11-17 14:43:54 +00002720 gen_fcvtql(rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002721 break;
2722 case 0x130:
2723 /* CVTQL/V */
j_mayer4c9649a2007-04-05 06:58:33 +00002724 case 0x530:
2725 /* CVTQL/SV */
Richard Henderson735cf452010-03-19 15:55:40 -07002726 /* ??? I'm pretty sure there's nothing that /sv needs to do that
2727 /v doesn't do. The only thing I can think is that /sv is a
2728 valid instruction merely for completeness in the ISA. */
2729 gen_fcvtql_v(ctx, rb, rc);
j_mayer4c9649a2007-04-05 06:58:33 +00002730 break;
2731 default:
2732 goto invalid_opc;
2733 }
2734 break;
2735 case 0x18:
2736 switch ((uint16_t)disp16) {
2737 case 0x0000:
2738 /* TRAPB */
Richard Henderson4af70372010-03-16 15:10:49 -07002739 /* No-op. */
j_mayer4c9649a2007-04-05 06:58:33 +00002740 break;
2741 case 0x0400:
2742 /* EXCB */
Richard Henderson4af70372010-03-16 15:10:49 -07002743 /* No-op. */
j_mayer4c9649a2007-04-05 06:58:33 +00002744 break;
2745 case 0x4000:
2746 /* MB */
2747 /* No-op */
2748 break;
2749 case 0x4400:
2750 /* WMB */
2751 /* No-op */
2752 break;
2753 case 0x8000:
2754 /* FETCH */
2755 /* No-op */
2756 break;
2757 case 0xA000:
2758 /* FETCH_M */
2759 /* No-op */
2760 break;
2761 case 0xC000:
2762 /* RPCC */
Richard Hendersona9406ea2011-09-22 08:11:18 -07002763 if (ra != 31) {
2764 if (use_icount) {
2765 gen_io_start();
2766 gen_helper_load_pcc(cpu_ir[ra]);
2767 gen_io_end();
2768 ret = EXIT_PC_STALE;
2769 } else {
2770 gen_helper_load_pcc(cpu_ir[ra]);
2771 }
2772 }
j_mayer4c9649a2007-04-05 06:58:33 +00002773 break;
2774 case 0xE000:
2775 /* RC */
Richard Hendersonac316ca2010-04-12 16:14:54 -07002776 gen_rx(ra, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00002777 break;
2778 case 0xE800:
2779 /* ECB */
j_mayer4c9649a2007-04-05 06:58:33 +00002780 break;
2781 case 0xF000:
2782 /* RS */
Richard Hendersonac316ca2010-04-12 16:14:54 -07002783 gen_rx(ra, 1);
j_mayer4c9649a2007-04-05 06:58:33 +00002784 break;
2785 case 0xF800:
2786 /* WH64 */
2787 /* No-op */
2788 break;
2789 default:
2790 goto invalid_opc;
2791 }
2792 break;
2793 case 0x19:
2794 /* HW_MFPR (PALcode) */
Richard Henderson26b46092011-05-23 12:12:29 -07002795#ifndef CONFIG_USER_ONLY
Richard Hendersona18ad892011-05-23 12:30:22 -07002796 if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
Richard Hendersonc781cf92011-04-28 10:40:08 -07002797 return gen_mfpr(ra, insn & 0xffff);
Richard Henderson26b46092011-05-23 12:12:29 -07002798 }
2799#endif
j_mayer4c9649a2007-04-05 06:58:33 +00002800 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002801 case 0x1A:
Richard Henderson49563a72010-03-29 10:48:14 -07002802 /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
2803 prediction stack action, which of course we don't implement. */
2804 if (rb != 31) {
aurel3237610352008-09-04 04:36:00 +00002805 tcg_gen_andi_i64(cpu_pc, cpu_ir[rb], ~3);
Richard Henderson49563a72010-03-29 10:48:14 -07002806 } else {
aurel3237610352008-09-04 04:36:00 +00002807 tcg_gen_movi_i64(cpu_pc, 0);
Richard Henderson49563a72010-03-29 10:48:14 -07002808 }
2809 if (ra != 31) {
aurel321304ca82008-11-06 09:16:57 +00002810 tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
Richard Henderson49563a72010-03-29 10:48:14 -07002811 }
Richard Henderson4af70372010-03-16 15:10:49 -07002812 ret = EXIT_PC_UPDATED;
j_mayer4c9649a2007-04-05 06:58:33 +00002813 break;
2814 case 0x1B:
2815 /* HW_LD (PALcode) */
Richard Hendersona18ad892011-05-23 12:30:22 -07002816#ifndef CONFIG_USER_ONLY
2817 if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
2818 TCGv addr;
2819
2820 if (ra == 31) {
2821 break;
2822 }
2823
2824 addr = tcg_temp_new();
aurel328bb6e982008-09-30 06:45:44 +00002825 if (rb != 31)
2826 tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
2827 else
2828 tcg_gen_movi_i64(addr, disp12);
2829 switch ((insn >> 12) & 0xF) {
2830 case 0x0:
aurel32b5d51022009-03-29 00:22:01 +00002831 /* Longword physical access (hw_ldl/p) */
Richard Henderson2374e732011-05-20 13:04:35 -07002832 gen_helper_ldl_phys(cpu_ir[ra], addr);
aurel328bb6e982008-09-30 06:45:44 +00002833 break;
2834 case 0x1:
aurel32b5d51022009-03-29 00:22:01 +00002835 /* Quadword physical access (hw_ldq/p) */
Richard Henderson2374e732011-05-20 13:04:35 -07002836 gen_helper_ldq_phys(cpu_ir[ra], addr);
aurel328bb6e982008-09-30 06:45:44 +00002837 break;
2838 case 0x2:
aurel32b5d51022009-03-29 00:22:01 +00002839 /* Longword physical access with lock (hw_ldl_l/p) */
Richard Henderson2374e732011-05-20 13:04:35 -07002840 gen_helper_ldl_l_phys(cpu_ir[ra], addr);
aurel328bb6e982008-09-30 06:45:44 +00002841 break;
2842 case 0x3:
aurel32b5d51022009-03-29 00:22:01 +00002843 /* Quadword physical access with lock (hw_ldq_l/p) */
Richard Henderson2374e732011-05-20 13:04:35 -07002844 gen_helper_ldq_l_phys(cpu_ir[ra], addr);
aurel328bb6e982008-09-30 06:45:44 +00002845 break;
2846 case 0x4:
aurel32b5d51022009-03-29 00:22:01 +00002847 /* Longword virtual PTE fetch (hw_ldl/v) */
Richard Henderson2374e732011-05-20 13:04:35 -07002848 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00002849 case 0x5:
aurel32b5d51022009-03-29 00:22:01 +00002850 /* Quadword virtual PTE fetch (hw_ldq/v) */
Richard Henderson2374e732011-05-20 13:04:35 -07002851 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00002852 break;
2853 case 0x6:
2854 /* Incpu_ir[ra]id */
aurel32b5d51022009-03-29 00:22:01 +00002855 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00002856 case 0x7:
2857 /* Incpu_ir[ra]id */
aurel32b5d51022009-03-29 00:22:01 +00002858 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00002859 case 0x8:
aurel32b5d51022009-03-29 00:22:01 +00002860 /* Longword virtual access (hw_ldl) */
Richard Henderson2374e732011-05-20 13:04:35 -07002861 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00002862 case 0x9:
aurel32b5d51022009-03-29 00:22:01 +00002863 /* Quadword virtual access (hw_ldq) */
Richard Henderson2374e732011-05-20 13:04:35 -07002864 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00002865 case 0xA:
aurel32b5d51022009-03-29 00:22:01 +00002866 /* Longword virtual access with protection check (hw_ldl/w) */
Richard Henderson84178452011-05-20 13:11:25 -07002867 tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_KERNEL_IDX);
aurel328bb6e982008-09-30 06:45:44 +00002868 break;
2869 case 0xB:
aurel32b5d51022009-03-29 00:22:01 +00002870 /* Quadword virtual access with protection check (hw_ldq/w) */
Richard Henderson84178452011-05-20 13:11:25 -07002871 tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_KERNEL_IDX);
aurel328bb6e982008-09-30 06:45:44 +00002872 break;
2873 case 0xC:
aurel32b5d51022009-03-29 00:22:01 +00002874 /* Longword virtual access with alt access mode (hw_ldl/a)*/
Richard Henderson2374e732011-05-20 13:04:35 -07002875 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00002876 case 0xD:
aurel32b5d51022009-03-29 00:22:01 +00002877 /* Quadword virtual access with alt access mode (hw_ldq/a) */
Richard Henderson2374e732011-05-20 13:04:35 -07002878 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00002879 case 0xE:
2880 /* Longword virtual access with alternate access mode and
Richard Henderson2374e732011-05-20 13:04:35 -07002881 protection checks (hw_ldl/wa) */
2882 tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_USER_IDX);
aurel328bb6e982008-09-30 06:45:44 +00002883 break;
2884 case 0xF:
2885 /* Quadword virtual access with alternate access mode and
Richard Henderson2374e732011-05-20 13:04:35 -07002886 protection checks (hw_ldq/wa) */
2887 tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_USER_IDX);
aurel328bb6e982008-09-30 06:45:44 +00002888 break;
2889 }
2890 tcg_temp_free(addr);
Richard Hendersona18ad892011-05-23 12:30:22 -07002891 break;
j_mayer4c9649a2007-04-05 06:58:33 +00002892 }
j_mayer4c9649a2007-04-05 06:58:33 +00002893#endif
Richard Hendersona18ad892011-05-23 12:30:22 -07002894 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002895 case 0x1C:
2896 switch (fn7) {
2897 case 0x00:
2898 /* SEXTB */
Richard Hendersona18ad892011-05-23 12:30:22 -07002899 if ((ctx->tb->flags & TB_FLAGS_AMASK_BWX) == 0) {
j_mayer4c9649a2007-04-05 06:58:33 +00002900 goto invalid_opc;
Richard Hendersona18ad892011-05-23 12:30:22 -07002901 }
aurel32ae8ecd42008-09-16 22:44:02 +00002902 if (likely(rc != 31)) {
2903 if (islit)
2904 tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int8_t)lit));
aurel32ae8ecd42008-09-16 22:44:02 +00002905 else
aurel32dfaa8582008-09-18 10:11:26 +00002906 tcg_gen_ext8s_i64(cpu_ir[rc], cpu_ir[rb]);
aurel32ae8ecd42008-09-16 22:44:02 +00002907 }
j_mayer4c9649a2007-04-05 06:58:33 +00002908 break;
2909 case 0x01:
2910 /* SEXTW */
Richard Hendersona18ad892011-05-23 12:30:22 -07002911 if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
2912 if (likely(rc != 31)) {
2913 if (islit) {
2914 tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int16_t)lit));
2915 } else {
2916 tcg_gen_ext16s_i64(cpu_ir[rc], cpu_ir[rb]);
2917 }
2918 }
2919 break;
aurel32ae8ecd42008-09-16 22:44:02 +00002920 }
Richard Hendersona18ad892011-05-23 12:30:22 -07002921 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002922 case 0x30:
2923 /* CTPOP */
Richard Hendersona18ad892011-05-23 12:30:22 -07002924 if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
2925 if (likely(rc != 31)) {
2926 if (islit) {
2927 tcg_gen_movi_i64(cpu_ir[rc], ctpop64(lit));
2928 } else {
2929 gen_helper_ctpop(cpu_ir[rc], cpu_ir[rb]);
2930 }
2931 }
2932 break;
aurel32ae8ecd42008-09-16 22:44:02 +00002933 }
Richard Hendersona18ad892011-05-23 12:30:22 -07002934 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002935 case 0x31:
2936 /* PERR */
Richard Hendersona18ad892011-05-23 12:30:22 -07002937 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2938 gen_perr(ra, rb, rc, islit, lit);
2939 break;
2940 }
2941 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002942 case 0x32:
2943 /* CTLZ */
Richard Hendersona18ad892011-05-23 12:30:22 -07002944 if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
2945 if (likely(rc != 31)) {
2946 if (islit) {
2947 tcg_gen_movi_i64(cpu_ir[rc], clz64(lit));
2948 } else {
2949 gen_helper_ctlz(cpu_ir[rc], cpu_ir[rb]);
2950 }
2951 }
2952 break;
aurel32ae8ecd42008-09-16 22:44:02 +00002953 }
Richard Hendersona18ad892011-05-23 12:30:22 -07002954 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002955 case 0x33:
2956 /* CTTZ */
Richard Hendersona18ad892011-05-23 12:30:22 -07002957 if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
2958 if (likely(rc != 31)) {
2959 if (islit) {
2960 tcg_gen_movi_i64(cpu_ir[rc], ctz64(lit));
2961 } else {
2962 gen_helper_cttz(cpu_ir[rc], cpu_ir[rb]);
2963 }
2964 }
2965 break;
aurel32ae8ecd42008-09-16 22:44:02 +00002966 }
Richard Hendersona18ad892011-05-23 12:30:22 -07002967 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002968 case 0x34:
2969 /* UNPKBW */
Richard Hendersona18ad892011-05-23 12:30:22 -07002970 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2971 if (real_islit || ra != 31) {
2972 goto invalid_opc;
2973 }
2974 gen_unpkbw(rb, rc);
2975 break;
2976 }
2977 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002978 case 0x35:
Richard Henderson13e4df92009-12-10 12:04:42 -08002979 /* UNPKBL */
Richard Hendersona18ad892011-05-23 12:30:22 -07002980 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2981 if (real_islit || ra != 31) {
2982 goto invalid_opc;
2983 }
2984 gen_unpkbl(rb, rc);
2985 break;
2986 }
2987 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002988 case 0x36:
2989 /* PKWB */
Richard Hendersona18ad892011-05-23 12:30:22 -07002990 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2991 if (real_islit || ra != 31) {
2992 goto invalid_opc;
2993 }
2994 gen_pkwb(rb, rc);
2995 break;
2996 }
2997 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00002998 case 0x37:
2999 /* PKLB */
Richard Hendersona18ad892011-05-23 12:30:22 -07003000 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
3001 if (real_islit || ra != 31) {
3002 goto invalid_opc;
3003 }
3004 gen_pklb(rb, rc);
3005 break;
3006 }
3007 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003008 case 0x38:
3009 /* MINSB8 */
Richard Hendersona18ad892011-05-23 12:30:22 -07003010 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
3011 gen_minsb8(ra, rb, rc, islit, lit);
3012 break;
3013 }
3014 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003015 case 0x39:
3016 /* MINSW4 */
Richard Hendersona18ad892011-05-23 12:30:22 -07003017 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
3018 gen_minsw4(ra, rb, rc, islit, lit);
3019 break;
3020 }
3021 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003022 case 0x3A:
3023 /* MINUB8 */
Richard Hendersona18ad892011-05-23 12:30:22 -07003024 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
3025 gen_minub8(ra, rb, rc, islit, lit);
3026 break;
3027 }
3028 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003029 case 0x3B:
3030 /* MINUW4 */
Richard Hendersona18ad892011-05-23 12:30:22 -07003031 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
3032 gen_minuw4(ra, rb, rc, islit, lit);
3033 break;
3034 }
3035 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003036 case 0x3C:
3037 /* MAXUB8 */
Richard Hendersona18ad892011-05-23 12:30:22 -07003038 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
3039 gen_maxub8(ra, rb, rc, islit, lit);
3040 break;
3041 }
3042 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003043 case 0x3D:
3044 /* MAXUW4 */
Richard Hendersona18ad892011-05-23 12:30:22 -07003045 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
3046 gen_maxuw4(ra, rb, rc, islit, lit);
3047 break;
3048 }
3049 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003050 case 0x3E:
3051 /* MAXSB8 */
Richard Hendersona18ad892011-05-23 12:30:22 -07003052 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
3053 gen_maxsb8(ra, rb, rc, islit, lit);
3054 break;
3055 }
3056 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003057 case 0x3F:
3058 /* MAXSW4 */
Richard Hendersona18ad892011-05-23 12:30:22 -07003059 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
3060 gen_maxsw4(ra, rb, rc, islit, lit);
3061 break;
3062 }
3063 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003064 case 0x70:
3065 /* FTOIT */
Richard Hendersona18ad892011-05-23 12:30:22 -07003066 if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
j_mayer4c9649a2007-04-05 06:58:33 +00003067 goto invalid_opc;
Richard Hendersona18ad892011-05-23 12:30:22 -07003068 }
aurel32f18cd222008-09-29 17:21:28 +00003069 if (likely(rc != 31)) {
3070 if (ra != 31)
3071 tcg_gen_mov_i64(cpu_ir[rc], cpu_fir[ra]);
3072 else
3073 tcg_gen_movi_i64(cpu_ir[rc], 0);
3074 }
j_mayer4c9649a2007-04-05 06:58:33 +00003075 break;
3076 case 0x78:
3077 /* FTOIS */
Richard Hendersona18ad892011-05-23 12:30:22 -07003078 if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
j_mayer4c9649a2007-04-05 06:58:33 +00003079 goto invalid_opc;
Richard Hendersona18ad892011-05-23 12:30:22 -07003080 }
aurel32f18cd222008-09-29 17:21:28 +00003081 if (rc != 31) {
pbrooka7812ae2008-11-17 14:43:54 +00003082 TCGv_i32 tmp1 = tcg_temp_new_i32();
aurel32f18cd222008-09-29 17:21:28 +00003083 if (ra != 31)
pbrooka7812ae2008-11-17 14:43:54 +00003084 gen_helper_s_to_memory(tmp1, cpu_fir[ra]);
aurel32f18cd222008-09-29 17:21:28 +00003085 else {
3086 TCGv tmp2 = tcg_const_i64(0);
pbrooka7812ae2008-11-17 14:43:54 +00003087 gen_helper_s_to_memory(tmp1, tmp2);
aurel32f18cd222008-09-29 17:21:28 +00003088 tcg_temp_free(tmp2);
3089 }
3090 tcg_gen_ext_i32_i64(cpu_ir[rc], tmp1);
pbrooka7812ae2008-11-17 14:43:54 +00003091 tcg_temp_free_i32(tmp1);
aurel32f18cd222008-09-29 17:21:28 +00003092 }
j_mayer4c9649a2007-04-05 06:58:33 +00003093 break;
3094 default:
3095 goto invalid_opc;
3096 }
3097 break;
3098 case 0x1D:
3099 /* HW_MTPR (PALcode) */
Richard Henderson26b46092011-05-23 12:12:29 -07003100#ifndef CONFIG_USER_ONLY
Richard Hendersona18ad892011-05-23 12:30:22 -07003101 if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
Richard Hendersonbc242702011-04-21 18:58:09 -07003102 return gen_mtpr(ctx, rb, insn & 0xffff);
Richard Henderson26b46092011-05-23 12:12:29 -07003103 }
3104#endif
j_mayer4c9649a2007-04-05 06:58:33 +00003105 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003106 case 0x1E:
Richard Henderson508b43e2011-05-20 13:21:15 -07003107 /* HW_RET (PALcode) */
Richard Hendersona18ad892011-05-23 12:30:22 -07003108#ifndef CONFIG_USER_ONLY
3109 if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
3110 if (rb == 31) {
3111 /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
3112 address from EXC_ADDR. This turns out to be useful for our
3113 emulation PALcode, so continue to accept it. */
3114 TCGv tmp = tcg_temp_new();
3115 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUState, exc_addr));
3116 gen_helper_hw_ret(tmp);
3117 tcg_temp_free(tmp);
3118 } else {
3119 gen_helper_hw_ret(cpu_ir[rb]);
3120 }
3121 ret = EXIT_PC_UPDATED;
3122 break;
j_mayer4c9649a2007-04-05 06:58:33 +00003123 }
j_mayer4c9649a2007-04-05 06:58:33 +00003124#endif
Richard Hendersona18ad892011-05-23 12:30:22 -07003125 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003126 case 0x1F:
3127 /* HW_ST (PALcode) */
Richard Hendersona18ad892011-05-23 12:30:22 -07003128#ifndef CONFIG_USER_ONLY
3129 if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
aurel328bb6e982008-09-30 06:45:44 +00003130 TCGv addr, val;
pbrooka7812ae2008-11-17 14:43:54 +00003131 addr = tcg_temp_new();
aurel328bb6e982008-09-30 06:45:44 +00003132 if (rb != 31)
3133 tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
3134 else
3135 tcg_gen_movi_i64(addr, disp12);
3136 if (ra != 31)
3137 val = cpu_ir[ra];
3138 else {
pbrooka7812ae2008-11-17 14:43:54 +00003139 val = tcg_temp_new();
aurel328bb6e982008-09-30 06:45:44 +00003140 tcg_gen_movi_i64(val, 0);
3141 }
3142 switch ((insn >> 12) & 0xF) {
3143 case 0x0:
3144 /* Longword physical access */
Richard Henderson2374e732011-05-20 13:04:35 -07003145 gen_helper_stl_phys(addr, val);
aurel328bb6e982008-09-30 06:45:44 +00003146 break;
3147 case 0x1:
3148 /* Quadword physical access */
Richard Henderson2374e732011-05-20 13:04:35 -07003149 gen_helper_stq_phys(addr, val);
aurel328bb6e982008-09-30 06:45:44 +00003150 break;
3151 case 0x2:
3152 /* Longword physical access with lock */
Richard Henderson2374e732011-05-20 13:04:35 -07003153 gen_helper_stl_c_phys(val, addr, val);
aurel328bb6e982008-09-30 06:45:44 +00003154 break;
3155 case 0x3:
3156 /* Quadword physical access with lock */
Richard Henderson2374e732011-05-20 13:04:35 -07003157 gen_helper_stq_c_phys(val, addr, val);
aurel328bb6e982008-09-30 06:45:44 +00003158 break;
3159 case 0x4:
3160 /* Longword virtual access */
Richard Henderson2374e732011-05-20 13:04:35 -07003161 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00003162 case 0x5:
3163 /* Quadword virtual access */
Richard Henderson2374e732011-05-20 13:04:35 -07003164 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00003165 case 0x6:
3166 /* Invalid */
3167 goto invalid_opc;
3168 case 0x7:
3169 /* Invalid */
3170 goto invalid_opc;
3171 case 0x8:
3172 /* Invalid */
3173 goto invalid_opc;
3174 case 0x9:
3175 /* Invalid */
3176 goto invalid_opc;
3177 case 0xA:
3178 /* Invalid */
3179 goto invalid_opc;
3180 case 0xB:
3181 /* Invalid */
3182 goto invalid_opc;
3183 case 0xC:
3184 /* Longword virtual access with alternate access mode */
Richard Henderson2374e732011-05-20 13:04:35 -07003185 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00003186 case 0xD:
3187 /* Quadword virtual access with alternate access mode */
Richard Henderson2374e732011-05-20 13:04:35 -07003188 goto invalid_opc;
aurel328bb6e982008-09-30 06:45:44 +00003189 case 0xE:
3190 /* Invalid */
3191 goto invalid_opc;
3192 case 0xF:
3193 /* Invalid */
3194 goto invalid_opc;
3195 }
aurel3245d46ce2009-03-29 00:14:06 +00003196 if (ra == 31)
aurel328bb6e982008-09-30 06:45:44 +00003197 tcg_temp_free(val);
3198 tcg_temp_free(addr);
Richard Hendersona18ad892011-05-23 12:30:22 -07003199 break;
j_mayer4c9649a2007-04-05 06:58:33 +00003200 }
j_mayer4c9649a2007-04-05 06:58:33 +00003201#endif
Richard Hendersona18ad892011-05-23 12:30:22 -07003202 goto invalid_opc;
j_mayer4c9649a2007-04-05 06:58:33 +00003203 case 0x20:
3204 /* LDF */
aurel32f18cd222008-09-29 17:21:28 +00003205 gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003206 break;
3207 case 0x21:
3208 /* LDG */
aurel32f18cd222008-09-29 17:21:28 +00003209 gen_load_mem(ctx, &gen_qemu_ldg, ra, rb, disp16, 1, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003210 break;
3211 case 0x22:
3212 /* LDS */
aurel32f18cd222008-09-29 17:21:28 +00003213 gen_load_mem(ctx, &gen_qemu_lds, ra, rb, disp16, 1, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003214 break;
3215 case 0x23:
3216 /* LDT */
aurel32f18cd222008-09-29 17:21:28 +00003217 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 1, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003218 break;
3219 case 0x24:
3220 /* STF */
Richard Henderson6910b8f2010-04-07 15:42:26 -07003221 gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003222 break;
3223 case 0x25:
3224 /* STG */
Richard Henderson6910b8f2010-04-07 15:42:26 -07003225 gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003226 break;
3227 case 0x26:
3228 /* STS */
Richard Henderson6910b8f2010-04-07 15:42:26 -07003229 gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003230 break;
3231 case 0x27:
3232 /* STT */
Richard Henderson6910b8f2010-04-07 15:42:26 -07003233 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003234 break;
3235 case 0x28:
3236 /* LDL */
aurel32f18cd222008-09-29 17:21:28 +00003237 gen_load_mem(ctx, &tcg_gen_qemu_ld32s, ra, rb, disp16, 0, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003238 break;
3239 case 0x29:
3240 /* LDQ */
aurel32f18cd222008-09-29 17:21:28 +00003241 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003242 break;
3243 case 0x2A:
3244 /* LDL_L */
aurel32f4ed8672008-09-30 06:45:34 +00003245 gen_load_mem(ctx, &gen_qemu_ldl_l, ra, rb, disp16, 0, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003246 break;
3247 case 0x2B:
3248 /* LDQ_L */
aurel32f4ed8672008-09-30 06:45:34 +00003249 gen_load_mem(ctx, &gen_qemu_ldq_l, ra, rb, disp16, 0, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003250 break;
3251 case 0x2C:
3252 /* STL */
Richard Henderson6910b8f2010-04-07 15:42:26 -07003253 gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003254 break;
3255 case 0x2D:
3256 /* STQ */
Richard Henderson6910b8f2010-04-07 15:42:26 -07003257 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003258 break;
3259 case 0x2E:
3260 /* STL_C */
Richard Henderson6910b8f2010-04-07 15:42:26 -07003261 ret = gen_store_conditional(ctx, ra, rb, disp16, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003262 break;
3263 case 0x2F:
3264 /* STQ_C */
Richard Henderson6910b8f2010-04-07 15:42:26 -07003265 ret = gen_store_conditional(ctx, ra, rb, disp16, 1);
j_mayer4c9649a2007-04-05 06:58:33 +00003266 break;
3267 case 0x30:
3268 /* BR */
Richard Henderson4af70372010-03-16 15:10:49 -07003269 ret = gen_bdirect(ctx, ra, disp21);
j_mayer4c9649a2007-04-05 06:58:33 +00003270 break;
pbrooka7812ae2008-11-17 14:43:54 +00003271 case 0x31: /* FBEQ */
Richard Henderson4af70372010-03-16 15:10:49 -07003272 ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
Richard Hendersondbb30fe2009-12-13 17:46:17 -08003273 break;
pbrooka7812ae2008-11-17 14:43:54 +00003274 case 0x32: /* FBLT */
Richard Henderson4af70372010-03-16 15:10:49 -07003275 ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
Richard Hendersondbb30fe2009-12-13 17:46:17 -08003276 break;
pbrooka7812ae2008-11-17 14:43:54 +00003277 case 0x33: /* FBLE */
Richard Henderson4af70372010-03-16 15:10:49 -07003278 ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
j_mayer4c9649a2007-04-05 06:58:33 +00003279 break;
3280 case 0x34:
3281 /* BSR */
Richard Henderson4af70372010-03-16 15:10:49 -07003282 ret = gen_bdirect(ctx, ra, disp21);
j_mayer4c9649a2007-04-05 06:58:33 +00003283 break;
pbrooka7812ae2008-11-17 14:43:54 +00003284 case 0x35: /* FBNE */
Richard Henderson4af70372010-03-16 15:10:49 -07003285 ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
Richard Hendersondbb30fe2009-12-13 17:46:17 -08003286 break;
pbrooka7812ae2008-11-17 14:43:54 +00003287 case 0x36: /* FBGE */
Richard Henderson4af70372010-03-16 15:10:49 -07003288 ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
Richard Hendersondbb30fe2009-12-13 17:46:17 -08003289 break;
pbrooka7812ae2008-11-17 14:43:54 +00003290 case 0x37: /* FBGT */
Richard Henderson4af70372010-03-16 15:10:49 -07003291 ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
j_mayer4c9649a2007-04-05 06:58:33 +00003292 break;
3293 case 0x38:
3294 /* BLBC */
Richard Henderson4af70372010-03-16 15:10:49 -07003295 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
j_mayer4c9649a2007-04-05 06:58:33 +00003296 break;
3297 case 0x39:
3298 /* BEQ */
Richard Henderson4af70372010-03-16 15:10:49 -07003299 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003300 break;
3301 case 0x3A:
3302 /* BLT */
Richard Henderson4af70372010-03-16 15:10:49 -07003303 ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003304 break;
3305 case 0x3B:
3306 /* BLE */
Richard Henderson4af70372010-03-16 15:10:49 -07003307 ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003308 break;
3309 case 0x3C:
3310 /* BLBS */
Richard Henderson4af70372010-03-16 15:10:49 -07003311 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
j_mayer4c9649a2007-04-05 06:58:33 +00003312 break;
3313 case 0x3D:
3314 /* BNE */
Richard Henderson4af70372010-03-16 15:10:49 -07003315 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003316 break;
3317 case 0x3E:
3318 /* BGE */
Richard Henderson4af70372010-03-16 15:10:49 -07003319 ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003320 break;
3321 case 0x3F:
3322 /* BGT */
Richard Henderson4af70372010-03-16 15:10:49 -07003323 ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003324 break;
3325 invalid_opc:
Richard Henderson8aa3fa22010-04-07 13:32:50 -07003326 ret = gen_invalid(ctx);
j_mayer4c9649a2007-04-05 06:58:33 +00003327 break;
3328 }
3329
3330 return ret;
3331}
3332
Blue Swirl636aa202009-08-16 09:06:54 +00003333static inline void gen_intermediate_code_internal(CPUState *env,
3334 TranslationBlock *tb,
3335 int search_pc)
j_mayer4c9649a2007-04-05 06:58:33 +00003336{
j_mayer4c9649a2007-04-05 06:58:33 +00003337 DisasContext ctx, *ctxp = &ctx;
3338 target_ulong pc_start;
3339 uint32_t insn;
3340 uint16_t *gen_opc_end;
aliguoria1d1bb32008-11-18 20:07:32 +00003341 CPUBreakpoint *bp;
j_mayer4c9649a2007-04-05 06:58:33 +00003342 int j, lj = -1;
Richard Henderson4af70372010-03-16 15:10:49 -07003343 ExitStatus ret;
pbrook2e70f6e2008-06-29 01:03:05 +00003344 int num_insns;
3345 int max_insns;
j_mayer4c9649a2007-04-05 06:58:33 +00003346
3347 pc_start = tb->pc;
j_mayer4c9649a2007-04-05 06:58:33 +00003348 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
Richard Henderson4af70372010-03-16 15:10:49 -07003349
3350 ctx.tb = tb;
3351 ctx.env = env;
j_mayer4c9649a2007-04-05 06:58:33 +00003352 ctx.pc = pc_start;
Richard Hendersonbba9bdc2011-05-20 14:14:44 -07003353 ctx.mem_idx = cpu_mmu_index(env);
Richard Hendersonf24518b2010-01-04 14:27:23 -08003354
3355 /* ??? Every TB begins with unset rounding mode, to be initialized on
3356 the first fp insn of the TB. Alternately we could define a proper
3357 default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure
3358 to reset the FP_STATUS to that default at the end of any TB that
3359 changes the default. We could even (gasp) dynamiclly figure out
3360 what default would be most efficient given the running program. */
3361 ctx.tb_rm = -1;
3362 /* Similarly for flush-to-zero. */
3363 ctx.tb_ftz = -1;
3364
pbrook2e70f6e2008-06-29 01:03:05 +00003365 num_insns = 0;
3366 max_insns = tb->cflags & CF_COUNT_MASK;
3367 if (max_insns == 0)
3368 max_insns = CF_COUNT_MASK;
3369
3370 gen_icount_start();
Richard Henderson4af70372010-03-16 15:10:49 -07003371 do {
Blue Swirl72cf2d42009-09-12 07:36:22 +00003372 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
3373 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
aliguoria1d1bb32008-11-18 20:07:32 +00003374 if (bp->pc == ctx.pc) {
j_mayer4c9649a2007-04-05 06:58:33 +00003375 gen_excp(&ctx, EXCP_DEBUG, 0);
3376 break;
3377 }
3378 }
3379 }
3380 if (search_pc) {
3381 j = gen_opc_ptr - gen_opc_buf;
3382 if (lj < j) {
3383 lj++;
3384 while (lj < j)
3385 gen_opc_instr_start[lj++] = 0;
j_mayer4c9649a2007-04-05 06:58:33 +00003386 }
aurel32ed1dda52009-03-29 01:04:39 +00003387 gen_opc_pc[lj] = ctx.pc;
3388 gen_opc_instr_start[lj] = 1;
3389 gen_opc_icount[lj] = num_insns;
j_mayer4c9649a2007-04-05 06:58:33 +00003390 }
pbrook2e70f6e2008-06-29 01:03:05 +00003391 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
3392 gen_io_start();
j_mayer4c9649a2007-04-05 06:58:33 +00003393 insn = ldl_code(ctx.pc);
pbrook2e70f6e2008-06-29 01:03:05 +00003394 num_insns++;
Richard Hendersonc4b3be32009-12-19 15:17:14 -08003395
3396 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
3397 tcg_gen_debug_insn_start(ctx.pc);
3398 }
3399
j_mayer4c9649a2007-04-05 06:58:33 +00003400 ctx.pc += 4;
3401 ret = translate_one(ctxp, insn);
Richard Henderson4af70372010-03-16 15:10:49 -07003402
Richard Hendersonbf1b03f2011-04-25 12:52:57 -07003403 /* If we reach a page boundary, are single stepping,
3404 or exhaust instruction count, stop generation. */
3405 if (ret == NO_EXIT
3406 && ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
3407 || gen_opc_ptr >= gen_opc_end
3408 || num_insns >= max_insns
3409 || singlestep
3410 || env->singlestep_enabled)) {
3411 ret = EXIT_PC_STALE;
aurel321b530a62009-04-05 20:08:59 +00003412 }
Richard Henderson4af70372010-03-16 15:10:49 -07003413 } while (ret == NO_EXIT);
aurel3219bf5172008-12-07 23:26:32 +00003414
Richard Henderson4af70372010-03-16 15:10:49 -07003415 if (tb->cflags & CF_LAST_IO) {
pbrook2e70f6e2008-06-29 01:03:05 +00003416 gen_io_end();
Richard Henderson4af70372010-03-16 15:10:49 -07003417 }
3418
3419 switch (ret) {
3420 case EXIT_GOTO_TB:
Richard Henderson8aa3fa22010-04-07 13:32:50 -07003421 case EXIT_NORETURN:
Richard Henderson4af70372010-03-16 15:10:49 -07003422 break;
3423 case EXIT_PC_STALE:
3424 tcg_gen_movi_i64(cpu_pc, ctx.pc);
3425 /* FALLTHRU */
3426 case EXIT_PC_UPDATED:
Richard Hendersonbf1b03f2011-04-25 12:52:57 -07003427 if (env->singlestep_enabled) {
3428 gen_excp_1(EXCP_DEBUG, 0);
3429 } else {
3430 tcg_gen_exit_tb(0);
3431 }
Richard Henderson4af70372010-03-16 15:10:49 -07003432 break;
3433 default:
3434 abort();
3435 }
3436
pbrook2e70f6e2008-06-29 01:03:05 +00003437 gen_icount_end(tb, num_insns);
j_mayer4c9649a2007-04-05 06:58:33 +00003438 *gen_opc_ptr = INDEX_op_end;
3439 if (search_pc) {
3440 j = gen_opc_ptr - gen_opc_buf;
3441 lj++;
3442 while (lj <= j)
3443 gen_opc_instr_start[lj++] = 0;
j_mayer4c9649a2007-04-05 06:58:33 +00003444 } else {
3445 tb->size = ctx.pc - pc_start;
pbrook2e70f6e2008-06-29 01:03:05 +00003446 tb->icount = num_insns;
j_mayer4c9649a2007-04-05 06:58:33 +00003447 }
Richard Henderson4af70372010-03-16 15:10:49 -07003448
Richard Henderson806991d2009-12-10 12:54:04 -08003449#ifdef DEBUG_DISAS
aliguori8fec2b82009-01-15 22:36:53 +00003450 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
aliguori93fcfe32009-01-15 22:34:14 +00003451 qemu_log("IN: %s\n", lookup_symbol(pc_start));
3452 log_target_disas(pc_start, ctx.pc - pc_start, 1);
3453 qemu_log("\n");
j_mayer4c9649a2007-04-05 06:58:33 +00003454 }
j_mayer4c9649a2007-04-05 06:58:33 +00003455#endif
j_mayer4c9649a2007-04-05 06:58:33 +00003456}
3457
ths2cfc5f12008-07-18 18:01:29 +00003458void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
j_mayer4c9649a2007-04-05 06:58:33 +00003459{
ths2cfc5f12008-07-18 18:01:29 +00003460 gen_intermediate_code_internal(env, tb, 0);
j_mayer4c9649a2007-04-05 06:58:33 +00003461}
3462
ths2cfc5f12008-07-18 18:01:29 +00003463void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
j_mayer4c9649a2007-04-05 06:58:33 +00003464{
ths2cfc5f12008-07-18 18:01:29 +00003465 gen_intermediate_code_internal(env, tb, 1);
j_mayer4c9649a2007-04-05 06:58:33 +00003466}
3467
Richard Hendersona964acc2009-12-09 15:46:36 -08003468struct cpu_def_t {
3469 const char *name;
3470 int implver, amask;
3471};
3472
3473static const struct cpu_def_t cpu_defs[] = {
3474 { "ev4", IMPLVER_2106x, 0 },
3475 { "ev5", IMPLVER_21164, 0 },
3476 { "ev56", IMPLVER_21164, AMASK_BWX },
3477 { "pca56", IMPLVER_21164, AMASK_BWX | AMASK_MVI },
3478 { "ev6", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP },
3479 { "ev67", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
3480 | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), },
3481 { "ev68", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
3482 | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), },
3483 { "21064", IMPLVER_2106x, 0 },
3484 { "21164", IMPLVER_21164, 0 },
3485 { "21164a", IMPLVER_21164, AMASK_BWX },
3486 { "21164pc", IMPLVER_21164, AMASK_BWX | AMASK_MVI },
3487 { "21264", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP },
3488 { "21264a", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
3489 | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), }
3490};
3491
bellardaaed9092007-11-10 15:15:54 +00003492CPUAlphaState * cpu_alpha_init (const char *cpu_model)
j_mayer4c9649a2007-04-05 06:58:33 +00003493{
3494 CPUAlphaState *env;
Richard Hendersona964acc2009-12-09 15:46:36 -08003495 int implver, amask, i, max;
j_mayer4c9649a2007-04-05 06:58:33 +00003496
Anthony Liguori7267c092011-08-20 22:09:37 -05003497 env = g_malloc0(sizeof(CPUAlphaState));
j_mayer4c9649a2007-04-05 06:58:33 +00003498 cpu_exec_init(env);
pbrook2e70f6e2008-06-29 01:03:05 +00003499 alpha_translate_init();
j_mayer4c9649a2007-04-05 06:58:33 +00003500 tlb_flush(env, 1);
Richard Hendersona964acc2009-12-09 15:46:36 -08003501
3502 /* Default to ev67; no reason not to emulate insns by default. */
3503 implver = IMPLVER_21264;
3504 amask = (AMASK_BWX | AMASK_FIX | AMASK_CIX | AMASK_MVI
3505 | AMASK_TRAP | AMASK_PREFETCH);
3506
3507 max = ARRAY_SIZE(cpu_defs);
3508 for (i = 0; i < max; i++) {
3509 if (strcmp (cpu_model, cpu_defs[i].name) == 0) {
3510 implver = cpu_defs[i].implver;
3511 amask = cpu_defs[i].amask;
3512 break;
3513 }
3514 }
3515 env->implver = implver;
3516 env->amask = amask;
3517
j_mayer4c9649a2007-04-05 06:58:33 +00003518#if defined (CONFIG_USER_ONLY)
Richard Hendersonea879fc2011-04-18 14:19:17 -07003519 env->ps = PS_USER_MODE;
Richard Henderson2edd07e2009-12-21 13:02:40 -08003520 cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
3521 | FPCR_UNFD | FPCR_INED | FPCR_DNOD));
Richard Henderson6049f4f2009-12-27 18:30:03 -08003522#endif
Richard Henderson6910b8f2010-04-07 15:42:26 -07003523 env->lock_addr = -1;
Richard Henderson26b46092011-05-23 12:12:29 -07003524 env->fen = 1;
Richard Hendersondad081e2010-01-04 11:19:14 -08003525
aliguori0bf46a42009-04-24 18:03:41 +00003526 qemu_init_vcpu(env);
j_mayer4c9649a2007-04-05 06:58:33 +00003527 return env;
3528}
bellardaaed9092007-11-10 15:15:54 +00003529
Stefan Weile87b7cb2011-04-18 06:39:52 +00003530void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
aurel32d2856f12008-04-28 00:32:32 +00003531{
3532 env->pc = gen_opc_pc[pc_pos];
3533}