Commit 91a19e8e authored by Michael Beck's avatar Michael Beck
Browse files

- add builtin_(trap|bswap)

[r24882]
parent f34059bc
......@@ -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
......@@ -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;
......
......@@ -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;
/**
......
......@@ -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);
......
......@@ -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
......@@ -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
#
......
......@@ -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;
......
......@@ -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
......
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