Small simplification in ia32 ASM emitter.
[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 #   outs      => { "out1", "out2" } # optional, creates pn_op_out1, ... consts
32 #   ins       => { "in1", "in2" }   # optional, creates n_op_in1, ... consts
33 #   mode      => "mode_Iu"          # optional, predefines the mode
34 #   emit      => "emit code with templates",
35 #   attr      => "attitional attribute arguments for constructor",
36 #   init_attr => "emit attribute initialization template",
37 #   rd_constructor => "c source code which constructs an ir_node",
38 #   hash_func => "name of the hash function for this operation",
39 #   latency   => "latency of this operation (can be float)"
40 #   attr_type => "name of the attribute struct",
41 # },
42 #
43 # ... # (all nodes you need to describe)
44 #
45 # ); # close the %nodes initializer
46
47 # op_flags: flags for the operation, OPTIONAL (default is "N")
48 # the op_flags correspond to the firm irop_flags:
49 #   N   irop_flag_none
50 #   L   irop_flag_labeled
51 #   C   irop_flag_commutative
52 #   X   irop_flag_cfopcode
53 #   I   irop_flag_ip_cfopcode
54 #   F   irop_flag_fragile
55 #   Y   irop_flag_forking
56 #   H   irop_flag_highlevel
57 #   c   irop_flag_constlike
58 #   K   irop_flag_keep
59 #   NB  irop_flag_dump_noblock
60 #   NI  irop_flag_dump_noinput
61 #
62 # irn_flags: special node flags, OPTIONAL (default is 0)
63 # following irn_flags are supported:
64 #   R   rematerializeable
65 #   N   not spillable
66 #   I   ignore for register allocation
67 #   S   modifies stack pointer
68 #
69 # state: state of the operation, OPTIONAL (default is "floats")
70 #
71 # arity: arity of the operation, MUST NOT BE OMITTED
72 #
73 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
74 #        are always the first 3 arguments and are always autmatically
75 #        created)
76 #        If this key is missing the following arguments will be created:
77 #        for i = 1 .. arity: ir_node *op_i
78 #        ir_mode *mode
79 #
80 # outs:  if a node defines more than one output, the names of the projections
81 #        nodes having outs having automatically the mode mode_T
82 #        One can also annotate some flags for each out, additional to irn_flags.
83 #        They are separated from name with a colon ':', and concatenated by pipe '|'
84 #        Only I and S are available at the moment (same meaning as in irn_flags).
85 #        example: [ "frame:I", "stack:I|S", "M" ]
86 #
87 # comment: OPTIONAL comment for the node constructor
88 #
89 # rd_constructor: for every operation there will be a
90 #      new_rd_<arch>_<op-name> function with the arguments from above
91 #      which creates the ir_node corresponding to the defined operation
92 #      you can either put the complete source code of this function here
93 #
94 #      This key is OPTIONAL. If omitted, the following constructor will
95 #      be created:
96 #      if (!op_<arch>_<op-name>) assert(0);
97 #      for i = 1 to arity
98 #         set in[i] = op_i
99 #      done
100 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
101 #      return res
102 #
103 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
104 #
105
106 # register types:
107 #   0 - no special type
108 #   1 - caller save (register must be saved by the caller of a function)
109 #   2 - callee save (register must be saved by the called function)
110 #   4 - ignore (do not assign this register)
111 #   8 - emitter can choose an arbitrary register of this class
112 #  16 - the register is a virtual one
113 #  32 - register represents a state
114 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
115 %reg_classes = (
116         gp => [
117                 { name => "edx", type => 1 },
118                 { name => "ecx", type => 1 },
119                 { name => "eax", type => 1 },
120                 { name => "ebx", type => 2 },
121                 { name => "esi", type => 2 },
122                 { name => "edi", type => 2 },
123                 { name => "ebp", type => 2 },
124                 { name => "esp", type => 4 },
125                 { name => "gp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
126                 { name => "gp_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
127                 { mode => "mode_Iu" }
128         ],
129         mmx => [
130                 { name => "mm0", type => 4 },
131                 { name => "mm1", type => 4 },
132                 { name => "mm2", type => 4 },
133                 { name => "mm3", type => 4 },
134                 { name => "mm4", type => 4 },
135                 { name => "mm5", type => 4 },
136                 { name => "mm6", type => 4 },
137                 { name => "mm7", type => 4 },
138                 { mode => "mode_E", flags => "manual_ra" }
139         ],
140         xmm => [
141                 { name => "xmm0", type => 1 },
142                 { name => "xmm1", type => 1 },
143                 { name => "xmm2", type => 1 },
144                 { name => "xmm3", type => 1 },
145                 { name => "xmm4", type => 1 },
146                 { name => "xmm5", type => 1 },
147                 { name => "xmm6", type => 1 },
148                 { name => "xmm7", type => 1 },
149                 { name => "xmm_NOREG", type => 4 | 16 },     # we need a dummy register for NoReg nodes
150                 { name => "xmm_UKNWN", type => 4 | 8 | 16},  # we need a dummy register for Unknown nodes
151                 { mode => "mode_E" }
152         ],
153         vfp => [
154                 { name => "vf0", type => 1 | 16 },
155                 { name => "vf1", type => 1 | 16 },
156                 { name => "vf2", type => 1 | 16 },
157                 { name => "vf3", type => 1 | 16 },
158                 { name => "vf4", type => 1 | 16 },
159                 { name => "vf5", type => 1 | 16 },
160                 { name => "vf6", type => 1 | 16 },
161                 { name => "vf7", type => 1 | 16 },
162                 { name => "vfp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
163                 { name => "vfp_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
164                 { mode => "mode_E" }
165         ],
166         st => [
167                 { name => "st0", realname => "st",    type => 4 },
168                 { name => "st1", realname => "st(1)", type => 4 },
169                 { name => "st2", realname => "st(2)", type => 4 },
170                 { name => "st3", realname => "st(3)", type => 4 },
171                 { name => "st4", realname => "st(4)", type => 4 },
172                 { name => "st5", realname => "st(5)", type => 4 },
173                 { name => "st6", realname => "st(6)", type => 4 },
174                 { name => "st7", realname => "st(7)", type => 4 },
175                 { mode => "mode_E", flags => "manual_ra" }
176         ],
177         fp_cw => [      # the floating point control word
178                 { name => "fpcw", type => 4|32 },
179                 { mode => "mode_fpcw", flags => "manual_ra|state" }
180         ],
181         flags => [
182                 { name => "eflags", type => 0 },
183                 { mode => "mode_Iu", flags => "manual_ra" }
184         ],
185 ); # %reg_classes
186
187 %cpu = (
188         GP     => [ 1, "GP_EAX", "GP_EBX", "GP_ECX", "GP_EDX", "GP_ESI", "GP_EDI", "GP_EBP" ],
189         SSE    => [ 1, "SSE_XMM0", "SSE_XMM1", "SSE_XMM2", "SSE_XMM3", "SSE_XMM4", "SSE_XMM5", "SSE_XMM6", "SSE_XMM7" ],
190         VFP    => [ 1, "VFP_VF0", "VFP_VF1", "VFP_VF2", "VFP_VF3", "VFP_VF4", "VFP_VF5", "VFP_VF6", "VFP_VF7" ],
191         BRANCH => [ 1, "BRANCH1", "BRANCH2" ],
192 ); # %cpu
193
194 %vliw = (
195         bundle_size       => 1,
196         bundels_per_cycle => 1
197 ); # vliw
198
199 %emit_templates = (
200         S0 => "${arch}_emit_source_register(node, 0);",
201         S1 => "${arch}_emit_source_register(node, 1);",
202         S2 => "${arch}_emit_source_register(node, 2);",
203         S3 => "${arch}_emit_source_register(node, 3);",
204         SB1 => "${arch}_emit_8bit_source_register_or_immediate(node, 1);",
205         SB2 => "${arch}_emit_8bit_source_register_or_immediate(node, 2);",
206         SB3 => "${arch}_emit_8bit_source_register_or_immediate(node, 3);",
207         SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
208         SI3 => "${arch}_emit_source_register_or_immediate(node, 3);",
209         D0 => "${arch}_emit_dest_register(node, 0);",
210         D1 => "${arch}_emit_dest_register(node, 1);",
211         DB0 => "${arch}_emit_8bit_dest_register(node, 0);",
212         X0 => "${arch}_emit_x87_register(node, 0);",
213         X1 => "${arch}_emit_x87_register(node, 1);",
214         SE => "${arch}_emit_extend_suffix(get_ia32_ls_mode(node));",
215         ME => "if(get_mode_size_bits(get_ia32_ls_mode(node)) != 32)\n
216                    ia32_emit_mode_suffix(node);",
217         M  => "${arch}_emit_mode_suffix(node);",
218         XM => "${arch}_emit_x87_mode_suffix(node);",
219         XXM => "${arch}_emit_xmm_mode_suffix(node);",
220         XSD => "${arch}_emit_xmm_mode_suffix_s(node);",
221         AM => "${arch}_emit_am(node);",
222         unop3 => "${arch}_emit_unop(node, n_ia32_unary_op);",
223         unop4 => "${arch}_emit_unop(node, n_ia32_binary_right);",
224         binop => "${arch}_emit_binop(node);",
225         x87_binop => "${arch}_emit_x87_binop(node);",
226         CMP0  => "${arch}_emit_cmp_suffix_node(node, 0);",
227         CMP3  => "${arch}_emit_cmp_suffix_node(node, 3);",
228 );
229
230 #--------------------------------------------------#
231 #                        _                         #
232 #                       (_)                        #
233 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
234 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
235 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
236 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
237 #                                      | |         #
238 #                                      |_|         #
239 #--------------------------------------------------#
240
241 $default_op_attr_type = "ia32_op_attr_t";
242 $default_attr_type    = "ia32_attr_t";
243 $default_copy_attr    = "ia32_copy_attr";
244
245 sub ia32_custom_init_attr {
246         my $node = shift;
247         my $name = shift;
248         my $res = "";
249
250         if(defined($node->{modified_flags})) {
251                 $res .= "\tset_ia32_flags(res, get_ia32_flags(res) | arch_irn_flags_modify_flags);\n";
252         }
253         if(defined($node->{am})) {
254                 my $am = $node->{am};
255                 if($am eq "source,unary") {
256                         $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_unary);";
257                 } elsif($am eq "source,binary") {
258                         $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_binary);";
259                 } elsif($am eq "source,ternary") {
260                         $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_ternary);";
261                 } elsif($am eq "none") {
262                         # nothing to do
263                 } else {
264                         die("Invalid address mode '$am' specified on op $name");
265                 }
266                 if($am ne "none") {
267                         if($node->{state} ne "exc_pinned"
268                                         and $node->{state} ne "pinned") {
269                                 die("AM nodes must have pinned or AM pinned state ($name)");
270                         }
271                 }
272         }
273         return $res;
274 }
275 $custom_init_attr_func = \&ia32_custom_init_attr;
276
277 %init_attr = (
278         ia32_asm_attr_t =>
279                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
280                 "\tinit_ia32_x87_attributes(res);".
281                 "\tinit_ia32_asm_attributes(res);",
282         ia32_attr_t     =>
283                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
284         ia32_condcode_attr_t =>
285                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
286                 "\tinit_ia32_condcode_attributes(res, pnc);",
287         ia32_copyb_attr_t =>
288                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
289                 "\tinit_ia32_copyb_attributes(res, size);",
290         ia32_immediate_attr_t =>
291                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
292                 "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, offset);",
293         ia32_x87_attr_t =>
294                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
295                 "\tinit_ia32_x87_attributes(res);",
296 );
297
298 %compare_attr = (
299         ia32_asm_attr_t       => "ia32_compare_asm_attr",
300         ia32_attr_t           => "ia32_compare_nodes_attr",
301         ia32_condcode_attr_t  => "ia32_compare_condcode_attr",
302         ia32_copyb_attr_t     => "ia32_compare_copyb_attr",
303         ia32_immediate_attr_t => "ia32_compare_immediate_attr",
304         ia32_x87_attr_t       => "ia32_compare_x87_attr",
305 );
306
307 %operands = (
308 );
309
310 $mode_xmm     = "mode_E";
311 $mode_gp      = "mode_Iu";
312 $mode_flags   = "mode_Iu";
313 $mode_fpcw    = "mode_fpcw";
314 $status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ];
315 $fpcw_flags   = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
316                   "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ];
317
318 %nodes = (
319
320 Immediate => {
321         state     => "pinned",
322         op_flags  => "c",
323         irn_flags => "I",
324         reg_req   => { out => [ "gp_NOREG" ] },
325         attr      => "ir_entity *symconst, int symconst_sign, long offset",
326         attr_type => "ia32_immediate_attr_t",
327         hash_func => "ia32_hash_Immediate",
328         latency   => 0,
329         mode      => $mode_gp,
330 },
331
332 Asm => {
333         mode      => "mode_T",
334         arity     => "variable",
335         out_arity => "variable",
336         attr_type => "ia32_asm_attr_t",
337         attr      => "ident *asm_text, const ia32_asm_reg_t *register_map",
338         init_attr => "attr->asm_text = asm_text;\n".
339                      "\tattr->register_map = register_map;\n",
340         latency   => 10,
341         modified_flags => 1,
342 },
343
344 # "allocates" a free register
345 ProduceVal => {
346         op_flags  => "c",
347         irn_flags => "R",
348         reg_req   => { out => [ "gp" ] },
349         emit      => "",
350         units     => [ ],
351         latency   => 0,
352         mode      => $mode_gp,
353         cmp_attr  => "return 1;",
354 },
355
356 #-----------------------------------------------------------------#
357 #  _       _                                         _            #
358 # (_)     | |                                       | |           #
359 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
360 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
361 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
362 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
363 #                   __/ |                                         #
364 #                  |___/                                          #
365 #-----------------------------------------------------------------#
366
367 # commutative operations
368
369 Add => {
370         irn_flags => "R",
371         state     => "exc_pinned",
372         reg_req   => { in  => [ "gp", "gp", "none", "gp", "gp" ],
373                        out => [ "in_r4 in_r5", "flags", "none" ] },
374         ins       => [ "base", "index", "mem", "left", "right" ],
375         outs      => [ "res", "flags", "M" ],
376         emit      => '. add%M %binop',
377         am        => "source,binary",
378         units     => [ "GP" ],
379         latency   => 1,
380         mode      => $mode_gp,
381         modified_flags => $status_flags
382 },
383
384 AddMem => {
385         irn_flags => "R",
386         state     => "exc_pinned",
387         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
388         ins       => [ "base", "index", "mem", "val" ],
389         emit      => ". add%M %SI3, %AM",
390         units     => [ "GP" ],
391         latency   => 1,
392         mode      => "mode_M",
393         modified_flags => $status_flags
394 },
395
396 AddMem8Bit => {
397         irn_flags => "R",
398         state     => "exc_pinned",
399         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
400         ins       => [ "base", "index", "mem", "val" ],
401         emit      => ". add%M %SB3, %AM",
402         units     => [ "GP" ],
403         latency   => 1,
404         mode      => "mode_M",
405         modified_flags => $status_flags
406 },
407
408 Adc => {
409         state     => "exc_pinned",
410         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
411                        out => [ "in_r4 in_r5", "flags", "none" ] },
412         ins       => [ "base", "index", "mem", "left", "right", "eflags" ],
413         outs      => [ "res", "flags", "M" ],
414         emit      => '. adc%M %binop',
415         am        => "source,binary",
416         units     => [ "GP" ],
417         latency   => 1,
418         mode      => $mode_gp,
419         modified_flags => $status_flags
420 },
421
422 l_Add => {
423         op_flags  => "C",
424         reg_req   => { in => [ "none", "none" ], out => [ "none" ] },
425         ins       => [ "left", "right" ],
426 },
427
428 l_Adc => {
429         reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
430         ins       => [ "left", "right", "eflags" ],
431 },
432
433 Mul => {
434         # we should not rematrialize this node. It produces 2 results and has
435         # very strict constraints
436         state     => "exc_pinned",
437         reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ],
438                        out => [ "eax", "edx", "none" ] },
439         ins       => [ "base", "index", "mem", "left", "right" ],
440         emit      => '. mul%M %unop4',
441         outs      => [ "res_low", "res_high", "M" ],
442         am        => "source,binary",
443         latency   => 10,
444         units     => [ "GP" ],
445         modified_flags => $status_flags
446 },
447
448 l_Mul => {
449         # we should not rematrialize this node. It produces 2 results and has
450         # very strict constraints
451         op_flags  => "C",
452         cmp_attr  => "return 1;",
453         outs      => [ "EAX", "EDX", "M" ],
454         arity     => 2
455 },
456
457 IMul => {
458         irn_flags => "R",
459         state     => "exc_pinned",
460         # TODO: adjust out requirements for the 3 operand form
461         # (no need for should_be_same then)
462         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
463                            out => [ "in_r4 in_r5", "flags", "none" ] },
464         ins       => [ "base", "index", "mem", "left", "right" ],
465         outs      => [ "res", "flags", "M" ],
466         am        => "source,binary",
467         latency   => 5,
468         units     => [ "GP" ],
469         mode      => $mode_gp,
470         modified_flags => $status_flags
471 },
472
473 IMul1OP => {
474         irn_flags => "R",
475         state     => "exc_pinned",
476         reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ],
477                        out => [ "eax", "edx", "none" ] },
478         ins       => [ "base", "index", "mem", "left", "right" ],
479         emit      => '. imul%M %unop4',
480         outs      => [ "res_low", "res_high", "M" ],
481         am        => "source,binary",
482         latency   => 5,
483         units     => [ "GP" ],
484         modified_flags => $status_flags
485 },
486
487 l_IMul => {
488         op_flags  => "C",
489         cmp_attr  => "return 1;",
490         outs      => [ "res_low", "res_high", "M" ],
491         arity     => 2
492 },
493
494 And => {
495         irn_flags => "R",
496         state     => "exc_pinned",
497         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
498                            out => [ "in_r4 in_r5", "flags", "none" ] },
499         ins       => [ "base", "index", "mem", "left", "right" ],
500         outs      => [ "res", "flags", "M" ],
501         op_modes  => "commutative | am | immediate | mode_neutral",
502         am        => "source,binary",
503         emit      => '. and%M %binop',
504         units     => [ "GP" ],
505         latency   => 1,
506         mode      => $mode_gp,
507         modified_flags => $status_flags
508 },
509
510 AndMem => {
511         irn_flags => "R",
512         state     => "exc_pinned",
513         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
514         ins       => [ "base", "index", "mem", "val" ],
515         emit      => '. and%M %SI3, %AM',
516         units     => [ "GP" ],
517         latency   => 1,
518         mode      => "mode_M",
519         modified_flags => $status_flags
520 },
521
522 AndMem8Bit => {
523         irn_flags => "R",
524         state     => "exc_pinned",
525         reg_req   => { in => [ "gp", "gp", "none",  "eax ebx ecx edx" ], out => [ "none" ] },
526         ins       => [ "base", "index", "mem", "val" ],
527         emit      => '. and%M %SB3, %AM',
528         units     => [ "GP" ],
529         latency   => 1,
530         mode      => "mode_M",
531         modified_flags => $status_flags
532 },
533
534 Or => {
535         irn_flags => "R",
536         state     => "exc_pinned",
537         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
538                        out => [ "in_r4 in_r5", "flags", "none" ] },
539         ins       => [ "base", "index", "mem", "left", "right" ],
540         outs      => [ "res", "flags", "M" ],
541         am        => "source,binary",
542         emit      => '. or%M %binop',
543         units     => [ "GP" ],
544         latency   => 1,
545         mode      => $mode_gp,
546         modified_flags => $status_flags
547 },
548
549 OrMem => {
550         irn_flags => "R",
551         state     => "exc_pinned",
552         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
553         ins       => [ "base", "index", "mem", "val" ],
554         emit      => '. or%M %SI3, %AM',
555         units     => [ "GP" ],
556         latency   => 1,
557         mode      => "mode_M",
558         modified_flags => $status_flags
559 },
560
561 OrMem8Bit => {
562         irn_flags => "R",
563         state     => "exc_pinned",
564         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
565         ins       => [ "base", "index", "mem", "val" ],
566         emit      => '. or%M %SB3, %AM',
567         units     => [ "GP" ],
568         latency   => 1,
569         mode      => "mode_M",
570         modified_flags => $status_flags
571 },
572
573 Xor => {
574         irn_flags => "R",
575         state     => "exc_pinned",
576         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
577                        out => [ "in_r4 in_r5", "flags", "none" ] },
578         ins       => [ "base", "index", "mem", "left", "right" ],
579         outs      => [ "res", "flags", "M" ],
580         am        => "source,binary",
581         emit      => '. xor%M %binop',
582         units     => [ "GP" ],
583         latency   => 1,
584         mode      => $mode_gp,
585         modified_flags => $status_flags
586 },
587
588 XorMem => {
589         irn_flags => "R",
590         state     => "exc_pinned",
591         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
592         ins       => [ "base", "index", "mem", "val" ],
593         emit      => '. xor%M %SI3, %AM',
594         units     => [ "GP" ],
595         latency   => 1,
596         mode      => "mode_M",
597         modified_flags => $status_flags
598 },
599
600 XorMem8Bit => {
601         irn_flags => "R",
602         state     => "exc_pinned",
603         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
604         ins       => [ "base", "index", "mem", "val" ],
605         emit      => '. xor%M %SB3, %AM',
606         units     => [ "GP" ],
607         latency   => 1,
608         mode      => "mode_M",
609         modified_flags => $status_flags
610 },
611
612 # not commutative operations
613
614 Sub => {
615         irn_flags => "R",
616         state     => "exc_pinned",
617         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
618                        out => [ "in_r4", "flags", "none" ] },
619         ins       => [ "base", "index", "mem", "minuend", "subtrahend" ],
620         outs      => [ "res", "flags", "M" ],
621         am        => "source,binary",
622         emit      => '. sub%M %binop',
623         units     => [ "GP" ],
624         latency   => 1,
625         mode      => $mode_gp,
626         modified_flags => $status_flags
627 },
628
629 SubMem => {
630         irn_flags => "R",
631         state     => "exc_pinned",
632         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
633         ins       => [ "base", "index", "mem", "subtrahend" ],
634         emit      => '. sub%M %SI3, %AM',
635         units     => [ "GP" ],
636         latency   => 1,
637         mode      => 'mode_M',
638         modified_flags => $status_flags
639 },
640
641 SubMem8Bit => {
642         irn_flags => "R",
643         state     => "exc_pinned",
644         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
645         ins       => [ "base", "index", "mem", "subtrahend" ],
646         emit      => '. sub%M %SB3, %AM',
647         units     => [ "GP" ],
648         latency   => 1,
649         mode      => 'mode_M',
650         modified_flags => $status_flags
651 },
652
653 Sbb => {
654         state     => "exc_pinned",
655         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
656                        out => [ "in_r4 !in_r5", "flags", "none" ] },
657         ins       => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ],
658         outs      => [ "res", "flags", "M" ],
659         am        => "source,binary",
660         emit      => '. sbb%M %binop',
661         units     => [ "GP" ],
662         latency   => 1,
663         mode      => $mode_gp,
664         modified_flags => $status_flags
665 },
666
667 l_Sub => {
668         reg_req   => { in => [ "none", "none" ], out => [ "none" ] },
669         ins       => [ "minuend", "subtrahend" ],
670 },
671
672 l_Sbb => {
673         reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
674         ins       => [ "minuend", "subtrahend", "eflags" ],
675 },
676
677 IDiv => {
678         op_flags  => "F|L",
679         state     => "exc_pinned",
680         reg_req   => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
681                        out => [ "eax", "flags", "none", "edx", "none" ] },
682         ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
683         outs      => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
684         am        => "source,ternary",
685         emit      => ". idiv%M %unop3",
686         latency   => 25,
687         units     => [ "GP" ],
688         modified_flags => $status_flags
689 },
690
691 Div => {
692         op_flags  => "F|L",
693         state     => "exc_pinned",
694         reg_req   => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
695                        out => [ "eax", "flags", "none", "edx", "none" ] },
696         ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
697         outs      => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
698         am        => "source,ternary",
699         emit      => ". div%M %unop3",
700         latency   => 25,
701         units     => [ "GP" ],
702         modified_flags => $status_flags
703 },
704
705 Shl => {
706         irn_flags => "R",
707         reg_req   => { in => [ "gp", "ecx" ],
708                        out => [ "in_r1 !in_r2", "flags" ] },
709         ins       => [ "val", "count" ],
710         outs      => [ "res", "flags" ],
711         emit      => '. shl %SB1, %S0',
712         units     => [ "GP" ],
713         latency   => 1,
714         mode      => $mode_gp,
715         modified_flags => $status_flags
716 },
717
718 ShlMem => {
719         irn_flags => "R",
720         state     => "exc_pinned",
721         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
722         ins       => [ "base", "index", "mem", "count" ],
723         emit      => '. shl%M %SB3, %AM',
724         units     => [ "GP" ],
725         latency   => 1,
726         mode      => "mode_M",
727         modified_flags => $status_flags
728 },
729
730 l_ShlDep => {
731         cmp_attr => "return 1;",
732         ins      => [ "val", "count", "dep" ],
733         arity    => 3
734 },
735
736 ShlD => {
737         irn_flags => "R",
738         reg_req   => { in => [ "gp", "gp", "ecx" ],
739                        out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
740         ins       => [ "val_high", "val_low", "count" ],
741         outs      => [ "res", "flags" ],
742         emit      => ". shld%M %SB2, %S1, %D0",
743         latency   => 6,
744         units     => [ "GP" ],
745         mode      => $mode_gp,
746         modified_flags => $status_flags
747 },
748
749 l_ShlD => {
750         cmp_attr  => "return 1;",
751         ins       => [ "val_high", "val_low", "count" ],
752         arity     => 3,
753 },
754
755 Shr => {
756         irn_flags => "R",
757         reg_req   => { in => [ "gp", "ecx" ],
758                        out => [ "in_r1 !in_r2", "flags" ] },
759         ins       => [ "val", "count" ],
760         outs      => [ "res", "flags" ],
761         emit      => '. shr %SB1, %S0',
762         units     => [ "GP" ],
763         mode      => $mode_gp,
764         latency   => 1,
765         modified_flags => $status_flags
766 },
767
768 ShrMem => {
769         irn_flags => "R",
770         state     => "exc_pinned",
771         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
772         ins       => [ "base", "index", "mem", "count" ],
773         emit      => '. shr%M %SB3, %AM',
774         units     => [ "GP" ],
775         mode      => "mode_M",
776         latency   => 1,
777         modified_flags => $status_flags
778 },
779
780 l_ShrDep => {
781         cmp_attr  => "return 1;",
782         ins       => [ "val", "count", "dep" ],
783         arity     => 3
784 },
785
786 ShrD => {
787         irn_flags => "R",
788         reg_req   => { in => [ "gp", "gp", "ecx" ],
789                        out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
790         ins       => [ "val_high", "val_low", "count" ],
791         outs      => [ "res", "flags" ],
792         emit      => ". shrd%M %SB2, %S1, %D0",
793         latency   => 6,
794         units     => [ "GP" ],
795         mode      => $mode_gp,
796         modified_flags => $status_flags
797 },
798
799 l_ShrD => {
800         cmp_attr  => "return 1;",
801         arity     => 3,
802         ins       => [ "val_high", "val_low", "count" ],
803 },
804
805 Sar => {
806         irn_flags => "R",
807         reg_req   => { in => [ "gp", "ecx" ],
808                        out => [ "in_r1 !in_r2", "flags" ] },
809         ins       => [ "val", "count" ],
810         outs      => [ "res", "flags" ],
811         emit      => '. sar %SB1, %S0',
812         units     => [ "GP" ],
813         latency   => 1,
814         mode      => $mode_gp,
815         modified_flags => $status_flags
816 },
817
818 SarMem => {
819         irn_flags => "R",
820         state     => "exc_pinned",
821         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
822         ins       => [ "base", "index", "mem", "count" ],
823         emit      => '. sar%M %SB3, %AM',
824         units     => [ "GP" ],
825         latency   => 1,
826         mode      => "mode_M",
827         modified_flags => $status_flags
828 },
829
830 l_SarDep => {
831         cmp_attr  => "return 1;",
832         ins       => [ "val", "count", "dep" ],
833         arity     => 3
834 },
835
836 Ror => {
837         irn_flags => "R",
838         reg_req   => { in => [ "gp", "ecx" ],
839                        out => [ "in_r1 !in_r2", "flags" ] },
840         ins       => [ "val", "count" ],
841         outs      => [ "res", "flags" ],
842         emit      => '. ror %SB1, %S0',
843         units     => [ "GP" ],
844         latency   => 1,
845         mode      => $mode_gp,
846         modified_flags => $status_flags
847 },
848
849 RorMem => {
850         irn_flags => "R",
851         state     => "exc_pinned",
852         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
853         ins       => [ "base", "index", "mem", "count" ],
854         emit      => '. ror%M %SB3, %AM',
855         units     => [ "GP" ],
856         latency   => 1,
857         mode      => "mode_M",
858         modified_flags => $status_flags
859 },
860
861 Rol => {
862         irn_flags => "R",
863         reg_req   => { in => [ "gp", "ecx" ],
864                        out => [ "in_r1 !in_r2", "flags" ] },
865         ins       => [ "val", "count" ],
866         outs      => [ "res", "flags" ],
867         emit      => '. rol %SB1, %S0',
868         units     => [ "GP" ],
869         latency   => 1,
870         mode      => $mode_gp,
871         modified_flags => $status_flags
872 },
873
874 RolMem => {
875         irn_flags => "R",
876         state     => "exc_pinned",
877         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
878         ins       => [ "base", "index", "mem", "count" ],
879         emit      => '. rol%M %SB3, %AM',
880         units     => [ "GP" ],
881         latency   => 1,
882         mode      => "mode_M",
883         modified_flags => $status_flags
884 },
885
886 # unary operations
887
888 Neg => {
889         irn_flags => "R",
890         reg_req   => { in => [ "gp" ],
891                        out => [ "in_r1", "flags" ] },
892         emit      => '. neg %S0',
893         ins       => [ "val" ],
894         outs      => [ "res", "flags" ],
895         units     => [ "GP" ],
896         latency   => 1,
897         mode      => $mode_gp,
898         modified_flags => $status_flags
899 },
900
901 NegMem => {
902         irn_flags => "R",
903         state     => "exc_pinned",
904         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
905         ins       => [ "base", "index", "mem" ],
906         emit      => '. neg%M %AM',
907         units     => [ "GP" ],
908         latency   => 1,
909         mode      => "mode_M",
910         modified_flags => $status_flags
911 },
912
913 Minus64Bit => {
914         irn_flags => "R",
915         reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1", "gp" ] },
916         outs      => [ "low_res", "high_res" ],
917         units     => [ "GP" ],
918         latency   => 3,
919         modified_flags => $status_flags
920 },
921
922
923 Inc => {
924         irn_flags => "R",
925         reg_req   => { in => [ "gp" ],
926                        out => [ "in_r1", "flags" ] },
927         ins       => [ "val" ],
928         outs      => [ "res", "flags" ],
929         emit      => '. inc %S0',
930         units     => [ "GP" ],
931         mode      => $mode_gp,
932         latency   => 1,
933         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
934 },
935
936 IncMem => {
937         irn_flags => "R",
938         state     => "exc_pinned",
939         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
940         ins       => [ "base", "index", "mem" ],
941         emit      => '. inc%M %AM',
942         units     => [ "GP" ],
943         mode      => "mode_M",
944         latency   => 1,
945         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
946 },
947
948 Dec => {
949         irn_flags => "R",
950         reg_req   => { in => [ "gp" ],
951                        out => [ "in_r1", "flags" ] },
952         ins       => [ "val" ],
953         outs      => [ "res", "flags" ],
954         emit      => '. dec %S0',
955         units     => [ "GP" ],
956         mode      => $mode_gp,
957         latency   => 1,
958         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
959 },
960
961 DecMem => {
962         irn_flags => "R",
963         state     => "exc_pinned",
964         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
965         ins       => [ "base", "index", "mem" ],
966         emit      => '. dec%M %AM',
967         units     => [ "GP" ],
968         mode      => "mode_M",
969         latency   => 1,
970         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
971 },
972
973 Not => {
974         irn_flags => "R",
975         reg_req   => { in => [ "gp" ],
976                        out => [ "in_r1", "flags" ] },
977         ins       => [ "val" ],
978         outs      => [ "res", "flags" ],
979         emit      => '. not %S0',
980         units     => [ "GP" ],
981         latency   => 1,
982         mode      => $mode_gp,
983         # no flags modified
984 },
985
986 NotMem => {
987         irn_flags => "R",
988         state     => "exc_pinned",
989         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
990         ins       => [ "base", "index", "mem" ],
991         emit      => '. not%M %AM',
992         units     => [ "GP" ],
993         latency   => 1,
994         mode      => "mode_M",
995         # no flags modified
996 },
997
998 Cmc => {
999         reg_req => { in => [ "flags" ], out => [ "flags" ] },
1000         emit    => '.cmc',
1001         units     => [ "GP" ],
1002         latency   => 1,
1003         mode      => $mode_flags,
1004         modified_flags => $status_flags
1005 },
1006
1007 Stc => {
1008         reg_req => { out => [ "flags" ] },
1009         emit    => '.stc',
1010         units     => [ "GP" ],
1011         latency   => 1,
1012         mode      => $mode_flags,
1013         modified_flags => $status_flags
1014 },
1015
1016 # other operations
1017
1018 Cmp => {
1019         irn_flags => "R",
1020         state     => "exc_pinned",
1021         reg_req   => { in  => [ "gp", "gp", "none", "gp", "gp" ],
1022                        out => [ "flags", "none", "none" ] },
1023         ins       => [ "base", "index", "mem", "left", "right" ],
1024         outs      => [ "eflags", "unused", "M" ],
1025         am        => "source,binary",
1026         emit      => '. cmp%M %binop',
1027         attr      => "int ins_permuted, int cmp_unsigned",
1028         init_attr => "attr->data.ins_permuted   = ins_permuted;\n".
1029                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1030         latency   => 1,
1031         units     => [ "GP" ],
1032         mode      => $mode_flags,
1033         modified_flags => $status_flags
1034 },
1035
1036 Cmp8Bit => {
1037         irn_flags => "R",
1038         state     => "exc_pinned",
1039         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] },
1040         ins       => [ "base", "index", "mem", "left", "right" ],
1041         outs      => [ "eflags" ],
1042         am        => "source,binary",
1043         emit      => '. cmpb %binop',
1044         attr      => "int ins_permuted, int cmp_unsigned",
1045         init_attr => "attr->data.ins_permuted   = ins_permuted;\n".
1046                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1047         latency   => 1,
1048         units     => [ "GP" ],
1049         mode      => $mode_flags,
1050         modified_flags => $status_flags
1051 },
1052
1053 Test => {
1054         irn_flags => "R",
1055         state     => "exc_pinned",
1056         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] },
1057         ins       => [ "base", "index", "mem", "left", "right" ],
1058         outs      => [ "eflags" ],
1059         am        => "source,binary",
1060         emit      => '. test%M %binop',
1061         attr      => "int ins_permuted, int cmp_unsigned",
1062         init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1063                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1064         latency   => 1,
1065         units     => [ "GP" ],
1066         mode      => $mode_flags,
1067         modified_flags => $status_flags
1068 },
1069
1070 Test8Bit => {
1071         irn_flags => "R",
1072         state     => "exc_pinned",
1073         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] },
1074         ins       => [ "base", "index", "mem", "left", "right" ],
1075         outs      => [ "eflags" ],
1076         am        => "source,binary",
1077         emit      => '. testb %binop',
1078         attr      => "int ins_permuted, int cmp_unsigned",
1079         init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1080                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1081         latency   => 1,
1082         units     => [ "GP" ],
1083         mode      => $mode_flags,
1084         modified_flags => $status_flags
1085 },
1086
1087 Set => {
1088         #irn_flags => "R",
1089         reg_req   => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] },
1090         ins       => [ "eflags" ],
1091         attr_type => "ia32_condcode_attr_t",
1092         attr      => "pn_Cmp pnc, int ins_permuted",
1093         init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
1094                       "\tset_ia32_ls_mode(res, mode_Bu);\n",
1095         emit      => '. set%CMP0 %DB0',
1096         latency   => 1,
1097         units     => [ "GP" ],
1098         mode      => $mode_gp,
1099 },
1100
1101 SetMem => {
1102         #irn_flags => "R",
1103         state     => "exc_pinned",
1104         reg_req   => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] },
1105         ins       => [ "base", "index", "mem","eflags" ],
1106         attr_type => "ia32_condcode_attr_t",
1107         attr      => "pn_Cmp pnc, int ins_permuted",
1108         init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
1109                       "\tset_ia32_ls_mode(res, mode_Bu);\n",
1110         emit      => '. set%CMP3 %AM',
1111         latency   => 1,
1112         units     => [ "GP" ],
1113         mode      => 'mode_M',
1114 },
1115
1116 CMov => {
1117         #irn_flags => "R",
1118         # (note: leave the false,true order intact to make it compatible with other
1119         #  ia32_binary ops)
1120         state     => "exc_pinned",
1121         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "eflags" ], out => [ "in_r4 in_r5" ] },
1122         ins       => [ "base", "index", "mem", "val_false", "val_true", "eflags" ],
1123         am        => "source,binary",
1124         attr_type => "ia32_condcode_attr_t",
1125         attr      => "int ins_permuted, pn_Cmp pnc",
1126         init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
1127         latency   => 1,
1128         units     => [ "GP" ],
1129         mode      => $mode_gp,
1130 },
1131
1132 Jcc => {
1133         state     => "pinned",
1134         op_flags  => "L|X|Y",
1135         reg_req   => { in  => [ "eflags" ], out => [ "none", "none" ] },
1136         ins       => [ "eflags" ],
1137         outs      => [ "false", "true" ],
1138         attr_type => "ia32_condcode_attr_t",
1139         attr      => "pn_Cmp pnc",
1140         latency   => 2,
1141         units     => [ "BRANCH" ],
1142 },
1143
1144 SwitchJmp => {
1145         state     => "pinned",
1146         op_flags  => "L|X|Y",
1147         reg_req   => { in => [ "gp" ], out => [ "none" ] },
1148         mode      => "mode_T",
1149         attr_type => "ia32_condcode_attr_t",
1150         attr      => "long pnc",
1151         latency   => 3,
1152         units     => [ "BRANCH" ],
1153         modified_flags => $status_flags,
1154 },
1155
1156 IJmp => {
1157         state     => "pinned",
1158         op_flags  => "X",
1159         reg_req   => { in => [ "gp", "gp", "none", "gp" ] },
1160         ins       => [ "base", "index", "mem", "target" ],
1161         am        => "source,unary",
1162         emit      => '. jmp *%unop3',
1163         latency   => 1,
1164         units     => [ "BRANCH" ],
1165         mode      => "mode_X",
1166 },
1167
1168 Const => {
1169         op_flags  => "c",
1170         irn_flags => "R",
1171         reg_req   => { out => [ "gp" ] },
1172         units     => [ "GP" ],
1173         attr      => "ir_entity *symconst, int symconst_sign, long offset",
1174         attr_type => "ia32_immediate_attr_t",
1175         latency   => 1,
1176         mode      => $mode_gp,
1177 },
1178
1179 GetEIP => {
1180         op_flags => "c",
1181         reg_req  => { out => [ "gp" ] },
1182         units    => [ "GP" ],
1183         latency  => 5,
1184         mode     => $mode_gp,
1185         modified_flags => $status_flags,
1186 },
1187
1188 Unknown_GP => {
1189         state     => "pinned",
1190         op_flags  => "c|NB",
1191         irn_flags => "I",
1192         reg_req   => { out => [ "gp_UKNWN" ] },
1193         units     => [],
1194         emit      => "",
1195         latency   => 0,
1196         mode      => $mode_gp
1197 },
1198
1199 Unknown_VFP => {
1200         state     => "pinned",
1201         op_flags  => "c|NB",
1202         irn_flags => "I",
1203         reg_req   => { out => [ "vfp_UKNWN" ] },
1204         units     => [],
1205         emit      => "",
1206         mode      => "mode_E",
1207         latency   => 0,
1208         attr_type => "ia32_x87_attr_t",
1209 },
1210
1211 Unknown_XMM => {
1212         state     => "pinned",
1213         op_flags  => "c|NB",
1214         irn_flags => "I",
1215         reg_req   => { out => [ "xmm_UKNWN" ] },
1216         units     => [],
1217         emit      => "",
1218         latency   => 0,
1219         mode      => $mode_xmm
1220 },
1221
1222 NoReg_GP => {
1223         state     => "pinned",
1224         op_flags  => "c|NB|NI",
1225         irn_flags => "I",
1226         reg_req   => { out => [ "gp_NOREG" ] },
1227         units     => [],
1228         emit      => "",
1229         latency   => 0,
1230         mode      => $mode_gp
1231 },
1232
1233 NoReg_VFP => {
1234         state     => "pinned",
1235         op_flags  => "c|NB|NI",
1236         irn_flags => "I",
1237         reg_req   => { out => [ "vfp_NOREG" ] },
1238         units     => [],
1239         emit      => "",
1240         mode      => "mode_E",
1241         latency   => 0,
1242         attr_type => "ia32_x87_attr_t",
1243 },
1244
1245 NoReg_XMM => {
1246         state     => "pinned",
1247         op_flags  => "c|NB|NI",
1248         irn_flags => "I",
1249         reg_req   => { out => [ "xmm_NOREG" ] },
1250         units     => [],
1251         emit      => "",
1252         latency   => 0,
1253         mode      => "mode_E"
1254 },
1255
1256 ChangeCW => {
1257         state     => "pinned",
1258         op_flags  => "c",
1259         irn_flags => "I",
1260         reg_req   => { out => [ "fp_cw" ] },
1261         mode      => $mode_fpcw,
1262         latency   => 3,
1263         units     => [ "GP" ],
1264         modified_flags => $fpcw_flags
1265 },
1266
1267 FldCW => {
1268         op_flags  => "L|F",
1269         state     => "pinned",
1270         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] },
1271         ins       => [ "base", "index", "mem" ],
1272         latency   => 5,
1273         emit      => ". fldcw %AM",
1274         mode      => $mode_fpcw,
1275         units     => [ "GP" ],
1276         modified_flags => $fpcw_flags
1277 },
1278
1279 FnstCW => {
1280         op_flags  => "L|F",
1281         state     => "pinned",
1282         reg_req   => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
1283         ins       => [ "base", "index", "mem", "fpcw" ],
1284         latency   => 5,
1285         emit      => ". fnstcw %AM",
1286         mode      => "mode_M",
1287         units     => [ "GP" ],
1288 },
1289
1290 FnstCWNOP => {
1291         op_flags  => "L|F",
1292         state     => "pinned",
1293         reg_req   => { in => [ "fp_cw" ], out => [ "none" ] },
1294         ins       => [ "fpcw" ],
1295         latency   => 0,
1296         emit      => "",
1297         mode      => "mode_M",
1298 },
1299
1300 Cltd => {
1301         # we should not rematrialize this node. It has very strict constraints.
1302         reg_req   => { in => [ "eax", "edx" ], out => [ "edx" ] },
1303         ins       => [ "val", "clobbered" ],
1304         emit      => '. cltd',
1305         latency   => 1,
1306         mode      => $mode_gp,
1307         units     => [ "GP" ],
1308 },
1309
1310 # Load / Store
1311 #
1312 # Note that we add additional latency values depending on address mode, so a
1313 # lateny of 0 for load is correct
1314
1315 Load => {
1316         op_flags  => "L|F",
1317         state     => "exc_pinned",
1318         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "gp", "none", "none" ] },
1319         ins       => [ "base", "index", "mem" ],
1320         outs      => [ "res", "M", "X_exc" ],
1321         latency   => 0,
1322         emit      => ". mov%SE%ME%.l %AM, %D0",
1323         units     => [ "GP" ],
1324 },
1325
1326 l_Load => {
1327         op_flags  => "L|F",
1328         cmp_attr  => "return 1;",
1329         outs      => [ "res", "M" ],
1330         arity     => 2,
1331 },
1332
1333 l_Store => {
1334         op_flags  => "L|F",
1335         cmp_attr  => "return 1;",
1336         state     => "exc_pinned",
1337         arity     => 3,
1338         mode      => "mode_M",
1339 },
1340
1341 Store => {
1342         op_flags  => "L|F",
1343         state     => "exc_pinned",
1344         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none", "none" ] },
1345         ins       => [ "base", "index", "mem", "val" ],
1346         outs      => [ "M", "X_exc" ],
1347         emit      => '. mov%M %SI3, %AM',
1348         latency   => 2,
1349         units     => [ "GP" ],
1350         mode      => "mode_M",
1351 },
1352
1353 Store8Bit => {
1354         op_flags  => "L|F",
1355         state     => "exc_pinned",
1356         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none", "none" ] },
1357         ins       => [ "base", "index", "mem", "val" ],
1358         outs      => [ "M", "X_exc" ],
1359         emit      => '. mov%M %SB3, %AM',
1360         latency   => 2,
1361         units     => [ "GP" ],
1362         mode      => "mode_M",
1363 },
1364
1365 Lea => {
1366         irn_flags => "R",
1367         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
1368         ins       => [ "base", "index" ],
1369         emit      => '. leal %AM, %D0',
1370         latency   => 2,
1371         units     => [ "GP" ],
1372         mode      => $mode_gp,
1373 # lea doesn't modify the flags, but setting this seems advantageous since it
1374 # increases chances that the Lea is transformed back to an Add
1375         modified_flags => 1,
1376 },
1377
1378 Push => {
1379         state     => "exc_pinned",
1380         reg_req   => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp", "none" ] },
1381         ins       => [ "base", "index", "mem", "val", "stack" ],
1382         emit      => '. push%M %unop3',
1383         outs      => [ "stack:I|S", "M" ],
1384         am        => "source,unary",
1385         latency   => 2,
1386         units     => [ "GP" ],
1387 },
1388
1389 Pop => {
1390         state     => "exc_pinned",
1391         reg_req   => { in => [ "none", "esp" ], out => [ "gp", "none", "none", "esp" ] },
1392         ins       => [ "mem", "stack" ],
1393         outs      => [ "res", "M", "unused", "stack:I|S" ],
1394         emit      => '. pop%M %D0',
1395         latency   => 3, # Pop is more expensive than Push on Athlon
1396         units     => [ "GP" ],
1397 },
1398
1399 PopMem => {
1400         state     => "exc_pinned",
1401         reg_req   => { in => [ "gp", "gp", "none", "esp" ], out => [ "none", "none", "none", "esp" ] },
1402         ins       => [ "base", "index", "mem", "stack" ],
1403         outs      => [ "unused0", "M", "unused1", "stack:I|S" ],
1404         emit      => '. pop%M %AM',
1405         latency   => 3, # Pop is more expensive than Push on Athlon
1406         units     => [ "GP" ],
1407 },
1408
1409 Enter => {
1410         reg_req   => { in => [ "esp" ], out => [ "ebp", "esp", "none" ] },
1411         emit      => '. enter',
1412         outs      => [ "frame:I", "stack:I|S", "M" ],
1413         latency   => 15,
1414         units     => [ "GP" ],
1415 },
1416
1417 Leave => {
1418         reg_req   => { in => [ "esp", "ebp" ], out => [ "ebp", "esp" ] },
1419         emit      => '. leave',
1420         outs      => [ "frame:I", "stack:I|S" ],
1421         latency   => 3,
1422         units     => [ "GP" ],
1423 },
1424
1425 AddSP => {
1426         irn_flags => "I",
1427         state     => "pinned",
1428         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "none" ] },
1429         ins       => [ "base", "index", "mem", "stack", "size" ],
1430         am        => "source,binary",
1431         emit      => '. addl %binop',
1432         latency   => 1,
1433         outs      => [ "stack:I|S", "M" ],
1434         units     => [ "GP" ],
1435         modified_flags => $status_flags
1436 },
1437
1438 SubSP => {
1439 #irn_flags => "I",
1440         state     => "pinned",
1441         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "gp", "none" ] },
1442         ins       => [ "base", "index", "mem", "stack", "size" ],
1443         am        => "source,binary",
1444         emit      => ". subl %binop\n".
1445                      ". movl %%esp, %D1",
1446         latency   => 2,
1447         outs      => [ "stack:I|S", "addr", "M" ],
1448         units     => [ "GP" ],
1449         modified_flags => $status_flags
1450 },
1451
1452 RepPrefix => {
1453         op_flags  => "K",
1454         state     => "pinned",
1455         mode      => "mode_M",
1456         emit      => ". rep",
1457         latency   => 0,
1458 },
1459
1460 LdTls => {
1461         irn_flags => "R",
1462         reg_req   => { out => [ "gp" ] },
1463         units     => [ "GP" ],
1464         latency   => 1,
1465 },
1466
1467 Bt => {
1468         irn_flags => "R",
1469         state     => "exc_pinned",
1470         reg_req   => { in => [ "gp", "gp" ], out => [ "flags" ] },
1471         ins       => [ "left", "right" ],
1472         emit      => '. bt%M %S1, %S0',
1473         units     => [ "GP" ],
1474         latency   => 1,
1475         mode      => $mode_flags,
1476         modified_flags => $status_flags  # only CF is set, but the other flags are undefined
1477 },
1478
1479 #-----------------------------------------------------------------------------#
1480 #   _____ _____ ______    __ _             _                     _            #
1481 #  / ____/ ____|  ____|  / _| |           | |                   | |           #
1482 # | (___| (___ | |__    | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1483 #  \___ \\___ \|  __|   |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1484 #  ____) |___) | |____  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1485 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1486 #-----------------------------------------------------------------------------#
1487
1488 # produces a 0/+0.0
1489 xZero => {
1490         irn_flags => "R",
1491         reg_req   => { out => [ "xmm" ] },
1492         emit      => '. xorp%XSD %D0, %D0',
1493         latency   => 3,
1494         units     => [ "SSE" ],
1495         mode      => $mode_xmm
1496 },
1497
1498 xPzero => {
1499         irn_flags => "R",
1500         reg_req   => { out => [ "xmm" ] },
1501         emit      => '. pxor %D0, %D0',
1502         latency   => 3,
1503         units     => [ "SSE" ],
1504         mode      => $mode_xmm
1505 },
1506
1507 # produces all 1 bits
1508 xAllOnes => {
1509         irn_flags => "R",
1510         reg_req   => { out => [ "xmm" ] },
1511         emit      => '. pcmpeqb %D0, %D0',
1512         latency   => 3,
1513         units     => [ "SSE" ],
1514         mode      => $mode_xmm
1515 },
1516
1517 # integer shift left, dword
1518 xPslld => {
1519         irn_flags => "R",
1520         reg_req   => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1521         emit      => '. pslld %SI1, %D0',
1522         latency   => 3,
1523         units     => [ "SSE" ],
1524         mode      => $mode_xmm
1525 },
1526
1527 # integer shift left, qword
1528 xPsllq => {
1529         irn_flags => "R",
1530         reg_req   => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1531         emit      => '. psllq %SI1, %D0',
1532         latency   => 3,
1533         units     => [ "SSE" ],
1534         mode      => $mode_xmm
1535 },
1536
1537 # integer shift right, dword
1538 xPsrld => {
1539         irn_flags => "R",
1540         reg_req   => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1541         emit      => '. psrld %SI1, %D0',
1542         latency   => 1,
1543         units     => [ "SSE" ],
1544         mode      => $mode_xmm
1545 },
1546
1547 # mov from integer to SSE register
1548 xMovd  => {
1549         irn_flags => "R",
1550         reg_req   => { in => [ "gp" ], out => [ "xmm" ] },
1551         emit      => '. movd %S0, %D0',
1552         latency   => 1,
1553         units     => [ "SSE" ],
1554         mode      => $mode_xmm
1555 },
1556
1557 # commutative operations
1558
1559 xAdd => {
1560         irn_flags => "R",
1561         state     => "exc_pinned",
1562         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1563         ins       => [ "base", "index", "mem", "left", "right" ],
1564         am        => "source,binary",
1565         emit      => '. add%XXM %binop',
1566         latency   => 4,
1567         units     => [ "SSE" ],
1568         mode      => $mode_xmm
1569 },
1570
1571 xMul => {
1572         irn_flags => "R",
1573         state     => "exc_pinned",
1574         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1575         ins       => [ "base", "index", "mem", "left", "right" ],
1576         am        => "source,binary",
1577         emit      => '. mul%XXM %binop',
1578         latency   => 4,
1579         units     => [ "SSE" ],
1580         mode      => $mode_xmm
1581 },
1582
1583 xMax => {
1584         irn_flags => "R",
1585         state     => "exc_pinned",
1586         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1587         ins       => [ "base", "index", "mem", "left", "right" ],
1588         am        => "source,binary",
1589         emit      => '. max%XXM %binop',
1590         latency   => 2,
1591         units     => [ "SSE" ],
1592         mode      => $mode_xmm
1593 },
1594
1595 xMin => {
1596         irn_flags => "R",
1597         state     => "exc_pinned",
1598         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1599         ins       => [ "base", "index", "mem", "left", "right" ],
1600         am        => "source,binary",
1601         emit      => '. min%XXM %binop',
1602         latency   => 2,
1603         units     => [ "SSE" ],
1604         mode      => $mode_xmm
1605 },
1606
1607 xAnd => {
1608         irn_flags => "R",
1609         state     => "exc_pinned",
1610         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1611         ins       => [ "base", "index", "mem", "left", "right" ],
1612         am        => "source,binary",
1613         emit      => '. andp%XSD %binop',
1614         latency   => 3,
1615         units     => [ "SSE" ],
1616         mode      => $mode_xmm
1617 },
1618
1619 xOr => {
1620         irn_flags => "R",
1621         state     => "exc_pinned",
1622         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1623         ins       => [ "base", "index", "mem", "left", "right" ],
1624         am        => "source,binary",
1625         emit      => '. orp%XSD %binop',
1626         latency   => 3,
1627         units     => [ "SSE" ],
1628         mode      => $mode_xmm
1629 },
1630
1631 xXor => {
1632         irn_flags => "R",
1633         state     => "exc_pinned",
1634         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1635         ins       => [ "base", "index", "mem", "left", "right" ],
1636         am        => "source,binary",
1637         emit      => '. xorp%XSD %binop',
1638         latency   => 3,
1639         units     => [ "SSE" ],
1640         mode      => $mode_xmm
1641 },
1642
1643 # not commutative operations
1644
1645 xAndNot => {
1646         irn_flags => "R",
1647         state     => "exc_pinned",
1648         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] },
1649         ins       => [ "base", "index", "mem", "left", "right" ],
1650         am        => "source,binary",
1651         emit      => '. andnp%XSD %binop',
1652         latency   => 3,
1653         units     => [ "SSE" ],
1654         mode      => $mode_xmm
1655 },
1656
1657 xSub => {
1658         irn_flags => "R",
1659         state     => "exc_pinned",
1660         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1661         ins       => [ "base", "index", "mem", "minuend", "subtrahend" ],
1662         am        => "source,binary",
1663         emit      => '. sub%XXM %binop',
1664         latency   => 4,
1665         units     => [ "SSE" ],
1666         mode      => $mode_xmm
1667 },
1668
1669 xDiv => {
1670         irn_flags => "R",
1671         state     => "exc_pinned",
1672         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5", "none" ] },
1673         ins       => [ "base", "index", "mem", "dividend", "divisor" ],
1674         am        => "source,binary",
1675         outs      => [ "res", "M" ],
1676         emit      => '. div%XXM %binop',
1677         latency   => 16,
1678         units     => [ "SSE" ],
1679 },
1680
1681 # other operations
1682
1683 Ucomi => {
1684         irn_flags => "R",
1685         state     => "exc_pinned",
1686         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "eflags" ] },
1687         ins       => [ "base", "index", "mem", "left", "right" ],
1688         outs      => [ "flags" ],
1689         am        => "source,binary",
1690         attr      => "int ins_permuted",
1691         init_attr => "attr->data.ins_permuted = ins_permuted;",
1692         emit      => ' .ucomi%XXM %binop',
1693         latency   => 3,
1694         units     => [ "SSE" ],
1695         mode      => $mode_flags,
1696         modified_flags => 1,
1697 },
1698
1699 # Load / Store
1700
1701 xLoad => {
1702         op_flags  => "L|F",
1703         state     => "exc_pinned",
1704         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none", "none" ] },
1705         ins       => [ "base", "index", "mem" ],
1706         outs      => [ "res", "M", "X_exc" ],
1707         emit      => '. mov%XXM %AM, %D0',
1708         attr      => "ir_mode *load_mode",
1709         init_attr => "attr->ls_mode = load_mode;",
1710         latency   => 0,
1711         units     => [ "SSE" ],
1712 },
1713
1714 xStore => {
1715         op_flags => "L|F",
1716         state    => "exc_pinned",
1717         reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none", "none" ] },
1718         ins       => [ "base", "index", "mem", "val" ],
1719         outs      => [ "M", "X_exc" ],
1720         emit     => '. mov%XXM %S3, %AM',
1721         latency  => 0,
1722         units    => [ "SSE" ],
1723         mode     => "mode_M",
1724 },
1725
1726 xStoreSimple => {
1727         op_flags => "L|F",
1728         state    => "exc_pinned",
1729         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
1730         ins      => [ "base", "index", "mem", "val" ],
1731         emit     => '. mov%XXM %S3, %AM',
1732         latency  => 0,
1733         units    => [ "SSE" ],
1734         mode     => "mode_M",
1735 },
1736
1737 CvtSI2SS => {
1738         op_flags => "L|F",
1739         state     => "exc_pinned",
1740         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1741         ins      => [ "base", "index", "mem", "val" ],
1742         am       => "source,unary",
1743         emit     => '. cvtsi2ss %unop3, %D0',
1744         latency  => 2,
1745         units    => [ "SSE" ],
1746         mode     => $mode_xmm
1747 },
1748
1749 CvtSI2SD => {
1750         op_flags => "L|F",
1751         state     => "exc_pinned",
1752         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1753         ins      => [ "base", "index", "mem", "val" ],
1754         am       => "source,unary",
1755         emit     => '. cvtsi2sd %unop3, %D0',
1756         latency  => 2,
1757         units    => [ "SSE" ],
1758         mode     => $mode_xmm
1759 },
1760
1761
1762 l_LLtoFloat => {
1763         op_flags => "L|F",
1764         cmp_attr => "return 1;",
1765         ins      => [ "val_high", "val_low" ],
1766 },
1767
1768 l_FloattoLL => {
1769         op_flags => "L|F",
1770         cmp_attr => "return 1;",
1771         ins      => [ "val" ],
1772         outs     => [ "res_high", "res_low" ],
1773 },
1774
1775 # CopyB
1776
1777 CopyB => {
1778         op_flags  => "F|H",
1779         state     => "pinned",
1780         reg_req   => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
1781         outs      => [ "DST", "SRC", "CNT", "M" ],
1782         attr_type => "ia32_copyb_attr_t",
1783         attr      => "unsigned size",
1784         units     => [ "GP" ],
1785         latency  => 3,
1786 # we don't care about this flag, so no need to mark this node
1787 #       modified_flags => [ "DF" ]
1788 },
1789
1790 CopyB_i => {
1791         op_flags  => "F|H",
1792         state     => "pinned",
1793         reg_req   => { in => [ "edi", "esi", "none" ], out => [  "edi", "esi", "none" ] },
1794         outs      => [ "DST", "SRC", "M" ],
1795         attr_type => "ia32_copyb_attr_t",
1796         attr      => "unsigned size",
1797         units     => [ "GP" ],
1798         latency  => 3,
1799 # we don't care about this flag, so no need to mark this node
1800 #       modified_flags => [ "DF" ]
1801 },
1802
1803 # Conversions
1804
1805 Conv_I2I => {
1806         state     => "exc_pinned",
1807         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "gp", "none" ] },
1808         ins       => [ "base", "index", "mem", "val" ],
1809         am        => "source,unary",
1810         units     => [ "GP" ],
1811         latency   => 1,
1812         attr      => "ir_mode *smaller_mode",
1813         init_attr => "attr->ls_mode = smaller_mode;",
1814         mode      => $mode_gp,
1815 },
1816
1817 Conv_I2I8Bit => {
1818         state     => "exc_pinned",
1819         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "gp", "none" ] },
1820         ins       => [ "base", "index", "mem", "val" ],
1821         am        => "source,unary",
1822         units     => [ "GP" ],
1823         latency   => 1,
1824         attr      => "ir_mode *smaller_mode",
1825         init_attr => "attr->ls_mode = smaller_mode;",
1826         mode      => $mode_gp,
1827 },
1828
1829 Conv_I2FP => {
1830         state     => "exc_pinned",
1831         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
1832         ins       => [ "base", "index", "mem", "val" ],
1833         am        => "source,unary",
1834         latency   => 10,
1835         units     => [ "SSE" ],
1836         mode      => $mode_xmm,
1837 },
1838
1839 Conv_FP2I => {
1840         state     => "exc_pinned",
1841         reg_req   => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
1842         ins       => [ "base", "index", "mem", "val" ],
1843         am        => "source,unary",
1844         latency   => 10,
1845         units     => [ "SSE" ],
1846         mode      => $mode_gp,
1847 },
1848
1849 Conv_FP2FP => {
1850         state     => "exc_pinned",
1851         reg_req   => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
1852         ins       => [ "base", "index", "mem", "val" ],
1853         am        => "source,unary",
1854         latency   => 8,
1855         units     => [ "SSE" ],
1856         mode      => $mode_xmm,
1857 },
1858
1859 #----------------------------------------------------------#
1860 #        _      _               _    __ _             _    #
1861 #       (_)    | |             | |  / _| |           | |   #
1862 # __   ___ _ __| |_ _   _  __ _| | | |_| | ___   __ _| |_  #
1863 # \ \ / / | '__| __| | | |/ _` | | |  _| |/ _ \ / _` | __| #
1864 #  \ V /| | |  | |_| |_| | (_| | | | | | | (_) | (_| | |_  #
1865 #   \_/ |_|_|   \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
1866 #                 | |                                      #
1867 #  _ __   ___   __| | ___  ___                             #
1868 # | '_ \ / _ \ / _` |/ _ \/ __|                            #
1869 # | | | | (_) | (_| |  __/\__ \                            #
1870 # |_| |_|\___/ \__,_|\___||___/                            #
1871 #----------------------------------------------------------#
1872
1873 # rematerialisation disabled for all float nodes for now, because the fpcw
1874 # handler runs before spilling and we might end up with wrong fpcw then
1875
1876 vfadd => {
1877 #       irn_flags => "R",
1878         state     => "exc_pinned",
1879         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1880         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1881         am        => "source,binary",
1882         latency   => 4,
1883         units     => [ "VFP" ],
1884         mode      => "mode_E",
1885         attr_type => "ia32_x87_attr_t",
1886 },
1887
1888 vfmul => {
1889 #       irn_flags => "R",
1890         state     => "exc_pinned",
1891         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1892         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1893         am        => "source,binary",
1894         latency   => 4,
1895         units     => [ "VFP" ],
1896         mode      => "mode_E",
1897         attr_type => "ia32_x87_attr_t",
1898 },
1899
1900 vfsub => {
1901 #       irn_flags => "R",
1902         state     => "exc_pinned",
1903         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1904         ins       => [ "base", "index", "mem", "minuend", "subtrahend", "fpcw" ],
1905         am        => "source,binary",
1906         latency   => 4,
1907         units     => [ "VFP" ],
1908         mode      => "mode_E",
1909         attr_type => "ia32_x87_attr_t",
1910 },
1911
1912 vfdiv => {
1913         state     => "exc_pinned",
1914         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
1915         ins       => [ "base", "index", "mem", "dividend", "divisor", "fpcw" ],
1916         am        => "source,binary",
1917         outs      => [ "res", "M" ],
1918         latency   => 20,
1919         units     => [ "VFP" ],
1920         attr_type => "ia32_x87_attr_t",
1921 },
1922
1923 vfprem => {
1924         reg_req   => { in => [ "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1925         ins       => [ "left", "right", "fpcw" ],
1926         latency   => 20,
1927         units     => [ "VFP" ],
1928         mode      => "mode_E",
1929         attr_type => "ia32_x87_attr_t",
1930 },
1931
1932 vfabs => {
1933         irn_flags => "R",
1934         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1935         ins       => [ "value" ],
1936         latency   => 2,
1937         units     => [ "VFP" ],
1938         mode      => "mode_E",
1939         attr_type => "ia32_x87_attr_t",
1940 },
1941
1942 vfchs => {
1943         irn_flags => "R",
1944         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1945         ins       => [ "value" ],
1946         latency   => 2,
1947         units     => [ "VFP" ],
1948         mode      => "mode_E",
1949         attr_type => "ia32_x87_attr_t",
1950 },
1951
1952 # virtual Load and Store
1953
1954 vfld => {
1955         irn_flags => "R",
1956         op_flags  => "L|F",
1957         state     => "exc_pinned",
1958         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none", "none" ] },
1959         ins       => [ "base", "index", "mem" ],
1960         outs      => [ "res", "M", "X_exc" ],
1961         attr      => "ir_mode *load_mode",
1962         init_attr => "attr->attr.ls_mode = load_mode;",
1963         latency   => 2,
1964         units     => [ "VFP" ],
1965         attr_type => "ia32_x87_attr_t",
1966 },
1967
1968 vfst => {
1969         irn_flags => "R",
1970         op_flags  => "L|F",
1971         state     => "exc_pinned",
1972         reg_req   => { in => [ "gp", "gp", "none", "vfp" ], out => [ "none", "none" ] },
1973         ins       => [ "base", "index", "mem", "val" ],
1974         outs      => [ "M", "X_exc" ],
1975         attr      => "ir_mode *store_mode",
1976         init_attr => "attr->attr.ls_mode = store_mode;",
1977         latency   => 2,
1978         units     => [ "VFP" ],
1979         mode      => "mode_M",
1980         attr_type => "ia32_x87_attr_t",
1981 },
1982
1983 # Conversions
1984
1985 vfild => {
1986         state     => "exc_pinned",
1987         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1988         outs      => [ "res", "M" ],
1989         ins       => [ "base", "index", "mem" ],
1990         latency   => 4,
1991         units     => [ "VFP" ],
1992         attr_type => "ia32_x87_attr_t",
1993 },
1994
1995 l_vfild => {
1996         cmp_attr  => "return 1;",
1997         outs      => [ "res", "M" ],
1998         arity     => 2,
1999 },
2000
2001 vfist => {
2002         state     => "exc_pinned",
2003         reg_req   => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] },
2004         ins       => [ "base", "index", "mem", "val", "fpcw" ],
2005         latency   => 4,
2006         units     => [ "VFP" ],
2007         mode      => "mode_M",
2008         attr_type => "ia32_x87_attr_t",
2009 },
2010
2011 # SSE3 fisttp instruction
2012 vfisttp => {
2013         state     => "exc_pinned",
2014         reg_req   => { in => [ "gp", "gp", "none", "vfp" ], out => [ "in_r4", "none" ]},
2015         ins       => [ "base", "index", "mem", "val" ],
2016         outs      => [ "res", "M" ],
2017         latency   => 4,
2018         units     => [ "VFP" ],
2019         attr_type => "ia32_x87_attr_t",
2020 },
2021
2022 l_vfist => {
2023         cmp_attr  => "return 1;",
2024         state     => "exc_pinned",
2025         arity     => 3,
2026         mode      => "mode_M",
2027 },
2028
2029
2030 # constants
2031
2032 vfldz => {
2033         irn_flags => "R",
2034         reg_req   => { out => [ "vfp" ] },
2035         latency   => 4,
2036         units     => [ "VFP" ],
2037         mode      => "mode_E",
2038         attr_type => "ia32_x87_attr_t",
2039 },
2040
2041 vfld1 => {
2042         irn_flags => "R",
2043         reg_req   => { out => [ "vfp" ] },
2044         latency   => 4,
2045         units     => [ "VFP" ],
2046         mode      => "mode_E",
2047         attr_type => "ia32_x87_attr_t",
2048 },
2049
2050 vfldpi => {
2051         irn_flags => "R",
2052         reg_req   => { out => [ "vfp" ] },
2053         latency   => 4,
2054         units     => [ "VFP" ],
2055         mode      => "mode_E",
2056         attr_type => "ia32_x87_attr_t",
2057 },
2058
2059 vfldln2 => {
2060         irn_flags => "R",
2061         reg_req   => { out => [ "vfp" ] },
2062         latency   => 4,
2063         units     => [ "VFP" ],
2064         mode      => "mode_E",
2065         attr_type => "ia32_x87_attr_t",
2066 },
2067
2068 vfldlg2 => {
2069         irn_flags => "R",
2070         reg_req   => { out => [ "vfp" ] },
2071         latency   => 4,
2072         units     => [ "VFP" ],
2073         mode      => "mode_E",
2074         attr_type => "ia32_x87_attr_t",
2075 },
2076
2077 vfldl2t => {
2078         irn_flags => "R",
2079         reg_req   => { out => [ "vfp" ] },
2080         latency   => 4,
2081         units     => [ "VFP" ],
2082         mode      => "mode_E",
2083         attr_type => "ia32_x87_attr_t",
2084 },
2085
2086 vfldl2e => {
2087         irn_flags => "R",
2088         reg_req   => { out => [ "vfp" ] },
2089         latency   => 4,
2090         units     => [ "VFP" ],
2091         mode      => "mode_E",
2092         attr_type => "ia32_x87_attr_t",
2093 },
2094
2095 # other
2096
2097 vFucomFnstsw => {
2098 # we can't allow to rematerialize this node so we don't have
2099 #  accidently produce Phi(Fucom, Fucom(ins_permuted))
2100 #       irn_flags => "R",
2101         reg_req   => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
2102         ins       => [ "left", "right" ],
2103         outs      => [ "flags" ],
2104         attr      => "int ins_permuted",
2105         init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2106         latency   => 3,
2107         units     => [ "VFP" ],
2108         attr_type => "ia32_x87_attr_t",
2109         mode      => $mode_gp
2110 },
2111
2112 vFucomi => {
2113         irn_flags => "R",
2114         reg_req   => { in => [ "vfp", "vfp" ], out => [ "eflags" ] },
2115         ins       => [ "left", "right" ],
2116         outs      => [ "flags" ],
2117         attr      => "int ins_permuted",
2118         init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2119         latency   => 3,
2120         units     => [ "VFP" ],
2121         attr_type => "ia32_x87_attr_t",
2122         mode      => $mode_gp
2123 },
2124
2125 vFtstFnstsw => {
2126 #       irn_flags => "R",
2127         reg_req   => { in => [ "vfp" ], out => [ "eax" ] },
2128         ins       => [ "left" ],
2129         outs      => [ "flags" ],
2130         attr      => "int ins_permuted",
2131         init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2132         latency   => 3,
2133         units     => [ "VFP" ],
2134         attr_type => "ia32_x87_attr_t",
2135         mode      => $mode_gp
2136 },
2137
2138 Sahf => {
2139         irn_flags => "R",
2140         reg_req   => { in => [ "eax" ], out => [ "eflags" ] },
2141         ins       => [ "val" ],
2142         outs      => [ "flags" ],
2143         emit      => '. sahf',
2144         latency   => 1,
2145         units     => [ "GP" ],
2146         mode      => $mode_flags,
2147 },
2148
2149 #------------------------------------------------------------------------#
2150 #       ___ _____    __ _             _                     _            #
2151 # __  _( _ )___  |  / _| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
2152 # \ \/ / _ \  / /  | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
2153 #  >  < (_) |/ /   |  _| | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
2154 # /_/\_\___//_/    |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
2155 #------------------------------------------------------------------------#
2156
2157 # Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
2158 #       are swapped, we work this around in the emitter...
2159
2160 fadd => {
2161         state     => "exc_pinned",
2162         rd_constructor => "NONE",
2163         reg_req   => { },
2164         emit      => '. fadd%XM %x87_binop',
2165         latency   => 4,
2166         attr_type => "ia32_x87_attr_t",
2167 },
2168
2169 faddp => {
2170         state     => "exc_pinned",
2171         rd_constructor => "NONE",
2172         reg_req   => { },
2173         emit      => '. faddp%XM %x87_binop',
2174         latency   => 4,
2175         attr_type => "ia32_x87_attr_t",
2176 },
2177
2178 fmul => {
2179         state     => "exc_pinned",
2180         rd_constructor => "NONE",
2181         reg_req   => { },
2182         emit      => '. fmul%XM %x87_binop',
2183         latency   => 4,
2184         attr_type => "ia32_x87_attr_t",
2185 },
2186
2187 fmulp => {
2188         state     => "exc_pinned",
2189         rd_constructor => "NONE",
2190         reg_req   => { },
2191         emit      => '. fmulp%XM %x87_binop',,
2192         latency   => 4,
2193         attr_type => "ia32_x87_attr_t",
2194 },
2195
2196 fsub => {
2197         state     => "exc_pinned",
2198         rd_constructor => "NONE",
2199         reg_req   => { },
2200         emit      => '. fsub%XM %x87_binop',
2201         latency   => 4,
2202         attr_type => "ia32_x87_attr_t",
2203 },
2204
2205 fsubp => {
2206         state     => "exc_pinned",
2207         rd_constructor => "NONE",
2208         reg_req   => { },
2209 # see note about gas bugs
2210         emit      => '. fsubrp%XM %x87_binop',
2211         latency   => 4,
2212         attr_type => "ia32_x87_attr_t",
2213 },
2214
2215 fsubr => {
2216         state     => "exc_pinned",
2217         rd_constructor => "NONE",
2218         irn_flags => "R",
2219         reg_req   => { },
2220         emit      => '. fsubr%XM %x87_binop',
2221         latency   => 4,
2222         attr_type => "ia32_x87_attr_t",
2223 },
2224
2225 fsubrp => {
2226         state     => "exc_pinned",
2227         rd_constructor => "NONE",
2228         irn_flags => "R",
2229         reg_req   => { },
2230 # see note about gas bugs
2231         emit      => '. fsubp%XM %x87_binop',
2232         latency   => 4,
2233         attr_type => "ia32_x87_attr_t",
2234 },
2235
2236 fprem => {
2237         rd_constructor => "NONE",
2238         reg_req   => { },
2239         emit      => '. fprem1',
2240         latency   => 20,
2241         attr_type => "ia32_x87_attr_t",
2242 },
2243
2244 # this node is just here, to keep the simulator running
2245 # we can omit this when a fprem simulation function exists
2246 fpremp => {
2247         rd_constructor => "NONE",
2248         reg_req   => { },
2249         emit      => '. fprem1\n'.
2250                      '. fstp %X0',
2251         latency   => 20,
2252         attr_type => "ia32_x87_attr_t",
2253 },
2254
2255 fdiv => {
2256         state     => "exc_pinned",
2257         rd_constructor => "NONE",
2258         reg_req   => { },
2259         emit      => '. fdiv%XM %x87_binop',
2260         latency   => 20,
2261         attr_type => "ia32_x87_attr_t",
2262 },
2263
2264 fdivp => {
2265         state     => "exc_pinned",
2266         rd_constructor => "NONE",
2267         reg_req   => { },
2268 # see note about gas bugs
2269         emit      => '. fdivrp%XM %x87_binop',
2270         latency   => 20,
2271         attr_type => "ia32_x87_attr_t",
2272 },
2273
2274 fdivr => {
2275         state     => "exc_pinned",
2276         rd_constructor => "NONE",
2277         reg_req   => { },
2278         emit      => '. fdivr%XM %x87_binop',
2279         latency   => 20,
2280         attr_type => "ia32_x87_attr_t",
2281 },
2282
2283 fdivrp => {
2284         state     => "exc_pinned",
2285         rd_constructor => "NONE",
2286         reg_req   => { },
2287 # see note about gas bugs
2288         emit      => '. fdivp%XM %x87_binop',
2289         latency   => 20,
2290         attr_type => "ia32_x87_attr_t",
2291 },
2292
2293 fabs => {
2294         rd_constructor => "NONE",
2295         reg_req   => { },
2296         emit      => '. fabs',
2297         latency   => 4,
2298         attr_type => "ia32_x87_attr_t",
2299 },
2300
2301 fchs => {
2302         op_flags  => "R|K",
2303         rd_constructor => "NONE",
2304         reg_req   => { },
2305         emit      => '. fchs',
2306         latency   => 4,
2307         attr_type => "ia32_x87_attr_t",
2308 },
2309
2310 # x87 Load and Store
2311
2312 fld => {
2313         rd_constructor => "NONE",
2314         op_flags  => "R|L|F",
2315         state     => "exc_pinned",
2316         reg_req   => { },
2317         emit      => '. fld%XM %AM',
2318         attr_type => "ia32_x87_attr_t",
2319         latency   => 2,
2320 },
2321
2322 fst => {
2323         rd_constructor => "NONE",
2324         op_flags  => "R|L|F",
2325         state     => "exc_pinned",
2326         reg_req   => { },
2327         emit      => '. fst%XM %AM',
2328         mode      => "mode_M",
2329         attr_type => "ia32_x87_attr_t",
2330         latency   => 2,
2331 },
2332
2333 fstp => {
2334         rd_constructor => "NONE",
2335         op_flags  => "R|L|F",
2336         state     => "exc_pinned",
2337         reg_req   => { },
2338         emit      => '. fstp%XM %AM',
2339         mode      => "mode_M",
2340         attr_type => "ia32_x87_attr_t",
2341         latency   => 2,
2342 },
2343
2344 # Conversions
2345
2346 fild => {
2347         state     => "exc_pinned",
2348         rd_constructor => "NONE",
2349         reg_req   => { },
2350         emit      => '. fild%M %AM',
2351         attr_type => "ia32_x87_attr_t",
2352         latency   => 2,
2353 },
2354
2355 fist => {
2356         state     => "exc_pinned",
2357         rd_constructor => "NONE",
2358         reg_req   => { },
2359         emit      => '. fist%M %AM',
2360         mode      => "mode_M",
2361         attr_type => "ia32_x87_attr_t",
2362         latency   => 2,
2363 },
2364
2365 fistp => {
2366         state     => "exc_pinned",
2367         rd_constructor => "NONE",
2368         reg_req   => { },
2369         emit      => '. fistp%M %AM',
2370         mode      => "mode_M",
2371         attr_type => "ia32_x87_attr_t",
2372         latency   => 2,
2373 },
2374
2375 # SSE3 firsttp instruction
2376 fisttp => {
2377         state     => "exc_pinned",
2378         rd_constructor => "NONE",
2379         reg_req   => { },
2380         emit      => '. fisttp%M %AM',
2381         mode      => "mode_M",
2382         attr_type => "ia32_x87_attr_t",
2383         latency   => 2,
2384 },
2385
2386 # constants
2387
2388 fldz => {
2389         op_flags  => "R|c|K",
2390         irn_flags => "R",
2391         reg_req   => { out => [ "vfp" ] },
2392         emit      => '. fldz',
2393         attr_type => "ia32_x87_attr_t",
2394         latency   => 2,
2395 },
2396
2397 fld1 => {
2398         op_flags  => "R|c|K",
2399         irn_flags => "R",
2400         reg_req   => { out => [ "vfp" ] },
2401         emit      => '. fld1',
2402         attr_type => "ia32_x87_attr_t",
2403         latency   => 2,
2404 },
2405
2406 fldpi => {
2407         op_flags  => "R|c|K",
2408         irn_flags => "R",
2409         reg_req   => { out => [ "vfp" ] },
2410         emit      => '. fldpi',
2411         attr_type => "ia32_x87_attr_t",
2412         latency   => 2,
2413 },
2414
2415 fldln2 => {
2416         op_flags  => "R|c|K",
2417         irn_flags => "R",
2418         reg_req   => { out => [ "vfp" ] },
2419         emit      => '. fldln2',
2420         attr_type => "ia32_x87_attr_t",
2421         latency   => 2,
2422 },
2423
2424 fldlg2 => {
2425         op_flags  => "R|c|K",
2426         irn_flags => "R",
2427         reg_req   => { out => [ "vfp" ] },
2428         emit      => '. fldlg2',
2429         attr_type => "ia32_x87_attr_t",
2430         latency   => 2,
2431 },
2432
2433 fldl2t => {
2434         op_flags  => "R|c|K",
2435         irn_flags => "R",
2436         reg_req   => { out => [ "vfp" ] },
2437         emit      => '. fldll2t',
2438         attr_type => "ia32_x87_attr_t",
2439         latency   => 2,
2440 },
2441
2442 fldl2e => {
2443         op_flags  => "R|c|K",
2444         irn_flags => "R",
2445         reg_req   => { out => [ "vfp" ] },
2446         emit      => '. fldl2e',
2447         attr_type => "ia32_x87_attr_t",
2448         latency   => 2,
2449 },
2450
2451 # fxch, fpush, fpop
2452 # Note that it is NEVER allowed to do CSE on these nodes
2453 # Moreover, note the virtual register requierements!
2454
2455 fxch => {
2456         op_flags  => "R|K",
2457         reg_req   => { },
2458         cmp_attr  => "return 1;",
2459         emit      => '. fxch %X0',
2460         attr_type => "ia32_x87_attr_t",
2461         mode      => "mode_ANY",
2462         latency   => 1,
2463 },
2464
2465 fpush => {
2466         op_flags  => "R|K",
2467         reg_req   => {},
2468         cmp_attr  => "return 1;",
2469         emit      => '. fld %X0',
2470         attr_type => "ia32_x87_attr_t",
2471         mode      => "mode_ANY",
2472         latency   => 1,
2473 },
2474
2475 fpushCopy => {
2476         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
2477         cmp_attr  => "return 1;",
2478         emit      => '. fld %X0',
2479         attr_type => "ia32_x87_attr_t",
2480         latency   => 1,
2481 },
2482
2483 fpop => {
2484         op_flags  => "K",
2485         reg_req   => { },
2486         cmp_attr  => "return 1;",
2487         emit      => '. fstp %X0',
2488         attr_type => "ia32_x87_attr_t",
2489         mode      => "mode_ANY",
2490         latency   => 1,
2491 },
2492
2493 ffreep => {
2494         op_flags  => "K",
2495         reg_req   => { },
2496         cmp_attr  => "return 1;",
2497         emit      => '. ffreep %X0',
2498         attr_type => "ia32_x87_attr_t",
2499         mode      => "mode_ANY",
2500         latency   => 1,
2501 },
2502
2503 emms => {
2504         op_flags  => "K",
2505         reg_req   => { },
2506         cmp_attr  => "return 1;",
2507         emit      => '. emms',
2508         attr_type => "ia32_x87_attr_t",
2509         mode      => "mode_ANY",
2510         latency   => 3,
2511 },
2512
2513 femms => {
2514         op_flags  => "K",
2515         reg_req   => { },
2516         cmp_attr  => "return 1;",
2517         emit      => '. femms',
2518         attr_type => "ia32_x87_attr_t",
2519         mode      => "mode_ANY",
2520         latency   => 3,
2521 },
2522
2523 # compare
2524
2525 FucomFnstsw => {
2526         reg_req   => { },
2527         emit      => ". fucom %X1\n".
2528                      ". fnstsw %%ax",
2529         attr_type => "ia32_x87_attr_t",
2530         latency   => 2,
2531 },
2532
2533 FucompFnstsw => {
2534         reg_req   => { },
2535         emit      => ". fucomp %X1\n".
2536                      ". fnstsw %%ax",
2537         attr_type => "ia32_x87_attr_t",
2538         latency   => 2,
2539 },
2540
2541 FucomppFnstsw => {
2542         reg_req   => { },
2543         emit      => ". fucompp\n".
2544                      ". fnstsw %%ax",
2545         attr_type => "ia32_x87_attr_t",
2546         latency   => 2,
2547 },
2548
2549 Fucomi => {
2550         reg_req   => { },
2551         emit      => '. fucomi %X1',
2552         attr_type => "ia32_x87_attr_t",
2553         latency   => 1,
2554 },
2555
2556 Fucompi => {
2557         reg_req   => { },
2558         emit      => '. fucompi %X1',
2559         attr_type => "ia32_x87_attr_t",
2560         latency   => 1,
2561 },
2562
2563 FtstFnstsw => {
2564         reg_req   => { },
2565         emit      => ". ftst\n".
2566                      ". fnstsw %%ax",
2567         attr_type => "ia32_x87_attr_t",
2568         latency   => 2,
2569 },
2570
2571
2572 # -------------------------------------------------------------------------------- #
2573 #  ____ ____  _____                  _                               _             #
2574 # / ___/ ___|| ____| __   _____  ___| |_ ___  _ __   _ __   ___   __| | ___  ___   #
2575 # \___ \___ \|  _|   \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __|  #
2576 #  ___) |__) | |___   \ V /  __/ (__| || (_) | |    | | | | (_) | (_| |  __/\__ \  #
2577 # |____/____/|_____|   \_/ \___|\___|\__\___/|_|    |_| |_|\___/ \__,_|\___||___/  #
2578 #                                                                                  #
2579 # -------------------------------------------------------------------------------- #
2580
2581
2582 # Spilling and reloading of SSE registers, hardcoded, not generated #
2583
2584 xxLoad => {
2585         op_flags  => "L|F",
2586         state     => "exc_pinned",
2587         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
2588         emit      => '. movdqu %D0, %AM',
2589         outs      => [ "res", "M" ],
2590         units     => [ "SSE" ],
2591         latency   => 1,
2592 },
2593
2594 xxStore => {
2595         op_flags => "L|F",
2596         state    => "exc_pinned",
2597         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
2598         ins      => [ "base", "index", "mem", "val" ],
2599         emit     => '. movdqu %binop',
2600         units    => [ "SSE" ],
2601         latency   => 1,
2602         mode     => "mode_M",
2603 },
2604
2605 ); # end of %nodes
2606
2607 # Include the generated SIMD node specification written by the SIMD optimization
2608 $my_script_name = dirname($myname) . "/../ia32/ia32_simd_spec.pl";
2609 unless ($return = do $my_script_name) {
2610         warn "couldn't parse $my_script_name: $@" if $@;
2611         warn "couldn't do $my_script_name: $!"    unless defined $return;
2612         warn "couldn't run $my_script_name"       unless $return;
2613 }
2614
2615 # Transform some attributes
2616 foreach my $op (keys(%nodes)) {
2617         my $node         = $nodes{$op};
2618         my $op_attr_init = $node->{op_attr_init};
2619
2620         if(defined($op_attr_init)) {
2621                 $op_attr_init .= "\n\t";
2622         } else {
2623                 $op_attr_init = "";
2624         }
2625
2626         if(!defined($node->{latency})) {
2627                 if($op =~ m/^l_/) {
2628                         $node->{latency} = 0;
2629                 } else {
2630                         die("Latency missing for op $op");
2631                 }
2632         }
2633         $op_attr_init .= "attr->latency = ".$node->{latency} . ";";
2634
2635         $node->{op_attr_init} = $op_attr_init;
2636 }
2637
2638 print "";