From ba72dae68f179f2b5fa01424c344213b5260e7fa Mon Sep 17 00:00:00 2001 From: Timerix Date: Fri, 18 Apr 2025 02:46:46 +0500 Subject: [PATCH] refactored registers --- README.md | 86 +++++++++++----- TODO.md | 6 +- examples/conditional_jump.tasm | 12 +-- examples/loop.tasm | 8 +- examples/stdout.tasm | 10 +- examples/window.tasm | 4 +- src/VM/VM.c | 27 ++++- src/VM/VM.h | 32 ++---- src/compiler/Compiler.c | 26 ++--- src/instructions/impl/JMP.c | 36 ++++--- src/instructions/impl/MOVC.c | 17 ++-- src/instructions/impl/MOVR.c | 17 ++-- src/instructions/impl/SYS.c | 34 +++---- src/instructions/impl/impl_macros.h | 60 +++++++---- src/instructions/impl/logical_operators.c | 115 ++++++---------------- src/instructions/impl/math_operators.c | 36 +------ src/instructions/registers.c | 81 +++++++++++++-- src/instructions/registers.h | 34 +++++-- 18 files changed, 359 insertions(+), 282 deletions(-) diff --git a/README.md b/README.md index 870a2be..9d75165 100644 --- a/README.md +++ b/README.md @@ -9,31 +9,69 @@ Machine code interpreter written in pure C. Can execute programs up to 1 MEGABYT ``` ## Assembly language -### Instructions -| code | name | arguments | details | -|------|------|-----------|---------| -| 00 | NOP | | ignored instruction | -| 01 | MOVC | `dst_register`, `value` | push constant value into `dst_register` | -| 02 | MOVR | `dst_register`, `src_register` | copy value from `src_register` to `dst_register` -| 03 | ADD | `dst_register`, `src_register` | `dst` += `src` | -| 04 | SUB | `dst_register`, `src_register` | `dst` -= `src` | -| 05 | MUL | `dst_register`, `src_register` | `dst` *= `src` | -| 06 | DIV | `dst_register`, `src_register` | `dst` /= `src` | -| 07 | MOD | `dst_register`, `src_register` | `dst` %= `src` | -| 08 | SYS | | call system function | -| 09 | EXIT | | stop the program with exit code in `ax` | - ### Registers -| code | name | size (bits) | -|------|------|-------------| -| 01 | ax | 32 | -| 02 | bx | 32 | -| 03 | cx | 32 | -| 04 | dx | 32 | +| name | code | size (bits) | +|-----|------|----| +| rax | 0x01 | 64 | +| eax | 0x02 | 32 | +| ax | 0x04 | 16 | +| al | 0x07 | 8 | +| ah | 0x08 | 8 | +| | +| rbx | 0x11 | 64 | +| ebx | 0x12 | 32 | +| bx | 0x14 | 16 | +| bl | 0x17 | 8 | +| bh | 0x18 | 8 | +| | +| rcx | 0x21 | 64 | +| ecx | 0x22 | 32 | +| cx | 0x24 | 16 | +| cl | 0x27 | 8 | +| ch | 0x28 | 8 | +| | +| rdx | 0x31 | 64 | +| edx | 0x32 | 32 | +| dx | 0x34 | 16 | +| dl | 0x37 | 8 | +| dh | 0x38 | 8 | + +### Instructions +| name | arguments | details | +|------|-----------|---------| +| NOP | | ignored instruction | +| EXIT | | stop the program with exit code in `eax` | +| SYS | | call system function | +| | +| MOVC | `dst_register`, `value` | push constant value into `dst_register` | +| MOVR | `dst_register`, `src_register` | copy value from `src_register` to `dst_register` | +| | +| ADD | `dst_register`, `src_register` | `dst += src` | +| SUB | `dst_register`, `src_register` | `dst -= src` | +| MUL | `dst_register`, `src_register` | `dst *= src` | +| DIV | `dst_register`, `src_register` | `dst /= src` | +| MOD | `dst_register`, `src_register` | `dst %= src` | +| | +| EQ | `dst_register`, `src_register` | `cmp_flag = dst == src` | +| NE | `dst_register`, `src_register` | `cmp_flag = dst != src` | +| LT | `dst_register`, `src_register` | `cmp_flag = dst < src` | +| LE | `dst_register`, `src_register` | `cmp_flag = dst <= src` | +| GT | `dst_register`, `src_register` | `cmp_flag = dst > src` | +| GE | `dst_register`, `src_register` | `cmp_flag = dst >= src` | +| | +| NOT | `dst_register` | `dst = !dst` | +| INV | `dst_register` | `dst = ~dst` | +| OR | `dst_register`, `src_register` | `dst = dst \| src` | +| XOR | `dst_register`, `src_register` | `dst = dst ^ src` | +| AND | `dst_register`, `src_register` | `dst = dst & src` | +| | +| JMP | `dst_register` | goto `dst` | +| JNZ | `dst_register` | if (`cmp_flag` != 0) goto `dst` | +| JZ | `dst_register` | if (`cmp_flag` == 0) goto `dst` | ### System functions To call a system function you need to push values to registers and write `SYS` opcode. The return value of a function will will be avaliable in `ax` after call. -| `ax` | name | `bx` | `cx` | `dx` | details | -|-----------|------|----|----|----|---------| -| 0 | read | file number | buffer pointer | buffer size | read data from file | -| 1 | write | file number | buffer pointer | buffer size | write data to file | +| name | `al` | `ah` | `rbx` | `ecx` | details | +|------|------|------|-------|-------|---------| +| read | 0 | file number | buffer pointer | buffer size | read data from file | +| write | 1 | file number | buffer pointer | buffer size | write data to file | diff --git a/TODO.md b/TODO.md index d977d80..0b1e055 100644 --- a/TODO.md +++ b/TODO.md @@ -1,9 +1,11 @@ # TODO List - add negative number arguments support +- add movc char support +- add padding to compilation +- VM debug log +- add display syscalls - change section binary format: 1. code 2. exit instruction with code ERR_U_FORGOT_TO_CALL_EXIT 3. data -- add padding to compilation - arguments validation for each instruction -- VM debug mode diff --git a/examples/conditional_jump.tasm b/examples/conditional_jump.tasm index 6d3937e..eef005b 100644 --- a/examples/conditional_jump.tasm +++ b/examples/conditional_jump.tasm @@ -11,19 +11,19 @@ jz @false cx .true: const8 true.msg "true\n" -movc cx @true.msg -movc dx #true.msg +movc rbx @true.msg +movc ecx #true.msg jmp @print .false const8 false.msg "false\n" -movc cx @false.msg -movc dx #false.msg +movc rbx @false.msg +movc ecx #false.msg jmp @print .print: -movc ax 1 -movc bx 1 +movc al 1 +movc ah 1 sys jmp @end diff --git a/examples/loop.tasm b/examples/loop.tasm index 824c30c..ae84514 100644 --- a/examples/loop.tasm +++ b/examples/loop.tasm @@ -6,9 +6,9 @@ Example of self-repeating code section .loop const8 datum "ITERATION!!! " -movc ax 1 -movc bx 1 -movc cx @datum -movc dx #datum +movc al 1 +movc ah 1 +movc rbx @datum +movc ecx #datum sys jmp @loop diff --git a/examples/stdout.tasm b/examples/stdout.tasm index f3595ea..f971656 100644 --- a/examples/stdout.tasm +++ b/examples/stdout.tasm @@ -4,13 +4,13 @@ .data: // named array of 8-bit values -const8 msg "Hello, World" +const8 msg "Hello, World!\n" .main: -movc ax 1; // sys_write -movc bx 1; // stdout -movc cx @msg; // address of msg data -movc dx #msg; // size of msg data +movc al 1; // sys_write +movc ah 1; // stdout +movc rbx @msg; // address of msg data +movc ecx #msg; // size of msg data sys movc ax 0 exit diff --git a/examples/window.tasm b/examples/window.tasm index 7c2b84a..58322f5 100644 --- a/examples/window.tasm +++ b/examples/window.tasm @@ -3,7 +3,5 @@ Example of graphical application */ .main: - -jif -jel +//TODO: write code here exit diff --git a/src/VM/VM.c b/src/VM/VM.c index 0f7e313..766b8c7 100644 --- a/src/VM/VM.c +++ b/src/VM/VM.c @@ -50,7 +50,7 @@ i32 VM_boot(VM* vm){ u8 opcode = vm->data[vm->current_pos]; const Instruction* instr = Instruction_getByOpcode(opcode); - // printfe("[at 0x%x] %02X %s\n", (u32)vm->current_pos, opcode, instr->name); + // printfe("[at 0x%x] %02X %s\n", (u32)vm->current_pos, opcode, instr->name.data); if(instr == NULL){ VM_setError(vm, "unknown opcode %02X", opcode); return -1; @@ -60,7 +60,7 @@ i32 VM_boot(VM* vm){ i32 bytes_read = instr->implementation(vm); // internal error occured if(bytes_read < 0) - return -1; + return bytes_read; if(vm->state == VMState_Exited) break; @@ -72,7 +72,7 @@ i32 VM_boot(VM* vm){ } // exit code of the program should be in ax register - return vm->registers.a.u32v0; + return vm->registers.a.ex; } bool VM_dataRead(VM* vm, void* dst, size_t pos, size_t size){ @@ -84,6 +84,25 @@ bool VM_dataRead(VM* vm, void* dst, size_t pos, size_t size){ return false; } - memcpy(dst, vm->data + pos, size); + void* addr = vm->data + pos; + memcpy(dst, addr, size); return true; } + +void VM_registerRead(VM* vm, void* dst, RegisterCode code) { + u8 index = code / 0x10; + u8 part = code & 0xf; + u8 offset = part / 8; + u8 size = 8 / part; + void* addr = (u8*)(&vm->registers.array[index]) + offset; + memcpy(dst, addr, size); +} + +void VM_registerWrite(VM* vm, void* src, RegisterCode code){ + u8 index = code / 0x10; + u8 part = code & 0xf; + u8 offset = part / 8; + u8 size = 8 / part; + void* addr = (u8*)(&vm->registers.array[index]) + offset; + memcpy(addr, src, size); +} diff --git a/src/VM/VM.h b/src/VM/VM.h index 6903abb..e6c89ad 100644 --- a/src/VM/VM.h +++ b/src/VM/VM.h @@ -1,33 +1,15 @@ #pragma once #include "../std.h" #include "../string/str.h" +#include "../instructions/registers.h" typedef union Register { - u64 u64v; - f64 f64v; - struct { - u32 u32v0; - u32 u32v1; - }; - struct { - f32 f32v0; - f32 f32v1; - }; + u64 rx; + u32 ex; + u16 x; struct { - u16 u16v0; - u16 u16v1; - u16 u16v2; - u16 u16v3; - }; - struct { - u8 u8v0; - u8 u8v1; - u8 u8v2; - u8 u8v3; - u8 u8v4; - u8 u8v5; - u8 u8v6; - u8 u8v7; + u8 l; + u8 h; }; } Register; @@ -69,6 +51,8 @@ bool VM_setMemory(VM* vm, u8* data, size_t size); i32 VM_boot(VM* vm); bool VM_dataRead(VM* vm, void* dst, size_t pos, size_t size); +void VM_registerRead(VM* vm, void* dst, RegisterCode code); +void VM_registerWrite(VM* vm, void* src, RegisterCode code); #define VM_setError(vm, format, ...) _VM_setError(vm, __func__, format ,##__VA_ARGS__) void _VM_setError(VM* vm, cstr context, cstr format, ...) __attribute__((__format__(__printf__, 3, 4))); diff --git a/src/compiler/Compiler.c b/src/compiler/Compiler.c index 1b7e649..bb17bbb 100644 --- a/src/compiler/Compiler.c +++ b/src/compiler/Compiler.c @@ -90,22 +90,21 @@ static bool compileSection(Compiler* cmp, Section* sec){ List_u8_push(&cs->bytes, arg->value.register_code); break; case ArgumentType_ConstValue: - //TODO: add const value size parsing - List_u8_pushMany(&cs->bytes, (void*)&arg->value.i, 4); + List_u8_pushMany(&cs->bytes, (void*)&arg->value.i, 8); break; case ArgumentType_ConstDataPointer: List_NamedRef_push(&cs->named_refs, NamedRef_construct( arg->value.data_name, NamedRefType_Ptr, cs->bytes.len)); - List_u8_pushMany(&cs->bytes, zeroes, 4); + List_u8_pushMany(&cs->bytes, zeroes, 8); break; case ArgumentType_ConstDataSize: List_NamedRef_push(&cs->named_refs, NamedRef_construct( arg->value.data_name, NamedRefType_Size, cs->bytes.len)); - List_u8_pushMany(&cs->bytes, zeroes, 4); + List_u8_pushMany(&cs->bytes, zeroes, 8); break; } } @@ -148,6 +147,10 @@ static bool compileBinary(Compiler* cmp){ for(u32 i = 0; i < cmp->binary.section_list.len; i++){ CompiledSection* sec = &cmp->binary.section_list.data[i]; total_size += sec->bytes.len; + bool is_main_sec = str_equals(sec->name, main_sec_name); + if(!is_main_sec){ + sec->offset = prev_sec->offset + prev_sec->bytes.len; + } ConstDataProps cd = ConstDataProps_construct(sec->name, sec->bytes.len, sec->offset); if(!HashMap_ConstDataProps_tryPush(&cmp->binary.const_data_map, cd.name, cd)){ @@ -161,10 +164,9 @@ static bool compileBinary(Compiler* cmp){ } } - if(str_equals(sec->name, main_sec_name)) + if(is_main_sec) continue; prev_sec->next = sec; - sec->offset = prev_sec->offset + prev_sec->bytes.len; prev_sec = sec; } @@ -180,16 +182,15 @@ static bool compileBinary(Compiler* cmp){ returnError("can't find named data '%s'", str_copy(ref->name).data); } - void* ref_value_ptr = sec->bytes.data + ref->offset; - + u64* ref_value_ptr = (void*)(sec->bytes.data + ref->offset); switch(ref->type){ default: returnError("invalid NamedRefType %i", ref->type); case NamedRefType_Size: - *((u32*)ref_value_ptr) = target_data->size; + *ref_value_ptr = target_data->size; break; case NamedRefType_Ptr: - *((u32*)ref_value_ptr) = target_data->offset; + *ref_value_ptr = target_data->offset; break; } } @@ -320,8 +321,9 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name, fclose(f); returnError("invalid argument type %i", arg->type); case ArgumentType_Register: - const char* register_names[] = {"null", "ax", "bx", "cx", "dx"}; - printf("%s", register_names[arg->value.register_code]); + str register_name = RegisterCode_toString(arg->value.register_code); + printf("%s 0x%x", register_name.data, arg->value.register_code); + free(register_name.data); break; case ArgumentType_ConstValue: printf(IFWIN("%lli", "%li"), arg->value.i); diff --git a/src/instructions/impl/JMP.c b/src/instructions/impl/JMP.c index 9121806..d39948f 100644 --- a/src/instructions/impl/JMP.c +++ b/src/instructions/impl/JMP.c @@ -2,7 +2,7 @@ // JUMP [destination address] i32 JMP_impl(VM* vm){ - u32 dst_addr = 0; + u64 dst_addr = 0; readVar(dst_addr); vm->current_pos = dst_addr; @@ -13,28 +13,38 @@ i32 JMP_impl(VM* vm){ // JNZ [destination address] [condition register] i32 JNZ_impl(VM* vm){ - u32 dst_addr = 0; + u64 dst_addr = 0; readVar(dst_addr); - u8 cond_register_i = 0; - readRegisterVar(cond_register_i); - if(vm->registers.array[cond_register_i].u32v0 != 0){ + RegisterCode reg_code = 0; + readRegisterCode(reg_code); + u64 cond_reg_value = 0; + VM_registerRead(vm, &cond_reg_value, reg_code); + + if(cond_reg_value != 0){ vm->current_pos = dst_addr; } - return sizeof(dst_addr) + sizeof(cond_register_i); + return sizeof(dst_addr) + sizeof(reg_code); } // JZ [destination address] [condition register] i32 JZ_impl(VM* vm){ - u32 dst_addr = 0; - readVar(dst_addr); - u8 cond_register_i = 0; - readRegisterVar(cond_register_i); - - if(vm->registers.array[cond_register_i].u32v0 == 0){ + u64 dst_addr = 0; + { + if(!VM_dataRead(vm, &dst_addr, vm->current_pos, sizeof(dst_addr))) + return -1; + vm->current_pos += sizeof(dst_addr); + }; + + RegisterCode reg_code = 0; + readRegisterCode(reg_code); + u64 cond_reg_value = 0; + VM_registerRead(vm, &cond_reg_value, reg_code); + + if(cond_reg_value == 0){ vm->current_pos = dst_addr; } - return sizeof(dst_addr) + sizeof(cond_register_i); + return sizeof(dst_addr) + sizeof(reg_code); } diff --git a/src/instructions/impl/MOVC.c b/src/instructions/impl/MOVC.c index ae28ebd..f37c1b6 100644 --- a/src/instructions/impl/MOVC.c +++ b/src/instructions/impl/MOVC.c @@ -2,16 +2,11 @@ /// MOVC [dst_register] [value_size] [value] i32 MOVC_impl(VM* vm){ - u8 dst_register_i = 0; - readRegisterVar(dst_register_i); - /*u8 value_size = 0; - readValueSizeVar(value_size);*/ - u8 value_size = 4;\ + RegisterCode dst_reg_code = 0; + readRegisterCode(dst_reg_code); + u64 const_value = 0; + readVar(const_value); - vm->registers.array[dst_register_i].u64v = 0; - if(!VM_dataRead(vm, &vm->registers.array[dst_register_i].u64v, vm->current_pos, value_size)) - return -1; - vm->current_pos += value_size; - - return sizeof(dst_register_i) + sizeof(value_size) + value_size; + VM_registerWrite(vm, &const_value, dst_reg_code); + return sizeof(dst_reg_code) + sizeof(const_value); } diff --git a/src/instructions/impl/MOVR.c b/src/instructions/impl/MOVR.c index 5f628fd..4094cef 100644 --- a/src/instructions/impl/MOVR.c +++ b/src/instructions/impl/MOVR.c @@ -2,15 +2,16 @@ /// MOVR [dst_register] [src_register] i32 MOVR_impl(VM* vm){ - u8 dst_register_i = 0; - readRegisterVar(dst_register_i); - u8 src_register_i = 0; - readRegisterVar(src_register_i); - if(dst_register_i == src_register_i){ - VM_setError(vm, "dst_register_i == src_register_i (%x) ", src_register_i); + RegisterCode dst_reg_code = 0, src_reg_code = 0; + readRegisterCode(dst_reg_code); + readRegisterCode(src_reg_code); + if(dst_reg_code == src_reg_code){ + VM_setError(vm, "dst_reg_code == src_reg_code (%x) ", src_reg_code); return -1; } - vm->registers.array[dst_register_i].u64v = vm->registers.array[src_register_i].u64v; - return sizeof(dst_register_i) + sizeof(src_register_i); + u64 src_reg_value = 0; + VM_registerRead(vm, &src_reg_value, src_reg_code); + VM_registerWrite(vm, &src_reg_value, dst_reg_code); + return sizeof(dst_reg_code) + sizeof(src_reg_code); } diff --git a/src/instructions/impl/SYS.c b/src/instructions/impl/SYS.c index bb241b4..50a3128 100644 --- a/src/instructions/impl/SYS.c +++ b/src/instructions/impl/SYS.c @@ -1,6 +1,6 @@ #include "impl_macros.h" -FILE* NULLABLE(fileFromN)(VM* vm, u32 file_n){ +FILE* NULLABLE(fileFromN)(VM* vm, u8 file_n){ FILE* f = NULL; switch(file_n){ case 0: f = stdin; break; @@ -15,13 +15,13 @@ FILE* NULLABLE(fileFromN)(VM* vm, u32 file_n){ } // sys_read -// bx - file n -// cx - buffer ptr -// dx - buffer size +// ah - file n +// rbx - buffer ptr +// ecx - buffer size i32 SYS_read(VM* vm){ - const u32 file_n = vm->registers.b.u32v0; - u8* const buf = vm->data + vm->registers.c.u32v0; - const u32 size = vm->registers.d.u32v0; + const u8 file_n = vm->registers.a.h; + u8* const buf = vm->data + vm->registers.b.rx; + const u32 size = vm->registers.c.ex; if(buf + size > vm->data + vm->data_size) return 40; @@ -31,13 +31,13 @@ i32 SYS_read(VM* vm){ } // sys_write -// bx - file n -// cx - buffer ptr -// dx - buffer size +// ah - file n +// rbx - buffer ptr +// ecx - buffer size i32 SYS_write(VM* vm){ - const u32 file_n = vm->registers.b.u32v0; - u8* const buf = vm->data + vm->registers.c.u32v0; - const u32 size = vm->registers.d.u32v0; + const u8 file_n = vm->registers.a.h; + u8* const buf = vm->data + vm->registers.b.rx; + const u32 size = vm->registers.c.ex; if(buf + size > vm->data + vm->data_size) return 41; @@ -47,10 +47,10 @@ i32 SYS_write(VM* vm){ } /// SYS -/// before call: ax - func code -/// after call: ax - result code +/// before call: al - func code +/// after call: eax - result code i32 SYS_impl(VM* vm){ - u32 func_code = vm->registers.a.u32v0; + u8 func_code = vm->registers.a.l; i32 result_code = 0; switch(func_code){ case 0: @@ -64,6 +64,6 @@ i32 SYS_impl(VM* vm){ return -1; } - vm->registers.a.u64v = result_code; + vm->registers.a.ex = result_code; return 0; } diff --git a/src/instructions/impl/impl_macros.h b/src/instructions/impl/impl_macros.h index c8cafa5..d3c1cd9 100644 --- a/src/instructions/impl/impl_macros.h +++ b/src/instructions/impl/impl_macros.h @@ -8,29 +8,55 @@ vm->current_pos += sizeof(VAR);\ } -#define validateRegisterIndex(VAR) {\ - if(VAR> sizeof(vm->registers)){\ +#define validateRegisterCode(VAR) \ + if(VAR == RegisterCode_Unset || VAR > RegisterCode_dh){\ VM_setError(vm, "invalid register index (%x)", VAR);\ return -1;\ - }\ -} + } -#define readRegisterVar(VAR) {\ +#define readRegisterCode(VAR) {\ readVar(VAR);\ - VAR -= 1;\ - validateRegisterIndex(VAR);\ + validateRegisterCode(VAR);\ } -/* -#define validateValueSize(VAR) {\ - if(VAR < 1 || VAR > 8){\ - VM_setError(vm, "invalid value_size (%x)", VAR);\ - return -1;\ - }\ +#define OPERATOR_IMPL_1(NAME, OPERATOR)\ +i32 NAME##_impl (VM* vm) {\ + RegisterCode dst_reg_code = 0;\ + readRegisterCode(dst_reg_code);\ + u64 dst_reg_value = 0;\ + VM_registerRead(vm, &dst_reg_value, dst_reg_code);\ + \ + dst_reg_value = OPERATOR dst_reg_value;\ + VM_registerWrite(vm, &dst_reg_value, dst_reg_code);\ + return sizeof(dst_reg_code);\ } -#define readValueSizeVar(VAR) {\ - readVar(VAR);\ - validateValueSize(VAR);\ +#define OPERATOR_IMPL_2(NAME, OPERATOR)\ +i32 NAME##_impl (VM* vm) {\ + RegisterCode dst_reg_code = 0, src_reg_code = 0;\ + readRegisterCode(dst_reg_code);\ + readRegisterCode(src_reg_code);\ + u64 dst_reg_value = 0, src_reg_value = 0;\ + VM_registerRead(vm, &dst_reg_value, dst_reg_code);\ + VM_registerRead(vm, &src_reg_value, src_reg_code);\ + \ + dst_reg_value = dst_reg_value OPERATOR src_reg_value;\ + VM_registerWrite(vm, &dst_reg_value, dst_reg_code);\ + return sizeof(dst_reg_code) + sizeof(src_reg_code);\ +} + +#define OPERATOR_IMPL_3(NAME, OPERATOR)\ +i32 NAME##_impl (VM* vm) {\ + RegisterCode dst_reg_code = 0, src0_reg_code = 0, src1_reg_code = 0;\ + readRegisterCode(dst_reg_code);\ + readRegisterCode(src0_reg_code);\ + readRegisterCode(src1_reg_code);\ + u64 dst_reg_value = 0, src0_reg_value = 0, src1_reg_value = 0;\ + VM_registerRead(vm, &dst_reg_value, dst_reg_code);\ + VM_registerRead(vm, &src0_reg_value, src0_reg_code);\ + VM_registerRead(vm, &src1_reg_value, src1_reg_code);\ + \ + dst_reg_value = src0_reg_value OPERATOR src1_reg_value;\ + VM_registerWrite(vm, &dst_reg_value, dst_reg_code);\ + return sizeof(dst_reg_code) + sizeof(src0_reg_code) + sizeof(src1_reg_code);\ } -*/ diff --git a/src/instructions/impl/logical_operators.c b/src/instructions/impl/logical_operators.c index c831dbc..cc1e53b 100644 --- a/src/instructions/impl/logical_operators.c +++ b/src/instructions/impl/logical_operators.c @@ -1,93 +1,36 @@ #include "impl_macros.h" -#define logicalOperator1Impl(NAME, OPERATOR)\ -i32 NAME##_impl (VM* vm) {\ - u8 src_register_i = 0;\ - readRegisterVar(src_register_i);\ - /*u8 value_size = 0;\ - readValueSizeVar(value_size);*/\ - u8 value_size = 4;\ - \ - switch(value_size){\ - case 1: \ - vm->registers.array[src_register_i].u8v0 = OPERATOR vm->registers.array[src_register_i].u8v0;\ - break;\ - case 2: \ - vm->registers.array[src_register_i].u16v0 = OPERATOR vm->registers.array[src_register_i].u16v0;\ - break;\ - case 4: \ - vm->registers.array[src_register_i].u32v0 = OPERATOR vm->registers.array[src_register_i].u32v0;\ - break;\ - case 8: \ - vm->registers.array[src_register_i].u64v = OPERATOR vm->registers.array[src_register_i].u64v;\ - break;\ - }\ - return sizeof(src_register_i) /*+ sizeof(value_size)*/;\ -} +/// NOT [dst_register] +OPERATOR_IMPL_1(NOT, !) -#define logicalOperator2Impl(NAME, OPERATOR)\ -i32 NAME##_impl (VM* vm) {\ - u8 dst_register_i = 0, src_register_i = 0;\ - readRegisterVar(dst_register_i);\ - readRegisterVar(src_register_i);\ - /*u8 value_size = 0;\ - readValueSizeVar(value_size);*/\ - u8 value_size = 4;\ - \ - switch(value_size){\ - case 1: \ - vm->registers.array[dst_register_i].u8v0 OPERATOR##= vm->registers.array[src_register_i].u8v0;\ - break;\ - case 2: \ - vm->registers.array[dst_register_i].u16v0 OPERATOR##= vm->registers.array[src_register_i].u16v0;\ - break;\ - case 4: \ - vm->registers.array[dst_register_i].u32v0 OPERATOR##= vm->registers.array[src_register_i].u32v0;\ - break;\ - case 8: \ - vm->registers.array[dst_register_i].u64v OPERATOR##= vm->registers.array[src_register_i].u64v;\ - break;\ - }\ - return sizeof(dst_register_i) + sizeof(src_register_i) /*+ sizeof(value_size)*/;\ -} +/// INV [dst_register] +OPERATOR_IMPL_1(INV, ~) -#define logicalOperator3Impl(NAME, OPERATOR)\ -i32 NAME##_impl (VM* vm) {\ - u8 dst_register_i = 0, src0_register_i = 0, src1_register_i = 0;\ - readRegisterVar(dst_register_i);\ - readRegisterVar(src0_register_i);\ - readRegisterVar(src1_register_i);\ - /*u8 value_size = 0;\ - readValueSizeVar(value_size);*/\ - u8 value_size = 4;\ - \ - switch(value_size){\ - case 1: \ - vm->registers.array[dst_register_i].u8v0 = vm->registers.array[src0_register_i].u8v0 OPERATOR vm->registers.array[src1_register_i].u8v0;\ - break;\ - case 2: \ - vm->registers.array[dst_register_i].u16v0 = vm->registers.array[src0_register_i].u16v0 OPERATOR vm->registers.array[src1_register_i].u16v0;\ - break;\ - case 4: \ - vm->registers.array[dst_register_i].u32v0 = vm->registers.array[src0_register_i].u32v0 OPERATOR vm->registers.array[src1_register_i].u32v0;\ - break;\ - case 8: \ - vm->registers.array[dst_register_i].u64v = vm->registers.array[src0_register_i].u64v OPERATOR vm->registers.array[src1_register_i].u64v;\ - break;\ - }\ - return sizeof(dst_register_i) + sizeof(src0_register_i) + sizeof(src1_register_i) /*+ sizeof(value_size)*/;\ -} -logicalOperator3Impl(EQ, ==) -logicalOperator3Impl(NE, !=) -logicalOperator3Impl(LT, <) -logicalOperator3Impl(LE, <=) -logicalOperator3Impl(GT, >) -logicalOperator3Impl(GE, >=) +/// OR [dst_register] [src_register] +OPERATOR_IMPL_2(OR, |) -logicalOperator1Impl(NOT, !) -logicalOperator1Impl(INV, ~) +/// XOR [dst_register] [src_register] +OPERATOR_IMPL_2(XOR, ^) -logicalOperator2Impl(OR, |) -logicalOperator2Impl(XOR, ^) -logicalOperator2Impl(AND, &) +/// AND [dst_register] [src_register] +OPERATOR_IMPL_2(AND, &) + + +/// EQ [dst_register] [src0_register] [src1_register] +OPERATOR_IMPL_3(EQ, ==) + +/// NE [dst_register] [src0_register] [src1_register] +OPERATOR_IMPL_3(NE, !=) + +/// LT [dst_register] [src0_register] [src1_register] +OPERATOR_IMPL_3(LT, <) + +/// LE [dst_register] [src0_register] [src1_register] +OPERATOR_IMPL_3(LE, <=) + +/// GT [dst_register] [src0_register] [src1_register] +OPERATOR_IMPL_3(GT, >) + +/// GE [dst_register] [src0_register] [src1_register] +OPERATOR_IMPL_3(GE, >=) diff --git a/src/instructions/impl/math_operators.c b/src/instructions/impl/math_operators.c index 0446600..e641b98 100644 --- a/src/instructions/impl/math_operators.c +++ b/src/instructions/impl/math_operators.c @@ -1,42 +1,16 @@ #include "impl_macros.h" -#define mathOperator2Impl(NAME, OPERATOR)\ -i32 NAME##_impl (VM* vm) {\ - u8 dst_register_i = 0, src_register_i = 0;\ - readRegisterVar(dst_register_i);\ - readRegisterVar(src_register_i);\ - /*u8 value_size = 0;\ - readValueSizeVar(value_size);*/\ - u8 value_size = 4;\ - \ - switch(value_size){\ - case 1: \ - vm->registers.array[dst_register_i].u8v0 OPERATOR##= vm->registers.array[src_register_i].u8v0;\ - break;\ - case 2: \ - vm->registers.array[dst_register_i].u16v0 OPERATOR##= vm->registers.array[src_register_i].u16v0;\ - break;\ - case 4: \ - vm->registers.array[dst_register_i].u32v0 OPERATOR##= vm->registers.array[src_register_i].u32v0;\ - break;\ - case 8: \ - vm->registers.array[dst_register_i].u64v OPERATOR##= vm->registers.array[src_register_i].u64v;\ - break;\ - }\ - return sizeof(dst_register_i) + sizeof(src_register_i) /*+ sizeof(value_size)*/;\ -} - /// ADD [dst_register] [src_register] -mathOperator2Impl(ADD, +) +OPERATOR_IMPL_2(ADD, +) /// SUB [dst_register] [src_register] -mathOperator2Impl(SUB, -) +OPERATOR_IMPL_2(SUB, -) /// MUL [dst_register] [src_register] -mathOperator2Impl(MUL, *) +OPERATOR_IMPL_2(MUL, *) /// DIV [dst_register] [src_register] -mathOperator2Impl(DIV, /) +OPERATOR_IMPL_2(DIV, /) /// MOD [dst_register] [src_register] -mathOperator2Impl(MOD, %) +OPERATOR_IMPL_2(MOD, %) diff --git a/src/instructions/registers.c b/src/instructions/registers.c index 70153e4..95a2bf8 100644 --- a/src/instructions/registers.c +++ b/src/instructions/registers.c @@ -1,13 +1,76 @@ #include "registers.h" +#define check_code(R) if(str_equals(lower, STR(#R))) code = RegisterCode_##R; + RegisterCode RegisterCode_parse(str r){ - if(str_equals(r, STR("ax"))) - return RegisterCode_ax; - if(str_equals(r, STR("bx"))) - return RegisterCode_bx; - if(str_equals(r, STR("cx"))) - return RegisterCode_cx; - if(str_equals(r, STR("dx"))) - return RegisterCode_dx; - return RegisterCode_Unset; + str lower = str_toLower(r); + RegisterCode code = RegisterCode_Unset; + // a + check_code(rax) + else check_code(eax) + else check_code(ax) + else check_code(al) + else check_code(ah) + // b + else check_code(rbx) + else check_code(ebx) + else check_code(bx) + else check_code(bl) + else check_code(bh) + // c + else check_code(rcx) + else check_code(ecx) + else check_code(cx) + else check_code(cl) + else check_code(ch) + //d + else check_code(rdx) + else check_code(edx) + else check_code(dx) + else check_code(dl) + else check_code(dh) + + free(lower.data); + return code; } + +str RegisterCode_toString(RegisterCode code){ + char buf[3] = { '?', 'a', 'x' }; + u8 index = code / 0x10; + switch(index){ + default: + return str_copy(STR("!!! ERROR: invalid RegisterCode !!!")); + case 0: + case 1: + case 2: + case 3: + buf[1] += index; + break; + } + + str buf_str = str_construct(buf, 3, false); + switch(code & 0xf){ + default: + return str_copy(STR("!!! ERROR: invalid RegisterCode !!!")); + case 1: + buf_str.data[0] = 'r'; + break; + case 2: + buf_str.data[0] = 'e'; + break; + case 4: + buf_str.data += 1; + buf_str.len -= 1; + break; + case 7: + buf_str.data[0] = 'l'; + buf_str.len -= 1; + break; + case 8: + buf_str.data[0] = 'h'; + buf_str.len -= 1; + break; + } + + return str_copy(buf_str); +} \ No newline at end of file diff --git a/src/instructions/registers.h b/src/instructions/registers.h index 6b0db8e..45bb2fd 100644 --- a/src/instructions/registers.h +++ b/src/instructions/registers.h @@ -3,11 +3,33 @@ #include "../string/str.h" typedef enum RegisterCode { - RegisterCode_Unset, - RegisterCode_ax, - RegisterCode_bx, - RegisterCode_cx, - RegisterCode_dx -} RegisterCode; + RegisterCode_Unset = 0, + + RegisterCode_rax = 0x01, + RegisterCode_eax = 0x02, + RegisterCode_ax = 0x04, + RegisterCode_al = 0x07, + RegisterCode_ah = 0x08, + + RegisterCode_rbx = 0x11, + RegisterCode_ebx = 0x12, + RegisterCode_bx = 0x14, + RegisterCode_bl = 0x17, + RegisterCode_bh = 0x18, + + RegisterCode_rcx = 0x21, + RegisterCode_ecx = 0x22, + RegisterCode_cx = 0x24, + RegisterCode_cl = 0x27, + RegisterCode_ch = 0x28, + + RegisterCode_rdx = 0x31, + RegisterCode_edx = 0x32, + RegisterCode_dx = 0x34, + RegisterCode_dl = 0x37, + RegisterCode_dh = 0x38, +} __attribute__((__packed__)) RegisterCode; RegisterCode RegisterCode_parse(str register_name); +/// @return allocated string +str RegisterCode_toString(RegisterCode code);