OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 1485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1497 while (bit_vector != 0) { | 1497 while (bit_vector != 0) { |
1498 if ((bit_vector & 1) != 0) { | 1498 if ((bit_vector & 1) != 0) { |
1499 count++; | 1499 count++; |
1500 } | 1500 } |
1501 bit_vector >>= 1; | 1501 bit_vector >>= 1; |
1502 } | 1502 } |
1503 return count; | 1503 return count; |
1504 } | 1504 } |
1505 | 1505 |
1506 | 1506 |
1507 // Addressing Mode 4 - Load and Store Multiple | 1507 void Simulator::ProcessPUW(Instruction* instr, |
1508 void Simulator::HandleRList(Instruction* instr, bool load) { | 1508 int num_regs, |
| 1509 int reg_size, |
| 1510 intptr_t* start_address, |
| 1511 intptr_t* end_address) { |
1509 int rn = instr->RnValue(); | 1512 int rn = instr->RnValue(); |
1510 int32_t rn_val = get_register(rn); | 1513 int32_t rn_val = get_register(rn); |
1511 int rlist = instr->RlistValue(); | |
1512 int num_regs = count_bits(rlist); | |
1513 | |
1514 intptr_t start_address = 0; | |
1515 intptr_t end_address = 0; | |
1516 switch (instr->PUField()) { | 1514 switch (instr->PUField()) { |
1517 case da_x: { | 1515 case da_x: { |
1518 UNIMPLEMENTED(); | 1516 UNIMPLEMENTED(); |
1519 break; | 1517 break; |
1520 } | 1518 } |
1521 case ia_x: { | 1519 case ia_x: { |
1522 start_address = rn_val; | 1520 *start_address = rn_val; |
1523 end_address = rn_val + (num_regs * 4) - 4; | 1521 *end_address = rn_val + (num_regs * reg_size) - reg_size; |
1524 rn_val = rn_val + (num_regs * 4); | 1522 rn_val = rn_val + (num_regs * reg_size); |
1525 break; | 1523 break; |
1526 } | 1524 } |
1527 case db_x: { | 1525 case db_x: { |
1528 start_address = rn_val - (num_regs * 4); | 1526 *start_address = rn_val - (num_regs * reg_size); |
1529 end_address = rn_val - 4; | 1527 *end_address = rn_val - reg_size; |
1530 rn_val = start_address; | 1528 rn_val = *start_address; |
1531 break; | 1529 break; |
1532 } | 1530 } |
1533 case ib_x: { | 1531 case ib_x: { |
1534 start_address = rn_val + 4; | 1532 *start_address = rn_val + reg_size; |
1535 end_address = rn_val + (num_regs * 4); | 1533 *end_address = rn_val + (num_regs * reg_size); |
1536 rn_val = end_address; | 1534 rn_val = *end_address; |
1537 break; | 1535 break; |
1538 } | 1536 } |
1539 default: { | 1537 default: { |
1540 UNREACHABLE(); | 1538 UNREACHABLE(); |
1541 break; | 1539 break; |
1542 } | 1540 } |
1543 } | 1541 } |
1544 if (instr->HasW()) { | 1542 if (instr->HasW()) { |
1545 set_register(rn, rn_val); | 1543 set_register(rn, rn_val); |
1546 } | 1544 } |
| 1545 } |
| 1546 |
| 1547 // Addressing Mode 4 - Load and Store Multiple |
| 1548 void Simulator::HandleRList(Instruction* instr, bool load) { |
| 1549 int rlist = instr->RlistValue(); |
| 1550 int num_regs = count_bits(rlist); |
| 1551 |
| 1552 intptr_t start_address = 0; |
| 1553 intptr_t end_address = 0; |
| 1554 ProcessPUW(instr, num_regs, kPointerSize, &start_address, &end_address); |
| 1555 |
1547 intptr_t* address = reinterpret_cast<intptr_t*>(start_address); | 1556 intptr_t* address = reinterpret_cast<intptr_t*>(start_address); |
1548 int reg = 0; | 1557 int reg = 0; |
1549 while (rlist != 0) { | 1558 while (rlist != 0) { |
1550 if ((rlist & 1) != 0) { | 1559 if ((rlist & 1) != 0) { |
1551 if (load) { | 1560 if (load) { |
1552 set_register(reg, *address); | 1561 set_register(reg, *address); |
1553 } else { | 1562 } else { |
1554 *address = get_register(reg); | 1563 *address = get_register(reg); |
1555 } | 1564 } |
1556 address += 1; | 1565 address += 1; |
1557 } | 1566 } |
1558 reg++; | 1567 reg++; |
1559 rlist >>= 1; | 1568 rlist >>= 1; |
1560 } | 1569 } |
1561 ASSERT(end_address == ((intptr_t)address) - 4); | 1570 ASSERT(end_address == ((intptr_t)address) - 4); |
1562 } | 1571 } |
1563 | 1572 |
1564 | 1573 |
| 1574 // Addressing Mode 6 - Load and Store Multiple Coprocessor registers. |
| 1575 void Simulator::HandleVList(Instruction* instr) { |
| 1576 VFPRegPrecision precision = |
| 1577 (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision; |
| 1578 int operand_size = (precision == kSinglePrecision) ? 4 : 8; |
| 1579 |
| 1580 bool load = (instr->VLValue() == 0x1); |
| 1581 |
| 1582 int vd; |
| 1583 int num_regs; |
| 1584 vd = instr->VFPDRegValue(precision); |
| 1585 if (precision == kSinglePrecision) { |
| 1586 num_regs = instr->Immed8Value(); |
| 1587 } else { |
| 1588 num_regs = instr->Immed8Value() / 2; |
| 1589 } |
| 1590 |
| 1591 intptr_t start_address = 0; |
| 1592 intptr_t end_address = 0; |
| 1593 ProcessPUW(instr, num_regs, operand_size, &start_address, &end_address); |
| 1594 |
| 1595 intptr_t* address = reinterpret_cast<intptr_t*>(start_address); |
| 1596 for (int reg = vd; reg < vd + num_regs; reg++) { |
| 1597 if (precision == kSinglePrecision) { |
| 1598 if (load) { |
| 1599 set_s_register_from_sinteger( |
| 1600 reg, ReadW(reinterpret_cast<int32_t>(address), instr)); |
| 1601 } else { |
| 1602 WriteW(reinterpret_cast<int32_t>(address), |
| 1603 get_sinteger_from_s_register(reg), instr); |
| 1604 } |
| 1605 address += 1; |
| 1606 } else { |
| 1607 if (load) { |
| 1608 set_s_register_from_sinteger( |
| 1609 2 * reg, ReadW(reinterpret_cast<int32_t>(address), instr)); |
| 1610 set_s_register_from_sinteger( |
| 1611 2 * reg + 1, ReadW(reinterpret_cast<int32_t>(address + 1), instr)); |
| 1612 } else { |
| 1613 WriteW(reinterpret_cast<int32_t>(address), |
| 1614 get_sinteger_from_s_register(2 * reg), instr); |
| 1615 WriteW(reinterpret_cast<int32_t>(address + 1), |
| 1616 get_sinteger_from_s_register(2 * reg + 1), instr); |
| 1617 } |
| 1618 address += 2; |
| 1619 } |
| 1620 } |
| 1621 ASSERT_EQ(((intptr_t)address) - operand_size, end_address); |
| 1622 } |
| 1623 |
| 1624 |
1565 // Calls into the V8 runtime are based on this very simple interface. | 1625 // Calls into the V8 runtime are based on this very simple interface. |
1566 // Note: To be able to return two values from some calls the code in runtime.cc | 1626 // Note: To be able to return two values from some calls the code in runtime.cc |
1567 // uses the ObjectPair which is essentially two 32-bit values stuffed into a | 1627 // uses the ObjectPair which is essentially two 32-bit values stuffed into a |
1568 // 64-bit value. With the code below we assume that all runtime calls return | 1628 // 64-bit value. With the code below we assume that all runtime calls return |
1569 // 64 bits of result. If they don't, the r1 result register contains a bogus | 1629 // 64 bits of result. If they don't, the r1 result register contains a bogus |
1570 // value, which is fine because it is caller-saved. | 1630 // value, which is fine because it is caller-saved. |
1571 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 1631 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, |
1572 int32_t arg1, | 1632 int32_t arg1, |
1573 int32_t arg2, | 1633 int32_t arg2, |
1574 int32_t arg3, | 1634 int32_t arg3, |
(...skipping 1363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2938 int32_t address = get_register(rn) + 4 * offset; | 2998 int32_t address = get_register(rn) + 4 * offset; |
2939 if (instr->HasL()) { | 2999 if (instr->HasL()) { |
2940 // Load double from memory: vldr. | 3000 // Load double from memory: vldr. |
2941 set_s_register_from_sinteger(vd, ReadW(address, instr)); | 3001 set_s_register_from_sinteger(vd, ReadW(address, instr)); |
2942 } else { | 3002 } else { |
2943 // Store double to memory: vstr. | 3003 // Store double to memory: vstr. |
2944 WriteW(address, get_sinteger_from_s_register(vd), instr); | 3004 WriteW(address, get_sinteger_from_s_register(vd), instr); |
2945 } | 3005 } |
2946 break; | 3006 break; |
2947 } | 3007 } |
| 3008 case 0x4: |
| 3009 case 0x5: |
| 3010 case 0x6: |
| 3011 case 0x7: |
| 3012 case 0x9: |
| 3013 case 0xB: |
| 3014 // Load/store multiple single from memory: vldm/vstm. |
| 3015 HandleVList(instr); |
| 3016 break; |
2948 default: | 3017 default: |
2949 UNIMPLEMENTED(); // Not used by V8. | 3018 UNIMPLEMENTED(); // Not used by V8. |
2950 break; | |
2951 } | 3019 } |
2952 } else if (instr->CoprocessorValue() == 0xB) { | 3020 } else if (instr->CoprocessorValue() == 0xB) { |
2953 switch (instr->OpcodeValue()) { | 3021 switch (instr->OpcodeValue()) { |
2954 case 0x2: | 3022 case 0x2: |
2955 // Load and store double to two GP registers | 3023 // Load and store double to two GP registers |
2956 if (instr->Bits(7, 4) != 0x1) { | 3024 if (instr->Bits(7, 4) != 0x1) { |
2957 UNIMPLEMENTED(); // Not used by V8. | 3025 UNIMPLEMENTED(); // Not used by V8. |
2958 } else { | 3026 } else { |
2959 int rt = instr->RtValue(); | 3027 int rt = instr->RtValue(); |
2960 int rn = instr->RnValue(); | 3028 int rn = instr->RnValue(); |
(...skipping 26 matching lines...) Expand all Loading... |
2987 // Load double from memory: vldr. | 3055 // Load double from memory: vldr. |
2988 set_s_register_from_sinteger(2*vd, ReadW(address, instr)); | 3056 set_s_register_from_sinteger(2*vd, ReadW(address, instr)); |
2989 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr)); | 3057 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr)); |
2990 } else { | 3058 } else { |
2991 // Store double to memory: vstr. | 3059 // Store double to memory: vstr. |
2992 WriteW(address, get_sinteger_from_s_register(2*vd), instr); | 3060 WriteW(address, get_sinteger_from_s_register(2*vd), instr); |
2993 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr); | 3061 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr); |
2994 } | 3062 } |
2995 break; | 3063 break; |
2996 } | 3064 } |
| 3065 case 0x4: |
| 3066 case 0x5: |
| 3067 case 0x9: |
| 3068 // Load/store multiple double from memory: vldm/vstm. |
| 3069 HandleVList(instr); |
| 3070 break; |
2997 default: | 3071 default: |
2998 UNIMPLEMENTED(); // Not used by V8. | 3072 UNIMPLEMENTED(); // Not used by V8. |
2999 break; | |
3000 } | 3073 } |
3001 } else { | 3074 } else { |
3002 UNIMPLEMENTED(); // Not used by V8. | 3075 UNIMPLEMENTED(); // Not used by V8. |
3003 } | 3076 } |
3004 } | 3077 } |
3005 | 3078 |
3006 | 3079 |
3007 // Executes the current instruction. | 3080 // Executes the current instruction. |
3008 void Simulator::InstructionDecode(Instruction* instr) { | 3081 void Simulator::InstructionDecode(Instruction* instr) { |
3009 if (v8::internal::FLAG_check_icache) { | 3082 if (v8::internal::FLAG_check_icache) { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3206 uintptr_t address = *stack_slot; | 3279 uintptr_t address = *stack_slot; |
3207 set_register(sp, current_sp + sizeof(uintptr_t)); | 3280 set_register(sp, current_sp + sizeof(uintptr_t)); |
3208 return address; | 3281 return address; |
3209 } | 3282 } |
3210 | 3283 |
3211 } } // namespace v8::internal | 3284 } } // namespace v8::internal |
3212 | 3285 |
3213 #endif // USE_SIMULATOR | 3286 #endif // USE_SIMULATOR |
3214 | 3287 |
3215 #endif // V8_TARGET_ARCH_ARM | 3288 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |