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