tinycc-devel
[Top][All Lists]
Advanced

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

[Tinycc-devel] [PATCH 2/3] arm-asm: Add ldrex, ldrexb, strex, strexb


From: Danny Milosavljevic
Subject: [Tinycc-devel] [PATCH 2/3] arm-asm: Add ldrex, ldrexb, strex, strexb
Date: Tue, 5 Jan 2021 01:06:39 +0100

---
 arm-asm.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 arm-tok.h |  4 ++++
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/arm-asm.c b/arm-asm.c
index 27f396b..5b64fa6 100644
--- a/arm-asm.c
+++ b/arm-asm.c
@@ -939,10 +939,11 @@ static void asm_long_multiplication_opcode(TCCState *s1, 
int token)
 static void asm_single_data_transfer_opcode(TCCState *s1, int token)
 {
     Operand ops[3];
+    Operand strex_operand;
     int exclam = 0;
     int closed_bracket = 0;
     int op2_minus = 0;
-    uint32_t opcode = 1 << 26;
+    uint32_t opcode = 0;
     // Note: ldr r0, [r4, #4]  ; simple offset: r0 = *(int*)(r4+4); r4 
unchanged
     // Note: ldr r0, [r4, #4]! ; pre-indexed:   r0 = *(int*)(r4+4); r4 = r4+4
     // Note: ldr r0, [r4], #4  ; post-indexed:  r0 = *(int*)(r4+0); r4 = r4+4
@@ -955,9 +956,25 @@ static void asm_single_data_transfer_opcode(TCCState *s1, 
int token)
         return;
     }
     if (tok != ',')
-        expect("two arguments");
+        expect("at least two arguments");
     else
         next(); // skip ','
+
+    switch (ARM_INSTRUCTION_GROUP(token)) {
+    case TOK_ASM_strexbeq:
+    case TOK_ASM_strexeq:
+        parse_operand(s1, &strex_operand);
+        if (strex_operand.type != OP_REG32) {
+            expect("register");
+            return;
+        }
+        if (tok != ',')
+            expect("at least three arguments");
+        else
+            next(); // skip ','
+        break;
+    }
+
     if (tok != '[')
         expect("'['");
     else
@@ -1039,6 +1056,7 @@ static void asm_single_data_transfer_opcode(TCCState *s1, 
int token)
         opcode |= 1 << 22; // B
         /* fallthrough */
     case TOK_ASM_streq:
+        opcode |= 1 << 26; // Load/Store
         asm_emit_opcode(token, opcode);
         break;
     case TOK_ASM_ldrbeq:
@@ -1046,6 +1064,47 @@ static void asm_single_data_transfer_opcode(TCCState 
*s1, int token)
         /* fallthrough */
     case TOK_ASM_ldreq:
         opcode |= 1 << 20; // L
+        opcode |= 1 << 26; // Load/Store
+        asm_emit_opcode(token, opcode);
+        break;
+    case TOK_ASM_strexbeq:
+        opcode |= 1 << 22; // B
+        /* fallthrough */
+    case TOK_ASM_strexeq:
+        if (opcode & 0xFFF) {
+            tcc_error("offset not allowed with 'strex'");
+            return;
+        } else if (opcode & ENCODE_IMMEDIATE_FLAG) { // if set, it means it's 
NOT immediate
+            tcc_error("offset not allowed with 'strex'");
+            return;
+        }
+        if ((opcode & (1 << 24)) == 0) { // add offset after transfer
+            tcc_error("adding offset after transfer not allowed with 'strex'");
+            return;
+        }
+
+        opcode |= 0xf90;
+        opcode |= strex_operand.reg;
+        asm_emit_opcode(token, opcode);
+        break;
+    case TOK_ASM_ldrexbeq:
+        opcode |= 1 << 22; // B
+        /* fallthrough */
+    case TOK_ASM_ldrexeq:
+        if (opcode & 0xFFF) {
+            tcc_error("offset not allowed with 'ldrex'");
+            return;
+        } else if (opcode & ENCODE_IMMEDIATE_FLAG) { // if set, it means it's 
NOT immediate
+            tcc_error("offset not allowed with 'ldrex'");
+            return;
+        }
+        if ((opcode & (1 << 24)) == 0) { // add offset after transfer
+            tcc_error("adding offset after transfer not allowed with 'ldrex'");
+            return;
+        }
+        opcode |= 1 << 20; // L
+        opcode |= 0x00f;
+        opcode |= 0xf90;
         asm_emit_opcode(token, opcode);
         break;
     default:
@@ -1163,6 +1222,10 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
     case TOK_ASM_ldrbeq:
     case TOK_ASM_streq:
     case TOK_ASM_strbeq:
+    case TOK_ASM_ldrexeq:
+    case TOK_ASM_ldrexbeq:
+    case TOK_ASM_strexeq:
+    case TOK_ASM_strexbeq:
         return asm_single_data_transfer_opcode(s1, token);
 
     case TOK_ASM_andeq:
diff --git a/arm-tok.h b/arm-tok.h
index 7c1a202..be927cc 100644
--- a/arm-tok.h
+++ b/arm-tok.h
@@ -93,6 +93,10 @@
  DEF_ASM_CONDED(ldrb)
  DEF_ASM_CONDED(str)
  DEF_ASM_CONDED(strb)
+ DEF_ASM_CONDED(ldrex)
+ DEF_ASM_CONDED(ldrexb)
+ DEF_ASM_CONDED(strex)
+ DEF_ASM_CONDED(strexb)
 
  DEF_ASM_CONDED(stmda)
  DEF_ASM_CONDED(ldmda)



reply via email to

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