Add ldrexd/strexd to the Arm assembler
Bug: v8:6532 Change-Id: Id89f81b12205900fc935e6232840e1976e24d3b4 Reviewed-on: https://chromium-review.googlesource.com/1176962 Commit-Queue: Deepti Gandluri <gdeepti@chromium.org> Reviewed-by: Bill Budge <bbudge@chromium.org> Cr-Commit-Position: refs/heads/master@{#55228}
This commit is contained in:
parent
bca38dbf29
commit
c7e4bf4550
@ -2240,6 +2240,32 @@ void Assembler::strexh(Register src1, Register src2, Register dst,
|
||||
0xF9 * B4 | src2.code());
|
||||
}
|
||||
|
||||
void Assembler::ldrexd(Register dst1, Register dst2, const MemOperand& src,
|
||||
Condition cond) {
|
||||
// cond(31-28) | 00011011(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
|
||||
DCHECK(src.rm() == no_reg);
|
||||
DCHECK(dst1 != lr); // r14.
|
||||
// The pair of destination registers is restricted to being an even-numbered
|
||||
// register and the odd-numbered register that immediately follows it.
|
||||
DCHECK_EQ(0, dst1.code() % 2);
|
||||
DCHECK_EQ(dst1.code() + 1, dst2.code());
|
||||
emit(cond | B24 | B23 | B21 | B20 | src.rn_.code() * B16 | dst1.code() * B12 |
|
||||
0xF9F);
|
||||
}
|
||||
|
||||
void Assembler::strexd(Register res, Register src1, Register src2,
|
||||
const MemOperand& dst, Condition cond) {
|
||||
// cond(31-28) | 00011010(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
|
||||
DCHECK(dst.rm() == no_reg);
|
||||
DCHECK(src1 != lr); // r14.
|
||||
// The pair of source registers is restricted to being an even-numbered
|
||||
// register and the odd-numbered register that immediately follows it.
|
||||
DCHECK_EQ(0, src1.code() % 2);
|
||||
DCHECK_EQ(src1.code() + 1, src2.code());
|
||||
emit(cond | B24 | B23 | B21 | dst.rn_.code() * B16 | res.code() * B12 |
|
||||
0xF9 * B4 | src1.code());
|
||||
}
|
||||
|
||||
// Preload instructions.
|
||||
void Assembler::pld(const MemOperand& address) {
|
||||
// Instruction details available in ARM DDI 0406C.b, A8.8.128.
|
||||
|
@ -931,6 +931,10 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
void strexb(Register src1, Register src2, Register dst, Condition cond = al);
|
||||
void ldrexh(Register dst, Register src, Condition cond = al);
|
||||
void strexh(Register src1, Register src2, Register dst, Condition cond = al);
|
||||
void ldrexd(Register dst1, Register dst2, const MemOperand& src,
|
||||
Condition cond = al);
|
||||
void strexd(Register res, Register src1, Register src2, const MemOperand& dst,
|
||||
Condition cond = al);
|
||||
|
||||
// Preload instructions
|
||||
void pld(const MemOperand& address);
|
||||
|
@ -786,6 +786,9 @@ void Decoder::DecodeType01(Instruction* instr) {
|
||||
case 0:
|
||||
Format(instr, "ldrex'cond 'rt, ['rn]");
|
||||
break;
|
||||
case 1:
|
||||
Format(instr, "ldrexd'cond 'rt, ['rn]");
|
||||
break;
|
||||
case 2:
|
||||
Format(instr, "ldrexb'cond 'rt, ['rn]");
|
||||
break;
|
||||
@ -804,6 +807,9 @@ void Decoder::DecodeType01(Instruction* instr) {
|
||||
case 0:
|
||||
Format(instr, "strex'cond 'rd, 'rm, ['rn]");
|
||||
break;
|
||||
case 1:
|
||||
Format(instr, "strexd'cond 'rd, 'rm, ['rn]");
|
||||
break;
|
||||
case 2:
|
||||
Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
|
||||
break;
|
||||
|
@ -1097,6 +1097,14 @@ int32_t* Simulator::ReadDW(int32_t addr) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int32_t* Simulator::ReadExDW(int32_t addr) {
|
||||
base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
|
||||
local_monitor_.NotifyLoadExcl(addr, TransactionSize::DoubleWord);
|
||||
global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
|
||||
&global_monitor_processor_);
|
||||
int32_t* ptr = reinterpret_cast<int32_t*>(addr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
|
||||
// All supported ARM targets allow unaligned accesses, so we don't need to
|
||||
@ -1110,6 +1118,19 @@ void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
|
||||
*ptr = value2;
|
||||
}
|
||||
|
||||
int Simulator::WriteExDW(int32_t addr, int32_t value1, int32_t value2) {
|
||||
base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
|
||||
if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::DoubleWord) &&
|
||||
global_monitor_.Pointer()->NotifyStoreExcl_Locked(
|
||||
addr, &global_monitor_processor_)) {
|
||||
intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
|
||||
*ptr++ = value1;
|
||||
*ptr = value2;
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the limit of the stack area to enable checking for stack overflows.
|
||||
uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
|
||||
@ -2054,6 +2075,12 @@ void Simulator::DecodeType01(Instruction* instr) {
|
||||
set_register(rt, value);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
// Format(instr, "ldrexd'cond 'rt, ['rn]");
|
||||
int* rn_data = ReadExDW(addr);
|
||||
set_dw_register(rt, rn_data);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// Format(instr, "ldrexb'cond 'rt, ['rn]");
|
||||
uint8_t value = ReadExBU(addr);
|
||||
@ -2087,6 +2114,15 @@ void Simulator::DecodeType01(Instruction* instr) {
|
||||
set_register(rd, status);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
// Format(instr, "strexd'cond 'rd, 'rm, ['rn]");
|
||||
DCHECK_EQ(rt % 2, 0);
|
||||
int32_t value1 = get_register(rt);
|
||||
int32_t value2 = get_register(rt + 1);
|
||||
int status = WriteExDW(addr, value1, value2);
|
||||
set_register(rd, status);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
|
||||
uint8_t value = get_register(rt);
|
||||
|
@ -291,6 +291,8 @@ class Simulator : public SimulatorBase {
|
||||
|
||||
int32_t* ReadDW(int32_t addr);
|
||||
void WriteDW(int32_t addr, int32_t value1, int32_t value2);
|
||||
int32_t* ReadExDW(int32_t addr);
|
||||
int WriteExDW(int32_t addr, int32_t value1, int32_t value2);
|
||||
|
||||
// Executing is handled based on the instruction type.
|
||||
// Both type 0 and type 1 rolled into one.
|
||||
@ -414,6 +416,7 @@ class Simulator : public SimulatorBase {
|
||||
Byte = 1,
|
||||
HalfWord = 2,
|
||||
Word = 4,
|
||||
DoubleWord = 8,
|
||||
};
|
||||
|
||||
// The least-significant bits of the address are ignored. The number of bits
|
||||
|
@ -1615,6 +1615,9 @@ TEST(LoadStoreExclusive) {
|
||||
COMPARE(strexh(r0, r1, r2), "e1e20f91 strexh r0, r1, [r2]");
|
||||
COMPARE(ldrex(r0, r1), "e1910f9f ldrex r0, [r1]");
|
||||
COMPARE(strex(r0, r1, r2), "e1820f91 strex r0, r1, [r2]");
|
||||
COMPARE(ldrexd(r0, r1, MemOperand(r2)), "e1b20f9f ldrexd r0, [r2]");
|
||||
COMPARE(strexd(r0, r2, r3, MemOperand(r4)),
|
||||
"e1a40f92 strexd r0, r2, [r4]");
|
||||
|
||||
VERIFY_RUN();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user