Skip to content

Commit 40ebba7

Browse files
author
Morten Borup Petersen
committed
Fix RVC prime register en/decode
1 parent 54693b4 commit 40ebba7

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed

src/isa/instruction.h

+18-5
Original file line numberDiff line numberDiff line change
@@ -420,9 +420,21 @@ struct Reg : public Field<tokenIndex, BitRangeSet<BitRange>> {
420420
if (!success) {
421421
return Error(line, "Unknown register '" + regToken + "'");
422422
}
423+
424+
// Allow implementations to hook into verification.
425+
if (auto res = RegImpl::verifyApply(line, regIndex); res.isError()) {
426+
return res;
427+
}
428+
423429
instruction |= BitRange().apply(regIndex);
424430
return Result<>::def();
425431
}
432+
433+
// Implementation-specific hook for verification of apply-time register index.
434+
static Result<> verifyApply(const TokenizedSrcLine &, unsigned) {
435+
return Result<>::def();
436+
}
437+
426438
/// Decodes this register into its name. Adds it to the assembly line.
427439
static bool decode(const Instr_T instruction, const Reg_T,
428440
const ReverseSymbolMap &, LineTokens &line) {
@@ -484,7 +496,8 @@ struct ImmPartSet {
484496
constexpr static void apply(const Instr_T value, Instr_T &instruction) {
485497
(ImmParts::apply(value, instruction), ...);
486498
}
487-
/// Decodes this immediate into its value by combining values from each part.
499+
/// Decodes this immediate into its value by combining values from each
500+
/// part.
488501
constexpr static void decode(Instr_T &value, const Instr_T instruction) {
489502
(ImmParts::decode(value, instruction), ...);
490503
}
@@ -553,8 +566,8 @@ struct ImmBase : public Field<tokenIndex, typename ImmParts::BitRanges> {
553566
using Reg_T_S = typename std::make_signed<Reg_T>::type;
554567
using Reg_T_U = typename std::make_unsigned<Reg_T>::type;
555568

556-
/// Converts a string to its immediate value (if it exists). Success is set to
557-
/// false if this fails.
569+
/// Converts a string to its immediate value (if it exists). Success is set
570+
/// to false if this fails.
558571
constexpr static int64_t getImm(const QString &immToken, bool &success,
559572
ImmConvInfo &convInfo) {
560573
return repr == Repr::Signed
@@ -690,8 +703,8 @@ template <unsigned tokenIndex, unsigned width, Repr repr, typename ImmParts,
690703
using ImmSym =
691704
ImmBase<tokenIndex, width, repr, ImmParts, symbolType, defaultTransformer>;
692705

693-
/** @brief Shorthand for an Immediate with the default value transformer and no
694-
* symbol type. */
706+
/** @brief Shorthand for an Immediate with the default value transformer and
707+
* no symbol type. */
695708
template <unsigned tokenIndex, unsigned width, Repr repr, typename ImmParts>
696709
using Imm = ImmBase<tokenIndex, width, repr, ImmParts, SymbolType::None,
697710
defaultTransformer>;

src/isa/rv_c_ext.h

+29-5
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,43 @@ struct RegRs2 : public GPR_Reg<RegRs2<tokenIndex>, tokenIndex, BitRange<2, 6>> {
5656
constexpr static std::string_view NAME = "rs2";
5757
};
5858

59+
// A prime bitrange represents rd', rs1', rs2' in compressed instructions, where
60+
// the bit range represents registers offset by 8.
61+
template <unsigned start, unsigned stop>
62+
struct PrimeBitRange : public BitRange<start, stop> {
63+
constexpr Instr_T decode(Instr_T instruction) const {
64+
return BitRange<start, stop>::decode(instruction) + 8;
65+
}
66+
};
67+
68+
template <typename TImpl, unsigned tokenIndex, typename Range>
69+
struct RegPrime : public GPR_Reg<TImpl, tokenIndex, Range> {
70+
constexpr static std::string_view NAME = TImpl::NAME;
71+
72+
// Only accept registers x8-x15
73+
static Result<> verifyApply(const TokenizedSrcLine &line, unsigned regIndex) {
74+
if (regIndex < 8 || regIndex > 15) {
75+
return Error(line, "Invalid register index for prime register: " +
76+
QString::number(regIndex) +
77+
" (valid range: x8-x15)");
78+
}
79+
return Result<>::def();
80+
}
81+
};
82+
5983
/// The RV-C Rs1' field contains a source register index.
6084
/// It is defined as a 3-bit field in bits 7-9 of the instruction
6185
template <unsigned tokenIndex>
62-
struct RegRs1Prime
63-
: public GPR_Reg<RegRs1Prime<tokenIndex>, tokenIndex, BitRange<7, 9>> {
86+
struct RegRs1Prime : public RegPrime<RegRs1Prime<tokenIndex>, tokenIndex,
87+
PrimeBitRange<7, 9>> {
6488
constexpr static std::string_view NAME = "rs1'";
6589
};
6690

6791
/// The RV-C Rs2' field contains a source register index.
6892
/// It is defined as a 3-bit field in bits 2-4 of the instruction
6993
template <unsigned tokenIndex>
70-
struct RegRs2Prime
71-
: public GPR_Reg<RegRs2Prime<tokenIndex>, tokenIndex, BitRange<2, 4>> {
94+
struct RegRs2Prime : public RegPrime<RegRs2Prime<tokenIndex>, tokenIndex,
95+
PrimeBitRange<2, 4>> {
7296
constexpr static std::string_view NAME = "rs2'";
7397
};
7498

@@ -77,7 +101,7 @@ struct RegRs2Prime
77101
/// It is defined as a 3-bit field in bits 2-4 of the instruction
78102
template <unsigned tokenIndex>
79103
struct RegRdPrime
80-
: public GPR_Reg<RegRdPrime<tokenIndex>, tokenIndex, BitRange<2, 4>> {
104+
: public RegPrime<RegRdPrime<tokenIndex>, tokenIndex, PrimeBitRange<2, 4>> {
81105
constexpr static std::string_view NAME = "rd'";
82106
};
83107

0 commit comments

Comments
 (0)