bearch_arm.c 16.8 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

20
21
22
/**
 * @file
 * @brief   The main arm backend driver file.
23
 * @author  Matthias Braun, Oliver Richter, Tobias Gneist
24
25
 * @version $Id$
 */
26
27
#include "config.h"

Matthias Braun's avatar
Matthias Braun committed
28
29
#include "lc_opts.h"
#include "lc_opts_enum.h"
Michael Beck's avatar
Michael Beck committed
30

31
32
33
34
35
#include "irgwalk.h"
#include "irprog.h"
#include "irprintf.h"
#include "ircons.h"
#include "irgmod.h"
36
#include "irgopt.h"
Matthias Braun's avatar
Matthias Braun committed
37
#include "iroptimize.h"
38
#include "irdump.h"
39
#include "lower_calls.h"
40
#include "error.h"
41
42
43

#include "bitset.h"
#include "debug.h"
44
#include "array_t.h"
Michael Beck's avatar
Michael Beck committed
45
#include "irtools.h"
46

47
#include "../bearch.h"
48
#include "../benode.h"
49
#include "../belower.h"
50
#include "../besched.h"
51
#include "be.h"
52
#include "../bemachine.h"
53
#include "../bemodule.h"
54
#include "../beirg.h"
Michael Beck's avatar
Michael Beck committed
55
#include "../bespillslots.h"
56
#include "../bespillutil.h"
Michael Beck's avatar
Michael Beck committed
57
#include "../begnuas.h"
58
#include "../belistsched.h"
59
#include "../beflags.h"
60
#include "../bestack.h"
61
62
63

#include "bearch_arm_t.h"

64
65
#include "arm_new_nodes.h"
#include "gen_arm_regalloc_if.h"
66
#include "arm_transform.h"
67
#include "arm_optimize.h"
68
69
70
#include "arm_emitter.h"
#include "arm_map_regs.h"

71
static arch_irn_class_t arm_classify(const ir_node *irn)
Matthias Braun's avatar
Matthias Braun committed
72
{
73
	(void) irn;
74
	/* TODO: we should mark reload/spill instructions and classify them here */
75
	return arch_irn_class_none;
76
77
}

78
79
80
81
82
static ir_entity *arm_get_frame_entity(const ir_node *irn)
{
	const arm_attr_t *attr = get_arm_attr_const(irn);

	if (is_arm_FrameAddr(irn)) {
83
84
		const arm_SymConst_attr_t *frame_attr = get_arm_SymConst_attr_const(irn);
		return frame_attr->entity;
85
86
87
88
89
90
91
92
	}
	if (attr->is_load_store) {
		const arm_load_store_attr_t *load_store_attr
			= get_arm_load_store_attr_const(irn);
		if (load_store_attr->is_frame_entity) {
			return load_store_attr->entity;
		}
	}
93
94
95
96
97
98
99
	return NULL;
}

/**
 * This function is called by the generic backend to correct offsets for
 * nodes accessing the stack.
 */
100
static void arm_set_stack_bias(ir_node *irn, int bias)
101
{
102
	if (is_arm_FrameAddr(irn)) {
103
		arm_SymConst_attr_t *attr = get_arm_SymConst_attr(irn);
104
105
106
107
108
109
		attr->fp_offset += bias;
	} else {
		arm_load_store_attr_t *attr = get_arm_load_store_attr(irn);
		assert(attr->base.is_load_store);
		attr->offset += bias;
	}
110
111
}

112
static int arm_get_sp_bias(const ir_node *irn)
Matthias Braun's avatar
Matthias Braun committed
113
{
114
	/* We don't have any nodes changing the stack pointer.
115
	   We probably want to support post-/pre increment/decrement later */
Matthias Braun's avatar
Matthias Braun committed
116
	(void) irn;
117
118
119
	return 0;
}

120
121
/* fill register allocator interface */

Matthias Braun's avatar
Matthias Braun committed
122
static const arch_irn_ops_t arm_irn_ops = {
123
124
	arm_classify,
	arm_get_frame_entity,
125
	arm_set_stack_bias,
126
	arm_get_sp_bias,
127
128
129
130
	NULL,    /* get_inverse             */
	NULL,    /* get_op_estimated_cost   */
	NULL,    /* possible_memory_operand */
	NULL,    /* perform_memory_operand  */
131
132
133
};

/**
Michael Beck's avatar
Michael Beck committed
134
135
 * Transforms the standard Firm graph into
 * a ARM firm graph.
136
 */
137
static void arm_prepare_graph(ir_graph *irg)
138
{
139
	/* transform nodes into assembler instructions */
140
	arm_transform_graph(irg);
141

142
	/* do local optimizations (mainly CSE) */
143
	local_optimize_graph(irg);
144
145

	/* do code placement, to optimize the position of constants */
146
	place_code(irg);
147
}
148

149
static void arm_collect_frame_entity_nodes(ir_node *node, void *data)
Matthias Braun's avatar
Matthias Braun committed
150
{
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
	be_fec_env_t  *env = (be_fec_env_t*)data;
	const ir_mode *mode;
	int            align;
	ir_entity     *entity;
	const arm_load_store_attr_t *attr;

	if (be_is_Reload(node) && be_get_frame_entity(node) == NULL) {
		mode  = get_irn_mode(node);
		align = get_mode_size_bytes(mode);
		be_node_needs_frame_entity(env, node, mode, align);
		return;
	}

	switch (get_arm_irn_opcode(node)) {
	case iro_arm_Ldf:
	case iro_arm_Ldr:
		break;
	default:
		return;
	}

	attr   = get_arm_load_store_attr_const(node);
	entity = attr->entity;
	mode   = attr->load_store_mode;
	align  = get_mode_size_bytes(mode);
	if (entity != NULL)
		return;
	if (!attr->is_frame_entity)
		return;
	be_node_needs_frame_entity(env, node, mode, align);
181
182
}

183
static void arm_set_frame_entity(ir_node *node, ir_entity *entity)
Matthias Braun's avatar
Matthias Braun committed
184
{
185
186
187
188
189
190
	if (is_be_node(node)) {
		be_node_set_frame_entity(node, entity);
	} else {
		arm_load_store_attr_t *attr = get_arm_load_store_attr(node);
		attr->entity = entity;
	}
191
192
}

193
194
195
196
static void transform_Reload(ir_node *node)
{
	ir_node   *block  = get_nodes_block(node);
	dbg_info  *dbgi   = get_irn_dbg_info(node);
197
198
	ir_node   *ptr    = get_irn_n(node, n_be_Reload_frame);
	ir_node   *mem    = get_irn_n(node, n_be_Reload_mem);
199
	ir_mode   *mode   = get_irn_mode(node);
200
	ir_entity *entity = be_get_frame_entity(node);
201
202
	const arch_register_t *reg;
	ir_node   *proj;
203
204
205
206
	ir_node   *load;

	ir_node  *sched_point = sched_prev(node);

207
208
209
210
	load = new_bd_arm_Ldr(dbgi, block, ptr, mem, mode, entity, false, 0, true);
	sched_add_after(sched_point, load);
	sched_remove(node);

211
	proj = new_rd_Proj(dbgi, load, mode, pn_arm_Ldr_res);
212
213
214
215
216
217
218
219
220
221
222

	reg = arch_get_irn_register(node);
	arch_set_irn_register(proj, reg);

	exchange(node, proj);
}

static void transform_Spill(ir_node *node)
{
	ir_node   *block  = get_nodes_block(node);
	dbg_info  *dbgi   = get_irn_dbg_info(node);
223
	ir_node   *ptr    = get_irn_n(node, n_be_Spill_frame);
224
	ir_graph  *irg    = get_irn_irg(node);
225
	ir_node   *mem    = get_irg_no_mem(irg);
226
	ir_node   *val    = get_irn_n(node, n_be_Spill_val);
227
228
229
230
231
232
233
234
235
236
237
238
239
	ir_mode   *mode   = get_irn_mode(val);
	ir_entity *entity = be_get_frame_entity(node);
	ir_node   *sched_point;
	ir_node   *store;

	sched_point = sched_prev(node);
	store = new_bd_arm_Str(dbgi, block, ptr, val, mem, mode, entity, false, 0,
	                       true);

	sched_remove(node);
	sched_add_after(sched_point, store);

	exchange(node, store);
240
241
}

242
static void arm_after_ra_walker(ir_node *block, void *data)
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
{
	ir_node *node, *prev;
	(void) data;

	for (node = sched_last(block); !sched_is_begin(node); node = prev) {
		prev = sched_prev(node);

		if (be_is_Reload(node)) {
			transform_Reload(node);
		} else if (be_is_Spill(node)) {
			transform_Spill(node);
		}
	}
}

258
259
260
261
/**
 * Called immediately before emit phase.
 */
static void arm_finish_irg(ir_graph *irg)
Matthias Braun's avatar
Matthias Braun committed
262
{
263
264
265
	be_stack_layout_t *stack_layout = be_get_irg_stack_layout(irg);
	bool               at_begin     = stack_layout->sp_relative ? true : false;
	be_fec_env_t      *fec_env      = be_new_frame_entity_coalescer(irg);
266
267

	irg_walk_graph(irg, NULL, arm_collect_frame_entity_nodes, fec_env);
268
	be_assign_entities(fec_env, arm_set_frame_entity, at_begin);
269
	be_free_frame_entity_coalescer(fec_env);
270

271
	irg_block_walk_graph(irg, NULL, arm_after_ra_walker, NULL);
272
273
274
275
276
277
278
279
280
281
282
283

	/* fix stack entity offsets */
	be_abi_fix_stack_nodes(irg);
	be_abi_fix_stack_bias(irg);

	/* do peephole optimizations and fix stack offsets */
	arm_peephole_optimization(irg);
}

static void arm_before_ra(ir_graph *irg)
{
	be_sched_fix_flags(irg, &arm_reg_classes[CLASS_arm_flags], NULL, NULL);
Michael Beck's avatar
Michael Beck committed
284
}
285
286
287
288

/**
 * Initializes the code generator.
 */
289
static void arm_init_graph(ir_graph *irg)
290
{
291
	(void) irg;
292
293
294
295
296
297
298
299
}


/**
 * Maps all intrinsic calls that the backend support
 * and map all instructions the backend did not support
 * to runtime calls.
 */
Matthias Braun's avatar
Matthias Braun committed
300
301
static void arm_handle_intrinsics(void)
{
302
303
304
	ir_type *tp, *int_tp, *uint_tp;
	i_record records[8];
	int n_records = 0;
305

Michael Beck's avatar
Michael Beck committed
306
307
	runtime_rt rt_iDiv, rt_uDiv, rt_iMod, rt_uMod;

308
309
#define ID(x) new_id_from_chars(x, sizeof(x)-1)

310
311
	int_tp  = get_type_for_mode(mode_Is);
	uint_tp = get_type_for_mode(mode_Iu);
312

Michael Beck's avatar
Michael Beck committed
313
	/* ARM has neither a signed div instruction ... */
314
315
316
	{
		i_instr_record *map_Div = &records[n_records++].i_instr;

317
		tp = new_type_method(2, 1);
318
319
320
321
		set_method_param_type(tp, 0, int_tp);
		set_method_param_type(tp, 1, int_tp);
		set_method_res_type(tp, 0, int_tp);

Michael Beck's avatar
Michael Beck committed
322
323
324
325
326
327
328
329
		rt_iDiv.ent             = new_entity(get_glob_type(), ID("__divsi3"), tp);
		set_entity_ld_ident(rt_iDiv.ent, ID("__divsi3"));
		rt_iDiv.mode            = mode_T;
		rt_iDiv.res_mode        = mode_Is;
		rt_iDiv.mem_proj_nr     = pn_Div_M;
		rt_iDiv.regular_proj_nr = pn_Div_X_regular;
		rt_iDiv.exc_proj_nr     = pn_Div_X_except;
		rt_iDiv.res_proj_nr     = pn_Div_res;
330

331
332
		add_entity_linkage(rt_iDiv.ent, IR_LINKAGE_CONSTANT);
		set_entity_visibility(rt_iDiv.ent, ir_visibility_external);
333
334
335
336

		map_Div->kind     = INTRINSIC_INSTR;
		map_Div->op       = op_Div;
		map_Div->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
Michael Beck's avatar
Michael Beck committed
337
		map_Div->ctx      = &rt_iDiv;
338
339
340
341
342
	}
	/* ... nor an unsigned div instruction ... */
	{
		i_instr_record *map_Div = &records[n_records++].i_instr;

343
		tp = new_type_method(2, 1);
344
345
346
347
		set_method_param_type(tp, 0, uint_tp);
		set_method_param_type(tp, 1, uint_tp);
		set_method_res_type(tp, 0, uint_tp);

Michael Beck's avatar
Michael Beck committed
348
349
350
351
352
353
354
355
		rt_uDiv.ent             = new_entity(get_glob_type(), ID("__udivsi3"), tp);
		set_entity_ld_ident(rt_uDiv.ent, ID("__udivsi3"));
		rt_uDiv.mode            = mode_T;
		rt_uDiv.res_mode        = mode_Iu;
		rt_uDiv.mem_proj_nr     = pn_Div_M;
		rt_uDiv.regular_proj_nr = pn_Div_X_regular;
		rt_uDiv.exc_proj_nr     = pn_Div_X_except;
		rt_uDiv.res_proj_nr     = pn_Div_res;
356

357
		set_entity_visibility(rt_uDiv.ent, ir_visibility_external);
358
359
360
361

		map_Div->kind     = INTRINSIC_INSTR;
		map_Div->op       = op_Div;
		map_Div->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
Michael Beck's avatar
Michael Beck committed
362
		map_Div->ctx      = &rt_uDiv;
363
	}
Michael Beck's avatar
Michael Beck committed
364
	/* ... nor a signed mod instruction ... */
365
366
367
	{
		i_instr_record *map_Mod = &records[n_records++].i_instr;

368
		tp = new_type_method(2, 1);
369
370
371
372
		set_method_param_type(tp, 0, int_tp);
		set_method_param_type(tp, 1, int_tp);
		set_method_res_type(tp, 0, int_tp);

Michael Beck's avatar
Michael Beck committed
373
374
375
376
377
378
379
380
		rt_iMod.ent             = new_entity(get_glob_type(), ID("__modsi3"), tp);
		set_entity_ld_ident(rt_iMod.ent, ID("__modsi3"));
		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;
381

382
		set_entity_visibility(rt_iMod.ent, ir_visibility_external);
383
384
385
386

		map_Mod->kind     = INTRINSIC_INSTR;
		map_Mod->op       = op_Mod;
		map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
Michael Beck's avatar
Michael Beck committed
387
		map_Mod->ctx      = &rt_iMod;
388
389
390
391
392
	}
	/* ... nor an unsigned mod. */
	{
		i_instr_record *map_Mod = &records[n_records++].i_instr;

393
		tp = new_type_method(2, 1);
394
395
396
397
		set_method_param_type(tp, 0, uint_tp);
		set_method_param_type(tp, 1, uint_tp);
		set_method_res_type(tp, 0, uint_tp);

Michael Beck's avatar
Michael Beck committed
398
399
400
401
402
403
404
405
		rt_uMod.ent             = new_entity(get_glob_type(), ID("__umodsi3"), tp);
		set_entity_ld_ident(rt_uMod.ent, ID("__umodsi3"));
		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;
406

407
		set_entity_visibility(rt_uMod.ent, ir_visibility_external);
408
409
410
411

		map_Mod->kind     = INTRINSIC_INSTR;
		map_Mod->op       = op_Mod;
		map_Mod->i_mapper = (i_mapper_func)i_mapper_RuntimeCall;
Michael Beck's avatar
Michael Beck committed
412
		map_Mod->ctx      = &rt_uMod;
413
414
415
	}

	if (n_records > 0)
416
		lower_intrinsics(records, n_records, /*part_block_used=*/0);
417
418
}

419
extern const arch_isa_if_t arm_isa_if;
420
static arm_isa_t arm_isa_template = {
Michael Beck's avatar
Michael Beck committed
421
422
	{
		&arm_isa_if,           /* isa interface */
423
424
		N_ARM_REGISTERS,
		arm_registers,
425
426
		N_ARM_CLASSES,
		arm_reg_classes,
427
428
		&arm_registers[REG_SP],  /* stack pointer */
		&arm_registers[REG_R11], /* base pointer */
429
		&arm_reg_classes[CLASS_arm_gp],  /* static link pointer class */
430
		2,                     /* power of two stack alignment for calls, 2^2 == 4 */
Michael Beck's avatar
Michael Beck committed
431
		NULL,                  /* main environment */
432
433
		7,                     /* spill costs */
		5,                     /* reload costs */
434
		true,                  /* we do have custom abi handling */
Michael Beck's avatar
Michael Beck committed
435
	},
Michael Beck's avatar
Michael Beck committed
436
	ARM_FPU_ARCH_FPE,      /* FPU architecture */
437
438
439
440
441
};

/**
 * Initializes the backend ISA and opens the output file.
 */
442
443
static arch_env_t *arm_init(FILE *file_handle)
{
444
	arm_isa_t *isa = XMALLOC(arm_isa_t);
445
	*isa = arm_isa_template;
446

Matthias Braun's avatar
Matthias Braun committed
447
	arm_register_init();
Michael Beck's avatar
Michael Beck committed
448

449
	be_emit_init(file_handle);
Michael Beck's avatar
Michael Beck committed
450

Matthias Braun's avatar
Matthias Braun committed
451
	arm_create_opcodes(&arm_irn_ops);
Michael Beck's avatar
Michael Beck committed
452
	arm_handle_intrinsics();
453

454
455
	be_gas_emit_types = false;

456
	return &isa->base;
457
458
459
460
461
}



/**
Michael Beck's avatar
Michael Beck committed
462
 * Closes the output file and frees the ISA structure.
463
 */
464
465
static void arm_done(void *self)
{
466
	arm_isa_t *isa = (arm_isa_t*)self;
Michael Beck's avatar
Michael Beck committed
467

468
	be_gas_emit_decls(isa->base.main_env);
Michael Beck's avatar
Michael Beck committed
469

470
	be_emit_exit();
471
472
473
474
475
476
477
478
479
	free(self);
}

/**
 * Get the register class which shall be used to store a value of a given mode.
 * @param self The this pointer.
 * @param mode The mode in question.
 * @return A register class which can hold values of the given mode.
 */
480
static const arch_register_class_t *arm_get_reg_class_for_mode(const ir_mode *mode)
481
{
482
	if (mode_is_float(mode))
Michael Beck's avatar
Michael Beck committed
483
		return &arm_reg_classes[CLASS_arm_fpa];
484
	else
Michael Beck's avatar
Michael Beck committed
485
		return &arm_reg_classes[CLASS_arm_gp];
486
487
}

488
489
490
/**
 * Returns the necessary byte alignment for storing a register of given class.
 */
491
492
static int arm_get_reg_class_alignment(const arch_register_class_t *cls)
{
493
	(void) cls;
Michael Beck's avatar
Michael Beck committed
494
495
	/* ARM is a 32 bit CPU, no need for other alignment */
	return 4;
496
497
}

498
499
500
/**
 * Return irp irgs in the desired order.
 */
501
502
static ir_graph **arm_get_irg_list(const void *self, ir_graph ***irg_list)
{
503
504
	(void) self;
	(void) irg_list;
505
506
507
	return NULL;
}

Michael Beck's avatar
Michael Beck committed
508
509
510
511
/**
 * Allows or disallows the creation of Psi nodes for the given Phi nodes.
 * @return 1 if allowed, 0 otherwise
 */
512
513
514
515
516
517
static int arm_is_mux_allowed(ir_node *sel, ir_node *mux_false,
                              ir_node *mux_true)
{
	(void) sel;
	(void) mux_false;
	(void) mux_true;
518
	return false;
Michael Beck's avatar
Michael Beck committed
519
520
}

521
static asm_constraint_flags_t arm_parse_asm_constraint(const char **c)
522
523
524
525
526
527
{
	/* asm not supported */
	(void) c;
	return ASM_CONSTRAINT_FLAG_INVALID;
}

528
static int arm_is_valid_clobber(const char *clobber)
529
530
{
	(void) clobber;
531
	return 0;
532
533
}

534
535
static void arm_lower_for_target(void)
{
Michael Beck's avatar
Michael Beck committed
536
	size_t i, n_irgs = get_irp_n_irgs();
537

538
	/* lower compound param handling */
539
	lower_calls_with_compounds(LF_RETURN_HIDDEN);
540

541
542
	for (i = 0; i < n_irgs; ++i) {
		ir_graph *irg = get_irp_irg(i);
Matthias Braun's avatar
Matthias Braun committed
543
		lower_switch(irg, 4, 256, true);
544
	}
545
546
547
548
549
550

	for (i = 0; i < n_irgs; ++i) {
		ir_graph *irg = get_irp_irg(i);
		/* Turn all small CopyBs into loads/stores and all bigger CopyBs into
		 * memcpy calls.
		 * TODO:  These constants need arm-specific tuning. */
551
		lower_CopyB(irg, 31, 32, false);
552
	}
553
554
}

Michael Beck's avatar
Michael Beck committed
555
556
557
/**
 * Returns the libFirm configuration parameter for this backend.
 */
558
559
static const backend_params *arm_get_libfirm_params(void)
{
560
	static ir_settings_arch_dep_t ad = {
Michael Beck's avatar
Michael Beck committed
561
		1,    /* allow subs */
562
		1,    /* Muls are fast enough on ARM but ... */
Michael Beck's avatar
Michael Beck committed
563
564
565
566
567
		31,   /* ... one shift would be possible better */
		NULL, /* no evaluator function */
		0,    /* SMUL is needed, only in Arch M */
		0,    /* UMUL is needed, only in Arch M */
		32,   /* SMUL & UMUL available for 32 bit */
Michael Beck's avatar
Michael Beck committed
568
569
	};
	static backend_params p = {
570
		0,     /* don't support inline assembler yet */
571
		1,     /* support Rotl nodes */
572
		1,     /* big endian */
573
574
		1,     /* modulo shift efficient */
		0,     /* non-modulo shift not efficient */
575
576
		&ad,   /* will be set later */
		arm_is_mux_allowed, /* allow_ifconv function */
577
		32,    /* machine size */
578
		NULL,  /* float arithmetic mode (TODO) */
579
580
581
		NULL,  /* long long type */
		NULL,  /* unsigned long long type */
		NULL,  /* long double type */
582
583
		0,     /* no trampoline support: size 0 */
		0,     /* no trampoline support: align 0 */
584
585
		NULL,  /* no trampoline support: no trampoline builder */
		4      /* alignment of stack parameter */
Michael Beck's avatar
Michael Beck committed
586
587
588
589
590
	};

	return &p;
}

Michael Beck's avatar
Michael Beck committed
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
/* fpu set architectures. */
static const lc_opt_enum_int_items_t arm_fpu_items[] = {
	{ "softfloat", ARM_FPU_ARCH_SOFTFLOAT },
	{ "fpe",       ARM_FPU_ARCH_FPE },
	{ "fpa",       ARM_FPU_ARCH_FPA },
	{ "vfp1xd",    ARM_FPU_ARCH_VFP_V1xD },
	{ "vfp1",      ARM_FPU_ARCH_VFP_V1 },
	{ "vfp2",      ARM_FPU_ARCH_VFP_V2 },
	{ NULL,        0 }
};

static lc_opt_enum_int_var_t arch_fpu_var = {
	&arm_isa_template.fpu_arch, arm_fpu_items
};

Michael Beck's avatar
Michael Beck committed
606
static const lc_opt_table_entry_t arm_options[] = {
Michael Beck's avatar
Michael Beck committed
607
	LC_OPT_ENT_ENUM_INT("fpunit",    "select the floating point unit", &arch_fpu_var),
608
	LC_OPT_LAST
Michael Beck's avatar
Michael Beck committed
609
};
610
611
612

const arch_isa_if_t arm_isa_if = {
	arm_init,
613
	arm_lower_for_target,
614
	arm_done,
615
	NULL,  /* handle_intrinsics */
616
	arm_get_reg_class_for_mode,
617
	NULL,
Michael Beck's avatar
Michael Beck committed
618
	arm_get_reg_class_alignment,
Michael Beck's avatar
Michael Beck committed
619
	arm_get_libfirm_params,
620
	arm_get_irg_list,
621
	NULL,               /* mark remat */
622
	arm_parse_asm_constraint,
623
624
625
626
627
628
629
630
631
	arm_is_valid_clobber,

	arm_init_graph,
	NULL,  /* get_pic_base */
	NULL,  /* before_abi */
	arm_prepare_graph,
	arm_before_ra,
	arm_finish_irg,
	arm_gen_routine,
632
	NULL, /* register_saved_by */
633
634
	be_new_spill,
	be_new_reload,
635
};
636

Matthias Braun's avatar
Matthias Braun committed
637
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_arm)
638
639
640
641
642
643
644
645
void be_init_arch_arm(void)
{
	lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
	lc_opt_entry_t *arm_grp = lc_opt_get_grp(be_grp, "arm");

	lc_opt_add_table(arm_grp, arm_options);

	be_register_isa_if("arm", &arm_isa_if);
646
647

	arm_init_transform();
648
	arm_init_emitter();
649
}