tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] [PATCH 6/8] arm-asm: Add vldr, vstr.


From: Danny Milosavljevic
Subject: [Tinycc-devel] [PATCH 6/8] arm-asm: Add vldr, vstr.
Date: Thu, 14 Jan 2021 23:22:25 +0100

Also add s0...s31, d0...d15
---
 arm-asm.c                  | 105 ++++++++++++++++++++++++++++++++++++-
 arm-tok.h                  |  59 +++++++++++++++++++++
 tests/arm-asm-testsuite.sh |   8 ++-
 3 files changed, 169 insertions(+), 3 deletions(-)

diff --git a/arm-asm.c b/arm-asm.c
index 3591651..7e59ad7 100644
--- a/arm-asm.c
+++ b/arm-asm.c
@@ -1289,11 +1289,11 @@ static void asm_emit_coprocessor_data_transfer(uint32_t 
high_nibble, uint8_t cp_
     if (writeback)
         opcode |= 1 << 21; // write offset back into register
 
-    if (offset->type == OP_IM8 || offset->type == OP_IM8N) {
+    if (offset->type == OP_IM8 || offset->type == OP_IM8N || offset->type == 
OP_IM32) {
         int v = offset->e.v;
         if (offset_minus)
             tcc_error("minus before '#' not supported for immediate values");
-        if (offset->type == OP_IM8N)
+        if (offset->type == OP_IM8N || v < 0)
             v = -v;
         else
             opcode |= 1 << 23; // up
@@ -1302,6 +1302,10 @@ static void asm_emit_coprocessor_data_transfer(uint32_t 
high_nibble, uint8_t cp_
             return;
         }
         v >>= 2;
+        if (v > 255) {
+            tcc_error("immediate offset must be between -1020 and 1020");
+            return;
+        }
         opcode |= v;
     } else if (offset->type == OP_REG32) {
         if (!offset_minus)
@@ -1439,6 +1443,97 @@ static void 
asm_coprocessor_data_transfer_opcode(TCCState *s1, int token)
     }
 }
 
+#if defined(TCC_ARM_VFP)
+#define CP_SINGLE_PRECISION_FLOAT 10
+#define CP_DOUBLE_PRECISION_FLOAT 11
+
+/* Read the VFP register referred to by T.
+   If OK, returns its number.
+   If not OK, returns -1. */
+static int asm_parse_vfp_regvar(int t, int double_precision)
+{
+    if (double_precision) {
+        if (t >= TOK_ASM_d0 && t <= TOK_ASM_d15)
+            return t - TOK_ASM_d0;
+    } else {
+        if (t >= TOK_ASM_s0 && t <= TOK_ASM_s31)
+            return t - TOK_ASM_s0;
+    }
+    return -1;
+}
+
+
+static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int 
token)
+{
+    Operand ops[3];
+    uint8_t coprocessor = 0;
+    uint8_t coprocessor_destination_register = 0;
+    int long_transfer = 0;
+    int reg;
+    // Note: vldr p1, c0, [r4, #4]  ; simple offset: r0 = *(int*)(r4+4); r4 
unchanged
+    // Note: Not allowed: vldr p2, c0, [r4, #4]! ; pre-indexed:   r0 = 
*(int*)(r4+4); r4 = r4+4
+    // Note: Not allowed: vldr p3, c0, [r4], #4  ; post-indexed:  r0 = 
*(int*)(r4+0); r4 = r4+4
+
+    if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) {
+        coprocessor = CP_SINGLE_PRECISION_FLOAT;
+        coprocessor_destination_register = reg;
+        long_transfer = coprocessor_destination_register & 1;
+        coprocessor_destination_register >>= 1;
+        next();
+    } else if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) {
+        coprocessor = CP_DOUBLE_PRECISION_FLOAT;
+        coprocessor_destination_register = reg;
+        next();
+    } else {
+        expect("floating point register");
+        return;
+    }
+
+    if (tok == ',')
+        next();
+    else
+        expect("','");
+
+    if (tok != '[')
+        expect("'['");
+    else
+        next(); // skip '['
+
+    parse_operand(s1, &ops[1]);
+    if (ops[1].type != OP_REG32) {
+        expect("(first source operand) register");
+        return;
+    }
+    if (tok == ',') {
+        next(); // skip ','
+        parse_operand(s1, &ops[2]);
+        if (ops[2].type != OP_IM8 && ops[2].type != OP_IM8N) {
+            expect("immediate offset");
+            return;
+        }
+    } else {
+        // end of input expression in brackets--assume 0 offset
+        ops[2].type = OP_IM8;
+        ops[2].e.v = 0;
+    }
+    if (tok != ']')
+        expect("']'");
+    else
+        next(); // skip ']'
+
+    switch (ARM_INSTRUCTION_GROUP(token)) {
+    case TOK_ASM_vldreq:
+        asm_emit_coprocessor_data_transfer(condition_code_of_token(token), 
coprocessor, coprocessor_destination_register, &ops[1], &ops[2], 0, 1, 0, 
long_transfer, 1);
+        break;
+    case TOK_ASM_vstreq:
+        asm_emit_coprocessor_data_transfer(condition_code_of_token(token), 
coprocessor, coprocessor_destination_register, &ops[1], &ops[2], 0, 1, 0, 
long_transfer, 0);
+        break;
+    default:
+        expect("floating point data transfer instruction");
+    }
+}
+#endif
+
 static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token)
 {
     Operand ops[3];
@@ -1780,6 +1875,12 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
     case TOK_ASM_stcleq:
         return asm_coprocessor_data_transfer_opcode(s1, token);
 
+#if defined(TCC_ARM_VFP)
+    case TOK_ASM_vldreq:
+    case TOK_ASM_vstreq:
+        return asm_floating_point_single_data_transfer_opcode(s1, token);
+#endif
+
     default:
         expect("known instruction");
     }
diff --git a/arm-tok.h b/arm-tok.h
index 28794e2..3dc3ea0 100644
--- a/arm-tok.h
+++ b/arm-tok.h
@@ -66,6 +66,60 @@
  DEF_ASM(c14)
  DEF_ASM(c15)
 
+ /* single-precision VFP registers */
+
+ DEF_ASM(s0)
+ DEF_ASM(s1)
+ DEF_ASM(s2)
+ DEF_ASM(s3)
+ DEF_ASM(s4)
+ DEF_ASM(s5)
+ DEF_ASM(s6)
+ DEF_ASM(s7)
+ DEF_ASM(s8)
+ DEF_ASM(s9)
+ DEF_ASM(s10)
+ DEF_ASM(s11)
+ DEF_ASM(s12)
+ DEF_ASM(s13)
+ DEF_ASM(s14)
+ DEF_ASM(s15)
+ DEF_ASM(s16)
+ DEF_ASM(s17)
+ DEF_ASM(s18)
+ DEF_ASM(s19)
+ DEF_ASM(s20)
+ DEF_ASM(s21)
+ DEF_ASM(s22)
+ DEF_ASM(s23)
+ DEF_ASM(s24)
+ DEF_ASM(s25)
+ DEF_ASM(s26)
+ DEF_ASM(s27)
+ DEF_ASM(s28)
+ DEF_ASM(s29)
+ DEF_ASM(s30)
+ DEF_ASM(s31)
+
+ /* double-precision VFP registers */
+
+ DEF_ASM(d0)
+ DEF_ASM(d1)
+ DEF_ASM(d2)
+ DEF_ASM(d3)
+ DEF_ASM(d4)
+ DEF_ASM(d5)
+ DEF_ASM(d6)
+ DEF_ASM(d7)
+ DEF_ASM(d8)
+ DEF_ASM(d9)
+ DEF_ASM(d10)
+ DEF_ASM(d11)
+ DEF_ASM(d12)
+ DEF_ASM(d13)
+ DEF_ASM(d14)
+ DEF_ASM(d15)
+
  /* data processing directives */
 
  DEF_ASM(asl)
@@ -225,3 +279,8 @@
  DEF_ASM_CONDED(cdp)
  DEF_ASM_CONDED(mcr)
  DEF_ASM_CONDED(mrc)
+
+ // Floating point high-level instructions
+
+ DEF_ASM_CONDED(vldr)
+ DEF_ASM_CONDED(vstr)
diff --git a/tests/arm-asm-testsuite.sh b/tests/arm-asm-testsuite.sh
index 4995c4c..1a76a2d 100755
--- a/tests/arm-asm-testsuite.sh
+++ b/tests/arm-asm-testsuite.sh
@@ -5,7 +5,7 @@ set -e
 # Note: "{r3}" is definitely different--but would complicate the assembler.
 
 state="`mktemp -d`"
-cat ../arm-tok.h |grep DEF_ASM |grep -v 'not useful' |grep -v '#define' |grep 
-v '/[*]' |sed -e 's;^[ ]*DEF_ASM[^(]*(\(.*\)).*$;\1;' | egrep -v 
'^((r|c|p)[0-9]+|fp|ip|sp|lr|pc|asl)$' | while read s
+cat ../arm-tok.h |grep DEF_ASM |grep -v 'not useful' |grep -v '#define' |grep 
-v '/[*]' |sed -e 's;^[ ]*DEF_ASM[^(]*(\(.*\)).*$;\1;' | egrep -v 
'^((r|c|p|s|d)[0-9]+|fp|ip|sp|lr|pc|asl)$' | while read s
 do
        ok=0
        for args in "r3, r4, r5, r6" \
@@ -97,6 +97,12 @@ do
                     "p5, c2, [r3, #-4]" \
                     "p5, c2, [r3, #0x45]" \
                     "p5, c2, [r3, #-0x45]" \
+                    "s2, [r3]" \
+                    "s3, [r4]" \
+                    "s2, [r3, #4]" \
+                    "s2, [r3, #-4]" \
+                    "s2, [r3, #0x45]" \
+                    "s2, [r3, #-0x45]" \
                    ""
        do
                #echo ".syntax unified" > a.s



reply via email to

[Prev in Thread] Current Thread [Next in Thread]