.section .text
.align 1
.global _err_halt
.type _err_halt, %function
_err_halt:
push {lr}
mov r0, mov r4, r10
add r4, 1: bl _platform_putch
sub r4, bne 1b
2: mov r0, bl _platform_putch
ldr r0, =_halted_str
bl putstr
ldr r1, =0xE000ED0C
ldr r0, =0x05FA0004
str r0, [r1]
// should reset at this point
1: b 1b
// print the null-terminated string pointed to by r0
.align 1
.global putstr
.type putstr, %function
putstr:
push {lr}
mov r4, r0
1: ldrb r0, [r4]
cmp r0, beq 2f
bl _platform_putch
add r4, b 1b
2: pop {pc}
.align 2
.global Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr r0, =control_stack
mov r9, r0
bl setup_words
bl _platform_serial_init
1: ldr r0, =_prompt_str
bl putstr
bl read_input
mov r0, bl _platform_putch
bl compile
bl execute_scratchword
mov r0, bl _platform_putch
b 1b
setup_words:
push {lr}
ldr r5, =environment
add r1, r5, str r1, [r5] // head (address where next word goes)
mov r0, str r0, [r5, // load ROM words
ldr r4, =rom_word_list
1: ldr r0, [r4]
cmp r0, beq 2f
push {r4}
bl add_rom_word
pop {r4}
add r4, b 1b
2: pop {pc}
read_input:
push {lr}
ldr r4, =input_buffer
mov r8, r4
mov r5, mov r10, r5
1: bl _platform_getch
cmp r0, beq 2f
cmp r0, beq 3f
cmp r0, beq 3f
// a regular character
cmp r5, beq 1b // buffer is full, go back to start
strb r0, [r4, r5] // store char in buffer
bl _platform_putch // print the character
add r5, b 1b // go back to start
// a newline
2: sub r6, r4, strb r5, [r6] // write the number of characters
pop {pc} // return
// a backspace
3: cmp r5, beq 1b // if we're already at zero characters, do nothing and continue
sub r5, #1 // remove one char from the input buffer count
mov r0, #0x08
bl _platform_putch // backspace one character
mov r0, #' '
bl _platform_putch // print a space
mov r0, #0x08
bl _platform_putch // and backspace again
b 1b // back to the top
add_rom_word:
ldr r5, =environment
ldr r1, [r5] // r1 is now the head address
ldrh r2, [r0] // get the number of bytes for the ROM word
mov r4, #0 // counter value
1: ldr r3, [r0, r4] // load
str r3, [r1, r4] // store
add r4, #4
cmp r4, r2 // if we've copied all the bytes
bne 1b // loop
add r1, r2 // add to get the next head location
str r1, [r5] // store the new head
mov r2, str r2, [r1] // And make sure the next word offset is end of list
bx lr
// r8 - in, input buffer address
// r10 - in/out, input buffer word position
// r11 - out, word length
.global get_next_word
.type get_next_word, %function
get_next_word:
mov r4, r8 // r4 is the local input buffer address
ldr r5, =input_counter
ldrb r5, [r5] // r5 is the input buffer length
mov r0, r10 // r0 is word position
1:
ldrb r2, [r4, r0] // load char
cmp r2, bne 2f // if so, continue
add r0, cmp r0, r5
beq 4f // have we hit the input buffer length?
b 1b
2: mov r1, r0
3: ldrb r2, [r4, r1]
cmp r2, beq 4f // is it not a space?
add r1, cmp r1, r5 // have we hit the input buffer length?
bne 3b // if not, continue
4: sub r1, r0 // word length is end - beginning
mov r11, r1
mov r10, r0
bx lr
// based on the input string starting at r10 and with length r11, set r0 to the
// beginning of the word's code or else set r0 to 0 if the word was not found.
.global search_environment
.type search_environment, %function
search_environment:
push {r4, r5, r6, lr}
ldr r6, =input_buffer
mov r1, r10 // load input buffer position
add r6, r1 // r6 is now a pointer into the input buffer
ldr r4, =environment
add r4, #4 // start at the beginning
1: ldrh r0, [r4] // load the offset to next word
cmp r0, #0
beq 5f // if it's zero, we're done
ldrb r3, [r4, #8] // load the name length
cmp r3, r11 // is it the same as the length we have in r11?
beq 3f // string lengths are the same; compare bytes
2: add r4, r0 // else add to the word pointer
b 1b // and try the next word
3: ldrh r5, [r4, #2] // load code length
add r5, #10 // add header offset
add r5, r4 // r5 is the beginning of the word name string
mov r1, #0 // set up index
4: ldrb r2, [r5, r1] // load dict byte
ldrb r3, [r6, r1] // load input byte
cmp r2, r3 // are they the same?
bne 2b // if not, go to the next dict word
add r1, #1 // increment
cmp r1, r11 // have we checked all the bytes in the word?
bne 4b // if not, check next byte
// success!
mov r0, r4
pop {r4, r5, r6, pc}
// the word was not found; set r0 to 0
5: mov r0, #0
pop {r4, r5, r6, pc}