Damien George | 04b9147 | 2014-05-03 23:27:38 +0100 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the Micro Python project, http://micropython.org/ |
| 3 | * |
| 4 | * The MIT License (MIT) |
| 5 | * |
| 6 | * Copyright (c) 2013, 2014 Damien P. George |
| 7 | * |
| 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 9 | * of this software and associated documentation files (the "Software"), to deal |
| 10 | * in the Software without restriction, including without limitation the rights |
| 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 12 | * copies of the Software, and to permit persons to whom the Software is |
| 13 | * furnished to do so, subject to the following conditions: |
| 14 | * |
| 15 | * The above copyright notice and this permission notice shall be included in |
| 16 | * all copies or substantial portions of the Software. |
| 17 | * |
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 24 | * THE SOFTWARE. |
| 25 | */ |
| 26 | |
Paul Sokolovsky | b1ce37d | 2014-04-30 04:19:20 +0300 | [diff] [blame] | 27 | #if defined(__x86_64__) && !MICROPY_NLR_SETJMP |
Damien George | 133b083 | 2014-09-26 13:07:26 +0000 | [diff] [blame] | 28 | |
| 29 | // We only need the functions here if we are on x86-64, and we are not |
| 30 | // using setjmp/longjmp. |
| 31 | // |
| 32 | // For reference, x86-64 callee save regs are: |
| 33 | // rbx, rbp, rsp, r12, r13, r14, r15 |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 34 | |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 35 | // the offset of nlr_top within mp_state_ctx_t |
| 36 | #define NLR_TOP_OFFSET (2 * 8) |
| 37 | |
Damien George | 5b7aa29 | 2015-01-08 16:24:44 +0000 | [diff] [blame] | 38 | #if defined(__APPLE__) && defined(__MACH__) |
| 39 | #define NLR_TOP (_mp_state_ctx + NLR_TOP_OFFSET) |
| 40 | #else |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 41 | #define NLR_TOP (mp_state_ctx + NLR_TOP_OFFSET) |
Damien George | 5b7aa29 | 2015-01-08 16:24:44 +0000 | [diff] [blame] | 42 | #endif |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 43 | |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 44 | .file "nlr.s" |
| 45 | .text |
| 46 | |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 47 | #if !defined(__CYGWIN__) |
| 48 | |
Damien George | 133b083 | 2014-09-26 13:07:26 +0000 | [diff] [blame] | 49 | /******************************************************************************/ |
| 50 | // |
| 51 | // Functions for *nix and OSX. |
| 52 | // OSX needs _ prefix for binding to C, and doesn't support some directives. |
| 53 | // |
| 54 | /******************************************************************************/ |
Antonin ENFRUN | 6caae0b | 2014-05-11 21:28:26 +0200 | [diff] [blame] | 55 | |
Damien George | 133b083 | 2014-09-26 13:07:26 +0000 | [diff] [blame] | 56 | /**************************************/ |
| 57 | // mp_uint_t nlr_push(rdi=nlr_buf_t *nlr) |
| 58 | |
xbe | 6068210 | 2014-03-21 02:05:39 -0700 | [diff] [blame] | 59 | #if !(defined(__APPLE__) && defined(__MACH__)) |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 60 | .globl nlr_push |
| 61 | .type nlr_push, @function |
| 62 | nlr_push: |
Mikael Eiman | 5d02e2d | 2014-01-04 20:15:04 +0100 | [diff] [blame] | 63 | #else |
| 64 | .globl _nlr_push |
| 65 | _nlr_push: |
| 66 | #endif |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 67 | movq (%rsp), %rax # load return %rip |
| 68 | movq %rax, 16(%rdi) # store %rip into nlr_buf |
| 69 | movq %rbp, 24(%rdi) # store %rbp into nlr_buf |
| 70 | movq %rsp, 32(%rdi) # store %rsp into nlr_buf |
| 71 | movq %rbx, 40(%rdi) # store %rbx into nlr_buf |
| 72 | movq %r12, 48(%rdi) # store %r12 into nlr_buf |
| 73 | movq %r13, 56(%rdi) # store %r13 into nlr_buf |
| 74 | movq %r14, 64(%rdi) # store %r14 into nlr_buf |
| 75 | movq %r15, 72(%rdi) # store %r15 into nlr_buf |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 76 | movq NLR_TOP(%rip), %rax # get last nlr_buf |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 77 | movq %rax, (%rdi) # store it |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 78 | movq %rdi, NLR_TOP(%rip) # stor new nlr_buf (to make linked list) |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 79 | xorq %rax, %rax # return 0, normal return |
| 80 | ret # return |
xbe | 6068210 | 2014-03-21 02:05:39 -0700 | [diff] [blame] | 81 | #if !(defined(__APPLE__) && defined(__MACH__)) |
Mikael Eiman | f53cdd9 | 2014-01-04 20:19:19 +0100 | [diff] [blame] | 82 | .size nlr_push, .-nlr_push |
| 83 | #endif |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 84 | |
Damien George | 133b083 | 2014-09-26 13:07:26 +0000 | [diff] [blame] | 85 | /**************************************/ |
| 86 | // void nlr_pop() |
| 87 | |
xbe | 6068210 | 2014-03-21 02:05:39 -0700 | [diff] [blame] | 88 | #if !(defined(__APPLE__) && defined(__MACH__)) |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 89 | .globl nlr_pop |
| 90 | .type nlr_pop, @function |
| 91 | nlr_pop: |
Mikael Eiman | 5d02e2d | 2014-01-04 20:15:04 +0100 | [diff] [blame] | 92 | #else |
| 93 | .globl _nlr_pop |
| 94 | _nlr_pop: |
| 95 | #endif |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 96 | movq NLR_TOP(%rip), %rax # get nlr_top into %rax |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 97 | movq (%rax), %rax # load prev nlr_buf |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 98 | movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list) |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 99 | ret # return |
xbe | 6068210 | 2014-03-21 02:05:39 -0700 | [diff] [blame] | 100 | #if !(defined(__APPLE__) && defined(__MACH__)) |
Mikael Eiman | f53cdd9 | 2014-01-04 20:19:19 +0100 | [diff] [blame] | 101 | .size nlr_pop, .-nlr_pop |
| 102 | #endif |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 103 | |
Damien George | 133b083 | 2014-09-26 13:07:26 +0000 | [diff] [blame] | 104 | /**************************************/ |
| 105 | // void nlr_jump(rdi=mp_uint_t val) |
| 106 | |
xbe | 6068210 | 2014-03-21 02:05:39 -0700 | [diff] [blame] | 107 | #if !(defined(__APPLE__) && defined(__MACH__)) |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 108 | .globl nlr_jump |
| 109 | .type nlr_jump, @function |
| 110 | nlr_jump: |
Mikael Eiman | 5d02e2d | 2014-01-04 20:15:04 +0100 | [diff] [blame] | 111 | #else |
| 112 | .globl _nlr_jump |
| 113 | _nlr_jump: |
| 114 | #endif |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 115 | movq %rdi, %rax # put return value in %rax |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 116 | movq NLR_TOP(%rip), %rdi # get nlr_top into %rdi |
Damien George | 26cf55a | 2014-04-08 14:08:14 +0000 | [diff] [blame] | 117 | test %rdi, %rdi # check for nlr_top being NULL |
| 118 | je .fail # fail if nlr_top is NULL |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 119 | movq %rax, 8(%rdi) # store return value |
| 120 | movq (%rdi), %rax # load prev nlr_buf |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 121 | movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list) |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 122 | movq 72(%rdi), %r15 # load saved %r15 |
| 123 | movq 64(%rdi), %r14 # load saved %r14 |
| 124 | movq 56(%rdi), %r13 # load saved %r13 |
| 125 | movq 48(%rdi), %r12 # load saved %r12 |
| 126 | movq 40(%rdi), %rbx # load saved %rbx |
| 127 | movq 32(%rdi), %rsp # load saved %rsp |
| 128 | movq 24(%rdi), %rbp # load saved %rbp |
| 129 | movq 16(%rdi), %rax # load saved %rip |
| 130 | movq %rax, (%rsp) # store saved %rip to stack |
| 131 | xorq %rax, %rax # clear return register |
| 132 | inc %al # increase to make 1, non-local return |
| 133 | ret # return |
Damien George | 26cf55a | 2014-04-08 14:08:14 +0000 | [diff] [blame] | 134 | .fail: |
| 135 | movq %rax, %rdi # put argument back in first-arg register |
xbe | 6068210 | 2014-03-21 02:05:39 -0700 | [diff] [blame] | 136 | #if !(defined(__APPLE__) && defined(__MACH__)) |
Damien George | 133b083 | 2014-09-26 13:07:26 +0000 | [diff] [blame] | 137 | je nlr_jump_fail # transfer control to nlr_jump_fail |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 138 | .size nlr_jump, .-nlr_jump |
Damien George | 133b083 | 2014-09-26 13:07:26 +0000 | [diff] [blame] | 139 | #else |
| 140 | je _nlr_jump_fail # transfer control to nlr_jump_fail |
Mikael Eiman | 5d02e2d | 2014-01-04 20:15:04 +0100 | [diff] [blame] | 141 | #endif |
Damien | ce89a21 | 2013-10-15 22:25:17 +0100 | [diff] [blame] | 142 | |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 143 | #else // !defined(__CYGWIN__) |
| 144 | |
Damien George | 133b083 | 2014-09-26 13:07:26 +0000 | [diff] [blame] | 145 | /******************************************************************************/ |
| 146 | // |
| 147 | // Functions for Cygwin |
| 148 | // |
| 149 | /******************************************************************************/ |
| 150 | |
| 151 | /**************************************/ |
| 152 | // mp_uint_t nlr_push(rcx=nlr_buf_t *nlr) |
| 153 | |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 154 | .globl nlr_push |
| 155 | nlr_push: |
| 156 | movq (%rsp), %rax # load return %rip |
| 157 | movq %rax, 16(%rcx) # store %rip into nlr_buf |
| 158 | movq %rbp, 24(%rcx) # store %rbp into nlr_buf |
| 159 | movq %rsp, 32(%rcx) # store %rsp into nlr_buf |
| 160 | movq %rbx, 40(%rcx) # store %rbx into nlr_buf |
| 161 | movq %r12, 48(%rcx) # store %r12 into nlr_buf |
| 162 | movq %r13, 56(%rcx) # store %r13 into nlr_buf |
| 163 | movq %r14, 64(%rcx) # store %r14 into nlr_buf |
| 164 | movq %r15, 72(%rcx) # store %r15 into |
| 165 | movq %rdi, 80(%rcx) # store %rdr into |
| 166 | movq %rsi, 88(%rcx) # store %rsi into |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 167 | movq NLR_TOP(%rip), %rax # get last nlr_buf |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 168 | movq %rax, (%rcx) # store it |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 169 | movq %rcx, NLR_TOP(%rip) # stor new nlr_buf (to make linked list) |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 170 | xorq %rax, %rax # return 0, normal return |
| 171 | ret # return |
| 172 | |
Damien George | 133b083 | 2014-09-26 13:07:26 +0000 | [diff] [blame] | 173 | /**************************************/ |
| 174 | // void nlr_pop() |
| 175 | |
Damien George | 26cf55a | 2014-04-08 14:08:14 +0000 | [diff] [blame] | 176 | .globl nlr_pop |
| 177 | nlr_pop: |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 178 | movq NLR_TOP(%rip), %rax # get nlr_top into %rax |
Damien George | 26cf55a | 2014-04-08 14:08:14 +0000 | [diff] [blame] | 179 | movq (%rax), %rax # load prev nlr_buf |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 180 | movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list) |
Damien George | 26cf55a | 2014-04-08 14:08:14 +0000 | [diff] [blame] | 181 | ret # return |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 182 | |
Damien George | 133b083 | 2014-09-26 13:07:26 +0000 | [diff] [blame] | 183 | /**************************************/ |
| 184 | // void nlr_jump(rcx=mp_uint_t val) |
| 185 | |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 186 | .globl nlr_jump |
| 187 | nlr_jump: |
| 188 | movq %rcx, %rax # put return value in %rax |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 189 | movq NLR_TOP(%rip), %rcx # get nlr_top into %rcx |
Damien George | 26cf55a | 2014-04-08 14:08:14 +0000 | [diff] [blame] | 190 | test %rcx, %rcx # check for nlr_top being NULL |
| 191 | je .fail # fail if nlr_top is NULL |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 192 | movq %rax, 8(%rcx) # store return value |
| 193 | movq (%rcx), %rax # load prev nlr_buf |
Damien George | b4b10fd | 2015-01-01 23:30:53 +0000 | [diff] [blame] | 194 | movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list) |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 195 | movq 72(%rcx), %r15 # load saved %r15 |
| 196 | movq 64(%rcx), %r14 # load saved %r14 |
| 197 | movq 56(%rcx), %r13 # load saved %r13 |
| 198 | movq 48(%rcx), %r12 # load saved %r12 |
| 199 | movq 40(%rcx), %rbx # load saved %rbx |
| 200 | movq 32(%rcx), %rsp # load saved %rsp |
| 201 | movq 24(%rcx), %rbp # load saved %rbp |
| 202 | movq 16(%rcx), %rax # load saved %rip |
| 203 | movq 80(%rcx), %rdi # store %rdr into |
| 204 | movq 88(%rcx), %rsi # store %rsi into |
| 205 | movq %rax, (%rsp) # store saved %rip to stack |
| 206 | xorq %rax, %rax # clear return register |
| 207 | inc %al # increase to make 1, non-local return |
| 208 | ret # return |
Damien George | 26cf55a | 2014-04-08 14:08:14 +0000 | [diff] [blame] | 209 | .fail: |
| 210 | movq %rax, %rcx # put argument back in first-arg register |
| 211 | je nlr_jump_fail # transfer control to nlr_jump_fail |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 212 | |
Damien George | 4b34c76 | 2014-04-03 23:51:16 +0100 | [diff] [blame] | 213 | #endif // !defined(__CYGWIN__) |
| 214 | |
Damien George | 133b083 | 2014-09-26 13:07:26 +0000 | [diff] [blame] | 215 | #endif // defined(__x86_64__) && !MICROPY_NLR_SETJMP |