void Thumb2Assembler::Fixup::Emit()

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;
    }
  }
}