]> git.proxmox.com Git - mirror_qemu.git/blame - target-s390x/translate.c
target-s390: Implement LURA, LURAG, STURG
[mirror_qemu.git] / target-s390x / translate.c
CommitLineData
10ec5117
AG
1/*
2 * S/390 translation
3 *
4 * Copyright (c) 2009 Ulrich Hecht
e023e832 5 * Copyright (c) 2010 Alexander Graf
10ec5117
AG
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
70539e18 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
10ec5117 19 */
e023e832 20
e023e832
AG
21/* #define DEBUG_INLINE_BRANCHES */
22#define S390X_DEBUG_DISAS
23/* #define S390X_DEBUG_DISAS_VERBOSE */
24
25#ifdef S390X_DEBUG_DISAS_VERBOSE
26# define LOG_DISAS(...) qemu_log(__VA_ARGS__)
27#else
28# define LOG_DISAS(...) do { } while (0)
29#endif
10ec5117
AG
30
31#include "cpu.h"
76cad711 32#include "disas/disas.h"
10ec5117 33#include "tcg-op.h"
1de7afc9 34#include "qemu/log.h"
58a9e35b 35#include "qemu/host-utils.h"
f08b6170 36#include "exec/cpu_ldst.h"
10ec5117 37
e023e832
AG
38/* global register indexes */
39static TCGv_ptr cpu_env;
40
022c62cb 41#include "exec/gen-icount.h"
2ef6175a
RH
42#include "exec/helper-proto.h"
43#include "exec/helper-gen.h"
e023e832 44
a7e30d84
LV
45#include "trace-tcg.h"
46
ad044d09
RH
47
48/* Information that (most) every instruction needs to manipulate. */
e023e832 49typedef struct DisasContext DisasContext;
ad044d09
RH
50typedef struct DisasInsn DisasInsn;
51typedef struct DisasFields DisasFields;
52
e023e832 53struct DisasContext {
e023e832 54 struct TranslationBlock *tb;
ad044d09
RH
55 const DisasInsn *insn;
56 DisasFields *fields;
57 uint64_t pc, next_pc;
58 enum cc_op cc_op;
59 bool singlestep_enabled;
e023e832
AG
60};
61
3fde06f5
RH
62/* Information carried about a condition to be evaluated. */
63typedef struct {
64 TCGCond cond:8;
65 bool is_64;
66 bool g1;
67 bool g2;
68 union {
69 struct { TCGv_i64 a, b; } s64;
70 struct { TCGv_i32 a, b; } s32;
71 } u;
72} DisasCompare;
73
e023e832
AG
74#define DISAS_EXCP 4
75
e023e832
AG
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
4f3adfb2 81static uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
e023e832
AG
82{
83 if (!(s->tb->flags & FLAG_MASK_64)) {
84 if (s->tb->flags & FLAG_MASK_32) {
85 return pc | 0x80000000;
86 }
87 }
88 return pc;
89}
90
878096ee
AF
91void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
92 int flags)
10ec5117 93{
878096ee
AF
94 S390CPU *cpu = S390_CPU(cs);
95 CPUS390XState *env = &cpu->env;
10ec5117 96 int i;
e023e832 97
d885bdd4
RH
98 if (env->cc_op > 3) {
99 cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %15s\n",
100 env->psw.mask, env->psw.addr, cc_name(env->cc_op));
101 } else {
102 cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %02x\n",
103 env->psw.mask, env->psw.addr, env->cc_op);
104 }
105
10ec5117 106 for (i = 0; i < 16; i++) {
e023e832 107 cpu_fprintf(f, "R%02d=%016" PRIx64, i, env->regs[i]);
10ec5117
AG
108 if ((i % 4) == 3) {
109 cpu_fprintf(f, "\n");
110 } else {
111 cpu_fprintf(f, " ");
112 }
113 }
e023e832 114
10ec5117 115 for (i = 0; i < 16; i++) {
431253c2 116 cpu_fprintf(f, "F%02d=%016" PRIx64, i, env->fregs[i].ll);
10ec5117
AG
117 if ((i % 4) == 3) {
118 cpu_fprintf(f, "\n");
119 } else {
120 cpu_fprintf(f, " ");
121 }
122 }
e023e832 123
e023e832
AG
124#ifndef CONFIG_USER_ONLY
125 for (i = 0; i < 16; i++) {
126 cpu_fprintf(f, "C%02d=%016" PRIx64, i, env->cregs[i]);
127 if ((i % 4) == 3) {
128 cpu_fprintf(f, "\n");
129 } else {
130 cpu_fprintf(f, " ");
131 }
132 }
133#endif
134
e023e832
AG
135#ifdef DEBUG_INLINE_BRANCHES
136 for (i = 0; i < CC_OP_MAX; i++) {
137 cpu_fprintf(f, " %15s = %10ld\t%10ld\n", cc_name(i),
138 inline_branch_miss[i], inline_branch_hit[i]);
139 }
140#endif
d885bdd4
RH
141
142 cpu_fprintf(f, "\n");
10ec5117
AG
143}
144
e023e832
AG
145static TCGv_i64 psw_addr;
146static TCGv_i64 psw_mask;
147
148static TCGv_i32 cc_op;
149static TCGv_i64 cc_src;
150static TCGv_i64 cc_dst;
151static TCGv_i64 cc_vr;
152
431253c2 153static char cpu_reg_names[32][4];
e023e832 154static TCGv_i64 regs[16];
431253c2 155static TCGv_i64 fregs[16];
e023e832
AG
156
157static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
158
d5a43964
AG
159void s390x_translate_init(void)
160{
e023e832 161 int i;
e023e832
AG
162
163 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
431253c2
RH
164 psw_addr = tcg_global_mem_new_i64(TCG_AREG0,
165 offsetof(CPUS390XState, psw.addr),
e023e832 166 "psw_addr");
431253c2
RH
167 psw_mask = tcg_global_mem_new_i64(TCG_AREG0,
168 offsetof(CPUS390XState, psw.mask),
e023e832
AG
169 "psw_mask");
170
a4e3ad19 171 cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUS390XState, cc_op),
e023e832 172 "cc_op");
a4e3ad19 173 cc_src = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_src),
e023e832 174 "cc_src");
a4e3ad19 175 cc_dst = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_dst),
e023e832 176 "cc_dst");
a4e3ad19 177 cc_vr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_vr),
e023e832
AG
178 "cc_vr");
179
e023e832 180 for (i = 0; i < 16; i++) {
431253c2 181 snprintf(cpu_reg_names[i], sizeof(cpu_reg_names[0]), "r%d", i);
e023e832 182 regs[i] = tcg_global_mem_new(TCG_AREG0,
431253c2
RH
183 offsetof(CPUS390XState, regs[i]),
184 cpu_reg_names[i]);
185 }
186
187 for (i = 0; i < 16; i++) {
188 snprintf(cpu_reg_names[i + 16], sizeof(cpu_reg_names[0]), "f%d", i);
189 fregs[i] = tcg_global_mem_new(TCG_AREG0,
190 offsetof(CPUS390XState, fregs[i].d),
191 cpu_reg_names[i + 16]);
e023e832 192 }
d5a43964
AG
193}
194
4f3adfb2 195static TCGv_i64 load_reg(int reg)
10ec5117 196{
e023e832
AG
197 TCGv_i64 r = tcg_temp_new_i64();
198 tcg_gen_mov_i64(r, regs[reg]);
199 return r;
10ec5117
AG
200}
201
4f3adfb2 202static TCGv_i64 load_freg32_i64(int reg)
d764a8d1
RH
203{
204 TCGv_i64 r = tcg_temp_new_i64();
205 tcg_gen_shri_i64(r, fregs[reg], 32);
206 return r;
207}
208
4f3adfb2 209static void store_reg(int reg, TCGv_i64 v)
e023e832
AG
210{
211 tcg_gen_mov_i64(regs[reg], v);
212}
213
4f3adfb2 214static void store_freg(int reg, TCGv_i64 v)
e023e832 215{
431253c2 216 tcg_gen_mov_i64(fregs[reg], v);
e023e832
AG
217}
218
4f3adfb2 219static void store_reg32_i64(int reg, TCGv_i64 v)
e023e832
AG
220{
221 /* 32 bit register writes keep the upper half */
e023e832 222 tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
e023e832
AG
223}
224
4f3adfb2 225static void store_reg32h_i64(int reg, TCGv_i64 v)
77f8d6c3
RH
226{
227 tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
228}
229
4f3adfb2 230static void store_freg32_i64(int reg, TCGv_i64 v)
d764a8d1
RH
231{
232 tcg_gen_deposit_i64(fregs[reg], fregs[reg], v, 32, 32);
233}
234
4f3adfb2 235static void return_low128(TCGv_i64 dest)
1ac5889f
RH
236{
237 tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
238}
239
4f3adfb2 240static void update_psw_addr(DisasContext *s)
e023e832
AG
241{
242 /* psw.addr */
243 tcg_gen_movi_i64(psw_addr, s->pc);
244}
245
7a6c7067
RH
246static void update_cc_op(DisasContext *s)
247{
248 if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
249 tcg_gen_movi_i32(cc_op, s->cc_op);
250 }
251}
252
4f3adfb2 253static void potential_page_fault(DisasContext *s)
e023e832 254{
e023e832 255 update_psw_addr(s);
7a6c7067 256 update_cc_op(s);
e023e832
AG
257}
258
46ee3d84 259static inline uint64_t ld_code2(CPUS390XState *env, uint64_t pc)
e023e832 260{
46ee3d84 261 return (uint64_t)cpu_lduw_code(env, pc);
e023e832
AG
262}
263
46ee3d84 264static inline uint64_t ld_code4(CPUS390XState *env, uint64_t pc)
e023e832 265{
ad044d09 266 return (uint64_t)(uint32_t)cpu_ldl_code(env, pc);
e023e832
AG
267}
268
4f3adfb2 269static int get_mem_index(DisasContext *s)
e023e832
AG
270{
271 switch (s->tb->flags & FLAG_MASK_ASC) {
272 case PSW_ASC_PRIMARY >> 32:
273 return 0;
274 case PSW_ASC_SECONDARY >> 32:
275 return 1;
276 case PSW_ASC_HOME >> 32:
277 return 2;
278 default:
279 tcg_abort();
280 break;
281 }
282}
283
d5a103cd 284static void gen_exception(int excp)
e023e832 285{
d5a103cd 286 TCGv_i32 tmp = tcg_const_i32(excp);
089f5c06 287 gen_helper_exception(cpu_env, tmp);
e023e832 288 tcg_temp_free_i32(tmp);
e023e832
AG
289}
290
d5a103cd 291static void gen_program_exception(DisasContext *s, int code)
e023e832
AG
292{
293 TCGv_i32 tmp;
294
d5a103cd 295 /* Remember what pgm exeption this was. */
e023e832 296 tmp = tcg_const_i32(code);
a4e3ad19 297 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
e023e832
AG
298 tcg_temp_free_i32(tmp);
299
d5a103cd
RH
300 tmp = tcg_const_i32(s->next_pc - s->pc);
301 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen));
e023e832
AG
302 tcg_temp_free_i32(tmp);
303
d5a103cd
RH
304 /* Advance past instruction. */
305 s->pc = s->next_pc;
e023e832
AG
306 update_psw_addr(s);
307
d5a103cd 308 /* Save off cc. */
7a6c7067 309 update_cc_op(s);
e023e832 310
d5a103cd
RH
311 /* Trigger exception. */
312 gen_exception(EXCP_PGM);
e023e832
AG
313}
314
d5a103cd 315static inline void gen_illegal_opcode(DisasContext *s)
e023e832 316{
d5a103cd 317 gen_program_exception(s, PGM_SPECIFICATION);
e023e832
AG
318}
319
d5a103cd 320static inline void check_privileged(DisasContext *s)
e023e832
AG
321{
322 if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
d5a103cd 323 gen_program_exception(s, PGM_PRIVILEGED);
e023e832
AG
324 }
325}
326
e023e832
AG
327static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
328{
bacf43c6
RH
329 TCGv_i64 tmp = tcg_temp_new_i64();
330 bool need_31 = !(s->tb->flags & FLAG_MASK_64);
e023e832 331
bacf43c6
RH
332 /* Note that d2 is limited to 20 bits, signed. If we crop negative
333 displacements early we create larger immedate addends. */
e023e832 334
bacf43c6
RH
335 /* Note that addi optimizes the imm==0 case. */
336 if (b2 && x2) {
337 tcg_gen_add_i64(tmp, regs[b2], regs[x2]);
338 tcg_gen_addi_i64(tmp, tmp, d2);
e023e832 339 } else if (b2) {
bacf43c6
RH
340 tcg_gen_addi_i64(tmp, regs[b2], d2);
341 } else if (x2) {
342 tcg_gen_addi_i64(tmp, regs[x2], d2);
e023e832 343 } else {
bacf43c6
RH
344 if (need_31) {
345 d2 &= 0x7fffffff;
346 need_31 = false;
347 }
348 tcg_gen_movi_i64(tmp, d2);
e023e832 349 }
bacf43c6
RH
350 if (need_31) {
351 tcg_gen_andi_i64(tmp, tmp, 0x7fffffff);
e023e832
AG
352 }
353
354 return tmp;
355}
356
f24c49c2
RH
357static inline bool live_cc_data(DisasContext *s)
358{
359 return (s->cc_op != CC_OP_DYNAMIC
360 && s->cc_op != CC_OP_STATIC
361 && s->cc_op > 3);
362}
363
aa31bf60 364static inline void gen_op_movi_cc(DisasContext *s, uint32_t val)
e023e832 365{
f24c49c2
RH
366 if (live_cc_data(s)) {
367 tcg_gen_discard_i64(cc_src);
368 tcg_gen_discard_i64(cc_dst);
369 tcg_gen_discard_i64(cc_vr);
370 }
e023e832
AG
371 s->cc_op = CC_OP_CONST0 + val;
372}
373
374static void gen_op_update1_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 dst)
375{
f24c49c2
RH
376 if (live_cc_data(s)) {
377 tcg_gen_discard_i64(cc_src);
378 tcg_gen_discard_i64(cc_vr);
379 }
e023e832 380 tcg_gen_mov_i64(cc_dst, dst);
e023e832
AG
381 s->cc_op = op;
382}
383
e023e832
AG
384static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
385 TCGv_i64 dst)
386{
f24c49c2
RH
387 if (live_cc_data(s)) {
388 tcg_gen_discard_i64(cc_vr);
389 }
e023e832
AG
390 tcg_gen_mov_i64(cc_src, src);
391 tcg_gen_mov_i64(cc_dst, dst);
e023e832
AG
392 s->cc_op = op;
393}
394
e023e832
AG
395static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
396 TCGv_i64 dst, TCGv_i64 vr)
397{
398 tcg_gen_mov_i64(cc_src, src);
399 tcg_gen_mov_i64(cc_dst, dst);
400 tcg_gen_mov_i64(cc_vr, vr);
401 s->cc_op = op;
402}
403
4f3adfb2 404static void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
e023e832
AG
405{
406 gen_op_update1_cc_i64(s, CC_OP_NZ, val);
407}
408
4f3adfb2 409static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i64 val)
68c8bd93
RH
410{
411 gen_op_update1_cc_i64(s, CC_OP_NZ_F32, val);
412}
413
4f3adfb2 414static void gen_set_cc_nz_f64(DisasContext *s, TCGv_i64 val)
68c8bd93
RH
415{
416 gen_op_update1_cc_i64(s, CC_OP_NZ_F64, val);
417}
418
4f3adfb2 419static void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
68c8bd93
RH
420{
421 gen_op_update2_cc_i64(s, CC_OP_NZ_F128, vh, vl);
422}
423
e023e832 424/* CC value is in env->cc_op */
4f3adfb2 425static void set_cc_static(DisasContext *s)
e023e832 426{
f24c49c2
RH
427 if (live_cc_data(s)) {
428 tcg_gen_discard_i64(cc_src);
429 tcg_gen_discard_i64(cc_dst);
430 tcg_gen_discard_i64(cc_vr);
431 }
e023e832
AG
432 s->cc_op = CC_OP_STATIC;
433}
434
e023e832
AG
435/* calculates cc into cc_op */
436static void gen_op_calc_cc(DisasContext *s)
437{
7a6c7067
RH
438 TCGv_i32 local_cc_op;
439 TCGv_i64 dummy;
440
441 TCGV_UNUSED_I32(local_cc_op);
442 TCGV_UNUSED_I64(dummy);
443 switch (s->cc_op) {
444 default:
445 dummy = tcg_const_i64(0);
446 /* FALLTHRU */
447 case CC_OP_ADD_64:
448 case CC_OP_ADDU_64:
449 case CC_OP_ADDC_64:
450 case CC_OP_SUB_64:
451 case CC_OP_SUBU_64:
452 case CC_OP_SUBB_64:
453 case CC_OP_ADD_32:
454 case CC_OP_ADDU_32:
455 case CC_OP_ADDC_32:
456 case CC_OP_SUB_32:
457 case CC_OP_SUBU_32:
458 case CC_OP_SUBB_32:
459 local_cc_op = tcg_const_i32(s->cc_op);
460 break;
461 case CC_OP_CONST0:
462 case CC_OP_CONST1:
463 case CC_OP_CONST2:
464 case CC_OP_CONST3:
465 case CC_OP_STATIC:
466 case CC_OP_DYNAMIC:
467 break;
468 }
e023e832
AG
469
470 switch (s->cc_op) {
471 case CC_OP_CONST0:
472 case CC_OP_CONST1:
473 case CC_OP_CONST2:
474 case CC_OP_CONST3:
475 /* s->cc_op is the cc value */
476 tcg_gen_movi_i32(cc_op, s->cc_op - CC_OP_CONST0);
477 break;
478 case CC_OP_STATIC:
479 /* env->cc_op already is the cc value */
480 break;
481 case CC_OP_NZ:
482 case CC_OP_ABS_64:
483 case CC_OP_NABS_64:
484 case CC_OP_ABS_32:
485 case CC_OP_NABS_32:
486 case CC_OP_LTGT0_32:
487 case CC_OP_LTGT0_64:
488 case CC_OP_COMP_32:
489 case CC_OP_COMP_64:
490 case CC_OP_NZ_F32:
491 case CC_OP_NZ_F64:
102bf2c6 492 case CC_OP_FLOGR:
e023e832 493 /* 1 argument */
932385a3 494 gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
e023e832
AG
495 break;
496 case CC_OP_ICM:
497 case CC_OP_LTGT_32:
498 case CC_OP_LTGT_64:
499 case CC_OP_LTUGTU_32:
500 case CC_OP_LTUGTU_64:
501 case CC_OP_TM_32:
502 case CC_OP_TM_64:
cbe24bfa
RH
503 case CC_OP_SLA_32:
504 case CC_OP_SLA_64:
587626f8 505 case CC_OP_NZ_F128:
e023e832 506 /* 2 arguments */
932385a3 507 gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
e023e832
AG
508 break;
509 case CC_OP_ADD_64:
510 case CC_OP_ADDU_64:
4e4bb438 511 case CC_OP_ADDC_64:
e023e832
AG
512 case CC_OP_SUB_64:
513 case CC_OP_SUBU_64:
4e4bb438 514 case CC_OP_SUBB_64:
e023e832
AG
515 case CC_OP_ADD_32:
516 case CC_OP_ADDU_32:
4e4bb438 517 case CC_OP_ADDC_32:
e023e832
AG
518 case CC_OP_SUB_32:
519 case CC_OP_SUBU_32:
4e4bb438 520 case CC_OP_SUBB_32:
e023e832 521 /* 3 arguments */
932385a3 522 gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, cc_vr);
e023e832
AG
523 break;
524 case CC_OP_DYNAMIC:
525 /* unknown operation - assume 3 arguments and cc_op in env */
932385a3 526 gen_helper_calc_cc(cc_op, cpu_env, cc_op, cc_src, cc_dst, cc_vr);
e023e832
AG
527 break;
528 default:
529 tcg_abort();
530 }
531
7a6c7067
RH
532 if (!TCGV_IS_UNUSED_I32(local_cc_op)) {
533 tcg_temp_free_i32(local_cc_op);
534 }
535 if (!TCGV_IS_UNUSED_I64(dummy)) {
536 tcg_temp_free_i64(dummy);
537 }
e023e832
AG
538
539 /* We now have cc in cc_op as constant */
540 set_cc_static(s);
541}
542
8ac33cdb 543static int use_goto_tb(DisasContext *s, uint64_t dest)
e023e832 544{
8ac33cdb
RH
545 /* NOTE: we handle the case where the TB spans two pages here */
546 return (((dest & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK)
547 || (dest & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))
548 && !s->singlestep_enabled
549 && !(s->tb->cflags & CF_LAST_IO));
550}
e023e832 551
4f3adfb2 552static void account_noninline_branch(DisasContext *s, int cc_op)
e023e832
AG
553{
554#ifdef DEBUG_INLINE_BRANCHES
555 inline_branch_miss[cc_op]++;
556#endif
557}
558
4f3adfb2 559static void account_inline_branch(DisasContext *s, int cc_op)
e023e832
AG
560{
561#ifdef DEBUG_INLINE_BRANCHES
3fde06f5 562 inline_branch_hit[cc_op]++;
e023e832
AG
563#endif
564}
565
3fde06f5 566/* Table of mask values to comparison codes, given a comparison as input.
de379661 567 For such, CC=3 should not be possible. */
3fde06f5
RH
568static const TCGCond ltgt_cond[16] = {
569 TCG_COND_NEVER, TCG_COND_NEVER, /* | | | x */
de379661
RH
570 TCG_COND_GT, TCG_COND_GT, /* | | GT | x */
571 TCG_COND_LT, TCG_COND_LT, /* | LT | | x */
572 TCG_COND_NE, TCG_COND_NE, /* | LT | GT | x */
573 TCG_COND_EQ, TCG_COND_EQ, /* EQ | | | x */
574 TCG_COND_GE, TCG_COND_GE, /* EQ | | GT | x */
575 TCG_COND_LE, TCG_COND_LE, /* EQ | LT | | x */
3fde06f5
RH
576 TCG_COND_ALWAYS, TCG_COND_ALWAYS, /* EQ | LT | GT | x */
577};
578
579/* Table of mask values to comparison codes, given a logic op as input.
580 For such, only CC=0 and CC=1 should be possible. */
581static const TCGCond nz_cond[16] = {
de379661
RH
582 TCG_COND_NEVER, TCG_COND_NEVER, /* | | x | x */
583 TCG_COND_NEVER, TCG_COND_NEVER,
584 TCG_COND_NE, TCG_COND_NE, /* | NE | x | x */
585 TCG_COND_NE, TCG_COND_NE,
586 TCG_COND_EQ, TCG_COND_EQ, /* EQ | | x | x */
587 TCG_COND_EQ, TCG_COND_EQ,
588 TCG_COND_ALWAYS, TCG_COND_ALWAYS, /* EQ | NE | x | x */
589 TCG_COND_ALWAYS, TCG_COND_ALWAYS,
3fde06f5
RH
590};
591
592/* Interpret MASK in terms of S->CC_OP, and fill in C with all the
593 details required to generate a TCG comparison. */
594static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
e023e832 595{
3fde06f5
RH
596 TCGCond cond;
597 enum cc_op old_cc_op = s->cc_op;
e023e832 598
3fde06f5
RH
599 if (mask == 15 || mask == 0) {
600 c->cond = (mask ? TCG_COND_ALWAYS : TCG_COND_NEVER);
601 c->u.s32.a = cc_op;
602 c->u.s32.b = cc_op;
603 c->g1 = c->g2 = true;
604 c->is_64 = false;
605 return;
606 }
607
608 /* Find the TCG condition for the mask + cc op. */
609 switch (old_cc_op) {
e023e832 610 case CC_OP_LTGT0_32:
e023e832 611 case CC_OP_LTGT0_64:
e023e832 612 case CC_OP_LTGT_32:
e023e832 613 case CC_OP_LTGT_64:
3fde06f5
RH
614 cond = ltgt_cond[mask];
615 if (cond == TCG_COND_NEVER) {
e023e832
AG
616 goto do_dynamic;
617 }
3fde06f5 618 account_inline_branch(s, old_cc_op);
e023e832 619 break;
3fde06f5 620
e023e832 621 case CC_OP_LTUGTU_32:
e023e832 622 case CC_OP_LTUGTU_64:
3fde06f5
RH
623 cond = tcg_unsigned_cond(ltgt_cond[mask]);
624 if (cond == TCG_COND_NEVER) {
e023e832
AG
625 goto do_dynamic;
626 }
3fde06f5 627 account_inline_branch(s, old_cc_op);
e023e832 628 break;
3fde06f5 629
e023e832 630 case CC_OP_NZ:
3fde06f5
RH
631 cond = nz_cond[mask];
632 if (cond == TCG_COND_NEVER) {
e023e832
AG
633 goto do_dynamic;
634 }
3fde06f5 635 account_inline_branch(s, old_cc_op);
e023e832 636 break;
e023e832 637
3fde06f5 638 case CC_OP_TM_32:
e023e832 639 case CC_OP_TM_64:
e023e832 640 switch (mask) {
3fde06f5
RH
641 case 8:
642 cond = TCG_COND_EQ;
e023e832 643 break;
3fde06f5
RH
644 case 4 | 2 | 1:
645 cond = TCG_COND_NE;
e023e832
AG
646 break;
647 default:
648 goto do_dynamic;
649 }
3fde06f5 650 account_inline_branch(s, old_cc_op);
e023e832 651 break;
3fde06f5 652
e023e832
AG
653 case CC_OP_ICM:
654 switch (mask) {
3fde06f5
RH
655 case 8:
656 cond = TCG_COND_EQ;
e023e832 657 break;
3fde06f5
RH
658 case 4 | 2 | 1:
659 case 4 | 2:
660 cond = TCG_COND_NE;
e023e832
AG
661 break;
662 default:
663 goto do_dynamic;
664 }
3fde06f5 665 account_inline_branch(s, old_cc_op);
e023e832 666 break;
3fde06f5 667
102bf2c6
RH
668 case CC_OP_FLOGR:
669 switch (mask & 0xa) {
670 case 8: /* src == 0 -> no one bit found */
671 cond = TCG_COND_EQ;
672 break;
673 case 2: /* src != 0 -> one bit found */
674 cond = TCG_COND_NE;
675 break;
676 default:
677 goto do_dynamic;
678 }
679 account_inline_branch(s, old_cc_op);
680 break;
681
a359b770
RH
682 case CC_OP_ADDU_32:
683 case CC_OP_ADDU_64:
684 switch (mask) {
685 case 8 | 2: /* vr == 0 */
686 cond = TCG_COND_EQ;
687 break;
688 case 4 | 1: /* vr != 0 */
689 cond = TCG_COND_NE;
690 break;
691 case 8 | 4: /* no carry -> vr >= src */
692 cond = TCG_COND_GEU;
693 break;
694 case 2 | 1: /* carry -> vr < src */
695 cond = TCG_COND_LTU;
696 break;
697 default:
698 goto do_dynamic;
699 }
700 account_inline_branch(s, old_cc_op);
701 break;
702
703 case CC_OP_SUBU_32:
704 case CC_OP_SUBU_64:
705 /* Note that CC=0 is impossible; treat it as dont-care. */
706 switch (mask & 7) {
707 case 2: /* zero -> op1 == op2 */
708 cond = TCG_COND_EQ;
709 break;
710 case 4 | 1: /* !zero -> op1 != op2 */
711 cond = TCG_COND_NE;
712 break;
713 case 4: /* borrow (!carry) -> op1 < op2 */
714 cond = TCG_COND_LTU;
715 break;
716 case 2 | 1: /* !borrow (carry) -> op1 >= op2 */
717 cond = TCG_COND_GEU;
718 break;
719 default:
720 goto do_dynamic;
721 }
722 account_inline_branch(s, old_cc_op);
723 break;
724
e023e832 725 default:
3fde06f5
RH
726 do_dynamic:
727 /* Calculate cc value. */
e023e832 728 gen_op_calc_cc(s);
3fde06f5 729 /* FALLTHRU */
e023e832 730
3fde06f5
RH
731 case CC_OP_STATIC:
732 /* Jump based on CC. We'll load up the real cond below;
733 the assignment here merely avoids a compiler warning. */
e023e832 734 account_noninline_branch(s, old_cc_op);
3fde06f5
RH
735 old_cc_op = CC_OP_STATIC;
736 cond = TCG_COND_NEVER;
737 break;
738 }
e023e832 739
3fde06f5
RH
740 /* Load up the arguments of the comparison. */
741 c->is_64 = true;
742 c->g1 = c->g2 = false;
743 switch (old_cc_op) {
744 case CC_OP_LTGT0_32:
745 c->is_64 = false;
746 c->u.s32.a = tcg_temp_new_i32();
747 tcg_gen_trunc_i64_i32(c->u.s32.a, cc_dst);
748 c->u.s32.b = tcg_const_i32(0);
749 break;
750 case CC_OP_LTGT_32:
751 case CC_OP_LTUGTU_32:
a359b770 752 case CC_OP_SUBU_32:
3fde06f5
RH
753 c->is_64 = false;
754 c->u.s32.a = tcg_temp_new_i32();
755 tcg_gen_trunc_i64_i32(c->u.s32.a, cc_src);
756 c->u.s32.b = tcg_temp_new_i32();
757 tcg_gen_trunc_i64_i32(c->u.s32.b, cc_dst);
758 break;
759
760 case CC_OP_LTGT0_64:
761 case CC_OP_NZ:
102bf2c6 762 case CC_OP_FLOGR:
3fde06f5
RH
763 c->u.s64.a = cc_dst;
764 c->u.s64.b = tcg_const_i64(0);
765 c->g1 = true;
766 break;
767 case CC_OP_LTGT_64:
768 case CC_OP_LTUGTU_64:
a359b770 769 case CC_OP_SUBU_64:
3fde06f5
RH
770 c->u.s64.a = cc_src;
771 c->u.s64.b = cc_dst;
772 c->g1 = c->g2 = true;
773 break;
774
775 case CC_OP_TM_32:
776 case CC_OP_TM_64:
58a9e35b 777 case CC_OP_ICM:
3fde06f5
RH
778 c->u.s64.a = tcg_temp_new_i64();
779 c->u.s64.b = tcg_const_i64(0);
780 tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst);
781 break;
a359b770
RH
782
783 case CC_OP_ADDU_32:
784 c->is_64 = false;
785 c->u.s32.a = tcg_temp_new_i32();
786 c->u.s32.b = tcg_temp_new_i32();
787 tcg_gen_trunc_i64_i32(c->u.s32.a, cc_vr);
788 if (cond == TCG_COND_EQ || cond == TCG_COND_NE) {
789 tcg_gen_movi_i32(c->u.s32.b, 0);
790 } else {
791 tcg_gen_trunc_i64_i32(c->u.s32.b, cc_src);
792 }
793 break;
794
795 case CC_OP_ADDU_64:
796 c->u.s64.a = cc_vr;
797 c->g1 = true;
798 if (cond == TCG_COND_EQ || cond == TCG_COND_NE) {
799 c->u.s64.b = tcg_const_i64(0);
800 } else {
801 c->u.s64.b = cc_src;
802 c->g2 = true;
803 }
804 break;
3fde06f5
RH
805
806 case CC_OP_STATIC:
807 c->is_64 = false;
808 c->u.s32.a = cc_op;
809 c->g1 = true;
e023e832 810 switch (mask) {
e023e832 811 case 0x8 | 0x4 | 0x2: /* cc != 3 */
3fde06f5
RH
812 cond = TCG_COND_NE;
813 c->u.s32.b = tcg_const_i32(3);
e023e832
AG
814 break;
815 case 0x8 | 0x4 | 0x1: /* cc != 2 */
3fde06f5
RH
816 cond = TCG_COND_NE;
817 c->u.s32.b = tcg_const_i32(2);
e023e832
AG
818 break;
819 case 0x8 | 0x2 | 0x1: /* cc != 1 */
3fde06f5
RH
820 cond = TCG_COND_NE;
821 c->u.s32.b = tcg_const_i32(1);
e023e832 822 break;
3fde06f5
RH
823 case 0x8 | 0x2: /* cc == 0 || cc == 2 => (cc & 1) == 0 */
824 cond = TCG_COND_EQ;
825 c->g1 = false;
826 c->u.s32.a = tcg_temp_new_i32();
827 c->u.s32.b = tcg_const_i32(0);
828 tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
e023e832
AG
829 break;
830 case 0x8 | 0x4: /* cc < 2 */
3fde06f5
RH
831 cond = TCG_COND_LTU;
832 c->u.s32.b = tcg_const_i32(2);
e023e832
AG
833 break;
834 case 0x8: /* cc == 0 */
3fde06f5
RH
835 cond = TCG_COND_EQ;
836 c->u.s32.b = tcg_const_i32(0);
e023e832
AG
837 break;
838 case 0x4 | 0x2 | 0x1: /* cc != 0 */
3fde06f5
RH
839 cond = TCG_COND_NE;
840 c->u.s32.b = tcg_const_i32(0);
e023e832 841 break;
3fde06f5
RH
842 case 0x4 | 0x1: /* cc == 1 || cc == 3 => (cc & 1) != 0 */
843 cond = TCG_COND_NE;
844 c->g1 = false;
845 c->u.s32.a = tcg_temp_new_i32();
846 c->u.s32.b = tcg_const_i32(0);
847 tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
e023e832
AG
848 break;
849 case 0x4: /* cc == 1 */
3fde06f5
RH
850 cond = TCG_COND_EQ;
851 c->u.s32.b = tcg_const_i32(1);
e023e832
AG
852 break;
853 case 0x2 | 0x1: /* cc > 1 */
3fde06f5
RH
854 cond = TCG_COND_GTU;
855 c->u.s32.b = tcg_const_i32(1);
e023e832
AG
856 break;
857 case 0x2: /* cc == 2 */
3fde06f5
RH
858 cond = TCG_COND_EQ;
859 c->u.s32.b = tcg_const_i32(2);
e023e832
AG
860 break;
861 case 0x1: /* cc == 3 */
3fde06f5
RH
862 cond = TCG_COND_EQ;
863 c->u.s32.b = tcg_const_i32(3);
e023e832 864 break;
3fde06f5
RH
865 default:
866 /* CC is masked by something else: (8 >> cc) & mask. */
867 cond = TCG_COND_NE;
868 c->g1 = false;
869 c->u.s32.a = tcg_const_i32(8);
870 c->u.s32.b = tcg_const_i32(0);
871 tcg_gen_shr_i32(c->u.s32.a, c->u.s32.a, cc_op);
872 tcg_gen_andi_i32(c->u.s32.a, c->u.s32.a, mask);
e023e832
AG
873 break;
874 }
875 break;
3fde06f5
RH
876
877 default:
878 abort();
e023e832 879 }
3fde06f5
RH
880 c->cond = cond;
881}
882
883static void free_compare(DisasCompare *c)
884{
885 if (!c->g1) {
886 if (c->is_64) {
887 tcg_temp_free_i64(c->u.s64.a);
888 } else {
889 tcg_temp_free_i32(c->u.s32.a);
890 }
891 }
892 if (!c->g2) {
893 if (c->is_64) {
894 tcg_temp_free_i64(c->u.s64.b);
895 } else {
896 tcg_temp_free_i32(c->u.s32.b);
897 }
898 }
899}
900
ad044d09
RH
901/* ====================================================================== */
902/* Define the insn format enumeration. */
903#define F0(N) FMT_##N,
904#define F1(N, X1) F0(N)
905#define F2(N, X1, X2) F0(N)
906#define F3(N, X1, X2, X3) F0(N)
907#define F4(N, X1, X2, X3, X4) F0(N)
908#define F5(N, X1, X2, X3, X4, X5) F0(N)
909
910typedef enum {
911#include "insn-format.def"
912} DisasFormat;
913
914#undef F0
915#undef F1
916#undef F2
917#undef F3
918#undef F4
919#undef F5
920
921/* Define a structure to hold the decoded fields. We'll store each inside
922 an array indexed by an enum. In order to conserve memory, we'll arrange
923 for fields that do not exist at the same time to overlap, thus the "C"
924 for compact. For checking purposes there is an "O" for original index
925 as well that will be applied to availability bitmaps. */
926
927enum DisasFieldIndexO {
928 FLD_O_r1,
929 FLD_O_r2,
930 FLD_O_r3,
931 FLD_O_m1,
932 FLD_O_m3,
933 FLD_O_m4,
934 FLD_O_b1,
935 FLD_O_b2,
936 FLD_O_b4,
937 FLD_O_d1,
938 FLD_O_d2,
939 FLD_O_d4,
940 FLD_O_x2,
941 FLD_O_l1,
942 FLD_O_l2,
943 FLD_O_i1,
944 FLD_O_i2,
945 FLD_O_i3,
946 FLD_O_i4,
947 FLD_O_i5
948};
949
950enum DisasFieldIndexC {
951 FLD_C_r1 = 0,
952 FLD_C_m1 = 0,
953 FLD_C_b1 = 0,
954 FLD_C_i1 = 0,
955
956 FLD_C_r2 = 1,
957 FLD_C_b2 = 1,
958 FLD_C_i2 = 1,
959
960 FLD_C_r3 = 2,
961 FLD_C_m3 = 2,
962 FLD_C_i3 = 2,
963
964 FLD_C_m4 = 3,
965 FLD_C_b4 = 3,
966 FLD_C_i4 = 3,
967 FLD_C_l1 = 3,
968
969 FLD_C_i5 = 4,
970 FLD_C_d1 = 4,
971
972 FLD_C_d2 = 5,
973
974 FLD_C_d4 = 6,
975 FLD_C_x2 = 6,
976 FLD_C_l2 = 6,
977
978 NUM_C_FIELD = 7
979};
980
981struct DisasFields {
982 unsigned op:8;
983 unsigned op2:8;
984 unsigned presentC:16;
985 unsigned int presentO;
986 int c[NUM_C_FIELD];
987};
988
989/* This is the way fields are to be accessed out of DisasFields. */
990#define have_field(S, F) have_field1((S), FLD_O_##F)
991#define get_field(S, F) get_field1((S), FLD_O_##F, FLD_C_##F)
992
993static bool have_field1(const DisasFields *f, enum DisasFieldIndexO c)
994{
995 return (f->presentO >> c) & 1;
996}
997
998static int get_field1(const DisasFields *f, enum DisasFieldIndexO o,
999 enum DisasFieldIndexC c)
1000{
1001 assert(have_field1(f, o));
1002 return f->c[c];
1003}
1004
1005/* Describe the layout of each field in each format. */
1006typedef struct DisasField {
1007 unsigned int beg:8;
1008 unsigned int size:8;
1009 unsigned int type:2;
1010 unsigned int indexC:6;
1011 enum DisasFieldIndexO indexO:8;
1012} DisasField;
1013
1014typedef struct DisasFormatInfo {
1015 DisasField op[NUM_C_FIELD];
1016} DisasFormatInfo;
1017
1018#define R(N, B) { B, 4, 0, FLD_C_r##N, FLD_O_r##N }
1019#define M(N, B) { B, 4, 0, FLD_C_m##N, FLD_O_m##N }
1020#define BD(N, BB, BD) { BB, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1021 { BD, 12, 0, FLD_C_d##N, FLD_O_d##N }
1022#define BXD(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1023 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
1024 { 20, 12, 0, FLD_C_d##N, FLD_O_d##N }
1025#define BDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1026 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
1027#define BXDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1028 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
1029 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
1030#define I(N, B, S) { B, S, 1, FLD_C_i##N, FLD_O_i##N }
1031#define L(N, B, S) { B, S, 0, FLD_C_l##N, FLD_O_l##N }
1032
1033#define F0(N) { { } },
1034#define F1(N, X1) { { X1 } },
1035#define F2(N, X1, X2) { { X1, X2 } },
1036#define F3(N, X1, X2, X3) { { X1, X2, X3 } },
1037#define F4(N, X1, X2, X3, X4) { { X1, X2, X3, X4 } },
1038#define F5(N, X1, X2, X3, X4, X5) { { X1, X2, X3, X4, X5 } },
1039
1040static const DisasFormatInfo format_info[] = {
1041#include "insn-format.def"
1042};
1043
1044#undef F0
1045#undef F1
1046#undef F2
1047#undef F3
1048#undef F4
1049#undef F5
1050#undef R
1051#undef M
1052#undef BD
1053#undef BXD
1054#undef BDL
1055#undef BXDL
1056#undef I
1057#undef L
1058
1059/* Generally, we'll extract operands into this structures, operate upon
1060 them, and store them back. See the "in1", "in2", "prep", "wout" sets
1061 of routines below for more details. */
1062typedef struct {
1063 bool g_out, g_out2, g_in1, g_in2;
1064 TCGv_i64 out, out2, in1, in2;
1065 TCGv_i64 addr1;
1066} DisasOps;
1067
49f7ee80
RH
1068/* Instructions can place constraints on their operands, raising specification
1069 exceptions if they are violated. To make this easy to automate, each "in1",
1070 "in2", "prep", "wout" helper will have a SPEC_<name> define that equals one
1071 of the following, or 0. To make this easy to document, we'll put the
1072 SPEC_<name> defines next to <name>. */
1073
1074#define SPEC_r1_even 1
1075#define SPEC_r2_even 2
b7886de3
RH
1076#define SPEC_r3_even 4
1077#define SPEC_r1_f128 8
1078#define SPEC_r2_f128 16
49f7ee80 1079
ad044d09
RH
1080/* Return values from translate_one, indicating the state of the TB. */
1081typedef enum {
1082 /* Continue the TB. */
1083 NO_EXIT,
1084 /* We have emitted one or more goto_tb. No fixup required. */
1085 EXIT_GOTO_TB,
1086 /* We are not using a goto_tb (for whatever reason), but have updated
1087 the PC (for whatever reason), so there's no need to do it again on
1088 exiting the TB. */
1089 EXIT_PC_UPDATED,
1090 /* We are exiting the TB, but have neither emitted a goto_tb, nor
1091 updated the PC for the next instruction to be executed. */
1092 EXIT_PC_STALE,
1093 /* We are ending the TB with a noreturn function call, e.g. longjmp.
1094 No following code will be executed. */
1095 EXIT_NORETURN,
1096} ExitStatus;
1097
1098typedef enum DisasFacility {
1099 FAC_Z, /* zarch (default) */
1100 FAC_CASS, /* compare and swap and store */
1101 FAC_CASS2, /* compare and swap and store 2*/
1102 FAC_DFP, /* decimal floating point */
1103 FAC_DFPR, /* decimal floating point rounding */
1104 FAC_DO, /* distinct operands */
1105 FAC_EE, /* execute extensions */
1106 FAC_EI, /* extended immediate */
1107 FAC_FPE, /* floating point extension */
1108 FAC_FPSSH, /* floating point support sign handling */
1109 FAC_FPRGR, /* FPR-GR transfer */
1110 FAC_GIE, /* general instructions extension */
1111 FAC_HFP_MA, /* HFP multiply-and-add/subtract */
1112 FAC_HW, /* high-word */
1113 FAC_IEEEE_SIM, /* IEEE exception sumilation */
1114 FAC_LOC, /* load/store on condition */
1115 FAC_LD, /* long displacement */
1116 FAC_PC, /* population count */
1117 FAC_SCF, /* store clock fast */
1118 FAC_SFLE, /* store facility list extended */
1119} DisasFacility;
1120
1121struct DisasInsn {
1122 unsigned opc:16;
b7886de3
RH
1123 DisasFormat fmt:8;
1124 DisasFacility fac:8;
1125 unsigned spec:8;
ad044d09
RH
1126
1127 const char *name;
1128
1129 void (*help_in1)(DisasContext *, DisasFields *, DisasOps *);
1130 void (*help_in2)(DisasContext *, DisasFields *, DisasOps *);
1131 void (*help_prep)(DisasContext *, DisasFields *, DisasOps *);
1132 void (*help_wout)(DisasContext *, DisasFields *, DisasOps *);
1133 void (*help_cout)(DisasContext *, DisasOps *);
1134 ExitStatus (*help_op)(DisasContext *, DisasOps *);
1135
1136 uint64_t data;
1137};
1138
8ac33cdb 1139/* ====================================================================== */
085d8134 1140/* Miscellaneous helpers, used by several operations. */
8ac33cdb 1141
cbe24bfa
RH
1142static void help_l2_shift(DisasContext *s, DisasFields *f,
1143 DisasOps *o, int mask)
1144{
1145 int b2 = get_field(f, b2);
1146 int d2 = get_field(f, d2);
1147
1148 if (b2 == 0) {
1149 o->in2 = tcg_const_i64(d2 & mask);
1150 } else {
1151 o->in2 = get_address(s, 0, b2, d2);
1152 tcg_gen_andi_i64(o->in2, o->in2, mask);
1153 }
1154}
1155
8ac33cdb
RH
1156static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
1157{
1158 if (dest == s->next_pc) {
1159 return NO_EXIT;
1160 }
1161 if (use_goto_tb(s, dest)) {
7a6c7067 1162 update_cc_op(s);
8ac33cdb
RH
1163 tcg_gen_goto_tb(0);
1164 tcg_gen_movi_i64(psw_addr, dest);
8cfd0495 1165 tcg_gen_exit_tb((uintptr_t)s->tb);
8ac33cdb
RH
1166 return EXIT_GOTO_TB;
1167 } else {
1168 tcg_gen_movi_i64(psw_addr, dest);
1169 return EXIT_PC_UPDATED;
1170 }
1171}
1172
7233f2ed
RH
1173static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
1174 bool is_imm, int imm, TCGv_i64 cdest)
1175{
1176 ExitStatus ret;
1177 uint64_t dest = s->pc + 2 * imm;
1178 int lab;
1179
1180 /* Take care of the special cases first. */
1181 if (c->cond == TCG_COND_NEVER) {
1182 ret = NO_EXIT;
1183 goto egress;
1184 }
1185 if (is_imm) {
1186 if (dest == s->next_pc) {
1187 /* Branch to next. */
1188 ret = NO_EXIT;
1189 goto egress;
1190 }
1191 if (c->cond == TCG_COND_ALWAYS) {
1192 ret = help_goto_direct(s, dest);
1193 goto egress;
1194 }
1195 } else {
1196 if (TCGV_IS_UNUSED_I64(cdest)) {
1197 /* E.g. bcr %r0 -> no branch. */
1198 ret = NO_EXIT;
1199 goto egress;
1200 }
1201 if (c->cond == TCG_COND_ALWAYS) {
1202 tcg_gen_mov_i64(psw_addr, cdest);
1203 ret = EXIT_PC_UPDATED;
1204 goto egress;
1205 }
1206 }
1207
1208 if (use_goto_tb(s, s->next_pc)) {
1209 if (is_imm && use_goto_tb(s, dest)) {
1210 /* Both exits can use goto_tb. */
7a6c7067 1211 update_cc_op(s);
7233f2ed
RH
1212
1213 lab = gen_new_label();
1214 if (c->is_64) {
1215 tcg_gen_brcond_i64(c->cond, c->u.s64.a, c->u.s64.b, lab);
1216 } else {
1217 tcg_gen_brcond_i32(c->cond, c->u.s32.a, c->u.s32.b, lab);
1218 }
1219
1220 /* Branch not taken. */
1221 tcg_gen_goto_tb(0);
1222 tcg_gen_movi_i64(psw_addr, s->next_pc);
8cfd0495 1223 tcg_gen_exit_tb((uintptr_t)s->tb + 0);
7233f2ed
RH
1224
1225 /* Branch taken. */
1226 gen_set_label(lab);
1227 tcg_gen_goto_tb(1);
1228 tcg_gen_movi_i64(psw_addr, dest);
8cfd0495 1229 tcg_gen_exit_tb((uintptr_t)s->tb + 1);
7233f2ed
RH
1230
1231 ret = EXIT_GOTO_TB;
1232 } else {
1233 /* Fallthru can use goto_tb, but taken branch cannot. */
1234 /* Store taken branch destination before the brcond. This
1235 avoids having to allocate a new local temp to hold it.
1236 We'll overwrite this in the not taken case anyway. */
1237 if (!is_imm) {
1238 tcg_gen_mov_i64(psw_addr, cdest);
1239 }
1240
1241 lab = gen_new_label();
1242 if (c->is_64) {
1243 tcg_gen_brcond_i64(c->cond, c->u.s64.a, c->u.s64.b, lab);
1244 } else {
1245 tcg_gen_brcond_i32(c->cond, c->u.s32.a, c->u.s32.b, lab);
1246 }
1247
1248 /* Branch not taken. */
7a6c7067 1249 update_cc_op(s);
7233f2ed
RH
1250 tcg_gen_goto_tb(0);
1251 tcg_gen_movi_i64(psw_addr, s->next_pc);
8cfd0495 1252 tcg_gen_exit_tb((uintptr_t)s->tb + 0);
7233f2ed
RH
1253
1254 gen_set_label(lab);
1255 if (is_imm) {
1256 tcg_gen_movi_i64(psw_addr, dest);
1257 }
1258 ret = EXIT_PC_UPDATED;
1259 }
1260 } else {
1261 /* Fallthru cannot use goto_tb. This by itself is vanishingly rare.
1262 Most commonly we're single-stepping or some other condition that
1263 disables all use of goto_tb. Just update the PC and exit. */
1264
1265 TCGv_i64 next = tcg_const_i64(s->next_pc);
1266 if (is_imm) {
1267 cdest = tcg_const_i64(dest);
1268 }
1269
1270 if (c->is_64) {
1271 tcg_gen_movcond_i64(c->cond, psw_addr, c->u.s64.a, c->u.s64.b,
1272 cdest, next);
1273 } else {
1274 TCGv_i32 t0 = tcg_temp_new_i32();
1275 TCGv_i64 t1 = tcg_temp_new_i64();
1276 TCGv_i64 z = tcg_const_i64(0);
1277 tcg_gen_setcond_i32(c->cond, t0, c->u.s32.a, c->u.s32.b);
1278 tcg_gen_extu_i32_i64(t1, t0);
1279 tcg_temp_free_i32(t0);
1280 tcg_gen_movcond_i64(TCG_COND_NE, psw_addr, t1, z, cdest, next);
1281 tcg_temp_free_i64(t1);
1282 tcg_temp_free_i64(z);
1283 }
1284
1285 if (is_imm) {
1286 tcg_temp_free_i64(cdest);
1287 }
1288 tcg_temp_free_i64(next);
1289
1290 ret = EXIT_PC_UPDATED;
1291 }
1292
1293 egress:
1294 free_compare(c);
1295 return ret;
1296}
1297
ad044d09
RH
1298/* ====================================================================== */
1299/* The operations. These perform the bulk of the work for any insn,
1300 usually after the operands have been loaded and output initialized. */
1301
b9bca3e5
RH
1302static ExitStatus op_abs(DisasContext *s, DisasOps *o)
1303{
1304 gen_helper_abs_i64(o->out, o->in2);
1305 return NO_EXIT;
1306}
1307
5d7fd045
RH
1308static ExitStatus op_absf32(DisasContext *s, DisasOps *o)
1309{
1310 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffull);
1311 return NO_EXIT;
1312}
1313
1314static ExitStatus op_absf64(DisasContext *s, DisasOps *o)
1315{
1316 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull);
1317 return NO_EXIT;
1318}
1319
1320static ExitStatus op_absf128(DisasContext *s, DisasOps *o)
1321{
1322 tcg_gen_andi_i64(o->out, o->in1, 0x7fffffffffffffffull);
1323 tcg_gen_mov_i64(o->out2, o->in2);
1324 return NO_EXIT;
1325}
1326
ad044d09
RH
1327static ExitStatus op_add(DisasContext *s, DisasOps *o)
1328{
1329 tcg_gen_add_i64(o->out, o->in1, o->in2);
1330 return NO_EXIT;
1331}
1332
4e4bb438
RH
1333static ExitStatus op_addc(DisasContext *s, DisasOps *o)
1334{
c95ec459
RH
1335 DisasCompare cmp;
1336 TCGv_i64 carry;
4e4bb438
RH
1337
1338 tcg_gen_add_i64(o->out, o->in1, o->in2);
1339
c95ec459
RH
1340 /* The carry flag is the msb of CC, therefore the branch mask that would
1341 create that comparison is 3. Feeding the generated comparison to
1342 setcond produces the carry flag that we desire. */
1343 disas_jcc(s, &cmp, 3);
1344 carry = tcg_temp_new_i64();
1345 if (cmp.is_64) {
1346 tcg_gen_setcond_i64(cmp.cond, carry, cmp.u.s64.a, cmp.u.s64.b);
1347 } else {
1348 TCGv_i32 t = tcg_temp_new_i32();
1349 tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
1350 tcg_gen_extu_i32_i64(carry, t);
1351 tcg_temp_free_i32(t);
1352 }
1353 free_compare(&cmp);
4e4bb438 1354
c95ec459
RH
1355 tcg_gen_add_i64(o->out, o->out, carry);
1356 tcg_temp_free_i64(carry);
4e4bb438
RH
1357 return NO_EXIT;
1358}
1359
587626f8
RH
1360static ExitStatus op_aeb(DisasContext *s, DisasOps *o)
1361{
1362 gen_helper_aeb(o->out, cpu_env, o->in1, o->in2);
1363 return NO_EXIT;
1364}
1365
1366static ExitStatus op_adb(DisasContext *s, DisasOps *o)
1367{
1368 gen_helper_adb(o->out, cpu_env, o->in1, o->in2);
1369 return NO_EXIT;
1370}
1371
1372static ExitStatus op_axb(DisasContext *s, DisasOps *o)
1373{
1374 gen_helper_axb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
1375 return_low128(o->out2);
1376 return NO_EXIT;
1377}
1378
3bbfbd1f
RH
1379static ExitStatus op_and(DisasContext *s, DisasOps *o)
1380{
1381 tcg_gen_and_i64(o->out, o->in1, o->in2);
1382 return NO_EXIT;
1383}
1384
facfc864
RH
1385static ExitStatus op_andi(DisasContext *s, DisasOps *o)
1386{
1387 int shift = s->insn->data & 0xff;
1388 int size = s->insn->data >> 8;
1389 uint64_t mask = ((1ull << size) - 1) << shift;
1390
1391 assert(!o->g_in2);
1392 tcg_gen_shli_i64(o->in2, o->in2, shift);
1393 tcg_gen_ori_i64(o->in2, o->in2, ~mask);
1394 tcg_gen_and_i64(o->out, o->in1, o->in2);
1395
1396 /* Produce the CC from only the bits manipulated. */
1397 tcg_gen_andi_i64(cc_dst, o->out, mask);
1398 set_cc_nz_u64(s, cc_dst);
1399 return NO_EXIT;
1400}
1401
8ac33cdb
RH
1402static ExitStatus op_bas(DisasContext *s, DisasOps *o)
1403{
1404 tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
1405 if (!TCGV_IS_UNUSED_I64(o->in2)) {
1406 tcg_gen_mov_i64(psw_addr, o->in2);
1407 return EXIT_PC_UPDATED;
1408 } else {
1409 return NO_EXIT;
1410 }
1411}
1412
1413static ExitStatus op_basi(DisasContext *s, DisasOps *o)
1414{
1415 tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
1416 return help_goto_direct(s, s->pc + 2 * get_field(s->fields, i2));
1417}
1418
7233f2ed
RH
1419static ExitStatus op_bc(DisasContext *s, DisasOps *o)
1420{
1421 int m1 = get_field(s->fields, m1);
1422 bool is_imm = have_field(s->fields, i2);
1423 int imm = is_imm ? get_field(s->fields, i2) : 0;
1424 DisasCompare c;
1425
1426 disas_jcc(s, &c, m1);
1427 return help_branch(s, &c, is_imm, imm, o->in2);
1428}
1429
c61aad69
RH
1430static ExitStatus op_bct32(DisasContext *s, DisasOps *o)
1431{
1432 int r1 = get_field(s->fields, r1);
1433 bool is_imm = have_field(s->fields, i2);
1434 int imm = is_imm ? get_field(s->fields, i2) : 0;
1435 DisasCompare c;
1436 TCGv_i64 t;
1437
1438 c.cond = TCG_COND_NE;
1439 c.is_64 = false;
1440 c.g1 = false;
1441 c.g2 = false;
1442
1443 t = tcg_temp_new_i64();
1444 tcg_gen_subi_i64(t, regs[r1], 1);
1445 store_reg32_i64(r1, t);
1446 c.u.s32.a = tcg_temp_new_i32();
1447 c.u.s32.b = tcg_const_i32(0);
1448 tcg_gen_trunc_i64_i32(c.u.s32.a, t);
1449 tcg_temp_free_i64(t);
1450
1451 return help_branch(s, &c, is_imm, imm, o->in2);
1452}
1453
1454static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
1455{
1456 int r1 = get_field(s->fields, r1);
1457 bool is_imm = have_field(s->fields, i2);
1458 int imm = is_imm ? get_field(s->fields, i2) : 0;
1459 DisasCompare c;
1460
1461 c.cond = TCG_COND_NE;
1462 c.is_64 = true;
1463 c.g1 = true;
1464 c.g2 = false;
1465
1466 tcg_gen_subi_i64(regs[r1], regs[r1], 1);
1467 c.u.s64.a = regs[r1];
1468 c.u.s64.b = tcg_const_i64(0);
1469
2cf5e350
RH
1470 return help_branch(s, &c, is_imm, imm, o->in2);
1471}
1472
1473static ExitStatus op_bx32(DisasContext *s, DisasOps *o)
1474{
1475 int r1 = get_field(s->fields, r1);
1476 int r3 = get_field(s->fields, r3);
1477 bool is_imm = have_field(s->fields, i2);
1478 int imm = is_imm ? get_field(s->fields, i2) : 0;
1479 DisasCompare c;
1480 TCGv_i64 t;
1481
1482 c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
1483 c.is_64 = false;
1484 c.g1 = false;
1485 c.g2 = false;
1486
1487 t = tcg_temp_new_i64();
1488 tcg_gen_add_i64(t, regs[r1], regs[r3]);
1489 c.u.s32.a = tcg_temp_new_i32();
1490 c.u.s32.b = tcg_temp_new_i32();
1491 tcg_gen_trunc_i64_i32(c.u.s32.a, t);
1492 tcg_gen_trunc_i64_i32(c.u.s32.b, regs[r3 | 1]);
1493 store_reg32_i64(r1, t);
1494 tcg_temp_free_i64(t);
1495
1496 return help_branch(s, &c, is_imm, imm, o->in2);
1497}
1498
1499static ExitStatus op_bx64(DisasContext *s, DisasOps *o)
1500{
1501 int r1 = get_field(s->fields, r1);
1502 int r3 = get_field(s->fields, r3);
1503 bool is_imm = have_field(s->fields, i2);
1504 int imm = is_imm ? get_field(s->fields, i2) : 0;
1505 DisasCompare c;
1506
1507 c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
1508 c.is_64 = true;
1509
1510 if (r1 == (r3 | 1)) {
1511 c.u.s64.b = load_reg(r3 | 1);
1512 c.g2 = false;
1513 } else {
1514 c.u.s64.b = regs[r3 | 1];
1515 c.g2 = true;
1516 }
1517
1518 tcg_gen_add_i64(regs[r1], regs[r1], regs[r3]);
1519 c.u.s64.a = regs[r1];
1520 c.g1 = true;
1521
c61aad69
RH
1522 return help_branch(s, &c, is_imm, imm, o->in2);
1523}
1524
5550359f
RH
1525static ExitStatus op_cj(DisasContext *s, DisasOps *o)
1526{
1527 int imm, m3 = get_field(s->fields, m3);
1528 bool is_imm;
1529 DisasCompare c;
1530
de379661 1531 c.cond = ltgt_cond[m3];
5550359f
RH
1532 if (s->insn->data) {
1533 c.cond = tcg_unsigned_cond(c.cond);
1534 }
1535 c.is_64 = c.g1 = c.g2 = true;
1536 c.u.s64.a = o->in1;
1537 c.u.s64.b = o->in2;
1538
1539 is_imm = have_field(s->fields, i4);
1540 if (is_imm) {
1541 imm = get_field(s->fields, i4);
1542 } else {
1543 imm = 0;
1544 o->out = get_address(s, 0, get_field(s->fields, b4),
1545 get_field(s->fields, d4));
1546 }
1547
1548 return help_branch(s, &c, is_imm, imm, o->out);
1549}
1550
587626f8
RH
1551static ExitStatus op_ceb(DisasContext *s, DisasOps *o)
1552{
1553 gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2);
1554 set_cc_static(s);
1555 return NO_EXIT;
1556}
1557
1558static ExitStatus op_cdb(DisasContext *s, DisasOps *o)
1559{
1560 gen_helper_cdb(cc_op, cpu_env, o->in1, o->in2);
1561 set_cc_static(s);
1562 return NO_EXIT;
1563}
1564
1565static ExitStatus op_cxb(DisasContext *s, DisasOps *o)
1566{
1567 gen_helper_cxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2);
1568 set_cc_static(s);
1569 return NO_EXIT;
1570}
1571
68c8bd93
RH
1572static ExitStatus op_cfeb(DisasContext *s, DisasOps *o)
1573{
1574 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1575 gen_helper_cfeb(o->out, cpu_env, o->in2, m3);
1576 tcg_temp_free_i32(m3);
1577 gen_set_cc_nz_f32(s, o->in2);
1578 return NO_EXIT;
1579}
1580
1581static ExitStatus op_cfdb(DisasContext *s, DisasOps *o)
1582{
1583 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1584 gen_helper_cfdb(o->out, cpu_env, o->in2, m3);
1585 tcg_temp_free_i32(m3);
1586 gen_set_cc_nz_f64(s, o->in2);
1587 return NO_EXIT;
1588}
1589
1590static ExitStatus op_cfxb(DisasContext *s, DisasOps *o)
1591{
1592 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1593 gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3);
1594 tcg_temp_free_i32(m3);
1595 gen_set_cc_nz_f128(s, o->in1, o->in2);
1596 return NO_EXIT;
1597}
1598
1599static ExitStatus op_cgeb(DisasContext *s, DisasOps *o)
1600{
1601 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1602 gen_helper_cgeb(o->out, cpu_env, o->in2, m3);
1603 tcg_temp_free_i32(m3);
1604 gen_set_cc_nz_f32(s, o->in2);
1605 return NO_EXIT;
1606}
1607
1608static ExitStatus op_cgdb(DisasContext *s, DisasOps *o)
1609{
1610 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1611 gen_helper_cgdb(o->out, cpu_env, o->in2, m3);
1612 tcg_temp_free_i32(m3);
1613 gen_set_cc_nz_f64(s, o->in2);
1614 return NO_EXIT;
1615}
1616
1617static ExitStatus op_cgxb(DisasContext *s, DisasOps *o)
1618{
1619 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1620 gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3);
1621 tcg_temp_free_i32(m3);
1622 gen_set_cc_nz_f128(s, o->in1, o->in2);
1623 return NO_EXIT;
1624}
1625
6ac1b45f
RH
1626static ExitStatus op_clfeb(DisasContext *s, DisasOps *o)
1627{
1628 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1629 gen_helper_clfeb(o->out, cpu_env, o->in2, m3);
1630 tcg_temp_free_i32(m3);
1631 gen_set_cc_nz_f32(s, o->in2);
1632 return NO_EXIT;
1633}
1634
1635static ExitStatus op_clfdb(DisasContext *s, DisasOps *o)
1636{
1637 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1638 gen_helper_clfdb(o->out, cpu_env, o->in2, m3);
1639 tcg_temp_free_i32(m3);
1640 gen_set_cc_nz_f64(s, o->in2);
1641 return NO_EXIT;
1642}
1643
1644static ExitStatus op_clfxb(DisasContext *s, DisasOps *o)
1645{
1646 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1647 gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m3);
1648 tcg_temp_free_i32(m3);
1649 gen_set_cc_nz_f128(s, o->in1, o->in2);
1650 return NO_EXIT;
1651}
1652
1653static ExitStatus op_clgeb(DisasContext *s, DisasOps *o)
1654{
1655 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1656 gen_helper_clgeb(o->out, cpu_env, o->in2, m3);
1657 tcg_temp_free_i32(m3);
1658 gen_set_cc_nz_f32(s, o->in2);
1659 return NO_EXIT;
1660}
1661
1662static ExitStatus op_clgdb(DisasContext *s, DisasOps *o)
1663{
1664 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1665 gen_helper_clgdb(o->out, cpu_env, o->in2, m3);
1666 tcg_temp_free_i32(m3);
1667 gen_set_cc_nz_f64(s, o->in2);
1668 return NO_EXIT;
1669}
1670
1671static ExitStatus op_clgxb(DisasContext *s, DisasOps *o)
1672{
1673 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1674 gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m3);
1675 tcg_temp_free_i32(m3);
1676 gen_set_cc_nz_f128(s, o->in1, o->in2);
1677 return NO_EXIT;
1678}
1679
683bb9a8
RH
1680static ExitStatus op_cegb(DisasContext *s, DisasOps *o)
1681{
1682 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1683 gen_helper_cegb(o->out, cpu_env, o->in2, m3);
1684 tcg_temp_free_i32(m3);
1685 return NO_EXIT;
1686}
1687
1688static ExitStatus op_cdgb(DisasContext *s, DisasOps *o)
1689{
1690 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1691 gen_helper_cdgb(o->out, cpu_env, o->in2, m3);
1692 tcg_temp_free_i32(m3);
1693 return NO_EXIT;
1694}
1695
1696static ExitStatus op_cxgb(DisasContext *s, DisasOps *o)
1697{
1698 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1699 gen_helper_cxgb(o->out, cpu_env, o->in2, m3);
1700 tcg_temp_free_i32(m3);
2112bf1b
RH
1701 return_low128(o->out2);
1702 return NO_EXIT;
1703}
1704
1705static ExitStatus op_celgb(DisasContext *s, DisasOps *o)
1706{
1707 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1708 gen_helper_celgb(o->out, cpu_env, o->in2, m3);
1709 tcg_temp_free_i32(m3);
1710 return NO_EXIT;
1711}
1712
1713static ExitStatus op_cdlgb(DisasContext *s, DisasOps *o)
1714{
1715 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1716 gen_helper_cdlgb(o->out, cpu_env, o->in2, m3);
1717 tcg_temp_free_i32(m3);
1718 return NO_EXIT;
1719}
1720
1721static ExitStatus op_cxlgb(DisasContext *s, DisasOps *o)
1722{
1723 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1724 gen_helper_cxlgb(o->out, cpu_env, o->in2, m3);
1725 tcg_temp_free_i32(m3);
683bb9a8
RH
1726 return_low128(o->out2);
1727 return NO_EXIT;
1728}
1729
374724f9
RH
1730static ExitStatus op_cksm(DisasContext *s, DisasOps *o)
1731{
1732 int r2 = get_field(s->fields, r2);
1733 TCGv_i64 len = tcg_temp_new_i64();
1734
1735 potential_page_fault(s);
1736 gen_helper_cksm(len, cpu_env, o->in1, o->in2, regs[r2 + 1]);
1737 set_cc_static(s);
1738 return_low128(o->out);
1739
1740 tcg_gen_add_i64(regs[r2], regs[r2], len);
1741 tcg_gen_sub_i64(regs[r2 + 1], regs[r2 + 1], len);
1742 tcg_temp_free_i64(len);
1743
1744 return NO_EXIT;
1745}
1746
4f7403d5
RH
1747static ExitStatus op_clc(DisasContext *s, DisasOps *o)
1748{
1749 int l = get_field(s->fields, l1);
1750 TCGv_i32 vl;
1751
1752 switch (l + 1) {
1753 case 1:
1754 tcg_gen_qemu_ld8u(cc_src, o->addr1, get_mem_index(s));
1755 tcg_gen_qemu_ld8u(cc_dst, o->in2, get_mem_index(s));
1756 break;
1757 case 2:
1758 tcg_gen_qemu_ld16u(cc_src, o->addr1, get_mem_index(s));
1759 tcg_gen_qemu_ld16u(cc_dst, o->in2, get_mem_index(s));
1760 break;
1761 case 4:
1762 tcg_gen_qemu_ld32u(cc_src, o->addr1, get_mem_index(s));
1763 tcg_gen_qemu_ld32u(cc_dst, o->in2, get_mem_index(s));
1764 break;
1765 case 8:
1766 tcg_gen_qemu_ld64(cc_src, o->addr1, get_mem_index(s));
1767 tcg_gen_qemu_ld64(cc_dst, o->in2, get_mem_index(s));
1768 break;
1769 default:
1770 potential_page_fault(s);
1771 vl = tcg_const_i32(l);
1772 gen_helper_clc(cc_op, cpu_env, vl, o->addr1, o->in2);
1773 tcg_temp_free_i32(vl);
1774 set_cc_static(s);
1775 return NO_EXIT;
1776 }
1777 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, cc_src, cc_dst);
1778 return NO_EXIT;
1779}
1780
eb66e6a9
RH
1781static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
1782{
1783 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
1784 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
1785 potential_page_fault(s);
1786 gen_helper_clcle(cc_op, cpu_env, r1, o->in2, r3);
1787 tcg_temp_free_i32(r1);
1788 tcg_temp_free_i32(r3);
1789 set_cc_static(s);
1790 return NO_EXIT;
1791}
1792
32a44d58
RH
1793static ExitStatus op_clm(DisasContext *s, DisasOps *o)
1794{
1795 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1796 TCGv_i32 t1 = tcg_temp_new_i32();
1797 tcg_gen_trunc_i64_i32(t1, o->in1);
1798 potential_page_fault(s);
1799 gen_helper_clm(cc_op, cpu_env, t1, m3, o->in2);
1800 set_cc_static(s);
1801 tcg_temp_free_i32(t1);
1802 tcg_temp_free_i32(m3);
1803 return NO_EXIT;
1804}
1805
aa31bf60
RH
1806static ExitStatus op_clst(DisasContext *s, DisasOps *o)
1807{
1808 potential_page_fault(s);
1809 gen_helper_clst(o->in1, cpu_env, regs[0], o->in1, o->in2);
1810 set_cc_static(s);
1811 return_low128(o->in2);
1812 return NO_EXIT;
1813}
1814
2db014b5
RH
1815static ExitStatus op_cps(DisasContext *s, DisasOps *o)
1816{
1817 TCGv_i64 t = tcg_temp_new_i64();
1818 tcg_gen_andi_i64(t, o->in1, 0x8000000000000000ull);
1819 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull);
1820 tcg_gen_or_i64(o->out, o->out, t);
1821 tcg_temp_free_i64(t);
1822 return NO_EXIT;
1823}
1824
f3de39c4
RH
1825static ExitStatus op_cs(DisasContext *s, DisasOps *o)
1826{
b7886de3
RH
1827 /* FIXME: needs an atomic solution for CONFIG_USER_ONLY. */
1828 int d2 = get_field(s->fields, d2);
1829 int b2 = get_field(s->fields, b2);
1830 int is_64 = s->insn->data;
1831 TCGv_i64 addr, mem, cc, z;
1832
1833 /* Note that in1 = R3 (new value) and
1834 in2 = (zero-extended) R1 (expected value). */
1835
1836 /* Load the memory into the (temporary) output. While the PoO only talks
1837 about moving the memory to R1 on inequality, if we include equality it
1838 means that R1 is equal to the memory in all conditions. */
1839 addr = get_address(s, 0, b2, d2);
1840 if (is_64) {
1841 tcg_gen_qemu_ld64(o->out, addr, get_mem_index(s));
1842 } else {
1843 tcg_gen_qemu_ld32u(o->out, addr, get_mem_index(s));
1844 }
1845
1846 /* Are the memory and expected values (un)equal? Note that this setcond
1847 produces the output CC value, thus the NE sense of the test. */
1848 cc = tcg_temp_new_i64();
1849 tcg_gen_setcond_i64(TCG_COND_NE, cc, o->in2, o->out);
1850
1851 /* If the memory and expected values are equal (CC==0), copy R3 to MEM.
1852 Recall that we are allowed to unconditionally issue the store (and
1853 thus any possible write trap), so (re-)store the original contents
1854 of MEM in case of inequality. */
1855 z = tcg_const_i64(0);
1856 mem = tcg_temp_new_i64();
1857 tcg_gen_movcond_i64(TCG_COND_EQ, mem, cc, z, o->in1, o->out);
1858 if (is_64) {
1859 tcg_gen_qemu_st64(mem, addr, get_mem_index(s));
1860 } else {
1861 tcg_gen_qemu_st32(mem, addr, get_mem_index(s));
1862 }
1863 tcg_temp_free_i64(z);
1864 tcg_temp_free_i64(mem);
1865 tcg_temp_free_i64(addr);
1866
1867 /* Store CC back to cc_op. Wait until after the store so that any
1868 exception gets the old cc_op value. */
1869 tcg_gen_trunc_i64_i32(cc_op, cc);
1870 tcg_temp_free_i64(cc);
f3de39c4
RH
1871 set_cc_static(s);
1872 return NO_EXIT;
1873}
1874
b7886de3 1875static ExitStatus op_cdsg(DisasContext *s, DisasOps *o)
f3de39c4 1876{
b7886de3
RH
1877 /* FIXME: needs an atomic solution for CONFIG_USER_ONLY. */
1878 int r1 = get_field(s->fields, r1);
f3de39c4 1879 int r3 = get_field(s->fields, r3);
b7886de3
RH
1880 int d2 = get_field(s->fields, d2);
1881 int b2 = get_field(s->fields, b2);
1882 TCGv_i64 addrh, addrl, memh, meml, outh, outl, cc, z;
1883
1884 /* Note that R1:R1+1 = expected value and R3:R3+1 = new value. */
1885
1886 addrh = get_address(s, 0, b2, d2);
1887 addrl = get_address(s, 0, b2, d2 + 8);
1888 outh = tcg_temp_new_i64();
1889 outl = tcg_temp_new_i64();
1890
1891 tcg_gen_qemu_ld64(outh, addrh, get_mem_index(s));
1892 tcg_gen_qemu_ld64(outl, addrl, get_mem_index(s));
1893
1894 /* Fold the double-word compare with arithmetic. */
1895 cc = tcg_temp_new_i64();
1896 z = tcg_temp_new_i64();
1897 tcg_gen_xor_i64(cc, outh, regs[r1]);
1898 tcg_gen_xor_i64(z, outl, regs[r1 + 1]);
1899 tcg_gen_or_i64(cc, cc, z);
1900 tcg_gen_movi_i64(z, 0);
1901 tcg_gen_setcond_i64(TCG_COND_NE, cc, cc, z);
1902
1903 memh = tcg_temp_new_i64();
1904 meml = tcg_temp_new_i64();
1905 tcg_gen_movcond_i64(TCG_COND_EQ, memh, cc, z, regs[r3], outh);
1906 tcg_gen_movcond_i64(TCG_COND_EQ, meml, cc, z, regs[r3 + 1], outl);
1907 tcg_temp_free_i64(z);
1908
1909 tcg_gen_qemu_st64(memh, addrh, get_mem_index(s));
1910 tcg_gen_qemu_st64(meml, addrl, get_mem_index(s));
1911 tcg_temp_free_i64(memh);
1912 tcg_temp_free_i64(meml);
1913 tcg_temp_free_i64(addrh);
1914 tcg_temp_free_i64(addrl);
1915
1916 /* Save back state now that we've passed all exceptions. */
1917 tcg_gen_mov_i64(regs[r1], outh);
1918 tcg_gen_mov_i64(regs[r1 + 1], outl);
1919 tcg_gen_trunc_i64_i32(cc_op, cc);
1920 tcg_temp_free_i64(outh);
1921 tcg_temp_free_i64(outl);
1922 tcg_temp_free_i64(cc);
f3de39c4
RH
1923 set_cc_static(s);
1924 return NO_EXIT;
1925}
1926
3d596f49
RH
1927#ifndef CONFIG_USER_ONLY
1928static ExitStatus op_csp(DisasContext *s, DisasOps *o)
1929{
1930 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
1931 check_privileged(s);
1932 gen_helper_csp(cc_op, cpu_env, r1, o->in2);
1933 tcg_temp_free_i32(r1);
1934 set_cc_static(s);
1935 return NO_EXIT;
1936}
1937#endif
1938
c49daa51
RH
1939static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
1940{
1941 TCGv_i64 t1 = tcg_temp_new_i64();
1942 TCGv_i32 t2 = tcg_temp_new_i32();
1943 tcg_gen_trunc_i64_i32(t2, o->in1);
1944 gen_helper_cvd(t1, t2);
1945 tcg_temp_free_i32(t2);
1946 tcg_gen_qemu_st64(t1, o->in2, get_mem_index(s));
1947 tcg_temp_free_i64(t1);
1948 return NO_EXIT;
1949}
1950
1c268751
RH
1951static ExitStatus op_ct(DisasContext *s, DisasOps *o)
1952{
1953 int m3 = get_field(s->fields, m3);
1954 int lab = gen_new_label();
1955 TCGv_i32 t;
1956 TCGCond c;
1957
de379661 1958 c = tcg_invert_cond(ltgt_cond[m3]);
1c268751
RH
1959 if (s->insn->data) {
1960 c = tcg_unsigned_cond(c);
1961 }
1962 tcg_gen_brcond_i64(c, o->in1, o->in2, lab);
1963
1964 /* Set DXC to 0xff. */
1965 t = tcg_temp_new_i32();
1966 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
1967 tcg_gen_ori_i32(t, t, 0xff00);
1968 tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
1969 tcg_temp_free_i32(t);
1970
1971 /* Trap. */
1972 gen_program_exception(s, PGM_DATA);
1973
1974 gen_set_label(lab);
1975 return NO_EXIT;
1976}
1977
972e35b9
RH
1978#ifndef CONFIG_USER_ONLY
1979static ExitStatus op_diag(DisasContext *s, DisasOps *o)
1980{
1981 TCGv_i32 tmp;
1982
1983 check_privileged(s);
1984 potential_page_fault(s);
1985
1986 /* We pretend the format is RX_a so that D2 is the field we want. */
1987 tmp = tcg_const_i32(get_field(s->fields, d2) & 0xfff);
1988 gen_helper_diag(regs[2], cpu_env, tmp, regs[2], regs[1]);
1989 tcg_temp_free_i32(tmp);
1990 return NO_EXIT;
1991}
1992#endif
1993
891452e5
RH
1994static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
1995{
1996 gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
1997 return_low128(o->out);
1998 return NO_EXIT;
1999}
2000
2001static ExitStatus op_divu32(DisasContext *s, DisasOps *o)
2002{
2003 gen_helper_divu32(o->out2, cpu_env, o->in1, o->in2);
2004 return_low128(o->out);
2005 return NO_EXIT;
2006}
2007
2008static ExitStatus op_divs64(DisasContext *s, DisasOps *o)
2009{
2010 gen_helper_divs64(o->out2, cpu_env, o->in1, o->in2);
2011 return_low128(o->out);
2012 return NO_EXIT;
2013}
2014
2015static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
2016{
2017 gen_helper_divu64(o->out2, cpu_env, o->out, o->out2, o->in2);
2018 return_low128(o->out);
2019 return NO_EXIT;
2020}
2021
f08a5c31
RH
2022static ExitStatus op_deb(DisasContext *s, DisasOps *o)
2023{
2024 gen_helper_deb(o->out, cpu_env, o->in1, o->in2);
2025 return NO_EXIT;
2026}
2027
2028static ExitStatus op_ddb(DisasContext *s, DisasOps *o)
2029{
2030 gen_helper_ddb(o->out, cpu_env, o->in1, o->in2);
2031 return NO_EXIT;
2032}
2033
2034static ExitStatus op_dxb(DisasContext *s, DisasOps *o)
2035{
2036 gen_helper_dxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
2037 return_low128(o->out2);
2038 return NO_EXIT;
2039}
2040
d62a4c97
RH
2041static ExitStatus op_ear(DisasContext *s, DisasOps *o)
2042{
2043 int r2 = get_field(s->fields, r2);
2044 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, aregs[r2]));
2045 return NO_EXIT;
2046}
2047
ea20490f
RH
2048static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
2049{
2050 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
2051 return NO_EXIT;
2052}
2053
e30a9d3f
RH
2054static ExitStatus op_epsw(DisasContext *s, DisasOps *o)
2055{
2056 int r1 = get_field(s->fields, r1);
2057 int r2 = get_field(s->fields, r2);
2058 TCGv_i64 t = tcg_temp_new_i64();
2059
2060 /* Note the "subsequently" in the PoO, which implies a defined result
2061 if r1 == r2. Thus we cannot defer these writes to an output hook. */
2062 tcg_gen_shri_i64(t, psw_mask, 32);
2063 store_reg32_i64(r1, t);
2064 if (r2 != 0) {
2065 store_reg32_i64(r2, psw_mask);
2066 }
2067
2068 tcg_temp_free_i64(t);
2069 return NO_EXIT;
2070}
2071
6e764e97
RH
2072static ExitStatus op_ex(DisasContext *s, DisasOps *o)
2073{
2074 /* ??? Perhaps a better way to implement EXECUTE is to set a bit in
2075 tb->flags, (ab)use the tb->cs_base field as the address of
2076 the template in memory, and grab 8 bits of tb->flags/cflags for
2077 the contents of the register. We would then recognize all this
2078 in gen_intermediate_code_internal, generating code for exactly
2079 one instruction. This new TB then gets executed normally.
2080
2081 On the other hand, this seems to be mostly used for modifying
2082 MVC inside of memcpy, which needs a helper call anyway. So
2083 perhaps this doesn't bear thinking about any further. */
2084
2085 TCGv_i64 tmp;
2086
2087 update_psw_addr(s);
7a6c7067 2088 update_cc_op(s);
6e764e97
RH
2089
2090 tmp = tcg_const_i64(s->next_pc);
2091 gen_helper_ex(cc_op, cpu_env, cc_op, o->in1, o->in2, tmp);
2092 tcg_temp_free_i64(tmp);
2093
2094 set_cc_static(s);
2095 return NO_EXIT;
2096}
2097
102bf2c6
RH
2098static ExitStatus op_flogr(DisasContext *s, DisasOps *o)
2099{
2100 /* We'll use the original input for cc computation, since we get to
2101 compare that against 0, which ought to be better than comparing
2102 the real output against 64. It also lets cc_dst be a convenient
2103 temporary during our computation. */
2104 gen_op_update1_cc_i64(s, CC_OP_FLOGR, o->in2);
2105
2106 /* R1 = IN ? CLZ(IN) : 64. */
2107 gen_helper_clz(o->out, o->in2);
2108
2109 /* R1+1 = IN & ~(found bit). Note that we may attempt to shift this
2110 value by 64, which is undefined. But since the shift is 64 iff the
2111 input is zero, we still get the correct result after and'ing. */
2112 tcg_gen_movi_i64(o->out2, 0x8000000000000000ull);
2113 tcg_gen_shr_i64(o->out2, o->out2, o->out);
2114 tcg_gen_andc_i64(o->out2, cc_dst, o->out2);
2115 return NO_EXIT;
2116}
2117
58a9e35b
RH
2118static ExitStatus op_icm(DisasContext *s, DisasOps *o)
2119{
2120 int m3 = get_field(s->fields, m3);
2121 int pos, len, base = s->insn->data;
2122 TCGv_i64 tmp = tcg_temp_new_i64();
2123 uint64_t ccm;
2124
2125 switch (m3) {
2126 case 0xf:
2127 /* Effectively a 32-bit load. */
2128 tcg_gen_qemu_ld32u(tmp, o->in2, get_mem_index(s));
2129 len = 32;
2130 goto one_insert;
2131
2132 case 0xc:
2133 case 0x6:
2134 case 0x3:
2135 /* Effectively a 16-bit load. */
2136 tcg_gen_qemu_ld16u(tmp, o->in2, get_mem_index(s));
2137 len = 16;
2138 goto one_insert;
2139
2140 case 0x8:
2141 case 0x4:
2142 case 0x2:
2143 case 0x1:
2144 /* Effectively an 8-bit load. */
2145 tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
2146 len = 8;
2147 goto one_insert;
2148
2149 one_insert:
2150 pos = base + ctz32(m3) * 8;
2151 tcg_gen_deposit_i64(o->out, o->out, tmp, pos, len);
2152 ccm = ((1ull << len) - 1) << pos;
2153 break;
2154
2155 default:
2156 /* This is going to be a sequence of loads and inserts. */
2157 pos = base + 32 - 8;
2158 ccm = 0;
2159 while (m3) {
2160 if (m3 & 0x8) {
2161 tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
2162 tcg_gen_addi_i64(o->in2, o->in2, 1);
2163 tcg_gen_deposit_i64(o->out, o->out, tmp, pos, 8);
2164 ccm |= 0xff << pos;
2165 }
2166 m3 = (m3 << 1) & 0xf;
2167 pos -= 8;
2168 }
2169 break;
2170 }
2171
2172 tcg_gen_movi_i64(tmp, ccm);
2173 gen_op_update2_cc_i64(s, CC_OP_ICM, tmp, o->out);
2174 tcg_temp_free_i64(tmp);
2175 return NO_EXIT;
2176}
2177
facfc864
RH
2178static ExitStatus op_insi(DisasContext *s, DisasOps *o)
2179{
2180 int shift = s->insn->data & 0xff;
2181 int size = s->insn->data >> 8;
2182 tcg_gen_deposit_i64(o->out, o->in1, o->in2, shift, size);
2183 return NO_EXIT;
2184}
2185
6e2704e7
RH
2186static ExitStatus op_ipm(DisasContext *s, DisasOps *o)
2187{
2188 TCGv_i64 t1;
2189
2190 gen_op_calc_cc(s);
2191 tcg_gen_andi_i64(o->out, o->out, ~0xff000000ull);
2192
2193 t1 = tcg_temp_new_i64();
2194 tcg_gen_shli_i64(t1, psw_mask, 20);
2195 tcg_gen_shri_i64(t1, t1, 36);
2196 tcg_gen_or_i64(o->out, o->out, t1);
2197
2198 tcg_gen_extu_i32_i64(t1, cc_op);
2199 tcg_gen_shli_i64(t1, t1, 28);
2200 tcg_gen_or_i64(o->out, o->out, t1);
2201 tcg_temp_free_i64(t1);
2202 return NO_EXIT;
2203}
2204
cfef53e3
RH
2205#ifndef CONFIG_USER_ONLY
2206static ExitStatus op_ipte(DisasContext *s, DisasOps *o)
2207{
2208 check_privileged(s);
2209 gen_helper_ipte(cpu_env, o->in1, o->in2);
2210 return NO_EXIT;
2211}
8026417c
RH
2212
2213static ExitStatus op_iske(DisasContext *s, DisasOps *o)
2214{
2215 check_privileged(s);
2216 gen_helper_iske(o->out, cpu_env, o->in2);
2217 return NO_EXIT;
2218}
cfef53e3
RH
2219#endif
2220
587626f8
RH
2221static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
2222{
2223 gen_helper_ldeb(o->out, cpu_env, o->in2);
2224 return NO_EXIT;
2225}
2226
2227static ExitStatus op_ledb(DisasContext *s, DisasOps *o)
2228{
2229 gen_helper_ledb(o->out, cpu_env, o->in2);
2230 return NO_EXIT;
2231}
2232
2233static ExitStatus op_ldxb(DisasContext *s, DisasOps *o)
2234{
2235 gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
2236 return NO_EXIT;
2237}
2238
2239static ExitStatus op_lexb(DisasContext *s, DisasOps *o)
2240{
2241 gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
2242 return NO_EXIT;
2243}
2244
2245static ExitStatus op_lxdb(DisasContext *s, DisasOps *o)
2246{
2247 gen_helper_lxdb(o->out, cpu_env, o->in2);
2248 return_low128(o->out2);
2249 return NO_EXIT;
2250}
2251
2252static ExitStatus op_lxeb(DisasContext *s, DisasOps *o)
2253{
2254 gen_helper_lxeb(o->out, cpu_env, o->in2);
2255 return_low128(o->out2);
2256 return NO_EXIT;
2257}
2258
7691c23b
RH
2259static ExitStatus op_llgt(DisasContext *s, DisasOps *o)
2260{
2261 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
2262 return NO_EXIT;
2263}
2264
c698d876
RH
2265static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
2266{
2267 tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
2268 return NO_EXIT;
2269}
2270
2271static ExitStatus op_ld8u(DisasContext *s, DisasOps *o)
2272{
2273 tcg_gen_qemu_ld8u(o->out, o->in2, get_mem_index(s));
2274 return NO_EXIT;
2275}
2276
2277static ExitStatus op_ld16s(DisasContext *s, DisasOps *o)
2278{
2279 tcg_gen_qemu_ld16s(o->out, o->in2, get_mem_index(s));
2280 return NO_EXIT;
2281}
2282
2283static ExitStatus op_ld16u(DisasContext *s, DisasOps *o)
2284{
2285 tcg_gen_qemu_ld16u(o->out, o->in2, get_mem_index(s));
2286 return NO_EXIT;
2287}
2288
22c37a08
RH
2289static ExitStatus op_ld32s(DisasContext *s, DisasOps *o)
2290{
2291 tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s));
2292 return NO_EXIT;
2293}
2294
2295static ExitStatus op_ld32u(DisasContext *s, DisasOps *o)
2296{
2297 tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s));
2298 return NO_EXIT;
2299}
2300
2301static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
2302{
2303 tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s));
2304 return NO_EXIT;
2305}
2306
632086da
RH
2307static ExitStatus op_loc(DisasContext *s, DisasOps *o)
2308{
2309 DisasCompare c;
2310
2311 disas_jcc(s, &c, get_field(s->fields, m3));
2312
2313 if (c.is_64) {
2314 tcg_gen_movcond_i64(c.cond, o->out, c.u.s64.a, c.u.s64.b,
2315 o->in2, o->in1);
2316 free_compare(&c);
2317 } else {
2318 TCGv_i32 t32 = tcg_temp_new_i32();
2319 TCGv_i64 t, z;
2320
2321 tcg_gen_setcond_i32(c.cond, t32, c.u.s32.a, c.u.s32.b);
2322 free_compare(&c);
2323
2324 t = tcg_temp_new_i64();
2325 tcg_gen_extu_i32_i64(t, t32);
2326 tcg_temp_free_i32(t32);
2327
2328 z = tcg_const_i64(0);
2329 tcg_gen_movcond_i64(TCG_COND_NE, o->out, t, z, o->in2, o->in1);
2330 tcg_temp_free_i64(t);
2331 tcg_temp_free_i64(z);
2332 }
2333
2334 return NO_EXIT;
2335}
2336
8b5ff571 2337#ifndef CONFIG_USER_ONLY
504488b8
RH
2338static ExitStatus op_lctl(DisasContext *s, DisasOps *o)
2339{
2340 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2341 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2342 check_privileged(s);
2343 potential_page_fault(s);
2344 gen_helper_lctl(cpu_env, r1, o->in2, r3);
2345 tcg_temp_free_i32(r1);
2346 tcg_temp_free_i32(r3);
2347 return NO_EXIT;
2348}
2349
3e398cf9
RH
2350static ExitStatus op_lctlg(DisasContext *s, DisasOps *o)
2351{
2352 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2353 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2354 check_privileged(s);
2355 potential_page_fault(s);
2356 gen_helper_lctlg(cpu_env, r1, o->in2, r3);
2357 tcg_temp_free_i32(r1);
2358 tcg_temp_free_i32(r3);
2359 return NO_EXIT;
2360}
d8fe4a9c
RH
2361static ExitStatus op_lra(DisasContext *s, DisasOps *o)
2362{
2363 check_privileged(s);
2364 potential_page_fault(s);
2365 gen_helper_lra(o->out, cpu_env, o->in2);
2366 set_cc_static(s);
2367 return NO_EXIT;
2368}
2369
8b5ff571
RH
2370static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
2371{
2372 TCGv_i64 t1, t2;
2373
2374 check_privileged(s);
2375
2376 t1 = tcg_temp_new_i64();
2377 t2 = tcg_temp_new_i64();
2378 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2379 tcg_gen_addi_i64(o->in2, o->in2, 4);
2380 tcg_gen_qemu_ld32u(t2, o->in2, get_mem_index(s));
2381 /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */
2382 tcg_gen_shli_i64(t1, t1, 32);
2383 gen_helper_load_psw(cpu_env, t1, t2);
2384 tcg_temp_free_i64(t1);
2385 tcg_temp_free_i64(t2);
2386 return EXIT_NORETURN;
2387}
7ab938d7
RH
2388
2389static ExitStatus op_lpswe(DisasContext *s, DisasOps *o)
2390{
2391 TCGv_i64 t1, t2;
2392
2393 check_privileged(s);
2394
2395 t1 = tcg_temp_new_i64();
2396 t2 = tcg_temp_new_i64();
2397 tcg_gen_qemu_ld64(t1, o->in2, get_mem_index(s));
2398 tcg_gen_addi_i64(o->in2, o->in2, 8);
2399 tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s));
2400 gen_helper_load_psw(cpu_env, t1, t2);
2401 tcg_temp_free_i64(t1);
2402 tcg_temp_free_i64(t2);
2403 return EXIT_NORETURN;
2404}
8b5ff571
RH
2405#endif
2406
7df3e93a
RH
2407static ExitStatus op_lam(DisasContext *s, DisasOps *o)
2408{
2409 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2410 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2411 potential_page_fault(s);
2412 gen_helper_lam(cpu_env, r1, o->in2, r3);
2413 tcg_temp_free_i32(r1);
2414 tcg_temp_free_i32(r3);
2415 return NO_EXIT;
2416}
2417
77f8d6c3
RH
2418static ExitStatus op_lm32(DisasContext *s, DisasOps *o)
2419{
2420 int r1 = get_field(s->fields, r1);
2421 int r3 = get_field(s->fields, r3);
2422 TCGv_i64 t = tcg_temp_new_i64();
2423 TCGv_i64 t4 = tcg_const_i64(4);
2424
2425 while (1) {
2426 tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
2427 store_reg32_i64(r1, t);
2428 if (r1 == r3) {
2429 break;
2430 }
2431 tcg_gen_add_i64(o->in2, o->in2, t4);
2432 r1 = (r1 + 1) & 15;
2433 }
2434
2435 tcg_temp_free_i64(t);
2436 tcg_temp_free_i64(t4);
2437 return NO_EXIT;
2438}
2439
2440static ExitStatus op_lmh(DisasContext *s, DisasOps *o)
2441{
2442 int r1 = get_field(s->fields, r1);
2443 int r3 = get_field(s->fields, r3);
2444 TCGv_i64 t = tcg_temp_new_i64();
2445 TCGv_i64 t4 = tcg_const_i64(4);
2446
2447 while (1) {
2448 tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
2449 store_reg32h_i64(r1, t);
2450 if (r1 == r3) {
2451 break;
2452 }
2453 tcg_gen_add_i64(o->in2, o->in2, t4);
2454 r1 = (r1 + 1) & 15;
2455 }
2456
2457 tcg_temp_free_i64(t);
2458 tcg_temp_free_i64(t4);
2459 return NO_EXIT;
2460}
2461
2462static ExitStatus op_lm64(DisasContext *s, DisasOps *o)
2463{
2464 int r1 = get_field(s->fields, r1);
2465 int r3 = get_field(s->fields, r3);
2466 TCGv_i64 t8 = tcg_const_i64(8);
2467
2468 while (1) {
2469 tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
2470 if (r1 == r3) {
2471 break;
2472 }
2473 tcg_gen_add_i64(o->in2, o->in2, t8);
2474 r1 = (r1 + 1) & 15;
2475 }
2476
2477 tcg_temp_free_i64(t8);
2478 return NO_EXIT;
2479}
2480
9c3fd85b
RH
2481#ifndef CONFIG_USER_ONLY
2482static ExitStatus op_lura(DisasContext *s, DisasOps *o)
2483{
2484 check_privileged(s);
2485 potential_page_fault(s);
2486 gen_helper_lura(o->out, cpu_env, o->in2);
2487 return NO_EXIT;
2488}
2489
2490static ExitStatus op_lurag(DisasContext *s, DisasOps *o)
2491{
2492 check_privileged(s);
2493 potential_page_fault(s);
2494 gen_helper_lurag(o->out, cpu_env, o->in2);
2495 return NO_EXIT;
2496}
2497#endif
2498
22c37a08
RH
2499static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
2500{
2501 o->out = o->in2;
2502 o->g_out = o->g_in2;
2503 TCGV_UNUSED_I64(o->in2);
2504 o->g_in2 = false;
2505 return NO_EXIT;
2506}
2507
d764a8d1
RH
2508static ExitStatus op_movx(DisasContext *s, DisasOps *o)
2509{
2510 o->out = o->in1;
2511 o->out2 = o->in2;
2512 o->g_out = o->g_in1;
2513 o->g_out2 = o->g_in2;
2514 TCGV_UNUSED_I64(o->in1);
2515 TCGV_UNUSED_I64(o->in2);
2516 o->g_in1 = o->g_in2 = false;
2517 return NO_EXIT;
2518}
2519
af9e5a04
RH
2520static ExitStatus op_mvc(DisasContext *s, DisasOps *o)
2521{
2522 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
2523 potential_page_fault(s);
2524 gen_helper_mvc(cpu_env, l, o->addr1, o->in2);
2525 tcg_temp_free_i32(l);
2526 return NO_EXIT;
2527}
2528
e1eaada9
RH
2529static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
2530{
2531 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2532 TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
2533 potential_page_fault(s);
2534 gen_helper_mvcl(cc_op, cpu_env, r1, r2);
2535 tcg_temp_free_i32(r1);
2536 tcg_temp_free_i32(r2);
2537 set_cc_static(s);
2538 return NO_EXIT;
2539}
2540
eb66e6a9
RH
2541static ExitStatus op_mvcle(DisasContext *s, DisasOps *o)
2542{
2543 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2544 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2545 potential_page_fault(s);
2546 gen_helper_mvcle(cc_op, cpu_env, r1, o->in2, r3);
2547 tcg_temp_free_i32(r1);
2548 tcg_temp_free_i32(r3);
2549 set_cc_static(s);
2550 return NO_EXIT;
2551}
2552
97c3ab61
RH
2553#ifndef CONFIG_USER_ONLY
2554static ExitStatus op_mvcp(DisasContext *s, DisasOps *o)
2555{
2556 int r1 = get_field(s->fields, l1);
2557 check_privileged(s);
2558 potential_page_fault(s);
2559 gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
2560 set_cc_static(s);
2561 return NO_EXIT;
2562}
2563
2564static ExitStatus op_mvcs(DisasContext *s, DisasOps *o)
2565{
2566 int r1 = get_field(s->fields, l1);
2567 check_privileged(s);
2568 potential_page_fault(s);
2569 gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
2570 set_cc_static(s);
2571 return NO_EXIT;
2572}
2573#endif
2574
ee6c38d5
RH
2575static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
2576{
2577 potential_page_fault(s);
2578 gen_helper_mvpg(cpu_env, regs[0], o->in1, o->in2);
2579 set_cc_static(s);
2580 return NO_EXIT;
2581}
2582
aa31bf60
RH
2583static ExitStatus op_mvst(DisasContext *s, DisasOps *o)
2584{
2585 potential_page_fault(s);
2586 gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2);
2587 set_cc_static(s);
2588 return_low128(o->in2);
2589 return NO_EXIT;
2590}
2591
d1c04a2b
RH
2592static ExitStatus op_mul(DisasContext *s, DisasOps *o)
2593{
2594 tcg_gen_mul_i64(o->out, o->in1, o->in2);
2595 return NO_EXIT;
2596}
2597
1ac5889f
RH
2598static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
2599{
dc46d1c6 2600 tcg_gen_mulu2_i64(o->out2, o->out, o->in1, o->in2);
1ac5889f
RH
2601 return NO_EXIT;
2602}
2603
83b00736
RH
2604static ExitStatus op_meeb(DisasContext *s, DisasOps *o)
2605{
2606 gen_helper_meeb(o->out, cpu_env, o->in1, o->in2);
2607 return NO_EXIT;
2608}
2609
2610static ExitStatus op_mdeb(DisasContext *s, DisasOps *o)
2611{
2612 gen_helper_mdeb(o->out, cpu_env, o->in1, o->in2);
2613 return NO_EXIT;
2614}
2615
2616static ExitStatus op_mdb(DisasContext *s, DisasOps *o)
2617{
2618 gen_helper_mdb(o->out, cpu_env, o->in1, o->in2);
2619 return NO_EXIT;
2620}
2621
2622static ExitStatus op_mxb(DisasContext *s, DisasOps *o)
2623{
2624 gen_helper_mxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
2625 return_low128(o->out2);
2626 return NO_EXIT;
2627}
2628
2629static ExitStatus op_mxdb(DisasContext *s, DisasOps *o)
2630{
2631 gen_helper_mxdb(o->out, cpu_env, o->out, o->out2, o->in2);
2632 return_low128(o->out2);
2633 return NO_EXIT;
2634}
2635
722bfec3
RH
2636static ExitStatus op_maeb(DisasContext *s, DisasOps *o)
2637{
2638 TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
2639 gen_helper_maeb(o->out, cpu_env, o->in1, o->in2, r3);
2640 tcg_temp_free_i64(r3);
2641 return NO_EXIT;
2642}
2643
2644static ExitStatus op_madb(DisasContext *s, DisasOps *o)
2645{
2646 int r3 = get_field(s->fields, r3);
2647 gen_helper_madb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
2648 return NO_EXIT;
2649}
2650
2651static ExitStatus op_mseb(DisasContext *s, DisasOps *o)
2652{
2653 TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
2654 gen_helper_mseb(o->out, cpu_env, o->in1, o->in2, r3);
2655 tcg_temp_free_i64(r3);
2656 return NO_EXIT;
2657}
2658
2659static ExitStatus op_msdb(DisasContext *s, DisasOps *o)
2660{
2661 int r3 = get_field(s->fields, r3);
2662 gen_helper_msdb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
2663 return NO_EXIT;
2664}
2665
b9bca3e5
RH
2666static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
2667{
2668 gen_helper_nabs_i64(o->out, o->in2);
2669 return NO_EXIT;
2670}
2671
5d7fd045
RH
2672static ExitStatus op_nabsf32(DisasContext *s, DisasOps *o)
2673{
2674 tcg_gen_ori_i64(o->out, o->in2, 0x80000000ull);
2675 return NO_EXIT;
2676}
2677
2678static ExitStatus op_nabsf64(DisasContext *s, DisasOps *o)
2679{
2680 tcg_gen_ori_i64(o->out, o->in2, 0x8000000000000000ull);
2681 return NO_EXIT;
2682}
2683
2684static ExitStatus op_nabsf128(DisasContext *s, DisasOps *o)
2685{
2686 tcg_gen_ori_i64(o->out, o->in1, 0x8000000000000000ull);
2687 tcg_gen_mov_i64(o->out2, o->in2);
2688 return NO_EXIT;
2689}
2690
0a949039
RH
2691static ExitStatus op_nc(DisasContext *s, DisasOps *o)
2692{
2693 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
2694 potential_page_fault(s);
2695 gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2);
2696 tcg_temp_free_i32(l);
2697 set_cc_static(s);
2698 return NO_EXIT;
2699}
2700
b9bca3e5
RH
2701static ExitStatus op_neg(DisasContext *s, DisasOps *o)
2702{
2703 tcg_gen_neg_i64(o->out, o->in2);
2704 return NO_EXIT;
2705}
2706
5d7fd045
RH
2707static ExitStatus op_negf32(DisasContext *s, DisasOps *o)
2708{
2709 tcg_gen_xori_i64(o->out, o->in2, 0x80000000ull);
2710 return NO_EXIT;
2711}
2712
2713static ExitStatus op_negf64(DisasContext *s, DisasOps *o)
2714{
2715 tcg_gen_xori_i64(o->out, o->in2, 0x8000000000000000ull);
2716 return NO_EXIT;
2717}
2718
2719static ExitStatus op_negf128(DisasContext *s, DisasOps *o)
2720{
2721 tcg_gen_xori_i64(o->out, o->in1, 0x8000000000000000ull);
2722 tcg_gen_mov_i64(o->out2, o->in2);
2723 return NO_EXIT;
2724}
2725
0a949039
RH
2726static ExitStatus op_oc(DisasContext *s, DisasOps *o)
2727{
2728 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
2729 potential_page_fault(s);
2730 gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2);
2731 tcg_temp_free_i32(l);
2732 set_cc_static(s);
2733 return NO_EXIT;
2734}
2735
3bbfbd1f
RH
2736static ExitStatus op_or(DisasContext *s, DisasOps *o)
2737{
2738 tcg_gen_or_i64(o->out, o->in1, o->in2);
2739 return NO_EXIT;
2740}
2741
facfc864
RH
2742static ExitStatus op_ori(DisasContext *s, DisasOps *o)
2743{
2744 int shift = s->insn->data & 0xff;
2745 int size = s->insn->data >> 8;
2746 uint64_t mask = ((1ull << size) - 1) << shift;
2747
2748 assert(!o->g_in2);
2749 tcg_gen_shli_i64(o->in2, o->in2, shift);
2750 tcg_gen_or_i64(o->out, o->in1, o->in2);
2751
2752 /* Produce the CC from only the bits manipulated. */
2753 tcg_gen_andi_i64(cc_dst, o->out, mask);
2754 set_cc_nz_u64(s, cc_dst);
2755 return NO_EXIT;
2756}
2757
99b4f24b
RH
2758static ExitStatus op_popcnt(DisasContext *s, DisasOps *o)
2759{
2760 gen_helper_popcnt(o->out, o->in2);
2761 return NO_EXIT;
2762}
2763
0568d8aa
RH
2764#ifndef CONFIG_USER_ONLY
2765static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
2766{
2767 check_privileged(s);
2768 gen_helper_ptlb(cpu_env);
2769 return NO_EXIT;
2770}
2771#endif
2772
2d6a8698
RH
2773static ExitStatus op_risbg(DisasContext *s, DisasOps *o)
2774{
2775 int i3 = get_field(s->fields, i3);
2776 int i4 = get_field(s->fields, i4);
2777 int i5 = get_field(s->fields, i5);
2778 int do_zero = i4 & 0x80;
2779 uint64_t mask, imask, pmask;
2780 int pos, len, rot;
2781
2782 /* Adjust the arguments for the specific insn. */
2783 switch (s->fields->op2) {
2784 case 0x55: /* risbg */
2785 i3 &= 63;
2786 i4 &= 63;
2787 pmask = ~0;
2788 break;
2789 case 0x5d: /* risbhg */
2790 i3 &= 31;
2791 i4 &= 31;
2792 pmask = 0xffffffff00000000ull;
2793 break;
2794 case 0x51: /* risblg */
2795 i3 &= 31;
2796 i4 &= 31;
2797 pmask = 0x00000000ffffffffull;
2798 break;
2799 default:
2800 abort();
2801 }
2802
2803 /* MASK is the set of bits to be inserted from R2.
2804 Take care for I3/I4 wraparound. */
2805 mask = pmask >> i3;
2806 if (i3 <= i4) {
2807 mask ^= pmask >> i4 >> 1;
2808 } else {
2809 mask |= ~(pmask >> i4 >> 1);
2810 }
2811 mask &= pmask;
2812
2813 /* IMASK is the set of bits to be kept from R1. In the case of the high/low
2814 insns, we need to keep the other half of the register. */
2815 imask = ~mask | ~pmask;
2816 if (do_zero) {
2817 if (s->fields->op2 == 0x55) {
2818 imask = 0;
2819 } else {
2820 imask = ~pmask;
2821 }
2822 }
2823
2824 /* In some cases we can implement this with deposit, which can be more
2825 efficient on some hosts. */
2826 if (~mask == imask && i3 <= i4) {
2827 if (s->fields->op2 == 0x5d) {
2828 i3 += 32, i4 += 32;
2829 }
2830 /* Note that we rotate the bits to be inserted to the lsb, not to
2831 the position as described in the PoO. */
2832 len = i4 - i3 + 1;
2833 pos = 63 - i4;
2834 rot = (i5 - pos) & 63;
2835 } else {
2836 pos = len = -1;
2837 rot = i5 & 63;
2838 }
2839
2840 /* Rotate the input as necessary. */
2841 tcg_gen_rotli_i64(o->in2, o->in2, rot);
2842
2843 /* Insert the selected bits into the output. */
2844 if (pos >= 0) {
2845 tcg_gen_deposit_i64(o->out, o->out, o->in2, pos, len);
2846 } else if (imask == 0) {
2847 tcg_gen_andi_i64(o->out, o->in2, mask);
2848 } else {
2849 tcg_gen_andi_i64(o->in2, o->in2, mask);
2850 tcg_gen_andi_i64(o->out, o->out, imask);
2851 tcg_gen_or_i64(o->out, o->out, o->in2);
2852 }
2853 return NO_EXIT;
d6c6372e
RH
2854}
2855
2856static ExitStatus op_rosbg(DisasContext *s, DisasOps *o)
2857{
2858 int i3 = get_field(s->fields, i3);
2859 int i4 = get_field(s->fields, i4);
2860 int i5 = get_field(s->fields, i5);
2861 uint64_t mask;
2862
2863 /* If this is a test-only form, arrange to discard the result. */
2864 if (i3 & 0x80) {
2865 o->out = tcg_temp_new_i64();
2866 o->g_out = false;
2867 }
2868
2869 i3 &= 63;
2870 i4 &= 63;
2871 i5 &= 63;
2872
2873 /* MASK is the set of bits to be operated on from R2.
2874 Take care for I3/I4 wraparound. */
2875 mask = ~0ull >> i3;
2876 if (i3 <= i4) {
2877 mask ^= ~0ull >> i4 >> 1;
2878 } else {
2879 mask |= ~(~0ull >> i4 >> 1);
2880 }
2881
2882 /* Rotate the input as necessary. */
2883 tcg_gen_rotli_i64(o->in2, o->in2, i5);
2884
2885 /* Operate. */
2886 switch (s->fields->op2) {
2887 case 0x55: /* AND */
2888 tcg_gen_ori_i64(o->in2, o->in2, ~mask);
2889 tcg_gen_and_i64(o->out, o->out, o->in2);
2890 break;
2891 case 0x56: /* OR */
2892 tcg_gen_andi_i64(o->in2, o->in2, mask);
2893 tcg_gen_or_i64(o->out, o->out, o->in2);
2894 break;
2895 case 0x57: /* XOR */
2896 tcg_gen_andi_i64(o->in2, o->in2, mask);
2897 tcg_gen_xor_i64(o->out, o->out, o->in2);
2898 break;
2899 default:
2900 abort();
2901 }
2902
2903 /* Set the CC. */
2904 tcg_gen_andi_i64(cc_dst, o->out, mask);
2905 set_cc_nz_u64(s, cc_dst);
2906 return NO_EXIT;
2d6a8698
RH
2907}
2908
d54f5865
RH
2909static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
2910{
2911 tcg_gen_bswap16_i64(o->out, o->in2);
2912 return NO_EXIT;
2913}
2914
2915static ExitStatus op_rev32(DisasContext *s, DisasOps *o)
2916{
2917 tcg_gen_bswap32_i64(o->out, o->in2);
2918 return NO_EXIT;
2919}
2920
2921static ExitStatus op_rev64(DisasContext *s, DisasOps *o)
2922{
2923 tcg_gen_bswap64_i64(o->out, o->in2);
2924 return NO_EXIT;
2925}
2926
cbe24bfa
RH
2927static ExitStatus op_rll32(DisasContext *s, DisasOps *o)
2928{
2929 TCGv_i32 t1 = tcg_temp_new_i32();
2930 TCGv_i32 t2 = tcg_temp_new_i32();
2931 TCGv_i32 to = tcg_temp_new_i32();
2932 tcg_gen_trunc_i64_i32(t1, o->in1);
2933 tcg_gen_trunc_i64_i32(t2, o->in2);
2934 tcg_gen_rotl_i32(to, t1, t2);
2935 tcg_gen_extu_i32_i64(o->out, to);
2936 tcg_temp_free_i32(t1);
2937 tcg_temp_free_i32(t2);
2938 tcg_temp_free_i32(to);
2939 return NO_EXIT;
2940}
2941
2942static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
2943{
2944 tcg_gen_rotl_i64(o->out, o->in1, o->in2);
2945 return NO_EXIT;
2946}
2947
5cc69c54
RH
2948#ifndef CONFIG_USER_ONLY
2949static ExitStatus op_rrbe(DisasContext *s, DisasOps *o)
2950{
2951 check_privileged(s);
2952 gen_helper_rrbe(cc_op, cpu_env, o->in2);
2953 set_cc_static(s);
2954 return NO_EXIT;
2955}
14244b21
RH
2956
2957static ExitStatus op_sacf(DisasContext *s, DisasOps *o)
2958{
2959 check_privileged(s);
2960 gen_helper_sacf(cpu_env, o->in2);
2961 /* Addressing mode has changed, so end the block. */
2962 return EXIT_PC_STALE;
2963}
8612c935 2964#endif
44dd33ba
AG
2965
2966static ExitStatus op_sam(DisasContext *s, DisasOps *o)
2967{
2968 int sam = s->insn->data;
8612c935
RH
2969 TCGv_i64 tsam;
2970 uint64_t mask;
44dd33ba 2971
8612c935
RH
2972 switch (sam) {
2973 case 0:
2974 mask = 0xffffff;
2975 break;
2976 case 1:
2977 mask = 0x7fffffff;
2978 break;
2979 default:
2980 mask = -1;
2981 break;
2982 }
2983
2984 /* Bizzare but true, we check the address of the current insn for the
2985 specification exception, not the next to be executed. Thus the PoO
2986 documents that Bad Things Happen two bytes before the end. */
2987 if (s->pc & ~mask) {
2988 gen_program_exception(s, PGM_SPECIFICATION);
2989 return EXIT_NORETURN;
2990 }
2991 s->next_pc &= mask;
44dd33ba 2992
8612c935
RH
2993 tsam = tcg_const_i64(sam);
2994 tcg_gen_deposit_i64(psw_mask, psw_mask, tsam, 31, 2);
44dd33ba 2995 tcg_temp_free_i64(tsam);
8612c935
RH
2996
2997 /* Always exit the TB, since we (may have) changed execution mode. */
44dd33ba
AG
2998 return EXIT_PC_STALE;
2999}
5cc69c54 3000
d62a4c97
RH
3001static ExitStatus op_sar(DisasContext *s, DisasOps *o)
3002{
3003 int r1 = get_field(s->fields, r1);
3004 tcg_gen_st32_i64(o->in2, cpu_env, offsetof(CPUS390XState, aregs[r1]));
3005 return NO_EXIT;
3006}
3007
1a800a2d
RH
3008static ExitStatus op_seb(DisasContext *s, DisasOps *o)
3009{
3010 gen_helper_seb(o->out, cpu_env, o->in1, o->in2);
3011 return NO_EXIT;
3012}
3013
3014static ExitStatus op_sdb(DisasContext *s, DisasOps *o)
3015{
3016 gen_helper_sdb(o->out, cpu_env, o->in1, o->in2);
3017 return NO_EXIT;
3018}
3019
3020static ExitStatus op_sxb(DisasContext *s, DisasOps *o)
3021{
3022 gen_helper_sxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
3023 return_low128(o->out2);
3024 return NO_EXIT;
3025}
3026
16d7b2a4
RH
3027static ExitStatus op_sqeb(DisasContext *s, DisasOps *o)
3028{
3029 gen_helper_sqeb(o->out, cpu_env, o->in2);
3030 return NO_EXIT;
3031}
3032
3033static ExitStatus op_sqdb(DisasContext *s, DisasOps *o)
3034{
3035 gen_helper_sqdb(o->out, cpu_env, o->in2);
3036 return NO_EXIT;
3037}
3038
3039static ExitStatus op_sqxb(DisasContext *s, DisasOps *o)
3040{
3041 gen_helper_sqxb(o->out, cpu_env, o->in1, o->in2);
3042 return_low128(o->out2);
3043 return NO_EXIT;
3044}
3045
0c240015 3046#ifndef CONFIG_USER_ONLY
dc458df9
RH
3047static ExitStatus op_servc(DisasContext *s, DisasOps *o)
3048{
3049 check_privileged(s);
3050 potential_page_fault(s);
3051 gen_helper_servc(cc_op, cpu_env, o->in2, o->in1);
3052 set_cc_static(s);
3053 return NO_EXIT;
3054}
3055
0c240015
RH
3056static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
3057{
3058 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3059 check_privileged(s);
3060 potential_page_fault(s);
3061 gen_helper_sigp(cc_op, cpu_env, o->in2, r1, o->in1);
3062 tcg_temp_free_i32(r1);
3063 return NO_EXIT;
3064}
3065#endif
3066
b92fa334
RH
3067static ExitStatus op_soc(DisasContext *s, DisasOps *o)
3068{
3069 DisasCompare c;
3070 TCGv_i64 a;
3071 int lab, r1;
3072
3073 disas_jcc(s, &c, get_field(s->fields, m3));
3074
3075 lab = gen_new_label();
3076 if (c.is_64) {
3077 tcg_gen_brcond_i64(c.cond, c.u.s64.a, c.u.s64.b, lab);
3078 } else {
3079 tcg_gen_brcond_i32(c.cond, c.u.s32.a, c.u.s32.b, lab);
3080 }
3081 free_compare(&c);
3082
3083 r1 = get_field(s->fields, r1);
3084 a = get_address(s, 0, get_field(s->fields, b2), get_field(s->fields, d2));
3085 if (s->insn->data) {
3086 tcg_gen_qemu_st64(regs[r1], a, get_mem_index(s));
3087 } else {
3088 tcg_gen_qemu_st32(regs[r1], a, get_mem_index(s));
3089 }
3090 tcg_temp_free_i64(a);
3091
3092 gen_set_label(lab);
3093 return NO_EXIT;
3094}
3095
cbe24bfa
RH
3096static ExitStatus op_sla(DisasContext *s, DisasOps *o)
3097{
3098 uint64_t sign = 1ull << s->insn->data;
3099 enum cc_op cco = s->insn->data == 31 ? CC_OP_SLA_32 : CC_OP_SLA_64;
3100 gen_op_update2_cc_i64(s, cco, o->in1, o->in2);
3101 tcg_gen_shl_i64(o->out, o->in1, o->in2);
3102 /* The arithmetic left shift is curious in that it does not affect
3103 the sign bit. Copy that over from the source unchanged. */
3104 tcg_gen_andi_i64(o->out, o->out, ~sign);
3105 tcg_gen_andi_i64(o->in1, o->in1, sign);
3106 tcg_gen_or_i64(o->out, o->out, o->in1);
3107 return NO_EXIT;
3108}
3109
3110static ExitStatus op_sll(DisasContext *s, DisasOps *o)
3111{
3112 tcg_gen_shl_i64(o->out, o->in1, o->in2);
3113 return NO_EXIT;
3114}
3115
3116static ExitStatus op_sra(DisasContext *s, DisasOps *o)
3117{
3118 tcg_gen_sar_i64(o->out, o->in1, o->in2);
3119 return NO_EXIT;
3120}
3121
3122static ExitStatus op_srl(DisasContext *s, DisasOps *o)
3123{
3124 tcg_gen_shr_i64(o->out, o->in1, o->in2);
3125 return NO_EXIT;
3126}
3127
8379bfdb
RH
3128static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
3129{
3130 gen_helper_sfpc(cpu_env, o->in2);
3131 return NO_EXIT;
3132}
3133
411edc22
RH
3134static ExitStatus op_sfas(DisasContext *s, DisasOps *o)
3135{
3136 gen_helper_sfas(cpu_env, o->in2);
3137 return NO_EXIT;
3138}
3139
a12000b9
RH
3140static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
3141{
3142 int b2 = get_field(s->fields, b2);
3143 int d2 = get_field(s->fields, d2);
3144 TCGv_i64 t1 = tcg_temp_new_i64();
3145 TCGv_i64 t2 = tcg_temp_new_i64();
3146 int mask, pos, len;
3147
3148 switch (s->fields->op2) {
3149 case 0x99: /* SRNM */
3150 pos = 0, len = 2;
3151 break;
3152 case 0xb8: /* SRNMB */
3153 pos = 0, len = 3;
3154 break;
3155 case 0xb9: /* SRNMT */
3156 pos = 4, len = 3;
5b90a866 3157 break;
a12000b9
RH
3158 default:
3159 tcg_abort();
3160 }
3161 mask = (1 << len) - 1;
3162
3163 /* Insert the value into the appropriate field of the FPC. */
3164 if (b2 == 0) {
3165 tcg_gen_movi_i64(t1, d2 & mask);
3166 } else {
3167 tcg_gen_addi_i64(t1, regs[b2], d2);
3168 tcg_gen_andi_i64(t1, t1, mask);
3169 }
3170 tcg_gen_ld32u_i64(t2, cpu_env, offsetof(CPUS390XState, fpc));
3171 tcg_gen_deposit_i64(t2, t2, t1, pos, len);
3172 tcg_temp_free_i64(t1);
3173
3174 /* Then install the new FPC to set the rounding mode in fpu_status. */
3175 gen_helper_sfpc(cpu_env, t2);
3176 tcg_temp_free_i64(t2);
3177 return NO_EXIT;
3178}
3179
7d30bb73 3180#ifndef CONFIG_USER_ONLY
28d55556
RH
3181static ExitStatus op_spka(DisasContext *s, DisasOps *o)
3182{
3183 check_privileged(s);
3184 tcg_gen_shri_i64(o->in2, o->in2, 4);
3185 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY - 4, 4);
3186 return NO_EXIT;
3187}
3188
2bbde27f
RH
3189static ExitStatus op_sske(DisasContext *s, DisasOps *o)
3190{
3191 check_privileged(s);
3192 gen_helper_sske(cpu_env, o->in1, o->in2);
3193 return NO_EXIT;
3194}
3195
7d30bb73
RH
3196static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
3197{
3198 check_privileged(s);
3199 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
3200 return NO_EXIT;
3201}
145cdb40 3202
411fea3d
RH
3203static ExitStatus op_stap(DisasContext *s, DisasOps *o)
3204{
3205 check_privileged(s);
3206 /* ??? Surely cpu address != cpu number. In any case the previous
3207 version of this stored more than the required half-word, so it
3208 is unlikely this has ever been tested. */
3209 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
3210 return NO_EXIT;
3211}
3212
434c91a5
RH
3213static ExitStatus op_stck(DisasContext *s, DisasOps *o)
3214{
3215 gen_helper_stck(o->out, cpu_env);
3216 /* ??? We don't implement clock states. */
3217 gen_op_movi_cc(s, 0);
3218 return NO_EXIT;
39a5003c
RH
3219}
3220
3221static ExitStatus op_stcke(DisasContext *s, DisasOps *o)
3222{
3223 TCGv_i64 c1 = tcg_temp_new_i64();
3224 TCGv_i64 c2 = tcg_temp_new_i64();
3225 gen_helper_stck(c1, cpu_env);
3226 /* Shift the 64-bit value into its place as a zero-extended
3227 104-bit value. Note that "bit positions 64-103 are always
3228 non-zero so that they compare differently to STCK"; we set
3229 the least significant bit to 1. */
3230 tcg_gen_shli_i64(c2, c1, 56);
3231 tcg_gen_shri_i64(c1, c1, 8);
3232 tcg_gen_ori_i64(c2, c2, 0x10000);
3233 tcg_gen_qemu_st64(c1, o->in2, get_mem_index(s));
3234 tcg_gen_addi_i64(o->in2, o->in2, 8);
3235 tcg_gen_qemu_st64(c2, o->in2, get_mem_index(s));
3236 tcg_temp_free_i64(c1);
3237 tcg_temp_free_i64(c2);
3238 /* ??? We don't implement clock states. */
3239 gen_op_movi_cc(s, 0);
3240 return NO_EXIT;
434c91a5
RH
3241}
3242
dd3eb7b5
RH
3243static ExitStatus op_sckc(DisasContext *s, DisasOps *o)
3244{
3245 check_privileged(s);
3246 gen_helper_sckc(cpu_env, o->in2);
3247 return NO_EXIT;
3248}
3249
3250static ExitStatus op_stckc(DisasContext *s, DisasOps *o)
3251{
3252 check_privileged(s);
3253 gen_helper_stckc(o->out, cpu_env);
3254 return NO_EXIT;
3255}
3256
3e398cf9
RH
3257static ExitStatus op_stctg(DisasContext *s, DisasOps *o)
3258{
3259 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3260 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
3261 check_privileged(s);
3262 potential_page_fault(s);
3263 gen_helper_stctg(cpu_env, r1, o->in2, r3);
3264 tcg_temp_free_i32(r1);
3265 tcg_temp_free_i32(r3);
3266 return NO_EXIT;
3267}
3268
504488b8
RH
3269static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
3270{
3271 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3272 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
3273 check_privileged(s);
3274 potential_page_fault(s);
3275 gen_helper_stctl(cpu_env, r1, o->in2, r3);
3276 tcg_temp_free_i32(r1);
3277 tcg_temp_free_i32(r3);
3278 return NO_EXIT;
3279}
3280
71bd6669
RH
3281static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
3282{
7f745b31
RH
3283 TCGv_i64 t1 = tcg_temp_new_i64();
3284
71bd6669
RH
3285 check_privileged(s);
3286 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
7f745b31
RH
3287 tcg_gen_ld32u_i64(t1, cpu_env, offsetof(CPUS390XState, machine_type));
3288 tcg_gen_deposit_i64(o->out, o->out, t1, 32, 32);
3289 tcg_temp_free_i64(t1);
3290
71bd6669
RH
3291 return NO_EXIT;
3292}
3293
c4f0a863
RH
3294static ExitStatus op_spt(DisasContext *s, DisasOps *o)
3295{
3296 check_privileged(s);
3297 gen_helper_spt(cpu_env, o->in2);
3298 return NO_EXIT;
3299}
3300
fc778b55
RH
3301static ExitStatus op_stfl(DisasContext *s, DisasOps *o)
3302{
3303 TCGv_i64 f, a;
3304 /* We really ought to have more complete indication of facilities
3305 that we implement. Address this when STFLE is implemented. */
3306 check_privileged(s);
3307 f = tcg_const_i64(0xc0000000);
3308 a = tcg_const_i64(200);
3309 tcg_gen_qemu_st32(f, a, get_mem_index(s));
3310 tcg_temp_free_i64(f);
3311 tcg_temp_free_i64(a);
3312 return NO_EXIT;
3313}
3314
c4f0a863
RH
3315static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
3316{
3317 check_privileged(s);
3318 gen_helper_stpt(o->out, cpu_env);
3319 return NO_EXIT;
3320}
3321
d14b3e09
RH
3322static ExitStatus op_stsi(DisasContext *s, DisasOps *o)
3323{
3324 check_privileged(s);
3325 potential_page_fault(s);
3326 gen_helper_stsi(cc_op, cpu_env, o->in2, regs[0], regs[1]);
3327 set_cc_static(s);
3328 return NO_EXIT;
3329}
3330
e805a0d3
RH
3331static ExitStatus op_spx(DisasContext *s, DisasOps *o)
3332{
3333 check_privileged(s);
3334 gen_helper_spx(cpu_env, o->in2);
3335 return NO_EXIT;
3336}
3337
2c423fc0
RH
3338static ExitStatus op_subchannel(DisasContext *s, DisasOps *o)
3339{
3340 check_privileged(s);
3341 /* Not operational. */
3342 gen_op_movi_cc(s, 3);
3343 return NO_EXIT;
3344}
3345
e805a0d3
RH
3346static ExitStatus op_stpx(DisasContext *s, DisasOps *o)
3347{
3348 check_privileged(s);
3349 tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, psa));
3350 tcg_gen_andi_i64(o->out, o->out, 0x7fffe000);
3351 return NO_EXIT;
3352}
3353
145cdb40
RH
3354static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
3355{
3356 uint64_t i2 = get_field(s->fields, i2);
3357 TCGv_i64 t;
3358
3359 check_privileged(s);
3360
3361 /* It is important to do what the instruction name says: STORE THEN.
3362 If we let the output hook perform the store then if we fault and
3363 restart, we'll have the wrong SYSTEM MASK in place. */
3364 t = tcg_temp_new_i64();
3365 tcg_gen_shri_i64(t, psw_mask, 56);
3366 tcg_gen_qemu_st8(t, o->addr1, get_mem_index(s));
3367 tcg_temp_free_i64(t);
3368
3369 if (s->fields->op == 0xac) {
3370 tcg_gen_andi_i64(psw_mask, psw_mask,
3371 (i2 << 56) | 0x00ffffffffffffffull);
3372 } else {
3373 tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56);
3374 }
3375 return NO_EXIT;
3376}
204504e2
RH
3377
3378static ExitStatus op_stura(DisasContext *s, DisasOps *o)
3379{
3380 check_privileged(s);
3381 potential_page_fault(s);
3382 gen_helper_stura(cpu_env, o->in2, o->in1);
3383 return NO_EXIT;
3384}
9c3fd85b
RH
3385
3386static ExitStatus op_sturg(DisasContext *s, DisasOps *o)
3387{
3388 check_privileged(s);
3389 potential_page_fault(s);
3390 gen_helper_sturg(cpu_env, o->in2, o->in1);
3391 return NO_EXIT;
3392}
7d30bb73
RH
3393#endif
3394
2b280b97
RH
3395static ExitStatus op_st8(DisasContext *s, DisasOps *o)
3396{
3397 tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s));
3398 return NO_EXIT;
3399}
3400
3401static ExitStatus op_st16(DisasContext *s, DisasOps *o)
3402{
3403 tcg_gen_qemu_st16(o->in1, o->in2, get_mem_index(s));
3404 return NO_EXIT;
3405}
3406
3407static ExitStatus op_st32(DisasContext *s, DisasOps *o)
3408{
3409 tcg_gen_qemu_st32(o->in1, o->in2, get_mem_index(s));
3410 return NO_EXIT;
3411}
3412
3413static ExitStatus op_st64(DisasContext *s, DisasOps *o)
3414{
3415 tcg_gen_qemu_st64(o->in1, o->in2, get_mem_index(s));
3416 return NO_EXIT;
3417}
3418
7df3e93a
RH
3419static ExitStatus op_stam(DisasContext *s, DisasOps *o)
3420{
3421 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3422 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
3423 potential_page_fault(s);
3424 gen_helper_stam(cpu_env, r1, o->in2, r3);
3425 tcg_temp_free_i32(r1);
3426 tcg_temp_free_i32(r3);
3427 return NO_EXIT;
3428}
3429
2ae68059
RH
3430static ExitStatus op_stcm(DisasContext *s, DisasOps *o)
3431{
3432 int m3 = get_field(s->fields, m3);
3433 int pos, base = s->insn->data;
3434 TCGv_i64 tmp = tcg_temp_new_i64();
3435
3436 pos = base + ctz32(m3) * 8;
3437 switch (m3) {
3438 case 0xf:
3439 /* Effectively a 32-bit store. */
3440 tcg_gen_shri_i64(tmp, o->in1, pos);
3441 tcg_gen_qemu_st32(tmp, o->in2, get_mem_index(s));
3442 break;
3443
3444 case 0xc:
3445 case 0x6:
3446 case 0x3:
3447 /* Effectively a 16-bit store. */
3448 tcg_gen_shri_i64(tmp, o->in1, pos);
3449 tcg_gen_qemu_st16(tmp, o->in2, get_mem_index(s));
3450 break;
3451
3452 case 0x8:
3453 case 0x4:
3454 case 0x2:
3455 case 0x1:
3456 /* Effectively an 8-bit store. */
3457 tcg_gen_shri_i64(tmp, o->in1, pos);
3458 tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
3459 break;
3460
3461 default:
3462 /* This is going to be a sequence of shifts and stores. */
3463 pos = base + 32 - 8;
3464 while (m3) {
3465 if (m3 & 0x8) {
3466 tcg_gen_shri_i64(tmp, o->in1, pos);
3467 tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
3468 tcg_gen_addi_i64(o->in2, o->in2, 1);
3469 }
3470 m3 = (m3 << 1) & 0xf;
3471 pos -= 8;
3472 }
3473 break;
3474 }
3475 tcg_temp_free_i64(tmp);
3476 return NO_EXIT;
3477}
3478
77f8d6c3
RH
3479static ExitStatus op_stm(DisasContext *s, DisasOps *o)
3480{
3481 int r1 = get_field(s->fields, r1);
3482 int r3 = get_field(s->fields, r3);
3483 int size = s->insn->data;
3484 TCGv_i64 tsize = tcg_const_i64(size);
3485
3486 while (1) {
3487 if (size == 8) {
3488 tcg_gen_qemu_st64(regs[r1], o->in2, get_mem_index(s));
3489 } else {
3490 tcg_gen_qemu_st32(regs[r1], o->in2, get_mem_index(s));
3491 }
3492 if (r1 == r3) {
3493 break;
3494 }
3495 tcg_gen_add_i64(o->in2, o->in2, tsize);
3496 r1 = (r1 + 1) & 15;
3497 }
3498
3499 tcg_temp_free_i64(tsize);
3500 return NO_EXIT;
3501}
3502
3503static ExitStatus op_stmh(DisasContext *s, DisasOps *o)
3504{
3505 int r1 = get_field(s->fields, r1);
3506 int r3 = get_field(s->fields, r3);
3507 TCGv_i64 t = tcg_temp_new_i64();
3508 TCGv_i64 t4 = tcg_const_i64(4);
3509 TCGv_i64 t32 = tcg_const_i64(32);
3510
3511 while (1) {
3512 tcg_gen_shl_i64(t, regs[r1], t32);
3513 tcg_gen_qemu_st32(t, o->in2, get_mem_index(s));
3514 if (r1 == r3) {
3515 break;
3516 }
3517 tcg_gen_add_i64(o->in2, o->in2, t4);
3518 r1 = (r1 + 1) & 15;
3519 }
3520
3521 tcg_temp_free_i64(t);
3522 tcg_temp_free_i64(t4);
3523 tcg_temp_free_i64(t32);
3524 return NO_EXIT;
3525}
3526
4600c994
RH
3527static ExitStatus op_srst(DisasContext *s, DisasOps *o)
3528{
3529 potential_page_fault(s);
3530 gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2);
3531 set_cc_static(s);
3532 return_low128(o->in2);
3533 return NO_EXIT;
3534}
3535
ad044d09
RH
3536static ExitStatus op_sub(DisasContext *s, DisasOps *o)
3537{
3538 tcg_gen_sub_i64(o->out, o->in1, o->in2);
3539 return NO_EXIT;
3540}
3541
4e4bb438
RH
3542static ExitStatus op_subb(DisasContext *s, DisasOps *o)
3543{
c95ec459
RH
3544 DisasCompare cmp;
3545 TCGv_i64 borrow;
4e4bb438 3546
c95ec459 3547 tcg_gen_sub_i64(o->out, o->in1, o->in2);
4e4bb438 3548
c95ec459
RH
3549 /* The !borrow flag is the msb of CC. Since we want the inverse of
3550 that, we ask for a comparison of CC=0 | CC=1 -> mask of 8 | 4. */
3551 disas_jcc(s, &cmp, 8 | 4);
3552 borrow = tcg_temp_new_i64();
3553 if (cmp.is_64) {
3554 tcg_gen_setcond_i64(cmp.cond, borrow, cmp.u.s64.a, cmp.u.s64.b);
3555 } else {
3556 TCGv_i32 t = tcg_temp_new_i32();
3557 tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
3558 tcg_gen_extu_i32_i64(borrow, t);
3559 tcg_temp_free_i32(t);
3560 }
3561 free_compare(&cmp);
3562
3563 tcg_gen_sub_i64(o->out, o->out, borrow);
3564 tcg_temp_free_i64(borrow);
4e4bb438
RH
3565 return NO_EXIT;
3566}
3567
b9836c1a
RH
3568static ExitStatus op_svc(DisasContext *s, DisasOps *o)
3569{
3570 TCGv_i32 t;
3571
3572 update_psw_addr(s);
7a6c7067 3573 update_cc_op(s);
b9836c1a
RH
3574
3575 t = tcg_const_i32(get_field(s->fields, i1) & 0xff);
3576 tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code));
3577 tcg_temp_free_i32(t);
3578
3579 t = tcg_const_i32(s->next_pc - s->pc);
3580 tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
3581 tcg_temp_free_i32(t);
3582
3583 gen_exception(EXCP_SVC);
3584 return EXIT_NORETURN;
3585}
3586
31aa97d1
RH
3587static ExitStatus op_tceb(DisasContext *s, DisasOps *o)
3588{
3589 gen_helper_tceb(cc_op, o->in1, o->in2);
3590 set_cc_static(s);
3591 return NO_EXIT;
3592}
3593
3594static ExitStatus op_tcdb(DisasContext *s, DisasOps *o)
3595{
3596 gen_helper_tcdb(cc_op, o->in1, o->in2);
3597 set_cc_static(s);
3598 return NO_EXIT;
3599}
3600
3601static ExitStatus op_tcxb(DisasContext *s, DisasOps *o)
3602{
3603 gen_helper_tcxb(cc_op, o->out, o->out2, o->in2);
3604 set_cc_static(s);
3605 return NO_EXIT;
3606}
3607
112bf079
RH
3608#ifndef CONFIG_USER_ONLY
3609static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
3610{
3611 potential_page_fault(s);
3612 gen_helper_tprot(cc_op, o->addr1, o->in2);
3613 set_cc_static(s);
3614 return NO_EXIT;
3615}
3616#endif
3617
0a949039
RH
3618static ExitStatus op_tr(DisasContext *s, DisasOps *o)
3619{
3620 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3621 potential_page_fault(s);
3622 gen_helper_tr(cpu_env, l, o->addr1, o->in2);
3623 tcg_temp_free_i32(l);
3624 set_cc_static(s);
3625 return NO_EXIT;
3626}
3627
3628static ExitStatus op_unpk(DisasContext *s, DisasOps *o)
3629{
3630 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3631 potential_page_fault(s);
3632 gen_helper_unpk(cpu_env, l, o->addr1, o->in2);
3633 tcg_temp_free_i32(l);
3634 return NO_EXIT;
3635}
3636
3637static ExitStatus op_xc(DisasContext *s, DisasOps *o)
3638{
d074ac6d
RH
3639 int d1 = get_field(s->fields, d1);
3640 int d2 = get_field(s->fields, d2);
3641 int b1 = get_field(s->fields, b1);
3642 int b2 = get_field(s->fields, b2);
3643 int l = get_field(s->fields, l1);
3644 TCGv_i32 t32;
3645
3646 o->addr1 = get_address(s, 0, b1, d1);
3647
3648 /* If the addresses are identical, this is a store/memset of zero. */
3649 if (b1 == b2 && d1 == d2 && (l + 1) <= 32) {
3650 o->in2 = tcg_const_i64(0);
3651
3652 l++;
3653 while (l >= 8) {
3654 tcg_gen_qemu_st64(o->in2, o->addr1, get_mem_index(s));
3655 l -= 8;
3656 if (l > 0) {
3657 tcg_gen_addi_i64(o->addr1, o->addr1, 8);
3658 }
3659 }
3660 if (l >= 4) {
3661 tcg_gen_qemu_st32(o->in2, o->addr1, get_mem_index(s));
3662 l -= 4;
3663 if (l > 0) {
3664 tcg_gen_addi_i64(o->addr1, o->addr1, 4);
3665 }
3666 }
3667 if (l >= 2) {
3668 tcg_gen_qemu_st16(o->in2, o->addr1, get_mem_index(s));
3669 l -= 2;
3670 if (l > 0) {
3671 tcg_gen_addi_i64(o->addr1, o->addr1, 2);
3672 }
3673 }
3674 if (l) {
3675 tcg_gen_qemu_st8(o->in2, o->addr1, get_mem_index(s));
3676 }
3677 gen_op_movi_cc(s, 0);
3678 return NO_EXIT;
3679 }
3680
3681 /* But in general we'll defer to a helper. */
3682 o->in2 = get_address(s, 0, b2, d2);
3683 t32 = tcg_const_i32(l);
0a949039 3684 potential_page_fault(s);
d074ac6d
RH
3685 gen_helper_xc(cc_op, cpu_env, t32, o->addr1, o->in2);
3686 tcg_temp_free_i32(t32);
0a949039
RH
3687 set_cc_static(s);
3688 return NO_EXIT;
3689}
3690
3bbfbd1f
RH
3691static ExitStatus op_xor(DisasContext *s, DisasOps *o)
3692{
3693 tcg_gen_xor_i64(o->out, o->in1, o->in2);
3694 return NO_EXIT;
3695}
3696
facfc864
RH
3697static ExitStatus op_xori(DisasContext *s, DisasOps *o)
3698{
3699 int shift = s->insn->data & 0xff;
3700 int size = s->insn->data >> 8;
3701 uint64_t mask = ((1ull << size) - 1) << shift;
3702
3703 assert(!o->g_in2);
3704 tcg_gen_shli_i64(o->in2, o->in2, shift);
3705 tcg_gen_xor_i64(o->out, o->in1, o->in2);
3706
3707 /* Produce the CC from only the bits manipulated. */
3708 tcg_gen_andi_i64(cc_dst, o->out, mask);
3709 set_cc_nz_u64(s, cc_dst);
3710 return NO_EXIT;
3711}
3712
24db8412
RH
3713static ExitStatus op_zero(DisasContext *s, DisasOps *o)
3714{
3715 o->out = tcg_const_i64(0);
3716 return NO_EXIT;
3717}
3718
3719static ExitStatus op_zero2(DisasContext *s, DisasOps *o)
3720{
3721 o->out = tcg_const_i64(0);
3722 o->out2 = o->out;
3723 o->g_out2 = true;
3724 return NO_EXIT;
3725}
3726
ad044d09
RH
3727/* ====================================================================== */
3728/* The "Cc OUTput" generators. Given the generated output (and in some cases
3729 the original inputs), update the various cc data structures in order to
3730 be able to compute the new condition code. */
3731
b9bca3e5
RH
3732static void cout_abs32(DisasContext *s, DisasOps *o)
3733{
3734 gen_op_update1_cc_i64(s, CC_OP_ABS_32, o->out);
3735}
3736
3737static void cout_abs64(DisasContext *s, DisasOps *o)
3738{
3739 gen_op_update1_cc_i64(s, CC_OP_ABS_64, o->out);
3740}
3741
ad044d09
RH
3742static void cout_adds32(DisasContext *s, DisasOps *o)
3743{
3744 gen_op_update3_cc_i64(s, CC_OP_ADD_32, o->in1, o->in2, o->out);
3745}
3746
3747static void cout_adds64(DisasContext *s, DisasOps *o)
3748{
3749 gen_op_update3_cc_i64(s, CC_OP_ADD_64, o->in1, o->in2, o->out);
3750}
3751
3752static void cout_addu32(DisasContext *s, DisasOps *o)
3753{
3754 gen_op_update3_cc_i64(s, CC_OP_ADDU_32, o->in1, o->in2, o->out);
3755}
3756
3757static void cout_addu64(DisasContext *s, DisasOps *o)
3758{
3759 gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
3760}
3761
4e4bb438
RH
3762static void cout_addc32(DisasContext *s, DisasOps *o)
3763{
3764 gen_op_update3_cc_i64(s, CC_OP_ADDC_32, o->in1, o->in2, o->out);
3765}
3766
3767static void cout_addc64(DisasContext *s, DisasOps *o)
3768{
3769 gen_op_update3_cc_i64(s, CC_OP_ADDC_64, o->in1, o->in2, o->out);
3770}
3771
a7e836d5
RH
3772static void cout_cmps32(DisasContext *s, DisasOps *o)
3773{
3774 gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);
3775}
3776
3777static void cout_cmps64(DisasContext *s, DisasOps *o)
3778{
3779 gen_op_update2_cc_i64(s, CC_OP_LTGT_64, o->in1, o->in2);
3780}
3781
3782static void cout_cmpu32(DisasContext *s, DisasOps *o)
3783{
3784 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_32, o->in1, o->in2);
3785}
3786
3787static void cout_cmpu64(DisasContext *s, DisasOps *o)
3788{
3789 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
3790}
3791
587626f8
RH
3792static void cout_f32(DisasContext *s, DisasOps *o)
3793{
3794 gen_op_update1_cc_i64(s, CC_OP_NZ_F32, o->out);
3795}
3796
3797static void cout_f64(DisasContext *s, DisasOps *o)
3798{
3799 gen_op_update1_cc_i64(s, CC_OP_NZ_F64, o->out);
3800}
3801
3802static void cout_f128(DisasContext *s, DisasOps *o)
3803{
3804 gen_op_update2_cc_i64(s, CC_OP_NZ_F128, o->out, o->out2);
3805}
3806
b9bca3e5
RH
3807static void cout_nabs32(DisasContext *s, DisasOps *o)
3808{
3809 gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
3810}
3811
3812static void cout_nabs64(DisasContext *s, DisasOps *o)
3813{
3814 gen_op_update1_cc_i64(s, CC_OP_NABS_64, o->out);
3815}
3816
3817static void cout_neg32(DisasContext *s, DisasOps *o)
3818{
3819 gen_op_update1_cc_i64(s, CC_OP_COMP_32, o->out);
3820}
3821
3822static void cout_neg64(DisasContext *s, DisasOps *o)
3823{
3824 gen_op_update1_cc_i64(s, CC_OP_COMP_64, o->out);
3825}
3826
3bbfbd1f
RH
3827static void cout_nz32(DisasContext *s, DisasOps *o)
3828{
3829 tcg_gen_ext32u_i64(cc_dst, o->out);
3830 gen_op_update1_cc_i64(s, CC_OP_NZ, cc_dst);
3831}
3832
3833static void cout_nz64(DisasContext *s, DisasOps *o)
3834{
3835 gen_op_update1_cc_i64(s, CC_OP_NZ, o->out);
3836}
3837
11bf2d73
RH
3838static void cout_s32(DisasContext *s, DisasOps *o)
3839{
3840 gen_op_update1_cc_i64(s, CC_OP_LTGT0_32, o->out);
3841}
3842
3843static void cout_s64(DisasContext *s, DisasOps *o)
3844{
3845 gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, o->out);
3846}
3847
ad044d09
RH
3848static void cout_subs32(DisasContext *s, DisasOps *o)
3849{
3850 gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
3851}
3852
3853static void cout_subs64(DisasContext *s, DisasOps *o)
3854{
3855 gen_op_update3_cc_i64(s, CC_OP_SUB_64, o->in1, o->in2, o->out);
3856}
3857
3858static void cout_subu32(DisasContext *s, DisasOps *o)
3859{
3860 gen_op_update3_cc_i64(s, CC_OP_SUBU_32, o->in1, o->in2, o->out);
3861}
3862
3863static void cout_subu64(DisasContext *s, DisasOps *o)
3864{
3865 gen_op_update3_cc_i64(s, CC_OP_SUBU_64, o->in1, o->in2, o->out);
3866}
3867
4e4bb438
RH
3868static void cout_subb32(DisasContext *s, DisasOps *o)
3869{
3870 gen_op_update3_cc_i64(s, CC_OP_SUBB_32, o->in1, o->in2, o->out);
3871}
3872
3873static void cout_subb64(DisasContext *s, DisasOps *o)
3874{
3875 gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
3876}
3877
00d2dc19
RH
3878static void cout_tm32(DisasContext *s, DisasOps *o)
3879{
3880 gen_op_update2_cc_i64(s, CC_OP_TM_32, o->in1, o->in2);
3881}
3882
3883static void cout_tm64(DisasContext *s, DisasOps *o)
3884{
3885 gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2);
3886}
3887
ad044d09 3888/* ====================================================================== */
805a2505 3889/* The "PREParation" generators. These initialize the DisasOps.OUT fields
ad044d09
RH
3890 with the TCG register to which we will write. Used in combination with
3891 the "wout" generators, in some cases we need a new temporary, and in
3892 some cases we can write to a TCG global. */
3893
3894static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
3895{
3896 o->out = tcg_temp_new_i64();
3897}
49f7ee80 3898#define SPEC_prep_new 0
ad044d09 3899
891452e5
RH
3900static void prep_new_P(DisasContext *s, DisasFields *f, DisasOps *o)
3901{
3902 o->out = tcg_temp_new_i64();
3903 o->out2 = tcg_temp_new_i64();
3904}
49f7ee80 3905#define SPEC_prep_new_P 0
891452e5 3906
ad044d09
RH
3907static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
3908{
3909 o->out = regs[get_field(f, r1)];
3910 o->g_out = true;
3911}
49f7ee80 3912#define SPEC_prep_r1 0
ad044d09 3913
1ac5889f
RH
3914static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
3915{
1ac5889f
RH
3916 int r1 = get_field(f, r1);
3917 o->out = regs[r1];
49f7ee80 3918 o->out2 = regs[r1 + 1];
1ac5889f
RH
3919 o->g_out = o->g_out2 = true;
3920}
49f7ee80 3921#define SPEC_prep_r1_P SPEC_r1_even
1ac5889f 3922
587626f8
RH
3923static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
3924{
3925 o->out = fregs[get_field(f, r1)];
3926 o->g_out = true;
3927}
49f7ee80 3928#define SPEC_prep_f1 0
587626f8
RH
3929
3930static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o)
3931{
587626f8
RH
3932 int r1 = get_field(f, r1);
3933 o->out = fregs[r1];
49f7ee80 3934 o->out2 = fregs[r1 + 2];
587626f8
RH
3935 o->g_out = o->g_out2 = true;
3936}
49f7ee80 3937#define SPEC_prep_x1 SPEC_r1_f128
587626f8 3938
ad044d09
RH
3939/* ====================================================================== */
3940/* The "Write OUTput" generators. These generally perform some non-trivial
3941 copy of data to TCG globals, or to main memory. The trivial cases are
3942 generally handled by having a "prep" generator install the TCG global
3943 as the destination of the operation. */
3944
22c37a08
RH
3945static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
3946{
3947 store_reg(get_field(f, r1), o->out);
3948}
49f7ee80 3949#define SPEC_wout_r1 0
22c37a08 3950
afdc70be
RH
3951static void wout_r1_8(DisasContext *s, DisasFields *f, DisasOps *o)
3952{
3953 int r1 = get_field(f, r1);
3954 tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8);
3955}
49f7ee80 3956#define SPEC_wout_r1_8 0
afdc70be 3957
d54f5865
RH
3958static void wout_r1_16(DisasContext *s, DisasFields *f, DisasOps *o)
3959{
3960 int r1 = get_field(f, r1);
3961 tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 16);
3962}
49f7ee80 3963#define SPEC_wout_r1_16 0
d54f5865 3964
ad044d09
RH
3965static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
3966{
3967 store_reg32_i64(get_field(f, r1), o->out);
3968}
49f7ee80 3969#define SPEC_wout_r1_32 0
ad044d09 3970
891452e5
RH
3971static void wout_r1_P32(DisasContext *s, DisasFields *f, DisasOps *o)
3972{
891452e5
RH
3973 int r1 = get_field(f, r1);
3974 store_reg32_i64(r1, o->out);
49f7ee80 3975 store_reg32_i64(r1 + 1, o->out2);
891452e5 3976}
49f7ee80 3977#define SPEC_wout_r1_P32 SPEC_r1_even
891452e5 3978
d87aaf93
RH
3979static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
3980{
d87aaf93 3981 int r1 = get_field(f, r1);
49f7ee80 3982 store_reg32_i64(r1 + 1, o->out);
d87aaf93
RH
3983 tcg_gen_shri_i64(o->out, o->out, 32);
3984 store_reg32_i64(r1, o->out);
3985}
49f7ee80 3986#define SPEC_wout_r1_D32 SPEC_r1_even
22c37a08 3987
d764a8d1
RH
3988static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o)
3989{
3990 store_freg32_i64(get_field(f, r1), o->out);
3991}
49f7ee80 3992#define SPEC_wout_e1 0
d764a8d1
RH
3993
3994static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
3995{
3996 store_freg(get_field(f, r1), o->out);
3997}
49f7ee80 3998#define SPEC_wout_f1 0
d764a8d1
RH
3999
4000static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
4001{
4002 int f1 = get_field(s->fields, r1);
4003 store_freg(f1, o->out);
49f7ee80 4004 store_freg(f1 + 2, o->out2);
d764a8d1 4005}
49f7ee80 4006#define SPEC_wout_x1 SPEC_r1_f128
d764a8d1 4007
22c37a08
RH
4008static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
4009{
4010 if (get_field(f, r1) != get_field(f, r2)) {
4011 store_reg32_i64(get_field(f, r1), o->out);
4012 }
4013}
49f7ee80 4014#define SPEC_wout_cond_r1r2_32 0
d87aaf93 4015
d764a8d1
RH
4016static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
4017{
4018 if (get_field(f, r1) != get_field(f, r2)) {
4019 store_freg32_i64(get_field(f, r1), o->out);
4020 }
4021}
49f7ee80 4022#define SPEC_wout_cond_e1e2 0
d764a8d1 4023
6a04d76a
RH
4024static void wout_m1_8(DisasContext *s, DisasFields *f, DisasOps *o)
4025{
4026 tcg_gen_qemu_st8(o->out, o->addr1, get_mem_index(s));
4027}
49f7ee80 4028#define SPEC_wout_m1_8 0
6a04d76a
RH
4029
4030static void wout_m1_16(DisasContext *s, DisasFields *f, DisasOps *o)
4031{
4032 tcg_gen_qemu_st16(o->out, o->addr1, get_mem_index(s));
4033}
49f7ee80 4034#define SPEC_wout_m1_16 0
6a04d76a 4035
ad044d09
RH
4036static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
4037{
4038 tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
4039}
49f7ee80 4040#define SPEC_wout_m1_32 0
ad044d09
RH
4041
4042static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
4043{
4044 tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
4045}
49f7ee80 4046#define SPEC_wout_m1_64 0
ad044d09 4047
ea20490f
RH
4048static void wout_m2_32(DisasContext *s, DisasFields *f, DisasOps *o)
4049{
4050 tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s));
4051}
49f7ee80 4052#define SPEC_wout_m2_32 0
ea20490f 4053
ad044d09
RH
4054/* ====================================================================== */
4055/* The "INput 1" generators. These load the first operand to an insn. */
4056
4057static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
4058{
4059 o->in1 = load_reg(get_field(f, r1));
4060}
49f7ee80 4061#define SPEC_in1_r1 0
ad044d09 4062
d1c04a2b
RH
4063static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4064{
4065 o->in1 = regs[get_field(f, r1)];
4066 o->g_in1 = true;
4067}
49f7ee80 4068#define SPEC_in1_r1_o 0
d1c04a2b 4069
cbe24bfa
RH
4070static void in1_r1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4071{
4072 o->in1 = tcg_temp_new_i64();
4073 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1)]);
4074}
49f7ee80 4075#define SPEC_in1_r1_32s 0
cbe24bfa
RH
4076
4077static void in1_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4078{
4079 o->in1 = tcg_temp_new_i64();
4080 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1)]);
4081}
49f7ee80 4082#define SPEC_in1_r1_32u 0
cbe24bfa 4083
32a44d58
RH
4084static void in1_r1_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
4085{
4086 o->in1 = tcg_temp_new_i64();
4087 tcg_gen_shri_i64(o->in1, regs[get_field(f, r1)], 32);
4088}
49f7ee80 4089#define SPEC_in1_r1_sr32 0
32a44d58 4090
1ac5889f
RH
4091static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
4092{
49f7ee80 4093 o->in1 = load_reg(get_field(f, r1) + 1);
1ac5889f 4094}
49f7ee80 4095#define SPEC_in1_r1p1 SPEC_r1_even
1ac5889f 4096
d87aaf93
RH
4097static void in1_r1p1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4098{
d87aaf93 4099 o->in1 = tcg_temp_new_i64();
49f7ee80 4100 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1) + 1]);
d87aaf93 4101}
49f7ee80 4102#define SPEC_in1_r1p1_32s SPEC_r1_even
d87aaf93
RH
4103
4104static void in1_r1p1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4105{
d87aaf93 4106 o->in1 = tcg_temp_new_i64();
49f7ee80 4107 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1) + 1]);
d87aaf93 4108}
49f7ee80 4109#define SPEC_in1_r1p1_32u SPEC_r1_even
d87aaf93 4110
891452e5
RH
4111static void in1_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4112{
891452e5
RH
4113 int r1 = get_field(f, r1);
4114 o->in1 = tcg_temp_new_i64();
4115 tcg_gen_concat32_i64(o->in1, regs[r1 + 1], regs[r1]);
4116}
49f7ee80 4117#define SPEC_in1_r1_D32 SPEC_r1_even
891452e5 4118
ad044d09
RH
4119static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
4120{
4121 o->in1 = load_reg(get_field(f, r2));
4122}
49f7ee80 4123#define SPEC_in1_r2 0
ad044d09
RH
4124
4125static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
4126{
4127 o->in1 = load_reg(get_field(f, r3));
4128}
49f7ee80 4129#define SPEC_in1_r3 0
ad044d09 4130
cbe24bfa
RH
4131static void in1_r3_o(DisasContext *s, DisasFields *f, DisasOps *o)
4132{
4133 o->in1 = regs[get_field(f, r3)];
4134 o->g_in1 = true;
4135}
49f7ee80 4136#define SPEC_in1_r3_o 0
cbe24bfa
RH
4137
4138static void in1_r3_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4139{
4140 o->in1 = tcg_temp_new_i64();
4141 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r3)]);
4142}
49f7ee80 4143#define SPEC_in1_r3_32s 0
cbe24bfa
RH
4144
4145static void in1_r3_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4146{
4147 o->in1 = tcg_temp_new_i64();
4148 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r3)]);
4149}
49f7ee80 4150#define SPEC_in1_r3_32u 0
cbe24bfa 4151
b7886de3
RH
4152static void in1_r3_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4153{
4154 int r3 = get_field(f, r3);
4155 o->in1 = tcg_temp_new_i64();
4156 tcg_gen_concat32_i64(o->in1, regs[r3 + 1], regs[r3]);
4157}
4158#define SPEC_in1_r3_D32 SPEC_r3_even
4159
00574261
RH
4160static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
4161{
4162 o->in1 = load_freg32_i64(get_field(f, r1));
4163}
49f7ee80 4164#define SPEC_in1_e1 0
00574261
RH
4165
4166static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4167{
4168 o->in1 = fregs[get_field(f, r1)];
4169 o->g_in1 = true;
4170}
49f7ee80 4171#define SPEC_in1_f1_o 0
00574261 4172
587626f8
RH
4173static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4174{
587626f8
RH
4175 int r1 = get_field(f, r1);
4176 o->out = fregs[r1];
49f7ee80 4177 o->out2 = fregs[r1 + 2];
587626f8
RH
4178 o->g_out = o->g_out2 = true;
4179}
49f7ee80 4180#define SPEC_in1_x1_o SPEC_r1_f128
587626f8 4181
2db014b5
RH
4182static void in1_f3_o(DisasContext *s, DisasFields *f, DisasOps *o)
4183{
4184 o->in1 = fregs[get_field(f, r3)];
4185 o->g_in1 = true;
4186}
49f7ee80 4187#define SPEC_in1_f3_o 0
2db014b5 4188
ad044d09
RH
4189static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
4190{
4191 o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
4192}
49f7ee80 4193#define SPEC_in1_la1 0
ad044d09 4194
e025e52a
RH
4195static void in1_la2(DisasContext *s, DisasFields *f, DisasOps *o)
4196{
4197 int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
4198 o->addr1 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
4199}
49f7ee80 4200#define SPEC_in1_la2 0
e025e52a 4201
a7e836d5
RH
4202static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4203{
4204 in1_la1(s, f, o);
4205 o->in1 = tcg_temp_new_i64();
4206 tcg_gen_qemu_ld8u(o->in1, o->addr1, get_mem_index(s));
4207}
49f7ee80 4208#define SPEC_in1_m1_8u 0
a7e836d5
RH
4209
4210static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4211{
4212 in1_la1(s, f, o);
4213 o->in1 = tcg_temp_new_i64();
4214 tcg_gen_qemu_ld16s(o->in1, o->addr1, get_mem_index(s));
4215}
49f7ee80 4216#define SPEC_in1_m1_16s 0
a7e836d5
RH
4217
4218static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4219{
4220 in1_la1(s, f, o);
4221 o->in1 = tcg_temp_new_i64();
4222 tcg_gen_qemu_ld16u(o->in1, o->addr1, get_mem_index(s));
4223}
49f7ee80 4224#define SPEC_in1_m1_16u 0
a7e836d5 4225
ad044d09
RH
4226static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4227{
4228 in1_la1(s, f, o);
4229 o->in1 = tcg_temp_new_i64();
4230 tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
4231}
49f7ee80 4232#define SPEC_in1_m1_32s 0
ad044d09 4233
e272b3ac
RH
4234static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4235{
4236 in1_la1(s, f, o);
4237 o->in1 = tcg_temp_new_i64();
4238 tcg_gen_qemu_ld32u(o->in1, o->addr1, get_mem_index(s));
4239}
49f7ee80 4240#define SPEC_in1_m1_32u 0
e272b3ac 4241
ad044d09
RH
4242static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
4243{
4244 in1_la1(s, f, o);
4245 o->in1 = tcg_temp_new_i64();
4246 tcg_gen_qemu_ld64(o->in1, o->addr1, get_mem_index(s));
4247}
49f7ee80 4248#define SPEC_in1_m1_64 0
ad044d09
RH
4249
4250/* ====================================================================== */
4251/* The "INput 2" generators. These load the second operand to an insn. */
4252
e025e52a
RH
4253static void in2_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4254{
4255 o->in2 = regs[get_field(f, r1)];
4256 o->g_in2 = true;
4257}
49f7ee80 4258#define SPEC_in2_r1_o 0
e025e52a
RH
4259
4260static void in2_r1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4261{
4262 o->in2 = tcg_temp_new_i64();
4263 tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r1)]);
4264}
49f7ee80 4265#define SPEC_in2_r1_16u 0
e025e52a
RH
4266
4267static void in2_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4268{
4269 o->in2 = tcg_temp_new_i64();
4270 tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r1)]);
4271}
49f7ee80 4272#define SPEC_in2_r1_32u 0
e025e52a 4273
b7886de3
RH
4274static void in2_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4275{
4276 int r1 = get_field(f, r1);
4277 o->in2 = tcg_temp_new_i64();
4278 tcg_gen_concat32_i64(o->in2, regs[r1 + 1], regs[r1]);
4279}
4280#define SPEC_in2_r1_D32 SPEC_r1_even
4281
ad044d09
RH
4282static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
4283{
4284 o->in2 = load_reg(get_field(f, r2));
4285}
49f7ee80 4286#define SPEC_in2_r2 0
ad044d09 4287
d1c04a2b
RH
4288static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
4289{
4290 o->in2 = regs[get_field(f, r2)];
4291 o->g_in2 = true;
4292}
49f7ee80 4293#define SPEC_in2_r2_o 0
d1c04a2b 4294
8ac33cdb
RH
4295static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
4296{
4297 int r2 = get_field(f, r2);
4298 if (r2 != 0) {
4299 o->in2 = load_reg(r2);
4300 }
4301}
49f7ee80 4302#define SPEC_in2_r2_nz 0
8ac33cdb 4303
c698d876
RH
4304static void in2_r2_8s(DisasContext *s, DisasFields *f, DisasOps *o)
4305{
4306 o->in2 = tcg_temp_new_i64();
4307 tcg_gen_ext8s_i64(o->in2, regs[get_field(f, r2)]);
4308}
49f7ee80 4309#define SPEC_in2_r2_8s 0
c698d876
RH
4310
4311static void in2_r2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4312{
4313 o->in2 = tcg_temp_new_i64();
4314 tcg_gen_ext8u_i64(o->in2, regs[get_field(f, r2)]);
4315}
49f7ee80 4316#define SPEC_in2_r2_8u 0
c698d876
RH
4317
4318static void in2_r2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4319{
4320 o->in2 = tcg_temp_new_i64();
4321 tcg_gen_ext16s_i64(o->in2, regs[get_field(f, r2)]);
4322}
49f7ee80 4323#define SPEC_in2_r2_16s 0
c698d876
RH
4324
4325static void in2_r2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4326{
4327 o->in2 = tcg_temp_new_i64();
4328 tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r2)]);
4329}
49f7ee80 4330#define SPEC_in2_r2_16u 0
c698d876 4331
ad044d09
RH
4332static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
4333{
4334 o->in2 = load_reg(get_field(f, r3));
4335}
49f7ee80 4336#define SPEC_in2_r3 0
ad044d09
RH
4337
4338static void in2_r2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4339{
4340 o->in2 = tcg_temp_new_i64();
4341 tcg_gen_ext32s_i64(o->in2, regs[get_field(f, r2)]);
4342}
49f7ee80 4343#define SPEC_in2_r2_32s 0
ad044d09
RH
4344
4345static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4346{
4347 o->in2 = tcg_temp_new_i64();
4348 tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
4349}
49f7ee80 4350#define SPEC_in2_r2_32u 0
ad044d09 4351
d764a8d1
RH
4352static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o)
4353{
4354 o->in2 = load_freg32_i64(get_field(f, r2));
4355}
49f7ee80 4356#define SPEC_in2_e2 0
d764a8d1
RH
4357
4358static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
4359{
4360 o->in2 = fregs[get_field(f, r2)];
4361 o->g_in2 = true;
4362}
49f7ee80 4363#define SPEC_in2_f2_o 0
d764a8d1
RH
4364
4365static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
4366{
587626f8
RH
4367 int r2 = get_field(f, r2);
4368 o->in1 = fregs[r2];
49f7ee80 4369 o->in2 = fregs[r2 + 2];
d764a8d1
RH
4370 o->g_in1 = o->g_in2 = true;
4371}
49f7ee80 4372#define SPEC_in2_x2_o SPEC_r2_f128
d764a8d1 4373
374724f9
RH
4374static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
4375{
4376 o->in2 = get_address(s, 0, get_field(f, r2), 0);
4377}
49f7ee80 4378#define SPEC_in2_ra2 0
374724f9 4379
ad044d09
RH
4380static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
4381{
4382 int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
4383 o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
4384}
49f7ee80 4385#define SPEC_in2_a2 0
ad044d09 4386
a7e836d5
RH
4387static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
4388{
4389 o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
4390}
49f7ee80 4391#define SPEC_in2_ri2 0
a7e836d5 4392
cbe24bfa
RH
4393static void in2_sh32(DisasContext *s, DisasFields *f, DisasOps *o)
4394{
4395 help_l2_shift(s, f, o, 31);
4396}
49f7ee80 4397#define SPEC_in2_sh32 0
cbe24bfa
RH
4398
4399static void in2_sh64(DisasContext *s, DisasFields *f, DisasOps *o)
4400{
4401 help_l2_shift(s, f, o, 63);
4402}
49f7ee80 4403#define SPEC_in2_sh64 0
cbe24bfa 4404
afdc70be
RH
4405static void in2_m2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4406{
4407 in2_a2(s, f, o);
4408 tcg_gen_qemu_ld8u(o->in2, o->in2, get_mem_index(s));
4409}
49f7ee80 4410#define SPEC_in2_m2_8u 0
afdc70be 4411
d82287de
RH
4412static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4413{
4414 in2_a2(s, f, o);
4415 tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
4416}
49f7ee80 4417#define SPEC_in2_m2_16s 0
d82287de 4418
d54f5865
RH
4419static void in2_m2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4420{
4421 in2_a2(s, f, o);
4422 tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
4423}
49f7ee80 4424#define SPEC_in2_m2_16u 0
d54f5865 4425
ad044d09
RH
4426static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4427{
4428 in2_a2(s, f, o);
4429 tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
4430}
49f7ee80 4431#define SPEC_in2_m2_32s 0
ad044d09
RH
4432
4433static void in2_m2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4434{
4435 in2_a2(s, f, o);
4436 tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
4437}
49f7ee80 4438#define SPEC_in2_m2_32u 0
ad044d09
RH
4439
4440static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
4441{
4442 in2_a2(s, f, o);
4443 tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
4444}
49f7ee80 4445#define SPEC_in2_m2_64 0
ad044d09 4446
a7e836d5
RH
4447static void in2_mri2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4448{
4449 in2_ri2(s, f, o);
4450 tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
4451}
49f7ee80 4452#define SPEC_in2_mri2_16u 0
a7e836d5
RH
4453
4454static void in2_mri2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4455{
4456 in2_ri2(s, f, o);
4457 tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
4458}
49f7ee80 4459#define SPEC_in2_mri2_32s 0
a7e836d5
RH
4460
4461static void in2_mri2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4462{
4463 in2_ri2(s, f, o);
4464 tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
4465}
49f7ee80 4466#define SPEC_in2_mri2_32u 0
a7e836d5
RH
4467
4468static void in2_mri2_64(DisasContext *s, DisasFields *f, DisasOps *o)
4469{
4470 in2_ri2(s, f, o);
4471 tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
4472}
49f7ee80 4473#define SPEC_in2_mri2_64 0
a7e836d5 4474
ad044d09
RH
4475static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
4476{
4477 o->in2 = tcg_const_i64(get_field(f, i2));
4478}
49f7ee80 4479#define SPEC_in2_i2 0
ad044d09 4480
a7e836d5
RH
4481static void in2_i2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4482{
4483 o->in2 = tcg_const_i64((uint8_t)get_field(f, i2));
4484}
49f7ee80 4485#define SPEC_in2_i2_8u 0
a7e836d5
RH
4486
4487static void in2_i2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4488{
4489 o->in2 = tcg_const_i64((uint16_t)get_field(f, i2));
4490}
49f7ee80 4491#define SPEC_in2_i2_16u 0
a7e836d5 4492
ad044d09
RH
4493static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4494{
4495 o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
4496}
49f7ee80 4497#define SPEC_in2_i2_32u 0
ad044d09 4498
ade9dea4
RH
4499static void in2_i2_16u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
4500{
4501 uint64_t i2 = (uint16_t)get_field(f, i2);
4502 o->in2 = tcg_const_i64(i2 << s->insn->data);
4503}
49f7ee80 4504#define SPEC_in2_i2_16u_shl 0
ade9dea4
RH
4505
4506static void in2_i2_32u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
4507{
4508 uint64_t i2 = (uint32_t)get_field(f, i2);
4509 o->in2 = tcg_const_i64(i2 << s->insn->data);
4510}
49f7ee80 4511#define SPEC_in2_i2_32u_shl 0
ade9dea4 4512
ad044d09
RH
4513/* ====================================================================== */
4514
4515/* Find opc within the table of insns. This is formulated as a switch
4516 statement so that (1) we get compile-time notice of cut-paste errors
4517 for duplicated opcodes, and (2) the compiler generates the binary
4518 search tree, rather than us having to post-process the table. */
4519
4520#define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \
4521 D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0)
4522
4523#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) insn_ ## NM,
4524
4525enum DisasInsnEnum {
4526#include "insn-data.def"
4527};
4528
4529#undef D
49f7ee80
RH
4530#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
4531 .opc = OPC, \
4532 .fmt = FMT_##FT, \
4533 .fac = FAC_##FC, \
4534 .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \
4535 .name = #NM, \
4536 .help_in1 = in1_##I1, \
4537 .help_in2 = in2_##I2, \
4538 .help_prep = prep_##P, \
4539 .help_wout = wout_##W, \
4540 .help_cout = cout_##CC, \
4541 .help_op = op_##OP, \
4542 .data = D \
ad044d09
RH
4543 },
4544
4545/* Allow 0 to be used for NULL in the table below. */
4546#define in1_0 NULL
4547#define in2_0 NULL
4548#define prep_0 NULL
4549#define wout_0 NULL
4550#define cout_0 NULL
4551#define op_0 NULL
4552
49f7ee80
RH
4553#define SPEC_in1_0 0
4554#define SPEC_in2_0 0
4555#define SPEC_prep_0 0
4556#define SPEC_wout_0 0
4557
ad044d09
RH
4558static const DisasInsn insn_info[] = {
4559#include "insn-data.def"
4560};
4561
4562#undef D
4563#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
4564 case OPC: return &insn_info[insn_ ## NM];
4565
4566static const DisasInsn *lookup_opc(uint16_t opc)
4567{
4568 switch (opc) {
4569#include "insn-data.def"
4570 default:
4571 return NULL;
4572 }
4573}
4574
4575#undef D
4576#undef C
4577
4578/* Extract a field from the insn. The INSN should be left-aligned in
4579 the uint64_t so that we can more easily utilize the big-bit-endian
4580 definitions we extract from the Principals of Operation. */
4581
4582static void extract_field(DisasFields *o, const DisasField *f, uint64_t insn)
4583{
4584 uint32_t r, m;
4585
4586 if (f->size == 0) {
4587 return;
4588 }
4589
4590 /* Zero extract the field from the insn. */
4591 r = (insn << f->beg) >> (64 - f->size);
4592
4593 /* Sign-extend, or un-swap the field as necessary. */
4594 switch (f->type) {
4595 case 0: /* unsigned */
4596 break;
4597 case 1: /* signed */
4598 assert(f->size <= 32);
4599 m = 1u << (f->size - 1);
4600 r = (r ^ m) - m;
4601 break;
4602 case 2: /* dl+dh split, signed 20 bit. */
4603 r = ((int8_t)r << 12) | (r >> 8);
4604 break;
4605 default:
4606 abort();
4607 }
4608
4609 /* Validate that the "compressed" encoding we selected above is valid.
4610 I.e. we havn't make two different original fields overlap. */
4611 assert(((o->presentC >> f->indexC) & 1) == 0);
4612 o->presentC |= 1 << f->indexC;
4613 o->presentO |= 1 << f->indexO;
4614
4615 o->c[f->indexC] = r;
4616}
4617
4618/* Lookup the insn at the current PC, extracting the operands into O and
4619 returning the info struct for the insn. Returns NULL for invalid insn. */
4620
4621static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
4622 DisasFields *f)
4623{
4624 uint64_t insn, pc = s->pc;
d5a103cd 4625 int op, op2, ilen;
ad044d09
RH
4626 const DisasInsn *info;
4627
4628 insn = ld_code2(env, pc);
4629 op = (insn >> 8) & 0xff;
d5a103cd
RH
4630 ilen = get_ilen(op);
4631 s->next_pc = s->pc + ilen;
4632
4633 switch (ilen) {
4634 case 2:
ad044d09
RH
4635 insn = insn << 48;
4636 break;
d5a103cd 4637 case 4:
ad044d09
RH
4638 insn = ld_code4(env, pc) << 32;
4639 break;
d5a103cd 4640 case 6:
ad044d09
RH
4641 insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
4642 break;
4643 default:
4644 abort();
4645 }
4646
4647 /* We can't actually determine the insn format until we've looked up
4648 the full insn opcode. Which we can't do without locating the
4649 secondary opcode. Assume by default that OP2 is at bit 40; for
4650 those smaller insns that don't actually have a secondary opcode
4651 this will correctly result in OP2 = 0. */
4652 switch (op) {
4653 case 0x01: /* E */
4654 case 0x80: /* S */
4655 case 0x82: /* S */
4656 case 0x93: /* S */
4657 case 0xb2: /* S, RRF, RRE */
4658 case 0xb3: /* RRE, RRD, RRF */
4659 case 0xb9: /* RRE, RRF */
4660 case 0xe5: /* SSE, SIL */
4661 op2 = (insn << 8) >> 56;
4662 break;
4663 case 0xa5: /* RI */
4664 case 0xa7: /* RI */
4665 case 0xc0: /* RIL */
4666 case 0xc2: /* RIL */
4667 case 0xc4: /* RIL */
4668 case 0xc6: /* RIL */
4669 case 0xc8: /* SSF */
4670 case 0xcc: /* RIL */
4671 op2 = (insn << 12) >> 60;
4672 break;
4673 case 0xd0 ... 0xdf: /* SS */
4674 case 0xe1: /* SS */
4675 case 0xe2: /* SS */
4676 case 0xe8: /* SS */
4677 case 0xe9: /* SS */
4678 case 0xea: /* SS */
4679 case 0xee ... 0xf3: /* SS */
4680 case 0xf8 ... 0xfd: /* SS */
4681 op2 = 0;
4682 break;
4683 default:
4684 op2 = (insn << 40) >> 56;
4685 break;
4686 }
4687
4688 memset(f, 0, sizeof(*f));
4689 f->op = op;
4690 f->op2 = op2;
4691
4692 /* Lookup the instruction. */
4693 info = lookup_opc(op << 8 | op2);
4694
4695 /* If we found it, extract the operands. */
4696 if (info != NULL) {
4697 DisasFormat fmt = info->fmt;
4698 int i;
4699
4700 for (i = 0; i < NUM_C_FIELD; ++i) {
4701 extract_field(f, &format_info[fmt].op[i], insn);
4702 }
4703 }
4704 return info;
4705}
4706
4707static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
4708{
4709 const DisasInsn *insn;
4710 ExitStatus ret = NO_EXIT;
4711 DisasFields f;
4712 DisasOps o;
4713
4f3adfb2 4714 /* Search for the insn in the table. */
ad044d09 4715 insn = extract_insn(env, s, &f);
e023e832 4716
4f3adfb2 4717 /* Not found means unimplemented/illegal opcode. */
ad044d09 4718 if (insn == NULL) {
4f3adfb2
RH
4719 qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%02x%02x\n",
4720 f.op, f.op2);
4721 gen_illegal_opcode(s);
4722 return EXIT_NORETURN;
ad044d09
RH
4723 }
4724
49f7ee80
RH
4725 /* Check for insn specification exceptions. */
4726 if (insn->spec) {
4727 int spec = insn->spec, excp = 0, r;
4728
4729 if (spec & SPEC_r1_even) {
4730 r = get_field(&f, r1);
4731 if (r & 1) {
4732 excp = PGM_SPECIFICATION;
4733 }
4734 }
4735 if (spec & SPEC_r2_even) {
4736 r = get_field(&f, r2);
4737 if (r & 1) {
b7886de3
RH
4738 excp = PGM_SPECIFICATION;
4739 }
4740 }
4741 if (spec & SPEC_r3_even) {
4742 r = get_field(&f, r3);
4743 if (r & 1) {
49f7ee80
RH
4744 excp = PGM_SPECIFICATION;
4745 }
4746 }
4747 if (spec & SPEC_r1_f128) {
4748 r = get_field(&f, r1);
4749 if (r > 13) {
4750 excp = PGM_SPECIFICATION;
4751 }
4752 }
4753 if (spec & SPEC_r2_f128) {
4754 r = get_field(&f, r2);
4755 if (r > 13) {
4756 excp = PGM_SPECIFICATION;
4757 }
4758 }
4759 if (excp) {
4760 gen_program_exception(s, excp);
4761 return EXIT_NORETURN;
4762 }
4763 }
4764
ad044d09
RH
4765 /* Set up the strutures we use to communicate with the helpers. */
4766 s->insn = insn;
4767 s->fields = &f;
4768 o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
4769 TCGV_UNUSED_I64(o.out);
4770 TCGV_UNUSED_I64(o.out2);
4771 TCGV_UNUSED_I64(o.in1);
4772 TCGV_UNUSED_I64(o.in2);
4773 TCGV_UNUSED_I64(o.addr1);
4774
4775 /* Implement the instruction. */
4776 if (insn->help_in1) {
4777 insn->help_in1(s, &f, &o);
4778 }
4779 if (insn->help_in2) {
4780 insn->help_in2(s, &f, &o);
4781 }
4782 if (insn->help_prep) {
4783 insn->help_prep(s, &f, &o);
4784 }
4785 if (insn->help_op) {
4786 ret = insn->help_op(s, &o);
4787 }
4788 if (insn->help_wout) {
4789 insn->help_wout(s, &f, &o);
4790 }
4791 if (insn->help_cout) {
4792 insn->help_cout(s, &o);
4793 }
4794
4795 /* Free any temporaries created by the helpers. */
4796 if (!TCGV_IS_UNUSED_I64(o.out) && !o.g_out) {
4797 tcg_temp_free_i64(o.out);
4798 }
4799 if (!TCGV_IS_UNUSED_I64(o.out2) && !o.g_out2) {
4800 tcg_temp_free_i64(o.out2);
4801 }
4802 if (!TCGV_IS_UNUSED_I64(o.in1) && !o.g_in1) {
4803 tcg_temp_free_i64(o.in1);
4804 }
4805 if (!TCGV_IS_UNUSED_I64(o.in2) && !o.g_in2) {
4806 tcg_temp_free_i64(o.in2);
4807 }
4808 if (!TCGV_IS_UNUSED_I64(o.addr1)) {
4809 tcg_temp_free_i64(o.addr1);
4810 }
4811
4812 /* Advance to the next instruction. */
4813 s->pc = s->next_pc;
4814 return ret;
e023e832
AG
4815}
4816
d9916c23 4817static inline void gen_intermediate_code_internal(S390CPU *cpu,
e023e832 4818 TranslationBlock *tb,
d9916c23 4819 bool search_pc)
e023e832 4820{
ed2803da 4821 CPUState *cs = CPU(cpu);
d9916c23 4822 CPUS390XState *env = &cpu->env;
e023e832
AG
4823 DisasContext dc;
4824 target_ulong pc_start;
4825 uint64_t next_page_start;
4826 uint16_t *gen_opc_end;
4827 int j, lj = -1;
4828 int num_insns, max_insns;
4829 CPUBreakpoint *bp;
ad044d09 4830 ExitStatus status;
d5a103cd 4831 bool do_debug;
e023e832
AG
4832
4833 pc_start = tb->pc;
4834
4835 /* 31-bit mode */
4836 if (!(tb->flags & FLAG_MASK_64)) {
4837 pc_start &= 0x7fffffff;
4838 }
4839
e023e832 4840 dc.tb = tb;
ad044d09 4841 dc.pc = pc_start;
e023e832 4842 dc.cc_op = CC_OP_DYNAMIC;
ed2803da 4843 do_debug = dc.singlestep_enabled = cs->singlestep_enabled;
e023e832 4844
92414b31 4845 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
e023e832
AG
4846
4847 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
4848
4849 num_insns = 0;
4850 max_insns = tb->cflags & CF_COUNT_MASK;
4851 if (max_insns == 0) {
4852 max_insns = CF_COUNT_MASK;
4853 }
4854
cd42d5b2 4855 gen_tb_start(tb);
e023e832
AG
4856
4857 do {
e023e832 4858 if (search_pc) {
92414b31 4859 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
e023e832
AG
4860 if (lj < j) {
4861 lj++;
4862 while (lj < j) {
ab1103de 4863 tcg_ctx.gen_opc_instr_start[lj++] = 0;
e023e832
AG
4864 }
4865 }
25983cad 4866 tcg_ctx.gen_opc_pc[lj] = dc.pc;
e023e832 4867 gen_opc_cc_op[lj] = dc.cc_op;
ab1103de 4868 tcg_ctx.gen_opc_instr_start[lj] = 1;
c9c99c22 4869 tcg_ctx.gen_opc_icount[lj] = num_insns;
e023e832 4870 }
ad044d09 4871 if (++num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
e023e832
AG
4872 gen_io_start();
4873 }
7193b5f6
RH
4874
4875 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
4876 tcg_gen_debug_insn_start(dc.pc);
4877 }
4878
d5a103cd 4879 status = NO_EXIT;
f0c3c505
AF
4880 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
4881 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
d5a103cd
RH
4882 if (bp->pc == dc.pc) {
4883 status = EXIT_PC_STALE;
4884 do_debug = true;
4885 break;
4886 }
4887 }
4888 }
4889 if (status == NO_EXIT) {
4890 status = translate_one(env, &dc);
4891 }
ad044d09
RH
4892
4893 /* If we reach a page boundary, are single stepping,
4894 or exhaust instruction count, stop generation. */
4895 if (status == NO_EXIT
4896 && (dc.pc >= next_page_start
4897 || tcg_ctx.gen_opc_ptr >= gen_opc_end
4898 || num_insns >= max_insns
4899 || singlestep
ed2803da 4900 || cs->singlestep_enabled)) {
ad044d09 4901 status = EXIT_PC_STALE;
e023e832 4902 }
ad044d09 4903 } while (status == NO_EXIT);
e023e832
AG
4904
4905 if (tb->cflags & CF_LAST_IO) {
4906 gen_io_end();
4907 }
ad044d09
RH
4908
4909 switch (status) {
4910 case EXIT_GOTO_TB:
4911 case EXIT_NORETURN:
4912 break;
4913 case EXIT_PC_STALE:
4914 update_psw_addr(&dc);
4915 /* FALLTHRU */
4916 case EXIT_PC_UPDATED:
7a6c7067
RH
4917 /* Next TB starts off with CC_OP_DYNAMIC, so make sure the
4918 cc op type is in env */
4919 update_cc_op(&dc);
4920 /* Exit the TB, either by raising a debug exception or by return. */
d5a103cd
RH
4921 if (do_debug) {
4922 gen_exception(EXCP_DEBUG);
ad044d09 4923 } else {
ad044d09
RH
4924 tcg_gen_exit_tb(0);
4925 }
4926 break;
4927 default:
4928 abort();
e023e832 4929 }
ad044d09 4930
806f352d 4931 gen_tb_end(tb, num_insns);
efd7f486 4932 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
e023e832 4933 if (search_pc) {
92414b31 4934 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
e023e832
AG
4935 lj++;
4936 while (lj <= j) {
ab1103de 4937 tcg_ctx.gen_opc_instr_start[lj++] = 0;
e023e832
AG
4938 }
4939 } else {
4940 tb->size = dc.pc - pc_start;
4941 tb->icount = num_insns;
4942 }
ad044d09 4943
e023e832 4944#if defined(S390X_DEBUG_DISAS)
e023e832
AG
4945 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
4946 qemu_log("IN: %s\n", lookup_symbol(pc_start));
f4359b9f 4947 log_target_disas(env, pc_start, dc.pc - pc_start, 1);
e023e832
AG
4948 qemu_log("\n");
4949 }
4950#endif
4951}
4952
a4e3ad19 4953void gen_intermediate_code (CPUS390XState *env, struct TranslationBlock *tb)
e023e832 4954{
d9916c23 4955 gen_intermediate_code_internal(s390_env_get_cpu(env), tb, false);
e023e832
AG
4956}
4957
a4e3ad19 4958void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb)
e023e832 4959{
d9916c23 4960 gen_intermediate_code_internal(s390_env_get_cpu(env), tb, true);
e023e832
AG
4961}
4962
a4e3ad19 4963void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos)
e023e832
AG
4964{
4965 int cc_op;
25983cad 4966 env->psw.addr = tcg_ctx.gen_opc_pc[pc_pos];
e023e832
AG
4967 cc_op = gen_opc_cc_op[pc_pos];
4968 if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) {
4969 env->cc_op = cc_op;
4970 }
10ec5117 4971}