* @brief This file implements the ia32 node emitter.
* @author Christian Wuerdig, Matthias Braun
* @version $Id$
+ *
+ * Summary table for x86 floatingpoint compares:
+ * pnc_Eq => !P && E
+ * pnc_Lt => !P && B
+ * pnc_Le => !P && BE
+ * pnc_Gt => A
+ * pnc_Ge => AE
+ * pnc_Lg => P || NE
+ * pnc_Leg => NP (ordered)
+ * pnc_Uo => P
+ * pnc_Ue => E
+ * pnc_Ul => B
+ * pnc_Ule => BE
+ * pnc_Ug => P || A
+ * pnc_Uge => P || AE
+ * pnc_Ne => NE
*/
#include "config.h"
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
-#define BLOCK_PREFIX ".L"
-
#define SNPRINTF_BUF_LEN 128
static const ia32_isa_t *isa;
static char *get_unique_label(char *buf, size_t buflen, const char *prefix)
{
static unsigned long id = 0;
- snprintf(buf, buflen, "%s%lu", prefix, ++id);
+ snprintf(buf, buflen, "%s%s%lu", be_gas_get_private_prefix(), prefix, ++id);
return buf;
}
static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust)
{
- set_entity_backend_marked(entity, 1);
be_gas_emit_entity(entity);
if (get_entity_owner(entity) == get_tls_type()) {
- if (get_entity_visibility(entity) == visibility_external_allocated) {
+ if (get_entity_visibility(entity) == ir_visibility_external) {
be_emit_cstring("@INDNTPOFF");
} else {
be_emit_cstring("@NTPOFF");
if (mode_is_float(mode)) {
switch (get_mode_size_bits(mode)) {
- case 32: be_emit_char('s'); return;
- case 64: be_emit_char('l'); return;
- case 80:
- case 96: be_emit_char('t'); return;
+ case 32: be_emit_char('s'); return;
+ case 64: be_emit_char('l'); return;
+ /* long doubles have different sizes due to alignment on different
+ * platforms. */
+ case 80:
+ case 96:
+ case 128: be_emit_char('t'); return;
}
} else {
assert(mode_is_int(mode));
static char get_xmm_mode_suffix(ir_mode *mode)
{
assert(mode_is_float(mode));
- switch(get_mode_size_bits(mode)) {
+ switch (get_mode_size_bits(mode)) {
case 32: return 's';
case 64: return 'd';
default: panic("Invalid XMM mode");
return get_irn_link(irn);
}
-/**
- * Emits a block label for the given block.
- */
-static void ia32_emit_block_name(const ir_node *block)
-{
- if (has_Block_entity(block)) {
- ir_entity *entity = get_Block_entity(block);
- be_gas_emit_entity(entity);
- } else {
- be_emit_cstring(BLOCK_PREFIX);
- be_emit_irprintf("%ld", get_irn_node_nr(block));
- }
-}
-
/**
* Emits the target label for a control flow node.
*/
static void ia32_emit_cfop_target(const ir_node *node)
{
ir_node *block = get_cfop_target_block(node);
- ia32_emit_block_name(block);
+ be_gas_emit_block_name(block);
}
/*
break;
++fmt;
- while (1) {
- switch(*fmt) {
+ for (;;) {
+ switch (*fmt) {
case '*': mod |= EMIT_ALTERNATE_AM; break;
case '#': mod |= EMIT_RESPECT_LS; break;
case 'l': mod |= EMIT_LONG; break;
break;
case 'R': {
+ const arch_register_t *reg = va_arg(ap, const arch_register_t*);
if (get_ia32_op_type(node) == ia32_AddrModeS) {
goto emit_AM;
} else {
- const arch_register_t *reg = va_arg(ap, const arch_register_t*);
if (mod & EMIT_ALTERNATE_AM)
be_emit_char('*');
emit_register(reg, NULL);
*/
void ia32_emit_x87_binop(const ir_node *node)
{
- switch(get_ia32_op_type(node)) {
+ switch (get_ia32_op_type(node)) {
case ia32_Normal:
{
const ia32_x87_attr_t *x87_attr = get_ia32_x87_attr_const(node);
return get_negated_pnc(pnc, mode);
}
-void ia32_emit_cmp_suffix_node(const ir_node *node,
- int flags_pos)
+void ia32_emit_cmp_suffix_node(const ir_node *node, int flags_pos)
{
- const ia32_attr_t *attr = get_ia32_attr_const(node);
-
pn_Cmp pnc = get_ia32_condcode(node);
-
pnc = determine_final_pnc(node, flags_pos, pnc);
- if (attr->data.ins_permuted)
- pnc = ia32_get_negated_pnc(pnc);
ia32_emit_cmp_suffix(pnc);
}
pnc = determine_final_pnc(node, n_ia32_CMovcc_eflags, pnc);
/* although you can't set ins_permuted in the constructor it might still
- be set by memory operand folding */
+ * be set by memory operand folding
+ * Permuting inputs of a cmov means the condition is negated!
+ */
if (attr->data.ins_permuted)
pnc = ia32_get_negated_pnc(pnc);
const ir_edge_t *edge;
/* fill the table structure */
- get_unique_label(tbl->label, SNPRINTF_BUF_LEN, ".TBL_");
+ get_unique_label(tbl->label, SNPRINTF_BUF_LEN, "TBL_");
tbl->defProj = NULL;
tbl->num_branches = get_irn_n_edges(node) - 1;
tbl->branches = XMALLOCNZ(branch_t, tbl->num_branches);
c = *(++s);
/* parse modifiers */
- switch(c) {
+ switch (c) {
case 0:
ir_fprintf(stderr, "Warning: asm text (%+F) ends with %%\n", node);
be_emit_char('%');
/* emit it */
if (modifier != 0) {
be_emit_char('%');
- switch(modifier) {
+ switch (modifier) {
case 'b':
reg_name = ia32_get_mapped_reg_name(isa->regs_8bit, reg);
break;
if (s[0] != '\t')
be_emit_char('\t');
- while(*s != 0) {
+ while (*s != 0) {
if (*s == '%') {
s = emit_asm_operand(node, s);
} else {
static inline bool is_unknown_reg(const arch_register_t *reg)
{
- if(reg == &ia32_gp_regs[REG_GP_UKNWN]
+ if (reg == &ia32_gp_regs[REG_GP_UKNWN]
|| reg == &ia32_xmm_regs[REG_XMM_UKNWN]
|| reg == &ia32_vfp_regs[REG_VFP_UKNWN])
return true;
ia32_emitf(node, "\tmovl %S0, %D0\n");
ia32_emitf(node, "\tmovl $%u, %S1\n", attr->count);
- ia32_emitf(NULL, BLOCK_PREFIX "%ld:\n", get_irn_node_nr(node));
+ be_gas_emit_block_name(node);
+ be_emit_cstring(":\n");
+ be_emit_write_line();
ia32_emitf(node, "\tmovl (%D0), %D0\n");
ia32_emitf(node, "\tdec %S1\n");
- ia32_emitf(node, "\tjnz " BLOCK_PREFIX "%ld\n", get_irn_node_nr(node));
+ be_emit_cstring("\tjnz ");
+ be_gas_emit_block_name(node);
+ be_emit_finish_line_gas(node);
}
static void emit_be_Return(const ir_node *node)
return 0;
n_cfgpreds = get_Block_n_cfgpreds(block);
- for(i = 0; i < n_cfgpreds; ++i) {
+ for (i = 0; i < n_cfgpreds; ++i) {
const ir_node *pred = get_Block_cfgpred_block(block, i);
double pred_freq = get_block_execfreq(exec_freq, pred);
}
if (need_label) {
- ia32_emit_block_name(block);
+ be_gas_emit_block_name(block);
be_emit_char(':');
be_emit_pad_comment();
be_emit_cstring(" /* ");
} else {
be_emit_cstring("\t/* ");
- ia32_emit_block_name(block);
+ be_gas_emit_block_name(block);
be_emit_cstring(": ");
}
isa = cg->isa;
do_pic = cg->birg->main_env->options->pic;
+ be_gas_elf_type_char = '@';
+
ia32_register_emitters();
- get_unique_label(pic_base_label, sizeof(pic_base_label), ".PIC_BASE");
+ get_unique_label(pic_base_label, sizeof(pic_base_label), "PIC_BASE");
be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi));
be_gas_emit_function_prolog(entity, ia32_cg_config.function_alignment);
ia32_emit_exc_label(exc_list[i].exc_instr);
be_emit_char('\n');
be_emit_cstring("\t.long ");
- ia32_emit_block_name(exc_list[i].block);
+ be_gas_emit_block_name(exc_list[i].block);
be_emit_char('\n');
}
}
be_emit_cstring("\t.long ");
if (entity_sign)
be_emit_char('-');
- set_entity_backend_marked(entity, 1);
be_gas_emit_entity(entity);
if (get_entity_owner(entity) == get_tls_type()) {
- if (get_entity_visibility(entity) == visibility_external_allocated) {
+ if (get_entity_visibility(entity) == ir_visibility_external) {
be_emit_cstring("@INDNTPOFF");
} else {
be_emit_cstring("@NTPOFF");
static void bemit_jmp_destination(const ir_node *dest_block)
{
be_emit_cstring("\t.long ");
- ia32_emit_block_name(dest_block);
+ be_gas_emit_block_name(dest_block);
be_emit_cstring(" - . - 4\n");
be_emit_write_line();
}