Add ZLSH instruction
Some checks failed
Test / build (push) Failing after 6s

This commit is contained in:
shylie 2025-12-06 13:23:04 -05:00
parent d271bdc959
commit 7a49be864a
12 changed files with 81 additions and 133 deletions

View File

@ -39,7 +39,7 @@ IncludeCategories:
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseBlocks: true
InsertNewlineAtEOF: true
InsertNewlineAtEOF: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
.cache/
.idea/
build/
emulator/customasm/*.bin
cmake-build-*/

View File

@ -19,31 +19,33 @@
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
║ CONF ║ Configure processor ║ D = old config ║ CCCR ║ 0001 ║ 0DDd ║ dddd ║ 0000 ║ 0100 ║ 0AAa ║ aaaa ║ ║ 010 ║ A <= B ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
BWOR ║ Bitwise or ║ D = A | B ║ CCCR ║ 0010 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 011 ║ A = B ║
COPY ║ Copy data ║ D = A ║ CCCR ║ 0001 ║ 0DDd ║ dddd ║ 0000 ║ 0101 ║ 0AAa ║ aaaa ║ ║ 011 ║ A = B ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
║ BAND ║ Bitwise and ║ D = A & B ║ CCCR ║ 0011 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 100 ║ A >= B ║
║ BWOR ║ Bitwise or ║ D = A | B ║ CCCR ║ 0010 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 100 ║ A >= B ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
║ BXOR ║ Bitwise exclusive or ║ D = A ^ B ║ CCCR ║ 0100 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 101 ║ A > B ║
║ BAND ║ Bitwise and ║ D = A & B ║ CCCR ║ 0011 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 101 ║ A > B ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
ZRSH ║ Pad zero right shift ║ D = A >> B ║ CCCR ║ 0101 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 110 ║ A != B ║
BXOR ║ Bitwise exclusive or ║ D = A ^ B ║ CCCR ║ 0100 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 110 ║ A != B ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
SRSH ║ Signed right shift ║ D = A >> B ║ CCCR ║ 0110 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 111 ║ Reserved ║
ZRSH ║ Pad zero right shift ║ D = A >> B ║ CCCR ║ 0101 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 111 ║ Reserved ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╩═════════════════════════╣
ZLSH ║ Pad zero left shift ║ D = A << B ║ CCCR ║ 0111 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ SIMD bits ║
SRSH ║ Signed right shift ║ D = A >> B ║ CCCR ║ 0110 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ SIMD bits ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╦═════════════════════════╣
║ CLSH ║ Circular left shift ║ D = A << B ║ CCCR ║ 1000 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 00 ║ 1 32-bit number ║
║ ZLSH ║ Pad zero left shift ║ D = A << B ║ CCCR ║ 0111 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 00 ║ 1 32-bit number ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╦═════════════════════════╣
║ CLSH ║ Circular left shift ║ D = A << B ║ CCCR ║ 1000 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 01 ║ 2 16-bit numbers ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
║ ADDI ║ Addition ║ D = A + B ║ CCCR ║ 1001 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 01 ║ 2 16-bit numbers ║
║ ADDI ║ Addition ║ D = A + B ║ CCCR ║ 1001 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 10 ║ 4 8-bit numbers
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
║ SUBT ║ Subtraction ║ D = A - B ║ CCCR ║ 1010 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 10 ║ 4 8-bit numbers ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
║ MULT ║ Multiplication ║ D = A * B ║ CCCR ║ 1011 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 11 ║ 8 4-bit numbers ║
║ SUBT ║ Subtraction ║ D = A - B ║ CCCR ║ 1010 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 11 ║ 8 4-bit numbers ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╩═════════════════════════╣
DIVI ║ Division ║ D = A / B ║ CCCR ║ 1100 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ Processor configuration bits ║
║ MULT ║ Multiplication ║ D = A * B ║ CCCR ║ 1011 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ Processor configuration bits ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╦═════════════════════════╣
MODU ║ Modulus ║ D = A % B ║ CCCR ║ 1101 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 4-0 ║ Multiplication shift ║
DIVI ║ Division ║ D = A / B ║ CCCR ║ 1100 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 4-0 ║ Multiplication shift ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
║ RESERVED ║ ║ ║ ║ 1110 ║ ║ ║ ║ ║ ║ ║ ║ 31-4 ║ Reserved ║
║ MODU ║ Modulus ║ D = A % B ║ CCCR ║ 1101 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 31-4 ║ Reserved ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
║ RESERVED ║ ║ ║ ║ 1110 ║ ║ ║ ║ ║ ║ ║ ║ ║ ║
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
║ RESERVED ║ ║ ║ ║ 1111 ║ ║ ║ ║ ║ ║ ║ ║ ║ ║
╚══════════╩══════════════════════╩════════════════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╩══╩══════╩═════════════════════════╝

View File

@ -4,6 +4,7 @@ project(foot-emulator)
add_library(foot-emulator src/foot-emulator.cpp include/foot-emulator.h)
target_include_directories(foot-emulator PUBLIC include)
target_link_libraries(foot-emulator PUBLIC dwarf)
find_package(SDL3 REQUIRED CONFIG)

View File

@ -1,8 +0,0 @@
#include "foot.asm"
CNST. r1, #0xFFFF
loop:
CNST. [r1], #65
CNST. [r1], #66
CNST. r31, #loop

View File

@ -1,59 +0,0 @@
#once
#subruledef operand
{
#{immediate: i5} => 0b00 @ immediate
r{register: u5} => 0b01 @ register
[r{register: u5}] => 0b10 @ register
[r{register: u5}++] => 0b11 @ register
}
#subruledef crflags
{
. => 0b0000
.l => 0b0010
.le => 0b0100
.e => 0b0110
.ge => 0b1000
.g => 0b1010
.ne => 0b1100
.r => 0b0001
.rl => 0b0011
.rle => 0b0101
.re => 0b0111
.rge => 0b1001
.re => 0b1011
.rne => 0b1101
}
#ruledef
{
CNST{flags: crflags} {dst: operand}, #{imm: i16} => imm[7:0] @ imm[15:8] @ 0b0 @ dst @ flags @ 0b0000
CMPR{flags: crflags} {dst: operand}, {a: operand} => 0b0 @ a @ 0x00 @ 0b0 @ dst @ flags @ 0b0001
BWNG{flags: crflags} {dst: operand}, {a: operand} => 0b0 @ a @ 0x01 @ 0b0 @ dst @ flags @ 0b0001
ARNG{flags: crflags} {dst: operand}, {a: operand} => 0b0 @ a @ 0x02 @ 0b0 @ dst @ flags @ 0b0001
LONG{flags: crflags} {dst: operand}, {a: operand} => 0b0 @ a @ 0x03 @ 0b0 @ dst @ flags @ 0b0001
CONF{flags: crflags} {dst: operand}, {a: operand} => 0b0 @ a @ 0x04 @ 0b0 @ dst @ flags @ 0b0001
BWOR{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b0010
BAND{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b0011
BXOR{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b0100
SRSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b0110
ZLSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b0111
CLSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1000
ADDI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1001
ADDI{flags: crflags}v {dst: operand}, {a: operand}, {b: operand} => 0b1 @ a @ 0b0 @ b @ 0b1 @ dst @ flags @ 0b1001
SUBT{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1010
MULT{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1011
DIVI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1100
MODU{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1101
}
#bankdef mem
{
#bits 32
#addr 0
#size 0x10000
#outp 0
}
#bank mem

View File

@ -1,10 +0,0 @@
#include "foot.asm"
CNST. r30, #0x1000
loop:
CNST. r0, #0xEFFE
ADDI.r [r0++], [r0], r30
CNST. r0, #0xEFFE
ADDI.rv [r0++], [r0], r30
CNST. r31, #loop

View File

@ -33,13 +33,15 @@ public:
virtual uint16_t mapped_memory_size() const { return assigned_memory_size; }
protected:
Device(uint16_t size);
Device(uint16_t size, unsigned int update_frequency);
uint32_t& memory(uint16_t index);
private:
uint32_t* assigned_memory_base;
uint32_t assigned_memory_size;
unsigned int update_frequency;
};
class Emulator
@ -52,8 +54,11 @@ public:
Emulator();
Emulator(const Emulator&) = delete;
Emulator& operator=(const Emulator&) = delete;
void run(const std::vector<uint32_t>& program);
void run(std::istream& program);
void run(const std::string& filename);
void map_device(std::unique_ptr<Device>&& device);
@ -75,7 +80,7 @@ private:
uint32_t instruction;
uint32_t configuration;
uint32_t dummy_value;
std::vector<std::unique_ptr<Device>> devices;
std::vector<std::pair<std::unique_ptr<Device>, unsigned int>> devices;
uint32_t mapped_base;
bool keep_running;
@ -88,6 +93,7 @@ private:
void ARNG();
void LONG();
void CONF();
void COPY();
void BWOR();
void BAND();
void BXOR();

View File

@ -12,9 +12,10 @@ Operand::Operand(uint8_t bits) :
register_index(bits & 0b00011111)
{}
Device::Device(uint16_t size) :
Device::Device(uint16_t size, unsigned int update_frequency) :
assigned_memory_base(nullptr),
assigned_memory_size(size)
assigned_memory_size(size),
update_frequency(update_frequency)
{}
uint32_t& Device::memory(uint16_t index)
@ -42,25 +43,17 @@ void Emulator::run(const std::vector<uint32_t>& program)
run_internal();
}
void Emulator::run(std::istream& program)
void Emulator::run(const std::string& filename)
{
ELFIO::elfio reader;
reader.load(program);
for (const auto& seg : reader.segments)
if (!reader.load(filename)) { return; }
for (const auto& segment : reader.segments)
{
if (segment->get_type() != ELFIO::PT_LOAD) { continue; }
uint64_t dest = seg->get_virtual_address();
uint64_t msize = seg->get_memory_size();
uint64_t fsize = seg->get_file_size();
const char* data = seg->get_data();
if (seg->get_type() != ELFIO::PT_LOAD)
{
continue;
}
memcpy(reinterpret_cast<char*>(memory.data()) + dest, data, fsize);
memcpy(reinterpret_cast<char*>(memory.data()) + segment->get_virtual_address(), segment->get_data(), segment->get_file_size());
}
registers[PC] = reader.get_entry() / 4;
@ -72,7 +65,7 @@ void Emulator::map_device(std::unique_ptr<Device>&& device)
{
device->assigned_memory_base = &memory[mapped_base];
mapped_base += device->mapped_memory_size();
devices.push_back(std::move(device));
devices.emplace_back(std::move(device), 0);
}
uint32_t& Emulator::memory_at(uint32_t address)
@ -151,6 +144,10 @@ void Emulator::run_instruction()
case 4:
CONF();
break;
case 5:
COPY();
break;
}
break;
@ -216,13 +213,21 @@ void Emulator::run_internal()
while (keep_running)
{
run_instruction();
for (const auto& device : devices)
for (auto& [device, current_interval] : devices)
{
if (current_interval == device->update_frequency)
{
current_interval = 0;
if (device->update())
{
keep_running = false;
}
}
else
{
current_interval += 1;
}
}
}
}
@ -288,6 +293,14 @@ void Emulator::CONF()
configuration = a;
}
void Emulator::COPY()
{
uint32_t a = decode_operand(instruction & 0x000000FF);
uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16);
d = a;
}
void Emulator::BWOR()
{
uint32_t a = decode_operand(instruction & 0x000000FF);

View File

@ -12,7 +12,7 @@ class PrintDevice : public foot::Device
{
public:
PrintDevice() :
Device(1)
Device(1, 1)
{
}
@ -21,7 +21,8 @@ public:
uint32_t& value = memory(0);
if (value != 0)
{
SDL_Log("%1s", (char*)&value);
fprintf(stdout, "%d\n", value);
fflush(stdout);
value = 0;
}
@ -33,7 +34,7 @@ class MemoryViewDevice : public foot::Device
{
public:
MemoryViewDevice(SDL_Renderer* render, uint8_t width, uint8_t height) :
Device(width * height),
Device(width * height, 100000),
render(render),
texture(SDL_CreateTexture(render, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, width, height)),
width(width),
@ -54,12 +55,11 @@ public:
{
std::cout << SDL_GetError() << std::endl;
}
int idx = 0;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
pixels[i + j * width] = memory(i + j * width);
pixels[i + j * width] = memory(i + j * width) | 0xFF000000;
}
}
SDL_UnlockTexture(texture);
@ -96,14 +96,6 @@ int main(int argc, char** argv)
constexpr int WIDTH = 64;
constexpr int HEIGHT = 64;
std::ifstream file(argv[1], std::ios::binary);
if (!file.is_open())
{
std::cerr << "Failed to open file: " << argv[1] << std::endl;
return 1;
}
SDL_Window* window;
SDL_Renderer* render;
@ -114,7 +106,7 @@ int main(int argc, char** argv)
emu.map_device(std::make_unique<PrintDevice>());
emu.map_device(std::make_unique<MemoryViewDevice>(render, WIDTH, HEIGHT));
emu.run(file);
emu.run(argv[1]);
SDL_DestroyRenderer(render);
SDL_DestroyWindow(window);

11
foot.script Normal file
View File

@ -0,0 +1,11 @@
MEMORY
{
default (RWX) : ORIGIN = 0x0, LENGTH = 256K
}
ENTRY(entry);
SECTIONS
{
. = 0x0;
}