ppc32_new_nodes.c 13.1 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

20
/**
21
 * @file
22
23
 * @brief  This file implements the creation of the architecture specific firm
 *         opcodes and the corresponding node constructors for the ppc assembler
24
25
26
 *         irg.
 * @author  Moritz Kroll, Jens Mueller
 * @version $Id$
27
 */
28
#include "config.h"
29
30
31
32
33
34
35
36
37
38
39
40

#include <stdlib.h>

#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 "irvrfy_t.h"
#include "irprintf.h"
41
#include "xmalloc.h"
42

43
#include "../bearch.h"
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

#include "ppc32_nodes_attr.h"
#include "ppc32_new_nodes.h"
#include "gen_ppc32_regalloc_if.h"



/***********************************************************************************
 *      _                                   _       _             __
 *     | |                                 (_)     | |           / _|
 *   __| |_   _ _ __ ___  _ __   ___ _ __   _ _ __ | |_ ___ _ __| |_ __ _  ___ ___
 *  / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__|  _/ _` |/ __/ _ \
 * | (_| | |_| | | | | | | |_) |  __/ |    | | | | | ||  __/ |  | || (_| | (_|  __/
 *  \__,_|\__,_|_| |_| |_| .__/ \___|_|    |_|_| |_|\__\___|_|  |_| \__,_|\___\___|
 *                       | |
 *                       |_|
 ***********************************************************************************/

/**
 * Dumps the register requirements for either in or out.
 */
Matthias Braun's avatar
Matthias Braun committed
65
static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs, int inout) {
66
	char *dir = inout ? "out" : "in";
67
	int   max = inout ? (int) arch_irn_get_n_outs(n)  : get_irn_arity(n);
Matthias Braun's avatar
Matthias Braun committed
68
	char  buf[1024];
69
70
	int   i;

Matthias Braun's avatar
Matthias Braun committed
71
	memset(buf, 0, sizeof(buf));
72
73
74
75
76

	if (reqs) {
		for (i = 0; i < max; i++) {
			fprintf(F, "%sreq #%d =", dir, i);

Matthias Braun's avatar
Matthias Braun committed
77
			if (reqs[i]->type == arch_register_req_type_none) {
78
79
80
				fprintf(F, " n/a");
			}

Matthias Braun's avatar
Matthias Braun committed
81
82
			if (reqs[i]->type & arch_register_req_type_normal) {
				fprintf(F, " %s", reqs[i]->cls->name);
83
84
			}

Matthias Braun's avatar
Matthias Braun committed
85
86
87
			if (reqs[i]->type & arch_register_req_type_limited) {
				fprintf(F, " %s",
				        arch_register_req_format(buf, sizeof(buf), reqs[i], n));
88
89
			}

Matthias Braun's avatar
Matthias Braun committed
90
			if (reqs[i]->type & arch_register_req_type_should_be_same) {
91
92
93
94
95
96
97
98
99
				const unsigned other = reqs[i]->other_same;
				int i;

				ir_fprintf(F, " same as");
				for (i = 0; 1U << i <= other; ++i) {
					if (other & (1U << i)) {
						ir_fprintf(F, " %+F", get_irn_n(n, i));
					}
				}
100
101
			}

102
			if (reqs[i]->type & arch_register_req_type_must_be_different) {
103
104
105
106
107
108
109
110
111
				const unsigned other = reqs[i]->other_different;
				int i;

				ir_fprintf(F, " different from");
				for (i = 0; 1U << i <= other; ++i) {
					if (other & (1U << i)) {
						ir_fprintf(F, " %+F", get_irn_n(n, i));
					}
				}
112
113
114
115
116
117
			}

			fprintf(F, "\n");
		}

		fprintf(F, "\n");
Matthias Braun's avatar
Matthias Braun committed
118
	} else {
119
120
121
122
123
124
125
126
127
128
129
130
		fprintf(F, "%sreq = N/A\n", dir);
	}
}


/**
 * Dumper interface for dumping ppc32 nodes in vcg.
 * @param n        the node to dump
 * @param F        the output file
 * @param reason   indicates which kind of information should be dumped
 * @return 0 on success or != 0 on failure
 */
131
static int ppc32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
132
133
  	ir_mode     *mode = NULL;
	int          bad  = 0;
134
	int          i, n_res, flags;
Matthias Braun's avatar
Matthias Braun committed
135
	const arch_register_req_t **reqs;
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

	switch (reason) {
		case dump_node_opcode_txt:
			fprintf(F, "%s", get_irn_opname(n));
			break;

		case dump_node_mode_txt:
			mode = get_irn_mode(n);

			if (mode) {
				fprintf(F, "[%s]", get_mode_name(mode));
			}
			else {
				fprintf(F, "[?NOMODE?]");
			}
			break;

		case dump_node_nodeattr_txt:

			/* TODO: dump some attributes which should show up */
			/* in node name in dump (e.g. consts or the like)  */

			break;

		case dump_node_info_txt:
			fprintf(F, "=== ppc attr begin ===\n");

			/* dump IN requirements */
			if (get_irn_arity(n) > 0) {
				reqs = get_ppc32_in_req_all(n);
				dump_reg_req(F, n, reqs, 0);
			}

169
170
171
			n_res = arch_irn_get_n_outs(n);
			if (n_res > 0) {
				/* dump OUT requirements */
172
173
174
				reqs = get_ppc32_out_req_all(n);
				dump_reg_req(F, n, reqs, 1);

175
176
177
178
179
				/* dump assigned registers */
				for (i = 0; i < n_res; i++) {
					const arch_register_t *reg = arch_irn_get_register(n, i);

					fprintf(F, "reg #%d = %s\n", i, reg ? arch_register_get_name(reg) : "n/a");
180
				}
181
				fprintf(F, "\n");
182
183
184
			}

			/* dump n_res */
185
			fprintf(F, "n_res = %d\n", n_res);
186
187
188

			/* dump flags */
			fprintf(F, "flags =");
189
190
			flags = arch_irn_get_flags(n);
			if (flags == arch_irn_flags_none) {
191
192
193
				fprintf(F, " none");
			}
			else {
194
				if (flags & arch_irn_flags_dont_spill) {
195
196
					fprintf(F, " unspillable");
				}
197
				if (flags & arch_irn_flags_rematerializable) {
198
199
					fprintf(F, " remat");
				}
200
201
202
				if (flags & arch_irn_flags_modify_flags) {
					fprintf(F, " modify_flags");
				}
203
			}
204
			fprintf(F, " (%d)\n", flags);
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229

			/* TODO: dump all additional attributes */

			fprintf(F, "=== ppc attr end ===\n");
			/* end of: case dump_node_info_txt */
			break;
	}


	return bad;
}



/***************************************************************************************************
 *        _   _                   _       __        _                    _   _               _
 *       | | | |                 | |     / /       | |                  | | | |             | |
 *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
 *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
 * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
 *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
 *                                        __/ |
 *                                       |___/
 ***************************************************************************************************/

230
ppc32_attr_t *get_ppc32_attr(ir_node *node) {
231
	assert(is_ppc32_irn(node) && "need ppc node to get attributes");
232
	return (ppc32_attr_t *)get_irn_generic_attr(node);
233
234
}

235
236
237
238
239
240
241
const ppc32_attr_t *get_ppc32_attr_const(const ir_node *node) {
	assert(is_ppc32_irn(node) && "need ppc node to get attributes");
	return (const ppc32_attr_t *)get_irn_generic_attr_const(node);
}



242
243
244
/**
 * Returns the argument register requirements of a ppc node.
 */
Matthias Braun's avatar
Matthias Braun committed
245
const arch_register_req_t **get_ppc32_in_req_all(const ir_node *node) {
246
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
247
248
249
250
251
252
	return attr->in_req;
}

/**
 * Returns the result register requirements of an ppc node.
 */
Matthias Braun's avatar
Matthias Braun committed
253
const arch_register_req_t **get_ppc32_out_req_all(const ir_node *node) {
254
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
255
256
257
258
259
260
	return attr->out_req;
}

/**
 * Returns the argument register requirement at position pos of an ppc node.
 */
Matthias Braun's avatar
Matthias Braun committed
261
const arch_register_req_t *get_ppc32_in_req(const ir_node *node, int pos) {
262
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
263
264
265
266
267
268
	return attr->in_req[pos];
}

/**
 * Returns the result register requirement at position pos of an ppc node.
 */
Matthias Braun's avatar
Matthias Braun committed
269
const arch_register_req_t *get_ppc32_out_req(const ir_node *node, int pos) {
270
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
271
272
273
274
275
276
	return attr->out_req[pos];
}

/**
 * Sets the OUT register requirements at position pos.
 */
Matthias Braun's avatar
Matthias Braun committed
277
void set_ppc32_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
278
279
280
281
282
283
284
	ppc32_attr_t *attr   = get_ppc32_attr(node);
	attr->out_req[pos] = req;
}

/**
 * Sets the IN register requirements at position pos.
 */
Matthias Braun's avatar
Matthias Braun committed
285
void set_ppc32_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
	ppc32_attr_t *attr  = get_ppc32_attr(node);
	attr->in_req[pos] = req;
}

/**
 * Sets the type of the constant (if any)
 * May be either iro_Const or iro_SymConst
 */
/* void set_ppc32_type(const ir_node *node, opcode type) {
	ppc32_attr_t *attr = get_ppc32_attr(node);
	attr->type      = type;
}  */

/**
 * Returns the type of the content (if any)
 */
ppc32_attr_content_type get_ppc32_type(const ir_node *node) {
303
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
304
305
306
307
308
309
	return attr->content_type;
}

/**
 * Sets a tarval type content (also updating the content_type)
 */
310
void set_ppc32_constant_tarval(ir_node *node, tarval *const_tarval) {
311
312
	ppc32_attr_t *attr = get_ppc32_attr(node);
	attr->content_type = ppc32_ac_Const;
313
	attr->data.constant_tarval = const_tarval;
314
315
316
317
318
319
}

/**
 * Returns a tarval type constant
 */
tarval *get_ppc32_constant_tarval(const ir_node *node) {
320
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
321
	return attr->data.constant_tarval;
322
323
324
325
326
}

/**
 * Sets an ident type constant (also updating the content_type)
 */
327
void set_ppc32_symconst_ident(ir_node *node, ident *symconst_ident) {
328
329
	ppc32_attr_t *attr = get_ppc32_attr(node);
	attr->content_type = ppc32_ac_SymConst;
330
	attr->data.symconst_ident = symconst_ident;
331
332
333
334
335
336
}

/**
 * Returns an ident type constant
 */
ident *get_ppc32_symconst_ident(const ir_node *node) {
337
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
338
	return attr->data.symconst_ident;
339
340
341
342
343
344
}


/**
 * Sets an entity (also updating the content_type)
 */
345
void set_ppc32_frame_entity(ir_node *node, ir_entity *ent) {
346
347
	ppc32_attr_t *attr = get_ppc32_attr(node);
	attr->content_type = ppc32_ac_FrameEntity;
348
	attr->data.frame_entity = ent;
349
350
351
352
353
}

/**
 * Returns an entity
 */
354
ir_entity *get_ppc32_frame_entity(const ir_node *node) {
355
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
356
	return attr->data.frame_entity;
357
358
359
360
361
}

/**
 * Sets a Rlwimi const (also updating the content_type)
 */
362
void set_ppc32_rlwimi_const(ir_node *node, unsigned shift, unsigned maskA, unsigned maskB) {
363
364
	ppc32_attr_t *attr = get_ppc32_attr(node);
	attr->content_type = ppc32_ac_RlwimiConst;
365
366
367
	attr->data.rlwimi_const.shift = shift;
	attr->data.rlwimi_const.maskA = maskA;
	attr->data.rlwimi_const.maskB = maskB;
368
369
370
371
372
}

/**
 * Returns the rlwimi const structure
 */
373
374
const rlwimi_const_t *get_ppc32_rlwimi_const(const ir_node *node) {
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
375
	return &attr->data.rlwimi_const;
376
377
378
379
380
}

/**
 * Sets a Proj number (also updating the content_type)
 */
381
void set_ppc32_proj_nr(ir_node *node, int proj_nr) {
382
383
	ppc32_attr_t *attr = get_ppc32_attr(node);
	attr->content_type = ppc32_ac_BranchProj;
384
	attr->data.proj_nr = proj_nr;
385
386
387
388
389
390
}

/**
 * Returns the proj number
 */
int get_ppc32_proj_nr(const ir_node *node) {
391
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
392
	return attr->data.proj_nr;
393
394
395
396
397
}

/**
 * Sets an offset for a memory access (also updating the content_type)
 */
398
void set_ppc32_offset(ir_node *node, int offset) {
399
400
	ppc32_attr_t *attr = get_ppc32_attr(node);
	attr->content_type = ppc32_ac_Offset;
401
	attr->data.offset  = offset;
402
403
404
405
406
407
}

/**
 * Returns the offset
 */
int get_ppc32_offset(const ir_node *node) {
408
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
409
	return attr->data.offset;
410
411
412
413
414
}

/**
 * Sets the offset mode (ppc32_ao_None, ppc32_ao_Lo16, ppc32_ao_Hi16 or ppc32_ao_Ha16)
 */
415
void set_ppc32_offset_mode(ir_node *node, ppc32_attr_offset_mode mode) {
416
417
418
419
420
421
422
423
	ppc32_attr_t *attr = get_ppc32_attr(node);
	attr->offset_mode = mode;
}

/**
 * Returns the offset mode
 */
ppc32_attr_offset_mode get_ppc32_offset_mode(const ir_node *node) {
424
	const ppc32_attr_t *attr = get_ppc32_attr_const(node);
425
426
427
428
429
430
431
432
	return attr->offset_mode;
}


/**
 * Initializes ppc specific node attributes
 */
void init_ppc32_attributes(ir_node *node, int flags,
Matthias Braun's avatar
Matthias Braun committed
433
						 const arch_register_req_t **in_reqs, const arch_register_req_t **out_reqs,
434
						 const be_execution_unit_t ***execution_units,
435
						 int n_res) {
436
437
438
	ir_graph       *irg  = get_irn_irg(node);
	struct obstack *obst = get_irg_obstack(irg);
	ppc32_attr_t   *attr = get_ppc32_attr(node);
439
	backend_info_t  *info;
Matthias Braun's avatar
Matthias Braun committed
440
	(void) execution_units;
441

442
	arch_irn_set_flags(node, flags);
443
	attr->in_req  = in_reqs;
444
445
446
	attr->out_req = out_reqs;

	attr->content_type = ppc32_ac_None;
447
448
	attr->offset_mode  = ppc32_ao_Illegal;
	attr->data.empty   = NULL;
449

450
451
452
	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]));
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
}


/***************************************************************************************
 *                  _                            _                   _
 *                 | |                          | |                 | |
 *  _ __   ___   __| | ___    ___ ___  _ __  ___| |_ _ __ _   _  ___| |_ ___  _ __ ___
 * | '_ \ / _ \ / _` |/ _ \  / __/ _ \| '_ \/ __| __| '__| | | |/ __| __/ _ \| '__/ __|
 * | | | | (_) | (_| |  __/ | (_| (_) | | | \__ \ |_| |  | |_| | (__| || (_) | |  \__ \
 * |_| |_|\___/ \__,_|\___|  \___\___/|_| |_|___/\__|_|   \__,_|\___|\__\___/|_|  |___/
 *
 ***************************************************************************************/

/* Include the generated constructor functions */
#include "gen_ppc32_new_nodes.c.inl"