diff --git a/.vscode/launch.json b/.vscode/launch.json index 2cecc3d..d62fcf1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "${workspaceFolder}/bin/tcpu", "windows": { "program": "${workspaceFolder}/bin/tcpu.exe" }, - "args": [ "-c", "../examples/conditional_jump.tasm", "o.bin", "--debug", "-i", "o.bin" ], + "args": [ "-c", "../examples/loop.tasm", "o.bin", "--debug", "-i", "o.bin" ], "cwd": "${workspaceFolder}/bin", "preLaunchTask": "build_exec_dbg", "stopAtEntry": false, diff --git a/README.md b/README.md index 9d75165..75f1c7b 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Machine code interpreter written in pure C. Can execute programs up to 1 MEGABYT | EXIT | | stop the program with exit code in `eax` | | SYS | | call system function | | | -| MOVC | `dst_register`, `value` | push constant value into `dst_register` | +| MOVC | `dst_register`, `const_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` | @@ -65,9 +65,9 @@ Machine code interpreter written in pure C. Can execute programs up to 1 MEGABYT | 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` | +| JMP | `dst_address_const` | goto `dst` | +| JNZ | `dst_address_const` | if (`cmp_flag` != 0) goto `dst` | +| JZ | `dst_address_const` | 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. diff --git a/examples/conditional_jump.tasm b/examples/conditional_jump.tasm index eef005b..56df892 100644 --- a/examples/conditional_jump.tasm +++ b/examples/conditional_jump.tasm @@ -5,9 +5,9 @@ Example of behavior change depending on some condition .main: movc ax 1 movc bx 2 -gt cx ax bx -jnz @true cx -jz @false cx +gt ax bx +jnz @true +jz @false .true: const8 true.msg "true\n" diff --git a/examples/loop.tasm b/examples/loop.tasm index ae84514..827597e 100644 --- a/examples/loop.tasm +++ b/examples/loop.tasm @@ -3,6 +3,7 @@ Example of self-repeating code section */ .main: +movc dx 0; // loop counter .loop const8 datum "ITERATION!!! " @@ -11,4 +12,11 @@ movc ah 1 movc rbx @datum movc ecx #datum sys -jmp @loop + +movc cx 1 +add dx cx +movc cx 8 +lt dx cx +jnz @loop +movc rax 0 +exit diff --git a/src/VM/VM.h b/src/VM/VM.h index e6c89ad..5a71579 100644 --- a/src/VM/VM.h +++ b/src/VM/VM.h @@ -30,6 +30,10 @@ typedef struct VM { }; Register array[4]; } registers; + + struct { + bool cmp; // result of comparison operation + } flags; VMState state; char* NULLABLE(error_message); // not null on if state == VMState_InternalError diff --git a/src/instructions/impl/JMP.c b/src/instructions/impl/JMP.c index d39948f..d82eecc 100644 --- a/src/instructions/impl/JMP.c +++ b/src/instructions/impl/JMP.c @@ -11,40 +11,26 @@ i32 JMP_impl(VM* vm){ } -// JNZ [destination address] [condition register] +// JNZ [destination address] i32 JNZ_impl(VM* vm){ u64 dst_addr = 0; readVar(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){ + if(vm->flags.cmp != 0){ vm->current_pos = dst_addr; } - return sizeof(dst_addr) + sizeof(reg_code); + return sizeof(dst_addr); } -// JZ [destination address] [condition register] +// JZ [destination address] i32 JZ_impl(VM* vm){ u64 dst_addr = 0; - { - if(!VM_dataRead(vm, &dst_addr, vm->current_pos, sizeof(dst_addr))) - return -1; - vm->current_pos += sizeof(dst_addr); - }; + readVar(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){ + if(vm->flags.cmp == 0){ vm->current_pos = dst_addr; } - return sizeof(dst_addr) + sizeof(reg_code); + return sizeof(dst_addr); } diff --git a/src/instructions/impl/impl_macros.h b/src/instructions/impl/impl_macros.h index d3c1cd9..a69a14d 100644 --- a/src/instructions/impl/impl_macros.h +++ b/src/instructions/impl/impl_macros.h @@ -45,18 +45,15 @@ i32 NAME##_impl (VM* vm) {\ return sizeof(dst_reg_code) + sizeof(src_reg_code);\ } -#define OPERATOR_IMPL_3(NAME, OPERATOR)\ +#define OPERATOR_IMPL_CMP_FLAG(NAME, OPERATOR)\ i32 NAME##_impl (VM* vm) {\ - RegisterCode dst_reg_code = 0, src0_reg_code = 0, src1_reg_code = 0;\ - readRegisterCode(dst_reg_code);\ + RegisterCode src0_reg_code = 0, src1_reg_code = 0;\ 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);\ + u64 src0_reg_value = 0, src1_reg_value = 0;\ 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);\ + vm->flags.cmp = src0_reg_value OPERATOR src1_reg_value;\ + return 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 cc1e53b..aa4dd2a 100644 --- a/src/instructions/impl/logical_operators.c +++ b/src/instructions/impl/logical_operators.c @@ -17,20 +17,20 @@ OPERATOR_IMPL_2(XOR, ^) OPERATOR_IMPL_2(AND, &) -/// EQ [dst_register] [src0_register] [src1_register] -OPERATOR_IMPL_3(EQ, ==) +/// EQ [src0_register] [src1_register] +OPERATOR_IMPL_CMP_FLAG(EQ, ==) -/// NE [dst_register] [src0_register] [src1_register] -OPERATOR_IMPL_3(NE, !=) +/// NE [src0_register] [src1_register] +OPERATOR_IMPL_CMP_FLAG(NE, !=) -/// LT [dst_register] [src0_register] [src1_register] -OPERATOR_IMPL_3(LT, <) +/// LT [src0_register] [src1_register] +OPERATOR_IMPL_CMP_FLAG(LT, <) -/// LE [dst_register] [src0_register] [src1_register] -OPERATOR_IMPL_3(LE, <=) +/// LE [src0_register] [src1_register] +OPERATOR_IMPL_CMP_FLAG(LE, <=) -/// GT [dst_register] [src0_register] [src1_register] -OPERATOR_IMPL_3(GT, >) +/// GT [src0_register] [src1_register] +OPERATOR_IMPL_CMP_FLAG(GT, >) -/// GE [dst_register] [src0_register] [src1_register] -OPERATOR_IMPL_3(GE, >=) +/// GE [src0_register] [src1_register] +OPERATOR_IMPL_CMP_FLAG(GE, >=)