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