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
#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
	ir_graph *irg  = current_ir_graph;
85
86
87
88
	ir_node *res;

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

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

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

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

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

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

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

		for (cnt = 1; cnt < vn.ops; ++cnt) {
Michael Beck's avatar
Michael Beck committed
128
129
			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
130
			result = bic_i_node;
131
132
		}
	}
Michael Beck's avatar
Michael Beck committed
133
134
	else {
		/* add bits */
135
		result = create_mov_node(dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
Michael Beck's avatar
Michael Beck committed
136
137

		for (cnt = 1; cnt < v.ops; ++cnt) {
Michael Beck's avatar
Michael Beck committed
138
139
			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
140
141
			result = orr_i_node;
		}
142
143
144
145
	}
	return result;
}

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

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

Michael Beck's avatar
Michael Beck committed
174
175
176
/**
 * Generate code for a sign extension.
 */
177
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
178
	ir_graph *irg   = current_ir_graph;
179
	int shift_width = 32 - result_bits;
180
	ir_node *shift_const_node = create_const_graph_value(dbg, block, shift_width);
Michael Beck's avatar
Michael Beck committed
181
182
	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);
183
184
185
	return rshift_node;
}

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

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

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

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

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

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

		if (is_arm_Mov_i(new_op1))
Michael Beck's avatar
Michael Beck committed
328
			return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
329
		if (is_arm_Mov_i(new_op2))
Michael Beck's avatar
Michael Beck committed
330
			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
331
332

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

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

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

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

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

/**
367
 * Creates an ARM Mul.
368
369
370
 *
 * @return the created arm Mul node
 */
371
372
373
374
375
376
377
378
379
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
380

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

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

420
	assert(mode != mode_E && "IEEE Extended FP not supported");
421

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

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

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

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

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

/**
499
 * Creates an ARM Sub.
500
501
502
 *
 * @return the created arm Sub node
 */
503
504
505
506
507
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
508
	ir_node  *new_op2 = be_transform_node(op2);
509
510
511
512
	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
513
514
	arm_shift_modifier mod;

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

		if (is_arm_Mov_i(new_op1))
Michael Beck's avatar
Michael Beck committed
538
			return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
539
		if (is_arm_Mov_i(new_op2))
Michael Beck's avatar
Michael Beck committed
540
			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
541
542

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

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

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

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

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

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

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

Michael Beck's avatar
Michael Beck committed
619
620
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
/**
 * 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
649
650
651
	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
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
	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
670
		ir_node *right = get_Add_right(op2);
Michael Beck's avatar
Michael Beck committed
671
672
673
674
		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
675
			ir_node *left = get_Add_left(op2);
Michael Beck's avatar
Michael Beck committed
676
677

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

701
702
703
704
705
706
707
708
709
			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
710
711
712
713
714
715
716
717
718
	}

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

	return rotate;
}

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

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

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

752
	if (mode_is_float(mode)) {
753
754
755
756
		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
757
			assert(mode != mode_E && "IEEE Extended FP not supported");
758
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
759
760
		}
		else {
761
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
762
		}
763
	}
764
	assert(mode_is_data(mode));
765
	mode = mode_Iu;
766
	return new_rd_arm_Abs(dbg, current_ir_graph, block, new_op, mode);
767
768
769
770
771
}

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

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

/**
 * Transforms a Load.
 *
801
 * @return the created ARM Load node
802
 */
803
static ir_node *gen_Load(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
804
805
806
807
808
809
810
811
812
	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;
813

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

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

	/* 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);
867
		be_new_Keep(arch_get_irn_reg_class(proj, -1), irg, block, 1, &proj);
868
869
	}

Michael Beck's avatar
Michael Beck committed
870
	return new_load;
871
872
873
874
875
}

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

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