Unified · Split
| @@ -1058,9 +1058,9 @@ static uint32_t encbranchoffset(int pos, int addr, int fail) · 1057 unmodified lines | ||
| 1058 | 1058 | { |
| 1059 | 1059 | addr-=pos+8; |
| 1060 | 1060 | addr/=4; |
| 1061 | − if(addr>=0x1000000 || addr<-0x1000000) { // FIXME: Is that correct? | |
| 1061 | + if(addr>=0x7fffff || addr<-0x800000) { | |
| 1062 | 1062 | if(fail) |
| 1063 | − tcc_error("function bigger than 32MB"); | |
| 1063 | + tcc_error("branch offset is too far"); | |
| 1064 | 1064 | return 0; |
| 1065 | 1065 | } |
| 1066 | 1066 | return /*not 0x0A000000|*/(addr&0xffffff); |
| @@ -1070,26 +1070,30 @@ static void asm_branch_opcode(TCCState *s1, int token) · 3 unmodified lines | ||
| 1070 | 1070 | { |
| 1071 | 1071 | int jmp_disp = 0; |
| 1072 | 1072 | Operand op; |
| 1073 | − parse_operand(s1, &op); | |
| 1074 | − if (op.type == OP_IM32 || op.type == OP_IM8 || op.type == OP_IM8N) { | |
| 1075 | − jmp_disp = encbranchoffset(ind, op.e.v, 0); | |
| 1076 | − if (jmp_disp < -0x800000 || jmp_disp > 0x7fffff) { | |
| 1077 | − tcc_error("branch is too far"); | |
| 1073 | + ExprValue e; | |
| 1074 | + ElfSym *esym; | |
| 1075 | + | |
| 1076 | + switch (ARM_INSTRUCTION_GROUP(token)) { | |
| 1077 | + case TOK_ASM_beq: | |
| 1078 | + case TOK_ASM_bleq: | |
| 1079 | + asm_expr(s1, &e); | |
| 1080 | + esym = elfsym(e.sym); | |
| 1081 | + if (!esym || esym->st_shndx != cur_text_section->sh_num) { | |
| 1082 | + tcc_error("invalid branch target"); | |
| 1078 | 1083 | return; |
| 1079 | 1084 | } |
| 1085 | + jmp_disp = encbranchoffset(ind, e.v + esym->st_value, 1); | |
| 1086 | + break; | |
| 1087 | + default: | |
| 1088 | + parse_operand(s1, &op); | |
| 1089 | + break; | |
| 1080 | 1090 | } |
| 1081 | 1091 | switch (ARM_INSTRUCTION_GROUP(token)) { |
| 1082 | 1092 | case TOK_ASM_beq: |
| 1083 | − if (op.type == OP_IM32 || op.type == OP_IM8 || op.type == OP_IM8N) | |
| 1084 | − asm_emit_opcode(token, (0xa << 24) | (jmp_disp & 0xffffff)); | |
| 1085 | − else | |
| 1086 | − expect("branch target"); | |
| 1093 | + asm_emit_opcode(token, (0xa << 24) | (jmp_disp & 0xffffff)); | |
| 1087 | 1094 | break; |
| 1088 | 1095 | case TOK_ASM_bleq: |
| 1089 | − if (op.type == OP_IM32 || op.type == OP_IM8 || op.type == OP_IM8N) | |
| 1090 | − asm_emit_opcode(token, (0xb << 24) | (jmp_disp & 0xffffff)); | |
| 1091 | − else | |
| 1092 | − expect("branch target"); | |
| 1096 | + asm_emit_opcode(token, (0xb << 24) | (jmp_disp & 0xffffff)); | |
| 1093 | 1097 | break; |
| 1094 | 1098 | case TOK_ASM_bxeq: |
| 1095 | 1099 | if (op.type != OP_REG32) |