- add builtin_(trap|bswap)
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Tue, 23 Dec 2008 22:30:31 +0000 (22:30 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Tue, 23 Dec 2008 22:30:31 +0000 (22:30 +0000)
[r24882]

include/libfirm/firm_types.h
ir/be/ia32/ia32_architecture.c
ir/be/ia32/ia32_architecture.h
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_emitter.h
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c
ir/ir/irnode.c

index 734e0f2..70b4491 100644 (file)
@@ -220,6 +220,7 @@ typedef struct {
 /** Supported libFirm builtins. */
 /** Supported libFirm builtins. */
 typedef enum {
+       ir_bk_trap,                   /**< GCC __builtin_trap(): insert debug break */
        ir_bk_return_address,         /**< GCC __builtin_return_address() */
        ir_bk_frame_addess,           /**< GCC __builtin_frame_address() */
        ir_bk_prefetch,               /**< GCC __builtin_prefetch() */
@@ -228,6 +229,7 @@ typedef enum {
        ir_bk_ctz,                    /**< GCC __builtin_ctz(): count trailing zero */
        ir_bk_popcount,               /**< GCC __builtin_popcount(): population count */
        ir_bk_parity,                 /**< GCC __builtin_parity(): parity */
+       ir_bk_bswap,                  /**< byte swap */
 } ir_builtin_kind;
 
 #endif
index 351aebb..2d48a44 100644 (file)
@@ -509,6 +509,7 @@ void ia32_setup_cg_config(void)
        c->use_sse_prefetch     = FLAGS(arch, (arch_feature_3DNowE | arch_feature_sse1));
        c->use_3dnow_prefetch   = FLAGS(arch, arch_feature_3DNow);
        c->use_popcnt           = FLAGS(arch, (arch_feature_sse4_2 | arch_feature_sse4a));
+       c->use_i486             = (arch & arch_mask) >= arch_i486;
        c->optimize_cc          = opt_cc;
        c->use_unsafe_floatconv = opt_unsafe_floatconv;
 
index c494490..a88776f 100644 (file)
@@ -78,6 +78,8 @@ typedef struct {
        unsigned use_3dnow_prefetch:1;
        /** use SSE4.2 or SSE4a popcnt instruction */
        unsigned use_popcnt:1;
+       /** use i486 instructions */
+       unsigned use_i486:1;
        /** optimize calling convention where possible */
        unsigned optimize_cc:1;
        /**
index 2008d3a..9086f41 100644 (file)
@@ -211,6 +211,9 @@ static char *get_unique_label(char *buf, size_t buflen, const char *prefix)
  * |_|                                       |_|
  *************************************************************/
 
+/**
+ * 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);
@@ -220,6 +223,18 @@ static void emit_8bit_register(const arch_register_t *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);
@@ -304,7 +319,7 @@ static void emit_ia32_Immediate(const ir_node *node)
 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;
@@ -314,6 +329,13 @@ void ia32_emit_8bit_source_register_or_immediate(const ir_node *node, int pos)
        emit_8bit_register(reg);
 }
 
+void ia32_emit_8bit_high_source_register(const ir_node *node, int pos)
+{
+       const ir_node         *in = get_irn_n(node, pos);
+       const arch_register_t *reg = get_in_reg(node, pos);
+       emit_8bit_register_high(reg);
+}
+
 void ia32_emit_dest_register(const ir_node *node, int pos)
 {
        const arch_register_t *reg  = get_out_reg(node, pos);
index 477fe55..fc16668 100644 (file)
@@ -38,6 +38,7 @@ void ia32_emit_8bit_dest_register(const ir_node *node, int pos);
 void ia32_emit_x87_register(const ir_node *node, int pos);
 void ia32_emit_source_register_or_immediate(const ir_node *node, int pos);
 void ia32_emit_8bit_source_register_or_immediate(const ir_node *node, int pos);
+void ia32_emit_8bit_high_source_register(const ir_node *node, int pos);
 void ia32_emit_mode_suffix(const ir_node *node);
 void ia32_emit_x87_mode_suffix(const ir_node *node);
 void ia32_emit_xmm_mode_suffix(const ir_node *node);
@@ -53,5 +54,4 @@ void ia32_gen_routine(ia32_code_gen_t *cg, ir_graph *irg);
 
 /** Initializes the Emitter. */
 void ia32_init_emitter(void);
-
 #endif
index 8c78963..2ccf12d 100644 (file)
@@ -197,9 +197,11 @@ $arch = "ia32";
        S1 => "${arch}_emit_source_register(node, 1);",
        S2 => "${arch}_emit_source_register(node, 2);",
        S3 => "${arch}_emit_source_register(node, 3);",
+       SB0 => "${arch}_emit_8bit_source_register_or_immediate(node, 0);",
        SB1 => "${arch}_emit_8bit_source_register_or_immediate(node, 1);",
        SB2 => "${arch}_emit_8bit_source_register_or_immediate(node, 2);",
        SB3 => "${arch}_emit_8bit_source_register_or_immediate(node, 3);",
+       SH0 => "${arch}_emit_8bit_high_source_register(node, 0);",
        SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
        SI3 => "${arch}_emit_source_register_or_immediate(node, 3);",
        D0 => "${arch}_emit_dest_register(node, 0);",
@@ -1568,6 +1570,47 @@ ClimbFrame => {
        mode      => $mode_gp
 },
 
+#
+# bswap
+#
+Bswap => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp" ],
+                      out => [ "in_r1" ] },
+       emit      => '. bswap%M %S0',
+       ins       => [ "val" ],
+       units     => [ "GP" ],
+       latency   => 1,
+       mode      => $mode_gp,
+},
+
+#
+# bswap16, use xchg here
+#
+Bswap16 => {
+       irn_flags => "R",
+       reg_req   => { in => [ "eax ebx ecx edx" ],
+                      out => [ "in_r1" ] },
+       emit      => '. xchg %SB0, %SH0',
+       ins       => [ "val" ],
+       units     => [ "GP" ],
+       latency   => 1,
+       mode      => $mode_gp,
+},
+
+#
+# BreakPoint
+#
+Breakpoint => {
+       state     => "pinned",
+       reg_req   => { in => [ "none" ], out => [ "none" ] },
+       ins       => [ "mem" ],
+       latency   => 0,
+       emit      => ". int3",
+       units     => [ "GP" ],
+       mode      => mode_M,
+},
+
 #
 # Intel style prefetching
 #
index bb475cc..684d250 100644 (file)
@@ -4518,6 +4518,17 @@ static ir_node *gen_be_Call(ir_node *node)
        return call;
 }
 
+/**
+ * Transform Builtin trap
+ */
+static ir_node *gen_trap(ir_node *node) {
+       dbg_info *dbgi  = get_irn_dbg_info(node);
+       ir_node *block  = be_transform_node(get_nodes_block(node));
+       ir_node *mem    = be_transform_node(get_Builtin_mem(node));
+
+       return new_bd_ia32_Breakpoint(dbgi, block, mem);
+}
+
 /**
  * Transform Builtin return_address
  */
@@ -4697,7 +4708,7 @@ static ir_node *gen_prefetch(ir_node *node) {
 }
 
 /**
- * Transform ...
+ * Transform bsf like node
  */
 static ir_node *gen_unop_AM(ir_node *node, construct_binop_dest_func *func)
 {
@@ -4928,6 +4939,51 @@ static ir_node *gen_popcount(ir_node *node) {
        return new_bd_ia32_Lea(dbgi, new_block, m13, s5);
 }
 
+/**
+ * Transform builtin byte swap.
+ */
+static ir_node *gen_bswap(ir_node *node) {
+       ir_node *param     = be_transform_node(get_Builtin_param(node, 0));
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+
+       ir_node *block     = get_nodes_block(node);
+       ir_node *new_block = be_transform_node(block);
+       ir_mode *mode      = get_irn_mode(param);
+       unsigned size      = get_mode_size_bits(mode);
+       ir_node  *m1, *m2, *m3, *m4, *s1, *s2, *s3, *s4, *noreg, *nomem;
+
+       switch (size) {
+       case 32:
+               if (ia32_cg_config.use_i486) {
+                       /* swap available */
+                       return new_bd_ia32_Bswap(dbgi, new_block, param);
+               }
+               s1 = new_bd_ia32_Shl(dbgi, new_block, param, create_Immediate(NULL, 0, 24));
+               s2 = new_bd_ia32_Shl(dbgi, new_block, param, create_Immediate(NULL, 0, 8));
+
+               noreg = ia32_new_NoReg_gp(env_cg);
+               nomem = new_NoMem();
+
+               m1 = new_bd_ia32_And(dbgi, new_block, noreg, noreg, nomem, s2, create_Immediate(NULL, 0, 0xFF00));
+               m2 = new_bd_ia32_Lea(dbgi, new_block, s1, m1);
+
+               s3 = new_bd_ia32_Shr(dbgi, new_block, param, create_Immediate(NULL, 0, 8));
+
+               m3 = new_bd_ia32_And(dbgi, new_block, noreg, noreg, nomem, s3, create_Immediate(NULL, 0, 0xFF0000));
+               m4 = new_bd_ia32_Lea(dbgi, new_block, m2, m3);
+
+               s4 = new_bd_ia32_Shr(dbgi, new_block, param, create_Immediate(NULL, 0, 24));
+               return new_bd_ia32_Lea(dbgi, new_block, m4, s4);
+
+       case 16:
+               /* swap16 always available */
+               return new_bd_ia32_Bswap16(dbgi, new_block, param);
+
+       default:
+               panic("Invalid bswap size (%d)", size);
+       }
+}
+
 /**
  * Transform Builtin node.
  */
@@ -4935,6 +4991,8 @@ static ir_node *gen_Builtin(ir_node *node) {
        ir_builtin_kind kind = get_Builtin_kind(node);
 
        switch (kind) {
+       case ir_bk_trap:
+               return gen_trap(node);
        case ir_bk_return_address:
                return gen_return_address(node);
        case ir_bk_frame_addess:
@@ -4951,6 +5009,8 @@ static ir_node *gen_Builtin(ir_node *node) {
                return gen_parity(node);
        case ir_bk_popcount:
                return gen_popcount(node);
+       case ir_bk_bswap:
+               return gen_bswap(node);
        }
        panic("Builtin %s not implemented in IA32", get_builtin_kind_name(kind));
 }
@@ -4971,8 +5031,10 @@ static ir_node *gen_Proj_Builtin(ir_node *proj) {
        case ir_bk_ctz:
        case ir_bk_parity:
        case ir_bk_popcount:
+       case ir_bk_bswap:
                assert(get_Proj_proj(proj) == pn_Builtin_1_result);
                return new_node;
+       case ir_bk_trap:
        case ir_bk_prefetch:
                assert(get_Proj_proj(proj) == pn_Builtin_M);
                return new_node;
index e1d7b57..e104a5c 100644 (file)
@@ -1438,9 +1438,16 @@ set_Builtin_type(ir_node *node, ir_type *tp) {
 const char *get_builtin_kind_name(ir_builtin_kind kind) {
 #define X(a)    case a: return #a + 6;
        switch (kind) {
+               X(ir_bk_trap);
                X(ir_bk_return_address);
                X(ir_bk_frame_addess);
                X(ir_bk_prefetch);
+               X(ir_bk_ffs);
+               X(ir_bk_clz);
+               X(ir_bk_ctz);
+               X(ir_bk_popcount);
+               X(ir_bk_parity);
+               X(ir_bk_bswap);
        }
        return "<unknown>";
 #undef X