blob: 7c4eae7311d14d2d59389b3d1c2f6a5f0958d4cf [file]
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_MPACT_RISCV_RISCV_BIN_SETTERS_H_
#define THIRD_PARTY_MPACT_RISCV_RISCV_BIN_SETTERS_H_
#include <cstdint>
#include <initializer_list>
#include <string>
#include <utility>
#include <vector>
#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "mpact/sim/util/asm/opcode_assembler_interface.h"
#include "mpact/sim/util/asm/resolver_interface.h"
#include "re2/re2.h"
#include "riscv/riscv_getter_helpers.h"
// This file contains various setters for the RiscV binary encoder that is used
// by the assembler to map from operand text strings to integer values.
namespace mpact {
namespace sim {
namespace riscv {
using ::mpact::sim::util::assembler::RelocationInfo;
using ::mpact::sim::util::assembler::ResolverInterface;
// Initializer lists for maps for different subsets of registers, mapping from
// the register name to the register number.
constexpr std::initializer_list<const std::pair<absl::string_view, uint64_t>>
kRegisterList = {
{"x0", 0}, {"x1", 1}, {"x2", 2}, {"x3", 3}, {"x4", 4},
{"x5", 5}, {"x6", 6}, {"x7", 7}, {"x8", 8}, {"x9", 9},
{"x10", 10}, {"x11", 11}, {"x12", 12}, {"x13", 13}, {"x14", 14},
{"x15", 15}, {"x16", 16}, {"x17", 17}, {"x18", 18}, {"x19", 19},
{"x20", 20}, {"x21", 21}, {"x22", 22}, {"x23", 23}, {"x24", 24},
{"x25", 25}, {"x26", 26}, {"x27", 27}, {"x28", 28}, {"x29", 29},
{"x30", 30}, {"x31", 31}, {"zero", 0}, {"ra", 1}, {"sp", 2},
{"gp", 3}, {"tp", 4}, {"t0", 5}, {"t1", 6}, {"t2", 7},
{"s0", 8}, {"s1", 9}, {"a0", 10}, {"a1", 11}, {"a2", 12},
{"a3", 13}, {"a4", 14}, {"a5", 15}, {"a6", 16}, {"a7", 17},
{"s2", 18}, {"s3", 19}, {"s4", 20}, {"s5", 21}, {"s6", 22},
{"s7", 23}, {"s8", 24}, {"s9", 25}, {"s10", 26}, {"s11", 27},
{"t3", 28}, {"t4", 29}, {"t5", 30}, {"t6", 31}};
constexpr std::initializer_list<const std::pair<absl::string_view, uint64_t>>
kCRegisterList = {
{"x8", 8}, {"x9", 9}, {"x10", 10}, {"x11", 11},
{"x12", 12}, {"x13", 13}, {"x14", 14}, {"x15", 15},
{"s0", 8}, {"s1", 9}, {"a0", 10}, {"a1", 11},
{"a2", 12}, {"a3", 13}, {"a4", 14}, {"a5", 15},
};
constexpr std::initializer_list<const std::pair<absl::string_view, uint64_t>>
kFRegisterList = {
{"f0", 0}, {"f1", 1}, {"f2", 2}, {"f3", 3}, {"f4", 4},
{"f5", 5}, {"f6", 6}, {"f7", 7}, {"f8", 8}, {"f9", 9},
{"f10", 10}, {"f11", 11}, {"f12", 12}, {"f13", 13}, {"f14", 14},
{"f15", 15}, {"f16", 16}, {"f17", 17}, {"f18", 18}, {"f19", 19},
{"f20", 20}, {"f21", 21}, {"f22", 22}, {"f23", 23}, {"f24", 24},
{"f25", 25}, {"f26", 26}, {"f27", 27}, {"f28", 28}, {"f29", 29},
{"f30", 30}, {"f31", 31}, {"ft0", 0}, {"ft1", 1}, {"ft2", 2},
{"ft3", 3}, {"ft4", 4}, {"ft5", 5}, {"ft6", 6}, {"ft7", 7},
{"fs0", 8}, {"fs1", 9}, {"fa0", 10}, {"fa1", 11}, {"fa2", 12},
{"fa3", 13}, {"fa4", 14}, {"fa5", 15}, {"fa6", 16}, {"fa7", 17},
{"fs2", 18}, {"fs3", 19}, {"fs4", 20}, {"fs5", 21}, {"fs6", 22},
{"fs7", 23}, {"fs8", 24}, {"fs9", 25}, {"fs10", 26}, {"fs11", 27},
{"ft8", 28}, {"ft9", 29}, {"ft10", 30}, {"ft11", 31}};
constexpr std::initializer_list<const std::pair<absl::string_view, uint64_t>>
kDRegisterList = {
{"d0", 0}, {"d1", 1}, {"d2", 2}, {"d3", 3}, {"d4", 4},
{"d5", 5}, {"d6", 6}, {"d7", 7}, {"d8", 8}, {"d9", 9},
{"d10", 10}, {"d11", 11}, {"d12", 12}, {"d13", 13}, {"d14", 14},
{"d15", 15}, {"d16", 16}, {"d17", 17}, {"d18", 18}, {"d19", 19},
{"d20", 20}, {"d21", 21}, {"d22", 22}, {"d23", 23}, {"d24", 24},
{"d25", 25}, {"d26", 26}, {"d27", 27}, {"d28", 28}, {"d29", 29},
{"d30", 30}, {"d31", 31}, {"dt0", 0}, {"dt1", 1}, {"dt2", 2},
{"dt3", 3}, {"dt4", 4}, {"dt5", 5}, {"dt6", 6}, {"dt7", 7},
{"ds0", 8}, {"ds1", 9}, {"da0", 10}, {"da1", 11}, {"da2", 12},
{"da3", 13}, {"da4", 14}, {"da5", 15}, {"da6", 16}, {"da7", 17},
{"ds2", 18}, {"ds3", 19}, {"ds4", 20}, {"ds5", 21}, {"ds6", 22},
{"ds7", 23}, {"ds8", 24}, {"ds9", 25}, {"ds10", 26}, {"ds11", 27},
{"dt8", 28}, {"dt9", 29}, {"dt10", 30}, {"dt11", 31}};
constexpr std::initializer_list<const std::pair<absl::string_view, uint64_t>>
kDCRegisterList = {
{"d8", 8}, {"d9", 9}, {"d10", 10}, {"d11", 11},
{"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15},
{"ds0", 8}, {"ds1", 9}, {"da0", 10}, {"da1", 11},
{"da2", 12}, {"da3", 13}, {"da4", 14}, {"da5", 15},
};
// This is the initializer list for the map from CSR register names to register
// numbers.
constexpr std::initializer_list<const std::pair<absl::string_view, uint64_t>>
kCsrRegisterList = {
{"fflags", 0x001},
{"frm", 0x002},
{"fcsr", 0x003},
{"cycle", 0xc00},
{"time", 0xc01},
{"instret", 0xc02},
{"hpmcounter3", 0xc03},
{"hpmcounter4", 0xc04},
{"hpmcounter5", 0xc05},
{"hpmcounter6", 0xc06},
{"hpmcounter7", 0xc07},
{"hpmcounter8", 0xc08},
{"hpmcounter9", 0xc09},
{"hpmcounter10", 0xc0a},
{"hpmcounter11", 0xc0b},
{"hpmcounter12", 0xc0c},
{"hpmcounter13", 0xc0d},
{"hpmcounter14", 0xc0e},
{"hpmcounter15", 0xc0f},
{"hpmcounter16", 0xc10},
{"hpmcounter17", 0xc11},
{"hpmcounter18", 0xc12},
{"hpmcounter19", 0xc13},
{"hpmcounter20", 0xc14},
{"hpmcounter21", 0xc15},
{"hpmcounter22", 0xc16},
{"hpmcounter23", 0xc17},
{"hpmcounter24", 0xc18},
{"hpmcounter25", 0xc19},
{"hpmcounter26", 0xc1a},
{"hpmcounter27", 0xc1b},
{"hpmcounter28", 0xc1c},
{"hpmcounter29", 0xc1d},
{"hpmcounter30", 0xc1e},
{"hpmcounter31", 0xc1f},
{"cycleh", 0xc80},
{"timeh", 0xc81},
{"instreth", 0xc82},
{"hpmcounter3h", 0xc83},
{"hpmcounter4h", 0xc84},
{"hpmcounter5h", 0xc85},
{"hpmcounter6h", 0xc86},
{"hpmcounter7h", 0xc87},
{"hpmcounter8h", 0xc88},
{"hpmcounter9h", 0xc89},
{"hpmcounter10h", 0xc8a},
{"hpmcounter11h", 0xc8b},
{"hpmcounter12h", 0xc8c},
{"hpmcounter13h", 0xc8d},
{"hpmcounter14h", 0xc8e},
{"hpmcounter15h", 0xc8f},
{"hpmcounter16h", 0xc90},
{"hpmcounter17h", 0xc91},
{"hpmcounter18h", 0xc92},
{"hpmcounter19h", 0xc93},
{"hpmcounter20h", 0xc94},
{"hpmcounter2h1", 0xc95},
{"hpmcounter22h", 0xc96},
{"hpmcounter23h", 0xc97},
{"hpmcounter24h", 0xc98},
{"hpmcounter25h", 0xc99},
{"hpmcounter26h", 0xc9a},
{"hpmcounter27h", 0xc9b},
{"hpmcounter28h", 0xc9c},
{"hpmcounter29h", 0xc9d},
{"hpmcounter30h", 0xc9e},
{"hpmcounter3h1", 0xc9f},
{"sstatus", 0x100},
{"sie", 0x104},
{"stvec", 0x105},
{"stcounteren", 0x106},
{"senvcfg", 0x10a},
{"scountinhibit", 0x120},
{"sscratch", 0x140},
{"sepc", 0x141},
{"scause", 0x142},
{"stval", 0x143},
{"sip", 0x144},
{"scountovf", 0xda0},
{"satp", 0x180},
{"scontext", 0x5a8},
{"sstateen0", 0x10c},
{"sstateen1", 0x10d},
{"sstateen2", 0x10e},
{"sstateen3", 0x10f},
{"hstatus", 0x600},
{"hedeleg", 0x602},
{"hideleg", 0x603},
{"hie", 0x604},
{"hcounteren", 0x606},
{"hgeie", 0x607},
{"hedelegh", 0x612},
{"htval", 0x643},
{"hip", 0x644},
{"hvip", 0x645},
{"htinst", 0x64a},
{"hgeip", 0xe12},
{"henvcfg", 0x60a},
{"henvcfgh", 0x61a},
{"hgatp", 0x680},
{"hcontext", 0x6a8},
{"htimedelta", 0x605},
{"htimedeltah", 0x615},
{"hstateen0", 0x60c},
{"hstateen1", 0x60d},
{"hstateen2", 0x60e},
{"hstateen3", 0x60f},
{"hstateen0h", 0x61c},
{"hstateen1h", 0x61d},
{"hstateen2h", 0x61e},
{"hstateen3h", 0x61f},
{"vsstatus", 0x200},
{"vsie", 0x204},
{"vstvec", 0x205},
{"vsscratch", 0x240},
{"vsepc", 0x241},
{"vscause", 0x242},
{"vstval", 0x243},
{"vsip", 0x244},
{"vsatp", 0x280},
{"mvendorid", 0xf11},
{"marchid", 0xf12},
{"mimpid", 0xf13},
{"mhartid", 0xf14},
{"mconfigptr", 0xf15},
{"mstatus", 0x300},
{"misa", 0x301},
{"medeleg", 0x302},
{"mideleg", 0x303},
{"mie", 0x304},
{"mcounteren", 0x306},
{"mstatush", 0x310},
{"medelegh", 0x312},
{"mscratch", 0x340},
{"mepc", 0x341},
{"mcause", 0x342},
{"mtval", 0x343},
{"mip", 0x344},
{"mtinst", 0x34a},
{"mtval2", 0x34b},
{"menvcfg", 0x30a},
{"menvcfgh", 0x31a},
{"mseccfg", 0x747},
{"mseccfgh", 0x757},
{"pmpcfg0", 0x3a0},
{"pmpcfg1", 0x3a1},
{"pmpcfg2", 0x3a2},
{"pmpcfg3", 0x3a3},
{"pmpcfg4", 0x3a4},
{"pmpcfg5", 0x3a5},
{"pmpcfg6", 0x3a6},
{"pmpcfg7", 0x3a7},
{"pmpcfg8", 0x3a8},
{"pmpcfg9", 0x3a9},
{"pmpcfg10", 0x3aa},
{"pmpcfg11", 0x3ab},
{"pmpcfg12", 0x3ac},
{"pmpcfg13", 0x3ad},
{"pmpcfg14", 0x3ae},
{"pmpcfg15", 0x3af},
{"pmpaddr0", 0x3b0},
{"pmpaddr1", 0x3b1},
{"pmpaddr2", 0x3b2},
{"pmpaddr3", 0x3b3},
{"pmpaddr4", 0x3b4},
{"pmpaddr5", 0x3b5},
{"pmpaddr6", 0x3b6},
{"pmpaddr7", 0x3b7},
{"pmpaddr8", 0x3b8},
{"pmpaddr9", 0x3b9},
{"pmpaddr10", 0x3ba},
{"pmpaddr11", 0x3bb},
{"pmpaddr12", 0x3bc},
{"pmpaddr13", 0x3bd},
{"pmpaddr14", 0x3be},
{"pmpaddr15", 0x3bf},
{"pmpaddr16", 0x3c0},
{"pmpaddr17", 0x3c1},
{"pmpaddr18", 0x3c2},
{"pmpaddr19", 0x3c3},
{"pmpaddr20", 0x3c4},
{"pmpaddr21", 0x3c5},
{"pmpaddr22", 0x3c6},
{"pmpaddr23", 0x3c7},
{"pmpaddr24", 0x3c8},
{"pmpaddr25", 0x3c9},
{"pmpaddr26", 0x3ca},
{"pmpaddr27", 0x3cb},
{"pmpaddr28", 0x3cc},
{"pmpaddr29", 0x3cd},
{"pmpaddr30", 0x3ce},
{"pmpaddr31", 0x3cf},
{"pmpaddr32", 0x3d0},
{"pmpaddr33", 0x3d1},
{"pmpaddr34", 0x3d2},
{"pmpaddr35", 0x3d3},
{"pmpaddr36", 0x3d4},
{"pmpaddr37", 0x3d5},
{"pmpaddr38", 0x3d6},
{"pmpaddr39", 0x3d7},
{"pmpaddr40", 0x3d8},
{"pmpaddr41", 0x3d9},
{"pmpaddr42", 0x3da},
{"pmpaddr43", 0x3db},
{"pmpaddr44", 0x3dc},
{"pmpaddr45", 0x3dd},
{"pmpaddr46", 0x3de},
{"pmpaddr47", 0x3df},
{"pmpaddr48", 0x3e0},
{"pmpaddr49", 0x3e1},
{"pmpaddr50", 0x3e2},
{"pmpaddr51", 0x3e3},
{"pmpaddr52", 0x3e4},
{"pmpaddr53", 0x3e5},
{"pmpaddr54", 0x3e6},
{"pmpaddr55", 0x3e7},
{"pmpaddr56", 0x3e8},
{"pmpaddr57", 0x3e9},
{"pmpaddr58", 0x3ea},
{"pmpaddr59", 0x3eb},
{"pmpaddr60", 0x3ec},
{"pmpaddr61", 0x3ed},
{"pmpaddr62", 0x3ee},
{"pmpaddr63", 0x3ef},
{"mstateen0", 0x30c},
{"mstateen1", 0x30d},
{"mstateen2", 0x30e},
{"mstateen3", 0x30f},
{"mstateen0h", 0x31c},
{"mstateen1h", 0x31d},
{"mstateen2h", 0x31e},
{"mstateen3h", 0x31f},
{"mnscratch", 0x740},
{"mnepc", 0x741},
{"mncause", 0x742},
{"mnstatus", 0x743},
{"mcycle", 0xb00},
{"minstret", 0xb02},
{"mhpmcounter3", 0xb03},
{"mhpmcounter4", 0xb04},
{"mhpmcounter5", 0xb05},
{"mhpmcounter6", 0xb06},
{"mhpmcounter7", 0xb07},
{"mhpmcounter8", 0xb08},
{"mhpmcounter9", 0xb09},
{"mhpmcounter10", 0xb0a},
{"mhpmcounter11", 0xb0b},
{"mhpmcounter12", 0xb0c},
{"mhpmcounter13", 0xb0d},
{"mhpmcounter14", 0xb0e},
{"mhpmcounter15", 0xb0f},
{"mhpmcounter16", 0xb10},
{"mhpmcounter17", 0xb11},
{"mhpmcounter18", 0xb12},
{"mhpmcounter19", 0xb13},
{"mhpmcounter20", 0xb14},
{"mhpmcounter21", 0xb15},
{"mhpmcounter22", 0xb16},
{"mhpmcounter23", 0xb17},
{"mhpmcounter24", 0xb18},
{"mhpmcounter25", 0xb19},
{"mhpmcounter26", 0xb1a},
{"mhpmcounter27", 0xb1b},
{"mhpmcounter28", 0xb1c},
{"mhpmcounter29", 0xb1d},
{"mhpmcounter30", 0xb1e},
{"mhpmcounter31", 0xb1f},
{"mcycleh", 0xb80},
{"minstreth", 0xb82},
{"mhpmcounter3h", 0xb83},
{"mhpmcounter4h", 0xb84},
{"mhpmcounter5h", 0xb85},
{"mhpmcounter6h", 0xb86},
{"mhpmcounter7h", 0xb87},
{"mhpmcounter8h", 0xb88},
{"mhpmcounter9h", 0xb89},
{"mhpmcounter10h", 0xb8a},
{"mhpmcounter11h", 0xb8b},
{"mhpmcounter12h", 0xb8c},
{"mhpmcounter13h", 0xb8d},
{"mhpmcounter14h", 0xb8e},
{"mhpmcounter15h", 0xb8f},
{"mhpmcounter16h", 0xb90},
{"mhpmcounter17h", 0xb91},
{"mhpmcounter18h", 0xb92},
{"mhpmcounter19h", 0xb93},
{"mhpmcounter20h", 0xb94},
{"mhpmcounter21h", 0xb95},
{"mhpmcounter22h", 0xb96},
{"mhpmcounter23h", 0xb97},
{"mhpmcounter24h", 0xb98},
{"mhpmcounter25h", 0xb99},
{"mhpmcounter26h", 0xb9a},
{"mhpmcounter27h", 0xb9b},
{"mhpmcounter28h", 0xb9c},
{"mhpmcounter29h", 0xb9d},
{"mhpmcounter30h", 0xb9e},
{"mhpmcounter31h", 0xb9f},
{"mcountinhibit", 0x320},
{"mhpmevent3", 0x323},
{"mhpmevent4", 0x324},
{"mhpmevent5", 0x325},
{"mhpmevent6", 0x326},
{"mhpmevent7", 0x327},
{"mhpmevent8", 0x328},
{"mhpmevent9", 0x329},
{"mhpmevent10", 0x32a},
{"mhpmevent11", 0x32b},
{"mhpmevent12", 0x32c},
{"mhpmevent13", 0x32d},
{"mhpmevent14", 0x32e},
{"mhpmevent15", 0x32f},
{"mhpmevent16", 0x330},
{"mhpmevent17", 0x331},
{"mhpmevent18", 0x332},
{"mhpmevent19", 0x333},
{"mhpmevent20", 0x334},
{"mhpmevent21", 0x335},
{"mhpmevent22", 0x336},
{"mhpmevent23", 0x337},
{"mhpmevent24", 0x338},
{"mhpmevent25", 0x339},
{"mhpmevent26", 0x33a},
{"mhpmevent27", 0x33b},
{"mhpmevent28", 0x33c},
{"mhpmevent29", 0x33d},
{"mhpmevent30", 0x33e},
{"mhpmevent31", 0x33f},
{"mhpmevent3h", 0x723},
{"mhpmevent4h", 0x724},
{"mhpmevent5h", 0x725},
{"mhpmevent6h", 0x726},
{"mhpmevent7h", 0x727},
{"mhpmevent8h", 0x728},
{"mhpmevent9h", 0x729},
{"mhpmevent10h", 0x72a},
{"mhpmevent11h", 0x72b},
{"mhpmevent12h", 0x72c},
{"mhpmevent13h", 0x72d},
{"mhpmevent14h", 0x72e},
{"mhpmevent15h", 0x72f},
{"mhpmevent16h", 0x730},
{"mhpmevent17h", 0x731},
{"mhpmevent18h", 0x732},
{"mhpmevent19h", 0x733},
{"mhpmevent20h", 0x734},
{"mhpmevent21h", 0x735},
{"mhpmevent22h", 0x736},
{"mhpmevent23h", 0x737},
{"mhpmevent24h", 0x738},
{"mhpmevent25h", 0x739},
{"mhpmevent26h", 0x73a},
{"mhpmevent27h", 0x73b},
{"mhpmevent28h", 0x73c},
{"mhpmevent29h", 0x73d},
{"mhpmevent30h", 0x73e},
{"mhpmevent31h", 0x73f},
};
// A helper function to convert a text string to an integer. The function takes
// either numeric literals (hexadecimal or decimal), symbol names, or relocation
// functions, e.g., %hi(<symbol name>).
template <typename T>
absl::StatusOr<T> SimpleTextToInt(absl::string_view op_text,
ResolverInterface* resolver) {
T value;
static RE2 hex_re("^\\s*0x([0-9a-fA-F]+)\\s*$");
static RE2 dec_re("^\\s*(-?[0-9]+)\\s*$");
static RE2 relo_re("^\\s*\\%[a-zA-Z0-9_]+\\s*\\(([a-zA-Z0-9_]+)\\s*\\)\\s*$");
static RE2 symbol_re("^\\s*([a-zA-Z0-9_]+)\\s*$");
std::string str;
std::string text(op_text);
// First see if the operand is a relocation function, and extract the text
// argument. A relocation function is on the form of %name(arg).
if (RE2::FullMatch(op_text, relo_re, &str)) {
text = str;
}
// Extract the hex immediate.
if (RE2::FullMatch(text, hex_re, &str)) {
if (absl::SimpleHexAtoi(str, &value)) return value;
return absl::InvalidArgumentError(
absl::StrCat("Invalid hexadecimal immediate: ", text));
}
// Extract the decimal immediate.
if (RE2::FullMatch(text, dec_re, &str)) {
if (absl::SimpleAtoi(str, &value)) return value;
return absl::InvalidArgumentError(
absl::StrCat("Invalid decimal immediate: ", text));
}
// Extract the symbol.
if (RE2::FullMatch(text, symbol_re, &str)) {
if (resolver != nullptr) {
auto res = resolver->Resolve(str);
if (!res.ok()) {
return res.status();
}
return static_cast<T>(res.value());
}
}
return absl::InvalidArgumentError(absl::StrCat("Invalid argument: ", text));
}
using ValueMap = absl::flat_hash_map<absl::string_view, uint64_t>;
// This function adds the bin setters for the source operands to the given map.
template <typename Enum, typename Map, typename Encoder>
void AddRiscvSourceOpBinSetters(Map& map) {
Insert(map, *Enum::kAAq,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map = {{"", 0}, {".aq", 1}};
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::AType::InsertAq(iter->second, 0ULL);
});
Insert(map, *Enum::kARl,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map = {{"", 0}, {".rl", 1}};
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::AType::InsertRl(iter->second, 0ULL);
});
Insert(map, *Enum::kBImm12,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<uint32_t>(text, resolver);
if (!res.ok()) return res.status();
uint32_t delta = res.value() - address;
return Encoder::BType::InsertBImm(delta, 0ULL);
});
Insert(map, *Enum::kC3drs2,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kDCRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::CS::InsertCsRs2(iter->second, 0ULL);
});
Insert(map, *Enum::kC3rs1,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kCRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::CL::InsertClRs1(iter->second, 0ULL);
});
Insert(map, *Enum::kC3rs2,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kCRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::CS::InsertCsRs2(iter->second, 0ULL);
});
Insert(map, *Enum::kCSRUimm5,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<uint32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::IType::InsertIUimm5(res.value(), 0ULL);
});
Insert(map, *Enum::kCdrs2,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kDRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::CR::InsertRs2(iter->second, 0ULL);
});
Insert(map, *Enum::kCrs1,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::CR::InsertRs1(iter->second, 0ULL);
});
Insert(map, *Enum::kCrs2,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::CR::InsertRs2(iter->second, 0ULL);
});
Insert(map, *Enum::kCsr,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kCsrRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::IType::InsertUImm12(iter->second, 0ULL);
});
Insert(map, *Enum::kDrs1,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kDRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::RType::InsertRs1(iter->second, 0ULL);
});
Insert(map, *Enum::kDrs2,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kDRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::RType::InsertRs2(iter->second, 0ULL);
});
Insert(map, *Enum::kDrs3,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kDRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::R4Type::InsertRs3(iter->second, 0ULL);
});
Insert(map, *Enum::kFrs1,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kFRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::RType::InsertRs1(iter->second, 0ULL);
});
Insert(map, *Enum::kFrs2,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kFRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::RType::InsertRs1(iter->second, 0ULL);
});
Insert(map, *Enum::kFrs3,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kFRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::R4Type::InsertRs3(iter->second, 0ULL);
});
Insert(map, *Enum::kICbImm8,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
uint32_t delta = res.value() - address;
return Encoder::CB::InsertBimm(delta, 0ULL);
});
Insert(map, *Enum::kICiImm6,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::CI::InsertImm6(res.value(), 0ULL);
});
Insert(map, *Enum::kICiImm612,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::CI::InsertImm18(res.value(), 0ULL);
});
Insert(map, *Enum::kICiImm6x16,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::CI::InsertCiImm10(res.value(), 0ULL);
});
Insert(map, *Enum::kICiUimm6,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::CI::InsertUimm6(res.value(), 0ULL);
});
Insert(map, *Enum::kICiUimm6x4,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::CI::InsertCiImmW(res.value(), 0ULL);
});
Insert(map, *Enum::kICiUimm6x8,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::CI::InsertCiImmD(res.value(), 0ULL);
});
Insert(map, *Enum::kICiwUimm8x4,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::CIW::InsertCiwImm10(res.value(), 0ULL);
});
Insert(map, *Enum::kICjImm11,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
auto delta = res.value() - address;
return Encoder::CJ::InsertJimm(delta, 0ULL);
});
Insert(map, *Enum::kIClUimm5x4,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<uint32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::CL::InsertClImmW(res.value(), 0ULL);
});
Insert(map, *Enum::kIClUimm5x8,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::CL::InsertClImmD(res.value(), 0ULL);
});
Insert(map, *Enum::kICssUimm6x4,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<uint32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::CS::InsertCsImmW(res.value(), 0ULL);
});
Insert(map, *Enum::kICssUimm6x8,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<uint32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::CS::InsertCsImmD(res.value(), 0ULL);
});
Insert(map, *Enum::kIImm12,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::IType::InsertImm12(res.value(), 0ULL);
});
Insert(map, *Enum::kIUimm5,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<uint32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::RType::InsertRUimm5(res.value(), 0ULL);
});
Insert(map, *Enum::kIUimm6,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<uint32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::RSType::InsertRUimm6(res.value(), 0ULL);
});
Insert(map, *Enum::kJImm12,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::IType::InsertImm12(res.value(), 0ULL);
});
Insert(map, *Enum::kJImm20,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<int32_t>(text, resolver);
if (!res.ok()) return res.status();
uint32_t delta = res.value() - address;
auto value = Encoder::JType::InsertJImm(delta, 0ULL);
return value;
});
Insert(map, *Enum::kPred,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<uint32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::Fence::InsertPred(res.value(), 0ULL);
});
Insert(map, *Enum::kRd,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::RType::InsertRd(iter->second, 0ULL);
});
Insert(map, *Enum::kRm,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::R4Type::InsertRs3(iter->second, 0ULL);
});
Insert(map, *Enum::kRs1,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::RType::InsertRs1(iter->second, 0ULL);
});
Insert(map, *Enum::kRs2,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::RType::InsertRs2(iter->second, 0ULL);
});
Insert(map, *Enum::kSImm12,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<uint32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::SType::InsertSImm(res.value(), 0ULL);
});
Insert(map, *Enum::kSucc,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<uint32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::Fence::InsertSucc(res.value(), 0ULL);
});
Insert(map, *Enum::kUImm20,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
auto res = SimpleTextToInt<uint32_t>(text, resolver);
if (!res.ok()) return res.status();
return Encoder::UType::InsertUImm(res.value(), 0ULL);
});
}
// This function adds the destination operand setters for the RiscV ISA to the
// given map.
template <typename Enum, typename Map, typename Encoder>
void AddRiscvDestOpBinSetters(Map& map) {
Insert(map, *Enum::kC3drd,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kDCRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid destination operand: ", text));
}
return Encoder::CL::InsertClRd(iter->second, 0ULL);
});
Insert(map, *Enum::kC3rd,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kCRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid destination operand: ", text));
}
return Encoder::CL::InsertClRd(iter->second, 0ULL);
});
Insert(map, *Enum::kC3rs1,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kCRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid destination operand: ", text));
}
return Encoder::CS::InsertCsRs1(iter->second, 0ULL);
});
Insert(map, *Enum::kCsr,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kCsrRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid source operand: ", text));
}
return Encoder::IType::InsertUImm12(iter->second, 0ULL);
});
Insert(map, *Enum::kDrd,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kDRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid destination operand: ", text));
}
return Encoder::RType::InsertRd(iter->second, 0ULL);
});
Insert(map, *Enum::kFrd,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kFRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid destination operand: ", text));
}
return Encoder::RType::InsertRd(iter->second, 0ULL);
});
Insert(map, *Enum::kRd,
[](uint64_t address, absl::string_view text,
ResolverInterface* resolver) -> absl::StatusOr<uint64_t> {
static ValueMap map(kRegisterList);
auto iter = map.find(text);
if (iter == map.end()) {
return absl::InvalidArgumentError(
absl::StrCat("Invalid destination operand: ", text));
}
return Encoder::RType::InsertRd(iter->second, 0ULL);
});
}
// These functions add the appropriate relocation entry to the relocations
// vector if the operand (in text) requires it.
namespace internal {
absl::Status RelocateAddiIImm12(uint64_t address, absl::string_view text,
ResolverInterface* resolver,
std::vector<RelocationInfo>& relocations);
absl::Status RelocateJJImm20(uint64_t address, absl::string_view text,
ResolverInterface* resolver,
std::vector<RelocationInfo>& relocations);
absl::Status RelocateJrJImm12(uint64_t address, absl::string_view text,
ResolverInterface* resolver,
std::vector<RelocationInfo>& relocations);
absl::Status RelocateLuiUImm20(uint64_t address, absl::string_view text,
ResolverInterface* resolver,
std::vector<RelocationInfo>& relocations);
absl::Status RelocateSdSImm12(uint64_t address, absl::string_view text,
ResolverInterface* resolver,
std::vector<RelocationInfo>& relocations);
absl::Status RelocateAuipcUImm20(uint64_t address, absl::string_view text,
ResolverInterface* resolver,
std::vector<RelocationInfo>& relocations);
} // namespace internal
// This function adds the source operand relocation setters for the RiscV ISA to
// the given map. Notice that the key in the map is the tuple consisting of the
// opcode and the source operand enum values.
template <typename OpcodeEnum, typename SourceOpEnum, typename Map>
void AddRiscvSourceOpRelocationSetters(Map& map) {
Insert(map, OpcodeEnum::kAddi, SourceOpEnum::kIImm12,
internal::RelocateAddiIImm12);
Insert(map, OpcodeEnum::kJal, SourceOpEnum::kJImm20,
internal::RelocateJJImm20);
Insert(map, OpcodeEnum::kJ, SourceOpEnum::kJImm20, internal::RelocateJJImm20);
Insert(map, OpcodeEnum::kJr, SourceOpEnum::kJImm12,
internal::RelocateJrJImm12);
Insert(map, OpcodeEnum::kLui, SourceOpEnum::kUImm20,
internal::RelocateLuiUImm20);
Insert(map, OpcodeEnum::kSd, SourceOpEnum::kSImm12,
internal::RelocateSdSImm12);
Insert(map, OpcodeEnum::kJalr, SourceOpEnum::kJImm12,
internal::RelocateJrJImm12);
Insert(map, OpcodeEnum::kAuipc, SourceOpEnum::kUImm20,
internal::RelocateAuipcUImm20);
}
} // namespace riscv
} // namespace sim
} // namespace mpact
#endif // THIRD_PARTY_MPACT_RISCV_RISCV_BIN_SETTERS_H_