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();
}