|
| 1 | +/* |
| 2 | + * Set of KickAssembler macros for subroutine implementation. |
| 3 | + * |
| 4 | + * With these macros one can realize communication with subroutines using stack. This approach |
| 5 | + * is following: |
| 6 | + * 1) subroutine caller prepares input parameters and pushes them to the stack using push*() macros |
| 7 | + * 2) subroutine is then called using JSR |
| 8 | + * 3) subroutine first preserves return address in local variable using invokeStackBegin(variablePtr) macro |
| 9 | + * 4) subroutine then pulls all pushed parameters in opposite order using pull*() macros |
| 10 | + * 5) when subroutine is about to end, just before RTS is called, it must restore return address with invokeStackEnd(varPtr) macro |
| 11 | + * |
| 12 | + * Requires KickAssembler v4.x |
| 13 | + * (c) 2017-2018 Maciej Malecki |
| 14 | + */ |
| 15 | +#importonce |
| 16 | +.filenamespace c128lib |
| 17 | + |
| 18 | +/* |
| 19 | + * Preserves return address that is used with JSR. |
| 20 | + * Should be called at beginning of subroutine. |
| 21 | + * |
| 22 | + * Params: |
| 23 | + * placeholderPtr - pointer to the memory location (that is local variable of the subroutine) |
| 24 | + * where return address will be preserved. |
| 25 | + */ |
| 26 | +.macro invokeStackBegin(placeholderPtr) { |
| 27 | + pla |
| 28 | + sta placeholderPtr |
| 29 | + pla |
| 30 | + sta placeholderPtr + 1 |
| 31 | +} |
| 32 | + |
| 33 | +/* |
| 34 | + * Restores return address that will be then used with RTS. |
| 35 | + * Should be called at the very end of subroutine just before RTS. |
| 36 | + * |
| 37 | + * Params: |
| 38 | + * placeholderPtr - pointer to the memory location (that is local variable of the subroutine) |
| 39 | + * from where return address will be restored. |
| 40 | + */ |
| 41 | +.macro invokeStackEnd(placeholderPtr) { |
| 42 | + lda placeholderPtr + 1 |
| 43 | + pha |
| 44 | + lda placeholderPtr |
| 45 | + pha |
| 46 | +} |
| 47 | + |
| 48 | +/* |
| 49 | + * Pushes byte value as a parameter to the subroutine. |
| 50 | + * Such value should be then pulled in subroutine in opposite order. |
| 51 | + * |
| 52 | + * Params: |
| 53 | + * value - byte value of the parameter for subroutine |
| 54 | + */ |
| 55 | +.macro pushParamB(value) { |
| 56 | + lda #value |
| 57 | + pha |
| 58 | +} |
| 59 | + |
| 60 | +/* |
| 61 | + * Pushes two bytes value as a parameter to the subroutine. |
| 62 | + * Such value should be then pulled in subroutine in opposite order. |
| 63 | + * |
| 64 | + * Params: |
| 65 | + * value - word value of the parameter for subroutine |
| 66 | + */ |
| 67 | +.macro pushParamW(value) { |
| 68 | + pushParamB(<value) |
| 69 | + pushParamB(>value) |
| 70 | +} |
| 71 | + |
| 72 | +/* |
| 73 | + * Pushes byte pointed by an address as a parameter to the subroutine. |
| 74 | + * Such value should be then pulled in subroutine in opposite order. |
| 75 | + * |
| 76 | + * Params: |
| 77 | + * ptr - pointer to the byte value of the parameter for subroutine |
| 78 | + */ |
| 79 | +.macro pushParamBInd(ptr) { |
| 80 | + lda ptr |
| 81 | + pha |
| 82 | +} |
| 83 | + |
| 84 | +/* |
| 85 | + * Pushes two bytes value pointed by an address as a parameter to the subroutine. |
| 86 | + * Such value should be then pulled in subroutine in opposite order. |
| 87 | + * |
| 88 | + * Params: |
| 89 | + * ptr - pointer to the two bytes value of the parameter for subroutine |
| 90 | + */ |
| 91 | +.macro pushParamWInd(ptr) { |
| 92 | + pushParamBInd(ptr) |
| 93 | + pushParamBInd(ptr + 1) |
| 94 | +} |
| 95 | + |
| 96 | +/* |
| 97 | + * Pulls byte value from the stack and stores it under given address. |
| 98 | + * |
| 99 | + * Params: |
| 100 | + * placeholderPtr - pointer to the memory location where given byte will be pulled to |
| 101 | + */ |
| 102 | +.macro pullParamB(placeholderPtr) { |
| 103 | + pla |
| 104 | + sta placeholderPtr |
| 105 | +} |
| 106 | + |
| 107 | +/* |
| 108 | + * Pulls two bytes value from the stack and stores it under given address. |
| 109 | + * |
| 110 | + * Params: |
| 111 | + * placeholderPtr - pointer to the beginning of memory location where given two bytes will be pulled to |
| 112 | + */ |
| 113 | +.macro pullParamW(placeholderPtr) { |
| 114 | + pullParamB(placeholderPtr + 1) |
| 115 | + pullParamB(placeholderPtr) |
| 116 | +} |
| 117 | + |
| 118 | +/* |
| 119 | + * Pulls two bytes value from the stack and stores it under provided addresses. |
| 120 | + * |
| 121 | + * Params: |
| 122 | + * placeholderPtrList - List of memory locations, where given two byte value will be stored |
| 123 | + */ |
| 124 | +.macro pullParamWList(placeholderPtrList) { |
| 125 | + .assert "list must be non empty", placeholderPtrList.size() > 0, true |
| 126 | + pla |
| 127 | + .for (var i = 0; i < placeholderPtrList.size(); i++) sta placeholderPtrList.get(i) + 1 |
| 128 | + pla |
| 129 | + .for (var i = 0; i < placeholderPtrList.size(); i++) sta placeholderPtrList.get(i) |
| 130 | +} |
| 131 | +.assert "pullParamWList([$aaaa, $bbbb])", {pullParamWList(List().add($aaaa, $bbbb))}, |
| 132 | +{pla;sta $aaaa + 1; sta $bbbb + 1; pla; sta $aaaa; sta $bbbb} |
0 commit comments