Skip to content

Commit 5986099

Browse files
authored
Merge pull request #51 from jjkt/semihost-extended-exit-vabs
Semihost extended exit and More floating point support (VABS, VCMP, VMRS)
2 parents 0dd14a8 + 1d87c1e commit 5986099

File tree

26 files changed

+1326
-130
lines changed

26 files changed

+1326
-130
lines changed

src/main.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ fn run_bin(
5959
trace: bool,
6060
option_trace_start: Option<u64>,
6161
itm_file: Option<Box<dyn io::Write + 'static>>,
62-
) -> Result<()> {
62+
) -> Result<u32> {
6363
let res = Object::parse(buffer).unwrap();
6464

6565
let elf = match res {
@@ -196,7 +196,7 @@ fn run_bin(
196196
cycles_per_sec,
197197
cycles_per_sec / 1_000_000.0,
198198
);
199-
Ok(())
199+
Ok(statistics.exit_code)
200200
}
201201

202202
fn open_itm_file(filename: &str) -> Option<Box<dyn io::Write + 'static>> {
@@ -208,8 +208,8 @@ fn open_itm_file(filename: &str) -> Option<Box<dyn io::Write + 'static>> {
208208
}
209209
}
210210

211-
fn run(args: &ArgMatches) -> Result<()> {
212-
match args.subcommand() {
211+
fn run(args: &ArgMatches) -> Result<u32> {
212+
let exit_code = match args.subcommand() {
213213
Some(("run", run_matches)) => {
214214
let filename = run_matches
215215
.get_one::<String>("EXECUTABLE")
@@ -234,13 +234,13 @@ fn run(args: &ArgMatches) -> Result<()> {
234234
run_matches.get_flag("trace"),
235235
trace_start,
236236
itm_output,
237-
)?;
237+
)?
238238
}
239239
Some((_, _)) => unreachable!(),
240240
None => unreachable!(), // If all subcommands are defined above, anything else is unreachabe!()
241-
}
241+
};
242242

243-
Ok(())
243+
Ok(exit_code)
244244
}
245245

246246
fn main() {
@@ -301,17 +301,23 @@ fn main() {
301301
.init()
302302
.unwrap();
303303

304-
if let Err(ref e) = run(&cmd) {
305-
error!("error: {}", e);
306-
307-
for e in e.iter().skip(1) {
308-
error!("caused by: {}", e);
304+
let result = run(&cmd);
305+
match result {
306+
Ok(exit_code) => {
307+
std::process::exit(exit_code as i32);
309308
}
309+
Err(ref e) => {
310+
error!("error: {}", e);
310311

311-
if let Some(backtrace) = e.backtrace() {
312-
error!("backtrace: {:?}", backtrace);
313-
}
312+
for e in e.iter().skip(1) {
313+
error!("caused by: {}", e);
314+
}
315+
316+
if let Some(backtrace) = e.backtrace() {
317+
error!("backtrace: {:?}", backtrace);
318+
}
314319

315-
::std::process::exit(1);
320+
::std::process::exit(1);
321+
}
316322
}
317323
}

src/semihost.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,24 @@ pub fn get_semihost_func(start: Instant) -> impl FnMut(&SemihostingCommand) -> S
168168
stop,
169169
}
170170
}
171-
SemihostingCommand::SysExitExtended { ref reason, .. } => {
171+
SemihostingCommand::SysExitExtended { ref reason, subcode } => {
172172
// println!("sys exit {:?}", reason);
173173

174+
let stop = matches!(
175+
reason,
176+
SysExceptionReason::ADPStoppedApplicationExit | SysExceptionReason::ADPStoppedRunTimeErrorUnknown
177+
);
178+
179+
let exit_code = if reason == &SysExceptionReason::ADPStoppedApplicationExit {
180+
Some(*subcode)
181+
} else {
182+
None
183+
};
184+
174185
SemihostingResponse::SysExitExtended {
175186
success: true,
176-
stop: reason == &SysExceptionReason::ADPStoppedApplicationExit,
187+
stop,
188+
exit_code
177189
}
178190
}
179191
SemihostingCommand::SysErrno { .. } => {

test_gcc.sh

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ function arch_supports_cores()
2525
}
2626

2727
declare -a archs=("armv6m" "armv7m" "armv7em")
28-
declare -a gcc_tests=("hello_world" "pi" "instruction-test-bench")
28+
declare -a gcc_tests=("hello_world" "instruction-test-bench" "pi")
2929

3030
for i in "${gcc_tests[@]}"
3131
do
3232
cd tests/$i
3333
make -s clean
34-
make -s
34+
make
3535
cd ../..
3636
for a in "${archs[@]}"
3737
do
@@ -42,7 +42,12 @@ do
4242
for c in "${cores[@]}"
4343
do
4444
echo "./target/release/zmu-$a run tests/$i/$i-$c.elf"
45+
# read return code and abort on failure:
4546
./target/release/zmu-$a run tests/$i/$i-$c.elf
47+
if [[ $? -ne 0 ]]; then
48+
echo "Test failed"
49+
exit $?
50+
fi
4651
echo ""
4752
done
4853
done
Lines changed: 89 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,107 @@
11
#include <stdio.h>
22
#include <stdlib.h>
3+
#include <assert.h>
4+
5+
/*
6+
This test bench is used to test various ARM Cortex-M instructions.
7+
If you want to test exact instruction, use inline assembly.
8+
If you want to test a general concept, use C code. The latter
9+
has downside of unpredictable compiler code generation.
10+
*/
11+
12+
/*
13+
14+
Potentially useful defines lookup:
15+
16+
arm-none-eabi-gcc ... -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-sp-d16
17+
18+
#define __VFP_FP__ 1
19+
#define __ARM_PCS_VFP 1
20+
#define __ARM_ARCH_PROFILE 77
21+
#define __ARM_ARCH_7EM__ 1
22+
#define __ARM_FEATURE_DSP 1
23+
24+
25+
*/
26+
27+
#if defined(__ARM_PCS_VFP) && defined(__VFP_FP__)
28+
// Hard floating-point is enabled, and VFP instructions are available
29+
#define HARD_FLOATING_POINT_ENABLED 1
30+
#else
31+
// Hard floating-point is not enabled or VFP support is absent
32+
#define HARD_FLOATING_POINT_ENABLED 0
33+
#endif
34+
335

436
#if __ARM_ARCH >= 7
537
unsigned int bfc_0_32(int value)
638
{
7-
asm volatile (
39+
asm volatile(
840
"bfc %[value], 0, 32"
9-
: [value] "+r" (value));
41+
: [value] "+r"(value));
1042
return value;
1143
}
1244
unsigned int bfc_0_16(int value)
1345
{
14-
asm volatile (
46+
asm volatile(
1547
"bfc %[value], 0, 16"
16-
: [value] "+r" (value));
48+
: [value] "+r"(value));
1749
return value;
1850
}
1951
unsigned int bfc_15_16(int value)
2052
{
21-
asm volatile (
53+
asm volatile(
2254
"bfc %[value], 15, 16"
23-
: [value] "+r" (value));
55+
: [value] "+r"(value));
2456
return value;
2557
}
26-
#endif
27-
// [lsb] "I" (lsb), [width] "I" (width)
28-
int main(void)
58+
59+
void bfc(void)
2960
{
30-
31-
#if __ARM_ARCH >= 7
61+
assert(bfc_0_32(0xffffffff) == 0xffffffff);
3262
printf("bfc(0xffffffff, 0, 32) = 0x%08x\n", bfc_0_32(0xffffffff));
3363
printf("bfc(0xffffffff, 0, 16) = 0x%08x\n", bfc_0_16(0xffffffff));
3464
printf("bfc(0xffffffff, 15, 16) = 0x%08x\n", bfc_15_16(0xffffffff));
35-
#endif
65+
}
66+
67+
#endif
68+
69+
#if HARD_FLOATING_POINT_ENABLED
70+
float vabs(float value)
71+
{
72+
float result;
73+
74+
asm volatile(
75+
"VABS.F32 %0, %1"
76+
: "=t"(result)
77+
: "t"(value));
78+
79+
return result;
80+
}
81+
82+
void floating_point(void)
83+
{
84+
// Try to generate floating-point data-processing instructions
85+
// VABS, VADD, VCMP, VCVT, VDIV, VFMA, VFNMA, VMAXNM
86+
// VMLA, VMOV, VMOV, VMUL, VNEG, VNMLA, VRINTA, VRINTZ
87+
// VSEL, VSQRT, VSUB
88+
89+
assert(vabs(-1.0f) == 1.0f);
90+
assert(vabs(-42.0f) == 42.0f);
91+
assert(vabs(0.0f) == 0.0f);
92+
assert(vabs(1.0f) == 1.0f);
93+
}
94+
#endif
95+
int main(void)
96+
{
97+
98+
#if __ARM_ARCH >= 7
99+
bfc();
100+
#endif
101+
102+
#if HARD_FLOATING_POINT_ENABLED
103+
floating_point();
104+
#endif
36105
}
37106

38107
void SystemInit(void)
@@ -48,5 +117,11 @@ void _start(void)
48117
exit(0);
49118
}
50119

51-
__attribute__((used))
52-
void _fini(void) { }
120+
__attribute__((used)) void _fini(void) {}
121+
122+
123+
void __assert_func( const char *filename, int line, const char *assert_func, const char *expr )
124+
{
125+
printf("assert_failed: %s:%d\n", filename, line);
126+
exit(1);
127+
}

zmu.code-workspace

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
"settings": {
1111
"rust-analyzer.cargo.features": [
1212
"armv7em generic-device"
13-
]
13+
],
14+
"files.associations": {
15+
"assert.h": "c"
16+
}
1417
}
1518
}

zmu_cortex_m/build.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,17 +273,18 @@ fn main() -> Result<(), Box<dyn Error>> {
273273
("1110100..1.11111................", "LDRD_lit_t1"),
274274
("1110100..1.1....................", "LDRD_imm_t1"),
275275
("1110100..1.0....................", "STRD_imm_t1"),
276-
//("111011101.110000....101.11.0....": "VABS_t1"),
276+
("111011101.110000....101.11.0....", "VABS_t1"),
277277
//("111011100.11........101..0.0....": "VADD_t1"),
278-
//("111011101.110100....101..1.0....": "VCMP_t1"),
279-
//("111011101.110101....101..1.0....": "VCMP_t2"),
278+
("111011101.110100....101..1.0....", "VCMP_t1"),
279+
("111011101.110101....101..1.0....", "VCMP_t2"),
280280
//("111111101.1111......101..1.0....": "VCVT_t1"),
281281
//("111011101.111.1.....101..1.0....": "VCVT_fx_t1"),
282282
//("111011101.110111....101.11.0....": "VCVT_ds_t1"),
283283
//("111011101.11001.....101..1.0....": "VCVTB"),
284284
//("111011101.00........101..0.0....": "VDIV"),
285285
//("111011101.10........101....0....": "VFMAS"),
286286
//("111011101.01........101....0....": "VFNMAS"),
287+
("1110111011110001....101000010000", "VMRS"),
287288
("1110110....0........1011.......0", "VSTM_t1"),
288289
("1110110....0........1010........", "VSTM_t2"),
289290
("11101101..01........1011........", "VLDR_t1"),

zmu_cortex_m/src/core/exception.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ impl ExceptionHandling for Processor {
504504
&& nested_activation == 1 // deactivate() reduced one
505505
&& self.scr.get_bit(1)
506506
{
507-
self.state.set_bit(1, true); // sleeping = true
507+
self.sleeping = true;
508508
}
509509

510510
Ok(())
@@ -516,7 +516,7 @@ impl ExceptionHandling for Processor {
516516
#[inline(always)]
517517
fn check_exceptions(&mut self) {
518518
if let Some(exception) = self.get_pending_exception() {
519-
self.state.set_bit(1, false); // sleeping == false
519+
self.sleeping = false;
520520
self.clear_pending_exception(exception);
521521
let pc = self.get_pc();
522522
// TODO: handle failure to enter exception

0 commit comments

Comments
 (0)