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 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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. | 271 // A mask for the Rd register for push, pop, ldr, str instructions. |
272 const Instr kRdMask = 0x0000f000; | 272 const Instr kRdMask = 0x0000f000; |
| 273 static const int kRdShift = 12; |
273 static const Instr kLdrRegFpOffsetPattern = | 274 static const Instr kLdrRegFpOffsetPattern = |
274 al | B26 | L | Offset | fp.code() * B16; | 275 al | B26 | L | Offset | fp.code() * B16; |
275 static const Instr kStrRegFpOffsetPattern = | 276 static const Instr kStrRegFpOffsetPattern = |
276 al | B26 | Offset | fp.code() * B16; | 277 al | B26 | Offset | fp.code() * B16; |
277 static const Instr kLdrRegFpNegOffsetPattern = | 278 static const Instr kLdrRegFpNegOffsetPattern = |
278 al | B26 | L | NegOffset | fp.code() * B16; | 279 al | B26 | L | NegOffset | fp.code() * B16; |
279 static const Instr kStrRegFpNegOffsetPattern = | 280 static const Instr kStrRegFpNegOffsetPattern = |
280 al | B26 | NegOffset | fp.code() * B16; | 281 al | B26 | NegOffset | fp.code() * B16; |
281 static const Instr kLdrStrInstrTypeMask = 0xffff0000; | 282 static const Instr kLdrStrInstrTypeMask = 0xffff0000; |
282 static const Instr kLdrStrInstrArgumentMask = 0x0000ffff; | 283 static const Instr kLdrStrInstrArgumentMask = 0x0000ffff; |
283 static const Instr kLdrStrOffsetMask = 0x00000fff; | 284 static const Instr kLdrStrOffsetMask = 0x00000fff; |
284 static const int kRdShift = 12; | |
285 | 285 |
286 // Spare buffer. | 286 // Spare buffer. |
287 static const int kMinimalBufferSize = 4*KB; | 287 static const int kMinimalBufferSize = 4*KB; |
288 static byte* spare_buffer_ = NULL; | 288 static byte* spare_buffer_ = NULL; |
289 | 289 |
290 Assembler::Assembler(void* buffer, int buffer_size) { | 290 Assembler::Assembler(void* buffer, int buffer_size) { |
291 if (buffer == NULL) { | 291 if (buffer == NULL) { |
292 // Do our own buffer management. | 292 // Do our own buffer management. |
293 if (buffer_size <= kMinimalBufferSize) { | 293 if (buffer_size <= kMinimalBufferSize) { |
294 buffer_size = kMinimalBufferSize; | 294 buffer_size = kMinimalBufferSize; |
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
931 | 931 |
932 | 932 |
933 void Assembler::add(Register dst, Register src1, const Operand& src2, | 933 void Assembler::add(Register dst, Register src1, const Operand& src2, |
934 SBit s, Condition cond) { | 934 SBit s, Condition cond) { |
935 addrmod1(cond | 4*B21 | s, src1, dst, src2); | 935 addrmod1(cond | 4*B21 | s, src1, dst, src2); |
936 | 936 |
937 // Eliminate pattern: push(r), pop() | 937 // Eliminate pattern: push(r), pop() |
938 // str(src, MemOperand(sp, 4, NegPreIndex), al); | 938 // str(src, MemOperand(sp, 4, NegPreIndex), al); |
939 // add(sp, sp, Operand(kPointerSize)); | 939 // add(sp, sp, Operand(kPointerSize)); |
940 // Both instructions can be eliminated. | 940 // Both instructions can be eliminated. |
941 int pattern_size = 2 * kInstrSize; | 941 if (can_peephole_optimize(2) && |
942 if (FLAG_push_pop_elimination && | |
943 last_bound_pos_ <= (pc_offset() - pattern_size) && | |
944 reloc_info_writer.last_pc() <= (pc_ - pattern_size) && | |
945 // Pattern. | 942 // Pattern. |
946 instr_at(pc_ - 1 * kInstrSize) == kPopInstruction && | 943 instr_at(pc_ - 1 * kInstrSize) == kPopInstruction && |
947 (instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) { | 944 (instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) { |
948 pc_ -= 2 * kInstrSize; | 945 pc_ -= 2 * kInstrSize; |
949 if (FLAG_print_push_pop_elimination) { | 946 if (FLAG_print_peephole_optimization) { |
950 PrintF("%x push(reg)/pop() eliminated\n", pc_offset()); | 947 PrintF("%x push(reg)/pop() eliminated\n", pc_offset()); |
951 } | 948 } |
952 } | 949 } |
953 } | 950 } |
954 | 951 |
955 | 952 |
956 void Assembler::adc(Register dst, Register src1, const Operand& src2, | 953 void Assembler::adc(Register dst, Register src1, const Operand& src2, |
957 SBit s, Condition cond) { | 954 SBit s, Condition cond) { |
958 addrmod1(cond | 5*B21 | s, src1, dst, src2); | 955 addrmod1(cond | 5*B21 | s, src1, dst, src2); |
959 } | 956 } |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1136 WriteRecordedPositions(); | 1133 WriteRecordedPositions(); |
1137 } | 1134 } |
1138 addrmod2(cond | B26 | L, dst, src); | 1135 addrmod2(cond | B26 | L, dst, src); |
1139 | 1136 |
1140 // Eliminate pattern: push(ry), pop(rx) | 1137 // Eliminate pattern: push(ry), pop(rx) |
1141 // str(ry, MemOperand(sp, 4, NegPreIndex), al) | 1138 // str(ry, MemOperand(sp, 4, NegPreIndex), al) |
1142 // ldr(rx, MemOperand(sp, 4, PostIndex), al) | 1139 // ldr(rx, MemOperand(sp, 4, PostIndex), al) |
1143 // Both instructions can be eliminated if ry = rx. | 1140 // Both instructions can be eliminated if ry = rx. |
1144 // If ry != rx, a register copy from ry to rx is inserted | 1141 // If ry != rx, a register copy from ry to rx is inserted |
1145 // after eliminating the push and the pop instructions. | 1142 // after eliminating the push and the pop instructions. |
1146 int pattern_size = 2 * kInstrSize; | |
1147 Instr push_instr = instr_at(pc_ - 2 * kInstrSize); | 1143 Instr push_instr = instr_at(pc_ - 2 * kInstrSize); |
1148 Instr pop_instr = instr_at(pc_ - 1 * kInstrSize); | 1144 Instr pop_instr = instr_at(pc_ - 1 * kInstrSize); |
1149 | 1145 |
1150 if (FLAG_push_pop_elimination && | 1146 if (can_peephole_optimize(2) && |
1151 last_bound_pos_ <= (pc_offset() - pattern_size) && | 1147 IsPush(push_instr) && |
1152 reloc_info_writer.last_pc() <= (pc_ - pattern_size) && | 1148 IsPop(pop_instr)) { |
1153 IsPush(push_instr) && | |
1154 IsPop(pop_instr)) { | |
1155 if ((pop_instr & kRdMask) != (push_instr & kRdMask)) { | 1149 if ((pop_instr & kRdMask) != (push_instr & kRdMask)) { |
1156 // For consecutive push and pop on different registers, | 1150 // For consecutive push and pop on different registers, |
1157 // we delete both the push & pop and insert a register move. | 1151 // we delete both the push & pop and insert a register move. |
1158 // push ry, pop rx --> mov rx, ry | 1152 // push ry, pop rx --> mov rx, ry |
1159 Register reg_pushed, reg_popped; | 1153 Register reg_pushed, reg_popped; |
1160 reg_pushed = GetRd(push_instr); | 1154 reg_pushed = GetRd(push_instr); |
1161 reg_popped = GetRd(pop_instr); | 1155 reg_popped = GetRd(pop_instr); |
1162 pc_ -= 2 * kInstrSize; | 1156 pc_ -= 2 * kInstrSize; |
1163 // Insert a mov instruction, which is better than a pair of push & pop | 1157 // Insert a mov instruction, which is better than a pair of push & pop |
1164 mov(reg_popped, reg_pushed); | 1158 mov(reg_popped, reg_pushed); |
1165 if (FLAG_print_push_pop_elimination) { | 1159 if (FLAG_print_peephole_optimization) { |
1166 PrintF("%x push/pop (diff reg) replaced by a reg move\n", pc_offset()); | 1160 PrintF("%x push/pop (diff reg) replaced by a reg move\n", pc_offset()); |
1167 } | 1161 } |
1168 } else { | 1162 } else { |
1169 // For consecutive push and pop on the same register, | 1163 // For consecutive push and pop on the same register, |
1170 // both the push and the pop can be deleted. | 1164 // both the push and the pop can be deleted. |
1171 pc_ -= 2 * kInstrSize; | 1165 pc_ -= 2 * kInstrSize; |
1172 if (FLAG_print_push_pop_elimination) { | 1166 if (FLAG_print_peephole_optimization) { |
1173 PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); | 1167 PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); |
1174 } | 1168 } |
1175 } | 1169 } |
1176 } | 1170 } |
1177 | 1171 |
1178 pattern_size = 2 * kInstrSize; | 1172 if (can_peephole_optimize(2)) { |
1179 if (FLAG_peephole_optimization && | |
1180 last_bound_pos_ <= (pc_offset() - pattern_size) && | |
1181 reloc_info_writer.last_pc() <= (pc_ - pattern_size)) { | |
1182 Instr str_instr = instr_at(pc_ - 2 * kInstrSize); | 1173 Instr str_instr = instr_at(pc_ - 2 * kInstrSize); |
1183 Instr ldr_instr = instr_at(pc_ - 1 * kInstrSize); | 1174 Instr ldr_instr = instr_at(pc_ - 1 * kInstrSize); |
1184 | 1175 |
1185 if ((IsStrRegFpOffset(str_instr) && | 1176 if ((IsStrRegFpOffset(str_instr) && |
1186 IsLdrRegFpOffset(ldr_instr)) || | 1177 IsLdrRegFpOffset(ldr_instr)) || |
1187 (IsStrRegFpNegOffset(str_instr) && | 1178 (IsStrRegFpNegOffset(str_instr) && |
1188 IsLdrRegFpNegOffset(ldr_instr))) { | 1179 IsLdrRegFpNegOffset(ldr_instr))) { |
1189 if ((ldr_instr & kLdrStrInstrArgumentMask) == | 1180 if ((ldr_instr & kLdrStrInstrArgumentMask) == |
1190 (str_instr & kLdrStrInstrArgumentMask)) { | 1181 (str_instr & kLdrStrInstrArgumentMask)) { |
1191 // Pattern: Ldr/str same fp+offset, same register. | 1182 // Pattern: Ldr/str same fp+offset, same register. |
(...skipping 27 matching lines...) Expand all Loading... |
1219 pc_ -= 1 * kInstrSize; | 1210 pc_ -= 1 * kInstrSize; |
1220 // Insert a mov instruction, which is better than ldr. | 1211 // Insert a mov instruction, which is better than ldr. |
1221 mov(reg_loaded, reg_stored); | 1212 mov(reg_loaded, reg_stored); |
1222 if (FLAG_print_peephole_optimization) { | 1213 if (FLAG_print_peephole_optimization) { |
1223 PrintF("%x str/ldr (fp + same offset), diff reg \n", pc_offset()); | 1214 PrintF("%x str/ldr (fp + same offset), diff reg \n", pc_offset()); |
1224 } | 1215 } |
1225 } | 1216 } |
1226 } | 1217 } |
1227 } | 1218 } |
1228 | 1219 |
1229 pattern_size = 3 * kInstrSize; | 1220 if (can_peephole_optimize(3)) { |
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); | 1221 Instr mem_write_instr = instr_at(pc_ - 3 * kInstrSize); |
1234 Instr ldr_instr = instr_at(pc_ - 2 * kInstrSize); | 1222 Instr ldr_instr = instr_at(pc_ - 2 * kInstrSize); |
1235 Instr mem_read_instr = instr_at(pc_ - 1 * kInstrSize); | 1223 Instr mem_read_instr = instr_at(pc_ - 1 * kInstrSize); |
1236 if (IsPush(mem_write_instr) && | 1224 if (IsPush(mem_write_instr) && |
1237 IsPop(mem_read_instr)) { | 1225 IsPop(mem_read_instr)) { |
1238 if ((IsLdrRegFpOffset(ldr_instr) || | 1226 if ((IsLdrRegFpOffset(ldr_instr) || |
1239 IsLdrRegFpNegOffset(ldr_instr))) { | 1227 IsLdrRegFpNegOffset(ldr_instr))) { |
1240 if ((mem_write_instr & kRdMask) == | 1228 if ((mem_write_instr & kRdMask) == |
1241 (mem_read_instr & kRdMask)) { | 1229 (mem_read_instr & kRdMask)) { |
1242 // Pattern: push & pop from/to same register, | 1230 // Pattern: push & pop from/to same register, |
(...skipping 10 matching lines...) Expand all Loading... |
1253 // else | 1241 // else |
1254 // ldr rz, [fp, #-24] | 1242 // ldr rz, [fp, #-24] |
1255 | 1243 |
1256 if ((mem_write_instr & kRdMask) == (ldr_instr & kRdMask)) { | 1244 if ((mem_write_instr & kRdMask) == (ldr_instr & kRdMask)) { |
1257 pc_ -= 3 * kInstrSize; | 1245 pc_ -= 3 * kInstrSize; |
1258 } else { | 1246 } else { |
1259 pc_ -= 3 * kInstrSize; | 1247 pc_ -= 3 * kInstrSize; |
1260 // Reinsert back the ldr rz. | 1248 // Reinsert back the ldr rz. |
1261 emit(ldr_instr); | 1249 emit(ldr_instr); |
1262 } | 1250 } |
1263 if (FLAG_print_push_pop_elimination) { | 1251 if (FLAG_print_peephole_optimization) { |
1264 PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset()); | 1252 PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset()); |
1265 } | 1253 } |
1266 } else { | 1254 } else { |
1267 // Pattern: push & pop from/to different registers | 1255 // Pattern: push & pop from/to different registers |
1268 // with a fp+offset ldr in between | 1256 // with a fp+offset ldr in between |
1269 // | 1257 // |
1270 // The following: | 1258 // The following: |
1271 // str rx, [sp, #-4]! | 1259 // str rx, [sp, #-4]! |
1272 // ldr rz, [fp, #-24] | 1260 // ldr rz, [fp, #-24] |
1273 // ldr ry, [sp], #+4 | 1261 // ldr ry, [sp], #+4 |
(...skipping 24 matching lines...) Expand all Loading... |
1298 } else if (((mem_read_instr & kRdMask) | 1286 } else if (((mem_read_instr & kRdMask) |
1299 != (ldr_instr & kRdMask)) || | 1287 != (ldr_instr & kRdMask)) || |
1300 ((mem_write_instr & kRdMask) | 1288 ((mem_write_instr & kRdMask) |
1301 == (ldr_instr & kRdMask)) ) { | 1289 == (ldr_instr & kRdMask)) ) { |
1302 reg_pushed = GetRd(mem_write_instr); | 1290 reg_pushed = GetRd(mem_write_instr); |
1303 reg_popped = GetRd(mem_read_instr); | 1291 reg_popped = GetRd(mem_read_instr); |
1304 pc_ -= 3 * kInstrSize; | 1292 pc_ -= 3 * kInstrSize; |
1305 mov(reg_popped, reg_pushed); | 1293 mov(reg_popped, reg_pushed); |
1306 emit(ldr_instr); | 1294 emit(ldr_instr); |
1307 } | 1295 } |
1308 if (FLAG_print_push_pop_elimination) { | 1296 if (FLAG_print_peephole_optimization) { |
1309 PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset()); | 1297 PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset()); |
1310 } | 1298 } |
1311 } | 1299 } |
1312 } | 1300 } |
1313 } | 1301 } |
1314 } | 1302 } |
1315 } | 1303 } |
1316 | 1304 |
1317 | 1305 |
1318 void Assembler::str(Register src, const MemOperand& dst, Condition cond) { | 1306 void Assembler::str(Register src, const MemOperand& dst, Condition cond) { |
1319 addrmod2(cond | B26, src, dst); | 1307 addrmod2(cond | B26, src, dst); |
1320 | 1308 |
1321 // Eliminate pattern: pop(), push(r) | 1309 // Eliminate pattern: pop(), push(r) |
1322 // add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al | 1310 // add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al |
1323 // -> str r, [sp, 0], al | 1311 // -> str r, [sp, 0], al |
1324 int pattern_size = 2 * kInstrSize; | 1312 if (can_peephole_optimize(2) && |
1325 if (FLAG_push_pop_elimination && | |
1326 last_bound_pos_ <= (pc_offset() - pattern_size) && | |
1327 reloc_info_writer.last_pc() <= (pc_ - pattern_size) && | |
1328 // Pattern. | 1313 // Pattern. |
1329 instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) && | 1314 instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) && |
1330 instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) { | 1315 instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) { |
1331 pc_ -= 2 * kInstrSize; | 1316 pc_ -= 2 * kInstrSize; |
1332 emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12); | 1317 emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12); |
1333 if (FLAG_print_push_pop_elimination) { | 1318 if (FLAG_print_peephole_optimization) { |
1334 PrintF("%x pop()/push(reg) eliminated\n", pc_offset()); | 1319 PrintF("%x pop()/push(reg) eliminated\n", pc_offset()); |
1335 } | 1320 } |
1336 } | 1321 } |
1337 } | 1322 } |
1338 | 1323 |
1339 | 1324 |
1340 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) { | 1325 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) { |
1341 addrmod2(cond | B26 | B | L, dst, src); | 1326 addrmod2(cond | B26 | B | L, dst, src); |
1342 } | 1327 } |
1343 | 1328 |
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2265 bind(&after_pool); | 2250 bind(&after_pool); |
2266 } | 2251 } |
2267 | 2252 |
2268 // Since a constant pool was just emitted, move the check offset forward by | 2253 // Since a constant pool was just emitted, move the check offset forward by |
2269 // the standard interval. | 2254 // the standard interval. |
2270 next_buffer_check_ = pc_offset() + kCheckConstInterval; | 2255 next_buffer_check_ = pc_offset() + kCheckConstInterval; |
2271 } | 2256 } |
2272 | 2257 |
2273 | 2258 |
2274 } } // namespace v8::internal | 2259 } } // namespace v8::internal |
OLD | NEW |