diff --git a/Makefile b/Makefile index 1e7d72e..46ece94 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,9 @@ all: k.exe -src = instr/instrs.c karch/decd.c karch/main.c karch/regs.c karch/dump.c +src = instr/instrs.c karch/decd.c karch/main.c karch/regs.c \ + karch/dump.c instr/jumps.c + obj = $(patsubst %.c,%.o,$(src)) %.o: %.c instrs/i_arch.h */*.h $(src) diff --git a/instr/INSTRS b/instr/INSTRS index 53f7474..e9b308a 100644 --- a/instr/INSTRS +++ b/instr/INSTRS @@ -81,6 +81,61 @@ inc m dec r dec m +# +# Comparison instruction +# + +# Affects ZF and CF +cmp r r +cmp r i +cmp r m +cmp i r +cmp i i +cmp i m +cmp m r +cmp m i +cmp m m + +# Only affects ZF +test r r +test r i +test r m +test i r +test i i +test i m +test m r +test m i +test m m + +# +# Jump instructions +# + +jmp r +jmp i + +jz r +jz i +jnz r +jnz i +je r +je i +jne r +jne i + +ja r +ja i +jae r +jae i + +jb r +jb i +jbe r +jbe i + +# Jump if RCX is 0 +#jcxz + # # Movement instructions # @@ -99,6 +154,9 @@ xchg m r xchg m i xchg m m +lea r m +lea m m + # # Stack manipulation instructions # @@ -114,10 +172,15 @@ call m ret +pushf + # # Supervisor only instructions # +popf + cli sti +stop diff --git a/instr/instrs.c b/instr/instrs.c index efc5b7c..770478b 100644 --- a/instr/instrs.c +++ b/instr/instrs.c @@ -12,6 +12,10 @@ IMPL_START_0(nop) } IMPL_END; +// +// Logical instructions +// + IMPL_START_2(and) { v1 &= v2; @@ -48,6 +52,10 @@ IMPL_START_1(not) } IMPL_OUT; +// +// Unsigned arithmetic instructions +// + IMPL_START_2(add) { v1 += v2; @@ -105,6 +113,46 @@ IMPL_START_1(dec) } IMPL_OUT; +// +// Comparison instructions +// + +IMPL_START_2(cmp) +{ + if (v1 == v2) { + ctx->r[FLG].val |= ZF; + ctx->r[FLG].val &= ~CF; + } + + else if (v1 < v2) { + ctx->r[FLG].val &= ~ZF; + ctx->r[FLG].val |= CF; + } + + else { + ctx->r[FLG].val &= ~ZF; + ctx->r[FLG].val &= ~CF; + } +} +IMPL_END; + +IMPL_START_2(test) +{ + ulong v = v1 & v2; + + if (v == 0) ctx->r[FLG].val |= ZF; + else ctx->r[FLG].val &= ~ZF; +} +IMPL_END; + +// +// Jump instructions +// + +// +// Movement instructions +// + IMPL_START_2(mov) { v1 = v2; @@ -119,6 +167,18 @@ IMPL_START_2(xchg) } IMPL_OUT; +IMPL_START_1(lea) +{ + assert(p2->mem); + + v1 = (p2->type == A_REG ? ctx->r[p2->val].val : p2->val) + p2->off; +} +IMPL_OUT; + +// +// Stack manipulation instructions +// + IMPL_START_1(push) { if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) { @@ -180,17 +240,59 @@ IMPL_START_0(ret) } IMPL_END; +IMPL_START_0(pushf) +{ + if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) { + _except(ctx, E_STK, "Misaligned stack REGS"); + } + + if (ctx->r[RSP].val > ctx->r[RBP].val) { + _except(ctx, E_STK, "RSP above RBP"); + } + + writemem64(ctx, ctx->r[FLG].val, ctx->r[RSP].val); + ctx->r[RSP].val -= 8; +} +IMPL_END; + +IMPL_START_0(popf) +{ + if (ctx->r[RSP].val % 8 > 0 || ctx->r[RBP].val % 8 > 0) { + _except(ctx, E_STK, "Misaligned stack REGS"); + } + + if (ctx->r[RSP].val >= ctx->r[RBP].val) { + _except(ctx, E_STK, "RBP above RSP"); + } + + CHK_SUPERV(); // XXX + + ctx->r[RSP].val += 8; + ctx->r[FLG].val = readmem64(ctx, ctx->r[RSP].val); +} +IMPL_END; + +// +// Supervisor only instructions +// + IMPL_START_0(cli) { CHK_SUPERV(); - ctx->r[FLG].val &= ~(1L<<63); + ctx->r[FLG].val &= ~IF; } IMPL_END; IMPL_START_0(sti) { CHK_SUPERV(); - ctx->r[FLG].val |= 1L<<63; + ctx->r[FLG].val |= IF; +} +IMPL_END; + +IMPL_START_0(stop) +{ + _except(ctx, E_SHT, "STOP INSTR"); } IMPL_END; diff --git a/instr/instrs.h b/instr/instrs.h index a64c732..140fbed 100644 --- a/instr/instrs.h +++ b/instr/instrs.h @@ -41,7 +41,7 @@ void i_##name(ctx_t *ctx, acc_t *p1, acc_t *p2) \ #define CHK_SUPERV() \ do { \ - if ((ctx->r[FLG].val & (1L << 62)) == 1) { \ + if ((ctx->r[FLG].val & UF) == 1) { \ _except(ctx, E_SYS, "Supervisor-only INSTR"); \ } \ } while (0) diff --git a/instr/instrs.py b/instr/instrs.py index f491788..f64f857 100644 --- a/instr/instrs.py +++ b/instr/instrs.py @@ -8,6 +8,8 @@ hd = open("instr/arch_i.h", "w") count = 0 +hd.write("// Auto-generated by instrs.py from INSTRS\n\n"); + hd.write("#ifdef _NEED_ARCH_I\n") hd.write("instr_t arch_i[] =\n{\n\n") hd.write("#endif\n") diff --git a/instr/jumps.c b/instr/jumps.c index e69de29..5123fe7 100644 --- a/instr/jumps.c +++ b/instr/jumps.c @@ -0,0 +1,67 @@ +// The OS/K Team licences this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "instrs.h" +#include "arch_i.h" + +IMPL_START_1(jmp) +{ + ctx->r[RIP].val = v1; +} +IMPL_END; + +IMPL_START_1(jz) +{ + if (ctx->r[FLG].val & ZF) + ctx->r[RIP].val = v1; +} +IMPL_END; + +IMPL_START_1(jnz) +{ + if (!(ctx->r[FLG].val & ZF)) + ctx->r[RIP].val = v1; +} +IMPL_END; + +IMPL_START_1(je) +{ + if (ctx->r[FLG].val & ZF) + ctx->r[RIP].val = v1; +} +IMPL_END; + +IMPL_START_1(jne) +{ + if (!(ctx->r[FLG].val & ZF)) + ctx->r[RIP].val = v1; +} +IMPL_END; + +IMPL_START_1(ja) +{ + if (!(ctx->r[FLG].val & ZF) && !(ctx->r[FLG].val & CF)) + ctx->r[RIP].val = v1; +} +IMPL_END; + +IMPL_START_1(jae) +{ + if (!(ctx->r[FLG].val & CF)) + ctx->r[RIP].val = v1; +} +IMPL_END; + +IMPL_START_1(jb) +{ + if (!(ctx->r[FLG].val & ZF) && ctx->r[FLG].val & CF) + ctx->r[RIP].val = v1; +} +IMPL_END; + +IMPL_START_1(jbe) +{ + if (ctx->r[FLG].val & CF) + ctx->r[RIP].val = v1; +} +IMPL_END; diff --git a/karch/arch.h b/karch/arch.h index 29d87b0..85fdc9a 100644 --- a/karch/arch.h +++ b/karch/arch.h @@ -46,6 +46,21 @@ enum SYS = 1 << 9, // Reserved for supervisor mode }; +// FLG register +enum +{ + CF = 1 << 0, // Carry flag + PF = 1 << 1, // Parity flag + AC = 1 << 2, // Auxiliary flag + ZF = 1 << 3, // Zero flag + OV = 1 << 4, // Overflow flag + DF = 1 << 5, // Direction flag + SF = 1 << 6, // Sign flag + + UF = 1 << 16, // User-mode flag + IF = 1 << 17, // Interrupts enable flag +}; + struct reg_t { char *name; diff --git a/karch/main.c b/karch/main.c index 266dd9d..e92de30 100644 --- a/karch/main.c +++ b/karch/main.c @@ -10,7 +10,7 @@ ushort fwprog[] = { I_CALL_I, A_IMM32, (MEMOFF+0x13)>>16, (MEMOFF+0x13)&0xFF, I_ADD_R_I, RAX, A_IMM16, 1, - 0xFFFF, + I_STOP, I_ADD_R_I, RBX, A_IMM16, 1, I_RET,