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