175 lines
3.6 KiB
NASM
175 lines
3.6 KiB
NASM
; ops
|
|
; - [ ] nat (positive integers)
|
|
; - [ ] * mult (i think anything bigger than 16 bits just gets cut off, george does not need big numbers rite)
|
|
; - [ ] / div (what do we do w fractions/remainders)
|
|
; - [ ] + add (same w *)
|
|
; - [ ] - sub (what should happen when y > x & x - y? )
|
|
; - [ ] int (pos/neg 2s complement numbers) (lots of the above applies)
|
|
; - [ ] * mult
|
|
; - [ ] / div
|
|
; - [ ] + add
|
|
; - [ ] - sub
|
|
; - [ ] bool
|
|
; - [ ] & and
|
|
; - [ ] | or
|
|
;
|
|
; literals (these will be macros here, meaning when i implement them in the compiler they will depend on what literals r being pushed)
|
|
; - [ ] bool
|
|
; - [ ] num
|
|
; - [ ] str
|
|
; - [ ] char
|
|
;
|
|
; i/o
|
|
; - [ ] write (pop off an address and some data and store it)
|
|
; - [ ] read (pop off an address and push the data at that address onto the stack)
|
|
; - [ ] key (stealing algo from forth: pause execution until there's a key pressed, then push that key on the stack, i don't think this breaks anything, this could probably be written easily in fuzzy w/ write and read words)
|
|
;
|
|
; control flow
|
|
; - [ ] if (pop off a bool and jump to word, this will also depend on compiler, so writing as macro)
|
|
|
|
; for example
|
|
; a is nat: 5
|
|
; b is nat: 3
|
|
; c bool is nat: if[a | b] *we'll figure out syntax later*
|
|
; true c
|
|
;
|
|
; (assuming c gets inlined since it's only referenced in the body)
|
|
; compiles to
|
|
; a:
|
|
; lda 5
|
|
; dex
|
|
; dex
|
|
; sta 0, x
|
|
; rts
|
|
;
|
|
; b:
|
|
; lda 3
|
|
; dex
|
|
; dex
|
|
; sta 0, x
|
|
; rts
|
|
;
|
|
; main:
|
|
; lda #1
|
|
; dex
|
|
; dex
|
|
; sta 0, x
|
|
; stz 1,x
|
|
; lda #1
|
|
; inx
|
|
; inx
|
|
; bit 2, x
|
|
; beq .falsy
|
|
; jsr a
|
|
; .falsy:
|
|
; jsr b
|
|
; stp ; or whatever here
|
|
|
|
|
|
; literals - the important thing is what the actual value is, each of these functions/macros are the same for any type, since the val is always just a 16 bit number
|
|
|
|
.macro lit, val
|
|
lda val
|
|
dex
|
|
dex
|
|
sta 0, x
|
|
stz 1, x
|
|
.endm
|
|
|
|
; control flow
|
|
|
|
.macro if, bool, addr ; condition, where to jump if true; pops a bool off the stack
|
|
lda #1
|
|
; in either case we pop a cell off the top
|
|
inx
|
|
inx
|
|
; but still need to check the bool on top
|
|
; TODO: make sure this works
|
|
bit 2, x
|
|
beq .falsy
|
|
; TODO: words will be defined as subroutines ig,
|
|
; and will be returned from after execution
|
|
jsr addr
|
|
.falsy:
|
|
.endm
|
|
|
|
; ops
|
|
nat_plus:
|
|
clc
|
|
lda 0, x
|
|
adc 2, x
|
|
sta 2, x
|
|
lda 1, x
|
|
adc 3, x
|
|
sta 3, x
|
|
inx
|
|
inx
|
|
rts
|
|
|
|
nat_mult_2:
|
|
asl 0, x
|
|
rol 1, x
|
|
rts
|
|
|
|
; after a silly escapade plotting u16 overflow charts
|
|
; i am making the executive decision that the vast majority
|
|
; of results (those that overflow 2 bytes) will be wrong :)
|
|
; for the sake of all results being 1 cell wide :)
|
|
; see this plot: ./overflow.png
|
|
; algo here: https://www.llx.com/Neil/a2/mult.html
|
|
nat_mult:
|
|
result = $200
|
|
lda #0 ; initialize result to 0
|
|
sta result+2
|
|
ldy #16 ; 16 bits in NUM2
|
|
.1:
|
|
lsr 0, x ; low byte of first number
|
|
ror 1, x
|
|
bcc .2 ; 0 or 1?
|
|
phy ; some register shuffling so we don't lose x stack pointer
|
|
tay
|
|
clc
|
|
lda 2, x ; low byte of second number
|
|
adc result + 2 ; add it to low byte of result
|
|
sta result + 2
|
|
tya
|
|
ply
|
|
adc 3, x ;
|
|
.2:
|
|
ror
|
|
ror result + 2
|
|
ror result + 1
|
|
ror result
|
|
dey
|
|
bne .1
|
|
sta result + 3
|
|
dex
|
|
dex
|
|
; TODO: double check endianness of result
|
|
lda result + 3 ; store high byte of result
|
|
sta 0, x
|
|
lda result + 2 ; store low byte of result
|
|
sta 1, x
|
|
rts
|
|
|
|
; i/o
|
|
read:
|
|
lda (0, x)
|
|
sta 0, x
|
|
stz 1, x
|
|
rts
|
|
|
|
write:
|
|
lda 0, x
|
|
sta (2, x)
|
|
inx
|
|
inx
|
|
inx
|
|
inx
|
|
rts
|
|
|
|
key:
|
|
;TODO
|
|
|
|
|