Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Semihost extended exit and More floating point support (VABS, VCMP, VMRS) #51

Merged
merged 2 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fn run_bin(
trace: bool,
option_trace_start: Option<u64>,
itm_file: Option<Box<dyn io::Write + 'static>>,
) -> Result<()> {
) -> Result<u32> {
let res = Object::parse(buffer).unwrap();

let elf = match res {
Expand Down Expand Up @@ -196,7 +196,7 @@ fn run_bin(
cycles_per_sec,
cycles_per_sec / 1_000_000.0,
);
Ok(())
Ok(statistics.exit_code)
}

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

fn run(args: &ArgMatches) -> Result<()> {
match args.subcommand() {
fn run(args: &ArgMatches) -> Result<u32> {
let exit_code = match args.subcommand() {
Some(("run", run_matches)) => {
let filename = run_matches
.get_one::<String>("EXECUTABLE")
Expand All @@ -234,13 +234,13 @@ fn run(args: &ArgMatches) -> Result<()> {
run_matches.get_flag("trace"),
trace_start,
itm_output,
)?;
)?
}
Some((_, _)) => unreachable!(),
None => unreachable!(), // If all subcommands are defined above, anything else is unreachabe!()
}
};

Ok(())
Ok(exit_code)
}

fn main() {
Expand Down Expand Up @@ -301,17 +301,23 @@ fn main() {
.init()
.unwrap();

if let Err(ref e) = run(&cmd) {
error!("error: {}", e);

for e in e.iter().skip(1) {
error!("caused by: {}", e);
let result = run(&cmd);
match result {
Ok(exit_code) => {
std::process::exit(exit_code as i32);
}
Err(ref e) => {
error!("error: {}", e);

if let Some(backtrace) = e.backtrace() {
error!("backtrace: {:?}", backtrace);
}
for e in e.iter().skip(1) {
error!("caused by: {}", e);
}

if let Some(backtrace) = e.backtrace() {
error!("backtrace: {:?}", backtrace);
}

::std::process::exit(1);
::std::process::exit(1);
}
}
}
16 changes: 14 additions & 2 deletions src/semihost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,24 @@ pub fn get_semihost_func(start: Instant) -> impl FnMut(&SemihostingCommand) -> S
stop,
}
}
SemihostingCommand::SysExitExtended { ref reason, .. } => {
SemihostingCommand::SysExitExtended { ref reason, subcode } => {
// println!("sys exit {:?}", reason);

let stop = matches!(
reason,
SysExceptionReason::ADPStoppedApplicationExit | SysExceptionReason::ADPStoppedRunTimeErrorUnknown
);

let exit_code = if reason == &SysExceptionReason::ADPStoppedApplicationExit {
Some(*subcode)
} else {
None
};

SemihostingResponse::SysExitExtended {
success: true,
stop: reason == &SysExceptionReason::ADPStoppedApplicationExit,
stop,
exit_code
}
}
SemihostingCommand::SysErrno { .. } => {
Expand Down
9 changes: 7 additions & 2 deletions test_gcc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ function arch_supports_cores()
}

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

for i in "${gcc_tests[@]}"
do
cd tests/$i
make -s clean
make -s
make
cd ../..
for a in "${archs[@]}"
do
Expand All @@ -42,7 +42,12 @@ do
for c in "${cores[@]}"
do
echo "./target/release/zmu-$a run tests/$i/$i-$c.elf"
# read return code and abort on failure:
./target/release/zmu-$a run tests/$i/$i-$c.elf
if [[ $? -ne 0 ]]; then
echo "Test failed"
exit $?
fi
echo ""
done
done
Expand Down
103 changes: 89 additions & 14 deletions tests/instruction-test-bench/main.c
Original file line number Diff line number Diff line change
@@ -1,38 +1,107 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

/*
This test bench is used to test various ARM Cortex-M instructions.
If you want to test exact instruction, use inline assembly.
If you want to test a general concept, use C code. The latter
has downside of unpredictable compiler code generation.
*/

/*

Potentially useful defines lookup:

arm-none-eabi-gcc ... -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-sp-d16

#define __VFP_FP__ 1
#define __ARM_PCS_VFP 1
#define __ARM_ARCH_PROFILE 77
#define __ARM_ARCH_7EM__ 1
#define __ARM_FEATURE_DSP 1


*/

#if defined(__ARM_PCS_VFP) && defined(__VFP_FP__)
// Hard floating-point is enabled, and VFP instructions are available
#define HARD_FLOATING_POINT_ENABLED 1
#else
// Hard floating-point is not enabled or VFP support is absent
#define HARD_FLOATING_POINT_ENABLED 0
#endif


#if __ARM_ARCH >= 7
unsigned int bfc_0_32(int value)
{
asm volatile (
asm volatile(
"bfc %[value], 0, 32"
: [value] "+r" (value));
: [value] "+r"(value));
return value;
}
unsigned int bfc_0_16(int value)
{
asm volatile (
asm volatile(
"bfc %[value], 0, 16"
: [value] "+r" (value));
: [value] "+r"(value));
return value;
}
unsigned int bfc_15_16(int value)
{
asm volatile (
asm volatile(
"bfc %[value], 15, 16"
: [value] "+r" (value));
: [value] "+r"(value));
return value;
}
#endif
// [lsb] "I" (lsb), [width] "I" (width)
int main(void)

void bfc(void)
{

#if __ARM_ARCH >= 7
assert(bfc_0_32(0xffffffff) == 0xffffffff);
printf("bfc(0xffffffff, 0, 32) = 0x%08x\n", bfc_0_32(0xffffffff));
printf("bfc(0xffffffff, 0, 16) = 0x%08x\n", bfc_0_16(0xffffffff));
printf("bfc(0xffffffff, 15, 16) = 0x%08x\n", bfc_15_16(0xffffffff));
#endif
}

#endif

#if HARD_FLOATING_POINT_ENABLED
float vabs(float value)
{
float result;

asm volatile(
"VABS.F32 %0, %1"
: "=t"(result)
: "t"(value));

return result;
}

void floating_point(void)
{
// Try to generate floating-point data-processing instructions
// VABS, VADD, VCMP, VCVT, VDIV, VFMA, VFNMA, VMAXNM
// VMLA, VMOV, VMOV, VMUL, VNEG, VNMLA, VRINTA, VRINTZ
// VSEL, VSQRT, VSUB

assert(vabs(-1.0f) == 1.0f);
assert(vabs(-42.0f) == 42.0f);
assert(vabs(0.0f) == 0.0f);
assert(vabs(1.0f) == 1.0f);
}
#endif
int main(void)
{

#if __ARM_ARCH >= 7
bfc();
#endif

#if HARD_FLOATING_POINT_ENABLED
floating_point();
#endif
}

void SystemInit(void)
Expand All @@ -48,5 +117,11 @@ void _start(void)
exit(0);
}

__attribute__((used))
void _fini(void) { }
__attribute__((used)) void _fini(void) {}


void __assert_func( const char *filename, int line, const char *assert_func, const char *expr )
{
printf("assert_failed: %s:%d\n", filename, line);
exit(1);
}
5 changes: 4 additions & 1 deletion zmu.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
"settings": {
"rust-analyzer.cargo.features": [
"armv7em generic-device"
]
],
"files.associations": {
"assert.h": "c"
}
}
}
7 changes: 4 additions & 3 deletions zmu_cortex_m/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,17 +273,18 @@ fn main() -> Result<(), Box<dyn Error>> {
("1110100..1.11111................", "LDRD_lit_t1"),
("1110100..1.1....................", "LDRD_imm_t1"),
("1110100..1.0....................", "STRD_imm_t1"),
//("111011101.110000....101.11.0....": "VABS_t1"),
("111011101.110000....101.11.0....", "VABS_t1"),
//("111011100.11........101..0.0....": "VADD_t1"),
//("111011101.110100....101..1.0....": "VCMP_t1"),
//("111011101.110101....101..1.0....": "VCMP_t2"),
("111011101.110100....101..1.0....", "VCMP_t1"),
("111011101.110101....101..1.0....", "VCMP_t2"),
//("111111101.1111......101..1.0....": "VCVT_t1"),
//("111011101.111.1.....101..1.0....": "VCVT_fx_t1"),
//("111011101.110111....101.11.0....": "VCVT_ds_t1"),
//("111011101.11001.....101..1.0....": "VCVTB"),
//("111011101.00........101..0.0....": "VDIV"),
//("111011101.10........101....0....": "VFMAS"),
//("111011101.01........101....0....": "VFNMAS"),
("1110111011110001....101000010000", "VMRS"),
("1110110....0........1011.......0", "VSTM_t1"),
("1110110....0........1010........", "VSTM_t2"),
("11101101..01........1011........", "VLDR_t1"),
Expand Down
4 changes: 2 additions & 2 deletions zmu_cortex_m/src/core/exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ impl ExceptionHandling for Processor {
&& nested_activation == 1 // deactivate() reduced one
&& self.scr.get_bit(1)
{
self.state.set_bit(1, true); // sleeping = true
self.sleeping = true;
}

Ok(())
Expand All @@ -516,7 +516,7 @@ impl ExceptionHandling for Processor {
#[inline(always)]
fn check_exceptions(&mut self) {
if let Some(exception) = self.get_pending_exception() {
self.state.set_bit(1, false); // sleeping == false
self.sleeping = false;
self.clear_pending_exception(exception);
let pc = self.get_pc();
// TODO: handle failure to enter exception
Expand Down
Loading
Loading