diff --git a/src/assembler/mipsrelocations.h b/src/assembler/mipsrelocations.h new file mode 100644 index 000000000..701ea24e8 --- /dev/null +++ b/src/assembler/mipsrelocations.h @@ -0,0 +1,70 @@ +#pragma once + +#include "QDebug" +#include "VSRTL/interface/vsrtl_binutils.h" +#include "relocation.h" + +namespace Ripes { +namespace Assembler { + +// pcrel_lo/hi are restricted to 32-bit absolute addresses, so keep computations +// in this base. +inline uint32_t pcrel_hi16(const uint32_t val, const uint32_t reloc_addr) { + return ((val - (reloc_addr % 0xFFFFF000) + 0x800) >> 16); +} + +template +Relocation mips_pcrel_hi() { + return Relocation("%pcrel_hi16", + [](const Reg_T val, const Reg_T reloc_addr) + -> HandleRelocationRes { + const uint32_t _hi16 = pcrel_hi16(val, reloc_addr); + return {_hi16}; + }); +} + +template +Relocation mips_pcrel_lo() { + return Relocation( + "%pcrel_lo16", + [](const Reg_T val, + const Reg_T reloc_addr) -> HandleRelocationRes { + using Reg_T_S = typename std::make_signed::type; + const uint32_t _hi16 = pcrel_hi16(val, reloc_addr); + const uint32_t lo16 = val & 0x0000FFF; + return {static_cast( + static_cast(vsrtl::signextend(lo16, 16)))}; + }); +} + +template +Relocation mips_hi() { + return Relocation( + "%hi", + [](const Reg_T val, const Reg_T /*reloc_addr*/) + -> HandleRelocationRes { return {val >> 16 & 0xFFFFFF}; }); +} + +template +Relocation mips_lo() { + return Relocation( + "%lo", + [](const Reg_T val, const Reg_T /*reloc_addr*/) + -> HandleRelocationRes { return {val & 0xFFF}; }); +} + +template +RelocationsVec mipsRelocations() { + RelocationsVec relocations; + + relocations.push_back( + std::make_shared>(mips_pcrel_hi())); + relocations.push_back( + std::make_shared>(mips_pcrel_lo())); + relocations.push_back(std::make_shared>(mips_hi())); + relocations.push_back(std::make_shared>(mips_lo())); + + return relocations; +} +} // namespace Assembler +} // namespace Ripes