arm_transform.c 48 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
93
	/* ensure the const is scheduled AFTER the stack frame */
	add_irn_dep(res, get_irg_frame(irg));
Michael Beck's avatar
Michael Beck committed
94
	return res;
95
96
}

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

	if (mode_needs_gp_reg(mode))
		mode = mode_Iu;
Michael Beck's avatar
Michael Beck committed
107
	res = new_rd_arm_Mvn_i(dbg, irg, block, mode, value);
108
109
	/* ensure the const is scheduled AFTER the stack frame */
	add_irn_dep(res, get_irg_frame(irg));
Michael Beck's avatar
Michael Beck committed
110
	return res;
111
112
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		if (is_arm_Mov_i(new_op1))
Michael Beck's avatar
Michael Beck committed
332
			return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
333
		if (is_arm_Mov_i(new_op2))
Michael Beck's avatar
Michael Beck committed
334
			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
335
336

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

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

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

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

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

/**
371
 * Creates an ARM Mul.
372
373
374
 *
 * @return the created arm Mul node
 */
375
376
377
378
379
380
381
382
383
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
384

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

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

424
	assert(mode != mode_E && "IEEE Extended FP not supported");
425

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

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

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

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

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

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

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

		if (is_arm_Mov_i(new_op1))
Michael Beck's avatar
Michael Beck committed
542
			return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_imm_value(new_op1));
543
		if (is_arm_Mov_i(new_op2))
Michael Beck's avatar
Michael Beck committed
544
			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
545
546

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

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

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

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

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

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

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

/**
 * Transforms a Not node.
 *
626
 * @return the created ARM Not node
627
 */
628
629
630
631
632
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);
633
	ir_mode  *mode    = mode_Iu;
Michael Beck's avatar
Michael Beck committed
634
	arm_shift_modifier mod = ARM_SHF_NONE;
635
	int      v        = is_shifter_operand(new_op, &mod);
Michael Beck's avatar
Michael Beck committed
636
637

	if (v) {
638
		new_op = get_irn_n(new_op, 0);
Michael Beck's avatar
Michael Beck committed
639
	}
Michael Beck's avatar
Michael Beck committed
640
	return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, mode, mod, v);
641
642
}

Michael Beck's avatar
Michael Beck committed
643
644
645
646
/**
 * Transforms an Abs node.
 *
 * @param env   The transformation environment
647
 * @return the created ARM Abs node
Michael Beck's avatar
Michael Beck committed
648
 */
649
650
static ir_node *gen_Abs(ir_node *node) {
	ir_node  *block   = be_transform_node(get_nodes_block(node));
651
	ir_node  *op      = get_Abs_op(node);
652
653
654
	ir_node  *new_op  = be_transform_node(op);
	dbg_info *dbg     = get_irn_dbg_info(node);
	ir_mode  *mode    = get_irn_mode(node);
655

656
	if (mode_is_float(mode)) {
657
658
659
660
		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
661
			assert(mode != mode_E && "IEEE Extended FP not supported");
Michael Beck's avatar
Michael Beck committed
662
663
664
665
			panic("VFP not supported yet\n");
		}
		else {
			panic("Softfloat not supported yet\n");
Michael Beck's avatar
Michael Beck committed
666
		}
667
	}
668
	assert(mode_is_data(mode));
669
	mode = mode_Iu;
670
	return new_rd_arm_Abs(dbg, current_ir_graph, block, new_op, mode);
671
672
673
674
675
}

/**
 * Transforms a Minus node.
 *
676
 * @return the created ARM Minus node
677
 */
678
679
680
681
682
683
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
684

685
	if (mode_is_float(mode)) {
686
687
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
688
			return new_rd_arm_fpaMvf(dbg, current_ir_graph, block, op, mode);
689
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
690
			assert(mode != mode_E && "IEEE Extended FP not supported");
Michael Beck's avatar
Michael Beck committed
691
692
693
694
			panic("VFP not supported yet\n");
		}
		else {
			panic("Softfloat not supported yet\n");
Michael Beck's avatar
Michael Beck committed
695
		}
696
	}
697
	assert(mode_is_data(mode));
698
	mode = mode_Iu;
Michael Beck's avatar
Michael Beck committed
699
	return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, 0);
700
701
702
703
704
}

/**
 * Transforms a Load.
 *
705
 * @return the created ARM Load node
706
 */
707
static ir_node *gen_Load(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
708
709
710
711
712
713
714
715
716
	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;
717

Michael Beck's avatar
Michael Beck committed
718
	if (mode_is_float(mode)) {
719
720
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
Michael Beck's avatar
Michael Beck committed
721
			new_load = new_rd_arm_fpaLdf(dbg, irg, block, new_ptr, new_mem, mode);
722
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
723
			assert(mode != mode_E && "IEEE Extended FP not supported");
724
725
726
727
			panic("VFP not supported yet\n");
		}
		else {
			panic("Softfloat not supported yet\n");
Michael Beck's avatar
Michael Beck committed
728
		}
729
	}
730
	else {
731
		assert(mode_is_data(mode) && "unsupported mode for Load");
732
733
734
735
736

		if (mode_is_signed(mode)) {
			/* sign extended loads */
			switch (get_mode_size_bits(mode)) {
			case 8:
Michael Beck's avatar
Michael Beck committed
737
				new_load = new_rd_arm_Loadbs(dbg, irg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
738
				break;
739
			case 16:
Michael Beck's avatar
Michael Beck committed
740
				new_load = new_rd_arm_Loadhs(dbg, irg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
741
				break;
742
			case 32:
Michael Beck's avatar
Michael Beck committed
743
				new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
744
745
				break;
			default:
Michael Beck's avatar
Michael Beck committed
746
				panic("mode size not supported\n");
747
748
749
750
751
			}
		} else {
			/* zero extended loads */
			switch (get_mode_size_bits(mode)) {
			case 8:
Michael Beck's avatar
Michael Beck committed
752
				new_load = new_rd_arm_Loadb(dbg, irg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
753
				break;
754
			case 16:
Michael Beck's avatar
Michael Beck committed
755
				new_load = new_rd_arm_Loadh(dbg, irg, block, new_ptr, new_mem);
Michael Beck's avatar
Michael Beck committed
756
				break;
757
			case 32:
Michael Beck's avatar
Michael Beck committed
758
				new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem);
759
760
				break;
			default:
Michael Beck's avatar
Michael Beck committed
761
				panic("mode size not supported\n");
762
763
			}
		}
764
	}
Michael Beck's avatar
Michael Beck committed
765
	set_irn_pinned(new_load, get_irn_pinned(node));
766
767
768
769
770
771
772
773

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

Michael Beck's avatar
Michael Beck committed
774
	return new_load;
775
776
777
778
779
}

/**
 * Transforms a Store.
 *
780
 * @return the created ARM Store node
781
 */
782
static ir_node *gen_Store(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
783
784
785
786
787
788
789
790
791
792
793
	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;
794

Michael Beck's avatar
Michael Beck committed
795
	if (mode_is_float(mode)) {
796
797
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
Michael Beck's avatar
Michael Beck committed
798
			new_store = new_rd_arm_fpaStf(dbg, irg, block, new_ptr, new_val, new_mem, mode);
799
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
800
			assert(mode != mode_E && "IEEE Extended FP not supported");
Michael Beck's avatar
Michael Beck committed
801
802
803
804
805
			panic("VFP not supported yet\n");
		} else {
			panic("Softfloat not supported yet\n");
		}
	} else {
806
		assert(mode_is_data(mode) && "unsupported mode for Store");
Michael Beck's avatar
Michael Beck committed
807
808
809
810
811
812
813
		switch (get_mode_size_bits(mode)) {
		case 8:
			new_store = new_rd_arm_Storeb(dbg, irg, block, new_ptr, new_val, new_mem);
		case 16:
			new_store = new_rd_arm_Storeh(dbg, irg, block, new_ptr, new_val, new_mem);
		default:
			new_store = new_rd_arm_Store(dbg, irg, block, new_ptr, new_val, new_mem);
Michael Beck's avatar
Michael Beck committed
814
		}
815
	}
Michael Beck's avatar
Michael Beck committed
816
817
	set_irn_pinned(new_store, get_irn_pinned(node));
	return new_store;
818
819
}

820
821
822
823
824
825
826
827
828
829
830
831
832
/**
 * Transforms a Cond.
 *
 * @return the created ARM Cond node
 */
static ir_node *gen_Cond(ir_node *node) {
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *selector = get_Cond_selector(node);
	ir_graph *irg      = current_ir_graph;
	dbg_info *dbg      = get_irn_dbg_info(node);
	ir_mode  *mode     = get_irn_mode(selector);

	if (mode == mode_b) {
833
		/* an conditional jump */
834
835
836
837
838
839
		ir_node *cmp_node = get_Proj_pred(selector);
		ir_node *op1      = get_Cmp_left(cmp_node);
		ir_node *new_op1  = be_transform_node(op1);
		ir_node *op2      = get_Cmp_right(cmp_node);
		ir_node *new_op2  = be_transform_node(op2);

840
841
842
843
844
845
846
847
848
849
850
851
852
853
		if (mode_is_float(get_irn_mode(op1))) {
			/* floating point compare */
			pn_Cmp pnc = get_Proj_proj(selector);

			if (pnc & pn_Cmp_Uo) {
				/* check for unordered, need cmf */
				return new_rd_arm_fpaCmfBra(dbg, irg, block, new_op1, new_op2, pnc);
			}
			/* Hmm: use need cmfe */
			return new_rd_arm_fpaCmfeBra(dbg, irg, block, new_op1, new_op2, pnc);
		} else {
			/* integer compare */
			return new_rd_arm_CmpBra(dbg, irg, block, new_op1, new_op2, get_Proj_proj(selector));
		}
854
	} else {
855
856
		/* SwitchJmp */
		ir_node *new_op = be_transform_node(selector);
857
858
859
860
861
862
863
864
865
866
867
		ir_node *const_graph;
		ir_node *sub;

		ir_node *proj;
		const ir_edge_t *edge;
		int min = INT_MAX;
		int max = INT_MIN;
		int translation;
		int pn;
		int n_projs;

868
		foreach_out_edge(node, edge) {
869
870
871
872
873
874
875
876
877
			proj = get_edge_src_irn(edge);
			assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");

			pn = get_Proj_proj(proj);

			min = pn<min ? pn : min;
			max = pn>max ? pn : max;
		}
		translation = min;
878
		n_projs = max - translation + 1;
879

880
		foreach_out_edge(node, edge) {
881
882
883
884
885
886
887
			proj = get_edge_src_irn(edge);
			assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");

			pn = get_Proj_proj(proj) - translation;
			set_Proj_proj(proj, pn);
		}

888
		const_graph = create_const_graph_value(dbg, block, translation);
Michael Beck's avatar
Michael Beck committed
889
		sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, 0);
890
		return new_rd_arm_SwitchJmp(dbg, irg, block, sub, n_projs, get_Cond_defaultProj(node) - translation);
891
892
893
894
895
896
897
898
	}
}

/**
 * Returns the name of a SymConst.
 * @param symc  the SymConst
 * @return name of the SymConst
 */
Michael Beck's avatar
Michael Beck committed
899
static ident *get_sc_ident(ir_node *symc) {
Michael Beck's avatar
Michael Beck committed
900
	ir_entity *ent;
901
902
903

	switch (get_SymConst_kind(symc)) {
		case symconst_addr_name:
Michael Beck's avatar
Michael Beck committed
904
			return get_SymConst_name(symc);
905
906

		case symconst_addr_ent:
Michael Beck's avatar
Michael Beck committed
907
			ent = get_SymConst_entity(symc);
Michael Beck's avatar
Michael Beck committed
908
			set_entity_backend_marked(ent, 1);
Michael Beck's avatar
Michael Beck committed
909
			return get_entity_ld_ident(ent);
910
911
912
913
914
915
916
917

		default:
			assert(0 && "Unsupported SymConst");
	}

	return NULL;
}

918
919
static tarval *fpa_imm[3][fpa_max];

920
921
/**
 * Check, if a floating point tarval is an fpa immediate, i.e.
922
 * one of 0, 1, 2, 3, 4, 5, 10, or 0.5.
923
924
 */
static int is_fpa_immediate(tarval *tv) {
925
926
927
928
929
930
931
932
933
934
935
936