we can parse lots of assembler constraints now (but not all yet), and emit immediates...
[libfirm] / ir / be / ia32 / ia32_new_nodes.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief       Handling of ia32 specific firm opcodes.
23  * @author      Christian Wuerdig
24  * @version     $Id$
25  *
26  * This file implements the creation of the achitecture specific firm opcodes
27  * and the coresponding node constructors for the ia32 assembler irg.
28  */
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <stdlib.h>
34
35 #include "irprog_t.h"
36 #include "irgraph_t.h"
37 #include "irnode_t.h"
38 #include "irmode_t.h"
39 #include "ircons_t.h"
40 #include "iropt_t.h"
41 #include "irop.h"
42 #include "firm_common_t.h"
43 #include "irvrfy_t.h"
44 #include "irprintf.h"
45 #include "iredges.h"
46 #include "error.h"
47 #include "raw_bitset.h"
48 #include "xmalloc.h"
49
50 #include "../bearch_t.h"
51
52 #include "bearch_ia32_t.h"
53 #include "ia32_nodes_attr.h"
54 #include "ia32_new_nodes.h"
55 #include "gen_ia32_regalloc_if.h"
56 #include "gen_ia32_machine.h"
57
58 /**
59  * returns true if a node has x87 registers
60  */
61 int ia32_has_x87_register(const ir_node *n) {
62         assert(is_ia32_irn(n) && "Need ia32 node.");
63         return is_irn_machine_user(n, 0);
64 }
65
66 /***********************************************************************************
67  *      _                                   _       _             __
68  *     | |                                 (_)     | |           / _|
69  *   __| |_   _ _ __ ___  _ __   ___ _ __   _ _ __ | |_ ___ _ __| |_ __ _  ___ ___
70  *  / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__|  _/ _` |/ __/ _ \
71  * | (_| | |_| | | | | | | |_) |  __/ |    | | | | | ||  __/ |  | || (_| | (_|  __/
72  *  \__,_|\__,_|_| |_| |_| .__/ \___|_|    |_|_| |_|\__\___|_|  |_| \__,_|\___\___|
73  *                       | |
74  *                       |_|
75  ***********************************************************************************/
76
77 /**
78  * Dumps the register requirements for either in or out.
79  */
80 static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
81                          int inout) {
82         char *dir = inout ? "out" : "in";
83         int   max = inout ? get_ia32_n_res(n) : get_irn_arity(n);
84         char  buf[1024];
85         int   i;
86
87         memset(buf, 0, sizeof(buf));
88
89         if (reqs) {
90                 for (i = 0; i < max; i++) {
91                         fprintf(F, "%sreq #%d =", dir, i);
92
93                         if (reqs[i]->type == arch_register_req_type_none) {
94                                 fprintf(F, " n/a");
95                         }
96
97                         if (reqs[i]->type & arch_register_req_type_normal) {
98                                 fprintf(F, " %s", reqs[i]->cls->name);
99                         }
100
101                         if (reqs[i]->type & arch_register_req_type_limited) {
102                                 fprintf(F, " %s",
103                                         arch_register_req_format(buf, sizeof(buf), reqs[i], n));
104                         }
105
106                         if (reqs[i]->type & arch_register_req_type_should_be_same) {
107                                 ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->other_same));
108                         }
109
110                         if (reqs[i]->type & arch_register_req_type_should_be_different) {
111                                 ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->other_different));
112                         }
113
114                         fprintf(F, "\n");
115                 }
116
117                 fprintf(F, "\n");
118         }
119         else {
120                 fprintf(F, "%sreq = N/A\n", dir);
121         }
122 }
123
124 /**
125  * Dumper interface for dumping ia32 nodes in vcg.
126  * @param n        the node to dump
127  * @param F        the output file
128  * @param reason   indicates which kind of information should be dumped
129  * @return 0 on success or != 0 on failure
130  */
131 static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
132         ir_mode     *mode = NULL;
133         int          bad  = 0;
134         int          i, n_res, am_flav, flags;
135         const ia32_attr_t *attr = get_ia32_attr_const(n);
136         const arch_register_req_t **reqs;
137         const arch_register_t     **slots;
138
139         switch (reason) {
140                 case dump_node_opcode_txt:
141                         fprintf(F, "%s", get_irn_opname(n));
142                         break;
143
144                 case dump_node_mode_txt:
145                         mode = get_irn_mode(n);
146
147                         if (is_ia32_Ld(n) || is_ia32_St(n)) {
148                                 mode = get_ia32_ls_mode(n);
149                         }
150
151                         fprintf(F, "[%s]", mode ? get_mode_name(mode) : "?NOMODE?");
152                         break;
153
154                 case dump_node_nodeattr_txt:
155                         if (is_ia32_ImmConst(n) || is_ia32_ImmSymConst(n)) {
156                                 if(is_ia32_ImmSymConst(n)) {
157                                         ir_entity *ent = get_ia32_Immop_symconst(n);
158                                         ident *id = get_entity_ld_ident(ent);
159                                         fprintf(F, "[SymC %s]", get_id_str(id));
160                                 } else {
161                                         char buf[128];
162                                         tarval *tv = get_ia32_Immop_tarval(n);
163
164                                         tarval_snprintf(buf, sizeof(buf), tv);
165                                         fprintf(F, "[%s]", buf);
166                                 }
167                         }
168
169                         if (! is_ia32_Lea(n)) {
170                                 if (is_ia32_AddrModeS(n)) {
171                                         fprintf(F, "[AM S] ");
172                                 }
173                                 else if (is_ia32_AddrModeD(n)) {
174                                         fprintf(F, "[AM D] ");
175                                 }
176                         }
177
178                         break;
179
180                 case dump_node_info_txt:
181                         n_res = get_ia32_n_res(n);
182                         fprintf(F, "=== IA32 attr begin ===\n");
183
184                         /* dump IN requirements */
185                         if (get_irn_arity(n) > 0) {
186                                 reqs = get_ia32_in_req_all(n);
187                                 dump_reg_req(F, n, reqs, 0);
188                         }
189
190                         /* dump OUT requirements */
191                         if (n_res > 0) {
192                                 reqs = get_ia32_out_req_all(n);
193                                 dump_reg_req(F, n, reqs, 1);
194                         }
195
196                         /* dump assigned registers */
197                         slots = get_ia32_slots(n);
198                         if (slots && n_res > 0) {
199                                 for (i = 0; i < n_res; i++) {
200                                         const arch_register_t *reg;
201
202                                         /* retrieve "real" x87 register */
203                                         if (ia32_has_x87_register(n))
204                                                 reg = get_ia32_attr(n)->x87[i + 2];
205                                         else
206                                                 reg = slots[i];
207
208                                         fprintf(F, "reg #%d = %s\n", i, reg ? arch_register_get_name(reg) : "n/a");
209                                 }
210                                 fprintf(F, "\n");
211                         }
212
213                         /* dump op type */
214                         fprintf(F, "op = ");
215                         switch (get_ia32_op_type(n)) {
216                                 case ia32_Normal:
217                                         fprintf(F, "Normal");
218                                         break;
219                                 case ia32_AddrModeD:
220                                         fprintf(F, "AM Dest (Load+Store)");
221                                         break;
222                                 case ia32_AddrModeS:
223                                         fprintf(F, "AM Source (Load)");
224                                         break;
225                                 default:
226                                         fprintf(F, "unknown (%d)", get_ia32_op_type(n));
227                                         break;
228                         }
229                         fprintf(F, "\n");
230
231                         /* dump immop type */
232                         fprintf(F, "immediate = ");
233                         switch (get_ia32_immop_type(n)) {
234                                 case ia32_ImmNone:
235                                         fprintf(F, "None");
236                                         break;
237                                 case ia32_ImmConst:
238                                         fprintf(F, "Const");
239                                         break;
240                                 case ia32_ImmSymConst:
241                                         fprintf(F, "SymConst");
242                                         break;
243                                 case ia32_ImmAsm:
244                                         fprintf(F, "Asm '%s'\n",
245                                                 get_id_str(attr->cnst_val.asm_text));
246                                         break;
247                                 default:
248                                         fprintf(F, "unknown (%d)", get_ia32_immop_type(n));
249                                         break;
250                         }
251                         fprintf(F, "\n");
252
253                         /* dump supported am */
254                         fprintf(F, "AM support = ");
255                         switch (get_ia32_am_support(n)) {
256                                 case ia32_am_None:
257                                         fprintf(F, "none");
258                                         break;
259                                 case ia32_am_Source:
260                                         fprintf(F, "source only (Load)");
261                                         break;
262                                 case ia32_am_Dest:
263                                         fprintf(F, "dest only (Load+Store)");
264                                         break;
265                                 case ia32_am_Full:
266                                         fprintf(F, "full");
267                                         break;
268                                 default:
269                                         fprintf(F, "unknown (%d)", get_ia32_am_support(n));
270                                         break;
271                         }
272                         fprintf(F, "\n");
273
274                         /* dump am flavour */
275                         fprintf(F, "AM flavour =");
276                         am_flav = get_ia32_am_flavour(n);
277                         if (am_flav == ia32_am_N) {
278                                 fprintf(F, " none");
279                         }
280                         else {
281                                 if (am_flav & ia32_O) {
282                                         fprintf(F, " O");
283                                 }
284                                 if (am_flav & ia32_B) {
285                                         fprintf(F, " B");
286                                 }
287                                 if (am_flav & ia32_I) {
288                                         fprintf(F, " I");
289                                 }
290                                 if (am_flav & ia32_S) {
291                                         fprintf(F, " S");
292                                 }
293                         }
294                         fprintf(F, " (%d)\n", am_flav);
295
296                         /* dump AM offset */
297                         if(get_ia32_am_offs_int(n) != 0) {
298                                 fprintf(F, "AM offset = %d\n", get_ia32_am_offs_int(n));
299                         }
300
301                         /* dump AM symconst */
302                         if(get_ia32_am_sc(n) != NULL) {
303                                 ir_entity *ent = get_ia32_am_sc(n);
304                                 ident *id = get_entity_ld_ident(ent);
305                                 fprintf(F, "AM symconst = %s\n", get_id_str(id));
306                         }
307
308                         /* dump AM scale */
309                         fprintf(F, "AM scale = %d\n", get_ia32_am_scale(n));
310
311                         /* dump pn code */
312                         if(is_ia32_SwitchJmp(n)) {
313                                 fprintf(F, "pn_code = %d\n", get_ia32_pncode(n));
314                         } else {
315                                 if(get_ia32_pncode(n) & ia32_pn_Cmp_Unsigned) {
316                                         int pnc = get_ia32_pncode(n);
317                                         fprintf(F, "pn_code = %d (%s, unsigned)\n",
318                                                 pnc, get_pnc_string(pnc & ~ia32_pn_Cmp_Unsigned));
319                                 } else {
320                                         fprintf(F, "pn_code = %d (%s)\n", get_ia32_pncode(n),
321                                                 get_pnc_string(get_ia32_pncode(n)));
322                                 }
323                         }
324
325                         /* dump n_res */
326                         fprintf(F, "n_res = %d\n", get_ia32_n_res(n));
327
328                         /* dump use_frame */
329                         fprintf(F, "use_frame = %d\n", is_ia32_use_frame(n));
330
331                         /* commutative */
332                         fprintf(F, "commutative = %d\n", is_ia32_commutative(n));
333
334                         /* emit cl */
335                         fprintf(F, "emit cl instead of ecx = %d\n", is_ia32_emit_cl(n));
336
337                         /* got lea */
338                         fprintf(F, "got loea = %d\n", is_ia32_got_lea(n));
339
340                         /* need stackent */
341                         fprintf(F, "need stackent = %d\n", is_ia32_need_stackent(n));
342
343                         /* dump latency */
344                         fprintf(F, "latency = %d\n", get_ia32_latency(n));
345
346                         /* dump flags */
347                         fprintf(F, "flags =");
348                         flags = get_ia32_flags(n);
349                         if (flags == arch_irn_flags_none) {
350                                 fprintf(F, " none");
351                         }
352                         else {
353                                 if (flags & arch_irn_flags_dont_spill) {
354                                         fprintf(F, " unspillable");
355                                 }
356                                 if (flags & arch_irn_flags_rematerializable) {
357                                         fprintf(F, " remat");
358                                 }
359                                 if (flags & arch_irn_flags_ignore) {
360                                         fprintf(F, " ignore");
361                                 }
362                                 if (flags & arch_irn_flags_modify_sp) {
363                                         fprintf(F, " modify_sp");
364                                 }
365                         }
366                         fprintf(F, " (%d)\n", flags);
367
368                         /* dump frame entity */
369                         fprintf(F, "frame entity = ");
370                         if (get_ia32_frame_ent(n)) {
371                                 ir_fprintf(F, "%+F", get_ia32_frame_ent(n));
372                         }
373                         else {
374                                 fprintf(F, "n/a");
375                         }
376                         fprintf(F, "\n");
377
378                         /* dump modes */
379                         fprintf(F, "ls_mode = ");
380                         if (get_ia32_ls_mode(n)) {
381                                 ir_fprintf(F, "%+F", get_ia32_ls_mode(n));
382                         }
383                         else {
384                                 fprintf(F, "n/a");
385                         }
386                         fprintf(F, "\n");
387
388 #ifndef NDEBUG
389                         /* dump original ir node name */
390                         fprintf(F, "orig node = ");
391                         if (get_ia32_orig_node(n)) {
392                                 fprintf(F, "%s", get_ia32_orig_node(n));
393                         }
394                         else {
395                                 fprintf(F, "n/a");
396                         }
397                         fprintf(F, "\n");
398 #endif /* NDEBUG */
399
400                         fprintf(F, "=== IA32 attr end ===\n");
401                         /* end of: case dump_node_info_txt */
402                         break;
403         }
404
405         return bad;
406 }
407
408
409
410 /***************************************************************************************************
411  *        _   _                   _       __        _                    _   _               _
412  *       | | | |                 | |     / /       | |                  | | | |             | |
413  *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
414  *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
415  * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
416  *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
417  *                                        __/ |
418  *                                       |___/
419  ***************************************************************************************************/
420
421 /**
422  * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
423  * Firm was made by people hating const :-(
424  */
425 ia32_attr_t *get_ia32_attr(const ir_node *node) {
426         assert(is_ia32_irn(node) && "need ia32 node to get ia32 attributes");
427         return (ia32_attr_t *)get_irn_generic_attr((ir_node *)node);
428 }
429
430 const ia32_attr_t *get_ia32_attr_const(const ir_node *node) {
431         assert(is_ia32_irn(node) && "need ia32 node to get ia32 attributes");
432         return (const ia32_attr_t*) get_irn_generic_attr_const(node);
433 }
434
435 /**
436  * Gets the type of an ia32 node.
437  */
438 ia32_op_type_t get_ia32_op_type(const ir_node *node) {
439         ia32_attr_t *attr = get_ia32_attr(node);
440         return attr->data.tp;
441 }
442
443 /**
444  * Sets the type of an ia32 node.
445  */
446 void set_ia32_op_type(ir_node *node, ia32_op_type_t tp) {
447         ia32_attr_t *attr = get_ia32_attr(node);
448         attr->data.tp     = tp;
449 }
450
451 /**
452  * Gets the immediate op type of an ia32 node.
453  */
454 ia32_immop_type_t get_ia32_immop_type(const ir_node *node) {
455         ia32_attr_t *attr = get_ia32_attr(node);
456         return attr->data.imm_tp;
457 }
458
459 /**
460  * Gets the supported address mode of an ia32 node
461  */
462 ia32_am_type_t get_ia32_am_support(const ir_node *node) {
463         ia32_attr_t *attr = get_ia32_attr(node);
464         return attr->data.am_support;
465 }
466
467 /**
468  * Sets the supported address mode of an ia32 node
469  */
470 void set_ia32_am_support(ir_node *node, ia32_am_type_t am_tp) {
471         ia32_attr_t *attr     = get_ia32_attr(node);
472         attr->data.am_support = am_tp;
473 }
474
475 /**
476  * Gets the address mode flavour of an ia32 node
477  */
478 ia32_am_flavour_t get_ia32_am_flavour(const ir_node *node) {
479         ia32_attr_t *attr = get_ia32_attr(node);
480         return attr->data.am_flavour;
481 }
482
483 /**
484  * Sets the address mode flavour of an ia32 node
485  */
486 void set_ia32_am_flavour(ir_node *node, ia32_am_flavour_t am_flavour) {
487         ia32_attr_t *attr     = get_ia32_attr(node);
488         attr->data.am_flavour = am_flavour;
489 }
490
491 /**
492  * Gets the address mode offset as int.
493  */
494 int get_ia32_am_offs_int(const ir_node *node) {
495         ia32_attr_t *attr = get_ia32_attr(node);
496         return attr->am_offs;
497 }
498
499 /**
500  * Sets the address mode offset from an int.
501  */
502 void set_ia32_am_offs_int(ir_node *node, int offset) {
503         ia32_attr_t *attr = get_ia32_attr(node);
504         attr->am_offs = offset;
505 }
506
507 void add_ia32_am_offs_int(ir_node *node, int offset) {
508         ia32_attr_t *attr = get_ia32_attr(node);
509         attr->am_offs += offset;
510 }
511
512 /**
513  * Returns the symconst entity associated to address mode.
514  */
515 ir_entity *get_ia32_am_sc(const ir_node *node) {
516         ia32_attr_t *attr = get_ia32_attr(node);
517         return attr->am_sc;
518 }
519
520 /**
521  * Sets the symconst entity associated to address mode.
522  */
523 void set_ia32_am_sc(ir_node *node, ir_entity *entity) {
524         ia32_attr_t *attr = get_ia32_attr(node);
525         attr->am_sc       = entity;
526 }
527
528 /**
529  * Sets the sign bit for address mode symconst.
530  */
531 void set_ia32_am_sc_sign(ir_node *node) {
532         ia32_attr_t *attr     = get_ia32_attr(node);
533         attr->data.am_sc_sign = 1;
534 }
535
536 /**
537  * Clears the sign bit for address mode symconst.
538  */
539 void clear_ia32_am_sc_sign(ir_node *node) {
540         ia32_attr_t *attr     = get_ia32_attr(node);
541         attr->data.am_sc_sign = 0;
542 }
543
544 /**
545  * Returns the sign bit for address mode symconst.
546  */
547 int is_ia32_am_sc_sign(const ir_node *node) {
548         ia32_attr_t *attr = get_ia32_attr(node);
549         return attr->data.am_sc_sign;
550 }
551
552 /**
553  * Gets the addr mode const.
554  */
555 int get_ia32_am_scale(const ir_node *node) {
556         ia32_attr_t *attr = get_ia32_attr(node);
557         return attr->data.am_scale;
558 }
559
560 /**
561  * Sets the index register scale for address mode.
562  */
563 void set_ia32_am_scale(ir_node *node, int scale) {
564         ia32_attr_t *attr   = get_ia32_attr(node);
565         attr->data.am_scale = scale;
566 }
567
568 /**
569  * Return the tarval of an immediate operation or NULL in case of SymConst
570  */
571 tarval *get_ia32_Immop_tarval(const ir_node *node) {
572         ia32_attr_t *attr = get_ia32_attr(node);
573         assert(attr->data.imm_tp == ia32_ImmConst);
574     return attr->cnst_val.tv;
575 }
576
577 /**
578  * Sets the attributes of an immediate operation to the specified tarval
579  */
580 void set_ia32_Immop_tarval(ir_node *node, tarval *tv) {
581         ia32_attr_t *attr = get_ia32_attr(node);
582         attr->data.imm_tp = ia32_ImmConst;
583         attr->cnst_val.tv = tv;
584 }
585
586 void set_ia32_Immop_symconst(ir_node *node, ir_entity *entity) {
587         ia32_attr_t *attr = get_ia32_attr(node);
588         attr->data.imm_tp = ia32_ImmSymConst;
589         attr->cnst_val.sc = entity;
590 }
591
592 ir_entity *get_ia32_Immop_symconst(const ir_node *node) {
593         ia32_attr_t *attr = get_ia32_attr(node);
594         assert(attr->data.imm_tp == ia32_ImmSymConst);
595         return attr->cnst_val.sc;
596 }
597
598 /**
599  * Sets the uses_frame flag.
600  */
601 void set_ia32_use_frame(ir_node *node) {
602         ia32_attr_t *attr    = get_ia32_attr(node);
603         attr->data.use_frame = 1;
604 }
605
606 /**
607  * Clears the uses_frame flag.
608  */
609 void clear_ia32_use_frame(ir_node *node) {
610         ia32_attr_t *attr    = get_ia32_attr(node);
611         attr->data.use_frame = 0;
612 }
613
614 /**
615  * Gets the uses_frame flag.
616  */
617 int is_ia32_use_frame(const ir_node *node) {
618         ia32_attr_t *attr = get_ia32_attr(node);
619         return attr->data.use_frame;
620 }
621
622 /**
623  * Sets node to commutative.
624  */
625 void set_ia32_commutative(ir_node *node) {
626         ia32_attr_t *attr         = get_ia32_attr(node);
627         attr->data.is_commutative = 1;
628 }
629
630 /**
631  * Sets node to non-commutative.
632  */
633 void clear_ia32_commutative(ir_node *node) {
634         ia32_attr_t *attr         = get_ia32_attr(node);
635         attr->data.is_commutative = 0;
636 }
637
638 /**
639  * Checks if node is commutative.
640  */
641 int is_ia32_commutative(const ir_node *node) {
642         ia32_attr_t *attr = get_ia32_attr(node);
643         return attr->data.is_commutative;
644 }
645
646 /**
647  * Sets node emit_cl.
648  */
649 void set_ia32_emit_cl(ir_node *node) {
650         ia32_attr_t *attr  = get_ia32_attr(node);
651         attr->data.emit_cl = 1;
652 }
653
654 /**
655  * Clears node emit_cl.
656  */
657 void clear_ia32_emit_cl(ir_node *node) {
658         ia32_attr_t *attr  = get_ia32_attr(node);
659         attr->data.emit_cl = 0;
660 }
661
662 /**
663  * Checks if node needs %cl.
664  */
665 int is_ia32_emit_cl(const ir_node *node) {
666         ia32_attr_t *attr = get_ia32_attr(node);
667         return attr->data.emit_cl;
668 }
669
670 /**
671  * Sets node got_lea.
672  */
673 void set_ia32_got_lea(ir_node *node) {
674         ia32_attr_t *attr  = get_ia32_attr(node);
675         attr->data.got_lea = 1;
676 }
677
678 /**
679  * Clears node got_lea.
680  */
681 void clear_ia32_got_lea(ir_node *node) {
682         ia32_attr_t *attr  = get_ia32_attr(node);
683         attr->data.got_lea = 0;
684 }
685
686 /**
687  * Checks if node got lea.
688  */
689 int is_ia32_got_lea(const ir_node *node) {
690         ia32_attr_t *attr = get_ia32_attr(node);
691         return attr->data.got_lea;
692 }
693
694 void set_ia32_need_stackent(ir_node *node) {
695         ia32_attr_t *attr     = get_ia32_attr(node);
696         attr->data.need_stackent = 1;
697 }
698
699 void clear_ia32_need_stackent(ir_node *node) {
700         ia32_attr_t *attr     = get_ia32_attr(node);
701         attr->data.need_stackent = 0;
702 }
703
704 int is_ia32_need_stackent(const ir_node *node) {
705         ia32_attr_t *attr = get_ia32_attr(node);
706         return attr->data.need_stackent;
707 }
708
709 /**
710  * Gets the mode of the stored/loaded value (only set for Store/Load)
711  */
712 ir_mode *get_ia32_ls_mode(const ir_node *node) {
713         ia32_attr_t *attr = get_ia32_attr(node);
714         return attr->ls_mode;
715 }
716
717 /**
718  * Sets the mode of the stored/loaded value (only set for Store/Load)
719  */
720 void set_ia32_ls_mode(ir_node *node, ir_mode *mode) {
721         ia32_attr_t *attr = get_ia32_attr(node);
722         attr->ls_mode     = mode;
723 }
724
725 /**
726  * Gets the frame entity assigned to this node.
727  */
728 ir_entity *get_ia32_frame_ent(const ir_node *node) {
729         ia32_attr_t *attr = get_ia32_attr(node);
730         return attr->frame_ent;
731 }
732
733 /**
734  * Sets the frame entity for this node.
735  */
736 void set_ia32_frame_ent(ir_node *node, ir_entity *ent) {
737         ia32_attr_t *attr = get_ia32_attr(node);
738         attr->frame_ent   = ent;
739         if(ent != NULL)
740                 set_ia32_use_frame(node);
741         else
742                 clear_ia32_use_frame(node);
743 }
744
745
746 /**
747  * Gets the instruction latency.
748  */
749 unsigned get_ia32_latency(const ir_node *node) {
750         ia32_attr_t *attr = get_ia32_attr(node);
751         return attr->latency;
752 }
753
754 /**
755 * Sets the instruction latency.
756 */
757 void set_ia32_latency(ir_node *node, unsigned latency) {
758         ia32_attr_t *attr = get_ia32_attr(node);
759         attr->latency     = latency;
760 }
761
762 /**
763  * Returns the argument register requirements of an ia32 node.
764  */
765 const arch_register_req_t **get_ia32_in_req_all(const ir_node *node) {
766         ia32_attr_t *attr = get_ia32_attr(node);
767         return attr->in_req;
768 }
769
770 /**
771  * Sets the argument register requirements of an ia32 node.
772  */
773 void set_ia32_in_req_all(ir_node *node, const arch_register_req_t **reqs) {
774         ia32_attr_t *attr = get_ia32_attr(node);
775         attr->in_req      = reqs;
776 }
777
778 /**
779  * Returns the result register requirements of an ia32 node.
780  */
781 const arch_register_req_t **get_ia32_out_req_all(const ir_node *node) {
782         ia32_attr_t *attr = get_ia32_attr(node);
783         return attr->out_req;
784 }
785
786 /**
787  * Sets the result register requirements of an ia32 node.
788  */
789 void set_ia32_out_req_all(ir_node *node, const arch_register_req_t **reqs) {
790         ia32_attr_t *attr = get_ia32_attr(node);
791         attr->out_req     = reqs;
792 }
793
794 /**
795  * Returns the argument register requirement at position pos of an ia32 node.
796  */
797 const arch_register_req_t *get_ia32_in_req(const ir_node *node, int pos) {
798         ia32_attr_t *attr = get_ia32_attr(node);
799         if(attr->in_req == NULL)
800                 return arch_no_register_req;
801
802         return attr->in_req[pos];
803 }
804
805 /**
806  * Returns the result register requirement at position pos of an ia32 node.
807  */
808 const arch_register_req_t *get_ia32_out_req(const ir_node *node, int pos) {
809         ia32_attr_t *attr = get_ia32_attr(node);
810         if(attr->out_req == NULL)
811                 return arch_no_register_req;
812
813         return attr->out_req[pos];
814 }
815
816 /**
817  * Sets the OUT register requirements at position pos.
818  */
819 void set_ia32_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
820         ia32_attr_t *attr  = get_ia32_attr(node);
821         attr->out_req[pos] = req;
822 }
823
824 /**
825  * Sets the IN register requirements at position pos.
826  */
827 void set_ia32_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
828         ia32_attr_t *attr = get_ia32_attr(node);
829         attr->in_req[pos] = req;
830 }
831
832 /**
833  * Returns the register flag of an ia32 node.
834  */
835 arch_irn_flags_t get_ia32_flags(const ir_node *node) {
836         ia32_attr_t *attr = get_ia32_attr(node);
837         return attr->data.flags;
838 }
839
840 /**
841  * Sets the register flag of an ia32 node.
842  */
843 void set_ia32_flags(ir_node *node, arch_irn_flags_t flags) {
844         ia32_attr_t *attr = get_ia32_attr(node);
845         attr->data.flags  = flags;
846 }
847
848 /**
849  * Returns the result register slots of an ia32 node.
850  */
851 const arch_register_t **get_ia32_slots(const ir_node *node) {
852         ia32_attr_t *attr = get_ia32_attr(node);
853         return attr->slots;
854 }
855
856 /**
857  * Sets the number of results.
858  */
859 void set_ia32_n_res(ir_node *node, int n_res) {
860         ia32_attr_t *attr = get_ia32_attr(node);
861         attr->data.n_res  = n_res;
862 }
863
864 /**
865  * Returns the number of results.
866  */
867 int get_ia32_n_res(const ir_node *node) {
868         ia32_attr_t *attr = get_ia32_attr(node);
869         return attr->data.n_res;
870 }
871
872 /**
873  * Returns the flavour of an ia32 node,
874  */
875 ia32_op_flavour_t get_ia32_flavour(const ir_node *node) {
876         ia32_attr_t *attr = get_ia32_attr(node);
877         return attr->data.op_flav;
878 }
879
880 /**
881  * Sets the flavour of an ia32 node to flavour_Div/Mod/DivMod/Mul/Mulh.
882  */
883 void set_ia32_flavour(ir_node *node, ia32_op_flavour_t op_flav) {
884         ia32_attr_t *attr  = get_ia32_attr(node);
885         attr->data.op_flav = op_flav;
886 }
887
888 /**
889  * Returns the projnum code.
890  */
891 pn_Cmp get_ia32_pncode(const ir_node *node) {
892         ia32_attr_t *attr = get_ia32_attr(node);
893         return attr->pn_code;
894 }
895
896 /**
897  * Sets the projnum code
898  */
899 void set_ia32_pncode(ir_node *node, pn_Cmp code) {
900         ia32_attr_t *attr = get_ia32_attr(node);
901         attr->pn_code     = code;
902 }
903
904 /**
905  * Sets the flags for the n'th out.
906  */
907 void set_ia32_out_flags(ir_node *node, arch_irn_flags_t flags, int pos) {
908         ia32_attr_t *attr = get_ia32_attr(node);
909         assert(pos < (int) attr->data.n_res && "Invalid OUT position.");
910         attr->out_flags[pos] = flags;
911 }
912
913 /**
914  * Gets the flags for the n'th out.
915  */
916 arch_irn_flags_t get_ia32_out_flags(const ir_node *node, int pos) {
917         ia32_attr_t *attr = get_ia32_attr(node);
918         return pos < (int)attr->data.n_res ? attr->out_flags[pos] : arch_irn_flags_none;
919 }
920
921 /**
922  * Get the list of available execution units.
923  */
924 const be_execution_unit_t ***get_ia32_exec_units(const ir_node *node) {
925         ia32_attr_t *attr = get_ia32_attr(node);
926         return attr->exec_units;
927 }
928
929 /**
930  * Get the exception label attribute.
931  */
932 unsigned get_ia32_exc_label(const ir_node *node) {
933         ia32_attr_t *attr = get_ia32_attr(node);
934         return attr->data.except_label;
935 }
936
937 /**
938  * Set the exception label attribute.
939  */
940 void set_ia32_exc_label(ir_node *node, unsigned flag) {
941         ia32_attr_t *attr = get_ia32_attr(node);
942         attr->data.except_label = flag;
943 }
944
945 #ifndef NDEBUG
946
947 /**
948  * Returns the name of the original ir node.
949  */
950 const char *get_ia32_orig_node(const ir_node *node) {
951         ia32_attr_t *attr = get_ia32_attr(node);
952         return attr->orig_node;
953 }
954
955 /**
956  * Sets the name of the original ir node.
957  */
958 void set_ia32_orig_node(ir_node *node, const char *name) {
959         ia32_attr_t *attr = get_ia32_attr(node);
960         attr->orig_node   = name;
961 }
962
963 #endif /* NDEBUG */
964
965 /******************************************************************************************************
966  *                      _       _         _   _           __                  _   _
967  *                     (_)     | |       | | | |         / _|                | | (_)
968  *  ___ _ __   ___  ___ _  __ _| |   __ _| |_| |_ _ __  | |_ _   _ _ __   ___| |_ _  ___  _ __    ___
969  * / __| '_ \ / _ \/ __| |/ _` | |  / _` | __| __| '__| |  _| | | | '_ \ / __| __| |/ _ \| '_ \  / __|
970  * \__ \ |_) |  __/ (__| | (_| | | | (_| | |_| |_| |    | | | |_| | | | | (__| |_| | (_) | | | | \__ \
971  * |___/ .__/ \___|\___|_|\__,_|_|  \__,_|\__|\__|_|    |_|  \__,_|_| |_|\___|\__|_|\___/|_| |_| |___/
972  *     | |
973  *     |_|
974  ******************************************************************************************************/
975
976 /**
977  * Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node
978  */
979 void copy_ia32_Immop_attr(ir_node *node, ir_node *from) {
980         ia32_immop_type_t immop_type = get_ia32_immop_type(from);
981
982         if(immop_type == ia32_ImmConst) {
983                 set_ia32_Immop_tarval(node, get_ia32_Immop_tarval(from));
984         } else if(immop_type == ia32_ImmSymConst) {
985                 set_ia32_Immop_symconst(node, get_ia32_Immop_symconst(from));
986         } else {
987                 ia32_attr_t *attr = get_ia32_attr(node);
988                 assert(immop_type == ia32_ImmNone);
989                 attr->data.imm_tp = ia32_ImmNone;
990         }
991 }
992
993 /**
994  * Copy the attributes from a Firm Const/SymConst to an ia32_Const
995  */
996 void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
997         assert(is_ia32_Cnst(ia32_cnst) && "Need ia32_Const to set Const attr");
998
999         switch (get_irn_opcode(cnst)) {
1000                 case iro_Const:
1001                         set_ia32_Const_tarval(ia32_cnst, get_Const_tarval(cnst));
1002                         break;
1003                 case iro_SymConst:
1004                         assert(get_SymConst_kind(cnst) == symconst_addr_ent);
1005                         set_ia32_Immop_symconst(ia32_cnst, get_SymConst_entity(cnst));
1006                         break;
1007                 case iro_Unknown:
1008                         assert(0 && "Unknown Const NYI");
1009                         break;
1010                 default:
1011                         assert(0 && "Cannot create ia32_Const for this opcode");
1012         }
1013 }
1014
1015 void set_ia32_Const_tarval(ir_node *ia32_cnst, tarval *tv) {
1016 #if 0
1017         if(mode_is_reference(get_tarval_mode(tv))) {
1018                 if(tarval_is_null(tv)) {
1019                         tv = get_tarval_null(mode_Iu);
1020                 } else {
1021                         long val;
1022                         /* workaround... */
1023                         if(!tarval_is_long(tv))
1024                                 panic("Can't convert reference tarval to mode_Iu at %+F", ia32_cnst);
1025                         val = get_tarval_long(tv);
1026                         tv = new_tarval_from_long(val, mode_Iu);
1027                 }
1028         } else {
1029                 tv = tarval_convert_to(tv, mode_Iu);
1030         }
1031 #else
1032         tv = tarval_convert_to(tv, mode_Iu);
1033 #endif
1034
1035         assert(tv != get_tarval_bad() && tv != get_tarval_undefined()
1036                         && tv != NULL);
1037         set_ia32_Immop_tarval(ia32_cnst, tv);
1038 }
1039
1040
1041 /**
1042  * Sets the AddrMode(S|D) attribute
1043  */
1044 void set_ia32_AddrMode(ir_node *node, char direction) {
1045         ia32_attr_t *attr = get_ia32_attr(node);
1046
1047         switch (direction) {
1048                 case 'D':
1049                         attr->data.tp = ia32_AddrModeD;
1050                         break;
1051                 case 'S':
1052                         attr->data.tp = ia32_AddrModeS;
1053                         break;
1054                 default:
1055                         assert(0 && "wrong AM type");
1056         }
1057 }
1058
1059 /**
1060  * Returns whether or not the node is an immediate operation with Const.
1061  */
1062 int is_ia32_ImmConst(const ir_node *node) {
1063         ia32_attr_t *attr = get_ia32_attr(node);
1064         return (attr->data.imm_tp == ia32_ImmConst);
1065 }
1066
1067 /**
1068  * Returns whether or not the node is an immediate operation with SymConst.
1069  */
1070 int is_ia32_ImmSymConst(const ir_node *node) {
1071         ia32_attr_t *attr = get_ia32_attr(node);
1072         return (attr->data.imm_tp == ia32_ImmSymConst);
1073 }
1074
1075 /**
1076  * Returns whether or not the node is an AddrModeS node.
1077  */
1078 int is_ia32_AddrModeS(const ir_node *node) {
1079         ia32_attr_t *attr = get_ia32_attr(node);
1080         return (attr->data.tp == ia32_AddrModeS);
1081 }
1082
1083 /**
1084  * Returns whether or not the node is an AddrModeD node.
1085  */
1086 int is_ia32_AddrModeD(const ir_node *node) {
1087         ia32_attr_t *attr = get_ia32_attr(node);
1088         return (attr->data.tp == ia32_AddrModeD);
1089 }
1090
1091 /**
1092  * Checks if node is a Load or xLoad/vfLoad.
1093  */
1094 int is_ia32_Ld(const ir_node *node) {
1095         int op = get_ia32_irn_opcode(node);
1096         return op == iro_ia32_Load ||
1097                op == iro_ia32_xLoad ||
1098                op == iro_ia32_vfld ||
1099                op == iro_ia32_fld;
1100 }
1101
1102 /**
1103  * Checks if node is a Store or xStore/vfStore.
1104  */
1105 int is_ia32_St(const ir_node *node) {
1106         int op = get_ia32_irn_opcode(node);
1107         return op == iro_ia32_Store ||
1108                op == iro_ia32_Store8Bit ||
1109                op == iro_ia32_xStore ||
1110                op == iro_ia32_vfst ||
1111                op == iro_ia32_fst ||
1112                op == iro_ia32_fstp;
1113 }
1114
1115 /**
1116  * Checks if node is a Const or xConst/vfConst.
1117  */
1118 int is_ia32_Cnst(const ir_node *node) {
1119         int op = get_ia32_irn_opcode(node);
1120         return op == iro_ia32_Const || op == iro_ia32_xConst || op == iro_ia32_vfConst;
1121 }
1122
1123 /**
1124  * Returns the name of the OUT register at position pos.
1125  */
1126 const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
1127         ia32_attr_t *attr = get_ia32_attr(node);
1128
1129         assert(pos < (int) attr->data.n_res && "Invalid OUT position.");
1130         assert(attr->slots[pos]  && "No register assigned");
1131
1132         return arch_register_get_name(attr->slots[pos]);
1133 }
1134
1135 /**
1136  * Returns the index of the OUT register at position pos within its register class.
1137  */
1138 int get_ia32_out_regnr(const ir_node *node, int pos) {
1139         ia32_attr_t *attr = get_ia32_attr(node);
1140
1141         assert(pos < (int) attr->data.n_res && "Invalid OUT position.");
1142         assert(attr->slots[pos]  && "No register assigned");
1143
1144         return arch_register_get_index(attr->slots[pos]);
1145 }
1146
1147 /**
1148  * Returns the OUT register at position pos.
1149  */
1150 const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) {
1151         ia32_attr_t *attr = get_ia32_attr(node);
1152
1153         assert(pos < (int) attr->data.n_res && "Invalid OUT position.");
1154         assert(attr->slots[pos]  && "No register assigned");
1155
1156         return attr->slots[pos];
1157 }
1158
1159 /**
1160  * Initializes the nodes attributes.
1161  */
1162 void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
1163                           const arch_register_req_t **in_reqs,
1164                           const arch_register_req_t **out_reqs,
1165                           const be_execution_unit_t ***execution_units,
1166                           int n_res, unsigned latency)
1167 {
1168         ia32_attr_t *attr = get_ia32_attr(node);
1169
1170         set_ia32_flags(node, flags);
1171         set_ia32_in_req_all(node, in_reqs);
1172         set_ia32_out_req_all(node, out_reqs);
1173         set_ia32_latency(node, latency);
1174         set_ia32_n_res(node, n_res);
1175
1176         attr->exec_units = execution_units;
1177
1178         attr->out_flags = NEW_ARR_D(int, get_irg_obstack(get_irn_irg(node)), n_res);
1179         memset(attr->out_flags, 0, n_res * sizeof(attr->out_flags[0]));
1180
1181         memset((void *)attr->slots, 0, n_res * sizeof(attr->slots[0]));
1182 }
1183
1184 ir_node *get_ia32_result_proj(const ir_node *node)
1185 {
1186         const ir_edge_t *edge;
1187
1188         foreach_out_edge(node, edge) {
1189                 ir_node *proj = get_edge_src_irn(edge);
1190                 if(get_Proj_proj(proj) == 0) {
1191                         return proj;
1192                 }
1193         }
1194         return NULL;
1195 }
1196
1197 /***************************************************************************************
1198  *                  _                            _                   _
1199  *                 | |                          | |                 | |
1200  *  _ __   ___   __| | ___    ___ ___  _ __  ___| |_ _ __ _   _  ___| |_ ___  _ __ ___
1201  * | '_ \ / _ \ / _` |/ _ \  / __/ _ \| '_ \/ __| __| '__| | | |/ __| __/ _ \| '__/ __|
1202  * | | | | (_) | (_| |  __/ | (_| (_) | | | \__ \ |_| |  | |_| | (__| || (_) | |  \__ \
1203  * |_| |_|\___/ \__,_|\___|  \___\___/|_| |_|___/\__|_|   \__,_|\___|\__\___/|_|  |___/
1204  *
1205  ***************************************************************************************/
1206
1207 /* default compare operation to compare attributes */
1208 int ia32_compare_attr(ia32_attr_t *a, ia32_attr_t *b) {
1209         if (a->data.tp != b->data.tp
1210                         || a->data.imm_tp != b->data.imm_tp)
1211                 return 1;
1212
1213         if (a->data.imm_tp == ia32_ImmConst
1214                         && a->cnst_val.tv != b->cnst_val.tv)
1215                 return 1;
1216
1217         if (a->data.imm_tp == ia32_ImmSymConst
1218                         && a->cnst_val.sc != b->cnst_val.sc)
1219                 return 1;
1220         if(a->data.imm_tp == ia32_ImmAsm
1221                         && a->cnst_val.asm_text != b->cnst_val.asm_text)
1222                 return 1;
1223
1224         if (a->data.am_flavour != b->data.am_flavour
1225             || a->data.am_scale != b->data.am_scale
1226             || a->data.am_sc_sign != b->data.am_sc_sign
1227             || a->am_offs != b->am_offs
1228             || a->am_sc != b->am_sc
1229             || a->ls_mode != b->ls_mode)
1230                 return 1;
1231
1232         if (a->data.use_frame != b->data.use_frame
1233             || a->data.use_frame != b->data.use_frame
1234             || a->frame_ent != b->frame_ent)
1235                 return 1;
1236
1237         if(a->pn_code != b->pn_code)
1238                 return 1;
1239
1240         if (a->data.tp != b->data.tp
1241             || a->data.op_flav != b->data.op_flav)
1242                 return 1;
1243
1244         if (a->data.except_label != b->data.except_label)
1245                 return 1;
1246
1247         return 0;
1248 }
1249
1250 /* copies the ia32 attributes */
1251 static void ia32_copy_attr(const ir_node *old_node, ir_node *new_node) {
1252         ia32_attr_t *attr_old = get_ia32_attr(old_node);
1253         ia32_attr_t *attr_new = get_ia32_attr(new_node);
1254
1255         /* copy the attributes */
1256         memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
1257
1258         /* copy out flags */
1259         attr_new->out_flags =
1260                 DUP_ARR_D(int, get_irg_obstack(get_irn_irg(new_node)), attr_old->out_flags);
1261 }
1262
1263 /* Include the generated constructor functions */
1264 #include "gen_ia32_new_nodes.c.inl"
1265
1266 /**
1267  * Registers the ia32_copy_attr function for all ia32 opcodes.
1268  */
1269 void ia32_register_copy_attr_func(void) {
1270         int i;
1271
1272         for (i = get_irp_n_opcodes() - 1; i >= 0; --i) {
1273                 ir_op *op = get_irp_opcode(i);
1274                 if (is_ia32_op(op))
1275                         op->ops.copy_attr = ia32_copy_attr;
1276         }
1277 }