Browse Source

Reword the readme slightly in Gidubba and convert the readme, license, and example programs to a Gidubba-friendly format

main
CrazyEttin 6 months ago
parent
commit
152d2d107f
  1. 363
      examples/ascii.asm
  2. 425
      examples/echo.asm
  3. 47
      license.md
  4. 216
      readme.md

363
examples/ascii.asm

@ -1,181 +1,182 @@
;ASCII code printer
;Print a prompt
load r0, prompt
store ffff, r0
load r0, space
store ffff, r0
;Read a character to r0 and load it to r2
load r0, ffff
xor r2, r2
xor r2, r0
;Print a newline and align
cleq r0, r0, newln
load r1, space
store ffff, r1
store ffff, r1
;Convert and print the high nibble
;Convert
ror r0
ror r0
ror r0
ror r0
cleq r0, r0, n2hex
;Print
store ffff, r0
;Re-load the character to r0
xor r0, r0
xor r0, r2
;Convert and print the low nibble
;Convert
cleq r0, r0, n2hex
;Print
store ffff, r0
;Print a newline
cleq r0, r0, newln
;Halt
halt
;***
;Print a newline
newln: load r1, cr
store ffff, r1
load r1, lf
store ffff, r1
ret
;***
;Get the hexadecimal digit of a nibble
;Extract the low nibble
n2hex: load r1, mask
and r0, r1
;Locate the nibble in the table
load r1, nbl0
breq r0, r1, dgt0
load r1, nbl1
breq r0, r1, dgt1
load r1, nbl2
breq r0, r1, dgt2
load r1, nbl3
breq r0, r1, dgt3
load r1, nbl4
breq r0, r1, dgt4
load r1, nbl5
breq r0, r1, dgt5
load r1, nbl6
breq r0, r1, dgt6
load r1, nbl7
breq r0, r1, dgt7
load r1, nbl8
breq r0, r1, dgt8
load r1, nbl9
breq r0, r1, dgt9
load r1, nbla
breq r0, r1, dgta
load r1, nblb
breq r0, r1, dgtb
load r1, nblc
breq r0, r1, dgtc
load r1, nbld
breq r0, r1, dgtd
load r1, nble
breq r0, r1, dgte
load r1, nblf
breq r0, r1, dgtf
;Load the hexadecimal digit of the nibble
dgt0: load r0, hex0
breq r0, r0, n2hend
dgt1: load r0, hex1
breq r0, r0, n2hend
dgt2: load r0, hex2
breq r0, r0, n2hend
dgt3: load r0, hex3
breq r0, r0, n2hend
dgt4: load r0, hex4
breq r0, r0, n2hend
dgt5: load r0, hex5
breq r0, r0, n2hend
dgt6: load r0, hex6
breq r0, r0, n2hend
dgt7: load r0, hex7
breq r0, r0, n2hend
dgt8: load r0, hex8
breq r0, r0, n2hend
dgt9: load r0, hex9
breq r0, r0, n2hend
dgta: load r0, hexa
breq r0, r0, n2hend
dgtb: load r0, hexb
breq r0, r0, n2hend
dgtc: load r0, hexc
breq r0, r0, n2hend
dgtd: load r0, hexd
breq r0, r0, n2hend
dgte: load r0, hexe
breq r0, r0, n2hend
dgtf: load r0, hexf
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
;ASCII code printer
;Print a prompt
load r0, prompt
store ffff, r0
load r0, space
store ffff, r0
;Read a character to r0 and load it to r2
load r0, ffff
xor r2, r2
xor r2, r0
;Print a newline and align
cleq r0, r0, newln
load r1, space
store ffff, r1
store ffff, r1
;Convert and print the high nibble
;Convert
ror r0
ror r0
ror r0
ror r0
cleq r0, r0, n2hex
;Print
store ffff, r0
;Re-load the character to r0
xor r0, r0
xor r0, r2
;Convert and print the low nibble
;Convert
cleq r0, r0, n2hex
;Print
store ffff, r0
;Print a newline
cleq r0, r0, newln
;Halt
halt
;***
;Print a newline
newln: load r1, cr
store ffff, r1
load r1, lf
store ffff, r1
ret
;***
;Get the hexadecimal digit of a nibble
;Extract the low nibble
n2hex: load r1, mask
and r0, r1
;Locate the nibble in the table
load r1, nbl0
breq r0, r1, dgt0
load r1, nbl1
breq r0, r1, dgt1
load r1, nbl2
breq r0, r1, dgt2
load r1, nbl3
breq r0, r1, dgt3
load r1, nbl4
breq r0, r1, dgt4
load r1, nbl5
breq r0, r1, dgt5
load r1, nbl6
breq r0, r1, dgt6
load r1, nbl7
breq r0, r1, dgt7
load r1, nbl8
breq r0, r1, dgt8
load r1, nbl9
breq r0, r1, dgt9
load r1, nbla
breq r0, r1, dgta
load r1, nblb
breq r0, r1, dgtb
load r1, nblc
breq r0, r1, dgtc
load r1, nbld
breq r0, r1, dgtd
load r1, nble
breq r0, r1, dgte
load r1, nblf
breq r0, r1, dgtf
;Load the hexadecimal digit of the nibble
dgt0: load r0, hex0
breq r0, r0, n2hend
dgt1: load r0, hex1
breq r0, r0, n2hend
dgt2: load r0, hex2
breq r0, r0, n2hend
dgt3: load r0, hex3
breq r0, r0, n2hend
dgt4: load r0, hex4
breq r0, r0, n2hend
dgt5: load r0, hex5
breq r0, r0, n2hend
dgt6: load r0, hex6
breq r0, r0, n2hend
dgt7: load r0, hex7
breq r0, r0, n2hend
dgt8: load r0, hex8
breq r0, r0, n2hend
dgt9: load r0, hex9
breq r0, r0, n2hend
dgta: load r0, hexa
breq r0, r0, n2hend
dgtb: load r0, hexb
breq r0, r0, n2hend
dgtc: load r0, hexc
breq r0, r0, n2hend
dgtd: load r0, hexd
breq r0, r0, n2hend
dgte: load r0, hexe
breq r0, r0, n2hend
dgtf: load r0, hexf
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


425
examples/echo.asm

@ -1,212 +1,213 @@
;String echo
;***
;Input
;Restore the buffer start address
;High byte
input: load r0, bfstrt
store chstor + 1, r0
;Low byte
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
;Read a character
inloop: load r1, ffff
;Check for control characters and the buffer end
;Escape
load r2, esc
breq r1, r2, escbr
;Carriage return
load r2, cr
breq r1, r2, crbr
;Buffer end
load r2, bfsize
brneq r0, r2, chstor
;Backtrack if at the buffer end
load r2, bs
store ffff, r2
breq r0, r0, inloop
;Store the character in the buffer
chstor: store buffer, r1
;Increment the character counter and store it in r3
;Increment
load r2, one
cleq r0, r0, sum
;Store
xor r3, r3
xor r3, r0
;Increment the buffer address
;Low byte
load r0, chstor + 2
load r2, one
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 a backslash and a newline
;Backslash
escbr: load r0, space
store ffff, r0
load r0, bslash
store ffff, r0
;Newline
load r0, cr
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
;Get the buffer address
crbr: load r1, chstor + 1
store endsto + 1, r1
load r1, chstor + 2
store endsto + 2, r1
;Store
xor r0, r0
endsto: store 0000, 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
;Increment the buffer address
;Low byte
load r0, chprnt + 2
load r2, one
cleq r0, r0, sum
store chprnt + 2, r0
;Add the overflow to the high byte
load r0, chprnt + 1
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store chprnt + 1, r0
;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
;***
;Add r2 to r0 with the overflow stored in r1
;Reset overflow
sum: xor r1, r1
store ovrflw, r1
;Copy the first argument to r1
sumlop: xor r1, r1
xor r1, r0
;Calculate the sum and carry and copy the pre-shift carry to r1
;Sum
xor r0, r2
;Carry
and r2, r1
;Copy the pre-shift carry
xor r1, r1
xor r1, r2
;Shift the carry
shl r2
;Check for and store overflow if any
;Check
rol r1
breq r1, r2, nvrflw
;Store
load r1, one
store ovrflw, r1
;Check for no carry
nvrflw: xor r1, r1
breq r1, r2, sumend
;Loop
breq r0, r0, sumlop
;Load overflow and return
sumend: load r1, ovrflw
ret
;***
;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
buffer:
;String echo
;***
;Input
;Restore the buffer start address
;High byte
input: load r0, bfstrt
store chstor + 1, r0
;Low byte
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
;Read a character
inloop: load r1, ffff
;Check for control characters and the buffer end
;Escape
load r2, esc
breq r1, r2, escbr
;Carriage return
load r2, cr
breq r1, r2, crbr
;Buffer end
load r2, bfsize
brneq r0, r2, chstor
;Backtrack if at the buffer end
load r2, bs
store ffff, r2
breq r0, r0, inloop
;Store the character in the buffer
chstor: store buffer, r1
;Increment the character counter and store it in r3
;Increment
load r2, one
cleq r0, r0, sum
;Store
xor r3, r3
xor r3, r0
;Increment the buffer address
;Low byte
load r0, chstor + 2
load r2, one
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 a backslash and a newline
;Backslash
escbr: load r0, space
store ffff, r0
load r0, bslash
store ffff, r0
;Newline
load r0, cr
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
;Get the buffer address
crbr: load r1, chstor + 1
store endsto + 1, r1
load r1, chstor + 2
store endsto + 2, r1
;Store
xor r0, r0
endsto: store 0000, 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
;Increment the buffer address
;Low byte
load r0, chprnt + 2
load r2, one
cleq r0, r0, sum
store chprnt + 2, r0
;Add the overflow to the high byte
load r0, chprnt + 1
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store chprnt + 1, r0
;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
;***
;Add r2 to r0 with the overflow stored in r1
;Reset overflow
sum: xor r1, r1
store ovrflw, r1
;Copy the first argument to r1
sumlop: xor r1, r1
xor r1, r0
;Calculate the sum and carry and copy the pre-shift carry to r1
;Sum
xor r0, r2
;Carry
and r2, r1
;Copy the pre-shift carry
xor r1, r1
xor r1, r2
;Shift the carry
shl r2
;Check for and store overflow if any
;Check
rol r1
breq r1, r2, nvrflw
;Store
load r1, one
store ovrflw, r1
;Check for no carry
nvrflw: xor r1, r1
breq r1, r2, sumend
;Loop
breq r0, r0, sumlop
;Load overflow and return
sumend: load r1, ovrflw
ret
;***
;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
buffer:


47
license.md

@ -1,23 +1,24 @@
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.
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.


216
readme.md

@ -1,108 +1,108 @@
Thingamajig
===========
Thingamajig is a RISC-y and MISC-y homebrew computer architecture. Its
git repository can be found at
https://ahti.space/git/crazyettin/Thingamajig.
Included Software
-----------------
The repository includes an emulator implementation of Thingamajig, a
control program for the emulated punched tape reader and punch, and an
assembler and a disassembler, all written in FreePascal. It also
includes couple of simple example programs for Thingamajig written in
Assembly.
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 locations 0-FFFF
Multi-byte values are big-endian. Memory addresses FFF0-FFFF are
reserved for memory mapped devices; the instruction and return pointers
cannot have values higher than FFEF and FFF0 respectively to avoid them.
The instruction and return pointers are initialised as 0 and FFF0
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.
0 HALT
1 RET IP = *RP; RP += 2
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 -= 2; *RP = IP; IP = ADDR}
F CLNEQ RX, RY, ADDR if (RX != RY) {RP -= 2; *RP = IP; IP = ADDR}
Assembly Language
-----------------
Lines of assembly are of the following form:
LABEL: OPER ARG1, ARG2, ARG3 ;Comment
The language is case-insensitive and uses hexadecimal numbers. A label
can consist of any alphanumeric characters as long as it is not
interpretable as a hexadecimal number. The label, instruction, and
comment elements are all optional, as is spacing between the arguments.
For the arguments of each instruction see the previous section.
Address arguments can be either absolute addresses or references to or
relative to a label. Relative references are of the form LABEL +/- N,
the spacing being optional. Note that the assembler does not check for
addresses or references to reserved addresses.
In addition to the true instructions there are three
pseudo-instructions. ORG defines the starting address of the program: it
can only occur as the first instruction and cannot have a label, and is
not required if the starting address is 0. DATA introduces a byte of
data. ADDR introduces two bytes of data containing the address of a
reference to or relative to a label.
Memory-Mapped Devices
---------------------
Input (when read from) and output (when written to) are mapped to
address FFFF. The emulator emulates a dumb terminal with local echo for
this.
Arbitrary devices can be mapped to the other reserved addresses.
In Linux the emulator can be compiled with support for a line printer
and an emulated punched tape reader and punch with the arguments
-dprinter and -dtape respectively. The printer prints into /dev/usb/lp0
and the tape files read from and punched to are (re)set using the
settape program. The printer is mapped to address FFFE in the emulator
and the tape reader and punch to FFFD. If you wish to use a different
setup you have to modify the code yourself.
Initial Program Loader
----------------------
At boot the initial program loader loads a program to the memory
starting from address 0 after which is cedes control to the CPU. The
emulator loads the program from a file.
Thingamajig
===========
Thingamajig is a RISC-y and MISC-y homebrew computer architecture. Its
git repository can be found at
https://ahti.space/git/crazyettin/Thingamajig.
Included Software
-----------------
The repository includes an emulator implementation of Thingamajig, a
control program for the emulated punched tape reader and punch, and an
assembler and a disassembler, all written in FreePascal. It also
includes couple of simple example programs for Thingamajig written in
Assembly.
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 locations 0-FFFF
Multi-byte values are big-endian. Memory addresses FFF0-FFFF are
reserved for memory mapped devices; the instruction and return pointers
cannot have values higher than FFEF and FFF0 respectively to avoid them.
The instruction and return pointers are initialised as 0 and FFF0
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.
0 HALT
1 RET IP = *RP; RP += 2
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 -= 2; *RP = IP; IP = ADDR}
F CLNEQ RX, RY, ADDR if (RX != RY) {RP -= 2; *RP = IP; IP = ADDR}
Assembly Language
-----------------
Lines of assembly are of the following form:
LABEL: OPER ARG1, ARG2, ARG3 ;Comment
The language is case-insensitive and uses hexadecimal numbers. A label
can consist of any alphanumeric characters as long as it is not
interpretable as a hexadecimal number. The label, instruction, and
comment elements are all optional, as is spacing between the arguments.
For the arguments of each instruction see the previous section.
Address arguments can be either absolute addresses or references to or
relative to a label. Relative references are of the form LABEL +/- N,
the spacing being optional. Note that the assembler does not check for
addresses or references to reserved addresses.
In addition to the true instructions there are three
pseudo-instructions. ORG defines the starting address of the program: it
can only occur as the first instruction and cannot have a label, and is
not required if the starting address is 0. DATA introduces a byte of
data. ADDR introduces two bytes of data containing the address of a
reference to or relative to a label.
Memory-Mapped Devices
---------------------
Input (when read from) and output (when written to) are mapped to
address FFFF. The emulator emulates a dumb terminal with local echo.
Arbitrary devices can be mapped to the other reserved addresses.
In Linux the emulator can be compiled with support for a line printer
and an emulated punched tape reader and punch with the arguments
-dprinter and -dtape respectively. The printer is mapped to address FFFE
and the tape reader and punch to FFFD. The printer prints into
/dev/usb/lp0 and the tape files read from and punched to are (re)set
using the settape program. If you wish to use a different setup you have
to modify the code yourself.
Initial Program Loader
----------------------
At boot the initial program loader loads a program to the memory
starting from address 0 after which is cedes control to the CPU. The
emulator loads the program from a file.

Loading…
Cancel
Save