This commit is contained in:
julianb0 2019-07-02 20:13:05 +02:00
parent f9ecf442a1
commit b8d29210fb
No known key found for this signature in database
GPG Key ID: 9C7ACF0C053FB8A1
20 changed files with 141 additions and 169 deletions

View File

@ -30,8 +30,7 @@ doprnt:
.print_regular: .print_regular:
; everything below rdi is a regular character; print it ; everything below rdi is a regular character; print it
cmp rbx, rdi b.e rbx, rdi, .check_modf
j.z .check_modf
mov ax0, b[rbx] mov ax0, b[rbx]
call .doput call .doput
@ -41,29 +40,22 @@ doprnt:
.check_modf: .check_modf:
; did we find a '%' ? ; did we find a '%' ?
cmp b[rbx], '%' ; if not, then we found fmt's null-terminator; we're done
j.nz .epilogue ; no, we found fmt's null-terminator; we're done b.nz b[rbx], '%', .epilogue
; we did find a modifier / '%' ; we did find a modifier / '%'
mov rax, b[rbx+1] mov rax, b[rbx+1]
add rbx, 2 add rbx, 2
cmp rax, 's' b.e rax, 's', .modf_s
j.z .modf_s b.e rax, 'c', .modf_c
cmp rax, 'c' b.e rax, 'p', .modf_p
j.z .modf_c b.e rax, 'x', .modf_x
cmp rax, 'p' b.e rax, 'd', .modf_d
j.z .modf_p b.e rax, 'o', .modf_o
cmp rax, 'x' b.e rax, 'b', .modf_b
j.z .modf_x b.e rax, '%', .modf_percent
cmp rax, 'd'
j.z .modf_d
cmp rax, 'o'
j.z .modf_o
cmp rax, 'b'
j.z .modf_b
cmp rax, '%'
j.z .modf_percent
; unrecognized ; unrecognized
jmp .bad_modifier jmp .bad_modifier

View File

@ -23,14 +23,11 @@ ltostr:
xor rx8, rx8 xor rx8, rx8
; make sure base is in [2, 32] ; make sure base is in [2, 32]
cmp ax2, 2 b.b ax2, 2, .bad
j.b .bad b.a ax2, 36, .bad
cmp ax2, 36
j.a .bad
; deal with zero ; deal with zero
test ax1, ax1 b.e ax1, 0, .zero
j.z .zero
; deal with base 10 signedness ; deal with base 10 signedness
@ -45,14 +42,12 @@ ltostr:
; main loop ; main loop
.conv: .conv:
test ax1, ax1 b.e ax1, 0, .fini
j.z .fini
mov r10, ax1 mov r10, ax1
rem r10, ax2 ; ax1 % base rem r10, ax2 ; ax1 % base
cmp r10, 9 ; r10 > 9 ? b.a r10, 9, .nondec ; r10 > 9 ?
j.a .nondec
add r10, '0' add r10, '0'
jmp .next jmp .next

View File

@ -33,15 +33,9 @@ nprintf:
; ;
print: print:
mov rcx, STRLEN_MAX mov rcx, STRLEN_MAX
b.z b[ax0], 0, .1
prns.rep.nz ax0
.1: .1:
cmp b[ax0], 0
ret.z
prn b[ax0]
inc ax0
loop .1
ret ret
; ;
@ -49,11 +43,8 @@ print:
; ;
print_n: print_n:
mov rcx, ax1 mov rcx, ax1
b.z b[ax0], 0, .1
prns.rep.nz ax0
.1: .1:
prn b[ax0]
inc ax0
loop .1
ret ret

View File

@ -31,14 +31,11 @@ strtoq:
mov rdx, ax0 mov rdx, ax0
; make sure base is in [2, 32] ; make sure base is in [2, 32]
cmp ax1, 1 b.z ax1, 1, .bad
j.z .bad b.a ax1, 36, .bad
cmp ax1, 36
j.a .bad
; empty string? ; empty string?
cmp b[rdx], 0 b.z b[rdx], 0, .done
jmp.z .done
.skip_spc: .skip_spc:
cmp b[rdx], ' ' cmp b[rdx], ' '
@ -62,36 +59,27 @@ strtoq:
.unsigned: .unsigned:
; base 0 ; base 0
test ax1, ax1 b.z ax1, 0, .base_0
jmp.z .base_0
; base prefix? ; base prefix?
cmp b[rdx], '0' b.nz b[rdx], '0', .main_loop
jmp.nz .main_loop
inc rdx inc rdx
movzx rcx, b[rdx]
; string is "0" ; "0x"/"0b" prefix
cmp b[rdx], 0 b.z rcx, 0, .done ; "0"
jmp.z .done b.z rcx, 'x', .parsed_0x
b.z rcx, 'b', .parsed_0b
; "0x" prefix
cmp b[rdx], 'x'
jmp.z .parsed_0x
; "0b" prefix
cmp b[rdx], 'b'
jmp.z .parsed_0b
; may be octal, but we don't care ; may be octal, but we don't care
; we accept "0110101010" (binary) for instance ; we accept "0110101010" (despite base=2) for instance
jmp .main_loop jmp .main_loop
.parsed_0x: .parsed_0x:
; are we in base 16? ; are we in base 16?
; if not, leave rax = 0 and *rdx = 'x' ; if not, leave rax = 0 and *rdx = 'x'
cmp ax1, 16 b.nz ax1, 16, .done
jmp.nz .done
; else ; else
inc rdx inc rdx
jmp .main_loop jmp .main_loop
@ -99,8 +87,7 @@ strtoq:
.parsed_0b: .parsed_0b:
; are we in base 2? ; are we in base 2?
; if not, leave rax = 0 and *rdx = 'b' ; if not, leave rax = 0 and *rdx = 'b'
cmp ax1, 2 b.nz ax1, 2, .done
jmp.nz .done
; else ; else
inc rdx inc rdx
jmp .main_loop jmp .main_loop
@ -126,7 +113,7 @@ strtoq:
mov ax1, 8 mov ax1, 8
.main_loop: .main_loop:
mov rx8, b[rdx] movzx rx8, b[rdx]
inc rdx inc rdx
cmp rx8, '0' cmp rx8, '0'
@ -148,8 +135,7 @@ strtoq:
.next: .next:
; too large for base? ; too large for base?
cmp rx8, ax1 b.ae rx8, ax1, .done
jmp.ae .done
mul rax, ax1 mul rax, ax1
add rax, rx8 add rax, rx8

View File

@ -53,8 +53,7 @@ strrev2:
; increase ax0 while decreasing ax1, performing exchanges ; increase ax0 while decreasing ax1, performing exchanges
.2: .2:
cmp ax0, ax1 b.ae ax0, ax1, .3
j.ae .3
xchg b[ax0], b[ax1] xchg b[ax0], b[ax1]

View File

@ -9,7 +9,6 @@ start:
xor rbp, rbp xor rbp, rbp
call main call main
call CMD.builtins.dir call CMD.builtins.dir
hlt hlt
@ -19,8 +18,7 @@ start:
scan rax scan rax
xpause xpause
test rax, rax b.z rax, 0, .1
j.z .1
prn rax prn rax
jmp .1 jmp .1

View File

@ -2,8 +2,9 @@
; See the LICENSE file in the project root for more information. ; See the LICENSE file in the project root for more information.
PrintBootMsg: PrintBootMsg:
mov ax0, .bootmsg mov rcx, STRLEN_MAX
call print mov rdx, .bootmsg
prns.rep.nz rdx
ret ret
.bootmsg = "Starting DOS...\n\n" .bootmsg = "Starting DOS...\n\n"

View File

@ -5,8 +5,9 @@ CMD.builtins.dir:
sub nx0, nx0 # no. of files found sub nx0, nx0 # no. of files found
mov ax0, .dirmsg mov rcx, STRLEN_MAX
call print mov rdx, .dirmsg
prns.rep.nz rdx
.dirmsg = "Directory of C:\\\n\n" .dirmsg = "Directory of C:\\\n\n"
@ -22,8 +23,7 @@ CMD.builtins.dir:
call DISK.FindNext call DISK.FindNext
.list: .list:
test rax, rax b.z rax, 0, .end
j.z .end
; found something ; found something
inc nx0 inc nx0
@ -34,12 +34,9 @@ CMD.builtins.dir:
mov r11, r10 mov r11, r10
scasb.rep.nz r10, '.' scasb.rep.nz r10, '.'
.print_file_name: ; print file name
prn b[r11] ksub rcx, r10, r11
inc r11 prns.rep r11
cmp r11, r10
j.b .print_file_name
; calculate where to put extension ; calculate where to put extension
ksub r11, r10, .buf ksub r11, r10, .buf
@ -47,8 +44,7 @@ CMD.builtins.dir:
.ext_pad: .ext_pad:
; print at least 11 non-space characters before extension ; print at least 11 non-space characters before extension
cmp r11, 11 b.ae r11, 11, .print_ext
j.ae .print_ext
prn ' ' prn ' '
inc r11 inc r11
jmp .ext_pad jmp .ext_pad
@ -62,21 +58,18 @@ CMD.builtins.dir:
inc.z r10 inc.z r10
.print_ext.1: .print_ext.1:
cmp b[r10], 0 b.z b[r10], 0, .print_ext.2
j.z .print_ext.2
; print and decrease rcx, unless it's already 0 ; print and decrease rcx, unless it's already 0
prn b[r10] prn b[r10]
inc r10 inc r10
test rcx, rcx dec.cxnz rcx
dec.nz rcx
jmp .print_ext.1 jmp .print_ext.1
.print_ext.2: .print_ext.2:
; did we print at least 4 bytes? ; did we print at least 4 bytes?
test rcx, rcx j.cxz .print_bytes ; yes, carry on
j.z .print_bytes ; yes, carry on
prn.rep ' ' prn.rep ' '
@ -109,8 +102,9 @@ CMD.builtins.dir:
call printf call printf
add rsp, 8 add rsp, 8
mov ax0, .endstr2 mov rcx, STRLEN_MAX
call print mov rdx, .endstr2
prns.rep.nz rdx
pop nx0 pop nx0
ret ret

View File

@ -10,6 +10,23 @@
# #
prn rim prn rim
#
# Print a string to standard output (PRN)
#
# COMPARE([%1], 0)
#
# IF (ZF == 0) THEN
# PRN([%1])
# IF (DF == 0) THEN
# %1 = %1 + 1
# ELSE
# %1 = %1 - 1
# FI
# FI
#
#
prns r
# #
# Scan a character from standard input (SCAN) # Scan a character from standard input (SCAN)
# #

View File

@ -13,5 +13,5 @@ include "FLAGS"
include "INOUT" include "INOUT"
include "DEBUG" include "DEBUG"
include "STRING" include "STRING"
include "KINSTRS" include "TERNARY"

View File

@ -24,20 +24,20 @@ jmp ri
loop ri loop ri
# #
# Relative jump (BCH) instruction ("branch") # Conditional absolute jumps (B)
# #
# RIP = RIP + $1 # COMPARE($1, $2)
# #
b ri # IF (COND) THEN
bch ri # RIP = $3
# FI
# #
# RCX-dependent relative jump (BOOP) instruction # Sets CF, OF, ZF and SF according to the comparison's results
# #
# IF (RCX > 0) THEN # This instruction is special in that the COND field specified is not evaluated
# RCX = RCX - 1 # before the instruction is executed, but after the comparison it effectuates
# RIP = RIP + $1 #
# FI # Suffixing B with the REP suffix results in undefined behavior
# #
boop ri b rim rim ri

View File

@ -13,6 +13,24 @@ IMPL_START_1(prn)
} }
IMPL_END IMPL_END
IMPL_START_0(prns)
{
uchar ch = readmemzx(ctx, R(p1->reg), 1);
COMPARE(ch, 0);
if ((flg & ZF) == 0)
{
console_putc(ctx, ch);
if (flg & DF)
R(p1->reg)--;
else
R(p1->reg)++;
}
}
IMPL_END
IMPL_START_1(scan) IMPL_START_1(scan)
{ {
v1 = console_scankeybuf(ctx); v1 = console_scankeybuf(ctx);

View File

@ -3,9 +3,7 @@
#include <in/instrs.h> #include <in/instrs.h>
// //----------------------------------------------------------------------------//
// Jump instructions
//
IMPL_START_1(j) IMPL_START_1(j)
{ {
@ -28,24 +26,16 @@ IMPL_START_1(loop)
} }
IMPL_END; IMPL_END;
IMPL_START_1(b) //----------------------------------------------------------------------------//
IMPL_START_3(b)
{ {
rip += v1; COMPARE(v1, v2);
if (eval_cond(ctx, ctx->cond))
rip = v3;
} }
IMPL_END; IMPL_END;
IMPL_START_1(bch) //----------------------------------------------------------------------------//
{
rip += v1;
}
IMPL_END;
IMPL_START_1(boop)
{
if (rcx > 0) {
rcx--;
rip += v1;
}
}
IMPL_END;

View File

@ -8,7 +8,7 @@
#define K_IMPL_ALU(name, expr) \ #define K_IMPL_ALU(name, expr) \
IMPL_START_3(k##name) \ IMPL_START_3(k##name) \
{ \ { \
v1 = expr; \ v1 = (expr); \
} \ } \
IMPL_OUT_ZSF IMPL_OUT_ZSF

View File

@ -70,6 +70,9 @@ struct ctx_t
// Instructions executed so far // Instructions executed so far
ulong ninstrs; ulong ninstrs;
// Last COND field
uint cond;
}; };
#define R(X) ctx->rf[X] #define R(X) ctx->rf[X]

View File

@ -7,7 +7,8 @@
// Read the "DECD" file before reading this code // Read the "DECD" file before reading this code
// //
static void check_param_type(ctx_t *ctx, instr_t *in, uint prm, uchar fmt, int which) static void check_param_type(ctx_t *ctx, instr_t *in,
uint prm, uchar fmt, int which)
{ {
bool ok; bool ok;
@ -153,7 +154,6 @@ void decode(ctx_t *ctx)
acc_t p3 = { 0 }; acc_t p3 = { 0 };
bool rep = 0; bool rep = 0;
uint cond = 0;
bool lock, nomore; bool lock, nomore;
ushort w1, w2; ushort w1, w2;
@ -172,9 +172,9 @@ void decode(ctx_t *ctx)
nomore = !!(w1 & SUFF_NOMORE); nomore = !!(w1 & SUFF_NOMORE);
if (w1 & SUFF_COND) if (w1 & SUFF_COND)
{ ctx->cond = ctx->get(ctx);
cond = ctx->get(ctx); else
} ctx->cond = 0;
w1 &= ~(SUFF_LOCK|SUFF_NOMORE|SUFF_COND); w1 &= ~(SUFF_LOCK|SUFF_NOMORE|SUFF_COND);
@ -217,7 +217,7 @@ void decode(ctx_t *ctx)
f1, f2, f3, in->full); f1, f2, f3, in->full);
} }
exec_instr(ctx, in, NULL, NULL, NULL, lock, rep, cond); exec_instr(ctx, in, NULL, NULL, NULL, lock, rep);
return; return;
} }
@ -237,7 +237,7 @@ void decode(ctx_t *ctx)
f1, f2, f3, in->full); f1, f2, f3, in->full);
} }
exec_instr(ctx, in, &p1, NULL, NULL, lock, rep, cond); exec_instr(ctx, in, &p1, NULL, NULL, lock, rep);
return; return;
} }
@ -257,13 +257,13 @@ void decode(ctx_t *ctx)
f1, f2, f3, in->full); f1, f2, f3, in->full);
} }
exec_instr(ctx, in, &p1, &p2, NULL, lock, rep, cond); exec_instr(ctx, in, &p1, &p2, NULL, lock, rep);
return; return;
} }
check_param_type(ctx, in, in->prm3, f3, 3); check_param_type(ctx, in, in->prm3, f3, 3);
extract_param(ctx, &p3, f3); extract_param(ctx, &p3, f3);
exec_instr(ctx, in, &p1, &p2, &p3, lock, rep, cond); exec_instr(ctx, in, &p1, &p2, &p3, lock, rep);
} }

View File

@ -81,14 +81,15 @@ struct instr_t
ulong *, ulong *, ulong *); ulong *, ulong *, ulong *);
}; };
bool eval_cond(ctx_t *ctx, uint cond);
void exec_instr(ctx_t *ctx, void exec_instr(ctx_t *ctx,
instr_t *in, instr_t *in,
acc_t *p1, acc_t *p1,
acc_t *p2, acc_t *p2,
acc_t *p3, acc_t *p3,
bool lock, bool lock,
bool rep, bool rep);
uint cond);
void extract_param(ctx_t *ctx, void extract_param(ctx_t *ctx,
acc_t *p, acc_t *p,
@ -100,6 +101,5 @@ void dump_instr(ctx_t *ctx,
acc_t *p2, acc_t *p2,
acc_t *p3, acc_t *p3,
bool lock, bool lock,
bool rep, bool rep);
uint cond);

View File

@ -13,10 +13,6 @@ char *cond_suffixes[] =
"?" "?"
}; };
#ifndef _ATT_STYLE
#define _ATT_STYLE 0
#endif
void dump_acc(ctx_t *ctx, acc_t *p); void dump_acc(ctx_t *ctx, acc_t *p);
void dump_instr(ctx_t *ctx, void dump_instr(ctx_t *ctx,
@ -25,12 +21,9 @@ void dump_instr(ctx_t *ctx,
acc_t *p2, acc_t *p2,
acc_t *p3, acc_t *p3,
bool lock, bool lock,
bool rep, bool rep)
uint cond)
{ {
/* uint cond = ctx->cond;
trace("%03lu 0x%lX:\t", ctx->ninstrs, pc);
*/
trace("0x%lX:\t", rpc); trace("0x%lX:\t", rpc);

View File

@ -2,6 +2,7 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
#include <pc/arch.h> #include <pc/arch.h>
#include <in/arch_i.h>
bool eval_cond(ctx_t *ctx, uint cond) bool eval_cond(ctx_t *ctx, uint cond)
{ {
@ -50,8 +51,7 @@ void exec_instr(ctx_t *ctx,
acc_t *p2, acc_t *p2,
acc_t *p3, acc_t *p3,
bool lock, bool lock,
bool rep, bool rep)
uint cond)
{ {
bool out; bool out;
ulong r1 = 0, r2 = 0, r3 = 0; ulong r1 = 0, r2 = 0, r3 = 0;
@ -67,17 +67,12 @@ void exec_instr(ctx_t *ctx,
// For REPs we evaluate the condition AFTER running the instruction, // For REPs we evaluate the condition AFTER running the instruction,
// in a do ... while(cond) fashion // in a do ... while(cond) fashion
// //
if (!rep && !eval_cond(ctx, cond)) if (ctx->cond && in->func != i_b) // 'B' instruction is special
{ if (!rep && !eval_cond(ctx, ctx->cond))
#ifndef NDEBUG return;
// Say something about ignored instruction?
//trace("0x%lX:\n", rpc);
#endif
return;
}
#ifndef NDEBUG #ifndef NDEBUG
dump_instr(ctx, in, p1, p2, p3, lock, rep, cond); dump_instr(ctx, in, p1, p2, p3, lock, rep);
#endif #endif
do_rep: do_rep:
@ -132,7 +127,7 @@ do_rep:
if (rep) if (rep)
{ {
// RCX remains untouched when condition fails // RCX remains untouched when condition fails
if (!eval_cond(ctx, cond)) if (!eval_cond(ctx, ctx->cond))
return; return;
if (rcx > 0) if (rcx > 0)
@ -145,7 +140,7 @@ do_rep:
#ifndef NDEBUG #ifndef NDEBUG
// Show that we're REP'ing // Show that we're REP'ing
dump_instr(ctx, in, p1, p2, p3, lock, rep, cond); dump_instr(ctx, in, p1, p2, p3, lock, rep);
#endif #endif
goto do_rep; goto do_rep;