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 |