lcpu: officially support legacy 32bit branch
32-bit builds using the development headers work on the legacy 32-bit branch so I don't really see a reason to not support it.. sure, it sucks that I now won't be able to get rid of a pretty gnarly codepath, but /shrug
This commit is contained in:
parent
6eada83eeb
commit
7ae6acfc3b
19
README.md
19
README.md
|
@ -9,7 +9,7 @@ It provides:
|
||||||
(that and the more reasons to not use Lua for a part of this codebase, the better...)
|
(that and the more reasons to not use Lua for a part of this codebase, the better...)
|
||||||
- Interoperation with the Wiremod addon (and addons which implement Wiremod integration)
|
- Interoperation with the Wiremod addon (and addons which implement Wiremod integration)
|
||||||
|
|
||||||
This addon (for now) works with both the non-beta branch and the x86-64 beta branches of GMod.
|
This addon works with both the non-beta branch and the x86-64 beta branches of GMod, however rigorous testing is usually only done with the x86-64 beta branch.
|
||||||
|
|
||||||
Note that the GitHub mirror is provided only for convinence, and is not used for active development.
|
Note that the GitHub mirror is provided only for convinence, and is not used for active development.
|
||||||
See [this link](https://git.crustywindo.ws/modeco80/gmod-lcpu) for the actual development repository.
|
See [this link](https://git.crustywindo.ws/modeco80/gmod-lcpu) for the actual development repository.
|
||||||
|
@ -20,28 +20,15 @@ You will need Wiremod installed, either from the Workshop or cloned as a filesys
|
||||||
|
|
||||||
This repository is set up to be a Filesystem Addon; therefore, workflows which clone repositories from Git and put them in addons/ should be able to work with the LCPU addon just fine.
|
This repository is set up to be a Filesystem Addon; therefore, workflows which clone repositories from Git and put them in addons/ should be able to work with the LCPU addon just fine.
|
||||||
|
|
||||||
Preliminary installation steps (by hand):
|
Preliminary installation steps (for Linux):
|
||||||
|
|
||||||
```
|
```
|
||||||
garrysmod/addons$ git clone --recursive https://git.crustywindo.ws/modeco80/gmod-lcpu.git lcpu
|
garrysmod/addons$ git clone --recursive https://git.crustywindo.ws/modeco80/gmod-lcpu.git lcpu
|
||||||
garrysmod/addons$ cd lcpu
|
garrysmod/addons$ cd lcpu
|
||||||
|
garrysmod/addons/lcpu$ ./build_module.sh
|
||||||
# Build the LCPU native module. These steps build the linux64 version of the module
|
|
||||||
# on linux; you'll need to alter it if you want to build for 32-bit.
|
|
||||||
garrysmod/addons/lcpu$ cmake -Wno-dev -GNinja -S native -B build \
|
|
||||||
-DCMAKE_BUILD_TYPE=Release
|
|
||||||
garrysmod/addons/lcpu$ ninja -C build
|
|
||||||
|
|
||||||
# Install the native module (Linux)
|
|
||||||
# For Windows you can do the same thing, just replace this
|
|
||||||
# with how you'd do it in batch (or use Explorer, I'm not your dad)
|
|
||||||
garrysmod/addons/lcpu$ [[ ! -d '../../lua/bin']] && mkdir -p ../../lua/bin && cp build/projects/lcpu/*.dll ../../lua/bin
|
|
||||||
|
|
||||||
# Tada!
|
# Tada!
|
||||||
```
|
```
|
||||||
|
|
||||||
On Linux you can alternatively use the `./build_module.sh` script that will do all the build and installation steps automatically, once cloning the repository in the garrysmod/addons folder.
|
|
||||||
|
|
||||||
Windows building is currently untested; I see no reason why it wouldn't work.
|
Windows building is currently untested; I see no reason why it wouldn't work.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Build the LCPU addon for the reccomended environment
|
# Build the LCPU native module for both linux32 and linux64
|
||||||
# and install it into the proper directory gmod wants native modules to be.
|
# and install it into the proper directory gmod wants native modules to be.
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
|
@ -8,11 +8,38 @@ set -x
|
||||||
# where your game server is
|
# where your game server is
|
||||||
GS_PATH="/home/lily/gs/gmod"
|
GS_PATH="/home/lily/gs/gmod"
|
||||||
|
|
||||||
cmake -Wno-dev -GNinja -S native -B module_build -DCMAKE_BUILD_TYPE=Release
|
# make the module build directory
|
||||||
ninja -C module_build
|
[[ ! -d "module_build" ]] && {
|
||||||
|
mkdir module_build
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 cmake build dir
|
||||||
|
# $@ any other args to cmake
|
||||||
|
cmake_gen() {
|
||||||
|
local BD=$1
|
||||||
|
shift
|
||||||
|
cmake -Wno-dev -GNinja -S native -B module_build/$BD $@ -DCMAKE_BUILD_TYPE=Release
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 cmake build dir
|
||||||
|
cmake_build() {
|
||||||
|
ninja -C module_build/$1
|
||||||
|
}
|
||||||
|
|
||||||
|
build_and_place() {
|
||||||
|
cmake_gen linux32 --toolchain $PWD/native/cmake/linux32-toolchain.cmake
|
||||||
|
cmake_gen linux64
|
||||||
|
cmake_build linux32
|
||||||
|
cmake_build linux64
|
||||||
|
|
||||||
|
# GMod doesn't actually make the lua/bin directory on its own
|
||||||
|
# so we have to check if it exists first and make if it doesn't
|
||||||
[[ ! -d "$GS_PATH/garrysmod/lua/bin" ]] && {
|
[[ ! -d "$GS_PATH/garrysmod/lua/bin" ]] && {
|
||||||
mkdir -p $GS_PATH/garrysmod/lua/bin
|
mkdir -p $GS_PATH/garrysmod/lua/bin
|
||||||
}
|
}
|
||||||
|
|
||||||
cp -v module_build/projects/lcpu/*.dll $GS_PATH/garrysmod/lua/bin
|
cp -v module_build/linux32/projects/lcpu/*.dll $GS_PATH/garrysmod/lua/bin
|
||||||
|
cp -v module_build/linux64/projects/lcpu/*.dll $GS_PATH/garrysmod/lua/bin
|
||||||
|
}
|
||||||
|
|
||||||
|
build_and_place
|
||||||
|
|
|
@ -9,8 +9,6 @@ add_subdirectory(projects/lucore)
|
||||||
# RISC-V emulator library
|
# RISC-V emulator library
|
||||||
add_subdirectory(projects/riscv)
|
add_subdirectory(projects/riscv)
|
||||||
|
|
||||||
add_subdirectory(projects/riscv_test_harness)
|
|
||||||
|
|
||||||
# Garry's Mod native bindings to RISC-V emulator
|
# Garry's Mod native bindings to RISC-V emulator
|
||||||
# Also lua device stuff
|
# Also lua device stuff
|
||||||
add_subdirectory(projects/lcpu)
|
add_subdirectory(projects/lcpu)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# toolchain file for linux multilib building
|
||||||
|
set(CMAKE_C_FLAGS "-m32" CACHE STRING "C compiler flags" FORCE)
|
||||||
|
set(CMAKE_CXX_FLAGS "-m32" CACHE STRING "C++ compiler flags" FORCE)
|
||||||
|
|
||||||
|
if(EXISTS /usr/lib32)
|
||||||
|
set(LIB32 /usr/lib32)
|
||||||
|
else()
|
||||||
|
set(LIB32 /usr/lib)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
set(CMAKE_SYSTEM_LIBRARY_PATH ${LIB32} CACHE STRING "system library search path" FORCE)
|
||||||
|
set(CMAKE_LIBRARY_PATH ${LIB32} CACHE STRING "library search path" FORCE)
|
||||||
|
|
||||||
|
# this is probably unlikely to be needed, but just in case
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "-m32 -L${LIB32}" CACHE STRING "executable linker flags" FORCE)
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "-m32 -L${LIB32}" CACHE STRING "shared library linker flags" FORCE)
|
||||||
|
set(CMAKE_MODULE_LINKER_FLAGS "-m32 -L${LIB32}" CACHE STRING "module linker flags" FORCE)
|
||||||
|
|
||||||
|
# point pkg-config to lib32
|
||||||
|
if(EXISTS ${LIB32}/pkgconfig)
|
||||||
|
set(ENV{PKG_CONFIG_LIBDIR} ${LIB32}/pkgconfig:/usr/share/pkgconfig:/usr/lib/pkgconfig:/usr/lib64/pkgconfig)
|
||||||
|
endif()
|
|
@ -1,15 +1,9 @@
|
||||||
#include "SourceSink.hpp"
|
#include "SourceSink.hpp"
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <lucore/Assert.hpp>
|
#include <lucore/Assert.hpp>
|
||||||
#include <lucore/Library.hpp>
|
#include <lucore/Library.hpp>
|
||||||
#include <lucore/Types.hpp>
|
#include <lucore/Types.hpp>
|
||||||
|
|
||||||
// The old non-beta branch of GMod on Linux has multiple tier0 libraries for client and server.
|
|
||||||
// This compatibility define allows to support that case (for now). Once this define is removed,
|
|
||||||
// the old codepath can be totally removed.
|
|
||||||
#define LCPU_SUPPORT_OLD_GMOD
|
|
||||||
|
|
||||||
namespace tier0 {
|
namespace tier0 {
|
||||||
lucore::Library* library = nullptr;
|
lucore::Library* library = nullptr;
|
||||||
|
|
||||||
|
@ -17,7 +11,6 @@ namespace tier0 {
|
||||||
Msg_t Msg {};
|
Msg_t Msg {};
|
||||||
|
|
||||||
bool OpenLibrary() {
|
bool OpenLibrary() {
|
||||||
#ifdef LCPU_SUPPORT_OLD_GMOD
|
|
||||||
constexpr static std::string_view tier0_libraries[] {
|
constexpr static std::string_view tier0_libraries[] {
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
"tier0_srv",
|
"tier0_srv",
|
||||||
|
@ -32,12 +25,6 @@ namespace tier0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
// The x86-64 branch of GMod, including the 32-bit binaries in the branch,
|
|
||||||
// have a single tier0 library, which makes the codepath much simpler.
|
|
||||||
// Hopefully I can switch to this path at some point.
|
|
||||||
tier0::library = lucore::Library::OpenExisting("tier0");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(tier0::library == nullptr)
|
if(tier0::library == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
@ -65,14 +52,14 @@ namespace lcpu {
|
||||||
|
|
||||||
SourceSink::SourceSink() {
|
SourceSink::SourceSink() {
|
||||||
if(!tier0::OpenLibrary()) {
|
if(!tier0::OpenLibrary()) {
|
||||||
std::printf("Tier0 could not be opened\n");
|
std::printf("Tier0 could not be opened - aborting\n");
|
||||||
std::quick_exit(10);
|
std::quick_exit(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: A bit nicer of an error message?
|
// TODO: A bit nicer of an error message?
|
||||||
// Explain *what* to do if you see this message.
|
// Explain *what* to do if you see this message.
|
||||||
if(!tier0::GrabSymbols()) {
|
if(!tier0::GrabSymbols()) {
|
||||||
std::printf("Tier0 symbols could not be grabbed\n");
|
std::printf("Tier0 symbols could not be grabbed - aborting\n");
|
||||||
std::quick_exit(10);
|
std::quick_exit(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace lucore::detail {
|
||||||
}
|
}
|
||||||
|
|
||||||
void* OsLibrarySymbol(OsLibraryHandle dll, const char* symbolName) {
|
void* OsLibrarySymbol(OsLibraryHandle dll, const char* symbolName) {
|
||||||
return GetProcAddressA(reinterpret_cast<HMODULE*>(dll), symbolName);
|
return GetProcAddressA(reinterpret_cast<HMODULE>(dll), symbolName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OsFreeLibrary(OsLibraryHandle handle) {
|
void OsFreeLibrary(OsLibraryHandle handle) {
|
||||||
|
|
|
@ -12,4 +12,4 @@ Depends on lucore.
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
TBD (if this is moved to another repo). See the riscv_test_harness project.
|
TBD (if this is moved to another repo). See the lcpu project
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
add_executable(rvtest
|
|
||||||
main.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(rvtest PUBLIC
|
|
||||||
riscv::riscv
|
|
||||||
)
|
|
|
@ -1,69 +0,0 @@
|
||||||
//! A test harness for testing if the riscv library actually works.
|
|
||||||
#include <cstdio> // I know, I know, but this is a test program. Yell later :)
|
|
||||||
#include <lucore/Assert.hpp>
|
|
||||||
#include <lucore/Logger.hpp>
|
|
||||||
#include <lucore/StdoutSink.hpp>
|
|
||||||
#include <riscv/System.hpp>
|
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
/// simple 16550 UART implementation
|
|
||||||
struct SimpleUartDevice : public riscv::Bus::MmioDevice {
|
|
||||||
constexpr static riscv::Address BASE_ADDRESS = 0x10000000;
|
|
||||||
|
|
||||||
riscv::Address Base() const override { return BASE_ADDRESS; }
|
|
||||||
|
|
||||||
riscv::Address Size() const override { return 12; } // for now
|
|
||||||
|
|
||||||
u32 Peek(riscv::Address address) override {
|
|
||||||
switch(address) {
|
|
||||||
case BASE_ADDRESS: return '\0'; // just return 0 for the input register
|
|
||||||
case BASE_ADDRESS + 5: return 0x60; // active, but no keyboard input
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Poke(riscv::Address address, u32 value) override {
|
|
||||||
if(address == BASE_ADDRESS) {
|
|
||||||
char c = value & 0x000000ff;
|
|
||||||
fputc(c, stderr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
lucore::LoggerAttachStdout();
|
|
||||||
|
|
||||||
LUCORE_CHECK(argc == 2, "this test harness expects one argument (the file to load into riscv memory and execute). got {} arguments", argc);
|
|
||||||
|
|
||||||
// 128 KB of ram. Won't be enough to boot linux but should be good enough to test most baremetal apps
|
|
||||||
auto system = riscv::System::Create(128 * 1024);
|
|
||||||
LUCORE_CHECK(system, "could not create system for some reason.");
|
|
||||||
|
|
||||||
// Attach our UART device
|
|
||||||
system->bus->AttachDevice(new SimpleUartDevice);
|
|
||||||
|
|
||||||
auto fp = std::fopen(argv[1], "rb");
|
|
||||||
LUCORE_CHECK(fp, "could not open file \"{}\"", argv[1]);
|
|
||||||
|
|
||||||
std::fseek(fp, 0, SEEK_END);
|
|
||||||
auto len = std::ftell(fp);
|
|
||||||
std::fseek(fp, 0, SEEK_SET);
|
|
||||||
|
|
||||||
std::fread(system->ram->Raw(), 1, len, fp);
|
|
||||||
std::fclose(fp);
|
|
||||||
|
|
||||||
// This allows the host program running under the test
|
|
||||||
// harness to tell us to shut down.
|
|
||||||
bool shouldExit = false;
|
|
||||||
system->OnPowerOff = [&shouldExit]() { shouldExit = true; };
|
|
||||||
|
|
||||||
while(!shouldExit) {
|
|
||||||
system->Step();
|
|
||||||
//std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
||||||
}
|
|
||||||
|
|
||||||
delete system;
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
PROJECT = test
|
|
||||||
|
|
||||||
# where your rv32 toolchain is
|
|
||||||
TCPATH = /home/lily/bin/riscv/bin
|
|
||||||
PREFIX = $(TCPATH)/riscv32-unknown-elf
|
|
||||||
|
|
||||||
CC = $(PREFIX)-gcc
|
|
||||||
CXX = $(PREFIX)-g++
|
|
||||||
|
|
||||||
ARCHFLAGS = -ffreestanding -fno-stack-protector -fdata-sections -ffunction-sections -march=rv32ima -mabi=ilp32
|
|
||||||
CCFLAGS = -g -Os $(ARCHFLAGS) -std=c18
|
|
||||||
CXXFLAGS = $(ARCHFLAGS) -g -Os -std=c++20 -fno-exceptions -fno-rtti
|
|
||||||
LDFLAGS = -T binary.ld -nostdlib -Wl,--gc-sections
|
|
||||||
|
|
||||||
OBJS = start.o \
|
|
||||||
main.o
|
|
||||||
|
|
||||||
.PHONY: all test clean
|
|
||||||
|
|
||||||
all: $(PROJECT).bin $(PROJECT).debug.txt
|
|
||||||
|
|
||||||
# this assumes the lcpu project build dir you're using is
|
|
||||||
# [lcpu repo root]/build
|
|
||||||
test: $(PROJECT).bin $(PROJECT).debug.txt
|
|
||||||
../../../../build/projects/riscv_test_harness/rvtest $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm $(PROJECT).elf $(PROJECT).bin $(PROJECT).debug.txt $(OBJS)
|
|
||||||
|
|
||||||
# Link rules
|
|
||||||
|
|
||||||
$(PROJECT).elf: $(OBJS)
|
|
||||||
$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $(OBJS)
|
|
||||||
|
|
||||||
$(PROJECT).bin : $(PROJECT).elf
|
|
||||||
$(PREFIX)-objcopy $^ -O binary $@
|
|
||||||
|
|
||||||
$(PROJECT).debug.txt : $(PROJECT).elf
|
|
||||||
$(PREFIX)-objdump -t $^ > $@
|
|
||||||
$(PREFIX)-objdump -S $^ >> $@
|
|
||||||
|
|
||||||
# Compile rules
|
|
||||||
|
|
||||||
%.o: %.cpp
|
|
||||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
|
||||||
|
|
||||||
%.o: %.c
|
|
||||||
$(CC) -c $(CCFLAGS) $< -o $@
|
|
||||||
|
|
||||||
%.o: %.S
|
|
||||||
$(CC) -x assembler-with-cpp -march=rv32ima -mabi=ilp32 -c $< -o $@
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
# what
|
|
||||||
|
|
||||||
This is a simple bare-metal riscv program that is able to run on the test harness that does some testing.
|
|
||||||
|
|
||||||
It is barebones, I know.
|
|
|
@ -1,73 +0,0 @@
|
||||||
__heap_size = 0x1000;
|
|
||||||
__stack_size = 0x1000;
|
|
||||||
|
|
||||||
ENTRY(_start)
|
|
||||||
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
. = 0x80000000;
|
|
||||||
.text : ALIGN(16) {
|
|
||||||
__TEXT_BEGIN__ = .;
|
|
||||||
*(.initial_jump)
|
|
||||||
*(.entry.text)
|
|
||||||
*(.init.literal)
|
|
||||||
*(.init)
|
|
||||||
*(.text)
|
|
||||||
*(.literal .text .literal.* .text.* .stub)
|
|
||||||
*(.out_jump.literal.*)
|
|
||||||
*(.out_jump.*)
|
|
||||||
__TEXT_END__ = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we're on a newer compiler */
|
|
||||||
/DISCARD/ :
|
|
||||||
{
|
|
||||||
*(.interp)
|
|
||||||
*(.dynsym)
|
|
||||||
*(.dynstr)
|
|
||||||
*(.header)
|
|
||||||
} : phdr
|
|
||||||
|
|
||||||
.data : ALIGN(16) {
|
|
||||||
__DATA_BEGIN__ = .;
|
|
||||||
*(.rodata)
|
|
||||||
*(.rodata.*)
|
|
||||||
*(.gnu.linkonce.r.*)
|
|
||||||
*(.rodata1)
|
|
||||||
*(.dynsbss)
|
|
||||||
*(.gnu.linkonce.sb.*)
|
|
||||||
*(.scommon)
|
|
||||||
*(.gnu.linkonce.sb2.*)
|
|
||||||
*(.sbss)
|
|
||||||
*(.sbss.*)
|
|
||||||
*(.sbss2)
|
|
||||||
*(.sbss2.*)
|
|
||||||
*(.dynbss)
|
|
||||||
*(.data)
|
|
||||||
*(.data.*)
|
|
||||||
*(.got)
|
|
||||||
*(.got.*)
|
|
||||||
__DATA_END__ = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bss : ALIGN( 16 ) {
|
|
||||||
__BSS_BEGIN__ = .;
|
|
||||||
*(.bss) /* Tricky: BSS needs to be allocated but not sent. GCC Will not populate these for calculating data size */
|
|
||||||
*(.bss.*)
|
|
||||||
__BSS_END__ = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
.heap : ALIGN( 16 ) {
|
|
||||||
_sheap = .;
|
|
||||||
. = . + __heap_size;
|
|
||||||
_eheap = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stack : ALIGN( 16 ) {
|
|
||||||
_estack = .;
|
|
||||||
. = . + __stack_size;
|
|
||||||
_sstack = .;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
// a simple test program
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
uint32_t strlen(const char* str) {
|
|
||||||
if(!str)
|
|
||||||
return 0;
|
|
||||||
const char* c = str;
|
|
||||||
while(*c++)
|
|
||||||
;
|
|
||||||
return c - str;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SYSCON *(volatile uint32_t*)0x11100000
|
|
||||||
|
|
||||||
#define UART_BASE 0x10000000
|
|
||||||
#define UART_DATA *(volatile uint32_t*)UART_BASE
|
|
||||||
#define UART_STATUS UART_DATA
|
|
||||||
|
|
||||||
void putc(char c) {
|
|
||||||
UART_DATA = (uint32_t)c;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((noinline)) void puts(const char* str) {
|
|
||||||
const uint32_t length = strlen(str);
|
|
||||||
for(uint32_t i = 0; i < length; ++i)
|
|
||||||
putc(str[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t value = 0;
|
|
||||||
static uint16_t shortvalue = 0;
|
|
||||||
static uint8_t bytevalue = 0;
|
|
||||||
|
|
||||||
#define COUNTER_TEST(var, max) \
|
|
||||||
for(int i = 0; i < max; ++i) { \
|
|
||||||
puts(#var " is (before modification): "); \
|
|
||||||
putc("0123456789"[var]); \
|
|
||||||
putc('\n'); \
|
|
||||||
\
|
|
||||||
var = i; \
|
|
||||||
puts(#var " is (after modification): "); \
|
|
||||||
putc("0123456789"[var]); \
|
|
||||||
putc('\n'); \
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
puts("hello world I guess\n");
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
COUNTER_TEST(value, 9);
|
|
||||||
COUNTER_TEST(shortvalue, 9);
|
|
||||||
COUNTER_TEST(bytevalue, 9);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Shut down the test harness once we're done testing.
|
|
||||||
puts("Tests done, shutting down test harness...\n");
|
|
||||||
//SYSCON = 0x5555;
|
|
||||||
|
|
||||||
// loop forever
|
|
||||||
for(;;);
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
# Simple bare-metal RISCV startup code.
|
|
||||||
|
|
||||||
.section .initial_jump
|
|
||||||
.global _start
|
|
||||||
|
|
||||||
.extern main
|
|
||||||
|
|
||||||
.align 4
|
|
||||||
_start:
|
|
||||||
la sp, _sstack # set up C stack
|
|
||||||
addi sp,sp,-16 # ...
|
|
||||||
sw ra,12(sp) # ...
|
|
||||||
jal ra, main # jump to C code!
|
|
Loading…
Reference in New Issue