bearch.c 7.49 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_t.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
	const arch_irn_ops_t *ops = get_irn_ops(irn);
75
	return ops->get_irn_reg_req(irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
76
77
}

78
void arch_set_frame_offset(ir_node *irn, int offset)
Sebastian Hack's avatar
Sebastian Hack committed
79
{
80
	const arch_irn_ops_t *ops = get_irn_ops(irn);
81
	ops->set_frame_offset(irn, offset);
Sebastian Hack's avatar
Sebastian Hack committed
82
83
}

84
ir_entity *arch_get_frame_entity(const ir_node *irn)
85
{
86
	const arch_irn_ops_t *ops = get_irn_ops(irn);
87
	return ops->get_frame_entity(irn);
88
89
}

90
void arch_set_frame_entity(ir_node *irn, ir_entity *ent)
91
{
92
	const arch_irn_ops_t *ops = get_irn_ops(irn);
93
	ops->set_frame_entity(irn, ent);
94
95
}

96
int arch_get_sp_bias(ir_node *irn)
97
{
98
	const arch_irn_ops_t *ops = get_irn_ops(irn);
99
	return ops->get_sp_bias(irn);
100
101
}

102
arch_inverse_t *arch_get_inverse(const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack)
103
{
104
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
105

Matthias Braun's avatar
Matthias Braun committed
106
	if(ops->get_inverse) {
107
		return ops->get_inverse(irn, i, inverse, obstack);
Matthias Braun's avatar
Matthias Braun committed
108
109
110
	} else {
		return NULL;
	}
111
112
}

113
114
int arch_possible_memory_operand(const ir_node *irn, unsigned int i)
{
115
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
116

Matthias Braun's avatar
Matthias Braun committed
117
	if(ops->possible_memory_operand) {
118
		return ops->possible_memory_operand(irn, i);
119
120
121
122
123
	} else {
		return 0;
	}
}

124
125
void arch_perform_memory_operand(ir_node *irn, ir_node *spill, unsigned int i)
{
126
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
127

Matthias Braun's avatar
Matthias Braun committed
128
	if(ops->perform_memory_operand) {
129
		ops->perform_memory_operand(irn, spill, i);
130
131
132
133
134
	} else {
		return;
	}
}

135
int arch_get_op_estimated_cost(const ir_node *irn)
136
{
137
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
138

Matthias Braun's avatar
Matthias Braun committed
139
	if(ops->get_op_estimated_cost) {
140
		return ops->get_op_estimated_cost(irn);
Matthias Braun's avatar
Matthias Braun committed
141
142
143
	} else {
		return 1;
	}
144
145
}

146
void arch_put_non_ignore_regs(const arch_register_class_t *cls, bitset_t *bs)
Sebastian Hack's avatar
Sebastian Hack committed
147
{
148
	unsigned i;
Sebastian Hack's avatar
Sebastian Hack committed
149
150
151
152
153
154
155

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

156
int arch_reg_is_allocatable(const ir_node *irn, int pos, const arch_register_t *reg)
Sebastian Hack's avatar
Sebastian Hack committed
157
{
158
	const arch_register_req_t *req = arch_get_register_req(irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
159

Matthias Braun's avatar
Matthias Braun committed
160
	if(req->type == arch_register_req_type_none)
Sebastian Hack's avatar
Sebastian Hack committed
161
162
		return 0;

Matthias Braun's avatar
Matthias Braun committed
163
164
165
	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));
166
167
	}

Matthias Braun's avatar
Matthias Braun committed
168
	return req->cls == reg->reg_class;
Sebastian Hack's avatar
Sebastian Hack committed
169
170
}

171
const arch_register_class_t *arch_get_irn_reg_class(const ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
172
{
173
	const arch_register_req_t *req = arch_get_register_req(irn, pos);
Matthias Braun's avatar
Matthias Braun committed
174
175
176
177

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

	return req->cls;
Sebastian Hack's avatar
Sebastian Hack committed
178
179
}

180
static inline reg_out_info_t *get_out_info(const ir_node *node)
181
{
182
183
184
185
186
187
188
189
190
191
192
193
	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];
194
}
195

196
197

static inline reg_out_info_t *get_out_info_n(const ir_node *node, int pos)
198
{
199
200
201
202
	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];
203
}
204

205
206

const arch_register_t *arch_get_irn_register(const ir_node *node)
207
{
208
209
	const reg_out_info_t *out = get_out_info(node);
	return out->reg;
210
}
Sebastian Hack's avatar
Sebastian Hack committed
211

212
const arch_register_t *arch_irn_get_register(const ir_node *node, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
213
{
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
	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
252
}
Sebastian Hack's avatar
Sebastian Hack committed
253

Matthias Braun's avatar
Matthias Braun committed
254
255
256
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
257
258
259
260
261
{
	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
262
263
264
		unsigned n_regs = req->cls->n_regs;
		unsigned i;

Sebastian Hack's avatar
Sebastian Hack committed
265
		strncat(buf, " limited:", len);
Matthias Braun's avatar
Matthias Braun committed
266
267
268
269
270
271
		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
272
273
274
275
		}
	}

	if(arch_register_req_is(req, should_be_same)) {
276
277
278
279
280
281
282
283
284
		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);
			}
285
		}
Sebastian Hack's avatar
Sebastian Hack committed
286
287
	}

288
	if (arch_register_req_is(req, must_be_different)) {
289
290
291
292
293
294
295
296
297
298
		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
299
300
	}

301
302
303
304
305
306
307
	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
308
309
	return buf;
}
Matthias Braun's avatar
Matthias Braun committed
310
311
312
313
314

static const arch_register_req_t no_requirement = {
	arch_register_req_type_none,
	NULL,
	NULL,
315
316
	0,
	0
Matthias Braun's avatar
Matthias Braun committed
317
318
};
const arch_register_req_t *arch_no_register_req = &no_requirement;