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