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