| @@ -276,6 +276,8 @@ static int asm_parse_reg(int *type) · 275 unmodified lines |
| 276 | 276 | *type = OP_EA32; |
| 277 | 277 | } else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) { |
| 278 | 278 | reg = tok - TOK_ASM_rax; |
| 279 | + } else if (tok == TOK_ASM_rip) { |
| 280 | + reg = 8; |
| 279 | 281 | #endif |
| 280 | 282 | } else { |
| 281 | 283 | error_32: |
| @@ -444,7 +446,7 @@ static void gen_disp32(ExprValue *pe) · 162 unmodified lines |
| 444 | 446 | } |
| 445 | 447 | |
| 446 | 448 | /* generate the modrm operand */ |
| 447 | | −static inline void asm_modrm(int reg, Operand *op) |
| 449 | +static inline int asm_modrm(int reg, Operand *op) |
| 448 | 450 | { |
| 449 | 451 | int mod, reg1, reg2, sib_reg1; |
| 450 | 452 | |
| @@ -459,6 +461,13 @@ static inline void asm_modrm(int reg, Operand *op) · 8 unmodified lines |
| 459 | 461 | g(0x05 + (reg << 3)); |
| 460 | 462 | #endif |
| 461 | 463 | gen_expr32(&op->e); |
| 464 | +#ifdef TCC_TARGET_X86_64 |
| 465 | + } else if (op->reg == 8) { |
| 466 | + ExprValue *pe = &op->e; |
| 467 | + g(0x05 + (reg << 3)); |
| 468 | + gen_addrpc32(pe->sym ? VT_SYM : 0, pe->sym, pe->v); |
| 469 | + return ind; |
| 470 | +#endif |
| 462 | 471 | } else { |
| 463 | 472 | sib_reg1 = op->reg; |
| 464 | 473 | /* fist compute displacement encoding */ |
| @@ -491,12 +500,13 @@ static inline void asm_modrm(int reg, Operand *op) · 26 unmodified lines |
| 491 | 500 | gen_expr32(&op->e); |
| 492 | 501 | } |
| 493 | 502 | } |
| 503 | + return 0; |
| 494 | 504 | } |
| 495 | 505 | |
| 496 | 506 | ST_FUNC void asm_opcode(TCCState *s1, int opcode) |
| 497 | 507 | { |
| 498 | 508 | const ASMInstr *pa; |
| 499 | | − int i, modrm_index, reg, v, op1, seg_prefix; |
| 509 | + int i, modrm_index, reg, v, op1, seg_prefix, pc; |
| 500 | 510 | int nb_ops, s; |
| 501 | 511 | Operand ops[MAX_OPERANDS], *pop; |
| 502 | 512 | int op_type[3]; /* decoded op type */ |
| @@ -802,6 +812,8 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 299 unmodified lines |
| 802 | 812 | } else { |
| 803 | 813 | reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7; |
| 804 | 814 | } |
| 815 | + |
| 816 | + pc = 0; |
| 805 | 817 | if (pa->instr_type & OPC_MODRM) { |
| 806 | 818 | /* first look for an ea operand */ |
| 807 | 819 | for(i = 0;i < nb_ops; i++) { |
| @@ -828,8 +840,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 20 unmodified lines |
| 828 | 840 | break; |
| 829 | 841 | } |
| 830 | 842 | } |
| 831 | | − |
| 832 | | − asm_modrm(reg, &ops[modrm_index]); |
| 843 | + pc = asm_modrm(reg, &ops[modrm_index]); |
| 833 | 844 | } |
| 834 | 845 | |
| 835 | 846 | /* emit constants */ |
| @@ -858,30 +869,29 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 22 unmodified lines |
| 858 | 869 | else |
| 859 | 870 | v = OP_IM64; |
| 860 | 871 | } |
| 872 | + |
| 873 | + if ((v & (OP_IM8 | OP_IM8S | OP_IM16)) && ops[i].e.sym) |
| 874 | + tcc_error("cannot relocate"); |
| 875 | + |
| 861 | 876 | if (v & (OP_IM8 | OP_IM8S)) { |
| 862 | | − if (ops[i].e.sym) |
| 863 | | − goto error_relocate; |
| 864 | 877 | g(ops[i].e.v); |
| 865 | 878 | } else if (v & OP_IM16) { |
| 866 | | − if (ops[i].e.sym) |
| 867 | | − error_relocate: |
| 868 | | − tcc_error("cannot relocate"); |
| 869 | | − else |
| 870 | | − gen_le16(ops[i].e.v); |
| 871 | | − } else { |
| 872 | | − if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) { |
| 873 | | − gen_disp32(&ops[i].e); |
| 874 | | − } else { |
| 879 | + gen_le16(ops[i].e.v); |
| 875 | 880 | #ifdef TCC_TARGET_X86_64 |
| 876 | | − if (v & OP_IM64) |
| 877 | | − gen_expr64(&ops[i].e); |
| 878 | | − else |
| 881 | + } else if (v & OP_IM64) { |
| 882 | + gen_expr64(&ops[i].e); |
| 879 | 883 | #endif |
| 880 | | − gen_expr32(&ops[i].e); |
| 881 | | − } |
| 884 | + } else if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) { |
| 885 | + gen_disp32(&ops[i].e); |
| 886 | + } else { |
| 887 | + gen_expr32(&ops[i].e); |
| 882 | 888 | } |
| 883 | 889 | } |
| 884 | 890 | } |
| 891 | + |
| 892 | + /* after immediate operands, adjust pc-relative address */ |
| 893 | + if (pc) |
| 894 | + *(int*)(text_section->data + pc - 4) -= ind - pc; |
| 885 | 895 | } |
| 886 | 896 | |
| 887 | 897 | /* return the constraint priority (we allocate first the lowest |
| @@ -1189,17 +1199,20 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 301 unmodified lines |
| 1189 | 1199 | cstr_ccat(add_str, '$'); |
| 1190 | 1200 | if (r & VT_SYM) { |
| 1191 | 1201 | cstr_cat(add_str, get_tok_str(sv->sym->v, NULL), -1); |
| 1192 | | − if ((uint32_t)sv->c.i != 0) { |
| 1193 | | − cstr_ccat(add_str, '+'); |
| 1194 | | − } else { |
| 1195 | | − return; |
| 1196 | | − } |
| 1202 | + if ((uint32_t)sv->c.i == 0) |
| 1203 | + goto no_offset; |
| 1204 | + cstr_ccat(add_str, '+'); |
| 1197 | 1205 | } |
| 1198 | 1206 | val = sv->c.i; |
| 1199 | 1207 | if (modifier == 'n') |
| 1200 | 1208 | val = -val; |
| 1201 | 1209 | snprintf(buf, sizeof(buf), "%d", (int)sv->c.i); |
| 1202 | 1210 | cstr_cat(add_str, buf, -1); |
| 1211 | + no_offset:; |
| 1212 | +#ifdef TCC_TARGET_X86_64 |
| 1213 | + if (r & VT_LVAL) |
| 1214 | + cstr_cat(add_str, "(%rip)", -1); |
| 1215 | +#endif |
| 1203 | 1216 | } else if ((r & VT_VALMASK) == VT_LOCAL) { |
| 1204 | 1217 | #ifdef TCC_TARGET_X86_64 |
| 1205 | 1218 | snprintf(buf, sizeof(buf), "%d(%%rbp)", (int)sv->c.i); |
| @@ -1212,7 +1225,12 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 6 unmodified lines |
| 1212 | 1225 | if (reg >= VT_CONST) |
| 1213 | 1226 | tcc_error("internal compiler error"); |
| 1214 | 1227 | snprintf(buf, sizeof(buf), "(%%%s)", |
| 1215 | | − get_tok_str(TOK_ASM_eax + reg, NULL)); |
| 1228 | +#ifdef TCC_TARGET_X86_64 |
| 1229 | + get_tok_str(TOK_ASM_rax + reg, NULL) |
| 1230 | +#else |
| 1231 | + get_tok_str(TOK_ASM_eax + reg, NULL) |
| 1232 | +#endif |
| 1233 | + ); |
| 1216 | 1234 | cstr_cat(add_str, buf, -1); |
| 1217 | 1235 | } else { |
| 1218 | 1236 | /* register case */ |
| @@ -1244,6 +1262,8 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 25 unmodified lines |
| 1244 | 1262 | size = -1; |
| 1245 | 1263 | } else if (modifier == 'w') { |
| 1246 | 1264 | size = 2; |
| 1265 | + } else if (modifier == 'k') { |
| 1266 | + size = 4; |
| 1247 | 1267 | #ifdef TCC_TARGET_X86_64 |
| 1248 | 1268 | } else if (modifier == 'q') { |
| 1249 | 1269 | size = 8; |
| @@ -1311,7 +1331,8 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, · 61 unmodified lines |
| 1311 | 1331 | output cases) */ |
| 1312 | 1332 | SValue sv; |
| 1313 | 1333 | sv = *op->vt; |
| 1314 | | − sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL; |
| 1334 | + sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL; |
| 1335 | + sv.type.t = VT_PTR; |
| 1315 | 1336 | load(op->reg, &sv); |
| 1316 | 1337 | } else if (i >= nb_outputs || op->is_rw) { |
| 1317 | 1338 | /* load value in register */ |