|
|
1.1 root 1: /*
2: * S/390 translation
3: *
4: * Copyright (c) 2009 Ulrich Hecht
1.1.1.4 root 5: * Copyright (c) 2010 Alexander Graf
1.1 root 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
1.1.1.2 root 18: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 19: */
1.1.1.4 root 20:
21: /* #define DEBUG_ILLEGAL_INSTRUCTIONS */
22: /* #define DEBUG_INLINE_BRANCHES */
23: #define S390X_DEBUG_DISAS
24: /* #define S390X_DEBUG_DISAS_VERBOSE */
25:
26: #ifdef S390X_DEBUG_DISAS_VERBOSE
27: # define LOG_DISAS(...) qemu_log(__VA_ARGS__)
28: #else
29: # define LOG_DISAS(...) do { } while (0)
30: #endif
1.1 root 31:
32: #include "cpu.h"
33: #include "disas.h"
34: #include "tcg-op.h"
35: #include "qemu-log.h"
36:
1.1.1.4 root 37: /* global register indexes */
38: static TCGv_ptr cpu_env;
39:
40: #include "gen-icount.h"
1.1.1.6 ! root 41: #include "helper.h"
1.1.1.4 root 42: #define GEN_HELPER 1
1.1.1.6 ! root 43: #include "helper.h"
1.1.1.4 root 44:
45: typedef struct DisasContext DisasContext;
46: struct DisasContext {
47: uint64_t pc;
48: int is_jmp;
49: enum cc_op cc_op;
50: struct TranslationBlock *tb;
51: };
52:
53: #define DISAS_EXCP 4
54:
55: static void gen_op_calc_cc(DisasContext *s);
56:
57: #ifdef DEBUG_INLINE_BRANCHES
58: static uint64_t inline_branch_hit[CC_OP_MAX];
59: static uint64_t inline_branch_miss[CC_OP_MAX];
60: #endif
61:
62: static inline void debug_insn(uint64_t insn)
63: {
64: LOG_DISAS("insn: 0x%" PRIx64 "\n", insn);
65: }
66:
67: static inline uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
68: {
69: if (!(s->tb->flags & FLAG_MASK_64)) {
70: if (s->tb->flags & FLAG_MASK_32) {
71: return pc | 0x80000000;
72: }
73: }
74: return pc;
75: }
76:
1.1.1.6 ! root 77: void cpu_dump_state(CPUS390XState *env, FILE *f, fprintf_function cpu_fprintf,
1.1 root 78: int flags)
79: {
80: int i;
1.1.1.4 root 81:
82: for (i = 0; i < 16; i++) {
83: cpu_fprintf(f, "R%02d=%016" PRIx64, i, env->regs[i]);
84: if ((i % 4) == 3) {
85: cpu_fprintf(f, "\n");
86: } else {
87: cpu_fprintf(f, " ");
88: }
89: }
90:
1.1 root 91: for (i = 0; i < 16; i++) {
1.1.1.4 root 92: cpu_fprintf(f, "F%02d=%016" PRIx64, i, *(uint64_t *)&env->fregs[i]);
1.1 root 93: if ((i % 4) == 3) {
94: cpu_fprintf(f, "\n");
95: } else {
96: cpu_fprintf(f, " ");
97: }
98: }
1.1.1.4 root 99:
100: cpu_fprintf(f, "\n");
101:
102: #ifndef CONFIG_USER_ONLY
1.1 root 103: for (i = 0; i < 16; i++) {
1.1.1.4 root 104: cpu_fprintf(f, "C%02d=%016" PRIx64, i, env->cregs[i]);
1.1 root 105: if ((i % 4) == 3) {
106: cpu_fprintf(f, "\n");
107: } else {
108: cpu_fprintf(f, " ");
109: }
110: }
1.1.1.4 root 111: #endif
112:
113: cpu_fprintf(f, "\n");
114:
115: if (env->cc_op > 3) {
116: cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %15s\n",
117: env->psw.mask, env->psw.addr, cc_name(env->cc_op));
118: } else {
119: cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %02x\n",
120: env->psw.mask, env->psw.addr, env->cc_op);
121: }
122:
123: #ifdef DEBUG_INLINE_BRANCHES
124: for (i = 0; i < CC_OP_MAX; i++) {
125: cpu_fprintf(f, " %15s = %10ld\t%10ld\n", cc_name(i),
126: inline_branch_miss[i], inline_branch_hit[i]);
127: }
128: #endif
1.1 root 129: }
130:
1.1.1.4 root 131: static TCGv_i64 psw_addr;
132: static TCGv_i64 psw_mask;
133:
134: static TCGv_i32 cc_op;
135: static TCGv_i64 cc_src;
136: static TCGv_i64 cc_dst;
137: static TCGv_i64 cc_vr;
138:
139: static char cpu_reg_names[10*3 + 6*4];
140: static TCGv_i64 regs[16];
141:
142: static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
143:
144: void s390x_translate_init(void)
145: {
146: int i;
147: size_t cpu_reg_names_size = sizeof(cpu_reg_names);
148: char *p;
149:
150: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1.1.1.6 ! root 151: psw_addr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, psw.addr),
1.1.1.4 root 152: "psw_addr");
1.1.1.6 ! root 153: psw_mask = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, psw.mask),
1.1.1.4 root 154: "psw_mask");
155:
1.1.1.6 ! root 156: cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUS390XState, cc_op),
1.1.1.4 root 157: "cc_op");
1.1.1.6 ! root 158: cc_src = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_src),
1.1.1.4 root 159: "cc_src");
1.1.1.6 ! root 160: cc_dst = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_dst),
1.1.1.4 root 161: "cc_dst");
1.1.1.6 ! root 162: cc_vr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_vr),
1.1.1.4 root 163: "cc_vr");
164:
165: p = cpu_reg_names;
166: for (i = 0; i < 16; i++) {
167: snprintf(p, cpu_reg_names_size, "r%d", i);
168: regs[i] = tcg_global_mem_new(TCG_AREG0,
1.1.1.6 ! root 169: offsetof(CPUS390XState, regs[i]), p);
1.1.1.4 root 170: p += (i < 10) ? 3 : 4;
171: cpu_reg_names_size -= (i < 10) ? 3 : 4;
172: }
173: }
174:
175: static inline TCGv_i64 load_reg(int reg)
1.1 root 176: {
1.1.1.4 root 177: TCGv_i64 r = tcg_temp_new_i64();
178: tcg_gen_mov_i64(r, regs[reg]);
179: return r;
1.1 root 180: }
181:
1.1.1.4 root 182: static inline TCGv_i64 load_freg(int reg)
1.1 root 183: {
1.1.1.4 root 184: TCGv_i64 r = tcg_temp_new_i64();
1.1.1.6 ! root 185: tcg_gen_ld_i64(r, cpu_env, offsetof(CPUS390XState, fregs[reg].d));
1.1.1.4 root 186: return r;
1.1 root 187: }
188:
1.1.1.4 root 189: static inline TCGv_i32 load_freg32(int reg)
1.1 root 190: {
1.1.1.4 root 191: TCGv_i32 r = tcg_temp_new_i32();
1.1.1.6 ! root 192: tcg_gen_ld_i32(r, cpu_env, offsetof(CPUS390XState, fregs[reg].l.upper));
1.1.1.4 root 193: return r;
194: }
195:
196: static inline TCGv_i32 load_reg32(int reg)
197: {
198: TCGv_i32 r = tcg_temp_new_i32();
199: tcg_gen_trunc_i64_i32(r, regs[reg]);
200: return r;
201: }
202:
203: static inline TCGv_i64 load_reg32_i64(int reg)
204: {
205: TCGv_i64 r = tcg_temp_new_i64();
206: tcg_gen_ext32s_i64(r, regs[reg]);
207: return r;
208: }
209:
210: static inline void store_reg(int reg, TCGv_i64 v)
211: {
212: tcg_gen_mov_i64(regs[reg], v);
213: }
214:
215: static inline void store_freg(int reg, TCGv_i64 v)
216: {
1.1.1.6 ! root 217: tcg_gen_st_i64(v, cpu_env, offsetof(CPUS390XState, fregs[reg].d));
1.1.1.4 root 218: }
219:
220: static inline void store_reg32(int reg, TCGv_i32 v)
221: {
222: #if HOST_LONG_BITS == 32
223: tcg_gen_mov_i32(TCGV_LOW(regs[reg]), v);
224: #else
225: TCGv_i64 tmp = tcg_temp_new_i64();
226: tcg_gen_extu_i32_i64(tmp, v);
227: /* 32 bit register writes keep the upper half */
228: tcg_gen_deposit_i64(regs[reg], regs[reg], tmp, 0, 32);
229: tcg_temp_free_i64(tmp);
230: #endif
231: }
232:
233: static inline void store_reg32_i64(int reg, TCGv_i64 v)
234: {
235: /* 32 bit register writes keep the upper half */
236: #if HOST_LONG_BITS == 32
237: tcg_gen_mov_i32(TCGV_LOW(regs[reg]), TCGV_LOW(v));
238: #else
239: tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
240: #endif
241: }
242:
243: static inline void store_reg16(int reg, TCGv_i32 v)
244: {
245: TCGv_i64 tmp = tcg_temp_new_i64();
246: tcg_gen_extu_i32_i64(tmp, v);
247: /* 16 bit register writes keep the upper bytes */
248: tcg_gen_deposit_i64(regs[reg], regs[reg], tmp, 0, 16);
249: tcg_temp_free_i64(tmp);
250: }
251:
252: static inline void store_reg8(int reg, TCGv_i64 v)
253: {
254: /* 8 bit register writes keep the upper bytes */
255: tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 8);
256: }
257:
258: static inline void store_freg32(int reg, TCGv_i32 v)
259: {
1.1.1.6 ! root 260: tcg_gen_st_i32(v, cpu_env, offsetof(CPUS390XState, fregs[reg].l.upper));
1.1.1.4 root 261: }
262:
263: static inline void update_psw_addr(DisasContext *s)
264: {
265: /* psw.addr */
266: tcg_gen_movi_i64(psw_addr, s->pc);
267: }
268:
269: static inline void potential_page_fault(DisasContext *s)
270: {
271: #ifndef CONFIG_USER_ONLY
272: update_psw_addr(s);
273: gen_op_calc_cc(s);
274: #endif
275: }
276:
277: static inline uint64_t ld_code2(uint64_t pc)
278: {
279: return (uint64_t)lduw_code(pc);
280: }
281:
282: static inline uint64_t ld_code4(uint64_t pc)
283: {
284: return (uint64_t)ldl_code(pc);
285: }
286:
287: static inline uint64_t ld_code6(uint64_t pc)
288: {
289: uint64_t opc;
290: opc = (uint64_t)lduw_code(pc) << 32;
291: opc |= (uint64_t)(uint32_t)ldl_code(pc+2);
292: return opc;
293: }
294:
295: static inline int get_mem_index(DisasContext *s)
296: {
297: switch (s->tb->flags & FLAG_MASK_ASC) {
298: case PSW_ASC_PRIMARY >> 32:
299: return 0;
300: case PSW_ASC_SECONDARY >> 32:
301: return 1;
302: case PSW_ASC_HOME >> 32:
303: return 2;
304: default:
305: tcg_abort();
306: break;
307: }
308: }
309:
310: static inline void gen_debug(DisasContext *s)
311: {
312: TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
313: update_psw_addr(s);
314: gen_op_calc_cc(s);
315: gen_helper_exception(tmp);
316: tcg_temp_free_i32(tmp);
317: s->is_jmp = DISAS_EXCP;
318: }
319:
320: #ifdef CONFIG_USER_ONLY
321:
322: static void gen_illegal_opcode(DisasContext *s, int ilc)
323: {
324: TCGv_i32 tmp = tcg_const_i32(EXCP_SPEC);
325: update_psw_addr(s);
326: gen_op_calc_cc(s);
327: gen_helper_exception(tmp);
328: tcg_temp_free_i32(tmp);
329: s->is_jmp = DISAS_EXCP;
330: }
331:
332: #else /* CONFIG_USER_ONLY */
333:
334: static void debug_print_inst(DisasContext *s, int ilc)
335: {
336: #ifdef DEBUG_ILLEGAL_INSTRUCTIONS
337: uint64_t inst = 0;
338:
339: switch (ilc & 3) {
340: case 1:
341: inst = ld_code2(s->pc);
342: break;
343: case 2:
344: inst = ld_code4(s->pc);
345: break;
346: case 3:
347: inst = ld_code6(s->pc);
348: break;
349: }
350:
351: fprintf(stderr, "Illegal instruction [%d at %016" PRIx64 "]: 0x%016"
352: PRIx64 "\n", ilc, s->pc, inst);
353: #endif
354: }
355:
356: static void gen_program_exception(DisasContext *s, int ilc, int code)
357: {
358: TCGv_i32 tmp;
359:
360: debug_print_inst(s, ilc);
361:
362: /* remember what pgm exeption this was */
363: tmp = tcg_const_i32(code);
1.1.1.6 ! root 364: tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
1.1.1.4 root 365: tcg_temp_free_i32(tmp);
366:
367: tmp = tcg_const_i32(ilc);
1.1.1.6 ! root 368: tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilc));
1.1.1.4 root 369: tcg_temp_free_i32(tmp);
370:
371: /* advance past instruction */
372: s->pc += (ilc * 2);
373: update_psw_addr(s);
374:
375: /* save off cc */
376: gen_op_calc_cc(s);
377:
378: /* trigger exception */
379: tmp = tcg_const_i32(EXCP_PGM);
380: gen_helper_exception(tmp);
381: tcg_temp_free_i32(tmp);
382:
383: /* end TB here */
384: s->is_jmp = DISAS_EXCP;
385: }
386:
387:
388: static void gen_illegal_opcode(DisasContext *s, int ilc)
389: {
390: gen_program_exception(s, ilc, PGM_SPECIFICATION);
391: }
392:
393: static void gen_privileged_exception(DisasContext *s, int ilc)
394: {
395: gen_program_exception(s, ilc, PGM_PRIVILEGED);
396: }
397:
398: static void check_privileged(DisasContext *s, int ilc)
399: {
400: if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
401: gen_privileged_exception(s, ilc);
402: }
403: }
404:
405: #endif /* CONFIG_USER_ONLY */
406:
407: static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
408: {
409: TCGv_i64 tmp;
410:
411: /* 31-bitify the immediate part; register contents are dealt with below */
412: if (!(s->tb->flags & FLAG_MASK_64)) {
413: d2 &= 0x7fffffffUL;
414: }
415:
416: if (x2) {
417: if (d2) {
418: tmp = tcg_const_i64(d2);
419: tcg_gen_add_i64(tmp, tmp, regs[x2]);
420: } else {
421: tmp = load_reg(x2);
422: }
423: if (b2) {
424: tcg_gen_add_i64(tmp, tmp, regs[b2]);
425: }
426: } else if (b2) {
427: if (d2) {
428: tmp = tcg_const_i64(d2);
429: tcg_gen_add_i64(tmp, tmp, regs[b2]);
430: } else {
431: tmp = load_reg(b2);
432: }
433: } else {
434: tmp = tcg_const_i64(d2);
435: }
436:
437: /* 31-bit mode mask if there are values loaded from registers */
438: if (!(s->tb->flags & FLAG_MASK_64) && (x2 || b2)) {
439: tcg_gen_andi_i64(tmp, tmp, 0x7fffffffUL);
440: }
441:
442: return tmp;
443: }
444:
445: static void gen_op_movi_cc(DisasContext *s, uint32_t val)
446: {
447: s->cc_op = CC_OP_CONST0 + val;
448: }
449:
450: static void gen_op_update1_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 dst)
451: {
452: tcg_gen_discard_i64(cc_src);
453: tcg_gen_mov_i64(cc_dst, dst);
454: tcg_gen_discard_i64(cc_vr);
455: s->cc_op = op;
456: }
457:
458: static void gen_op_update1_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 dst)
459: {
460: tcg_gen_discard_i64(cc_src);
461: tcg_gen_extu_i32_i64(cc_dst, dst);
462: tcg_gen_discard_i64(cc_vr);
463: s->cc_op = op;
464: }
465:
466: static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
467: TCGv_i64 dst)
468: {
469: tcg_gen_mov_i64(cc_src, src);
470: tcg_gen_mov_i64(cc_dst, dst);
471: tcg_gen_discard_i64(cc_vr);
472: s->cc_op = op;
473: }
474:
475: static void gen_op_update2_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 src,
476: TCGv_i32 dst)
477: {
478: tcg_gen_extu_i32_i64(cc_src, src);
479: tcg_gen_extu_i32_i64(cc_dst, dst);
480: tcg_gen_discard_i64(cc_vr);
481: s->cc_op = op;
482: }
483:
484: static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
485: TCGv_i64 dst, TCGv_i64 vr)
486: {
487: tcg_gen_mov_i64(cc_src, src);
488: tcg_gen_mov_i64(cc_dst, dst);
489: tcg_gen_mov_i64(cc_vr, vr);
490: s->cc_op = op;
491: }
492:
493: static void gen_op_update3_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 src,
494: TCGv_i32 dst, TCGv_i32 vr)
495: {
496: tcg_gen_extu_i32_i64(cc_src, src);
497: tcg_gen_extu_i32_i64(cc_dst, dst);
498: tcg_gen_extu_i32_i64(cc_vr, vr);
499: s->cc_op = op;
500: }
501:
502: static inline void set_cc_nz_u32(DisasContext *s, TCGv_i32 val)
503: {
504: gen_op_update1_cc_i32(s, CC_OP_NZ, val);
505: }
506:
507: static inline void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
508: {
509: gen_op_update1_cc_i64(s, CC_OP_NZ, val);
510: }
511:
512: static inline void cmp_32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
513: enum cc_op cond)
514: {
515: gen_op_update2_cc_i32(s, cond, v1, v2);
516: }
517:
518: static inline void cmp_64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
519: enum cc_op cond)
520: {
521: gen_op_update2_cc_i64(s, cond, v1, v2);
522: }
523:
524: static inline void cmp_s32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
525: {
526: cmp_32(s, v1, v2, CC_OP_LTGT_32);
527: }
528:
529: static inline void cmp_u32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
530: {
531: cmp_32(s, v1, v2, CC_OP_LTUGTU_32);
532: }
533:
534: static inline void cmp_s32c(DisasContext *s, TCGv_i32 v1, int32_t v2)
535: {
536: /* XXX optimize for the constant? put it in s? */
537: TCGv_i32 tmp = tcg_const_i32(v2);
538: cmp_32(s, v1, tmp, CC_OP_LTGT_32);
539: tcg_temp_free_i32(tmp);
540: }
541:
542: static inline void cmp_u32c(DisasContext *s, TCGv_i32 v1, uint32_t v2)
543: {
544: TCGv_i32 tmp = tcg_const_i32(v2);
545: cmp_32(s, v1, tmp, CC_OP_LTUGTU_32);
546: tcg_temp_free_i32(tmp);
547: }
548:
549: static inline void cmp_s64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2)
550: {
551: cmp_64(s, v1, v2, CC_OP_LTGT_64);
552: }
553:
554: static inline void cmp_u64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2)
555: {
556: cmp_64(s, v1, v2, CC_OP_LTUGTU_64);
557: }
558:
559: static inline void cmp_s64c(DisasContext *s, TCGv_i64 v1, int64_t v2)
560: {
561: TCGv_i64 tmp = tcg_const_i64(v2);
562: cmp_s64(s, v1, tmp);
563: tcg_temp_free_i64(tmp);
564: }
565:
566: static inline void cmp_u64c(DisasContext *s, TCGv_i64 v1, uint64_t v2)
567: {
568: TCGv_i64 tmp = tcg_const_i64(v2);
569: cmp_u64(s, v1, tmp);
570: tcg_temp_free_i64(tmp);
571: }
572:
573: static inline void set_cc_s32(DisasContext *s, TCGv_i32 val)
574: {
575: gen_op_update1_cc_i32(s, CC_OP_LTGT0_32, val);
576: }
577:
578: static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
579: {
580: gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
581: }
582:
583: static void set_cc_add64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2, TCGv_i64 vr)
584: {
585: gen_op_update3_cc_i64(s, CC_OP_ADD_64, v1, v2, vr);
586: }
587:
588: static void set_cc_addu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
589: TCGv_i64 vr)
590: {
591: gen_op_update3_cc_i64(s, CC_OP_ADDU_64, v1, v2, vr);
592: }
593:
594: static void set_cc_sub64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2, TCGv_i64 vr)
595: {
596: gen_op_update3_cc_i64(s, CC_OP_SUB_64, v1, v2, vr);
597: }
598:
599: static void set_cc_subu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
600: TCGv_i64 vr)
601: {
602: gen_op_update3_cc_i64(s, CC_OP_SUBU_64, v1, v2, vr);
603: }
604:
605: static void set_cc_abs64(DisasContext *s, TCGv_i64 v1)
606: {
607: gen_op_update1_cc_i64(s, CC_OP_ABS_64, v1);
608: }
609:
610: static void set_cc_nabs64(DisasContext *s, TCGv_i64 v1)
611: {
612: gen_op_update1_cc_i64(s, CC_OP_NABS_64, v1);
613: }
614:
615: static void set_cc_add32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2, TCGv_i32 vr)
616: {
617: gen_op_update3_cc_i32(s, CC_OP_ADD_32, v1, v2, vr);
618: }
619:
620: static void set_cc_addu32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
621: TCGv_i32 vr)
622: {
623: gen_op_update3_cc_i32(s, CC_OP_ADDU_32, v1, v2, vr);
624: }
625:
626: static void set_cc_sub32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2, TCGv_i32 vr)
627: {
628: gen_op_update3_cc_i32(s, CC_OP_SUB_32, v1, v2, vr);
629: }
630:
631: static void set_cc_subu32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
632: TCGv_i32 vr)
633: {
634: gen_op_update3_cc_i32(s, CC_OP_SUBU_32, v1, v2, vr);
635: }
636:
637: static void set_cc_abs32(DisasContext *s, TCGv_i32 v1)
638: {
639: gen_op_update1_cc_i32(s, CC_OP_ABS_32, v1);
640: }
641:
642: static void set_cc_nabs32(DisasContext *s, TCGv_i32 v1)
643: {
644: gen_op_update1_cc_i32(s, CC_OP_NABS_32, v1);
645: }
646:
647: static void set_cc_comp32(DisasContext *s, TCGv_i32 v1)
648: {
649: gen_op_update1_cc_i32(s, CC_OP_COMP_32, v1);
650: }
651:
652: static void set_cc_comp64(DisasContext *s, TCGv_i64 v1)
653: {
654: gen_op_update1_cc_i64(s, CC_OP_COMP_64, v1);
655: }
656:
657: static void set_cc_icm(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
658: {
659: gen_op_update2_cc_i32(s, CC_OP_ICM, v1, v2);
660: }
661:
662: static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2)
663: {
664: tcg_gen_extu_i32_i64(cc_src, v1);
665: tcg_gen_mov_i64(cc_dst, v2);
666: tcg_gen_discard_i64(cc_vr);
667: s->cc_op = CC_OP_LTGT_F32;
668: }
669:
670: static void set_cc_nz_f32(DisasContext *s, TCGv_i32 v1)
671: {
672: gen_op_update1_cc_i32(s, CC_OP_NZ_F32, v1);
673: }
674:
675: static inline void set_cc_nz_f64(DisasContext *s, TCGv_i64 v1)
676: {
677: gen_op_update1_cc_i64(s, CC_OP_NZ_F64, v1);
678: }
679:
680: /* CC value is in env->cc_op */
681: static inline void set_cc_static(DisasContext *s)
682: {
683: tcg_gen_discard_i64(cc_src);
684: tcg_gen_discard_i64(cc_dst);
685: tcg_gen_discard_i64(cc_vr);
686: s->cc_op = CC_OP_STATIC;
687: }
688:
689: static inline void gen_op_set_cc_op(DisasContext *s)
690: {
691: if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
692: tcg_gen_movi_i32(cc_op, s->cc_op);
693: }
694: }
695:
696: static inline void gen_update_cc_op(DisasContext *s)
697: {
698: gen_op_set_cc_op(s);
699: }
700:
701: /* calculates cc into cc_op */
702: static void gen_op_calc_cc(DisasContext *s)
703: {
704: TCGv_i32 local_cc_op = tcg_const_i32(s->cc_op);
705: TCGv_i64 dummy = tcg_const_i64(0);
706:
707: switch (s->cc_op) {
708: case CC_OP_CONST0:
709: case CC_OP_CONST1:
710: case CC_OP_CONST2:
711: case CC_OP_CONST3:
712: /* s->cc_op is the cc value */
713: tcg_gen_movi_i32(cc_op, s->cc_op - CC_OP_CONST0);
714: break;
715: case CC_OP_STATIC:
716: /* env->cc_op already is the cc value */
717: break;
718: case CC_OP_NZ:
719: case CC_OP_ABS_64:
720: case CC_OP_NABS_64:
721: case CC_OP_ABS_32:
722: case CC_OP_NABS_32:
723: case CC_OP_LTGT0_32:
724: case CC_OP_LTGT0_64:
725: case CC_OP_COMP_32:
726: case CC_OP_COMP_64:
727: case CC_OP_NZ_F32:
728: case CC_OP_NZ_F64:
729: /* 1 argument */
730: gen_helper_calc_cc(cc_op, local_cc_op, dummy, cc_dst, dummy);
731: break;
732: case CC_OP_ICM:
733: case CC_OP_LTGT_32:
734: case CC_OP_LTGT_64:
735: case CC_OP_LTUGTU_32:
736: case CC_OP_LTUGTU_64:
737: case CC_OP_TM_32:
738: case CC_OP_TM_64:
739: case CC_OP_LTGT_F32:
740: case CC_OP_LTGT_F64:
741: case CC_OP_SLAG:
742: /* 2 arguments */
743: gen_helper_calc_cc(cc_op, local_cc_op, cc_src, cc_dst, dummy);
744: break;
745: case CC_OP_ADD_64:
746: case CC_OP_ADDU_64:
747: case CC_OP_SUB_64:
748: case CC_OP_SUBU_64:
749: case CC_OP_ADD_32:
750: case CC_OP_ADDU_32:
751: case CC_OP_SUB_32:
752: case CC_OP_SUBU_32:
753: /* 3 arguments */
754: gen_helper_calc_cc(cc_op, local_cc_op, cc_src, cc_dst, cc_vr);
755: break;
756: case CC_OP_DYNAMIC:
757: /* unknown operation - assume 3 arguments and cc_op in env */
758: gen_helper_calc_cc(cc_op, cc_op, cc_src, cc_dst, cc_vr);
759: break;
760: default:
761: tcg_abort();
762: }
763:
764: tcg_temp_free_i32(local_cc_op);
765:
766: /* We now have cc in cc_op as constant */
767: set_cc_static(s);
768: }
769:
770: static inline void decode_rr(DisasContext *s, uint64_t insn, int *r1, int *r2)
771: {
772: debug_insn(insn);
773:
774: *r1 = (insn >> 4) & 0xf;
775: *r2 = insn & 0xf;
776: }
777:
778: static inline TCGv_i64 decode_rx(DisasContext *s, uint64_t insn, int *r1,
779: int *x2, int *b2, int *d2)
780: {
781: debug_insn(insn);
782:
783: *r1 = (insn >> 20) & 0xf;
784: *x2 = (insn >> 16) & 0xf;
785: *b2 = (insn >> 12) & 0xf;
786: *d2 = insn & 0xfff;
787:
788: return get_address(s, *x2, *b2, *d2);
789: }
790:
791: static inline void decode_rs(DisasContext *s, uint64_t insn, int *r1, int *r3,
792: int *b2, int *d2)
793: {
794: debug_insn(insn);
795:
796: *r1 = (insn >> 20) & 0xf;
797: /* aka m3 */
798: *r3 = (insn >> 16) & 0xf;
799: *b2 = (insn >> 12) & 0xf;
800: *d2 = insn & 0xfff;
801: }
802:
803: static inline TCGv_i64 decode_si(DisasContext *s, uint64_t insn, int *i2,
804: int *b1, int *d1)
805: {
806: debug_insn(insn);
807:
808: *i2 = (insn >> 16) & 0xff;
809: *b1 = (insn >> 12) & 0xf;
810: *d1 = insn & 0xfff;
811:
812: return get_address(s, 0, *b1, *d1);
813: }
814:
815: static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc)
816: {
817: TranslationBlock *tb;
818:
819: gen_update_cc_op(s);
820:
821: tb = s->tb;
822: /* NOTE: we handle the case where the TB spans two pages here */
823: if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
824: (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
825: /* jump to same page: we can use a direct jump */
826: tcg_gen_goto_tb(tb_num);
827: tcg_gen_movi_i64(psw_addr, pc);
1.1.1.5 root 828: tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
1.1.1.4 root 829: } else {
830: /* jump to another page: currently not optimized */
831: tcg_gen_movi_i64(psw_addr, pc);
832: tcg_gen_exit_tb(0);
833: }
834: }
835:
836: static inline void account_noninline_branch(DisasContext *s, int cc_op)
837: {
838: #ifdef DEBUG_INLINE_BRANCHES
839: inline_branch_miss[cc_op]++;
840: #endif
841: }
842:
843: static inline void account_inline_branch(DisasContext *s)
844: {
845: #ifdef DEBUG_INLINE_BRANCHES
846: inline_branch_hit[s->cc_op]++;
847: #endif
848: }
849:
850: static void gen_jcc(DisasContext *s, uint32_t mask, int skip)
851: {
852: TCGv_i32 tmp, tmp2, r;
853: TCGv_i64 tmp64;
854: int old_cc_op;
855:
856: switch (s->cc_op) {
857: case CC_OP_LTGT0_32:
858: tmp = tcg_temp_new_i32();
859: tcg_gen_trunc_i64_i32(tmp, cc_dst);
860: switch (mask) {
861: case 0x8 | 0x4: /* dst <= 0 */
862: tcg_gen_brcondi_i32(TCG_COND_GT, tmp, 0, skip);
863: break;
864: case 0x8 | 0x2: /* dst >= 0 */
865: tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, skip);
866: break;
867: case 0x8: /* dst == 0 */
868: tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, skip);
869: break;
870: case 0x7: /* dst != 0 */
871: case 0x6: /* dst != 0 */
872: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, skip);
873: break;
874: case 0x4: /* dst < 0 */
875: tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, skip);
876: break;
877: case 0x2: /* dst > 0 */
878: tcg_gen_brcondi_i32(TCG_COND_LE, tmp, 0, skip);
879: break;
880: default:
881: tcg_temp_free_i32(tmp);
882: goto do_dynamic;
883: }
884: account_inline_branch(s);
885: tcg_temp_free_i32(tmp);
886: break;
887: case CC_OP_LTGT0_64:
888: switch (mask) {
889: case 0x8 | 0x4: /* dst <= 0 */
890: tcg_gen_brcondi_i64(TCG_COND_GT, cc_dst, 0, skip);
891: break;
892: case 0x8 | 0x2: /* dst >= 0 */
893: tcg_gen_brcondi_i64(TCG_COND_LT, cc_dst, 0, skip);
894: break;
895: case 0x8: /* dst == 0 */
896: tcg_gen_brcondi_i64(TCG_COND_NE, cc_dst, 0, skip);
897: break;
898: case 0x7: /* dst != 0 */
899: case 0x6: /* dst != 0 */
900: tcg_gen_brcondi_i64(TCG_COND_EQ, cc_dst, 0, skip);
901: break;
902: case 0x4: /* dst < 0 */
903: tcg_gen_brcondi_i64(TCG_COND_GE, cc_dst, 0, skip);
904: break;
905: case 0x2: /* dst > 0 */
906: tcg_gen_brcondi_i64(TCG_COND_LE, cc_dst, 0, skip);
907: break;
908: default:
909: goto do_dynamic;
910: }
911: account_inline_branch(s);
912: break;
913: case CC_OP_LTGT_32:
914: tmp = tcg_temp_new_i32();
915: tmp2 = tcg_temp_new_i32();
916: tcg_gen_trunc_i64_i32(tmp, cc_src);
917: tcg_gen_trunc_i64_i32(tmp2, cc_dst);
918: switch (mask) {
919: case 0x8 | 0x4: /* src <= dst */
920: tcg_gen_brcond_i32(TCG_COND_GT, tmp, tmp2, skip);
921: break;
922: case 0x8 | 0x2: /* src >= dst */
923: tcg_gen_brcond_i32(TCG_COND_LT, tmp, tmp2, skip);
924: break;
925: case 0x8: /* src == dst */
926: tcg_gen_brcond_i32(TCG_COND_NE, tmp, tmp2, skip);
927: break;
928: case 0x7: /* src != dst */
929: case 0x6: /* src != dst */
930: tcg_gen_brcond_i32(TCG_COND_EQ, tmp, tmp2, skip);
931: break;
932: case 0x4: /* src < dst */
933: tcg_gen_brcond_i32(TCG_COND_GE, tmp, tmp2, skip);
934: break;
935: case 0x2: /* src > dst */
936: tcg_gen_brcond_i32(TCG_COND_LE, tmp, tmp2, skip);
937: break;
938: default:
939: tcg_temp_free_i32(tmp);
940: tcg_temp_free_i32(tmp2);
941: goto do_dynamic;
942: }
943: account_inline_branch(s);
944: tcg_temp_free_i32(tmp);
945: tcg_temp_free_i32(tmp2);
946: break;
947: case CC_OP_LTGT_64:
948: switch (mask) {
949: case 0x8 | 0x4: /* src <= dst */
950: tcg_gen_brcond_i64(TCG_COND_GT, cc_src, cc_dst, skip);
951: break;
952: case 0x8 | 0x2: /* src >= dst */
953: tcg_gen_brcond_i64(TCG_COND_LT, cc_src, cc_dst, skip);
954: break;
955: case 0x8: /* src == dst */
956: tcg_gen_brcond_i64(TCG_COND_NE, cc_src, cc_dst, skip);
957: break;
958: case 0x7: /* src != dst */
959: case 0x6: /* src != dst */
960: tcg_gen_brcond_i64(TCG_COND_EQ, cc_src, cc_dst, skip);
961: break;
962: case 0x4: /* src < dst */
963: tcg_gen_brcond_i64(TCG_COND_GE, cc_src, cc_dst, skip);
964: break;
965: case 0x2: /* src > dst */
966: tcg_gen_brcond_i64(TCG_COND_LE, cc_src, cc_dst, skip);
967: break;
968: default:
969: goto do_dynamic;
970: }
971: account_inline_branch(s);
972: break;
973: case CC_OP_LTUGTU_32:
974: tmp = tcg_temp_new_i32();
975: tmp2 = tcg_temp_new_i32();
976: tcg_gen_trunc_i64_i32(tmp, cc_src);
977: tcg_gen_trunc_i64_i32(tmp2, cc_dst);
978: switch (mask) {
979: case 0x8 | 0x4: /* src <= dst */
980: tcg_gen_brcond_i32(TCG_COND_GTU, tmp, tmp2, skip);
981: break;
982: case 0x8 | 0x2: /* src >= dst */
983: tcg_gen_brcond_i32(TCG_COND_LTU, tmp, tmp2, skip);
984: break;
985: case 0x8: /* src == dst */
986: tcg_gen_brcond_i32(TCG_COND_NE, tmp, tmp2, skip);
987: break;
988: case 0x7: /* src != dst */
989: case 0x6: /* src != dst */
990: tcg_gen_brcond_i32(TCG_COND_EQ, tmp, tmp2, skip);
991: break;
992: case 0x4: /* src < dst */
993: tcg_gen_brcond_i32(TCG_COND_GEU, tmp, tmp2, skip);
994: break;
995: case 0x2: /* src > dst */
996: tcg_gen_brcond_i32(TCG_COND_LEU, tmp, tmp2, skip);
997: break;
998: default:
999: tcg_temp_free_i32(tmp);
1000: tcg_temp_free_i32(tmp2);
1001: goto do_dynamic;
1002: }
1003: account_inline_branch(s);
1004: tcg_temp_free_i32(tmp);
1005: tcg_temp_free_i32(tmp2);
1006: break;
1007: case CC_OP_LTUGTU_64:
1008: switch (mask) {
1009: case 0x8 | 0x4: /* src <= dst */
1010: tcg_gen_brcond_i64(TCG_COND_GTU, cc_src, cc_dst, skip);
1011: break;
1012: case 0x8 | 0x2: /* src >= dst */
1013: tcg_gen_brcond_i64(TCG_COND_LTU, cc_src, cc_dst, skip);
1014: break;
1015: case 0x8: /* src == dst */
1016: tcg_gen_brcond_i64(TCG_COND_NE, cc_src, cc_dst, skip);
1017: break;
1018: case 0x7: /* src != dst */
1019: case 0x6: /* src != dst */
1020: tcg_gen_brcond_i64(TCG_COND_EQ, cc_src, cc_dst, skip);
1021: break;
1022: case 0x4: /* src < dst */
1023: tcg_gen_brcond_i64(TCG_COND_GEU, cc_src, cc_dst, skip);
1024: break;
1025: case 0x2: /* src > dst */
1026: tcg_gen_brcond_i64(TCG_COND_LEU, cc_src, cc_dst, skip);
1027: break;
1028: default:
1029: goto do_dynamic;
1030: }
1031: account_inline_branch(s);
1032: break;
1033: case CC_OP_NZ:
1034: switch (mask) {
1035: /* dst == 0 || dst != 0 */
1036: case 0x8 | 0x4:
1037: case 0x8 | 0x4 | 0x2:
1038: case 0x8 | 0x4 | 0x2 | 0x1:
1039: case 0x8 | 0x4 | 0x1:
1040: break;
1041: /* dst == 0 */
1042: case 0x8:
1043: case 0x8 | 0x2:
1044: case 0x8 | 0x2 | 0x1:
1045: case 0x8 | 0x1:
1046: tcg_gen_brcondi_i64(TCG_COND_NE, cc_dst, 0, skip);
1047: break;
1048: /* dst != 0 */
1049: case 0x4:
1050: case 0x4 | 0x2:
1051: case 0x4 | 0x2 | 0x1:
1052: case 0x4 | 0x1:
1053: tcg_gen_brcondi_i64(TCG_COND_EQ, cc_dst, 0, skip);
1054: break;
1055: default:
1056: goto do_dynamic;
1057: }
1058: account_inline_branch(s);
1059: break;
1060: case CC_OP_TM_32:
1061: tmp = tcg_temp_new_i32();
1062: tmp2 = tcg_temp_new_i32();
1063:
1064: tcg_gen_trunc_i64_i32(tmp, cc_src);
1065: tcg_gen_trunc_i64_i32(tmp2, cc_dst);
1066: tcg_gen_and_i32(tmp, tmp, tmp2);
1067: switch (mask) {
1068: case 0x8: /* val & mask == 0 */
1069: tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, skip);
1070: break;
1071: case 0x4 | 0x2 | 0x1: /* val & mask != 0 */
1072: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, skip);
1073: break;
1074: default:
1075: tcg_temp_free_i32(tmp);
1076: tcg_temp_free_i32(tmp2);
1077: goto do_dynamic;
1078: }
1079: tcg_temp_free_i32(tmp);
1080: tcg_temp_free_i32(tmp2);
1081: account_inline_branch(s);
1082: break;
1083: case CC_OP_TM_64:
1084: tmp64 = tcg_temp_new_i64();
1085:
1086: tcg_gen_and_i64(tmp64, cc_src, cc_dst);
1087: switch (mask) {
1088: case 0x8: /* val & mask == 0 */
1089: tcg_gen_brcondi_i64(TCG_COND_NE, tmp64, 0, skip);
1090: break;
1091: case 0x4 | 0x2 | 0x1: /* val & mask != 0 */
1092: tcg_gen_brcondi_i64(TCG_COND_EQ, tmp64, 0, skip);
1093: break;
1094: default:
1095: tcg_temp_free_i64(tmp64);
1096: goto do_dynamic;
1097: }
1098: tcg_temp_free_i64(tmp64);
1099: account_inline_branch(s);
1100: break;
1101: case CC_OP_ICM:
1102: switch (mask) {
1103: case 0x8: /* val == 0 */
1104: tcg_gen_brcondi_i64(TCG_COND_NE, cc_dst, 0, skip);
1105: break;
1106: case 0x4 | 0x2 | 0x1: /* val != 0 */
1107: case 0x4 | 0x2: /* val != 0 */
1108: tcg_gen_brcondi_i64(TCG_COND_EQ, cc_dst, 0, skip);
1109: break;
1110: default:
1111: goto do_dynamic;
1112: }
1113: account_inline_branch(s);
1114: break;
1115: case CC_OP_STATIC:
1116: old_cc_op = s->cc_op;
1117: goto do_dynamic_nocccalc;
1118: case CC_OP_DYNAMIC:
1119: default:
1120: do_dynamic:
1121: old_cc_op = s->cc_op;
1122: /* calculate cc value */
1123: gen_op_calc_cc(s);
1124:
1125: do_dynamic_nocccalc:
1126: /* jump based on cc */
1127: account_noninline_branch(s, old_cc_op);
1128:
1129: switch (mask) {
1130: case 0x8 | 0x4 | 0x2 | 0x1:
1131: /* always true */
1132: break;
1133: case 0x8 | 0x4 | 0x2: /* cc != 3 */
1134: tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 3, skip);
1135: break;
1136: case 0x8 | 0x4 | 0x1: /* cc != 2 */
1137: tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 2, skip);
1138: break;
1139: case 0x8 | 0x2 | 0x1: /* cc != 1 */
1140: tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 1, skip);
1141: break;
1142: case 0x8 | 0x2: /* cc == 0 ||Â cc == 2 */
1143: tmp = tcg_temp_new_i32();
1144: tcg_gen_andi_i32(tmp, cc_op, 1);
1145: tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, skip);
1146: tcg_temp_free_i32(tmp);
1147: break;
1148: case 0x8 | 0x4: /* cc < 2 */
1149: tcg_gen_brcondi_i32(TCG_COND_GEU, cc_op, 2, skip);
1150: break;
1151: case 0x8: /* cc == 0 */
1152: tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 0, skip);
1153: break;
1154: case 0x4 | 0x2 | 0x1: /* cc != 0 */
1155: tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 0, skip);
1156: break;
1157: case 0x4 | 0x1: /* cc == 1 ||Â cc == 3 */
1158: tmp = tcg_temp_new_i32();
1159: tcg_gen_andi_i32(tmp, cc_op, 1);
1160: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, skip);
1161: tcg_temp_free_i32(tmp);
1162: break;
1163: case 0x4: /* cc == 1 */
1164: tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 1, skip);
1165: break;
1166: case 0x2 | 0x1: /* cc > 1 */
1167: tcg_gen_brcondi_i32(TCG_COND_LEU, cc_op, 1, skip);
1168: break;
1169: case 0x2: /* cc == 2 */
1170: tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 2, skip);
1171: break;
1172: case 0x1: /* cc == 3 */
1173: tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 3, skip);
1174: break;
1175: default: /* cc is masked by something else */
1176: tmp = tcg_const_i32(3);
1177: /* 3 - cc */
1178: tcg_gen_sub_i32(tmp, tmp, cc_op);
1179: tmp2 = tcg_const_i32(1);
1180: /* 1 << (3 - cc) */
1181: tcg_gen_shl_i32(tmp2, tmp2, tmp);
1182: r = tcg_const_i32(mask);
1183: /* mask & (1 << (3 - cc)) */
1184: tcg_gen_and_i32(r, r, tmp2);
1185: tcg_temp_free_i32(tmp);
1186: tcg_temp_free_i32(tmp2);
1187:
1188: tcg_gen_brcondi_i32(TCG_COND_EQ, r, 0, skip);
1189: tcg_temp_free_i32(r);
1190: break;
1191: }
1192: break;
1193: }
1194: }
1195:
1196: static void gen_bcr(DisasContext *s, uint32_t mask, TCGv_i64 target,
1197: uint64_t offset)
1198: {
1199: int skip;
1200:
1201: if (mask == 0xf) {
1202: /* unconditional */
1203: tcg_gen_mov_i64(psw_addr, target);
1204: tcg_gen_exit_tb(0);
1205: } else if (mask == 0) {
1206: /* ignore cc and never match */
1207: gen_goto_tb(s, 0, offset + 2);
1208: } else {
1209: TCGv_i64 new_addr = tcg_temp_local_new_i64();
1210:
1211: tcg_gen_mov_i64(new_addr, target);
1212: skip = gen_new_label();
1213: gen_jcc(s, mask, skip);
1214: tcg_gen_mov_i64(psw_addr, new_addr);
1215: tcg_temp_free_i64(new_addr);
1216: tcg_gen_exit_tb(0);
1217: gen_set_label(skip);
1218: tcg_temp_free_i64(new_addr);
1219: gen_goto_tb(s, 1, offset + 2);
1220: }
1221: }
1222:
1223: static void gen_brc(uint32_t mask, DisasContext *s, int32_t offset)
1224: {
1225: int skip;
1226:
1227: if (mask == 0xf) {
1228: /* unconditional */
1229: gen_goto_tb(s, 0, s->pc + offset);
1230: } else if (mask == 0) {
1231: /* ignore cc and never match */
1232: gen_goto_tb(s, 0, s->pc + 4);
1233: } else {
1234: skip = gen_new_label();
1235: gen_jcc(s, mask, skip);
1236: gen_goto_tb(s, 0, s->pc + offset);
1237: gen_set_label(skip);
1238: gen_goto_tb(s, 1, s->pc + 4);
1239: }
1240: s->is_jmp = DISAS_TB_JUMP;
1241: }
1242:
1243: static void gen_op_mvc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
1244: {
1245: TCGv_i64 tmp, tmp2;
1246: int i;
1247: int l_memset = gen_new_label();
1248: int l_out = gen_new_label();
1249: TCGv_i64 dest = tcg_temp_local_new_i64();
1250: TCGv_i64 src = tcg_temp_local_new_i64();
1251: TCGv_i32 vl;
1252:
1253: /* Find out if we should use the inline version of mvc */
1254: switch (l) {
1255: case 0:
1256: case 1:
1257: case 2:
1258: case 3:
1259: case 4:
1260: case 5:
1261: case 6:
1262: case 7:
1263: case 11:
1264: case 15:
1265: /* use inline */
1266: break;
1267: default:
1268: /* Fall back to helper */
1269: vl = tcg_const_i32(l);
1270: potential_page_fault(s);
1271: gen_helper_mvc(vl, s1, s2);
1272: tcg_temp_free_i32(vl);
1273: return;
1274: }
1275:
1276: tcg_gen_mov_i64(dest, s1);
1277: tcg_gen_mov_i64(src, s2);
1278:
1279: if (!(s->tb->flags & FLAG_MASK_64)) {
1280: /* XXX what if we overflow while moving? */
1281: tcg_gen_andi_i64(dest, dest, 0x7fffffffUL);
1282: tcg_gen_andi_i64(src, src, 0x7fffffffUL);
1283: }
1284:
1285: tmp = tcg_temp_new_i64();
1286: tcg_gen_addi_i64(tmp, src, 1);
1287: tcg_gen_brcond_i64(TCG_COND_EQ, dest, tmp, l_memset);
1288: tcg_temp_free_i64(tmp);
1289:
1290: switch (l) {
1291: case 0:
1292: tmp = tcg_temp_new_i64();
1293:
1294: tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
1295: tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
1296:
1297: tcg_temp_free_i64(tmp);
1298: break;
1299: case 1:
1300: tmp = tcg_temp_new_i64();
1301:
1302: tcg_gen_qemu_ld16u(tmp, src, get_mem_index(s));
1303: tcg_gen_qemu_st16(tmp, dest, get_mem_index(s));
1304:
1305: tcg_temp_free_i64(tmp);
1306: break;
1307: case 3:
1308: tmp = tcg_temp_new_i64();
1309:
1310: tcg_gen_qemu_ld32u(tmp, src, get_mem_index(s));
1311: tcg_gen_qemu_st32(tmp, dest, get_mem_index(s));
1312:
1313: tcg_temp_free_i64(tmp);
1314: break;
1315: case 4:
1316: tmp = tcg_temp_new_i64();
1317: tmp2 = tcg_temp_new_i64();
1318:
1319: tcg_gen_qemu_ld32u(tmp, src, get_mem_index(s));
1320: tcg_gen_addi_i64(src, src, 4);
1321: tcg_gen_qemu_ld8u(tmp2, src, get_mem_index(s));
1322: tcg_gen_qemu_st32(tmp, dest, get_mem_index(s));
1323: tcg_gen_addi_i64(dest, dest, 4);
1324: tcg_gen_qemu_st8(tmp2, dest, get_mem_index(s));
1325:
1326: tcg_temp_free_i64(tmp);
1327: tcg_temp_free_i64(tmp2);
1328: break;
1329: case 7:
1330: tmp = tcg_temp_new_i64();
1331:
1332: tcg_gen_qemu_ld64(tmp, src, get_mem_index(s));
1333: tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
1334:
1335: tcg_temp_free_i64(tmp);
1336: break;
1337: default:
1338: /* The inline version can become too big for too uneven numbers, only
1339: use it on known good lengths */
1340: tmp = tcg_temp_new_i64();
1341: tmp2 = tcg_const_i64(8);
1342: for (i = 0; (i + 7) <= l; i += 8) {
1343: tcg_gen_qemu_ld64(tmp, src, get_mem_index(s));
1344: tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
1345:
1346: tcg_gen_add_i64(src, src, tmp2);
1347: tcg_gen_add_i64(dest, dest, tmp2);
1348: }
1349:
1350: tcg_temp_free_i64(tmp2);
1351: tmp2 = tcg_const_i64(1);
1352:
1353: for (; i <= l; i++) {
1354: tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
1355: tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
1356:
1357: tcg_gen_add_i64(src, src, tmp2);
1358: tcg_gen_add_i64(dest, dest, tmp2);
1359: }
1360:
1361: tcg_temp_free_i64(tmp2);
1362: tcg_temp_free_i64(tmp);
1363: break;
1364: }
1365:
1366: tcg_gen_br(l_out);
1367:
1368: gen_set_label(l_memset);
1369: /* memset case (dest == (src + 1)) */
1370:
1371: tmp = tcg_temp_new_i64();
1372: tmp2 = tcg_temp_new_i64();
1373: /* fill tmp with the byte */
1374: tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
1375: tcg_gen_shli_i64(tmp2, tmp, 8);
1376: tcg_gen_or_i64(tmp, tmp, tmp2);
1377: tcg_gen_shli_i64(tmp2, tmp, 16);
1378: tcg_gen_or_i64(tmp, tmp, tmp2);
1379: tcg_gen_shli_i64(tmp2, tmp, 32);
1380: tcg_gen_or_i64(tmp, tmp, tmp2);
1381: tcg_temp_free_i64(tmp2);
1382:
1383: tmp2 = tcg_const_i64(8);
1384:
1385: for (i = 0; (i + 7) <= l; i += 8) {
1386: tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
1387: tcg_gen_addi_i64(dest, dest, 8);
1388: }
1389:
1390: tcg_temp_free_i64(tmp2);
1391: tmp2 = tcg_const_i64(1);
1392:
1393: for (; i <= l; i++) {
1394: tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
1395: tcg_gen_addi_i64(dest, dest, 1);
1396: }
1397:
1398: tcg_temp_free_i64(tmp2);
1399: tcg_temp_free_i64(tmp);
1400:
1401: gen_set_label(l_out);
1402:
1403: tcg_temp_free(dest);
1404: tcg_temp_free(src);
1405: }
1406:
1407: static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
1408: {
1409: TCGv_i64 tmp;
1410: TCGv_i64 tmp2;
1411: TCGv_i32 vl;
1412:
1413: /* check for simple 32bit or 64bit match */
1414: switch (l) {
1415: case 0:
1416: tmp = tcg_temp_new_i64();
1417: tmp2 = tcg_temp_new_i64();
1418:
1419: tcg_gen_qemu_ld8u(tmp, s1, get_mem_index(s));
1420: tcg_gen_qemu_ld8u(tmp2, s2, get_mem_index(s));
1421: cmp_u64(s, tmp, tmp2);
1422:
1423: tcg_temp_free_i64(tmp);
1424: tcg_temp_free_i64(tmp2);
1425: return;
1426: case 1:
1427: tmp = tcg_temp_new_i64();
1428: tmp2 = tcg_temp_new_i64();
1429:
1430: tcg_gen_qemu_ld16u(tmp, s1, get_mem_index(s));
1431: tcg_gen_qemu_ld16u(tmp2, s2, get_mem_index(s));
1432: cmp_u64(s, tmp, tmp2);
1433:
1434: tcg_temp_free_i64(tmp);
1435: tcg_temp_free_i64(tmp2);
1436: return;
1437: case 3:
1438: tmp = tcg_temp_new_i64();
1439: tmp2 = tcg_temp_new_i64();
1440:
1441: tcg_gen_qemu_ld32u(tmp, s1, get_mem_index(s));
1442: tcg_gen_qemu_ld32u(tmp2, s2, get_mem_index(s));
1443: cmp_u64(s, tmp, tmp2);
1444:
1445: tcg_temp_free_i64(tmp);
1446: tcg_temp_free_i64(tmp2);
1447: return;
1448: case 7:
1449: tmp = tcg_temp_new_i64();
1450: tmp2 = tcg_temp_new_i64();
1451:
1452: tcg_gen_qemu_ld64(tmp, s1, get_mem_index(s));
1453: tcg_gen_qemu_ld64(tmp2, s2, get_mem_index(s));
1454: cmp_u64(s, tmp, tmp2);
1455:
1456: tcg_temp_free_i64(tmp);
1457: tcg_temp_free_i64(tmp2);
1458: return;
1459: }
1460:
1461: potential_page_fault(s);
1462: vl = tcg_const_i32(l);
1463: gen_helper_clc(cc_op, vl, s1, s2);
1464: tcg_temp_free_i32(vl);
1465: set_cc_static(s);
1466: }
1467:
1468: static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
1469: {
1470: TCGv_i64 addr, tmp, tmp2, tmp3, tmp4;
1471: TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
1472:
1473: LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
1474: op, r1, x2, b2, d2);
1475: addr = get_address(s, x2, b2, d2);
1476: switch (op) {
1477: case 0x2: /* LTG R1,D2(X2,B2) [RXY] */
1478: case 0x4: /* lg r1,d2(x2,b2) */
1479: tcg_gen_qemu_ld64(regs[r1], addr, get_mem_index(s));
1480: if (op == 0x2) {
1481: set_cc_s64(s, regs[r1]);
1482: }
1483: break;
1484: case 0x12: /* LT R1,D2(X2,B2) [RXY] */
1485: tmp2 = tcg_temp_new_i64();
1486: tmp32_1 = tcg_temp_new_i32();
1487: tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
1488: tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
1489: store_reg32(r1, tmp32_1);
1490: set_cc_s32(s, tmp32_1);
1491: tcg_temp_free_i64(tmp2);
1492: tcg_temp_free_i32(tmp32_1);
1493: break;
1494: case 0xc: /* MSG R1,D2(X2,B2) [RXY] */
1495: case 0x1c: /* MSGF R1,D2(X2,B2) [RXY] */
1496: tmp2 = tcg_temp_new_i64();
1497: if (op == 0xc) {
1498: tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
1499: } else {
1500: tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
1501: }
1502: tcg_gen_mul_i64(regs[r1], regs[r1], tmp2);
1503: tcg_temp_free_i64(tmp2);
1504: break;
1505: case 0xd: /* DSG R1,D2(X2,B2) [RXY] */
1506: case 0x1d: /* DSGF R1,D2(X2,B2) [RXY] */
1507: tmp2 = tcg_temp_new_i64();
1508: if (op == 0x1d) {
1509: tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
1510: } else {
1511: tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
1512: }
1513: tmp4 = load_reg(r1 + 1);
1514: tmp3 = tcg_temp_new_i64();
1515: tcg_gen_div_i64(tmp3, tmp4, tmp2);
1516: store_reg(r1 + 1, tmp3);
1517: tcg_gen_rem_i64(tmp3, tmp4, tmp2);
1518: store_reg(r1, tmp3);
1519: tcg_temp_free_i64(tmp2);
1520: tcg_temp_free_i64(tmp3);
1521: tcg_temp_free_i64(tmp4);
1522: break;
1523: case 0x8: /* AG R1,D2(X2,B2) [RXY] */
1524: case 0xa: /* ALG R1,D2(X2,B2) [RXY] */
1525: case 0x18: /* AGF R1,D2(X2,B2) [RXY] */
1526: case 0x1a: /* ALGF R1,D2(X2,B2) [RXY] */
1527: if (op == 0x1a) {
1528: tmp2 = tcg_temp_new_i64();
1529: tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1530: } else if (op == 0x18) {
1531: tmp2 = tcg_temp_new_i64();
1532: tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
1533: } else {
1534: tmp2 = tcg_temp_new_i64();
1535: tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
1536: }
1537: tmp4 = load_reg(r1);
1538: tmp3 = tcg_temp_new_i64();
1539: tcg_gen_add_i64(tmp3, tmp4, tmp2);
1540: store_reg(r1, tmp3);
1541: switch (op) {
1542: case 0x8:
1543: case 0x18:
1544: set_cc_add64(s, tmp4, tmp2, tmp3);
1545: break;
1546: case 0xa:
1547: case 0x1a:
1548: set_cc_addu64(s, tmp4, tmp2, tmp3);
1549: break;
1550: default:
1551: tcg_abort();
1552: }
1553: tcg_temp_free_i64(tmp2);
1554: tcg_temp_free_i64(tmp3);
1555: tcg_temp_free_i64(tmp4);
1556: break;
1557: case 0x9: /* SG R1,D2(X2,B2) [RXY] */
1558: case 0xb: /* SLG R1,D2(X2,B2) [RXY] */
1559: case 0x19: /* SGF R1,D2(X2,B2) [RXY] */
1560: case 0x1b: /* SLGF R1,D2(X2,B2) [RXY] */
1561: tmp2 = tcg_temp_new_i64();
1562: if (op == 0x19) {
1563: tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
1564: } else if (op == 0x1b) {
1565: tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1566: } else {
1567: tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
1568: }
1569: tmp4 = load_reg(r1);
1570: tmp3 = tcg_temp_new_i64();
1571: tcg_gen_sub_i64(tmp3, tmp4, tmp2);
1572: store_reg(r1, tmp3);
1573: switch (op) {
1574: case 0x9:
1575: case 0x19:
1576: set_cc_sub64(s, tmp4, tmp2, tmp3);
1577: break;
1578: case 0xb:
1579: case 0x1b:
1580: set_cc_subu64(s, tmp4, tmp2, tmp3);
1581: break;
1582: default:
1583: tcg_abort();
1584: }
1585: tcg_temp_free_i64(tmp2);
1586: tcg_temp_free_i64(tmp3);
1587: tcg_temp_free_i64(tmp4);
1588: break;
1589: case 0xf: /* LRVG R1,D2(X2,B2) [RXE] */
1590: tmp2 = tcg_temp_new_i64();
1591: tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
1592: tcg_gen_bswap64_i64(tmp2, tmp2);
1593: store_reg(r1, tmp2);
1594: tcg_temp_free_i64(tmp2);
1595: break;
1596: case 0x14: /* LGF R1,D2(X2,B2) [RXY] */
1597: case 0x16: /* LLGF R1,D2(X2,B2) [RXY] */
1598: tmp2 = tcg_temp_new_i64();
1599: tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1600: if (op == 0x14) {
1601: tcg_gen_ext32s_i64(tmp2, tmp2);
1602: }
1603: store_reg(r1, tmp2);
1604: tcg_temp_free_i64(tmp2);
1605: break;
1606: case 0x15: /* LGH R1,D2(X2,B2) [RXY] */
1607: tmp2 = tcg_temp_new_i64();
1608: tcg_gen_qemu_ld16s(tmp2, addr, get_mem_index(s));
1609: store_reg(r1, tmp2);
1610: tcg_temp_free_i64(tmp2);
1611: break;
1612: case 0x17: /* LLGT R1,D2(X2,B2) [RXY] */
1613: tmp2 = tcg_temp_new_i64();
1614: tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1615: tcg_gen_andi_i64(tmp2, tmp2, 0x7fffffffULL);
1616: store_reg(r1, tmp2);
1617: tcg_temp_free_i64(tmp2);
1618: break;
1619: case 0x1e: /* LRV R1,D2(X2,B2) [RXY] */
1620: tmp2 = tcg_temp_new_i64();
1621: tmp32_1 = tcg_temp_new_i32();
1622: tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1623: tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
1624: tcg_temp_free_i64(tmp2);
1625: tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
1626: store_reg32(r1, tmp32_1);
1627: tcg_temp_free_i32(tmp32_1);
1628: break;
1629: case 0x1f: /* LRVH R1,D2(X2,B2) [RXY] */
1630: tmp2 = tcg_temp_new_i64();
1631: tmp32_1 = tcg_temp_new_i32();
1632: tcg_gen_qemu_ld16u(tmp2, addr, get_mem_index(s));
1633: tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
1634: tcg_temp_free_i64(tmp2);
1635: tcg_gen_bswap16_i32(tmp32_1, tmp32_1);
1636: store_reg16(r1, tmp32_1);
1637: tcg_temp_free_i32(tmp32_1);
1638: break;
1639: case 0x20: /* CG R1,D2(X2,B2) [RXY] */
1640: case 0x21: /* CLG R1,D2(X2,B2) */
1641: case 0x30: /* CGF R1,D2(X2,B2) [RXY] */
1642: case 0x31: /* CLGF R1,D2(X2,B2) [RXY] */
1643: tmp2 = tcg_temp_new_i64();
1644: switch (op) {
1645: case 0x20:
1646: case 0x21:
1647: tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
1648: break;
1649: case 0x30:
1650: tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
1651: break;
1652: case 0x31:
1653: tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1654: break;
1655: default:
1656: tcg_abort();
1657: }
1658: switch (op) {
1659: case 0x20:
1660: case 0x30:
1661: cmp_s64(s, regs[r1], tmp2);
1662: break;
1663: case 0x21:
1664: case 0x31:
1665: cmp_u64(s, regs[r1], tmp2);
1666: break;
1667: default:
1668: tcg_abort();
1669: }
1670: tcg_temp_free_i64(tmp2);
1671: break;
1672: case 0x24: /* stg r1, d2(x2,b2) */
1673: tcg_gen_qemu_st64(regs[r1], addr, get_mem_index(s));
1674: break;
1675: case 0x3e: /* STRV R1,D2(X2,B2) [RXY] */
1676: tmp32_1 = load_reg32(r1);
1677: tmp2 = tcg_temp_new_i64();
1678: tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
1679: tcg_gen_extu_i32_i64(tmp2, tmp32_1);
1680: tcg_temp_free_i32(tmp32_1);
1681: tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
1682: tcg_temp_free_i64(tmp2);
1683: break;
1684: case 0x50: /* STY R1,D2(X2,B2) [RXY] */
1685: tmp32_1 = load_reg32(r1);
1686: tmp2 = tcg_temp_new_i64();
1687: tcg_gen_extu_i32_i64(tmp2, tmp32_1);
1688: tcg_temp_free_i32(tmp32_1);
1689: tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
1690: tcg_temp_free_i64(tmp2);
1691: break;
1692: case 0x57: /* XY R1,D2(X2,B2) [RXY] */
1693: tmp32_1 = load_reg32(r1);
1694: tmp32_2 = tcg_temp_new_i32();
1695: tmp2 = tcg_temp_new_i64();
1696: tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1697: tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
1698: tcg_temp_free_i64(tmp2);
1699: tcg_gen_xor_i32(tmp32_2, tmp32_1, tmp32_2);
1700: store_reg32(r1, tmp32_2);
1701: set_cc_nz_u32(s, tmp32_2);
1702: tcg_temp_free_i32(tmp32_1);
1703: tcg_temp_free_i32(tmp32_2);
1704: break;
1705: case 0x58: /* LY R1,D2(X2,B2) [RXY] */
1706: tmp3 = tcg_temp_new_i64();
1707: tcg_gen_qemu_ld32u(tmp3, addr, get_mem_index(s));
1708: store_reg32_i64(r1, tmp3);
1709: tcg_temp_free_i64(tmp3);
1710: break;
1711: case 0x5a: /* AY R1,D2(X2,B2) [RXY] */
1712: case 0x5b: /* SY R1,D2(X2,B2) [RXY] */
1713: tmp32_1 = load_reg32(r1);
1714: tmp32_2 = tcg_temp_new_i32();
1715: tmp32_3 = tcg_temp_new_i32();
1716: tmp2 = tcg_temp_new_i64();
1717: tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
1718: tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
1719: tcg_temp_free_i64(tmp2);
1720: switch (op) {
1721: case 0x5a:
1722: tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
1723: break;
1724: case 0x5b:
1725: tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
1726: break;
1727: default:
1728: tcg_abort();
1729: }
1730: store_reg32(r1, tmp32_3);
1731: switch (op) {
1732: case 0x5a:
1733: set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
1734: break;
1735: case 0x5b:
1736: set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
1737: break;
1738: default:
1739: tcg_abort();
1740: }
1741: tcg_temp_free_i32(tmp32_1);
1742: tcg_temp_free_i32(tmp32_2);
1743: tcg_temp_free_i32(tmp32_3);
1744: break;
1745: case 0x71: /* LAY R1,D2(X2,B2) [RXY] */
1746: store_reg(r1, addr);
1747: break;
1748: case 0x72: /* STCY R1,D2(X2,B2) [RXY] */
1749: tmp32_1 = load_reg32(r1);
1750: tmp2 = tcg_temp_new_i64();
1751: tcg_gen_ext_i32_i64(tmp2, tmp32_1);
1752: tcg_gen_qemu_st8(tmp2, addr, get_mem_index(s));
1753: tcg_temp_free_i32(tmp32_1);
1754: tcg_temp_free_i64(tmp2);
1755: break;
1756: case 0x73: /* ICY R1,D2(X2,B2) [RXY] */
1757: tmp3 = tcg_temp_new_i64();
1758: tcg_gen_qemu_ld8u(tmp3, addr, get_mem_index(s));
1759: store_reg8(r1, tmp3);
1760: tcg_temp_free_i64(tmp3);
1761: break;
1762: case 0x76: /* LB R1,D2(X2,B2) [RXY] */
1763: case 0x77: /* LGB R1,D2(X2,B2) [RXY] */
1764: tmp2 = tcg_temp_new_i64();
1765: tcg_gen_qemu_ld8s(tmp2, addr, get_mem_index(s));
1766: switch (op) {
1767: case 0x76:
1768: tcg_gen_ext8s_i64(tmp2, tmp2);
1769: store_reg32_i64(r1, tmp2);
1770: break;
1771: case 0x77:
1772: tcg_gen_ext8s_i64(tmp2, tmp2);
1773: store_reg(r1, tmp2);
1774: break;
1775: default:
1776: tcg_abort();
1777: }
1778: tcg_temp_free_i64(tmp2);
1779: break;
1780: case 0x78: /* LHY R1,D2(X2,B2) [RXY] */
1781: tmp2 = tcg_temp_new_i64();
1782: tcg_gen_qemu_ld16s(tmp2, addr, get_mem_index(s));
1783: store_reg32_i64(r1, tmp2);
1784: tcg_temp_free_i64(tmp2);
1785: break;
1786: case 0x80: /* NG R1,D2(X2,B2) [RXY] */
1787: case 0x81: /* OG R1,D2(X2,B2) [RXY] */
1788: case 0x82: /* XG R1,D2(X2,B2) [RXY] */
1789: tmp3 = tcg_temp_new_i64();
1790: tcg_gen_qemu_ld64(tmp3, addr, get_mem_index(s));
1791: switch (op) {
1792: case 0x80:
1793: tcg_gen_and_i64(regs[r1], regs[r1], tmp3);
1794: break;
1795: case 0x81:
1796: tcg_gen_or_i64(regs[r1], regs[r1], tmp3);
1797: break;
1798: case 0x82:
1799: tcg_gen_xor_i64(regs[r1], regs[r1], tmp3);
1800: break;
1801: default:
1802: tcg_abort();
1803: }
1804: set_cc_nz_u64(s, regs[r1]);
1805: tcg_temp_free_i64(tmp3);
1806: break;
1807: case 0x86: /* MLG R1,D2(X2,B2) [RXY] */
1808: tmp2 = tcg_temp_new_i64();
1809: tmp32_1 = tcg_const_i32(r1);
1810: tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
1811: gen_helper_mlg(tmp32_1, tmp2);
1812: tcg_temp_free_i64(tmp2);
1813: tcg_temp_free_i32(tmp32_1);
1814: break;
1815: case 0x87: /* DLG R1,D2(X2,B2) [RXY] */
1816: tmp2 = tcg_temp_new_i64();
1817: tmp32_1 = tcg_const_i32(r1);
1818: tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
1819: gen_helper_dlg(tmp32_1, tmp2);
1820: tcg_temp_free_i64(tmp2);
1821: tcg_temp_free_i32(tmp32_1);
1822: break;
1823: case 0x88: /* ALCG R1,D2(X2,B2) [RXY] */
1824: tmp2 = tcg_temp_new_i64();
1825: tmp3 = tcg_temp_new_i64();
1826: tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
1827: /* XXX possible optimization point */
1828: gen_op_calc_cc(s);
1829: tcg_gen_extu_i32_i64(tmp3, cc_op);
1830: tcg_gen_shri_i64(tmp3, tmp3, 1);
1831: tcg_gen_andi_i64(tmp3, tmp3, 1);
1832: tcg_gen_add_i64(tmp3, tmp2, tmp3);
1833: tcg_gen_add_i64(tmp3, regs[r1], tmp3);
1834: store_reg(r1, tmp3);
1835: set_cc_addu64(s, regs[r1], tmp2, tmp3);
1836: tcg_temp_free_i64(tmp2);
1837: tcg_temp_free_i64(tmp3);
1838: break;
1839: case 0x89: /* SLBG R1,D2(X2,B2) [RXY] */
1840: tmp2 = tcg_temp_new_i64();
1841: tmp32_1 = tcg_const_i32(r1);
1842: tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
1843: /* XXX possible optimization point */
1844: gen_op_calc_cc(s);
1845: gen_helper_slbg(cc_op, cc_op, tmp32_1, regs[r1], tmp2);
1846: set_cc_static(s);
1847: tcg_temp_free_i64(tmp2);
1848: tcg_temp_free_i32(tmp32_1);
1849: break;
1850: case 0x90: /* LLGC R1,D2(X2,B2) [RXY] */
1851: tcg_gen_qemu_ld8u(regs[r1], addr, get_mem_index(s));
1852: break;
1853: case 0x91: /* LLGH R1,D2(X2,B2) [RXY] */
1854: tcg_gen_qemu_ld16u(regs[r1], addr, get_mem_index(s));
1855: break;
1856: case 0x94: /* LLC R1,D2(X2,B2) [RXY] */
1857: tmp2 = tcg_temp_new_i64();
1858: tcg_gen_qemu_ld8u(tmp2, addr, get_mem_index(s));
1859: store_reg32_i64(r1, tmp2);
1860: tcg_temp_free_i64(tmp2);
1861: break;
1862: case 0x95: /* LLH R1,D2(X2,B2) [RXY] */
1863: tmp2 = tcg_temp_new_i64();
1864: tcg_gen_qemu_ld16u(tmp2, addr, get_mem_index(s));
1865: store_reg32_i64(r1, tmp2);
1866: tcg_temp_free_i64(tmp2);
1867: break;
1868: case 0x96: /* ML R1,D2(X2,B2) [RXY] */
1869: tmp2 = tcg_temp_new_i64();
1870: tmp3 = load_reg((r1 + 1) & 15);
1871: tcg_gen_ext32u_i64(tmp3, tmp3);
1872: tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1873: tcg_gen_mul_i64(tmp2, tmp2, tmp3);
1874: store_reg32_i64((r1 + 1) & 15, tmp2);
1875: tcg_gen_shri_i64(tmp2, tmp2, 32);
1876: store_reg32_i64(r1, tmp2);
1877: tcg_temp_free_i64(tmp2);
1878: tcg_temp_free_i64(tmp3);
1879: break;
1880: case 0x97: /* DL R1,D2(X2,B2) [RXY] */
1881: /* reg(r1) = reg(r1, r1+1) % ld32(addr) */
1882: /* reg(r1+1) = reg(r1, r1+1) / ld32(addr) */
1883: tmp = load_reg(r1);
1884: tmp2 = tcg_temp_new_i64();
1885: tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1886: tmp3 = load_reg((r1 + 1) & 15);
1887: tcg_gen_ext32u_i64(tmp2, tmp2);
1888: tcg_gen_ext32u_i64(tmp3, tmp3);
1889: tcg_gen_shli_i64(tmp, tmp, 32);
1890: tcg_gen_or_i64(tmp, tmp, tmp3);
1891:
1892: tcg_gen_rem_i64(tmp3, tmp, tmp2);
1893: tcg_gen_div_i64(tmp, tmp, tmp2);
1894: store_reg32_i64((r1 + 1) & 15, tmp);
1895: store_reg32_i64(r1, tmp3);
1896: tcg_temp_free_i64(tmp);
1897: tcg_temp_free_i64(tmp2);
1898: tcg_temp_free_i64(tmp3);
1899: break;
1900: case 0x98: /* ALC R1,D2(X2,B2) [RXY] */
1901: tmp2 = tcg_temp_new_i64();
1902: tmp32_1 = load_reg32(r1);
1903: tmp32_2 = tcg_temp_new_i32();
1904: tmp32_3 = tcg_temp_new_i32();
1905: tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1906: tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
1907: /* XXX possible optimization point */
1908: gen_op_calc_cc(s);
1909: gen_helper_addc_u32(tmp32_3, cc_op, tmp32_1, tmp32_2);
1910: set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
1911: store_reg32(r1, tmp32_3);
1912: tcg_temp_free_i64(tmp2);
1913: tcg_temp_free_i32(tmp32_1);
1914: tcg_temp_free_i32(tmp32_2);
1915: tcg_temp_free_i32(tmp32_3);
1916: break;
1917: case 0x99: /* SLB R1,D2(X2,B2) [RXY] */
1918: tmp2 = tcg_temp_new_i64();
1919: tmp32_1 = tcg_const_i32(r1);
1920: tmp32_2 = tcg_temp_new_i32();
1921: tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
1922: tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
1923: /* XXX possible optimization point */
1924: gen_op_calc_cc(s);
1925: gen_helper_slb(cc_op, cc_op, tmp32_1, tmp32_2);
1926: set_cc_static(s);
1927: tcg_temp_free_i64(tmp2);
1928: tcg_temp_free_i32(tmp32_1);
1929: tcg_temp_free_i32(tmp32_2);
1930: break;
1931: default:
1932: LOG_DISAS("illegal e3 operation 0x%x\n", op);
1933: gen_illegal_opcode(s, 3);
1934: break;
1935: }
1936: tcg_temp_free_i64(addr);
1937: }
1938:
1939: #ifndef CONFIG_USER_ONLY
1940: static void disas_e5(DisasContext* s, uint64_t insn)
1941: {
1942: TCGv_i64 tmp, tmp2;
1943: int op = (insn >> 32) & 0xff;
1944:
1945: tmp = get_address(s, 0, (insn >> 28) & 0xf, (insn >> 16) & 0xfff);
1946: tmp2 = get_address(s, 0, (insn >> 12) & 0xf, insn & 0xfff);
1947:
1948: LOG_DISAS("disas_e5: insn %" PRIx64 "\n", insn);
1949: switch (op) {
1950: case 0x01: /* TPROT D1(B1),D2(B2) [SSE] */
1951: /* Test Protection */
1952: potential_page_fault(s);
1953: gen_helper_tprot(cc_op, tmp, tmp2);
1954: set_cc_static(s);
1955: break;
1956: default:
1957: LOG_DISAS("illegal e5 operation 0x%x\n", op);
1958: gen_illegal_opcode(s, 3);
1959: break;
1960: }
1961:
1962: tcg_temp_free_i64(tmp);
1963: tcg_temp_free_i64(tmp2);
1964: }
1965: #endif
1966:
1967: static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2)
1968: {
1969: TCGv_i64 tmp, tmp2, tmp3, tmp4;
1970: TCGv_i32 tmp32_1, tmp32_2;
1971: int i, stm_len;
1972: int ilc = 3;
1973:
1974: LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
1975: op, r1, r3, b2, d2);
1976: switch (op) {
1977: case 0xc: /* SRLG R1,R3,D2(B2) [RSY] */
1978: case 0xd: /* SLLG R1,R3,D2(B2) [RSY] */
1979: case 0xa: /* SRAG R1,R3,D2(B2) [RSY] */
1980: case 0xb: /* SLAG R1,R3,D2(B2) [RSY] */
1981: case 0x1c: /* RLLG R1,R3,D2(B2) [RSY] */
1982: if (b2) {
1983: tmp = get_address(s, 0, b2, d2);
1984: tcg_gen_andi_i64(tmp, tmp, 0x3f);
1985: } else {
1986: tmp = tcg_const_i64(d2 & 0x3f);
1987: }
1988: switch (op) {
1989: case 0xc:
1990: tcg_gen_shr_i64(regs[r1], regs[r3], tmp);
1991: break;
1992: case 0xd:
1993: tcg_gen_shl_i64(regs[r1], regs[r3], tmp);
1994: break;
1995: case 0xa:
1996: tcg_gen_sar_i64(regs[r1], regs[r3], tmp);
1997: break;
1998: case 0xb:
1999: tmp2 = tcg_temp_new_i64();
2000: tmp3 = tcg_temp_new_i64();
2001: gen_op_update2_cc_i64(s, CC_OP_SLAG, regs[r3], tmp);
2002: tcg_gen_shl_i64(tmp2, regs[r3], tmp);
2003: /* override sign bit with source sign */
2004: tcg_gen_andi_i64(tmp2, tmp2, ~0x8000000000000000ULL);
2005: tcg_gen_andi_i64(tmp3, regs[r3], 0x8000000000000000ULL);
2006: tcg_gen_or_i64(regs[r1], tmp2, tmp3);
2007: tcg_temp_free_i64(tmp2);
2008: tcg_temp_free_i64(tmp3);
2009: break;
2010: case 0x1c:
2011: tcg_gen_rotl_i64(regs[r1], regs[r3], tmp);
2012: break;
2013: default:
2014: tcg_abort();
2015: break;
2016: }
2017: if (op == 0xa) {
2018: set_cc_s64(s, regs[r1]);
2019: }
2020: tcg_temp_free_i64(tmp);
2021: break;
2022: case 0x1d: /* RLL R1,R3,D2(B2) [RSY] */
2023: if (b2) {
2024: tmp = get_address(s, 0, b2, d2);
2025: tcg_gen_andi_i64(tmp, tmp, 0x3f);
2026: } else {
2027: tmp = tcg_const_i64(d2 & 0x3f);
2028: }
2029: tmp32_1 = tcg_temp_new_i32();
2030: tmp32_2 = load_reg32(r3);
2031: tcg_gen_trunc_i64_i32(tmp32_1, tmp);
2032: switch (op) {
2033: case 0x1d:
2034: tcg_gen_rotl_i32(tmp32_1, tmp32_2, tmp32_1);
2035: break;
2036: default:
2037: tcg_abort();
2038: break;
2039: }
2040: store_reg32(r1, tmp32_1);
2041: tcg_temp_free_i64(tmp);
2042: tcg_temp_free_i32(tmp32_1);
2043: tcg_temp_free_i32(tmp32_2);
2044: break;
2045: case 0x4: /* LMG R1,R3,D2(B2) [RSE] */
2046: case 0x24: /* STMG R1,R3,D2(B2) [RSE] */
2047: stm_len = 8;
2048: goto do_mh;
2049: case 0x26: /* STMH R1,R3,D2(B2) [RSE] */
2050: case 0x96: /* LMH R1,R3,D2(B2) [RSE] */
2051: stm_len = 4;
2052: do_mh:
2053: /* Apparently, unrolling lmg/stmg of any size gains performance -
2054: even for very long ones... */
2055: tmp = get_address(s, 0, b2, d2);
2056: tmp3 = tcg_const_i64(stm_len);
2057: tmp4 = tcg_const_i64(op == 0x26 ? 32 : 4);
2058: for (i = r1;; i = (i + 1) % 16) {
2059: switch (op) {
2060: case 0x4:
2061: tcg_gen_qemu_ld64(regs[i], tmp, get_mem_index(s));
2062: break;
2063: case 0x96:
2064: tmp2 = tcg_temp_new_i64();
2065: #if HOST_LONG_BITS == 32
2066: tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
2067: tcg_gen_trunc_i64_i32(TCGV_HIGH(regs[i]), tmp2);
2068: #else
2069: tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
2070: tcg_gen_shl_i64(tmp2, tmp2, tmp4);
2071: tcg_gen_ext32u_i64(regs[i], regs[i]);
2072: tcg_gen_or_i64(regs[i], regs[i], tmp2);
2073: #endif
2074: tcg_temp_free_i64(tmp2);
2075: break;
2076: case 0x24:
2077: tcg_gen_qemu_st64(regs[i], tmp, get_mem_index(s));
2078: break;
2079: case 0x26:
2080: tmp2 = tcg_temp_new_i64();
2081: tcg_gen_shr_i64(tmp2, regs[i], tmp4);
2082: tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
2083: tcg_temp_free_i64(tmp2);
2084: break;
2085: default:
2086: tcg_abort();
2087: }
2088: if (i == r3) {
2089: break;
2090: }
2091: tcg_gen_add_i64(tmp, tmp, tmp3);
2092: }
2093: tcg_temp_free_i64(tmp);
2094: tcg_temp_free_i64(tmp3);
2095: tcg_temp_free_i64(tmp4);
2096: break;
2097: case 0x2c: /* STCMH R1,M3,D2(B2) [RSY] */
2098: tmp = get_address(s, 0, b2, d2);
2099: tmp32_1 = tcg_const_i32(r1);
2100: tmp32_2 = tcg_const_i32(r3);
2101: potential_page_fault(s);
2102: gen_helper_stcmh(tmp32_1, tmp, tmp32_2);
2103: tcg_temp_free_i64(tmp);
2104: tcg_temp_free_i32(tmp32_1);
2105: tcg_temp_free_i32(tmp32_2);
2106: break;
2107: #ifndef CONFIG_USER_ONLY
2108: case 0x2f: /* LCTLG R1,R3,D2(B2) [RSE] */
2109: /* Load Control */
2110: check_privileged(s, ilc);
2111: tmp = get_address(s, 0, b2, d2);
2112: tmp32_1 = tcg_const_i32(r1);
2113: tmp32_2 = tcg_const_i32(r3);
2114: potential_page_fault(s);
2115: gen_helper_lctlg(tmp32_1, tmp, tmp32_2);
2116: tcg_temp_free_i64(tmp);
2117: tcg_temp_free_i32(tmp32_1);
2118: tcg_temp_free_i32(tmp32_2);
2119: break;
2120: case 0x25: /* STCTG R1,R3,D2(B2) [RSE] */
2121: /* Store Control */
2122: check_privileged(s, ilc);
2123: tmp = get_address(s, 0, b2, d2);
2124: tmp32_1 = tcg_const_i32(r1);
2125: tmp32_2 = tcg_const_i32(r3);
2126: potential_page_fault(s);
2127: gen_helper_stctg(tmp32_1, tmp, tmp32_2);
2128: tcg_temp_free_i64(tmp);
2129: tcg_temp_free_i32(tmp32_1);
2130: tcg_temp_free_i32(tmp32_2);
2131: break;
2132: #endif
2133: case 0x30: /* CSG R1,R3,D2(B2) [RSY] */
2134: tmp = get_address(s, 0, b2, d2);
2135: tmp32_1 = tcg_const_i32(r1);
2136: tmp32_2 = tcg_const_i32(r3);
2137: potential_page_fault(s);
2138: /* XXX rewrite in tcg */
2139: gen_helper_csg(cc_op, tmp32_1, tmp, tmp32_2);
2140: set_cc_static(s);
2141: tcg_temp_free_i64(tmp);
2142: tcg_temp_free_i32(tmp32_1);
2143: tcg_temp_free_i32(tmp32_2);
2144: break;
2145: case 0x3e: /* CDSG R1,R3,D2(B2) [RSY] */
2146: tmp = get_address(s, 0, b2, d2);
2147: tmp32_1 = tcg_const_i32(r1);
2148: tmp32_2 = tcg_const_i32(r3);
2149: potential_page_fault(s);
2150: /* XXX rewrite in tcg */
2151: gen_helper_cdsg(cc_op, tmp32_1, tmp, tmp32_2);
2152: set_cc_static(s);
2153: tcg_temp_free_i64(tmp);
2154: tcg_temp_free_i32(tmp32_1);
2155: tcg_temp_free_i32(tmp32_2);
2156: break;
2157: case 0x51: /* TMY D1(B1),I2 [SIY] */
2158: tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
2159: tmp2 = tcg_const_i64((r1 << 4) | r3);
2160: tcg_gen_qemu_ld8u(tmp, tmp, get_mem_index(s));
2161: /* yes, this is a 32 bit operation with 64 bit tcg registers, because
2162: that incurs less conversions */
2163: cmp_64(s, tmp, tmp2, CC_OP_TM_32);
2164: tcg_temp_free_i64(tmp);
2165: tcg_temp_free_i64(tmp2);
2166: break;
2167: case 0x52: /* MVIY D1(B1),I2 [SIY] */
2168: tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
2169: tmp2 = tcg_const_i64((r1 << 4) | r3);
2170: tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
2171: tcg_temp_free_i64(tmp);
2172: tcg_temp_free_i64(tmp2);
2173: break;
2174: case 0x55: /* CLIY D1(B1),I2 [SIY] */
2175: tmp3 = get_address(s, 0, b2, d2); /* SIY -> this is the 1st operand */
2176: tmp = tcg_temp_new_i64();
2177: tmp32_1 = tcg_temp_new_i32();
2178: tcg_gen_qemu_ld8u(tmp, tmp3, get_mem_index(s));
2179: tcg_gen_trunc_i64_i32(tmp32_1, tmp);
2180: cmp_u32c(s, tmp32_1, (r1 << 4) | r3);
2181: tcg_temp_free_i64(tmp);
2182: tcg_temp_free_i64(tmp3);
2183: tcg_temp_free_i32(tmp32_1);
2184: break;
2185: case 0x80: /* ICMH R1,M3,D2(B2) [RSY] */
2186: tmp = get_address(s, 0, b2, d2);
2187: tmp32_1 = tcg_const_i32(r1);
2188: tmp32_2 = tcg_const_i32(r3);
2189: potential_page_fault(s);
2190: /* XXX split CC calculation out */
2191: gen_helper_icmh(cc_op, tmp32_1, tmp, tmp32_2);
2192: set_cc_static(s);
2193: tcg_temp_free_i64(tmp);
2194: tcg_temp_free_i32(tmp32_1);
2195: tcg_temp_free_i32(tmp32_2);
2196: break;
2197: default:
2198: LOG_DISAS("illegal eb operation 0x%x\n", op);
2199: gen_illegal_opcode(s, ilc);
2200: break;
2201: }
2202: }
2203:
2204: static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
2205: int r1b)
2206: {
2207: TCGv_i32 tmp_r1, tmp32;
2208: TCGv_i64 addr, tmp;
2209: addr = get_address(s, x2, b2, d2);
2210: tmp_r1 = tcg_const_i32(r1);
2211: switch (op) {
1.1.1.5 root 2212: case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */
2213: potential_page_fault(s);
2214: gen_helper_ldeb(tmp_r1, addr);
2215: break;
1.1.1.4 root 2216: case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */
2217: potential_page_fault(s);
2218: gen_helper_lxdb(tmp_r1, addr);
2219: break;
2220: case 0x9: /* CEB R1,D2(X2,B2) [RXE] */
2221: tmp = tcg_temp_new_i64();
2222: tmp32 = load_freg32(r1);
2223: tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
2224: set_cc_cmp_f32_i64(s, tmp32, tmp);
2225: tcg_temp_free_i64(tmp);
2226: tcg_temp_free_i32(tmp32);
2227: break;
2228: case 0xa: /* AEB R1,D2(X2,B2) [RXE] */
2229: tmp = tcg_temp_new_i64();
2230: tmp32 = tcg_temp_new_i32();
2231: tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
2232: tcg_gen_trunc_i64_i32(tmp32, tmp);
2233: gen_helper_aeb(tmp_r1, tmp32);
2234: tcg_temp_free_i64(tmp);
2235: tcg_temp_free_i32(tmp32);
2236:
2237: tmp32 = load_freg32(r1);
2238: set_cc_nz_f32(s, tmp32);
2239: tcg_temp_free_i32(tmp32);
2240: break;
2241: case 0xb: /* SEB R1,D2(X2,B2) [RXE] */
2242: tmp = tcg_temp_new_i64();
2243: tmp32 = tcg_temp_new_i32();
2244: tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
2245: tcg_gen_trunc_i64_i32(tmp32, tmp);
2246: gen_helper_seb(tmp_r1, tmp32);
2247: tcg_temp_free_i64(tmp);
2248: tcg_temp_free_i32(tmp32);
2249:
2250: tmp32 = load_freg32(r1);
2251: set_cc_nz_f32(s, tmp32);
2252: tcg_temp_free_i32(tmp32);
2253: break;
2254: case 0xd: /* DEB R1,D2(X2,B2) [RXE] */
2255: tmp = tcg_temp_new_i64();
2256: tmp32 = tcg_temp_new_i32();
2257: tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
2258: tcg_gen_trunc_i64_i32(tmp32, tmp);
2259: gen_helper_deb(tmp_r1, tmp32);
2260: tcg_temp_free_i64(tmp);
2261: tcg_temp_free_i32(tmp32);
2262: break;
2263: case 0x10: /* TCEB R1,D2(X2,B2) [RXE] */
2264: potential_page_fault(s);
2265: gen_helper_tceb(cc_op, tmp_r1, addr);
2266: set_cc_static(s);
2267: break;
2268: case 0x11: /* TCDB R1,D2(X2,B2) [RXE] */
2269: potential_page_fault(s);
2270: gen_helper_tcdb(cc_op, tmp_r1, addr);
2271: set_cc_static(s);
2272: break;
2273: case 0x12: /* TCXB R1,D2(X2,B2) [RXE] */
2274: potential_page_fault(s);
2275: gen_helper_tcxb(cc_op, tmp_r1, addr);
2276: set_cc_static(s);
2277: break;
2278: case 0x17: /* MEEB R1,D2(X2,B2) [RXE] */
2279: tmp = tcg_temp_new_i64();
2280: tmp32 = tcg_temp_new_i32();
2281: tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
2282: tcg_gen_trunc_i64_i32(tmp32, tmp);
2283: gen_helper_meeb(tmp_r1, tmp32);
2284: tcg_temp_free_i64(tmp);
2285: tcg_temp_free_i32(tmp32);
2286: break;
2287: case 0x19: /* CDB R1,D2(X2,B2) [RXE] */
2288: potential_page_fault(s);
2289: gen_helper_cdb(cc_op, tmp_r1, addr);
2290: set_cc_static(s);
2291: break;
2292: case 0x1a: /* ADB R1,D2(X2,B2) [RXE] */
2293: potential_page_fault(s);
2294: gen_helper_adb(cc_op, tmp_r1, addr);
2295: set_cc_static(s);
2296: break;
2297: case 0x1b: /* SDB R1,D2(X2,B2) [RXE] */
2298: potential_page_fault(s);
2299: gen_helper_sdb(cc_op, tmp_r1, addr);
2300: set_cc_static(s);
2301: break;
2302: case 0x1c: /* MDB R1,D2(X2,B2) [RXE] */
2303: potential_page_fault(s);
2304: gen_helper_mdb(tmp_r1, addr);
2305: break;
2306: case 0x1d: /* DDB R1,D2(X2,B2) [RXE] */
2307: potential_page_fault(s);
2308: gen_helper_ddb(tmp_r1, addr);
2309: break;
2310: case 0x1e: /* MADB R1,R3,D2(X2,B2) [RXF] */
2311: /* for RXF insns, r1 is R3 and r1b is R1 */
2312: tmp32 = tcg_const_i32(r1b);
2313: potential_page_fault(s);
2314: gen_helper_madb(tmp32, addr, tmp_r1);
2315: tcg_temp_free_i32(tmp32);
2316: break;
2317: default:
2318: LOG_DISAS("illegal ed operation 0x%x\n", op);
2319: gen_illegal_opcode(s, 3);
2320: return;
2321: }
2322: tcg_temp_free_i32(tmp_r1);
2323: tcg_temp_free_i64(addr);
2324: }
2325:
2326: static void disas_a5(DisasContext *s, int op, int r1, int i2)
2327: {
2328: TCGv_i64 tmp, tmp2;
2329: TCGv_i32 tmp32;
2330: LOG_DISAS("disas_a5: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
2331: switch (op) {
2332: case 0x0: /* IIHH R1,I2 [RI] */
2333: tmp = tcg_const_i64(i2);
2334: tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 48, 16);
2335: tcg_temp_free_i64(tmp);
2336: break;
2337: case 0x1: /* IIHL R1,I2 [RI] */
2338: tmp = tcg_const_i64(i2);
2339: tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 32, 16);
2340: tcg_temp_free_i64(tmp);
2341: break;
2342: case 0x2: /* IILH R1,I2 [RI] */
2343: tmp = tcg_const_i64(i2);
2344: tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 16, 16);
2345: tcg_temp_free_i64(tmp);
2346: break;
2347: case 0x3: /* IILL R1,I2 [RI] */
2348: tmp = tcg_const_i64(i2);
2349: tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 0, 16);
2350: tcg_temp_free_i64(tmp);
2351: break;
2352: case 0x4: /* NIHH R1,I2 [RI] */
2353: case 0x8: /* OIHH R1,I2 [RI] */
2354: tmp = load_reg(r1);
2355: tmp32 = tcg_temp_new_i32();
2356: switch (op) {
2357: case 0x4:
2358: tmp2 = tcg_const_i64((((uint64_t)i2) << 48)
2359: | 0x0000ffffffffffffULL);
2360: tcg_gen_and_i64(tmp, tmp, tmp2);
2361: break;
2362: case 0x8:
2363: tmp2 = tcg_const_i64(((uint64_t)i2) << 48);
2364: tcg_gen_or_i64(tmp, tmp, tmp2);
2365: break;
2366: default:
2367: tcg_abort();
2368: }
2369: store_reg(r1, tmp);
2370: tcg_gen_shri_i64(tmp2, tmp, 48);
2371: tcg_gen_trunc_i64_i32(tmp32, tmp2);
2372: set_cc_nz_u32(s, tmp32);
2373: tcg_temp_free_i64(tmp2);
2374: tcg_temp_free_i32(tmp32);
2375: tcg_temp_free_i64(tmp);
2376: break;
2377: case 0x5: /* NIHL R1,I2 [RI] */
2378: case 0x9: /* OIHL R1,I2 [RI] */
2379: tmp = load_reg(r1);
2380: tmp32 = tcg_temp_new_i32();
2381: switch (op) {
2382: case 0x5:
2383: tmp2 = tcg_const_i64((((uint64_t)i2) << 32)
2384: | 0xffff0000ffffffffULL);
2385: tcg_gen_and_i64(tmp, tmp, tmp2);
2386: break;
2387: case 0x9:
2388: tmp2 = tcg_const_i64(((uint64_t)i2) << 32);
2389: tcg_gen_or_i64(tmp, tmp, tmp2);
2390: break;
2391: default:
2392: tcg_abort();
2393: }
2394: store_reg(r1, tmp);
2395: tcg_gen_shri_i64(tmp2, tmp, 32);
2396: tcg_gen_trunc_i64_i32(tmp32, tmp2);
2397: tcg_gen_andi_i32(tmp32, tmp32, 0xffff);
2398: set_cc_nz_u32(s, tmp32);
2399: tcg_temp_free_i64(tmp2);
2400: tcg_temp_free_i32(tmp32);
2401: tcg_temp_free_i64(tmp);
2402: break;
2403: case 0x6: /* NILH R1,I2 [RI] */
2404: case 0xa: /* OILH R1,I2 [RI] */
2405: tmp = load_reg(r1);
2406: tmp32 = tcg_temp_new_i32();
2407: switch (op) {
2408: case 0x6:
2409: tmp2 = tcg_const_i64((((uint64_t)i2) << 16)
2410: | 0xffffffff0000ffffULL);
2411: tcg_gen_and_i64(tmp, tmp, tmp2);
2412: break;
2413: case 0xa:
2414: tmp2 = tcg_const_i64(((uint64_t)i2) << 16);
2415: tcg_gen_or_i64(tmp, tmp, tmp2);
2416: break;
2417: default:
2418: tcg_abort();
2419: }
2420: store_reg(r1, tmp);
2421: tcg_gen_shri_i64(tmp, tmp, 16);
2422: tcg_gen_trunc_i64_i32(tmp32, tmp);
2423: tcg_gen_andi_i32(tmp32, tmp32, 0xffff);
2424: set_cc_nz_u32(s, tmp32);
2425: tcg_temp_free_i64(tmp2);
2426: tcg_temp_free_i32(tmp32);
2427: tcg_temp_free_i64(tmp);
2428: break;
2429: case 0x7: /* NILL R1,I2 [RI] */
2430: case 0xb: /* OILL R1,I2 [RI] */
2431: tmp = load_reg(r1);
2432: tmp32 = tcg_temp_new_i32();
2433: switch (op) {
2434: case 0x7:
2435: tmp2 = tcg_const_i64(i2 | 0xffffffffffff0000ULL);
2436: tcg_gen_and_i64(tmp, tmp, tmp2);
2437: break;
2438: case 0xb:
2439: tmp2 = tcg_const_i64(i2);
2440: tcg_gen_or_i64(tmp, tmp, tmp2);
2441: break;
2442: default:
2443: tcg_abort();
2444: }
2445: store_reg(r1, tmp);
2446: tcg_gen_trunc_i64_i32(tmp32, tmp);
2447: tcg_gen_andi_i32(tmp32, tmp32, 0xffff);
2448: set_cc_nz_u32(s, tmp32); /* signedness should not matter here */
2449: tcg_temp_free_i64(tmp2);
2450: tcg_temp_free_i32(tmp32);
2451: tcg_temp_free_i64(tmp);
2452: break;
2453: case 0xc: /* LLIHH R1,I2 [RI] */
2454: tmp = tcg_const_i64( ((uint64_t)i2) << 48 );
2455: store_reg(r1, tmp);
2456: tcg_temp_free_i64(tmp);
2457: break;
2458: case 0xd: /* LLIHL R1,I2 [RI] */
2459: tmp = tcg_const_i64( ((uint64_t)i2) << 32 );
2460: store_reg(r1, tmp);
2461: tcg_temp_free_i64(tmp);
2462: break;
2463: case 0xe: /* LLILH R1,I2 [RI] */
2464: tmp = tcg_const_i64( ((uint64_t)i2) << 16 );
2465: store_reg(r1, tmp);
2466: tcg_temp_free_i64(tmp);
2467: break;
2468: case 0xf: /* LLILL R1,I2 [RI] */
2469: tmp = tcg_const_i64(i2);
2470: store_reg(r1, tmp);
2471: tcg_temp_free_i64(tmp);
2472: break;
2473: default:
2474: LOG_DISAS("illegal a5 operation 0x%x\n", op);
2475: gen_illegal_opcode(s, 2);
2476: return;
2477: }
2478: }
2479:
2480: static void disas_a7(DisasContext *s, int op, int r1, int i2)
2481: {
2482: TCGv_i64 tmp, tmp2;
2483: TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
2484: int l1;
2485:
2486: LOG_DISAS("disas_a7: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
2487: switch (op) {
2488: case 0x0: /* TMLH or TMH R1,I2 [RI] */
2489: case 0x1: /* TMLL or TML R1,I2 [RI] */
2490: case 0x2: /* TMHH R1,I2 [RI] */
2491: case 0x3: /* TMHL R1,I2 [RI] */
2492: tmp = load_reg(r1);
2493: tmp2 = tcg_const_i64((uint16_t)i2);
2494: switch (op) {
2495: case 0x0:
2496: tcg_gen_shri_i64(tmp, tmp, 16);
2497: break;
2498: case 0x1:
2499: break;
2500: case 0x2:
2501: tcg_gen_shri_i64(tmp, tmp, 48);
2502: break;
2503: case 0x3:
2504: tcg_gen_shri_i64(tmp, tmp, 32);
2505: break;
2506: }
2507: tcg_gen_andi_i64(tmp, tmp, 0xffff);
2508: cmp_64(s, tmp, tmp2, CC_OP_TM_64);
2509: tcg_temp_free_i64(tmp);
2510: tcg_temp_free_i64(tmp2);
2511: break;
2512: case 0x4: /* brc m1, i2 */
2513: gen_brc(r1, s, i2 * 2LL);
2514: return;
2515: case 0x5: /* BRAS R1,I2 [RI] */
2516: tmp = tcg_const_i64(pc_to_link_info(s, s->pc + 4));
2517: store_reg(r1, tmp);
2518: tcg_temp_free_i64(tmp);
2519: gen_goto_tb(s, 0, s->pc + i2 * 2LL);
2520: s->is_jmp = DISAS_TB_JUMP;
2521: break;
2522: case 0x6: /* BRCT R1,I2 [RI] */
2523: tmp32_1 = load_reg32(r1);
2524: tcg_gen_subi_i32(tmp32_1, tmp32_1, 1);
2525: store_reg32(r1, tmp32_1);
2526: gen_update_cc_op(s);
2527: l1 = gen_new_label();
2528: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp32_1, 0, l1);
2529: gen_goto_tb(s, 0, s->pc + (i2 * 2LL));
2530: gen_set_label(l1);
2531: gen_goto_tb(s, 1, s->pc + 4);
2532: s->is_jmp = DISAS_TB_JUMP;
2533: tcg_temp_free_i32(tmp32_1);
2534: break;
2535: case 0x7: /* BRCTG R1,I2 [RI] */
2536: tmp = load_reg(r1);
2537: tcg_gen_subi_i64(tmp, tmp, 1);
2538: store_reg(r1, tmp);
2539: gen_update_cc_op(s);
2540: l1 = gen_new_label();
2541: tcg_gen_brcondi_i64(TCG_COND_EQ, tmp, 0, l1);
2542: gen_goto_tb(s, 0, s->pc + (i2 * 2LL));
2543: gen_set_label(l1);
2544: gen_goto_tb(s, 1, s->pc + 4);
2545: s->is_jmp = DISAS_TB_JUMP;
2546: tcg_temp_free_i64(tmp);
2547: break;
2548: case 0x8: /* lhi r1, i2 */
2549: tmp32_1 = tcg_const_i32(i2);
2550: store_reg32(r1, tmp32_1);
2551: tcg_temp_free_i32(tmp32_1);
2552: break;
2553: case 0x9: /* lghi r1, i2 */
2554: tmp = tcg_const_i64(i2);
2555: store_reg(r1, tmp);
2556: tcg_temp_free_i64(tmp);
2557: break;
2558: case 0xa: /* AHI R1,I2 [RI] */
2559: tmp32_1 = load_reg32(r1);
2560: tmp32_2 = tcg_temp_new_i32();
2561: tmp32_3 = tcg_const_i32(i2);
2562:
2563: if (i2 < 0) {
2564: tcg_gen_subi_i32(tmp32_2, tmp32_1, -i2);
2565: } else {
2566: tcg_gen_add_i32(tmp32_2, tmp32_1, tmp32_3);
2567: }
2568:
2569: store_reg32(r1, tmp32_2);
2570: set_cc_add32(s, tmp32_1, tmp32_3, tmp32_2);
2571: tcg_temp_free_i32(tmp32_1);
2572: tcg_temp_free_i32(tmp32_2);
2573: tcg_temp_free_i32(tmp32_3);
2574: break;
2575: case 0xb: /* aghi r1, i2 */
2576: tmp = load_reg(r1);
2577: tmp2 = tcg_const_i64(i2);
2578:
2579: if (i2 < 0) {
2580: tcg_gen_subi_i64(regs[r1], tmp, -i2);
2581: } else {
2582: tcg_gen_add_i64(regs[r1], tmp, tmp2);
2583: }
2584: set_cc_add64(s, tmp, tmp2, regs[r1]);
2585: tcg_temp_free_i64(tmp);
2586: tcg_temp_free_i64(tmp2);
2587: break;
2588: case 0xc: /* MHI R1,I2 [RI] */
2589: tmp32_1 = load_reg32(r1);
2590: tcg_gen_muli_i32(tmp32_1, tmp32_1, i2);
2591: store_reg32(r1, tmp32_1);
2592: tcg_temp_free_i32(tmp32_1);
2593: break;
2594: case 0xd: /* MGHI R1,I2 [RI] */
2595: tmp = load_reg(r1);
2596: tcg_gen_muli_i64(tmp, tmp, i2);
2597: store_reg(r1, tmp);
2598: tcg_temp_free_i64(tmp);
2599: break;
2600: case 0xe: /* CHI R1,I2 [RI] */
2601: tmp32_1 = load_reg32(r1);
2602: cmp_s32c(s, tmp32_1, i2);
2603: tcg_temp_free_i32(tmp32_1);
2604: break;
2605: case 0xf: /* CGHI R1,I2 [RI] */
2606: tmp = load_reg(r1);
2607: cmp_s64c(s, tmp, i2);
2608: tcg_temp_free_i64(tmp);
2609: break;
2610: default:
2611: LOG_DISAS("illegal a7 operation 0x%x\n", op);
2612: gen_illegal_opcode(s, 2);
2613: return;
2614: }
2615: }
2616:
2617: static void disas_b2(DisasContext *s, int op, uint32_t insn)
2618: {
2619: TCGv_i64 tmp, tmp2, tmp3;
2620: TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
2621: int r1, r2;
2622: int ilc = 2;
2623: #ifndef CONFIG_USER_ONLY
2624: int r3, d2, b2;
2625: #endif
2626:
2627: r1 = (insn >> 4) & 0xf;
2628: r2 = insn & 0xf;
2629:
2630: LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
2631:
2632: switch (op) {
2633: case 0x22: /* IPM R1 [RRE] */
2634: tmp32_1 = tcg_const_i32(r1);
2635: gen_op_calc_cc(s);
2636: gen_helper_ipm(cc_op, tmp32_1);
2637: tcg_temp_free_i32(tmp32_1);
2638: break;
2639: case 0x41: /* CKSM R1,R2 [RRE] */
2640: tmp32_1 = tcg_const_i32(r1);
2641: tmp32_2 = tcg_const_i32(r2);
2642: potential_page_fault(s);
2643: gen_helper_cksm(tmp32_1, tmp32_2);
2644: tcg_temp_free_i32(tmp32_1);
2645: tcg_temp_free_i32(tmp32_2);
2646: gen_op_movi_cc(s, 0);
2647: break;
2648: case 0x4e: /* SAR R1,R2 [RRE] */
2649: tmp32_1 = load_reg32(r2);
1.1.1.6 ! root 2650: tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
1.1.1.4 root 2651: tcg_temp_free_i32(tmp32_1);
2652: break;
2653: case 0x4f: /* EAR R1,R2 [RRE] */
2654: tmp32_1 = tcg_temp_new_i32();
1.1.1.6 ! root 2655: tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r2]));
1.1.1.4 root 2656: store_reg32(r1, tmp32_1);
2657: tcg_temp_free_i32(tmp32_1);
2658: break;
2659: case 0x52: /* MSR R1,R2 [RRE] */
2660: tmp32_1 = load_reg32(r1);
2661: tmp32_2 = load_reg32(r2);
2662: tcg_gen_mul_i32(tmp32_1, tmp32_1, tmp32_2);
2663: store_reg32(r1, tmp32_1);
2664: tcg_temp_free_i32(tmp32_1);
2665: tcg_temp_free_i32(tmp32_2);
2666: break;
2667: case 0x54: /* MVPG R1,R2 [RRE] */
2668: tmp = load_reg(0);
2669: tmp2 = load_reg(r1);
2670: tmp3 = load_reg(r2);
2671: potential_page_fault(s);
2672: gen_helper_mvpg(tmp, tmp2, tmp3);
2673: tcg_temp_free_i64(tmp);
2674: tcg_temp_free_i64(tmp2);
2675: tcg_temp_free_i64(tmp3);
2676: /* XXX check CCO bit and set CC accordingly */
2677: gen_op_movi_cc(s, 0);
2678: break;
2679: case 0x55: /* MVST R1,R2 [RRE] */
2680: tmp32_1 = load_reg32(0);
2681: tmp32_2 = tcg_const_i32(r1);
2682: tmp32_3 = tcg_const_i32(r2);
2683: potential_page_fault(s);
2684: gen_helper_mvst(tmp32_1, tmp32_2, tmp32_3);
2685: tcg_temp_free_i32(tmp32_1);
2686: tcg_temp_free_i32(tmp32_2);
2687: tcg_temp_free_i32(tmp32_3);
2688: gen_op_movi_cc(s, 1);
2689: break;
2690: case 0x5d: /* CLST R1,R2 [RRE] */
2691: tmp32_1 = load_reg32(0);
2692: tmp32_2 = tcg_const_i32(r1);
2693: tmp32_3 = tcg_const_i32(r2);
2694: potential_page_fault(s);
2695: gen_helper_clst(cc_op, tmp32_1, tmp32_2, tmp32_3);
2696: set_cc_static(s);
2697: tcg_temp_free_i32(tmp32_1);
2698: tcg_temp_free_i32(tmp32_2);
2699: tcg_temp_free_i32(tmp32_3);
2700: break;
2701: case 0x5e: /* SRST R1,R2 [RRE] */
2702: tmp32_1 = load_reg32(0);
2703: tmp32_2 = tcg_const_i32(r1);
2704: tmp32_3 = tcg_const_i32(r2);
2705: potential_page_fault(s);
2706: gen_helper_srst(cc_op, tmp32_1, tmp32_2, tmp32_3);
2707: set_cc_static(s);
2708: tcg_temp_free_i32(tmp32_1);
2709: tcg_temp_free_i32(tmp32_2);
2710: tcg_temp_free_i32(tmp32_3);
2711: break;
2712:
2713: #ifndef CONFIG_USER_ONLY
2714: case 0x02: /* STIDP D2(B2) [S] */
2715: /* Store CPU ID */
2716: check_privileged(s, ilc);
2717: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2718: tmp = get_address(s, 0, b2, d2);
2719: potential_page_fault(s);
2720: gen_helper_stidp(tmp);
2721: tcg_temp_free_i64(tmp);
2722: break;
2723: case 0x04: /* SCK D2(B2) [S] */
2724: /* Set Clock */
2725: check_privileged(s, ilc);
2726: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2727: tmp = get_address(s, 0, b2, d2);
2728: potential_page_fault(s);
2729: gen_helper_sck(cc_op, tmp);
2730: set_cc_static(s);
2731: tcg_temp_free_i64(tmp);
2732: break;
2733: case 0x05: /* STCK D2(B2) [S] */
2734: /* Store Clock */
2735: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2736: tmp = get_address(s, 0, b2, d2);
2737: potential_page_fault(s);
2738: gen_helper_stck(cc_op, tmp);
2739: set_cc_static(s);
2740: tcg_temp_free_i64(tmp);
2741: break;
2742: case 0x06: /* SCKC D2(B2) [S] */
2743: /* Set Clock Comparator */
2744: check_privileged(s, ilc);
2745: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2746: tmp = get_address(s, 0, b2, d2);
2747: potential_page_fault(s);
2748: gen_helper_sckc(tmp);
2749: tcg_temp_free_i64(tmp);
2750: break;
2751: case 0x07: /* STCKC D2(B2) [S] */
2752: /* Store Clock Comparator */
2753: check_privileged(s, ilc);
2754: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2755: tmp = get_address(s, 0, b2, d2);
2756: potential_page_fault(s);
2757: gen_helper_stckc(tmp);
2758: tcg_temp_free_i64(tmp);
2759: break;
2760: case 0x08: /* SPT D2(B2) [S] */
2761: /* Set CPU Timer */
2762: check_privileged(s, ilc);
2763: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2764: tmp = get_address(s, 0, b2, d2);
2765: potential_page_fault(s);
2766: gen_helper_spt(tmp);
2767: tcg_temp_free_i64(tmp);
2768: break;
2769: case 0x09: /* STPT D2(B2) [S] */
2770: /* Store CPU Timer */
2771: check_privileged(s, ilc);
2772: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2773: tmp = get_address(s, 0, b2, d2);
2774: potential_page_fault(s);
2775: gen_helper_stpt(tmp);
2776: tcg_temp_free_i64(tmp);
2777: break;
2778: case 0x0a: /* SPKA D2(B2) [S] */
2779: /* Set PSW Key from Address */
2780: check_privileged(s, ilc);
2781: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2782: tmp = get_address(s, 0, b2, d2);
2783: tmp2 = tcg_temp_new_i64();
2784: tcg_gen_andi_i64(tmp2, psw_mask, ~PSW_MASK_KEY);
2785: tcg_gen_shli_i64(tmp, tmp, PSW_SHIFT_KEY - 4);
2786: tcg_gen_or_i64(psw_mask, tmp2, tmp);
2787: tcg_temp_free_i64(tmp2);
2788: tcg_temp_free_i64(tmp);
2789: break;
2790: case 0x0d: /* PTLB [S] */
2791: /* Purge TLB */
2792: check_privileged(s, ilc);
2793: gen_helper_ptlb();
2794: break;
2795: case 0x10: /* SPX D2(B2) [S] */
2796: /* Set Prefix Register */
2797: check_privileged(s, ilc);
2798: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2799: tmp = get_address(s, 0, b2, d2);
2800: potential_page_fault(s);
2801: gen_helper_spx(tmp);
2802: tcg_temp_free_i64(tmp);
2803: break;
2804: case 0x11: /* STPX D2(B2) [S] */
2805: /* Store Prefix */
2806: check_privileged(s, ilc);
2807: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2808: tmp = get_address(s, 0, b2, d2);
2809: tmp2 = tcg_temp_new_i64();
1.1.1.6 ! root 2810: tcg_gen_ld_i64(tmp2, cpu_env, offsetof(CPUS390XState, psa));
1.1.1.4 root 2811: tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
2812: tcg_temp_free_i64(tmp);
2813: tcg_temp_free_i64(tmp2);
2814: break;
2815: case 0x12: /* STAP D2(B2) [S] */
2816: /* Store CPU Address */
2817: check_privileged(s, ilc);
2818: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2819: tmp = get_address(s, 0, b2, d2);
2820: tmp2 = tcg_temp_new_i64();
2821: tmp32_1 = tcg_temp_new_i32();
1.1.1.6 ! root 2822: tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, cpu_num));
1.1.1.4 root 2823: tcg_gen_extu_i32_i64(tmp2, tmp32_1);
2824: tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
2825: tcg_temp_free_i64(tmp);
2826: tcg_temp_free_i64(tmp2);
2827: tcg_temp_free_i32(tmp32_1);
2828: break;
2829: case 0x21: /* IPTE R1,R2 [RRE] */
2830: /* Invalidate PTE */
2831: check_privileged(s, ilc);
2832: r1 = (insn >> 4) & 0xf;
2833: r2 = insn & 0xf;
2834: tmp = load_reg(r1);
2835: tmp2 = load_reg(r2);
2836: gen_helper_ipte(tmp, tmp2);
2837: tcg_temp_free_i64(tmp);
2838: tcg_temp_free_i64(tmp2);
2839: break;
2840: case 0x29: /* ISKE R1,R2 [RRE] */
2841: /* Insert Storage Key Extended */
2842: check_privileged(s, ilc);
2843: r1 = (insn >> 4) & 0xf;
2844: r2 = insn & 0xf;
2845: tmp = load_reg(r2);
2846: tmp2 = tcg_temp_new_i64();
2847: gen_helper_iske(tmp2, tmp);
2848: store_reg(r1, tmp2);
2849: tcg_temp_free_i64(tmp);
2850: tcg_temp_free_i64(tmp2);
2851: break;
2852: case 0x2a: /* RRBE R1,R2 [RRE] */
2853: /* Set Storage Key Extended */
2854: check_privileged(s, ilc);
2855: r1 = (insn >> 4) & 0xf;
2856: r2 = insn & 0xf;
2857: tmp32_1 = load_reg32(r1);
2858: tmp = load_reg(r2);
2859: gen_helper_rrbe(cc_op, tmp32_1, tmp);
2860: set_cc_static(s);
2861: tcg_temp_free_i32(tmp32_1);
2862: tcg_temp_free_i64(tmp);
2863: break;
2864: case 0x2b: /* SSKE R1,R2 [RRE] */
2865: /* Set Storage Key Extended */
2866: check_privileged(s, ilc);
2867: r1 = (insn >> 4) & 0xf;
2868: r2 = insn & 0xf;
2869: tmp32_1 = load_reg32(r1);
2870: tmp = load_reg(r2);
2871: gen_helper_sske(tmp32_1, tmp);
2872: tcg_temp_free_i32(tmp32_1);
2873: tcg_temp_free_i64(tmp);
2874: break;
2875: case 0x34: /* STCH ? */
2876: /* Store Subchannel */
2877: check_privileged(s, ilc);
2878: gen_op_movi_cc(s, 3);
2879: break;
2880: case 0x46: /* STURA R1,R2 [RRE] */
2881: /* Store Using Real Address */
2882: check_privileged(s, ilc);
2883: r1 = (insn >> 4) & 0xf;
2884: r2 = insn & 0xf;
2885: tmp32_1 = load_reg32(r1);
2886: tmp = load_reg(r2);
2887: potential_page_fault(s);
2888: gen_helper_stura(tmp, tmp32_1);
2889: tcg_temp_free_i32(tmp32_1);
2890: tcg_temp_free_i64(tmp);
2891: break;
2892: case 0x50: /* CSP R1,R2 [RRE] */
2893: /* Compare And Swap And Purge */
2894: check_privileged(s, ilc);
2895: r1 = (insn >> 4) & 0xf;
2896: r2 = insn & 0xf;
2897: tmp32_1 = tcg_const_i32(r1);
2898: tmp32_2 = tcg_const_i32(r2);
2899: gen_helper_csp(cc_op, tmp32_1, tmp32_2);
2900: set_cc_static(s);
2901: tcg_temp_free_i32(tmp32_1);
2902: tcg_temp_free_i32(tmp32_2);
2903: break;
2904: case 0x5f: /* CHSC ? */
2905: /* Channel Subsystem Call */
2906: check_privileged(s, ilc);
2907: gen_op_movi_cc(s, 3);
2908: break;
2909: case 0x78: /* STCKE D2(B2) [S] */
2910: /* Store Clock Extended */
2911: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2912: tmp = get_address(s, 0, b2, d2);
2913: potential_page_fault(s);
2914: gen_helper_stcke(cc_op, tmp);
2915: set_cc_static(s);
2916: tcg_temp_free_i64(tmp);
2917: break;
2918: case 0x79: /* SACF D2(B2) [S] */
2919: /* Store Clock Extended */
2920: check_privileged(s, ilc);
2921: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2922: tmp = get_address(s, 0, b2, d2);
2923: potential_page_fault(s);
2924: gen_helper_sacf(tmp);
2925: tcg_temp_free_i64(tmp);
2926: /* addressing mode has changed, so end the block */
2927: s->pc += ilc * 2;
2928: update_psw_addr(s);
2929: s->is_jmp = DISAS_EXCP;
2930: break;
2931: case 0x7d: /* STSI D2,(B2) [S] */
2932: check_privileged(s, ilc);
2933: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2934: tmp = get_address(s, 0, b2, d2);
2935: tmp32_1 = load_reg32(0);
2936: tmp32_2 = load_reg32(1);
2937: potential_page_fault(s);
2938: gen_helper_stsi(cc_op, tmp, tmp32_1, tmp32_2);
2939: set_cc_static(s);
2940: tcg_temp_free_i64(tmp);
2941: tcg_temp_free_i32(tmp32_1);
2942: tcg_temp_free_i32(tmp32_2);
2943: break;
2944: case 0x9d: /* LFPC D2(B2) [S] */
2945: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2946: tmp = get_address(s, 0, b2, d2);
2947: tmp2 = tcg_temp_new_i64();
2948: tmp32_1 = tcg_temp_new_i32();
2949: tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
2950: tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
1.1.1.6 ! root 2951: tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
1.1.1.4 root 2952: tcg_temp_free_i64(tmp);
2953: tcg_temp_free_i64(tmp2);
2954: tcg_temp_free_i32(tmp32_1);
2955: break;
2956: case 0xb1: /* STFL D2(B2) [S] */
2957: /* Store Facility List (CPU features) at 200 */
2958: check_privileged(s, ilc);
2959: tmp2 = tcg_const_i64(0xc0000000);
2960: tmp = tcg_const_i64(200);
2961: tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
2962: tcg_temp_free_i64(tmp2);
2963: tcg_temp_free_i64(tmp);
2964: break;
2965: case 0xb2: /* LPSWE D2(B2) [S] */
2966: /* Load PSW Extended */
2967: check_privileged(s, ilc);
2968: decode_rs(s, insn, &r1, &r3, &b2, &d2);
2969: tmp = get_address(s, 0, b2, d2);
2970: tmp2 = tcg_temp_new_i64();
2971: tmp3 = tcg_temp_new_i64();
2972: tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
2973: tcg_gen_addi_i64(tmp, tmp, 8);
2974: tcg_gen_qemu_ld64(tmp3, tmp, get_mem_index(s));
2975: gen_helper_load_psw(tmp2, tmp3);
2976: /* we need to keep cc_op intact */
2977: s->is_jmp = DISAS_JUMP;
2978: tcg_temp_free_i64(tmp);
2979: tcg_temp_free_i64(tmp2);
2980: tcg_temp_free_i64(tmp3);
2981: break;
2982: case 0x20: /* SERVC R1,R2 [RRE] */
2983: /* SCLP Service call (PV hypercall) */
2984: check_privileged(s, ilc);
2985: potential_page_fault(s);
2986: tmp32_1 = load_reg32(r2);
2987: tmp = load_reg(r1);
2988: gen_helper_servc(cc_op, tmp32_1, tmp);
2989: set_cc_static(s);
2990: tcg_temp_free_i32(tmp32_1);
2991: tcg_temp_free_i64(tmp);
2992: break;
2993: #endif
2994: default:
2995: LOG_DISAS("illegal b2 operation 0x%x\n", op);
2996: gen_illegal_opcode(s, ilc);
2997: break;
2998: }
2999: }
3000:
3001: static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
3002: {
3003: TCGv_i64 tmp;
3004: TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
3005: LOG_DISAS("disas_b3: op 0x%x m3 0x%x r1 %d r2 %d\n", op, m3, r1, r2);
3006: #define FP_HELPER(i) \
3007: tmp32_1 = tcg_const_i32(r1); \
3008: tmp32_2 = tcg_const_i32(r2); \
3009: gen_helper_ ## i (tmp32_1, tmp32_2); \
3010: tcg_temp_free_i32(tmp32_1); \
3011: tcg_temp_free_i32(tmp32_2);
3012:
3013: #define FP_HELPER_CC(i) \
3014: tmp32_1 = tcg_const_i32(r1); \
3015: tmp32_2 = tcg_const_i32(r2); \
3016: gen_helper_ ## i (cc_op, tmp32_1, tmp32_2); \
3017: set_cc_static(s); \
3018: tcg_temp_free_i32(tmp32_1); \
3019: tcg_temp_free_i32(tmp32_2);
3020:
3021: switch (op) {
3022: case 0x0: /* LPEBR R1,R2 [RRE] */
3023: FP_HELPER_CC(lpebr);
3024: break;
3025: case 0x2: /* LTEBR R1,R2 [RRE] */
3026: FP_HELPER_CC(ltebr);
3027: break;
3028: case 0x3: /* LCEBR R1,R2 [RRE] */
3029: FP_HELPER_CC(lcebr);
3030: break;
3031: case 0x4: /* LDEBR R1,R2 [RRE] */
3032: FP_HELPER(ldebr);
3033: break;
3034: case 0x5: /* LXDBR R1,R2 [RRE] */
3035: FP_HELPER(lxdbr);
3036: break;
3037: case 0x9: /* CEBR R1,R2 [RRE] */
3038: FP_HELPER_CC(cebr);
3039: break;
3040: case 0xa: /* AEBR R1,R2 [RRE] */
3041: FP_HELPER_CC(aebr);
3042: break;
3043: case 0xb: /* SEBR R1,R2 [RRE] */
3044: FP_HELPER_CC(sebr);
3045: break;
3046: case 0xd: /* DEBR R1,R2 [RRE] */
3047: FP_HELPER(debr);
3048: break;
3049: case 0x10: /* LPDBR R1,R2 [RRE] */
3050: FP_HELPER_CC(lpdbr);
3051: break;
3052: case 0x12: /* LTDBR R1,R2 [RRE] */
3053: FP_HELPER_CC(ltdbr);
3054: break;
3055: case 0x13: /* LCDBR R1,R2 [RRE] */
3056: FP_HELPER_CC(lcdbr);
3057: break;
3058: case 0x15: /* SQBDR R1,R2 [RRE] */
3059: FP_HELPER(sqdbr);
3060: break;
3061: case 0x17: /* MEEBR R1,R2 [RRE] */
3062: FP_HELPER(meebr);
3063: break;
3064: case 0x19: /* CDBR R1,R2 [RRE] */
3065: FP_HELPER_CC(cdbr);
3066: break;
3067: case 0x1a: /* ADBR R1,R2 [RRE] */
3068: FP_HELPER_CC(adbr);
3069: break;
3070: case 0x1b: /* SDBR R1,R2 [RRE] */
3071: FP_HELPER_CC(sdbr);
3072: break;
3073: case 0x1c: /* MDBR R1,R2 [RRE] */
3074: FP_HELPER(mdbr);
3075: break;
3076: case 0x1d: /* DDBR R1,R2 [RRE] */
3077: FP_HELPER(ddbr);
3078: break;
3079: case 0xe: /* MAEBR R1,R3,R2 [RRF] */
3080: case 0x1e: /* MADBR R1,R3,R2 [RRF] */
3081: case 0x1f: /* MSDBR R1,R3,R2 [RRF] */
3082: /* for RRF insns, m3 is R1, r1 is R3, and r2 is R2 */
3083: tmp32_1 = tcg_const_i32(m3);
3084: tmp32_2 = tcg_const_i32(r2);
3085: tmp32_3 = tcg_const_i32(r1);
3086: switch (op) {
3087: case 0xe:
3088: gen_helper_maebr(tmp32_1, tmp32_3, tmp32_2);
3089: break;
3090: case 0x1e:
3091: gen_helper_madbr(tmp32_1, tmp32_3, tmp32_2);
3092: break;
3093: case 0x1f:
3094: gen_helper_msdbr(tmp32_1, tmp32_3, tmp32_2);
3095: break;
3096: default:
3097: tcg_abort();
3098: }
3099: tcg_temp_free_i32(tmp32_1);
3100: tcg_temp_free_i32(tmp32_2);
3101: tcg_temp_free_i32(tmp32_3);
3102: break;
3103: case 0x40: /* LPXBR R1,R2 [RRE] */
3104: FP_HELPER_CC(lpxbr);
3105: break;
3106: case 0x42: /* LTXBR R1,R2 [RRE] */
3107: FP_HELPER_CC(ltxbr);
3108: break;
3109: case 0x43: /* LCXBR R1,R2 [RRE] */
3110: FP_HELPER_CC(lcxbr);
3111: break;
3112: case 0x44: /* LEDBR R1,R2 [RRE] */
3113: FP_HELPER(ledbr);
3114: break;
3115: case 0x45: /* LDXBR R1,R2 [RRE] */
3116: FP_HELPER(ldxbr);
3117: break;
3118: case 0x46: /* LEXBR R1,R2 [RRE] */
3119: FP_HELPER(lexbr);
3120: break;
3121: case 0x49: /* CXBR R1,R2 [RRE] */
3122: FP_HELPER_CC(cxbr);
3123: break;
3124: case 0x4a: /* AXBR R1,R2 [RRE] */
3125: FP_HELPER_CC(axbr);
3126: break;
3127: case 0x4b: /* SXBR R1,R2 [RRE] */
3128: FP_HELPER_CC(sxbr);
3129: break;
3130: case 0x4c: /* MXBR R1,R2 [RRE] */
3131: FP_HELPER(mxbr);
3132: break;
3133: case 0x4d: /* DXBR R1,R2 [RRE] */
3134: FP_HELPER(dxbr);
3135: break;
3136: case 0x65: /* LXR R1,R2 [RRE] */
3137: tmp = load_freg(r2);
3138: store_freg(r1, tmp);
3139: tcg_temp_free_i64(tmp);
3140: tmp = load_freg(r2 + 2);
3141: store_freg(r1 + 2, tmp);
3142: tcg_temp_free_i64(tmp);
3143: break;
3144: case 0x74: /* LZER R1 [RRE] */
3145: tmp32_1 = tcg_const_i32(r1);
3146: gen_helper_lzer(tmp32_1);
3147: tcg_temp_free_i32(tmp32_1);
3148: break;
3149: case 0x75: /* LZDR R1 [RRE] */
3150: tmp32_1 = tcg_const_i32(r1);
3151: gen_helper_lzdr(tmp32_1);
3152: tcg_temp_free_i32(tmp32_1);
3153: break;
3154: case 0x76: /* LZXR R1 [RRE] */
3155: tmp32_1 = tcg_const_i32(r1);
3156: gen_helper_lzxr(tmp32_1);
3157: tcg_temp_free_i32(tmp32_1);
3158: break;
3159: case 0x84: /* SFPC R1 [RRE] */
3160: tmp32_1 = load_reg32(r1);
1.1.1.6 ! root 3161: tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
1.1.1.4 root 3162: tcg_temp_free_i32(tmp32_1);
3163: break;
3164: case 0x8c: /* EFPC R1 [RRE] */
3165: tmp32_1 = tcg_temp_new_i32();
1.1.1.6 ! root 3166: tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
1.1.1.4 root 3167: store_reg32(r1, tmp32_1);
3168: tcg_temp_free_i32(tmp32_1);
3169: break;
3170: case 0x94: /* CEFBR R1,R2 [RRE] */
3171: case 0x95: /* CDFBR R1,R2 [RRE] */
3172: case 0x96: /* CXFBR R1,R2 [RRE] */
3173: tmp32_1 = tcg_const_i32(r1);
3174: tmp32_2 = load_reg32(r2);
3175: switch (op) {
3176: case 0x94:
3177: gen_helper_cefbr(tmp32_1, tmp32_2);
3178: break;
3179: case 0x95:
3180: gen_helper_cdfbr(tmp32_1, tmp32_2);
3181: break;
3182: case 0x96:
3183: gen_helper_cxfbr(tmp32_1, tmp32_2);
3184: break;
3185: default:
3186: tcg_abort();
3187: }
3188: tcg_temp_free_i32(tmp32_1);
3189: tcg_temp_free_i32(tmp32_2);
3190: break;
3191: case 0x98: /* CFEBR R1,R2 [RRE] */
3192: case 0x99: /* CFDBR R1,R2 [RRE] */
3193: case 0x9a: /* CFXBR R1,R2 [RRE] */
3194: tmp32_1 = tcg_const_i32(r1);
3195: tmp32_2 = tcg_const_i32(r2);
3196: tmp32_3 = tcg_const_i32(m3);
3197: switch (op) {
3198: case 0x98:
3199: gen_helper_cfebr(cc_op, tmp32_1, tmp32_2, tmp32_3);
3200: break;
3201: case 0x99:
3202: gen_helper_cfdbr(cc_op, tmp32_1, tmp32_2, tmp32_3);
3203: break;
3204: case 0x9a:
3205: gen_helper_cfxbr(cc_op, tmp32_1, tmp32_2, tmp32_3);
3206: break;
3207: default:
3208: tcg_abort();
3209: }
3210: set_cc_static(s);
3211: tcg_temp_free_i32(tmp32_1);
3212: tcg_temp_free_i32(tmp32_2);
3213: tcg_temp_free_i32(tmp32_3);
3214: break;
3215: case 0xa4: /* CEGBR R1,R2 [RRE] */
3216: case 0xa5: /* CDGBR R1,R2 [RRE] */
3217: tmp32_1 = tcg_const_i32(r1);
3218: tmp = load_reg(r2);
3219: switch (op) {
3220: case 0xa4:
3221: gen_helper_cegbr(tmp32_1, tmp);
3222: break;
3223: case 0xa5:
3224: gen_helper_cdgbr(tmp32_1, tmp);
3225: break;
3226: default:
3227: tcg_abort();
3228: }
3229: tcg_temp_free_i32(tmp32_1);
3230: tcg_temp_free_i64(tmp);
3231: break;
3232: case 0xa6: /* CXGBR R1,R2 [RRE] */
3233: tmp32_1 = tcg_const_i32(r1);
3234: tmp = load_reg(r2);
3235: gen_helper_cxgbr(tmp32_1, tmp);
3236: tcg_temp_free_i32(tmp32_1);
3237: tcg_temp_free_i64(tmp);
3238: break;
3239: case 0xa8: /* CGEBR R1,R2 [RRE] */
3240: tmp32_1 = tcg_const_i32(r1);
3241: tmp32_2 = tcg_const_i32(r2);
3242: tmp32_3 = tcg_const_i32(m3);
3243: gen_helper_cgebr(cc_op, tmp32_1, tmp32_2, tmp32_3);
3244: set_cc_static(s);
3245: tcg_temp_free_i32(tmp32_1);
3246: tcg_temp_free_i32(tmp32_2);
3247: tcg_temp_free_i32(tmp32_3);
3248: break;
3249: case 0xa9: /* CGDBR R1,R2 [RRE] */
3250: tmp32_1 = tcg_const_i32(r1);
3251: tmp32_2 = tcg_const_i32(r2);
3252: tmp32_3 = tcg_const_i32(m3);
3253: gen_helper_cgdbr(cc_op, tmp32_1, tmp32_2, tmp32_3);
3254: set_cc_static(s);
3255: tcg_temp_free_i32(tmp32_1);
3256: tcg_temp_free_i32(tmp32_2);
3257: tcg_temp_free_i32(tmp32_3);
3258: break;
3259: case 0xaa: /* CGXBR R1,R2 [RRE] */
3260: tmp32_1 = tcg_const_i32(r1);
3261: tmp32_2 = tcg_const_i32(r2);
3262: tmp32_3 = tcg_const_i32(m3);
3263: gen_helper_cgxbr(cc_op, tmp32_1, tmp32_2, tmp32_3);
3264: set_cc_static(s);
3265: tcg_temp_free_i32(tmp32_1);
3266: tcg_temp_free_i32(tmp32_2);
3267: tcg_temp_free_i32(tmp32_3);
3268: break;
3269: default:
3270: LOG_DISAS("illegal b3 operation 0x%x\n", op);
3271: gen_illegal_opcode(s, 2);
3272: break;
3273: }
3274:
3275: #undef FP_HELPER_CC
3276: #undef FP_HELPER
3277: }
3278:
3279: static void disas_b9(DisasContext *s, int op, int r1, int r2)
3280: {
3281: TCGv_i64 tmp, tmp2, tmp3;
3282: TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
3283:
3284: LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
3285: switch (op) {
3286: case 0x0: /* LPGR R1,R2 [RRE] */
3287: case 0x1: /* LNGR R1,R2 [RRE] */
3288: case 0x2: /* LTGR R1,R2 [RRE] */
3289: case 0x3: /* LCGR R1,R2 [RRE] */
3290: case 0x10: /* LPGFR R1,R2 [RRE] */
3291: case 0x11: /* LNFGR R1,R2 [RRE] */
3292: case 0x12: /* LTGFR R1,R2 [RRE] */
3293: case 0x13: /* LCGFR R1,R2 [RRE] */
3294: if (op & 0x10) {
3295: tmp = load_reg32_i64(r2);
3296: } else {
3297: tmp = load_reg(r2);
3298: }
3299: switch (op & 0xf) {
3300: case 0x0: /* LP?GR */
3301: set_cc_abs64(s, tmp);
3302: gen_helper_abs_i64(tmp, tmp);
3303: store_reg(r1, tmp);
3304: break;
3305: case 0x1: /* LN?GR */
3306: set_cc_nabs64(s, tmp);
3307: gen_helper_nabs_i64(tmp, tmp);
3308: store_reg(r1, tmp);
3309: break;
3310: case 0x2: /* LT?GR */
3311: if (r1 != r2) {
3312: store_reg(r1, tmp);
3313: }
3314: set_cc_s64(s, tmp);
3315: break;
3316: case 0x3: /* LC?GR */
3317: tcg_gen_neg_i64(regs[r1], tmp);
3318: set_cc_comp64(s, regs[r1]);
3319: break;
3320: }
3321: tcg_temp_free_i64(tmp);
3322: break;
3323: case 0x4: /* LGR R1,R2 [RRE] */
3324: store_reg(r1, regs[r2]);
3325: break;
3326: case 0x6: /* LGBR R1,R2 [RRE] */
3327: tmp2 = load_reg(r2);
3328: tcg_gen_ext8s_i64(tmp2, tmp2);
3329: store_reg(r1, tmp2);
3330: tcg_temp_free_i64(tmp2);
3331: break;
3332: case 0x8: /* AGR R1,R2 [RRE] */
3333: case 0xa: /* ALGR R1,R2 [RRE] */
3334: tmp = load_reg(r1);
3335: tmp2 = load_reg(r2);
3336: tmp3 = tcg_temp_new_i64();
3337: tcg_gen_add_i64(tmp3, tmp, tmp2);
3338: store_reg(r1, tmp3);
3339: switch (op) {
3340: case 0x8:
3341: set_cc_add64(s, tmp, tmp2, tmp3);
3342: break;
3343: case 0xa:
3344: set_cc_addu64(s, tmp, tmp2, tmp3);
3345: break;
3346: default:
3347: tcg_abort();
3348: }
3349: tcg_temp_free_i64(tmp);
3350: tcg_temp_free_i64(tmp2);
3351: tcg_temp_free_i64(tmp3);
3352: break;
3353: case 0x9: /* SGR R1,R2 [RRE] */
3354: case 0xb: /* SLGR R1,R2 [RRE] */
3355: case 0x1b: /* SLGFR R1,R2 [RRE] */
3356: case 0x19: /* SGFR R1,R2 [RRE] */
3357: tmp = load_reg(r1);
3358: switch (op) {
3359: case 0x1b:
3360: tmp32_1 = load_reg32(r2);
3361: tmp2 = tcg_temp_new_i64();
3362: tcg_gen_extu_i32_i64(tmp2, tmp32_1);
3363: tcg_temp_free_i32(tmp32_1);
3364: break;
3365: case 0x19:
3366: tmp32_1 = load_reg32(r2);
3367: tmp2 = tcg_temp_new_i64();
3368: tcg_gen_ext_i32_i64(tmp2, tmp32_1);
3369: tcg_temp_free_i32(tmp32_1);
3370: break;
3371: default:
3372: tmp2 = load_reg(r2);
3373: break;
3374: }
3375: tmp3 = tcg_temp_new_i64();
3376: tcg_gen_sub_i64(tmp3, tmp, tmp2);
3377: store_reg(r1, tmp3);
3378: switch (op) {
3379: case 0x9:
3380: case 0x19:
3381: set_cc_sub64(s, tmp, tmp2, tmp3);
3382: break;
3383: case 0xb:
3384: case 0x1b:
3385: set_cc_subu64(s, tmp, tmp2, tmp3);
3386: break;
3387: default:
3388: tcg_abort();
3389: }
3390: tcg_temp_free_i64(tmp);
3391: tcg_temp_free_i64(tmp2);
3392: tcg_temp_free_i64(tmp3);
3393: break;
3394: case 0xc: /* MSGR R1,R2 [RRE] */
3395: case 0x1c: /* MSGFR R1,R2 [RRE] */
3396: tmp = load_reg(r1);
3397: tmp2 = load_reg(r2);
3398: if (op == 0x1c) {
3399: tcg_gen_ext32s_i64(tmp2, tmp2);
3400: }
3401: tcg_gen_mul_i64(tmp, tmp, tmp2);
3402: store_reg(r1, tmp);
3403: tcg_temp_free_i64(tmp);
3404: tcg_temp_free_i64(tmp2);
3405: break;
3406: case 0xd: /* DSGR R1,R2 [RRE] */
3407: case 0x1d: /* DSGFR R1,R2 [RRE] */
3408: tmp = load_reg(r1 + 1);
3409: if (op == 0xd) {
3410: tmp2 = load_reg(r2);
3411: } else {
3412: tmp32_1 = load_reg32(r2);
3413: tmp2 = tcg_temp_new_i64();
3414: tcg_gen_ext_i32_i64(tmp2, tmp32_1);
3415: tcg_temp_free_i32(tmp32_1);
3416: }
3417: tmp3 = tcg_temp_new_i64();
3418: tcg_gen_div_i64(tmp3, tmp, tmp2);
3419: store_reg(r1 + 1, tmp3);
3420: tcg_gen_rem_i64(tmp3, tmp, tmp2);
3421: store_reg(r1, tmp3);
3422: tcg_temp_free_i64(tmp);
3423: tcg_temp_free_i64(tmp2);
3424: tcg_temp_free_i64(tmp3);
3425: break;
3426: case 0x14: /* LGFR R1,R2 [RRE] */
3427: tmp32_1 = load_reg32(r2);
3428: tmp = tcg_temp_new_i64();
3429: tcg_gen_ext_i32_i64(tmp, tmp32_1);
3430: store_reg(r1, tmp);
3431: tcg_temp_free_i32(tmp32_1);
3432: tcg_temp_free_i64(tmp);
3433: break;
3434: case 0x16: /* LLGFR R1,R2 [RRE] */
3435: tmp32_1 = load_reg32(r2);
3436: tmp = tcg_temp_new_i64();
3437: tcg_gen_extu_i32_i64(tmp, tmp32_1);
3438: store_reg(r1, tmp);
3439: tcg_temp_free_i32(tmp32_1);
3440: tcg_temp_free_i64(tmp);
3441: break;
3442: case 0x17: /* LLGTR R1,R2 [RRE] */
3443: tmp32_1 = load_reg32(r2);
3444: tmp = tcg_temp_new_i64();
3445: tcg_gen_andi_i32(tmp32_1, tmp32_1, 0x7fffffffUL);
3446: tcg_gen_extu_i32_i64(tmp, tmp32_1);
3447: store_reg(r1, tmp);
3448: tcg_temp_free_i32(tmp32_1);
3449: tcg_temp_free_i64(tmp);
3450: break;
3451: case 0x18: /* AGFR R1,R2 [RRE] */
3452: case 0x1a: /* ALGFR R1,R2 [RRE] */
3453: tmp32_1 = load_reg32(r2);
3454: tmp2 = tcg_temp_new_i64();
3455: if (op == 0x18) {
3456: tcg_gen_ext_i32_i64(tmp2, tmp32_1);
3457: } else {
3458: tcg_gen_extu_i32_i64(tmp2, tmp32_1);
3459: }
3460: tcg_temp_free_i32(tmp32_1);
3461: tmp = load_reg(r1);
3462: tmp3 = tcg_temp_new_i64();
3463: tcg_gen_add_i64(tmp3, tmp, tmp2);
3464: store_reg(r1, tmp3);
3465: if (op == 0x18) {
3466: set_cc_add64(s, tmp, tmp2, tmp3);
3467: } else {
3468: set_cc_addu64(s, tmp, tmp2, tmp3);
3469: }
3470: tcg_temp_free_i64(tmp);
3471: tcg_temp_free_i64(tmp2);
3472: tcg_temp_free_i64(tmp3);
3473: break;
3474: case 0x0f: /* LRVGR R1,R2 [RRE] */
3475: tcg_gen_bswap64_i64(regs[r1], regs[r2]);
3476: break;
3477: case 0x1f: /* LRVR R1,R2 [RRE] */
3478: tmp32_1 = load_reg32(r2);
3479: tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
3480: store_reg32(r1, tmp32_1);
3481: tcg_temp_free_i32(tmp32_1);
3482: break;
3483: case 0x20: /* CGR R1,R2 [RRE] */
3484: case 0x30: /* CGFR R1,R2 [RRE] */
3485: tmp2 = load_reg(r2);
3486: if (op == 0x30) {
3487: tcg_gen_ext32s_i64(tmp2, tmp2);
3488: }
3489: tmp = load_reg(r1);
3490: cmp_s64(s, tmp, tmp2);
3491: tcg_temp_free_i64(tmp);
3492: tcg_temp_free_i64(tmp2);
3493: break;
3494: case 0x21: /* CLGR R1,R2 [RRE] */
3495: case 0x31: /* CLGFR R1,R2 [RRE] */
3496: tmp2 = load_reg(r2);
3497: if (op == 0x31) {
3498: tcg_gen_ext32u_i64(tmp2, tmp2);
3499: }
3500: tmp = load_reg(r1);
3501: cmp_u64(s, tmp, tmp2);
3502: tcg_temp_free_i64(tmp);
3503: tcg_temp_free_i64(tmp2);
3504: break;
3505: case 0x26: /* LBR R1,R2 [RRE] */
3506: tmp32_1 = load_reg32(r2);
3507: tcg_gen_ext8s_i32(tmp32_1, tmp32_1);
3508: store_reg32(r1, tmp32_1);
3509: tcg_temp_free_i32(tmp32_1);
3510: break;
3511: case 0x27: /* LHR R1,R2 [RRE] */
3512: tmp32_1 = load_reg32(r2);
3513: tcg_gen_ext16s_i32(tmp32_1, tmp32_1);
3514: store_reg32(r1, tmp32_1);
3515: tcg_temp_free_i32(tmp32_1);
3516: break;
3517: case 0x80: /* NGR R1,R2 [RRE] */
3518: case 0x81: /* OGR R1,R2 [RRE] */
3519: case 0x82: /* XGR R1,R2 [RRE] */
3520: tmp = load_reg(r1);
3521: tmp2 = load_reg(r2);
3522: switch (op) {
3523: case 0x80:
3524: tcg_gen_and_i64(tmp, tmp, tmp2);
3525: break;
3526: case 0x81:
3527: tcg_gen_or_i64(tmp, tmp, tmp2);
3528: break;
3529: case 0x82:
3530: tcg_gen_xor_i64(tmp, tmp, tmp2);
3531: break;
3532: default:
3533: tcg_abort();
3534: }
3535: store_reg(r1, tmp);
3536: set_cc_nz_u64(s, tmp);
3537: tcg_temp_free_i64(tmp);
3538: tcg_temp_free_i64(tmp2);
3539: break;
3540: case 0x83: /* FLOGR R1,R2 [RRE] */
3541: tmp = load_reg(r2);
3542: tmp32_1 = tcg_const_i32(r1);
3543: gen_helper_flogr(cc_op, tmp32_1, tmp);
3544: set_cc_static(s);
3545: tcg_temp_free_i64(tmp);
3546: tcg_temp_free_i32(tmp32_1);
3547: break;
3548: case 0x84: /* LLGCR R1,R2 [RRE] */
3549: tmp = load_reg(r2);
3550: tcg_gen_andi_i64(tmp, tmp, 0xff);
3551: store_reg(r1, tmp);
3552: tcg_temp_free_i64(tmp);
3553: break;
3554: case 0x85: /* LLGHR R1,R2 [RRE] */
3555: tmp = load_reg(r2);
3556: tcg_gen_andi_i64(tmp, tmp, 0xffff);
3557: store_reg(r1, tmp);
3558: tcg_temp_free_i64(tmp);
3559: break;
3560: case 0x87: /* DLGR R1,R2 [RRE] */
3561: tmp32_1 = tcg_const_i32(r1);
3562: tmp = load_reg(r2);
3563: gen_helper_dlg(tmp32_1, tmp);
3564: tcg_temp_free_i64(tmp);
3565: tcg_temp_free_i32(tmp32_1);
3566: break;
3567: case 0x88: /* ALCGR R1,R2 [RRE] */
3568: tmp = load_reg(r1);
3569: tmp2 = load_reg(r2);
3570: tmp3 = tcg_temp_new_i64();
3571: gen_op_calc_cc(s);
3572: tcg_gen_extu_i32_i64(tmp3, cc_op);
3573: tcg_gen_shri_i64(tmp3, tmp3, 1);
3574: tcg_gen_andi_i64(tmp3, tmp3, 1);
3575: tcg_gen_add_i64(tmp3, tmp2, tmp3);
3576: tcg_gen_add_i64(tmp3, tmp, tmp3);
3577: store_reg(r1, tmp3);
3578: set_cc_addu64(s, tmp, tmp2, tmp3);
3579: tcg_temp_free_i64(tmp);
3580: tcg_temp_free_i64(tmp2);
3581: tcg_temp_free_i64(tmp3);
3582: break;
3583: case 0x89: /* SLBGR R1,R2 [RRE] */
3584: tmp = load_reg(r1);
3585: tmp2 = load_reg(r2);
3586: tmp32_1 = tcg_const_i32(r1);
3587: gen_op_calc_cc(s);
3588: gen_helper_slbg(cc_op, cc_op, tmp32_1, tmp, tmp2);
3589: set_cc_static(s);
3590: tcg_temp_free_i64(tmp);
3591: tcg_temp_free_i64(tmp2);
3592: tcg_temp_free_i32(tmp32_1);
3593: break;
3594: case 0x94: /* LLCR R1,R2 [RRE] */
3595: tmp32_1 = load_reg32(r2);
3596: tcg_gen_andi_i32(tmp32_1, tmp32_1, 0xff);
3597: store_reg32(r1, tmp32_1);
3598: tcg_temp_free_i32(tmp32_1);
3599: break;
3600: case 0x95: /* LLHR R1,R2 [RRE] */
3601: tmp32_1 = load_reg32(r2);
3602: tcg_gen_andi_i32(tmp32_1, tmp32_1, 0xffff);
3603: store_reg32(r1, tmp32_1);
3604: tcg_temp_free_i32(tmp32_1);
3605: break;
3606: case 0x96: /* MLR R1,R2 [RRE] */
3607: /* reg(r1, r1+1) = reg(r1+1) * reg(r2) */
3608: tmp2 = load_reg(r2);
3609: tmp3 = load_reg((r1 + 1) & 15);
3610: tcg_gen_ext32u_i64(tmp2, tmp2);
3611: tcg_gen_ext32u_i64(tmp3, tmp3);
3612: tcg_gen_mul_i64(tmp2, tmp2, tmp3);
3613: store_reg32_i64((r1 + 1) & 15, tmp2);
3614: tcg_gen_shri_i64(tmp2, tmp2, 32);
3615: store_reg32_i64(r1, tmp2);
3616: tcg_temp_free_i64(tmp2);
3617: tcg_temp_free_i64(tmp3);
3618: break;
3619: case 0x97: /* DLR R1,R2 [RRE] */
3620: /* reg(r1) = reg(r1, r1+1) % reg(r2) */
3621: /* reg(r1+1) = reg(r1, r1+1) / reg(r2) */
3622: tmp = load_reg(r1);
3623: tmp2 = load_reg(r2);
3624: tmp3 = load_reg((r1 + 1) & 15);
3625: tcg_gen_ext32u_i64(tmp2, tmp2);
3626: tcg_gen_ext32u_i64(tmp3, tmp3);
3627: tcg_gen_shli_i64(tmp, tmp, 32);
3628: tcg_gen_or_i64(tmp, tmp, tmp3);
3629:
3630: tcg_gen_rem_i64(tmp3, tmp, tmp2);
3631: tcg_gen_div_i64(tmp, tmp, tmp2);
3632: store_reg32_i64((r1 + 1) & 15, tmp);
3633: store_reg32_i64(r1, tmp3);
3634: tcg_temp_free_i64(tmp);
3635: tcg_temp_free_i64(tmp2);
3636: tcg_temp_free_i64(tmp3);
3637: break;
3638: case 0x98: /* ALCR R1,R2 [RRE] */
3639: tmp32_1 = load_reg32(r1);
3640: tmp32_2 = load_reg32(r2);
3641: tmp32_3 = tcg_temp_new_i32();
3642: /* XXX possible optimization point */
3643: gen_op_calc_cc(s);
3644: gen_helper_addc_u32(tmp32_3, cc_op, tmp32_1, tmp32_2);
3645: set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
3646: store_reg32(r1, tmp32_3);
3647: tcg_temp_free_i32(tmp32_1);
3648: tcg_temp_free_i32(tmp32_2);
3649: tcg_temp_free_i32(tmp32_3);
3650: break;
3651: case 0x99: /* SLBR R1,R2 [RRE] */
3652: tmp32_1 = load_reg32(r2);
3653: tmp32_2 = tcg_const_i32(r1);
3654: gen_op_calc_cc(s);
3655: gen_helper_slb(cc_op, cc_op, tmp32_2, tmp32_1);
3656: set_cc_static(s);
3657: tcg_temp_free_i32(tmp32_1);
3658: tcg_temp_free_i32(tmp32_2);
3659: break;
3660: default:
3661: LOG_DISAS("illegal b9 operation 0x%x\n", op);
3662: gen_illegal_opcode(s, 2);
3663: break;
3664: }
3665: }
3666:
3667: static void disas_c0(DisasContext *s, int op, int r1, int i2)
3668: {
3669: TCGv_i64 tmp;
3670: TCGv_i32 tmp32_1, tmp32_2;
3671: uint64_t target = s->pc + i2 * 2LL;
3672: int l1;
3673:
3674: LOG_DISAS("disas_c0: op 0x%x r1 %d i2 %d\n", op, r1, i2);
3675:
3676: switch (op) {
3677: case 0: /* larl r1, i2 */
3678: tmp = tcg_const_i64(target);
3679: store_reg(r1, tmp);
3680: tcg_temp_free_i64(tmp);
3681: break;
3682: case 0x1: /* LGFI R1,I2 [RIL] */
3683: tmp = tcg_const_i64((int64_t)i2);
3684: store_reg(r1, tmp);
3685: tcg_temp_free_i64(tmp);
3686: break;
3687: case 0x4: /* BRCL M1,I2 [RIL] */
3688: /* m1 & (1 << (3 - cc)) */
3689: tmp32_1 = tcg_const_i32(3);
3690: tmp32_2 = tcg_const_i32(1);
3691: gen_op_calc_cc(s);
3692: tcg_gen_sub_i32(tmp32_1, tmp32_1, cc_op);
3693: tcg_gen_shl_i32(tmp32_2, tmp32_2, tmp32_1);
3694: tcg_temp_free_i32(tmp32_1);
3695: tmp32_1 = tcg_const_i32(r1); /* m1 == r1 */
3696: tcg_gen_and_i32(tmp32_1, tmp32_1, tmp32_2);
3697: l1 = gen_new_label();
3698: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp32_1, 0, l1);
3699: gen_goto_tb(s, 0, target);
3700: gen_set_label(l1);
3701: gen_goto_tb(s, 1, s->pc + 6);
3702: s->is_jmp = DISAS_TB_JUMP;
3703: tcg_temp_free_i32(tmp32_1);
3704: tcg_temp_free_i32(tmp32_2);
3705: break;
3706: case 0x5: /* brasl r1, i2 */
3707: tmp = tcg_const_i64(pc_to_link_info(s, s->pc + 6));
3708: store_reg(r1, tmp);
3709: tcg_temp_free_i64(tmp);
3710: gen_goto_tb(s, 0, target);
3711: s->is_jmp = DISAS_TB_JUMP;
3712: break;
3713: case 0x7: /* XILF R1,I2 [RIL] */
3714: case 0xb: /* NILF R1,I2 [RIL] */
3715: case 0xd: /* OILF R1,I2 [RIL] */
3716: tmp32_1 = load_reg32(r1);
3717: switch (op) {
3718: case 0x7:
3719: tcg_gen_xori_i32(tmp32_1, tmp32_1, (uint32_t)i2);
3720: break;
3721: case 0xb:
3722: tcg_gen_andi_i32(tmp32_1, tmp32_1, (uint32_t)i2);
3723: break;
3724: case 0xd:
3725: tcg_gen_ori_i32(tmp32_1, tmp32_1, (uint32_t)i2);
3726: break;
3727: default:
3728: tcg_abort();
3729: }
3730: store_reg32(r1, tmp32_1);
3731: set_cc_nz_u32(s, tmp32_1);
3732: tcg_temp_free_i32(tmp32_1);
3733: break;
3734: case 0x9: /* IILF R1,I2 [RIL] */
3735: tmp32_1 = tcg_const_i32((uint32_t)i2);
3736: store_reg32(r1, tmp32_1);
3737: tcg_temp_free_i32(tmp32_1);
3738: break;
3739: case 0xa: /* NIHF R1,I2 [RIL] */
3740: tmp = load_reg(r1);
3741: tmp32_1 = tcg_temp_new_i32();
3742: tcg_gen_andi_i64(tmp, tmp, (((uint64_t)((uint32_t)i2)) << 32)
3743: | 0xffffffffULL);
3744: store_reg(r1, tmp);
3745: tcg_gen_shri_i64(tmp, tmp, 32);
3746: tcg_gen_trunc_i64_i32(tmp32_1, tmp);
3747: set_cc_nz_u32(s, tmp32_1);
3748: tcg_temp_free_i64(tmp);
3749: tcg_temp_free_i32(tmp32_1);
3750: break;
3751: case 0xe: /* LLIHF R1,I2 [RIL] */
3752: tmp = tcg_const_i64(((uint64_t)(uint32_t)i2) << 32);
3753: store_reg(r1, tmp);
3754: tcg_temp_free_i64(tmp);
3755: break;
3756: case 0xf: /* LLILF R1,I2 [RIL] */
3757: tmp = tcg_const_i64((uint32_t)i2);
3758: store_reg(r1, tmp);
3759: tcg_temp_free_i64(tmp);
3760: break;
3761: default:
3762: LOG_DISAS("illegal c0 operation 0x%x\n", op);
3763: gen_illegal_opcode(s, 3);
3764: break;
3765: }
3766: }
3767:
3768: static void disas_c2(DisasContext *s, int op, int r1, int i2)
3769: {
3770: TCGv_i64 tmp, tmp2, tmp3;
3771: TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
3772:
3773: switch (op) {
3774: case 0x4: /* SLGFI R1,I2 [RIL] */
3775: case 0xa: /* ALGFI R1,I2 [RIL] */
3776: tmp = load_reg(r1);
3777: tmp2 = tcg_const_i64((uint64_t)(uint32_t)i2);
3778: tmp3 = tcg_temp_new_i64();
3779: switch (op) {
3780: case 0x4:
3781: tcg_gen_sub_i64(tmp3, tmp, tmp2);
3782: set_cc_subu64(s, tmp, tmp2, tmp3);
3783: break;
3784: case 0xa:
3785: tcg_gen_add_i64(tmp3, tmp, tmp2);
3786: set_cc_addu64(s, tmp, tmp2, tmp3);
3787: break;
3788: default:
3789: tcg_abort();
3790: }
3791: store_reg(r1, tmp3);
3792: tcg_temp_free_i64(tmp);
3793: tcg_temp_free_i64(tmp2);
3794: tcg_temp_free_i64(tmp3);
3795: break;
3796: case 0x5: /* SLFI R1,I2 [RIL] */
3797: case 0xb: /* ALFI R1,I2 [RIL] */
3798: tmp32_1 = load_reg32(r1);
3799: tmp32_2 = tcg_const_i32(i2);
3800: tmp32_3 = tcg_temp_new_i32();
3801: switch (op) {
3802: case 0x5:
3803: tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
3804: set_cc_subu32(s, tmp32_1, tmp32_2, tmp32_3);
3805: break;
3806: case 0xb:
3807: tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
3808: set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
3809: break;
3810: default:
3811: tcg_abort();
3812: }
3813: store_reg32(r1, tmp32_3);
3814: tcg_temp_free_i32(tmp32_1);
3815: tcg_temp_free_i32(tmp32_2);
3816: tcg_temp_free_i32(tmp32_3);
3817: break;
3818: case 0xc: /* CGFI R1,I2 [RIL] */
3819: tmp = load_reg(r1);
3820: cmp_s64c(s, tmp, (int64_t)i2);
3821: tcg_temp_free_i64(tmp);
3822: break;
3823: case 0xe: /* CLGFI R1,I2 [RIL] */
3824: tmp = load_reg(r1);
3825: cmp_u64c(s, tmp, (uint64_t)(uint32_t)i2);
3826: tcg_temp_free_i64(tmp);
3827: break;
3828: case 0xd: /* CFI R1,I2 [RIL] */
3829: tmp32_1 = load_reg32(r1);
3830: cmp_s32c(s, tmp32_1, i2);
3831: tcg_temp_free_i32(tmp32_1);
3832: break;
3833: case 0xf: /* CLFI R1,I2 [RIL] */
3834: tmp32_1 = load_reg32(r1);
3835: cmp_u32c(s, tmp32_1, i2);
3836: tcg_temp_free_i32(tmp32_1);
3837: break;
3838: default:
3839: LOG_DISAS("illegal c2 operation 0x%x\n", op);
3840: gen_illegal_opcode(s, 3);
3841: break;
3842: }
3843: }
3844:
3845: static void gen_and_or_xor_i32(int opc, TCGv_i32 tmp, TCGv_i32 tmp2)
3846: {
3847: switch (opc & 0xf) {
3848: case 0x4:
3849: tcg_gen_and_i32(tmp, tmp, tmp2);
3850: break;
3851: case 0x6:
3852: tcg_gen_or_i32(tmp, tmp, tmp2);
3853: break;
3854: case 0x7:
3855: tcg_gen_xor_i32(tmp, tmp, tmp2);
3856: break;
3857: default:
3858: tcg_abort();
3859: }
3860: }
3861:
3862: static void disas_s390_insn(DisasContext *s)
3863: {
3864: TCGv_i64 tmp, tmp2, tmp3, tmp4;
3865: TCGv_i32 tmp32_1, tmp32_2, tmp32_3, tmp32_4;
3866: unsigned char opc;
3867: uint64_t insn;
3868: int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
3869: TCGv_i32 vl;
3870: int ilc;
3871: int l1;
3872:
3873: opc = ldub_code(s->pc);
3874: LOG_DISAS("opc 0x%x\n", opc);
3875:
3876: ilc = get_ilc(opc);
3877:
3878: switch (opc) {
3879: #ifndef CONFIG_USER_ONLY
3880: case 0x01: /* SAM */
3881: insn = ld_code2(s->pc);
3882: /* set addressing mode, but we only do 64bit anyways */
3883: break;
3884: #endif
3885: case 0x6: /* BCTR R1,R2 [RR] */
3886: insn = ld_code2(s->pc);
3887: decode_rr(s, insn, &r1, &r2);
3888: tmp32_1 = load_reg32(r1);
3889: tcg_gen_subi_i32(tmp32_1, tmp32_1, 1);
3890: store_reg32(r1, tmp32_1);
3891:
3892: if (r2) {
3893: gen_update_cc_op(s);
3894: l1 = gen_new_label();
3895: tcg_gen_brcondi_i32(TCG_COND_NE, tmp32_1, 0, l1);
3896:
3897: /* not taking the branch, jump to after the instruction */
3898: gen_goto_tb(s, 0, s->pc + 2);
3899: gen_set_label(l1);
3900:
3901: /* take the branch, move R2 into psw.addr */
3902: tmp32_1 = load_reg32(r2);
3903: tmp = tcg_temp_new_i64();
3904: tcg_gen_extu_i32_i64(tmp, tmp32_1);
3905: tcg_gen_mov_i64(psw_addr, tmp);
3906: s->is_jmp = DISAS_JUMP;
3907: tcg_temp_free_i32(tmp32_1);
3908: tcg_temp_free_i64(tmp);
3909: }
3910: break;
3911: case 0x7: /* BCR M1,R2 [RR] */
3912: insn = ld_code2(s->pc);
3913: decode_rr(s, insn, &r1, &r2);
3914: if (r2) {
3915: tmp = load_reg(r2);
3916: gen_bcr(s, r1, tmp, s->pc);
3917: tcg_temp_free_i64(tmp);
3918: s->is_jmp = DISAS_TB_JUMP;
3919: } else {
3920: /* XXX: "serialization and checkpoint-synchronization function"? */
3921: }
3922: break;
3923: case 0xa: /* SVC I [RR] */
3924: insn = ld_code2(s->pc);
3925: debug_insn(insn);
3926: i = insn & 0xff;
3927: update_psw_addr(s);
3928: gen_op_calc_cc(s);
3929: tmp32_1 = tcg_const_i32(i);
3930: tmp32_2 = tcg_const_i32(ilc * 2);
3931: tmp32_3 = tcg_const_i32(EXCP_SVC);
1.1.1.6 ! root 3932: tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code));
! 3933: tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilc));
1.1.1.4 root 3934: gen_helper_exception(tmp32_3);
3935: s->is_jmp = DISAS_EXCP;
3936: tcg_temp_free_i32(tmp32_1);
3937: tcg_temp_free_i32(tmp32_2);
3938: tcg_temp_free_i32(tmp32_3);
3939: break;
3940: case 0xd: /* BASR R1,R2 [RR] */
3941: insn = ld_code2(s->pc);
3942: decode_rr(s, insn, &r1, &r2);
3943: tmp = tcg_const_i64(pc_to_link_info(s, s->pc + 2));
3944: store_reg(r1, tmp);
3945: if (r2) {
3946: tmp2 = load_reg(r2);
3947: tcg_gen_mov_i64(psw_addr, tmp2);
3948: tcg_temp_free_i64(tmp2);
3949: s->is_jmp = DISAS_JUMP;
3950: }
3951: tcg_temp_free_i64(tmp);
3952: break;
3953: case 0xe: /* MVCL R1,R2 [RR] */
3954: insn = ld_code2(s->pc);
3955: decode_rr(s, insn, &r1, &r2);
3956: tmp32_1 = tcg_const_i32(r1);
3957: tmp32_2 = tcg_const_i32(r2);
3958: potential_page_fault(s);
3959: gen_helper_mvcl(cc_op, tmp32_1, tmp32_2);
3960: set_cc_static(s);
3961: tcg_temp_free_i32(tmp32_1);
3962: tcg_temp_free_i32(tmp32_2);
3963: break;
3964: case 0x10: /* LPR R1,R2 [RR] */
3965: insn = ld_code2(s->pc);
3966: decode_rr(s, insn, &r1, &r2);
3967: tmp32_1 = load_reg32(r2);
3968: set_cc_abs32(s, tmp32_1);
3969: gen_helper_abs_i32(tmp32_1, tmp32_1);
3970: store_reg32(r1, tmp32_1);
3971: tcg_temp_free_i32(tmp32_1);
3972: break;
3973: case 0x11: /* LNR R1,R2 [RR] */
3974: insn = ld_code2(s->pc);
3975: decode_rr(s, insn, &r1, &r2);
3976: tmp32_1 = load_reg32(r2);
3977: set_cc_nabs32(s, tmp32_1);
3978: gen_helper_nabs_i32(tmp32_1, tmp32_1);
3979: store_reg32(r1, tmp32_1);
3980: tcg_temp_free_i32(tmp32_1);
3981: break;
3982: case 0x12: /* LTR R1,R2 [RR] */
3983: insn = ld_code2(s->pc);
3984: decode_rr(s, insn, &r1, &r2);
3985: tmp32_1 = load_reg32(r2);
3986: if (r1 != r2) {
3987: store_reg32(r1, tmp32_1);
3988: }
3989: set_cc_s32(s, tmp32_1);
3990: tcg_temp_free_i32(tmp32_1);
3991: break;
3992: case 0x13: /* LCR R1,R2 [RR] */
3993: insn = ld_code2(s->pc);
3994: decode_rr(s, insn, &r1, &r2);
3995: tmp32_1 = load_reg32(r2);
3996: tcg_gen_neg_i32(tmp32_1, tmp32_1);
3997: store_reg32(r1, tmp32_1);
3998: set_cc_comp32(s, tmp32_1);
3999: tcg_temp_free_i32(tmp32_1);
4000: break;
4001: case 0x14: /* NR R1,R2 [RR] */
4002: case 0x16: /* OR R1,R2 [RR] */
4003: case 0x17: /* XR R1,R2 [RR] */
4004: insn = ld_code2(s->pc);
4005: decode_rr(s, insn, &r1, &r2);
4006: tmp32_2 = load_reg32(r2);
4007: tmp32_1 = load_reg32(r1);
4008: gen_and_or_xor_i32(opc, tmp32_1, tmp32_2);
4009: store_reg32(r1, tmp32_1);
4010: set_cc_nz_u32(s, tmp32_1);
4011: tcg_temp_free_i32(tmp32_1);
4012: tcg_temp_free_i32(tmp32_2);
4013: break;
4014: case 0x18: /* LR R1,R2 [RR] */
4015: insn = ld_code2(s->pc);
4016: decode_rr(s, insn, &r1, &r2);
4017: tmp32_1 = load_reg32(r2);
4018: store_reg32(r1, tmp32_1);
4019: tcg_temp_free_i32(tmp32_1);
4020: break;
4021: case 0x15: /* CLR R1,R2 [RR] */
4022: case 0x19: /* CR R1,R2 [RR] */
4023: insn = ld_code2(s->pc);
4024: decode_rr(s, insn, &r1, &r2);
4025: tmp32_1 = load_reg32(r1);
4026: tmp32_2 = load_reg32(r2);
4027: if (opc == 0x15) {
4028: cmp_u32(s, tmp32_1, tmp32_2);
4029: } else {
4030: cmp_s32(s, tmp32_1, tmp32_2);
4031: }
4032: tcg_temp_free_i32(tmp32_1);
4033: tcg_temp_free_i32(tmp32_2);
4034: break;
4035: case 0x1a: /* AR R1,R2 [RR] */
4036: case 0x1e: /* ALR R1,R2 [RR] */
4037: insn = ld_code2(s->pc);
4038: decode_rr(s, insn, &r1, &r2);
4039: tmp32_1 = load_reg32(r1);
4040: tmp32_2 = load_reg32(r2);
4041: tmp32_3 = tcg_temp_new_i32();
4042: tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
4043: store_reg32(r1, tmp32_3);
4044: if (opc == 0x1a) {
4045: set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
4046: } else {
4047: set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
4048: }
4049: tcg_temp_free_i32(tmp32_1);
4050: tcg_temp_free_i32(tmp32_2);
4051: tcg_temp_free_i32(tmp32_3);
4052: break;
4053: case 0x1b: /* SR R1,R2 [RR] */
4054: case 0x1f: /* SLR R1,R2 [RR] */
4055: insn = ld_code2(s->pc);
4056: decode_rr(s, insn, &r1, &r2);
4057: tmp32_1 = load_reg32(r1);
4058: tmp32_2 = load_reg32(r2);
4059: tmp32_3 = tcg_temp_new_i32();
4060: tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
4061: store_reg32(r1, tmp32_3);
4062: if (opc == 0x1b) {
4063: set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
4064: } else {
4065: set_cc_subu32(s, tmp32_1, tmp32_2, tmp32_3);
4066: }
4067: tcg_temp_free_i32(tmp32_1);
4068: tcg_temp_free_i32(tmp32_2);
4069: tcg_temp_free_i32(tmp32_3);
4070: break;
4071: case 0x1c: /* MR R1,R2 [RR] */
4072: /* reg(r1, r1+1) = reg(r1+1) * reg(r2) */
4073: insn = ld_code2(s->pc);
4074: decode_rr(s, insn, &r1, &r2);
4075: tmp2 = load_reg(r2);
4076: tmp3 = load_reg((r1 + 1) & 15);
4077: tcg_gen_ext32s_i64(tmp2, tmp2);
4078: tcg_gen_ext32s_i64(tmp3, tmp3);
4079: tcg_gen_mul_i64(tmp2, tmp2, tmp3);
4080: store_reg32_i64((r1 + 1) & 15, tmp2);
4081: tcg_gen_shri_i64(tmp2, tmp2, 32);
4082: store_reg32_i64(r1, tmp2);
4083: tcg_temp_free_i64(tmp2);
4084: tcg_temp_free_i64(tmp3);
4085: break;
4086: case 0x1d: /* DR R1,R2 [RR] */
4087: insn = ld_code2(s->pc);
4088: decode_rr(s, insn, &r1, &r2);
4089: tmp32_1 = load_reg32(r1);
4090: tmp32_2 = load_reg32(r1 + 1);
4091: tmp32_3 = load_reg32(r2);
4092:
4093: tmp = tcg_temp_new_i64(); /* dividend */
4094: tmp2 = tcg_temp_new_i64(); /* divisor */
4095: tmp3 = tcg_temp_new_i64();
4096:
4097: /* dividend is r(r1 << 32) | r(r1 + 1) */
4098: tcg_gen_extu_i32_i64(tmp, tmp32_1);
4099: tcg_gen_extu_i32_i64(tmp2, tmp32_2);
4100: tcg_gen_shli_i64(tmp, tmp, 32);
4101: tcg_gen_or_i64(tmp, tmp, tmp2);
4102:
4103: /* divisor is r(r2) */
4104: tcg_gen_ext_i32_i64(tmp2, tmp32_3);
4105:
4106: tcg_gen_div_i64(tmp3, tmp, tmp2);
4107: tcg_gen_rem_i64(tmp, tmp, tmp2);
4108:
4109: tcg_gen_trunc_i64_i32(tmp32_1, tmp);
4110: tcg_gen_trunc_i64_i32(tmp32_2, tmp3);
4111:
4112: store_reg32(r1, tmp32_1); /* remainder */
4113: store_reg32(r1 + 1, tmp32_2); /* quotient */
4114: tcg_temp_free_i32(tmp32_1);
4115: tcg_temp_free_i32(tmp32_2);
4116: tcg_temp_free_i32(tmp32_3);
4117: tcg_temp_free_i64(tmp);
4118: tcg_temp_free_i64(tmp2);
4119: tcg_temp_free_i64(tmp3);
4120: break;
4121: case 0x28: /* LDR R1,R2 [RR] */
4122: insn = ld_code2(s->pc);
4123: decode_rr(s, insn, &r1, &r2);
4124: tmp = load_freg(r2);
4125: store_freg(r1, tmp);
4126: tcg_temp_free_i64(tmp);
4127: break;
4128: case 0x38: /* LER R1,R2 [RR] */
4129: insn = ld_code2(s->pc);
4130: decode_rr(s, insn, &r1, &r2);
4131: tmp32_1 = load_freg32(r2);
4132: store_freg32(r1, tmp32_1);
4133: tcg_temp_free_i32(tmp32_1);
4134: break;
4135: case 0x40: /* STH R1,D2(X2,B2) [RX] */
4136: insn = ld_code4(s->pc);
4137: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4138: tmp2 = load_reg(r1);
4139: tcg_gen_qemu_st16(tmp2, tmp, get_mem_index(s));
4140: tcg_temp_free_i64(tmp);
4141: tcg_temp_free_i64(tmp2);
4142: break;
4143: case 0x41: /* la */
4144: insn = ld_code4(s->pc);
4145: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4146: store_reg(r1, tmp); /* FIXME: 31/24-bit addressing */
4147: tcg_temp_free_i64(tmp);
4148: break;
4149: case 0x42: /* STC R1,D2(X2,B2) [RX] */
4150: insn = ld_code4(s->pc);
4151: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4152: tmp2 = load_reg(r1);
4153: tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
4154: tcg_temp_free_i64(tmp);
4155: tcg_temp_free_i64(tmp2);
4156: break;
4157: case 0x43: /* IC R1,D2(X2,B2) [RX] */
4158: insn = ld_code4(s->pc);
4159: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4160: tmp2 = tcg_temp_new_i64();
4161: tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
4162: store_reg8(r1, tmp2);
4163: tcg_temp_free_i64(tmp);
4164: tcg_temp_free_i64(tmp2);
4165: break;
4166: case 0x44: /* EX R1,D2(X2,B2) [RX] */
4167: insn = ld_code4(s->pc);
4168: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4169: tmp2 = load_reg(r1);
4170: tmp3 = tcg_const_i64(s->pc + 4);
4171: update_psw_addr(s);
4172: gen_op_calc_cc(s);
4173: gen_helper_ex(cc_op, cc_op, tmp2, tmp, tmp3);
4174: set_cc_static(s);
4175: tcg_temp_free_i64(tmp);
4176: tcg_temp_free_i64(tmp2);
4177: tcg_temp_free_i64(tmp3);
4178: break;
4179: case 0x46: /* BCT R1,D2(X2,B2) [RX] */
4180: insn = ld_code4(s->pc);
4181: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4182: tcg_temp_free_i64(tmp);
4183:
4184: tmp32_1 = load_reg32(r1);
4185: tcg_gen_subi_i32(tmp32_1, tmp32_1, 1);
4186: store_reg32(r1, tmp32_1);
4187:
4188: gen_update_cc_op(s);
4189: l1 = gen_new_label();
4190: tcg_gen_brcondi_i32(TCG_COND_NE, tmp32_1, 0, l1);
4191:
4192: /* not taking the branch, jump to after the instruction */
4193: gen_goto_tb(s, 0, s->pc + 4);
4194: gen_set_label(l1);
4195:
4196: /* take the branch, move R2 into psw.addr */
4197: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4198: tcg_gen_mov_i64(psw_addr, tmp);
4199: s->is_jmp = DISAS_JUMP;
4200: tcg_temp_free_i32(tmp32_1);
4201: tcg_temp_free_i64(tmp);
4202: break;
4203: case 0x47: /* BC M1,D2(X2,B2) [RX] */
4204: insn = ld_code4(s->pc);
4205: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4206: gen_bcr(s, r1, tmp, s->pc + 4);
4207: tcg_temp_free_i64(tmp);
4208: s->is_jmp = DISAS_TB_JUMP;
4209: break;
4210: case 0x48: /* LH R1,D2(X2,B2) [RX] */
4211: insn = ld_code4(s->pc);
4212: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4213: tmp2 = tcg_temp_new_i64();
4214: tcg_gen_qemu_ld16s(tmp2, tmp, get_mem_index(s));
4215: store_reg32_i64(r1, tmp2);
4216: tcg_temp_free_i64(tmp);
4217: tcg_temp_free_i64(tmp2);
4218: break;
4219: case 0x49: /* CH R1,D2(X2,B2) [RX] */
4220: insn = ld_code4(s->pc);
4221: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4222: tmp32_1 = load_reg32(r1);
4223: tmp32_2 = tcg_temp_new_i32();
4224: tmp2 = tcg_temp_new_i64();
4225: tcg_gen_qemu_ld16s(tmp2, tmp, get_mem_index(s));
4226: tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
4227: cmp_s32(s, tmp32_1, tmp32_2);
4228: tcg_temp_free_i32(tmp32_1);
4229: tcg_temp_free_i32(tmp32_2);
4230: tcg_temp_free_i64(tmp);
4231: tcg_temp_free_i64(tmp2);
4232: break;
4233: case 0x4a: /* AH R1,D2(X2,B2) [RX] */
4234: case 0x4b: /* SH R1,D2(X2,B2) [RX] */
4235: case 0x4c: /* MH R1,D2(X2,B2) [RX] */
4236: insn = ld_code4(s->pc);
4237: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4238: tmp2 = tcg_temp_new_i64();
4239: tmp32_1 = load_reg32(r1);
4240: tmp32_2 = tcg_temp_new_i32();
4241: tmp32_3 = tcg_temp_new_i32();
4242:
4243: tcg_gen_qemu_ld16s(tmp2, tmp, get_mem_index(s));
4244: tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
4245: switch (opc) {
4246: case 0x4a:
4247: tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
4248: set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
4249: break;
4250: case 0x4b:
4251: tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
4252: set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
4253: break;
4254: case 0x4c:
4255: tcg_gen_mul_i32(tmp32_3, tmp32_1, tmp32_2);
4256: break;
4257: default:
4258: tcg_abort();
4259: }
4260: store_reg32(r1, tmp32_3);
4261:
4262: tcg_temp_free_i32(tmp32_1);
4263: tcg_temp_free_i32(tmp32_2);
4264: tcg_temp_free_i32(tmp32_3);
4265: tcg_temp_free_i64(tmp);
4266: tcg_temp_free_i64(tmp2);
4267: break;
4268: case 0x4d: /* BAS R1,D2(X2,B2) [RX] */
4269: insn = ld_code4(s->pc);
4270: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4271: tmp2 = tcg_const_i64(pc_to_link_info(s, s->pc + 4));
4272: store_reg(r1, tmp2);
4273: tcg_gen_mov_i64(psw_addr, tmp);
4274: tcg_temp_free_i64(tmp);
4275: tcg_temp_free_i64(tmp2);
4276: s->is_jmp = DISAS_JUMP;
4277: break;
4278: case 0x4e: /* CVD R1,D2(X2,B2) [RX] */
4279: insn = ld_code4(s->pc);
4280: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4281: tmp2 = tcg_temp_new_i64();
4282: tmp32_1 = tcg_temp_new_i32();
4283: tcg_gen_trunc_i64_i32(tmp32_1, regs[r1]);
4284: gen_helper_cvd(tmp2, tmp32_1);
4285: tcg_gen_qemu_st64(tmp2, tmp, get_mem_index(s));
4286: tcg_temp_free_i64(tmp);
4287: tcg_temp_free_i64(tmp2);
4288: tcg_temp_free_i32(tmp32_1);
4289: break;
4290: case 0x50: /* st r1, d2(x2, b2) */
4291: insn = ld_code4(s->pc);
4292: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4293: tmp2 = load_reg(r1);
4294: tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
4295: tcg_temp_free_i64(tmp);
4296: tcg_temp_free_i64(tmp2);
4297: break;
4298: case 0x55: /* CL R1,D2(X2,B2) [RX] */
4299: insn = ld_code4(s->pc);
4300: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4301: tmp2 = tcg_temp_new_i64();
4302: tmp32_1 = tcg_temp_new_i32();
4303: tmp32_2 = load_reg32(r1);
4304: tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
4305: tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
4306: cmp_u32(s, tmp32_2, tmp32_1);
4307: tcg_temp_free_i64(tmp);
4308: tcg_temp_free_i64(tmp2);
4309: tcg_temp_free_i32(tmp32_1);
4310: tcg_temp_free_i32(tmp32_2);
4311: break;
4312: case 0x54: /* N R1,D2(X2,B2) [RX] */
4313: case 0x56: /* O R1,D2(X2,B2) [RX] */
4314: case 0x57: /* X R1,D2(X2,B2) [RX] */
4315: insn = ld_code4(s->pc);
4316: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4317: tmp2 = tcg_temp_new_i64();
4318: tmp32_1 = load_reg32(r1);
4319: tmp32_2 = tcg_temp_new_i32();
4320: tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
4321: tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
4322: gen_and_or_xor_i32(opc, tmp32_1, tmp32_2);
4323: store_reg32(r1, tmp32_1);
4324: set_cc_nz_u32(s, tmp32_1);
4325: tcg_temp_free_i64(tmp);
4326: tcg_temp_free_i64(tmp2);
4327: tcg_temp_free_i32(tmp32_1);
4328: tcg_temp_free_i32(tmp32_2);
4329: break;
4330: case 0x58: /* l r1, d2(x2, b2) */
4331: insn = ld_code4(s->pc);
4332: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4333: tmp2 = tcg_temp_new_i64();
4334: tmp32_1 = tcg_temp_new_i32();
4335: tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
4336: tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
4337: store_reg32(r1, tmp32_1);
4338: tcg_temp_free_i64(tmp);
4339: tcg_temp_free_i64(tmp2);
4340: tcg_temp_free_i32(tmp32_1);
4341: break;
4342: case 0x59: /* C R1,D2(X2,B2) [RX] */
4343: insn = ld_code4(s->pc);
4344: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4345: tmp2 = tcg_temp_new_i64();
4346: tmp32_1 = tcg_temp_new_i32();
4347: tmp32_2 = load_reg32(r1);
4348: tcg_gen_qemu_ld32s(tmp2, tmp, get_mem_index(s));
4349: tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
4350: cmp_s32(s, tmp32_2, tmp32_1);
4351: tcg_temp_free_i64(tmp);
4352: tcg_temp_free_i64(tmp2);
4353: tcg_temp_free_i32(tmp32_1);
4354: tcg_temp_free_i32(tmp32_2);
4355: break;
4356: case 0x5a: /* A R1,D2(X2,B2) [RX] */
4357: case 0x5b: /* S R1,D2(X2,B2) [RX] */
4358: case 0x5e: /* AL R1,D2(X2,B2) [RX] */
4359: case 0x5f: /* SL R1,D2(X2,B2) [RX] */
4360: insn = ld_code4(s->pc);
4361: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4362: tmp32_1 = load_reg32(r1);
4363: tmp32_2 = tcg_temp_new_i32();
4364: tmp32_3 = tcg_temp_new_i32();
4365: tcg_gen_qemu_ld32s(tmp, tmp, get_mem_index(s));
4366: tcg_gen_trunc_i64_i32(tmp32_2, tmp);
4367: switch (opc) {
4368: case 0x5a:
4369: case 0x5e:
4370: tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
4371: break;
4372: case 0x5b:
4373: case 0x5f:
4374: tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
4375: break;
4376: default:
4377: tcg_abort();
4378: }
4379: store_reg32(r1, tmp32_3);
4380: switch (opc) {
4381: case 0x5a:
4382: set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
4383: break;
4384: case 0x5e:
4385: set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
4386: break;
4387: case 0x5b:
4388: set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
4389: break;
4390: case 0x5f:
4391: set_cc_subu32(s, tmp32_1, tmp32_2, tmp32_3);
4392: break;
4393: default:
4394: tcg_abort();
4395: }
4396: tcg_temp_free_i64(tmp);
4397: tcg_temp_free_i32(tmp32_1);
4398: tcg_temp_free_i32(tmp32_2);
4399: tcg_temp_free_i32(tmp32_3);
4400: break;
4401: case 0x5c: /* M R1,D2(X2,B2) [RX] */
4402: /* reg(r1, r1+1) = reg(r1+1) * *(s32*)addr */
4403: insn = ld_code4(s->pc);
4404: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4405: tmp2 = tcg_temp_new_i64();
4406: tcg_gen_qemu_ld32s(tmp2, tmp, get_mem_index(s));
4407: tmp3 = load_reg((r1 + 1) & 15);
4408: tcg_gen_ext32s_i64(tmp2, tmp2);
4409: tcg_gen_ext32s_i64(tmp3, tmp3);
4410: tcg_gen_mul_i64(tmp2, tmp2, tmp3);
4411: store_reg32_i64((r1 + 1) & 15, tmp2);
4412: tcg_gen_shri_i64(tmp2, tmp2, 32);
4413: store_reg32_i64(r1, tmp2);
4414: tcg_temp_free_i64(tmp);
4415: tcg_temp_free_i64(tmp2);
4416: tcg_temp_free_i64(tmp3);
4417: break;
4418: case 0x5d: /* D R1,D2(X2,B2) [RX] */
4419: insn = ld_code4(s->pc);
4420: tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4421: tmp32_1 = load_reg32(r1);
4422: tmp32_2 = load_reg32(r1 + 1);
4423:
4424: tmp = tcg_temp_new_i64();
4425: tmp2 = tcg_temp_new_i64();
4426:
4427: /* dividend is r(r1 << 32) | r(r1 + 1) */
4428: tcg_gen_extu_i32_i64(tmp, tmp32_1);
4429: tcg_gen_extu_i32_i64(tmp2, tmp32_2);
4430: tcg_gen_shli_i64(tmp, tmp, 32);
4431: tcg_gen_or_i64(tmp, tmp, tmp2);
4432:
4433: /* divisor is in memory */
4434: tcg_gen_qemu_ld32s(tmp2, tmp3, get_mem_index(s));
4435:
4436: /* XXX divisor == 0 -> FixP divide exception */
4437:
4438: tcg_gen_div_i64(tmp3, tmp, tmp2);
4439: tcg_gen_rem_i64(tmp, tmp, tmp2);
4440:
4441: tcg_gen_trunc_i64_i32(tmp32_1, tmp);
4442: tcg_gen_trunc_i64_i32(tmp32_2, tmp3);
4443:
4444: store_reg32(r1, tmp32_1); /* remainder */
4445: store_reg32(r1 + 1, tmp32_2); /* quotient */
4446: tcg_temp_free_i32(tmp32_1);
4447: tcg_temp_free_i32(tmp32_2);
4448: tcg_temp_free_i64(tmp);
4449: tcg_temp_free_i64(tmp2);
4450: tcg_temp_free_i64(tmp3);
4451: break;
4452: case 0x60: /* STD R1,D2(X2,B2) [RX] */
4453: insn = ld_code4(s->pc);
4454: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4455: tmp2 = load_freg(r1);
4456: tcg_gen_qemu_st64(tmp2, tmp, get_mem_index(s));
4457: tcg_temp_free_i64(tmp);
4458: tcg_temp_free_i64(tmp2);
4459: break;
4460: case 0x68: /* LD R1,D2(X2,B2) [RX] */
4461: insn = ld_code4(s->pc);
4462: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4463: tmp2 = tcg_temp_new_i64();
4464: tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
4465: store_freg(r1, tmp2);
4466: tcg_temp_free_i64(tmp);
4467: tcg_temp_free_i64(tmp2);
4468: break;
4469: case 0x70: /* STE R1,D2(X2,B2) [RX] */
4470: insn = ld_code4(s->pc);
4471: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4472: tmp2 = tcg_temp_new_i64();
4473: tmp32_1 = load_freg32(r1);
4474: tcg_gen_extu_i32_i64(tmp2, tmp32_1);
4475: tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
4476: tcg_temp_free_i64(tmp);
4477: tcg_temp_free_i64(tmp2);
4478: tcg_temp_free_i32(tmp32_1);
4479: break;
4480: case 0x71: /* MS R1,D2(X2,B2) [RX] */
4481: insn = ld_code4(s->pc);
4482: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4483: tmp2 = tcg_temp_new_i64();
4484: tmp32_1 = load_reg32(r1);
4485: tmp32_2 = tcg_temp_new_i32();
4486: tcg_gen_qemu_ld32s(tmp2, tmp, get_mem_index(s));
4487: tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
4488: tcg_gen_mul_i32(tmp32_1, tmp32_1, tmp32_2);
4489: store_reg32(r1, tmp32_1);
4490: tcg_temp_free_i64(tmp);
4491: tcg_temp_free_i64(tmp2);
4492: tcg_temp_free_i32(tmp32_1);
4493: tcg_temp_free_i32(tmp32_2);
4494: break;
4495: case 0x78: /* LE R1,D2(X2,B2) [RX] */
4496: insn = ld_code4(s->pc);
4497: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4498: tmp2 = tcg_temp_new_i64();
4499: tmp32_1 = tcg_temp_new_i32();
4500: tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
4501: tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
4502: store_freg32(r1, tmp32_1);
4503: tcg_temp_free_i64(tmp);
4504: tcg_temp_free_i64(tmp2);
4505: tcg_temp_free_i32(tmp32_1);
4506: break;
4507: #ifndef CONFIG_USER_ONLY
4508: case 0x80: /* SSM D2(B2) [S] */
4509: /* Set System Mask */
4510: check_privileged(s, ilc);
4511: insn = ld_code4(s->pc);
4512: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4513: tmp = get_address(s, 0, b2, d2);
4514: tmp2 = tcg_temp_new_i64();
4515: tmp3 = tcg_temp_new_i64();
4516: tcg_gen_andi_i64(tmp3, psw_mask, ~0xff00000000000000ULL);
4517: tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
4518: tcg_gen_shli_i64(tmp2, tmp2, 56);
4519: tcg_gen_or_i64(psw_mask, tmp3, tmp2);
4520: tcg_temp_free_i64(tmp);
4521: tcg_temp_free_i64(tmp2);
4522: tcg_temp_free_i64(tmp3);
4523: break;
4524: case 0x82: /* LPSW D2(B2) [S] */
4525: /* Load PSW */
4526: check_privileged(s, ilc);
4527: insn = ld_code4(s->pc);
4528: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4529: tmp = get_address(s, 0, b2, d2);
4530: tmp2 = tcg_temp_new_i64();
4531: tmp3 = tcg_temp_new_i64();
4532: tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
4533: tcg_gen_addi_i64(tmp, tmp, 4);
4534: tcg_gen_qemu_ld32u(tmp3, tmp, get_mem_index(s));
4535: gen_helper_load_psw(tmp2, tmp3);
4536: tcg_temp_free_i64(tmp);
4537: tcg_temp_free_i64(tmp2);
4538: tcg_temp_free_i64(tmp3);
4539: /* we need to keep cc_op intact */
4540: s->is_jmp = DISAS_JUMP;
4541: break;
4542: case 0x83: /* DIAG R1,R3,D2 [RS] */
4543: /* Diagnose call (KVM hypercall) */
4544: check_privileged(s, ilc);
4545: potential_page_fault(s);
4546: insn = ld_code4(s->pc);
4547: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4548: tmp32_1 = tcg_const_i32(insn & 0xfff);
4549: tmp2 = load_reg(2);
4550: tmp3 = load_reg(1);
4551: gen_helper_diag(tmp2, tmp32_1, tmp2, tmp3);
4552: store_reg(2, tmp2);
4553: tcg_temp_free_i32(tmp32_1);
4554: tcg_temp_free_i64(tmp2);
4555: tcg_temp_free_i64(tmp3);
4556: break;
4557: #endif
4558: case 0x88: /* SRL R1,D2(B2) [RS] */
4559: case 0x89: /* SLL R1,D2(B2) [RS] */
4560: case 0x8a: /* SRA R1,D2(B2) [RS] */
4561: insn = ld_code4(s->pc);
4562: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4563: tmp = get_address(s, 0, b2, d2);
4564: tmp32_1 = load_reg32(r1);
4565: tmp32_2 = tcg_temp_new_i32();
4566: tcg_gen_trunc_i64_i32(tmp32_2, tmp);
4567: tcg_gen_andi_i32(tmp32_2, tmp32_2, 0x3f);
4568: switch (opc) {
4569: case 0x88:
4570: tcg_gen_shr_i32(tmp32_1, tmp32_1, tmp32_2);
4571: break;
4572: case 0x89:
4573: tcg_gen_shl_i32(tmp32_1, tmp32_1, tmp32_2);
4574: break;
4575: case 0x8a:
4576: tcg_gen_sar_i32(tmp32_1, tmp32_1, tmp32_2);
4577: set_cc_s32(s, tmp32_1);
4578: break;
4579: default:
4580: tcg_abort();
4581: }
4582: store_reg32(r1, tmp32_1);
4583: tcg_temp_free_i64(tmp);
4584: tcg_temp_free_i32(tmp32_1);
4585: tcg_temp_free_i32(tmp32_2);
4586: break;
4587: case 0x8c: /* SRDL R1,D2(B2) [RS] */
4588: case 0x8d: /* SLDL R1,D2(B2) [RS] */
4589: case 0x8e: /* SRDA R1,D2(B2) [RS] */
4590: insn = ld_code4(s->pc);
4591: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4592: tmp = get_address(s, 0, b2, d2); /* shift */
4593: tmp2 = tcg_temp_new_i64();
4594: tmp32_1 = load_reg32(r1);
4595: tmp32_2 = load_reg32(r1 + 1);
4596: tcg_gen_concat_i32_i64(tmp2, tmp32_2, tmp32_1); /* operand */
4597: switch (opc) {
4598: case 0x8c:
4599: tcg_gen_shr_i64(tmp2, tmp2, tmp);
4600: break;
4601: case 0x8d:
4602: tcg_gen_shl_i64(tmp2, tmp2, tmp);
4603: break;
4604: case 0x8e:
4605: tcg_gen_sar_i64(tmp2, tmp2, tmp);
4606: set_cc_s64(s, tmp2);
4607: break;
4608: }
4609: tcg_gen_shri_i64(tmp, tmp2, 32);
4610: tcg_gen_trunc_i64_i32(tmp32_1, tmp);
4611: store_reg32(r1, tmp32_1);
4612: tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
4613: store_reg32(r1 + 1, tmp32_2);
4614: tcg_temp_free_i64(tmp);
4615: tcg_temp_free_i64(tmp2);
4616: break;
4617: case 0x98: /* LM R1,R3,D2(B2) [RS] */
4618: case 0x90: /* STM R1,R3,D2(B2) [RS] */
4619: insn = ld_code4(s->pc);
4620: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4621:
4622: tmp = get_address(s, 0, b2, d2);
4623: tmp2 = tcg_temp_new_i64();
4624: tmp3 = tcg_const_i64(4);
4625: tmp4 = tcg_const_i64(0xffffffff00000000ULL);
4626: for (i = r1;; i = (i + 1) % 16) {
4627: if (opc == 0x98) {
4628: tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
4629: tcg_gen_and_i64(regs[i], regs[i], tmp4);
4630: tcg_gen_or_i64(regs[i], regs[i], tmp2);
4631: } else {
4632: tcg_gen_qemu_st32(regs[i], tmp, get_mem_index(s));
4633: }
4634: if (i == r3) {
4635: break;
4636: }
4637: tcg_gen_add_i64(tmp, tmp, tmp3);
4638: }
4639: tcg_temp_free_i64(tmp);
4640: tcg_temp_free_i64(tmp2);
4641: tcg_temp_free_i64(tmp3);
4642: tcg_temp_free_i64(tmp4);
4643: break;
4644: case 0x91: /* TM D1(B1),I2 [SI] */
4645: insn = ld_code4(s->pc);
4646: tmp = decode_si(s, insn, &i2, &b1, &d1);
4647: tmp2 = tcg_const_i64(i2);
4648: tcg_gen_qemu_ld8u(tmp, tmp, get_mem_index(s));
4649: cmp_64(s, tmp, tmp2, CC_OP_TM_32);
4650: tcg_temp_free_i64(tmp);
4651: tcg_temp_free_i64(tmp2);
4652: break;
4653: case 0x92: /* MVI D1(B1),I2 [SI] */
4654: insn = ld_code4(s->pc);
4655: tmp = decode_si(s, insn, &i2, &b1, &d1);
4656: tmp2 = tcg_const_i64(i2);
4657: tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
4658: tcg_temp_free_i64(tmp);
4659: tcg_temp_free_i64(tmp2);
4660: break;
4661: case 0x94: /* NI D1(B1),I2 [SI] */
4662: case 0x96: /* OI D1(B1),I2 [SI] */
4663: case 0x97: /* XI D1(B1),I2 [SI] */
4664: insn = ld_code4(s->pc);
4665: tmp = decode_si(s, insn, &i2, &b1, &d1);
4666: tmp2 = tcg_temp_new_i64();
4667: tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
4668: switch (opc) {
4669: case 0x94:
4670: tcg_gen_andi_i64(tmp2, tmp2, i2);
4671: break;
4672: case 0x96:
4673: tcg_gen_ori_i64(tmp2, tmp2, i2);
4674: break;
4675: case 0x97:
4676: tcg_gen_xori_i64(tmp2, tmp2, i2);
4677: break;
4678: default:
4679: tcg_abort();
4680: }
4681: tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
4682: set_cc_nz_u64(s, tmp2);
4683: tcg_temp_free_i64(tmp);
4684: tcg_temp_free_i64(tmp2);
4685: break;
4686: case 0x95: /* CLI D1(B1),I2 [SI] */
4687: insn = ld_code4(s->pc);
4688: tmp = decode_si(s, insn, &i2, &b1, &d1);
4689: tmp2 = tcg_temp_new_i64();
4690: tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
4691: cmp_u64c(s, tmp2, i2);
4692: tcg_temp_free_i64(tmp);
4693: tcg_temp_free_i64(tmp2);
4694: break;
4695: case 0x9a: /* LAM R1,R3,D2(B2) [RS] */
4696: insn = ld_code4(s->pc);
4697: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4698: tmp = get_address(s, 0, b2, d2);
4699: tmp32_1 = tcg_const_i32(r1);
4700: tmp32_2 = tcg_const_i32(r3);
4701: potential_page_fault(s);
4702: gen_helper_lam(tmp32_1, tmp, tmp32_2);
4703: tcg_temp_free_i64(tmp);
4704: tcg_temp_free_i32(tmp32_1);
4705: tcg_temp_free_i32(tmp32_2);
4706: break;
4707: case 0x9b: /* STAM R1,R3,D2(B2) [RS] */
4708: insn = ld_code4(s->pc);
4709: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4710: tmp = get_address(s, 0, b2, d2);
4711: tmp32_1 = tcg_const_i32(r1);
4712: tmp32_2 = tcg_const_i32(r3);
4713: potential_page_fault(s);
4714: gen_helper_stam(tmp32_1, tmp, tmp32_2);
4715: tcg_temp_free_i64(tmp);
4716: tcg_temp_free_i32(tmp32_1);
4717: tcg_temp_free_i32(tmp32_2);
4718: break;
4719: case 0xa5:
4720: insn = ld_code4(s->pc);
4721: r1 = (insn >> 20) & 0xf;
4722: op = (insn >> 16) & 0xf;
4723: i2 = insn & 0xffff;
4724: disas_a5(s, op, r1, i2);
4725: break;
4726: case 0xa7:
4727: insn = ld_code4(s->pc);
4728: r1 = (insn >> 20) & 0xf;
4729: op = (insn >> 16) & 0xf;
4730: i2 = (short)insn;
4731: disas_a7(s, op, r1, i2);
4732: break;
4733: case 0xa8: /* MVCLE R1,R3,D2(B2) [RS] */
4734: insn = ld_code4(s->pc);
4735: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4736: tmp = get_address(s, 0, b2, d2);
4737: tmp32_1 = tcg_const_i32(r1);
4738: tmp32_2 = tcg_const_i32(r3);
4739: potential_page_fault(s);
4740: gen_helper_mvcle(cc_op, tmp32_1, tmp, tmp32_2);
4741: set_cc_static(s);
4742: tcg_temp_free_i64(tmp);
4743: tcg_temp_free_i32(tmp32_1);
4744: tcg_temp_free_i32(tmp32_2);
4745: break;
4746: case 0xa9: /* CLCLE R1,R3,D2(B2) [RS] */
4747: insn = ld_code4(s->pc);
4748: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4749: tmp = get_address(s, 0, b2, d2);
4750: tmp32_1 = tcg_const_i32(r1);
4751: tmp32_2 = tcg_const_i32(r3);
4752: potential_page_fault(s);
4753: gen_helper_clcle(cc_op, tmp32_1, tmp, tmp32_2);
4754: set_cc_static(s);
4755: tcg_temp_free_i64(tmp);
4756: tcg_temp_free_i32(tmp32_1);
4757: tcg_temp_free_i32(tmp32_2);
4758: break;
4759: #ifndef CONFIG_USER_ONLY
4760: case 0xac: /* STNSM D1(B1),I2 [SI] */
4761: case 0xad: /* STOSM D1(B1),I2 [SI] */
4762: check_privileged(s, ilc);
4763: insn = ld_code4(s->pc);
4764: tmp = decode_si(s, insn, &i2, &b1, &d1);
4765: tmp2 = tcg_temp_new_i64();
4766: tcg_gen_shri_i64(tmp2, psw_mask, 56);
4767: tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
4768: if (opc == 0xac) {
4769: tcg_gen_andi_i64(psw_mask, psw_mask,
4770: ((uint64_t)i2 << 56) | 0x00ffffffffffffffULL);
4771: } else {
4772: tcg_gen_ori_i64(psw_mask, psw_mask, (uint64_t)i2 << 56);
4773: }
4774: tcg_temp_free_i64(tmp);
4775: tcg_temp_free_i64(tmp2);
4776: break;
4777: case 0xae: /* SIGP R1,R3,D2(B2) [RS] */
4778: check_privileged(s, ilc);
4779: insn = ld_code4(s->pc);
4780: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4781: tmp = get_address(s, 0, b2, d2);
4782: tmp2 = load_reg(r3);
4783: tmp32_1 = tcg_const_i32(r1);
4784: potential_page_fault(s);
4785: gen_helper_sigp(cc_op, tmp, tmp32_1, tmp2);
4786: set_cc_static(s);
4787: tcg_temp_free_i64(tmp);
4788: tcg_temp_free_i64(tmp2);
4789: tcg_temp_free_i32(tmp32_1);
4790: break;
4791: case 0xb1: /* LRA R1,D2(X2, B2) [RX] */
4792: check_privileged(s, ilc);
4793: insn = ld_code4(s->pc);
4794: tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
4795: tmp32_1 = tcg_const_i32(r1);
4796: potential_page_fault(s);
4797: gen_helper_lra(cc_op, tmp, tmp32_1);
4798: set_cc_static(s);
4799: tcg_temp_free_i64(tmp);
4800: tcg_temp_free_i32(tmp32_1);
4801: break;
4802: #endif
4803: case 0xb2:
4804: insn = ld_code4(s->pc);
4805: op = (insn >> 16) & 0xff;
4806: switch (op) {
4807: case 0x9c: /* STFPC D2(B2) [S] */
4808: d2 = insn & 0xfff;
4809: b2 = (insn >> 12) & 0xf;
4810: tmp32_1 = tcg_temp_new_i32();
4811: tmp = tcg_temp_new_i64();
4812: tmp2 = get_address(s, 0, b2, d2);
1.1.1.6 ! root 4813: tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
1.1.1.4 root 4814: tcg_gen_extu_i32_i64(tmp, tmp32_1);
4815: tcg_gen_qemu_st32(tmp, tmp2, get_mem_index(s));
4816: tcg_temp_free_i32(tmp32_1);
4817: tcg_temp_free_i64(tmp);
4818: tcg_temp_free_i64(tmp2);
4819: break;
4820: default:
4821: disas_b2(s, op, insn);
4822: break;
4823: }
4824: break;
4825: case 0xb3:
4826: insn = ld_code4(s->pc);
4827: op = (insn >> 16) & 0xff;
4828: r3 = (insn >> 12) & 0xf; /* aka m3 */
4829: r1 = (insn >> 4) & 0xf;
4830: r2 = insn & 0xf;
4831: disas_b3(s, op, r3, r1, r2);
4832: break;
4833: #ifndef CONFIG_USER_ONLY
4834: case 0xb6: /* STCTL R1,R3,D2(B2) [RS] */
4835: /* Store Control */
4836: check_privileged(s, ilc);
4837: insn = ld_code4(s->pc);
4838: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4839: tmp = get_address(s, 0, b2, d2);
4840: tmp32_1 = tcg_const_i32(r1);
4841: tmp32_2 = tcg_const_i32(r3);
4842: potential_page_fault(s);
4843: gen_helper_stctl(tmp32_1, tmp, tmp32_2);
4844: tcg_temp_free_i64(tmp);
4845: tcg_temp_free_i32(tmp32_1);
4846: tcg_temp_free_i32(tmp32_2);
4847: break;
4848: case 0xb7: /* LCTL R1,R3,D2(B2) [RS] */
4849: /* Load Control */
4850: check_privileged(s, ilc);
4851: insn = ld_code4(s->pc);
4852: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4853: tmp = get_address(s, 0, b2, d2);
4854: tmp32_1 = tcg_const_i32(r1);
4855: tmp32_2 = tcg_const_i32(r3);
4856: potential_page_fault(s);
4857: gen_helper_lctl(tmp32_1, tmp, tmp32_2);
4858: tcg_temp_free_i64(tmp);
4859: tcg_temp_free_i32(tmp32_1);
4860: tcg_temp_free_i32(tmp32_2);
4861: break;
4862: #endif
4863: case 0xb9:
4864: insn = ld_code4(s->pc);
4865: r1 = (insn >> 4) & 0xf;
4866: r2 = insn & 0xf;
4867: op = (insn >> 16) & 0xff;
4868: disas_b9(s, op, r1, r2);
4869: break;
4870: case 0xba: /* CS R1,R3,D2(B2) [RS] */
4871: insn = ld_code4(s->pc);
4872: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4873: tmp = get_address(s, 0, b2, d2);
4874: tmp32_1 = tcg_const_i32(r1);
4875: tmp32_2 = tcg_const_i32(r3);
4876: potential_page_fault(s);
4877: gen_helper_cs(cc_op, tmp32_1, tmp, tmp32_2);
4878: set_cc_static(s);
4879: tcg_temp_free_i64(tmp);
4880: tcg_temp_free_i32(tmp32_1);
4881: tcg_temp_free_i32(tmp32_2);
4882: break;
4883: case 0xbd: /* CLM R1,M3,D2(B2) [RS] */
4884: insn = ld_code4(s->pc);
4885: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4886: tmp = get_address(s, 0, b2, d2);
4887: tmp32_1 = load_reg32(r1);
4888: tmp32_2 = tcg_const_i32(r3);
4889: potential_page_fault(s);
4890: gen_helper_clm(cc_op, tmp32_1, tmp32_2, tmp);
4891: set_cc_static(s);
4892: tcg_temp_free_i64(tmp);
4893: tcg_temp_free_i32(tmp32_1);
4894: tcg_temp_free_i32(tmp32_2);
4895: break;
4896: case 0xbe: /* STCM R1,M3,D2(B2) [RS] */
4897: insn = ld_code4(s->pc);
4898: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4899: tmp = get_address(s, 0, b2, d2);
4900: tmp32_1 = load_reg32(r1);
4901: tmp32_2 = tcg_const_i32(r3);
4902: potential_page_fault(s);
4903: gen_helper_stcm(tmp32_1, tmp32_2, tmp);
4904: tcg_temp_free_i64(tmp);
4905: tcg_temp_free_i32(tmp32_1);
4906: tcg_temp_free_i32(tmp32_2);
4907: break;
4908: case 0xbf: /* ICM R1,M3,D2(B2) [RS] */
4909: insn = ld_code4(s->pc);
4910: decode_rs(s, insn, &r1, &r3, &b2, &d2);
4911: if (r3 == 15) {
4912: /* effectively a 32-bit load */
4913: tmp = get_address(s, 0, b2, d2);
4914: tmp32_1 = tcg_temp_new_i32();
4915: tmp32_2 = tcg_const_i32(r3);
4916: tcg_gen_qemu_ld32u(tmp, tmp, get_mem_index(s));
4917: store_reg32_i64(r1, tmp);
4918: tcg_gen_trunc_i64_i32(tmp32_1, tmp);
4919: set_cc_icm(s, tmp32_2, tmp32_1);
4920: tcg_temp_free_i64(tmp);
4921: tcg_temp_free_i32(tmp32_1);
4922: tcg_temp_free_i32(tmp32_2);
4923: } else if (r3) {
4924: uint32_t mask = 0x00ffffffUL;
4925: uint32_t shift = 24;
4926: int m3 = r3;
4927: tmp = get_address(s, 0, b2, d2);
4928: tmp2 = tcg_temp_new_i64();
4929: tmp32_1 = load_reg32(r1);
4930: tmp32_2 = tcg_temp_new_i32();
4931: tmp32_3 = tcg_const_i32(r3);
4932: tmp32_4 = tcg_const_i32(0);
4933: while (m3) {
4934: if (m3 & 8) {
4935: tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
4936: tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
4937: if (shift) {
4938: tcg_gen_shli_i32(tmp32_2, tmp32_2, shift);
4939: }
4940: tcg_gen_andi_i32(tmp32_1, tmp32_1, mask);
4941: tcg_gen_or_i32(tmp32_1, tmp32_1, tmp32_2);
4942: tcg_gen_or_i32(tmp32_4, tmp32_4, tmp32_2);
4943: tcg_gen_addi_i64(tmp, tmp, 1);
4944: }
4945: m3 = (m3 << 1) & 0xf;
4946: mask = (mask >> 8) | 0xff000000UL;
4947: shift -= 8;
4948: }
4949: store_reg32(r1, tmp32_1);
4950: set_cc_icm(s, tmp32_3, tmp32_4);
4951: tcg_temp_free_i64(tmp);
4952: tcg_temp_free_i64(tmp2);
4953: tcg_temp_free_i32(tmp32_1);
4954: tcg_temp_free_i32(tmp32_2);
4955: tcg_temp_free_i32(tmp32_3);
4956: tcg_temp_free_i32(tmp32_4);
4957: } else {
4958: /* i.e. env->cc = 0 */
4959: gen_op_movi_cc(s, 0);
4960: }
4961: break;
4962: case 0xc0:
4963: case 0xc2:
4964: insn = ld_code6(s->pc);
4965: r1 = (insn >> 36) & 0xf;
4966: op = (insn >> 32) & 0xf;
4967: i2 = (int)insn;
4968: switch (opc) {
4969: case 0xc0:
4970: disas_c0(s, op, r1, i2);
4971: break;
4972: case 0xc2:
4973: disas_c2(s, op, r1, i2);
4974: break;
4975: default:
4976: tcg_abort();
4977: }
4978: break;
4979: case 0xd2: /* MVC D1(L,B1),D2(B2) [SS] */
4980: case 0xd4: /* NC D1(L,B1),D2(B2) [SS] */
4981: case 0xd5: /* CLC D1(L,B1),D2(B2) [SS] */
4982: case 0xd6: /* OC D1(L,B1),D2(B2) [SS] */
4983: case 0xd7: /* XC D1(L,B1),D2(B2) [SS] */
4984: case 0xdc: /* TR D1(L,B1),D2(B2) [SS] */
4985: case 0xf3: /* UNPK D1(L1,B1),D2(L2,B2) [SS] */
4986: insn = ld_code6(s->pc);
4987: vl = tcg_const_i32((insn >> 32) & 0xff);
4988: b1 = (insn >> 28) & 0xf;
4989: b2 = (insn >> 12) & 0xf;
4990: d1 = (insn >> 16) & 0xfff;
4991: d2 = insn & 0xfff;
4992: tmp = get_address(s, 0, b1, d1);
4993: tmp2 = get_address(s, 0, b2, d2);
4994: switch (opc) {
4995: case 0xd2:
4996: gen_op_mvc(s, (insn >> 32) & 0xff, tmp, tmp2);
4997: break;
4998: case 0xd4:
4999: potential_page_fault(s);
5000: gen_helper_nc(cc_op, vl, tmp, tmp2);
5001: set_cc_static(s);
5002: break;
5003: case 0xd5:
5004: gen_op_clc(s, (insn >> 32) & 0xff, tmp, tmp2);
5005: break;
5006: case 0xd6:
5007: potential_page_fault(s);
5008: gen_helper_oc(cc_op, vl, tmp, tmp2);
5009: set_cc_static(s);
5010: break;
5011: case 0xd7:
5012: potential_page_fault(s);
5013: gen_helper_xc(cc_op, vl, tmp, tmp2);
5014: set_cc_static(s);
5015: break;
5016: case 0xdc:
5017: potential_page_fault(s);
5018: gen_helper_tr(vl, tmp, tmp2);
5019: set_cc_static(s);
5020: break;
5021: case 0xf3:
5022: potential_page_fault(s);
5023: gen_helper_unpk(vl, tmp, tmp2);
5024: break;
5025: default:
5026: tcg_abort();
5027: }
5028: tcg_temp_free_i64(tmp);
5029: tcg_temp_free_i64(tmp2);
5030: break;
5031: #ifndef CONFIG_USER_ONLY
5032: case 0xda: /* MVCP D1(R1,B1),D2(B2),R3 [SS] */
5033: case 0xdb: /* MVCS D1(R1,B1),D2(B2),R3 [SS] */
5034: check_privileged(s, ilc);
5035: potential_page_fault(s);
5036: insn = ld_code6(s->pc);
5037: r1 = (insn >> 36) & 0xf;
5038: r3 = (insn >> 32) & 0xf;
5039: b1 = (insn >> 28) & 0xf;
5040: d1 = (insn >> 16) & 0xfff;
5041: b2 = (insn >> 12) & 0xf;
5042: d2 = insn & 0xfff;
5043: tmp = load_reg(r1);
5044: /* XXX key in r3 */
5045: tmp2 = get_address(s, 0, b1, d1);
5046: tmp3 = get_address(s, 0, b2, d2);
5047: if (opc == 0xda) {
5048: gen_helper_mvcp(cc_op, tmp, tmp2, tmp3);
5049: } else {
5050: gen_helper_mvcs(cc_op, tmp, tmp2, tmp3);
5051: }
5052: set_cc_static(s);
5053: tcg_temp_free_i64(tmp);
5054: tcg_temp_free_i64(tmp2);
5055: tcg_temp_free_i64(tmp3);
5056: break;
5057: #endif
5058: case 0xe3:
5059: insn = ld_code6(s->pc);
5060: debug_insn(insn);
5061: op = insn & 0xff;
5062: r1 = (insn >> 36) & 0xf;
5063: x2 = (insn >> 32) & 0xf;
5064: b2 = (insn >> 28) & 0xf;
5065: d2 = ((int)((((insn >> 16) & 0xfff)
5066: | ((insn << 4) & 0xff000)) << 12)) >> 12;
5067: disas_e3(s, op, r1, x2, b2, d2 );
5068: break;
5069: #ifndef CONFIG_USER_ONLY
5070: case 0xe5:
5071: /* Test Protection */
5072: check_privileged(s, ilc);
5073: insn = ld_code6(s->pc);
5074: debug_insn(insn);
5075: disas_e5(s, insn);
5076: break;
5077: #endif
5078: case 0xeb:
5079: insn = ld_code6(s->pc);
5080: debug_insn(insn);
5081: op = insn & 0xff;
5082: r1 = (insn >> 36) & 0xf;
5083: r3 = (insn >> 32) & 0xf;
5084: b2 = (insn >> 28) & 0xf;
5085: d2 = ((int)((((insn >> 16) & 0xfff)
5086: | ((insn << 4) & 0xff000)) << 12)) >> 12;
5087: disas_eb(s, op, r1, r3, b2, d2);
5088: break;
5089: case 0xed:
5090: insn = ld_code6(s->pc);
5091: debug_insn(insn);
5092: op = insn & 0xff;
5093: r1 = (insn >> 36) & 0xf;
5094: x2 = (insn >> 32) & 0xf;
5095: b2 = (insn >> 28) & 0xf;
5096: d2 = (short)((insn >> 16) & 0xfff);
5097: r1b = (insn >> 12) & 0xf;
5098: disas_ed(s, op, r1, x2, b2, d2, r1b);
5099: break;
5100: default:
5101: LOG_DISAS("unimplemented opcode 0x%x\n", opc);
5102: gen_illegal_opcode(s, ilc);
5103: break;
5104: }
5105:
5106: /* Instruction length is encoded in the opcode */
5107: s->pc += (ilc * 2);
5108: }
5109:
1.1.1.6 ! root 5110: static inline void gen_intermediate_code_internal(CPUS390XState *env,
1.1.1.4 root 5111: TranslationBlock *tb,
5112: int search_pc)
5113: {
5114: DisasContext dc;
5115: target_ulong pc_start;
5116: uint64_t next_page_start;
5117: uint16_t *gen_opc_end;
5118: int j, lj = -1;
5119: int num_insns, max_insns;
5120: CPUBreakpoint *bp;
5121:
5122: pc_start = tb->pc;
5123:
5124: /* 31-bit mode */
5125: if (!(tb->flags & FLAG_MASK_64)) {
5126: pc_start &= 0x7fffffff;
5127: }
5128:
5129: dc.pc = pc_start;
5130: dc.is_jmp = DISAS_NEXT;
5131: dc.tb = tb;
5132: dc.cc_op = CC_OP_DYNAMIC;
5133:
5134: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
5135:
5136: next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
5137:
5138: num_insns = 0;
5139: max_insns = tb->cflags & CF_COUNT_MASK;
5140: if (max_insns == 0) {
5141: max_insns = CF_COUNT_MASK;
5142: }
5143:
5144: gen_icount_start();
5145:
5146: do {
5147: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
5148: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
5149: if (bp->pc == dc.pc) {
5150: gen_debug(&dc);
5151: break;
5152: }
5153: }
5154: }
5155: if (search_pc) {
5156: j = gen_opc_ptr - gen_opc_buf;
5157: if (lj < j) {
5158: lj++;
5159: while (lj < j) {
5160: gen_opc_instr_start[lj++] = 0;
5161: }
5162: }
5163: gen_opc_pc[lj] = dc.pc;
5164: gen_opc_cc_op[lj] = dc.cc_op;
5165: gen_opc_instr_start[lj] = 1;
5166: gen_opc_icount[lj] = num_insns;
5167: }
5168: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
5169: gen_io_start();
5170: }
5171: #if defined(S390X_DEBUG_DISAS_VERBOSE)
5172: LOG_DISAS("pc " TARGET_FMT_lx "\n",
5173: dc.pc);
5174: #endif
5175: disas_s390_insn(&dc);
5176:
5177: num_insns++;
5178: if (env->singlestep_enabled) {
5179: gen_debug(&dc);
5180: }
5181: } while (!dc.is_jmp && gen_opc_ptr < gen_opc_end && dc.pc < next_page_start
5182: && num_insns < max_insns && !env->singlestep_enabled
5183: && !singlestep);
5184:
5185: if (!dc.is_jmp) {
5186: update_psw_addr(&dc);
5187: }
5188:
5189: if (singlestep && dc.cc_op != CC_OP_DYNAMIC) {
5190: gen_op_calc_cc(&dc);
5191: } else {
5192: /* next TB starts off with CC_OP_DYNAMIC, so make sure the cc op type
5193: is in env */
5194: gen_op_set_cc_op(&dc);
5195: }
5196:
5197: if (tb->cflags & CF_LAST_IO) {
5198: gen_io_end();
5199: }
5200: /* Generate the return instruction */
5201: if (dc.is_jmp != DISAS_TB_JUMP) {
5202: tcg_gen_exit_tb(0);
5203: }
5204: gen_icount_end(tb, num_insns);
5205: *gen_opc_ptr = INDEX_op_end;
5206: if (search_pc) {
5207: j = gen_opc_ptr - gen_opc_buf;
5208: lj++;
5209: while (lj <= j) {
5210: gen_opc_instr_start[lj++] = 0;
5211: }
5212: } else {
5213: tb->size = dc.pc - pc_start;
5214: tb->icount = num_insns;
5215: }
5216: #if defined(S390X_DEBUG_DISAS)
5217: log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
5218: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
5219: qemu_log("IN: %s\n", lookup_symbol(pc_start));
5220: log_target_disas(pc_start, dc.pc - pc_start, 1);
5221: qemu_log("\n");
5222: }
5223: #endif
5224: }
5225:
1.1.1.6 ! root 5226: void gen_intermediate_code (CPUS390XState *env, struct TranslationBlock *tb)
1.1.1.4 root 5227: {
5228: gen_intermediate_code_internal(env, tb, 0);
5229: }
5230:
1.1.1.6 ! root 5231: void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb)
1.1.1.4 root 5232: {
5233: gen_intermediate_code_internal(env, tb, 1);
5234: }
5235:
1.1.1.6 ! root 5236: void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos)
1.1.1.4 root 5237: {
5238: int cc_op;
5239: env->psw.addr = gen_opc_pc[pc_pos];
5240: cc_op = gen_opc_cc_op[pc_pos];
5241: if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) {
5242: env->cc_op = cc_op;
5243: }
1.1 root 5244: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.