@@ -63,6 +63,7 @@ class RISCV final : public TargetInfo {
6363#define INTERNAL_R_RISCV_X0REL_S 259
6464
6565#define INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_LO_I 270
66+ #define INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_HI 271
6667
6768const uint64_t dtpOffset = 0x800 ;
6869
@@ -398,8 +399,10 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
398399 return R_GOT_PC;
399400 case R_RISCV_CHERI_TLS_GD_CAPTAB_PCREL_HI20:
400401 return R_TLSGD_PC;
402+ case INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_HI:
403+ return R_PC;
401404 case R_RISCV_CHERIOT_COMPARTMENT_HI:
402- return isPCCRelative (ctx, loc, &s) ? R_PC : RE_CHERIOT_COMPARTMENT_CGPREL_HI;
405+ return RE_CHERIOT_COMPARTMENT_CGPREL_HI;
403406 case R_RISCV_CHERIOT_COMPARTMENT_LO_I:
404407 case R_RISCV_CHERIOT_COMPARTMENT_LO_S:
405408 return RE_CHERIOT_COMPARTMENT_CGPREL_LO;
@@ -500,8 +503,9 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
500503 if (isInt<20 >(hi)) {
501504 relocate (loc,
502505 Relocation{R_NONE,
503- ctx.arg .isCheriot ? R_RISCV_CHERIOT_COMPARTMENT_HI
504- : R_RISCV_PCREL_HI20,
506+ ctx.arg .isCheriot
507+ ? INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_HI
508+ : R_RISCV_PCREL_HI20,
505509 0 , 0 , rel.sym },
506510 val);
507511 relocate (loc + 4 ,
@@ -676,12 +680,24 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
676680 case R_RISCV_CHERIOT_COMPARTMENT_HI: {
677681 // AUICGP
678682 uint32_t opcode = AUICGP;
679- if (isPCCRelative (ctx, loc, rel.sym )) {
680- opcode = AUIPCC;
681- if (int64_t (val) < 0 )
682- val = (val + 0x7ff ) & ~0x7ff ;
683- val = int64_t (val) >> 11 ;
684- }
683+ uint32_t existingOpcode = read32le (loc) & 0x7f ;
684+ if ((existingOpcode != AUIPCC) && (existingOpcode != AUICGP))
685+ warn (" R_RISCV_CHERIOT_COMPARTMENT_HI relocation applied to instruction "
686+ " with unexpected opcode " +
687+ Twine (existingOpcode));
688+ checkInt (ctx, loc, SignExtend64 (val + 0x800 , bits) >> 12 , 20 , rel);
689+ // Preserve the target register. We will rewrite the opcode (source
690+ // register) to either AUICGP or AUIPCC and set the immediate field.
691+ uint32_t insn = read32le (loc) & 0x00000f80 ;
692+ write32le (loc, insn | (val << 12 ) | opcode);
693+ break ;
694+ }
695+ case INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_HI: {
696+ // AUIPCC
697+ uint32_t opcode = AUIPCC;
698+ if (int64_t (val) < 0 )
699+ val = (val + 0x7ff ) & ~0x7ff ;
700+ val = int64_t (val) >> 11 ;
685701 uint32_t existingOpcode = read32le (loc) & 0x7f ;
686702 if ((existingOpcode != AUIPCC) && (existingOpcode != AUICGP))
687703 warn (" R_RISCV_CHERIOT_COMPARTMENT_HI relocation applied to instruction "
@@ -1065,7 +1081,12 @@ static void relaxCGP(Ctx &ctx, const InputSection &sec, size_t i, uint64_t loc,
10651081static bool rewriteCheriotLowRelocs (Ctx &ctx, InputSection &sec) {
10661082 bool modified = false ;
10671083 for (auto &r : sec.relocations ) {
1068- if (r.type == R_RISCV_CHERIOT_COMPARTMENT_LO_I) {
1084+ if (r.type == R_RISCV_CHERIOT_COMPARTMENT_HI &&
1085+ isPCCRelative (ctx, nullptr , r.sym )) {
1086+ modified = true ;
1087+ r.type = INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_HI;
1088+ r.expr = R_PC;
1089+ } else if (r.type == R_RISCV_CHERIOT_COMPARTMENT_LO_I) {
10691090 // If this is PCC-relative, then the relocation points to the auicgp /
10701091 // auipcc instruction and we need to look there to find the real target.
10711092 if (!isPCCRelative (ctx, nullptr , r.sym ))
@@ -1091,7 +1112,8 @@ static bool rewriteCheriotLowRelocs(Ctx &ctx, InputSection &sec) {
10911112
10921113 const Relocation *target = nullptr ;
10931114 for (auto it = range.first ; it != range.second ; ++it)
1094- if (it->type == R_RISCV_CHERIOT_COMPARTMENT_HI) {
1115+ if (it->type == R_RISCV_CHERIOT_COMPARTMENT_HI ||
1116+ it->type == INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_HI) {
10951117 target = &*it;
10961118 break ;
10971119 }
0 commit comments