seperate out asm and kern
This commit is contained in:
parent
b9a837e3c7
commit
335822afc6
14
Makefile
14
Makefile
@ -34,12 +34,22 @@ endif
|
|||||||
|
|
||||||
HEADERS = $(shell find . -name *.h)
|
HEADERS = $(shell find . -name *.h)
|
||||||
|
|
||||||
|
ASM_SOURCES = $(shell find asm/ -name *.c)
|
||||||
|
ASM_OBJECTS = $(patsubst %.c,build/%.o,$(ASM_SOURCES))
|
||||||
|
|
||||||
VM_SOURCES = $(shell find vm/ -name *.c)
|
VM_SOURCES = $(shell find vm/ -name *.c)
|
||||||
VM_OBJECTS = $(patsubst %.c,build/%.o,$(VM_SOURCES))
|
VM_OBJECTS = $(patsubst %.c,build/%.o,$(VM_SOURCES))
|
||||||
|
|
||||||
all: bin/vm
|
KERN_SOURCES = $(shell find kern/ -name *.c)
|
||||||
|
KERN_OBJECTS = $(patsubst %.c,build/%.o,$(KERN_SOURCES))
|
||||||
|
|
||||||
bin/vm: $(VM_OBJECTS)
|
all: bin/vm bin/build_disk_image
|
||||||
|
|
||||||
|
bin/vm: $(VM_OBJECTS) $(ASM_OBJECTS)
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CC) $^ -o $@ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
||||||
|
|
||||||
|
bin/build_disk_image: $(KERN_OBJECTS) $(ASM_OBJECTS)
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
$(CC) $^ -o $@ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
$(CC) $^ -o $@ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "asm.h"
|
#include "asm.h"
|
||||||
#include "vm.h"
|
#include "common/op_str.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -633,6 +633,9 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
|
|||||||
printf("done!\n");
|
printf("done!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(unres_labels);
|
||||||
|
free(res_labels);
|
||||||
|
|
||||||
return ip * 2;
|
return ip * 2;
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "vm.h"
|
#include "common/arch.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
69
common/arch.h
Normal file
69
common/arch.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
R0 = 0,
|
||||||
|
R1 = 1,
|
||||||
|
R2 = 2,
|
||||||
|
R3 = 3,
|
||||||
|
R4 = 4,
|
||||||
|
Rbp = 5,
|
||||||
|
Rsp = 6,
|
||||||
|
Rfl = 7,
|
||||||
|
Rcs = 8,
|
||||||
|
Rip = 9,
|
||||||
|
} Reg;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Fl_Zero,
|
||||||
|
Fl_Eq,
|
||||||
|
Fl_Be,
|
||||||
|
Fl_Lt,
|
||||||
|
Fl_Err,
|
||||||
|
Fl_Int,
|
||||||
|
Fl_Vcd,
|
||||||
|
} Flag;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Op_Nop,
|
||||||
|
Op_Hlt,
|
||||||
|
Op_Jmp,
|
||||||
|
Op_Jnz,
|
||||||
|
Op_Test,
|
||||||
|
Op_Cmp,
|
||||||
|
Op_Mov8,
|
||||||
|
Op_Mov16,
|
||||||
|
Op_In,
|
||||||
|
Op_Out,
|
||||||
|
Op_Call,
|
||||||
|
Op_Ret,
|
||||||
|
Op_Lit,
|
||||||
|
Op_Int,
|
||||||
|
Op_Or,
|
||||||
|
Op_Xor,
|
||||||
|
Op_And,
|
||||||
|
Op_Shl,
|
||||||
|
Op_RShl,
|
||||||
|
Op_Shr,
|
||||||
|
Op_RShr,
|
||||||
|
Op_Add,
|
||||||
|
Op_Sub,
|
||||||
|
Op_RSub,
|
||||||
|
Op_Mul,
|
||||||
|
Op_IMul,
|
||||||
|
Op_Div,
|
||||||
|
Op_IDiv,
|
||||||
|
Op_RDiv,
|
||||||
|
Op_RIDiv,
|
||||||
|
Op_Mod,
|
||||||
|
Op_RMod,
|
||||||
|
} Op;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Int_DiskRead = 0,
|
||||||
|
Int_DiskWrite = 1,
|
||||||
|
Int_Key = 32,
|
||||||
|
} VM_Int;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Device_Keyboard,
|
||||||
|
} VM_Device;
|
74
common/op_str.h
Normal file
74
common/op_str.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "arch.h"
|
||||||
|
|
||||||
|
static inline const char* op_str(Op op)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case Op_Nop:
|
||||||
|
return "nop";
|
||||||
|
case Op_Hlt:
|
||||||
|
return "hlt";
|
||||||
|
case Op_Jmp:
|
||||||
|
return "jmp";
|
||||||
|
case Op_Jnz:
|
||||||
|
return "jnz";
|
||||||
|
case Op_Test:
|
||||||
|
return "test";
|
||||||
|
case Op_Cmp:
|
||||||
|
return "cmp";
|
||||||
|
case Op_Mov8:
|
||||||
|
return "mov8";
|
||||||
|
case Op_Mov16:
|
||||||
|
return "mov16";
|
||||||
|
case Op_In:
|
||||||
|
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_Or:
|
||||||
|
return "or";
|
||||||
|
case Op_Xor:
|
||||||
|
return "xor";
|
||||||
|
case Op_And:
|
||||||
|
return "and";
|
||||||
|
case Op_Shl:
|
||||||
|
return "shl";
|
||||||
|
case Op_RShl:
|
||||||
|
return "rshl";
|
||||||
|
case Op_Shr:
|
||||||
|
return "shr";
|
||||||
|
case Op_RShr:
|
||||||
|
return "rshr";
|
||||||
|
case Op_Add:
|
||||||
|
return "add";
|
||||||
|
case Op_Sub:
|
||||||
|
return "sub";
|
||||||
|
case Op_RSub:
|
||||||
|
return "rsub";
|
||||||
|
case Op_Mul:
|
||||||
|
return "mul";
|
||||||
|
case Op_IMul:
|
||||||
|
return "imul";
|
||||||
|
case Op_Div:
|
||||||
|
return "div";
|
||||||
|
case Op_IDiv:
|
||||||
|
return "idiv";
|
||||||
|
case Op_RDiv:
|
||||||
|
return "rdiv";
|
||||||
|
case Op_RIDiv:
|
||||||
|
return "ridiv";
|
||||||
|
case Op_Mod:
|
||||||
|
return "mod";
|
||||||
|
case Op_RMod:
|
||||||
|
return "rmod";
|
||||||
|
}
|
||||||
|
return "---";
|
||||||
|
}
|
13
common/video_character_display.h
Normal file
13
common/video_character_display.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define vcd_ch_width 8
|
||||||
|
#define vcd_ch_height 8
|
||||||
|
static const int vcd_width_in_ch = 40;
|
||||||
|
static const int vcd_height_in_ch = 12;
|
||||||
|
|
||||||
|
static const int vcd_px_width = 4;
|
||||||
|
static const int vcd_px_height = 8;
|
||||||
|
static const int vcd_width_in_px
|
||||||
|
= vcd_width_in_ch * vcd_ch_width * vcd_px_width;
|
||||||
|
static const int vcd_height_in_px
|
||||||
|
= vcd_height_in_ch * vcd_ch_height * vcd_px_height;
|
215
kern/main.c
Normal file
215
kern/main.c
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
#include "asm/asm.h"
|
||||||
|
#include "common/video_character_display.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
const size_t block_size = 512;
|
||||||
|
const size_t block_amount = 32;
|
||||||
|
|
||||||
|
void write_program(FILE* fp);
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
FILE* fp = fopen("build/image", "wb");
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(
|
||||||
|
stderr, "error: could not open build/image: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("clearing disk...\n");
|
||||||
|
uint8_t* data = calloc(block_size, 1);
|
||||||
|
for (size_t i = 0; i < block_amount; ++i) {
|
||||||
|
fwrite(data, 1, block_size, fp);
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
printf("done!\n");
|
||||||
|
|
||||||
|
write_program(fp);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_program(FILE* fp)
|
||||||
|
{
|
||||||
|
int label_ids = 0;
|
||||||
|
|
||||||
|
int main_loop = label_ids++;
|
||||||
|
int interrupt_table = label_ids++;
|
||||||
|
int keyboard_interrupt = label_ids++;
|
||||||
|
int keyboard_interrupt_0 = label_ids++;
|
||||||
|
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++;
|
||||||
|
|
||||||
|
#define L(LABEL) s_label(LABEL)
|
||||||
|
|
||||||
|
Line program_asm[] = {
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
// rsp points *at* the top element
|
||||||
|
s_mov16_r_i(Rbp, 2048),
|
||||||
|
s_mov16_r_i(Rsp, 2048 - 2),
|
||||||
|
|
||||||
|
s_lit_l(interrupt_table),
|
||||||
|
s_or_i(Rfl, Rfl, 1 << Fl_Int),
|
||||||
|
|
||||||
|
s_or_i(Rfl, Rfl, 1 << Fl_Vcd),
|
||||||
|
|
||||||
|
s_mov16_r_i(R0, 512),
|
||||||
|
s_mov16_r_i(R1, 1),
|
||||||
|
s_int(Int_DiskRead),
|
||||||
|
|
||||||
|
L(main_loop),
|
||||||
|
s_hlt(),
|
||||||
|
s_jmp_l(main_loop),
|
||||||
|
|
||||||
|
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),
|
||||||
|
s_mov16_r_r(Rbp, Rsp),
|
||||||
|
s_push_r(R0),
|
||||||
|
s_push_r(R1),
|
||||||
|
s_push_r(R2),
|
||||||
|
s_push_r(R3),
|
||||||
|
|
||||||
|
s_in_i(R0, Device_Keyboard),
|
||||||
|
|
||||||
|
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_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_call_l(put_char),
|
||||||
|
s_jmp_l(keyboard_interrupt_4),
|
||||||
|
|
||||||
|
L(keyboard_interrupt_1),
|
||||||
|
s_mov16_r_ml(R1, screen_x),
|
||||||
|
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),
|
||||||
|
s_mov16_r_r(Rsp, Rbp),
|
||||||
|
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, vcd_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, vcd_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),
|
||||||
|
s_data_i(0),
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t program_asm_size = sizeof(program_asm) / sizeof(program_asm[0]);
|
||||||
|
|
||||||
|
uint16_t* program = calloc(512 * 2, sizeof(uint16_t));
|
||||||
|
|
||||||
|
printf("assembling program...\n");
|
||||||
|
uint16_t program_size
|
||||||
|
= assemble_to_binary(program, program_asm, program_asm_size);
|
||||||
|
printf("done!\n");
|
||||||
|
printf("program size = %d\n", program_size);
|
||||||
|
|
||||||
|
printf("writing program to disk...\n");
|
||||||
|
fwrite(program, sizeof(uint16_t), program_size, fp);
|
||||||
|
printf("done!\n");
|
||||||
|
|
||||||
|
free(program);
|
||||||
|
}
|
45
vm/main.c
45
vm/main.c
@ -1,5 +1,7 @@
|
|||||||
|
#include "asm/asm.h"
|
||||||
|
#include "common/op_str.h"
|
||||||
|
#include "common/video_character_display.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "vm/asm.h"
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_error.h>
|
#include <SDL2/SDL_error.h>
|
||||||
#include <SDL2/SDL_events.h>
|
#include <SDL2/SDL_events.h>
|
||||||
@ -75,16 +77,6 @@ Interrupt int_queue_pop(InterruptQueue* queue)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ch_width 8
|
|
||||||
#define ch_height 8
|
|
||||||
static const int width_in_ch = 40;
|
|
||||||
static const int height_in_ch = 12;
|
|
||||||
|
|
||||||
static const int px_width = 4;
|
|
||||||
static const int px_height = 8;
|
|
||||||
static const int width_in_px = width_in_ch * ch_width * px_width;
|
|
||||||
static const int height_in_px = height_in_ch * ch_height * px_height;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
IODevice io_device;
|
IODevice io_device;
|
||||||
|
|
||||||
@ -121,7 +113,7 @@ int sdldevice_construct(SdlDevice* device)
|
|||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
SDL_Renderer* renderer;
|
SDL_Renderer* renderer;
|
||||||
res = SDL_CreateWindowAndRenderer(
|
res = SDL_CreateWindowAndRenderer(
|
||||||
width_in_px, height_in_px, 0, &window, &renderer);
|
vcd_width_in_px, vcd_height_in_px, 0, &window, &renderer);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"error: could not create window/renderer: %s\n",
|
"error: could not create window/renderer: %s\n",
|
||||||
@ -132,8 +124,8 @@ int sdldevice_construct(SdlDevice* device)
|
|||||||
SDL_Texture* buffer_texture = SDL_CreateTexture(renderer,
|
SDL_Texture* buffer_texture = SDL_CreateTexture(renderer,
|
||||||
SDL_PIXELFORMAT_RGBA32,
|
SDL_PIXELFORMAT_RGBA32,
|
||||||
SDL_TEXTUREACCESS_STREAMING,
|
SDL_TEXTUREACCESS_STREAMING,
|
||||||
width_in_px,
|
vcd_width_in_px,
|
||||||
height_in_px);
|
vcd_height_in_px);
|
||||||
if (buffer_texture == NULL) {
|
if (buffer_texture == NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"error: could not create buffer texture: %s\n",
|
"error: could not create buffer texture: %s\n",
|
||||||
@ -205,22 +197,23 @@ void sdldevice_set_char(IODevice* io_device, uint16_t offset, uint8_t value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int ch_y = 0; ch_y < ch_height; ++ch_y) {
|
for (int ch_y = 0; ch_y < vcd_ch_height; ++ch_y) {
|
||||||
for (int ch_x = 0; ch_x < ch_width; ++ch_x) {
|
for (int ch_x = 0; ch_x < vcd_ch_width; ++ch_x) {
|
||||||
bool ch
|
bool ch = charset[value]
|
||||||
= charset[value] >> (ch_y * ch_width + (ch_width - ch_x - 1))
|
>> (ch_y * vcd_ch_width + (vcd_ch_width - ch_x - 1))
|
||||||
& 1;
|
& 1;
|
||||||
|
|
||||||
for (int px_y = 0; px_y < px_height; ++px_y) {
|
for (int px_y = 0; px_y < vcd_px_height; ++px_y) {
|
||||||
for (int px_x = 0; px_x < px_width; ++px_x) {
|
for (int px_x = 0; px_x < vcd_px_width; ++px_x) {
|
||||||
|
|
||||||
int x = (offset % width_in_ch * ch_width + ch_x) * px_width
|
int x = (offset % vcd_width_in_ch * vcd_ch_width + ch_x)
|
||||||
|
* vcd_px_width
|
||||||
+ px_x;
|
+ px_x;
|
||||||
int y
|
int y = (offset / vcd_width_in_ch * vcd_ch_height + ch_y)
|
||||||
= (offset / width_in_ch * ch_height + ch_y) * px_height
|
* vcd_px_height
|
||||||
+ px_y;
|
+ px_y;
|
||||||
|
|
||||||
buffer[y * width_in_px + x] = ch
|
buffer[y * vcd_width_in_px + x] = ch
|
||||||
? (SDL_Color) { 0xff, 0xff, 0xff, 0xff }
|
? (SDL_Color) { 0xff, 0xff, 0xff, 0xff }
|
||||||
: (SDL_Color) { 0x00, 0x00, 0x00, 0xff };
|
: (SDL_Color) { 0x00, 0x00, 0x00, 0xff };
|
||||||
}
|
}
|
||||||
@ -507,7 +500,7 @@ int main(void)
|
|||||||
s_push_r(R2),
|
s_push_r(R2),
|
||||||
|
|
||||||
s_mov16_r_ml(R2, screen_y),
|
s_mov16_r_ml(R2, screen_y),
|
||||||
s_mul_i(R2, R2, width_in_ch),
|
s_mul_i(R2, R2, vcd_width_in_ch),
|
||||||
s_mov16_r_ml(R1, screen_x),
|
s_mov16_r_ml(R1, screen_x),
|
||||||
s_add_i(R1, R1, 0x0c00),
|
s_add_i(R1, R1, 0x0c00),
|
||||||
s_add_r(R1, R1, R2),
|
s_add_r(R1, R1, R2),
|
||||||
@ -517,7 +510,7 @@ int main(void)
|
|||||||
s_add_i(R1, R1, 1),
|
s_add_i(R1, R1, 1),
|
||||||
s_mov16_ml_r(screen_x, R1),
|
s_mov16_ml_r(screen_x, R1),
|
||||||
|
|
||||||
s_cmp_i(R1, width_in_ch),
|
s_cmp_i(R1, vcd_width_in_ch),
|
||||||
s_mov16_r_r(R2, Rfl),
|
s_mov16_r_r(R2, Rfl),
|
||||||
s_and_i(R2, R2, 1 << Fl_Eq),
|
s_and_i(R2, R2, 1 << Fl_Eq),
|
||||||
s_jnz_l(R2, put_char_0),
|
s_jnz_l(R2, put_char_0),
|
||||||
|
72
vm/vm.c
72
vm/vm.c
@ -1,4 +1,5 @@
|
|||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
#include "common/arch.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -552,74 +553,3 @@ static inline uint16_t ins_op2_or_imm(VM* vm, uint16_t ins)
|
|||||||
{
|
{
|
||||||
return ins_reg_val_or_imm(vm, ins, 6, 7, 0x7);
|
return ins_reg_val_or_imm(vm, ins, 6, 7, 0x7);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* op_str(Op op)
|
|
||||||
{
|
|
||||||
switch (op) {
|
|
||||||
case Op_Nop:
|
|
||||||
return "nop";
|
|
||||||
case Op_Hlt:
|
|
||||||
return "hlt";
|
|
||||||
case Op_Jmp:
|
|
||||||
return "jmp";
|
|
||||||
case Op_Jnz:
|
|
||||||
return "jnz";
|
|
||||||
case Op_Test:
|
|
||||||
return "test";
|
|
||||||
case Op_Cmp:
|
|
||||||
return "cmp";
|
|
||||||
case Op_Mov8:
|
|
||||||
return "mov8";
|
|
||||||
case Op_Mov16:
|
|
||||||
return "mov16";
|
|
||||||
case Op_In:
|
|
||||||
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_Or:
|
|
||||||
return "or";
|
|
||||||
case Op_Xor:
|
|
||||||
return "xor";
|
|
||||||
case Op_And:
|
|
||||||
return "and";
|
|
||||||
case Op_Shl:
|
|
||||||
return "shl";
|
|
||||||
case Op_RShl:
|
|
||||||
return "rshl";
|
|
||||||
case Op_Shr:
|
|
||||||
return "shr";
|
|
||||||
case Op_RShr:
|
|
||||||
return "rshr";
|
|
||||||
case Op_Add:
|
|
||||||
return "add";
|
|
||||||
case Op_Sub:
|
|
||||||
return "sub";
|
|
||||||
case Op_RSub:
|
|
||||||
return "rsub";
|
|
||||||
case Op_Mul:
|
|
||||||
return "mul";
|
|
||||||
case Op_IMul:
|
|
||||||
return "imul";
|
|
||||||
case Op_Div:
|
|
||||||
return "div";
|
|
||||||
case Op_IDiv:
|
|
||||||
return "idiv";
|
|
||||||
case Op_RDiv:
|
|
||||||
return "rdiv";
|
|
||||||
case Op_RIDiv:
|
|
||||||
return "ridiv";
|
|
||||||
case Op_Mod:
|
|
||||||
return "mod";
|
|
||||||
case Op_RMod:
|
|
||||||
return "rmod";
|
|
||||||
}
|
|
||||||
return "---";
|
|
||||||
}
|
|
||||||
|
70
vm/vm.h
70
vm/vm.h
@ -2,74 +2,6 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
R0 = 0,
|
|
||||||
R1 = 1,
|
|
||||||
R2 = 2,
|
|
||||||
R3 = 3,
|
|
||||||
R4 = 4,
|
|
||||||
Rbp = 5,
|
|
||||||
Rsp = 6,
|
|
||||||
Rfl = 7,
|
|
||||||
Rcs = 8,
|
|
||||||
Rip = 9,
|
|
||||||
} Reg;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
Fl_Zero,
|
|
||||||
Fl_Eq,
|
|
||||||
Fl_Be,
|
|
||||||
Fl_Lt,
|
|
||||||
Fl_Err,
|
|
||||||
Fl_Int,
|
|
||||||
Fl_Vcd,
|
|
||||||
} Flag;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
Op_Nop,
|
|
||||||
Op_Hlt,
|
|
||||||
Op_Jmp,
|
|
||||||
Op_Jnz,
|
|
||||||
Op_Test,
|
|
||||||
Op_Cmp,
|
|
||||||
Op_Mov8,
|
|
||||||
Op_Mov16,
|
|
||||||
Op_In,
|
|
||||||
Op_Out,
|
|
||||||
Op_Call,
|
|
||||||
Op_Ret,
|
|
||||||
Op_Lit,
|
|
||||||
Op_Int,
|
|
||||||
Op_Or,
|
|
||||||
Op_Xor,
|
|
||||||
Op_And,
|
|
||||||
Op_Shl,
|
|
||||||
Op_RShl,
|
|
||||||
Op_Shr,
|
|
||||||
Op_RShr,
|
|
||||||
Op_Add,
|
|
||||||
Op_Sub,
|
|
||||||
Op_RSub,
|
|
||||||
Op_Mul,
|
|
||||||
Op_IMul,
|
|
||||||
Op_Div,
|
|
||||||
Op_IDiv,
|
|
||||||
Op_RDiv,
|
|
||||||
Op_RIDiv,
|
|
||||||
Op_Mod,
|
|
||||||
Op_RMod,
|
|
||||||
} Op;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
Int_DiskRead = 0,
|
|
||||||
Int_DiskWrite = 1,
|
|
||||||
Int_Key = 32,
|
|
||||||
} VM_Int;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
Device_Keyboard,
|
|
||||||
} VM_Device;
|
|
||||||
|
|
||||||
typedef struct Drive Drive;
|
typedef struct Drive Drive;
|
||||||
typedef void (*DriveReadFn)(Drive* drive, uint8_t* block, uint16_t i);
|
typedef void (*DriveReadFn)(Drive* drive, uint8_t* block, uint16_t i);
|
||||||
typedef void (*DriveWriteFn)(Drive* drive, const uint8_t* block, uint16_t i);
|
typedef void (*DriveWriteFn)(Drive* drive, const uint8_t* block, uint16_t i);
|
||||||
@ -114,5 +46,3 @@ struct IODevice {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void vm_start(Drive* boot_drive, IODevice* io_device);
|
void vm_start(Drive* boot_drive, IODevice* io_device);
|
||||||
|
|
||||||
const char* op_str(Op op);
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user