]> git.proxmox.com Git - mirror_qemu.git/blame - target-s390x/translate.c
target-s390x: implement TRANSLATE AND TEST instruction
[mirror_qemu.git] / target-s390x / translate.c
CommitLineData
10ec5117
AG
1/*
2 * S/390 translation
3 *
4 * Copyright (c) 2009 Ulrich Hecht
e023e832 5 * Copyright (c) 2010 Alexander Graf
10ec5117
AG
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
70539e18 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
10ec5117 19 */
e023e832 20
e023e832
AG
21/* #define DEBUG_INLINE_BRANCHES */
22#define S390X_DEBUG_DISAS
23/* #define S390X_DEBUG_DISAS_VERBOSE */
24
25#ifdef S390X_DEBUG_DISAS_VERBOSE
26# define LOG_DISAS(...) qemu_log(__VA_ARGS__)
27#else
28# define LOG_DISAS(...) do { } while (0)
29#endif
10ec5117
AG
30
31#include "cpu.h"
76cad711 32#include "disas/disas.h"
10ec5117 33#include "tcg-op.h"
1de7afc9 34#include "qemu/log.h"
58a9e35b 35#include "qemu/host-utils.h"
f08b6170 36#include "exec/cpu_ldst.h"
10ec5117 37
e023e832
AG
38/* global register indexes */
39static TCGv_ptr cpu_env;
40
022c62cb 41#include "exec/gen-icount.h"
2ef6175a
RH
42#include "exec/helper-proto.h"
43#include "exec/helper-gen.h"
e023e832 44
a7e30d84
LV
45#include "trace-tcg.h"
46
ad044d09
RH
47
48/* Information that (most) every instruction needs to manipulate. */
e023e832 49typedef struct DisasContext DisasContext;
ad044d09
RH
50typedef struct DisasInsn DisasInsn;
51typedef struct DisasFields DisasFields;
52
e023e832 53struct DisasContext {
e023e832 54 struct TranslationBlock *tb;
ad044d09
RH
55 const DisasInsn *insn;
56 DisasFields *fields;
57 uint64_t pc, next_pc;
58 enum cc_op cc_op;
59 bool singlestep_enabled;
e023e832
AG
60};
61
3fde06f5
RH
62/* Information carried about a condition to be evaluated. */
63typedef struct {
64 TCGCond cond:8;
65 bool is_64;
66 bool g1;
67 bool g2;
68 union {
69 struct { TCGv_i64 a, b; } s64;
70 struct { TCGv_i32 a, b; } s32;
71 } u;
72} DisasCompare;
73
e023e832
AG
74#define DISAS_EXCP 4
75
e023e832
AG
76#ifdef DEBUG_INLINE_BRANCHES
77static uint64_t inline_branch_hit[CC_OP_MAX];
78static uint64_t inline_branch_miss[CC_OP_MAX];
79#endif
80
4f3adfb2 81static uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
e023e832
AG
82{
83 if (!(s->tb->flags & FLAG_MASK_64)) {
84 if (s->tb->flags & FLAG_MASK_32) {
85 return pc | 0x80000000;
86 }
87 }
88 return pc;
89}
90
878096ee
AF
91void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
92 int flags)
10ec5117 93{
878096ee
AF
94 S390CPU *cpu = S390_CPU(cs);
95 CPUS390XState *env = &cpu->env;
10ec5117 96 int i;
e023e832 97
d885bdd4
RH
98 if (env->cc_op > 3) {
99 cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %15s\n",
100 env->psw.mask, env->psw.addr, cc_name(env->cc_op));
101 } else {
102 cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %02x\n",
103 env->psw.mask, env->psw.addr, env->cc_op);
104 }
105
10ec5117 106 for (i = 0; i < 16; i++) {
e023e832 107 cpu_fprintf(f, "R%02d=%016" PRIx64, i, env->regs[i]);
10ec5117
AG
108 if ((i % 4) == 3) {
109 cpu_fprintf(f, "\n");
110 } else {
111 cpu_fprintf(f, " ");
112 }
113 }
e023e832 114
10ec5117 115 for (i = 0; i < 16; i++) {
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
ed0bcece
AJ
2119static ExitStatus op_fieb(DisasContext *s, DisasOps *o)
2120{
2121 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
2122 gen_helper_fieb(o->out, cpu_env, o->in2, m3);
2123 tcg_temp_free_i32(m3);
2124 return NO_EXIT;
2125}
2126
2127static ExitStatus op_fidb(DisasContext *s, DisasOps *o)
2128{
2129 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
2130 gen_helper_fidb(o->out, cpu_env, o->in2, m3);
2131 tcg_temp_free_i32(m3);
2132 return NO_EXIT;
2133}
2134
2135static ExitStatus op_fixb(DisasContext *s, DisasOps *o)
2136{
2137 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
2138 gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m3);
2139 return_low128(o->out2);
2140 tcg_temp_free_i32(m3);
2141 return NO_EXIT;
2142}
2143
102bf2c6
RH
2144static ExitStatus op_flogr(DisasContext *s, DisasOps *o)
2145{
2146 /* We'll use the original input for cc computation, since we get to
2147 compare that against 0, which ought to be better than comparing
2148 the real output against 64. It also lets cc_dst be a convenient
2149 temporary during our computation. */
2150 gen_op_update1_cc_i64(s, CC_OP_FLOGR, o->in2);
2151
2152 /* R1 = IN ? CLZ(IN) : 64. */
2153 gen_helper_clz(o->out, o->in2);
2154
2155 /* R1+1 = IN & ~(found bit). Note that we may attempt to shift this
2156 value by 64, which is undefined. But since the shift is 64 iff the
2157 input is zero, we still get the correct result after and'ing. */
2158 tcg_gen_movi_i64(o->out2, 0x8000000000000000ull);
2159 tcg_gen_shr_i64(o->out2, o->out2, o->out);
2160 tcg_gen_andc_i64(o->out2, cc_dst, o->out2);
2161 return NO_EXIT;
2162}
2163
58a9e35b
RH
2164static ExitStatus op_icm(DisasContext *s, DisasOps *o)
2165{
2166 int m3 = get_field(s->fields, m3);
2167 int pos, len, base = s->insn->data;
2168 TCGv_i64 tmp = tcg_temp_new_i64();
2169 uint64_t ccm;
2170
2171 switch (m3) {
2172 case 0xf:
2173 /* Effectively a 32-bit load. */
2174 tcg_gen_qemu_ld32u(tmp, o->in2, get_mem_index(s));
2175 len = 32;
2176 goto one_insert;
2177
2178 case 0xc:
2179 case 0x6:
2180 case 0x3:
2181 /* Effectively a 16-bit load. */
2182 tcg_gen_qemu_ld16u(tmp, o->in2, get_mem_index(s));
2183 len = 16;
2184 goto one_insert;
2185
2186 case 0x8:
2187 case 0x4:
2188 case 0x2:
2189 case 0x1:
2190 /* Effectively an 8-bit load. */
2191 tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
2192 len = 8;
2193 goto one_insert;
2194
2195 one_insert:
2196 pos = base + ctz32(m3) * 8;
2197 tcg_gen_deposit_i64(o->out, o->out, tmp, pos, len);
2198 ccm = ((1ull << len) - 1) << pos;
2199 break;
2200
2201 default:
2202 /* This is going to be a sequence of loads and inserts. */
2203 pos = base + 32 - 8;
2204 ccm = 0;
2205 while (m3) {
2206 if (m3 & 0x8) {
2207 tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
2208 tcg_gen_addi_i64(o->in2, o->in2, 1);
2209 tcg_gen_deposit_i64(o->out, o->out, tmp, pos, 8);
2210 ccm |= 0xff << pos;
2211 }
2212 m3 = (m3 << 1) & 0xf;
2213 pos -= 8;
2214 }
2215 break;
2216 }
2217
2218 tcg_gen_movi_i64(tmp, ccm);
2219 gen_op_update2_cc_i64(s, CC_OP_ICM, tmp, o->out);
2220 tcg_temp_free_i64(tmp);
2221 return NO_EXIT;
2222}
2223
facfc864
RH
2224static ExitStatus op_insi(DisasContext *s, DisasOps *o)
2225{
2226 int shift = s->insn->data & 0xff;
2227 int size = s->insn->data >> 8;
2228 tcg_gen_deposit_i64(o->out, o->in1, o->in2, shift, size);
2229 return NO_EXIT;
2230}
2231
6e2704e7
RH
2232static ExitStatus op_ipm(DisasContext *s, DisasOps *o)
2233{
2234 TCGv_i64 t1;
2235
2236 gen_op_calc_cc(s);
2237 tcg_gen_andi_i64(o->out, o->out, ~0xff000000ull);
2238
2239 t1 = tcg_temp_new_i64();
2240 tcg_gen_shli_i64(t1, psw_mask, 20);
2241 tcg_gen_shri_i64(t1, t1, 36);
2242 tcg_gen_or_i64(o->out, o->out, t1);
2243
2244 tcg_gen_extu_i32_i64(t1, cc_op);
2245 tcg_gen_shli_i64(t1, t1, 28);
2246 tcg_gen_or_i64(o->out, o->out, t1);
2247 tcg_temp_free_i64(t1);
2248 return NO_EXIT;
2249}
2250
cfef53e3
RH
2251#ifndef CONFIG_USER_ONLY
2252static ExitStatus op_ipte(DisasContext *s, DisasOps *o)
2253{
2254 check_privileged(s);
2255 gen_helper_ipte(cpu_env, o->in1, o->in2);
2256 return NO_EXIT;
2257}
8026417c
RH
2258
2259static ExitStatus op_iske(DisasContext *s, DisasOps *o)
2260{
2261 check_privileged(s);
2262 gen_helper_iske(o->out, cpu_env, o->in2);
2263 return NO_EXIT;
2264}
cfef53e3
RH
2265#endif
2266
587626f8
RH
2267static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
2268{
2269 gen_helper_ldeb(o->out, cpu_env, o->in2);
2270 return NO_EXIT;
2271}
2272
2273static ExitStatus op_ledb(DisasContext *s, DisasOps *o)
2274{
2275 gen_helper_ledb(o->out, cpu_env, o->in2);
2276 return NO_EXIT;
2277}
2278
2279static ExitStatus op_ldxb(DisasContext *s, DisasOps *o)
2280{
2281 gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
2282 return NO_EXIT;
2283}
2284
2285static ExitStatus op_lexb(DisasContext *s, DisasOps *o)
2286{
2287 gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
2288 return NO_EXIT;
2289}
2290
2291static ExitStatus op_lxdb(DisasContext *s, DisasOps *o)
2292{
2293 gen_helper_lxdb(o->out, cpu_env, o->in2);
2294 return_low128(o->out2);
2295 return NO_EXIT;
2296}
2297
2298static ExitStatus op_lxeb(DisasContext *s, DisasOps *o)
2299{
2300 gen_helper_lxeb(o->out, cpu_env, o->in2);
2301 return_low128(o->out2);
2302 return NO_EXIT;
2303}
2304
7691c23b
RH
2305static ExitStatus op_llgt(DisasContext *s, DisasOps *o)
2306{
2307 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
2308 return NO_EXIT;
2309}
2310
c698d876
RH
2311static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
2312{
2313 tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
2314 return NO_EXIT;
2315}
2316
2317static ExitStatus op_ld8u(DisasContext *s, DisasOps *o)
2318{
2319 tcg_gen_qemu_ld8u(o->out, o->in2, get_mem_index(s));
2320 return NO_EXIT;
2321}
2322
2323static ExitStatus op_ld16s(DisasContext *s, DisasOps *o)
2324{
2325 tcg_gen_qemu_ld16s(o->out, o->in2, get_mem_index(s));
2326 return NO_EXIT;
2327}
2328
2329static ExitStatus op_ld16u(DisasContext *s, DisasOps *o)
2330{
2331 tcg_gen_qemu_ld16u(o->out, o->in2, get_mem_index(s));
2332 return NO_EXIT;
2333}
2334
22c37a08
RH
2335static ExitStatus op_ld32s(DisasContext *s, DisasOps *o)
2336{
2337 tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s));
2338 return NO_EXIT;
2339}
2340
2341static ExitStatus op_ld32u(DisasContext *s, DisasOps *o)
2342{
2343 tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s));
2344 return NO_EXIT;
2345}
2346
2347static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
2348{
2349 tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s));
2350 return NO_EXIT;
2351}
2352
632086da
RH
2353static ExitStatus op_loc(DisasContext *s, DisasOps *o)
2354{
2355 DisasCompare c;
2356
2357 disas_jcc(s, &c, get_field(s->fields, m3));
2358
2359 if (c.is_64) {
2360 tcg_gen_movcond_i64(c.cond, o->out, c.u.s64.a, c.u.s64.b,
2361 o->in2, o->in1);
2362 free_compare(&c);
2363 } else {
2364 TCGv_i32 t32 = tcg_temp_new_i32();
2365 TCGv_i64 t, z;
2366
2367 tcg_gen_setcond_i32(c.cond, t32, c.u.s32.a, c.u.s32.b);
2368 free_compare(&c);
2369
2370 t = tcg_temp_new_i64();
2371 tcg_gen_extu_i32_i64(t, t32);
2372 tcg_temp_free_i32(t32);
2373
2374 z = tcg_const_i64(0);
2375 tcg_gen_movcond_i64(TCG_COND_NE, o->out, t, z, o->in2, o->in1);
2376 tcg_temp_free_i64(t);
2377 tcg_temp_free_i64(z);
2378 }
2379
2380 return NO_EXIT;
2381}
2382
8b5ff571 2383#ifndef CONFIG_USER_ONLY
504488b8
RH
2384static ExitStatus op_lctl(DisasContext *s, DisasOps *o)
2385{
2386 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2387 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2388 check_privileged(s);
2389 potential_page_fault(s);
2390 gen_helper_lctl(cpu_env, r1, o->in2, r3);
2391 tcg_temp_free_i32(r1);
2392 tcg_temp_free_i32(r3);
2393 return NO_EXIT;
2394}
2395
3e398cf9
RH
2396static ExitStatus op_lctlg(DisasContext *s, DisasOps *o)
2397{
2398 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2399 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2400 check_privileged(s);
2401 potential_page_fault(s);
2402 gen_helper_lctlg(cpu_env, r1, o->in2, r3);
2403 tcg_temp_free_i32(r1);
2404 tcg_temp_free_i32(r3);
2405 return NO_EXIT;
2406}
d8fe4a9c
RH
2407static ExitStatus op_lra(DisasContext *s, DisasOps *o)
2408{
2409 check_privileged(s);
2410 potential_page_fault(s);
2411 gen_helper_lra(o->out, cpu_env, o->in2);
2412 set_cc_static(s);
2413 return NO_EXIT;
2414}
2415
8b5ff571
RH
2416static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
2417{
2418 TCGv_i64 t1, t2;
2419
2420 check_privileged(s);
2421
2422 t1 = tcg_temp_new_i64();
2423 t2 = tcg_temp_new_i64();
2424 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2425 tcg_gen_addi_i64(o->in2, o->in2, 4);
2426 tcg_gen_qemu_ld32u(t2, o->in2, get_mem_index(s));
2427 /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */
2428 tcg_gen_shli_i64(t1, t1, 32);
2429 gen_helper_load_psw(cpu_env, t1, t2);
2430 tcg_temp_free_i64(t1);
2431 tcg_temp_free_i64(t2);
2432 return EXIT_NORETURN;
2433}
7ab938d7
RH
2434
2435static ExitStatus op_lpswe(DisasContext *s, DisasOps *o)
2436{
2437 TCGv_i64 t1, t2;
2438
2439 check_privileged(s);
2440
2441 t1 = tcg_temp_new_i64();
2442 t2 = tcg_temp_new_i64();
2443 tcg_gen_qemu_ld64(t1, o->in2, get_mem_index(s));
2444 tcg_gen_addi_i64(o->in2, o->in2, 8);
2445 tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s));
2446 gen_helper_load_psw(cpu_env, t1, t2);
2447 tcg_temp_free_i64(t1);
2448 tcg_temp_free_i64(t2);
2449 return EXIT_NORETURN;
2450}
8b5ff571
RH
2451#endif
2452
7df3e93a
RH
2453static ExitStatus op_lam(DisasContext *s, DisasOps *o)
2454{
2455 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2456 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2457 potential_page_fault(s);
2458 gen_helper_lam(cpu_env, r1, o->in2, r3);
2459 tcg_temp_free_i32(r1);
2460 tcg_temp_free_i32(r3);
2461 return NO_EXIT;
2462}
2463
77f8d6c3
RH
2464static ExitStatus op_lm32(DisasContext *s, DisasOps *o)
2465{
2466 int r1 = get_field(s->fields, r1);
2467 int r3 = get_field(s->fields, r3);
aa752a4a 2468 TCGv_i64 t1, t2;
77f8d6c3 2469
aa752a4a
AJ
2470 /* Only one register to read. */
2471 t1 = tcg_temp_new_i64();
2472 if (unlikely(r1 == r3)) {
2473 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2474 store_reg32_i64(r1, t1);
2475 tcg_temp_free(t1);
2476 return NO_EXIT;
2477 }
2478
2479 /* First load the values of the first and last registers to trigger
2480 possible page faults. */
2481 t2 = tcg_temp_new_i64();
2482 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2483 tcg_gen_addi_i64(t2, o->in2, 4 * ((r3 - r1) & 15));
2484 tcg_gen_qemu_ld32u(t2, t2, get_mem_index(s));
2485 store_reg32_i64(r1, t1);
2486 store_reg32_i64(r3, t2);
2487
2488 /* Only two registers to read. */
2489 if (((r1 + 1) & 15) == r3) {
2490 tcg_temp_free(t2);
2491 tcg_temp_free(t1);
2492 return NO_EXIT;
2493 }
2494
2495 /* Then load the remaining registers. Page fault can't occur. */
2496 r3 = (r3 - 1) & 15;
2497 tcg_gen_movi_i64(t2, 4);
2498 while (r1 != r3) {
77f8d6c3 2499 r1 = (r1 + 1) & 15;
aa752a4a
AJ
2500 tcg_gen_add_i64(o->in2, o->in2, t2);
2501 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2502 store_reg32_i64(r1, t1);
77f8d6c3 2503 }
aa752a4a
AJ
2504 tcg_temp_free(t2);
2505 tcg_temp_free(t1);
77f8d6c3 2506
77f8d6c3
RH
2507 return NO_EXIT;
2508}
2509
2510static ExitStatus op_lmh(DisasContext *s, DisasOps *o)
2511{
2512 int r1 = get_field(s->fields, r1);
2513 int r3 = get_field(s->fields, r3);
aa752a4a 2514 TCGv_i64 t1, t2;
77f8d6c3 2515
aa752a4a
AJ
2516 /* Only one register to read. */
2517 t1 = tcg_temp_new_i64();
2518 if (unlikely(r1 == r3)) {
2519 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2520 store_reg32h_i64(r1, t1);
2521 tcg_temp_free(t1);
2522 return NO_EXIT;
2523 }
2524
2525 /* First load the values of the first and last registers to trigger
2526 possible page faults. */
2527 t2 = tcg_temp_new_i64();
2528 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2529 tcg_gen_addi_i64(t2, o->in2, 4 * ((r3 - r1) & 15));
2530 tcg_gen_qemu_ld32u(t2, t2, get_mem_index(s));
2531 store_reg32h_i64(r1, t1);
2532 store_reg32h_i64(r3, t2);
2533
2534 /* Only two registers to read. */
2535 if (((r1 + 1) & 15) == r3) {
2536 tcg_temp_free(t2);
2537 tcg_temp_free(t1);
2538 return NO_EXIT;
2539 }
2540
2541 /* Then load the remaining registers. Page fault can't occur. */
2542 r3 = (r3 - 1) & 15;
2543 tcg_gen_movi_i64(t2, 4);
2544 while (r1 != r3) {
77f8d6c3 2545 r1 = (r1 + 1) & 15;
aa752a4a
AJ
2546 tcg_gen_add_i64(o->in2, o->in2, t2);
2547 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2548 store_reg32h_i64(r1, t1);
77f8d6c3 2549 }
aa752a4a
AJ
2550 tcg_temp_free(t2);
2551 tcg_temp_free(t1);
77f8d6c3 2552
77f8d6c3
RH
2553 return NO_EXIT;
2554}
2555
2556static ExitStatus op_lm64(DisasContext *s, DisasOps *o)
2557{
2558 int r1 = get_field(s->fields, r1);
2559 int r3 = get_field(s->fields, r3);
aa752a4a 2560 TCGv_i64 t1, t2;
77f8d6c3 2561
aa752a4a
AJ
2562 /* Only one register to read. */
2563 if (unlikely(r1 == r3)) {
77f8d6c3 2564 tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
aa752a4a
AJ
2565 return NO_EXIT;
2566 }
2567
2568 /* First load the values of the first and last registers to trigger
2569 possible page faults. */
2570 t1 = tcg_temp_new_i64();
2571 t2 = tcg_temp_new_i64();
2572 tcg_gen_qemu_ld64(t1, o->in2, get_mem_index(s));
2573 tcg_gen_addi_i64(t2, o->in2, 8 * ((r3 - r1) & 15));
2574 tcg_gen_qemu_ld64(regs[r3], t2, get_mem_index(s));
2575 tcg_gen_mov_i64(regs[r1], t1);
2576 tcg_temp_free(t2);
2577
2578 /* Only two registers to read. */
2579 if (((r1 + 1) & 15) == r3) {
2580 tcg_temp_free(t1);
2581 return NO_EXIT;
2582 }
2583
2584 /* Then load the remaining registers. Page fault can't occur. */
2585 r3 = (r3 - 1) & 15;
2586 tcg_gen_movi_i64(t1, 8);
2587 while (r1 != r3) {
77f8d6c3 2588 r1 = (r1 + 1) & 15;
aa752a4a
AJ
2589 tcg_gen_add_i64(o->in2, o->in2, t1);
2590 tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
77f8d6c3 2591 }
aa752a4a 2592 tcg_temp_free(t1);
77f8d6c3 2593
77f8d6c3
RH
2594 return NO_EXIT;
2595}
2596
9c3fd85b
RH
2597#ifndef CONFIG_USER_ONLY
2598static ExitStatus op_lura(DisasContext *s, DisasOps *o)
2599{
2600 check_privileged(s);
2601 potential_page_fault(s);
2602 gen_helper_lura(o->out, cpu_env, o->in2);
2603 return NO_EXIT;
2604}
2605
2606static ExitStatus op_lurag(DisasContext *s, DisasOps *o)
2607{
2608 check_privileged(s);
2609 potential_page_fault(s);
2610 gen_helper_lurag(o->out, cpu_env, o->in2);
2611 return NO_EXIT;
2612}
2613#endif
2614
22c37a08
RH
2615static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
2616{
2617 o->out = o->in2;
2618 o->g_out = o->g_in2;
2619 TCGV_UNUSED_I64(o->in2);
2620 o->g_in2 = false;
2621 return NO_EXIT;
2622}
2623
a1c7610a
AJ
2624static ExitStatus op_mov2e(DisasContext *s, DisasOps *o)
2625{
2626 int b2 = get_field(s->fields, b2);
2627 TCGv ar1 = tcg_temp_new_i64();
2628
2629 o->out = o->in2;
2630 o->g_out = o->g_in2;
2631 TCGV_UNUSED_I64(o->in2);
2632 o->g_in2 = false;
2633
2634 switch (s->tb->flags & FLAG_MASK_ASC) {
2635 case PSW_ASC_PRIMARY >> 32:
2636 tcg_gen_movi_i64(ar1, 0);
2637 break;
2638 case PSW_ASC_ACCREG >> 32:
2639 tcg_gen_movi_i64(ar1, 1);
2640 break;
2641 case PSW_ASC_SECONDARY >> 32:
2642 if (b2) {
2643 tcg_gen_ld32u_i64(ar1, cpu_env, offsetof(CPUS390XState, aregs[b2]));
2644 } else {
2645 tcg_gen_movi_i64(ar1, 0);
2646 }
2647 break;
2648 case PSW_ASC_HOME >> 32:
2649 tcg_gen_movi_i64(ar1, 2);
2650 break;
2651 }
2652
2653 tcg_gen_st32_i64(ar1, cpu_env, offsetof(CPUS390XState, aregs[1]));
2654 tcg_temp_free_i64(ar1);
2655
2656 return NO_EXIT;
2657}
2658
d764a8d1
RH
2659static ExitStatus op_movx(DisasContext *s, DisasOps *o)
2660{
2661 o->out = o->in1;
2662 o->out2 = o->in2;
2663 o->g_out = o->g_in1;
2664 o->g_out2 = o->g_in2;
2665 TCGV_UNUSED_I64(o->in1);
2666 TCGV_UNUSED_I64(o->in2);
2667 o->g_in1 = o->g_in2 = false;
2668 return NO_EXIT;
2669}
2670
af9e5a04
RH
2671static ExitStatus op_mvc(DisasContext *s, DisasOps *o)
2672{
2673 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
2674 potential_page_fault(s);
2675 gen_helper_mvc(cpu_env, l, o->addr1, o->in2);
2676 tcg_temp_free_i32(l);
2677 return NO_EXIT;
2678}
2679
e1eaada9
RH
2680static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
2681{
2682 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2683 TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
2684 potential_page_fault(s);
2685 gen_helper_mvcl(cc_op, cpu_env, r1, r2);
2686 tcg_temp_free_i32(r1);
2687 tcg_temp_free_i32(r2);
2688 set_cc_static(s);
2689 return NO_EXIT;
2690}
2691
eb66e6a9
RH
2692static ExitStatus op_mvcle(DisasContext *s, DisasOps *o)
2693{
2694 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2695 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2696 potential_page_fault(s);
2697 gen_helper_mvcle(cc_op, cpu_env, r1, o->in2, r3);
2698 tcg_temp_free_i32(r1);
2699 tcg_temp_free_i32(r3);
2700 set_cc_static(s);
2701 return NO_EXIT;
2702}
2703
97c3ab61
RH
2704#ifndef CONFIG_USER_ONLY
2705static ExitStatus op_mvcp(DisasContext *s, DisasOps *o)
2706{
2707 int r1 = get_field(s->fields, l1);
2708 check_privileged(s);
2709 potential_page_fault(s);
2710 gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
2711 set_cc_static(s);
2712 return NO_EXIT;
2713}
2714
2715static ExitStatus op_mvcs(DisasContext *s, DisasOps *o)
2716{
2717 int r1 = get_field(s->fields, l1);
2718 check_privileged(s);
2719 potential_page_fault(s);
2720 gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
2721 set_cc_static(s);
2722 return NO_EXIT;
2723}
2724#endif
2725
ee6c38d5
RH
2726static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
2727{
2728 potential_page_fault(s);
2729 gen_helper_mvpg(cpu_env, regs[0], o->in1, o->in2);
2730 set_cc_static(s);
2731 return NO_EXIT;
2732}
2733
aa31bf60
RH
2734static ExitStatus op_mvst(DisasContext *s, DisasOps *o)
2735{
2736 potential_page_fault(s);
2737 gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2);
2738 set_cc_static(s);
2739 return_low128(o->in2);
2740 return NO_EXIT;
2741}
2742
d1c04a2b
RH
2743static ExitStatus op_mul(DisasContext *s, DisasOps *o)
2744{
2745 tcg_gen_mul_i64(o->out, o->in1, o->in2);
2746 return NO_EXIT;
2747}
2748
1ac5889f
RH
2749static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
2750{
dc46d1c6 2751 tcg_gen_mulu2_i64(o->out2, o->out, o->in1, o->in2);
1ac5889f
RH
2752 return NO_EXIT;
2753}
2754
83b00736
RH
2755static ExitStatus op_meeb(DisasContext *s, DisasOps *o)
2756{
2757 gen_helper_meeb(o->out, cpu_env, o->in1, o->in2);
2758 return NO_EXIT;
2759}
2760
2761static ExitStatus op_mdeb(DisasContext *s, DisasOps *o)
2762{
2763 gen_helper_mdeb(o->out, cpu_env, o->in1, o->in2);
2764 return NO_EXIT;
2765}
2766
2767static ExitStatus op_mdb(DisasContext *s, DisasOps *o)
2768{
2769 gen_helper_mdb(o->out, cpu_env, o->in1, o->in2);
2770 return NO_EXIT;
2771}
2772
2773static ExitStatus op_mxb(DisasContext *s, DisasOps *o)
2774{
2775 gen_helper_mxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
2776 return_low128(o->out2);
2777 return NO_EXIT;
2778}
2779
2780static ExitStatus op_mxdb(DisasContext *s, DisasOps *o)
2781{
2782 gen_helper_mxdb(o->out, cpu_env, o->out, o->out2, o->in2);
2783 return_low128(o->out2);
2784 return NO_EXIT;
2785}
2786
722bfec3
RH
2787static ExitStatus op_maeb(DisasContext *s, DisasOps *o)
2788{
2789 TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
2790 gen_helper_maeb(o->out, cpu_env, o->in1, o->in2, r3);
2791 tcg_temp_free_i64(r3);
2792 return NO_EXIT;
2793}
2794
2795static ExitStatus op_madb(DisasContext *s, DisasOps *o)
2796{
2797 int r3 = get_field(s->fields, r3);
2798 gen_helper_madb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
2799 return NO_EXIT;
2800}
2801
2802static ExitStatus op_mseb(DisasContext *s, DisasOps *o)
2803{
2804 TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
2805 gen_helper_mseb(o->out, cpu_env, o->in1, o->in2, r3);
2806 tcg_temp_free_i64(r3);
2807 return NO_EXIT;
2808}
2809
2810static ExitStatus op_msdb(DisasContext *s, DisasOps *o)
2811{
2812 int r3 = get_field(s->fields, r3);
2813 gen_helper_msdb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
2814 return NO_EXIT;
2815}
2816
b9bca3e5
RH
2817static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
2818{
d3010781
AJ
2819 TCGv_i64 z, n;
2820 z = tcg_const_i64(0);
2821 n = tcg_temp_new_i64();
2822 tcg_gen_neg_i64(n, o->in2);
2823 tcg_gen_movcond_i64(TCG_COND_GE, o->out, o->in2, z, n, o->in2);
2824 tcg_temp_free_i64(n);
2825 tcg_temp_free_i64(z);
b9bca3e5
RH
2826 return NO_EXIT;
2827}
2828
5d7fd045
RH
2829static ExitStatus op_nabsf32(DisasContext *s, DisasOps *o)
2830{
2831 tcg_gen_ori_i64(o->out, o->in2, 0x80000000ull);
2832 return NO_EXIT;
2833}
2834
2835static ExitStatus op_nabsf64(DisasContext *s, DisasOps *o)
2836{
2837 tcg_gen_ori_i64(o->out, o->in2, 0x8000000000000000ull);
2838 return NO_EXIT;
2839}
2840
2841static ExitStatus op_nabsf128(DisasContext *s, DisasOps *o)
2842{
2843 tcg_gen_ori_i64(o->out, o->in1, 0x8000000000000000ull);
2844 tcg_gen_mov_i64(o->out2, o->in2);
2845 return NO_EXIT;
2846}
2847
0a949039
RH
2848static ExitStatus op_nc(DisasContext *s, DisasOps *o)
2849{
2850 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
2851 potential_page_fault(s);
2852 gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2);
2853 tcg_temp_free_i32(l);
2854 set_cc_static(s);
2855 return NO_EXIT;
2856}
2857
b9bca3e5
RH
2858static ExitStatus op_neg(DisasContext *s, DisasOps *o)
2859{
2860 tcg_gen_neg_i64(o->out, o->in2);
2861 return NO_EXIT;
2862}
2863
5d7fd045
RH
2864static ExitStatus op_negf32(DisasContext *s, DisasOps *o)
2865{
2866 tcg_gen_xori_i64(o->out, o->in2, 0x80000000ull);
2867 return NO_EXIT;
2868}
2869
2870static ExitStatus op_negf64(DisasContext *s, DisasOps *o)
2871{
2872 tcg_gen_xori_i64(o->out, o->in2, 0x8000000000000000ull);
2873 return NO_EXIT;
2874}
2875
2876static ExitStatus op_negf128(DisasContext *s, DisasOps *o)
2877{
2878 tcg_gen_xori_i64(o->out, o->in1, 0x8000000000000000ull);
2879 tcg_gen_mov_i64(o->out2, o->in2);
2880 return NO_EXIT;
2881}
2882
0a949039
RH
2883static ExitStatus op_oc(DisasContext *s, DisasOps *o)
2884{
2885 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
2886 potential_page_fault(s);
2887 gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2);
2888 tcg_temp_free_i32(l);
2889 set_cc_static(s);
2890 return NO_EXIT;
2891}
2892
3bbfbd1f
RH
2893static ExitStatus op_or(DisasContext *s, DisasOps *o)
2894{
2895 tcg_gen_or_i64(o->out, o->in1, o->in2);
2896 return NO_EXIT;
2897}
2898
facfc864
RH
2899static ExitStatus op_ori(DisasContext *s, DisasOps *o)
2900{
2901 int shift = s->insn->data & 0xff;
2902 int size = s->insn->data >> 8;
2903 uint64_t mask = ((1ull << size) - 1) << shift;
2904
2905 assert(!o->g_in2);
2906 tcg_gen_shli_i64(o->in2, o->in2, shift);
2907 tcg_gen_or_i64(o->out, o->in1, o->in2);
2908
2909 /* Produce the CC from only the bits manipulated. */
2910 tcg_gen_andi_i64(cc_dst, o->out, mask);
2911 set_cc_nz_u64(s, cc_dst);
2912 return NO_EXIT;
2913}
2914
99b4f24b
RH
2915static ExitStatus op_popcnt(DisasContext *s, DisasOps *o)
2916{
2917 gen_helper_popcnt(o->out, o->in2);
2918 return NO_EXIT;
2919}
2920
0568d8aa
RH
2921#ifndef CONFIG_USER_ONLY
2922static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
2923{
2924 check_privileged(s);
2925 gen_helper_ptlb(cpu_env);
2926 return NO_EXIT;
2927}
2928#endif
2929
2d6a8698
RH
2930static ExitStatus op_risbg(DisasContext *s, DisasOps *o)
2931{
2932 int i3 = get_field(s->fields, i3);
2933 int i4 = get_field(s->fields, i4);
2934 int i5 = get_field(s->fields, i5);
2935 int do_zero = i4 & 0x80;
2936 uint64_t mask, imask, pmask;
2937 int pos, len, rot;
2938
2939 /* Adjust the arguments for the specific insn. */
2940 switch (s->fields->op2) {
2941 case 0x55: /* risbg */
2942 i3 &= 63;
2943 i4 &= 63;
2944 pmask = ~0;
2945 break;
2946 case 0x5d: /* risbhg */
2947 i3 &= 31;
2948 i4 &= 31;
2949 pmask = 0xffffffff00000000ull;
2950 break;
2951 case 0x51: /* risblg */
2952 i3 &= 31;
2953 i4 &= 31;
2954 pmask = 0x00000000ffffffffull;
2955 break;
2956 default:
2957 abort();
2958 }
2959
2960 /* MASK is the set of bits to be inserted from R2.
2961 Take care for I3/I4 wraparound. */
2962 mask = pmask >> i3;
2963 if (i3 <= i4) {
2964 mask ^= pmask >> i4 >> 1;
2965 } else {
2966 mask |= ~(pmask >> i4 >> 1);
2967 }
2968 mask &= pmask;
2969
2970 /* IMASK is the set of bits to be kept from R1. In the case of the high/low
2971 insns, we need to keep the other half of the register. */
2972 imask = ~mask | ~pmask;
2973 if (do_zero) {
2974 if (s->fields->op2 == 0x55) {
2975 imask = 0;
2976 } else {
2977 imask = ~pmask;
2978 }
2979 }
2980
2981 /* In some cases we can implement this with deposit, which can be more
2982 efficient on some hosts. */
2983 if (~mask == imask && i3 <= i4) {
2984 if (s->fields->op2 == 0x5d) {
2985 i3 += 32, i4 += 32;
2986 }
2987 /* Note that we rotate the bits to be inserted to the lsb, not to
2988 the position as described in the PoO. */
2989 len = i4 - i3 + 1;
2990 pos = 63 - i4;
2991 rot = (i5 - pos) & 63;
2992 } else {
2993 pos = len = -1;
2994 rot = i5 & 63;
2995 }
2996
2997 /* Rotate the input as necessary. */
2998 tcg_gen_rotli_i64(o->in2, o->in2, rot);
2999
3000 /* Insert the selected bits into the output. */
3001 if (pos >= 0) {
3002 tcg_gen_deposit_i64(o->out, o->out, o->in2, pos, len);
3003 } else if (imask == 0) {
3004 tcg_gen_andi_i64(o->out, o->in2, mask);
3005 } else {
3006 tcg_gen_andi_i64(o->in2, o->in2, mask);
3007 tcg_gen_andi_i64(o->out, o->out, imask);
3008 tcg_gen_or_i64(o->out, o->out, o->in2);
3009 }
3010 return NO_EXIT;
d6c6372e
RH
3011}
3012
3013static ExitStatus op_rosbg(DisasContext *s, DisasOps *o)
3014{
3015 int i3 = get_field(s->fields, i3);
3016 int i4 = get_field(s->fields, i4);
3017 int i5 = get_field(s->fields, i5);
3018 uint64_t mask;
3019
3020 /* If this is a test-only form, arrange to discard the result. */
3021 if (i3 & 0x80) {
3022 o->out = tcg_temp_new_i64();
3023 o->g_out = false;
3024 }
3025
3026 i3 &= 63;
3027 i4 &= 63;
3028 i5 &= 63;
3029
3030 /* MASK is the set of bits to be operated on from R2.
3031 Take care for I3/I4 wraparound. */
3032 mask = ~0ull >> i3;
3033 if (i3 <= i4) {
3034 mask ^= ~0ull >> i4 >> 1;
3035 } else {
3036 mask |= ~(~0ull >> i4 >> 1);
3037 }
3038
3039 /* Rotate the input as necessary. */
3040 tcg_gen_rotli_i64(o->in2, o->in2, i5);
3041
3042 /* Operate. */
3043 switch (s->fields->op2) {
3044 case 0x55: /* AND */
3045 tcg_gen_ori_i64(o->in2, o->in2, ~mask);
3046 tcg_gen_and_i64(o->out, o->out, o->in2);
3047 break;
3048 case 0x56: /* OR */
3049 tcg_gen_andi_i64(o->in2, o->in2, mask);
3050 tcg_gen_or_i64(o->out, o->out, o->in2);
3051 break;
3052 case 0x57: /* XOR */
3053 tcg_gen_andi_i64(o->in2, o->in2, mask);
3054 tcg_gen_xor_i64(o->out, o->out, o->in2);
3055 break;
3056 default:
3057 abort();
3058 }
3059
3060 /* Set the CC. */
3061 tcg_gen_andi_i64(cc_dst, o->out, mask);
3062 set_cc_nz_u64(s, cc_dst);
3063 return NO_EXIT;
2d6a8698
RH
3064}
3065
d54f5865
RH
3066static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
3067{
3068 tcg_gen_bswap16_i64(o->out, o->in2);
3069 return NO_EXIT;
3070}
3071
3072static ExitStatus op_rev32(DisasContext *s, DisasOps *o)
3073{
3074 tcg_gen_bswap32_i64(o->out, o->in2);
3075 return NO_EXIT;
3076}
3077
3078static ExitStatus op_rev64(DisasContext *s, DisasOps *o)
3079{
3080 tcg_gen_bswap64_i64(o->out, o->in2);
3081 return NO_EXIT;
3082}
3083
cbe24bfa
RH
3084static ExitStatus op_rll32(DisasContext *s, DisasOps *o)
3085{
3086 TCGv_i32 t1 = tcg_temp_new_i32();
3087 TCGv_i32 t2 = tcg_temp_new_i32();
3088 TCGv_i32 to = tcg_temp_new_i32();
3089 tcg_gen_trunc_i64_i32(t1, o->in1);
3090 tcg_gen_trunc_i64_i32(t2, o->in2);
3091 tcg_gen_rotl_i32(to, t1, t2);
3092 tcg_gen_extu_i32_i64(o->out, to);
3093 tcg_temp_free_i32(t1);
3094 tcg_temp_free_i32(t2);
3095 tcg_temp_free_i32(to);
3096 return NO_EXIT;
3097}
3098
3099static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
3100{
3101 tcg_gen_rotl_i64(o->out, o->in1, o->in2);
3102 return NO_EXIT;
3103}
3104
5cc69c54
RH
3105#ifndef CONFIG_USER_ONLY
3106static ExitStatus op_rrbe(DisasContext *s, DisasOps *o)
3107{
3108 check_privileged(s);
3109 gen_helper_rrbe(cc_op, cpu_env, o->in2);
3110 set_cc_static(s);
3111 return NO_EXIT;
3112}
14244b21
RH
3113
3114static ExitStatus op_sacf(DisasContext *s, DisasOps *o)
3115{
3116 check_privileged(s);
3117 gen_helper_sacf(cpu_env, o->in2);
3118 /* Addressing mode has changed, so end the block. */
3119 return EXIT_PC_STALE;
3120}
8612c935 3121#endif
44dd33ba
AG
3122
3123static ExitStatus op_sam(DisasContext *s, DisasOps *o)
3124{
3125 int sam = s->insn->data;
8612c935
RH
3126 TCGv_i64 tsam;
3127 uint64_t mask;
44dd33ba 3128
8612c935
RH
3129 switch (sam) {
3130 case 0:
3131 mask = 0xffffff;
3132 break;
3133 case 1:
3134 mask = 0x7fffffff;
3135 break;
3136 default:
3137 mask = -1;
3138 break;
3139 }
3140
631b22ea 3141 /* Bizarre but true, we check the address of the current insn for the
8612c935
RH
3142 specification exception, not the next to be executed. Thus the PoO
3143 documents that Bad Things Happen two bytes before the end. */
3144 if (s->pc & ~mask) {
3145 gen_program_exception(s, PGM_SPECIFICATION);
3146 return EXIT_NORETURN;
3147 }
3148 s->next_pc &= mask;
44dd33ba 3149
8612c935
RH
3150 tsam = tcg_const_i64(sam);
3151 tcg_gen_deposit_i64(psw_mask, psw_mask, tsam, 31, 2);
44dd33ba 3152 tcg_temp_free_i64(tsam);
8612c935
RH
3153
3154 /* Always exit the TB, since we (may have) changed execution mode. */
44dd33ba
AG
3155 return EXIT_PC_STALE;
3156}
5cc69c54 3157
d62a4c97
RH
3158static ExitStatus op_sar(DisasContext *s, DisasOps *o)
3159{
3160 int r1 = get_field(s->fields, r1);
3161 tcg_gen_st32_i64(o->in2, cpu_env, offsetof(CPUS390XState, aregs[r1]));
3162 return NO_EXIT;
3163}
3164
1a800a2d
RH
3165static ExitStatus op_seb(DisasContext *s, DisasOps *o)
3166{
3167 gen_helper_seb(o->out, cpu_env, o->in1, o->in2);
3168 return NO_EXIT;
3169}
3170
3171static ExitStatus op_sdb(DisasContext *s, DisasOps *o)
3172{
3173 gen_helper_sdb(o->out, cpu_env, o->in1, o->in2);
3174 return NO_EXIT;
3175}
3176
3177static ExitStatus op_sxb(DisasContext *s, DisasOps *o)
3178{
3179 gen_helper_sxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
3180 return_low128(o->out2);
3181 return NO_EXIT;
3182}
3183
16d7b2a4
RH
3184static ExitStatus op_sqeb(DisasContext *s, DisasOps *o)
3185{
3186 gen_helper_sqeb(o->out, cpu_env, o->in2);
3187 return NO_EXIT;
3188}
3189
3190static ExitStatus op_sqdb(DisasContext *s, DisasOps *o)
3191{
3192 gen_helper_sqdb(o->out, cpu_env, o->in2);
3193 return NO_EXIT;
3194}
3195
3196static ExitStatus op_sqxb(DisasContext *s, DisasOps *o)
3197{
3198 gen_helper_sqxb(o->out, cpu_env, o->in1, o->in2);
3199 return_low128(o->out2);
3200 return NO_EXIT;
3201}
3202
0c240015 3203#ifndef CONFIG_USER_ONLY
dc458df9
RH
3204static ExitStatus op_servc(DisasContext *s, DisasOps *o)
3205{
3206 check_privileged(s);
3207 potential_page_fault(s);
3208 gen_helper_servc(cc_op, cpu_env, o->in2, o->in1);
3209 set_cc_static(s);
3210 return NO_EXIT;
3211}
3212
0c240015
RH
3213static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
3214{
3215 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3216 check_privileged(s);
3217 potential_page_fault(s);
3218 gen_helper_sigp(cc_op, cpu_env, o->in2, r1, o->in1);
3219 tcg_temp_free_i32(r1);
3220 return NO_EXIT;
3221}
3222#endif
3223
b92fa334
RH
3224static ExitStatus op_soc(DisasContext *s, DisasOps *o)
3225{
3226 DisasCompare c;
3227 TCGv_i64 a;
42a268c2
RH
3228 TCGLabel *lab;
3229 int r1;
b92fa334
RH
3230
3231 disas_jcc(s, &c, get_field(s->fields, m3));
3232
c095ed73
AG
3233 /* We want to store when the condition is fulfilled, so branch
3234 out when it's not */
3235 c.cond = tcg_invert_cond(c.cond);
3236
b92fa334
RH
3237 lab = gen_new_label();
3238 if (c.is_64) {
3239 tcg_gen_brcond_i64(c.cond, c.u.s64.a, c.u.s64.b, lab);
3240 } else {
3241 tcg_gen_brcond_i32(c.cond, c.u.s32.a, c.u.s32.b, lab);
3242 }
3243 free_compare(&c);
3244
3245 r1 = get_field(s->fields, r1);
3246 a = get_address(s, 0, get_field(s->fields, b2), get_field(s->fields, d2));
3247 if (s->insn->data) {
3248 tcg_gen_qemu_st64(regs[r1], a, get_mem_index(s));
3249 } else {
3250 tcg_gen_qemu_st32(regs[r1], a, get_mem_index(s));
3251 }
3252 tcg_temp_free_i64(a);
3253
3254 gen_set_label(lab);
3255 return NO_EXIT;
3256}
3257
cbe24bfa
RH
3258static ExitStatus op_sla(DisasContext *s, DisasOps *o)
3259{
3260 uint64_t sign = 1ull << s->insn->data;
3261 enum cc_op cco = s->insn->data == 31 ? CC_OP_SLA_32 : CC_OP_SLA_64;
3262 gen_op_update2_cc_i64(s, cco, o->in1, o->in2);
3263 tcg_gen_shl_i64(o->out, o->in1, o->in2);
3264 /* The arithmetic left shift is curious in that it does not affect
3265 the sign bit. Copy that over from the source unchanged. */
3266 tcg_gen_andi_i64(o->out, o->out, ~sign);
3267 tcg_gen_andi_i64(o->in1, o->in1, sign);
3268 tcg_gen_or_i64(o->out, o->out, o->in1);
3269 return NO_EXIT;
3270}
3271
3272static ExitStatus op_sll(DisasContext *s, DisasOps *o)
3273{
3274 tcg_gen_shl_i64(o->out, o->in1, o->in2);
3275 return NO_EXIT;
3276}
3277
3278static ExitStatus op_sra(DisasContext *s, DisasOps *o)
3279{
3280 tcg_gen_sar_i64(o->out, o->in1, o->in2);
3281 return NO_EXIT;
3282}
3283
3284static ExitStatus op_srl(DisasContext *s, DisasOps *o)
3285{
3286 tcg_gen_shr_i64(o->out, o->in1, o->in2);
3287 return NO_EXIT;
3288}
3289
8379bfdb
RH
3290static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
3291{
3292 gen_helper_sfpc(cpu_env, o->in2);
3293 return NO_EXIT;
3294}
3295
411edc22
RH
3296static ExitStatus op_sfas(DisasContext *s, DisasOps *o)
3297{
3298 gen_helper_sfas(cpu_env, o->in2);
3299 return NO_EXIT;
3300}
3301
a12000b9
RH
3302static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
3303{
3304 int b2 = get_field(s->fields, b2);
3305 int d2 = get_field(s->fields, d2);
3306 TCGv_i64 t1 = tcg_temp_new_i64();
3307 TCGv_i64 t2 = tcg_temp_new_i64();
3308 int mask, pos, len;
3309
3310 switch (s->fields->op2) {
3311 case 0x99: /* SRNM */
3312 pos = 0, len = 2;
3313 break;
3314 case 0xb8: /* SRNMB */
3315 pos = 0, len = 3;
3316 break;
3317 case 0xb9: /* SRNMT */
3318 pos = 4, len = 3;
5b90a866 3319 break;
a12000b9
RH
3320 default:
3321 tcg_abort();
3322 }
3323 mask = (1 << len) - 1;
3324
3325 /* Insert the value into the appropriate field of the FPC. */
3326 if (b2 == 0) {
3327 tcg_gen_movi_i64(t1, d2 & mask);
3328 } else {
3329 tcg_gen_addi_i64(t1, regs[b2], d2);
3330 tcg_gen_andi_i64(t1, t1, mask);
3331 }
3332 tcg_gen_ld32u_i64(t2, cpu_env, offsetof(CPUS390XState, fpc));
3333 tcg_gen_deposit_i64(t2, t2, t1, pos, len);
3334 tcg_temp_free_i64(t1);
3335
3336 /* Then install the new FPC to set the rounding mode in fpu_status. */
3337 gen_helper_sfpc(cpu_env, t2);
3338 tcg_temp_free_i64(t2);
3339 return NO_EXIT;
3340}
3341
7d30bb73 3342#ifndef CONFIG_USER_ONLY
28d55556
RH
3343static ExitStatus op_spka(DisasContext *s, DisasOps *o)
3344{
3345 check_privileged(s);
3346 tcg_gen_shri_i64(o->in2, o->in2, 4);
3347 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY - 4, 4);
3348 return NO_EXIT;
3349}
3350
2bbde27f
RH
3351static ExitStatus op_sske(DisasContext *s, DisasOps *o)
3352{
3353 check_privileged(s);
3354 gen_helper_sske(cpu_env, o->in1, o->in2);
3355 return NO_EXIT;
3356}
3357
7d30bb73
RH
3358static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
3359{
3360 check_privileged(s);
3361 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
3362 return NO_EXIT;
3363}
145cdb40 3364
411fea3d
RH
3365static ExitStatus op_stap(DisasContext *s, DisasOps *o)
3366{
3367 check_privileged(s);
3368 /* ??? Surely cpu address != cpu number. In any case the previous
3369 version of this stored more than the required half-word, so it
3370 is unlikely this has ever been tested. */
3371 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
3372 return NO_EXIT;
3373}
3374
434c91a5
RH
3375static ExitStatus op_stck(DisasContext *s, DisasOps *o)
3376{
3377 gen_helper_stck(o->out, cpu_env);
3378 /* ??? We don't implement clock states. */
3379 gen_op_movi_cc(s, 0);
3380 return NO_EXIT;
39a5003c
RH
3381}
3382
3383static ExitStatus op_stcke(DisasContext *s, DisasOps *o)
3384{
3385 TCGv_i64 c1 = tcg_temp_new_i64();
3386 TCGv_i64 c2 = tcg_temp_new_i64();
3387 gen_helper_stck(c1, cpu_env);
3388 /* Shift the 64-bit value into its place as a zero-extended
3389 104-bit value. Note that "bit positions 64-103 are always
3390 non-zero so that they compare differently to STCK"; we set
3391 the least significant bit to 1. */
3392 tcg_gen_shli_i64(c2, c1, 56);
3393 tcg_gen_shri_i64(c1, c1, 8);
3394 tcg_gen_ori_i64(c2, c2, 0x10000);
3395 tcg_gen_qemu_st64(c1, o->in2, get_mem_index(s));
3396 tcg_gen_addi_i64(o->in2, o->in2, 8);
3397 tcg_gen_qemu_st64(c2, o->in2, get_mem_index(s));
3398 tcg_temp_free_i64(c1);
3399 tcg_temp_free_i64(c2);
3400 /* ??? We don't implement clock states. */
3401 gen_op_movi_cc(s, 0);
3402 return NO_EXIT;
434c91a5
RH
3403}
3404
dd3eb7b5
RH
3405static ExitStatus op_sckc(DisasContext *s, DisasOps *o)
3406{
3407 check_privileged(s);
3408 gen_helper_sckc(cpu_env, o->in2);
3409 return NO_EXIT;
3410}
3411
3412static ExitStatus op_stckc(DisasContext *s, DisasOps *o)
3413{
3414 check_privileged(s);
3415 gen_helper_stckc(o->out, cpu_env);
3416 return NO_EXIT;
3417}
3418
3e398cf9
RH
3419static ExitStatus op_stctg(DisasContext *s, DisasOps *o)
3420{
3421 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3422 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
3423 check_privileged(s);
3424 potential_page_fault(s);
3425 gen_helper_stctg(cpu_env, r1, o->in2, r3);
3426 tcg_temp_free_i32(r1);
3427 tcg_temp_free_i32(r3);
3428 return NO_EXIT;
3429}
3430
504488b8
RH
3431static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
3432{
3433 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3434 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
3435 check_privileged(s);
3436 potential_page_fault(s);
3437 gen_helper_stctl(cpu_env, r1, o->in2, r3);
3438 tcg_temp_free_i32(r1);
3439 tcg_temp_free_i32(r3);
3440 return NO_EXIT;
3441}
3442
71bd6669
RH
3443static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
3444{
7f745b31
RH
3445 TCGv_i64 t1 = tcg_temp_new_i64();
3446
71bd6669
RH
3447 check_privileged(s);
3448 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
7f745b31
RH
3449 tcg_gen_ld32u_i64(t1, cpu_env, offsetof(CPUS390XState, machine_type));
3450 tcg_gen_deposit_i64(o->out, o->out, t1, 32, 32);
3451 tcg_temp_free_i64(t1);
3452
71bd6669
RH
3453 return NO_EXIT;
3454}
3455
c4f0a863
RH
3456static ExitStatus op_spt(DisasContext *s, DisasOps *o)
3457{
3458 check_privileged(s);
3459 gen_helper_spt(cpu_env, o->in2);
3460 return NO_EXIT;
3461}
3462
fc778b55
RH
3463static ExitStatus op_stfl(DisasContext *s, DisasOps *o)
3464{
3465 TCGv_i64 f, a;
3466 /* We really ought to have more complete indication of facilities
3467 that we implement. Address this when STFLE is implemented. */
3468 check_privileged(s);
3469 f = tcg_const_i64(0xc0000000);
3470 a = tcg_const_i64(200);
3471 tcg_gen_qemu_st32(f, a, get_mem_index(s));
3472 tcg_temp_free_i64(f);
3473 tcg_temp_free_i64(a);
3474 return NO_EXIT;
3475}
3476
c4f0a863
RH
3477static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
3478{
3479 check_privileged(s);
3480 gen_helper_stpt(o->out, cpu_env);
3481 return NO_EXIT;
3482}
3483
d14b3e09
RH
3484static ExitStatus op_stsi(DisasContext *s, DisasOps *o)
3485{
3486 check_privileged(s);
3487 potential_page_fault(s);
3488 gen_helper_stsi(cc_op, cpu_env, o->in2, regs[0], regs[1]);
3489 set_cc_static(s);
3490 return NO_EXIT;
3491}
3492
e805a0d3
RH
3493static ExitStatus op_spx(DisasContext *s, DisasOps *o)
3494{
3495 check_privileged(s);
3496 gen_helper_spx(cpu_env, o->in2);
3497 return NO_EXIT;
3498}
3499
2c423fc0
RH
3500static ExitStatus op_subchannel(DisasContext *s, DisasOps *o)
3501{
3502 check_privileged(s);
3503 /* Not operational. */
3504 gen_op_movi_cc(s, 3);
3505 return NO_EXIT;
3506}
3507
e805a0d3
RH
3508static ExitStatus op_stpx(DisasContext *s, DisasOps *o)
3509{
3510 check_privileged(s);
3511 tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, psa));
3512 tcg_gen_andi_i64(o->out, o->out, 0x7fffe000);
3513 return NO_EXIT;
3514}
3515
145cdb40
RH
3516static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
3517{
3518 uint64_t i2 = get_field(s->fields, i2);
3519 TCGv_i64 t;
3520
3521 check_privileged(s);
3522
3523 /* It is important to do what the instruction name says: STORE THEN.
3524 If we let the output hook perform the store then if we fault and
3525 restart, we'll have the wrong SYSTEM MASK in place. */
3526 t = tcg_temp_new_i64();
3527 tcg_gen_shri_i64(t, psw_mask, 56);
3528 tcg_gen_qemu_st8(t, o->addr1, get_mem_index(s));
3529 tcg_temp_free_i64(t);
3530
3531 if (s->fields->op == 0xac) {
3532 tcg_gen_andi_i64(psw_mask, psw_mask,
3533 (i2 << 56) | 0x00ffffffffffffffull);
3534 } else {
3535 tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56);
3536 }
3537 return NO_EXIT;
3538}
204504e2
RH
3539
3540static ExitStatus op_stura(DisasContext *s, DisasOps *o)
3541{
3542 check_privileged(s);
3543 potential_page_fault(s);
3544 gen_helper_stura(cpu_env, o->in2, o->in1);
3545 return NO_EXIT;
3546}
9c3fd85b
RH
3547
3548static ExitStatus op_sturg(DisasContext *s, DisasOps *o)
3549{
3550 check_privileged(s);
3551 potential_page_fault(s);
3552 gen_helper_sturg(cpu_env, o->in2, o->in1);
3553 return NO_EXIT;
3554}
7d30bb73
RH
3555#endif
3556
2b280b97
RH
3557static ExitStatus op_st8(DisasContext *s, DisasOps *o)
3558{
3559 tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s));
3560 return NO_EXIT;
3561}
3562
3563static ExitStatus op_st16(DisasContext *s, DisasOps *o)
3564{
3565 tcg_gen_qemu_st16(o->in1, o->in2, get_mem_index(s));
3566 return NO_EXIT;
3567}
3568
3569static ExitStatus op_st32(DisasContext *s, DisasOps *o)
3570{
3571 tcg_gen_qemu_st32(o->in1, o->in2, get_mem_index(s));
3572 return NO_EXIT;
3573}
3574
3575static ExitStatus op_st64(DisasContext *s, DisasOps *o)
3576{
3577 tcg_gen_qemu_st64(o->in1, o->in2, get_mem_index(s));
3578 return NO_EXIT;
3579}
3580
7df3e93a
RH
3581static ExitStatus op_stam(DisasContext *s, DisasOps *o)
3582{
3583 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3584 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
3585 potential_page_fault(s);
3586 gen_helper_stam(cpu_env, r1, o->in2, r3);
3587 tcg_temp_free_i32(r1);
3588 tcg_temp_free_i32(r3);
3589 return NO_EXIT;
3590}
3591
2ae68059
RH
3592static ExitStatus op_stcm(DisasContext *s, DisasOps *o)
3593{
3594 int m3 = get_field(s->fields, m3);
3595 int pos, base = s->insn->data;
3596 TCGv_i64 tmp = tcg_temp_new_i64();
3597
3598 pos = base + ctz32(m3) * 8;
3599 switch (m3) {
3600 case 0xf:
3601 /* Effectively a 32-bit store. */
3602 tcg_gen_shri_i64(tmp, o->in1, pos);
3603 tcg_gen_qemu_st32(tmp, o->in2, get_mem_index(s));
3604 break;
3605
3606 case 0xc:
3607 case 0x6:
3608 case 0x3:
3609 /* Effectively a 16-bit store. */
3610 tcg_gen_shri_i64(tmp, o->in1, pos);
3611 tcg_gen_qemu_st16(tmp, o->in2, get_mem_index(s));
3612 break;
3613
3614 case 0x8:
3615 case 0x4:
3616 case 0x2:
3617 case 0x1:
3618 /* Effectively an 8-bit store. */
3619 tcg_gen_shri_i64(tmp, o->in1, pos);
3620 tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
3621 break;
3622
3623 default:
3624 /* This is going to be a sequence of shifts and stores. */
3625 pos = base + 32 - 8;
3626 while (m3) {
3627 if (m3 & 0x8) {
3628 tcg_gen_shri_i64(tmp, o->in1, pos);
3629 tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
3630 tcg_gen_addi_i64(o->in2, o->in2, 1);
3631 }
3632 m3 = (m3 << 1) & 0xf;
3633 pos -= 8;
3634 }
3635 break;
3636 }
3637 tcg_temp_free_i64(tmp);
3638 return NO_EXIT;
3639}
3640
77f8d6c3
RH
3641static ExitStatus op_stm(DisasContext *s, DisasOps *o)
3642{
3643 int r1 = get_field(s->fields, r1);
3644 int r3 = get_field(s->fields, r3);
3645 int size = s->insn->data;
3646 TCGv_i64 tsize = tcg_const_i64(size);
3647
3648 while (1) {
3649 if (size == 8) {
3650 tcg_gen_qemu_st64(regs[r1], o->in2, get_mem_index(s));
3651 } else {
3652 tcg_gen_qemu_st32(regs[r1], o->in2, get_mem_index(s));
3653 }
3654 if (r1 == r3) {
3655 break;
3656 }
3657 tcg_gen_add_i64(o->in2, o->in2, tsize);
3658 r1 = (r1 + 1) & 15;
3659 }
3660
3661 tcg_temp_free_i64(tsize);
3662 return NO_EXIT;
3663}
3664
3665static ExitStatus op_stmh(DisasContext *s, DisasOps *o)
3666{
3667 int r1 = get_field(s->fields, r1);
3668 int r3 = get_field(s->fields, r3);
3669 TCGv_i64 t = tcg_temp_new_i64();
3670 TCGv_i64 t4 = tcg_const_i64(4);
3671 TCGv_i64 t32 = tcg_const_i64(32);
3672
3673 while (1) {
3674 tcg_gen_shl_i64(t, regs[r1], t32);
3675 tcg_gen_qemu_st32(t, o->in2, get_mem_index(s));
3676 if (r1 == r3) {
3677 break;
3678 }
3679 tcg_gen_add_i64(o->in2, o->in2, t4);
3680 r1 = (r1 + 1) & 15;
3681 }
3682
3683 tcg_temp_free_i64(t);
3684 tcg_temp_free_i64(t4);
3685 tcg_temp_free_i64(t32);
3686 return NO_EXIT;
3687}
3688
4600c994
RH
3689static ExitStatus op_srst(DisasContext *s, DisasOps *o)
3690{
3691 potential_page_fault(s);
3692 gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2);
3693 set_cc_static(s);
3694 return_low128(o->in2);
3695 return NO_EXIT;
3696}
3697
ad044d09
RH
3698static ExitStatus op_sub(DisasContext *s, DisasOps *o)
3699{
3700 tcg_gen_sub_i64(o->out, o->in1, o->in2);
3701 return NO_EXIT;
3702}
3703
4e4bb438
RH
3704static ExitStatus op_subb(DisasContext *s, DisasOps *o)
3705{
c95ec459
RH
3706 DisasCompare cmp;
3707 TCGv_i64 borrow;
4e4bb438 3708
c95ec459 3709 tcg_gen_sub_i64(o->out, o->in1, o->in2);
4e4bb438 3710
c95ec459
RH
3711 /* The !borrow flag is the msb of CC. Since we want the inverse of
3712 that, we ask for a comparison of CC=0 | CC=1 -> mask of 8 | 4. */
3713 disas_jcc(s, &cmp, 8 | 4);
3714 borrow = tcg_temp_new_i64();
3715 if (cmp.is_64) {
3716 tcg_gen_setcond_i64(cmp.cond, borrow, cmp.u.s64.a, cmp.u.s64.b);
3717 } else {
3718 TCGv_i32 t = tcg_temp_new_i32();
3719 tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
3720 tcg_gen_extu_i32_i64(borrow, t);
3721 tcg_temp_free_i32(t);
3722 }
3723 free_compare(&cmp);
3724
3725 tcg_gen_sub_i64(o->out, o->out, borrow);
3726 tcg_temp_free_i64(borrow);
4e4bb438
RH
3727 return NO_EXIT;
3728}
3729
b9836c1a
RH
3730static ExitStatus op_svc(DisasContext *s, DisasOps *o)
3731{
3732 TCGv_i32 t;
3733
3734 update_psw_addr(s);
7a6c7067 3735 update_cc_op(s);
b9836c1a
RH
3736
3737 t = tcg_const_i32(get_field(s->fields, i1) & 0xff);
3738 tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code));
3739 tcg_temp_free_i32(t);
3740
3741 t = tcg_const_i32(s->next_pc - s->pc);
3742 tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
3743 tcg_temp_free_i32(t);
3744
3745 gen_exception(EXCP_SVC);
3746 return EXIT_NORETURN;
3747}
3748
31aa97d1
RH
3749static ExitStatus op_tceb(DisasContext *s, DisasOps *o)
3750{
3751 gen_helper_tceb(cc_op, o->in1, o->in2);
3752 set_cc_static(s);
3753 return NO_EXIT;
3754}
3755
3756static ExitStatus op_tcdb(DisasContext *s, DisasOps *o)
3757{
3758 gen_helper_tcdb(cc_op, o->in1, o->in2);
3759 set_cc_static(s);
3760 return NO_EXIT;
3761}
3762
3763static ExitStatus op_tcxb(DisasContext *s, DisasOps *o)
3764{
3765 gen_helper_tcxb(cc_op, o->out, o->out2, o->in2);
3766 set_cc_static(s);
3767 return NO_EXIT;
3768}
3769
112bf079
RH
3770#ifndef CONFIG_USER_ONLY
3771static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
3772{
3773 potential_page_fault(s);
3774 gen_helper_tprot(cc_op, o->addr1, o->in2);
3775 set_cc_static(s);
3776 return NO_EXIT;
3777}
3778#endif
3779
0a949039
RH
3780static ExitStatus op_tr(DisasContext *s, DisasOps *o)
3781{
3782 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3783 potential_page_fault(s);
3784 gen_helper_tr(cpu_env, l, o->addr1, o->in2);
3785 tcg_temp_free_i32(l);
3786 set_cc_static(s);
3787 return NO_EXIT;
3788}
3789
54f00775
AJ
3790static ExitStatus op_trt(DisasContext *s, DisasOps *o)
3791{
3792 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3793 potential_page_fault(s);
3794 gen_helper_trt(cc_op, cpu_env, l, o->addr1, o->in2);
3795 tcg_temp_free_i32(l);
3796 set_cc_static(s);
3797 return NO_EXIT;
3798}
3799
0a949039
RH
3800static ExitStatus op_unpk(DisasContext *s, DisasOps *o)
3801{
3802 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3803 potential_page_fault(s);
3804 gen_helper_unpk(cpu_env, l, o->addr1, o->in2);
3805 tcg_temp_free_i32(l);
3806 return NO_EXIT;
3807}
3808
3809static ExitStatus op_xc(DisasContext *s, DisasOps *o)
3810{
d074ac6d
RH
3811 int d1 = get_field(s->fields, d1);
3812 int d2 = get_field(s->fields, d2);
3813 int b1 = get_field(s->fields, b1);
3814 int b2 = get_field(s->fields, b2);
3815 int l = get_field(s->fields, l1);
3816 TCGv_i32 t32;
3817
3818 o->addr1 = get_address(s, 0, b1, d1);
3819
3820 /* If the addresses are identical, this is a store/memset of zero. */
3821 if (b1 == b2 && d1 == d2 && (l + 1) <= 32) {
3822 o->in2 = tcg_const_i64(0);
3823
3824 l++;
3825 while (l >= 8) {
3826 tcg_gen_qemu_st64(o->in2, o->addr1, get_mem_index(s));
3827 l -= 8;
3828 if (l > 0) {
3829 tcg_gen_addi_i64(o->addr1, o->addr1, 8);
3830 }
3831 }
3832 if (l >= 4) {
3833 tcg_gen_qemu_st32(o->in2, o->addr1, get_mem_index(s));
3834 l -= 4;
3835 if (l > 0) {
3836 tcg_gen_addi_i64(o->addr1, o->addr1, 4);
3837 }
3838 }
3839 if (l >= 2) {
3840 tcg_gen_qemu_st16(o->in2, o->addr1, get_mem_index(s));
3841 l -= 2;
3842 if (l > 0) {
3843 tcg_gen_addi_i64(o->addr1, o->addr1, 2);
3844 }
3845 }
3846 if (l) {
3847 tcg_gen_qemu_st8(o->in2, o->addr1, get_mem_index(s));
3848 }
3849 gen_op_movi_cc(s, 0);
3850 return NO_EXIT;
3851 }
3852
3853 /* But in general we'll defer to a helper. */
3854 o->in2 = get_address(s, 0, b2, d2);
3855 t32 = tcg_const_i32(l);
0a949039 3856 potential_page_fault(s);
d074ac6d
RH
3857 gen_helper_xc(cc_op, cpu_env, t32, o->addr1, o->in2);
3858 tcg_temp_free_i32(t32);
0a949039
RH
3859 set_cc_static(s);
3860 return NO_EXIT;
3861}
3862
3bbfbd1f
RH
3863static ExitStatus op_xor(DisasContext *s, DisasOps *o)
3864{
3865 tcg_gen_xor_i64(o->out, o->in1, o->in2);
3866 return NO_EXIT;
3867}
3868
facfc864
RH
3869static ExitStatus op_xori(DisasContext *s, DisasOps *o)
3870{
3871 int shift = s->insn->data & 0xff;
3872 int size = s->insn->data >> 8;
3873 uint64_t mask = ((1ull << size) - 1) << shift;
3874
3875 assert(!o->g_in2);
3876 tcg_gen_shli_i64(o->in2, o->in2, shift);
3877 tcg_gen_xor_i64(o->out, o->in1, o->in2);
3878
3879 /* Produce the CC from only the bits manipulated. */
3880 tcg_gen_andi_i64(cc_dst, o->out, mask);
3881 set_cc_nz_u64(s, cc_dst);
3882 return NO_EXIT;
3883}
3884
24db8412
RH
3885static ExitStatus op_zero(DisasContext *s, DisasOps *o)
3886{
3887 o->out = tcg_const_i64(0);
3888 return NO_EXIT;
3889}
3890
3891static ExitStatus op_zero2(DisasContext *s, DisasOps *o)
3892{
3893 o->out = tcg_const_i64(0);
3894 o->out2 = o->out;
3895 o->g_out2 = true;
3896 return NO_EXIT;
3897}
3898
ad044d09
RH
3899/* ====================================================================== */
3900/* The "Cc OUTput" generators. Given the generated output (and in some cases
3901 the original inputs), update the various cc data structures in order to
3902 be able to compute the new condition code. */
3903
b9bca3e5
RH
3904static void cout_abs32(DisasContext *s, DisasOps *o)
3905{
3906 gen_op_update1_cc_i64(s, CC_OP_ABS_32, o->out);
3907}
3908
3909static void cout_abs64(DisasContext *s, DisasOps *o)
3910{
3911 gen_op_update1_cc_i64(s, CC_OP_ABS_64, o->out);
3912}
3913
ad044d09
RH
3914static void cout_adds32(DisasContext *s, DisasOps *o)
3915{
3916 gen_op_update3_cc_i64(s, CC_OP_ADD_32, o->in1, o->in2, o->out);
3917}
3918
3919static void cout_adds64(DisasContext *s, DisasOps *o)
3920{
3921 gen_op_update3_cc_i64(s, CC_OP_ADD_64, o->in1, o->in2, o->out);
3922}
3923
3924static void cout_addu32(DisasContext *s, DisasOps *o)
3925{
3926 gen_op_update3_cc_i64(s, CC_OP_ADDU_32, o->in1, o->in2, o->out);
3927}
3928
3929static void cout_addu64(DisasContext *s, DisasOps *o)
3930{
3931 gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
3932}
3933
4e4bb438
RH
3934static void cout_addc32(DisasContext *s, DisasOps *o)
3935{
3936 gen_op_update3_cc_i64(s, CC_OP_ADDC_32, o->in1, o->in2, o->out);
3937}
3938
3939static void cout_addc64(DisasContext *s, DisasOps *o)
3940{
3941 gen_op_update3_cc_i64(s, CC_OP_ADDC_64, o->in1, o->in2, o->out);
3942}
3943
a7e836d5
RH
3944static void cout_cmps32(DisasContext *s, DisasOps *o)
3945{
3946 gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);
3947}
3948
3949static void cout_cmps64(DisasContext *s, DisasOps *o)
3950{
3951 gen_op_update2_cc_i64(s, CC_OP_LTGT_64, o->in1, o->in2);
3952}
3953
3954static void cout_cmpu32(DisasContext *s, DisasOps *o)
3955{
3956 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_32, o->in1, o->in2);
3957}
3958
3959static void cout_cmpu64(DisasContext *s, DisasOps *o)
3960{
3961 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
3962}
3963
587626f8
RH
3964static void cout_f32(DisasContext *s, DisasOps *o)
3965{
3966 gen_op_update1_cc_i64(s, CC_OP_NZ_F32, o->out);
3967}
3968
3969static void cout_f64(DisasContext *s, DisasOps *o)
3970{
3971 gen_op_update1_cc_i64(s, CC_OP_NZ_F64, o->out);
3972}
3973
3974static void cout_f128(DisasContext *s, DisasOps *o)
3975{
3976 gen_op_update2_cc_i64(s, CC_OP_NZ_F128, o->out, o->out2);
3977}
3978
b9bca3e5
RH
3979static void cout_nabs32(DisasContext *s, DisasOps *o)
3980{
3981 gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
3982}
3983
3984static void cout_nabs64(DisasContext *s, DisasOps *o)
3985{
3986 gen_op_update1_cc_i64(s, CC_OP_NABS_64, o->out);
3987}
3988
3989static void cout_neg32(DisasContext *s, DisasOps *o)
3990{
3991 gen_op_update1_cc_i64(s, CC_OP_COMP_32, o->out);
3992}
3993
3994static void cout_neg64(DisasContext *s, DisasOps *o)
3995{
3996 gen_op_update1_cc_i64(s, CC_OP_COMP_64, o->out);
3997}
3998
3bbfbd1f
RH
3999static void cout_nz32(DisasContext *s, DisasOps *o)
4000{
4001 tcg_gen_ext32u_i64(cc_dst, o->out);
4002 gen_op_update1_cc_i64(s, CC_OP_NZ, cc_dst);
4003}
4004
4005static void cout_nz64(DisasContext *s, DisasOps *o)
4006{
4007 gen_op_update1_cc_i64(s, CC_OP_NZ, o->out);
4008}
4009
11bf2d73
RH
4010static void cout_s32(DisasContext *s, DisasOps *o)
4011{
4012 gen_op_update1_cc_i64(s, CC_OP_LTGT0_32, o->out);
4013}
4014
4015static void cout_s64(DisasContext *s, DisasOps *o)
4016{
4017 gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, o->out);
4018}
4019
ad044d09
RH
4020static void cout_subs32(DisasContext *s, DisasOps *o)
4021{
4022 gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
4023}
4024
4025static void cout_subs64(DisasContext *s, DisasOps *o)
4026{
4027 gen_op_update3_cc_i64(s, CC_OP_SUB_64, o->in1, o->in2, o->out);
4028}
4029
4030static void cout_subu32(DisasContext *s, DisasOps *o)
4031{
4032 gen_op_update3_cc_i64(s, CC_OP_SUBU_32, o->in1, o->in2, o->out);
4033}
4034
4035static void cout_subu64(DisasContext *s, DisasOps *o)
4036{
4037 gen_op_update3_cc_i64(s, CC_OP_SUBU_64, o->in1, o->in2, o->out);
4038}
4039
4e4bb438
RH
4040static void cout_subb32(DisasContext *s, DisasOps *o)
4041{
4042 gen_op_update3_cc_i64(s, CC_OP_SUBB_32, o->in1, o->in2, o->out);
4043}
4044
4045static void cout_subb64(DisasContext *s, DisasOps *o)
4046{
4047 gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
4048}
4049
00d2dc19
RH
4050static void cout_tm32(DisasContext *s, DisasOps *o)
4051{
4052 gen_op_update2_cc_i64(s, CC_OP_TM_32, o->in1, o->in2);
4053}
4054
4055static void cout_tm64(DisasContext *s, DisasOps *o)
4056{
4057 gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2);
4058}
4059
ad044d09 4060/* ====================================================================== */
805a2505 4061/* The "PREParation" generators. These initialize the DisasOps.OUT fields
ad044d09
RH
4062 with the TCG register to which we will write. Used in combination with
4063 the "wout" generators, in some cases we need a new temporary, and in
4064 some cases we can write to a TCG global. */
4065
4066static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
4067{
4068 o->out = tcg_temp_new_i64();
4069}
49f7ee80 4070#define SPEC_prep_new 0
ad044d09 4071
891452e5
RH
4072static void prep_new_P(DisasContext *s, DisasFields *f, DisasOps *o)
4073{
4074 o->out = tcg_temp_new_i64();
4075 o->out2 = tcg_temp_new_i64();
4076}
49f7ee80 4077#define SPEC_prep_new_P 0
891452e5 4078
ad044d09
RH
4079static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
4080{
4081 o->out = regs[get_field(f, r1)];
4082 o->g_out = true;
4083}
49f7ee80 4084#define SPEC_prep_r1 0
ad044d09 4085
1ac5889f
RH
4086static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
4087{
1ac5889f
RH
4088 int r1 = get_field(f, r1);
4089 o->out = regs[r1];
49f7ee80 4090 o->out2 = regs[r1 + 1];
1ac5889f
RH
4091 o->g_out = o->g_out2 = true;
4092}
49f7ee80 4093#define SPEC_prep_r1_P SPEC_r1_even
1ac5889f 4094
587626f8
RH
4095static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
4096{
4097 o->out = fregs[get_field(f, r1)];
4098 o->g_out = true;
4099}
49f7ee80 4100#define SPEC_prep_f1 0
587626f8
RH
4101
4102static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o)
4103{
587626f8
RH
4104 int r1 = get_field(f, r1);
4105 o->out = fregs[r1];
49f7ee80 4106 o->out2 = fregs[r1 + 2];
587626f8
RH
4107 o->g_out = o->g_out2 = true;
4108}
49f7ee80 4109#define SPEC_prep_x1 SPEC_r1_f128
587626f8 4110
ad044d09
RH
4111/* ====================================================================== */
4112/* The "Write OUTput" generators. These generally perform some non-trivial
4113 copy of data to TCG globals, or to main memory. The trivial cases are
4114 generally handled by having a "prep" generator install the TCG global
4115 as the destination of the operation. */
4116
22c37a08
RH
4117static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
4118{
4119 store_reg(get_field(f, r1), o->out);
4120}
49f7ee80 4121#define SPEC_wout_r1 0
22c37a08 4122
afdc70be
RH
4123static void wout_r1_8(DisasContext *s, DisasFields *f, DisasOps *o)
4124{
4125 int r1 = get_field(f, r1);
4126 tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8);
4127}
49f7ee80 4128#define SPEC_wout_r1_8 0
afdc70be 4129
d54f5865
RH
4130static void wout_r1_16(DisasContext *s, DisasFields *f, DisasOps *o)
4131{
4132 int r1 = get_field(f, r1);
4133 tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 16);
4134}
49f7ee80 4135#define SPEC_wout_r1_16 0
d54f5865 4136
ad044d09
RH
4137static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
4138{
4139 store_reg32_i64(get_field(f, r1), o->out);
4140}
49f7ee80 4141#define SPEC_wout_r1_32 0
ad044d09 4142
891452e5
RH
4143static void wout_r1_P32(DisasContext *s, DisasFields *f, DisasOps *o)
4144{
891452e5
RH
4145 int r1 = get_field(f, r1);
4146 store_reg32_i64(r1, o->out);
49f7ee80 4147 store_reg32_i64(r1 + 1, o->out2);
891452e5 4148}
49f7ee80 4149#define SPEC_wout_r1_P32 SPEC_r1_even
891452e5 4150
d87aaf93
RH
4151static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4152{
d87aaf93 4153 int r1 = get_field(f, r1);
49f7ee80 4154 store_reg32_i64(r1 + 1, o->out);
d87aaf93
RH
4155 tcg_gen_shri_i64(o->out, o->out, 32);
4156 store_reg32_i64(r1, o->out);
4157}
49f7ee80 4158#define SPEC_wout_r1_D32 SPEC_r1_even
22c37a08 4159
d764a8d1
RH
4160static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o)
4161{
4162 store_freg32_i64(get_field(f, r1), o->out);
4163}
49f7ee80 4164#define SPEC_wout_e1 0
d764a8d1
RH
4165
4166static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
4167{
4168 store_freg(get_field(f, r1), o->out);
4169}
49f7ee80 4170#define SPEC_wout_f1 0
d764a8d1
RH
4171
4172static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
4173{
4174 int f1 = get_field(s->fields, r1);
4175 store_freg(f1, o->out);
49f7ee80 4176 store_freg(f1 + 2, o->out2);
d764a8d1 4177}
49f7ee80 4178#define SPEC_wout_x1 SPEC_r1_f128
d764a8d1 4179
22c37a08
RH
4180static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
4181{
4182 if (get_field(f, r1) != get_field(f, r2)) {
4183 store_reg32_i64(get_field(f, r1), o->out);
4184 }
4185}
49f7ee80 4186#define SPEC_wout_cond_r1r2_32 0
d87aaf93 4187
d764a8d1
RH
4188static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
4189{
4190 if (get_field(f, r1) != get_field(f, r2)) {
4191 store_freg32_i64(get_field(f, r1), o->out);
4192 }
4193}
49f7ee80 4194#define SPEC_wout_cond_e1e2 0
d764a8d1 4195
6a04d76a
RH
4196static void wout_m1_8(DisasContext *s, DisasFields *f, DisasOps *o)
4197{
4198 tcg_gen_qemu_st8(o->out, o->addr1, get_mem_index(s));
4199}
49f7ee80 4200#define SPEC_wout_m1_8 0
6a04d76a
RH
4201
4202static void wout_m1_16(DisasContext *s, DisasFields *f, DisasOps *o)
4203{
4204 tcg_gen_qemu_st16(o->out, o->addr1, get_mem_index(s));
4205}
49f7ee80 4206#define SPEC_wout_m1_16 0
6a04d76a 4207
ad044d09
RH
4208static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
4209{
4210 tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
4211}
49f7ee80 4212#define SPEC_wout_m1_32 0
ad044d09
RH
4213
4214static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
4215{
4216 tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
4217}
49f7ee80 4218#define SPEC_wout_m1_64 0
ad044d09 4219
ea20490f
RH
4220static void wout_m2_32(DisasContext *s, DisasFields *f, DisasOps *o)
4221{
4222 tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s));
4223}
49f7ee80 4224#define SPEC_wout_m2_32 0
ea20490f 4225
57af7289
AG
4226static void wout_m2_32_r1_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
4227{
4228 /* XXX release reservation */
4229 tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
4230 store_reg32_i64(get_field(f, r1), o->in2);
4231}
4232#define SPEC_wout_m2_32_r1_atomic 0
4233
4234static void wout_m2_64_r1_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
4235{
4236 /* XXX release reservation */
4237 tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
4238 store_reg(get_field(f, r1), o->in2);
4239}
4240#define SPEC_wout_m2_64_r1_atomic 0
4241
ad044d09
RH
4242/* ====================================================================== */
4243/* The "INput 1" generators. These load the first operand to an insn. */
4244
4245static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
4246{
4247 o->in1 = load_reg(get_field(f, r1));
4248}
49f7ee80 4249#define SPEC_in1_r1 0
ad044d09 4250
d1c04a2b
RH
4251static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4252{
4253 o->in1 = regs[get_field(f, r1)];
4254 o->g_in1 = true;
4255}
49f7ee80 4256#define SPEC_in1_r1_o 0
d1c04a2b 4257
cbe24bfa
RH
4258static void in1_r1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4259{
4260 o->in1 = tcg_temp_new_i64();
4261 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1)]);
4262}
49f7ee80 4263#define SPEC_in1_r1_32s 0
cbe24bfa
RH
4264
4265static void in1_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4266{
4267 o->in1 = tcg_temp_new_i64();
4268 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1)]);
4269}
49f7ee80 4270#define SPEC_in1_r1_32u 0
cbe24bfa 4271
32a44d58
RH
4272static void in1_r1_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
4273{
4274 o->in1 = tcg_temp_new_i64();
4275 tcg_gen_shri_i64(o->in1, regs[get_field(f, r1)], 32);
4276}
49f7ee80 4277#define SPEC_in1_r1_sr32 0
32a44d58 4278
1ac5889f
RH
4279static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
4280{
49f7ee80 4281 o->in1 = load_reg(get_field(f, r1) + 1);
1ac5889f 4282}
49f7ee80 4283#define SPEC_in1_r1p1 SPEC_r1_even
1ac5889f 4284
d87aaf93
RH
4285static void in1_r1p1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4286{
d87aaf93 4287 o->in1 = tcg_temp_new_i64();
49f7ee80 4288 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1) + 1]);
d87aaf93 4289}
49f7ee80 4290#define SPEC_in1_r1p1_32s SPEC_r1_even
d87aaf93
RH
4291
4292static void in1_r1p1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4293{
d87aaf93 4294 o->in1 = tcg_temp_new_i64();
49f7ee80 4295 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1) + 1]);
d87aaf93 4296}
49f7ee80 4297#define SPEC_in1_r1p1_32u SPEC_r1_even
d87aaf93 4298
891452e5
RH
4299static void in1_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4300{
891452e5
RH
4301 int r1 = get_field(f, r1);
4302 o->in1 = tcg_temp_new_i64();
4303 tcg_gen_concat32_i64(o->in1, regs[r1 + 1], regs[r1]);
4304}
49f7ee80 4305#define SPEC_in1_r1_D32 SPEC_r1_even
891452e5 4306
ad044d09
RH
4307static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
4308{
4309 o->in1 = load_reg(get_field(f, r2));
4310}
49f7ee80 4311#define SPEC_in1_r2 0
ad044d09
RH
4312
4313static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
4314{
4315 o->in1 = load_reg(get_field(f, r3));
4316}
49f7ee80 4317#define SPEC_in1_r3 0
ad044d09 4318
cbe24bfa
RH
4319static void in1_r3_o(DisasContext *s, DisasFields *f, DisasOps *o)
4320{
4321 o->in1 = regs[get_field(f, r3)];
4322 o->g_in1 = true;
4323}
49f7ee80 4324#define SPEC_in1_r3_o 0
cbe24bfa
RH
4325
4326static void in1_r3_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4327{
4328 o->in1 = tcg_temp_new_i64();
4329 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r3)]);
4330}
49f7ee80 4331#define SPEC_in1_r3_32s 0
cbe24bfa
RH
4332
4333static void in1_r3_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4334{
4335 o->in1 = tcg_temp_new_i64();
4336 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r3)]);
4337}
49f7ee80 4338#define SPEC_in1_r3_32u 0
cbe24bfa 4339
b7886de3
RH
4340static void in1_r3_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4341{
4342 int r3 = get_field(f, r3);
4343 o->in1 = tcg_temp_new_i64();
4344 tcg_gen_concat32_i64(o->in1, regs[r3 + 1], regs[r3]);
4345}
4346#define SPEC_in1_r3_D32 SPEC_r3_even
4347
00574261
RH
4348static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
4349{
4350 o->in1 = load_freg32_i64(get_field(f, r1));
4351}
49f7ee80 4352#define SPEC_in1_e1 0
00574261
RH
4353
4354static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4355{
4356 o->in1 = fregs[get_field(f, r1)];
4357 o->g_in1 = true;
4358}
49f7ee80 4359#define SPEC_in1_f1_o 0
00574261 4360
587626f8
RH
4361static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4362{
587626f8
RH
4363 int r1 = get_field(f, r1);
4364 o->out = fregs[r1];
49f7ee80 4365 o->out2 = fregs[r1 + 2];
587626f8
RH
4366 o->g_out = o->g_out2 = true;
4367}
49f7ee80 4368#define SPEC_in1_x1_o SPEC_r1_f128
587626f8 4369
2db014b5
RH
4370static void in1_f3_o(DisasContext *s, DisasFields *f, DisasOps *o)
4371{
4372 o->in1 = fregs[get_field(f, r3)];
4373 o->g_in1 = true;
4374}
49f7ee80 4375#define SPEC_in1_f3_o 0
2db014b5 4376
ad044d09
RH
4377static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
4378{
4379 o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
4380}
49f7ee80 4381#define SPEC_in1_la1 0
ad044d09 4382
e025e52a
RH
4383static void in1_la2(DisasContext *s, DisasFields *f, DisasOps *o)
4384{
4385 int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
4386 o->addr1 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
4387}
49f7ee80 4388#define SPEC_in1_la2 0
e025e52a 4389
a7e836d5
RH
4390static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4391{
4392 in1_la1(s, f, o);
4393 o->in1 = tcg_temp_new_i64();
4394 tcg_gen_qemu_ld8u(o->in1, o->addr1, get_mem_index(s));
4395}
49f7ee80 4396#define SPEC_in1_m1_8u 0
a7e836d5
RH
4397
4398static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4399{
4400 in1_la1(s, f, o);
4401 o->in1 = tcg_temp_new_i64();
4402 tcg_gen_qemu_ld16s(o->in1, o->addr1, get_mem_index(s));
4403}
49f7ee80 4404#define SPEC_in1_m1_16s 0
a7e836d5
RH
4405
4406static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4407{
4408 in1_la1(s, f, o);
4409 o->in1 = tcg_temp_new_i64();
4410 tcg_gen_qemu_ld16u(o->in1, o->addr1, get_mem_index(s));
4411}
49f7ee80 4412#define SPEC_in1_m1_16u 0
a7e836d5 4413
ad044d09
RH
4414static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4415{
4416 in1_la1(s, f, o);
4417 o->in1 = tcg_temp_new_i64();
4418 tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
4419}
49f7ee80 4420#define SPEC_in1_m1_32s 0
ad044d09 4421
e272b3ac
RH
4422static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4423{
4424 in1_la1(s, f, o);
4425 o->in1 = tcg_temp_new_i64();
4426 tcg_gen_qemu_ld32u(o->in1, o->addr1, get_mem_index(s));
4427}
49f7ee80 4428#define SPEC_in1_m1_32u 0
e272b3ac 4429
ad044d09
RH
4430static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
4431{
4432 in1_la1(s, f, o);
4433 o->in1 = tcg_temp_new_i64();
4434 tcg_gen_qemu_ld64(o->in1, o->addr1, get_mem_index(s));
4435}
49f7ee80 4436#define SPEC_in1_m1_64 0
ad044d09
RH
4437
4438/* ====================================================================== */
4439/* The "INput 2" generators. These load the second operand to an insn. */
4440
e025e52a
RH
4441static void in2_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4442{
4443 o->in2 = regs[get_field(f, r1)];
4444 o->g_in2 = true;
4445}
49f7ee80 4446#define SPEC_in2_r1_o 0
e025e52a
RH
4447
4448static void in2_r1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4449{
4450 o->in2 = tcg_temp_new_i64();
4451 tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r1)]);
4452}
49f7ee80 4453#define SPEC_in2_r1_16u 0
e025e52a
RH
4454
4455static void in2_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4456{
4457 o->in2 = tcg_temp_new_i64();
4458 tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r1)]);
4459}
49f7ee80 4460#define SPEC_in2_r1_32u 0
e025e52a 4461
b7886de3
RH
4462static void in2_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4463{
4464 int r1 = get_field(f, r1);
4465 o->in2 = tcg_temp_new_i64();
4466 tcg_gen_concat32_i64(o->in2, regs[r1 + 1], regs[r1]);
4467}
4468#define SPEC_in2_r1_D32 SPEC_r1_even
4469
ad044d09
RH
4470static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
4471{
4472 o->in2 = load_reg(get_field(f, r2));
4473}
49f7ee80 4474#define SPEC_in2_r2 0
ad044d09 4475
d1c04a2b
RH
4476static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
4477{
4478 o->in2 = regs[get_field(f, r2)];
4479 o->g_in2 = true;
4480}
49f7ee80 4481#define SPEC_in2_r2_o 0
d1c04a2b 4482
8ac33cdb
RH
4483static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
4484{
4485 int r2 = get_field(f, r2);
4486 if (r2 != 0) {
4487 o->in2 = load_reg(r2);
4488 }
4489}
49f7ee80 4490#define SPEC_in2_r2_nz 0
8ac33cdb 4491
c698d876
RH
4492static void in2_r2_8s(DisasContext *s, DisasFields *f, DisasOps *o)
4493{
4494 o->in2 = tcg_temp_new_i64();
4495 tcg_gen_ext8s_i64(o->in2, regs[get_field(f, r2)]);
4496}
49f7ee80 4497#define SPEC_in2_r2_8s 0
c698d876
RH
4498
4499static void in2_r2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4500{
4501 o->in2 = tcg_temp_new_i64();
4502 tcg_gen_ext8u_i64(o->in2, regs[get_field(f, r2)]);
4503}
49f7ee80 4504#define SPEC_in2_r2_8u 0
c698d876
RH
4505
4506static void in2_r2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4507{
4508 o->in2 = tcg_temp_new_i64();
4509 tcg_gen_ext16s_i64(o->in2, regs[get_field(f, r2)]);
4510}
49f7ee80 4511#define SPEC_in2_r2_16s 0
c698d876
RH
4512
4513static void in2_r2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4514{
4515 o->in2 = tcg_temp_new_i64();
4516 tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r2)]);
4517}
49f7ee80 4518#define SPEC_in2_r2_16u 0
c698d876 4519
ad044d09
RH
4520static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
4521{
4522 o->in2 = load_reg(get_field(f, r3));
4523}
49f7ee80 4524#define SPEC_in2_r3 0
ad044d09
RH
4525
4526static void in2_r2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4527{
4528 o->in2 = tcg_temp_new_i64();
4529 tcg_gen_ext32s_i64(o->in2, regs[get_field(f, r2)]);
4530}
49f7ee80 4531#define SPEC_in2_r2_32s 0
ad044d09
RH
4532
4533static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4534{
4535 o->in2 = tcg_temp_new_i64();
4536 tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
4537}
49f7ee80 4538#define SPEC_in2_r2_32u 0
ad044d09 4539
d764a8d1
RH
4540static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o)
4541{
4542 o->in2 = load_freg32_i64(get_field(f, r2));
4543}
49f7ee80 4544#define SPEC_in2_e2 0
d764a8d1
RH
4545
4546static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
4547{
4548 o->in2 = fregs[get_field(f, r2)];
4549 o->g_in2 = true;
4550}
49f7ee80 4551#define SPEC_in2_f2_o 0
d764a8d1
RH
4552
4553static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
4554{
587626f8
RH
4555 int r2 = get_field(f, r2);
4556 o->in1 = fregs[r2];
49f7ee80 4557 o->in2 = fregs[r2 + 2];
d764a8d1
RH
4558 o->g_in1 = o->g_in2 = true;
4559}
49f7ee80 4560#define SPEC_in2_x2_o SPEC_r2_f128
d764a8d1 4561
374724f9
RH
4562static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
4563{
4564 o->in2 = get_address(s, 0, get_field(f, r2), 0);
4565}
49f7ee80 4566#define SPEC_in2_ra2 0
374724f9 4567
ad044d09
RH
4568static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
4569{
4570 int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
4571 o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
4572}
49f7ee80 4573#define SPEC_in2_a2 0
ad044d09 4574
a7e836d5
RH
4575static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
4576{
4577 o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
4578}
49f7ee80 4579#define SPEC_in2_ri2 0
a7e836d5 4580
cbe24bfa
RH
4581static void in2_sh32(DisasContext *s, DisasFields *f, DisasOps *o)
4582{
4583 help_l2_shift(s, f, o, 31);
4584}
49f7ee80 4585#define SPEC_in2_sh32 0
cbe24bfa
RH
4586
4587static void in2_sh64(DisasContext *s, DisasFields *f, DisasOps *o)
4588{
4589 help_l2_shift(s, f, o, 63);
4590}
49f7ee80 4591#define SPEC_in2_sh64 0
cbe24bfa 4592
afdc70be
RH
4593static void in2_m2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4594{
4595 in2_a2(s, f, o);
4596 tcg_gen_qemu_ld8u(o->in2, o->in2, get_mem_index(s));
4597}
49f7ee80 4598#define SPEC_in2_m2_8u 0
afdc70be 4599
d82287de
RH
4600static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4601{
4602 in2_a2(s, f, o);
4603 tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
4604}
49f7ee80 4605#define SPEC_in2_m2_16s 0
d82287de 4606
d54f5865
RH
4607static void in2_m2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4608{
4609 in2_a2(s, f, o);
4610 tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
4611}
49f7ee80 4612#define SPEC_in2_m2_16u 0
d54f5865 4613
ad044d09
RH
4614static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4615{
4616 in2_a2(s, f, o);
4617 tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
4618}
49f7ee80 4619#define SPEC_in2_m2_32s 0
ad044d09
RH
4620
4621static void in2_m2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4622{
4623 in2_a2(s, f, o);
4624 tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
4625}
49f7ee80 4626#define SPEC_in2_m2_32u 0
ad044d09
RH
4627
4628static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
4629{
4630 in2_a2(s, f, o);
4631 tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
4632}
49f7ee80 4633#define SPEC_in2_m2_64 0
ad044d09 4634
a7e836d5
RH
4635static void in2_mri2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4636{
4637 in2_ri2(s, f, o);
4638 tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
4639}
49f7ee80 4640#define SPEC_in2_mri2_16u 0
a7e836d5
RH
4641
4642static void in2_mri2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4643{
4644 in2_ri2(s, f, o);
4645 tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
4646}
49f7ee80 4647#define SPEC_in2_mri2_32s 0
a7e836d5
RH
4648
4649static void in2_mri2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4650{
4651 in2_ri2(s, f, o);
4652 tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
4653}
49f7ee80 4654#define SPEC_in2_mri2_32u 0
a7e836d5
RH
4655
4656static void in2_mri2_64(DisasContext *s, DisasFields *f, DisasOps *o)
4657{
4658 in2_ri2(s, f, o);
4659 tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
4660}
49f7ee80 4661#define SPEC_in2_mri2_64 0
a7e836d5 4662
57af7289
AG
4663static void in2_m2_32s_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
4664{
4665 /* XXX should reserve the address */
4666 in1_la2(s, f, o);
4667 o->in2 = tcg_temp_new_i64();
4668 tcg_gen_qemu_ld32s(o->in2, o->addr1, get_mem_index(s));
4669}
4670#define SPEC_in2_m2_32s_atomic 0
4671
4672static void in2_m2_64_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
4673{
4674 /* XXX should reserve the address */
4675 in1_la2(s, f, o);
4676 o->in2 = tcg_temp_new_i64();
4677 tcg_gen_qemu_ld64(o->in2, o->addr1, get_mem_index(s));
4678}
4679#define SPEC_in2_m2_64_atomic 0
4680
ad044d09
RH
4681static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
4682{
4683 o->in2 = tcg_const_i64(get_field(f, i2));
4684}
49f7ee80 4685#define SPEC_in2_i2 0
ad044d09 4686
a7e836d5
RH
4687static void in2_i2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4688{
4689 o->in2 = tcg_const_i64((uint8_t)get_field(f, i2));
4690}
49f7ee80 4691#define SPEC_in2_i2_8u 0
a7e836d5
RH
4692
4693static void in2_i2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4694{
4695 o->in2 = tcg_const_i64((uint16_t)get_field(f, i2));
4696}
49f7ee80 4697#define SPEC_in2_i2_16u 0
a7e836d5 4698
ad044d09
RH
4699static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4700{
4701 o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
4702}
49f7ee80 4703#define SPEC_in2_i2_32u 0
ad044d09 4704
ade9dea4
RH
4705static void in2_i2_16u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
4706{
4707 uint64_t i2 = (uint16_t)get_field(f, i2);
4708 o->in2 = tcg_const_i64(i2 << s->insn->data);
4709}
49f7ee80 4710#define SPEC_in2_i2_16u_shl 0
ade9dea4
RH
4711
4712static void in2_i2_32u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
4713{
4714 uint64_t i2 = (uint32_t)get_field(f, i2);
4715 o->in2 = tcg_const_i64(i2 << s->insn->data);
4716}
49f7ee80 4717#define SPEC_in2_i2_32u_shl 0
ade9dea4 4718
ad044d09
RH
4719/* ====================================================================== */
4720
4721/* Find opc within the table of insns. This is formulated as a switch
4722 statement so that (1) we get compile-time notice of cut-paste errors
4723 for duplicated opcodes, and (2) the compiler generates the binary
4724 search tree, rather than us having to post-process the table. */
4725
4726#define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \
4727 D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0)
4728
4729#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) insn_ ## NM,
4730
4731enum DisasInsnEnum {
4732#include "insn-data.def"
4733};
4734
4735#undef D
49f7ee80
RH
4736#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
4737 .opc = OPC, \
4738 .fmt = FMT_##FT, \
4739 .fac = FAC_##FC, \
4740 .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \
4741 .name = #NM, \
4742 .help_in1 = in1_##I1, \
4743 .help_in2 = in2_##I2, \
4744 .help_prep = prep_##P, \
4745 .help_wout = wout_##W, \
4746 .help_cout = cout_##CC, \
4747 .help_op = op_##OP, \
4748 .data = D \
ad044d09
RH
4749 },
4750
4751/* Allow 0 to be used for NULL in the table below. */
4752#define in1_0 NULL
4753#define in2_0 NULL
4754#define prep_0 NULL
4755#define wout_0 NULL
4756#define cout_0 NULL
4757#define op_0 NULL
4758
49f7ee80
RH
4759#define SPEC_in1_0 0
4760#define SPEC_in2_0 0
4761#define SPEC_prep_0 0
4762#define SPEC_wout_0 0
4763
ad044d09
RH
4764static const DisasInsn insn_info[] = {
4765#include "insn-data.def"
4766};
4767
4768#undef D
4769#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
4770 case OPC: return &insn_info[insn_ ## NM];
4771
4772static const DisasInsn *lookup_opc(uint16_t opc)
4773{
4774 switch (opc) {
4775#include "insn-data.def"
4776 default:
4777 return NULL;
4778 }
4779}
4780
4781#undef D
4782#undef C
4783
4784/* Extract a field from the insn. The INSN should be left-aligned in
4785 the uint64_t so that we can more easily utilize the big-bit-endian
4786 definitions we extract from the Principals of Operation. */
4787
4788static void extract_field(DisasFields *o, const DisasField *f, uint64_t insn)
4789{
4790 uint32_t r, m;
4791
4792 if (f->size == 0) {
4793 return;
4794 }
4795
4796 /* Zero extract the field from the insn. */
4797 r = (insn << f->beg) >> (64 - f->size);
4798
4799 /* Sign-extend, or un-swap the field as necessary. */
4800 switch (f->type) {
4801 case 0: /* unsigned */
4802 break;
4803 case 1: /* signed */
4804 assert(f->size <= 32);
4805 m = 1u << (f->size - 1);
4806 r = (r ^ m) - m;
4807 break;
4808 case 2: /* dl+dh split, signed 20 bit. */
4809 r = ((int8_t)r << 12) | (r >> 8);
4810 break;
4811 default:
4812 abort();
4813 }
4814
4815 /* Validate that the "compressed" encoding we selected above is valid.
4816 I.e. we havn't make two different original fields overlap. */
4817 assert(((o->presentC >> f->indexC) & 1) == 0);
4818 o->presentC |= 1 << f->indexC;
4819 o->presentO |= 1 << f->indexO;
4820
4821 o->c[f->indexC] = r;
4822}
4823
4824/* Lookup the insn at the current PC, extracting the operands into O and
4825 returning the info struct for the insn. Returns NULL for invalid insn. */
4826
4827static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
4828 DisasFields *f)
4829{
4830 uint64_t insn, pc = s->pc;
d5a103cd 4831 int op, op2, ilen;
ad044d09
RH
4832 const DisasInsn *info;
4833
4834 insn = ld_code2(env, pc);
4835 op = (insn >> 8) & 0xff;
d5a103cd
RH
4836 ilen = get_ilen(op);
4837 s->next_pc = s->pc + ilen;
4838
4839 switch (ilen) {
4840 case 2:
ad044d09
RH
4841 insn = insn << 48;
4842 break;
d5a103cd 4843 case 4:
ad044d09
RH
4844 insn = ld_code4(env, pc) << 32;
4845 break;
d5a103cd 4846 case 6:
ad044d09
RH
4847 insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
4848 break;
4849 default:
4850 abort();
4851 }
4852
4853 /* We can't actually determine the insn format until we've looked up
4854 the full insn opcode. Which we can't do without locating the
4855 secondary opcode. Assume by default that OP2 is at bit 40; for
4856 those smaller insns that don't actually have a secondary opcode
4857 this will correctly result in OP2 = 0. */
4858 switch (op) {
4859 case 0x01: /* E */
4860 case 0x80: /* S */
4861 case 0x82: /* S */
4862 case 0x93: /* S */
4863 case 0xb2: /* S, RRF, RRE */
4864 case 0xb3: /* RRE, RRD, RRF */
4865 case 0xb9: /* RRE, RRF */
4866 case 0xe5: /* SSE, SIL */
4867 op2 = (insn << 8) >> 56;
4868 break;
4869 case 0xa5: /* RI */
4870 case 0xa7: /* RI */
4871 case 0xc0: /* RIL */
4872 case 0xc2: /* RIL */
4873 case 0xc4: /* RIL */
4874 case 0xc6: /* RIL */
4875 case 0xc8: /* SSF */
4876 case 0xcc: /* RIL */
4877 op2 = (insn << 12) >> 60;
4878 break;
4879 case 0xd0 ... 0xdf: /* SS */
4880 case 0xe1: /* SS */
4881 case 0xe2: /* SS */
4882 case 0xe8: /* SS */
4883 case 0xe9: /* SS */
4884 case 0xea: /* SS */
4885 case 0xee ... 0xf3: /* SS */
4886 case 0xf8 ... 0xfd: /* SS */
4887 op2 = 0;
4888 break;
4889 default:
4890 op2 = (insn << 40) >> 56;
4891 break;
4892 }
4893
4894 memset(f, 0, sizeof(*f));
4895 f->op = op;
4896 f->op2 = op2;
4897
4898 /* Lookup the instruction. */
4899 info = lookup_opc(op << 8 | op2);
4900
4901 /* If we found it, extract the operands. */
4902 if (info != NULL) {
4903 DisasFormat fmt = info->fmt;
4904 int i;
4905
4906 for (i = 0; i < NUM_C_FIELD; ++i) {
4907 extract_field(f, &format_info[fmt].op[i], insn);
4908 }
4909 }
4910 return info;
4911}
4912
4913static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
4914{
4915 const DisasInsn *insn;
4916 ExitStatus ret = NO_EXIT;
4917 DisasFields f;
4918 DisasOps o;
4919
4f3adfb2 4920 /* Search for the insn in the table. */
ad044d09 4921 insn = extract_insn(env, s, &f);
e023e832 4922
4f3adfb2 4923 /* Not found means unimplemented/illegal opcode. */
ad044d09 4924 if (insn == NULL) {
4f3adfb2
RH
4925 qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%02x%02x\n",
4926 f.op, f.op2);
4927 gen_illegal_opcode(s);
4928 return EXIT_NORETURN;
ad044d09
RH
4929 }
4930
49f7ee80
RH
4931 /* Check for insn specification exceptions. */
4932 if (insn->spec) {
4933 int spec = insn->spec, excp = 0, r;
4934
4935 if (spec & SPEC_r1_even) {
4936 r = get_field(&f, r1);
4937 if (r & 1) {
4938 excp = PGM_SPECIFICATION;
4939 }
4940 }
4941 if (spec & SPEC_r2_even) {
4942 r = get_field(&f, r2);
4943 if (r & 1) {
b7886de3
RH
4944 excp = PGM_SPECIFICATION;
4945 }
4946 }
4947 if (spec & SPEC_r3_even) {
4948 r = get_field(&f, r3);
4949 if (r & 1) {
49f7ee80
RH
4950 excp = PGM_SPECIFICATION;
4951 }
4952 }
4953 if (spec & SPEC_r1_f128) {
4954 r = get_field(&f, r1);
4955 if (r > 13) {
4956 excp = PGM_SPECIFICATION;
4957 }
4958 }
4959 if (spec & SPEC_r2_f128) {
4960 r = get_field(&f, r2);
4961 if (r > 13) {
4962 excp = PGM_SPECIFICATION;
4963 }
4964 }
4965 if (excp) {
4966 gen_program_exception(s, excp);
4967 return EXIT_NORETURN;
4968 }
4969 }
4970
ad044d09
RH
4971 /* Set up the strutures we use to communicate with the helpers. */
4972 s->insn = insn;
4973 s->fields = &f;
4974 o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
4975 TCGV_UNUSED_I64(o.out);
4976 TCGV_UNUSED_I64(o.out2);
4977 TCGV_UNUSED_I64(o.in1);
4978 TCGV_UNUSED_I64(o.in2);
4979 TCGV_UNUSED_I64(o.addr1);
4980
4981 /* Implement the instruction. */
4982 if (insn->help_in1) {
4983 insn->help_in1(s, &f, &o);
4984 }
4985 if (insn->help_in2) {
4986 insn->help_in2(s, &f, &o);
4987 }
4988 if (insn->help_prep) {
4989 insn->help_prep(s, &f, &o);
4990 }
4991 if (insn->help_op) {
4992 ret = insn->help_op(s, &o);
4993 }
4994 if (insn->help_wout) {
4995 insn->help_wout(s, &f, &o);
4996 }
4997 if (insn->help_cout) {
4998 insn->help_cout(s, &o);
4999 }
5000
5001 /* Free any temporaries created by the helpers. */
5002 if (!TCGV_IS_UNUSED_I64(o.out) && !o.g_out) {
5003 tcg_temp_free_i64(o.out);
5004 }
5005 if (!TCGV_IS_UNUSED_I64(o.out2) && !o.g_out2) {
5006 tcg_temp_free_i64(o.out2);
5007 }
5008 if (!TCGV_IS_UNUSED_I64(o.in1) && !o.g_in1) {
5009 tcg_temp_free_i64(o.in1);
5010 }
5011 if (!TCGV_IS_UNUSED_I64(o.in2) && !o.g_in2) {
5012 tcg_temp_free_i64(o.in2);
5013 }
5014 if (!TCGV_IS_UNUSED_I64(o.addr1)) {
5015 tcg_temp_free_i64(o.addr1);
5016 }
5017
5018 /* Advance to the next instruction. */
5019 s->pc = s->next_pc;
5020 return ret;
e023e832
AG
5021}
5022
d9916c23 5023static inline void gen_intermediate_code_internal(S390CPU *cpu,
e023e832 5024 TranslationBlock *tb,
d9916c23 5025 bool search_pc)
e023e832 5026{
ed2803da 5027 CPUState *cs = CPU(cpu);
d9916c23 5028 CPUS390XState *env = &cpu->env;
e023e832
AG
5029 DisasContext dc;
5030 target_ulong pc_start;
5031 uint64_t next_page_start;
e023e832
AG
5032 int j, lj = -1;
5033 int num_insns, max_insns;
5034 CPUBreakpoint *bp;
ad044d09 5035 ExitStatus status;
d5a103cd 5036 bool do_debug;
e023e832
AG
5037
5038 pc_start = tb->pc;
5039
5040 /* 31-bit mode */
5041 if (!(tb->flags & FLAG_MASK_64)) {
5042 pc_start &= 0x7fffffff;
5043 }
5044
e023e832 5045 dc.tb = tb;
ad044d09 5046 dc.pc = pc_start;
e023e832 5047 dc.cc_op = CC_OP_DYNAMIC;
ed2803da 5048 do_debug = dc.singlestep_enabled = cs->singlestep_enabled;
e023e832 5049
e023e832
AG
5050 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
5051
5052 num_insns = 0;
5053 max_insns = tb->cflags & CF_COUNT_MASK;
5054 if (max_insns == 0) {
5055 max_insns = CF_COUNT_MASK;
5056 }
5057
cd42d5b2 5058 gen_tb_start(tb);
e023e832
AG
5059
5060 do {
e023e832 5061 if (search_pc) {
fe700adb 5062 j = tcg_op_buf_count();
e023e832
AG
5063 if (lj < j) {
5064 lj++;
5065 while (lj < j) {
ab1103de 5066 tcg_ctx.gen_opc_instr_start[lj++] = 0;
e023e832
AG
5067 }
5068 }
25983cad 5069 tcg_ctx.gen_opc_pc[lj] = dc.pc;
e023e832 5070 gen_opc_cc_op[lj] = dc.cc_op;
ab1103de 5071 tcg_ctx.gen_opc_instr_start[lj] = 1;
c9c99c22 5072 tcg_ctx.gen_opc_icount[lj] = num_insns;
e023e832 5073 }
ad044d09 5074 if (++num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
e023e832
AG
5075 gen_io_start();
5076 }
7193b5f6
RH
5077
5078 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
5079 tcg_gen_debug_insn_start(dc.pc);
5080 }
5081
d5a103cd 5082 status = NO_EXIT;
f0c3c505
AF
5083 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
5084 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
d5a103cd
RH
5085 if (bp->pc == dc.pc) {
5086 status = EXIT_PC_STALE;
5087 do_debug = true;
5088 break;
5089 }
5090 }
5091 }
5092 if (status == NO_EXIT) {
5093 status = translate_one(env, &dc);
5094 }
ad044d09
RH
5095
5096 /* If we reach a page boundary, are single stepping,
5097 or exhaust instruction count, stop generation. */
5098 if (status == NO_EXIT
5099 && (dc.pc >= next_page_start
fe700adb 5100 || tcg_op_buf_full()
ad044d09
RH
5101 || num_insns >= max_insns
5102 || singlestep
ed2803da 5103 || cs->singlestep_enabled)) {
ad044d09 5104 status = EXIT_PC_STALE;
e023e832 5105 }
ad044d09 5106 } while (status == NO_EXIT);
e023e832
AG
5107
5108 if (tb->cflags & CF_LAST_IO) {
5109 gen_io_end();
5110 }
ad044d09
RH
5111
5112 switch (status) {
5113 case EXIT_GOTO_TB:
5114 case EXIT_NORETURN:
5115 break;
5116 case EXIT_PC_STALE:
5117 update_psw_addr(&dc);
5118 /* FALLTHRU */
5119 case EXIT_PC_UPDATED:
7a6c7067
RH
5120 /* Next TB starts off with CC_OP_DYNAMIC, so make sure the
5121 cc op type is in env */
5122 update_cc_op(&dc);
5123 /* Exit the TB, either by raising a debug exception or by return. */
d5a103cd
RH
5124 if (do_debug) {
5125 gen_exception(EXCP_DEBUG);
ad044d09 5126 } else {
ad044d09
RH
5127 tcg_gen_exit_tb(0);
5128 }
5129 break;
5130 default:
5131 abort();
e023e832 5132 }
ad044d09 5133
806f352d 5134 gen_tb_end(tb, num_insns);
0a7df5da 5135
e023e832 5136 if (search_pc) {
fe700adb 5137 j = tcg_op_buf_count();
e023e832
AG
5138 lj++;
5139 while (lj <= j) {
ab1103de 5140 tcg_ctx.gen_opc_instr_start[lj++] = 0;
e023e832
AG
5141 }
5142 } else {
5143 tb->size = dc.pc - pc_start;
5144 tb->icount = num_insns;
5145 }
ad044d09 5146
e023e832 5147#if defined(S390X_DEBUG_DISAS)
e023e832
AG
5148 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
5149 qemu_log("IN: %s\n", lookup_symbol(pc_start));
f4359b9f 5150 log_target_disas(env, pc_start, dc.pc - pc_start, 1);
e023e832
AG
5151 qemu_log("\n");
5152 }
5153#endif
5154}
5155
a4e3ad19 5156void gen_intermediate_code (CPUS390XState *env, struct TranslationBlock *tb)
e023e832 5157{
d9916c23 5158 gen_intermediate_code_internal(s390_env_get_cpu(env), tb, false);
e023e832
AG
5159}
5160
a4e3ad19 5161void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb)
e023e832 5162{
d9916c23 5163 gen_intermediate_code_internal(s390_env_get_cpu(env), tb, true);
e023e832
AG
5164}
5165
a4e3ad19 5166void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos)
e023e832
AG
5167{
5168 int cc_op;
25983cad 5169 env->psw.addr = tcg_ctx.gen_opc_pc[pc_pos];
e023e832
AG
5170 cc_op = gen_opc_cc_op[pc_pos];
5171 if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) {
5172 env->cc_op = cc_op;
5173 }
10ec5117 5174}