sparc_bearch.c 17.4 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
337
338
	case cpu_v8plus:
		sparc_cg_config.use_cas = true;
		has_fpu = false;
		break;
339
	case cpu_leon:
340
341
342
		sparc_cg_config.use_cas = true;
		has_fpu = true;
		break;
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
	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;
	}
}

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

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

376
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
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);
414
	return be_new_Proj(load, pn_sparc_Ld_res);
415
416
417
418
419
420
421
422
423
}

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

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

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

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

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

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

		sparc_finish_graph(irg);
		sparc_emit_function(irg);

		be_step_last(irg);
	}

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

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

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

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

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

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

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

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

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

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

	ir_mode *mode_unsigned_long_long
550
		= new_int_mode("unsigned long long", irma_twos_complement, 64, 0, 64);
551
	ir_type *type_unsigned_long_long
552
		= get_type_for_mode(mode_unsigned_long_long);
553
	ir_type *type_va_list
554
		= new_type_pointer(get_type_for_mode(mode_ANY));
555
556

	p.type_unsigned_long_long = type_unsigned_long_long;
557
	p.vararg.va_list_type     = type_va_list;
558

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

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

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

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