| @@ -276,6 +276,8 @@ static int asm_parse_reg(int *type) · 275 unmodified lines |
| 276 | *type = OP_EA32; | 276 | *type = OP_EA32; |
| 277 | } else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) { | 277 | } else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) { |
| 278 | reg = tok - TOK_ASM_rax; | 278 | reg = tok - TOK_ASM_rax; |
| | 279 | } else if (tok == TOK_ASM_rip) { |
| | 280 | reg = 8; |
| 279 | #endif | 281 | #endif |
| 280 | } else { | 282 | } else { |
| 281 | error_32: | 283 | error_32: |
| @@ -444,7 +446,7 @@ static void gen_disp32(ExprValue *pe) · 162 unmodified lines |
| 444 | } | 446 | } |
| 445 | | 447 | |
| 446 | /* generate the modrm operand */ | 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 | int mod, reg1, reg2, sib_reg1; | 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 | g(0x05 + (reg << 3)); | 461 | g(0x05 + (reg << 3)); |
| 460 | #endif | 462 | #endif |
| 461 | gen_expr32(&op->e); | 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 | } else { | 471 | } else { |
| 463 | sib_reg1 = op->reg; | 472 | sib_reg1 = op->reg; |
| 464 | /* fist compute displacement encoding */ | 473 | /* fist compute displacement encoding */ |
| @@ -491,12 +500,13 @@ static inline void asm_modrm(int reg, Operand *op) · 26 unmodified lines |
| 491 | gen_expr32(&op->e); | 500 | gen_expr32(&op->e); |
| 492 | } | 501 | } |
| 493 | } | 502 | } |
| | 503 | return 0; |
| 494 | } | 504 | } |
| 495 | | 505 | |
| 496 | ST_FUNC void asm_opcode(TCCState *s1, int opcode) | 506 | ST_FUNC void asm_opcode(TCCState *s1, int opcode) |
| 497 | { | 507 | { |
| 498 | const ASMInstr *pa; | 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 | int nb_ops, s; | 510 | int nb_ops, s; |
| 501 | Operand ops[MAX_OPERANDS], *pop; | 511 | Operand ops[MAX_OPERANDS], *pop; |
| 502 | int op_type[3]; /* decoded op type */ | 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 | } else { | 812 | } else { |
| 803 | reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7; | 813 | reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7; |
| 804 | } | 814 | } |
| | 815 | |
| | 816 | pc = 0; |
| 805 | if (pa->instr_type & OPC_MODRM) { | 817 | if (pa->instr_type & OPC_MODRM) { |
| 806 | /* first look for an ea operand */ | 818 | /* first look for an ea operand */ |
| 807 | for(i = 0;i < nb_ops; i++) { | 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 | break; | 840 | break; |
| 829 | } | 841 | } |
| 830 | } | 842 | } |
| 831 | | 843 | pc = asm_modrm(reg, &ops[modrm_index]); |
| 832 | asm_modrm(reg, &ops[modrm_index]); | | |
| 833 | } | 844 | } |
| 834 | | 845 | |
| 835 | /* emit constants */ | 846 | /* emit constants */ |
| @@ -858,30 +869,29 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 22 unmodified lines |
| 858 | else | 869 | else |
| 859 | v = OP_IM64; | 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 | if (v & (OP_IM8 | OP_IM8S)) { | 876 | if (v & (OP_IM8 | OP_IM8S)) { |
| 862 | if (ops[i].e.sym) | | |
| 863 | goto error_relocate; | | |
| 864 | g(ops[i].e.v); | 877 | g(ops[i].e.v); |
| 865 | } else if (v & OP_IM16) { | 878 | } else if (v & OP_IM16) { |
| 866 | if (ops[i].e.sym) | 879 | gen_le16(ops[i].e.v); |
| 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 { | | |
| 875 | #ifdef TCC_TARGET_X86_64 | 880 | #ifdef TCC_TARGET_X86_64 |
| 876 | if (v & OP_IM64) | 881 | } else if (v & OP_IM64) { |
| 877 | gen_expr64(&ops[i].e); | 882 | gen_expr64(&ops[i].e); |
| 878 | else | | |
| 879 | #endif | 883 | #endif |
| 880 | gen_expr32(&ops[i].e); | 884 | } else if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) { |
| 881 | } | 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 | /* return the constraint priority (we allocate first the lowest | 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 | cstr_ccat(add_str, '$'); | 1199 | cstr_ccat(add_str, '$'); |
| 1190 | if (r & VT_SYM) { | 1200 | if (r & VT_SYM) { |
| 1191 | cstr_cat(add_str, get_tok_str(sv->sym->v, NULL), -1); | 1201 | cstr_cat(add_str, get_tok_str(sv->sym->v, NULL), -1); |
| 1192 | if ((uint32_t)sv->c.i != 0) { | 1202 | if ((uint32_t)sv->c.i == 0) |
| 1193 | cstr_ccat(add_str, '+'); | 1203 | goto no_offset; |
| 1194 | } else { | 1204 | cstr_ccat(add_str, '+'); |
| 1195 | return; | | |
| 1196 | } | | |
| 1197 | } | 1205 | } |
| 1198 | val = sv->c.i; | 1206 | val = sv->c.i; |
| 1199 | if (modifier == 'n') | 1207 | if (modifier == 'n') |
| 1200 | val = -val; | 1208 | val = -val; |
| 1201 | snprintf(buf, sizeof(buf), "%d", (int)sv->c.i); | 1209 | snprintf(buf, sizeof(buf), "%d", (int)sv->c.i); |
| 1202 | cstr_cat(add_str, buf, -1); | 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 | } else if ((r & VT_VALMASK) == VT_LOCAL) { | 1216 | } else if ((r & VT_VALMASK) == VT_LOCAL) { |
| 1204 | #ifdef TCC_TARGET_X86_64 | 1217 | #ifdef TCC_TARGET_X86_64 |
| 1205 | snprintf(buf, sizeof(buf), "%d(%%rbp)", (int)sv->c.i); | 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 | if (reg >= VT_CONST) | 1225 | if (reg >= VT_CONST) |
| 1213 | tcc_error("internal compiler error"); | 1226 | tcc_error("internal compiler error"); |
| 1214 | snprintf(buf, sizeof(buf), "(%%%s)", | 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 | cstr_cat(add_str, buf, -1); | 1234 | cstr_cat(add_str, buf, -1); |
| 1217 | } else { | 1235 | } else { |
| 1218 | /* register case */ | 1236 | /* register case */ |
| @@ -1244,6 +1262,8 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 25 unmodified lines |
| 1244 | size = -1; | 1262 | size = -1; |
| 1245 | } else if (modifier == 'w') { | 1263 | } else if (modifier == 'w') { |
| 1246 | size = 2; | 1264 | size = 2; |
| | 1265 | } else if (modifier == 'k') { |
| | 1266 | size = 4; |
| 1247 | #ifdef TCC_TARGET_X86_64 | 1267 | #ifdef TCC_TARGET_X86_64 |
| 1248 | } else if (modifier == 'q') { | 1268 | } else if (modifier == 'q') { |
| 1249 | size = 8; | 1269 | size = 8; |
| @@ -1311,7 +1331,8 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, · 61 unmodified lines |
| 1311 | output cases) */ | 1331 | output cases) */ |
| 1312 | SValue sv; | 1332 | SValue sv; |
| 1313 | sv = *op->vt; | 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 | load(op->reg, &sv); | 1336 | load(op->reg, &sv); |
| 1316 | } else if (i >= nb_outputs || op->is_rw) { | 1337 | } else if (i >= nb_outputs || op->is_rw) { |
| 1317 | /* load value in register */ | 1338 | /* load value in register */ |