---
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>=0x100 || addr<-0x100) { // FIXME: Is that correct?
+ if(addr>=0x7f || addr<-0x80) {
if(fail)
- tcc_error("function bigger than 32MB");
+ tcc_error("branch offset is too far");
return 0;
}
return /*not 0x0A00|*/(addr&0xff);
@@ -1070,26 +1070,30 @@ static void asm_branch_opcode(TCCState *s1, int token)
{
int jmp_disp = 0;
Operand op;
-parse_operand(s1, );
-if (op.type == OP_IM32 || op.type == OP_IM8 || op.type == OP_IM8N) {
-jmp_disp = encbranchoffset(ind, op.e.v, 0);
-if (jmp_disp < -0x80 || jmp_disp > 0x7f) {
-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, );
+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, );
+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 & 0xff));
-else
-expect("branch target");
+asm_emit_opcode(token, (0xa << 24) | (jmp_disp & 0xff));
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 & 0xff));
-else
-expect("branch target");
+asm_emit_opcode(token, (0xb << 24) | (jmp_disp & 0xff));
break;
case TOK_ASM_bxeq:
if (op.type != OP_REG32)
___
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel