Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
|
Karl Klose
2011/04/06 06:52:56
2011
Søren Thygesen Gjesse
2011/04/06 08:00:09
Done.
| |
| 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, bool load) { | |
| 1576 VFPRegPrecision precision = | |
| 1577 (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision; | |
| 1578 int operand_size = (precision == kSinglePrecision) ? 4 : 8; | |
| 1579 | |
| 1580 int vd; | |
| 1581 int num_regs; | |
| 1582 if (precision == kSinglePrecision) { | |
| 1583 vd = instr->VdValue() << 1 | instr->DValue(); | |
|
Rodolph Perfetta
2011/04/05 18:16:39
Use instr->VFPDregValue(kSinglePrecision) here.
Søren Thygesen Gjesse
2011/04/06 08:00:09
Used
vd = instr->VFPDRegValue(precision);
befo
| |
| 1584 num_regs = instr->Immed8Value(); | |
| 1585 } else { | |
| 1586 vd = instr->VdValue(); | |
| 1587 num_regs = instr->Immed8Value() / 2; | |
| 1588 } | |
| 1589 | |
| 1590 intptr_t start_address = 0; | |
| 1591 intptr_t end_address = 0; | |
| 1592 ProcessPUW(instr, num_regs, operand_size, &start_address, &end_address); | |
| 1593 | |
| 1594 intptr_t* address = reinterpret_cast<intptr_t*>(start_address); | |
| 1595 for (int reg = vd; reg < vd + num_regs; reg++) { | |
| 1596 if (precision == kSinglePrecision) { | |
| 1597 if (load) { | |
| 1598 set_s_register_from_sinteger( | |
| 1599 reg, ReadW(reinterpret_cast<int32_t>(address), instr)); | |
| 1600 } else { | |
| 1601 WriteW(reinterpret_cast<int32_t>(address), | |
| 1602 get_sinteger_from_s_register(reg), instr); | |
| 1603 } | |
| 1604 address += 1; | |
| 1605 } else { | |
| 1606 if (load) { | |
| 1607 set_s_register_from_sinteger( | |
| 1608 2 * reg, ReadW(reinterpret_cast<int32_t>(address), instr)); | |
| 1609 set_s_register_from_sinteger( | |
| 1610 2 * reg + 1, ReadW(reinterpret_cast<int32_t>(address + 1), instr)); | |
| 1611 } else { | |
| 1612 WriteW(reinterpret_cast<int32_t>(address), | |
| 1613 get_sinteger_from_s_register(2 * reg), instr); | |
| 1614 WriteW(reinterpret_cast<int32_t>(address + 1), | |
| 1615 get_sinteger_from_s_register(2 * reg + 1), instr); | |
| 1616 } | |
| 1617 address += 2; | |
| 1618 } | |
| 1619 } | |
| 1620 ASSERT_EQ(((intptr_t)address) - operand_size, end_address); | |
| 1621 } | |
| 1622 | |
| 1623 | |
| 1565 // Calls into the V8 runtime are based on this very simple interface. | 1624 // 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 | 1625 // 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 | 1626 // 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 | 1627 // 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 | 1628 // 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. | 1629 // value, which is fine because it is caller-saved. |
| 1571 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 1630 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, |
| 1572 int32_t arg1, | 1631 int32_t arg1, |
| 1573 int32_t arg2, | 1632 int32_t arg2, |
| 1574 int32_t arg3, | 1633 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; | 2997 int32_t address = get_register(rn) + 4 * offset; |
| 2939 if (instr->HasL()) { | 2998 if (instr->HasL()) { |
| 2940 // Load double from memory: vldr. | 2999 // Load double from memory: vldr. |
| 2941 set_s_register_from_sinteger(vd, ReadW(address, instr)); | 3000 set_s_register_from_sinteger(vd, ReadW(address, instr)); |
| 2942 } else { | 3001 } else { |
| 2943 // Store double to memory: vstr. | 3002 // Store double to memory: vstr. |
| 2944 WriteW(address, get_sinteger_from_s_register(vd), instr); | 3003 WriteW(address, get_sinteger_from_s_register(vd), instr); |
| 2945 } | 3004 } |
| 2946 break; | 3005 break; |
| 2947 } | 3006 } |
| 2948 default: | 3007 default: { |
| 2949 UNIMPLEMENTED(); // Not used by V8. | 3008 BlockAddrMode am = |
| 3009 static_cast<BlockAddrMode>( | |
| 3010 instr->BitField(24, 21) & kBlockAddrModeMask); | |
| 3011 if (am == ia || am == ia_w || am == db_w) { | |
| 3012 bool to_arm_register = (instr->VLValue() == 0x1); | |
|
Rodolph Perfetta
2011/04/05 18:16:39
Since the instruction encoding is given to HandleV
Søren Thygesen Gjesse
2011/04/06 08:00:09
No - argument removed.
| |
| 3013 if (to_arm_register) { | |
| 3014 // Load multiple single from memory: vldm. | |
| 3015 HandleVList(instr, true); | |
| 3016 } else { | |
| 3017 HandleVList(instr, false); | |
| 3018 } | |
| 3019 } else { | |
| 3020 UNIMPLEMENTED(); // Not used by V8. | |
| 3021 } | |
| 2950 break; | 3022 break; |
| 3023 } | |
| 2951 } | 3024 } |
| 2952 } else if (instr->CoprocessorValue() == 0xB) { | 3025 } else if (instr->CoprocessorValue() == 0xB) { |
| 2953 switch (instr->OpcodeValue()) { | 3026 switch (instr->OpcodeValue()) { |
| 2954 case 0x2: | 3027 case 0x2: |
| 2955 // Load and store double to two GP registers | 3028 // Load and store double to two GP registers |
| 2956 if (instr->Bits(7, 4) != 0x1) { | 3029 if (instr->Bits(7, 4) != 0x1) { |
| 2957 UNIMPLEMENTED(); // Not used by V8. | 3030 UNIMPLEMENTED(); // Not used by V8. |
| 2958 } else { | 3031 } else { |
| 2959 int rt = instr->RtValue(); | 3032 int rt = instr->RtValue(); |
| 2960 int rn = instr->RnValue(); | 3033 int rn = instr->RnValue(); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 2987 // Load double from memory: vldr. | 3060 // Load double from memory: vldr. |
| 2988 set_s_register_from_sinteger(2*vd, ReadW(address, instr)); | 3061 set_s_register_from_sinteger(2*vd, ReadW(address, instr)); |
| 2989 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr)); | 3062 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr)); |
| 2990 } else { | 3063 } else { |
| 2991 // Store double to memory: vstr. | 3064 // Store double to memory: vstr. |
| 2992 WriteW(address, get_sinteger_from_s_register(2*vd), instr); | 3065 WriteW(address, get_sinteger_from_s_register(2*vd), instr); |
| 2993 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr); | 3066 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr); |
| 2994 } | 3067 } |
| 2995 break; | 3068 break; |
| 2996 } | 3069 } |
| 2997 default: | 3070 default: { |
| 2998 UNIMPLEMENTED(); // Not used by V8. | 3071 BlockAddrMode am = |
| 3072 static_cast<BlockAddrMode>( | |
| 3073 instr->BitField(24, 21) & kBlockAddrModeMask); | |
| 3074 if (am == ia || am == ia_w || am == db_w) { | |
| 3075 bool to_arm_register = (instr->VLValue() == 0x1); | |
|
Rodolph Perfetta
2011/04/05 18:16:39
Ditto.
Søren Thygesen Gjesse
2011/04/06 08:00:09
Done.
| |
| 3076 if (to_arm_register) { | |
| 3077 // Load multiple double from memory: vldm. | |
| 3078 HandleVList(instr, true); | |
| 3079 } else { | |
| 3080 HandleVList(instr, false); | |
| 3081 } | |
| 3082 } else { | |
| 3083 UNIMPLEMENTED(); // Not used by V8. | |
| 3084 } | |
| 2999 break; | 3085 break; |
| 3086 } | |
| 3000 } | 3087 } |
| 3001 } else { | 3088 } else { |
| 3002 UNIMPLEMENTED(); // Not used by V8. | 3089 UNIMPLEMENTED(); // Not used by V8. |
| 3003 } | 3090 } |
| 3004 } | 3091 } |
| 3005 | 3092 |
| 3006 | 3093 |
| 3007 // Executes the current instruction. | 3094 // Executes the current instruction. |
| 3008 void Simulator::InstructionDecode(Instruction* instr) { | 3095 void Simulator::InstructionDecode(Instruction* instr) { |
| 3009 if (v8::internal::FLAG_check_icache) { | 3096 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; | 3293 uintptr_t address = *stack_slot; |
| 3207 set_register(sp, current_sp + sizeof(uintptr_t)); | 3294 set_register(sp, current_sp + sizeof(uintptr_t)); |
| 3208 return address; | 3295 return address; |
| 3209 } | 3296 } |
| 3210 | 3297 |
| 3211 } } // namespace v8::internal | 3298 } } // namespace v8::internal |
| 3212 | 3299 |
| 3213 #endif // USE_SIMULATOR | 3300 #endif // USE_SIMULATOR |
| 3214 | 3301 |
| 3215 #endif // V8_TARGET_ARCH_ARM | 3302 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |