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