cleanup and improve generate_opcode script, you can now have nodes with variable...
[libfirm] / ir / be / ia32 / ia32_spec.pl
1 # Creation: 2005/10/19
2 # $Id$
3 # This is the specification for the ia32 assembler Firm-operations
4
5 use File::Basename;
6
7 $new_emit_syntax = 1;
8 my $myname = $0;
9
10 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
11 $arch = "ia32";
12
13 # The node description is done as a perl hash initializer with the
14 # following structure:
15 #
16 # %nodes = (
17 #
18 # <op-name> => {
19 #   op_flags  => "N|L|C|X|I|F|Y|H|c|K",
20 #   irn_flags => "R|N|I|S"
21 #   arity     => "0|1|2|3 ... |variable|dynamic|any",
22 #   state     => "floats|pinned|mem_pinned|exc_pinned",
23 #   args      => [
24 #                    { type => "type 1", name => "name 1" },
25 #                    { type => "type 2", name => "name 2" },
26 #                    ...
27 #                  ],
28 #   comment   => "any comment for constructor",
29 #   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
30 #   cmp_attr  => "c source code for comparing node attributes",
31 #   emit      => "emit code with templates",
32 #   attr      => "attitional attribute arguments for constructor"
33 #   init_attr => "emit attribute initialization template"
34 #   rd_constructor => "c source code which constructs an ir_node"
35 #   latency   => "latency of this operation (can be float)"
36 # },
37 #
38 # ... # (all nodes you need to describe)
39 #
40 # ); # close the %nodes initializer
41
42 # op_flags: flags for the operation, OPTIONAL (default is "N")
43 # the op_flags correspond to the firm irop_flags:
44 #   N   irop_flag_none
45 #   L   irop_flag_labeled
46 #   C   irop_flag_commutative
47 #   X   irop_flag_cfopcode
48 #   I   irop_flag_ip_cfopcode
49 #   F   irop_flag_fragile
50 #   Y   irop_flag_forking
51 #   H   irop_flag_highlevel
52 #   c   irop_flag_constlike
53 #   K   irop_flag_keep
54 #
55 # irn_flags: special node flags, OPTIONAL (default is 0)
56 # following irn_flags are supported:
57 #   R   rematerializeable
58 #   N   not spillable
59 #   I   ignore for register allocation
60 #   S   modifies stack pointer
61 #
62 # state: state of the operation, OPTIONAL (default is "floats")
63 #
64 # arity: arity of the operation, MUST NOT BE OMITTED
65 #
66 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
67 #        are always the first 3 arguments and are always autmatically
68 #        created)
69 #        If this key is missing the following arguments will be created:
70 #        for i = 1 .. arity: ir_node *op_i
71 #        ir_mode *mode
72 #
73 # outs:  if a node defines more than one output, the names of the projections
74 #        nodes having outs having automatically the mode mode_T
75 #        One can also annotate some flags for each out, additional to irn_flags.
76 #        They are separated from name with a colon ':', and concatenated by pipe '|'
77 #        Only I and S are available at the moment (same meaning as in irn_flags).
78 #        example: [ "frame:I", "stack:I|S", "M" ]
79 #
80 # comment: OPTIONAL comment for the node constructor
81 #
82 # rd_constructor: for every operation there will be a
83 #      new_rd_<arch>_<op-name> function with the arguments from above
84 #      which creates the ir_node corresponding to the defined operation
85 #      you can either put the complete source code of this function here
86 #
87 #      This key is OPTIONAL. If omitted, the following constructor will
88 #      be created:
89 #      if (!op_<arch>_<op-name>) assert(0);
90 #      for i = 1 to arity
91 #         set in[i] = op_i
92 #      done
93 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
94 #      return res
95 #
96 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
97 #
98 # latency: the latency of the operation, default is 1
99 #
100
101 # register types:
102 #   0 - no special type
103 #   1 - caller save (register must be saved by the caller of a function)
104 #   2 - callee save (register must be saved by the called function)
105 #   4 - ignore (do not assign this register)
106 #   8 - emitter can choose an arbitrary register of this class
107 #  16 - the register is a virtual one
108 #  32 - register represents a state
109 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
110 %reg_classes = (
111         gp => [
112                 { name => "eax", type => 1 },
113                 { name => "edx", type => 1 },
114                 { name => "ebx", type => 2 },
115                 { name => "ecx", type => 1 },
116                 { name => "esi", type => 2 },
117                 { name => "edi", type => 2 },
118                 { name => "ebp", type => 2 },
119                 { name => "esp", type => 4 },
120                 { name => "gp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
121                 { name => "gp_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
122                 { mode => "mode_Iu" }
123         ],
124         xmm => [
125                 { name => "xmm0", type => 1 },
126                 { name => "xmm1", type => 1 },
127                 { name => "xmm2", type => 1 },
128                 { name => "xmm3", type => 1 },
129                 { name => "xmm4", type => 1 },
130                 { name => "xmm5", type => 1 },
131                 { name => "xmm6", type => 1 },
132                 { name => "xmm7", type => 1 },
133                 { name => "xmm_NOREG", type => 4 | 16 },     # we need a dummy register for NoReg nodes
134                 { name => "xmm_UKNWN", type => 4 | 8 | 16},  # we need a dummy register for Unknown nodes
135                 { mode => "mode_E" }
136         ],
137         vfp => [
138                 { name => "vf0", type => 1 | 16 },
139                 { name => "vf1", type => 1 | 16 },
140                 { name => "vf2", type => 1 | 16 },
141                 { name => "vf3", type => 1 | 16 },
142                 { name => "vf4", type => 1 | 16 },
143                 { name => "vf5", type => 1 | 16 },
144                 { name => "vf6", type => 1 | 16 },
145                 { name => "vf7", type => 1 | 16 },
146                 { name => "vfp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
147                 { name => "vfp_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
148                 { mode => "mode_E" }
149         ],
150         st => [
151                 { name => "st0", realname => "st",    type => 4 },
152                 { name => "st1", realname => "st(1)", type => 4 },
153                 { name => "st2", realname => "st(2)", type => 4 },
154                 { name => "st3", realname => "st(3)", type => 4 },
155                 { name => "st4", realname => "st(4)", type => 4 },
156                 { name => "st5", realname => "st(5)", type => 4 },
157                 { name => "st6", realname => "st(6)", type => 4 },
158                 { name => "st7", realname => "st(7)", type => 4 },
159                 { mode => "mode_E" }
160         ],
161         fp_cw => [      # the floating point control word
162                 { name => "fpcw", type => 4 | 32},
163                 { mode => "mode_fpcw" }
164         ],
165         flags => [
166                 { name => "eflags", type => 4 },
167                 { mode => "mode_Iu" }
168         ],
169         fp_sw => [
170                 { name => "fpsw", type => 4 },
171                 { mode => "mode_Hu" }
172         ],
173 ); # %reg_classes
174
175 %flags = (
176         CF  => { reg => "eflags", bit => 0 },
177         PF  => { reg => "eflags", bit => 2 },
178         AF  => { reg => "eflags", bit => 4 },
179         ZF  => { reg => "eflags", bit => 6 },
180         SF  => { reg => "eflags", bit => 7 },
181         TF  => { reg => "eflags", bit => 8 },
182         IF  => { reg => "eflags", bit => 9 },
183         DF  => { reg => "eflags", bit => 10 },
184         OF  => { reg => "eflags", bit => 11 },
185         IOPL0 => { reg => "eflags", bit => 12 },
186         IOPL1 => { reg => "eflags", bit => 13 },
187         NT  => { reg => "eflags", bit => 14 },
188         RF  => { reg => "eflags", bit => 16 },
189         VM  => { reg => "eflags", bit => 17 },
190         AC  => { reg => "eflags", bit => 18 },
191         VIF => { reg => "eflags", bit => 19 },
192         VIP => { reg => "eflags", bit => 20 },
193         ID  => { reg => "eflags", bit => 21 },
194
195         FP_IE => { reg => "fpsw", bit => 0 },
196         FP_DE => { reg => "fpsw", bit => 1 },
197         FP_ZE => { reg => "fpsw", bit => 2 },
198         FP_OE => { reg => "fpsw", bit => 3 },
199         FP_UE => { reg => "fpsw", bit => 4 },
200         FP_PE => { reg => "fpsw", bit => 5 },
201         FP_SF => { reg => "fpsw", bit => 6 },
202         FP_ES => { reg => "fpsw", bit => 7 },
203         FP_C0 => { reg => "fpsw", bit => 8 },
204         FP_C1 => { reg => "fpsw", bit => 9 },
205         FP_C2 => { reg => "fpsw", bit => 10 },
206         FP_TOP0 => { reg => "fpsw", bit => 11 },
207         FP_TOP1 => { reg => "fpsw", bit => 12 },
208         FP_TOP2 => { reg => "fpsw", bit => 13 },
209         FP_C3 => { reg => "fpsw", bit => 14 },
210         FP_B  => { reg => "fpsw", bit => 15 },
211
212         FP_IM => { reg => "fpcw", bit => 0 },
213         FP_DM => { reg => "fpcw", bit => 1 },
214         FP_ZM => { reg => "fpcw", bit => 2 },
215         FP_OM => { reg => "fpcw", bit => 3 },
216         FP_UM => { reg => "fpcw", bit => 4 },
217         FP_PM => { reg => "fpcw", bit => 5 },
218         FP_PC0 => { reg => "fpcw", bit => 8 },
219         FP_PC1 => { reg => "fpcw", bit => 9 },
220         FP_RC0 => { reg => "fpcw", bit => 10 },
221         FP_RC1 => { reg => "fpcw", bit => 11 },
222         FP_X  => { reg => "fpcw", bit => 12 }
223 ); # %flags
224
225 %cpu = (
226         GP     => [ 1, "GP_EAX", "GP_EBX", "GP_ECX", "GP_EDX", "GP_ESI", "GP_EDI", "GP_EBP" ],
227         SSE    => [ 1, "SSE_XMM0", "SSE_XMM1", "SSE_XMM2", "SSE_XMM3", "SSE_XMM4", "SSE_XMM5", "SSE_XMM6", "SSE_XMM7" ],
228         VFP    => [ 1, "VFP_VF0", "VFP_VF1", "VFP_VF2", "VFP_VF3", "VFP_VF4", "VFP_VF5", "VFP_VF6", "VFP_VF7" ],
229         BRANCH => [ 1, "BRANCH1", "BRANCH2" ],
230 ); # %cpu
231
232 %vliw = (
233         bundle_size       => 1,
234         bundels_per_cycle => 1
235 ); # vliw
236
237 %emit_templates = (
238         S0 => "${arch}_emit_source_register(env, node, 0);",
239         S1 => "${arch}_emit_source_register(env, node, 1);",
240         S2 => "${arch}_emit_source_register(env, node, 2);",
241         S3 => "${arch}_emit_source_register(env, node, 3);",
242         S4 => "${arch}_emit_source_register(env, node, 4);",
243         S5 => "${arch}_emit_source_register(env, node, 5);",
244         D0 => "${arch}_emit_dest_register(env, node, 0);",
245         D1 => "${arch}_emit_dest_register(env, node, 1);",
246         D2 => "${arch}_emit_dest_register(env, node, 2);",
247         D3 => "${arch}_emit_dest_register(env, node, 3);",
248         D4 => "${arch}_emit_dest_register(env, node, 4);",
249         D5 => "${arch}_emit_dest_register(env, node, 5);",
250         X0 => "${arch}_emit_x87_name(env, node, 0);",
251         X1 => "${arch}_emit_x87_name(env, node, 1);",
252         X2 => "${arch}_emit_x87_name(env, node, 2);",
253         C  => "${arch}_emit_immediate(env, node);",
254         SE => "${arch}_emit_extend_suffix(env, get_ia32_ls_mode(node));",
255         ME => "if(get_mode_size_bits(get_ia32_ls_mode(node)) != 32)\n
256                    ia32_emit_mode_suffix(env, node);",
257         M  => "${arch}_emit_mode_suffix(env, node);",
258         XM => "${arch}_emit_x87_mode_suffix(env, node);",
259         XXM => "${arch}_emit_xmm_mode_suffix(env, node);",
260         XSD => "${arch}_emit_xmm_mode_suffix_s(env, node);",
261         AM => "${arch}_emit_am(env, node);",
262         unop => "${arch}_emit_unop(env, node);",
263         binop => "${arch}_emit_binop(env, node);",
264         x87_binop => "${arch}_emit_x87_binop(env, node);",
265 );
266
267 #--------------------------------------------------#
268 #                        _                         #
269 #                       (_)                        #
270 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
271 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
272 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
273 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
274 #                                      | |         #
275 #                                      |_|         #
276 #--------------------------------------------------#
277
278 $default_cmp_attr  = "return ia32_compare_attr(attr_a, attr_b);";
279 $default_attr_type = "ia32_attr_t";
280
281 %operands = (
282 );
283
284 $mode_xmm     = "mode_E";
285 $mode_gp      = "mode_Iu";
286 $mode_fpcw    = "mode_fpcw";
287 $status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ];
288 $fpcw_flags   = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
289                   "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ];
290
291 %nodes = (
292
293 #Immediate => {
294 #       irn_flags => "i",
295 #       reg_req   => { out => [ "NoReg_GP" ] },
296 #       mode      => $mode_gp,
297 #       attr_type => "ia32_imm_t",
298 #},
299
300 Asm => {
301         mode      => "mode_T",
302         arity     => "variable",
303         out_arity => "variable",
304 },
305
306 #-----------------------------------------------------------------#
307 #  _       _                                         _            #
308 # (_)     | |                                       | |           #
309 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
310 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
311 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
312 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
313 #                   __/ |                                         #
314 #                  |___/                                          #
315 #-----------------------------------------------------------------#
316
317 # commutative operations
318
319 # NOTE:
320 # All nodes supporting Addressmode have 5 INs:
321 # 1 - base    r1 == NoReg in case of no AM or no base
322 # 2 - index   r2 == NoReg in case of no AM or no index
323 # 3 - op1     r3 == always present
324 # 4 - op2     r4 == NoReg in case of immediate operation
325 # 5 - mem     NoMem in case of no AM otherwise it takes the mem from the Load
326
327 Add => {
328         irn_flags => "R",
329         reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
330         ins       => [ "base", "index", "left", "right", "mem" ],
331         emit      => '. add%M %binop',
332         units     => [ "GP" ],
333         mode      => $mode_gp,
334         modified_flags => $status_flags
335 },
336
337 Adc => {
338         reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
339         emit      => '. adc%M %binop',
340         units     => [ "GP" ],
341         mode      => $mode_gp,
342         modified_flags => $status_flags
343 },
344
345 Add64Bit => {
346         irn_flags => "R",
347         arity     => 4,
348         reg_req   => { in => [ "gp", "gp", "gp", "gp" ], out => [ "!in", "!in" ] },
349         emit      => '
350 . movl %S0, %D0
351 . movl %S1, %D1
352 . addl %S2, %D0
353 . adcl %S3, %D1
354 ',
355         outs      => [ "low_res", "high_res" ],
356         units     => [ "GP" ],
357         modified_flags => $status_flags
358 },
359
360 l_Add => {
361         op_flags  => "C",
362         irn_flags => "R",
363         cmp_attr  => "return 1;",
364         arity     => 2,
365 },
366
367 l_Adc => {
368         op_flags  => "C",
369         cmp_attr  => "return 1;",
370         arity     => 2,
371 },
372
373 Mul => {
374         # we should not rematrialize this node. It produces 2 results and has
375         # very strict constrains
376         reg_req   => { in => [ "gp", "gp", "eax", "gp", "none" ], out => [ "eax", "edx", "none" ] },
377         emit      => '. mul%M %unop',
378         outs      => [ "EAX", "EDX", "M" ],
379         latency   => 10,
380         units     => [ "GP" ],
381         modified_flags => $status_flags
382 },
383
384 l_Mul => {
385         # we should not rematrialize this node. It produces 2 results and has
386         # very strict constrains
387         op_flags  => "C",
388         cmp_attr  => "return 1;",
389         outs      => [ "EAX", "EDX", "M" ],
390         arity     => 2
391 },
392
393 IMul => {
394         irn_flags => "R",
395         reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
396         emit      => '. imul%M %binop',
397         latency   => 5,
398         units     => [ "GP" ],
399         mode      => $mode_gp,
400         modified_flags => $status_flags
401 },
402
403 IMul1OP => {
404         irn_flags => "R",
405         reg_req   => { in => [ "gp", "gp", "eax", "gp", "none" ], out => [ "eax", "edx", "none" ] },
406         emit      => '. imul%M %unop',
407         outs      => [ "EAX", "EDX", "M" ],
408         latency   => 5,
409         units     => [ "GP" ],
410         modified_flags => $status_flags
411 },
412
413 l_IMul => {
414         op_flags  => "C",
415         cmp_attr  => "return 1;",
416         arity     => 2
417 },
418
419 And => {
420         irn_flags => "R",
421         reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
422         emit      => '. and%M %binop',
423         units     => [ "GP" ],
424         mode      => $mode_gp,
425         modified_flags => $status_flags
426 },
427
428 Or => {
429         irn_flags => "R",
430         reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
431         emit      => '. or%M %binop',
432         units     => [ "GP" ],
433         mode      => $mode_gp,
434         modified_flags => $status_flags
435 },
436
437 Xor => {
438         irn_flags => "R",
439         reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
440         emit      => '. xor%M %binop',
441         units     => [ "GP" ],
442         mode      => $mode_gp,
443         modified_flags => $status_flags
444 },
445
446 l_Xor => {
447         op_flags  => "C",
448         cmp_attr  => "return 1;",
449         arity     => 2,
450         modified_flags => $status_flags
451 },
452
453 # not commutative operations
454
455 Sub => {
456         irn_flags => "R",
457         reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
458         emit      => '. sub%M %binop',
459         units     => [ "GP" ],
460         mode      => $mode_gp,
461         modified_flags => $status_flags
462 },
463
464 Sbb => {
465         reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3 !in_r4" ] },
466         emit      => '. sbb%M %binop',
467         units     => [ "GP" ],
468         mode      => $mode_gp,
469         modified_flags => $status_flags
470 },
471
472 Sub64Bit => {
473         irn_flags => "R",
474         arity     => 4,
475         reg_req   => { in => [ "gp", "gp", "gp", "gp" ], out => [ "!in", "!in" ] },
476         emit      => '
477 . movl %S0, %D0
478 . movl %S1, %D1
479 . subl %S2, %D0
480 . sbbl %S3, %D1
481 ',
482         outs      => [ "low_res", "high_res" ],
483         units     => [ "GP" ],
484         modified_flags => $status_flags
485 },
486
487 l_Sub => {
488         irn_flags => "R",
489         cmp_attr  => "return 1;",
490         arity     => 2,
491 },
492
493 l_Sbb => {
494         cmp_attr  => "return 1;",
495         arity     => 2,
496 },
497
498 IDiv => {
499         op_flags  => "F|L",
500         state     => "exc_pinned",
501         reg_req   => { in => [ "gp", "gp", "eax", "edx", "gp", "none" ], out => [ "eax", "edx", "none" ] },
502         attr      => "ia32_op_flavour_t dm_flav",
503         init_attr => "attr->data.op_flav = dm_flav;",
504         emit      => ". idiv%M %unop",
505         outs      => [ "div_res", "mod_res", "M" ],
506         latency   => 25,
507         units     => [ "GP" ],
508         modified_flags => $status_flags
509 },
510
511 Div => {
512         op_flags  => "F|L",
513         state     => "exc_pinned",
514         reg_req   => { in => [ "gp", "gp", "eax", "edx", "gp", "none" ], out => [ "eax", "edx", "none" ] },
515         attr      => "ia32_op_flavour_t dm_flav",
516         init_attr => "attr->data.op_flav = dm_flav;",
517         emit      => ". div%M %unop",
518         outs      => [ "div_res", "mod_res", "M" ],
519         latency   => 25,
520         units     => [ "GP" ],
521         modified_flags => $status_flags
522 },
523
524 Shl => {
525         irn_flags => "R",
526         reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
527         ins       => [ "base", "index", "left", "right", "mem" ],
528         emit      => '. shl%M %binop',
529         units     => [ "GP" ],
530         mode      => $mode_gp,
531         modified_flags => $status_flags
532 },
533
534 l_Shl => {
535         cmp_attr  => "return 1;",
536         arity     => 2
537 },
538
539 ShlD => {
540         irn_flags => "R",
541         # Out requirements is: different from all in
542         # This is because, out must be different from LowPart and ShiftCount.
543         # We could say "!ecx !in_r4" but it can occur, that all values live through
544         # this Shift and the only value dying is the ShiftCount. Then there would be a
545         # register missing, as result must not be ecx and all other registers are
546         # occupied. What we should write is "!in_r4 !in_r5", but this is not supported
547         # (and probably never will). So we create artificial interferences of the result
548         # with all inputs, so the spiller can always assure a free register.
549         reg_req   => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] },
550         emit      =>
551 '
552 if (get_ia32_immop_type(node) == ia32_ImmNone) {
553         if (get_ia32_op_type(node) == ia32_AddrModeD) {
554                 . shld%M %%cl, %S3, %AM
555         } else {
556                 . shld%M %%cl, %S3, %S2
557         }
558 } else {
559         if (get_ia32_op_type(node) == ia32_AddrModeD) {
560                 . shld%M %C, %S3, %AM
561         } else {
562                 . shld%M %C, %S3, %S2
563         }
564 }
565 ',
566         latency   => 6,
567         units     => [ "GP" ],
568         mode      => $mode_gp,
569         modified_flags => $status_flags
570 },
571
572 l_ShlD => {
573         cmp_attr  => "return 1;",
574         arity     => 3,
575 },
576
577 Shr => {
578         irn_flags => "R",
579         reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
580         emit      => '. shr%M %binop',
581         units     => [ "GP" ],
582         mode      => $mode_gp,
583         modified_flags => $status_flags
584 },
585
586 l_Shr => {
587         cmp_attr  => "return 1;",
588         arity     => 2
589 },
590
591 ShrD => {
592         irn_flags => "R",
593         # Out requirements is: different from all in
594         # This is because, out must be different from LowPart and ShiftCount.
595         # We could say "!ecx !in_r4" but it can occur, that all values live through
596         # this Shift and the only value dying is the ShiftCount. Then there would be a
597         # register missing, as result must not be ecx and all other registers are
598         # occupied. What we should write is "!in_r4 !in_r5", but this is not supported
599         # (and probably never will). So we create artificial interferences of the result
600         # with all inputs, so the spiller can always assure a free register.
601         reg_req   => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] },
602         emit      => '
603 if (get_ia32_immop_type(node) == ia32_ImmNone) {
604         if (get_ia32_op_type(node) == ia32_AddrModeD) {
605                 . shrd%M %%cl, %S3, %AM
606         } else {
607                 . shrd%M %%cl, %S3, %S2
608         }
609 } else {
610         if (get_ia32_op_type(node) == ia32_AddrModeD) {
611                 . shrd%M %C, %S3, %AM
612         } else {
613                 . shrd%M %C, %S3, %S2
614         }
615 }
616 ',
617         latency   => 6,
618         units     => [ "GP" ],
619         mode      => $mode_gp,
620         modified_flags => $status_flags
621 },
622
623 l_ShrD => {
624         cmp_attr  => "return 1;",
625         arity     => 3
626 },
627
628 Sar => {
629         irn_flags => "R",
630         reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
631         emit      => '. sar%M %binop',
632         units     => [ "GP" ],
633         mode      => $mode_gp,
634         modified_flags => $status_flags
635 },
636
637 l_Sar => {
638         cmp_attr  => "return 1;",
639         arity     => 2
640 },
641
642 Ror => {
643         irn_flags => "R",
644         reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
645         emit      => '. ror%M %binop',
646         units     => [ "GP" ],
647         mode      => $mode_gp,
648         modified_flags => $status_flags
649 },
650
651 Rol => {
652         irn_flags => "R",
653         reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
654         emit      => '. rol%M %binop',
655         units     => [ "GP" ],
656         mode      => $mode_gp,
657         modified_flags => $status_flags
658 },
659
660 # unary operations
661
662 Neg => {
663         irn_flags => "R",
664         reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
665         emit      => '. neg%M %unop',
666         units     => [ "GP" ],
667         mode      => $mode_gp,
668         modified_flags => $status_flags
669 },
670
671 Minus64Bit => {
672         irn_flags => "R",
673         reg_req   => { in => [ "gp", "gp", "gp" ], out => [ "!in", "!in" ] },
674         emit      => '
675 . movl %S0, %D0
676 . movl %S0, %D1
677 . subl %S1, %D0
678 . sbbl %S2, %D1
679 ',
680         outs      => [ "low_res", "high_res" ],
681         units     => [ "GP" ],
682         modified_flags => $status_flags
683 },
684
685
686 l_Neg => {
687         cmp_attr  => "return 1;",
688         arity     => 1,
689 },
690
691 Inc => {
692         irn_flags => "R",
693         reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
694         emit      => '. inc%M %unop',
695         units     => [ "GP" ],
696         mode      => $mode_gp,
697         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
698 },
699
700 Dec => {
701         irn_flags => "R",
702         reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
703         emit      => '. dec%M %unop',
704         units     => [ "GP" ],
705         mode      => $mode_gp,
706         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
707 },
708
709 Not => {
710         irn_flags => "R",
711         reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
712         emit      => '. not%M %unop',
713         units     => [ "GP" ],
714         mode      => $mode_gp,
715         modified_flags => []
716 },
717
718 # other operations
719
720 CondJmp => {
721         state     => "pinned",
722         op_flags  => "L|X|Y",
723         reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "none", "none"] },
724         outs      => [ "false", "true" ],
725         latency   => 3,
726         units     => [ "BRANCH" ],
727 },
728
729 TestJmp => {
730         state     => "pinned",
731         op_flags  => "L|X|Y",
732         reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
733         outs      => [ "false", "true" ],
734         latency   => 3,
735         units     => [ "BRANCH" ],
736 },
737
738 CJmpAM => {
739         state     => "pinned",
740         op_flags  => "L|X|Y",
741         reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "none", "none" ] },
742         outs      => [ "false", "true" ],
743         units     => [ "BRANCH" ],
744 },
745
746 CJmp => {
747         state     => "pinned",
748         op_flags  => "L|X|Y",
749         reg_req   => { in => [ "gp", "gp" ] },
750         units     => [ "BRANCH" ],
751 },
752
753 SwitchJmp => {
754         state     => "pinned",
755         op_flags  => "L|X|Y",
756         reg_req   => { in => [ "gp" ], out => [ "none" ] },
757         latency   => 3,
758         units     => [ "BRANCH" ],
759 },
760
761 Const => {
762         op_flags  => "c",
763         irn_flags => "R",
764         reg_req   => { out => [ "gp" ] },
765         units     => [ "GP" ],
766         mode      => $mode_gp,
767 },
768
769 Unknown_GP => {
770         state     => "pinned",
771         op_flags  => "c",
772         irn_flags => "I",
773         reg_req   => { out => [ "gp_UKNWN" ] },
774         units     => [],
775         emit      => "",
776         mode      => $mode_gp
777 },
778
779 Unknown_VFP => {
780         state     => "pinned",
781         op_flags  => "c",
782         irn_flags => "I",
783         reg_req   => { out => [ "vfp_UKNWN" ] },
784         units     => [],
785         emit      => "",
786         mode      => "mode_E"
787 },
788
789 Unknown_XMM => {
790         state     => "pinned",
791         op_flags  => "c",
792         irn_flags => "I",
793         reg_req   => { out => [ "xmm_UKNWN" ] },
794         units     => [],
795         emit      => "",
796         mode      => "mode_E"
797 },
798
799 NoReg_GP => {
800         state     => "pinned",
801         op_flags  => "c",
802         irn_flags => "I",
803         reg_req   => { out => [ "gp_NOREG" ] },
804         units     => [],
805         emit      => "",
806         mode      => $mode_gp
807 },
808
809 NoReg_VFP => {
810         state     => "pinned",
811         op_flags  => "c",
812         irn_flags => "I",
813         reg_req   => { out => [ "vfp_NOREG" ] },
814         units     => [],
815         emit      => "",
816         mode      => "mode_E"
817 },
818
819 NoReg_XMM => {
820         state     => "pinned",
821         op_flags  => "c",
822         irn_flags => "I",
823         reg_req   => { out => [ "xmm_NOREG" ] },
824         units     => [],
825         emit      => "",
826         mode      => "mode_E"
827 },
828
829 ChangeCW => {
830         state     => "pinned",
831         op_flags  => "c",
832         irn_flags => "I",
833         reg_req   => { out => [ "fp_cw" ] },
834         mode      => $mode_fpcw,
835         latency   => 3,
836         units     => [ "GP" ],
837         modified_flags => $fpcw_flags
838 },
839
840 FldCW => {
841         op_flags  => "L|F",
842         state     => "exc_pinned",
843         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] },
844         latency   => 5,
845         emit      => ". fldcw %AM",
846         mode      => $mode_fpcw,
847         units     => [ "GP" ],
848         modified_flags => $fpcw_flags
849 },
850
851 FnstCW => {
852         op_flags  => "L|F",
853         state     => "exc_pinned",
854         reg_req   => { in => [ "gp", "gp", "fp_cw", "none" ], out => [ "none" ] },
855         latency   => 5,
856         emit      => ". fnstcw %AM",
857         mode      => "mode_M",
858         units     => [ "GP" ],
859 },
860
861 Cltd => {
862         # we should not rematrialize this node. It produces 2 results and has
863         # very strict constrains
864         reg_req   => { in => [ "gp" ], out => [ "eax in_r1", "edx" ] },
865         emit      => '. cltd',
866         outs      => [ "EAX", "EDX" ],
867         units     => [ "GP" ],
868 },
869
870 # Load / Store
871
872 Load => {
873         op_flags  => "L|F",
874         state     => "exc_pinned",
875         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
876         latency   => 3,
877         emit      => ". mov%SE%ME%.l %AM, %D0",
878         outs      => [ "res", "M" ],
879         units     => [ "GP" ],
880 },
881
882 l_Load => {
883         op_flags  => "L|F",
884         cmp_attr  => "return 1;",
885         outs      => [ "res", "M" ],
886         arity     => 2,
887 },
888
889 l_Store => {
890         op_flags  => "L|F",
891         cmp_attr  => "return 1;",
892         state     => "exc_pinned",
893         arity     => 3,
894         mode      => "mode_M",
895 },
896
897 Store => {
898         op_flags  => "L|F",
899         state     => "exc_pinned",
900         reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "none" ] },
901         emit      => '. mov%M %binop',
902         latency   => 3,
903         units     => [ "GP" ],
904         mode      => "mode_M",
905 },
906
907 Store8Bit => {
908         op_flags  => "L|F",
909         state     => "exc_pinned",
910         reg_req   => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => ["none" ] },
911         emit      => '. mov%M %binop',
912         latency   => 3,
913         units     => [ "GP" ],
914         mode      => "mode_M",
915 },
916
917 Lea => {
918         irn_flags => "R",
919         reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1" ] },
920         emit      => '. leal %AM, %D0',
921         latency   => 2,
922         units     => [ "GP" ],
923         mode      => $mode_gp,
924         modified_flags => [],
925 },
926
927 Push => {
928         reg_req   => { in => [ "gp", "gp", "gp", "esp", "none" ], out => [ "esp", "none" ] },
929         emit      => '. push%M %unop',
930         outs      => [ "stack:I|S", "M" ],
931         latency   => 3,
932         units     => [ "GP" ],
933         modified_flags => [],
934 },
935
936 Pop => {
937         reg_req   => { in => [ "gp", "gp", "esp", "none" ], out => [ "esp", "gp", "none" ] },
938         emit      => '. pop%M %unop',
939         outs      => [ "stack:I|S", "res", "M" ],
940         latency   => 4,
941         units     => [ "GP" ],
942         modified_flags => [],
943 },
944
945 Enter => {
946         reg_req   => { in => [ "esp" ], out => [ "ebp", "esp", "none" ] },
947         emit      => '. enter',
948         outs      => [ "frame:I", "stack:I|S", "M" ],
949         latency   => 15,
950         units     => [ "GP" ],
951 },
952
953 Leave => {
954         reg_req   => { in => [ "esp", "ebp" ], out => [ "ebp", "esp" ] },
955         emit      => '. leave',
956         outs      => [ "frame:I", "stack:I|S" ],
957         latency   => 3,
958         units     => [ "GP" ],
959 },
960
961 AddSP => {
962         irn_flags => "I",
963         reg_req   => { in => [ "gp", "gp", "esp", "gp", "none" ], out => [ "in_r3", "none" ] },
964         emit      => '. addl %binop',
965         outs      => [ "stack:S", "M" ],
966         units     => [ "GP" ],
967         modified_flags => $status_flags
968 },
969
970 SubSP => {
971         irn_flags => "I",
972         reg_req   => { in => [ "gp", "gp", "esp", "gp", "none" ], out => [ "in_r3", "none" ] },
973         emit      => '. subl %binop',
974         outs      => [ "stack:S", "M" ],
975         units     => [ "GP" ],
976         modified_flags => $status_flags
977 },
978
979 LdTls => {
980         irn_flags => "R",
981         reg_req   => { out => [ "gp" ] },
982         units     => [ "GP" ],
983 },
984
985 # the int instruction
986 int => {
987         reg_req   => { in => [ "none" ], out => [ "none" ] },
988         mode      => "mode_M",
989         attr      => "tarval *tv",
990         init_attr => "\tset_ia32_Immop_tarval(res, tv);",
991         emit      => '. int %C',
992         units     => [ "GP" ],
993         cmp_attr  => "return 1;",
994 },
995
996
997 #-----------------------------------------------------------------------------#
998 #   _____ _____ ______    __ _             _                     _            #
999 #  / ____/ ____|  ____|  / _| |           | |                   | |           #
1000 # | (___| (___ | |__    | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1001 #  \___ \\___ \|  __|   |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1002 #  ____) |___) | |____  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1003 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1004 #-----------------------------------------------------------------------------#
1005
1006 # commutative operations
1007
1008 xAdd => {
1009         irn_flags => "R",
1010         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
1011         emit      => '. add%XXM %binop',
1012         latency   => 4,
1013         units     => [ "SSE" ],
1014         mode      => "mode_E",
1015 },
1016
1017 xMul => {
1018         irn_flags => "R",
1019         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
1020         emit      => '. mul%XXM %binop',
1021         latency   => 4,
1022         units     => [ "SSE" ],
1023         mode      => "mode_E",
1024 },
1025
1026 xMax => {
1027         irn_flags => "R",
1028         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
1029         emit      => '. max%XXM %binop',
1030         latency   => 2,
1031         units     => [ "SSE" ],
1032         mode      => "mode_E",
1033 },
1034
1035 xMin => {
1036         irn_flags => "R",
1037         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
1038         emit      => '. min%XXM %binop',
1039         latency   => 2,
1040         units     => [ "SSE" ],
1041         mode      => "mode_E",
1042 },
1043
1044 xAnd => {
1045         irn_flags => "R",
1046         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
1047         emit      => '. andp%XSD %binop',
1048         latency   => 3,
1049         units     => [ "SSE" ],
1050         mode      => "mode_E",
1051 },
1052
1053 xOr => {
1054         irn_flags => "R",
1055         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
1056         emit      => '. orp%XSD %binop',
1057         units     => [ "SSE" ],
1058         mode      => "mode_E",
1059 },
1060
1061 xXor => {
1062         irn_flags => "R",
1063         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
1064         emit      => '. xorp%XSD %binop',
1065         latency   => 3,
1066         units     => [ "SSE" ],
1067         mode      => "mode_E",
1068 },
1069
1070 # not commutative operations
1071
1072 xAndNot => {
1073         irn_flags => "R",
1074         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3 !in_r4" ] },
1075         emit      => '. andnp%XSD %binop',
1076         latency   => 3,
1077         units     => [ "SSE" ],
1078         mode      => "mode_E",
1079 },
1080
1081 xSub => {
1082         irn_flags => "R",
1083         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
1084         emit      => '. sub%XXM %binop',
1085         latency   => 4,
1086         units     => [ "SSE" ],
1087         mode      => "mode_E",
1088 },
1089
1090 xDiv => {
1091         irn_flags => "R",
1092         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3 !in_r4", "none" ] },
1093         outs      => [ "res", "M" ],
1094         emit      => '. div%XXM %binop',
1095         latency   => 16,
1096         units     => [ "SSE" ],
1097 },
1098
1099 # other operations
1100
1101 xCmp => {
1102         irn_flags => "R",
1103         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3 !in_r4" ] },
1104         latency   => 3,
1105         units     => [ "SSE" ],
1106         mode      => "mode_E",
1107 },
1108
1109 xCondJmp => {
1110         state     => "pinned",
1111         op_flags  => "L|X|Y",
1112         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "none", "none" ] },
1113         outs      => [ "false", "true" ],
1114         latency   => 5,
1115         units     => [ "SSE" ],
1116 },
1117
1118 xConst => {
1119         op_flags  => "c",
1120         irn_flags => "R",
1121         reg_req   => { out => [ "xmm" ] },
1122         emit      => '. mov%XXM %C, %D0',
1123         latency   => 2,
1124         units     => [ "SSE" ],
1125         mode      => "mode_E",
1126 },
1127
1128 # Load / Store
1129
1130 xLoad => {
1131         op_flags  => "L|F",
1132         state     => "exc_pinned",
1133         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
1134         emit      => '. mov%XXM %AM, %D0',
1135         outs      => [ "res", "M" ],
1136         latency   => 2,
1137         units     => [ "SSE" ],
1138 },
1139
1140 xStore => {
1141         op_flags => "L|F",
1142         state    => "exc_pinned",
1143         reg_req  => { in => [ "gp", "gp", "xmm", "none" ] },
1144         emit     => '. mov%XXM %binop',
1145         latency  => 2,
1146         units    => [ "SSE" ],
1147         mode     => "mode_M",
1148 },
1149
1150 xStoreSimple => {
1151         op_flags => "L|F",
1152         state    => "exc_pinned",
1153         reg_req  => { in => [ "gp", "gp", "xmm", "none" ] },
1154         ins      => [ "base", "index", "val", "mem" ],
1155         emit     => '. mov%XXM %S2, %AM',
1156         latency  => 2,
1157         units    => [ "SSE" ],
1158         mode     => "mode_M",
1159 },
1160
1161 CvtSI2SS => {
1162         op_flags => "L|F",
1163         reg_req  => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm" ] },
1164         emit     => '. cvtsi2ss %D0, %AM',
1165         latency  => 2,
1166         units    => [ "SSE" ],
1167         mode     => $mode_xmm
1168 },
1169
1170 CvtSI2SD => {
1171         op_flags => "L|F",
1172         reg_req  => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm" ] },
1173         emit     => '. cvtsi2sd %unop',
1174         latency  => 2,
1175         units    => [ "SSE" ],
1176         mode     => $mode_xmm
1177 },
1178
1179
1180 l_X87toSSE => {
1181         op_flags => "L|F",
1182         cmp_attr => "return 1;",
1183         arity    => 3,
1184 },
1185
1186 l_SSEtoX87 => {
1187         op_flags => "L|F",
1188         cmp_attr => "return 1;",
1189         arity    => 3,
1190 },
1191
1192 GetST0 => {
1193         op_flags => "L|F",
1194         irn_flags => "I",
1195         state    => "exc_pinned",
1196         reg_req  => { in => [ "gp", "gp", "none" ] },
1197         emit     => '. fstp%XM %AM',
1198         latency  => 4,
1199         units    => [ "SSE" ],
1200         mode     => "mode_M",
1201 },
1202
1203 SetST0 => {
1204         op_flags => "L|F",
1205         irn_flags => "I",
1206         state    => "exc_pinned",
1207         reg_req  => { in => [ "gp", "gp", "none" ], out => [ "vf0", "none" ] },
1208         ins      => [ "base", "index", "mem" ],
1209         emit     => '. fld%XM %AM',
1210         outs     => [ "res", "M" ],
1211         latency  => 2,
1212         units     => [ "SSE" ],
1213 },
1214
1215 # CopyB
1216
1217 CopyB => {
1218         op_flags => "F|H",
1219         state    => "pinned",
1220         reg_req  => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
1221         outs     => [ "DST", "SRC", "CNT", "M" ],
1222         units    => [ "GP" ],
1223         modified_flags => [ "DF" ]
1224 },
1225
1226 CopyB_i => {
1227         op_flags => "F|H",
1228         state    => "pinned",
1229         reg_req  => { in => [ "edi", "esi", "none" ], out => [  "edi", "esi", "none" ] },
1230         outs     => [ "DST", "SRC", "M" ],
1231         units    => [ "GP" ],
1232         modified_flags => [ "DF" ]
1233 },
1234
1235 # Conversions
1236
1237 Conv_I2I => {
1238         reg_req  => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3", "none" ] },
1239         units    => [ "GP" ],
1240         mode     => $mode_gp,
1241         modified_flags => $status_flags
1242 },
1243
1244 Conv_I2I8Bit => {
1245         reg_req  => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => [ "in_r3", "none" ] },
1246         units    => [ "GP" ],
1247         mode     => $mode_gp,
1248         modified_flags => $status_flags
1249 },
1250
1251 Conv_I2FP => {
1252         reg_req  => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm", "none" ] },
1253         latency  => 10,
1254         units    => [ "SSE" ],
1255         mode     => "mode_E",
1256 },
1257
1258 Conv_FP2I => {
1259         reg_req  => { in => [ "gp", "gp", "xmm", "none" ], out => [ "gp", "none" ] },
1260         latency  => 10,
1261         units    => [ "SSE" ],
1262         mode     => $mode_gp,
1263 },
1264
1265 Conv_FP2FP => {
1266         reg_req  => { in => [ "gp", "gp", "xmm", "none" ], out => [ "xmm", "none" ] },
1267         latency  => 8,
1268         units    => [ "SSE" ],
1269         mode     => "mode_E",
1270 },
1271
1272 CmpCMov => {
1273         irn_flags => "R",
1274         reg_req   => { in => [ "gp", "gp", "gp", "gp" ], out => [ "in_r4" ] },
1275         latency   => 2,
1276         units     => [ "GP" ],
1277         mode      => $mode_gp,
1278 },
1279
1280 PsiCondCMov => {
1281         irn_flags => "R",
1282         reg_req   => { in => [ "gp", "gp", "gp" ], out => [ "in_r3" ] },
1283         latency   => 2,
1284         units     => [ "GP" ],
1285         mode      => $mode_gp,
1286 },
1287
1288 xCmpCMov => {
1289         irn_flags => "R",
1290         reg_req   => { in => [ "xmm", "xmm", "gp", "gp" ], out => [ "in_r4" ] },
1291         latency   => 5,
1292         units     => [ "SSE" ],
1293         mode      => $mode_gp,
1294 },
1295
1296 vfCmpCMov => {
1297         irn_flags => "R",
1298         reg_req   => { in => [ "vfp", "vfp", "gp", "gp" ], out => [ "in_r4" ] },
1299         latency   => 10,
1300         units     => [ "VFP" ],
1301         mode      => $mode_gp,
1302 },
1303
1304 CmpSet => {
1305         irn_flags => "R",
1306         reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "eax ebx ecx edx" ] },
1307         latency   => 2,
1308         units     => [ "GP" ],
1309         mode      => $mode_gp,
1310 },
1311
1312 PsiCondSet => {
1313         irn_flags => "R",
1314         reg_req   => { in => [ "gp" ], out => [ "eax ebx ecx edx" ] },
1315         latency   => 2,
1316         units     => [ "GP" ],
1317         mode      => $mode_gp,
1318 },
1319
1320 xCmpSet => {
1321         irn_flags => "R",
1322         reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "eax ebx ecx edx" ] },
1323         latency   => 5,
1324         units     => [ "SSE" ],
1325         mode      => $mode_gp,
1326 },
1327
1328 vfCmpSet => {
1329         irn_flags => "R",
1330         reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "eax ebx ecx edx" ] },
1331         latency   => 10,
1332         units     => [ "VFP" ],
1333         mode      => $mode_gp,
1334 },
1335
1336 vfCMov => {
1337         irn_flags => "R",
1338         reg_req   => { in => [ "vfp", "vfp", "vfp", "vfp" ], out => [ "vfp" ] },
1339         latency   => 10,
1340         units     => [ "VFP" ],
1341         mode      => "mode_E",
1342 },
1343
1344 #----------------------------------------------------------#
1345 #        _      _               _    __ _             _    #
1346 #       (_)    | |             | |  / _| |           | |   #
1347 # __   ___ _ __| |_ _   _  __ _| | | |_| | ___   __ _| |_  #
1348 # \ \ / / | '__| __| | | |/ _` | | |  _| |/ _ \ / _` | __| #
1349 #  \ V /| | |  | |_| |_| | (_| | | | | | | (_) | (_| | |_  #
1350 #   \_/ |_|_|   \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
1351 #                 | |                                      #
1352 #  _ __   ___   __| | ___  ___                             #
1353 # | '_ \ / _ \ / _` |/ _ \/ __|                            #
1354 # | | | | (_) | (_| |  __/\__ \                            #
1355 # |_| |_|\___/ \__,_|\___||___/                            #
1356 #----------------------------------------------------------#
1357
1358 vfadd => {
1359         irn_flags => "R",
1360         reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
1361         latency   => 4,
1362         units     => [ "VFP" ],
1363         mode      => "mode_E",
1364 },
1365
1366 vfmul => {
1367         irn_flags => "R",
1368         reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
1369         latency   => 4,
1370         units     => [ "VFP" ],
1371         mode      => "mode_E",
1372 },
1373
1374 l_vfmul => {
1375         op_flags  => "C",
1376         cmp_attr  => "return 1;",
1377         arity     => 2,
1378 },
1379
1380 vfsub => {
1381         irn_flags => "R",
1382         reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
1383         latency   => 4,
1384         units     => [ "VFP" ],
1385         mode      => "mode_E",
1386 },
1387
1388 l_vfsub => {
1389         cmp_attr  => "return 1;",
1390         arity     => 2,
1391 },
1392
1393 vfdiv => {
1394         reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp", "none" ] },
1395         outs      => [ "res", "M" ],
1396         latency   => 20,
1397         units     => [ "VFP" ],
1398 },
1399
1400 l_vfdiv => {
1401         cmp_attr  => "return 1;",
1402         outs      => [ "res", "M" ],
1403         arity     => 2,
1404 },
1405
1406 vfprem => {
1407         reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
1408         latency   => 20,
1409         units     => [ "VFP" ],
1410         mode      => "mode_E",
1411 },
1412
1413 l_vfprem => {
1414         cmp_attr  => "return 1;",
1415         arity     => 2,
1416 },
1417
1418 vfabs => {
1419         irn_flags => "R",
1420         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1421         latency   => 2,
1422         units     => [ "VFP" ],
1423         mode      => "mode_E",
1424 },
1425
1426 vfchs => {
1427         irn_flags => "R",
1428         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1429         latency   => 2,
1430         units     => [ "VFP" ],
1431         mode      => "mode_E",
1432 },
1433
1434 vfsin => {
1435         irn_flags => "R",
1436         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1437         latency   => 150,
1438         units     => [ "VFP" ],
1439         mode      => "mode_E",
1440 },
1441
1442 vfcos => {
1443         irn_flags => "R",
1444         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1445         latency   => 150,
1446         units     => [ "VFP" ],
1447         mode      => "mode_E",
1448 },
1449
1450 vfsqrt => {
1451         irn_flags => "R",
1452         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1453         latency   => 30,
1454         units     => [ "VFP" ],
1455         mode      => "mode_E",
1456 },
1457
1458 # virtual Load and Store
1459
1460 vfld => {
1461         op_flags  => "L|F",
1462         state     => "exc_pinned",
1463         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1464         outs      => [ "res", "M" ],
1465         latency   => 2,
1466         units     => [ "VFP" ],
1467 },
1468
1469 vfst => {
1470         op_flags  => "L|F",
1471         state     => "exc_pinned",
1472         reg_req   => { in => [ "gp", "gp", "vfp", "none" ] },
1473         latency   => 2,
1474         units     => [ "VFP" ],
1475         mode      => "mode_M",
1476 },
1477
1478 # Conversions
1479
1480 vfild => {
1481         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1482         outs      => [ "res", "M" ],
1483         latency   => 4,
1484         units     => [ "VFP" ],
1485 },
1486
1487 l_vfild => {
1488         cmp_attr  => "return 1;",
1489         outs      => [ "res", "M" ],
1490         arity     => 2,
1491 },
1492
1493 vfist => {
1494         reg_req   => { in => [ "gp", "gp", "vfp", "fpcw", "none" ] },
1495         latency   => 4,
1496         units     => [ "VFP" ],
1497         mode      => "mode_M",
1498 },
1499
1500 l_vfist => {
1501         cmp_attr  => "return 1;",
1502         arity     => 3,
1503         mode      => "mode_M",
1504 },
1505
1506
1507 # constants
1508
1509 vfldz => {
1510         irn_flags => "R",
1511         reg_req   => { out => [ "vfp" ] },
1512         latency   => 4,
1513         units     => [ "VFP" ],
1514         mode      => "mode_E",
1515 },
1516
1517 vfld1 => {
1518         irn_flags => "R",
1519         reg_req   => { out => [ "vfp" ] },
1520         latency   => 4,
1521         units     => [ "VFP" ],
1522         mode      => "mode_E",
1523 },
1524
1525 vfldpi => {
1526         irn_flags => "R",
1527         reg_req   => { out => [ "vfp" ] },
1528         latency   => 4,
1529         units     => [ "VFP" ],
1530         mode      => "mode_E",
1531 },
1532
1533 vfldln2 => {
1534         irn_flags => "R",
1535         reg_req   => { out => [ "vfp" ] },
1536         latency   => 4,
1537         units     => [ "VFP" ],
1538         mode      => "mode_E",
1539 },
1540
1541 vfldlg2 => {
1542         irn_flags => "R",
1543         reg_req   => { out => [ "vfp" ] },
1544         latency   => 4,
1545         units     => [ "VFP" ],
1546         mode      => "mode_E",
1547 },
1548
1549 vfldl2t => {
1550         irn_flags => "R",
1551         reg_req   => { out => [ "vfp" ] },
1552         latency   => 4,
1553         units     => [ "VFP" ],
1554         mode      => "mode_E",
1555 },
1556
1557 vfldl2e => {
1558         irn_flags => "R",
1559         reg_req   => { out => [ "vfp" ] },
1560         latency   => 4,
1561         units     => [ "VFP" ],
1562         mode      => "mode_E",
1563 },
1564
1565 vfConst => {
1566         op_flags  => "c",
1567         irn_flags => "R",
1568 #  init_attr => "  set_ia32_ls_mode(res, mode);",
1569         reg_req   => { out => [ "vfp" ] },
1570         latency   => 3,
1571         units     => [ "VFP" ],
1572         mode      => "mode_E",
1573 },
1574
1575 # other
1576
1577 vfCondJmp => {
1578         state     => "pinned",
1579         op_flags  => "L|X|Y",
1580         reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "none", "none", "eax" ] },
1581         outs      => [ "false", "true", "temp_reg_eax" ],
1582         latency   => 10,
1583         units     => [ "VFP" ],
1584 },
1585
1586 #------------------------------------------------------------------------#
1587 #       ___ _____    __ _             _                     _            #
1588 # __  _( _ )___  |  / _| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1589 # \ \/ / _ \  / /  | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1590 #  >  < (_) |/ /   |  _| | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1591 # /_/\_\___//_/    |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1592 #------------------------------------------------------------------------#
1593
1594 # Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
1595 #       are swapped, we work this around in the emitter...
1596
1597 fadd => {
1598         op_flags  => "R",
1599         rd_constructor => "NONE",
1600         reg_req   => { },
1601         emit      => '. fadd%XM %x87_binop',
1602 },
1603
1604 faddp => {
1605         op_flags  => "R",
1606         rd_constructor => "NONE",
1607         reg_req   => { },
1608         emit      => '. faddp %x87_binop',
1609 },
1610
1611 fmul => {
1612         op_flags  => "R",
1613         rd_constructor => "NONE",
1614         reg_req   => { },
1615         emit      => '. fmul%XM %x87_binop',
1616 },
1617
1618 fmulp => {
1619         op_flags  => "R",
1620         rd_constructor => "NONE",
1621         reg_req   => { },
1622         emit      => '. fmulp %x87_binop',,
1623 },
1624
1625 fsub => {
1626         op_flags  => "R",
1627         rd_constructor => "NONE",
1628         reg_req   => { },
1629         emit      => '. fsub%XM %x87_binop',
1630 },
1631
1632 fsubp => {
1633         op_flags  => "R",
1634         rd_constructor => "NONE",
1635         reg_req   => { },
1636 # see note about gas bugs
1637         emit      => '. fsubrp %x87_binop',
1638 },
1639
1640 fsubr => {
1641         op_flags  => "R",
1642         rd_constructor => "NONE",
1643         irn_flags => "R",
1644         reg_req   => { },
1645         emit      => '. fsubr%XM %x87_binop',
1646 },
1647
1648 fsubrp => {
1649         op_flags  => "R",
1650         rd_constructor => "NONE",
1651         irn_flags => "R",
1652         reg_req   => { },
1653 # see note about gas bugs
1654         emit      => '. fsubp %x87_binop',
1655 },
1656
1657 fprem => {
1658         op_flags  => "R",
1659         rd_constructor => "NONE",
1660         reg_req   => { },
1661         emit      => '. fprem1',
1662 },
1663
1664 # this node is just here, to keep the simulator running
1665 # we can omit this when a fprem simulation function exists
1666 fpremp => {
1667         op_flags  => "R",
1668         rd_constructor => "NONE",
1669         reg_req   => { },
1670         emit      => '. fprem1',
1671 },
1672
1673 fdiv => {
1674         op_flags  => "R",
1675         rd_constructor => "NONE",
1676         reg_req   => { },
1677         emit      => '. fdiv%XM %x87_binop',
1678 },
1679
1680 fdivp => {
1681         op_flags  => "R",
1682         rd_constructor => "NONE",
1683         reg_req   => { },
1684 # see note about gas bugs
1685         emit      => '. fdivrp %x87_binop',
1686 },
1687
1688 fdivr => {
1689         op_flags  => "R",
1690         rd_constructor => "NONE",
1691         reg_req   => { },
1692         emit      => '. fdivr%XM %x87_binop',
1693 },
1694
1695 fdivrp => {
1696         op_flags  => "R",
1697         rd_constructor => "NONE",
1698         reg_req   => { },
1699 # see note about gas bugs
1700         emit      => '. fdivp %x87_binop',
1701 },
1702
1703 fabs => {
1704         op_flags  => "R",
1705         rd_constructor => "NONE",
1706         reg_req   => { },
1707         emit      => '. fabs',
1708 },
1709
1710 fchs => {
1711         op_flags  => "R|K",
1712         rd_constructor => "NONE",
1713         reg_req   => { },
1714         emit      => '. fchs',
1715 },
1716
1717 fsin => {
1718         op_flags  => "R",
1719         rd_constructor => "NONE",
1720         reg_req   => { },
1721         emit      => '. fsin',
1722 },
1723
1724 fcos => {
1725         op_flags  => "R",
1726         rd_constructor => "NONE",
1727         reg_req   => { },
1728         emit      => '. fcos',
1729 },
1730
1731 fsqrt => {
1732         op_flags  => "R",
1733         rd_constructor => "NONE",
1734         reg_req   => { },
1735         emit      => '. fsqrt $',
1736 },
1737
1738 # x87 Load and Store
1739
1740 fld => {
1741         rd_constructor => "NONE",
1742         op_flags  => "R|L|F",
1743         state     => "exc_pinned",
1744         reg_req   => { },
1745         emit      => '. fld%XM %AM',
1746 },
1747
1748 fst => {
1749         rd_constructor => "NONE",
1750         op_flags  => "R|L|F",
1751         state     => "exc_pinned",
1752         reg_req   => { },
1753         emit      => '. fst%XM %AM',
1754         mode      => "mode_M",
1755 },
1756
1757 fstp => {
1758         rd_constructor => "NONE",
1759         op_flags  => "R|L|F",
1760         state     => "exc_pinned",
1761         reg_req   => { },
1762         emit      => '. fstp%XM %AM',
1763         mode      => "mode_M",
1764 },
1765
1766 # Conversions
1767
1768 fild => {
1769         op_flags  => "R",
1770         rd_constructor => "NONE",
1771         reg_req   => { },
1772         emit      => '. fild%XM %AM',
1773 },
1774
1775 fist => {
1776         op_flags  => "R",
1777         rd_constructor => "NONE",
1778         reg_req   => { },
1779         emit      => '. fist%XM %AM',
1780         mode      => "mode_M",
1781 },
1782
1783 fistp => {
1784         op_flags  => "R",
1785         rd_constructor => "NONE",
1786         reg_req   => { },
1787         emit      => '. fistp%XM %AM',
1788         mode      => "mode_M",
1789 },
1790
1791 # constants
1792
1793 fldz => {
1794         op_flags  => "R|c|K",
1795         irn_flags  => "R",
1796         reg_req   => { },
1797         emit      => '. fldz',
1798 },
1799
1800 fld1 => {
1801         op_flags  => "R|c|K",
1802         irn_flags  => "R",
1803         reg_req   => { },
1804         emit      => '. fld1',
1805 },
1806
1807 fldpi => {
1808         op_flags  => "R|c|K",
1809         irn_flags  => "R",
1810         reg_req   => { },
1811         emit      => '. fldpi',
1812 },
1813
1814 fldln2 => {
1815         op_flags  => "R|c|K",
1816         irn_flags  => "R",
1817         reg_req   => { },
1818         emit      => '. fldln2',
1819 },
1820
1821 fldlg2 => {
1822         op_flags  => "R|c|K",
1823         irn_flags  => "R",
1824         reg_req   => { },
1825         emit      => '. fldlg2',
1826 },
1827
1828 fldl2t => {
1829         op_flags  => "R|c|K",
1830         irn_flags  => "R",
1831         reg_req   => { },
1832         emit      => '. fldll2t',
1833 },
1834
1835 fldl2e => {
1836         op_flags  => "R|c|K",
1837         irn_flags  => "R",
1838         reg_req   => { },
1839         emit      => '. fldl2e',
1840 },
1841
1842 # fxch, fpush, fpop
1843 # Note that it is NEVER allowed to do CSE on these nodes
1844 # Moreover, note the virtual register requierements!
1845
1846 fxch => {
1847         op_flags  => "R|K",
1848         reg_req   => { },
1849         cmp_attr  => "return 1;",
1850         emit      => '. fxch %X0',
1851 },
1852
1853 fpush => {
1854         op_flags  => "R|K",
1855         reg_req   => {},
1856         cmp_attr  => "return 1;",
1857         emit      => '. fld %X0',
1858 },
1859
1860 fpushCopy => {
1861         op_flags  => "R",
1862         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1863         cmp_attr  => "return 1;",
1864         emit      => '. fld %X0',
1865 },
1866
1867 fpop => {
1868         op_flags  => "R|K",
1869         reg_req   => { },
1870         cmp_attr  => "return 1;",
1871         emit      => '. fstp %X0',
1872 },
1873
1874 # compare
1875
1876 fcomJmp => {
1877         op_flags  => "L|X|Y",
1878         reg_req   => { },
1879 },
1880
1881 fcompJmp => {
1882         op_flags  => "L|X|Y",
1883         reg_req   => { },
1884 },
1885
1886 fcomppJmp => {
1887         op_flags  => "L|X|Y",
1888         reg_req   => { },
1889 },
1890
1891 fcomrJmp => {
1892         op_flags  => "L|X|Y",
1893         reg_req   => { },
1894 },
1895
1896 fcomrpJmp => {
1897         op_flags  => "L|X|Y",
1898         reg_req   => { },
1899 },
1900
1901 fcomrppJmp => {
1902         op_flags  => "L|X|Y",
1903         reg_req   => { },
1904 },
1905
1906
1907 # -------------------------------------------------------------------------------- #
1908 #  ____ ____  _____                  _                               _             #
1909 # / ___/ ___|| ____| __   _____  ___| |_ ___  _ __   _ __   ___   __| | ___  ___   #
1910 # \___ \___ \|  _|   \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __|  #
1911 #  ___) |__) | |___   \ V /  __/ (__| || (_) | |    | | | | (_) | (_| |  __/\__ \  #
1912 # |____/____/|_____|   \_/ \___|\___|\__\___/|_|    |_| |_|\___/ \__,_|\___||___/  #
1913 #                                                                                  #
1914 # -------------------------------------------------------------------------------- #
1915
1916
1917 # Spilling and reloading of SSE registers, hardcoded, not generated #
1918
1919 xxLoad => {
1920         op_flags  => "L|F",
1921         state     => "exc_pinned",
1922         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
1923         emit      => '. movdqu %D0, %AM',
1924         outs      => [ "res", "M" ],
1925         units     => [ "SSE" ],
1926 },
1927
1928 xxStore => {
1929         op_flags => "L|F",
1930         state    => "exc_pinned",
1931         reg_req  => { in => [ "gp", "gp", "xmm", "none" ] },
1932         emit     => '. movdqu %binop',
1933         units    => [ "SSE" ],
1934         mode     => "mode_M",
1935 },
1936
1937 ); # end of %nodes
1938
1939 # Include the generated SIMD node specification written by the SIMD optimization
1940 $my_script_name = dirname($myname) . "/../ia32/ia32_simd_spec.pl";
1941 unless ($return = do $my_script_name) {
1942         warn "couldn't parse $my_script_name: $@" if $@;
1943         warn "couldn't do $my_script_name: $!"    unless defined $return;
1944         warn "couldn't run $my_script_name"       unless $return;
1945 }