Commit 672a3898 authored by Matthias Braun's avatar Matthias Braun
Browse files

ia32: Introduce X86_IMM_PCREL

Calls+Jumps really use PC relative addresses even if they look the same
in the assembler. Create an immediate kind for that, this allows a
slightly simpler bemit_entity().
parent 6e196911
......@@ -205,7 +205,9 @@ static void emit_relocation_no_offset(x86_immediate_kind_t const kind,
{
be_gas_emit_entity(entity);
switch (kind) {
case X86_IMM_ADDR: return;
case X86_IMM_ADDR:
case X86_IMM_PCREL:
return;
case X86_IMM_GOTPCREL: be_emit_cstring("@GOTPCREL"); return;
case X86_IMM_VALUE:
case X86_IMM_TLS_IE:
......
......@@ -182,6 +182,7 @@ static void ia32_emit_relocation(x86_imm32_t const *const imm)
be_gas_emit_entity(entity);
switch (imm->kind) {
case X86_IMM_ADDR:
case X86_IMM_PCREL:
return;
case X86_IMM_TLS_IE: be_emit_cstring("@INDNTPOFF"); return;
case X86_IMM_TLS_LE: be_emit_cstring("@NTPOFF"); return;
......@@ -1684,7 +1685,7 @@ static void bemit32(const uint32_t u32)
* Emit address of an entity. If @p is_relative is true then a relative
* offset from behind the address to the entity is created.
*/
static void bemit_entity(x86_imm32_t const *const imm, bool is_relative)
static void bemit_entity(x86_imm32_t const *const imm)
{
ir_entity *entity = imm->entity;
int32_t offset = imm->offset;
......@@ -1696,23 +1697,14 @@ static void bemit_entity(x86_imm32_t const *const imm, bool is_relative)
/* the final version should remember the position in the bytestream
and patch it with the correct address at linktime... */
be_emit_cstring("\t.long ");
be_gas_emit_entity(entity);
if (is_tls_entity(entity)) {
if (!entity_has_definition(entity)) {
be_emit_cstring("@INDNTPOFF");
} else {
be_emit_cstring("@NTPOFF");
}
}
if (is_relative) {
if (imm->kind == X86_IMM_PCREL) {
be_gas_emit_entity(entity);
be_emit_cstring("-.");
offset -= 4;
}
if (offset != 0) {
be_emit_irprintf("%+"PRId32, offset);
} else {
ia32_emit_relocation(imm);
}
be_emit_char('\n');
be_emit_write_line();
......@@ -1860,7 +1852,7 @@ static void bemit_mod_am(unsigned reg, const ir_node *node)
if (emitoffs == 8) {
bemit8((unsigned) offset);
} else if (emitoffs == 32) {
bemit_entity(&attr->am_imm, false);
bemit_entity(&attr->am_imm);
}
}
......@@ -1899,10 +1891,10 @@ static void bemit_0f_unop_reg(ir_node const *const node, unsigned char const cod
bemit_unop_reg(node, code, input);
}
static void bemit_imm32(ir_node const *const node, bool const relative)
static void bemit_imm32(ir_node const *const node)
{
const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node);
bemit_entity(&attr->imm, relative);
bemit_entity(&attr->imm);
}
static void bemit_imm(ia32_immediate_attr_t const *const attr,
......@@ -1911,7 +1903,7 @@ static void bemit_imm(ia32_immediate_attr_t const *const attr,
switch (size) {
case 8: bemit8(attr->imm.offset); break;
case 16: bemit16(attr->imm.offset); break;
case 32: bemit_entity(&attr->imm, false); break;
case 32: bemit_entity(&attr->imm); break;
}
}
......@@ -1981,7 +1973,7 @@ static void bemit_mov_const(const ir_node *node)
{
arch_register_t const *const out = arch_get_irn_register_out(node, pn_ia32_Const_res);
bemit8(0xB8 + out->encoding);
bemit_imm32(node, false);
bemit_imm32(node);
}
static bool use_eax_short_form(ir_node const *const node)
......@@ -2488,7 +2480,7 @@ static void bemit_load(const ir_node *node)
as 0xA1 [offset] */
bemit8(0xA1);
ia32_attr_t const *const attr = get_ia32_attr_const(node);
bemit_entity(&attr->am_imm, false);
bemit_entity(&attr->am_imm);
return;
}
}
......@@ -2527,7 +2519,7 @@ static void bemit_store(const ir_node *node)
bemit8(0xA3);
}
ia32_attr_t const *const attr = get_ia32_attr_const(node);
bemit_entity(&attr->am_imm, false);
bemit_entity(&attr->am_imm);
return;
}
}
......@@ -2601,7 +2593,7 @@ static void bemit_call(const ir_node *node)
if (is_ia32_Immediate(proc)) {
bemit8(0xE8);
bemit_imm32(proc, true);
bemit_imm32(proc);
} else {
bemit_unop(node, 0xFF, 2, n_ia32_Call_addr);
}
......
......@@ -4396,6 +4396,15 @@ static ir_node *gen_Jmp(ir_node *node)
return new_node;
}
static void adjust_pc_relative_relocation(ir_node *node)
{
if (!is_ia32_Immediate(node))
return;
ia32_immediate_attr_t *attr = get_ia32_immediate_attr(node);
if (attr->imm.kind == X86_IMM_ADDR)
attr->imm.kind = X86_IMM_PCREL;
}
/**
* Transform IJmp
*/
......@@ -4408,6 +4417,7 @@ static ir_node *gen_IJmp(ir_node *node)
ia32_address_mode_t am;
match_arguments(&am, block, NULL, op, NULL,
match_am | match_immediate | match_upconv);
adjust_pc_relative_relocation(am.new_op2);
x86_address_t *addr = &am.addr;
dbg_info *dbgi = get_irn_dbg_info(node);
......@@ -4936,7 +4946,9 @@ static ir_node *gen_Call(ir_node *node)
ir_node *const old_block = get_nodes_block(node);
ir_node *const callee = get_Call_ptr(node);
ir_node *const mem = get_Call_mem(node);
match_arguments(&am, old_block, NULL, callee, mem, match_am | match_immediate | match_upconv);
match_arguments(&am, old_block, NULL, callee, mem,
match_am | match_immediate | match_upconv);
adjust_pc_relative_relocation(am.new_op2);
ir_type *const type = get_Call_type(node);
x86_cconv_t *const cconv = ia32_decide_calling_convention(type, NULL);
......
......@@ -84,6 +84,7 @@ char const *x86_get_immediate_kind_str(x86_immediate_kind_t const kind)
switch (kind) {
case X86_IMM_VALUE: return "value";
case X86_IMM_ADDR: return "addr";
case X86_IMM_PCREL: return "pcrel";
case X86_IMM_PICBASE_REL: return "picbase_rel";
case X86_IMM_TLS_IE: return "tls_ie";
case X86_IMM_TLS_LE: return "tls_le";
......
......@@ -21,11 +21,12 @@
typedef enum x86_immediate_kind_t {
X86_IMM_VALUE, /**< no relocation, just a value */
X86_IMM_ADDR, /**< "normal" absolute addresses to a symbol */
X86_IMM_PCREL, /**< PC relative address */
X86_IMM_PICBASE_REL, /**< relative to pic base address */
X86_IMM_TLS_IE, /**< thread local storage, initial exec */
X86_IMM_TLS_LE, /**< thread local storage, load exec */
X86_IMM_FRAMEOFFSET, /**< offset to entity on stackframe */
X86_IMM_GOTPCREL, /**< global offset table entry PIC relative (elf64) */
X86_IMM_GOTPCREL, /**< global offset table entry PC relative (elf64) */
X86_IMM_GOTOFF, /**< address relative to global offset table */
X86_IMM_GOT, /**< global offset table entry offset */
X86_IMM_PLT, /**< address to entry in procedure linkage table */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment