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