arm_transform.c 55.2 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2010 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
 * @brief   The codegenerator (transform FIRM into arm FIRM)
23
 * @author  Matthias Braun, 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
#include "../beabihelper.h"
#include "../beabi.h"
47

48
#include "bearch_arm_t.h"
49
50
#include "arm_nodes_attr.h"
#include "arm_transform.h"
51
#include "arm_optimize.h"
52
53
#include "arm_new_nodes.h"
#include "arm_map_regs.h"
54
#include "arm_cconv.h"
55
56
57
58
59

#include "gen_arm_regalloc_if.h"

#include <limits.h>

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

62
63
/** hold the current code generator during transformation */
static arm_code_gen_t *env_cg;
64

65
66
67
68
69
70
71
72
static const arch_register_t *sp_reg = &arm_gp_regs[REG_SP];
static ir_mode               *mode_gp;
static beabi_helper_env_t    *abihelper;
static calling_convention_t  *cconv = NULL;

static pmap                  *node_to_stack;

static bool mode_needs_gp_reg(ir_mode *mode)
73
{
74
	return mode_is_int(mode) || mode_is_reference(mode);
75
76
}

Michael Beck's avatar
Michael Beck committed
77
/**
78
 * create firm graph for a constant
Michael Beck's avatar
Michael Beck committed
79
 */
80
81
82
static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block,
                                         unsigned int value)
{
83
	ir_node *result;
84
	arm_vals v, vn;
Michael Beck's avatar
Michael Beck committed
85
	int cnt;
86

87
88
89
90
91
92
	/* 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 */
93
94
	arm_gen_vals_from_word(value, &v);
	arm_gen_vals_from_word(~value, &vn);
Michael Beck's avatar
Michael Beck committed
95
96
97

	if (vn.ops < v.ops) {
		/* remove bits */
98
99
		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
100
101

		for (cnt = 1; cnt < vn.ops; ++cnt) {
102
103
			result = new_bd_arm_Bic_imm(dbgi, block, result,
			                            vn.values[cnt], vn.rors[cnt]);
104
		}
105
	} else {
Michael Beck's avatar
Michael Beck committed
106
		/* add bits */
107
108
		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
109
110

		for (cnt = 1; cnt < v.ops; ++cnt) {
111
112
			result = new_bd_arm_Or_imm(dbgi, block, result,
			                           v.values[cnt], v.rors[cnt]);
Michael Beck's avatar
Michael Beck committed
113
		}
114
115
116
117
	}
	return result;
}

118
119
120
121
122
/**
 * Create a DAG constructing a given Const.
 *
 * @param irn  a Firm const
 */
123
124
static ir_node *create_const_graph(ir_node *irn, ir_node *block)
{
125
126
	tarval  *tv = get_Const_tarval(irn);
	ir_mode *mode = get_tarval_mode(tv);
127
	unsigned value;
128
129
130
131
132
133
134

	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);
135
	return create_const_graph_value(get_irn_dbg_info(irn), block, value);
136
137
}

Michael Beck's avatar
Michael Beck committed
138
/**
Michael Beck's avatar
Michael Beck committed
139
140
141
142
143
144
 * 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
145
 */
146
147
148
149
150
151
152
153
154
155
156
157
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");
	}
158
159
}

Michael Beck's avatar
Michael Beck committed
160
161
162
/**
 * Generate code for a sign extension.
 */
163
164
165
166
167
168
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);
169
170
171
	return rshift_node;
}

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
199
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
200
201
202
/**
 * Transforms a Conv node.
 *
203
 * @return The created ia32 Conv node
Michael Beck's avatar
Michael Beck committed
204
 */
205
206
static ir_node *gen_Conv(ir_node *node)
{
207
208
209
210
211
212
213
214
215
216
217
218
219
220
	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)) {
		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
221
					/* from float to float */
222
					return new_bd_arm_fpaMvf(dbg, block, new_op, dst_mode);
223
				} else {
Michael Beck's avatar
Michael Beck committed
224
					/* from float to int */
225
					return new_bd_arm_fpaFix(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
226
				}
227
			} else {
Michael Beck's avatar
Michael Beck committed
228
				/* from int to float */
229
				return new_bd_arm_fpaFlt(dbg, block, new_op, dst_mode);
Michael Beck's avatar
Michael Beck committed
230
			}
231
		} else if (USE_VFP(env_cg->isa)) {
232
			panic("VFP not supported yet");
233
		} else {
234
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
235
		}
236
	} else { /* complete in gp registers */
237
238
		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
239
240
		int min_bits;
		ir_mode *min_mode;
241

Michael Beck's avatar
Michael Beck committed
242
		if (src_bits == dst_bits) {
Michael Beck's avatar
Michael Beck committed
243
			/* kill unnecessary conv */
Michael Beck's avatar
Michael Beck committed
244
			return new_op;
245
246
247
248
249
		}

		if (src_bits < dst_bits) {
			min_bits = src_bits;
			min_mode = src_mode;
Michael Beck's avatar
Michael Beck committed
250
		} else {
251
252
253
254
255
256
257
258
259
260
261
262
			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);
263
264
265
266
		}
	}
}

267
268
269
270
271
272
273
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
274
	unsigned val, low_pos, high_pos;
275
276
277

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

279
	val = get_tarval_long(get_Const_tarval(node));
Michael Beck's avatar
Michael Beck committed
280

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

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

319
static bool is_downconv(const ir_node *node)
320
321
322
323
324
{
	ir_mode *src_mode;
	ir_mode *dest_mode;

	if (!is_Conv(node))
325
		return false;
326
327
328
329
330

	/* 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)
331
		return false;
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385

	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
386
}
387
388

/**
389
 * Creates an ARM Add.
390
391
392
 *
 * @return the created arm Add node
 */
393
394
static ir_node *gen_Add(ir_node *node)
{
395
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
396

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

426
			return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
Michael Beck's avatar
Michael Beck committed
427
		}
Michael Beck's avatar
Michael Beck committed
428
		if (is_arm_Mul(new_op2) && get_irn_n_edges(op2) == 1) {
429
430
431
			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
432

433
			return new_bd_arm_Mla(dbgi, block, new_op1, new_op2, new_op3);
Michael Beck's avatar
Michael Beck committed
434
		}
435
#endif
436

437
438
		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
439
440
	}
}
441
442

/**
443
 * Creates an ARM Mul.
444
445
446
 *
 * @return the created arm Mul node
 */
447
448
static ir_node *gen_Mul(ir_node *node)
{
449
450
451
452
453
454
455
	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
456

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

477
478
static ir_node *gen_Quot(ir_node *node)
{
479
480
481
482
483
484
485
	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
486

487
	assert(mode != mode_E && "IEEE Extended FP not supported");
488

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
	} else {
501
		panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
502
	}
Michael Beck's avatar
Michael Beck committed
503
504
}

505
506
507
508
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);
509
}
510

511
512
513
514
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);
515
}
516

517
518
519
520
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);
521
}
522

523
524
static ir_node *gen_Sub(ir_node *node)
{
525
526
527
528
	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
529
	ir_node  *new_op2 = be_transform_node(op2);
530
	ir_mode  *mode    = get_irn_mode(node);
531
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
532

533
	if (mode_is_float(mode)) {
534
		if (USE_FPA(env_cg->isa)) {
535
#if 0
536
			if (is_arm_Mov_i(new_op1))
537
				return new_bd_arm_fpaRsf_i(dbgi, block, new_op2, mode, get_arm_imm_value(new_op1));
538
			if (is_arm_Mov_i(new_op2))
539
540
541
				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);
542
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
543
			assert(mode != mode_E && "IEEE Extended FP not supported");
544
			panic("VFP not supported yet");
545
		} else {
546
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
547
		}
548
549
550
	} 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
551
	}
552
}
Michael Beck's avatar
Michael Beck committed
553

Michael Beck's avatar
Michael Beck committed
554
555
556
557
/**
 * Checks if a given value can be used as an immediate for the given
 * ARM shift mode.
 */
558
559
560
561
562
563
564
565
566
567
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
568
569
570
571
572
573
574
/**
 * generate an ARM shift instruction.
 *
 * @param node            the node
 * @param flags           matching flags
 * @param shift_modifier  initial encoding of the desired shift operation
 */
575
static ir_node *make_shift(ir_node *node, match_flags_t flags,
576
		arm_shift_modifier_t shift_modifier)
577
{
578
579
580
581
	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);
582
583
584
585
586
587
	ir_node  *new_op1;
	ir_node  *new_op2;

	if (flags & MATCH_SIZE_NEUTRAL) {
		op1 = arm_skip_downconv(op1);
		op2 = arm_skip_downconv(op2);
588
	}
589

590
	new_op1 = be_transform_node(op1);
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
	if (is_Const(op2)) {
		tarval      *tv  = get_Const_tarval(op2);
		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);
		}
	}

608
	new_op2 = be_transform_node(op2);
609
610
	return new_bd_arm_Mov_reg_shift_reg(dbgi, block, new_op1, new_op2,
	                                    shift_modifier);
611
612
}

613
614
615
static ir_node *gen_Shl(ir_node *node)
{
	return make_shift(node, MATCH_SIZE_NEUTRAL, ARM_SHF_LSL_REG);
616
617
}

618
619
620
static ir_node *gen_Shr(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_LSR_REG);
621
622
}

623
624
625
static ir_node *gen_Shrs(ir_node *node)
{
	return make_shift(node, MATCH_NONE, ARM_SHF_ASR_REG);
626
627
}

628
629
static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2)
{
Michael Beck's avatar
Michael Beck committed
630
631
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
632
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
633
634
	ir_node  *new_op2 = be_transform_node(op2);

635
636
	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
637
638
}

639
640
static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2)
{
Michael Beck's avatar
Michael Beck committed
641
642
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
643
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
644
645
	ir_node  *new_op2 = be_transform_node(op2);

646
	/* Note: there is no Rol on arm, we have to use Ror */
647
648
649
	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
650
651
}

652
653
static ir_node *gen_Rotl(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
654
655
656
657
658
659
660
661
662
	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
663
		ir_node *right = get_Add_right(op2);
Michael Beck's avatar
Michael Beck committed
664
665
666
667
		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
668
			ir_node *left = get_Add_left(op2);
Michael Beck's avatar
Michael Beck committed
669
670

			if (is_Minus(left) &&
Michael Beck's avatar
Michael Beck committed
671
			    tarval_is_long(tv)          &&
Michael Beck's avatar
Michael Beck committed
672
673
674
675
			    get_tarval_long(tv) == bits &&
			    bits                == 32)
				rotate = gen_Ror(node, op1, get_Minus_op(left));
		}
Michael Beck's avatar
Michael Beck committed
676
677
678
679
680
681
682
683
684
685
686
687
688
	} 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);
		}
689
	} else if (is_Const(op2)) {
690
691
692
		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
693

694
695
696
697
		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);
698

699
700
701
			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
702
703
704
705
706
707
708
709
710
	}

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

	return rotate;
}

711
712
static ir_node *gen_Not(ir_node *node)
{
713
714
715
	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);
716
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
717

718
719
720
	/* TODO: we could do alot more here with all the Mvn variations */

	return new_bd_arm_Mvn_reg(dbgi, block, new_op);
721
722
}

723
724
static ir_node *gen_Abs(ir_node *node)
{
725
	ir_node  *block   = be_transform_node(get_nodes_block(node));
726
	ir_node  *op      = get_Abs_op(node);
727
	ir_node  *new_op  = be_transform_node(op);
728
	dbg_info *dbgi    = get_irn_dbg_info(node);
729
	ir_mode  *mode    = get_irn_mode(node);
730

731
	if (mode_is_float(mode)) {
732
		if (USE_FPA(env_cg->isa)) {
733
			return new_bd_arm_fpaAbs(dbgi, block, new_op, mode);
734
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
735
			assert(mode != mode_E && "IEEE Extended FP not supported");
736
			panic("VFP not supported yet");
737
		} else {
738
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
739
		}
740
	}
741
	assert(mode_is_data(mode));
742
	return new_bd_arm_Abs(dbgi, block, new_op);
743
744
}

745
746
static ir_node *gen_Minus(ir_node *node)
{
747
748
749
	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);
750
	dbg_info *dbgi    = get_irn_dbg_info(node);
751
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
752

753
	if (mode_is_float(mode)) {
754
		if (USE_FPA(env_cg->isa)) {
755
			return new_bd_arm_fpaMvf(dbgi, block, op, mode);
756
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
757
			assert(mode != mode_E && "IEEE Extended FP not supported");
758
			panic("VFP not supported yet");
759
		} else {
760
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
761
		}
762
	}
763
	assert(mode_is_data(mode));
764
	return new_bd_arm_Rsb_imm(dbgi, block, new_op, 0, 0);
765
766
}

767
768
static ir_node *gen_Load(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
769
770
771
772
773
774
	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);
775
	dbg_info *dbgi      = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
776
	ir_node  *new_load = NULL;
777

Michael Beck's avatar
Michael Beck committed
778
	if (mode_is_float(mode)) {
779
		if (USE_FPA(env_cg->isa)) {
780
			new_load = new_bd_arm_fpaLdf(dbgi, block, new_ptr, new_mem, mode);
781
		} else if (USE_VFP(env_cg->isa)) {
Michael Beck's avatar
Michael Beck committed
782
			assert(mode != mode_E && "IEEE Extended FP not supported");
783
			panic("VFP not supported yet");
784
		} else {
785
			panic("Softfloat not supported yet");
Michael Beck's avatar
Michael Beck committed
786
		}
787
	} else {
788
		assert(mode_is_data(mode) && "unsupported mode for Load");
789

790
		new_load = new_bd_arm_Ldr(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false);
791
	}
Michael Beck's avatar
Michael Beck committed
792
	set_irn_pinned(new_load, get_irn_pinned(node));
793
794
795
796

	/* 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 */
797
		ir_node *proj = new_r_Proj(new_load, mode_Iu, pn_arm_Ldr_res);
798
		be_new_Keep(block, 1, &proj);
799
800
	}

Michael Beck's avatar
Michael Beck committed
801
	return new_load;
802
803
}

804
805
static ir_node *gen_Store(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
806
807
808
809
810
811
812
813
	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);
814
	dbg_info *dbgi     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
815
	ir_node *new_store = NULL;
816

Michael Beck's avatar
Michael Beck committed
817
	if (mode_is_float(mode)) {
818
		if (USE_FPA(env_cg->isa)) {
819
820
			new_store = new_bd_arm_fpaStf(dbgi, block, new_ptr, new_val,
			                              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");
Michael Beck's avatar
Michael Beck committed
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 Store");
829
830
		new_store = new_bd_arm_Str(dbgi, block, new_ptr, new_val, new_mem, mode,
		                           NULL, 0, 0, false);
831
	}
Michael Beck's avatar
Michael Beck committed
832
833
	set_irn_pinned(new_store, get_irn_pinned(node));
	return new_store;
834
835
}

836
837
838
839
840
841
842
843
844
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);
}

845
846
static ir_node *gen_SwitchJmp(ir_node *node)
{
847
848
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *selector = get_Cond_selector(node);
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
	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;
873

874
875
876
	foreach_out_edge(node, edge) {
		proj = get_edge_src_irn(edge);
		assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
877

878
879
880
		pn = get_Proj_proj(proj) - translation;
		set_Proj_proj(proj, pn);
	}
881

882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
	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)) {
899
900
901
902
903
904
		/* TODO: this is broken... */
		new_op1 = be_transform_node(op1);
		new_op2 = be_transform_node(op2);

		return new_bd_arm_Cmfe(dbgi, block, new_op1, new_op2, false);

905
906
907
908
909
910
911
912
913
		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);
914
		}
915
916
917
918
		/* Hmm: use need cmfe */
		return new_bd_arm_fpaCmfeBra(dbgi, block, new_op1, new_op2, pnc);
#endif
	}
919

920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
	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);
935
	}
936

Michael Beck's avatar
Michael Beck committed
937
	/* integer compare, TODO: use shifter_op in all its combinations */
938
939
940
941
942
943
	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);
944
945
}

946
947
948
949
950
951
952
static ir_node *gen_Cond(ir_node *node)
{
	ir_node  *selector = get_Cond_selector(node);
	ir_mode  *mode     = get_irn_mode(selector);
	ir_node  *block;
	ir_node  *flag_node;
	dbg_info *dbgi;
953

954
955
	if (mode != mode_b) {
		return gen_SwitchJmp(node);
956
	}
957
958
959
960
961
	assert(is_Proj(selector));

	block     = be_transform_node(get_nodes_block(node));
	dbgi      = get_irn_dbg_info(node);
	flag_node = be_transform_node(get_Proj_pred(selector));
962

963
	return new_bd_arm_B(dbgi, block, flag_node, get_Proj_proj(selector));
964
965
}

966
967
static tarval *fpa_imm[3][fpa_max];

968
#if 0
969
970
/**
 * Check, if a floating point tarval is an fpa immediate, i.e.
971
 * one of 0, 1, 2, 3, 4, 5, 10, or 0.5.
972
 */
973
974
static int is_fpa_immediate(tarval *tv)
{
975
976
977
978
979
980
981
982
983
984
985
986
987
988
	ir_mode *mode = get_tarval_mode(tv);
	int i, j, res = 1;

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

989
	if (tarval_is_negative(tv)) {
990
991
992
993
994
995
		tv = tarval_neg(tv);
		res = -1;
	}

	for (j = 0; j < fpa_max; ++j) {
		if (tv == fpa_imm[i][j])
Michael Beck's avatar
Michael Beck committed
996
			return res * j;
997
	}
Michael Beck's avatar
Michael Beck committed
998
	return fpa_max;
999
}
1000
#endif
For faster browsing, not all history is shown. View entire blame