functions
This commit is contained in:
parent
eab5a313ab
commit
8cb0ac6070
@ -61,91 +61,98 @@ key_press_int:
|
||||
cmp r1, 44 ; spacebar
|
||||
mov r2, rfl
|
||||
and r2, fl_eq
|
||||
; jnz r2, .incr
|
||||
; add r1, 61
|
||||
; mov byte [r0], r1
|
||||
;.incr:
|
||||
; mov r0, [counter]
|
||||
; add r0, 1
|
||||
; mov [counter], r0
|
||||
|
||||
jnz r2, .print_space
|
||||
add r1, 61 ; scancode letter -> ascii
|
||||
mov [rsp], r0
|
||||
|
||||
mov [rsp], r1
|
||||
add rsp, 2
|
||||
call print_char
|
||||
;call print_char
|
||||
call print_u16
|
||||
sub rsp, 2
|
||||
|
||||
jmp .leave
|
||||
.print_space:
|
||||
mov r0, ' '
|
||||
mov [rsp], r0
|
||||
mov r1, ' '
|
||||
|
||||
mov [rsp], r1
|
||||
add rsp, 2
|
||||
call print_char
|
||||
sub rsp, 2
|
||||
|
||||
.leave:
|
||||
reti
|
||||
|
||||
print_char:
|
||||
mov [rsp], rbp
|
||||
mov rbp, rsp
|
||||
add rsp, 2
|
||||
mov rbp, rsp
|
||||
|
||||
mov r1, [rbp-6]
|
||||
|
||||
mov r0, [counter]
|
||||
add r0, vcd_base
|
||||
mov r1, [kbd_code]
|
||||
cmp r1, ' '
|
||||
mov r2, rfl
|
||||
and r2, fl_eq
|
||||
jnz r2, .incr
|
||||
add r1, 61
|
||||
mov byte [r0], r1
|
||||
.incr:
|
||||
mov r0, [counter]
|
||||
add r0, 1
|
||||
mov [counter], r0
|
||||
.leave:
|
||||
mov rsp, rbp
|
||||
sub rsp, 2
|
||||
mov rbp, [rsp]
|
||||
ret
|
||||
|
||||
;print_int:
|
||||
; mov [rsp], rbp
|
||||
; add rsp, 2
|
||||
; mov rbp, rsp
|
||||
; add rsp, rsp, 2
|
||||
;
|
||||
; mov r1, [rbp-2]
|
||||
;
|
||||
; mov r2, 10000
|
||||
; mov r3, 0
|
||||
; jmp .c_10000
|
||||
;.b_10000:
|
||||
; add r3, 1
|
||||
; sub r1, r2
|
||||
;.c_10000:
|
||||
; cmp r2, r1
|
||||
; mov r0, rfl
|
||||
; and r0, fl_eq | fl_lt
|
||||
; jnz r0, .b_10000
|
||||
; add r3, 48
|
||||
print_u16:
|
||||
mov [rsp], rbp
|
||||
add rsp, 2
|
||||
mov rbp, rsp
|
||||
|
||||
mov r1, [rbp-6] ; value to print
|
||||
mov r4, 0 ; place index
|
||||
|
||||
;scancode_to_char:
|
||||
; cmp r1, 61
|
||||
;
|
||||
; mov r2, rfl
|
||||
; and r2, r2, FL_LT
|
||||
; jnz .not_letter
|
||||
;
|
||||
; ; if r1 > 86 { goto .not_letter }
|
||||
; cmp r1, 86
|
||||
; mov r2, rfl
|
||||
; xor r2, 0xffff
|
||||
; and r2, r2, FL_EQ | FL_LT
|
||||
;
|
||||
;
|
||||
; mov r4, rfl
|
||||
; and r4, r4, FL_EQ
|
||||
; shr r4, r4, 2
|
||||
jmp .digits_cond
|
||||
.digits_body:
|
||||
mov r2, .places
|
||||
add r2, r4
|
||||
mov r2, [r2] ; place
|
||||
|
||||
mov r3, 0 ; place occurences
|
||||
jmp .place_cond
|
||||
.place_body:
|
||||
add r3, 1
|
||||
sub r1, r2
|
||||
.place_cond:
|
||||
cmp r2, r1
|
||||
mov r0, rfl
|
||||
and r0, fl_eq | fl_lt
|
||||
jnz r0, .place_body
|
||||
|
||||
mov r0, r3
|
||||
add r0, 48
|
||||
mov [rsp], r0
|
||||
add rsp, 2
|
||||
call print_char
|
||||
sub rsp, 2
|
||||
|
||||
add r4, 2
|
||||
.digits_cond:
|
||||
cmp r4, 10
|
||||
mov r0, rfl
|
||||
and r0, fl_lt
|
||||
jnz r0, .digits_body
|
||||
|
||||
.leave:
|
||||
mov rsp, rbp
|
||||
sub rsp, 2
|
||||
mov rbp, [rsp]
|
||||
ret
|
||||
|
||||
.places:
|
||||
dw 10000, 1000, 100, 10, 1
|
||||
|
||||
|
||||
|
||||
|
||||
@ -406,24 +406,24 @@ void Assembler::assemble_line(const Line& line)
|
||||
l.mov_imm(dst->as_reg(), src->as_imm());
|
||||
} else if (dst_ty == Reg and src_ty == MemWordReg) {
|
||||
auto [reg, offset] = src->as_reg_imm_pair();
|
||||
l.load_word_reg(dst->as_reg(), reg, offset);
|
||||
l.ldw_reg(dst->as_reg(), reg, offset);
|
||||
} else if (dst_ty == Reg and src_ty == MemWordImm) {
|
||||
l.load_word_imm(dst->as_reg(), src->as_imm());
|
||||
l.ldw_imm(dst->as_reg(), src->as_imm());
|
||||
} else if (dst_ty == MemWordReg and src_ty == Reg) {
|
||||
auto [reg, offset] = dst->as_reg_imm_pair();
|
||||
l.store_word_reg(reg, offset, src->as_reg());
|
||||
l.stw_reg(reg, offset, src->as_reg());
|
||||
} else if (dst_ty == MemWordImm and src_ty == Reg) {
|
||||
l.store_word_imm(dst->as_imm(), src->as_reg());
|
||||
l.stw_imm(dst->as_imm(), src->as_reg());
|
||||
} else if (dst_ty == Reg and src_ty == MemByteReg) {
|
||||
auto [reg, offset] = src->as_reg_imm_pair();
|
||||
l.load_byte_reg(dst->as_reg(), reg, offset);
|
||||
l.ldb_reg(dst->as_reg(), reg, offset);
|
||||
} else if (dst_ty == Reg and src_ty == MemByteImm) {
|
||||
l.load_byte_imm(dst->as_reg(), src->as_imm());
|
||||
l.ldb_imm(dst->as_reg(), src->as_imm());
|
||||
} else if (dst_ty == MemByteReg and src_ty == Reg) {
|
||||
auto [reg, offset] = dst->as_reg_imm_pair();
|
||||
l.store_byte_reg(reg, offset, src->as_reg());
|
||||
l.stb_reg(reg, offset, src->as_reg());
|
||||
} else if (dst_ty == MemByteImm and src_ty == Reg) {
|
||||
l.store_byte_imm(dst->as_imm(), src->as_reg());
|
||||
l.stb_imm(dst->as_imm(), src->as_reg());
|
||||
} else {
|
||||
operation_not_supported();
|
||||
}
|
||||
@ -912,8 +912,6 @@ bool Assembler::arg_count_wrong(const Line& ins, size_t count)
|
||||
auto Assembler::define_sym(std::string ident, uint16_t value)
|
||||
-> std::expected<void, std::string>
|
||||
{
|
||||
std::println("define_sym(\"{}\", {})", ident, value);
|
||||
|
||||
if (m_syms.contains(ident)) {
|
||||
return std::unexpected(
|
||||
std::format("symbol \"{}\" already defined", ident));
|
||||
@ -926,8 +924,6 @@ auto Assembler::define_sym(std::string ident, uint16_t value)
|
||||
auto Assembler::get_sym(const std::string& ident)
|
||||
-> std::expected<uint16_t, std::string>
|
||||
{
|
||||
std::println(" get_sym(\"{}\")", ident);
|
||||
|
||||
if (not m_syms.contains(ident)) {
|
||||
return std::unexpected(std::format("symbol \"{}\" not defined", ident));
|
||||
}
|
||||
|
||||
@ -141,77 +141,77 @@ void Builder::mov_imm(Reg dst, uint16_t imm)
|
||||
i.build(*this);
|
||||
}
|
||||
|
||||
void Builder::load_word_reg(Reg dst, Reg addr, uint16_t offset)
|
||||
void Builder::ldw_reg(Reg dst, Reg addr, uint16_t offset)
|
||||
{
|
||||
LOG;
|
||||
auto i = InsBuilder(Op::LoadWord);
|
||||
auto i = InsBuilder(Op::LdW);
|
||||
i.dst_reg(dst);
|
||||
i.op1_reg(addr);
|
||||
i.imm_without_flag(offset);
|
||||
i.build(*this);
|
||||
}
|
||||
|
||||
void Builder::load_word_imm(Reg dst, uint16_t addr)
|
||||
void Builder::ldw_imm(Reg dst, uint16_t addr)
|
||||
{
|
||||
LOG;
|
||||
auto i = InsBuilder(Op::LoadWord);
|
||||
auto i = InsBuilder(Op::LdW);
|
||||
i.dst_reg(dst);
|
||||
i.imm(addr);
|
||||
i.build(*this);
|
||||
}
|
||||
|
||||
void Builder::store_word_reg(Reg dst, uint16_t offset, Reg op2)
|
||||
void Builder::stw_reg(Reg dst, uint16_t offset, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
auto i = InsBuilder(Op::StoreWord);
|
||||
auto i = InsBuilder(Op::StW);
|
||||
i.dst_reg(dst);
|
||||
i.imm_without_flag(offset);
|
||||
i.op2_reg(op2);
|
||||
i.build(*this);
|
||||
}
|
||||
|
||||
void Builder::store_word_imm(uint16_t dst, Reg op2)
|
||||
void Builder::stw_imm(uint16_t dst, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
auto i = InsBuilder(Op::StoreWord);
|
||||
auto i = InsBuilder(Op::StW);
|
||||
i.imm(dst);
|
||||
i.op2_reg(op2);
|
||||
i.build(*this);
|
||||
}
|
||||
|
||||
void Builder::load_byte_reg(Reg dst, Reg addr, uint16_t offset)
|
||||
void Builder::ldb_reg(Reg dst, Reg addr, uint16_t offset)
|
||||
{
|
||||
LOG;
|
||||
auto i = InsBuilder(Op::LoadByte);
|
||||
auto i = InsBuilder(Op::LdB);
|
||||
i.dst_reg(dst);
|
||||
i.op1_reg(addr);
|
||||
i.imm_without_flag(offset);
|
||||
i.build(*this);
|
||||
}
|
||||
|
||||
void Builder::load_byte_imm(Reg dst, uint16_t addr)
|
||||
void Builder::ldb_imm(Reg dst, uint16_t addr)
|
||||
{
|
||||
LOG;
|
||||
auto i = InsBuilder(Op::LoadByte);
|
||||
auto i = InsBuilder(Op::LdB);
|
||||
i.dst_reg(dst);
|
||||
i.imm(addr);
|
||||
i.build(*this);
|
||||
}
|
||||
|
||||
void Builder::store_byte_reg(Reg dst, uint16_t offset, Reg op2)
|
||||
void Builder::stb_reg(Reg dst, uint16_t offset, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
auto i = InsBuilder(Op::StoreByte);
|
||||
auto i = InsBuilder(Op::StB);
|
||||
i.dst_reg(dst);
|
||||
i.imm_without_flag(offset);
|
||||
i.op2_reg(op2);
|
||||
i.build(*this);
|
||||
}
|
||||
|
||||
void Builder::store_byte_imm(uint16_t dst, Reg op2)
|
||||
void Builder::stb_imm(uint16_t dst, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
auto i = InsBuilder(Op::StoreByte);
|
||||
auto i = InsBuilder(Op::StB);
|
||||
i.imm(dst);
|
||||
i.op2_reg(op2);
|
||||
i.build(*this);
|
||||
|
||||
@ -23,14 +23,14 @@ public:
|
||||
void jnz_imm(Reg op1, uint16_t op2);
|
||||
void mov_reg(Reg dst, Reg src);
|
||||
void mov_imm(Reg dst, uint16_t imm);
|
||||
void load_word_reg(Reg dst, Reg addr, uint16_t offset);
|
||||
void load_word_imm(Reg dst, uint16_t addr);
|
||||
void store_word_reg(Reg dst, uint16_t offset, Reg op2);
|
||||
void store_word_imm(uint16_t dst, Reg op2);
|
||||
void load_byte_reg(Reg dst, Reg addr, uint16_t offset);
|
||||
void load_byte_imm(Reg dst, uint16_t addr);
|
||||
void store_byte_reg(Reg dst, uint16_t offset, Reg op2);
|
||||
void store_byte_imm(uint16_t dst, Reg op2);
|
||||
void ldw_reg(Reg dst, Reg addr, uint16_t offset);
|
||||
void ldw_imm(Reg dst, uint16_t addr);
|
||||
void stw_reg(Reg dst, uint16_t offset, Reg op2);
|
||||
void stw_imm(uint16_t dst, Reg op2);
|
||||
void ldb_reg(Reg dst, Reg addr, uint16_t offset);
|
||||
void ldb_imm(Reg dst, uint16_t addr);
|
||||
void stb_reg(Reg dst, uint16_t offset, Reg op2);
|
||||
void stb_imm(uint16_t dst, Reg op2);
|
||||
void cmp_reg(Reg op1, Reg op2);
|
||||
void cmp_imm(Reg op1, uint16_t op2);
|
||||
void or_reg(Reg dst, Reg op1, Reg op2);
|
||||
|
||||
@ -26,6 +26,11 @@ constexpr uint64_t char_data(uint8_t ch)
|
||||
case '2': return 0x003C66060C18307E;
|
||||
case '3': return 0x003C66060C06663C;
|
||||
case '4': return 0x000C1C3C6C7E0C0C;
|
||||
case '5': return 0x007E607C0606663C;
|
||||
case '6': return 0x003C66607C66663C;
|
||||
case '7': return 0x007F63060C181818;
|
||||
case '8': return 0x003C66663C66663C;
|
||||
case '9': return 0x003C66663E06663C;
|
||||
|
||||
case 'A': return 0x00187E66667E6666;
|
||||
case 'B': return 0x00787E667C667E7C;
|
||||
@ -173,7 +178,7 @@ auto IoDevice::poll_event() -> std::unique_ptr<IoEvent>
|
||||
std::lock_guard lock(mx);
|
||||
|
||||
SDL_Event event;
|
||||
if (SDL_PollEvent(&event)) {
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
return std::make_unique<IoEvent>(
|
||||
|
||||
61
src/vm.cpp
61
src/vm.cpp
@ -273,13 +273,13 @@ struct InsReader {
|
||||
int VM::run_instruction()
|
||||
{
|
||||
auto ip = *m_rip;
|
||||
if (ip > 0x400)
|
||||
if (ip >= 0x400)
|
||||
return -1;
|
||||
|
||||
auto ins = InsReader(*this);
|
||||
auto op = static_cast<Op>(ins.to_u16() & 0b11'1111);
|
||||
std::println(
|
||||
" [{: 2x}]: 0x{:04x} {: <9} {:04b} {:04b} {:04b} {:04b} {:04x}",
|
||||
" [{: >2x}]: 0x{:04x} {: <6} {:04b} {:04b} {:04b} {:04b} {:04x}",
|
||||
ip,
|
||||
ins.to_u16(),
|
||||
op_str(op),
|
||||
@ -293,10 +293,36 @@ int VM::run_instruction()
|
||||
case Op::Nop:
|
||||
break;
|
||||
case Op::Hlt:
|
||||
if (not m_interrupts_enabled) {
|
||||
std::println("warning: halted without interrupts enabled");
|
||||
}
|
||||
m_halted = true;
|
||||
break;
|
||||
case Op::Jmp: {
|
||||
auto op1 = ins.op1_or_imm();
|
||||
|
||||
if (op1 == 1) {
|
||||
for (uint16_t reg = 0; reg < 10; ++reg) {
|
||||
constexpr auto reg_strs = std::array {
|
||||
"r0"sv,
|
||||
"r1"sv,
|
||||
"r2"sv,
|
||||
"r3"sv,
|
||||
"r4"sv,
|
||||
"r5"sv,
|
||||
"rbp"sv,
|
||||
"rsp"sv,
|
||||
"rfl"sv,
|
||||
"rip"sv,
|
||||
};
|
||||
std::println(" {: <3} | {:04x} {: 5}",
|
||||
reg_strs[reg],
|
||||
this->reg(static_cast<Reg>(reg)),
|
||||
this->reg(static_cast<Reg>(reg)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
*m_rip = op1;
|
||||
break;
|
||||
}
|
||||
@ -315,7 +341,7 @@ int VM::run_instruction()
|
||||
set_reg(dst, src);
|
||||
break;
|
||||
}
|
||||
case Op::LoadWord: {
|
||||
case Op::LdW: {
|
||||
auto addr = ins.mem_addr(ins.op1(), eat_word());
|
||||
|
||||
if ((addr & 0b1) != 0) {
|
||||
@ -331,7 +357,7 @@ int VM::run_instruction()
|
||||
set_reg(reg, word(addr));
|
||||
break;
|
||||
}
|
||||
case Op::StoreWord: {
|
||||
case Op::StW: {
|
||||
auto addr = ins.mem_addr(ins.dst(), eat_word());
|
||||
|
||||
if ((addr & 0b1) != 0) {
|
||||
@ -353,14 +379,14 @@ int VM::run_instruction()
|
||||
|
||||
break;
|
||||
}
|
||||
case Op::LoadByte: {
|
||||
case Op::LdB: {
|
||||
auto addr = ins.mem_addr(ins.op1(), eat_word());
|
||||
auto reg = ins.dst_reg();
|
||||
|
||||
set_reg(reg, byte(addr));
|
||||
break;
|
||||
}
|
||||
case Op::StoreByte: {
|
||||
case Op::StB: {
|
||||
auto addr = ins.mem_addr(ins.dst(), eat_word());
|
||||
auto src = ins.op2();
|
||||
|
||||
@ -448,9 +474,9 @@ int VM::run_instruction()
|
||||
case Op::Call: {
|
||||
auto op1 = ins.op1_or_imm();
|
||||
|
||||
auto return_addr = word(*m_rip);
|
||||
auto return_addr = *m_rip;
|
||||
set_word(*m_rsp, return_addr);
|
||||
*m_rsp -= 2;
|
||||
*m_rsp += 2;
|
||||
|
||||
*m_rip = op1;
|
||||
break;
|
||||
@ -464,7 +490,6 @@ int VM::run_instruction()
|
||||
case Op::RetI: {
|
||||
*m_rsp -= 2;
|
||||
auto return_addr = word(*m_rsp);
|
||||
|
||||
*m_rip = return_addr;
|
||||
|
||||
m_interrupts_enabled = true;
|
||||
@ -579,7 +604,7 @@ void VM::interrupt(uint16_t handler_addr)
|
||||
m_interrupts_enabled = false;
|
||||
}
|
||||
|
||||
const char* vc5::op_str(Op op)
|
||||
auto vc5::op_str(Op op) -> std::string_view
|
||||
{
|
||||
switch (op) {
|
||||
case Op::Nop:
|
||||
@ -592,14 +617,14 @@ const char* vc5::op_str(Op op)
|
||||
return "Jnz";
|
||||
case Op::Mov:
|
||||
return "Mov";
|
||||
case Op::LoadWord:
|
||||
return "LoadWord";
|
||||
case Op::StoreWord:
|
||||
return "StoreWord";
|
||||
case Op::LoadByte:
|
||||
return "LoadByte";
|
||||
case Op::StoreByte:
|
||||
return "StoreByte";
|
||||
case Op::LdW:
|
||||
return "LdW";
|
||||
case Op::StW:
|
||||
return "StW";
|
||||
case Op::LdB:
|
||||
return "LdB";
|
||||
case Op::StB:
|
||||
return "StB";
|
||||
case Op::Cmp:
|
||||
return "Cmp";
|
||||
case Op::Or:
|
||||
|
||||
11
src/vm.hpp
11
src/vm.hpp
@ -7,6 +7,7 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <span>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
namespace vc5 {
|
||||
@ -17,10 +18,10 @@ enum class Op : uint16_t {
|
||||
Jmp,
|
||||
Jnz,
|
||||
Mov,
|
||||
LoadWord,
|
||||
StoreWord,
|
||||
LoadByte,
|
||||
StoreByte,
|
||||
LdW,
|
||||
StW,
|
||||
LdB,
|
||||
StB,
|
||||
Cmp,
|
||||
Or,
|
||||
And,
|
||||
@ -49,7 +50,7 @@ enum class Op : uint16_t {
|
||||
DSKW,
|
||||
};
|
||||
|
||||
const char* op_str(Op op);
|
||||
auto op_str(Op op) -> std::string_view;
|
||||
|
||||
enum class Reg : uint16_t {
|
||||
R0 = 0,
|
||||
|
||||
105
src/vm_main.cpp
105
src/vm_main.cpp
@ -4,6 +4,7 @@
|
||||
#include "vm.hpp"
|
||||
#include <SDL2/SDL_main.h>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <print>
|
||||
#include <string>
|
||||
|
||||
@ -11,118 +12,20 @@ using namespace std::chrono_literals;
|
||||
|
||||
using namespace vc5;
|
||||
|
||||
static void make_program(uint8_t* data);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
auto device = IoDevice::create().value();
|
||||
device->set_title("vc5");
|
||||
|
||||
if (argc < 2) {
|
||||
auto disk = MemoryDisk(128);
|
||||
|
||||
make_program(disk.data());
|
||||
|
||||
std::println("memory disk");
|
||||
for (size_t i = 0; i < 128; i += 4) {
|
||||
std::println("{:02x} {:02x} {:02x} {:02x}",
|
||||
disk.data()[i],
|
||||
disk.data()[i + 1],
|
||||
disk.data()[i + 2],
|
||||
disk.data()[i + 3]);
|
||||
if (argc > 2) {
|
||||
std::println("error: no boot disk (file name) specified");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
auto vm = VM(*device, disk);
|
||||
vm.run();
|
||||
} else {
|
||||
auto disk = FileDisk(argv[1]);
|
||||
|
||||
auto memory_disk = MemoryDisk(128);
|
||||
make_program(memory_disk.data());
|
||||
|
||||
auto file_block = std::vector<uint8_t>(BlockDevice::block_size);
|
||||
disk.read(file_block.data(), 0);
|
||||
|
||||
auto memory_block = std::vector<uint8_t>(BlockDevice::block_size);
|
||||
memory_disk.read(memory_block.data(), 0);
|
||||
|
||||
std::println("file disk");
|
||||
for (size_t i = 0; i < 128; i += 4) {
|
||||
std::println("{:02x} {:02x} {:02x} {:02x}",
|
||||
file_block[i],
|
||||
file_block[i + 1],
|
||||
file_block[i + 2],
|
||||
file_block[i + 3]);
|
||||
}
|
||||
|
||||
auto vm = VM(*device, disk);
|
||||
vm.run();
|
||||
}
|
||||
}
|
||||
|
||||
void make_program(uint8_t* data)
|
||||
{
|
||||
using namespace vc5::regs;
|
||||
|
||||
auto l = tools::Builder(data);
|
||||
|
||||
l.mov_imm(rsp, 0x1000);
|
||||
l.mov_reg(rbp, rsp);
|
||||
|
||||
l.mov_imm(r0, 512);
|
||||
l.mov_imm(r1, 1);
|
||||
l.dskr(r0, r1);
|
||||
|
||||
l.mov_imm(r0, 0x2000);
|
||||
l.store_word_imm(0x700, r0);
|
||||
l.lvcd_imm(0x700);
|
||||
|
||||
l.mov_imm(r0, 0x1ffc);
|
||||
l.store_word_imm(0x702, r0);
|
||||
l.mov_imm(r0, 0x1ffe);
|
||||
l.store_word_imm(0x704, r0);
|
||||
auto to_set_key_press_int = l.ip();
|
||||
l.mov_imm(r0, 0);
|
||||
l.store_word_imm(0x706, r0);
|
||||
l.lkbd_imm(0x702);
|
||||
|
||||
l.mov_imm(r0, 0);
|
||||
l.store_word_imm(0x600, r0);
|
||||
|
||||
auto main_loop = l.ip();
|
||||
l.hlt();
|
||||
l.jmp_imm(main_loop);
|
||||
|
||||
auto key_press_int = l.ip();
|
||||
l.load_word_imm(r0, 0x1ffc);
|
||||
l.and_imm(r0, r0, 1);
|
||||
auto to_set_key_press_int_leave = l.ip();
|
||||
l.jnz_imm(r0, 0);
|
||||
|
||||
l.load_word_imm(r0, 0x600);
|
||||
l.add_imm(r0, r0, 0x2000);
|
||||
l.load_word_imm(r1, 0x1ffe);
|
||||
l.cmp_imm(r1, 44);
|
||||
l.mov_reg(r2, rfl);
|
||||
l.and_imm(r2, r2, 2);
|
||||
auto to_set_key_press_incr = l.ip();
|
||||
l.jnz_imm(r2, 0);
|
||||
l.add_imm(r1, r1, 61);
|
||||
l.store_byte_reg(r0, 0, r1);
|
||||
auto key_press_incr = l.ip();
|
||||
l.load_word_imm(r0, 0x600);
|
||||
l.add_imm(r0, r0, 1);
|
||||
l.store_word_imm(0x600, r0);
|
||||
|
||||
auto key_press_int_leave = l.ip();
|
||||
l.reti();
|
||||
|
||||
l.set_ip(to_set_key_press_int + 2);
|
||||
l.push(key_press_int);
|
||||
l.set_ip(to_set_key_press_incr + 2);
|
||||
l.push(key_press_incr);
|
||||
l.set_ip(to_set_key_press_int_leave + 2);
|
||||
l.push(key_press_int_leave);
|
||||
}
|
||||
|
||||
extern "C" const char* __asan_default_options(void)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user