in compiler/utils/arm/assembler_thumb2.cc [2131:2308]
void Thumb2Assembler::Fixup::Emit(AssemblerBuffer* buffer, uint32_t code_size) const {
switch (GetSize()) {
case kBranch16Bit: {
DCHECK(type_ == kUnconditional || type_ == kConditional);
DCHECK_EQ(type_ == kConditional, cond_ != AL);
int16_t encoding = BEncoding16(GetOffset(code_size), cond_);
buffer->Store<int16_t>(location_, encoding);
break;
}
case kBranch32Bit: {
DCHECK(type_ == kConditional || type_ == kUnconditional ||
type_ == kUnconditionalLink || type_ == kUnconditionalLinkX);
DCHECK_EQ(type_ == kConditional, cond_ != AL);
int32_t encoding = BEncoding32(GetOffset(code_size), cond_);
if (type_ == kUnconditionalLink) {
DCHECK_NE(encoding & B12, 0);
encoding |= B14;
} else if (type_ == kUnconditionalLinkX) {
DCHECK_NE(encoding & B12, 0);
encoding ^= B14 | B12;
}
buffer->Store<int16_t>(location_, encoding >> 16);
buffer->Store<int16_t>(location_ + 2u, static_cast<int16_t>(encoding & 0xffff));
break;
}
case kCbxz16Bit: {
DCHECK(type_ == kCompareAndBranchXZero);
int16_t encoding = CbxzEncoding16(rn_, GetOffset(code_size), cond_);
buffer->Store<int16_t>(location_, encoding);
break;
}
case kCbxz32Bit: {
DCHECK(type_ == kCompareAndBranchXZero);
DCHECK(cond_ == EQ || cond_ == NE);
int16_t cmp_encoding = CmpRnImm8Encoding16(rn_, 0);
int16_t b_encoding = BEncoding16(GetOffset(code_size), cond_);
buffer->Store<int16_t>(location_, cmp_encoding);
buffer->Store<int16_t>(location_ + 2, b_encoding);
break;
}
case kCbxz48Bit: {
DCHECK(type_ == kCompareAndBranchXZero);
DCHECK(cond_ == EQ || cond_ == NE);
int16_t cmp_encoding = CmpRnImm8Encoding16(rn_, 0);
int32_t b_encoding = BEncoding32(GetOffset(code_size), cond_);
buffer->Store<int16_t>(location_, cmp_encoding);
buffer->Store<int16_t>(location_ + 2u, b_encoding >> 16);
buffer->Store<int16_t>(location_ + 4u, static_cast<int16_t>(b_encoding & 0xffff));
break;
}
case kLiteral1KiB: {
DCHECK(type_ == kLoadLiteralNarrow);
int16_t encoding = LdrLitEncoding16(rn_, GetOffset(code_size));
buffer->Store<int16_t>(location_, encoding);
break;
}
case kLiteral4KiB: {
DCHECK(type_ == kLoadLiteralNarrow);
// GetOffset() uses PC+4 but load literal uses AlignDown(PC+4, 4). Adjust offset accordingly.
int32_t encoding = LdrLitEncoding32(rn_, GetOffset(code_size));
buffer->Store<int16_t>(location_, encoding >> 16);
buffer->Store<int16_t>(location_ + 2u, static_cast<int16_t>(encoding & 0xffff));
break;
}
case kLiteral64KiB: {
DCHECK(type_ == kLoadLiteralNarrow);
int32_t mov_encoding = MovwEncoding32(rn_, GetOffset(code_size));
int16_t add_pc_encoding = AddRdnRmEncoding16(rn_, PC);
int16_t ldr_encoding = LdrRtRnImm5Encoding16(rn_, rn_, 0);
buffer->Store<int16_t>(location_, mov_encoding >> 16);
buffer->Store<int16_t>(location_ + 2u, static_cast<int16_t>(mov_encoding & 0xffff));
buffer->Store<int16_t>(location_ + 4u, add_pc_encoding);
buffer->Store<int16_t>(location_ + 6u, ldr_encoding);
break;
}
case kLiteral1MiB: {
DCHECK(type_ == kLoadLiteralNarrow);
int32_t offset = GetOffset(code_size);
int32_t mov_encoding = MovModImmEncoding32(rn_, offset & ~0xfff);
int16_t add_pc_encoding = AddRdnRmEncoding16(rn_, PC);
int32_t ldr_encoding = LdrRtRnImm12Encoding(rn_, rn_, offset & 0xfff);
buffer->Store<int16_t>(location_, mov_encoding >> 16);
buffer->Store<int16_t>(location_ + 2u, static_cast<int16_t>(mov_encoding & 0xffff));
buffer->Store<int16_t>(location_ + 4u, add_pc_encoding);
buffer->Store<int16_t>(location_ + 6u, ldr_encoding >> 16);
buffer->Store<int16_t>(location_ + 8u, static_cast<int16_t>(ldr_encoding & 0xffff));
break;
}
case kLiteralFar: {
DCHECK(type_ == kLoadLiteralNarrow);
int32_t offset = GetOffset(code_size);
int32_t movw_encoding = MovwEncoding32(rn_, offset & 0xffff);
int32_t movt_encoding = MovtEncoding32(rn_, offset & ~0xffff);
int16_t add_pc_encoding = AddRdnRmEncoding16(rn_, PC);
int32_t ldr_encoding = LdrRtRnImm12Encoding(rn_, rn_, 0);
buffer->Store<int16_t>(location_, movw_encoding >> 16);
buffer->Store<int16_t>(location_ + 2u, static_cast<int16_t>(movw_encoding & 0xffff));
buffer->Store<int16_t>(location_ + 4u, movt_encoding >> 16);
buffer->Store<int16_t>(location_ + 6u, static_cast<int16_t>(movt_encoding & 0xffff));
buffer->Store<int16_t>(location_ + 8u, add_pc_encoding);
buffer->Store<int16_t>(location_ + 10u, ldr_encoding >> 16);
buffer->Store<int16_t>(location_ + 12u, static_cast<int16_t>(ldr_encoding & 0xffff));
break;
}
case kLiteralAddr1KiB: {
DCHECK(type_ == kLoadLiteralAddr);
int16_t encoding = AdrEncoding16(rn_, GetOffset(code_size));
buffer->Store<int16_t>(location_, encoding);
break;
}
case kLiteralAddr4KiB: {
DCHECK(type_ == kLoadLiteralAddr);
int32_t encoding = AdrEncoding32(rn_, GetOffset(code_size));
buffer->Store<int16_t>(location_, encoding >> 16);
buffer->Store<int16_t>(location_ + 2u, static_cast<int16_t>(encoding & 0xffff));
break;
}
case kLiteralAddr64KiB: {
DCHECK(type_ == kLoadLiteralAddr);
int32_t mov_encoding = MovwEncoding32(rn_, GetOffset(code_size));
int16_t add_pc_encoding = AddRdnRmEncoding16(rn_, PC);
buffer->Store<int16_t>(location_, mov_encoding >> 16);
buffer->Store<int16_t>(location_ + 2u, static_cast<int16_t>(mov_encoding & 0xffff));
buffer->Store<int16_t>(location_ + 4u, add_pc_encoding);
break;
}
case kLiteralAddrFar: {
DCHECK(type_ == kLoadLiteralAddr);
int32_t offset = GetOffset(code_size);
int32_t movw_encoding = MovwEncoding32(rn_, offset & 0xffff);
int32_t movt_encoding = MovtEncoding32(rn_, offset & ~0xffff);
int16_t add_pc_encoding = AddRdnRmEncoding16(rn_, PC);
buffer->Store<int16_t>(location_, movw_encoding >> 16);
buffer->Store<int16_t>(location_ + 2u, static_cast<int16_t>(movw_encoding & 0xffff));
buffer->Store<int16_t>(location_ + 4u, movt_encoding >> 16);
buffer->Store<int16_t>(location_ + 6u, static_cast<int16_t>(movt_encoding & 0xffff));
buffer->Store<int16_t>(location_ + 8u, add_pc_encoding);
break;
}
case kLongOrFPLiteral1KiB: {
int32_t encoding = LoadWideOrFpEncoding(PC, GetOffset(code_size)); // DCHECKs type_.
buffer->Store<int16_t>(location_, encoding >> 16);
buffer->Store<int16_t>(location_ + 2u, static_cast<int16_t>(encoding & 0xffff));
break;
}
case kLongOrFPLiteral256KiB: {
int32_t offset = GetOffset(code_size);
int32_t mov_encoding = MovModImmEncoding32(IP, offset & ~0x3ff);
int16_t add_pc_encoding = AddRdnRmEncoding16(IP, PC);
int32_t ldr_encoding = LoadWideOrFpEncoding(IP, offset & 0x3ff); // DCHECKs type_.
buffer->Store<int16_t>(location_, mov_encoding >> 16);
buffer->Store<int16_t>(location_ + 2u, static_cast<int16_t>(mov_encoding & 0xffff));
buffer->Store<int16_t>(location_ + 4u, add_pc_encoding);
buffer->Store<int16_t>(location_ + 6u, ldr_encoding >> 16);
buffer->Store<int16_t>(location_ + 8u, static_cast<int16_t>(ldr_encoding & 0xffff));
break;
}
case kLongOrFPLiteralFar: {
int32_t offset = GetOffset(code_size);
int32_t movw_encoding = MovwEncoding32(IP, offset & 0xffff);
int32_t movt_encoding = MovtEncoding32(IP, offset & ~0xffff);
int16_t add_pc_encoding = AddRdnRmEncoding16(IP, PC);
int32_t ldr_encoding = LoadWideOrFpEncoding(IP, 0); // DCHECKs type_.
buffer->Store<int16_t>(location_, movw_encoding >> 16);
buffer->Store<int16_t>(location_ + 2u, static_cast<int16_t>(movw_encoding & 0xffff));
buffer->Store<int16_t>(location_ + 4u, movt_encoding >> 16);
buffer->Store<int16_t>(location_ + 6u, static_cast<int16_t>(movt_encoding & 0xffff));
buffer->Store<int16_t>(location_ + 8u, add_pc_encoding);
buffer->Store<int16_t>(location_ + 10u, ldr_encoding >> 16);
buffer->Store<int16_t>(location_ + 12u, static_cast<int16_t>(ldr_encoding & 0xffff));
break;
}
}
}