|
|
1.1 ! root 1: /* ! 2: * CRIS emulation for qemu: main translation routines. ! 3: * ! 4: * Copyright (c) 2007 AXIS Communications AB ! 5: * Written by Edgar E. Iglesias. ! 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 ! 18: * License along with this library; if not, write to the Free Software ! 19: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! 20: */ ! 21: ! 22: /* ! 23: * This file implements a CRIS decoder-stage in SW. The decoder translates the ! 24: * guest (CRIS) machine-code into host machine code via dyngen using the ! 25: * micro-operations described in op.c ! 26: * ! 27: * The micro-operations for CRIS translation implement a RISC style ISA. ! 28: * Note that the micro-operations typically order their operands ! 29: * starting with the dst. CRIS asm, does the opposite. ! 30: * ! 31: * For example the following CRIS code: ! 32: * add.d [$r0], $r1 ! 33: * ! 34: * translates into: ! 35: * ! 36: * gen_movl_T0_reg(0); // Fetch $r0 into T0 ! 37: * gen_load_T0_T0(); // Load T0, @T0 ! 38: * gen_movl_reg_T0(1); // Writeback T0 into $r1 ! 39: * ! 40: * The actual names for the micro-code generators vary but the example ! 41: * illustrates the point. ! 42: */ ! 43: ! 44: #include <stdarg.h> ! 45: #include <stdlib.h> ! 46: #include <stdio.h> ! 47: #include <string.h> ! 48: #include <inttypes.h> ! 49: #include <assert.h> ! 50: ! 51: #include "cpu.h" ! 52: #include "exec-all.h" ! 53: #include "disas.h" ! 54: #include "crisv32-decode.h" ! 55: ! 56: #define CRIS_STATS 0 ! 57: #if CRIS_STATS ! 58: #define STATS(x) x ! 59: #else ! 60: #define STATS(x) ! 61: #endif ! 62: ! 63: #define DISAS_CRIS 0 ! 64: #if DISAS_CRIS ! 65: #define DIS(x) x ! 66: #else ! 67: #define DIS(x) ! 68: #endif ! 69: ! 70: #ifdef USE_DIRECT_JUMP ! 71: #define TBPARAM(x) ! 72: #else ! 73: #define TBPARAM(x) (long)(x) ! 74: #endif ! 75: ! 76: #define BUG() (gen_BUG(dc, __FILE__, __LINE__)) ! 77: #define BUG_ON(x) ({if (x) BUG();}) ! 78: ! 79: /* Used by the decoder. */ ! 80: #define EXTRACT_FIELD(src, start, end) \ ! 81: (((src) >> start) & ((1 << (end - start + 1)) - 1)) ! 82: ! 83: #define CC_MASK_NZ 0xc ! 84: #define CC_MASK_NZV 0xe ! 85: #define CC_MASK_NZVC 0xf ! 86: #define CC_MASK_RNZV 0x10e ! 87: ! 88: static uint16_t *gen_opc_ptr; ! 89: static uint32_t *gen_opparam_ptr; ! 90: ! 91: enum { ! 92: #define DEF(s, n, copy_size) INDEX_op_ ## s, ! 93: #include "opc.h" ! 94: #undef DEF ! 95: NB_OPS, ! 96: }; ! 97: #include "gen-op.h" ! 98: ! 99: /* This is the state at translation time. */ ! 100: typedef struct DisasContext { ! 101: CPUState *env; ! 102: target_ulong pc, insn_pc; ! 103: ! 104: /* Decoder. */ ! 105: uint32_t ir; ! 106: uint32_t opcode; ! 107: unsigned int op1; ! 108: unsigned int op2; ! 109: unsigned int zsize, zzsize; ! 110: unsigned int mode; ! 111: unsigned int postinc; ! 112: ! 113: ! 114: struct ! 115: { ! 116: int op; ! 117: int size; ! 118: unsigned int mask; ! 119: } cc_state[3]; ! 120: int cc_i; ! 121: ! 122: int update_cc; ! 123: int cc_op; ! 124: int cc_size; ! 125: uint32_t cc_mask; ! 126: int flags_live; ! 127: int flagx_live; ! 128: int flags_x; ! 129: uint32_t tb_entry_flags; ! 130: ! 131: int memidx; /* user or kernel mode. */ ! 132: int is_jmp; ! 133: int dyn_jmp; ! 134: ! 135: uint32_t delayed_pc; ! 136: int delayed_branch; ! 137: int bcc; ! 138: uint32_t condlabel; ! 139: ! 140: struct TranslationBlock *tb; ! 141: int singlestep_enabled; ! 142: } DisasContext; ! 143: ! 144: void cris_prepare_jmp (DisasContext *dc, uint32_t dst); ! 145: static void gen_BUG(DisasContext *dc, char *file, int line) ! 146: { ! 147: printf ("BUG: pc=%x %s %d\n", dc->pc, file, line); ! 148: fprintf (logfile, "BUG: pc=%x %s %d\n", dc->pc, file, line); ! 149: cpu_dump_state (dc->env, stdout, fprintf, 0); ! 150: fflush(NULL); ! 151: cris_prepare_jmp (dc, 0x70000000 + line); ! 152: } ! 153: ! 154: /* Table to generate quick moves from T0 onto any register. */ ! 155: static GenOpFunc *gen_movl_reg_T0[16] = ! 156: { ! 157: gen_op_movl_r0_T0, gen_op_movl_r1_T0, ! 158: gen_op_movl_r2_T0, gen_op_movl_r3_T0, ! 159: gen_op_movl_r4_T0, gen_op_movl_r5_T0, ! 160: gen_op_movl_r6_T0, gen_op_movl_r7_T0, ! 161: gen_op_movl_r8_T0, gen_op_movl_r9_T0, ! 162: gen_op_movl_r10_T0, gen_op_movl_r11_T0, ! 163: gen_op_movl_r12_T0, gen_op_movl_r13_T0, ! 164: gen_op_movl_r14_T0, gen_op_movl_r15_T0, ! 165: }; ! 166: static GenOpFunc *gen_movl_T0_reg[16] = ! 167: { ! 168: gen_op_movl_T0_r0, gen_op_movl_T0_r1, ! 169: gen_op_movl_T0_r2, gen_op_movl_T0_r3, ! 170: gen_op_movl_T0_r4, gen_op_movl_T0_r5, ! 171: gen_op_movl_T0_r6, gen_op_movl_T0_r7, ! 172: gen_op_movl_T0_r8, gen_op_movl_T0_r9, ! 173: gen_op_movl_T0_r10, gen_op_movl_T0_r11, ! 174: gen_op_movl_T0_r12, gen_op_movl_T0_r13, ! 175: gen_op_movl_T0_r14, gen_op_movl_T0_r15, ! 176: }; ! 177: ! 178: static void noop_write(void) { ! 179: /* nop. */ ! 180: } ! 181: ! 182: static void gen_vr_read(void) { ! 183: gen_op_movl_T0_im(32); ! 184: } ! 185: ! 186: static void gen_ccs_read(void) { ! 187: gen_op_movl_T0_p13(); ! 188: } ! 189: ! 190: static void gen_ccs_write(void) { ! 191: gen_op_movl_p13_T0(); ! 192: } ! 193: ! 194: /* Table to generate quick moves from T0 onto any register. */ ! 195: static GenOpFunc *gen_movl_preg_T0[16] = ! 196: { ! 197: noop_write, /* bz, not writeable. */ ! 198: noop_write, /* vr, not writeable. */ ! 199: gen_op_movl_p2_T0, gen_op_movl_p3_T0, ! 200: noop_write, /* wz, not writeable. */ ! 201: gen_op_movl_p5_T0, ! 202: gen_op_movl_p6_T0, gen_op_movl_p7_T0, ! 203: noop_write, /* dz, not writeable. */ ! 204: gen_op_movl_p9_T0, ! 205: gen_op_movl_p10_T0, gen_op_movl_p11_T0, ! 206: gen_op_movl_p12_T0, ! 207: gen_ccs_write, /* ccs needs special treatment. */ ! 208: gen_op_movl_p14_T0, gen_op_movl_p15_T0, ! 209: }; ! 210: static GenOpFunc *gen_movl_T0_preg[16] = ! 211: { ! 212: gen_op_movl_T0_p0, ! 213: gen_vr_read, ! 214: gen_op_movl_T0_p2, gen_op_movl_T0_p3, ! 215: gen_op_movl_T0_p4, gen_op_movl_T0_p5, ! 216: gen_op_movl_T0_p6, gen_op_movl_T0_p7, ! 217: gen_op_movl_T0_p8, gen_op_movl_T0_p9, ! 218: gen_op_movl_T0_p10, gen_op_movl_T0_p11, ! 219: gen_op_movl_T0_p12, ! 220: gen_ccs_read, /* ccs needs special treatment. */ ! 221: gen_op_movl_T0_p14, gen_op_movl_T0_p15, ! 222: }; ! 223: ! 224: /* We need this table to handle moves with implicit width. */ ! 225: int preg_sizes[] = { ! 226: 1, /* bz. */ ! 227: 1, /* vr. */ ! 228: 4, /* pid. */ ! 229: 1, /* srs. */ ! 230: 2, /* wz. */ ! 231: 4, 4, 4, ! 232: 4, 4, 4, 4, ! 233: 4, 4, 4, 4, ! 234: }; ! 235: ! 236: #ifdef CONFIG_USER_ONLY ! 237: #define GEN_OP_LD(width, reg) \ ! 238: void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \ ! 239: gen_op_ld##width##_T0_##reg##_raw(); \ ! 240: } ! 241: #define GEN_OP_ST(width, reg) \ ! 242: void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \ ! 243: gen_op_st##width##_##reg##_T1_raw(); \ ! 244: } ! 245: #else ! 246: #define GEN_OP_LD(width, reg) \ ! 247: void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \ ! 248: if (dc->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \ ! 249: else gen_op_ld##width##_T0_##reg##_user();\ ! 250: } ! 251: #define GEN_OP_ST(width, reg) \ ! 252: void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \ ! 253: if (dc->memidx) gen_op_st##width##_##reg##_T1_kernel(); \ ! 254: else gen_op_st##width##_##reg##_T1_user();\ ! 255: } ! 256: #endif ! 257: ! 258: GEN_OP_LD(ub, T0) ! 259: GEN_OP_LD(b, T0) ! 260: GEN_OP_ST(b, T0) ! 261: GEN_OP_LD(uw, T0) ! 262: GEN_OP_LD(w, T0) ! 263: GEN_OP_ST(w, T0) ! 264: GEN_OP_LD(l, T0) ! 265: GEN_OP_ST(l, T0) ! 266: ! 267: static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) ! 268: { ! 269: TranslationBlock *tb; ! 270: tb = dc->tb; ! 271: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { ! 272: if (n == 0) ! 273: gen_op_goto_tb0(TBPARAM(tb)); ! 274: else ! 275: gen_op_goto_tb1(TBPARAM(tb)); ! 276: gen_op_movl_T0_0(); ! 277: } else { ! 278: gen_op_movl_T0_0(); ! 279: } ! 280: gen_op_exit_tb(); ! 281: } ! 282: ! 283: /* Sign extend at translation time. */ ! 284: static int sign_extend(unsigned int val, unsigned int width) ! 285: { ! 286: int sval; ! 287: ! 288: /* LSL. */ ! 289: val <<= 31 - width; ! 290: sval = val; ! 291: /* ASR. */ ! 292: sval >>= 31 - width; ! 293: return sval; ! 294: } ! 295: ! 296: static void cris_evaluate_flags(DisasContext *dc) ! 297: { ! 298: if (!dc->flags_live) { ! 299: ! 300: switch (dc->cc_op) ! 301: { ! 302: case CC_OP_MCP: ! 303: gen_op_evaluate_flags_mcp (); ! 304: break; ! 305: case CC_OP_MULS: ! 306: gen_op_evaluate_flags_muls (); ! 307: break; ! 308: case CC_OP_MULU: ! 309: gen_op_evaluate_flags_mulu (); ! 310: break; ! 311: case CC_OP_MOVE: ! 312: switch (dc->cc_size) ! 313: { ! 314: case 4: ! 315: gen_op_evaluate_flags_move_4(); ! 316: break; ! 317: case 2: ! 318: gen_op_evaluate_flags_move_2(); ! 319: break; ! 320: default: ! 321: gen_op_evaluate_flags (); ! 322: break; ! 323: } ! 324: break; ! 325: ! 326: default: ! 327: { ! 328: switch (dc->cc_size) ! 329: { ! 330: case 4: ! 331: gen_op_evaluate_flags_alu_4 (); ! 332: break; ! 333: default: ! 334: gen_op_evaluate_flags (); ! 335: break; ! 336: } ! 337: } ! 338: break; ! 339: } ! 340: dc->flags_live = 1; ! 341: } ! 342: } ! 343: ! 344: static void cris_cc_mask(DisasContext *dc, unsigned int mask) ! 345: { ! 346: uint32_t ovl; ! 347: ! 348: ovl = (dc->cc_mask ^ mask) & ~mask; ! 349: if (ovl) { ! 350: /* TODO: optimize this case. It trigs all the time. */ ! 351: cris_evaluate_flags (dc); ! 352: } ! 353: dc->cc_mask = mask; ! 354: ! 355: dc->update_cc = 1; ! 356: if (mask == 0) ! 357: dc->update_cc = 0; ! 358: else { ! 359: gen_op_update_cc_mask(mask); ! 360: dc->flags_live = 0; ! 361: } ! 362: } ! 363: ! 364: static void cris_update_cc_op(DisasContext *dc, int op) ! 365: { ! 366: dc->cc_op = op; ! 367: gen_op_update_cc_op(op); ! 368: dc->flags_live = 0; ! 369: } ! 370: static void cris_update_cc_size(DisasContext *dc, int size) ! 371: { ! 372: dc->cc_size = size; ! 373: gen_op_update_cc_size_im(size); ! 374: } ! 375: ! 376: /* op is the operation. ! 377: T0, T1 are the operands. ! 378: dst is the destination reg. ! 379: */ ! 380: static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size) ! 381: { ! 382: int writeback = 1; ! 383: if (dc->update_cc) { ! 384: cris_update_cc_op(dc, op); ! 385: cris_update_cc_size(dc, size); ! 386: gen_op_update_cc_x(dc->flagx_live, dc->flags_x); ! 387: gen_op_update_cc_dest_T0(); ! 388: } ! 389: ! 390: /* Emit the ALU insns. */ ! 391: switch (op) ! 392: { ! 393: case CC_OP_ADD: ! 394: gen_op_addl_T0_T1(); ! 395: /* Extended arithmetics. */ ! 396: if (!dc->flagx_live) ! 397: gen_op_addxl_T0_C(); ! 398: else if (dc->flags_x) ! 399: gen_op_addxl_T0_C(); ! 400: break; ! 401: case CC_OP_ADDC: ! 402: gen_op_addl_T0_T1(); ! 403: gen_op_addl_T0_C(); ! 404: break; ! 405: case CC_OP_MCP: ! 406: gen_op_addl_T0_T1(); ! 407: gen_op_addl_T0_R(); ! 408: break; ! 409: case CC_OP_SUB: ! 410: gen_op_negl_T1_T1(); ! 411: gen_op_addl_T0_T1(); ! 412: /* CRIS flag evaluation needs ~src. */ ! 413: gen_op_negl_T1_T1(); ! 414: gen_op_not_T1_T1(); ! 415: ! 416: /* Extended arithmetics. */ ! 417: if (!dc->flagx_live) ! 418: gen_op_subxl_T0_C(); ! 419: else if (dc->flags_x) ! 420: gen_op_subxl_T0_C(); ! 421: break; ! 422: case CC_OP_MOVE: ! 423: gen_op_movl_T0_T1(); ! 424: break; ! 425: case CC_OP_OR: ! 426: gen_op_orl_T0_T1(); ! 427: break; ! 428: case CC_OP_AND: ! 429: gen_op_andl_T0_T1(); ! 430: break; ! 431: case CC_OP_XOR: ! 432: gen_op_xorl_T0_T1(); ! 433: break; ! 434: case CC_OP_LSL: ! 435: gen_op_lsll_T0_T1(); ! 436: break; ! 437: case CC_OP_LSR: ! 438: gen_op_lsrl_T0_T1(); ! 439: break; ! 440: case CC_OP_ASR: ! 441: gen_op_asrl_T0_T1(); ! 442: break; ! 443: case CC_OP_NEG: ! 444: gen_op_negl_T0_T1(); ! 445: /* Extended arithmetics. */ ! 446: gen_op_subxl_T0_C(); ! 447: break; ! 448: case CC_OP_LZ: ! 449: gen_op_lz_T0_T1(); ! 450: break; ! 451: case CC_OP_BTST: ! 452: gen_op_btst_T0_T1(); ! 453: writeback = 0; ! 454: break; ! 455: case CC_OP_MULS: ! 456: gen_op_muls_T0_T1(); ! 457: break; ! 458: case CC_OP_MULU: ! 459: gen_op_mulu_T0_T1(); ! 460: break; ! 461: case CC_OP_DSTEP: ! 462: gen_op_dstep_T0_T1(); ! 463: break; ! 464: case CC_OP_BOUND: ! 465: gen_op_bound_T0_T1(); ! 466: break; ! 467: case CC_OP_CMP: ! 468: gen_op_negl_T1_T1(); ! 469: gen_op_addl_T0_T1(); ! 470: /* CRIS flag evaluation needs ~src. */ ! 471: gen_op_negl_T1_T1(); ! 472: gen_op_not_T1_T1(); ! 473: ! 474: /* Extended arithmetics. */ ! 475: gen_op_subxl_T0_C(); ! 476: writeback = 0; ! 477: break; ! 478: default: ! 479: fprintf (logfile, "illegal ALU op.\n"); ! 480: BUG(); ! 481: break; ! 482: } ! 483: ! 484: if (dc->update_cc) ! 485: gen_op_update_cc_src_T1(); ! 486: ! 487: if (size == 1) ! 488: gen_op_andl_T0_im(0xff); ! 489: else if (size == 2) ! 490: gen_op_andl_T0_im(0xffff); ! 491: /* Writeback. */ ! 492: if (writeback) { ! 493: if (size == 4) ! 494: gen_movl_reg_T0[rd](); ! 495: else { ! 496: gen_op_movl_T1_T0(); ! 497: gen_movl_T0_reg[rd](); ! 498: if (size == 1) ! 499: gen_op_andl_T0_im(~0xff); ! 500: else ! 501: gen_op_andl_T0_im(~0xffff); ! 502: gen_op_orl_T0_T1(); ! 503: gen_movl_reg_T0[rd](); ! 504: gen_op_movl_T0_T1(); ! 505: } ! 506: } ! 507: if (dc->update_cc) ! 508: gen_op_update_cc_result_T0(); ! 509: ! 510: { ! 511: /* TODO: Optimize this. */ ! 512: if (!dc->flagx_live) ! 513: cris_evaluate_flags(dc); ! 514: } ! 515: } ! 516: ! 517: static int arith_cc(DisasContext *dc) ! 518: { ! 519: if (dc->update_cc) { ! 520: switch (dc->cc_op) { ! 521: case CC_OP_ADD: return 1; ! 522: case CC_OP_SUB: return 1; ! 523: case CC_OP_LSL: return 1; ! 524: case CC_OP_LSR: return 1; ! 525: case CC_OP_ASR: return 1; ! 526: case CC_OP_CMP: return 1; ! 527: default: ! 528: return 0; ! 529: } ! 530: } ! 531: return 0; ! 532: } ! 533: ! 534: static void gen_tst_cc (DisasContext *dc, int cond) ! 535: { ! 536: int arith_opt; ! 537: ! 538: /* TODO: optimize more condition codes. */ ! 539: arith_opt = arith_cc(dc) && !dc->flags_live; ! 540: switch (cond) { ! 541: case CC_EQ: ! 542: if (arith_opt) ! 543: gen_op_tst_cc_eq_fast (); ! 544: else { ! 545: cris_evaluate_flags(dc); ! 546: gen_op_tst_cc_eq (); ! 547: } ! 548: break; ! 549: case CC_NE: ! 550: if (arith_opt) ! 551: gen_op_tst_cc_ne_fast (); ! 552: else { ! 553: cris_evaluate_flags(dc); ! 554: gen_op_tst_cc_ne (); ! 555: } ! 556: break; ! 557: case CC_CS: ! 558: cris_evaluate_flags(dc); ! 559: gen_op_tst_cc_cs (); ! 560: break; ! 561: case CC_CC: ! 562: cris_evaluate_flags(dc); ! 563: gen_op_tst_cc_cc (); ! 564: break; ! 565: case CC_VS: ! 566: cris_evaluate_flags(dc); ! 567: gen_op_tst_cc_vs (); ! 568: break; ! 569: case CC_VC: ! 570: cris_evaluate_flags(dc); ! 571: gen_op_tst_cc_vc (); ! 572: break; ! 573: case CC_PL: ! 574: if (arith_opt) ! 575: gen_op_tst_cc_pl_fast (); ! 576: else { ! 577: cris_evaluate_flags(dc); ! 578: gen_op_tst_cc_pl (); ! 579: } ! 580: break; ! 581: case CC_MI: ! 582: if (arith_opt) ! 583: gen_op_tst_cc_mi_fast (); ! 584: else { ! 585: cris_evaluate_flags(dc); ! 586: gen_op_tst_cc_mi (); ! 587: } ! 588: break; ! 589: case CC_LS: ! 590: cris_evaluate_flags(dc); ! 591: gen_op_tst_cc_ls (); ! 592: break; ! 593: case CC_HI: ! 594: cris_evaluate_flags(dc); ! 595: gen_op_tst_cc_hi (); ! 596: break; ! 597: case CC_GE: ! 598: cris_evaluate_flags(dc); ! 599: gen_op_tst_cc_ge (); ! 600: break; ! 601: case CC_LT: ! 602: cris_evaluate_flags(dc); ! 603: gen_op_tst_cc_lt (); ! 604: break; ! 605: case CC_GT: ! 606: cris_evaluate_flags(dc); ! 607: gen_op_tst_cc_gt (); ! 608: break; ! 609: case CC_LE: ! 610: cris_evaluate_flags(dc); ! 611: gen_op_tst_cc_le (); ! 612: break; ! 613: case CC_P: ! 614: cris_evaluate_flags(dc); ! 615: gen_op_tst_cc_p (); ! 616: break; ! 617: case CC_A: ! 618: cris_evaluate_flags(dc); ! 619: gen_op_movl_T0_im (1); ! 620: break; ! 621: default: ! 622: BUG(); ! 623: break; ! 624: }; ! 625: } ! 626: ! 627: static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond) ! 628: { ! 629: /* This helps us re-schedule the micro-code to insns in delay-slots ! 630: before the actual jump. */ ! 631: dc->delayed_branch = 2; ! 632: dc->delayed_pc = dc->pc + offset; ! 633: dc->bcc = cond; ! 634: if (cond != CC_A) ! 635: { ! 636: gen_tst_cc (dc, cond); ! 637: gen_op_evaluate_bcc (); ! 638: } ! 639: gen_op_movl_T0_im (dc->delayed_pc); ! 640: gen_op_movl_btarget_T0 (); ! 641: } ! 642: ! 643: /* Dynamic jumps, when the dest is in a live reg for example. */ ! 644: void cris_prepare_dyn_jmp (DisasContext *dc) ! 645: { ! 646: /* This helps us re-schedule the micro-code to insns in delay-slots ! 647: before the actual jump. */ ! 648: dc->delayed_branch = 2; ! 649: dc->dyn_jmp = 1; ! 650: dc->bcc = CC_A; ! 651: } ! 652: ! 653: void cris_prepare_jmp (DisasContext *dc, uint32_t dst) ! 654: { ! 655: /* This helps us re-schedule the micro-code to insns in delay-slots ! 656: before the actual jump. */ ! 657: dc->delayed_branch = 2; ! 658: dc->delayed_pc = dst; ! 659: dc->dyn_jmp = 0; ! 660: dc->bcc = CC_A; ! 661: } ! 662: ! 663: void gen_load_T0_T0 (DisasContext *dc, unsigned int size, int sign) ! 664: { ! 665: if (size == 1) { ! 666: if (sign) ! 667: gen_op_ldb_T0_T0(dc); ! 668: else ! 669: gen_op_ldub_T0_T0(dc); ! 670: } ! 671: else if (size == 2) { ! 672: if (sign) ! 673: gen_op_ldw_T0_T0(dc); ! 674: else ! 675: gen_op_lduw_T0_T0(dc); ! 676: } ! 677: else { ! 678: gen_op_ldl_T0_T0(dc); ! 679: } ! 680: } ! 681: ! 682: void gen_store_T0_T1 (DisasContext *dc, unsigned int size) ! 683: { ! 684: /* Remember, operands are flipped. CRIS has reversed order. */ ! 685: if (size == 1) { ! 686: gen_op_stb_T0_T1(dc); ! 687: } ! 688: else if (size == 2) { ! 689: gen_op_stw_T0_T1(dc); ! 690: } ! 691: else ! 692: gen_op_stl_T0_T1(dc); ! 693: } ! 694: ! 695: /* sign extend T1 according to size. */ ! 696: static void gen_sext_T1_T0(int size) ! 697: { ! 698: if (size == 1) ! 699: gen_op_extb_T1_T0(); ! 700: else if (size == 2) ! 701: gen_op_extw_T1_T0(); ! 702: } ! 703: ! 704: static void gen_sext_T1_T1(int size) ! 705: { ! 706: if (size == 1) ! 707: gen_op_extb_T1_T1(); ! 708: else if (size == 2) ! 709: gen_op_extw_T1_T1(); ! 710: } ! 711: ! 712: static void gen_sext_T0_T0(int size) ! 713: { ! 714: if (size == 1) ! 715: gen_op_extb_T0_T0(); ! 716: else if (size == 2) ! 717: gen_op_extw_T0_T0(); ! 718: } ! 719: ! 720: static void gen_zext_T0_T0(int size) ! 721: { ! 722: if (size == 1) ! 723: gen_op_zextb_T0_T0(); ! 724: else if (size == 2) ! 725: gen_op_zextw_T0_T0(); ! 726: } ! 727: ! 728: static void gen_zext_T1_T0(int size) ! 729: { ! 730: if (size == 1) ! 731: gen_op_zextb_T1_T0(); ! 732: else if (size == 2) ! 733: gen_op_zextw_T1_T0(); ! 734: } ! 735: ! 736: static void gen_zext_T1_T1(int size) ! 737: { ! 738: if (size == 1) ! 739: gen_op_zextb_T1_T1(); ! 740: else if (size == 2) ! 741: gen_op_zextw_T1_T1(); ! 742: } ! 743: ! 744: #if DISAS_CRIS ! 745: static char memsize_char(int size) ! 746: { ! 747: switch (size) ! 748: { ! 749: case 1: return 'b'; break; ! 750: case 2: return 'w'; break; ! 751: case 4: return 'd'; break; ! 752: default: ! 753: return 'x'; ! 754: break; ! 755: } ! 756: } ! 757: #endif ! 758: ! 759: static unsigned int memsize_z(DisasContext *dc) ! 760: { ! 761: return dc->zsize + 1; ! 762: } ! 763: ! 764: static unsigned int memsize_zz(DisasContext *dc) ! 765: { ! 766: switch (dc->zzsize) ! 767: { ! 768: case 0: return 1; ! 769: case 1: return 2; ! 770: default: ! 771: return 4; ! 772: } ! 773: } ! 774: ! 775: static void do_postinc (DisasContext *dc, int size) ! 776: { ! 777: if (!dc->postinc) ! 778: return; ! 779: gen_movl_T0_reg[dc->op1](); ! 780: gen_op_addl_T0_im(size); ! 781: gen_movl_reg_T0[dc->op1](); ! 782: } ! 783: ! 784: ! 785: static void dec_prep_move_r(DisasContext *dc, int rs, int rd, ! 786: int size, int s_ext) ! 787: { ! 788: gen_movl_T0_reg[rs](); ! 789: gen_op_movl_T1_T0(); ! 790: if (s_ext) ! 791: gen_sext_T1_T1(size); ! 792: else ! 793: gen_zext_T1_T1(size); ! 794: } ! 795: ! 796: /* Prepare T0 and T1 for a register alu operation. ! 797: s_ext decides if the operand1 should be sign-extended or zero-extended when ! 798: needed. */ ! 799: static void dec_prep_alu_r(DisasContext *dc, int rs, int rd, ! 800: int size, int s_ext) ! 801: { ! 802: dec_prep_move_r(dc, rs, rd, size, s_ext); ! 803: ! 804: gen_movl_T0_reg[rd](); ! 805: if (s_ext) ! 806: gen_sext_T0_T0(size); ! 807: else ! 808: gen_zext_T0_T0(size); ! 809: } ! 810: ! 811: /* Prepare T0 and T1 for a memory + alu operation. ! 812: s_ext decides if the operand1 should be sign-extended or zero-extended when ! 813: needed. */ ! 814: static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize) ! 815: { ! 816: unsigned int rs, rd; ! 817: uint32_t imm; ! 818: int is_imm; ! 819: int insn_len = 2; ! 820: ! 821: rs = dc->op1; ! 822: rd = dc->op2; ! 823: is_imm = rs == 15 && dc->postinc; ! 824: ! 825: /* Load [$rs] onto T1. */ ! 826: if (is_imm) { ! 827: insn_len = 2 + memsize; ! 828: if (memsize == 1) ! 829: insn_len++; ! 830: ! 831: imm = ldl_code(dc->pc + 2); ! 832: if (memsize != 4) { ! 833: if (s_ext) { ! 834: imm = sign_extend(imm, (memsize * 8) - 1); ! 835: } else { ! 836: if (memsize == 1) ! 837: imm &= 0xff; ! 838: else ! 839: imm &= 0xffff; ! 840: } ! 841: } ! 842: DIS(fprintf (logfile, "imm=%x rd=%d sext=%d ms=%d\n", ! 843: imm, rd, s_ext, memsize)); ! 844: gen_op_movl_T1_im (imm); ! 845: dc->postinc = 0; ! 846: } else { ! 847: gen_movl_T0_reg[rs](); ! 848: gen_load_T0_T0(dc, memsize, 0); ! 849: gen_op_movl_T1_T0(); ! 850: if (s_ext) ! 851: gen_sext_T1_T1(memsize); ! 852: else ! 853: gen_zext_T1_T1(memsize); ! 854: } ! 855: ! 856: /* put dest in T0. */ ! 857: gen_movl_T0_reg[rd](); ! 858: return insn_len; ! 859: } ! 860: ! 861: #if DISAS_CRIS ! 862: static const char *cc_name(int cc) ! 863: { ! 864: static char *cc_names[16] = { ! 865: "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi", ! 866: "ls", "hi", "ge", "lt", "gt", "le", "a", "p" ! 867: }; ! 868: assert(cc < 16); ! 869: return cc_names[cc]; ! 870: } ! 871: #endif ! 872: ! 873: static unsigned int dec_bccq(DisasContext *dc) ! 874: { ! 875: int32_t offset; ! 876: int sign; ! 877: uint32_t cond = dc->op2; ! 878: int tmp; ! 879: ! 880: offset = EXTRACT_FIELD (dc->ir, 1, 7); ! 881: sign = EXTRACT_FIELD(dc->ir, 0, 0); ! 882: ! 883: offset *= 2; ! 884: offset |= sign << 8; ! 885: tmp = offset; ! 886: offset = sign_extend(offset, 8); ! 887: ! 888: /* op2 holds the condition-code. */ ! 889: cris_cc_mask(dc, 0); ! 890: cris_prepare_cc_branch (dc, offset, cond); ! 891: return 2; ! 892: } ! 893: static unsigned int dec_addoq(DisasContext *dc) ! 894: { ! 895: uint32_t imm; ! 896: ! 897: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7); ! 898: imm = sign_extend(dc->op1, 7); ! 899: ! 900: DIS(fprintf (logfile, "addoq %d, $r%u\n", imm, dc->op2)); ! 901: cris_cc_mask(dc, 0); ! 902: /* Fetch register operand, */ ! 903: gen_movl_T0_reg[dc->op2](); ! 904: gen_op_movl_T1_im(imm); ! 905: crisv32_alu_op(dc, CC_OP_ADD, REG_ACR, 4); ! 906: return 2; ! 907: } ! 908: static unsigned int dec_addq(DisasContext *dc) ! 909: { ! 910: DIS(fprintf (logfile, "addq %u, $r%u\n", dc->op1, dc->op2)); ! 911: ! 912: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); ! 913: ! 914: cris_cc_mask(dc, CC_MASK_NZVC); ! 915: /* Fetch register operand, */ ! 916: gen_movl_T0_reg[dc->op2](); ! 917: gen_op_movl_T1_im(dc->op1); ! 918: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4); ! 919: return 2; ! 920: } ! 921: static unsigned int dec_moveq(DisasContext *dc) ! 922: { ! 923: uint32_t imm; ! 924: ! 925: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); ! 926: imm = sign_extend(dc->op1, 5); ! 927: DIS(fprintf (logfile, "moveq %d, $r%u\n", imm, dc->op2)); ! 928: ! 929: cris_cc_mask(dc, 0); ! 930: gen_op_movl_T1_im(imm); ! 931: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4); ! 932: ! 933: return 2; ! 934: } ! 935: static unsigned int dec_subq(DisasContext *dc) ! 936: { ! 937: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); ! 938: ! 939: DIS(fprintf (logfile, "subq %u, $r%u\n", dc->op1, dc->op2)); ! 940: ! 941: cris_cc_mask(dc, CC_MASK_NZVC); ! 942: /* Fetch register operand, */ ! 943: gen_movl_T0_reg[dc->op2](); ! 944: gen_op_movl_T1_im(dc->op1); ! 945: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4); ! 946: return 2; ! 947: } ! 948: static unsigned int dec_cmpq(DisasContext *dc) ! 949: { ! 950: uint32_t imm; ! 951: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); ! 952: imm = sign_extend(dc->op1, 5); ! 953: ! 954: DIS(fprintf (logfile, "cmpq %d, $r%d\n", imm, dc->op2)); ! 955: cris_cc_mask(dc, CC_MASK_NZVC); ! 956: gen_movl_T0_reg[dc->op2](); ! 957: gen_op_movl_T1_im(imm); ! 958: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4); ! 959: return 2; ! 960: } ! 961: static unsigned int dec_andq(DisasContext *dc) ! 962: { ! 963: uint32_t imm; ! 964: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); ! 965: imm = sign_extend(dc->op1, 5); ! 966: ! 967: DIS(fprintf (logfile, "andq %d, $r%d\n", imm, dc->op2)); ! 968: cris_cc_mask(dc, CC_MASK_NZ); ! 969: gen_movl_T0_reg[dc->op2](); ! 970: gen_op_movl_T1_im(imm); ! 971: crisv32_alu_op(dc, CC_OP_AND, dc->op2, 4); ! 972: return 2; ! 973: } ! 974: static unsigned int dec_orq(DisasContext *dc) ! 975: { ! 976: uint32_t imm; ! 977: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5); ! 978: imm = sign_extend(dc->op1, 5); ! 979: DIS(fprintf (logfile, "orq %d, $r%d\n", imm, dc->op2)); ! 980: cris_cc_mask(dc, CC_MASK_NZ); ! 981: gen_movl_T0_reg[dc->op2](); ! 982: gen_op_movl_T1_im(imm); ! 983: crisv32_alu_op(dc, CC_OP_OR, dc->op2, 4); ! 984: return 2; ! 985: } ! 986: static unsigned int dec_btstq(DisasContext *dc) ! 987: { ! 988: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); ! 989: DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2)); ! 990: cris_evaluate_flags(dc); ! 991: cris_cc_mask(dc, CC_MASK_NZ); ! 992: gen_movl_T0_reg[dc->op2](); ! 993: gen_op_movl_T1_im(dc->op1); ! 994: crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4); ! 995: ! 996: cris_update_cc_op(dc, CC_OP_FLAGS); ! 997: gen_op_movl_flags_T0(); ! 998: dc->flags_live = 1; ! 999: return 2; ! 1000: } ! 1001: static unsigned int dec_asrq(DisasContext *dc) ! 1002: { ! 1003: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); ! 1004: DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2)); ! 1005: cris_cc_mask(dc, CC_MASK_NZ); ! 1006: gen_movl_T0_reg[dc->op2](); ! 1007: gen_op_movl_T1_im(dc->op1); ! 1008: crisv32_alu_op(dc, CC_OP_ASR, dc->op2, 4); ! 1009: return 2; ! 1010: } ! 1011: static unsigned int dec_lslq(DisasContext *dc) ! 1012: { ! 1013: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); ! 1014: DIS(fprintf (logfile, "lslq %u, $r%d\n", dc->op1, dc->op2)); ! 1015: ! 1016: cris_cc_mask(dc, CC_MASK_NZ); ! 1017: gen_movl_T0_reg[dc->op2](); ! 1018: gen_op_movl_T1_im(dc->op1); ! 1019: crisv32_alu_op(dc, CC_OP_LSL, dc->op2, 4); ! 1020: return 2; ! 1021: } ! 1022: static unsigned int dec_lsrq(DisasContext *dc) ! 1023: { ! 1024: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); ! 1025: DIS(fprintf (logfile, "lsrq %u, $r%d\n", dc->op1, dc->op2)); ! 1026: ! 1027: cris_cc_mask(dc, CC_MASK_NZ); ! 1028: gen_movl_T0_reg[dc->op2](); ! 1029: gen_op_movl_T1_im(dc->op1); ! 1030: crisv32_alu_op(dc, CC_OP_LSR, dc->op2, 4); ! 1031: return 2; ! 1032: } ! 1033: ! 1034: static unsigned int dec_move_r(DisasContext *dc) ! 1035: { ! 1036: int size = memsize_zz(dc); ! 1037: ! 1038: DIS(fprintf (logfile, "move.%c $r%u, $r%u\n", ! 1039: memsize_char(size), dc->op1, dc->op2)); ! 1040: ! 1041: cris_cc_mask(dc, CC_MASK_NZ); ! 1042: dec_prep_move_r(dc, dc->op1, dc->op2, size, 0); ! 1043: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, size); ! 1044: return 2; ! 1045: } ! 1046: ! 1047: static unsigned int dec_scc_r(DisasContext *dc) ! 1048: { ! 1049: int cond = dc->op2; ! 1050: ! 1051: DIS(fprintf (logfile, "s%s $r%u\n", ! 1052: cc_name(cond), dc->op1)); ! 1053: ! 1054: if (cond != CC_A) ! 1055: { ! 1056: gen_tst_cc (dc, cond); ! 1057: gen_op_movl_T1_T0(); ! 1058: } ! 1059: else ! 1060: gen_op_movl_T1_im(1); ! 1061: ! 1062: cris_cc_mask(dc, 0); ! 1063: crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4); ! 1064: return 2; ! 1065: } ! 1066: ! 1067: static unsigned int dec_and_r(DisasContext *dc) ! 1068: { ! 1069: int size = memsize_zz(dc); ! 1070: ! 1071: DIS(fprintf (logfile, "and.%c $r%u, $r%u\n", ! 1072: memsize_char(size), dc->op1, dc->op2)); ! 1073: cris_cc_mask(dc, CC_MASK_NZ); ! 1074: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0); ! 1075: crisv32_alu_op(dc, CC_OP_AND, dc->op2, size); ! 1076: return 2; ! 1077: } ! 1078: ! 1079: static unsigned int dec_lz_r(DisasContext *dc) ! 1080: { ! 1081: DIS(fprintf (logfile, "lz $r%u, $r%u\n", ! 1082: dc->op1, dc->op2)); ! 1083: cris_cc_mask(dc, CC_MASK_NZ); ! 1084: dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0); ! 1085: crisv32_alu_op(dc, CC_OP_LZ, dc->op2, 4); ! 1086: return 2; ! 1087: } ! 1088: ! 1089: static unsigned int dec_lsl_r(DisasContext *dc) ! 1090: { ! 1091: int size = memsize_zz(dc); ! 1092: ! 1093: DIS(fprintf (logfile, "lsl.%c $r%u, $r%u\n", ! 1094: memsize_char(size), dc->op1, dc->op2)); ! 1095: cris_cc_mask(dc, CC_MASK_NZ); ! 1096: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0); ! 1097: gen_op_andl_T1_im(63); ! 1098: crisv32_alu_op(dc, CC_OP_LSL, dc->op2, size); ! 1099: return 2; ! 1100: } ! 1101: ! 1102: static unsigned int dec_lsr_r(DisasContext *dc) ! 1103: { ! 1104: int size = memsize_zz(dc); ! 1105: ! 1106: DIS(fprintf (logfile, "lsr.%c $r%u, $r%u\n", ! 1107: memsize_char(size), dc->op1, dc->op2)); ! 1108: cris_cc_mask(dc, CC_MASK_NZ); ! 1109: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0); ! 1110: gen_op_andl_T1_im(63); ! 1111: crisv32_alu_op(dc, CC_OP_LSR, dc->op2, size); ! 1112: return 2; ! 1113: } ! 1114: ! 1115: static unsigned int dec_asr_r(DisasContext *dc) ! 1116: { ! 1117: int size = memsize_zz(dc); ! 1118: ! 1119: DIS(fprintf (logfile, "asr.%c $r%u, $r%u\n", ! 1120: memsize_char(size), dc->op1, dc->op2)); ! 1121: cris_cc_mask(dc, CC_MASK_NZ); ! 1122: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1); ! 1123: gen_op_andl_T1_im(63); ! 1124: crisv32_alu_op(dc, CC_OP_ASR, dc->op2, size); ! 1125: return 2; ! 1126: } ! 1127: ! 1128: static unsigned int dec_muls_r(DisasContext *dc) ! 1129: { ! 1130: int size = memsize_zz(dc); ! 1131: ! 1132: DIS(fprintf (logfile, "muls.%c $r%u, $r%u\n", ! 1133: memsize_char(size), dc->op1, dc->op2)); ! 1134: cris_cc_mask(dc, CC_MASK_NZV); ! 1135: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1); ! 1136: gen_sext_T0_T0(size); ! 1137: crisv32_alu_op(dc, CC_OP_MULS, dc->op2, 4); ! 1138: return 2; ! 1139: } ! 1140: ! 1141: static unsigned int dec_mulu_r(DisasContext *dc) ! 1142: { ! 1143: int size = memsize_zz(dc); ! 1144: ! 1145: DIS(fprintf (logfile, "mulu.%c $r%u, $r%u\n", ! 1146: memsize_char(size), dc->op1, dc->op2)); ! 1147: cris_cc_mask(dc, CC_MASK_NZV); ! 1148: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0); ! 1149: gen_zext_T0_T0(size); ! 1150: crisv32_alu_op(dc, CC_OP_MULU, dc->op2, 4); ! 1151: return 2; ! 1152: } ! 1153: ! 1154: ! 1155: static unsigned int dec_dstep_r(DisasContext *dc) ! 1156: { ! 1157: DIS(fprintf (logfile, "dstep $r%u, $r%u\n", dc->op1, dc->op2)); ! 1158: cris_cc_mask(dc, CC_MASK_NZ); ! 1159: gen_movl_T0_reg[dc->op1](); ! 1160: gen_op_movl_T1_T0(); ! 1161: gen_movl_T0_reg[dc->op2](); ! 1162: crisv32_alu_op(dc, CC_OP_DSTEP, dc->op2, 4); ! 1163: return 2; ! 1164: } ! 1165: ! 1166: static unsigned int dec_xor_r(DisasContext *dc) ! 1167: { ! 1168: int size = memsize_zz(dc); ! 1169: DIS(fprintf (logfile, "xor.%c $r%u, $r%u\n", ! 1170: memsize_char(size), dc->op1, dc->op2)); ! 1171: BUG_ON(size != 4); /* xor is dword. */ ! 1172: cris_cc_mask(dc, CC_MASK_NZ); ! 1173: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0); ! 1174: crisv32_alu_op(dc, CC_OP_XOR, dc->op2, 4); ! 1175: return 2; ! 1176: } ! 1177: ! 1178: static unsigned int dec_bound_r(DisasContext *dc) ! 1179: { ! 1180: int size = memsize_zz(dc); ! 1181: DIS(fprintf (logfile, "bound.%c $r%u, $r%u\n", ! 1182: memsize_char(size), dc->op1, dc->op2)); ! 1183: cris_cc_mask(dc, CC_MASK_NZ); ! 1184: /* TODO: needs optmimization. */ ! 1185: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0); ! 1186: /* rd should be 4. */ ! 1187: gen_movl_T0_reg[dc->op2](); ! 1188: crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4); ! 1189: return 2; ! 1190: } ! 1191: ! 1192: static unsigned int dec_cmp_r(DisasContext *dc) ! 1193: { ! 1194: int size = memsize_zz(dc); ! 1195: DIS(fprintf (logfile, "cmp.%c $r%u, $r%u\n", ! 1196: memsize_char(size), dc->op1, dc->op2)); ! 1197: cris_cc_mask(dc, CC_MASK_NZVC); ! 1198: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0); ! 1199: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, size); ! 1200: return 2; ! 1201: } ! 1202: ! 1203: static unsigned int dec_abs_r(DisasContext *dc) ! 1204: { ! 1205: DIS(fprintf (logfile, "abs $r%u, $r%u\n", ! 1206: dc->op1, dc->op2)); ! 1207: cris_cc_mask(dc, CC_MASK_NZ); ! 1208: dec_prep_move_r(dc, dc->op1, dc->op2, 4, 0); ! 1209: gen_op_absl_T1_T1(); ! 1210: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4); ! 1211: return 2; ! 1212: } ! 1213: ! 1214: static unsigned int dec_add_r(DisasContext *dc) ! 1215: { ! 1216: int size = memsize_zz(dc); ! 1217: DIS(fprintf (logfile, "add.%c $r%u, $r%u\n", ! 1218: memsize_char(size), dc->op1, dc->op2)); ! 1219: cris_cc_mask(dc, CC_MASK_NZVC); ! 1220: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0); ! 1221: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, size); ! 1222: return 2; ! 1223: } ! 1224: ! 1225: static unsigned int dec_addc_r(DisasContext *dc) ! 1226: { ! 1227: DIS(fprintf (logfile, "addc $r%u, $r%u\n", ! 1228: dc->op1, dc->op2)); ! 1229: cris_evaluate_flags(dc); ! 1230: cris_cc_mask(dc, CC_MASK_NZVC); ! 1231: dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0); ! 1232: crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4); ! 1233: return 2; ! 1234: } ! 1235: ! 1236: static unsigned int dec_mcp_r(DisasContext *dc) ! 1237: { ! 1238: DIS(fprintf (logfile, "mcp $p%u, $r%u\n", ! 1239: dc->op2, dc->op1)); ! 1240: cris_evaluate_flags(dc); ! 1241: cris_cc_mask(dc, CC_MASK_RNZV); ! 1242: gen_movl_T0_preg[dc->op2](); ! 1243: gen_op_movl_T1_T0(); ! 1244: gen_movl_T0_reg[dc->op1](); ! 1245: crisv32_alu_op(dc, CC_OP_MCP, dc->op1, 4); ! 1246: return 2; ! 1247: } ! 1248: ! 1249: #if DISAS_CRIS ! 1250: static char * swapmode_name(int mode, char *modename) { ! 1251: int i = 0; ! 1252: if (mode & 8) ! 1253: modename[i++] = 'n'; ! 1254: if (mode & 4) ! 1255: modename[i++] = 'w'; ! 1256: if (mode & 2) ! 1257: modename[i++] = 'b'; ! 1258: if (mode & 1) ! 1259: modename[i++] = 'r'; ! 1260: modename[i++] = 0; ! 1261: return modename; ! 1262: } ! 1263: #endif ! 1264: ! 1265: static unsigned int dec_swap_r(DisasContext *dc) ! 1266: { ! 1267: DIS(char modename[4]); ! 1268: DIS(fprintf (logfile, "swap%s $r%u\n", ! 1269: swapmode_name(dc->op2, modename), dc->op1)); ! 1270: ! 1271: cris_cc_mask(dc, CC_MASK_NZ); ! 1272: gen_movl_T0_reg[dc->op1](); ! 1273: if (dc->op2 & 8) ! 1274: gen_op_not_T0_T0(); ! 1275: if (dc->op2 & 4) ! 1276: gen_op_swapw_T0_T0(); ! 1277: if (dc->op2 & 2) ! 1278: gen_op_swapb_T0_T0(); ! 1279: if (dc->op2 & 1) ! 1280: gen_op_swapr_T0_T0(); ! 1281: gen_op_movl_T1_T0(); ! 1282: crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4); ! 1283: return 2; ! 1284: } ! 1285: ! 1286: static unsigned int dec_or_r(DisasContext *dc) ! 1287: { ! 1288: int size = memsize_zz(dc); ! 1289: DIS(fprintf (logfile, "or.%c $r%u, $r%u\n", ! 1290: memsize_char(size), dc->op1, dc->op2)); ! 1291: cris_cc_mask(dc, CC_MASK_NZ); ! 1292: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0); ! 1293: crisv32_alu_op(dc, CC_OP_OR, dc->op2, size); ! 1294: return 2; ! 1295: } ! 1296: ! 1297: static unsigned int dec_addi_r(DisasContext *dc) ! 1298: { ! 1299: DIS(fprintf (logfile, "addi.%c $r%u, $r%u\n", ! 1300: memsize_char(memsize_zz(dc)), dc->op2, dc->op1)); ! 1301: cris_cc_mask(dc, 0); ! 1302: dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0); ! 1303: gen_op_lsll_T0_im(dc->zzsize); ! 1304: gen_op_addl_T0_T1(); ! 1305: gen_movl_reg_T0[dc->op1](); ! 1306: return 2; ! 1307: } ! 1308: ! 1309: static unsigned int dec_addi_acr(DisasContext *dc) ! 1310: { ! 1311: DIS(fprintf (logfile, "addi.%c $r%u, $r%u, $acr\n", ! 1312: memsize_char(memsize_zz(dc)), dc->op2, dc->op1)); ! 1313: cris_cc_mask(dc, 0); ! 1314: dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0); ! 1315: gen_op_lsll_T0_im(dc->zzsize); ! 1316: gen_op_addl_T0_T1(); ! 1317: gen_movl_reg_T0[REG_ACR](); ! 1318: return 2; ! 1319: } ! 1320: ! 1321: static unsigned int dec_neg_r(DisasContext *dc) ! 1322: { ! 1323: int size = memsize_zz(dc); ! 1324: DIS(fprintf (logfile, "neg.%c $r%u, $r%u\n", ! 1325: memsize_char(size), dc->op1, dc->op2)); ! 1326: cris_cc_mask(dc, CC_MASK_NZVC); ! 1327: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0); ! 1328: crisv32_alu_op(dc, CC_OP_NEG, dc->op2, size); ! 1329: return 2; ! 1330: } ! 1331: ! 1332: static unsigned int dec_btst_r(DisasContext *dc) ! 1333: { ! 1334: DIS(fprintf (logfile, "btst $r%u, $r%u\n", ! 1335: dc->op1, dc->op2)); ! 1336: cris_evaluate_flags(dc); ! 1337: cris_cc_mask(dc, CC_MASK_NZ); ! 1338: dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0); ! 1339: crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4); ! 1340: ! 1341: cris_update_cc_op(dc, CC_OP_FLAGS); ! 1342: gen_op_movl_flags_T0(); ! 1343: dc->flags_live = 1; ! 1344: return 2; ! 1345: } ! 1346: ! 1347: static unsigned int dec_sub_r(DisasContext *dc) ! 1348: { ! 1349: int size = memsize_zz(dc); ! 1350: DIS(fprintf (logfile, "sub.%c $r%u, $r%u\n", ! 1351: memsize_char(size), dc->op1, dc->op2)); ! 1352: cris_cc_mask(dc, CC_MASK_NZVC); ! 1353: dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0); ! 1354: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, size); ! 1355: return 2; ! 1356: } ! 1357: ! 1358: /* Zero extension. From size to dword. */ ! 1359: static unsigned int dec_movu_r(DisasContext *dc) ! 1360: { ! 1361: int size = memsize_z(dc); ! 1362: DIS(fprintf (logfile, "movu.%c $r%u, $r%u\n", ! 1363: memsize_char(size), ! 1364: dc->op1, dc->op2)); ! 1365: ! 1366: cris_cc_mask(dc, CC_MASK_NZ); ! 1367: dec_prep_move_r(dc, dc->op1, dc->op2, size, 0); ! 1368: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4); ! 1369: return 2; ! 1370: } ! 1371: ! 1372: /* Sign extension. From size to dword. */ ! 1373: static unsigned int dec_movs_r(DisasContext *dc) ! 1374: { ! 1375: int size = memsize_z(dc); ! 1376: DIS(fprintf (logfile, "movs.%c $r%u, $r%u\n", ! 1377: memsize_char(size), ! 1378: dc->op1, dc->op2)); ! 1379: ! 1380: cris_cc_mask(dc, CC_MASK_NZ); ! 1381: gen_movl_T0_reg[dc->op1](); ! 1382: /* Size can only be qi or hi. */ ! 1383: gen_sext_T1_T0(size); ! 1384: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4); ! 1385: return 2; ! 1386: } ! 1387: ! 1388: /* zero extension. From size to dword. */ ! 1389: static unsigned int dec_addu_r(DisasContext *dc) ! 1390: { ! 1391: int size = memsize_z(dc); ! 1392: DIS(fprintf (logfile, "addu.%c $r%u, $r%u\n", ! 1393: memsize_char(size), ! 1394: dc->op1, dc->op2)); ! 1395: ! 1396: cris_cc_mask(dc, CC_MASK_NZVC); ! 1397: gen_movl_T0_reg[dc->op1](); ! 1398: /* Size can only be qi or hi. */ ! 1399: gen_zext_T1_T0(size); ! 1400: gen_movl_T0_reg[dc->op2](); ! 1401: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4); ! 1402: return 2; ! 1403: } ! 1404: /* Sign extension. From size to dword. */ ! 1405: static unsigned int dec_adds_r(DisasContext *dc) ! 1406: { ! 1407: int size = memsize_z(dc); ! 1408: DIS(fprintf (logfile, "adds.%c $r%u, $r%u\n", ! 1409: memsize_char(size), ! 1410: dc->op1, dc->op2)); ! 1411: ! 1412: cris_cc_mask(dc, CC_MASK_NZVC); ! 1413: gen_movl_T0_reg[dc->op1](); ! 1414: /* Size can only be qi or hi. */ ! 1415: gen_sext_T1_T0(size); ! 1416: gen_movl_T0_reg[dc->op2](); ! 1417: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4); ! 1418: return 2; ! 1419: } ! 1420: ! 1421: /* Zero extension. From size to dword. */ ! 1422: static unsigned int dec_subu_r(DisasContext *dc) ! 1423: { ! 1424: int size = memsize_z(dc); ! 1425: DIS(fprintf (logfile, "subu.%c $r%u, $r%u\n", ! 1426: memsize_char(size), ! 1427: dc->op1, dc->op2)); ! 1428: ! 1429: cris_cc_mask(dc, CC_MASK_NZVC); ! 1430: gen_movl_T0_reg[dc->op1](); ! 1431: /* Size can only be qi or hi. */ ! 1432: gen_zext_T1_T0(size); ! 1433: gen_movl_T0_reg[dc->op2](); ! 1434: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4); ! 1435: return 2; ! 1436: } ! 1437: ! 1438: /* Sign extension. From size to dword. */ ! 1439: static unsigned int dec_subs_r(DisasContext *dc) ! 1440: { ! 1441: int size = memsize_z(dc); ! 1442: DIS(fprintf (logfile, "subs.%c $r%u, $r%u\n", ! 1443: memsize_char(size), ! 1444: dc->op1, dc->op2)); ! 1445: ! 1446: cris_cc_mask(dc, CC_MASK_NZVC); ! 1447: gen_movl_T0_reg[dc->op1](); ! 1448: /* Size can only be qi or hi. */ ! 1449: gen_sext_T1_T0(size); ! 1450: gen_movl_T0_reg[dc->op2](); ! 1451: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4); ! 1452: return 2; ! 1453: } ! 1454: ! 1455: static unsigned int dec_setclrf(DisasContext *dc) ! 1456: { ! 1457: uint32_t flags; ! 1458: int set = (~dc->opcode >> 2) & 1; ! 1459: ! 1460: flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4) ! 1461: | EXTRACT_FIELD(dc->ir, 0, 3); ! 1462: DIS(fprintf (logfile, "set=%d flags=%x\n", set, flags)); ! 1463: if (set && flags == 0) ! 1464: DIS(fprintf (logfile, "nop\n")); ! 1465: else if (!set && (flags & 0x20)) ! 1466: DIS(fprintf (logfile, "di\n")); ! 1467: else ! 1468: DIS(fprintf (logfile, "%sf %x\n", ! 1469: set ? "set" : "clr", ! 1470: flags)); ! 1471: ! 1472: if (set && (flags & X_FLAG)) { ! 1473: dc->flagx_live = 1; ! 1474: dc->flags_x = 1; ! 1475: } ! 1476: ! 1477: /* Simply decode the flags. */ ! 1478: cris_evaluate_flags (dc); ! 1479: cris_update_cc_op(dc, CC_OP_FLAGS); ! 1480: if (set) ! 1481: gen_op_setf (flags); ! 1482: else ! 1483: gen_op_clrf (flags); ! 1484: dc->flags_live = 1; ! 1485: return 2; ! 1486: } ! 1487: ! 1488: static unsigned int dec_move_rs(DisasContext *dc) ! 1489: { ! 1490: DIS(fprintf (logfile, "move $r%u, $s%u\n", dc->op1, dc->op2)); ! 1491: cris_cc_mask(dc, 0); ! 1492: gen_movl_T0_reg[dc->op1](); ! 1493: gen_op_movl_sreg_T0(dc->op2); ! 1494: ! 1495: if (dc->op2 == 5) /* srs is checked at runtime. */ ! 1496: gen_op_movl_tlb_lo_T0(); ! 1497: return 2; ! 1498: } ! 1499: static unsigned int dec_move_sr(DisasContext *dc) ! 1500: { ! 1501: DIS(fprintf (logfile, "move $s%u, $r%u\n", dc->op1, dc->op2)); ! 1502: cris_cc_mask(dc, 0); ! 1503: gen_op_movl_T0_sreg(dc->op1); ! 1504: gen_op_movl_T1_T0(); ! 1505: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4); ! 1506: return 2; ! 1507: } ! 1508: static unsigned int dec_move_rp(DisasContext *dc) ! 1509: { ! 1510: DIS(fprintf (logfile, "move $r%u, $p%u\n", dc->op1, dc->op2)); ! 1511: cris_cc_mask(dc, 0); ! 1512: gen_movl_T0_reg[dc->op1](); ! 1513: gen_op_movl_T1_T0(); ! 1514: gen_movl_preg_T0[dc->op2](); ! 1515: return 2; ! 1516: } ! 1517: static unsigned int dec_move_pr(DisasContext *dc) ! 1518: { ! 1519: DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2)); ! 1520: cris_cc_mask(dc, 0); ! 1521: gen_movl_T0_preg[dc->op2](); ! 1522: gen_op_movl_T1_T0(); ! 1523: crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, preg_sizes[dc->op2]); ! 1524: return 2; ! 1525: } ! 1526: ! 1527: static unsigned int dec_move_mr(DisasContext *dc) ! 1528: { ! 1529: int memsize = memsize_zz(dc); ! 1530: int insn_len; ! 1531: DIS(fprintf (logfile, "move.%c [$r%u%s, $r%u\n", ! 1532: memsize_char(memsize), ! 1533: dc->op1, dc->postinc ? "+]" : "]", ! 1534: dc->op2)); ! 1535: ! 1536: cris_cc_mask(dc, CC_MASK_NZ); ! 1537: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1538: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, memsize); ! 1539: do_postinc(dc, memsize); ! 1540: return insn_len; ! 1541: } ! 1542: ! 1543: static unsigned int dec_movs_m(DisasContext *dc) ! 1544: { ! 1545: int memsize = memsize_z(dc); ! 1546: int insn_len; ! 1547: DIS(fprintf (logfile, "movs.%c [$r%u%s, $r%u\n", ! 1548: memsize_char(memsize), ! 1549: dc->op1, dc->postinc ? "+]" : "]", ! 1550: dc->op2)); ! 1551: ! 1552: /* sign extend. */ ! 1553: cris_cc_mask(dc, CC_MASK_NZ); ! 1554: insn_len = dec_prep_alu_m(dc, 1, memsize); ! 1555: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4); ! 1556: do_postinc(dc, memsize); ! 1557: return insn_len; ! 1558: } ! 1559: ! 1560: static unsigned int dec_addu_m(DisasContext *dc) ! 1561: { ! 1562: int memsize = memsize_z(dc); ! 1563: int insn_len; ! 1564: DIS(fprintf (logfile, "addu.%c [$r%u%s, $r%u\n", ! 1565: memsize_char(memsize), ! 1566: dc->op1, dc->postinc ? "+]" : "]", ! 1567: dc->op2)); ! 1568: ! 1569: /* sign extend. */ ! 1570: cris_cc_mask(dc, CC_MASK_NZVC); ! 1571: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1572: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4); ! 1573: do_postinc(dc, memsize); ! 1574: return insn_len; ! 1575: } ! 1576: ! 1577: static unsigned int dec_adds_m(DisasContext *dc) ! 1578: { ! 1579: int memsize = memsize_z(dc); ! 1580: int insn_len; ! 1581: DIS(fprintf (logfile, "adds.%c [$r%u%s, $r%u\n", ! 1582: memsize_char(memsize), ! 1583: dc->op1, dc->postinc ? "+]" : "]", ! 1584: dc->op2)); ! 1585: ! 1586: /* sign extend. */ ! 1587: cris_cc_mask(dc, CC_MASK_NZVC); ! 1588: insn_len = dec_prep_alu_m(dc, 1, memsize); ! 1589: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4); ! 1590: do_postinc(dc, memsize); ! 1591: return insn_len; ! 1592: } ! 1593: ! 1594: static unsigned int dec_subu_m(DisasContext *dc) ! 1595: { ! 1596: int memsize = memsize_z(dc); ! 1597: int insn_len; ! 1598: DIS(fprintf (logfile, "subu.%c [$r%u%s, $r%u\n", ! 1599: memsize_char(memsize), ! 1600: dc->op1, dc->postinc ? "+]" : "]", ! 1601: dc->op2)); ! 1602: ! 1603: /* sign extend. */ ! 1604: cris_cc_mask(dc, CC_MASK_NZVC); ! 1605: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1606: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4); ! 1607: do_postinc(dc, memsize); ! 1608: return insn_len; ! 1609: } ! 1610: ! 1611: static unsigned int dec_subs_m(DisasContext *dc) ! 1612: { ! 1613: int memsize = memsize_z(dc); ! 1614: int insn_len; ! 1615: DIS(fprintf (logfile, "subs.%c [$r%u%s, $r%u\n", ! 1616: memsize_char(memsize), ! 1617: dc->op1, dc->postinc ? "+]" : "]", ! 1618: dc->op2)); ! 1619: ! 1620: /* sign extend. */ ! 1621: cris_cc_mask(dc, CC_MASK_NZVC); ! 1622: insn_len = dec_prep_alu_m(dc, 1, memsize); ! 1623: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4); ! 1624: do_postinc(dc, memsize); ! 1625: return insn_len; ! 1626: } ! 1627: ! 1628: static unsigned int dec_movu_m(DisasContext *dc) ! 1629: { ! 1630: int memsize = memsize_z(dc); ! 1631: int insn_len; ! 1632: ! 1633: DIS(fprintf (logfile, "movu.%c [$r%u%s, $r%u\n", ! 1634: memsize_char(memsize), ! 1635: dc->op1, dc->postinc ? "+]" : "]", ! 1636: dc->op2)); ! 1637: ! 1638: cris_cc_mask(dc, CC_MASK_NZ); ! 1639: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1640: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4); ! 1641: do_postinc(dc, memsize); ! 1642: return insn_len; ! 1643: } ! 1644: ! 1645: static unsigned int dec_cmpu_m(DisasContext *dc) ! 1646: { ! 1647: int memsize = memsize_z(dc); ! 1648: int insn_len; ! 1649: DIS(fprintf (logfile, "cmpu.%c [$r%u%s, $r%u\n", ! 1650: memsize_char(memsize), ! 1651: dc->op1, dc->postinc ? "+]" : "]", ! 1652: dc->op2)); ! 1653: ! 1654: cris_cc_mask(dc, CC_MASK_NZVC); ! 1655: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1656: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4); ! 1657: do_postinc(dc, memsize); ! 1658: return insn_len; ! 1659: } ! 1660: ! 1661: static unsigned int dec_cmps_m(DisasContext *dc) ! 1662: { ! 1663: int memsize = memsize_z(dc); ! 1664: int insn_len; ! 1665: DIS(fprintf (logfile, "cmps.%c [$r%u%s, $r%u\n", ! 1666: memsize_char(memsize), ! 1667: dc->op1, dc->postinc ? "+]" : "]", ! 1668: dc->op2)); ! 1669: ! 1670: cris_cc_mask(dc, CC_MASK_NZVC); ! 1671: insn_len = dec_prep_alu_m(dc, 1, memsize); ! 1672: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc)); ! 1673: do_postinc(dc, memsize); ! 1674: return insn_len; ! 1675: } ! 1676: ! 1677: static unsigned int dec_cmp_m(DisasContext *dc) ! 1678: { ! 1679: int memsize = memsize_zz(dc); ! 1680: int insn_len; ! 1681: DIS(fprintf (logfile, "cmp.%c [$r%u%s, $r%u\n", ! 1682: memsize_char(memsize), ! 1683: dc->op1, dc->postinc ? "+]" : "]", ! 1684: dc->op2)); ! 1685: ! 1686: cris_cc_mask(dc, CC_MASK_NZVC); ! 1687: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1688: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc)); ! 1689: do_postinc(dc, memsize); ! 1690: return insn_len; ! 1691: } ! 1692: ! 1693: static unsigned int dec_test_m(DisasContext *dc) ! 1694: { ! 1695: int memsize = memsize_zz(dc); ! 1696: int insn_len; ! 1697: DIS(fprintf (logfile, "test.%d [$r%u%s] op2=%x\n", ! 1698: memsize_char(memsize), ! 1699: dc->op1, dc->postinc ? "+]" : "]", ! 1700: dc->op2)); ! 1701: ! 1702: cris_cc_mask(dc, CC_MASK_NZ); ! 1703: gen_op_clrf(3); ! 1704: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1705: gen_op_swp_T0_T1(); ! 1706: gen_op_movl_T1_im(0); ! 1707: crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc)); ! 1708: do_postinc(dc, memsize); ! 1709: return insn_len; ! 1710: } ! 1711: ! 1712: static unsigned int dec_and_m(DisasContext *dc) ! 1713: { ! 1714: int memsize = memsize_zz(dc); ! 1715: int insn_len; ! 1716: DIS(fprintf (logfile, "and.%d [$r%u%s, $r%u\n", ! 1717: memsize_char(memsize), ! 1718: dc->op1, dc->postinc ? "+]" : "]", ! 1719: dc->op2)); ! 1720: ! 1721: cris_cc_mask(dc, CC_MASK_NZ); ! 1722: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1723: crisv32_alu_op(dc, CC_OP_AND, dc->op2, memsize_zz(dc)); ! 1724: do_postinc(dc, memsize); ! 1725: return insn_len; ! 1726: } ! 1727: ! 1728: static unsigned int dec_add_m(DisasContext *dc) ! 1729: { ! 1730: int memsize = memsize_zz(dc); ! 1731: int insn_len; ! 1732: DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n", ! 1733: memsize_char(memsize), ! 1734: dc->op1, dc->postinc ? "+]" : "]", ! 1735: dc->op2)); ! 1736: ! 1737: cris_cc_mask(dc, CC_MASK_NZVC); ! 1738: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1739: crisv32_alu_op(dc, CC_OP_ADD, dc->op2, memsize_zz(dc)); ! 1740: do_postinc(dc, memsize); ! 1741: return insn_len; ! 1742: } ! 1743: ! 1744: static unsigned int dec_addo_m(DisasContext *dc) ! 1745: { ! 1746: int memsize = memsize_zz(dc); ! 1747: int insn_len; ! 1748: DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n", ! 1749: memsize_char(memsize), ! 1750: dc->op1, dc->postinc ? "+]" : "]", ! 1751: dc->op2)); ! 1752: ! 1753: cris_cc_mask(dc, 0); ! 1754: insn_len = dec_prep_alu_m(dc, 1, memsize); ! 1755: crisv32_alu_op(dc, CC_OP_ADD, REG_ACR, 4); ! 1756: do_postinc(dc, memsize); ! 1757: return insn_len; ! 1758: } ! 1759: ! 1760: static unsigned int dec_bound_m(DisasContext *dc) ! 1761: { ! 1762: int memsize = memsize_zz(dc); ! 1763: int insn_len; ! 1764: DIS(fprintf (logfile, "bound.%d [$r%u%s, $r%u\n", ! 1765: memsize_char(memsize), ! 1766: dc->op1, dc->postinc ? "+]" : "]", ! 1767: dc->op2)); ! 1768: ! 1769: cris_cc_mask(dc, CC_MASK_NZ); ! 1770: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1771: crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4); ! 1772: do_postinc(dc, memsize); ! 1773: return insn_len; ! 1774: } ! 1775: ! 1776: static unsigned int dec_addc_mr(DisasContext *dc) ! 1777: { ! 1778: int insn_len = 2; ! 1779: DIS(fprintf (logfile, "addc [$r%u%s, $r%u\n", ! 1780: dc->op1, dc->postinc ? "+]" : "]", ! 1781: dc->op2)); ! 1782: ! 1783: cris_evaluate_flags(dc); ! 1784: cris_cc_mask(dc, CC_MASK_NZVC); ! 1785: insn_len = dec_prep_alu_m(dc, 0, 4); ! 1786: crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4); ! 1787: do_postinc(dc, 4); ! 1788: return insn_len; ! 1789: } ! 1790: ! 1791: static unsigned int dec_sub_m(DisasContext *dc) ! 1792: { ! 1793: int memsize = memsize_zz(dc); ! 1794: int insn_len; ! 1795: DIS(fprintf (logfile, "sub.%c [$r%u%s, $r%u ir=%x zz=%x\n", ! 1796: memsize_char(memsize), ! 1797: dc->op1, dc->postinc ? "+]" : "]", ! 1798: dc->op2, dc->ir, dc->zzsize)); ! 1799: ! 1800: cris_cc_mask(dc, CC_MASK_NZVC); ! 1801: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1802: crisv32_alu_op(dc, CC_OP_SUB, dc->op2, memsize); ! 1803: do_postinc(dc, memsize); ! 1804: return insn_len; ! 1805: } ! 1806: ! 1807: static unsigned int dec_or_m(DisasContext *dc) ! 1808: { ! 1809: int memsize = memsize_zz(dc); ! 1810: int insn_len; ! 1811: DIS(fprintf (logfile, "or.%d [$r%u%s, $r%u pc=%x\n", ! 1812: memsize_char(memsize), ! 1813: dc->op1, dc->postinc ? "+]" : "]", ! 1814: dc->op2, dc->pc)); ! 1815: ! 1816: cris_cc_mask(dc, CC_MASK_NZ); ! 1817: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1818: crisv32_alu_op(dc, CC_OP_OR, dc->op2, memsize_zz(dc)); ! 1819: do_postinc(dc, memsize); ! 1820: return insn_len; ! 1821: } ! 1822: ! 1823: static unsigned int dec_move_mp(DisasContext *dc) ! 1824: { ! 1825: int memsize = memsize_zz(dc); ! 1826: int insn_len = 2; ! 1827: ! 1828: DIS(fprintf (logfile, "move.%c [$r%u%s, $p%u\n", ! 1829: memsize_char(memsize), ! 1830: dc->op1, ! 1831: dc->postinc ? "+]" : "]", ! 1832: dc->op2)); ! 1833: ! 1834: cris_cc_mask(dc, 0); ! 1835: insn_len = dec_prep_alu_m(dc, 0, memsize); ! 1836: gen_op_movl_T0_T1(); ! 1837: gen_movl_preg_T0[dc->op2](); ! 1838: ! 1839: do_postinc(dc, memsize); ! 1840: return insn_len; ! 1841: } ! 1842: ! 1843: static unsigned int dec_move_pm(DisasContext *dc) ! 1844: { ! 1845: int memsize; ! 1846: ! 1847: memsize = preg_sizes[dc->op2]; ! 1848: ! 1849: DIS(fprintf (logfile, "move.%d $p%u, [$r%u%s\n", ! 1850: memsize, dc->op2, dc->op1, dc->postinc ? "+]" : "]")); ! 1851: ! 1852: cris_cc_mask(dc, 0); ! 1853: /* prepare store. */ ! 1854: gen_movl_T0_preg[dc->op2](); ! 1855: gen_op_movl_T1_T0(); ! 1856: gen_movl_T0_reg[dc->op1](); ! 1857: gen_store_T0_T1(dc, memsize); ! 1858: if (dc->postinc) ! 1859: { ! 1860: gen_op_addl_T0_im(memsize); ! 1861: gen_movl_reg_T0[dc->op1](); ! 1862: } ! 1863: return 2; ! 1864: } ! 1865: ! 1866: static unsigned int dec_movem_mr(DisasContext *dc) ! 1867: { ! 1868: int i; ! 1869: ! 1870: DIS(fprintf (logfile, "movem [$r%u%s, $r%u\n", dc->op1, ! 1871: dc->postinc ? "+]" : "]", dc->op2)); ! 1872: ! 1873: cris_cc_mask(dc, 0); ! 1874: /* fetch the address into T1. */ ! 1875: gen_movl_T0_reg[dc->op1](); ! 1876: gen_op_movl_T1_T0(); ! 1877: for (i = 0; i <= dc->op2; i++) { ! 1878: /* Perform the load onto regnum i. Always dword wide. */ ! 1879: gen_load_T0_T0(dc, 4, 0); ! 1880: gen_movl_reg_T0[i](); ! 1881: /* Update the address. */ ! 1882: gen_op_addl_T1_im(4); ! 1883: gen_op_movl_T0_T1(); ! 1884: } ! 1885: if (dc->postinc) { ! 1886: /* writeback the updated pointer value. */ ! 1887: gen_movl_reg_T0[dc->op1](); ! 1888: } ! 1889: return 2; ! 1890: } ! 1891: ! 1892: static unsigned int dec_movem_rm(DisasContext *dc) ! 1893: { ! 1894: int i; ! 1895: ! 1896: DIS(fprintf (logfile, "movem $r%u, [$r%u%s\n", dc->op2, dc->op1, ! 1897: dc->postinc ? "+]" : "]")); ! 1898: ! 1899: cris_cc_mask(dc, 0); ! 1900: for (i = 0; i <= dc->op2; i++) { ! 1901: /* Fetch register i into T1. */ ! 1902: gen_movl_T0_reg[i](); ! 1903: gen_op_movl_T1_T0(); ! 1904: ! 1905: /* Fetch the address into T0. */ ! 1906: gen_movl_T0_reg[dc->op1](); ! 1907: /* Displace it. */ ! 1908: gen_op_addl_T0_im(i * 4); ! 1909: ! 1910: /* Perform the store. */ ! 1911: gen_store_T0_T1(dc, 4); ! 1912: } ! 1913: if (dc->postinc) { ! 1914: /* Update the address. */ ! 1915: gen_op_addl_T0_im(4); ! 1916: /* writeback the updated pointer value. */ ! 1917: gen_movl_reg_T0[dc->op1](); ! 1918: } ! 1919: return 2; ! 1920: } ! 1921: ! 1922: static unsigned int dec_move_rm(DisasContext *dc) ! 1923: { ! 1924: int memsize; ! 1925: ! 1926: memsize = memsize_zz(dc); ! 1927: ! 1928: DIS(fprintf (logfile, "move.%d $r%u, [$r%u]\n", ! 1929: memsize, dc->op2, dc->op1)); ! 1930: ! 1931: cris_cc_mask(dc, 0); ! 1932: /* prepare store. */ ! 1933: gen_movl_T0_reg[dc->op2](); ! 1934: gen_op_movl_T1_T0(); ! 1935: gen_movl_T0_reg[dc->op1](); ! 1936: gen_store_T0_T1(dc, memsize); ! 1937: if (dc->postinc) ! 1938: { ! 1939: gen_op_addl_T0_im(memsize); ! 1940: gen_movl_reg_T0[dc->op1](); ! 1941: } ! 1942: return 2; ! 1943: } ! 1944: ! 1945: ! 1946: static unsigned int dec_lapcq(DisasContext *dc) ! 1947: { ! 1948: DIS(fprintf (logfile, "lapcq %x, $r%u\n", ! 1949: dc->pc + dc->op1*2, dc->op2)); ! 1950: cris_cc_mask(dc, 0); ! 1951: gen_op_movl_T1_im(dc->pc + dc->op1*2); ! 1952: crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4); ! 1953: return 2; ! 1954: } ! 1955: ! 1956: static unsigned int dec_lapc_im(DisasContext *dc) ! 1957: { ! 1958: unsigned int rd; ! 1959: int32_t imm; ! 1960: int insn_len = 6; ! 1961: ! 1962: rd = dc->op2; ! 1963: ! 1964: cris_cc_mask(dc, 0); ! 1965: imm = ldl_code(dc->pc + 2); ! 1966: DIS(fprintf (logfile, "lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2)); ! 1967: gen_op_movl_T0_im (dc->pc + imm); ! 1968: gen_movl_reg_T0[rd] (); ! 1969: return insn_len; ! 1970: } ! 1971: ! 1972: /* Jump to special reg. */ ! 1973: static unsigned int dec_jump_p(DisasContext *dc) ! 1974: { ! 1975: DIS(fprintf (logfile, "jump $p%u\n", dc->op2)); ! 1976: cris_cc_mask(dc, 0); ! 1977: /* Store the return address in Pd. */ ! 1978: gen_movl_T0_preg[dc->op2](); ! 1979: gen_op_movl_btarget_T0(); ! 1980: cris_prepare_dyn_jmp(dc); ! 1981: return 2; ! 1982: } ! 1983: ! 1984: /* Jump and save. */ ! 1985: static unsigned int dec_jas_r(DisasContext *dc) ! 1986: { ! 1987: DIS(fprintf (logfile, "jas $r%u, $p%u\n", dc->op1, dc->op2)); ! 1988: cris_cc_mask(dc, 0); ! 1989: /* Stor the return address in Pd. */ ! 1990: gen_movl_T0_reg[dc->op1](); ! 1991: gen_op_movl_btarget_T0(); ! 1992: gen_op_movl_T0_im(dc->pc + 4); ! 1993: gen_movl_preg_T0[dc->op2](); ! 1994: cris_prepare_dyn_jmp(dc); ! 1995: return 2; ! 1996: } ! 1997: ! 1998: static unsigned int dec_jas_im(DisasContext *dc) ! 1999: { ! 2000: uint32_t imm; ! 2001: ! 2002: imm = ldl_code(dc->pc + 2); ! 2003: ! 2004: DIS(fprintf (logfile, "jas 0x%x\n", imm)); ! 2005: cris_cc_mask(dc, 0); ! 2006: /* Stor the return address in Pd. */ ! 2007: gen_op_movl_T0_im(imm); ! 2008: gen_op_movl_btarget_T0(); ! 2009: gen_op_movl_T0_im(dc->pc + 8); ! 2010: gen_movl_preg_T0[dc->op2](); ! 2011: cris_prepare_dyn_jmp(dc); ! 2012: return 6; ! 2013: } ! 2014: ! 2015: static unsigned int dec_jasc_im(DisasContext *dc) ! 2016: { ! 2017: uint32_t imm; ! 2018: ! 2019: imm = ldl_code(dc->pc + 2); ! 2020: ! 2021: DIS(fprintf (logfile, "jasc 0x%x\n", imm)); ! 2022: cris_cc_mask(dc, 0); ! 2023: /* Stor the return address in Pd. */ ! 2024: gen_op_movl_T0_im(imm); ! 2025: gen_op_movl_btarget_T0(); ! 2026: gen_op_movl_T0_im(dc->pc + 8 + 4); ! 2027: gen_movl_preg_T0[dc->op2](); ! 2028: cris_prepare_dyn_jmp(dc); ! 2029: return 6; ! 2030: } ! 2031: ! 2032: static unsigned int dec_jasc_r(DisasContext *dc) ! 2033: { ! 2034: DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2)); ! 2035: cris_cc_mask(dc, 0); ! 2036: /* Stor the return address in Pd. */ ! 2037: gen_movl_T0_reg[dc->op1](); ! 2038: gen_op_movl_btarget_T0(); ! 2039: gen_op_movl_T0_im(dc->pc + 4 + 4); ! 2040: gen_movl_preg_T0[dc->op2](); ! 2041: cris_prepare_dyn_jmp(dc); ! 2042: return 2; ! 2043: } ! 2044: ! 2045: static unsigned int dec_bcc_im(DisasContext *dc) ! 2046: { ! 2047: int32_t offset; ! 2048: uint32_t cond = dc->op2; ! 2049: ! 2050: offset = ldl_code(dc->pc + 2); ! 2051: offset = sign_extend(offset, 15); ! 2052: ! 2053: DIS(fprintf (logfile, "b%s %d pc=%x dst=%x\n", ! 2054: cc_name(cond), offset, ! 2055: dc->pc, dc->pc + offset)); ! 2056: ! 2057: cris_cc_mask(dc, 0); ! 2058: /* op2 holds the condition-code. */ ! 2059: cris_prepare_cc_branch (dc, offset, cond); ! 2060: return 4; ! 2061: } ! 2062: ! 2063: static unsigned int dec_bas_im(DisasContext *dc) ! 2064: { ! 2065: int32_t simm; ! 2066: ! 2067: ! 2068: simm = ldl_code(dc->pc + 2); ! 2069: ! 2070: DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2)); ! 2071: cris_cc_mask(dc, 0); ! 2072: /* Stor the return address in Pd. */ ! 2073: gen_op_movl_T0_im(dc->pc + simm); ! 2074: gen_op_movl_btarget_T0(); ! 2075: gen_op_movl_T0_im(dc->pc + 8); ! 2076: gen_movl_preg_T0[dc->op2](); ! 2077: cris_prepare_dyn_jmp(dc); ! 2078: return 6; ! 2079: } ! 2080: ! 2081: static unsigned int dec_basc_im(DisasContext *dc) ! 2082: { ! 2083: int32_t simm; ! 2084: simm = ldl_code(dc->pc + 2); ! 2085: ! 2086: DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2)); ! 2087: cris_cc_mask(dc, 0); ! 2088: /* Stor the return address in Pd. */ ! 2089: gen_op_movl_T0_im(dc->pc + simm); ! 2090: gen_op_movl_btarget_T0(); ! 2091: gen_op_movl_T0_im(dc->pc + 12); ! 2092: gen_movl_preg_T0[dc->op2](); ! 2093: cris_prepare_dyn_jmp(dc); ! 2094: return 6; ! 2095: } ! 2096: ! 2097: static unsigned int dec_rfe_etc(DisasContext *dc) ! 2098: { ! 2099: DIS(fprintf (logfile, "rfe_etc opc=%x pc=0x%x op1=%d op2=%d\n", ! 2100: dc->opcode, dc->pc, dc->op1, dc->op2)); ! 2101: ! 2102: cris_cc_mask(dc, 0); ! 2103: ! 2104: if (dc->op2 == 15) /* ignore halt. */ ! 2105: goto done; ! 2106: ! 2107: switch (dc->op2 & 7) { ! 2108: case 2: ! 2109: /* rfe. */ ! 2110: cris_evaluate_flags(dc); ! 2111: gen_op_ccs_rshift(); ! 2112: break; ! 2113: case 5: ! 2114: /* rfn. */ ! 2115: BUG(); ! 2116: break; ! 2117: case 6: ! 2118: /* break. */ ! 2119: gen_op_movl_T0_im(dc->pc); ! 2120: gen_op_movl_pc_T0(); ! 2121: /* Breaks start at 16 in the exception vector. */ ! 2122: gen_op_break_im(dc->op1 + 16); ! 2123: break; ! 2124: default: ! 2125: printf ("op2=%x\n", dc->op2); ! 2126: BUG(); ! 2127: break; ! 2128: ! 2129: } ! 2130: done: ! 2131: return 2; ! 2132: } ! 2133: ! 2134: static unsigned int dec_null(DisasContext *dc) ! 2135: { ! 2136: printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n", ! 2137: dc->pc, dc->opcode, dc->op1, dc->op2); ! 2138: fflush(NULL); ! 2139: BUG(); ! 2140: return 2; ! 2141: } ! 2142: ! 2143: struct decoder_info { ! 2144: struct { ! 2145: uint32_t bits; ! 2146: uint32_t mask; ! 2147: }; ! 2148: unsigned int (*dec)(DisasContext *dc); ! 2149: } decinfo[] = { ! 2150: /* Order matters here. */ ! 2151: {DEC_MOVEQ, dec_moveq}, ! 2152: {DEC_BTSTQ, dec_btstq}, ! 2153: {DEC_CMPQ, dec_cmpq}, ! 2154: {DEC_ADDOQ, dec_addoq}, ! 2155: {DEC_ADDQ, dec_addq}, ! 2156: {DEC_SUBQ, dec_subq}, ! 2157: {DEC_ANDQ, dec_andq}, ! 2158: {DEC_ORQ, dec_orq}, ! 2159: {DEC_ASRQ, dec_asrq}, ! 2160: {DEC_LSLQ, dec_lslq}, ! 2161: {DEC_LSRQ, dec_lsrq}, ! 2162: {DEC_BCCQ, dec_bccq}, ! 2163: ! 2164: {DEC_BCC_IM, dec_bcc_im}, ! 2165: {DEC_JAS_IM, dec_jas_im}, ! 2166: {DEC_JAS_R, dec_jas_r}, ! 2167: {DEC_JASC_IM, dec_jasc_im}, ! 2168: {DEC_JASC_R, dec_jasc_r}, ! 2169: {DEC_BAS_IM, dec_bas_im}, ! 2170: {DEC_BASC_IM, dec_basc_im}, ! 2171: {DEC_JUMP_P, dec_jump_p}, ! 2172: {DEC_LAPC_IM, dec_lapc_im}, ! 2173: {DEC_LAPCQ, dec_lapcq}, ! 2174: ! 2175: {DEC_RFE_ETC, dec_rfe_etc}, ! 2176: {DEC_ADDC_MR, dec_addc_mr}, ! 2177: ! 2178: {DEC_MOVE_MP, dec_move_mp}, ! 2179: {DEC_MOVE_PM, dec_move_pm}, ! 2180: {DEC_MOVEM_MR, dec_movem_mr}, ! 2181: {DEC_MOVEM_RM, dec_movem_rm}, ! 2182: {DEC_MOVE_PR, dec_move_pr}, ! 2183: {DEC_SCC_R, dec_scc_r}, ! 2184: {DEC_SETF, dec_setclrf}, ! 2185: {DEC_CLEARF, dec_setclrf}, ! 2186: ! 2187: {DEC_MOVE_SR, dec_move_sr}, ! 2188: {DEC_MOVE_RP, dec_move_rp}, ! 2189: {DEC_SWAP_R, dec_swap_r}, ! 2190: {DEC_ABS_R, dec_abs_r}, ! 2191: {DEC_LZ_R, dec_lz_r}, ! 2192: {DEC_MOVE_RS, dec_move_rs}, ! 2193: {DEC_BTST_R, dec_btst_r}, ! 2194: {DEC_ADDC_R, dec_addc_r}, ! 2195: ! 2196: {DEC_DSTEP_R, dec_dstep_r}, ! 2197: {DEC_XOR_R, dec_xor_r}, ! 2198: {DEC_MCP_R, dec_mcp_r}, ! 2199: {DEC_CMP_R, dec_cmp_r}, ! 2200: ! 2201: {DEC_ADDI_R, dec_addi_r}, ! 2202: {DEC_ADDI_ACR, dec_addi_acr}, ! 2203: ! 2204: {DEC_ADD_R, dec_add_r}, ! 2205: {DEC_SUB_R, dec_sub_r}, ! 2206: ! 2207: {DEC_ADDU_R, dec_addu_r}, ! 2208: {DEC_ADDS_R, dec_adds_r}, ! 2209: {DEC_SUBU_R, dec_subu_r}, ! 2210: {DEC_SUBS_R, dec_subs_r}, ! 2211: {DEC_LSL_R, dec_lsl_r}, ! 2212: ! 2213: {DEC_AND_R, dec_and_r}, ! 2214: {DEC_OR_R, dec_or_r}, ! 2215: {DEC_BOUND_R, dec_bound_r}, ! 2216: {DEC_ASR_R, dec_asr_r}, ! 2217: {DEC_LSR_R, dec_lsr_r}, ! 2218: ! 2219: {DEC_MOVU_R, dec_movu_r}, ! 2220: {DEC_MOVS_R, dec_movs_r}, ! 2221: {DEC_NEG_R, dec_neg_r}, ! 2222: {DEC_MOVE_R, dec_move_r}, ! 2223: ! 2224: /* ftag_fidx_i_m. */ ! 2225: /* ftag_fidx_d_m. */ ! 2226: ! 2227: {DEC_MULS_R, dec_muls_r}, ! 2228: {DEC_MULU_R, dec_mulu_r}, ! 2229: ! 2230: {DEC_ADDU_M, dec_addu_m}, ! 2231: {DEC_ADDS_M, dec_adds_m}, ! 2232: {DEC_SUBU_M, dec_subu_m}, ! 2233: {DEC_SUBS_M, dec_subs_m}, ! 2234: ! 2235: {DEC_CMPU_M, dec_cmpu_m}, ! 2236: {DEC_CMPS_M, dec_cmps_m}, ! 2237: {DEC_MOVU_M, dec_movu_m}, ! 2238: {DEC_MOVS_M, dec_movs_m}, ! 2239: ! 2240: {DEC_CMP_M, dec_cmp_m}, ! 2241: {DEC_ADDO_M, dec_addo_m}, ! 2242: {DEC_BOUND_M, dec_bound_m}, ! 2243: {DEC_ADD_M, dec_add_m}, ! 2244: {DEC_SUB_M, dec_sub_m}, ! 2245: {DEC_AND_M, dec_and_m}, ! 2246: {DEC_OR_M, dec_or_m}, ! 2247: {DEC_MOVE_RM, dec_move_rm}, ! 2248: {DEC_TEST_M, dec_test_m}, ! 2249: {DEC_MOVE_MR, dec_move_mr}, ! 2250: ! 2251: {{0, 0}, dec_null} ! 2252: }; ! 2253: ! 2254: static inline unsigned int ! 2255: cris_decoder(DisasContext *dc) ! 2256: { ! 2257: unsigned int insn_len = 2; ! 2258: uint32_t tmp; ! 2259: int i; ! 2260: ! 2261: /* Load a halfword onto the instruction register. */ ! 2262: tmp = ldl_code(dc->pc); ! 2263: dc->ir = tmp & 0xffff; ! 2264: ! 2265: /* Now decode it. */ ! 2266: dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11); ! 2267: dc->op1 = EXTRACT_FIELD(dc->ir, 0, 3); ! 2268: dc->op2 = EXTRACT_FIELD(dc->ir, 12, 15); ! 2269: dc->zsize = EXTRACT_FIELD(dc->ir, 4, 4); ! 2270: dc->zzsize = EXTRACT_FIELD(dc->ir, 4, 5); ! 2271: dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10); ! 2272: ! 2273: /* Large switch for all insns. */ ! 2274: for (i = 0; i < sizeof decinfo / sizeof decinfo[0]; i++) { ! 2275: if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) ! 2276: { ! 2277: insn_len = decinfo[i].dec(dc); ! 2278: break; ! 2279: } ! 2280: } ! 2281: ! 2282: return insn_len; ! 2283: } ! 2284: ! 2285: static void check_breakpoint(CPUState *env, DisasContext *dc) ! 2286: { ! 2287: int j; ! 2288: if (env->nb_breakpoints > 0) { ! 2289: for(j = 0; j < env->nb_breakpoints; j++) { ! 2290: if (env->breakpoints[j] == dc->pc) { ! 2291: cris_evaluate_flags (dc); ! 2292: gen_op_movl_T0_im((long)dc->pc); ! 2293: gen_op_movl_pc_T0(); ! 2294: gen_op_debug(); ! 2295: dc->is_jmp = DISAS_UPDATE; ! 2296: } ! 2297: } ! 2298: } ! 2299: } ! 2300: ! 2301: ! 2302: /* generate intermediate code for basic block 'tb'. */ ! 2303: struct DisasContext ctx; ! 2304: static int ! 2305: gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, ! 2306: int search_pc) ! 2307: { ! 2308: uint16_t *gen_opc_end; ! 2309: uint32_t pc_start; ! 2310: unsigned int insn_len; ! 2311: int j, lj; ! 2312: struct DisasContext *dc = &ctx; ! 2313: uint32_t next_page_start; ! 2314: ! 2315: pc_start = tb->pc; ! 2316: dc->env = env; ! 2317: dc->tb = tb; ! 2318: ! 2319: gen_opc_ptr = gen_opc_buf; ! 2320: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; ! 2321: gen_opparam_ptr = gen_opparam_buf; ! 2322: ! 2323: dc->is_jmp = DISAS_NEXT; ! 2324: dc->pc = pc_start; ! 2325: dc->singlestep_enabled = env->singlestep_enabled; ! 2326: dc->flagx_live = 0; ! 2327: dc->flags_x = 0; ! 2328: next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; ! 2329: lj = -1; ! 2330: do ! 2331: { ! 2332: check_breakpoint(env, dc); ! 2333: if (dc->is_jmp == DISAS_JUMP) ! 2334: goto done; ! 2335: ! 2336: if (search_pc) { ! 2337: j = gen_opc_ptr - gen_opc_buf; ! 2338: if (lj < j) { ! 2339: lj++; ! 2340: while (lj < j) ! 2341: gen_opc_instr_start[lj++] = 0; ! 2342: } ! 2343: gen_opc_pc[lj] = dc->pc; ! 2344: gen_opc_instr_start[lj] = 1; ! 2345: } ! 2346: ! 2347: insn_len = cris_decoder(dc); ! 2348: STATS(gen_op_exec_insn()); ! 2349: dc->pc += insn_len; ! 2350: if (!dc->flagx_live ! 2351: || (dc->flagx_live && ! 2352: !(dc->cc_op == CC_OP_FLAGS && dc->flags_x))) { ! 2353: gen_movl_T0_preg[SR_CCS](); ! 2354: gen_op_andl_T0_im(~X_FLAG); ! 2355: gen_movl_preg_T0[SR_CCS](); ! 2356: dc->flagx_live = 1; ! 2357: dc->flags_x = 0; ! 2358: } ! 2359: ! 2360: /* Check for delayed branches here. If we do it before ! 2361: actually genereating any host code, the simulator will just ! 2362: loop doing nothing for on this program location. */ ! 2363: if (dc->delayed_branch) { ! 2364: dc->delayed_branch--; ! 2365: if (dc->delayed_branch == 0) ! 2366: { ! 2367: if (dc->bcc == CC_A) { ! 2368: gen_op_jmp (); ! 2369: dc->is_jmp = DISAS_UPDATE; ! 2370: } ! 2371: else { ! 2372: /* Conditional jmp. */ ! 2373: gen_op_cc_jmp (dc->delayed_pc, dc->pc); ! 2374: dc->is_jmp = DISAS_UPDATE; ! 2375: } ! 2376: } ! 2377: } ! 2378: ! 2379: if (env->singlestep_enabled) ! 2380: break; ! 2381: } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end ! 2382: && dc->pc < next_page_start); ! 2383: ! 2384: if (!dc->is_jmp) { ! 2385: gen_op_movl_T0_im((long)dc->pc); ! 2386: gen_op_movl_pc_T0(); ! 2387: } ! 2388: ! 2389: cris_evaluate_flags (dc); ! 2390: done: ! 2391: if (__builtin_expect(env->singlestep_enabled, 0)) { ! 2392: gen_op_debug(); ! 2393: } else { ! 2394: switch(dc->is_jmp) { ! 2395: case DISAS_NEXT: ! 2396: gen_goto_tb(dc, 1, dc->pc); ! 2397: break; ! 2398: default: ! 2399: case DISAS_JUMP: ! 2400: case DISAS_UPDATE: ! 2401: /* indicate that the hash table must be used ! 2402: to find the next TB */ ! 2403: /* T0 is used to index the jmp tables. */ ! 2404: gen_op_movl_T0_0(); ! 2405: gen_op_exit_tb(); ! 2406: break; ! 2407: case DISAS_TB_JUMP: ! 2408: /* nothing more to generate */ ! 2409: break; ! 2410: } ! 2411: } ! 2412: *gen_opc_ptr = INDEX_op_end; ! 2413: if (search_pc) { ! 2414: j = gen_opc_ptr - gen_opc_buf; ! 2415: lj++; ! 2416: while (lj <= j) ! 2417: gen_opc_instr_start[lj++] = 0; ! 2418: } else { ! 2419: tb->size = dc->pc - pc_start; ! 2420: } ! 2421: ! 2422: #ifdef DEBUG_DISAS ! 2423: if (loglevel & CPU_LOG_TB_IN_ASM) { ! 2424: fprintf(logfile, "--------------\n"); ! 2425: fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); ! 2426: target_disas(logfile, pc_start, dc->pc + 4 - pc_start, 0); ! 2427: fprintf(logfile, "\n"); ! 2428: if (loglevel & CPU_LOG_TB_OP) { ! 2429: fprintf(logfile, "OP:\n"); ! 2430: dump_ops(gen_opc_buf, gen_opparam_buf); ! 2431: fprintf(logfile, "\n"); ! 2432: } ! 2433: } ! 2434: #endif ! 2435: return 0; ! 2436: } ! 2437: ! 2438: int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb) ! 2439: { ! 2440: return gen_intermediate_code_internal(env, tb, 0); ! 2441: } ! 2442: ! 2443: int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) ! 2444: { ! 2445: return gen_intermediate_code_internal(env, tb, 1); ! 2446: } ! 2447: ! 2448: void cpu_dump_state (CPUState *env, FILE *f, ! 2449: int (*cpu_fprintf)(FILE *f, const char *fmt, ...), ! 2450: int flags) ! 2451: { ! 2452: int i; ! 2453: uint32_t srs; ! 2454: ! 2455: if (!env || !f) ! 2456: return; ! 2457: ! 2458: cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n" ! 2459: "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n" ! 2460: "debug=%x %x %x\n", ! 2461: env->pc, env->pregs[SR_CCS], env->btaken, env->btarget, ! 2462: env->cc_op, ! 2463: env->cc_src, env->cc_dest, env->cc_result, env->cc_mask, ! 2464: env->debug1, env->debug2, env->debug3); ! 2465: ! 2466: for (i = 0; i < 16; i++) { ! 2467: cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]); ! 2468: if ((i + 1) % 4 == 0) ! 2469: cpu_fprintf(f, "\n"); ! 2470: } ! 2471: cpu_fprintf(f, "\nspecial regs:\n"); ! 2472: for (i = 0; i < 16; i++) { ! 2473: cpu_fprintf(f, "p%2.2d=%8.8x ", i, env->pregs[i]); ! 2474: if ((i + 1) % 4 == 0) ! 2475: cpu_fprintf(f, "\n"); ! 2476: } ! 2477: srs = env->pregs[SR_SRS]; ! 2478: cpu_fprintf(f, "\nsupport function regs bank %d:\n", srs); ! 2479: if (srs < 256) { ! 2480: for (i = 0; i < 16; i++) { ! 2481: cpu_fprintf(f, "s%2.2d=%8.8x ", ! 2482: i, env->sregs[srs][i]); ! 2483: if ((i + 1) % 4 == 0) ! 2484: cpu_fprintf(f, "\n"); ! 2485: } ! 2486: } ! 2487: cpu_fprintf(f, "\n\n"); ! 2488: ! 2489: } ! 2490: ! 2491: CPUCRISState *cpu_cris_init (const char *cpu_model) ! 2492: { ! 2493: CPUCRISState *env; ! 2494: ! 2495: env = qemu_mallocz(sizeof(CPUCRISState)); ! 2496: if (!env) ! 2497: return NULL; ! 2498: cpu_exec_init(env); ! 2499: cpu_reset(env); ! 2500: return env; ! 2501: } ! 2502: ! 2503: void cpu_reset (CPUCRISState *env) ! 2504: { ! 2505: memset(env, 0, offsetof(CPUCRISState, breakpoints)); ! 2506: tlb_flush(env, 1); ! 2507: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.