void sparc_emit_immediate(const ir_node *node)
{
- int const val = get_sparc_attr_const(node)->immediate_value;
- assert(-4096 <= val && val < 4096);
- be_emit_irprintf("%d", val);
+ int32_t value = get_sparc_attr_const(node)->immediate_value;
+ assert(-4096 <= value && value < 4096);
+ be_emit_irprintf("%d", value);
+}
+
+void sparc_emit_high_immediate(const ir_node *node)
+{
+ uint32_t value = (uint32_t) get_sparc_attr_const(node)->immediate_value;
+ be_emit_irprintf("%%hi(0x%X)", value);
}
void sparc_emit_source_register(const ir_node *node, int pos)
be_emit_finish_line_gas(irn);
}
-/**
- * emits code to load hi 22 bit of a constant
- */
-static void emit_sparc_HiImm(const ir_node *irn)
-{
- const sparc_attr_t *attr = get_sparc_attr_const(irn);
- be_emit_cstring("\tsethi ");
- be_emit_irprintf("%%hi(%d), ", attr->immediate_value);
- sparc_emit_dest_register(irn, 0);
- be_emit_finish_line_gas(irn);
-}
-
-/**
- * emits code to load lo 10bits of a constant
- */
-static void emit_sparc_LoImm(const ir_node *irn)
-{
- const sparc_attr_t *attr = get_sparc_attr_const(irn);
- be_emit_cstring("\tor ");
- sparc_emit_source_register(irn, 0);
- be_emit_irprintf(", %%lo(%d), ", attr->immediate_value);
- sparc_emit_dest_register(irn, 0);
- be_emit_finish_line_gas(irn);
-}
-
/**
* emits code for mulh
*/
set_emitter(op_sparc_Call, emit_sparc_Call);
set_emitter(op_sparc_fbfcc, emit_sparc_fbfcc);
set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr);
- set_emitter(op_sparc_HiImm, emit_sparc_HiImm);
- set_emitter(op_sparc_LoImm, emit_sparc_LoImm);
set_emitter(op_sparc_Mulh, emit_sparc_Mulh);
set_emitter(op_sparc_Save, emit_sparc_Save);
set_emitter(op_sparc_SDiv, emit_sparc_SDiv);
#include "bearch_sparc_t.h"
void sparc_emit_immediate(const ir_node *node);
+void sparc_emit_high_immediate(const ir_node *node);
void sparc_emit_mode(const ir_node *node);
void sparc_emit_source_register(const ir_node *node, int pos);
void sparc_emit_reg_or_imm(const ir_node *node, int pos);
}
}
-static void sparc_set_attr_imm(ir_node *res, int immediate_value)
+static void sparc_set_attr_imm(ir_node *res, int32_t immediate_value)
{
sparc_attr_t *attr = get_irn_generic_attr(res);
attr->immediate_value = immediate_value;
#define FIRM_BE_SPARC_SPARC_NODES_ATTR_H
#include "../bearch.h"
+#include <stdint.h>
typedef struct sparc_attr_t sparc_attr_t;
{
except_attr exc; /**< the exception attribute. MUST be the first one. */
const arch_register_req_t **in_req; /**< register requirements for arguments */
- int immediate_value; /* immediate values */
+ int32_t immediate_value; /* immediate values */
bool is_load_store;
ir_entity *immediate_value_entity; /* hack for now */
D5 => "${arch}_emit_dest_register(node, 4);",
D6 => "${arch}_emit_dest_register(node, 5);",
IM => "${arch}_emit_immediate(node);",
+ HIM => "${arch}_emit_high_immediate(node);",
LM => "${arch}_emit_load_mode(node);",
SM => "${arch}_emit_store_mode(node);",
FLSM => "${arch}_emit_float_load_store_mode(node);",
my %cmp_operand_constructors = (
imm => {
- attr => "int immediate_value",
+ attr => "int32_t immediate_value",
custominit => "sparc_set_attr_imm(res, immediate_value);",
reg_req => { in => [ "gp" ], out => [ "flags" ] },
ins => [ "left" ],
my %unop_operand_constructors = (
imm => {
- attr => "int immediate_value",
+ attr => "int32_t immediate_value",
custominit => "sparc_set_attr_imm(res, immediate_value);",
reg_req => { in => [], out => [ "gp" ] },
},
my %binop_operand_constructors = (
imm => {
- attr => "int immediate_value",
+ attr => "int32_t immediate_value",
custominit => "sparc_set_attr_imm(res, immediate_value);",
reg_req => { in => [ "gp" ], out => [ "gp" ] },
ins => [ "left" ],
emit => '. ld%LM [%S1%O], %D1'
},
-HiImm => {
- irn_flags => [ "rematerializable" ],
- state => "exc_pinned",
- outs => [ "res" ],
- mode => $mode_gp,
- reg_req => { in => [], out => [ "gp" ] },
- attr => "int immediate_value",
- custominit => "sparc_set_attr_imm(res, immediate_value);",
-},
-
-LoImm => {
- irn_flags => [ "rematerializable" ],
- state => "exc_pinned",
- ins => [ "hireg" ],
- outs => [ "res" ],
- mode => $mode_gp,
- reg_req => { in => [ "gp" ], out => [ "gp" ] },
- attr => "int immediate_value",
+SetHi => {
+ irn_flags => [ "rematerializable" ],
+ outs => [ "res" ],
+ mode => $mode_gp,
+ reg_req => { in => [], out => [ "gp" ] },
+ attr => "int32_t immediate_value",
custominit => "sparc_set_attr_imm(res, immediate_value);",
+ emit => '. sethi %HIM, %D1'
},
St => {
emit => '. st%SM %S2, [%S1%O]'
},
-Mov => {
- irn_flags => [ "rematerializable" ],
- arity => "variable",
- emit => '. mov %R1I, %D1',
- mode => $mode_gp,
- constructors => \%unop_operand_constructors,
-},
-
Save => {
reg_req => {
in => [ "sp", "none"],
#include "iredges.h"
#include "ircons.h"
#include "irprintf.h"
+#include "iroptimize.h"
#include "dbginfo.h"
#include "iropt_t.h"
#include "debug.h"
}
}
-/**
- * Creates a possible DAG for a constant.
- */
-static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
- long value)
-{
- ir_node *result;
-
- /* we need to load hi & lo separately */
- if (value < -4096 || value > 4095) {
- ir_node *hi = new_bd_sparc_HiImm(dbgi, block, (int) value);
- result = new_bd_sparc_LoImm(dbgi, block, hi, value);
- be_dep_on_frame(hi);
- } else {
- result = new_bd_sparc_Mov_imm(dbgi, block, (int) value);
- be_dep_on_frame(result);
- }
-
- return result;
-}
-
-/**
- * Create a DAG constructing a given Const.
- *
- * @param irn a Firm const
- */
-static ir_node *create_const_graph(ir_node *irn, ir_node *block)
-{
- tarval *tv = get_Const_tarval(irn);
- ir_mode *mode = get_tarval_mode(tv);
- dbg_info *dbgi = get_irn_dbg_info(irn);
- long value;
-
-
- if (mode_is_reference(mode)) {
- /* SPARC V8 is 32bit, so we can safely convert a reference tarval into Iu */
- assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_gp));
- tv = tarval_convert_to(tv, mode_gp);
- }
-
- value = get_tarval_long(tv);
- return create_const_graph_value(dbgi, block, value);
-}
-
typedef enum {
MATCH_NONE = 0,
MATCH_COMMUTATIVE = 1 << 0, /**< commutative operation. */
typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
typedef ir_node* (*new_binop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode);
-typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, int simm13);
+typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, int32_t immediate);
typedef ir_node* (*new_unop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_mode *mode);
/**
*/
static bool is_imm_encodeable(const ir_node *node)
{
- long val;
-
+ long value;
if (!is_Const(node))
return false;
- val = get_tarval_long(get_Const_tarval(node));
-
- return -4096 <= val && val <= 4095;
+ value = get_tarval_long(get_Const_tarval(node));
+ return -4096 <= value && value <= 4095;
}
/**
return entity;
}
-/**
- * Transforms a Const node.
- *
- * @param node the ir Const node
- * @return The transformed sparc node.
- */
static ir_node *gen_Const(ir_node *node)
{
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_mode *mode = get_irn_mode(node);
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ ir_mode *mode = get_irn_mode(node);
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ tarval *tv;
+ long value;
if (mode_is_float(mode)) {
- dbg_info *dbgi = get_irn_dbg_info(node);
tarval *tv = get_Const_tarval(node);
ir_entity *entity = create_float_const_entity(tv);
ir_node *addr = make_addr(dbgi, entity);
return proj;
}
- /* use the 0 register instead of a 0-constant */
- if (is_Const_null(node)) {
+ tv = get_Const_tarval(node);
+ value = get_tarval_long(tv);
+ if (value == 0) {
return get_g0();
+ } else if (-4096 <= value && value <= 4095) {
+ return new_bd_sparc_Or_imm(dbgi, block, get_g0(), value);
+ } else {
+ ir_node *hi = new_bd_sparc_SetHi(dbgi, block, value);
+ be_dep_on_frame(hi);
+ if ((value & 0x3ff) != 0) {
+ return new_bd_sparc_Or_imm(dbgi, block, hi, value & 0x3ff);
+ } else {
+ return hi;
+ }
}
-
- return create_const_graph(node, block);
}
static ir_mode *get_cmp_mode(ir_node *b_value)
// switch/case jumps
if (mode != mode_b) {
- panic("SwitchJmp not supported yet");
+ panic("SwitchJump not implemented yet");
}
// regular if/else jumps
static ir_node *gen_Unknown(ir_node *node)
{
- ir_node *block = get_nodes_block(node);
- ir_node *new_block = be_transform_node(block);
- dbg_info *dbgi = get_irn_dbg_info(node);
-
/* just produce a 0 */
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
be_dep_on_frame(node);
return node;
} else if (mode_needs_gp_reg(mode)) {
- return create_const_graph_value(dbgi, new_block, 0);
+ return get_g0();
}
panic("Unexpected Unknown mode");
node_to_stack = NULL;
be_add_missing_keeps(irg);
+
+ /* do code placement, to optimize the position of constants */
+ place_code(cg->irg);
}
void sparc_init_transform(void)