arm_transform.c 62.6 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

6
7
/**
 * @file
Michael Beck's avatar
Michael Beck committed
8
 * @brief   The codegenerator (transform FIRM into arm FIRM)
9
 * @author  Matthias Braun, Oliver Richter, Tobias Gneist, Michael Beck
10
 */
11
#include "arm_bearch_t.h"
12
13
14
15
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
#include "irgmod.h"
16
#include "iredges_t.h"
17
18
19
20
#include "ircons.h"
#include "dbginfo.h"
#include "iropt_t.h"
#include "debug.h"
Matthias Braun's avatar
Matthias Braun committed
21
#include "panic.h"
22
#include "util.h"
23

24
25
26
27
#include "benode.h"
#include "beirg.h"
#include "beutil.h"
#include "betranshlp.h"
28
29
30

#include "arm_nodes_attr.h"
#include "arm_transform.h"
31
#include "arm_optimize.h"
32
#include "arm_new_nodes.h"
33
#include "arm_cconv.h"
34
35

#include "gen_arm_regalloc_if.h"
Matthias Braun's avatar
Matthias Braun committed
36
#include "gen_arm_new_nodes.h"
37

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

40
static const arch_register_t *sp_reg = &arm_registers[REG_SP];
41
static be_stack_env_t         stack_env;
42
43
static calling_convention_t  *cconv = NULL;

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
static const arch_register_t *const callee_saves[] = {
	&arm_registers[REG_R4],
	&arm_registers[REG_R5],
	&arm_registers[REG_R6],
	&arm_registers[REG_R7],
	&arm_registers[REG_R8],
	&arm_registers[REG_R9],
	&arm_registers[REG_R10],
	&arm_registers[REG_R11],
	&arm_registers[REG_LR],
};

static const arch_register_t *const caller_saves[] = {
	&arm_registers[REG_R0],
	&arm_registers[REG_R1],
	&arm_registers[REG_R2],
	&arm_registers[REG_R3],
	&arm_registers[REG_LR],

	&arm_registers[REG_F0],
	&arm_registers[REG_F1],
	&arm_registers[REG_F2],
	&arm_registers[REG_F3],
	&arm_registers[REG_F4],
	&arm_registers[REG_F5],
	&arm_registers[REG_F6],
	&arm_registers[REG_F7],
};

73
74
75
76
77
static ir_node *get_initial_sp(ir_graph *const irg)
{
	return be_get_Start_proj(irg, &arm_registers[REG_SP]);
}

Matthias Braun's avatar
Matthias Braun committed
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
void arm_gen_vals_from_word(uint32_t value, arm_vals *result)
{
	/* TODO: not optimal yet, as we only "shift" the value and don't take
	 * advantage of rotations */

	/* special case: we prefer shift amount 0 */
	if (value <= 0xFF) {
		result->values[0] = value;
		result->rors[0]   = 0;
		result->ops       = 1;
		return;
	}

	int initial = 0;
	result->ops = 0;
	do {
		while ((value & 0x3) == 0) {
			value  >>= 2;
			initial += 2;
		}

		result->values[result->ops] = value & 0xFF;
		result->rors[result->ops]   = (32-initial) % 32;
		++result->ops;

		value  >>= 8;
		initial += 8;
	} while (value != 0);
}

Michael Beck's avatar
Michael Beck committed
108
/**
109
 * create firm graph for a constant
Michael Beck's avatar
Michael Beck committed
110
 */
111
static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
Matthias Braun's avatar
Matthias Braun committed
112
                                         uint32_t value)
113
{
114
115
116
117
118
119
	/* We only have 8 bit immediates. So we possibly have to combine several
	 * operations to construct the desired value.
	 *
	 * we can either create the value by adding bits to 0 or by removing bits
	 * from an register with all bits set. Try which alternative needs fewer
	 * operations */
Matthias Braun's avatar
Matthias Braun committed
120
	arm_vals v;
121
	arm_gen_vals_from_word(value, &v);
Matthias Braun's avatar
Matthias Braun committed
122
	arm_vals vn;
123
	arm_gen_vals_from_word(~value, &vn);
Michael Beck's avatar
Michael Beck committed
124

Matthias Braun's avatar
Matthias Braun committed
125
	ir_node *result;
Michael Beck's avatar
Michael Beck committed
126
127
	if (vn.ops < v.ops) {
		/* remove bits */
128
		result = new_bd_arm_Mvn_imm(dbgi, block, vn.values[0], vn.rors[0]);
Michael Beck's avatar
Michael Beck committed
129

Matthias Braun's avatar
Matthias Braun committed
130
		for (unsigned cnt = 1; cnt < vn.ops; ++cnt) {
131
132
			result = new_bd_arm_Bic_imm(dbgi, block, result,
			                            vn.values[cnt], vn.rors[cnt]);
133
		}
134
	} else {
Michael Beck's avatar
Michael Beck committed
135
		/* add bits */
136
		result = new_bd_arm_Mov_imm(dbgi, block, v.values[0], v.rors[0]);
Michael Beck's avatar
Michael Beck committed
137

Matthias Braun's avatar
Matthias Braun committed
138
		for (unsigned cnt = 1; cnt < v.ops; ++cnt) {
139
140
			result = new_bd_arm_Or_imm(dbgi, block, result,
			                           v.values[cnt], v.rors[cnt]);
Michael Beck's avatar
Michael Beck committed
141
		}
142
143
144
145
	}
	return result;
}

146
147
148
149
150
/**
 * Create a DAG constructing a given Const.
 *
 * @param irn  a Firm const
 */
151
152
static ir_node *create_const_graph(ir_node *irn, ir_node *block)
{
Matthias Braun's avatar
Matthias Braun committed
153
154
	ir_tarval *tv   = get_Const_tarval(irn);
	ir_mode   *mode = get_tarval_mode(tv);
155
156
	if (mode_is_reference(mode)) {
		/* ARM is 32bit, so we can safely convert a reference tarval into Iu */
157
158
		assert(get_mode_size_bits(mode) == get_mode_size_bits(arm_mode_gp));
		tv = tarval_convert_to(tv, arm_mode_gp);
159
	}
Matthias Braun's avatar
Matthias Braun committed
160
	long value = get_tarval_long(tv);
161
	return create_const_graph_value(get_irn_dbg_info(irn), block, value);
162
163
}

Michael Beck's avatar
Michael Beck committed
164
/**
Michael Beck's avatar
Michael Beck committed
165
166
167
168
169
170
 * 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
171
 */
172
static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
Matthias Braun's avatar
Matthias Braun committed
173
                                   unsigned src_bits)
174
175
176
177
178
179
180
181
182
183
{
	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");
	}
184
185
}

Michael Beck's avatar
Michael Beck committed
186
187
188
/**
 * Generate code for a sign extension.
 */
189
static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
Matthias Braun's avatar
Matthias Braun committed
190
                                   unsigned src_bits)
191
{
Matthias Braun's avatar
Matthias Braun committed
192
	unsigned shift_width = 32 - src_bits;
193
194
	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);
195
196
197
	return rshift_node;
}

198
199
200
static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
                              ir_mode *orig_mode)
{
Matthias Braun's avatar
Matthias Braun committed
201
	unsigned bits = get_mode_size_bits(orig_mode);
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
	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)
{
Matthias Braun's avatar
Matthias Braun committed
220
221
	(void)transformed_node;
	(void)mode;
222
223
224
225
	/* TODO */
	return false;
}

Michael Beck's avatar
Michael Beck committed
226
227
228
/**
 * Transforms a Conv node.
 *
229
 * @return The created ia32 Conv node
Michael Beck's avatar
Michael Beck committed
230
 */
231
232
static ir_node *gen_Conv(ir_node *node)
{
233
	ir_node  *block    = be_transform_nodes_block(node);
234
235
236
237
238
239
240
241
242
243
	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)) {
244
		if (arm_cg_config.fpu == ARM_FPU_FPA) {
245
246
			if (mode_is_float(src_mode)) {
				if (mode_is_float(dst_mode)) {
Michael Beck's avatar
Michael Beck committed
247
					/* from float to float */
248
					return new_bd_arm_Mvf(dbg, block, new_op, dst_mode);
249
				} else {
Michael Beck's avatar
Michael Beck committed
250
					/* from float to int */
251
					panic("TODO");
Michael Beck's avatar
Michael Beck committed
252
				}
253
			} else {
Michael Beck's avatar
Michael Beck committed
254
				/* from int to float */
255
256
257
258
259
				if (!mode_is_signed(src_mode)) {
					panic("TODO");
				} else {
					return new_bd_arm_FltX(dbg, block, new_op, dst_mode);
				}
Michael Beck's avatar
Michael Beck committed
260
			}
261
		} else {
262
			panic("softfloat not lowered");
Michael Beck's avatar
Michael Beck committed
263
		}
264
	} else { /* complete in gp registers */
Matthias Braun's avatar
Matthias Braun committed
265
266
		unsigned src_bits = get_mode_size_bits(src_mode);
		unsigned dst_bits = get_mode_size_bits(dst_mode);
Michael Beck's avatar
Michael Beck committed
267
		if (src_bits == dst_bits) {
Michael Beck's avatar
Michael Beck committed
268
			/* kill unnecessary conv */
Michael Beck's avatar
Michael Beck committed
269
			return new_op;
270
271
		}

Matthias Braun's avatar
Matthias Braun committed
272
273
		unsigned min_bits;
		ir_mode *min_mode;
274
275
276
		if (src_bits < dst_bits) {
			min_bits = src_bits;
			min_mode = src_mode;
Michael Beck's avatar
Michael Beck committed
277
		} else {
278
279
280
281
282
283
284
285
286
287
288
289
			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);
290
291
292
293
		}
	}
}

294
typedef struct {
Matthias Braun's avatar
Matthias Braun committed
295
296
	uint8_t imm_8;
	uint8_t rot;
297
298
} arm_immediate_t;

299
static bool try_encode_val_as_immediate(uint32_t val, arm_immediate_t *const res)
300
301
302
303
304
{
	if (val <= 0xff) {
		res->imm_8 = val;
		res->rot   = 0;
		return true;
Michael Beck's avatar
Michael Beck committed
305
	}
306
307
308
309
310
311
312
	/* 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.
	 */
Matthias Braun's avatar
Matthias Braun committed
313
314
	unsigned low_pos  = ntz(val) & ~1u;
	unsigned high_pos = (32-nlz(val)+1) & ~1u;
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333

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

334
335
336
337
typedef enum imm_match_t {
	IMM_NONE = 0,
	IMM_POS  = 1 << 0,
	IMM_NOT  = 1 << 1,
338
	IMM_NEG  = 1 << 2,
339
} imm_match_t;
340

341
static imm_match_t try_encode_as_immediate(ir_node const *const node, arm_immediate_t *const res, imm_match_t const match)
342
343
{
	if (!is_Const(node))
344
		return IMM_NONE;
345
	uint32_t const val = get_Const_long(node);
346
347
348
	return
		match & IMM_POS && try_encode_val_as_immediate( val, res) ? IMM_POS :
		match & IMM_NOT && try_encode_val_as_immediate(~val, res) ? IMM_NOT :
349
		match & IMM_NEG && try_encode_val_as_immediate(-val, res) ? IMM_NEG :
350
		IMM_NONE;
351
352
}

353
354
typedef enum {
	MATCH_NONE         = 0,
Michael Beck's avatar
Michael Beck committed
355
	MATCH_COMMUTATIVE  = 1 << 0,  /**< commutative node */
Michael Beck's avatar
Michael Beck committed
356
357
	MATCH_REVERSE      = 1 << 1,  /**< support reverse opcode */
	MATCH_SIZE_NEUTRAL = 1 << 2,
358
} match_flags_t;
359
ENUM_BITSET(match_flags_t)
360

Michael Beck's avatar
Michael Beck committed
361
362
363
364
365
366
367
368
369
370
371
372
373
/**
 * possible binop constructors.
 */
typedef struct arm_binop_factory_t {
	/** normal reg op reg operation. */
	ir_node *(*new_binop_reg)(dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2);
	/** normal reg op imm operation. */
	ir_node *(*new_binop_imm)(dbg_info *dbgi, ir_node *block, ir_node *op1, unsigned char imm8, unsigned char imm_rot);
	/** barrel shifter reg op (reg shift reg operation. */
	ir_node *(*new_binop_reg_shift_reg)(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right, ir_node *shift, arm_shift_modifier_t shift_modifier);
	/** barrel shifter reg op (reg shift imm operation. */
	ir_node *(*new_binop_reg_shift_imm)(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right, arm_shift_modifier_t shift_modifier, unsigned shift_immediate);
} arm_binop_factory_t;
374

Matthias Braun's avatar
Matthias Braun committed
375
376
377
static ir_node *gen_int_binop_ops(ir_node *node, ir_node *op1, ir_node *op2,
                                  match_flags_t flags,
                                  const arm_binop_factory_t *factory)
378
{
379
	ir_node  *block = be_transform_nodes_block(node);
Matthias Braun's avatar
Matthias Braun committed
380
	dbg_info *dbgi  = get_irn_dbg_info(node);
381
382

	if (flags & MATCH_SIZE_NEUTRAL) {
383
384
		op1 = be_skip_downconv(op1, true);
		op2 = be_skip_downconv(op2, true);
385
386
	} else {
		assert(get_mode_size_bits(get_irn_mode(node)) == 32);
387
388
		op1 = be_skip_sameconv(op1);
		op2 = be_skip_sameconv(op2);
389
390
	}

Matthias Braun's avatar
Matthias Braun committed
391
	arm_immediate_t imm;
392
	if (try_encode_as_immediate(op2, &imm, IMM_POS) != IMM_NONE) {
Matthias Braun's avatar
Matthias Braun committed
393
		ir_node *new_op1 = be_transform_node(op1);
Michael Beck's avatar
Michael Beck committed
394
		return factory->new_binop_imm(dbgi, block, new_op1, imm.imm_8, imm.rot);
395
	}
Matthias Braun's avatar
Matthias Braun committed
396
	ir_node *new_op2 = be_transform_node(op2);
397
    if ((flags & (MATCH_COMMUTATIVE|MATCH_REVERSE)) && try_encode_as_immediate(op1, &imm, IMM_POS) != IMM_NONE) {
Michael Beck's avatar
Michael Beck committed
398
399
400
401
		if (flags & MATCH_REVERSE)
			return factory[1].new_binop_imm(dbgi, block, new_op2, imm.imm_8, imm.rot);
		else
			return factory[0].new_binop_imm(dbgi, block, new_op2, imm.imm_8, imm.rot);
402
	}
Matthias Braun's avatar
Matthias Braun committed
403
	ir_node *new_op1 = be_transform_node(op1);
404

Michael Beck's avatar
Michael Beck committed
405
406
407
408
409
410
411
412
413
414
415
	/* check if we can fold in a Mov */
	if (is_arm_Mov(new_op2)) {
		const arm_shifter_operand_t *attr = get_arm_shifter_operand_attr_const(new_op2);

		switch (attr->shift_modifier) {
		case ARM_SHF_IMM:
		case ARM_SHF_ASR_IMM:
		case ARM_SHF_LSL_IMM:
		case ARM_SHF_LSR_IMM:
		case ARM_SHF_ROR_IMM:
			if (factory->new_binop_reg_shift_imm) {
416
				ir_node *mov_op = get_irn_n(new_op2, n_arm_Mov_Rm);
Michael Beck's avatar
Michael Beck committed
417
418
419
420
421
422
423
424
425
426
				return factory->new_binop_reg_shift_imm(dbgi, block, new_op1, mov_op,
					attr->shift_modifier, attr->shift_immediate);
			}
			break;

		case ARM_SHF_ASR_REG:
		case ARM_SHF_LSL_REG:
		case ARM_SHF_LSR_REG:
		case ARM_SHF_ROR_REG:
			if (factory->new_binop_reg_shift_reg) {
427
428
				ir_node *mov_op  = get_irn_n(new_op2, n_arm_Mov_Rm);
				ir_node *mov_sft = get_irn_n(new_op2, n_arm_Mov_Rs);
Michael Beck's avatar
Michael Beck committed
429
430
431
432
				return factory->new_binop_reg_shift_reg(dbgi, block, new_op1, mov_op, mov_sft,
					attr->shift_modifier);
			}
			break;
Matthias Braun's avatar
Matthias Braun committed
433
434
435
436
437
		case ARM_SHF_REG:
		case ARM_SHF_RRX:
			break;
		case ARM_SHF_INVALID:
			panic("invalid shift");
Michael Beck's avatar
Michael Beck committed
438
439
		}
	}
Michael Beck's avatar
Michael Beck committed
440
	if ((flags & (MATCH_COMMUTATIVE|MATCH_REVERSE)) && is_arm_Mov(new_op1)) {
Michael Beck's avatar
Michael Beck committed
441
		const arm_shifter_operand_t *attr = get_arm_shifter_operand_attr_const(new_op1);
Michael Beck's avatar
Michael Beck committed
442
		int idx = flags & MATCH_REVERSE ? 1 : 0;
Michael Beck's avatar
Michael Beck committed
443
444
445
446
447
448
449

		switch (attr->shift_modifier) {
		case ARM_SHF_IMM:
		case ARM_SHF_ASR_IMM:
		case ARM_SHF_LSL_IMM:
		case ARM_SHF_LSR_IMM:
		case ARM_SHF_ROR_IMM:
Michael Beck's avatar
Michael Beck committed
450
			if (factory[idx].new_binop_reg_shift_imm) {
451
				ir_node *mov_op = get_irn_n(new_op1, n_arm_Mov_Rm);
Michael Beck's avatar
Michael Beck committed
452
				return factory[idx].new_binop_reg_shift_imm(dbgi, block, new_op2, mov_op,
Michael Beck's avatar
Michael Beck committed
453
454
455
456
457
458
459
460
					attr->shift_modifier, attr->shift_immediate);
			}
			break;

		case ARM_SHF_ASR_REG:
		case ARM_SHF_LSL_REG:
		case ARM_SHF_LSR_REG:
		case ARM_SHF_ROR_REG:
Michael Beck's avatar
Michael Beck committed
461
			if (factory[idx].new_binop_reg_shift_reg) {
462
463
				ir_node *mov_op  = get_irn_n(new_op1, n_arm_Mov_Rm);
				ir_node *mov_sft = get_irn_n(new_op1, n_arm_Mov_Rs);
Michael Beck's avatar
Michael Beck committed
464
				return factory[idx].new_binop_reg_shift_reg(dbgi, block, new_op2, mov_op, mov_sft,
Michael Beck's avatar
Michael Beck committed
465
466
467
					attr->shift_modifier);
			}
			break;
Matthias Braun's avatar
Matthias Braun committed
468
469
470
471
472
473

		case ARM_SHF_REG:
		case ARM_SHF_RRX:
			break;
		case ARM_SHF_INVALID:
			panic("invalid shift");
Michael Beck's avatar
Michael Beck committed
474
475
476
		}
	}
	return factory->new_binop_reg(dbgi, block, new_op1, new_op2);
Michael Beck's avatar
Michael Beck committed
477
}
478

Matthias Braun's avatar
Matthias Braun committed
479
480
481
482
483
484
485
486
static ir_node *gen_int_binop(ir_node *node, match_flags_t flags,
                              const arm_binop_factory_t *factory)
{
	ir_node *op1 = get_binop_left(node);
	ir_node *op2 = get_binop_right(node);
	return gen_int_binop_ops(node, op1, op2, flags, factory);
}

487
488
489
490
static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2,
                        bool negate_op)
{
	dbg_info *dbgi    = get_irn_dbg_info(node);
491
	ir_node  *block   = be_transform_nodes_block(node);
492
493
494
495
496
497
498
499
500
501
502
503
	ir_node  *new_op1 = be_transform_node(op1);
	if (is_Const(op2)) {
		ir_tarval *tv   = get_Const_tarval(op2);
		ir_mode   *mode = get_irn_mode(node);
		long       bits = get_mode_size_bits(mode);
		if (tarval_is_long(tv) && bits == 32) {
			long val = get_tarval_long(tv);
			val = (negate_op ? bits - val : val) & 31;
			return new_bd_arm_Mov_reg_shift_imm(dbgi, block, new_op1, ARM_SHF_ROR_IMM, val);
		}
	}

Matthias Braun's avatar
Matthias Braun committed
504
	ir_node *new_op2 = be_transform_node(op2);
505
506
507
508
	if (negate_op) {
		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,
yb9976's avatar
yb9976 committed
509
	                                    ARM_SHF_ROR_REG);
510
511
}

Matthias Braun's avatar
Matthias Braun committed
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
static bool is_low_mask(ir_tarval *tv)
{
	return get_tarval_popcount(tv) == 16 && get_tarval_highest_bit(tv) == 15;
}

static bool is_high_mask(ir_tarval *tv)
{
	return get_tarval_popcount(tv) == 16 && get_tarval_lowest_bit(tv) == 16;
}

static ir_node *match_pkh(ir_node *node)
{
	assert(is_Or(node) || is_Add(node));
	ir_node *left  = get_binop_left(node);
	ir_node *right = get_binop_right(node);
	if (!is_And(left) || !is_And(right))
		return NULL;
	ir_node *left_right  = get_And_right(left);
	ir_node *right_right = get_And_right(right);
	if (!is_Const(left_right) || !is_Const(right_right))
		return NULL;
	/* we want the low-mask on the right side */
	if (is_high_mask(get_Const_tarval(left_right))) {
		ir_node *tmp = left;
yb9976's avatar
yb9976 committed
536
537
		left       = right;
		right      = tmp;
Matthias Braun's avatar
Matthias Braun committed
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
		left_right = right_right;
	} else if (!is_high_mask(get_Const_tarval(right_right))) {
		return NULL;
	}
	if (!is_low_mask(get_Const_tarval(left_right)))
		return NULL;
	ir_node *left_left  = get_And_left(left);
	ir_node *right_left = get_And_left(right);
	static const arm_binop_factory_t pkhbt_pkhtb_factory[2] = {
		{
			new_bd_arm_Pkhbt_reg,
			new_bd_arm_Pkhbt_imm,
			new_bd_arm_Pkhbt_reg_shift_reg,
			new_bd_arm_Pkhbt_reg_shift_imm
		},
		{
			new_bd_arm_Pkhtb_reg,
			new_bd_arm_Pkhtb_imm,
			new_bd_arm_Pkhtb_reg_shift_reg,
			new_bd_arm_Pkhtb_reg_shift_imm
		}
	};
	return gen_int_binop_ops(node, left_left, right_left, MATCH_REVERSE,
	                         pkhbt_pkhtb_factory);
}

564
/**
565
 * Creates an ARM Add.
566
567
568
 *
 * @return the created arm Add node
 */
569
570
static ir_node *gen_Add(ir_node *node)
{
571
572
573
574
575
576
577
	ir_node *rotl_left;
	ir_node *rotl_right;
	if (be_pattern_is_rotl(node, &rotl_left, &rotl_right)) {
		if (is_Minus(rotl_right))
			return gen_Ror(node, rotl_left, get_Minus_op(rotl_right), false);
		return gen_Ror(node, rotl_left, rotl_right, true);
	}
Matthias Braun's avatar
Matthias Braun committed
578
579
580
	ir_node *pkh = match_pkh(node);
	if (pkh != NULL)
		return pkh;
581

Michael Beck's avatar
Michael Beck committed
582
	ir_mode *mode = get_irn_mode(node);
583
	if (mode_is_float(mode)) {
584
		ir_node  *block   = be_transform_nodes_block(node);
585
586
587
588
589
		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);
590
		if (arm_cg_config.fpu == ARM_FPU_FPA) {
591
			return new_bd_arm_Adf(dbgi, block, new_op1, new_op2, mode);
592
		} else {
593
			panic("softfloat not lowered");
594
595
		}
	} else {
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
		ir_node *left  = get_Add_left(node);
		ir_node *right = get_Add_right(node);
		ir_node *mul_left;
		ir_node *mul_right;
		ir_node *other;
		if (is_Mul(left)) {
			mul_left  = get_Mul_left(left);
			mul_right = get_Mul_right(left);
			other     = right;
			goto create_mla;
		} else if (is_Mul(right)) {
			mul_left  = get_Mul_left(right);
			mul_right = get_Mul_right(right);
			other     = left;
create_mla:;
			dbg_info *dbgi      = get_irn_dbg_info(node);
612
			ir_node  *block     = be_transform_nodes_block(node);
613
614
615
616
			ir_node  *new_left  = be_transform_node(mul_left);
			ir_node  *new_right = be_transform_node(mul_right);
			ir_node  *new_add   = be_transform_node(other);
			if (arm_cg_config.variant < ARM_VARIANT_6)
617
				return new_bd_arm_Mla_v5(dbgi, block, new_left, new_right, new_add);
618
619
620
621
622
			else
				return new_bd_arm_Mla(dbgi, block, new_left, new_right,
				                      new_add);
		}

623
624
625
626
627
628
629
630
		arm_immediate_t imm;
		if (try_encode_as_immediate(right, &imm, IMM_NEG) != IMM_NONE) {
			dbg_info *const dbgi     = get_irn_dbg_info(node);
			ir_node  *const block    = be_transform_nodes_block(node);
			ir_node  *const new_left = be_transform_node(left);
			return new_bd_arm_Sub_imm(dbgi, block, new_left, imm.imm_8, imm.rot);
		}

631
632
633
634
635
636
637
638
639
		static const arm_binop_factory_t add_factory = {
			new_bd_arm_Add_reg,
			new_bd_arm_Add_imm,
			new_bd_arm_Add_reg_shift_reg,
			new_bd_arm_Add_reg_shift_imm
		};
		return gen_int_binop_ops(node, left, right,
		                         MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
		                         &add_factory);
Michael Beck's avatar
Michael Beck committed
640
641
	}
}
642

Matthias Braun's avatar
Matthias Braun committed
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
static ir_node *gen_arm_AddS_t(ir_node *node)
{
	static const arm_binop_factory_t adds_factory = {
		new_bd_arm_AddS_reg,
		new_bd_arm_AddS_imm,
		new_bd_arm_AddS_reg_shift_reg,
		new_bd_arm_AddS_reg_shift_imm,
	};
	ir_node *left  = get_irn_n(node, n_arm_AddS_t_left);
	ir_node *right = get_irn_n(node, n_arm_AddS_t_right);
	ir_node *res   = gen_int_binop_ops(node, left, right,
	                                   MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
	                                   &adds_factory);
	arch_set_irn_register_out(res, pn_arm_AddS_flags, &arm_registers[REG_FL]);
	return res;
}

static ir_node *gen_Proj_arm_AddS_t(ir_node *node)
{
662
	unsigned pn       = get_Proj_num(node);
Matthias Braun's avatar
Matthias Braun committed
663
664
665
666
	ir_node *pred     = get_Proj_pred(node);
	ir_node *new_pred = be_transform_node(pred);
	switch ((pn_arm_AddS_t)pn) {
	case pn_arm_AddS_t_res:
667
		return be_new_Proj(new_pred, pn_arm_AddS_res);
Matthias Braun's avatar
Matthias Braun committed
668
	case pn_arm_AddS_t_flags:
669
		return be_new_Proj(new_pred, pn_arm_AddS_flags);
Matthias Braun's avatar
Matthias Braun committed
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
	}
	panic("%+F: Invalid proj number", node);
}

static ir_node *gen_arm_AdC_t(ir_node *node)
{
	ir_node *left  = get_irn_n(node, n_arm_AdC_t_left);
	ir_node *right = get_irn_n(node, n_arm_AdC_t_right);
	ir_node *flags = get_irn_n(node, n_arm_AdC_t_flags);
	/* TODO: handle complete set of shifter operands */
	ir_node *new_left  = be_transform_node(left);
	ir_node *new_right = be_transform_node(right);
	ir_node *new_flags = be_transform_node(flags);

	dbg_info *dbgi      = get_irn_dbg_info(node);
685
	ir_node  *new_block = be_transform_nodes_block(node);
Matthias Braun's avatar
Matthias Braun committed
686
687
688
689
690
	ir_node  *res       = new_bd_arm_AdC_reg(dbgi, new_block, new_left,
	                                         new_right, new_flags);
	return res;
}

691
/**
692
 * Creates an ARM Mul.
693
694
695
 *
 * @return the created arm Mul node
 */
696
697
static ir_node *gen_Mul(ir_node *node)
{
698
	ir_node  *block   = be_transform_nodes_block(node);
699
700
701
702
703
704
	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
705

706
	if (mode_is_float(mode)) {
707
		if (arm_cg_config.fpu == ARM_FPU_FPA) {
708
			return new_bd_arm_Muf(dbg, block, new_op1, new_op2, mode);
709
		} else {
710
			panic("softfloat not lowered");
Michael Beck's avatar
Michael Beck committed
711
		}
712
	}
713
	if (arm_cg_config.variant < ARM_VARIANT_6) {
714
		return new_bd_arm_Mul_v5(dbg, block, new_op1, new_op2);
715
716
717
	} else {
		return new_bd_arm_Mul(dbg, block, new_op1, new_op2);
	}
718
719
}

Matthias Braun's avatar
Matthias Braun committed
720
721
static ir_node *gen_arm_UMulL_t(ir_node *node)
{
722
	ir_node  *block     = be_transform_nodes_block(node);
Matthias Braun's avatar
Matthias Braun committed
723
724
725
726
727
728
729
730
731
732
	ir_node  *left      = get_irn_n(node, n_arm_UMulL_t_left);
	ir_node  *new_left  = be_transform_node(left);
	ir_node  *right     = get_irn_n(node, n_arm_UMulL_t_right);
	ir_node  *new_right = be_transform_node(right);
	dbg_info *dbgi      = get_irn_dbg_info(node);
	return new_bd_arm_UMulL(dbgi, block, new_left, new_right);
}

static ir_node *gen_Proj_arm_UMulL_t(ir_node *node)
{
733
	unsigned pn       = get_Proj_num(node);
Matthias Braun's avatar
Matthias Braun committed
734
735
736
737
	ir_node *pred     = get_Proj_pred(node);
	ir_node *new_pred = be_transform_node(pred);
	switch ((pn_arm_UMulL_t)pn) {
	case pn_arm_UMulL_t_low:
738
		return be_new_Proj(new_pred, pn_arm_UMulL_low);
Matthias Braun's avatar
Matthias Braun committed
739
	case pn_arm_UMulL_t_high:
740
		return be_new_Proj(new_pred, pn_arm_UMulL_high);
Matthias Braun's avatar
Matthias Braun committed
741
742
743
744
	}
	panic("%+F: Invalid proj number", node);
}

745
static ir_node *gen_Div(ir_node *node)
746
{
747
	ir_node  *block   = be_transform_nodes_block(node);
748
	ir_node  *op1     = get_Div_left(node);
749
	ir_node  *new_op1 = be_transform_node(op1);
750
	ir_node  *op2     = get_Div_right(node);
751
	ir_node  *new_op2 = be_transform_node(op2);
752
	ir_mode  *mode    = get_Div_resmode(node);
753
	dbg_info *dbg     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
754

755
756
	/* integer division should be replaced by builtin call */
	assert(mode_is_float(mode));
757

758
	if (arm_cg_config.fpu == ARM_FPU_FPA) {
759
		return new_bd_arm_Dvf(dbg, block, new_op1, new_op2, mode);
760
	} else {
761
		panic("softfloat not lowered");
Michael Beck's avatar
Michael Beck committed
762
	}
Michael Beck's avatar
Michael Beck committed
763
764
}

765
766
static ir_node *gen_And(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
767
768
769
770
771
772
	static const arm_binop_factory_t and_factory = {
		new_bd_arm_And_reg,
		new_bd_arm_And_imm,
		new_bd_arm_And_reg_shift_reg,
		new_bd_arm_And_reg_shift_imm
	};
Michael Beck's avatar
Michael Beck committed
773
774
775
776
777
778
779
780
	static const arm_binop_factory_t bic_factory = {
		new_bd_arm_Bic_reg,
		new_bd_arm_Bic_imm,
		new_bd_arm_Bic_reg_shift_reg,
		new_bd_arm_Bic_reg_shift_imm
	};

	/* check for and not */
781
	arm_immediate_t imm;
Michael Beck's avatar
Michael Beck committed
782
783
	ir_node *left  = get_And_left(node);
	ir_node *right = get_And_right(node);
Matthias Braun's avatar
Matthias Braun committed
784
785
786
787
788
789
790
791
	if (is_Not(right)) {
		ir_node *right_not = get_Not_op(right);
		return gen_int_binop_ops(node, left, right_not, MATCH_SIZE_NEUTRAL,
		                         &bic_factory);
	} else if (is_Not(left)) {
		ir_node *left_not = get_Not_op(left);
		return gen_int_binop_ops(node, right, left_not, MATCH_SIZE_NEUTRAL,
		                         &bic_factory);
792
	} else if (try_encode_as_immediate(right, &imm, IMM_NOT) != IMM_NONE) {
793
794
795
796
		dbg_info *const dbgi  = get_irn_dbg_info(node);
		ir_node  *const block = be_transform_nodes_block(node);
		ir_node  *const new_l = be_transform_node(left);
		return new_bd_arm_Bic_imm(dbgi, block, new_l, imm.imm_8, imm.rot);
Matthias Braun's avatar
Matthias Braun committed
797
798
799
	} else {
		return gen_int_binop(node, MATCH_COMMUTATIVE|MATCH_SIZE_NEUTRAL,
		                     &and_factory);
Michael Beck's avatar
Michael Beck committed
800
	}
801
}
802

803
804
static ir_node *gen_Or(ir_node *node)
{
805
806
807
808
809
810
811
	ir_node *rotl_left;
	ir_node *rotl_right;
	if (be_pattern_is_rotl(node, &rotl_left, &rotl_right)) {
		if (is_Minus(rotl_right))
			return gen_Ror(node, rotl_left, get_Minus_op(rotl_right), false);
		return gen_Ror(node, rotl_left, rotl_right, true);
	}
Matthias Braun's avatar
Matthias Braun committed
812
813
814
	ir_node *pkh = match_pkh(node);
	if (pkh != NULL)
		return pkh;
815

Michael Beck's avatar
Michael Beck committed
816
817
818
819
820
821
822
	static const arm_binop_factory_t or_factory = {
		new_bd_arm_Or_reg,
		new_bd_arm_Or_imm,
		new_bd_arm_Or_reg_shift_reg,
		new_bd_arm_Or_reg_shift_imm
	};
	return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, &or_factory);
823
}
824

Matthias Braun's avatar
Matthias Braun committed
825
826
827
828
829
830
831
832
833
834
835
836
837
static ir_node *gen_arm_OrPl_t(ir_node *node)
{
	ir_node *left     = get_irn_n(node, n_arm_OrPl_t_left);
	ir_node *right    = get_irn_n(node, n_arm_OrPl_t_right);
	ir_node *falseval = get_irn_n(node, n_arm_OrPl_t_falseval);
	ir_node *flags    = get_irn_n(node, n_arm_OrPl_t_flags);
	/* TODO: handle complete set of shifter operands */
	ir_node *new_left     = be_transform_node(left);
	ir_node *new_right    = be_transform_node(right);
	ir_node *new_falseval = be_transform_node(falseval);
	ir_node *new_flags    = be_transform_node(flags);

	dbg_info *dbgi      = get_irn_dbg_info(node);
838
	ir_node  *new_block = be_transform_nodes_block(node);
Matthias Braun's avatar
Matthias Braun committed
839
840
841
842
843
	ir_node  *res       = new_bd_arm_OrPl(dbgi, new_block, new_left, new_right,
	                                      new_falseval, new_flags);
	return res;
}

844
845
static ir_node *gen_Eor(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
846
847
848
849
850
851
	static const arm_binop_factory_t eor_factory = {
		new_bd_arm_Eor_reg,
		new_bd_arm_Eor_imm,
		new_bd_arm_Eor_reg_shift_reg,
		new_bd_arm_Eor_reg_shift_imm
	};
Matthias Braun's avatar
Matthias Braun committed
852
853
	return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL,
	                     &eor_factory);
854
}
855

856
857
static ir_node *gen_Sub(ir_node *node)
{
858
859
860
	ir_mode *mode  = get_irn_mode(node);
	ir_node *left  = get_Sub_left(node);
	ir_node *right = get_Sub_right(node);
861
	if (mode_is_float(mode)) {
862
		ir_node  *block     = be_transform_nodes_block(node);
863
864
865
866
		ir_node  *new_left  = be_transform_node(left);
		ir_node  *new_right = be_transform_node(right);
		dbg_info *dbgi      = get_irn_dbg_info(node);

867
		if (arm_cg_config.fpu == ARM_FPU_FPA) {
868
			return new_bd_arm_Suf(dbgi, block, new_left, new_right, mode);
869
		} else {
870
			panic("softfloat not lowered");
Michael Beck's avatar
Michael Beck committed
871
		}
872
	} else {
873
874
		if (is_Mul(right) && arm_cg_config.variant >= ARM_VARIANT_6T2) {
			dbg_info *dbgi      = get_irn_dbg_info(node);
875
			ir_node  *block     = be_transform_nodes_block(node);
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
			ir_node  *mul_left  = get_Mul_left(right);
			ir_node  *mul_right = get_Mul_right(right);
			ir_node  *new_left  = be_transform_node(mul_left);
			ir_node  *new_right = be_transform_node(mul_right);
			ir_node  *new_sub   = be_transform_node(left);
			return new_bd_arm_Mls(dbgi, block, new_left, new_right, new_sub);
		}

		static const arm_binop_factory_t sub_rsb_factory[2] = {
			{
				new_bd_arm_Sub_reg,
				new_bd_arm_Sub_imm,
				new_bd_arm_Sub_reg_shift_reg,
				new_bd_arm_Sub_reg_shift_imm
			},
			{
				new_bd_arm_Rsb_reg,
				new_bd_arm_Rsb_imm,
				new_bd_arm_Rsb_reg_shift_reg,
				new_bd_arm_Rsb_reg_shift_imm
			}
		};
Michael Beck's avatar
Michael Beck committed
898
		return gen_int_binop(node, MATCH_SIZE_NEUTRAL | MATCH_REVERSE, sub_rsb_factory);
Michael Beck's avatar
Michael Beck committed
899
	}
900
}
Michael Beck's avatar
Michael Beck committed
901

Matthias Braun's avatar
Matthias Braun committed
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
static ir_node *gen_arm_SubS_t(ir_node *node)
{
	static const arm_binop_factory_t subs_factory[2] = {
		{
			new_bd_arm_SubS_reg,
			new_bd_arm_SubS_imm,
			new_bd_arm_SubS_reg_shift_reg,
			new_bd_arm_SubS_reg_shift_imm,
		},
		{
			new_bd_arm_RsbS_reg,
			new_bd_arm_RsbS_imm,
			new_bd_arm_RsbS_reg_shift_reg,
			new_bd_arm_RsbS_reg_shift_imm,
		},
	};
	ir_node *left  = get_irn_n(node, n_arm_SubS_t_left);
	ir_node *right = get_irn_n(node, n_arm_SubS_t_right);
	ir_node *res   = gen_int_binop_ops(node, left, right,
	                                   MATCH_SIZE_NEUTRAL | MATCH_REVERSE,
	                                   subs_factory);
	assert((int)pn_arm_SubS_flags == (int)pn_arm_RsbS_flags);
	arch_set_irn_register_out(res, pn_arm_SubS_flags, &arm_registers[REG_FL]);
	return res;
}

static ir_node *gen_Proj_arm_SubS_t(ir_node *node)
{
930
	unsigned pn       = get_Proj_num(node);
Matthias Braun's avatar
Matthias Braun committed
931
932
933
934
935
936
	ir_node *pred     = get_Proj_pred(node);
	ir_node *new_pred = be_transform_node(pred);
	assert((int)pn_arm_SubS_flags == (int)pn_arm_RsbS_flags);
	assert((int)pn_arm_SubS_res == (int)pn_arm_RsbS_res);
	switch ((pn_arm_SubS_t)pn) {
	case pn_arm_SubS_t_res:
937
		return be_new_Proj(new_pred, pn_arm_SubS_res);
Matthias Braun's avatar
Matthias Braun committed
938
	case pn_arm_SubS_t_flags:
939
		return be_new_Proj(new_pred, pn_arm_SubS_flags);
Matthias Braun's avatar
Matthias Braun committed
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
	}
	panic("%+F: Invalid proj number", node);
}

static ir_node *gen_arm_SbC_t(ir_node *node)
{
	ir_node *left  = get_irn_n(node, n_arm_SbC_t_left);
	ir_node *right = get_irn_n(node, n_arm_SbC_t_right);
	ir_node *flags = get_irn_n(node, n_arm_SbC_t_flags);
	/* TODO: handle complete set of shifter operands */
	ir_node *new_left  = be_transform_node(left);
	ir_node *new_right = be_transform_node(right);
	ir_node *new_flags = be_transform_node(flags);

	dbg_info *dbgi      = get_irn_dbg_info(node);
955
	ir_node  *new_block = be_transform_nodes_block(node);
Matthias Braun's avatar
Matthias Braun committed
956
957
958
959
960
	ir_node  *res       = new_bd_arm_SbC_reg(dbgi, new_block, new_left,
	                                         new_right, new_flags);
	return res;
}

Michael Beck's avatar
Michael Beck committed
961
962
963
964
/**
 * Checks if a given value can be used as an immediate for the given
 * ARM shift mode.
 */
965
966
967
968
969
970
971
972
973
974
static bool can_use_shift_constant(unsigned int val,
                                   arm_shift_modifier_t modifier)
{
	if (val <= 31)
		return true;
	if (val == 32 && modifier != ARM_SHF_LSL_REG && modifier != ARM_SHF_ROR_REG)
		return true;
	return false;
}

Michael Beck's avatar
Michael Beck committed
975
976
977
978
979
980
981
/**
 * generate an ARM shift instruction.
 *
 * @param node            the node
 * @param flags           matching flags
 * @param shift_modifier  initial encoding of the desired shift operation
 */
982
static ir_node *make_shift(ir_node *node, match_flags_t flags,
983
		arm_shift_modifier_t shift_modifier)
984
{
985
	ir_node  *block = be_transform_nodes_block(node);
986
987
988
	ir_node  *op1   = get_binop_left(node);
	ir_node  *op2   = get_binop_right(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
989
	ir_mode  *mode  = get_irn_mode(node);
Matthias Braun's avatar
Matthias Braun committed
990
991
	if (get_mode_modulo_shift(mode) != 256)
		panic("modulo shift!=256 not supported");
992

993
	if (flags & MATCH_SIZE_NEUTRAL) {
994
995
		op1 = be_skip_downconv(op1, true);
		op2 = be_skip_downconv(op2, true);
996
	}
997

Matthias Braun's avatar
Matthias Braun committed
998
	ir_node *new_op1 = be_transform_node(op1);
999
	if (is_Const(op2)) {
1000
		unsigned int const val = get_Const_long(op2);
For faster browsing, not all history is shown. View entire blame