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