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