backspace and return

This commit is contained in:
sfja 2025-03-31 18:47:41 +02:00
parent cad6ed9604
commit b9a837e3c7
6 changed files with 314 additions and 83 deletions

View File

@ -13,13 +13,14 @@ if &shortmess =~ 'A'
else else
set shortmess=aoO set shortmess=aoO
endif endif
badd +437 vm/main.c badd +440 vm/main.c
badd +48 Makefile badd +11 Makefile
badd +10 vm/vm.h badd +12 vm/vm.h
badd +181 vm/vm.c badd +262 vm/vm.c
badd +14 vm/asm.h badd +91 vm/asm.h
badd +263 vm/asm.c badd +378 vm/asm.c
badd +747 ~/.config/nvim/init.lua badd +747 ~/.config/nvim/init.lua
badd +10 compile_flags.txt
argglobal argglobal
%argdel %argdel
$argadd vm/main.c $argadd vm/main.c
@ -28,7 +29,7 @@ tabnew +setlocal\ bufhidden=wipe
tabnew +setlocal\ bufhidden=wipe tabnew +setlocal\ bufhidden=wipe
tabnew +setlocal\ bufhidden=wipe tabnew +setlocal\ bufhidden=wipe
tabrewind tabrewind
edit vm/main.c edit Makefile
let s:save_splitbelow = &splitbelow let s:save_splitbelow = &splitbelow
let s:save_splitright = &splitright let s:save_splitright = &splitright
set splitbelow splitright set splitbelow splitright
@ -45,9 +46,10 @@ set winminheight=0
set winheight=1 set winheight=1
set winminwidth=0 set winminwidth=0
set winwidth=1 set winwidth=1
exe 'vert 1resize ' . ((&columns * 123 + 128) / 256) exe 'vert 1resize ' . ((&columns * 71 + 128) / 256)
exe 'vert 2resize ' . ((&columns * 132 + 128) / 256) exe 'vert 2resize ' . ((&columns * 184 + 128) / 256)
argglobal argglobal
balt compile_flags.txt
setlocal fdm=manual setlocal fdm=manual
setlocal fde=0 setlocal fde=0
setlocal fmr={{{,}}} setlocal fmr={{{,}}}
@ -58,19 +60,19 @@ setlocal fdn=20
setlocal fen setlocal fen
silent! normal! zE silent! normal! zE
let &fdl = &fdl let &fdl = &fdl
let s:l = 437 - ((37 * winheight(0) + 32) / 65) let s:l = 11 - ((10 * winheight(0) + 32) / 65)
if s:l < 1 | let s:l = 1 | endif if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l keepjumps exe s:l
normal! zt normal! zt
keepjumps 437 keepjumps 11
normal! 012| normal! 027|
wincmd w wincmd w
argglobal argglobal
if bufexists(fnamemodify("Makefile", ":p")) | buffer Makefile | else | edit Makefile | endif if bufexists(fnamemodify("vm/main.c", ":p")) | buffer vm/main.c | else | edit vm/main.c | endif
if &buftype ==# 'terminal' if &buftype ==# 'terminal'
silent file Makefile silent file vm/main.c
endif endif
balt vm/main.c balt vm/asm.c
setlocal fdm=manual setlocal fdm=manual
setlocal fde=0 setlocal fde=0
setlocal fmr={{{,}}} setlocal fmr={{{,}}}
@ -81,15 +83,16 @@ setlocal fdn=20
setlocal fen setlocal fen
silent! normal! zE silent! normal! zE
let &fdl = &fdl let &fdl = &fdl
let s:l = 15 - ((14 * winheight(0) + 32) / 65) let s:l = 440 - ((29 * winheight(0) + 32) / 65)
if s:l < 1 | let s:l = 1 | endif if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l keepjumps exe s:l
normal! zt normal! zt
keepjumps 15 keepjumps 440
normal! 0 normal! 010|
wincmd w wincmd w
exe 'vert 1resize ' . ((&columns * 123 + 128) / 256) 2wincmd w
exe 'vert 2resize ' . ((&columns * 132 + 128) / 256) exe 'vert 1resize ' . ((&columns * 71 + 128) / 256)
exe 'vert 2resize ' . ((&columns * 184 + 128) / 256)
tabnext tabnext
edit vm/vm.h edit vm/vm.h
let s:save_splitbelow = &splitbelow let s:save_splitbelow = &splitbelow
@ -122,12 +125,12 @@ setlocal fdn=20
setlocal fen setlocal fen
silent! normal! zE silent! normal! zE
let &fdl = &fdl let &fdl = &fdl
let s:l = 10 - ((9 * winheight(0) + 32) / 65) let s:l = 12 - ((11 * winheight(0) + 32) / 65)
if s:l < 1 | let s:l = 1 | endif if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l keepjumps exe s:l
normal! zt normal! zt
keepjumps 10 keepjumps 12
normal! 011| normal! 06|
wincmd w wincmd w
argglobal argglobal
if bufexists(fnamemodify("vm/vm.c", ":p")) | buffer vm/vm.c | else | edit vm/vm.c | endif if bufexists(fnamemodify("vm/vm.c", ":p")) | buffer vm/vm.c | else | edit vm/vm.c | endif
@ -145,12 +148,12 @@ setlocal fdn=20
setlocal fen setlocal fen
silent! normal! zE silent! normal! zE
let &fdl = &fdl let &fdl = &fdl
let s:l = 83 - ((7 * winheight(0) + 32) / 65) let s:l = 262 - ((49 * winheight(0) + 32) / 65)
if s:l < 1 | let s:l = 1 | endif if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l keepjumps exe s:l
normal! zt normal! zt
keepjumps 83 keepjumps 262
normal! 021| normal! 0
wincmd w wincmd w
exe 'vert 1resize ' . ((&columns * 93 + 128) / 256) exe 'vert 1resize ' . ((&columns * 93 + 128) / 256)
exe 'vert 2resize ' . ((&columns * 162 + 128) / 256) exe 'vert 2resize ' . ((&columns * 162 + 128) / 256)
@ -186,12 +189,12 @@ setlocal fdn=20
setlocal fen setlocal fen
silent! normal! zE silent! normal! zE
let &fdl = &fdl let &fdl = &fdl
let s:l = 53 - ((34 * winheight(0) + 32) / 65) let s:l = 91 - ((48 * winheight(0) + 32) / 65)
if s:l < 1 | let s:l = 1 | endif if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l keepjumps exe s:l
normal! zt normal! zt
keepjumps 53 keepjumps 91
normal! 0 normal! 045|
wincmd w wincmd w
argglobal argglobal
if bufexists(fnamemodify("vm/asm.c", ":p")) | buffer vm/asm.c | else | edit vm/asm.c | endif if bufexists(fnamemodify("vm/asm.c", ":p")) | buffer vm/asm.c | else | edit vm/asm.c | endif
@ -209,12 +212,12 @@ setlocal fdn=20
setlocal fen setlocal fen
silent! normal! zE silent! normal! zE
let &fdl = &fdl let &fdl = &fdl
let s:l = 265 - ((36 * winheight(0) + 32) / 65) let s:l = 146 - ((10 * winheight(0) + 32) / 65)
if s:l < 1 | let s:l = 1 | endif if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l keepjumps exe s:l
normal! zt normal! zt
keepjumps 265 keepjumps 146
normal! 032| normal! 019|
wincmd w wincmd w
exe 'vert 1resize ' . ((&columns * 87 + 128) / 256) exe 'vert 1resize ' . ((&columns * 87 + 128) / 256)
exe 'vert 2resize ' . ((&columns * 168 + 128) / 256) exe 'vert 2resize ' . ((&columns * 168 + 128) / 256)
@ -239,7 +242,7 @@ set winwidth=1
exe 'vert 1resize ' . ((&columns * 127 + 128) / 256) exe 'vert 1resize ' . ((&columns * 127 + 128) / 256)
exe 'vert 2resize ' . ((&columns * 128 + 128) / 256) exe 'vert 2resize ' . ((&columns * 128 + 128) / 256)
argglobal argglobal
balt vm/asm.h balt vm/vm.c
setlocal fdm=manual setlocal fdm=manual
setlocal fde=0 setlocal fde=0
setlocal fmr={{{,}}} setlocal fmr={{{,}}}
@ -250,12 +253,12 @@ setlocal fdn=20
setlocal fen setlocal fen
silent! normal! zE silent! normal! zE
let &fdl = &fdl let &fdl = &fdl
let s:l = 265 - ((35 * winheight(0) + 32) / 65) let s:l = 369 - ((29 * winheight(0) + 32) / 65)
if s:l < 1 | let s:l = 1 | endif if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l keepjumps exe s:l
normal! zt normal! zt
keepjumps 265 keepjumps 369
normal! 031| normal! 042|
wincmd w wincmd w
argglobal argglobal
if bufexists(fnamemodify("vm/vm.c", ":p")) | buffer vm/vm.c | else | edit vm/vm.c | endif if bufexists(fnamemodify("vm/vm.c", ":p")) | buffer vm/vm.c | else | edit vm/vm.c | endif
@ -273,16 +276,16 @@ setlocal fdn=20
setlocal fen setlocal fen
silent! normal! zE silent! normal! zE
let &fdl = &fdl let &fdl = &fdl
let s:l = 123 - ((48 * winheight(0) + 32) / 65) let s:l = 228 - ((61 * winheight(0) + 32) / 65)
if s:l < 1 | let s:l = 1 | endif if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l keepjumps exe s:l
normal! zt normal! zt
keepjumps 123 keepjumps 228
normal! 0 normal! 01|
wincmd w wincmd w
exe 'vert 1resize ' . ((&columns * 127 + 128) / 256) exe 'vert 1resize ' . ((&columns * 127 + 128) / 256)
exe 'vert 2resize ' . ((&columns * 128 + 128) / 256) exe 'vert 2resize ' . ((&columns * 128 + 128) / 256)
tabnext 3 tabnext 1
set stal=1 set stal=1
if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'
silent exe 'bwipe ' . s:wipebuf silent exe 'bwipe ' . s:wipebuf

103
vm/asm.c
View File

@ -149,6 +149,24 @@ Line s_in_i(Reg dst_reg, uint16_t op1_imm)
.op1 = (Ex) { .imm = op1_imm }, .op1 = (Ex) { .imm = op1_imm },
}; };
} }
Line s_call_i(uint16_t op1_imm)
{
return (Line) {
.ty = LineTy_Call_Imm,
.op1 = (Ex) { .imm = op1_imm },
};
}
Line s_call_l(int op1_label)
{
return (Line) {
.ty = LineTy_Call_Label,
.op1 = (Ex) { .label = op1_label },
};
}
Line s_ret(void)
{
return (Line) { .ty = LineTy_Ret };
}
Line s_lit_i(uint16_t op1_imm) Line s_lit_i(uint16_t op1_imm)
{ {
return (Line) { return (Line) {
@ -187,9 +205,29 @@ Line s_iret(void)
} }
DEFINE_BINARY_I(or, Or) DEFINE_BINARY_I(or, Or)
DEFINE_BINARY_I(xor, Xor)
DEFINE_BINARY_I(and, And) DEFINE_BINARY_I(and, And)
DEFINE_BINARY_I(add, Add) DEFINE_BINARY_I(add, Add)
DEFINE_BINARY_I(sub, Sub) DEFINE_BINARY_I(sub, Sub)
DEFINE_BINARY_I(mul, Mul)
#define DEFINE_BINARY_R(FN, LINETY) \
Line s_##FN##_r(Reg dst_reg, Reg op1_reg, Reg op2_reg) \
{ \
return (Line) { \
.ty = LineTy_##LINETY##_Reg, \
.dst = (Ex) { .reg = (uint16_t)dst_reg }, \
.op1 = (Ex) { .reg = (uint16_t)op1_reg }, \
.op2 = (Ex) { .reg = (uint16_t)op2_reg }, \
}; \
}
DEFINE_BINARY_R(or, Or)
DEFINE_BINARY_R(xor, Xor)
DEFINE_BINARY_R(and, And)
DEFINE_BINARY_R(add, Add)
DEFINE_BINARY_R(sub, Sub)
DEFINE_BINARY_R(mul, Mul)
static inline void add_dst_reg(uint32_t* ins, uint16_t reg); static inline void add_dst_reg(uint32_t* ins, uint16_t reg);
static inline void add_op1_reg(uint32_t* ins, uint16_t reg); static inline void add_op1_reg(uint32_t* ins, uint16_t reg);
@ -200,7 +238,7 @@ static inline void set_mov_addr_is_reg(uint32_t* ins);
static inline void set_mov_is_store(uint32_t* ins); static inline void set_mov_is_store(uint32_t* ins);
static inline uint16_t linety_arithm_ins(LineTy ty); static inline uint16_t linety_arithm_ins(LineTy ty);
void assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size) uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
{ {
bool debug = false; bool debug = false;
@ -443,6 +481,31 @@ void assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
out[ip++] = op1; out[ip++] = op1;
break; break;
} }
case LineTy_Call_Imm: {
uint16_t op1 = line->op1.imm;
uint32_t ins = Op_Call;
set_is_imm(&ins);
out[ip++] = (uint16_t)ins;
out[ip++] = op1;
break;
}
case LineTy_Call_Label: {
int op1 = line->op1.label;
uint32_t ins = Op_Call;
set_is_imm(&ins);
out[ip++] = (uint16_t)ins;
ADD_LABEL(op1);
break;
}
case LineTy_Ret: {
uint32_t ins = Op_Ret;
out[ip++] = (uint16_t)ins;
break;
}
case LineTy_Lit_Imm: { case LineTy_Lit_Imm: {
uint16_t op1 = line->op1.imm; uint16_t op1 = line->op1.imm;
@ -472,13 +535,17 @@ void assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
break; break;
} }
case LineTy_IRet: { case LineTy_IRet: {
out[ip++] = Op_IRet; uint32_t ins = Op_Ret;
ins |= 1 << 6;
out[ip++] = (uint16_t)ins;
break; break;
} }
case LineTy_Or_Imm: case LineTy_Or_Imm:
case LineTy_Xor_Imm:
case LineTy_And_Imm: case LineTy_And_Imm:
case LineTy_Add_Imm: case LineTy_Add_Imm:
case LineTy_Sub_Imm: { case LineTy_Sub_Imm:
case LineTy_Mul_Imm: {
uint16_t dst = line->dst.reg; uint16_t dst = line->dst.reg;
uint16_t op1 = line->op1.reg; uint16_t op1 = line->op1.reg;
uint16_t op2 = line->op2.imm; uint16_t op2 = line->op2.imm;
@ -492,6 +559,24 @@ void assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
out[ip++] = op2; out[ip++] = op2;
break; break;
} }
case LineTy_Or_Reg:
case LineTy_Xor_Reg:
case LineTy_And_Reg:
case LineTy_Add_Reg:
case LineTy_Sub_Reg:
case LineTy_Mul_Reg: {
uint16_t dst = line->dst.reg;
uint16_t op1 = line->op1.reg;
uint16_t op2 = line->op2.reg;
uint32_t ins = linety_arithm_ins(line->ty);
add_op2_reg(&ins, op2);
add_op1_reg(&ins, op1);
add_dst_reg(&ins, dst);
out[ip++] = (uint16_t)ins;
break;
}
} }
if (debug) { if (debug) {
@ -547,6 +632,8 @@ void assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
if (debug) { if (debug) {
printf("done!\n"); printf("done!\n");
} }
return ip * 2;
} }
static inline void add_dst_reg(uint32_t* ins, uint16_t reg) static inline void add_dst_reg(uint32_t* ins, uint16_t reg)
@ -582,13 +669,23 @@ static inline uint16_t linety_arithm_ins(LineTy ty)
{ {
switch (ty) { switch (ty) {
case LineTy_Or_Imm: case LineTy_Or_Imm:
case LineTy_Or_Reg:
return Op_Or; return Op_Or;
case LineTy_Xor_Imm:
case LineTy_Xor_Reg:
return Op_Xor;
case LineTy_And_Imm: case LineTy_And_Imm:
case LineTy_And_Reg:
return Op_And; return Op_And;
case LineTy_Add_Imm: case LineTy_Add_Imm:
case LineTy_Add_Reg:
return Op_Add; return Op_Add;
case LineTy_Sub_Imm: case LineTy_Sub_Imm:
case LineTy_Sub_Reg:
return Op_Sub; return Op_Sub;
case LineTy_Mul_Imm:
case LineTy_Mul_Reg:
return Op_Mul;
default: default:
fprintf(stderr, "error: line type '%d' not handled\n", ty); fprintf(stderr, "error: line type '%d' not handled\n", ty);
exit(1); exit(1);

View File

@ -24,14 +24,25 @@ typedef enum {
LineTy_Mov16_MemReg_Reg, LineTy_Mov16_MemReg_Reg,
LineTy_Mov16_MemLabel_Reg, LineTy_Mov16_MemLabel_Reg,
LineTy_In_Imm, LineTy_In_Imm,
LineTy_Call_Imm,
LineTy_Call_Label,
LineTy_Ret,
LineTy_Lit_Imm, LineTy_Lit_Imm,
LineTy_Lit_Label, LineTy_Lit_Label,
LineTy_Int, LineTy_Int,
LineTy_IRet, LineTy_IRet,
LineTy_Or_Imm, LineTy_Or_Imm,
LineTy_Xor_Imm,
LineTy_And_Imm, LineTy_And_Imm,
LineTy_Add_Imm, LineTy_Add_Imm,
LineTy_Sub_Imm, LineTy_Sub_Imm,
LineTy_Mul_Imm,
LineTy_Or_Reg,
LineTy_Xor_Reg,
LineTy_And_Reg,
LineTy_Add_Reg,
LineTy_Sub_Reg,
LineTy_Mul_Reg,
} LineTy; } LineTy;
typedef struct { typedef struct {
@ -71,20 +82,32 @@ Line s_mov16_r_ml(Reg dst_reg, int op2_label);
Line s_mov16_mr_r(Reg dst_reg, uint16_t dst_offset, Reg op2_reg); Line s_mov16_mr_r(Reg dst_reg, uint16_t dst_offset, Reg op2_reg);
Line s_mov16_ml_r(int dst_label, Reg op2_reg); Line s_mov16_ml_r(int dst_label, Reg op2_reg);
Line s_in_i(Reg dst_reg, uint16_t op1_imm); Line s_in_i(Reg dst_reg, uint16_t op1_imm);
Line s_call_i(uint16_t op1_imm);
Line s_call_l(int op1_label);
Line s_ret(void);
Line s_lit_i(uint16_t op1_imm); Line s_lit_i(uint16_t op1_imm);
Line s_lit_l(int op1_label); Line s_lit_l(int op1_label);
Line s_int(uint8_t int_id); Line s_int(uint8_t int_id);
Line s_iret(void); Line s_iret(void);
Line s_or_i(Reg dst_reg, Reg op1_reg, uint16_t op2_imm); Line s_or_i(Reg dst_reg, Reg op1_reg, uint16_t op2_imm);
Line s_xor_i(Reg dst_reg, Reg op1_reg, uint16_t op2_imm);
Line s_and_i(Reg dst_reg, Reg op1_reg, uint16_t op2_imm); Line s_and_i(Reg dst_reg, Reg op1_reg, uint16_t op2_imm);
Line s_add_i(Reg dst_reg, Reg op1_reg, uint16_t op2_imm); Line s_add_i(Reg dst_reg, Reg op1_reg, uint16_t op2_imm);
Line s_sub_i(Reg dst_reg, Reg op1_reg, uint16_t op2_imm); Line s_sub_i(Reg dst_reg, Reg op1_reg, uint16_t op2_imm);
Line s_mul_i(Reg dst_reg, Reg op1_reg, uint16_t op2_imm);
Line s_or_r(Reg dst_reg, Reg op1_reg, Reg op2_reg);
Line s_xor_r(Reg dst_reg, Reg op1_reg, Reg op2_reg);
Line s_and_r(Reg dst_reg, Reg op1_reg, Reg op2_reg);
Line s_add_r(Reg dst_reg, Reg op1_reg, Reg op2_reg);
Line s_sub_r(Reg dst_reg, Reg op1_reg, Reg op2_reg);
Line s_mul_r(Reg dst_reg, Reg op1_reg, Reg op2_reg);
#define s_push_r(REG) s_add_i(Rsp, Rsp, 2), s_mov16_mr_r(Rsp, 0, REG) #define s_push_r(REG) s_add_i(Rsp, Rsp, 2), s_mov16_mr_r(Rsp, 0, REG)
#define s_pop_r(REG) s_mov16_r_mr(REG, Rsp, 2), s_sub_i(Rsp, Rsp, 2) #define s_pop_r(REG) s_mov16_r_mr(REG, Rsp, 0), s_sub_i(Rsp, Rsp, 2)
void assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size); uint16_t assemble_to_binary(
uint16_t* out, const Line* lines, size_t lines_size);
#define fmt_binary(VAL) \ #define fmt_binary(VAL) \
(VAL) >> 7 & 1 ? '1' : '0', (VAL) >> 6 & 1 ? '1' : '0', \ (VAL) >> 7 & 1 ? '1' : '0', (VAL) >> 6 & 1 ? '1' : '0', \

109
vm/main.c
View File

@ -269,7 +269,8 @@ static inline bool is_exit_event(SDL_Event* event)
return event->type == SDL_QUIT return event->type == SDL_QUIT
|| (event->type == SDL_KEYDOWN || (event->type == SDL_KEYDOWN
&& event->key.keysym.scancode == SDL_SCANCODE_ESCAPE && event->key.keysym.scancode == SDL_SCANCODE_ESCAPE
&& event->key.keysym.mod & KMOD_CTRL); // && event->key.keysym.mod & KMOD_CTRL
);
} }
void sdldevice_poll_events(SdlDevice* device) void sdldevice_poll_events(SdlDevice* device)
@ -392,6 +393,10 @@ int main(void)
int keyboard_interrupt_1 = label_ids++; int keyboard_interrupt_1 = label_ids++;
int keyboard_interrupt_2 = label_ids++; int keyboard_interrupt_2 = label_ids++;
int keyboard_interrupt_3 = label_ids++; int keyboard_interrupt_3 = label_ids++;
int keyboard_interrupt_4 = label_ids++;
int put_char = label_ids++;
int put_char_0 = label_ids++;
int put_char_1 = label_ids++;
int screen_x = label_ids++; int screen_x = label_ids++;
int screen_y = label_ids++; int screen_y = label_ids++;
@ -399,7 +404,6 @@ int main(void)
Line program_asm[] = { Line program_asm[] = {
// clang-format off // clang-format off
s_nop(),
// rsp points *at* the top element // rsp points *at* the top element
s_mov16_r_i(Rbp, 2048), s_mov16_r_i(Rbp, 2048),
@ -417,12 +421,13 @@ int main(void)
L(main_loop), L(main_loop),
s_hlt(), s_hlt(),
s_jmp_l(main_loop), s_jmp_l(main_loop),
s_nop(),
L(interrupt_table), L(interrupt_table),
// size // size
s_data_i(1), s_data_i(1),
s_data_l(keyboard_interrupt), s_data_l(keyboard_interrupt),
s_nop(), s_nop(),
L(keyboard_interrupt), L(keyboard_interrupt),
s_and_i(Rfl, Rfl, (uint16_t)~(1 << Fl_Int)), s_and_i(Rfl, Rfl, (uint16_t)~(1 << Fl_Int)),
s_push_r(Rbp), s_push_r(Rbp),
@ -430,28 +435,63 @@ int main(void)
s_push_r(R0), s_push_r(R0),
s_push_r(R1), s_push_r(R1),
s_push_r(R2), s_push_r(R2),
s_push_r(R3),
// read keyboard port
s_in_i(R0, Device_Keyboard), s_in_i(R0, Device_Keyboard),
s_add_i(R0, R0, 'A' - 4),
s_cmp_i(R0, 105), s_cmp_i(R0, 44),
s_mov16_r_r(R1, Rfl), s_mov16_r_r(R1, Rfl),
s_and_i(R1, R1, 1 << Fl_Eq), s_and_i(R1, R1, 1 << Fl_Eq),
s_jnz_l(R1, keyboard_interrupt_0), s_jnz_l(R1, keyboard_interrupt_0),
s_jmp_l(keyboard_interrupt_1),
s_cmp_i(R0, 42),
s_mov16_r_r(R1, Rfl),
s_and_i(R1, R1, 1 << Fl_Eq),
s_jnz_l(R1, keyboard_interrupt_1),
s_cmp_i(R0, 40),
s_mov16_r_r(R1, Rfl),
s_and_i(R1, R1, 1 << Fl_Eq),
s_jnz_l(R1, keyboard_interrupt_2),
s_jmp_l(keyboard_interrupt_3),
L(keyboard_interrupt_0), L(keyboard_interrupt_0),
s_mov16_r_i(R0, ' '), s_mov16_r_i(R0, ' '),
s_jmp_l(keyboard_interrupt_1), s_call_l(put_char),
s_jmp_l(keyboard_interrupt_4),
L(keyboard_interrupt_1), L(keyboard_interrupt_1),
s_mov16_r_ml(R1, screen_x), s_mov16_r_ml(R1, screen_x),
s_add_i(R1, R1, 0x0c00), s_cmp_i(R1, 0),
s_mov8_mr_r(R1, R0), s_mov16_r_r(R2, Rfl),
s_and_i(R2, R2, 1 << Fl_Eq),
s_mov16_r_ml(R1, screen_x), s_jnz_l(R2, keyboard_interrupt_4),
s_add_i(R1, R1, 1), s_sub_i(R1, R1, 1),
s_mov16_ml_r(screen_x, R1), s_mov16_ml_r(screen_x, R1),
s_mov16_r_i(R0, ' '),
s_call_l(put_char),
s_mov16_r_ml(R1, screen_x),
s_sub_i(R1, R1, 1),
s_mov16_ml_r(screen_x, R1),
s_jmp_l(keyboard_interrupt_4),
L(keyboard_interrupt_2),
s_mov16_r_ml(R1, screen_y),
s_add_i(R1, R1, 1),
s_mov16_ml_r(screen_y, R1),
s_mov16_r_i(R1, 0),
s_mov16_ml_r(screen_x, R1),
s_jmp_l(keyboard_interrupt_4),
L(keyboard_interrupt_3),
s_add_i(R0, R0, 'A' - 4),
s_call_l(put_char),
s_jmp_l(keyboard_interrupt_4),
L(keyboard_interrupt_4),
s_pop_r(R3),
s_pop_r(R2), s_pop_r(R2),
s_pop_r(R1), s_pop_r(R1),
s_pop_r(R0), s_pop_r(R0),
@ -459,6 +499,45 @@ int main(void)
s_pop_r(Rbp), s_pop_r(Rbp),
s_or_i(Rfl, Rfl, 1 << Fl_Int), s_or_i(Rfl, Rfl, 1 << Fl_Int),
s_iret(), s_iret(),
L(put_char),
s_push_r(Rbp),
s_mov16_r_r(Rbp, Rsp),
s_push_r(R1),
s_push_r(R2),
s_mov16_r_ml(R2, screen_y),
s_mul_i(R2, R2, width_in_ch),
s_mov16_r_ml(R1, screen_x),
s_add_i(R1, R1, 0x0c00),
s_add_r(R1, R1, R2),
s_mov8_mr_r(R1, R0),
s_mov16_r_ml(R1, screen_x),
s_add_i(R1, R1, 1),
s_mov16_ml_r(screen_x, R1),
s_cmp_i(R1, width_in_ch),
s_mov16_r_r(R2, Rfl),
s_and_i(R2, R2, 1 << Fl_Eq),
s_jnz_l(R2, put_char_0),
s_jmp_l(put_char_1),
L(put_char_0),
s_mov16_r_ml(R1, screen_y),
s_add_i(R1, R1, 1),
s_mov16_ml_r(screen_y, R1),
s_mov16_r_i(R1, 0),
s_mov16_ml_r(screen_x, R1),
L(put_char_1),
s_pop_r(R1),
s_pop_r(R2),
s_mov16_r_r(Rsp, Rbp),
s_pop_r(Rbp),
s_ret(),
L(screen_x), L(screen_x),
s_data_i(0), s_data_i(0),
L(screen_y), L(screen_y),
@ -470,7 +549,9 @@ int main(void)
size_t program_asm_size = sizeof(program_asm) / sizeof(program_asm[0]); size_t program_asm_size = sizeof(program_asm) / sizeof(program_asm[0]);
uint16_t* program = calloc(512 * 2, sizeof(uint16_t)); uint16_t* program = calloc(512 * 2, sizeof(uint16_t));
assemble_to_binary(program, program_asm, program_asm_size); uint16_t program_size
= assemble_to_binary(program, program_asm, program_asm_size);
printf("program size = %d\n", program_size);
// dump_program(program); // dump_program(program);

72
vm/vm.c
View File

@ -22,7 +22,6 @@ static inline void handle_device_write(
VM* vm, uint16_t op1, uint16_t device_id); VM* vm, uint16_t op1, uint16_t device_id);
static inline int handle_interrupt(VM* vm, uint8_t int_id); static inline int handle_interrupt(VM* vm, uint8_t int_id);
static inline int jump_to_interrupt_handler(VM* vm, uint8_t int_id); static inline int jump_to_interrupt_handler(VM* vm, uint8_t int_id);
static inline void interrupt_return(VM* vm);
static inline void maybe_update_vcd(VM* vm, uint16_t addr); static inline void maybe_update_vcd(VM* vm, uint16_t addr);
static inline uint16_t eat_uint16(VM* vm); static inline uint16_t eat_uint16(VM* vm);
static inline uint16_t read_seg_uint16(VM* vm, uint16_t ptr); static inline uint16_t read_seg_uint16(VM* vm, uint16_t ptr);
@ -57,9 +56,10 @@ void vm_start(Drive* boot_drive, IODevice* io_device)
VM* vm = &vm_inst; VM* vm = &vm_inst;
uint16_t* rip = &vm->regs[Rip]; uint16_t* rbp = &vm->regs[Rbp];
uint16_t* rsp = &vm->regs[Rsp]; uint16_t* rsp = &vm->regs[Rsp];
uint16_t* rfl = &vm->regs[Rfl]; uint16_t* rfl = &vm->regs[Rfl];
uint16_t* rip = &vm->regs[Rip];
uint16_t* rcs = &vm->regs[Rcs]; uint16_t* rcs = &vm->regs[Rcs];
const uint16_t bootloader_size = 512; const uint16_t bootloader_size = 512;
@ -72,10 +72,10 @@ void vm_start(Drive* boot_drive, IODevice* io_device)
uint16_t ins = eat_uint16(vm); uint16_t ins = eat_uint16(vm);
Op op = ins_op(ins); Op op = ins_op(ins);
/*printf("[%3d] = %3d %s\n", *rip - 2, op, op_str(op));*/ // printf("[%3d] = %3d %s\n", *rip - 2, op, op_str(op));
if (*rip >= 300) { if (*rip >= 1024) {
printf("killed: rip >= 200\n"); printf("killed: rip >= 1024\n");
exit(0); exit(0);
} }
@ -224,6 +224,46 @@ void vm_start(Drive* boot_drive, IODevice* io_device)
handle_device_write(vm, op1, device_id); handle_device_write(vm, op1, device_id);
break; break;
} }
case Op_Call: {
bool is_far_call = ins >> 13 & 1;
uint16_t op1 = ins_op1_or_imm(vm, ins);
if (is_far_call) {
uint16_t op2 = ins_reg_val_or_imm(vm, ins, 14, 7, 0x7);
*rsp += 2;
*(uint16_t*)&vm->mem[*rsp] = *rcs;
*rsp += 2;
*(uint16_t*)&vm->mem[*rsp] = *rip;
*rip = op1;
*rcs = op2;
} else {
*rsp += 2;
*(uint16_t*)&vm->mem[*rsp] = *rip;
*rip = op1;
}
break;
}
case Op_Ret: {
bool is_far_return = ins >> 6 & 1;
if (is_far_return) {
*rip = *(uint16_t*)&vm->mem[*rsp];
*rsp -= 2;
*rcs = *(uint16_t*)&vm->mem[*rsp];
*rsp -= 2;
} else {
*rip = *(uint16_t*)&vm->mem[*rsp];
*rsp -= 2;
}
break;
}
case Op_Lit: { case Op_Lit: {
uint16_t op2 = ins_op1_or_imm(vm, ins); uint16_t op2 = ins_op1_or_imm(vm, ins);
vm->int_table = op2; vm->int_table = op2;
@ -238,10 +278,6 @@ void vm_start(Drive* boot_drive, IODevice* io_device)
} }
break; break;
} }
case Op_IRet: {
interrupt_return(vm);
break;
}
case Op_Or: case Op_Or:
case Op_Xor: case Op_Xor:
@ -440,18 +476,6 @@ static inline int jump_to_interrupt_handler(VM* vm, uint8_t int_id)
return 0; return 0;
} }
static inline void interrupt_return(VM* vm)
{
uint16_t* rsp = &vm->regs[Rsp];
uint16_t* rip = &vm->regs[Rip];
uint16_t* rcs = &vm->regs[Rcs];
*rip = *(uint16_t*)&vm->mem[*rsp];
*rsp -= 2;
*rcs = *(uint16_t*)&vm->mem[*rsp];
*rsp -= 2;
}
static inline void maybe_update_vcd(VM* vm, uint16_t addr) static inline void maybe_update_vcd(VM* vm, uint16_t addr)
{ {
if (!vm->io_device) if (!vm->io_device)
@ -552,12 +576,14 @@ const char* op_str(Op op)
return "in"; return "in";
case Op_Out: case Op_Out:
return "out"; return "out";
case Op_Call:
return "call";
case Op_Ret:
return "ret";
case Op_Lit: case Op_Lit:
return "lit"; return "lit";
case Op_Int: case Op_Int:
return "int"; return "int";
case Op_IRet:
return "iret";
case Op_Or: case Op_Or:
return "or"; return "or";
case Op_Xor: case Op_Xor:

View File

@ -36,9 +36,10 @@ typedef enum {
Op_Mov16, Op_Mov16,
Op_In, Op_In,
Op_Out, Op_Out,
Op_Call,
Op_Ret,
Op_Lit, Op_Lit,
Op_Int, Op_Int,
Op_IRet,
Op_Or, Op_Or,
Op_Xor, Op_Xor,
Op_And, Op_And,