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