#!/bin/bash # # SPDX-License-Identifier: BSD-3-Clause # # Copyright © 2019 Keith Packard # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # # 3. Neither the name of the copyright holder nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # OF THE POSSIBILITY OF SUCH DAMAGE. # qemu="qemu-system-arm" # select the program elf="$1" shift cpu=unknown machine=unknown memory= # # Map ELF information to required core type # cpu_arch=`arm-none-eabi-readelf -A "$elf" | awk '/Tag_CPU_arch:/ { print $2 }'` cpu_profile=`arm-none-eabi-readelf -A "$elf" | awk '/Tag_CPU_arch_profile:/ { print $2 }'` fp_arch=`arm-none-eabi-readelf -A "$elf" | awk '/Tag_FP_arch/ { print $2 }'` fp_use=`arm-none-eabi-readelf -A "$elf" | awk '/Tag_ABI_HardFP_use/ { print $2 }'` ram_addr=`arm-none-eabi-readelf -l "$elf" | awk '/LOAD.*RW/ { if (min_va == 0 || $3 < min_va) min_va = $3; } END { print(min_va); }'` case "$cpu_arch"/"$cpu_profile" in v4T/) cpu=ti925t ;; v5TE/|v5T/) cpu=arm926 ;; v6S-M/Microcontroller) cpu=cortex-m0 ;; v7/Application) case "$fp_arch" in VFPv3) cpu=cortex-a9 ;; VFPv3-D16) cpu=cortex-a8 ;; VFPv4) cpu=cortex-a7 ;; *) cpu=cortex-a7 ;; esac ;; v7/) case "$fp_arch" in VFPv3) cpu=cortex-r5 ;; VFPv3-D16) cpu=cortex-r5f ;; *) cpu=cortex-r5 ;; esac ;; v7/Microcontroller) case "$fp_arch" in FPv5/FP-D16) case "$fp_use" in SP) cpu=cortex-m4 ;; *) cpu=cortex-m7 ;; esac ;; VFPv4-D16) cpu=cortex-m7 ;; *) cpu=cortex-m3 ;; esac ;; v7/Realtime) cpu=cortex-r5f ;; v7E-M/Microcontroller) cpu=cortex-m7 case "$fp_arch" in FPv5/FP-D16) case "$fp_use" in SP) cpu=cortex-m4 ;; esac ;; VFPv4-D16) cpu=cortex-m7 ;; *) cpu=cortex-m4 ;; esac ;; v8-M.*/Microcontroller) case "$fp_arch" in FPv5/FP-D16) case "$fp_use" in SP) cpu=cortex-m33 ;; *) cpu=cortex-m55 ;; esac ;; *) cpu=cortex-m33 ;; esac ;; v8.1-M.mainline/Microcontroller) cpu=cortex-m55 ;; v8/Application) cpu=cortex-a57 ;; esac # # Select a QEMU machine based on the CPU # case $cpu in cortex-m0) machine=microbit memory="-global nrf51-soc.sram-size=2097152 -global nrf51-soc.flash-size=4194304" ;; # mps2-an385 offers a cortex-m3 processor cortex-m3) machine=mps2-an385 ;; # mps2-an386 offers a cortex-m4 processor cortex-m4) machine=mps2-an386 ;; # mps2-an500 offers a cortex-m7 processor cortex-m7) machine=mps2-an500 ;; # mps2-an505 offers a cortex-m33 processor cortex-m33) machine=mps2-an505 ;; # mps3-an547 offers a cortex-m55 processor cortex-m55) machine=mps3-an547 ;; cortex-a57) machine=none cpu=max memory="-m 1G" ;; cortex-a?) case "$ram_addr" in 0x48*) machine=vexpress-a9 cpu=cortex-a9 ;; *) machine=none ;; esac memory="-m 1G" ;; # The 'none' machine supports many non-M # processors ti925t|arm*|cortex-a*|cortex-r*) machine=none memory="-m 1G" ;; esac # # Make sure the target machine and cpu is supported by qemu # if $qemu -machine help | grep -q "^$machine "; then if $qemu -machine $machine -cpu help | grep -q "^ *$cpu"; then : else echo "Skipping $elf: unsupported cpu on $machine" exit 77 fi else echo "Skipping $elf: unsupported machine" exit 77 fi # Map stdio to a multiplexed character device so we can use it # for the monitor and semihosting output chardev=stdio,mux=on,id=stdio0 # Point the semihosting driver at our new chardev cmdline="program-name" input="" done=0 while [ "$done" != "1" ]; do case "$1" in --) shift done=1 ;; -s|"") done=1 ;; *) cmdline="$cmdline $1" case "$input" in "") input="$1" ;; *) input="$input $1" ;; esac shift ;; esac done semi=enable=on,chardev=stdio0,arg="$cmdline" # Disable monitor mon=none # Disable serial serial=none export QEMU_AUDIO_DRV=none input_file=`mktemp` trap 'rm "$input_file"' 0 echo "$input" > "$input_file" "$qemu" $memory \ -chardev "$chardev" \ -semihosting-config "$semi" \ -monitor "$mon" \ -serial "$serial" \ -machine "$machine",accel=tcg \ -cpu "$cpu" \ -device loader,file="$elf",cpu-num=0 \ -nographic \ "$@" < $input_file result=$? if [ $result != 0 ]; then case $cpu in # Cortex-a8 qemu has minor floating point errors # when run on i686 processors cortex-a8) test="$(uname -m)-$elf" case "$test" in i?86-*math_test|i?86-*math_test_?|i?86-*math_test_??) echo "fp imprecise for $cpu on" "$(uname -m)" result=77 ;; esac ;; esac fi exit $result