arm_transform.c 55.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-2010 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
/**
 * @file
Michael Beck's avatar
Michael Beck committed
22
 * @brief   The codegenerator (transform FIRM into arm FIRM)
23
 * @author  Matthias Braun, Oliver Richter, Tobias Gneist, Michael Beck
24
25
 * @version $Id$
 */
26
27
28
29
30
31
32
33
34
#include "config.h"

#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
#include "irgmod.h"
#include "iredges.h"
#include "irvrfy.h"
#include "ircons.h"
Michael Beck's avatar
Michael Beck committed
35
#include "irprintf.h"
36
37
38
#include "dbginfo.h"
#include "iropt_t.h"
#include "debug.h"
Michael Beck's avatar
Michael Beck committed
39
#include "error.h"
40

41
#include "../benode.h"
42
#include "../beirg.h"
43
#include "../beutil.h"
44
#include "../betranshlp.h"
45
46
#include "../beabihelper.h"
#include "../beabi.h"
47

48
#include "bearch_arm_t.h"
49
50
#include "arm_nodes_attr.h"
#include "arm_transform.h"
51
#include "arm_optimize.h"
52
53
#include "arm_new_nodes.h"
#include "arm_map_regs.h"
54
#include "arm_cconv.h"
55
56
57
58
59

#include "gen_arm_regalloc_if.h"

#include <limits.h>

60
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
Michael Beck's avatar
Michael Beck committed
61

62
63
/** hold the current code generator during transformation */
static arm_code_gen_t *env_cg;
64

65
66
67
68
69
70
71
72
static const arch_register_t *sp_reg = &arm_gp_regs[REG_SP];
static ir_mode               *mode_gp;
static beabi_helper_env_t    *abihelper;
static calling_convention_t  *cconv = NULL;

static pmap                  *node_to_stack;

static bool mode_needs_gp_reg(ir_mode *mode)
73
{
74
	return mode_is_int(mode) || mode_is_reference(mode);
75
76
}

Michael Beck's avatar
Michael Beck committed
77
/**
78
 * create firm graph for a constant
Michael Beck's avatar
Michael Beck committed
79
 */
80
81
82
static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
                                         unsigned int value)
{
83
	ir_node *result;
84
	arm_vals v, vn;
Michael Beck's avatar
Michael Beck committed
85
	int cnt;
86

87
88
89
90
91
92
	/* We only have 8 bit immediates. So we possibly have to combine several
	 * operations to construct the desired value.
	 *
	 * we can either create the value by adding bits to 0 or by removing bits
	 * from an register with all bits set. Try which alternative needs fewer
	 * operations */
93
94
	arm_gen_vals_from_word(value, &v);
	arm_gen_vals_from_word(~value, &vn);
Michael Beck's avatar
Michael Beck committed
95
96
97

	if (vn.ops < v.ops) {
		/* remove bits */
98
99
		result = new_bd_arm_Mvn_imm(dbgi, block, vn.values[0], vn.rors[0]);
		be_dep_on_frame(result);
Michael Beck's avatar
Michael Beck committed
100
101

		for (cnt = 1; cnt < vn.ops; ++cnt) {
102
103
			result = new_bd_arm_Bic_imm(dbgi, block, result,
			                            vn.values[cnt], vn.rors[cnt]);
104
		}
105
	} else {
Michael Beck's avatar
Michael Beck committed
106
		/* add bits */
107
108
		result = new_bd_arm_Mov_imm(dbgi, block, v.values[0], v.rors[0]);
		be_dep_on_frame(result);
Michael Beck's avatar
Michael Beck committed
109
110

		for (cnt = 1; cnt < v.ops; ++cnt) {
111
112
			result = new_bd_arm_Or_imm(dbgi, block, result,
			                           v.values[cnt], v.rors[cnt]);
Michael Beck's avatar
Michael Beck committed
113
		}
114
115
116
117
	}
	return result;
}

118
119
120
121
122
/**
 * Create a DAG constructing a given Const.
 *
 * @param irn  a Firm const
 */
123
124
static ir_node *create_const_graph(ir_node *irn, ir_node *block)
{
125
126
	tarval  *tv = get_Const_tarval(irn);
	ir_mode *mode = get_tarval_mode(tv);
127
	unsigned value;
128
129
130
131
132
133
134

	if (mode_is_reference(mode)) {
		/* ARM is 32bit, so we can safely convert a reference tarval into Iu */
		assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Iu));
		tv = tarval_convert_to(tv, mode_Iu);
	}
	value = get_tarval_long(tv);
135
	return create_const_graph_value(get_irn_dbg_info(irn), block, value);
136
137
}

Michael Beck's avatar
Michael Beck committed
138
/**
Michael Beck's avatar
Michael Beck committed
139
140
141
142
143
144
 * Create an And that will zero out upper bits.
 *
 * @param dbgi     debug info
 * @param block    the basic block
 * @param op       the original node
 * param src_bits  number of lower bits that will remain
Michael Beck's avatar
Michael Beck committed
145
 */
146
147
148
149
150
151
152
153
154
155
156
157
static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                                   int src_bits)
{
	if (src_bits == 8) {
		return new_bd_arm_And_imm(dbgi, block, op, 0xFF, 0);
	} else if (src_bits == 16) {
		ir_node *lshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, 16);
		ir_node *rshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift, ARM_SHF_LSR_IMM, 16);
		return rshift;
	} else {
		panic("zero extension only supported for 8 and 16 bits");
	}
158
159
}

Michael Beck's avatar
Michael Beck committed
160
161
162
/**
 * Generate code for a sign extension.
 */
163
164
165
166
167
168
static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                                   int src_bits)
{
	int shift_width = 32 - src_bits;
	ir_node *lshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, shift_width);
	ir_node *rshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift_node, ARM_SHF_ASR_IMM, shift_width);
169
170
171
	return rshift_node;
}

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                              ir_mode *orig_mode)
{
	int bits = get_mode_size_bits(orig_mode);
	if (bits == 32)
		return op;

	if (mode_is_signed(orig_mode)) {
		return gen_sign_extension(dbgi, block, op, bits);
	} else {
		return gen_zero_extension(dbgi, block, op, bits);
	}
}

/**
 * returns true if it is assured, that the upper bits of a node are "clean"
 * which means for a 16 or 8 bit value, that the upper bits in the register
 * are 0 for unsigned and a copy of the last significant bit for signed
 * numbers.
 */
static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
{
	(void) transformed_node;
	(void) mode;
	/* TODO */
	return false;
}

Michael Beck's avatar
Michael Beck committed
200
201
202
/**
 * Transforms a Conv node.
 *
203
 * @return The created ia32 Conv node
Michael Beck's avatar
Michael Beck committed
204
 */
205
206
static ir_node *gen_Conv(ir_node *node)
{
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *op       = get_Conv_op(node);
	ir_node  *new_op   = be_transform_node(op);
	ir_mode  *src_mode = get_irn_mode(op);
	ir_mode  *dst_mode = get_irn_mode(node);
	dbg_info *dbg      = get_irn_dbg_info(node);

	if (src_mode == dst_mode)
		return new_op;

	if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
		env_cg->have_fp_insn = 1;

		if (USE_FPA(env_cg->isa)) {
			if (mode_is_float(src_mode)) {
				if (mode_is_float(dst_mode)) {
Michael Beck's avatar
Michael Beck committed
223
					/* from float to float */
224
					return new_bd_arm_fpaMvf(dbg, block, new_op, dst_mode);
225
				} else {
Michael Beck's avatar
Michael Beck committed
226
					/* from float to int */
227
					return new_bd_arm_fpaFix(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
228
				}
229
			} else {
Michael Beck's avatar
Michael Beck committed
230
				/* from int to float */
231
				return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
232
			}
233
		} else if (USE_VFP(env_cg->isa)) {
234
			panic("VFP not supported yet");
235
		} else {
236
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
237
		}
238
	} else { /* complete in gp registers */
239
240
		int src_bits = get_mode_size_bits(src_mode);
		int dst_bits = get_mode_size_bits(dst_mode);
Michael Beck's avatar
Michael Beck committed
241
242
		int min_bits;
		ir_mode *min_mode;
243

Michael Beck's avatar
Michael Beck committed
244
		if (src_bits == dst_bits) {
Michael Beck's avatar
Michael Beck committed
245
			/* kill unnecessary conv */
Michael Beck's avatar
Michael Beck committed
246
			return new_op;
247
248
249
250
251
		}

		if (src_bits < dst_bits) {
			min_bits = src_bits;
			min_mode = src_mode;
Michael Beck's avatar
Michael Beck committed
252
		} else {
253
254
255
256
257
258
259
260
261
262
263
264
			min_bits = dst_bits;
			min_mode = dst_mode;
		}

		if (upper_bits_clean(new_op, min_mode)) {
			return new_op;
		}

		if (mode_is_signed(min_mode)) {
			return gen_sign_extension(dbg, block, new_op, min_bits);
		} else {
			return gen_zero_extension(dbg, block, new_op, min_bits);
265
266
267
268
		}
	}
}

269
270
271
272
273
274
275
typedef struct {
	unsigned char  imm_8;
	unsigned char  rot;
} arm_immediate_t;

static bool try_encode_as_immediate(const ir_node *node, arm_immediate_t *res)
{
Michael Beck's avatar
Michael Beck committed
276
	unsigned val, low_pos, high_pos;
277
278
279

	if (!is_Const(node))
		return false;
Michael Beck's avatar
Michael Beck committed
280

281
	val = get_tarval_long(get_Const_tarval(node));
Michael Beck's avatar
Michael Beck committed
282

283
284
285
286
287
288
289
290
291
	if (val == 0) {
		res->imm_8 = 0;
		res->rot   = 0;
		return true;
	}
	if (val <= 0xff) {
		res->imm_8 = val;
		res->rot   = 0;
		return true;
Michael Beck's avatar
Michael Beck committed
292
	}
293
294
295
296
297
298
299
	/* arm allows to use to rotate an 8bit immediate value by a multiple of 2
	   (= 0, 2, 4, 6, ...).
	   So we determine the smallest even position with a bit set
	   and the highest even position with no bit set anymore.
	   If the difference between these 2 is <= 8, then we can encode the value
	   as immediate.
	 */
Michael Beck's avatar
Michael Beck committed
300
301
	low_pos  = ntz(val) & ~1u;
	high_pos = (32-nlz(val)+1) & ~1u;
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

	if (high_pos - low_pos <= 8) {
		res->imm_8 = val >> low_pos;
		res->rot   = 32 - low_pos;
		return true;
	}

	if (high_pos > 24) {
		res->rot = 34 - high_pos;
		val      = val >> (32-res->rot) | val << (res->rot);
		if (val <= 0xff) {
			res->imm_8 = val;
			return true;
		}
	}

	return false;
}

321
static bool is_downconv(const ir_node *node)
322
323
324
325
326
{
	ir_mode *src_mode;
	ir_mode *dest_mode;

	if (!is_Conv(node))
327
		return false;
328
329
330
331
332

	/* we only want to skip the conv when we're the only user
	 * (not optimal but for now...)
	 */
	if (get_irn_n_edges(node) > 1)
333
		return false;
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387

	src_mode  = get_irn_mode(get_Conv_op(node));
	dest_mode = get_irn_mode(node);
	return
		mode_needs_gp_reg(src_mode)  &&
		mode_needs_gp_reg(dest_mode) &&
		get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
}

static ir_node *arm_skip_downconv(ir_node *node)
{
	while (is_downconv(node))
		node = get_Conv_op(node);
	return node;
}

typedef enum {
	MATCH_NONE         = 0,
	MATCH_COMMUTATIVE  = 1 << 0,
	MATCH_SIZE_NEUTRAL = 1 << 1,
} match_flags_t;

typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, unsigned char imm8, unsigned char imm_rot);

static ir_node *gen_int_binop(ir_node *node, match_flags_t flags,
		new_binop_reg_func new_reg, new_binop_imm_func new_imm)
{
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_binop_left(node);
	ir_node  *new_op1;
	ir_node  *op2     = get_binop_right(node);
	ir_node  *new_op2;
	dbg_info *dbgi    = get_irn_dbg_info(node);
	arm_immediate_t imm;

	if (flags & MATCH_SIZE_NEUTRAL) {
		op1 = arm_skip_downconv(op1);
		op2 = arm_skip_downconv(op2);
	} else {
		assert(get_mode_size_bits(get_irn_mode(node)) == 32);
	}

	if (try_encode_as_immediate(op2, &imm)) {
		ir_node *new_op1 = be_transform_node(op1);
		return new_imm(dbgi, block, new_op1, imm.imm_8, imm.rot);
	}
	new_op2 = be_transform_node(op2);
    if ((flags & MATCH_COMMUTATIVE) && try_encode_as_immediate(op1, &imm)) {
		return new_imm(dbgi, block, new_op2, imm.imm_8, imm.rot);
	}
	new_op1 = be_transform_node(op1);

	return new_reg(dbgi, block, new_op1, new_op2);
Michael Beck's avatar
Michael Beck committed
388
}
389
390

/**
391
 * Creates an ARM Add.
392
393
394
 *
 * @return the created arm Add node
 */
395
396
static ir_node *gen_Add(ir_node *node)
{
397
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
398

399
	if (mode_is_float(mode)) {
400
401
402
403
404
405
		ir_node  *block   = be_transform_node(get_nodes_block(node));
		ir_node  *op1     = get_Add_left(node);
		ir_node  *op2     = get_Add_right(node);
		dbg_info *dbgi    = get_irn_dbg_info(node);
		ir_node  *new_op1 = be_transform_node(op1);
		ir_node  *new_op2 = be_transform_node(op2);
406
		env_cg->have_fp_insn = 1;
407
		if (USE_FPA(env_cg->isa)) {
408
#if 0
409
			if (is_arm_fpaMvf_i(new_op1))
410
				return new_bd_arm_fpaAdf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
411
			if (is_arm_fpaMvf_i(new_op2))
412
413
414
				return new_bd_arm_fpaAdf_i(dbgi, block, new_op1, mode, get_arm_imm_value(new_op2));
#endif
			return new_bd_arm_fpaAdf(dbgi, block, new_op1, new_op2, mode);
415
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
416
			assert(mode != mode_E && "IEEE Extended FP not supported");
417
			panic("VFP not supported yet");
418
		} else {
419
			panic("Softfloat not supported yet");
420
421
		}
	} else {
422
#if 0
Michael Beck's avatar
Michael Beck committed
423
		/* check for MLA */
Michael Beck's avatar
Michael Beck committed
424
		if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
425
			new_op3 = new_op2;
Michael Beck's avatar
Michael Beck committed
426
427
			new_op2 = get_irn_n(new_op1, 1);
			new_op1 = get_irn_n(new_op1, 0);
Michael Beck's avatar
Michael Beck committed
428

429
			return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
Michael Beck's avatar
Michael Beck committed
430
		}
Michael Beck's avatar
Michael Beck committed
431
		if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
432
433
434
			new_op3 = new_op1;
			new_op1 = get_irn_n(new_op2, 0);
			new_op2 = get_irn_n(new_op2, 1);
Michael Beck's avatar
Michael Beck committed
435

436
			return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
Michael Beck's avatar
Michael Beck committed
437
		}
438
#endif
439

440
441
		return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
				new_bd_arm_Add_reg, new_bd_arm_Add_imm);
Michael Beck's avatar
Michael Beck committed
442
443
	}
}
444
445

/**
446
 * Creates an ARM Mul.
447
448
449
 *
 * @return the created arm Mul node
 */
450
451
static ir_node *gen_Mul(ir_node *node)
{
452
453
454
455
456
457
458
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_Mul_left(node);
	ir_node  *new_op1 = be_transform_node(op1);
	ir_node  *op2     = get_Mul_right(node);
	ir_node  *new_op2 = be_transform_node(op2);
	ir_mode  *mode    = get_irn_mode(node);
	dbg_info *dbg     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
459

460
	if (mode_is_float(mode)) {
461
		env_cg->have_fp_insn = 1;
462
		if (USE_FPA(env_cg->isa)) {
463
#if 0
464
			if (is_arm_Mov_i(new_op1))
465
				return new_bd_arm_fpaMuf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
466
			if (is_arm_Mov_i(new_op2))
467
				return new_bd_arm_fpaMuf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
468
#endif
469
			return new_bd_arm_fpaMuf(dbg, block, new_op1, new_op2, mode);
470
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
471
			assert(mode != mode_E && "IEEE Extended FP not supported");
472
			panic("VFP not supported yet");
473
		} else {
474
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
475
		}
476
	}
477
	assert(mode_is_data(mode));
478
	return new_bd_arm_Mul(dbg, block, new_op1, new_op2);
479
480
}

481
482
static ir_node *gen_Quot(ir_node *node)
{
483
484
485
486
487
488
489
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_Quot_left(node);
	ir_node  *new_op1 = be_transform_node(op1);
	ir_node  *op2     = get_Quot_right(node);
	ir_node  *new_op2 = be_transform_node(op2);
	ir_mode  *mode    = get_irn_mode(node);
	dbg_info *dbg     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
490

491
	assert(mode != mode_E && "IEEE Extended FP not supported");
492

493
	env_cg->have_fp_insn = 1;
494
	if (USE_FPA(env_cg->isa)) {
495
#if 0
496
		if (is_arm_Mov_i(new_op1))
497
			return new_bd_arm_fpaRdf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
498
		if (is_arm_Mov_i(new_op2))
499
			return new_bd_arm_fpaDvf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
500
#endif
501
		return new_bd_arm_fpaDvf(dbg, block, new_op1, new_op2, mode);
502
	} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
503
		assert(mode != mode_E && "IEEE Extended FP not supported");
504
		panic("VFP not supported yet");
505
	} else {
506
		panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
507
	}
Michael Beck's avatar
Michael Beck committed
508
509
}

510
511
512
513
static ir_node *gen_And(ir_node *node)
{
	return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
			new_bd_arm_And_reg, new_bd_arm_And_imm);
514
}
515

516
517
518
519
static ir_node *gen_Or(ir_node *node)
{
	return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
			new_bd_arm_Or_reg, new_bd_arm_Or_imm);
520
}
521

522
523
524
525
static ir_node *gen_Eor(ir_node *node)
{
	return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
			new_bd_arm_Eor_reg, new_bd_arm_Eor_imm);
526
}
527

528
529
static ir_node *gen_Sub(ir_node *node)
{
530
531
532
533
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_Sub_left(node);
	ir_node  *new_op1 = be_transform_node(op1);
	ir_node  *op2     = get_Sub_right(node);
Michael Beck's avatar
Michael Beck committed
534
	ir_node  *new_op2 = be_transform_node(op2);
535
	ir_mode  *mode    = get_irn_mode(node);
536
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
537

538
	if (mode_is_float(mode)) {
539
		env_cg->have_fp_insn = 1;
540
		if (USE_FPA(env_cg->isa)) {
541
#if 0
542
			if (is_arm_Mov_i(new_op1))
543
				return new_bd_arm_fpaRsf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
544
			if (is_arm_Mov_i(new_op2))
545
546
547
				return new_bd_arm_fpaSuf_i(dbgi, block, new_op1, mode, get_arm_imm_value(new_op2));
#endif
			return new_bd_arm_fpaSuf(dbgi, block, new_op1, new_op2, mode);
548
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
549
			assert(mode != mode_E && "IEEE Extended FP not supported");
550
			panic("VFP not supported yet");
551
		} else {
552
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
553
		}
554
555
556
	} else {
		return gen_int_binop(node, MATCH_SIZE_NEUTRAL,
				new_bd_arm_Sub_reg, new_bd_arm_Sub_imm);
Michael Beck's avatar
Michael Beck committed
557
	}
558
}
Michael Beck's avatar
Michael Beck committed
559

Michael Beck's avatar
Michael Beck committed
560
561
562
563
/**
 * Checks if a given value can be used as an immediate for the given
 * ARM shift mode.
 */
564
565
566
567
568
569
570
571
572
573
static bool can_use_shift_constant(unsigned int val,
                                   arm_shift_modifier_t modifier)
{
	if (val <= 31)
		return true;
	if (val == 32 && modifier != ARM_SHF_LSL_REG && modifier != ARM_SHF_ROR_REG)
		return true;
	return false;
}

Michael Beck's avatar
Michael Beck committed
574
575
576
577
578
579
580
/**
 * generate an ARM shift instruction.
 *
 * @param node            the node
 * @param flags           matching flags
 * @param shift_modifier  initial encoding of the desired shift operation
 */
581
static ir_node *make_shift(ir_node *node, match_flags_t flags,
582
		arm_shift_modifier_t shift_modifier)
583
{
584
585
586
587
	ir_node  *block = be_transform_node(get_nodes_block(node));
	ir_node  *op1   = get_binop_left(node);
	ir_node  *op2   = get_binop_right(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
588
589
590
591
592
593
	ir_node  *new_op1;
	ir_node  *new_op2;

	if (flags & MATCH_SIZE_NEUTRAL) {
		op1 = arm_skip_downconv(op1);
		op2 = arm_skip_downconv(op2);
594
	}
595

596
	new_op1 = be_transform_node(op1);
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
	if (is_Const(op2)) {
		tarval      *tv  = get_Const_tarval(op2);
		unsigned int val = get_tarval_long(tv);
		assert(tarval_is_long(tv));
		if (can_use_shift_constant(val, shift_modifier)) {
			switch (shift_modifier) {
			case ARM_SHF_LSL_REG: shift_modifier = ARM_SHF_LSL_IMM; break;
			case ARM_SHF_LSR_REG: shift_modifier = ARM_SHF_LSR_IMM; break;
			case ARM_SHF_ASR_REG: shift_modifier = ARM_SHF_ASR_IMM; break;
			case ARM_SHF_ROR_REG: shift_modifier = ARM_SHF_ROR_IMM; break;
			default: panic("unexpected shift modifier");
			}
			return new_bd_arm_Mov_reg_shift_imm(dbgi, block, new_op1,
			                                    shift_modifier, val);
		}
	}

614
	new_op2 = be_transform_node(op2);
615
616
	return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
	                                    shift_modifier);
617
618
}

619
620
621
static ir_node *gen_Shl(ir_node *node)
{
	return make_shift(node, MATCH_SIZE_NEUTRAL, ARM_SHF_LSL_REG);
622
623
}

624
625
626
static ir_node *gen_Shr(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_LSR_REG);
627
628
}

629
630
631
static ir_node *gen_Shrs(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_ASR_REG);
632
633
}

634
635
static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2)
{
Michael Beck's avatar
Michael Beck committed
636
637
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
638
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
639
640
	ir_node  *new_op2 = be_transform_node(op2);

641
642
	return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
	                                    ARM_SHF_ROR_REG);
Michael Beck's avatar
Michael Beck committed
643
644
}

645
646
static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2)
{
Michael Beck's avatar
Michael Beck committed
647
648
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
649
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
650
651
	ir_node  *new_op2 = be_transform_node(op2);

652
	/* Note: there is no Rol on arm, we have to use Ror */
653
654
655
	new_op2 = new_bd_arm_Rsb_imm(dbgi, block, new_op2, 32, 0);
	return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
	                                    ARM_SHF_ROR_REG);
Michael Beck's avatar
Michael Beck committed
656
657
}

658
659
static ir_node *gen_Rotl(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
660
661
662
663
664
665
666
667
668
	ir_node *rotate = NULL;
	ir_node *op1    = get_Rotl_left(node);
	ir_node *op2    = get_Rotl_right(node);

	/* Firm has only RotL, so we are looking for a right (op2)
	   operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
	   that means we can create a RotR. */

	if (is_Add(op2)) {
Michael Beck's avatar
Michael Beck committed
669
		ir_node *right = get_Add_right(op2);
Michael Beck's avatar
Michael Beck committed
670
671
672
673
		if (is_Const(right)) {
			tarval  *tv   = get_Const_tarval(right);
			ir_mode *mode = get_irn_mode(node);
			long     bits = get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
674
			ir_node *left = get_Add_left(op2);
Michael Beck's avatar
Michael Beck committed
675
676

			if (is_Minus(left) &&
Michael Beck's avatar
Michael Beck committed
677
			    tarval_is_long(tv)          &&
Michael Beck's avatar
Michael Beck committed
678
679
680
681
			    get_tarval_long(tv) == bits &&
			    bits                == 32)
				rotate = gen_Ror(node, op1, get_Minus_op(left));
		}
Michael Beck's avatar
Michael Beck committed
682
683
684
685
686
687
688
689
690
691
692
693
694
	} else if (is_Sub(op2)) {
		ir_node *left = get_Sub_left(op2);
		if (is_Const(left)) {
			tarval  *tv   = get_Const_tarval(left);
			ir_mode *mode = get_irn_mode(node);
			long     bits = get_mode_size_bits(mode);
			ir_node *right = get_Sub_right(op2);

			if (tarval_is_long(tv)          &&
			    get_tarval_long(tv) == bits &&
			    bits                == 32)
				rotate = gen_Ror(node, op1, right);
		}
695
	} else if (is_Const(op2)) {
696
697
698
		tarval  *tv   = get_Const_tarval(op2);
		ir_mode *mode = get_irn_mode(node);
		long     bits = get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
699

700
701
702
703
		if (tarval_is_long(tv) && bits == 32) {
			ir_node  *block   = be_transform_node(get_nodes_block(node));
			ir_node  *new_op1 = be_transform_node(op1);
			dbg_info *dbgi    = get_irn_dbg_info(node);
704

705
706
707
			bits = (bits - get_tarval_long(tv)) & 31;
			rotate = new_bd_arm_Mov_reg_shift_imm(dbgi, block, new_op1, ARM_SHF_ROR_IMM, bits);
		}
Michael Beck's avatar
Michael Beck committed
708
709
710
711
712
713
714
715
716
	}

	if (rotate == NULL) {
		rotate = gen_Rol(node, op1, op2);
	}

	return rotate;
}

717
718
static ir_node *gen_Not(ir_node *node)
{
719
720
721
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op      = get_Not_op(node);
	ir_node  *new_op  = be_transform_node(op);
722
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
723

724
725
726
	/* TODO: we could do alot more here with all the Mvn variations */

	return new_bd_arm_Mvn_reg(dbgi, block, new_op);
727
728
}

729
730
static ir_node *gen_Abs(ir_node *node)
{
731
	ir_node  *block   = be_transform_node(get_nodes_block(node));
732
	ir_node  *op      = get_Abs_op(node);
733
	ir_node  *new_op  = be_transform_node(op);
734
	dbg_info *dbgi    = get_irn_dbg_info(node);
735
	ir_mode  *mode    = get_irn_mode(node);
736

737
	if (mode_is_float(mode)) {
738
		env_cg->have_fp_insn = 1;
739
		if (USE_FPA(env_cg->isa)) {
740
			return new_bd_arm_fpaAbs(dbgi, block, new_op, mode);
741
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
742
			assert(mode != mode_E && "IEEE Extended FP not supported");
743
			panic("VFP not supported yet");
744
		} else {
745
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
746
		}
747
	}
748
	assert(mode_is_data(mode));
749
	return new_bd_arm_Abs(dbgi, block, new_op);
750
751
}

752
753
static ir_node *gen_Minus(ir_node *node)
{
754
755
756
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op      = get_Minus_op(node);
	ir_node  *new_op  = be_transform_node(op);
757
	dbg_info *dbgi    = get_irn_dbg_info(node);
758
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
759

760
	if (mode_is_float(mode)) {
761
		env_cg->have_fp_insn = 1;
762
		if (USE_FPA(env_cg->isa)) {
763
			return new_bd_arm_fpaMvf(dbgi, block, op, mode);
764
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
765
			assert(mode != mode_E && "IEEE Extended FP not supported");
766
			panic("VFP not supported yet");
767
		} else {
768
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
769
		}
770
	}
771
	assert(mode_is_data(mode));
772
	return new_bd_arm_Rsb_imm(dbgi, block, new_op, 0, 0);
773
774
}

775
776
static ir_node *gen_Load(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
777
778
779
780
781
782
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *ptr      = get_Load_ptr(node);
	ir_node  *new_ptr  = be_transform_node(ptr);
	ir_node  *mem      = get_Load_mem(node);
	ir_node  *new_mem  = be_transform_node(mem);
	ir_mode  *mode     = get_Load_mode(node);
783
	dbg_info *dbgi      = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
784
	ir_node  *new_load = NULL;
785

Michael Beck's avatar
Michael Beck committed
786
	if (mode_is_float(mode)) {
787
		env_cg->have_fp_insn = 1;
788
		if (USE_FPA(env_cg->isa)) {
789
			new_load = new_bd_arm_fpaLdf(dbgi, block, new_ptr, new_mem, mode);
790
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
791
			assert(mode != mode_E && "IEEE Extended FP not supported");
792
			panic("VFP not supported yet");
793
		} else {
794
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
795
		}
796
	} else {
797
		assert(mode_is_data(mode) && "unsupported mode for Load");
798

799
		new_load = new_bd_arm_Ldr(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false);
800
	}
Michael Beck's avatar
Michael Beck committed
801
	set_irn_pinned(new_load, get_irn_pinned(node));
802
803
804
805

	/* check for special case: the loaded value might not be used */
	if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) {
		/* add a result proj and a Keep to produce a pseudo use */
806
		ir_node *proj = new_r_Proj(new_load, mode_Iu, pn_arm_Ldr_res);
807
		be_new_Keep(block, 1, &proj);
808
809
	}

Michael Beck's avatar
Michael Beck committed
810
	return new_load;
811
812
}

813
814
static ir_node *gen_Store(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
815
816
817
818
819
820
821
822
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *ptr      = get_Store_ptr(node);
	ir_node  *new_ptr  = be_transform_node(ptr);
	ir_node  *mem      = get_Store_mem(node);
	ir_node  *new_mem  = be_transform_node(mem);
	ir_node  *val      = get_Store_value(node);
	ir_node  *new_val  = be_transform_node(val);
	ir_mode  *mode     = get_irn_mode(val);
823
	dbg_info *dbgi     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
824
	ir_node *new_store = NULL;
825

Michael Beck's avatar
Michael Beck committed
826
	if (mode_is_float(mode)) {
827
		env_cg->have_fp_insn = 1;
828
		if (USE_FPA(env_cg->isa)) {
829
830
			new_store = new_bd_arm_fpaStf(dbgi, block, new_ptr, new_val,
			                              new_mem, mode);
831
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
832
			assert(mode != mode_E && "IEEE Extended FP not supported");
833
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
834
		} else {
835
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
836
837
		}
	} else {
838
		assert(mode_is_data(mode) && "unsupported mode for Store");
839
840
		new_store = new_bd_arm_Str(dbgi, block, new_ptr, new_val, new_mem, mode,
		                           NULL, 0, 0, false);
841
	}
Michael Beck's avatar
Michael Beck committed
842
843
	set_irn_pinned(new_store, get_irn_pinned(node));
	return new_store;
844
845
}

846
847
848
849
850
851
852
853
854
static ir_node *gen_Jmp(ir_node *node)
{
	ir_node  *block     = get_nodes_block(node);
	ir_node  *new_block = be_transform_node(block);
	dbg_info *dbgi      = get_irn_dbg_info(node);

	return new_bd_arm_Jmp(dbgi, new_block);
}

855
856
static ir_node *gen_SwitchJmp(ir_node *node)
{
857
858
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *selector = get_Cond_selector(node);
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
	dbg_info *dbgi     = get_irn_dbg_info(node);
	ir_node *new_op = be_transform_node(selector);
	ir_node *const_graph;
	ir_node *sub;

	ir_node *proj;
	const ir_edge_t *edge;
	int min = INT_MAX;
	int max = INT_MIN;
	int translation;
	int pn;
	int n_projs;

	foreach_out_edge(node, edge) {
		proj = get_edge_src_irn(edge);
		assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");

		pn = get_Proj_proj(proj);

		min = pn<min ? pn : min;
		max = pn>max ? pn : max;
	}
	translation = min;
	n_projs = max - translation + 1;
883

884
885
886
	foreach_out_edge(node, edge) {
		proj = get_edge_src_irn(edge);
		assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
887

888
889
890
		pn = get_Proj_proj(proj) - translation;
		set_Proj_proj(proj, pn);
	}
891

892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
	const_graph = create_const_graph_value(dbgi, block, translation);
	sub = new_bd_arm_Sub_reg(dbgi, block, new_op, const_graph);
	return new_bd_arm_SwitchJmp(dbgi, block, sub, n_projs, get_Cond_default_proj(node) - translation);
}

static ir_node *gen_Cmp(ir_node *node)
{
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *op1      = get_Cmp_left(node);
	ir_node  *op2      = get_Cmp_right(node);
	ir_mode  *cmp_mode = get_irn_mode(op1);
	dbg_info *dbgi     = get_irn_dbg_info(node);
	ir_node  *new_op1;
	ir_node  *new_op2;
	bool      is_unsigned;

	if (mode_is_float(cmp_mode)) {
909
910
911
912
913
914
		/* TODO: this is broken... */
		new_op1 = be_transform_node(op1);
		new_op2 = be_transform_node(op2);

		return new_bd_arm_Cmfe(dbgi, block, new_op1, new_op2, false);

915
916
917
918
919
920
921
922
923
		panic("FloatCmp NIY");
#if 0
		ir_node *new_op2  = be_transform_node(op2);
		/* floating point compare */
		pn_Cmp pnc = get_Proj_proj(selector);

		if (pnc & pn_Cmp_Uo) {
			/* check for unordered, need cmf */
			return new_bd_arm_fpaCmfBra(dbgi, block, new_op1, new_op2, pnc);
924
		}
925
926
927
928
		/* Hmm: use need cmfe */
		return new_bd_arm_fpaCmfeBra(dbgi, block, new_op1, new_op2, pnc);
#endif
	}
929

930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
	assert(get_irn_mode(op2) == cmp_mode);
	is_unsigned = !mode_is_signed(cmp_mode);

	/* compare with 0 can be done with Tst */
	if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) {
		new_op1 = be_transform_node(op1);
		new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
		return new_bd_arm_Tst_reg(dbgi, block, new_op1, new_op1, false,
		                          is_unsigned);
	}
	if (is_Const(op1) && tarval_is_null(get_Const_tarval(op1))) {
		new_op2 = be_transform_node(op2);
		new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
		return new_bd_arm_Tst_reg(dbgi, block, new_op2, new_op2, true,
		                          is_unsigned);
945
	}
946

Michael Beck's avatar
Michael Beck committed
947
	/* integer compare, TODO: use shifter_op in all its combinations */
948
949
950
951
952
953
	new_op1 = be_transform_node(op1);
	new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
	new_op2 = be_transform_node(op2);
	new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
	return new_bd_arm_Cmp_reg(dbgi, block, new_op1, new_op2, false,
	                          is_unsigned);
954
955
}

956
957
958
959
960
961
962
static ir_node *gen_Cond(ir_node *node)
{
	ir_node  *selector = get_Cond_selector(node);
	ir_mode  *mode     = get_irn_mode(selector);
	ir_node  *block;
	ir_node  *flag_node;
	dbg_info *dbgi;
963

964
965
	if (mode != mode_b) {
		return gen_SwitchJmp(node);
966
	}
967
968
969
970
971
	assert(is_Proj(selector));

	block     = be_transform_node(get_nodes_block(node));
	dbgi      = get_irn_dbg_info(node);
	flag_node = be_transform_node(get_Proj_pred(selector));
972

973
	return new_bd_arm_B(dbgi, block, flag_node, get_Proj_proj(selector));
974
975
}

976
977
static tarval *fpa_imm[3][fpa_max];

978
#if 0
979
980
/**
 * Check, if a floating point tarval is an fpa immediate, i.e.
981
 * one of 0, 1, 2, 3, 4, 5, 10, or 0.5.
982
 */
983
984
static int is_fpa_immediate(tarval *tv)
{
985
986
987
988
989
990
991
992
993
994
995
996
997
998
	ir_mode *mode = get_tarval_mode(tv);
	int i, j, res = 1;

	switch (get_mode_size_bits(mode)) {
	case 32:
		i = 0;
		break;
	case 64:
		i = 1;
		break;
	default:
		i = 2;
	}

999
	if (tarval_is_negative(tv)) {
1000
		tv = tarval_neg(tv);
For faster browsing, not all history is shown. View entire blame