Changeset 99798 in webkit
- Timestamp:
- Nov 9, 2011 6:32:49 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r99788 r99798 1 2011-11-09 Gavin Barraclough <barraclough@apple.com> 2 3 Renovate ARMv7 assembler/macro-assembler 4 https://bugs.webkit.org/show_bug.cgi?id=71982 5 6 Reviewed by Geoff Garen. 7 8 ARMv7Assembler: 9 * add support for strb (byte stores) 10 * rename the VMOV_CtoS opcodes (there are currently backwards!) 11 * add support for adc (add with carry) 12 * add support for vsqrt, vabs 13 * add support for vmov (between FPRs, and to/from GPR pairs). 14 * remove '_F64' postfixes from instructions (these aren't helpful, functions can already be distinguished by their signatures). 15 * rename vcvt_F64_S32 to vcvt_signedToFloatingPoint, the prior postfix was unhelpful in failing to distinguish the types (S32 indicates a single precision register, but the type could be float, int32, or uint32). 16 * rename vcvtr_S32_F64 to vcvt_floatingPointToSigned, as for previous, also vcvtr was the incorrect name for the operation (the emitted instruction truncates). 17 18 MacroAssemblerARMv7: 19 * add 3-operand versions of and32, lshift32, or32, rshift32, urshift32, sub32, xor32, 20 * add store8, and store32 imm to base-index. 21 * fix load32WithCompactAddressOffsetPatch to work for all gprs (the fix is a little kludgy but functional; to do better we'll have to also fix the repatching code). 22 * Update supportsFloating* flags (all features now supported). 23 * add moveDouble, storeDouble to absolute address, addDouble to absolute address 24 * add 3-operand double operations. 25 * implement sqrtDouble/absDouble 26 * add branchTruncateDoubleToInt32, implement truncateDoubleToInt32 27 * move should do nothing if src == dest 28 * branchTest8-on-memory can be implemented in terms of branchTest32-on-register (branchTest8-on-register has been removed). 29 * add 3-operand branchAdd32, branchSub32, also branchAdd32 absolute address. 30 1 31 2011-11-09 Gavin Barraclough <barraclough@apple.com> 2 32 -
trunk/Source/JavaScriptCore/assembler/ARMv7Assembler.h
r95901 r99798 535 535 OP_BX = 0x4700, 536 536 OP_STR_reg_T1 = 0x5000, 537 OP_STRB_reg_T1 = 0x5400, 537 538 OP_LDR_reg_T1 = 0x5800, 538 539 OP_LDRH_reg_T1 = 0x5A00, … … 540 541 OP_STR_imm_T1 = 0x6000, 541 542 OP_LDR_imm_T1 = 0x6800, 543 OP_STRB_imm_T1 = 0x7000, 542 544 OP_LDRB_imm_T1 = 0x7800, 543 545 OP_LDRH_imm_T1 = 0x8800, … … 570 572 OP_SUB_S_reg_T2 = 0xEBB0, 571 573 OP_CMP_reg_T2 = 0xEBB0, 574 OP_VMOV_CtoD = 0xEC00, 575 OP_VMOV_DtoC = 0xEC10, 572 576 OP_VSTR = 0xED00, 573 577 OP_VLDR = 0xED10, 574 OP_VMOV_ StoC= 0xEE00,575 OP_VMOV_ CtoS= 0xEE10,578 OP_VMOV_CtoS = 0xEE00, 579 OP_VMOV_StoC = 0xEE10, 576 580 OP_VMUL_T2 = 0xEE20, 577 581 OP_VADD_T2 = 0xEE30, 578 582 OP_VSUB_T2 = 0xEE30, 579 583 OP_VDIV = 0xEE80, 584 OP_VABS_T2 = 0xEEB0, 580 585 OP_VCMP = 0xEEB0, 581 586 OP_VCVT_FPIVFP = 0xEEB0, 587 OP_VMOV_T2 = 0xEEB0, 582 588 OP_VMOV_IMM_T2 = 0xEEB0, 583 589 OP_VMRS = 0xEEB0, 590 OP_VSQRT_T1 = 0xEEB0, 584 591 OP_B_T3a = 0xF000, 585 592 OP_B_T4a = 0xF000, … … 593 600 OP_ADD_S_imm_T3 = 0xF110, 594 601 OP_CMN_imm = 0xF110, 602 OP_ADC_imm = 0xF140, 595 603 OP_SUB_imm_T3 = 0xF1A0, 596 604 OP_SUB_S_imm_T3 = 0xF1B0, … … 603 611 OP_UBFX_T1 = 0xF3C0, 604 612 OP_NOP_T2a = 0xF3AF, 613 OP_STRB_imm_T3 = 0xF800, 614 OP_STRB_reg_T2 = 0xF800, 605 615 OP_LDRB_imm_T3 = 0xF810, 606 616 OP_LDRB_reg_T2 = 0xF810, … … 611 621 OP_LDR_imm_T4 = 0xF850, 612 622 OP_LDR_reg_T2 = 0xF850, 623 OP_STRB_imm_T2 = 0xF880, 613 624 OP_LDRB_imm_T2 = 0xF890, 614 625 OP_LDRH_imm_T2 = 0xF8B0, … … 628 639 OP_VLDRb = 0x0A00, 629 640 OP_VMOV_IMM_T2b = 0x0A00, 641 OP_VMOV_T2b = 0x0A40, 630 642 OP_VMUL_T2b = 0x0A00, 631 643 OP_VSTRb = 0x0A00, 644 OP_VMOV_StoCb = 0x0A10, 632 645 OP_VMOV_CtoSb = 0x0A10, 633 OP_VMOV_StoCb = 0x0A10, 646 OP_VMOV_DtoCb = 0x0A10, 647 OP_VMOV_CtoDb = 0x0A10, 634 648 OP_VMRSb = 0x0A10, 649 OP_VABS_T2b = 0x0A40, 635 650 OP_VCMPb = 0x0A40, 636 651 OP_VCVT_FPIVFPb = 0x0A40, 637 652 OP_VSUB_T2b = 0x0A40, 653 OP_VSQRT_T1b = 0x0A40, 638 654 OP_NOP_T2b = 0x8000, 639 655 OP_B_T3b = 0x8000, … … 701 717 public: 702 718 719 void adc(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 720 { 721 // Rd can only be SP if Rn is also SP. 722 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 723 ASSERT(rd != ARMRegisters::pc); 724 ASSERT(rn != ARMRegisters::pc); 725 ASSERT(imm.isEncodedImm()); 726 727 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADC_imm, rn, rd, imm); 728 } 729 703 730 void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 704 731 { … … 862 889 } 863 890 864 void bkpt(uint8_t imm =0)891 void bkpt(uint8_t imm = 0) 865 892 { 866 893 m_formatter.oneWordOp8Imm8(OP_BKPT, imm); … … 1355 1382 } 1356 1383 1384 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. 1385 ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm) 1386 { 1387 ASSERT(rt != ARMRegisters::pc); 1388 ASSERT(rn != ARMRegisters::pc); 1389 ASSERT(imm.isUInt12()); 1390 1391 if (!((rt | rn) & 8) && imm.isUInt7()) 1392 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STRB_imm_T1, imm.getUInt7() >> 2, rn, rt); 1393 else 1394 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRB_imm_T2, rn, rt, imm.getUInt12()); 1395 } 1396 1397 // If index is set, this is a regular offset or a pre-indexed store; 1398 // if index is not set then is is a post-index store. 1399 // 1400 // If wback is set rn is updated - this is a pre or post index store, 1401 // if wback is not set this is a regular offset memory access. 1402 // 1403 // (-255 <= offset <= 255) 1404 // _reg = REG[rn] 1405 // _tmp = _reg + offset 1406 // MEM[index ? _tmp : _reg] = REG[rt] 1407 // if (wback) REG[rn] = _tmp 1408 ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback) 1409 { 1410 ASSERT(rt != ARMRegisters::pc); 1411 ASSERT(rn != ARMRegisters::pc); 1412 ASSERT(index || wback); 1413 ASSERT(!wback | (rt != rn)); 1414 1415 bool add = true; 1416 if (offset < 0) { 1417 add = false; 1418 offset = -offset; 1419 } 1420 ASSERT((offset & ~0xff) == 0); 1421 1422 offset |= (wback << 8); 1423 offset |= (add << 9); 1424 offset |= (index << 10); 1425 offset |= (1 << 11); 1426 1427 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRB_imm_T3, rn, rt, offset); 1428 } 1429 1430 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. 1431 ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0) 1432 { 1433 ASSERT(rn != ARMRegisters::pc); 1434 ASSERT(!BadReg(rm)); 1435 ASSERT(shift <= 3); 1436 1437 if (!shift && !((rt | rn | rm) & 8)) 1438 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STRB_reg_T1, rm, rn, rt); 1439 else 1440 m_formatter.twoWordOp12Reg4FourFours(OP_STRB_reg_T2, rn, FourFours(rt, 0, shift, rm)); 1441 } 1442 1357 1443 ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 1358 1444 { … … 1490 1576 } 1491 1577 1492 void vadd _F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)1578 void vadd(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm) 1493 1579 { 1494 1580 m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm); 1495 1581 } 1496 1582 1497 void vcmp _F64(FPDoubleRegisterID rd, FPDoubleRegisterID rm)1583 void vcmp(FPDoubleRegisterID rd, FPDoubleRegisterID rm) 1498 1584 { 1499 1585 m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(4), rd, rm); 1500 1586 } 1501 1587 1502 void vcmpz _F64(FPDoubleRegisterID rd)1588 void vcmpz(FPDoubleRegisterID rd) 1503 1589 { 1504 1590 m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0)); 1505 1591 } 1506 1592 1507 void vcvt_ F64_S32(FPDoubleRegisterID rd, FPSingleRegisterID rm)1593 void vcvt_signedToFloatingPoint(FPDoubleRegisterID rd, FPSingleRegisterID rm) 1508 1594 { 1509 1595 // boolean values are 64bit (toInt, unsigned, roundZero) … … 1511 1597 } 1512 1598 1513 void vcvt r_S32_F64(FPSingleRegisterID rd, FPDoubleRegisterID rm)1599 void vcvt_floatingPointToSigned(FPSingleRegisterID rd, FPDoubleRegisterID rm) 1514 1600 { 1515 1601 // boolean values are 64bit (toInt, unsigned, roundZero) … … 1517 1603 } 1518 1604 1519 void vdiv _F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)1605 void vdiv(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm) 1520 1606 { 1521 1607 m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm); … … 1530 1616 { 1531 1617 ASSERT(!BadReg(rd)); 1532 m_formatter.vfpOp(OP_VMOV_ CtoS, OP_VMOV_CtoSb, false, rn, rd, VFPOperand(0));1618 m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rn, rd, VFPOperand(0)); 1533 1619 } 1534 1620 … … 1536 1622 { 1537 1623 ASSERT(!BadReg(rn)); 1538 m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rd, rn, VFPOperand(0)); 1624 m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rd, rn, VFPOperand(0)); 1625 } 1626 1627 void vmov(RegisterID rd1, RegisterID rd2, FPDoubleRegisterID rn) 1628 { 1629 ASSERT(!BadReg(rd1)); 1630 ASSERT(!BadReg(rd2)); 1631 m_formatter.vfpOp(OP_VMOV_DtoC, OP_VMOV_DtoCb, true, rd2, VFPOperand(rd1 | 16), rn); 1632 } 1633 1634 void vmov(FPDoubleRegisterID rd, RegisterID rn1, RegisterID rn2) 1635 { 1636 ASSERT(!BadReg(rn1)); 1637 ASSERT(!BadReg(rn2)); 1638 m_formatter.vfpOp(OP_VMOV_CtoD, OP_VMOV_CtoDb, true, rn2, VFPOperand(rn1 | 16), rd); 1639 } 1640 1641 void vmov(FPDoubleRegisterID rd, FPDoubleRegisterID rn) 1642 { 1643 m_formatter.vfpOp(OP_VMOV_T2, OP_VMOV_T2b, true, VFPOperand(0), rd, rn); 1539 1644 } 1540 1645 … … 1545 1650 } 1546 1651 1547 void vmul _F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)1652 void vmul(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm) 1548 1653 { 1549 1654 m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm); … … 1555 1660 } 1556 1661 1557 void vsub _F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)1662 void vsub(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm) 1558 1663 { 1559 1664 m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm); 1665 } 1666 1667 void vabs(FPDoubleRegisterID rd, FPDoubleRegisterID rm) 1668 { 1669 m_formatter.vfpOp(OP_VABS_T2, OP_VABS_T2b, true, VFPOperand(16), rd, rm); 1670 } 1671 1672 void vsqrt(FPDoubleRegisterID rd, FPDoubleRegisterID rm) 1673 { 1674 m_formatter.vfpOp(OP_VSQRT_T1, OP_VSQRT_T1b, true, VFPOperand(17), rd, rm); 1560 1675 } 1561 1676 … … 1807 1922 } 1808 1923 1924 #ifndef NDEBUG 1925 unsigned debugOffset() { return m_formatter.debugOffset(); } 1926 #endif 1927 1809 1928 private: 1810 1929 // VFP operations commonly take one or more 5-bit operands, typically representing a … … 1866 1985 op |= 0x10; 1867 1986 } else { 1987 ASSERT(!isRoundZero); 1868 1988 // 'op' field in instruction is isUnsigned 1869 1989 if (!isUnsigned) -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h
r99787 r99798 212 212 } 213 213 214 void and32(RegisterID src, RegisterID dest)215 { 216 m_assembler.ARM_and(dest, dest, src);217 } 218 219 void and32(TrustedImm32 imm, RegisterID dest)214 void and32(RegisterID op1, RegisterID op2, RegisterID dest) 215 { 216 m_assembler.ARM_and(dest, op1, op2); 217 } 218 219 void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) 220 220 { 221 221 ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); 222 222 if (armImm.isValid()) 223 m_assembler.ARM_and(dest, dest, armImm);223 m_assembler.ARM_and(dest, src, armImm); 224 224 else { 225 225 move(imm, dataTempRegister); 226 m_assembler.ARM_and(dest, dest, dataTempRegister); 227 } 226 m_assembler.ARM_and(dest, src, dataTempRegister); 227 } 228 } 229 230 void and32(RegisterID src, RegisterID dest) 231 { 232 and32(dest, src, dest); 233 } 234 235 void and32(TrustedImm32 imm, RegisterID dest) 236 { 237 and32(imm, dest, dest); 228 238 } 229 239 … … 233 243 } 234 244 235 void lshift32(RegisterID s hift_amount, RegisterID dest)245 void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) 236 246 { 237 247 // Clamp the shift to the range 0..31 238 248 ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f); 239 249 ASSERT(armImm.isValid()); 240 m_assembler.ARM_and(dataTempRegister, shift_amount, armImm); 241 242 m_assembler.lsl(dest, dest, dataTempRegister); 250 m_assembler.ARM_and(dataTempRegister, shiftAmount, armImm); 251 252 m_assembler.lsl(dest, src, dataTempRegister); 253 } 254 255 void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) 256 { 257 m_assembler.lsl(dest, src, imm.m_value & 0x1f); 258 } 259 260 void lshift32(RegisterID shiftAmount, RegisterID dest) 261 { 262 lshift32(dest, shiftAmount, dest); 243 263 } 244 264 245 265 void lshift32(TrustedImm32 imm, RegisterID dest) 246 266 { 247 m_assembler.lsl(dest, dest, imm.m_value & 0x1f);267 lshift32(dest, imm, dest); 248 268 } 249 269 … … 276 296 void or32(TrustedImm32 imm, RegisterID dest) 277 297 { 298 or32(imm, dest, dest); 299 } 300 301 void or32(RegisterID op1, RegisterID op2, RegisterID dest) 302 { 303 m_assembler.orr(dest, op1, op2); 304 } 305 306 void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) 307 { 278 308 ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); 279 309 if (armImm.isValid()) 280 m_assembler.orr(dest, dest, armImm);310 m_assembler.orr(dest, src, armImm); 281 311 else { 282 312 move(imm, dataTempRegister); 283 m_assembler.orr(dest, dest, dataTempRegister); 284 } 285 } 286 287 void or32(RegisterID op1, RegisterID op2, RegisterID dest) 288 { 289 m_assembler.orr(dest, op1, op2); 290 } 291 292 void rshift32(RegisterID shift_amount, RegisterID dest) 313 m_assembler.orr(dest, src, dataTempRegister); 314 } 315 } 316 317 void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) 293 318 { 294 319 // Clamp the shift to the range 0..31 295 320 ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f); 296 321 ASSERT(armImm.isValid()); 297 m_assembler.ARM_and(dataTempRegister, shift_amount, armImm); 298 299 m_assembler.asr(dest, dest, dataTempRegister); 300 } 301 322 m_assembler.ARM_and(dataTempRegister, shiftAmount, armImm); 323 324 m_assembler.asr(dest, src, dataTempRegister); 325 } 326 327 void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) 328 { 329 m_assembler.asr(dest, src, imm.m_value & 0x1f); 330 } 331 332 void rshift32(RegisterID shiftAmount, RegisterID dest) 333 { 334 rshift32(dest, shiftAmount, dest); 335 } 336 302 337 void rshift32(TrustedImm32 imm, RegisterID dest) 303 338 { … … 305 340 } 306 341 307 void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) 308 { 309 m_assembler.asr(dest, src, imm.m_value & 0x1f); 310 } 311 312 void urshift32(RegisterID shift_amount, RegisterID dest) 342 void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) 313 343 { 314 344 // Clamp the shift to the range 0..31 315 345 ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f); 316 346 ASSERT(armImm.isValid()); 317 m_assembler.ARM_and(dataTempRegister, shift _amount, armImm);347 m_assembler.ARM_and(dataTempRegister, shiftAmount, armImm); 318 348 319 m_assembler.lsr(dest, dest, dataTempRegister); 349 m_assembler.lsr(dest, src, dataTempRegister); 350 } 351 352 void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) 353 { 354 m_assembler.lsr(dest, src, imm.m_value & 0x1f); 355 } 356 357 void urshift32(RegisterID shiftAmount, RegisterID dest) 358 { 359 urshift32(dest, shiftAmount, dest); 320 360 } 321 361 322 362 void urshift32(TrustedImm32 imm, RegisterID dest) 323 363 { 324 m_assembler.lsr(dest, dest, imm.m_value & 0x1f);364 urshift32(dest, imm, dest); 325 365 } 326 366 … … 381 421 } 382 422 383 void xor32(RegisterID src, RegisterID dest)384 { 385 m_assembler.eor(dest, dest, src);386 } 387 388 void xor32(TrustedImm32 imm, RegisterID dest)423 void xor32(RegisterID op1, RegisterID op2, RegisterID dest) 424 { 425 m_assembler.eor(dest, op1, op2); 426 } 427 428 void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) 389 429 { 390 430 ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); 391 431 if (armImm.isValid()) 392 m_assembler.eor(dest, dest, armImm);432 m_assembler.eor(dest, src, armImm); 393 433 else { 394 434 move(imm, dataTempRegister); 395 m_assembler.eor(dest, dest, dataTempRegister); 396 } 435 m_assembler.eor(dest, src, dataTempRegister); 436 } 437 } 438 439 void xor32(RegisterID src, RegisterID dest) 440 { 441 xor32(dest, src, dest); 442 } 443 444 void xor32(TrustedImm32 imm, RegisterID dest) 445 { 446 xor32(imm, dest, dest); 397 447 } 398 448 … … 462 512 } 463 513 514 void store8(RegisterID src, ArmAddress address) 515 { 516 if (address.type == ArmAddress::HasIndex) 517 m_assembler.strb(src, address.base, address.u.index, address.u.scale); 518 else if (address.u.offset >= 0) { 519 ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12(address.u.offset); 520 ASSERT(armImm.isValid()); 521 m_assembler.strb(src, address.base, armImm); 522 } else { 523 ASSERT(address.u.offset >= -255); 524 m_assembler.strb(src, address.base, address.u.offset, true, false); 525 } 526 } 527 464 528 public: 465 529 void load32(ImplicitAddress address, RegisterID dest) … … 501 565 } 502 566 567 // FIXME: we should be able to plant a compact load relative to/from any base/dest register. 503 568 DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest) 504 569 { 570 RegisterID base = address.base; 571 572 if (base >= ARMRegisters::r8) { 573 move(base, addressTempRegister); 574 base = addressTempRegister; 575 } 576 505 577 DataLabelCompact label(this); 506 578 ASSERT(address.offset >= 0); 507 579 ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset); 508 580 ASSERT(ARMThumbImmediate::makeUInt12(address.offset).isUInt7()); 509 m_assembler.ldrCompact(dest, address.base, ARMThumbImmediate::makeUInt12(address.offset)); 581 582 if (dest >= ARMRegisters::r8) { 583 m_assembler.ldrCompact(addressTempRegister, base, ARMThumbImmediate::makeUInt12(address.offset)); 584 move(addressTempRegister, dest); 585 } else 586 m_assembler.ldrCompact(dest, base, ARMThumbImmediate::makeUInt12(address.offset)); 510 587 return label; 511 588 } … … 550 627 } 551 628 629 void store32(TrustedImm32 imm, BaseIndex address) 630 { 631 move(imm, dataTempRegister); 632 store32(dataTempRegister, setupArmAddress(address)); 633 } 634 552 635 void store32(RegisterID src, const void* address) 553 636 { … … 562 645 } 563 646 647 void store8(RegisterID src, BaseIndex address) 648 { 649 store8(src, setupArmAddress(address)); 650 } 651 564 652 565 653 // Floating-point operations: 566 654 567 655 static bool supportsFloatingPoint() { return true; } 568 // On x86(_64) the MacroAssembler provides an interface to truncate a double to an integer. 569 // If a value is not representable as an integer, and possibly for some values that are, 570 // (on x86 INT_MIN, since this is indistinguishable from results for out-of-range/NaN input) 571 // a branch will be taken. It is not clear whether this interface will be well suited to 572 // other platforms. On ARMv7 the hardware truncation operation produces multiple possible 573 // failure values (saturates to INT_MIN & INT_MAX, NaN reulsts in a value of 0). This is a 574 // temporary solution while we work out what this interface should be. Either we need to 575 // decide to make this interface work on all platforms, rework the interface to make it more 576 // generic, or decide that the MacroAssembler cannot practically be used to abstracted these 577 // operations, and make clients go directly to the m_assembler to plant truncation instructions. 578 // In short, FIXME:. 579 static bool supportsFloatingPointTruncate() { return false; } 580 581 static bool supportsFloatingPointSqrt() 582 { 583 return false; 584 } 585 static bool supportsFloatingPointAbs() { return false; } 656 static bool supportsFloatingPointTruncate() { return true; } 657 static bool supportsFloatingPointSqrt() { return true; } 658 static bool supportsFloatingPointAbs() { return true; } 586 659 587 660 void loadDouble(ImplicitAddress address, FPRegisterID dest) … … 600 673 } 601 674 675 void moveDouble(FPRegisterID src, FPRegisterID dest) 676 { 677 if (src != dest) 678 m_assembler.vmov(dest, src); 679 } 680 602 681 void loadDouble(const void* address, FPRegisterID dest) 603 682 { … … 621 700 } 622 701 702 void storeDouble(FPRegisterID src, const void* address) 703 { 704 move(ImmPtr(address), addressTempRegister); 705 storeDouble(src, addressTempRegister); 706 } 707 623 708 void addDouble(FPRegisterID src, FPRegisterID dest) 624 709 { 625 m_assembler.vadd _F64(dest, dest, src);710 m_assembler.vadd(dest, dest, src); 626 711 } 627 712 … … 632 717 } 633 718 719 void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 720 { 721 m_assembler.vadd(dest, op1, op2); 722 } 723 724 void addDouble(AbsoluteAddress address, FPRegisterID dest) 725 { 726 loadDouble(address.m_ptr, fpTempRegister); 727 m_assembler.vadd(dest, dest, fpTempRegister); 728 } 729 634 730 void divDouble(FPRegisterID src, FPRegisterID dest) 635 731 { 636 m_assembler.vdiv_F64(dest, dest, src); 732 m_assembler.vdiv(dest, dest, src); 733 } 734 735 void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 736 { 737 m_assembler.vdiv(dest, op1, op2); 637 738 } 638 739 639 740 void subDouble(FPRegisterID src, FPRegisterID dest) 640 741 { 641 m_assembler.vsub _F64(dest, dest, src);742 m_assembler.vsub(dest, dest, src); 642 743 } 643 744 … … 648 749 } 649 750 751 void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 752 { 753 m_assembler.vsub(dest, op1, op2); 754 } 755 650 756 void mulDouble(FPRegisterID src, FPRegisterID dest) 651 757 { 652 m_assembler.vmul _F64(dest, dest, src);758 m_assembler.vmul(dest, dest, src); 653 759 } 654 760 … … 659 765 } 660 766 661 void sqrtDouble(FPRegisterID, FPRegisterID) NO_RETURN_DUE_TO_ASSERT 662 { 663 ASSERT_NOT_REACHED(); 664 } 665 666 void absDouble(FPRegisterID, FPRegisterID) NO_RETURN_DUE_TO_ASSERT 667 { 668 ASSERT_NOT_REACHED(); 767 void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 768 { 769 m_assembler.vmul(dest, op1, op2); 770 } 771 772 void sqrtDouble(FPRegisterID src, FPRegisterID dest) 773 { 774 m_assembler.vsqrt(dest, src); 775 } 776 777 void absDouble(FPRegisterID src, FPRegisterID dest) 778 { 779 m_assembler.vabs(dest, src); 669 780 } 670 781 … … 672 783 { 673 784 m_assembler.vmov(fpTempRegisterAsSingle(), src); 674 m_assembler.vcvt_ F64_S32(dest, fpTempRegisterAsSingle());785 m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle()); 675 786 } 676 787 … … 680 791 load32(address, dataTempRegister); 681 792 m_assembler.vmov(fpTempRegisterAsSingle(), dataTempRegister); 682 m_assembler.vcvt_ F64_S32(dest, fpTempRegisterAsSingle());793 m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle()); 683 794 } 684 795 … … 688 799 load32(address.m_ptr, dataTempRegister); 689 800 m_assembler.vmov(fpTempRegisterAsSingle(), dataTempRegister); 690 m_assembler.vcvt_ F64_S32(dest, fpTempRegisterAsSingle());801 m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle()); 691 802 } 692 803 693 804 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right) 694 805 { 695 m_assembler.vcmp _F64(left, right);806 m_assembler.vcmp(left, right); 696 807 m_assembler.vmrs(); 697 808 … … 715 826 } 716 827 717 Jump branchTruncateDoubleToInt32(FPRegisterID, RegisterID) 718 { 719 ASSERT_NOT_REACHED(); 720 return jump(); 721 } 722 828 enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful }; 829 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) 830 { 831 // Convert into dest. 832 m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src); 833 m_assembler.vmov(dest, fpTempRegisterAsSingle()); 834 835 // Calculate 2x dest. If the value potentially underflowed, it will have 836 // clamped to 0x80000000, so 2x dest is zero in this case. In the case of 837 // overflow the result will be equal to -2. 838 Jump underflow = branchAdd32(Zero, dest, dest, dataTempRegister); 839 Jump noOverflow = branch32(NotEqual, dataTempRegister, Imm32(-2)); 840 841 // For BranchIfTruncateSuccessful, we branch if 'noOverflow' jumps. 842 underflow.link(this); 843 if (branchType == BranchIfTruncateSuccessful) 844 return noOverflow; 845 846 // We'll reach the current point in the code on failure, so plant a 847 // jump here & link the success case. 848 Jump failure = jump(); 849 noOverflow.link(this); 850 return failure; 851 } 852 853 // Result is undefined if the value is outside of the integer range. 854 void truncateDoubleToInt32(FPRegisterID src, RegisterID dest) 855 { 856 m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src); 857 m_assembler.vmov(dest, fpTempRegisterAsSingle()); 858 } 859 723 860 // Convert 'src' to an integer, and places the resulting 'dest'. 724 861 // If the result is not representable as a 32 bit value, branch. … … 727 864 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID) 728 865 { 729 m_assembler.vcvt r_S32_F64(fpTempRegisterAsSingle(), src);866 m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src); 730 867 m_assembler.vmov(dest, fpTempRegisterAsSingle()); 731 868 732 869 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump. 733 m_assembler.vcvt_ F64_S32(fpTempRegister, fpTempRegisterAsSingle());870 m_assembler.vcvt_signedToFloatingPoint(fpTempRegister, fpTempRegisterAsSingle()); 734 871 failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, fpTempRegister)); 735 872 … … 740 877 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID) 741 878 { 742 m_assembler.vcmpz _F64(reg);879 m_assembler.vcmpz(reg); 743 880 m_assembler.vmrs(); 744 881 Jump unordered = makeBranch(ARMv7Assembler::ConditionVS); … … 750 887 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID) 751 888 { 752 m_assembler.vcmpz _F64(reg);889 m_assembler.vcmpz(reg); 753 890 m_assembler.vmrs(); 754 891 Jump unordered = makeBranch(ARMv7Assembler::ConditionVS); … … 820 957 void move(RegisterID src, RegisterID dest) 821 958 { 822 m_assembler.mov(dest, src); 959 if (src != dest) 960 m_assembler.mov(dest, src); 823 961 } 824 962 … … 837 975 void signExtend32ToPtr(RegisterID src, RegisterID dest) 838 976 { 839 if (src != dest) 840 move(src, dest); 977 move(src, dest); 841 978 } 842 979 843 980 void zeroExtend32ToPtr(RegisterID src, RegisterID dest) 844 981 { 845 if (src != dest) 846 move(src, dest); 982 move(src, dest); 983 } 984 985 // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc. 986 static RelationalCondition invert(RelationalCondition cond) 987 { 988 return static_cast<RelationalCondition>(cond ^ 1); 847 989 } 848 990 … … 1018 1160 // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/ 1019 1161 load8(address, addressTempRegister); 1020 return branchTest 8(cond, addressTempRegister, mask);1162 return branchTest32(cond, addressTempRegister, mask); 1021 1163 } 1022 1164 … … 1035 1177 void jump(AbsoluteAddress address) 1036 1178 { 1037 move(Trusted dImmPtr(address.m_ptr), dataTempRegister);1179 move(TrustedImmPtr(address.m_ptr), dataTempRegister); 1038 1180 load32(Address(dataTempRegister), dataTempRegister); 1039 1181 m_assembler.bx(dataTempRegister); … … 1051 1193 // operation caused an overflow to occur. 1052 1194 1053 Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)1054 { 1055 m_assembler.add_S(dest, dest, src);1195 Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) 1196 { 1197 m_assembler.add_S(dest, op1, op2); 1056 1198 return Jump(makeBranch(cond)); 1057 1199 } 1058 1200 1059 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)1201 Jump branchAdd32(ResultCondition cond, RegisterID op1, TrustedImm32 imm, RegisterID dest) 1060 1202 { 1061 1203 ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); 1062 1204 if (armImm.isValid()) 1063 m_assembler.add_S(dest, dest, armImm);1205 m_assembler.add_S(dest, op1, armImm); 1064 1206 else { 1065 1207 move(imm, dataTempRegister); 1066 m_assembler.add_S(dest, dest, dataTempRegister); 1067 } 1208 m_assembler.add_S(dest, op1, dataTempRegister); 1209 } 1210 return Jump(makeBranch(cond)); 1211 } 1212 1213 Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest) 1214 { 1215 return branchAdd32(cond, dest, src, dest); 1216 } 1217 1218 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) 1219 { 1220 return branchAdd32(cond, dest, imm, dest); 1221 } 1222 1223 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest) 1224 { 1225 // Move the high bits of the address into addressTempRegister, 1226 // and load the value into dataTempRegister. 1227 move(ImmPtr(dest.m_ptr), addressTempRegister); 1228 m_assembler.ldr(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt16(0)); 1229 1230 // Do the add. 1231 ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); 1232 if (armImm.isValid()) 1233 m_assembler.add_S(dataTempRegister, dataTempRegister, armImm); 1234 else { 1235 // If the operand does not fit into an immediate then load it temporarily 1236 // into addressTempRegister; since we're overwriting addressTempRegister 1237 // we'll need to reload it with the high bits of the address afterwards. 1238 move(imm, addressTempRegister); 1239 m_assembler.add_S(dataTempRegister, dataTempRegister, addressTempRegister); 1240 move(ImmPtr(dest.m_ptr), addressTempRegister); 1241 } 1242 1243 // Store the result. 1244 m_assembler.str(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt16(0)); 1245 1068 1246 return Jump(makeBranch(cond)); 1069 1247 } … … 1098 1276 } 1099 1277 1100 Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)1101 { 1102 m_assembler.sub_S(dest, dest, src);1278 Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) 1279 { 1280 m_assembler.sub_S(dest, op1, op2); 1103 1281 return Jump(makeBranch(cond)); 1104 1282 } 1105 1283 1106 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)1284 Jump branchSub32(ResultCondition cond, RegisterID op1, TrustedImm32 imm, RegisterID dest) 1107 1285 { 1108 1286 ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); 1109 1287 if (armImm.isValid()) 1110 m_assembler.sub_S(dest, dest, armImm);1288 m_assembler.sub_S(dest, op1, armImm); 1111 1289 else { 1112 1290 move(imm, dataTempRegister); 1113 m_assembler.sub_S(dest, dest, dataTempRegister);1291 m_assembler.sub_S(dest, op1, dataTempRegister); 1114 1292 } 1115 1293 return Jump(makeBranch(cond)); 1294 } 1295 1296 Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest) 1297 { 1298 return branchSub32(cond, dest, src, dest); 1299 } 1300 1301 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) 1302 { 1303 return branchSub32(cond, dest, imm, dest); 1116 1304 } 1117 1305 … … 1131 1319 // Miscellaneous operations: 1132 1320 1133 void breakpoint( )1134 { 1135 m_assembler.bkpt( 0);1321 void breakpoint(uint8_t imm = 0) 1322 { 1323 m_assembler.bkpt(imm); 1136 1324 } 1137 1325
Note: See TracChangeset
for help on using the changeset viewer.