bearch_arm.c 34.3 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
23
24
25
/**
 * @file
 * @brief   The main arm backend driver file.
 * @author  Oliver Richter, Tobias Gneist
 * @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
36
#include "pseudo_irg.h"
#include "irgwalk.h"
#include "irprog.h"
#include "irprintf.h"
#include "ircons.h"
#include "irgmod.h"
37
#include "irgopt.h"
Matthias Braun's avatar
Matthias Braun committed
38
#include "iroptimize.h"
39
#include "lowering.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_t.h"                /* the general register allocator interface */
48
49
50
#include "../benode_t.h"
#include "../belower.h"
#include "../besched_t.h"
51
#include "be.h"
52
#include "../beabi.h"
53
#include "../bemachine.h"
54
#include "../beilpsched.h"
55
#include "../bemodule.h"
56
#include "../beirg_t.h"
Michael Beck's avatar
Michael Beck committed
57
#include "../bespillslots.h"
Michael Beck's avatar
Michael Beck committed
58
#include "../begnuas.h"
59
60
61
62
63
64

#include "bearch_arm_t.h"

#include "arm_new_nodes.h"           /* arm nodes interface */
#include "gen_arm_regalloc_if.h"     /* the generated interface (register type and class defenitions) */
#include "arm_transform.h"
65
#include "arm_optimize.h"
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include "arm_emitter.h"
#include "arm_map_regs.h"

#define DEBUG_MODULE "firm.be.arm.isa"

/* TODO: ugly, but we need it to get access to the registers assigned to Phi nodes */
static set *cur_reg_set = NULL;

/**************************************************
 *                         _ _              _  __
 *                        | | |            (_)/ _|
 *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
 * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
 * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
 * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
 *            __/ |
 *           |___/
 **************************************************/

/**
 * Return register requirements for a arm node.
 * If the node returns a tuple (mode_T) then the proj's
 * will be asked for this information.
 */
90
91
static const arch_register_req_t *arm_get_irn_reg_req(const ir_node *node,
                                                      int pos)
Matthias Braun's avatar
Matthias Braun committed
92
{
93
	long               node_pos = pos == -1 ? 0 : pos;
Matthias Braun's avatar
Matthias Braun committed
94
	ir_mode           *mode     = get_irn_mode(node);
95

Michael Beck's avatar
Michael Beck committed
96
	if (is_Block(node) || mode == mode_X) {
Matthias Braun's avatar
Matthias Braun committed
97
		return arch_no_register_req;
98
99
100
	}

	if (mode == mode_T && pos < 0) {
Matthias Braun's avatar
Matthias Braun committed
101
		return arch_no_register_req;
102
103
	}

Matthias Braun's avatar
Matthias Braun committed
104
	if (is_Proj(node)) {
Michael Beck's avatar
Michael Beck committed
105
106
107
		if(mode == mode_M)
			return arch_no_register_req;

108
109
		if(pos >= 0) {
			return arch_no_register_req;
110
111
		}

112
113
		node_pos = (pos == -1) ? get_Proj_proj(node) : pos;
		node     = skip_Proj_const(node);
114
115
116
	}

	/* get requirements for our own nodes */
Matthias Braun's avatar
Matthias Braun committed
117
118
	if (is_arm_irn(node)) {
		const arch_register_req_t *req;
119
		if (pos >= 0) {
Matthias Braun's avatar
Matthias Braun committed
120
121
122
			req = get_arm_in_req(node, pos);
		} else {
			req = get_arm_out_req(node, node_pos);
123
124
		}

Matthias Braun's avatar
Matthias Braun committed
125
		return req;
126
127
	}

128
	/* unknown should be transformed by now */
Matthias Braun's avatar
Matthias Braun committed
129
130
	assert(!is_Unknown(node));
	return arch_no_register_req;
131
132
}

133
static arch_irn_class_t arm_classify(const ir_node *irn)
Matthias Braun's avatar
Matthias Braun committed
134
{
Matthias Braun's avatar
Matthias Braun committed
135
	irn = skip_Proj_const(irn);
136
137
138
139
140
141
142
143

	if (is_cfop(irn)) {
		return arch_irn_class_branch;
	}

	return 0;
}

144
145
146
static ir_entity *arm_get_frame_entity(const ir_node *irn) {
	/* we do NOT transform be_Spill or be_Reload nodes, so we never
	   have frame access using ARM nodes. */
Michael Beck's avatar
Michael Beck committed
147
	(void) irn;
148
149
150
	return NULL;
}

151
static void arm_set_frame_entity(ir_node *irn, ir_entity *ent) {
Michael Beck's avatar
Michael Beck committed
152
153
	(void) irn;
	(void) ent;
154
	panic("arm_set_frame_entity() called. This should not happen.");
155
156
}

157
158
159
160
/**
 * This function is called by the generic backend to correct offsets for
 * nodes accessing the stack.
 */
161
static void arm_set_stack_bias(ir_node *irn, int bias)
162
163
164
{
	(void) irn;
	(void) bias;
165
166
167
	/* TODO: correct offset if irn accesses the stack */
}

168
static int arm_get_sp_bias(const ir_node *irn)
Matthias Braun's avatar
Matthias Braun committed
169
170
{
	(void) irn;
171
172
173
	return 0;
}

174
175
/* fill register allocator interface */

Matthias Braun's avatar
Matthias Braun committed
176
static const arch_irn_ops_t arm_irn_ops = {
177
178
179
	arm_get_irn_reg_req,
	arm_classify,
	arm_get_frame_entity,
180
	arm_set_frame_entity,
181
	arm_set_stack_bias,
182
	arm_get_sp_bias,
183
184
185
186
	NULL,    /* get_inverse             */
	NULL,    /* get_op_estimated_cost   */
	NULL,    /* possible_memory_operand */
	NULL,    /* perform_memory_operand  */
187
188
189
190
191
192
193
194
195
196
197
198
199
200
};

/**************************************************
 *                _                         _  __
 *               | |                       (_)/ _|
 *   ___ ___   __| | ___  __ _  ___ _ __    _| |_
 *  / __/ _ \ / _` |/ _ \/ _` |/ _ \ '_ \  | |  _|
 * | (_| (_) | (_| |  __/ (_| |  __/ | | | | | |
 *  \___\___/ \__,_|\___|\__, |\___|_| |_| |_|_|
 *                        __/ |
 *                       |___/
 **************************************************/

/**
Michael Beck's avatar
Michael Beck committed
201
202
 * Transforms the standard Firm graph into
 * a ARM firm graph.
203
204
205
206
 */
static void arm_prepare_graph(void *self) {
	arm_code_gen_t *cg = self;

207
208
	/* transform nodes into assembler instructions */
	arm_transform_graph(cg);
209

210
211
	/* do local optimizations (mainly CSE) */
	local_optimize_graph(cg->irg);
212

213
214
215
216
217
218
219
220
221
	if (cg->dump)
		be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);

	/* do code placement, to optimize the position of constants */
	place_code(cg->irg);

	if (cg->dump)
		be_dump(cg->irg, "-place", dump_ir_block_graph_sched);
}
222
223
224
225

/**
 * Called immediately before emit phase.
 */
Matthias Braun's avatar
Matthias Braun committed
226
227
static void arm_finish_irg(void *self)
{
228
229
230
231
	arm_code_gen_t *cg = self;

	/* do peephole optimizations and fix stack offsets */
	arm_peephole_optimization(cg);
232
233
234
}


Matthias Braun's avatar
Matthias Braun committed
235
236
237
static void arm_before_ra(void *self)
{
	(void) self;
238
239
240
	/* Some stuff you need to do immediately after register allocation */
}

Michael Beck's avatar
Michael Beck committed
241
242
243
244
/**
 * We transform Spill and Reload here. This needs to be done before
 * stack biasing otherwise we would miss the corrected offset for these nodes.
 */
Matthias Braun's avatar
Matthias Braun committed
245
246
static void arm_after_ra(void *self)
{
Michael Beck's avatar
Michael Beck committed
247
248
249
	arm_code_gen_t *cg = self;
	be_coalesce_spillslots(cg->birg);
}
250
251
252
253
254
255
256

/**
 * Emits the code, closes the output file and frees
 * the code generator interface.
 */
static void arm_emit_and_done(void *self) {
	arm_code_gen_t *cg = self;
Michael Beck's avatar
Michael Beck committed
257
	ir_graph       *irg = cg->irg;
258

Michael Beck's avatar
Michael Beck committed
259
	arm_gen_routine(cg, irg);
260
261
262
263
264
265
266
267

	cur_reg_set = NULL;

	/* de-allocate code generator */
	del_set(cg->reg_set);
	free(self);
}

Michael Beck's avatar
Michael Beck committed
268
269
270
271
272
273
/**
 * Move a double floating point value into an integer register.
 * Place the move operation into block bl.
 *
 * Handle some special cases here:
 * 1.) A constant: simply split into two
Michael Beck's avatar
Michael Beck committed
274
 * 2.) A load: simply split into two
Michael Beck's avatar
Michael Beck committed
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
 */
static ir_node *convert_dbl_to_int(ir_node *bl, ir_node *arg, ir_node *mem,
                                   ir_node **resH, ir_node **resL) {
	if (is_Const(arg)) {
		tarval *tv = get_Const_tarval(arg);
		unsigned v;

		/* get the upper 32 bits */
		v =            get_tarval_sub_bits(tv, 7);
		v = (v << 8) | get_tarval_sub_bits(tv, 6);
		v = (v << 8) | get_tarval_sub_bits(tv, 5);
		v = (v << 8) | get_tarval_sub_bits(tv, 4);
		*resH = new_Const_long(mode_Is, v);

		/* get the lower 32 bits */
		v =            get_tarval_sub_bits(tv, 3);
		v = (v << 8) | get_tarval_sub_bits(tv, 2);
		v = (v << 8) | get_tarval_sub_bits(tv, 1);
		v = (v << 8) | get_tarval_sub_bits(tv, 0);
		*resL = new_Const_long(mode_Is, v);
295
	} else if (is_Load(skip_Proj(arg))) {
Michael Beck's avatar
Michael Beck committed
296
		/* FIXME: handling of low/high depends on LE/BE here */
297
		panic("Unimplemented convert_dbl_to_int() case");
Michael Beck's avatar
Michael Beck committed
298
299
300
301
	}
	else {
		ir_node *conv;

302
		conv = new_bd_arm_fpaDbl2GP(NULL, bl, arg, mem);
Michael Beck's avatar
Michael Beck committed
303
		/* move high/low */
304
305
306
		*resL = new_r_Proj(bl, conv, mode_Is, pn_arm_fpaDbl2GP_low);
		*resH = new_r_Proj(bl, conv, mode_Is, pn_arm_fpaDbl2GP_high);
		mem   = new_r_Proj(bl, conv, mode_M,  pn_arm_fpaDbl2GP_M);
Michael Beck's avatar
Michael Beck committed
307
308
309
	}
	return mem;
}
310
311

/**
Michael Beck's avatar
Michael Beck committed
312
 * Move a single floating point value into an integer register.
313
 * Place the move operation into block bl.
Michael Beck's avatar
Michael Beck committed
314
315
316
 *
 * Handle some special cases here:
 * 1.) A constant: simply move
Michael Beck's avatar
Michael Beck committed
317
 * 2.) A load: simply load
318
 */
Matthias Braun's avatar
Matthias Braun committed
319
320
321
322
static ir_node *convert_sng_to_int(ir_node *bl, ir_node *arg)
{
	(void) bl;

Michael Beck's avatar
Michael Beck committed
323
324
325
326
327
328
329
330
331
332
	if (is_Const(arg)) {
		tarval *tv = get_Const_tarval(arg);
		unsigned v;

		/* get the lower 32 bits */
		v =            get_tarval_sub_bits(tv, 3);
		v = (v << 8) | get_tarval_sub_bits(tv, 2);
		v = (v << 8) | get_tarval_sub_bits(tv, 1);
		v = (v << 8) | get_tarval_sub_bits(tv, 0);
		return new_Const_long(mode_Is, v);
333
	} else if (is_Load(skip_Proj(arg))) {
Michael Beck's avatar
Michael Beck committed
334
335
336
337
		ir_node *load;

		load = skip_Proj(arg);
	}
338
	panic("Unimplemented convert_sng_to_int() case");
339
340
341
342
343
}

/**
 * Convert the arguments of a call to support the
 * ARM calling convention of general purpose AND floating
Michael Beck's avatar
Michael Beck committed
344
 * point arguments.
345
346
347
348
 */
static void handle_calls(ir_node *call, void *env)
{
	arm_code_gen_t *cg = env;
Michael Beck's avatar
Michael Beck committed
349
	int i, j, n, size, idx, flag, n_param, n_res, first_variadic;
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
	ir_type *mtp, *new_mtd, *new_tp[5];
	ir_node *new_in[5], **in;
	ir_node *bl;

	if (! is_Call(call))
		return;

	/* check, if we need conversions */
	n = get_Call_n_params(call);
	mtp = get_Call_type(call);
	assert(get_method_n_params(mtp) == n);

	/* it's always enough to handle the first 4 parameters */
	if (n > 4)
		n = 4;
	flag = size = idx = 0;
	bl = get_nodes_block(call);
	for (i = 0; i < n; ++i) {
		ir_type *param_tp = get_method_param_type(mtp, i);

		if (is_compound_type(param_tp)) {
			/* an aggregate parameter: bad case */
			assert(0);
		}
		else {
			/* a primitive parameter */
			ir_mode *mode = get_type_mode(param_tp);

			if (mode_is_float(mode)) {
				if (get_mode_size_bits(mode) > 32) {
Michael Beck's avatar
Michael Beck committed
380
381
382
					ir_node *mem = get_Call_mem(call);

					/* Beware: ARM wants the high part first */
383
					size += 2 * 4;
Michael Beck's avatar
Michael Beck committed
384
385
386
387
388
					new_tp[idx]   = cg->int_tp;
					new_tp[idx+1] = cg->int_tp;
					mem = convert_dbl_to_int(bl, get_Call_param(call, i), mem, &new_in[idx], &new_in[idx+1]);
					idx += 2;
					set_Call_mem(call, mem);
389
390
391
392
				}
				else {
					size += 4;
					new_tp[idx] = cg->int_tp;
Michael Beck's avatar
Michael Beck committed
393
					new_in[idx] = convert_sng_to_int(bl, get_Call_param(call, i));
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
420
421
422
423
424
425
426
427
					++idx;
				}
				flag = 1;
			}
			else {
				size += 4;
				new_tp[idx] = param_tp;
				new_in[idx] = get_Call_param(call, i);
				++idx;
			}
		}

		if (size >= 16)
			break;
	}

	/* if flag is NOT set, no need to translate the method type */
	if (! flag)
		return;

	/* construct a new method type */
	n       = i;
	n_param = get_method_n_params(mtp) - n + idx;
	n_res   = get_method_n_ress(mtp);
	new_mtd = new_d_type_method(get_type_ident(mtp), n_param, n_res, get_type_dbg_info(mtp));

	for (i = 0; i < idx; ++i)
		set_method_param_type(new_mtd, i, new_tp[i]);
	for (i = n, j = idx; i < get_method_n_params(mtp); ++i)
		set_method_param_type(new_mtd, j++, get_method_param_type(mtp, i));
	for (i = 0; i < n_res; ++i)
		set_method_res_type(new_mtd, i, get_method_res_type(mtp, i));

	set_method_calling_convention(new_mtd, get_method_calling_convention(mtp));
Michael Beck's avatar
Michael Beck committed
428
429
430
	first_variadic = get_method_first_variadic_param_index(mtp);
	if (first_variadic >= 0)
		set_method_first_variadic_param_index(new_mtd, first_variadic);
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453

	if (is_lowered_type(mtp)) {
		mtp = get_associated_type(mtp);
	}
	set_lowered_type(mtp, new_mtd);

	set_Call_type(call, new_mtd);

	/* calculate new in array of the Call */
	NEW_ARR_A(ir_node *, in, n_param + 2);
	for (i = 0; i < idx; ++i)
		in[2 + i] = new_in[i];
	for (i = n, j = idx; i < get_method_n_params(mtp); ++i)
		in[2 + j++] = get_Call_param(call, i);

	in[0] = get_Call_mem(call);
	in[1] = get_Call_ptr(call);

	/* finally, change the call inputs */
	set_irn_in(call, n_param + 2, in);
}

/**
Michael Beck's avatar
Michael Beck committed
454
 * Handle graph transformations before the abi converter does its work.
455
456
457
458
459
460
461
 */
static void arm_before_abi(void *self) {
	arm_code_gen_t *cg = self;

	irg_walk_graph(cg->irg, NULL, handle_calls, cg);
}

462
/* forward */
Matthias Braun's avatar
Matthias Braun committed
463
static void *arm_cg_init(be_irg_t *birg);
464
465
466

static const arch_code_generator_if_t arm_code_gen_if = {
	arm_cg_init,
467
	NULL,               /* get_pic_base */
468
	arm_before_abi,     /* before abi introduce */
469
	arm_prepare_graph,
470
	NULL,               /* spill */
471
	arm_before_ra,      /* before register allocation hook */
Michael Beck's avatar
Michael Beck committed
472
	arm_after_ra,
473
	arm_finish_irg,
474
475
476
477
478
479
	arm_emit_and_done,
};

/**
 * Initializes the code generator.
 */
Matthias Braun's avatar
Matthias Braun committed
480
static void *arm_cg_init(be_irg_t *birg) {
481
	static ir_type *int_tp = NULL;
482
	arm_isa_t      *isa = (arm_isa_t *)birg->main_env->arch_env;
483
484
	arm_code_gen_t *cg;

Michael Beck's avatar
Michael Beck committed
485
	if (! int_tp) {
486
487
488
489
		/* create an integer type with machine size */
		int_tp = new_type_primitive(new_id_from_chars("int", 3), mode_Is);
	}

490
	cg = XMALLOC(arm_code_gen_t);
491
492
493
494
495
496
497
	cg->impl         = &arm_code_gen_if;
	cg->irg          = birg->irg;
	cg->reg_set      = new_set(arm_cmp_irn_reg_assoc, 1024);
	cg->isa          = isa;
	cg->birg         = birg;
	cg->int_tp       = int_tp;
	cg->have_fp_insn = 0;
Michael Beck's avatar
Michael Beck committed
498
499
	cg->unknown_gp   = NULL;
	cg->unknown_fpa  = NULL;
500
	cg->dump         = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0;
501

502
	FIRM_DBG_REGISTER(cg->mod, "firm.be.arm.cg");
503
504
505

	cur_reg_set = cg->reg_set;

Michael Beck's avatar
Michael Beck committed
506
507
508
	/* enter the current code generator */
	isa->cg = cg;

509
510
511
512
513
514
515
516
517
	return (arch_code_generator_t *)cg;
}


/**
 * Maps all intrinsic calls that the backend support
 * and map all instructions the backend did not support
 * to runtime calls.
 */
Michael Beck's avatar
Michael Beck committed
518
static void arm_handle_intrinsics(void) {
519
520
521
	ir_type *tp, *int_tp, *uint_tp;
	i_record records[8];
	int n_records = 0;
522

Michael Beck's avatar
Michael Beck committed
523
524
	runtime_rt rt_iDiv, rt_uDiv, rt_iMod, rt_uMod;

525
526
#define ID(x) new_id_from_chars(x, sizeof(x)-1)

527
528
	int_tp  = new_type_primitive(ID("int"), mode_Is);
	uint_tp = new_type_primitive(ID("uint"), mode_Iu);
529

Michael Beck's avatar
Michael Beck committed
530
	/* ARM has neither a signed div instruction ... */
531
532
533
534
535
536
537
538
	{
		i_instr_record *map_Div = &records[n_records++].i_instr;

		tp = new_type_method(ID("rt_iDiv"), 2, 1);
		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
539
540
541
542
543
544
545
546
547
		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.exc_mem_proj_nr = pn_Div_M;
		rt_iDiv.res_proj_nr     = pn_Div_res;
548

Michael Beck's avatar
Michael Beck committed
549
		set_entity_visibility(rt_iDiv.ent, visibility_external_allocated);
550
551
552
553

		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
554
		map_Div->ctx      = &rt_iDiv;
555
556
557
558
559
560
561
562
563
564
	}
	/* ... nor an unsigned div instruction ... */
	{
		i_instr_record *map_Div = &records[n_records++].i_instr;

		tp = new_type_method(ID("rt_uDiv"), 2, 1);
		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
565
566
567
568
569
570
571
572
573
		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.exc_mem_proj_nr = pn_Div_M;
		rt_uDiv.res_proj_nr     = pn_Div_res;
574

Michael Beck's avatar
Michael Beck committed
575
		set_entity_visibility(rt_uDiv.ent, visibility_external_allocated);
576
577
578
579

		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
580
		map_Div->ctx      = &rt_uDiv;
581
	}
Michael Beck's avatar
Michael Beck committed
582
	/* ... nor a signed mod instruction ... */
583
584
585
586
587
588
589
590
	{
		i_instr_record *map_Mod = &records[n_records++].i_instr;

		tp = new_type_method(ID("rt_iMod"), 2, 1);
		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
591
592
593
594
595
596
597
598
599
		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.exc_mem_proj_nr = pn_Mod_M;
		rt_iMod.res_proj_nr     = pn_Mod_res;
600

Michael Beck's avatar
Michael Beck committed
601
		set_entity_visibility(rt_iMod.ent, visibility_external_allocated);
602
603
604
605

		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
606
		map_Mod->ctx      = &rt_iMod;
607
608
609
610
611
612
613
614
615
616
	}
	/* ... nor an unsigned mod. */
	{
		i_instr_record *map_Mod = &records[n_records++].i_instr;

		tp = new_type_method(ID("rt_uMod"), 2, 1);
		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
617
618
619
620
621
622
623
624
625
		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.exc_mem_proj_nr = pn_Mod_M;
		rt_uMod.res_proj_nr     = pn_Mod_res;
626

Michael Beck's avatar
Michael Beck committed
627
		set_entity_visibility(rt_uMod.ent, visibility_external_allocated);
628
629
630
631

		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
632
		map_Mod->ctx      = &rt_uMod;
633
634
635
	}

	if (n_records > 0)
636
		lower_intrinsics(records, n_records, /*part_block_used=*/0);
637
638
639
640
641
642
643
644
645
646
647
648
649
}

/*****************************************************************
 *  ____             _                  _   _____  _____
 * |  _ \           | |                | | |_   _|/ ____|  /\
 * | |_) | __ _  ___| | _____ _ __   __| |   | | | (___   /  \
 * |  _ < / _` |/ __| |/ / _ \ '_ \ / _` |   | |  \___ \ / /\ \
 * | |_) | (_| | (__|   <  __/ | | | (_| |  _| |_ ____) / ____ \
 * |____/ \__,_|\___|_|\_\___|_| |_|\__,_| |_____|_____/_/    \_\
 *
 *****************************************************************/

static arm_isa_t arm_isa_template = {
Michael Beck's avatar
Michael Beck committed
650
651
652
653
	{
		&arm_isa_if,           /* isa interface */
		&arm_gp_regs[REG_SP],  /* stack pointer */
		&arm_gp_regs[REG_R11], /* base pointer */
654
		&arm_reg_classes[CLASS_arm_gp],  /* static link pointer class */
Michael Beck's avatar
Michael Beck committed
655
		-1,                    /* stack direction */
656
		2,                     /* power of two stack alignment for calls, 2^2 == 4 */
Michael Beck's avatar
Michael Beck committed
657
		NULL,                  /* main environment */
658
659
		7,                     /* spill costs */
		5,                     /* reload costs */
Michael Beck's avatar
Michael Beck committed
660
	},
Michael Beck's avatar
Michael Beck committed
661
	0,                     /* use generic register names instead of SP, LR, PC */
Michael Beck's avatar
Michael Beck committed
662
	ARM_FPU_ARCH_FPE,      /* FPU architecture */
Michael Beck's avatar
Michael Beck committed
663
	NULL,                  /* current code generator */
664
665
666
667
668
};

/**
 * Initializes the backend ISA and opens the output file.
 */
669
static arch_env_t *arm_init(FILE *file_handle) {
670
671
672
	static int inited = 0;
	arm_isa_t *isa;

Michael Beck's avatar
Michael Beck committed
673
	if (inited)
674
675
		return NULL;

676
	isa = XMALLOC(arm_isa_t);
677
678
	memcpy(isa, &arm_isa_template, sizeof(*isa));

Matthias Braun's avatar
Matthias Braun committed
679
	arm_register_init();
Michael Beck's avatar
Michael Beck committed
680

681
	isa->cg  = NULL;
682
	be_emit_init(file_handle);
Michael Beck's avatar
Michael Beck committed
683

Matthias Braun's avatar
Matthias Braun committed
684
	arm_create_opcodes(&arm_irn_ops);
Michael Beck's avatar
Michael Beck committed
685
	arm_handle_intrinsics();
686

Michael Beck's avatar
Michael Beck committed
687
688
689
690
691
	/* needed for the debug support */
	be_gas_emit_switch_section(GAS_SECTION_TEXT);
	be_emit_cstring(".Ltext0:\n");
	be_emit_write_line();

Michael Beck's avatar
Michael Beck committed
692
693
694
695
696
697
	/* we mark referenced global entities, so we can only emit those which
	 * are actually referenced. (Note: you mustn't use the type visited flag
	 * elsewhere in the backend)
	 */
	inc_master_type_visited();

698
	inited = 1;
699
	return &isa->arch_env;
700
701
702
703
704
}



/**
Michael Beck's avatar
Michael Beck committed
705
 * Closes the output file and frees the ISA structure.
706
707
 */
static void arm_done(void *self) {
Michael Beck's avatar
Michael Beck committed
708
709
	arm_isa_t *isa = self;

710
	be_gas_emit_decls(isa->arch_env.main_env, 1);
Michael Beck's avatar
Michael Beck committed
711

712
	be_emit_exit();
713
714
715
716
	free(self);
}


Michael Beck's avatar
Michael Beck committed
717
718
719
720
721
722
/**
 * Report the number of register classes.
 * If we don't have fp instructions, report only GP
 * here to speed up register allocation (and makes dumps
 * smaller and more readable).
 */
723
724
static unsigned arm_get_n_reg_class(const void *self) {
	(void) self;
Michael Beck's avatar
Michael Beck committed
725
	return N_CLASSES;
726
727
}

Michael Beck's avatar
Michael Beck committed
728
729
730
/**
 * Return the register class with requested index.
 */
731
732
static const arch_register_class_t *arm_get_reg_class(const void *self,
                                                      unsigned i) {
733
	(void) self;
734
	assert(i < N_CLASSES);
Michael Beck's avatar
Michael Beck committed
735
	return &arm_reg_classes[i];
736
737
738
739
740
741
742
743
744
}

/**
 * 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.
 */
const arch_register_class_t *arm_get_reg_class_for_mode(const void *self, const ir_mode *mode) {
745
	(void) self;
746
	if (mode_is_float(mode))
Michael Beck's avatar
Michael Beck committed
747
		return &arm_reg_classes[CLASS_arm_fpa];
748
	else
Michael Beck's avatar
Michael Beck committed
749
		return &arm_reg_classes[CLASS_arm_gp];
750
751
752
753
754
}

/**
 * Produces the type which sits between the stack args and the locals on the stack.
 * it will contain the return address and space to store the old base pointer.
Michael Beck's avatar
Michael Beck committed
755
 * @return The Firm type modeling the ABI between type.
756
757
758
 */
static ir_type *arm_get_between_type(void *self) {
	static ir_type *between_type = NULL;
759
	static ir_entity *old_bp_ent = NULL;
760
	(void) self;
761

Michael Beck's avatar
Michael Beck committed
762
	if (between_type == NULL) {
763
		ir_entity *ret_addr_ent;
764
765
766
767
768
769
770
		ir_type *ret_addr_type = new_type_primitive(new_id_from_str("return_addr"), mode_P);
		ir_type *old_bp_type   = new_type_primitive(new_id_from_str("bp"), mode_P);

		between_type           = new_type_class(new_id_from_str("arm_between_type"));
		old_bp_ent             = new_entity(between_type, new_id_from_str("old_bp"), old_bp_type);
		ret_addr_ent           = new_entity(between_type, new_id_from_str("old_bp"), ret_addr_type);

771
772
		set_entity_offset(old_bp_ent, 0);
		set_entity_offset(ret_addr_ent, get_type_size_bytes(old_bp_type));
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
		set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
	}

	return between_type;
}


typedef struct {
	be_abi_call_flags_bits_t flags;
	const arch_env_t *arch_env;
	ir_graph *irg;
} arm_abi_env_t;

static void *arm_abi_init(const be_abi_call_t *call, const arch_env_t *arch_env, ir_graph *irg)
{
788
789
	arm_abi_env_t       *env = XMALLOC(arm_abi_env_t);
	be_abi_call_flags_t  fl  = be_abi_call_get_flags(call);
790
791
792
793
794
795
796
	env->flags    = fl.bits;
	env->irg      = irg;
	env->arch_env = arch_env;
	return env;
}

/**
797
 * Generate the routine prologue.
Michael Beck's avatar
Michael Beck committed
798
 *
799
800
801
802
 * @param self       The callback object.
 * @param mem        A pointer to the mem node. Update this if you define new memory.
 * @param reg_map    A map mapping all callee_save/ignore/parameter registers to their defining nodes.
 * @param stack_bias Points to the current stack bias, can be modified if needed.
Michael Beck's avatar
Michael Beck committed
803
804
805
806
 *
 * @return        The register which shall be used as a stack frame base.
 *
 * All nodes which define registers in @p reg_map must keep @p reg_map current.
807
 */
808
static const arch_register_t *arm_abi_prologue(void *self, ir_node **mem, pmap *reg_map, int *stack_bias) {
Michael Beck's avatar
Michael Beck committed
809
	arm_abi_env_t         *env = self;
810
	ir_node               *store;
Michael Beck's avatar
Michael Beck committed
811
812
813
	ir_graph              *irg;
	ir_node               *block;
	arch_register_class_t *gp;
814

Michael Beck's avatar
Michael Beck committed
815
816
	ir_node               *fp, *ip, *lr, *pc;
	ir_node               *sp = be_abi_reg_map_get(reg_map, env->arch_env->sp);
817

818
819
	(void) stack_bias;

Michael Beck's avatar
Michael Beck committed
820
	if (env->flags.try_omit_fp)
821
		return env->arch_env->sp;
822

Michael Beck's avatar
Michael Beck committed
823
824
825
826
827
828
829
830
831
	fp = be_abi_reg_map_get(reg_map, env->arch_env->bp);
	ip = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_R12]);
	lr = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_LR]);
	pc = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_PC]);

	gp    = &arm_reg_classes[CLASS_arm_gp];
	irg   = env->irg;
	block = get_irg_start_block(irg);

832
833
834
835
836
837
	/* mark bp register as ignore */
	be_set_constr_single_reg_out(get_Proj_pred(fp),
	                             get_Proj_proj(fp), env->arch_env->bp,
	                             arch_register_req_type_ignore);

	/* copy SP to IP (so we can spill it */
838
	ip = be_new_Copy(gp, block, sp);
839
	be_set_constr_single_reg_out(ip, 0, &arm_gp_regs[REG_R12], 0);
840

841
	/* spill stuff */
842
	store = new_bd_arm_StoreStackM4Inc(NULL, block, sp, fp, ip, lr, pc, *mem);
843

844
	sp = new_r_Proj(block, store, env->arch_env->sp->reg_class->mode, pn_arm_StoreStackM4Inc_ptr);
845
	arch_set_irn_register(sp, env->arch_env->sp);
846
	*mem = new_r_Proj(block, store, mode_M, pn_arm_StoreStackM4Inc_M);
847

848
849
	/* frame pointer is ip-4 (because ip is our old sp value) */
	fp = new_bd_arm_Sub_i(NULL, block, ip, get_irn_mode(fp), 4);
850
	arch_set_irn_register(fp, env->arch_env->bp);
851
852
853
854
855
856
857

	/* beware: we change the fp but the StoreStackM4Inc above wants the old
	 * fp value. We are not allowed to spill or anything in the prolog, so we
	 * have to enforce some order here. (scheduler/regalloc are too stupid
	 * to extract this order from register requirements) */
	add_irn_dep(fp, store);

858
	fp = be_new_Copy(gp, block, fp); // XXX Gammelfix: only be_ have custom register requirements
859
860
861
	be_set_constr_single_reg_out(fp, 0, env->arch_env->bp,
	                             arch_register_req_type_ignore);
	arch_set_irn_register(fp, env->arch_env->bp);
862

863
	be_abi_reg_map_set(reg_map, env->arch_env->bp, fp);
864
	be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R12], ip);
865
	be_abi_reg_map_set(reg_map, env->arch_env->sp, sp);
Michael Beck's avatar
Michael Beck committed
866
867
	be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_LR], lr);
	be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_PC], pc);
868

869
	return env->arch_env->bp;
870
871
}

Michael Beck's avatar
Michael Beck committed
872
873
874
/**
 * Builds the ARM epilogue
 */
875
876
static void arm_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map) {
	arm_abi_env_t *env = self;
877
878
	ir_node *curr_sp = be_abi_reg_map_get(reg_map, env->arch_env->sp);
	ir_node *curr_bp = be_abi_reg_map_get(reg_map, env->arch_env->bp);
Michael Beck's avatar
Michael Beck committed
879
880
	ir_node *curr_pc = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_PC]);
	ir_node	*curr_lr = be_abi_reg_map_get(reg_map, &arm_gp_regs[REG_LR]);
881

Matthias Braun's avatar
Matthias Braun committed
882
	// TODO: Activate Omit fp in epilogue
Michael Beck's avatar
Michael Beck committed
883
	if (env->flags.try_omit_fp) {
884
		curr_sp = be_new_IncSP(env->arch_env->sp, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0);
885

886
		curr_lr = be_new_CopyKeep_single(&arm_reg_classes[CLASS_arm_gp], bl, curr_lr, curr_sp, get_irn_mode(curr_lr));
887
		be_set_constr_single_reg_out(curr_lr, 0, &arm_gp_regs[REG_LR], 0);
888

889
		curr_pc = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], bl, curr_lr );
890
		be_set_constr_single_reg_out(curr_pc, BE_OUT_POS(0), &arm_gp_regs[REG_PC], 0);
891
892
	} else {
		ir_node *load_node;
893
894
895

		load_node = new_bd_arm_LoadStackM3Epilogue(NULL, bl, curr_bp, *mem);

896
897
898
899
		curr_bp = new_r_Proj(bl, load_node, env->arch_env->bp->reg_class->mode, pn_arm_LoadStackM3Epilogue_res0);
		curr_sp = new_r_Proj(bl, load_node, env->arch_env->sp->reg_class->mode, pn_arm_LoadStackM3Epilogue_res1);
		curr_pc = new_r_Proj(bl, load_node, mode_Iu, pn_arm_LoadStackM3Epilogue_res2);
		*mem    = new_r_Proj(bl, load_node, mode_M, pn_arm_LoadStackM3Epilogue_M);
900
901
902
		arch_set_irn_register(curr_bp, env->arch_env->bp);
		arch_set_irn_register(curr_sp, env->arch_env->sp);
		arch_set_irn_register(curr_pc, &arm_gp_regs[REG_PC]);
903
	}
904
905
	be_abi_reg_map_set(reg_map, env->arch_env->sp, curr_sp);
	be_abi_reg_map_set(reg_map, env->arch_env->bp, curr_bp);
Michael Beck's avatar
Michael Beck committed
906
907
	be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_LR], curr_lr);
	be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_PC], curr_pc);
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
}

static const be_abi_callbacks_t arm_abi_callbacks = {
	arm_abi_init,
	free,
	arm_get_between_type,
	arm_abi_prologue,
	arm_abi_epilogue,
};


/**
 * Get the ABI restrictions for procedure calls.
 * @param self        The this pointer.
 * @param method_type The type of the method (procedure) in question.
 * @param abi         The abi object to be modified
 */
void arm_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi) {
	ir_type  *tp;
	ir_mode  *mode;
	int       i;
	int       n = get_method_n_params(method_type);
Matthias Braun's avatar
Matthias Braun committed
930
	be_abi_call_flags_t call_flags = be_abi_call_get_flags(abi);
931
	(void) self;
932

Matthias Braun's avatar
Matthias Braun committed
933
934
935
936
937
938
939
	/* set abi flags for calls */
	call_flags.bits.left_to_right         = 0;
	call_flags.bits.store_args_sequential = 0;
	/* call_flags.bits.try_omit_fp     don't change this we can handle both */
	call_flags.bits.fp_free               = 0;
	call_flags.bits.call_has_imm          = 1;  /* IA32 calls can have immediate address */

940
	/* set stack parameter passing style */
Matthias Braun's avatar
Matthias Braun committed
941
	be_abi_call_set_flags(abi, call_flags, &arm_abi_callbacks);
942
943
944
945

	for (i = 0; i < n; i++) {
		/* reg = get reg for param i;          */
		/* be_abi_call_param_reg(abi, i, reg); */
946
		if (i < 4) {
947
			be_abi_call_param_reg(abi, i, arm_get_RegParam_reg(i));
948
949
950
951
952
		} else {
			tp   = get_method_param_type(method_type, i);
			mode = get_type_mode(tp);
			be_abi_call_param_stack(abi, i, mode, 4, 0, 0);
		}
953
954
	}

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
	/* set return registers */
	n = get_method_n_ress(method_type);

	assert(n <= 2 && "more than two results not supported");

	/* In case of 64bit returns, we will have two 32bit values */
	if (n == 2) {
		tp   = get_method_res_type(method_type, 0);
		mode = get_type_mode(tp);

		assert(!mode_is_float(mode) && "two FP results not supported");

		tp   = get_method_res_type(method_type, 1);
		mode = get_type_mode(tp);

		assert(!mode_is_float(mode) && "mixed INT, FP results not supported");

		be_abi_call_res_reg(abi, 0, &arm_gp_regs[REG_R0]);
		be_abi_call_res_reg(abi, 1, &arm_gp_regs[REG_R1]);
	} else if (n == 1) {
		const arch_register_t *reg;

977
		tp   = get_method_res_type(method_type, 0);
978
		assert(is_atomic_type(tp));
979
980
		mode = get_type_mode(tp);

981
982
		reg = mode_is_float(mode) ? &arm_fpa_regs[REG_F0] : &arm_gp_regs[REG_R0];
		be_abi_call_res_reg(abi, 0, reg);
983
984
985
986
	}
}

int arm_to_appear_in_schedule(void *block_env, const ir_node *irn) {
987
	(void) block_env;
988
989
990
991
	if(!is_arm_irn(irn))
		return -1;

	return 1;
992
993
994
995
996
997
}

/**
 * Initializes the code generator interface.
 */
static const arch_code_generator_if_t *arm_get_code_generator_if(void *self) {
998
	(void) self;
999
1000
1001
1002
1003
1004
1005
1006
	return &arm_code_gen_if;
}

list_sched_selector_t arm_sched_selector;

/**
 * Returns the reg_pressure scheduler with to_appear_in_schedule() over\loaded
 */
Christian Würdig's avatar
Christian Würdig committed
1007
static const list_sched_selector_t *arm_get_list_sched_selector(const void *self, list_sched_selector_t *selector) {
1008
	(void) self;
Matthias Braun's avatar
Matthias Braun committed
1009
1010
	memcpy(&arm_sched_selector, selector, sizeof(arm_sched_selector));
	/* arm_sched_selector.exectime              = arm_sched_exectime; */
1011
1012
	arm_sched_selector.to_appear_in_schedule = arm_to_appear_in_schedule;
	return &arm_sched_selector;
Matthias Braun's avatar
Matthias Braun committed
1013

1014
1015
}

1016
static const ilp_sched_selector_t *arm_get_ilp_sched_selector(const void *self) {
1017
	(void) self;
1018
1019
1020
	return NULL;
}

1021
1022
1023
1024
/**
 * Returns the necessary byte alignment for storing a register of given class.
 */
static int arm_get_reg_class_alignment(const void *self, const arch_register_class_t *cls) {
1025
1026
	(void) self;
	(void) cls;
Michael Beck's avatar
Michael Beck committed
1027
1028
	/* ARM is a 32 bit CPU, no need for other alignment */
	return 4;
1029
1030
}

1031
static const be_execution_unit_t ***arm_get_allowed_execution_units(const void *self, const ir_node *irn) {
1032
1033
	(void) self;
	(void) irn;
1034
	/* TODO */
1035
	panic("Unimplemented arm_get_allowed_execution_units()");
1036
1037
1038
}

static const be_machine_t *arm_get_machine(const void *self) {
1039
	(void) self;
1040
	/* TODO */
1041
	panic("Unimplemented arm_get_machine()");
1042
1043
}

1044
1045
1046
/**
 * Return irp irgs in the desired order.
 */
Christian Würdig's avatar
Christian Würdig committed
1047
static ir_graph **arm_get_irg_list(const void *self, ir_graph ***irg_list) {
1048
1049
	(void) self;
	(void) irg_list;
1050
1051
1052
	return NULL;
}

Michael Beck's avatar
Michael Beck committed
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
/**
 * Allows or disallows the creation of Psi nodes for the given Phi nodes.
 * @return 1 if allowed, 0 otherwise
 */
static int arm_is_psi_allowed(ir_node *sel, ir_node *phi_list, int i, int j) {
	ir_node *cmp, *cmp_a, *phi;
	ir_mode *mode;


	/* currently Psi support is not implemented */
	return 0;

/* we don't want long long Psi */
#define IS_BAD_PSI_MODE(mode) (!mode_is_float(mode) && get_mode_size_bits(mode) > 32)

	if (get_irn_mode(sel) != mode_b)
		return 0;

	cmp   = get_Proj_pred(sel);
	cmp_a = get_Cmp_left(cmp);
	mode  = get_irn_mode(cmp_a);

	if (IS_BAD_PSI_MODE(mode))
		return 0;

	/* check the Phi nodes */
	for (phi = phi_list; phi; phi = get_irn_link(phi)) {
		ir_node *pred_i = get_irn_n(phi, i);
		ir_node *pred_j = get_irn_n(phi, j);
		ir_mode *mode_i = get_irn_mode(pred_i);
		ir_mode *mode_j = get_irn_mode(pred_j);

		if (IS_BAD_PSI_MODE(mode_i) || IS_BAD_PSI_MODE(mode_j))
			return 0;
	}

#undef IS_BAD_PSI_MODE

	return 1;
}

1094
1095
1096
1097
1098
1099
1100
1101
static asm_constraint_flags_t arm_parse_asm_constraint(const void *self, const char **c)
{
	/* asm not supported */
	(void) self;
	(void) c;
	return ASM_CONSTRAINT_FLAG_INVALID;
}

1102
static int arm_is_valid_clobber(const void *self, const char *clobber)
1103
1104
1105
{
	(void) self;
	(void) clobber;
1106
	return 0;
1107
1108
}

Michael Beck's avatar
Michael Beck committed
1109
1110
1111
1112
/**
 * Returns the libFirm configuration parameter for this backend.
 */
static const backend_params *arm_get_libfirm_params(void) {
1113
	static const ir_settings_if_conv_t ifconv = {
Michael Beck's avatar
Michael Beck committed
1114
1115
1116
		4,                    /* maxdepth, doesn't matter for Psi-conversion */
		arm_is_psi_allowed   /* allows or disallows Psi creation for given selector */
	};
1117
	static ir_settings_arch_dep_t ad = {
Michael Beck's avatar
Michael Beck committed
1118
1119
1120
1121
1122
1123
1124
		1,    /* allow subs */
		1,	  /* Muls are fast enough on ARM but ... */
		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
1125
1126
	};
	static backend_params p = {
1127
		1,     /* need dword lowering */
1128
		0,     /* don't support inline assembler yet */
Michael Beck's avatar
Michael Beck committed
1129
1130
		NULL,  /* will be set later */
		NULL,  /* but yet no creator function */
1131
		NULL,  /* context for create_intrinsic_fkt */
1132
1133
		NULL,  /* ifconv_info will be set below */
		NULL,  /* float arithmetic mode (TODO) */
1134
1135
		0,     /* no trampoline support: size 0 */
		0,     /* no trampoline support: align 0 */
1136
1137
		NULL,  /* no trampoline support: no trampoline builder */
		4      /* alignment of stack parameter */
Michael Beck's avatar
Michael Beck committed
1138
1139
	};

Michael Beck's avatar
Michael Beck committed
1140
1141
	p.dep_param    = &ad;
	p.if_conv_info = &ifconv;
Michael Beck's avatar
Michael Beck committed
1142
1143
1144
	return &p;
}

Michael Beck's avatar
Michael Beck committed
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
/* 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
1160
static const lc_opt_table_entry_t arm_options[] = {
Michael Beck's avatar
Michael Beck committed
1161
	LC_OPT_ENT_ENUM_INT("fpunit",    "select the floating point unit", &arch_fpu_var),
Michael Beck's avatar
Michael Beck committed
1162
	LC_OPT_ENT_BOOL("gen_reg_names", "use generic register names", &arm_isa_template.gen_reg_names),
1163
	LC_OPT_LAST
Michael Beck's avatar
Michael Beck committed
1164
};
1165
1166
1167
1168

const arch_isa_if_t arm_isa_if = {
	arm_init,
	arm_done,
1169
	NULL,  /* handle_intrinsics */
1170
1171
1172
1173
1174
1175
	arm_get_n_reg_class,
	arm_get_reg_class,
	arm_get_reg_class_for_mode,
	arm_get_call_abi,
	arm_get_code_generator_if,
	arm_get_list_sched_selector,
1176
	arm_get_ilp_sched_selector,
Michael Beck's avatar
Michael Beck committed
1177
	arm_get_reg_class_alignment,
Michael Beck's avatar
Michael Beck committed
1178
	arm_get_libfirm_params,
1179
1180
	arm_get_allowed_execution_units,
	arm_get_machine,
1181
	arm_get_irg_list,
Matthias Braun's avatar