diff --git a/.gitignore b/.gitignore index 919c8cc..11a2b81 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -main.exe +build test-dump-asm.o test-dump.asm -test-input.o +test-input.o \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index d722921..413fa48 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -5,7 +5,8 @@ "includePath": [ "${workspaceFolder}/**", "C:/MinGW/include/**", - "src/**" + "src/**", + "${workspaceFolder}/emsdk/upstream/lib/clang/17/include/**" ], "defines": [ "_DEBUG", diff --git a/.vscode/settings.json b/.vscode/settings.json index 8535b32..f8a399a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,5 +8,6 @@ "errno.h": "c", "stdbool.h": "c", "sim8086.h": "c" - } + }, + "liveServer.settings.root": "./build/web" } \ No newline at end of file diff --git a/Makefile b/Makefile index dbb713b..e976cf4 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,19 @@ -CC=gcc CFLAGS=-g -Wall -.DEFAULT_GOAL := main +.PHONY := cli web clean serve-web -%: src/%.c - $(CC) -o $@ $< $(CFLAGS) +cli: src/cli.c + mkdir -p build + gcc -o build/cli.exe src/cli.c $(CFLAGS) + +web: src/web.c + rm -rf build/web + mkdir -p build/web + emcc -o build/web/sim8086.js src/web.c --no-entry -sEXPORTED_RUNTIME_METHODS=cwrap,AsciiToString -sEXPORTED_FUNCTIONS=_free,_malloc $(CFLAGS) + cp -r src/web/* build/web + +serve-web: + cd build/web && python -m http.server clean: - rm main.exe \ No newline at end of file + rm -r build \ No newline at end of file diff --git a/README.md b/README.md index 4b8e199..aa7bf55 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,23 @@ For [Computer, Enhance!](https://www.computerenhance.com/) Examples gotten from: https://github.com/cmuratori/computer_enhance/tree/main/perfaware/part1 +## Building & Running + +### CLI +```shell +make cli +./build/cli +``` + +### Web +```shell +# This assumes that you already have `emcc` in your path somewhere +make web +make serve-web +``` + +## Manual + 8086 reference manual: https://edge.edx.org/c4x/BITSPilani/EEE231/asset/8086_family_Users_Manual_1_.pdf Important pages in manual: * Registers - 24 diff --git a/src/main.c b/src/cli.c similarity index 98% rename from src/main.c rename to src/cli.c index 8d6aaf7..dcbd255 100644 --- a/src/main.c +++ b/src/cli.c @@ -5,12 +5,7 @@ #include #include "os.h" -#include "sim8086.h" - -#include "sim8086.c" -#include "sim8086_memory.c" -#include "sim8086_decoder.c" -#include "sim8086_simulator.c" +#include "sim8086/prelude.h" // TODO: refactor cli commands, there is a lot of repeating code for reading assemblies and compiling them. @@ -108,8 +103,7 @@ int dissassemble(FILE *src, FILE *dst) { } instruction_to_str(buff, sizeof(buff), &inst); - fprintf(dst, buff); - fprintf(dst, "\n"); + fprintf(dst, "%s\b", buff); } return 0; diff --git a/src/sim8086_decoder.c b/src/sim8086/decoder.c similarity index 100% rename from src/sim8086_decoder.c rename to src/sim8086/decoder.c diff --git a/src/sim8086_memory.c b/src/sim8086/memory.c similarity index 83% rename from src/sim8086_memory.c rename to src/sim8086/memory.c index b2d45c7..1158a39 100644 --- a/src/sim8086_memory.c +++ b/src/sim8086/memory.c @@ -1,8 +1,13 @@ -#include - // TODO: add error codes -int load_mem_from_stream(struct memory *mem, FILE *stream, u32 start) { +int load_mem_from_buff(struct memory *mem, u8 *buff, u16 buff_size, u16 start) +{ + if (start + buff_size > MEMORY_SIZE) return -1; + memcpy(mem->mem + start, buff, buff_size); + return 0; +} + +int load_mem_from_stream(struct memory *mem, FILE *stream, u16 start) { u32 offset = 0; while (true) { u8 byte = fgetc(stream); @@ -14,7 +19,7 @@ int load_mem_from_stream(struct memory *mem, FILE *stream, u32 start) { return offset; } -int load_mem_from_file(struct memory *mem, const char *filename, u32 start) { +int load_mem_from_file(struct memory *mem, const char *filename, u16 start) { FILE *stream = fopen(filename, "rb"); if (stream == NULL) { return -1; diff --git a/src/sim8086/prelude.h b/src/sim8086/prelude.h new file mode 100644 index 0000000..76d66bf --- /dev/null +++ b/src/sim8086/prelude.h @@ -0,0 +1,6 @@ +#include "sim8086.h" + +#include "utils.c" +#include "memory.c" +#include "decoder.c" +#include "simulator.c" \ No newline at end of file diff --git a/src/sim8086.h b/src/sim8086/sim8086.h similarity index 86% rename from src/sim8086.h rename to src/sim8086/sim8086.h index 406c2a8..4972083 100644 --- a/src/sim8086.h +++ b/src/sim8086/sim8086.h @@ -1,6 +1,8 @@ #include #include #include +#include +#include #define u32 uint32_t #define i32 int32_t @@ -9,8 +11,20 @@ #define u8 uint8_t #define i8 int8_t +#ifdef SIM8086_EMCC +#define panic(...) \ + emscripten_log(EM_LOG_ERROR, "PANIC(%s:%d): ", __FILE__, __LINE__); \ + emscripten_log(EM_LOG_ERROR, __VA_ARGS__); \ + abort() +#define todo(...) \ + emscripten_log(EM_LOG_WARN, "TODO(%s:%d): ", __FILE__, __LINE__); \ + emscripten_log(EM_LOG_WARN, __VA_ARGS__); \ + abort() +#else #define panic(...) fprintf(stderr, "PANIC(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort() #define todo(...) fprintf(stderr, "TODO(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort() +#endif + #define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0])) #define MEMORY_SIZE 65536 // 2^16 diff --git a/src/sim8086_simulator.c b/src/sim8086/simulator.c similarity index 100% rename from src/sim8086_simulator.c rename to src/sim8086/simulator.c diff --git a/src/sim8086.c b/src/sim8086/utils.c similarity index 100% rename from src/sim8086.c rename to src/sim8086/utils.c diff --git a/src/web.c b/src/web.c new file mode 100644 index 0000000..0c07caa --- /dev/null +++ b/src/web.c @@ -0,0 +1,66 @@ +#include + +#define SIM8086_EMCC +#include "sim8086/prelude.h" + +#define EXPORT EMSCRIPTEN_KEEPALIVE +#define dbg(...) emscripten_log(EM_LOG_CONSOLE, __VA_ARGS__) + +EXPORT struct memory memory_state; +EXPORT struct cpu_state cpu_state; +EXPORT struct instruction current_instruction; + +/* -------------------- Decoder ----------------------- */ + +EXPORT int decode_inst_at_ip() { + return decode_instruction(&memory_state, &cpu_state.ip, ¤t_instruction); +} + +EXPORT void get_inst_str(char *buff, size_t buff_size) { + instruction_to_str(buff, buff_size, ¤t_instruction); +} + +/* -------------------- Memory ----------------------- */ + +EXPORT int load_to_memory_state(u8 *assembly, u16 assembly_size, u16 start) { + return load_mem_from_buff(&memory_state, assembly, assembly_size, start); +} + +EXPORT u8 *get_memory_state_base() { + return memory_state.mem; +} + +EXPORT size_t get_memory_state_size(u8 *assembly, u16 assembly_size, u16 start) { + return MEMORY_SIZE; +} + +/* -------------------- CPU ----------------------- */ + +EXPORT void cpu_reset() +{ + memset(&cpu_state, 0, sizeof(cpu_state)); +} + +#define CPU_STATE_GETTER(field) EXPORT u16 cpu_get_##field() { return cpu_state.field; } +#define CPU_STATE_SETTER(field) EXPORT void cpu_set_##field(u16 value) { cpu_state.field = value; } +#define CPU_STATE_ACCESOR(field) CPU_STATE_SETTER(field) CPU_STATE_GETTER(field) + +CPU_STATE_ACCESOR(ip) +CPU_STATE_ACCESOR(ax) +CPU_STATE_ACCESOR(bx) +CPU_STATE_ACCESOR(cx) +CPU_STATE_ACCESOR(dx) +CPU_STATE_ACCESOR(sp) +CPU_STATE_ACCESOR(bp) +CPU_STATE_ACCESOR(si) +CPU_STATE_ACCESOR(di) + +EXPORT bool cpu_get_zero_flag() +{ + return cpu_state.flags.zero; +} + +EXPORT bool cpu_get_sign_flag() +{ + return cpu_state.flags.sign; +} \ No newline at end of file diff --git a/src/web/index.html b/src/web/index.html new file mode 100644 index 0000000..9c5f7d3 --- /dev/null +++ b/src/web/index.html @@ -0,0 +1,225 @@ + + + + + + sim8086.wasm + + + + + + + + +
+

sim8086.wasm

+
+
a
+
+
+ +
+
+
+ + + + + + + + + + +
+
+
+
+
+
+
+
+ + + + + \ No newline at end of file