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