arm_transform.c 36 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* The codegenrator (transform FIRM into arm FIRM */
/* $Id$ */

#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
15
#include "irprintf.h"
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "dbginfo.h"
#include "iropt_t.h"
#include "debug.h"

#include "../benode_t.h"
#include "bearch_arm_t.h"

#include "arm_nodes_attr.h"
#include "../arch/archop.h"     /* we need this for Min and Max nodes */
#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
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
extern ir_op *get_op_Mulh(void);



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

typedef struct vals_ {
Michael Beck's avatar
Michael Beck committed
49
50
51
	int ops;
	unsigned char values[4];
	unsigned char shifts[4];
52
53
} vals;

54
55
56
57
58
59
60
61
/** 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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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;
		}
	}
98
99
}

Michael Beck's avatar
Michael Beck committed
100
101
102
/**
 * Creates a arm_Const node.
 */
103
104
105
106
static ir_node *create_const_node(ir_node *irn, ir_node *block, long value) {
	tarval *tv = new_tarval_from_long(value, mode_Iu);
	dbg_info *dbg = get_irn_dbg_info(irn);
	return new_rd_arm_Mov_i(dbg, current_ir_graph, block, get_irn_mode(irn), tv);
107
108
}

Michael Beck's avatar
Michael Beck committed
109
110
111
/**
 * Creates a arm_Const_Neg node.
 */
112
113
114
115
static ir_node *create_const_neg_node(ir_node *irn, ir_node *block, long value) {
	tarval *tv = new_tarval_from_long(value, mode_Iu);
	dbg_info *dbg = get_irn_dbg_info(irn);
	return new_rd_arm_Mvn_i(dbg, current_ir_graph, block, get_irn_mode(irn), tv);
116
117
}

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

Michael Beck's avatar
Michael Beck committed
120
121
122
123
/**
 * Encodes an immediate with shifter operand
 */
static unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate) {
124
125
126
	return immediate | ((shift>>1)<<8);
}

Michael Beck's avatar
Michael Beck committed
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
 * 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.
 */
140
static ir_node *create_const_graph_value(ir_node *irn, ir_node *block, unsigned int value) {
141
142
	ir_node *result;
	int negate = 0;
Michael Beck's avatar
Michael Beck committed
143
144
	vals v, vn;
	int cnt;
145
146
	ir_mode *mode = get_irn_mode(irn);
	dbg_info *dbg = get_irn_dbg_info(irn);
147

Michael Beck's avatar
Michael Beck committed
148
149
150
151
152
	gen_vals_from_word(value, &v);
	gen_vals_from_word(~value, &vn);

	if (vn.ops < v.ops) {
		/* remove bits */
153
		result = create_const_neg_node(irn, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0]));
Michael Beck's avatar
Michael Beck committed
154
155
156

		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);
157
			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
158
			result = bic_i_node;
159
160
		}
	}
Michael Beck's avatar
Michael Beck committed
161
162
	else {
		/* add bits */
163
		result = create_const_node(irn, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0]));
Michael Beck's avatar
Michael Beck committed
164
165
166

		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);
167
			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
168
169
			result = orr_i_node;
		}
170
171
172
173
	}
	return result;
}

174
175
176
177
178
179
180
181
/**
 * Create a DAG constructing a given Const.
 *
 * @param irn  a Firm const
 */
static ir_node *create_const_graph(ir_node *irn, ir_node *block) {
	int value = get_tarval_long(get_Const_tarval(irn));
	return create_const_graph_value(irn, block, value);
182
183
184
185
}



186
static ir_node *gen_Const(ir_node *irn, arm_code_gen_t *cg) {
187
	ir_node *result;
188
189
190
191
192
193
194
195
196
197
198
199
200
201
	ir_graph *irg = current_ir_graph;
	ir_node *block = get_nodes_block(irn);
	ir_mode *mode = get_irn_mode(irn);
	dbg_info *dbg = get_irn_dbg_info(irn);

	assert(mode != mode_E && "IEEE Extended FP not supported");
	if (mode == mode_F)
		result = new_rd_arm_fConst(dbg, irg, block, mode, get_Const_tarval(irn));
	else if (mode == mode_D)
		result = new_rd_arm_fConst(dbg, irg, block, mode, get_Const_tarval(irn));
	else if (mode == mode_P)
		return irn;
	else
		result = create_const_graph(irn, block);
202
203
204
	return result;
}

205
206
static ir_node *gen_mask(ir_node *irn, ir_node *op, int result_bits) {
	ir_node *block = get_nodes_block(irn);
207
	unsigned mask_bits = (1 << result_bits) - 1;
208
209
210
	ir_node *mask_node = create_const_graph_value(irn, block, mask_bits);
	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);
211
212
}

213
214
static ir_node *gen_sign_extension(ir_node *irn, ir_node *op, int result_bits) {
	ir_node *block = get_nodes_block(irn);
215
	int shift_width = 32 - result_bits;
216
217
218
219
220
	ir_graph *irg = current_ir_graph;
	ir_node *shift_const_node = create_const_graph_value(irn, block, shift_width);
	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));
221
222
223
	return rshift_node;
}

Michael Beck's avatar
Michael Beck committed
224
225
226
227
228
229
/**
 * Transforms a Conv node.
 *
 * @param env   The transformation environment
 * @return the created arm Conv node
 */
230
231
232
233
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);
234
	ir_mode *in_mode = get_irn_mode(op);
235
236
	ir_mode *out_mode = get_irn_mode(irn);
	dbg_info *dbg    = get_irn_dbg_info(irn);
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

	assert( in_mode != mode_E && "");
	assert( in_mode != mode_Ls && "");
	assert( in_mode != mode_Lu && "");
	assert( out_mode != mode_E && "");
	assert( out_mode != mode_Ls && "");
	assert( out_mode != mode_Lu && "");

	if (in_mode == out_mode)
		return op;

	if ((mode_is_int(in_mode) || mode_is_reference(in_mode))
		&& (mode_is_reference(out_mode) || mode_is_int(out_mode))) {
		int in_bits = get_mode_size_bits(in_mode);
		int out_bits = get_mode_size_bits(out_mode);
		int in_sign = get_mode_sign(in_mode);
		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) {
271
				return gen_mask(irn, op, out_bits);
272
			} else {
273
				return gen_sign_extension(irn, op, out_bits);
274
275
276
277
278
279
280
281
282
283
284
285
286
287
			}
		}

		// 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) {
288
				return gen_sign_extension(irn, op, out_bits);
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
			} 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) {
305
				return gen_sign_extension(irn, op, out_bits);
306
			} else {
307
				return gen_mask(irn, op, out_bits);
308
309
310
			}
		}
		assert(0 && "recheck integer conversion logic!");
311
		return irn;
312
	} else if (in_mode == mode_D && out_mode == mode_F) {
313
		return new_rd_arm_fConvD2S(dbg, irg, block, op, out_mode);
314
	} else if (in_mode == mode_F && out_mode == mode_D) {
315
		return new_rd_arm_fConvS2D(dbg, irg, block, op, out_mode);
316
	} else if (mode_is_int(in_mode) && mode_is_float(out_mode)) {
317
318
		cg->have_fp = 1;
		return irn; /* TODO: implement int->float conversion*/
319
	} else if (mode_is_float(in_mode) && mode_is_int(out_mode)) {
320
321
		cg->have_fp = 1;
		return irn; /* TODO: implement float->int conversion*/
322
323
	} else {
		assert(0 && "not implemented conversion");
324
		return irn;
325
326
327
	}
}

Michael Beck's avatar
Michael Beck committed
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
/**
 * 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;
}
345
346
347
348
349
350
351

/**
 * Creates an arm Add.
 *
 * @param env   The transformation environment
 * @return the created arm Add node
 */
352
353
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
354
355
	ir_node *op1 = get_Add_left(irn);
	ir_node *op2 = get_Add_right(irn);
356
357
	ir_mode *mode = get_irn_mode(irn);
	ir_graph *irg = current_ir_graph;
Michael Beck's avatar
Michael Beck committed
358
359
360
	ir_node *op3;
	int v;
	arm_shift_modifier mod;
361
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
362

363
	assert(mode != mode_E && "IEEE Extended FP not supported");
364

365
366
367
	if (mode_is_float(mode)) {
		cg->have_fp = 1;
		return new_rd_arm_fAdd(dbg, irg, block, op1, op2, mode);
368
	}
369
	if (mode_is_numP(mode)) {
Michael Beck's avatar
Michael Beck committed
370
		if (is_arm_Mov_i(op1))
371
			return new_rd_arm_Add_i(dbg, irg, block, op2, mode, get_arm_value(op1));
Michael Beck's avatar
Michael Beck committed
372
		if (is_arm_Mov_i(op2))
373
			return new_rd_arm_Add_i(dbg, irg, block, op1, mode, get_arm_value(op2));
Michael Beck's avatar
Michael Beck committed
374
375
376
377
378
379
380

		/* 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);

381
			return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode);
Michael Beck's avatar
Michael Beck committed
382
383
384
385
386
387
		}
		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);

388
			return new_rd_arm_Mla(dbg, irg, block, op1, op2, op3, mode);
Michael Beck's avatar
Michael Beck committed
389
		}
390

Michael Beck's avatar
Michael Beck committed
391
392
393
394
		/* is the first a shifter */
		v = is_shifter_operand(op1, &mod);
		if (v) {
			op1 = get_irn_n(op1, 0);
395
			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
396
397
398
399
400
		}
		/* is the second a shifter */
		v = is_shifter_operand(op2, &mod);
		if (v) {
			op2 = get_irn_n(op2, 0);
401
			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
402
		}
403

Michael Beck's avatar
Michael Beck committed
404
		/* normal ADD */
405
		return new_rd_arm_Add(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL);
Michael Beck's avatar
Michael Beck committed
406
407
408
409
410
	}

	assert(0 && "unknown mode for add");
	return NULL;
}
411
412
413
414

/**
 * Creates an arm Mul.
 *
Michael Beck's avatar
Michael Beck committed
415
 * @param env   The transformation environment
416
417
 * @return the created arm Mul node
 */
418
419
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
420
421
	ir_node *op1 = get_Mul_left(irn);
	ir_node *op2 = get_Mul_right(irn);
422
423
424
	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
425

426
	assert(mode != mode_E && "IEEE Extended FP not supported");
427

428
429
430
	if (mode_is_float(mode)) {
		cg->have_fp = 1;
		return new_rd_arm_fMul(dbg, irg, block, op1, op2, mode);
431
	}
432
	return new_rd_arm_Mul(dbg, irg, block, op1, op2, mode);
433
434
435
}

/**
Michael Beck's avatar
Michael Beck committed
436
 * Creates an arm floating point Div.
437
 *
Michael Beck's avatar
Michael Beck committed
438
 * @param env   The transformation environment
439
440
 * @return the created arm fDiv node
 */
441
442
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
443
444
	ir_node *op1 = get_Quot_left(irn);
	ir_node *op2 = get_Quot_right(irn);
445
446
	ir_mode *mode = get_irn_mode(irn);
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
447

448
	assert(mode != mode_E && "IEEE Extended FP not supported");
449

450
	return new_rd_arm_fDiv(dbg, current_ir_graph, block, op1, op2, mode);
Michael Beck's avatar
Michael Beck committed
451
452
453
}

#define GEN_INT_OP(op) \
454
455
456
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
457
458
459
460
	ir_node *op1 = get_ ## op ## _left(irn); \
	ir_node *op2 = get_ ## op ## _right(irn); \
	int v; \
	arm_shift_modifier mod; \
461
462
	ir_mode *mode = get_irn_mode(irn); \
	dbg_info *dbg = get_irn_dbg_info(irn); \
Michael Beck's avatar
Michael Beck committed
463
464
 \
	if (is_arm_Mov_i(op1)) \
465
		return new_rd_arm_ ## op ## _i(dbg, irg, block, op2, mode, get_arm_value(op1)); \
Michael Beck's avatar
Michael Beck committed
466
	if (is_arm_Mov_i(op2)) \
467
		return new_rd_arm_ ## op ## _i(dbg, irg, block, op1, mode, get_arm_value(op2)); \
Michael Beck's avatar
Michael Beck committed
468
469
470
471
	/* is the first a shifter */ \
	v = is_shifter_operand(op1, &mod); \
	if (v) { \
		op1 = get_irn_n(op1, 0); \
472
		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
473
474
475
476
477
	} \
	/* is the second a shifter */ \
	v = is_shifter_operand(op2, &mod); \
	if (v) { \
		op2 = get_irn_n(op2, 0); \
478
		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
479
480
	} \
	/* Normal op */ \
481
	return new_rd_arm_ ## op(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL); \
482
483
484
485
486
487
}


/**
 * Creates an arm And.
 *
Michael Beck's avatar
Michael Beck committed
488
 * @param env   The transformation environment
489
490
 * @return the created arm And node
 */
491
static ir_node *gen_And(ir_node *irn, arm_code_gen_t *cg);
Michael Beck's avatar
Michael Beck committed
492
GEN_INT_OP(And)
493
494

/**
Michael Beck's avatar
Michael Beck committed
495
 * Creates an arm Orr.
496
 *
Michael Beck's avatar
Michael Beck committed
497
 * @param env   The transformation environment
498
499
 * @return the created arm Or node
 */
500
static ir_node *gen_Or(ir_node *irn, arm_code_gen_t *cg);
Michael Beck's avatar
Michael Beck committed
501
GEN_INT_OP(Or)
502
503
504
505

/**
 * Creates an arm Eor.
 *
Michael Beck's avatar
Michael Beck committed
506
 * @param env   The transformation environment
507
508
 * @return the created arm Eor node
 */
509
static ir_node *gen_Eor(ir_node *irn, arm_code_gen_t *cg);
Michael Beck's avatar
Michael Beck committed
510
GEN_INT_OP(Eor)
511
512
513
514

/**
 * Creates an arm Sub.
 *
Michael Beck's avatar
Michael Beck committed
515
 * @param env   The transformation environment
516
517
 * @return the created arm Sub node
 */
518
519
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
520
521
522
523
	ir_node *op1 = get_Sub_left(irn);
	ir_node *op2 = get_Sub_right(irn);
	int v;
	arm_shift_modifier mod;
524
525
526
	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
527

528
	assert(mode != mode_E && "IEEE Extended FP not supported");
529

530
531
532
	if (mode_is_float(mode)) {
		cg->have_fp = 1;
		return new_rd_arm_fSub(dbg, irg, block, op1, op2, mode);
Michael Beck's avatar
Michael Beck committed
533
	}
534
	if (mode_is_numP(mode)) {
Michael Beck's avatar
Michael Beck committed
535
		if (is_arm_Mov_i(op1))
536
			return new_rd_arm_Rsb_i(dbg, irg, block, op2, mode, get_arm_value(op1));
Michael Beck's avatar
Michael Beck committed
537
		if (is_arm_Mov_i(op2))
538
			return new_rd_arm_Sub_i(dbg, irg, block, op1, mode, get_arm_value(op2));
Michael Beck's avatar
Michael Beck committed
539
540
541
542
543

		/* is the first a shifter */
		v = is_shifter_operand(op1, &mod);
		if (v) {
			op1 = get_irn_n(op1, 0);
544
			return new_rd_arm_Rsb(dbg, irg, block, op2, op1, mode, mod, new_tarval_from_long(v, mode_Iu));
545
		}
Michael Beck's avatar
Michael Beck committed
546
547
548
549
		/* is the second a shifter */
		v = is_shifter_operand(op2, &mod);
		if (v) {
			op2 = get_irn_n(op2, 0);
550
			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
551
552
		}
		/* normal sub */
553
		return new_rd_arm_Sub(dbg, irg, block, op1, op2, mode, ARM_SHF_NONE, NULL);
554
	}
Michael Beck's avatar
Michael Beck committed
555
556
	assert(0 && "unknown mode for sub");
	return NULL;
557
558
559
560
561
}

/**
 * Creates an arm Shl.
 *
Michael Beck's avatar
Michael Beck committed
562
 * @param env   The transformation environment
563
564
 * @return the created arm Shl node
 */
565
static ir_node *gen_Shl(ir_node *irn, arm_code_gen_t *cg) {
566
	ir_node *result;
567
	ir_node *block = get_nodes_block(irn);
Michael Beck's avatar
Michael Beck committed
568
569
	ir_node *op1 = get_Shl_left(irn);
	ir_node *op2 = get_Shl_right(irn);
570
571
572
	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
573
574

	if (is_arm_Mov_i(op2)) {
575
		result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSL, get_arm_value(op2));
576
	} else {
577
		result = new_rd_arm_Shl(dbg, irg, block, op1, op2, mode);
578
579
580
581
582
583
584
	}
	return result;
}

/**
 * Creates an arm Shr.
 *
Michael Beck's avatar
Michael Beck committed
585
 * @param env   The transformation environment
586
587
 * @return the created arm Shr node
 */
588
static ir_node *gen_Shr(ir_node *irn, arm_code_gen_t *cg) {
589
	ir_node *result;
590
	ir_node *block = get_nodes_block(irn);
Michael Beck's avatar
Michael Beck committed
591
592
	ir_node *op1 = get_Shr_left(irn);
	ir_node *op2 = get_Shr_right(irn);
593
594
595
	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
596
597

	if (is_arm_Mov_i(op2)) {
598
		result = new_rd_arm_Mov(dbg, irg, block, op1, mode, ARM_SHF_LSR, get_arm_value(op2));
599
	} else {
600
		result = new_rd_arm_Shr(dbg, irg, block, op1, op2, mode);
601
602
603
604
605
606
607
	}
	return result;
}

/**
 * Creates an arm Shrs.
 *
Michael Beck's avatar
Michael Beck committed
608
 * @param env   The transformation environment
609
610
 * @return the created arm Shrs node
 */
611
static ir_node *gen_Shrs(ir_node *irn, arm_code_gen_t *cg) {
612
	ir_node *result;
613
	ir_node *block = get_nodes_block(irn);
Michael Beck's avatar
Michael Beck committed
614
615
	ir_node *op1 = get_Shrs_left(irn);
	ir_node *op2 = get_Shrs_right(irn);
616
617
	ir_mode *mode = get_irn_mode(irn);
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
618
619

	if (is_arm_Mov_i(op2)) {
620
		result = new_rd_arm_Mov(dbg, current_ir_graph, block, op1, mode, ARM_SHF_ASR, get_arm_value(op2));
621
	} else {
622
		result = new_rd_arm_Shrs(dbg, current_ir_graph, block, op1, op2, mode);
623
624
625
626
627
628
629
	}
	return result;
}

/**
 * Transforms a Not node.
 *
Michael Beck's avatar
Michael Beck committed
630
 * @param env   The transformation environment
631
632
 * @return the created arm Not node
 */
633
634
635
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
636
637
638
	int v;
	arm_shift_modifier mod = ARM_SHF_NONE;
	tarval  *tv = NULL;
639
	dbg_info *dbg = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
640
641
642
643
644
645

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

Michael Beck's avatar
Michael Beck committed
649
650
651
652
653
654
/**
 * Transforms an Abs node.
 *
 * @param env   The transformation environment
 * @return the created arm Abs node
 */
655
656
657
658
659
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);
660

661
	assert(mode != mode_E && "IEEE Extended FP not supported");
662

663
664
665
	if (mode_is_float(mode)) {
		cg->have_fp = 1;
		return new_rd_arm_fAbs(dbg, current_ir_graph, block, op, mode);
666
	}
667
	return new_rd_arm_Abs(dbg, current_ir_graph, block, op, mode);
668
669
670
671
672
}

/**
 * Transforms a Minus node.
 *
Michael Beck's avatar
Michael Beck committed
673
 * @param env   The transformation environment
674
675
 * @return the created arm Minus node
 */
676
677
678
679
680
681
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
682

683
684
	if (mode_is_float(mode)) {
		return new_rd_arm_fNeg(dbg, irg, block, op, mode);
685
	}
686
	return new_rd_arm_Rsb_i(dbg, irg, block, op, mode, get_mode_null(mode));
687
688
689
690
691
692
693
694
695
696
697
}

/**
 * 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
 */
698
699
700
701
702
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);
703

Michael Beck's avatar
Michael Beck committed
704
	if (mode_is_float(mode)) {
705
		cg->have_fp = 1;
Michael Beck's avatar
Michael Beck committed
706
		/* FIXME: set the load mode */
707
		return new_rd_arm_fLoad(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn), mode_T);
708
709
	}
	if (mode == mode_Bu) {
710
		return new_rd_arm_Loadb(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn), mode_T);
711
712
	}
	if (mode == mode_Bs) {
713
		return new_rd_arm_Loadbs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn), mode_T);
714
715
	}
	if (mode == mode_Hu) {
716
		return new_rd_arm_Loadh(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn), mode_T);
717
718
	}
	if (mode == mode_Hs) {
719
		return new_rd_arm_Loadhs(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn), mode_T);
720
721
	}
	if (mode_is_reference(mode)) {
722
		return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn), mode_T);
723
	}
724
	return new_rd_arm_Load(dbg, irg, block, get_Load_ptr(irn), get_Load_mem(irn), mode_T);
725
726
727
728
729
730
731
732
733
734
735
}

/**
 * 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
 */
736
737
738
739
740
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);
741

742
	assert(mode != mode_E && "IEEE Extended FP not supported");
Michael Beck's avatar
Michael Beck committed
743
	if (mode_is_float(mode)) {
744
		cg->have_fp = 1;
Michael Beck's avatar
Michael Beck committed
745
		/* FIXME: set the store mode */
746
		return new_rd_arm_fStore(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn), mode_T);
747
748
	}
	if (mode == mode_Bu) {
749
		return new_rd_arm_Storeb(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn), mode_T);
750
751
	}
	if (mode == mode_Bs) {
752
		return new_rd_arm_Storebs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn), mode_T);
753
754
	}
	if (mode == mode_Hu) {
755
		return new_rd_arm_Storeh(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn), mode_T);
756
757
	}
	if (mode == mode_Hs) {
758
		return new_rd_arm_Storehs(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn), mode_T);
759
	}
760
	return new_rd_arm_Store(dbg, irg, block, get_Store_ptr(irn), get_Store_value(irn), get_Store_mem(irn), mode_T);
761
762
763
}


764
static ir_node *gen_Cond(ir_node *irn, arm_code_gen_t *cg) {
Christian Würdig's avatar
Christian Würdig committed
765
	ir_node *result   = NULL;
766
767
768
769
	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
770

771
772
773
774
775
776
	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);
777
		result = new_rd_arm_CondJmp(dbg, irg, block, op1, op2, mode_T);
778
779
780
		set_arm_proj_num(result, get_Proj_proj(proj_node));
	} else {
		//SwitchJmp
781
		ir_node *op = get_irn_n(irn, 0);
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
		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);
		}


823
824
825
826
		const_node = new_rd_Const(dbg, irg, block, mode_Iu, new_tarval_from_long(translation, mode_Iu));
		const_graph = gen_Const(const_node, cg);
		sub = new_rd_arm_Sub(dbg, irg, block, op, const_graph, get_irn_mode(op), ARM_SHF_NONE, NULL);
		result = new_rd_arm_SwitchJmp(dbg, irg, block, sub, mode_T);
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
		set_arm_n_projs(result, n_projs);
		set_arm_default_proj_num(result, get_Cond_defaultProj(irn)-translation);
	}
	return result;
}

/**
 * Returns the name of a SymConst.
 * @param symc  the SymConst
 * @return name of the SymConst
 */
const char *get_sc_name(ir_node *symc) {
	if (get_irn_opcode(symc) != iro_SymConst)
		return "NONE";

	switch (get_SymConst_kind(symc)) {
		case symconst_addr_name:
			return get_id_str(get_SymConst_name(symc));

		case symconst_addr_ent:
			return get_entity_ld_name(get_SymConst_entity(symc));

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

	return NULL;
}

856
857
858
859
860
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);
	return new_rd_arm_SymConst(dbg, current_ir_graph, block, mode, get_sc_name(irn));
861
862
863
864
865
866
867
868
869
870
}



/**
 * Transforms a CopyB node.
 *
 * @param env   The transformation environment
 * @return The transformed node.
 */
871
static ir_node *gen_CopyB(ir_node *irn, arm_code_gen_t *cg) {
872
	ir_node  *res   = NULL;
873
874
875
876
877
878
879
880
	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;
881
882
883
	ir_node *src_copy;
	ir_node *dst_copy;

Michael Beck's avatar
Michael Beck committed
884
885
	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);
886
887
888
889
890
891
892
893
894
895
896

 	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
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
/********************************************
 *  _                          _
 * | |                        | |
 * | |__   ___ _ __   ___   __| | ___  ___
 * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
 * | |_) |  __/ | | | (_) | (_| |  __/\__ \
 * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
 *
 ********************************************/

/**
 * 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) {
	unsigned offset    = be_get_IncSP_offset(inc_sp);
	be_stack_dir_t dir = be_get_IncSP_direction(inc_sp);

	if (offset == BE_STACK_FRAME_SIZE)
		return 0;
	return dir == be_stack_dir_expand ? (int)offset : -(int)offset;
}

924
static ir_node *gen_StackParam(ir_node *irn, arm_code_gen_t *cg) {
Michael Beck's avatar
Michael Beck committed
925
926
#if 0
	ir_node *new_op = NULL;
927
	ir_node *block  = get_nodes_block(irn);
Michael Beck's avatar
Michael Beck committed
928
929
	ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
	ir_node *mem    = new_rd_NoMem(env->irg);
930
931
	ir_node *ptr    = get_irn_n(irn, 0);
	entity  *ent    = be_get_frame_entity(irn);
Michael Beck's avatar
Michael Beck committed
932
933
934
935
936
937
938
939
940
941
	ir_mode *mode   = env->mode;

//	/* 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))
942
			new_op = new_rd_ia32_fLoad(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
Michael Beck's avatar
Michael Beck committed
943
944
		else {
			env->cg->used_x87 = 1;
945
			new_op = new_rd_ia32_vfld(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
Michael Beck's avatar
Michael Beck committed
946
947
948
		}
	}
	else {
949
		new_op = new_rd_ia32_Load(env->dbg, env->irg, block, ptr, noreg, mem, mode_T);
Michael Beck's avatar
Michael Beck committed
950
951
952
953
954
955
956
957
958
959
960
961
	}

	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));

962
	return new_rd_Proj(env->dbg, env->irg, block, new_op, mode, 0);
Michael Beck's avatar
Michael Beck committed
963
964
965
966
967
968
#endif
}

/**
 * Transforms a FrameAddr into an ia32 Add.
 */
969
970
971
static ir_node *gen_be_FrameAddr(ir_node *irn, arm_code_gen_t *cg) {
	ir_node *block  = get_nodes_block(irn);
	entity  *ent    = be_get_frame_entity(irn);
Michael Beck's avatar
Michael Beck committed
972
	int     offset  = get_entity_offset_bytes(ent);
973
	ir_node *op     = get_irn_n(irn, 0);
Michael Beck's avatar
Michael Beck committed
974
	ir_node *cnst;
975
976
	ir_mode *mode   = get_irn_mode(irn);
	dbg_info *dbg   = get_irn_dbg_info(irn);
Michael Beck's avatar
Michael Beck committed
977
978
979
980
981
982

	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);
	}
983
984
985
986
	cnst = create_const_graph_value(irn, block, (unsigned)offset);
	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
987
988
989
990
991
}

/**
 * Transforms a FrameLoad into an ia32 Load.
 */
992
static ir_node *gen_FrameLoad(ir_node *irn, arm_code_gen_t *cg) {
Michael Beck's avatar
Michael Beck committed
993
994
995
#if 0
	ir_node *new_op = NULL;
	ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
996
997
998
	ir_node *mem    = get_irn_n(irn, 0);
	ir_node *ptr    = get_irn_n(irn, 1);
	entity  *ent    = be_get_frame_entity(irn);
Michael Beck's avatar
Michael Beck committed
999
1000
1001
1002
	ir_mode *mode   = get_type_mode(get_entity_type(ent));

	if (mode_is_float(mode)) {
		if (USE_SSE2(env->cg))
1003
			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
1004
1005
		else {
			env->cg->used_x87 = 1;
1006
			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
1007
1008
1009
		}
	}
	else {
1010
		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
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
	}

	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;
#endif
}


/**
 * Transforms a FrameStore into an ia32 Store.
 */
1031
static ir_node *gen_FrameStore(ir_node *irn, arm_code_gen_t *cg) {
Michael Beck's avatar
Michael Beck committed
1032
1033
1034
#if 0
	ir_node *new_op = NULL;
	ir_node *noreg  = ia32_new_NoReg_gp(env->cg);
1035
1036
1037
1038
	ir_node *mem    = get_irn_n(irn, 0);
	ir_node *ptr    = get_irn_n(irn, 1);
	ir_node *val    = get_irn_n(irn, 2);
	entity  *ent    = be_get_frame_entity(irn);
Michael Beck's avatar
Michael Beck committed
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
	ir_mode *mode   = get_irn_mode(val);

	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;
#endif
}


1071
// static ir_node *gen_be_Copy(ir_node *irn, arm_code_gen_t *cg) {
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
// 	return new_rd_arm_Copy(env->dbg, env->irg, env->block, op, env->mode);
// }

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

/************************************************************************/
/* move constants out of startblock                                       */
/************************************************************************/
void arm_move_consts(ir_node *node, void *env) {
	arm_code_gen_t *cgenv = (arm_code_gen_t *)env;
	int i;
Michael Beck's avatar
Michael Beck committed
1091

1092
1093
	if (is_Block(node))
		return;
Michael Beck's avatar
Michael Beck committed
1094

1095
	if (is_Phi(node)) {
Michael Beck's avatar
Michael Beck committed
1096
		for (i = 0; i < get_irn_arity(node); i++) {
1097
1098
1099
1100
			ir_node *pred = get_irn_n(node,i);
			opcode pred_code = get_irn_opcode(pred);
			if (pred_code == iro_Const) {
				ir_node *const_graph;
1101
				const_graph = create_const_graph(pred, get_nodes_block(get_irn_n(get_nodes_block(node),i)));
1102
1103
1104
1105
1106
				set_irn_n(node, i, const_graph);
			} else if (pred_code == iro_SymConst) {
				const char *str = get_sc_name(pred);
				ir_node *symconst_node;
				symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
Michael Beck's avatar
Michael Beck committed
1107
1108
					current_ir_graph, get_nodes_block(get_irn_n(get_nodes_block(node),i)),
					get_irn_mode(pred), str);
1109
1110
1111
1112
1113
				set_irn_n(node, i, symconst_node);
			}
		}
		return;
	}
Michael Beck's avatar
Michael Beck committed
1114
	for (i = 0; i < get_irn_arity(node); i++) {
1115
1116
1117
1118
		ir_node *pred = get_irn_n(node,i);
		opcode pred_code = get_irn_opcode(pred);
		if (pred_code == iro_Const) {
			ir_node *const_graph;
1119
			const_graph = create_const_graph(pred, get_nodes_block(node));
1120
1121
1122
1123
1124
			set_irn_n(node, i, const_graph);
		} else if (pred_code == iro_SymConst) {
			const char *str = get_sc_name(pred);
			ir_node *symconst_node;
			symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
Michael Beck's avatar
Michael Beck committed
1125
1126
				current_ir_graph, get_nodes_block(node),
				get_irn_mode(pred), str);
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
			set_irn_n(node, i, symconst_node);
		}
	}
}


/************************************************************************/
/* move symbolic constants out of startblock                            */
/************************************************************************/
void arm_move_symconsts(ir_node *node, void *env) {
	int i;
Christian Würdig's avatar
Christian Würdig committed
1138

1139
1140
	if (is_Block(node))
		return;
Christian Würdig's avatar
Christian Würdig committed
1141

Michael Beck's avatar
Michael Beck committed
1142
	for (i = 0; i < get_irn_arity(node); i++) {
Christian Würdig's avatar
Christian Würdig committed
1143
1144
1145
		ir_node *pred      = get_irn_n(node,i);
		opcode   pred_code = get_irn_opcode(pred);

1146
1147
		if (pred_code == iro_SymConst) {
			const char *str = get_sc_name(pred);
Christian Würdig's avatar
Christian Würdig committed
1148
1149
			ir_node    *symconst_node;

1150
			symconst_node = new_rd_arm_SymConst(get_irn_dbg_info(pred),
Michael Beck's avatar
Michael Beck committed
1151
				current_ir_graph, get_nodes_block(node), get_irn_mode(pred), str);
1152
1153
1154
1155
1156
			set_irn_n(node, i, symconst_node);
		}
	}
}

Michael Beck's avatar
Michael Beck committed
1157
1158
1159
/**
 * the BAD transformer.
 */
1160
1161
static ir_node *bad_transform(ir_node *irn, arm_code_gen_t *cg) {
	ir_fprintf(stderr, "Not implemented: %+F\n", irn);
Michael Beck's avatar
Michael Beck committed
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
	assert(0);
	return NULL;
}

/**
 * Enters all transform functions into the generic pointer
 */
void arm_register_transformers(void) {
	ir_op *op_Max, *op_Min, *op_Mulh;

	/* first clear the generic function pointer for all ops */
	clear_irp_opcodes_generic_func();

#define FIRM_OP(a)     op_##a->ops.generic = (op_func)gen_##a
#define BAD(a)         op_##a->ops.generic = (op_func)bad_transform
#define IGN(a)

	FIRM_OP(Add);  // done
	FIRM_OP(Mul);  // done
	FIRM_OP(Quot); // done
	FIRM_OP(And);  // done
	FIRM_OP(Or);   // done
	FIRM_OP(Eor);  // done

	FIRM_OP(Sub);  // done
	FIRM_OP(Shl);  // done
	FIRM_OP(Shr);  // done
	FIRM_OP(Shrs); // done

	FIRM_OP(Minus); // done
	FIRM_OP(Not);   // done
	FIRM_OP(Abs);   // done

	FIRM_OP(CopyB); // done
	FIRM_OP(Const); // TODO: floating point consts
	FIRM_OP(Conv); // TODO: floating point conversions

	FIRM_OP(Load);   // done
	FIRM_OP(Store);  // done

	FIRM_OP(SymConst);
	FIRM_OP(Cond);	  // integer done

	/* TODO: implement these nodes */

	IGN(Div);    // intrinsic lowering
	IGN(Mod);    // intrinsic lowering
	IGN(DivMod); // TODO: implement DivMod

	IGN(Mux);
	IGN(Unknown);
	IGN(Cmp);     // done, implemented in cond

	/* You probably don't need to handle the following nodes */

	IGN(Call);
	IGN(Proj);
	IGN(Alloc);

	IGN(Block);
	IGN(Start);
	IGN(End);
	IGN(NoMem);
	IGN(Phi);
	IGN(IJmp);
	IGN(Jmp);     // emitter done
	IGN(Break);
	IGN(Sync);

	BAD(Raise);
	BAD(Sel);
	BAD(InstOf);
	BAD(Cast);
	BAD(Free);
	BAD(Tuple);
	BAD(Id);
	BAD(Bad);
	BAD(Confirm);
	BAD(Filter);
	BAD(CallBegin);
	BAD(EndReg);
	BAD(EndExcept);

	FIRM_OP(be_FrameAddr);

	op_Max = get_op_Max();
	if (op_Max)
		BAD(Max);
	op_Min = get_op_Min();
	if (op_Min)
		BAD(Min);
	op_Mulh = get_op_Mulh();
	if (op_Mulh)
		BAD(Mulh);

#undef IGN
#undef FIRM_OP
#undef BAD
}

1262
typedef ir_node *(transform_func)(ir_node *irn, arm_code_gen_t *cg);
1263
1264
1265
1266
1267
1268
1269
1270
1271

/**
 * Transforms the given firm node (and maybe some other related nodes)
 * into one or more assembler nodes.
 *
 * @param node    the firm node
 * @param env     the debug module
 */
void arm_transform_node(ir_node *node, void *env) {
Michael Beck's avatar
Michael Beck committed
1272
1273
1274
	arm_code_gen_t *cg = (arm_code_gen_t *)env;
	ir_op *op          = get_irn_op(node);
	ir_node *asm_node  = NULL;
1275

Michael Beck's avatar
Michael Beck committed
1276
	if (op == op_Block)
1277
1278
		return;

Michael Beck's avatar
Michael Beck committed
1279
	DBG((cg->mod, LEVEL_1, "check %+F ... ", node));
1280

Michael Beck's avatar
Michael Beck committed
1281
1282
1283
	if (op->ops.generic) {
		transform_func *transform = (transform_func *)op->ops.generic;

1284
		asm_node = (*transform)(node, cg);
1285
1286
1287
1288
	}

	if (asm_node) {
		exchange(node, asm_node);
Michael Beck's avatar
Michael Beck committed
1289
		DB((cg->mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));