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