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