arm_transform.c 45.2 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
/**
 * @file
Michael Beck's avatar
Michael Beck committed
22
23
 * @brief   The codegenerator (transform FIRM into arm FIRM)
 * @author  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
47
48
#include "bearch_arm_t.h"

#include "arm_nodes_attr.h"
#include "arm_transform.h"
49
#include "arm_optimize.h"
50
51
52
53
54
55
56
#include "arm_new_nodes.h"
#include "arm_map_regs.h"

#include "gen_arm_regalloc_if.h"

#include <limits.h>

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

59
60
/** hold the current code generator during transformation */
static arm_code_gen_t *env_cg;
61

62
63
static inline int mode_needs_gp_reg(ir_mode *mode)
{
64
	return mode_is_int(mode) || mode_is_reference(mode);
65
66
}

Michael Beck's avatar
Michael Beck committed
67
68
69
/**
 * Creates a possible DAG for an constant.
 */
70
71
72
static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
                                         unsigned int value)
{
73
	ir_node *result;
74
	arm_vals v, vn;
Michael Beck's avatar
Michael Beck committed
75
	int cnt;
76

77
78
	arm_gen_vals_from_word(value, &v);
	arm_gen_vals_from_word(~value, &vn);
Michael Beck's avatar
Michael Beck committed
79
80
81

	if (vn.ops < v.ops) {
		/* remove bits */
82
83
		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
84
85

		for (cnt = 1; cnt < vn.ops; ++cnt) {
86
87
			result = new_bd_arm_Bic_imm(dbgi, block, result,
			                            vn.values[cnt], vn.rors[cnt]);
88
		}
89
	} else {
Michael Beck's avatar
Michael Beck committed
90
		/* add bits */
91
92
		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
93
94

		for (cnt = 1; cnt < v.ops; ++cnt) {
95
96
			result = new_bd_arm_Or_imm(dbgi, block, result,
			                           v.values[cnt], v.rors[cnt]);
Michael Beck's avatar
Michael Beck committed
97
		}
98
99
100
101
	}
	return result;
}

102
103
104
105
106
/**
 * Create a DAG constructing a given Const.
 *
 * @param irn  a Firm const
 */
107
108
static ir_node *create_const_graph(ir_node *irn, ir_node *block)
{
109
110
	tarval  *tv = get_Const_tarval(irn);
	ir_mode *mode = get_tarval_mode(tv);
111
	unsigned value;
112
113
114
115
116
117
118

	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);
119
	return create_const_graph_value(get_irn_dbg_info(irn), block, value);
120
121
}

Michael Beck's avatar
Michael Beck committed
122
/**
Michael Beck's avatar
Michael Beck committed
123
124
125
126
127
128
 * 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
129
 */
130
131
132
133
134
135
136
137
138
139
140
141
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");
	}
142
143
}

Michael Beck's avatar
Michael Beck committed
144
145
146
/**
 * Generate code for a sign extension.
 */
147
148
149
150
151
152
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);
153
154
155
	return rshift_node;
}

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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
184
185
186
/**
 * Transforms a Conv node.
 *
187
 * @return The created ia32 Conv node
Michael Beck's avatar
Michael Beck committed
188
 */
189
190
static ir_node *gen_Conv(ir_node *node)
{
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
	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
207
					/* from float to float */
208
					return new_bd_arm_fpaMvf(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
209
210
211
				}
				else {
					/* from float to int */
212
					return new_bd_arm_fpaFix(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
213
214
215
216
				}
			}
			else {
				/* from int to float */
217
				return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
218
			}
219
		} else if (USE_VFP(env_cg->isa)) {
220
			panic("VFP not supported yet");
221
			return NULL;
222
		} else {
223
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
224
225
			return NULL;
		}
226
	} else { /* complete in gp registers */
227
228
		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
229
230
		int min_bits;
		ir_mode *min_mode;
231

Michael Beck's avatar
Michael Beck committed
232
233
234
		if (src_bits == dst_bits) {
			/* kill unneccessary conv */
			return new_op;
235
236
237
238
239
		}

		if (src_bits < dst_bits) {
			min_bits = src_bits;
			min_mode = src_mode;
Michael Beck's avatar
Michael Beck committed
240
		} else {
241
242
243
244
245
246
247
248
249
250
251
252
			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);
253
254
255
256
		}
	}
}

257
258
259
260
261
262
263
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
264
	unsigned val, low_pos, high_pos;
265
266
267

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

269
	val = get_tarval_long(get_Const_tarval(node));
Michael Beck's avatar
Michael Beck committed
270

271
272
273
274
275
276
277
278
279
	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
280
	}
281
282
283
284
285
286
287
	/* 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
288
289
	low_pos  = ntz(val) & ~1u;
	high_pos = (32-nlz(val)+1) & ~1u;
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
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

	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;
}

static int is_downconv(const ir_node *node)
{
	ir_mode *src_mode;
	ir_mode *dest_mode;

	if (!is_Conv(node))
		return 0;

	/* 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)
		return 0;

	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
376
}
377
378

/**
379
 * Creates an ARM Add.
380
381
382
 *
 * @return the created arm Add node
 */
383
384
static ir_node *gen_Add(ir_node *node)
{
385
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
386

387
	if (mode_is_float(mode)) {
388
389
390
391
392
393
		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);
394
		env_cg->have_fp_insn = 1;
395
		if (USE_FPA(env_cg->isa)) {
396
#if 0
397
			if (is_arm_fpaMvf_i(new_op1))
398
				return new_bd_arm_fpaAdf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
399
			if (is_arm_fpaMvf_i(new_op2))
400
401
402
				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);
403
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
404
			assert(mode != mode_E && "IEEE Extended FP not supported");
405
			panic("VFP not supported yet");
406
			return NULL;
Michael Beck's avatar
Michael Beck committed
407
		}
408
		else {
409
			panic("Softfloat not supported yet");
410
411
412
			return NULL;
		}
	} else {
413
#if 0
Michael Beck's avatar
Michael Beck committed
414
		/* check for MLA */
Michael Beck's avatar
Michael Beck committed
415
		if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
416
			new_op3 = new_op2;
Michael Beck's avatar
Michael Beck committed
417
418
			new_op2 = get_irn_n(new_op1, 1);
			new_op1 = get_irn_n(new_op1, 0);
Michael Beck's avatar
Michael Beck committed
419

420
			return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
Michael Beck's avatar
Michael Beck committed
421
		}
Michael Beck's avatar
Michael Beck committed
422
		if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
423
424
425
			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
426

427
			return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
Michael Beck's avatar
Michael Beck committed
428
		}
429
#endif
430

431
432
		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
433
434
	}
}
435
436

/**
437
 * Creates an ARM Mul.
438
439
440
 *
 * @return the created arm Mul node
 */
441
442
static ir_node *gen_Mul(ir_node *node)
{
443
444
445
446
447
448
449
	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
450

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

/**
477
 * Creates an ARM floating point Div.
478
 *
Michael Beck's avatar
Michael Beck committed
479
 * @param env   The transformation environment
480
481
 * @return the created arm fDiv node
 */
482
483
static ir_node *gen_Quot(ir_node *node)
{
484
485
486
487
488
489
490
	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
491

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

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

513
/**
514
 * Creates an ARM And.
515
516
517
 *
 * @return the created arm And node
 */
518
519
520
521
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);
522
}
523
524

/**
525
 * Creates an ARM Orr.
526
 *
Michael Beck's avatar
Michael Beck committed
527
 * @param env   The transformation environment
528
529
 * @return the created arm Or node
 */
530
531
532
533
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);
534
}
535
536

/**
537
 * Creates an ARM Eor.
538
539
540
 *
 * @return the created arm Eor node
 */
541
542
543
544
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);
545
}
546
547

/**
548
 * Creates an ARM Sub.
549
550
551
 *
 * @return the created arm Sub node
 */
552
553
static ir_node *gen_Sub(ir_node *node)
{
554
555
556
557
	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
558
	ir_node  *new_op2 = be_transform_node(op2);
559
	ir_mode  *mode    = get_irn_mode(node);
560
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
561

562
	if (mode_is_float(mode)) {
563
		env_cg->have_fp_insn = 1;
564
		if (USE_FPA(env_cg->isa)) {
565
#if 0
566
			if (is_arm_Mov_i(new_op1))
567
				return new_bd_arm_fpaRsf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
568
			if (is_arm_Mov_i(new_op2))
569
570
571
				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);
572
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
573
			assert(mode != mode_E && "IEEE Extended FP not supported");
574
			panic("VFP not supported yet");
575
			return NULL;
576
		} else {
577
			panic("Softfloat not supported yet");
578
			return NULL;
Michael Beck's avatar
Michael Beck committed
579
		}
580
581
582
	} 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
583
	}
584
}
Michael Beck's avatar
Michael Beck committed
585

586
587
588
589
590
591
592
593
594
595
596
597
598
static ir_node *make_shift(ir_node *node, match_flags_t flags,
		arm_shift_modifier shift_modifier)
{
	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);
	ir_node  *new_op1;
	ir_node  *new_op2;

	if (flags & MATCH_SIZE_NEUTRAL) {
		op1 = arm_skip_downconv(op1);
		op2 = arm_skip_downconv(op2);
599
	}
600
601
602
	new_op1 = be_transform_node(op1);
	new_op2 = be_transform_node(op2);
	return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2, shift_modifier);
603
604
605
}

/**
606
 * Creates an ARM Shl.
607
 *
608
 * @return the created ARM Shl node
609
 */
610
611
612
static ir_node *gen_Shl(ir_node *node)
{
	return make_shift(node, MATCH_SIZE_NEUTRAL, ARM_SHF_LSL_REG);
613
614
615
}

/**
616
 * Creates an ARM Shr.
617
 *
618
 * @return the created ARM Shr node
619
 */
620
621
622
static ir_node *gen_Shr(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_LSR_REG);
623
624
625
}

/**
626
 * Creates an ARM Shrs.
627
 *
628
 * @return the created ARM Shrs node
629
 */
630
631
632
static ir_node *gen_Shrs(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_ASR_REG);
633
634
}

Michael Beck's avatar
Michael Beck committed
635
636
637
638
639
/**
 * Creates an ARM Ror.
 *
 * @return the created ARM Ror node
 */
640
641
static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2)
{
Michael Beck's avatar
Michael Beck committed
642
643
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
644
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
645
646
	ir_node  *new_op2 = be_transform_node(op2);

647
648
	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
649
650
651
652
653
654
655
656
657
}

/**
 * Creates an ARM Rol.
 *
 * @return the created ARM Rol node
 *
 * Note: there is no Rol on arm, we have to use Ror
 */
658
659
static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2)
{
Michael Beck's avatar
Michael Beck committed
660
661
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
662
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
663
664
	ir_node  *new_op2 = be_transform_node(op2);

665
666
667
	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
668
669
670
671
672
673
674
}

/**
 * Creates an ARM ROR from a Firm Rotl.
 *
 * @return the created ARM Ror node
 */
675
676
static ir_node *gen_Rotl(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
677
678
679
680
681
682
683
684
685
	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
686
		ir_node *right = get_Add_right(op2);
Michael Beck's avatar
Michael Beck committed
687
688
689
690
		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
691
			ir_node *left = get_Add_left(op2);
Michael Beck's avatar
Michael Beck committed
692
693

			if (is_Minus(left) &&
Michael Beck's avatar
Michael Beck committed
694
			    tarval_is_long(tv)          &&
Michael Beck's avatar
Michael Beck committed
695
696
697
698
			    get_tarval_long(tv) == bits &&
			    bits                == 32)
				rotate = gen_Ror(node, op1, get_Minus_op(left));
		}
Michael Beck's avatar
Michael Beck committed
699
700
701
702
703
704
705
706
707
708
709
710
711
	} 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);
		}
712
	} else if (is_Const(op2)) {
713
714
715
		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
716

717
718
719
720
		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);
721

722
723
724
			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
725
726
727
728
729
730
731
732
733
	}

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

	return rotate;
}

734
735
736
/**
 * Transforms a Not node.
 *
737
 * @return the created ARM Not node
738
 */
739
740
static ir_node *gen_Not(ir_node *node)
{
741
742
743
	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);
744
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
745

746
747
748
	/* TODO: we could do alot more here with all the Mvn variations */

	return new_bd_arm_Mvn_reg(dbgi, block, new_op);
749
750
}

Michael Beck's avatar
Michael Beck committed
751
752
753
754
/**
 * Transforms an Abs node.
 *
 * @param env   The transformation environment
755
 * @return the created ARM Abs node
Michael Beck's avatar
Michael Beck committed
756
 */
757
758
static ir_node *gen_Abs(ir_node *node)
{
759
	ir_node  *block   = be_transform_node(get_nodes_block(node));
760
	ir_node  *op      = get_Abs_op(node);
761
	ir_node  *new_op  = be_transform_node(op);
762
	dbg_info *dbgi    = get_irn_dbg_info(node);
763
	ir_mode  *mode    = get_irn_mode(node);
764

765
	if (mode_is_float(mode)) {
766
767
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
768
			return new_bd_arm_fpaAbs(dbgi, block, new_op, mode);
769
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
770
			assert(mode != mode_E && "IEEE Extended FP not supported");
771
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
772
773
		}
		else {
774
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
775
		}
776
	}
777
	assert(mode_is_data(mode));
778
	return new_bd_arm_Abs(dbgi, block, new_op);
779
780
781
782
783
}

/**
 * Transforms a Minus node.
 *
784
 * @return the created ARM Minus node
785
 */
786
787
static ir_node *gen_Minus(ir_node *node)
{
788
789
790
	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);
791
	dbg_info *dbgi    = get_irn_dbg_info(node);
792
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
793

794
	if (mode_is_float(mode)) {
795
796
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
797
			return new_bd_arm_fpaMvf(dbgi, block, op, mode);
798
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
799
			assert(mode != mode_E && "IEEE Extended FP not supported");
800
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
801
802
		}
		else {
803
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
804
		}
805
	}
806
	assert(mode_is_data(mode));
807
	return new_bd_arm_Rsb_imm(dbgi, block, new_op, 0, 0);
808
809
810
811
812
}

/**
 * Transforms a Load.
 *
813
 * @return the created ARM Load node
814
 */
815
816
static ir_node *gen_Load(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
817
818
819
820
821
822
	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);
823
	dbg_info *dbgi      = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
824
	ir_node  *new_load = NULL;
825

Michael Beck's avatar
Michael Beck committed
826
	if (mode_is_float(mode)) {
827
828
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
829
			new_load = new_bd_arm_fpaLdf(dbgi, block, new_ptr, new_mem, mode);
830
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
831
			assert(mode != mode_E && "IEEE Extended FP not supported");
832
			panic("VFP not supported yet");
833
		} else {
834
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
835
		}
836
	} else {
837
		assert(mode_is_data(mode) && "unsupported mode for Load");
838

839
		new_load = new_bd_arm_Ldr(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false);
840
	}
Michael Beck's avatar
Michael Beck committed
841
	set_irn_pinned(new_load, get_irn_pinned(node));
842
843
844
845

	/* 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 */
846
		ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Ldr_res);
847
		be_new_Keep(block, 1, &proj);
848
849
	}

Michael Beck's avatar
Michael Beck committed
850
	return new_load;
851
852
853
854
855
}

/**
 * Transforms a Store.
 *
856
 * @return the created ARM Store node
857
 */
858
859
static ir_node *gen_Store(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
860
861
862
863
864
865
866
867
	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);
868
	dbg_info *dbgi     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
869
	ir_node *new_store = NULL;
870

Michael Beck's avatar
Michael Beck committed
871
	if (mode_is_float(mode)) {
872
873
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
874
875
			new_store = new_bd_arm_fpaStf(dbgi, block, new_ptr, new_val,
			                              new_mem, mode);
876
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
877
			assert(mode != mode_E && "IEEE Extended FP not supported");
878
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
879
		} else {
880
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
881
882
		}
	} else {
883
		assert(mode_is_data(mode) && "unsupported mode for Store");
884
885
		new_store = new_bd_arm_Str(dbgi, block, new_ptr, new_val, new_mem, mode,
		                           NULL, 0, 0, false);
886
	}
Michael Beck's avatar
Michael Beck committed
887
888
	set_irn_pinned(new_store, get_irn_pinned(node));
	return new_store;
889
890
}

891
892
893
894
895
896
897
898
899
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);
}

900
901
902
903
904
905
906
907
908
909
static ir_node *gen_be_Call(ir_node *node)
{
	ir_node *res = be_duplicate_node(node);
	arch_irn_add_flags(res, arch_irn_flags_modify_flags);

	return res;
}

static ir_node *gen_SwitchJmp(ir_node *node)
{
910
911
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *selector = get_Cond_selector(node);
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
	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;
936

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

941
942
943
		pn = get_Proj_proj(proj) - translation;
		set_Proj_proj(proj, pn);
	}
944

945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
	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)) {
		/* TODO: revivie this code */
		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);
972
		}
973
974
975
976
		/* Hmm: use need cmfe */
		return new_bd_arm_fpaCmfeBra(dbgi, block, new_op1, new_op2, pnc);
#endif
	}
977

978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
	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);
993
	}
994
995
996
997
998
999
1000

	/* integer compare, TODO: use shifer_op in all its combinations */
	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,