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