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