-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Minimal 64 Home Computer support (#27)
* first version of minimal 64 configuration * fixed bug when instruction configured for 0 operands * allow predefined contants fot start with _ * added minimal 64 os constants * corrected os function calling convention * finalized minimal 64 release * documentation update * added prime numbers example * added random maze example * bumped version * typos
- Loading branch information
1 parent
4da0062
commit add2003
Showing
19 changed files
with
2,342 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Minimal 64 Home Computer | ||
*Current as of v1.2.x of the Minimal 64 Home Computer* | ||
|
||
The Minimal 64 Home Computer (Minimal 64) is TTL CPU designed by Carsten Herting (slu4). Carsten has made his [Minimal 64 design open and available to others](https://github.com/slu4coder/The-Minimal-64-Home-Computer/) to build. The Minimal 64 is is well documented, and even has [a YouTube video series](https://www.youtube.com/watch?v=3zGTsi4AYLw&list=PLYlQj5cfIcBVrKpKJ-Sj68nkw6IRb9KOp) dedicated to it. | ||
|
||
As part of his effort to demonstrate the "minimal effort" needed to make a working computer, Carsten has already implemented a simple yet solid assembler for the Minimal 64 Home Computer. So the question might be asked, "Why port the Minimal 64 to BespokeASM?" Simply put, to have a more robust assembler for the Minimal 64. For example, the instruction set for the Minimal 64 is simple (no overly complex instructions), and so actions like pushing a value on the stack takes at least two instructions to complete. In scenarios like this, BespokeASM's instruction macros can simplify the code needed to accomplish common tasks. | ||
|
||
So the goal of this port to **BespokeASM** is to first support the basic instruction set of the Minimal 64 in its original form, but then build on that with richer features such as instruction macros to make assembly coding for the Minimal CPU more productive. | ||
|
||
## Minimal 64 Assembly | ||
The **BespokeASM** instruction set configration file `slu4-minimal-64.yaml` is available in this directory. Assuming that **BespookeASM** is [properly installed in the current python environment](https://github.com/michaelkamprath/bespokeasm/wiki/Installation-and-Usage#installation), to compile Minimal 64 assembly into a Intel Hex representation that the Minimal 64 OS's `receive` instruction can take, use the following command: | ||
|
||
```sh | ||
bespokeasm compile -n -p -t intel_hex -c /path/to/slu4-minimal-64.yaml /path/to/my-code.min64 | ||
``` | ||
|
||
The arguments to the command above are: | ||
|
||
* `-n` - Indicates that no binary image should be generated. | ||
* `-p` - indicates that a textual representation of the assembled code should be emitted. | ||
* `-t intel_hex` - Specifies the format of the textual rerpesentation of the compiled code, in this case being Intel Hex. If you ommit this option, the default textual representation of an human-readable listing will be used. | ||
* `-c /path/to/slu4-minimal-64.yaml` - The file path to the **BespokeASM** instruction set configuration for the Minimal 64. | ||
* `/path/to/my-code.min64` - The file path to the Minimal 64 assembly code to be compiled. Here by convention the assembly code has a file extension of `.min64`. While **BespokeASM** can work with any file extension for the code, the convention is used so that code editors know what file type they are editing and thus are able to support syntax highlighting specific to the Minimal 64 assembly syntax. See **BespokeASM**'s documentation on syntax highlighting support for more information. | ||
|
||
### Instruction Set | ||
Carsten Herting thoroughly documents [the instruction set for the Minimal 64 in his user guide](https://docs.google.com/document/d/1e4hL9Z7BLIoUlErWgJOngnSMYLXjfnsZB9BtlwhTC6U/edit?usp=sharing). All of the documented instructions in their original syntax are implemented in in this **BespokeASM** port. However, **BespokeASM** will be case insensitive when matching instruction mnemonics. | ||
|
||
### Instruction Macros | ||
The following instruction macros have been added in the ISA confutation file for the Minimal 64. All macros that interact with the stack maintain byte order according to Min64 OS calling convention, which pushes the LSB of the value first despite the system otherwise using little endian byte ordering. Not that this means multibyte values on the stack cannot be used directly art their stack memory address and must be "pulled" from the stack to another memory location where they can be represented in little endian byte ordering. | ||
|
||
| Macros Instruction | Operand 1 | Operand 2 | Description | | ||
|:-:|:-:|:-:|:--| | ||
| `spinit` | - | - | Init the stack popint to a value of `0xFFFE`. | | ||
| `phsi` | 1 byte | - | Pushes a 1 byte immediate value onto the stack. | | ||
| `phs2i` | 2 bytes | - | Pushes a 2 byte immediate value onto the stack. | | ||
| `phs4i` | 4 bytes | - | Pushes a 4 byte immediate value onto the stack. | | ||
| `phsa` | absolute address | - | Push onto stack 1 byte found at absolute address | | ||
| `phs2a` | absolute address | - | Push onto stack 2 bytes found at absolute address | | ||
| `phs4a` | absolute address | - | Push onto stack 4 bytes found at absolute address | | ||
| `phss` | stack offset | - | Push onto stack 1 byte value currently found at indicated stack offset | | ||
| `phs2s` | stack offset | - | Push onto stack 2 byte value currently found at indicated stack offset | | ||
| `phs4s` | stack offset | - | Push onto stack 4 byte value currently found at indicated stack offset | | ||
| `pls2` | - | - | Pull 2 bytes from stack. Last byte pulled will be in A register. | | ||
| `pls4` | - | - | Pull 4 bytes from stack. Last byte pulled will be in A register. | | ||
| `cpy2as` | absolute address | stack offset | Copy 2 bytes of data sourced from indicated stack offset to memory starting at indicated absolute address. Convert from stack big endian ordering to RAM little endian ordering. | | ||
| `cpy2sa` | stack offset | absolute address | Copy 2 bytes of data sourced from absolute address to stack at indicated offset. Convert from RAM little endian to stack big endian ordering ordering. | | ||
| `cpy4as` | absolute address | stack offset | Copy 4 bytes of data sourced from indicated stack offset to memory starting at indicated absolute address. Convert from stack big endian ordering to RAM little endian ordering. | | ||
| `cpy4sa` | stack offset | absolute address | Copy 4 bytes of data sourced from absolute address to stack at indicated offset. Convert from RAM little endian to stack big endian ordering ordering. | | ||
| `cpy4ai` | absolute address | immediate | Copy 4 bytes of immediate value to memory starting at indicated absolute address. Preserves endian ordering. | | ||
| `cpy4si` | stack offset | immediate | Copy 4 bytes of immediate value to stack at indicated offset. Convert from RAM little endian to stack big endian ordering ordering. | | ||
| `cpy4ss` | stack offset | stack offset | Copy 4 bytes of data from stack starting at indicated offset (2nd operand) to another location in stack starting at indicated offset (1rst operand). Byte ordering is preserved. | | ||
|
||
The operand descriptions use the definitions provided by documentation for Minimal 64. You should assume the accumulator (register `A`) is not preserved across any of these macros. | ||
|
||
### Assembly Syntax | ||
**BespokeASM**'s syntax is close to the syntax that Carsten used for the Minimal CPU's assembly language. However, there are some differences: | ||
|
||
* **BespokeASM** used a different syntax for some directives, notably the `.org` directive, which has the `#org` syntax in the Minimal CPU assembly. **BespokeASM** also has [a richer set of directives available](https://github.com/michaelkamprath/bespokeasm/wiki/Assembly-Language-Syntax#directives). | ||
* The Minimal CPU's assembler has no data type directives. Instead, the assembler directly converts numeric values and strings to byte code exactly where it sits in the code. In **BespokeASM** one must declare a data type using [a data directive](https://github.com/michaelkamprath/bespokeasm/wiki/Assembly-Language-Syntax#data) when defining data in the byte code. | ||
* The Minimal CPU assembler emits byte code in the order it was in the original assembly code, while **BespokeASM** emits byte code in address order. For the most part, these two orderings can be pretty much the same, however, differences will show up if multiple `.org` directives are use or multiple additional source files are included. | ||
* The Minimal CPU uses a `<` and `>` to do byte slicing of constant values, with `<` meaning least significant byte and `>` meaning most significant byte (and it assumes a 2 byte value). **BespokeASM** using `BYTE0(..)` and `BYTE1(..)` [to accomplish the same goals](https://github.com/michaelkamprath/bespokeasm/wiki/Assembly-Language-Syntax#numeric-expressions) (respectively). | ||
|
||
There are several other features that **BespokeASM** provides over the Minimal 64 assembly syntax, such as richer math expressions for constant values and [several preprocessor directives](https://github.com/michaelkamprath/bespokeasm/wiki/Assembly-Language-Syntax#preprocessor), but the differences listed above are the ones that require code written for the Minimal 64 assembler to be altered to be assembled with **BespokeASM**. | ||
|
||
### Predefined Compiler Constants | ||
The Minimal 64 operating system provided call vectors for a suite of API functions and system subroutines that are made available to user written programs. These API function labels are documented in the "API Functions" section of the Minimal 64 user guide. All documented API functions are implemented as predefined constants in this **BepsokeASM** port. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
; --------------------------------------- | ||
; VGA demo drawing 16 x 16 bubble sprites | ||
; by C. Herting (slu4) 2022 | ||
; | ||
; ported to BespokeASM syntax by Michael Kamprath | ||
; --------------------------------------- | ||
#require "slu4-min64-asm >= 1.2.0" | ||
.org 0x8000 | ||
|
||
start: LDI 0xfe STA 0xffff | ||
JPS _Clear ; clear VGA | ||
|
||
rloop: JPS _Random ANI 1 STA table+0 | ||
redox: JPS _Random CPI 192 BCS redox | ||
LSL ORB table+0 LDI 0 ROL STA table+1 | ||
redoy: JPS _Random CPI 224 BCS redoy | ||
STA table+2 | ||
|
||
drawit: LDA table+0 PHS | ||
LDA table+1 PHS | ||
LDA table+2 PHS | ||
JPS DrawSprite PLS PLS PLS | ||
|
||
JPA rloop | ||
|
||
ptr: .2byte 0xffff | ||
|
||
; ------------------------------------------------ | ||
; Draws a 16x16 pixel sprite at the given position | ||
; push: x_lsb, x_msb, y | ||
; pull: #, #, # | ||
; modifies: X | ||
; ------------------------------------------------ | ||
DrawSprite: LDS 3 LL6 STA addr+0 ; use ypos | ||
LDS 3 RL7 ANI 63 ADI 0xc3 STA addr+1 | ||
LDS 4 DEC LDS 5 ; add xpos | ||
RL6 ANI 63 ADI 12 ORB addr+0 ; preprare target address | ||
LDS 5 ANI 7 STA shift ; calc bit pos | ||
LDI LSB(data) STA dptr+0 LDI BYTE1(data) STA dptr+1 ; data is hard-coded | ||
lineloop: LDR dptr STA buffer+0 INW dptr | ||
LDR dptr STA buffer+1 CLB buffer+2 | ||
LXA shift DEX BCC shiftdone ; shift that buffer to pixel position | ||
shiftloop: LLW buffer+0 RLB buffer+2 DEX BCS shiftloop | ||
shiftdone: NEB mask BEQ clearit | ||
LDA buffer+0 ORR addr STR addr INW addr ; store line buffer to VRAM addr | ||
LDA buffer+1 ORR addr STR addr INW addr | ||
LDA buffer+2 ORR addr STR addr | ||
JPA common | ||
clearit: LDA buffer+0 NOT ANR addr STR addr INW addr ; store line buffer to VRAM addr | ||
LDA buffer+1 NOT ANR addr STR addr INW addr | ||
LDA buffer+2 NOT ANR addr STR addr | ||
common: LDI 62 ADW addr ; ... and move to the next line | ||
INW dptr LDA dptr+0 CPI LSB(data+32) BNE lineloop ; haben wir alle sprite daten verarbeitet? | ||
RTS | ||
|
||
shift: .byte 0xff | ||
dptr: .2byte 0xffff | ||
addr: .2byte 0xffff | ||
mask: .byte 0x01 | ||
data: .byte 0xe0,0x07,0x98,0x1a,0x04,0x34,0x02,0x68,0x62,0x50,0x11,0xa0,0x09,0xd0,0x09,0xa0 | ||
.byte 0x01,0xd0,0x03,0xa8,0x05,0xd4,0x0a,0x6a,0x56,0x55,0xac,0x2a,0x58,0x1d,0xe0,0x07 | ||
buffer: .byte 0xff, 0xff, 0xff | ||
|
||
table: ; position data for sprite entities |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
; Hello World | ||
; for the Minimal 64 Home Computer | ||
; | ||
; This simple program simply displays a string to the screen | ||
; and then returns to the OS prompt. | ||
; | ||
#require "slu4-min64-asm >= 1.2.0" | ||
.org 0x8000 | ||
init: | ||
; init the stack vector | ||
spinit | ||
|
||
start: | ||
phs2i message_str | ||
jps _Print | ||
pls2 | ||
|
||
end: | ||
jpa _Prompt | ||
|
||
message_str: | ||
.cstr "Hello World!\n" |
Oops, something went wrong.