amd64_new_nodes.c 8.99 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
24
25
#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"
#include "xmalloc.h"

26
#include "bearch.h"
27
28
29
30
31

#include "amd64_nodes_attr.h"
#include "amd64_new_nodes.h"
#include "gen_amd64_regalloc_if.h"

32
33
34
static const char *get_op_mode_string(amd64_op_mode_t mode)
{
	switch (mode) {
35
36
	case AMD64_OP_ADDR_IMM:   return "addr+imm";
	case AMD64_OP_ADDR_REG:   return "addr+reg";
37
38
39
	case AMD64_OP_ADDR:       return "addr";
	case AMD64_OP_IMM32:      return "imm32";
	case AMD64_OP_IMM64:      return "imm64";
40
	case AMD64_OP_NONE:       return "none";
41
	case AMD64_OP_RAX_ADDR:   return "rax_addr";
42
43
44
45
46
47
48
49
50
	case AMD64_OP_RAX_REG:    return "rax_reg";
	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_UNOP_ADDR:  return "unop_addr";
	case AMD64_OP_UNOP_IMM32: return "unop_imm32";
	case AMD64_OP_UNOP_REG:   return "unop_reg";
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
	}
	panic("invalid op_mode");
}

static const char *get_insn_mode_string(amd64_insn_mode_t mode)
{
	switch (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";
	}
	panic("invalid insn_mode");
}

66
67
68
/**
 * Dumper interface for dumping amd64 nodes in vcg.
 * @param F        the output file
69
 * @param n        the node to dump
70
71
 * @param reason   indicates which kind of information should be dumped
 */
72
static void amd64_dump_node(FILE *F, const ir_node *n, dump_reason_t reason)
73
74
75
76
77
78
79
{
	switch (reason) {
	case dump_node_opcode_txt:
		fprintf(F, "%s", get_irn_opname(n));
		break;

	case dump_node_mode_txt:
80
		fprintf(F, "[%s]", get_mode_name(get_irn_mode(n)));
81
82
83
84
85
86
87
		break;

	case dump_node_nodeattr_txt:
		break;

	case dump_node_info_txt:
		arch_dump_reqs_and_registers(F, n);
Matthias Braun's avatar
Matthias Braun committed
88
		const amd64_attr_t *attr = get_amd64_attr_const(n);
89
		fprintf(F, "mode = %s\n", get_op_mode_string(attr->op_mode));
90
91
		amd64_op_mode_t op_mode = attr->op_mode;
		if (op_mode == AMD64_OP_ADDR_REG) {
92
93
			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);
94
95
96
97
98
		} else if (op_mode == AMD64_OP_IMM64) {
			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);
99
100
		}
		if (amd64_has_addr_attr(n)) {
101
102
			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
103
104
			fprintf(F, "base input: %d\n", addr_attr->addr.base_input);
			fprintf(F, "index input: %d\n", addr_attr->addr.index_input);
105
106
107
			ir_fprintf(F, "am imm: %+F%+" PRId32 "\n", addr_attr->addr.immediate.entity, addr_attr->addr.immediate.offset);
			break;
		}
108
109
110
	}
}

Matthias Braun's avatar
Matthias Braun committed
111
112
static void init_be_info(ir_node *node, arch_irn_flags_t flags,
                         const arch_register_req_t **in_reqs, int n_res)
113
{
114
115
116
117
118
119
120
	arch_set_irn_flags(node, flags);
	arch_set_irn_register_reqs_in(node, in_reqs);

	ir_graph       *irg  = get_irn_irg(node);
	struct obstack *obst = get_irg_obstack(irg);
	backend_info_t *info = be_get_info(node);
	info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, n_res);
121
122
}

Matthias Braun's avatar
Matthias Braun committed
123
124
125
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)
126
{
Matthias Braun's avatar
Matthias Braun committed
127
128
129
130
	init_be_info(node, flags, in_reqs, n_res);
	amd64_attr_t *attr = get_amd64_attr(node);
	attr->op_mode = op_mode;
}
131

Matthias Braun's avatar
Matthias Braun committed
132
133
134
135
static void init_amd64_switch_attributes(ir_node *node,
                                         const ir_switch_table *table,
                                         ir_entity *table_entity)
{
136
137
138
139
	amd64_switch_jmp_attr_t *attr = get_amd64_switch_jmp_attr(node);
	attr->table        = table;
	attr->table_entity = table_entity;

Matthias Braun's avatar
Matthias Braun committed
140
	for (unsigned o = 0, n_outs = arch_get_irn_n_outs(node); o < n_outs; o++) {
141
142
143
144
		arch_set_irn_register_req_out(node, o, arch_no_register_req);
	}
}

145
static void init_amd64_cc_attributes(ir_node *node, x86_condition_code_t cc)
146
{
147
	amd64_cc_attr_t *attr = get_amd64_cc_attr(node);
148
	attr->cc = cc;
149
150
}

Matthias Braun's avatar
Matthias Braun committed
151
152
153
static void init_amd64_movimm_attributes(ir_node *node,
                                         amd64_insn_mode_t insn_mode,
                                         ir_entity *entity, int64_t offset)
154
{
155
	amd64_movimm_attr_t *attr = get_amd64_movimm_attr(node);
Matthias Braun's avatar
Matthias Braun committed
156
157
158
	attr->insn_mode        = insn_mode;
	attr->immediate.entity = entity;
	attr->immediate.offset = offset;
159
160
}

Matthias Braun's avatar
Matthias Braun committed
161
162
static int cmp_imm32(const amd64_imm32_t *const imm0,
                     const amd64_imm32_t *const imm1)
Matthias Braun's avatar
Matthias Braun committed
163
{
Matthias Braun's avatar
Matthias Braun committed
164
165
166
167
168
169
170
171
172
173
174
175
176
	return imm0->offset != imm1->offset || imm0->entity != imm1->entity;
}

static int cmp_imm64(const amd64_imm64_t *const imm0,
                     const amd64_imm64_t *const imm1)
{
	return imm0->offset != imm1->offset || imm0->entity != imm1->entity;
}

static int cmp_addr(const amd64_addr_t *const am0,
                    const amd64_addr_t *const am1)
{
	return cmp_imm32(&am0->immediate, &am1->immediate)
Matthias Braun's avatar
Matthias Braun committed
177
178
179
180
181
182
	    || am0->base_input != am1->base_input
	    || am0->index_input != am1->index_input
	    || am0->log_scale != am1->log_scale
	    || am0->segment != am1->segment;
}

Michael Beck's avatar
Michael Beck committed
183
static int cmp_amd64_attr(const ir_node *a, const ir_node *b)
184
185
186
{
	const amd64_attr_t *attr_a = get_amd64_attr_const(a);
	const amd64_attr_t *attr_b = get_amd64_attr_const(b);
Matthias Braun's avatar
Matthias Braun committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
	return attr_a->op_mode != attr_b->op_mode;
}

static int cmp_amd64_addr_attr(const ir_node *a, const ir_node *b)
{
	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);
	return cmp_amd64_attr(a, b)
	    || cmp_addr(&attr_a->addr, &attr_b->addr)
	    || attr_a->insn_mode != attr_b->insn_mode
	    || attr_a->needs_frame_ent != attr_b->needs_frame_ent;
}

static int cmp_amd64_binop_addr_attr(const ir_node *a,
                                     const ir_node *b)
{
	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);
	if (cmp_amd64_addr_attr(a, b))
		return 1;
	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) {
		return cmp_imm32(&attr_a->u.immediate, &attr_b->u.immediate);
	} else {
		return attr_a->u.reg_input != attr_b->u.reg_input;
	}
213
214
215
216
217
218
219
}

static int cmp_amd64_movimm_attr(const ir_node *const a,
                                 const ir_node *const b)
{
	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);
Matthias Braun's avatar
Matthias Braun committed
220
221
222
223
224
225
226
227
228
229
230
231
232
	return cmp_amd64_attr(a, b)
	    || cmp_imm64(&attr_a->immediate, &attr_b->immediate)
	    || attr_a->insn_mode != attr_b->insn_mode;
}

static int cmp_amd64_shift_attr(const ir_node *const a,
                                const ir_node *const b)
{
	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);
	return cmp_amd64_attr(a, b)
	    || attr_a->immediate != attr_b->immediate
	    || attr_a->insn_mode != attr_b->insn_mode;
233
234
235
236
237
238
239
240
241
}

static int cmp_amd64_cc_attr(const ir_node *const a,
                             const ir_node *const b)
{
	if (cmp_amd64_attr(a, b))
		return true;
	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);
242
	return attr_a->cc != attr_b->cc;
243
244
245
246
247
248
249
250
251
252
253
254
}

static int cmp_amd64_switch_jmp_attr(const ir_node *const a,
                                    const ir_node *const b)
{
	if (cmp_amd64_attr(a, b))
		return true;
	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);
	return attr_a->table != attr_b->table;
255
256
}

257
static void amd64_copy_attr(ir_graph *irg, const ir_node *old_node,
258
                            ir_node *new_node)
259
260
261
262
263
264
265
266
267
268
269
{
	struct obstack   *obst       = get_irg_obstack(irg);
	const amd64_attr_t *attr_old = get_amd64_attr_const(old_node);
	amd64_attr_t     *attr_new   = get_amd64_attr(new_node);
	backend_info_t   *old_info   = be_get_info(old_node);
	backend_info_t   *new_info   = be_get_info(new_node);

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

	/* copy out flags */
270
	new_info->flags = old_info->flags;
271
272
	new_info->out_infos =
		DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
273
	new_info->in_reqs = old_info->in_reqs;
274
275
}

276
277
/* Include the generated constructor functions */
#include "gen_amd64_new_nodes.c.inl"