bearch_arm.c 36.4 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
28
29
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

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

33
34
35
36
37
38
#include "pseudo_irg.h"
#include "irgwalk.h"
#include "irprog.h"
#include "irprintf.h"
#include "ircons.h"
#include "irgmod.h"
39
#include "irgopt.h"
Matthias Braun's avatar
Matthias Braun committed
40
#include "iroptimize.h"
41
#include "lowering.h"
42
#include "error.h"
43
44
45

#include "bitset.h"
#include "debug.h"
Michael Beck's avatar
Michael Beck committed
46
#include "irtools.h"
47

48
#include "../bearch_t.h"                /* the general register allocator interface */
49
50
51
#include "../benode_t.h"
#include "../belower.h"
#include "../besched_t.h"
52
#include "be.h"
53
#include "../beabi.h"
54
#include "../bemachine.h"
55
#include "../beilpsched.h"
56
#include "../bemodule.h"
57
#include "../beirg_t.h"
Michael Beck's avatar
Michael Beck committed
58
#include "../bespillslots.h"
Michael Beck's avatar
Michael Beck committed
59
#include "../begnuas.h"
60
61
62
63
64
65

#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"
66
#include "arm_optimize.h"
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#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.
 */
91
92
static const arch_register_req_t *arm_get_irn_reg_req(const ir_node *node,
                                                      int pos)
Matthias Braun's avatar
Matthias Braun committed
93
{
94
	long               node_pos = pos == -1 ? 0 : pos;
Matthias Braun's avatar
Matthias Braun committed
95
	ir_mode           *mode     = get_irn_mode(node);
96

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

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

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

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

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

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

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

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

134
static void arm_set_irn_reg(ir_node *irn, const arch_register_t *reg)
Matthias Braun's avatar
Matthias Braun committed
135
{
136
137
	int pos = 0;

138
139
140
	if (get_irn_mode(irn) == mode_X) {
		return;
	}
141

142
143
	if (is_Proj(irn)) {
		pos = get_Proj_proj(irn);
Matthias Braun's avatar
Matthias Braun committed
144
		irn = skip_Proj(irn);
145
146
147
148
149
150
151
152
153
154
155
156
157
158
	}

	if (is_arm_irn(irn)) {
		const arch_register_t **slots;

		slots      = get_arm_slots(irn);
		slots[pos] = reg;
	}
	else {
		/* here we set the registers for the Phi nodes */
		arm_set_firm_reg(irn, reg, cur_reg_set);
	}
}

159
static const arch_register_t *arm_get_irn_reg(const ir_node *irn)
Matthias Braun's avatar
Matthias Braun committed
160
{
161
162
163
164
165
166
167
168
169
	int pos = 0;
	const arch_register_t *reg = NULL;

	if (is_Proj(irn)) {

		if (get_irn_mode(irn) == mode_X) {
			return NULL;
		}

170
		pos = get_Proj_proj(irn);
Matthias Braun's avatar
Matthias Braun committed
171
		irn = skip_Proj_const(irn);
172
173
174
175
176
177
178
179
180
181
182
183
184
185
	}

	if (is_arm_irn(irn)) {
		const arch_register_t **slots;
		slots = get_arm_slots(irn);
		reg   = slots[pos];
	}
	else {
		reg = arm_get_firm_reg(irn, cur_reg_set);
	}

	return reg;
}

186
static arch_irn_class_t arm_classify(const ir_node *irn)
Matthias Braun's avatar
Matthias Braun committed
187
{
Matthias Braun's avatar
Matthias Braun committed
188
	irn = skip_Proj_const(irn);
189
190
191
192
193
194
195
196
197
198
199

	if (is_cfop(irn)) {
		return arch_irn_class_branch;
	}
	else if (is_arm_irn(irn)) {
		return arch_irn_class_normal;
	}

	return 0;
}

200
static arch_irn_flags_t arm_get_flags(const ir_node *irn)
Matthias Braun's avatar
Matthias Braun committed
201
{
202
	arch_irn_flags_t flags = arch_irn_flags_none;
203

204
	if(is_Unknown(irn)) {
205
206
207
		return arch_irn_flags_ignore;
	}

208
209
210
211
212
213
214
215
216
217
218
219
220
	if (is_Proj(irn) && mode_is_datab(get_irn_mode(irn))) {
		ir_node *pred = get_Proj_pred(irn);
		if (is_arm_irn(pred)) {
			flags = get_arm_out_flags(pred, get_Proj_proj(irn));
		}
		irn = pred;
	}

	if (is_arm_irn(irn)) {
		flags |= get_arm_flags(irn);
	}

	return flags;
221
222
}

223
224
225
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
226
	(void) irn;
227
228
229
	return NULL;
}

230
static void arm_set_frame_entity(ir_node *irn, ir_entity *ent) {
Michael Beck's avatar
Michael Beck committed
231
232
	(void) irn;
	(void) ent;
233
	panic("arm_set_frame_entity() called. This should not happen.");
234
235
}

236
237
238
239
/**
 * This function is called by the generic backend to correct offsets for
 * nodes accessing the stack.
 */
240
static void arm_set_stack_bias(ir_node *irn, int bias)
241
242
243
{
	(void) irn;
	(void) bias;
244
245
246
	/* TODO: correct offset if irn accesses the stack */
}

247
static int arm_get_sp_bias(const ir_node *irn)
Matthias Braun's avatar
Matthias Braun committed
248
249
{
	(void) irn;
250
251
252
	return 0;
}

253
254
/* fill register allocator interface */

Matthias Braun's avatar
Matthias Braun committed
255
static const arch_irn_ops_t arm_irn_ops = {
256
257
258
259
260
261
	arm_get_irn_reg_req,
	arm_set_irn_reg,
	arm_get_irn_reg,
	arm_classify,
	arm_get_flags,
	arm_get_frame_entity,
262
	arm_set_frame_entity,
263
	arm_set_stack_bias,
264
	arm_get_sp_bias,
265
266
267
268
	NULL,    /* get_inverse             */
	NULL,    /* get_op_estimated_cost   */
	NULL,    /* possible_memory_operand */
	NULL,    /* perform_memory_operand  */
269
270
271
272
273
274
275
276
277
278
279
280
281
282
};

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

/**
Michael Beck's avatar
Michael Beck committed
283
284
 * Transforms the standard Firm graph into
 * a ARM firm graph.
285
286
287
288
 */
static void arm_prepare_graph(void *self) {
	arm_code_gen_t *cg = self;

289
290
	/* transform nodes into assembler instructions */
	arm_transform_graph(cg);
291

292
293
	/* do local optimizations (mainly CSE) */
	local_optimize_graph(cg->irg);
294

295
296
297
298
299
300
301
302
303
	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);
}
304
305
306
307

/**
 * Called immediately before emit phase.
 */
Matthias Braun's avatar
Matthias Braun committed
308
309
static void arm_finish_irg(void *self)
{
310
311
312
313
	arm_code_gen_t *cg = self;

	/* do peephole optimizations and fix stack offsets */
	arm_peephole_optimization(cg);
314
315
316
317
318
319
}


/**
 * These are some hooks which must be filled but are probably not needed.
 */
Matthias Braun's avatar
Matthias Braun committed
320
321
322
static void arm_before_sched(void *self)
{
	(void) self;
323
324
325
	/* Some stuff you need to do after scheduling but before register allocation */
}

Matthias Braun's avatar
Matthias Braun committed
326
327
328
static void arm_before_ra(void *self)
{
	(void) self;
329
330
331
	/* Some stuff you need to do immediately after register allocation */
}

Michael Beck's avatar
Michael Beck committed
332
333
334
335
/**
 * 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
336
337
static void arm_after_ra(void *self)
{
Michael Beck's avatar
Michael Beck committed
338
339
340
	arm_code_gen_t *cg = self;
	be_coalesce_spillslots(cg->birg);
}
341
342
343
344
345
346
347

/**
 * 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
348
	ir_graph       *irg = cg->irg;
349

Michael Beck's avatar
Michael Beck committed
350
	arm_gen_routine(cg, irg);
351
352
353
354
355
356
357
358

	cur_reg_set = NULL;

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

Michael Beck's avatar
Michael Beck committed
359
360
361
362
363
364
/**
 * 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
365
 * 2.) A load: simply split into two
Michael Beck's avatar
Michael Beck committed
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
 */
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);
	}
	else if (get_irn_op(skip_Proj(arg)) == op_Load) {
		/* FIXME: handling of low/high depends on LE/BE here */
		assert(0);
	}
	else {
		ir_graph *irg = current_ir_graph;
		ir_node *conv;

		conv = new_rd_arm_fpaDbl2GP(NULL, irg, bl, arg, mem);
		/* move high/low */
		*resL = new_r_Proj(irg, bl, conv, mode_Is, pn_arm_fpaDbl2GP_low);
		*resH = new_r_Proj(irg, bl, conv, mode_Is, pn_arm_fpaDbl2GP_high);
		mem   = new_r_Proj(irg, bl, conv, mode_M,  pn_arm_fpaDbl2GP_M);
	}
	return mem;
}
403
404

/**
Michael Beck's avatar
Michael Beck committed
405
 * Move a single floating point value into an integer register.
406
 * Place the move operation into block bl.
Michael Beck's avatar
Michael Beck committed
407
408
409
 *
 * Handle some special cases here:
 * 1.) A constant: simply move
Michael Beck's avatar
Michael Beck committed
410
 * 2.) A load: simply load
411
 */
Matthias Braun's avatar
Matthias Braun committed
412
413
414
415
static ir_node *convert_sng_to_int(ir_node *bl, ir_node *arg)
{
	(void) bl;

Michael Beck's avatar
Michael Beck committed
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
	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);
	}
	else if (get_irn_op(skip_Proj(arg)) == op_Load) {
		ir_node *load;

		load = skip_Proj(arg);
	}
	assert(0);
433
434
435
436
437
438
	return NULL;
}

/**
 * Convert the arguments of a call to support the
 * ARM calling convention of general purpose AND floating
Michael Beck's avatar
Michael Beck committed
439
 * point arguments.
440
441
442
443
 */
static void handle_calls(ir_node *call, void *env)
{
	arm_code_gen_t *cg = env;
Michael Beck's avatar
Michael Beck committed
444
	int i, j, n, size, idx, flag, n_param, n_res, first_variadic;
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
	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
475
476
477
					ir_node *mem = get_Call_mem(call);

					/* Beware: ARM wants the high part first */
478
					size += 2 * 4;
Michael Beck's avatar
Michael Beck committed
479
480
481
482
483
					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);
484
485
486
487
				}
				else {
					size += 4;
					new_tp[idx] = cg->int_tp;
Michael Beck's avatar
Michael Beck committed
488
					new_in[idx] = convert_sng_to_int(bl, get_Call_param(call, i));
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
					++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
523
524
525
	first_variadic = get_method_first_variadic_param_index(mtp);
	if (first_variadic >= 0)
		set_method_first_variadic_param_index(new_mtd, first_variadic);
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548

	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
549
 * Handle graph transformations before the abi converter does its work.
550
551
552
553
554
555
556
 */
static void arm_before_abi(void *self) {
	arm_code_gen_t *cg = self;

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

557
/* forward */
Matthias Braun's avatar
Matthias Braun committed
558
static void *arm_cg_init(be_irg_t *birg);
559
560
561

static const arch_code_generator_if_t arm_code_gen_if = {
	arm_cg_init,
562
	NULL,               /* get_pic_base */
563
	arm_before_abi,     /* before abi introduce */
564
	arm_prepare_graph,
565
	NULL,               /* spill */
566
567
	arm_before_sched,   /* before scheduling hook */
	arm_before_ra,      /* before register allocation hook */
Michael Beck's avatar
Michael Beck committed
568
	arm_after_ra,
569
	arm_finish_irg,
570
571
572
573
574
575
	arm_emit_and_done,
};

/**
 * Initializes the code generator.
 */
Matthias Braun's avatar
Matthias Braun committed
576
static void *arm_cg_init(be_irg_t *birg) {
577
	static ir_type *int_tp = NULL;
578
	arm_isa_t      *isa = (arm_isa_t *)birg->main_env->arch_env;
579
580
	arm_code_gen_t *cg;

Michael Beck's avatar
Michael Beck committed
581
	if (! int_tp) {
582
583
584
585
586
		/* create an integer type with machine size */
		int_tp = new_type_primitive(new_id_from_chars("int", 3), mode_Is);
	}

	cg = xmalloc(sizeof(*cg));
587
588
589
	cg->impl         = &arm_code_gen_if;
	cg->irg          = birg->irg;
	cg->reg_set      = new_set(arm_cmp_irn_reg_assoc, 1024);
590
	cg->arch_env     = birg->main_env->arch_env;
591
592
593
594
	cg->isa          = isa;
	cg->birg         = birg;
	cg->int_tp       = int_tp;
	cg->have_fp_insn = 0;
Michael Beck's avatar
Michael Beck committed
595
596
	cg->unknown_gp   = NULL;
	cg->unknown_fpa  = NULL;
597
	cg->dump         = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0;
598

599
	FIRM_DBG_REGISTER(cg->mod, "firm.be.arm.cg");
600
601
602

	cur_reg_set = cg->reg_set;

Michael Beck's avatar
Michael Beck committed
603
604
605
	/* enter the current code generator */
	isa->cg = cg;

606
607
608
609
610
611
612
613
614
	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
615
static void arm_handle_intrinsics(void) {
616
617
618
	ir_type *tp, *int_tp, *uint_tp;
	i_record records[8];
	int n_records = 0;
619

Michael Beck's avatar
Michael Beck committed
620
621
	runtime_rt rt_iDiv, rt_uDiv, rt_iMod, rt_uMod;

622
623
#define ID(x) new_id_from_chars(x, sizeof(x)-1)

624
625
	int_tp  = new_type_primitive(ID("int"), mode_Is);
	uint_tp = new_type_primitive(ID("uint"), mode_Iu);
626

Michael Beck's avatar
Michael Beck committed
627
	/* ARM has neither a signed div instruction ... */
628
629
630
631
632
633
634
635
	{
		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
636
637
638
639
640
641
642
643
644
		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;
645

Michael Beck's avatar
Michael Beck committed
646
		set_entity_visibility(rt_iDiv.ent, visibility_external_allocated);
647
648
649
650

		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
651
		map_Div->ctx      = &rt_iDiv;
652
653
654
655
656
657
658
659
660
661
	}
	/* ... 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
662
663
664
665
666
667
668
669
670
		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;
671

Michael Beck's avatar
Michael Beck committed
672
		set_entity_visibility(rt_uDiv.ent, visibility_external_allocated);
673
674
675
676

		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
677
		map_Div->ctx      = &rt_uDiv;
678
	}
Michael Beck's avatar
Michael Beck committed
679
	/* ... nor a signed mod instruction ... */
680
681
682
683
684
685
686
687
	{
		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
688
689
690
691
692
693
694
695
696
		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;
697

Michael Beck's avatar
Michael Beck committed
698
		set_entity_visibility(rt_iMod.ent, visibility_external_allocated);
699
700
701
702

		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
703
		map_Mod->ctx      = &rt_iMod;
704
705
706
707
708
709
710
711
712
713
	}
	/* ... 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
714
715
716
717
718
719
720
721
722
		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;
723

Michael Beck's avatar
Michael Beck committed
724
		set_entity_visibility(rt_uMod.ent, visibility_external_allocated);
725
726
727
728

		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
729
		map_Mod->ctx      = &rt_uMod;
730
731
732
	}

	if (n_records > 0)
733
		lower_intrinsics(records, n_records, /*part_block_used=*/0);
734
735
736
737
738
739
740
741
742
743
744
745
746
}

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

static arm_isa_t arm_isa_template = {
Michael Beck's avatar
Michael Beck committed
747
748
749
750
751
	{
		&arm_isa_if,           /* isa interface */
		&arm_gp_regs[REG_SP],  /* stack pointer */
		&arm_gp_regs[REG_R11], /* base pointer */
		-1,                    /* stack direction */
752
		2,                     /* power of two stack alignment for calls, 2^2 == 4 */
Michael Beck's avatar
Michael Beck committed
753
		NULL,                  /* main environment */
754
755
		7,                     /* spill costs */
		5,                     /* reload costs */
Michael Beck's avatar
Michael Beck committed
756
	},
Michael Beck's avatar
Michael Beck committed
757
	0,                     /* use generic register names instead of SP, LR, PC */
Michael Beck's avatar
Michael Beck committed
758
	ARM_FPU_ARCH_FPE,      /* FPU architecture */
Michael Beck's avatar
Michael Beck committed
759
	NULL,                  /* current code generator */
760
761
762
763
764
};

/**
 * Initializes the backend ISA and opens the output file.
 */
765
static arch_env_t *arm_init(FILE *file_handle) {
766
767
768
	static int inited = 0;
	arm_isa_t *isa;

Michael Beck's avatar
Michael Beck committed
769
	if (inited)
770
771
		return NULL;

Michael Beck's avatar
Michael Beck committed
772
	isa = xmalloc(sizeof(*isa));
773
774
	memcpy(isa, &arm_isa_template, sizeof(*isa));

Matthias Braun's avatar
Matthias Braun committed
775
	arm_register_init();
Michael Beck's avatar
Michael Beck committed
776

777
	isa->cg  = NULL;
778
	be_emit_init(file_handle);
Michael Beck's avatar
Michael Beck committed
779

Matthias Braun's avatar
Matthias Braun committed
780
	arm_create_opcodes(&arm_irn_ops);
Michael Beck's avatar
Michael Beck committed
781
	arm_handle_intrinsics();
782

Michael Beck's avatar
Michael Beck committed
783
784
785
786
787
	/* 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
788
789
790
791
792
793
	/* 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();

794
	inited = 1;
795
	return &isa->arch_env;
796
797
798
799
800
}



/**
Michael Beck's avatar
Michael Beck committed
801
 * Closes the output file and frees the ISA structure.
802
803
 */
static void arm_done(void *self) {
Michael Beck's avatar
Michael Beck committed
804
805
	arm_isa_t *isa = self;

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

808
	be_emit_exit();
809
810
811
812
	free(self);
}


Michael Beck's avatar
Michael Beck committed
813
814
815
816
817
818
/**
 * 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).
 */
819
820
static unsigned arm_get_n_reg_class(const void *self) {
	(void) self;
Michael Beck's avatar
Michael Beck committed
821
	return N_CLASSES;
822
823
}

Michael Beck's avatar
Michael Beck committed
824
825
826
/**
 * Return the register class with requested index.
 */
827
828
static const arch_register_class_t *arm_get_reg_class(const void *self,
                                                      unsigned i) {
829
	(void) self;
830
	assert(i < N_CLASSES);
Michael Beck's avatar
Michael Beck committed
831
	return &arm_reg_classes[i];
832
833
834
835
836
837
838
839
840
}

/**
 * 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) {
841
	(void) self;
842
	if (mode_is_float(mode))
Michael Beck's avatar
Michael Beck committed
843
		return &arm_reg_classes[CLASS_arm_fpa];
844
	else
Michael Beck's avatar
Michael Beck committed
845
		return &arm_reg_classes[CLASS_arm_gp];
846
847
848
849
850
}

/**
 * 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
851
 * @return The Firm type modeling the ABI between type.
852
853
854
 */
static ir_type *arm_get_between_type(void *self) {
	static ir_type *between_type = NULL;
855
	static ir_entity *old_bp_ent = NULL;
856
	(void) self;
857

Michael Beck's avatar
Michael Beck committed
858
	if (between_type == NULL) {
859
		ir_entity *ret_addr_ent;
860
861
862
863
864
865
866
		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);

867
868
		set_entity_offset(old_bp_ent, 0);
		set_entity_offset(ret_addr_ent, get_type_size_bytes(old_bp_type));
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
		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)
{
Michael Beck's avatar
Michael Beck committed
884
	arm_abi_env_t *env     = xmalloc(sizeof(env[0]));
885
886
887
888
889
890
891
	be_abi_call_flags_t fl = be_abi_call_get_flags(call);
	env->flags    = fl.bits;
	env->irg      = irg;
	env->arch_env = arch_env;
	return env;
}

Michael Beck's avatar
Michael Beck committed
892
893
894
895
896
897
/**
 * Put all registers which are saved by the prologue/epilogue in a set.
 *
 * @param self  The callback object.
 * @param s     The result set.
 */
898
899
900
static void arm_abi_dont_save_regs(void *self, pset *s)
{
	arm_abi_env_t *env = self;
Michael Beck's avatar
Michael Beck committed
901
	if (env->flags.try_omit_fp)
902
		pset_insert_ptr(s, env->arch_env->bp);
903
904
905
906
907
}



/**
Michael Beck's avatar
Michael Beck committed
908
909
910
911
912
913
914
915
916
* Generate the routine prologue.
 *
 * @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.
 *
 * @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.
917
918
 */
static const arch_register_t *arm_abi_prologue(void *self, ir_node **mem, pmap *reg_map) {
Michael Beck's avatar
Michael Beck committed
919
920
921
922
923
	arm_abi_env_t         *env = self;
	ir_node               *keep, *store;
	ir_graph              *irg;
	ir_node               *block;
	arch_register_class_t *gp;
924

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

Michael Beck's avatar
Michael Beck committed
928
	if (env->flags.try_omit_fp)
929
		return env->arch_env->sp;
930

Michael Beck's avatar
Michael Beck committed
931
932
933
934
935
936
937
938
939
	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);

Michael Beck's avatar
Michael Beck committed
940
	ip = be_new_Copy(gp, irg, block, sp);
Michael Beck's avatar
Michael Beck committed
941
942
	arch_set_irn_register(env->arch_env, ip, &arm_gp_regs[REG_R12]);
	be_set_constr_single_reg(ip, BE_OUT_POS(0), &arm_gp_regs[REG_R12] );
943

Michael Beck's avatar
Michael Beck committed
944
	store = new_rd_arm_StoreStackM4Inc(NULL, irg, block, sp, fp, ip, lr, pc, *mem);
945

946
947
	sp = new_r_Proj(irg, block, store, env->arch_env->sp->reg_class->mode, pn_arm_StoreStackM4Inc_ptr);
	arch_set_irn_register(env->arch_env, sp, env->arch_env->sp);
Michael Beck's avatar
Michael Beck committed
948
	*mem = new_r_Proj(irg, block, store, mode_M, pn_arm_StoreStackM4Inc_M);
949
950

	keep = be_new_CopyKeep_single(gp, irg, block, ip, sp, get_irn_mode(ip));
Matthias Braun's avatar
Matthias Braun committed
951
952
953
	be_node_set_reg_class(keep, 1, gp);
	arch_set_irn_register(env->arch_env, keep, &arm_gp_regs[REG_R12]);
	be_set_constr_single_reg(keep, BE_OUT_POS(0), &arm_gp_regs[REG_R12] );
954

Michael Beck's avatar
Michael Beck committed
955
	fp = new_rd_arm_Sub_i(NULL, irg, block, keep, get_irn_mode(fp), 4);
956
	arch_set_irn_register(env->arch_env, fp, env->arch_env->bp);
957
958
959
	fp = be_new_Copy(gp, irg, block, fp); // XXX Gammelfix: only be_ nodes can have the ignore flag set
	arch_set_irn_register(env->arch_env, fp, env->arch_env->bp);
	be_node_set_flags(fp, BE_OUT_POS(0), arch_irn_flags_ignore);
960

961
	be_abi_reg_map_set(reg_map, env->arch_env->bp, fp);
Michael Beck's avatar
Michael Beck committed
962
	be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R12], keep);
963
	be_abi_reg_map_set(reg_map, env->arch_env->sp, sp);
Michael Beck's avatar
Michael Beck committed
964
965
	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);
966

967
	return env->arch_env->bp;
968
969
}

Michael Beck's avatar
Michael Beck committed
970
971
972
/**
 * Builds the ARM epilogue
 */
973
974
static void arm_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map) {
	arm_abi_env_t *env = self;
975
976
	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
977
978
	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]);
979

Matthias Braun's avatar
Matthias Braun committed
980
	// TODO: Activate Omit fp in epilogue
Michael Beck's avatar
Michael Beck committed
981
	if (env->flags.try_omit_fp) {
982
		curr_sp = be_new_IncSP(env->arch_env->sp, env->irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0);
Sebastian Hack's avatar
Sebastian Hack committed
983
		add_irn_dep(curr_sp, *mem);
984

Michael Beck's avatar
Michael Beck committed
985
986
987
988
		curr_lr = be_new_CopyKeep_single(&arm_reg_classes[CLASS_arm_gp], env->irg, bl, curr_lr, curr_sp, get_irn_mode(curr_lr));
		be_node_set_reg_class(curr_lr, 1, &arm_reg_classes[CLASS_arm_gp]);
		arch_set_irn_register(env->arch_env, curr_lr, &arm_gp_regs[REG_LR]);
		be_set_constr_single_reg(curr_lr, BE_OUT_POS(0), &arm_gp_regs[REG_LR] );
989

Michael Beck's avatar
Michael Beck committed
990
991
992
		curr_pc = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], env->irg, bl, curr_lr );
		arch_set_irn_register(env->arch_env, curr_pc, &arm_gp_regs[REG_PC]);
		be_set_constr_single_reg(curr_pc, BE_OUT_POS(0), &arm_gp_regs[REG_PC] );
Michael Beck's avatar
Michael Beck committed
993
		be_node_set_flags(curr_pc, BE_OUT_POS(0), arch_irn_flags_ignore);
994
995
996
	} else {
		ir_node *sub12_node;
		ir_node *load_node;
Michael Beck's avatar
Michael Beck committed
997
		sub12_node = new_rd_arm_Sub_i(NULL, env->irg, bl, curr_bp, mode_Iu, 12);
Matthias Braun's avatar
Matthias Braun committed
998
999
		// FIXME
		//set_arm_req_out_all(sub12_node, sub12_req);
1000
		arch_set_irn_register(env->arch_env, sub12_node, env->arch_env->sp);
For faster browsing, not all history is shown. View entire blame