@@ -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,9 +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
403- : RE_CHERIOT_COMPARTMENT_CGPREL_HI;
405+ return RE_CHERIOT_COMPARTMENT_CGPREL_HI;
404406 case R_RISCV_CHERIOT_COMPARTMENT_LO_I:
405407 case R_RISCV_CHERIOT_COMPARTMENT_LO_S:
406408 return RE_CHERIOT_COMPARTMENT_CGPREL_LO;
@@ -501,8 +503,9 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
501503 if (isInt<20 >(hi)) {
502504 relocate (loc,
503505 Relocation{R_NONE,
504- ctx.arg .isCheriot ? R_RISCV_CHERIOT_COMPARTMENT_HI
505- : R_RISCV_PCREL_HI20,
506+ ctx.arg .isCheriot
507+ ? INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_HI
508+ : R_RISCV_PCREL_HI20,
506509 0 , 0 , rel.sym },
507510 val);
508511 relocate (loc + 4 ,
@@ -677,12 +680,24 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
677680 case R_RISCV_CHERIOT_COMPARTMENT_HI: {
678681 // AUICGP
679682 uint32_t opcode = AUICGP;
680- if (isPCCRelative (ctx, loc, rel.sym )) {
681- opcode = AUIPCC;
682- if (int64_t (val) < 0 )
683- val = (val + 0x7ff ) & ~0x7ff ;
684- val = int64_t (val) >> 11 ;
685- }
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 ;
686701 uint32_t existingOpcode = read32le (loc) & 0x7f ;
687702 if ((existingOpcode != AUIPCC) && (existingOpcode != AUICGP))
688703 warn (" R_RISCV_CHERIOT_COMPARTMENT_HI relocation applied to instruction "
@@ -1066,7 +1081,12 @@ static void relaxCGP(Ctx &ctx, const InputSection &sec, size_t i, uint64_t loc,
10661081static bool rewriteCheriotLowRelocs (Ctx &ctx, InputSection &sec) {
10671082 bool modified = false ;
10681083 for (auto &r : sec.relocations ) {
1069- 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) {
10701090 // If this is PCC-relative, then the relocation points to the auicgp /
10711091 // auipcc instruction and we need to look there to find the real target.
10721092 if (!isPCCRelative (ctx, nullptr , r.sym ))
@@ -1092,7 +1112,8 @@ static bool rewriteCheriotLowRelocs(Ctx &ctx, InputSection &sec) {
10921112
10931113 const Relocation *target = nullptr ;
10941114 for (auto it = range.first ; it != range.second ; ++it)
1095- 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) {
10961117 target = &*it;
10971118 break ;
10981119 }
0 commit comments