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