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