📄 simulator-arm.cc.svn-base
字号:
uint32_t uright = static_cast<uint32_t>(right); return (uright > uleft);}// Calculate V flag value for additions and subtractions.bool Simulator::OverflowFrom(int32_t alu_out, int32_t left, int32_t right, bool addition) { bool overflow; if (addition) { // operands have the same sign overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) // and operands and result have different sign && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); } else { // operands have different signs overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) // and first operand and result have different signs && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); } return overflow;}// Addressing Mode 1 - Data-processing operands:// Get the value based on the shifter_operand with register.int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { Shift shift = instr->ShiftField(); int shift_amount = instr->ShiftAmountField(); int32_t result = get_register(instr->RmField()); if (instr->Bit(4) == 0) { // by immediate if ((shift == ROR) && (shift_amount == 0)) { UNIMPLEMENTED(); return result; } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { shift_amount = 32; } switch (shift) { case ASR: { if (shift_amount == 0) { if (result < 0) { result = 0xffffffff; *carry_out = true; } else { result = 0; *carry_out = false; } } else { result >>= (shift_amount - 1); *carry_out = (result & 1) == 1; result >>= 1; } break; } case LSL: { if (shift_amount == 0) { *carry_out = c_flag_; } else { result <<= (shift_amount - 1); *carry_out = (result < 0); result <<= 1; } break; } case LSR: { if (shift_amount == 0) { result = 0; *carry_out = c_flag_; } else { uint32_t uresult = static_cast<uint32_t>(result); uresult >>= (shift_amount - 1); *carry_out = (uresult & 1) == 1; uresult >>= 1; result = static_cast<int32_t>(uresult); } break; } case ROR: { UNIMPLEMENTED(); break; } default: { UNREACHABLE(); break; } } } else { // by register int rs = instr->RsField(); shift_amount = get_register(rs) &0xff; switch (shift) { case ASR: { if (shift_amount == 0) { *carry_out = c_flag_; } else if (shift_amount < 32) { result >>= (shift_amount - 1); *carry_out = (result & 1) == 1; result >>= 1; } else { ASSERT(shift_amount >= 32); if (result < 0) { *carry_out = true; result = 0xffffffff; } else { *carry_out = false; result = 0; } } break; } case LSL: { if (shift_amount == 0) { *carry_out = c_flag_; } else if (shift_amount < 32) { result <<= (shift_amount - 1); *carry_out = (result < 0); result <<= 1; } else if (shift_amount == 32) { *carry_out = (result & 1) == 1; result = 0; } else { ASSERT(shift_amount > 32); *carry_out = false; result = 0; } break; } case LSR: { if (shift_amount == 0) { *carry_out = c_flag_; } else if (shift_amount < 32) { uint32_t uresult = static_cast<uint32_t>(result); uresult >>= (shift_amount - 1); *carry_out = (uresult & 1) == 1; uresult >>= 1; result = static_cast<int32_t>(uresult); } else if (shift_amount == 32) { *carry_out = (result < 0); result = 0; } else { *carry_out = false; result = 0; } break; } case ROR: { UNIMPLEMENTED(); break; } default: { UNREACHABLE(); break; } } } return result;}// Addressing Mode 1 - Data-processing operands:// Get the value based on the shifter_operand with immediate.int32_t Simulator::GetImm(Instr* instr, bool* carry_out) { int rotate = instr->RotateField() * 2; int immed8 = instr->Immed8Field(); int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); *carry_out = (rotate == 0) ? c_flag_ : (imm < 0); return imm;}static int count_bits(int bit_vector) { int count = 0; while (bit_vector != 0) { if ((bit_vector & 1) != 0) { count++; } bit_vector >>= 1; } return count;}// Addressing Mode 4 - Load and Store Multiplevoid Simulator::HandleRList(Instr* instr, bool load) { int rn = instr->RnField(); int32_t rn_val = get_register(rn); int rlist = instr->RlistField(); int num_regs = count_bits(rlist); intptr_t start_address = 0; intptr_t end_address = 0; switch (instr->PUField()) { case 0: { // Print("da"); UNIMPLEMENTED(); break; } case 1: { // Print("ia"); start_address = rn_val; end_address = rn_val + (num_regs * 4) - 4; rn_val = rn_val + (num_regs * 4); break; } case 2: { // Print("db"); start_address = rn_val - (num_regs * 4); end_address = rn_val - 4; rn_val = start_address; break; } case 3: { // Print("ib"); UNIMPLEMENTED(); break; } default: { UNREACHABLE(); break; } } if (instr->HasW()) { set_register(rn, rn_val); } intptr_t* address = reinterpret_cast<intptr_t*>(start_address); int reg = 0; while (rlist != 0) { if ((rlist & 1) != 0) { if (load) { set_register(reg, *address); } else { *address = get_register(reg); } address += 1; } reg++; rlist >>= 1; } ASSERT(end_address == ((intptr_t)address) - 4);}// Calls into the V8 runtime are based on this very simple interface.// Note: To be able to return two values from some calls the code in runtime.cc// uses the ObjectPair which is essentially two 32-bit values stuffed into a// 64-bit value. With the code below we assume that all runtime calls return// 64 bits of result. If they don't, the r1 result register contains a bogus// value, which is fine because it is caller-saved.typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1);// Software interrupt instructions are used by the simulator to call into the// C-based V8 runtime.void Simulator::SoftwareInterrupt(Instr* instr) { switch (instr->SwiField()) { case call_rt_r5: { SimulatorRuntimeCall target = reinterpret_cast<SimulatorRuntimeCall>(get_register(r5)); intptr_t arg0 = get_register(r0); intptr_t arg1 = get_register(r1); int64_t result = target(arg0, arg1); int32_t lo_res = static_cast<int32_t>(result); int32_t hi_res = static_cast<int32_t>(result >> 32); set_register(r0, lo_res); set_register(r1, hi_res); set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); break; } case call_rt_r2: { SimulatorRuntimeCall target = reinterpret_cast<SimulatorRuntimeCall>(get_register(r2)); intptr_t arg0 = get_register(r0); intptr_t arg1 = get_register(r1); int64_t result = target(arg0, arg1); int32_t lo_res = static_cast<int32_t>(result); int32_t hi_res = static_cast<int32_t>(result >> 32); set_register(r0, lo_res); set_register(r1, hi_res); set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); break; } case break_point: { Debugger dbg(this); dbg.Debug(); break; } default: { UNREACHABLE(); break; } }}// Handle execution based on instruction types.// Instruction types 0 and 1 are both rolled into one function because they// only differ in the handling of the shifter_operand.void Simulator::DecodeType01(Instr* instr) { int type = instr->TypeField(); if ((type == 0) && instr->IsSpecialType0()) { // multiply instruction or extra loads and stores if (instr->Bits(7, 4) == 9) { if (instr->Bit(24) == 0) { // multiply instructions int rd = instr->RdField(); int rm = instr->RmField(); int rs = instr->RsField(); int32_t rs_val = get_register(rs); int32_t rm_val = get_register(rm); if (instr->Bit(23) == 0) { if (instr->Bit(21) == 0) { // Format(instr, "mul'cond's 'rd, 'rm, 'rs"); int32_t alu_out = rm_val * rs_val; set_register(rd, alu_out); if (instr->HasS()) { SetNZFlags(alu_out); } } else { Format(instr, "mla'cond's 'rd, 'rm, 'rs, 'rn"); } } else { // Format(instr, "'um'al'cond's 'rn, 'rd, 'rs, 'rm"); int rn = instr->RnField(); int32_t hi_res = 0; int32_t lo_res = 0; if (instr->Bit(22) == 0) { // signed multiply UNIMPLEMENTED(); } else { // unsigned multiply uint64_t left_op = rm_val; uint64_t right_op = rs_val; uint64_t result = left_op * right_op; hi_res = static_cast<int32_t>(result >> 32); lo_res = static_cast<int32_t>(result & 0xffffffff); } set_register(rn, hi_res); set_register(rd, lo_res); if (instr->HasS()) { UNIMPLEMENTED(); } } } else { UNIMPLEMENTED(); // not used by V8 } } else { // extra load/store instructions int rd = instr->RdField(); int rn = instr->RnField(); int32_t rn_val = get_register(rn); int32_t addr = 0; if (instr->Bit(22) == 0) { int rm = instr->RmField(); int32_t rm_val = get_register(rm); switch (instr->PUField()) { case 0: { // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); ASSERT(!instr->HasW()); addr = rn_val; rn_val -= rm_val; set_register(rn, rn_val); break; } case 1: { // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); ASSERT(!instr->HasW()); addr = rn_val; rn_val += rm_val; set_register(rn, rn_val); break; } case 2: { // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); rn_val -= rm_val; addr = rn_val; if (instr->HasW()) { set_register(rn, rn_val); } break; } case 3: { // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); rn_val += rm_val; addr = rn_val; if (instr->HasW()) { set_register(rn, rn_val); } break; } default: { // The PU field is a 2-bit field. UNREACHABLE(); break; } } } else { int32_t imm_val = (instr->ImmedHField() << 4) | instr->ImmedLField(); switch (instr->PUField()) { case 0: { // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); ASSERT(!instr->HasW()); addr = rn_val; rn_val -= imm_val; set_register(rn, rn_val); break; } case 1: { // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); ASSERT(!instr->HasW()); addr = rn_val; rn_val += imm_val; set_register(rn, rn_val); break; } case 2: { // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); rn_val -= imm_val; addr = rn_val; if (instr->HasW()) { set_register(rn, rn_val); } break; } case 3: { // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); rn_val += imm_val; addr = rn_val; if (instr->HasW()) { set_register(rn, rn_val); } break; } default: { // The PU field is a 2-bit field. UNREACHABLE(); break; } } } if (instr->HasH()) { if (instr->HasSign()) { int16_t* haddr = reinterpret_cast<int16_t*>(addr); if (instr->HasL()) { int16_t val = *haddr; set_register(rd, val); } else { int16_t val = get_register(rd); *haddr = val; } } else { uint16_t* haddr = reinterpret_cast<uint16_t*>(addr); if (instr->HasL()) { uint16_t val = *haddr; set_register(rd, val); } else { uint16_t val = get_register(rd); *haddr = val; } } } else { // signed byte loads ASSERT(instr->HasSign()); ASSERT(instr->HasL()); int8_t* baddr = reinterpret_cast<int8_t*>(addr); int8_t val = *baddr; set_register(rd, val); } return; } } else { int rd = instr->RdField(); int rn = instr->RnField(); int32_t rn_val = get_register(rn); int32_t shifter_operand = 0; bool shifter_carry_out = 0; if (type == 0) { shifter_operand = GetShiftRm(instr, &shifter_carry_out); } else { ASSERT(instr->TypeField() == 1); shifter_operand = GetImm(instr, &shifter_carry_out); } int32_t alu_out; switch (instr->OpcodeField()) { case AND: { // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm"); // Format(instr, "and'cond's 'rd, 'rn, 'imm"); alu_out = rn_val & shifter_operand; set_register(rd, alu_out); if (instr->HasS()) { SetNZFlags(alu_out); SetCFlag(shifter_carry_out);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -