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