translate.c revision 413f05aaf54fa08c0ae7e997327a4f4a473c0a8d
1/* 2 * ARM translation 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * Copyright (c) 2005 CodeSourcery, LLC 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#include <stdarg.h> 22#include <stdlib.h> 23#include <stdio.h> 24#include <string.h> 25#include <inttypes.h> 26 27#include "cpu.h" 28#include "exec-all.h" 29#include "disas.h" 30 31#define ENABLE_ARCH_5J 0 32#define ENABLE_ARCH_6 1 33#define ENABLE_ARCH_6T2 1 34 35#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op; 36 37/* internal defines */ 38typedef struct DisasContext { 39 target_ulong pc; 40 int is_jmp; 41 /* Nonzero if this instruction has been conditionally skipped. */ 42 int condjmp; 43 /* The label that will be jumped to when the instruction is skipped. */ 44 int condlabel; 45 struct TranslationBlock *tb; 46 int singlestep_enabled; 47 int thumb; 48#if !defined(CONFIG_USER_ONLY) 49 int user; 50#endif 51} DisasContext; 52 53#if defined(CONFIG_USER_ONLY) 54#define IS_USER(s) 1 55#else 56#define IS_USER(s) (s->user) 57#endif 58 59#define DISAS_JUMP_NEXT 4 60 61#ifdef USE_DIRECT_JUMP 62#define TBPARAM(x) 63#else 64#define TBPARAM(x) (long)(x) 65#endif 66 67/* XXX: move that elsewhere */ 68static uint16_t *gen_opc_ptr; 69static uint32_t *gen_opparam_ptr; 70extern FILE *logfile; 71extern int loglevel; 72 73enum { 74#define DEF(s, n, copy_size) INDEX_op_ ## s, 75#include "opc.h" 76#undef DEF 77 NB_OPS, 78}; 79 80#include "gen-op.h" 81 82static GenOpFunc1 *gen_test_cc[14] = { 83 gen_op_test_eq, 84 gen_op_test_ne, 85 gen_op_test_cs, 86 gen_op_test_cc, 87 gen_op_test_mi, 88 gen_op_test_pl, 89 gen_op_test_vs, 90 gen_op_test_vc, 91 gen_op_test_hi, 92 gen_op_test_ls, 93 gen_op_test_ge, 94 gen_op_test_lt, 95 gen_op_test_gt, 96 gen_op_test_le, 97}; 98 99const uint8_t table_logic_cc[16] = { 100 1, /* and */ 101 1, /* xor */ 102 0, /* sub */ 103 0, /* rsb */ 104 0, /* add */ 105 0, /* adc */ 106 0, /* sbc */ 107 0, /* rsc */ 108 1, /* andl */ 109 1, /* xorl */ 110 0, /* cmp */ 111 0, /* cmn */ 112 1, /* orr */ 113 1, /* mov */ 114 1, /* bic */ 115 1, /* mvn */ 116}; 117 118static GenOpFunc1 *gen_shift_T1_im[4] = { 119 gen_op_shll_T1_im, 120 gen_op_shrl_T1_im, 121 gen_op_sarl_T1_im, 122 gen_op_rorl_T1_im, 123}; 124 125static GenOpFunc *gen_shift_T1_0[4] = { 126 NULL, 127 gen_op_shrl_T1_0, 128 gen_op_sarl_T1_0, 129 gen_op_rrxl_T1, 130}; 131 132static GenOpFunc1 *gen_shift_T2_im[4] = { 133 gen_op_shll_T2_im, 134 gen_op_shrl_T2_im, 135 gen_op_sarl_T2_im, 136 gen_op_rorl_T2_im, 137}; 138 139static GenOpFunc *gen_shift_T2_0[4] = { 140 NULL, 141 gen_op_shrl_T2_0, 142 gen_op_sarl_T2_0, 143 gen_op_rrxl_T2, 144}; 145 146static GenOpFunc1 *gen_shift_T1_im_cc[4] = { 147 gen_op_shll_T1_im_cc, 148 gen_op_shrl_T1_im_cc, 149 gen_op_sarl_T1_im_cc, 150 gen_op_rorl_T1_im_cc, 151}; 152 153static GenOpFunc *gen_shift_T1_0_cc[4] = { 154 NULL, 155 gen_op_shrl_T1_0_cc, 156 gen_op_sarl_T1_0_cc, 157 gen_op_rrxl_T1_cc, 158}; 159 160static GenOpFunc *gen_shift_T1_T0[4] = { 161 gen_op_shll_T1_T0, 162 gen_op_shrl_T1_T0, 163 gen_op_sarl_T1_T0, 164 gen_op_rorl_T1_T0, 165}; 166 167static GenOpFunc *gen_shift_T1_T0_cc[4] = { 168 gen_op_shll_T1_T0_cc, 169 gen_op_shrl_T1_T0_cc, 170 gen_op_sarl_T1_T0_cc, 171 gen_op_rorl_T1_T0_cc, 172}; 173 174static GenOpFunc *gen_op_movl_TN_reg[3][16] = { 175 { 176 gen_op_movl_T0_r0, 177 gen_op_movl_T0_r1, 178 gen_op_movl_T0_r2, 179 gen_op_movl_T0_r3, 180 gen_op_movl_T0_r4, 181 gen_op_movl_T0_r5, 182 gen_op_movl_T0_r6, 183 gen_op_movl_T0_r7, 184 gen_op_movl_T0_r8, 185 gen_op_movl_T0_r9, 186 gen_op_movl_T0_r10, 187 gen_op_movl_T0_r11, 188 gen_op_movl_T0_r12, 189 gen_op_movl_T0_r13, 190 gen_op_movl_T0_r14, 191 gen_op_movl_T0_r15, 192 }, 193 { 194 gen_op_movl_T1_r0, 195 gen_op_movl_T1_r1, 196 gen_op_movl_T1_r2, 197 gen_op_movl_T1_r3, 198 gen_op_movl_T1_r4, 199 gen_op_movl_T1_r5, 200 gen_op_movl_T1_r6, 201 gen_op_movl_T1_r7, 202 gen_op_movl_T1_r8, 203 gen_op_movl_T1_r9, 204 gen_op_movl_T1_r10, 205 gen_op_movl_T1_r11, 206 gen_op_movl_T1_r12, 207 gen_op_movl_T1_r13, 208 gen_op_movl_T1_r14, 209 gen_op_movl_T1_r15, 210 }, 211 { 212 gen_op_movl_T2_r0, 213 gen_op_movl_T2_r1, 214 gen_op_movl_T2_r2, 215 gen_op_movl_T2_r3, 216 gen_op_movl_T2_r4, 217 gen_op_movl_T2_r5, 218 gen_op_movl_T2_r6, 219 gen_op_movl_T2_r7, 220 gen_op_movl_T2_r8, 221 gen_op_movl_T2_r9, 222 gen_op_movl_T2_r10, 223 gen_op_movl_T2_r11, 224 gen_op_movl_T2_r12, 225 gen_op_movl_T2_r13, 226 gen_op_movl_T2_r14, 227 gen_op_movl_T2_r15, 228 }, 229}; 230 231static GenOpFunc *gen_op_movl_reg_TN[2][16] = { 232 { 233 gen_op_movl_r0_T0, 234 gen_op_movl_r1_T0, 235 gen_op_movl_r2_T0, 236 gen_op_movl_r3_T0, 237 gen_op_movl_r4_T0, 238 gen_op_movl_r5_T0, 239 gen_op_movl_r6_T0, 240 gen_op_movl_r7_T0, 241 gen_op_movl_r8_T0, 242 gen_op_movl_r9_T0, 243 gen_op_movl_r10_T0, 244 gen_op_movl_r11_T0, 245 gen_op_movl_r12_T0, 246 gen_op_movl_r13_T0, 247 gen_op_movl_r14_T0, 248 gen_op_movl_r15_T0, 249 }, 250 { 251 gen_op_movl_r0_T1, 252 gen_op_movl_r1_T1, 253 gen_op_movl_r2_T1, 254 gen_op_movl_r3_T1, 255 gen_op_movl_r4_T1, 256 gen_op_movl_r5_T1, 257 gen_op_movl_r6_T1, 258 gen_op_movl_r7_T1, 259 gen_op_movl_r8_T1, 260 gen_op_movl_r9_T1, 261 gen_op_movl_r10_T1, 262 gen_op_movl_r11_T1, 263 gen_op_movl_r12_T1, 264 gen_op_movl_r13_T1, 265 gen_op_movl_r14_T1, 266 gen_op_movl_r15_T1, 267 }, 268}; 269 270static GenOpFunc1 *gen_op_movl_TN_im[3] = { 271 gen_op_movl_T0_im, 272 gen_op_movl_T1_im, 273 gen_op_movl_T2_im, 274}; 275 276static GenOpFunc1 *gen_shift_T0_im_thumb[3] = { 277 gen_op_shll_T0_im_thumb, 278 gen_op_shrl_T0_im_thumb, 279 gen_op_sarl_T0_im_thumb, 280}; 281 282static inline void gen_bx(DisasContext *s) 283{ 284 s->is_jmp = DISAS_UPDATE; 285 gen_op_bx_T0(); 286} 287 288 289#if defined(CONFIG_USER_ONLY) 290#define gen_ldst(name, s) gen_op_##name##_raw() 291#else 292#define gen_ldst(name, s) do { \ 293 if (IS_USER(s)) \ 294 gen_op_##name##_user(); \ 295 else \ 296 gen_op_##name##_kernel(); \ 297 } while (0) 298#endif 299 300static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t) 301{ 302 int val; 303 304 if (reg == 15) { 305 /* normaly, since we updated PC, we need only to add one insn */ 306 if (s->thumb) 307 val = (long)s->pc + 2; 308 else 309 val = (long)s->pc + 4; 310 gen_op_movl_TN_im[t](val); 311 } else { 312 gen_op_movl_TN_reg[t][reg](); 313 } 314} 315 316static inline void gen_movl_T0_reg(DisasContext *s, int reg) 317{ 318 gen_movl_TN_reg(s, reg, 0); 319} 320 321static inline void gen_movl_T1_reg(DisasContext *s, int reg) 322{ 323 gen_movl_TN_reg(s, reg, 1); 324} 325 326static inline void gen_movl_T2_reg(DisasContext *s, int reg) 327{ 328 gen_movl_TN_reg(s, reg, 2); 329} 330 331static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t) 332{ 333 gen_op_movl_reg_TN[t][reg](); 334 if (reg == 15) { 335 s->is_jmp = DISAS_JUMP; 336 } 337} 338 339static inline void gen_movl_reg_T0(DisasContext *s, int reg) 340{ 341 gen_movl_reg_TN(s, reg, 0); 342} 343 344static inline void gen_movl_reg_T1(DisasContext *s, int reg) 345{ 346 gen_movl_reg_TN(s, reg, 1); 347} 348 349/* Force a TB lookup after an instruction that changes the CPU state. */ 350static inline void gen_lookup_tb(DisasContext *s) 351{ 352 gen_op_movl_T0_im(s->pc); 353 gen_movl_reg_T0(s, 15); 354 s->is_jmp = DISAS_UPDATE; 355} 356 357static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) 358{ 359 int val, rm, shift, shiftop; 360 361 if (!(insn & (1 << 25))) { 362 /* immediate */ 363 val = insn & 0xfff; 364 if (!(insn & (1 << 23))) 365 val = -val; 366 if (val != 0) 367 gen_op_addl_T1_im(val); 368 } else { 369 /* shift/register */ 370 rm = (insn) & 0xf; 371 shift = (insn >> 7) & 0x1f; 372 gen_movl_T2_reg(s, rm); 373 shiftop = (insn >> 5) & 3; 374 if (shift != 0) { 375 gen_shift_T2_im[shiftop](shift); 376 } else if (shiftop != 0) { 377 gen_shift_T2_0[shiftop](); 378 } 379 if (!(insn & (1 << 23))) 380 gen_op_subl_T1_T2(); 381 else 382 gen_op_addl_T1_T2(); 383 } 384} 385 386static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, 387 int extra) 388{ 389 int val, rm; 390 391 if (insn & (1 << 22)) { 392 /* immediate */ 393 val = (insn & 0xf) | ((insn >> 4) & 0xf0); 394 val += extra; 395 if (!(insn & (1 << 23))) 396 val = -val; 397 if (val != 0) 398 gen_op_addl_T1_im(val); 399 } else { 400 /* register */ 401 if (extra) 402 gen_op_addl_T1_im(extra); 403 rm = (insn) & 0xf; 404 gen_movl_T2_reg(s, rm); 405 if (!(insn & (1 << 23))) 406 gen_op_subl_T1_T2(); 407 else 408 gen_op_addl_T1_T2(); 409 } 410} 411 412#define VFP_OP(name) \ 413static inline void gen_vfp_##name(int dp) \ 414{ \ 415 if (dp) \ 416 gen_op_vfp_##name##d(); \ 417 else \ 418 gen_op_vfp_##name##s(); \ 419} 420 421VFP_OP(add) 422VFP_OP(sub) 423VFP_OP(mul) 424VFP_OP(div) 425VFP_OP(neg) 426VFP_OP(abs) 427VFP_OP(sqrt) 428VFP_OP(cmp) 429VFP_OP(cmpe) 430VFP_OP(F1_ld0) 431VFP_OP(uito) 432VFP_OP(sito) 433VFP_OP(toui) 434VFP_OP(touiz) 435VFP_OP(tosi) 436VFP_OP(tosiz) 437 438#undef VFP_OP 439 440static inline void gen_vfp_ld(DisasContext *s, int dp) 441{ 442 if (dp) 443 gen_ldst(vfp_ldd, s); 444 else 445 gen_ldst(vfp_lds, s); 446} 447 448static inline void gen_vfp_st(DisasContext *s, int dp) 449{ 450 if (dp) 451 gen_ldst(vfp_std, s); 452 else 453 gen_ldst(vfp_sts, s); 454} 455 456static inline long 457vfp_reg_offset (int dp, int reg) 458{ 459 if (dp) 460 return offsetof(CPUARMState, vfp.regs[reg]); 461 else if (reg & 1) { 462 return offsetof(CPUARMState, vfp.regs[reg >> 1]) 463 + offsetof(CPU_DoubleU, l.upper); 464 } else { 465 return offsetof(CPUARMState, vfp.regs[reg >> 1]) 466 + offsetof(CPU_DoubleU, l.lower); 467 } 468} 469static inline void gen_mov_F0_vreg(int dp, int reg) 470{ 471 if (dp) 472 gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg)); 473 else 474 gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg)); 475} 476 477static inline void gen_mov_F1_vreg(int dp, int reg) 478{ 479 if (dp) 480 gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg)); 481 else 482 gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg)); 483} 484 485static inline void gen_mov_vreg_F0(int dp, int reg) 486{ 487 if (dp) 488 gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg)); 489 else 490 gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg)); 491} 492 493/* Disassemble system coprocessor (cp15) instruction. Return nonzero if 494 instruction is not defined. */ 495static int disas_cp15_insn(DisasContext *s, uint32_t insn) 496{ 497 uint32_t rd; 498 499 /* ??? Some cp15 registers are accessible from userspace. */ 500 if (IS_USER(s)) { 501 return 1; 502 } 503 if ((insn & 0x0fff0fff) == 0x0e070f90 504 || (insn & 0x0fff0fff) == 0x0e070f58) { 505 /* Wait for interrupt. */ 506 gen_op_movl_T0_im((long)s->pc); 507 gen_op_movl_reg_TN[0][15](); 508 gen_op_wfi(); 509 s->is_jmp = DISAS_JUMP; 510 return 0; 511 } 512 rd = (insn >> 12) & 0xf; 513 if (insn & (1 << 20)) { 514 gen_op_movl_T0_cp15(insn); 515 /* If the destination register is r15 then sets condition codes. */ 516 if (rd != 15) 517 gen_movl_reg_T0(s, rd); 518 } else { 519 gen_movl_T0_reg(s, rd); 520 gen_op_movl_cp15_T0(insn); 521 } 522 gen_lookup_tb(s); 523 return 0; 524} 525 526/* Disassemble a VFP instruction. Returns nonzero if an error occured 527 (ie. an undefined instruction). */ 528static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) 529{ 530 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask; 531 int dp, veclen; 532 533 if (!arm_feature(env, ARM_FEATURE_VFP)) 534 return 1; 535 536 if ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) == 0) { 537 /* VFP disabled. Only allow fmxr/fmrx to/from fpexc and fpsid. */ 538 if ((insn & 0x0fe00fff) != 0x0ee00a10) 539 return 1; 540 rn = (insn >> 16) & 0xf; 541 if (rn != 0 && rn != 8) 542 return 1; 543 } 544 dp = ((insn & 0xf00) == 0xb00); 545 switch ((insn >> 24) & 0xf) { 546 case 0xe: 547 if (insn & (1 << 4)) { 548 /* single register transfer */ 549 if ((insn & 0x6f) != 0x00) 550 return 1; 551 rd = (insn >> 12) & 0xf; 552 if (dp) { 553 if (insn & 0x80) 554 return 1; 555 rn = (insn >> 16) & 0xf; 556 /* Get the existing value even for arm->vfp moves because 557 we only set half the register. */ 558 gen_mov_F0_vreg(1, rn); 559 gen_op_vfp_mrrd(); 560 if (insn & (1 << 20)) { 561 /* vfp->arm */ 562 if (insn & (1 << 21)) 563 gen_movl_reg_T1(s, rd); 564 else 565 gen_movl_reg_T0(s, rd); 566 } else { 567 /* arm->vfp */ 568 if (insn & (1 << 21)) 569 gen_movl_T1_reg(s, rd); 570 else 571 gen_movl_T0_reg(s, rd); 572 gen_op_vfp_mdrr(); 573 gen_mov_vreg_F0(dp, rn); 574 } 575 } else { 576 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1); 577 if (insn & (1 << 20)) { 578 /* vfp->arm */ 579 if (insn & (1 << 21)) { 580 /* system register */ 581 rn >>= 1; 582 switch (rn) { 583 case ARM_VFP_FPSID: 584 case ARM_VFP_FPEXC: 585 case ARM_VFP_FPINST: 586 case ARM_VFP_FPINST2: 587 gen_op_vfp_movl_T0_xreg(rn); 588 break; 589 case ARM_VFP_FPSCR: 590 if (rd == 15) 591 gen_op_vfp_movl_T0_fpscr_flags(); 592 else 593 gen_op_vfp_movl_T0_fpscr(); 594 break; 595 default: 596 return 1; 597 } 598 } else { 599 gen_mov_F0_vreg(0, rn); 600 gen_op_vfp_mrs(); 601 } 602 if (rd == 15) { 603 /* Set the 4 flag bits in the CPSR. */ 604 gen_op_movl_cpsr_T0(0xf0000000); 605 } else 606 gen_movl_reg_T0(s, rd); 607 } else { 608 /* arm->vfp */ 609 gen_movl_T0_reg(s, rd); 610 if (insn & (1 << 21)) { 611 rn >>= 1; 612 /* system register */ 613 switch (rn) { 614 case ARM_VFP_FPSID: 615 /* Writes are ignored. */ 616 break; 617 case ARM_VFP_FPSCR: 618 gen_op_vfp_movl_fpscr_T0(); 619 gen_lookup_tb(s); 620 break; 621 case ARM_VFP_FPEXC: 622 gen_op_vfp_movl_xreg_T0(rn); 623 gen_lookup_tb(s); 624 break; 625 case ARM_VFP_FPINST: 626 case ARM_VFP_FPINST2: 627 gen_op_vfp_movl_xreg_T0(rn); 628 break; 629 default: 630 return 1; 631 } 632 } else { 633 gen_op_vfp_msr(); 634 gen_mov_vreg_F0(0, rn); 635 } 636 } 637 } 638 } else { 639 /* data processing */ 640 /* The opcode is in bits 23, 21, 20 and 6. */ 641 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1); 642 if (dp) { 643 if (op == 15) { 644 /* rn is opcode */ 645 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1); 646 } else { 647 /* rn is register number */ 648 if (insn & (1 << 7)) 649 return 1; 650 rn = (insn >> 16) & 0xf; 651 } 652 653 if (op == 15 && (rn == 15 || rn > 17)) { 654 /* Integer or single precision destination. */ 655 rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1); 656 } else { 657 if (insn & (1 << 22)) 658 return 1; 659 rd = (insn >> 12) & 0xf; 660 } 661 662 if (op == 15 && (rn == 16 || rn == 17)) { 663 /* Integer source. */ 664 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1); 665 } else { 666 if (insn & (1 << 5)) 667 return 1; 668 rm = insn & 0xf; 669 } 670 } else { 671 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1); 672 if (op == 15 && rn == 15) { 673 /* Double precision destination. */ 674 if (insn & (1 << 22)) 675 return 1; 676 rd = (insn >> 12) & 0xf; 677 } else 678 rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1); 679 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1); 680 } 681 682 veclen = env->vfp.vec_len; 683 if (op == 15 && rn > 3) 684 veclen = 0; 685 686 /* Shut up compiler warnings. */ 687 delta_m = 0; 688 delta_d = 0; 689 bank_mask = 0; 690 691 if (veclen > 0) { 692 if (dp) 693 bank_mask = 0xc; 694 else 695 bank_mask = 0x18; 696 697 /* Figure out what type of vector operation this is. */ 698 if ((rd & bank_mask) == 0) { 699 /* scalar */ 700 veclen = 0; 701 } else { 702 if (dp) 703 delta_d = (env->vfp.vec_stride >> 1) + 1; 704 else 705 delta_d = env->vfp.vec_stride + 1; 706 707 if ((rm & bank_mask) == 0) { 708 /* mixed scalar/vector */ 709 delta_m = 0; 710 } else { 711 /* vector */ 712 delta_m = delta_d; 713 } 714 } 715 } 716 717 /* Load the initial operands. */ 718 if (op == 15) { 719 switch (rn) { 720 case 16: 721 case 17: 722 /* Integer source */ 723 gen_mov_F0_vreg(0, rm); 724 break; 725 case 8: 726 case 9: 727 /* Compare */ 728 gen_mov_F0_vreg(dp, rd); 729 gen_mov_F1_vreg(dp, rm); 730 break; 731 case 10: 732 case 11: 733 /* Compare with zero */ 734 gen_mov_F0_vreg(dp, rd); 735 gen_vfp_F1_ld0(dp); 736 break; 737 default: 738 /* One source operand. */ 739 gen_mov_F0_vreg(dp, rm); 740 } 741 } else { 742 /* Two source operands. */ 743 gen_mov_F0_vreg(dp, rn); 744 gen_mov_F1_vreg(dp, rm); 745 } 746 747 for (;;) { 748 /* Perform the calculation. */ 749 switch (op) { 750 case 0: /* mac: fd + (fn * fm) */ 751 gen_vfp_mul(dp); 752 gen_mov_F1_vreg(dp, rd); 753 gen_vfp_add(dp); 754 break; 755 case 1: /* nmac: fd - (fn * fm) */ 756 gen_vfp_mul(dp); 757 gen_vfp_neg(dp); 758 gen_mov_F1_vreg(dp, rd); 759 gen_vfp_add(dp); 760 break; 761 case 2: /* msc: -fd + (fn * fm) */ 762 gen_vfp_mul(dp); 763 gen_mov_F1_vreg(dp, rd); 764 gen_vfp_sub(dp); 765 break; 766 case 3: /* nmsc: -fd - (fn * fm) */ 767 gen_vfp_mul(dp); 768 gen_mov_F1_vreg(dp, rd); 769 gen_vfp_add(dp); 770 gen_vfp_neg(dp); 771 break; 772 case 4: /* mul: fn * fm */ 773 gen_vfp_mul(dp); 774 break; 775 case 5: /* nmul: -(fn * fm) */ 776 gen_vfp_mul(dp); 777 gen_vfp_neg(dp); 778 break; 779 case 6: /* add: fn + fm */ 780 gen_vfp_add(dp); 781 break; 782 case 7: /* sub: fn - fm */ 783 gen_vfp_sub(dp); 784 break; 785 case 8: /* div: fn / fm */ 786 gen_vfp_div(dp); 787 break; 788 case 15: /* extension space */ 789 switch (rn) { 790 case 0: /* cpy */ 791 /* no-op */ 792 break; 793 case 1: /* abs */ 794 gen_vfp_abs(dp); 795 break; 796 case 2: /* neg */ 797 gen_vfp_neg(dp); 798 break; 799 case 3: /* sqrt */ 800 gen_vfp_sqrt(dp); 801 break; 802 case 8: /* cmp */ 803 gen_vfp_cmp(dp); 804 break; 805 case 9: /* cmpe */ 806 gen_vfp_cmpe(dp); 807 break; 808 case 10: /* cmpz */ 809 gen_vfp_cmp(dp); 810 break; 811 case 11: /* cmpez */ 812 gen_vfp_F1_ld0(dp); 813 gen_vfp_cmpe(dp); 814 break; 815 case 15: /* single<->double conversion */ 816 if (dp) 817 gen_op_vfp_fcvtsd(); 818 else 819 gen_op_vfp_fcvtds(); 820 break; 821 case 16: /* fuito */ 822 gen_vfp_uito(dp); 823 break; 824 case 17: /* fsito */ 825 gen_vfp_sito(dp); 826 break; 827 case 24: /* ftoui */ 828 gen_vfp_toui(dp); 829 break; 830 case 25: /* ftouiz */ 831 gen_vfp_touiz(dp); 832 break; 833 case 26: /* ftosi */ 834 gen_vfp_tosi(dp); 835 break; 836 case 27: /* ftosiz */ 837 gen_vfp_tosiz(dp); 838 break; 839 default: /* undefined */ 840 printf ("rn:%d\n", rn); 841 return 1; 842 } 843 break; 844 default: /* undefined */ 845 printf ("op:%d\n", op); 846 return 1; 847 } 848 849 /* Write back the result. */ 850 if (op == 15 && (rn >= 8 && rn <= 11)) 851 ; /* Comparison, do nothing. */ 852 else if (op == 15 && rn > 17) 853 /* Integer result. */ 854 gen_mov_vreg_F0(0, rd); 855 else if (op == 15 && rn == 15) 856 /* conversion */ 857 gen_mov_vreg_F0(!dp, rd); 858 else 859 gen_mov_vreg_F0(dp, rd); 860 861 /* break out of the loop if we have finished */ 862 if (veclen == 0) 863 break; 864 865 if (op == 15 && delta_m == 0) { 866 /* single source one-many */ 867 while (veclen--) { 868 rd = ((rd + delta_d) & (bank_mask - 1)) 869 | (rd & bank_mask); 870 gen_mov_vreg_F0(dp, rd); 871 } 872 break; 873 } 874 /* Setup the next operands. */ 875 veclen--; 876 rd = ((rd + delta_d) & (bank_mask - 1)) 877 | (rd & bank_mask); 878 879 if (op == 15) { 880 /* One source operand. */ 881 rm = ((rm + delta_m) & (bank_mask - 1)) 882 | (rm & bank_mask); 883 gen_mov_F0_vreg(dp, rm); 884 } else { 885 /* Two source operands. */ 886 rn = ((rn + delta_d) & (bank_mask - 1)) 887 | (rn & bank_mask); 888 gen_mov_F0_vreg(dp, rn); 889 if (delta_m) { 890 rm = ((rm + delta_m) & (bank_mask - 1)) 891 | (rm & bank_mask); 892 gen_mov_F1_vreg(dp, rm); 893 } 894 } 895 } 896 } 897 break; 898 case 0xc: 899 case 0xd: 900 if (dp && (insn & (1 << 22))) { 901 /* two-register transfer */ 902 rn = (insn >> 16) & 0xf; 903 rd = (insn >> 12) & 0xf; 904 if (dp) { 905 if (insn & (1 << 5)) 906 return 1; 907 rm = insn & 0xf; 908 } else 909 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1); 910 911 if (insn & (1 << 20)) { 912 /* vfp->arm */ 913 if (dp) { 914 gen_mov_F0_vreg(1, rm); 915 gen_op_vfp_mrrd(); 916 gen_movl_reg_T0(s, rd); 917 gen_movl_reg_T1(s, rn); 918 } else { 919 gen_mov_F0_vreg(0, rm); 920 gen_op_vfp_mrs(); 921 gen_movl_reg_T0(s, rn); 922 gen_mov_F0_vreg(0, rm + 1); 923 gen_op_vfp_mrs(); 924 gen_movl_reg_T0(s, rd); 925 } 926 } else { 927 /* arm->vfp */ 928 if (dp) { 929 gen_movl_T0_reg(s, rd); 930 gen_movl_T1_reg(s, rn); 931 gen_op_vfp_mdrr(); 932 gen_mov_vreg_F0(1, rm); 933 } else { 934 gen_movl_T0_reg(s, rn); 935 gen_op_vfp_msr(); 936 gen_mov_vreg_F0(0, rm); 937 gen_movl_T0_reg(s, rd); 938 gen_op_vfp_msr(); 939 gen_mov_vreg_F0(0, rm + 1); 940 } 941 } 942 } else { 943 /* Load/store */ 944 rn = (insn >> 16) & 0xf; 945 if (dp) 946 rd = (insn >> 12) & 0xf; 947 else 948 rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1); 949 gen_movl_T1_reg(s, rn); 950 if ((insn & 0x01200000) == 0x01000000) { 951 /* Single load/store */ 952 offset = (insn & 0xff) << 2; 953 if ((insn & (1 << 23)) == 0) 954 offset = -offset; 955 gen_op_addl_T1_im(offset); 956 if (insn & (1 << 20)) { 957 gen_vfp_ld(s, dp); 958 gen_mov_vreg_F0(dp, rd); 959 } else { 960 gen_mov_F0_vreg(dp, rd); 961 gen_vfp_st(s, dp); 962 } 963 } else { 964 /* load/store multiple */ 965 if (dp) 966 n = (insn >> 1) & 0x7f; 967 else 968 n = insn & 0xff; 969 970 if (insn & (1 << 24)) /* pre-decrement */ 971 gen_op_addl_T1_im(-((insn & 0xff) << 2)); 972 973 if (dp) 974 offset = 8; 975 else 976 offset = 4; 977 for (i = 0; i < n; i++) { 978 if (insn & (1 << 20)) { 979 /* load */ 980 gen_vfp_ld(s, dp); 981 gen_mov_vreg_F0(dp, rd + i); 982 } else { 983 /* store */ 984 gen_mov_F0_vreg(dp, rd + i); 985 gen_vfp_st(s, dp); 986 } 987 gen_op_addl_T1_im(offset); 988 } 989 if (insn & (1 << 21)) { 990 /* writeback */ 991 if (insn & (1 << 24)) 992 offset = -offset * n; 993 else if (dp && (insn & 1)) 994 offset = 4; 995 else 996 offset = 0; 997 998 if (offset != 0) 999 gen_op_addl_T1_im(offset); 1000 gen_movl_reg_T1(s, rn); 1001 } 1002 } 1003 } 1004 break; 1005 default: 1006 /* Should never happen. */ 1007 return 1; 1008 } 1009 return 0; 1010} 1011 1012static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) 1013{ 1014 TranslationBlock *tb; 1015 1016 tb = s->tb; 1017 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { 1018 if (n == 0) 1019 gen_op_goto_tb0(TBPARAM(tb)); 1020 else 1021 gen_op_goto_tb1(TBPARAM(tb)); 1022 gen_op_movl_T0_im(dest); 1023 gen_op_movl_r15_T0(); 1024 gen_op_movl_T0_im((long)tb + n); 1025 gen_op_exit_tb(); 1026 } else { 1027 gen_op_movl_T0_im(dest); 1028 gen_op_movl_r15_T0(); 1029 gen_op_movl_T0_0(); 1030 gen_op_exit_tb(); 1031 } 1032} 1033 1034static inline void gen_jmp (DisasContext *s, uint32_t dest) 1035{ 1036 if (__builtin_expect(s->singlestep_enabled, 0)) { 1037 /* An indirect jump so that we still trigger the debug exception. */ 1038 if (s->thumb) 1039 dest |= 1; 1040 gen_op_movl_T0_im(dest); 1041 gen_bx(s); 1042 } else { 1043 gen_goto_tb(s, 0, dest); 1044 s->is_jmp = DISAS_TB_JUMP; 1045 } 1046} 1047 1048static inline void gen_mulxy(int x, int y) 1049{ 1050 if (x) 1051 gen_op_sarl_T0_im(16); 1052 else 1053 gen_op_sxth_T0(); 1054 if (y) 1055 gen_op_sarl_T1_im(16); 1056 else 1057 gen_op_sxth_T1(); 1058 gen_op_mul_T0_T1(); 1059} 1060 1061/* Return the mask of PSR bits set by a MSR instruction. */ 1062static uint32_t msr_mask(DisasContext *s, int flags, int spsr) { 1063 uint32_t mask; 1064 1065 mask = 0; 1066 if (flags & (1 << 0)) 1067 mask |= 0xff; 1068 if (flags & (1 << 1)) 1069 mask |= 0xff00; 1070 if (flags & (1 << 2)) 1071 mask |= 0xff0000; 1072 if (flags & (1 << 3)) 1073 mask |= 0xff000000; 1074 /* Mask out undefined bits. */ 1075 mask &= 0xf90f03ff; 1076 /* Mask out state bits. */ 1077 if (!spsr) 1078 mask &= ~0x01000020; 1079 /* Mask out privileged bits. */ 1080 if (IS_USER(s)) 1081 mask &= 0xf80f0200; 1082 return mask; 1083} 1084 1085/* Returns nonzero if access to the PSR is not permitted. */ 1086static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr) 1087{ 1088 if (spsr) { 1089 /* ??? This is also undefined in system mode. */ 1090 if (IS_USER(s)) 1091 return 1; 1092 gen_op_movl_spsr_T0(mask); 1093 } else { 1094 gen_op_movl_cpsr_T0(mask); 1095 } 1096 gen_lookup_tb(s); 1097 return 0; 1098} 1099 1100static void gen_exception_return(DisasContext *s) 1101{ 1102 gen_op_movl_reg_TN[0][15](); 1103 gen_op_movl_T0_spsr(); 1104 gen_op_movl_cpsr_T0(0xffffffff); 1105 s->is_jmp = DISAS_UPDATE; 1106} 1107 1108static void disas_arm_insn(CPUState * env, DisasContext *s) 1109{ 1110 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh; 1111 1112 insn = ldl_code(s->pc); 1113 s->pc += 4; 1114 1115 cond = insn >> 28; 1116 if (cond == 0xf){ 1117 /* Unconditional instructions. */ 1118 if ((insn & 0x0d70f000) == 0x0550f000) 1119 return; /* PLD */ 1120 else if ((insn & 0x0e000000) == 0x0a000000) { 1121 /* branch link and change to thumb (blx <offset>) */ 1122 int32_t offset; 1123 1124 val = (uint32_t)s->pc; 1125 gen_op_movl_T0_im(val); 1126 gen_movl_reg_T0(s, 14); 1127 /* Sign-extend the 24-bit offset */ 1128 offset = (((int32_t)insn) << 8) >> 8; 1129 /* offset * 4 + bit24 * 2 + (thumb bit) */ 1130 val += (offset << 2) | ((insn >> 23) & 2) | 1; 1131 /* pipeline offset */ 1132 val += 4; 1133 gen_op_movl_T0_im(val); 1134 gen_bx(s); 1135 return; 1136 } else if ((insn & 0x0fe00000) == 0x0c400000) { 1137 /* Coprocessor double register transfer. */ 1138 } else if ((insn & 0x0f000010) == 0x0e000010) { 1139 /* Additional coprocessor register transfer. */ 1140 } else if ((insn & 0x0ff10010) == 0x01000000) { 1141 /* cps (privileged) */ 1142 } else if ((insn & 0x0ffffdff) == 0x01010000) { 1143 /* setend */ 1144 if (insn & (1 << 9)) { 1145 /* BE8 mode not implemented. */ 1146 goto illegal_op; 1147 } 1148 return; 1149 } 1150 goto illegal_op; 1151 } 1152 if (cond != 0xe) { 1153 /* if not always execute, we generate a conditional jump to 1154 next instruction */ 1155 s->condlabel = gen_new_label(); 1156 gen_test_cc[cond ^ 1](s->condlabel); 1157 s->condjmp = 1; 1158 //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); 1159 //s->is_jmp = DISAS_JUMP_NEXT; 1160 } 1161 if ((insn & 0x0f900000) == 0x03000000) { 1162 if ((insn & 0x0fb0f000) != 0x0320f000) 1163 goto illegal_op; 1164 /* CPSR = immediate */ 1165 val = insn & 0xff; 1166 shift = ((insn >> 8) & 0xf) * 2; 1167 if (shift) 1168 val = (val >> shift) | (val << (32 - shift)); 1169 gen_op_movl_T0_im(val); 1170 i = ((insn & (1 << 22)) != 0); 1171 if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i)) 1172 goto illegal_op; 1173 } else if ((insn & 0x0f900000) == 0x01000000 1174 && (insn & 0x00000090) != 0x00000090) { 1175 /* miscellaneous instructions */ 1176 op1 = (insn >> 21) & 3; 1177 sh = (insn >> 4) & 0xf; 1178 rm = insn & 0xf; 1179 switch (sh) { 1180 case 0x0: /* move program status register */ 1181 if (op1 & 1) { 1182 /* PSR = reg */ 1183 gen_movl_T0_reg(s, rm); 1184 i = ((op1 & 2) != 0); 1185 if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i)) 1186 goto illegal_op; 1187 } else { 1188 /* reg = PSR */ 1189 rd = (insn >> 12) & 0xf; 1190 if (op1 & 2) { 1191 if (IS_USER(s)) 1192 goto illegal_op; 1193 gen_op_movl_T0_spsr(); 1194 } else { 1195 gen_op_movl_T0_cpsr(); 1196 } 1197 gen_movl_reg_T0(s, rd); 1198 } 1199 break; 1200 case 0x1: 1201 if (op1 == 1) { 1202 /* branch/exchange thumb (bx). */ 1203 gen_movl_T0_reg(s, rm); 1204 gen_bx(s); 1205 } else if (op1 == 3) { 1206 /* clz */ 1207 rd = (insn >> 12) & 0xf; 1208 gen_movl_T0_reg(s, rm); 1209 gen_op_clz_T0(); 1210 gen_movl_reg_T0(s, rd); 1211 } else { 1212 goto illegal_op; 1213 } 1214 break; 1215 case 0x2: 1216 if (op1 == 1) { 1217 ARCH(5J); /* bxj */ 1218 /* Trivial implementation equivalent to bx. */ 1219 gen_movl_T0_reg(s, rm); 1220 gen_bx(s); 1221 } else { 1222 goto illegal_op; 1223 } 1224 break; 1225 case 0x3: 1226 if (op1 != 1) 1227 goto illegal_op; 1228 1229 /* branch link/exchange thumb (blx) */ 1230 val = (uint32_t)s->pc; 1231 gen_op_movl_T0_im(val); 1232 gen_movl_reg_T0(s, 14); 1233 gen_movl_T0_reg(s, rm); 1234 gen_bx(s); 1235 break; 1236 case 0x5: /* saturating add/subtract */ 1237 rd = (insn >> 12) & 0xf; 1238 rn = (insn >> 16) & 0xf; 1239 gen_movl_T0_reg(s, rm); 1240 gen_movl_T1_reg(s, rn); 1241 if (op1 & 2) 1242 gen_op_double_T1_saturate(); 1243 if (op1 & 1) 1244 gen_op_subl_T0_T1_saturate(); 1245 else 1246 gen_op_addl_T0_T1_saturate(); 1247 gen_movl_reg_T0(s, rd); 1248 break; 1249 case 7: /* bkpt */ 1250 gen_op_movl_T0_im((long)s->pc - 4); 1251 gen_op_movl_reg_TN[0][15](); 1252 gen_op_bkpt(); 1253 s->is_jmp = DISAS_JUMP; 1254 break; 1255 case 0x8: /* signed multiply */ 1256 case 0xa: 1257 case 0xc: 1258 case 0xe: 1259 rs = (insn >> 8) & 0xf; 1260 rn = (insn >> 12) & 0xf; 1261 rd = (insn >> 16) & 0xf; 1262 if (op1 == 1) { 1263 /* (32 * 16) >> 16 */ 1264 gen_movl_T0_reg(s, rm); 1265 gen_movl_T1_reg(s, rs); 1266 if (sh & 4) 1267 gen_op_sarl_T1_im(16); 1268 else 1269 gen_op_sxth_T1(); 1270 gen_op_imulw_T0_T1(); 1271 if ((sh & 2) == 0) { 1272 gen_movl_T1_reg(s, rn); 1273 gen_op_addl_T0_T1_setq(); 1274 } 1275 gen_movl_reg_T0(s, rd); 1276 } else { 1277 /* 16 * 16 */ 1278 gen_movl_T0_reg(s, rm); 1279 gen_movl_T1_reg(s, rs); 1280 gen_mulxy(sh & 2, sh & 4); 1281 if (op1 == 2) { 1282 gen_op_signbit_T1_T0(); 1283 gen_op_addq_T0_T1(rn, rd); 1284 gen_movl_reg_T0(s, rn); 1285 gen_movl_reg_T1(s, rd); 1286 } else { 1287 if (op1 == 0) { 1288 gen_movl_T1_reg(s, rn); 1289 gen_op_addl_T0_T1_setq(); 1290 } 1291 gen_movl_reg_T0(s, rd); 1292 } 1293 } 1294 break; 1295 default: 1296 goto illegal_op; 1297 } 1298 } else if (((insn & 0x0e000000) == 0 && 1299 (insn & 0x00000090) != 0x90) || 1300 ((insn & 0x0e000000) == (1 << 25))) { 1301 int set_cc, logic_cc, shiftop; 1302 1303 op1 = (insn >> 21) & 0xf; 1304 set_cc = (insn >> 20) & 1; 1305 logic_cc = table_logic_cc[op1] & set_cc; 1306 1307 /* data processing instruction */ 1308 if (insn & (1 << 25)) { 1309 /* immediate operand */ 1310 val = insn & 0xff; 1311 shift = ((insn >> 8) & 0xf) * 2; 1312 if (shift) 1313 val = (val >> shift) | (val << (32 - shift)); 1314 gen_op_movl_T1_im(val); 1315 if (logic_cc && shift) 1316 gen_op_mov_CF_T1(); 1317 } else { 1318 /* register */ 1319 rm = (insn) & 0xf; 1320 gen_movl_T1_reg(s, rm); 1321 shiftop = (insn >> 5) & 3; 1322 if (!(insn & (1 << 4))) { 1323 shift = (insn >> 7) & 0x1f; 1324 if (shift != 0) { 1325 if (logic_cc) { 1326 gen_shift_T1_im_cc[shiftop](shift); 1327 } else { 1328 gen_shift_T1_im[shiftop](shift); 1329 } 1330 } else if (shiftop != 0) { 1331 if (logic_cc) { 1332 gen_shift_T1_0_cc[shiftop](); 1333 } else { 1334 gen_shift_T1_0[shiftop](); 1335 } 1336 } 1337 } else { 1338 rs = (insn >> 8) & 0xf; 1339 gen_movl_T0_reg(s, rs); 1340 if (logic_cc) { 1341 gen_shift_T1_T0_cc[shiftop](); 1342 } else { 1343 gen_shift_T1_T0[shiftop](); 1344 } 1345 } 1346 } 1347 if (op1 != 0x0f && op1 != 0x0d) { 1348 rn = (insn >> 16) & 0xf; 1349 gen_movl_T0_reg(s, rn); 1350 } 1351 rd = (insn >> 12) & 0xf; 1352 switch(op1) { 1353 case 0x00: 1354 gen_op_andl_T0_T1(); 1355 gen_movl_reg_T0(s, rd); 1356 if (logic_cc) 1357 gen_op_logic_T0_cc(); 1358 break; 1359 case 0x01: 1360 gen_op_xorl_T0_T1(); 1361 gen_movl_reg_T0(s, rd); 1362 if (logic_cc) 1363 gen_op_logic_T0_cc(); 1364 break; 1365 case 0x02: 1366 if (set_cc && rd == 15) { 1367 /* SUBS r15, ... is used for exception return. */ 1368 if (IS_USER(s)) 1369 goto illegal_op; 1370 gen_op_subl_T0_T1_cc(); 1371 gen_exception_return(s); 1372 } else { 1373 if (set_cc) 1374 gen_op_subl_T0_T1_cc(); 1375 else 1376 gen_op_subl_T0_T1(); 1377 gen_movl_reg_T0(s, rd); 1378 } 1379 break; 1380 case 0x03: 1381 if (set_cc) 1382 gen_op_rsbl_T0_T1_cc(); 1383 else 1384 gen_op_rsbl_T0_T1(); 1385 gen_movl_reg_T0(s, rd); 1386 break; 1387 case 0x04: 1388 if (set_cc) 1389 gen_op_addl_T0_T1_cc(); 1390 else 1391 gen_op_addl_T0_T1(); 1392 gen_movl_reg_T0(s, rd); 1393 break; 1394 case 0x05: 1395 if (set_cc) 1396 gen_op_adcl_T0_T1_cc(); 1397 else 1398 gen_op_adcl_T0_T1(); 1399 gen_movl_reg_T0(s, rd); 1400 break; 1401 case 0x06: 1402 if (set_cc) 1403 gen_op_sbcl_T0_T1_cc(); 1404 else 1405 gen_op_sbcl_T0_T1(); 1406 gen_movl_reg_T0(s, rd); 1407 break; 1408 case 0x07: 1409 if (set_cc) 1410 gen_op_rscl_T0_T1_cc(); 1411 else 1412 gen_op_rscl_T0_T1(); 1413 gen_movl_reg_T0(s, rd); 1414 break; 1415 case 0x08: 1416 if (set_cc) { 1417 gen_op_andl_T0_T1(); 1418 gen_op_logic_T0_cc(); 1419 } 1420 break; 1421 case 0x09: 1422 if (set_cc) { 1423 gen_op_xorl_T0_T1(); 1424 gen_op_logic_T0_cc(); 1425 } 1426 break; 1427 case 0x0a: 1428 if (set_cc) { 1429 gen_op_subl_T0_T1_cc(); 1430 } 1431 break; 1432 case 0x0b: 1433 if (set_cc) { 1434 gen_op_addl_T0_T1_cc(); 1435 } 1436 break; 1437 case 0x0c: 1438 gen_op_orl_T0_T1(); 1439 gen_movl_reg_T0(s, rd); 1440 if (logic_cc) 1441 gen_op_logic_T0_cc(); 1442 break; 1443 case 0x0d: 1444 if (logic_cc && rd == 15) { 1445 /* MOVS r15, ... is used for exception return. */ 1446 if (IS_USER(s)) 1447 goto illegal_op; 1448 gen_op_movl_T0_T1(); 1449 gen_exception_return(s); 1450 } else { 1451 gen_movl_reg_T1(s, rd); 1452 if (logic_cc) 1453 gen_op_logic_T1_cc(); 1454 } 1455 break; 1456 case 0x0e: 1457 gen_op_bicl_T0_T1(); 1458 gen_movl_reg_T0(s, rd); 1459 if (logic_cc) 1460 gen_op_logic_T0_cc(); 1461 break; 1462 default: 1463 case 0x0f: 1464 gen_op_notl_T1(); 1465 gen_movl_reg_T1(s, rd); 1466 if (logic_cc) 1467 gen_op_logic_T1_cc(); 1468 break; 1469 } 1470 } else { 1471 /* other instructions */ 1472 op1 = (insn >> 24) & 0xf; 1473 switch(op1) { 1474 case 0x0: 1475 case 0x1: 1476 /* multiplies, extra load/stores */ 1477 sh = (insn >> 5) & 3; 1478 if (sh == 0) { 1479 if (op1 == 0x0) { 1480 rd = (insn >> 16) & 0xf; 1481 rn = (insn >> 12) & 0xf; 1482 rs = (insn >> 8) & 0xf; 1483 rm = (insn) & 0xf; 1484 if (((insn >> 22) & 3) == 0) { 1485 /* 32 bit mul */ 1486 gen_movl_T0_reg(s, rs); 1487 gen_movl_T1_reg(s, rm); 1488 gen_op_mul_T0_T1(); 1489 if (insn & (1 << 21)) { 1490 gen_movl_T1_reg(s, rn); 1491 gen_op_addl_T0_T1(); 1492 } 1493 if (insn & (1 << 20)) 1494 gen_op_logic_T0_cc(); 1495 gen_movl_reg_T0(s, rd); 1496 } else { 1497 /* 64 bit mul */ 1498 gen_movl_T0_reg(s, rs); 1499 gen_movl_T1_reg(s, rm); 1500 if (insn & (1 << 22)) 1501 gen_op_imull_T0_T1(); 1502 else 1503 gen_op_mull_T0_T1(); 1504 if (insn & (1 << 21)) /* mult accumulate */ 1505 gen_op_addq_T0_T1(rn, rd); 1506 if (!(insn & (1 << 23))) { /* double accumulate */ 1507 ARCH(6); 1508 gen_op_addq_lo_T0_T1(rn); 1509 gen_op_addq_lo_T0_T1(rd); 1510 } 1511 if (insn & (1 << 20)) 1512 gen_op_logicq_cc(); 1513 gen_movl_reg_T0(s, rn); 1514 gen_movl_reg_T1(s, rd); 1515 } 1516 } else { 1517 rn = (insn >> 16) & 0xf; 1518 rd = (insn >> 12) & 0xf; 1519 if (insn & (1 << 23)) { 1520 /* load/store exclusive */ 1521 goto illegal_op; 1522 } else { 1523 /* SWP instruction */ 1524 rm = (insn) & 0xf; 1525 1526 gen_movl_T0_reg(s, rm); 1527 gen_movl_T1_reg(s, rn); 1528 if (insn & (1 << 22)) { 1529 gen_ldst(swpb, s); 1530 } else { 1531 gen_ldst(swpl, s); 1532 } 1533 gen_movl_reg_T0(s, rd); 1534 } 1535 } 1536 } else { 1537 int address_offset; 1538 /* Misc load/store */ 1539 rn = (insn >> 16) & 0xf; 1540 rd = (insn >> 12) & 0xf; 1541 gen_movl_T1_reg(s, rn); 1542 if (insn & (1 << 24)) 1543 gen_add_datah_offset(s, insn, 0); 1544 address_offset = 0; 1545 if (insn & (1 << 20)) { 1546 /* load */ 1547 switch(sh) { 1548 case 1: 1549 gen_ldst(lduw, s); 1550 break; 1551 case 2: 1552 gen_ldst(ldsb, s); 1553 break; 1554 default: 1555 case 3: 1556 gen_ldst(ldsw, s); 1557 break; 1558 } 1559 gen_movl_reg_T0(s, rd); 1560 } else if (sh & 2) { 1561 /* doubleword */ 1562 if (sh & 1) { 1563 /* store */ 1564 gen_movl_T0_reg(s, rd); 1565 gen_ldst(stl, s); 1566 gen_op_addl_T1_im(4); 1567 gen_movl_T0_reg(s, rd + 1); 1568 gen_ldst(stl, s); 1569 } else { 1570 /* load */ 1571 gen_ldst(ldl, s); 1572 gen_movl_reg_T0(s, rd); 1573 gen_op_addl_T1_im(4); 1574 gen_ldst(ldl, s); 1575 gen_movl_reg_T0(s, rd + 1); 1576 } 1577 address_offset = -4; 1578 } else { 1579 /* store */ 1580 gen_movl_T0_reg(s, rd); 1581 gen_ldst(stw, s); 1582 } 1583 if (!(insn & (1 << 24))) { 1584 gen_add_datah_offset(s, insn, address_offset); 1585 gen_movl_reg_T1(s, rn); 1586 } else if (insn & (1 << 21)) { 1587 if (address_offset) 1588 gen_op_addl_T1_im(address_offset); 1589 gen_movl_reg_T1(s, rn); 1590 } 1591 } 1592 break; 1593 case 0x4: 1594 case 0x5: 1595 case 0x6: 1596 case 0x7: 1597 /* Check for undefined extension instructions 1598 * per the ARM Bible IE: 1599 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx 1600 */ 1601 sh = (0xf << 20) | (0xf << 4); 1602 if (op1 == 0x7 && ((insn & sh) == sh)) 1603 { 1604 goto illegal_op; 1605 } 1606 /* load/store byte/word */ 1607 rn = (insn >> 16) & 0xf; 1608 rd = (insn >> 12) & 0xf; 1609 gen_movl_T1_reg(s, rn); 1610 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000); 1611 if (insn & (1 << 24)) 1612 gen_add_data_offset(s, insn); 1613 if (insn & (1 << 20)) { 1614 /* load */ 1615#if defined(CONFIG_USER_ONLY) 1616 if (insn & (1 << 22)) 1617 gen_op_ldub_raw(); 1618 else 1619 gen_op_ldl_raw(); 1620#else 1621 if (insn & (1 << 22)) { 1622 if (i) 1623 gen_op_ldub_user(); 1624 else 1625 gen_op_ldub_kernel(); 1626 } else { 1627 if (i) 1628 gen_op_ldl_user(); 1629 else 1630 gen_op_ldl_kernel(); 1631 } 1632#endif 1633 if (rd == 15) 1634 gen_bx(s); 1635 else 1636 gen_movl_reg_T0(s, rd); 1637 } else { 1638 /* store */ 1639 gen_movl_T0_reg(s, rd); 1640#if defined(CONFIG_USER_ONLY) 1641 if (insn & (1 << 22)) 1642 gen_op_stb_raw(); 1643 else 1644 gen_op_stl_raw(); 1645#else 1646 if (insn & (1 << 22)) { 1647 if (i) 1648 gen_op_stb_user(); 1649 else 1650 gen_op_stb_kernel(); 1651 } else { 1652 if (i) 1653 gen_op_stl_user(); 1654 else 1655 gen_op_stl_kernel(); 1656 } 1657#endif 1658 } 1659 if (!(insn & (1 << 24))) { 1660 gen_add_data_offset(s, insn); 1661 gen_movl_reg_T1(s, rn); 1662 } else if (insn & (1 << 21)) 1663 gen_movl_reg_T1(s, rn); { 1664 } 1665 break; 1666 case 0x08: 1667 case 0x09: 1668 { 1669 int j, n, user, loaded_base; 1670 /* load/store multiple words */ 1671 /* XXX: store correct base if write back */ 1672 user = 0; 1673 if (insn & (1 << 22)) { 1674 if (IS_USER(s)) 1675 goto illegal_op; /* only usable in supervisor mode */ 1676 1677 if ((insn & (1 << 15)) == 0) 1678 user = 1; 1679 } 1680 rn = (insn >> 16) & 0xf; 1681 gen_movl_T1_reg(s, rn); 1682 1683 /* compute total size */ 1684 loaded_base = 0; 1685 n = 0; 1686 for(i=0;i<16;i++) { 1687 if (insn & (1 << i)) 1688 n++; 1689 } 1690 /* XXX: test invalid n == 0 case ? */ 1691 if (insn & (1 << 23)) { 1692 if (insn & (1 << 24)) { 1693 /* pre increment */ 1694 gen_op_addl_T1_im(4); 1695 } else { 1696 /* post increment */ 1697 } 1698 } else { 1699 if (insn & (1 << 24)) { 1700 /* pre decrement */ 1701 gen_op_addl_T1_im(-(n * 4)); 1702 } else { 1703 /* post decrement */ 1704 if (n != 1) 1705 gen_op_addl_T1_im(-((n - 1) * 4)); 1706 } 1707 } 1708 j = 0; 1709 for(i=0;i<16;i++) { 1710 if (insn & (1 << i)) { 1711 if (insn & (1 << 20)) { 1712 /* load */ 1713 gen_ldst(ldl, s); 1714 if (i == 15) { 1715 gen_bx(s); 1716 } else if (user) { 1717 gen_op_movl_user_T0(i); 1718 } else if (i == rn) { 1719 gen_op_movl_T2_T0(); 1720 loaded_base = 1; 1721 } else { 1722 gen_movl_reg_T0(s, i); 1723 } 1724 } else { 1725 /* store */ 1726 if (i == 15) { 1727 /* special case: r15 = PC + 12 */ 1728 val = (long)s->pc + 8; 1729 gen_op_movl_TN_im[0](val); 1730 } else if (user) { 1731 gen_op_movl_T0_user(i); 1732 } else { 1733 gen_movl_T0_reg(s, i); 1734 } 1735 gen_ldst(stl, s); 1736 } 1737 j++; 1738 /* no need to add after the last transfer */ 1739 if (j != n) 1740 gen_op_addl_T1_im(4); 1741 } 1742 } 1743 if (insn & (1 << 21)) { 1744 /* write back */ 1745 if (insn & (1 << 23)) { 1746 if (insn & (1 << 24)) { 1747 /* pre increment */ 1748 } else { 1749 /* post increment */ 1750 gen_op_addl_T1_im(4); 1751 } 1752 } else { 1753 if (insn & (1 << 24)) { 1754 /* pre decrement */ 1755 if (n != 1) 1756 gen_op_addl_T1_im(-((n - 1) * 4)); 1757 } else { 1758 /* post decrement */ 1759 gen_op_addl_T1_im(-(n * 4)); 1760 } 1761 } 1762 gen_movl_reg_T1(s, rn); 1763 } 1764 if (loaded_base) { 1765 gen_op_movl_T0_T2(); 1766 gen_movl_reg_T0(s, rn); 1767 } 1768 if ((insn & (1 << 22)) && !user) { 1769 /* Restore CPSR from SPSR. */ 1770 gen_op_movl_T0_spsr(); 1771 gen_op_movl_cpsr_T0(0xffffffff); 1772 s->is_jmp = DISAS_UPDATE; 1773 } 1774 } 1775 break; 1776 case 0xa: 1777 case 0xb: 1778 { 1779 int32_t offset; 1780 1781 /* branch (and link) */ 1782 val = (int32_t)s->pc; 1783 if (insn & (1 << 24)) { 1784 gen_op_movl_T0_im(val); 1785 gen_op_movl_reg_TN[0][14](); 1786 } 1787 offset = (((int32_t)insn << 8) >> 8); 1788 val += (offset << 2) + 4; 1789 gen_jmp(s, val); 1790 } 1791 break; 1792 case 0xc: 1793 case 0xd: 1794 case 0xe: 1795 /* Coprocessor. */ 1796 op1 = (insn >> 8) & 0xf; 1797 switch (op1) { 1798 case 10: 1799 case 11: 1800 if (disas_vfp_insn (env, s, insn)) 1801 goto illegal_op; 1802 break; 1803 case 15: 1804 if (disas_cp15_insn (s, insn)) 1805 goto illegal_op; 1806 break; 1807 default: 1808 /* unknown coprocessor. */ 1809 goto illegal_op; 1810 } 1811 break; 1812 case 0xf: 1813 /* swi */ 1814 gen_op_movl_T0_im((long)s->pc); 1815 gen_op_movl_reg_TN[0][15](); 1816 gen_op_swi(); 1817 s->is_jmp = DISAS_JUMP; 1818 break; 1819 default: 1820 illegal_op: 1821 gen_op_movl_T0_im((long)s->pc - 4); 1822 gen_op_movl_reg_TN[0][15](); 1823 gen_op_undef_insn(); 1824 s->is_jmp = DISAS_JUMP; 1825 break; 1826 } 1827 } 1828} 1829 1830static void disas_thumb_insn(DisasContext *s) 1831{ 1832 uint32_t val, insn, op, rm, rn, rd, shift, cond; 1833 int32_t offset; 1834 int i; 1835 1836 insn = lduw_code(s->pc); 1837 s->pc += 2; 1838 1839 switch (insn >> 12) { 1840 case 0: case 1: 1841 rd = insn & 7; 1842 op = (insn >> 11) & 3; 1843 if (op == 3) { 1844 /* add/subtract */ 1845 rn = (insn >> 3) & 7; 1846 gen_movl_T0_reg(s, rn); 1847 if (insn & (1 << 10)) { 1848 /* immediate */ 1849 gen_op_movl_T1_im((insn >> 6) & 7); 1850 } else { 1851 /* reg */ 1852 rm = (insn >> 6) & 7; 1853 gen_movl_T1_reg(s, rm); 1854 } 1855 if (insn & (1 << 9)) 1856 gen_op_subl_T0_T1_cc(); 1857 else 1858 gen_op_addl_T0_T1_cc(); 1859 gen_movl_reg_T0(s, rd); 1860 } else { 1861 /* shift immediate */ 1862 rm = (insn >> 3) & 7; 1863 shift = (insn >> 6) & 0x1f; 1864 gen_movl_T0_reg(s, rm); 1865 gen_shift_T0_im_thumb[op](shift); 1866 gen_movl_reg_T0(s, rd); 1867 } 1868 break; 1869 case 2: case 3: 1870 /* arithmetic large immediate */ 1871 op = (insn >> 11) & 3; 1872 rd = (insn >> 8) & 0x7; 1873 if (op == 0) { 1874 gen_op_movl_T0_im(insn & 0xff); 1875 } else { 1876 gen_movl_T0_reg(s, rd); 1877 gen_op_movl_T1_im(insn & 0xff); 1878 } 1879 switch (op) { 1880 case 0: /* mov */ 1881 gen_op_logic_T0_cc(); 1882 break; 1883 case 1: /* cmp */ 1884 gen_op_subl_T0_T1_cc(); 1885 break; 1886 case 2: /* add */ 1887 gen_op_addl_T0_T1_cc(); 1888 break; 1889 case 3: /* sub */ 1890 gen_op_subl_T0_T1_cc(); 1891 break; 1892 } 1893 if (op != 1) 1894 gen_movl_reg_T0(s, rd); 1895 break; 1896 case 4: 1897 if (insn & (1 << 11)) { 1898 rd = (insn >> 8) & 7; 1899 /* load pc-relative. Bit 1 of PC is ignored. */ 1900 val = s->pc + 2 + ((insn & 0xff) * 4); 1901 val &= ~(uint32_t)2; 1902 gen_op_movl_T1_im(val); 1903 gen_ldst(ldl, s); 1904 gen_movl_reg_T0(s, rd); 1905 break; 1906 } 1907 if (insn & (1 << 10)) { 1908 /* data processing extended or blx */ 1909 rd = (insn & 7) | ((insn >> 4) & 8); 1910 rm = (insn >> 3) & 0xf; 1911 op = (insn >> 8) & 3; 1912 switch (op) { 1913 case 0: /* add */ 1914 gen_movl_T0_reg(s, rd); 1915 gen_movl_T1_reg(s, rm); 1916 gen_op_addl_T0_T1(); 1917 gen_movl_reg_T0(s, rd); 1918 break; 1919 case 1: /* cmp */ 1920 gen_movl_T0_reg(s, rd); 1921 gen_movl_T1_reg(s, rm); 1922 gen_op_subl_T0_T1_cc(); 1923 break; 1924 case 2: /* mov/cpy */ 1925 gen_movl_T0_reg(s, rm); 1926 gen_movl_reg_T0(s, rd); 1927 break; 1928 case 3:/* branch [and link] exchange thumb register */ 1929 if (insn & (1 << 7)) { 1930 val = (uint32_t)s->pc | 1; 1931 gen_op_movl_T1_im(val); 1932 gen_movl_reg_T1(s, 14); 1933 } 1934 gen_movl_T0_reg(s, rm); 1935 gen_bx(s); 1936 break; 1937 } 1938 break; 1939 } 1940 1941 /* data processing register */ 1942 rd = insn & 7; 1943 rm = (insn >> 3) & 7; 1944 op = (insn >> 6) & 0xf; 1945 if (op == 2 || op == 3 || op == 4 || op == 7) { 1946 /* the shift/rotate ops want the operands backwards */ 1947 val = rm; 1948 rm = rd; 1949 rd = val; 1950 val = 1; 1951 } else { 1952 val = 0; 1953 } 1954 1955 if (op == 9) /* neg */ 1956 gen_op_movl_T0_im(0); 1957 else if (op != 0xf) /* mvn doesn't read its first operand */ 1958 gen_movl_T0_reg(s, rd); 1959 1960 gen_movl_T1_reg(s, rm); 1961 switch (op) { 1962 case 0x0: /* and */ 1963 gen_op_andl_T0_T1(); 1964 gen_op_logic_T0_cc(); 1965 break; 1966 case 0x1: /* eor */ 1967 gen_op_xorl_T0_T1(); 1968 gen_op_logic_T0_cc(); 1969 break; 1970 case 0x2: /* lsl */ 1971 gen_op_shll_T1_T0_cc(); 1972 gen_op_logic_T1_cc(); 1973 break; 1974 case 0x3: /* lsr */ 1975 gen_op_shrl_T1_T0_cc(); 1976 gen_op_logic_T1_cc(); 1977 break; 1978 case 0x4: /* asr */ 1979 gen_op_sarl_T1_T0_cc(); 1980 gen_op_logic_T1_cc(); 1981 break; 1982 case 0x5: /* adc */ 1983 gen_op_adcl_T0_T1_cc(); 1984 break; 1985 case 0x6: /* sbc */ 1986 gen_op_sbcl_T0_T1_cc(); 1987 break; 1988 case 0x7: /* ror */ 1989 gen_op_rorl_T1_T0_cc(); 1990 gen_op_logic_T1_cc(); 1991 break; 1992 case 0x8: /* tst */ 1993 gen_op_andl_T0_T1(); 1994 gen_op_logic_T0_cc(); 1995 rd = 16; 1996 break; 1997 case 0x9: /* neg */ 1998 gen_op_subl_T0_T1_cc(); 1999 break; 2000 case 0xa: /* cmp */ 2001 gen_op_subl_T0_T1_cc(); 2002 rd = 16; 2003 break; 2004 case 0xb: /* cmn */ 2005 gen_op_addl_T0_T1_cc(); 2006 rd = 16; 2007 break; 2008 case 0xc: /* orr */ 2009 gen_op_orl_T0_T1(); 2010 gen_op_logic_T0_cc(); 2011 break; 2012 case 0xd: /* mul */ 2013 gen_op_mull_T0_T1(); 2014 gen_op_logic_T0_cc(); 2015 break; 2016 case 0xe: /* bic */ 2017 gen_op_bicl_T0_T1(); 2018 gen_op_logic_T0_cc(); 2019 break; 2020 case 0xf: /* mvn */ 2021 gen_op_notl_T1(); 2022 gen_op_logic_T1_cc(); 2023 val = 1; 2024 rm = rd; 2025 break; 2026 } 2027 if (rd != 16) { 2028 if (val) 2029 gen_movl_reg_T1(s, rm); 2030 else 2031 gen_movl_reg_T0(s, rd); 2032 } 2033 break; 2034 2035 case 5: 2036 /* load/store register offset. */ 2037 rd = insn & 7; 2038 rn = (insn >> 3) & 7; 2039 rm = (insn >> 6) & 7; 2040 op = (insn >> 9) & 7; 2041 gen_movl_T1_reg(s, rn); 2042 gen_movl_T2_reg(s, rm); 2043 gen_op_addl_T1_T2(); 2044 2045 if (op < 3) /* store */ 2046 gen_movl_T0_reg(s, rd); 2047 2048 switch (op) { 2049 case 0: /* str */ 2050 gen_ldst(stl, s); 2051 break; 2052 case 1: /* strh */ 2053 gen_ldst(stw, s); 2054 break; 2055 case 2: /* strb */ 2056 gen_ldst(stb, s); 2057 break; 2058 case 3: /* ldrsb */ 2059 gen_ldst(ldsb, s); 2060 break; 2061 case 4: /* ldr */ 2062 gen_ldst(ldl, s); 2063 break; 2064 case 5: /* ldrh */ 2065 gen_ldst(lduw, s); 2066 break; 2067 case 6: /* ldrb */ 2068 gen_ldst(ldub, s); 2069 break; 2070 case 7: /* ldrsh */ 2071 gen_ldst(ldsw, s); 2072 break; 2073 } 2074 if (op >= 3) /* load */ 2075 gen_movl_reg_T0(s, rd); 2076 break; 2077 2078 case 6: 2079 /* load/store word immediate offset */ 2080 rd = insn & 7; 2081 rn = (insn >> 3) & 7; 2082 gen_movl_T1_reg(s, rn); 2083 val = (insn >> 4) & 0x7c; 2084 gen_op_movl_T2_im(val); 2085 gen_op_addl_T1_T2(); 2086 2087 if (insn & (1 << 11)) { 2088 /* load */ 2089 gen_ldst(ldl, s); 2090 gen_movl_reg_T0(s, rd); 2091 } else { 2092 /* store */ 2093 gen_movl_T0_reg(s, rd); 2094 gen_ldst(stl, s); 2095 } 2096 break; 2097 2098 case 7: 2099 /* load/store byte immediate offset */ 2100 rd = insn & 7; 2101 rn = (insn >> 3) & 7; 2102 gen_movl_T1_reg(s, rn); 2103 val = (insn >> 6) & 0x1f; 2104 gen_op_movl_T2_im(val); 2105 gen_op_addl_T1_T2(); 2106 2107 if (insn & (1 << 11)) { 2108 /* load */ 2109 gen_ldst(ldub, s); 2110 gen_movl_reg_T0(s, rd); 2111 } else { 2112 /* store */ 2113 gen_movl_T0_reg(s, rd); 2114 gen_ldst(stb, s); 2115 } 2116 break; 2117 2118 case 8: 2119 /* load/store halfword immediate offset */ 2120 rd = insn & 7; 2121 rn = (insn >> 3) & 7; 2122 gen_movl_T1_reg(s, rn); 2123 val = (insn >> 5) & 0x3e; 2124 gen_op_movl_T2_im(val); 2125 gen_op_addl_T1_T2(); 2126 2127 if (insn & (1 << 11)) { 2128 /* load */ 2129 gen_ldst(lduw, s); 2130 gen_movl_reg_T0(s, rd); 2131 } else { 2132 /* store */ 2133 gen_movl_T0_reg(s, rd); 2134 gen_ldst(stw, s); 2135 } 2136 break; 2137 2138 case 9: 2139 /* load/store from stack */ 2140 rd = (insn >> 8) & 7; 2141 gen_movl_T1_reg(s, 13); 2142 val = (insn & 0xff) * 4; 2143 gen_op_movl_T2_im(val); 2144 gen_op_addl_T1_T2(); 2145 2146 if (insn & (1 << 11)) { 2147 /* load */ 2148 gen_ldst(ldl, s); 2149 gen_movl_reg_T0(s, rd); 2150 } else { 2151 /* store */ 2152 gen_movl_T0_reg(s, rd); 2153 gen_ldst(stl, s); 2154 } 2155 break; 2156 2157 case 10: 2158 /* add to high reg */ 2159 rd = (insn >> 8) & 7; 2160 if (insn & (1 << 11)) { 2161 /* SP */ 2162 gen_movl_T0_reg(s, 13); 2163 } else { 2164 /* PC. bit 1 is ignored. */ 2165 gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2); 2166 } 2167 val = (insn & 0xff) * 4; 2168 gen_op_movl_T1_im(val); 2169 gen_op_addl_T0_T1(); 2170 gen_movl_reg_T0(s, rd); 2171 break; 2172 2173 case 11: 2174 /* misc */ 2175 op = (insn >> 8) & 0xf; 2176 switch (op) { 2177 case 0: 2178 /* adjust stack pointer */ 2179 gen_movl_T1_reg(s, 13); 2180 val = (insn & 0x7f) * 4; 2181 if (insn & (1 << 7)) 2182 val = -(int32_t)val; 2183 gen_op_movl_T2_im(val); 2184 gen_op_addl_T1_T2(); 2185 gen_movl_reg_T1(s, 13); 2186 break; 2187 2188 case 4: case 5: case 0xc: case 0xd: 2189 /* push/pop */ 2190 gen_movl_T1_reg(s, 13); 2191 if (insn & (1 << 8)) 2192 offset = 4; 2193 else 2194 offset = 0; 2195 for (i = 0; i < 8; i++) { 2196 if (insn & (1 << i)) 2197 offset += 4; 2198 } 2199 if ((insn & (1 << 11)) == 0) { 2200 gen_op_movl_T2_im(-offset); 2201 gen_op_addl_T1_T2(); 2202 } 2203 gen_op_movl_T2_im(4); 2204 for (i = 0; i < 8; i++) { 2205 if (insn & (1 << i)) { 2206 if (insn & (1 << 11)) { 2207 /* pop */ 2208 gen_ldst(ldl, s); 2209 gen_movl_reg_T0(s, i); 2210 } else { 2211 /* push */ 2212 gen_movl_T0_reg(s, i); 2213 gen_ldst(stl, s); 2214 } 2215 /* advance to the next address. */ 2216 gen_op_addl_T1_T2(); 2217 } 2218 } 2219 if (insn & (1 << 8)) { 2220 if (insn & (1 << 11)) { 2221 /* pop pc */ 2222 gen_ldst(ldl, s); 2223 /* don't set the pc until the rest of the instruction 2224 has completed */ 2225 } else { 2226 /* push lr */ 2227 gen_movl_T0_reg(s, 14); 2228 gen_ldst(stl, s); 2229 } 2230 gen_op_addl_T1_T2(); 2231 } 2232 if ((insn & (1 << 11)) == 0) { 2233 gen_op_movl_T2_im(-offset); 2234 gen_op_addl_T1_T2(); 2235 } 2236 /* write back the new stack pointer */ 2237 gen_movl_reg_T1(s, 13); 2238 /* set the new PC value */ 2239 if ((insn & 0x0900) == 0x0900) 2240 gen_bx(s); 2241 break; 2242 2243 case 0xe: /* bkpt */ 2244 gen_op_movl_T0_im((long)s->pc - 2); 2245 gen_op_movl_reg_TN[0][15](); 2246 gen_op_bkpt(); 2247 s->is_jmp = DISAS_JUMP; 2248 break; 2249 2250 default: 2251 goto undef; 2252 } 2253 break; 2254 2255 case 12: 2256 /* load/store multiple */ 2257 rn = (insn >> 8) & 0x7; 2258 gen_movl_T1_reg(s, rn); 2259 gen_op_movl_T2_im(4); 2260 for (i = 0; i < 8; i++) { 2261 if (insn & (1 << i)) { 2262 if (insn & (1 << 11)) { 2263 /* load */ 2264 gen_ldst(ldl, s); 2265 gen_movl_reg_T0(s, i); 2266 } else { 2267 /* store */ 2268 gen_movl_T0_reg(s, i); 2269 gen_ldst(stl, s); 2270 } 2271 /* advance to the next address */ 2272 gen_op_addl_T1_T2(); 2273 } 2274 } 2275 /* Base register writeback. */ 2276 if ((insn & (1 << rn)) == 0) 2277 gen_movl_reg_T1(s, rn); 2278 break; 2279 2280 case 13: 2281 /* conditional branch or swi */ 2282 cond = (insn >> 8) & 0xf; 2283 if (cond == 0xe) 2284 goto undef; 2285 2286 if (cond == 0xf) { 2287 /* swi */ 2288 gen_op_movl_T0_im((long)s->pc | 1); 2289 /* Don't set r15. */ 2290 gen_op_movl_reg_TN[0][15](); 2291 gen_op_swi(); 2292 s->is_jmp = DISAS_JUMP; 2293 break; 2294 } 2295 /* generate a conditional jump to next instruction */ 2296 s->condlabel = gen_new_label(); 2297 gen_test_cc[cond ^ 1](s->condlabel); 2298 s->condjmp = 1; 2299 //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); 2300 //s->is_jmp = DISAS_JUMP_NEXT; 2301 gen_movl_T1_reg(s, 15); 2302 2303 /* jump to the offset */ 2304 val = (uint32_t)s->pc + 2; 2305 offset = ((int32_t)insn << 24) >> 24; 2306 val += offset << 1; 2307 gen_jmp(s, val); 2308 break; 2309 2310 case 14: 2311 /* unconditional branch */ 2312 if (insn & (1 << 11)) { 2313 /* Second half of blx. */ 2314 offset = ((insn & 0x7ff) << 1); 2315 gen_movl_T0_reg(s, 14); 2316 gen_op_movl_T1_im(offset); 2317 gen_op_addl_T0_T1(); 2318 gen_op_movl_T1_im(0xfffffffc); 2319 gen_op_andl_T0_T1(); 2320 2321 val = (uint32_t)s->pc; 2322 gen_op_movl_T1_im(val | 1); 2323 gen_movl_reg_T1(s, 14); 2324 gen_bx(s); 2325 break; 2326 } 2327 val = (uint32_t)s->pc; 2328 offset = ((int32_t)insn << 21) >> 21; 2329 val += (offset << 1) + 2; 2330 gen_jmp(s, val); 2331 break; 2332 2333 case 15: 2334 /* branch and link [and switch to arm] */ 2335 if ((s->pc & ~TARGET_PAGE_MASK) == 0) { 2336 /* Instruction spans a page boundary. Implement it as two 2337 16-bit instructions in case the second half causes an 2338 prefetch abort. */ 2339 offset = ((int32_t)insn << 21) >> 9; 2340 val = s->pc + 2 + offset; 2341 gen_op_movl_T0_im(val); 2342 gen_movl_reg_T0(s, 14); 2343 break; 2344 } 2345 if (insn & (1 << 11)) { 2346 /* Second half of bl. */ 2347 offset = ((insn & 0x7ff) << 1) | 1; 2348 gen_movl_T0_reg(s, 14); 2349 gen_op_movl_T1_im(offset); 2350 gen_op_addl_T0_T1(); 2351 2352 val = (uint32_t)s->pc; 2353 gen_op_movl_T1_im(val | 1); 2354 gen_movl_reg_T1(s, 14); 2355 gen_bx(s); 2356 break; 2357 } 2358 offset = ((int32_t)insn << 21) >> 10; 2359 insn = lduw_code(s->pc); 2360 offset |= insn & 0x7ff; 2361 2362 val = (uint32_t)s->pc + 2; 2363 gen_op_movl_T1_im(val | 1); 2364 gen_movl_reg_T1(s, 14); 2365 2366 val += offset << 1; 2367 if (insn & (1 << 12)) { 2368 /* bl */ 2369 gen_jmp(s, val); 2370 } else { 2371 /* blx */ 2372 val &= ~(uint32_t)2; 2373 gen_op_movl_T0_im(val); 2374 gen_bx(s); 2375 } 2376 } 2377 return; 2378undef: 2379 gen_op_movl_T0_im((long)s->pc - 2); 2380 gen_op_movl_reg_TN[0][15](); 2381 gen_op_undef_insn(); 2382 s->is_jmp = DISAS_JUMP; 2383} 2384 2385/* generate intermediate code in gen_opc_buf and gen_opparam_buf for 2386 basic block 'tb'. If search_pc is TRUE, also generate PC 2387 information for each intermediate instruction. */ 2388static inline int gen_intermediate_code_internal(CPUState *env, 2389 TranslationBlock *tb, 2390 int search_pc) 2391{ 2392 DisasContext dc1, *dc = &dc1; 2393 uint16_t *gen_opc_end; 2394 int j, lj; 2395 target_ulong pc_start; 2396 uint32_t next_page_start; 2397 2398 /* generate intermediate code */ 2399 pc_start = tb->pc; 2400 2401 dc->tb = tb; 2402 2403 gen_opc_ptr = gen_opc_buf; 2404 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; 2405 gen_opparam_ptr = gen_opparam_buf; 2406 2407 dc->is_jmp = DISAS_NEXT; 2408 dc->pc = pc_start; 2409 dc->singlestep_enabled = env->singlestep_enabled; 2410 dc->condjmp = 0; 2411 dc->thumb = env->thumb; 2412#if !defined(CONFIG_USER_ONLY) 2413 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR; 2414#endif 2415 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; 2416 nb_gen_labels = 0; 2417 lj = -1; 2418 do { 2419 if (env->nb_breakpoints > 0) { 2420 for(j = 0; j < env->nb_breakpoints; j++) { 2421 if (env->breakpoints[j] == dc->pc) { 2422 gen_op_movl_T0_im((long)dc->pc); 2423 gen_op_movl_reg_TN[0][15](); 2424 gen_op_debug(); 2425 dc->is_jmp = DISAS_JUMP; 2426 break; 2427 } 2428 } 2429 } 2430 if (search_pc) { 2431 j = gen_opc_ptr - gen_opc_buf; 2432 if (lj < j) { 2433 lj++; 2434 while (lj < j) 2435 gen_opc_instr_start[lj++] = 0; 2436 } 2437 gen_opc_pc[lj] = dc->pc; 2438 gen_opc_instr_start[lj] = 1; 2439 } 2440 2441 if (env->thumb) 2442 disas_thumb_insn(dc); 2443 else 2444 disas_arm_insn(env, dc); 2445 2446 if (dc->condjmp && !dc->is_jmp) { 2447 gen_set_label(dc->condlabel); 2448 dc->condjmp = 0; 2449 } 2450 /* Translation stops when a conditional branch is enoutered. 2451 * Otherwise the subsequent code could get translated several times. 2452 * Also stop translation when a page boundary is reached. This 2453 * ensures prefech aborts occur at the right place. */ 2454 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 2455 !env->singlestep_enabled && 2456 dc->pc < next_page_start); 2457 /* At this stage dc->condjmp will only be set when the skipped 2458 * instruction was a conditional branch, and the PC has already been 2459 * written. */ 2460 if (__builtin_expect(env->singlestep_enabled, 0)) { 2461 /* Make sure the pc is updated, and raise a debug exception. */ 2462 if (dc->condjmp) { 2463 gen_op_debug(); 2464 gen_set_label(dc->condlabel); 2465 } 2466 if (dc->condjmp || !dc->is_jmp) { 2467 gen_op_movl_T0_im((long)dc->pc); 2468 gen_op_movl_reg_TN[0][15](); 2469 dc->condjmp = 0; 2470 } 2471 gen_op_debug(); 2472 } else { 2473 switch(dc->is_jmp) { 2474 case DISAS_NEXT: 2475 gen_goto_tb(dc, 1, dc->pc); 2476 break; 2477 default: 2478 case DISAS_JUMP: 2479 case DISAS_UPDATE: 2480 /* indicate that the hash table must be used to find the next TB */ 2481 gen_op_movl_T0_0(); 2482 gen_op_exit_tb(); 2483 break; 2484 case DISAS_TB_JUMP: 2485 /* nothing more to generate */ 2486 break; 2487 } 2488 if (dc->condjmp) { 2489 gen_set_label(dc->condlabel); 2490 gen_goto_tb(dc, 1, dc->pc); 2491 dc->condjmp = 0; 2492 } 2493 } 2494 *gen_opc_ptr = INDEX_op_end; 2495 2496#ifdef DEBUG_DISAS 2497 if (loglevel & CPU_LOG_TB_IN_ASM) { 2498 fprintf(logfile, "----------------\n"); 2499 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); 2500 target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb); 2501 fprintf(logfile, "\n"); 2502 if (loglevel & (CPU_LOG_TB_OP)) { 2503 fprintf(logfile, "OP:\n"); 2504 dump_ops(gen_opc_buf, gen_opparam_buf); 2505 fprintf(logfile, "\n"); 2506 } 2507 } 2508#endif 2509 if (search_pc) { 2510 j = gen_opc_ptr - gen_opc_buf; 2511 lj++; 2512 while (lj <= j) 2513 gen_opc_instr_start[lj++] = 0; 2514 tb->size = 0; 2515 } else { 2516 tb->size = dc->pc - pc_start; 2517 } 2518 return 0; 2519} 2520 2521int gen_intermediate_code(CPUState *env, TranslationBlock *tb) 2522{ 2523 return gen_intermediate_code_internal(env, tb, 0); 2524} 2525 2526int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) 2527{ 2528 return gen_intermediate_code_internal(env, tb, 1); 2529} 2530 2531static const char *cpu_mode_names[16] = { 2532 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt", 2533 "???", "???", "???", "und", "???", "???", "???", "sys" 2534}; 2535void cpu_dump_state(CPUState *env, FILE *f, 2536 int (*cpu_fprintf)(FILE *f, const char *fmt, ...), 2537 int flags) 2538{ 2539 int i; 2540 union { 2541 uint32_t i; 2542 float s; 2543 } s0, s1; 2544 CPU_DoubleU d; 2545 uint32_t psr; 2546 2547 for(i=0;i<16;i++) { 2548 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]); 2549 if ((i % 4) == 3) 2550 cpu_fprintf(f, "\n"); 2551 else 2552 cpu_fprintf(f, " "); 2553 } 2554 psr = cpsr_read(env); 2555 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d %x\n", 2556 psr, 2557 psr & (1 << 31) ? 'N' : '-', 2558 psr & (1 << 30) ? 'Z' : '-', 2559 psr & (1 << 29) ? 'C' : '-', 2560 psr & (1 << 28) ? 'V' : '-', 2561 psr & CPSR_T ? 'T' : 'A', 2562 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26); 2563 2564 for (i = 0; i < 16; i++) { 2565 d.d = env->vfp.regs[i]; 2566 s0.i = d.l.lower; 2567 s1.i = d.l.upper; 2568 cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n", 2569 i * 2, (int)s0.i, s0.s, 2570 i * 2 + 1, (int)s0.i, s0.s, 2571 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower, 2572 d.d); 2573 } 2574 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); 2575} 2576 2577