1#!/bin/sh
2#
3# SPDX-License-Identifier: BSD-3-Clause
4#
5# Copyright © 2019 Keith Packard
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10#
11# 1. Redistributions of source code must retain the above copyright
12#    notice, this list of conditions and the following disclaimer.
13#
14# 2. Redistributions in binary form must reproduce the above
15#    copyright notice, this list of conditions and the following
16#    disclaimer in the documentation and/or other materials provided
17#    with the distribution.
18#
19# 3. Neither the name of the copyright holder nor the names of its
20#    contributors may be used to endorse or promote products derived
21#    from this software without specific prior written permission.
22#
23# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
34# OF THE POSSIBILITY OF SUCH DAMAGE.
35#
36
37qemu="qemu-system-arm"
38
39# select the program
40elf="$1"
41shift
42
43cpu=unknown
44machine=unknown
45memory=
46
47#
48# Map from GCC configuration to QEMU CPU type
49#
50
51case "$elf" in
52    *arm_v5te_hard*|*arm_v5te_softfp*)
53	# The only v5 supported by qemu is the arm946,
54	# which doesn't have an FPU, and all of the GCC
55	#cpu=arm946
56	;;
57
58    # v6-m - Cortex-M0
59    *thumb_v6_m_nofp*)
60	cpu=cortex-m0
61	;;
62
63    # v7-a/v7ve - Cortex-A7
64    *thumb_v7_a*|*thumb_v7ve_*)
65	cpu=cortex-a7
66	;;
67
68    # v7-m - Cortex-M3
69    *thumb_v7_m_nofp*)
70	cpu=cortex-m3
71	;;
72
73    # v7-r - Cortex-R5
74    *thumb_v7_r*)
75	cpu=cortex-r5f
76	;;
77
78    # v7e-m - Cortex-M4
79    *thumb_v7e_m_nofp*)
80	cpu=cortex-m4
81	;;
82    *thumb_v7e_m_fp_hard*)
83	cpu=cortex-m4
84	;;
85    *thumb_v7e_m_fp_softfp*)
86	cpu=cortex-m4
87	;;
88
89    # v7e-m dp - Cortex-M7
90    *thumb_v7e_m_dp_hard*)
91	cpu=cortex-m7
92	;;
93    *thumb_v7e_m_dp_softfp*)
94	cpu=cortex-m7
95	;;
96
97    # v8-a - unknown
98    *thumb_v8_a*)
99	cpu=unknown
100	;;
101
102    # v8.1 - unknown
103    *thumb_v8_1*)
104	cpu=unknown
105	;;
106
107    # v8-m with single-precision FPU - Cortex-M33
108    *thumb_v8_m_base_nofp*)
109	cpu=cortex-m33
110	;;
111    *thumb_v8_m_main_fp_softfp*)
112	cpu=cortex-m33
113	;;
114    *thumb_v8_m_main_dp_softfp*)
115	;;
116    *thumb_v8_m_main_fp_hard*)
117	cpu=cortex-m33
118	;;
119    *thumb_v8_m_main_nofp*)
120	cpu=cortex-m33
121	;;
122
123    # v8-m with double-preicision FPU - none
124    *thumb_v8_m_main_dp_hard*)
125	;;
126
127    # v7 - Cortex-A7
128    *thumb_v7_nofp*)
129	cpu=cortex-a7
130	;;
131
132    # v7 with FPU - Cortex-A9
133    *thumb_v7_fp_hard*)
134	cpu=cortex-a8
135	;;
136    *thumb_v7_fp_softfp*)
137	cpu=cortex-a8
138	;;
139
140    # v4t - ti925t
141    *)
142	# ARMv4t is the default
143	cpu=ti925t
144	;;
145esac
146
147#
148# Select a QEMU machine based on the CPU
149#
150case $cpu in
151
152    # mps2-an385 offers a cortex-m3 processor
153    cortex-m3)
154	machine=mps2-an385
155	;;
156
157    # Maybe qemu upstream will take this machine
158    # which supports all Cortex-M processors
159    cortex-m*)
160	machine=virtm
161	;;
162
163    cortex-a53)
164	;;
165
166    # The 'none' machine supports all non-M
167    # processors
168    ti925t|arm946|cortex-a*|cortex-r*)
169	machine=none
170	memory="-m 1G"
171	;;
172
173esac
174
175#
176# Make sure the target machine is supported by qemu
177#
178if $qemu -machine help | grep -q "^$machine "; then
179    :
180else
181    echo "Skipping $elf" unsupported machine
182    exit 77
183fi
184
185# Map stdio to a multiplexed character device so we can use it
186# for the monitor and semihosting output
187
188chardev=stdio,mux=on,id=stdio0
189
190# Point the semihosting driver at our new chardev
191
192semi=enable=on,chardev=stdio0
193
194input=""
195
196case "$1" in
197    --)
198	semi="$semi",arg="$2"
199	shift
200	shift
201	;;
202    -*|"")
203	;;
204    *)
205	semi="$semi",arg="$1"
206	input="$1"
207	shift
208	;;
209esac
210
211# Disable monitor
212
213mon=none
214
215# Disable serial
216
217serial=none
218
219# shellcheck disable=SC2086
220echo "$input" | "$qemu" $memory \
221      -chardev "$chardev" \
222      -semihosting-config "$semi" \
223      -monitor "$mon" \
224      -serial "$serial" \
225      -machine "$machine",accel=tcg \
226      -cpu "$cpu" \
227      -device loader,file="$elf",cpu-num=0 \
228      -nographic \
229      "$@"
230
231result=$?
232
233if [ $result != 0 ]; then
234    case $cpu in
235	# Cortex-a8 qemu has minor floating point errors
236	# when run on i686 processors
237	cortex-a8)
238	    test="$(uname -m)-$elf"
239	    case "$test" in
240		i?86-*math_test)
241		    echo "fp imprecise for $cpu on" "$(uname -m)"
242		    result=77
243		    ;;
244	    esac
245	    ;;
246    esac
247fi
248exit $result
249