sparc_bearch.c 17.6 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);
Matthias Braun's avatar
Matthias Braun committed
174
175
176
177
178
179
180
181
	ir_node   *fadd        = new_rd_Add(dbgi, true_block, res, c_const, mode_d);

	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);
Matthias Braun's avatar
Matthias Braun committed
229
	ir_node   *sub         = new_rd_Sub(dbgi, true_block, float_x, limitc,
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
230
	                                    mode_f);
Matthias Braun's avatar
Matthias Braun committed
231
	ir_node   *sub_conv    = new_rd_Conv(dbgi, true_block, sub, mode_s);
232
	ir_node   *xorn        = new_rd_Eor(dbgi, true_block, sub_conv, c_const);
Matthias Braun's avatar
Matthias Braun committed
233
234
235
236
237
238
239
240

	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);
241
	collect_new_phi_node(phi);
Matthias Braun's avatar
Matthias Braun committed
242
243
244

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

Matthias Braun's avatar
Matthias Braun committed
247
static bool sparc_rewrite_Conv(ir_node *node)
248
249
250
251
252
253
{
	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)
254
255
	    && get_mode_size_bits(from_mode) == 32
	    && !mode_is_signed(from_mode)) {
256
		rewrite_unsigned_float_Conv(node);
Matthias Braun's avatar
Matthias Braun committed
257
		return true;
258
	}
259
	if (mode_is_float(from_mode) && mode_is_int(to_mode)
260
	    && get_mode_size_bits(to_mode) <= 32
261
	    && !mode_is_signed(to_mode)) {
262
263
		rewrite_float_unsigned_Conv(node);
		return true;
264
	}
265

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

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

static void handle_intrinsic(ir_node *node, void *data)
273
{
Matthias Braun's avatar
Matthias Braun committed
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
	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;
	}
}
289

290
291
static ir_type *make_mod_type(ir_type *const tp)
{
292
	ir_type *const mtp = new_type_method(2, 1, false);
293
294
295
296
297
298
	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
299
300
301
302
static void sparc_create_runtime_entities(void)
{
	if (rem != NULL)
		return;
303

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

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

Matthias Braun's avatar
Matthias Braun committed
313
314
315
316
static void sparc_handle_intrinsics(ir_graph *irg)
{
	sparc_create_runtime_entities();
	ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
317
	collect_phiprojs_and_start_block_nodes(irg);
Matthias Braun's avatar
Matthias Braun committed
318
319
320
321
322
323
	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,
324
			IR_GRAPH_PROPERTY_NO_BADS
Matthias Braun's avatar
Matthias Braun committed
325
326
327
328
			| IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES
			| IR_GRAPH_PROPERTY_MANY_RETURNS
			| IR_GRAPH_PROPERTY_ONE_RETURN);
	}
329
330
}

331
332
static void sparc_setup_cg_config(void)
{
333
334
	memset(&sparc_cg_config, 0, sizeof(sparc_cg_config));
	bool has_fpu = false;
335
	switch ((sparc_cpu_t)cpu) {
336
337
338
339
	case cpu_v8plus:
		sparc_cg_config.use_cas = true;
		has_fpu = false;
		break;
340
	case cpu_leon:
341
342
343
		sparc_cg_config.use_cas = true;
		has_fpu = true;
		break;
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
	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;
	}
}

363
364
static void sparc_init(void)
{
365
	sparc_init_asm_constraints();
366
	sparc_register_init();
367
	sparc_create_opcodes();
368
	sparc_cconv_init();
369
	sparc_setup_cg_config();
370
371
}

Matthias Braun's avatar
Matthias Braun committed
372
373
374
375
376
static void sparc_finish(void)
{
	sparc_free_opcodes();
}

377
378
379
380
381
382
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
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);
415
	return be_new_Proj(load, pn_sparc_Ld_res);
416
417
418
419
420
421
422
423
424
}

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

425
static void sparc_generate_code(FILE *output, const char *cup_name)
Hannes Rapp's avatar
Hannes Rapp committed
426
{
427
428
	be_gas_elf_type_char = '#';
	be_gas_elf_variant   = ELF_VARIANT_SPARC;
429
	sparc_constants = pmap_create();
Hannes Rapp's avatar
Hannes Rapp committed
430

431
	be_begin(output, cup_name);
432
	unsigned *const sp_is_non_ssa = rbitset_alloca(N_SPARC_REGISTERS);
433
	rbitset_set(sp_is_non_ssa, REG_SP);
434
435
436
437
438

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

439
440
441
		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
442
		be_birg_from_irg(irg)->non_ssa_regs = sp_is_non_ssa;
443
444
445
446
447
448
		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
449
		                   NULL, sparc_modifies_flags, NULL);
450
		be_sched_fix_flags(irg, &sparc_reg_classes[CLASS_sparc_fpflags],
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
451
		                   NULL, sparc_modifies_fp_flags, NULL);
452
453
		be_timer_pop(T_RA_PREPARATION);

454
		be_step_regalloc(irg, &sparc_regalloc_if);
455
456
457
458
459
460
461
462

		sparc_finish_graph(irg);
		sparc_emit_function(irg);

		be_step_last(irg);
	}

	be_finish();
463
	pmap_destroy(sparc_constants);
Hannes Rapp's avatar
Hannes Rapp committed
464
465
}

466
467
static void sparc_lower_for_target(void)
{
468
	lower_calls_with_compounds(LF_RETURN_HIDDEN, NULL);
469
	be_after_irp_transform("lower-calls");
470

471
	foreach_irp_irg(i, irg) {
472
473
474
		/* Turn all small CopyBs into loads/stores and all bigger CopyBs into
		 * memcpy calls. */
		lower_CopyB(irg, 31, 32, false);
475
		be_after_transform(irg, "lower-copyb");
476
477
	}

478
	if (!sparc_cg_config.use_fpu) {
479
		lower_floating_point();
480
481
		be_after_irp_transform("lower-fp");
	}
482

483
	ir_builtin_kind supported[8];
484
	size_t s = 0;
485
	supported[s++] = ir_bk_saturating_increment;
486
487
	if (sparc_cg_config.use_cas)
		supported[s++] = ir_bk_compare_swap;
488
	supported[s++] = ir_bk_va_start;
489
490
	assert(s < ARRAY_SIZE(supported));
	lower_builtins(s, supported);
491
	be_after_irp_transform("lower-builtins");
492

Matthias Braun's avatar
Matthias Braun committed
493
	ir_mode *mode_gp = sparc_reg_classes[CLASS_sparc_gp].mode;
494
	foreach_irp_irg(i, irg) {
495
		lower_switch(irg, 4, 256, mode_gp);
496
		be_after_transform(irg, "lower-switch");
497
498
	}

499
	sparc_lower_64bit();
500
	be_after_irp_transform("lower-64");
501

502
	foreach_irp_irg(i, irg) {
503
		ir_lower_mode_b(irg, mode_Iu);
504
		be_after_transform(irg, "lower-modeb");
505
		lower_alloc(irg, SPARC_PO2_STACK_ALIGNMENT);
506
		be_after_transform(irg, "lower-alloc");
507
	}
508
509
}

510
511
512
static int sparc_is_mux_allowed(ir_node *sel, ir_node *mux_false,
                                ir_node *mux_true)
{
513
	return ir_is_optimizable_mux(sel, mux_false, mux_true);
514
515
}

Hannes Rapp's avatar
Hannes Rapp committed
516
517
518
/**
 * Returns the libFirm configuration parameter for this backend.
 */
519
520
static const backend_params *sparc_get_backend_params(void)
{
521
	static const ir_settings_arch_dep_t arch_dep = {
522
523
524
525
526
527
528
		.also_use_subs        = true,
		.maximum_shifts       = 1,
		.highest_shift_amount = 31,
		.evaluate             = NULL,
		.allow_mulhs          = true,
		.allow_mulhu          = true,
		.max_bits_for_mulh    = 32,
529
	};
Hannes Rapp's avatar
Hannes Rapp committed
530
	static backend_params p = {
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
		.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_long                 = NULL,  /* will be set later */
		.type_unsigned_long_long        = 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                         = {
546
547
			.va_list_type = NULL, /* will be set later */
			.lower_va_arg = be_default_lower_va_arg,
548
		},
Hannes Rapp's avatar
Hannes Rapp committed
549
	};
550
551

	ir_mode *mode_long_long
552
		= new_int_mode("long long", irma_twos_complement, 64, 1, 64);
553
554
	ir_type *type_long_long = new_type_primitive(mode_long_long);
	ir_mode *mode_unsigned_long_long
555
		= new_int_mode("unsigned long long", irma_twos_complement, 64, 0, 64);
556
557
	ir_type *type_unsigned_long_long
		= new_type_primitive(mode_unsigned_long_long);
558
559
	ir_type *type_va_list
		= new_type_pointer(new_type_primitive(mode_ANY));
560
561
562

	p.type_long_long          = type_long_long;
	p.type_unsigned_long_long = type_unsigned_long_long;
563
	p.vararg.va_list_type     = type_va_list;
564

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

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

582
static arch_isa_if_t const sparc_isa_if = {
583
584
585
586
587
588
589
590
591
	.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,
592
	.is_valid_clobber      = be_default_is_valid_clobber,
593
594
	.handle_intrinsics     = sparc_handle_intrinsics,
	.get_op_estimated_cost = sparc_get_op_estimated_cost,
Hannes Rapp's avatar
Hannes Rapp committed
595
596
};

597
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc)
Hannes Rapp's avatar
Hannes Rapp committed
598
599
void be_init_arch_sparc(void)
{
600
601
602
603
604
	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
605
606
607
608
609
	be_register_isa_if("sparc", &sparc_isa_if);
	FIRM_DBG_REGISTER(dbg, "firm.be.sparc.cg");
	sparc_init_transform();
	sparc_init_emitter();
}