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