⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interpreter.inc

📁 This a basic compiler for MSP430
💻 INC
📖 第 1 页 / 共 5 页
字号:
; Butterfly BASIC - a BASIC interpreter for the MSP430
; Copyright (c) 2003, 2004 Paul Curtis
; email: plc@rowley.co.uk

; Butterfly Basic Register Usage
; ------------------------------
; R4 - current token taken from tokenized program image
; R5 - pointer to start of line currently executing
; R6 - pointer to current token within executing line
; R11 - for use exclusively by statement parsers
; R12/R13 - evaluation next on stack when entering binary operator routines
; R14/R15 - evaluation top of stack

#define tp  r6
#define lp  r5

#define BREAK 0x01
#define TIMER 0x02

; Hardware multiplier registers
#if 0
MPY     equ     0x130
MPYS    equ     0x132
MAC     equ     0x134
MACS    equ     0x136
OP2     equ     0x138
RESLO   equ     0x13a
RESHI   equ     0x13c
SUMEXT  equ     0x13e
#endif

#define COMMAND_TOKENS 0
#define UNARY_TOKENS   1
#define MISC_TOKENS    2
#define BINARY_TOKENS  3
                                 
#define END_OF_RAM 0xa00

        INCLUDELIB "c_sf"

; Keywords
#define T(SYM, STR, FUNC, PREC) _T SYM

_T	macro	X
X	equ	symval
symval	set	symval+1
	endm

#define USER_TOKENS "user_tokens.inc"

symval              set     $80
FIRST_COMMAND_TOKEN equ symval
#undef PART
#define PART COMMAND_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"
LAST_COMMAND_TOKEN  equ symval-1
FIRST_UNARY_TOKEN   equ symval
#undef PART
#define PART UNARY_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"
LAST_UNARY_TOKEN    equ symval-1
FIRST_MISC_TOKEN    equ symval
#undef PART
#define PART MISC_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"
LAST_MISC_TOKEN     equ symval-1
FIRST_BINARY_TOKEN  equ symval
#undef PART
#define PART BINARY_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"
LAST_BINARY_TOKEN   equ symval-1
LAST_TOKEN          equ symval

; Token command table
#undef T
#define T(SYM, STR, FUNC, PREC) _C FUNC

_C	macro	X
	dw      X
	endm

        .code
cmdtab:
#undef PART
#define PART COMMAND_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"

binarytab:
#undef PART
#define PART BINARY_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"

unarytab:
#undef PART
#define PART UNARY_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"

; Binary operator precedence table
#undef T
#define T(SYM, STR, FUNC, PREC) _P PREC

_P	macro	X
	db      X
	endm

        .code
operator_precedence:
        dc.b    0
#undef PART
#define PART BINARY_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"

; Keyword table
#undef T
#define T(SYM, STR, FUNC, PREC) _K STR

_K	macro	X
	db      X, 0
	endm

        .code
kwtab:
#undef PART
#define PART COMMAND_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"
#undef PART
#define PART UNARY_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"
#undef PART
#define PART MISC_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"
#undef PART
#define PART BINARY_TOKENS
#include "../tokens.inc"
#include "user_tokens.inc"


; Variable storage
        .bss
current_channel ds.b    1
trace_channel   ds.b    1
trace_flags     ds.b    1
        even
vars            ds.w    26*2                 ; A to Z is 104 bytes
arrays          ds.w    26*2                 ; A() to Z() is 104 bytes; 2 bytes for address, 2 for dimension
ramtop          ds.w    1
flashtop        ds.w    1
break_tp        ds.w    1                    ; break vector
break_lp        ds.w    1                    ; start of line of last ON BREAK
data_lp         ds.w    1                    ; pointer to start of line of current DATA statement
data_tp         ds.w    1                    ; pointer for DATA statements on READ
cont_tp         ds.w    1
cont_lp         ds.w    1
flags           ds.w    1
rndseed         ds.w    2
auto_line       ds.w    1                    ; line number for AUTO
auto_inc        ds.w    1                    ; line increment for AUTO
convert_buffer  ds.b    16

; This points to the (logical) first line of code in a user's program.
; As the program is edited, program_start will move to point to the
; lowest-numbered line number.
program_start   ds.w    1

        .code
	even

reset::
; Zero the whole of UDATA
        mov.w   #SFB(UDATA0), r15
        mov.w   #SFE(UDATA0)-SFB(UDATA0), r13
reset_10:
        mov.b   #0, @r15
	add.w   #1, r15
	sub.w   #1, r13
	jnz     reset_10

; Entry point for cold start.
        mov.w   #WDTPW+WDTHOLD, &WDTCTL      ; Turn off watchdog
        mov.w   #END_OF_RAM, sp              ; Initialise stack
        call    #hw_init                     ; Initialise hardware environment
        mov.b   #1, &current_channel         ; Default channel for output and tracing is #1
        mov.b   #1, &trace_channel
        mov.b   #0, &trace_flags             ; Start by not tracing

; Sign on.
        mov.w   #copyright_message, r15
        call    #print_message

; Prepare memory and show how much there is to the user.
        call    #new
        call    #memory

; Initialise PRNG.
        mov.w   #25374, &rndseed[0]
        mov.w   #63398, &rndseed[1]

; Come out of AUTO mode and go to ready.
no_auto:
        mov.w   #0, &auto_line               ; drop out of AUTO mode

; Entry point for main BASIC command entry loop
ready:
        mov.w   #1, r15                      ; Select the default channel
        call    #select_channel
        mov.w   #ready_message, r15          ; Indicate we're ready to accept a command
        call    #print_message
	mov.w   &ramtop, r14                 ; prepare to read string into ramtop
	cmp.w	#0, &auto_line               ; under control of AUTO?
	jz      ready_20
	mov.w   &auto_line, r14              ; load line number
	add.w   &auto_inc, &auto_line        ; update line number for next time round
	jnc     ready_05                     ; did the line number wrap?
        mov.w   #0, &auto_line               ; ...yes, come out of AUTO
ready_05:
	mov.w   #0, r15                      ; zero extend for conversion
	call    #print_integer               ; print it and also put it in the conversion buffer
	mov.w   #convert_buffer, r15         ; prepare to copy from convert buffer...
	mov.w   &ramtop, r14                 ; ...to ramtop
ready_10:
	mov.b   @r15+, @r14                  ; copy byte
	add.w   #1, r14                      ; no auto increment on destination
	cmp.b   #0, -1(r15)                  ; end of string copied?
	jnz     ready_10                     ; no, continue copying...
	mov.b   #' ', r15                    ; prepare to
	call    #print_char                  ; print a space
	mov.b   r15, -1(r14)                 ; and put it in the buffer
ready_20:
	call    #get_string_00               ; read string to memory at R14
        mov.w   #0, lp                       ; we're not executing a line stored in flash, so errors don't report a line number

; Skip initial spaces
        mov.w   &ramtop, tp
interpreter_00:
        mov.b   @tp+, r4                     ; Get character from buffer         
        cmp.b   #' ', r4                     ; if it's a space, ignore it
        jz      interpreter_00
        sub.w   #1, tp                       ; we've gone one too far with autoincrement, so adjust
        cmp.b   #0, r4                       ; if nothing on the entered line...
        jz      no_auto                      ; ...just be silent, drop AUTO, and get another line

; Figure out whether this is an immediate command or a numbered line
        call    #is_digit
        jc      interpreter_20               ; if carry set, then a line with line number has been entered

; No line nunber, so this is an immediate command
	mov.w   #0, &auto_line               ; come out of AUTO
        call    #tokenize                    ; tokenize put
        mov.w   &ramtop, tp                  ; start interpreting from the tokenized buffer
        jmp     chrget                       ; and execute

; Deal with a numbered line
interpreter_20:
        add.w   #1, tp                       ; point to next character
        call    #read_int                    ; read the line number into r15:r14...
        push.w  r14                          ; ...but only use the lower 16 bits
        sub.w   #1, tp                       ; we've run one too far on the line number
        mov.w   tp, r9                       ; save token pointer
        call    #tokenize                    ; tokenize the line
        pop.w   r14                          ; restore the line number
        mov.w   #program_start, r11          ; pointer to previous line

; Come out of AUTO mode if no line
        cmp.b   #0, @r9                      ; empty line?
	jnz     interpreter_30               ; ...no, process the line
        cmp.w   #0, &auto_line               ; in AUTO mode?
        jnz     no_auto                      ; ...yes, drop AUTO mode and go to ready mode

; Copy line into flash
interpreter_30:
        mov.w   &flashtop, r10
        mov.w   r10, r7
        mov.w   r14, r4
        add.w   #2, r10
        call    #flash_write_word
        add.w   #2, r10
copy_line:
        mov.b   @r9+, r4
        call    #flash_write_byte
        add.w   #1, r10
        cmp.w   #0, r4
        jnz     copy_line
        add.w   #1, r10
        bic.w   #1, r10
        mov.w   r10, &flashtop

; Find line number in r14
        mov.w   #program_start, r11
        mov.w   &program_start, r15
        cmp.w   #0, r15
        jz      insert_new_line
        jmp     x_find_line_10
x_find_line_00:
        mov.w   r15, r11
        mov.w   @r15, r15
        cmp.w   #0, r15
        jz      insert_new_line
x_find_line_10:
        cmp.w   2(r15), r14
        jz      replace_existing_line
        jc      x_find_line_00

; Insert line at r15.
insert_new_line:
        cmp.b   #0, 4(r7)                    ; Nothing to insert, i.e. deleting a non-existent line?
        jz      ready                        ; Yep, nothing to do.

; Point new line's foward pointer to point at next line.
        mov.w   r7, r10
        mov.w   @r11, r4
        call    #flash_write_word

; Update previous line's forward pointer to point here.
        mov.w   r7, r4
        mov.w   r11, r10
        call    #flash_write_word
        jmp     ready

replace_existing_line:
; Delete line entirely?
        cmp.b   #0, 4(r7)
        jz      delete_line

; Update previous line's forward pointer to point here.
        mov.w   @r15, r4                     ; data to write
        mov.w   r7, r10                      ; address to write at
        call    #flash_write_word

; Point previous line's forward pointer to point at next line.
        mov.w   r11, r10
        mov.w   r7, r4
        call    #flash_write_word
        jmp     ready

; Delete line
delete_line:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -