Add immediate loading and change the register argument placement in store

This commit is contained in:
CrazyEttin 2022-08-25 17:19:32 +03:00
parent 06f4c731c3
commit 3eba71ab0e
6 changed files with 317 additions and 253 deletions

View File

@ -349,14 +349,33 @@ begin
//First argument
OneArgReg (2);
//Second argument
AddrArg (3, 1);
//Immediate
if LeftStr (Elem [3], 1) = '#' then begin
Elem [3] := TrimLeftSet (Elem [3], ['#']);
if (BP + 1) >= $fff0 then MemError;
try
if Hex2Dec (Elem [3]) <= $ff then begin
Bin [BP] := Bin [BP] + 3;
Bin [BP + 1] := Hex2Dec (Elem [3]);
end
else ArgError;
except
ArgError;
end;
end
//Address
else AddrArg (3, 1);
end;
//Store
if Bin [BP] = $b0 then begin
//First argument
AddrArg (2, 1);
//Second argument
OneArgReg (3);
if CompareText (Elem [3], 'R0') = 0 then Bin [BP] := Bin [BP] + 0
else if CompareText (Elem [3], 'R1') = 0 then Bin [BP] := Bin [BP] + 1
else if CompareText (Elem [3], 'R2') = 0 then Bin [BP] := Bin [BP] + 2
else if CompareText (Elem [3], 'R3') = 0 then Bin [BP] := Bin [BP] + 3
else ArgError;
end;
//Branches and calls
if Bin [BP] >= $c0 then begin
@ -367,7 +386,13 @@ begin
end;
//Increment the byte pointer
if Bin [BP] >= $a0 then BP := BP + 3
if Bin [BP] >= $a0 then begin
if Bin [BP] <= $af then begin
if (Bin [BP] and 3) <> 0 then BP := BP + 2
else BP := BP + 3;
end
else BP := BP + 3;
end
else BP := BP + 1;
end;

View File

@ -75,18 +75,36 @@ begin
X := Bin [BP] and $c shr 2;
Y := Bin [BP] and 3;
BP := BP + 1;
//Address argument
//Immediate or address argument
if Op >= $a then begin
//Immediate or high byte of address
Addr := Bin [BP];
Addr := Addr shl 8;
BP := BP + 1;
Addr := Addr + Bin [BP];
BP := BP - 1;
//Low byte of address
if Op = $a then begin
if Y = 0 then begin
Addr := Addr + Bin [BP];
BP := BP - 1;
end
else BP := BP - 1;
end
else begin
Addr := Addr + Bin [BP];
BP := BP - 1;
end;
end;
//Print the data
write (IntToHex (Op, 1), IntToHex (Regs, 1));
if Op >= $a then write (IntToHex (Addr, 4)) else write (' ');
if Op >= $a then begin
if Op = $a then begin
if Y = 0 then write (IntToHex (Addr, 4))
else write (IntToHex (Addr shr 8, 2), ' ');
end
else write (IntToHex (Addr, 4));
end
else write (' ');
write (' ');
//Print the instruction
@ -96,7 +114,13 @@ begin
if Op >= 2 then write ('R', X);
if Op >= 6 then if Op <= 9 then write (', R', Y);
if OP >= $c then write (', R', Y);
if Op >= $a then write (', ', IntToHex (Addr, 1));
if Op >= $a then begin
if Op = $a then begin
if Y = 0 then write (', ', IntToHex (Addr, 1))
else write (', #', IntToHex (Addr shr 8, 1))
end
else write (', ', IntToHex (Addr, 1));
end;
writeln ();
end;

View File

@ -21,7 +21,7 @@ var
Hlt, ASCII, Verbose: boolean; //Halt, ASCII, and verbose flags
Op, Regs: 0 .. $f; //Opcode
X, Y: 0 .. 3; //Register arguments
Addr, IP, RP: word; //Address argument and instruction and return pointers
Addr, IP, RP: word; //Immediate or address argument and instruction and return pointers
R: array [0 .. 3] of byte; //General-purpose registers
Mem: array [0 .. $ffef] of byte; //Memory
Prog{$ifdef printer}, Prn{$endif}{$ifdef tape}, TapeIn, TapeOut{$endif}: file of byte; //Program file, line printer, and tape reader and punch tapes
@ -138,9 +138,9 @@ begin
writeln ('Error: illegal instruction pointer value');
halt;
end;
//Address argument
//Immediate or address argument
if Op >= $a then begin
//High byte
//Immediate or high byte of address
Addr := Mem [IP];
Addr := Addr shl 8;
IP := IP + 1;
@ -148,12 +148,24 @@ begin
writeln ('Error: illegal instruction pointer value');
halt;
end;
//Low byte
Addr := Addr + Mem [IP];
IP := IP + 1;
if IP > $ffef then begin
writeln ('Error: illegal instruction pointer value');
halt;
//Low byte of address
if Op = $a then begin
if Y = 0 then begin
Addr := Addr + Mem [IP];
IP := IP + 1;
if IP > $ffef then begin
writeln ('Error: illegal instruction pointer value');
halt;
end;
end;
end
else begin
Addr := Addr + Mem [IP];
IP := IP + 1;
if IP > $ffef then begin
writeln ('Error: illegal instruction pointer value');
halt;
end;
end;
end
else Addr := 0;
@ -197,99 +209,104 @@ begin
else if Op = 9 then R [X] := R [X] xor R [Y]
//Load
else if Op = $a then begin
//Terminal input
if Addr = IO then begin
wait;
//Read a keypress
repeat
Ch := ReadKey;
//Check for non-ASCII keys
if Ch = ansichar (0) then begin
//Non-ASCII
if keypressed then begin
Scan := ReadKey;
//The delete key inserts the delete character
if Scan = ansichar ($53) then begin
Ch := ansichar ($7f);
ASCII := true;
//Immediate
if Y <> 0 then R [X] := Addr shr 8
//Address
else begin
//Terminal input
if Addr = IO then begin
wait;
//Read a keypress
repeat
Ch := ReadKey;
//Check for non-ASCII keys
if Ch = ansichar (0) then begin
//Non-ASCII
if keypressed then begin
Scan := ReadKey;
//The delete key inserts the delete character
if Scan = ansichar ($53) then begin
Ch := ansichar ($7f);
ASCII := true;
end
//Unused function keys insert a null
else ASCII := true;
end
//Unused function keys insert a null
//Null
else ASCII := true;
end
//Null
//Other ASCII
else ASCII := true;
until ASCII = true;
//Bodge for the home and end keys
if Ch = ansichar ($37) then begin
if keypressed then begin
Scan := ReadKey;
Scan := ReadKey;
Scan := ReadKey;
Ch := ansichar (0);
end;
end
//Other ASCII
else ASCII := true;
until ASCII = true;
//Bodge for the home and end keys
if Ch = ansichar ($37) then begin
if keypressed then begin
Scan := ReadKey;
Scan := ReadKey;
Scan := ReadKey;
Ch := ansichar (0);
else if Ch = ansichar ($38) then begin
if keypressed then begin
Scan := ReadKey;
Scan := ReadKey;
Scan := ReadKey;
Ch := ansichar (0);
end;
end;
//Process the keypress
Output; //Local echo
R [X] := byte (Ch);
end
//Tape reader
{$ifdef tape}
else if Addr = $fffd then begin
wait;
assign (State, ExpandFileName ('~/.tapes.thingamajig'));
//Check the reader state
if FileExists (ExpandFileName ('~/.tapes.thingamajig')) then begin
try
reset (State);
read (State, Reader);
read (State, Punch);
close (State);
except
end;
end;
//Read
assign (TapeIn, Reader.Path);
try
reset (TapeIn);
seek (TapeIn, Reader.Pos);
read (TapeIn, R [X]);
close (TapeIn);
Reader.Pos := Reader.Pos + 1;
except
R [X] := $ff;
end;
//Save the reader state
if FileExists (ExpandFileName ('~/.tapes.thingamajig')) then begin
try
rewrite (State);
write (State, Reader);
write (State, Punch);
close (State);
except
end;
end;
end
else if Ch = ansichar ($38) then begin
if keypressed then begin
Scan := ReadKey;
Scan := ReadKey;
Scan := ReadKey;
Ch := ansichar (0);
end;
end;
//Process the keypress
Output; //Local echo
R [X] := byte (Ch);
end
//Tape reader
{$ifdef tape}
else if Addr = $fffd then begin
wait;
assign (State, ExpandFileName ('~/.tapes.thingamajig'));
//Check the reader state
if FileExists (ExpandFileName ('~/.tapes.thingamajig')) then begin
try
reset (State);
read (State, Reader);
read (State, Punch);
close (State);
except
end;
end;
//Read
assign (TapeIn, Reader.Path);
try
reset (TapeIn);
seek (TapeIn, Reader.Pos);
read (TapeIn, R [X]);
close (TapeIn);
Reader.Pos := Reader.Pos + 1;
except
R [X] := $ff;
end;
//Save the reader state
if FileExists (ExpandFileName ('~/.tapes.thingamajig')) then begin
try
rewrite (State);
write (State, Reader);
write (State, Punch);
close (State);
except
end;
end;
end
{$endif}
//Regular load
else R [X] := Mem [Addr];
{$endif}
//Regular load
else R [X] := Mem [Addr];
end;
end
//Store
else if Op = $b then begin
//Terminal output
if Addr = IO then begin
wait;
Ch := ansichar (R [X]);
Ch := ansichar (R [Y]);
Output;
end
//Printer
@ -299,7 +316,7 @@ begin
assign (Prn, '/dev/usb/lp0');
try
rewrite (Prn);
write (Prn, R [X]);
write (Prn, R [Y]);
close (Prn);
except
end;
@ -326,7 +343,7 @@ begin
if FileExists (Punch.Path) = false then begin
try
rewrite (TapeOut);
write (TapeOut, R [X]);
write (TapeOut, R [Y]);
close (TapeOut);
Punch.Reset := false;
except
@ -335,7 +352,7 @@ begin
else if Punch.Reset then begin
try
rewrite (TapeOut);
write (TapeOut, R [X]);
write (TapeOut, R [Y]);
close (TapeOut);
Punch.Reset := false;
except
@ -345,7 +362,7 @@ begin
try
reset (TapeOut);
seek (TapeOut, FileSize (TapeOut));
write (TapeOut, R [X]);
write (TapeOut, R [Y]);
close (TapeOut);
except
end;
@ -364,7 +381,7 @@ begin
end
{$endif}
//Regular store
else Mem [Addr] := R [X];
else Mem [Addr] := R [Y];
end
//Breq
else if Op = $c then begin

View File

@ -1,9 +1,9 @@
;ASCII code printer
;Print a prompt
load r0, prompt
load r0, #3e
store ffff, r0
load r0, space
load r0, #20
store ffff, r0
;Read a character to r0 and load it to r2
@ -11,11 +11,8 @@
xor r2, r2
xor r2, r0
;Print a newline and align
;Print a newline
cleq r0, r0, newln
load r1, space
store ffff, r1
store ffff, r1
;Convert and print the high nibble
;Convert
@ -46,9 +43,9 @@
;***
;Print a newline
newln: load r1, cr
newln: load r1, #d
store ffff, r1
load r1, lf
load r1, #a
store ffff, r1
ret
@ -57,126 +54,77 @@ newln: load r1, cr
;Get the hexadecimal digit of a nibble
;Extract the low nibble
n2hex: load r1, mask
n2hex: load r1, #f
and r0, r1
;Locate the nibble in the table
load r1, nbl0
load r1, #0
breq r0, r1, dgt0
load r1, nbl1
load r1, #1
breq r0, r1, dgt1
load r1, nbl2
load r1, #2
breq r0, r1, dgt2
load r1, nbl3
load r1, #3
breq r0, r1, dgt3
load r1, nbl4
load r1, #4
breq r0, r1, dgt4
load r1, nbl5
load r1, #5
breq r0, r1, dgt5
load r1, nbl6
load r1, #6
breq r0, r1, dgt6
load r1, nbl7
load r1, #7
breq r0, r1, dgt7
load r1, nbl8
load r1, #8
breq r0, r1, dgt8
load r1, nbl9
load r1, #9
breq r0, r1, dgt9
load r1, nbla
load r1, #a
breq r0, r1, dgta
load r1, nblb
load r1, #b
breq r0, r1, dgtb
load r1, nblc
load r1, #c
breq r0, r1, dgtc
load r1, nbld
load r1, #d
breq r0, r1, dgtd
load r1, nble
load r1, #e
breq r0, r1, dgte
load r1, nblf
load r1, #f
breq r0, r1, dgtf
;Load the hexadecimal digit of the nibble
dgt0: load r0, hex0
dgt0: load r0, #30
breq r0, r0, n2hend
dgt1: load r0, hex1
dgt1: load r0, #31
breq r0, r0, n2hend
dgt2: load r0, hex2
dgt2: load r0, #32
breq r0, r0, n2hend
dgt3: load r0, hex3
dgt3: load r0, #33
breq r0, r0, n2hend
dgt4: load r0, hex4
dgt4: load r0, #34
breq r0, r0, n2hend
dgt5: load r0, hex5
dgt5: load r0, #35
breq r0, r0, n2hend
dgt6: load r0, hex6
dgt6: load r0, #36
breq r0, r0, n2hend
dgt7: load r0, hex7
dgt7: load r0, #37
breq r0, r0, n2hend
dgt8: load r0, hex8
dgt8: load r0, #38
breq r0, r0, n2hend
dgt9: load r0, hex9
dgt9: load r0, #39
breq r0, r0, n2hend
dgta: load r0, hexa
dgta: load r0, #41
breq r0, r0, n2hend
dgtb: load r0, hexb
dgtb: load r0, #42
breq r0, r0, n2hend
dgtc: load r0, hexc
dgtc: load r0, #43
breq r0, r0, n2hend
dgtd: load r0, hexd
dgtd: load r0, #44
breq r0, r0, n2hend
dgte: load r0, hexe
dgte: load r0, #45
breq r0, r0, n2hend
dgtf: load r0, hexf
dgtf: load r0, #46
breq r0, r0, n2hend
;Return
n2hend: ret
;***
;Data
;Characters
cr: data d
lf: data a
space: data 20
prompt: data 3e
;Mask
mask: data f
;Nibble table
nbl0: data 0
nbl1: data 1
nbl2: data 2
nbl3: data 3
nbl4: data 4
nbl5: data 5
nbl6: data 6
nbl7: data 7
nbl8: data 8
nbl9: data 9
nbla: data a
nblb: data b
nblc: data c
nbld: data d
nble: data e
nblf: data f
;Hexadecimal table
hex0: data 30
hex1: data 31
hex2: data 32
hex3: data 33
hex4: data 34
hex5: data 35
hex6: data 36
hex7: data 37
hex8: data 38
hex9: data 39
hexa: data 41
hexb: data 42
hexc: data 43
hexd: data 44
hexe: data 45
hexf: data 46


View File

@ -4,6 +4,12 @@
;Input
;Print a prompt
load r0, #3e
store ffff, r0
load r0, #20
store ffff, r0
;Restore the buffer start address
;High byte
input: load r0, bfstrt
@ -12,12 +18,6 @@ input: load r0, bfstrt
load r0, bfstrt + 1
store chstor + 2, r0
;Print a prompt
load r0, prompt
store ffff, r0
load r0, space
store ffff, r0
;Initialise the character counter
xor r0, r0
@ -25,18 +25,24 @@ input: load r0, bfstrt
inloop: load r1, ffff
;Check for control characters and the buffer end
;Delete
load r2, #7f
breq r1, r2, delbr
;Escape
load r2, esc
load r2, #1b
breq r1, r2, escbr
;Carriage return
load r2, cr
load r2, #d
breq r1, r2, crbr
;Line feed
load r2, #a
breq r1, r2, lfbr
;Buffer end
load r2, bfsize
brneq r0, r2, chstor
;Backtrack if at the buffer end
load r2, bs
load r2, #8
store ffff, r2
breq r0, r0, inloop
@ -45,7 +51,7 @@ chstor: store buffer, r1
;Increment the character counter and store it in r3
;Increment
load r2, one
load r2, #1
cleq r0, r0, sum
;Store
xor r3, r3
@ -54,7 +60,48 @@ chstor: store buffer, r1
;Increment the buffer address
;Low byte
load r0, chstor + 2
load r2, one
load r2, #1
cleq r0, r0, sum
store chstor + 2, r0
;Add the overflow to the high byte
load r0, chstor + 1
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store chstor + 1, r0
;Reload the character counter to r0
xor r0, r0
xor r0, r3
;Read the next character
breq r0, r0, inloop
;Print an underscore
delbr: load r2, #5f
store ffff, r2
;Check for buffer start
xor r2, r2
breq r0, r2, inloop
;Decrement the character counter and store it in r3
;Decrement
load r2, #ff
cleq r0, r0, sum
;Store
xor r3, r3
xor r3, r0
;Decrement the buffer address
;High byte
load r0, chstor + 1
load r2, #ff
cleq r0, r0, sum
store chstor + 1, r0
;Low byte
load r0, chstor + 2
load r2, #ff
cleq r0, r0, sum
store chstor + 2, r0
;Add the overflow to the high byte
@ -73,56 +120,78 @@ chstor: store buffer, r1
;Print a backslash and a newline
;Backslash
escbr: load r0, space
escbr: load r0, #20
store ffff, r0
load r0, bslash
load r0, #5c
store ffff, r0
;Newline
load r0, cr
load r0, #d
store ffff, r0
load r0, #a
store ffff, r0
;Align
load r0, #20
store ffff, r0
load r0, lf
store ffff, r0
;Start a new input line
breq r0, r0, input
;Store a string-terminating zero in the buffer
;Print a line feed
crbr: load r0, #a
store ffff, r0
breq r0, r0, endnul
;Print a carriage return
lfbr: load r0, #d
store ffff, r0
;Store a carriage return in the buffer
;Get the buffer address
crbr: load r1, chstor + 1
endnul: load r1, chstor + 1
store endsto + 1, r1
load r1, chstor + 2
store endsto + 2, r1
;Store
xor r0, r0
endsto: store 0000, r0
load r0, #d
endsto: store 0, r0
;Increment the buffer address
;Low byte
load r0, endsto + 2
load r2, #1
cleq r0, r0, sum
store endlf + 2, r0
;Add the overflow to the high byte
load r0, endsto + 1
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store endlf + 1, r0
;Store a line feed in the buffer
load r0, #a
endlf: store 0, r0
;***
;Print
;Print a line feed and align with the input
;Line feed
load r0, lf
store ffff, r0
;Align
load r0, space
store ffff, r0
store ffff, r0
;Load a character from the buffer
chprnt: load r1, buffer
;Check for string end
xor r2, r2
breq r1, r2, end
;Print the character
store ffff, r1
;Check for string end
load r2, #a
breq r1, r2, end
;Increment the buffer address
;Low byte
load r0, chprnt + 2
load r2, one
load r2, #1
cleq r0, r0, sum
store chprnt + 2, r0
;Add the overflow to the high byte
@ -135,14 +204,8 @@ chprnt: load r1, buffer
;Print the next character
breq r0, r0, chprnt
;Print a newline
end: load r0, cr
store ffff, r0
load r0, lf
store ffff, r0
;Halt
halt
end: halt
;***
@ -172,7 +235,7 @@ sumlop: xor r1, r1
rol r1
breq r1, r2, nvrflw
;Store
load r1, one
load r1, #1
store ovrflw, r1
;Check for no carry
@ -190,24 +253,12 @@ sumend: load r1, ovrflw
;Data
;Constants
one: data 1
;Characters
bs: data 8
lf: data a
cr: data d
esc: data 1b
space: data 20
prompt: data 3e
bslash: data 5c
;Variables
ovrflw: data 0
;Buffer
bfstrt: addr buffer
bfsize: data ff
bfsize: data fe
buffer:


View File

@ -37,9 +37,9 @@ respectively, while other registers and memory are unitialised.
Instructions
------------
Instructions without an address argument are 8-bit and those with one
24-bit. The instruction pointer is incremented before being accessed or
modified.
Instructions without an immediate or address argument are 8-bit, those
with an immediate one 16-bit, and those with an address one 24-bit. The
instruction pointer is incremented before being accessed or modified.
0 HALT
1 RET IP = *RP; RP += 2
@ -54,10 +54,9 @@ modified.
8 OR RX, RY RX |= RY
9 XOR RX, RY RX ^= RY
A LOAD RX, ADDR RX = *ADDR
B STORE RX, ADDR *ADDR = RX Written as "STORE ADDR, RX" in
assembly for the sake of
consistency.
A LOAD RX, ~0, IMM RX = IMM Written as "LOAD RX, #IMM"
0, ADDR RX = *ADDR Written as "LOAD RX, ADDR"
B STORE RY, ADDR *ADDR = RY Written as "STORE ADDR, RY"
C BREQ RX, RY, ADDR if (RX == RY) IP = ADDR
D BRNEQ RX, RY, ADDR if (RX != RY) IP = ADDR