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