- "outs" => [ "res", "M" ],
- "latency" => 6,
- "units" => [ "ALU1", "SSE1" ],
-},
-
-"l_ShrD" => {
- "cmp_attr" => " return 1;\n",
- "comment" => "construct lowered ShrD: ShrD(a, b, c) = a, b >> count (shift rigth count bits from a into b)",
- "arity" => 3
-},
-
-"Shrs" => {
- "irn_flags" => "R",
- "comment" => "construct Shrs: Shrs(a, b) = a >> b",
- "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
- "emit" => '. sar %ia32_emit_binop /* Shrs(%A1, %A2) -> %D1 */',
- "outs" => [ "res", "M" ],
- "units" => [ "ALU1", "SSE1" ],
-},
-
-"l_Shrs" => {
- "cmp_attr" => " return 1;\n",
- "comment" => "construct lowered Shrs: Shrs(a, b) = a << b",
- "arity" => 2
-},
-
-"RotR" => {
- "irn_flags" => "R",
- "comment" => "construct RotR: RotR(a, b) = a ROTR b",
- "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
- "emit" => '. ror %ia32_emit_binop /* RotR(%A1, %A2) -> %D1 */',
- "outs" => [ "res", "M" ],
- "units" => [ "ALU1", "SSE1" ],
-},
-
-"RotL" => {
- "irn_flags" => "R",
- "comment" => "construct RotL: RotL(a, b) = a ROTL b",
- "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
- "emit" => '. rol %ia32_emit_binop /* RotL(%A1, %A2) -> %D1 */',
- "outs" => [ "res", "M" ],
- "units" => [ "ALU1", "SSE1" ],
+ outs => [ "low_res", "high_res" ],
+ units => [ "GP" ],
+ modified_flags => $status_flags
+},
+
+IDiv => {
+ op_flags => "F|L",
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] },
+ ins => [ "base", "index", "mem", "left_low", "left_high", "right" ],
+ outs => [ "div_res", "mod_res", "M" ],
+ attr => "ia32_op_flavour_t dm_flav",
+ am => "source,ternary",
+ init_attr => "attr->data.op_flav = dm_flav;",
+ emit => ". idiv%M %unop5",
+ latency => 25,
+ units => [ "GP" ],
+ modified_flags => $status_flags
+},
+
+Div => {
+ op_flags => "F|L",
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] },
+ ins => [ "base", "index", "mem", "left_low", "left_high", "right" ],
+ outs => [ "div_res", "mod_res", "M" ],
+ attr => "ia32_op_flavour_t dm_flav",
+ am => "source,ternary",
+ init_attr => "attr->data.op_flav = dm_flav;",
+ emit => ". div%M %unop5",
+ latency => 25,
+ units => [ "GP" ],
+ modified_flags => $status_flags
+},
+
+Shl => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
+ ins => [ "left", "right" ],
+ am => "dest,binary",
+ emit => '. shl %SB1, %S0',
+ units => [ "GP" ],
+ mode => $mode_gp,
+ modified_flags => $status_flags
+},
+
+ShlMem => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
+ ins => [ "base", "index", "mem", "count" ],
+ emit => '. shl%M %SB3, %AM',
+ units => [ "GP" ],
+ mode => "mode_M",
+ modified_flags => $status_flags
+},
+
+l_ShlDep => {
+ cmp_attr => "return 1;",
+ # value, cnt, dependency
+ arity => 3
+},
+
+ShlD => {
+ # FIXME: WHY? the right requirement is in_r3 !in_r5, especially this is the same as in Shl
+ #
+ # Out requirements is: different from all in
+ # This is because, out must be different from LowPart and ShiftCount.
+ # We could say "!ecx !in_r4" but it can occur, that all values live through
+ # this Shift and the only value dying is the ShiftCount. Then there would be a
+ # register missing, as result must not be ecx and all other registers are
+ # occupied. What we should write is "!in_r4 !in_r5", but this is not supported
+ # (and probably never will). So we create artificial interferences of the result
+ # with all inputs, so the spiller can always assure a free register.
+ # reg_req => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] },
+
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "ecx" ], out => [ "in_r1 !in_r3" ] },
+ ins => [ "left_high", "left_low", "right" ],
+ am => "dest,ternary",
+ emit => '. shld%M %SB2, %S1, %S0',
+ latency => 6,
+ units => [ "GP" ],
+ mode => $mode_gp,
+ modified_flags => $status_flags
+},
+
+l_ShlD => {
+ cmp_attr => "return 1;",
+ arity => 3,
+},
+
+Shr => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
+ ins => [ "val", "count" ],
+ am => "dest,binary",
+ emit => '. shr %SB1, %S0',
+ units => [ "GP" ],
+ mode => $mode_gp,
+ modified_flags => $status_flags
+},
+
+ShrMem => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
+ ins => [ "base", "index", "mem", "count" ],
+ emit => '. shr%M %SB3, %AM',
+ units => [ "GP" ],
+ mode => "mode_M",
+ modified_flags => $status_flags
+},
+
+l_ShrDep => {
+ cmp_attr => "return 1;",
+ # value, cnt, dependency
+ arity => 3
+},
+
+ShrD => {
+ # FIXME: WHY? the right requirement is in_r3 !in_r5, especially this is the same as in Shr
+ #
+ # Out requirements is: different from all in
+ # This is because, out must be different from LowPart and ShiftCount.
+ # We could say "!ecx !in_r4" but it can occur, that all values live through
+ # this Shift and the only value dying is the ShiftCount. Then there would be a
+ # register missing, as result must not be ecx and all other registers are
+ # occupied. What we should write is "!in_r4 !in_r5", but this is not supported
+ # (and probably never will). So we create artificial interferences of the result
+ # with all inputs, so the spiller can always assure a free register.
+ # reg_req => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] },
+
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "ecx" ], out => [ "in_r1 !in_r3" ] },
+ ins => [ "left_high", "left_low", "right" ],
+ am => "dest,ternary",
+ emit => '. shrd%M %SB2, %S1, %S0',
+ latency => 6,
+ units => [ "GP" ],
+ mode => $mode_gp,
+ modified_flags => $status_flags
+},
+
+l_ShrD => {
+ cmp_attr => "return 1;",
+ arity => 3
+},
+
+Sar => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
+ ins => [ "val", "count" ],
+ am => "dest,binary",
+ emit => '. sar %SB1, %S0',
+ units => [ "GP" ],
+ mode => $mode_gp,
+ modified_flags => $status_flags
+},
+
+SarMem => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
+ ins => [ "base", "index", "mem", "count" ],
+ emit => '. sar%M %SB3, %AM',
+ units => [ "GP" ],
+ mode => "mode_M",
+ modified_flags => $status_flags
+},
+
+l_Sar => {
+ cmp_attr => "return 1;",
+ # value, cnt
+ arity => 2
+},
+
+l_SarDep => {
+ cmp_attr => "return 1;",
+ # value, cnt, dependency
+ arity => 3
+},
+
+Ror => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
+ ins => [ "val", "count" ],
+ am => "dest,binary",
+ emit => '. ror %SB1, %S0',
+ units => [ "GP" ],
+ mode => $mode_gp,
+ modified_flags => $status_flags
+},
+
+RorMem => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
+ ins => [ "base", "index", "mem", "count" ],
+ emit => '. ror%M %SB3, %AM',
+ units => [ "GP" ],
+ mode => "mode_M",
+ modified_flags => $status_flags
+},
+
+Rol => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
+ ins => [ "val", "count" ],
+ am => "dest,binary",
+ emit => '. rol %SB1, %S0',
+ units => [ "GP" ],
+ mode => $mode_gp,
+ modified_flags => $status_flags
+},
+
+RolMem => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
+ ins => [ "base", "index", "mem", "count" ],
+ emit => '. rol%M %SB3, %AM',
+ units => [ "GP" ],
+ mode => "mode_M",
+ modified_flags => $status_flags