fortrangoingonforty/afs-as / 521e09a

Browse files

Fix standalone operand aliases

Authored by espadonne
SHA
521e09a573914f31629f56b0618cb1f5eae954d7
Parents
cc2cd50
Tree
8fa4f0e

3 changed files

StatusFile+-
M src/encode.rs 30 0
M src/parse.rs 89 55
M tests/verify_against_system_as.rs 37 0
src/encode.rsmodified
@@ -662,6 +662,26 @@ pub enum Inst {
662662
     StrFpImm8 { rt: FpReg, rn: GpReg, offset: u16 },
663663
     /// STR Qt, [Xn, #offset]
664664
     StrFpImm128 { rt: FpReg, rn: GpReg, offset: u16 },
665
+    /// LDUR Dt, [Xn, #offset]
666
+    LdurFp64 { rt: FpReg, rn: GpReg, offset: i16 },
667
+    /// LDUR St, [Xn, #offset]
668
+    LdurFp32 { rt: FpReg, rn: GpReg, offset: i16 },
669
+    /// LDUR Ht, [Xn, #offset]
670
+    LdurFp16 { rt: FpReg, rn: GpReg, offset: i16 },
671
+    /// LDUR Bt, [Xn, #offset]
672
+    LdurFp8 { rt: FpReg, rn: GpReg, offset: i16 },
673
+    /// LDUR Qt, [Xn, #offset]
674
+    LdurFp128 { rt: FpReg, rn: GpReg, offset: i16 },
675
+    /// STUR Dt, [Xn, #offset]
676
+    SturFp64 { rt: FpReg, rn: GpReg, offset: i16 },
677
+    /// STUR St, [Xn, #offset]
678
+    SturFp32 { rt: FpReg, rn: GpReg, offset: i16 },
679
+    /// STUR Ht, [Xn, #offset]
680
+    SturFp16 { rt: FpReg, rn: GpReg, offset: i16 },
681
+    /// STUR Bt, [Xn, #offset]
682
+    SturFp8 { rt: FpReg, rn: GpReg, offset: i16 },
683
+    /// STUR Qt, [Xn, #offset]
684
+    SturFp128 { rt: FpReg, rn: GpReg, offset: i16 },
665685
     /// LDR Dt, [Xn, Rm{, extend}]
666686
     LdrFpReg64 {
667687
         rt: FpReg,
@@ -2148,6 +2168,16 @@ impl Inst {
21482168
             Inst::StrFpImm16 { rt, rn, offset } => ldst_uimm_fp(0b01, 0b00, 1, *offset, *rn, *rt),
21492169
             Inst::StrFpImm8 { rt, rn, offset } => ldst_uimm_fp(0b00, 0b00, 0, *offset, *rn, *rt),
21502170
             Inst::StrFpImm128 { rt, rn, offset } => ldst_uimm_fp(0b00, 0b10, 4, *offset, *rn, *rt),
2171
+            Inst::LdurFp64 { rt, rn, offset } => ldst_idx_fp(0b11, 0b01, *offset, 0b00, *rn, *rt),
2172
+            Inst::LdurFp32 { rt, rn, offset } => ldst_idx_fp(0b10, 0b01, *offset, 0b00, *rn, *rt),
2173
+            Inst::LdurFp16 { rt, rn, offset } => ldst_idx_fp(0b01, 0b01, *offset, 0b00, *rn, *rt),
2174
+            Inst::LdurFp8 { rt, rn, offset } => ldst_idx_fp(0b00, 0b01, *offset, 0b00, *rn, *rt),
2175
+            Inst::LdurFp128 { rt, rn, offset } => ldst_idx_fp(0b00, 0b11, *offset, 0b00, *rn, *rt),
2176
+            Inst::SturFp64 { rt, rn, offset } => ldst_idx_fp(0b11, 0b00, *offset, 0b00, *rn, *rt),
2177
+            Inst::SturFp32 { rt, rn, offset } => ldst_idx_fp(0b10, 0b00, *offset, 0b00, *rn, *rt),
2178
+            Inst::SturFp16 { rt, rn, offset } => ldst_idx_fp(0b01, 0b00, *offset, 0b00, *rn, *rt),
2179
+            Inst::SturFp8 { rt, rn, offset } => ldst_idx_fp(0b00, 0b00, *offset, 0b00, *rn, *rt),
2180
+            Inst::SturFp128 { rt, rn, offset } => ldst_idx_fp(0b00, 0b10, *offset, 0b00, *rn, *rt),
21512181
             Inst::LdrFpReg64 {
21522182
                 rt,
21532183
                 rn,
src/parse.rsmodified
@@ -2455,7 +2455,7 @@ impl<'a> Parser<'a> {
24552455
         if self.peek_is_scalar_fp_reg() {
24562456
             return self.parse_simd_lane_extract();
24572457
         }
2458
-        let (rd, sf) = self.parse_gp_reg_with_size()?;
2458
+        let (rd, sf, rd_kind) = self.parse_gp_reg_with_size_kind()?;
24592459
         self.expect(&Tok::Comma)?;
24602460
         if self.starts_immediate_expr() {
24612461
             let imm = self.parse_immediate_const_expr("mov immediate")?;
@@ -2468,8 +2468,8 @@ impl<'a> Parser<'a> {
24682468
                 )))
24692469
             }
24702470
         } else {
2471
-            let (rm, _) = self.parse_gp_reg_with_size()?;
2472
-            if rm == SP || rd == SP {
2471
+            let (rm, _, rm_kind) = self.parse_gp_reg_with_size_kind()?;
2472
+            if rm_kind == GpRegKind::Sp || rd_kind == GpRegKind::Sp {
24732473
                 // MOV involving SP → ADD Xd, Xn, #0 (SP can't be used in ORR shifted reg)
24742474
                 Ok(Inst::AddImm {
24752475
                     rd,
@@ -2944,6 +2944,54 @@ impl<'a> Parser<'a> {
29442944
         }
29452945
     }
29462946
 
2947
+    fn fp_mem_offset_inst(
2948
+        &self,
2949
+        is_load: bool,
2950
+        width: FpMemWidth,
2951
+        rt: FpReg,
2952
+        rn: GpReg,
2953
+        offset: i64,
2954
+    ) -> Result<Inst, ParseError> {
2955
+        let scale = 1i64 << width.scale();
2956
+        let fits_unsigned = offset >= 0 && offset % scale == 0 && (offset >> width.scale()) <= 0xFFF;
2957
+        if fits_unsigned {
2958
+            let offset = offset as u16;
2959
+            return Ok(match (is_load, width) {
2960
+                (true, FpMemWidth::H16) => Inst::LdrFpImm16 { rt, rn, offset },
2961
+                (false, FpMemWidth::H16) => Inst::StrFpImm16 { rt, rn, offset },
2962
+                (true, FpMemWidth::B8) => Inst::LdrFpImm8 { rt, rn, offset },
2963
+                (false, FpMemWidth::B8) => Inst::StrFpImm8 { rt, rn, offset },
2964
+                (true, FpMemWidth::D64) => Inst::LdrFpImm64 { rt, rn, offset },
2965
+                (false, FpMemWidth::D64) => Inst::StrFpImm64 { rt, rn, offset },
2966
+                (true, FpMemWidth::S32) => Inst::LdrFpImm32 { rt, rn, offset },
2967
+                (false, FpMemWidth::S32) => Inst::StrFpImm32 { rt, rn, offset },
2968
+                (true, FpMemWidth::Q128) => Inst::LdrFpImm128 { rt, rn, offset },
2969
+                (false, FpMemWidth::Q128) => Inst::StrFpImm128 { rt, rn, offset },
2970
+            });
2971
+        }
2972
+
2973
+        if (-256..=255).contains(&offset) {
2974
+            let offset = offset as i16;
2975
+            return Ok(match (is_load, width) {
2976
+                (true, FpMemWidth::H16) => Inst::LdurFp16 { rt, rn, offset },
2977
+                (false, FpMemWidth::H16) => Inst::SturFp16 { rt, rn, offset },
2978
+                (true, FpMemWidth::B8) => Inst::LdurFp8 { rt, rn, offset },
2979
+                (false, FpMemWidth::B8) => Inst::SturFp8 { rt, rn, offset },
2980
+                (true, FpMemWidth::D64) => Inst::LdurFp64 { rt, rn, offset },
2981
+                (false, FpMemWidth::D64) => Inst::SturFp64 { rt, rn, offset },
2982
+                (true, FpMemWidth::S32) => Inst::LdurFp32 { rt, rn, offset },
2983
+                (false, FpMemWidth::S32) => Inst::SturFp32 { rt, rn, offset },
2984
+                (true, FpMemWidth::Q128) => Inst::LdurFp128 { rt, rn, offset },
2985
+                (false, FpMemWidth::Q128) => Inst::SturFp128 { rt, rn, offset },
2986
+            });
2987
+        }
2988
+
2989
+        Err(self.err(format!(
2990
+            "FP/SIMD memory offset {offset} is out of range for {}",
2991
+            if is_load { "LDR" } else { "STR" }
2992
+        )))
2993
+    }
2994
+
29472995
     fn parse_ldur_stur(&mut self, is_load: bool) -> Result<Stmt, ParseError> {
29482996
         let (rt, sf) = self.parse_gp_reg_with_size()?;
29492997
         self.expect(&Tok::Comma)?;
@@ -3328,58 +3376,7 @@ impl<'a> Parser<'a> {
33283376
             return Ok(Stmt::Instruction(inst));
33293377
         }
33303378
 
3331
-        let inst = match (is_load, width) {
3332
-            (true, FpMemWidth::H16) => Inst::LdrFpImm16 {
3333
-                rt,
3334
-                rn,
3335
-                offset: offset as u16,
3336
-            },
3337
-            (false, FpMemWidth::H16) => Inst::StrFpImm16 {
3338
-                rt,
3339
-                rn,
3340
-                offset: offset as u16,
3341
-            },
3342
-            (true, FpMemWidth::B8) => Inst::LdrFpImm8 {
3343
-                rt,
3344
-                rn,
3345
-                offset: offset as u16,
3346
-            },
3347
-            (false, FpMemWidth::B8) => Inst::StrFpImm8 {
3348
-                rt,
3349
-                rn,
3350
-                offset: offset as u16,
3351
-            },
3352
-            (true, FpMemWidth::D64) => Inst::LdrFpImm64 {
3353
-                rt,
3354
-                rn,
3355
-                offset: offset as u16,
3356
-            },
3357
-            (false, FpMemWidth::D64) => Inst::StrFpImm64 {
3358
-                rt,
3359
-                rn,
3360
-                offset: offset as u16,
3361
-            },
3362
-            (true, FpMemWidth::S32) => Inst::LdrFpImm32 {
3363
-                rt,
3364
-                rn,
3365
-                offset: offset as u16,
3366
-            },
3367
-            (false, FpMemWidth::S32) => Inst::StrFpImm32 {
3368
-                rt,
3369
-                rn,
3370
-                offset: offset as u16,
3371
-            },
3372
-            (true, FpMemWidth::Q128) => Inst::LdrFpImm128 {
3373
-                rt,
3374
-                rn,
3375
-                offset: offset as u16,
3376
-            },
3377
-            (false, FpMemWidth::Q128) => Inst::StrFpImm128 {
3378
-                rt,
3379
-                rn,
3380
-                offset: offset as u16,
3381
-            },
3382
-        };
3379
+        let inst = self.fp_mem_offset_inst(is_load, width, rt, rn, offset)?;
33833380
         Ok(Stmt::Instruction(inst))
33843381
     }
33853382
 
@@ -5758,6 +5755,19 @@ mod tests {
57585755
         );
57595756
     }
57605757
 
5758
+    #[test]
5759
+    fn parse_mov_wzr_keeps_zero_register() {
5760
+        assert_eq!(
5761
+            parse_inst("mov w26, wzr"),
5762
+            Inst::OrrReg {
5763
+                rd: W26,
5764
+                rn: WZR,
5765
+                rm: WZR,
5766
+                sf: false
5767
+            }
5768
+        );
5769
+    }
5770
+
57615771
     #[test]
57625772
     fn parse_ubfiz_() {
57635773
         assert_eq!(
@@ -6583,6 +6593,30 @@ mod tests {
65836593
         );
65846594
     }
65856595
 
6596
+    #[test]
6597
+    fn parse_str_s_negative_offset_uses_unscaled() {
6598
+        assert_eq!(
6599
+            parse_inst("str s8, [x29, #-4]"),
6600
+            Inst::SturFp32 {
6601
+                rt: S8,
6602
+                rn: X29,
6603
+                offset: -4
6604
+            }
6605
+        );
6606
+    }
6607
+
6608
+    #[test]
6609
+    fn parse_ldr_s_negative_offset_uses_unscaled() {
6610
+        assert_eq!(
6611
+            parse_inst("ldr s9, [x29, #-4]"),
6612
+            Inst::LdurFp32 {
6613
+                rt: S9,
6614
+                rn: X29,
6615
+                offset: -4
6616
+            }
6617
+        );
6618
+    }
6619
+
65866620
     #[test]
65876621
     fn parse_ldr_s_register_offset() {
65886622
         assert_eq!(
tests/verify_against_system_as.rsmodified
@@ -431,6 +431,19 @@ fn sys_movn_hi() {
431431
     );
432432
 }
433433
 
434
+#[test]
435
+fn sys_mov_wzr() {
436
+    verify(
437
+        "mov w26, wzr",
438
+        Inst::OrrReg {
439
+            rd: W26,
440
+            rn: WZR,
441
+            rm: WZR,
442
+            sf: false,
443
+        },
444
+    );
445
+}
446
+
434447
 // ---- Shifts ----
435448
 
436449
 #[test]
@@ -1683,6 +1696,30 @@ fn sys_str_s_pre() {
16831696
     );
16841697
 }
16851698
 
1699
+#[test]
1700
+fn sys_str_s_neg_offset() {
1701
+    verify(
1702
+        "str s8, [x29, #-4]",
1703
+        Inst::SturFp32 {
1704
+            rt: S8,
1705
+            rn: X29,
1706
+            offset: -4,
1707
+        },
1708
+    );
1709
+}
1710
+
1711
+#[test]
1712
+fn sys_ldr_s_neg_offset() {
1713
+    verify(
1714
+        "ldr s9, [x29, #-4]",
1715
+        Inst::LdurFp32 {
1716
+            rt: S9,
1717
+            rn: X29,
1718
+            offset: -4,
1719
+        },
1720
+    );
1721
+}
1722
+
16861723
 // ---- Address generation ----
16871724
 
16881725
 #[test]