- Added Linker and multiple file assembly support.
All checks were successful
continuous-integration/drone/push Build is passing

- Added asm/registers.asm and asm/api.asm  with some used registers on the platform
- Added embedded resources into build
This commit is contained in:
DataHoarder 2021-01-01 06:41:02 +01:00
parent a824385ec4
commit d9094e7d83
13 changed files with 385 additions and 30 deletions

View file

@ -3,6 +3,26 @@ project(rrcc)
set(CMAKE_CXX_STANDARD 14)
# Compilation step for static resources
FUNCTION(ADD_RESOURCES out_var)
SET(result)
FOREACH(in_f ${ARGN})
FILE(RELATIVE_PATH src_f ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${in_f})
SET(out_f "${PROJECT_BINARY_DIR}/${in_f}.o")
get_filename_component(out_d ${out_f} DIRECTORY)
FILE(MAKE_DIRECTORY ${out_d})
ADD_CUSTOM_COMMAND(OUTPUT ${out_f}
COMMAND ld --relocatable --format binary --output ${out_f} ${src_f}
DEPENDS ${in_f}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Embedding object ${src_f} into ${out_f}"
VERBATIM
)
LIST(APPEND result ${out_f})
ENDFOREACH()
SET(${out_var} "${result}" PARENT_SCOPE)
ENDFUNCTION()
set(SOURCE_FILES
src/instructions/AddressOffset.h
@ -28,6 +48,11 @@ set(SOURCE_FILES
src/Token.cpp src/Token.h
src/Declaration.cpp src/Declaration.h
src/Function.cpp src/Function.h
src/Assembler.cpp src/Assembler.h)
src/Assembler.cpp src/Assembler.h src/Linker.cpp src/Linker.h src/EmbeddedResource.h)
add_executable(rrc-as src/rrcas.cpp ${SOURCE_FILES})
ADD_RESOURCES(embeddedResources
asm/registers.asm
asm/api.asm
)
add_executable(rrc-as src/rrcas.cpp ${SOURCE_FILES} ${embeddedResources})

View file

@ -19,4 +19,10 @@ NOTE: **This is a Work In Progress project**
Assembler, kind-of 2-Pass. Quite loose token syntax defined in [Token.h](src/Token.h)
### Usage
* `$ ./rrc-as code.asm output.bin`
* `$ ./rrc-as code.asm [code2.asm ...] output.bin`
* Multiple asm files can be specified. They are interpreted from first in arguments to last.
* You can call functions across files, as they will be linked together.
* Directive resolution occurs at parsing time, so while you can override values it does not affect previously parsed files.
* Directives like `.constant` are passed to the next files.
* These files will be automatically included in front every time:
* *[asm/registers.asm](asm/registers.asm)*

51
asm/api.asm Normal file
View file

@ -0,0 +1,51 @@
; Definition of registers found on FM10000 official images for comunication back with driver/manager
; Based on Intel datasheet and BSD-3 code.
.constant api_SPI_LOCK_STATE, %0x800
.constant api_PCIE_SBUS_LOCK_STATE, %0x801
.constant api_SOFT_RESET_LOCK_STATE, %0x802
.constant api_RECOVERY_STATUS_VECTOR, %0x803
.constant api_PEP_MAC_BASE, %0x80a
.constant api_CUSTOM_MAC_BASE, %0x864
.constant api_BSM_STATUS, %0x990
.constant api_EEPROM_IMAGE_VERSION, %0x991
.constant api_MASTER_FW_VERSION, %0x992
.constant api_SERDES_FW_VERSION, %0x993
.constant api_SERDES_STATUS_1, %0x994
.constant api_SERDES_STATUS_2, %0x995
.constant api_SERDES_STATUS_3, %0x996
.constant api_SERDES_STATUS_4, %0x997
.constant api_PCIE_MASTER_STATUS, %0x998
.constant api_PCIE_SERDES_STATUS, %0x999
.constant api_DE_COLD_RESET_STATUS, %0x9ae
.constant api_SBUS_RESET_STATUS, %0x9af
.constant api_MEMORY_REPAIR_STATUS, %0x9b0
.constant api_MEMORY_INIT_STATUS, %0x9b1
.constant api_PCIE_PCS_DIS_STATUS, %0x9b2
.constant api_PCIE_MASTER_FW_DL_STATUS, %0x9b3
.constant api_PCIE_FW_CHECK_STATUS, %0x9b4
.constant api_PCIE_SERDES_FW_DL_STATUS, %0x9b5
.constant api_PCIE_SERDES_INIT_STATUS, %0x9b6
.constant api_PCIE_PCS_EN_STATUS, %0x9b7
.constant api_PCIE_DE_WARM_RESET_STATUS, %0x9b8
.constant api_PCIE_ISR_STATUS_0, %0x9b9
.constant api_PCIE_ISR_STATUS_1, %0x9ba
.constant api_PCIE_ISR_STATUS_2, %0x9bb
.constant api_PCIE_ISR_STATUS_3, %0x9bc
.constant api_PCIE_ISR_STATUS_4, %0x9bd
.constant api_PCIE_ISR_STATUS_5, %0x9be
.constant api_PCIE_ISR_STATUS_6, %0x9bf
.constant api_PCIE_ISR_STATUS_7, %0x9c0
.constant api_PCIE_ISR_STATUS_8, %0x9c1
.constant api_SERDES_OOR_STATUS_PASS_1, %0x9c2
.constant api_SERDES_OOR_STATUS_PASS_2, %0x9c3
.constant api_SW_LOCK_ERR_STATUS, %0x9c4
.constant api_PCIE_EN_REFCLK_STATUS, %0x9c5
.constant api_RE_RESET_MASK_STATUS_1, %0x9c6
.constant api_RE_RESET_MASK_STATUS_2, %0x9c7
.constant api_RE_RESET_ERR_STATUS, %0x9c8

83
asm/registers.asm Normal file
View file

@ -0,0 +1,83 @@
; Definition of registers found on FM10000 ASIP
; Based on Intel datasheet and BSD-3 code.
.constant FATAL_CODE, %0x0
.constant LAST_FATAL_CODE, %0x1
.constant SOFT_RESET, %0x3
.constant DEVICE_CFG, %0x4
.constant RESET_CFG, %0x5
.constant WATCHDOG_CFG, %0x6
.constant MGMT_SCRATCH_0, %0x8
.constant MGMT_SCRATCH_1, %0x9
.constant VITAL_PRODUCT_DATA, %0x304
.constant GLOBAL_INTERRUPT_DETECT, %0x400
.constant INTERRUPT_MASK_BSM, %0x442
.constant CHIP_VERSION, %0x452
.constant BSM_SCRATCH_START, %0x800
.constant BSM_SCRATCH_END, %0xBFF
.constant BSM_ARGS, %0x000C01
.constant BSM_ADDR_OFFSET_0, %0x000C04
.constant BSM_ADDR_OFFSET_1, %0x000C05
.constant BSM_ADDR_OFFSET_2, %0x000C06
.constant BSM_ADDR_OFFSET_3, %0x000C07
.constant BSM_COUNTER_0, %0x000C08
.constant BSM_COUNTER_1, %0x000C09
.constant BIST_CTRL_0, %0x000C10
.constant BIST_CTRL_1, %0x000C11
.constant REI_CTRL, %0x000C12
.constant REI_STAT, %0x000C13
.constant GPIO_CFG, %0x000C15
.constant GPIO_DATA, %0x000C16
.constant GPIO_IP, %0x000C17
.constant GPIO_IM, %0x000C18
.constant PLL_PCIE_CTRL, %0x2241
.constant PLL_PCIE_STAT, %0x2242
.constant SBUS_PCIE_CFG, %0x2243
.constant SBUS_PCIE_COMMAND, %0x2244
.constant SBUS_PCIE_REQUEST, %0x2245
.constant SBUS_PCIE_RESPONSE, %0x2246
.constant SBUS_PCIE_SPICO_IN, %0x2247
.constant SBUS_PCIE_SPICO_OUT, %0x2248
.constant SBUS_PCIE_IP, %0x2249
.constant SBUS_PCIE_IM, %0x224a
.constant PCIE_XPLL_CTRL, %0x3000
.constant PCIE_CLK_CTRL, %0x3001
.constant PCIE_CLK_CTRL_2, %0x3002
.constant PCIE_CLKMON_RATIO_CFG, %0x3003
.constant PCIE_CLKMON_TOLERANCE_CFG, %0x3004
.constant PCIE_CLKMON_DEADLINES_CFG, %0x3005
.constant PCIE_CLK_STAT, %0x3006
.constant PCIE_CLK_IP, %0x3007
.constant PCIE_CLK_IM, %0x3008
.constant PCIE_WARM_RESET_DELAY, %0x3009
.constant PORTS_MGMT_BASE_ADDRESS, %0xE8000
.constant PLL_EPL_CTRL, %0xE8000
.constant PLL_EPL_STAT, %0xE8001
.constant PLL_FABRIC_CTRL, %0xE8002
.constant PLL_FABRIC_STAT, %0xE8003
.constant PLL_FABRIC_LOCK, %0xE8004
.constant SBUS_EPL_CFG, %0xE8005
.constant SBUS_EPL_COMMAND, %0xE8006
.constant SBUS_EPL_REQUEST, %0xE8007
.constant SBUS_EPL_RESPONSE, %0xE8008
.constant SBUS_EPL_SPICO_IN, %0xE8009
.constant SBUS_EPL_SPICO_OUT, %0xE800a
.constant SBUS_EPL_IP, %0xE800b
.constant SBUS_EPL_IM, %0xE800c
.constant PM_CLKOBS_CTRL, %0xE8012

View file

@ -43,7 +43,7 @@ void Assembler::assemble(uint32_t baseAddress, uint32_t imageSize) {
if (placementMode == FunctionPlacementMode::PlaceAll) {
for (auto &f : parser.getTree()) {
for (auto &f : linker.getTree()) {
if (freeOffsetLocation == baseAddress && f.label != "entrypoint") {
throw std::runtime_error("entrypoint not at start");
}
@ -184,7 +184,7 @@ uint32_t Assembler::placeFunction(uint32_t base, const Function &function) {
}
const Function *Assembler::getFunctionByLabel(const std::string &l) {
for (auto &f : parser.getTree()) {
for (auto &f : linker.getTree()) {
if (f.label == l) {
return &f;
}

View file

@ -27,13 +27,12 @@
#pragma once
#include "Parser.h"
#include "Linker.h"
#include "instructions/Instruction.h"
class Assembler {
private:
const Parser &parser;
const Linker &linker;
bool padEndFunction = true;
std::vector<uint8_t> bytes;
std::unordered_map<std::string, uint32_t> knownRegisters;
@ -45,7 +44,7 @@ private:
public:
Assembler(const Parser &parser) : parser(parser) {
Assembler(const Linker &linker) : linker(linker) {
}

54
src/EmbeddedResource.h Normal file
View file

@ -0,0 +1,54 @@
/*****************************************************************************
* Copyright (c) 2020, rrcc FM10K-Documentation Contributors
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma once
#include <cstddef>
class EmbeddedResource {
public:
EmbeddedResource(const char *start, const char *end) : mData(start),
mSize(end - start) {}
const char *const &data() const { return mData; }
const size_t &size() const { return mSize; }
const char *begin() const { return mData; }
const char *end() const { return mData + mSize; }
private:
const char *mData;
size_t mSize;
};
#define LOAD_RESOURCE(x) ([]() { \
extern const char _binary_##x##_start, _binary_##x##_end; \
return EmbeddedResource(&_binary_##x##_start, &_binary_##x##_end); \
})()

51
src/Linker.cpp Normal file
View file

@ -0,0 +1,51 @@
/*****************************************************************************
* Copyright (c) 2020, rrcc FM10K-Documentation Contributors
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "Linker.h"
void Linker::addFromParser(const Parser &p) {
for (auto &fn : p.getTree()) {
addFunction(fn);
}
for (auto &v : p.getVariables()) {
variables[v.first] = v.second;
}
}
void Linker::addFunction(const Function &f) {
for (auto &fn : functions) {
if (fn.label == f.label) {
fn = f;
return;
}
}
functions.push_back(f);
}
void Linker::addVariable(const std::string &k, const std::vector<Token> &v) {
variables[k] = v;
}

54
src/Linker.h Normal file
View file

@ -0,0 +1,54 @@
/*****************************************************************************
* Copyright (c) 2020, rrcc FM10K-Documentation Contributors
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma once
#include "Parser.h"
class Linker {
std::vector<Function> functions;
std::unordered_map<std::string, std::vector<Token>> variables;
public:
Linker() {
}
void addFunction(const Function &f);
void addVariable(const std::string &k, const std::vector<Token> &v);
void addFromParser(const Parser &p);
const std::vector<Function> &getTree() const {
return functions;
}
const auto &getVariables() const {
return variables;
}
};

View file

@ -30,7 +30,6 @@
void Parser::parse() {
offset = 0;
functions.clear();
variables.clear();
std::string currentValue;
uint8_t c;

View file

@ -29,6 +29,7 @@
#include <cstdint>
#include <utility>
#include <vector>
#include <algorithm>
#include <unordered_map>
@ -94,8 +95,13 @@ class Parser {
static bool isAlphaNumeric(const std::string &v);
public:
Parser(const std::vector<uint8_t> &bytes, std::unordered_map<std::string, std::vector<Token>> variables) : bytes(
bytes), variables(std::move(variables)) {
}
Parser(const std::vector<uint8_t> &bytes) : bytes(bytes) {
parse();
}
void parse();

View file

@ -56,6 +56,8 @@ public:
//End of Token: \n\t[space],;
};
Token(const Token &) = default;
Token(Type type, std::string valueString, uint32_t valueImmediate = 0) : type(type), valueImmediate(valueImmediate),
valueString(std::move(valueString)) {

View file

@ -3,40 +3,65 @@
#include <vector>
#include "Parser.h"
#include "Assembler.h"
#include "instructions/virtual/Stack.h"
#include "EmbeddedResource.h"
int main(int argc, char *argv[]) {
if (argc < 3) {
std::cout << "Usage: " << argv[0] << " code.asm output.bin\n";
std::cout << "Usage: " << argv[0] << " code.asm [code2.asm ...] output.bin\n";
return 1;
}
try {
std::ifstream image(argv[1]);
if (image.is_open()) {
std::vector<uint8_t> bytes;
int c;
while (!image.eof() && (c = image.get()) != EOF) {
bytes.push_back(c);
}
Linker linker;
std::vector<EmbeddedResource> embeddedResources = {
LOAD_RESOURCE(asm_registers_asm),
LOAD_RESOURCE(asm_api_asm)
};
Parser parser(bytes);
linker.addVariable("rrcc_STACK_START",
{Token(Token::Type::RegisterLocation, std::to_string(Instruction::Stack::stackRegisterStart),
Instruction::Stack::stackRegisterStart)});
linker.addVariable("rrcc_STACK_POINTER", {Token(Token::Type::RegisterLocation,
std::to_string(Instruction::Stack::stackOffsetRegisterAddress),
Instruction::Stack::stackOffsetRegisterAddress)});
for (auto &r : embeddedResources) {
std::vector<uint8_t> bytes(r.begin(), r.end());
Parser parser(bytes, linker.getVariables());
parser.parse();
linker.addFromParser(parser);
}
Assembler assembler(parser);
assembler.assemble();
std::ofstream patchedImage(argv[2]);
if (patchedImage.is_open()) {
auto &result = assembler.getImage();
for (auto c : result) {
patchedImage.put(c);
for (int inputIndex = 1; inputIndex < (argc - 1); ++inputIndex) {
std::ifstream image(argv[inputIndex]);
if (image.is_open()) {
std::vector<uint8_t> bytes;
int c;
while (!image.eof() && (c = image.get()) != EOF) {
bytes.push_back(c);
}
patchedImage.close();
Parser parser(bytes, linker.getVariables());
parser.parse();
linker.addFromParser(parser);
} else {
throw std::runtime_error("Could not open " + std::string(argv[inputIndex]));
}
}
Assembler assembler(linker);
assembler.assemble();
std::ofstream patchedImage(argv[argc - 1]);
if (patchedImage.is_open()) {
auto &result = assembler.getImage();
for (auto c : result) {
patchedImage.put(c);
}
patchedImage.close();
}
} catch (const std::exception &e) {
std::cerr << "Exception: " << e.what() << "\n";