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