arm_transform.c 48.5 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_t.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

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

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

/**
361
 * Creates an ARM Mul.
362
363
364
 *
 * @return the created arm Mul node
 */
365
366
367
368
369
370
371
372
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
373

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

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

413
	assert(mode != mode_E && "IEEE Extended FP not supported");
414

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

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

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

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

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

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

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

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

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

/**
551
 * Creates an ARM Shl.
552
 *
553
 * @return the created ARM Shl node
554
 */
555
556
557
558
559
560
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);
561
	ir_mode  *mode    = mode_Iu;
562
563
564
	dbg_info *dbg     = get_irn_dbg_info(node);

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

/**
571
 * Creates an ARM Shr.
572
 *
573
 * @return the created ARM Shr node
574
 */
575
576
577
578
579
580
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);
581
	ir_mode  *mode    = mode_Iu;
582
583
584
	dbg_info *dbg     = get_irn_dbg_info(node);

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

/**
591
 * Creates an ARM Shrs.
592
 *
593
 * @return the created ARM Shrs node
594
 */
595
596
597
598
599
600
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);
601
	ir_mode  *mode    = mode_Iu;
602
603
604
	dbg_info *dbg     = get_irn_dbg_info(node);

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

Michael Beck's avatar
Michael Beck committed
610
611
612
613
614
615
616
617
618
619
620
621
622
/**
 * 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)) {
623
		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
624
	}
625
	return new_bd_arm_Ror(dbg, block, new_op1, new_op2, mode);
Michael Beck's avatar
Michael Beck committed
626
627
628
629
630
631
632
633
634
635
636
637
638
639
}

/**
 * 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
640
641
	ir_node  *new_op2 = be_transform_node(op2);

642
643
	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
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
}

/**
 * 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
661
		ir_node *right = get_Add_right(op2);
Michael Beck's avatar
Michael Beck committed
662
663
664
665
		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
666
			ir_node *left = get_Add_left(op2);
Michael Beck's avatar
Michael Beck committed
667
668

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

692
693
694
695
696
697
698
			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;
699
				rotate = new_bd_arm_Mov(dbg, block, new_op1, mode, ARM_SHF_ROR, bits);
700
			}
Michael Beck's avatar
Michael Beck committed
701
702
703
704
705
706
707
708
709
	}

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

	return rotate;
}

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

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

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

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

/**
 * Transforms a Minus node.
 *
763
 * @return the created ARM Minus node
764
 */
765
766
767
768
769
770
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
771

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

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

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

		if (mode_is_signed(mode)) {
			/* sign extended loads */
			switch (get_mode_size_bits(mode)) {
			case 8:
823
				new_load = new_bd_arm_Loadbs(dbg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
824
				break;
825
			case 16:
826
				new_load = new_bd_arm_Loadhs(dbg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
827
				break;
828
			case 32:
829
				new_load = new_bd_arm_Load(dbg, block, new_ptr, new_mem);
830
831
				break;
			default:
832
				panic("mode size not supported");
833
834
835
836
837
			}
		} else {
			/* zero extended loads */
			switch (get_mode_size_bits(mode)) {
			case 8:
838
				new_load = new_bd_arm_Loadb(dbg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
839
				break;
840
			case 16:
841
				new_load = new_bd_arm_Loadh(dbg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
842
				break;
843
			case 32:
844
				new_load = new_bd_arm_Load(dbg, block, new_ptr, new_mem);
845
846
				break;
			default:
847
				panic("mode size not supported");
848
849
			}
		}
850
	}
Michael Beck's avatar
Michael Beck committed
851
	set_irn_pinned(new_load, get_irn_pinned(node));
852
853
854
855

	/* 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 */
856
857
		ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Load_res);
		be_new_Keep(arch_get_irn_reg_class_out(proj), block, 1, &proj);
858
859
	}

Michael Beck's avatar
Michael Beck committed
860
	return new_load;
861
862
863
864
865
}

/**
 * Transforms a Store.
 *
866
 * @return the created ARM Store node
867
 */
868
static ir_node *gen_Store(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
869
870
871
872
873
874
875
876
877
878
	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;
879

Michael Beck's avatar
Michael Beck committed
880
	if (mode_is_float(mode)) {
881
882
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
883
			new_store = new_bd_arm_fpaStf(dbg, block, new_ptr, new_val, new_mem, mode);
Michael Beck's avatar