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