diff --git a/Session.vim b/Session.vim index 3c8eae5..d936148 100644 --- a/Session.vim +++ b/Session.vim @@ -13,13 +13,14 @@ if &shortmess =~ 'A' else set shortmess=aoO endif -badd +437 vm/main.c -badd +48 Makefile -badd +10 vm/vm.h -badd +181 vm/vm.c -badd +14 vm/asm.h -badd +263 vm/asm.c +badd +440 vm/main.c +badd +11 Makefile +badd +12 vm/vm.h +badd +262 vm/vm.c +badd +91 vm/asm.h +badd +378 vm/asm.c badd +747 ~/.config/nvim/init.lua +badd +10 compile_flags.txt argglobal %argdel $argadd vm/main.c @@ -28,7 +29,7 @@ tabnew +setlocal\ bufhidden=wipe tabnew +setlocal\ bufhidden=wipe tabnew +setlocal\ bufhidden=wipe tabrewind -edit vm/main.c +edit Makefile let s:save_splitbelow = &splitbelow let s:save_splitright = &splitright set splitbelow splitright @@ -45,9 +46,10 @@ set winminheight=0 set winheight=1 set winminwidth=0 set winwidth=1 -exe 'vert 1resize ' . ((&columns * 123 + 128) / 256) -exe 'vert 2resize ' . ((&columns * 132 + 128) / 256) +exe 'vert 1resize ' . ((&columns * 71 + 128) / 256) +exe 'vert 2resize ' . ((&columns * 184 + 128) / 256) argglobal +balt compile_flags.txt setlocal fdm=manual setlocal fde=0 setlocal fmr={{{,}}} @@ -58,19 +60,19 @@ setlocal fdn=20 setlocal fen silent! normal! zE 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 keepjumps exe s:l normal! zt -keepjumps 437 -normal! 012| +keepjumps 11 +normal! 027| wincmd w 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' - silent file Makefile + silent file vm/main.c endif -balt vm/main.c +balt vm/asm.c setlocal fdm=manual setlocal fde=0 setlocal fmr={{{,}}} @@ -81,15 +83,16 @@ setlocal fdn=20 setlocal fen silent! normal! zE 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 keepjumps exe s:l normal! zt -keepjumps 15 -normal! 0 +keepjumps 440 +normal! 010| wincmd w -exe 'vert 1resize ' . ((&columns * 123 + 128) / 256) -exe 'vert 2resize ' . ((&columns * 132 + 128) / 256) +2wincmd w +exe 'vert 1resize ' . ((&columns * 71 + 128) / 256) +exe 'vert 2resize ' . ((&columns * 184 + 128) / 256) tabnext edit vm/vm.h let s:save_splitbelow = &splitbelow @@ -122,12 +125,12 @@ setlocal fdn=20 setlocal fen silent! normal! zE 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 keepjumps exe s:l normal! zt -keepjumps 10 -normal! 011| +keepjumps 12 +normal! 06| wincmd w argglobal 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 silent! normal! zE 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 keepjumps exe s:l normal! zt -keepjumps 83 -normal! 021| +keepjumps 262 +normal! 0 wincmd w exe 'vert 1resize ' . ((&columns * 93 + 128) / 256) exe 'vert 2resize ' . ((&columns * 162 + 128) / 256) @@ -186,12 +189,12 @@ setlocal fdn=20 setlocal fen silent! normal! zE 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 keepjumps exe s:l normal! zt -keepjumps 53 -normal! 0 +keepjumps 91 +normal! 045| wincmd w argglobal 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 silent! normal! zE 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 keepjumps exe s:l normal! zt -keepjumps 265 -normal! 032| +keepjumps 146 +normal! 019| wincmd w exe 'vert 1resize ' . ((&columns * 87 + 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 2resize ' . ((&columns * 128 + 128) / 256) argglobal -balt vm/asm.h +balt vm/vm.c setlocal fdm=manual setlocal fde=0 setlocal fmr={{{,}}} @@ -250,12 +253,12 @@ setlocal fdn=20 setlocal fen silent! normal! zE 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 keepjumps exe s:l normal! zt -keepjumps 265 -normal! 031| +keepjumps 369 +normal! 042| wincmd w argglobal 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 silent! normal! zE 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 keepjumps exe s:l normal! zt -keepjumps 123 -normal! 0 +keepjumps 228 +normal! 01| wincmd w exe 'vert 1resize ' . ((&columns * 127 + 128) / 256) exe 'vert 2resize ' . ((&columns * 128 + 128) / 256) -tabnext 3 +tabnext 1 set stal=1 if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' silent exe 'bwipe ' . s:wipebuf diff --git a/vm/asm.c b/vm/asm.c index 3e595a1..68c8642 100644 --- a/vm/asm.c +++ b/vm/asm.c @@ -149,6 +149,24 @@ Line s_in_i(Reg dst_reg, uint16_t 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) { return (Line) { @@ -187,9 +205,29 @@ Line s_iret(void) } DEFINE_BINARY_I(or, Or) +DEFINE_BINARY_I(xor, Xor) DEFINE_BINARY_I(and, And) DEFINE_BINARY_I(add, Add) 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_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 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; @@ -443,6 +481,31 @@ void assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size) out[ip++] = op1; 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: { 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; } case LineTy_IRet: { - out[ip++] = Op_IRet; + uint32_t ins = Op_Ret; + ins |= 1 << 6; + out[ip++] = (uint16_t)ins; break; } case LineTy_Or_Imm: + case LineTy_Xor_Imm: case LineTy_And_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 op1 = line->op1.reg; 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; 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) { @@ -547,6 +632,8 @@ void assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size) if (debug) { printf("done!\n"); } + + return ip * 2; } 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) { case LineTy_Or_Imm: + case LineTy_Or_Reg: return Op_Or; + case LineTy_Xor_Imm: + case LineTy_Xor_Reg: + return Op_Xor; case LineTy_And_Imm: + case LineTy_And_Reg: return Op_And; case LineTy_Add_Imm: + case LineTy_Add_Reg: return Op_Add; case LineTy_Sub_Imm: + case LineTy_Sub_Reg: return Op_Sub; + case LineTy_Mul_Imm: + case LineTy_Mul_Reg: + return Op_Mul; default: fprintf(stderr, "error: line type '%d' not handled\n", ty); exit(1); diff --git a/vm/asm.h b/vm/asm.h index de45593..c706b5b 100644 --- a/vm/asm.h +++ b/vm/asm.h @@ -24,14 +24,25 @@ typedef enum { LineTy_Mov16_MemReg_Reg, LineTy_Mov16_MemLabel_Reg, LineTy_In_Imm, + LineTy_Call_Imm, + LineTy_Call_Label, + LineTy_Ret, LineTy_Lit_Imm, LineTy_Lit_Label, LineTy_Int, LineTy_IRet, LineTy_Or_Imm, + LineTy_Xor_Imm, LineTy_And_Imm, LineTy_Add_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; 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_ml_r(int dst_label, Reg op2_reg); 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_l(int op1_label); Line s_int(uint8_t int_id); Line s_iret(void); 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_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_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_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) \ (VAL) >> 7 & 1 ? '1' : '0', (VAL) >> 6 & 1 ? '1' : '0', \ diff --git a/vm/main.c b/vm/main.c index 31114c3..9fb8136 100644 --- a/vm/main.c +++ b/vm/main.c @@ -269,7 +269,8 @@ static inline bool is_exit_event(SDL_Event* event) return event->type == SDL_QUIT || (event->type == SDL_KEYDOWN && 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) @@ -392,6 +393,10 @@ int main(void) int keyboard_interrupt_1 = label_ids++; int keyboard_interrupt_2 = 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_y = label_ids++; @@ -399,7 +404,6 @@ int main(void) Line program_asm[] = { // clang-format off - s_nop(), // rsp points *at* the top element s_mov16_r_i(Rbp, 2048), @@ -417,12 +421,13 @@ int main(void) L(main_loop), s_hlt(), s_jmp_l(main_loop), - s_nop(), + L(interrupt_table), // size s_data_i(1), s_data_l(keyboard_interrupt), s_nop(), + L(keyboard_interrupt), s_and_i(Rfl, Rfl, (uint16_t)~(1 << Fl_Int)), s_push_r(Rbp), @@ -430,28 +435,63 @@ int main(void) s_push_r(R0), s_push_r(R1), s_push_r(R2), + s_push_r(R3), - // read keyboard port 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_and_i(R1, R1, 1 << Fl_Eq), 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), 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), s_mov16_r_ml(R1, screen_x), - s_add_i(R1, R1, 0x0c00), - s_mov8_mr_r(R1, R0), - - s_mov16_r_ml(R1, screen_x), - s_add_i(R1, R1, 1), + s_cmp_i(R1, 0), + s_mov16_r_r(R2, Rfl), + s_and_i(R2, R2, 1 << Fl_Eq), + s_jnz_l(R2, keyboard_interrupt_4), + s_sub_i(R1, R1, 1), 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(R1), s_pop_r(R0), @@ -459,6 +499,45 @@ int main(void) s_pop_r(Rbp), s_or_i(Rfl, Rfl, 1 << Fl_Int), 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), s_data_i(0), L(screen_y), @@ -470,7 +549,9 @@ int main(void) size_t program_asm_size = sizeof(program_asm) / sizeof(program_asm[0]); 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); diff --git a/vm/vm.c b/vm/vm.c index 2f3eb82..67822ec 100644 --- a/vm/vm.c +++ b/vm/vm.c @@ -22,7 +22,6 @@ static inline void handle_device_write( VM* vm, uint16_t op1, uint16_t device_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 void interrupt_return(VM* vm); static inline void maybe_update_vcd(VM* vm, uint16_t addr); static inline uint16_t eat_uint16(VM* vm); 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; - uint16_t* rip = &vm->regs[Rip]; + uint16_t* rbp = &vm->regs[Rbp]; uint16_t* rsp = &vm->regs[Rsp]; uint16_t* rfl = &vm->regs[Rfl]; + uint16_t* rip = &vm->regs[Rip]; uint16_t* rcs = &vm->regs[Rcs]; 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); 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) { - printf("killed: rip >= 200\n"); + if (*rip >= 1024) { + printf("killed: rip >= 1024\n"); exit(0); } @@ -224,6 +224,46 @@ void vm_start(Drive* boot_drive, IODevice* io_device) handle_device_write(vm, op1, device_id); 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: { uint16_t op2 = ins_op1_or_imm(vm, ins); vm->int_table = op2; @@ -238,10 +278,6 @@ void vm_start(Drive* boot_drive, IODevice* io_device) } break; } - case Op_IRet: { - interrupt_return(vm); - break; - } case Op_Or: case Op_Xor: @@ -440,18 +476,6 @@ static inline int jump_to_interrupt_handler(VM* vm, uint8_t int_id) 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) { if (!vm->io_device) @@ -552,12 +576,14 @@ const char* op_str(Op op) return "in"; case Op_Out: return "out"; + case Op_Call: + return "call"; + case Op_Ret: + return "ret"; case Op_Lit: return "lit"; case Op_Int: return "int"; - case Op_IRet: - return "iret"; case Op_Or: return "or"; case Op_Xor: diff --git a/vm/vm.h b/vm/vm.h index 2b6f2dc..79a4904 100644 --- a/vm/vm.h +++ b/vm/vm.h @@ -36,9 +36,10 @@ typedef enum { Op_Mov16, Op_In, Op_Out, + Op_Call, + Op_Ret, Op_Lit, Op_Int, - Op_IRet, Op_Or, Op_Xor, Op_And,