Unified · Split
| @@ -272,18 +272,25 @@ static void asm_jal_opcode(TCCState *s1, int token){ · 271 unmodified lines | ||
| 272 | 272 | static const Operand ra = {.type = OP_REG, .reg = 1}; |
| 273 | 273 | Operand ops[2]; |
| 274 | 274 | parse_operand(s1, &ops[0]); |
| 275 | − if ( tok == ',') | |
| 276 | − next(); | |
| 277 | − else { | |
| 275 | + if ( ops[0].type != OP_REG ) { | |
| 278 | 276 | /* no more operands, it's the pseudoinstruction: |
| 279 | − * jal rs | |
| 277 | + * jal offset | |
| 280 | 278 | * Expand to: |
| 281 | − * jal ra, rs | |
| 279 | + * jal ra, offset | |
| 282 | 280 | */ |
| 283 | − asm_emit_j(token, 0x6f, &ra, &ops[0]); | |
| 284 | − return; | |
| 281 | + ops[1] = ops[0]; | |
| 282 | + ops[0] = ra; | |
| 283 | + goto emit; | |
| 285 | 284 | } |
| 285 | + if ( tok == ',') | |
| 286 | + next(); | |
| 287 | + else | |
| 288 | + expect("','"); | |
| 286 | 289 | parse_operand(s1, &ops[1]); |
| 290 | +emit: | |
| 291 | + if (ops[1].e.sym && ops[1].e.sym->type.t & (VT_EXTERN | VT_STATIC)){ | |
| 292 | + greloca(cur_text_section, ops[1].e.sym, ind, R_RISCV_JAL, 0); | |
| 293 | + } | |
| 287 | 294 | asm_emit_j(token, 0x6f, &ops[0], &ops[1]); |
| 288 | 295 | } |
| 289 | 296 | |
| @@ -722,7 +729,7 @@ static void asm_emit_j(int token, uint32_t opcode, const Operand* rd, const Oper · 432 unmodified lines | ||
| 722 | 729 | imm = rs2->e.v; |
| 723 | 730 | |
| 724 | 731 | /* even offsets in a +- 1 MiB range */ |
| 725 | − if (imm > 0x1ffffe) { | |
| 732 | + if ((int)imm > (1 << 20) -1 || (int)imm <= -1 * ((1 << 20) -1)) { | |
| 726 | 733 | tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 0x1fffff", get_tok_str(token, NULL)); |
| 727 | 734 | return; |
| 728 | 735 | } |