Initial commit
This commit is contained in:
commit
75123a629a
|
@ -0,0 +1,105 @@
|
||||||
|
program Disassembler;
|
||||||
|
|
||||||
|
uses Crt, Sysutils;
|
||||||
|
|
||||||
|
var
|
||||||
|
Op, Regs: 0 .. $f; //Opcode
|
||||||
|
X, Y: 0 .. 3; //Register arguments
|
||||||
|
Addr, IP, EP: word; //Address argument and instruction and end pointers
|
||||||
|
Opcodes: array [0 .. $f] of string; //Opcodes in human readable form
|
||||||
|
Bin: array [0 .. $ffef] of byte; //Program in binary form
|
||||||
|
Prog: file of byte; //Program file
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
//Populate the opcode array
|
||||||
|
Opcodes [0] := 'HALT ';
|
||||||
|
Opcodes [1] := 'RET ';
|
||||||
|
Opcodes [2] := 'SHL ';
|
||||||
|
Opcodes [3] := 'SHR ';
|
||||||
|
Opcodes [4] := 'ROL ';
|
||||||
|
Opcodes [5] := 'ROR ';
|
||||||
|
Opcodes [6] := 'NAND ';
|
||||||
|
Opcodes [7] := 'AND ';
|
||||||
|
Opcodes [8] := 'OR ';
|
||||||
|
Opcodes [9] := 'XOR ';
|
||||||
|
Opcodes [$a] := 'LOAD ';
|
||||||
|
Opcodes [$b] := 'STORE ';
|
||||||
|
Opcodes [$c] := 'BREQ ';
|
||||||
|
Opcodes [$d] := 'BRNEQ ';
|
||||||
|
Opcodes [$e] := 'CLEQ ';
|
||||||
|
Opcodes [$f] := 'CLNEQ ';
|
||||||
|
|
||||||
|
//Initialise the pointer
|
||||||
|
IP := 0;
|
||||||
|
|
||||||
|
//Read a program file and check for errors
|
||||||
|
if ParamCount <> 1 then begin
|
||||||
|
writeln ('Usage: disassembler program');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
{$i-}
|
||||||
|
assign (Prog, ParamStr (1));
|
||||||
|
reset (Prog);
|
||||||
|
{$i+}
|
||||||
|
if IOResult <> 0 then begin
|
||||||
|
writeln ('Usage: disassembler program');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
repeat
|
||||||
|
read (Prog, Bin [IP]);
|
||||||
|
IP := IP + 1;
|
||||||
|
until (eof (Prog)) or (IP = $fff0);
|
||||||
|
|
||||||
|
//Save the end point and reinitialise the instruction pointer
|
||||||
|
EP := IP;
|
||||||
|
IP := 0;
|
||||||
|
|
||||||
|
//Begin the main loop
|
||||||
|
repeat
|
||||||
|
|
||||||
|
//Print the memory location
|
||||||
|
if IP < $1000 then write (' ');
|
||||||
|
if IP < $100 then write (' ');
|
||||||
|
if IP < $10 then write (' ');
|
||||||
|
write (IntToHex (IP, 1), ' ');
|
||||||
|
|
||||||
|
//Fetch the instruction and increment the instruction pointer
|
||||||
|
//Opcode
|
||||||
|
Op := Bin [IP] and $f0 shr 4;
|
||||||
|
//Register arguments
|
||||||
|
Regs := Bin [IP] and $f;
|
||||||
|
X := Bin [IP] and $c shr 2;
|
||||||
|
Y := Bin [IP] and 3;
|
||||||
|
IP := IP + 1;
|
||||||
|
//Address argument
|
||||||
|
if Op >= $a then begin
|
||||||
|
Addr := Bin [IP];
|
||||||
|
Addr := Addr shl 8;
|
||||||
|
IP := IP + 1;
|
||||||
|
Addr := Addr + Bin [IP];
|
||||||
|
IP := IP - 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//Print the data
|
||||||
|
write (IntToHex (Op, 1), IntToHex (Regs, 1));
|
||||||
|
if Op >= $a then write (IntToHex (Addr, 4)) else write (' ');
|
||||||
|
write (' ');
|
||||||
|
|
||||||
|
//Print the instruction
|
||||||
|
write (Opcodes [Op]);
|
||||||
|
if Op = $b then writeln (IntToHex (Addr, 1), ', R', X)
|
||||||
|
else begin
|
||||||
|
if Op >= 2 then if Op <> $b 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));
|
||||||
|
writeln ();
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
until (IP >= EP);
|
||||||
|
|
||||||
|
end.
|
|
@ -0,0 +1,146 @@
|
||||||
|
program Emulator;
|
||||||
|
|
||||||
|
uses Crt;
|
||||||
|
|
||||||
|
const
|
||||||
|
IO = $ffff;
|
||||||
|
|
||||||
|
var
|
||||||
|
Halt: boolean; //Halt flag
|
||||||
|
Op: 0 .. $f; //Opcode
|
||||||
|
X, Y: 0 .. 3; //Register arguments
|
||||||
|
Addr, IP, RP: word; //Address argument and instruction and return pointers
|
||||||
|
R: array [0 .. 3] of byte; //General-purpose registers
|
||||||
|
Mem: array [0 .. $ffef] of byte; //Memory
|
||||||
|
Prog: file of byte; //Program file
|
||||||
|
Ch: ansichar; //Character for input and output
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
//Initialise the halt flag and the pointers
|
||||||
|
Halt := false;
|
||||||
|
IP := 0;
|
||||||
|
RP := $fff0;
|
||||||
|
|
||||||
|
//Read a program file and check for errors
|
||||||
|
if ParamCount <> 1 then begin
|
||||||
|
writeln ('Usage: emulator program');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
{$i-}
|
||||||
|
assign (Prog, ParamStr (1));
|
||||||
|
reset (Prog);
|
||||||
|
{$i+}
|
||||||
|
if IOResult <> 0 then begin
|
||||||
|
writeln ('Usage: emulator program');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
repeat
|
||||||
|
read (Prog, Mem [IP]);
|
||||||
|
IP := IP + 1;
|
||||||
|
until (eof (Prog)) or (IP = $fff0);
|
||||||
|
|
||||||
|
//Reinitialise the instruction pointer
|
||||||
|
IP := 0;
|
||||||
|
|
||||||
|
//Begin the main loop
|
||||||
|
while (Halt = false) do begin
|
||||||
|
|
||||||
|
//Fetch the instruction and increment the instruction pointer
|
||||||
|
//Opcode
|
||||||
|
Op := Mem [IP] and $f0 shr 4;
|
||||||
|
//Register arguments
|
||||||
|
X := Mem [IP] and $c shr 2;
|
||||||
|
Y := Mem [IP] and 3;
|
||||||
|
IP := IP + 1;
|
||||||
|
if IP > $ffef then break;
|
||||||
|
//Address argument
|
||||||
|
if Op >= $a then begin
|
||||||
|
Addr := Mem [IP];
|
||||||
|
Addr := Addr shl 8;
|
||||||
|
IP := IP + 1;
|
||||||
|
if IP > $ffef then break;
|
||||||
|
Addr := Addr + Mem [IP];
|
||||||
|
IP := IP + 1;
|
||||||
|
if IP > $ffef then break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//Decode and execute the instruction
|
||||||
|
//Halt
|
||||||
|
if Op = 0 then Halt := true
|
||||||
|
//Ret
|
||||||
|
else if Op = 1 then begin
|
||||||
|
IP := Mem [RP];
|
||||||
|
RP := RP + 1;
|
||||||
|
if RP > $fff0 then break;
|
||||||
|
end
|
||||||
|
//Shl
|
||||||
|
else if Op = 2 then R [X] := R [X] shl 1
|
||||||
|
//Shr
|
||||||
|
else if Op = 3 then R [X] := R [X] shr 1
|
||||||
|
//Rol
|
||||||
|
else if Op = 4 then R [X] := RolByte (R [X])
|
||||||
|
//Ror
|
||||||
|
else if Op = 5 then R [X] := RorByte (R [X])
|
||||||
|
//Nand
|
||||||
|
else if Op = 6 then R [X] := not (R [X] and R [Y])
|
||||||
|
//And
|
||||||
|
else if Op = 7 then R [X] := R [X] and R [Y]
|
||||||
|
//Or
|
||||||
|
else if Op = 8 then R [X] := R [X] or R [Y]
|
||||||
|
//Xor
|
||||||
|
else if Op = 9 then R [X] := R [X] xor R [Y]
|
||||||
|
//Load
|
||||||
|
else if Op = $a then begin
|
||||||
|
//Input
|
||||||
|
if Addr = IO then begin
|
||||||
|
Ch := ReadKey;
|
||||||
|
write (Ch);
|
||||||
|
R [X] := byte (Ch);
|
||||||
|
end
|
||||||
|
//Regular load
|
||||||
|
else R [X] := Mem [Addr];
|
||||||
|
end
|
||||||
|
//Store
|
||||||
|
else if Op = $b then begin
|
||||||
|
//Output
|
||||||
|
if Addr = IO then begin
|
||||||
|
Ch := ansichar (R [X]);
|
||||||
|
write (Ch);
|
||||||
|
end
|
||||||
|
//Regular store
|
||||||
|
else Mem [Addr] := R [X];
|
||||||
|
end
|
||||||
|
//Breq
|
||||||
|
else if Op = $c then begin
|
||||||
|
if R [X] = R [Y] then IP := Addr;
|
||||||
|
end
|
||||||
|
//Brneq
|
||||||
|
else if Op = $d then begin
|
||||||
|
if R [X] <> R [Y] then IP := Addr;
|
||||||
|
end
|
||||||
|
//Cleq
|
||||||
|
else if Op = $e then begin
|
||||||
|
if R [X] = R [Y] then begin
|
||||||
|
RP := RP - 1;
|
||||||
|
if RP > $fff0 then break;
|
||||||
|
Mem [RP] := IP;
|
||||||
|
IP := Addr;
|
||||||
|
if IP > $ffef then break;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
//Clneq
|
||||||
|
else if Op = $f then begin
|
||||||
|
if R [X] <> R [Y] then begin
|
||||||
|
RP := RP - 1;
|
||||||
|
if RP > $fff0 then break;
|
||||||
|
Mem [RP] := IP;
|
||||||
|
IP := Addr;
|
||||||
|
if IP > $ffef then break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//End the main loop
|
||||||
|
end
|
||||||
|
|
||||||
|
end.
|
|
@ -0,0 +1,23 @@
|
||||||
|
MIT License
|
||||||
|
===========
|
||||||
|
|
||||||
|
Copyright (c) 2022
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,58 @@
|
||||||
|
Thingamajig
|
||||||
|
===========
|
||||||
|
|
||||||
|
Thingamajig is a RISC-y and MISC-y hobbyist instruction set
|
||||||
|
architecture. Its git repository can be found at
|
||||||
|
https://ahti.space/git/crazyettin/Thingamajig.
|
||||||
|
|
||||||
|
Registers and Memory
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
* 24-bit instruction register IR
|
||||||
|
* 16-bit instruction and return pointers IP and RP
|
||||||
|
* 8-bit general-purpose registers R0-R3
|
||||||
|
* 8-bit memory addresses 0-FFFF
|
||||||
|
|
||||||
|
Multi-byte values are big-endian. Memory addresses FFF0-FFFF are
|
||||||
|
reserved for memory mapped devices. The instruction and return pointers
|
||||||
|
should not have values higher than FFEF and FFF0 respectively to avoid
|
||||||
|
the reserved addresses. The instruction and return pointers are
|
||||||
|
initialised as 0 and FFF0 respectively; other registers and memory are
|
||||||
|
unitialised.
|
||||||
|
|
||||||
|
Memory-Mapped Devices
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Input (when read from) and output (when written to) are mapped to
|
||||||
|
address FFFF. Arbitrary devices can be mapped to the other reserved
|
||||||
|
addresses.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
0 HALT
|
||||||
|
1 RET IP = *RP; RP += 1
|
||||||
|
|
||||||
|
2 SHL RX RX <<= 1 Logical shifts
|
||||||
|
3 SHR RX RX >>= 1
|
||||||
|
4 ROL RX RX <<= 1 Rotating shifts
|
||||||
|
5 ROR RX RX >>= 1
|
||||||
|
|
||||||
|
6 NAND RX, RY RX = ~(RX & RY)
|
||||||
|
7 AND RX, RY RX &= RY
|
||||||
|
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.
|
||||||
|
|
||||||
|
C BREQ RX, RY, ADDR if (RX == RY) IP = ADDR
|
||||||
|
D BRNEQ RX, RY, ADDR if (RX != RY) IP = ADDR
|
||||||
|
E CLEQ RX, RY, ADDR if (RX == RY) {RP -= 1; *RP = IP; IP = ADDR}
|
||||||
|
F CLNEQ RX, RY, ADDR if (RX != RY) {RP -= 1; *RP = IP; IP = ADDR}
|
Loading…
Reference in New Issue