arm_transform.c 37.4 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
 *
 * 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
41
42
#include "dbginfo.h"
#include "iropt_t.h"
#include "debug.h"

#include "../benode_t.h"
Michael Beck's avatar
Michael Beck committed
43
#include "../beirg_t.h"
44
45
46
#include "bearch_arm_t.h"

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

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
extern ir_op *get_op_Mulh(void);



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

typedef struct vals_ {
Michael Beck's avatar
Michael Beck committed
72
73
74
	int ops;
	unsigned char values[4];
	unsigned char shifts[4];
75
76
} vals;

77
78
79
80
81
82
83
84
/** Execute ROL. */
static unsigned do_rol(unsigned v, unsigned rol) {
	return (v << rol) | (v >> (32 - rol));
}

/**
 * construct 8bit values und rot amounts for a value
 */
Michael Beck's avatar
Michael Beck committed
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
static void gen_vals_from_word(unsigned int value, vals *result)
{
	int initial = 0;

	memset(result, 0, sizeof(*result));

	/* special case: we prefer shift amount 0 */
	if (value < 0x100) {
		result->values[0] = value;
		result->ops       = 1;
		return;
	}

	while (value != 0) {
		if (value & 0xFF) {
			unsigned v = do_rol(value, 8) & 0xFFFFFF;
			int shf = 0;
			for (;;) {
				if ((v & 3) != 0)
					break;
				shf += 2;
				v >>= 2;
			}
			v  &= 0xFF;
			shf = (initial + shf - 8) & 0x1F;
			result->values[result->ops] = v;
			result->shifts[result->ops] = shf;
			++result->ops;

			value ^= do_rol(v, shf) >> initial;
		}
		else {
			value >>= 8;
			initial += 8;
		}
	}
121
122
}

Michael Beck's avatar
Michael Beck committed
123
124
125
/**
 * Creates a arm_Const node.
 */
Michael Beck's avatar
Michael Beck committed
126
static ir_node *create_const_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) {
127
128
	tarval *tv = new_tarval_from_long(value, mode_Iu);
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
129
130
131
132
	ir_node *res = new_rd_arm_Mov_i(dbg, current_ir_graph, block, get_irn_mode(irn), tv);
	/* ensure the const is schedules AFTER the barrier */
	add_irn_dep(res, be_abi_get_start_barrier(abi));
	return res;
133
134
}

Michael Beck's avatar
Michael Beck committed
135
136
137
/**
 * Creates a arm_Const_Neg node.
 */
Michael Beck's avatar
Michael Beck committed
138
static ir_node *create_const_neg_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) {
139
140
	tarval *tv = new_tarval_from_long(value, mode_Iu);
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
141
142
143
144
	ir_node *res = new_rd_arm_Mvn_i(dbg, current_ir_graph, block, get_irn_mode(irn), tv);
	add_irn_dep(res, be_abi_get_start_barrier(abi));
	/* ensure the const is schedules AFTER the barrier */
	return res;
145
146
}

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

Michael Beck's avatar
Michael Beck committed
149
150
151
152
/**
 * Encodes an immediate with shifter operand
 */
static unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate) {
153
154
155
	return immediate | ((shift>>1)<<8);
}

Michael Beck's avatar
Michael Beck committed
156
157
158
159
160
161
162
163
164
165
166
167
168
/**
 * Decode an immediate with shifter operand
 */
unsigned int arm_decode_imm_w_shift(tarval *tv) {
	unsigned l = get_tarval_long(tv);
	unsigned rol = (l & ~0xFF) >> 7;

	return do_rol(l & 0xFF, rol);
}

/**
 * Creates a possible DAG for an constant.
 */
Michael Beck's avatar
Michael Beck committed
169
static ir_node *create_const_graph_value(be_abi_irg_t *abi, ir_node *irn, ir_node *block, unsigned int value) {
170
	ir_node *result;
Michael Beck's avatar
Michael Beck committed
171
172
	vals v, vn;
	int cnt;
173
174
	ir_mode *mode = get_irn_mode(irn);
	dbg_info *dbg = get_irn_dbg_info(irn);
175

Michael Beck's avatar
Michael Beck committed
176
177
178
179
180
	gen_vals_from_word(value, &v);
	gen_vals_from_word(~value, &vn);

	if (vn.ops < v.ops) {
		/* remove bits */
Michael Beck's avatar
Michael Beck committed
181
		result = create_const_neg_node(abi, irn, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
Michael Beck's avatar
Michael Beck committed
182
183
184

		for (cnt = 1; cnt < vn.ops; ++cnt) {
			tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode_Iu);
185
			ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode, tv);
Michael Beck's avatar
Michael Beck committed
186
			result = bic_i_node;
187
188
		}
	}
Michael Beck's avatar
Michael Beck committed
189
190
	else {
		/* add bits */
Michael Beck's avatar
Michael Beck committed
191
		result = create_const_node(abi, irn, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
Michael Beck's avatar
Michael Beck committed
192
193
194

		for (cnt = 1; cnt < v.ops; ++cnt) {
			tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode_Iu);
195
			ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, tv);
Michael Beck's avatar
Michael Beck committed
196
197
			result = orr_i_node;
		}
198
199
200
201
	}
	return result;
}

202
203
204
205
206
/**
 * Create a DAG constructing a given Const.
 *
 * @param irn  a Firm const
 */
Michael Beck's avatar
Michael Beck committed
207
static ir_node *create_const_graph(be_abi_irg_t *abi, ir_node *irn, ir_node *block) {
208
	int value = get_tarval_long(get_Const_tarval(irn));
Michael Beck's avatar
Michael Beck committed
209
	return create_const_graph_value(abi, irn, block, value);
210
211
}

Michael Beck's avatar
Michael Beck committed
212
213
214
/**
 * Creates code for a Firm Const node.
 */
Michael Beck's avatar
Michael Beck committed
215
static ir_node *gen_arm_Const(ir_node *irn, ir_node *block, arm_code_gen_t *cg) {
216
217
218
219
	ir_graph *irg = current_ir_graph;
	ir_mode *mode = get_irn_mode(irn);
	dbg_info *dbg = get_irn_dbg_info(irn);

Michael Beck's avatar
Michael Beck committed
220
	if (mode_is_float(mode)) {
Michael Beck's avatar
Michael Beck committed
221
222
223
224
225
226
227
		cg->have_fp = 1;
		if (USE_FPA(cg->isa)) {
			irn = new_rd_arm_fpaConst(dbg, irg, block, get_Const_tarval(irn));
			/* ensure the const is schedules AFTER the barrier */
			add_irn_dep(irn, be_abi_get_start_barrier(cg->birg->abi));
			return irn;
		}
Michael Beck's avatar
Michael Beck committed
228
229
230
231
232
		else if (USE_VFP(cg->isa))
			assert(mode != mode_E && "IEEE Extended FP not supported");
		assert(0 && "NYI");
	}
	else if (mode_is_reference(mode))
233
		return irn;
Michael Beck's avatar
Michael Beck committed
234
	return create_const_graph(cg->birg->abi, irn, block);
235
236
}

Michael Beck's avatar
Michael Beck committed
237
static ir_node *gen_mask(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
238
	ir_node *block = get_nodes_block(irn);
239
	unsigned mask_bits = (1 << result_bits) - 1;
Michael Beck's avatar
Michael Beck committed
240
	ir_node *mask_node = create_const_graph_value(abi, irn, block, mask_bits);
241
242
	dbg_info *dbg = get_irn_dbg_info(irn);
	return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, get_irn_mode(irn), ARM_SHF_NONE, NULL);
243
244
}

Michael Beck's avatar
Michael Beck committed
245
static ir_node *gen_sign_extension(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) {
246
	ir_node *block = get_nodes_block(irn);
247
	int shift_width = 32 - result_bits;
248
	ir_graph *irg = current_ir_graph;
Michael Beck's avatar
Michael Beck committed
249
	ir_node *shift_const_node = create_const_graph_value(abi, irn, block, shift_width);
250
251
252
	dbg_info *dbg = get_irn_dbg_info(irn);
	ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, get_irn_mode(op));
	ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, get_irn_mode(irn));
253
254
255
	return rshift_node;
}

Michael Beck's avatar
Michael Beck committed
256
257
258
259
260
261
/**
 * Transforms a Conv node.
 *
 * @param env   The transformation environment
 * @return the created arm Conv node
 */
262
263
264
265
static ir_node *gen_Conv(ir_node *irn, arm_code_gen_t *cg) {
	ir_graph *irg = current_ir_graph;
	ir_node *block   = get_nodes_block(irn);
	ir_node *op      = get_Conv_op(irn);
266
	ir_mode *in_mode = get_irn_mode(op);
267
268
	ir_mode *out_mode = get_irn_mode(irn);
	dbg_info *dbg    = get_irn_dbg_info(irn);
269
270
271
272

	if (in_mode == out_mode)
		return op;

Michael Beck's avatar
Michael Beck committed
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
	if (mode_is_float(in_mode) || mode_is_float(out_mode)) {
		cg->have_fp = 1;

		if (USE_FPA(cg->isa)) {
			if (mode_is_float(in_mode)) {
				if (mode_is_float(out_mode)) {
					/* from float to float */
					return new_rd_arm_fpaMov(dbg, irg, block, op, out_mode);
				}
				else {
					/* from float to int */
					return new_rd_arm_fpaFix(dbg, irg, block, op, out_mode);
				}
			}
			else {
				/* from int to float */
				return new_rd_arm_fpaFlt(dbg, irg, block, op, out_mode);
			}
		}
		assert(0 && "NYI");
	}
	else { /* complete in gp registers */
		int in_bits  = get_mode_size_bits(in_mode);
296
		int out_bits = get_mode_size_bits(out_mode);
Michael Beck's avatar
Michael Beck committed
297
		int in_sign  = get_mode_sign(in_mode);
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
		int out_sign = get_mode_sign(out_mode);

		// 32 -> 32
			// NOPpen
		if (in_bits == out_bits && in_bits == 32)
			return op;

		// 16 -> 16
			// unsigned -> unsigned
				// NOP
			// unsigned -> signed
				// sign extension (31:16)=(15)
			// signed -> unsigned
				// maskieren (31:16)=0
			// signed -> signed
				// NOP
		if (in_bits == out_bits && out_bits < 32) {
			if (in_sign && !out_sign) {
Michael Beck's avatar
Michael Beck committed
316
				return gen_mask(cg->birg->abi, irn, op, out_bits);
317
			} else {
Michael Beck's avatar
Michael Beck committed
318
				return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
319
320
321
322
323
324
325
326
327
328
329
330
331
332
			}
		}

		// 16 -> 32
			// unsigned -> unsigned
				// NOP
			// unsigned -> signed
				// NOP
			// signed -> unsigned
				// sign extension (31:16)=(15)
			// signed -> signed
				// sign extension (31:16)=(15)
		if (in_bits < out_bits) {
			if (in_sign) {
Michael Beck's avatar
Michael Beck committed
333
				return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
			} else {
				return op;
			}
		}

		// 32 -> 16
			// unsigned -> unsigned
				// maskieren (31:16)=0
			// unsigned -> signed
				// maskieren (31:16)=0
			// signed -> unsigned
				// maskieren (31:16)=0
			// signed -> signed
				// sign extension (erledigt auch maskieren) (31:16)=(15)
		if (in_bits > out_bits) {
			if (in_sign && out_sign) {
Michael Beck's avatar
Michael Beck committed
350
				return gen_sign_extension(cg->birg->abi, irn, op, out_bits);
351
			} else {
Michael Beck's avatar
Michael Beck committed
352
				return gen_mask(cg->birg->abi, irn, op, out_bits);
353
354
355
			}
		}
		assert(0 && "recheck integer conversion logic!");
356
		return irn;
357
	}
Michael Beck's avatar
Michael Beck committed
358
	return NULL;
359
360
}

Michael Beck's avatar
Michael Beck committed
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
/**
 * 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) {
		long v = get_tarval_long(get_arm_value(n));
		if (v < 32)
			return (int)v;
	}
	return 0;
}
378
379
380
381
382
383
384

/**
 * Creates an arm Add.
 *
 * @param env   The transformation environment
 * @return the created arm Add node
 */
385
386
static ir_node *gen_Add(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block = get_nodes_block(irn);
Michael Beck's avatar
Michael Beck committed
387
388
	ir_node *op1 = get_Add_left(irn);
	ir_node *op2 = get_Add_right(irn);
389
390
	ir_mode *mode = get_irn_mode(irn);
	ir_graph *irg = current_ir_graph;
Michael Beck's avatar
Michael Beck committed
391
392
393
	ir_node *op3;
	int v;
	arm_shift_modifier mod;
394
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
395

396
397
	if (mode_is_float(mode)) {
		cg->have_fp = 1;
Michael Beck's avatar
Michael Beck committed
398
399
400
401
402
403
		if (USE_FPA(cg->isa))
			return new_rd_arm_fpaAdd(dbg, irg, block, op1, op2, mode);
		else if (USE_VFP(cg->isa)) {
			assert(mode != mode_E && "IEEE Extended FP not supported");
		}
		assert(0 && "NYI");
404
	}
405
	if (mode_is_numP(mode)) {
Michael Beck's avatar
Michael Beck committed
406
		if (is_arm_Mov_i(op1))
407
			return new_rd_arm_Add_i(dbg, irg, block, op2, mode, get_arm_value(op1));
Michael Beck's avatar
Michael Beck committed
408
		if (is_arm_Mov_i(op2))
409
			return new_rd_arm_Add_i(dbg, irg, block, op1, mode, get_arm_value(op2));
Michael Beck's avatar
Michael Beck committed
410
411
412
413
414
415
416

		/* check for MLA */
		if (is_arm_Mul(op1) && get_irn_n_edges(op1) == 1) {
			op3 = op2;
			op2 = get_irn_n(op1, 1);
			op1 = get_irn_n(op1, 0);

417
			return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode);
Michael Beck's avatar
Michael Beck committed
418
419
420
421
422
423
		}
		if (is_arm_Mul(op2) && get_irn_n_edges(op2) == 1) {
			op3 = op1;
			op1 = get_irn_n(op2, 0);
			op2 = get_irn_n(op2, 1);

424
			return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode);
Michael Beck's avatar
Michael Beck committed
425
		}
426

Michael Beck's avatar
Michael Beck committed
427
428
429
430
		/* is the first a shifter */
		v = is_shifter_operand(op1, &mod);
		if (v) {
			op1 = get_irn_n(op1, 0);
431
			return new_rd_arm_Add(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu));
Michael Beck's avatar
Michael Beck committed
432
433
434
435
436
		}
		/* is the second a shifter */
		v = is_shifter_operand(op2, &mod);
		if (v) {
			op2 = get_irn_n(op2, 0);
437
			return new_rd_arm_Add(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu));
Michael Beck's avatar
Michael Beck committed
438
		}
439

Michael Beck's avatar
Michael Beck committed
440
		/* normal ADD */
441
		return new_rd_arm_Add(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL);
Michael Beck's avatar
Michael Beck committed
442
443
444
445
446
	}

	assert(0 && "unknown mode for add");
	return NULL;
}
447
448
449
450

/**
 * Creates an arm Mul.
 *
Michael Beck's avatar
Michael Beck committed
451
 * @param env   The transformation environment
452
453
 * @return the created arm Mul node
 */
454
455
static ir_node *gen_Mul(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block = get_nodes_block(irn);
Michael Beck's avatar
Michael Beck committed
456
457
	ir_node *op1 = get_Mul_left(irn);
	ir_node *op2 = get_Mul_right(irn);
458
459
460
	ir_mode *mode = get_irn_mode(irn);
	ir_graph *irg = current_ir_graph;
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
461

462
463
	if (mode_is_float(mode)) {
		cg->have_fp = 1;
Michael Beck's avatar
Michael Beck committed
464
465
466
467
468
469
		if (USE_FPA(cg->isa))
			return new_rd_arm_fpaMul(dbg, irg, block, op1, op2, mode);
		else if (USE_VFP(cg->isa)) {
			assert(mode != mode_E && "IEEE Extended FP not supported");
		}
		assert(0 && "NYI");
470
	}
471
	return new_rd_arm_Mul(dbg, irg, block, op1, op2, mode);
472
473
474
}

/**
Michael Beck's avatar
Michael Beck committed
475
 * Creates an arm floating point Div.
476
 *
Michael Beck's avatar
Michael Beck committed
477
 * @param env   The transformation environment
478
479
 * @return the created arm fDiv node
 */
480
481
static ir_node *gen_Quot(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block = get_nodes_block(irn);
Michael Beck's avatar
Michael Beck committed
482
483
	ir_node *op1 = get_Quot_left(irn);
	ir_node *op2 = get_Quot_right(irn);
484
485
	ir_mode *mode = get_irn_mode(irn);
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
486

487
	assert(mode != mode_E && "IEEE Extended FP not supported");
488

Michael Beck's avatar
Michael Beck committed
489
490
491
492
493
494
495
496
497
	cg->have_fp = 1;
	if (USE_FPA(cg->isa))
		return new_rd_arm_fpaDiv(dbg, current_ir_graph, block, op1, op2, mode);
	else if (USE_VFP(cg->isa)) {
		assert(mode != mode_E && "IEEE Extended FP not supported");
	}
	assert(0 && "NYI");

	return NULL;
Michael Beck's avatar
Michael Beck committed
498
499
500
}

#define GEN_INT_OP(op) \
501
502
503
static ir_node *gen_ ## op(ir_node *irn, arm_code_gen_t *cg) { \
	ir_graph *irg = current_ir_graph; \
	ir_node *block = get_nodes_block(irn); \
Michael Beck's avatar
Michael Beck committed
504
505
506
507
	ir_node *op1 = get_ ## op ## _left(irn); \
	ir_node *op2 = get_ ## op ## _right(irn); \
	int v; \
	arm_shift_modifier mod; \
508
509
	ir_mode *mode = get_irn_mode(irn); \
	dbg_info *dbg = get_irn_dbg_info(irn); \
Michael Beck's avatar
Michael Beck committed
510
511
 \
	if (is_arm_Mov_i(op1)) \
512
		return new_rd_arm_ ## op ## _i(dbg, irg, block, op2, mode, get_arm_value(op1)); \
Michael Beck's avatar
Michael Beck committed
513
	if (is_arm_Mov_i(op2)) \
514
		return new_rd_arm_ ## op ## _i(dbg, irg, block, op1, mode, get_arm_value(op2)); \
Michael Beck's avatar
Michael Beck committed
515
516
517
518
	/* is the first a shifter */ \
	v = is_shifter_operand(op1, &mod); \
	if (v) { \
		op1 = get_irn_n(op1, 0); \
519
		return new_rd_arm_ ## op(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu)); \
Michael Beck's avatar
Michael Beck committed
520
521
522
523
524
	} \
	/* is the second a shifter */ \
	v = is_shifter_operand(op2, &mod); \
	if (v) { \
		op2 = get_irn_n(op2, 0); \
525
		return new_rd_arm_ ## op(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu)); \
Michael Beck's avatar
Michael Beck committed
526
527
	} \
	/* Normal op */ \
528
	return new_rd_arm_ ## op(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL); \
529
530
531
532
533
534
}


/**
 * Creates an arm And.
 *
Michael Beck's avatar
Michael Beck committed
535
 * @param env   The transformation environment
536
537
 * @return the created arm And node
 */
538
static ir_node *gen_And(ir_node *irn, arm_code_gen_t *cg);
Michael Beck's avatar
Michael Beck committed
539
GEN_INT_OP(And)
540
541

/**
Michael Beck's avatar
Michael Beck committed
542
 * Creates an arm Orr.
543
 *
Michael Beck's avatar
Michael Beck committed
544
 * @param env   The transformation environment
545
546
 * @return the created arm Or node
 */
547
static ir_node *gen_Or(ir_node *irn, arm_code_gen_t *cg);
Michael Beck's avatar
Michael Beck committed
548
GEN_INT_OP(Or)
549
550
551
552

/**
 * Creates an arm Eor.
 *
Michael Beck's avatar
Michael Beck committed
553
 * @param env   The transformation environment
554
555
 * @return the created arm Eor node
 */
556
static ir_node *gen_Eor(ir_node *irn, arm_code_gen_t *cg);
Michael Beck's avatar
Michael Beck committed
557
GEN_INT_OP(Eor)
558
559
560
561

/**
 * Creates an arm Sub.
 *
Michael Beck's avatar
Michael Beck committed
562
 * @param env   The transformation environment
563
564
 * @return the created arm Sub node
 */
565
566
static ir_node *gen_Sub(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block = get_nodes_block(irn);
Michael Beck's avatar
Michael Beck committed
567
568
569
570
	ir_node *op1 = get_Sub_left(irn);
	ir_node *op2 = get_Sub_right(irn);
	int v;
	arm_shift_modifier mod;
571
572
573
	ir_mode *mode = get_irn_mode(irn);
	ir_graph *irg = current_ir_graph;
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
574

575
576
	if (mode_is_float(mode)) {
		cg->have_fp = 1;
Michael Beck's avatar
Michael Beck committed
577
578
579
580
581
582
		if (USE_FPA(cg->isa))
			return new_rd_arm_fpaSub(dbg, irg, block, op1, op2, mode);
		else if (USE_VFP(cg->isa)) {
			assert(mode != mode_E && "IEEE Extended FP not supported");
		}
		assert(0 && "NYI");
Michael Beck's avatar
Michael Beck committed
583
	}
584
	if (mode_is_numP(mode)) {
Michael Beck's avatar
Michael Beck committed
585
		if (is_arm_Mov_i(op1))
586
			return new_rd_arm_Rsb_i(dbg, irg, block, op2, mode, get_arm_value(op1));
Michael Beck's avatar
Michael Beck committed
587
		if (is_arm_Mov_i(op2))
588
			return new_rd_arm_Sub_i(dbg, irg, block, op1, mode, get_arm_value(op2));
Michael Beck's avatar
Michael Beck committed
589
590
591
592
593

		/* is the first a shifter */
		v = is_shifter_operand(op1, &mod);
		if (v) {
			op1 = get_irn_n(op1, 0);
594
			return new_rd_arm_Rsb(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu));
595
		}
Michael Beck's avatar
Michael Beck committed
596
597
598
599
		/* is the second a shifter */
		v = is_shifter_operand(op2, &mod);
		if (v) {
			op2 = get_irn_n(op2, 0);
600
			return new_rd_arm_Sub(dbg, irg, block, op1, op2, mode, mod, new_tarval_from_long(v, mode_Iu));
Michael Beck's avatar
Michael Beck committed
601
602
		}
		/* normal sub */
603
		return new_rd_arm_Sub(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL);
604
	}
Michael Beck's avatar
Michael Beck committed
605
606
	assert(0 && "unknown mode for sub");
	return NULL;
607
608
609
610
611
}

/**
 * Creates an arm Shl.
 *
Michael Beck's avatar
Michael Beck committed
612
 * @param env   The transformation environment
613
614
 * @return the created arm Shl node
 */
615
static ir_node *gen_Shl(ir_node *irn, arm_code_gen_t *cg) {
616
	ir_node *result;
617
	ir_node *block = get_nodes_block(irn);
Michael Beck's avatar
Michael Beck committed
618
619
	ir_node *op1 = get_Shl_left(irn);
	ir_node *op2 = get_Shl_right(irn);
620
621
622
	ir_mode *mode = get_irn_mode(irn);
	ir_graph *irg = current_ir_graph;
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
623
624

	if (is_arm_Mov_i(op2)) {
625
		result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSL, get_arm_value(op2));
626
	} else {
627
		result = new_rd_arm_Shl(dbg, irg, block, op1, op2, mode);
628
629
630
631
632
633
634
	}
	return result;
}

/**
 * Creates an arm Shr.
 *
Michael Beck's avatar
Michael Beck committed
635
 * @param env   The transformation environment
636
637
 * @return the created arm Shr node
 */
638
static ir_node *gen_Shr(ir_node *irn, arm_code_gen_t *cg) {
639
	ir_node *result;
640
	ir_node *block = get_nodes_block(irn);
Michael Beck's avatar
Michael Beck committed
641
642
	ir_node *op1 = get_Shr_left(irn);
	ir_node *op2 = get_Shr_right(irn);
643
644
645
	ir_mode *mode = get_irn_mode(irn);
	ir_graph *irg = current_ir_graph;
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
646
647

	if (is_arm_Mov_i(op2)) {
648
		result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSR, get_arm_value(op2));
649
	} else {
650
		result = new_rd_arm_Shr(dbg, irg, block, op1, op2, mode);
651
652
653
654
655
656
657
	}
	return result;
}

/**
 * Creates an arm Shrs.
 *
Michael Beck's avatar
Michael Beck committed
658
 * @param env   The transformation environment
659
660
 * @return the created arm Shrs node
 */
661
static ir_node *gen_Shrs(ir_node *irn, arm_code_gen_t *cg) {
662
	ir_node *result;
663
	ir_node *block = get_nodes_block(irn);
Michael Beck's avatar
Michael Beck committed
664
665
	ir_node *op1 = get_Shrs_left(irn);
	ir_node *op2 = get_Shrs_right(irn);
666
667
	ir_mode *mode = get_irn_mode(irn);
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
668
669

	if (is_arm_Mov_i(op2)) {
670
		result = new_rd_arm_Mov(dbg, current_ir_graph, block, op1, mode, ARM_SHF_ASR, get_arm_value(op2));
671
	} else {
672
		result = new_rd_arm_Shrs(dbg, current_ir_graph, block, op1, op2, mode);
673
674
675
676
677
678
679
	}
	return result;
}

/**
 * Transforms a Not node.
 *
Michael Beck's avatar
Michael Beck committed
680
 * @param env   The transformation environment
681
682
 * @return the created arm Not node
 */
683
684
685
static ir_node *gen_Not(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block = get_nodes_block(irn);
	ir_node *op = get_Not_op(irn);
Michael Beck's avatar
Michael Beck committed
686
687
688
	int v;
	arm_shift_modifier mod = ARM_SHF_NONE;
	tarval  *tv = NULL;
689
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
690
691
692
693
694
695

	v = is_shifter_operand(op, &mod);
	if (v) {
		op = get_irn_n(op, 0);
		tv = new_tarval_from_long(v, mode_Iu);
	}
696
	return new_rd_arm_Mvn(dbg, current_ir_graph, block, op, get_irn_mode(irn), mod, tv);
697
698
}

Michael Beck's avatar
Michael Beck committed
699
700
701
702
703
704
/**
 * Transforms an Abs node.
 *
 * @param env   The transformation environment
 * @return the created arm Abs node
 */
705
706
707
708
709
static ir_node *gen_Abs(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block = get_nodes_block(irn);
	ir_node *op = get_Abs_op(irn);
	ir_mode *mode = get_irn_mode(irn);
	dbg_info *dbg = get_irn_dbg_info(irn);
710

711
712
	if (mode_is_float(mode)) {
		cg->have_fp = 1;
Michael Beck's avatar
Michael Beck committed
713
714
715
716
717
718
		if (USE_FPA(cg->isa))
			return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, op, mode);
		else if (USE_VFP(cg->isa)) {
			assert(mode != mode_E && "IEEE Extended FP not supported");
		}
		assert(0 && "NYI");
719
	}
720
	return new_rd_arm_Abs(dbg, current_ir_graph, block, op, mode);
721
722
723
724
725
}

/**
 * Transforms a Minus node.
 *
Michael Beck's avatar
Michael Beck committed
726
 * @param env   The transformation environment
727
728
 * @return the created arm Minus node
 */
729
730
731
732
733
734
static ir_node *gen_Minus(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block = get_nodes_block(irn);
	ir_node *op = get_Minus_op(irn);
	ir_mode *mode = get_irn_mode(irn);
	ir_graph *irg = current_ir_graph;
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
735

736
	if (mode_is_float(mode)) {
Michael Beck's avatar
Michael Beck committed
737
738
739
740
741
742
743
		cg->have_fp = 1;
		if (USE_FPA(cg->isa))
			return new_rd_arm_fpaMnv(dbg, irg, block, op, mode);
		else if (USE_VFP(cg->isa)) {
			assert(mode != mode_E && "IEEE Extended FP not supported");
		}
		assert(0 && "NYI");
744
	}
745
	return new_rd_arm_Rsb_i(dbg, irg, block, op, mode, get_mode_null(mode));
746
747
748
749
750
751
752
753
754
755
756
}

/**
 * Transforms a Load.
 *
 * @param mod     the debug module
 * @param block   the block the new node should belong to
 * @param node    the ir Load node
 * @param mode    node mode
 * @return the created arm Load node
 */
757
758
759
760
761
static ir_node *gen_Load(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block = get_nodes_block(irn);
	ir_mode *mode = get_Load_mode(irn);
	ir_graph *irg = current_ir_graph;
	dbg_info *dbg = get_irn_dbg_info(irn);
762

Michael Beck's avatar
Michael Beck committed
763
	if (mode_is_float(mode)) {
764
		cg->have_fp = 1;
Michael Beck's avatar
Michael Beck committed
765
766
767
768
769
770
771
		if (USE_FPA(cg->isa))
			return new_rd_arm_fpaLdf(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn),
				get_Load_mode(irn));
		else if (USE_VFP(cg->isa)) {
			assert(mode != mode_E && "IEEE Extended FP not supported");
		}
		assert(0 && "NYI");
772
773
	}
	if (mode == mode_Bu) {
Michael Beck's avatar
Michael Beck committed
774
		return new_rd_arm_Loadb(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
775
776
	}
	if (mode == mode_Bs) {
Michael Beck's avatar
Michael Beck committed
777
		return new_rd_arm_Loadbs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
778
779
	}
	if (mode == mode_Hu) {
Michael Beck's avatar
Michael Beck committed
780
		return new_rd_arm_Loadh(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
781
782
	}
	if (mode == mode_Hs) {
Michael Beck's avatar
Michael Beck committed
783
		return new_rd_arm_Loadhs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
784
785
	}
	if (mode_is_reference(mode)) {
Michael Beck's avatar
Michael Beck committed
786
		return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
787
	}
Michael Beck's avatar
Michael Beck committed
788
	return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn));
789
790
791
792
793
794
795
796
797
798
799
}

/**
 * Transforms a Store.
 *
 * @param mod     the debug module
 * @param block   the block the new node should belong to
 * @param node    the ir Store node
 * @param mode    node mode
 * @return the created arm Store node
 */
800
801
802
803
804
static ir_node *gen_Store(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block = get_nodes_block(irn);
	ir_mode *mode = get_irn_mode(get_Store_value(irn));
	ir_graph *irg = current_ir_graph;
	dbg_info *dbg = get_irn_dbg_info(irn);
805

806
	assert(mode != mode_E && "IEEE Extended FP not supported");
Michael Beck's avatar
Michael Beck committed
807
	if (mode_is_float(mode)) {
808
		cg->have_fp = 1;
Michael Beck's avatar
Michael Beck committed
809
810
811
812
813
814
815
		if (USE_FPA(cg->isa))
			return new_rd_arm_fpaStf(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn),
				get_Store_mem(irn), get_irn_mode(get_Store_value(irn)));
		else if (USE_VFP(cg->isa)) {
			assert(mode != mode_E && "IEEE Extended FP not supported");
		}
		assert(0 && "NYI");
816
817
	}
	if (mode == mode_Bu) {
Michael Beck's avatar
Michael Beck committed
818
		return new_rd_arm_Storeb(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
819
820
	}
	if (mode == mode_Bs) {
Michael Beck's avatar
Michael Beck committed
821
		return new_rd_arm_Storebs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
822
823
	}
	if (mode == mode_Hu) {
Michael Beck's avatar
Michael Beck committed
824
		return new_rd_arm_Storeh(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
825
826
	}
	if (mode == mode_Hs) {
Michael Beck's avatar
Michael Beck committed
827
		return new_rd_arm_Storehs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
828
	}
Michael Beck's avatar
Michael Beck committed
829
	return new_rd_arm_Store(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn));
830
831
832
}


833
static ir_node *gen_Cond(ir_node *irn, arm_code_gen_t *cg) {
Christian Würdig's avatar
Christian Würdig committed
834
	ir_node *result   = NULL;
835
836
837
838
	ir_node *selector = get_Cond_selector(irn);
	ir_node *block    = get_nodes_block(irn);
	ir_graph *irg     = current_ir_graph;
	dbg_info *dbg     = get_irn_dbg_info(irn);
Christian Würdig's avatar
Christian Würdig committed
839

840
841
842
843
844
845
	if ( get_irn_mode(selector) == mode_b ) {
		//CondJmp
		ir_node *proj_node = get_Cond_selector(irn);
		ir_node *cmp_node = get_Proj_pred(proj_node);
		ir_node *op1 = get_Cmp_left(cmp_node);
		ir_node *op2 = get_Cmp_right(cmp_node);
Michael Beck's avatar
Michael Beck committed
846
		result = new_rd_arm_CondJmp(dbg, irg, block, op1, op2, get_Proj_proj(proj_node));
847
848
	} else {
		//SwitchJmp
849
		ir_node *op = get_irn_n(irn, 0);
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
		ir_node *const_graph;
		ir_node *sub;
		ir_node *const_node;

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

		foreach_out_edge(irn, edge) {
			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;
		norm_max = max - translation;
		norm_min = min - translation;

		n_projs = norm_max + 1;
		projs = xcalloc(n_projs , sizeof(ir_node*));


		foreach_out_edge(irn, edge) {
			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);
		}


Michael Beck's avatar
Michael Beck committed
891
892
		const_node  = new_rd_Const(dbg, irg, block, mode_Iu, new_tarval_from_long(translation, mode_Iu));
		const_graph = create_const_graph(cg->birg->abi, const_node, block);
893
		sub = new_rd_arm_Sub(dbg, irg, block, op, const_graph, get_irn_mode(op), ARM_SHF_NONE, NULL);
Michael Beck's avatar
Michael Beck committed
894
895
		result = new_rd_arm_SwitchJmp(dbg, irg, block, sub,
			n_projs, get_Cond_defaultProj(irn)-translation);
896
897
898
899
900
901
902
903
904
	}
	return result;
}

/**
 * Returns the name of a SymConst.
 * @param symc  the SymConst
 * @return name of the SymConst
 */
Michael Beck's avatar
Michael Beck committed
905
static ident *get_sc_ident(ir_node *symc) {
Michael Beck's avatar
Michael Beck committed
906
	ir_entity *ent;
907
908
909

	switch (get_SymConst_kind(symc)) {
		case symconst_addr_name:
Michael Beck's avatar
Michael Beck committed
910
			return get_SymConst_name(symc);
911
912

		case symconst_addr_ent:
Michael Beck's avatar
Michael Beck committed
913
914
			ent = get_SymConst_entity(symc);
			mark_entity_visited(ent);
Michael Beck's avatar
Michael Beck committed
915
			return get_entity_ld_ident(ent);
916
917
918
919
920
921
922
923

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

	return NULL;
}

Michael Beck's avatar
Michael Beck committed
924
925
926
/**
 * Transforms a SymConst node.
 */
927
928
929
930
static ir_node *gen_SymConst(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block = get_nodes_block(irn);
	ir_mode *mode = get_irn_mode(irn);
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
931
	return new_rd_arm_SymConst(dbg, current_ir_graph, block, mode, get_sc_ident(irn));
932
933
934
935
936
937
938
939
940
941
}



/**
 * Transforms a CopyB node.
 *
 * @param env   The transformation environment
 * @return The transformed node.
 */
942
static ir_node *gen_CopyB(ir_node *irn, arm_code_gen_t *cg) {
943
	ir_node  *res   = NULL;
944
945
946
947
948
949
950
951
	dbg_info *dbg   = get_irn_dbg_info(irn);
	ir_mode  *mode  = get_irn_mode(irn);
	ir_node  *src   = get_CopyB_src(irn);
	ir_node  *dst   = get_CopyB_dst(irn);
	ir_node  *mem   = get_CopyB_mem(irn);
	ir_node  *block = get_nodes_block(irn);
	int       size  = get_type_size_bytes(get_CopyB_type(irn));
	ir_graph *irg   = current_ir_graph;
952
953
954
	ir_node *src_copy;
	ir_node *dst_copy;

Michael Beck's avatar
Michael Beck committed
955
956
	src_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, src);
	dst_copy = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], irg, block, dst);
957
958
959
960
961
962
963
964
965
966
967

 	res = new_rd_arm_CopyB( dbg, irg, block, dst_copy, src_copy, new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), new_rd_arm_EmptyReg(dbg, irg, block, mode_Iu), mem, mode);
	set_arm_value(res, new_tarval_from_long(size, mode_Iu));

	return res;
}





Michael Beck's avatar
Michael Beck committed
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
/********************************************
 *  _                          _
 * | |                        | |
 * | |__   ___ _ __   ___   __| | ___  ___
 * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
 * | |_) |  __/ | | | (_) | (_| |  __/\__ \
 * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
 *
 ********************************************/

/**
 * Return an expanding stack offset.
 * Note that function is called in the transform phase
 * where the stack offsets are still relative regarding
 * the first (frame allocating) IncSP.
 * However this is exactly what we want because frame
 * access must be done relative the the fist IncSP ...
 */
static int get_sp_expand_offset(ir_node *inc_sp) {
987
	int offset = be_get_IncSP_offset(inc_sp);
Michael Beck's avatar
Michael Beck committed
988

989
	if (offset == BE_STACK_FRAME_SIZE_EXPAND)
Michael Beck's avatar
Michael Beck committed
990
		return 0;
991
992

	return offset;
Michael Beck's avatar
Michael Beck committed
993
994
995
}

#if 0
Matthias Braun's avatar
Matthias Braun committed
996
static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) {
997
998
999
1000
1001
1002
1003
	ir_node   *new_op = NULL;
	ir_node   *block  = get_nodes_block(irn);
	ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
	ir_node   *mem    = new_rd_NoMem(env->irg);
	ir_node   *ptr    = get_irn_n(irn, 0);
	ir_entity *ent    = be_get_frame_entity(irn);
	ir_mode   *mode   = env->mode;
Michael Beck's avatar
Michael Beck committed
1004
1005
1006
1007
1008
1009
1010
1011
1012

//	/* If the StackParam has only one user ->     */
//	/* put it in the Block where the user resides */
//	if (get_irn_n_edges(node) == 1) {
//		env->block = get_nodes_block(get_edge_src_irn(get_irn_out_edge_first(node)));
//	}

	if (mode_is_float(mode)) {
		if (USE_SSE2(env->cg))
1013
			new_op = new_rd_ia32_fLoad(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
Michael Beck's avatar
Michael Beck committed
1014
1015
		else {
			env->cg->used_x87 = 1;
1016
			new_op = new_rd_ia32_vfld(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
Michael Beck's avatar
Michael Beck committed
1017
1018
1019
		}
	}
	else {
1020
		new_op = new_rd_ia32_Load(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
Michael Beck's avatar
Michael Beck committed
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
	}

	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

	set_ia32_am_support(new_op, ia32_am_Source);
	set_ia32_op_type(new_op, ia32_AddrModeS);
	set_ia32_am_flavour(new_op, ia32_B);
	set_ia32_ls_mode(new_op, mode);

	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));

1033
	return new_rd_Proj(env->dbg, env->irg, block, new_op, mode, 0);
Michael Beck's avatar
Michael Beck committed
1034
}
Matthias Braun's avatar
Matthias Braun committed
1035
#endif
Michael Beck's avatar
Michael Beck committed
1036
1037
1038
1039

/**
 * Transforms a FrameAddr into an ia32 Add.
 */
1040
1041
static ir_node *gen_be_FrameAddr(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block  = get_nodes_block(irn);
1042
	ir_entity *ent  = be_get_frame_entity(irn);
1043
	int     offset  = get_entity_offset(ent);
1044
	ir_node *op     = get_irn_n(irn, 0);
Michael Beck's avatar
Michael Beck committed
1045
	ir_node *cnst;
1046
1047
	ir_mode *mode   = get_irn_mode(irn);
	dbg_info *dbg   = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
1048
1049
1050
1051
1052
1053

	if (be_is_IncSP(op)) {
		/* BEWARE: we get an offset which is absolute from an offset that
		   is relative. Both must be merged */
		offset += get_sp_expand_offset(op);
	}
Michael Beck's avatar
Michael Beck committed
1054
	cnst = create_const_graph_value(cg->birg->abi, irn, block, (unsigned)offset);
1055
1056
1057
	if (is_arm_Mov_i(cnst))
		return new_rd_arm_Add_i(dbg, current_ir_graph, block, op, mode, get_arm_value(cnst));
	return new_rd_arm_Add(dbg, current_ir_graph, block, op, cnst, mode, ARM_SHF_NONE, NULL);
Michael Beck's avatar
Michael Beck committed
1058
1059
}

Matthias Braun's avatar
Matthias Braun committed
1060
#if 0
Michael Beck's avatar
Michael Beck committed
1061
1062
1063
/**
 * Transforms a FrameLoad into an ia32 Load.
 */
1064
static ir_node *gen_FrameLoad(ir_node *irn, arm_code_gen_t *cg) {
1065
1066
1067
1068
1069
1070
	ir_node   *new_op = NULL;
	ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
	ir_node   *mem    = get_irn_n(irn, 0);
	ir_node   *ptr    = get_irn_n(irn, 1);
	ir_entity *ent    = be_get_frame_entity(irn);
	ir_mode   *mode   = get_type_mode(get_entity_type(ent));
Michael Beck's avatar
Michael Beck committed
1071
1072
1073

	if (mode_is_float(mode)) {
		if (USE_SSE2(env->cg))
1074
			new_op = new_rd_ia32_fLoad(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
Michael Beck's avatar
Michael Beck committed
1075
1076
		else {
			env->cg->used_x87 = 1;
1077
			new_op = new_rd_ia32_vfld(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
Michael Beck's avatar
Michael Beck committed
1078
1079
1080
		}
	}
	else {
1081
		new_op = new_rd_ia32_Load(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T);
Michael Beck's avatar
Michael Beck committed
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
	}

	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

	set_ia32_am_support(new_op, ia32_am_Source);
	set_ia32_op_type(new_op, ia32_AddrModeS);
	set_ia32_am_flavour(new_op, ia32_B);
	set_ia32_ls_mode(new_op, mode);

	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));

	return new_op;
}
Matthias Braun's avatar
Matthias Braun committed
1096
#endif
Michael Beck's avatar
Michael Beck committed
1097

Matthias Braun's avatar
Matthias Braun committed
1098
#if 0
Michael Beck's avatar
Michael Beck committed
1099
1100
1101
/**
 * Transforms a FrameStore into an ia32 Store.
 */
1102
static ir_node *gen_FrameStore(ir_node *irn, arm_code_gen_t *cg) {
1103
1104
1105
1106
1107
1108
1109
	ir_node   *new_op = NULL;
	ir_node   *noreg  = ia32_new_NoReg_gp(env->cg);
	ir_node   *mem    = get_irn_n(irn, 0);
	ir_node   *ptr    = get_irn_n(irn, 1);
	ir_node   *val    = get_irn_n(irn, 2);
	ir_entity *ent    = be_get_frame_entity(irn);
	ir_mode   *mode   = get_irn_mode(val);
Michael Beck's avatar
Michael Beck committed
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137

	if (mode_is_float(mode)) {
		if (USE_SSE2(env->cg))
			new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
		else {
			env->cg->used_x87 = 1;
			new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
		}
	}
	else if (get_mode_size_bits(mode) == 8) {
		new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
	}
	else {
		new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T);
	}

	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

	set_ia32_am_support(new_op, ia32_am_Dest);
	set_ia32_op_type(new_op, ia32_AddrModeD);
	set_ia32_am_flavour(new_op, ia32_B);
	set_ia32_ls_mode(new_op, mode);

	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn));

	return new_op;
}
Matthias Braun's avatar
Matthias Braun committed
1138
#endif
Michael Beck's avatar
Michael Beck committed
1139
1140


1141
// static ir_node *gen_be_Copy(ir_node *irn, arm_code_gen_t *cg) {
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
// 	return new_rd_arm_Copy(env->dbg, env->irg, env->block, op, env->mode);
// }

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

Michael Beck's avatar
Michael Beck committed
1155
1156
1157
/**
 * move constants out of the start block
 */
1158
void arm_move_consts(ir_node *node, void *env) {
Michael Beck's avatar
Michael Beck committed
1159
	arm_code_gen_t *cg = env;
1160
	int i;
Michael Beck's avatar
Michael Beck committed
1161

1162
1163
	if (is_Block(node))
		return;
Michael Beck's avatar
Michael Beck committed
1164

1165
	if (is_Phi(node)) {
Michael Beck's avatar
Michael Beck committed
1166
		for (i = get_irn_arity(node) - 1; i >= 0; --i) {
1167
			ir_node *pred = get_irn_n(node,i);
1168
			ir_opcode pred_code = get_irn_opcode(pred);
1169
			if (pred_code == iro_Const) {
Michael Beck's avatar
Michael Beck committed
1170
1171
1172
				ir_node *block = get_nodes_block(get_irn_n(get_nodes_block(node),i));
				ir_node *nn    = gen_arm_Const(pred, block, cg);
				set_irn_n(node, i, nn);
Michael Beck's avatar
Michael Beck committed
1173
1174
1175
1176
1177
			}
			else if (pred_code == iro_SymConst) {
				/* FIXME: in general, SymConst always require a load, so it
				   might be better to place them into the first real block
				   and let the spiller rematerialize them. */
Michael Beck's avatar
Michael Beck committed
1178
				ident *id = get_sc_ident(pred);
1179
1180
				ir_node *symconst_node;
				symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
Michael Beck's avatar
Michael Beck committed
1181
					current_ir_graph, get_nodes_block(get_irn_n(get_nodes_block(node),i)),
Michael Beck's avatar
Michael Beck committed
1182
					get_irn_mode(pred), id);
1183
1184
1185
1186
1187
				set_irn_n(node, i, symconst_node);
			}
		}
		return;
	}
Michael Beck's avatar
Michael Beck committed
1188
	for (i = 0; i < get_irn_arity(node); i++) {
1189
		ir_node *pred = get_irn_n(node,i);
Michael Beck's avatar