]> git.proxmox.com Git - mirror_qemu.git/blame - target/alpha/translate.c
target: Use vaddr in gen_intermediate_code
[mirror_qemu.git] / target / alpha / translate.c
CommitLineData
4c9649a9
JM
1/*
2 * Alpha emulation cpu translation for qemu.
5fafdf24 3 *
4c9649a9
JM
4 * Copyright (c) 2007 Jocelyn Mayer
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
d6ea4236 9 * version 2.1 of the License, or (at your option) any later version.
4c9649a9
JM
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
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
4c9649a9
JM
18 */
19
e2e5e114 20#include "qemu/osdep.h"
4c9649a9 21#include "cpu.h"
d2528bdc 22#include "sysemu/cpus.h"
76cad711 23#include "disas/disas.h"
1de7afc9 24#include "qemu/host-utils.h"
63c91552 25#include "exec/exec-all.h"
dcb32f1d 26#include "tcg/tcg-op.h"
2ef6175a
RH
27#include "exec/helper-proto.h"
28#include "exec/helper-gen.h"
3de811c6 29#include "exec/translator.h"
508127e2 30#include "exec/log.h"
a7e30d84 31
d53106c9
RH
32#define HELPER_H "helper.h"
33#include "exec/helper-info.c.inc"
34#undef HELPER_H
a7e30d84 35
19188121 36#undef ALPHA_DEBUG_DISAS
f24518b5 37#define CONFIG_SOFTFLOAT_INLINE
d12d51d5
AL
38
39#ifdef ALPHA_DEBUG_DISAS
806991da 40# define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
d12d51d5
AL
41#else
42# define LOG_DISAS(...) do { } while (0)
43#endif
44
4c9649a9
JM
45typedef struct DisasContext DisasContext;
46struct DisasContext {
c5f80657
RH
47 DisasContextBase base;
48
fed14246
RH
49#ifdef CONFIG_USER_ONLY
50 MemOp unalign;
51#else
2f458b7c
RH
52 uint64_t palbr;
53#endif
489a0e64 54 uint32_t tbflags;
4c9649a9 55 int mem_idx;
f24518b5 56
c6d41b36
RH
57 /* implver and amask values for this CPU. */
58 int implver;
59 int amask;
60
f24518b5
RH
61 /* Current rounding mode for this TB. */
62 int tb_rm;
63 /* Current flush-to-zero setting for this TB. */
64 int tb_ftz;
ca6862a6 65
59124384
RH
66 /* The set of registers active in the current context. */
67 TCGv *ir;
68
194cfb43
RH
69 /* Temporaries for $31 and $f31 as source and destination. */
70 TCGv zero;
71 TCGv sink;
4c9649a9
JM
72};
73
fed14246
RH
74#ifdef CONFIG_USER_ONLY
75#define UNALIGN(C) (C)->unalign
76#else
6ffaac9c 77#define UNALIGN(C) MO_ALIGN
fed14246
RH
78#endif
79
3de811c6
RH
80/* Target-specific return values from translate_one, indicating the
81 state of the TB. Note that DISAS_NEXT indicates that we are not
82 exiting the TB. */
83#define DISAS_PC_UPDATED_NOCHAIN DISAS_TARGET_0
84#define DISAS_PC_UPDATED DISAS_TARGET_1
85#define DISAS_PC_STALE DISAS_TARGET_2
4af70374 86
3761035f 87/* global register indexes */
59124384 88static TCGv cpu_std_ir[31];
f18cd223 89static TCGv cpu_fir[31];
496cb5b9 90static TCGv cpu_pc;
6910b8f6 91static TCGv cpu_lock_addr;
6910b8f6 92static TCGv cpu_lock_value;
496cb5b9 93
59124384
RH
94#ifndef CONFIG_USER_ONLY
95static TCGv cpu_pal_ir[31];
96#endif
97
0c28246f 98void alpha_translate_init(void)
2e70f6ef 99{
39acc647
RH
100#define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUAlphaState, V) }
101
102 typedef struct { TCGv *var; const char *name; int ofs; } GlobalVar;
103 static const GlobalVar vars[] = {
104 DEF_VAR(pc),
105 DEF_VAR(lock_addr),
39acc647 106 DEF_VAR(lock_value),
39acc647
RH
107 };
108
109#undef DEF_VAR
110
111 /* Use the symbolic register names that match the disassembler. */
112 static const char greg_names[31][4] = {
113 "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
114 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
115 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
116 "t10", "t11", "ra", "t12", "at", "gp", "sp"
117 };
118 static const char freg_names[31][4] = {
119 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
120 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
121 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
122 "f24", "f25", "f26", "f27", "f28", "f29", "f30"
123 };
59124384
RH
124#ifndef CONFIG_USER_ONLY
125 static const char shadow_names[8][8] = {
126 "pal_t7", "pal_s0", "pal_s1", "pal_s2",
127 "pal_s3", "pal_s4", "pal_s5", "pal_t11"
128 };
129#endif
39acc647 130
496cb5b9 131 int i;
496cb5b9 132
496cb5b9 133 for (i = 0; i < 31; i++) {
ad75a51e 134 cpu_std_ir[i] = tcg_global_mem_new_i64(tcg_env,
59124384
RH
135 offsetof(CPUAlphaState, ir[i]),
136 greg_names[i]);
39acc647 137 }
f18cd223 138
39acc647 139 for (i = 0; i < 31; i++) {
ad75a51e 140 cpu_fir[i] = tcg_global_mem_new_i64(tcg_env,
39acc647
RH
141 offsetof(CPUAlphaState, fir[i]),
142 freg_names[i]);
496cb5b9
AJ
143 }
144
59124384
RH
145#ifndef CONFIG_USER_ONLY
146 memcpy(cpu_pal_ir, cpu_std_ir, sizeof(cpu_pal_ir));
147 for (i = 0; i < 8; i++) {
148 int r = (i == 7 ? 25 : i + 8);
ad75a51e 149 cpu_pal_ir[r] = tcg_global_mem_new_i64(tcg_env,
59124384
RH
150 offsetof(CPUAlphaState,
151 shadow[i]),
152 shadow_names[i]);
153 }
154#endif
155
39acc647
RH
156 for (i = 0; i < ARRAY_SIZE(vars); ++i) {
157 const GlobalVar *v = &vars[i];
ad75a51e 158 *v->var = tcg_global_mem_new_i64(tcg_env, v->ofs, v->name);
39acc647 159 }
2e70f6ef
PB
160}
161
194cfb43
RH
162static TCGv load_zero(DisasContext *ctx)
163{
f764718d 164 if (!ctx->zero) {
212c88c0 165 ctx->zero = tcg_constant_i64(0);
194cfb43
RH
166 }
167 return ctx->zero;
168}
169
170static TCGv dest_sink(DisasContext *ctx)
171{
f764718d 172 if (!ctx->sink) {
8f811b9a 173 ctx->sink = tcg_temp_new();
194cfb43
RH
174 }
175 return ctx->sink;
176}
177
ed283916
RH
178static void free_context_temps(DisasContext *ctx)
179{
f764718d 180 if (ctx->sink) {
ed283916 181 tcg_gen_discard_i64(ctx->sink);
f764718d 182 ctx->sink = NULL;
ed283916 183 }
ed283916
RH
184}
185
194cfb43
RH
186static TCGv load_gpr(DisasContext *ctx, unsigned reg)
187{
188 if (likely(reg < 31)) {
59124384 189 return ctx->ir[reg];
194cfb43
RH
190 } else {
191 return load_zero(ctx);
192 }
193}
194
195static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
196 uint8_t lit, bool islit)
197{
198 if (islit) {
212c88c0 199 return tcg_constant_i64(lit);
194cfb43 200 } else if (likely(reg < 31)) {
59124384 201 return ctx->ir[reg];
194cfb43
RH
202 } else {
203 return load_zero(ctx);
204 }
205}
206
207static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
208{
209 if (likely(reg < 31)) {
59124384 210 return ctx->ir[reg];
194cfb43
RH
211 } else {
212 return dest_sink(ctx);
213 }
214}
215
6b88b37c 216static TCGv load_fpr(DisasContext *ctx, unsigned reg)
194cfb43
RH
217{
218 if (likely(reg < 31)) {
219 return cpu_fir[reg];
220 } else {
221 return load_zero(ctx);
222 }
223}
224
075b8ddb 225static TCGv dest_fpr(DisasContext *ctx, unsigned reg)
194cfb43
RH
226{
227 if (likely(reg < 31)) {
228 return cpu_fir[reg];
229 } else {
230 return dest_sink(ctx);
231 }
232}
233
bcd2625d
RH
234static int get_flag_ofs(unsigned shift)
235{
236 int ofs = offsetof(CPUAlphaState, flags);
e03b5686 237#if HOST_BIG_ENDIAN
bcd2625d
RH
238 ofs += 3 - (shift / 8);
239#else
240 ofs += shift / 8;
241#endif
242 return ofs;
243}
244
245static void ld_flag_byte(TCGv val, unsigned shift)
246{
ad75a51e 247 tcg_gen_ld8u_i64(val, tcg_env, get_flag_ofs(shift));
bcd2625d
RH
248}
249
250static void st_flag_byte(TCGv val, unsigned shift)
251{
ad75a51e 252 tcg_gen_st8_i64(val, tcg_env, get_flag_ofs(shift));
bcd2625d
RH
253}
254
bf1b03fe 255static void gen_excp_1(int exception, int error_code)
4c9649a9 256{
a7812ae4 257 TCGv_i32 tmp1, tmp2;
6ad02592 258
904bd855
RH
259 tmp1 = tcg_constant_i32(exception);
260 tmp2 = tcg_constant_i32(error_code);
ad75a51e 261 gen_helper_excp(tcg_env, tmp1, tmp2);
bf1b03fe 262}
8aa3fa20 263
3de811c6 264static DisasJumpType gen_excp(DisasContext *ctx, int exception, int error_code)
bf1b03fe 265{
c5f80657 266 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
bf1b03fe 267 gen_excp_1(exception, error_code);
3de811c6 268 return DISAS_NORETURN;
4c9649a9
JM
269}
270
3de811c6 271static inline DisasJumpType gen_invalid(DisasContext *ctx)
4c9649a9 272{
8aa3fa20 273 return gen_excp(ctx, EXCP_OPCDEC, 0);
4c9649a9
JM
274}
275
45263531 276static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
f18cd223 277{
a7812ae4 278 TCGv_i32 tmp32 = tcg_temp_new_i32();
fed14246 279 tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
45263531 280 gen_helper_memory_to_f(dest, tmp32);
f18cd223
AJ
281}
282
45263531 283static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr)
f18cd223 284{
a7812ae4 285 TCGv tmp = tcg_temp_new();
fc313c64 286 tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
45263531 287 gen_helper_memory_to_g(dest, tmp);
f18cd223
AJ
288}
289
45263531 290static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr)
f18cd223 291{
a7812ae4 292 TCGv_i32 tmp32 = tcg_temp_new_i32();
fed14246 293 tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
45263531 294 gen_helper_memory_to_s(dest, tmp32);
f18cd223
AJ
295}
296
45263531
RH
297static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr)
298{
fc313c64 299 tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
45263531
RH
300}
301
302static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
303 void (*func)(DisasContext *, TCGv, TCGv))
304{
305 /* Loads to $f31 are prefetches, which we can treat as nops. */
306 if (likely(ra != 31)) {
307 TCGv addr = tcg_temp_new();
308 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
309 func(ctx, cpu_fir[ra], addr);
45263531
RH
310 }
311}
312
5ffcb334
RH
313static void gen_load_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
314 MemOp op, bool clear, bool locked)
f4ed8679 315{
5ffcb334 316 TCGv addr, dest;
023d8ca2 317
6910b8f6
RH
318 /* LDQ_U with ra $31 is UNOP. Other various loads are forms of
319 prefetches, which we can treat as nops. No worries about
320 missed exceptions here. */
321 if (unlikely(ra == 31)) {
023d8ca2 322 return;
6910b8f6 323 }
023d8ca2 324
5ffcb334
RH
325 addr = tcg_temp_new();
326 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
595b8fdd 327 if (clear) {
5ffcb334 328 tcg_gen_andi_i64(addr, addr, ~0x7);
fed14246
RH
329 } else if (!locked) {
330 op |= UNALIGN(ctx);
023d8ca2 331 }
6910b8f6 332
5ffcb334
RH
333 dest = ctx->ir[ra];
334 tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, op);
6910b8f6 335
5ffcb334
RH
336 if (locked) {
337 tcg_gen_mov_i64(cpu_lock_addr, addr);
338 tcg_gen_mov_i64(cpu_lock_value, dest);
339 }
023d8ca2
AJ
340}
341
45263531 342static void gen_stf(DisasContext *ctx, TCGv src, TCGv addr)
f18cd223 343{
a7812ae4 344 TCGv_i32 tmp32 = tcg_temp_new_i32();
45263531 345 gen_helper_f_to_memory(tmp32, addr);
fed14246 346 tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
f18cd223
AJ
347}
348
45263531 349static void gen_stg(DisasContext *ctx, TCGv src, TCGv addr)
f18cd223 350{
a7812ae4 351 TCGv tmp = tcg_temp_new();
45263531 352 gen_helper_g_to_memory(tmp, src);
fc313c64 353 tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
f18cd223
AJ
354}
355
45263531 356static void gen_sts(DisasContext *ctx, TCGv src, TCGv addr)
f18cd223 357{
a7812ae4 358 TCGv_i32 tmp32 = tcg_temp_new_i32();
45263531 359 gen_helper_s_to_memory(tmp32, src);
fed14246 360 tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
f18cd223
AJ
361}
362
45263531
RH
363static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr)
364{
fc313c64 365 tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
45263531
RH
366}
367
368static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
369 void (*func)(DisasContext *, TCGv, TCGv))
370{
371 TCGv addr = tcg_temp_new();
372 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
373 func(ctx, load_fpr(ctx, ra), addr);
45263531
RH
374}
375
5ffcb334
RH
376static void gen_store_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
377 MemOp op, bool clear)
023d8ca2 378{
5ffcb334 379 TCGv addr, src;
6910b8f6 380
5ffcb334
RH
381 addr = tcg_temp_new();
382 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
595b8fdd 383 if (clear) {
5ffcb334 384 tcg_gen_andi_i64(addr, addr, ~0x7);
fed14246
RH
385 } else {
386 op |= UNALIGN(ctx);
023d8ca2 387 }
595b8fdd 388
5ffcb334
RH
389 src = load_gpr(ctx, ra);
390 tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, op);
6910b8f6
RH
391}
392
3de811c6
RH
393static DisasJumpType gen_store_conditional(DisasContext *ctx, int ra, int rb,
394 int32_t disp16, int mem_idx,
14776ab5 395 MemOp op)
6910b8f6 396{
ed283916
RH
397 TCGLabel *lab_fail, *lab_done;
398 TCGv addr, val;
6910b8f6 399
ed283916 400 addr = tcg_temp_new_i64();
cd2d46fd 401 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
ed283916 402 free_context_temps(ctx);
6910b8f6 403
ed283916
RH
404 lab_fail = gen_new_label();
405 lab_done = gen_new_label();
406 tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
6910b8f6 407
ed283916
RH
408 val = tcg_temp_new_i64();
409 tcg_gen_atomic_cmpxchg_i64(val, cpu_lock_addr, cpu_lock_value,
410 load_gpr(ctx, ra), mem_idx, op);
411 free_context_temps(ctx);
6910b8f6 412
ed283916
RH
413 if (ra != 31) {
414 tcg_gen_setcond_i64(TCG_COND_EQ, ctx->ir[ra], val, cpu_lock_value);
415 }
ed283916 416 tcg_gen_br(lab_done);
6910b8f6 417
ed283916
RH
418 gen_set_label(lab_fail);
419 if (ra != 31) {
59124384 420 tcg_gen_movi_i64(ctx->ir[ra], 0);
6910b8f6 421 }
ed283916
RH
422
423 gen_set_label(lab_done);
424 tcg_gen_movi_i64(cpu_lock_addr, -1);
3de811c6 425 return DISAS_NEXT;
023d8ca2
AJ
426}
427
b114b68a
RH
428static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
429{
21a7e89e 430 return translator_use_goto_tb(&ctx->base, dest);
4af70374 431}
dbb30fe6 432
3de811c6 433static DisasJumpType gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
4af70374 434{
c5f80657 435 uint64_t dest = ctx->base.pc_next + (disp << 2);
4af70374
RH
436
437 if (ra != 31) {
c5f80657 438 tcg_gen_movi_i64(ctx->ir[ra], ctx->base.pc_next);
4af70374
RH
439 }
440
441 /* Notice branch-to-next; used to initialize RA with the PC. */
442 if (disp == 0) {
443 return 0;
444 } else if (use_goto_tb(ctx, dest)) {
445 tcg_gen_goto_tb(0);
446 tcg_gen_movi_i64(cpu_pc, dest);
07ea28b4 447 tcg_gen_exit_tb(ctx->base.tb, 0);
3de811c6 448 return DISAS_NORETURN;
4af70374
RH
449 } else {
450 tcg_gen_movi_i64(cpu_pc, dest);
3de811c6 451 return DISAS_PC_UPDATED;
4af70374 452 }
dbb30fe6
RH
453}
454
3de811c6
RH
455static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond,
456 TCGv cmp, int32_t disp)
dbb30fe6 457{
c5f80657 458 uint64_t dest = ctx->base.pc_next + (disp << 2);
42a268c2 459 TCGLabel *lab_true = gen_new_label();
9c29504e 460
4af70374
RH
461 if (use_goto_tb(ctx, dest)) {
462 tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
463
464 tcg_gen_goto_tb(0);
c5f80657 465 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
07ea28b4 466 tcg_gen_exit_tb(ctx->base.tb, 0);
4af70374
RH
467
468 gen_set_label(lab_true);
469 tcg_gen_goto_tb(1);
470 tcg_gen_movi_i64(cpu_pc, dest);
07ea28b4 471 tcg_gen_exit_tb(ctx->base.tb, 1);
4af70374 472
3de811c6 473 return DISAS_NORETURN;
4af70374 474 } else {
904bd855
RH
475 TCGv_i64 z = load_zero(ctx);
476 TCGv_i64 d = tcg_constant_i64(dest);
477 TCGv_i64 p = tcg_constant_i64(ctx->base.pc_next);
4af70374 478
57e289de 479 tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p);
3de811c6 480 return DISAS_PC_UPDATED;
4af70374
RH
481 }
482}
483
3de811c6
RH
484static DisasJumpType gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
485 int32_t disp, int mask)
4af70374 486{
76bff4f8 487 if (mask) {
22d716c2 488 TCGv tmp = tcg_temp_new();
3de811c6 489 DisasJumpType ret;
4af70374 490
22d716c2
RH
491 tcg_gen_andi_i64(tmp, load_gpr(ctx, ra), 1);
492 ret = gen_bcond_internal(ctx, cond, tmp, disp);
22d716c2
RH
493 return ret;
494 }
495 return gen_bcond_internal(ctx, cond, load_gpr(ctx, ra), disp);
4c9649a9
JM
496}
497
4af70374 498/* Fold -0.0 for comparison with COND. */
dbb30fe6 499
4af70374 500static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
4c9649a9 501{
dbb30fe6 502 uint64_t mzero = 1ull << 63;
f18cd223 503
dbb30fe6
RH
504 switch (cond) {
505 case TCG_COND_LE:
506 case TCG_COND_GT:
507 /* For <= or >, the -0.0 value directly compares the way we want. */
4af70374 508 tcg_gen_mov_i64(dest, src);
a7812ae4 509 break;
dbb30fe6
RH
510
511 case TCG_COND_EQ:
512 case TCG_COND_NE:
513 /* For == or !=, we can simply mask off the sign bit and compare. */
4af70374 514 tcg_gen_andi_i64(dest, src, mzero - 1);
a7812ae4 515 break;
dbb30fe6
RH
516
517 case TCG_COND_GE:
dbb30fe6 518 case TCG_COND_LT:
d55a3211
RH
519 /* For >= or <, map -0.0 to +0.0. */
520 tcg_gen_movcond_i64(TCG_COND_NE, dest, src, tcg_constant_i64(mzero),
521 src, tcg_constant_i64(0));
a7812ae4 522 break;
dbb30fe6 523
a7812ae4
PB
524 default:
525 abort();
f18cd223 526 }
dbb30fe6
RH
527}
528
3de811c6
RH
529static DisasJumpType gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
530 int32_t disp)
dbb30fe6 531{
76bff4f8 532 TCGv cmp_tmp = tcg_temp_new();
3de811c6 533 DisasJumpType ret;
6a9b110d 534
76bff4f8 535 gen_fold_mzero(cond, cmp_tmp, load_fpr(ctx, ra));
6a9b110d 536 ret = gen_bcond_internal(ctx, cond, cmp_tmp, disp);
6a9b110d 537 return ret;
4c9649a9
JM
538}
539
65809352 540static void gen_fcmov(DisasContext *ctx, TCGCond cond, int ra, int rb, int rc)
dbb30fe6 541{
65809352 542 TCGv_i64 va, vb, z;
dbb30fe6 543
65809352
RH
544 z = load_zero(ctx);
545 vb = load_fpr(ctx, rb);
546 va = tcg_temp_new();
547 gen_fold_mzero(cond, va, load_fpr(ctx, ra));
dbb30fe6 548
65809352 549 tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc), va, z, vb, load_fpr(ctx, rc));
dbb30fe6
RH
550}
551
f24518b5
RH
552#define QUAL_RM_N 0x080 /* Round mode nearest even */
553#define QUAL_RM_C 0x000 /* Round mode chopped */
554#define QUAL_RM_M 0x040 /* Round mode minus infinity */
555#define QUAL_RM_D 0x0c0 /* Round mode dynamic */
556#define QUAL_RM_MASK 0x0c0
557
558#define QUAL_U 0x100 /* Underflow enable (fp output) */
559#define QUAL_V 0x100 /* Overflow enable (int output) */
560#define QUAL_S 0x400 /* Software completion enable */
561#define QUAL_I 0x200 /* Inexact detection enable */
562
563static void gen_qual_roundmode(DisasContext *ctx, int fn11)
564{
565 TCGv_i32 tmp;
566
567 fn11 &= QUAL_RM_MASK;
568 if (fn11 == ctx->tb_rm) {
569 return;
570 }
571 ctx->tb_rm = fn11;
572
573 tmp = tcg_temp_new_i32();
574 switch (fn11) {
575 case QUAL_RM_N:
576 tcg_gen_movi_i32(tmp, float_round_nearest_even);
577 break;
578 case QUAL_RM_C:
579 tcg_gen_movi_i32(tmp, float_round_to_zero);
580 break;
581 case QUAL_RM_M:
582 tcg_gen_movi_i32(tmp, float_round_down);
583 break;
584 case QUAL_RM_D:
ad75a51e 585 tcg_gen_ld8u_i32(tmp, tcg_env,
4a58aedf 586 offsetof(CPUAlphaState, fpcr_dyn_round));
f24518b5
RH
587 break;
588 }
589
590#if defined(CONFIG_SOFTFLOAT_INLINE)
6b4c305c 591 /* ??? The "fpu/softfloat.h" interface is to call set_float_rounding_mode.
f24518b5
RH
592 With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
593 sets the one field. */
ad75a51e 594 tcg_gen_st8_i32(tmp, tcg_env,
4d5712f1 595 offsetof(CPUAlphaState, fp_status.float_rounding_mode));
f24518b5
RH
596#else
597 gen_helper_setroundmode(tmp);
598#endif
f24518b5
RH
599}
600
601static void gen_qual_flushzero(DisasContext *ctx, int fn11)
602{
603 TCGv_i32 tmp;
604
605 fn11 &= QUAL_U;
606 if (fn11 == ctx->tb_ftz) {
607 return;
608 }
609 ctx->tb_ftz = fn11;
610
611 tmp = tcg_temp_new_i32();
612 if (fn11) {
613 /* Underflow is enabled, use the FPCR setting. */
ad75a51e 614 tcg_gen_ld8u_i32(tmp, tcg_env,
4a58aedf 615 offsetof(CPUAlphaState, fpcr_flush_to_zero));
f24518b5
RH
616 } else {
617 /* Underflow is disabled, force flush-to-zero. */
618 tcg_gen_movi_i32(tmp, 1);
619 }
620
621#if defined(CONFIG_SOFTFLOAT_INLINE)
ad75a51e 622 tcg_gen_st8_i32(tmp, tcg_env,
4d5712f1 623 offsetof(CPUAlphaState, fp_status.flush_to_zero));
f24518b5
RH
624#else
625 gen_helper_setflushzero(tmp);
626#endif
f24518b5
RH
627}
628
8b0190bb 629static TCGv gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp)
f24518b5 630{
74343409 631 TCGv val;
8b0190bb
RH
632
633 if (unlikely(reg == 31)) {
634 val = load_zero(ctx);
f24518b5 635 } else {
8b0190bb 636 val = cpu_fir[reg];
74343409
RH
637 if ((fn11 & QUAL_S) == 0) {
638 if (is_cmp) {
ad75a51e 639 gen_helper_ieee_input_cmp(tcg_env, val);
74343409 640 } else {
ad75a51e 641 gen_helper_ieee_input(tcg_env, val);
74343409 642 }
b99e8069
RH
643 } else {
644#ifndef CONFIG_USER_ONLY
645 /* In system mode, raise exceptions for denormals like real
646 hardware. In user mode, proceed as if the OS completion
647 handler is handling the denormal as per spec. */
ad75a51e 648 gen_helper_ieee_input_s(tcg_env, val);
b99e8069 649#endif
74343409 650 }
f24518b5
RH
651 }
652 return val;
653}
654
471d4930 655static void gen_fp_exc_raise(int rc, int fn11)
f24518b5
RH
656{
657 /* ??? We ought to be able to do something with imprecise exceptions.
658 E.g. notice we're still in the trap shadow of something within the
659 TB and do not generate the code to signal the exception; end the TB
660 when an exception is forced to arrive, either by consumption of a
661 register value or TRAPB or EXCB. */
471d4930
RH
662 TCGv_i32 reg, ign;
663 uint32_t ignore = 0;
664
665 if (!(fn11 & QUAL_U)) {
666 /* Note that QUAL_U == QUAL_V, so ignore either. */
667 ignore |= FPCR_UNF | FPCR_IOV;
668 }
669 if (!(fn11 & QUAL_I)) {
670 ignore |= FPCR_INE;
671 }
904bd855 672 ign = tcg_constant_i32(ignore);
f24518b5 673
f24518b5
RH
674 /* ??? Pass in the regno of the destination so that the helper can
675 set EXC_MASK, which contains a bitmask of destination registers
676 that have caused arithmetic traps. A simple userspace emulation
677 does not require this. We do need it for a guest kernel's entArith,
678 or if we were to do something clever with imprecise exceptions. */
904bd855 679 reg = tcg_constant_i32(rc + 32);
f24518b5 680 if (fn11 & QUAL_S) {
ad75a51e 681 gen_helper_fp_exc_raise_s(tcg_env, ign, reg);
f24518b5 682 } else {
ad75a51e 683 gen_helper_fp_exc_raise(tcg_env, ign, reg);
f24518b5 684 }
f24518b5
RH
685}
686
3da653fa 687static void gen_cvtlq(TCGv vc, TCGv vb)
593f17e5 688{
e8d8fef4 689 TCGv tmp = tcg_temp_new();
735cf45f 690
e8d8fef4
RH
691 /* The arithmetic right shift here, plus the sign-extended mask below
692 yields a sign-extended result without an explicit ext32s_i64. */
729028a6
PMD
693 tcg_gen_shri_i64(tmp, vb, 29);
694 tcg_gen_sari_i64(vc, vb, 32);
695 tcg_gen_deposit_i64(vc, vc, tmp, 0, 30);
735cf45f
RH
696}
697
4a58aedf
RH
698static void gen_ieee_arith2(DisasContext *ctx,
699 void (*helper)(TCGv, TCGv_ptr, TCGv),
f24518b5
RH
700 int rb, int rc, int fn11)
701{
702 TCGv vb;
703
f24518b5
RH
704 gen_qual_roundmode(ctx, fn11);
705 gen_qual_flushzero(ctx, fn11);
f24518b5 706
8b0190bb 707 vb = gen_ieee_input(ctx, rb, fn11, 0);
ad75a51e 708 helper(dest_fpr(ctx, rc), tcg_env, vb);
f24518b5
RH
709
710 gen_fp_exc_raise(rc, fn11);
711}
712
713#define IEEE_ARITH2(name) \
3da653fa
RH
714static inline void glue(gen_, name)(DisasContext *ctx, \
715 int rb, int rc, int fn11) \
f24518b5
RH
716{ \
717 gen_ieee_arith2(ctx, gen_helper_##name, rb, rc, fn11); \
718}
719IEEE_ARITH2(sqrts)
720IEEE_ARITH2(sqrtt)
721IEEE_ARITH2(cvtst)
722IEEE_ARITH2(cvtts)
723
3da653fa 724static void gen_cvttq(DisasContext *ctx, int rb, int rc, int fn11)
f24518b5 725{
e20b8c04 726 TCGv vb, vc;
f24518b5 727
f24518b5 728 /* No need to set flushzero, since we have an integer output. */
8b0190bb 729 vb = gen_ieee_input(ctx, rb, fn11, 0);
e20b8c04 730 vc = dest_fpr(ctx, rc);
f24518b5 731
c24a8a0b
RH
732 /* Almost all integer conversions use cropped rounding;
733 special case that. */
734 if ((fn11 & QUAL_RM_MASK) == QUAL_RM_C) {
ad75a51e 735 gen_helper_cvttq_c(vc, tcg_env, vb);
c24a8a0b 736 } else {
f24518b5 737 gen_qual_roundmode(ctx, fn11);
ad75a51e 738 gen_helper_cvttq(vc, tcg_env, vb);
f24518b5 739 }
471d4930 740 gen_fp_exc_raise(rc, fn11);
4c9649a9
JM
741}
742
4a58aedf
RH
743static void gen_ieee_intcvt(DisasContext *ctx,
744 void (*helper)(TCGv, TCGv_ptr, TCGv),
7d37435b 745 int rb, int rc, int fn11)
f24518b5 746{
e20b8c04 747 TCGv vb, vc;
f24518b5
RH
748
749 gen_qual_roundmode(ctx, fn11);
e20b8c04
RH
750 vb = load_fpr(ctx, rb);
751 vc = dest_fpr(ctx, rc);
f24518b5
RH
752
753 /* The only exception that can be raised by integer conversion
754 is inexact. Thus we only need to worry about exceptions when
755 inexact handling is requested. */
756 if (fn11 & QUAL_I) {
ad75a51e 757 helper(vc, tcg_env, vb);
f24518b5
RH
758 gen_fp_exc_raise(rc, fn11);
759 } else {
ad75a51e 760 helper(vc, tcg_env, vb);
f24518b5
RH
761 }
762}
763
764#define IEEE_INTCVT(name) \
3da653fa
RH
765static inline void glue(gen_, name)(DisasContext *ctx, \
766 int rb, int rc, int fn11) \
f24518b5
RH
767{ \
768 gen_ieee_intcvt(ctx, gen_helper_##name, rb, rc, fn11); \
769}
770IEEE_INTCVT(cvtqs)
771IEEE_INTCVT(cvtqt)
772
ef3765cb 773static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask)
dc96be4b 774{
904bd855 775 TCGv vmask = tcg_constant_i64(mask);
ef3765cb 776 TCGv tmp = tcg_temp_new_i64();
dc96be4b 777
ef3765cb
RH
778 if (inv_a) {
779 tcg_gen_andc_i64(tmp, vmask, va);
dc96be4b 780 } else {
ef3765cb 781 tcg_gen_and_i64(tmp, va, vmask);
dc96be4b
RH
782 }
783
ef3765cb
RH
784 tcg_gen_andc_i64(vc, vb, vmask);
785 tcg_gen_or_i64(vc, vc, tmp);
dc96be4b
RH
786}
787
f24518b5 788static void gen_ieee_arith3(DisasContext *ctx,
4a58aedf 789 void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
f24518b5
RH
790 int ra, int rb, int rc, int fn11)
791{
e20b8c04 792 TCGv va, vb, vc;
f24518b5
RH
793
794 gen_qual_roundmode(ctx, fn11);
795 gen_qual_flushzero(ctx, fn11);
f24518b5 796
8b0190bb
RH
797 va = gen_ieee_input(ctx, ra, fn11, 0);
798 vb = gen_ieee_input(ctx, rb, fn11, 0);
e20b8c04 799 vc = dest_fpr(ctx, rc);
ad75a51e 800 helper(vc, tcg_env, va, vb);
f24518b5
RH
801
802 gen_fp_exc_raise(rc, fn11);
803}
804
805#define IEEE_ARITH3(name) \
3da653fa
RH
806static inline void glue(gen_, name)(DisasContext *ctx, \
807 int ra, int rb, int rc, int fn11) \
f24518b5
RH
808{ \
809 gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc, fn11); \
810}
811IEEE_ARITH3(adds)
812IEEE_ARITH3(subs)
813IEEE_ARITH3(muls)
814IEEE_ARITH3(divs)
815IEEE_ARITH3(addt)
816IEEE_ARITH3(subt)
817IEEE_ARITH3(mult)
818IEEE_ARITH3(divt)
819
820static void gen_ieee_compare(DisasContext *ctx,
4a58aedf 821 void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
f24518b5
RH
822 int ra, int rb, int rc, int fn11)
823{
e20b8c04 824 TCGv va, vb, vc;
f24518b5 825
8b0190bb
RH
826 va = gen_ieee_input(ctx, ra, fn11, 1);
827 vb = gen_ieee_input(ctx, rb, fn11, 1);
e20b8c04 828 vc = dest_fpr(ctx, rc);
ad75a51e 829 helper(vc, tcg_env, va, vb);
f24518b5
RH
830
831 gen_fp_exc_raise(rc, fn11);
832}
833
834#define IEEE_CMP3(name) \
3da653fa
RH
835static inline void glue(gen_, name)(DisasContext *ctx, \
836 int ra, int rb, int rc, int fn11) \
f24518b5
RH
837{ \
838 gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc, fn11); \
839}
840IEEE_CMP3(cmptun)
841IEEE_CMP3(cmpteq)
842IEEE_CMP3(cmptlt)
843IEEE_CMP3(cmptle)
a7812ae4 844
248c42f3
RH
845static inline uint64_t zapnot_mask(uint8_t lit)
846{
847 uint64_t mask = 0;
848 int i;
849
850 for (i = 0; i < 8; ++i) {
67debe3a 851 if ((lit >> i) & 1) {
248c42f3 852 mask |= 0xffull << (i * 8);
67debe3a 853 }
248c42f3
RH
854 }
855 return mask;
856}
857
87d98f95
RH
858/* Implement zapnot with an immediate operand, which expands to some
859 form of immediate AND. This is a basic building block in the
860 definition of many of the other byte manipulation instructions. */
248c42f3 861static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
87d98f95 862{
87d98f95
RH
863 switch (lit) {
864 case 0x00:
248c42f3 865 tcg_gen_movi_i64(dest, 0);
87d98f95
RH
866 break;
867 case 0x01:
248c42f3 868 tcg_gen_ext8u_i64(dest, src);
87d98f95
RH
869 break;
870 case 0x03:
248c42f3 871 tcg_gen_ext16u_i64(dest, src);
87d98f95
RH
872 break;
873 case 0x0f:
248c42f3 874 tcg_gen_ext32u_i64(dest, src);
87d98f95
RH
875 break;
876 case 0xff:
248c42f3 877 tcg_gen_mov_i64(dest, src);
87d98f95
RH
878 break;
879 default:
b144be9e 880 tcg_gen_andi_i64(dest, src, zapnot_mask(lit));
87d98f95
RH
881 break;
882 }
883}
884
248c42f3 885/* EXTWH, EXTLH, EXTQH */
9a734d64 886static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
ffec44f1 887 uint8_t lit, uint8_t byte_mask)
b3249f63 888{
9a734d64 889 if (islit) {
f49f1ae7
RH
890 int pos = (64 - lit * 8) & 0x3f;
891 int len = cto32(byte_mask) * 8;
892 if (pos < len) {
893 tcg_gen_deposit_z_i64(vc, va, pos, len - pos);
894 } else {
895 tcg_gen_movi_i64(vc, 0);
896 }
67debe3a 897 } else {
9a734d64
RH
898 TCGv tmp = tcg_temp_new();
899 tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3);
900 tcg_gen_neg_i64(tmp, tmp);
901 tcg_gen_andi_i64(tmp, tmp, 0x3f);
902 tcg_gen_shl_i64(vc, va, tmp);
377a43b6 903 }
9a734d64 904 gen_zapnoti(vc, vc, byte_mask);
b3249f63
AJ
905}
906
248c42f3 907/* EXTBL, EXTWL, EXTLL, EXTQL */
9a734d64 908static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
ffec44f1 909 uint8_t lit, uint8_t byte_mask)
b3249f63 910{
9a734d64 911 if (islit) {
f49f1ae7
RH
912 int pos = (lit & 7) * 8;
913 int len = cto32(byte_mask) * 8;
914 if (pos + len >= 64) {
915 len = 64 - pos;
916 }
917 tcg_gen_extract_i64(vc, va, pos, len);
67debe3a 918 } else {
9a734d64
RH
919 TCGv tmp = tcg_temp_new();
920 tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7);
921 tcg_gen_shli_i64(tmp, tmp, 3);
922 tcg_gen_shr_i64(vc, va, tmp);
f49f1ae7 923 gen_zapnoti(vc, vc, byte_mask);
248c42f3
RH
924 }
925}
926
50eb6e5c 927/* INSWH, INSLH, INSQH */
5e5863ec 928static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
50eb6e5c
RH
929 uint8_t lit, uint8_t byte_mask)
930{
5e5863ec 931 if (islit) {
f49f1ae7
RH
932 int pos = 64 - (lit & 7) * 8;
933 int len = cto32(byte_mask) * 8;
934 if (pos < len) {
935 tcg_gen_extract_i64(vc, va, pos, len - pos);
50eb6e5c 936 } else {
f49f1ae7 937 tcg_gen_movi_i64(vc, 0);
50eb6e5c 938 }
5e5863ec 939 } else {
f49f1ae7 940 TCGv tmp = tcg_temp_new();
5e5863ec
RH
941 TCGv shift = tcg_temp_new();
942
f49f1ae7
RH
943 /* The instruction description has us left-shift the byte mask
944 and extract bits <15:8> and apply that zap at the end. This
945 is equivalent to simply performing the zap first and shifting
946 afterward. */
947 gen_zapnoti(tmp, va, byte_mask);
948
5e5863ec
RH
949 /* If (B & 7) == 0, we need to shift by 64 and leave a zero. Do this
950 portably by splitting the shift into two parts: shift_count-1 and 1.
951 Arrange for the -1 by using ones-complement instead of
952 twos-complement in the negation: ~(B * 8) & 63. */
953
954 tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
955 tcg_gen_not_i64(shift, shift);
956 tcg_gen_andi_i64(shift, shift, 0x3f);
957
958 tcg_gen_shr_i64(vc, tmp, shift);
959 tcg_gen_shri_i64(vc, vc, 1);
50eb6e5c
RH
960 }
961}
962
248c42f3 963/* INSBL, INSWL, INSLL, INSQL */
5e5863ec 964static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
ffec44f1 965 uint8_t lit, uint8_t byte_mask)
248c42f3 966{
5e5863ec 967 if (islit) {
f49f1ae7
RH
968 int pos = (lit & 7) * 8;
969 int len = cto32(byte_mask) * 8;
970 if (pos + len > 64) {
971 len = 64 - pos;
972 }
973 tcg_gen_deposit_z_i64(vc, va, pos, len);
5e5863ec 974 } else {
f49f1ae7 975 TCGv tmp = tcg_temp_new();
5e5863ec 976 TCGv shift = tcg_temp_new();
f49f1ae7
RH
977
978 /* The instruction description has us left-shift the byte mask
979 and extract bits <15:8> and apply that zap at the end. This
980 is equivalent to simply performing the zap first and shifting
981 afterward. */
982 gen_zapnoti(tmp, va, byte_mask);
983
5e5863ec
RH
984 tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
985 tcg_gen_shli_i64(shift, shift, 3);
986 tcg_gen_shl_i64(vc, tmp, shift);
377a43b6 987 }
b3249f63
AJ
988}
989
ffec44f1 990/* MSKWH, MSKLH, MSKQH */
9a8fa1bd 991static void gen_msk_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
ffec44f1
RH
992 uint8_t lit, uint8_t byte_mask)
993{
9a8fa1bd
RH
994 if (islit) {
995 gen_zapnoti(vc, va, ~((byte_mask << (lit & 7)) >> 8));
ffec44f1
RH
996 } else {
997 TCGv shift = tcg_temp_new();
998 TCGv mask = tcg_temp_new();
999
1000 /* The instruction description is as above, where the byte_mask
1001 is shifted left, and then we extract bits <15:8>. This can be
1002 emulated with a right-shift on the expanded byte mask. This
1003 requires extra care because for an input <2:0> == 0 we need a
1004 shift of 64 bits in order to generate a zero. This is done by
1005 splitting the shift into two parts, the variable shift - 1
1006 followed by a constant 1 shift. The code we expand below is
9a8fa1bd 1007 equivalent to ~(B * 8) & 63. */
ffec44f1 1008
9a8fa1bd 1009 tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
ffec44f1
RH
1010 tcg_gen_not_i64(shift, shift);
1011 tcg_gen_andi_i64(shift, shift, 0x3f);
1012 tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
1013 tcg_gen_shr_i64(mask, mask, shift);
1014 tcg_gen_shri_i64(mask, mask, 1);
1015
9a8fa1bd 1016 tcg_gen_andc_i64(vc, va, mask);
ffec44f1
RH
1017 }
1018}
1019
14ab1634 1020/* MSKBL, MSKWL, MSKLL, MSKQL */
9a8fa1bd 1021static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
ffec44f1 1022 uint8_t lit, uint8_t byte_mask)
14ab1634 1023{
9a8fa1bd
RH
1024 if (islit) {
1025 gen_zapnoti(vc, va, ~(byte_mask << (lit & 7)));
14ab1634
RH
1026 } else {
1027 TCGv shift = tcg_temp_new();
1028 TCGv mask = tcg_temp_new();
1029
9a8fa1bd 1030 tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
14ab1634 1031 tcg_gen_shli_i64(shift, shift, 3);
9a8fa1bd 1032 tcg_gen_movi_i64(mask, zapnot_mask(byte_mask));
14ab1634
RH
1033 tcg_gen_shl_i64(mask, mask, shift);
1034
9a8fa1bd 1035 tcg_gen_andc_i64(vc, va, mask);
14ab1634
RH
1036 }
1037}
1038
59124384 1039static void gen_rx(DisasContext *ctx, int ra, int set)
ac316ca4 1040{
ac316ca4 1041 if (ra != 31) {
bcd2625d 1042 ld_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
ac316ca4
RH
1043 }
1044
492f85b9 1045 st_flag_byte(tcg_constant_i64(set), ENV_FLAG_RX_SHIFT);
ac316ca4
RH
1046}
1047
3de811c6 1048static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode)
2ace7e55
RH
1049{
1050 /* We're emulating OSF/1 PALcode. Many of these are trivial access
1051 to internal cpu registers. */
1052
1053 /* Unprivileged PAL call */
1054 if (palcode >= 0x80 && palcode < 0xC0) {
1055 switch (palcode) {
1056 case 0x86:
1057 /* IMB */
1058 /* No-op inside QEMU. */
1059 break;
1060 case 0x9E:
1061 /* RDUNIQUE */
ad75a51e 1062 tcg_gen_ld_i64(ctx->ir[IR_V0], tcg_env,
06ef8604 1063 offsetof(CPUAlphaState, unique));
2ace7e55
RH
1064 break;
1065 case 0x9F:
1066 /* WRUNIQUE */
ad75a51e 1067 tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
06ef8604 1068 offsetof(CPUAlphaState, unique));
2ace7e55
RH
1069 break;
1070 default:
ba96394e
RH
1071 palcode &= 0xbf;
1072 goto do_call_pal;
2ace7e55 1073 }
3de811c6 1074 return DISAS_NEXT;
2ace7e55
RH
1075 }
1076
1077#ifndef CONFIG_USER_ONLY
1078 /* Privileged PAL code */
bcd2625d 1079 if (palcode < 0x40 && (ctx->tbflags & ENV_FLAG_PS_USER) == 0) {
2ace7e55
RH
1080 switch (palcode) {
1081 case 0x01:
1082 /* CFLUSH */
1083 /* No-op inside QEMU. */
1084 break;
1085 case 0x02:
1086 /* DRAINA */
1087 /* No-op inside QEMU. */
1088 break;
1089 case 0x2D:
1090 /* WRVPTPTR */
ad75a51e 1091 tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
06ef8604 1092 offsetof(CPUAlphaState, vptptr));
2ace7e55
RH
1093 break;
1094 case 0x31:
1095 /* WRVAL */
ad75a51e 1096 tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
06ef8604 1097 offsetof(CPUAlphaState, sysval));
2ace7e55
RH
1098 break;
1099 case 0x32:
1100 /* RDVAL */
ad75a51e 1101 tcg_gen_ld_i64(ctx->ir[IR_V0], tcg_env,
06ef8604 1102 offsetof(CPUAlphaState, sysval));
2ace7e55
RH
1103 break;
1104
bec5e2b9 1105 case 0x35:
2ace7e55 1106 /* SWPIPL */
2ace7e55
RH
1107 /* Note that we already know we're in kernel mode, so we know
1108 that PS only contains the 3 IPL bits. */
bcd2625d 1109 ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT);
2ace7e55
RH
1110
1111 /* But make sure and store only the 3 IPL bits from the user. */
f401c032
RH
1112 {
1113 TCGv tmp = tcg_temp_new();
1114 tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
1115 st_flag_byte(tmp, ENV_FLAG_PS_SHIFT);
f401c032 1116 }
54e1d4ed
RH
1117
1118 /* Allow interrupts to be recognized right away. */
c5f80657 1119 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
3de811c6 1120 return DISAS_PC_UPDATED_NOCHAIN;
2ace7e55
RH
1121
1122 case 0x36:
1123 /* RDPS */
bcd2625d 1124 ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT);
2ace7e55 1125 break;
bcd2625d 1126
2ace7e55
RH
1127 case 0x38:
1128 /* WRUSP */
ad75a51e 1129 tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
06ef8604 1130 offsetof(CPUAlphaState, usp));
2ace7e55
RH
1131 break;
1132 case 0x3A:
1133 /* RDUSP */
ad75a51e 1134 tcg_gen_ld_i64(ctx->ir[IR_V0], tcg_env,
06ef8604 1135 offsetof(CPUAlphaState, usp));
2ace7e55
RH
1136 break;
1137 case 0x3C:
1138 /* WHAMI */
ad75a51e 1139 tcg_gen_ld32s_i64(ctx->ir[IR_V0], tcg_env,
55e5c285 1140 -offsetof(AlphaCPU, env) + offsetof(CPUState, cpu_index));
2ace7e55
RH
1141 break;
1142
bec5e2b9
RH
1143 case 0x3E:
1144 /* WTINT */
ad75a51e 1145 tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
904bd855
RH
1146 -offsetof(AlphaCPU, env) +
1147 offsetof(CPUState, halted));
bec5e2b9
RH
1148 tcg_gen_movi_i64(ctx->ir[IR_V0], 0);
1149 return gen_excp(ctx, EXCP_HALTED, 0);
1150
2ace7e55 1151 default:
ba96394e
RH
1152 palcode &= 0x3f;
1153 goto do_call_pal;
2ace7e55 1154 }
3de811c6 1155 return DISAS_NEXT;
2ace7e55
RH
1156 }
1157#endif
2ace7e55 1158 return gen_invalid(ctx);
ba96394e
RH
1159
1160 do_call_pal:
1161#ifdef CONFIG_USER_ONLY
1162 return gen_excp(ctx, EXCP_CALL_PAL, palcode);
1163#else
1164 {
2f458b7c 1165 TCGv tmp = tcg_temp_new();
c5f80657 1166 uint64_t exc_addr = ctx->base.pc_next;
2f458b7c
RH
1167 uint64_t entry = ctx->palbr;
1168
bcd2625d 1169 if (ctx->tbflags & ENV_FLAG_PAL_MODE) {
2f458b7c
RH
1170 exc_addr |= 1;
1171 } else {
1172 tcg_gen_movi_i64(tmp, 1);
bcd2625d 1173 st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
2f458b7c 1174 }
ba96394e 1175
2f458b7c 1176 tcg_gen_movi_i64(tmp, exc_addr);
ad75a51e 1177 tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUAlphaState, exc_addr));
ba96394e 1178
2f458b7c
RH
1179 entry += (palcode & 0x80
1180 ? 0x2000 + (palcode - 0x80) * 64
1181 : 0x1000 + palcode * 64);
a9ead832 1182
288a5fe9
RH
1183 tcg_gen_movi_i64(cpu_pc, entry);
1184 return DISAS_PC_UPDATED;
ba96394e
RH
1185 }
1186#endif
2ace7e55
RH
1187}
1188
26b46094
RH
1189#ifndef CONFIG_USER_ONLY
1190
26b46094
RH
1191#define PR_LONG 0x200000
1192
1193static int cpu_pr_data(int pr)
1194{
1195 switch (pr) {
26b46094
RH
1196 case 2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
1197 case 3: return offsetof(CPUAlphaState, trap_arg0);
1198 case 4: return offsetof(CPUAlphaState, trap_arg1);
1199 case 5: return offsetof(CPUAlphaState, trap_arg2);
1200 case 6: return offsetof(CPUAlphaState, exc_addr);
1201 case 7: return offsetof(CPUAlphaState, palbr);
1202 case 8: return offsetof(CPUAlphaState, ptbr);
1203 case 9: return offsetof(CPUAlphaState, vptptr);
1204 case 10: return offsetof(CPUAlphaState, unique);
1205 case 11: return offsetof(CPUAlphaState, sysval);
1206 case 12: return offsetof(CPUAlphaState, usp);
1207
26b46094
RH
1208 case 40 ... 63:
1209 return offsetof(CPUAlphaState, scratch[pr - 40]);
c781cf96
RH
1210
1211 case 251:
1212 return offsetof(CPUAlphaState, alarm_expire);
26b46094
RH
1213 }
1214 return 0;
1215}
1216
3de811c6 1217static DisasJumpType gen_mfpr(DisasContext *ctx, TCGv va, int regno)
26b46094 1218{
59124384
RH
1219 void (*helper)(TCGv);
1220 int data;
1221
1222 switch (regno) {
1223 case 32 ... 39:
1224 /* Accessing the "non-shadow" general registers. */
1225 regno = regno == 39 ? 25 : regno - 32 + 8;
1226 tcg_gen_mov_i64(va, cpu_std_ir[regno]);
1227 break;
1228
1229 case 250: /* WALLTIME */
1230 helper = gen_helper_get_walltime;
1231 goto do_helper;
1232 case 249: /* VMTIME */
1233 helper = gen_helper_get_vmtime;
1234 do_helper:
dfd1b812 1235 if (translator_io_start(&ctx->base)) {
0e154fe9 1236 helper(va);
3de811c6 1237 return DISAS_PC_STALE;
c781cf96 1238 } else {
0e154fe9 1239 helper(va);
c781cf96 1240 }
59124384 1241 break;
26b46094 1242
bcd2625d
RH
1243 case 0: /* PS */
1244 ld_flag_byte(va, ENV_FLAG_PS_SHIFT);
1245 break;
1246 case 1: /* FEN */
1247 ld_flag_byte(va, ENV_FLAG_FEN_SHIFT);
1248 break;
1249
59124384
RH
1250 default:
1251 /* The basic registers are data only, and unknown registers
1252 are read-zero, write-ignore. */
1253 data = cpu_pr_data(regno);
1254 if (data == 0) {
1255 tcg_gen_movi_i64(va, 0);
59124384 1256 } else if (data & PR_LONG) {
ad75a51e 1257 tcg_gen_ld32s_i64(va, tcg_env, data & ~PR_LONG);
59124384 1258 } else {
ad75a51e 1259 tcg_gen_ld_i64(va, tcg_env, data);
59124384
RH
1260 }
1261 break;
26b46094 1262 }
59124384 1263
3de811c6 1264 return DISAS_NEXT;
26b46094
RH
1265}
1266
3de811c6 1267static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
26b46094 1268{
bc24270e 1269 int data;
ef951ee3 1270 DisasJumpType ret = DISAS_NEXT;
26b46094 1271
bc24270e
RH
1272 switch (regno) {
1273 case 255:
3b4fefd6 1274 /* TBIA */
ad75a51e 1275 gen_helper_tbia(tcg_env);
bc24270e
RH
1276 break;
1277
1278 case 254:
3b4fefd6 1279 /* TBIS */
ad75a51e 1280 gen_helper_tbis(tcg_env, vb);
bc24270e
RH
1281 break;
1282
1283 case 253:
1284 /* WAIT */
ad75a51e 1285 tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
904bd855 1286 -offsetof(AlphaCPU, env) + offsetof(CPUState, halted));
bec5e2b9 1287 return gen_excp(ctx, EXCP_HALTED, 0);
bc24270e 1288
034ebc27
RH
1289 case 252:
1290 /* HALT */
0e154fe9 1291 gen_helper_halt(vb);
3de811c6 1292 return DISAS_PC_STALE;
034ebc27 1293
c781cf96
RH
1294 case 251:
1295 /* ALARM */
dfd1b812 1296 if (translator_io_start(&ctx->base)) {
ef951ee3
PD
1297 ret = DISAS_PC_STALE;
1298 }
ad75a51e 1299 gen_helper_set_alarm(tcg_env, vb);
c781cf96
RH
1300 break;
1301
a9ead832
RH
1302 case 7:
1303 /* PALBR */
ad75a51e 1304 tcg_gen_st_i64(vb, tcg_env, offsetof(CPUAlphaState, palbr));
a9ead832
RH
1305 /* Changing the PAL base register implies un-chaining all of the TBs
1306 that ended with a CALL_PAL. Since the base register usually only
1307 changes during boot, flushing everything works well. */
ad75a51e 1308 gen_helper_tb_flush(tcg_env);
3de811c6 1309 return DISAS_PC_STALE;
a9ead832 1310
59124384
RH
1311 case 32 ... 39:
1312 /* Accessing the "non-shadow" general registers. */
1313 regno = regno == 39 ? 25 : regno - 32 + 8;
1314 tcg_gen_mov_i64(cpu_std_ir[regno], vb);
1315 break;
1316
bcd2625d
RH
1317 case 0: /* PS */
1318 st_flag_byte(vb, ENV_FLAG_PS_SHIFT);
1319 break;
1320 case 1: /* FEN */
1321 st_flag_byte(vb, ENV_FLAG_FEN_SHIFT);
1322 break;
1323
bc24270e 1324 default:
3b4fefd6
RH
1325 /* The basic registers are data only, and unknown registers
1326 are read-zero, write-ignore. */
bc24270e 1327 data = cpu_pr_data(regno);
3b4fefd6 1328 if (data != 0) {
bcd2625d 1329 if (data & PR_LONG) {
ad75a51e 1330 tcg_gen_st32_i64(vb, tcg_env, data & ~PR_LONG);
3b4fefd6 1331 } else {
ad75a51e 1332 tcg_gen_st_i64(vb, tcg_env, data);
3b4fefd6 1333 }
26b46094 1334 }
bc24270e 1335 break;
26b46094
RH
1336 }
1337
ef951ee3 1338 return ret;
26b46094
RH
1339}
1340#endif /* !USER_ONLY*/
1341
ed085138
RH
1342#define REQUIRE_NO_LIT \
1343 do { \
1344 if (real_islit) { \
1345 goto invalid_opc; \
1346 } \
1347 } while (0)
1348
c6d41b36
RH
1349#define REQUIRE_AMASK(FLAG) \
1350 do { \
1351 if ((ctx->amask & AMASK_##FLAG) == 0) { \
1352 goto invalid_opc; \
1353 } \
1354 } while (0)
1355
5238c886
RH
1356#define REQUIRE_TB_FLAG(FLAG) \
1357 do { \
489a0e64 1358 if ((ctx->tbflags & (FLAG)) == 0) { \
5238c886
RH
1359 goto invalid_opc; \
1360 } \
1361 } while (0)
1362
64f45e49
RH
1363#define REQUIRE_REG_31(WHICH) \
1364 do { \
1365 if (WHICH != 31) { \
1366 goto invalid_opc; \
1367 } \
1368 } while (0)
1369
9d14a042
RH
1370#define REQUIRE_FEN \
1371 do { \
1372 if (!(ctx->tbflags & ENV_FLAG_FEN)) { \
1373 goto raise_fen; \
1374 } \
1375 } while (0)
1376
3de811c6 1377static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
4c9649a9 1378{
a9e05a1c 1379 int32_t disp21, disp16, disp12 __attribute__((unused));
f88fe4e3 1380 uint16_t fn11;
194cfb43 1381 uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
ed085138 1382 bool islit, real_islit;
4d1628e8 1383 TCGv va, vb, vc, tmp, tmp2;
075b8ddb 1384 TCGv_i32 t32;
3de811c6 1385 DisasJumpType ret;
4c9649a9
JM
1386
1387 /* Decode all instruction fields */
a9e05a1c
RH
1388 opc = extract32(insn, 26, 6);
1389 ra = extract32(insn, 21, 5);
1390 rb = extract32(insn, 16, 5);
1391 rc = extract32(insn, 0, 5);
ed085138 1392 real_islit = islit = extract32(insn, 12, 1);
a9e05a1c
RH
1393 lit = extract32(insn, 13, 8);
1394
1395 disp21 = sextract32(insn, 0, 21);
1396 disp16 = sextract32(insn, 0, 16);
1397 disp12 = sextract32(insn, 0, 12);
1398
1399 fn11 = extract32(insn, 5, 11);
1400 fpfn = extract32(insn, 5, 6);
1401 fn7 = extract32(insn, 5, 7);
1402
dfaa8583 1403 if (rb == 31 && !islit) {
a9e05a1c 1404 islit = true;
dfaa8583 1405 lit = 0;
194cfb43 1406 }
806991da 1407
3de811c6 1408 ret = DISAS_NEXT;
4c9649a9
JM
1409 switch (opc) {
1410 case 0x00:
1411 /* CALL_PAL */
a9e05a1c 1412 ret = gen_call_pal(ctx, insn & 0x03ffffff);
2ace7e55 1413 break;
4c9649a9
JM
1414 case 0x01:
1415 /* OPC01 */
1416 goto invalid_opc;
1417 case 0x02:
1418 /* OPC02 */
1419 goto invalid_opc;
1420 case 0x03:
1421 /* OPC03 */
1422 goto invalid_opc;
1423 case 0x04:
1424 /* OPC04 */
1425 goto invalid_opc;
1426 case 0x05:
1427 /* OPC05 */
1428 goto invalid_opc;
1429 case 0x06:
1430 /* OPC06 */
1431 goto invalid_opc;
1432 case 0x07:
1433 /* OPC07 */
1434 goto invalid_opc;
194cfb43 1435
4c9649a9
JM
1436 case 0x09:
1437 /* LDAH */
194cfb43
RH
1438 disp16 = (uint32_t)disp16 << 16;
1439 /* fall through */
1440 case 0x08:
1441 /* LDA */
1442 va = dest_gpr(ctx, ra);
1443 /* It's worth special-casing immediate loads. */
1444 if (rb == 31) {
1445 tcg_gen_movi_i64(va, disp16);
1446 } else {
1447 tcg_gen_addi_i64(va, load_gpr(ctx, rb), disp16);
496cb5b9 1448 }
4c9649a9 1449 break;
194cfb43 1450
4c9649a9
JM
1451 case 0x0A:
1452 /* LDBU */
c6d41b36 1453 REQUIRE_AMASK(BWX);
5ffcb334 1454 gen_load_int(ctx, ra, rb, disp16, MO_UB, 0, 0);
5238c886 1455 break;
4c9649a9
JM
1456 case 0x0B:
1457 /* LDQ_U */
fc313c64 1458 gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 1, 0);
4c9649a9
JM
1459 break;
1460 case 0x0C:
1461 /* LDWU */
c6d41b36 1462 REQUIRE_AMASK(BWX);
5ffcb334 1463 gen_load_int(ctx, ra, rb, disp16, MO_LEUW, 0, 0);
5238c886 1464 break;
4c9649a9
JM
1465 case 0x0D:
1466 /* STW */
c6d41b36 1467 REQUIRE_AMASK(BWX);
5ffcb334 1468 gen_store_int(ctx, ra, rb, disp16, MO_LEUW, 0);
4c9649a9
JM
1469 break;
1470 case 0x0E:
1471 /* STB */
c6d41b36 1472 REQUIRE_AMASK(BWX);
5ffcb334 1473 gen_store_int(ctx, ra, rb, disp16, MO_UB, 0);
4c9649a9
JM
1474 break;
1475 case 0x0F:
1476 /* STQ_U */
fc313c64 1477 gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 1);
4c9649a9 1478 break;
194cfb43 1479
4c9649a9 1480 case 0x10:
194cfb43
RH
1481 vc = dest_gpr(ctx, rc);
1482 vb = load_gpr_lit(ctx, rb, lit, islit);
1483
1484 if (ra == 31) {
1485 if (fn7 == 0x00) {
1486 /* Special case ADDL as SEXTL. */
1487 tcg_gen_ext32s_i64(vc, vb);
1488 break;
1489 }
1490 if (fn7 == 0x29) {
1491 /* Special case SUBQ as NEGQ. */
1492 tcg_gen_neg_i64(vc, vb);
1493 break;
1494 }
1495 }
1496
1497 va = load_gpr(ctx, ra);
4c9649a9
JM
1498 switch (fn7) {
1499 case 0x00:
1500 /* ADDL */
194cfb43
RH
1501 tcg_gen_add_i64(vc, va, vb);
1502 tcg_gen_ext32s_i64(vc, vc);
4c9649a9
JM
1503 break;
1504 case 0x02:
1505 /* S4ADDL */
194cfb43
RH
1506 tmp = tcg_temp_new();
1507 tcg_gen_shli_i64(tmp, va, 2);
1508 tcg_gen_add_i64(tmp, tmp, vb);
1509 tcg_gen_ext32s_i64(vc, tmp);
4c9649a9
JM
1510 break;
1511 case 0x09:
1512 /* SUBL */
194cfb43
RH
1513 tcg_gen_sub_i64(vc, va, vb);
1514 tcg_gen_ext32s_i64(vc, vc);
4c9649a9
JM
1515 break;
1516 case 0x0B:
1517 /* S4SUBL */
194cfb43
RH
1518 tmp = tcg_temp_new();
1519 tcg_gen_shli_i64(tmp, va, 2);
1520 tcg_gen_sub_i64(tmp, tmp, vb);
1521 tcg_gen_ext32s_i64(vc, tmp);
4c9649a9
JM
1522 break;
1523 case 0x0F:
1524 /* CMPBGE */
112e4518
RH
1525 if (ra == 31) {
1526 /* Special case 0 >= X as X == 0. */
1527 gen_helper_cmpbe0(vc, vb);
1528 } else {
1529 gen_helper_cmpbge(vc, va, vb);
1530 }
4c9649a9
JM
1531 break;
1532 case 0x12:
1533 /* S8ADDL */
194cfb43
RH
1534 tmp = tcg_temp_new();
1535 tcg_gen_shli_i64(tmp, va, 3);
1536 tcg_gen_add_i64(tmp, tmp, vb);
1537 tcg_gen_ext32s_i64(vc, tmp);
4c9649a9
JM
1538 break;
1539 case 0x1B:
1540 /* S8SUBL */
194cfb43
RH
1541 tmp = tcg_temp_new();
1542 tcg_gen_shli_i64(tmp, va, 3);
1543 tcg_gen_sub_i64(tmp, tmp, vb);
1544 tcg_gen_ext32s_i64(vc, tmp);
4c9649a9
JM
1545 break;
1546 case 0x1D:
1547 /* CMPULT */
95868348 1548 tcg_gen_setcond_i64(TCG_COND_LTU, vc, va, vb);
4c9649a9
JM
1549 break;
1550 case 0x20:
1551 /* ADDQ */
194cfb43 1552 tcg_gen_add_i64(vc, va, vb);
4c9649a9
JM
1553 break;
1554 case 0x22:
1555 /* S4ADDQ */
194cfb43
RH
1556 tmp = tcg_temp_new();
1557 tcg_gen_shli_i64(tmp, va, 2);
1558 tcg_gen_add_i64(vc, tmp, vb);
4c9649a9
JM
1559 break;
1560 case 0x29:
1561 /* SUBQ */
194cfb43 1562 tcg_gen_sub_i64(vc, va, vb);
4c9649a9
JM
1563 break;
1564 case 0x2B:
1565 /* S4SUBQ */
194cfb43
RH
1566 tmp = tcg_temp_new();
1567 tcg_gen_shli_i64(tmp, va, 2);
1568 tcg_gen_sub_i64(vc, tmp, vb);
4c9649a9
JM
1569 break;
1570 case 0x2D:
1571 /* CMPEQ */
95868348 1572 tcg_gen_setcond_i64(TCG_COND_EQ, vc, va, vb);
4c9649a9
JM
1573 break;
1574 case 0x32:
1575 /* S8ADDQ */
194cfb43
RH
1576 tmp = tcg_temp_new();
1577 tcg_gen_shli_i64(tmp, va, 3);
1578 tcg_gen_add_i64(vc, tmp, vb);
4c9649a9
JM
1579 break;
1580 case 0x3B:
1581 /* S8SUBQ */
194cfb43
RH
1582 tmp = tcg_temp_new();
1583 tcg_gen_shli_i64(tmp, va, 3);
1584 tcg_gen_sub_i64(vc, tmp, vb);
4c9649a9
JM
1585 break;
1586 case 0x3D:
1587 /* CMPULE */
95868348 1588 tcg_gen_setcond_i64(TCG_COND_LEU, vc, va, vb);
4c9649a9
JM
1589 break;
1590 case 0x40:
1591 /* ADDL/V */
4d1628e8
RH
1592 tmp = tcg_temp_new();
1593 tcg_gen_ext32s_i64(tmp, va);
1594 tcg_gen_ext32s_i64(vc, vb);
1595 tcg_gen_add_i64(tmp, tmp, vc);
1596 tcg_gen_ext32s_i64(vc, tmp);
ad75a51e 1597 gen_helper_check_overflow(tcg_env, vc, tmp);
4c9649a9
JM
1598 break;
1599 case 0x49:
1600 /* SUBL/V */
4d1628e8
RH
1601 tmp = tcg_temp_new();
1602 tcg_gen_ext32s_i64(tmp, va);
1603 tcg_gen_ext32s_i64(vc, vb);
1604 tcg_gen_sub_i64(tmp, tmp, vc);
1605 tcg_gen_ext32s_i64(vc, tmp);
ad75a51e 1606 gen_helper_check_overflow(tcg_env, vc, tmp);
4c9649a9
JM
1607 break;
1608 case 0x4D:
1609 /* CMPLT */
95868348 1610 tcg_gen_setcond_i64(TCG_COND_LT, vc, va, vb);
4c9649a9
JM
1611 break;
1612 case 0x60:
1613 /* ADDQ/V */
4d1628e8
RH
1614 tmp = tcg_temp_new();
1615 tmp2 = tcg_temp_new();
1616 tcg_gen_eqv_i64(tmp, va, vb);
1617 tcg_gen_mov_i64(tmp2, va);
1618 tcg_gen_add_i64(vc, va, vb);
1619 tcg_gen_xor_i64(tmp2, tmp2, vc);
1620 tcg_gen_and_i64(tmp, tmp, tmp2);
1621 tcg_gen_shri_i64(tmp, tmp, 63);
1622 tcg_gen_movi_i64(tmp2, 0);
ad75a51e 1623 gen_helper_check_overflow(tcg_env, tmp, tmp2);
4c9649a9
JM
1624 break;
1625 case 0x69:
1626 /* SUBQ/V */
4d1628e8
RH
1627 tmp = tcg_temp_new();
1628 tmp2 = tcg_temp_new();
1629 tcg_gen_xor_i64(tmp, va, vb);
1630 tcg_gen_mov_i64(tmp2, va);
1631 tcg_gen_sub_i64(vc, va, vb);
1632 tcg_gen_xor_i64(tmp2, tmp2, vc);
1633 tcg_gen_and_i64(tmp, tmp, tmp2);
1634 tcg_gen_shri_i64(tmp, tmp, 63);
1635 tcg_gen_movi_i64(tmp2, 0);
ad75a51e 1636 gen_helper_check_overflow(tcg_env, tmp, tmp2);
4c9649a9
JM
1637 break;
1638 case 0x6D:
1639 /* CMPLE */
95868348 1640 tcg_gen_setcond_i64(TCG_COND_LE, vc, va, vb);
4c9649a9
JM
1641 break;
1642 default:
1643 goto invalid_opc;
1644 }
1645 break;
db4a1645 1646
4c9649a9 1647 case 0x11:
db4a1645
RH
1648 if (fn7 == 0x20) {
1649 if (rc == 31) {
1650 /* Special case BIS as NOP. */
1651 break;
1652 }
1653 if (ra == 31) {
1654 /* Special case BIS as MOV. */
1655 vc = dest_gpr(ctx, rc);
1656 if (islit) {
1657 tcg_gen_movi_i64(vc, lit);
67debe3a 1658 } else {
db4a1645 1659 tcg_gen_mov_i64(vc, load_gpr(ctx, rb));
67debe3a 1660 }
db4a1645 1661 break;
30c7183b 1662 }
db4a1645
RH
1663 }
1664
1665 vc = dest_gpr(ctx, rc);
1666 vb = load_gpr_lit(ctx, rb, lit, islit);
1667
1668 if (fn7 == 0x28 && ra == 31) {
1669 /* Special case ORNOT as NOT. */
1670 tcg_gen_not_i64(vc, vb);
1671 break;
1672 }
1673
1674 va = load_gpr(ctx, ra);
1675 switch (fn7) {
1676 case 0x00:
1677 /* AND */
1678 tcg_gen_and_i64(vc, va, vb);
4c9649a9
JM
1679 break;
1680 case 0x08:
1681 /* BIC */
db4a1645 1682 tcg_gen_andc_i64(vc, va, vb);
4c9649a9
JM
1683 break;
1684 case 0x14:
1685 /* CMOVLBS */
83ebb7cd
RH
1686 tmp = tcg_temp_new();
1687 tcg_gen_andi_i64(tmp, va, 1);
1688 tcg_gen_movcond_i64(TCG_COND_NE, vc, tmp, load_zero(ctx),
1689 vb, load_gpr(ctx, rc));
4c9649a9
JM
1690 break;
1691 case 0x16:
1692 /* CMOVLBC */
83ebb7cd
RH
1693 tmp = tcg_temp_new();
1694 tcg_gen_andi_i64(tmp, va, 1);
1695 tcg_gen_movcond_i64(TCG_COND_EQ, vc, tmp, load_zero(ctx),
1696 vb, load_gpr(ctx, rc));
4c9649a9
JM
1697 break;
1698 case 0x20:
1699 /* BIS */
db4a1645 1700 tcg_gen_or_i64(vc, va, vb);
4c9649a9
JM
1701 break;
1702 case 0x24:
1703 /* CMOVEQ */
83ebb7cd
RH
1704 tcg_gen_movcond_i64(TCG_COND_EQ, vc, va, load_zero(ctx),
1705 vb, load_gpr(ctx, rc));
4c9649a9
JM
1706 break;
1707 case 0x26:
1708 /* CMOVNE */
83ebb7cd
RH
1709 tcg_gen_movcond_i64(TCG_COND_NE, vc, va, load_zero(ctx),
1710 vb, load_gpr(ctx, rc));
4c9649a9
JM
1711 break;
1712 case 0x28:
1713 /* ORNOT */
db4a1645 1714 tcg_gen_orc_i64(vc, va, vb);
4c9649a9
JM
1715 break;
1716 case 0x40:
1717 /* XOR */
db4a1645 1718 tcg_gen_xor_i64(vc, va, vb);
4c9649a9
JM
1719 break;
1720 case 0x44:
1721 /* CMOVLT */
83ebb7cd
RH
1722 tcg_gen_movcond_i64(TCG_COND_LT, vc, va, load_zero(ctx),
1723 vb, load_gpr(ctx, rc));
4c9649a9
JM
1724 break;
1725 case 0x46:
1726 /* CMOVGE */
83ebb7cd
RH
1727 tcg_gen_movcond_i64(TCG_COND_GE, vc, va, load_zero(ctx),
1728 vb, load_gpr(ctx, rc));
4c9649a9
JM
1729 break;
1730 case 0x48:
1731 /* EQV */
db4a1645 1732 tcg_gen_eqv_i64(vc, va, vb);
4c9649a9
JM
1733 break;
1734 case 0x61:
1735 /* AMASK */
64f45e49 1736 REQUIRE_REG_31(ra);
c6d41b36 1737 tcg_gen_andi_i64(vc, vb, ~ctx->amask);
4c9649a9
JM
1738 break;
1739 case 0x64:
1740 /* CMOVLE */
83ebb7cd
RH
1741 tcg_gen_movcond_i64(TCG_COND_LE, vc, va, load_zero(ctx),
1742 vb, load_gpr(ctx, rc));
4c9649a9
JM
1743 break;
1744 case 0x66:
1745 /* CMOVGT */
83ebb7cd
RH
1746 tcg_gen_movcond_i64(TCG_COND_GT, vc, va, load_zero(ctx),
1747 vb, load_gpr(ctx, rc));
4c9649a9
JM
1748 break;
1749 case 0x6C:
1750 /* IMPLVER */
64f45e49 1751 REQUIRE_REG_31(ra);
db4a1645 1752 tcg_gen_movi_i64(vc, ctx->implver);
4c9649a9
JM
1753 break;
1754 default:
1755 goto invalid_opc;
1756 }
1757 break;
3bd67b7d 1758
4c9649a9 1759 case 0x12:
3bd67b7d
RH
1760 vc = dest_gpr(ctx, rc);
1761 va = load_gpr(ctx, ra);
4c9649a9
JM
1762 switch (fn7) {
1763 case 0x02:
1764 /* MSKBL */
9a8fa1bd 1765 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x01);
4c9649a9
JM
1766 break;
1767 case 0x06:
1768 /* EXTBL */
9a734d64 1769 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x01);
4c9649a9
JM
1770 break;
1771 case 0x0B:
1772 /* INSBL */
5e5863ec 1773 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x01);
4c9649a9
JM
1774 break;
1775 case 0x12:
1776 /* MSKWL */
9a8fa1bd 1777 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x03);
4c9649a9
JM
1778 break;
1779 case 0x16:
1780 /* EXTWL */
9a734d64 1781 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x03);
4c9649a9
JM
1782 break;
1783 case 0x1B:
1784 /* INSWL */
5e5863ec 1785 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x03);
4c9649a9
JM
1786 break;
1787 case 0x22:
1788 /* MSKLL */
9a8fa1bd 1789 gen_msk_l(ctx, vc, va, rb, islit, lit, 0x0f);
4c9649a9
JM
1790 break;
1791 case 0x26:
1792 /* EXTLL */
9a734d64 1793 gen_ext_l(ctx, vc, va, rb, islit, lit, 0x0f);
4c9649a9
JM
1794 break;
1795 case 0x2B:
1796 /* INSLL */
5e5863ec 1797 gen_ins_l(ctx, vc, va, rb, islit, lit, 0x0f);
4c9649a9
JM
1798 break;
1799 case 0x30:
1800 /* ZAP */
b144be9e
RH
1801 if (islit) {
1802 gen_zapnoti(vc, va, ~lit);
1803 } else {
1804 gen_helper_zap(vc, va, load_gpr(ctx, rb));
1805 }
4c9649a9
JM
1806 break;
1807 case 0x31:
1808 /* ZAPNOT */
b144be9e
RH
1809 if (islit) {
1810 gen_zapnoti(vc, va, lit);
1811 } else {
1812 gen_helper_zapnot(vc, va, load_gpr(ctx, rb));
1813 }
4c9649a9
JM
1814 break;
1815 case 0x32:
1816 /* MSKQL */
9a8fa1bd 1817 gen_msk_l(ctx, vc, va, rb, islit, lit, 0xff);
4c9649a9
JM
1818 break;
1819 case 0x34:
1820 /* SRL */
3bd67b7d
RH
1821 if (islit) {
1822 tcg_gen_shri_i64(vc, va, lit & 0x3f);
1823 } else {
1824 tmp = tcg_temp_new();
1825 vb = load_gpr(ctx, rb);
1826 tcg_gen_andi_i64(tmp, vb, 0x3f);
1827 tcg_gen_shr_i64(vc, va, tmp);
30c7183b 1828 }
4c9649a9
JM
1829 break;
1830 case 0x36:
1831 /* EXTQL */
9a734d64 1832 gen_ext_l(ctx, vc, va, rb, islit, lit, 0xff);
4c9649a9
JM
1833 break;
1834 case 0x39:
1835 /* SLL */
3bd67b7d
RH
1836 if (islit) {
1837 tcg_gen_shli_i64(vc, va, lit & 0x3f);
1838 } else {
1839 tmp = tcg_temp_new();
1840 vb = load_gpr(ctx, rb);
1841 tcg_gen_andi_i64(tmp, vb, 0x3f);
1842 tcg_gen_shl_i64(vc, va, tmp);
30c7183b 1843 }
4c9649a9
JM
1844 break;
1845 case 0x3B:
1846 /* INSQL */
5e5863ec 1847 gen_ins_l(ctx, vc, va, rb, islit, lit, 0xff);
4c9649a9
JM
1848 break;
1849 case 0x3C:
1850 /* SRA */
3bd67b7d
RH
1851 if (islit) {
1852 tcg_gen_sari_i64(vc, va, lit & 0x3f);
1853 } else {
1854 tmp = tcg_temp_new();
1855 vb = load_gpr(ctx, rb);
1856 tcg_gen_andi_i64(tmp, vb, 0x3f);
1857 tcg_gen_sar_i64(vc, va, tmp);
30c7183b 1858 }
4c9649a9
JM
1859 break;
1860 case 0x52:
1861 /* MSKWH */
9a8fa1bd 1862 gen_msk_h(ctx, vc, va, rb, islit, lit, 0x03);
4c9649a9
JM
1863 break;
1864 case 0x57:
1865 /* INSWH */
5e5863ec 1866 gen_ins_h(ctx, vc, va, rb, islit, lit, 0x03);
4c9649a9
JM
1867 break;
1868 case 0x5A:
1869 /* EXTWH */
9a734d64 1870 gen_ext_h(ctx, vc, va, rb, islit, lit, 0x03);
4c9649a9
JM
1871 break;
1872 case 0x62:
1873 /* MSKLH */
9a8fa1bd 1874 gen_msk_h(ctx, vc, va, rb, islit, lit, 0x0f);
4c9649a9
JM
1875 break;
1876 case 0x67:
1877 /* INSLH */
5e5863ec 1878 gen_ins_h(ctx, vc, va, rb, islit, lit, 0x0f);
4c9649a9
JM
1879 break;
1880 case 0x6A:
1881 /* EXTLH */
9a734d64 1882 gen_ext_h(ctx, vc, va, rb, islit, lit, 0x0f);
4c9649a9
JM
1883 break;
1884 case 0x72:
1885 /* MSKQH */
9a8fa1bd 1886 gen_msk_h(ctx, vc, va, rb, islit, lit, 0xff);
4c9649a9
JM
1887 break;
1888 case 0x77:
1889 /* INSQH */
5e5863ec 1890 gen_ins_h(ctx, vc, va, rb, islit, lit, 0xff);
4c9649a9
JM
1891 break;
1892 case 0x7A:
1893 /* EXTQH */
9a734d64 1894 gen_ext_h(ctx, vc, va, rb, islit, lit, 0xff);
4c9649a9
JM
1895 break;
1896 default:
1897 goto invalid_opc;
1898 }
1899 break;
de4d3555 1900
4c9649a9 1901 case 0x13:
de4d3555
RH
1902 vc = dest_gpr(ctx, rc);
1903 vb = load_gpr_lit(ctx, rb, lit, islit);
1904 va = load_gpr(ctx, ra);
4c9649a9
JM
1905 switch (fn7) {
1906 case 0x00:
1907 /* MULL */
de4d3555
RH
1908 tcg_gen_mul_i64(vc, va, vb);
1909 tcg_gen_ext32s_i64(vc, vc);
4c9649a9
JM
1910 break;
1911 case 0x20:
1912 /* MULQ */
de4d3555 1913 tcg_gen_mul_i64(vc, va, vb);
4c9649a9
JM
1914 break;
1915 case 0x30:
1916 /* UMULH */
de4d3555
RH
1917 tmp = tcg_temp_new();
1918 tcg_gen_mulu2_i64(tmp, vc, va, vb);
4c9649a9
JM
1919 break;
1920 case 0x40:
1921 /* MULL/V */
4d1628e8
RH
1922 tmp = tcg_temp_new();
1923 tcg_gen_ext32s_i64(tmp, va);
1924 tcg_gen_ext32s_i64(vc, vb);
1925 tcg_gen_mul_i64(tmp, tmp, vc);
1926 tcg_gen_ext32s_i64(vc, tmp);
ad75a51e 1927 gen_helper_check_overflow(tcg_env, vc, tmp);
4c9649a9
JM
1928 break;
1929 case 0x60:
1930 /* MULQ/V */
4d1628e8
RH
1931 tmp = tcg_temp_new();
1932 tmp2 = tcg_temp_new();
1933 tcg_gen_muls2_i64(vc, tmp, va, vb);
1934 tcg_gen_sari_i64(tmp2, vc, 63);
ad75a51e 1935 gen_helper_check_overflow(tcg_env, tmp, tmp2);
4c9649a9
JM
1936 break;
1937 default:
1938 goto invalid_opc;
1939 }
1940 break;
075b8ddb 1941
4c9649a9 1942 case 0x14:
c6d41b36 1943 REQUIRE_AMASK(FIX);
baee04ab 1944 vc = dest_fpr(ctx, rc);
f24518b5 1945 switch (fpfn) { /* fn11 & 0x3F */
4c9649a9
JM
1946 case 0x04:
1947 /* ITOFS */
64f45e49 1948 REQUIRE_REG_31(rb);
9d14a042 1949 REQUIRE_FEN;
075b8ddb
RH
1950 t32 = tcg_temp_new_i32();
1951 va = load_gpr(ctx, ra);
ecc7b3aa 1952 tcg_gen_extrl_i64_i32(t32, va);
075b8ddb 1953 gen_helper_memory_to_s(vc, t32);
4c9649a9
JM
1954 break;
1955 case 0x0A:
1956 /* SQRTF */
64f45e49 1957 REQUIRE_REG_31(ra);
9d14a042 1958 REQUIRE_FEN;
baee04ab 1959 vb = load_fpr(ctx, rb);
ad75a51e 1960 gen_helper_sqrtf(vc, tcg_env, vb);
5238c886 1961 break;
4c9649a9
JM
1962 case 0x0B:
1963 /* SQRTS */
64f45e49 1964 REQUIRE_REG_31(ra);
9d14a042 1965 REQUIRE_FEN;
3da653fa 1966 gen_sqrts(ctx, rb, rc, fn11);
5238c886 1967 break;
4c9649a9
JM
1968 case 0x14:
1969 /* ITOFF */
64f45e49 1970 REQUIRE_REG_31(rb);
9d14a042 1971 REQUIRE_FEN;
075b8ddb
RH
1972 t32 = tcg_temp_new_i32();
1973 va = load_gpr(ctx, ra);
ecc7b3aa 1974 tcg_gen_extrl_i64_i32(t32, va);
075b8ddb 1975 gen_helper_memory_to_f(vc, t32);
4c9649a9
JM
1976 break;
1977 case 0x24:
1978 /* ITOFT */
64f45e49 1979 REQUIRE_REG_31(rb);
9d14a042 1980 REQUIRE_FEN;
075b8ddb 1981 va = load_gpr(ctx, ra);
075b8ddb 1982 tcg_gen_mov_i64(vc, va);
4c9649a9
JM
1983 break;
1984 case 0x2A:
1985 /* SQRTG */
64f45e49 1986 REQUIRE_REG_31(ra);
9d14a042 1987 REQUIRE_FEN;
baee04ab 1988 vb = load_fpr(ctx, rb);
ad75a51e 1989 gen_helper_sqrtg(vc, tcg_env, vb);
5238c886 1990 break;
4c9649a9
JM
1991 case 0x02B:
1992 /* SQRTT */
64f45e49 1993 REQUIRE_REG_31(ra);
9d14a042 1994 REQUIRE_FEN;
3da653fa 1995 gen_sqrtt(ctx, rb, rc, fn11);
5238c886 1996 break;
4c9649a9
JM
1997 default:
1998 goto invalid_opc;
1999 }
2000 break;
6b88b37c 2001
4c9649a9
JM
2002 case 0x15:
2003 /* VAX floating point */
2004 /* XXX: rounding mode and trap are ignored (!) */
baee04ab
RH
2005 vc = dest_fpr(ctx, rc);
2006 vb = load_fpr(ctx, rb);
3d045dbc 2007 va = load_fpr(ctx, ra);
f24518b5 2008 switch (fpfn) { /* fn11 & 0x3F */
4c9649a9
JM
2009 case 0x00:
2010 /* ADDF */
9d14a042 2011 REQUIRE_FEN;
ad75a51e 2012 gen_helper_addf(vc, tcg_env, va, vb);
4c9649a9
JM
2013 break;
2014 case 0x01:
2015 /* SUBF */
9d14a042 2016 REQUIRE_FEN;
ad75a51e 2017 gen_helper_subf(vc, tcg_env, va, vb);
4c9649a9
JM
2018 break;
2019 case 0x02:
2020 /* MULF */
9d14a042 2021 REQUIRE_FEN;
ad75a51e 2022 gen_helper_mulf(vc, tcg_env, va, vb);
4c9649a9
JM
2023 break;
2024 case 0x03:
2025 /* DIVF */
9d14a042 2026 REQUIRE_FEN;
ad75a51e 2027 gen_helper_divf(vc, tcg_env, va, vb);
4c9649a9
JM
2028 break;
2029 case 0x1E:
64f45e49
RH
2030 /* CVTDG -- TODO */
2031 REQUIRE_REG_31(ra);
4c9649a9 2032 goto invalid_opc;
4c9649a9
JM
2033 case 0x20:
2034 /* ADDG */
9d14a042 2035 REQUIRE_FEN;
ad75a51e 2036 gen_helper_addg(vc, tcg_env, va, vb);
4c9649a9
JM
2037 break;
2038 case 0x21:
2039 /* SUBG */
9d14a042 2040 REQUIRE_FEN;
ad75a51e 2041 gen_helper_subg(vc, tcg_env, va, vb);
4c9649a9
JM
2042 break;
2043 case 0x22:
2044 /* MULG */
9d14a042 2045 REQUIRE_FEN;
ad75a51e 2046 gen_helper_mulg(vc, tcg_env, va, vb);
4c9649a9
JM
2047 break;
2048 case 0x23:
2049 /* DIVG */
9d14a042 2050 REQUIRE_FEN;
ad75a51e 2051 gen_helper_divg(vc, tcg_env, va, vb);
4c9649a9
JM
2052 break;
2053 case 0x25:
2054 /* CMPGEQ */
9d14a042 2055 REQUIRE_FEN;
ad75a51e 2056 gen_helper_cmpgeq(vc, tcg_env, va, vb);
4c9649a9
JM
2057 break;
2058 case 0x26:
2059 /* CMPGLT */
9d14a042 2060 REQUIRE_FEN;
ad75a51e 2061 gen_helper_cmpglt(vc, tcg_env, va, vb);
4c9649a9
JM
2062 break;
2063 case 0x27:
2064 /* CMPGLE */
9d14a042 2065 REQUIRE_FEN;
ad75a51e 2066 gen_helper_cmpgle(vc, tcg_env, va, vb);
4c9649a9
JM
2067 break;
2068 case 0x2C:
2069 /* CVTGF */
64f45e49 2070 REQUIRE_REG_31(ra);
9d14a042 2071 REQUIRE_FEN;
ad75a51e 2072 gen_helper_cvtgf(vc, tcg_env, vb);
4c9649a9
JM
2073 break;
2074 case 0x2D:
64f45e49
RH
2075 /* CVTGD -- TODO */
2076 REQUIRE_REG_31(ra);
4c9649a9 2077 goto invalid_opc;
4c9649a9
JM
2078 case 0x2F:
2079 /* CVTGQ */
64f45e49 2080 REQUIRE_REG_31(ra);
9d14a042 2081 REQUIRE_FEN;
ad75a51e 2082 gen_helper_cvtgq(vc, tcg_env, vb);
4c9649a9
JM
2083 break;
2084 case 0x3C:
2085 /* CVTQF */
64f45e49 2086 REQUIRE_REG_31(ra);
9d14a042 2087 REQUIRE_FEN;
ad75a51e 2088 gen_helper_cvtqf(vc, tcg_env, vb);
4c9649a9
JM
2089 break;
2090 case 0x3E:
2091 /* CVTQG */
64f45e49 2092 REQUIRE_REG_31(ra);
9d14a042 2093 REQUIRE_FEN;
ad75a51e 2094 gen_helper_cvtqg(vc, tcg_env, vb);
4c9649a9
JM
2095 break;
2096 default:
2097 goto invalid_opc;
2098 }
2099 break;
6b88b37c 2100
4c9649a9
JM
2101 case 0x16:
2102 /* IEEE floating-point */
f24518b5 2103 switch (fpfn) { /* fn11 & 0x3F */
4c9649a9
JM
2104 case 0x00:
2105 /* ADDS */
9d14a042 2106 REQUIRE_FEN;
3da653fa 2107 gen_adds(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2108 break;
2109 case 0x01:
2110 /* SUBS */
9d14a042 2111 REQUIRE_FEN;
3da653fa 2112 gen_subs(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2113 break;
2114 case 0x02:
2115 /* MULS */
9d14a042 2116 REQUIRE_FEN;
3da653fa 2117 gen_muls(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2118 break;
2119 case 0x03:
2120 /* DIVS */
9d14a042 2121 REQUIRE_FEN;
3da653fa 2122 gen_divs(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2123 break;
2124 case 0x20:
2125 /* ADDT */
9d14a042 2126 REQUIRE_FEN;
3da653fa 2127 gen_addt(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2128 break;
2129 case 0x21:
2130 /* SUBT */
9d14a042 2131 REQUIRE_FEN;
3da653fa 2132 gen_subt(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2133 break;
2134 case 0x22:
2135 /* MULT */
9d14a042 2136 REQUIRE_FEN;
3da653fa 2137 gen_mult(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2138 break;
2139 case 0x23:
2140 /* DIVT */
9d14a042 2141 REQUIRE_FEN;
3da653fa 2142 gen_divt(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2143 break;
2144 case 0x24:
2145 /* CMPTUN */
9d14a042 2146 REQUIRE_FEN;
3da653fa 2147 gen_cmptun(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2148 break;
2149 case 0x25:
2150 /* CMPTEQ */
9d14a042 2151 REQUIRE_FEN;
3da653fa 2152 gen_cmpteq(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2153 break;
2154 case 0x26:
2155 /* CMPTLT */
9d14a042 2156 REQUIRE_FEN;
3da653fa 2157 gen_cmptlt(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2158 break;
2159 case 0x27:
2160 /* CMPTLE */
9d14a042 2161 REQUIRE_FEN;
3da653fa 2162 gen_cmptle(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2163 break;
2164 case 0x2C:
64f45e49 2165 REQUIRE_REG_31(ra);
9d14a042 2166 REQUIRE_FEN;
a74b4d2c 2167 if (fn11 == 0x2AC || fn11 == 0x6AC) {
4c9649a9 2168 /* CVTST */
3da653fa 2169 gen_cvtst(ctx, rb, rc, fn11);
4c9649a9
JM
2170 } else {
2171 /* CVTTS */
3da653fa 2172 gen_cvtts(ctx, rb, rc, fn11);
4c9649a9
JM
2173 }
2174 break;
2175 case 0x2F:
2176 /* CVTTQ */
64f45e49 2177 REQUIRE_REG_31(ra);
9d14a042 2178 REQUIRE_FEN;
3da653fa 2179 gen_cvttq(ctx, rb, rc, fn11);
4c9649a9
JM
2180 break;
2181 case 0x3C:
2182 /* CVTQS */
64f45e49 2183 REQUIRE_REG_31(ra);
9d14a042 2184 REQUIRE_FEN;
3da653fa 2185 gen_cvtqs(ctx, rb, rc, fn11);
4c9649a9
JM
2186 break;
2187 case 0x3E:
2188 /* CVTQT */
64f45e49 2189 REQUIRE_REG_31(ra);
9d14a042 2190 REQUIRE_FEN;
3da653fa 2191 gen_cvtqt(ctx, rb, rc, fn11);
4c9649a9
JM
2192 break;
2193 default:
2194 goto invalid_opc;
2195 }
2196 break;
6b88b37c 2197
4c9649a9
JM
2198 case 0x17:
2199 switch (fn11) {
2200 case 0x010:
2201 /* CVTLQ */
64f45e49 2202 REQUIRE_REG_31(ra);
9d14a042 2203 REQUIRE_FEN;
e8d8fef4
RH
2204 vc = dest_fpr(ctx, rc);
2205 vb = load_fpr(ctx, rb);
3da653fa 2206 gen_cvtlq(vc, vb);
4c9649a9
JM
2207 break;
2208 case 0x020:
6b88b37c 2209 /* CPYS */
9d14a042 2210 REQUIRE_FEN;
6b88b37c
RH
2211 if (rc == 31) {
2212 /* Special case CPYS as FNOP. */
ef3765cb 2213 } else {
6b88b37c 2214 vc = dest_fpr(ctx, rc);
ef3765cb
RH
2215 va = load_fpr(ctx, ra);
2216 if (ra == rb) {
2217 /* Special case CPYS as FMOV. */
6b88b37c 2218 tcg_gen_mov_i64(vc, va);
ef3765cb
RH
2219 } else {
2220 vb = load_fpr(ctx, rb);
2221 gen_cpy_mask(vc, va, vb, 0, 0x8000000000000000ULL);
a06d48d9 2222 }
4c9649a9
JM
2223 }
2224 break;
2225 case 0x021:
2226 /* CPYSN */
9d14a042 2227 REQUIRE_FEN;
ef3765cb
RH
2228 vc = dest_fpr(ctx, rc);
2229 vb = load_fpr(ctx, rb);
2230 va = load_fpr(ctx, ra);
2231 gen_cpy_mask(vc, va, vb, 1, 0x8000000000000000ULL);
4c9649a9
JM
2232 break;
2233 case 0x022:
2234 /* CPYSE */
9d14a042 2235 REQUIRE_FEN;
ef3765cb
RH
2236 vc = dest_fpr(ctx, rc);
2237 vb = load_fpr(ctx, rb);
2238 va = load_fpr(ctx, ra);
2239 gen_cpy_mask(vc, va, vb, 0, 0xFFF0000000000000ULL);
4c9649a9
JM
2240 break;
2241 case 0x024:
2242 /* MT_FPCR */
9d14a042 2243 REQUIRE_FEN;
6b88b37c 2244 va = load_fpr(ctx, ra);
ad75a51e 2245 gen_helper_store_fpcr(tcg_env, va);
9d5a626b
RH
2246 if (ctx->tb_rm == QUAL_RM_D) {
2247 /* Re-do the copy of the rounding mode to fp_status
2248 the next time we use dynamic rounding. */
2249 ctx->tb_rm = -1;
2250 }
4c9649a9
JM
2251 break;
2252 case 0x025:
2253 /* MF_FPCR */
9d14a042 2254 REQUIRE_FEN;
6b88b37c 2255 va = dest_fpr(ctx, ra);
ad75a51e 2256 gen_helper_load_fpcr(va, tcg_env);
4c9649a9
JM
2257 break;
2258 case 0x02A:
2259 /* FCMOVEQ */
9d14a042 2260 REQUIRE_FEN;
65809352 2261 gen_fcmov(ctx, TCG_COND_EQ, ra, rb, rc);
4c9649a9
JM
2262 break;
2263 case 0x02B:
2264 /* FCMOVNE */
9d14a042 2265 REQUIRE_FEN;
65809352 2266 gen_fcmov(ctx, TCG_COND_NE, ra, rb, rc);
4c9649a9
JM
2267 break;
2268 case 0x02C:
2269 /* FCMOVLT */
9d14a042 2270 REQUIRE_FEN;
65809352 2271 gen_fcmov(ctx, TCG_COND_LT, ra, rb, rc);
4c9649a9
JM
2272 break;
2273 case 0x02D:
2274 /* FCMOVGE */
9d14a042 2275 REQUIRE_FEN;
65809352 2276 gen_fcmov(ctx, TCG_COND_GE, ra, rb, rc);
4c9649a9
JM
2277 break;
2278 case 0x02E:
2279 /* FCMOVLE */
9d14a042 2280 REQUIRE_FEN;
65809352 2281 gen_fcmov(ctx, TCG_COND_LE, ra, rb, rc);
4c9649a9
JM
2282 break;
2283 case 0x02F:
2284 /* FCMOVGT */
9d14a042 2285 REQUIRE_FEN;
65809352 2286 gen_fcmov(ctx, TCG_COND_GT, ra, rb, rc);
4c9649a9 2287 break;
57a808b6
RH
2288 case 0x030: /* CVTQL */
2289 case 0x130: /* CVTQL/V */
2290 case 0x530: /* CVTQL/SV */
64f45e49 2291 REQUIRE_REG_31(ra);
9d14a042 2292 REQUIRE_FEN;
e8d8fef4
RH
2293 vc = dest_fpr(ctx, rc);
2294 vb = load_fpr(ctx, rb);
ad75a51e 2295 gen_helper_cvtql(vc, tcg_env, vb);
57a808b6 2296 gen_fp_exc_raise(rc, fn11);
4c9649a9
JM
2297 break;
2298 default:
2299 goto invalid_opc;
2300 }
2301 break;
89fe090b 2302
4c9649a9
JM
2303 case 0x18:
2304 switch ((uint16_t)disp16) {
2305 case 0x0000:
2306 /* TRAPB */
4af70374 2307 /* No-op. */
4c9649a9
JM
2308 break;
2309 case 0x0400:
2310 /* EXCB */
4af70374 2311 /* No-op. */
4c9649a9
JM
2312 break;
2313 case 0x4000:
2314 /* MB */
ae2264d5 2315 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
4c9649a9
JM
2316 break;
2317 case 0x4400:
2318 /* WMB */
ae2264d5 2319 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
4c9649a9
JM
2320 break;
2321 case 0x8000:
2322 /* FETCH */
2323 /* No-op */
2324 break;
2325 case 0xA000:
2326 /* FETCH_M */
2327 /* No-op */
2328 break;
2329 case 0xC000:
2330 /* RPCC */
89fe090b 2331 va = dest_gpr(ctx, ra);
dfd1b812 2332 if (translator_io_start(&ctx->base)) {
3de811c6 2333 ret = DISAS_PC_STALE;
a9406ea1 2334 }
ad75a51e 2335 gen_helper_load_pcc(va, tcg_env);
4c9649a9
JM
2336 break;
2337 case 0xE000:
2338 /* RC */
59124384 2339 gen_rx(ctx, ra, 0);
4c9649a9
JM
2340 break;
2341 case 0xE800:
2342 /* ECB */
4c9649a9
JM
2343 break;
2344 case 0xF000:
2345 /* RS */
59124384 2346 gen_rx(ctx, ra, 1);
4c9649a9
JM
2347 break;
2348 case 0xF800:
2349 /* WH64 */
2350 /* No-op */
2351 break;
2517def6
RH
2352 case 0xFC00:
2353 /* WH64EN */
2354 /* No-op */
2355 break;
4c9649a9
JM
2356 default:
2357 goto invalid_opc;
2358 }
2359 break;
8f56ced8 2360
4c9649a9
JM
2361 case 0x19:
2362 /* HW_MFPR (PALcode) */
26b46094 2363#ifndef CONFIG_USER_ONLY
bcd2625d 2364 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
0e154fe9 2365 va = dest_gpr(ctx, ra);
bd79255d 2366 ret = gen_mfpr(ctx, va, insn & 0xffff);
a9e05a1c 2367 break;
5238c886 2368#else
4c9649a9 2369 goto invalid_opc;
5238c886 2370#endif
8f56ced8 2371
4c9649a9 2372 case 0x1A:
49563a72
RH
2373 /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
2374 prediction stack action, which of course we don't implement. */
8f56ced8
RH
2375 vb = load_gpr(ctx, rb);
2376 tcg_gen_andi_i64(cpu_pc, vb, ~3);
49563a72 2377 if (ra != 31) {
c5f80657 2378 tcg_gen_movi_i64(ctx->ir[ra], ctx->base.pc_next);
49563a72 2379 }
3de811c6 2380 ret = DISAS_PC_UPDATED;
4c9649a9 2381 break;
1eaa1da7 2382
4c9649a9
JM
2383 case 0x1B:
2384 /* HW_LD (PALcode) */
a18ad893 2385#ifndef CONFIG_USER_ONLY
bcd2625d 2386 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
5238c886 2387 {
1eaa1da7
RH
2388 TCGv addr = tcg_temp_new();
2389 vb = load_gpr(ctx, rb);
2390 va = dest_gpr(ctx, ra);
a18ad893 2391
1eaa1da7 2392 tcg_gen_addi_i64(addr, vb, disp12);
8bb6e981
AJ
2393 switch ((insn >> 12) & 0xF) {
2394 case 0x0:
b5d51029 2395 /* Longword physical access (hw_ldl/p) */
33948b68 2396 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
8bb6e981
AJ
2397 break;
2398 case 0x1:
b5d51029 2399 /* Quadword physical access (hw_ldq/p) */
33948b68 2400 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
8bb6e981
AJ
2401 break;
2402 case 0x2:
b5d51029 2403 /* Longword physical access with lock (hw_ldl_l/p) */
33948b68 2404 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
5ffcb334
RH
2405 tcg_gen_mov_i64(cpu_lock_addr, addr);
2406 tcg_gen_mov_i64(cpu_lock_value, va);
8bb6e981
AJ
2407 break;
2408 case 0x3:
b5d51029 2409 /* Quadword physical access with lock (hw_ldq_l/p) */
33948b68 2410 tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
5ffcb334
RH
2411 tcg_gen_mov_i64(cpu_lock_addr, addr);
2412 tcg_gen_mov_i64(cpu_lock_value, va);
8bb6e981
AJ
2413 break;
2414 case 0x4:
b5d51029 2415 /* Longword virtual PTE fetch (hw_ldl/v) */
2374e73e 2416 goto invalid_opc;
8bb6e981 2417 case 0x5:
b5d51029 2418 /* Quadword virtual PTE fetch (hw_ldq/v) */
2374e73e 2419 goto invalid_opc;
8bb6e981
AJ
2420 break;
2421 case 0x6:
59124384 2422 /* Invalid */
b5d51029 2423 goto invalid_opc;
8bb6e981 2424 case 0x7:
59124384 2425 /* Invaliid */
b5d51029 2426 goto invalid_opc;
8bb6e981 2427 case 0x8:
b5d51029 2428 /* Longword virtual access (hw_ldl) */
2374e73e 2429 goto invalid_opc;
8bb6e981 2430 case 0x9:
b5d51029 2431 /* Quadword virtual access (hw_ldq) */
2374e73e 2432 goto invalid_opc;
8bb6e981 2433 case 0xA:
b5d51029 2434 /* Longword virtual access with protection check (hw_ldl/w) */
33948b68
RH
2435 tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX,
2436 MO_LESL | MO_ALIGN);
8bb6e981
AJ
2437 break;
2438 case 0xB:
b5d51029 2439 /* Quadword virtual access with protection check (hw_ldq/w) */
33948b68
RH
2440 tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX,
2441 MO_LEUQ | MO_ALIGN);
8bb6e981
AJ
2442 break;
2443 case 0xC:
b5d51029 2444 /* Longword virtual access with alt access mode (hw_ldl/a)*/
2374e73e 2445 goto invalid_opc;
8bb6e981 2446 case 0xD:
b5d51029 2447 /* Quadword virtual access with alt access mode (hw_ldq/a) */
2374e73e 2448 goto invalid_opc;
8bb6e981
AJ
2449 case 0xE:
2450 /* Longword virtual access with alternate access mode and
2374e73e 2451 protection checks (hw_ldl/wa) */
33948b68
RH
2452 tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX,
2453 MO_LESL | MO_ALIGN);
8bb6e981
AJ
2454 break;
2455 case 0xF:
2456 /* Quadword virtual access with alternate access mode and
2374e73e 2457 protection checks (hw_ldq/wa) */
33948b68
RH
2458 tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX,
2459 MO_LEUQ | MO_ALIGN);
8bb6e981
AJ
2460 break;
2461 }
a18ad893 2462 break;
4c9649a9 2463 }
5238c886 2464#else
a18ad893 2465 goto invalid_opc;
5238c886 2466#endif
c67b67e5 2467
4c9649a9 2468 case 0x1C:
c67b67e5 2469 vc = dest_gpr(ctx, rc);
cd2754ad
RH
2470 if (fn7 == 0x70) {
2471 /* FTOIT */
c6d41b36 2472 REQUIRE_AMASK(FIX);
cd2754ad
RH
2473 REQUIRE_REG_31(rb);
2474 va = load_fpr(ctx, ra);
2475 tcg_gen_mov_i64(vc, va);
2476 break;
2477 } else if (fn7 == 0x78) {
2478 /* FTOIS */
c6d41b36 2479 REQUIRE_AMASK(FIX);
cd2754ad
RH
2480 REQUIRE_REG_31(rb);
2481 t32 = tcg_temp_new_i32();
2482 va = load_fpr(ctx, ra);
2483 gen_helper_s_to_memory(t32, va);
2484 tcg_gen_ext_i32_i64(vc, t32);
cd2754ad
RH
2485 break;
2486 }
2487
2488 vb = load_gpr_lit(ctx, rb, lit, islit);
4c9649a9
JM
2489 switch (fn7) {
2490 case 0x00:
2491 /* SEXTB */
c6d41b36 2492 REQUIRE_AMASK(BWX);
64f45e49 2493 REQUIRE_REG_31(ra);
c67b67e5 2494 tcg_gen_ext8s_i64(vc, vb);
4c9649a9
JM
2495 break;
2496 case 0x01:
2497 /* SEXTW */
c6d41b36 2498 REQUIRE_AMASK(BWX);
64f45e49 2499 REQUIRE_REG_31(ra);
c67b67e5 2500 tcg_gen_ext16s_i64(vc, vb);
5238c886 2501 break;
4c9649a9
JM
2502 case 0x30:
2503 /* CTPOP */
c6d41b36 2504 REQUIRE_AMASK(CIX);
64f45e49 2505 REQUIRE_REG_31(ra);
ed085138 2506 REQUIRE_NO_LIT;
de26a584 2507 tcg_gen_ctpop_i64(vc, vb);
5238c886 2508 break;
4c9649a9
JM
2509 case 0x31:
2510 /* PERR */
c6d41b36 2511 REQUIRE_AMASK(MVI);
ed085138 2512 REQUIRE_NO_LIT;
cd2754ad
RH
2513 va = load_gpr(ctx, ra);
2514 gen_helper_perr(vc, va, vb);
5238c886 2515 break;
4c9649a9
JM
2516 case 0x32:
2517 /* CTLZ */
c6d41b36 2518 REQUIRE_AMASK(CIX);
64f45e49 2519 REQUIRE_REG_31(ra);
ed085138 2520 REQUIRE_NO_LIT;
881549da 2521 tcg_gen_clzi_i64(vc, vb, 64);
5238c886 2522 break;
4c9649a9
JM
2523 case 0x33:
2524 /* CTTZ */
c6d41b36 2525 REQUIRE_AMASK(CIX);
64f45e49 2526 REQUIRE_REG_31(ra);
ed085138 2527 REQUIRE_NO_LIT;
881549da 2528 tcg_gen_ctzi_i64(vc, vb, 64);
5238c886 2529 break;
4c9649a9
JM
2530 case 0x34:
2531 /* UNPKBW */
c6d41b36 2532 REQUIRE_AMASK(MVI);
64f45e49 2533 REQUIRE_REG_31(ra);
ed085138 2534 REQUIRE_NO_LIT;
f477ed3c 2535 gen_helper_unpkbw(vc, vb);
5238c886 2536 break;
4c9649a9 2537 case 0x35:
13e4df99 2538 /* UNPKBL */
c6d41b36 2539 REQUIRE_AMASK(MVI);
64f45e49 2540 REQUIRE_REG_31(ra);
ed085138 2541 REQUIRE_NO_LIT;
f477ed3c 2542 gen_helper_unpkbl(vc, vb);
5238c886 2543 break;
4c9649a9
JM
2544 case 0x36:
2545 /* PKWB */
c6d41b36 2546 REQUIRE_AMASK(MVI);
64f45e49 2547 REQUIRE_REG_31(ra);
ed085138 2548 REQUIRE_NO_LIT;
f477ed3c 2549 gen_helper_pkwb(vc, vb);
5238c886 2550 break;
4c9649a9
JM
2551 case 0x37:
2552 /* PKLB */
c6d41b36 2553 REQUIRE_AMASK(MVI);
64f45e49 2554 REQUIRE_REG_31(ra);
ed085138 2555 REQUIRE_NO_LIT;
f477ed3c 2556 gen_helper_pklb(vc, vb);
5238c886 2557 break;
4c9649a9
JM
2558 case 0x38:
2559 /* MINSB8 */
c6d41b36 2560 REQUIRE_AMASK(MVI);
cd2754ad
RH
2561 va = load_gpr(ctx, ra);
2562 gen_helper_minsb8(vc, va, vb);
5238c886 2563 break;
4c9649a9
JM
2564 case 0x39:
2565 /* MINSW4 */
c6d41b36 2566 REQUIRE_AMASK(MVI);
cd2754ad
RH
2567 va = load_gpr(ctx, ra);
2568 gen_helper_minsw4(vc, va, vb);
5238c886 2569 break;
4c9649a9
JM
2570 case 0x3A:
2571 /* MINUB8 */
c6d41b36 2572 REQUIRE_AMASK(MVI);
cd2754ad
RH
2573 va = load_gpr(ctx, ra);
2574 gen_helper_minub8(vc, va, vb);
5238c886 2575 break;
4c9649a9
JM
2576 case 0x3B:
2577 /* MINUW4 */
c6d41b36 2578 REQUIRE_AMASK(MVI);
cd2754ad
RH
2579 va = load_gpr(ctx, ra);
2580 gen_helper_minuw4(vc, va, vb);
5238c886 2581 break;
4c9649a9
JM
2582 case 0x3C:
2583 /* MAXUB8 */
c6d41b36 2584 REQUIRE_AMASK(MVI);
cd2754ad
RH
2585 va = load_gpr(ctx, ra);
2586 gen_helper_maxub8(vc, va, vb);
5238c886 2587 break;
4c9649a9
JM
2588 case 0x3D:
2589 /* MAXUW4 */
c6d41b36 2590 REQUIRE_AMASK(MVI);
cd2754ad
RH
2591 va = load_gpr(ctx, ra);
2592 gen_helper_maxuw4(vc, va, vb);
5238c886 2593 break;
4c9649a9
JM
2594 case 0x3E:
2595 /* MAXSB8 */
c6d41b36 2596 REQUIRE_AMASK(MVI);
cd2754ad
RH
2597 va = load_gpr(ctx, ra);
2598 gen_helper_maxsb8(vc, va, vb);
5238c886 2599 break;
4c9649a9
JM
2600 case 0x3F:
2601 /* MAXSW4 */
c6d41b36 2602 REQUIRE_AMASK(MVI);
cd2754ad
RH
2603 va = load_gpr(ctx, ra);
2604 gen_helper_maxsw4(vc, va, vb);
4c9649a9
JM
2605 break;
2606 default:
2607 goto invalid_opc;
2608 }
2609 break;
46010969 2610
4c9649a9
JM
2611 case 0x1D:
2612 /* HW_MTPR (PALcode) */
26b46094 2613#ifndef CONFIG_USER_ONLY
bcd2625d 2614 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
0e154fe9 2615 vb = load_gpr(ctx, rb);
a9e05a1c
RH
2616 ret = gen_mtpr(ctx, vb, insn & 0xffff);
2617 break;
5238c886 2618#else
4c9649a9 2619 goto invalid_opc;
5238c886 2620#endif
46010969 2621
4c9649a9 2622 case 0x1E:
508b43ea 2623 /* HW_RET (PALcode) */
a18ad893 2624#ifndef CONFIG_USER_ONLY
bcd2625d 2625 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
5238c886
RH
2626 if (rb == 31) {
2627 /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
2628 address from EXC_ADDR. This turns out to be useful for our
2629 emulation PALcode, so continue to accept it. */
3e646c3a 2630 vb = dest_sink(ctx);
ad75a51e 2631 tcg_gen_ld_i64(vb, tcg_env, offsetof(CPUAlphaState, exc_addr));
5238c886 2632 } else {
6c05d3de 2633 vb = load_gpr(ctx, rb);
4c9649a9 2634 }
bcd2625d 2635 tcg_gen_movi_i64(cpu_lock_addr, -1);
904bd855 2636 st_flag_byte(load_zero(ctx), ENV_FLAG_RX_SHIFT);
6c05d3de 2637 tmp = tcg_temp_new();
6c05d3de 2638 tcg_gen_andi_i64(tmp, vb, 1);
bcd2625d 2639 st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
6c05d3de 2640 tcg_gen_andi_i64(cpu_pc, vb, ~3);
54e1d4ed 2641 /* Allow interrupts to be recognized right away. */
3de811c6 2642 ret = DISAS_PC_UPDATED_NOCHAIN;
5238c886
RH
2643 break;
2644#else
a18ad893 2645 goto invalid_opc;
5238c886 2646#endif
a4af3044 2647
4c9649a9
JM
2648 case 0x1F:
2649 /* HW_ST (PALcode) */
a18ad893 2650#ifndef CONFIG_USER_ONLY
bcd2625d 2651 REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
5238c886 2652 {
8bb6e981
AJ
2653 switch ((insn >> 12) & 0xF) {
2654 case 0x0:
2655 /* Longword physical access */
6a73ecf5
RH
2656 va = load_gpr(ctx, ra);
2657 vb = load_gpr(ctx, rb);
2658 tmp = tcg_temp_new();
2659 tcg_gen_addi_i64(tmp, vb, disp12);
33948b68 2660 tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
8bb6e981
AJ
2661 break;
2662 case 0x1:
2663 /* Quadword physical access */
6a73ecf5
RH
2664 va = load_gpr(ctx, ra);
2665 vb = load_gpr(ctx, rb);
2666 tmp = tcg_temp_new();
2667 tcg_gen_addi_i64(tmp, vb, disp12);
33948b68 2668 tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
8bb6e981
AJ
2669 break;
2670 case 0x2:
2671 /* Longword physical access with lock */
6a73ecf5 2672 ret = gen_store_conditional(ctx, ra, rb, disp12,
33948b68 2673 MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
8bb6e981
AJ
2674 break;
2675 case 0x3:
2676 /* Quadword physical access with lock */
6a73ecf5 2677 ret = gen_store_conditional(ctx, ra, rb, disp12,
33948b68 2678 MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
8bb6e981
AJ
2679 break;
2680 case 0x4:
2681 /* Longword virtual access */
2374e73e 2682 goto invalid_opc;
8bb6e981
AJ
2683 case 0x5:
2684 /* Quadword virtual access */
2374e73e 2685 goto invalid_opc;
8bb6e981
AJ
2686 case 0x6:
2687 /* Invalid */
2688 goto invalid_opc;
2689 case 0x7:
2690 /* Invalid */
2691 goto invalid_opc;
2692 case 0x8:
2693 /* Invalid */
2694 goto invalid_opc;
2695 case 0x9:
2696 /* Invalid */
2697 goto invalid_opc;
2698 case 0xA:
2699 /* Invalid */
2700 goto invalid_opc;
2701 case 0xB:
2702 /* Invalid */
2703 goto invalid_opc;
2704 case 0xC:
2705 /* Longword virtual access with alternate access mode */
2374e73e 2706 goto invalid_opc;
8bb6e981
AJ
2707 case 0xD:
2708 /* Quadword virtual access with alternate access mode */
2374e73e 2709 goto invalid_opc;
8bb6e981
AJ
2710 case 0xE:
2711 /* Invalid */
2712 goto invalid_opc;
2713 case 0xF:
2714 /* Invalid */
2715 goto invalid_opc;
2716 }
a18ad893 2717 break;
4c9649a9 2718 }
5238c886 2719#else
a18ad893 2720 goto invalid_opc;
5238c886 2721#endif
4c9649a9
JM
2722 case 0x20:
2723 /* LDF */
9d14a042 2724 REQUIRE_FEN;
45263531 2725 gen_load_fp(ctx, ra, rb, disp16, gen_ldf);
4c9649a9
JM
2726 break;
2727 case 0x21:
2728 /* LDG */
9d14a042 2729 REQUIRE_FEN;
45263531 2730 gen_load_fp(ctx, ra, rb, disp16, gen_ldg);
4c9649a9
JM
2731 break;
2732 case 0x22:
2733 /* LDS */
9d14a042 2734 REQUIRE_FEN;
45263531 2735 gen_load_fp(ctx, ra, rb, disp16, gen_lds);
4c9649a9
JM
2736 break;
2737 case 0x23:
2738 /* LDT */
9d14a042 2739 REQUIRE_FEN;
45263531 2740 gen_load_fp(ctx, ra, rb, disp16, gen_ldt);
4c9649a9
JM
2741 break;
2742 case 0x24:
2743 /* STF */
9d14a042 2744 REQUIRE_FEN;
45263531 2745 gen_store_fp(ctx, ra, rb, disp16, gen_stf);
4c9649a9
JM
2746 break;
2747 case 0x25:
2748 /* STG */
9d14a042 2749 REQUIRE_FEN;
45263531 2750 gen_store_fp(ctx, ra, rb, disp16, gen_stg);
4c9649a9
JM
2751 break;
2752 case 0x26:
2753 /* STS */
9d14a042 2754 REQUIRE_FEN;
45263531 2755 gen_store_fp(ctx, ra, rb, disp16, gen_sts);
4c9649a9
JM
2756 break;
2757 case 0x27:
2758 /* STT */
9d14a042 2759 REQUIRE_FEN;
45263531 2760 gen_store_fp(ctx, ra, rb, disp16, gen_stt);
4c9649a9
JM
2761 break;
2762 case 0x28:
2763 /* LDL */
5ffcb334 2764 gen_load_int(ctx, ra, rb, disp16, MO_LESL, 0, 0);
4c9649a9
JM
2765 break;
2766 case 0x29:
2767 /* LDQ */
fc313c64 2768 gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 0, 0);
4c9649a9
JM
2769 break;
2770 case 0x2A:
2771 /* LDL_L */
33948b68 2772 gen_load_int(ctx, ra, rb, disp16, MO_LESL | MO_ALIGN, 0, 1);
4c9649a9
JM
2773 break;
2774 case 0x2B:
2775 /* LDQ_L */
33948b68 2776 gen_load_int(ctx, ra, rb, disp16, MO_LEUQ | MO_ALIGN, 0, 1);
4c9649a9
JM
2777 break;
2778 case 0x2C:
2779 /* STL */
5ffcb334 2780 gen_store_int(ctx, ra, rb, disp16, MO_LEUL, 0);
4c9649a9
JM
2781 break;
2782 case 0x2D:
2783 /* STQ */
fc313c64 2784 gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 0);
4c9649a9
JM
2785 break;
2786 case 0x2E:
2787 /* STL_C */
6a73ecf5 2788 ret = gen_store_conditional(ctx, ra, rb, disp16,
33948b68 2789 ctx->mem_idx, MO_LESL | MO_ALIGN);
4c9649a9
JM
2790 break;
2791 case 0x2F:
2792 /* STQ_C */
6a73ecf5 2793 ret = gen_store_conditional(ctx, ra, rb, disp16,
33948b68 2794 ctx->mem_idx, MO_LEUQ | MO_ALIGN);
4c9649a9
JM
2795 break;
2796 case 0x30:
2797 /* BR */
4af70374 2798 ret = gen_bdirect(ctx, ra, disp21);
4c9649a9 2799 break;
a7812ae4 2800 case 0x31: /* FBEQ */
9d14a042 2801 REQUIRE_FEN;
4af70374 2802 ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
dbb30fe6 2803 break;
a7812ae4 2804 case 0x32: /* FBLT */
9d14a042 2805 REQUIRE_FEN;
4af70374 2806 ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
dbb30fe6 2807 break;
a7812ae4 2808 case 0x33: /* FBLE */
9d14a042 2809 REQUIRE_FEN;
4af70374 2810 ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
4c9649a9
JM
2811 break;
2812 case 0x34:
2813 /* BSR */
4af70374 2814 ret = gen_bdirect(ctx, ra, disp21);
4c9649a9 2815 break;
a7812ae4 2816 case 0x35: /* FBNE */
9d14a042 2817 REQUIRE_FEN;
4af70374 2818 ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
dbb30fe6 2819 break;
a7812ae4 2820 case 0x36: /* FBGE */
9d14a042 2821 REQUIRE_FEN;
4af70374 2822 ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
dbb30fe6 2823 break;
a7812ae4 2824 case 0x37: /* FBGT */
9d14a042 2825 REQUIRE_FEN;
4af70374 2826 ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
4c9649a9
JM
2827 break;
2828 case 0x38:
2829 /* BLBC */
4af70374 2830 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
4c9649a9
JM
2831 break;
2832 case 0x39:
2833 /* BEQ */
4af70374 2834 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
4c9649a9
JM
2835 break;
2836 case 0x3A:
2837 /* BLT */
4af70374 2838 ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
4c9649a9
JM
2839 break;
2840 case 0x3B:
2841 /* BLE */
4af70374 2842 ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
4c9649a9
JM
2843 break;
2844 case 0x3C:
2845 /* BLBS */
4af70374 2846 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
4c9649a9
JM
2847 break;
2848 case 0x3D:
2849 /* BNE */
4af70374 2850 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
4c9649a9
JM
2851 break;
2852 case 0x3E:
2853 /* BGE */
4af70374 2854 ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
4c9649a9
JM
2855 break;
2856 case 0x3F:
2857 /* BGT */
4af70374 2858 ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
4c9649a9
JM
2859 break;
2860 invalid_opc:
8aa3fa20 2861 ret = gen_invalid(ctx);
4c9649a9 2862 break;
9d14a042
RH
2863 raise_fen:
2864 ret = gen_excp(ctx, EXCP_FEN, 0);
2865 break;
4c9649a9
JM
2866 }
2867
2868 return ret;
2869}
2870
b542683d 2871static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
4c9649a9 2872{
99a92b94 2873 DisasContext *ctx = container_of(dcbase, DisasContext, base);
b77af26e 2874 CPUAlphaState *env = cpu_env(cpu);
3fd3442a 2875 int64_t bound;
c5f80657 2876
99a92b94
RH
2877 ctx->tbflags = ctx->base.tb->flags;
2878 ctx->mem_idx = cpu_mmu_index(env, false);
2879 ctx->implver = env->implver;
2880 ctx->amask = env->amask;
f24518b5 2881
59124384 2882#ifdef CONFIG_USER_ONLY
99a92b94 2883 ctx->ir = cpu_std_ir;
fed14246 2884 ctx->unalign = (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN);
59124384 2885#else
99a92b94
RH
2886 ctx->palbr = env->palbr;
2887 ctx->ir = (ctx->tbflags & ENV_FLAG_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
59124384
RH
2888#endif
2889
f24518b5
RH
2890 /* ??? Every TB begins with unset rounding mode, to be initialized on
2891 the first fp insn of the TB. Alternately we could define a proper
2892 default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure
2893 to reset the FP_STATUS to that default at the end of any TB that
8b81968c 2894 changes the default. We could even (gasp) dynamically figure out
f24518b5 2895 what default would be most efficient given the running program. */
99a92b94 2896 ctx->tb_rm = -1;
f24518b5 2897 /* Similarly for flush-to-zero. */
99a92b94 2898 ctx->tb_ftz = -1;
f24518b5 2899
f764718d
RH
2900 ctx->zero = NULL;
2901 ctx->sink = NULL;
b114b68a 2902
99a92b94 2903 /* Bound the number of insns to execute to those left on the page. */
3fd3442a 2904 bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
b542683d 2905 ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
99a92b94 2906}
8aa5c65f 2907
99a92b94
RH
2908static void alpha_tr_tb_start(DisasContextBase *db, CPUState *cpu)
2909{
2910}
667b8e29 2911
99a92b94
RH
2912static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
2913{
2914 tcg_gen_insn_start(dcbase->pc_next);
2915}
c4b3be39 2916
99a92b94
RH
2917static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
2918{
2919 DisasContext *ctx = container_of(dcbase, DisasContext, base);
b77af26e 2920 CPUAlphaState *env = cpu_env(cpu);
4e116893 2921 uint32_t insn = translator_ldl(env, &ctx->base, ctx->base.pc_next);
99a92b94
RH
2922
2923 ctx->base.pc_next += 4;
2924 ctx->base.is_jmp = translate_one(ctx, insn);
2925
2926 free_context_temps(ctx);
99a92b94
RH
2927}
2928
2929static void alpha_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
2930{
2931 DisasContext *ctx = container_of(dcbase, DisasContext, base);
4af70374 2932
99a92b94 2933 switch (ctx->base.is_jmp) {
3de811c6 2934 case DISAS_NORETURN:
4af70374 2935 break;
3de811c6 2936 case DISAS_TOO_MANY:
99a92b94 2937 if (use_goto_tb(ctx, ctx->base.pc_next)) {
2d826cdc 2938 tcg_gen_goto_tb(0);
99a92b94 2939 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
07ea28b4 2940 tcg_gen_exit_tb(ctx->base.tb, 0);
2d826cdc
RH
2941 }
2942 /* FALLTHRU */
3de811c6 2943 case DISAS_PC_STALE:
99a92b94 2944 tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
4af70374 2945 /* FALLTHRU */
3de811c6 2946 case DISAS_PC_UPDATED:
1760e4ab
RH
2947 tcg_gen_lookup_and_goto_ptr();
2948 break;
3de811c6 2949 case DISAS_PC_UPDATED_NOCHAIN:
1760e4ab 2950 tcg_gen_exit_tb(NULL, 0);
4af70374
RH
2951 break;
2952 default:
2d826cdc 2953 g_assert_not_reached();
4c9649a9 2954 }
99a92b94 2955}
4af70374 2956
8eb806a7
RH
2957static void alpha_tr_disas_log(const DisasContextBase *dcbase,
2958 CPUState *cpu, FILE *logfile)
99a92b94 2959{
8eb806a7
RH
2960 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
2961 target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
99a92b94
RH
2962}
2963
2964static const TranslatorOps alpha_tr_ops = {
2965 .init_disas_context = alpha_tr_init_disas_context,
2966 .tb_start = alpha_tr_tb_start,
2967 .insn_start = alpha_tr_insn_start,
99a92b94
RH
2968 .translate_insn = alpha_tr_translate_insn,
2969 .tb_stop = alpha_tr_tb_stop,
2970 .disas_log = alpha_tr_disas_log,
2971};
4af70374 2972
597f9b2d 2973void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int *max_insns,
32f0c394 2974 vaddr pc, void *host_pc)
99a92b94
RH
2975{
2976 DisasContext dc;
306c8721 2977 translator_loop(cpu, tb, max_insns, pc, host_pc, &alpha_tr_ops, &dc.base);
4c9649a9 2978}