PTSL
PTSL or Portable Terse Stack Language is a language designed by User:Moon for use in a simulated universe/tabletop game/community written world. It is intended as a mechanism for storing programs on cartridges designed to run on multiple systems. Due to its nature as a terse language, it's also rather esoteric, hence it being documented on this wiki.
Execution enviornment
PTSL executes in a flat memory space of up to 224 bytes (16MiB), divided in 8KB pages. Any memory beyond this space is treated as Memory Mapped IO space, for direct access to system devices when the program supports it. There can be up to 254 MMIO devices mapped, with MMIO device 0 being RAM and MMIO device 1 being the first 64KB of cartridge.
0 | RAM |
1 | CART[0] |
2 | MMIO[0] |
3-254 | MMIO[1-253] |
255 | MMIO[254] |
Program execution can begin in either RAM (Bank 0) or CART[0] (Bank 1), MMIO devices are not executable unless they are mapped as a storage device, like extra RAM or extra cartridge space.
Not all of RAM is immediately accessable, and has to be requested in 64KB pages by the program before use.
The stack is located in the first page of RAM, with values on the stack being exactly 32 bits.
Instructions
Each opcode is 8 bits long, with up to 32 bits of data associated with it.
ID | Opcode | Definition |
---|---|---|
00 | DROP | SP-- |
01 | DUP | [SP++] = [SP] |
02 | SWAP | swap [SP-1] [SP] |
03 | PUSHI32 data | [SP++] = [DATA:32] |
04 | PUSHI24 data | [SP++] = [DATA:24] |
05 | PUSHI16 data | [SP++] = [DATA:16] |
06 | PUSHI8 data | [SP++] = [DATA:8] |
07 | LOADI32 | [SP] = MEM[[SP]:32] |
08 | LOADI24 | [SP] = MEM[[SP]:24] |
09 | LOADI16 | [SP] = MEM[[SP]:16] |
0A | LOADI8 | [SP] = MEM[[SP]:8] |
0B | JUMP | PC = [SP--] |
0C | JPIF | IF [SP--] { PC = [SP--] } |
0D | ADDI8 | [SP] = [SP] + [DATA:8] |
0E | ADD | [SP--] = [SP-1] + [SP-2] |
0F | ADC | |
10 | SUBVI8 | [SP--] = [SP-1] - [DATA:8] |
11 | SUBI8V | [SP--] = [DATA:8] - [SP-1] |
12 | SUB | [SP--] = [SP-1] - [SP-2] |
13 | SBB | |
14 | 8BCRRY | |
15 | 16BCRRY | |
16 | 32BCRRY | |
17 | CALLI32 | [RSP++] = PC; PC = [DATA:I32] |
18 | CALL | [RSP++] = PC; PC = [SP--] |
19 | PUSHRS | [RSP++] = [SP--] |
1A | PEEKRS | [SP++] = [RSP] |
1B | POPRS | [SP++] = [RSP--] |
1C | PUSHRSP | [SP++] = RSP |
1D | POPRSP | RSP = [SP--] |
1E | ALLOCP | Request memory page from OS |
1F | MAPDEV | Map device [SP-1] to page [SP-2]. |
20 | COPY | Fast copy, provided by OS. [SP-1] = Length, [SP-2] = Source, [SP-3] = Dest |
21 | JPRELI8 | PC = PC + [SDATA:8] |
22 | JPRELI16 | PC = PC + [SDATA:16] |
23 | JPREL | PC = PC + [SP--] |
24 | RET | PC = [RSP--] |
25 | GREQ | [SP--] = [SP-1] >= [SP-2] (Signed) |
26 | LEEQ | [SP--] = [SP-1] <= [SP-2] (Signed) |
27 | GRTR | [SP--] = [SP-1] > [SP-2] (Signed) |
28 | LESS | [SP--] = [SP-1] < [SP-2] (Signed) |
29 | ABEQ | [SP--] = [SP-1] >= [SP-2] (Unsigned) |
2A | BLEQ | [SP--] = [SP-1] <= [SP-2] (Unsigned) |
2B | ABOV | [SP--] = [SP-1] > [SP-2] (Unsigned) |
2C | BELO | [SP--] = [SP-1] < [SP-2] (Unsigned) |
2D | STORI32 | MEM[[SP]:32] = [SP--] |
2E | STORI24 | MEM[[SP]:24] = [SP--] |
2F | STORI16 | MEM[[SP]:16] = [SP--] |
30 | STORI8 | MEM[[SP]:8] = [SP--] |
31 | NOT | [SP] = ![SP] |
32 | AND | [SP--] = [SP-1] & [SP-2] |
33 | OR | [SP-2] |
34 | XOR | [SP--] = [SP-1] ^ [SP-2] |
35 | MUL | [SP--] = [SP-1] * [SP-2] |
36 | DIVMOD | A = [SP-1] / [SP-2]; [SP-1] = [SP-1] % [SP-2]; [SP] = A |
37 | SHL | [SP--] = [SP-1] << [SP-2] |
38 | SHR | [SP--] = [SP-1] >> [SP-2] |
39 | SHRA | [SP--] = [SP-1] >>> [SP-2] |
3A | SHL8 | [SP] = [SP] << 8 |
3B | SHL16 | [SP] = [SP] << 16 |
3C | SHL24 | [SP] = [SP] << 24 |
3D | PUSH1 | [SP++] = 1 |
3E | SETQC | [QUICKCONST] = [DATA:32] |
3F | GETQC32 | [SP++] = [QUICKCONST:32] |
40 | GETQC16 | [SP++] = [QUICKCONST:16] |
41 | GETQC8 | [SP++] = [QUICKCONST:8] |
42 | MXCHG | swap [SP-1] MEM[[SP--]:32] |
43 | SETSP | SP = [SP] |
44 | SYSINF | Writes system info to address pointed to by [SP--]. Must be a 256 byte space. |
45 | PUSH0 | [SP++] = 0 |
46 | BITSET | |
47 | BITGET | |
48 | BITFLIP | |
49 | JMPTOASM | Execute system specific assembly code at location pointed to by [SP--] |
4A | CALLASM | Same as JMPTOASM, but provides a return value in a system dependent register. |
4B | MSET32 | Set the region specified by [SP-1] of length [SP-2] to [SP-3:32]. Undefined behavior if region length is not multiple of 4 |
4C | MSET16 | Set the region specified by [SP-1] of length [SP-2] to [SP-3:16]. Undefined behavior if region length is not multiple of 2 |
4D | MSET8 | Set the region specified by [SP-1] of length [SP-2] to [SP-3:8]. |
4E | SHL1 | [SP] = [SP] << 1 |
4F | SHR1 | [SP] = [SP] >> 1 |
50 | SHLI8 | [SP] = [SP] << [DATA:8] |
51 | SHRI8 | [SP] = [SP] >> [DATA:8] |
52 | OVER | [SP++] = [SP-1] |
53 | ROT | rotate [SP], [SP-1], [SP-2] |
FF | EXPLD | System prints "BANG!" to display, halts. May also play noise from system speaker if one is present. |
Example code
The following is written in the human readable PTSLASM format, instead of PTSL directly.
Hello, World!
; Assumes that it is running on a MX08-A. Not a good example of portable code :) %DEF TERMINAL_DEVICE_ID 0xFF000001 ; MX08-A terminal %DEF MMIO0 0x02000000 %DEF STR_HELLO_WORLD_LEN 13 [ORG 0x000000] _START: PUSHI24 0x001000 PUSHRSP ; Set up return stack. Not used in this demo, but worth setting up. PUSHI8 2 PUSHI32 TERMINAL_DEVICE_ID MAPDEV PUSHI8 STR_HELLO_WORLD_LEN PUSHI24 STR_HELLO_WORLD PUSHI32 MMIO0 COPY .HANG: JUMPRELI8 0x00 STR_HELLO_WORLD: DB "Hello, World!"