arm_transform.c 50.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
35
36
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#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
37
#include "irprintf.h"
38
39
40
#include "dbginfo.h"
#include "iropt_t.h"
#include "debug.h"
Michael Beck's avatar
Michael Beck committed
41
#include "error.h"
42
43

#include "../benode_t.h"
Michael Beck's avatar
Michael Beck committed
44
#include "../beirg_t.h"
45
#include "../beutil.h"
46
#include "../betranshlp.h"
47
48
49
#include "bearch_arm_t.h"

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

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

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


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

77
static INLINE int mode_needs_gp_reg(ir_mode *mode) {
78
	return mode_is_int(mode) || mode_is_reference(mode);
79
80
}

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

	if (mode_needs_gp_reg(mode))
		mode = mode_Iu;
Michael Beck's avatar
Michael Beck committed
91
	res = new_rd_arm_Mov_i(dbg, irg, block, mode, value);
92
	be_dep_on_frame(res);
Michael Beck's avatar
Michael Beck committed
93
	return res;
94
95
}

Michael Beck's avatar
Michael Beck committed
96
97
98
/**
 * Creates a arm_Const_Neg node.
 */
99
static ir_node *create_mvn_node(dbg_info *dbg, ir_node *block, long value) {
Michael Beck's avatar
Michael Beck committed
100
	ir_mode *mode = mode_Iu;
Michael Beck's avatar
Michael Beck committed
101
	ir_graph *irg = current_ir_graph;
102
103
104
105
	ir_node *res;

	if (mode_needs_gp_reg(mode))
		mode = mode_Iu;
Michael Beck's avatar
Michael Beck committed
106
	res = new_rd_arm_Mvn_i(dbg, irg, block, mode, value);
107
	be_dep_on_frame(res);
Michael Beck's avatar
Michael Beck committed
108
	return res;
109
110
}

111
#define NEW_BINOP_NODE(opname, env, op1, op2) new_rd_arm_##opname(env->dbg, current_ir_graph, env->block, op1, op2, env->mode)
112

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

122
123
	arm_gen_vals_from_word(value, &v);
	arm_gen_vals_from_word(~value, &vn);
Michael Beck's avatar
Michael Beck committed
124
125
126

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

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

		for (cnt = 1; cnt < v.ops; ++cnt) {
Michael Beck's avatar
Michael Beck committed
140
141
			long value = arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]);
			ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, value);
Michael Beck's avatar
Michael Beck committed
142
143
			result = orr_i_node;
		}
144
145
146
147
	}
	return result;
}

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

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

Michael Beck's avatar
Michael Beck committed
176
177
178
/**
 * Generate code for a sign extension.
 */
179
static ir_node *gen_sign_extension(dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) {
Michael Beck's avatar
Michael Beck committed
180
	ir_graph *irg   = current_ir_graph;
181
	int shift_width = 32 - result_bits;
182
	ir_node *shift_const_node = create_const_graph_value(dbg, block, shift_width);
Michael Beck's avatar
Michael Beck committed
183
184
	ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, mode_Iu);
	ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, mode_Iu);
185
186
187
	return rshift_node;
}

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

Michael Beck's avatar
Michael Beck committed
239
240
241
		if (is_Load(skip_Proj(op))) {
			if (src_bits == dst_bits) {
				/* kill unneccessary conv */
242
				return new_op;
243
			}
Michael Beck's avatar
Michael Beck committed
244
245
			/* after a load, the bit size is already converted */
			src_bits = 32;
246
		}
Michael Beck's avatar
Michael Beck committed
247
248
249
250
251
252
253
254

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

Michael Beck's avatar
Michael Beck committed
272
273
274
275
276
277
278
279
280
281
282
/**
 * 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
283
		long v = get_arm_imm_value(n);
Michael Beck's avatar
Michael Beck committed
284
285
286
287
288
		if (v < 32)
			return (int)v;
	}
	return 0;
}
289
290

/**
291
 * Creates an ARM Add.
292
293
294
 *
 * @return the created arm Add node
 */
295
296
297
298
299
300
301
302
303
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_graph *irg     = current_ir_graph;
	ir_node  *new_op3;
Michael Beck's avatar
Michael Beck committed
304
305
	int v;
	arm_shift_modifier mod;
306
	dbg_info *dbg = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
307

308
	if (mode_is_float(mode)) {
309
		env_cg->have_fp_insn = 1;
310
311
		if (USE_FPA(env_cg->isa)) {
			if (is_arm_fpaMvf_i(new_op1))
Michael Beck's avatar
Michael Beck committed
312
				return new_rd_arm_fpaAdf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
313
			if (is_arm_fpaMvf_i(new_op2))
Michael Beck's avatar
Michael Beck committed
314
				return new_rd_arm_fpaAdf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
315
316
			return new_rd_arm_fpaAdf(dbg, irg, block, new_op1, new_op2, mode);
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
317
			assert(mode != mode_E && "IEEE Extended FP not supported");
318
			panic("VFP not supported yet");
319
			return NULL;
Michael Beck's avatar
Michael Beck committed
320
		}
321
		else {
322
			panic("Softfloat not supported yet");
323
324
325
			return NULL;
		}
	} else {
326
		assert(mode_is_data(mode));
327
		mode = mode_Iu;
328
329

		if (is_arm_Mov_i(new_op1))
Michael Beck's avatar
Michael Beck committed
330
			return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
331
		if (is_arm_Mov_i(new_op2))
Michael Beck's avatar
Michael Beck committed
332
			return new_rd_arm_Add_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
Michael Beck's avatar
Michael Beck committed
333
334

		/* check for MLA */
Michael Beck's avatar
Michael Beck committed
335
		if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
336
			new_op3 = new_op2;
Michael Beck's avatar
Michael Beck committed
337
338
			new_op2 = get_irn_n(new_op1, 1);
			new_op1 = get_irn_n(new_op1, 0);
Michael Beck's avatar
Michael Beck committed
339

340
			return new_rd_arm_Mla(dbg, irg, block, new_op1, new_op2, new_op3, mode);
Michael Beck's avatar
Michael Beck committed
341
		}
Michael Beck's avatar
Michael Beck committed
342
		if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
343
344
345
			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
346

347
			return new_rd_arm_Mla(dbg, irg, block, new_op1, new_op2, new_op3, mode);
Michael Beck's avatar
Michael Beck committed
348
		}
349

Michael Beck's avatar
Michael Beck committed
350
		/* is the first a shifter */
351
		v = is_shifter_operand(new_op1, &mod);
Michael Beck's avatar
Michael Beck committed
352
		if (v) {
353
			new_op1 = get_irn_n(new_op1, 0);
Michael Beck's avatar
Michael Beck committed
354
			return new_rd_arm_Add(dbg, irg, block, new_op2, new_op1, mode, mod, v);
Michael Beck's avatar
Michael Beck committed
355
356
		}
		/* is the second a shifter */
357
		v = is_shifter_operand(new_op2, &mod);
Michael Beck's avatar
Michael Beck committed
358
		if (v) {
359
			new_op2 = get_irn_n(new_op2, 0);
Michael Beck's avatar
Michael Beck committed
360
			return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, mod, v);
Michael Beck's avatar
Michael Beck committed
361
		}
362

Michael Beck's avatar
Michael Beck committed
363
		/* normal ADD */
Michael Beck's avatar
Michael Beck committed
364
		return new_rd_arm_Add(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
Michael Beck's avatar
Michael Beck committed
365
366
	}
}
367
368

/**
369
 * Creates an ARM Mul.
370
371
372
 *
 * @return the created arm Mul node
 */
373
374
375
376
377
378
379
380
381
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);
	ir_graph *irg     = current_ir_graph;
	dbg_info *dbg     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
382

383
	if (mode_is_float(mode)) {
384
		env_cg->have_fp_insn = 1;
385
386
		if (USE_FPA(env_cg->isa)) {
			if (is_arm_Mov_i(new_op1))
Michael Beck's avatar
Michael Beck committed
387
				return new_rd_arm_fpaMuf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
388
			if (is_arm_Mov_i(new_op2))
Michael Beck's avatar
Michael Beck committed
389
				return new_rd_arm_fpaMuf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
390
391
			return new_rd_arm_fpaMuf(dbg, irg, block, new_op1, new_op2, mode);
		}
392
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
393
			assert(mode != mode_E && "IEEE Extended FP not supported");
394
			panic("VFP not supported yet");
395
			return NULL;
396
397
		}
		else {
398
			panic("Softfloat not supported yet");
399
			return NULL;
Michael Beck's avatar
Michael Beck committed
400
		}
401
	}
402
	assert(mode_is_data(mode));
403
	mode = mode_Iu;
404
	return new_rd_arm_Mul(dbg, irg, block, new_op1, new_op2, mode);
405
406
407
}

/**
408
 * Creates an ARM floating point Div.
409
 *
Michael Beck's avatar
Michael Beck committed
410
 * @param env   The transformation environment
411
412
 * @return the created arm fDiv node
 */
413
414
415
416
417
418
419
420
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
421

422
	assert(mode != mode_E && "IEEE Extended FP not supported");
423

424
	env_cg->have_fp_insn = 1;
425
426
	if (USE_FPA(env_cg->isa)) {
		if (is_arm_Mov_i(new_op1))
Michael Beck's avatar
Michael Beck committed
427
			return new_rd_arm_fpaRdf_i(dbg, current_ir_graph, block, new_op2, mode, get_arm_imm_value(new_op1));
428
		if (is_arm_Mov_i(new_op2))
Michael Beck's avatar
Michael Beck committed
429
			return new_rd_arm_fpaDvf_i(dbg, current_ir_graph, block, new_op1, mode, get_arm_imm_value(new_op2));
430
431
		return new_rd_arm_fpaDvf(dbg, current_ir_graph, block, new_op1, new_op2, mode);
	} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
432
		assert(mode != mode_E && "IEEE Extended FP not supported");
433
		panic("VFP not supported yet");
434
435
	}
	else {
436
		panic("Softfloat not supported yet");
437
		return NULL;
Michael Beck's avatar
Michael Beck committed
438
	}
Michael Beck's avatar
Michael Beck committed
439
440
441
}

#define GEN_INT_OP(op) \
442
443
444
445
446
447
	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); \
	ir_graph *irg     = current_ir_graph; \
448
	ir_mode  *mode    = mode_Iu; \
449
450
	dbg_info *dbg     = get_irn_dbg_info(node); \
	int      v; \
Michael Beck's avatar
Michael Beck committed
451
452
	arm_shift_modifier mod; \
 \
453
	if (is_arm_Mov_i(new_op1)) \
Michael Beck's avatar
Michael Beck committed
454
		return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1)); \
455
	if (is_arm_Mov_i(new_op2)) \
Michael Beck's avatar
Michael Beck committed
456
		return new_rd_arm_ ## op ## _i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2)); \
Michael Beck's avatar
Michael Beck committed
457
	/* is the first a shifter */ \
458
	v = is_shifter_operand(new_op1, &mod); \
Michael Beck's avatar
Michael Beck committed
459
	if (v) { \
460
		new_op1 = get_irn_n(new_op1, 0); \
Michael Beck's avatar
Michael Beck committed
461
		return new_rd_arm_ ## op(dbg, irg, block, new_op2, new_op1, mode, mod, v); \
Michael Beck's avatar
Michael Beck committed
462
463
	} \
	/* is the second a shifter */ \
464
	v = is_shifter_operand(new_op2, &mod); \
Michael Beck's avatar
Michael Beck committed
465
	if (v) { \
466
		new_op2 = get_irn_n(new_op2, 0); \
Michael Beck's avatar
Michael Beck committed
467
		return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, mod, v); \
Michael Beck's avatar
Michael Beck committed
468
469
	} \
	/* Normal op */ \
Michael Beck's avatar
Michael Beck committed
470
	return new_rd_arm_ ## op(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0) \
471
472

/**
473
 * Creates an ARM And.
474
475
476
 *
 * @return the created arm And node
 */
477
478
479
static ir_node *gen_And(ir_node *node) {
	GEN_INT_OP(And);
}
480
481

/**
482
 * Creates an ARM Orr.
483
 *
Michael Beck's avatar
Michael Beck committed
484
 * @param env   The transformation environment
485
486
 * @return the created arm Or node
 */
487
488
489
static ir_node *gen_Or(ir_node *node) {
	GEN_INT_OP(Or);
}
490
491

/**
492
 * Creates an ARM Eor.
493
494
495
 *
 * @return the created arm Eor node
 */
496
497
498
static ir_node *gen_Eor(ir_node *node) {
	GEN_INT_OP(Eor);
}
499
500

/**
501
 * Creates an ARM Sub.
502
503
504
 *
 * @return the created arm Sub node
 */
505
506
507
508
509
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
510
	ir_node  *new_op2 = be_transform_node(op2);
511
512
513
514
	ir_mode  *mode    = get_irn_mode(node);
	ir_graph *irg     = current_ir_graph;
	dbg_info *dbg     = get_irn_dbg_info(node);
	int      v;
Michael Beck's avatar
Michael Beck committed
515
516
	arm_shift_modifier mod;

517
	if (mode_is_float(mode)) {
518
		env_cg->have_fp_insn = 1;
519
520
		if (USE_FPA(env_cg->isa)) {
			if (is_arm_Mov_i(new_op1))
Michael Beck's avatar
Michael Beck committed
521
				return new_rd_arm_fpaRsf_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
522
			if (is_arm_Mov_i(new_op2))
Michael Beck's avatar
Michael Beck committed
523
				return new_rd_arm_fpaSuf_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
524
525
			return new_rd_arm_fpaSuf(dbg, irg, block, new_op1, new_op2, mode);
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
526
			assert(mode != mode_E && "IEEE Extended FP not supported");
527
			panic("VFP not supported yet");
528
529
530
			return NULL;
		}
		else {
531
			panic("Softfloat not supported yet");
532
			return NULL;
Michael Beck's avatar
Michael Beck committed
533
		}
Michael Beck's avatar
Michael Beck committed
534
	}
535
	else {
536
		assert(mode_is_data(mode) && "unknown mode for Sub");
537
		mode = mode_Iu;
538
539

		if (is_arm_Mov_i(new_op1))
Michael Beck's avatar
Michael Beck committed
540
			return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
541
		if (is_arm_Mov_i(new_op2))
Michael Beck's avatar
Michael Beck committed
542
			return new_rd_arm_Sub_i(dbg, irg, block, new_op1, mode, get_arm_imm_value(new_op2));
Michael Beck's avatar
Michael Beck committed
543
544

		/* is the first a shifter */
545
		v = is_shifter_operand(new_op1, &mod);
Michael Beck's avatar
Michael Beck committed
546
		if (v) {
547
			new_op1 = get_irn_n(new_op1, 0);
Michael Beck's avatar
Michael Beck committed
548
			return new_rd_arm_Rsb(dbg, irg, block, new_op2, new_op1, mode, mod, v);
549
		}
Michael Beck's avatar
Michael Beck committed
550
		/* is the second a shifter */
551
		v = is_shifter_operand(new_op2, &mod);
Michael Beck's avatar
Michael Beck committed
552
		if (v) {
553
			new_op2 = get_irn_n(new_op2, 0);
Michael Beck's avatar
Michael Beck committed
554
			return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, mod, v);
Michael Beck's avatar
Michael Beck committed
555
556
		}
		/* normal sub */
Michael Beck's avatar
Michael Beck committed
557
		return new_rd_arm_Sub(dbg, irg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
558
559
560
561
	}
}

/**
562
 * Creates an ARM Shl.
563
 *
564
 * @return the created ARM Shl node
565
 */
566
567
568
569
570
571
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);
572
	ir_mode  *mode    = mode_Iu;
573
574
575
	dbg_info *dbg     = get_irn_dbg_info(node);

	if (is_arm_Mov_i(new_op2)) {
Michael Beck's avatar
Michael Beck committed
576
		return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSL, get_arm_imm_value(new_op2));
577
	}
578
	return new_rd_arm_Shl(dbg, current_ir_graph, block, new_op1, new_op2, mode);
579
580
581
}

/**
582
 * Creates an ARM Shr.
583
 *
584
 * @return the created ARM Shr node
585
 */
586
587
588
589
590
591
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);
592
	ir_mode  *mode    = mode_Iu;
593
594
595
	dbg_info *dbg     = get_irn_dbg_info(node);

	if (is_arm_Mov_i(new_op2)) {
Michael Beck's avatar
Michael Beck committed
596
		return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_LSR, get_arm_imm_value(new_op2));
597
	}
598
	return new_rd_arm_Shr(dbg, current_ir_graph, block, new_op1, new_op2, mode);
599
600
601
}

/**
602
 * Creates an ARM Shrs.
603
 *
604
 * @return the created ARM Shrs node
605
 */
606
607
608
609
610
611
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);
612
	ir_mode  *mode    = mode_Iu;
613
614
615
	dbg_info *dbg     = get_irn_dbg_info(node);

	if (is_arm_Mov_i(new_op2)) {
Michael Beck's avatar
Michael Beck committed
616
		return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ASR, get_arm_imm_value(new_op2));
617
	}
618
	return new_rd_arm_Shrs(dbg, current_ir_graph, block, new_op1, new_op2, mode);
619
620
}

Michael Beck's avatar
Michael Beck committed
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
/**
 * 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)) {
		return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ROR, get_arm_imm_value(new_op2));
	}
	return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode);
}

/**
 * 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
651
652
653
	ir_node  *new_op2 = be_transform_node(op2);

	new_op2 = new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op2, mode, 32);
Michael Beck's avatar
Michael Beck committed
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
	return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode);
}

/**
 * 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
672
		ir_node *right = get_Add_right(op2);
Michael Beck's avatar
Michael Beck committed
673
674
675
676
		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
677
			ir_node *left = get_Add_left(op2);
Michael Beck's avatar
Michael Beck committed
678
679

			if (is_Minus(left) &&
Michael Beck's avatar
Michael Beck committed
680
			    tarval_is_long(tv)          &&
Michael Beck's avatar
Michael Beck committed
681
682
683
684
			    get_tarval_long(tv) == bits &&
			    bits                == 32)
				rotate = gen_Ror(node, op1, get_Minus_op(left));
		}
Michael Beck's avatar
Michael Beck committed
685
686
687
688
689
690
691
692
693
694
695
696
697
	} 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);
		}
698
699
700
701
	} 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
702

703
704
705
706
707
708
709
710
711
			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;
				rotate = new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ROR, bits);
			}
Michael Beck's avatar
Michael Beck committed
712
713
714
715
716
717
718
719
720
	}

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

	return rotate;
}

721
722
723
/**
 * Transforms a Not node.
 *
724
 * @return the created ARM Not node
725
 */
726
727
728
729
730
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);
731
	ir_mode  *mode    = mode_Iu;
Michael Beck's avatar
Michael Beck committed
732
	arm_shift_modifier mod = ARM_SHF_NONE;
733
	int      v        = is_shifter_operand(new_op, &mod);
Michael Beck's avatar
Michael Beck committed
734
735

	if (v) {
736
		new_op = get_irn_n(new_op, 0);
Michael Beck's avatar
Michael Beck committed
737
	}
Michael Beck's avatar
Michael Beck committed
738
	return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, mode, mod, v);
739
740
}

Michael Beck's avatar
Michael Beck committed
741
742
743
744
/**
 * Transforms an Abs node.
 *
 * @param env   The transformation environment
745
 * @return the created ARM Abs node
Michael Beck's avatar
Michael Beck committed
746
 */
747
748
static ir_node *gen_Abs(ir_node *node) {
	ir_node  *block   = be_transform_node(get_nodes_block(node));
749
	ir_node  *op      = get_Abs_op(node);
750
751
752
	ir_node  *new_op  = be_transform_node(op);
	dbg_info *dbg     = get_irn_dbg_info(node);
	ir_mode  *mode    = get_irn_mode(node);
753

754
	if (mode_is_float(mode)) {
755
756
757
758
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
			return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, new_op, mode);
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
759
			assert(mode != mode_E && "IEEE Extended FP not supported");
760
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
761
762
		}
		else {
763
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
764
		}
765
	}
766
	assert(mode_is_data(mode));
767
	mode = mode_Iu;
768
	return new_rd_arm_Abs(dbg, current_ir_graph, block, new_op, mode);
769
770
771
772
773
}

/**
 * Transforms a Minus node.
 *
774
 * @return the created ARM Minus node
775
 */
776
777
778
779
780
781
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
782

783
	if (mode_is_float(mode)) {
784
785
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
786
			return new_rd_arm_fpaMvf(dbg, current_ir_graph, block, op, mode);
787
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
788
			assert(mode != mode_E && "IEEE Extended FP not supported");
789
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
790
791
		}
		else {
792
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
793
		}
794
	}
795
	assert(mode_is_data(mode));
796
	mode = mode_Iu;
Michael Beck's avatar
Michael Beck committed
797
	return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, 0);
798
799
800
801
802
}

/**
 * Transforms a Load.
 *
803
 * @return the created ARM Load node
804
 */
805
static ir_node *gen_Load(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
806
807
808
809
810
811
812
813
814
	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);
	ir_graph *irg      = current_ir_graph;
	dbg_info *dbg      = get_irn_dbg_info(node);
	ir_node  *new_load = NULL;
815

Michael Beck's avatar
Michael Beck committed
816
	if (mode_is_float(mode)) {
817
818
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
Michael Beck's avatar
Michael Beck committed
819
			new_load = new_rd_arm_fpaLdf(dbg, irg, block, new_ptr, new_mem, mode);
820
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
821
			assert(mode != mode_E && "IEEE Extended FP not supported");
822
			panic("VFP not supported yet");
823
824
		}
		else {
825
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
826
		}
827
	}
828
	else {
829
		assert(mode_is_data(mode) && "unsupported mode for Load");
830
831
832
833
834

		if (mode_is_signed(mode)) {
			/* sign extended loads */
			switch (get_mode_size_bits(mode)) {
			case 8:
Michael Beck's avatar
Michael Beck committed
835
				new_load = new_rd_arm_Loadbs(dbg, irg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
836
				break;
837
			case 16:
Michael Beck's avatar
Michael Beck committed
838
				new_load = new_rd_arm_Loadhs(dbg, irg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
839
				break;
840
			case 32:
Michael Beck's avatar
Michael Beck committed
841
				new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
842
843
				break;
			default:
844
				panic("mode size not supported");
845
846
847
848
849
			}
		} else {
			/* zero extended loads */
			switch (get_mode_size_bits(mode)) {
			case 8:
Michael Beck's avatar
Michael Beck committed
850
				new_load = new_rd_arm_Loadb(dbg, irg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
851
				break;
852
			case 16:
Michael Beck's avatar
Michael Beck committed
853
				new_load = new_rd_arm_Loadh(dbg, irg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
854
				break;
855
			case 32:
Michael Beck's avatar
Michael Beck committed
856
				new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
857
858
				break;
			default:
859
				panic("mode size not supported");
860
861
			}
		}
862
	}
Michael Beck's avatar
Michael Beck committed
863
	set_irn_pinned(new_load, get_irn_pinned(node));
864
865
866
867
868

	/* 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 */
		ir_node *proj = new_r_Proj(irg, block, new_load, mode_Iu, pn_arm_Load_res);
869
		be_new_Keep(arch_get_irn_reg_class(proj, -1), irg, block, 1, &proj);
870
871
	}

Michael Beck's avatar
Michael Beck committed
872
	return new_load;
873
874
875
876
877
}

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

Michael Beck's avatar
Michael Beck committed
893
	if (mode_is_float(mode)) {
894
895
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
Michael Beck's avatar
Michael Beck committed
896
			new_store = new_rd_arm_fpaStf(dbg, irg, block, new_ptr, new_val, new_mem, mode);
897
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
898
			assert(mode != mode_E && "IEEE Extended FP not supported");
899
			panic("VFP not supported yet