Commit 2dd358a8 authored by Matthias Braun's avatar Matthias Braun
Browse files

ia32, amd64: Share code to emit immediates.

parent d13cb0a6
......@@ -212,29 +212,6 @@ typedef enum amd64_emit_mod_t {
} amd64_emit_mod_t;
ENUM_BITSET(amd64_emit_mod_t)
static void emit_relocation_no_offset(x86_immediate_kind_t const kind,
ir_entity const *const entity)
{
be_gas_emit_entity(entity);
switch (kind) {
case X86_IMM_ADDR:
case X86_IMM_PCREL:
return;
case X86_IMM_GOTPCREL: be_emit_cstring("@GOTPCREL"); return;
case X86_IMM_PLT: be_emit_cstring("@PLT"); return;
case X86_IMM_VALUE:
case X86_IMM_TLS_IE:
case X86_IMM_TLS_LE:
case X86_IMM_PICBASE_REL:
case X86_IMM_FRAMEENT:
case X86_IMM_FRAMEOFFSET:
case X86_IMM_GOT:
case X86_IMM_GOTOFF:
break;
}
panic("unexpected or invalid immediate kind");
}
static void amd64_emit_immediate64(const amd64_imm64_t *const imm)
{
if (imm->kind == X86_IMM_VALUE) {
......@@ -242,26 +219,11 @@ static void amd64_emit_immediate64(const amd64_imm64_t *const imm)
be_emit_irprintf("0x%" PRIX64, imm->offset);
return;
}
emit_relocation_no_offset(imm->kind, imm->entity);
x86_emit_relocation_no_offset(imm->kind, imm->entity);
if (imm->offset != 0)
be_emit_irprintf("%+" PRId64, imm->offset);
}
static void amd64_emit_immediate32(bool const prefix,
x86_imm32_t const *const imm)
{
if (prefix)
be_emit_char('$');
if (imm->kind == X86_IMM_VALUE) {
assert(imm->entity == NULL);
be_emit_irprintf("%" PRId32, imm->offset);
return;
}
emit_relocation_no_offset(imm->kind, imm->entity);
if (imm->offset != 0)
be_emit_irprintf("%+" PRId32, imm->offset);
}
static void amd64_emit_addr(const ir_node *const node,
const x86_addr_t *const addr)
{
......@@ -273,7 +235,7 @@ static void amd64_emit_addr(const ir_node *const node,
if (entity != NULL) {
assert(addr->immediate.kind != X86_IMM_VALUE);
assert(!is_frame_type(get_entity_owner(entity)));
emit_relocation_no_offset(addr->immediate.kind, entity);
x86_emit_relocation_no_offset(addr->immediate.kind, entity);
if (offset != 0)
be_emit_irprintf("%+" PRId32, offset);
} else if (offset != 0 || variant == X86_ADDR_JUST_IMM) {
......@@ -316,7 +278,8 @@ static void amd64_emit_am(const ir_node *const node, bool indirect_star)
case AMD64_OP_REG_IMM: {
const amd64_binop_addr_attr_t *const binop_attr
= (const amd64_binop_addr_attr_t*)attr;
amd64_emit_immediate32(true, &binop_attr->u.immediate);
be_emit_char('$');
x86_emit_imm32(&binop_attr->u.immediate);
be_emit_cstring(", ");
goto emit_addr_reg;
}
......@@ -339,7 +302,8 @@ static void amd64_emit_am(const ir_node *const node, bool indirect_star)
case AMD64_OP_ADDR_IMM: {
const amd64_binop_addr_attr_t *const binop_attr
= (const amd64_binop_addr_attr_t*)attr;
amd64_emit_immediate32(true, &binop_attr->u.immediate);
be_emit_char('$');
x86_emit_imm32(&binop_attr->u.immediate);
be_emit_cstring(", ");
goto emit_addr;
}
......@@ -368,7 +332,7 @@ emit_addr_reg:
return;
}
case AMD64_OP_IMM32:
amd64_emit_immediate32(false, &attr->addr.immediate);
x86_emit_imm32(&attr->addr.immediate);
return;
case AMD64_OP_X87:
......@@ -725,11 +689,12 @@ static void emit_amd64_asm_operand(ir_node const *const node, char const modifie
return;
}
case ASM_OP_IMMEDIATE: {
amd64_emit_immediate32(modifier != 'c', &op->u.imm32);
case ASM_OP_IMMEDIATE:
if (modifier != 'c')
be_emit_char('$');
x86_emit_imm32(&op->u.imm32);
return;
}
}
panic("invalid asm operand kind");
}
......
......@@ -184,53 +184,14 @@ static void emit_register(const arch_register_t *reg, ir_mode *mode)
be_emit_string(name);
}
static void ia32_emit_relocation(x86_imm32_t const *const imm)
{
ir_entity *entity = imm->entity;
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;
case X86_IMM_GOT: be_emit_cstring("@GOT"); return;
case X86_IMM_GOTOFF: be_emit_cstring("@GOTOFF"); return;
case X86_IMM_PLT: be_emit_cstring("@PLT"); return;
case X86_IMM_PICBASE_REL:
be_emit_char('-');
be_emit_string(pic_base_label);
return;
case X86_IMM_FRAMEENT:
case X86_IMM_FRAMEOFFSET:
case X86_IMM_GOTPCREL:
case X86_IMM_VALUE:
break;
}
panic("Unexpected immediate kind");
}
static void emit_ia32_immediate(bool const prefix, x86_imm32_t const *const imm)
static void emit_ia32_immediate_attr(bool const prefix,
ir_node const *const node)
{
ia32_immediate_attr_t const *const attr
= get_ia32_immediate_attr_const(node);
if (prefix)
be_emit_char('$');
ir_entity const *const entity = imm->entity;
int32_t const offset = imm->offset;
if (entity != NULL) {
assert(imm->kind != X86_IMM_VALUE);
ia32_emit_relocation(imm);
if (offset != 0)
be_emit_irprintf("%+"PRId32, offset);
} else {
assert(imm->kind == X86_IMM_VALUE);
be_emit_irprintf("0x%"PRIX32, (uint32_t)offset);
}
}
static void emit_ia32_immediate_attr(bool const prefix, ir_node const *const node)
{
ia32_immediate_attr_t const *const attr = get_ia32_immediate_attr_const(node);
emit_ia32_immediate(prefix, &attr->imm);
x86_emit_imm32(&attr->imm);
}
static void ia32_emit_mode_suffix_mode(const ir_mode *mode)
......@@ -383,9 +344,7 @@ static void ia32_emit_am(ir_node const *const node)
int32_t const offset = attr->addr.immediate.offset;
ir_entity const *const entity = attr->addr.immediate.entity;
if (entity) {
assert(attr->addr.immediate.kind != X86_IMM_VALUE);
const ia32_attr_t *attr = get_ia32_attr_const(node);
ia32_emit_relocation(&attr->addr.immediate);
x86_emit_relocation_no_offset(attr->addr.immediate.kind, entity);
if (offset != 0)
be_emit_irprintf("%+"PRId32, offset);
} else if (offset != 0 || (!base && !idx)) {
......@@ -1002,7 +961,9 @@ static void emit_ia32_asm_operand(ir_node const *const node, char const modifier
}
case ASM_OP_IMMEDIATE:
emit_ia32_immediate(modifier != 'c', &op->u.imm32);
if (modifier != 'c')
be_emit_char('$');
x86_emit_imm32(&op->u.imm32);
return;
}
panic("invalid asm operand kind");
......@@ -1644,11 +1605,6 @@ static unsigned emit_jit_entity_relocation_asm(char *const buffer,
return 4;
}
x86_imm32_t imm = {
.kind = be_kind,
.entity = entity,
.offset = offset,
};
unsigned res = 4;
if (be_kind == X86_IMM_PCREL) {
/* cheat... */
......@@ -1657,7 +1613,9 @@ static unsigned emit_jit_entity_relocation_asm(char *const buffer,
} else {
be_emit_cstring("\t.long ");
}
ia32_emit_relocation(&imm);
x86_emit_relocation_no_offset(be_kind, entity);
if (offset != 0)
be_emit_irprintf("%+"PRId32, offset);
be_emit_char('\n');
be_emit_write_line();
return res;
......@@ -1689,6 +1647,7 @@ void ia32_emit_function(ir_graph *const irg)
}
get_unique_label(pic_base_label, sizeof(pic_base_label), "PIC_BASE");
x86_pic_base_label = pic_base_label;
if (ia32_cg_config.emit_machcode) {
/* For debugging we can jit the code and output it embedded into a
......
......@@ -13,13 +13,17 @@
#include <inttypes.h>
#include "bediagnostic.h"
#include "begnuas.h"
#include "betranshlp.h"
#include "beemitter.h"
#include "irmode_t.h"
#include "irnode_t.h"
#include "irprintf.h"
#include "panic.h"
#include "tv_t.h"
char const *x86_pic_base_label;
static bool check_immediate_constraint(long val, char immediate_constraint_type)
{
/* Workaround for warning about always true comparison when long has 32 bits. */
......@@ -114,3 +118,48 @@ void x86_dump_imm32(x86_imm32_t const *const imm, FILE *const F)
if (imm->kind != X86_IMM_VALUE && imm->kind != X86_IMM_ADDR)
fprintf(F, " [%s]", x86_get_immediate_kind_str(imm->kind));
}
void x86_emit_relocation_no_offset(x86_immediate_kind_t const kind,
ir_entity const *const entity)
{
be_gas_emit_entity(entity);
switch (kind) {
case X86_IMM_ADDR:
case X86_IMM_PCREL:
return;
case X86_IMM_PICBASE_REL:
be_emit_char('-');
be_emit_string(x86_pic_base_label);
return;
char const *rstr;
case X86_IMM_GOTPCREL: rstr = "@GOTPCREL"; goto emit_str;
case X86_IMM_PLT: rstr = "@PLT"; goto emit_str;
case X86_IMM_TLS_IE: rstr = "@INDNTPOFF"; goto emit_str;
case X86_IMM_TLS_LE: rstr = "@NTPOFF"; goto emit_str;
case X86_IMM_GOT: rstr = "@GOT"; goto emit_str;
case X86_IMM_GOTOFF: rstr = "@GOTOFF"; goto emit_str;
emit_str:
be_emit_string(rstr);
return;
case X86_IMM_VALUE:
case X86_IMM_FRAMEENT:
case X86_IMM_FRAMEOFFSET:
break;
}
panic("unexpected or invalid immediate kind");
}
void x86_emit_imm32(x86_imm32_t const *const imm)
{
x86_immediate_kind_t const kind = imm->kind;
int32_t const offset = imm->offset;
if (kind == X86_IMM_VALUE) {
assert(imm->entity == NULL);
be_emit_irprintf("%"PRId32, (uint32_t)offset);
} else {
x86_emit_relocation_no_offset(kind, imm->entity);
if (offset != 0)
be_emit_irprintf("%+"PRId32, offset);
}
}
......@@ -17,6 +17,8 @@
#include "compiler.h"
#include "firm_types.h"
extern char const *x86_pic_base_label;
/** immediate/relocation types (see also ELF file format) */
typedef enum x86_immediate_kind_t {
X86_IMM_VALUE, /**< no relocation, just a value */
......@@ -49,6 +51,10 @@ char const *x86_get_immediate_kind_str(x86_immediate_kind_t const kind);
void x86_dump_imm32(x86_imm32_t const *imm, FILE *F);
void x86_emit_imm32(x86_imm32_t const *imm);
void x86_emit_relocation_no_offset(x86_immediate_kind_t kind,
ir_entity const *entity);
static inline bool x86_imm32_equal(x86_imm32_t const *const imm0,
x86_imm32_t const *const imm1)
{
......
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