Add immediate loading and change the register argument placement in store
This commit is contained in:
parent
06f4c731c3
commit
3eba71ab0e
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
205
emulator.pas
205
emulator.pas
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
13
readme.md
13
readme.md
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue