bearch_sparc.c 17 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
13
14
15
#include "be_t.h"
#include "bearch_sparc_t.h"
#include "beflags.h"
#include "begnuas.h"
#include "bemodule.h"
16
#include "bera.h"
17
18
19
#include "besched.h"
#include "betranshlp.h"
#include "gen_sparc_regalloc_if.h"
20
#include "irarch_t.h"
21
#include "ircons_t.h"
Hannes Rapp's avatar
Hannes Rapp committed
22
#include "irgmod.h"
23
#include "irgwalk.h"
24
#include "iropt_t.h"
25
26
27
#include "irprog_t.h"
#include "irtools.h"
#include "lc_opts_enum.h"
28
#include "lower_alloc.h"
29
#include "lower_builtins.h"
30
#include "lower_calls.h"
31
#include "lower_mode_b.h"
32
#include "lower_softfloat.h"
33
34
35
#include "lowering.h"
#include "sparc_cconv.h"
#include "sparc_emitter.h"
Hannes Rapp's avatar
Hannes Rapp committed
36
37
#include "sparc_new_nodes.h"
#include "sparc_transform.h"
38
#include "util.h"
39

Hannes Rapp's avatar
Hannes Rapp committed
40
41
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

42
43
pmap *sparc_constants;

44
45
ir_mode *sparc_mode_Q;

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
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       },
	{ "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
};

88
static bool use_softfloat;
89
90
91
92
93
94
95
96

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
97
/**
98
 * Transforms the standard firm graph into a SPARC firm graph
Hannes Rapp's avatar
Hannes Rapp committed
99
 */
100
static void sparc_select_instructions(ir_graph *irg)
Hannes Rapp's avatar
Hannes Rapp committed
101
{
102
	be_timer_push(T_CODEGEN);
103
	sparc_transform_graph(irg);
104
	be_timer_pop(T_CODEGEN);
105
	be_dump(DUMP_BE, irg, "code-selection");
Hannes Rapp's avatar
Hannes Rapp committed
106
107
}

108
109
static bool sparc_modifies_flags(const ir_node *node)
{
110
	be_foreach_out(node, o) {
111
		const arch_register_req_t *req = arch_get_irn_register_req_out(node, o);
112
		if (req->cls == &sparc_reg_classes[CLASS_sparc_flags])
113
114
115
			return true;
	}
	return false;
116
117
118
119
}

static bool sparc_modifies_fp_flags(const ir_node *node)
{
120
	be_foreach_out(node, o) {
121
		const arch_register_req_t *req = arch_get_irn_register_req_out(node, o);
122
		if (req->cls == &sparc_reg_classes[CLASS_sparc_fpflags])
123
124
125
			return true;
	}
	return false;
126
127
}

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
 * 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
146
147
148
149
150
151
152
	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);
153
	ir_node   *zero        = new_r_Const_null(irg, mode_s);
154
	collect_new_start_block_node(zero);
Matthias Braun's avatar
Matthias Braun committed
155
156
157
158
159
160
161
162
163
164
165
166
167
	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);
168
	collect_new_start_block_node(c_const);
Matthias Braun's avatar
Matthias Braun committed
169
170
171
172
173
174
175
176
	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);
177
	collect_new_phi_node(phi);
Matthias Braun's avatar
Matthias Braun committed
178
179
180

	ir_node *res_conv = new_rd_Conv(dbgi, lower_block, phi, dest_mode);
	exchange(node, res_conv);
181
182
}

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/**
 * 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
202
203
204
205
206
207
208
	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);
209
	collect_new_start_block_node(limitc);
Matthias Braun's avatar
Matthias Braun committed
210
211
212
213
214
215
216
217
218
219
220
221
	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);

222
	ir_node   *c_const     = new_r_Const_long(irg, mode_s, 0x80000000L);
223
	collect_new_start_block_node(c_const);
Matthias Braun's avatar
Matthias Braun committed
224
225
226
227
228
229
230
231
232
233
234
235
236
	ir_node   *sub         = new_rd_Sub(dbgi, true_block, float_x, limitc,
										mode_f);
	ir_node   *sub_conv    = new_rd_Conv(dbgi, true_block, sub, mode_s);
	ir_node   *xorn        = new_rd_Eor(dbgi, true_block, sub_conv, c_const,
										mode_s);

	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);
237
	collect_new_phi_node(phi);
Matthias Braun's avatar
Matthias Braun committed
238
239
240

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

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

Matthias Braun's avatar
Matthias Braun committed
262
	return false;
263
264
}

Matthias Braun's avatar
Matthias Braun committed
265
266
267
268
static ir_entity *rem;
static ir_entity *urem;

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

Matthias Braun's avatar
Matthias Braun committed
286
287
288
289
static void sparc_create_runtime_entities(void)
{
	if (rem != NULL)
		return;
290

Matthias Braun's avatar
Matthias Braun committed
291
292
293
294
295
	ir_type *int_tp = new_type_primitive(mode_Is);
	ir_type *mod_tp = new_type_method(2, 1);
	set_method_param_type(mod_tp, 0, int_tp);
	set_method_param_type(mod_tp, 1, int_tp);
	set_method_res_type(mod_tp, 0, int_tp);
Matthias Braun's avatar
Matthias Braun committed
296
	rem = create_compilerlib_entity(new_id_from_str(".rem"), mod_tp);
Matthias Braun's avatar
Matthias Braun committed
297
298
299
300
301
302

	ir_type *umod_tp = new_type_method(2, 1);
	ir_type *uint_tp = new_type_primitive(mode_Iu);
	set_method_param_type(umod_tp, 0, uint_tp);
	set_method_param_type(umod_tp, 1, uint_tp);
	set_method_res_type(umod_tp, 0, uint_tp);
Matthias Braun's avatar
Matthias Braun committed
303
304
	urem = create_compilerlib_entity(new_id_from_str(".urem"), umod_tp);
}
Matthias Braun's avatar
Matthias Braun committed
305

Matthias Braun's avatar
Matthias Braun committed
306
307
308
309
static void sparc_handle_intrinsics(ir_graph *irg)
{
	sparc_create_runtime_entities();
	ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
310
	collect_phiprojs_and_start_block_nodes(irg);
Matthias Braun's avatar
Matthias Braun committed
311
312
313
314
315
316
	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,
317
			IR_GRAPH_PROPERTY_NO_BADS
Matthias Braun's avatar
Matthias Braun committed
318
319
320
321
			| IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES
			| IR_GRAPH_PROPERTY_MANY_RETURNS
			| IR_GRAPH_PROPERTY_ONE_RETURN);
	}
322
323
}

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

356
357
static void sparc_init(void)
{
358
	sparc_init_asm_constraints();
359
	sparc_register_init();
360
	sparc_create_opcodes();
361
	sparc_cconv_init();
362
	sparc_setup_cg_config();
363
364
}

Matthias Braun's avatar
Matthias Braun committed
365
366
367
368
369
static void sparc_finish(void)
{
	sparc_free_opcodes();
}

370
371
372
373
374
375
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
414
415
416
417
418
419
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);
	ir_node *res = new_r_Proj(load, mode, pn_sparc_Ld_res);

	return res;
}

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

420
static void sparc_generate_code(FILE *output, const char *cup_name)
Hannes Rapp's avatar
Hannes Rapp committed
421
{
422
423
	be_gas_elf_type_char = '#';
	be_gas_elf_variant   = ELF_VARIANT_SPARC;
424
	sparc_constants = pmap_create();
Hannes Rapp's avatar
Hannes Rapp committed
425

426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
	be_begin(output, cup_name);

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

		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],
						   NULL, sparc_modifies_flags, NULL);
		be_sched_fix_flags(irg, &sparc_reg_classes[CLASS_sparc_fpflags],
						   NULL, sparc_modifies_fp_flags, NULL);
		be_timer_pop(T_RA_PREPARATION);

443
		be_step_regalloc(irg, &sparc_regalloc_if);
444
445
446
447
448
449
450
451

		sparc_finish_graph(irg);
		sparc_emit_function(irg);

		be_step_last(irg);
	}

	be_finish();
452
	pmap_destroy(sparc_constants);
Hannes Rapp's avatar
Hannes Rapp committed
453
454
}

455
456
static void sparc_lower_for_target(void)
{
457
	lower_calls_with_compounds(LF_RETURN_HIDDEN);
458
	be_after_irp_transform("lower-calls");
459

460
	foreach_irp_irg(i, irg) {
461
462
463
		/* Turn all small CopyBs into loads/stores and all bigger CopyBs into
		 * memcpy calls. */
		lower_CopyB(irg, 31, 32, false);
464
		be_after_transform(irg, "lower-copyb");
465
466
	}

467
	if (!sparc_cg_config.use_fpu) {
468
		lower_floating_point();
469
470
		be_after_irp_transform("lower-fp");
	}
471

472
	ir_builtin_kind supported[8];
473
	size_t s = 0;
474
	supported[s++] = ir_bk_saturating_increment;
475
476
	if (sparc_cg_config.use_cas)
		supported[s++] = ir_bk_compare_swap;
477
478
	assert(s < ARRAY_SIZE(supported));
	lower_builtins(s, supported);
479
	be_after_irp_transform("lower-builtins");
480

Matthias Braun's avatar
Matthias Braun committed
481
	ir_mode *mode_gp = sparc_reg_classes[CLASS_sparc_gp].mode;
482
	foreach_irp_irg(i, irg) {
483
		lower_switch(irg, 4, 256, mode_gp);
484
		be_after_transform(irg, "lower-switch");
485
486
	}

487
	sparc_lower_64bit();
488
	be_after_irp_transform("lower-64");
489

490
	foreach_irp_irg(i, irg) {
491
		ir_lower_mode_b(irg, mode_Iu);
492
		be_after_transform(irg, "lower-modeb");
493
		lower_alloc(irg, SPARC_PO2_STACK_ALIGNMENT);
494
		be_after_transform(irg, "lower-alloc");
495
	}
496
497
}

498
499
500
static int sparc_is_mux_allowed(ir_node *sel, ir_node *mux_false,
                                ir_node *mux_true)
{
501
	return ir_is_optimizable_mux(sel, mux_false, mux_true);
502
503
}

Hannes Rapp's avatar
Hannes Rapp committed
504
505
506
/**
 * Returns the libFirm configuration parameter for this backend.
 */
507
508
static const backend_params *sparc_get_backend_params(void)
{
509
	static const ir_settings_arch_dep_t arch_dep = {
510
511
512
513
514
515
516
		.also_use_subs        = true,
		.maximum_shifts       = 1,
		.highest_shift_amount = 31,
		.evaluate             = NULL,
		.allow_mulhs          = true,
		.allow_mulhu          = true,
		.max_bits_for_mulh    = 32,
517
	};
Hannes Rapp's avatar
Hannes Rapp committed
518
	static backend_params p = {
519
520
521
522
523
524
525
526
527
528
529
530
531
		.byte_order_big_endian         = true,
		.pic_supported                 = false,
		.unaligned_memaccess_supported = false,
		.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,
Hannes Rapp's avatar
Hannes Rapp committed
532
	};
533
534

	ir_mode *mode_long_long
535
		= new_int_mode("long long", irma_twos_complement, 64, 1, 64);
536
537
	ir_type *type_long_long = new_type_primitive(mode_long_long);
	ir_mode *mode_unsigned_long_long
538
		= new_int_mode("unsigned long long", irma_twos_complement, 64, 0, 64);
539
540
541
542
543
	ir_type *type_unsigned_long_long
		= new_type_primitive(mode_unsigned_long_long);

	p.type_long_long          = type_long_long;
	p.type_unsigned_long_long = type_unsigned_long_long;
544

545
546
547
	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);
548
549
550
	set_type_alignment_bytes(type_long_double, 8);
	set_type_size_bytes(type_long_double, 16);
	p.type_long_double = type_long_double;
Hannes Rapp's avatar
Hannes Rapp committed
551
552
553
	return &p;
}

554
555
556
557
558
559
560
561
static unsigned sparc_get_op_estimated_cost(const ir_node *node)
{
	/* TODO: refine */
	if (sparc_has_load_store_attr(node))
		return 5;
	return 1;
}

562
static arch_isa_if_t const sparc_isa_if = {
563
564
565
566
567
568
569
570
571
572
573
574
	.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,
	.is_valid_clobber      = sparc_is_valid_clobber,
	.handle_intrinsics     = sparc_handle_intrinsics,
	.get_op_estimated_cost = sparc_get_op_estimated_cost,
Hannes Rapp's avatar
Hannes Rapp committed
575
576
};

577
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc)
Hannes Rapp's avatar
Hannes Rapp committed
578
579
void be_init_arch_sparc(void)
{
580
581
582
583
584
	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
585
586
587
588
589
	be_register_isa_if("sparc", &sparc_isa_if);
	FIRM_DBG_REGISTER(dbg, "firm.be.sparc.cg");
	sparc_init_transform();
	sparc_init_emitter();
}