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