/words.s
.include "macros.inc"

.section .text

def_word halt
	b _halt
def_end halt

// pop  ( a -- )
def_word pop inline=1
	pop {r0}
def_end pop

// dup  ( a -- a a )
def_word dup
	pop {r0}
	push {r0}
	push {r0}
	bx lr
def_end dup

// add  ( a b -- a + b )
def_word add
	pop {r0, r1}
	add r0, r0, r1
	push {r0}
	bx lr
def_end add

def_word do
	// store the location following this word on the control stack
	mov r0, lr
	push_cs
	bx lr
def_end do

def_word while
	peek_cs
	pop {r1}
	cmp r1, #0
	beq 1f
	// jump to the word from the control stack, but do not pop it
	bx r0
1:	// complete the control stack pop and continue
	mov r9, r2
	bx lr
def_end while

def_word eq
	pop {r0, r1}
	cmp r0, r1
	beq 1f
	mov r0, #0
	b 2f
1:	mov r0, #1
2:	push {r0}
	bx lr
def_end eq

def_word ne
	pop {r0, r1}
	sub r0, r1
	push {r0}
	bx lr
def_end ne

def_word putch
	pop {r0}
	push {lr}
	ldr r1, 1f
	blx r1
	pop {pc}
.align 2
1:	.word _platform_putch
def_end putch

def_word getch
	push {lr}
	ldr r1, 1f
	blx r1
	pop {r1}
	push {r0}
	bx r1
.align 2
1:	.word _platform_getch
def_end getch

def_word if compile_time=1 inline=1
	pop {r0}
	cmp r0, #0
	beq . + 4    // incomplete conditional branch to else/endif
def_end if

.type _if_ctsupp, %function
_if_ctsupp:
	ldr r0, =scratch_pointer
	ldr r0, [r0]
	sub r0, #2
	push_cs      // push the location of the incomplete branch onto the control stack
	bx lr

def_word endif compile_time=1 inline=1
def_end endif

.type _endif_ctsupp, %function
_endif_ctsupp:
	ldr r1, =scratch_pointer
	ldr r1, [r1]             // get the current scratch pointer, which is our destination
	pop_cs                   // get the location of the branch instruction we saved earlier
	sub r2, r1, r0           // calculate the offset
	sub r2, #4               // subtract the PC reference offset
	lsr r2, #1               // and trim the LSB
	strb r2, [r0]            // and store the offset into the branch instruction
	bx lr

def_word else compile_time=1 inline=1
	b . + 4      // incomplete unconditional branch to following endif
def_end else

.type _else_ctsupp, %function
_else_ctsupp:
	ldr r1, =scratch_pointer
	ldr r1, [r1]             // get the current scratch pointer, which is our destination
	pop_cs                   // get the location of the branch instruction we saved earlier
	sub r2, r1, r0           // calculate the offset
	sub r2, #4               // subtract the PC reference offset
	lsr r2, #1               // and trim the LSB
	strb r2, [r0]            // and store the offset into the branch instruction
	mov r0, r1
	sub r0, #2
	push_cs                  // store the location of this incomplete branch on the control stack
	bx lr

.align 2
.global rom_word_list
rom_word_list:
	.word halt
	.word pop
	.word dup
	.word add
	.word do
	.word while
	.word eq
	.word ne
	.word putch
	.word getch
	.word if
	.word endif
	.word else
	.word 0      // zero terminated