bearch_sparc.c 18 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
16
17
18
19
20
21
 */
#include "config.h"

#include "lc_opts.h"
#include "lc_opts_enum.h"

#include "irgwalk.h"
#include "irprog.h"
#include "ircons.h"
#include "irgmod.h"
#include "irgopt.h"
#include "iroptimize.h"
22
23
#include "irtools.h"
#include "irdump.h"
24
#include "iropt_t.h"
Hannes Rapp's avatar
Hannes Rapp committed
25
#include "lowering.h"
26
#include "lower_dw.h"
27
#include "lower_alloc.h"
28
#include "lower_builtins.h"
29
#include "lower_calls.h"
30
#include "lower_mode_b.h"
31
#include "lower_softfloat.h"
Hannes Rapp's avatar
Hannes Rapp committed
32
33
#include "debug.h"
#include "array_t.h"
34
#include "error.h"
35
#include "util.h"
36
#include "be_t.h"
37
38
39
40
41
42
43
44
45
#include "bearch.h"
#include "benode.h"
#include "belower.h"
#include "besched.h"
#include "bemodule.h"
#include "begnuas.h"
#include "belistsched.h"
#include "beflags.h"
#include "beutil.h"
Hannes Rapp's avatar
Hannes Rapp committed
46
47
48
49
50
51
52

#include "bearch_sparc_t.h"

#include "sparc_new_nodes.h"
#include "gen_sparc_regalloc_if.h"
#include "sparc_transform.h"
#include "sparc_emitter.h"
53
#include "sparc_cconv.h"
54

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

57
static ir_entity *sparc_get_frame_entity(const ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
58
{
59
60
61
	if (is_sparc_FrameAddr(node)) {
		const sparc_attr_t *attr = get_sparc_attr_const(node);
		return attr->immediate_value_entity;
Hannes Rapp's avatar
Hannes Rapp committed
62
63
	}

64
65
66
	if (sparc_has_load_store_attr(node)) {
		const sparc_load_store_attr_t *load_store_attr
			= get_sparc_load_store_attr_const(node);
Hannes Rapp's avatar
Hannes Rapp committed
67
		if (load_store_attr->is_frame_entity) {
68
			return load_store_attr->base.immediate_value_entity;
Hannes Rapp's avatar
Hannes Rapp committed
69
70
71
		}
	}

Hannes Rapp's avatar
Hannes Rapp committed
72
73
74
75
76
77
78
	return NULL;
}

/**
 * This function is called by the generic backend to correct offsets for
 * nodes accessing the stack.
 */
79
static void sparc_set_frame_offset(ir_node *node, int offset)
Hannes Rapp's avatar
Hannes Rapp committed
80
{
81
82
83
84
85
86
	sparc_attr_t *attr = get_sparc_attr(node);
	attr->immediate_value += offset;

	/* must be a FrameAddr or a load/store node with frame_entity */
	assert(is_sparc_FrameAddr(node) ||
			get_sparc_load_store_attr_const(node)->is_frame_entity);
Hannes Rapp's avatar
Hannes Rapp committed
87
88
}

89
static int sparc_get_sp_bias(const ir_node *node)
Hannes Rapp's avatar
Hannes Rapp committed
90
{
91
	if (is_sparc_Save(node)) {
92
93
94
95
		const sparc_attr_t *attr = get_sparc_attr_const(node);
		if (get_irn_arity(node) == 3)
			panic("no support for _reg variant yet");

96
		return -attr->immediate_value;
97
98
	} else if (is_sparc_RestoreZero(node)) {
		return SP_BIAS_RESET;
99
100
	}
	return 0;
Hannes Rapp's avatar
Hannes Rapp committed
101
102
103
104
}

/* fill register allocator interface */

105
const arch_irn_ops_t sparc_irn_ops = {
Hannes Rapp's avatar
Hannes Rapp committed
106
107
108
109
110
111
112
113
114
115
116
117
	sparc_get_frame_entity,
	sparc_set_frame_offset,
	sparc_get_sp_bias,
	NULL,    /* get_op_estimated_cost   */
	NULL,    /* possible_memory_operand */
	NULL,    /* perform_memory_operand  */
};

/**
 * Transforms the standard firm graph into
 * a SPARC firm graph
 */
118
static void sparc_prepare_graph(ir_graph *irg)
Hannes Rapp's avatar
Hannes Rapp committed
119
{
120
	sparc_transform_graph(irg);
Hannes Rapp's avatar
Hannes Rapp committed
121
122
}

123
124
static bool sparc_modifies_flags(const ir_node *node)
{
125
	be_foreach_out(node, o) {
126
127
128
129
130
		const arch_register_req_t *req = arch_get_irn_register_req_out(node, o);
		if (req->cls == &sparc_reg_classes[CLASS_sparc_flags_class])
			return true;
	}
	return false;
131
132
133
134
}

static bool sparc_modifies_fp_flags(const ir_node *node)
{
135
	be_foreach_out(node, o) {
136
137
138
139
140
		const arch_register_req_t *req = arch_get_irn_register_req_out(node, o);
		if (req->cls == &sparc_reg_classes[CLASS_sparc_fpflags_class])
			return true;
	}
	return false;
141
142
}

143
static void sparc_before_ra(ir_graph *irg)
Hannes Rapp's avatar
Hannes Rapp committed
144
145
{
	/* fixup flags register */
146
	be_sched_fix_flags(irg, &sparc_reg_classes[CLASS_sparc_flags_class],
147
	                   NULL, sparc_modifies_flags);
148
	be_sched_fix_flags(irg, &sparc_reg_classes[CLASS_sparc_fpflags_class],
149
	                   NULL, sparc_modifies_fp_flags);
Hannes Rapp's avatar
Hannes Rapp committed
150
151
}

152
extern const arch_isa_if_t sparc_isa_if;
Hannes Rapp's avatar
Hannes Rapp committed
153
154
static sparc_isa_t sparc_isa_template = {
	{
155
		&sparc_isa_if,                       /* isa interface implementation */
156
157
		N_SPARC_REGISTERS,
		sparc_registers,
158
159
		N_SPARC_CLASSES,
		sparc_reg_classes,
160
161
162
163
164
165
166
		&sparc_registers[REG_SP],            /* stack pointer register */
		&sparc_registers[REG_FRAME_POINTER], /* base pointer register */
		3,                                   /* power of two stack alignment
		                                        for calls */
		7,                                   /* costs for a spill instruction */
		5,                                   /* costs for a reload instruction */
		true,                                /* custom abi handling */
Hannes Rapp's avatar
Hannes Rapp committed
167
	},
168
169
	NULL,                                  /* constants */
	SPARC_FPU_ARCH_FPU,                    /* FPU architecture */
Hannes Rapp's avatar
Hannes Rapp committed
170
171
};

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/**
 * 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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
	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);
	ir_node   *zero        = new_r_Const(irg, get_mode_null(mode_s));
	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);
	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);
	assert(get_Block_phis(lower_block) == NULL);
	set_Block_phis(lower_block, phi);
	set_Phi_next(phi, NULL);

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

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/**
 * 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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
	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);
	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);

	ir_tarval *correction  = new_tarval_from_long(0x80000000l, mode_s);
	ir_node   *c_const     = new_r_Const(irg, correction);
	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);
	assert(get_Block_phis(lower_block) == NULL);
	set_Block_phis(lower_block, phi);
	set_Phi_next(phi, NULL);

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

288
289
static int sparc_rewrite_Conv(ir_node *node, void *ctx)
{
Matthias Braun's avatar
Matthias Braun committed
290
	(void) ctx;
291
292
293
294
295
	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)
296
297
	    && get_mode_size_bits(from_mode) == 32
	    && !mode_is_signed(from_mode)) {
298
299
300
		rewrite_unsigned_float_Conv(node);
		return 1;
	}
301
	if (mode_is_float(from_mode) && mode_is_int(to_mode)
302
	    && get_mode_size_bits(to_mode) <= 32
303
304
305
306
	    && !mode_is_signed(to_mode)) {
	    rewrite_float_unsigned_Conv(node);
	    return 1;
	}
307
308
309
310

	return 0;
}

311
312
static void sparc_handle_intrinsics(void)
{
Matthias Braun's avatar
Matthias Braun committed
313
	i_record records[3];
314
	size_t n_records = 0;
315

316
	/* we need to rewrite some forms of int->float conversions */
Matthias Braun's avatar
Matthias Braun committed
317
318
319
320
	i_instr_record *map_Conv = &records[n_records++].i_instr;
	map_Conv->kind     = INTRINSIC_INSTR;
	map_Conv->op       = op_Conv;
	map_Conv->i_mapper = sparc_rewrite_Conv;
321
322

	/* SPARC has no signed mod instruction ... */
Matthias Braun's avatar
Matthias Braun committed
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
	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);

	runtime_rt rt_iMod;
	ident *mod_id = new_id_from_str(".rem");
	rt_iMod.ent             = new_entity(get_glob_type(), mod_id, mod_tp);
	set_entity_ld_ident(rt_iMod.ent, mod_id);
	rt_iMod.mode            = mode_T;
	rt_iMod.res_mode        = mode_Is;
	rt_iMod.mem_proj_nr     = pn_Mod_M;
	rt_iMod.regular_proj_nr = pn_Mod_X_regular;
	rt_iMod.exc_proj_nr     = pn_Mod_X_except;
	rt_iMod.res_proj_nr     = pn_Mod_res;
	set_entity_visibility(rt_iMod.ent, ir_visibility_external);

	i_instr_record *map_imod = &records[n_records++].i_instr;
	map_imod->kind     = INTRINSIC_INSTR;
	map_imod->op       = op_Mod;
	map_imod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
	map_imod->ctx      = &rt_iMod;
346

Matthias Braun's avatar
Matthias Braun committed
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
	/* ... nor an unsigned mod. */
	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);

	runtime_rt rt_uMod;
	ident *umod_id = new_id_from_str(".urem");
	rt_uMod.ent             = new_entity(get_glob_type(), umod_id, umod_tp);
	set_entity_ld_ident(rt_uMod.ent, umod_id);
	rt_uMod.mode            = mode_T;
	rt_uMod.res_mode        = mode_Iu;
	rt_uMod.mem_proj_nr     = pn_Mod_M;
	rt_uMod.regular_proj_nr = pn_Mod_X_regular;
	rt_uMod.exc_proj_nr     = pn_Mod_X_except;
	rt_uMod.res_proj_nr     = pn_Mod_res;
	set_entity_visibility(rt_uMod.ent, ir_visibility_external);

	i_instr_record *map_umod = &records[n_records++].i_instr;
	map_umod->kind     = INTRINSIC_INSTR;
	map_umod->op       = op_Mod;
	map_umod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
	map_umod->ctx      = &rt_uMod;

	assert(n_records <= ARRAY_SIZE(records));
373
	lower_intrinsics(records, n_records, /*part_block_used=*/ true);
374
375
}

376
377
378
379
380
381
382
static void sparc_init(void)
{
	sparc_register_init();
	sparc_create_opcodes(&sparc_irn_ops);
	sparc_cconv_init();
}

Matthias Braun's avatar
Matthias Braun committed
383
384
385
386
387
static void sparc_finish(void)
{
	sparc_free_opcodes();
}

388
static arch_env_t *sparc_begin_codegeneration(void)
Hannes Rapp's avatar
Hannes Rapp committed
389
{
390
	sparc_isa_t *isa = XMALLOC(sparc_isa_t);
391
	*isa = sparc_isa_template;
392
	isa->constants = pmap_create();
Hannes Rapp's avatar
Hannes Rapp committed
393

394
395
	be_gas_elf_type_char = '#';
	be_gas_elf_variant   = ELF_VARIANT_SPARC;
396

397
	return &isa->base;
Hannes Rapp's avatar
Hannes Rapp committed
398
399
400
401
402
}

/**
 * Closes the output file and frees the ISA structure.
 */
403
static void sparc_end_codegeneration(void *self)
Hannes Rapp's avatar
Hannes Rapp committed
404
{
405
	sparc_isa_t *isa = (sparc_isa_t*)self;
406
407
	pmap_destroy(isa->constants);
	free(isa);
Hannes Rapp's avatar
Hannes Rapp committed
408
409
}

410
411
static void sparc_lower_for_target(void)
{
412
	lower_calls_with_compounds(LF_RETURN_HIDDEN);
413

Matthias Braun's avatar
Matthias Braun committed
414
	for (size_t i = 0, n_irgs = get_irp_n_irgs(); i < n_irgs; ++i) {
415
416
417
418
419
420
		ir_graph *irg = get_irp_irg(i);
		/* Turn all small CopyBs into loads/stores and all bigger CopyBs into
		 * memcpy calls. */
		lower_CopyB(irg, 31, 32, false);
	}

421
422
423
	if (sparc_isa_template.fpu_arch == SPARC_FPU_ARCH_SOFTFLOAT)
		lower_floating_point();

424
425
	lower_builtins(0, NULL);

Matthias Braun's avatar
Matthias Braun committed
426
427
	ir_mode *mode_gp = sparc_reg_classes[CLASS_sparc_gp].mode;
	for (size_t i = 0, n_irgs = get_irp_n_irgs(); i < n_irgs; ++i) {
428
429
430
431
		ir_graph *irg = get_irp_irg(i);
		lower_switch(irg, 4, 256, mode_gp);
	}

432
433
	sparc_lower_64bit();

Matthias Braun's avatar
Matthias Braun committed
434
	for (size_t i = 0, n_irgs = get_irp_n_irgs(); i < n_irgs; ++i) {
435
		ir_graph *irg = get_irp_irg(i);
436
		ir_lower_mode_b(irg, mode_Iu);
Manuel Mohr's avatar
Manuel Mohr committed
437
438
439
		/* TODO: Pass SPARC_MIN_STACKSIZE as addr_delta as soon as
		 * Alloc nodes are implemented more efficiently. */
		lower_alloc(irg, SPARC_STACK_ALIGNMENT, true, 0);
440
	}
441
442
}

443
444
445
static int sparc_is_mux_allowed(ir_node *sel, ir_node *mux_false,
                                ir_node *mux_true)
{
446
	return ir_is_optimizable_mux(sel, mux_false, mux_true);
447
448
}

Hannes Rapp's avatar
Hannes Rapp committed
449
450
451
/**
 * Returns the libFirm configuration parameter for this backend.
 */
452
453
static const backend_params *sparc_get_backend_params(void)
{
454
455
456
457
458
459
460
461
462
	static const ir_settings_arch_dep_t arch_dep = {
		1,     /* also_use_subs */
		1,     /* maximum_shifts */
		31,    /* highest_shift_amount */
		NULL,  /* evaluate_cost_func */
		1,     /* allow mulhs */
		1,     /* allow mulhu */
		32,    /* max_bits_for_mulh */
	};
Hannes Rapp's avatar
Hannes Rapp committed
463
	static backend_params p = {
464
		0,     /* no support for RotL nodes */
465
		1,     /* big endian */
466
467
		1,     /* modulo shift efficient */
		0,     /* non-modulo shift not efficient */
468
		&arch_dep,              /* will be set later */
469
		sparc_is_mux_allowed,   /* parameter for if conversion */
470
		32,    /* machine size */
Hannes Rapp's avatar
Hannes Rapp committed
471
		NULL,  /* float arithmetic mode */
472
473
474
		NULL,  /* long long type */
		NULL,  /* usigned long long type */
		NULL,  /* long double type */
Hannes Rapp's avatar
Hannes Rapp committed
475
476
477
478
479
		0,     /* no trampoline support: size 0 */
		0,     /* no trampoline support: align 0 */
		NULL,  /* no trampoline support: no trampoline builder */
		4      /* alignment of stack parameter: typically 4 (32bit) or 8 (64bit) */
	};
480
481

	ir_mode *mode_long_long
482
		= new_int_mode("long long", irma_twos_complement, 64, 1, 64);
483
484
	ir_type *type_long_long = new_type_primitive(mode_long_long);
	ir_mode *mode_unsigned_long_long
485
		= new_int_mode("unsigned long long", irma_twos_complement, 64, 0, 64);
486
487
488
489
490
	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;
491

492
493
494
495
496
	ir_type *type_long_double = new_type_primitive(mode_Q);

	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
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
	return &p;
}

static asm_constraint_flags_t sparc_parse_asm_constraint(const char **c)
{
	(void) c;
	return ASM_CONSTRAINT_FLAG_INVALID;
}

static int sparc_is_valid_clobber(const char *clobber)
{
	(void) clobber;
	return 0;
}

512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
/* fpu set architectures. */
static const lc_opt_enum_int_items_t sparc_fpu_items[] = {
	{ "fpu",       SPARC_FPU_ARCH_FPU },
	{ "softfloat", SPARC_FPU_ARCH_SOFTFLOAT },
	{ NULL,        0 }
};

static lc_opt_enum_int_var_t arch_fpu_var = {
	&sparc_isa_template.fpu_arch, sparc_fpu_items
};

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_LAST
};

528
529
530
531
532
533
534
535
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);

Matthias Braun's avatar
Matthias Braun committed
536
	ir_node  *store;
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
	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);
	}
	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);

Matthias Braun's avatar
Matthias Braun committed
555
	ir_node  *load;
556
557
558
559
560
561
562
563
	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);
	}
	sched_add_before(before, load);
	assert((long)pn_sparc_Ld_res == (long)pn_sparc_Ldf_res);
Matthias Braun's avatar
Matthias Braun committed
564
	ir_node *res = new_r_Proj(load, mode, pn_sparc_Ld_res);
565
566
567
568

	return res;
}

Hannes Rapp's avatar
Hannes Rapp committed
569
570
const arch_isa_if_t sparc_isa_if = {
	sparc_init,
Matthias Braun's avatar
Matthias Braun committed
571
	sparc_finish,
572
	sparc_get_backend_params,
573
	sparc_lower_for_target,
Hannes Rapp's avatar
Hannes Rapp committed
574
	sparc_parse_asm_constraint,
575
576
	sparc_is_valid_clobber,

577
578
	sparc_begin_codegeneration,
	sparc_end_codegeneration,
579
	NULL,
580
581
582
583
584
585
586
587
588
	NULL,                /* get call abi */
	NULL,                /* mark remat */
	NULL,                /* get_pic_base */
	sparc_new_spill,
	sparc_new_reload,
	NULL,                /* register_saved_by */

	sparc_handle_intrinsics,
	NULL,                /* before_abi */
589
590
	sparc_prepare_graph,
	sparc_before_ra,
Matthias Braun's avatar
Matthias Braun committed
591
	sparc_finish_graph,
592
	sparc_emit_routine,
Hannes Rapp's avatar
Hannes Rapp committed
593
594
};

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