Commit c7e4bf45 authored by Deepti Gandluri's avatar Deepti Gandluri Committed by Commit Bot

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: 's avatarBill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55228}
parent bca38dbf
......@@ -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();
}
......
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