bearch_arm.c 15.7 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
26
#include "config.h"

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

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

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

46
47
48
49
#include "bearch.h"
#include "benode.h"
#include "belower.h"
#include "besched.h"
50
#include "be.h"
51
52
53
54
55
56
57
58
#include "bemodule.h"
#include "beirg.h"
#include "bespillslots.h"
#include "bespillutil.h"
#include "begnuas.h"
#include "belistsched.h"
#include "beflags.h"
#include "bestack.h"
59
60
61

#include "bearch_arm_t.h"

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

69
70
71
72
73
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)) {
74
75
		const arm_SymConst_attr_t *frame_attr = get_arm_SymConst_attr_const(irn);
		return frame_attr->entity;
76
77
78
79
80
81
82
83
	}
	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;
		}
	}
84
85
86
87
88
89
90
	return NULL;
}

/**
 * This function is called by the generic backend to correct offsets for
 * nodes accessing the stack.
 */
91
static void arm_set_stack_bias(ir_node *irn, int bias)
92
{
93
	if (is_arm_FrameAddr(irn)) {
94
		arm_SymConst_attr_t *attr = get_arm_SymConst_attr(irn);
95
96
97
98
99
100
		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;
	}
101
102
}

103
static int arm_get_sp_bias(const ir_node *irn)
Matthias Braun's avatar
Matthias Braun committed
104
{
105
	/* We don't have any nodes changing the stack pointer.
106
	   We probably want to support post-/pre increment/decrement later */
Matthias Braun's avatar
Matthias Braun committed
107
	(void) irn;
108
109
110
	return 0;
}

111
112
/* fill register allocator interface */

Matthias Braun's avatar
Matthias Braun committed
113
static const arch_irn_ops_t arm_irn_ops = {
114
	arm_get_frame_entity,
115
	arm_set_stack_bias,
116
	arm_get_sp_bias,
117
118
119
120
	NULL,    /* get_inverse             */
	NULL,    /* get_op_estimated_cost   */
	NULL,    /* possible_memory_operand */
	NULL,    /* perform_memory_operand  */
121
122
123
};

/**
Michael Beck's avatar
Michael Beck committed
124
125
 * Transforms the standard Firm graph into
 * a ARM firm graph.
126
 */
127
static void arm_prepare_graph(ir_graph *irg)
128
{
129
	/* transform nodes into assembler instructions */
130
	arm_transform_graph(irg);
131

132
	/* do local optimizations (mainly CSE) */
133
	local_optimize_graph(irg);
134
135

	/* do code placement, to optimize the position of constants */
136
	place_code(irg);
137
}
138

139
static void arm_collect_frame_entity_nodes(ir_node *node, void *data)
Matthias Braun's avatar
Matthias Braun committed
140
{
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
	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);
171
172
}

173
static void arm_set_frame_entity(ir_node *node, ir_entity *entity)
Matthias Braun's avatar
Matthias Braun committed
174
{
175
176
177
178
179
180
	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;
	}
181
182
}

183
184
185
186
static void transform_Reload(ir_node *node)
{
	ir_node   *block  = get_nodes_block(node);
	dbg_info  *dbgi   = get_irn_dbg_info(node);
187
188
	ir_node   *ptr    = get_irn_n(node, n_be_Reload_frame);
	ir_node   *mem    = get_irn_n(node, n_be_Reload_mem);
189
	ir_mode   *mode   = get_irn_mode(node);
190
	ir_entity *entity = be_get_frame_entity(node);
191
192
	const arch_register_t *reg;
	ir_node   *proj;
193
194
195
196
	ir_node   *load;

	ir_node  *sched_point = sched_prev(node);

197
198
199
200
	load = new_bd_arm_Ldr(dbgi, block, ptr, mem, mode, entity, false, 0, true);
	sched_add_after(sched_point, load);
	sched_remove(node);

201
	proj = new_rd_Proj(dbgi, load, mode, pn_arm_Ldr_res);
202
203
204
205
206
207
208
209
210
211
212

	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);
213
	ir_node   *ptr    = get_irn_n(node, n_be_Spill_frame);
214
	ir_graph  *irg    = get_irn_irg(node);
215
	ir_node   *mem    = get_irg_no_mem(irg);
216
	ir_node   *val    = get_irn_n(node, n_be_Spill_val);
217
218
219
220
221
222
223
224
225
226
227
228
229
	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);
230
231
}

232
static void arm_after_ra_walker(ir_node *block, void *data)
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
{
	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);
		}
	}
}

248
249
250
251
/**
 * Called immediately before emit phase.
 */
static void arm_finish_irg(ir_graph *irg)
Matthias Braun's avatar
Matthias Braun committed
252
{
253
254
255
	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);
256
257

	irg_walk_graph(irg, NULL, arm_collect_frame_entity_nodes, fec_env);
258
	be_assign_entities(fec_env, arm_set_frame_entity, at_begin);
259
	be_free_frame_entity_coalescer(fec_env);
260

261
	irg_block_walk_graph(irg, NULL, arm_after_ra_walker, NULL);
262
263
264
265
266
267
268
269
270
271
272
273

	/* 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
274
}
275
276
277
278

/**
 * Initializes the code generator.
 */
279
static void arm_init_graph(ir_graph *irg)
280
{
281
	(void) irg;
282
283
284
285
286
287
288
289
}


/**
 * 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
290
291
static void arm_handle_intrinsics(void)
{
292
293
294
	ir_type *tp, *int_tp, *uint_tp;
	i_record records[8];
	int n_records = 0;
295

Michael Beck's avatar
Michael Beck committed
296
297
	runtime_rt rt_iDiv, rt_uDiv, rt_iMod, rt_uMod;

298
299
#define ID(x) new_id_from_chars(x, sizeof(x)-1)

300
301
	int_tp  = get_type_for_mode(mode_Is);
	uint_tp = get_type_for_mode(mode_Iu);
302

Michael Beck's avatar
Michael Beck committed
303
	/* ARM has neither a signed div instruction ... */
304
305
306
	{
		i_instr_record *map_Div = &records[n_records++].i_instr;

307
		tp = new_type_method(2, 1);
308
309
310
311
		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
312
313
314
315
316
317
318
319
		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;
320

321
322
		add_entity_linkage(rt_iDiv.ent, IR_LINKAGE_CONSTANT);
		set_entity_visibility(rt_iDiv.ent, ir_visibility_external);
323
324
325
326

		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
327
		map_Div->ctx      = &rt_iDiv;
328
329
330
331
332
	}
	/* ... nor an unsigned div instruction ... */
	{
		i_instr_record *map_Div = &records[n_records++].i_instr;

333
		tp = new_type_method(2, 1);
334
335
336
337
		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
338
339
340
341
342
343
344
345
		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;
346

347
		set_entity_visibility(rt_uDiv.ent, ir_visibility_external);
348
349
350
351

		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
352
		map_Div->ctx      = &rt_uDiv;
353
	}
Michael Beck's avatar
Michael Beck committed
354
	/* ... nor a signed mod instruction ... */
355
356
357
	{
		i_instr_record *map_Mod = &records[n_records++].i_instr;

358
		tp = new_type_method(2, 1);
359
360
361
362
		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
363
364
365
366
367
368
369
370
		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;
371

372
		set_entity_visibility(rt_iMod.ent, ir_visibility_external);
373
374
375
376

		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
377
		map_Mod->ctx      = &rt_iMod;
378
379
380
381
382
	}
	/* ... nor an unsigned mod. */
	{
		i_instr_record *map_Mod = &records[n_records++].i_instr;

383
		tp = new_type_method(2, 1);
384
385
386
387
		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
388
389
390
391
392
393
394
395
		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;
396

397
		set_entity_visibility(rt_uMod.ent, ir_visibility_external);
398
399
400
401

		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
402
		map_Mod->ctx      = &rt_uMod;
403
404
405
	}

	if (n_records > 0)
406
		lower_intrinsics(records, n_records, /*part_block_used=*/0);
407
408
}

409
extern const arch_isa_if_t arm_isa_if;
410
static arm_isa_t arm_isa_template = {
Michael Beck's avatar
Michael Beck committed
411
412
	{
		&arm_isa_if,           /* isa interface */
413
414
		N_ARM_REGISTERS,
		arm_registers,
415
416
		N_ARM_CLASSES,
		arm_reg_classes,
417
418
		&arm_registers[REG_SP],  /* stack pointer */
		&arm_registers[REG_R11], /* base pointer */
419
		&arm_reg_classes[CLASS_arm_gp],  /* static link pointer class */
420
		2,                     /* power of two stack alignment for calls, 2^2 == 4 */
Michael Beck's avatar
Michael Beck committed
421
		NULL,                  /* main environment */
422
423
		7,                     /* spill costs */
		5,                     /* reload costs */
424
		true,                  /* we do have custom abi handling */
Michael Beck's avatar
Michael Beck committed
425
	},
Michael Beck's avatar
Michael Beck committed
426
	ARM_FPU_ARCH_FPE,      /* FPU architecture */
427
428
429
430
431
};

/**
 * Initializes the backend ISA and opens the output file.
 */
432
static arch_env_t *arm_init(const be_main_env_t *env)
433
{
434
	arm_isa_t *isa = XMALLOC(arm_isa_t);
435
	*isa = arm_isa_template;
436

Matthias Braun's avatar
Matthias Braun committed
437
	arm_register_init();
Michael Beck's avatar
Michael Beck committed
438

Matthias Braun's avatar
Matthias Braun committed
439
	arm_create_opcodes(&arm_irn_ops);
Michael Beck's avatar
Michael Beck committed
440
	arm_handle_intrinsics();
441

442
443
	be_gas_emit_types = false;

444
445
446
	be_emit_init(env->file_handle);
	be_gas_begin_compilation_unit(env);

447
	return &isa->base;
448
449
450
451
452
}



/**
Michael Beck's avatar
Michael Beck committed
453
 * Closes the output file and frees the ISA structure.
454
 */
455
456
static void arm_done(void *self)
{
457
	arm_isa_t *isa = (arm_isa_t*)self;
Michael Beck's avatar
Michael Beck committed
458

459
	be_gas_end_compilation_unit(isa->base.main_env);
Michael Beck's avatar
Michael Beck committed
460

461
	be_emit_exit();
462
463
464
	free(self);
}

Michael Beck's avatar
Michael Beck committed
465
466
467
468
/**
 * Allows or disallows the creation of Psi nodes for the given Phi nodes.
 * @return 1 if allowed, 0 otherwise
 */
469
470
471
472
473
474
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;
475
	return false;
Michael Beck's avatar
Michael Beck committed
476
477
}

478
static asm_constraint_flags_t arm_parse_asm_constraint(const char **c)
479
480
481
482
483
484
{
	/* asm not supported */
	(void) c;
	return ASM_CONSTRAINT_FLAG_INVALID;
}

485
static int arm_is_valid_clobber(const char *clobber)
486
487
{
	(void) clobber;
488
	return 0;
489
490
}

491
492
static void arm_lower_for_target(void)
{
Michael Beck's avatar
Michael Beck committed
493
	size_t i, n_irgs = get_irp_n_irgs();
494

495
	/* lower compound param handling */
496
	lower_calls_with_compounds(LF_RETURN_HIDDEN);
497

498
499
	for (i = 0; i < n_irgs; ++i) {
		ir_graph *irg = get_irp_irg(i);
Matthias Braun's avatar
Matthias Braun committed
500
		lower_switch(irg, 4, 256, false);
501
	}
502
503
504
505
506
507

	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. */
508
		lower_CopyB(irg, 31, 32, false);
509
	}
510
511
}

Michael Beck's avatar
Michael Beck committed
512
513
514
/**
 * Returns the libFirm configuration parameter for this backend.
 */
515
516
static const backend_params *arm_get_libfirm_params(void)
{
517
	static ir_settings_arch_dep_t ad = {
Michael Beck's avatar
Michael Beck committed
518
		1,    /* allow subs */
519
		1,    /* Muls are fast enough on ARM but ... */
Michael Beck's avatar
Michael Beck committed
520
521
522
523
524
		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
525
526
	};
	static backend_params p = {
527
		0,     /* don't support inline assembler yet */
528
		1,     /* support Rotl nodes */
529
		1,     /* big endian */
530
531
		1,     /* modulo shift efficient */
		0,     /* non-modulo shift not efficient */
532
533
		&ad,   /* will be set later */
		arm_is_mux_allowed, /* allow_ifconv function */
534
		32,    /* machine size */
535
		NULL,  /* float arithmetic mode (TODO) */
536
537
538
		NULL,  /* long long type */
		NULL,  /* unsigned long long type */
		NULL,  /* long double type */
539
540
		0,     /* no trampoline support: size 0 */
		0,     /* no trampoline support: align 0 */
541
542
		NULL,  /* no trampoline support: no trampoline builder */
		4      /* alignment of stack parameter */
Michael Beck's avatar
Michael Beck committed
543
544
545
546
547
	};

	return &p;
}

Michael Beck's avatar
Michael Beck committed
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
/* 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
563
static const lc_opt_table_entry_t arm_options[] = {
Michael Beck's avatar
Michael Beck committed
564
	LC_OPT_ENT_ENUM_INT("fpunit",    "select the floating point unit", &arch_fpu_var),
565
	LC_OPT_LAST
Michael Beck's avatar
Michael Beck committed
566
};
567
568
569

const arch_isa_if_t arm_isa_if = {
	arm_init,
570
	arm_lower_for_target,
571
	arm_done,
572
	NULL,  /* handle_intrinsics */
573
	NULL,
Michael Beck's avatar
Michael Beck committed
574
	arm_get_libfirm_params,
575
	NULL,               /* mark remat */
576
	arm_parse_asm_constraint,
577
578
579
580
581
582
583
584
585
	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,
586
	NULL, /* register_saved_by */
587
588
	be_new_spill,
	be_new_reload,
589
};
590

Matthias Braun's avatar
Matthias Braun committed
591
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_arm)
592
593
594
595
596
597
598
599
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);
600
601

	arm_init_transform();
602
	arm_init_emitter();
603
}