arm_new_nodes.c 15.6 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2011 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
22
23
24
25
26
 * @file
 * @brief  This file implements the creation of the architecture specific firm
 *         opcodes and the corresponding node constructors for the arm
 *         assembler irg.
 * @author Oliver Richter, Tobias Gneist
 * @version $Id$
27
 */
28
#include "config.h"
29
30

#include <stdlib.h>
31
#include <stdbool.h>
32
33
34
35
36
37
38
39
40

#include "irprog_t.h"
#include "irgraph_t.h"
#include "irnode_t.h"
#include "irmode_t.h"
#include "ircons_t.h"
#include "iropt_t.h"
#include "irop.h"
#include "irprintf.h"
41
#include "xmalloc.h"
42

43
#include "bearch.h"
44
45
46

#include "arm_nodes_attr.h"
#include "arm_new_nodes.h"
47
#include "arm_optimize.h"
48

49
#include "beabi.h"
50
51
#include "bearch_arm_t.h"

52
53
const char *arm_get_fpa_imm_name(long imm_value)
{
Michael Beck's avatar
Michael Beck committed
54
55
56
57
58
59
60
61
62
63
64
65
66
	static const char *fpa_imm[] = {
		"0",
		"1",
		"2",
		"3",
		"4",
		"5",
		"10",
		"0.5"
	};
	return fpa_imm[imm_value];
}

67
static bool arm_has_symconst_attr(const ir_node *node)
68
{
69
	return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
70
71
72
73
}

static bool has_load_store_attr(const ir_node *node)
{
74
75
	return is_arm_Ldr(node) || is_arm_Str(node) || is_arm_LinkLdrPC(node)
		|| is_arm_Ldf(node) || is_arm_Stf(node);
76
77
78
79
80
81
82
}

static bool has_shifter_operand(const ir_node *node)
{
	return is_arm_Add(node) || is_arm_And(node) || is_arm_Or(node)
		|| is_arm_Eor(node) || is_arm_Bic(node) || is_arm_Sub(node)
		|| is_arm_Rsb(node) || is_arm_Mov(node) || is_arm_Mvn(node)
83
		|| is_arm_Cmp(node) || is_arm_Tst(node) || is_arm_LinkMovPC(node);
84
85
86
87
88
89
}

static bool has_cmp_attr(const ir_node *node)
{
	return is_arm_Cmp(node) || is_arm_Tst(node);
}
90

91
92
static bool has_farith_attr(const ir_node *node)
{
93
94
	return is_arm_Adf(node) || is_arm_Muf(node) || is_arm_Suf(node)
	    || is_arm_Dvf(node) || is_arm_Mvf(node) || is_arm_FltX(node);
95
96
}

97
98
99
/**
 * Dumper interface for dumping arm nodes in vcg.
 * @param F        the output file
100
 * @param n        the node to dump
101
102
 * @param reason   indicates which kind of information should be dumped
 */
103
static void arm_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
104
{
105
	switch (reason) {
106
107
108
	case dump_node_opcode_txt:
		fprintf(F, "%s", get_irn_opname(n));

109
		if (arm_has_symconst_attr(n)) {
110
			const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
111
112
113
			if (attr->entity != NULL) {
				fputc(' ', F);
				fputs(get_entity_name(attr->entity), F);
114
			}
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
		}
		break;

	case dump_node_mode_txt:
		/* mode isn't relevant in the backend */
		break;

	case dump_node_nodeattr_txt:
		/* TODO: dump shift modifiers */
		break;

	case dump_node_info_txt:
		arch_dump_reqs_and_registers(F, n);

		if (has_load_store_attr(n)) {
			const arm_load_store_attr_t *attr
				= get_arm_load_store_attr_const(n);
			ir_fprintf(F, "load_store_mode = %+F\n", attr->load_store_mode);
			ir_fprintf(F, "entity = %+F\n", attr->entity);
			fprintf(F, "offset = %ld\n", attr->offset);
			fprintf(F, "is_frame_entity = %s\n",
					attr->is_frame_entity ? "yes" : "no");
			fprintf(F, "entity_sign = %s\n",
					attr->entity_sign ? "yes" : "no");
		}
		if (has_shifter_operand(n)) {
			const arm_shifter_operand_t *attr
				= get_arm_shifter_operand_attr_const(n);
			switch (attr->shift_modifier) {
			case ARM_SHF_REG:
				break;
			case ARM_SHF_IMM:
				fprintf(F, "modifier = imm %d ror %d\n",
						attr->immediate_value, attr->shift_immediate);
				break;
			case ARM_SHF_ASR_IMM:
				fprintf(F, "modifier = V >>s %d\n", attr->shift_immediate);
				break;
			case ARM_SHF_ASR_REG:
				fprintf(F, "modifier = V >>s R\n");
				break;
			case ARM_SHF_LSL_IMM:
				fprintf(F, "modifier = V << %d\n", attr->shift_immediate);
				break;
			case ARM_SHF_LSL_REG:
				fprintf(F, "modifier = V << R\n");
				break;
			case ARM_SHF_LSR_IMM:
				fprintf(F, "modifier = V >> %d\n", attr->shift_immediate);
				break;
			case ARM_SHF_LSR_REG:
				fprintf(F, "modifier = V >> R\n");
				break;
			case ARM_SHF_ROR_IMM:
				fprintf(F, "modifier = V ROR %d\n", attr->shift_immediate);
				break;
			case ARM_SHF_ROR_REG:
				fprintf(F, "modifier = V ROR R\n");
				break;
			case ARM_SHF_RRX:
				fprintf(F, "modifier = RRX\n");
				break;
			default:
			case ARM_SHF_INVALID:
				fprintf(F, "modifier = INVALID SHIFT MODIFIER\n");
				break;
181
			}
182
183
184
185
186
187
		}
		if (has_cmp_attr(n)) {
			const arm_cmp_attr_t *attr = get_arm_cmp_attr_const(n);
			fprintf(F, "cmp_attr =");
			if (attr->is_unsigned) {
				fprintf(F, " unsigned");
188
			}
189
190
			if (attr->ins_permuted) {
				fprintf(F, " inputs swapped");
191
			}
192
193
194
			fputc('\n', F);
		}
		if (arm_has_symconst_attr(n)) {
195
			const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
196
197
198
199
200
201
202
203
204

			fprintf(F, "entity = ");
			if (attr->entity != NULL) {
				fprintf(F, "'%s'", get_entity_name(attr->entity));
			} else {
				fputs("NULL", F);
			}
			fputc('\n', F);
			fprintf(F, "frame offset = %d\n", attr->fp_offset);
205
		}
206
207
208
209
		if (has_farith_attr(n)) {
			const arm_farith_attr_t *attr = get_arm_farith_attr_const(n);
			ir_fprintf(F, "arithmetic mode = %+F\n", attr->mode);
		}
210
		break;
211
212
213
	}
}

214
215
arm_attr_t *get_arm_attr(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
216
	assert(is_arm_irn(node) && "need arm node to get attributes");
217
	return (arm_attr_t*)get_irn_generic_attr(node);
Michael Beck's avatar
Michael Beck committed
218
219
}

220
221
const arm_attr_t *get_arm_attr_const(const ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
222
	assert(is_arm_irn(node) && "need arm node to get attributes");
223
	return (const arm_attr_t*)get_irn_generic_attr_const(node);
Michael Beck's avatar
Michael Beck committed
224
225
}

226
227
static bool has_symconst_attr(const ir_node *node)
{
228
	return is_arm_SymConst(node) || is_arm_FrameAddr(node) || is_arm_Bl(node);
229
230
}

231
232
arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
{
233
	assert(has_symconst_attr(node));
234
	return (arm_SymConst_attr_t*)get_irn_generic_attr(node);
Michael Beck's avatar
Michael Beck committed
235
236
}

237
238
const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
{
239
	assert(has_symconst_attr(node));
240
	return (const arm_SymConst_attr_t*)get_irn_generic_attr_const(node);
Michael Beck's avatar
Michael Beck committed
241
242
}

243
static const arm_fConst_attr_t *get_arm_fConst_attr_const(const ir_node *node)
244
{
245
	assert(is_arm_fConst(node));
246
	return (const arm_fConst_attr_t*)get_irn_generic_attr_const(node);
247
}
Michael Beck's avatar
Michael Beck committed
248

249
250
251
static arm_fConst_attr_t *get_arm_fConst_attr(ir_node *node)
{
	assert(is_arm_fConst(node));
252
	return (arm_fConst_attr_t*)get_irn_generic_attr(node);
Michael Beck's avatar
Michael Beck committed
253
254
}

255
arm_farith_attr_t *get_arm_farith_attr(ir_node *node)
256
{
257
	assert(has_farith_attr(node));
258
	return (arm_farith_attr_t*)get_irn_generic_attr(node);
259
}
Michael Beck's avatar
Michael Beck committed
260

261
262
263
const arm_farith_attr_t *get_arm_farith_attr_const(const ir_node *node)
{
	assert(has_farith_attr(node));
264
	return (const arm_farith_attr_t*)get_irn_generic_attr_const(node);
Michael Beck's avatar
Michael Beck committed
265
266
}

267
268
269
arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
{
	assert(is_arm_B(node));
270
	return (arm_CondJmp_attr_t*)get_irn_generic_attr(node);
Michael Beck's avatar
Michael Beck committed
271
272
}

273
274
275
const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
{
	assert(is_arm_B(node));
276
	return (const arm_CondJmp_attr_t*)get_irn_generic_attr_const(node);
Michael Beck's avatar
Michael Beck committed
277
278
}

279
280
arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
281
	assert(is_arm_SwitchJmp(node));
282
	return (arm_SwitchJmp_attr_t*)get_irn_generic_attr(node);
Michael Beck's avatar
Michael Beck committed
283
284
}

285
286
const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
287
	assert(is_arm_SwitchJmp(node));
288
289
290
291
292
293
294
295
296
297
298
299
300
	return (const arm_SwitchJmp_attr_t*)get_irn_generic_attr_const(node);
}

arm_CopyB_attr_t *get_arm_CopyB_attr(ir_node *node)
{
	assert(is_arm_CopyB(node));
	return (arm_CopyB_attr_t*)get_irn_generic_attr(node);
}

const arm_CopyB_attr_t *get_arm_CopyB_attr_const(const ir_node *node)
{
	assert(is_arm_CopyB(node));
	return (const arm_CopyB_attr_t*)get_irn_generic_attr_const(node);
301
302
}

Matthias Braun's avatar
Matthias Braun committed
303
ir_tarval *get_fConst_value(const ir_node *node)
304
{
305
	const arm_fConst_attr_t *attr = get_arm_fConst_attr_const(node);
Michael Beck's avatar
Michael Beck committed
306
307
308
	return attr->tv;
}

Matthias Braun's avatar
Matthias Braun committed
309
void set_fConst_value(ir_node *node, ir_tarval *tv)
310
{
311
	arm_fConst_attr_t *attr = get_arm_fConst_attr(node);
Michael Beck's avatar
Michael Beck committed
312
	attr->tv = tv;
313
314
}

315
ir_relation get_arm_CondJmp_relation(const ir_node *node)
316
{
Michael Beck's avatar
Michael Beck committed
317
	const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
318
	return attr->relation;
319
320
}

321
void set_arm_CondJmp_relation(ir_node *node, ir_relation relation)
322
{
Michael Beck's avatar
Michael Beck committed
323
	arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
324
	attr->relation = relation;
325
326
}

Michael Beck's avatar
Michael Beck committed
327
/* Set the ARM machine node attributes to default values. */
328
static void init_arm_attributes(ir_node *node, arch_irn_flags_t flags,
329
330
                         const arch_register_req_t ** in_reqs,
                         const be_execution_unit_t ***execution_units,
331
332
						 int n_res)
{
333
334
335
	ir_graph       *irg  = get_irn_irg(node);
	struct obstack *obst = get_irg_obstack(irg);
	arm_attr_t     *attr = get_arm_attr(node);
336
	backend_info_t *info;
337
	(void) execution_units;
338

339
340
	arch_set_irn_flags(node, flags);
	arch_set_irn_register_reqs_in(node, in_reqs);
341
	attr->is_load_store    = false;
342

343
344
345
	info            = be_get_info(node);
	info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
	memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
346
347
}

348
349
350
351
static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
                                           ir_entity *entity,
                                           int entity_sign, long offset,
                                           bool is_frame_entity)
352
{
353
	arm_load_store_attr_t *attr = get_arm_load_store_attr(res);
354
355
356
357
358
359
360
361
362
	attr->load_store_mode    = ls_mode;
	attr->entity             = entity;
	attr->entity_sign        = entity_sign;
	attr->is_frame_entity    = is_frame_entity;
	attr->offset             = offset;
	attr->base.is_load_store = true;
}

static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
363
                                     arm_shift_modifier_t shift_modifier,
364
365
                                     unsigned shift_immediate)
{
366
	arm_shifter_operand_t *attr = get_arm_shifter_operand_attr(res);
367
368
369
370
371
372
373
	attr->immediate_value = immediate_value;
	attr->shift_modifier  = shift_modifier;
	attr->shift_immediate = shift_immediate;
}

static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
{
374
	arm_cmp_attr_t *attr = get_arm_cmp_attr(res);
375
376
377
378
	attr->ins_permuted = ins_permuted;
	attr->is_unsigned  = is_unsigned;
}

379
380
static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity,
                                         int symconst_offset)
381
{
382
	arm_SymConst_attr_t *attr = get_arm_SymConst_attr(res);
383
	attr->entity    = entity;
384
	attr->fp_offset = symconst_offset;
385
386
}

387
388
static void init_arm_farith_attributes(ir_node *res, ir_mode *mode)
{
389
	arm_farith_attr_t *attr = get_arm_farith_attr(res);
390
391
392
	attr->mode = mode;
}

393
394
static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
{
395
	arm_CopyB_attr_t *attr = get_arm_CopyB_attr(res);
396
397
398
	attr->size = size;
}

Matthias Braun's avatar
Matthias Braun committed
399
400
401
402
403
404
405
406
407
408
409
410
411
412
static void init_arm_SwitchJmp_attributes(ir_node *res,
                                          const ir_switch_table *table)
{
	unsigned n_outs = arch_get_irn_n_outs(res);
	unsigned o;

	arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(res);
	attr->table = table;

	for (o = 0; o < n_outs; ++o) {
		arch_set_irn_register_req_out(res, o, arch_no_register_req);
	}
}

Michael Beck's avatar
Michael Beck committed
413
static int cmp_attr_arm(const ir_node *a, const ir_node *b)
414
{
415
416
417
	(void) a;
	(void) b;
	return 0;
Michael Beck's avatar
Michael Beck committed
418
419
}

Michael Beck's avatar
Michael Beck committed
420
static int cmp_attr_arm_SymConst(const ir_node *a, const ir_node *b)
421
{
Michael Beck's avatar
Michael Beck committed
422
423
424
425
426
427
	const arm_SymConst_attr_t *attr_a;
	const arm_SymConst_attr_t *attr_b;

	if (cmp_attr_arm(a, b))
		return 1;

428
429
	attr_a = get_arm_SymConst_attr_const(a);
	attr_b = get_arm_SymConst_attr_const(b);
430
431
	return attr_a->entity != attr_b->entity
		|| attr_a->fp_offset != attr_b->fp_offset;
Michael Beck's avatar
Michael Beck committed
432
433
}

Michael Beck's avatar
Michael Beck committed
434
static int cmp_attr_arm_CopyB(const ir_node *a, const ir_node *b)
435
436
437
438
439
440
441
{
	const arm_CopyB_attr_t *attr_a;
	const arm_CopyB_attr_t *attr_b;

	if (cmp_attr_arm(a, b))
		return 1;

442
443
	attr_a = get_arm_CopyB_attr_const(a);
	attr_b = get_arm_CopyB_attr_const(b);
444
445
446
	return attr_a->size != attr_b->size;
}

Michael Beck's avatar
Michael Beck committed
447
static int cmp_attr_arm_CondJmp(const ir_node *a, const ir_node *b)
448
{
449
450
	(void) a;
	(void) b;
Michael Beck's avatar
Michael Beck committed
451
452
453
454
	/* never identical */
	return 1;
}

Michael Beck's avatar
Michael Beck committed
455
static int cmp_attr_arm_SwitchJmp(const ir_node *a, const ir_node *b)
456
{
457
458
	(void) a;
	(void) b;
Michael Beck's avatar
Michael Beck committed
459
460
461
462
	/* never identical */
	return 1;
}

Michael Beck's avatar
Michael Beck committed
463
static int cmp_attr_arm_fConst(const ir_node *a, const ir_node *b)
464
{
465
466
	const arm_fConst_attr_t *attr_a;
	const arm_fConst_attr_t *attr_b;
Michael Beck's avatar
Michael Beck committed
467
468
469
470

	if (cmp_attr_arm(a, b))
		return 1;

471
472
	attr_a = get_arm_fConst_attr_const(a);
	attr_b = get_arm_fConst_attr_const(b);
Michael Beck's avatar
Michael Beck committed
473
474
475
476

	return attr_a->tv != attr_b->tv;
}

477

478
479
480
481
482
arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
{
	return (arm_load_store_attr_t*) get_irn_generic_attr(node);
}

483
484
485
486
487
488
489
490
491
492
const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node)
{
	return (const arm_load_store_attr_t*) get_irn_generic_attr_const(node);
}

arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
{
	return (arm_shifter_operand_t*) get_irn_generic_attr(node);
}

493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
const arm_shifter_operand_t *get_arm_shifter_operand_attr_const(
		const ir_node *node)
{
	return (const arm_shifter_operand_t*) get_irn_generic_attr_const(node);
}

arm_cmp_attr_t *get_arm_cmp_attr(ir_node *node)
{
	return (arm_cmp_attr_t*) get_irn_generic_attr(node);
}

const arm_cmp_attr_t *get_arm_cmp_attr_const(const ir_node *node)
{
	return (const arm_cmp_attr_t*) get_irn_generic_attr_const(node);
}

509
static int cmp_attr_arm_load_store(const ir_node *a, const ir_node *b)
510
511
512
513
514
515
516
{
	const arm_load_store_attr_t *attr_a;
	const arm_load_store_attr_t *attr_b;

	if (cmp_attr_arm(a, b))
		return 1;

517
518
	attr_a = get_arm_load_store_attr_const(a);
	attr_b = get_arm_load_store_attr_const(b);
519
520
521
522
523
524
525
526
	if (attr_a->entity != attr_b->entity
			|| attr_a->entity_sign != attr_b->entity_sign
			|| attr_a->offset != attr_b->offset)
		return 1;

	return 0;
}

527
static int cmp_attr_arm_shifter_operand(const ir_node *a, const ir_node *b)
528
529
530
531
532
533
534
{
	const arm_shifter_operand_t *attr_a;
	const arm_shifter_operand_t *attr_b;

	if (cmp_attr_arm(a, b))
		return 1;

535
536
	attr_a = get_arm_shifter_operand_attr_const(a);
	attr_b = get_arm_shifter_operand_attr_const(b);
537
538
539
540
541
542
543
544
	if (attr_a->shift_modifier != attr_b->shift_modifier
			|| attr_a->immediate_value != attr_b->immediate_value
			|| attr_a->shift_immediate != attr_b->shift_immediate)
		return 1;

	return 0;
}

545
static int cmp_attr_arm_cmp(const ir_node *a, const ir_node *b)
546
547
548
549
550
551
552
{
	const arm_cmp_attr_t *attr_a;
	const arm_cmp_attr_t *attr_b;

	if (cmp_attr_arm(a, b))
		return 1;

553
554
	attr_a = get_arm_cmp_attr_const(a);
	attr_b = get_arm_cmp_attr_const(b);
555
556
557
558
559
560
	if (attr_a->ins_permuted != attr_b->ins_permuted
			|| attr_a->is_unsigned != attr_b->is_unsigned)
		return 1;
	return 0;
}

561
static int cmp_attr_arm_farith(const ir_node *a, const ir_node *b)
562
563
564
565
566
567
568
569
570
571
572
573
{
	const arm_farith_attr_t *attr_a;
	const arm_farith_attr_t *attr_b;

	if (cmp_attr_arm(a, b))
		return 1;

	attr_a = get_arm_farith_attr_const(a);
	attr_b = get_arm_farith_attr_const(b);
	return attr_a->mode != attr_b->mode;
}

574
/** copies the ARM attributes of a node. */
575
576
static void arm_copy_attr(ir_graph *irg, const ir_node *old_node,
                          ir_node *new_node)
577
{
578
	struct obstack   *obst    = get_irg_obstack(irg);
579
580
	const arm_attr_t *attr_old = get_arm_attr_const(old_node);
	arm_attr_t       *attr_new = get_arm_attr(new_node);
581
582
	backend_info_t   *old_info = be_get_info(old_node);
	backend_info_t   *new_info = be_get_info(new_node);
583
584
585
586
587

	/* copy the attributes */
	memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));

	/* copy out flags */
588
	new_info->flags = old_info->flags;
589
590
	new_info->out_infos =
		DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
591
	new_info->in_reqs = old_info->in_reqs;
592
593
}

Michael Beck's avatar
Michael Beck committed
594

595
596
/* Include the generated constructor functions */
#include "gen_arm_new_nodes.c.inl"