arm_transform.c 44.4 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

20
21
/**
 * @file
Michael Beck's avatar
Michael Beck committed
22
23
 * @brief   The codegenerator (transform FIRM into arm FIRM)
 * @author  Oliver Richter, Tobias Gneist, Michael Beck
24
25
 * @version $Id$
 */
26
27
28
29
30
31
32
33
34
#include "config.h"

#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
#include "irgmod.h"
#include "iredges.h"
#include "irvrfy.h"
#include "ircons.h"
Michael Beck's avatar
Michael Beck committed
35
#include "irprintf.h"
36
37
38
#include "dbginfo.h"
#include "iropt_t.h"
#include "debug.h"
Michael Beck's avatar
Michael Beck committed
39
#include "error.h"
40

41
#include "../benode.h"
42
#include "../beirg.h"
43
#include "../beutil.h"
44
#include "../betranshlp.h"
45
46
47
48
#include "bearch_arm_t.h"

#include "arm_nodes_attr.h"
#include "arm_transform.h"
49
#include "arm_optimize.h"
50
51
52
53
54
55
56
#include "arm_new_nodes.h"
#include "arm_map_regs.h"

#include "gen_arm_regalloc_if.h"

#include <limits.h>

57
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
Michael Beck's avatar
Michael Beck committed
58

59
60
/** hold the current code generator during transformation */
static arm_code_gen_t *env_cg;
61

62
63
static inline int mode_needs_gp_reg(ir_mode *mode)
{
64
	return mode_is_int(mode) || mode_is_reference(mode);
65
66
}

Michael Beck's avatar
Michael Beck committed
67
68
69
/**
 * Creates a possible DAG for an constant.
 */
70
71
72
static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
                                         unsigned int value)
{
73
	ir_node *result;
74
	arm_vals v, vn;
Michael Beck's avatar
Michael Beck committed
75
	int cnt;
76

77
78
	arm_gen_vals_from_word(value, &v);
	arm_gen_vals_from_word(~value, &vn);
Michael Beck's avatar
Michael Beck committed
79
80
81

	if (vn.ops < v.ops) {
		/* remove bits */
82
83
		result = new_bd_arm_Mvn_imm(dbgi, block, vn.values[0], vn.rors[0]);
		be_dep_on_frame(result);
Michael Beck's avatar
Michael Beck committed
84
85

		for (cnt = 1; cnt < vn.ops; ++cnt) {
86
87
			result = new_bd_arm_Bic_imm(dbgi, block, result,
			                            vn.values[cnt], vn.rors[cnt]);
88
		}
89
	} else {
Michael Beck's avatar
Michael Beck committed
90
		/* add bits */
91
92
		result = new_bd_arm_Mov_imm(dbgi, block, v.values[0], v.rors[0]);
		be_dep_on_frame(result);
Michael Beck's avatar
Michael Beck committed
93
94

		for (cnt = 1; cnt < v.ops; ++cnt) {
95
96
			result = new_bd_arm_Or_imm(dbgi, block, result,
			                           v.values[cnt], v.rors[cnt]);
Michael Beck's avatar
Michael Beck committed
97
		}
98
99
100
101
	}
	return result;
}

102
103
104
105
106
/**
 * Create a DAG constructing a given Const.
 *
 * @param irn  a Firm const
 */
107
108
static ir_node *create_const_graph(ir_node *irn, ir_node *block)
{
109
110
	tarval  *tv = get_Const_tarval(irn);
	ir_mode *mode = get_tarval_mode(tv);
111
	unsigned value;
112
113
114
115
116
117
118

	if (mode_is_reference(mode)) {
		/* ARM is 32bit, so we can safely convert a reference tarval into Iu */
		assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Iu));
		tv = tarval_convert_to(tv, mode_Iu);
	}
	value = get_tarval_long(tv);
119
	return create_const_graph_value(get_irn_dbg_info(irn), block, value);
120
121
}

Michael Beck's avatar
Michael Beck committed
122
/**
Michael Beck's avatar
Michael Beck committed
123
124
125
126
127
128
 * Create an And that will zero out upper bits.
 *
 * @param dbgi     debug info
 * @param block    the basic block
 * @param op       the original node
 * param src_bits  number of lower bits that will remain
Michael Beck's avatar
Michael Beck committed
129
 */
130
131
132
133
134
135
136
137
138
139
140
141
static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                                   int src_bits)
{
	if (src_bits == 8) {
		return new_bd_arm_And_imm(dbgi, block, op, 0xFF, 0);
	} else if (src_bits == 16) {
		ir_node *lshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, 16);
		ir_node *rshift = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift, ARM_SHF_LSR_IMM, 16);
		return rshift;
	} else {
		panic("zero extension only supported for 8 and 16 bits");
	}
142
143
}

Michael Beck's avatar
Michael Beck committed
144
145
146
/**
 * Generate code for a sign extension.
 */
147
148
149
150
151
152
static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                                   int src_bits)
{
	int shift_width = 32 - src_bits;
	ir_node *lshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, op, ARM_SHF_LSL_IMM, shift_width);
	ir_node *rshift_node = new_bd_arm_Mov_reg_shift_imm(dbgi, block, lshift_node, ARM_SHF_ASR_IMM, shift_width);
153
154
155
	return rshift_node;
}

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                              ir_mode *orig_mode)
{
	int bits = get_mode_size_bits(orig_mode);
	if (bits == 32)
		return op;

	if (mode_is_signed(orig_mode)) {
		return gen_sign_extension(dbgi, block, op, bits);
	} else {
		return gen_zero_extension(dbgi, block, op, bits);
	}
}

/**
 * returns true if it is assured, that the upper bits of a node are "clean"
 * which means for a 16 or 8 bit value, that the upper bits in the register
 * are 0 for unsigned and a copy of the last significant bit for signed
 * numbers.
 */
static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
{
	(void) transformed_node;
	(void) mode;
	/* TODO */
	return false;
}

Michael Beck's avatar
Michael Beck committed
184
185
186
/**
 * Transforms a Conv node.
 *
187
 * @return The created ia32 Conv node
Michael Beck's avatar
Michael Beck committed
188
 */
189
190
static ir_node *gen_Conv(ir_node *node)
{
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *op       = get_Conv_op(node);
	ir_node  *new_op   = be_transform_node(op);
	ir_mode  *src_mode = get_irn_mode(op);
	ir_mode  *dst_mode = get_irn_mode(node);
	dbg_info *dbg      = get_irn_dbg_info(node);

	if (src_mode == dst_mode)
		return new_op;

	if (mode_is_float(src_mode) || mode_is_float(dst_mode)) {
		env_cg->have_fp_insn = 1;

		if (USE_FPA(env_cg->isa)) {
			if (mode_is_float(src_mode)) {
				if (mode_is_float(dst_mode)) {
Michael Beck's avatar
Michael Beck committed
207
					/* from float to float */
208
					return new_bd_arm_fpaMvf(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
209
210
211
				}
				else {
					/* from float to int */
212
					return new_bd_arm_fpaFix(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
213
214
215
216
				}
			}
			else {
				/* from int to float */
217
				return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
218
			}
219
		} else if (USE_VFP(env_cg->isa)) {
220
			panic("VFP not supported yet");
221
		} else {
222
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
223
		}
224
	} else { /* complete in gp registers */
225
226
		int src_bits = get_mode_size_bits(src_mode);
		int dst_bits = get_mode_size_bits(dst_mode);
Michael Beck's avatar
Michael Beck committed
227
228
		int min_bits;
		ir_mode *min_mode;
229

Michael Beck's avatar
Michael Beck committed
230
231
232
		if (src_bits == dst_bits) {
			/* kill unneccessary conv */
			return new_op;
233
234
235
236
237
		}

		if (src_bits < dst_bits) {
			min_bits = src_bits;
			min_mode = src_mode;
Michael Beck's avatar
Michael Beck committed
238
		} else {
239
240
241
242
243
244
245
246
247
248
249
250
			min_bits = dst_bits;
			min_mode = dst_mode;
		}

		if (upper_bits_clean(new_op, min_mode)) {
			return new_op;
		}

		if (mode_is_signed(min_mode)) {
			return gen_sign_extension(dbg, block, new_op, min_bits);
		} else {
			return gen_zero_extension(dbg, block, new_op, min_bits);
251
252
253
254
		}
	}
}

255
256
257
258
259
260
261
typedef struct {
	unsigned char  imm_8;
	unsigned char  rot;
} arm_immediate_t;

static bool try_encode_as_immediate(const ir_node *node, arm_immediate_t *res)
{
Michael Beck's avatar
Michael Beck committed
262
	unsigned val, low_pos, high_pos;
263
264
265

	if (!is_Const(node))
		return false;
Michael Beck's avatar
Michael Beck committed
266

267
	val = get_tarval_long(get_Const_tarval(node));
Michael Beck's avatar
Michael Beck committed
268

269
270
271
272
273
274
275
276
277
	if (val == 0) {
		res->imm_8 = 0;
		res->rot   = 0;
		return true;
	}
	if (val <= 0xff) {
		res->imm_8 = val;
		res->rot   = 0;
		return true;
Michael Beck's avatar
Michael Beck committed
278
	}
279
280
281
282
283
284
285
	/* arm allows to use to rotate an 8bit immediate value by a multiple of 2
	   (= 0, 2, 4, 6, ...).
	   So we determine the smallest even position with a bit set
	   and the highest even position with no bit set anymore.
	   If the difference between these 2 is <= 8, then we can encode the value
	   as immediate.
	 */
Michael Beck's avatar
Michael Beck committed
286
287
	low_pos  = ntz(val) & ~1u;
	high_pos = (32-nlz(val)+1) & ~1u;
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306

	if (high_pos - low_pos <= 8) {
		res->imm_8 = val >> low_pos;
		res->rot   = 32 - low_pos;
		return true;
	}

	if (high_pos > 24) {
		res->rot = 34 - high_pos;
		val      = val >> (32-res->rot) | val << (res->rot);
		if (val <= 0xff) {
			res->imm_8 = val;
			return true;
		}
	}

	return false;
}

307
static bool is_downconv(const ir_node *node)
308
309
310
311
312
{
	ir_mode *src_mode;
	ir_mode *dest_mode;

	if (!is_Conv(node))
313
		return false;
314
315
316
317
318

	/* we only want to skip the conv when we're the only user
	 * (not optimal but for now...)
	 */
	if (get_irn_n_edges(node) > 1)
319
		return false;
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373

	src_mode  = get_irn_mode(get_Conv_op(node));
	dest_mode = get_irn_mode(node);
	return
		mode_needs_gp_reg(src_mode)  &&
		mode_needs_gp_reg(dest_mode) &&
		get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
}

static ir_node *arm_skip_downconv(ir_node *node)
{
	while (is_downconv(node))
		node = get_Conv_op(node);
	return node;
}

typedef enum {
	MATCH_NONE         = 0,
	MATCH_COMMUTATIVE  = 1 << 0,
	MATCH_SIZE_NEUTRAL = 1 << 1,
} match_flags_t;

typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, unsigned char imm8, unsigned char imm_rot);

static ir_node *gen_int_binop(ir_node *node, match_flags_t flags,
		new_binop_reg_func new_reg, new_binop_imm_func new_imm)
{
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_binop_left(node);
	ir_node  *new_op1;
	ir_node  *op2     = get_binop_right(node);
	ir_node  *new_op2;
	dbg_info *dbgi    = get_irn_dbg_info(node);
	arm_immediate_t imm;

	if (flags & MATCH_SIZE_NEUTRAL) {
		op1 = arm_skip_downconv(op1);
		op2 = arm_skip_downconv(op2);
	} else {
		assert(get_mode_size_bits(get_irn_mode(node)) == 32);
	}

	if (try_encode_as_immediate(op2, &imm)) {
		ir_node *new_op1 = be_transform_node(op1);
		return new_imm(dbgi, block, new_op1, imm.imm_8, imm.rot);
	}
	new_op2 = be_transform_node(op2);
    if ((flags & MATCH_COMMUTATIVE) && try_encode_as_immediate(op1, &imm)) {
		return new_imm(dbgi, block, new_op2, imm.imm_8, imm.rot);
	}
	new_op1 = be_transform_node(op1);

	return new_reg(dbgi, block, new_op1, new_op2);
Michael Beck's avatar
Michael Beck committed
374
}
375
376

/**
377
 * Creates an ARM Add.
378
379
380
 *
 * @return the created arm Add node
 */
381
382
static ir_node *gen_Add(ir_node *node)
{
383
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
384

385
	if (mode_is_float(mode)) {
386
387
388
389
390
391
		ir_node  *block   = be_transform_node(get_nodes_block(node));
		ir_node  *op1     = get_Add_left(node);
		ir_node  *op2     = get_Add_right(node);
		dbg_info *dbgi    = get_irn_dbg_info(node);
		ir_node  *new_op1 = be_transform_node(op1);
		ir_node  *new_op2 = be_transform_node(op2);
392
		env_cg->have_fp_insn = 1;
393
		if (USE_FPA(env_cg->isa)) {
394
#if 0
395
			if (is_arm_fpaMvf_i(new_op1))
396
				return new_bd_arm_fpaAdf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
397
			if (is_arm_fpaMvf_i(new_op2))
398
399
400
				return new_bd_arm_fpaAdf_i(dbgi, block, new_op1, mode, get_arm_imm_value(new_op2));
#endif
			return new_bd_arm_fpaAdf(dbgi, block, new_op1, new_op2, mode);
401
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
402
			assert(mode != mode_E && "IEEE Extended FP not supported");
403
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
404
		}
405
		else {
406
			panic("Softfloat not supported yet");
407
408
		}
	} else {
409
#if 0
Michael Beck's avatar
Michael Beck committed
410
		/* check for MLA */
Michael Beck's avatar
Michael Beck committed
411
		if (is_arm_Mul(new_op1) && get_irn_n_edges(op1) == 1) {
412
			new_op3 = new_op2;
Michael Beck's avatar
Michael Beck committed
413
414
			new_op2 = get_irn_n(new_op1, 1);
			new_op1 = get_irn_n(new_op1, 0);
Michael Beck's avatar
Michael Beck committed
415

416
			return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
Michael Beck's avatar
Michael Beck committed
417
		}
Michael Beck's avatar
Michael Beck committed
418
		if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
419
420
421
			new_op3 = new_op1;
			new_op1 = get_irn_n(new_op2, 0);
			new_op2 = get_irn_n(new_op2, 1);
Michael Beck's avatar
Michael Beck committed
422

423
			return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
Michael Beck's avatar
Michael Beck committed
424
		}
425
#endif
426

427
428
		return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
				new_bd_arm_Add_reg, new_bd_arm_Add_imm);
Michael Beck's avatar
Michael Beck committed
429
430
	}
}
431
432

/**
433
 * Creates an ARM Mul.
434
435
436
 *
 * @return the created arm Mul node
 */
437
438
static ir_node *gen_Mul(ir_node *node)
{
439
440
441
442
443
444
445
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_Mul_left(node);
	ir_node  *new_op1 = be_transform_node(op1);
	ir_node  *op2     = get_Mul_right(node);
	ir_node  *new_op2 = be_transform_node(op2);
	ir_mode  *mode    = get_irn_mode(node);
	dbg_info *dbg     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
446

447
	if (mode_is_float(mode)) {
448
		env_cg->have_fp_insn = 1;
449
		if (USE_FPA(env_cg->isa)) {
450
#if 0
451
			if (is_arm_Mov_i(new_op1))
452
				return new_bd_arm_fpaMuf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
453
			if (is_arm_Mov_i(new_op2))
454
				return new_bd_arm_fpaMuf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
455
#endif
456
			return new_bd_arm_fpaMuf(dbg, block, new_op1, new_op2, mode);
457
		}
458
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
459
			assert(mode != mode_E && "IEEE Extended FP not supported");
460
			panic("VFP not supported yet");
461
462
		}
		else {
463
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
464
		}
465
	}
466
	assert(mode_is_data(mode));
467
	return new_bd_arm_Mul(dbg, block, new_op1, new_op2);
468
469
470
}

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

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

488
	env_cg->have_fp_insn = 1;
489
	if (USE_FPA(env_cg->isa)) {
490
#if 0
491
		if (is_arm_Mov_i(new_op1))
492
			return new_bd_arm_fpaRdf_i(dbg, block, new_op2, mode, get_arm_imm_value(new_op1));
493
		if (is_arm_Mov_i(new_op2))
494
			return new_bd_arm_fpaDvf_i(dbg, block, new_op1, mode, get_arm_imm_value(new_op2));
495
#endif
496
		return new_bd_arm_fpaDvf(dbg, block, new_op1, new_op2, mode);
497
	} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
498
		assert(mode != mode_E && "IEEE Extended FP not supported");
499
		panic("VFP not supported yet");
500
501
	}
	else {
502
		panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
503
	}
Michael Beck's avatar
Michael Beck committed
504
505
}

506
/**
507
 * Creates an ARM And.
508
509
510
 *
 * @return the created arm And node
 */
511
512
513
514
static ir_node *gen_And(ir_node *node)
{
	return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
			new_bd_arm_And_reg, new_bd_arm_And_imm);
515
}
516
517

/**
518
 * Creates an ARM Orr.
519
 *
Michael Beck's avatar
Michael Beck committed
520
 * @param env   The transformation environment
521
522
 * @return the created arm Or node
 */
523
524
525
526
static ir_node *gen_Or(ir_node *node)
{
	return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
			new_bd_arm_Or_reg, new_bd_arm_Or_imm);
527
}
528
529

/**
530
 * Creates an ARM Eor.
531
532
533
 *
 * @return the created arm Eor node
 */
534
535
536
537
static ir_node *gen_Eor(ir_node *node)
{
	return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
			new_bd_arm_Eor_reg, new_bd_arm_Eor_imm);
538
}
539
540

/**
541
 * Creates an ARM Sub.
542
543
544
 *
 * @return the created arm Sub node
 */
545
546
static ir_node *gen_Sub(ir_node *node)
{
547
548
549
550
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_Sub_left(node);
	ir_node  *new_op1 = be_transform_node(op1);
	ir_node  *op2     = get_Sub_right(node);
Michael Beck's avatar
Michael Beck committed
551
	ir_node  *new_op2 = be_transform_node(op2);
552
	ir_mode  *mode    = get_irn_mode(node);
553
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
554

555
	if (mode_is_float(mode)) {
556
		env_cg->have_fp_insn = 1;
557
		if (USE_FPA(env_cg->isa)) {
558
#if 0
559
			if (is_arm_Mov_i(new_op1))
560
				return new_bd_arm_fpaRsf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
561
			if (is_arm_Mov_i(new_op2))
562
563
564
				return new_bd_arm_fpaSuf_i(dbgi, block, new_op1, mode, get_arm_imm_value(new_op2));
#endif
			return new_bd_arm_fpaSuf(dbgi, block, new_op1, new_op2, mode);
565
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
566
			assert(mode != mode_E && "IEEE Extended FP not supported");
567
			panic("VFP not supported yet");
568
		} else {
569
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
570
		}
571
572
573
	} else {
		return gen_int_binop(node, MATCH_SIZE_NEUTRAL,
				new_bd_arm_Sub_reg, new_bd_arm_Sub_imm);
Michael Beck's avatar
Michael Beck committed
574
	}
575
}
Michael Beck's avatar
Michael Beck committed
576

577
578
579
580
581
582
583
584
585
586
static bool can_use_shift_constant(unsigned int val,
                                   arm_shift_modifier_t modifier)
{
	if (val <= 31)
		return true;
	if (val == 32 && modifier != ARM_SHF_LSL_REG && modifier != ARM_SHF_ROR_REG)
		return true;
	return false;
}

587
static ir_node *make_shift(ir_node *node, match_flags_t flags,
588
		arm_shift_modifier_t shift_modifier)
589
{
590
591
592
593
	ir_node  *block = be_transform_node(get_nodes_block(node));
	ir_node  *op1   = get_binop_left(node);
	ir_node  *op2   = get_binop_right(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
594
595
596
597
598
599
	ir_node  *new_op1;
	ir_node  *new_op2;

	if (flags & MATCH_SIZE_NEUTRAL) {
		op1 = arm_skip_downconv(op1);
		op2 = arm_skip_downconv(op2);
600
	}
601

602
	new_op1 = be_transform_node(op1);
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
	if (is_Const(op2)) {
		tarval      *tv  = get_Const_tarval(op2);
		unsigned int val = get_tarval_long(tv);
		assert(tarval_is_long(tv));
		if (can_use_shift_constant(val, shift_modifier)) {
			switch (shift_modifier) {
			case ARM_SHF_LSL_REG: shift_modifier = ARM_SHF_LSL_IMM; break;
			case ARM_SHF_LSR_REG: shift_modifier = ARM_SHF_LSR_IMM; break;
			case ARM_SHF_ASR_REG: shift_modifier = ARM_SHF_ASR_IMM; break;
			case ARM_SHF_ROR_REG: shift_modifier = ARM_SHF_ROR_IMM; break;
			default: panic("unexpected shift modifier");
			}
			return new_bd_arm_Mov_reg_shift_imm(dbgi, block, new_op1,
			                                    shift_modifier, val);
		}
	}

620
	new_op2 = be_transform_node(op2);
621
622
	return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
	                                    shift_modifier);
623
624
625
}

/**
626
 * Creates an ARM Shl.
627
 *
628
 * @return the created ARM Shl node
629
 */
630
631
632
static ir_node *gen_Shl(ir_node *node)
{
	return make_shift(node, MATCH_SIZE_NEUTRAL, ARM_SHF_LSL_REG);
633
634
635
}

/**
636
 * Creates an ARM Shr.
637
 *
638
 * @return the created ARM Shr node
639
 */
640
641
642
static ir_node *gen_Shr(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_LSR_REG);
643
644
645
}

/**
646
 * Creates an ARM Shrs.
647
 *
648
 * @return the created ARM Shrs node
649
 */
650
651
652
static ir_node *gen_Shrs(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_ASR_REG);
653
654
}

Michael Beck's avatar
Michael Beck committed
655
656
657
658
659
/**
 * Creates an ARM Ror.
 *
 * @return the created ARM Ror node
 */
660
661
static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2)
{
Michael Beck's avatar
Michael Beck committed
662
663
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
664
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
665
666
	ir_node  *new_op2 = be_transform_node(op2);

667
668
	return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
	                                    ARM_SHF_ROR_REG);
Michael Beck's avatar
Michael Beck committed
669
670
671
672
673
674
675
676
677
}

/**
 * Creates an ARM Rol.
 *
 * @return the created ARM Rol node
 *
 * Note: there is no Rol on arm, we have to use Ror
 */
678
679
static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2)
{
Michael Beck's avatar
Michael Beck committed
680
681
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
682
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
683
684
	ir_node  *new_op2 = be_transform_node(op2);

685
686
687
	new_op2 = new_bd_arm_Rsb_imm(dbgi, block, new_op2, 32, 0);
	return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
	                                    ARM_SHF_ROR_REG);
Michael Beck's avatar
Michael Beck committed
688
689
690
691
692
693
694
}

/**
 * Creates an ARM ROR from a Firm Rotl.
 *
 * @return the created ARM Ror node
 */
695
696
static ir_node *gen_Rotl(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
697
698
699
700
701
702
703
704
705
	ir_node *rotate = NULL;
	ir_node *op1    = get_Rotl_left(node);
	ir_node *op2    = get_Rotl_right(node);

	/* Firm has only RotL, so we are looking for a right (op2)
	   operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
	   that means we can create a RotR. */

	if (is_Add(op2)) {
Michael Beck's avatar
Michael Beck committed
706
		ir_node *right = get_Add_right(op2);
Michael Beck's avatar
Michael Beck committed
707
708
709
710
		if (is_Const(right)) {
			tarval  *tv   = get_Const_tarval(right);
			ir_mode *mode = get_irn_mode(node);
			long     bits = get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
711
			ir_node *left = get_Add_left(op2);
Michael Beck's avatar
Michael Beck committed
712
713

			if (is_Minus(left) &&
Michael Beck's avatar
Michael Beck committed
714
			    tarval_is_long(tv)          &&
Michael Beck's avatar
Michael Beck committed
715
716
717
718
			    get_tarval_long(tv) == bits &&
			    bits                == 32)
				rotate = gen_Ror(node, op1, get_Minus_op(left));
		}
Michael Beck's avatar
Michael Beck committed
719
720
721
722
723
724
725
726
727
728
729
730
731
	} else if (is_Sub(op2)) {
		ir_node *left = get_Sub_left(op2);
		if (is_Const(left)) {
			tarval  *tv   = get_Const_tarval(left);
			ir_mode *mode = get_irn_mode(node);
			long     bits = get_mode_size_bits(mode);
			ir_node *right = get_Sub_right(op2);

			if (tarval_is_long(tv)          &&
			    get_tarval_long(tv) == bits &&
			    bits                == 32)
				rotate = gen_Ror(node, op1, right);
		}
732
	} else if (is_Const(op2)) {
733
734
735
		tarval  *tv   = get_Const_tarval(op2);
		ir_mode *mode = get_irn_mode(node);
		long     bits = get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
736

737
738
739
740
		if (tarval_is_long(tv) && bits == 32) {
			ir_node  *block   = be_transform_node(get_nodes_block(node));
			ir_node  *new_op1 = be_transform_node(op1);
			dbg_info *dbgi    = get_irn_dbg_info(node);
741

742
743
744
			bits = (bits - get_tarval_long(tv)) & 31;
			rotate = new_bd_arm_Mov_reg_shift_imm(dbgi, block, new_op1, ARM_SHF_ROR_IMM, bits);
		}
Michael Beck's avatar
Michael Beck committed
745
746
747
748
749
750
751
752
753
	}

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

	return rotate;
}

754
755
756
/**
 * Transforms a Not node.
 *
757
 * @return the created ARM Not node
758
 */
759
760
static ir_node *gen_Not(ir_node *node)
{
761
762
763
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op      = get_Not_op(node);
	ir_node  *new_op  = be_transform_node(op);
764
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
765

766
767
768
	/* TODO: we could do alot more here with all the Mvn variations */

	return new_bd_arm_Mvn_reg(dbgi, block, new_op);
769
770
}

Michael Beck's avatar
Michael Beck committed
771
772
773
774
/**
 * Transforms an Abs node.
 *
 * @param env   The transformation environment
775
 * @return the created ARM Abs node
Michael Beck's avatar
Michael Beck committed
776
 */
777
778
static ir_node *gen_Abs(ir_node *node)
{
779
	ir_node  *block   = be_transform_node(get_nodes_block(node));
780
	ir_node  *op      = get_Abs_op(node);
781
	ir_node  *new_op  = be_transform_node(op);
782
	dbg_info *dbgi    = get_irn_dbg_info(node);
783
	ir_mode  *mode    = get_irn_mode(node);
784

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

/**
 * Transforms a Minus node.
 *
804
 * @return the created ARM Minus node
805
 */
806
807
static ir_node *gen_Minus(ir_node *node)
{
808
809
810
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op      = get_Minus_op(node);
	ir_node  *new_op  = be_transform_node(op);
811
	dbg_info *dbgi    = get_irn_dbg_info(node);
812
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
813

814
	if (mode_is_float(mode)) {
815
816
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
817
			return new_bd_arm_fpaMvf(dbgi, block, op, mode);
818
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
819
			assert(mode != mode_E && "IEEE Extended FP not supported");
820
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
821
822
		}
		else {
823
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
824
		}
825
	}
826
	assert(mode_is_data(mode));
827
	return new_bd_arm_Rsb_imm(dbgi, block, new_op, 0, 0);
828
829
830
831
832
}

/**
 * Transforms a Load.
 *
833
 * @return the created ARM Load node
834
 */
835
836
static ir_node *gen_Load(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
837
838
839
840
841
842
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *ptr      = get_Load_ptr(node);
	ir_node  *new_ptr  = be_transform_node(ptr);
	ir_node  *mem      = get_Load_mem(node);
	ir_node  *new_mem  = be_transform_node(mem);
	ir_mode  *mode     = get_Load_mode(node);
843
	dbg_info *dbgi      = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
844
	ir_node  *new_load = NULL;
845

Michael Beck's avatar
Michael Beck committed
846
	if (mode_is_float(mode)) {
847
848
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
849
			new_load = new_bd_arm_fpaLdf(dbgi, block, new_ptr, new_mem, mode);
850
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
851
			assert(mode != mode_E && "IEEE Extended FP not supported");
852
			panic("VFP not supported yet");
853
		} else {
854
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
855
		}
856
	} else {
857
		assert(mode_is_data(mode) && "unsupported mode for Load");
858

859
		new_load = new_bd_arm_Ldr(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false);
860
	}
Michael Beck's avatar
Michael Beck committed
861
	set_irn_pinned(new_load, get_irn_pinned(node));
862
863
864
865

	/* check for special case: the loaded value might not be used */
	if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) {
		/* add a result proj and a Keep to produce a pseudo use */
866
		ir_node *proj = new_r_Proj(new_load, mode_Iu, pn_arm_Ldr_res);
867
		be_new_Keep(block, 1, &proj);
868
869
	}

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

/**
 * Transforms a Store.
 *
876
 * @return the created ARM Store node
877
 */
878
879
static ir_node *gen_Store(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
880
881
882
883
884
885
886
887
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *ptr      = get_Store_ptr(node);
	ir_node  *new_ptr  = be_transform_node(ptr);
	ir_node  *mem      = get_Store_mem(node);
	ir_node  *new_mem  = be_transform_node(mem);
	ir_node  *val      = get_Store_value(node);
	ir_node  *new_val  = be_transform_node(val);
	ir_mode  *mode     = get_irn_mode(val);
888
	dbg_info *dbgi     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
889
	ir_node *new_store = NULL;
890

Michael Beck's avatar
Michael Beck committed
891
	if (mode_is_float(mode)) {
892
893
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
894
895
			new_store = new_bd_arm_fpaStf(dbgi, block, new_ptr, new_val,
			                              new_mem, mode);
896
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
897
			assert(mode != mode_E && "IEEE Extended FP not supported");
898
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
899
		} else {
900
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
901
902
		}
	} else {
903
		assert(mode_is_data(mode) && "unsupported mode for Store");
904
905
		new_store = new_bd_arm_Str(dbgi, block, new_ptr, new_val, new_mem, mode,
		                           NULL, 0, 0, false);
906
	}
Michael Beck's avatar
Michael Beck committed
907
908
	set_irn_pinned(new_store, get_irn_pinned(node));
	return new_store;
909
910
}

911
912
913
914
915
916
917
918
919
static ir_node *gen_Jmp(ir_node *node)
{
	ir_node  *block     = get_nodes_block(node);
	ir_node  *new_block = be_transform_node(block);
	dbg_info *dbgi      = get_irn_dbg_info(node);

	return new_bd_arm_Jmp(dbgi, new_block);
}

920
921
922
923
924
925
926
927
928
929
static ir_node *gen_be_Call(ir_node *node)
{
	ir_node *res = be_duplicate_node(node);
	arch_irn_add_flags(res, arch_irn_flags_modify_flags);

	return res;
}

static ir_node *gen_SwitchJmp(ir_node *node)
{
930
931
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *selector = get_Cond_selector(node);
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
	dbg_info *dbgi     = get_irn_dbg_info(node);
	ir_node *new_op = be_transform_node(selector);
	ir_node *const_graph;
	ir_node *sub;

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

	foreach_out_edge(node, 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;
	n_projs = max - translation + 1;
956

957
958
959
	foreach_out_edge(node, edge) {
		proj = get_edge_src_irn(edge);
		assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
960

961
962
963
		pn = get_Proj_proj(proj) - translation;
		set_Proj_proj(proj, pn);
	}
964

965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
	const_graph = create_const_graph_value(dbgi, block, translation);
	sub = new_bd_arm_Sub_reg(dbgi, block, new_op, const_graph);
	return new_bd_arm_SwitchJmp(dbgi, block, sub, n_projs, get_Cond_default_proj(node) - translation);
}

static ir_node *gen_Cmp(ir_node *node)
{
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *op1      = get_Cmp_left(node);
	ir_node  *op2      = get_Cmp_right(node);
	ir_mode  *cmp_mode = get_irn_mode(op1);
	dbg_info *dbgi     = get_irn_dbg_info(node);
	ir_node  *new_op1;
	ir_node  *new_op2;
	bool      is_unsigned;

	if (mode_is_float(cmp_mode)) {
		/* TODO: revivie this code */
		panic("FloatCmp NIY");
#if 0
		ir_node *new_op2  = be_transform_node(op2);
		/* floating point compare */
		pn_Cmp pnc = get_Proj_proj(selector);

		if (pnc & pn_Cmp_Uo) {
			/* check for unordered, need cmf */
			return new_bd_arm_fpaCmfBra(dbgi, block, new_op1, new_op2, pnc);
992
		}
993
994
995
996
		/* Hmm: use need cmfe */
		return new_bd_arm_fpaCmfeBra(dbgi, block, new_op1, new_op2, pnc);
#endif
	}
997

998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
	assert(get_irn_mode(op2) == cmp_mode);
	is_unsigned = !mode_is_signed(cmp_mode);

	/* compare with 0 can be done with Tst */
	if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) {
		new_op1 = be_transform_node(op1);
		new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
		return new_bd_arm_Tst_reg(dbgi, block, new_op1, new_op1, false,
		                          is_unsigned);
	}
	if (is_Const(op1) && tarval_is_null(get_Const_tarval(op1))) {
		new_op2 = be_transform_node(op2);
		new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
		return new_bd_arm_Tst_reg(dbgi, block, new_op2, new_op2, true,
		                          is_unsigned);
1013
	}
1014
1015
1016
1017
1018
1019
1020
1021

	/* integer compare, TODO: use shifer_op in all its combinations */
	new_op1 = be_transform_node(op1);
	new_op1 = gen_extension(dbgi, block, new_op1, cmp_mode);
	new_op2 = be_transform_node(op2);
	new_op2 = gen_extension(dbgi, block, new_op2, cmp_mode);
	return new_bd_arm_Cmp_reg(dbgi, block, new_op1, new_op2, false,
	                          is_unsigned);
1022
1023
1024
}

/**
1025
1026
1027
 * Transforms a Cond.
 *
 * @return the created ARM Cond node
1028
 */
1029
1030
1031
1032
1033
1034
1035
static ir_node *gen_Cond(ir_node *node)
{
	ir_node  *selector = get_Cond_selector(node);
	ir_mode  *mode     = get_irn_mode(selector);
	ir_node  *block;
	ir_node  *flag_node;
	dbg_info *dbgi;
1036

1037
1038
	if (mode != mode_b) {
		return gen_SwitchJmp(node);
1039
	}
1040
1041
1042
1043
1044
	assert(is_Proj(selector));

	block     = be_transform_node(get_nodes_block(node));
	dbgi      = get_irn_dbg_info(node);
	flag_node = be_transform_node(get_Proj_pred(selector));
1045

1046
	return new_bd_arm_B(dbgi, block, flag_node, get_Proj_proj(selector));
1047
1048
}