arm_transform.c 44.5 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
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

	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
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
587
588
589
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);
590
	}
591
592
593
	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);
594
595
596
}

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

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

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

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

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

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

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

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

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

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

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

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

	return rotate;
}

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

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

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

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

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

/**
 * Transforms a Minus node.
 *
775
 * @return the created ARM Minus node
776
 */
777
778
static ir_node *gen_Minus(ir_node *node)
{
779
780
781
	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);
782
	dbg_info *dbgi    = get_irn_dbg_info(node);
783
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
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_fpaMvf(dbgi, block, 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_Rsb_imm(dbgi, block, new_op, 0, 0);
799
800
801
802
803
}

/**
 * Transforms a Load.
 *
804
 * @return the created ARM Load node
805
 */
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(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
static ir_node *gen_Cond(ir_node *node)
For faster browsing, not all history is shown. View entire blame