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