]> git.proxmox.com Git - qemu.git/blame - target-alpha/translate.c
target-alpha: Disable interrupts properly.
[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
20#include <stdint.h>
21#include <stdlib.h>
22#include <stdio.h>
23
24#include "cpu.h"
25#include "exec-all.h"
26#include "disas.h"
ae8ecd42 27#include "host-utils.h"
57fec1fe 28#include "tcg-op.h"
ca10f867 29#include "qemu-common.h"
4c9649a9 30
a7812ae4
PB
31#include "helper.h"
32#define GEN_HELPER 1
33#include "helper.h"
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
RH
46 struct TranslationBlock *tb;
47 CPUAlphaState *env;
4c9649a9
JM
48 uint64_t pc;
49 int mem_idx;
f24518b5
RH
50
51 /* Current rounding mode for this TB. */
52 int tb_rm;
53 /* Current flush-to-zero setting for this TB. */
54 int tb_ftz;
4c9649a9
JM
55};
56
4af70374
RH
57/* Return values from translate_one, indicating the state of the TB.
58 Note that zero indicates that we are not exiting the TB. */
59
60typedef enum {
61 NO_EXIT,
62
63 /* We have emitted one or more goto_tb. No fixup required. */
64 EXIT_GOTO_TB,
65
66 /* We are not using a goto_tb (for whatever reason), but have updated
67 the PC (for whatever reason), so there's no need to do it again on
68 exiting the TB. */
69 EXIT_PC_UPDATED,
70
71 /* We are exiting the TB, but have neither emitted a goto_tb, nor
72 updated the PC for the next instruction to be executed. */
8aa3fa20
RH
73 EXIT_PC_STALE,
74
75 /* We are ending the TB with a noreturn function call, e.g. longjmp.
76 No following code will be executed. */
77 EXIT_NORETURN,
4af70374
RH
78} ExitStatus;
79
3761035f 80/* global register indexes */
a7812ae4 81static TCGv_ptr cpu_env;
496cb5b9 82static TCGv cpu_ir[31];
f18cd223 83static TCGv cpu_fir[31];
496cb5b9 84static TCGv cpu_pc;
6910b8f6
RH
85static TCGv cpu_lock_addr;
86static TCGv cpu_lock_st_addr;
87static TCGv cpu_lock_value;
ab471ade
RH
88#ifdef CONFIG_USER_ONLY
89static TCGv cpu_uniq;
90#endif
496cb5b9 91
3761035f 92/* register names */
f18cd223 93static char cpu_reg_names[10*4+21*5 + 10*5+21*6];
2e70f6ef
PB
94
95#include "gen-icount.h"
96
a5f1b965 97static void alpha_translate_init(void)
2e70f6ef 98{
496cb5b9
AJ
99 int i;
100 char *p;
2e70f6ef 101 static int done_init = 0;
496cb5b9 102
2e70f6ef
PB
103 if (done_init)
104 return;
496cb5b9 105
a7812ae4 106 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
496cb5b9
AJ
107
108 p = cpu_reg_names;
109 for (i = 0; i < 31; i++) {
110 sprintf(p, "ir%d", i);
a7812ae4
PB
111 cpu_ir[i] = tcg_global_mem_new_i64(TCG_AREG0,
112 offsetof(CPUState, ir[i]), p);
6ba8dcd7 113 p += (i < 10) ? 4 : 5;
f18cd223
AJ
114
115 sprintf(p, "fir%d", i);
a7812ae4
PB
116 cpu_fir[i] = tcg_global_mem_new_i64(TCG_AREG0,
117 offsetof(CPUState, fir[i]), p);
f18cd223 118 p += (i < 10) ? 5 : 6;
496cb5b9
AJ
119 }
120
a7812ae4
PB
121 cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
122 offsetof(CPUState, pc), "pc");
496cb5b9 123
6910b8f6
RH
124 cpu_lock_addr = tcg_global_mem_new_i64(TCG_AREG0,
125 offsetof(CPUState, lock_addr),
126 "lock_addr");
127 cpu_lock_st_addr = tcg_global_mem_new_i64(TCG_AREG0,
128 offsetof(CPUState, lock_st_addr),
129 "lock_st_addr");
130 cpu_lock_value = tcg_global_mem_new_i64(TCG_AREG0,
131 offsetof(CPUState, lock_value),
132 "lock_value");
f4ed8679 133
ab471ade
RH
134#ifdef CONFIG_USER_ONLY
135 cpu_uniq = tcg_global_mem_new_i64(TCG_AREG0,
136 offsetof(CPUState, unique), "uniq");
137#endif
138
496cb5b9 139 /* register helpers */
a7812ae4 140#define GEN_HELPER 2
496cb5b9
AJ
141#include "helper.h"
142
2e70f6ef
PB
143 done_init = 1;
144}
145
bf1b03fe 146static void gen_excp_1(int exception, int error_code)
4c9649a9 147{
a7812ae4 148 TCGv_i32 tmp1, tmp2;
6ad02592 149
6ad02592
AJ
150 tmp1 = tcg_const_i32(exception);
151 tmp2 = tcg_const_i32(error_code);
a7812ae4
PB
152 gen_helper_excp(tmp1, tmp2);
153 tcg_temp_free_i32(tmp2);
154 tcg_temp_free_i32(tmp1);
bf1b03fe 155}
8aa3fa20 156
bf1b03fe
RH
157static ExitStatus gen_excp(DisasContext *ctx, int exception, int error_code)
158{
159 tcg_gen_movi_i64(cpu_pc, ctx->pc);
160 gen_excp_1(exception, error_code);
8aa3fa20 161 return EXIT_NORETURN;
4c9649a9
JM
162}
163
8aa3fa20 164static inline ExitStatus gen_invalid(DisasContext *ctx)
4c9649a9 165{
8aa3fa20 166 return gen_excp(ctx, EXCP_OPCDEC, 0);
4c9649a9
JM
167}
168
636aa200 169static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
f18cd223 170{
a7812ae4
PB
171 TCGv tmp = tcg_temp_new();
172 TCGv_i32 tmp32 = tcg_temp_new_i32();
f18cd223 173 tcg_gen_qemu_ld32u(tmp, t1, flags);
a7812ae4
PB
174 tcg_gen_trunc_i64_i32(tmp32, tmp);
175 gen_helper_memory_to_f(t0, tmp32);
176 tcg_temp_free_i32(tmp32);
f18cd223
AJ
177 tcg_temp_free(tmp);
178}
179
636aa200 180static inline void gen_qemu_ldg(TCGv t0, TCGv t1, int flags)
f18cd223 181{
a7812ae4 182 TCGv tmp = tcg_temp_new();
f18cd223 183 tcg_gen_qemu_ld64(tmp, t1, flags);
a7812ae4 184 gen_helper_memory_to_g(t0, tmp);
f18cd223
AJ
185 tcg_temp_free(tmp);
186}
187
636aa200 188static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
f18cd223 189{
a7812ae4
PB
190 TCGv tmp = tcg_temp_new();
191 TCGv_i32 tmp32 = tcg_temp_new_i32();
f18cd223 192 tcg_gen_qemu_ld32u(tmp, t1, flags);
a7812ae4
PB
193 tcg_gen_trunc_i64_i32(tmp32, tmp);
194 gen_helper_memory_to_s(t0, tmp32);
195 tcg_temp_free_i32(tmp32);
f18cd223
AJ
196 tcg_temp_free(tmp);
197}
198
636aa200 199static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
f4ed8679 200{
f4ed8679 201 tcg_gen_qemu_ld32s(t0, t1, flags);
6910b8f6
RH
202 tcg_gen_mov_i64(cpu_lock_addr, t1);
203 tcg_gen_mov_i64(cpu_lock_value, t0);
f4ed8679
AJ
204}
205
636aa200 206static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
f4ed8679 207{
f4ed8679 208 tcg_gen_qemu_ld64(t0, t1, flags);
6910b8f6
RH
209 tcg_gen_mov_i64(cpu_lock_addr, t1);
210 tcg_gen_mov_i64(cpu_lock_value, t0);
f4ed8679
AJ
211}
212
636aa200
BS
213static inline void gen_load_mem(DisasContext *ctx,
214 void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1,
215 int flags),
216 int ra, int rb, int32_t disp16, int fp,
217 int clear)
023d8ca2 218{
6910b8f6 219 TCGv addr, va;
023d8ca2 220
6910b8f6
RH
221 /* LDQ_U with ra $31 is UNOP. Other various loads are forms of
222 prefetches, which we can treat as nops. No worries about
223 missed exceptions here. */
224 if (unlikely(ra == 31)) {
023d8ca2 225 return;
6910b8f6 226 }
023d8ca2 227
a7812ae4 228 addr = tcg_temp_new();
023d8ca2
AJ
229 if (rb != 31) {
230 tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
6910b8f6 231 if (clear) {
023d8ca2 232 tcg_gen_andi_i64(addr, addr, ~0x7);
6910b8f6 233 }
023d8ca2 234 } else {
6910b8f6 235 if (clear) {
023d8ca2 236 disp16 &= ~0x7;
6910b8f6 237 }
023d8ca2
AJ
238 tcg_gen_movi_i64(addr, disp16);
239 }
6910b8f6
RH
240
241 va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
242 tcg_gen_qemu_load(va, addr, ctx->mem_idx);
243
023d8ca2
AJ
244 tcg_temp_free(addr);
245}
246
636aa200 247static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
f18cd223 248{
a7812ae4
PB
249 TCGv_i32 tmp32 = tcg_temp_new_i32();
250 TCGv tmp = tcg_temp_new();
251 gen_helper_f_to_memory(tmp32, t0);
252 tcg_gen_extu_i32_i64(tmp, tmp32);
f18cd223
AJ
253 tcg_gen_qemu_st32(tmp, t1, flags);
254 tcg_temp_free(tmp);
a7812ae4 255 tcg_temp_free_i32(tmp32);
f18cd223
AJ
256}
257
636aa200 258static inline void gen_qemu_stg(TCGv t0, TCGv t1, int flags)
f18cd223 259{
a7812ae4
PB
260 TCGv tmp = tcg_temp_new();
261 gen_helper_g_to_memory(tmp, t0);
f18cd223
AJ
262 tcg_gen_qemu_st64(tmp, t1, flags);
263 tcg_temp_free(tmp);
264}
265
636aa200 266static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
f18cd223 267{
a7812ae4
PB
268 TCGv_i32 tmp32 = tcg_temp_new_i32();
269 TCGv tmp = tcg_temp_new();
270 gen_helper_s_to_memory(tmp32, t0);
271 tcg_gen_extu_i32_i64(tmp, tmp32);
f18cd223
AJ
272 tcg_gen_qemu_st32(tmp, t1, flags);
273 tcg_temp_free(tmp);
a7812ae4 274 tcg_temp_free_i32(tmp32);
f18cd223
AJ
275}
276
636aa200
BS
277static inline void gen_store_mem(DisasContext *ctx,
278 void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
279 int flags),
280 int ra, int rb, int32_t disp16, int fp,
6910b8f6 281 int clear)
023d8ca2 282{
6910b8f6
RH
283 TCGv addr, va;
284
285 addr = tcg_temp_new();
023d8ca2
AJ
286 if (rb != 31) {
287 tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
6910b8f6 288 if (clear) {
023d8ca2 289 tcg_gen_andi_i64(addr, addr, ~0x7);
6910b8f6 290 }
023d8ca2 291 } else {
6910b8f6 292 if (clear) {
023d8ca2 293 disp16 &= ~0x7;
6910b8f6 294 }
023d8ca2
AJ
295 tcg_gen_movi_i64(addr, disp16);
296 }
6910b8f6
RH
297
298 if (ra == 31) {
299 va = tcg_const_i64(0);
f18cd223 300 } else {
6910b8f6 301 va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
023d8ca2 302 }
6910b8f6
RH
303 tcg_gen_qemu_store(va, addr, ctx->mem_idx);
304
023d8ca2 305 tcg_temp_free(addr);
6910b8f6
RH
306 if (ra == 31) {
307 tcg_temp_free(va);
308 }
309}
310
311static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
312 int32_t disp16, int quad)
313{
314 TCGv addr;
315
316 if (ra == 31) {
317 /* ??? Don't bother storing anything. The user can't tell
318 the difference, since the zero register always reads zero. */
319 return NO_EXIT;
320 }
321
322#if defined(CONFIG_USER_ONLY)
323 addr = cpu_lock_st_addr;
324#else
e52458fe 325 addr = tcg_temp_local_new();
6910b8f6
RH
326#endif
327
328 if (rb != 31) {
329 tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
330 } else {
331 tcg_gen_movi_i64(addr, disp16);
332 }
333
334#if defined(CONFIG_USER_ONLY)
335 /* ??? This is handled via a complicated version of compare-and-swap
336 in the cpu_loop. Hopefully one day we'll have a real CAS opcode
337 in TCG so that this isn't necessary. */
338 return gen_excp(ctx, quad ? EXCP_STQ_C : EXCP_STL_C, ra);
339#else
340 /* ??? In system mode we are never multi-threaded, so CAS can be
341 implemented via a non-atomic load-compare-store sequence. */
342 {
343 int lab_fail, lab_done;
344 TCGv val;
345
346 lab_fail = gen_new_label();
347 lab_done = gen_new_label();
e52458fe 348 tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
6910b8f6
RH
349
350 val = tcg_temp_new();
351 if (quad) {
352 tcg_gen_qemu_ld64(val, addr, ctx->mem_idx);
353 } else {
354 tcg_gen_qemu_ld32s(val, addr, ctx->mem_idx);
355 }
e52458fe 356 tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
6910b8f6
RH
357
358 if (quad) {
359 tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
360 } else {
361 tcg_gen_qemu_st32(cpu_ir[ra], addr, ctx->mem_idx);
362 }
363 tcg_gen_movi_i64(cpu_ir[ra], 1);
364 tcg_gen_br(lab_done);
365
366 gen_set_label(lab_fail);
367 tcg_gen_movi_i64(cpu_ir[ra], 0);
368
369 gen_set_label(lab_done);
370 tcg_gen_movi_i64(cpu_lock_addr, -1);
371
372 tcg_temp_free(addr);
373 return NO_EXIT;
374 }
375#endif
023d8ca2
AJ
376}
377
4af70374 378static int use_goto_tb(DisasContext *ctx, uint64_t dest)
4c9649a9 379{
4af70374
RH
380 /* Check for the dest on the same page as the start of the TB. We
381 also want to suppress goto_tb in the case of single-steping and IO. */
382 return (((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0
383 && !ctx->env->singlestep_enabled
384 && !(ctx->tb->cflags & CF_LAST_IO));
385}
dbb30fe6 386
4af70374
RH
387static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
388{
389 uint64_t dest = ctx->pc + (disp << 2);
390
391 if (ra != 31) {
392 tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
393 }
394
395 /* Notice branch-to-next; used to initialize RA with the PC. */
396 if (disp == 0) {
397 return 0;
398 } else if (use_goto_tb(ctx, dest)) {
399 tcg_gen_goto_tb(0);
400 tcg_gen_movi_i64(cpu_pc, dest);
4b4a72e5 401 tcg_gen_exit_tb((tcg_target_long)ctx->tb);
4af70374
RH
402 return EXIT_GOTO_TB;
403 } else {
404 tcg_gen_movi_i64(cpu_pc, dest);
405 return EXIT_PC_UPDATED;
406 }
dbb30fe6
RH
407}
408
4af70374
RH
409static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
410 TCGv cmp, int32_t disp)
dbb30fe6 411{
4af70374 412 uint64_t dest = ctx->pc + (disp << 2);
dbb30fe6 413 int lab_true = gen_new_label();
9c29504e 414
4af70374
RH
415 if (use_goto_tb(ctx, dest)) {
416 tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
417
418 tcg_gen_goto_tb(0);
419 tcg_gen_movi_i64(cpu_pc, ctx->pc);
4b4a72e5 420 tcg_gen_exit_tb((tcg_target_long)ctx->tb);
4af70374
RH
421
422 gen_set_label(lab_true);
423 tcg_gen_goto_tb(1);
424 tcg_gen_movi_i64(cpu_pc, dest);
4b4a72e5 425 tcg_gen_exit_tb((tcg_target_long)ctx->tb + 1);
4af70374
RH
426
427 return EXIT_GOTO_TB;
428 } else {
429 int lab_over = gen_new_label();
430
431 /* ??? Consider using either
432 movi pc, next
433 addi tmp, pc, disp
434 movcond pc, cond, 0, tmp, pc
435 or
436 setcond tmp, cond, 0
437 movi pc, next
438 neg tmp, tmp
439 andi tmp, tmp, disp
440 add pc, pc, tmp
441 The current diamond subgraph surely isn't efficient. */
442
443 tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
444 tcg_gen_movi_i64(cpu_pc, ctx->pc);
445 tcg_gen_br(lab_over);
446 gen_set_label(lab_true);
447 tcg_gen_movi_i64(cpu_pc, dest);
448 gen_set_label(lab_over);
449
450 return EXIT_PC_UPDATED;
451 }
452}
453
454static ExitStatus gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
455 int32_t disp, int mask)
456{
457 TCGv cmp_tmp;
458
459 if (unlikely(ra == 31)) {
460 cmp_tmp = tcg_const_i64(0);
461 } else {
462 cmp_tmp = tcg_temp_new();
9c29504e 463 if (mask) {
4af70374 464 tcg_gen_andi_i64(cmp_tmp, cpu_ir[ra], 1);
dbb30fe6 465 } else {
4af70374 466 tcg_gen_mov_i64(cmp_tmp, cpu_ir[ra]);
dbb30fe6 467 }
9c29504e 468 }
4af70374
RH
469
470 return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
4c9649a9
JM
471}
472
4af70374 473/* Fold -0.0 for comparison with COND. */
dbb30fe6 474
4af70374 475static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
4c9649a9 476{
dbb30fe6 477 uint64_t mzero = 1ull << 63;
f18cd223 478
dbb30fe6
RH
479 switch (cond) {
480 case TCG_COND_LE:
481 case TCG_COND_GT:
482 /* For <= or >, the -0.0 value directly compares the way we want. */
4af70374 483 tcg_gen_mov_i64(dest, src);
a7812ae4 484 break;
dbb30fe6
RH
485
486 case TCG_COND_EQ:
487 case TCG_COND_NE:
488 /* For == or !=, we can simply mask off the sign bit and compare. */
4af70374 489 tcg_gen_andi_i64(dest, src, mzero - 1);
a7812ae4 490 break;
dbb30fe6
RH
491
492 case TCG_COND_GE:
dbb30fe6 493 case TCG_COND_LT:
4af70374
RH
494 /* For >= or <, map -0.0 to +0.0 via comparison and mask. */
495 tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero);
496 tcg_gen_neg_i64(dest, dest);
497 tcg_gen_and_i64(dest, dest, src);
a7812ae4 498 break;
dbb30fe6 499
a7812ae4
PB
500 default:
501 abort();
f18cd223 502 }
dbb30fe6
RH
503}
504
4af70374
RH
505static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
506 int32_t disp)
dbb30fe6 507{
4af70374 508 TCGv cmp_tmp;
dbb30fe6
RH
509
510 if (unlikely(ra == 31)) {
511 /* Very uncommon case, but easier to optimize it to an integer
512 comparison than continuing with the floating point comparison. */
4af70374 513 return gen_bcond(ctx, cond, ra, disp, 0);
dbb30fe6
RH
514 }
515
4af70374
RH
516 cmp_tmp = tcg_temp_new();
517 gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
518 return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
4c9649a9
JM
519}
520
bbe1dab4 521static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
4af70374 522 int islit, uint8_t lit, int mask)
4c9649a9 523{
bbe1dab4 524 TCGCond inv_cond = tcg_invert_cond(cond);
9c29504e
AJ
525 int l1;
526
527 if (unlikely(rc == 31))
528 return;
529
530 l1 = gen_new_label();
531
532 if (ra != 31) {
533 if (mask) {
a7812ae4 534 TCGv tmp = tcg_temp_new();
9c29504e
AJ
535 tcg_gen_andi_i64(tmp, cpu_ir[ra], 1);
536 tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
537 tcg_temp_free(tmp);
538 } else
539 tcg_gen_brcondi_i64(inv_cond, cpu_ir[ra], 0, l1);
540 } else {
541 /* Very uncommon case - Do not bother to optimize. */
542 TCGv tmp = tcg_const_i64(0);
543 tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
544 tcg_temp_free(tmp);
545 }
546
4c9649a9 547 if (islit)
9c29504e 548 tcg_gen_movi_i64(cpu_ir[rc], lit);
4c9649a9 549 else
dfaa8583 550 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
9c29504e 551 gen_set_label(l1);
4c9649a9
JM
552}
553
bbe1dab4 554static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
dbb30fe6 555{
4af70374 556 TCGv cmp_tmp;
dbb30fe6
RH
557 int l1;
558
4af70374 559 if (unlikely(rc == 31)) {
dbb30fe6 560 return;
4af70374
RH
561 }
562
563 cmp_tmp = tcg_temp_new();
dbb30fe6 564 if (unlikely(ra == 31)) {
4af70374
RH
565 tcg_gen_movi_i64(cmp_tmp, 0);
566 } else {
567 gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
dbb30fe6
RH
568 }
569
570 l1 = gen_new_label();
4af70374
RH
571 tcg_gen_brcondi_i64(tcg_invert_cond(cond), cmp_tmp, 0, l1);
572 tcg_temp_free(cmp_tmp);
dbb30fe6
RH
573
574 if (rb != 31)
575 tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]);
576 else
577 tcg_gen_movi_i64(cpu_fir[rc], 0);
578 gen_set_label(l1);
579}
580
f24518b5
RH
581#define QUAL_RM_N 0x080 /* Round mode nearest even */
582#define QUAL_RM_C 0x000 /* Round mode chopped */
583#define QUAL_RM_M 0x040 /* Round mode minus infinity */
584#define QUAL_RM_D 0x0c0 /* Round mode dynamic */
585#define QUAL_RM_MASK 0x0c0
586
587#define QUAL_U 0x100 /* Underflow enable (fp output) */
588#define QUAL_V 0x100 /* Overflow enable (int output) */
589#define QUAL_S 0x400 /* Software completion enable */
590#define QUAL_I 0x200 /* Inexact detection enable */
591
592static void gen_qual_roundmode(DisasContext *ctx, int fn11)
593{
594 TCGv_i32 tmp;
595
596 fn11 &= QUAL_RM_MASK;
597 if (fn11 == ctx->tb_rm) {
598 return;
599 }
600 ctx->tb_rm = fn11;
601
602 tmp = tcg_temp_new_i32();
603 switch (fn11) {
604 case QUAL_RM_N:
605 tcg_gen_movi_i32(tmp, float_round_nearest_even);
606 break;
607 case QUAL_RM_C:
608 tcg_gen_movi_i32(tmp, float_round_to_zero);
609 break;
610 case QUAL_RM_M:
611 tcg_gen_movi_i32(tmp, float_round_down);
612 break;
613 case QUAL_RM_D:
614 tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUState, fpcr_dyn_round));
615 break;
616 }
617
618#if defined(CONFIG_SOFTFLOAT_INLINE)
619 /* ??? The "softfloat.h" interface is to call set_float_rounding_mode.
620 With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
621 sets the one field. */
622 tcg_gen_st8_i32(tmp, cpu_env,
623 offsetof(CPUState, fp_status.float_rounding_mode));
624#else
625 gen_helper_setroundmode(tmp);
626#endif
627
628 tcg_temp_free_i32(tmp);
629}
630
631static void gen_qual_flushzero(DisasContext *ctx, int fn11)
632{
633 TCGv_i32 tmp;
634
635 fn11 &= QUAL_U;
636 if (fn11 == ctx->tb_ftz) {
637 return;
638 }
639 ctx->tb_ftz = fn11;
640
641 tmp = tcg_temp_new_i32();
642 if (fn11) {
643 /* Underflow is enabled, use the FPCR setting. */
644 tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUState, fpcr_flush_to_zero));
645 } else {
646 /* Underflow is disabled, force flush-to-zero. */
647 tcg_gen_movi_i32(tmp, 1);
648 }
649
650#if defined(CONFIG_SOFTFLOAT_INLINE)
651 tcg_gen_st8_i32(tmp, cpu_env,
652 offsetof(CPUState, fp_status.flush_to_zero));
653#else
654 gen_helper_setflushzero(tmp);
655#endif
656
657 tcg_temp_free_i32(tmp);
658}
659
660static TCGv gen_ieee_input(int reg, int fn11, int is_cmp)
661{
662 TCGv val = tcg_temp_new();
663 if (reg == 31) {
664 tcg_gen_movi_i64(val, 0);
665 } else if (fn11 & QUAL_S) {
666 gen_helper_ieee_input_s(val, cpu_fir[reg]);
667 } else if (is_cmp) {
668 gen_helper_ieee_input_cmp(val, cpu_fir[reg]);
669 } else {
670 gen_helper_ieee_input(val, cpu_fir[reg]);
671 }
672 return val;
673}
674
675static void gen_fp_exc_clear(void)
676{
677#if defined(CONFIG_SOFTFLOAT_INLINE)
678 TCGv_i32 zero = tcg_const_i32(0);
679 tcg_gen_st8_i32(zero, cpu_env,
680 offsetof(CPUState, fp_status.float_exception_flags));
681 tcg_temp_free_i32(zero);
682#else
683 gen_helper_fp_exc_clear();
684#endif
685}
686
687static void gen_fp_exc_raise_ignore(int rc, int fn11, int ignore)
688{
689 /* ??? We ought to be able to do something with imprecise exceptions.
690 E.g. notice we're still in the trap shadow of something within the
691 TB and do not generate the code to signal the exception; end the TB
692 when an exception is forced to arrive, either by consumption of a
693 register value or TRAPB or EXCB. */
694 TCGv_i32 exc = tcg_temp_new_i32();
695 TCGv_i32 reg;
696
697#if defined(CONFIG_SOFTFLOAT_INLINE)
698 tcg_gen_ld8u_i32(exc, cpu_env,
699 offsetof(CPUState, fp_status.float_exception_flags));
700#else
701 gen_helper_fp_exc_get(exc);
702#endif
703
704 if (ignore) {
705 tcg_gen_andi_i32(exc, exc, ~ignore);
706 }
707
708 /* ??? Pass in the regno of the destination so that the helper can
709 set EXC_MASK, which contains a bitmask of destination registers
710 that have caused arithmetic traps. A simple userspace emulation
711 does not require this. We do need it for a guest kernel's entArith,
712 or if we were to do something clever with imprecise exceptions. */
713 reg = tcg_const_i32(rc + 32);
714
715 if (fn11 & QUAL_S) {
716 gen_helper_fp_exc_raise_s(exc, reg);
717 } else {
718 gen_helper_fp_exc_raise(exc, reg);
719 }
720
721 tcg_temp_free_i32(reg);
722 tcg_temp_free_i32(exc);
723}
724
725static inline void gen_fp_exc_raise(int rc, int fn11)
726{
727 gen_fp_exc_raise_ignore(rc, fn11, fn11 & QUAL_I ? 0 : float_flag_inexact);
4c9649a9 728}
f24518b5 729
593f17e5
RH
730static void gen_fcvtlq(int rb, int rc)
731{
732 if (unlikely(rc == 31)) {
733 return;
734 }
735 if (unlikely(rb == 31)) {
736 tcg_gen_movi_i64(cpu_fir[rc], 0);
737 } else {
738 TCGv tmp = tcg_temp_new();
739
740 /* The arithmetic right shift here, plus the sign-extended mask below
741 yields a sign-extended result without an explicit ext32s_i64. */
742 tcg_gen_sari_i64(tmp, cpu_fir[rb], 32);
743 tcg_gen_shri_i64(cpu_fir[rc], cpu_fir[rb], 29);
744 tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000);
745 tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rc], 0x3fffffff);
746 tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
747
748 tcg_temp_free(tmp);
749 }
750}
751
735cf45f
RH
752static void gen_fcvtql(int rb, int rc)
753{
754 if (unlikely(rc == 31)) {
755 return;
756 }
757 if (unlikely(rb == 31)) {
758 tcg_gen_movi_i64(cpu_fir[rc], 0);
759 } else {
760 TCGv tmp = tcg_temp_new();
761
762 tcg_gen_andi_i64(tmp, cpu_fir[rb], 0xC0000000);
763 tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rb], 0x3FFFFFFF);
764 tcg_gen_shli_i64(tmp, tmp, 32);
765 tcg_gen_shli_i64(cpu_fir[rc], cpu_fir[rc], 29);
766 tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
767
768 tcg_temp_free(tmp);
769 }
770}
771
772static void gen_fcvtql_v(DisasContext *ctx, int rb, int rc)
773{
774 if (rb != 31) {
775 int lab = gen_new_label();
776 TCGv tmp = tcg_temp_new();
777
778 tcg_gen_ext32s_i64(tmp, cpu_fir[rb]);
779 tcg_gen_brcond_i64(TCG_COND_EQ, tmp, cpu_fir[rb], lab);
780 gen_excp(ctx, EXCP_ARITH, EXC_M_IOV);
781
782 gen_set_label(lab);
783 }
784 gen_fcvtql(rb, rc);
785}
786
f24518b5
RH
787#define FARITH2(name) \
788static inline void glue(gen_f, name)(int rb, int rc) \
789{ \
790 if (unlikely(rc == 31)) { \
791 return; \
792 } \
793 if (rb != 31) { \
794 gen_helper_ ## name (cpu_fir[rc], cpu_fir[rb]); \
795 } else { \
796 TCGv tmp = tcg_const_i64(0); \
797 gen_helper_ ## name (cpu_fir[rc], tmp); \
798 tcg_temp_free(tmp); \
799 } \
800}
f24518b5
RH
801
802/* ??? VAX instruction qualifiers ignored. */
a7812ae4
PB
803FARITH2(sqrtf)
804FARITH2(sqrtg)
a7812ae4
PB
805FARITH2(cvtgf)
806FARITH2(cvtgq)
807FARITH2(cvtqf)
808FARITH2(cvtqg)
f24518b5
RH
809
810static void gen_ieee_arith2(DisasContext *ctx, void (*helper)(TCGv, TCGv),
811 int rb, int rc, int fn11)
812{
813 TCGv vb;
814
815 /* ??? This is wrong: the instruction is not a nop, it still may
816 raise exceptions. */
817 if (unlikely(rc == 31)) {
818 return;
819 }
820
821 gen_qual_roundmode(ctx, fn11);
822 gen_qual_flushzero(ctx, fn11);
823 gen_fp_exc_clear();
824
825 vb = gen_ieee_input(rb, fn11, 0);
826 helper(cpu_fir[rc], vb);
827 tcg_temp_free(vb);
828
829 gen_fp_exc_raise(rc, fn11);
830}
831
832#define IEEE_ARITH2(name) \
833static inline void glue(gen_f, name)(DisasContext *ctx, \
834 int rb, int rc, int fn11) \
835{ \
836 gen_ieee_arith2(ctx, gen_helper_##name, rb, rc, fn11); \
837}
838IEEE_ARITH2(sqrts)
839IEEE_ARITH2(sqrtt)
840IEEE_ARITH2(cvtst)
841IEEE_ARITH2(cvtts)
842
843static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
844{
845 TCGv vb;
846 int ignore = 0;
847
848 /* ??? This is wrong: the instruction is not a nop, it still may
849 raise exceptions. */
850 if (unlikely(rc == 31)) {
851 return;
852 }
853
854 /* No need to set flushzero, since we have an integer output. */
855 gen_fp_exc_clear();
856 vb = gen_ieee_input(rb, fn11, 0);
857
858 /* Almost all integer conversions use cropped rounding, and most
859 also do not have integer overflow enabled. Special case that. */
860 switch (fn11) {
861 case QUAL_RM_C:
862 gen_helper_cvttq_c(cpu_fir[rc], vb);
863 break;
864 case QUAL_V | QUAL_RM_C:
865 case QUAL_S | QUAL_V | QUAL_RM_C:
866 ignore = float_flag_inexact;
867 /* FALLTHRU */
868 case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C:
869 gen_helper_cvttq_svic(cpu_fir[rc], vb);
870 break;
871 default:
872 gen_qual_roundmode(ctx, fn11);
873 gen_helper_cvttq(cpu_fir[rc], vb);
874 ignore |= (fn11 & QUAL_V ? 0 : float_flag_overflow);
875 ignore |= (fn11 & QUAL_I ? 0 : float_flag_inexact);
876 break;
877 }
878 tcg_temp_free(vb);
879
880 gen_fp_exc_raise_ignore(rc, fn11, ignore);
4c9649a9
JM
881}
882
f24518b5
RH
883static void gen_ieee_intcvt(DisasContext *ctx, void (*helper)(TCGv, TCGv),
884 int rb, int rc, int fn11)
885{
886 TCGv vb;
887
888 /* ??? This is wrong: the instruction is not a nop, it still may
889 raise exceptions. */
890 if (unlikely(rc == 31)) {
891 return;
892 }
893
894 gen_qual_roundmode(ctx, fn11);
895
896 if (rb == 31) {
897 vb = tcg_const_i64(0);
898 } else {
899 vb = cpu_fir[rb];
900 }
901
902 /* The only exception that can be raised by integer conversion
903 is inexact. Thus we only need to worry about exceptions when
904 inexact handling is requested. */
905 if (fn11 & QUAL_I) {
906 gen_fp_exc_clear();
907 helper(cpu_fir[rc], vb);
908 gen_fp_exc_raise(rc, fn11);
909 } else {
910 helper(cpu_fir[rc], vb);
911 }
912
913 if (rb == 31) {
914 tcg_temp_free(vb);
915 }
916}
917
918#define IEEE_INTCVT(name) \
919static inline void glue(gen_f, name)(DisasContext *ctx, \
920 int rb, int rc, int fn11) \
921{ \
922 gen_ieee_intcvt(ctx, gen_helper_##name, rb, rc, fn11); \
923}
924IEEE_INTCVT(cvtqs)
925IEEE_INTCVT(cvtqt)
926
dc96be4b
RH
927static void gen_cpys_internal(int ra, int rb, int rc, int inv_a, uint64_t mask)
928{
929 TCGv va, vb, vmask;
930 int za = 0, zb = 0;
931
932 if (unlikely(rc == 31)) {
933 return;
934 }
935
936 vmask = tcg_const_i64(mask);
937
938 TCGV_UNUSED_I64(va);
939 if (ra == 31) {
940 if (inv_a) {
941 va = vmask;
942 } else {
943 za = 1;
944 }
945 } else {
946 va = tcg_temp_new_i64();
947 tcg_gen_mov_i64(va, cpu_fir[ra]);
948 if (inv_a) {
949 tcg_gen_andc_i64(va, vmask, va);
950 } else {
951 tcg_gen_and_i64(va, va, vmask);
952 }
953 }
954
955 TCGV_UNUSED_I64(vb);
956 if (rb == 31) {
957 zb = 1;
958 } else {
959 vb = tcg_temp_new_i64();
960 tcg_gen_andc_i64(vb, cpu_fir[rb], vmask);
961 }
962
963 switch (za << 1 | zb) {
964 case 0 | 0:
965 tcg_gen_or_i64(cpu_fir[rc], va, vb);
966 break;
967 case 0 | 1:
968 tcg_gen_mov_i64(cpu_fir[rc], va);
969 break;
970 case 2 | 0:
971 tcg_gen_mov_i64(cpu_fir[rc], vb);
972 break;
973 case 2 | 1:
974 tcg_gen_movi_i64(cpu_fir[rc], 0);
975 break;
976 }
977
978 tcg_temp_free(vmask);
979 if (ra != 31) {
980 tcg_temp_free(va);
981 }
982 if (rb != 31) {
983 tcg_temp_free(vb);
984 }
985}
986
987static inline void gen_fcpys(int ra, int rb, int rc)
988{
989 gen_cpys_internal(ra, rb, rc, 0, 0x8000000000000000ULL);
990}
991
992static inline void gen_fcpysn(int ra, int rb, int rc)
993{
994 gen_cpys_internal(ra, rb, rc, 1, 0x8000000000000000ULL);
995}
996
997static inline void gen_fcpyse(int ra, int rb, int rc)
998{
999 gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
1000}
1001
f24518b5
RH
1002#define FARITH3(name) \
1003static inline void glue(gen_f, name)(int ra, int rb, int rc) \
1004{ \
1005 TCGv va, vb; \
1006 \
1007 if (unlikely(rc == 31)) { \
1008 return; \
1009 } \
1010 if (ra == 31) { \
1011 va = tcg_const_i64(0); \
1012 } else { \
1013 va = cpu_fir[ra]; \
1014 } \
1015 if (rb == 31) { \
1016 vb = tcg_const_i64(0); \
1017 } else { \
1018 vb = cpu_fir[rb]; \
1019 } \
1020 \
1021 gen_helper_ ## name (cpu_fir[rc], va, vb); \
1022 \
1023 if (ra == 31) { \
1024 tcg_temp_free(va); \
1025 } \
1026 if (rb == 31) { \
1027 tcg_temp_free(vb); \
1028 } \
1029}
f24518b5
RH
1030
1031/* ??? VAX instruction qualifiers ignored. */
a7812ae4
PB
1032FARITH3(addf)
1033FARITH3(subf)
1034FARITH3(mulf)
1035FARITH3(divf)
1036FARITH3(addg)
1037FARITH3(subg)
1038FARITH3(mulg)
1039FARITH3(divg)
1040FARITH3(cmpgeq)
1041FARITH3(cmpglt)
1042FARITH3(cmpgle)
f24518b5
RH
1043
1044static void gen_ieee_arith3(DisasContext *ctx,
1045 void (*helper)(TCGv, TCGv, TCGv),
1046 int ra, int rb, int rc, int fn11)
1047{
1048 TCGv va, vb;
1049
1050 /* ??? This is wrong: the instruction is not a nop, it still may
1051 raise exceptions. */
1052 if (unlikely(rc == 31)) {
1053 return;
1054 }
1055
1056 gen_qual_roundmode(ctx, fn11);
1057 gen_qual_flushzero(ctx, fn11);
1058 gen_fp_exc_clear();
1059
1060 va = gen_ieee_input(ra, fn11, 0);
1061 vb = gen_ieee_input(rb, fn11, 0);
1062 helper(cpu_fir[rc], va, vb);
1063 tcg_temp_free(va);
1064 tcg_temp_free(vb);
1065
1066 gen_fp_exc_raise(rc, fn11);
1067}
1068
1069#define IEEE_ARITH3(name) \
1070static inline void glue(gen_f, name)(DisasContext *ctx, \
1071 int ra, int rb, int rc, int fn11) \
1072{ \
1073 gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc, fn11); \
1074}
1075IEEE_ARITH3(adds)
1076IEEE_ARITH3(subs)
1077IEEE_ARITH3(muls)
1078IEEE_ARITH3(divs)
1079IEEE_ARITH3(addt)
1080IEEE_ARITH3(subt)
1081IEEE_ARITH3(mult)
1082IEEE_ARITH3(divt)
1083
1084static void gen_ieee_compare(DisasContext *ctx,
1085 void (*helper)(TCGv, TCGv, TCGv),
1086 int ra, int rb, int rc, int fn11)
1087{
1088 TCGv va, vb;
1089
1090 /* ??? This is wrong: the instruction is not a nop, it still may
1091 raise exceptions. */
1092 if (unlikely(rc == 31)) {
1093 return;
1094 }
1095
1096 gen_fp_exc_clear();
1097
1098 va = gen_ieee_input(ra, fn11, 1);
1099 vb = gen_ieee_input(rb, fn11, 1);
1100 helper(cpu_fir[rc], va, vb);
1101 tcg_temp_free(va);
1102 tcg_temp_free(vb);
1103
1104 gen_fp_exc_raise(rc, fn11);
1105}
1106
1107#define IEEE_CMP3(name) \
1108static inline void glue(gen_f, name)(DisasContext *ctx, \
1109 int ra, int rb, int rc, int fn11) \
1110{ \
1111 gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc, fn11); \
1112}
1113IEEE_CMP3(cmptun)
1114IEEE_CMP3(cmpteq)
1115IEEE_CMP3(cmptlt)
1116IEEE_CMP3(cmptle)
a7812ae4 1117
248c42f3
RH
1118static inline uint64_t zapnot_mask(uint8_t lit)
1119{
1120 uint64_t mask = 0;
1121 int i;
1122
1123 for (i = 0; i < 8; ++i) {
1124 if ((lit >> i) & 1)
1125 mask |= 0xffull << (i * 8);
1126 }
1127 return mask;
1128}
1129
87d98f95
RH
1130/* Implement zapnot with an immediate operand, which expands to some
1131 form of immediate AND. This is a basic building block in the
1132 definition of many of the other byte manipulation instructions. */
248c42f3 1133static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
87d98f95 1134{
87d98f95
RH
1135 switch (lit) {
1136 case 0x00:
248c42f3 1137 tcg_gen_movi_i64(dest, 0);
87d98f95
RH
1138 break;
1139 case 0x01:
248c42f3 1140 tcg_gen_ext8u_i64(dest, src);
87d98f95
RH
1141 break;
1142 case 0x03:
248c42f3 1143 tcg_gen_ext16u_i64(dest, src);
87d98f95
RH
1144 break;
1145 case 0x0f:
248c42f3 1146 tcg_gen_ext32u_i64(dest, src);
87d98f95
RH
1147 break;
1148 case 0xff:
248c42f3 1149 tcg_gen_mov_i64(dest, src);
87d98f95
RH
1150 break;
1151 default:
248c42f3 1152 tcg_gen_andi_i64 (dest, src, zapnot_mask (lit));
87d98f95
RH
1153 break;
1154 }
1155}
1156
1157static inline void gen_zapnot(int ra, int rb, int rc, int islit, uint8_t lit)
1158{
1159 if (unlikely(rc == 31))
1160 return;
1161 else if (unlikely(ra == 31))
1162 tcg_gen_movi_i64(cpu_ir[rc], 0);
1163 else if (islit)
248c42f3 1164 gen_zapnoti(cpu_ir[rc], cpu_ir[ra], lit);
87d98f95
RH
1165 else
1166 gen_helper_zapnot (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1167}
1168
1169static inline void gen_zap(int ra, int rb, int rc, int islit, uint8_t lit)
1170{
1171 if (unlikely(rc == 31))
1172 return;
1173 else if (unlikely(ra == 31))
1174 tcg_gen_movi_i64(cpu_ir[rc], 0);
1175 else if (islit)
248c42f3 1176 gen_zapnoti(cpu_ir[rc], cpu_ir[ra], ~lit);
87d98f95
RH
1177 else
1178 gen_helper_zap (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1179}
1180
1181
248c42f3 1182/* EXTWH, EXTLH, EXTQH */
ffec44f1
RH
1183static void gen_ext_h(int ra, int rb, int rc, int islit,
1184 uint8_t lit, uint8_t byte_mask)
b3249f63
AJ
1185{
1186 if (unlikely(rc == 31))
1187 return;
377a43b6
RH
1188 else if (unlikely(ra == 31))
1189 tcg_gen_movi_i64(cpu_ir[rc], 0);
1190 else {
dfaa8583 1191 if (islit) {
377a43b6
RH
1192 lit = (64 - (lit & 7) * 8) & 0x3f;
1193 tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit);
fe2b269a 1194 } else {
377a43b6 1195 TCGv tmp1 = tcg_temp_new();
b3249f63
AJ
1196 tcg_gen_andi_i64(tmp1, cpu_ir[rb], 7);
1197 tcg_gen_shli_i64(tmp1, tmp1, 3);
dbf95805
VW
1198 tcg_gen_neg_i64(tmp1, tmp1);
1199 tcg_gen_andi_i64(tmp1, tmp1, 0x3f);
dfaa8583 1200 tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], tmp1);
b3249f63 1201 tcg_temp_free(tmp1);
dfaa8583 1202 }
248c42f3 1203 gen_zapnoti(cpu_ir[rc], cpu_ir[rc], byte_mask);
377a43b6 1204 }
b3249f63
AJ
1205}
1206
248c42f3 1207/* EXTBL, EXTWL, EXTLL, EXTQL */
ffec44f1
RH
1208static void gen_ext_l(int ra, int rb, int rc, int islit,
1209 uint8_t lit, uint8_t byte_mask)
b3249f63
AJ
1210{
1211 if (unlikely(rc == 31))
1212 return;
377a43b6
RH
1213 else if (unlikely(ra == 31))
1214 tcg_gen_movi_i64(cpu_ir[rc], 0);
1215 else {
dfaa8583 1216 if (islit) {
377a43b6 1217 tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], (lit & 7) * 8);
dfaa8583 1218 } else {
a7812ae4 1219 TCGv tmp = tcg_temp_new();
b3249f63
AJ
1220 tcg_gen_andi_i64(tmp, cpu_ir[rb], 7);
1221 tcg_gen_shli_i64(tmp, tmp, 3);
dfaa8583 1222 tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], tmp);
b3249f63 1223 tcg_temp_free(tmp);
fe2b269a 1224 }
248c42f3
RH
1225 gen_zapnoti(cpu_ir[rc], cpu_ir[rc], byte_mask);
1226 }
1227}
1228
50eb6e5c
RH
1229/* INSWH, INSLH, INSQH */
1230static void gen_ins_h(int ra, int rb, int rc, int islit,
1231 uint8_t lit, uint8_t byte_mask)
1232{
1233 if (unlikely(rc == 31))
1234 return;
1235 else if (unlikely(ra == 31) || (islit && (lit & 7) == 0))
1236 tcg_gen_movi_i64(cpu_ir[rc], 0);
1237 else {
1238 TCGv tmp = tcg_temp_new();
1239
1240 /* The instruction description has us left-shift the byte mask
1241 and extract bits <15:8> and apply that zap at the end. This
1242 is equivalent to simply performing the zap first and shifting
1243 afterward. */
1244 gen_zapnoti (tmp, cpu_ir[ra], byte_mask);
1245
1246 if (islit) {
1247 /* Note that we have handled the lit==0 case above. */
1248 tcg_gen_shri_i64 (cpu_ir[rc], tmp, 64 - (lit & 7) * 8);
1249 } else {
1250 TCGv shift = tcg_temp_new();
1251
1252 /* If (B & 7) == 0, we need to shift by 64 and leave a zero.
1253 Do this portably by splitting the shift into two parts:
1254 shift_count-1 and 1. Arrange for the -1 by using
1255 ones-complement instead of twos-complement in the negation:
1256 ~((B & 7) * 8) & 63. */
1257
1258 tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1259 tcg_gen_shli_i64(shift, shift, 3);
1260 tcg_gen_not_i64(shift, shift);
1261 tcg_gen_andi_i64(shift, shift, 0x3f);
1262
1263 tcg_gen_shr_i64(cpu_ir[rc], tmp, shift);
1264 tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[rc], 1);
1265 tcg_temp_free(shift);
1266 }
1267 tcg_temp_free(tmp);
1268 }
1269}
1270
248c42f3 1271/* INSBL, INSWL, INSLL, INSQL */
ffec44f1
RH
1272static void gen_ins_l(int ra, int rb, int rc, int islit,
1273 uint8_t lit, uint8_t byte_mask)
248c42f3
RH
1274{
1275 if (unlikely(rc == 31))
1276 return;
1277 else if (unlikely(ra == 31))
1278 tcg_gen_movi_i64(cpu_ir[rc], 0);
1279 else {
1280 TCGv tmp = tcg_temp_new();
1281
1282 /* The instruction description has us left-shift the byte mask
1283 the same number of byte slots as the data and apply the zap
1284 at the end. This is equivalent to simply performing the zap
1285 first and shifting afterward. */
1286 gen_zapnoti (tmp, cpu_ir[ra], byte_mask);
1287
1288 if (islit) {
1289 tcg_gen_shli_i64(cpu_ir[rc], tmp, (lit & 7) * 8);
1290 } else {
1291 TCGv shift = tcg_temp_new();
1292 tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1293 tcg_gen_shli_i64(shift, shift, 3);
1294 tcg_gen_shl_i64(cpu_ir[rc], tmp, shift);
1295 tcg_temp_free(shift);
1296 }
1297 tcg_temp_free(tmp);
377a43b6 1298 }
b3249f63
AJ
1299}
1300
ffec44f1
RH
1301/* MSKWH, MSKLH, MSKQH */
1302static void gen_msk_h(int ra, int rb, int rc, int islit,
1303 uint8_t lit, uint8_t byte_mask)
1304{
1305 if (unlikely(rc == 31))
1306 return;
1307 else if (unlikely(ra == 31))
1308 tcg_gen_movi_i64(cpu_ir[rc], 0);
1309 else if (islit) {
1310 gen_zapnoti (cpu_ir[rc], cpu_ir[ra], ~((byte_mask << (lit & 7)) >> 8));
1311 } else {
1312 TCGv shift = tcg_temp_new();
1313 TCGv mask = tcg_temp_new();
1314
1315 /* The instruction description is as above, where the byte_mask
1316 is shifted left, and then we extract bits <15:8>. This can be
1317 emulated with a right-shift on the expanded byte mask. This
1318 requires extra care because for an input <2:0> == 0 we need a
1319 shift of 64 bits in order to generate a zero. This is done by
1320 splitting the shift into two parts, the variable shift - 1
1321 followed by a constant 1 shift. The code we expand below is
1322 equivalent to ~((B & 7) * 8) & 63. */
1323
1324 tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1325 tcg_gen_shli_i64(shift, shift, 3);
1326 tcg_gen_not_i64(shift, shift);
1327 tcg_gen_andi_i64(shift, shift, 0x3f);
1328 tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
1329 tcg_gen_shr_i64(mask, mask, shift);
1330 tcg_gen_shri_i64(mask, mask, 1);
1331
1332 tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], mask);
1333
1334 tcg_temp_free(mask);
1335 tcg_temp_free(shift);
1336 }
1337}
1338
14ab1634 1339/* MSKBL, MSKWL, MSKLL, MSKQL */
ffec44f1
RH
1340static void gen_msk_l(int ra, int rb, int rc, int islit,
1341 uint8_t lit, uint8_t byte_mask)
14ab1634
RH
1342{
1343 if (unlikely(rc == 31))
1344 return;
1345 else if (unlikely(ra == 31))
1346 tcg_gen_movi_i64(cpu_ir[rc], 0);
1347 else if (islit) {
1348 gen_zapnoti (cpu_ir[rc], cpu_ir[ra], ~(byte_mask << (lit & 7)));
1349 } else {
1350 TCGv shift = tcg_temp_new();
1351 TCGv mask = tcg_temp_new();
1352
1353 tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1354 tcg_gen_shli_i64(shift, shift, 3);
1355 tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
1356 tcg_gen_shl_i64(mask, mask, shift);
1357
1358 tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], mask);
1359
1360 tcg_temp_free(mask);
1361 tcg_temp_free(shift);
1362 }
1363}
1364
04acd307 1365/* Code to call arith3 helpers */
a7812ae4 1366#define ARITH3(name) \
636aa200
BS
1367static inline void glue(gen_, name)(int ra, int rb, int rc, int islit,\
1368 uint8_t lit) \
a7812ae4
PB
1369{ \
1370 if (unlikely(rc == 31)) \
1371 return; \
1372 \
1373 if (ra != 31) { \
1374 if (islit) { \
1375 TCGv tmp = tcg_const_i64(lit); \
1376 gen_helper_ ## name(cpu_ir[rc], cpu_ir[ra], tmp); \
1377 tcg_temp_free(tmp); \
1378 } else \
1379 gen_helper_ ## name (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); \
1380 } else { \
1381 TCGv tmp1 = tcg_const_i64(0); \
1382 if (islit) { \
1383 TCGv tmp2 = tcg_const_i64(lit); \
1384 gen_helper_ ## name (cpu_ir[rc], tmp1, tmp2); \
1385 tcg_temp_free(tmp2); \
1386 } else \
1387 gen_helper_ ## name (cpu_ir[rc], tmp1, cpu_ir[rb]); \
1388 tcg_temp_free(tmp1); \
1389 } \
b3249f63 1390}
a7812ae4
PB
1391ARITH3(cmpbge)
1392ARITH3(addlv)
1393ARITH3(sublv)
1394ARITH3(addqv)
1395ARITH3(subqv)
a7812ae4
PB
1396ARITH3(umulh)
1397ARITH3(mullv)
1398ARITH3(mulqv)
13e4df99
RH
1399ARITH3(minub8)
1400ARITH3(minsb8)
1401ARITH3(minuw4)
1402ARITH3(minsw4)
1403ARITH3(maxub8)
1404ARITH3(maxsb8)
1405ARITH3(maxuw4)
1406ARITH3(maxsw4)
1407ARITH3(perr)
1408
1409#define MVIOP2(name) \
1410static inline void glue(gen_, name)(int rb, int rc) \
1411{ \
1412 if (unlikely(rc == 31)) \
1413 return; \
1414 if (unlikely(rb == 31)) \
1415 tcg_gen_movi_i64(cpu_ir[rc], 0); \
1416 else \
1417 gen_helper_ ## name (cpu_ir[rc], cpu_ir[rb]); \
1418}
1419MVIOP2(pklb)
1420MVIOP2(pkwb)
1421MVIOP2(unpkbl)
1422MVIOP2(unpkbw)
b3249f63 1423
9e05960f
RH
1424static void gen_cmp(TCGCond cond, int ra, int rb, int rc,
1425 int islit, uint8_t lit)
01ff9cc8 1426{
9e05960f 1427 TCGv va, vb;
01ff9cc8 1428
9e05960f 1429 if (unlikely(rc == 31)) {
13e4df99 1430 return;
9e05960f 1431 }
01ff9cc8 1432
9e05960f
RH
1433 if (ra == 31) {
1434 va = tcg_const_i64(0);
1435 } else {
1436 va = cpu_ir[ra];
1437 }
1438 if (islit) {
1439 vb = tcg_const_i64(lit);
1440 } else {
1441 vb = cpu_ir[rb];
1442 }
01ff9cc8 1443
9e05960f 1444 tcg_gen_setcond_i64(cond, cpu_ir[rc], va, vb);
01ff9cc8 1445
9e05960f
RH
1446 if (ra == 31) {
1447 tcg_temp_free(va);
1448 }
1449 if (islit) {
1450 tcg_temp_free(vb);
1451 }
01ff9cc8
AJ
1452}
1453
ac316ca4
RH
1454static void gen_rx(int ra, int set)
1455{
1456 TCGv_i32 tmp;
1457
1458 if (ra != 31) {
1459 tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, offsetof(CPUState, intr_flag));
1460 }
1461
1462 tmp = tcg_const_i32(set);
1463 tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUState, intr_flag));
1464 tcg_temp_free_i32(tmp);
1465}
1466
26b46094
RH
1467#ifndef CONFIG_USER_ONLY
1468
1469#define PR_BYTE 0x100000
1470#define PR_LONG 0x200000
1471
1472static int cpu_pr_data(int pr)
1473{
1474 switch (pr) {
1475 case 0: return offsetof(CPUAlphaState, ps) | PR_BYTE;
1476 case 1: return offsetof(CPUAlphaState, fen) | PR_BYTE;
1477 case 2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
1478 case 3: return offsetof(CPUAlphaState, trap_arg0);
1479 case 4: return offsetof(CPUAlphaState, trap_arg1);
1480 case 5: return offsetof(CPUAlphaState, trap_arg2);
1481 case 6: return offsetof(CPUAlphaState, exc_addr);
1482 case 7: return offsetof(CPUAlphaState, palbr);
1483 case 8: return offsetof(CPUAlphaState, ptbr);
1484 case 9: return offsetof(CPUAlphaState, vptptr);
1485 case 10: return offsetof(CPUAlphaState, unique);
1486 case 11: return offsetof(CPUAlphaState, sysval);
1487 case 12: return offsetof(CPUAlphaState, usp);
1488
1489 case 32 ... 39:
1490 return offsetof(CPUAlphaState, shadow[pr - 32]);
1491 case 40 ... 63:
1492 return offsetof(CPUAlphaState, scratch[pr - 40]);
1493 }
1494 return 0;
1495}
1496
1497static void gen_mfpr(int ra, int regno)
1498{
1499 int data = cpu_pr_data(regno);
1500
1501 /* In our emulated PALcode, these processor registers have no
1502 side effects from reading. */
1503 if (ra == 31) {
1504 return;
1505 }
1506
1507 /* The basic registers are data only, and unknown registers
1508 are read-zero, write-ignore. */
1509 if (data == 0) {
1510 tcg_gen_movi_i64(cpu_ir[ra], 0);
1511 } else if (data & PR_BYTE) {
1512 tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, data & ~PR_BYTE);
1513 } else if (data & PR_LONG) {
1514 tcg_gen_ld32s_i64(cpu_ir[ra], cpu_env, data & ~PR_LONG);
1515 } else {
1516 tcg_gen_ld_i64(cpu_ir[ra], cpu_env, data);
1517 }
1518}
1519
1520static void gen_mtpr(int rb, int regno)
1521{
1522 TCGv tmp;
1523 int data;
1524
1525 if (rb == 31) {
1526 tmp = tcg_const_i64(0);
1527 } else {
1528 tmp = cpu_ir[rb];
1529 }
1530
1531 /* The basic registers are data only, and unknown registers
1532 are read-zero, write-ignore. */
1533 data = cpu_pr_data(regno);
1534 if (data != 0) {
1535 if (data & PR_BYTE) {
1536 tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE);
1537 } else if (data & PR_LONG) {
1538 tcg_gen_st32_i64(tmp, cpu_env, data & ~PR_LONG);
1539 } else {
1540 tcg_gen_st_i64(tmp, cpu_env, data);
1541 }
1542 }
1543
1544 if (rb == 31) {
1545 tcg_temp_free(tmp);
1546 }
1547}
1548#endif /* !USER_ONLY*/
1549
4af70374 1550static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
4c9649a9
JM
1551{
1552 uint32_t palcode;
1553 int32_t disp21, disp16, disp12;
f88fe4e3
BS
1554 uint16_t fn11;
1555 uint8_t opc, ra, rb, rc, fpfn, fn7, fn2, islit, real_islit;
adf3c8b6 1556 uint8_t lit;
4af70374 1557 ExitStatus ret;
4c9649a9
JM
1558
1559 /* Decode all instruction fields */
1560 opc = insn >> 26;
1561 ra = (insn >> 21) & 0x1F;
1562 rb = (insn >> 16) & 0x1F;
1563 rc = insn & 0x1F;
13e4df99 1564 real_islit = islit = (insn >> 12) & 1;
dfaa8583
AJ
1565 if (rb == 31 && !islit) {
1566 islit = 1;
1567 lit = 0;
1568 } else
1569 lit = (insn >> 13) & 0xFF;
4c9649a9
JM
1570 palcode = insn & 0x03FFFFFF;
1571 disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
1572 disp16 = (int16_t)(insn & 0x0000FFFF);
1573 disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20;
4c9649a9
JM
1574 fn11 = (insn >> 5) & 0x000007FF;
1575 fpfn = fn11 & 0x3F;
1576 fn7 = (insn >> 5) & 0x0000007F;
1577 fn2 = (insn >> 5) & 0x00000003;
806991da 1578 LOG_DISAS("opc %02x ra %2d rb %2d rc %2d disp16 %6d\n",
d12d51d5 1579 opc, ra, rb, rc, disp16);
806991da 1580
4af70374 1581 ret = NO_EXIT;
4c9649a9
JM
1582 switch (opc) {
1583 case 0x00:
1584 /* CALL_PAL */
ab471ade
RH
1585#ifdef CONFIG_USER_ONLY
1586 if (palcode == 0x9E) {
1587 /* RDUNIQUE */
1588 tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_uniq);
1589 break;
1590 } else if (palcode == 0x9F) {
1591 /* WRUNIQUE */
1592 tcg_gen_mov_i64(cpu_uniq, cpu_ir[IR_A0]);
1593 break;
1594 }
1595#endif
4c9649a9
JM
1596 if (palcode >= 0x80 && palcode < 0xC0) {
1597 /* Unprivileged PAL call */
07b6c13b 1598 ret = gen_excp(ctx, EXCP_CALL_PAL, palcode & 0xBF);
ab471ade
RH
1599 break;
1600 }
1601#ifndef CONFIG_USER_ONLY
1602 if (palcode < 0x40) {
4c9649a9 1603 /* Privileged PAL code */
8417845e 1604 if (ctx->mem_idx != MMU_KERNEL_IDX) {
4c9649a9 1605 goto invalid_opc;
8417845e 1606 }
07b6c13b 1607 ret = gen_excp(ctx, EXCP_CALL_PAL, palcode & 0x3F);
4c9649a9 1608 }
ab471ade
RH
1609#endif
1610 /* Invalid PAL call */
1611 goto invalid_opc;
4c9649a9
JM
1612 case 0x01:
1613 /* OPC01 */
1614 goto invalid_opc;
1615 case 0x02:
1616 /* OPC02 */
1617 goto invalid_opc;
1618 case 0x03:
1619 /* OPC03 */
1620 goto invalid_opc;
1621 case 0x04:
1622 /* OPC04 */
1623 goto invalid_opc;
1624 case 0x05:
1625 /* OPC05 */
1626 goto invalid_opc;
1627 case 0x06:
1628 /* OPC06 */
1629 goto invalid_opc;
1630 case 0x07:
1631 /* OPC07 */
1632 goto invalid_opc;
1633 case 0x08:
1634 /* LDA */
1ef4ef4e 1635 if (likely(ra != 31)) {
496cb5b9 1636 if (rb != 31)
3761035f
AJ
1637 tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16);
1638 else
1639 tcg_gen_movi_i64(cpu_ir[ra], disp16);
496cb5b9 1640 }
4c9649a9
JM
1641 break;
1642 case 0x09:
1643 /* LDAH */
1ef4ef4e 1644 if (likely(ra != 31)) {
496cb5b9 1645 if (rb != 31)
3761035f
AJ
1646 tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16 << 16);
1647 else
1648 tcg_gen_movi_i64(cpu_ir[ra], disp16 << 16);
496cb5b9 1649 }
4c9649a9
JM
1650 break;
1651 case 0x0A:
1652 /* LDBU */
a18ad893
RH
1653 if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
1654 gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
1655 break;
1656 }
1657 goto invalid_opc;
4c9649a9
JM
1658 case 0x0B:
1659 /* LDQ_U */
f18cd223 1660 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
4c9649a9
JM
1661 break;
1662 case 0x0C:
1663 /* LDWU */
a18ad893
RH
1664 if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
1665 gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
1666 break;
1667 }
1668 goto invalid_opc;
4c9649a9
JM
1669 case 0x0D:
1670 /* STW */
6910b8f6 1671 gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
4c9649a9
JM
1672 break;
1673 case 0x0E:
1674 /* STB */
6910b8f6 1675 gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
4c9649a9
JM
1676 break;
1677 case 0x0F:
1678 /* STQ_U */
6910b8f6 1679 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
4c9649a9
JM
1680 break;
1681 case 0x10:
1682 switch (fn7) {
1683 case 0x00:
1684 /* ADDL */
30c7183b
AJ
1685 if (likely(rc != 31)) {
1686 if (ra != 31) {
1687 if (islit) {
1688 tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
1689 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
dfaa8583 1690 } else {
30c7183b
AJ
1691 tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1692 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
dfaa8583 1693 }
30c7183b
AJ
1694 } else {
1695 if (islit)
dfaa8583 1696 tcg_gen_movi_i64(cpu_ir[rc], lit);
30c7183b 1697 else
dfaa8583 1698 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
30c7183b
AJ
1699 }
1700 }
4c9649a9
JM
1701 break;
1702 case 0x02:
1703 /* S4ADDL */
30c7183b
AJ
1704 if (likely(rc != 31)) {
1705 if (ra != 31) {
a7812ae4 1706 TCGv tmp = tcg_temp_new();
dfaa8583
AJ
1707 tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1708 if (islit)
1709 tcg_gen_addi_i64(tmp, tmp, lit);
1710 else
1711 tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
1712 tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1713 tcg_temp_free(tmp);
30c7183b
AJ
1714 } else {
1715 if (islit)
1716 tcg_gen_movi_i64(cpu_ir[rc], lit);
30c7183b 1717 else
dfaa8583 1718 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
30c7183b
AJ
1719 }
1720 }
4c9649a9
JM
1721 break;
1722 case 0x09:
1723 /* SUBL */
30c7183b
AJ
1724 if (likely(rc != 31)) {
1725 if (ra != 31) {
dfaa8583 1726 if (islit)
30c7183b 1727 tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
dfaa8583 1728 else
30c7183b 1729 tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
dfaa8583 1730 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
30c7183b
AJ
1731 } else {
1732 if (islit)
1733 tcg_gen_movi_i64(cpu_ir[rc], -lit);
dfaa8583 1734 else {
30c7183b
AJ
1735 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
1736 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
30c7183b
AJ
1737 }
1738 }
4c9649a9
JM
1739 break;
1740 case 0x0B:
1741 /* S4SUBL */
30c7183b
AJ
1742 if (likely(rc != 31)) {
1743 if (ra != 31) {
a7812ae4 1744 TCGv tmp = tcg_temp_new();
dfaa8583
AJ
1745 tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1746 if (islit)
1747 tcg_gen_subi_i64(tmp, tmp, lit);
1748 else
1749 tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
1750 tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1751 tcg_temp_free(tmp);
30c7183b
AJ
1752 } else {
1753 if (islit)
1754 tcg_gen_movi_i64(cpu_ir[rc], -lit);
dfaa8583 1755 else {
30c7183b
AJ
1756 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
1757 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
dfaa8583 1758 }
30c7183b
AJ
1759 }
1760 }
4c9649a9
JM
1761 break;
1762 case 0x0F:
1763 /* CMPBGE */
a7812ae4 1764 gen_cmpbge(ra, rb, rc, islit, lit);
4c9649a9
JM
1765 break;
1766 case 0x12:
1767 /* S8ADDL */
30c7183b
AJ
1768 if (likely(rc != 31)) {
1769 if (ra != 31) {
a7812ae4 1770 TCGv tmp = tcg_temp_new();
dfaa8583
AJ
1771 tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
1772 if (islit)
1773 tcg_gen_addi_i64(tmp, tmp, lit);
1774 else
1775 tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
1776 tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1777 tcg_temp_free(tmp);
30c7183b
AJ
1778 } else {
1779 if (islit)
1780 tcg_gen_movi_i64(cpu_ir[rc], lit);
30c7183b 1781 else
dfaa8583 1782 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
30c7183b
AJ
1783 }
1784 }
4c9649a9
JM
1785 break;
1786 case 0x1B:
1787 /* S8SUBL */
30c7183b
AJ
1788 if (likely(rc != 31)) {
1789 if (ra != 31) {
a7812ae4 1790 TCGv tmp = tcg_temp_new();
dfaa8583
AJ
1791 tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
1792 if (islit)
1793 tcg_gen_subi_i64(tmp, tmp, lit);
1794 else
1795 tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
1796 tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1797 tcg_temp_free(tmp);
30c7183b
AJ
1798 } else {
1799 if (islit)
1800 tcg_gen_movi_i64(cpu_ir[rc], -lit);
dfaa8583 1801 else
30c7183b
AJ
1802 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
1803 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
dfaa8583 1804 }
30c7183b
AJ
1805 }
1806 }
4c9649a9
JM
1807 break;
1808 case 0x1D:
1809 /* CMPULT */
01ff9cc8 1810 gen_cmp(TCG_COND_LTU, ra, rb, rc, islit, lit);
4c9649a9
JM
1811 break;
1812 case 0x20:
1813 /* ADDQ */
30c7183b
AJ
1814 if (likely(rc != 31)) {
1815 if (ra != 31) {
1816 if (islit)
1817 tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
30c7183b 1818 else
dfaa8583 1819 tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
30c7183b
AJ
1820 } else {
1821 if (islit)
1822 tcg_gen_movi_i64(cpu_ir[rc], lit);
30c7183b 1823 else
dfaa8583 1824 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
30c7183b
AJ
1825 }
1826 }
4c9649a9
JM
1827 break;
1828 case 0x22:
1829 /* S4ADDQ */
30c7183b
AJ
1830 if (likely(rc != 31)) {
1831 if (ra != 31) {
a7812ae4 1832 TCGv tmp = tcg_temp_new();
dfaa8583
AJ
1833 tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1834 if (islit)
1835 tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
1836 else
1837 tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
1838 tcg_temp_free(tmp);
30c7183b
AJ
1839 } else {
1840 if (islit)
1841 tcg_gen_movi_i64(cpu_ir[rc], lit);
30c7183b 1842 else
dfaa8583 1843 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
30c7183b
AJ
1844 }
1845 }
4c9649a9
JM
1846 break;
1847 case 0x29:
1848 /* SUBQ */
30c7183b
AJ
1849 if (likely(rc != 31)) {
1850 if (ra != 31) {
1851 if (islit)
1852 tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
30c7183b 1853 else
dfaa8583 1854 tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
30c7183b
AJ
1855 } else {
1856 if (islit)
1857 tcg_gen_movi_i64(cpu_ir[rc], -lit);
30c7183b 1858 else
dfaa8583 1859 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
30c7183b
AJ
1860 }
1861 }
4c9649a9
JM
1862 break;
1863 case 0x2B:
1864 /* S4SUBQ */
30c7183b
AJ
1865 if (likely(rc != 31)) {
1866 if (ra != 31) {
a7812ae4 1867 TCGv tmp = tcg_temp_new();
dfaa8583
AJ
1868 tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1869 if (islit)
1870 tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
1871 else
1872 tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
1873 tcg_temp_free(tmp);
30c7183b
AJ
1874 } else {
1875 if (islit)
1876 tcg_gen_movi_i64(cpu_ir[rc], -lit);
30c7183b 1877 else
dfaa8583 1878 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
30c7183b
AJ
1879 }
1880 }
4c9649a9
JM
1881 break;
1882 case 0x2D:
1883 /* CMPEQ */
01ff9cc8 1884 gen_cmp(TCG_COND_EQ, ra, rb, rc, islit, lit);
4c9649a9
JM
1885 break;
1886 case 0x32:
1887 /* S8ADDQ */
30c7183b
AJ
1888 if (likely(rc != 31)) {
1889 if (ra != 31) {
a7812ae4 1890 TCGv tmp = tcg_temp_new();
dfaa8583
AJ
1891 tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
1892 if (islit)
1893 tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
1894 else
1895 tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
1896 tcg_temp_free(tmp);
30c7183b
AJ
1897 } else {
1898 if (islit)
1899 tcg_gen_movi_i64(cpu_ir[rc], lit);
30c7183b 1900 else
dfaa8583 1901 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
30c7183b
AJ
1902 }
1903 }
4c9649a9
JM
1904 break;
1905 case 0x3B:
1906 /* S8SUBQ */
30c7183b
AJ
1907 if (likely(rc != 31)) {
1908 if (ra != 31) {
a7812ae4 1909 TCGv tmp = tcg_temp_new();
dfaa8583
AJ
1910 tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
1911 if (islit)
1912 tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
1913 else
1914 tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
1915 tcg_temp_free(tmp);
30c7183b
AJ
1916 } else {
1917 if (islit)
1918 tcg_gen_movi_i64(cpu_ir[rc], -lit);
30c7183b 1919 else
dfaa8583 1920 tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
30c7183b
AJ
1921 }
1922 }
4c9649a9
JM
1923 break;
1924 case 0x3D:
1925 /* CMPULE */
01ff9cc8 1926 gen_cmp(TCG_COND_LEU, ra, rb, rc, islit, lit);
4c9649a9
JM
1927 break;
1928 case 0x40:
1929 /* ADDL/V */
a7812ae4 1930 gen_addlv(ra, rb, rc, islit, lit);
4c9649a9
JM
1931 break;
1932 case 0x49:
1933 /* SUBL/V */
a7812ae4 1934 gen_sublv(ra, rb, rc, islit, lit);
4c9649a9
JM
1935 break;
1936 case 0x4D:
1937 /* CMPLT */
01ff9cc8 1938 gen_cmp(TCG_COND_LT, ra, rb, rc, islit, lit);
4c9649a9
JM
1939 break;
1940 case 0x60:
1941 /* ADDQ/V */
a7812ae4 1942 gen_addqv(ra, rb, rc, islit, lit);
4c9649a9
JM
1943 break;
1944 case 0x69:
1945 /* SUBQ/V */
a7812ae4 1946 gen_subqv(ra, rb, rc, islit, lit);
4c9649a9
JM
1947 break;
1948 case 0x6D:
1949 /* CMPLE */
01ff9cc8 1950 gen_cmp(TCG_COND_LE, ra, rb, rc, islit, lit);
4c9649a9
JM
1951 break;
1952 default:
1953 goto invalid_opc;
1954 }
1955 break;
1956 case 0x11:
1957 switch (fn7) {
1958 case 0x00:
1959 /* AND */
30c7183b 1960 if (likely(rc != 31)) {
dfaa8583 1961 if (ra == 31)
30c7183b
AJ
1962 tcg_gen_movi_i64(cpu_ir[rc], 0);
1963 else if (islit)
1964 tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], lit);
1965 else
1966 tcg_gen_and_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1967 }
4c9649a9
JM
1968 break;
1969 case 0x08:
1970 /* BIC */
30c7183b
AJ
1971 if (likely(rc != 31)) {
1972 if (ra != 31) {
1973 if (islit)
1974 tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
1b581c44
AJ
1975 else
1976 tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
30c7183b
AJ
1977 } else
1978 tcg_gen_movi_i64(cpu_ir[rc], 0);
1979 }
4c9649a9
JM
1980 break;
1981 case 0x14:
1982 /* CMOVLBS */
bbe1dab4 1983 gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 1);
4c9649a9
JM
1984 break;
1985 case 0x16:
1986 /* CMOVLBC */
bbe1dab4 1987 gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
4c9649a9
JM
1988 break;
1989 case 0x20:
1990 /* BIS */
30c7183b
AJ
1991 if (likely(rc != 31)) {
1992 if (ra != 31) {
1993 if (islit)
1994 tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], lit);
8bb6e981 1995 else
30c7183b 1996 tcg_gen_or_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
4c9649a9 1997 } else {
30c7183b
AJ
1998 if (islit)
1999 tcg_gen_movi_i64(cpu_ir[rc], lit);
30c7183b 2000 else
dfaa8583 2001 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
4c9649a9 2002 }
4c9649a9
JM
2003 }
2004 break;
2005 case 0x24:
2006 /* CMOVEQ */
bbe1dab4 2007 gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
4c9649a9
JM
2008 break;
2009 case 0x26:
2010 /* CMOVNE */
bbe1dab4 2011 gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 0);
4c9649a9
JM
2012 break;
2013 case 0x28:
2014 /* ORNOT */
30c7183b 2015 if (likely(rc != 31)) {
dfaa8583 2016 if (ra != 31) {
30c7183b
AJ
2017 if (islit)
2018 tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
1b581c44
AJ
2019 else
2020 tcg_gen_orc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
30c7183b
AJ
2021 } else {
2022 if (islit)
2023 tcg_gen_movi_i64(cpu_ir[rc], ~lit);
2024 else
2025 tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
2026 }
2027 }
4c9649a9
JM
2028 break;
2029 case 0x40:
2030 /* XOR */
30c7183b
AJ
2031 if (likely(rc != 31)) {
2032 if (ra != 31) {
2033 if (islit)
2034 tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], lit);
30c7183b 2035 else
dfaa8583 2036 tcg_gen_xor_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
30c7183b
AJ
2037 } else {
2038 if (islit)
2039 tcg_gen_movi_i64(cpu_ir[rc], lit);
30c7183b 2040 else
dfaa8583 2041 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
30c7183b
AJ
2042 }
2043 }
4c9649a9
JM
2044 break;
2045 case 0x44:
2046 /* CMOVLT */
bbe1dab4 2047 gen_cmov(TCG_COND_LT, ra, rb, rc, islit, lit, 0);
4c9649a9
JM
2048 break;
2049 case 0x46:
2050 /* CMOVGE */
bbe1dab4 2051 gen_cmov(TCG_COND_GE, ra, rb, rc, islit, lit, 0);
4c9649a9
JM
2052 break;
2053 case 0x48:
2054 /* EQV */
30c7183b
AJ
2055 if (likely(rc != 31)) {
2056 if (ra != 31) {
2057 if (islit)
2058 tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
1b581c44
AJ
2059 else
2060 tcg_gen_eqv_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
30c7183b
AJ
2061 } else {
2062 if (islit)
2063 tcg_gen_movi_i64(cpu_ir[rc], ~lit);
30c7183b 2064 else
dfaa8583 2065 tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
30c7183b
AJ
2066 }
2067 }
4c9649a9
JM
2068 break;
2069 case 0x61:
2070 /* AMASK */
ae8ecd42 2071 if (likely(rc != 31)) {
a18ad893
RH
2072 uint64_t amask = ctx->tb->flags >> TB_FLAGS_AMASK_SHIFT;
2073
2074 if (islit) {
2075 tcg_gen_movi_i64(cpu_ir[rc], lit & ~amask);
2076 } else {
2077 tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[rb], ~amask);
1a1f7dbc 2078 }
ae8ecd42 2079 }
4c9649a9
JM
2080 break;
2081 case 0x64:
2082 /* CMOVLE */
bbe1dab4 2083 gen_cmov(TCG_COND_LE, ra, rb, rc, islit, lit, 0);
4c9649a9
JM
2084 break;
2085 case 0x66:
2086 /* CMOVGT */
bbe1dab4 2087 gen_cmov(TCG_COND_GT, ra, rb, rc, islit, lit, 0);
4c9649a9
JM
2088 break;
2089 case 0x6C:
2090 /* IMPLVER */
3761035f 2091 if (rc != 31)
8579095b 2092 tcg_gen_movi_i64(cpu_ir[rc], ctx->env->implver);
4c9649a9
JM
2093 break;
2094 default:
2095 goto invalid_opc;
2096 }
2097 break;
2098 case 0x12:
2099 switch (fn7) {
2100 case 0x02:
2101 /* MSKBL */
14ab1634 2102 gen_msk_l(ra, rb, rc, islit, lit, 0x01);
4c9649a9
JM
2103 break;
2104 case 0x06:
2105 /* EXTBL */
377a43b6 2106 gen_ext_l(ra, rb, rc, islit, lit, 0x01);
4c9649a9
JM
2107 break;
2108 case 0x0B:
2109 /* INSBL */
248c42f3 2110 gen_ins_l(ra, rb, rc, islit, lit, 0x01);
4c9649a9
JM
2111 break;
2112 case 0x12:
2113 /* MSKWL */
14ab1634 2114 gen_msk_l(ra, rb, rc, islit, lit, 0x03);
4c9649a9
JM
2115 break;
2116 case 0x16:
2117 /* EXTWL */
377a43b6 2118 gen_ext_l(ra, rb, rc, islit, lit, 0x03);
4c9649a9
JM
2119 break;
2120 case 0x1B:
2121 /* INSWL */
248c42f3 2122 gen_ins_l(ra, rb, rc, islit, lit, 0x03);
4c9649a9
JM
2123 break;
2124 case 0x22:
2125 /* MSKLL */
14ab1634 2126 gen_msk_l(ra, rb, rc, islit, lit, 0x0f);
4c9649a9
JM
2127 break;
2128 case 0x26:
2129 /* EXTLL */
377a43b6 2130 gen_ext_l(ra, rb, rc, islit, lit, 0x0f);
4c9649a9
JM
2131 break;
2132 case 0x2B:
2133 /* INSLL */
248c42f3 2134 gen_ins_l(ra, rb, rc, islit, lit, 0x0f);
4c9649a9
JM
2135 break;
2136 case 0x30:
2137 /* ZAP */
a7812ae4 2138 gen_zap(ra, rb, rc, islit, lit);
4c9649a9
JM
2139 break;
2140 case 0x31:
2141 /* ZAPNOT */
a7812ae4 2142 gen_zapnot(ra, rb, rc, islit, lit);
4c9649a9
JM
2143 break;
2144 case 0x32:
2145 /* MSKQL */
14ab1634 2146 gen_msk_l(ra, rb, rc, islit, lit, 0xff);
4c9649a9
JM
2147 break;
2148 case 0x34:
2149 /* SRL */
30c7183b
AJ
2150 if (likely(rc != 31)) {
2151 if (ra != 31) {
2152 if (islit)
2153 tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
dfaa8583 2154 else {
a7812ae4 2155 TCGv shift = tcg_temp_new();
30c7183b
AJ
2156 tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
2157 tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], shift);
2158 tcg_temp_free(shift);
dfaa8583 2159 }
30c7183b
AJ
2160 } else
2161 tcg_gen_movi_i64(cpu_ir[rc], 0);
2162 }
4c9649a9
JM
2163 break;
2164 case 0x36:
2165 /* EXTQL */
377a43b6 2166 gen_ext_l(ra, rb, rc, islit, lit, 0xff);
4c9649a9
JM
2167 break;
2168 case 0x39:
2169 /* SLL */
30c7183b
AJ
2170 if (likely(rc != 31)) {
2171 if (ra != 31) {
2172 if (islit)
2173 tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
dfaa8583 2174 else {
a7812ae4 2175 TCGv shift = tcg_temp_new();
30c7183b
AJ
2176 tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
2177 tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], shift);
2178 tcg_temp_free(shift);
dfaa8583 2179 }
30c7183b
AJ
2180 } else
2181 tcg_gen_movi_i64(cpu_ir[rc], 0);
2182 }
4c9649a9
JM
2183 break;
2184 case 0x3B:
2185 /* INSQL */
248c42f3 2186 gen_ins_l(ra, rb, rc, islit, lit, 0xff);
4c9649a9
JM
2187 break;
2188 case 0x3C:
2189 /* SRA */
30c7183b
AJ
2190 if (likely(rc != 31)) {
2191 if (ra != 31) {
2192 if (islit)
2193 tcg_gen_sari_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
dfaa8583 2194 else {
a7812ae4 2195 TCGv shift = tcg_temp_new();
30c7183b
AJ
2196 tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
2197 tcg_gen_sar_i64(cpu_ir[rc], cpu_ir[ra], shift);
2198 tcg_temp_free(shift);
dfaa8583 2199 }
30c7183b
AJ
2200 } else
2201 tcg_gen_movi_i64(cpu_ir[rc], 0);
2202 }
4c9649a9
JM
2203 break;
2204 case 0x52:
2205 /* MSKWH */
ffec44f1 2206 gen_msk_h(ra, rb, rc, islit, lit, 0x03);
4c9649a9
JM
2207 break;
2208 case 0x57:
2209 /* INSWH */
50eb6e5c 2210 gen_ins_h(ra, rb, rc, islit, lit, 0x03);
4c9649a9
JM
2211 break;
2212 case 0x5A:
2213 /* EXTWH */
377a43b6 2214 gen_ext_h(ra, rb, rc, islit, lit, 0x03);
4c9649a9
JM
2215 break;
2216 case 0x62:
2217 /* MSKLH */
ffec44f1 2218 gen_msk_h(ra, rb, rc, islit, lit, 0x0f);
4c9649a9
JM
2219 break;
2220 case 0x67:
2221 /* INSLH */
50eb6e5c 2222 gen_ins_h(ra, rb, rc, islit, lit, 0x0f);
4c9649a9
JM
2223 break;
2224 case 0x6A:
2225 /* EXTLH */
377a43b6 2226 gen_ext_h(ra, rb, rc, islit, lit, 0x0f);
4c9649a9
JM
2227 break;
2228 case 0x72:
2229 /* MSKQH */
ffec44f1 2230 gen_msk_h(ra, rb, rc, islit, lit, 0xff);
4c9649a9
JM
2231 break;
2232 case 0x77:
2233 /* INSQH */
50eb6e5c 2234 gen_ins_h(ra, rb, rc, islit, lit, 0xff);
4c9649a9
JM
2235 break;
2236 case 0x7A:
2237 /* EXTQH */
377a43b6 2238 gen_ext_h(ra, rb, rc, islit, lit, 0xff);
4c9649a9
JM
2239 break;
2240 default:
2241 goto invalid_opc;
2242 }
2243 break;
2244 case 0x13:
2245 switch (fn7) {
2246 case 0x00:
2247 /* MULL */
30c7183b 2248 if (likely(rc != 31)) {
dfaa8583 2249 if (ra == 31)
30c7183b
AJ
2250 tcg_gen_movi_i64(cpu_ir[rc], 0);
2251 else {
2252 if (islit)
2253 tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
2254 else
2255 tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2256 tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
2257 }
2258 }
4c9649a9
JM
2259 break;
2260 case 0x20:
2261 /* MULQ */
30c7183b 2262 if (likely(rc != 31)) {
dfaa8583 2263 if (ra == 31)
30c7183b
AJ
2264 tcg_gen_movi_i64(cpu_ir[rc], 0);
2265 else if (islit)
2266 tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
2267 else
2268 tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2269 }
4c9649a9
JM
2270 break;
2271 case 0x30:
2272 /* UMULH */
a7812ae4 2273 gen_umulh(ra, rb, rc, islit, lit);
4c9649a9
JM
2274 break;
2275 case 0x40:
2276 /* MULL/V */
a7812ae4 2277 gen_mullv(ra, rb, rc, islit, lit);
4c9649a9
JM
2278 break;
2279 case 0x60:
2280 /* MULQ/V */
a7812ae4 2281 gen_mulqv(ra, rb, rc, islit, lit);
4c9649a9
JM
2282 break;
2283 default:
2284 goto invalid_opc;
2285 }
2286 break;
2287 case 0x14:
f24518b5 2288 switch (fpfn) { /* fn11 & 0x3F */
4c9649a9
JM
2289 case 0x04:
2290 /* ITOFS */
a18ad893 2291 if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
4c9649a9 2292 goto invalid_opc;
a18ad893 2293 }
f18cd223
AJ
2294 if (likely(rc != 31)) {
2295 if (ra != 31) {
a7812ae4 2296 TCGv_i32 tmp = tcg_temp_new_i32();
f18cd223 2297 tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
a7812ae4
PB
2298 gen_helper_memory_to_s(cpu_fir[rc], tmp);
2299 tcg_temp_free_i32(tmp);
f18cd223
AJ
2300 } else
2301 tcg_gen_movi_i64(cpu_fir[rc], 0);
2302 }
4c9649a9
JM
2303 break;
2304 case 0x0A:
2305 /* SQRTF */
a18ad893
RH
2306 if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
2307 gen_fsqrtf(rb, rc);
2308 break;
2309 }
2310 goto invalid_opc;
4c9649a9
JM
2311 case 0x0B:
2312 /* SQRTS */
a18ad893
RH
2313 if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
2314 gen_fsqrts(ctx, rb, rc, fn11);
2315 break;
2316 }
2317 goto invalid_opc;
4c9649a9
JM
2318 case 0x14:
2319 /* ITOFF */
a18ad893 2320 if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
4c9649a9 2321 goto invalid_opc;
a18ad893 2322 }
f18cd223
AJ
2323 if (likely(rc != 31)) {
2324 if (ra != 31) {
a7812ae4 2325 TCGv_i32 tmp = tcg_temp_new_i32();
f18cd223 2326 tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
a7812ae4
PB
2327 gen_helper_memory_to_f(cpu_fir[rc], tmp);
2328 tcg_temp_free_i32(tmp);
f18cd223
AJ
2329 } else
2330 tcg_gen_movi_i64(cpu_fir[rc], 0);
2331 }
4c9649a9
JM
2332 break;
2333 case 0x24:
2334 /* ITOFT */
a18ad893 2335 if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
4c9649a9 2336 goto invalid_opc;
a18ad893 2337 }
f18cd223
AJ
2338 if (likely(rc != 31)) {
2339 if (ra != 31)
2340 tcg_gen_mov_i64(cpu_fir[rc], cpu_ir[ra]);
2341 else
2342 tcg_gen_movi_i64(cpu_fir[rc], 0);
2343 }
4c9649a9
JM
2344 break;
2345 case 0x2A:
2346 /* SQRTG */
a18ad893
RH
2347 if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
2348 gen_fsqrtg(rb, rc);
2349 break;
2350 }
2351 goto invalid_opc;
4c9649a9
JM
2352 case 0x02B:
2353 /* SQRTT */
a18ad893
RH
2354 if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
2355 gen_fsqrtt(ctx, rb, rc, fn11);
2356 break;
2357 }
2358 goto invalid_opc;
4c9649a9
JM
2359 default:
2360 goto invalid_opc;
2361 }
2362 break;
2363 case 0x15:
2364 /* VAX floating point */
2365 /* XXX: rounding mode and trap are ignored (!) */
f24518b5 2366 switch (fpfn) { /* fn11 & 0x3F */
4c9649a9
JM
2367 case 0x00:
2368 /* ADDF */
a7812ae4 2369 gen_faddf(ra, rb, rc);
4c9649a9
JM
2370 break;
2371 case 0x01:
2372 /* SUBF */
a7812ae4 2373 gen_fsubf(ra, rb, rc);
4c9649a9
JM
2374 break;
2375 case 0x02:
2376 /* MULF */
a7812ae4 2377 gen_fmulf(ra, rb, rc);
4c9649a9
JM
2378 break;
2379 case 0x03:
2380 /* DIVF */
a7812ae4 2381 gen_fdivf(ra, rb, rc);
4c9649a9
JM
2382 break;
2383 case 0x1E:
2384 /* CVTDG */
2385#if 0 // TODO
a7812ae4 2386 gen_fcvtdg(rb, rc);
4c9649a9
JM
2387#else
2388 goto invalid_opc;
2389#endif
2390 break;
2391 case 0x20:
2392 /* ADDG */
a7812ae4 2393 gen_faddg(ra, rb, rc);
4c9649a9
JM
2394 break;
2395 case 0x21:
2396 /* SUBG */
a7812ae4 2397 gen_fsubg(ra, rb, rc);
4c9649a9
JM
2398 break;
2399 case 0x22:
2400 /* MULG */
a7812ae4 2401 gen_fmulg(ra, rb, rc);
4c9649a9
JM
2402 break;
2403 case 0x23:
2404 /* DIVG */
a7812ae4 2405 gen_fdivg(ra, rb, rc);
4c9649a9
JM
2406 break;
2407 case 0x25:
2408 /* CMPGEQ */
a7812ae4 2409 gen_fcmpgeq(ra, rb, rc);
4c9649a9
JM
2410 break;
2411 case 0x26:
2412 /* CMPGLT */
a7812ae4 2413 gen_fcmpglt(ra, rb, rc);
4c9649a9
JM
2414 break;
2415 case 0x27:
2416 /* CMPGLE */
a7812ae4 2417 gen_fcmpgle(ra, rb, rc);
4c9649a9
JM
2418 break;
2419 case 0x2C:
2420 /* CVTGF */
a7812ae4 2421 gen_fcvtgf(rb, rc);
4c9649a9
JM
2422 break;
2423 case 0x2D:
2424 /* CVTGD */
2425#if 0 // TODO
a7812ae4 2426 gen_fcvtgd(rb, rc);
4c9649a9
JM
2427#else
2428 goto invalid_opc;
2429#endif
2430 break;
2431 case 0x2F:
2432 /* CVTGQ */
a7812ae4 2433 gen_fcvtgq(rb, rc);
4c9649a9
JM
2434 break;
2435 case 0x3C:
2436 /* CVTQF */
a7812ae4 2437 gen_fcvtqf(rb, rc);
4c9649a9
JM
2438 break;
2439 case 0x3E:
2440 /* CVTQG */
a7812ae4 2441 gen_fcvtqg(rb, rc);
4c9649a9
JM
2442 break;
2443 default:
2444 goto invalid_opc;
2445 }
2446 break;
2447 case 0x16:
2448 /* IEEE floating-point */
f24518b5 2449 switch (fpfn) { /* fn11 & 0x3F */
4c9649a9
JM
2450 case 0x00:
2451 /* ADDS */
f24518b5 2452 gen_fadds(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2453 break;
2454 case 0x01:
2455 /* SUBS */
f24518b5 2456 gen_fsubs(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2457 break;
2458 case 0x02:
2459 /* MULS */
f24518b5 2460 gen_fmuls(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2461 break;
2462 case 0x03:
2463 /* DIVS */
f24518b5 2464 gen_fdivs(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2465 break;
2466 case 0x20:
2467 /* ADDT */
f24518b5 2468 gen_faddt(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2469 break;
2470 case 0x21:
2471 /* SUBT */
f24518b5 2472 gen_fsubt(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2473 break;
2474 case 0x22:
2475 /* MULT */
f24518b5 2476 gen_fmult(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2477 break;
2478 case 0x23:
2479 /* DIVT */
f24518b5 2480 gen_fdivt(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2481 break;
2482 case 0x24:
2483 /* CMPTUN */
f24518b5 2484 gen_fcmptun(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2485 break;
2486 case 0x25:
2487 /* CMPTEQ */
f24518b5 2488 gen_fcmpteq(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2489 break;
2490 case 0x26:
2491 /* CMPTLT */
f24518b5 2492 gen_fcmptlt(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2493 break;
2494 case 0x27:
2495 /* CMPTLE */
f24518b5 2496 gen_fcmptle(ctx, ra, rb, rc, fn11);
4c9649a9
JM
2497 break;
2498 case 0x2C:
a74b4d2c 2499 if (fn11 == 0x2AC || fn11 == 0x6AC) {
4c9649a9 2500 /* CVTST */
f24518b5 2501 gen_fcvtst(ctx, rb, rc, fn11);
4c9649a9
JM
2502 } else {
2503 /* CVTTS */
f24518b5 2504 gen_fcvtts(ctx, rb, rc, fn11);
4c9649a9
JM
2505 }
2506 break;
2507 case 0x2F:
2508 /* CVTTQ */
f24518b5 2509 gen_fcvttq(ctx, rb, rc, fn11);
4c9649a9
JM
2510 break;
2511 case 0x3C:
2512 /* CVTQS */
f24518b5 2513 gen_fcvtqs(ctx, rb, rc, fn11);
4c9649a9
JM
2514 break;
2515 case 0x3E:
2516 /* CVTQT */
f24518b5 2517 gen_fcvtqt(ctx, rb, rc, fn11);
4c9649a9
JM
2518 break;
2519 default:
2520 goto invalid_opc;
2521 }
2522 break;
2523 case 0x17:
2524 switch (fn11) {
2525 case 0x010:
2526 /* CVTLQ */
a7812ae4 2527 gen_fcvtlq(rb, rc);
4c9649a9
JM
2528 break;
2529 case 0x020:
f18cd223 2530 if (likely(rc != 31)) {
a06d48d9 2531 if (ra == rb) {
4c9649a9 2532 /* FMOV */
a06d48d9
RH
2533 if (ra == 31)
2534 tcg_gen_movi_i64(cpu_fir[rc], 0);
2535 else
2536 tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[ra]);
2537 } else {
f18cd223 2538 /* CPYS */
a7812ae4 2539 gen_fcpys(ra, rb, rc);
a06d48d9 2540 }
4c9649a9
JM
2541 }
2542 break;
2543 case 0x021:
2544 /* CPYSN */
a7812ae4 2545 gen_fcpysn(ra, rb, rc);
4c9649a9
JM
2546 break;
2547 case 0x022:
2548 /* CPYSE */
a7812ae4 2549 gen_fcpyse(ra, rb, rc);
4c9649a9
JM
2550 break;
2551 case 0x024:
2552 /* MT_FPCR */
f18cd223 2553 if (likely(ra != 31))
a7812ae4 2554 gen_helper_store_fpcr(cpu_fir[ra]);
f18cd223
AJ
2555 else {
2556 TCGv tmp = tcg_const_i64(0);
a7812ae4 2557 gen_helper_store_fpcr(tmp);
f18cd223
AJ
2558 tcg_temp_free(tmp);
2559 }
4c9649a9
JM
2560 break;
2561 case 0x025:
2562 /* MF_FPCR */
f18cd223 2563 if (likely(ra != 31))
a7812ae4 2564 gen_helper_load_fpcr(cpu_fir[ra]);
4c9649a9
JM
2565 break;
2566 case 0x02A:
2567 /* FCMOVEQ */
bbe1dab4 2568 gen_fcmov(TCG_COND_EQ, ra, rb, rc);
4c9649a9
JM
2569 break;
2570 case 0x02B:
2571 /* FCMOVNE */
bbe1dab4 2572 gen_fcmov(TCG_COND_NE, ra, rb, rc);
4c9649a9
JM
2573 break;
2574 case 0x02C:
2575 /* FCMOVLT */
bbe1dab4 2576 gen_fcmov(TCG_COND_LT, ra, rb, rc);
4c9649a9
JM
2577 break;
2578 case 0x02D:
2579 /* FCMOVGE */
bbe1dab4 2580 gen_fcmov(TCG_COND_GE, ra, rb, rc);
4c9649a9
JM
2581 break;
2582 case 0x02E:
2583 /* FCMOVLE */
bbe1dab4 2584 gen_fcmov(TCG_COND_LE, ra, rb, rc);
4c9649a9
JM
2585 break;
2586 case 0x02F:
2587 /* FCMOVGT */
bbe1dab4 2588 gen_fcmov(TCG_COND_GT, ra, rb, rc);
4c9649a9
JM
2589 break;
2590 case 0x030:
2591 /* CVTQL */
a7812ae4 2592 gen_fcvtql(rb, rc);
4c9649a9
JM
2593 break;
2594 case 0x130:
2595 /* CVTQL/V */
4c9649a9
JM
2596 case 0x530:
2597 /* CVTQL/SV */
735cf45f
RH
2598 /* ??? I'm pretty sure there's nothing that /sv needs to do that
2599 /v doesn't do. The only thing I can think is that /sv is a
2600 valid instruction merely for completeness in the ISA. */
2601 gen_fcvtql_v(ctx, rb, rc);
4c9649a9
JM
2602 break;
2603 default:
2604 goto invalid_opc;
2605 }
2606 break;
2607 case 0x18:
2608 switch ((uint16_t)disp16) {
2609 case 0x0000:
2610 /* TRAPB */
4af70374 2611 /* No-op. */
4c9649a9
JM
2612 break;
2613 case 0x0400:
2614 /* EXCB */
4af70374 2615 /* No-op. */
4c9649a9
JM
2616 break;
2617 case 0x4000:
2618 /* MB */
2619 /* No-op */
2620 break;
2621 case 0x4400:
2622 /* WMB */
2623 /* No-op */
2624 break;
2625 case 0x8000:
2626 /* FETCH */
2627 /* No-op */
2628 break;
2629 case 0xA000:
2630 /* FETCH_M */
2631 /* No-op */
2632 break;
2633 case 0xC000:
2634 /* RPCC */
3761035f 2635 if (ra != 31)
a7812ae4 2636 gen_helper_load_pcc(cpu_ir[ra]);
4c9649a9
JM
2637 break;
2638 case 0xE000:
2639 /* RC */
ac316ca4 2640 gen_rx(ra, 0);
4c9649a9
JM
2641 break;
2642 case 0xE800:
2643 /* ECB */
4c9649a9
JM
2644 break;
2645 case 0xF000:
2646 /* RS */
ac316ca4 2647 gen_rx(ra, 1);
4c9649a9
JM
2648 break;
2649 case 0xF800:
2650 /* WH64 */
2651 /* No-op */
2652 break;
2653 default:
2654 goto invalid_opc;
2655 }
2656 break;
2657 case 0x19:
2658 /* HW_MFPR (PALcode) */
26b46094 2659#ifndef CONFIG_USER_ONLY
a18ad893 2660 if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
26b46094
RH
2661 gen_mfpr(ra, insn & 0xffff);
2662 break;
2663 }
2664#endif
4c9649a9 2665 goto invalid_opc;
4c9649a9 2666 case 0x1A:
49563a72
RH
2667 /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
2668 prediction stack action, which of course we don't implement. */
2669 if (rb != 31) {
3761035f 2670 tcg_gen_andi_i64(cpu_pc, cpu_ir[rb], ~3);
49563a72 2671 } else {
3761035f 2672 tcg_gen_movi_i64(cpu_pc, 0);
49563a72
RH
2673 }
2674 if (ra != 31) {
1304ca87 2675 tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
49563a72 2676 }
4af70374 2677 ret = EXIT_PC_UPDATED;
4c9649a9
JM
2678 break;
2679 case 0x1B:
2680 /* HW_LD (PALcode) */
a18ad893
RH
2681#ifndef CONFIG_USER_ONLY
2682 if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
2683 TCGv addr;
2684
2685 if (ra == 31) {
2686 break;
2687 }
2688
2689 addr = tcg_temp_new();
8bb6e981
AJ
2690 if (rb != 31)
2691 tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
2692 else
2693 tcg_gen_movi_i64(addr, disp12);
2694 switch ((insn >> 12) & 0xF) {
2695 case 0x0:
b5d51029 2696 /* Longword physical access (hw_ldl/p) */
2374e73e 2697 gen_helper_ldl_phys(cpu_ir[ra], addr);
8bb6e981
AJ
2698 break;
2699 case 0x1:
b5d51029 2700 /* Quadword physical access (hw_ldq/p) */
2374e73e 2701 gen_helper_ldq_phys(cpu_ir[ra], addr);
8bb6e981
AJ
2702 break;
2703 case 0x2:
b5d51029 2704 /* Longword physical access with lock (hw_ldl_l/p) */
2374e73e 2705 gen_helper_ldl_l_phys(cpu_ir[ra], addr);
8bb6e981
AJ
2706 break;
2707 case 0x3:
b5d51029 2708 /* Quadword physical access with lock (hw_ldq_l/p) */
2374e73e 2709 gen_helper_ldq_l_phys(cpu_ir[ra], addr);
8bb6e981
AJ
2710 break;
2711 case 0x4:
b5d51029 2712 /* Longword virtual PTE fetch (hw_ldl/v) */
2374e73e 2713 goto invalid_opc;
8bb6e981 2714 case 0x5:
b5d51029 2715 /* Quadword virtual PTE fetch (hw_ldq/v) */
2374e73e 2716 goto invalid_opc;
8bb6e981
AJ
2717 break;
2718 case 0x6:
2719 /* Incpu_ir[ra]id */
b5d51029 2720 goto invalid_opc;
8bb6e981
AJ
2721 case 0x7:
2722 /* Incpu_ir[ra]id */
b5d51029 2723 goto invalid_opc;
8bb6e981 2724 case 0x8:
b5d51029 2725 /* Longword virtual access (hw_ldl) */
2374e73e 2726 goto invalid_opc;
8bb6e981 2727 case 0x9:
b5d51029 2728 /* Quadword virtual access (hw_ldq) */
2374e73e 2729 goto invalid_opc;
8bb6e981 2730 case 0xA:
b5d51029 2731 /* Longword virtual access with protection check (hw_ldl/w) */
8417845e 2732 tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_KERNEL_IDX);
8bb6e981
AJ
2733 break;
2734 case 0xB:
b5d51029 2735 /* Quadword virtual access with protection check (hw_ldq/w) */
8417845e 2736 tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_KERNEL_IDX);
8bb6e981
AJ
2737 break;
2738 case 0xC:
b5d51029 2739 /* Longword virtual access with alt access mode (hw_ldl/a)*/
2374e73e 2740 goto invalid_opc;
8bb6e981 2741 case 0xD:
b5d51029 2742 /* Quadword virtual access with alt access mode (hw_ldq/a) */
2374e73e 2743 goto invalid_opc;
8bb6e981
AJ
2744 case 0xE:
2745 /* Longword virtual access with alternate access mode and
2374e73e
RH
2746 protection checks (hw_ldl/wa) */
2747 tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_USER_IDX);
8bb6e981
AJ
2748 break;
2749 case 0xF:
2750 /* Quadword virtual access with alternate access mode and
2374e73e
RH
2751 protection checks (hw_ldq/wa) */
2752 tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_USER_IDX);
8bb6e981
AJ
2753 break;
2754 }
2755 tcg_temp_free(addr);
a18ad893 2756 break;
4c9649a9 2757 }
4c9649a9 2758#endif
a18ad893 2759 goto invalid_opc;
4c9649a9
JM
2760 case 0x1C:
2761 switch (fn7) {
2762 case 0x00:
2763 /* SEXTB */
a18ad893 2764 if ((ctx->tb->flags & TB_FLAGS_AMASK_BWX) == 0) {
4c9649a9 2765 goto invalid_opc;
a18ad893 2766 }
ae8ecd42
AJ
2767 if (likely(rc != 31)) {
2768 if (islit)
2769 tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int8_t)lit));
ae8ecd42 2770 else
dfaa8583 2771 tcg_gen_ext8s_i64(cpu_ir[rc], cpu_ir[rb]);
ae8ecd42 2772 }
4c9649a9
JM
2773 break;
2774 case 0x01:
2775 /* SEXTW */
a18ad893
RH
2776 if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
2777 if (likely(rc != 31)) {
2778 if (islit) {
2779 tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int16_t)lit));
2780 } else {
2781 tcg_gen_ext16s_i64(cpu_ir[rc], cpu_ir[rb]);
2782 }
2783 }
2784 break;
ae8ecd42 2785 }
a18ad893 2786 goto invalid_opc;
4c9649a9
JM
2787 case 0x30:
2788 /* CTPOP */
a18ad893
RH
2789 if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
2790 if (likely(rc != 31)) {
2791 if (islit) {
2792 tcg_gen_movi_i64(cpu_ir[rc], ctpop64(lit));
2793 } else {
2794 gen_helper_ctpop(cpu_ir[rc], cpu_ir[rb]);
2795 }
2796 }
2797 break;
ae8ecd42 2798 }
a18ad893 2799 goto invalid_opc;
4c9649a9
JM
2800 case 0x31:
2801 /* PERR */
a18ad893
RH
2802 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2803 gen_perr(ra, rb, rc, islit, lit);
2804 break;
2805 }
2806 goto invalid_opc;
4c9649a9
JM
2807 case 0x32:
2808 /* CTLZ */
a18ad893
RH
2809 if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
2810 if (likely(rc != 31)) {
2811 if (islit) {
2812 tcg_gen_movi_i64(cpu_ir[rc], clz64(lit));
2813 } else {
2814 gen_helper_ctlz(cpu_ir[rc], cpu_ir[rb]);
2815 }
2816 }
2817 break;
ae8ecd42 2818 }
a18ad893 2819 goto invalid_opc;
4c9649a9
JM
2820 case 0x33:
2821 /* CTTZ */
a18ad893
RH
2822 if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
2823 if (likely(rc != 31)) {
2824 if (islit) {
2825 tcg_gen_movi_i64(cpu_ir[rc], ctz64(lit));
2826 } else {
2827 gen_helper_cttz(cpu_ir[rc], cpu_ir[rb]);
2828 }
2829 }
2830 break;
ae8ecd42 2831 }
a18ad893 2832 goto invalid_opc;
4c9649a9
JM
2833 case 0x34:
2834 /* UNPKBW */
a18ad893
RH
2835 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2836 if (real_islit || ra != 31) {
2837 goto invalid_opc;
2838 }
2839 gen_unpkbw(rb, rc);
2840 break;
2841 }
2842 goto invalid_opc;
4c9649a9 2843 case 0x35:
13e4df99 2844 /* UNPKBL */
a18ad893
RH
2845 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2846 if (real_islit || ra != 31) {
2847 goto invalid_opc;
2848 }
2849 gen_unpkbl(rb, rc);
2850 break;
2851 }
2852 goto invalid_opc;
4c9649a9
JM
2853 case 0x36:
2854 /* PKWB */
a18ad893
RH
2855 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2856 if (real_islit || ra != 31) {
2857 goto invalid_opc;
2858 }
2859 gen_pkwb(rb, rc);
2860 break;
2861 }
2862 goto invalid_opc;
4c9649a9
JM
2863 case 0x37:
2864 /* PKLB */
a18ad893
RH
2865 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2866 if (real_islit || ra != 31) {
2867 goto invalid_opc;
2868 }
2869 gen_pklb(rb, rc);
2870 break;
2871 }
2872 goto invalid_opc;
4c9649a9
JM
2873 case 0x38:
2874 /* MINSB8 */
a18ad893
RH
2875 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2876 gen_minsb8(ra, rb, rc, islit, lit);
2877 break;
2878 }
2879 goto invalid_opc;
4c9649a9
JM
2880 case 0x39:
2881 /* MINSW4 */
a18ad893
RH
2882 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2883 gen_minsw4(ra, rb, rc, islit, lit);
2884 break;
2885 }
2886 goto invalid_opc;
4c9649a9
JM
2887 case 0x3A:
2888 /* MINUB8 */
a18ad893
RH
2889 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2890 gen_minub8(ra, rb, rc, islit, lit);
2891 break;
2892 }
2893 goto invalid_opc;
4c9649a9
JM
2894 case 0x3B:
2895 /* MINUW4 */
a18ad893
RH
2896 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2897 gen_minuw4(ra, rb, rc, islit, lit);
2898 break;
2899 }
2900 goto invalid_opc;
4c9649a9
JM
2901 case 0x3C:
2902 /* MAXUB8 */
a18ad893
RH
2903 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2904 gen_maxub8(ra, rb, rc, islit, lit);
2905 break;
2906 }
2907 goto invalid_opc;
4c9649a9
JM
2908 case 0x3D:
2909 /* MAXUW4 */
a18ad893
RH
2910 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2911 gen_maxuw4(ra, rb, rc, islit, lit);
2912 break;
2913 }
2914 goto invalid_opc;
4c9649a9
JM
2915 case 0x3E:
2916 /* MAXSB8 */
a18ad893
RH
2917 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2918 gen_maxsb8(ra, rb, rc, islit, lit);
2919 break;
2920 }
2921 goto invalid_opc;
4c9649a9
JM
2922 case 0x3F:
2923 /* MAXSW4 */
a18ad893
RH
2924 if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
2925 gen_maxsw4(ra, rb, rc, islit, lit);
2926 break;
2927 }
2928 goto invalid_opc;
4c9649a9
JM
2929 case 0x70:
2930 /* FTOIT */
a18ad893 2931 if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
4c9649a9 2932 goto invalid_opc;
a18ad893 2933 }
f18cd223
AJ
2934 if (likely(rc != 31)) {
2935 if (ra != 31)
2936 tcg_gen_mov_i64(cpu_ir[rc], cpu_fir[ra]);
2937 else
2938 tcg_gen_movi_i64(cpu_ir[rc], 0);
2939 }
4c9649a9
JM
2940 break;
2941 case 0x78:
2942 /* FTOIS */
a18ad893 2943 if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
4c9649a9 2944 goto invalid_opc;
a18ad893 2945 }
f18cd223 2946 if (rc != 31) {
a7812ae4 2947 TCGv_i32 tmp1 = tcg_temp_new_i32();
f18cd223 2948 if (ra != 31)
a7812ae4 2949 gen_helper_s_to_memory(tmp1, cpu_fir[ra]);
f18cd223
AJ
2950 else {
2951 TCGv tmp2 = tcg_const_i64(0);
a7812ae4 2952 gen_helper_s_to_memory(tmp1, tmp2);
f18cd223
AJ
2953 tcg_temp_free(tmp2);
2954 }
2955 tcg_gen_ext_i32_i64(cpu_ir[rc], tmp1);
a7812ae4 2956 tcg_temp_free_i32(tmp1);
f18cd223 2957 }
4c9649a9
JM
2958 break;
2959 default:
2960 goto invalid_opc;
2961 }
2962 break;
2963 case 0x1D:
2964 /* HW_MTPR (PALcode) */
26b46094 2965#ifndef CONFIG_USER_ONLY
a18ad893
RH
2966 if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
2967 gen_mtpr(rb, insn & 0xffff);
26b46094
RH
2968 break;
2969 }
2970#endif
4c9649a9 2971 goto invalid_opc;
4c9649a9 2972 case 0x1E:
508b43ea 2973 /* HW_RET (PALcode) */
a18ad893
RH
2974#ifndef CONFIG_USER_ONLY
2975 if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
2976 if (rb == 31) {
2977 /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
2978 address from EXC_ADDR. This turns out to be useful for our
2979 emulation PALcode, so continue to accept it. */
2980 TCGv tmp = tcg_temp_new();
2981 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUState, exc_addr));
2982 gen_helper_hw_ret(tmp);
2983 tcg_temp_free(tmp);
2984 } else {
2985 gen_helper_hw_ret(cpu_ir[rb]);
2986 }
2987 ret = EXIT_PC_UPDATED;
2988 break;
4c9649a9 2989 }
4c9649a9 2990#endif
a18ad893 2991 goto invalid_opc;
4c9649a9
JM
2992 case 0x1F:
2993 /* HW_ST (PALcode) */
a18ad893
RH
2994#ifndef CONFIG_USER_ONLY
2995 if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
8bb6e981 2996 TCGv addr, val;
a7812ae4 2997 addr = tcg_temp_new();
8bb6e981
AJ
2998 if (rb != 31)
2999 tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
3000 else
3001 tcg_gen_movi_i64(addr, disp12);
3002 if (ra != 31)
3003 val = cpu_ir[ra];
3004 else {
a7812ae4 3005 val = tcg_temp_new();
8bb6e981
AJ
3006 tcg_gen_movi_i64(val, 0);
3007 }
3008 switch ((insn >> 12) & 0xF) {
3009 case 0x0:
3010 /* Longword physical access */
2374e73e 3011 gen_helper_stl_phys(addr, val);
8bb6e981
AJ
3012 break;
3013 case 0x1:
3014 /* Quadword physical access */
2374e73e 3015 gen_helper_stq_phys(addr, val);
8bb6e981
AJ
3016 break;
3017 case 0x2:
3018 /* Longword physical access with lock */
2374e73e 3019 gen_helper_stl_c_phys(val, addr, val);
8bb6e981
AJ
3020 break;
3021 case 0x3:
3022 /* Quadword physical access with lock */
2374e73e 3023 gen_helper_stq_c_phys(val, addr, val);
8bb6e981
AJ
3024 break;
3025 case 0x4:
3026 /* Longword virtual access */
2374e73e 3027 goto invalid_opc;
8bb6e981
AJ
3028 case 0x5:
3029 /* Quadword virtual access */
2374e73e 3030 goto invalid_opc;
8bb6e981
AJ
3031 case 0x6:
3032 /* Invalid */
3033 goto invalid_opc;
3034 case 0x7:
3035 /* Invalid */
3036 goto invalid_opc;
3037 case 0x8:
3038 /* Invalid */
3039 goto invalid_opc;
3040 case 0x9:
3041 /* Invalid */
3042 goto invalid_opc;
3043 case 0xA:
3044 /* Invalid */
3045 goto invalid_opc;
3046 case 0xB:
3047 /* Invalid */
3048 goto invalid_opc;
3049 case 0xC:
3050 /* Longword virtual access with alternate access mode */
2374e73e 3051 goto invalid_opc;
8bb6e981
AJ
3052 case 0xD:
3053 /* Quadword virtual access with alternate access mode */
2374e73e 3054 goto invalid_opc;
8bb6e981
AJ
3055 case 0xE:
3056 /* Invalid */
3057 goto invalid_opc;
3058 case 0xF:
3059 /* Invalid */
3060 goto invalid_opc;
3061 }
45d46ce8 3062 if (ra == 31)
8bb6e981
AJ
3063 tcg_temp_free(val);
3064 tcg_temp_free(addr);
a18ad893 3065 break;
4c9649a9 3066 }
4c9649a9 3067#endif
a18ad893 3068 goto invalid_opc;
4c9649a9
JM
3069 case 0x20:
3070 /* LDF */
f18cd223 3071 gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
4c9649a9
JM
3072 break;
3073 case 0x21:
3074 /* LDG */
f18cd223 3075 gen_load_mem(ctx, &gen_qemu_ldg, ra, rb, disp16, 1, 0);
4c9649a9
JM
3076 break;
3077 case 0x22:
3078 /* LDS */
f18cd223 3079 gen_load_mem(ctx, &gen_qemu_lds, ra, rb, disp16, 1, 0);
4c9649a9
JM
3080 break;
3081 case 0x23:
3082 /* LDT */
f18cd223 3083 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 1, 0);
4c9649a9
JM
3084 break;
3085 case 0x24:
3086 /* STF */
6910b8f6 3087 gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0);
4c9649a9
JM
3088 break;
3089 case 0x25:
3090 /* STG */
6910b8f6 3091 gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0);
4c9649a9
JM
3092 break;
3093 case 0x26:
3094 /* STS */
6910b8f6 3095 gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0);
4c9649a9
JM
3096 break;
3097 case 0x27:
3098 /* STT */
6910b8f6 3099 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0);
4c9649a9
JM
3100 break;
3101 case 0x28:
3102 /* LDL */
f18cd223 3103 gen_load_mem(ctx, &tcg_gen_qemu_ld32s, ra, rb, disp16, 0, 0);
4c9649a9
JM
3104 break;
3105 case 0x29:
3106 /* LDQ */
f18cd223 3107 gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 0);
4c9649a9
JM
3108 break;
3109 case 0x2A:
3110 /* LDL_L */
f4ed8679 3111 gen_load_mem(ctx, &gen_qemu_ldl_l, ra, rb, disp16, 0, 0);
4c9649a9
JM
3112 break;
3113 case 0x2B:
3114 /* LDQ_L */
f4ed8679 3115 gen_load_mem(ctx, &gen_qemu_ldq_l, ra, rb, disp16, 0, 0);
4c9649a9
JM
3116 break;
3117 case 0x2C:
3118 /* STL */
6910b8f6 3119 gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0);
4c9649a9
JM
3120 break;
3121 case 0x2D:
3122 /* STQ */
6910b8f6 3123 gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0);
4c9649a9
JM
3124 break;
3125 case 0x2E:
3126 /* STL_C */
6910b8f6 3127 ret = gen_store_conditional(ctx, ra, rb, disp16, 0);
4c9649a9
JM
3128 break;
3129 case 0x2F:
3130 /* STQ_C */
6910b8f6 3131 ret = gen_store_conditional(ctx, ra, rb, disp16, 1);
4c9649a9
JM
3132 break;
3133 case 0x30:
3134 /* BR */
4af70374 3135 ret = gen_bdirect(ctx, ra, disp21);
4c9649a9 3136 break;
a7812ae4 3137 case 0x31: /* FBEQ */
4af70374 3138 ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
dbb30fe6 3139 break;
a7812ae4 3140 case 0x32: /* FBLT */
4af70374 3141 ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
dbb30fe6 3142 break;
a7812ae4 3143 case 0x33: /* FBLE */
4af70374 3144 ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
4c9649a9
JM
3145 break;
3146 case 0x34:
3147 /* BSR */
4af70374 3148 ret = gen_bdirect(ctx, ra, disp21);
4c9649a9 3149 break;
a7812ae4 3150 case 0x35: /* FBNE */
4af70374 3151 ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
dbb30fe6 3152 break;
a7812ae4 3153 case 0x36: /* FBGE */
4af70374 3154 ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
dbb30fe6 3155 break;
a7812ae4 3156 case 0x37: /* FBGT */
4af70374 3157 ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
4c9649a9
JM
3158 break;
3159 case 0x38:
3160 /* BLBC */
4af70374 3161 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
4c9649a9
JM
3162 break;
3163 case 0x39:
3164 /* BEQ */
4af70374 3165 ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
4c9649a9
JM
3166 break;
3167 case 0x3A:
3168 /* BLT */
4af70374 3169 ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
4c9649a9
JM
3170 break;
3171 case 0x3B:
3172 /* BLE */
4af70374 3173 ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
4c9649a9
JM
3174 break;
3175 case 0x3C:
3176 /* BLBS */
4af70374 3177 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
4c9649a9
JM
3178 break;
3179 case 0x3D:
3180 /* BNE */
4af70374 3181 ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
4c9649a9
JM
3182 break;
3183 case 0x3E:
3184 /* BGE */
4af70374 3185 ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
4c9649a9
JM
3186 break;
3187 case 0x3F:
3188 /* BGT */
4af70374 3189 ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
4c9649a9
JM
3190 break;
3191 invalid_opc:
8aa3fa20 3192 ret = gen_invalid(ctx);
4c9649a9
JM
3193 break;
3194 }
3195
3196 return ret;
3197}
3198
636aa200
BS
3199static inline void gen_intermediate_code_internal(CPUState *env,
3200 TranslationBlock *tb,
3201 int search_pc)
4c9649a9 3202{
4c9649a9
JM
3203 DisasContext ctx, *ctxp = &ctx;
3204 target_ulong pc_start;
3205 uint32_t insn;
3206 uint16_t *gen_opc_end;
a1d1bb31 3207 CPUBreakpoint *bp;
4c9649a9 3208 int j, lj = -1;
4af70374 3209 ExitStatus ret;
2e70f6ef
PB
3210 int num_insns;
3211 int max_insns;
4c9649a9
JM
3212
3213 pc_start = tb->pc;
4c9649a9 3214 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4af70374
RH
3215
3216 ctx.tb = tb;
3217 ctx.env = env;
4c9649a9 3218 ctx.pc = pc_start;
bba9bdce 3219 ctx.mem_idx = cpu_mmu_index(env);
f24518b5
RH
3220
3221 /* ??? Every TB begins with unset rounding mode, to be initialized on
3222 the first fp insn of the TB. Alternately we could define a proper
3223 default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure
3224 to reset the FP_STATUS to that default at the end of any TB that
3225 changes the default. We could even (gasp) dynamiclly figure out
3226 what default would be most efficient given the running program. */
3227 ctx.tb_rm = -1;
3228 /* Similarly for flush-to-zero. */
3229 ctx.tb_ftz = -1;
3230
2e70f6ef
PB
3231 num_insns = 0;
3232 max_insns = tb->cflags & CF_COUNT_MASK;
3233 if (max_insns == 0)
3234 max_insns = CF_COUNT_MASK;
3235
3236 gen_icount_start();
4af70374 3237 do {
72cf2d4f
BS
3238 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
3239 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 3240 if (bp->pc == ctx.pc) {
4c9649a9
JM
3241 gen_excp(&ctx, EXCP_DEBUG, 0);
3242 break;
3243 }
3244 }
3245 }
3246 if (search_pc) {
3247 j = gen_opc_ptr - gen_opc_buf;
3248 if (lj < j) {
3249 lj++;
3250 while (lj < j)
3251 gen_opc_instr_start[lj++] = 0;
4c9649a9 3252 }
ed1dda53
AJ
3253 gen_opc_pc[lj] = ctx.pc;
3254 gen_opc_instr_start[lj] = 1;
3255 gen_opc_icount[lj] = num_insns;
4c9649a9 3256 }
2e70f6ef
PB
3257 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
3258 gen_io_start();
4c9649a9 3259 insn = ldl_code(ctx.pc);
2e70f6ef 3260 num_insns++;
c4b3be39
RH
3261
3262 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
3263 tcg_gen_debug_insn_start(ctx.pc);
3264 }
3265
4c9649a9
JM
3266 ctx.pc += 4;
3267 ret = translate_one(ctxp, insn);
19bf517b 3268
bf1b03fe
RH
3269 /* If we reach a page boundary, are single stepping,
3270 or exhaust instruction count, stop generation. */
3271 if (ret == NO_EXIT
3272 && ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
3273 || gen_opc_ptr >= gen_opc_end
3274 || num_insns >= max_insns
3275 || singlestep
3276 || env->singlestep_enabled)) {
3277 ret = EXIT_PC_STALE;
1b530a6d 3278 }
4af70374
RH
3279 } while (ret == NO_EXIT);
3280
3281 if (tb->cflags & CF_LAST_IO) {
3282 gen_io_end();
4c9649a9 3283 }
4af70374
RH
3284
3285 switch (ret) {
3286 case EXIT_GOTO_TB:
8aa3fa20 3287 case EXIT_NORETURN:
4af70374
RH
3288 break;
3289 case EXIT_PC_STALE:
496cb5b9 3290 tcg_gen_movi_i64(cpu_pc, ctx.pc);
4af70374
RH
3291 /* FALLTHRU */
3292 case EXIT_PC_UPDATED:
bf1b03fe
RH
3293 if (env->singlestep_enabled) {
3294 gen_excp_1(EXCP_DEBUG, 0);
3295 } else {
3296 tcg_gen_exit_tb(0);
3297 }
4af70374
RH
3298 break;
3299 default:
3300 abort();
4c9649a9 3301 }
4af70374 3302
2e70f6ef 3303 gen_icount_end(tb, num_insns);
4c9649a9
JM
3304 *gen_opc_ptr = INDEX_op_end;
3305 if (search_pc) {
3306 j = gen_opc_ptr - gen_opc_buf;
3307 lj++;
3308 while (lj <= j)
3309 gen_opc_instr_start[lj++] = 0;
4c9649a9
JM
3310 } else {
3311 tb->size = ctx.pc - pc_start;
2e70f6ef 3312 tb->icount = num_insns;
4c9649a9 3313 }
4af70374 3314
806991da 3315#ifdef DEBUG_DISAS
8fec2b8c 3316 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
3317 qemu_log("IN: %s\n", lookup_symbol(pc_start));
3318 log_target_disas(pc_start, ctx.pc - pc_start, 1);
3319 qemu_log("\n");
4c9649a9 3320 }
4c9649a9 3321#endif
4c9649a9
JM
3322}
3323
2cfc5f17 3324void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
4c9649a9 3325{
2cfc5f17 3326 gen_intermediate_code_internal(env, tb, 0);
4c9649a9
JM
3327}
3328
2cfc5f17 3329void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
4c9649a9 3330{
2cfc5f17 3331 gen_intermediate_code_internal(env, tb, 1);
4c9649a9
JM
3332}
3333
a964acc6
RH
3334struct cpu_def_t {
3335 const char *name;
3336 int implver, amask;
3337};
3338
3339static const struct cpu_def_t cpu_defs[] = {
3340 { "ev4", IMPLVER_2106x, 0 },
3341 { "ev5", IMPLVER_21164, 0 },
3342 { "ev56", IMPLVER_21164, AMASK_BWX },
3343 { "pca56", IMPLVER_21164, AMASK_BWX | AMASK_MVI },
3344 { "ev6", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP },
3345 { "ev67", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
3346 | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), },
3347 { "ev68", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
3348 | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), },
3349 { "21064", IMPLVER_2106x, 0 },
3350 { "21164", IMPLVER_21164, 0 },
3351 { "21164a", IMPLVER_21164, AMASK_BWX },
3352 { "21164pc", IMPLVER_21164, AMASK_BWX | AMASK_MVI },
3353 { "21264", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP },
3354 { "21264a", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
3355 | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), }
3356};
3357
aaed909a 3358CPUAlphaState * cpu_alpha_init (const char *cpu_model)
4c9649a9
JM
3359{
3360 CPUAlphaState *env;
a964acc6 3361 int implver, amask, i, max;
4c9649a9
JM
3362
3363 env = qemu_mallocz(sizeof(CPUAlphaState));
4c9649a9 3364 cpu_exec_init(env);
2e70f6ef 3365 alpha_translate_init();
4c9649a9 3366 tlb_flush(env, 1);
a964acc6
RH
3367
3368 /* Default to ev67; no reason not to emulate insns by default. */
3369 implver = IMPLVER_21264;
3370 amask = (AMASK_BWX | AMASK_FIX | AMASK_CIX | AMASK_MVI
3371 | AMASK_TRAP | AMASK_PREFETCH);
3372
3373 max = ARRAY_SIZE(cpu_defs);
3374 for (i = 0; i < max; i++) {
3375 if (strcmp (cpu_model, cpu_defs[i].name) == 0) {
3376 implver = cpu_defs[i].implver;
3377 amask = cpu_defs[i].amask;
3378 break;
3379 }
3380 }
3381 env->implver = implver;
3382 env->amask = amask;
3383
4c9649a9 3384#if defined (CONFIG_USER_ONLY)
ea879fc7 3385 env->ps = PS_USER_MODE;
2edd07ef
RH
3386 cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
3387 | FPCR_UNFD | FPCR_INED | FPCR_DNOD));
6049f4f8 3388#endif
6910b8f6 3389 env->lock_addr = -1;
26b46094 3390 env->fen = 1;
dad081ee 3391
0bf46a40 3392 qemu_init_vcpu(env);
4c9649a9
JM
3393 return env;
3394}
aaed909a 3395
e87b7cb0 3396void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
d2856f1a
AJ
3397{
3398 env->pc = gen_opc_pc[pc_pos];
3399}