Add immediate loading and change the register argument placement in store
This commit is contained in:
parent
06f4c731c3
commit
3eba71ab0e
6 changed files with 317 additions and 253 deletions
|
@ -349,14 +349,33 @@ begin
|
||||||
//First argument
|
//First argument
|
||||||
OneArgReg (2);
|
OneArgReg (2);
|
||||||
//Second argument
|
//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;
|
end;
|
||||||
//Store
|
//Store
|
||||||
if Bin [BP] = $b0 then begin
|
if Bin [BP] = $b0 then begin
|
||||||
//First argument
|
//First argument
|
||||||
AddrArg (2, 1);
|
AddrArg (2, 1);
|
||||||
//Second argument
|
//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;
|
end;
|
||||||
//Branches and calls
|
//Branches and calls
|
||||||
if Bin [BP] >= $c0 then begin
|
if Bin [BP] >= $c0 then begin
|
||||||
|
@ -367,7 +386,13 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//Increment the byte pointer
|
//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;
|
else BP := BP + 1;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
|
@ -75,18 +75,36 @@ begin
|
||||||
X := Bin [BP] and $c shr 2;
|
X := Bin [BP] and $c shr 2;
|
||||||
Y := Bin [BP] and 3;
|
Y := Bin [BP] and 3;
|
||||||
BP := BP + 1;
|
BP := BP + 1;
|
||||||
//Address argument
|
//Immediate or address argument
|
||||||
if Op >= $a then begin
|
if Op >= $a then begin
|
||||||
|
//Immediate or high byte of address
|
||||||
Addr := Bin [BP];
|
Addr := Bin [BP];
|
||||||
Addr := Addr shl 8;
|
Addr := Addr shl 8;
|
||||||
BP := BP + 1;
|
BP := BP + 1;
|
||||||
Addr := Addr + Bin [BP];
|
//Low byte of address
|
||||||
BP := BP - 1;
|
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;
|
end;
|
||||||
|
|
||||||
//Print the data
|
//Print the data
|
||||||
write (IntToHex (Op, 1), IntToHex (Regs, 1));
|
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 (' ');
|
write (' ');
|
||||||
|
|
||||||
//Print the instruction
|
//Print the instruction
|
||||||
|
@ -96,7 +114,13 @@ begin
|
||||||
if Op >= 2 then write ('R', X);
|
if Op >= 2 then write ('R', X);
|
||||||
if Op >= 6 then if Op <= 9 then write (', R', Y);
|
if Op >= 6 then if Op <= 9 then write (', R', Y);
|
||||||
if OP >= $c 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 ();
|
writeln ();
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
205
emulator.pas
205
emulator.pas
|
@ -21,7 +21,7 @@ var
|
||||||
Hlt, ASCII, Verbose: boolean; //Halt, ASCII, and verbose flags
|
Hlt, ASCII, Verbose: boolean; //Halt, ASCII, and verbose flags
|
||||||
Op, Regs: 0 .. $f; //Opcode
|
Op, Regs: 0 .. $f; //Opcode
|
||||||
X, Y: 0 .. 3; //Register arguments
|
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
|
R: array [0 .. 3] of byte; //General-purpose registers
|
||||||
Mem: array [0 .. $ffef] of byte; //Memory
|
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
|
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');
|
writeln ('Error: illegal instruction pointer value');
|
||||||
halt;
|
halt;
|
||||||
end;
|
end;
|
||||||
//Address argument
|
//Immediate or address argument
|
||||||
if Op >= $a then begin
|
if Op >= $a then begin
|
||||||
//High byte
|
//Immediate or high byte of address
|
||||||
Addr := Mem [IP];
|
Addr := Mem [IP];
|
||||||
Addr := Addr shl 8;
|
Addr := Addr shl 8;
|
||||||
IP := IP + 1;
|
IP := IP + 1;
|
||||||
|
@ -148,12 +148,24 @@ begin
|
||||||
writeln ('Error: illegal instruction pointer value');
|
writeln ('Error: illegal instruction pointer value');
|
||||||
halt;
|
halt;
|
||||||
end;
|
end;
|
||||||
//Low byte
|
//Low byte of address
|
||||||
Addr := Addr + Mem [IP];
|
if Op = $a then begin
|
||||||
IP := IP + 1;
|
if Y = 0 then begin
|
||||||
if IP > $ffef then begin
|
Addr := Addr + Mem [IP];
|
||||||
writeln ('Error: illegal instruction pointer value');
|
IP := IP + 1;
|
||||||
halt;
|
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;
|
||||||
end
|
end
|
||||||
else Addr := 0;
|
else Addr := 0;
|
||||||
|
@ -197,99 +209,104 @@ begin
|
||||||
else if Op = 9 then R [X] := R [X] xor R [Y]
|
else if Op = 9 then R [X] := R [X] xor R [Y]
|
||||||
//Load
|
//Load
|
||||||
else if Op = $a then begin
|
else if Op = $a then begin
|
||||||
//Terminal input
|
//Immediate
|
||||||
if Addr = IO then begin
|
if Y <> 0 then R [X] := Addr shr 8
|
||||||
wait;
|
//Address
|
||||||
//Read a keypress
|
else begin
|
||||||
repeat
|
//Terminal input
|
||||||
Ch := ReadKey;
|
if Addr = IO then begin
|
||||||
//Check for non-ASCII keys
|
wait;
|
||||||
if Ch = ansichar (0) then begin
|
//Read a keypress
|
||||||
//Non-ASCII
|
repeat
|
||||||
if keypressed then begin
|
Ch := ReadKey;
|
||||||
Scan := ReadKey;
|
//Check for non-ASCII keys
|
||||||
//The delete key inserts the delete character
|
if Ch = ansichar (0) then begin
|
||||||
if Scan = ansichar ($53) then begin
|
//Non-ASCII
|
||||||
Ch := ansichar ($7f);
|
if keypressed then begin
|
||||||
ASCII := true;
|
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
|
end
|
||||||
//Unused function keys insert a null
|
//Null
|
||||||
else ASCII := true;
|
else ASCII := true;
|
||||||
end
|
end
|
||||||
//Null
|
//Other ASCII
|
||||||
else ASCII := true;
|
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
|
end
|
||||||
//Other ASCII
|
else if Ch = ansichar ($38) then begin
|
||||||
else ASCII := true;
|
if keypressed then begin
|
||||||
until ASCII = true;
|
Scan := ReadKey;
|
||||||
//Bodge for the home and end keys
|
Scan := ReadKey;
|
||||||
if Ch = ansichar ($37) then begin
|
Scan := ReadKey;
|
||||||
if keypressed then begin
|
Ch := ansichar (0);
|
||||||
Scan := ReadKey;
|
end;
|
||||||
Scan := ReadKey;
|
end;
|
||||||
Scan := ReadKey;
|
//Process the keypress
|
||||||
Ch := ansichar (0);
|
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;
|
||||||
end
|
end
|
||||||
else if Ch = ansichar ($38) then begin
|
{$endif}
|
||||||
if keypressed then begin
|
//Regular load
|
||||||
Scan := ReadKey;
|
else R [X] := Mem [Addr];
|
||||||
Scan := ReadKey;
|
end;
|
||||||
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];
|
|
||||||
end
|
end
|
||||||
//Store
|
//Store
|
||||||
else if Op = $b then begin
|
else if Op = $b then begin
|
||||||
//Terminal output
|
//Terminal output
|
||||||
if Addr = IO then begin
|
if Addr = IO then begin
|
||||||
wait;
|
wait;
|
||||||
Ch := ansichar (R [X]);
|
Ch := ansichar (R [Y]);
|
||||||
Output;
|
Output;
|
||||||
end
|
end
|
||||||
//Printer
|
//Printer
|
||||||
|
@ -299,7 +316,7 @@ begin
|
||||||
assign (Prn, '/dev/usb/lp0');
|
assign (Prn, '/dev/usb/lp0');
|
||||||
try
|
try
|
||||||
rewrite (Prn);
|
rewrite (Prn);
|
||||||
write (Prn, R [X]);
|
write (Prn, R [Y]);
|
||||||
close (Prn);
|
close (Prn);
|
||||||
except
|
except
|
||||||
end;
|
end;
|
||||||
|
@ -326,7 +343,7 @@ begin
|
||||||
if FileExists (Punch.Path) = false then begin
|
if FileExists (Punch.Path) = false then begin
|
||||||
try
|
try
|
||||||
rewrite (TapeOut);
|
rewrite (TapeOut);
|
||||||
write (TapeOut, R [X]);
|
write (TapeOut, R [Y]);
|
||||||
close (TapeOut);
|
close (TapeOut);
|
||||||
Punch.Reset := false;
|
Punch.Reset := false;
|
||||||
except
|
except
|
||||||
|
@ -335,7 +352,7 @@ begin
|
||||||
else if Punch.Reset then begin
|
else if Punch.Reset then begin
|
||||||
try
|
try
|
||||||
rewrite (TapeOut);
|
rewrite (TapeOut);
|
||||||
write (TapeOut, R [X]);
|
write (TapeOut, R [Y]);
|
||||||
close (TapeOut);
|
close (TapeOut);
|
||||||
Punch.Reset := false;
|
Punch.Reset := false;
|
||||||
except
|
except
|
||||||
|
@ -345,7 +362,7 @@ begin
|
||||||
try
|
try
|
||||||
reset (TapeOut);
|
reset (TapeOut);
|
||||||
seek (TapeOut, FileSize (TapeOut));
|
seek (TapeOut, FileSize (TapeOut));
|
||||||
write (TapeOut, R [X]);
|
write (TapeOut, R [Y]);
|
||||||
close (TapeOut);
|
close (TapeOut);
|
||||||
except
|
except
|
||||||
end;
|
end;
|
||||||
|
@ -364,7 +381,7 @@ begin
|
||||||
end
|
end
|
||||||
{$endif}
|
{$endif}
|
||||||
//Regular store
|
//Regular store
|
||||||
else Mem [Addr] := R [X];
|
else Mem [Addr] := R [Y];
|
||||||
end
|
end
|
||||||
//Breq
|
//Breq
|
||||||
else if Op = $c then begin
|
else if Op = $c then begin
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
;ASCII code printer
|
;ASCII code printer
|
||||||
|
|
||||||
;Print a prompt
|
;Print a prompt
|
||||||
load r0, prompt
|
load r0, #3e
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
load r0, space
|
load r0, #20
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
|
|
||||||
;Read a character to r0 and load it to r2
|
;Read a character to r0 and load it to r2
|
||||||
|
@ -11,11 +11,8 @@
|
||||||
xor r2, r2
|
xor r2, r2
|
||||||
xor r2, r0
|
xor r2, r0
|
||||||
|
|
||||||
;Print a newline and align
|
;Print a newline
|
||||||
cleq r0, r0, newln
|
cleq r0, r0, newln
|
||||||
load r1, space
|
|
||||||
store ffff, r1
|
|
||||||
store ffff, r1
|
|
||||||
|
|
||||||
;Convert and print the high nibble
|
;Convert and print the high nibble
|
||||||
;Convert
|
;Convert
|
||||||
|
@ -46,9 +43,9 @@
|
||||||
;***
|
;***
|
||||||
|
|
||||||
;Print a newline
|
;Print a newline
|
||||||
newln: load r1, cr
|
newln: load r1, #d
|
||||||
store ffff, r1
|
store ffff, r1
|
||||||
load r1, lf
|
load r1, #a
|
||||||
store ffff, r1
|
store ffff, r1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -57,126 +54,77 @@ newln: load r1, cr
|
||||||
;Get the hexadecimal digit of a nibble
|
;Get the hexadecimal digit of a nibble
|
||||||
|
|
||||||
;Extract the low nibble
|
;Extract the low nibble
|
||||||
n2hex: load r1, mask
|
n2hex: load r1, #f
|
||||||
and r0, r1
|
and r0, r1
|
||||||
|
|
||||||
;Locate the nibble in the table
|
;Locate the nibble in the table
|
||||||
load r1, nbl0
|
load r1, #0
|
||||||
breq r0, r1, dgt0
|
breq r0, r1, dgt0
|
||||||
load r1, nbl1
|
load r1, #1
|
||||||
breq r0, r1, dgt1
|
breq r0, r1, dgt1
|
||||||
load r1, nbl2
|
load r1, #2
|
||||||
breq r0, r1, dgt2
|
breq r0, r1, dgt2
|
||||||
load r1, nbl3
|
load r1, #3
|
||||||
breq r0, r1, dgt3
|
breq r0, r1, dgt3
|
||||||
load r1, nbl4
|
load r1, #4
|
||||||
breq r0, r1, dgt4
|
breq r0, r1, dgt4
|
||||||
load r1, nbl5
|
load r1, #5
|
||||||
breq r0, r1, dgt5
|
breq r0, r1, dgt5
|
||||||
load r1, nbl6
|
load r1, #6
|
||||||
breq r0, r1, dgt6
|
breq r0, r1, dgt6
|
||||||
load r1, nbl7
|
load r1, #7
|
||||||
breq r0, r1, dgt7
|
breq r0, r1, dgt7
|
||||||
load r1, nbl8
|
load r1, #8
|
||||||
breq r0, r1, dgt8
|
breq r0, r1, dgt8
|
||||||
load r1, nbl9
|
load r1, #9
|
||||||
breq r0, r1, dgt9
|
breq r0, r1, dgt9
|
||||||
load r1, nbla
|
load r1, #a
|
||||||
breq r0, r1, dgta
|
breq r0, r1, dgta
|
||||||
load r1, nblb
|
load r1, #b
|
||||||
breq r0, r1, dgtb
|
breq r0, r1, dgtb
|
||||||
load r1, nblc
|
load r1, #c
|
||||||
breq r0, r1, dgtc
|
breq r0, r1, dgtc
|
||||||
load r1, nbld
|
load r1, #d
|
||||||
breq r0, r1, dgtd
|
breq r0, r1, dgtd
|
||||||
load r1, nble
|
load r1, #e
|
||||||
breq r0, r1, dgte
|
breq r0, r1, dgte
|
||||||
load r1, nblf
|
load r1, #f
|
||||||
breq r0, r1, dgtf
|
breq r0, r1, dgtf
|
||||||
|
|
||||||
;Load the hexadecimal digit of the nibble
|
;Load the hexadecimal digit of the nibble
|
||||||
dgt0: load r0, hex0
|
dgt0: load r0, #30
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt1: load r0, hex1
|
dgt1: load r0, #31
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt2: load r0, hex2
|
dgt2: load r0, #32
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt3: load r0, hex3
|
dgt3: load r0, #33
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt4: load r0, hex4
|
dgt4: load r0, #34
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt5: load r0, hex5
|
dgt5: load r0, #35
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt6: load r0, hex6
|
dgt6: load r0, #36
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt7: load r0, hex7
|
dgt7: load r0, #37
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt8: load r0, hex8
|
dgt8: load r0, #38
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt9: load r0, hex9
|
dgt9: load r0, #39
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgta: load r0, hexa
|
dgta: load r0, #41
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgtb: load r0, hexb
|
dgtb: load r0, #42
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgtc: load r0, hexc
|
dgtc: load r0, #43
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgtd: load r0, hexd
|
dgtd: load r0, #44
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgte: load r0, hexe
|
dgte: load r0, #45
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgtf: load r0, hexf
|
dgtf: load r0, #46
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
|
|
||||||
;Return
|
;Return
|
||||||
n2hend: ret
|
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
|
;Input
|
||||||
|
|
||||||
|
;Print a prompt
|
||||||
|
load r0, #3e
|
||||||
|
store ffff, r0
|
||||||
|
load r0, #20
|
||||||
|
store ffff, r0
|
||||||
|
|
||||||
;Restore the buffer start address
|
;Restore the buffer start address
|
||||||
;High byte
|
;High byte
|
||||||
input: load r0, bfstrt
|
input: load r0, bfstrt
|
||||||
|
@ -12,12 +18,6 @@ input: load r0, bfstrt
|
||||||
load r0, bfstrt + 1
|
load r0, bfstrt + 1
|
||||||
store chstor + 2, r0
|
store chstor + 2, r0
|
||||||
|
|
||||||
;Print a prompt
|
|
||||||
load r0, prompt
|
|
||||||
store ffff, r0
|
|
||||||
load r0, space
|
|
||||||
store ffff, r0
|
|
||||||
|
|
||||||
;Initialise the character counter
|
;Initialise the character counter
|
||||||
xor r0, r0
|
xor r0, r0
|
||||||
|
|
||||||
|
@ -25,18 +25,24 @@ input: load r0, bfstrt
|
||||||
inloop: load r1, ffff
|
inloop: load r1, ffff
|
||||||
|
|
||||||
;Check for control characters and the buffer end
|
;Check for control characters and the buffer end
|
||||||
|
;Delete
|
||||||
|
load r2, #7f
|
||||||
|
breq r1, r2, delbr
|
||||||
;Escape
|
;Escape
|
||||||
load r2, esc
|
load r2, #1b
|
||||||
breq r1, r2, escbr
|
breq r1, r2, escbr
|
||||||
;Carriage return
|
;Carriage return
|
||||||
load r2, cr
|
load r2, #d
|
||||||
breq r1, r2, crbr
|
breq r1, r2, crbr
|
||||||
|
;Line feed
|
||||||
|
load r2, #a
|
||||||
|
breq r1, r2, lfbr
|
||||||
;Buffer end
|
;Buffer end
|
||||||
load r2, bfsize
|
load r2, bfsize
|
||||||
brneq r0, r2, chstor
|
brneq r0, r2, chstor
|
||||||
|
|
||||||
;Backtrack if at the buffer end
|
;Backtrack if at the buffer end
|
||||||
load r2, bs
|
load r2, #8
|
||||||
store ffff, r2
|
store ffff, r2
|
||||||
breq r0, r0, inloop
|
breq r0, r0, inloop
|
||||||
|
|
||||||
|
@ -45,7 +51,7 @@ chstor: store buffer, r1
|
||||||
|
|
||||||
;Increment the character counter and store it in r3
|
;Increment the character counter and store it in r3
|
||||||
;Increment
|
;Increment
|
||||||
load r2, one
|
load r2, #1
|
||||||
cleq r0, r0, sum
|
cleq r0, r0, sum
|
||||||
;Store
|
;Store
|
||||||
xor r3, r3
|
xor r3, r3
|
||||||
|
@ -54,7 +60,48 @@ chstor: store buffer, r1
|
||||||
;Increment the buffer address
|
;Increment the buffer address
|
||||||
;Low byte
|
;Low byte
|
||||||
load r0, chstor + 2
|
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
|
cleq r0, r0, sum
|
||||||
store chstor + 2, r0
|
store chstor + 2, r0
|
||||||
;Add the overflow to the high byte
|
;Add the overflow to the high byte
|
||||||
|
@ -73,56 +120,78 @@ chstor: store buffer, r1
|
||||||
|
|
||||||
;Print a backslash and a newline
|
;Print a backslash and a newline
|
||||||
;Backslash
|
;Backslash
|
||||||
escbr: load r0, space
|
escbr: load r0, #20
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
load r0, bslash
|
load r0, #5c
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
;Newline
|
;Newline
|
||||||
load r0, cr
|
load r0, #d
|
||||||
|
store ffff, r0
|
||||||
|
load r0, #a
|
||||||
|
store ffff, r0
|
||||||
|
|
||||||
|
;Align
|
||||||
|
load r0, #20
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
load r0, lf
|
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
|
|
||||||
;Start a new input line
|
;Start a new input line
|
||||||
breq r0, r0, input
|
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
|
;Get the buffer address
|
||||||
crbr: load r1, chstor + 1
|
endnul: load r1, chstor + 1
|
||||||
store endsto + 1, r1
|
store endsto + 1, r1
|
||||||
load r1, chstor + 2
|
load r1, chstor + 2
|
||||||
store endsto + 2, r1
|
store endsto + 2, r1
|
||||||
;Store
|
;Store
|
||||||
xor r0, r0
|
load r0, #d
|
||||||
endsto: store 0000, r0
|
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
|
||||||
|
|
||||||
;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
|
;Load a character from the buffer
|
||||||
chprnt: load r1, buffer
|
chprnt: load r1, buffer
|
||||||
|
|
||||||
;Check for string end
|
|
||||||
xor r2, r2
|
|
||||||
breq r1, r2, end
|
|
||||||
|
|
||||||
;Print the character
|
;Print the character
|
||||||
store ffff, r1
|
store ffff, r1
|
||||||
|
|
||||||
|
;Check for string end
|
||||||
|
load r2, #a
|
||||||
|
breq r1, r2, end
|
||||||
|
|
||||||
;Increment the buffer address
|
;Increment the buffer address
|
||||||
;Low byte
|
;Low byte
|
||||||
load r0, chprnt + 2
|
load r0, chprnt + 2
|
||||||
load r2, one
|
load r2, #1
|
||||||
cleq r0, r0, sum
|
cleq r0, r0, sum
|
||||||
store chprnt + 2, r0
|
store chprnt + 2, r0
|
||||||
;Add the overflow to the high byte
|
;Add the overflow to the high byte
|
||||||
|
@ -135,14 +204,8 @@ chprnt: load r1, buffer
|
||||||
;Print the next character
|
;Print the next character
|
||||||
breq r0, r0, chprnt
|
breq r0, r0, chprnt
|
||||||
|
|
||||||
;Print a newline
|
|
||||||
end: load r0, cr
|
|
||||||
store ffff, r0
|
|
||||||
load r0, lf
|
|
||||||
store ffff, r0
|
|
||||||
|
|
||||||
;Halt
|
;Halt
|
||||||
halt
|
end: halt
|
||||||
|
|
||||||
;***
|
;***
|
||||||
|
|
||||||
|
@ -172,7 +235,7 @@ sumlop: xor r1, r1
|
||||||
rol r1
|
rol r1
|
||||||
breq r1, r2, nvrflw
|
breq r1, r2, nvrflw
|
||||||
;Store
|
;Store
|
||||||
load r1, one
|
load r1, #1
|
||||||
store ovrflw, r1
|
store ovrflw, r1
|
||||||
|
|
||||||
;Check for no carry
|
;Check for no carry
|
||||||
|
@ -190,24 +253,12 @@ sumend: load r1, ovrflw
|
||||||
|
|
||||||
;Data
|
;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
|
;Variables
|
||||||
ovrflw: data 0
|
ovrflw: data 0
|
||||||
|
|
||||||
;Buffer
|
;Buffer
|
||||||
bfstrt: addr buffer
|
bfstrt: addr buffer
|
||||||
bfsize: data ff
|
bfsize: data fe
|
||||||
|
|
||||||
buffer:
|
buffer:
|
||||||
|
|
13
readme.md
13
readme.md
|
@ -37,9 +37,9 @@ respectively, while other registers and memory are unitialised.
|
||||||
Instructions
|
Instructions
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Instructions without an address argument are 8-bit and those with one
|
Instructions without an immediate or address argument are 8-bit, those
|
||||||
24-bit. The instruction pointer is incremented before being accessed or
|
with an immediate one 16-bit, and those with an address one 24-bit. The
|
||||||
modified.
|
instruction pointer is incremented before being accessed or modified.
|
||||||
|
|
||||||
0 HALT
|
0 HALT
|
||||||
1 RET IP = *RP; RP += 2
|
1 RET IP = *RP; RP += 2
|
||||||
|
@ -54,10 +54,9 @@ modified.
|
||||||
8 OR RX, RY RX |= RY
|
8 OR RX, RY RX |= RY
|
||||||
9 XOR RX, RY RX ^= RY
|
9 XOR RX, RY RX ^= RY
|
||||||
|
|
||||||
A LOAD RX, ADDR RX = *ADDR
|
A LOAD RX, ~0, IMM RX = IMM Written as "LOAD RX, #IMM"
|
||||||
B STORE RX, ADDR *ADDR = RX Written as "STORE ADDR, RX" in
|
0, ADDR RX = *ADDR Written as "LOAD RX, ADDR"
|
||||||
assembly for the sake of
|
B STORE RY, ADDR *ADDR = RY Written as "STORE ADDR, RY"
|
||||||
consistency.
|
|
||||||
|
|
||||||
C BREQ RX, RY, ADDR if (RX == RY) IP = ADDR
|
C BREQ RX, RY, ADDR if (RX == RY) IP = ADDR
|
||||||
D BRNEQ RX, RY, ADDR if (RX != RY) IP = ADDR
|
D BRNEQ RX, RY, ADDR if (RX != RY) IP = ADDR
|
||||||
|
|
Loading…
Reference in a new issue