arm_transform.c 49.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
/**
 * @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>

Michael Beck's avatar
Michael Beck committed
57

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

61
extern ir_op *get_op_Mulh(void);
62
63
64
65
66
67
68
69
70
71
72
73


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

74
static inline int mode_needs_gp_reg(ir_mode *mode) {
75
	return mode_is_int(mode) || mode_is_reference(mode);
76
77
}

Michael Beck's avatar
Michael Beck committed
78
79
80
/**
 * Creates a arm_Const node.
 */
81
static ir_node *create_mov_node(dbg_info *dbg, ir_node *block, long value) {
Michael Beck's avatar
Michael Beck committed
82
	ir_mode *mode  = mode_Iu;
83
84
85
86
	ir_node *res;

	if (mode_needs_gp_reg(mode))
		mode = mode_Iu;
87
	res = new_bd_arm_Mov_i(dbg, block, mode, value);
88
	be_dep_on_frame(res);
Michael Beck's avatar
Michael Beck committed
89
	return res;
90
91
}

Michael Beck's avatar
Michael Beck committed
92
93
94
/**
 * Creates a arm_Const_Neg node.
 */
95
static ir_node *create_mvn_node(dbg_info *dbg, ir_node *block, long value) {
Michael Beck's avatar
Michael Beck committed
96
	ir_mode *mode = mode_Iu;
97
98
99
100
	ir_node *res;

	if (mode_needs_gp_reg(mode))
		mode = mode_Iu;
101
	res = new_bd_arm_Mvn_i(dbg, block, mode, value);
102
	be_dep_on_frame(res);
Michael Beck's avatar
Michael Beck committed
103
	return res;
104
105
}

106
#define NEW_BINOP_NODE(opname, env, op1, op2) new_bd_arm_##opname(env->dbg, current_ir_graph, env->block, op1, op2, env->mode)
107

Michael Beck's avatar
Michael Beck committed
108
109
110
/**
 * Creates a possible DAG for an constant.
 */
111
static ir_node *create_const_graph_value(dbg_info *dbg, ir_node *block, unsigned int value) {
112
	ir_node *result;
113
	arm_vals v, vn;
Michael Beck's avatar
Michael Beck committed
114
	int cnt;
Michael Beck's avatar
Michael Beck committed
115
	ir_mode *mode = mode_Iu;
116

117
118
	arm_gen_vals_from_word(value, &v);
	arm_gen_vals_from_word(~value, &vn);
Michael Beck's avatar
Michael Beck committed
119
120
121

	if (vn.ops < v.ops) {
		/* remove bits */
122
		result = create_mvn_node(dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
Michael Beck's avatar
Michael Beck committed
123
124

		for (cnt = 1; cnt < vn.ops; ++cnt) {
Michael Beck's avatar
Michael Beck committed
125
			long value = arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]);
126
			ir_node *bic_i_node = new_bd_arm_Bic_i(dbg, block, result, mode, value);
Michael Beck's avatar
Michael Beck committed
127
			result = bic_i_node;
128
129
		}
	}
Michael Beck's avatar
Michael Beck committed
130
131
	else {
		/* add bits */
132
		result = create_mov_node(dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
Michael Beck's avatar
Michael Beck committed
133
134

		for (cnt = 1; cnt < v.ops; ++cnt) {
Michael Beck's avatar
Michael Beck committed
135
			long value = arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]);
136
			ir_node *orr_i_node = new_bd_arm_Or_i(dbg, block, result, mode, value);
Michael Beck's avatar
Michael Beck committed
137
138
			result = orr_i_node;
		}
139
140
141
142
	}
	return result;
}

143
144
145
146
147
/**
 * Create a DAG constructing a given Const.
 *
 * @param irn  a Firm const
 */
148
static ir_node *create_const_graph(ir_node *irn, ir_node *block) {
149
150
151
152
153
154
155
156
157
158
	tarval  *tv = get_Const_tarval(irn);
	ir_mode *mode = get_tarval_mode(tv);
	int     value;

	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);
159
	return create_const_graph_value(get_irn_dbg_info(irn), block, value);
160
161
}

Michael Beck's avatar
Michael Beck committed
162
163
164
/**
 * Create an And that will mask all upper bits
 */
165
static ir_node *gen_zero_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
166
	unsigned mask_bits = (1 << result_bits) - 1;
167
	ir_node *mask_node = create_const_graph_value(dbg, block, mask_bits);
168
	return new_bd_arm_And(dbg, block, op, mask_node, mode_Iu, ARM_SHF_NONE, 0);
169
170
}

Michael Beck's avatar
Michael Beck committed
171
172
173
/**
 * Generate code for a sign extension.
 */
174
static ir_node *gen_sign_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
175
	int shift_width = 32 - result_bits;
176
	ir_node *shift_const_node = create_const_graph_value(dbg, block, shift_width);
177
178
	ir_node *lshift_node = new_bd_arm_Shl(dbg, block, op, shift_const_node, mode_Iu);
	ir_node *rshift_node = new_bd_arm_Shrs(dbg, block, lshift_node, shift_const_node, mode_Iu);
179
180
181
	return rshift_node;
}

Michael Beck's avatar
Michael Beck committed
182
183
184
/**
 * Transforms a Conv node.
 *
185
 * @return The created ia32 Conv node
Michael Beck's avatar
Michael Beck committed
186
 */
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
static ir_node *gen_Conv(ir_node *node) {
	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
204
					/* from float to float */
205
					return new_bd_arm_fpaMvf(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
206
207
208
				}
				else {
					/* from float to int */
209
					return new_bd_arm_fpaFix(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
210
211
212
213
				}
			}
			else {
				/* from int to float */
214
				return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
215
216
			}
		}
Michael Beck's avatar
Michael Beck committed
217
		else if (USE_VFP(env_cg->isa)) {
218
			panic("VFP not supported yet");
219
220
			return NULL;
		}
Michael Beck's avatar
Michael Beck committed
221
		else {
222
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
223
224
			return NULL;
		}
Michael Beck's avatar
Michael Beck committed
225
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 (is_Load(skip_Proj(op))) {
			if (src_bits == dst_bits) {
				/* kill unneccessary conv */
235
				return new_op;
236
			}
Michael Beck's avatar
Michael Beck committed
237
238
			/* after a load, the bit size is already converted */
			src_bits = 32;
239
		}
Michael Beck's avatar
Michael Beck committed
240
241
242
243
244
245
246
247

		if (src_bits == dst_bits) {
			/* kill unneccessary conv */
			return new_op;
		} else if (dst_bits <= 32 && src_bits <= 32) {
			if (src_bits < dst_bits) {
				min_bits = src_bits;
				min_mode = src_mode;
248
			} else {
Michael Beck's avatar
Michael Beck committed
249
250
				min_bits = dst_bits;
				min_mode = dst_mode;
251
			}
Michael Beck's avatar
Michael Beck committed
252
			if (mode_is_signed(min_mode)) {
253
				return gen_sign_extension(dbg, block, new_op, min_bits);
254
			} else {
255
				return gen_zero_extension(dbg, block, new_op, min_bits);
256
			}
Michael Beck's avatar
Michael Beck committed
257
		} else {
258
			panic("Cannot handle Conv %+F->%+F with %d->%d bits", src_mode, dst_mode,
Michael Beck's avatar
Michael Beck committed
259
260
				src_bits, dst_bits);
			return NULL;
261
262
263
264
		}
	}
}

Michael Beck's avatar
Michael Beck committed
265
266
267
268
269
270
271
272
273
274
275
/**
 * Return true if an operand is a shifter operand
 */
static int is_shifter_operand(ir_node *n, arm_shift_modifier *pmod) {
	arm_shift_modifier mod = ARM_SHF_NONE;

	if (is_arm_Mov(n))
		mod = get_arm_shift_modifier(n);

	*pmod = mod;
	if (mod != ARM_SHF_NONE) {
Michael Beck's avatar
Michael Beck committed
276
		long v = get_arm_imm_value(n);
Michael Beck's avatar
Michael Beck committed
277
278
279
280
281
		if (v < 32)
			return (int)v;
	}
	return 0;
}
282
283

/**
284
 * Creates an ARM Add.
285
286
287
 *
 * @return the created arm Add node
 */
288
289
290
291
292
293
294
295
static ir_node *gen_Add(ir_node *node) {
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_Add_left(node);
	ir_node  *new_op1 = be_transform_node(op1);
	ir_node  *op2     = get_Add_right(node);
	ir_node  *new_op2 = be_transform_node(op2);
	ir_mode  *mode    = get_irn_mode(node);
	ir_node  *new_op3;
Michael Beck's avatar
Michael Beck committed
296
297
	int v;
	arm_shift_modifier mod;
298
	dbg_info *dbg = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
299

300
	if (mode_is_float(mode)) {
301
		env_cg->have_fp_insn = 1;
302
303
		if (USE_FPA(env_cg->isa)) {
			if (is_arm_fpaMvf_i(new_op1))
304
				return new_bd_arm_fpaAdf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
305
			if (is_arm_fpaMvf_i(new_op2))
306
307
				return new_bd_arm_fpaAdf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
			return new_bd_arm_fpaAdf(dbg, block, new_op1, new_op2, mode);
308
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
309
			assert(mode != mode_E && "IEEE Extended FP not supported");
310
			panic("VFP not supported yet");
311
			return NULL;
Michael Beck's avatar
Michael Beck committed
312
		}
313
		else {
314
			panic("Softfloat not supported yet");
315
316
317
			return NULL;
		}
	} else {
318
		assert(mode_is_data(mode));
319
		mode = mode_Iu;
320
321

		if (is_arm_Mov_i(new_op1))
322
			return new_bd_arm_Add_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
323
		if (is_arm_Mov_i(new_op2))
324
			return new_bd_arm_Add_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
Michael Beck's avatar
Michael Beck committed
325
326

		/* check for MLA */
Michael Beck's avatar
Michael Beck committed
327
		if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
328
			new_op3 = new_op2;
Michael Beck's avatar
Michael Beck committed
329
330
			new_op2 = get_irn_n(new_op1, 1);
			new_op1 = get_irn_n(new_op1, 0);
Michael Beck's avatar
Michael Beck committed
331

332
			return new_bd_arm_Mla(dbg, block, new_op1, new_op2, new_op3, mode);
Michael Beck's avatar
Michael Beck committed
333
		}
Michael Beck's avatar
Michael Beck committed
334
		if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
335
336
337
			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
338

339
			return new_bd_arm_Mla(dbg, block, new_op1, new_op2, new_op3, mode);
Michael Beck's avatar
Michael Beck committed
340
		}
341

342
#if 0
Michael Beck's avatar
Michael Beck committed
343
		/* is the first a shifter */
344
		v = is_shifter_operand(new_op1, &mod);
Michael Beck's avatar
Michael Beck committed
345
		if (v) {
346
			new_op1 = get_irn_n(new_op1, 0);
347
			return new_bd_arm_Add(dbg, block, new_op2, new_op1, mode, mod, v);
Michael Beck's avatar
Michael Beck committed
348
349
		}
		/* is the second a shifter */
350
		v = is_shifter_operand(new_op2, &mod);
Michael Beck's avatar
Michael Beck committed
351
		if (v) {
352
			new_op2 = get_irn_n(new_op2, 0);
353
			return new_bd_arm_Add(dbg, block, new_op1, new_op2, mode, mod, v);
Michael Beck's avatar
Michael Beck committed
354
		}
355
#endif
356

Michael Beck's avatar
Michael Beck committed
357
		/* normal ADD */
358
		return new_bd_arm_Add(dbg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
Michael Beck's avatar
Michael Beck committed
359
360
	}
}
361
362

/**
363
 * Creates an ARM Mul.
364
365
366
 *
 * @return the created arm Mul node
 */
367
368
369
370
371
372
373
374
static ir_node *gen_Mul(ir_node *node) {
	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
375

376
	if (mode_is_float(mode)) {
377
		env_cg->have_fp_insn = 1;
378
379
		if (USE_FPA(env_cg->isa)) {
			if (is_arm_Mov_i(new_op1))
380
				return new_bd_arm_fpaMuf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
381
			if (is_arm_Mov_i(new_op2))
382
383
				return new_bd_arm_fpaMuf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
			return new_bd_arm_fpaMuf(dbg, block, new_op1, new_op2, mode);
384
		}
385
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
386
			assert(mode != mode_E && "IEEE Extended FP not supported");
387
			panic("VFP not supported yet");
388
			return NULL;
389
390
		}
		else {
391
			panic("Softfloat not supported yet");
392
			return NULL;
Michael Beck's avatar
Michael Beck committed
393
		}
394
	}
395
	assert(mode_is_data(mode));
396
	mode = mode_Iu;
397
	return new_bd_arm_Mul(dbg, block, new_op1, new_op2, mode);
398
399
400
}

/**
401
 * Creates an ARM floating point Div.
402
 *
Michael Beck's avatar
Michael Beck committed
403
 * @param env   The transformation environment
404
405
 * @return the created arm fDiv node
 */
406
407
408
409
410
411
412
413
static ir_node *gen_Quot(ir_node *node) {
	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
414

415
	assert(mode != mode_E && "IEEE Extended FP not supported");
416

417
	env_cg->have_fp_insn = 1;
418
419
	if (USE_FPA(env_cg->isa)) {
		if (is_arm_Mov_i(new_op1))
420
			return new_bd_arm_fpaRdf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
421
		if (is_arm_Mov_i(new_op2))
422
423
			return new_bd_arm_fpaDvf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
		return new_bd_arm_fpaDvf(dbg, block, new_op1, new_op2, mode);
424
	} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
425
		assert(mode != mode_E && "IEEE Extended FP not supported");
426
		panic("VFP not supported yet");
427
428
	}
	else {
429
		panic("Softfloat not supported yet");
430
		return NULL;
Michael Beck's avatar
Michael Beck committed
431
	}
Michael Beck's avatar
Michael Beck committed
432
433
434
}

#define GEN_INT_OP(op) \
435
436
437
438
439
	ir_node  *block   = be_transform_node(get_nodes_block(node)); \
	ir_node  *op1     = get_ ## op ## _left(node); \
	ir_node  *new_op1 = be_transform_node(op1); \
	ir_node  *op2     = get_ ## op ## _right(node); \
	ir_node  *new_op2 = be_transform_node(op2); \
440
	ir_mode  *mode    = mode_Iu; \
441
442
	dbg_info *dbg     = get_irn_dbg_info(node); \
	int      v; \
Michael Beck's avatar
Michael Beck committed
443
444
	arm_shift_modifier mod; \
 \
445
	if (is_arm_Mov_i(new_op1)) \
446
		return new_bd_arm_ ## op ## _i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1)); \
447
	if (is_arm_Mov_i(new_op2)) \
448
		return new_bd_arm_ ## op ## _i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2)); \
Michael Beck's avatar
Michael Beck committed
449
	/* is the first a shifter */ \
450
	v = is_shifter_operand(new_op1, &mod); \
Michael Beck's avatar
Michael Beck committed
451
	if (v) { \
452
		new_op1 = get_irn_n(new_op1, 0); \
453
		return new_bd_arm_ ## op(dbg, block, new_op2, new_op1, mode, mod, v); \
Michael Beck's avatar
Michael Beck committed
454
455
	} \
	/* is the second a shifter */ \
456
	v = is_shifter_operand(new_op2, &mod); \
Michael Beck's avatar
Michael Beck committed
457
	if (v) { \
458
		new_op2 = get_irn_n(new_op2, 0); \
459
		return new_bd_arm_ ## op(dbg, block, new_op1, new_op2, mode, mod, v); \
Michael Beck's avatar
Michael Beck committed
460
461
	} \
	/* Normal op */ \
462
	return new_bd_arm_ ## op(dbg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0) \
463
464

/**
465
 * Creates an ARM And.
466
467
468
 *
 * @return the created arm And node
 */
469
470
471
static ir_node *gen_And(ir_node *node) {
	GEN_INT_OP(And);
}
472
473

/**
474
 * Creates an ARM Orr.
475
 *
Michael Beck's avatar
Michael Beck committed
476
 * @param env   The transformation environment
477
478
 * @return the created arm Or node
 */
479
480
481
static ir_node *gen_Or(ir_node *node) {
	GEN_INT_OP(Or);
}
482
483

/**
484
 * Creates an ARM Eor.
485
486
487
 *
 * @return the created arm Eor node
 */
488
489
490
static ir_node *gen_Eor(ir_node *node) {
	GEN_INT_OP(Eor);
}
491
492

/**
493
 * Creates an ARM Sub.
494
495
496
 *
 * @return the created arm Sub node
 */
497
498
499
500
501
static ir_node *gen_Sub(ir_node *node) {
	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
502
	ir_node  *new_op2 = be_transform_node(op2);
503
504
505
	ir_mode  *mode    = get_irn_mode(node);
	dbg_info *dbg     = get_irn_dbg_info(node);
	int      v;
Michael Beck's avatar
Michael Beck committed
506
507
	arm_shift_modifier mod;

508
	if (mode_is_float(mode)) {
509
		env_cg->have_fp_insn = 1;
510
511
		if (USE_FPA(env_cg->isa)) {
			if (is_arm_Mov_i(new_op1))
512
				return new_bd_arm_fpaRsf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
513
			if (is_arm_Mov_i(new_op2))
514
515
				return new_bd_arm_fpaSuf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
			return new_bd_arm_fpaSuf(dbg, block, new_op1, new_op2, mode);
516
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
517
			assert(mode != mode_E && "IEEE Extended FP not supported");
518
			panic("VFP not supported yet");
519
520
521
			return NULL;
		}
		else {
522
			panic("Softfloat not supported yet");
523
			return NULL;
Michael Beck's avatar
Michael Beck committed
524
		}
Michael Beck's avatar
Michael Beck committed
525
	}
526
	else {
527
		assert(mode_is_data(mode) && "unknown mode for Sub");
528
		mode = mode_Iu;
529
530

		if (is_arm_Mov_i(new_op1))
531
			return new_bd_arm_Rsb_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
532
		if (is_arm_Mov_i(new_op2))
533
			return new_bd_arm_Sub_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
Michael Beck's avatar
Michael Beck committed
534
535

		/* is the first a shifter */
536
		v = is_shifter_operand(new_op1, &mod);
Michael Beck's avatar
Michael Beck committed
537
		if (v) {
538
			new_op1 = get_irn_n(new_op1, 0);
539
			return new_bd_arm_Rsb(dbg, block, new_op2, new_op1, mode, mod, v);
540
		}
Michael Beck's avatar
Michael Beck committed
541
		/* is the second a shifter */
542
		v = is_shifter_operand(new_op2, &mod);
Michael Beck's avatar
Michael Beck committed
543
		if (v) {
544
			new_op2 = get_irn_n(new_op2, 0);
545
			return new_bd_arm_Sub(dbg, block, new_op1, new_op2, mode, mod, v);
Michael Beck's avatar
Michael Beck committed
546
547
		}
		/* normal sub */
548
		return new_bd_arm_Sub(dbg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
549
550
551
552
	}
}

/**
553
 * Creates an ARM Shl.
554
 *
555
 * @return the created ARM Shl node
556
 */
557
558
559
560
561
562
static ir_node *gen_Shl(ir_node *node) {
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_Shl_left(node);
	ir_node  *new_op1 = be_transform_node(op1);
	ir_node  *op2     = get_Shl_right(node);
	ir_node  *new_op2 = be_transform_node(op2);
563
	ir_mode  *mode    = mode_Iu;
564
565
566
	dbg_info *dbg     = get_irn_dbg_info(node);

	if (is_arm_Mov_i(new_op2)) {
567
		return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_LSL, get_arm_imm_value(new_op2));
568
	}
569
	return new_bd_arm_Shl(dbg, block, new_op1, new_op2, mode);
570
571
572
}

/**
573
 * Creates an ARM Shr.
574
 *
575
 * @return the created ARM Shr node
576
 */
577
578
579
580
581
582
static ir_node *gen_Shr(ir_node *node) {
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_Shr_left(node);
	ir_node  *new_op1 = be_transform_node(op1);
	ir_node  *op2     = get_Shr_right(node);
	ir_node  *new_op2 = be_transform_node(op2);
583
	ir_mode  *mode    = mode_Iu;
584
585
586
	dbg_info *dbg     = get_irn_dbg_info(node);

	if (is_arm_Mov_i(new_op2)) {
587
		return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_LSR, get_arm_imm_value(new_op2));
588
	}
589
	return new_bd_arm_Shr(dbg, block, new_op1, new_op2, mode);
590
591
592
}

/**
593
 * Creates an ARM Shrs.
594
 *
595
 * @return the created ARM Shrs node
596
 */
597
598
599
600
601
602
static ir_node *gen_Shrs(ir_node *node) {
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_Shrs_left(node);
	ir_node  *new_op1 = be_transform_node(op1);
	ir_node  *op2     = get_Shrs_right(node);
	ir_node  *new_op2 = be_transform_node(op2);
603
	ir_mode  *mode    = mode_Iu;
604
605
606
	dbg_info *dbg     = get_irn_dbg_info(node);

	if (is_arm_Mov_i(new_op2)) {
607
		return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_ASR, get_arm_imm_value(new_op2));
608
	}
609
	return new_bd_arm_Shrs(dbg, block, new_op1, new_op2, mode);
610
611
}

Michael Beck's avatar
Michael Beck committed
612
613
614
615
616
617
618
619
620
621
622
623
624
/**
 * Creates an ARM Ror.
 *
 * @return the created ARM Ror node
 */
static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2) {
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
	ir_node  *new_op2 = be_transform_node(op2);
	ir_mode  *mode    = mode_Iu;
	dbg_info *dbg     = get_irn_dbg_info(node);

	if (is_arm_Mov_i(new_op2)) {
625
		return new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_ROR, get_arm_imm_value(new_op2));
Michael Beck's avatar
Michael Beck committed
626
	}
627
	return new_bd_arm_Ror(dbg, block, new_op1, new_op2, mode);
Michael Beck's avatar
Michael Beck committed
628
629
630
631
632
633
634
635
636
637
638
639
640
641
}

/**
 * Creates an ARM Rol.
 *
 * @return the created ARM Rol node
 *
 * Note: there is no Rol on arm, we have to use Ror
 */
static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2) {
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
	ir_mode  *mode    = mode_Iu;
	dbg_info *dbg     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
642
643
	ir_node  *new_op2 = be_transform_node(op2);

644
645
	new_op2 = new_bd_arm_Rsb_i(dbg, block, new_op2, mode, 32);
	return new_bd_arm_Ror(dbg, block, new_op1, new_op2, mode);
Michael Beck's avatar
Michael Beck committed
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
}

/**
 * Creates an ARM ROR from a Firm Rotl.
 *
 * @return the created ARM Ror node
 */
static ir_node *gen_Rotl(ir_node *node) {
	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
663
		ir_node *right = get_Add_right(op2);
Michael Beck's avatar
Michael Beck committed
664
665
666
667
		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
668
			ir_node *left = get_Add_left(op2);
Michael Beck's avatar
Michael Beck committed
669
670

			if (is_Minus(left) &&
Michael Beck's avatar
Michael Beck committed
671
			    tarval_is_long(tv)          &&
Michael Beck's avatar
Michael Beck committed
672
673
674
675
			    get_tarval_long(tv) == bits &&
			    bits                == 32)
				rotate = gen_Ror(node, op1, get_Minus_op(left));
		}
Michael Beck's avatar
Michael Beck committed
676
677
678
679
680
681
682
683
684
685
686
687
688
	} 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);
		}
689
690
691
692
	} else if (is_Const(op2)) {
			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
693

694
695
696
697
698
699
700
			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);
				ir_mode  *mode    = mode_Iu;
				dbg_info *dbg     = get_irn_dbg_info(node);

				bits = (bits - get_tarval_long(tv)) & 31;
701
				rotate = new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_ROR, bits);
702
			}
Michael Beck's avatar
Michael Beck committed
703
704
705
706
707
708
709
710
711
	}

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

	return rotate;
}

712
713
714
/**
 * Transforms a Not node.
 *
715
 * @return the created ARM Not node
716
 */
717
718
719
720
721
static ir_node *gen_Not(ir_node *node) {
	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);
	dbg_info *dbg     = get_irn_dbg_info(node);
722
	ir_mode  *mode    = mode_Iu;
Michael Beck's avatar
Michael Beck committed
723
	arm_shift_modifier mod = ARM_SHF_NONE;
724
	int      v        = is_shifter_operand(new_op, &mod);
Michael Beck's avatar
Michael Beck committed
725
726

	if (v) {
727
		new_op = get_irn_n(new_op, 0);
Michael Beck's avatar
Michael Beck committed
728
	}
729
	return new_bd_arm_Mvn(dbg, block, new_op, mode, mod, v);
730
731
}

Michael Beck's avatar
Michael Beck committed
732
733
734
735
/**
 * Transforms an Abs node.
 *
 * @param env   The transformation environment
736
 * @return the created ARM Abs node
Michael Beck's avatar
Michael Beck committed
737
 */
738
739
static ir_node *gen_Abs(ir_node *node) {
	ir_node  *block   = be_transform_node(get_nodes_block(node));
740
	ir_node  *op      = get_Abs_op(node);
741
742
743
	ir_node  *new_op  = be_transform_node(op);
	dbg_info *dbg     = get_irn_dbg_info(node);
	ir_mode  *mode    = get_irn_mode(node);
744

745
	if (mode_is_float(mode)) {
746
747
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
748
			return new_bd_arm_fpaAbs(dbg, block, new_op, mode);
749
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
750
			assert(mode != mode_E && "IEEE Extended FP not supported");
751
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
752
753
		}
		else {
754
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
755
		}
756
	}
757
	assert(mode_is_data(mode));
758
	mode = mode_Iu;
759
	return new_bd_arm_Abs(dbg, block, new_op, mode);
760
761
762
763
764
}

/**
 * Transforms a Minus node.
 *
765
 * @return the created ARM Minus node
766
 */
767
768
769
770
771
772
static ir_node *gen_Minus(ir_node *node) {
	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);
	dbg_info *dbg     = get_irn_dbg_info(node);
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
773

774
	if (mode_is_float(mode)) {
775
776
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
777
			return new_bd_arm_fpaMvf(dbg, block, op, mode);
778
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
779
			assert(mode != mode_E && "IEEE Extended FP not supported");
780
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
781
782
		}
		else {
783
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
784
		}
785
	}
786
	assert(mode_is_data(mode));
787
	mode = mode_Iu;
788
	return new_bd_arm_Rsb_i(dbg, block, new_op, mode, 0);
789
790
791
792
793
}

/**
 * Transforms a Load.
 *
794
 * @return the created ARM Load node
795
 */
796
static ir_node *gen_Load(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
797
798
799
800
801
802
803
804
	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);
	dbg_info *dbg      = get_irn_dbg_info(node);
	ir_node  *new_load = NULL;
805

Michael Beck's avatar
Michael Beck committed
806
	if (mode_is_float(mode)) {
807
808
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
809
			new_load = new_bd_arm_fpaLdf(dbg, block, new_ptr, new_mem, mode);
810
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
811
			assert(mode != mode_E && "IEEE Extended FP not supported");
812
			panic("VFP not supported yet");
813
814
		}
		else {
815
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
816
		}
817
	}
818
	else {
819
		assert(mode_is_data(mode) && "unsupported mode for Load");
820
821
822
823
824

		if (mode_is_signed(mode)) {
			/* sign extended loads */
			switch (get_mode_size_bits(mode)) {
			case 8:
825
826
				new_load = new_bd_arm_Ldrbs(dbg, block, new_ptr, new_mem, NULL,
				                            0, 0);
Michael Beck's avatar
Michael Beck committed
827
				break;
828
			case 16:
829
830
				new_load = new_bd_arm_Ldrhs(dbg, block, new_ptr, new_mem, NULL,
				                            0, 0);
Michael Beck's avatar
Michael Beck committed
831
				break;
832
			case 32:
833
834
				new_load = new_bd_arm_Ldr(dbg, block, new_ptr, new_mem, NULL,
				                          0, 0);
835
836
				break;
			default:
837
				panic("mode size not supported");
838
839
840
841
842
			}
		} else {
			/* zero extended loads */
			switch (get_mode_size_bits(mode)) {
			case 8:
843
844
				new_load = new_bd_arm_Ldrb(dbg, block, new_ptr, new_mem, NULL,
				                           0, 0);
Michael Beck's avatar
Michael Beck committed
845
				break;
846
			case 16:
847
848
				new_load = new_bd_arm_Ldrh(dbg, block, new_ptr, new_mem, NULL,
				                           0, 0);
Michael Beck's avatar
Michael Beck committed
849
				break;
850
			case 32:
851
852
				new_load = new_bd_arm_Ldr(dbg, block, new_ptr, new_mem, NULL,
				                          0, 0);
853
854
				break;
			default:
855
				panic("mode size not supported");
856
857
			}
		}
858
	}
Michael Beck's avatar
Michael Beck committed
859
	set_irn_pinned(new_load, get_irn_pinned(node));
860
861
862
863

	/* 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 */
864
		ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Ldr_res);
865
		be_new_Keep(block, 1, &proj);
866
867
	}

Michael Beck's avatar
Michael Beck committed
868
	return new_load;
869
870
871
872
873
}

/**
 * Transforms a Store.
 *
874
 * @return the created ARM Store node
875
 */
876
877
static ir_node *gen_Store(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
878
879
880
881
882
883
884
885
886
887
	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);
	dbg_info *dbg      = get_irn_dbg_info(node);
	ir_node *new_store = NULL;
888