amd64_new_nodes.c 10.2 KB
Newer Older
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
4
5
6
7
8
9
10
11
12
 */

/**
 * @file
 * @brief   This file implements the creation of the achitecture specific firm
 *          opcodes and the coresponding node constructors for the amd64
 *          assembler irg.
 */
#include <stdlib.h>
Matthias Braun's avatar
Matthias Braun committed
13
#include <inttypes.h>
14

Matthias Braun's avatar
Matthias Braun committed
15
#include "panic.h"
16
17
18
19
20
21
22
23
#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 "irprintf.h"
#include "xmalloc.h"
24
#include "bedump.h"
25
26
27

#include "amd64_nodes_attr.h"
#include "amd64_new_nodes.h"
28
#include "bearch_amd64_t.h"
29
30
#include "gen_amd64_regalloc_if.h"

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
amd64_insn_mode_t get_amd64_insn_mode(const ir_node *node)
{
	if (is_amd64_mov_imm(node)) {
		const amd64_movimm_attr_t *const attr
			= get_amd64_movimm_attr_const(node);
		return attr->insn_mode;
	} else if (amd64_has_addr_attr(node)) {
		amd64_addr_attr_t const *const attr = get_amd64_addr_attr_const(node);
		return attr->insn_mode;
	} else if (amd64_has_cc_attr(node)) {
		amd64_cc_attr_t const *const attr = get_amd64_cc_attr_const(node);
		return attr->insn_mode;
	} else {
		panic("Node attributes do not contain insn_mode");
	}
}

Matthias Braun's avatar
Matthias Braun committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
x87_attr_t *amd64_get_x87_attr(ir_node *const node)
{
	amd64_attr_t const *const attr = get_amd64_attr_const(node);
	switch (attr->op_mode) {
	case AMD64_OP_X87:
		return &get_amd64_x87_attr(node)->x87;
	case AMD64_OP_X87_ADDR:
		panic("TODO");
	case AMD64_OP_X87_ADDR_REG:
		return &get_amd64_x87_binop_addr_attr(node)->x87;
	default:
		break;
	}
	panic("try to get x87 attr from invalid node '%s'", node);
}

x87_attr_t const *amd64_get_x87_attr_const(ir_node const *const node)
{
	/* hacky */
	return amd64_get_x87_attr((ir_node *)node);
}

70
71
72
73
74
75
76
77
78
79
80
81
82
int get_insn_mode_bits(amd64_insn_mode_t insn_mode)
{
	switch (insn_mode) {
	case INSN_MODE_8:       return 8;
	case INSN_MODE_16:      return 16;
	case INSN_MODE_32:      return 32;
	case INSN_MODE_64:      return 64;
	case INSN_MODE_128:     return 128;
	case INSN_MODE_INVALID:
	default:                panic("bad insn mode");
	}
}

83
84
85
static const char *get_op_mode_string(amd64_op_mode_t mode)
{
	switch (mode) {
Matthias Braun's avatar
Matthias Braun committed
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
	case AMD64_OP_ADDR_IMM:     return "addr+imm";
	case AMD64_OP_ADDR_REG:     return "addr+reg";
	case AMD64_OP_ADDR:         return "addr";
	case AMD64_OP_IMM32:        return "imm32";
	case AMD64_OP_IMM64:        return "imm64";
	case AMD64_OP_NONE:         return "none";
	case AMD64_OP_REG_ADDR:     return "reg+addr";
	case AMD64_OP_REG_IMM:      return "reg+imm";
	case AMD64_OP_REG_REG:      return "reg+reg";
	case AMD64_OP_REG:          return "reg";
	case AMD64_OP_SHIFT_IMM:    return "shift_imm";
	case AMD64_OP_SHIFT_REG:    return "shift_reg";
	case AMD64_OP_X87:          return "x87";
	case AMD64_OP_X87_ADDR:     return "x87+addr";
	case AMD64_OP_X87_ADDR_REG: return "x87+addr+reg";
101
	}
Matthias Braun's avatar
Matthias Braun committed
102
	return "invalid op_mode";
103
104
105
106
107
}

static const char *get_insn_mode_string(amd64_insn_mode_t mode)
{
	switch (mode) {
108
109
110
111
112
	case INSN_MODE_8:   return "8";
	case INSN_MODE_16:  return "16";
	case INSN_MODE_32:  return "32";
	case INSN_MODE_64:  return "64";
	case INSN_MODE_128: return "128";
113
	case INSN_MODE_INVALID: break;
114
	}
Matthias Braun's avatar
Matthias Braun committed
115
	return "invalid insn_mode";
116
117
}

118
119
120
/**
 * Dumper interface for dumping amd64 nodes in vcg.
 * @param F        the output file
121
 * @param n        the node to dump
122
123
 * @param reason   indicates which kind of information should be dumped
 */
124
static void amd64_dump_node(FILE *F, const ir_node *n, dump_reason_t reason)
125
126
127
128
129
130
131
{
	switch (reason) {
	case dump_node_opcode_txt:
		fprintf(F, "%s", get_irn_opname(n));
		break;

	case dump_node_mode_txt:
132
		fprintf(F, "[%s]", get_mode_name(get_irn_mode(n)));
133
134
135
136
137
		break;

	case dump_node_nodeattr_txt:
		break;

138
	case dump_node_info_txt: {
Matthias Braun's avatar
Matthias Braun committed
139
		const amd64_attr_t *attr = get_amd64_attr_const(n);
140
141
142
143
144
		amd64_op_mode_t const op_mode = attr->op_mode;
		fprintf(F, "mode = %s\n", get_op_mode_string(op_mode));
		switch (op_mode) {
		case AMD64_OP_ADDR_REG:
		case AMD64_OP_REG_ADDR: {
145
146
			const amd64_binop_addr_attr_t *binop_attr = get_amd64_binop_addr_attr_const(n);
			fprintf(F, "reg input: %d\n", binop_attr->u.reg_input);
147
148
149
			break;
		}
		case AMD64_OP_IMM64: {
150
151
152
153
			const amd64_imm64_t *const imm
				= &get_amd64_movimm_attr_const(n)->immediate;
			ir_fprintf(F, "imm64 entity: %+F\n", imm->entity);
			fprintf(F, "imm64 offset: 0x%" PRIX64 "\n", (uint64_t)imm->offset);
154
155
156
157
			break;
		}
		default:
			break;
158
159
		}
		if (amd64_has_addr_attr(n)) {
160
161
			const amd64_addr_attr_t *addr_attr = get_amd64_addr_attr_const(n);
			fprintf(F, "size = %s\n", get_insn_mode_string(addr_attr->insn_mode));
Matthias Braun's avatar
Matthias Braun committed
162
163
			fprintf(F, "base input: %d\n", addr_attr->addr.base_input);
			fprintf(F, "index input: %d\n", addr_attr->addr.index_input);
164
165
166
			fputs("am imm: ", F);
			x86_dump_imm32(&addr_attr->addr.immediate, F);
			fputc('\n', F);
167
168
			break;
		}
169
	}
170
	}
171
172
}

Matthias Braun's avatar
Matthias Braun committed
173
174
175
static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags,
                                  const arch_register_req_t **in_reqs,
                                  int n_res, amd64_op_mode_t op_mode)
176
{
177
	be_info_init_irn(node, flags, in_reqs, n_res);
Matthias Braun's avatar
Matthias Braun committed
178
179
180
	amd64_attr_t *attr = get_amd64_attr(node);
	attr->op_mode = op_mode;
}
181

Matthias Braun's avatar
Matthias Braun committed
182
183
184
185
static void init_amd64_switch_attributes(ir_node *node,
                                         const ir_switch_table *table,
                                         ir_entity *table_entity)
{
186
187
188
189
	amd64_switch_jmp_attr_t *attr = get_amd64_switch_jmp_attr(node);
	attr->table        = table;
	attr->table_entity = table_entity;

Christoph Mallon's avatar
Christoph Mallon committed
190
	be_foreach_out(node, o) {
191
		arch_set_irn_register_req_out(node, o, arch_exec_req);
192
193
194
	}
}

Andreas Fried's avatar
Andreas Fried committed
195
196
197
static void init_amd64_cc_attributes(ir_node *node,
                                     x86_condition_code_t cc,
                                     amd64_insn_mode_t insn_mode)
198
{
199
	amd64_cc_attr_t *attr = get_amd64_cc_attr(node);
Andreas Fried's avatar
Andreas Fried committed
200
201
	attr->cc        = cc;
	attr->insn_mode = insn_mode;
202
203
}

Matthias Braun's avatar
Matthias Braun committed
204
205
static void init_amd64_movimm_attributes(ir_node *node,
                                         amd64_insn_mode_t insn_mode,
Matthias Braun's avatar
Matthias Braun committed
206
                                         const amd64_imm64_t *imm)
207
{
208
	amd64_movimm_attr_t *attr = get_amd64_movimm_attr(node);
Matthias Braun's avatar
Matthias Braun committed
209
210
	attr->insn_mode = insn_mode;
	attr->immediate = *imm;
211
212
}

213
214
static bool imm64s_equal(const amd64_imm64_t *const imm0,
                         const amd64_imm64_t *const imm1)
Matthias Braun's avatar
Matthias Braun committed
215
{
216
	return imm0->offset == imm1->offset && imm0->entity == imm1->entity;
Matthias Braun's avatar
Matthias Braun committed
217
218
}

219
220
static bool amd64_addrs_equal(const amd64_addr_t *const am0,
                              const amd64_addr_t *const am1)
Matthias Braun's avatar
Matthias Braun committed
221
{
Matthias Braun's avatar
Matthias Braun committed
222
	return x86_imm32_equal(&am0->immediate, &am1->immediate)
223
224
225
226
	    && am0->base_input == am1->base_input
	    && am0->index_input == am1->index_input
	    && am0->log_scale == am1->log_scale
	    && am0->segment == am1->segment;
Matthias Braun's avatar
Matthias Braun committed
227
228
}

229
static int amd64_attrs_equal(const ir_node *a, const ir_node *b)
230
231
232
{
	const amd64_attr_t *attr_a = get_amd64_attr_const(a);
	const amd64_attr_t *attr_b = get_amd64_attr_const(b);
233
	return attr_a->op_mode == attr_b->op_mode;
Matthias Braun's avatar
Matthias Braun committed
234
235
}

236
static int amd64_addr_attrs_equal(const ir_node *a, const ir_node *b)
Matthias Braun's avatar
Matthias Braun committed
237
238
239
{
	const amd64_addr_attr_t *attr_a = get_amd64_addr_attr_const(a);
	const amd64_addr_attr_t *attr_b = get_amd64_addr_attr_const(b);
240
241
	return amd64_attrs_equal(a, b)
	    && amd64_addrs_equal(&attr_a->addr, &attr_b->addr)
242
	    && attr_a->insn_mode == attr_b->insn_mode;
Matthias Braun's avatar
Matthias Braun committed
243
244
}

245
246
static int amd64_binop_addr_attrs_equal(const ir_node *a,
                                        const ir_node *b)
Matthias Braun's avatar
Matthias Braun committed
247
248
249
{
	const amd64_binop_addr_attr_t *attr_a = get_amd64_binop_addr_attr_const(a);
	const amd64_binop_addr_attr_t *attr_b = get_amd64_binop_addr_attr_const(b);
250
251
	if (!amd64_addr_attrs_equal(a, b))
		return false;
Matthias Braun's avatar
Matthias Braun committed
252
253
	amd64_op_mode_t op_mode = attr_a->base.base.op_mode;
	if (op_mode == AMD64_OP_REG_IMM || op_mode == AMD64_OP_ADDR_IMM) {
Matthias Braun's avatar
Matthias Braun committed
254
		return x86_imm32_equal(&attr_a->u.immediate, &attr_b->u.immediate);
Matthias Braun's avatar
Matthias Braun committed
255
	} else {
256
		return attr_a->u.reg_input == attr_b->u.reg_input;
Matthias Braun's avatar
Matthias Braun committed
257
	}
258
259
}

260
261
static int amd64_movimm_attrs_equal(const ir_node *const a,
                                    const ir_node *const b)
262
263
264
{
	const amd64_movimm_attr_t *const attr_a = get_amd64_movimm_attr_const(a);
	const amd64_movimm_attr_t *const attr_b = get_amd64_movimm_attr_const(b);
265
266
267
	return amd64_attrs_equal(a, b)
	    && imm64s_equal(&attr_a->immediate, &attr_b->immediate)
	    && attr_a->insn_mode == attr_b->insn_mode;
Matthias Braun's avatar
Matthias Braun committed
268
269
}

270
271
static int amd64_shift_attrs_equal(const ir_node *const a,
                                   const ir_node *const b)
Matthias Braun's avatar
Matthias Braun committed
272
273
274
{
	const amd64_shift_attr_t *const attr_a = get_amd64_shift_attr_const(a);
	const amd64_shift_attr_t *const attr_b = get_amd64_shift_attr_const(b);
275
276
277
	return amd64_attrs_equal(a, b)
	    && attr_a->immediate == attr_b->immediate
	    && attr_a->insn_mode == attr_b->insn_mode;
278
279
}

280
281
static int amd64_cc_attrs_equal(const ir_node *const a,
                                const ir_node *const b)
282
283
284
{
	const amd64_cc_attr_t *const attr_a = get_amd64_cc_attr_const(a);
	const amd64_cc_attr_t *const attr_b = get_amd64_cc_attr_const(b);
285
	return amd64_attrs_equal(a, b) && attr_a->cc == attr_b->cc;
286
287
}

288
289
static int amd64_switch_jmp_attrs_equal(const ir_node *const a,
                                        const ir_node *const b)
290
291
292
293
294
{
	const amd64_switch_jmp_attr_t *const attr_a
		= get_amd64_switch_jmp_attr_const(a);
	const amd64_switch_jmp_attr_t *const attr_b
		= get_amd64_switch_jmp_attr_const(b);
295
	return amd64_attrs_equal(a, b) && attr_a->table == attr_b->table;
296
297
}

298
static int amd64_call_addr_attrs_equal(const ir_node *const a,
Matthias Braun's avatar
Matthias Braun committed
299
                                       const ir_node *const b)
300
301
302
303
304
305
306
307
{
	const amd64_call_addr_attr_t *const attr_a
		= get_amd64_call_addr_attr_const(a);
	const amd64_call_addr_attr_t *const attr_b
		= get_amd64_call_addr_attr_const(b);
	return amd64_addr_attrs_equal(a, b) && attr_a->call_tp == attr_b->call_tp;
}

Matthias Braun's avatar
Matthias Braun committed
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
static int amd64_x87_attrs_equal(const ir_node *const a,
                                 const ir_node *const b)
{
	/* we ignore x87 attributes for now */
	return amd64_attrs_equal(a, b);
}

static int amd64_x87_addr_attrs_equal(const ir_node *const a,
                                      const ir_node *const b)
{
	/* ignore x87 part for now */
	return amd64_addr_attrs_equal(a, b);
}

static int amd64_x87_binop_addr_attrs_equal(const ir_node *const a,
                                            const ir_node *const b)
{
	/* ignore x87 part for now */
	return amd64_binop_addr_attrs_equal(a, b);
}

329
330
/* Include the generated constructor functions */
#include "gen_amd64_new_nodes.c.inl"