]> git.proxmox.com Git - qemu.git/blame - target-s390x/translate.c
target-s390: Send signals for divide
[qemu.git] / target-s390x / translate.c
CommitLineData
10ec5117
AG
1/*
2 * S/390 translation
3 *
4 * Copyright (c) 2009 Ulrich Hecht
e023e832 5 * Copyright (c) 2010 Alexander Graf
10ec5117
AG
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
70539e18 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
10ec5117 19 */
e023e832 20
e023e832
AG
21/* #define DEBUG_INLINE_BRANCHES */
22#define S390X_DEBUG_DISAS
23/* #define S390X_DEBUG_DISAS_VERBOSE */
24
25#ifdef S390X_DEBUG_DISAS_VERBOSE
26# define LOG_DISAS(...) qemu_log(__VA_ARGS__)
27#else
28# define LOG_DISAS(...) do { } while (0)
29#endif
10ec5117
AG
30
31#include "cpu.h"
76cad711 32#include "disas/disas.h"
10ec5117 33#include "tcg-op.h"
1de7afc9 34#include "qemu/log.h"
10ec5117 35
e023e832
AG
36/* global register indexes */
37static TCGv_ptr cpu_env;
38
022c62cb 39#include "exec/gen-icount.h"
3208afbe 40#include "helper.h"
e023e832 41#define GEN_HELPER 1
3208afbe 42#include "helper.h"
e023e832 43
ad044d09
RH
44
45/* Information that (most) every instruction needs to manipulate. */
e023e832 46typedef struct DisasContext DisasContext;
ad044d09
RH
47typedef struct DisasInsn DisasInsn;
48typedef struct DisasFields DisasFields;
49
e023e832 50struct DisasContext {
e023e832 51 struct TranslationBlock *tb;
ad044d09
RH
52 const DisasInsn *insn;
53 DisasFields *fields;
54 uint64_t pc, next_pc;
55 enum cc_op cc_op;
56 bool singlestep_enabled;
57 int is_jmp;
e023e832
AG
58};
59
3fde06f5
RH
60/* Information carried about a condition to be evaluated. */
61typedef struct {
62 TCGCond cond:8;
63 bool is_64;
64 bool g1;
65 bool g2;
66 union {
67 struct { TCGv_i64 a, b; } s64;
68 struct { TCGv_i32 a, b; } s32;
69 } u;
70} DisasCompare;
71
e023e832
AG
72#define DISAS_EXCP 4
73
74static void gen_op_calc_cc(DisasContext *s);
75
76#ifdef DEBUG_INLINE_BRANCHES
77static uint64_t inline_branch_hit[CC_OP_MAX];
78static uint64_t inline_branch_miss[CC_OP_MAX];
79#endif
80
81static inline void debug_insn(uint64_t insn)
82{
83 LOG_DISAS("insn: 0x%" PRIx64 "\n", insn);
84}
85
86static inline uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
87{
88 if (!(s->tb->flags & FLAG_MASK_64)) {
89 if (s->tb->flags & FLAG_MASK_32) {
90 return pc | 0x80000000;
91 }
92 }
93 return pc;
94}
95
a4e3ad19 96void cpu_dump_state(CPUS390XState *env, FILE *f, fprintf_function cpu_fprintf,
10ec5117
AG
97 int flags)
98{
99 int i;
e023e832 100
d885bdd4
RH
101 if (env->cc_op > 3) {
102 cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %15s\n",
103 env->psw.mask, env->psw.addr, cc_name(env->cc_op));
104 } else {
105 cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %02x\n",
106 env->psw.mask, env->psw.addr, env->cc_op);
107 }
108
10ec5117 109 for (i = 0; i < 16; i++) {
e023e832 110 cpu_fprintf(f, "R%02d=%016" PRIx64, i, env->regs[i]);
10ec5117
AG
111 if ((i % 4) == 3) {
112 cpu_fprintf(f, "\n");
113 } else {
114 cpu_fprintf(f, " ");
115 }
116 }
e023e832 117
10ec5117 118 for (i = 0; i < 16; i++) {
431253c2 119 cpu_fprintf(f, "F%02d=%016" PRIx64, i, env->fregs[i].ll);
10ec5117
AG
120 if ((i % 4) == 3) {
121 cpu_fprintf(f, "\n");
122 } else {
123 cpu_fprintf(f, " ");
124 }
125 }
e023e832 126
e023e832
AG
127#ifndef CONFIG_USER_ONLY
128 for (i = 0; i < 16; i++) {
129 cpu_fprintf(f, "C%02d=%016" PRIx64, i, env->cregs[i]);
130 if ((i % 4) == 3) {
131 cpu_fprintf(f, "\n");
132 } else {
133 cpu_fprintf(f, " ");
134 }
135 }
136#endif
137
e023e832
AG
138#ifdef DEBUG_INLINE_BRANCHES
139 for (i = 0; i < CC_OP_MAX; i++) {
140 cpu_fprintf(f, " %15s = %10ld\t%10ld\n", cc_name(i),
141 inline_branch_miss[i], inline_branch_hit[i]);
142 }
143#endif
d885bdd4
RH
144
145 cpu_fprintf(f, "\n");
10ec5117
AG
146}
147
e023e832
AG
148static TCGv_i64 psw_addr;
149static TCGv_i64 psw_mask;
150
151static TCGv_i32 cc_op;
152static TCGv_i64 cc_src;
153static TCGv_i64 cc_dst;
154static TCGv_i64 cc_vr;
155
431253c2 156static char cpu_reg_names[32][4];
e023e832 157static TCGv_i64 regs[16];
431253c2 158static TCGv_i64 fregs[16];
e023e832
AG
159
160static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
161
d5a43964
AG
162void s390x_translate_init(void)
163{
e023e832 164 int i;
e023e832
AG
165
166 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
431253c2
RH
167 psw_addr = tcg_global_mem_new_i64(TCG_AREG0,
168 offsetof(CPUS390XState, psw.addr),
e023e832 169 "psw_addr");
431253c2
RH
170 psw_mask = tcg_global_mem_new_i64(TCG_AREG0,
171 offsetof(CPUS390XState, psw.mask),
e023e832
AG
172 "psw_mask");
173
a4e3ad19 174 cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUS390XState, cc_op),
e023e832 175 "cc_op");
a4e3ad19 176 cc_src = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_src),
e023e832 177 "cc_src");
a4e3ad19 178 cc_dst = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_dst),
e023e832 179 "cc_dst");
a4e3ad19 180 cc_vr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_vr),
e023e832
AG
181 "cc_vr");
182
e023e832 183 for (i = 0; i < 16; i++) {
431253c2 184 snprintf(cpu_reg_names[i], sizeof(cpu_reg_names[0]), "r%d", i);
e023e832 185 regs[i] = tcg_global_mem_new(TCG_AREG0,
431253c2
RH
186 offsetof(CPUS390XState, regs[i]),
187 cpu_reg_names[i]);
188 }
189
190 for (i = 0; i < 16; i++) {
191 snprintf(cpu_reg_names[i + 16], sizeof(cpu_reg_names[0]), "f%d", i);
192 fregs[i] = tcg_global_mem_new(TCG_AREG0,
193 offsetof(CPUS390XState, fregs[i].d),
194 cpu_reg_names[i + 16]);
e023e832 195 }
7e68da2a
RH
196
197 /* register helpers */
198#define GEN_HELPER 2
199#include "helper.h"
d5a43964
AG
200}
201
e023e832 202static inline TCGv_i64 load_reg(int reg)
10ec5117 203{
e023e832
AG
204 TCGv_i64 r = tcg_temp_new_i64();
205 tcg_gen_mov_i64(r, regs[reg]);
206 return r;
10ec5117
AG
207}
208
e023e832 209static inline TCGv_i64 load_freg(int reg)
10ec5117 210{
e023e832 211 TCGv_i64 r = tcg_temp_new_i64();
431253c2 212 tcg_gen_mov_i64(r, fregs[reg]);
e023e832 213 return r;
10ec5117
AG
214}
215
e023e832 216static inline TCGv_i32 load_freg32(int reg)
10ec5117 217{
e023e832 218 TCGv_i32 r = tcg_temp_new_i32();
431253c2
RH
219#if HOST_LONG_BITS == 32
220 tcg_gen_mov_i32(r, TCGV_HIGH(fregs[reg]));
221#else
222 tcg_gen_shri_i64(MAKE_TCGV_I64(GET_TCGV_I32(r)), fregs[reg], 32);
223#endif
e023e832
AG
224 return r;
225}
226
227static inline TCGv_i32 load_reg32(int reg)
228{
229 TCGv_i32 r = tcg_temp_new_i32();
230 tcg_gen_trunc_i64_i32(r, regs[reg]);
231 return r;
232}
233
234static inline TCGv_i64 load_reg32_i64(int reg)
235{
236 TCGv_i64 r = tcg_temp_new_i64();
237 tcg_gen_ext32s_i64(r, regs[reg]);
238 return r;
239}
240
241static inline void store_reg(int reg, TCGv_i64 v)
242{
243 tcg_gen_mov_i64(regs[reg], v);
244}
245
246static inline void store_freg(int reg, TCGv_i64 v)
247{
431253c2 248 tcg_gen_mov_i64(fregs[reg], v);
e023e832
AG
249}
250
251static inline void store_reg32(int reg, TCGv_i32 v)
252{
431253c2 253 /* 32 bit register writes keep the upper half */
e023e832
AG
254#if HOST_LONG_BITS == 32
255 tcg_gen_mov_i32(TCGV_LOW(regs[reg]), v);
256#else
431253c2
RH
257 tcg_gen_deposit_i64(regs[reg], regs[reg],
258 MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 32);
e023e832
AG
259#endif
260}
261
262static inline void store_reg32_i64(int reg, TCGv_i64 v)
263{
264 /* 32 bit register writes keep the upper half */
e023e832 265 tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
e023e832
AG
266}
267
268static inline void store_reg16(int reg, TCGv_i32 v)
269{
e023e832 270 /* 16 bit register writes keep the upper bytes */
431253c2
RH
271#if HOST_LONG_BITS == 32
272 tcg_gen_deposit_i32(TCGV_LOW(regs[reg]), TCGV_LOW(regs[reg]), v, 0, 16);
273#else
274 tcg_gen_deposit_i64(regs[reg], regs[reg],
275 MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 16);
276#endif
e023e832
AG
277}
278
279static inline void store_reg8(int reg, TCGv_i64 v)
280{
281 /* 8 bit register writes keep the upper bytes */
282 tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 8);
283}
284
285static inline void store_freg32(int reg, TCGv_i32 v)
286{
431253c2
RH
287 /* 32 bit register writes keep the lower half */
288#if HOST_LONG_BITS == 32
289 tcg_gen_mov_i32(TCGV_HIGH(fregs[reg]), v);
290#else
291 tcg_gen_deposit_i64(fregs[reg], fregs[reg],
292 MAKE_TCGV_I64(GET_TCGV_I32(v)), 32, 32);
293#endif
e023e832
AG
294}
295
1ac5889f
RH
296static inline void return_low128(TCGv_i64 dest)
297{
298 tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
299}
300
e023e832
AG
301static inline void update_psw_addr(DisasContext *s)
302{
303 /* psw.addr */
304 tcg_gen_movi_i64(psw_addr, s->pc);
305}
306
307static inline void potential_page_fault(DisasContext *s)
308{
309#ifndef CONFIG_USER_ONLY
310 update_psw_addr(s);
311 gen_op_calc_cc(s);
312#endif
313}
314
46ee3d84 315static inline uint64_t ld_code2(CPUS390XState *env, uint64_t pc)
e023e832 316{
46ee3d84 317 return (uint64_t)cpu_lduw_code(env, pc);
e023e832
AG
318}
319
46ee3d84 320static inline uint64_t ld_code4(CPUS390XState *env, uint64_t pc)
e023e832 321{
ad044d09 322 return (uint64_t)(uint32_t)cpu_ldl_code(env, pc);
e023e832
AG
323}
324
46ee3d84 325static inline uint64_t ld_code6(CPUS390XState *env, uint64_t pc)
e023e832 326{
ad044d09 327 return (ld_code2(env, pc) << 32) | ld_code4(env, pc + 2);
e023e832
AG
328}
329
330static inline int get_mem_index(DisasContext *s)
331{
332 switch (s->tb->flags & FLAG_MASK_ASC) {
333 case PSW_ASC_PRIMARY >> 32:
334 return 0;
335 case PSW_ASC_SECONDARY >> 32:
336 return 1;
337 case PSW_ASC_HOME >> 32:
338 return 2;
339 default:
340 tcg_abort();
341 break;
342 }
343}
344
d5a103cd 345static void gen_exception(int excp)
e023e832 346{
d5a103cd 347 TCGv_i32 tmp = tcg_const_i32(excp);
089f5c06 348 gen_helper_exception(cpu_env, tmp);
e023e832 349 tcg_temp_free_i32(tmp);
e023e832
AG
350}
351
d5a103cd 352static void gen_program_exception(DisasContext *s, int code)
e023e832
AG
353{
354 TCGv_i32 tmp;
355
d5a103cd 356 /* Remember what pgm exeption this was. */
e023e832 357 tmp = tcg_const_i32(code);
a4e3ad19 358 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
e023e832
AG
359 tcg_temp_free_i32(tmp);
360
d5a103cd
RH
361 tmp = tcg_const_i32(s->next_pc - s->pc);
362 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen));
e023e832
AG
363 tcg_temp_free_i32(tmp);
364
d5a103cd
RH
365 /* Advance past instruction. */
366 s->pc = s->next_pc;
e023e832
AG
367 update_psw_addr(s);
368
d5a103cd 369 /* Save off cc. */
e023e832
AG
370 gen_op_calc_cc(s);
371
d5a103cd
RH
372 /* Trigger exception. */
373 gen_exception(EXCP_PGM);
e023e832 374
d5a103cd 375 /* End TB here. */
e023e832
AG
376 s->is_jmp = DISAS_EXCP;
377}
378
d5a103cd 379static inline void gen_illegal_opcode(DisasContext *s)
e023e832 380{
d5a103cd 381 gen_program_exception(s, PGM_SPECIFICATION);
e023e832
AG
382}
383
d5a103cd 384static inline void check_privileged(DisasContext *s)
e023e832
AG
385{
386 if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
d5a103cd 387 gen_program_exception(s, PGM_PRIVILEGED);
e023e832
AG
388 }
389}
390
e023e832
AG
391static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
392{
393 TCGv_i64 tmp;
394
395 /* 31-bitify the immediate part; register contents are dealt with below */
396 if (!(s->tb->flags & FLAG_MASK_64)) {
397 d2 &= 0x7fffffffUL;
398 }
399
400 if (x2) {
401 if (d2) {
402 tmp = tcg_const_i64(d2);
403 tcg_gen_add_i64(tmp, tmp, regs[x2]);
404 } else {
405 tmp = load_reg(x2);
406 }
407 if (b2) {
408 tcg_gen_add_i64(tmp, tmp, regs[b2]);
409 }
410 } else if (b2) {
411 if (d2) {
412 tmp = tcg_const_i64(d2);
413 tcg_gen_add_i64(tmp, tmp, regs[b2]);
414 } else {
415 tmp = load_reg(b2);
416 }
417 } else {
418 tmp = tcg_const_i64(d2);
419 }
420
421 /* 31-bit mode mask if there are values loaded from registers */
422 if (!(s->tb->flags & FLAG_MASK_64) && (x2 || b2)) {
423 tcg_gen_andi_i64(tmp, tmp, 0x7fffffffUL);
424 }
425
426 return tmp;
427}
428
429static void gen_op_movi_cc(DisasContext *s, uint32_t val)
430{
431 s->cc_op = CC_OP_CONST0 + val;
432}
433
434static void gen_op_update1_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 dst)
435{
436 tcg_gen_discard_i64(cc_src);
437 tcg_gen_mov_i64(cc_dst, dst);
438 tcg_gen_discard_i64(cc_vr);
439 s->cc_op = op;
440}
441
442static void gen_op_update1_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 dst)
443{
444 tcg_gen_discard_i64(cc_src);
445 tcg_gen_extu_i32_i64(cc_dst, dst);
446 tcg_gen_discard_i64(cc_vr);
447 s->cc_op = op;
448}
449
450static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
451 TCGv_i64 dst)
452{
453 tcg_gen_mov_i64(cc_src, src);
454 tcg_gen_mov_i64(cc_dst, dst);
455 tcg_gen_discard_i64(cc_vr);
456 s->cc_op = op;
457}
458
459static void gen_op_update2_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 src,
460 TCGv_i32 dst)
461{
462 tcg_gen_extu_i32_i64(cc_src, src);
463 tcg_gen_extu_i32_i64(cc_dst, dst);
464 tcg_gen_discard_i64(cc_vr);
465 s->cc_op = op;
466}
467
468static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
469 TCGv_i64 dst, TCGv_i64 vr)
470{
471 tcg_gen_mov_i64(cc_src, src);
472 tcg_gen_mov_i64(cc_dst, dst);
473 tcg_gen_mov_i64(cc_vr, vr);
474 s->cc_op = op;
475}
476
e023e832
AG
477static inline void set_cc_nz_u32(DisasContext *s, TCGv_i32 val)
478{
479 gen_op_update1_cc_i32(s, CC_OP_NZ, val);
480}
481
482static inline void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
483{
484 gen_op_update1_cc_i64(s, CC_OP_NZ, val);
485}
486
487static inline void cmp_32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
488 enum cc_op cond)
489{
490 gen_op_update2_cc_i32(s, cond, v1, v2);
491}
492
493static inline void cmp_64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
494 enum cc_op cond)
495{
496 gen_op_update2_cc_i64(s, cond, v1, v2);
497}
498
499static inline void cmp_s32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
500{
501 cmp_32(s, v1, v2, CC_OP_LTGT_32);
502}
503
504static inline void cmp_u32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
505{
506 cmp_32(s, v1, v2, CC_OP_LTUGTU_32);
507}
508
509static inline void cmp_s32c(DisasContext *s, TCGv_i32 v1, int32_t v2)
510{
511 /* XXX optimize for the constant? put it in s? */
512 TCGv_i32 tmp = tcg_const_i32(v2);
513 cmp_32(s, v1, tmp, CC_OP_LTGT_32);
514 tcg_temp_free_i32(tmp);
515}
516
517static inline void cmp_u32c(DisasContext *s, TCGv_i32 v1, uint32_t v2)
518{
519 TCGv_i32 tmp = tcg_const_i32(v2);
520 cmp_32(s, v1, tmp, CC_OP_LTUGTU_32);
521 tcg_temp_free_i32(tmp);
522}
523
524static inline void cmp_s64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2)
525{
526 cmp_64(s, v1, v2, CC_OP_LTGT_64);
527}
528
529static inline void cmp_u64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2)
530{
531 cmp_64(s, v1, v2, CC_OP_LTUGTU_64);
532}
533
534static inline void cmp_s64c(DisasContext *s, TCGv_i64 v1, int64_t v2)
535{
536 TCGv_i64 tmp = tcg_const_i64(v2);
537 cmp_s64(s, v1, tmp);
538 tcg_temp_free_i64(tmp);
539}
540
541static inline void cmp_u64c(DisasContext *s, TCGv_i64 v1, uint64_t v2)
542{
543 TCGv_i64 tmp = tcg_const_i64(v2);
544 cmp_u64(s, v1, tmp);
545 tcg_temp_free_i64(tmp);
546}
547
548static inline void set_cc_s32(DisasContext *s, TCGv_i32 val)
549{
550 gen_op_update1_cc_i32(s, CC_OP_LTGT0_32, val);
551}
552
553static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
554{
555 gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
556}
557
e023e832
AG
558static void set_cc_icm(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
559{
560 gen_op_update2_cc_i32(s, CC_OP_ICM, v1, v2);
561}
562
563static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2)
564{
565 tcg_gen_extu_i32_i64(cc_src, v1);
566 tcg_gen_mov_i64(cc_dst, v2);
567 tcg_gen_discard_i64(cc_vr);
568 s->cc_op = CC_OP_LTGT_F32;
569}
570
e72ca652 571static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i32 v1)
e023e832
AG
572{
573 gen_op_update1_cc_i32(s, CC_OP_NZ_F32, v1);
574}
575
e023e832
AG
576/* CC value is in env->cc_op */
577static inline void set_cc_static(DisasContext *s)
578{
579 tcg_gen_discard_i64(cc_src);
580 tcg_gen_discard_i64(cc_dst);
581 tcg_gen_discard_i64(cc_vr);
582 s->cc_op = CC_OP_STATIC;
583}
584
585static inline void gen_op_set_cc_op(DisasContext *s)
586{
587 if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
588 tcg_gen_movi_i32(cc_op, s->cc_op);
589 }
590}
591
592static inline void gen_update_cc_op(DisasContext *s)
593{
594 gen_op_set_cc_op(s);
595}
596
597/* calculates cc into cc_op */
598static void gen_op_calc_cc(DisasContext *s)
599{
600 TCGv_i32 local_cc_op = tcg_const_i32(s->cc_op);
601 TCGv_i64 dummy = tcg_const_i64(0);
602
603 switch (s->cc_op) {
604 case CC_OP_CONST0:
605 case CC_OP_CONST1:
606 case CC_OP_CONST2:
607 case CC_OP_CONST3:
608 /* s->cc_op is the cc value */
609 tcg_gen_movi_i32(cc_op, s->cc_op - CC_OP_CONST0);
610 break;
611 case CC_OP_STATIC:
612 /* env->cc_op already is the cc value */
613 break;
614 case CC_OP_NZ:
615 case CC_OP_ABS_64:
616 case CC_OP_NABS_64:
617 case CC_OP_ABS_32:
618 case CC_OP_NABS_32:
619 case CC_OP_LTGT0_32:
620 case CC_OP_LTGT0_64:
621 case CC_OP_COMP_32:
622 case CC_OP_COMP_64:
623 case CC_OP_NZ_F32:
624 case CC_OP_NZ_F64:
625 /* 1 argument */
932385a3 626 gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
e023e832
AG
627 break;
628 case CC_OP_ICM:
629 case CC_OP_LTGT_32:
630 case CC_OP_LTGT_64:
631 case CC_OP_LTUGTU_32:
632 case CC_OP_LTUGTU_64:
633 case CC_OP_TM_32:
634 case CC_OP_TM_64:
635 case CC_OP_LTGT_F32:
636 case CC_OP_LTGT_F64:
637 case CC_OP_SLAG:
638 /* 2 arguments */
932385a3 639 gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
e023e832
AG
640 break;
641 case CC_OP_ADD_64:
642 case CC_OP_ADDU_64:
4e4bb438 643 case CC_OP_ADDC_64:
e023e832
AG
644 case CC_OP_SUB_64:
645 case CC_OP_SUBU_64:
4e4bb438 646 case CC_OP_SUBB_64:
e023e832
AG
647 case CC_OP_ADD_32:
648 case CC_OP_ADDU_32:
4e4bb438 649 case CC_OP_ADDC_32:
e023e832
AG
650 case CC_OP_SUB_32:
651 case CC_OP_SUBU_32:
4e4bb438 652 case CC_OP_SUBB_32:
e023e832 653 /* 3 arguments */
932385a3 654 gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, cc_vr);
e023e832
AG
655 break;
656 case CC_OP_DYNAMIC:
657 /* unknown operation - assume 3 arguments and cc_op in env */
932385a3 658 gen_helper_calc_cc(cc_op, cpu_env, cc_op, cc_src, cc_dst, cc_vr);
e023e832
AG
659 break;
660 default:
661 tcg_abort();
662 }
663
664 tcg_temp_free_i32(local_cc_op);
063eb0f3 665 tcg_temp_free_i64(dummy);
e023e832
AG
666
667 /* We now have cc in cc_op as constant */
668 set_cc_static(s);
669}
670
671static inline void decode_rr(DisasContext *s, uint64_t insn, int *r1, int *r2)
672{
673 debug_insn(insn);
674
675 *r1 = (insn >> 4) & 0xf;
676 *r2 = insn & 0xf;
677}
678
679static inline TCGv_i64 decode_rx(DisasContext *s, uint64_t insn, int *r1,
680 int *x2, int *b2, int *d2)
681{
682 debug_insn(insn);
683
684 *r1 = (insn >> 20) & 0xf;
685 *x2 = (insn >> 16) & 0xf;
686 *b2 = (insn >> 12) & 0xf;
687 *d2 = insn & 0xfff;
688
689 return get_address(s, *x2, *b2, *d2);
690}
691
692static inline void decode_rs(DisasContext *s, uint64_t insn, int *r1, int *r3,
693 int *b2, int *d2)
694{
695 debug_insn(insn);
696
697 *r1 = (insn >> 20) & 0xf;
698 /* aka m3 */
699 *r3 = (insn >> 16) & 0xf;
700 *b2 = (insn >> 12) & 0xf;
701 *d2 = insn & 0xfff;
702}
703
704static inline TCGv_i64 decode_si(DisasContext *s, uint64_t insn, int *i2,
705 int *b1, int *d1)
706{
707 debug_insn(insn);
708
709 *i2 = (insn >> 16) & 0xff;
710 *b1 = (insn >> 12) & 0xf;
711 *d1 = insn & 0xfff;
712
713 return get_address(s, 0, *b1, *d1);
714}
715
8ac33cdb 716static int use_goto_tb(DisasContext *s, uint64_t dest)
e023e832 717{
8ac33cdb
RH
718 /* NOTE: we handle the case where the TB spans two pages here */
719 return (((dest & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK)
720 || (dest & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))
721 && !s->singlestep_enabled
722 && !(s->tb->cflags & CF_LAST_IO));
723}
e023e832 724
8ac33cdb
RH
725static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc)
726{
e023e832
AG
727 gen_update_cc_op(s);
728
8ac33cdb 729 if (use_goto_tb(s, pc)) {
e023e832
AG
730 tcg_gen_goto_tb(tb_num);
731 tcg_gen_movi_i64(psw_addr, pc);
8ac33cdb 732 tcg_gen_exit_tb((tcg_target_long)s->tb + tb_num);
e023e832
AG
733 } else {
734 /* jump to another page: currently not optimized */
735 tcg_gen_movi_i64(psw_addr, pc);
736 tcg_gen_exit_tb(0);
737 }
738}
739
740static inline void account_noninline_branch(DisasContext *s, int cc_op)
741{
742#ifdef DEBUG_INLINE_BRANCHES
743 inline_branch_miss[cc_op]++;
744#endif
745}
746
3fde06f5 747static inline void account_inline_branch(DisasContext *s, int cc_op)
e023e832
AG
748{
749#ifdef DEBUG_INLINE_BRANCHES
3fde06f5 750 inline_branch_hit[cc_op]++;
e023e832
AG
751#endif
752}
753
3fde06f5
RH
754/* Table of mask values to comparison codes, given a comparison as input.
755 For a true comparison CC=3 will never be set, but we treat this
756 conservatively for possible use when CC=3 indicates overflow. */
757static const TCGCond ltgt_cond[16] = {
758 TCG_COND_NEVER, TCG_COND_NEVER, /* | | | x */
759 TCG_COND_GT, TCG_COND_NEVER, /* | | GT | x */
760 TCG_COND_LT, TCG_COND_NEVER, /* | LT | | x */
761 TCG_COND_NE, TCG_COND_NEVER, /* | LT | GT | x */
762 TCG_COND_EQ, TCG_COND_NEVER, /* EQ | | | x */
763 TCG_COND_GE, TCG_COND_NEVER, /* EQ | | GT | x */
764 TCG_COND_LE, TCG_COND_NEVER, /* EQ | LT | | x */
765 TCG_COND_ALWAYS, TCG_COND_ALWAYS, /* EQ | LT | GT | x */
766};
767
768/* Table of mask values to comparison codes, given a logic op as input.
769 For such, only CC=0 and CC=1 should be possible. */
770static const TCGCond nz_cond[16] = {
771 /* | | x | x */
772 TCG_COND_NEVER, TCG_COND_NEVER, TCG_COND_NEVER, TCG_COND_NEVER,
773 /* | NE | x | x */
774 TCG_COND_NE, TCG_COND_NE, TCG_COND_NE, TCG_COND_NE,
775 /* EQ | | x | x */
776 TCG_COND_EQ, TCG_COND_EQ, TCG_COND_EQ, TCG_COND_EQ,
777 /* EQ | NE | x | x */
778 TCG_COND_ALWAYS, TCG_COND_ALWAYS, TCG_COND_ALWAYS, TCG_COND_ALWAYS,
779};
780
781/* Interpret MASK in terms of S->CC_OP, and fill in C with all the
782 details required to generate a TCG comparison. */
783static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
e023e832 784{
3fde06f5
RH
785 TCGCond cond;
786 enum cc_op old_cc_op = s->cc_op;
e023e832 787
3fde06f5
RH
788 if (mask == 15 || mask == 0) {
789 c->cond = (mask ? TCG_COND_ALWAYS : TCG_COND_NEVER);
790 c->u.s32.a = cc_op;
791 c->u.s32.b = cc_op;
792 c->g1 = c->g2 = true;
793 c->is_64 = false;
794 return;
795 }
796
797 /* Find the TCG condition for the mask + cc op. */
798 switch (old_cc_op) {
e023e832 799 case CC_OP_LTGT0_32:
e023e832 800 case CC_OP_LTGT0_64:
e023e832 801 case CC_OP_LTGT_32:
e023e832 802 case CC_OP_LTGT_64:
3fde06f5
RH
803 cond = ltgt_cond[mask];
804 if (cond == TCG_COND_NEVER) {
e023e832
AG
805 goto do_dynamic;
806 }
3fde06f5 807 account_inline_branch(s, old_cc_op);
e023e832 808 break;
3fde06f5 809
e023e832 810 case CC_OP_LTUGTU_32:
e023e832 811 case CC_OP_LTUGTU_64:
3fde06f5
RH
812 cond = tcg_unsigned_cond(ltgt_cond[mask]);
813 if (cond == TCG_COND_NEVER) {
e023e832
AG
814 goto do_dynamic;
815 }
3fde06f5 816 account_inline_branch(s, old_cc_op);
e023e832 817 break;
3fde06f5 818
e023e832 819 case CC_OP_NZ:
3fde06f5
RH
820 cond = nz_cond[mask];
821 if (cond == TCG_COND_NEVER) {
e023e832
AG
822 goto do_dynamic;
823 }
3fde06f5 824 account_inline_branch(s, old_cc_op);
e023e832 825 break;
e023e832 826
3fde06f5 827 case CC_OP_TM_32:
e023e832 828 case CC_OP_TM_64:
e023e832 829 switch (mask) {
3fde06f5
RH
830 case 8:
831 cond = TCG_COND_EQ;
e023e832 832 break;
3fde06f5
RH
833 case 4 | 2 | 1:
834 cond = TCG_COND_NE;
e023e832
AG
835 break;
836 default:
837 goto do_dynamic;
838 }
3fde06f5 839 account_inline_branch(s, old_cc_op);
e023e832 840 break;
3fde06f5 841
e023e832
AG
842 case CC_OP_ICM:
843 switch (mask) {
3fde06f5
RH
844 case 8:
845 cond = TCG_COND_EQ;
e023e832 846 break;
3fde06f5
RH
847 case 4 | 2 | 1:
848 case 4 | 2:
849 cond = TCG_COND_NE;
e023e832
AG
850 break;
851 default:
852 goto do_dynamic;
853 }
3fde06f5 854 account_inline_branch(s, old_cc_op);
e023e832 855 break;
3fde06f5 856
e023e832 857 default:
3fde06f5
RH
858 do_dynamic:
859 /* Calculate cc value. */
e023e832 860 gen_op_calc_cc(s);
3fde06f5 861 /* FALLTHRU */
e023e832 862
3fde06f5
RH
863 case CC_OP_STATIC:
864 /* Jump based on CC. We'll load up the real cond below;
865 the assignment here merely avoids a compiler warning. */
e023e832 866 account_noninline_branch(s, old_cc_op);
3fde06f5
RH
867 old_cc_op = CC_OP_STATIC;
868 cond = TCG_COND_NEVER;
869 break;
870 }
e023e832 871
3fde06f5
RH
872 /* Load up the arguments of the comparison. */
873 c->is_64 = true;
874 c->g1 = c->g2 = false;
875 switch (old_cc_op) {
876 case CC_OP_LTGT0_32:
877 c->is_64 = false;
878 c->u.s32.a = tcg_temp_new_i32();
879 tcg_gen_trunc_i64_i32(c->u.s32.a, cc_dst);
880 c->u.s32.b = tcg_const_i32(0);
881 break;
882 case CC_OP_LTGT_32:
883 case CC_OP_LTUGTU_32:
884 c->is_64 = false;
885 c->u.s32.a = tcg_temp_new_i32();
886 tcg_gen_trunc_i64_i32(c->u.s32.a, cc_src);
887 c->u.s32.b = tcg_temp_new_i32();
888 tcg_gen_trunc_i64_i32(c->u.s32.b, cc_dst);
889 break;
890
891 case CC_OP_LTGT0_64:
892 case CC_OP_NZ:
893 case CC_OP_ICM:
894 c->u.s64.a = cc_dst;
895 c->u.s64.b = tcg_const_i64(0);
896 c->g1 = true;
897 break;
898 case CC_OP_LTGT_64:
899 case CC_OP_LTUGTU_64:
900 c->u.s64.a = cc_src;
901 c->u.s64.b = cc_dst;
902 c->g1 = c->g2 = true;
903 break;
904
905 case CC_OP_TM_32:
906 case CC_OP_TM_64:
907 c->u.s64.a = tcg_temp_new_i64();
908 c->u.s64.b = tcg_const_i64(0);
909 tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst);
910 break;
911
912 case CC_OP_STATIC:
913 c->is_64 = false;
914 c->u.s32.a = cc_op;
915 c->g1 = true;
e023e832 916 switch (mask) {
e023e832 917 case 0x8 | 0x4 | 0x2: /* cc != 3 */
3fde06f5
RH
918 cond = TCG_COND_NE;
919 c->u.s32.b = tcg_const_i32(3);
e023e832
AG
920 break;
921 case 0x8 | 0x4 | 0x1: /* cc != 2 */
3fde06f5
RH
922 cond = TCG_COND_NE;
923 c->u.s32.b = tcg_const_i32(2);
e023e832
AG
924 break;
925 case 0x8 | 0x2 | 0x1: /* cc != 1 */
3fde06f5
RH
926 cond = TCG_COND_NE;
927 c->u.s32.b = tcg_const_i32(1);
e023e832 928 break;
3fde06f5
RH
929 case 0x8 | 0x2: /* cc == 0 || cc == 2 => (cc & 1) == 0 */
930 cond = TCG_COND_EQ;
931 c->g1 = false;
932 c->u.s32.a = tcg_temp_new_i32();
933 c->u.s32.b = tcg_const_i32(0);
934 tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
e023e832
AG
935 break;
936 case 0x8 | 0x4: /* cc < 2 */
3fde06f5
RH
937 cond = TCG_COND_LTU;
938 c->u.s32.b = tcg_const_i32(2);
e023e832
AG
939 break;
940 case 0x8: /* cc == 0 */
3fde06f5
RH
941 cond = TCG_COND_EQ;
942 c->u.s32.b = tcg_const_i32(0);
e023e832
AG
943 break;
944 case 0x4 | 0x2 | 0x1: /* cc != 0 */
3fde06f5
RH
945 cond = TCG_COND_NE;
946 c->u.s32.b = tcg_const_i32(0);
e023e832 947 break;
3fde06f5
RH
948 case 0x4 | 0x1: /* cc == 1 || cc == 3 => (cc & 1) != 0 */
949 cond = TCG_COND_NE;
950 c->g1 = false;
951 c->u.s32.a = tcg_temp_new_i32();
952 c->u.s32.b = tcg_const_i32(0);
953 tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
e023e832
AG
954 break;
955 case 0x4: /* cc == 1 */
3fde06f5
RH
956 cond = TCG_COND_EQ;
957 c->u.s32.b = tcg_const_i32(1);
e023e832
AG
958 break;
959 case 0x2 | 0x1: /* cc > 1 */
3fde06f5
RH
960 cond = TCG_COND_GTU;
961 c->u.s32.b = tcg_const_i32(1);
e023e832
AG
962 break;
963 case 0x2: /* cc == 2 */
3fde06f5
RH
964 cond = TCG_COND_EQ;
965 c->u.s32.b = tcg_const_i32(2);
e023e832
AG
966 break;
967 case 0x1: /* cc == 3 */
3fde06f5
RH
968 cond = TCG_COND_EQ;
969 c->u.s32.b = tcg_const_i32(3);
e023e832 970 break;
3fde06f5
RH
971 default:
972 /* CC is masked by something else: (8 >> cc) & mask. */
973 cond = TCG_COND_NE;
974 c->g1 = false;
975 c->u.s32.a = tcg_const_i32(8);
976 c->u.s32.b = tcg_const_i32(0);
977 tcg_gen_shr_i32(c->u.s32.a, c->u.s32.a, cc_op);
978 tcg_gen_andi_i32(c->u.s32.a, c->u.s32.a, mask);
e023e832
AG
979 break;
980 }
981 break;
3fde06f5
RH
982
983 default:
984 abort();
e023e832 985 }
3fde06f5
RH
986 c->cond = cond;
987}
988
989static void free_compare(DisasCompare *c)
990{
991 if (!c->g1) {
992 if (c->is_64) {
993 tcg_temp_free_i64(c->u.s64.a);
994 } else {
995 tcg_temp_free_i32(c->u.s32.a);
996 }
997 }
998 if (!c->g2) {
999 if (c->is_64) {
1000 tcg_temp_free_i64(c->u.s64.b);
1001 } else {
1002 tcg_temp_free_i32(c->u.s32.b);
1003 }
1004 }
1005}
1006
e023e832
AG
1007static void gen_op_mvc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
1008{
1009 TCGv_i64 tmp, tmp2;
1010 int i;
1011 int l_memset = gen_new_label();
1012 int l_out = gen_new_label();
1013 TCGv_i64 dest = tcg_temp_local_new_i64();
1014 TCGv_i64 src = tcg_temp_local_new_i64();
1015 TCGv_i32 vl;
1016
1017 /* Find out if we should use the inline version of mvc */
1018 switch (l) {
1019 case 0:
1020 case 1:
1021 case 2:
1022 case 3:
1023 case 4:
1024 case 5:
1025 case 6:
1026 case 7:
1027 case 11:
1028 case 15:
1029 /* use inline */
1030 break;
1031 default:
1032 /* Fall back to helper */
1033 vl = tcg_const_i32(l);
1034 potential_page_fault(s);
19b0516f 1035 gen_helper_mvc(cpu_env, vl, s1, s2);
e023e832
AG
1036 tcg_temp_free_i32(vl);
1037 return;
1038 }
1039
1040 tcg_gen_mov_i64(dest, s1);
1041 tcg_gen_mov_i64(src, s2);
1042
1043 if (!(s->tb->flags & FLAG_MASK_64)) {
1044 /* XXX what if we overflow while moving? */
1045 tcg_gen_andi_i64(dest, dest, 0x7fffffffUL);
1046 tcg_gen_andi_i64(src, src, 0x7fffffffUL);
1047 }
1048
1049 tmp = tcg_temp_new_i64();
1050 tcg_gen_addi_i64(tmp, src, 1);
1051 tcg_gen_brcond_i64(TCG_COND_EQ, dest, tmp, l_memset);
1052 tcg_temp_free_i64(tmp);
1053
1054 switch (l) {
1055 case 0:
1056 tmp = tcg_temp_new_i64();
1057
1058 tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
1059 tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
1060
1061 tcg_temp_free_i64(tmp);
1062 break;
1063 case 1:
1064 tmp = tcg_temp_new_i64();
1065
1066 tcg_gen_qemu_ld16u(tmp, src, get_mem_index(s));
1067 tcg_gen_qemu_st16(tmp, dest, get_mem_index(s));
1068
1069 tcg_temp_free_i64(tmp);
1070 break;
1071 case 3:
1072 tmp = tcg_temp_new_i64();
1073
1074 tcg_gen_qemu_ld32u(tmp, src, get_mem_index(s));
1075 tcg_gen_qemu_st32(tmp, dest, get_mem_index(s));
1076
1077 tcg_temp_free_i64(tmp);
1078 break;
1079 case 4:
1080 tmp = tcg_temp_new_i64();
1081 tmp2 = tcg_temp_new_i64();
1082
1083 tcg_gen_qemu_ld32u(tmp, src, get_mem_index(s));
1084 tcg_gen_addi_i64(src, src, 4);
1085 tcg_gen_qemu_ld8u(tmp2, src, get_mem_index(s));
1086 tcg_gen_qemu_st32(tmp, dest, get_mem_index(s));
1087 tcg_gen_addi_i64(dest, dest, 4);
1088 tcg_gen_qemu_st8(tmp2, dest, get_mem_index(s));
1089
1090 tcg_temp_free_i64(tmp);
1091 tcg_temp_free_i64(tmp2);
1092 break;
1093 case 7:
1094 tmp = tcg_temp_new_i64();
1095
1096 tcg_gen_qemu_ld64(tmp, src, get_mem_index(s));
1097 tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
1098
1099 tcg_temp_free_i64(tmp);
1100 break;
1101 default:
1102 /* The inline version can become too big for too uneven numbers, only
1103 use it on known good lengths */
1104 tmp = tcg_temp_new_i64();
1105 tmp2 = tcg_const_i64(8);
1106 for (i = 0; (i + 7) <= l; i += 8) {
1107 tcg_gen_qemu_ld64(tmp, src, get_mem_index(s));
1108 tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
1109
1110 tcg_gen_add_i64(src, src, tmp2);
1111 tcg_gen_add_i64(dest, dest, tmp2);
1112 }
1113
1114 tcg_temp_free_i64(tmp2);
1115 tmp2 = tcg_const_i64(1);
1116
1117 for (; i <= l; i++) {
1118 tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
1119 tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
1120
1121 tcg_gen_add_i64(src, src, tmp2);
1122 tcg_gen_add_i64(dest, dest, tmp2);
1123 }
1124
1125 tcg_temp_free_i64(tmp2);
1126 tcg_temp_free_i64(tmp);
1127 break;
1128 }
1129
1130 tcg_gen_br(l_out);
1131
1132 gen_set_label(l_memset);
1133 /* memset case (dest == (src + 1)) */
1134
1135 tmp = tcg_temp_new_i64();
1136 tmp2 = tcg_temp_new_i64();
1137 /* fill tmp with the byte */
1138 tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
1139 tcg_gen_shli_i64(tmp2, tmp, 8);
1140 tcg_gen_or_i64(tmp, tmp, tmp2);
1141 tcg_gen_shli_i64(tmp2, tmp, 16);
1142 tcg_gen_or_i64(tmp, tmp, tmp2);
1143 tcg_gen_shli_i64(tmp2, tmp, 32);
1144 tcg_gen_or_i64(tmp, tmp, tmp2);
1145 tcg_temp_free_i64(tmp2);
1146
1147 tmp2 = tcg_const_i64(8);
1148
1149 for (i = 0; (i + 7) <= l; i += 8) {
1150 tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
1151 tcg_gen_addi_i64(dest, dest, 8);
1152 }
1153
1154 tcg_temp_free_i64(tmp2);
1155 tmp2 = tcg_const_i64(1);
1156
1157 for (; i <= l; i++) {
1158 tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
1159 tcg_gen_addi_i64(dest, dest, 1);
1160 }
1161
1162 tcg_temp_free_i64(tmp2);
1163 tcg_temp_free_i64(tmp);
1164
1165 gen_set_label(l_out);
1166
1167 tcg_temp_free(dest);
1168 tcg_temp_free(src);
1169}
1170
1171static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
1172{
1173 TCGv_i64 tmp;
1174 TCGv_i64 tmp2;
1175 TCGv_i32 vl;
1176
1177 /* check for simple 32bit or 64bit match */
1178 switch (l) {
1179 case 0:
1180 tmp = tcg_temp_new_i64();
1181 tmp2 = tcg_temp_new_i64();
1182
1183 tcg_gen_qemu_ld8u(tmp, s1, get_mem_index(s));
1184 tcg_gen_qemu_ld8u(tmp2, s2, get_mem_index(s));
1185 cmp_u64(s, tmp, tmp2);
1186
1187 tcg_temp_free_i64(tmp);
1188 tcg_temp_free_i64(tmp2);
1189 return;
1190 case 1:
1191 tmp = tcg_temp_new_i64();
1192 tmp2 = tcg_temp_new_i64();
1193
1194 tcg_gen_qemu_ld16u(tmp, s1, get_mem_index(s));
1195 tcg_gen_qemu_ld16u(tmp2, s2, get_mem_index(s));
1196 cmp_u64(s, tmp, tmp2);
1197
1198 tcg_temp_free_i64(tmp);
1199 tcg_temp_free_i64(tmp2);
1200 return;
1201 case 3:
1202 tmp = tcg_temp_new_i64();
1203 tmp2 = tcg_temp_new_i64();
1204
1205 tcg_gen_qemu_ld32u(tmp, s1, get_mem_index(s));
1206 tcg_gen_qemu_ld32u(tmp2, s2, get_mem_index(s));
1207 cmp_u64(s, tmp, tmp2);
1208
1209 tcg_temp_free_i64(tmp);
1210 tcg_temp_free_i64(tmp2);
1211 return;
1212 case 7:
1213 tmp = tcg_temp_new_i64();
1214 tmp2 = tcg_temp_new_i64();
1215
1216 tcg_gen_qemu_ld64(tmp, s1, get_mem_index(s));
1217 tcg_gen_qemu_ld64(tmp2, s2, get_mem_index(s));
1218 cmp_u64(s, tmp, tmp2);
1219
1220 tcg_temp_free_i64(tmp);
1221 tcg_temp_free_i64(tmp2);
1222 return;
1223 }
1224
1225 potential_page_fault(s);
1226 vl = tcg_const_i32(l);
19b0516f 1227 gen_helper_clc(cc_op, cpu_env, vl, s1, s2);
e023e832
AG
1228 tcg_temp_free_i32(vl);
1229 set_cc_static(s);
1230}
1231
46ee3d84
BS
1232static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
1233 int x2, int b2, int d2)
e023e832 1234{
891452e5 1235 TCGv_i64 addr, tmp2, tmp3;
4e4bb438 1236 TCGv_i32 tmp32_1;
e023e832
AG
1237
1238 LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
1239 op, r1, x2, b2, d2);
1240 addr = get_address(s, x2, b2, d2);
1241 switch (op) {
e023e832
AG
1242 case 0xf: /* LRVG R1,D2(X2,B2) [RXE] */
1243 tmp2 = tcg_temp_new_i64();
1244 tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
1245 tcg_gen_bswap64_i64(tmp2, tmp2);
1246 store_reg(r1, tmp2);
1247 tcg_temp_free_i64(tmp2);
1248 break;
e023e832
AG
1249 case 0x17: /* LLGT R1,D2(X2,B2) [RXY] */
1250 tmp2 = tcg_temp_new_i64();
1251 tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1252 tcg_gen_andi_i64(tmp2, tmp2, 0x7fffffffULL);
1253 store_reg(r1, tmp2);
1254 tcg_temp_free_i64(tmp2);
1255 break;
1256 case 0x1e: /* LRV R1,D2(X2,B2) [RXY] */
1257 tmp2 = tcg_temp_new_i64();
1258 tmp32_1 = tcg_temp_new_i32();
1259 tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1260 tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
1261 tcg_temp_free_i64(tmp2);
1262 tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
1263 store_reg32(r1, tmp32_1);
1264 tcg_temp_free_i32(tmp32_1);
1265 break;
1266 case 0x1f: /* LRVH R1,D2(X2,B2) [RXY] */
1267 tmp2 = tcg_temp_new_i64();
1268 tmp32_1 = tcg_temp_new_i32();
1269 tcg_gen_qemu_ld16u(tmp2, addr, get_mem_index(s));
1270 tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
1271 tcg_temp_free_i64(tmp2);
1272 tcg_gen_bswap16_i32(tmp32_1, tmp32_1);
1273 store_reg16(r1, tmp32_1);
1274 tcg_temp_free_i32(tmp32_1);
1275 break;
e023e832
AG
1276 case 0x3e: /* STRV R1,D2(X2,B2) [RXY] */
1277 tmp32_1 = load_reg32(r1);
1278 tmp2 = tcg_temp_new_i64();
1279 tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
1280 tcg_gen_extu_i32_i64(tmp2, tmp32_1);
1281 tcg_temp_free_i32(tmp32_1);
1282 tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
1283 tcg_temp_free_i64(tmp2);
1284 break;
e023e832
AG
1285 case 0x73: /* ICY R1,D2(X2,B2) [RXY] */
1286 tmp3 = tcg_temp_new_i64();
1287 tcg_gen_qemu_ld8u(tmp3, addr, get_mem_index(s));
1288 store_reg8(r1, tmp3);
1289 tcg_temp_free_i64(tmp3);
1290 break;
e023e832
AG
1291 default:
1292 LOG_DISAS("illegal e3 operation 0x%x\n", op);
d5a103cd 1293 gen_illegal_opcode(s);
e023e832
AG
1294 break;
1295 }
1296 tcg_temp_free_i64(addr);
1297}
1298
1299#ifndef CONFIG_USER_ONLY
46ee3d84 1300static void disas_e5(CPUS390XState *env, DisasContext* s, uint64_t insn)
e023e832
AG
1301{
1302 TCGv_i64 tmp, tmp2;
1303 int op = (insn >> 32) & 0xff;
1304
1305 tmp = get_address(s, 0, (insn >> 28) & 0xf, (insn >> 16) & 0xfff);
1306 tmp2 = get_address(s, 0, (insn >> 12) & 0xf, insn & 0xfff);
1307
1308 LOG_DISAS("disas_e5: insn %" PRIx64 "\n", insn);
1309 switch (op) {
1310 case 0x01: /* TPROT D1(B1),D2(B2) [SSE] */
1311 /* Test Protection */
1312 potential_page_fault(s);
1313 gen_helper_tprot(cc_op, tmp, tmp2);
1314 set_cc_static(s);
1315 break;
1316 default:
1317 LOG_DISAS("illegal e5 operation 0x%x\n", op);
d5a103cd 1318 gen_illegal_opcode(s);
e023e832
AG
1319 break;
1320 }
1321
1322 tcg_temp_free_i64(tmp);
1323 tcg_temp_free_i64(tmp2);
1324}
1325#endif
1326
46ee3d84
BS
1327static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
1328 int r3, int b2, int d2)
e023e832
AG
1329{
1330 TCGv_i64 tmp, tmp2, tmp3, tmp4;
1331 TCGv_i32 tmp32_1, tmp32_2;
1332 int i, stm_len;
e023e832
AG
1333
1334 LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
1335 op, r1, r3, b2, d2);
1336 switch (op) {
1337 case 0xc: /* SRLG R1,R3,D2(B2) [RSY] */
1338 case 0xd: /* SLLG R1,R3,D2(B2) [RSY] */
1339 case 0xa: /* SRAG R1,R3,D2(B2) [RSY] */
1340 case 0xb: /* SLAG R1,R3,D2(B2) [RSY] */
1341 case 0x1c: /* RLLG R1,R3,D2(B2) [RSY] */
1342 if (b2) {
1343 tmp = get_address(s, 0, b2, d2);
1344 tcg_gen_andi_i64(tmp, tmp, 0x3f);
1345 } else {
1346 tmp = tcg_const_i64(d2 & 0x3f);
1347 }
1348 switch (op) {
1349 case 0xc:
1350 tcg_gen_shr_i64(regs[r1], regs[r3], tmp);
1351 break;
1352 case 0xd:
1353 tcg_gen_shl_i64(regs[r1], regs[r3], tmp);
1354 break;
1355 case 0xa:
1356 tcg_gen_sar_i64(regs[r1], regs[r3], tmp);
1357 break;
1358 case 0xb:
1359 tmp2 = tcg_temp_new_i64();
1360 tmp3 = tcg_temp_new_i64();
1361 gen_op_update2_cc_i64(s, CC_OP_SLAG, regs[r3], tmp);
1362 tcg_gen_shl_i64(tmp2, regs[r3], tmp);
1363 /* override sign bit with source sign */
1364 tcg_gen_andi_i64(tmp2, tmp2, ~0x8000000000000000ULL);
1365 tcg_gen_andi_i64(tmp3, regs[r3], 0x8000000000000000ULL);
1366 tcg_gen_or_i64(regs[r1], tmp2, tmp3);
1367 tcg_temp_free_i64(tmp2);
1368 tcg_temp_free_i64(tmp3);
1369 break;
1370 case 0x1c:
1371 tcg_gen_rotl_i64(regs[r1], regs[r3], tmp);
1372 break;
1373 default:
1374 tcg_abort();
1375 break;
1376 }
1377 if (op == 0xa) {
1378 set_cc_s64(s, regs[r1]);
1379 }
1380 tcg_temp_free_i64(tmp);
1381 break;
1382 case 0x1d: /* RLL R1,R3,D2(B2) [RSY] */
1383 if (b2) {
1384 tmp = get_address(s, 0, b2, d2);
1385 tcg_gen_andi_i64(tmp, tmp, 0x3f);
1386 } else {
1387 tmp = tcg_const_i64(d2 & 0x3f);
1388 }
1389 tmp32_1 = tcg_temp_new_i32();
1390 tmp32_2 = load_reg32(r3);
1391 tcg_gen_trunc_i64_i32(tmp32_1, tmp);
1392 switch (op) {
1393 case 0x1d:
1394 tcg_gen_rotl_i32(tmp32_1, tmp32_2, tmp32_1);
1395 break;
1396 default:
1397 tcg_abort();
1398 break;
1399 }
1400 store_reg32(r1, tmp32_1);
1401 tcg_temp_free_i64(tmp);
1402 tcg_temp_free_i32(tmp32_1);
1403 tcg_temp_free_i32(tmp32_2);
1404 break;
1405 case 0x4: /* LMG R1,R3,D2(B2) [RSE] */
1406 case 0x24: /* STMG R1,R3,D2(B2) [RSE] */
1407 stm_len = 8;
1408 goto do_mh;
1409 case 0x26: /* STMH R1,R3,D2(B2) [RSE] */
1410 case 0x96: /* LMH R1,R3,D2(B2) [RSE] */
1411 stm_len = 4;
1412do_mh:
1413 /* Apparently, unrolling lmg/stmg of any size gains performance -
1414 even for very long ones... */
1415 tmp = get_address(s, 0, b2, d2);
1416 tmp3 = tcg_const_i64(stm_len);
be82ee2a 1417 tmp4 = tcg_const_i64(op == 0x26 ? 32 : 4);
e023e832
AG
1418 for (i = r1;; i = (i + 1) % 16) {
1419 switch (op) {
1420 case 0x4:
1421 tcg_gen_qemu_ld64(regs[i], tmp, get_mem_index(s));
1422 break;
1423 case 0x96:
1424 tmp2 = tcg_temp_new_i64();
1425#if HOST_LONG_BITS == 32
1426 tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
1427 tcg_gen_trunc_i64_i32(TCGV_HIGH(regs[i]), tmp2);
1428#else
e023e832 1429 tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
be82ee2a 1430 tcg_gen_shl_i64(tmp2, tmp2, tmp4);
e023e832
AG
1431 tcg_gen_ext32u_i64(regs[i], regs[i]);
1432 tcg_gen_or_i64(regs[i], regs[i], tmp2);
1433#endif
1434 tcg_temp_free_i64(tmp2);
1435 break;
1436 case 0x24:
1437 tcg_gen_qemu_st64(regs[i], tmp, get_mem_index(s));
1438 break;
1439 case 0x26:
1440 tmp2 = tcg_temp_new_i64();
1441 tcg_gen_shr_i64(tmp2, regs[i], tmp4);
1442 tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
1443 tcg_temp_free_i64(tmp2);
1444 break;
1445 default:
1446 tcg_abort();
1447 }
1448 if (i == r3) {
1449 break;
1450 }
1451 tcg_gen_add_i64(tmp, tmp, tmp3);
1452 }
1453 tcg_temp_free_i64(tmp);
21de37a7 1454 tcg_temp_free_i64(tmp3);
e023e832
AG
1455 tcg_temp_free_i64(tmp4);
1456 break;
1457 case 0x2c: /* STCMH R1,M3,D2(B2) [RSY] */
1458 tmp = get_address(s, 0, b2, d2);
1459 tmp32_1 = tcg_const_i32(r1);
1460 tmp32_2 = tcg_const_i32(r3);
1461 potential_page_fault(s);
19b0516f 1462 gen_helper_stcmh(cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
1463 tcg_temp_free_i64(tmp);
1464 tcg_temp_free_i32(tmp32_1);
1465 tcg_temp_free_i32(tmp32_2);
1466 break;
1467#ifndef CONFIG_USER_ONLY
1468 case 0x2f: /* LCTLG R1,R3,D2(B2) [RSE] */
1469 /* Load Control */
d5a103cd 1470 check_privileged(s);
e023e832
AG
1471 tmp = get_address(s, 0, b2, d2);
1472 tmp32_1 = tcg_const_i32(r1);
1473 tmp32_2 = tcg_const_i32(r3);
1474 potential_page_fault(s);
19b0516f 1475 gen_helper_lctlg(cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
1476 tcg_temp_free_i64(tmp);
1477 tcg_temp_free_i32(tmp32_1);
1478 tcg_temp_free_i32(tmp32_2);
1479 break;
1480 case 0x25: /* STCTG R1,R3,D2(B2) [RSE] */
1481 /* Store Control */
d5a103cd 1482 check_privileged(s);
e023e832
AG
1483 tmp = get_address(s, 0, b2, d2);
1484 tmp32_1 = tcg_const_i32(r1);
1485 tmp32_2 = tcg_const_i32(r3);
1486 potential_page_fault(s);
19b0516f 1487 gen_helper_stctg(cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
1488 tcg_temp_free_i64(tmp);
1489 tcg_temp_free_i32(tmp32_1);
1490 tcg_temp_free_i32(tmp32_2);
1491 break;
1492#endif
1493 case 0x30: /* CSG R1,R3,D2(B2) [RSY] */
1494 tmp = get_address(s, 0, b2, d2);
1495 tmp32_1 = tcg_const_i32(r1);
1496 tmp32_2 = tcg_const_i32(r3);
1497 potential_page_fault(s);
1498 /* XXX rewrite in tcg */
19b0516f 1499 gen_helper_csg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
1500 set_cc_static(s);
1501 tcg_temp_free_i64(tmp);
1502 tcg_temp_free_i32(tmp32_1);
1503 tcg_temp_free_i32(tmp32_2);
1504 break;
1505 case 0x3e: /* CDSG R1,R3,D2(B2) [RSY] */
1506 tmp = get_address(s, 0, b2, d2);
1507 tmp32_1 = tcg_const_i32(r1);
1508 tmp32_2 = tcg_const_i32(r3);
1509 potential_page_fault(s);
1510 /* XXX rewrite in tcg */
19b0516f 1511 gen_helper_cdsg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
1512 set_cc_static(s);
1513 tcg_temp_free_i64(tmp);
1514 tcg_temp_free_i32(tmp32_1);
1515 tcg_temp_free_i32(tmp32_2);
1516 break;
1517 case 0x51: /* TMY D1(B1),I2 [SIY] */
1518 tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
1519 tmp2 = tcg_const_i64((r1 << 4) | r3);
1520 tcg_gen_qemu_ld8u(tmp, tmp, get_mem_index(s));
1521 /* yes, this is a 32 bit operation with 64 bit tcg registers, because
1522 that incurs less conversions */
1523 cmp_64(s, tmp, tmp2, CC_OP_TM_32);
1524 tcg_temp_free_i64(tmp);
1525 tcg_temp_free_i64(tmp2);
1526 break;
1527 case 0x52: /* MVIY D1(B1),I2 [SIY] */
1528 tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
1529 tmp2 = tcg_const_i64((r1 << 4) | r3);
1530 tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
1531 tcg_temp_free_i64(tmp);
1532 tcg_temp_free_i64(tmp2);
1533 break;
e023e832
AG
1534 case 0x80: /* ICMH R1,M3,D2(B2) [RSY] */
1535 tmp = get_address(s, 0, b2, d2);
1536 tmp32_1 = tcg_const_i32(r1);
1537 tmp32_2 = tcg_const_i32(r3);
1538 potential_page_fault(s);
1539 /* XXX split CC calculation out */
19b0516f 1540 gen_helper_icmh(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
1541 set_cc_static(s);
1542 tcg_temp_free_i64(tmp);
1543 tcg_temp_free_i32(tmp32_1);
1544 tcg_temp_free_i32(tmp32_2);
1545 break;
1546 default:
1547 LOG_DISAS("illegal eb operation 0x%x\n", op);
d5a103cd 1548 gen_illegal_opcode(s);
e023e832
AG
1549 break;
1550 }
1551}
1552
46ee3d84
BS
1553static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
1554 int x2, int b2, int d2, int r1b)
e023e832
AG
1555{
1556 TCGv_i32 tmp_r1, tmp32;
1557 TCGv_i64 addr, tmp;
1558 addr = get_address(s, x2, b2, d2);
1559 tmp_r1 = tcg_const_i32(r1);
1560 switch (op) {
27b5979d
AG
1561 case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */
1562 potential_page_fault(s);
449c0d70 1563 gen_helper_ldeb(cpu_env, tmp_r1, addr);
27b5979d 1564 break;
e023e832
AG
1565 case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */
1566 potential_page_fault(s);
449c0d70 1567 gen_helper_lxdb(cpu_env, tmp_r1, addr);
e023e832
AG
1568 break;
1569 case 0x9: /* CEB R1,D2(X2,B2) [RXE] */
1570 tmp = tcg_temp_new_i64();
1571 tmp32 = load_freg32(r1);
1572 tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
1573 set_cc_cmp_f32_i64(s, tmp32, tmp);
1574 tcg_temp_free_i64(tmp);
1575 tcg_temp_free_i32(tmp32);
1576 break;
1577 case 0xa: /* AEB R1,D2(X2,B2) [RXE] */
1578 tmp = tcg_temp_new_i64();
1579 tmp32 = tcg_temp_new_i32();
1580 tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
1581 tcg_gen_trunc_i64_i32(tmp32, tmp);
449c0d70 1582 gen_helper_aeb(cpu_env, tmp_r1, tmp32);
e023e832
AG
1583 tcg_temp_free_i64(tmp);
1584 tcg_temp_free_i32(tmp32);
1585
1586 tmp32 = load_freg32(r1);
e72ca652 1587 gen_set_cc_nz_f32(s, tmp32);
e023e832
AG
1588 tcg_temp_free_i32(tmp32);
1589 break;
1590 case 0xb: /* SEB R1,D2(X2,B2) [RXE] */
1591 tmp = tcg_temp_new_i64();
1592 tmp32 = tcg_temp_new_i32();
1593 tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
1594 tcg_gen_trunc_i64_i32(tmp32, tmp);
449c0d70 1595 gen_helper_seb(cpu_env, tmp_r1, tmp32);
e023e832
AG
1596 tcg_temp_free_i64(tmp);
1597 tcg_temp_free_i32(tmp32);
1598
1599 tmp32 = load_freg32(r1);
e72ca652 1600 gen_set_cc_nz_f32(s, tmp32);
e023e832
AG
1601 tcg_temp_free_i32(tmp32);
1602 break;
1603 case 0xd: /* DEB R1,D2(X2,B2) [RXE] */
1604 tmp = tcg_temp_new_i64();
1605 tmp32 = tcg_temp_new_i32();
1606 tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
1607 tcg_gen_trunc_i64_i32(tmp32, tmp);
449c0d70 1608 gen_helper_deb(cpu_env, tmp_r1, tmp32);
e023e832
AG
1609 tcg_temp_free_i64(tmp);
1610 tcg_temp_free_i32(tmp32);
1611 break;
1612 case 0x10: /* TCEB R1,D2(X2,B2) [RXE] */
1613 potential_page_fault(s);
449c0d70 1614 gen_helper_tceb(cc_op, cpu_env, tmp_r1, addr);
e023e832
AG
1615 set_cc_static(s);
1616 break;
1617 case 0x11: /* TCDB R1,D2(X2,B2) [RXE] */
1618 potential_page_fault(s);
449c0d70 1619 gen_helper_tcdb(cc_op, cpu_env, tmp_r1, addr);
e023e832
AG
1620 set_cc_static(s);
1621 break;
1622 case 0x12: /* TCXB R1,D2(X2,B2) [RXE] */
1623 potential_page_fault(s);
449c0d70 1624 gen_helper_tcxb(cc_op, cpu_env, tmp_r1, addr);
e023e832
AG
1625 set_cc_static(s);
1626 break;
1627 case 0x17: /* MEEB R1,D2(X2,B2) [RXE] */
1628 tmp = tcg_temp_new_i64();
1629 tmp32 = tcg_temp_new_i32();
1630 tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
1631 tcg_gen_trunc_i64_i32(tmp32, tmp);
449c0d70 1632 gen_helper_meeb(cpu_env, tmp_r1, tmp32);
e023e832
AG
1633 tcg_temp_free_i64(tmp);
1634 tcg_temp_free_i32(tmp32);
1635 break;
1636 case 0x19: /* CDB R1,D2(X2,B2) [RXE] */
1637 potential_page_fault(s);
449c0d70 1638 gen_helper_cdb(cc_op, cpu_env, tmp_r1, addr);
e023e832
AG
1639 set_cc_static(s);
1640 break;
1641 case 0x1a: /* ADB R1,D2(X2,B2) [RXE] */
1642 potential_page_fault(s);
449c0d70 1643 gen_helper_adb(cc_op, cpu_env, tmp_r1, addr);
e023e832
AG
1644 set_cc_static(s);
1645 break;
1646 case 0x1b: /* SDB R1,D2(X2,B2) [RXE] */
1647 potential_page_fault(s);
449c0d70 1648 gen_helper_sdb(cc_op, cpu_env, tmp_r1, addr);
e023e832
AG
1649 set_cc_static(s);
1650 break;
1651 case 0x1c: /* MDB R1,D2(X2,B2) [RXE] */
1652 potential_page_fault(s);
449c0d70 1653 gen_helper_mdb(cpu_env, tmp_r1, addr);
e023e832
AG
1654 break;
1655 case 0x1d: /* DDB R1,D2(X2,B2) [RXE] */
1656 potential_page_fault(s);
449c0d70 1657 gen_helper_ddb(cpu_env, tmp_r1, addr);
e023e832
AG
1658 break;
1659 case 0x1e: /* MADB R1,R3,D2(X2,B2) [RXF] */
1660 /* for RXF insns, r1 is R3 and r1b is R1 */
1661 tmp32 = tcg_const_i32(r1b);
1662 potential_page_fault(s);
449c0d70 1663 gen_helper_madb(cpu_env, tmp32, addr, tmp_r1);
e023e832
AG
1664 tcg_temp_free_i32(tmp32);
1665 break;
1666 default:
1667 LOG_DISAS("illegal ed operation 0x%x\n", op);
d5a103cd 1668 gen_illegal_opcode(s);
e023e832
AG
1669 return;
1670 }
1671 tcg_temp_free_i32(tmp_r1);
1672 tcg_temp_free_i64(addr);
1673}
1674
46ee3d84
BS
1675static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
1676 int i2)
e023e832
AG
1677{
1678 TCGv_i64 tmp, tmp2;
e023e832
AG
1679
1680 LOG_DISAS("disas_a7: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
1681 switch (op) {
1682 case 0x0: /* TMLH or TMH R1,I2 [RI] */
1683 case 0x1: /* TMLL or TML R1,I2 [RI] */
1684 case 0x2: /* TMHH R1,I2 [RI] */
1685 case 0x3: /* TMHL R1,I2 [RI] */
1686 tmp = load_reg(r1);
1687 tmp2 = tcg_const_i64((uint16_t)i2);
1688 switch (op) {
1689 case 0x0:
1690 tcg_gen_shri_i64(tmp, tmp, 16);
1691 break;
1692 case 0x1:
1693 break;
1694 case 0x2:
1695 tcg_gen_shri_i64(tmp, tmp, 48);
1696 break;
1697 case 0x3:
1698 tcg_gen_shri_i64(tmp, tmp, 32);
1699 break;
1700 }
1701 tcg_gen_andi_i64(tmp, tmp, 0xffff);
1702 cmp_64(s, tmp, tmp2, CC_OP_TM_64);
1703 tcg_temp_free_i64(tmp);
1704 tcg_temp_free_i64(tmp2);
1705 break;
e023e832
AG
1706 default:
1707 LOG_DISAS("illegal a7 operation 0x%x\n", op);
d5a103cd 1708 gen_illegal_opcode(s);
e023e832
AG
1709 return;
1710 }
1711}
1712
46ee3d84
BS
1713static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
1714 uint32_t insn)
e023e832
AG
1715{
1716 TCGv_i64 tmp, tmp2, tmp3;
1717 TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
1718 int r1, r2;
e023e832
AG
1719#ifndef CONFIG_USER_ONLY
1720 int r3, d2, b2;
1721#endif
1722
1723 r1 = (insn >> 4) & 0xf;
1724 r2 = insn & 0xf;
1725
1726 LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
1727
1728 switch (op) {
1729 case 0x22: /* IPM R1 [RRE] */
1730 tmp32_1 = tcg_const_i32(r1);
1731 gen_op_calc_cc(s);
932385a3 1732 gen_helper_ipm(cpu_env, cc_op, tmp32_1);
e023e832
AG
1733 tcg_temp_free_i32(tmp32_1);
1734 break;
1735 case 0x41: /* CKSM R1,R2 [RRE] */
1736 tmp32_1 = tcg_const_i32(r1);
1737 tmp32_2 = tcg_const_i32(r2);
1738 potential_page_fault(s);
19b0516f 1739 gen_helper_cksm(cpu_env, tmp32_1, tmp32_2);
e023e832
AG
1740 tcg_temp_free_i32(tmp32_1);
1741 tcg_temp_free_i32(tmp32_2);
1742 gen_op_movi_cc(s, 0);
1743 break;
1744 case 0x4e: /* SAR R1,R2 [RRE] */
1745 tmp32_1 = load_reg32(r2);
a4e3ad19 1746 tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
e023e832
AG
1747 tcg_temp_free_i32(tmp32_1);
1748 break;
1749 case 0x4f: /* EAR R1,R2 [RRE] */
1750 tmp32_1 = tcg_temp_new_i32();
a4e3ad19 1751 tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r2]));
e023e832
AG
1752 store_reg32(r1, tmp32_1);
1753 tcg_temp_free_i32(tmp32_1);
1754 break;
e023e832
AG
1755 case 0x54: /* MVPG R1,R2 [RRE] */
1756 tmp = load_reg(0);
1757 tmp2 = load_reg(r1);
1758 tmp3 = load_reg(r2);
1759 potential_page_fault(s);
19b0516f 1760 gen_helper_mvpg(cpu_env, tmp, tmp2, tmp3);
e023e832
AG
1761 tcg_temp_free_i64(tmp);
1762 tcg_temp_free_i64(tmp2);
1763 tcg_temp_free_i64(tmp3);
1764 /* XXX check CCO bit and set CC accordingly */
1765 gen_op_movi_cc(s, 0);
1766 break;
1767 case 0x55: /* MVST R1,R2 [RRE] */
1768 tmp32_1 = load_reg32(0);
1769 tmp32_2 = tcg_const_i32(r1);
1770 tmp32_3 = tcg_const_i32(r2);
1771 potential_page_fault(s);
19b0516f 1772 gen_helper_mvst(cpu_env, tmp32_1, tmp32_2, tmp32_3);
e023e832
AG
1773 tcg_temp_free_i32(tmp32_1);
1774 tcg_temp_free_i32(tmp32_2);
1775 tcg_temp_free_i32(tmp32_3);
1776 gen_op_movi_cc(s, 1);
1777 break;
1778 case 0x5d: /* CLST R1,R2 [RRE] */
1779 tmp32_1 = load_reg32(0);
1780 tmp32_2 = tcg_const_i32(r1);
1781 tmp32_3 = tcg_const_i32(r2);
1782 potential_page_fault(s);
19b0516f 1783 gen_helper_clst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
e023e832
AG
1784 set_cc_static(s);
1785 tcg_temp_free_i32(tmp32_1);
1786 tcg_temp_free_i32(tmp32_2);
1787 tcg_temp_free_i32(tmp32_3);
1788 break;
1789 case 0x5e: /* SRST R1,R2 [RRE] */
1790 tmp32_1 = load_reg32(0);
1791 tmp32_2 = tcg_const_i32(r1);
1792 tmp32_3 = tcg_const_i32(r2);
1793 potential_page_fault(s);
19b0516f 1794 gen_helper_srst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
e023e832
AG
1795 set_cc_static(s);
1796 tcg_temp_free_i32(tmp32_1);
1797 tcg_temp_free_i32(tmp32_2);
1798 tcg_temp_free_i32(tmp32_3);
1799 break;
1800
1801#ifndef CONFIG_USER_ONLY
1802 case 0x02: /* STIDP D2(B2) [S] */
1803 /* Store CPU ID */
d5a103cd 1804 check_privileged(s);
e023e832
AG
1805 decode_rs(s, insn, &r1, &r3, &b2, &d2);
1806 tmp = get_address(s, 0, b2, d2);
1807 potential_page_fault(s);
089f5c06 1808 gen_helper_stidp(cpu_env, tmp);
e023e832
AG
1809 tcg_temp_free_i64(tmp);
1810 break;
1811 case 0x04: /* SCK D2(B2) [S] */
1812 /* Set Clock */
d5a103cd 1813 check_privileged(s);
e023e832
AG
1814 decode_rs(s, insn, &r1, &r3, &b2, &d2);
1815 tmp = get_address(s, 0, b2, d2);
1816 potential_page_fault(s);
1817 gen_helper_sck(cc_op, tmp);
1818 set_cc_static(s);
1819 tcg_temp_free_i64(tmp);
1820 break;
1821 case 0x05: /* STCK D2(B2) [S] */
1822 /* Store Clock */
1823 decode_rs(s, insn, &r1, &r3, &b2, &d2);
1824 tmp = get_address(s, 0, b2, d2);
1825 potential_page_fault(s);
089f5c06 1826 gen_helper_stck(cc_op, cpu_env, tmp);
e023e832
AG
1827 set_cc_static(s);
1828 tcg_temp_free_i64(tmp);
1829 break;
1830 case 0x06: /* SCKC D2(B2) [S] */
1831 /* Set Clock Comparator */
d5a103cd 1832 check_privileged(s);
e023e832
AG
1833 decode_rs(s, insn, &r1, &r3, &b2, &d2);
1834 tmp = get_address(s, 0, b2, d2);
1835 potential_page_fault(s);
089f5c06 1836 gen_helper_sckc(cpu_env, tmp);
e023e832
AG
1837 tcg_temp_free_i64(tmp);
1838 break;
1839 case 0x07: /* STCKC D2(B2) [S] */
1840 /* Store Clock Comparator */
d5a103cd 1841 check_privileged(s);
e023e832
AG
1842 decode_rs(s, insn, &r1, &r3, &b2, &d2);
1843 tmp = get_address(s, 0, b2, d2);
1844 potential_page_fault(s);
089f5c06 1845 gen_helper_stckc(cpu_env, tmp);
e023e832
AG
1846 tcg_temp_free_i64(tmp);
1847 break;
1848 case 0x08: /* SPT D2(B2) [S] */
1849 /* Set CPU Timer */
d5a103cd 1850 check_privileged(s);
e023e832
AG
1851 decode_rs(s, insn, &r1, &r3, &b2, &d2);
1852 tmp = get_address(s, 0, b2, d2);
1853 potential_page_fault(s);
089f5c06 1854 gen_helper_spt(cpu_env, tmp);
e023e832
AG
1855 tcg_temp_free_i64(tmp);
1856 break;
1857 case 0x09: /* STPT D2(B2) [S] */
1858 /* Store CPU Timer */
d5a103cd 1859 check_privileged(s);
e023e832
AG
1860 decode_rs(s, insn, &r1, &r3, &b2, &d2);
1861 tmp = get_address(s, 0, b2, d2);
1862 potential_page_fault(s);
089f5c06 1863 gen_helper_stpt(cpu_env, tmp);
e023e832
AG
1864 tcg_temp_free_i64(tmp);
1865 break;
1866 case 0x0a: /* SPKA D2(B2) [S] */
1867 /* Set PSW Key from Address */
d5a103cd 1868 check_privileged(s);
e023e832
AG
1869 decode_rs(s, insn, &r1, &r3, &b2, &d2);
1870 tmp = get_address(s, 0, b2, d2);
1871 tmp2 = tcg_temp_new_i64();
1872 tcg_gen_andi_i64(tmp2, psw_mask, ~PSW_MASK_KEY);
1873 tcg_gen_shli_i64(tmp, tmp, PSW_SHIFT_KEY - 4);
1874 tcg_gen_or_i64(psw_mask, tmp2, tmp);
1875 tcg_temp_free_i64(tmp2);
1876 tcg_temp_free_i64(tmp);
1877 break;
1878 case 0x0d: /* PTLB [S] */
1879 /* Purge TLB */
d5a103cd 1880 check_privileged(s);
19b0516f 1881 gen_helper_ptlb(cpu_env);
e023e832
AG
1882 break;
1883 case 0x10: /* SPX D2(B2) [S] */
1884 /* Set Prefix Register */
d5a103cd 1885 check_privileged(s);
e023e832
AG
1886 decode_rs(s, insn, &r1, &r3, &b2, &d2);
1887 tmp = get_address(s, 0, b2, d2);
1888 potential_page_fault(s);
089f5c06 1889 gen_helper_spx(cpu_env, tmp);
e023e832
AG
1890 tcg_temp_free_i64(tmp);
1891 break;
1892 case 0x11: /* STPX D2(B2) [S] */
1893 /* Store Prefix */
d5a103cd 1894 check_privileged(s);
e023e832
AG
1895 decode_rs(s, insn, &r1, &r3, &b2, &d2);
1896 tmp = get_address(s, 0, b2, d2);
1897 tmp2 = tcg_temp_new_i64();
a4e3ad19 1898 tcg_gen_ld_i64(tmp2, cpu_env, offsetof(CPUS390XState, psa));
e023e832
AG
1899 tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
1900 tcg_temp_free_i64(tmp);
1901 tcg_temp_free_i64(tmp2);
1902 break;
1903 case 0x12: /* STAP D2(B2) [S] */
1904 /* Store CPU Address */
d5a103cd 1905 check_privileged(s);
e023e832
AG
1906 decode_rs(s, insn, &r1, &r3, &b2, &d2);
1907 tmp = get_address(s, 0, b2, d2);
1908 tmp2 = tcg_temp_new_i64();
1909 tmp32_1 = tcg_temp_new_i32();
a4e3ad19 1910 tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, cpu_num));
e023e832
AG
1911 tcg_gen_extu_i32_i64(tmp2, tmp32_1);
1912 tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
1913 tcg_temp_free_i64(tmp);
1914 tcg_temp_free_i64(tmp2);
1915 tcg_temp_free_i32(tmp32_1);
1916 break;
1917 case 0x21: /* IPTE R1,R2 [RRE] */
1918 /* Invalidate PTE */
d5a103cd 1919 check_privileged(s);
e023e832
AG
1920 r1 = (insn >> 4) & 0xf;
1921 r2 = insn & 0xf;
1922 tmp = load_reg(r1);
1923 tmp2 = load_reg(r2);
19b0516f 1924 gen_helper_ipte(cpu_env, tmp, tmp2);
e023e832
AG
1925 tcg_temp_free_i64(tmp);
1926 tcg_temp_free_i64(tmp2);
1927 break;
1928 case 0x29: /* ISKE R1,R2 [RRE] */
1929 /* Insert Storage Key Extended */
d5a103cd 1930 check_privileged(s);
e023e832
AG
1931 r1 = (insn >> 4) & 0xf;
1932 r2 = insn & 0xf;
1933 tmp = load_reg(r2);
1934 tmp2 = tcg_temp_new_i64();
19b0516f 1935 gen_helper_iske(tmp2, cpu_env, tmp);
e023e832
AG
1936 store_reg(r1, tmp2);
1937 tcg_temp_free_i64(tmp);
1938 tcg_temp_free_i64(tmp2);
1939 break;
1940 case 0x2a: /* RRBE R1,R2 [RRE] */
1941 /* Set Storage Key Extended */
d5a103cd 1942 check_privileged(s);
e023e832
AG
1943 r1 = (insn >> 4) & 0xf;
1944 r2 = insn & 0xf;
1945 tmp32_1 = load_reg32(r1);
1946 tmp = load_reg(r2);
19b0516f 1947 gen_helper_rrbe(cc_op, cpu_env, tmp32_1, tmp);
e023e832
AG
1948 set_cc_static(s);
1949 tcg_temp_free_i32(tmp32_1);
1950 tcg_temp_free_i64(tmp);
1951 break;
1952 case 0x2b: /* SSKE R1,R2 [RRE] */
1953 /* Set Storage Key Extended */
d5a103cd 1954 check_privileged(s);
e023e832
AG
1955 r1 = (insn >> 4) & 0xf;
1956 r2 = insn & 0xf;
1957 tmp32_1 = load_reg32(r1);
1958 tmp = load_reg(r2);
19b0516f 1959 gen_helper_sske(cpu_env, tmp32_1, tmp);
e023e832
AG
1960 tcg_temp_free_i32(tmp32_1);
1961 tcg_temp_free_i64(tmp);
1962 break;
1963 case 0x34: /* STCH ? */
1964 /* Store Subchannel */
d5a103cd 1965 check_privileged(s);
e023e832
AG
1966 gen_op_movi_cc(s, 3);
1967 break;
1968 case 0x46: /* STURA R1,R2 [RRE] */
1969 /* Store Using Real Address */
d5a103cd 1970 check_privileged(s);
e023e832
AG
1971 r1 = (insn >> 4) & 0xf;
1972 r2 = insn & 0xf;
1973 tmp32_1 = load_reg32(r1);
1974 tmp = load_reg(r2);
1975 potential_page_fault(s);
19b0516f 1976 gen_helper_stura(cpu_env, tmp, tmp32_1);
e023e832
AG
1977 tcg_temp_free_i32(tmp32_1);
1978 tcg_temp_free_i64(tmp);
1979 break;
1980 case 0x50: /* CSP R1,R2 [RRE] */
1981 /* Compare And Swap And Purge */
d5a103cd 1982 check_privileged(s);
e023e832
AG
1983 r1 = (insn >> 4) & 0xf;
1984 r2 = insn & 0xf;
1985 tmp32_1 = tcg_const_i32(r1);
1986 tmp32_2 = tcg_const_i32(r2);
19b0516f 1987 gen_helper_csp(cc_op, cpu_env, tmp32_1, tmp32_2);
e023e832
AG
1988 set_cc_static(s);
1989 tcg_temp_free_i32(tmp32_1);
1990 tcg_temp_free_i32(tmp32_2);
1991 break;
1992 case 0x5f: /* CHSC ? */
1993 /* Channel Subsystem Call */
d5a103cd 1994 check_privileged(s);
e023e832
AG
1995 gen_op_movi_cc(s, 3);
1996 break;
1997 case 0x78: /* STCKE D2(B2) [S] */
1998 /* Store Clock Extended */
1999 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2000 tmp = get_address(s, 0, b2, d2);
2001 potential_page_fault(s);
089f5c06 2002 gen_helper_stcke(cc_op, cpu_env, tmp);
e023e832
AG
2003 set_cc_static(s);
2004 tcg_temp_free_i64(tmp);
2005 break;
2006 case 0x79: /* SACF D2(B2) [S] */
afd43fec 2007 /* Set Address Space Control Fast */
d5a103cd 2008 check_privileged(s);
e023e832
AG
2009 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2010 tmp = get_address(s, 0, b2, d2);
2011 potential_page_fault(s);
932385a3 2012 gen_helper_sacf(cpu_env, tmp);
e023e832
AG
2013 tcg_temp_free_i64(tmp);
2014 /* addressing mode has changed, so end the block */
d5a103cd 2015 s->pc = s->next_pc;
e023e832 2016 update_psw_addr(s);
afd43fec 2017 s->is_jmp = DISAS_JUMP;
e023e832
AG
2018 break;
2019 case 0x7d: /* STSI D2,(B2) [S] */
d5a103cd 2020 check_privileged(s);
e023e832
AG
2021 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2022 tmp = get_address(s, 0, b2, d2);
2023 tmp32_1 = load_reg32(0);
2024 tmp32_2 = load_reg32(1);
2025 potential_page_fault(s);
089f5c06 2026 gen_helper_stsi(cc_op, cpu_env, tmp, tmp32_1, tmp32_2);
e023e832
AG
2027 set_cc_static(s);
2028 tcg_temp_free_i64(tmp);
2029 tcg_temp_free_i32(tmp32_1);
2030 tcg_temp_free_i32(tmp32_2);
2031 break;
2032 case 0x9d: /* LFPC D2(B2) [S] */
2033 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2034 tmp = get_address(s, 0, b2, d2);
2035 tmp2 = tcg_temp_new_i64();
2036 tmp32_1 = tcg_temp_new_i32();
2037 tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
2038 tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
a4e3ad19 2039 tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
e023e832
AG
2040 tcg_temp_free_i64(tmp);
2041 tcg_temp_free_i64(tmp2);
2042 tcg_temp_free_i32(tmp32_1);
2043 break;
2044 case 0xb1: /* STFL D2(B2) [S] */
2045 /* Store Facility List (CPU features) at 200 */
d5a103cd 2046 check_privileged(s);
e023e832
AG
2047 tmp2 = tcg_const_i64(0xc0000000);
2048 tmp = tcg_const_i64(200);
2049 tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
2050 tcg_temp_free_i64(tmp2);
2051 tcg_temp_free_i64(tmp);
2052 break;
2053 case 0xb2: /* LPSWE D2(B2) [S] */
2054 /* Load PSW Extended */
d5a103cd 2055 check_privileged(s);
e023e832
AG
2056 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2057 tmp = get_address(s, 0, b2, d2);
2058 tmp2 = tcg_temp_new_i64();
2059 tmp3 = tcg_temp_new_i64();
2060 tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
2061 tcg_gen_addi_i64(tmp, tmp, 8);
2062 tcg_gen_qemu_ld64(tmp3, tmp, get_mem_index(s));
932385a3 2063 gen_helper_load_psw(cpu_env, tmp2, tmp3);
e023e832
AG
2064 /* we need to keep cc_op intact */
2065 s->is_jmp = DISAS_JUMP;
2066 tcg_temp_free_i64(tmp);
e32a1832
SW
2067 tcg_temp_free_i64(tmp2);
2068 tcg_temp_free_i64(tmp3);
e023e832
AG
2069 break;
2070 case 0x20: /* SERVC R1,R2 [RRE] */
2071 /* SCLP Service call (PV hypercall) */
d5a103cd 2072 check_privileged(s);
e023e832
AG
2073 potential_page_fault(s);
2074 tmp32_1 = load_reg32(r2);
2075 tmp = load_reg(r1);
089f5c06 2076 gen_helper_servc(cc_op, cpu_env, tmp32_1, tmp);
e023e832
AG
2077 set_cc_static(s);
2078 tcg_temp_free_i32(tmp32_1);
2079 tcg_temp_free_i64(tmp);
2080 break;
2081#endif
2082 default:
2083 LOG_DISAS("illegal b2 operation 0x%x\n", op);
d5a103cd 2084 gen_illegal_opcode(s);
e023e832
AG
2085 break;
2086 }
2087}
2088
46ee3d84
BS
2089static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
2090 int r1, int r2)
e023e832
AG
2091{
2092 TCGv_i64 tmp;
2093 TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
2094 LOG_DISAS("disas_b3: op 0x%x m3 0x%x r1 %d r2 %d\n", op, m3, r1, r2);
2095#define FP_HELPER(i) \
2096 tmp32_1 = tcg_const_i32(r1); \
2097 tmp32_2 = tcg_const_i32(r2); \
449c0d70 2098 gen_helper_ ## i(cpu_env, tmp32_1, tmp32_2); \
e023e832
AG
2099 tcg_temp_free_i32(tmp32_1); \
2100 tcg_temp_free_i32(tmp32_2);
2101
2102#define FP_HELPER_CC(i) \
2103 tmp32_1 = tcg_const_i32(r1); \
2104 tmp32_2 = tcg_const_i32(r2); \
449c0d70 2105 gen_helper_ ## i(cc_op, cpu_env, tmp32_1, tmp32_2); \
e023e832
AG
2106 set_cc_static(s); \
2107 tcg_temp_free_i32(tmp32_1); \
2108 tcg_temp_free_i32(tmp32_2);
2109
2110 switch (op) {
2111 case 0x0: /* LPEBR R1,R2 [RRE] */
2112 FP_HELPER_CC(lpebr);
2113 break;
2114 case 0x2: /* LTEBR R1,R2 [RRE] */
2115 FP_HELPER_CC(ltebr);
2116 break;
2117 case 0x3: /* LCEBR R1,R2 [RRE] */
2118 FP_HELPER_CC(lcebr);
2119 break;
2120 case 0x4: /* LDEBR R1,R2 [RRE] */
2121 FP_HELPER(ldebr);
2122 break;
2123 case 0x5: /* LXDBR R1,R2 [RRE] */
2124 FP_HELPER(lxdbr);
2125 break;
2126 case 0x9: /* CEBR R1,R2 [RRE] */
2127 FP_HELPER_CC(cebr);
2128 break;
2129 case 0xa: /* AEBR R1,R2 [RRE] */
2130 FP_HELPER_CC(aebr);
2131 break;
2132 case 0xb: /* SEBR R1,R2 [RRE] */
2133 FP_HELPER_CC(sebr);
2134 break;
2135 case 0xd: /* DEBR R1,R2 [RRE] */
2136 FP_HELPER(debr);
2137 break;
2138 case 0x10: /* LPDBR R1,R2 [RRE] */
2139 FP_HELPER_CC(lpdbr);
2140 break;
2141 case 0x12: /* LTDBR R1,R2 [RRE] */
2142 FP_HELPER_CC(ltdbr);
2143 break;
2144 case 0x13: /* LCDBR R1,R2 [RRE] */
2145 FP_HELPER_CC(lcdbr);
2146 break;
2147 case 0x15: /* SQBDR R1,R2 [RRE] */
2148 FP_HELPER(sqdbr);
2149 break;
2150 case 0x17: /* MEEBR R1,R2 [RRE] */
2151 FP_HELPER(meebr);
2152 break;
2153 case 0x19: /* CDBR R1,R2 [RRE] */
2154 FP_HELPER_CC(cdbr);
2155 break;
2156 case 0x1a: /* ADBR R1,R2 [RRE] */
2157 FP_HELPER_CC(adbr);
2158 break;
2159 case 0x1b: /* SDBR R1,R2 [RRE] */
2160 FP_HELPER_CC(sdbr);
2161 break;
2162 case 0x1c: /* MDBR R1,R2 [RRE] */
2163 FP_HELPER(mdbr);
2164 break;
2165 case 0x1d: /* DDBR R1,R2 [RRE] */
2166 FP_HELPER(ddbr);
2167 break;
2168 case 0xe: /* MAEBR R1,R3,R2 [RRF] */
2169 case 0x1e: /* MADBR R1,R3,R2 [RRF] */
2170 case 0x1f: /* MSDBR R1,R3,R2 [RRF] */
2171 /* for RRF insns, m3 is R1, r1 is R3, and r2 is R2 */
2172 tmp32_1 = tcg_const_i32(m3);
2173 tmp32_2 = tcg_const_i32(r2);
2174 tmp32_3 = tcg_const_i32(r1);
2175 switch (op) {
2176 case 0xe:
449c0d70 2177 gen_helper_maebr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
e023e832
AG
2178 break;
2179 case 0x1e:
449c0d70 2180 gen_helper_madbr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
e023e832
AG
2181 break;
2182 case 0x1f:
449c0d70 2183 gen_helper_msdbr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
e023e832
AG
2184 break;
2185 default:
2186 tcg_abort();
2187 }
2188 tcg_temp_free_i32(tmp32_1);
2189 tcg_temp_free_i32(tmp32_2);
2190 tcg_temp_free_i32(tmp32_3);
2191 break;
2192 case 0x40: /* LPXBR R1,R2 [RRE] */
2193 FP_HELPER_CC(lpxbr);
2194 break;
2195 case 0x42: /* LTXBR R1,R2 [RRE] */
2196 FP_HELPER_CC(ltxbr);
2197 break;
2198 case 0x43: /* LCXBR R1,R2 [RRE] */
2199 FP_HELPER_CC(lcxbr);
2200 break;
2201 case 0x44: /* LEDBR R1,R2 [RRE] */
2202 FP_HELPER(ledbr);
2203 break;
2204 case 0x45: /* LDXBR R1,R2 [RRE] */
2205 FP_HELPER(ldxbr);
2206 break;
2207 case 0x46: /* LEXBR R1,R2 [RRE] */
2208 FP_HELPER(lexbr);
2209 break;
2210 case 0x49: /* CXBR R1,R2 [RRE] */
2211 FP_HELPER_CC(cxbr);
2212 break;
2213 case 0x4a: /* AXBR R1,R2 [RRE] */
2214 FP_HELPER_CC(axbr);
2215 break;
2216 case 0x4b: /* SXBR R1,R2 [RRE] */
2217 FP_HELPER_CC(sxbr);
2218 break;
2219 case 0x4c: /* MXBR R1,R2 [RRE] */
2220 FP_HELPER(mxbr);
2221 break;
2222 case 0x4d: /* DXBR R1,R2 [RRE] */
2223 FP_HELPER(dxbr);
2224 break;
2225 case 0x65: /* LXR R1,R2 [RRE] */
2226 tmp = load_freg(r2);
2227 store_freg(r1, tmp);
2228 tcg_temp_free_i64(tmp);
2229 tmp = load_freg(r2 + 2);
2230 store_freg(r1 + 2, tmp);
2231 tcg_temp_free_i64(tmp);
2232 break;
2233 case 0x74: /* LZER R1 [RRE] */
2234 tmp32_1 = tcg_const_i32(r1);
449c0d70 2235 gen_helper_lzer(cpu_env, tmp32_1);
e023e832
AG
2236 tcg_temp_free_i32(tmp32_1);
2237 break;
2238 case 0x75: /* LZDR R1 [RRE] */
2239 tmp32_1 = tcg_const_i32(r1);
449c0d70 2240 gen_helper_lzdr(cpu_env, tmp32_1);
e023e832
AG
2241 tcg_temp_free_i32(tmp32_1);
2242 break;
2243 case 0x76: /* LZXR R1 [RRE] */
2244 tmp32_1 = tcg_const_i32(r1);
449c0d70 2245 gen_helper_lzxr(cpu_env, tmp32_1);
e023e832
AG
2246 tcg_temp_free_i32(tmp32_1);
2247 break;
2248 case 0x84: /* SFPC R1 [RRE] */
2249 tmp32_1 = load_reg32(r1);
a4e3ad19 2250 tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
e023e832
AG
2251 tcg_temp_free_i32(tmp32_1);
2252 break;
2253 case 0x8c: /* EFPC R1 [RRE] */
2254 tmp32_1 = tcg_temp_new_i32();
a4e3ad19 2255 tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
e023e832
AG
2256 store_reg32(r1, tmp32_1);
2257 tcg_temp_free_i32(tmp32_1);
2258 break;
2259 case 0x94: /* CEFBR R1,R2 [RRE] */
2260 case 0x95: /* CDFBR R1,R2 [RRE] */
2261 case 0x96: /* CXFBR R1,R2 [RRE] */
2262 tmp32_1 = tcg_const_i32(r1);
2263 tmp32_2 = load_reg32(r2);
2264 switch (op) {
2265 case 0x94:
449c0d70 2266 gen_helper_cefbr(cpu_env, tmp32_1, tmp32_2);
e023e832
AG
2267 break;
2268 case 0x95:
449c0d70 2269 gen_helper_cdfbr(cpu_env, tmp32_1, tmp32_2);
e023e832
AG
2270 break;
2271 case 0x96:
449c0d70 2272 gen_helper_cxfbr(cpu_env, tmp32_1, tmp32_2);
e023e832
AG
2273 break;
2274 default:
2275 tcg_abort();
2276 }
2277 tcg_temp_free_i32(tmp32_1);
2278 tcg_temp_free_i32(tmp32_2);
2279 break;
2280 case 0x98: /* CFEBR R1,R2 [RRE] */
2281 case 0x99: /* CFDBR R1,R2 [RRE] */
2282 case 0x9a: /* CFXBR R1,R2 [RRE] */
2283 tmp32_1 = tcg_const_i32(r1);
2284 tmp32_2 = tcg_const_i32(r2);
2285 tmp32_3 = tcg_const_i32(m3);
2286 switch (op) {
2287 case 0x98:
449c0d70 2288 gen_helper_cfebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
e023e832
AG
2289 break;
2290 case 0x99:
449c0d70 2291 gen_helper_cfdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
e023e832
AG
2292 break;
2293 case 0x9a:
449c0d70 2294 gen_helper_cfxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
e023e832
AG
2295 break;
2296 default:
2297 tcg_abort();
2298 }
2299 set_cc_static(s);
2300 tcg_temp_free_i32(tmp32_1);
2301 tcg_temp_free_i32(tmp32_2);
2302 tcg_temp_free_i32(tmp32_3);
2303 break;
2304 case 0xa4: /* CEGBR R1,R2 [RRE] */
2305 case 0xa5: /* CDGBR R1,R2 [RRE] */
2306 tmp32_1 = tcg_const_i32(r1);
2307 tmp = load_reg(r2);
2308 switch (op) {
2309 case 0xa4:
449c0d70 2310 gen_helper_cegbr(cpu_env, tmp32_1, tmp);
e023e832
AG
2311 break;
2312 case 0xa5:
449c0d70 2313 gen_helper_cdgbr(cpu_env, tmp32_1, tmp);
e023e832
AG
2314 break;
2315 default:
2316 tcg_abort();
2317 }
2318 tcg_temp_free_i32(tmp32_1);
2319 tcg_temp_free_i64(tmp);
2320 break;
2321 case 0xa6: /* CXGBR R1,R2 [RRE] */
2322 tmp32_1 = tcg_const_i32(r1);
2323 tmp = load_reg(r2);
449c0d70 2324 gen_helper_cxgbr(cpu_env, tmp32_1, tmp);
e023e832
AG
2325 tcg_temp_free_i32(tmp32_1);
2326 tcg_temp_free_i64(tmp);
2327 break;
2328 case 0xa8: /* CGEBR R1,R2 [RRE] */
2329 tmp32_1 = tcg_const_i32(r1);
2330 tmp32_2 = tcg_const_i32(r2);
2331 tmp32_3 = tcg_const_i32(m3);
449c0d70 2332 gen_helper_cgebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
e023e832
AG
2333 set_cc_static(s);
2334 tcg_temp_free_i32(tmp32_1);
2335 tcg_temp_free_i32(tmp32_2);
2336 tcg_temp_free_i32(tmp32_3);
2337 break;
2338 case 0xa9: /* CGDBR R1,R2 [RRE] */
2339 tmp32_1 = tcg_const_i32(r1);
2340 tmp32_2 = tcg_const_i32(r2);
2341 tmp32_3 = tcg_const_i32(m3);
449c0d70 2342 gen_helper_cgdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
e023e832
AG
2343 set_cc_static(s);
2344 tcg_temp_free_i32(tmp32_1);
2345 tcg_temp_free_i32(tmp32_2);
2346 tcg_temp_free_i32(tmp32_3);
2347 break;
2348 case 0xaa: /* CGXBR R1,R2 [RRE] */
2349 tmp32_1 = tcg_const_i32(r1);
2350 tmp32_2 = tcg_const_i32(r2);
2351 tmp32_3 = tcg_const_i32(m3);
449c0d70 2352 gen_helper_cgxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
e023e832
AG
2353 set_cc_static(s);
2354 tcg_temp_free_i32(tmp32_1);
2355 tcg_temp_free_i32(tmp32_2);
2356 tcg_temp_free_i32(tmp32_3);
2357 break;
2358 default:
2359 LOG_DISAS("illegal b3 operation 0x%x\n", op);
d5a103cd 2360 gen_illegal_opcode(s);
e023e832
AG
2361 break;
2362 }
2363
2364#undef FP_HELPER_CC
2365#undef FP_HELPER
2366}
2367
46ee3d84
BS
2368static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
2369 int r2)
e023e832 2370{
891452e5 2371 TCGv_i64 tmp;
4e4bb438 2372 TCGv_i32 tmp32_1;
e023e832
AG
2373
2374 LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
2375 switch (op) {
e023e832
AG
2376 case 0x17: /* LLGTR R1,R2 [RRE] */
2377 tmp32_1 = load_reg32(r2);
2378 tmp = tcg_temp_new_i64();
2379 tcg_gen_andi_i32(tmp32_1, tmp32_1, 0x7fffffffUL);
2380 tcg_gen_extu_i32_i64(tmp, tmp32_1);
2381 store_reg(r1, tmp);
2382 tcg_temp_free_i32(tmp32_1);
2383 tcg_temp_free_i64(tmp);
2384 break;
e1b45cca
AG
2385 case 0x0f: /* LRVGR R1,R2 [RRE] */
2386 tcg_gen_bswap64_i64(regs[r1], regs[r2]);
2387 break;
e023e832
AG
2388 case 0x1f: /* LRVR R1,R2 [RRE] */
2389 tmp32_1 = load_reg32(r2);
2390 tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
2391 store_reg32(r1, tmp32_1);
2392 tcg_temp_free_i32(tmp32_1);
2393 break;
e023e832
AG
2394 case 0x83: /* FLOGR R1,R2 [RRE] */
2395 tmp = load_reg(r2);
2396 tmp32_1 = tcg_const_i32(r1);
4fda26a7 2397 gen_helper_flogr(cc_op, cpu_env, tmp32_1, tmp);
e023e832
AG
2398 set_cc_static(s);
2399 tcg_temp_free_i64(tmp);
2400 tcg_temp_free_i32(tmp32_1);
2401 break;
e023e832
AG
2402 default:
2403 LOG_DISAS("illegal b9 operation 0x%x\n", op);
d5a103cd 2404 gen_illegal_opcode(s);
e023e832
AG
2405 break;
2406 }
2407}
2408
46ee3d84 2409static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
e023e832
AG
2410{
2411 TCGv_i64 tmp, tmp2, tmp3, tmp4;
2412 TCGv_i32 tmp32_1, tmp32_2, tmp32_3, tmp32_4;
2413 unsigned char opc;
2414 uint64_t insn;
2415 int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
2416 TCGv_i32 vl;
e023e832 2417
46ee3d84 2418 opc = cpu_ldub_code(env, s->pc);
e023e832
AG
2419 LOG_DISAS("opc 0x%x\n", opc);
2420
e023e832
AG
2421 switch (opc) {
2422#ifndef CONFIG_USER_ONLY
2423 case 0x01: /* SAM */
46ee3d84 2424 insn = ld_code2(env, s->pc);
e023e832
AG
2425 /* set addressing mode, but we only do 64bit anyways */
2426 break;
2427#endif
e023e832 2428 case 0xa: /* SVC I [RR] */
46ee3d84 2429 insn = ld_code2(env, s->pc);
e023e832
AG
2430 debug_insn(insn);
2431 i = insn & 0xff;
2432 update_psw_addr(s);
2433 gen_op_calc_cc(s);
2434 tmp32_1 = tcg_const_i32(i);
d5a103cd 2435 tmp32_2 = tcg_const_i32(s->next_pc - s->pc);
a4e3ad19 2436 tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code));
d5a103cd
RH
2437 tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
2438 gen_exception(EXCP_SVC);
e023e832
AG
2439 s->is_jmp = DISAS_EXCP;
2440 tcg_temp_free_i32(tmp32_1);
2441 tcg_temp_free_i32(tmp32_2);
e023e832 2442 break;
e023e832 2443 case 0xe: /* MVCL R1,R2 [RR] */
46ee3d84 2444 insn = ld_code2(env, s->pc);
e023e832
AG
2445 decode_rr(s, insn, &r1, &r2);
2446 tmp32_1 = tcg_const_i32(r1);
2447 tmp32_2 = tcg_const_i32(r2);
2448 potential_page_fault(s);
19b0516f 2449 gen_helper_mvcl(cc_op, cpu_env, tmp32_1, tmp32_2);
e023e832
AG
2450 set_cc_static(s);
2451 tcg_temp_free_i32(tmp32_1);
2452 tcg_temp_free_i32(tmp32_2);
2453 break;
e023e832 2454 case 0x28: /* LDR R1,R2 [RR] */
46ee3d84 2455 insn = ld_code2(env, s->pc);
e023e832
AG
2456 decode_rr(s, insn, &r1, &r2);
2457 tmp = load_freg(r2);
2458 store_freg(r1, tmp);
2459 tcg_temp_free_i64(tmp);
2460 break;
2461 case 0x38: /* LER R1,R2 [RR] */
46ee3d84 2462 insn = ld_code2(env, s->pc);
e023e832
AG
2463 decode_rr(s, insn, &r1, &r2);
2464 tmp32_1 = load_freg32(r2);
2465 store_freg32(r1, tmp32_1);
2466 tcg_temp_free_i32(tmp32_1);
2467 break;
e023e832 2468 case 0x43: /* IC R1,D2(X2,B2) [RX] */
46ee3d84 2469 insn = ld_code4(env, s->pc);
e023e832
AG
2470 tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
2471 tmp2 = tcg_temp_new_i64();
2472 tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
2473 store_reg8(r1, tmp2);
2474 tcg_temp_free_i64(tmp);
2475 tcg_temp_free_i64(tmp2);
2476 break;
2477 case 0x44: /* EX R1,D2(X2,B2) [RX] */
46ee3d84 2478 insn = ld_code4(env, s->pc);
e023e832
AG
2479 tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
2480 tmp2 = load_reg(r1);
2481 tmp3 = tcg_const_i64(s->pc + 4);
2482 update_psw_addr(s);
2483 gen_op_calc_cc(s);
19b0516f 2484 gen_helper_ex(cc_op, cpu_env, cc_op, tmp2, tmp, tmp3);
e023e832
AG
2485 set_cc_static(s);
2486 tcg_temp_free_i64(tmp);
2487 tcg_temp_free_i64(tmp2);
2488 tcg_temp_free_i64(tmp3);
2489 break;
e023e832 2490 case 0x4e: /* CVD R1,D2(X2,B2) [RX] */
46ee3d84 2491 insn = ld_code4(env, s->pc);
e023e832
AG
2492 tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
2493 tmp2 = tcg_temp_new_i64();
2494 tmp32_1 = tcg_temp_new_i32();
2495 tcg_gen_trunc_i64_i32(tmp32_1, regs[r1]);
2496 gen_helper_cvd(tmp2, tmp32_1);
2497 tcg_gen_qemu_st64(tmp2, tmp, get_mem_index(s));
2498 tcg_temp_free_i64(tmp);
2499 tcg_temp_free_i64(tmp2);
2500 tcg_temp_free_i32(tmp32_1);
2501 break;
e023e832 2502 case 0x60: /* STD R1,D2(X2,B2) [RX] */
46ee3d84 2503 insn = ld_code4(env, s->pc);
e023e832
AG
2504 tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
2505 tmp2 = load_freg(r1);
2506 tcg_gen_qemu_st64(tmp2, tmp, get_mem_index(s));
2507 tcg_temp_free_i64(tmp);
2508 tcg_temp_free_i64(tmp2);
2509 break;
2510 case 0x68: /* LD R1,D2(X2,B2) [RX] */
46ee3d84 2511 insn = ld_code4(env, s->pc);
e023e832
AG
2512 tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
2513 tmp2 = tcg_temp_new_i64();
2514 tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
2515 store_freg(r1, tmp2);
2516 tcg_temp_free_i64(tmp);
2517 tcg_temp_free_i64(tmp2);
2518 break;
2519 case 0x70: /* STE R1,D2(X2,B2) [RX] */
46ee3d84 2520 insn = ld_code4(env, s->pc);
e023e832
AG
2521 tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
2522 tmp2 = tcg_temp_new_i64();
2523 tmp32_1 = load_freg32(r1);
2524 tcg_gen_extu_i32_i64(tmp2, tmp32_1);
2525 tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
2526 tcg_temp_free_i64(tmp);
2527 tcg_temp_free_i64(tmp2);
2528 tcg_temp_free_i32(tmp32_1);
2529 break;
e023e832 2530 case 0x78: /* LE R1,D2(X2,B2) [RX] */
46ee3d84 2531 insn = ld_code4(env, s->pc);
e023e832
AG
2532 tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
2533 tmp2 = tcg_temp_new_i64();
2534 tmp32_1 = tcg_temp_new_i32();
2535 tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
2536 tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
2537 store_freg32(r1, tmp32_1);
2538 tcg_temp_free_i64(tmp);
2539 tcg_temp_free_i64(tmp2);
2540 tcg_temp_free_i32(tmp32_1);
2541 break;
2542#ifndef CONFIG_USER_ONLY
2543 case 0x80: /* SSM D2(B2) [S] */
2544 /* Set System Mask */
d5a103cd 2545 check_privileged(s);
46ee3d84 2546 insn = ld_code4(env, s->pc);
e023e832
AG
2547 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2548 tmp = get_address(s, 0, b2, d2);
2549 tmp2 = tcg_temp_new_i64();
2550 tmp3 = tcg_temp_new_i64();
2551 tcg_gen_andi_i64(tmp3, psw_mask, ~0xff00000000000000ULL);
2552 tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
2553 tcg_gen_shli_i64(tmp2, tmp2, 56);
2554 tcg_gen_or_i64(psw_mask, tmp3, tmp2);
2555 tcg_temp_free_i64(tmp);
2556 tcg_temp_free_i64(tmp2);
2557 tcg_temp_free_i64(tmp3);
2558 break;
2559 case 0x82: /* LPSW D2(B2) [S] */
2560 /* Load PSW */
d5a103cd 2561 check_privileged(s);
46ee3d84 2562 insn = ld_code4(env, s->pc);
e023e832
AG
2563 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2564 tmp = get_address(s, 0, b2, d2);
2565 tmp2 = tcg_temp_new_i64();
2566 tmp3 = tcg_temp_new_i64();
2567 tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
2568 tcg_gen_addi_i64(tmp, tmp, 4);
2569 tcg_gen_qemu_ld32u(tmp3, tmp, get_mem_index(s));
51855ecf
RH
2570 /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */
2571 tcg_gen_shli_i64(tmp2, tmp2, 32);
932385a3 2572 gen_helper_load_psw(cpu_env, tmp2, tmp3);
e023e832
AG
2573 tcg_temp_free_i64(tmp);
2574 tcg_temp_free_i64(tmp2);
2575 tcg_temp_free_i64(tmp3);
2576 /* we need to keep cc_op intact */
2577 s->is_jmp = DISAS_JUMP;
2578 break;
2579 case 0x83: /* DIAG R1,R3,D2 [RS] */
2580 /* Diagnose call (KVM hypercall) */
d5a103cd 2581 check_privileged(s);
e023e832 2582 potential_page_fault(s);
46ee3d84 2583 insn = ld_code4(env, s->pc);
e023e832
AG
2584 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2585 tmp32_1 = tcg_const_i32(insn & 0xfff);
2586 tmp2 = load_reg(2);
2587 tmp3 = load_reg(1);
089f5c06 2588 gen_helper_diag(tmp2, cpu_env, tmp32_1, tmp2, tmp3);
e023e832
AG
2589 store_reg(2, tmp2);
2590 tcg_temp_free_i32(tmp32_1);
2591 tcg_temp_free_i64(tmp2);
2592 tcg_temp_free_i64(tmp3);
2593 break;
2594#endif
2595 case 0x88: /* SRL R1,D2(B2) [RS] */
2596 case 0x89: /* SLL R1,D2(B2) [RS] */
2597 case 0x8a: /* SRA R1,D2(B2) [RS] */
46ee3d84 2598 insn = ld_code4(env, s->pc);
e023e832
AG
2599 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2600 tmp = get_address(s, 0, b2, d2);
2601 tmp32_1 = load_reg32(r1);
2602 tmp32_2 = tcg_temp_new_i32();
2603 tcg_gen_trunc_i64_i32(tmp32_2, tmp);
2604 tcg_gen_andi_i32(tmp32_2, tmp32_2, 0x3f);
2605 switch (opc) {
2606 case 0x88:
2607 tcg_gen_shr_i32(tmp32_1, tmp32_1, tmp32_2);
2608 break;
2609 case 0x89:
2610 tcg_gen_shl_i32(tmp32_1, tmp32_1, tmp32_2);
2611 break;
2612 case 0x8a:
2613 tcg_gen_sar_i32(tmp32_1, tmp32_1, tmp32_2);
2614 set_cc_s32(s, tmp32_1);
2615 break;
2616 default:
2617 tcg_abort();
2618 }
2619 store_reg32(r1, tmp32_1);
2620 tcg_temp_free_i64(tmp);
2621 tcg_temp_free_i32(tmp32_1);
2622 tcg_temp_free_i32(tmp32_2);
2623 break;
2624 case 0x8c: /* SRDL R1,D2(B2) [RS] */
2625 case 0x8d: /* SLDL R1,D2(B2) [RS] */
2626 case 0x8e: /* SRDA R1,D2(B2) [RS] */
46ee3d84 2627 insn = ld_code4(env, s->pc);
e023e832
AG
2628 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2629 tmp = get_address(s, 0, b2, d2); /* shift */
2630 tmp2 = tcg_temp_new_i64();
2631 tmp32_1 = load_reg32(r1);
2632 tmp32_2 = load_reg32(r1 + 1);
2633 tcg_gen_concat_i32_i64(tmp2, tmp32_2, tmp32_1); /* operand */
2634 switch (opc) {
2635 case 0x8c:
2636 tcg_gen_shr_i64(tmp2, tmp2, tmp);
2637 break;
2638 case 0x8d:
2639 tcg_gen_shl_i64(tmp2, tmp2, tmp);
2640 break;
2641 case 0x8e:
2642 tcg_gen_sar_i64(tmp2, tmp2, tmp);
2643 set_cc_s64(s, tmp2);
2644 break;
2645 }
2646 tcg_gen_shri_i64(tmp, tmp2, 32);
2647 tcg_gen_trunc_i64_i32(tmp32_1, tmp);
2648 store_reg32(r1, tmp32_1);
2649 tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
2650 store_reg32(r1 + 1, tmp32_2);
225b6af7
SW
2651 tcg_temp_free_i64(tmp);
2652 tcg_temp_free_i64(tmp2);
e023e832
AG
2653 break;
2654 case 0x98: /* LM R1,R3,D2(B2) [RS] */
2655 case 0x90: /* STM R1,R3,D2(B2) [RS] */
46ee3d84 2656 insn = ld_code4(env, s->pc);
e023e832
AG
2657 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2658
2659 tmp = get_address(s, 0, b2, d2);
2660 tmp2 = tcg_temp_new_i64();
2661 tmp3 = tcg_const_i64(4);
2662 tmp4 = tcg_const_i64(0xffffffff00000000ULL);
2663 for (i = r1;; i = (i + 1) % 16) {
2664 if (opc == 0x98) {
2665 tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
2666 tcg_gen_and_i64(regs[i], regs[i], tmp4);
2667 tcg_gen_or_i64(regs[i], regs[i], tmp2);
2668 } else {
2669 tcg_gen_qemu_st32(regs[i], tmp, get_mem_index(s));
2670 }
2671 if (i == r3) {
2672 break;
2673 }
2674 tcg_gen_add_i64(tmp, tmp, tmp3);
2675 }
bbf9f3b4 2676 tcg_temp_free_i64(tmp);
e023e832
AG
2677 tcg_temp_free_i64(tmp2);
2678 tcg_temp_free_i64(tmp3);
2679 tcg_temp_free_i64(tmp4);
2680 break;
2681 case 0x91: /* TM D1(B1),I2 [SI] */
46ee3d84 2682 insn = ld_code4(env, s->pc);
e023e832
AG
2683 tmp = decode_si(s, insn, &i2, &b1, &d1);
2684 tmp2 = tcg_const_i64(i2);
2685 tcg_gen_qemu_ld8u(tmp, tmp, get_mem_index(s));
2686 cmp_64(s, tmp, tmp2, CC_OP_TM_32);
2687 tcg_temp_free_i64(tmp);
2688 tcg_temp_free_i64(tmp2);
2689 break;
2690 case 0x92: /* MVI D1(B1),I2 [SI] */
46ee3d84 2691 insn = ld_code4(env, s->pc);
e023e832
AG
2692 tmp = decode_si(s, insn, &i2, &b1, &d1);
2693 tmp2 = tcg_const_i64(i2);
2694 tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
2695 tcg_temp_free_i64(tmp);
2696 tcg_temp_free_i64(tmp2);
2697 break;
2698 case 0x94: /* NI D1(B1),I2 [SI] */
2699 case 0x96: /* OI D1(B1),I2 [SI] */
2700 case 0x97: /* XI D1(B1),I2 [SI] */
46ee3d84 2701 insn = ld_code4(env, s->pc);
e023e832
AG
2702 tmp = decode_si(s, insn, &i2, &b1, &d1);
2703 tmp2 = tcg_temp_new_i64();
2704 tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
2705 switch (opc) {
2706 case 0x94:
2707 tcg_gen_andi_i64(tmp2, tmp2, i2);
2708 break;
2709 case 0x96:
2710 tcg_gen_ori_i64(tmp2, tmp2, i2);
2711 break;
2712 case 0x97:
2713 tcg_gen_xori_i64(tmp2, tmp2, i2);
2714 break;
2715 default:
2716 tcg_abort();
2717 }
2718 tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
2719 set_cc_nz_u64(s, tmp2);
2720 tcg_temp_free_i64(tmp);
2721 tcg_temp_free_i64(tmp2);
2722 break;
e023e832 2723 case 0x9a: /* LAM R1,R3,D2(B2) [RS] */
46ee3d84 2724 insn = ld_code4(env, s->pc);
e023e832
AG
2725 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2726 tmp = get_address(s, 0, b2, d2);
2727 tmp32_1 = tcg_const_i32(r1);
2728 tmp32_2 = tcg_const_i32(r3);
2729 potential_page_fault(s);
19b0516f 2730 gen_helper_lam(cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
2731 tcg_temp_free_i64(tmp);
2732 tcg_temp_free_i32(tmp32_1);
2733 tcg_temp_free_i32(tmp32_2);
2734 break;
2735 case 0x9b: /* STAM R1,R3,D2(B2) [RS] */
46ee3d84 2736 insn = ld_code4(env, s->pc);
e023e832
AG
2737 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2738 tmp = get_address(s, 0, b2, d2);
2739 tmp32_1 = tcg_const_i32(r1);
2740 tmp32_2 = tcg_const_i32(r3);
2741 potential_page_fault(s);
19b0516f 2742 gen_helper_stam(cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
2743 tcg_temp_free_i64(tmp);
2744 tcg_temp_free_i32(tmp32_1);
2745 tcg_temp_free_i32(tmp32_2);
2746 break;
e023e832 2747 case 0xa7:
46ee3d84 2748 insn = ld_code4(env, s->pc);
e023e832
AG
2749 r1 = (insn >> 20) & 0xf;
2750 op = (insn >> 16) & 0xf;
2751 i2 = (short)insn;
46ee3d84 2752 disas_a7(env, s, op, r1, i2);
e023e832
AG
2753 break;
2754 case 0xa8: /* MVCLE R1,R3,D2(B2) [RS] */
46ee3d84 2755 insn = ld_code4(env, s->pc);
e023e832
AG
2756 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2757 tmp = get_address(s, 0, b2, d2);
2758 tmp32_1 = tcg_const_i32(r1);
2759 tmp32_2 = tcg_const_i32(r3);
2760 potential_page_fault(s);
19b0516f 2761 gen_helper_mvcle(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
2762 set_cc_static(s);
2763 tcg_temp_free_i64(tmp);
2764 tcg_temp_free_i32(tmp32_1);
2765 tcg_temp_free_i32(tmp32_2);
2766 break;
2767 case 0xa9: /* CLCLE R1,R3,D2(B2) [RS] */
46ee3d84 2768 insn = ld_code4(env, s->pc);
e023e832
AG
2769 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2770 tmp = get_address(s, 0, b2, d2);
2771 tmp32_1 = tcg_const_i32(r1);
2772 tmp32_2 = tcg_const_i32(r3);
2773 potential_page_fault(s);
19b0516f 2774 gen_helper_clcle(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
2775 set_cc_static(s);
2776 tcg_temp_free_i64(tmp);
2777 tcg_temp_free_i32(tmp32_1);
2778 tcg_temp_free_i32(tmp32_2);
2779 break;
2780#ifndef CONFIG_USER_ONLY
2781 case 0xac: /* STNSM D1(B1),I2 [SI] */
2782 case 0xad: /* STOSM D1(B1),I2 [SI] */
d5a103cd 2783 check_privileged(s);
46ee3d84 2784 insn = ld_code4(env, s->pc);
e023e832
AG
2785 tmp = decode_si(s, insn, &i2, &b1, &d1);
2786 tmp2 = tcg_temp_new_i64();
2787 tcg_gen_shri_i64(tmp2, psw_mask, 56);
2788 tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
2789 if (opc == 0xac) {
2790 tcg_gen_andi_i64(psw_mask, psw_mask,
2791 ((uint64_t)i2 << 56) | 0x00ffffffffffffffULL);
2792 } else {
2793 tcg_gen_ori_i64(psw_mask, psw_mask, (uint64_t)i2 << 56);
2794 }
2795 tcg_temp_free_i64(tmp);
2796 tcg_temp_free_i64(tmp2);
2797 break;
2798 case 0xae: /* SIGP R1,R3,D2(B2) [RS] */
d5a103cd 2799 check_privileged(s);
46ee3d84 2800 insn = ld_code4(env, s->pc);
e023e832
AG
2801 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2802 tmp = get_address(s, 0, b2, d2);
2803 tmp2 = load_reg(r3);
2804 tmp32_1 = tcg_const_i32(r1);
2805 potential_page_fault(s);
089f5c06 2806 gen_helper_sigp(cc_op, cpu_env, tmp, tmp32_1, tmp2);
e023e832
AG
2807 set_cc_static(s);
2808 tcg_temp_free_i64(tmp);
2809 tcg_temp_free_i64(tmp2);
2810 tcg_temp_free_i32(tmp32_1);
2811 break;
2812 case 0xb1: /* LRA R1,D2(X2, B2) [RX] */
d5a103cd 2813 check_privileged(s);
46ee3d84 2814 insn = ld_code4(env, s->pc);
e023e832
AG
2815 tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
2816 tmp32_1 = tcg_const_i32(r1);
2817 potential_page_fault(s);
19b0516f 2818 gen_helper_lra(cc_op, cpu_env, tmp, tmp32_1);
e023e832
AG
2819 set_cc_static(s);
2820 tcg_temp_free_i64(tmp);
2821 tcg_temp_free_i32(tmp32_1);
2822 break;
2823#endif
2824 case 0xb2:
46ee3d84 2825 insn = ld_code4(env, s->pc);
e023e832
AG
2826 op = (insn >> 16) & 0xff;
2827 switch (op) {
2828 case 0x9c: /* STFPC D2(B2) [S] */
2829 d2 = insn & 0xfff;
2830 b2 = (insn >> 12) & 0xf;
2831 tmp32_1 = tcg_temp_new_i32();
2832 tmp = tcg_temp_new_i64();
2833 tmp2 = get_address(s, 0, b2, d2);
a4e3ad19 2834 tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
e023e832
AG
2835 tcg_gen_extu_i32_i64(tmp, tmp32_1);
2836 tcg_gen_qemu_st32(tmp, tmp2, get_mem_index(s));
2837 tcg_temp_free_i32(tmp32_1);
2838 tcg_temp_free_i64(tmp);
2839 tcg_temp_free_i64(tmp2);
2840 break;
2841 default:
46ee3d84 2842 disas_b2(env, s, op, insn);
e023e832
AG
2843 break;
2844 }
2845 break;
2846 case 0xb3:
46ee3d84 2847 insn = ld_code4(env, s->pc);
e023e832
AG
2848 op = (insn >> 16) & 0xff;
2849 r3 = (insn >> 12) & 0xf; /* aka m3 */
2850 r1 = (insn >> 4) & 0xf;
2851 r2 = insn & 0xf;
46ee3d84 2852 disas_b3(env, s, op, r3, r1, r2);
e023e832
AG
2853 break;
2854#ifndef CONFIG_USER_ONLY
2855 case 0xb6: /* STCTL R1,R3,D2(B2) [RS] */
2856 /* Store Control */
d5a103cd 2857 check_privileged(s);
46ee3d84 2858 insn = ld_code4(env, s->pc);
e023e832
AG
2859 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2860 tmp = get_address(s, 0, b2, d2);
2861 tmp32_1 = tcg_const_i32(r1);
2862 tmp32_2 = tcg_const_i32(r3);
2863 potential_page_fault(s);
19b0516f 2864 gen_helper_stctl(cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
2865 tcg_temp_free_i64(tmp);
2866 tcg_temp_free_i32(tmp32_1);
2867 tcg_temp_free_i32(tmp32_2);
2868 break;
2869 case 0xb7: /* LCTL R1,R3,D2(B2) [RS] */
2870 /* Load Control */
d5a103cd 2871 check_privileged(s);
46ee3d84 2872 insn = ld_code4(env, s->pc);
e023e832
AG
2873 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2874 tmp = get_address(s, 0, b2, d2);
2875 tmp32_1 = tcg_const_i32(r1);
2876 tmp32_2 = tcg_const_i32(r3);
2877 potential_page_fault(s);
19b0516f 2878 gen_helper_lctl(cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
2879 tcg_temp_free_i64(tmp);
2880 tcg_temp_free_i32(tmp32_1);
2881 tcg_temp_free_i32(tmp32_2);
2882 break;
2883#endif
2884 case 0xb9:
46ee3d84 2885 insn = ld_code4(env, s->pc);
e023e832
AG
2886 r1 = (insn >> 4) & 0xf;
2887 r2 = insn & 0xf;
2888 op = (insn >> 16) & 0xff;
46ee3d84 2889 disas_b9(env, s, op, r1, r2);
e023e832
AG
2890 break;
2891 case 0xba: /* CS R1,R3,D2(B2) [RS] */
46ee3d84 2892 insn = ld_code4(env, s->pc);
e023e832
AG
2893 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2894 tmp = get_address(s, 0, b2, d2);
2895 tmp32_1 = tcg_const_i32(r1);
2896 tmp32_2 = tcg_const_i32(r3);
2897 potential_page_fault(s);
19b0516f 2898 gen_helper_cs(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
e023e832
AG
2899 set_cc_static(s);
2900 tcg_temp_free_i64(tmp);
2901 tcg_temp_free_i32(tmp32_1);
2902 tcg_temp_free_i32(tmp32_2);
2903 break;
2904 case 0xbd: /* CLM R1,M3,D2(B2) [RS] */
46ee3d84 2905 insn = ld_code4(env, s->pc);
e023e832
AG
2906 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2907 tmp = get_address(s, 0, b2, d2);
2908 tmp32_1 = load_reg32(r1);
2909 tmp32_2 = tcg_const_i32(r3);
2910 potential_page_fault(s);
19b0516f 2911 gen_helper_clm(cc_op, cpu_env, tmp32_1, tmp32_2, tmp);
e023e832
AG
2912 set_cc_static(s);
2913 tcg_temp_free_i64(tmp);
2914 tcg_temp_free_i32(tmp32_1);
2915 tcg_temp_free_i32(tmp32_2);
2916 break;
2917 case 0xbe: /* STCM R1,M3,D2(B2) [RS] */
46ee3d84 2918 insn = ld_code4(env, s->pc);
e023e832
AG
2919 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2920 tmp = get_address(s, 0, b2, d2);
2921 tmp32_1 = load_reg32(r1);
2922 tmp32_2 = tcg_const_i32(r3);
2923 potential_page_fault(s);
19b0516f 2924 gen_helper_stcm(cpu_env, tmp32_1, tmp32_2, tmp);
e023e832
AG
2925 tcg_temp_free_i64(tmp);
2926 tcg_temp_free_i32(tmp32_1);
2927 tcg_temp_free_i32(tmp32_2);
2928 break;
2929 case 0xbf: /* ICM R1,M3,D2(B2) [RS] */
46ee3d84 2930 insn = ld_code4(env, s->pc);
e023e832
AG
2931 decode_rs(s, insn, &r1, &r3, &b2, &d2);
2932 if (r3 == 15) {
2933 /* effectively a 32-bit load */
2934 tmp = get_address(s, 0, b2, d2);
2935 tmp32_1 = tcg_temp_new_i32();
2936 tmp32_2 = tcg_const_i32(r3);
2937 tcg_gen_qemu_ld32u(tmp, tmp, get_mem_index(s));
2938 store_reg32_i64(r1, tmp);
2939 tcg_gen_trunc_i64_i32(tmp32_1, tmp);
2940 set_cc_icm(s, tmp32_2, tmp32_1);
2941 tcg_temp_free_i64(tmp);
2942 tcg_temp_free_i32(tmp32_1);
2943 tcg_temp_free_i32(tmp32_2);
2944 } else if (r3) {
2945 uint32_t mask = 0x00ffffffUL;
2946 uint32_t shift = 24;
2947 int m3 = r3;
2948 tmp = get_address(s, 0, b2, d2);
2949 tmp2 = tcg_temp_new_i64();
2950 tmp32_1 = load_reg32(r1);
2951 tmp32_2 = tcg_temp_new_i32();
2952 tmp32_3 = tcg_const_i32(r3);
2953 tmp32_4 = tcg_const_i32(0);
2954 while (m3) {
2955 if (m3 & 8) {
2956 tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
2957 tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
2958 if (shift) {
2959 tcg_gen_shli_i32(tmp32_2, tmp32_2, shift);
2960 }
2961 tcg_gen_andi_i32(tmp32_1, tmp32_1, mask);
2962 tcg_gen_or_i32(tmp32_1, tmp32_1, tmp32_2);
2963 tcg_gen_or_i32(tmp32_4, tmp32_4, tmp32_2);
2964 tcg_gen_addi_i64(tmp, tmp, 1);
2965 }
2966 m3 = (m3 << 1) & 0xf;
2967 mask = (mask >> 8) | 0xff000000UL;
2968 shift -= 8;
2969 }
2970 store_reg32(r1, tmp32_1);
2971 set_cc_icm(s, tmp32_3, tmp32_4);
2972 tcg_temp_free_i64(tmp);
2973 tcg_temp_free_i64(tmp2);
2974 tcg_temp_free_i32(tmp32_1);
2975 tcg_temp_free_i32(tmp32_2);
2976 tcg_temp_free_i32(tmp32_3);
2977 tcg_temp_free_i32(tmp32_4);
2978 } else {
2979 /* i.e. env->cc = 0 */
2980 gen_op_movi_cc(s, 0);
2981 }
2982 break;
e023e832
AG
2983 case 0xd2: /* MVC D1(L,B1),D2(B2) [SS] */
2984 case 0xd4: /* NC D1(L,B1),D2(B2) [SS] */
2985 case 0xd5: /* CLC D1(L,B1),D2(B2) [SS] */
2986 case 0xd6: /* OC D1(L,B1),D2(B2) [SS] */
2987 case 0xd7: /* XC D1(L,B1),D2(B2) [SS] */
2988 case 0xdc: /* TR D1(L,B1),D2(B2) [SS] */
2989 case 0xf3: /* UNPK D1(L1,B1),D2(L2,B2) [SS] */
46ee3d84 2990 insn = ld_code6(env, s->pc);
e023e832
AG
2991 vl = tcg_const_i32((insn >> 32) & 0xff);
2992 b1 = (insn >> 28) & 0xf;
2993 b2 = (insn >> 12) & 0xf;
2994 d1 = (insn >> 16) & 0xfff;
2995 d2 = insn & 0xfff;
2996 tmp = get_address(s, 0, b1, d1);
2997 tmp2 = get_address(s, 0, b2, d2);
2998 switch (opc) {
2999 case 0xd2:
3000 gen_op_mvc(s, (insn >> 32) & 0xff, tmp, tmp2);
3001 break;
3002 case 0xd4:
3003 potential_page_fault(s);
19b0516f 3004 gen_helper_nc(cc_op, cpu_env, vl, tmp, tmp2);
e023e832
AG
3005 set_cc_static(s);
3006 break;
3007 case 0xd5:
3008 gen_op_clc(s, (insn >> 32) & 0xff, tmp, tmp2);
3009 break;
3010 case 0xd6:
3011 potential_page_fault(s);
19b0516f 3012 gen_helper_oc(cc_op, cpu_env, vl, tmp, tmp2);
e023e832
AG
3013 set_cc_static(s);
3014 break;
3015 case 0xd7:
3016 potential_page_fault(s);
19b0516f 3017 gen_helper_xc(cc_op, cpu_env, vl, tmp, tmp2);
e023e832
AG
3018 set_cc_static(s);
3019 break;
3020 case 0xdc:
3021 potential_page_fault(s);
19b0516f 3022 gen_helper_tr(cpu_env, vl, tmp, tmp2);
e023e832
AG
3023 set_cc_static(s);
3024 break;
3025 case 0xf3:
3026 potential_page_fault(s);
19b0516f 3027 gen_helper_unpk(cpu_env, vl, tmp, tmp2);
e023e832
AG
3028 break;
3029 default:
3030 tcg_abort();
3031 }
3032 tcg_temp_free_i64(tmp);
3033 tcg_temp_free_i64(tmp2);
3034 break;
3035#ifndef CONFIG_USER_ONLY
3036 case 0xda: /* MVCP D1(R1,B1),D2(B2),R3 [SS] */
3037 case 0xdb: /* MVCS D1(R1,B1),D2(B2),R3 [SS] */
d5a103cd 3038 check_privileged(s);
e023e832 3039 potential_page_fault(s);
46ee3d84 3040 insn = ld_code6(env, s->pc);
e023e832
AG
3041 r1 = (insn >> 36) & 0xf;
3042 r3 = (insn >> 32) & 0xf;
3043 b1 = (insn >> 28) & 0xf;
3044 d1 = (insn >> 16) & 0xfff;
3045 b2 = (insn >> 12) & 0xf;
3046 d2 = insn & 0xfff;
3047 tmp = load_reg(r1);
3048 /* XXX key in r3 */
3049 tmp2 = get_address(s, 0, b1, d1);
3050 tmp3 = get_address(s, 0, b2, d2);
3051 if (opc == 0xda) {
19b0516f 3052 gen_helper_mvcp(cc_op, cpu_env, tmp, tmp2, tmp3);
e023e832 3053 } else {
19b0516f 3054 gen_helper_mvcs(cc_op, cpu_env, tmp, tmp2, tmp3);
e023e832
AG
3055 }
3056 set_cc_static(s);
3057 tcg_temp_free_i64(tmp);
3058 tcg_temp_free_i64(tmp2);
3059 tcg_temp_free_i64(tmp3);
3060 break;
3061#endif
3062 case 0xe3:
46ee3d84 3063 insn = ld_code6(env, s->pc);
e023e832
AG
3064 debug_insn(insn);
3065 op = insn & 0xff;
3066 r1 = (insn >> 36) & 0xf;
3067 x2 = (insn >> 32) & 0xf;
3068 b2 = (insn >> 28) & 0xf;
3069 d2 = ((int)((((insn >> 16) & 0xfff)
3070 | ((insn << 4) & 0xff000)) << 12)) >> 12;
46ee3d84 3071 disas_e3(env, s, op, r1, x2, b2, d2 );
e023e832
AG
3072 break;
3073#ifndef CONFIG_USER_ONLY
3074 case 0xe5:
3075 /* Test Protection */
d5a103cd 3076 check_privileged(s);
46ee3d84 3077 insn = ld_code6(env, s->pc);
e023e832 3078 debug_insn(insn);
46ee3d84 3079 disas_e5(env, s, insn);
e023e832
AG
3080 break;
3081#endif
3082 case 0xeb:
46ee3d84 3083 insn = ld_code6(env, s->pc);
e023e832
AG
3084 debug_insn(insn);
3085 op = insn & 0xff;
3086 r1 = (insn >> 36) & 0xf;
3087 r3 = (insn >> 32) & 0xf;
3088 b2 = (insn >> 28) & 0xf;
3089 d2 = ((int)((((insn >> 16) & 0xfff)
3090 | ((insn << 4) & 0xff000)) << 12)) >> 12;
46ee3d84 3091 disas_eb(env, s, op, r1, r3, b2, d2);
e023e832
AG
3092 break;
3093 case 0xed:
46ee3d84 3094 insn = ld_code6(env, s->pc);
e023e832
AG
3095 debug_insn(insn);
3096 op = insn & 0xff;
3097 r1 = (insn >> 36) & 0xf;
3098 x2 = (insn >> 32) & 0xf;
3099 b2 = (insn >> 28) & 0xf;
3100 d2 = (short)((insn >> 16) & 0xfff);
3101 r1b = (insn >> 12) & 0xf;
46ee3d84 3102 disas_ed(env, s, op, r1, x2, b2, d2, r1b);
e023e832
AG
3103 break;
3104 default:
71547a3b 3105 qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
d5a103cd 3106 gen_illegal_opcode(s);
e023e832
AG
3107 break;
3108 }
ad044d09
RH
3109}
3110
3111/* ====================================================================== */
3112/* Define the insn format enumeration. */
3113#define F0(N) FMT_##N,
3114#define F1(N, X1) F0(N)
3115#define F2(N, X1, X2) F0(N)
3116#define F3(N, X1, X2, X3) F0(N)
3117#define F4(N, X1, X2, X3, X4) F0(N)
3118#define F5(N, X1, X2, X3, X4, X5) F0(N)
3119
3120typedef enum {
3121#include "insn-format.def"
3122} DisasFormat;
3123
3124#undef F0
3125#undef F1
3126#undef F2
3127#undef F3
3128#undef F4
3129#undef F5
3130
3131/* Define a structure to hold the decoded fields. We'll store each inside
3132 an array indexed by an enum. In order to conserve memory, we'll arrange
3133 for fields that do not exist at the same time to overlap, thus the "C"
3134 for compact. For checking purposes there is an "O" for original index
3135 as well that will be applied to availability bitmaps. */
3136
3137enum DisasFieldIndexO {
3138 FLD_O_r1,
3139 FLD_O_r2,
3140 FLD_O_r3,
3141 FLD_O_m1,
3142 FLD_O_m3,
3143 FLD_O_m4,
3144 FLD_O_b1,
3145 FLD_O_b2,
3146 FLD_O_b4,
3147 FLD_O_d1,
3148 FLD_O_d2,
3149 FLD_O_d4,
3150 FLD_O_x2,
3151 FLD_O_l1,
3152 FLD_O_l2,
3153 FLD_O_i1,
3154 FLD_O_i2,
3155 FLD_O_i3,
3156 FLD_O_i4,
3157 FLD_O_i5
3158};
3159
3160enum DisasFieldIndexC {
3161 FLD_C_r1 = 0,
3162 FLD_C_m1 = 0,
3163 FLD_C_b1 = 0,
3164 FLD_C_i1 = 0,
3165
3166 FLD_C_r2 = 1,
3167 FLD_C_b2 = 1,
3168 FLD_C_i2 = 1,
3169
3170 FLD_C_r3 = 2,
3171 FLD_C_m3 = 2,
3172 FLD_C_i3 = 2,
3173
3174 FLD_C_m4 = 3,
3175 FLD_C_b4 = 3,
3176 FLD_C_i4 = 3,
3177 FLD_C_l1 = 3,
3178
3179 FLD_C_i5 = 4,
3180 FLD_C_d1 = 4,
3181
3182 FLD_C_d2 = 5,
3183
3184 FLD_C_d4 = 6,
3185 FLD_C_x2 = 6,
3186 FLD_C_l2 = 6,
3187
3188 NUM_C_FIELD = 7
3189};
3190
3191struct DisasFields {
3192 unsigned op:8;
3193 unsigned op2:8;
3194 unsigned presentC:16;
3195 unsigned int presentO;
3196 int c[NUM_C_FIELD];
3197};
3198
3199/* This is the way fields are to be accessed out of DisasFields. */
3200#define have_field(S, F) have_field1((S), FLD_O_##F)
3201#define get_field(S, F) get_field1((S), FLD_O_##F, FLD_C_##F)
3202
3203static bool have_field1(const DisasFields *f, enum DisasFieldIndexO c)
3204{
3205 return (f->presentO >> c) & 1;
3206}
3207
3208static int get_field1(const DisasFields *f, enum DisasFieldIndexO o,
3209 enum DisasFieldIndexC c)
3210{
3211 assert(have_field1(f, o));
3212 return f->c[c];
3213}
3214
3215/* Describe the layout of each field in each format. */
3216typedef struct DisasField {
3217 unsigned int beg:8;
3218 unsigned int size:8;
3219 unsigned int type:2;
3220 unsigned int indexC:6;
3221 enum DisasFieldIndexO indexO:8;
3222} DisasField;
3223
3224typedef struct DisasFormatInfo {
3225 DisasField op[NUM_C_FIELD];
3226} DisasFormatInfo;
3227
3228#define R(N, B) { B, 4, 0, FLD_C_r##N, FLD_O_r##N }
3229#define M(N, B) { B, 4, 0, FLD_C_m##N, FLD_O_m##N }
3230#define BD(N, BB, BD) { BB, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
3231 { BD, 12, 0, FLD_C_d##N, FLD_O_d##N }
3232#define BXD(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
3233 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
3234 { 20, 12, 0, FLD_C_d##N, FLD_O_d##N }
3235#define BDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
3236 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
3237#define BXDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
3238 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
3239 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
3240#define I(N, B, S) { B, S, 1, FLD_C_i##N, FLD_O_i##N }
3241#define L(N, B, S) { B, S, 0, FLD_C_l##N, FLD_O_l##N }
3242
3243#define F0(N) { { } },
3244#define F1(N, X1) { { X1 } },
3245#define F2(N, X1, X2) { { X1, X2 } },
3246#define F3(N, X1, X2, X3) { { X1, X2, X3 } },
3247#define F4(N, X1, X2, X3, X4) { { X1, X2, X3, X4 } },
3248#define F5(N, X1, X2, X3, X4, X5) { { X1, X2, X3, X4, X5 } },
3249
3250static const DisasFormatInfo format_info[] = {
3251#include "insn-format.def"
3252};
3253
3254#undef F0
3255#undef F1
3256#undef F2
3257#undef F3
3258#undef F4
3259#undef F5
3260#undef R
3261#undef M
3262#undef BD
3263#undef BXD
3264#undef BDL
3265#undef BXDL
3266#undef I
3267#undef L
3268
3269/* Generally, we'll extract operands into this structures, operate upon
3270 them, and store them back. See the "in1", "in2", "prep", "wout" sets
3271 of routines below for more details. */
3272typedef struct {
3273 bool g_out, g_out2, g_in1, g_in2;
3274 TCGv_i64 out, out2, in1, in2;
3275 TCGv_i64 addr1;
3276} DisasOps;
3277
3278/* Return values from translate_one, indicating the state of the TB. */
3279typedef enum {
3280 /* Continue the TB. */
3281 NO_EXIT,
3282 /* We have emitted one or more goto_tb. No fixup required. */
3283 EXIT_GOTO_TB,
3284 /* We are not using a goto_tb (for whatever reason), but have updated
3285 the PC (for whatever reason), so there's no need to do it again on
3286 exiting the TB. */
3287 EXIT_PC_UPDATED,
3288 /* We are exiting the TB, but have neither emitted a goto_tb, nor
3289 updated the PC for the next instruction to be executed. */
3290 EXIT_PC_STALE,
3291 /* We are ending the TB with a noreturn function call, e.g. longjmp.
3292 No following code will be executed. */
3293 EXIT_NORETURN,
3294} ExitStatus;
3295
3296typedef enum DisasFacility {
3297 FAC_Z, /* zarch (default) */
3298 FAC_CASS, /* compare and swap and store */
3299 FAC_CASS2, /* compare and swap and store 2*/
3300 FAC_DFP, /* decimal floating point */
3301 FAC_DFPR, /* decimal floating point rounding */
3302 FAC_DO, /* distinct operands */
3303 FAC_EE, /* execute extensions */
3304 FAC_EI, /* extended immediate */
3305 FAC_FPE, /* floating point extension */
3306 FAC_FPSSH, /* floating point support sign handling */
3307 FAC_FPRGR, /* FPR-GR transfer */
3308 FAC_GIE, /* general instructions extension */
3309 FAC_HFP_MA, /* HFP multiply-and-add/subtract */
3310 FAC_HW, /* high-word */
3311 FAC_IEEEE_SIM, /* IEEE exception sumilation */
3312 FAC_LOC, /* load/store on condition */
3313 FAC_LD, /* long displacement */
3314 FAC_PC, /* population count */
3315 FAC_SCF, /* store clock fast */
3316 FAC_SFLE, /* store facility list extended */
3317} DisasFacility;
3318
3319struct DisasInsn {
3320 unsigned opc:16;
3321 DisasFormat fmt:6;
3322 DisasFacility fac:6;
3323
3324 const char *name;
3325
3326 void (*help_in1)(DisasContext *, DisasFields *, DisasOps *);
3327 void (*help_in2)(DisasContext *, DisasFields *, DisasOps *);
3328 void (*help_prep)(DisasContext *, DisasFields *, DisasOps *);
3329 void (*help_wout)(DisasContext *, DisasFields *, DisasOps *);
3330 void (*help_cout)(DisasContext *, DisasOps *);
3331 ExitStatus (*help_op)(DisasContext *, DisasOps *);
3332
3333 uint64_t data;
3334};
3335
8ac33cdb
RH
3336/* ====================================================================== */
3337/* Miscelaneous helpers, used by several operations. */
3338
3339static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
3340{
3341 if (dest == s->next_pc) {
3342 return NO_EXIT;
3343 }
3344 if (use_goto_tb(s, dest)) {
3345 gen_update_cc_op(s);
3346 tcg_gen_goto_tb(0);
3347 tcg_gen_movi_i64(psw_addr, dest);
3348 tcg_gen_exit_tb((tcg_target_long)s->tb);
3349 return EXIT_GOTO_TB;
3350 } else {
3351 tcg_gen_movi_i64(psw_addr, dest);
3352 return EXIT_PC_UPDATED;
3353 }
3354}
3355
7233f2ed
RH
3356static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
3357 bool is_imm, int imm, TCGv_i64 cdest)
3358{
3359 ExitStatus ret;
3360 uint64_t dest = s->pc + 2 * imm;
3361 int lab;
3362
3363 /* Take care of the special cases first. */
3364 if (c->cond == TCG_COND_NEVER) {
3365 ret = NO_EXIT;
3366 goto egress;
3367 }
3368 if (is_imm) {
3369 if (dest == s->next_pc) {
3370 /* Branch to next. */
3371 ret = NO_EXIT;
3372 goto egress;
3373 }
3374 if (c->cond == TCG_COND_ALWAYS) {
3375 ret = help_goto_direct(s, dest);
3376 goto egress;
3377 }
3378 } else {
3379 if (TCGV_IS_UNUSED_I64(cdest)) {
3380 /* E.g. bcr %r0 -> no branch. */
3381 ret = NO_EXIT;
3382 goto egress;
3383 }
3384 if (c->cond == TCG_COND_ALWAYS) {
3385 tcg_gen_mov_i64(psw_addr, cdest);
3386 ret = EXIT_PC_UPDATED;
3387 goto egress;
3388 }
3389 }
3390
3391 if (use_goto_tb(s, s->next_pc)) {
3392 if (is_imm && use_goto_tb(s, dest)) {
3393 /* Both exits can use goto_tb. */
3394 gen_update_cc_op(s);
3395
3396 lab = gen_new_label();
3397 if (c->is_64) {
3398 tcg_gen_brcond_i64(c->cond, c->u.s64.a, c->u.s64.b, lab);
3399 } else {
3400 tcg_gen_brcond_i32(c->cond, c->u.s32.a, c->u.s32.b, lab);
3401 }
3402
3403 /* Branch not taken. */
3404 tcg_gen_goto_tb(0);
3405 tcg_gen_movi_i64(psw_addr, s->next_pc);
3406 tcg_gen_exit_tb((tcg_target_long)s->tb + 0);
3407
3408 /* Branch taken. */
3409 gen_set_label(lab);
3410 tcg_gen_goto_tb(1);
3411 tcg_gen_movi_i64(psw_addr, dest);
3412 tcg_gen_exit_tb((tcg_target_long)s->tb + 1);
3413
3414 ret = EXIT_GOTO_TB;
3415 } else {
3416 /* Fallthru can use goto_tb, but taken branch cannot. */
3417 /* Store taken branch destination before the brcond. This
3418 avoids having to allocate a new local temp to hold it.
3419 We'll overwrite this in the not taken case anyway. */
3420 if (!is_imm) {
3421 tcg_gen_mov_i64(psw_addr, cdest);
3422 }
3423
3424 lab = gen_new_label();
3425 if (c->is_64) {
3426 tcg_gen_brcond_i64(c->cond, c->u.s64.a, c->u.s64.b, lab);
3427 } else {
3428 tcg_gen_brcond_i32(c->cond, c->u.s32.a, c->u.s32.b, lab);
3429 }
3430
3431 /* Branch not taken. */
3432 gen_update_cc_op(s);
3433 tcg_gen_goto_tb(0);
3434 tcg_gen_movi_i64(psw_addr, s->next_pc);
3435 tcg_gen_exit_tb((tcg_target_long)s->tb + 0);
3436
3437 gen_set_label(lab);
3438 if (is_imm) {
3439 tcg_gen_movi_i64(psw_addr, dest);
3440 }
3441 ret = EXIT_PC_UPDATED;
3442 }
3443 } else {
3444 /* Fallthru cannot use goto_tb. This by itself is vanishingly rare.
3445 Most commonly we're single-stepping or some other condition that
3446 disables all use of goto_tb. Just update the PC and exit. */
3447
3448 TCGv_i64 next = tcg_const_i64(s->next_pc);
3449 if (is_imm) {
3450 cdest = tcg_const_i64(dest);
3451 }
3452
3453 if (c->is_64) {
3454 tcg_gen_movcond_i64(c->cond, psw_addr, c->u.s64.a, c->u.s64.b,
3455 cdest, next);
3456 } else {
3457 TCGv_i32 t0 = tcg_temp_new_i32();
3458 TCGv_i64 t1 = tcg_temp_new_i64();
3459 TCGv_i64 z = tcg_const_i64(0);
3460 tcg_gen_setcond_i32(c->cond, t0, c->u.s32.a, c->u.s32.b);
3461 tcg_gen_extu_i32_i64(t1, t0);
3462 tcg_temp_free_i32(t0);
3463 tcg_gen_movcond_i64(TCG_COND_NE, psw_addr, t1, z, cdest, next);
3464 tcg_temp_free_i64(t1);
3465 tcg_temp_free_i64(z);
3466 }
3467
3468 if (is_imm) {
3469 tcg_temp_free_i64(cdest);
3470 }
3471 tcg_temp_free_i64(next);
3472
3473 ret = EXIT_PC_UPDATED;
3474 }
3475
3476 egress:
3477 free_compare(c);
3478 return ret;
3479}
3480
ad044d09
RH
3481/* ====================================================================== */
3482/* The operations. These perform the bulk of the work for any insn,
3483 usually after the operands have been loaded and output initialized. */
3484
b9bca3e5
RH
3485static ExitStatus op_abs(DisasContext *s, DisasOps *o)
3486{
3487 gen_helper_abs_i64(o->out, o->in2);
3488 return NO_EXIT;
3489}
3490
ad044d09
RH
3491static ExitStatus op_add(DisasContext *s, DisasOps *o)
3492{
3493 tcg_gen_add_i64(o->out, o->in1, o->in2);
3494 return NO_EXIT;
3495}
3496
4e4bb438
RH
3497static ExitStatus op_addc(DisasContext *s, DisasOps *o)
3498{
3499 TCGv_i64 cc;
3500
3501 tcg_gen_add_i64(o->out, o->in1, o->in2);
3502
3503 /* XXX possible optimization point */
3504 gen_op_calc_cc(s);
3505 cc = tcg_temp_new_i64();
3506 tcg_gen_extu_i32_i64(cc, cc_op);
3507 tcg_gen_shri_i64(cc, cc, 1);
3508
3509 tcg_gen_add_i64(o->out, o->out, cc);
3510 tcg_temp_free_i64(cc);
3511 return NO_EXIT;
3512}
3513
3bbfbd1f
RH
3514static ExitStatus op_and(DisasContext *s, DisasOps *o)
3515{
3516 tcg_gen_and_i64(o->out, o->in1, o->in2);
3517 return NO_EXIT;
3518}
3519
facfc864
RH
3520static ExitStatus op_andi(DisasContext *s, DisasOps *o)
3521{
3522 int shift = s->insn->data & 0xff;
3523 int size = s->insn->data >> 8;
3524 uint64_t mask = ((1ull << size) - 1) << shift;
3525
3526 assert(!o->g_in2);
3527 tcg_gen_shli_i64(o->in2, o->in2, shift);
3528 tcg_gen_ori_i64(o->in2, o->in2, ~mask);
3529 tcg_gen_and_i64(o->out, o->in1, o->in2);
3530
3531 /* Produce the CC from only the bits manipulated. */
3532 tcg_gen_andi_i64(cc_dst, o->out, mask);
3533 set_cc_nz_u64(s, cc_dst);
3534 return NO_EXIT;
3535}
3536
8ac33cdb
RH
3537static ExitStatus op_bas(DisasContext *s, DisasOps *o)
3538{
3539 tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
3540 if (!TCGV_IS_UNUSED_I64(o->in2)) {
3541 tcg_gen_mov_i64(psw_addr, o->in2);
3542 return EXIT_PC_UPDATED;
3543 } else {
3544 return NO_EXIT;
3545 }
3546}
3547
3548static ExitStatus op_basi(DisasContext *s, DisasOps *o)
3549{
3550 tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
3551 return help_goto_direct(s, s->pc + 2 * get_field(s->fields, i2));
3552}
3553
7233f2ed
RH
3554static ExitStatus op_bc(DisasContext *s, DisasOps *o)
3555{
3556 int m1 = get_field(s->fields, m1);
3557 bool is_imm = have_field(s->fields, i2);
3558 int imm = is_imm ? get_field(s->fields, i2) : 0;
3559 DisasCompare c;
3560
3561 disas_jcc(s, &c, m1);
3562 return help_branch(s, &c, is_imm, imm, o->in2);
3563}
3564
c61aad69
RH
3565static ExitStatus op_bct32(DisasContext *s, DisasOps *o)
3566{
3567 int r1 = get_field(s->fields, r1);
3568 bool is_imm = have_field(s->fields, i2);
3569 int imm = is_imm ? get_field(s->fields, i2) : 0;
3570 DisasCompare c;
3571 TCGv_i64 t;
3572
3573 c.cond = TCG_COND_NE;
3574 c.is_64 = false;
3575 c.g1 = false;
3576 c.g2 = false;
3577
3578 t = tcg_temp_new_i64();
3579 tcg_gen_subi_i64(t, regs[r1], 1);
3580 store_reg32_i64(r1, t);
3581 c.u.s32.a = tcg_temp_new_i32();
3582 c.u.s32.b = tcg_const_i32(0);
3583 tcg_gen_trunc_i64_i32(c.u.s32.a, t);
3584 tcg_temp_free_i64(t);
3585
3586 return help_branch(s, &c, is_imm, imm, o->in2);
3587}
3588
3589static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
3590{
3591 int r1 = get_field(s->fields, r1);
3592 bool is_imm = have_field(s->fields, i2);
3593 int imm = is_imm ? get_field(s->fields, i2) : 0;
3594 DisasCompare c;
3595
3596 c.cond = TCG_COND_NE;
3597 c.is_64 = true;
3598 c.g1 = true;
3599 c.g2 = false;
3600
3601 tcg_gen_subi_i64(regs[r1], regs[r1], 1);
3602 c.u.s64.a = regs[r1];
3603 c.u.s64.b = tcg_const_i64(0);
3604
3605 return help_branch(s, &c, is_imm, imm, o->in2);
3606}
3607
891452e5
RH
3608static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
3609{
3610 gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
3611 return_low128(o->out);
3612 return NO_EXIT;
3613}
3614
3615static ExitStatus op_divu32(DisasContext *s, DisasOps *o)
3616{
3617 gen_helper_divu32(o->out2, cpu_env, o->in1, o->in2);
3618 return_low128(o->out);
3619 return NO_EXIT;
3620}
3621
3622static ExitStatus op_divs64(DisasContext *s, DisasOps *o)
3623{
3624 gen_helper_divs64(o->out2, cpu_env, o->in1, o->in2);
3625 return_low128(o->out);
3626 return NO_EXIT;
3627}
3628
3629static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
3630{
3631 gen_helper_divu64(o->out2, cpu_env, o->out, o->out2, o->in2);
3632 return_low128(o->out);
3633 return NO_EXIT;
3634}
3635
facfc864
RH
3636static ExitStatus op_insi(DisasContext *s, DisasOps *o)
3637{
3638 int shift = s->insn->data & 0xff;
3639 int size = s->insn->data >> 8;
3640 tcg_gen_deposit_i64(o->out, o->in1, o->in2, shift, size);
3641 return NO_EXIT;
3642}
3643
c698d876
RH
3644static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
3645{
3646 tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
3647 return NO_EXIT;
3648}
3649
3650static ExitStatus op_ld8u(DisasContext *s, DisasOps *o)
3651{
3652 tcg_gen_qemu_ld8u(o->out, o->in2, get_mem_index(s));
3653 return NO_EXIT;
3654}
3655
3656static ExitStatus op_ld16s(DisasContext *s, DisasOps *o)
3657{
3658 tcg_gen_qemu_ld16s(o->out, o->in2, get_mem_index(s));
3659 return NO_EXIT;
3660}
3661
3662static ExitStatus op_ld16u(DisasContext *s, DisasOps *o)
3663{
3664 tcg_gen_qemu_ld16u(o->out, o->in2, get_mem_index(s));
3665 return NO_EXIT;
3666}
3667
22c37a08
RH
3668static ExitStatus op_ld32s(DisasContext *s, DisasOps *o)
3669{
3670 tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s));
3671 return NO_EXIT;
3672}
3673
3674static ExitStatus op_ld32u(DisasContext *s, DisasOps *o)
3675{
3676 tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s));
3677 return NO_EXIT;
3678}
3679
3680static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
3681{
3682 tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s));
3683 return NO_EXIT;
3684}
3685
3686static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
3687{
3688 o->out = o->in2;
3689 o->g_out = o->g_in2;
3690 TCGV_UNUSED_I64(o->in2);
3691 o->g_in2 = false;
3692 return NO_EXIT;
3693}
3694
d1c04a2b
RH
3695static ExitStatus op_mul(DisasContext *s, DisasOps *o)
3696{
3697 tcg_gen_mul_i64(o->out, o->in1, o->in2);
3698 return NO_EXIT;
3699}
3700
1ac5889f
RH
3701static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
3702{
3703 gen_helper_mul128(o->out, cpu_env, o->in1, o->in2);
3704 return_low128(o->out2);
3705 return NO_EXIT;
3706}
3707
b9bca3e5
RH
3708static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
3709{
3710 gen_helper_nabs_i64(o->out, o->in2);
3711 return NO_EXIT;
3712}
3713
3714static ExitStatus op_neg(DisasContext *s, DisasOps *o)
3715{
3716 tcg_gen_neg_i64(o->out, o->in2);
3717 return NO_EXIT;
3718}
3719
3bbfbd1f
RH
3720static ExitStatus op_or(DisasContext *s, DisasOps *o)
3721{
3722 tcg_gen_or_i64(o->out, o->in1, o->in2);
3723 return NO_EXIT;
3724}
3725
facfc864
RH
3726static ExitStatus op_ori(DisasContext *s, DisasOps *o)
3727{
3728 int shift = s->insn->data & 0xff;
3729 int size = s->insn->data >> 8;
3730 uint64_t mask = ((1ull << size) - 1) << shift;
3731
3732 assert(!o->g_in2);
3733 tcg_gen_shli_i64(o->in2, o->in2, shift);
3734 tcg_gen_or_i64(o->out, o->in1, o->in2);
3735
3736 /* Produce the CC from only the bits manipulated. */
3737 tcg_gen_andi_i64(cc_dst, o->out, mask);
3738 set_cc_nz_u64(s, cc_dst);
3739 return NO_EXIT;
3740}
3741
2b280b97
RH
3742static ExitStatus op_st8(DisasContext *s, DisasOps *o)
3743{
3744 tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s));
3745 return NO_EXIT;
3746}
3747
3748static ExitStatus op_st16(DisasContext *s, DisasOps *o)
3749{
3750 tcg_gen_qemu_st16(o->in1, o->in2, get_mem_index(s));
3751 return NO_EXIT;
3752}
3753
3754static ExitStatus op_st32(DisasContext *s, DisasOps *o)
3755{
3756 tcg_gen_qemu_st32(o->in1, o->in2, get_mem_index(s));
3757 return NO_EXIT;
3758}
3759
3760static ExitStatus op_st64(DisasContext *s, DisasOps *o)
3761{
3762 tcg_gen_qemu_st64(o->in1, o->in2, get_mem_index(s));
3763 return NO_EXIT;
3764}
3765
ad044d09
RH
3766static ExitStatus op_sub(DisasContext *s, DisasOps *o)
3767{
3768 tcg_gen_sub_i64(o->out, o->in1, o->in2);
3769 return NO_EXIT;
3770}
3771
4e4bb438
RH
3772static ExitStatus op_subb(DisasContext *s, DisasOps *o)
3773{
3774 TCGv_i64 cc;
3775
3776 assert(!o->g_in2);
3777 tcg_gen_not_i64(o->in2, o->in2);
3778 tcg_gen_add_i64(o->out, o->in1, o->in2);
3779
3780 /* XXX possible optimization point */
3781 gen_op_calc_cc(s);
3782 cc = tcg_temp_new_i64();
3783 tcg_gen_extu_i32_i64(cc, cc_op);
3784 tcg_gen_shri_i64(cc, cc, 1);
3785 tcg_gen_add_i64(o->out, o->out, cc);
3786 tcg_temp_free_i64(cc);
3787 return NO_EXIT;
3788}
3789
3bbfbd1f
RH
3790static ExitStatus op_xor(DisasContext *s, DisasOps *o)
3791{
3792 tcg_gen_xor_i64(o->out, o->in1, o->in2);
3793 return NO_EXIT;
3794}
3795
facfc864
RH
3796static ExitStatus op_xori(DisasContext *s, DisasOps *o)
3797{
3798 int shift = s->insn->data & 0xff;
3799 int size = s->insn->data >> 8;
3800 uint64_t mask = ((1ull << size) - 1) << shift;
3801
3802 assert(!o->g_in2);
3803 tcg_gen_shli_i64(o->in2, o->in2, shift);
3804 tcg_gen_xor_i64(o->out, o->in1, o->in2);
3805
3806 /* Produce the CC from only the bits manipulated. */
3807 tcg_gen_andi_i64(cc_dst, o->out, mask);
3808 set_cc_nz_u64(s, cc_dst);
3809 return NO_EXIT;
3810}
3811
ad044d09
RH
3812/* ====================================================================== */
3813/* The "Cc OUTput" generators. Given the generated output (and in some cases
3814 the original inputs), update the various cc data structures in order to
3815 be able to compute the new condition code. */
3816
b9bca3e5
RH
3817static void cout_abs32(DisasContext *s, DisasOps *o)
3818{
3819 gen_op_update1_cc_i64(s, CC_OP_ABS_32, o->out);
3820}
3821
3822static void cout_abs64(DisasContext *s, DisasOps *o)
3823{
3824 gen_op_update1_cc_i64(s, CC_OP_ABS_64, o->out);
3825}
3826
ad044d09
RH
3827static void cout_adds32(DisasContext *s, DisasOps *o)
3828{
3829 gen_op_update3_cc_i64(s, CC_OP_ADD_32, o->in1, o->in2, o->out);
3830}
3831
3832static void cout_adds64(DisasContext *s, DisasOps *o)
3833{
3834 gen_op_update3_cc_i64(s, CC_OP_ADD_64, o->in1, o->in2, o->out);
3835}
3836
3837static void cout_addu32(DisasContext *s, DisasOps *o)
3838{
3839 gen_op_update3_cc_i64(s, CC_OP_ADDU_32, o->in1, o->in2, o->out);
3840}
3841
3842static void cout_addu64(DisasContext *s, DisasOps *o)
3843{
3844 gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
3845}
3846
4e4bb438
RH
3847static void cout_addc32(DisasContext *s, DisasOps *o)
3848{
3849 gen_op_update3_cc_i64(s, CC_OP_ADDC_32, o->in1, o->in2, o->out);
3850}
3851
3852static void cout_addc64(DisasContext *s, DisasOps *o)
3853{
3854 gen_op_update3_cc_i64(s, CC_OP_ADDC_64, o->in1, o->in2, o->out);
3855}
3856
a7e836d5
RH
3857static void cout_cmps32(DisasContext *s, DisasOps *o)
3858{
3859 gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);
3860}
3861
3862static void cout_cmps64(DisasContext *s, DisasOps *o)
3863{
3864 gen_op_update2_cc_i64(s, CC_OP_LTGT_64, o->in1, o->in2);
3865}
3866
3867static void cout_cmpu32(DisasContext *s, DisasOps *o)
3868{
3869 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_32, o->in1, o->in2);
3870}
3871
3872static void cout_cmpu64(DisasContext *s, DisasOps *o)
3873{
3874 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
3875}
3876
b9bca3e5
RH
3877static void cout_nabs32(DisasContext *s, DisasOps *o)
3878{
3879 gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
3880}
3881
3882static void cout_nabs64(DisasContext *s, DisasOps *o)
3883{
3884 gen_op_update1_cc_i64(s, CC_OP_NABS_64, o->out);
3885}
3886
3887static void cout_neg32(DisasContext *s, DisasOps *o)
3888{
3889 gen_op_update1_cc_i64(s, CC_OP_COMP_32, o->out);
3890}
3891
3892static void cout_neg64(DisasContext *s, DisasOps *o)
3893{
3894 gen_op_update1_cc_i64(s, CC_OP_COMP_64, o->out);
3895}
3896
3bbfbd1f
RH
3897static void cout_nz32(DisasContext *s, DisasOps *o)
3898{
3899 tcg_gen_ext32u_i64(cc_dst, o->out);
3900 gen_op_update1_cc_i64(s, CC_OP_NZ, cc_dst);
3901}
3902
3903static void cout_nz64(DisasContext *s, DisasOps *o)
3904{
3905 gen_op_update1_cc_i64(s, CC_OP_NZ, o->out);
3906}
3907
11bf2d73
RH
3908static void cout_s32(DisasContext *s, DisasOps *o)
3909{
3910 gen_op_update1_cc_i64(s, CC_OP_LTGT0_32, o->out);
3911}
3912
3913static void cout_s64(DisasContext *s, DisasOps *o)
3914{
3915 gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, o->out);
3916}
3917
ad044d09
RH
3918static void cout_subs32(DisasContext *s, DisasOps *o)
3919{
3920 gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
3921}
3922
3923static void cout_subs64(DisasContext *s, DisasOps *o)
3924{
3925 gen_op_update3_cc_i64(s, CC_OP_SUB_64, o->in1, o->in2, o->out);
3926}
3927
3928static void cout_subu32(DisasContext *s, DisasOps *o)
3929{
3930 gen_op_update3_cc_i64(s, CC_OP_SUBU_32, o->in1, o->in2, o->out);
3931}
3932
3933static void cout_subu64(DisasContext *s, DisasOps *o)
3934{
3935 gen_op_update3_cc_i64(s, CC_OP_SUBU_64, o->in1, o->in2, o->out);
3936}
3937
4e4bb438
RH
3938static void cout_subb32(DisasContext *s, DisasOps *o)
3939{
3940 gen_op_update3_cc_i64(s, CC_OP_SUBB_32, o->in1, o->in2, o->out);
3941}
3942
3943static void cout_subb64(DisasContext *s, DisasOps *o)
3944{
3945 gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
3946}
3947
ad044d09
RH
3948/* ====================================================================== */
3949/* The "PREPeration" generators. These initialize the DisasOps.OUT fields
3950 with the TCG register to which we will write. Used in combination with
3951 the "wout" generators, in some cases we need a new temporary, and in
3952 some cases we can write to a TCG global. */
3953
3954static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
3955{
3956 o->out = tcg_temp_new_i64();
3957}
3958
891452e5
RH
3959static void prep_new_P(DisasContext *s, DisasFields *f, DisasOps *o)
3960{
3961 o->out = tcg_temp_new_i64();
3962 o->out2 = tcg_temp_new_i64();
3963}
3964
ad044d09
RH
3965static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
3966{
3967 o->out = regs[get_field(f, r1)];
3968 o->g_out = true;
3969}
3970
1ac5889f
RH
3971static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
3972{
3973 /* ??? Specification exception: r1 must be even. */
3974 int r1 = get_field(f, r1);
3975 o->out = regs[r1];
3976 o->out2 = regs[(r1 + 1) & 15];
3977 o->g_out = o->g_out2 = true;
3978}
3979
ad044d09
RH
3980/* ====================================================================== */
3981/* The "Write OUTput" generators. These generally perform some non-trivial
3982 copy of data to TCG globals, or to main memory. The trivial cases are
3983 generally handled by having a "prep" generator install the TCG global
3984 as the destination of the operation. */
3985
22c37a08
RH
3986static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
3987{
3988 store_reg(get_field(f, r1), o->out);
3989}
3990
ad044d09
RH
3991static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
3992{
3993 store_reg32_i64(get_field(f, r1), o->out);
3994}
3995
891452e5
RH
3996static void wout_r1_P32(DisasContext *s, DisasFields *f, DisasOps *o)
3997{
3998 /* ??? Specification exception: r1 must be even. */
3999 int r1 = get_field(f, r1);
4000 store_reg32_i64(r1, o->out);
4001 store_reg32_i64((r1 + 1) & 15, o->out2);
4002}
4003
d87aaf93
RH
4004static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4005{
4006 /* ??? Specification exception: r1 must be even. */
4007 int r1 = get_field(f, r1);
4008 store_reg32_i64((r1 + 1) & 15, o->out);
4009 tcg_gen_shri_i64(o->out, o->out, 32);
4010 store_reg32_i64(r1, o->out);
4011}
22c37a08
RH
4012
4013static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
4014{
4015 if (get_field(f, r1) != get_field(f, r2)) {
4016 store_reg32_i64(get_field(f, r1), o->out);
4017 }
4018}
d87aaf93 4019
ad044d09
RH
4020static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
4021{
4022 tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
4023}
4024
4025static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
4026{
4027 tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
4028}
4029
4030/* ====================================================================== */
4031/* The "INput 1" generators. These load the first operand to an insn. */
4032
4033static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
4034{
4035 o->in1 = load_reg(get_field(f, r1));
4036}
4037
d1c04a2b
RH
4038static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4039{
4040 o->in1 = regs[get_field(f, r1)];
4041 o->g_in1 = true;
4042}
4043
1ac5889f
RH
4044static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
4045{
4046 /* ??? Specification exception: r1 must be even. */
4047 int r1 = get_field(f, r1);
4048 o->in1 = load_reg((r1 + 1) & 15);
4049}
4050
d87aaf93
RH
4051static void in1_r1p1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4052{
4053 /* ??? Specification exception: r1 must be even. */
4054 int r1 = get_field(f, r1);
4055 o->in1 = tcg_temp_new_i64();
4056 tcg_gen_ext32s_i64(o->in1, regs[(r1 + 1) & 15]);
4057}
4058
4059static void in1_r1p1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4060{
4061 /* ??? Specification exception: r1 must be even. */
4062 int r1 = get_field(f, r1);
4063 o->in1 = tcg_temp_new_i64();
4064 tcg_gen_ext32u_i64(o->in1, regs[(r1 + 1) & 15]);
4065}
4066
891452e5
RH
4067static void in1_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4068{
4069 /* ??? Specification exception: r1 must be even. */
4070 int r1 = get_field(f, r1);
4071 o->in1 = tcg_temp_new_i64();
4072 tcg_gen_concat32_i64(o->in1, regs[r1 + 1], regs[r1]);
4073}
4074
ad044d09
RH
4075static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
4076{
4077 o->in1 = load_reg(get_field(f, r2));
4078}
4079
4080static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
4081{
4082 o->in1 = load_reg(get_field(f, r3));
4083}
4084
4085static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
4086{
4087 o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
4088}
4089
a7e836d5
RH
4090static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4091{
4092 in1_la1(s, f, o);
4093 o->in1 = tcg_temp_new_i64();
4094 tcg_gen_qemu_ld8u(o->in1, o->addr1, get_mem_index(s));
4095}
4096
4097static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4098{
4099 in1_la1(s, f, o);
4100 o->in1 = tcg_temp_new_i64();
4101 tcg_gen_qemu_ld16s(o->in1, o->addr1, get_mem_index(s));
4102}
4103
4104static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4105{
4106 in1_la1(s, f, o);
4107 o->in1 = tcg_temp_new_i64();
4108 tcg_gen_qemu_ld16u(o->in1, o->addr1, get_mem_index(s));
4109}
4110
ad044d09
RH
4111static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4112{
4113 in1_la1(s, f, o);
4114 o->in1 = tcg_temp_new_i64();
4115 tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
4116}
4117
e272b3ac
RH
4118static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4119{
4120 in1_la1(s, f, o);
4121 o->in1 = tcg_temp_new_i64();
4122 tcg_gen_qemu_ld32u(o->in1, o->addr1, get_mem_index(s));
4123}
4124
ad044d09
RH
4125static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
4126{
4127 in1_la1(s, f, o);
4128 o->in1 = tcg_temp_new_i64();
4129 tcg_gen_qemu_ld64(o->in1, o->addr1, get_mem_index(s));
4130}
4131
4132/* ====================================================================== */
4133/* The "INput 2" generators. These load the second operand to an insn. */
4134
4135static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
4136{
4137 o->in2 = load_reg(get_field(f, r2));
4138}
4139
d1c04a2b
RH
4140static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
4141{
4142 o->in2 = regs[get_field(f, r2)];
4143 o->g_in2 = true;
4144}
4145
8ac33cdb
RH
4146static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
4147{
4148 int r2 = get_field(f, r2);
4149 if (r2 != 0) {
4150 o->in2 = load_reg(r2);
4151 }
4152}
4153
c698d876
RH
4154static void in2_r2_8s(DisasContext *s, DisasFields *f, DisasOps *o)
4155{
4156 o->in2 = tcg_temp_new_i64();
4157 tcg_gen_ext8s_i64(o->in2, regs[get_field(f, r2)]);
4158}
4159
4160static void in2_r2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4161{
4162 o->in2 = tcg_temp_new_i64();
4163 tcg_gen_ext8u_i64(o->in2, regs[get_field(f, r2)]);
4164}
4165
4166static void in2_r2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4167{
4168 o->in2 = tcg_temp_new_i64();
4169 tcg_gen_ext16s_i64(o->in2, regs[get_field(f, r2)]);
4170}
4171
4172static void in2_r2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4173{
4174 o->in2 = tcg_temp_new_i64();
4175 tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r2)]);
4176}
4177
ad044d09
RH
4178static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
4179{
4180 o->in2 = load_reg(get_field(f, r3));
4181}
4182
4183static void in2_r2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4184{
4185 o->in2 = tcg_temp_new_i64();
4186 tcg_gen_ext32s_i64(o->in2, regs[get_field(f, r2)]);
4187}
4188
4189static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4190{
4191 o->in2 = tcg_temp_new_i64();
4192 tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
4193}
4194
4195static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
4196{
4197 int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
4198 o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
4199}
4200
a7e836d5
RH
4201static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
4202{
4203 o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
4204}
4205
d82287de
RH
4206static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4207{
4208 in2_a2(s, f, o);
4209 tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
4210}
4211
ad044d09
RH
4212static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4213{
4214 in2_a2(s, f, o);
4215 tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
4216}
4217
4218static void in2_m2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4219{
4220 in2_a2(s, f, o);
4221 tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
4222}
4223
4224static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
4225{
4226 in2_a2(s, f, o);
4227 tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
4228}
4229
a7e836d5
RH
4230static void in2_mri2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4231{
4232 in2_ri2(s, f, o);
4233 tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
4234}
4235
4236static void in2_mri2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4237{
4238 in2_ri2(s, f, o);
4239 tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
4240}
4241
4242static void in2_mri2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4243{
4244 in2_ri2(s, f, o);
4245 tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
4246}
4247
4248static void in2_mri2_64(DisasContext *s, DisasFields *f, DisasOps *o)
4249{
4250 in2_ri2(s, f, o);
4251 tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
4252}
4253
ad044d09
RH
4254static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
4255{
4256 o->in2 = tcg_const_i64(get_field(f, i2));
4257}
4258
a7e836d5
RH
4259static void in2_i2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4260{
4261 o->in2 = tcg_const_i64((uint8_t)get_field(f, i2));
4262}
4263
4264static void in2_i2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4265{
4266 o->in2 = tcg_const_i64((uint16_t)get_field(f, i2));
4267}
4268
ad044d09
RH
4269static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4270{
4271 o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
4272}
4273
ade9dea4
RH
4274static void in2_i2_16u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
4275{
4276 uint64_t i2 = (uint16_t)get_field(f, i2);
4277 o->in2 = tcg_const_i64(i2 << s->insn->data);
4278}
4279
4280static void in2_i2_32u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
4281{
4282 uint64_t i2 = (uint32_t)get_field(f, i2);
4283 o->in2 = tcg_const_i64(i2 << s->insn->data);
4284}
4285
ad044d09
RH
4286/* ====================================================================== */
4287
4288/* Find opc within the table of insns. This is formulated as a switch
4289 statement so that (1) we get compile-time notice of cut-paste errors
4290 for duplicated opcodes, and (2) the compiler generates the binary
4291 search tree, rather than us having to post-process the table. */
4292
4293#define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \
4294 D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0)
4295
4296#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) insn_ ## NM,
4297
4298enum DisasInsnEnum {
4299#include "insn-data.def"
4300};
4301
4302#undef D
4303#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
4304 .opc = OPC, \
4305 .fmt = FMT_##FT, \
4306 .fac = FAC_##FC, \
4307 .name = #NM, \
4308 .help_in1 = in1_##I1, \
4309 .help_in2 = in2_##I2, \
4310 .help_prep = prep_##P, \
4311 .help_wout = wout_##W, \
4312 .help_cout = cout_##CC, \
4313 .help_op = op_##OP, \
4314 .data = D \
4315 },
4316
4317/* Allow 0 to be used for NULL in the table below. */
4318#define in1_0 NULL
4319#define in2_0 NULL
4320#define prep_0 NULL
4321#define wout_0 NULL
4322#define cout_0 NULL
4323#define op_0 NULL
4324
4325static const DisasInsn insn_info[] = {
4326#include "insn-data.def"
4327};
4328
4329#undef D
4330#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
4331 case OPC: return &insn_info[insn_ ## NM];
4332
4333static const DisasInsn *lookup_opc(uint16_t opc)
4334{
4335 switch (opc) {
4336#include "insn-data.def"
4337 default:
4338 return NULL;
4339 }
4340}
4341
4342#undef D
4343#undef C
4344
4345/* Extract a field from the insn. The INSN should be left-aligned in
4346 the uint64_t so that we can more easily utilize the big-bit-endian
4347 definitions we extract from the Principals of Operation. */
4348
4349static void extract_field(DisasFields *o, const DisasField *f, uint64_t insn)
4350{
4351 uint32_t r, m;
4352
4353 if (f->size == 0) {
4354 return;
4355 }
4356
4357 /* Zero extract the field from the insn. */
4358 r = (insn << f->beg) >> (64 - f->size);
4359
4360 /* Sign-extend, or un-swap the field as necessary. */
4361 switch (f->type) {
4362 case 0: /* unsigned */
4363 break;
4364 case 1: /* signed */
4365 assert(f->size <= 32);
4366 m = 1u << (f->size - 1);
4367 r = (r ^ m) - m;
4368 break;
4369 case 2: /* dl+dh split, signed 20 bit. */
4370 r = ((int8_t)r << 12) | (r >> 8);
4371 break;
4372 default:
4373 abort();
4374 }
4375
4376 /* Validate that the "compressed" encoding we selected above is valid.
4377 I.e. we havn't make two different original fields overlap. */
4378 assert(((o->presentC >> f->indexC) & 1) == 0);
4379 o->presentC |= 1 << f->indexC;
4380 o->presentO |= 1 << f->indexO;
4381
4382 o->c[f->indexC] = r;
4383}
4384
4385/* Lookup the insn at the current PC, extracting the operands into O and
4386 returning the info struct for the insn. Returns NULL for invalid insn. */
4387
4388static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
4389 DisasFields *f)
4390{
4391 uint64_t insn, pc = s->pc;
d5a103cd 4392 int op, op2, ilen;
ad044d09
RH
4393 const DisasInsn *info;
4394
4395 insn = ld_code2(env, pc);
4396 op = (insn >> 8) & 0xff;
d5a103cd
RH
4397 ilen = get_ilen(op);
4398 s->next_pc = s->pc + ilen;
4399
4400 switch (ilen) {
4401 case 2:
ad044d09
RH
4402 insn = insn << 48;
4403 break;
d5a103cd 4404 case 4:
ad044d09
RH
4405 insn = ld_code4(env, pc) << 32;
4406 break;
d5a103cd 4407 case 6:
ad044d09
RH
4408 insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
4409 break;
4410 default:
4411 abort();
4412 }
4413
4414 /* We can't actually determine the insn format until we've looked up
4415 the full insn opcode. Which we can't do without locating the
4416 secondary opcode. Assume by default that OP2 is at bit 40; for
4417 those smaller insns that don't actually have a secondary opcode
4418 this will correctly result in OP2 = 0. */
4419 switch (op) {
4420 case 0x01: /* E */
4421 case 0x80: /* S */
4422 case 0x82: /* S */
4423 case 0x93: /* S */
4424 case 0xb2: /* S, RRF, RRE */
4425 case 0xb3: /* RRE, RRD, RRF */
4426 case 0xb9: /* RRE, RRF */
4427 case 0xe5: /* SSE, SIL */
4428 op2 = (insn << 8) >> 56;
4429 break;
4430 case 0xa5: /* RI */
4431 case 0xa7: /* RI */
4432 case 0xc0: /* RIL */
4433 case 0xc2: /* RIL */
4434 case 0xc4: /* RIL */
4435 case 0xc6: /* RIL */
4436 case 0xc8: /* SSF */
4437 case 0xcc: /* RIL */
4438 op2 = (insn << 12) >> 60;
4439 break;
4440 case 0xd0 ... 0xdf: /* SS */
4441 case 0xe1: /* SS */
4442 case 0xe2: /* SS */
4443 case 0xe8: /* SS */
4444 case 0xe9: /* SS */
4445 case 0xea: /* SS */
4446 case 0xee ... 0xf3: /* SS */
4447 case 0xf8 ... 0xfd: /* SS */
4448 op2 = 0;
4449 break;
4450 default:
4451 op2 = (insn << 40) >> 56;
4452 break;
4453 }
4454
4455 memset(f, 0, sizeof(*f));
4456 f->op = op;
4457 f->op2 = op2;
4458
4459 /* Lookup the instruction. */
4460 info = lookup_opc(op << 8 | op2);
4461
4462 /* If we found it, extract the operands. */
4463 if (info != NULL) {
4464 DisasFormat fmt = info->fmt;
4465 int i;
4466
4467 for (i = 0; i < NUM_C_FIELD; ++i) {
4468 extract_field(f, &format_info[fmt].op[i], insn);
4469 }
4470 }
4471 return info;
4472}
4473
4474static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
4475{
4476 const DisasInsn *insn;
4477 ExitStatus ret = NO_EXIT;
4478 DisasFields f;
4479 DisasOps o;
4480
4481 insn = extract_insn(env, s, &f);
e023e832 4482
ad044d09
RH
4483 /* If not found, try the old interpreter. This includes ILLOPC. */
4484 if (insn == NULL) {
4485 disas_s390_insn(env, s);
4486 switch (s->is_jmp) {
4487 case DISAS_NEXT:
4488 ret = NO_EXIT;
4489 break;
4490 case DISAS_TB_JUMP:
4491 ret = EXIT_GOTO_TB;
4492 break;
4493 case DISAS_JUMP:
4494 ret = EXIT_PC_UPDATED;
4495 break;
4496 case DISAS_EXCP:
4497 ret = EXIT_NORETURN;
4498 break;
4499 default:
4500 abort();
4501 }
4502
4503 s->pc = s->next_pc;
4504 return ret;
4505 }
4506
4507 /* Set up the strutures we use to communicate with the helpers. */
4508 s->insn = insn;
4509 s->fields = &f;
4510 o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
4511 TCGV_UNUSED_I64(o.out);
4512 TCGV_UNUSED_I64(o.out2);
4513 TCGV_UNUSED_I64(o.in1);
4514 TCGV_UNUSED_I64(o.in2);
4515 TCGV_UNUSED_I64(o.addr1);
4516
4517 /* Implement the instruction. */
4518 if (insn->help_in1) {
4519 insn->help_in1(s, &f, &o);
4520 }
4521 if (insn->help_in2) {
4522 insn->help_in2(s, &f, &o);
4523 }
4524 if (insn->help_prep) {
4525 insn->help_prep(s, &f, &o);
4526 }
4527 if (insn->help_op) {
4528 ret = insn->help_op(s, &o);
4529 }
4530 if (insn->help_wout) {
4531 insn->help_wout(s, &f, &o);
4532 }
4533 if (insn->help_cout) {
4534 insn->help_cout(s, &o);
4535 }
4536
4537 /* Free any temporaries created by the helpers. */
4538 if (!TCGV_IS_UNUSED_I64(o.out) && !o.g_out) {
4539 tcg_temp_free_i64(o.out);
4540 }
4541 if (!TCGV_IS_UNUSED_I64(o.out2) && !o.g_out2) {
4542 tcg_temp_free_i64(o.out2);
4543 }
4544 if (!TCGV_IS_UNUSED_I64(o.in1) && !o.g_in1) {
4545 tcg_temp_free_i64(o.in1);
4546 }
4547 if (!TCGV_IS_UNUSED_I64(o.in2) && !o.g_in2) {
4548 tcg_temp_free_i64(o.in2);
4549 }
4550 if (!TCGV_IS_UNUSED_I64(o.addr1)) {
4551 tcg_temp_free_i64(o.addr1);
4552 }
4553
4554 /* Advance to the next instruction. */
4555 s->pc = s->next_pc;
4556 return ret;
e023e832
AG
4557}
4558
a4e3ad19 4559static inline void gen_intermediate_code_internal(CPUS390XState *env,
e023e832
AG
4560 TranslationBlock *tb,
4561 int search_pc)
4562{
4563 DisasContext dc;
4564 target_ulong pc_start;
4565 uint64_t next_page_start;
4566 uint16_t *gen_opc_end;
4567 int j, lj = -1;
4568 int num_insns, max_insns;
4569 CPUBreakpoint *bp;
ad044d09 4570 ExitStatus status;
d5a103cd 4571 bool do_debug;
e023e832
AG
4572
4573 pc_start = tb->pc;
4574
4575 /* 31-bit mode */
4576 if (!(tb->flags & FLAG_MASK_64)) {
4577 pc_start &= 0x7fffffff;
4578 }
4579
e023e832 4580 dc.tb = tb;
ad044d09 4581 dc.pc = pc_start;
e023e832 4582 dc.cc_op = CC_OP_DYNAMIC;
d5a103cd 4583 do_debug = dc.singlestep_enabled = env->singlestep_enabled;
ad044d09 4584 dc.is_jmp = DISAS_NEXT;
e023e832 4585
92414b31 4586 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
e023e832
AG
4587
4588 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
4589
4590 num_insns = 0;
4591 max_insns = tb->cflags & CF_COUNT_MASK;
4592 if (max_insns == 0) {
4593 max_insns = CF_COUNT_MASK;
4594 }
4595
4596 gen_icount_start();
4597
4598 do {
e023e832 4599 if (search_pc) {
92414b31 4600 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
e023e832
AG
4601 if (lj < j) {
4602 lj++;
4603 while (lj < j) {
ab1103de 4604 tcg_ctx.gen_opc_instr_start[lj++] = 0;
e023e832
AG
4605 }
4606 }
25983cad 4607 tcg_ctx.gen_opc_pc[lj] = dc.pc;
e023e832 4608 gen_opc_cc_op[lj] = dc.cc_op;
ab1103de 4609 tcg_ctx.gen_opc_instr_start[lj] = 1;
c9c99c22 4610 tcg_ctx.gen_opc_icount[lj] = num_insns;
e023e832 4611 }
ad044d09 4612 if (++num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
e023e832
AG
4613 gen_io_start();
4614 }
7193b5f6
RH
4615
4616 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
4617 tcg_gen_debug_insn_start(dc.pc);
4618 }
4619
d5a103cd
RH
4620 status = NO_EXIT;
4621 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
4622 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
4623 if (bp->pc == dc.pc) {
4624 status = EXIT_PC_STALE;
4625 do_debug = true;
4626 break;
4627 }
4628 }
4629 }
4630 if (status == NO_EXIT) {
4631 status = translate_one(env, &dc);
4632 }
ad044d09
RH
4633
4634 /* If we reach a page boundary, are single stepping,
4635 or exhaust instruction count, stop generation. */
4636 if (status == NO_EXIT
4637 && (dc.pc >= next_page_start
4638 || tcg_ctx.gen_opc_ptr >= gen_opc_end
4639 || num_insns >= max_insns
4640 || singlestep
4641 || env->singlestep_enabled)) {
4642 status = EXIT_PC_STALE;
e023e832 4643 }
ad044d09 4644 } while (status == NO_EXIT);
e023e832
AG
4645
4646 if (tb->cflags & CF_LAST_IO) {
4647 gen_io_end();
4648 }
ad044d09
RH
4649
4650 switch (status) {
4651 case EXIT_GOTO_TB:
4652 case EXIT_NORETURN:
4653 break;
4654 case EXIT_PC_STALE:
4655 update_psw_addr(&dc);
4656 /* FALLTHRU */
4657 case EXIT_PC_UPDATED:
4658 if (singlestep && dc.cc_op != CC_OP_DYNAMIC) {
4659 gen_op_calc_cc(&dc);
4660 } else {
4661 /* Next TB starts off with CC_OP_DYNAMIC,
4662 so make sure the cc op type is in env */
4663 gen_op_set_cc_op(&dc);
4664 }
d5a103cd
RH
4665 if (do_debug) {
4666 gen_exception(EXCP_DEBUG);
ad044d09
RH
4667 } else {
4668 /* Generate the return instruction */
4669 tcg_gen_exit_tb(0);
4670 }
4671 break;
4672 default:
4673 abort();
e023e832 4674 }
ad044d09 4675
e023e832 4676 gen_icount_end(tb, num_insns);
efd7f486 4677 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
e023e832 4678 if (search_pc) {
92414b31 4679 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
e023e832
AG
4680 lj++;
4681 while (lj <= j) {
ab1103de 4682 tcg_ctx.gen_opc_instr_start[lj++] = 0;
e023e832
AG
4683 }
4684 } else {
4685 tb->size = dc.pc - pc_start;
4686 tb->icount = num_insns;
4687 }
ad044d09 4688
e023e832 4689#if defined(S390X_DEBUG_DISAS)
e023e832
AG
4690 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
4691 qemu_log("IN: %s\n", lookup_symbol(pc_start));
f4359b9f 4692 log_target_disas(env, pc_start, dc.pc - pc_start, 1);
e023e832
AG
4693 qemu_log("\n");
4694 }
4695#endif
4696}
4697
a4e3ad19 4698void gen_intermediate_code (CPUS390XState *env, struct TranslationBlock *tb)
e023e832
AG
4699{
4700 gen_intermediate_code_internal(env, tb, 0);
4701}
4702
a4e3ad19 4703void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb)
e023e832
AG
4704{
4705 gen_intermediate_code_internal(env, tb, 1);
4706}
4707
a4e3ad19 4708void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos)
e023e832
AG
4709{
4710 int cc_op;
25983cad 4711 env->psw.addr = tcg_ctx.gen_opc_pc[pc_pos];
e023e832
AG
4712 cc_op = gen_opc_cc_op[pc_pos];
4713 if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) {
4714 env->cc_op = cc_op;
4715 }
10ec5117 4716}