From 91a19e8e14a08c5bbe9b121e55a67a57ca5cf73e Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Tue, 23 Dec 2008 22:30:31 +0000 Subject: [PATCH] - add builtin_(trap|bswap) [r24882] --- include/libfirm/firm_types.h | 2 ++ ir/be/ia32/ia32_architecture.c | 1 + ir/be/ia32/ia32_architecture.h | 2 ++ ir/be/ia32/ia32_emitter.c | 24 ++++++++++++- ir/be/ia32/ia32_emitter.h | 2 +- ir/be/ia32/ia32_spec.pl | 43 +++++++++++++++++++++++ ir/be/ia32/ia32_transform.c | 64 +++++++++++++++++++++++++++++++++- ir/ir/irnode.c | 7 ++++ 8 files changed, 142 insertions(+), 3 deletions(-) diff --git a/include/libfirm/firm_types.h b/include/libfirm/firm_types.h index 734e0f286..70b449108 100644 --- a/include/libfirm/firm_types.h +++ b/include/libfirm/firm_types.h @@ -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 diff --git a/ir/be/ia32/ia32_architecture.c b/ir/be/ia32/ia32_architecture.c index 351aebb64..2d48a443c 100644 --- a/ir/be/ia32/ia32_architecture.c +++ b/ir/be/ia32/ia32_architecture.c @@ -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; diff --git a/ir/be/ia32/ia32_architecture.h b/ir/be/ia32/ia32_architecture.h index c494490f0..a88776f74 100644 --- a/ir/be/ia32/ia32_architecture.h +++ b/ir/be/ia32/ia32_architecture.h @@ -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; /** diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 2008d3a46..9086f41c1 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -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); diff --git a/ir/be/ia32/ia32_emitter.h b/ir/be/ia32/ia32_emitter.h index 477fe55d8..fc16668d0 100644 --- a/ir/be/ia32/ia32_emitter.h +++ b/ir/be/ia32/ia32_emitter.h @@ -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 diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 8c789634b..2ccf12d41 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -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 # diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index bb475cc60..684d2503c 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -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; diff --git a/ir/ir/irnode.c b/ir/ir/irnode.c index e1d7b57e4..e104a5cdb 100644 --- a/ir/ir/irnode.c +++ b/ir/ir/irnode.c @@ -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 ""; #undef X -- 2.20.1