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