Commit de69f5be authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

Add support for bkpt instruction

The bkpt instruction is now supported by both the disassembler and the simulator. In the simulator it breaks to the native debugger if any like int3 on Intel.

Moved the handling of the miscellaneous instructions to a separate part.

Review URL: http://codereview.chromium.org/1576026


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4360 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4e6a738e
......@@ -151,24 +151,19 @@ enum Opcode {
};
// Some special instructions encoded as a TEQ with S=0 (bit 20).
enum Opcode9Bits {
// The bits for bit 7-4 for some type 0 miscellaneous instructions.
enum MiscInstructionsBits74 {
// With bits 22-21 01.
BX = 1,
BXJ = 2,
BLX = 3,
BKPT = 7
};
BKPT = 7,
// Some special instructions encoded as a CMN with S=0 (bit 20).
enum Opcode11Bits {
// With bits 22-21 11.
CLZ = 1
};
// S
// Shifter types for Data-processing operands as defined in section A5.1.2.
enum Shift {
no_shift = -1,
......@@ -310,6 +305,12 @@ class Instr {
// as well as multiplications).
inline bool IsSpecialType0() const { return (Bit(7) == 1) && (Bit(4) == 1); }
// Test for miscellaneous instructions encodings of type 0 instructions.
inline bool IsMiscType0() const { return (Bit(24) == 1)
&& (Bit(23) == 0)
&& (Bit(20) == 0)
&& ((Bit(7) == 0)); }
// Special accessors that test for existence of a value.
inline bool HasS() const { return SField() == 1; }
inline bool HasB() const { return BField() == 1; }
......
......@@ -449,6 +449,14 @@ int Decoder::FormatOption(Instr* instr, const char* format) {
out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
"%d", instr->ShiftAmountField());
return 8;
} else if (format[3] == '0') {
// 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0.
ASSERT(STRING_STARTS_WITH(format, "off0to3and8to19"));
out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
"%d",
(instr->Bits(19, 8) << 4) +
instr->Bits(3, 0));
return 15;
}
// 'off8: 8-bit offset for extra load and store instructions
ASSERT(STRING_STARTS_WITH(format, "off8"));
......@@ -650,6 +658,34 @@ void Decoder::DecodeType01(Instr* instr) {
}
return;
}
} else if ((type == 0) && instr->IsMiscType0()) {
if (instr->Bits(22, 21) == 1) {
switch (instr->Bits(7, 4)) {
case BX:
Format(instr, "bx'cond 'rm");
break;
case BLX:
Format(instr, "blx'cond 'rm");
break;
case BKPT:
Format(instr, "bkpt 'off0to3and8to19");
break;
default:
Unknown(instr); // not used by V8
break;
}
} else if (instr->Bits(22, 21) == 3) {
switch (instr->Bits(7, 4)) {
case CLZ:
Format(instr, "clz'cond 'rd, 'rm");
break;
default:
Unknown(instr); // not used by V8
break;
}
} else {
Unknown(instr); // not used by V8
}
} else {
switch (instr->OpcodeField()) {
case AND: {
......@@ -696,17 +732,9 @@ void Decoder::DecodeType01(Instr* instr) {
if (instr->HasS()) {
Format(instr, "teq'cond 'rn, 'shift_op");
} else {
switch (instr->Bits(7, 4)) {
case BX:
Format(instr, "bx'cond 'rm");
break;
case BLX:
Format(instr, "blx'cond 'rm");
break;
default:
Unknown(instr); // not used by V8
break;
}
// Other instructions matching this pattern are handled in the
// miscellaneous instructions part above.
UNREACHABLE();
}
break;
}
......@@ -722,14 +750,9 @@ void Decoder::DecodeType01(Instr* instr) {
if (instr->HasS()) {
Format(instr, "cmn'cond 'rn, 'shift_op");
} else {
switch (instr->Bits(7, 4)) {
case CLZ:
Format(instr, "clz'cond 'rd, 'rm");
break;
default:
Unknown(instr); // not used by V8
break;
}
// Other instructions matching this pattern are handled in the
// miscellaneous instructions part above.
UNREACHABLE();
}
break;
}
......
......@@ -1465,6 +1465,50 @@ void Simulator::DecodeType01(Instr* instr) {
}
return;
}
} else if ((type == 0) && instr->IsMiscType0()) {
if (instr->Bits(22, 21) == 1) {
int rm = instr->RmField();
switch (instr->Bits(7, 4)) {
case BX:
set_pc(get_register(rm));
break;
case BLX: {
uint32_t old_pc = get_pc();
set_pc(get_register(rm));
set_register(lr, old_pc + Instr::kInstrSize);
break;
}
case BKPT:
v8::internal::OS::DebugBreak();
break;
default:
UNIMPLEMENTED();
}
} else if (instr->Bits(22, 21) == 3) {
int rm = instr->RmField();
int rd = instr->RdField();
switch (instr->Bits(7, 4)) {
case CLZ: {
uint32_t bits = get_register(rm);
int leading_zeros = 0;
if (bits == 0) {
leading_zeros = 32;
} else {
while ((bits & 0x80000000u) == 0) {
bits <<= 1;
leading_zeros++;
}
}
set_register(rd, leading_zeros);
break;
}
default:
UNIMPLEMENTED();
}
} else {
PrintF("%08x\n", instr->InstructionBits());
UNIMPLEMENTED();
}
} else {
int rd = instr->RdField();
int rn = instr->RnField();
......@@ -1582,21 +1626,9 @@ void Simulator::DecodeType01(Instr* instr) {
SetNZFlags(alu_out);
SetCFlag(shifter_carry_out);
} else {
ASSERT(type == 0);
int rm = instr->RmField();
switch (instr->Bits(7, 4)) {
case BX:
set_pc(get_register(rm));
break;
case BLX: {
uint32_t old_pc = get_pc();
set_pc(get_register(rm));
set_register(lr, old_pc + Instr::kInstrSize);
break;
}
default:
UNIMPLEMENTED();
}
// Other instructions matching this pattern are handled in the
// miscellaneous instructions part above.
UNREACHABLE();
}
break;
}
......@@ -1624,27 +1656,9 @@ void Simulator::DecodeType01(Instr* instr) {
SetCFlag(!CarryFrom(rn_val, shifter_operand));
SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
} else {
ASSERT(type == 0);
int rm = instr->RmField();
int rd = instr->RdField();
switch (instr->Bits(7, 4)) {
case CLZ: {
uint32_t bits = get_register(rm);
int leading_zeros = 0;
if (bits == 0) {
leading_zeros = 32;
} else {
while ((bits & 0x80000000u) == 0) {
bits <<= 1;
leading_zeros++;
}
}
set_register(rd, leading_zeros);
break;
}
default:
UNIMPLEMENTED();
}
// Other instructions matching this pattern are handled in the
// miscellaneous instructions part above.
UNREACHABLE();
}
break;
}
......
......@@ -248,6 +248,16 @@ TEST(Type0) {
COMPARE(mvn(r5, Operand(r4), SetCC, cc),
"31f05004 mvnccs r5, r4");
// Miscellaneous instructions encoded as type 0.
COMPARE(blx(ip),
"e12fff3c blx ip");
COMPARE(bkpt(0),
"e1200070 bkpt 0");
COMPARE(bkpt(0xffff),
"e12fff7f bkpt 65535");
COMPARE(clz(r6, r7),
"e16f6f17 clz r6, r7");
VERIFY_RUN();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment