823d43ff4c37cb2238cd824c801e2675137f0d1f
[libfirm] / ir / be / amd64 / amd64_spec.pl
1 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
2
3 $arch = "amd64";
4
5 # The node description is done as a perl hash initializer with the
6 # following structure:
7 #
8 # %nodes = (
9 #
10 # <op-name> => {
11 #   arity     => "0|1|2|3 ... |variable|dynamic|any",   # optional
12 #   state     => "floats|pinned|mem_pinned|exc_pinned", # optional
13 #   args      => [
14 #                    { type => "type 1", name => "name 1" },
15 #                    { type => "type 2", name => "name 2" },
16 #                    ...
17 #                  ],
18 #   comment   => "any comment for constructor",  # optional
19 #   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
20 #   cmp_attr  => "c source code for comparing node attributes", # optional
21 #   outs      => { "out1", "out2" },# optional, creates pn_op_out1, ... consts
22 #   ins       => { "in1", "in2" },  # optional, creates n_op_in1, ... consts
23 #   mode      => "mode_Iu",         # optional, predefines the mode
24 #   emit      => "emit code with templates",   # optional for virtual nodes
25 #   attr      => "additional attribute arguments for constructor", # optional
26 #   init_attr => "emit attribute initialization template",         # optional
27 #   rd_constructor => "c source code which constructs an ir_node", # optional
28 #   hash_func => "name of the hash function for this operation",   # optional, get the default hash function else
29 #   latency   => "latency of this operation (can be float)"        # optional
30 #   attr_type => "name of the attribute struct",                   # optional
31 # },
32 #
33 # ... # (all nodes you need to describe)
34 #
35 # ); # close the %nodes initializer
36
37 # state: state of the operation, OPTIONAL (default is "floats")
38 #
39 # arity: arity of the operation, MUST NOT BE OMITTED
40 #
41 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
42 #        are always the first 3 arguments and are always autmatically
43 #        created)
44 #        If this key is missing the following arguments will be created:
45 #        for i = 1 .. arity: ir_node *op_i
46 #        ir_mode *mode
47 #
48 # outs:  if a node defines more than one output, the names of the projections
49 #        nodes having outs having automatically the mode mode_T
50 #
51 # comment: OPTIONAL comment for the node constructor
52 #
53 # register types:
54 $normal      =  0; # no special type
55 $ignore      =  1; # ignore (do not assign this register)
56 $virtual     =  2; # the register is a virtual one
57 $state       =  4; # register represents a state
58 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
59 %reg_classes = (
60         gp => [
61                 { name => "rax", dwarf => 0 },
62                 { name => "rcx", dwarf => 2 },
63                 { name => "rdx", dwarf => 1 },
64                 { name => "rsi", dwarf => 4 },
65                 { name => "rdi", dwarf => 5 },
66                 { name => "rbx", dwarf => 3 },
67                 { name => "rbp", dwarf => 6 },
68                 { name => "rsp", dwarf => 7, type => $ignore }, # stackpointer?
69                 { name => "r8",  dwarf => 8 },
70                 { name => "r9",  dwarf => 9 },
71                 { name => "r10", dwarf => 10 },
72                 { name => "r11", dwarf => 11 },
73                 { name => "r12", dwarf => 12 },
74                 { name => "r13", dwarf => 13 },
75                 { name => "r14", dwarf => 14 },
76                 { name => "r15", dwarf => 15 },
77 #               { name => "gp_NOREG", type => $ignore }, # we need a dummy register for NoReg nodes
78                 { mode => "mode_Lu" }
79         ],
80 #       fp => [
81 #               { name => "xmm0",  dwarf => 17 },
82 #               { name => "xmm1",  dwarf => 18 },
83 #               { name => "xmm2",  dwarf => 19 },
84 #               { name => "xmm3",  dwarf => 20 },
85 #               { name => "xmm4",  dwarf => 21 },
86 #               { name => "xmm5",  dwarf => 22 },
87 #               { name => "xmm6",  dwarf => 23 },
88 #               { name => "xmm7",  dwarf => 24 },
89 #               { name => "xmm8",  dwarf => 25 },
90 #               { name => "xmm9",  dwarf => 26 },
91 #               { name => "xmm10", dwarf => 27 },
92 #               { name => "xmm11", dwarf => 28 },
93 #               { name => "xmm12", dwarf => 29 },
94 #               { name => "xmm13", dwarf => 30 },
95 #               { name => "xmm14", dwarf => 31 },
96 #               { name => "xmm15", dwarf => 32 },
97 #               { mode => "mode_D" }
98 #       ]
99         flags => [
100                 { name => "eflags", dwarf => 49 },
101                 { mode => "mode_Iu", flags => "manual_ra" }
102         ],
103 );
104
105 $mode_gp        = "mode_Lu";
106 $mode_flags     = "mode_Iu";
107
108 sub amd64_custom_init_attr {
109         my $constr = shift;
110         my $node   = shift;
111         my $name   = shift;
112         my $res    = "";
113
114         if(defined($node->{modified_flags})) {
115                 $res .= "\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);\n";
116         }
117         return $res;
118 }
119 $custom_init_attr_func = \&amd64_custom_init_attr;
120
121 $default_copy_attr = "amd64_copy_attr";
122
123 %init_attr = (
124         amd64_attr_t           =>
125                  "\tinit_amd64_attributes(res, irn_flags_, in_reqs, n_res);",
126         amd64_SymConst_attr_t =>
127                 "\tinit_amd64_attributes(res, irn_flags_, in_reqs, n_res);"
128                 . "\tinit_amd64_SymConst_attributes(res, entity);",
129         amd64_condcode_attr_t =>
130                 "\tinit_amd64_attributes(res, irn_flags_, in_reqs, n_res);"
131                 . "\tinit_amd64_condcode_attributes(res, pnc);",
132 );
133
134 %compare_attr = (
135         amd64_attr_t           => "cmp_amd64_attr",
136         amd64_SymConst_attr_t  => "cmp_amd64_attr_SymConst",
137         amd64_condcode_attr_t  => "cmp_amd64_attr_condcode",
138 );
139
140 %nodes = (
141 Push => {
142         state     => "exc_pinned",
143         reg_req   => { in => [ "gp", "gp", "none", "gp", "rsp" ], out => [ "rsp:I|S", "none" ] },
144         ins       => [ "base", "index", "mem", "val", "stack" ],
145         emit      => 'push %S0',
146         outs      => [ "stack", "M" ],
147         am        => "source,unary",
148         latency   => 2,
149 #       units     => [ "GP" ],
150 },
151
152 Add => {
153         op_flags   => [ "commutative" ],
154         irn_flags  => [ "rematerializable" ],
155         state      => "exc_pinned",
156         reg_req    => { in => [ "gp", "gp" ],
157                         out => [ "gp" ] },
158         ins        => [ "left", "right" ],
159         outs       => [ "res" ],
160         mode       => $mode_gp,
161         modified_flags => 1,
162 },
163
164 Mul => {
165         # we should not rematrialize this node. It produces 2 results and has
166         # very strict constraints
167         state     => "exc_pinned",
168         reg_req   => { in  => [ "rax", "gp" ],
169                        out => [ "rax rdx" ] },
170         ins       => [ "left", "right" ],
171         emit      => 'mul %S1',
172         outs      => [ "res" ],
173         mode      => $mode_gp,
174         am        => "source,binary",
175         modified_flags => $status_flags
176 },
177
178 Sub => {
179         irn_flags  => [ "rematerializable" ],
180         state      => "exc_pinned",
181         reg_req    => { in => [ "gp", "gp" ],
182                         out => [ "gp" ] },
183         ins        => [ "left", "right" ],
184         outs       => [ "res" ],
185         mode       => $mode_gp,
186         modified_flags => 1,
187 },
188
189 Neg => {
190         irn_flags => [ "rematerializable" ],
191         reg_req   => { in => [ "gp" ],
192                        out => [ "in_r1", "flags" ] },
193         emit      => 'neg %S0',
194         ins       => [ "val" ],
195         outs      => [ "res", "flags" ],
196         mode      => $mode_gp,
197         modified_flags => $status_flags
198 },
199
200 Immediate => {
201         op_flags  => [ "constlike" ],
202         attr      => "unsigned imm_value",
203         init_attr => "attr->ext.imm_value = imm_value;",
204         reg_req   => { out => [ "gp" ] },
205         emit      => 'mov %C, %D0',
206         mode      => $mode_gp,
207 },
208
209 SymConst => {
210         op_flags  => [ "constlike" ],
211         irn_flags => [ "rematerializable" ],
212         attr      => "ir_entity *entity",
213         attr_type => "amd64_SymConst_attr_t",
214         reg_req   => { out => [ "gp" ] },
215         outs      => [ "res" ],
216         mode      => $mode_gp,
217 },
218
219 Conv => {
220         state     => "exc_pinned",
221         attr      => "ir_mode *smaller_mode",
222         init_attr => "attr->ls_mode = smaller_mode;",
223         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
224         ins       => [ "val" ],
225         outs      => [ "res" ],
226         mode      => $mode_gp,
227 },
228
229 Jmp => {
230         state     => "pinned",
231         op_flags  => [ "cfopcode" ],
232         reg_req   => { out => [ "none" ] },
233         mode      => "mode_X",
234 },
235
236 Cmp => {
237         irn_flags => [ "rematerializable" ],
238         state     => "exc_pinned",
239         reg_req   => { in  => [ "gp", "gp" ],
240                        out => [ "flags" ] },
241         ins       => [ "left", "right" ],
242         outs      => [ "eflags" ],
243         emit      => 'cmp %S0, %S1',
244         attr      => "int ins_permuted, int cmp_unsigned",
245         init_attr => "attr->data.ins_permuted   = ins_permuted;\n".
246                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
247         mode      => $mode_flags,
248         modified_flags => 1,
249 },
250
251 Jcc => {
252         state     => "pinned",
253         op_flags  => [ "cfopcode", "forking" ],
254         reg_req   => { in  => [ "eflags" ], out => [ "none", "none" ] },
255         ins       => [ "eflags" ],
256         outs      => [ "false", "true" ],
257         attr      => "ir_relation relation",
258         init_attr => "attr->ext.relation = relation;",
259         mode      => "mode_T",
260 },
261
262 Load => {
263         op_flags  => [ "uses_memory" ],
264         state     => "exc_pinned",
265         reg_req   => { in => [ "gp", "none" ],
266                        out => [ "gp", "none" ] },
267         ins       => [ "ptr", "mem" ],
268         outs      => [ "res",  "M" ],
269         attr      => "ir_entity *entity",
270         attr_type => "amd64_SymConst_attr_t",
271         emit      => "mov %O(%S0), %D0"
272 },
273
274 FrameAddr => {
275         op_flags  => [ "constlike" ],
276         irn_flags => [ "rematerializable" ],
277         reg_req   => { in => [ "gp" ], out => [ "gp" ] },
278         ins       => [ "base" ],
279         attr      => "ir_entity *entity",
280         attr_type => "amd64_SymConst_attr_t",
281         mode      => $mode_gp,
282 },
283
284 Store => {
285         op_flags  => [ "uses_memory" ],
286         state     => "exc_pinned",
287         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
288         ins       => [ "ptr", "val", "mem" ],
289         outs      => [ "M" ],
290         attr      => "ir_entity *entity",
291         attr_type => "amd64_SymConst_attr_t",
292         mode      => "mode_M",
293         emit      => "mov %S1, %O(%S0)"
294 },
295
296 #NoReg_GP => {
297 #       state     => "pinned",
298 #       op_flags  => [ "constlike", "dump_noblcok" ],
299 #       reg_req   => { out => [ "gp_NOREG:I" ] },
300 #       units     => [],
301 #       emit      => "",
302 #       latency   => 0,
303 #       mode      => $mode_gp,
304 #},
305 );