Adds ldp and stp instructions to ARM64.
These should be used instead of single register load and store on frame entry and exit. I'll update these in another change. R=regis@google.com Review URL: https://codereview.chromium.org//630033003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@40960 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
@@ -105,6 +105,9 @@ class Address : public ValueObject {
|
||||
Offset,
|
||||
PreIndex,
|
||||
PostIndex,
|
||||
PairOffset,
|
||||
PairPreIndex,
|
||||
PairPostIndex,
|
||||
Reg,
|
||||
PCOffset,
|
||||
Unknown,
|
||||
@@ -132,14 +135,29 @@ class Address : public ValueObject {
|
||||
encoding_ =
|
||||
((offset & 0x1ff) << kImm9Shift) |
|
||||
(static_cast<int32_t>(crn) << kRnShift);
|
||||
} else {
|
||||
} else if ((at == PreIndex) || (at == PostIndex)) {
|
||||
ASSERT(Utils::IsInt(9, offset));
|
||||
ASSERT((at == PreIndex) || (at == PostIndex));
|
||||
int32_t idx = (at == PostIndex) ? B10 : (B11 | B10);
|
||||
encoding_ =
|
||||
idx |
|
||||
((offset & 0x1ff) << kImm9Shift) |
|
||||
(static_cast<int32_t>(crn) << kRnShift);
|
||||
} else {
|
||||
ASSERT((at == PairOffset) || (at == PairPreIndex) ||
|
||||
(at == PairPostIndex));
|
||||
ASSERT(Utils::IsInt(7 + scale, offset) &&
|
||||
(offset == ((offset >> scale) << scale)));
|
||||
int32_t idx = 0;
|
||||
switch (at) {
|
||||
case PairPostIndex: idx = B23; break;
|
||||
case PairPreIndex: idx = B24 | B23; break;
|
||||
case PairOffset: idx = B24; break;
|
||||
default: UNREACHABLE(); break;
|
||||
}
|
||||
encoding_ =
|
||||
idx |
|
||||
(((offset >> scale) << kImm7Shift) & kImm7Mask) |
|
||||
(static_cast<int32_t>(crn) << kRnShift);
|
||||
}
|
||||
type_ = at;
|
||||
base_ = crn;
|
||||
@@ -161,9 +179,14 @@ class Address : public ValueObject {
|
||||
} else if (at == PCOffset) {
|
||||
return Utils::IsInt(21, offset) &&
|
||||
(offset == ((offset >> 2) << 2));
|
||||
} else {
|
||||
ASSERT((at == PreIndex) || (at == PostIndex));
|
||||
} else if ((at == PreIndex) || (at == PostIndex)) {
|
||||
return Utils::IsInt(9, offset);
|
||||
} else {
|
||||
ASSERT((at == PairOffset) || (at == PairPreIndex) ||
|
||||
(at == PairPostIndex));
|
||||
const int32_t scale = Log2OperandSizeBytes(sz);
|
||||
return (Utils::IsInt(7 + scale, offset) &&
|
||||
(offset == ((offset >> scale) << scale)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +200,13 @@ class Address : public ValueObject {
|
||||
return addr;
|
||||
}
|
||||
|
||||
static Address Pair(Register rn,
|
||||
int32_t offset = 0,
|
||||
AddressType at = PairOffset,
|
||||
OperandSize sz = kDoubleWord) {
|
||||
return Address(rn, offset, at, sz);
|
||||
}
|
||||
|
||||
// This addressing mode does not exist.
|
||||
static Address PC(Register r);
|
||||
|
||||
@@ -630,6 +660,9 @@ class Assembler : public ValueObject {
|
||||
|
||||
// Loads and Stores.
|
||||
void ldr(Register rt, Address a, OperandSize sz = kDoubleWord) {
|
||||
ASSERT((a.type() != Address::PairOffset) &&
|
||||
(a.type() != Address::PairPostIndex) &&
|
||||
(a.type() != Address::PairPreIndex));
|
||||
if (a.type() == Address::PCOffset) {
|
||||
ASSERT(sz == kDoubleWord);
|
||||
EmitLoadRegLiteral(LDRpc, rt, a, sz);
|
||||
@@ -648,9 +681,25 @@ class Assembler : public ValueObject {
|
||||
}
|
||||
}
|
||||
void str(Register rt, Address a, OperandSize sz = kDoubleWord) {
|
||||
ASSERT((a.type() != Address::PairOffset) &&
|
||||
(a.type() != Address::PairPostIndex) &&
|
||||
(a.type() != Address::PairPreIndex));
|
||||
EmitLoadStoreReg(STR, rt, a, sz);
|
||||
}
|
||||
|
||||
void ldp(Register rt, Register rt2, Address a, OperandSize sz = kDoubleWord) {
|
||||
ASSERT((a.type() == Address::PairOffset) ||
|
||||
(a.type() == Address::PairPostIndex) ||
|
||||
(a.type() == Address::PairPreIndex));
|
||||
EmitLoadStoreRegPair(LDP, rt, rt2, a, sz);
|
||||
}
|
||||
void stp(Register rt, Register rt2, Address a, OperandSize sz = kDoubleWord) {
|
||||
ASSERT((a.type() == Address::PairOffset) ||
|
||||
(a.type() == Address::PairPostIndex) ||
|
||||
(a.type() == Address::PairPreIndex));
|
||||
EmitLoadStoreRegPair(STP, rt, rt2, a, sz);
|
||||
}
|
||||
|
||||
// Conditional select.
|
||||
void csel(Register rd, Register rn, Register rm, Condition cond) {
|
||||
EmitConditionalSelect(CSEL, rd, rn, rm, cond, kDoubleWord);
|
||||
@@ -1601,6 +1650,29 @@ class Assembler : public ValueObject {
|
||||
Emit(encoding);
|
||||
}
|
||||
|
||||
void EmitLoadStoreRegPair(LoadStoreRegPairOp op,
|
||||
Register rt, Register rt2, Address a,
|
||||
OperandSize sz) {
|
||||
ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord));
|
||||
ASSERT((rt != CSP) && (rt != R31));
|
||||
ASSERT((rt2 != CSP) && (rt2 != R31));
|
||||
const Register crt = ConcreteRegister(rt);
|
||||
const Register crt2 = ConcreteRegister(rt2);
|
||||
int32_t opc;
|
||||
switch (sz) {
|
||||
case kDoubleWord: opc = B31; break;
|
||||
case kWord: opc = B30; break;
|
||||
case kUnsignedWord: opc = 0; break;
|
||||
default: UNREACHABLE(); break;
|
||||
}
|
||||
const int32_t encoding =
|
||||
opc | op |
|
||||
(static_cast<int32_t>(crt) << kRtShift) |
|
||||
(static_cast<int32_t>(crt2) << kRt2Shift) |
|
||||
a.encoding();
|
||||
Emit(encoding);
|
||||
}
|
||||
|
||||
void EmitPCRelOp(PCRelOp op, Register rd, const Immediate& imm) {
|
||||
ASSERT(Utils::IsInt(21, imm.value()));
|
||||
ASSERT((rd != R31) && (rd != CSP));
|
||||
|
||||
@@ -423,6 +423,44 @@ ASSEMBLER_TEST_RUN(LoadSigned32Bit, test) {
|
||||
}
|
||||
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(SimpleLoadStorePair, assembler) {
|
||||
__ SetupDartSP(kTestStackSpace);
|
||||
__ LoadImmediate(R2, 43, kNoPP);
|
||||
__ LoadImmediate(R3, 42, kNoPP);
|
||||
__ stp(R2, R3, Address(SP, -2*kWordSize, Address::PairPreIndex));
|
||||
__ ldp(R0, R1, Address(SP, 2*kWordSize, Address::PairPostIndex));
|
||||
__ sub(R0, R0, Operand(R1));
|
||||
__ mov(CSP, SP);
|
||||
__ ret();
|
||||
}
|
||||
|
||||
|
||||
ASSEMBLER_TEST_RUN(SimpleLoadStorePair, test) {
|
||||
typedef int64_t (*Int64Return)() DART_UNUSED;
|
||||
EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
|
||||
}
|
||||
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(LoadStorePairOffset, assembler) {
|
||||
__ SetupDartSP(kTestStackSpace);
|
||||
__ LoadImmediate(R2, 43, kNoPP);
|
||||
__ LoadImmediate(R3, 42, kNoPP);
|
||||
__ sub(SP, SP, Operand(4 * kWordSize));
|
||||
__ stp(R2, R3, Address::Pair(SP, 2 * kWordSize));
|
||||
__ ldp(R0, R1, Address::Pair(SP, 2 * kWordSize));
|
||||
__ add(SP, SP, Operand(4 * kWordSize));
|
||||
__ sub(R0, R0, Operand(R1));
|
||||
__ mov(CSP, SP);
|
||||
__ ret();
|
||||
}
|
||||
|
||||
|
||||
ASSEMBLER_TEST_RUN(LoadStorePairOffset, test) {
|
||||
typedef int64_t (*Int64Return)() DART_UNUSED;
|
||||
EXPECT_EQ(1, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
|
||||
}
|
||||
|
||||
|
||||
// Logical register operations.
|
||||
ASSEMBLER_TEST_GENERATE(AndRegs, assembler) {
|
||||
__ movz(R1, Immediate(43), 0);
|
||||
|
||||
@@ -369,6 +369,14 @@ enum LoadStoreRegOp {
|
||||
FLDRQ = LDR | B26 | B23,
|
||||
};
|
||||
|
||||
// C3.3.14-16
|
||||
enum LoadStoreRegPairOp {
|
||||
LoadStoreRegPairMask = 0x3a000000,
|
||||
LoadStoreRegPairFixed = LoadStoreFixed | B29,
|
||||
STP = LoadStoreRegPairFixed,
|
||||
LDP = LoadStoreRegPairFixed | B22,
|
||||
};
|
||||
|
||||
// C3.4.1
|
||||
enum AddSubImmOp {
|
||||
AddSubImmMask = 0x1f000000,
|
||||
@@ -581,6 +589,7 @@ _V(TestAndBranch) \
|
||||
_V(UnconditionalBranch) \
|
||||
_V(UnconditionalBranchReg) \
|
||||
_V(LoadStoreReg) \
|
||||
_V(LoadStoreRegPair) \
|
||||
_V(LoadRegLiteral) \
|
||||
_V(AddSubImm) \
|
||||
_V(LogicalImm) \
|
||||
@@ -654,6 +663,8 @@ enum InstructionFields {
|
||||
kRmBits = 5,
|
||||
kRtShift = 0,
|
||||
kRtBits = 5,
|
||||
kRt2Shift = 10,
|
||||
kRt2Bits = 5,
|
||||
|
||||
// V Registers.
|
||||
kVdShift = 0,
|
||||
@@ -674,6 +685,9 @@ enum InstructionFields {
|
||||
kImm5Bits = 5,
|
||||
kImm6Shift = 10,
|
||||
kImm6Bits = 6,
|
||||
kImm7Shift = 15,
|
||||
kImm7Bits = 7,
|
||||
kImm7Mask = 0x7f << kImm7Shift,
|
||||
kImm8Shift = 13,
|
||||
kImm8Bits = 8,
|
||||
kImm9Shift = 12,
|
||||
@@ -839,6 +853,8 @@ class Instr {
|
||||
Bits(kRmShift, kRmBits)); }
|
||||
inline Register RtField() const { return static_cast<Register>(
|
||||
Bits(kRtShift, kRtBits)); }
|
||||
inline Register Rt2Field() const { return static_cast<Register>(
|
||||
Bits(kRt2Shift, kRt2Bits)); }
|
||||
|
||||
inline VRegister VdField() const { return static_cast<VRegister>(
|
||||
Bits(kVdShift, kVdBits)); }
|
||||
@@ -852,6 +868,10 @@ class Instr {
|
||||
// Immediates
|
||||
inline int Imm3Field() const { return Bits(kImm3Shift, kImm3Bits); }
|
||||
inline int Imm6Field() const { return Bits(kImm6Shift, kImm6Bits); }
|
||||
inline int Imm7Field() const { return Bits(kImm7Shift, kImm7Bits); }
|
||||
// Sign-extended Imm7Field()
|
||||
inline int64_t SImm7Field() const {
|
||||
return (static_cast<int32_t>(Imm7Field()) << 25) >> 25; }
|
||||
inline int Imm8Field() const { return Bits(kImm8Shift, kImm8Bits); }
|
||||
inline int Imm9Field() const { return Bits(kImm9Shift, kImm9Bits); }
|
||||
// Sign-extended Imm9Field()
|
||||
|
||||
@@ -34,6 +34,7 @@ class ARM64Decoder : public ValueObject {
|
||||
void PrintVRegister(int reg);
|
||||
void PrintShiftExtendRm(Instr* instr);
|
||||
void PrintMemOperand(Instr* instr);
|
||||
void PrintPairMemOperand(Instr* instr);
|
||||
void PrintS(Instr* instr);
|
||||
void PrintCondition(Instr* instr);
|
||||
|
||||
@@ -216,9 +217,9 @@ void ARM64Decoder::PrintMemOperand(Instr* instr) {
|
||||
Print("[");
|
||||
PrintRegister(rn, R31IsSP);
|
||||
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
||||
remaining_size_in_buffer(),
|
||||
", #%d",
|
||||
imm9);
|
||||
remaining_size_in_buffer(),
|
||||
", #%d",
|
||||
imm9);
|
||||
Print("]");
|
||||
break;
|
||||
}
|
||||
@@ -272,6 +273,41 @@ void ARM64Decoder::PrintMemOperand(Instr* instr) {
|
||||
}
|
||||
|
||||
|
||||
void ARM64Decoder::PrintPairMemOperand(Instr* instr) {
|
||||
const Register rn = instr->RnField();
|
||||
const int32_t simm7 = instr->SImm7Field();
|
||||
const int32_t offset = simm7 << (2 + instr->Bit(31));
|
||||
Print("[");
|
||||
PrintRegister(rn, R31IsSP);
|
||||
switch (instr->Bits(23, 3)) {
|
||||
case 1:
|
||||
// rn + (imm7 << (2 + B31)), post-index, writeback.
|
||||
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
||||
remaining_size_in_buffer(),
|
||||
"], #%d !",
|
||||
offset);
|
||||
break;
|
||||
case 2:
|
||||
// rn + (imm7 << (2 + B31)), pre-index, no writeback.
|
||||
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
||||
remaining_size_in_buffer(),
|
||||
", #%d ]",
|
||||
offset);
|
||||
break;
|
||||
case 3:
|
||||
// rn + (imm7 << (2 + B31)), pre-index, writeback.
|
||||
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
||||
remaining_size_in_buffer(),
|
||||
", #%d ]!",
|
||||
offset);
|
||||
break;
|
||||
default:
|
||||
Print(", ???]");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Handle all register based formatting in these functions to reduce the
|
||||
// complexity of FormatOption.
|
||||
int ARM64Decoder::FormatRegister(Instr* instr, const char* format) {
|
||||
@@ -511,28 +547,34 @@ int ARM64Decoder::FormatOption(Instr* instr, const char* format) {
|
||||
return 5;
|
||||
}
|
||||
case 'p': {
|
||||
if (format[2] == 'a') {
|
||||
ASSERT(STRING_STARTS_WITH(format, "pcadr"));
|
||||
const int64_t immhi = instr->SImm19Field();
|
||||
const int64_t immlo = instr->Bits(29, 2);
|
||||
const int64_t off = (immhi << 2) | immlo;
|
||||
const int64_t pc = reinterpret_cast<int64_t>(instr);
|
||||
const int64_t dest = pc + off;
|
||||
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
||||
remaining_size_in_buffer(),
|
||||
"0x%"Px64,
|
||||
dest);
|
||||
if (format[1] == 'c') {
|
||||
if (format[2] == 'a') {
|
||||
ASSERT(STRING_STARTS_WITH(format, "pcadr"));
|
||||
const int64_t immhi = instr->SImm19Field();
|
||||
const int64_t immlo = instr->Bits(29, 2);
|
||||
const int64_t off = (immhi << 2) | immlo;
|
||||
const int64_t pc = reinterpret_cast<int64_t>(instr);
|
||||
const int64_t dest = pc + off;
|
||||
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
||||
remaining_size_in_buffer(),
|
||||
"0x%"Px64,
|
||||
dest);
|
||||
} else {
|
||||
ASSERT(STRING_STARTS_WITH(format, "pcldr"));
|
||||
const int64_t off = instr->SImm19Field() << 2;
|
||||
const int64_t pc = reinterpret_cast<int64_t>(instr);
|
||||
const int64_t dest = pc + off;
|
||||
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
||||
remaining_size_in_buffer(),
|
||||
"0x%"Px64,
|
||||
dest);
|
||||
}
|
||||
return 5;
|
||||
} else {
|
||||
ASSERT(STRING_STARTS_WITH(format, "pcldr"));
|
||||
const int64_t off = instr->SImm19Field() << 2;
|
||||
const int64_t pc = reinterpret_cast<int64_t>(instr);
|
||||
const int64_t dest = pc + off;
|
||||
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
||||
remaining_size_in_buffer(),
|
||||
"0x%"Px64,
|
||||
dest);
|
||||
ASSERT(STRING_STARTS_WITH(format, "pmemop"));
|
||||
PrintPairMemOperand(instr);
|
||||
return 6;
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
case 'r': {
|
||||
return FormatRegister(instr, format);
|
||||
@@ -674,6 +716,17 @@ void ARM64Decoder::DecodeLoadStoreReg(Instr* instr) {
|
||||
}
|
||||
|
||||
|
||||
void ARM64Decoder::DecodeLoadStoreRegPair(Instr* instr) {
|
||||
if (instr->Bit(22) == 1) {
|
||||
// Load.
|
||||
Format(instr, "ldp'sf 'rt, 'ra, 'pmemop");
|
||||
} else {
|
||||
// Store.
|
||||
Format(instr, "stp'sf 'rt, 'ra, 'pmemop");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ARM64Decoder::DecodeLoadRegLiteral(Instr* instr) {
|
||||
if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) ||
|
||||
(instr->Bits(24, 3) != 0)) {
|
||||
@@ -881,6 +934,8 @@ void ARM64Decoder::DecodeCompareBranch(Instr* instr) {
|
||||
void ARM64Decoder::DecodeLoadStore(Instr* instr) {
|
||||
if (instr->IsLoadStoreRegOp()) {
|
||||
DecodeLoadStoreReg(instr);
|
||||
} else if (instr->IsLoadStoreRegPairOp()) {
|
||||
DecodeLoadStoreRegPair(instr);
|
||||
} else if (instr->IsLoadRegLiteralOp()) {
|
||||
DecodeLoadRegLiteral(instr);
|
||||
} else {
|
||||
|
||||
@@ -1724,6 +1724,100 @@ void Simulator::DecodeLoadStoreReg(Instr* instr) {
|
||||
}
|
||||
|
||||
|
||||
void Simulator::DecodeLoadStoreRegPair(Instr* instr) {
|
||||
const int32_t opc = instr->Bits(23, 3);
|
||||
const Register rn = instr->RnField();
|
||||
const Register rt = instr->RtField();
|
||||
const Register rt2 = instr->Rt2Field();
|
||||
const int64_t rn_val = get_register(rn, R31IsSP);
|
||||
const intptr_t shift = 2 + instr->SFField();
|
||||
const intptr_t size = 1 << shift;
|
||||
const int32_t offset = (instr->SImm7Field() << shift);
|
||||
uword address = 0;
|
||||
uword wb_address = 0;
|
||||
bool wb = false;
|
||||
|
||||
if ((instr->Bits(30, 2) == 3) || (instr->Bit(26) != 0)) {
|
||||
UnimplementedInstruction(instr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate address.
|
||||
switch (opc) {
|
||||
case 1:
|
||||
address = rn_val;
|
||||
wb_address = rn_val + offset;
|
||||
wb = true;
|
||||
break;
|
||||
case 2:
|
||||
address = rn_val + offset;
|
||||
break;
|
||||
case 3:
|
||||
address = rn_val + offset;
|
||||
wb_address = address;
|
||||
wb = true;
|
||||
break;
|
||||
default:
|
||||
UnimplementedInstruction(instr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the address.
|
||||
if (IsIllegalAddress(address)) {
|
||||
HandleIllegalAccess(address, instr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Do access.
|
||||
if (instr->Bit(22)) {
|
||||
// Format(instr, "ldp'sf 'rt, 'ra, 'memop");
|
||||
const bool signd = instr->Bit(30) == 1;
|
||||
int64_t val1 = 0; // Sign extend into an int64_t.
|
||||
int64_t val2 = 0;
|
||||
if (instr->Bit(31) == 1) {
|
||||
// 64-bit read.
|
||||
val1 = ReadX(address, instr);
|
||||
val2 = ReadX(address + size, instr);
|
||||
} else {
|
||||
if (signd) {
|
||||
val1 = static_cast<int64_t>(ReadW(address, instr));
|
||||
val2 = static_cast<int64_t>(ReadW(address + size, instr));
|
||||
} else {
|
||||
val1 = static_cast<int64_t>(ReadWU(address, instr));
|
||||
val2 = static_cast<int64_t>(ReadWU(address + size, instr));
|
||||
}
|
||||
}
|
||||
|
||||
// Write to register.
|
||||
if (instr->Bit(31) == 1) {
|
||||
set_register(instr, rt, val1, R31IsZR);
|
||||
set_register(instr, rt2, val2, R31IsZR);
|
||||
} else {
|
||||
set_wregister(rt, static_cast<int32_t>(val1), R31IsZR);
|
||||
set_wregister(rt2, static_cast<int32_t>(val2), R31IsZR);
|
||||
}
|
||||
} else {
|
||||
// Format(instr, "stp'sf 'rt, 'ra, 'memop");
|
||||
if (instr->Bit(31) == 1) {
|
||||
const int64_t val1 = get_register(rt, R31IsZR);
|
||||
const int64_t val2 = get_register(rt2, R31IsZR);
|
||||
WriteX(address, val1, instr);
|
||||
WriteX(address + size, val2, instr);
|
||||
} else {
|
||||
const int32_t val1 = get_wregister(rt, R31IsZR);
|
||||
const int32_t val2 = get_wregister(rt2, R31IsZR);
|
||||
WriteW(address, val1, instr);
|
||||
WriteW(address + size, val2, instr);
|
||||
}
|
||||
}
|
||||
|
||||
// Do writeback.
|
||||
if (wb) {
|
||||
set_register(instr, rn, wb_address, R31IsSP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Simulator::DecodeLoadRegLiteral(Instr* instr) {
|
||||
if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) ||
|
||||
(instr->Bits(24, 3) != 0)) {
|
||||
@@ -1748,6 +1842,8 @@ void Simulator::DecodeLoadRegLiteral(Instr* instr) {
|
||||
void Simulator::DecodeLoadStore(Instr* instr) {
|
||||
if (instr->IsLoadStoreRegOp()) {
|
||||
DecodeLoadStoreReg(instr);
|
||||
} else if (instr->IsLoadStoreRegPairOp()) {
|
||||
DecodeLoadStoreRegPair(instr);
|
||||
} else if (instr->IsLoadRegLiteralOp()) {
|
||||
DecodeLoadRegLiteral(instr);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user