fuzzy/routines.asm

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