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