OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
8 #include "vm/constants_mips.h" | 8 #include "vm/constants_mips.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/instructions.h" | 10 #include "vm/instructions.h" |
11 #include "vm/object.h" | 11 #include "vm/object.h" |
12 | 12 |
13 namespace dart { | 13 namespace dart { |
14 | 14 |
15 CallPattern::CallPattern(uword pc, const Code& code) | 15 CallPattern::CallPattern(uword pc, const Code& code) |
16 : end_(reinterpret_cast<uword*>(pc)), | 16 : object_pool_(Array::Handle(code.ObjectPool())), |
| 17 end_(pc), |
| 18 args_desc_load_end_(0), |
| 19 ic_data_load_end_(0), |
17 target_address_pool_index_(-1), | 20 target_address_pool_index_(-1), |
18 args_desc_load_end_(-1), | |
19 args_desc_(Array::Handle()), | 21 args_desc_(Array::Handle()), |
20 ic_data_load_end_(-1), | 22 ic_data_(ICData::Handle()) { |
21 ic_data_(ICData::Handle()), | |
22 object_pool_(Array::Handle(code.ObjectPool())) { | |
23 ASSERT(code.ContainsInstructionAt(pc)); | 23 ASSERT(code.ContainsInstructionAt(pc)); |
24 ASSERT(Back(2) == 0x0020f809); // Last instruction: jalr RA, TMP(=R1) | 24 // Last instruction: jalr RA, TMP(=R1). |
| 25 ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0020f809); |
25 Register reg; | 26 Register reg; |
26 // First end is 0 so that we begin from the delay slot of the jalr. | 27 // The end of the pattern is the instruction after the delay slot of the jalr. |
27 ic_data_load_end_ = | 28 ic_data_load_end_ = |
28 DecodeLoadWordFromPool(2, ®, &target_address_pool_index_); | 29 InstructionPattern::DecodeLoadWordFromPool(end_ - (2 * Instr::kInstrSize), |
| 30 ®, |
| 31 &target_address_pool_index_); |
29 ASSERT(reg == TMP); | 32 ASSERT(reg == TMP); |
30 } | 33 } |
31 | 34 |
32 | 35 |
33 uword CallPattern::Back(int n) const { | 36 // Decodes a load sequence ending at 'end' (the last instruction of the load |
34 ASSERT(n > 0); | 37 // sequence is the instruction before the one at end). Returns a pointer to |
35 return *(end_ - n); | 38 // the first instruction in the sequence. Returns the register being loaded |
| 39 // and the loaded object in the output parameters 'reg' and 'obj' |
| 40 // respectively. |
| 41 uword InstructionPattern::DecodeLoadObject(uword end, |
| 42 const Array& object_pool, |
| 43 Register* reg, |
| 44 Object* obj) { |
| 45 uword start = 0; |
| 46 Instr* instr = Instr::At(end - Instr::kInstrSize); |
| 47 if (instr->OpcodeField() == LW) { |
| 48 intptr_t index = 0; |
| 49 start = DecodeLoadWordFromPool(end, reg, &index); |
| 50 *obj = object_pool.At(index); |
| 51 } else { |
| 52 intptr_t value = 0; |
| 53 start = DecodeLoadWordImmediate(end, reg, &value); |
| 54 *obj = reinterpret_cast<RawObject*>(value); |
| 55 } |
| 56 return start; |
36 } | 57 } |
37 | 58 |
38 | 59 |
39 // Decodes a load sequence ending at end. Returns the register being loaded and | 60 // Decodes a load sequence ending at 'end' (the last instruction of the load |
40 // the loaded object. | 61 // sequence is the instruction before the one at end). Returns a pointer to |
41 // Returns the location of the load sequence, counting the number of | 62 // the first instruction in the sequence. Returns the register being loaded |
42 // instructions back from the end of the call pattern. | 63 // and the loaded immediate value in the output parameters 'reg' and 'value' |
43 int CallPattern::DecodeLoadObject(int end, Register* reg, Object* obj) { | 64 // respectively. |
44 ASSERT(end > 0); | 65 uword InstructionPattern::DecodeLoadWordImmediate(uword end, |
45 uword i = Back(end + 1); | 66 Register* reg, |
46 Instr* instr = Instr::At(reinterpret_cast<uword>(&i)); | 67 intptr_t* value) { |
47 if (instr->OpcodeField() == LW) { | 68 // The pattern is a fixed size, but match backwards for uniformity with |
48 int index = 0; | 69 // DecodeLoadWordFromPool. |
49 end = DecodeLoadWordFromPool(end, reg, &index); | 70 uword start = end - Instr::kInstrSize; |
50 *obj = object_pool_.At(index); | 71 Instr* instr = Instr::At(start); |
51 } else { | 72 intptr_t imm = 0; |
52 int value = 0; | |
53 end = DecodeLoadWordImmediate(end, reg, &value); | |
54 *obj = reinterpret_cast<RawObject*>(value); | |
55 } | |
56 return end; | |
57 } | |
58 | |
59 | |
60 // Decodes a load sequence ending at end. Returns the register being loaded and | |
61 // the loaded immediate value. | |
62 // Returns the location of the load sequence, counting the number of | |
63 // instructions back from the end of the call pattern. | |
64 int CallPattern::DecodeLoadWordImmediate(int end, Register* reg, int* value) { | |
65 ASSERT(end > 0); | |
66 int imm = 0; | |
67 uword i = Back(++end); | |
68 Instr* instr = Instr::At(reinterpret_cast<uword>(&i)); | |
69 ASSERT(instr->OpcodeField() == ORI); | 73 ASSERT(instr->OpcodeField() == ORI); |
70 imm = instr->UImmField(); | 74 imm = instr->UImmField(); |
71 *reg = instr->RtField(); | 75 *reg = instr->RtField(); |
72 | 76 |
73 i = Back(++end); | 77 start -= Instr::kInstrSize; |
74 instr = Instr::At(reinterpret_cast<uword>(&i)); | 78 instr = Instr::At(start); |
75 ASSERT(instr->OpcodeField() == LUI); | 79 ASSERT(instr->OpcodeField() == LUI); |
76 ASSERT(instr->RtField() == *reg); | 80 ASSERT(instr->RtField() == *reg); |
77 imm |= (instr->UImmField() << 16); | 81 imm |= (instr->UImmField() << 16); |
78 *value = imm; | 82 *value = imm; |
79 return end; | 83 return start; |
80 } | 84 } |
81 | 85 |
82 | 86 |
83 // Decodes a load sequence ending at end. Returns the register being loaded and | 87 // Decodes a load sequence ending at 'end' (the last instruction of the load |
84 // the index in the pool being read from. | 88 // sequence is the instruction before the one at end). Returns a pointer to |
85 // Returns the location of the load sequence, counting the number of | 89 // the first instruction in the sequence. Returns the register being loaded |
86 // instructions back from the end of the call pattern. | 90 // and the index in the pool being read from in the output parameters 'reg' |
87 int CallPattern::DecodeLoadWordFromPool(int end, Register* reg, int* index) { | 91 // and 'index' respectively. |
88 ASSERT(end > 0); | 92 uword InstructionPattern::DecodeLoadWordFromPool(uword end, |
89 uword i = Back(++end); | 93 Register* reg, |
90 Instr* instr = Instr::At(reinterpret_cast<uword>(&i)); | 94 intptr_t* index) { |
91 int offset = 0; | 95 uword start = end - Instr::kInstrSize; |
| 96 Instr* instr = Instr::At(start); |
| 97 intptr_t offset = 0; |
92 if ((instr->OpcodeField() == LW) && (instr->RsField() == PP)) { | 98 if ((instr->OpcodeField() == LW) && (instr->RsField() == PP)) { |
93 offset = instr->SImmField(); | 99 offset = instr->SImmField(); |
94 *reg = instr->RtField(); | 100 *reg = instr->RtField(); |
95 } else { | 101 } else { |
96 ASSERT(instr->OpcodeField() == LW); | 102 ASSERT(instr->OpcodeField() == LW); |
97 offset = instr->SImmField(); | 103 offset = instr->SImmField(); |
98 *reg = instr->RtField(); | 104 *reg = instr->RtField(); |
99 | 105 |
100 i = Back(++end); | 106 start -= Instr::kInstrSize; |
101 instr = Instr::At(reinterpret_cast<uword>(&i)); | 107 instr = Instr::At(start); |
102 ASSERT(instr->OpcodeField() == SPECIAL); | 108 ASSERT(instr->OpcodeField() == SPECIAL); |
103 ASSERT(instr->FunctionField() == ADDU); | 109 ASSERT(instr->FunctionField() == ADDU); |
104 ASSERT(instr->RdField() == *reg); | 110 ASSERT(instr->RdField() == *reg); |
105 ASSERT(instr->RsField() == *reg); | 111 ASSERT(instr->RsField() == *reg); |
106 ASSERT(instr->RtField() == PP); | 112 ASSERT(instr->RtField() == PP); |
107 | 113 |
108 i = Back(++end); | 114 start -= Instr::kInstrSize; |
109 instr = Instr::At(reinterpret_cast<uword>(&i)); | 115 instr = Instr::At(start); |
110 ASSERT(instr->OpcodeField() == LUI); | 116 ASSERT(instr->OpcodeField() == LUI); |
111 ASSERT(instr->RtField() == *reg); | 117 ASSERT(instr->RtField() == *reg); |
112 // Offset is signed, so add the upper 16 bits. | 118 // Offset is signed, so add the upper 16 bits. |
113 offset += (instr->UImmField() << 16); | 119 offset += (instr->UImmField() << 16); |
114 } | 120 } |
115 offset += kHeapObjectTag; | 121 offset += kHeapObjectTag; |
116 ASSERT(Utils::IsAligned(offset, 4)); | 122 ASSERT(Utils::IsAligned(offset, 4)); |
117 *index = (offset - Array::data_offset())/4; | 123 *index = (offset - Array::data_offset()) / 4; |
118 return end; | 124 return start; |
119 } | 125 } |
120 | 126 |
121 | 127 |
122 RawICData* CallPattern::IcData() { | 128 RawICData* CallPattern::IcData() { |
123 if (ic_data_.IsNull()) { | 129 if (ic_data_.IsNull()) { |
124 Register reg; | 130 Register reg; |
125 args_desc_load_end_ = DecodeLoadObject(ic_data_load_end_, ®, &ic_data_); | 131 args_desc_load_end_ = |
| 132 InstructionPattern::DecodeLoadObject(ic_data_load_end_, |
| 133 object_pool_, |
| 134 ®, |
| 135 &ic_data_); |
126 ASSERT(reg == S5); | 136 ASSERT(reg == S5); |
127 } | 137 } |
128 return ic_data_.raw(); | 138 return ic_data_.raw(); |
129 } | 139 } |
130 | 140 |
131 | 141 |
132 RawArray* CallPattern::ClosureArgumentsDescriptor() { | 142 RawArray* CallPattern::ClosureArgumentsDescriptor() { |
133 if (args_desc_.IsNull()) { | 143 if (args_desc_.IsNull()) { |
134 IcData(); // Loading of the ic_data must be decoded first, if not already. | 144 IcData(); // Loading of the ic_data must be decoded first, if not already. |
135 Register reg; | 145 Register reg; |
136 DecodeLoadObject(args_desc_load_end_, ®, &args_desc_); | 146 InstructionPattern::DecodeLoadObject(args_desc_load_end_, |
| 147 object_pool_, |
| 148 ®, |
| 149 &args_desc_); |
137 ASSERT(reg == S4); | 150 ASSERT(reg == S4); |
138 } | 151 } |
139 return args_desc_.raw(); | 152 return args_desc_.raw(); |
140 } | 153 } |
141 | 154 |
142 | 155 |
143 uword CallPattern::TargetAddress() const { | 156 uword CallPattern::TargetAddress() const { |
144 ASSERT(target_address_pool_index_ >= 0); | 157 ASSERT(target_address_pool_index_ >= 0); |
145 const Object& target_address = | 158 const Object& target_address = |
146 Object::Handle(object_pool_.At(target_address_pool_index_)); | 159 Object::Handle(object_pool_.At(target_address_pool_index_)); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 const uint16_t target_lo = target_address & 0xffff; | 223 const uint16_t target_lo = target_address & 0xffff; |
211 const uint16_t target_hi = target_address >> 16; | 224 const uint16_t target_hi = target_address >> 16; |
212 | 225 |
213 lui->SetInstructionBits((lui_bits & 0xffff0000) | target_hi); | 226 lui->SetInstructionBits((lui_bits & 0xffff0000) | target_hi); |
214 ori->SetInstructionBits((ori_bits & 0xffff0000) | target_lo); | 227 ori->SetInstructionBits((ori_bits & 0xffff0000) | target_lo); |
215 } | 228 } |
216 | 229 |
217 } // namespace dart | 230 } // namespace dart |
218 | 231 |
219 #endif // defined TARGET_ARCH_MIPS | 232 #endif // defined TARGET_ARCH_MIPS |
220 | |
OLD | NEW |