|
|
1.1 ! root 1: /* ! 2: * ARM micro operations ! 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 "exec.h" ! 22: ! 23: #define REGNAME r0 ! 24: #define REG (env->regs[0]) ! 25: #include "op_template.h" ! 26: ! 27: #define REGNAME r1 ! 28: #define REG (env->regs[1]) ! 29: #include "op_template.h" ! 30: ! 31: #define REGNAME r2 ! 32: #define REG (env->regs[2]) ! 33: #include "op_template.h" ! 34: ! 35: #define REGNAME r3 ! 36: #define REG (env->regs[3]) ! 37: #include "op_template.h" ! 38: ! 39: #define REGNAME r4 ! 40: #define REG (env->regs[4]) ! 41: #include "op_template.h" ! 42: ! 43: #define REGNAME r5 ! 44: #define REG (env->regs[5]) ! 45: #include "op_template.h" ! 46: ! 47: #define REGNAME r6 ! 48: #define REG (env->regs[6]) ! 49: #include "op_template.h" ! 50: ! 51: #define REGNAME r7 ! 52: #define REG (env->regs[7]) ! 53: #include "op_template.h" ! 54: ! 55: #define REGNAME r8 ! 56: #define REG (env->regs[8]) ! 57: #include "op_template.h" ! 58: ! 59: #define REGNAME r9 ! 60: #define REG (env->regs[9]) ! 61: #include "op_template.h" ! 62: ! 63: #define REGNAME r10 ! 64: #define REG (env->regs[10]) ! 65: #include "op_template.h" ! 66: ! 67: #define REGNAME r11 ! 68: #define REG (env->regs[11]) ! 69: #include "op_template.h" ! 70: ! 71: #define REGNAME r12 ! 72: #define REG (env->regs[12]) ! 73: #include "op_template.h" ! 74: ! 75: #define REGNAME r13 ! 76: #define REG (env->regs[13]) ! 77: #include "op_template.h" ! 78: ! 79: #define REGNAME r14 ! 80: #define REG (env->regs[14]) ! 81: #include "op_template.h" ! 82: ! 83: #define REGNAME r15 ! 84: #define REG (env->regs[15]) ! 85: #define SET_REG(x) REG = x & ~(uint32_t)1 ! 86: #include "op_template.h" ! 87: ! 88: void OPPROTO op_bx_T0(void) ! 89: { ! 90: env->regs[15] = T0 & ~(uint32_t)1; ! 91: env->thumb = (T0 & 1) != 0; ! 92: } ! 93: ! 94: void OPPROTO op_movl_T0_0(void) ! 95: { ! 96: T0 = 0; ! 97: } ! 98: ! 99: void OPPROTO op_movl_T0_im(void) ! 100: { ! 101: T0 = PARAM1; ! 102: } ! 103: ! 104: void OPPROTO op_movl_T1_im(void) ! 105: { ! 106: T1 = PARAM1; ! 107: } ! 108: ! 109: void OPPROTO op_mov_CF_T1(void) ! 110: { ! 111: env->CF = ((uint32_t)T1) >> 31; ! 112: } ! 113: ! 114: void OPPROTO op_movl_T2_im(void) ! 115: { ! 116: T2 = PARAM1; ! 117: } ! 118: ! 119: void OPPROTO op_addl_T1_im(void) ! 120: { ! 121: T1 += PARAM1; ! 122: } ! 123: ! 124: void OPPROTO op_addl_T1_T2(void) ! 125: { ! 126: T1 += T2; ! 127: } ! 128: ! 129: void OPPROTO op_subl_T1_T2(void) ! 130: { ! 131: T1 -= T2; ! 132: } ! 133: ! 134: void OPPROTO op_addl_T0_T1(void) ! 135: { ! 136: T0 += T1; ! 137: } ! 138: ! 139: void OPPROTO op_addl_T0_T1_cc(void) ! 140: { ! 141: unsigned int src1; ! 142: src1 = T0; ! 143: T0 += T1; ! 144: env->NZF = T0; ! 145: env->CF = T0 < src1; ! 146: env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0); ! 147: } ! 148: ! 149: void OPPROTO op_adcl_T0_T1(void) ! 150: { ! 151: T0 += T1 + env->CF; ! 152: } ! 153: ! 154: void OPPROTO op_adcl_T0_T1_cc(void) ! 155: { ! 156: unsigned int src1; ! 157: src1 = T0; ! 158: if (!env->CF) { ! 159: T0 += T1; ! 160: env->CF = T0 < src1; ! 161: } else { ! 162: T0 += T1 + 1; ! 163: env->CF = T0 <= src1; ! 164: } ! 165: env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0); ! 166: env->NZF = T0; ! 167: FORCE_RET(); ! 168: } ! 169: ! 170: #define OPSUB(sub, sbc, res, T0, T1) \ ! 171: \ ! 172: void OPPROTO op_ ## sub ## l_T0_T1(void) \ ! 173: { \ ! 174: res = T0 - T1; \ ! 175: } \ ! 176: \ ! 177: void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \ ! 178: { \ ! 179: unsigned int src1; \ ! 180: src1 = T0; \ ! 181: T0 -= T1; \ ! 182: env->NZF = T0; \ ! 183: env->CF = src1 >= T1; \ ! 184: env->VF = (src1 ^ T1) & (src1 ^ T0); \ ! 185: res = T0; \ ! 186: } \ ! 187: \ ! 188: void OPPROTO op_ ## sbc ## l_T0_T1(void) \ ! 189: { \ ! 190: res = T0 - T1 + env->CF - 1; \ ! 191: } \ ! 192: \ ! 193: void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \ ! 194: { \ ! 195: unsigned int src1; \ ! 196: src1 = T0; \ ! 197: if (!env->CF) { \ ! 198: T0 = T0 - T1 - 1; \ ! 199: env->CF = src1 > T1; \ ! 200: } else { \ ! 201: T0 = T0 - T1; \ ! 202: env->CF = src1 >= T1; \ ! 203: } \ ! 204: env->VF = (src1 ^ T1) & (src1 ^ T0); \ ! 205: env->NZF = T0; \ ! 206: res = T0; \ ! 207: FORCE_RET(); \ ! 208: } ! 209: ! 210: OPSUB(sub, sbc, T0, T0, T1) ! 211: ! 212: OPSUB(rsb, rsc, T0, T1, T0) ! 213: ! 214: void OPPROTO op_andl_T0_T1(void) ! 215: { ! 216: T0 &= T1; ! 217: } ! 218: ! 219: void OPPROTO op_xorl_T0_T1(void) ! 220: { ! 221: T0 ^= T1; ! 222: } ! 223: ! 224: void OPPROTO op_orl_T0_T1(void) ! 225: { ! 226: T0 |= T1; ! 227: } ! 228: ! 229: void OPPROTO op_bicl_T0_T1(void) ! 230: { ! 231: T0 &= ~T1; ! 232: } ! 233: ! 234: void OPPROTO op_notl_T1(void) ! 235: { ! 236: T1 = ~T1; ! 237: } ! 238: ! 239: void OPPROTO op_logic_T0_cc(void) ! 240: { ! 241: env->NZF = T0; ! 242: } ! 243: ! 244: void OPPROTO op_logic_T1_cc(void) ! 245: { ! 246: env->NZF = T1; ! 247: } ! 248: ! 249: #define EIP (env->regs[15]) ! 250: ! 251: void OPPROTO op_test_eq(void) ! 252: { ! 253: if (env->NZF == 0) ! 254: GOTO_LABEL_PARAM(1);; ! 255: FORCE_RET(); ! 256: } ! 257: ! 258: void OPPROTO op_test_ne(void) ! 259: { ! 260: if (env->NZF != 0) ! 261: GOTO_LABEL_PARAM(1);; ! 262: FORCE_RET(); ! 263: } ! 264: ! 265: void OPPROTO op_test_cs(void) ! 266: { ! 267: if (env->CF != 0) ! 268: GOTO_LABEL_PARAM(1); ! 269: FORCE_RET(); ! 270: } ! 271: ! 272: void OPPROTO op_test_cc(void) ! 273: { ! 274: if (env->CF == 0) ! 275: GOTO_LABEL_PARAM(1); ! 276: FORCE_RET(); ! 277: } ! 278: ! 279: void OPPROTO op_test_mi(void) ! 280: { ! 281: if ((env->NZF & 0x80000000) != 0) ! 282: GOTO_LABEL_PARAM(1); ! 283: FORCE_RET(); ! 284: } ! 285: ! 286: void OPPROTO op_test_pl(void) ! 287: { ! 288: if ((env->NZF & 0x80000000) == 0) ! 289: GOTO_LABEL_PARAM(1); ! 290: FORCE_RET(); ! 291: } ! 292: ! 293: void OPPROTO op_test_vs(void) ! 294: { ! 295: if ((env->VF & 0x80000000) != 0) ! 296: GOTO_LABEL_PARAM(1); ! 297: FORCE_RET(); ! 298: } ! 299: ! 300: void OPPROTO op_test_vc(void) ! 301: { ! 302: if ((env->VF & 0x80000000) == 0) ! 303: GOTO_LABEL_PARAM(1); ! 304: FORCE_RET(); ! 305: } ! 306: ! 307: void OPPROTO op_test_hi(void) ! 308: { ! 309: if (env->CF != 0 && env->NZF != 0) ! 310: GOTO_LABEL_PARAM(1); ! 311: FORCE_RET(); ! 312: } ! 313: ! 314: void OPPROTO op_test_ls(void) ! 315: { ! 316: if (env->CF == 0 || env->NZF == 0) ! 317: GOTO_LABEL_PARAM(1); ! 318: FORCE_RET(); ! 319: } ! 320: ! 321: void OPPROTO op_test_ge(void) ! 322: { ! 323: if (((env->VF ^ env->NZF) & 0x80000000) == 0) ! 324: GOTO_LABEL_PARAM(1); ! 325: FORCE_RET(); ! 326: } ! 327: ! 328: void OPPROTO op_test_lt(void) ! 329: { ! 330: if (((env->VF ^ env->NZF) & 0x80000000) != 0) ! 331: GOTO_LABEL_PARAM(1); ! 332: FORCE_RET(); ! 333: } ! 334: ! 335: void OPPROTO op_test_gt(void) ! 336: { ! 337: if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0) ! 338: GOTO_LABEL_PARAM(1); ! 339: FORCE_RET(); ! 340: } ! 341: ! 342: void OPPROTO op_test_le(void) ! 343: { ! 344: if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0) ! 345: GOTO_LABEL_PARAM(1); ! 346: FORCE_RET(); ! 347: } ! 348: ! 349: void OPPROTO op_jmp0(void) ! 350: { ! 351: JUMP_TB(op_jmp0, PARAM1, 0, PARAM2); ! 352: } ! 353: ! 354: void OPPROTO op_jmp1(void) ! 355: { ! 356: JUMP_TB(op_jmp1, PARAM1, 1, PARAM2); ! 357: } ! 358: ! 359: void OPPROTO op_exit_tb(void) ! 360: { ! 361: EXIT_TB(); ! 362: } ! 363: ! 364: void OPPROTO op_movl_T0_psr(void) ! 365: { ! 366: T0 = compute_cpsr(); ! 367: } ! 368: ! 369: /* NOTE: N = 1 and Z = 1 cannot be stored currently */ ! 370: void OPPROTO op_movl_psr_T0(void) ! 371: { ! 372: unsigned int psr; ! 373: psr = T0; ! 374: env->CF = (psr >> 29) & 1; ! 375: env->NZF = (psr & 0xc0000000) ^ 0x40000000; ! 376: env->VF = (psr << 3) & 0x80000000; ! 377: /* for user mode we do not update other state info */ ! 378: } ! 379: ! 380: void OPPROTO op_mul_T0_T1(void) ! 381: { ! 382: T0 = T0 * T1; ! 383: } ! 384: ! 385: /* 64 bit unsigned mul */ ! 386: void OPPROTO op_mull_T0_T1(void) ! 387: { ! 388: uint64_t res; ! 389: res = (uint64_t)T0 * (uint64_t)T1; ! 390: T1 = res >> 32; ! 391: T0 = res; ! 392: } ! 393: ! 394: /* 64 bit signed mul */ ! 395: void OPPROTO op_imull_T0_T1(void) ! 396: { ! 397: uint64_t res; ! 398: res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); ! 399: T1 = res >> 32; ! 400: T0 = res; ! 401: } ! 402: ! 403: /* 48 bit signed mul, top 32 bits */ ! 404: void OPPROTO op_imulw_T0_T1(void) ! 405: { ! 406: uint64_t res; ! 407: res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); ! 408: T0 = res >> 16; ! 409: } ! 410: ! 411: void OPPROTO op_addq_T0_T1(void) ! 412: { ! 413: uint64_t res; ! 414: res = ((uint64_t)T1 << 32) | T0; ! 415: res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]); ! 416: T1 = res >> 32; ! 417: T0 = res; ! 418: } ! 419: ! 420: void OPPROTO op_addq_lo_T0_T1(void) ! 421: { ! 422: uint64_t res; ! 423: res = ((uint64_t)T1 << 32) | T0; ! 424: res += (uint64_t)(env->regs[PARAM1]); ! 425: T1 = res >> 32; ! 426: T0 = res; ! 427: } ! 428: ! 429: void OPPROTO op_logicq_cc(void) ! 430: { ! 431: env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0); ! 432: } ! 433: ! 434: /* memory access */ ! 435: ! 436: void OPPROTO op_ldub_T0_T1(void) ! 437: { ! 438: T0 = ldub((void *)T1); ! 439: } ! 440: ! 441: void OPPROTO op_ldsb_T0_T1(void) ! 442: { ! 443: T0 = ldsb((void *)T1); ! 444: } ! 445: ! 446: void OPPROTO op_lduw_T0_T1(void) ! 447: { ! 448: T0 = lduw((void *)T1); ! 449: } ! 450: ! 451: void OPPROTO op_ldsw_T0_T1(void) ! 452: { ! 453: T0 = ldsw((void *)T1); ! 454: } ! 455: ! 456: void OPPROTO op_ldl_T0_T1(void) ! 457: { ! 458: T0 = ldl((void *)T1); ! 459: } ! 460: ! 461: void OPPROTO op_stb_T0_T1(void) ! 462: { ! 463: stb((void *)T1, T0); ! 464: } ! 465: ! 466: void OPPROTO op_stw_T0_T1(void) ! 467: { ! 468: stw((void *)T1, T0); ! 469: } ! 470: ! 471: void OPPROTO op_stl_T0_T1(void) ! 472: { ! 473: stl((void *)T1, T0); ! 474: } ! 475: ! 476: void OPPROTO op_swpb_T0_T1(void) ! 477: { ! 478: int tmp; ! 479: ! 480: cpu_lock(); ! 481: tmp = ldub((void *)T1); ! 482: stb((void *)T1, T0); ! 483: T0 = tmp; ! 484: cpu_unlock(); ! 485: } ! 486: ! 487: void OPPROTO op_swpl_T0_T1(void) ! 488: { ! 489: int tmp; ! 490: ! 491: cpu_lock(); ! 492: tmp = ldl((void *)T1); ! 493: stl((void *)T1, T0); ! 494: T0 = tmp; ! 495: cpu_unlock(); ! 496: } ! 497: ! 498: /* shifts */ ! 499: ! 500: /* T1 based */ ! 501: ! 502: void OPPROTO op_shll_T1_im(void) ! 503: { ! 504: T1 = T1 << PARAM1; ! 505: } ! 506: ! 507: void OPPROTO op_shrl_T1_im(void) ! 508: { ! 509: T1 = (uint32_t)T1 >> PARAM1; ! 510: } ! 511: ! 512: void OPPROTO op_shrl_T1_0(void) ! 513: { ! 514: T1 = 0; ! 515: } ! 516: ! 517: void OPPROTO op_sarl_T1_im(void) ! 518: { ! 519: T1 = (int32_t)T1 >> PARAM1; ! 520: } ! 521: ! 522: void OPPROTO op_sarl_T1_0(void) ! 523: { ! 524: T1 = (int32_t)T1 >> 31; ! 525: } ! 526: ! 527: void OPPROTO op_rorl_T1_im(void) ! 528: { ! 529: int shift; ! 530: shift = PARAM1; ! 531: T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); ! 532: } ! 533: ! 534: void OPPROTO op_rrxl_T1(void) ! 535: { ! 536: T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31); ! 537: } ! 538: ! 539: /* T1 based, set C flag */ ! 540: void OPPROTO op_shll_T1_im_cc(void) ! 541: { ! 542: env->CF = (T1 >> (32 - PARAM1)) & 1; ! 543: T1 = T1 << PARAM1; ! 544: } ! 545: ! 546: void OPPROTO op_shrl_T1_im_cc(void) ! 547: { ! 548: env->CF = (T1 >> (PARAM1 - 1)) & 1; ! 549: T1 = (uint32_t)T1 >> PARAM1; ! 550: } ! 551: ! 552: void OPPROTO op_shrl_T1_0_cc(void) ! 553: { ! 554: env->CF = (T1 >> 31) & 1; ! 555: T1 = 0; ! 556: } ! 557: ! 558: void OPPROTO op_sarl_T1_im_cc(void) ! 559: { ! 560: env->CF = (T1 >> (PARAM1 - 1)) & 1; ! 561: T1 = (int32_t)T1 >> PARAM1; ! 562: } ! 563: ! 564: void OPPROTO op_sarl_T1_0_cc(void) ! 565: { ! 566: env->CF = (T1 >> 31) & 1; ! 567: T1 = (int32_t)T1 >> 31; ! 568: } ! 569: ! 570: void OPPROTO op_rorl_T1_im_cc(void) ! 571: { ! 572: int shift; ! 573: shift = PARAM1; ! 574: env->CF = (T1 >> (shift - 1)) & 1; ! 575: T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); ! 576: } ! 577: ! 578: void OPPROTO op_rrxl_T1_cc(void) ! 579: { ! 580: uint32_t c; ! 581: c = T1 & 1; ! 582: T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31); ! 583: env->CF = c; ! 584: } ! 585: ! 586: /* T2 based */ ! 587: void OPPROTO op_shll_T2_im(void) ! 588: { ! 589: T2 = T2 << PARAM1; ! 590: } ! 591: ! 592: void OPPROTO op_shrl_T2_im(void) ! 593: { ! 594: T2 = (uint32_t)T2 >> PARAM1; ! 595: } ! 596: ! 597: void OPPROTO op_shrl_T2_0(void) ! 598: { ! 599: T2 = 0; ! 600: } ! 601: ! 602: void OPPROTO op_sarl_T2_im(void) ! 603: { ! 604: T2 = (int32_t)T2 >> PARAM1; ! 605: } ! 606: ! 607: void OPPROTO op_sarl_T2_0(void) ! 608: { ! 609: T2 = (int32_t)T2 >> 31; ! 610: } ! 611: ! 612: void OPPROTO op_rorl_T2_im(void) ! 613: { ! 614: int shift; ! 615: shift = PARAM1; ! 616: T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift)); ! 617: } ! 618: ! 619: void OPPROTO op_rrxl_T2(void) ! 620: { ! 621: T2 = ((uint32_t)T2 >> 1) | ((uint32_t)env->CF << 31); ! 622: } ! 623: ! 624: /* T1 based, use T0 as shift count */ ! 625: ! 626: void OPPROTO op_shll_T1_T0(void) ! 627: { ! 628: int shift; ! 629: shift = T0 & 0xff; ! 630: if (shift >= 32) ! 631: T1 = 0; ! 632: else ! 633: T1 = T1 << shift; ! 634: FORCE_RET(); ! 635: } ! 636: ! 637: void OPPROTO op_shrl_T1_T0(void) ! 638: { ! 639: int shift; ! 640: shift = T0 & 0xff; ! 641: if (shift >= 32) ! 642: T1 = 0; ! 643: else ! 644: T1 = (uint32_t)T1 >> shift; ! 645: FORCE_RET(); ! 646: } ! 647: ! 648: void OPPROTO op_sarl_T1_T0(void) ! 649: { ! 650: int shift; ! 651: shift = T0 & 0xff; ! 652: if (shift >= 32) ! 653: shift = 31; ! 654: T1 = (int32_t)T1 >> shift; ! 655: } ! 656: ! 657: void OPPROTO op_rorl_T1_T0(void) ! 658: { ! 659: int shift; ! 660: shift = T0 & 0x1f; ! 661: if (shift) { ! 662: T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); ! 663: } ! 664: FORCE_RET(); ! 665: } ! 666: ! 667: /* T1 based, use T0 as shift count and compute CF */ ! 668: ! 669: void OPPROTO op_shll_T1_T0_cc(void) ! 670: { ! 671: int shift; ! 672: shift = T0 & 0xff; ! 673: if (shift >= 32) { ! 674: if (shift == 32) ! 675: env->CF = T1 & 1; ! 676: else ! 677: env->CF = 0; ! 678: T1 = 0; ! 679: } else if (shift != 0) { ! 680: env->CF = (T1 >> (32 - shift)) & 1; ! 681: T1 = T1 << shift; ! 682: } ! 683: FORCE_RET(); ! 684: } ! 685: ! 686: void OPPROTO op_shrl_T1_T0_cc(void) ! 687: { ! 688: int shift; ! 689: shift = T0 & 0xff; ! 690: if (shift >= 32) { ! 691: if (shift == 32) ! 692: env->CF = (T1 >> 31) & 1; ! 693: else ! 694: env->CF = 0; ! 695: T1 = 0; ! 696: } else if (shift != 0) { ! 697: env->CF = (T1 >> (shift - 1)) & 1; ! 698: T1 = (uint32_t)T1 >> shift; ! 699: } ! 700: FORCE_RET(); ! 701: } ! 702: ! 703: void OPPROTO op_sarl_T1_T0_cc(void) ! 704: { ! 705: int shift; ! 706: shift = T0 & 0xff; ! 707: if (shift >= 32) { ! 708: env->CF = (T1 >> 31) & 1; ! 709: T1 = (int32_t)T1 >> 31; ! 710: } else { ! 711: env->CF = (T1 >> (shift - 1)) & 1; ! 712: T1 = (int32_t)T1 >> shift; ! 713: } ! 714: FORCE_RET(); ! 715: } ! 716: ! 717: void OPPROTO op_rorl_T1_T0_cc(void) ! 718: { ! 719: int shift1, shift; ! 720: shift1 = T0 & 0xff; ! 721: shift = shift1 & 0x1f; ! 722: if (shift == 0) { ! 723: if (shift1 != 0) ! 724: env->CF = (T1 >> 31) & 1; ! 725: } else { ! 726: env->CF = (T1 >> (shift - 1)) & 1; ! 727: T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); ! 728: } ! 729: FORCE_RET(); ! 730: } ! 731: ! 732: /* misc */ ! 733: void OPPROTO op_clz_T0(void) ! 734: { ! 735: int count; ! 736: for (count = 32; T0 > 0; count--) ! 737: T0 = T0 >> 1; ! 738: T0 = count; ! 739: FORCE_RET(); ! 740: } ! 741: ! 742: void OPPROTO op_sarl_T0_im(void) ! 743: { ! 744: T0 = (int32_t)T0 >> PARAM1; ! 745: } ! 746: ! 747: /* 16->32 Sign extend */ ! 748: void OPPROTO op_sxl_T0(void) ! 749: { ! 750: T0 = (int16_t)T0; ! 751: } ! 752: ! 753: void OPPROTO op_sxl_T1(void) ! 754: { ! 755: T1 = (int16_t)T1; ! 756: } ! 757: ! 758: #define SIGNBIT (uint32_t)0x80000000 ! 759: /* saturating arithmetic */ ! 760: void OPPROTO op_addl_T0_T1_setq(void) ! 761: { ! 762: uint32_t res; ! 763: ! 764: res = T0 + T1; ! 765: if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) ! 766: env->QF = 1; ! 767: ! 768: T0 = res; ! 769: FORCE_RET(); ! 770: } ! 771: ! 772: void OPPROTO op_addl_T0_T1_saturate(void) ! 773: { ! 774: uint32_t res; ! 775: ! 776: res = T0 + T1; ! 777: if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) { ! 778: env->QF = 1; ! 779: if (T0 & SIGNBIT) ! 780: T0 = 0x80000000; ! 781: else ! 782: T0 = 0x7fffffff; ! 783: } ! 784: else ! 785: T0 = res; ! 786: ! 787: FORCE_RET(); ! 788: } ! 789: ! 790: void OPPROTO op_subl_T0_T1_saturate(void) ! 791: { ! 792: uint32_t res; ! 793: ! 794: res = T0 - T1; ! 795: if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) { ! 796: env->QF = 1; ! 797: if (T0 & SIGNBIT) ! 798: T0 = 0x8000000; ! 799: else ! 800: T0 = 0x7fffffff; ! 801: } ! 802: else ! 803: T0 = res; ! 804: ! 805: FORCE_RET(); ! 806: } ! 807: ! 808: void OPPROTO op_double_T1_saturate(void) ! 809: { ! 810: int32_t val; ! 811: ! 812: val = T1; ! 813: if (val >= 0x40000000) { ! 814: T1 = 0x7fffffff; ! 815: env->QF = 1; ! 816: } else if (val <= (int32_t)0xc0000000) { ! 817: T1 = 0x80000000; ! 818: env->QF = 1; ! 819: } else { ! 820: T1 = val << 1; ! 821: } ! 822: FORCE_RET(); ! 823: } ! 824: ! 825: /* thumb shift by immediate */ ! 826: void OPPROTO op_shll_T0_im_thumb(void) ! 827: { ! 828: int shift; ! 829: shift = PARAM1; ! 830: if (shift != 0) { ! 831: env->CF = (T1 >> (32 - shift)) & 1; ! 832: T0 = T0 << shift; ! 833: } ! 834: env->NZF = T0; ! 835: FORCE_RET(); ! 836: } ! 837: ! 838: void OPPROTO op_shrl_T0_im_thumb(void) ! 839: { ! 840: int shift; ! 841: ! 842: shift = PARAM1; ! 843: if (shift == 0) { ! 844: env->CF = ((uint32_t)shift) >> 31; ! 845: T0 = 0; ! 846: } else { ! 847: env->CF = (T0 >> (shift - 1)) & 1; ! 848: T0 = T0 >> shift; ! 849: } ! 850: env->NZF = T0; ! 851: FORCE_RET(); ! 852: } ! 853: ! 854: void OPPROTO op_sarl_T0_im_thumb(void) ! 855: { ! 856: int shift; ! 857: ! 858: shift = PARAM1; ! 859: if (shift == 0) { ! 860: T0 = ((int32_t)T0) >> 31; ! 861: env->CF = T0 & 1; ! 862: } else { ! 863: env->CF = (T0 >> (shift - 1)) & 1; ! 864: T0 = ((int32_t)T0) >> shift; ! 865: } ! 866: env->NZF = T0; ! 867: FORCE_RET(); ! 868: } ! 869: ! 870: /* exceptions */ ! 871: ! 872: void OPPROTO op_swi(void) ! 873: { ! 874: env->exception_index = EXCP_SWI; ! 875: cpu_loop_exit(); ! 876: } ! 877: ! 878: void OPPROTO op_undef_insn(void) ! 879: { ! 880: env->exception_index = EXCP_UDEF; ! 881: cpu_loop_exit(); ! 882: } ! 883: ! 884: void OPPROTO op_debug(void) ! 885: { ! 886: env->exception_index = EXCP_DEBUG; ! 887: cpu_loop_exit(); ! 888: } ! 889: ! 890: /* VFP support. We follow the convention used for VFP instrunctions: ! 891: Single precition routines have a "s" suffix, double precision a ! 892: "d" suffix. */ ! 893: ! 894: #define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void) ! 895: ! 896: #define VFP_BINOP(name) \ ! 897: VFP_OP(name, s) \ ! 898: { \ ! 899: FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status); \ ! 900: } \ ! 901: VFP_OP(name, d) \ ! 902: { \ ! 903: FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status); \ ! 904: } ! 905: VFP_BINOP(add) ! 906: VFP_BINOP(sub) ! 907: VFP_BINOP(mul) ! 908: VFP_BINOP(div) ! 909: #undef VFP_BINOP ! 910: ! 911: #define VFP_HELPER(name) \ ! 912: VFP_OP(name, s) \ ! 913: { \ ! 914: do_vfp_##name##s(); \ ! 915: } \ ! 916: VFP_OP(name, d) \ ! 917: { \ ! 918: do_vfp_##name##d(); \ ! 919: } ! 920: VFP_HELPER(abs) ! 921: VFP_HELPER(sqrt) ! 922: VFP_HELPER(cmp) ! 923: VFP_HELPER(cmpe) ! 924: #undef VFP_HELPER ! 925: ! 926: /* XXX: Will this do the right thing for NANs. Should invert the signbit ! 927: without looking at the rest of the value. */ ! 928: VFP_OP(neg, s) ! 929: { ! 930: FT0s = float32_chs(FT0s); ! 931: } ! 932: ! 933: VFP_OP(neg, d) ! 934: { ! 935: FT0d = float64_chs(FT0d); ! 936: } ! 937: ! 938: VFP_OP(F1_ld0, s) ! 939: { ! 940: union { ! 941: uint32_t i; ! 942: float32 s; ! 943: } v; ! 944: v.i = 0; ! 945: FT1s = v.s; ! 946: } ! 947: ! 948: VFP_OP(F1_ld0, d) ! 949: { ! 950: union { ! 951: uint64_t i; ! 952: float64 d; ! 953: } v; ! 954: v.i = 0; ! 955: FT1d = v.d; ! 956: } ! 957: ! 958: /* Helper routines to perform bitwise copies between float and int. */ ! 959: static inline float32 vfp_itos(uint32_t i) ! 960: { ! 961: union { ! 962: uint32_t i; ! 963: float32 s; ! 964: } v; ! 965: ! 966: v.i = i; ! 967: return v.s; ! 968: } ! 969: ! 970: static inline uint32_t vfp_stoi(float32 s) ! 971: { ! 972: union { ! 973: uint32_t i; ! 974: float32 s; ! 975: } v; ! 976: ! 977: v.s = s; ! 978: return v.i; ! 979: } ! 980: ! 981: /* Integer to float conversion. */ ! 982: VFP_OP(uito, s) ! 983: { ! 984: FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status); ! 985: } ! 986: ! 987: VFP_OP(uito, d) ! 988: { ! 989: FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status); ! 990: } ! 991: ! 992: VFP_OP(sito, s) ! 993: { ! 994: FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status); ! 995: } ! 996: ! 997: VFP_OP(sito, d) ! 998: { ! 999: FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status); ! 1000: } ! 1001: ! 1002: /* Float to integer conversion. */ ! 1003: VFP_OP(toui, s) ! 1004: { ! 1005: FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status)); ! 1006: } ! 1007: ! 1008: VFP_OP(toui, d) ! 1009: { ! 1010: FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status)); ! 1011: } ! 1012: ! 1013: VFP_OP(tosi, s) ! 1014: { ! 1015: FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status)); ! 1016: } ! 1017: ! 1018: VFP_OP(tosi, d) ! 1019: { ! 1020: FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status)); ! 1021: } ! 1022: ! 1023: /* TODO: Set rounding mode properly. */ ! 1024: VFP_OP(touiz, s) ! 1025: { ! 1026: FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status)); ! 1027: } ! 1028: ! 1029: VFP_OP(touiz, d) ! 1030: { ! 1031: FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status)); ! 1032: } ! 1033: ! 1034: VFP_OP(tosiz, s) ! 1035: { ! 1036: FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status)); ! 1037: } ! 1038: ! 1039: VFP_OP(tosiz, d) ! 1040: { ! 1041: FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status)); ! 1042: } ! 1043: ! 1044: /* floating point conversion */ ! 1045: VFP_OP(fcvtd, s) ! 1046: { ! 1047: FT0d = float32_to_float64(FT0s, &env->vfp.fp_status); ! 1048: } ! 1049: ! 1050: VFP_OP(fcvts, d) ! 1051: { ! 1052: FT0s = float64_to_float32(FT0d, &env->vfp.fp_status); ! 1053: } ! 1054: ! 1055: /* Get and Put values from registers. */ ! 1056: VFP_OP(getreg_F0, d) ! 1057: { ! 1058: FT0d = *(float64 *)((char *) env + PARAM1); ! 1059: } ! 1060: ! 1061: VFP_OP(getreg_F0, s) ! 1062: { ! 1063: FT0s = *(float32 *)((char *) env + PARAM1); ! 1064: } ! 1065: ! 1066: VFP_OP(getreg_F1, d) ! 1067: { ! 1068: FT1d = *(float64 *)((char *) env + PARAM1); ! 1069: } ! 1070: ! 1071: VFP_OP(getreg_F1, s) ! 1072: { ! 1073: FT1s = *(float32 *)((char *) env + PARAM1); ! 1074: } ! 1075: ! 1076: VFP_OP(setreg_F0, d) ! 1077: { ! 1078: *(float64 *)((char *) env + PARAM1) = FT0d; ! 1079: } ! 1080: ! 1081: VFP_OP(setreg_F0, s) ! 1082: { ! 1083: *(float32 *)((char *) env + PARAM1) = FT0s; ! 1084: } ! 1085: ! 1086: void OPPROTO op_vfp_movl_T0_fpscr(void) ! 1087: { ! 1088: do_vfp_get_fpscr (); ! 1089: } ! 1090: ! 1091: void OPPROTO op_vfp_movl_T0_fpscr_flags(void) ! 1092: { ! 1093: T0 = env->vfp.fpscr & (0xf << 28); ! 1094: } ! 1095: ! 1096: void OPPROTO op_vfp_movl_fpscr_T0(void) ! 1097: { ! 1098: do_vfp_set_fpscr(); ! 1099: } ! 1100: ! 1101: /* Move between FT0s to T0 */ ! 1102: void OPPROTO op_vfp_mrs(void) ! 1103: { ! 1104: T0 = vfp_stoi(FT0s); ! 1105: } ! 1106: ! 1107: void OPPROTO op_vfp_msr(void) ! 1108: { ! 1109: FT0s = vfp_itos(T0); ! 1110: } ! 1111: ! 1112: /* Move between FT0d and {T0,T1} */ ! 1113: void OPPROTO op_vfp_mrrd(void) ! 1114: { ! 1115: CPU_DoubleU u; ! 1116: ! 1117: u.d = FT0d; ! 1118: T0 = u.l.lower; ! 1119: T1 = u.l.upper; ! 1120: } ! 1121: ! 1122: void OPPROTO op_vfp_mdrr(void) ! 1123: { ! 1124: CPU_DoubleU u; ! 1125: ! 1126: u.l.lower = T0; ! 1127: u.l.upper = T1; ! 1128: FT0d = u.d; ! 1129: } ! 1130: ! 1131: /* Floating point load/store. Address is in T1 */ ! 1132: void OPPROTO op_vfp_lds(void) ! 1133: { ! 1134: FT0s = ldfl((void *)T1); ! 1135: } ! 1136: ! 1137: void OPPROTO op_vfp_ldd(void) ! 1138: { ! 1139: FT0d = ldfq((void *)T1); ! 1140: } ! 1141: ! 1142: void OPPROTO op_vfp_sts(void) ! 1143: { ! 1144: stfl((void *)T1, FT0s); ! 1145: } ! 1146: ! 1147: void OPPROTO op_vfp_std(void) ! 1148: { ! 1149: stfq((void *)T1, FT0d); ! 1150: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.