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