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