arm_transform.c 45.2 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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
static ir_node *gen_Conv(ir_node *node) {
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *op       = get_Conv_op(node);
	ir_node  *new_op   = be_transform_node(op);
	ir_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
206
					/* from float to float */
207
					return new_bd_arm_fpaMvf(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
208
209
210
				}
				else {
					/* from float to int */
211
					return new_bd_arm_fpaFix(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
212
213
214
215
				}
			}
			else {
				/* from int to float */
216
				return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
217
			}
218
		} else if (USE_VFP(env_cg->isa)) {
219
			panic("VFP not supported yet");
220
			return NULL;
221
		} else {
222
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
223
224
			return NULL;
		}
225
	} else { /* complete in gp registers */
226
227
		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
228
229
		int min_bits;
		ir_mode *min_mode;
230

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

		if (src_bits < dst_bits) {
			min_bits = src_bits;
			min_mode = src_mode;
Michael Beck's avatar
Michael Beck committed
239
		} else {
240
241
242
243
244
245
246
247
248
249
250
251
			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);
252
253
254
255
		}
	}
}

256
257
258
259
260
261
262
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
263
	unsigned val, low_pos, high_pos;
264
265
266

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

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

270
271
272
273
274
275
276
277
278
	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
279
	}
280
281
282
283
284
285
286
	/* 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
287
288
	low_pos  = ntz(val) & ~1u;
	high_pos = (32-nlz(val)+1) & ~1u;
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
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
374

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

static int is_downconv(const ir_node *node)
{
	ir_mode *src_mode;
	ir_mode *dest_mode;

	if (!is_Conv(node))
		return 0;

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

	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
375
}
376
377

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

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

419
			return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
Michael Beck's avatar
Michael Beck committed
420
		}
Michael Beck's avatar
Michael Beck committed
421
		if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
422
423
424
			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
425

426
			return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
Michael Beck's avatar
Michael Beck committed
427
		}
428
#endif
429

430
431
		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
432
433
	}
}
434
435

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

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

/**
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
482
483
484
485
486
487
static ir_node *gen_Quot(ir_node *node) {
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *op1     = get_Quot_left(node);
	ir_node  *new_op1 = be_transform_node(op1);
	ir_node  *op2     = get_Quot_right(node);
	ir_node  *new_op2 = be_transform_node(op2);
	ir_mode  *mode    = get_irn_mode(node);
	dbg_info *dbg     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
488

489
	assert(mode != mode_E && "IEEE Extended FP not supported");
490

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

510
/**
511
 * Creates an ARM And.
512
513
514
 *
 * @return the created arm And node
 */
515
516
517
518
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);
519
}
520
521

/**
522
 * Creates an ARM Orr.
523
 *
Michael Beck's avatar
Michael Beck committed
524
 * @param env   The transformation environment
525
526
 * @return the created arm Or node
 */
527
528
529
530
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);
531
}
532
533

/**
534
 * Creates an ARM Eor.
535
536
537
 *
 * @return the created arm Eor node
 */
538
539
540
541
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);
542
}
543
544

/**
545
 * Creates an ARM Sub.
546
547
548
 *
 * @return the created arm Sub node
 */
549
550
static ir_node *gen_Sub(ir_node *node)
{
551
552
553
554
	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
555
	ir_node  *new_op2 = be_transform_node(op2);
556
	ir_mode  *mode    = get_irn_mode(node);
557
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
558

559
	if (mode_is_float(mode)) {
560
		env_cg->have_fp_insn = 1;
561
		if (USE_FPA(env_cg->isa)) {
562
#if 0
563
			if (is_arm_Mov_i(new_op1))
564
				return new_bd_arm_fpaRsf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
565
			if (is_arm_Mov_i(new_op2))
566
567
568
				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);
569
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
570
			assert(mode != mode_E && "IEEE Extended FP not supported");
571
			panic("VFP not supported yet");
572
			return NULL;
573
		} else {
574
			panic("Softfloat not supported yet");
575
			return NULL;
Michael Beck's avatar
Michael Beck committed
576
		}
577
578
579
	} 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
580
	}
581
}
Michael Beck's avatar
Michael Beck committed
582

583
584
585
586
587
588
589
590
591
592
593
594
595
static ir_node *make_shift(ir_node *node, match_flags_t flags,
		arm_shift_modifier shift_modifier)
{
	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);
	ir_node  *new_op1;
	ir_node  *new_op2;

	if (flags & MATCH_SIZE_NEUTRAL) {
		op1 = arm_skip_downconv(op1);
		op2 = arm_skip_downconv(op2);
596
	}
597
598
599
	new_op1 = be_transform_node(op1);
	new_op2 = be_transform_node(op2);
	return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2, shift_modifier);
600
601
602
}

/**
603
 * Creates an ARM Shl.
604
 *
605
 * @return the created ARM Shl node
606
 */
607
608
609
static ir_node *gen_Shl(ir_node *node)
{
	return make_shift(node, MATCH_SIZE_NEUTRAL, ARM_SHF_LSL_REG);
610
611
612
}

/**
613
 * Creates an ARM Shr.
614
 *
615
 * @return the created ARM Shr node
616
 */
617
618
619
static ir_node *gen_Shr(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_LSR_REG);
620
621
622
}

/**
623
 * Creates an ARM Shrs.
624
 *
625
 * @return the created ARM Shrs node
626
 */
627
628
629
static ir_node *gen_Shrs(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_ASR_REG);
630
631
}

Michael Beck's avatar
Michael Beck committed
632
633
634
635
636
/**
 * Creates an ARM Ror.
 *
 * @return the created ARM Ror node
 */
637
638
static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2)
{
Michael Beck's avatar
Michael Beck committed
639
640
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
641
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
642
643
	ir_node  *new_op2 = be_transform_node(op2);

644
645
	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
646
647
648
649
650
651
652
653
654
}

/**
 * Creates an ARM Rol.
 *
 * @return the created ARM Rol node
 *
 * Note: there is no Rol on arm, we have to use Ror
 */
655
656
static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2)
{
Michael Beck's avatar
Michael Beck committed
657
658
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
659
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
660
661
	ir_node  *new_op2 = be_transform_node(op2);

662
663
664
	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
665
666
667
668
669
670
671
}

/**
 * Creates an ARM ROR from a Firm Rotl.
 *
 * @return the created ARM Ror node
 */
672
673
static ir_node *gen_Rotl(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
674
675
676
677
678
679
680
681
682
	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
683
		ir_node *right = get_Add_right(op2);
Michael Beck's avatar
Michael Beck committed
684
685
686
687
		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
688
			ir_node *left = get_Add_left(op2);
Michael Beck's avatar
Michael Beck committed
689
690

			if (is_Minus(left) &&
Michael Beck's avatar
Michael Beck committed
691
			    tarval_is_long(tv)          &&
Michael Beck's avatar
Michael Beck committed
692
693
694
695
			    get_tarval_long(tv) == bits &&
			    bits                == 32)
				rotate = gen_Ror(node, op1, get_Minus_op(left));
		}
Michael Beck's avatar
Michael Beck committed
696
697
698
699
700
701
702
703
704
705
706
707
708
	} 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);
		}
709
	} else if (is_Const(op2)) {
710
711
712
		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
713

714
715
716
717
		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);
718

719
720
721
			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
722
723
724
725
726
727
728
729
730
	}

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

	return rotate;
}

731
732
733
/**
 * Transforms a Not node.
 *
734
 * @return the created ARM Not node
735
 */
736
737
static ir_node *gen_Not(ir_node *node)
{
738
739
740
	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);
741
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
742

743
744
745
	/* TODO: we could do alot more here with all the Mvn variations */

	return new_bd_arm_Mvn_reg(dbgi, block, new_op);
746
747
}

Michael Beck's avatar
Michael Beck committed
748
749
750
751
/**
 * Transforms an Abs node.
 *
 * @param env   The transformation environment
752
 * @return the created ARM Abs node
Michael Beck's avatar
Michael Beck committed
753
 */
754
755
static ir_node *gen_Abs(ir_node *node)
{
756
	ir_node  *block   = be_transform_node(get_nodes_block(node));
757
	ir_node  *op      = get_Abs_op(node);
758
	ir_node  *new_op  = be_transform_node(op);
759
	dbg_info *dbgi    = get_irn_dbg_info(node);
760
	ir_mode  *mode    = get_irn_mode(node);
761

762
	if (mode_is_float(mode)) {
763
764
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
765
			return new_bd_arm_fpaAbs(dbgi, block, new_op, mode);
766
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
767
			assert(mode != mode_E && "IEEE Extended FP not supported");
768
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
769
770
		}
		else {
771
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
772
		}
773
	}
774
	assert(mode_is_data(mode));
775
	return new_bd_arm_Abs(dbgi, block, new_op);
776
777
778
779
780
}

/**
 * Transforms a Minus node.
 *
781
 * @return the created ARM Minus node
782
 */
783
784
static ir_node *gen_Minus(ir_node *node)
{
785
786
787
	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);
788
	dbg_info *dbgi    = get_irn_dbg_info(node);
789
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
790

791
	if (mode_is_float(mode)) {
792
793
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
794
			return new_bd_arm_fpaMvf(dbgi, block, op, mode);
795
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
796
			assert(mode != mode_E && "IEEE Extended FP not supported");
797
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
798
799
		}
		else {
800
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
801
		}
802
	}
803
	assert(mode_is_data(mode));
804
	return new_bd_arm_Rsb_imm(dbgi, block, new_op, 0, 0);
805
806
807
808
809
}

/**
 * Transforms a Load.
 *
810
 * @return the created ARM Load node
811
 */
812
static ir_node *gen_Load(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
813
814
815
816
817
818
	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);
819
	dbg_info *dbgi      = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
820
	ir_node  *new_load = NULL;
821

Michael Beck's avatar
Michael Beck committed
822
	if (mode_is_float(mode)) {
823
824
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
825
			new_load = new_bd_arm_fpaLdf(dbgi, block, new_ptr, new_mem, mode);
826
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
827
			assert(mode != mode_E && "IEEE Extended FP not supported");
828
			panic("VFP not supported yet");
829
		} else {
830
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
831
		}
832
	} else {
833
		assert(mode_is_data(mode) && "unsupported mode for Load");
834

835
		new_load = new_bd_arm_Ldr(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false);
836
	}
Michael Beck's avatar
Michael Beck committed
837
	set_irn_pinned(new_load, get_irn_pinned(node));
838
839
840
841

	/* 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 */
842
		ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Ldr_res);
843
		be_new_Keep(block, 1, &proj);
844
845
	}

Michael Beck's avatar
Michael Beck committed
846
	return new_load;
847
848
849
850
851
}

/**
 * Transforms a Store.
 *
852
 * @return the created ARM Store node
853
 */
854
855
static ir_node *gen_Store(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
856
857
858
859
860
861
862
863
	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);
864
	dbg_info *dbgi     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
865
	ir_node *new_store = NULL;
866

Michael Beck's avatar
Michael Beck committed
867
	if (mode_is_float(mode)) {
868
869
		env_cg->have_fp_insn = 1;
		if (USE_FPA(env_cg->isa))
870
871
			new_store = new_bd_arm_fpaStf(dbgi, block, new_ptr, new_val,
			                              new_mem, mode);
872
		else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
873
			assert(mode != mode_E && "IEEE Extended FP not supported");
874
			panic("VFP not supported yet");
Michael Beck's avatar
Michael Beck committed
875
		} else {
876
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
877
878
		}
	} else {
879
		assert(mode_is_data(mode) && "unsupported mode for Store");
880
881
		new_store = new_bd_arm_Str(dbgi, block, new_ptr, new_val, new_mem, mode,
		                           NULL, 0, 0, false);
882
	}
Michael Beck's avatar
Michael Beck committed
883
884
	set_irn_pinned(new_store, get_irn_pinned(node));
	return new_store;
885
886
}

887
888
889
890
891
892
893
894
895
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);
}

896
897
898
899
900
901
902
903
904
905
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)
{
906
907
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *selector = get_Cond_selector(node);
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
	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;
932

933
934
935
	foreach_out_edge(node, edge) {
		proj = get_edge_src_irn(edge);
		assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
936

937
938
939
		pn = get_Proj_proj(proj) - translation;
		set_Proj_proj(proj, pn);
	}
940

941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
	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);
968
		}
969
970
971
972
		/* Hmm: use need cmfe */
		return new_bd_arm_fpaCmfeBra(dbgi, block, new_op1, new_op2, pnc);
#endif
	}
973

974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
	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);
989
	}
990
991
992
993
994
995
996
997

	/* 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);
998
999
1000
}

/**
1001
1002
1003
 * Transforms a Cond.
 *
 * @return the created ARM Cond node
1004
 */
1005
1006
1007
1008
1009
1010
1011
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;
1012

1013
1014
	if (mode != mode_b) {
		return gen_SwitchJmp(node);
1015
	}
1016
1017
1018
1019
1020
	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));
1021

1022
	return new_bd_arm_B(dbgi, block, flag_node, get_Proj_proj(selector));
1023
1024
}

1025
1026
static tarval *fpa_imm[3][fpa_max];

1027
#if 0
1028
1029
/**
 * Check, if a floating point tarval is an fpa immediate, i.e.
1030
 * one of 0, 1, 2, 3, 4, 5, 10, or 0.5.
1031
 */
1032
1033
static int is_fpa_immediate(tarval *tv)
{
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
	ir_mode *mode = get_tarval_mode(tv);
	int i, j, res = 1;

	switch (get_mode_size_bits(mode)) {
	case 32:
		i = 0;
		break;
	case 64:
		i = 1;
		break;
	default:
		i = 2;
	}

	if (tarval_cmp(tv, get_tarval_null(mode)) & pn_Cmp_Lt) {
		tv = tarval_neg(tv);
		res = -1;
	}

	for (j = 0; j < fpa_max; ++j) {
		if (tv == fpa_imm[i][j])
Michael Beck's avatar
Michael Beck committed
1055
			return res * j;
1056
	}
Michael Beck's avatar
Michael Beck committed
1057
	return fpa_max;
1058
}