bearch.c 8.03 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
/**
Christian Würdig's avatar
Christian Würdig committed
21
22
23
24
 * @file
 * @brief       Processor architecture specification.
 * @author      Sebastian Hack
 * @version     $Id$
25
 */
26
#include "config.h"
Michael Beck's avatar
Michael Beck committed
27

28
29
#include <string.h>

30
#include "bearch.h"
Michael Beck's avatar
Michael Beck committed
31
#include "benode_t.h"
32
#include "beinfo.h"
Sebastian Hack's avatar
Sebastian Hack committed
33
#include "ircons_t.h"
Daniel Grund's avatar
Daniel Grund committed
34
#include "irnode_t.h"
35

Sebastian Hack's avatar
Sebastian Hack committed
36
#include "bitset.h"
Sebastian Hack's avatar
Sebastian Hack committed
37
#include "pset.h"
Matthias Braun's avatar
Matthias Braun committed
38
#include "raw_bitset.h"
39

Sebastian Hack's avatar
Sebastian Hack committed
40
41
#include "irprintf.h"

42
/* Initialize the architecture environment struct. */
43
arch_env_t *arch_env_init(const arch_isa_if_t *isa_if, FILE *file_handle, be_main_env_t *main_env)
44
{
45
46
47
	arch_env_t *arch_env = isa_if->init(file_handle);
	arch_env->main_env   = main_env;
	return arch_env;
Sebastian Hack's avatar
Sebastian Hack committed
48
49
50
}

/**
Sebastian Hack's avatar
Sebastian Hack committed
51
52
53
 * Get the isa responsible for a node.
 * @param irn The node to get the responsible isa for.
 * @return The irn operations given by the responsible isa.
Sebastian Hack's avatar
Sebastian Hack committed
54
 */
55
static inline const arch_irn_ops_t *get_irn_ops(const ir_node *irn)
56
{
Matthias Braun's avatar
Matthias Braun committed
57
58
59
60
61
62
63
	const ir_op          *ops;
	const arch_irn_ops_t *be_ops;

	if (is_Proj(irn)) {
		irn = get_Proj_pred(irn);
		assert(!is_Proj(irn));
	}
64

Matthias Braun's avatar
Matthias Braun committed
65
66
	ops    = get_irn_op(irn);
	be_ops = get_op_ops(ops)->be_ops;
Sebastian Hack's avatar
Sebastian Hack committed
67

Matthias Braun's avatar
Matthias Braun committed
68
69
	assert(be_ops);
	return be_ops;
70
71
}

72
const arch_register_req_t *arch_get_register_req(const ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
73
{
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
	const arch_irn_ops_t *ops;

	if (is_Proj(irn)) {
		assert(pos == -1);
		pos = -1-get_Proj_proj(irn);
		irn = get_Proj_pred(irn);
	}
	ops = get_irn_ops(irn);
	if (pos < 0) {
		return ops->get_irn_reg_req_out(irn, -pos-1);
	} else {
		return ops->get_irn_reg_req_in(irn, pos);
	}
}

const arch_register_req_t *arch_get_register_req_out(const ir_node *irn)
{
	int                   pos = 0;
	const arch_irn_ops_t *ops;

	if (is_Proj(irn)) {
		pos = get_Proj_proj(irn);
		irn = get_Proj_pred(irn);
	} else if (get_irn_mode(irn) == mode_T) {
		return arch_no_register_req;
	}
	ops = get_irn_ops(irn);
	return ops->get_irn_reg_req_out(irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
102
103
}

104
void arch_set_frame_offset(ir_node *irn, int offset)
Sebastian Hack's avatar
Sebastian Hack committed
105
{
106
	const arch_irn_ops_t *ops = get_irn_ops(irn);
107
	ops->set_frame_offset(irn, offset);
Sebastian Hack's avatar
Sebastian Hack committed
108
109
}

110
ir_entity *arch_get_frame_entity(const ir_node *irn)
111
{
112
	const arch_irn_ops_t *ops = get_irn_ops(irn);
113
	return ops->get_frame_entity(irn);
114
115
}

116
void arch_set_frame_entity(ir_node *irn, ir_entity *ent)
117
{
118
	const arch_irn_ops_t *ops = get_irn_ops(irn);
119
	ops->set_frame_entity(irn, ent);
120
121
}

122
int arch_get_sp_bias(ir_node *irn)
123
{
124
	const arch_irn_ops_t *ops = get_irn_ops(irn);
125
	return ops->get_sp_bias(irn);
126
127
}

128
arch_inverse_t *arch_get_inverse(const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack)
129
{
130
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
131

Matthias Braun's avatar
Matthias Braun committed
132
	if(ops->get_inverse) {
133
		return ops->get_inverse(irn, i, inverse, obstack);
Matthias Braun's avatar
Matthias Braun committed
134
135
136
	} else {
		return NULL;
	}
137
138
}

139
140
int arch_possible_memory_operand(const ir_node *irn, unsigned int i)
{
141
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
142

Matthias Braun's avatar
Matthias Braun committed
143
	if(ops->possible_memory_operand) {
144
		return ops->possible_memory_operand(irn, i);
145
146
147
148
149
	} else {
		return 0;
	}
}

150
151
void arch_perform_memory_operand(ir_node *irn, ir_node *spill, unsigned int i)
{
152
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
153

Matthias Braun's avatar
Matthias Braun committed
154
	if(ops->perform_memory_operand) {
155
		ops->perform_memory_operand(irn, spill, i);
156
157
158
159
160
	} else {
		return;
	}
}

161
int arch_get_op_estimated_cost(const ir_node *irn)
162
{
163
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
164

Matthias Braun's avatar
Matthias Braun committed
165
	if(ops->get_op_estimated_cost) {
166
		return ops->get_op_estimated_cost(irn);
Matthias Braun's avatar
Matthias Braun committed
167
168
169
	} else {
		return 1;
	}
170
171
}

172
void arch_put_non_ignore_regs(const arch_register_class_t *cls, bitset_t *bs)
Sebastian Hack's avatar
Sebastian Hack committed
173
{
174
	unsigned i;
Sebastian Hack's avatar
Sebastian Hack committed
175
176
177
178
179
180
181

	for(i = 0; i < cls->n_regs; ++i) {
		if(!arch_register_type_is(&cls->regs[i], ignore))
			bitset_set(bs, i);
	}
}

182
int arch_reg_is_allocatable(const ir_node *irn, int pos, const arch_register_t *reg)
Sebastian Hack's avatar
Sebastian Hack committed
183
{
184
	const arch_register_req_t *req = arch_get_register_req(irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
185

Matthias Braun's avatar
Matthias Braun committed
186
	if(req->type == arch_register_req_type_none)
Sebastian Hack's avatar
Sebastian Hack committed
187
188
		return 0;

Matthias Braun's avatar
Matthias Braun committed
189
190
191
	if(arch_register_req_is(req, limited)) {
		assert(arch_register_get_class(reg) == req->cls);
		return rbitset_is_set(req->limited, arch_register_get_index(reg));
192
193
	}

Matthias Braun's avatar
Matthias Braun committed
194
	return req->cls == reg->reg_class;
Sebastian Hack's avatar
Sebastian Hack committed
195
196
}

197
const arch_register_class_t *arch_get_irn_reg_class(const ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
198
{
199
	const arch_register_req_t *req = arch_get_register_req(irn, pos);
Matthias Braun's avatar
Matthias Braun committed
200
201
202
203

	assert(req->type != arch_register_req_type_none || req->cls == NULL);

	return req->cls;
Sebastian Hack's avatar
Sebastian Hack committed
204
205
}

206
static inline reg_out_info_t *get_out_info(const ir_node *node)
207
{
208
209
210
211
212
213
214
215
216
217
218
219
	int                   pos  = 0;
	const backend_info_t *info;

	assert(get_irn_mode(node) != mode_T);
	if (is_Proj(node)) {
		pos  = get_Proj_proj(node);
		node = get_Proj_pred(node);
	}

	info = be_get_info(node);
	assert(pos >= 0 && pos < ARR_LEN(info->out_infos));
	return &info->out_infos[pos];
220
}
221

222
223

static inline reg_out_info_t *get_out_info_n(const ir_node *node, int pos)
224
{
225
226
227
228
	const backend_info_t *info = be_get_info(node);
	assert(!is_Proj(node));
	assert(pos >= 0 && pos < ARR_LEN(info->out_infos));
	return &info->out_infos[pos];
229
}
230

231
232

const arch_register_t *arch_get_irn_register(const ir_node *node)
233
{
234
235
	const reg_out_info_t *out = get_out_info(node);
	return out->reg;
236
}
Sebastian Hack's avatar
Sebastian Hack committed
237

238
const arch_register_t *arch_irn_get_register(const ir_node *node, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
239
{
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
	const reg_out_info_t *out = get_out_info_n(node, pos);
	return out->reg;
}

void arch_irn_set_register(ir_node *node, int pos, const arch_register_t *reg)
{
	reg_out_info_t *out = get_out_info_n(node, pos);
	out->reg            = reg;
}

void arch_set_irn_register(ir_node *node, const arch_register_t *reg)
{
	reg_out_info_t *out = get_out_info(node);
	out->reg = reg;
}

arch_irn_class_t arch_irn_classify(const ir_node *node)
{
	const arch_irn_ops_t *ops = get_irn_ops(node);
	return ops->classify(node);
}

arch_irn_flags_t arch_irn_get_flags(const ir_node *node)
{
	backend_info_t *info = be_get_info(node);
	return info->flags;
}

void arch_irn_set_flags(ir_node *node, arch_irn_flags_t flags)
{
	backend_info_t *info = be_get_info(node);
	info->flags = flags;
}

void arch_irn_add_flags(ir_node *node, arch_irn_flags_t flags)
{
	backend_info_t *info = be_get_info(node);
	info->flags |= flags;
Sebastian Hack's avatar
Sebastian Hack committed
278
}
Sebastian Hack's avatar
Sebastian Hack committed
279

Matthias Braun's avatar
Matthias Braun committed
280
281
282
extern char *arch_register_req_format(char *buf, size_t len,
                                      const arch_register_req_t *req,
                                      const ir_node *node)
Sebastian Hack's avatar
Sebastian Hack committed
283
284
285
286
287
{
	char tmp[128];
	snprintf(buf, len, "class: %s", req->cls->name);

	if(arch_register_req_is(req, limited)) {
Matthias Braun's avatar
Matthias Braun committed
288
289
290
		unsigned n_regs = req->cls->n_regs;
		unsigned i;

Sebastian Hack's avatar
Sebastian Hack committed
291
		strncat(buf, " limited:", len);
Matthias Braun's avatar
Matthias Braun committed
292
293
294
295
296
297
		for(i = 0; i < n_regs; ++i) {
			if(rbitset_is_set(req->limited, i)) {
				const arch_register_t *reg = &req->cls->regs[i];
				strncat(buf, " ", len);
				strncat(buf, reg->name, len);
			}
Sebastian Hack's avatar
Sebastian Hack committed
298
299
300
301
		}
	}

	if(arch_register_req_is(req, should_be_same)) {
302
303
304
305
306
307
308
309
310
		const unsigned other = req->other_same;
		int i;

		ir_snprintf(tmp, sizeof(tmp), " same to:");
		for (i = 0; 1U << i <= other; ++i) {
			if (other & (1U << i)) {
				ir_snprintf(tmp, sizeof(tmp), " %+F", get_irn_n(skip_Proj_const(node), i));
				strncat(buf, tmp, len);
			}
311
		}
Sebastian Hack's avatar
Sebastian Hack committed
312
313
	}

314
	if (arch_register_req_is(req, must_be_different)) {
315
316
317
318
319
320
321
322
323
324
		const unsigned other = req->other_different;
		int i;

		ir_snprintf(tmp, sizeof(tmp), " different from:");
		for (i = 0; 1U << i <= other; ++i) {
			if (other & (1U << i)) {
				ir_snprintf(tmp, sizeof(tmp), " %+F", get_irn_n(skip_Proj_const(node), i));
				strncat(buf, tmp, len);
			}
		}
Sebastian Hack's avatar
Sebastian Hack committed
325
326
	}

327
328
329
330
331
332
333
	if (arch_register_req_is(req, ignore)) {
		strncat(buf, " ignore", len);
	}
	if (arch_register_req_is(req, produces_sp)) {
		strncat(buf, " produces_sp", len);
	}

Sebastian Hack's avatar
Sebastian Hack committed
334
335
	return buf;
}
Matthias Braun's avatar
Matthias Braun committed
336
337
338
339
340

static const arch_register_req_t no_requirement = {
	arch_register_req_type_none,
	NULL,
	NULL,
341
342
	0,
	0
Matthias Braun's avatar
Matthias Braun committed
343
344
};
const arch_register_req_t *arch_no_register_req = &no_requirement;