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