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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,6 +10,23 @@
#
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)
#

View File

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

View File

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

View File

@ -13,6 +13,24 @@ IMPL_START_1(prn)
}
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)
{
v1 = console_scankeybuf(ctx);

View File

@ -3,9 +3,7 @@
#include <in/instrs.h>
//
// Jump instructions
//
//----------------------------------------------------------------------------//
IMPL_START_1(j)
{
@ -28,24 +26,16 @@ IMPL_START_1(loop)
}
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_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) \
IMPL_START_3(k##name) \
{ \
v1 = expr; \
v1 = (expr); \
} \
IMPL_OUT_ZSF

View File

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

View File

@ -7,7 +7,8 @@
// 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;
@ -153,7 +154,6 @@ void decode(ctx_t *ctx)
acc_t p3 = { 0 };
bool rep = 0;
uint cond = 0;
bool lock, nomore;
ushort w1, w2;
@ -172,9 +172,9 @@ void decode(ctx_t *ctx)
nomore = !!(w1 & SUFF_NOMORE);
if (w1 & SUFF_COND)
{
cond = ctx->get(ctx);
}
ctx->cond = ctx->get(ctx);
else
ctx->cond = 0;
w1 &= ~(SUFF_LOCK|SUFF_NOMORE|SUFF_COND);
@ -217,7 +217,7 @@ void decode(ctx_t *ctx)
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;
}
@ -237,7 +237,7 @@ void decode(ctx_t *ctx)
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;
}
@ -257,13 +257,13 @@ void decode(ctx_t *ctx)
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;
}
check_param_type(ctx, in, in->prm3, f3, 3);
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 *);
};
bool eval_cond(ctx_t *ctx, uint cond);
void exec_instr(ctx_t *ctx,
instr_t *in,
acc_t *p1,
acc_t *p2,
acc_t *p3,
bool lock,
bool rep,
uint cond);
bool rep);
void extract_param(ctx_t *ctx,
acc_t *p,
@ -100,6 +101,5 @@ void dump_instr(ctx_t *ctx,
acc_t *p2,
acc_t *p3,
bool lock,
bool rep,
uint cond);
bool rep);

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_instr(ctx_t *ctx,
@ -25,12 +21,9 @@ void dump_instr(ctx_t *ctx,
acc_t *p2,
acc_t *p3,
bool lock,
bool rep,
uint cond)
bool rep)
{
/*
trace("%03lu 0x%lX:\t", ctx->ninstrs, pc);
*/
uint cond = ctx->cond;
trace("0x%lX:\t", rpc);

View File

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