The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/bin/sh

# -----------------------------------------------------------------------
#  gentramp.sh - Copyright (c) 2010, Plausible Labs Cooperative, Inc.
#  
#  ARM Trampoline Page Generator
#
#  Permission is hereby granted, free of charge, to any person obtaining
#  a copy of this software and associated documentation files (the
#  ``Software''), to deal in the Software without restriction, including
#  without limitation the rights to use, copy, modify, merge, publish,
#  distribute, sublicense, and/or sell copies of the Software, and to
#  permit persons to whom the Software is furnished to do so, subject to
#  the following conditions:
#
#  The above copyright notice and this permission notice shall be included
#  in all copies or substantial portions of the Software.
#
#  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
#  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
#  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
#  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#  DEALINGS IN THE SOFTWARE.
#  -----------------------------------------------------------------------

PROGNAME=$0

# Each trampoline is exactly 3 instructions, or 12 bytes. If any of these values change,
# the entire arm trampoline implementation must be updated to match, too.

# Size of an individual trampoline, in bytes
TRAMPOLINE_SIZE=12

# Page size, in bytes
PAGE_SIZE=4096

# Compute the size of the reachable config page; The first 16 bytes of the config page
# are unreachable due to our maximum pc-relative ldr offset.
PAGE_AVAIL=`expr $PAGE_SIZE - 16`

# Compute the number of of available trampolines. 
TRAMPOLINE_COUNT=`expr $PAGE_AVAIL / $TRAMPOLINE_SIZE`

header () {
    echo "# GENERATED CODE - DO NOT EDIT"
    echo "# This file was generated by $PROGNAME"
    echo ""

    # Write out the license header
cat << EOF
#  Copyright (c) 2010, Plausible Labs Cooperative, Inc.
#  
#  Permission is hereby granted, free of charge, to any person obtaining
#  a copy of this software and associated documentation files (the
#  ``Software''), to deal in the Software without restriction, including
#  without limitation the rights to use, copy, modify, merge, publish,
#  distribute, sublicense, and/or sell copies of the Software, and to
#  permit persons to whom the Software is furnished to do so, subject to
#  the following conditions:
#
#  The above copyright notice and this permission notice shall be included
#  in all copies or substantial portions of the Software.
#
#  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
#  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
#  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
#  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#  DEALINGS IN THE SOFTWARE.
#  -----------------------------------------------------------------------

EOF

    # Write out the trampoline table, aligned to the page boundary
    echo ".text"
    echo ".align 12"
    echo ".globl _ffi_closure_trampoline_table_page"
    echo "_ffi_closure_trampoline_table_page:"
}


# WARNING - Don't modify the trampoline code size without also updating the relevant libffi code
trampoline () {
    cat << END

    // trampoline
    // Save to stack
    stmfd sp!, {r0-r3}

    // Load the context argument from the config page.
    // This places the first usable config value at _ffi_closure_trampoline_table-4080
    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
    ldr r0, [pc, #-4092]

    // Load the jump address from the config page.
    ldr pc, [pc, #-4092]

END
}

main () {
    # Write out the header
    header

    # Write out the trampolines
    local i=0
    while [ $i -lt ${TRAMPOLINE_COUNT} ]; do
        trampoline
        local i=`expr $i + 1`
    done
}

main