arm_transform.c 49.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_t.h"
Michael Beck's avatar
Michael Beck committed
42
#include "../beirg_t.h"
43
#include "../beutil.h"
44
#include "../betranshlp.h"
45
46
47
#include "bearch_arm_t.h"

#include "arm_nodes_attr.h"
48
#include "archop.h"
49
#include "arm_transform.h"
50
#include "arm_optimize.h"
51
52
53
54
55
56
57
#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
58

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

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


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

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

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

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

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

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

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

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

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

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

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

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

144
145
146
147
148
/**
 * Create a DAG constructing a given Const.
 *
 * @param irn  a Firm const
 */
149
static ir_node *create_const_graph(ir_node *irn, ir_node *block) {
150
151
152
153
154
155
156
157
158
159
	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);
160
	return create_const_graph_value(get_irn_dbg_info(irn), block, value);
161
162
}

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

Michael Beck's avatar
Michael Beck committed
172
173
174
/**
 * Generate code for a sign extension.
 */
175
static ir_node *gen_sign_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
176
	int shift_width = 32 - result_bits;
177
	ir_node *shift_const_node = create_const_graph_value(dbg, block, shift_width);
178
179
	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);
180
181
182
	return rshift_node;
}

Michael Beck's avatar
Michael Beck committed
183
184
185
/**
 * Transforms a Conv node.
 *
186
 * @return The created ia32 Conv node
Michael Beck's avatar
Michael Beck committed
187
 */
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
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
205
					/* from float to float */
206
					return new_bd_arm_fpaMvf(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
207
208
209
				}
				else {
					/* from float to int */
210
					return new_bd_arm_fpaFix(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
211
212
213
214
				}
			}
			else {
				/* from int to float */
215
				return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
216
217
			}
		}
Michael Beck's avatar
Michael Beck committed
218
		else if (USE_VFP(env_cg->isa)) {
219
			panic("VFP not supported yet");
220
221
			return NULL;
		}
Michael Beck's avatar
Michael Beck committed
222
		else {
223
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
224
225
			return NULL;
		}
Michael Beck's avatar
Michael Beck committed
226
227
	}
	else { /* complete in gp registers */
228
229
		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
230
231
		int min_bits;
		ir_mode *min_mode;
232

Michael Beck's avatar
Michael Beck committed
233
234
235
		if (is_Load(skip_Proj(op))) {
			if (src_bits == dst_bits) {
				/* kill unneccessary conv */
236
				return new_op;
237
			}
Michael Beck's avatar
Michael Beck committed
238
239
			/* after a load, the bit size is already converted */
			src_bits = 32;
240
		}
Michael Beck's avatar
Michael Beck committed
241
242
243
244
245
246
247
248

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

Michael Beck's avatar
Michael Beck committed
266
267
268
269
270
271
272
273
274
275
276
/**
 * 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
277
		long v = get_arm_imm_value(n);
Michael Beck's avatar
Michael Beck committed
278
279
280
281
282
		if (v < 32)
			return (int)v;
	}
	return 0;
}
283
284

/**
285
 * Creates an ARM Add.
286
287
288
 *
 * @return the created arm Add node
 */
289
290
291
292
293
294
295
296
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
297
298
	int v;
	arm_shift_modifier mod;
299
	dbg_info *dbg = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
300

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return rotate;
}

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

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

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

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

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

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

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

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

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

858
859
		/* add a result proj and a Keep to produce a pseudo use */
		ir_node *proj = new_r_Proj(irg, block, new_load, mode_Iu, pn_arm_Load_res);
860
		be_new_Keep(arch_get_irn_reg_class_out(proj), irg, block, 1, &proj);
861
862
	}

Michael Beck's avatar
Michael Beck committed
863
	return new_load;
864
865
866
867
868
}

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