1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-06-14 08:29:33 +00:00
SixtyPical/doc/SixtyPical.md

408 lines
10 KiB
Markdown
Raw Normal View History

Sixtypical
==========
Sixtypical is a simplified version of [Sixtypical][].
This is a complete reboot of the previous design and implementation, which
was semantically a mess due to the way it was built.
This aims to be a simpler design which gets the static semantics right first,
and only then is extended to be more practical.
Types
-----
There are two TYPES in Sixtypical:
* bit (2 possible values)
* byte (256 possible values)
Memory locations
----------------
The primary concept in Sixtypical is the MEMORY LOCATION. At any given point
in time during execution, each memory location is either UNINITIALIZED or
INITIALIZED. At any given point in the program text, too, each memory
location is either uninitialized or initialized. Where-ever it is one or
the other during execution, it is the same in the corresponding place in
the program text; thus, it is a static property.
(There is actually a third state, WRITTEN, which indicates that the memory
location is not only initialized, but also that it has been written to in
the current routine.)
There are four general kinds of memory location. The first three are
pre-defined and built-in.
### Registers ###
Each of these hold a byte. They are initially uninitialized.
a
x
y
### Flags ###
Each of these hold a bit. They are initially uninitialized.
c (carry)
z (zero)
v (overflow)
n (negative)
### Constants ###
It may be strange to think of constants as memory locations, but keep in mind
that a memory location in Sixtypical need not map to a memory location in the
underlying hardware. All constants are read-only. Each is
initially initialized with the value that corresponds with its name.
They come in bit and byte types. There are two bit constants,
off
on
and two-hundred and fifty-six byte constants,
0
1
...
255
### User-defined ###
There may be any number of user-defined memory locations. They are defined
by giving the type, which must be `byte`, and the name.
byte pos
Routines
--------
Every routine must list all the memory locations it READS from, i.e. its
INPUTS, and all the memory locations it WRITES to, whether they are OUTPUTS
or merely TRASHED. Every memory location that is not written to is PRESERVED.
routine foo
inputs a, score
outputs x
trashes y {
...
}
Routines may call only routines previously defined in the program source.
Thus, recursive routines are not allowed.
There must be one routine called `main`. This routine is executed when
the program is run.
Instructions
------------
### ld ###
ld <dest-memory-location>, <src-memory-location>
Reads from src and writes to dest.
* It is illegal if dest is not a register.
* It is illegal if dest does not occur in the WRITES list of the current
routine.
* It is illegal if src is not of same type as dest (i.e., is not a byte.)
* It is illegal if src is uninitialized.
* It is illegal if src does not either:
* be a constant, or
* occur in the READS list of the current routine, or
* occur in the WRITES list of the current routine AND
that location has previously been written inside this routine.
After execution, dest is considered initialized. The flags `z` and `n` may be
changed by this instruction, and they are considered initialized after it has
executed.
Some combinations, such as `ld x, y`, are illegal because they do not map to
underlying opcodes.
Notes:
ld a, 123 → LDA #123
ld a, lives → LDA LIVES
ld x, 123 → LDX #123
ld x, lives → LDX LIVES
ld y, 123 → LDY #123
ld y, lives → LDY LIVES
ld x, a → TAX
ld y, a → TAY
ld a, x → TXA
ld a, y → TYA
### st ###
st <src-memory-location>, <dest-memory-location>
Reads from src and writes to dest.
* It is illegal if dest is a register or if dest is read-only.
* It is illegal if dest does not occur in the WRITES list of the current
routine.
* It is illegal if src is not of same type as dest.
* It is illegal if src is uninitialized.
* It is illegal if src does not either:
* be a constant, or
* occur in the READS list of the current routine, or
* occur in the WRITES list of the current routine AND
that location has previously been written inside this routine.
After execution, dest is considered initialized. No flags are
changed by this instruction (unless of course dest is a flag.)
Notes:
st a, lives → STA LIVES
st x, lives → STX LIVES
st y, lives → STY LIVES
st on, c → SEC
st off, c → CLC
### add dest, src ###
add <dest-memory-location>, <src-memory-location>
Adds the contents of src to dest and stores the result in dest.
* It is illegal if src OR dest OR c is uninitialized.
* It is illegal if dest is read-only.
* It is illegal if dest does not occur in the WRITES AND READS lists
of the current routine.
* It is illegal if src does not either:
* be a constant, or
* occur in the READS list of the current routine, or
* occur in the WRITES list of the current routine AND
that location has previously been written inside this routine.
Affects n, z, c, and v flags.
dest continues to be initialized afterwards.
Notes:
add a, delta → ADC DELTA
add a, 1 → ADC #1
### inc ###
TODO: these do not honour carry!
inc x → INX
inc y → INY
inc lives → INC LIVES
### sub ###
sub <dest-memory-location>, <src-memory-location>
Subtracts the contents of src from dest and stores the result in dest.
The constraints and effects are exactly the same as for `add`.
Notes:
sub a, delta → SBC DELTA
sub a, 1 → SBC #1
### dec ###
TODO: these do not honour carry!
dec x → DEX
dec y → DEY
dec lives → DEC LIVES
### cmp ###
cmp <dest-memory-location>, <src-memory-location>
Subtracts the contents of src from dest, but does not store the result.
The constraints and effects are the same as for `sub`, except that `c`
need not be initialized before executing `cmp`, and the `v` flag is
unaffected.
Notes:
cmp a, delta → CMP DELTA
cmp a, 1 → CMP #1
cmp x, 1 → CPX #1
cmp y, 1 → CPY #1
### and ###
and <dest-memory-location>, <src-memory-location>
"AND"s the contents of src with dest and stores the result in dest.
The constraints are the same as for `cmp`, except that the `c` flag
is not affected. i.e. only `n` and `z` flags are affected.
Notes:
and a, 8 → AND #8
### or ###
or <dest-memory-location>, <src-memory-location>
"OR"s the contents of src with dest and stores the result in dest.
The constraints and effects are exactly the same as for `and`.
Notes:
or a, 8 → ORA #8
### xor ###
xor <dest-memory-location>, <src-memory-location>
"XOR"s the contents of src with dest and stores the result in dest.
The constraints and effects are exactly the same as for `and`.
Notes:
xor a, 8 → EOR #8
### shl ###
shl <dest-memory-location>
Shifts the dest left one bit position. The rightmost position becomes `c`,
and `c` becomes the bit that was shifted off the left.
* It is illegal if dest is a register besides `a`.
* It is illegal if dest is read-only.
* It is illegal if dest OR c is uninitialized.
* It is illegal if dest does not occur in the WRITES AND READS lists
of the current routine.
Notes:
shl a → ROL A
shl lives → ROL LIVES
### shr ###
shr <dest-memory-location>
Shifts the dest right one bit position. The leftmost position becomes `c`,
and `c` becomes the bit that was shifted off the right.
Constraints are exactly the same as for `shl`.
Notes:
shr a → ROR A
shr lives → ROR LIVES
### call ###
call <routine-name>
Just before the call,
* It is illegal if any of the memory locations in the routine's READS list is
uninitialized.
Just after the call,
* All memory locations listed as TRASHED in the routine's WRITES list are
considered uninitialized.
Notes:
call routine → JSR ROUTINE
### if ###
if (bit) {
true-branch
} else {
false-branch
}
_bit_ is usually one of the flags, z or c.
Notes:
BEQ Branch on Result Zero
BMI Branch on Result Minus
BNE Branch on Result not Zero
BPL Branch on Result Plus
BCC Branch on Carry Clear
BCS Branch on Carry Set
BVC Branch on Overflow Clear
BVS Branch on Overflow Set
- - - -
Grammar
-------
Program ::= {Defn} {Routine}.
Defn ::= "byte" NewIdent.
Routine ::= "routine" NewIdent
["inputs" LocExprs] ["outputs" LocExprs] ["trashes" LocExprs]
Block.
LocExprs::= LocExpr {"," LocExpr}.
LocExpr ::= Register | Flag | Const | DefnIdent.
Register::= "a" | "x" | "y".
Flag ::= "c" | "z" | "n" | "v".
Const ::= "0" ... "255".
Block ::= "{" {Instr} "}".
Instr ::= "ld" LocExpr "," LocExpr
| "st" LocExpr "," LocExpr
| "add" LocExpr "," LocExpr
| "sub" LocExpr "," LocExpr
| "cmp" LocExpr "," LocExpr
| "and" LocExpr "," LocExpr
| "or" LocExpr "," LocExpr
| "xor" LocExpr "," LocExpr
| "shl" LocExpr
| "shr" LocExpr
| "inc" LocExpr
| "dec" LocExpr
| "call" RoutineIdent
| "if" LocExpr Block ["else" Block].
### 6502 instructions unsupported ###
ASL Shift Left One Bit (Memory or Accumulator)
LSR Shift Right One Bit (Memory or Accumulator)
BIT Test Bits in Memory with Accumulator
BRK Force Break
CLD Clear Decimal Mode
CLI Clear interrupt Disable Bit
CLV Clear Overflow Flag
NOP No Operation
JMP Jump to New Location // but may be generated as part of `if`
PHA Push Accumulator on Stack
PHP Push Processor Status on Stack
PLA Pull Accumulator from Stack
PLP Pull Processor Status from Stack
RTI Return from Interrupt
RTS Return from Subroutine
SED Set Decimal Mode
SEI Set Interrupt Disable Status
TSX Transfer Stack Pointer to Index X
TXS Transfer Index X to Stack Pointer