Changeset 176083 in webkit
- Timestamp:
- Nov 13, 2014 12:43:32 PM (9 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r176079 r176083 1 2014-11-13 Benjamin Poulain <benjamin@webkit.org> 2 3 ARMv7(s) Assembler: LDRH with immediate offset is loading from the wrong offset 4 https://bugs.webkit.org/show_bug.cgi?id=136914 5 6 Reviewed by Michael Saboff. 7 8 TLDR: the immediate offset of half-word load was divided by 2. 9 10 Story time: So I started getting those weird reports of :nth-child() behaving bizarrely 11 on ARMv7 and ARMv7s. To make things worse, the behavior changes depending on style updates. 12 13 I started looking the disassembly on the tests cases... 14 15 The first thing I noticed was that the computation of An+B looked wrong. For example, 16 in the case of n+6, the instruction should have been: 17 subs r1, r1, #6 18 but was 19 subs r1, r1, #2 20 21 After spending a lot of time trying to find the error in the assembler, I discovered 22 the problem was not real, but just a bug in the disassembler. 23 This is the first fix: ARMv7DOpcodeAddSubtractImmediate3's immediate3() was truncating 24 the value to 2 bits instead of 3 bits. 25 26 The disassembler being fixed, I still have no lead on the weird bug. Some disassembly later, 27 I realize the LDRH instruction is not decoded at all. The reason is that both LDRH and STRH 28 were under the umbrella ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord but the pattern 29 only matched SRTH. 30 31 I fix that next, ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord is split into 32 ARMv7DOpcodeStoreRegisterImmediateHalfWord and ARMv7DOpcodeLoadRegisterImmediateHalfWord, 33 each with their own pattern and their instruction group. 34 35 Now that I can see the LDRHs correctly, there is something fishy about them, their offset 36 is way too small for the data I load. 37 38 This time, looking at the binary, the generated code is indeed incorrect. It turns out that 39 the ARMv7 assembler shifted the offset of half-word load as if they were byte load: divided by 4. 40 As a result, all the load of half-words with more than zero offset were loading 41 values with a smaller offset than what they should have. 42 43 That being fixed, I dump the assembly: still wrong. I am ready to throw my keyboard through 44 my screen at that point. 45 46 Looking at the disassembler, there is yet again a bug. The computation of the scale() adjustment 47 of the offset was incorrect for anything but word loads. 48 I replaced it by a switch-case to make it explicit. 49 50 STRH is likely incorrect too. I'll fix that in a follow up, I want to survey all the 16 bits cases 51 that are not directly used by the CSS JIT. 52 53 * assembler/ARMv7Assembler.h: 54 (JSC::ARMv7Assembler::ldrh): 55 Fix the immediate scaling. Add an assertion to make sure the alignment of the input is correct. 56 57 * disassembler/ARMv7/ARMv7DOpcode.cpp: 58 (JSC::ARMv7Disassembler::ARMv7DOpcodeLoadStoreRegisterImmediate::scale): 59 Fix the scaling code. Just hardcode instruction-to-scale table. 60 61 * disassembler/ARMv7/ARMv7DOpcode.h: 62 (JSC::ARMv7Disassembler::ARMv7DOpcodeAddSubtractImmediate3::immediate3): 63 The mask for a 3 bits immediate is not 3 :) 64 65 (JSC::ARMv7Disassembler::ARMv7DOpcodeLoadStoreRegisterImmediate::scale): Deleted. 66 1 67 2014-11-13 Andreas Kling <akling@apple.com> 2 68 -
trunk/Source/JavaScriptCore/assembler/ARMv7Assembler.h
r176072 r176083 1156 1156 ASSERT(rn != ARMRegisters::pc); // LDR (literal) 1157 1157 ASSERT(imm.isUInt12()); 1158 ASSERT(!(imm.isUInt12() & 1)); 1158 1159 1159 1160 if (!((rt | rn) & 8) && imm.isUInt6()) 1160 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);1161 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 1, rn, rt); 1161 1162 else 1162 1163 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12()); -
trunk/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp
r173312 r176083 92 92 OPCODE_GROUP_ENTRY(0xe, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), 93 93 OPCODE_GROUP_ENTRY(0xf, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), 94 OPCODE_GROUP_ENTRY(0x10, ARMv7DOpcode LoadStoreRegisterImmediateHalfWord),95 OPCODE_GROUP_ENTRY(0x11, ARMv7DOpcodeLoad StoreRegisterImmediateHalfWord),94 OPCODE_GROUP_ENTRY(0x10, ARMv7DOpcodeStoreRegisterImmediateHalfWord), 95 OPCODE_GROUP_ENTRY(0x11, ARMv7DOpcodeLoadRegisterImmediateHalfWord), 96 96 OPCODE_GROUP_ENTRY(0x12, ARMv7DOpcodeLoadStoreRegisterSPRelative), 97 97 OPCODE_GROUP_ENTRY(0x13, ARMv7DOpcodeLoadStoreRegisterSPRelative), … … 525 525 } 526 526 527 unsigned ARMv7DOpcodeLoadStoreRegisterImmediate::scale() 528 { 529 switch (op()) { 530 case 0: 531 case 1: 532 return 2; 533 case 2: 534 case 3: 535 return 0; 536 case 4: 537 case 5: 538 return 1; 539 default: 540 break; 541 } 542 ASSERT_NOT_REACHED(); 543 return 0; 544 } 545 527 546 const char* const ARMv7DOpcodeLoadStoreRegisterOffsetT1::s_opNames[8] = { 528 547 "str", "strh", "strb", "ldrsb", "ldr", "ldrh", "ldrb", "ldrsh" -
trunk/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h
r173312 r176083 276 276 277 277 unsigned op() { return (m_opcode >> 9) & 0x1; } 278 unsigned immediate3() { return (m_opcode >> 6) & 0x 3; }278 unsigned immediate3() { return (m_opcode >> 6) & 0x7; } 279 279 unsigned rn() { return (m_opcode >> 3) & 0x7; } 280 280 }; … … 442 442 unsigned rn() { return (m_opcode >> 3) & 0x7; } 443 443 unsigned rt() { return m_opcode & 0x7; } 444 unsigned scale() { return 2 - (op() >> 1); }444 unsigned scale(); 445 445 }; 446 446 … … 453 453 }; 454 454 455 class ARMv7DOpcode LoadStoreRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate {455 class ARMv7DOpcodeStoreRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate { 456 456 public: 457 457 static const uint16_t s_mask = 0xf800; 458 458 static const uint16_t s_pattern = 0x8000; 459 460 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj); 461 }; 462 463 class ARMv7DOpcodeLoadRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate { 464 public: 465 static const uint16_t s_mask = 0xf800; 466 static const uint16_t s_pattern = 0x8800; 459 467 460 468 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj);
Note: See TracChangeset
for help on using the changeset viewer.