arm_transform.c 67 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 "bearch_arm_t.h"
12
13
14
15
16
17
18
19
20
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
#include "irgmod.h"
#include "iredges.h"
#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
28
29
#include "benode.h"
#include "beirg.h"
#include "beutil.h"
#include "betranshlp.h"
#include "beabihelper.h"
#include "beabi.h"
30
31
32

#include "arm_nodes_attr.h"
#include "arm_transform.h"
33
#include "arm_optimize.h"
34
#include "arm_new_nodes.h"
35
#include "arm_cconv.h"
36
37

#include "gen_arm_regalloc_if.h"
Matthias Braun's avatar
Matthias Braun committed
38
#include "gen_arm_new_nodes.h"
39
40
41

#include <limits.h>

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

44
45
46
47
48
typedef struct start_val_t {
	unsigned offset;
	ir_node *irn;
} start_val_t;

49
static const arch_register_t *sp_reg = &arm_registers[REG_SP];
50
static ir_mode               *mode_fp;
51
static be_stackorder_t       *stackorder;
52
static calling_convention_t  *cconv = NULL;
53
54
55
56
static start_val_t            start_mem;
static start_val_t            start_sp;
static unsigned               start_params_offset;
static unsigned               start_callee_saves_offset;
57
58
static pmap                  *node_to_stack;

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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],
};

Matthias Braun's avatar
Matthias Braun committed
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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
118
/**
119
 * create firm graph for a constant
Michael Beck's avatar
Michael Beck committed
120
 */
121
static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
Matthias Braun's avatar
Matthias Braun committed
122
                                         uint32_t value)
123
{
124
125
126
127
128
129
	/* 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
130
	arm_vals v;
131
	arm_gen_vals_from_word(value, &v);
Matthias Braun's avatar
Matthias Braun committed
132
	arm_vals vn;
133
	arm_gen_vals_from_word(~value, &vn);
Michael Beck's avatar
Michael Beck committed
134

Matthias Braun's avatar
Matthias Braun committed
135
	ir_node *result;
Michael Beck's avatar
Michael Beck committed
136
137
	if (vn.ops < v.ops) {
		/* remove bits */
138
		result = new_bd_arm_Mvn_imm(dbgi, block, vn.values[0], vn.rors[0]);
Michael Beck's avatar
Michael Beck committed
139

Matthias Braun's avatar
Matthias Braun committed
140
		for (unsigned cnt = 1; cnt < vn.ops; ++cnt) {
141
142
			result = new_bd_arm_Bic_imm(dbgi, block, result,
			                            vn.values[cnt], vn.rors[cnt]);
143
		}
144
	} else {
Michael Beck's avatar
Michael Beck committed
145
		/* add bits */
146
		result = new_bd_arm_Mov_imm(dbgi, block, v.values[0], v.rors[0]);
Michael Beck's avatar
Michael Beck committed
147

Matthias Braun's avatar
Matthias Braun committed
148
		for (unsigned cnt = 1; cnt < v.ops; ++cnt) {
149
150
			result = new_bd_arm_Or_imm(dbgi, block, result,
			                           v.values[cnt], v.rors[cnt]);
Michael Beck's avatar
Michael Beck committed
151
		}
152
153
154
155
	}
	return result;
}

156
157
158
159
160
/**
 * Create a DAG constructing a given Const.
 *
 * @param irn  a Firm const
 */
161
162
static ir_node *create_const_graph(ir_node *irn, ir_node *block)
{
Matthias Braun's avatar
Matthias Braun committed
163
164
	ir_tarval *tv   = get_Const_tarval(irn);
	ir_mode   *mode = get_tarval_mode(tv);
165
166
	if (mode_is_reference(mode)) {
		/* ARM is 32bit, so we can safely convert a reference tarval into Iu */
167
168
		assert(get_mode_size_bits(mode) == get_mode_size_bits(arm_mode_gp));
		tv = tarval_convert_to(tv, arm_mode_gp);
169
	}
Matthias Braun's avatar
Matthias Braun committed
170
	long value = get_tarval_long(tv);
171
	return create_const_graph_value(get_irn_dbg_info(irn), block, value);
172
173
}

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
static void make_start_out(start_val_t *const info, struct obstack *const obst,
                           ir_node *const start, size_t const offset,
                           arch_register_t const *const reg,
                           arch_register_req_type_t const flags)
{
	info->offset = offset;
	info->irn    = NULL;
	arch_register_req_t const *const req
		= be_create_reg_req(obst, reg, arch_register_req_type_ignore | flags);
	arch_set_irn_register_req_out(start, offset, req);
	arch_set_irn_register_out(start, offset, reg);
}

static ir_node *get_start_val(ir_graph *irg, start_val_t *const info)
{
	if (info->irn == NULL) {
		ir_node *const start = get_irg_start(irg);
		arch_register_class_t const *const cls
			= arch_get_irn_register_req_out(start, info->offset)->cls;
		ir_mode *mode = cls != NULL ? cls->mode : mode_M;
		info->irn = new_r_Proj(start, mode, info->offset);
	}
	return info->irn;
}

Michael Beck's avatar
Michael Beck committed
199
/**
Michael Beck's avatar
Michael Beck committed
200
201
202
203
204
205
 * 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
206
 */
207
static ir_node *gen_zero_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
Matthias Braun's avatar
Matthias Braun committed
208
                                   unsigned src_bits)
209
210
211
212
213
214
215
216
217
218
{
	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");
	}
219
220
}

Michael Beck's avatar
Michael Beck committed
221
222
223
/**
 * Generate code for a sign extension.
 */
224
static ir_node *gen_sign_extension(dbg_info *dbgi, ir_node *block, ir_node *op,
Matthias Braun's avatar
Matthias Braun committed
225
                                   unsigned src_bits)
226
{
Matthias Braun's avatar
Matthias Braun committed
227
	unsigned shift_width = 32 - src_bits;
228
229
	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);
230
231
232
	return rshift_node;
}

233
234
235
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
236
	unsigned bits = get_mode_size_bits(orig_mode);
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
	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
255
256
	(void)transformed_node;
	(void)mode;
257
258
259
260
	/* TODO */
	return false;
}

Michael Beck's avatar
Michael Beck committed
261
262
263
/**
 * Transforms a Conv node.
 *
264
 * @return The created ia32 Conv node
Michael Beck's avatar
Michael Beck committed
265
 */
266
267
static ir_node *gen_Conv(ir_node *node)
{
268
269
270
271
272
273
274
275
276
277
278
	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)) {
279
		if (arm_cg_config.use_fpa) {
280
281
			if (mode_is_float(src_mode)) {
				if (mode_is_float(dst_mode)) {
Michael Beck's avatar
Michael Beck committed
282
					/* from float to float */
283
					return new_bd_arm_Mvf(dbg, block, new_op, dst_mode);
284
				} else {
Michael Beck's avatar
Michael Beck committed
285
					/* from float to int */
286
					panic("TODO");
Michael Beck's avatar
Michael Beck committed
287
				}
288
			} else {
Michael Beck's avatar
Michael Beck committed
289
				/* from int to float */
290
291
292
293
294
				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
295
			}
296
		} else if (arm_cg_config.use_vfp) {
297
			panic("VFP not supported yet");
298
		} else {
299
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
300
		}
301
	} else { /* complete in gp registers */
Matthias Braun's avatar
Matthias Braun committed
302
303
		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
304
		if (src_bits == dst_bits) {
Michael Beck's avatar
Michael Beck committed
305
			/* kill unnecessary conv */
Michael Beck's avatar
Michael Beck committed
306
			return new_op;
307
308
		}

Matthias Braun's avatar
Matthias Braun committed
309
310
		unsigned min_bits;
		ir_mode *min_mode;
311
312
313
		if (src_bits < dst_bits) {
			min_bits = src_bits;
			min_mode = src_mode;
Michael Beck's avatar
Michael Beck committed
314
		} else {
315
316
317
318
319
320
321
322
323
324
325
326
			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);
327
328
329
330
		}
	}
}

331
typedef struct {
Matthias Braun's avatar
Matthias Braun committed
332
333
	uint8_t imm_8;
	uint8_t rot;
334
335
336
337
338
339
} arm_immediate_t;

static bool try_encode_as_immediate(const ir_node *node, arm_immediate_t *res)
{
	if (!is_Const(node))
		return false;
Michael Beck's avatar
Michael Beck committed
340

Matthias Braun's avatar
Matthias Braun committed
341
	uint32_t val = get_tarval_long(get_Const_tarval(node));
Michael Beck's avatar
Michael Beck committed
342

343
344
345
346
347
348
349
350
351
	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
352
	}
353
354
355
356
357
358
359
	/* 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
360
361
	unsigned low_pos  = ntz(val) & ~1u;
	unsigned high_pos = (32-nlz(val)+1) & ~1u;
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380

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

381
static bool is_downconv(const ir_node *node)
382
383
{
	if (!is_Conv(node))
384
		return false;
385
386

	/* we only want to skip the conv when we're the only user
Matthias Braun's avatar
Matthias Braun committed
387
	 * (not optimal but for now...) */
388
	if (get_irn_n_edges(node) > 1)
389
		return false;
390

Matthias Braun's avatar
Matthias Braun committed
391
392
	ir_mode *src_mode  = get_irn_mode(get_Conv_op(node));
	ir_mode *dest_mode = get_irn_mode(node);
Matthias Braun's avatar
Matthias Braun committed
393
394
	return get_mode_arithmetic(src_mode) == irma_twos_complement
	    && get_mode_arithmetic(dest_mode) == irma_twos_complement
Matthias Braun's avatar
Matthias Braun committed
395
	    && get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
396
397
398
399
400
401
402
403
404
405
406
}

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,
Michael Beck's avatar
Michael Beck committed
407
	MATCH_COMMUTATIVE  = 1 << 0,  /**< commutative node */
Michael Beck's avatar
Michael Beck committed
408
409
	MATCH_REVERSE      = 1 << 1,  /**< support reverse opcode */
	MATCH_SIZE_NEUTRAL = 1 << 2,
410
} match_flags_t;
411
ENUM_BITSET(match_flags_t)
412

Michael Beck's avatar
Michael Beck committed
413
414
415
416
417
418
419
420
421
422
423
424
425
/**
 * 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;
426

Matthias Braun's avatar
Matthias Braun committed
427
428
429
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)
430
{
Matthias Braun's avatar
Matthias Braun committed
431
432
	ir_node  *block = be_transform_node(get_nodes_block(node));
	dbg_info *dbgi  = get_irn_dbg_info(node);
433
434
435
436
437
438
439
440

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

Matthias Braun's avatar
Matthias Braun committed
441
	arm_immediate_t imm;
442
	if (try_encode_as_immediate(op2, &imm)) {
Matthias Braun's avatar
Matthias Braun committed
443
		ir_node *new_op1 = be_transform_node(op1);
Michael Beck's avatar
Michael Beck committed
444
		return factory->new_binop_imm(dbgi, block, new_op1, imm.imm_8, imm.rot);
445
	}
Matthias Braun's avatar
Matthias Braun committed
446
	ir_node *new_op2 = be_transform_node(op2);
Michael Beck's avatar
Michael Beck committed
447
448
449
450
451
    if ((flags & (MATCH_COMMUTATIVE|MATCH_REVERSE)) && try_encode_as_immediate(op1, &imm)) {
		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);
452
	}
Matthias Braun's avatar
Matthias Braun committed
453
	ir_node *new_op1 = be_transform_node(op1);
454

Michael Beck's avatar
Michael Beck committed
455
456
457
458
459
460
461
462
463
464
465
	/* 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) {
Michael Beck's avatar
Michael Beck committed
466
				ir_node *mov_op = get_irn_n(new_op2, 0);
Michael Beck's avatar
Michael Beck committed
467
468
469
470
471
472
473
474
475
476
				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) {
Michael Beck's avatar
Michael Beck committed
477
478
				ir_node *mov_op  = get_irn_n(new_op2, 0);
				ir_node *mov_sft = get_irn_n(new_op2, 1);
Michael Beck's avatar
Michael Beck committed
479
480
481
482
				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
483
484
485
486
487
		case ARM_SHF_REG:
		case ARM_SHF_RRX:
			break;
		case ARM_SHF_INVALID:
			panic("invalid shift");
Michael Beck's avatar
Michael Beck committed
488
489
		}
	}
Michael Beck's avatar
Michael Beck committed
490
	if ((flags & (MATCH_COMMUTATIVE|MATCH_REVERSE)) && is_arm_Mov(new_op1)) {
Michael Beck's avatar
Michael Beck committed
491
		const arm_shifter_operand_t *attr = get_arm_shifter_operand_attr_const(new_op1);
Michael Beck's avatar
Michael Beck committed
492
		int idx = flags & MATCH_REVERSE ? 1 : 0;
Michael Beck's avatar
Michael Beck committed
493
494
495
496
497
498
499

		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
500
			if (factory[idx].new_binop_reg_shift_imm) {
Matthias Braun's avatar
Matthias Braun committed
501
				ir_node *mov_op = get_irn_n(new_op1, 0);
Michael Beck's avatar
Michael Beck committed
502
				return factory[idx].new_binop_reg_shift_imm(dbgi, block, new_op2, mov_op,
Michael Beck's avatar
Michael Beck committed
503
504
505
506
507
508
509
510
					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
511
			if (factory[idx].new_binop_reg_shift_reg) {
Matthias Braun's avatar
Matthias Braun committed
512
513
				ir_node *mov_op  = get_irn_n(new_op1, 0);
				ir_node *mov_sft = get_irn_n(new_op1, 1);
Michael Beck's avatar
Michael Beck committed
514
				return factory[idx].new_binop_reg_shift_reg(dbgi, block, new_op2, mov_op, mov_sft,
Michael Beck's avatar
Michael Beck committed
515
516
517
					attr->shift_modifier);
			}
			break;
Matthias Braun's avatar
Matthias Braun committed
518
519
520
521
522
523

		case ARM_SHF_REG:
		case ARM_SHF_RRX:
			break;
		case ARM_SHF_INVALID:
			panic("invalid shift");
Michael Beck's avatar
Michael Beck committed
524
525
526
		}
	}
	return factory->new_binop_reg(dbgi, block, new_op1, new_op2);
Michael Beck's avatar
Michael Beck committed
527
}
528

Matthias Braun's avatar
Matthias Braun committed
529
530
531
532
533
534
535
536
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);
}

537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
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);
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	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
554
	ir_node *new_op2 = be_transform_node(op2);
555
556
557
558
559
560
561
	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,
											ARM_SHF_ROR_REG);
}

562
/**
563
 * Creates an ARM Add.
564
565
566
 *
 * @return the created arm Add node
 */
567
568
static ir_node *gen_Add(ir_node *node)
{
569
570
571
572
573
574
575
576
	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);
	}

Michael Beck's avatar
Michael Beck committed
577
578
579
580
581
582
583
584
	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
	};

	ir_mode *mode = get_irn_mode(node);
585
	if (mode_is_float(mode)) {
586
587
588
589
590
591
		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);
592
		if (arm_cg_config.use_fpa) {
593
			return new_bd_arm_Adf(dbgi, block, new_op1, new_op2, mode);
594
		} else if (arm_cg_config.use_vfp) {
595
			panic("VFP not supported yet");
596
		} else {
597
			panic("Softfloat not supported yet");
598
599
		}
	} else {
Matthias Braun's avatar
Matthias Braun committed
600
		/* TODO: check for MLA */
Michael Beck's avatar
Michael Beck committed
601
		return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, &add_factory);
Michael Beck's avatar
Michael Beck committed
602
603
	}
}
604

Matthias Braun's avatar
Matthias Braun committed
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
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)
{
	long     pn       = get_Proj_proj(node);
	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:
		return new_r_Proj(new_pred, arm_mode_gp, pn_arm_AddS_res);
	case pn_arm_AddS_t_flags:
		return new_r_Proj(new_pred, arm_mode_flags, pn_arm_AddS_flags);
	}
	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);
	ir_node  *block     = get_nodes_block(node);
	ir_node  *new_block = be_transform_node(block);
	ir_node  *res       = new_bd_arm_AdC_reg(dbgi, new_block, new_left,
	                                         new_right, new_flags);
	return res;
}

654
/**
655
 * Creates an ARM Mul.
656
657
658
 *
 * @return the created arm Mul node
 */
659
660
static ir_node *gen_Mul(ir_node *node)
{
661
662
663
664
665
666
667
	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
668

669
	if (mode_is_float(mode)) {
670
		if (arm_cg_config.use_fpa) {
671
			return new_bd_arm_Muf(dbg, block, new_op1, new_op2, mode);
672
		} else if (arm_cg_config.use_vfp) {
673
			panic("VFP not supported yet");
674
		} else {
675
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
676
		}
677
	}
678
	assert(mode_is_data(mode));
679
	if (arm_cg_config.variant < ARM_VARIANT_6) {
680
681
682
683
		return new_bd_arm_Mulv5(dbg, block, new_op1, new_op2);
	} else {
		return new_bd_arm_Mul(dbg, block, new_op1, new_op2);
	}
684
685
}

Matthias Braun's avatar
Matthias Braun committed
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
static ir_node *gen_arm_UMulL_t(ir_node *node)
{
	ir_node  *block     = be_transform_node(get_nodes_block(node));
	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)
{
	long     pn       = get_Proj_proj(node);
	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:
		return new_r_Proj(new_pred, arm_mode_gp, pn_arm_UMulL_low);
	case pn_arm_UMulL_t_high:
		return new_r_Proj(new_pred, arm_mode_gp, pn_arm_UMulL_high);
	}
	panic("%+F: Invalid proj number", node);
}

static ir_node *gen_arm_Mla_t(ir_node *node)
{
	ir_node  *block     = be_transform_node(get_nodes_block(node));
	ir_node  *left      = get_irn_n(node, n_arm_Mla_t_left);
	ir_node  *new_left  = be_transform_node(left);
	ir_node  *right     = get_irn_n(node, n_arm_Mla_t_right);
	ir_node  *new_right = be_transform_node(right);
	ir_node  *add       = get_irn_n(node, n_arm_Mla_t_add);
	ir_node  *new_add   = be_transform_node(add);
	dbg_info *dbgi      = get_irn_dbg_info(node);
	return new_bd_arm_Mla(dbgi, block, new_left, new_right, new_add);
}

724
static ir_node *gen_Div(ir_node *node)
725
{
726
	ir_node  *block   = be_transform_node(get_nodes_block(node));
727
	ir_node  *op1     = get_Div_left(node);
728
	ir_node  *new_op1 = be_transform_node(op1);
729
	ir_node  *op2     = get_Div_right(node);
730
	ir_node  *new_op2 = be_transform_node(op2);
731
	ir_mode  *mode    = get_Div_resmode(node);
732
	dbg_info *dbg     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
733

734
735
	/* integer division should be replaced by builtin call */
	assert(mode_is_float(mode));
736

737
	if (arm_cg_config.use_fpa) {
738
		return new_bd_arm_Dvf(dbg, block, new_op1, new_op2, mode);
739
	} else if (arm_cg_config.use_vfp) {
740
		panic("VFP not supported yet");
741
	} else {
742
		panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
743
	}
Michael Beck's avatar
Michael Beck committed
744
745
}

746
747
static ir_node *gen_And(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
748
749
750
751
752
753
	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
754
755
756
757
758
759
760
761
762
763
	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 */
	ir_node *left  = get_And_left(node);
	ir_node *right = get_And_right(node);
Matthias Braun's avatar
Matthias Braun committed
764
765
766
767
768
769
770
771
772
773
774
	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);
	} else {
		return gen_int_binop(node, MATCH_COMMUTATIVE|MATCH_SIZE_NEUTRAL,
		                     &and_factory);
Michael Beck's avatar
Michael Beck committed
775
	}
776
}
777

778
779
static ir_node *gen_Or(ir_node *node)
{
780
781
782
783
784
785
786
787
	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);
	}

Michael Beck's avatar
Michael Beck committed
788
789
790
791
792
793
794
	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);
795
}
796

Matthias Braun's avatar
Matthias Braun committed
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
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);
	ir_node  *block     = get_nodes_block(node);
	ir_node  *new_block = be_transform_node(block);
	ir_node  *res       = new_bd_arm_OrPl(dbgi, new_block, new_left, new_right,
	                                      new_falseval, new_flags);
	return res;
}

817
818
static ir_node *gen_Eor(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
819
820
821
822
823
824
825
	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
	};
	return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, &eor_factory);
826
}
827

828
829
static ir_node *gen_Sub(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
830
831
832
833
834
835
836
837
838
839
840
841
842
	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
843
844
	};

845
846
847
848
	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
849
	ir_node  *new_op2 = be_transform_node(op2);
850
	ir_mode  *mode    = get_irn_mode(node);
851
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
852

853
	if (mode_is_float(mode)) {
854
		if (arm_cg_config.use_fpa) {
855
			return new_bd_arm_Suf(dbgi, block, new_op1, new_op2, mode);
856
		} else if (arm_cg_config.use_vfp) {
857
			panic("VFP not supported yet");
858
		} else {
859
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
860
		}
861
	} else {
Michael Beck's avatar
Michael Beck committed
862
		return gen_int_binop(node, MATCH_SIZE_NEUTRAL | MATCH_REVERSE, sub_rsb_factory);
Michael Beck's avatar
Michael Beck committed
863
	}
864
}
Michael Beck's avatar
Michael Beck committed
865

Matthias Braun's avatar
Matthias Braun committed
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
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)
{
	long     pn       = get_Proj_proj(node);
	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:
		return new_r_Proj(new_pred, arm_mode_gp, pn_arm_SubS_res);
	case pn_arm_SubS_t_flags:
		return new_r_Proj(new_pred, arm_mode_flags, pn_arm_SubS_flags);
	}
	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);
	ir_node  *block     = get_nodes_block(node);
	ir_node  *new_block = be_transform_node(block);
	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
926
927
928
929
/**
 * Checks if a given value can be used as an immediate for the given
 * ARM shift mode.
 */
930
931
932
933
934
935
936
937
938
939
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
940
941
942
943
944
945
946
/**
 * generate an ARM shift instruction.
 *
 * @param node            the node
 * @param flags           matching flags
 * @param shift_modifier  initial encoding of the desired shift operation
 */
947
static ir_node *make_shift(ir_node *node, match_flags_t flags,
948
		arm_shift_modifier_t shift_modifier)
949
{
950
951
952
953
	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);
954
	ir_mode  *mode  = get_irn_mode(node);
Matthias Braun's avatar
Matthias Braun committed
955
956
	if (get_mode_modulo_shift(mode) != 256)
		panic("modulo shift!=256 not supported");
957

958
959
960
	if (flags & MATCH_SIZE_NEUTRAL) {
		op1 = arm_skip_downconv(op1);
		op2 = arm_skip_downconv(op2);
961
	}
962

Matthias Braun's avatar
Matthias Braun committed
963
	ir_node *new_op1 = be_transform_node(op1);
964
	if (is_Const(op2)) {
Matthias Braun's avatar
Matthias Braun committed
965
		ir_tarval   *tv  = get_Const_tarval(op2);
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
		unsigned int val = get_tarval_long(tv);
		assert(tarval_is_long(tv));
		if (can_use_shift_constant(val, shift_modifier)) {
			switch (shift_modifier) {
			case ARM_SHF_LSL_REG: shift_modifier = ARM_SHF_LSL_IMM; break;
			case ARM_SHF_LSR_REG: shift_modifier = ARM_SHF_LSR_IMM; break;
			case ARM_SHF_ASR_REG: shift_modifier = ARM_SHF_ASR_IMM; break;
			case ARM_SHF_ROR_REG: shift_modifier = ARM_SHF_ROR_IMM; break;
			default: panic("unexpected shift modifier");
			}
			return new_bd_arm_Mov_reg_shift_imm(dbgi, block, new_op1,
			                                    shift_modifier, val);
		}
	}

Matthias Braun's avatar
Matthias Braun committed
981
	ir_node *new_op2 = be_transform_node(op2);
982
983
	return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
	                                    shift_modifier);
984
985
}

986
987
988
static ir_node *gen_Shl(ir_node *node)
{
	return make_shift(node, MATCH_SIZE_NEUTRAL, ARM_SHF_LSL_REG);
989
990
}

991
992
993
static ir_node *gen_Shr(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_LSR_REG);
994
995
}

996
997
998
static ir_node *gen_Shrs(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_ASR_REG);
999
1000
}

For faster browsing, not all history is shown. View entire blame