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