arm_transform.c 45.1 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
123
124
/**
 * Create an And that will mask all upper bits
 */
125
126
127
128
129
130
131
132
133
134
135
136
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");
	}
137
138
}

Michael Beck's avatar
Michael Beck committed
139
140
141
/**
 * Generate code for a sign extension.
 */
142
143
144
145
146
147
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);
148
149
150
	return rshift_node;
}

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
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
179
180
181
/**
 * Transforms a Conv node.
 *
182
 * @return The created ia32 Conv node
Michael Beck's avatar
Michael Beck committed
183
 */
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
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
201
					/* from float to float */
202
					return new_bd_arm_fpaMvf(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
203
204
205
				}
				else {
					/* from float to int */
206
					return new_bd_arm_fpaFix(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
207
208
209
210
				}
			}
			else {
				/* from int to float */
211
				return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
212
			}
213
		} else if (USE_VFP(env_cg->isa)) {
214
			panic("VFP not supported yet");
215
			return NULL;
216
		} else {
217
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
218
219
			return NULL;
		}
220
	} else { /* complete in gp registers */
221
222
		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
223
224
		int min_bits;
		ir_mode *min_mode;
225

Michael Beck's avatar
Michael Beck committed
226
227
228
		if (src_bits == dst_bits) {
			/* kill unneccessary conv */
			return new_op;
229
230
231
232
233
		}

		if (src_bits < dst_bits) {
			min_bits = src_bits;
			min_mode = src_mode;
Michael Beck's avatar
Michael Beck committed
234
		} else {
235
236
237
238
239
240
241
242
243
244
245
246
			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);
247
248
249
250
		}
	}
}

251
252
253
254
255
256
257
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
258
	unsigned val, low_pos, high_pos;
259
260
261

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

263
	val = get_tarval_long(get_Const_tarval(node));
Michael Beck's avatar
Michael Beck committed
264

265
266
267
268
269
270
271
272
273
	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
274
	}
275
276
277
278
279
280
281
	/* 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
282
283
	low_pos  = ntz(val) & ~1u;
	high_pos = (32-nlz(val)+1) & ~1u;
284
285
286
287
288
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

	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
370
}
371
372

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

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

414
			return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
Michael Beck's avatar
Michael Beck committed
415
		}
Michael Beck's avatar
Michael Beck committed
416
		if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
417
418
419
			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
420

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

425
426
		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
427
428
	}
}
429
430

/**
431
 * Creates an ARM Mul.
432
433
434
 *
 * @return the created arm Mul node
 */
435
436
437
438
439
440
441
442
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
443

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

/**
470
 * Creates an ARM floating point Div.
471
 *
Michael Beck's avatar
Michael Beck committed
472
 * @param env   The transformation environment
473
474
 * @return the created arm fDiv node
 */
475
476
477
478
479
480
481
482
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
483

484
	assert(mode != mode_E && "IEEE Extended FP not supported");
485

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

505
/**
506
 * Creates an ARM And.
507
508
509
 *
 * @return the created arm And node
 */
510
511
512
513
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);
514
}
515
516

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

/**
529
 * Creates an ARM Eor.
530
531
532
 *
 * @return the created arm Eor node
 */
533
534
535
536
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);
537
}
538
539

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

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

578
579
580
581
582
583
584
585
586
587
588
589
590
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);
591
	}
592
593
594
	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);
595
596
597
}

/**
598
 * Creates an ARM Shl.
599
 *
600
 * @return the created ARM Shl node
601
 */
602
603
604
static ir_node *gen_Shl(ir_node *node)
{
	return make_shift(node, MATCH_SIZE_NEUTRAL, ARM_SHF_LSL_REG);
605
606
607
}

/**
608
 * Creates an ARM Shr.
609
 *
610
 * @return the created ARM Shr node
611
 */
612
613
614
static ir_node *gen_Shr(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_LSR_REG);
615
616
617
}

/**
618
 * Creates an ARM Shrs.
619
 *
620
 * @return the created ARM Shrs node
621
 */
622
623
624
static ir_node *gen_Shrs(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_ASR_REG);
625
626
}

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

639
640
	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
641
642
643
644
645
646
647
648
649
}

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

657
658
659
	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
660
661
662
663
664
665
666
}

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

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

709
710
711
712
		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);
713

714
715
716
			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
717
718
719
720
721
722
723
724
725
	}

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

	return rotate;
}

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

738
739
740
	/* TODO: we could do alot more here with all the Mvn variations */

	return new_bd_arm_Mvn_reg(dbgi, block, new_op);
741
742
}

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

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

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

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

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

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

830
		new_load = new_bd_arm_Ldr(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false);
831
	}
Michael Beck's avatar
Michael Beck committed
832
	set_irn_pinned(new_load, get_irn_pinned(node));
833
834
835
836

	/* 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 */
837
		ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Ldr_res);
838
		be_new_Keep(block, 1, &proj);
839
840
	}

Michael Beck's avatar
Michael Beck committed
841
	return new_load;
842
843
844
845
846
}

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

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

882
883
884
885
886
887
888
889
890
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);
}

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

928
929
930
	foreach_out_edge(node, edge) {
		proj = get_edge_src_irn(edge);
		assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
931

932
933
934
		pn = get_Proj_proj(proj) - translation;
		set_Proj_proj(proj, pn);
	}
935

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

969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
	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);
984
	}
985
986
987
988
989
990
991
992

	/* 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);
993
994
995
}

/**
996
997
998
 * Transforms a Cond.
 *
 * @return the created ARM Cond node
999
 */
1000
1001
1002
1003
1004
1005
1006
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;
1007

1008
1009
	if (mode != mode_b) {
		return gen_SwitchJmp(node);
1010
	}
1011
1012
1013
1014
1015
	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));
1016

1017
	return new_bd_arm_B(dbgi, block, flag_node, get_Proj_proj(selector));
1018
1019
}

1020
1021
static tarval *fpa_imm[3][fpa_max];

1022
#if 0
1023
1024
/**
 * Check, if a floating point tarval is an fpa immediate, i.e.
1025
 * one of 0, 1, 2, 3, 4, 5, 10, or 0.5.
1026
 */
1027
1028
static int is_fpa_immediate(tarval *tv)
{
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
	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
1050
			return res * j;
1051
	}
Michael Beck's avatar
Michael Beck committed
1052
	return fpa_max;
1053
}
1054
#endif
1055

Michael Beck's avatar
Michael Beck committed
1056
/**