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