[a7de7182] | 1 | Calling conventions, stack frame and zero page:
|
---|
| 2 |
|
---|
| 3 | The variables that normally are placed on the stack or in registers in C
|
---|
| 4 | are instead allocated in the zero page and saved on a (fictive) stack
|
---|
| 5 | when calling functions. Some locations have predefined functions though.
|
---|
| 6 | Arrays allocated as automatics are stored on the stack with a pointer
|
---|
| 7 | in zero page to its destination.
|
---|
| 8 |
|
---|
| 9 | 0-7 Unused
|
---|
| 10 | 10 Stack pointer
|
---|
| 11 | 11 Frame pointer
|
---|
| 12 | 12-14 Unused
|
---|
| 13 | 15 Used by prolog
|
---|
| 14 | 16 Prolog address, written in crt0
|
---|
| 15 | 17 Epilog address, written in crt0
|
---|
| 16 | 20-27 Auto-increment, scratch
|
---|
| 17 | 30-37 Auto-decrement, scratch
|
---|
| 18 | 40-47 Unused
|
---|
| 19 | 50-57 Scratch/Arguments
|
---|
| 20 | 60-77 Permanent, save before use.
|
---|
| 21 | 100-377 Addresses for subroutines, written by the assembler
|
---|
| 22 |
|
---|
| 23 | The normal registers (AC0-AC3) are all considered scratch registers.
|
---|
| 24 |
|
---|
| 25 | Register classes are assigned as:
|
---|
| 26 | AC0-AC3: AREGs.
|
---|
| 27 | AC2-AC3: BREGs.
|
---|
| 28 | 50-77: CREGs.
|
---|
| 29 | ...and eventually register pairs as DREGs.
|
---|
| 30 |
|
---|
| 31 | In byte code the low half of a word is the first byte (little-endian).
|
---|
| 32 | This is bit 8-15 in Nova syntax.
|
---|
| 33 |
|
---|
| 34 | The stack is growing towards lower adresses (as opposed to the Eclipse stack).
|
---|
| 35 | Stack layout:
|
---|
| 36 |
|
---|
| 37 | ! arg1 !
|
---|
| 38 | ! arg0 !
|
---|
| 39 | fp -> ! old pc!
|
---|
| 40 | ! old fp!
|
---|
| 41 | pc -> ! saved !
|
---|
| 42 |
|
---|
| 43 | A reference to a struct member in assembler, a = b->c; b is in ZP 50
|
---|
| 44 | + is zeropage-addressing
|
---|
| 45 | * is fp-adressing
|
---|
| 46 |
|
---|
| 47 | # offset 0
|
---|
| 48 | + lda 0,@50 # load value from indirect ZP 50 into ac0
|
---|
| 49 | * lda 2,,3 # load value from (ac3) into ac2
|
---|
| 50 | * lda 0,,2 # load value from (ac2) into ac0
|
---|
| 51 |
|
---|
| 52 | # offset 12
|
---|
| 53 | + lda 2,50 # load value from ZP 50 into ac2
|
---|
| 54 | + lda 0,12,2 # load value from (ac2+12) into ac0
|
---|
| 55 | * lda 2,,3 # load value from (ac3) into ac2
|
---|
| 56 | * lda 0,12,2 # load value from 12(ac2) into ac0
|
---|
| 57 |
|
---|
| 58 | # offset 517
|
---|
| 59 | + lda 2,50 # load value from ZP 50 into ac2
|
---|
| 60 | + lda 0,.L42-.,1 # load offset from .L42 PC-indexed
|
---|
| 61 | + addz 0,2,skp # add offset to ac2 and skip
|
---|
| 62 | +.L42: .word 517 # offset value
|
---|
| 63 | + lda 0,,2 # load value from (ac2) into ac0
|
---|
| 64 |
|
---|
| 65 | The prolog/epilog implementation; it is implemented as subroutines.
|
---|
| 66 |
|
---|
| 67 | .L42: .word 13 # number of words to save
|
---|
| 68 | func:
|
---|
| 69 | sta 3,@40 # save return address on stack
|
---|
| 70 | lda 2,.L42-.,1 # get save word count
|
---|
| 71 | jsr @45 # go to prolog
|
---|
| 72 | ...
|
---|
| 73 | lda 2,.L42-.,1 # get restore word count
|
---|
| 74 | jmp @46 # jump to epilog
|
---|
| 75 |
|
---|
| 76 | # words to save in 2, return address in 3
|
---|
| 77 | prolog:
|
---|
| 78 | sta 2,45 # save # of words to move at scratch
|
---|
| 79 | lda 0,41 # get old fp
|
---|
| 80 | lda 1,40 # get sp
|
---|
| 81 | sta 1,41 # save new fp
|
---|
| 82 | dsz 40 # decrement stack, will never be 0
|
---|
| 83 | sta 0,@40 # save old fp
|
---|
| 84 | dsz 40
|
---|
| 85 |
|
---|
| 86 | lda 0,off57 # fetch address of regs to save - 1
|
---|
| 87 | sta 0,20 # store address at autoincr
|
---|
| 88 | 1: lda 0,@20 # get word to copy
|
---|
| 89 | sta 0,@40 # push on stack
|
---|
| 90 | dsz 40 # manually decrement sp
|
---|
| 91 | dsz 45 # copied all words?
|
---|
| 92 | jmp 1b,1 # no, continue
|
---|
| 93 | jmp 0,3 # return
|
---|
| 94 |
|
---|
| 95 | epilog:
|
---|
| 96 | sta 2,45 # save # of words to move at scratch
|
---|
| 97 |
|
---|
| 98 | lda 3,off57 # fetch address of regs to save
|
---|
| 99 | sta 3,20 # store at autoincr
|
---|
| 100 | lda 3,41 # fetch fp
|
---|
| 101 | sta 3,30 # store at autodecr
|
---|
| 102 | lda 3,@30 # get old fp
|
---|
| 103 |
|
---|
| 104 | 1: lda 2,@30 # fetch word from stack
|
---|
| 105 | sta 2,@20 # store at orig place
|
---|
| 106 | dsz 45 # enough?
|
---|
| 107 | jmp 1b,1 # no, continue
|
---|
| 108 |
|
---|
| 109 | lda 2,41 # get new fp
|
---|
| 110 | sta 2,40 # restore stack
|
---|
| 111 | sta 3,41 # restore old fp
|
---|
| 112 | jmp @40 # Return
|
---|
| 113 |
|
---|
| 114 | Assembler syntax and functions.
|
---|
| 115 |
|
---|
| 116 | The assembler syntax mimics the DG assembler.
|
---|
| 117 | Load and store to addresses is written "lda 0,foo" to load from address foo.
|
---|
| 118 | If foo is not in zero page then the assembler will put the lda in the
|
---|
| 119 | text area close to the instruction and do an indirect pc-relative load.
|
---|
| 120 |
|
---|