[PATCH RISU 3/4] risugen/arm: Switch to thumb mode only once

Richard Henderson posted 4 patches 6 months ago
[PATCH RISU 3/4] risugen/arm: Switch to thumb mode only once
Posted by Richard Henderson 6 months ago
With thumb2 we can avoid jumping back and forth
between arm and thumb modes.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 risugen_arm.pm | 85 +++++++++++++-------------------------------------
 1 file changed, 21 insertions(+), 64 deletions(-)

diff --git a/risugen_arm.pm b/risugen_arm.pm
index c7ca62b..582bade 100644
--- a/risugen_arm.pm
+++ b/risugen_arm.pm
@@ -26,19 +26,8 @@ require Exporter;
 our @ISA    = qw(Exporter);
 our @EXPORT = qw(write_test_code);
 
-# Note that we always start in ARM mode even if the C code was compiled for
-# thumb because we are called by branch to a lsbit-clear pointer.
-# is_thumb tracks the mode we're actually currently in (ie should we emit
-# an arm or thumb insn?); test_thumb tells us which mode we need to switch
-# to to emit the insns under test.
-# Use .mode aarch64 to start in Aarch64 mode.
-
 my $is_aarch64 = 0; # are we in aarch64 mode?
-# For aarch64 it only makes sense to put the mode directive at the
-# beginning, and there is no switching away from aarch64 to arm/thumb.
-
-my $is_thumb = 0;   # are we currently in Thumb mode?
-my $test_thumb = 0; # should test code be Thumb mode?
+my $is_thumb = 0;   # are we in Thumb mode?
 
 # Maximum alignment restriction permitted for a memory op.
 my $MAXALIGN = 64;
@@ -134,46 +123,6 @@ sub write_data32($)
     printf "\t.word\t%#08x\n", $data;
 }
 
-sub write_switch_to_thumb()
-{
-    # Switch to thumb if we're not already there
-    if (!$is_thumb) {
-        # Note that we have to clean up R0 afterwards so it isn't
-        # tainted with a value which depends on PC.
-        printf "\tadd\tr0, pc, #1\n";
-        printf "\tbx\tr0\n";
-        printf ".thumb\n";
-        printf "\teors\tr0, r0\n";
-        $is_thumb = 1;
-    }
-}
-
-sub write_switch_to_arm()
-{
-    # Switch to ARM mode if we are in thumb mode
-    if ($is_thumb) {
-        printf "\t.balign\t4\n";
-        printf "\tbx\tpc\n";
-        printf "\tnop\n";
-        printf ".arm\n";
-        $is_thumb = 0;
-    }
-}
-
-sub write_switch_to_test_mode()
-{
-    # Switch to whichever mode we need for test code
-    if ($is_aarch64) {
-        return; # nothing to do
-    }
-
-    if ($test_thumb) {
-        write_switch_to_thumb();
-    } else {
-        write_switch_to_arm();
-    }
-}
-
 sub write_add_rri($$$)
 {
     my ($rd, $rn, $i) = @_;
@@ -345,7 +294,14 @@ sub write_random_arm_regdata($)
 {
     my ($fp_enabled) = @_;
     my $vfp = $fp_enabled ? 2 : 0; # 0 : no vfp, 1 : vfpd16, 2 : vfpd32
-    write_switch_to_arm();
+
+    # clear the flags (NZCVQ and GE)
+    if ($is_thumb) {
+        printf "\tmovw\tr0, #0\n";
+        printf "\tmsr\tAPSR_nzcvqg, r0\n";
+    } else {
+        printf "\tmsr\tAPSR_nzcvqg, #0\n";
+    }
 
     # initialise all registers
     printf "\tadr\tr0, 0f\n";
@@ -370,9 +326,6 @@ sub write_random_arm_regdata($)
         printf "\tvldmia\tr0!, {d16-d31}\n";
     }
     printf "\tldmia\tr0, {r0-r12,r14}\n";
-
-    # clear the flags (NZCVQ and GE)
-    printf "\tmsr\tAPSR_nzcvqg, #0\n";
 }
 
 sub write_random_aarch64_regdata($$)
@@ -447,7 +400,6 @@ sub write_memblock_setup()
     # Write code which sets up the memory block for loads and stores.
     # We set r0 to point to a block of 8K length
     # of random data, aligned to the maximum desired alignment.
-    write_switch_to_arm();
 
     printf "\tadr\t%s, 2f\n", xr(0);
     if ($is_aarch64) {
@@ -475,7 +427,6 @@ sub write_memblock_setup()
 sub write_set_fpscr_arm($)
 {
     my ($fpscr) = @_;
-    write_switch_to_arm();
     write_mov_ri(0, $fpscr);
     printf "\tvmsr\tfpscr, r0\n";
 }
@@ -824,13 +775,13 @@ sub write_test_code($$$$$$$$)
     my $subarch = $params->{ 'subarch' };
 
     if ($subarch && $subarch eq 'aarch64') {
-        $test_thumb = 0;
+        $is_thumb = 0;
         $is_aarch64 = 1;
     } elsif ($subarch && $subarch eq 'thumb') {
-        $test_thumb = 1;
+        $is_thumb = 1;
         $is_aarch64 = 0;
     } else {
-        $test_thumb = 0;
+        $is_thumb = 0;
         $is_aarch64 = 0;
     }
 
@@ -849,9 +800,17 @@ sub write_test_code($$$$$$$$)
     printf "\t.text\n";
     if (!$is_aarch64) {
 	printf "\t.syntax unified\n";
-        printf "\t.arm\n";
         printf "\t.arch armv7-a\n";
         printf "\t.fpu neon\n" if ($fp_enabled);
+
+        # We always start in ARM mode even if the C code was compiled for
+        # thumb because we are called by branch to a lsbit-clear pointer.
+        printf ".arm\n";
+        if ($is_thumb) {
+            printf "\tadd\tr0, pc, #1\n";
+            printf "\tbx\tr0\n";
+            printf ".thumb\n";
+        }
     }
 
     # convert from probability that insn will be conditional to
@@ -873,7 +832,6 @@ sub write_test_code($$$$$$$$)
     }
     # memblock setup doesn't clean its registers, so this must come afterwards.
     write_random_register_data($fp_enabled, $sve_enabled);
-    write_switch_to_test_mode();
 
     for my $i (1..$numinsns) {
         my $insn_enc = $keys[int rand (@keys)];
@@ -885,7 +843,6 @@ sub write_test_code($$$$$$$$)
         # for the VFP registers to decay to NaNs and zeroes.
         if (($i % 100) == 0) {
             write_random_register_data($fp_enabled, $sve_enabled);
-            write_switch_to_test_mode();
         }
         progress_update($i);
     }
-- 
2.34.1