tinycc-devel
[Top][All Lists]
Advanced

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

[Tinycc-devel] [PATCH] arm-asm: Add vmsr, vmrs


From: Danny Milosavljevic
Subject: [Tinycc-devel] [PATCH] arm-asm: Add vmsr, vmrs
Date: Tue, 26 Jan 2021 14:26:42 +0100

---
 arm-asm.c                  | 85 ++++++++++++++++++++++++++++++++++++--
 arm-tok.h                  | 12 ++++++
 tests/arm-asm-testsuite.sh |  9 +++-
 3 files changed, 101 insertions(+), 5 deletions(-)

diff --git a/arm-asm.c b/arm-asm.c
index 9c390d2..8cbcd51 100644
--- a/arm-asm.c
+++ b/arm-asm.c
@@ -77,6 +77,20 @@ static int asm_parse_vfp_regvar(int t, int double_precision)
     return -1;
 }
 
+static int asm_parse_vfp_status_regvar(int t)
+{
+    switch (t) {
+    case TOK_ASM_fpsid:
+        return 0;
+    case TOK_ASM_fpscr:
+        return 1;
+    case TOK_ASM_fpexc:
+        return 8;
+    default:
+        return -1;
+    }
+}
+
 /* Parse a text containing operand and store the result in OP */
 static void parse_operand(TCCState *s1, Operand *op)
 {
@@ -1915,10 +1929,6 @@ static void 
asm_floating_point_data_processing_opcode(TCCState *s1, int token) {
    VMOV Rd, Dn[0]
    VMOV Dn[1], Rd
    VMOV Rd, Dn[1]
-
-   VMSR <sysreg>, Rd
-   VMRS Rd, <sysreg>
-   VMRS APSR_nzcv, FPSCR
 */
 
     switch (ARM_INSTRUCTION_GROUP(token)) {
@@ -2110,6 +2120,68 @@ static void 
asm_floating_point_data_processing_opcode(TCCState *s1, int token) {
 
     asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor, 
opcode1, ops[0].reg, (ops[1].type == OP_IM8) ? ops[1].e.v : ops[1].reg, 
(ops[2].type == OP_IM8) ? ops[2].e.v : ops[2].reg, opcode2, 0);
 }
+
+static void asm_floating_point_status_register_opcode(TCCState* s1, int token)
+{
+    uint8_t coprocessor = CP_SINGLE_PRECISION_FLOAT;
+    uint8_t opcode;
+    int vfp_sys_reg = -1;
+    Operand arm_operand;
+    switch (ARM_INSTRUCTION_GROUP(token)) {
+    case TOK_ASM_vmrseq:
+        opcode = 0xf;
+        if (tok == TOK_ASM_apsr_nzcv) {
+            arm_operand.type = OP_REG32;
+            arm_operand.reg = 15; // not PC
+            next(); // skip apsr_nzcv
+        } else {
+            parse_operand(s1, &arm_operand);
+            if (arm_operand.type == OP_REG32 && arm_operand.reg == 15) {
+                tcc_error("'%s' does not support 'pc' as operand", 
get_tok_str(token, NULL));
+                return;
+            }
+        }
+
+        if (tok != ',')
+            expect("','");
+        else
+            next(); // skip ','
+        vfp_sys_reg = asm_parse_vfp_status_regvar(tok);
+        next(); // skip vfp sys reg
+        if (arm_operand.type == OP_REG32 && arm_operand.reg == 15 && 
vfp_sys_reg != 1) {
+            tcc_error("'%s' only supports the variant 'vmrs apsr_nzcv, fpscr' 
here", get_tok_str(token, NULL));
+            return;
+        }
+        break;
+    case TOK_ASM_vmsreq:
+        opcode = 0xe;
+        vfp_sys_reg = asm_parse_vfp_status_regvar(tok);
+        next(); // skip vfp sys reg
+        if (tok != ',')
+            expect("','");
+        else
+            next(); // skip ','
+        parse_operand(s1, &arm_operand);
+        if (arm_operand.type == OP_REG32 && arm_operand.reg == 15) {
+            tcc_error("'%s' does not support 'pc' as operand", 
get_tok_str(token, NULL));
+            return;
+        }
+        break;
+    default:
+        expect("floating point status register instruction");
+        return;
+    }
+    if (vfp_sys_reg == -1) {
+        expect("VFP system register");
+        return;
+    }
+    if (arm_operand.type != OP_REG32) {
+        expect("ARM register");
+        return;
+    }
+    asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor, 
opcode, arm_operand.reg, vfp_sys_reg, 0x10, 0, 0);
+}
+
 #endif
 
 static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token)
@@ -2518,6 +2590,11 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
     case TOK_ASM_vstmdbeq:
         asm_floating_point_block_data_transfer_opcode(s1, token);
         return;
+
+    case TOK_ASM_vmsreq:
+    case TOK_ASM_vmrseq:
+        asm_floating_point_status_register_opcode(s1, token);
+        return;
 #endif
 
     default:
diff --git a/arm-tok.h b/arm-tok.h
index 79514b0..2ee79ca 100644
--- a/arm-tok.h
+++ b/arm-tok.h
@@ -120,6 +120,16 @@
  DEF_ASM(d14)
  DEF_ASM(d15)
 
+ /* VFP status registers */
+
+ DEF_ASM(fpsid)
+ DEF_ASM(fpscr)
+ DEF_ASM(fpexc)
+
+ /* VFP magical ARM register */
+
+ DEF_ASM(apsr_nzcv)
+
  /* data processing directives */
 
  DEF_ASM(asl)
@@ -333,3 +343,5 @@
  DEF_ASM_CONDED(vstm)
  DEF_ASM_CONDED(vstmia)
  DEF_ASM_CONDED(vstmdb)
+ DEF_ASM_CONDED(vmsr)
+ DEF_ASM_CONDED(vmrs)
diff --git a/tests/arm-asm-testsuite.sh b/tests/arm-asm-testsuite.sh
index 19acf90..bfa1e10 100755
--- a/tests/arm-asm-testsuite.sh
+++ b/tests/arm-asm-testsuite.sh
@@ -14,7 +14,7 @@ cat ../arm-tok.h | \
   sed -e 's;^[ ]*DEF_ASM_CONDED_VFP_F32_F64[^(]*(\(.*\)).*$; 
DEF_ASM_CONDED(\1.f32)\
  DEF_ASM_CONDED(\1.f64);g' | \
   sed -e 's;^[ ]*DEF_ASM[^(]*(\(.*\)).*$;\1;g' | \
-  egrep -v '^((r|c|p|s|d)[0-9]+|fp|ip|sp|lr|pc|asl)$' | while read s
+  egrep -v 
'^((r|c|p|s|d)[0-9]+|fp|ip|sp|lr|pc|asl|apsr_nzcv|fpsid|fpscr|fpexc)$' | while 
read s
 do
        as_opts=""
        if [ "${s#v}" != "${s}" ]
@@ -155,6 +155,13 @@ do
                     "d1, r2, r3" \
                     "s1, r2" \
                     "r2, s1" \
+                    "r2, fpexc" \
+                    "r2, fpscr" \
+                    "r2, fpsid" \
+                    "apsr_nzcv, fpscr" \
+                    "fpexc, r2" \
+                    "fpscr, r2" \
+                    "fpsid, r2" \
                    ""
        do
                #echo ".syntax unified" > a.s



reply via email to

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