#include "irargs_t.h"
#include "irprog_t.h"
#include "iredges_t.h"
+#include "irtools.h"
#include "execfreq.h"
#include "error.h"
#include "raw_bitset.h"
#include "dbginfo.h"
+#include "lc_opts.h"
-#include "../besched_t.h"
+#include "../besched.h"
#include "../benode_t.h"
#include "../beabi.h"
#include "../be_dbgout.h"
#include "../beemitter.h"
#include "../begnuas.h"
-#include "../beirg_t.h"
+#include "../beirg.h"
#include "../be_dbgout.h"
#include "ia32_emitter.h"
static const ia32_isa_t *isa;
static ia32_code_gen_t *cg;
-static int do_pic;
static char pic_base_label[128];
static ir_label_t exc_label_id;
static int mark_spill_reload = 0;
+static int do_pic;
/** Return the next block in Block schedule */
static ir_node *get_prev_block_sched(const ir_node *block)
int need_label = 1;
int n_cfgpreds = get_Block_n_cfgpreds(block);
+ if (has_Block_entity(block))
+ return 1;
+
if (n_cfgpreds == 0) {
need_label = 0;
} else if (n_cfgpreds == 1) {
* |_| |_|
*************************************************************/
+/**
+ * Emit the name of the 8bit low register
+ */
static void emit_8bit_register(const arch_register_t *reg)
{
const char *reg_name = arch_register_get_name(reg);
be_emit_char('l');
}
+/**
+ * Emit the name of the 8bit high register
+ */
+static void emit_8bit_register_high(const arch_register_t *reg)
+{
+ const char *reg_name = arch_register_get_name(reg);
+
+ be_emit_char('%');
+ be_emit_char(reg_name[1]);
+ be_emit_char('h');
+}
+
static void emit_16bit_register(const arch_register_t *reg)
{
const char *reg_name = ia32_get_mapped_reg_name(isa->regs_16bit, reg);
be_emit_string(reg_name);
}
+/**
+ * emit a register, possible shortened by a mode
+ *
+ * @param reg the register
+ * @param mode the mode of the register or NULL for full register
+ */
static void emit_register(const arch_register_t *reg, const ir_mode *mode)
{
const char *reg_name;
static void ia32_emit_entity(ir_entity *entity, int no_pic_adjust)
{
- ident *id;
-
set_entity_backend_marked(entity, 1);
- id = get_entity_ld_ident(entity);
- be_emit_ident(id);
+ be_gas_emit_entity(entity);
if (get_entity_owner(entity) == get_tls_type()) {
if (get_entity_visibility(entity) == visibility_external_allocated) {
}
}
- if (!no_pic_adjust && do_pic) {
- /* TODO: only do this when necessary */
+ if (do_pic && !no_pic_adjust) {
be_emit_char('-');
be_emit_string(pic_base_label);
}
if (attr->symconst != NULL) {
if (attr->sc_sign)
be_emit_char('-');
- ia32_emit_entity(attr->symconst, 0);
+ ia32_emit_entity(attr->symconst, attr->no_pic_adjust);
}
if (attr->symconst == NULL || attr->offset != 0) {
if (attr->symconst != NULL) {
void ia32_emit_8bit_source_register_or_immediate(const ir_node *node, int pos)
{
const arch_register_t *reg;
- ir_node *in = get_irn_n(node, pos);
+ const ir_node *in = get_irn_n(node, pos);
if (is_ia32_Immediate(in)) {
emit_ia32_Immediate(in);
return;
emit_8bit_register(reg);
}
+void ia32_emit_8bit_high_source_register(const ir_node *node, int pos)
+{
+ const arch_register_t *reg = get_in_reg(node, pos);
+ emit_8bit_register_high(reg);
+}
+
+void ia32_emit_16bit_source_register_or_immediate(const ir_node *node, int pos)
+{
+ const arch_register_t *reg;
+ const ir_node *in = get_irn_n(node, pos);
+ if (is_ia32_Immediate(in)) {
+ emit_ia32_Immediate(in);
+ return;
+ }
+
+ reg = get_in_reg(node, pos);
+ emit_16bit_register(reg);
+}
+
void ia32_emit_dest_register(const ir_node *node, int pos)
{
const arch_register_t *reg = get_out_reg(node, pos);
emit_register(reg, NULL);
}
+void ia32_emit_dest_register_size(const ir_node *node, int pos)
+{
+ const arch_register_t *reg = get_out_reg(node, pos);
+
+ emit_register(reg, get_ia32_ls_mode(node));
+}
+
void ia32_emit_8bit_dest_register(const ir_node *node, int pos)
{
const arch_register_t *reg = get_out_reg(node, pos);
*/
static void ia32_emit_block_name(const ir_node *block)
{
- if (has_Block_label(block)) {
- be_emit_string(be_gas_block_label_prefix());
- be_emit_irprintf("%lu", get_Block_label(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));
NULL /* always true */
};
+/**
+ * Emit the suffix for a compare instruction.
+ */
static void ia32_emit_cmp_suffix(int pnc)
{
const char *str;
EMIT_LONG = 1U << 2
} ia32_emit_mod_t;
+/**
+ * Emits address mode.
+ */
+void ia32_emit_am(const ir_node *node)
+{
+ ir_entity *ent = get_ia32_am_sc(node);
+ int offs = get_ia32_am_offs_int(node);
+ ir_node *base = get_irn_n(node, n_ia32_base);
+ int has_base = !is_ia32_NoReg_GP(base);
+ ir_node *index = get_irn_n(node, n_ia32_index);
+ int has_index = !is_ia32_NoReg_GP(index);
+
+ /* just to be sure... */
+ assert(!is_ia32_use_frame(node) || get_ia32_frame_ent(node) != NULL);
+
+ /* emit offset */
+ if (ent != NULL) {
+ const ia32_attr_t *attr = get_ia32_attr_const(node);
+ if (is_ia32_am_sc_sign(node))
+ be_emit_char('-');
+ ia32_emit_entity(ent, attr->data.am_sc_no_pic_adjust);
+ }
+
+ /* also handle special case if nothing is set */
+ if (offs != 0 || (ent == NULL && !has_base && !has_index)) {
+ if (ent != NULL) {
+ be_emit_irprintf("%+d", offs);
+ } else {
+ be_emit_irprintf("%d", offs);
+ }
+ }
+
+ if (has_base || has_index) {
+ be_emit_char('(');
+
+ /* emit base */
+ if (has_base) {
+ const arch_register_t *reg = get_in_reg(node, n_ia32_base);
+ emit_register(reg, NULL);
+ }
+
+ /* emit index + scale */
+ if (has_index) {
+ const arch_register_t *reg = get_in_reg(node, n_ia32_index);
+ int scale;
+ be_emit_char(',');
+ emit_register(reg, NULL);
+
+ scale = get_ia32_am_scale(node);
+ if (scale > 0) {
+ be_emit_irprintf(",%d", 1 << scale);
+ }
+ }
+ be_emit_char(')');
+ }
+}
+
/**
* fmt parameter output
* ---- ---------------------- ---------------------------------------------
case 'M':
if (mod & EMIT_ALTERNATE_AM)
be_emit_char('*');
+
ia32_emit_am(node);
break;
ia32_emitf(node, fmt);
}
-/**
- * Emits address mode.
- */
-void ia32_emit_am(const ir_node *node)
-{
- ir_entity *ent = get_ia32_am_sc(node);
- int offs = get_ia32_am_offs_int(node);
- ir_node *base = get_irn_n(node, n_ia32_base);
- int has_base = !is_ia32_NoReg_GP(base);
- ir_node *index = get_irn_n(node, n_ia32_index);
- int has_index = !is_ia32_NoReg_GP(index);
-
- /* just to be sure... */
- assert(!is_ia32_use_frame(node) || get_ia32_frame_ent(node) != NULL);
-
- /* emit offset */
- if (ent != NULL) {
- if (is_ia32_am_sc_sign(node))
- be_emit_char('-');
- ia32_emit_entity(ent, 0);
- }
-
- /* also handle special case if nothing is set */
- if (offs != 0 || (ent == NULL && !has_base && !has_index)) {
- if (ent != NULL) {
- be_emit_irprintf("%+d", offs);
- } else {
- be_emit_irprintf("%d", offs);
- }
- }
-
- if (has_base || has_index) {
- be_emit_char('(');
-
- /* emit base */
- if (has_base) {
- const arch_register_t *reg = get_in_reg(node, n_ia32_base);
- emit_register(reg, NULL);
- }
-
- /* emit index + scale */
- if (has_index) {
- const arch_register_t *reg = get_in_reg(node, n_ia32_index);
- int scale;
- be_emit_char(',');
- emit_register(reg, NULL);
-
- scale = get_ia32_am_scale(node);
- if (scale > 0) {
- be_emit_irprintf(",%d", 1 << scale);
- }
- }
- be_emit_char(')');
- }
-}
-
static void emit_ia32_IMul(const ir_node *node)
{
ir_node *left = get_irn_n(node, n_ia32_IMul_left);
}
}
- if (need_label || has_Block_label(block)) {
+ if (need_label) {
ia32_emit_block_name(block);
be_emit_char(':');