2 * This file implements the creation of the achitecture specific firm opcodes
3 * and the coresponding node constructors for the $arch assembler irg.
4 * @author Christian Wuerdig
15 #include "irgraph_t.h"
21 #include "firm_common_t.h"
24 #include "../bearch.h"
26 #include "ia32_nodes_attr.h"
27 #include "ia32_new_nodes.h"
28 #include "gen_ia32_regalloc_if.h"
32 /***********************************************************************************
35 * __| |_ _ _ __ ___ _ __ ___ _ __ _ _ __ | |_ ___ _ __| |_ __ _ ___ ___
36 * / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__| _/ _` |/ __/ _ \
37 * | (_| | |_| | | | | | | |_) | __/ | | | | | | || __/ | | || (_| | (_| __/
38 * \__,_|\__,_|_| |_| |_| .__/ \___|_| |_|_| |_|\__\___|_| |_| \__,_|\___\___|
41 ***********************************************************************************/
44 * Prints a tarval to file F.
45 * @param F output file
47 * @param brackets 1 == print square brackets around tarval
49 static void fprintf_tv(FILE *F, tarval *tv, int brackets) {
51 tarval_snprintf(buf, sizeof(buf), tv);
54 fprintf(F, "[%s]", buf);
56 fprintf(F, "%s", buf);
60 * Returns the name of a SymConst.
61 * @param symc the SymConst
62 * @return name of the SymConst
64 const char *get_sc_name(ir_node *symc) {
65 if (get_irn_opcode(symc) != iro_SymConst)
68 switch (get_SymConst_kind(symc)) {
69 case symconst_addr_name:
70 return get_id_str(get_SymConst_name(symc));
72 case symconst_addr_ent:
73 return get_entity_ld_name(get_SymConst_entity(symc));
76 assert(0 && "Unsupported SymConst");
83 * Dumper interface for dumping ia32 nodes in vcg.
84 * @param n the node to dump
85 * @param F the output file
86 * @param reason indicates which kind of information should be dumped
87 * @return 0 on success or != 0 on failure
89 static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
95 const ia32_register_req_t **reqs;
96 const arch_register_t **slots;
99 case dump_node_opcode_txt:
100 name = get_irn_opname(n);
101 fprintf(F, "%s", name);
104 case dump_node_mode_txt:
105 mode = get_irn_mode(n);
107 if (mode == mode_BB || mode == mode_ANY || mode == mode_BAD || mode == mode_T) {
110 else if (is_ia32_Load(n)) {
111 mode = get_irn_mode(get_irn_n(n, 1));
113 else if (is_ia32_Store(n)) {
114 mode = get_irn_mode(get_irn_n(n, 2));
118 fprintf(F, "[%s]", get_mode_name(mode));
122 case dump_node_nodeattr_txt:
123 name = get_irn_opname(n);
124 p = name + strlen(name) - 2;
125 if ((p[0] == '_' && p[1] == 'i') || is_ia32_Const(n) || is_ia32_fConst(n)) {
126 tarval *tv = get_ia32_Immop_tarval(n);
128 fprintf_tv(F, tv, 1);
131 fprintf(F, "[SymC &%s]", get_sc_name(get_ia32_old_ir(n)));
134 else if (is_ia32_Call(n)) {
135 ir_node *sc = get_ia32_old_ir(n);
137 fprintf(F, "&%s ", get_sc_name(sc));
140 if (is_ia32_AddrMode(n)) {
141 fprintf(F, "[AddrMode] ");
146 case dump_node_info_txt:
147 attr = get_ia32_attr(n);
149 /* dump IN requirements */
150 if (get_irn_arity(n) > 0) {
151 reqs = get_ia32_in_req_all(n);
154 for (i = 0; i < get_irn_arity(n); i++) {
155 if (reqs[i]->req.type != arch_register_req_type_none) {
156 fprintf(F, "inreq[%d]=[%s]\n", i, reqs[i]->req.cls->name);
159 fprintf(F, "inreq[%d]=[none]\n", i);
166 fprintf(F, "NO IN REQS\n");
170 /* dump OUT requirements */
171 if (attr->n_res > 0) {
172 reqs = get_ia32_out_req_all(n);
175 for (i = 0; i < attr->n_res; i++) {
176 if (reqs[i]->req.type != arch_register_req_type_none) {
177 fprintf(F, "outreq[%d]=[%s]\n", i, reqs[i]->req.cls->name);
180 fprintf(F, "outreq[%d]=[none]\n", i);
185 fprintf(F, "NO OUT REQS\n");
189 /* dump assigned registers */
190 slots = get_ia32_slots(n);
191 if (slots && attr->n_res > 0) {
192 for (i = 0; i < attr->n_res; i++) {
194 fprintf(F, "reg #%d = %s\n", i, slots[i]->name);
197 fprintf(F, "reg #%d = n/a\n", i);
202 /* special for LEA */
203 if (is_ia32_Lea(n) || is_ia32_Lea_i(n)) {
204 tarval *o = get_ia32_am_offs(n);
205 tarval *tv = get_ia32_Immop_tarval(n);
212 fprintf(F, "(%s", get_irn_opname(get_irn_n(n, 0)));
214 if (is_ia32_Lea(n)) {
215 fprintf(F, ", %s", get_irn_opname(get_irn_n(n, 1)));
220 fprintf_tv(F, tv, 0);
232 /***************************************************************************************************
234 * | | | | | | / / | | | | | | | |
235 * __ _| |_| |_ _ __ ___ ___| |_ / /_ _ ___| |_ _ __ ___ ___| |_| |__ ___ __| |___
236 * / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
237 * | (_| | |_| |_| | \__ \ __/ |_ / / (_| | __/ |_ | | | | | | __/ |_| | | | (_) | (_| \__ \
238 * \__,_|\__|\__|_| |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
241 ***************************************************************************************************/
244 * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
245 * Firm was made by people hating const :-(
247 asmop_attr *get_ia32_attr(const ir_node *node) {
248 assert(is_ia32_irn(node) && "need ia32 node to get ia32 attributes");
249 return (asmop_attr *)get_irn_generic_attr((ir_node *)node);
253 * Gets the type of an ia32 node.
255 asmop_type_t get_ia32_op_type(const ir_node *node) {
256 asmop_attr *attr = get_ia32_attr(node);
261 * Sets the type of an ia32 node.
263 void set_ia32_op_type(const ir_node *node, asmop_type_t tp) {
264 asmop_attr *attr = get_ia32_attr(node);
269 * Gets the addr mode type of an ia32 node
271 addrmode_type_t get_ia32_am_type(const ir_node *node) {
272 asmop_attr *attr = get_ia32_attr(node);
277 * Sets the addr mode type of an ia32 node
279 void set_ia32_am_type(const ir_node *node, addrmode_type_t am_tp) {
280 asmop_attr *attr = get_ia32_attr(node);
285 * Gets the addr mode offset.
287 tarval *get_ia32_am_offs(const ir_node *node) {
288 asmop_attr *attr = get_ia32_attr(node);
289 return attr->am_offs;
293 * Sets the offset for addr mode.
295 void set_ia32_am_offs(ir_node *node, tarval *am_offs) {
296 asmop_attr *attr = get_ia32_attr(node);
297 attr->am_offs = am_offs;
301 * Gets the addr mode const.
303 tarval *get_ia32_am_const(const ir_node *node) {
304 asmop_attr *attr = get_ia32_attr(node);
305 return attr->am_const;
309 * Sets the const for addr mode.
311 void set_ia32_am_const(ir_node *node, tarval *am_const) {
312 asmop_attr *attr = get_ia32_attr(node);
313 attr->am_const = am_const;
317 * Return the tarval of an immediate operation or NULL in case of SymConst
319 tarval *get_ia32_Immop_tarval(const ir_node *node) {
320 asmop_attr *attr = get_ia32_attr(node);
325 * Sets the attributes of an immediate operation to the specified tarval
327 void set_ia32_Immop_tarval(ir_node *node, tarval *tv) {
328 asmop_attr *attr = get_ia32_attr(node);
333 * Return the old_ir attribute.
335 ir_node *get_ia32_old_ir(const ir_node *node) {
336 asmop_attr *attr = get_ia32_attr(node);
341 * Sets the old_ir attribute.
343 void set_ia32_old_ir(ir_node *node, ir_node *old_ir) {
344 asmop_attr *attr = get_ia32_attr(node);
345 attr->old_ir = old_ir;
349 * Returns the argument register requirements of an ia32 node.
351 const ia32_register_req_t **get_ia32_in_req_all(const ir_node *node) {
352 asmop_attr *attr = get_ia32_attr(node);
357 * Returns the result register requirements of an ia32 node.
359 const ia32_register_req_t **get_ia32_out_req_all(const ir_node *node) {
360 asmop_attr *attr = get_ia32_attr(node);
361 return attr->out_req;
365 * Returns the argument register requirement at position pos of an ia32 node.
367 const ia32_register_req_t *get_ia32_in_req(const ir_node *node, int pos) {
368 asmop_attr *attr = get_ia32_attr(node);
369 return attr->in_req[pos];
373 * Returns the result register requirement at position pos of an ia32 node.
375 const ia32_register_req_t *get_ia32_out_req(const ir_node *node, int pos) {
376 asmop_attr *attr = get_ia32_attr(node);
377 return attr->out_req[pos];
381 * Sets the OUT register requirements at position pos.
383 void set_ia32_req_out(ir_node *node, const ia32_register_req_t *req, int pos) {
384 asmop_attr *attr = get_ia32_attr(node);
385 attr->out_req[pos] = req;
389 * Sets the IN register requirements at position pos.
391 void set_ia32_req_in(ir_node *node, const ia32_register_req_t *req, int pos) {
392 asmop_attr *attr = get_ia32_attr(node);
393 attr->in_req[pos] = req;
397 * Returns the register flag of an ia32 node.
399 arch_irn_flags_t get_ia32_flags(const ir_node *node) {
400 asmop_attr *attr = get_ia32_attr(node);
405 * Sets the register flag of an ia32 node.
407 void set_ia32_flags(const ir_node *node, arch_irn_flags_t flags) {
408 asmop_attr *attr = get_ia32_attr(node);
413 * Returns the result register slots of an ia32 node.
415 const arch_register_t **get_ia32_slots(const ir_node *node) {
416 asmop_attr *attr = get_ia32_attr(node);
421 * Returns the name of the OUT register at position pos.
423 const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
424 asmop_attr *attr = get_ia32_attr(node);
426 assert(is_ia32_irn(node) && "Not an ia32 node.");
427 assert(pos < attr->n_res && "Invalid OUT position.");
428 assert(attr->slots[pos] && "No register assigned");
430 return arch_register_get_name(attr->slots[pos]);
434 * Returns the index of the OUT register at position pos within its register class.
436 int get_ia32_out_regnr(const ir_node *node, int pos) {
437 asmop_attr *attr = get_ia32_attr(node);
439 assert(is_ia32_irn(node) && "Not an ia32 node.");
440 assert(pos < attr->n_res && "Invalid OUT position.");
441 assert(attr->slots[pos] && "No register assigned");
443 return arch_register_get_index(attr->slots[pos]);
447 * Returns the OUT register at position pos.
449 const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) {
450 asmop_attr *attr = get_ia32_attr(node);
452 assert(is_ia32_irn(node) && "Not an ia32 node.");
453 assert(pos < attr->n_res && "Invalid OUT position.");
454 assert(attr->slots[pos] && "No register assigned");
456 return attr->slots[pos];
460 * Sets the number of results.
462 void set_ia32_n_res(ir_node *node, int n_res) {
463 asmop_attr *attr = get_ia32_attr(node);
468 * Returns the number of results.
470 int get_ia32_n_res(const ir_node *node) {
471 asmop_attr *attr = get_ia32_attr(node);
476 * Returns the flavour of an ia32 node,
478 op_flavour_t get_ia32_flavour(const ir_node *node) {
479 asmop_attr *attr = get_ia32_attr(node);
480 return attr->op_flav;
484 * Sets the flavour of an ia32 node to flavour_Div/Mod/DivMod/Mul/Mulh.
486 void set_ia32_flavour(ir_node *node, op_flavour_t op_flav) {
487 asmop_attr *attr = get_ia32_attr(node);
488 attr->op_flav = op_flav;
492 * Returns the projnum code.
494 long get_ia32_pncode(const ir_node *node) {
495 asmop_attr *attr = get_ia32_attr(node);
496 return attr->pn_code;
500 * Sets the projnum code
502 void set_ia32_pncode(ir_node *node, long code) {
503 asmop_attr *attr = get_ia32_attr(node);
504 attr->pn_code = code;
508 /******************************************************************************************************
510 * (_) | | | | | | / _| | | (_)
511 * ___ _ __ ___ ___ _ __ _| | __ _| |_| |_ _ __ | |_ _ _ _ __ ___| |_ _ ___ _ __ ___
512 * / __| '_ \ / _ \/ __| |/ _` | | / _` | __| __| '__| | _| | | | '_ \ / __| __| |/ _ \| '_ \ / __|
513 * \__ \ |_) | __/ (__| | (_| | | | (_| | |_| |_| | | | | |_| | | | | (__| |_| | (_) | | | | \__ \
514 * |___/ .__/ \___|\___|_|\__,_|_| \__,_|\__|\__|_| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_| |___/
517 ******************************************************************************************************/
520 * Gets the type of an ia32_Const.
522 unsigned get_ia32_Const_type(ir_node *node) {
523 asmop_attr *attr = get_ia32_attr(node);
525 assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to get type");
531 * Sets the type of an ia32_Const.
533 void set_ia32_Const_type(ir_node *node, int type) {
534 asmop_attr *attr = get_ia32_attr(node);
536 assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to set type");
537 assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type");
543 * Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node
545 void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
546 asmop_attr *na = get_ia32_attr(node);
547 asmop_attr *ca = get_ia32_attr(cnst);
549 assert((is_ia32_Const(cnst) || is_ia32_fConst(cnst)) && "Need ia32_Const to set Immop attr");
555 na->old_ir = xcalloc(1, sizeof(*(ca->old_ir)));
556 memcpy(na->old_ir, ca->old_ir, sizeof(*(ca->old_ir)));
564 * Copy the attributes from a Const to an ia32_Const
566 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
567 asmop_attr *attr = get_ia32_attr(ia32_cnst);
569 assert((is_ia32_Const(ia32_cnst) || is_ia32_fConst(ia32_cnst)) && "Need ia32_Const to set Const attr");
571 switch (get_irn_opcode(cnst)) {
573 attr->tp = asmop_Const;
574 attr->tv = get_Const_tarval(cnst);
577 attr->tp = asmop_SymConst;
579 attr->old_ir = xcalloc(1, sizeof(*cnst));
580 memcpy(attr->old_ir, cnst, sizeof(*cnst));
583 assert(0 && "Unknown Const NYI");
586 assert(0 && "Cannot create ia32_Const for this opcode");
591 * Sets the AddrMode attribute
593 void set_ia32_AddrMode(ir_node *node) {
594 asmop_attr *attr = get_ia32_attr(node);
595 attr->tp = asmop_AddrMode;
599 * Returns whether or not the node is an AddrMode node.
601 int is_ia32_AddrMode(ir_node *node) {
602 asmop_attr *attr = get_ia32_attr(node);
603 return (attr->tp == asmop_AddrMode);
608 /***************************************************************************************
611 * _ __ ___ __| | ___ ___ ___ _ __ ___| |_ _ __ _ _ ___| |_ ___ _ __ ___
612 * | '_ \ / _ \ / _` |/ _ \ / __/ _ \| '_ \/ __| __| '__| | | |/ __| __/ _ \| '__/ __|
613 * | | | | (_) | (_| | __/ | (_| (_) | | | \__ \ |_| | | |_| | (__| || (_) | | \__ \
614 * |_| |_|\___/ \__,_|\___| \___\___/|_| |_|___/\__|_| \__,_|\___|\__\___/|_| |___/
616 ***************************************************************************************/
618 /* Include the generated constructor functions */
619 #include "gen_ia32_new_nodes.c.inl"