auto scroll
This commit is contained in:
parent
25f7c12e97
commit
c1c8bcf0b3
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
|
||||
MAKEFLAGS += -j16
|
||||
|
||||
CXXFLAGS := -std=c++23 -Wall -Wextra -pedantic-errors -fsanitize=address
|
||||
CXXFLAGS := -std=c++23 -Wall -Wextra -pedantic-errors -fsanitize=address -g -ggdb
|
||||
LDFLAGS :=
|
||||
|
||||
CXXFLAGS += $(shell pkgconf sdl2 --cflags)
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
|
||||
|
||||
const fl_zero 0x1
|
||||
const fl_eq 0x2
|
||||
const fl_be 0x4
|
||||
const fl_lt 0x8
|
||||
const fl_err 0xa
|
||||
const fl_zero 1 << 0
|
||||
const fl_eq 1 << 1
|
||||
const fl_be 1 << 2
|
||||
const fl_ab 1 << 3
|
||||
const fl_lt 1 << 4
|
||||
const fl_gt 1 << 5
|
||||
const fl_err 1 << 6
|
||||
|
||||
const vcd_base 0x2000
|
||||
|
||||
@ -66,7 +68,7 @@ key_press_int:
|
||||
|
||||
mov [rsp], r1
|
||||
add rsp, 2
|
||||
call print_u16
|
||||
call term_putc
|
||||
sub rsp, 2
|
||||
|
||||
jmp .leave
|
||||
@ -81,7 +83,9 @@ key_press_int:
|
||||
.leave:
|
||||
reti
|
||||
|
||||
|
||||
const term_width 20
|
||||
const term_height 12
|
||||
|
||||
term_y:
|
||||
dw 0
|
||||
@ -95,23 +99,112 @@ term_putc:
|
||||
|
||||
mov r1, [rbp-6]
|
||||
|
||||
mov r0, [counter]
|
||||
add r0, vcd_base
|
||||
cmp r1, '\n'
|
||||
mov r0, rfl
|
||||
and r0, fl_eq
|
||||
jnz r0, .next_row
|
||||
|
||||
cmp r1, ' '
|
||||
mov r2, rfl
|
||||
and r2, fl_eq
|
||||
jnz r2, .incr
|
||||
mov r0, rfl
|
||||
and r0, fl_eq
|
||||
jnz r0, .next_col
|
||||
|
||||
cmp r1, '\0'
|
||||
mov r0, rfl
|
||||
and r0, fl_eq
|
||||
jnz r0, .next_col
|
||||
|
||||
mov r0, [term_y]
|
||||
mul r0, term_width
|
||||
add r0, vcd_base
|
||||
mov r2, [term_x]
|
||||
add r0, r2
|
||||
mov byte [r0], r1
|
||||
.incr:
|
||||
mov r0, [counter]
|
||||
add r0, 1
|
||||
mov [counter], r0
|
||||
|
||||
.next_col:
|
||||
mov r2, [term_x]
|
||||
add r2, 1
|
||||
mov [term_x], r2
|
||||
cmp r2, term_width
|
||||
mov r0, rfl
|
||||
and r0, fl_lt
|
||||
jnz r0, .leave
|
||||
|
||||
.next_row:
|
||||
mov r0, 0
|
||||
mov [term_x], r0
|
||||
|
||||
mov r2, [term_y]
|
||||
add r2, 1
|
||||
cmp r2, term_height
|
||||
mov r0, rfl
|
||||
and r0, fl_lt
|
||||
jnz r0, .increment_y
|
||||
|
||||
call term_scroll
|
||||
jmp .leave
|
||||
|
||||
.increment_y:
|
||||
mov [term_y], r2
|
||||
|
||||
.leave:
|
||||
mov rsp, rbp
|
||||
sub rsp, 2
|
||||
mov rbp, [rsp]
|
||||
ret
|
||||
|
||||
term_scroll:
|
||||
mov r1, 0 ; row
|
||||
jmp .l1_cond
|
||||
.l1_body:
|
||||
mov r2, 0 ; col
|
||||
jmp .l2_cond
|
||||
.l2_body:
|
||||
mov r0, term_width
|
||||
mul r0, r1
|
||||
add r0, r2
|
||||
mov r4, byte [vcd_base + term_width + r0]
|
||||
mov byte [vcd_base + r0], r4
|
||||
|
||||
add r2, 1
|
||||
.l2_cond:
|
||||
cmp r2, term_width
|
||||
mov r0, rfl
|
||||
and r0, fl_lt
|
||||
jnz r0, .l2_body
|
||||
|
||||
add r1, 1
|
||||
.l1_cond:
|
||||
cmp r1, term_height - 1
|
||||
mov r0, rfl
|
||||
and r0, fl_lt
|
||||
jnz r0, .l1_body
|
||||
|
||||
mov r2, 0
|
||||
jmp .l3_cond
|
||||
.l3_body:
|
||||
mov r0, ' '
|
||||
mov byte [vcd_base + (term_height - 1) * term_width + r2], r0
|
||||
|
||||
add r2, 1
|
||||
.l3_cond:
|
||||
cmp r2, term_width
|
||||
mov r0, rfl
|
||||
and r0, fl_lt
|
||||
jnz r0, .l3_body
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
print_u16:
|
||||
mov [rsp], rbp
|
||||
add rsp, 2
|
||||
|
||||
52
programs/term.txt
Normal file
52
programs/term.txt
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
const term_width: u16 = 20;
|
||||
const term_height: u16 = 12;
|
||||
|
||||
static term_x: u16 = 0;
|
||||
static term_y: u16 = 0;
|
||||
|
||||
static vcd: *u16 = 0x2000;
|
||||
|
||||
fn term_putc(ch: u16)
|
||||
{
|
||||
if (ch == '\n')
|
||||
continue 'next_line;
|
||||
|
||||
if (ch == '\0')
|
||||
continue 'next_col;
|
||||
if (ch == ' ')
|
||||
continue 'next_col;
|
||||
|
||||
vcd[term_y * term_width + term_x] = ch;
|
||||
|
||||
'next_col:
|
||||
term_x += 1;
|
||||
if (term_x < term_width)
|
||||
return
|
||||
|
||||
'next_line:
|
||||
term_x = 0;
|
||||
|
||||
if (term_y + 1 >= term_height) {
|
||||
term_scroll();
|
||||
} else {
|
||||
term_y += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn term_scroll()
|
||||
{
|
||||
for row: u16 in 0..term_height - 1 {
|
||||
for col: u16 in 0..term_width {
|
||||
|
||||
vcd[row * term_width + col]
|
||||
= vcd[(row + 1) * term_width + col];
|
||||
}
|
||||
}
|
||||
for col: u16 in 0..term_width {
|
||||
vcd[(term_height - 1) * term_width + col] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
// vim: syntax=rust
|
||||
|
||||
@ -245,6 +245,8 @@ enum class Mnemonic {
|
||||
add,
|
||||
sub,
|
||||
rsub,
|
||||
mul,
|
||||
imul,
|
||||
call,
|
||||
ret,
|
||||
reti,
|
||||
@ -276,6 +278,8 @@ static const auto mnemonic_map
|
||||
{ "add", M::add },
|
||||
{ "sub", M::sub },
|
||||
{ "rsub", M::rsub },
|
||||
{ "mul", M::mul },
|
||||
{ "imul", M::imul },
|
||||
{ "call", M::call },
|
||||
{ "ret", M::ret },
|
||||
{ "reti", M::reti },
|
||||
@ -459,7 +463,9 @@ void Assembler::assemble_line(const Line& line)
|
||||
case M::rshr:
|
||||
case M::add:
|
||||
case M::sub:
|
||||
case M::rsub: {
|
||||
case M::rsub:
|
||||
case M::mul:
|
||||
case M::imul: {
|
||||
auto dst = std::unique_ptr<EvaledOperand> {};
|
||||
auto op1_store = std::unique_ptr<EvaledOperand> {};
|
||||
auto op2 = std::unique_ptr<EvaledOperand> {};
|
||||
@ -519,6 +525,12 @@ void Assembler::assemble_line(const Line& line)
|
||||
case Mnemonic::rsub:
|
||||
l.rsub_reg(dst->as_reg(), op1->as_reg(), op2->as_reg());
|
||||
break;
|
||||
case M::mul:
|
||||
l.mul_reg(dst->as_reg(), op1->as_reg(), op2->as_reg());
|
||||
break;
|
||||
case M::imul:
|
||||
l.imul_reg(dst->as_reg(), op1->as_reg(), op2->as_reg());
|
||||
break;
|
||||
default:
|
||||
assert(false && "unhandled");
|
||||
}
|
||||
@ -554,6 +566,12 @@ void Assembler::assemble_line(const Line& line)
|
||||
case Mnemonic::rsub:
|
||||
l.rsub_imm(dst->as_reg(), op1->as_reg(), op2->as_imm());
|
||||
break;
|
||||
case M::mul:
|
||||
l.mul_imm(dst->as_reg(), op1->as_reg(), op2->as_imm());
|
||||
break;
|
||||
case M::imul:
|
||||
l.imul_imm(dst->as_reg(), op1->as_reg(), op2->as_imm());
|
||||
break;
|
||||
default:
|
||||
assert(false && "unhandled");
|
||||
}
|
||||
@ -672,6 +690,9 @@ auto Assembler::eval_operand(const Expr& expr) -> std::unique_ptr<EvaledOperand>
|
||||
return eval_operand_mem(*expr.as_unary());
|
||||
case Expr::Ty::MemByte: {
|
||||
auto evaled = eval_operand_mem(*expr.as_unary());
|
||||
if (not evaled)
|
||||
return nullptr;
|
||||
|
||||
switch (evaled->ty) {
|
||||
case EOT::MemWordImm:
|
||||
evaled->ty = EOT::MemByteImm;
|
||||
@ -695,7 +716,10 @@ auto Assembler::eval_operand(const Expr& expr) -> std::unique_ptr<EvaledOperand>
|
||||
case Expr::Ty::Shl:
|
||||
case Expr::Ty::Shr:
|
||||
case Expr::Ty::Add:
|
||||
case Expr::Ty::Sub: {
|
||||
case Expr::Ty::Sub:
|
||||
case Expr::Ty::Mul:
|
||||
case Expr::Ty::Div:
|
||||
case Expr::Ty::Mod: {
|
||||
return eval_operand_to_imm(expr);
|
||||
}
|
||||
}
|
||||
@ -715,7 +739,10 @@ auto Assembler::eval_operand_mem(const Expr& expr)
|
||||
case Expr::Ty::Xor:
|
||||
case Expr::Ty::And:
|
||||
case Expr::Ty::Shl:
|
||||
case Expr::Ty::Shr: {
|
||||
case Expr::Ty::Shr:
|
||||
case Expr::Ty::Mul:
|
||||
case Expr::Ty::Div:
|
||||
case Expr::Ty::Mod: {
|
||||
auto op = eval_operand_to_imm(expr);
|
||||
if (not op)
|
||||
return nullptr;
|
||||
@ -822,7 +849,9 @@ auto Assembler::eval_operand_to_imm(const Expr& expr)
|
||||
return std::make_unique<EO>(loc, EOT::Imm, *result);
|
||||
}
|
||||
case Expr::Ty::Reg:
|
||||
error(loc, "registers cannot be part of an expression");
|
||||
if (not m_second_pass) {
|
||||
error(loc, "registers cannot be part of an expression");
|
||||
}
|
||||
return nullptr;
|
||||
case Expr::Ty::Int:
|
||||
return std::make_unique<EO>(
|
||||
@ -843,7 +872,10 @@ auto Assembler::eval_operand_to_imm(const Expr& expr)
|
||||
case Expr::Ty::Shl:
|
||||
case Expr::Ty::Shr:
|
||||
case Expr::Ty::Add:
|
||||
case Expr::Ty::Sub: {
|
||||
case Expr::Ty::Sub:
|
||||
case Expr::Ty::Mul:
|
||||
case Expr::Ty::Div:
|
||||
case Expr::Ty::Mod: {
|
||||
auto& [left_expr, right_expr] = expr.as_binary();
|
||||
auto left = eval_operand_to_imm(*left_expr);
|
||||
if (not left)
|
||||
@ -886,15 +918,12 @@ auto Assembler::binary_op(Expr::Ty exprTy, uint16_t left, uint16_t right)
|
||||
return (uint16_t)((int16_t)left + (int16_t)right);
|
||||
case Expr::Ty::Sub:
|
||||
return (uint16_t)((int16_t)left - (int16_t)right);
|
||||
|
||||
// taken from vc3
|
||||
// case Expr::Ty::Mul:
|
||||
// return (uint16_t)((int16_t)left * (int16_t)right);
|
||||
// case Expr::Ty::Div:
|
||||
// return (uint16_t)((int16_t)left / (int16_t)right);
|
||||
// case Expr::Ty::Mod:
|
||||
// return (uint16_t)((int16_t)left % (int16_t)right);
|
||||
|
||||
case Expr::Ty::Mul:
|
||||
return (uint16_t)((int16_t)left * (int16_t)right);
|
||||
case Expr::Ty::Div:
|
||||
return (uint16_t)((int16_t)left / (int16_t)right);
|
||||
case Expr::Ty::Mod:
|
||||
return (uint16_t)((int16_t)left % (int16_t)right);
|
||||
default:
|
||||
assert(false && "unhandled");
|
||||
}
|
||||
@ -1087,13 +1116,16 @@ auto Parser::parse_binary(int prec) -> std::unique_ptr<Expr>
|
||||
using Op = std::tuple<TT, T, int>;
|
||||
|
||||
constexpr auto ops = std::array {
|
||||
Op { TT::Pipe, T::Or, 5 },
|
||||
Op { TT::Hat, T::Xor, 4 },
|
||||
Op { TT::Ampersand, T::And, 3 },
|
||||
Op { TT::LtLt, T::Shl, 2 },
|
||||
Op { TT::GtGt, T::Shr, 2 },
|
||||
Op { TT::Plus, T::Add, 1 },
|
||||
Op { TT::Minus, T::Sub, 1 },
|
||||
Op { TT::Pipe, T::Or, 6 },
|
||||
Op { TT::Hat, T::Xor, 5 },
|
||||
Op { TT::Ampersand, T::And, 4 },
|
||||
Op { TT::LtLt, T::Shl, 3 },
|
||||
Op { TT::GtGt, T::Shr, 3 },
|
||||
Op { TT::Plus, T::Add, 2 },
|
||||
Op { TT::Minus, T::Sub, 2 },
|
||||
Op { TT::Aster, T::Mul, 1 },
|
||||
Op { TT::Slash, T::Div, 1 },
|
||||
Op { TT::Perc, T::Mod, 1 },
|
||||
};
|
||||
|
||||
if (prec == 0) {
|
||||
|
||||
@ -44,6 +44,9 @@ namespace asmer {
|
||||
Shr,
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Mod,
|
||||
};
|
||||
|
||||
using Ptr = std::unique_ptr<Expr>;
|
||||
|
||||
131
src/builder.cpp
131
src/builder.cpp
@ -1,3 +1,4 @@
|
||||
#define DEFINE_BINARY_INSTRUCTIONS
|
||||
#include "builder.hpp"
|
||||
#include "vm.hpp"
|
||||
#include <cstdint>
|
||||
@ -235,125 +236,21 @@ void Builder::cmp_imm(Reg op1, uint16_t op2)
|
||||
i.build(*this);
|
||||
}
|
||||
|
||||
void Builder::or_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
binary_reg(dst, op1, op2, Op::Or);
|
||||
}
|
||||
#define X(NAME, OP) \
|
||||
void Builder::NAME##_reg(Reg dst, Reg op1, Reg op2) \
|
||||
{ \
|
||||
LOG; \
|
||||
binary_reg(dst, op1, op2, Op::OP); \
|
||||
} \
|
||||
void Builder::NAME##_imm(Reg dst, Reg op1, uint16_t op2) \
|
||||
{ \
|
||||
LOG; \
|
||||
binary_imm(dst, op1, op2, Op::OP); \
|
||||
}
|
||||
|
||||
void Builder::and_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
binary_reg(dst, op1, op2, Op::And);
|
||||
}
|
||||
BINARY_INSTRUCTIONS
|
||||
|
||||
void Builder::xor_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
binary_reg(dst, op1, op2, Op::Xor);
|
||||
}
|
||||
|
||||
void Builder::shl_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
binary_reg(dst, op1, op2, Op::Shl);
|
||||
}
|
||||
|
||||
void Builder::rshl_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
binary_reg(dst, op1, op2, Op::RShl);
|
||||
}
|
||||
|
||||
void Builder::shr_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
binary_reg(dst, op1, op2, Op::Shr);
|
||||
}
|
||||
|
||||
void Builder::rshr_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
binary_reg(dst, op1, op2, Op::RShr);
|
||||
}
|
||||
|
||||
void Builder::add_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
binary_reg(dst, op1, op2, Op::Add);
|
||||
}
|
||||
|
||||
void Builder::sub_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
binary_reg(dst, op1, op2, Op::Sub);
|
||||
}
|
||||
|
||||
void Builder::rsub_reg(Reg dst, Reg op1, Reg op2)
|
||||
{
|
||||
LOG;
|
||||
binary_reg(dst, op1, op2, Op::RSub);
|
||||
}
|
||||
|
||||
void Builder::or_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
LOG;
|
||||
binary_imm(dst, op1, op2, Op::Xor);
|
||||
}
|
||||
|
||||
void Builder::and_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
LOG;
|
||||
binary_imm(dst, op1, op2, Op::And);
|
||||
}
|
||||
|
||||
void Builder::xor_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
LOG;
|
||||
binary_imm(dst, op1, op2, Op::Xor);
|
||||
}
|
||||
|
||||
void Builder::shl_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
LOG;
|
||||
binary_imm(dst, op1, op2, Op::Shl);
|
||||
}
|
||||
|
||||
void Builder::rshl_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
LOG;
|
||||
binary_imm(dst, op1, op2, Op::RShl);
|
||||
}
|
||||
|
||||
void Builder::shr_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
LOG;
|
||||
binary_imm(dst, op1, op2, Op::Shr);
|
||||
}
|
||||
|
||||
void Builder::rshr_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
LOG;
|
||||
binary_imm(dst, op1, op2, Op::RShr);
|
||||
}
|
||||
|
||||
void Builder::add_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
LOG;
|
||||
binary_imm(dst, op1, op2, Op::Add);
|
||||
}
|
||||
|
||||
void Builder::sub_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
LOG;
|
||||
binary_imm(dst, op1, op2, Op::Sub);
|
||||
}
|
||||
|
||||
void Builder::rsub_imm(Reg dst, Reg op1, uint16_t op2)
|
||||
{
|
||||
LOG;
|
||||
binary_imm(dst, op1, op2, Op::RSub);
|
||||
}
|
||||
#undef X
|
||||
|
||||
void Builder::binary_reg(Reg dst, Reg op1, Reg op2, Op op)
|
||||
{
|
||||
|
||||
@ -4,6 +4,20 @@
|
||||
#include <cstdint>
|
||||
#include <print>
|
||||
|
||||
#define BINARY_INSTRUCTIONS \
|
||||
X(or, Or) \
|
||||
X(and, And) \
|
||||
X(xor, Xor) \
|
||||
X(shl, Shl) \
|
||||
X(rshl, RShl) \
|
||||
X(shr, Shr) \
|
||||
X(rshr, RShr) \
|
||||
X(add, Add) \
|
||||
X(sub, Sub) \
|
||||
X(rsub, RSub) \
|
||||
X(mul, Mul) \
|
||||
X(imul, IMul)
|
||||
|
||||
namespace vc5::tools {
|
||||
|
||||
using namespace vc5;
|
||||
@ -33,26 +47,15 @@ public:
|
||||
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);
|
||||
void and_reg(Reg dst, Reg op1, Reg op2);
|
||||
void xor_reg(Reg dst, Reg op1, Reg op2);
|
||||
void shl_reg(Reg dst, Reg op1, Reg op2);
|
||||
void rshl_reg(Reg dst, Reg op1, Reg op2);
|
||||
void shr_reg(Reg dst, Reg op1, Reg op2);
|
||||
void rshr_reg(Reg dst, Reg op1, Reg op2);
|
||||
void add_reg(Reg dst, Reg op1, Reg op2);
|
||||
void sub_reg(Reg dst, Reg op1, Reg op2);
|
||||
void rsub_reg(Reg dst, Reg op1, Reg op2);
|
||||
void or_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void and_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void xor_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void shl_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void rshl_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void shr_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void rshr_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void add_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void sub_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
void rsub_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
|
||||
#define X(NAME, OP) \
|
||||
void NAME##_reg(Reg dst, Reg op1, Reg op2); \
|
||||
void NAME##_imm(Reg dst, Reg op1, uint16_t op2);
|
||||
|
||||
BINARY_INSTRUCTIONS
|
||||
|
||||
#undef X
|
||||
|
||||
void call_reg(Reg op1);
|
||||
void call_imm(uint16_t op1);
|
||||
void ret();
|
||||
@ -103,3 +106,7 @@ private:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef DEFINE_BINARY_INSTRUCTIONS
|
||||
#undef BINARY_INSTRUCTIONS
|
||||
#endif
|
||||
|
||||
@ -131,7 +131,7 @@ auto Scanner::next() -> Tok
|
||||
}
|
||||
return tok(TT::Gt, loc);
|
||||
}
|
||||
if (test_in("\n()[].,:|^+-!")) {
|
||||
if (test_in("\n()[].,:|^+-*/%!")) {
|
||||
auto ty = static_cast<TT>(current());
|
||||
step();
|
||||
return tok(ty, loc);
|
||||
|
||||
@ -54,6 +54,9 @@ struct Tok {
|
||||
Ampersand = '&',
|
||||
Plus = '+',
|
||||
Minus = '-',
|
||||
Aster = '*',
|
||||
Slash = '/',
|
||||
Perc = '%',
|
||||
Exclam = '!',
|
||||
Lt = '<',
|
||||
Gt = '>',
|
||||
|
||||
35
src/vm.cpp
35
src/vm.cpp
@ -411,11 +411,21 @@ int VM::run_instruction()
|
||||
} else {
|
||||
*m_rfl &= (uint16_t)~(1u << std::to_underlying(Flag::Be));
|
||||
}
|
||||
if (op1 > op2) {
|
||||
*m_rfl |= 1u << std::to_underlying(Flag::Ab);
|
||||
} else {
|
||||
*m_rfl &= (uint16_t)~(1u << std::to_underlying(Flag::Ab));
|
||||
}
|
||||
if ((int16_t)op1 < (int16_t)op2) {
|
||||
*m_rfl |= 1u << std::to_underlying(Flag::Lt);
|
||||
} else {
|
||||
*m_rfl &= (uint16_t)~(1u << std::to_underlying(Flag::Lt));
|
||||
}
|
||||
if ((int16_t)op1 > (int16_t)op2) {
|
||||
*m_rfl |= 1u << std::to_underlying(Flag::Gt);
|
||||
} else {
|
||||
*m_rfl &= (uint16_t)~(1u << std::to_underlying(Flag::Gt));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Op::Or:
|
||||
@ -427,13 +437,18 @@ int VM::run_instruction()
|
||||
case Op::RShr:
|
||||
case Op::Add:
|
||||
case Op::Sub:
|
||||
case Op::RSub: {
|
||||
case Op::RSub:
|
||||
case Op::Mul:
|
||||
case Op::IMul: {
|
||||
auto op1 = ins.op1();
|
||||
auto op2 = ins.op2_or_imm();
|
||||
auto dst_reg = ins.dst_reg();
|
||||
|
||||
uint16_t* dst = &m_regs[std::to_underlying(dst_reg)];
|
||||
|
||||
auto as_u16 = [](auto v) { return static_cast<uint16_t>(v); };
|
||||
auto as_i16 = [](auto v) { return static_cast<int16_t>(v); };
|
||||
|
||||
switch (op) {
|
||||
case Op::Or:
|
||||
*dst = op1 | op2;
|
||||
@ -445,16 +460,16 @@ int VM::run_instruction()
|
||||
*dst = op1 & op2;
|
||||
break;
|
||||
case Op::Shl:
|
||||
*dst = static_cast<uint16_t>(op1 << op2);
|
||||
*dst = as_u16(op1 << op2);
|
||||
break;
|
||||
case Op::RShl:
|
||||
*dst = static_cast<uint16_t>(op2 << op1);
|
||||
*dst = as_u16(op2 << op1);
|
||||
break;
|
||||
case Op::Shr:
|
||||
*dst = static_cast<uint16_t>(op1 >> op2);
|
||||
*dst = as_u16(op1 >> op2);
|
||||
break;
|
||||
case Op::RShr:
|
||||
*dst = static_cast<uint16_t>(op2 >> op1);
|
||||
*dst = as_u16(op2 >> op1);
|
||||
break;
|
||||
case Op::Add:
|
||||
*dst = op1 + op2;
|
||||
@ -465,6 +480,12 @@ int VM::run_instruction()
|
||||
case Op::RSub:
|
||||
*dst = op2 - op1;
|
||||
break;
|
||||
case Op::Mul:
|
||||
*dst = op1 * op2;
|
||||
break;
|
||||
case Op::IMul:
|
||||
*dst = as_u16(as_i16(op1) * as_i16(op2));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -647,6 +668,10 @@ auto vc5::op_str(Op op) -> std::string_view
|
||||
return "Sub";
|
||||
case Op::RSub:
|
||||
return "RSub";
|
||||
case Op::Mul:
|
||||
return "Mul";
|
||||
case Op::IMul:
|
||||
return "IMul";
|
||||
case Op::Call:
|
||||
return "Call";
|
||||
case Op::Ret:
|
||||
|
||||
@ -33,6 +33,8 @@ enum class Op : uint16_t {
|
||||
Add,
|
||||
Sub,
|
||||
RSub,
|
||||
Mul,
|
||||
IMul,
|
||||
|
||||
Call,
|
||||
Ret,
|
||||
@ -82,8 +84,10 @@ enum class Flag : uint16_t {
|
||||
Zero = 0,
|
||||
Eq = 1,
|
||||
Be = 2,
|
||||
Lt = 3,
|
||||
Err = 4,
|
||||
Ab = 3,
|
||||
Lt = 4,
|
||||
Gt = 5,
|
||||
Err = 6,
|
||||
};
|
||||
|
||||
struct VcdDescript {
|
||||
|
||||
@ -8,12 +8,17 @@ if exists("b:current_syntax")
|
||||
endif
|
||||
|
||||
syn keyword Keyword const align db dw
|
||||
syn keyword Keyword nop hlt jmp jnz mov cmp or and xor shl rshl shr rshr add sub rsub
|
||||
syn keyword Keyword nop hlt jmp jnz mov cmp
|
||||
syn keyword Keyword or and xor shl rshl shr rshr add sub rsub mul imul
|
||||
syn keyword Keyword call ret reti lkbd lvcd dskr dskw
|
||||
syn keyword Type byte word
|
||||
syn keyword Operator r0 r1 r2 r3 r4 r5 rbp rsp rfl rip
|
||||
|
||||
syn match Operator '+'
|
||||
syn match Operator '-'
|
||||
syn match Operator '*'
|
||||
syn match Operator '/'
|
||||
syn match Operator '%'
|
||||
syn match Operator '='
|
||||
syn match Operator '<'
|
||||
syn match Operator '>'
|
||||
@ -21,7 +26,6 @@ syn match Operator '|'
|
||||
syn match Operator '^'
|
||||
syn match Operator '&'
|
||||
|
||||
|
||||
syn match Number '0'
|
||||
syn match Number '[1-9][0-9]*'
|
||||
syn match Number '0b[01]*'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user