tinycc-devel
[Top][All Lists]
Advanced

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

[Tinycc-devel] [PATCH 1/3] arm-asm: Implement branch to label


From: Danny Milosavljevic
Subject: [Tinycc-devel] [PATCH 1/3] arm-asm: Implement branch to label
Date: Tue, 5 Jan 2021 01:06:38 +0100

---
 arm-asm.c | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/arm-asm.c b/arm-asm.c
index fc92898..27f396b 100644
--- a/arm-asm.c
+++ b/arm-asm.c
@@ -1058,9 +1058,9 @@ static uint32_t encbranchoffset(int pos, int addr, int 
fail)
 {
   addr-=pos+8;
   addr/=4;
-  if(addr>=0x1000000 || addr<-0x1000000) { // FIXME: Is that correct?
+  if(addr>=0x7fffff || addr<-0x800000) {
     if(fail)
-      tcc_error("function bigger than 32MB");
+      tcc_error("branch offset is too far");
     return 0;
   }
   return /*not 0x0A000000|*/(addr&0xffffff);
@@ -1070,26 +1070,30 @@ static void asm_branch_opcode(TCCState *s1, int token)
 {
     int jmp_disp = 0;
     Operand op;
-    parse_operand(s1, &op);
-    if (op.type == OP_IM32 || op.type == OP_IM8 || op.type == OP_IM8N) {
-        jmp_disp = encbranchoffset(ind, op.e.v, 0);
-        if (jmp_disp < -0x800000 || jmp_disp > 0x7fffff) {
-            tcc_error("branch is too far");
+    ExprValue e;
+    ElfSym *esym;
+
+    switch (ARM_INSTRUCTION_GROUP(token)) {
+    case TOK_ASM_beq:
+    case TOK_ASM_bleq:
+        asm_expr(s1, &e);
+        esym = elfsym(e.sym);
+        if (!esym || esym->st_shndx != cur_text_section->sh_num) {
+            tcc_error("invalid branch target");
             return;
         }
+        jmp_disp = encbranchoffset(ind, e.v + esym->st_value, 1);
+        break;
+    default:
+        parse_operand(s1, &op);
+        break;
     }
     switch (ARM_INSTRUCTION_GROUP(token)) {
     case TOK_ASM_beq:
-        if (op.type == OP_IM32 || op.type == OP_IM8 || op.type == OP_IM8N)
-            asm_emit_opcode(token, (0xa << 24) | (jmp_disp & 0xffffff));
-        else
-            expect("branch target");
+        asm_emit_opcode(token, (0xa << 24) | (jmp_disp & 0xffffff));
         break;
     case TOK_ASM_bleq:
-        if (op.type == OP_IM32 || op.type == OP_IM8 || op.type == OP_IM8N)
-            asm_emit_opcode(token, (0xb << 24) | (jmp_disp & 0xffffff));
-        else
-            expect("branch target");
+        asm_emit_opcode(token, (0xb << 24) | (jmp_disp & 0xffffff));
         break;
     case TOK_ASM_bxeq:
         if (op.type != OP_REG32)



reply via email to

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