sparc_bearch.c 17.3 KB
Newer Older
Hannes Rapp's avatar
Hannes Rapp committed
1 2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Hannes Rapp's avatar
Hannes Rapp committed
4 5 6 7 8
 */

/**
 * @file
 * @brief    The main sparc backend driver file.
Matthias Braun's avatar
Matthias Braun committed
9
 * @author   Hannes Rapp, Matthias Braun
Hannes Rapp's avatar
Hannes Rapp committed
10
 */
11 12
#include "sparc_bearch_t.h"

13 14 15
#include "be_t.h"
#include "beflags.h"
#include "begnuas.h"
Matthias Braun's avatar
Matthias Braun committed
16
#include "beirg.h"
17
#include "bemodule.h"
18
#include "bera.h"
19 20
#include "besched.h"
#include "betranshlp.h"
21
#include "bevarargs.h"
22
#include "debug.h"
23
#include "gen_sparc_regalloc_if.h"
24
#include "irarch.h"
25
#include "ircons_t.h"
Hannes Rapp's avatar
Hannes Rapp committed
26
#include "irgmod.h"
27
#include "irgwalk.h"
28
#include "iropt_t.h"
29 30 31
#include "irprog_t.h"
#include "irtools.h"
#include "lc_opts_enum.h"
32
#include "lower_alloc.h"
33
#include "lower_builtins.h"
34
#include "lower_calls.h"
35
#include "lower_mode_b.h"
36
#include "lower_softfloat.h"
37 38 39
#include "lowering.h"
#include "sparc_cconv.h"
#include "sparc_emitter.h"
Hannes Rapp's avatar
Hannes Rapp committed
40 41
#include "sparc_new_nodes.h"
#include "sparc_transform.h"
42
#include "util.h"
43

Hannes Rapp's avatar
Hannes Rapp committed
44 45
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

46 47
pmap *sparc_constants;

48 49
ir_mode *sparc_mode_Q;

50 51 52 53 54 55 56 57 58 59 60 61
typedef enum {
	cpu_generic,
	cpu_v8plus,
	cpu_leon,
	cpu_supersparc,
	cpu_hypersparc,
} sparc_cpu_t;
static const lc_opt_enum_int_items_t cpu_items[] = {
	{ "generic",    cpu_generic    },
	{ "v8",         cpu_generic    },
	{ "v8plus",     cpu_v8plus     },
	{ "leon",       cpu_leon       },
62
	{ "leon3",      cpu_leon       },
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
	{ "supersparc", cpu_supersparc },
	{ "hypersparc", cpu_hypersparc },
	{ NULL,         0               },
};

static int cpu;
static lc_opt_enum_int_var_t cpu_var = {
	&cpu, cpu_items
};

sparc_codegen_config_t sparc_cg_config;

typedef enum {
	use_fpu_auto,
	use_fpu_yes,
	use_fpu_no
} sparc_use_fpu_t;
/* fpu set architectures. */
static const lc_opt_enum_int_items_t fpu_items[] = {
	{ "auto",      use_fpu_auto },
	{ "fpu",       use_fpu_yes  },
	{ "softfloat", use_fpu_no   },
	{ NULL,        0 }
};

static int fpu;
static lc_opt_enum_int_var_t arch_fpu_var = {
	&fpu, fpu_items
};

93
static bool use_softfloat;
94 95 96 97 98 99 100 101

static const lc_opt_table_entry_t sparc_options[] = {
	LC_OPT_ENT_ENUM_INT("fpunit",     "select the floating point unit", &arch_fpu_var),
	LC_OPT_ENT_ENUM_INT("cpu",        "select architecture variant",    &cpu_var),
	LC_OPT_ENT_BOOL    ("soft-float", "equivalent to fpmath=softfloat", &use_softfloat),
	LC_OPT_LAST
};

Hannes Rapp's avatar
Hannes Rapp committed
102
/**
103
 * Transforms the standard firm graph into a SPARC firm graph
Hannes Rapp's avatar
Hannes Rapp committed
104
 */
105
static void sparc_select_instructions(ir_graph *irg)
Hannes Rapp's avatar
Hannes Rapp committed
106
{
107
	be_timer_push(T_CODEGEN);
108
	sparc_transform_graph(irg);
109
	be_timer_pop(T_CODEGEN);
110
	be_dump(DUMP_BE, irg, "code-selection");
Hannes Rapp's avatar
Hannes Rapp committed
111 112
}

113 114
static bool sparc_modifies_flags(const ir_node *node)
{
115
	be_foreach_out(node, o) {
116
		const arch_register_req_t *req = arch_get_irn_register_req_out(node, o);
117
		if (req->cls == &sparc_reg_classes[CLASS_sparc_flags])
118 119 120
			return true;
	}
	return false;
121 122 123 124
}

static bool sparc_modifies_fp_flags(const ir_node *node)
{
125
	be_foreach_out(node, o) {
126
		const arch_register_req_t *req = arch_get_irn_register_req_out(node, o);
127
		if (req->cls == &sparc_reg_classes[CLASS_sparc_fpflags])
128 129 130
			return true;
	}
	return false;
131 132
}

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
/**
 * rewrite unsigned->float conversion.
 * Sparc has no instruction for this so instead we do the following:
 *
 *   int    signed_x = unsigned_value_x;
 *   double res      = signed_x;
 *   if (signed_x < 0)
 *       res += 4294967296. ;
 *   return (float) res;
 */
static void rewrite_unsigned_float_Conv(ir_node *node)
{
	ir_graph *irg         = get_irn_irg(node);
	dbg_info *dbgi        = get_irn_dbg_info(node);
	ir_node  *lower_block = get_nodes_block(node);

	part_block(node);

Matthias Braun's avatar
Matthias Braun committed
151 152 153 154 155 156 157
	ir_node   *block       = get_nodes_block(node);
	ir_node   *unsigned_x  = get_Conv_op(node);
	ir_mode   *mode_u      = get_irn_mode(unsigned_x);
	ir_mode   *mode_s      = find_signed_mode(mode_u);
	ir_mode   *mode_d      = mode_D;
	ir_node   *signed_x    = new_rd_Conv(dbgi, block, unsigned_x, mode_s);
	ir_node   *res         = new_rd_Conv(dbgi, block, signed_x, mode_d);
158
	ir_node   *zero        = new_r_Const_null(irg, mode_s);
159
	collect_new_start_block_node(zero);
Matthias Braun's avatar
Matthias Braun committed
160 161 162 163 164 165 166 167 168 169 170 171 172
	ir_node   *cmp         = new_rd_Cmp(dbgi, block, signed_x, zero,
	                                    ir_relation_less);
	ir_node   *cond        = new_rd_Cond(dbgi, block, cmp);
	ir_node   *proj_true   = new_r_Proj(cond, mode_X, pn_Cond_true);
	ir_node   *proj_false  = new_r_Proj(cond, mode_X, pn_Cond_false);
	ir_node   *in_true[1]  = { proj_true };
	ir_node   *in_false[1] = { proj_false };
	ir_node   *true_block  = new_r_Block(irg, ARRAY_SIZE(in_true), in_true);
	ir_node   *false_block = new_r_Block(irg, ARRAY_SIZE(in_false),in_false);
	ir_node   *true_jmp    = new_r_Jmp(true_block);
	ir_node   *false_jmp   = new_r_Jmp(false_block);
	ir_tarval *correction  = new_tarval_from_double(4294967296., mode_d);
	ir_node   *c_const     = new_r_Const(irg, correction);
173
	collect_new_start_block_node(c_const);
174
	ir_node   *fadd        = new_rd_Add(dbgi, true_block, res, c_const);
Matthias Braun's avatar
Matthias Braun committed
175 176 177 178 179 180 181

	ir_node  *lower_in[2] = { true_jmp, false_jmp };
	ir_node  *phi_in[2]   = { fadd, res };
	ir_mode  *dest_mode   = get_irn_mode(node);

	set_irn_in(lower_block, ARRAY_SIZE(lower_in), lower_in);
	ir_node *phi = new_r_Phi(lower_block, ARRAY_SIZE(phi_in), phi_in, mode_d);
182
	collect_new_phi_node(phi);
Matthias Braun's avatar
Matthias Braun committed
183 184 185

	ir_node *res_conv = new_rd_Conv(dbgi, lower_block, phi, dest_mode);
	exchange(node, res_conv);
186 187
}

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
/**
 * rewrite float->unsigned conversions.
 * Sparc has no instruction for this so instead we do the following:
 *
 * if (x >= 2147483648.) {
 *   converted ^= (int)(x-2147483648.) ^ 0x80000000;
 * } else {
 *   converted = (int)x;
 * }
 * return (unsigned)converted;
 */
static void rewrite_float_unsigned_Conv(ir_node *node)
{
	ir_graph *irg         = get_irn_irg(node);
	dbg_info *dbgi        = get_irn_dbg_info(node);
	ir_node  *lower_block = get_nodes_block(node);

	part_block(node);

Matthias Braun's avatar
Matthias Braun committed
207 208 209 210 211 212 213
	ir_node   *block       = get_nodes_block(node);
	ir_node   *float_x     = get_Conv_op(node);
	ir_mode   *mode_u      = get_irn_mode(node);
	ir_mode   *mode_s      = find_signed_mode(mode_u);
	ir_mode   *mode_f      = get_irn_mode(float_x);
	ir_tarval *limit       = new_tarval_from_double(2147483648., mode_f);
	ir_node   *limitc      = new_r_Const(irg, limit);
214
	collect_new_start_block_node(limitc);
Matthias Braun's avatar
Matthias Braun committed
215 216 217 218 219 220 221 222 223 224 225 226
	ir_node   *cmp         = new_rd_Cmp(dbgi, block, float_x, limitc,
	                                    ir_relation_greater_equal);
	ir_node   *cond        = new_rd_Cond(dbgi, block, cmp);
	ir_node   *proj_true   = new_r_Proj(cond, mode_X, pn_Cond_true);
	ir_node   *proj_false  = new_r_Proj(cond, mode_X, pn_Cond_false);
	ir_node   *in_true[1]  = { proj_true };
	ir_node   *in_false[1] = { proj_false };
	ir_node   *true_block  = new_r_Block(irg, ARRAY_SIZE(in_true), in_true);
	ir_node   *false_block = new_r_Block(irg, ARRAY_SIZE(in_false),in_false);
	ir_node   *true_jmp    = new_r_Jmp(true_block);
	ir_node   *false_jmp   = new_r_Jmp(false_block);

227
	ir_node   *c_const     = new_r_Const_long(irg, mode_s, 0x80000000L);
228
	collect_new_start_block_node(c_const);
229
	ir_node   *sub         = new_rd_Sub(dbgi, true_block, float_x, limitc);
Matthias Braun's avatar
Matthias Braun committed
230
	ir_node   *sub_conv    = new_rd_Conv(dbgi, true_block, sub, mode_s);
231
	ir_node   *xorn        = new_rd_Eor(dbgi, true_block, sub_conv, c_const);
Matthias Braun's avatar
Matthias Braun committed
232 233 234 235 236 237 238 239

	ir_node   *converted   = new_rd_Conv(dbgi, false_block, float_x,mode_s);

	ir_node  *lower_in[2] = { true_jmp, false_jmp };
	ir_node  *phi_in[2]   = { xorn, converted };

	set_irn_in(lower_block, ARRAY_SIZE(lower_in), lower_in);
	ir_node *phi = new_r_Phi(lower_block, ARRAY_SIZE(phi_in), phi_in, mode_s);
240
	collect_new_phi_node(phi);
Matthias Braun's avatar
Matthias Braun committed
241 242 243

	ir_node *res_conv = new_rd_Conv(dbgi, lower_block, phi, mode_u);
	exchange(node, res_conv);
244 245
}

Matthias Braun's avatar
Matthias Braun committed
246
static bool sparc_rewrite_Conv(ir_node *node)
247 248 249 250 251 252
{
	ir_mode *to_mode   = get_irn_mode(node);
	ir_node *op        = get_Conv_op(node);
	ir_mode *from_mode = get_irn_mode(op);

	if (mode_is_float(to_mode) && mode_is_int(from_mode)
253 254
	    && get_mode_size_bits(from_mode) == 32
	    && !mode_is_signed(from_mode)) {
255
		rewrite_unsigned_float_Conv(node);
Matthias Braun's avatar
Matthias Braun committed
256
		return true;
257
	}
258
	if (mode_is_float(from_mode) && mode_is_int(to_mode)
259
	    && get_mode_size_bits(to_mode) <= 32
260
	    && !mode_is_signed(to_mode)) {
261 262
		rewrite_float_unsigned_Conv(node);
		return true;
263
	}
264

Matthias Braun's avatar
Matthias Braun committed
265
	return false;
266 267
}

Matthias Braun's avatar
Matthias Braun committed
268 269 270 271
static ir_entity *rem;
static ir_entity *urem;

static void handle_intrinsic(ir_node *node, void *data)
272
{
Matthias Braun's avatar
Matthias Braun committed
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
	bool *changed = (bool*)data;
	if (is_Mod(node)) {
		ir_mode *mode = get_Mod_resmode(node);
		if (get_mode_arithmetic(mode) == irma_twos_complement) {
			ir_entity *entity = mode_is_signed(mode) ? rem : urem;
			be_map_exc_node_to_runtime_call(node, mode, entity, pn_Mod_M,
			                                pn_Mod_X_regular, pn_Mod_X_except,
			                                pn_Mod_res);
			*changed = true;
		}
	} else if (is_Conv(node)) {
		if (sparc_rewrite_Conv(node))
			*changed = true;
	}
}
288

289 290
static ir_type *make_mod_type(ir_type *const tp)
{
291
	ir_type *const mtp = new_type_method(2, 1, false, cc_cdecl_set, mtp_no_property);
292 293 294 295 296 297
	set_method_param_type(mtp, 0, tp);
	set_method_param_type(mtp, 1, tp);
	set_method_res_type(mtp, 0, tp);
	return mtp;
}

Matthias Braun's avatar
Matthias Braun committed
298 299 300 301
static void sparc_create_runtime_entities(void)
{
	if (rem != NULL)
		return;
302

303
	ir_type *const int_tp = get_type_for_mode(mode_Is);
304
	ir_type *const mod_tp = make_mod_type(int_tp);
Matthias Braun's avatar
Matthias Braun committed
305
	rem = create_compilerlib_entity(new_id_from_str(".rem"), mod_tp);
Matthias Braun's avatar
Matthias Braun committed
306

307
	ir_type *const uint_tp = get_type_for_mode(mode_Iu);
308
	ir_type *const umod_tp = make_mod_type(uint_tp);
Matthias Braun's avatar
Matthias Braun committed
309 310
	urem = create_compilerlib_entity(new_id_from_str(".urem"), umod_tp);
}
Matthias Braun's avatar
Matthias Braun committed
311

Matthias Braun's avatar
Matthias Braun committed
312 313 314 315
static void sparc_handle_intrinsics(ir_graph *irg)
{
	sparc_create_runtime_entities();
	ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
316
	collect_phiprojs_and_start_block_nodes(irg);
Matthias Braun's avatar
Matthias Braun committed
317 318 319 320 321 322
	bool changed = false;
	irg_walk_graph(irg, handle_intrinsic, NULL, &changed);
	ir_free_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);

	if (changed) {
		confirm_irg_properties(irg,
323
			IR_GRAPH_PROPERTY_NO_BADS
Matthias Braun's avatar
Matthias Braun committed
324 325 326 327
			| IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES
			| IR_GRAPH_PROPERTY_MANY_RETURNS
			| IR_GRAPH_PROPERTY_ONE_RETURN);
	}
328 329
}

330 331
static void sparc_setup_cg_config(void)
{
332 333
	memset(&sparc_cg_config, 0, sizeof(sparc_cg_config));
	bool has_fpu = false;
334
	switch ((sparc_cpu_t)cpu) {
335 336
	case cpu_v8plus:
		sparc_cg_config.use_cas = true;
Manuel Mohr's avatar
Manuel Mohr committed
337
		sparc_cg_config.cas_asi = 0x80;
338 339
		has_fpu = false;
		break;
340
	case cpu_leon:
341
		sparc_cg_config.use_cas = true;
Manuel Mohr's avatar
Manuel Mohr committed
342 343 344 345
		/* According to Gaisler's GRIP documentation, section 77.2.7,
		 * the LEON requires the ASI 0x0A for CAS usage in user mode.
		 */
		sparc_cg_config.cas_asi = 0x0A;
346 347
		has_fpu = true;
		break;
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
	case cpu_hypersparc:
		has_fpu = true;
		break;
	case cpu_supersparc:
	case cpu_generic:
		has_fpu = false;
		break;
	}

	if (use_softfloat)
		fpu = use_fpu_no;

	if (fpu == use_fpu_auto) {
		sparc_cg_config.use_fpu = has_fpu;
	} else {
		sparc_cg_config.use_fpu = fpu == use_fpu_yes;
	}
}

367 368
static void sparc_init(void)
{
369 370
	ir_mode *const ptr_mode = new_reference_mode("p32", 32, 32);
	set_modeP(ptr_mode);
371
	sparc_init_asm_constraints();
372
	sparc_register_init();
373
	sparc_create_opcodes();
374
	sparc_cconv_init();
375
	sparc_setup_cg_config();
376 377
}

Matthias Braun's avatar
Matthias Braun committed
378 379 380 381 382
static void sparc_finish(void)
{
	sparc_free_opcodes();
}

383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
static ir_node *sparc_new_spill(ir_node *value, ir_node *after)
{
	ir_node  *block = get_block(after);
	ir_graph *irg   = get_irn_irg(value);
	ir_node  *frame = get_irg_frame(irg);
	ir_node  *mem   = get_irg_no_mem(irg);
	ir_mode  *mode  = get_irn_mode(value);

	ir_node  *store;
	if (mode_is_float(mode)) {
		store = create_stf(NULL, block, value, frame, mem, mode, NULL, 0, true);
	} else {
		store = new_bd_sparc_St_imm(NULL, block, value, frame, mem, mode, NULL,
		                            0, true);
	}
	arch_add_irn_flags(store, arch_irn_flag_spill);
	sched_add_after(after, store);
	return store;
}

static ir_node *sparc_new_reload(ir_node *value, ir_node *spill,
                                 ir_node *before)
{
	ir_node  *block = get_block(before);
	ir_graph *irg   = get_irn_irg(value);
	ir_node  *frame = get_irg_frame(irg);
	ir_mode  *mode  = get_irn_mode(value);

	ir_node  *load;
	if (mode_is_float(mode)) {
		load = create_ldf(NULL, block, frame, spill, mode, NULL, 0, true);
	} else {
		load = new_bd_sparc_Ld_imm(NULL, block, frame, spill, mode, NULL, 0,
		                           true);
	}
	arch_add_irn_flags(load, arch_irn_flag_reload);
	sched_add_before(before, load);
	assert((long)pn_sparc_Ld_res == (long)pn_sparc_Ldf_res);
421
	return be_new_Proj(load, pn_sparc_Ld_res);
422 423 424 425 426 427 428 429 430
}

static const regalloc_if_t sparc_regalloc_if = {
	.spill_cost  = 7,
	.reload_cost = 5,
	.new_spill   = sparc_new_spill,
	.new_reload  = sparc_new_reload,
};

431
static void sparc_generate_code(FILE *output, const char *cup_name)
Hannes Rapp's avatar
Hannes Rapp committed
432
{
433 434
	be_gas_elf_type_char = '#';
	be_gas_elf_variant   = ELF_VARIANT_SPARC;
435
	sparc_constants = pmap_create();
Hannes Rapp's avatar
Hannes Rapp committed
436

437
	be_begin(output, cup_name);
438
	unsigned *const sp_is_non_ssa = rbitset_alloca(N_SPARC_REGISTERS);
439
	rbitset_set(sp_is_non_ssa, REG_SP);
440 441 442 443 444

	foreach_irp_irg(i, irg) {
		if (!be_step_first(irg))
			continue;

445 446 447
		struct obstack *obst = be_get_be_obst(irg);
		be_birg_from_irg(irg)->isa_link = OALLOCZ(obst, sparc_irg_data_t);

Matthias Braun's avatar
Matthias Braun committed
448
		be_birg_from_irg(irg)->non_ssa_regs = sp_is_non_ssa;
449 450 451 452 453 454
		sparc_select_instructions(irg);

		be_step_schedule(irg);

		be_timer_push(T_RA_PREPARATION);
		be_sched_fix_flags(irg, &sparc_reg_classes[CLASS_sparc_flags],
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
455
		                   NULL, sparc_modifies_flags, NULL);
456
		be_sched_fix_flags(irg, &sparc_reg_classes[CLASS_sparc_fpflags],
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
457
		                   NULL, sparc_modifies_fp_flags, NULL);
458 459
		be_timer_pop(T_RA_PREPARATION);

460
		be_step_regalloc(irg, &sparc_regalloc_if);
461 462 463 464 465 466 467 468

		sparc_finish_graph(irg);
		sparc_emit_function(irg);

		be_step_last(irg);
	}

	be_finish();
469
	pmap_destroy(sparc_constants);
Hannes Rapp's avatar
Hannes Rapp committed
470 471
}

Matthias Braun's avatar
Matthias Braun committed
472 473 474 475 476
static void sparc_lower_va_arg(ir_node *node)
{
	be_default_lower_va_arg(node, true, 4);
}

477 478 479 480 481 482 483 484 485 486 487 488 489
static const ir_settings_arch_dep_t sparc_arch_dep = {
	.replace_muls         = true,
	.replace_divs         = true,
	.replace_mods         = true,
	.allow_mulhs          = true,
	.allow_mulhu          = true,
	.also_use_subs        = true,
	.maximum_shifts       = 1,
	.highest_shift_amount = 31,
	.evaluate             = NULL,
	.max_bits_for_mulh    = 32,
};

490 491
static void sparc_lower_for_target(void)
{
492 493 494
	ir_arch_lower(&sparc_arch_dep);
	be_after_irp_transform("lower-arch-dep");

495
	lower_calls_with_compounds(LF_RETURN_HIDDEN, NULL);
496
	be_after_irp_transform("lower-calls");
497

498
	foreach_irp_irg(i, irg) {
499 500 501
		/* Turn all small CopyBs into loads/stores and all bigger CopyBs into
		 * memcpy calls. */
		lower_CopyB(irg, 31, 32, false);
502
		be_after_transform(irg, "lower-copyb");
503 504
	}

505
	if (!sparc_cg_config.use_fpu) {
506
		lower_floating_point();
507 508
		be_after_irp_transform("lower-fp");
	}
509

510
	ir_builtin_kind supported[8];
511
	size_t s = 0;
512
	supported[s++] = ir_bk_saturating_increment;
513 514
	if (sparc_cg_config.use_cas)
		supported[s++] = ir_bk_compare_swap;
515
	supported[s++] = ir_bk_va_start;
516
	assert(s < ARRAY_SIZE(supported));
Matthias Braun's avatar
Matthias Braun committed
517
	lower_builtins(s, supported, sparc_lower_va_arg);
518
	be_after_irp_transform("lower-builtins");
519

Matthias Braun's avatar
Matthias Braun committed
520
	ir_mode *mode_gp = sparc_reg_classes[CLASS_sparc_gp].mode;
521
	foreach_irp_irg(i, irg) {
522
		lower_switch(irg, 4, 256, mode_gp);
523
		be_after_transform(irg, "lower-switch");
524 525
	}

526
	sparc_lower_64bit();
527
	be_after_irp_transform("lower-64");
528

529
	foreach_irp_irg(i, irg) {
530
		ir_lower_mode_b(irg, mode_Iu);
531
		be_after_transform(irg, "lower-modeb");
532
		lower_alloc(irg, SPARC_PO2_STACK_ALIGNMENT);
533
		be_after_transform(irg, "lower-alloc");
534
	}
535 536
}

537 538 539
static int sparc_is_mux_allowed(ir_node *sel, ir_node *mux_false,
                                ir_node *mux_true)
{
540
	return ir_is_optimizable_mux(sel, mux_false, mux_true);
541 542
}

Hannes Rapp's avatar
Hannes Rapp committed
543 544 545
/**
 * Returns the libFirm configuration parameter for this backend.
 */
546 547
static const backend_params *sparc_get_backend_params(void)
{
Hannes Rapp's avatar
Hannes Rapp committed
548
	static backend_params p = {
549 550 551 552 553 554 555 556 557 558
		.byte_order_big_endian          = true,
		.pic_supported                  = false,
		.unaligned_memaccess_supported  = false,
		.thread_local_storage_supported = true,
		.modulo_shift                   = 32,
		.allow_ifconv                   = sparc_is_mux_allowed,
		.machine_size                   = 32,
		.mode_float_arithmetic          = NULL,  /* will be set later */
		.type_long_double               = NULL,  /* will be set later */
		.float_int_overflow             = ir_overflow_min_max,
Hannes Rapp's avatar
Hannes Rapp committed
559
	};
560

561
	be_set_va_list_type_pointer(&p);
562

563 564
	sparc_mode_Q
		= new_float_mode("Q", irma_ieee754, 15, 112, ir_overflow_min_max);
565
	ir_type *type_long_double = get_type_for_mode(sparc_mode_Q);
566 567
	set_type_alignment(type_long_double, 8);
	set_type_size(type_long_double, 16);
568
	p.type_long_double = type_long_double;
Hannes Rapp's avatar
Hannes Rapp committed
569 570 571
	return &p;
}

572 573 574 575 576 577 578 579
static unsigned sparc_get_op_estimated_cost(const ir_node *node)
{
	/* TODO: refine */
	if (sparc_has_load_store_attr(node))
		return 5;
	return 1;
}

580
static arch_isa_if_t const sparc_isa_if = {
581 582 583 584 585 586 587 588 589
	.n_registers           = N_SPARC_REGISTERS,
	.registers             = sparc_registers,
	.n_register_classes    = N_SPARC_CLASSES,
	.register_classes      = sparc_reg_classes,
	.init                  = sparc_init,
	.finish                = sparc_finish,
	.generate_code         = sparc_generate_code,
	.get_params            = sparc_get_backend_params,
	.lower_for_target      = sparc_lower_for_target,
590
	.is_valid_clobber      = be_default_is_valid_clobber,
591 592
	.handle_intrinsics     = sparc_handle_intrinsics,
	.get_op_estimated_cost = sparc_get_op_estimated_cost,
Hannes Rapp's avatar
Hannes Rapp committed
593 594
};

595
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc)
Hannes Rapp's avatar
Hannes Rapp committed
596 597
void be_init_arch_sparc(void)
{
598 599 600 601 602
	lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
	lc_opt_entry_t *sparc_grp = lc_opt_get_grp(be_grp, "sparc");

	lc_opt_add_table(sparc_grp, sparc_options);

Hannes Rapp's avatar
Hannes Rapp committed
603 604 605 606 607
	be_register_isa_if("sparc", &sparc_isa_if);
	FIRM_DBG_REGISTER(dbg, "firm.be.sparc.cg");
	sparc_init_transform();
	sparc_init_emitter();
}