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_t.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
}

472 473
static void sparc_lower_for_target(void)
{
474
	lower_calls_with_compounds(LF_RETURN_HIDDEN, NULL);
475
	be_after_irp_transform("lower-calls");
476

477
	foreach_irp_irg(i, irg) {
478 479 480
		/* Turn all small CopyBs into loads/stores and all bigger CopyBs into
		 * memcpy calls. */
		lower_CopyB(irg, 31, 32, false);
481
		be_after_transform(irg, "lower-copyb");
482 483
	}

484
	if (!sparc_cg_config.use_fpu) {
485
		lower_floating_point();
486 487
		be_after_irp_transform("lower-fp");
	}
488

489
	ir_builtin_kind supported[8];
490
	size_t s = 0;
491
	supported[s++] = ir_bk_saturating_increment;
492 493
	if (sparc_cg_config.use_cas)
		supported[s++] = ir_bk_compare_swap;
494
	supported[s++] = ir_bk_va_start;
495 496
	assert(s < ARRAY_SIZE(supported));
	lower_builtins(s, supported);
497
	be_after_irp_transform("lower-builtins");
498

Matthias Braun's avatar
Matthias Braun committed
499
	ir_mode *mode_gp = sparc_reg_classes[CLASS_sparc_gp].mode;
500
	foreach_irp_irg(i, irg) {
501
		lower_switch(irg, 4, 256, mode_gp);
502
		be_after_transform(irg, "lower-switch");
503 504
	}

505
	sparc_lower_64bit();
506
	be_after_irp_transform("lower-64");
507

508
	foreach_irp_irg(i, irg) {
509
		ir_lower_mode_b(irg, mode_Iu);
510
		be_after_transform(irg, "lower-modeb");
511
		lower_alloc(irg, SPARC_PO2_STACK_ALIGNMENT);
512
		be_after_transform(irg, "lower-alloc");
513
	}
514 515
}

516 517 518
static int sparc_is_mux_allowed(ir_node *sel, ir_node *mux_false,
                                ir_node *mux_true)
{
519
	return ir_is_optimizable_mux(sel, mux_false, mux_true);
520 521
}

Hannes Rapp's avatar
Hannes Rapp committed
522 523 524
/**
 * Returns the libFirm configuration parameter for this backend.
 */
525 526
static const backend_params *sparc_get_backend_params(void)
{
527
	static const ir_settings_arch_dep_t arch_dep = {
528 529 530 531 532 533 534
		.also_use_subs        = true,
		.maximum_shifts       = 1,
		.highest_shift_amount = 31,
		.evaluate             = NULL,
		.allow_mulhs          = true,
		.allow_mulhu          = true,
		.max_bits_for_mulh    = 32,
535
	};
Hannes Rapp's avatar
Hannes Rapp committed
536
	static backend_params p = {
537 538 539 540 541 542 543 544 545 546 547 548 549
		.byte_order_big_endian          = true,
		.pic_supported                  = false,
		.unaligned_memaccess_supported  = false,
		.thread_local_storage_supported = true,
		.modulo_shift                   = 32,
		.dep_param                      = &arch_dep,
		.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 */
		.stack_param_align              = 4,
		.float_int_overflow             = ir_overflow_min_max,
		.vararg                         = {
550
			.va_list_type = NULL, /* will be set later */
551
			.lower_va_arg = be_default_lower_va_arg_compound_ptr,
552
		},
Hannes Rapp's avatar
Hannes Rapp committed
553
	};
554

555
	be_set_va_list_type_pointer(&p);
556

557 558
	sparc_mode_Q
		= new_float_mode("Q", irma_ieee754, 15, 112, ir_overflow_min_max);
559
	ir_type *type_long_double = get_type_for_mode(sparc_mode_Q);
560 561
	set_type_alignment(type_long_double, 8);
	set_type_size(type_long_double, 16);
562
	p.type_long_double = type_long_double;
Hannes Rapp's avatar
Hannes Rapp committed
563 564 565
	return &p;
}

566 567 568 569 570 571 572 573
static unsigned sparc_get_op_estimated_cost(const ir_node *node)
{
	/* TODO: refine */
	if (sparc_has_load_store_attr(node))
		return 5;
	return 1;
}

574
static arch_isa_if_t const sparc_isa_if = {
575 576 577 578 579 580 581 582 583
	.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,
584
	.is_valid_clobber      = be_default_is_valid_clobber,
585 586
	.handle_intrinsics     = sparc_handle_intrinsics,
	.get_op_estimated_cost = sparc_get_op_estimated_cost,
Hannes Rapp's avatar
Hannes Rapp committed
587 588
};

589
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc)
Hannes Rapp's avatar
Hannes Rapp committed
590 591
void be_init_arch_sparc(void)
{
592 593 594 595 596
	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
597 598 599 600 601
	be_register_isa_if("sparc", &sparc_isa_if);
	FIRM_DBG_REGISTER(dbg, "firm.be.sparc.cg");
	sparc_init_transform();
	sparc_init_emitter();
}