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