Add some tests for SIMD instruction variants
All checks were successful
Test / build (push) Successful in 11s

This commit is contained in:
shylie 2025-08-19 08:03:58 -04:00
parent 80d83f2062
commit e647b9e146
11 changed files with 113 additions and 61 deletions

View File

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

View File

@ -2,12 +2,10 @@
#subruledef operand
{
#{immediate: i5} => 0b000 @ immediate
r{register: u5} => 0b001 @ register
[r{register: u5}++] => 0b010 @ register
[r{register: u5}--] => 0b011 @ register
[r{register: u5}] => 0b100 @ register
[r{register: u5} + {offset: u2}] => 0b1 @ offset @ register
#{immediate: i5} => 0b00 @ immediate
r{register: u5} => 0b01 @ register
[r{register: u5}] => 0b10 @ register
[r{register: u5}++] => 0b11 @ register
}
#subruledef crflags
@ -30,28 +28,29 @@
#ruledef
{
CNST{flags: crflags} {dst: operand}, #{imm: i16} => imm @ flags @ 0b0000 @ dst
CMPR{flags: crflags} {dst: operand}, {a: operand} => 0x00 @ a @ flags @ 0b0001 @ dst
BWNG{flags: crflags} {dst: operand}, {a: operand} => 0x01 @ a @ flags @ 0b0001 @ dst
ARNG{flags: crflags} {dst: operand}, {a: operand} => 0x02 @ a @ flags @ 0b0001 @ dst
LONG{flags: crflags} {dst: operand}, {a: operand} => 0x03 @ a @ flags @ 0b0001 @ dst
BWOR{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0010 @ dst
BAND{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0011 @ dst
BXOR{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0100 @ dst
URSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0101 @ dst
SRSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0110 @ dst
ZLSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0111 @ dst
CLSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1000 @ dst
ADDI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1001 @ dst
SUBT{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1010 @ dst
MULT{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1011 @ dst
DIVI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1110 @ dst
MODU{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1111 @ dst
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 16
#bits 32
#addr 0
#size 0x10000
#outp 0

View File

@ -4,5 +4,7 @@ CNST. r30, #0x1000
loop:
CNST. r0, #0xEFFE
CNST.r [r0++], #29
ADDI.r [r0++], [r0], r30
CNST. r0, #0xEFFE
ADDI.rv [r0++], [r0], r30
CNST. r31, #loop

View File

@ -17,8 +17,8 @@ struct Operand
{
Immediate = 0,
Direct,
IndirectAutoIncrement,
Indirect
Indirect,
IndirectAutoIncrement
} addressing_mode;
uint8_t register_index;
};

View File

@ -369,8 +369,9 @@ uint32_t Emulator::apply_many_unary(uint32_t a, uint32_t (Emulator::*fn)(uint32_
for (int i = 0; i < simd_elements(); i++)
{
uint32_t simd_element_a = (a >> (i * 32 / simd_elements())) & ((uint64_t(1) << (32 / simd_elements())) - 1);
uint32_t simd_result = (this->*fn)(simd_element_a) << (i * 32 / simd_elements());
uint32_t simd_width_mask = ((uint64_t(1) << (32 / simd_elements())) - 1);
uint32_t simd_element_a = (a >> (i * 32 / simd_elements())) & simd_width_mask;
uint32_t simd_result = ((this->*fn)(simd_element_a) & simd_width_mask) << (i * 32 / simd_elements());
result |= simd_result;
}
@ -383,9 +384,10 @@ uint32_t Emulator::apply_many_binary(uint32_t a, uint32_t b, uint32_t (Emulator:
for (int i = 0; i < simd_elements(); i++)
{
uint32_t simd_element_a = (a >> (i * 32 / simd_elements())) & ((uint64_t(1) << (32 / simd_elements())) - 1);
uint32_t simd_element_b = (b >> (i * 32 / simd_elements())) & ((uint64_t(1) << (32 / simd_elements())) - 1);
uint32_t simd_result = (this->*fn)(simd_element_a, simd_element_b) << (i * 32 / simd_elements());
uint32_t simd_width_mask = ((uint64_t(1) << (32 / simd_elements())) - 1);
uint32_t simd_element_a = (a >> (i * 32 / simd_elements())) & simd_width_mask;
uint32_t simd_element_b = (b >> (i * 32 / simd_elements())) & simd_width_mask;
uint32_t simd_result = ((this->*fn)(simd_element_a, simd_element_b) & simd_width_mask) << (i * 32 / simd_elements());
result |= simd_result;
}

View File

@ -15,14 +15,14 @@ std::vector<uint32_t> read_file(std::istream& stream)
std::streampos pos = stream.tellg();
stream.seekg(0, std::ios::end);
pos = stream.tellg() - pos;
buf.resize(pos / 2);
buf.resize(pos / 4);
stream.seekg(0, std::ios::beg);
for (int i = 0; i < buf.size(); i++)
{
char value[4] = {};
stream.read(value, 4);
buf[i] = uint32_t(value[0]) | uint32_t(value[1]) << 8 | uint32_t(value[2]) << 16 | uint32_t(value[3]) << 24;
unsigned char value[4] = {};
stream.read((char*)value, 4);
buf[i] = uint32_t(value[0]) | (uint32_t(value[1]) << 8) | (uint32_t(value[2]) << 16) | (uint32_t(value[3]) << 24);
}
return buf;
@ -53,12 +53,14 @@ class MemoryViewDevice : public foot::Device
{
public:
MemoryViewDevice(SDL_Renderer* render, uint8_t width, uint8_t height) :
Device(width * height / 2),
Device(width * height),
render(render),
texture(SDL_CreateTexture(render, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, width, height)),
texture(SDL_CreateTexture(render, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, width, height)),
width(width),
height(height)
{}
{
SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
}
~MemoryViewDevice()
{
SDL_DestroyTexture(texture);
@ -67,34 +69,22 @@ public:
bool update() override
{
int pitch;
uint8_t* pixels;
uint32_t* pixels;
if (!SDL_LockTexture(texture, nullptr, (void**)&pixels, &pitch))
{
std::cout << SDL_GetError() << std::endl;
}
int idx = 0;
for (int i = 0; i < width / 2; i++)
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
//TODO: fix
const uint16_t mem = memory(i + j * width / 2);
const uint8_t left = mem & 0xFF;
const uint8_t right = mem >> 8;
pixels[idx + 0] = left;
pixels[idx + 1] = left;
pixels[idx + 2] = left;
pixels[idx + 3] = right;
pixels[idx + 4] = right;
pixels[idx + 5] = right;
idx += 6;
pixels[i + j * width] = memory(i + j * width);
}
}
SDL_UnlockTexture(texture);
SDL_RenderTexture(render, texture, nullptr, nullptr);
SDL_RenderPresent(render);
SDL_Event event;
@ -121,7 +111,6 @@ private:
int main(int argc, char** argv)
{
if (argc > 1)
{
constexpr int WIDTH = 64;
@ -139,7 +128,7 @@ int main(int argc, char** argv)
SDL_Renderer* render;
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer("foot emulator", WIDTH * 4, HEIGHT * 4, 0, &window, &render);
SDL_CreateWindowAndRenderer("foot emulator", WIDTH * 8, HEIGHT * 8, 0, &window, &render);
foot::Emulator emu;
emu.map_device(std::make_unique<PrintDevice>());

View File

@ -14,5 +14,17 @@ int main(int argc, char** argv)
if (!check(0xFFFFBA99, emu.register_at(0))) { return 1; }
}
// CNST
// dst - 0, Direct
// imm - 0x4567
//
// ARNG 4-bit SIMD
// dst - 0, Direct
// a - 0, Direct
{
foot::Emulator emu = run_instructions({ 0x00204567, 0x01A002A0 });
if (!check(0x0000CBA9, emu.register_at(0))) { return 1; }
}
return 0;
}

View File

@ -31,7 +31,7 @@ int main(int argc, char** argv)
// imm = 0x1234
{
bool failed = false;
foot::Emulator emu = run_instructions({ 0x003E0010, 0x10501234 });
foot::Emulator emu = run_instructions({ 0x003E0010, 0x10601234 });
for (int i = 0; i < 0x10; i++)
{
if (!check(0x1234, emu.memory_at(i))) { failed = true; }

View File

@ -22,5 +22,18 @@ int main(int argc, char** argv)
if (!check(0x00000001, emu.register_at(0))) { return 1; }
}
// CNST
// dst - 0, Direct
// imm - 0x0230
//
// LONG 4-bit SIMD
// dst - 0, Direct
// a - 0, Direct
{
foot::Emulator emu = run_instructions({ 0x00200230, 0x01A003A0 });
if (!check(0x11111001, emu.register_at(0))) { return 1; }
}
return 0;
}

View File

@ -27,5 +27,22 @@ int main(int argc, char** argv)
if (!check((-2) >> 2, emu.register_at(0))) { return 1; }
}
// CNST
// dst - 0, Direct
// imm - 0x8686
//
// CNST
// dst - 1, Direct
// imm - 0x1122
//
// SRSH - 4-bit SIMD
// dst - 0, Direct
// a - 0, Direct
// b - 1, Direct
{
foot::Emulator emu = run_instructions({ 0x00208686, 0x00211122, 0x06A021A0 });
if (!check(0x4321, emu.register_at(0))) { return 1; }
}
return 0;
}

View File

@ -15,5 +15,23 @@ int main(int argc, char** argv)
if (!check(0x0001159C, emu.register_at(0))) { return 1; }
}
// CNST
// dst - 0, Direct
// imm - 0x4343
//
// CNST
// dst - 1, Direct
// imm - 0x1122
//
// ZLSH - 4-bit SIMD
// dst - 0, Direct
// a - 0, Direct
// b - 1, Direct
{
foot::Emulator emu = run_instructions({ 0x00204343, 0x00211122, 0x07A021A0 });
if (!check(0x860C, emu.register_at(0))) { return 1; }
}
return 0;
}