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
	sparc_init_asm_constraints();
370
	sparc_register_init();
371
	sparc_create_opcodes();
372
	sparc_cconv_init();
373
	sparc_setup_cg_config();
374
375
}

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

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
415
416
417
418
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);
419
	return be_new_Proj(load, pn_sparc_Ld_res);
420
421
422
423
424
425
426
427
428
}

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

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

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

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

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

458
		be_step_regalloc(irg, &sparc_regalloc_if);
459
460
461
462
463
464
465
466

		sparc_finish_graph(irg);
		sparc_emit_function(irg);

		be_step_last(irg);
	}

	be_finish();
467
	pmap_destroy(sparc_constants);
Hannes Rapp's avatar
Hannes Rapp committed
468
469
}

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

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

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

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

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

503
	sparc_lower_64bit();
504
	be_after_irp_transform("lower-64");
505

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

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

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

553
	ir_type *type_va_list
554
		= new_type_pointer(get_type_for_mode(mode_ANY));
555
	p.vararg.va_list_type = type_va_list;
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();
}