OLD | NEW |
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
6 // are met: | 6 // are met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 // mov lr, pc | 261 // mov lr, pc |
262 const Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12; | 262 const Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12; |
263 // ldr rd, [pc, #offset] | 263 // ldr rd, [pc, #offset] |
264 const Instr kLdrPCMask = CondMask | 15 * B24 | 7 * B20 | 15 * B16; | 264 const Instr kLdrPCMask = CondMask | 15 * B24 | 7 * B20 | 15 * B16; |
265 const Instr kLdrPCPattern = al | 5 * B24 | L | pc.code() * B16; | 265 const Instr kLdrPCPattern = al | 5 * B24 | L | pc.code() * B16; |
266 // blxcc rm | 266 // blxcc rm |
267 const Instr kBlxRegMask = | 267 const Instr kBlxRegMask = |
268 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; | 268 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; |
269 const Instr kBlxRegPattern = | 269 const Instr kBlxRegPattern = |
270 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4; | 270 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4; |
| 271 // A mask for the Rd register for push, pop, ldr, str instructions. |
| 272 const Instr kRdMask = 0x0000f000; |
| 273 static const Instr kLdrRegFpOffsetPattern = |
| 274 al | B26 | L | Offset | fp.code() * B16; |
| 275 static const Instr kStrRegFpOffsetPattern = |
| 276 al | B26 | Offset | fp.code() * B16; |
| 277 static const Instr kLdrRegFpNegOffsetPattern = |
| 278 al | B26 | L | NegOffset | fp.code() * B16; |
| 279 static const Instr kStrRegFpNegOffsetPattern = |
| 280 al | B26 | NegOffset | fp.code() * B16; |
| 281 static const Instr kLdrStrInstrTypeMask = 0xffff0000; |
| 282 static const Instr kLdrStrInstrArgumentMask = 0x0000ffff; |
| 283 static const Instr kLdrStrOffsetMask = 0x00000fff; |
| 284 static const int kRdShift = 12; |
271 | 285 |
272 // Spare buffer. | 286 // Spare buffer. |
273 static const int kMinimalBufferSize = 4*KB; | 287 static const int kMinimalBufferSize = 4*KB; |
274 static byte* spare_buffer_ = NULL; | 288 static byte* spare_buffer_ = NULL; |
275 | 289 |
276 Assembler::Assembler(void* buffer, int buffer_size) { | 290 Assembler::Assembler(void* buffer, int buffer_size) { |
277 if (buffer == NULL) { | 291 if (buffer == NULL) { |
278 // Do our own buffer management. | 292 // Do our own buffer management. |
279 if (buffer_size <= kMinimalBufferSize) { | 293 if (buffer_size <= kMinimalBufferSize) { |
280 buffer_size = kMinimalBufferSize; | 294 buffer_size = kMinimalBufferSize; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 bool positive = offset >= 0; | 402 bool positive = offset >= 0; |
389 if (!positive) offset = -offset; | 403 if (!positive) offset = -offset; |
390 ASSERT(is_uint12(offset)); | 404 ASSERT(is_uint12(offset)); |
391 // Set bit indicating whether the offset should be added. | 405 // Set bit indicating whether the offset should be added. |
392 instr = (instr & ~B23) | (positive ? B23 : 0); | 406 instr = (instr & ~B23) | (positive ? B23 : 0); |
393 // Set the actual offset. | 407 // Set the actual offset. |
394 return (instr & ~Off12Mask) | offset; | 408 return (instr & ~Off12Mask) | offset; |
395 } | 409 } |
396 | 410 |
397 | 411 |
| 412 Register Assembler::GetRd(Instr instr) { |
| 413 Register reg; |
| 414 reg.code_ = ((instr & kRdMask) >> kRdShift); |
| 415 return reg; |
| 416 } |
| 417 |
| 418 |
| 419 bool Assembler::IsPush(Instr instr) { |
| 420 return ((instr & ~kRdMask) == kPushRegPattern); |
| 421 } |
| 422 |
| 423 |
| 424 bool Assembler::IsPop(Instr instr) { |
| 425 return ((instr & ~kRdMask) == kPopRegPattern); |
| 426 } |
| 427 |
| 428 |
| 429 bool Assembler::IsStrRegFpOffset(Instr instr) { |
| 430 return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern); |
| 431 } |
| 432 |
| 433 |
| 434 bool Assembler::IsLdrRegFpOffset(Instr instr) { |
| 435 return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern); |
| 436 } |
| 437 |
| 438 |
| 439 bool Assembler::IsStrRegFpNegOffset(Instr instr) { |
| 440 return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern); |
| 441 } |
| 442 |
| 443 |
| 444 bool Assembler::IsLdrRegFpNegOffset(Instr instr) { |
| 445 return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern); |
| 446 } |
| 447 |
| 448 |
398 // Labels refer to positions in the (to be) generated code. | 449 // Labels refer to positions in the (to be) generated code. |
399 // There are bound, linked, and unused labels. | 450 // There are bound, linked, and unused labels. |
400 // | 451 // |
401 // Bound labels refer to known positions in the already | 452 // Bound labels refer to known positions in the already |
402 // generated code. pos() is the position the label refers to. | 453 // generated code. pos() is the position the label refers to. |
403 // | 454 // |
404 // Linked labels refer to unknown positions in the code | 455 // Linked labels refer to unknown positions in the code |
405 // to be generated; pos() is the position of the last | 456 // to be generated; pos() is the position of the last |
406 // instruction using the label. | 457 // instruction using the label. |
407 | 458 |
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1079 } | 1130 } |
1080 | 1131 |
1081 | 1132 |
1082 // Load/Store instructions. | 1133 // Load/Store instructions. |
1083 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { | 1134 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { |
1084 if (dst.is(pc)) { | 1135 if (dst.is(pc)) { |
1085 WriteRecordedPositions(); | 1136 WriteRecordedPositions(); |
1086 } | 1137 } |
1087 addrmod2(cond | B26 | L, dst, src); | 1138 addrmod2(cond | B26 | L, dst, src); |
1088 | 1139 |
1089 // Eliminate pattern: push(r), pop(r) | 1140 // Eliminate pattern: push(ry), pop(rx) |
1090 // str(r, MemOperand(sp, 4, NegPreIndex), al) | 1141 // str(ry, MemOperand(sp, 4, NegPreIndex), al) |
1091 // ldr(r, MemOperand(sp, 4, PostIndex), al) | 1142 // ldr(rx, MemOperand(sp, 4, PostIndex), al) |
1092 // Both instructions can be eliminated. | 1143 // Both instructions can be eliminated if ry = rx. |
| 1144 // If ry != rx, a register copy from ry to rx is inserted |
| 1145 // after eliminating the push and the pop instructions. |
1093 int pattern_size = 2 * kInstrSize; | 1146 int pattern_size = 2 * kInstrSize; |
| 1147 Instr push_instr = instr_at(pc_ - 2 * kInstrSize); |
| 1148 Instr pop_instr = instr_at(pc_ - 1 * kInstrSize); |
| 1149 |
1094 if (FLAG_push_pop_elimination && | 1150 if (FLAG_push_pop_elimination && |
| 1151 last_bound_pos_ <= (pc_offset() - pattern_size) && |
| 1152 reloc_info_writer.last_pc() <= (pc_ - pattern_size) && |
| 1153 IsPush(push_instr) && |
| 1154 IsPop(pop_instr)) { |
| 1155 if ((pop_instr & kRdMask) != (push_instr & kRdMask)) { |
| 1156 // For consecutive push and pop on different registers, |
| 1157 // we delete both the push & pop and insert a register move. |
| 1158 // push ry, pop rx --> mov rx, ry |
| 1159 Register reg_pushed, reg_popped; |
| 1160 reg_pushed = GetRd(push_instr); |
| 1161 reg_popped = GetRd(pop_instr); |
| 1162 pc_ -= 2 * kInstrSize; |
| 1163 // Insert a mov instruction, which is better than a pair of push & pop |
| 1164 mov(reg_popped, reg_pushed); |
| 1165 if (FLAG_print_push_pop_elimination) { |
| 1166 PrintF("%x push/pop (diff reg) replaced by a reg move\n", pc_offset()); |
| 1167 } |
| 1168 } else { |
| 1169 // For consecutive push and pop on the same register, |
| 1170 // both the push and the pop can be deleted. |
| 1171 pc_ -= 2 * kInstrSize; |
| 1172 if (FLAG_print_push_pop_elimination) { |
| 1173 PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); |
| 1174 } |
| 1175 } |
| 1176 } |
| 1177 |
| 1178 pattern_size = 2 * kInstrSize; |
| 1179 if (FLAG_peephole_optimization && |
1095 last_bound_pos_ <= (pc_offset() - pattern_size) && | 1180 last_bound_pos_ <= (pc_offset() - pattern_size) && |
1096 reloc_info_writer.last_pc() <= (pc_ - pattern_size) && | 1181 reloc_info_writer.last_pc() <= (pc_ - pattern_size)) { |
1097 // Pattern. | 1182 Instr str_instr = instr_at(pc_ - 2 * kInstrSize); |
1098 instr_at(pc_ - 1 * kInstrSize) == (kPopRegPattern | dst.code() * B12) && | 1183 Instr ldr_instr = instr_at(pc_ - 1 * kInstrSize); |
1099 instr_at(pc_ - 2 * kInstrSize) == (kPushRegPattern | dst.code() * B12)) { | 1184 |
1100 pc_ -= 2 * kInstrSize; | 1185 if ((IsStrRegFpOffset(str_instr) && |
1101 if (FLAG_print_push_pop_elimination) { | 1186 IsLdrRegFpOffset(ldr_instr)) || |
1102 PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); | 1187 (IsStrRegFpNegOffset(str_instr) && |
| 1188 IsLdrRegFpNegOffset(ldr_instr))) { |
| 1189 if ((ldr_instr & kLdrStrInstrArgumentMask) == |
| 1190 (str_instr & kLdrStrInstrArgumentMask)) { |
| 1191 // Pattern: Ldr/str same fp+offset, same register. |
| 1192 // |
| 1193 // The following: |
| 1194 // str rx, [fp, #-12] |
| 1195 // ldr rx, [fp, #-12] |
| 1196 // |
| 1197 // Becomes: |
| 1198 // str rx, [fp, #-12] |
| 1199 |
| 1200 pc_ -= 1 * kInstrSize; |
| 1201 if (FLAG_print_peephole_optimization) { |
| 1202 PrintF("%x str/ldr (fp + same offset), same reg\n", pc_offset()); |
| 1203 } |
| 1204 } else if ((ldr_instr & kLdrStrOffsetMask) == |
| 1205 (str_instr & kLdrStrOffsetMask)) { |
| 1206 // Pattern: Ldr/str same fp+offset, different register. |
| 1207 // |
| 1208 // The following: |
| 1209 // str rx, [fp, #-12] |
| 1210 // ldr ry, [fp, #-12] |
| 1211 // |
| 1212 // Becomes: |
| 1213 // str rx, [fp, #-12] |
| 1214 // mov ry, rx |
| 1215 |
| 1216 Register reg_stored, reg_loaded; |
| 1217 reg_stored = GetRd(str_instr); |
| 1218 reg_loaded = GetRd(ldr_instr); |
| 1219 pc_ -= 1 * kInstrSize; |
| 1220 // Insert a mov instruction, which is better than ldr. |
| 1221 mov(reg_loaded, reg_stored); |
| 1222 if (FLAG_print_peephole_optimization) { |
| 1223 PrintF("%x str/ldr (fp + same offset), diff reg \n", pc_offset()); |
| 1224 } |
| 1225 } |
| 1226 } |
| 1227 } |
| 1228 |
| 1229 pattern_size = 3 * kInstrSize; |
| 1230 if (FLAG_push_pop_elimination && |
| 1231 last_bound_pos_ <= (pc_offset() - pattern_size) && |
| 1232 reloc_info_writer.last_pc() <= (pc_ - pattern_size)) { |
| 1233 Instr mem_write_instr = instr_at(pc_ - 3 * kInstrSize); |
| 1234 Instr ldr_instr = instr_at(pc_ - 2 * kInstrSize); |
| 1235 Instr mem_read_instr = instr_at(pc_ - 1 * kInstrSize); |
| 1236 if (IsPush(mem_write_instr) && |
| 1237 IsPop(mem_read_instr)) { |
| 1238 if ((IsLdrRegFpOffset(ldr_instr) || |
| 1239 IsLdrRegFpNegOffset(ldr_instr))) { |
| 1240 if ((mem_write_instr & kRdMask) == |
| 1241 (mem_read_instr & kRdMask)) { |
| 1242 // Pattern: push & pop from/to same register, |
| 1243 // with a fp+offset ldr in between |
| 1244 // |
| 1245 // The following: |
| 1246 // str rx, [sp, #-4]! |
| 1247 // ldr rz, [fp, #-24] |
| 1248 // ldr rx, [sp], #+4 |
| 1249 // |
| 1250 // Becomes: |
| 1251 // if(rx == rz) |
| 1252 // delete all |
| 1253 // else |
| 1254 // ldr rz, [fp, #-24] |
| 1255 |
| 1256 if ((mem_write_instr & kRdMask) == (ldr_instr & kRdMask)) { |
| 1257 pc_ -= 3 * kInstrSize; |
| 1258 } else { |
| 1259 pc_ -= 3 * kInstrSize; |
| 1260 // Reinsert back the ldr rz. |
| 1261 emit(ldr_instr); |
| 1262 } |
| 1263 if (FLAG_print_push_pop_elimination) { |
| 1264 PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset()); |
| 1265 } |
| 1266 } else { |
| 1267 // Pattern: push & pop from/to different registers |
| 1268 // with a fp+offset ldr in between |
| 1269 // |
| 1270 // The following: |
| 1271 // str rx, [sp, #-4]! |
| 1272 // ldr rz, [fp, #-24] |
| 1273 // ldr ry, [sp], #+4 |
| 1274 // |
| 1275 // Becomes: |
| 1276 // if(ry == rz) |
| 1277 // mov ry, rx; |
| 1278 // else if(rx != rz) |
| 1279 // ldr rz, [fp, #-24] |
| 1280 // mov ry, rx |
| 1281 // else if((ry != rz) || (rx == rz)) becomes: |
| 1282 // mov ry, rx |
| 1283 // ldr rz, [fp, #-24] |
| 1284 |
| 1285 Register reg_pushed, reg_popped; |
| 1286 if ((mem_read_instr & kRdMask) == (ldr_instr & kRdMask)) { |
| 1287 reg_pushed = GetRd(mem_write_instr); |
| 1288 reg_popped = GetRd(mem_read_instr); |
| 1289 pc_ -= 3 * kInstrSize; |
| 1290 mov(reg_popped, reg_pushed); |
| 1291 } else if ((mem_write_instr & kRdMask) |
| 1292 != (ldr_instr & kRdMask)) { |
| 1293 reg_pushed = GetRd(mem_write_instr); |
| 1294 reg_popped = GetRd(mem_read_instr); |
| 1295 pc_ -= 3 * kInstrSize; |
| 1296 emit(ldr_instr); |
| 1297 mov(reg_popped, reg_pushed); |
| 1298 } else if (((mem_read_instr & kRdMask) |
| 1299 != (ldr_instr & kRdMask)) || |
| 1300 ((mem_write_instr & kRdMask) |
| 1301 == (ldr_instr & kRdMask)) ) { |
| 1302 reg_pushed = GetRd(mem_write_instr); |
| 1303 reg_popped = GetRd(mem_read_instr); |
| 1304 pc_ -= 3 * kInstrSize; |
| 1305 mov(reg_popped, reg_pushed); |
| 1306 emit(ldr_instr); |
| 1307 } |
| 1308 if (FLAG_print_push_pop_elimination) { |
| 1309 PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset()); |
| 1310 } |
| 1311 } |
| 1312 } |
1103 } | 1313 } |
1104 } | 1314 } |
1105 } | 1315 } |
1106 | 1316 |
1107 | 1317 |
1108 void Assembler::str(Register src, const MemOperand& dst, Condition cond) { | 1318 void Assembler::str(Register src, const MemOperand& dst, Condition cond) { |
1109 addrmod2(cond | B26, src, dst); | 1319 addrmod2(cond | B26, src, dst); |
1110 | 1320 |
1111 // Eliminate pattern: pop(), push(r) | 1321 // Eliminate pattern: pop(), push(r) |
1112 // add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al | 1322 // add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al |
(...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2055 bind(&after_pool); | 2265 bind(&after_pool); |
2056 } | 2266 } |
2057 | 2267 |
2058 // Since a constant pool was just emitted, move the check offset forward by | 2268 // Since a constant pool was just emitted, move the check offset forward by |
2059 // the standard interval. | 2269 // the standard interval. |
2060 next_buffer_check_ = pc_offset() + kCheckConstInterval; | 2270 next_buffer_check_ = pc_offset() + kCheckConstInterval; |
2061 } | 2271 } |
2062 | 2272 |
2063 | 2273 |
2064 } } // namespace v8::internal | 2274 } } // namespace v8::internal |
OLD | NEW |