Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 registers_[pc] = value; | 421 registers_[pc] = value; |
| 422 } | 422 } |
| 423 | 423 |
| 424 | 424 |
| 425 // Raw access to the PC register without the special adjustment when reading. | 425 // Raw access to the PC register without the special adjustment when reading. |
| 426 int32_t Simulator::get_pc() const { | 426 int32_t Simulator::get_pc() const { |
| 427 return registers_[pc]; | 427 return registers_[pc]; |
| 428 } | 428 } |
| 429 | 429 |
| 430 | 430 |
| 431 // The ARM cannot do unaligned reads and writes. On some ARM platforms an | |
| 432 // interrupt is caused. On others it does a funky rotation thing. For now we | |
| 433 // simply disallow unaligned reads, but at some point we may want to move to | |
| 434 // emulating the rotate behaviour. Note that simulator runs have the runtime | |
| 435 // system running directly on the host system and only generated code is | |
| 436 // executed in the simulator. Since the host is typically IA32 we will not | |
| 437 // get the correct ARM-like behaviour on unaligned accesses. | |
| 438 | |
| 439 int Simulator::ReadW(int32_t addr) { | |
| 440 if ((addr & 3) == 0) { | |
| 441 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | |
| 442 return *ptr; | |
| 443 } | |
| 444 PrintF("Unaligned read at %x\n", addr); | |
|
iposva
2008/10/28 15:34:17
It would be helpful to print the PC and the addres
| |
| 445 UNIMPLEMENTED(); | |
| 446 return 0; | |
| 447 } | |
| 448 | |
| 449 | |
| 450 void Simulator::WriteW(int32_t addr, int value) { | |
| 451 if ((addr & 3) == 0) { | |
| 452 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | |
| 453 *ptr = value; | |
| 454 return; | |
| 455 } | |
| 456 PrintF("Unaligned write at %x\n", addr); | |
| 457 UNIMPLEMENTED(); | |
| 458 } | |
| 459 | |
| 460 | |
| 461 uint16_t Simulator::ReadHU(int32_t addr) { | |
| 462 if ((addr & 1) == 0) { | |
| 463 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | |
| 464 return *ptr; | |
| 465 } | |
| 466 PrintF("Unaligned read at %x\n", addr); | |
| 467 UNIMPLEMENTED(); | |
| 468 return 0; | |
| 469 } | |
| 470 | |
| 471 | |
| 472 int16_t Simulator::ReadH(int32_t addr) { | |
| 473 if ((addr & 1) == 0) { | |
| 474 int16_t* ptr = reinterpret_cast<int16_t*>(addr); | |
| 475 return *ptr; | |
| 476 } | |
| 477 PrintF("Unaligned read at %x\n", addr); | |
| 478 UNIMPLEMENTED(); | |
| 479 return 0; | |
| 480 } | |
| 481 | |
| 482 | |
| 483 void Simulator::WriteH(int32_t addr, uint16_t value) { | |
|
iposva
2008/10/28 15:34:17
The two WriteH and WriteB variants are really hard
| |
| 484 if ((addr & 1) == 0) { | |
| 485 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | |
| 486 *ptr = value; | |
| 487 return; | |
| 488 } | |
| 489 PrintF("Unaligned write at %x\n", addr); | |
| 490 UNIMPLEMENTED(); | |
| 491 } | |
| 492 | |
| 493 | |
| 494 void Simulator::WriteH(int32_t addr, int16_t value) { | |
| 495 if ((addr & 1) == 0) { | |
| 496 int16_t* ptr = reinterpret_cast<int16_t*>(addr); | |
| 497 *ptr = value; | |
| 498 return; | |
| 499 } | |
| 500 PrintF("Unaligned write at %x\n", addr); | |
| 501 UNIMPLEMENTED(); | |
| 502 } | |
| 503 | |
| 504 | |
| 505 uint8_t Simulator::ReadBU(int32_t addr) { | |
| 506 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | |
|
iposva
2008/10/28 15:34:17
Why no alignment check here? ;-)
| |
| 507 return *ptr; | |
| 508 } | |
| 509 | |
| 510 | |
| 511 int8_t Simulator::ReadB(int32_t addr) { | |
| 512 int8_t* ptr = reinterpret_cast<int8_t*>(addr); | |
| 513 return *ptr; | |
| 514 } | |
| 515 | |
| 516 | |
| 517 void Simulator::WriteB(int32_t addr, uint8_t value) { | |
| 518 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | |
| 519 *ptr = value; | |
| 520 } | |
| 521 | |
| 522 | |
| 523 void Simulator::WriteB(int32_t addr, int8_t value) { | |
| 524 int8_t* ptr = reinterpret_cast<int8_t*>(addr); | |
| 525 *ptr = value; | |
| 526 } | |
| 527 | |
| 528 | |
| 431 // Returns the limit of the stack area to enable checking for stack overflows. | 529 // Returns the limit of the stack area to enable checking for stack overflows. |
| 432 uintptr_t Simulator::StackLimit() const { | 530 uintptr_t Simulator::StackLimit() const { |
| 433 // Leave a safety margin of 256 bytes to prevent overrunning the stack when | 531 // Leave a safety margin of 256 bytes to prevent overrunning the stack when |
| 434 // pushing values. | 532 // pushing values. |
| 435 return reinterpret_cast<uintptr_t>(stack_) + 256; | 533 return reinterpret_cast<uintptr_t>(stack_) + 256; |
| 436 } | 534 } |
| 437 | 535 |
| 438 | 536 |
| 439 // Unsupported instructions use Format to print an error and stop execution. | 537 // Unsupported instructions use Format to print an error and stop execution. |
| 440 void Simulator::Format(Instr* instr, const char* format) { | 538 void Simulator::Format(Instr* instr, const char* format) { |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 946 } | 1044 } |
| 947 default: { | 1045 default: { |
| 948 // The PU field is a 2-bit field. | 1046 // The PU field is a 2-bit field. |
| 949 UNREACHABLE(); | 1047 UNREACHABLE(); |
| 950 break; | 1048 break; |
| 951 } | 1049 } |
| 952 } | 1050 } |
| 953 } | 1051 } |
| 954 if (instr->HasH()) { | 1052 if (instr->HasH()) { |
| 955 if (instr->HasSign()) { | 1053 if (instr->HasSign()) { |
| 956 int16_t* haddr = reinterpret_cast<int16_t*>(addr); | |
| 957 if (instr->HasL()) { | 1054 if (instr->HasL()) { |
| 958 int16_t val = *haddr; | 1055 int16_t val = ReadH(addr); |
| 959 set_register(rd, val); | 1056 set_register(rd, val); |
| 960 } else { | 1057 } else { |
| 961 int16_t val = get_register(rd); | 1058 int16_t val = get_register(rd); |
| 962 *haddr = val; | 1059 WriteH(addr, val); |
| 963 } | 1060 } |
| 964 } else { | 1061 } else { |
| 965 uint16_t* haddr = reinterpret_cast<uint16_t*>(addr); | |
| 966 if (instr->HasL()) { | 1062 if (instr->HasL()) { |
| 967 uint16_t val = *haddr; | 1063 uint16_t val = ReadHU(addr); |
| 968 set_register(rd, val); | 1064 set_register(rd, val); |
| 969 } else { | 1065 } else { |
| 970 uint16_t val = get_register(rd); | 1066 uint16_t val = get_register(rd); |
| 971 *haddr = val; | 1067 WriteH(addr, val); |
| 972 } | 1068 } |
| 973 } | 1069 } |
| 974 } else { | 1070 } else { |
| 975 // signed byte loads | 1071 // signed byte loads |
| 976 ASSERT(instr->HasSign()); | 1072 ASSERT(instr->HasSign()); |
| 977 ASSERT(instr->HasL()); | 1073 ASSERT(instr->HasL()); |
| 978 int8_t* baddr = reinterpret_cast<int8_t*>(addr); | 1074 int8_t val = ReadB(addr); |
| 979 int8_t val = *baddr; | |
| 980 set_register(rd, val); | 1075 set_register(rd, val); |
| 981 } | 1076 } |
| 982 return; | 1077 return; |
| 983 } | 1078 } |
| 984 } else { | 1079 } else { |
| 985 int rd = instr->RdField(); | 1080 int rd = instr->RdField(); |
| 986 int rn = instr->RnField(); | 1081 int rn = instr->RnField(); |
| 987 int32_t rn_val = get_register(rn); | 1082 int32_t rn_val = get_register(rn); |
| 988 int32_t shifter_operand = 0; | 1083 int32_t shifter_operand = 0; |
| 989 bool shifter_carry_out = 0; | 1084 bool shifter_carry_out = 0; |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1224 set_register(rn, rn_val); | 1319 set_register(rn, rn_val); |
| 1225 } | 1320 } |
| 1226 break; | 1321 break; |
| 1227 } | 1322 } |
| 1228 default: { | 1323 default: { |
| 1229 UNREACHABLE(); | 1324 UNREACHABLE(); |
| 1230 break; | 1325 break; |
| 1231 } | 1326 } |
| 1232 } | 1327 } |
| 1233 if (instr->HasB()) { | 1328 if (instr->HasB()) { |
| 1234 byte* baddr = reinterpret_cast<byte*>(addr); | |
| 1235 if (instr->HasL()) { | 1329 if (instr->HasL()) { |
| 1236 byte val = *baddr; | 1330 byte val = ReadBU(addr); |
| 1237 set_register(rd, val); | 1331 set_register(rd, val); |
| 1238 } else { | 1332 } else { |
| 1239 byte val = get_register(rd); | 1333 byte val = get_register(rd); |
| 1240 *baddr = val; | 1334 WriteB(addr, val); |
| 1241 } | 1335 } |
| 1242 } else { | 1336 } else { |
| 1243 intptr_t* iaddr = reinterpret_cast<intptr_t*>(addr); | |
| 1244 if (instr->HasL()) { | 1337 if (instr->HasL()) { |
| 1245 set_register(rd, *iaddr); | 1338 set_register(rd, ReadW(addr)); |
| 1246 } else { | 1339 } else { |
| 1247 *iaddr = get_register(rd); | 1340 WriteW(addr, get_register(rd)); |
| 1248 } | 1341 } |
| 1249 } | 1342 } |
| 1250 } | 1343 } |
| 1251 | 1344 |
| 1252 | 1345 |
| 1253 void Simulator::DecodeType3(Instr* instr) { | 1346 void Simulator::DecodeType3(Instr* instr) { |
| 1254 int rd = instr->RdField(); | 1347 int rd = instr->RdField(); |
| 1255 int rn = instr->RnField(); | 1348 int rn = instr->RnField(); |
| 1256 int32_t rn_val = get_register(rn); | 1349 int32_t rn_val = get_register(rn); |
| 1257 bool shifter_carry_out = 0; | 1350 bool shifter_carry_out = 0; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1285 break; | 1378 break; |
| 1286 } | 1379 } |
| 1287 default: { | 1380 default: { |
| 1288 UNREACHABLE(); | 1381 UNREACHABLE(); |
| 1289 break; | 1382 break; |
| 1290 } | 1383 } |
| 1291 } | 1384 } |
| 1292 if (instr->HasB()) { | 1385 if (instr->HasB()) { |
| 1293 UNIMPLEMENTED(); | 1386 UNIMPLEMENTED(); |
| 1294 } else { | 1387 } else { |
| 1295 intptr_t* iaddr = reinterpret_cast<intptr_t*>(addr); | |
| 1296 if (instr->HasL()) { | 1388 if (instr->HasL()) { |
| 1297 set_register(rd, *iaddr); | 1389 set_register(rd, ReadW(addr)); |
| 1298 } else { | 1390 } else { |
| 1299 *iaddr = get_register(rd); | 1391 WriteW(addr, get_register(rd)); |
| 1300 } | 1392 } |
| 1301 } | 1393 } |
| 1302 } | 1394 } |
| 1303 | 1395 |
| 1304 | 1396 |
| 1305 void Simulator::DecodeType4(Instr* instr) { | 1397 void Simulator::DecodeType4(Instr* instr) { |
| 1306 ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode | 1398 ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode |
| 1307 if (instr->HasL()) { | 1399 if (instr->HasL()) { |
| 1308 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); | 1400 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); |
| 1309 HandleRList(instr, true); | 1401 HandleRList(instr, true); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1497 set_register(r10, r10_val); | 1589 set_register(r10, r10_val); |
| 1498 set_register(r11, r11_val); | 1590 set_register(r11, r11_val); |
| 1499 | 1591 |
| 1500 int result = get_register(r0); | 1592 int result = get_register(r0); |
| 1501 return reinterpret_cast<Object*>(result); | 1593 return reinterpret_cast<Object*>(result); |
| 1502 } | 1594 } |
| 1503 | 1595 |
| 1504 } } // namespace assembler::arm | 1596 } } // namespace assembler::arm |
| 1505 | 1597 |
| 1506 #endif // !defined(__arm__) | 1598 #endif // !defined(__arm__) |
| OLD | NEW |