-"Sub" => {
- "irn_flags" => "R",
- "comment" => "construct Sub: Sub(a, b) = a - b",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
- "emit" => '. subl %binop',
- "units" => [ "GP" ],
- "mode" => "mode_Iu",
-},
-
-"Sbb" => {
- "comment" => "construct Sub with Carry: SubC(a, b) = a - b - carry",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3 !in_r4" ] },
- "emit" => '. sbbl %binop',
- "units" => [ "GP" ],
- "mode" => "mode_Iu",
-},
-
-"Sub64Bit" => {
- "irn_flags" => "R",
- "comment" => "construct 64Bit Sub: Sub(a_l, a_h, b_l, b_h) = a_l - b_l; a_h - b_h - borrow",
- "arity" => 4,
- "reg_req" => { "in" => [ "gp", "gp", "gp", "gp" ], "out" => [ "!in", "!in" ] },
- "emit" => '
-. movl %S1, %D1
-. movl %S2, %D2
-. subl %S3, %D1
-. sbbl %S4, %D2
-',
- "outs" => [ "low_res", "high_res" ],
- "units" => [ "GP" ],
-},
-
-"l_Sub" => {
- "irn_flags" => "R",
- "cmp_attr" => "return 1;",
- "comment" => "construct lowered Sub: Sub(a, b) = a - b",
- "arity" => 2,
-},
-
-"l_Sbb" => {
- "cmp_attr" => "return 1;",
- "comment" => "construct lowered Sub with Carry: SubC(a, b) = a - b - carry",
- "arity" => 2,
-},
-
-"IDiv" => {
- "op_flags" => "F|L",
- "state" => "exc_pinned",
- "reg_req" => { "in" => [ "gp", "gp", "eax", "edx", "gp", "none" ], "out" => [ "eax", "edx", "none" ] },
- "attr" => "ia32_op_flavour_t dm_flav",
- "init_attr" => "attr->data.op_flav = dm_flav;",
- "emit" => ". idivl %unop",
- "outs" => [ "div_res", "mod_res", "M" ],
- "latency" => 25,
- "units" => [ "GP" ],
-},
-
-"Div" => {
- "op_flags" => "F|L",
- "state" => "exc_pinned",
- "reg_req" => { "in" => [ "gp", "gp", "eax", "edx", "gp", "none" ], "out" => [ "eax", "edx", "none" ] },
- "attr" => "ia32_op_flavour_t dm_flav",
- "init_attr" => "attr->data.op_flav = dm_flav;",
- "emit" => ". divl %unop",
- "outs" => [ "div_res", "mod_res", "M" ],
- "latency" => 25,
- "units" => [ "GP" ],
-},
-
-"Shl" => {
- "irn_flags" => "R",
- "comment" => "construct Shl: Shl(a, b) = a << b",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
- "emit" => '. shll %binop',
- "units" => [ "GP" ],
- "mode" => "mode_Iu",
-},
-
-"l_Shl" => {
- "cmp_attr" => "return 1;",
- "comment" => "construct lowered Shl: Shl(a, b) = a << b",
- "arity" => 2
-},
-
-"ShlD" => {
- "irn_flags" => "R",
- "comment" => "construct ShlD: ShlD(a, b, c) = a, b << count (shift left count bits from b into a)",
- # 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" ] },
- "emit" =>
-'
-if (get_ia32_immop_type(node) == ia32_ImmNone) {
- if (get_ia32_op_type(node) == ia32_AddrModeD) {
- . shldl %%cl, %S4, %AM
- } else {
- . shldl %%cl, %S4, %S3
- }
-} else {
- if (get_ia32_op_type(node) == ia32_AddrModeD) {
- . shldl $%C, %S4, %AM
- } else {
- . shldl $%C, %S4, %S3
- }
-}
-',
- "latency" => 6,
- "units" => [ "GP" ],
- "mode" => "mode_Iu",
-},
-
-"l_ShlD" => {
- "cmp_attr" => "return 1;",
- "comment" => "construct lowered ShlD: ShlD(a, b, c) = a, b << count (shift left count bits from b into a)",
- "arity" => 3,
-},
-
-"Shr" => {
- "irn_flags" => "R",
- "comment" => "construct Shr: Shr(a, b) = a >> b",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
- "emit" => '. shrl %binop',
- "units" => [ "GP" ],
- "mode" => "mode_Iu",
-},
-
-"l_Shr" => {
- "cmp_attr" => "return 1;",
- "comment" => "construct lowered Shr: Shr(a, b) = a << b",
- "arity" => 2
-},
-
-"ShrD" => {
- "irn_flags" => "R",
- "comment" => "construct ShrD: ShrD(a, b, c) = a, b >> count (shift rigth count bits from a into b)",
- # 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" ] },
- "emit" => '
-if (get_ia32_immop_type(node) == ia32_ImmNone) {
- if (get_ia32_op_type(node) == ia32_AddrModeD) {
- . shrdl %%cl, %S4, %AM
- } else {
- . shrdl %%cl, %S4, %S3
- }
-} else {
- if (get_ia32_op_type(node) == ia32_AddrModeD) {
- . shrdl $%C, %S4, %AM
- } else {
- . shrdl $%C, %S4, %S3
- }
-}
-',
- "latency" => 6,
- "units" => [ "GP" ],
- "mode" => "mode_Iu",
-},
-
-"l_ShrD" => {
- "cmp_attr" => "return 1;",
- "comment" => "construct lowered ShrD: ShrD(a, b, c) = a, b >> count (shift rigth count bits from a into b)",
- "arity" => 3
-},
-
-"Sar" => {
- "irn_flags" => "R",
- "comment" => "construct Shrs: Shrs(a, b) = a >> b",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
- "emit" => '. sarl %binop',
- "units" => [ "GP" ],
- "mode" => "mode_Iu",
-},
-
-"l_Sar" => {
- "cmp_attr" => "return 1;",
- "comment" => "construct lowered Sar: Sar(a, b) = a << b",
- "arity" => 2
-},
-
-"Ror" => {
- "irn_flags" => "R",
- "comment" => "construct Ror: Ror(a, b) = a ROR b",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
- "emit" => '. rorl %binop',
- "units" => [ "GP" ],
- "mode" => "mode_Iu",
-},
-
-"Rol" => {
- "irn_flags" => "R",
- "comment" => "construct Rol: Rol(a, b) = a ROL b",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
- "emit" => '. roll %binop',
- "units" => [ "GP" ],
- "mode" => "mode_Iu",
+Sub => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4", "none", "flags" ] },
+ ins => [ "base", "index", "mem", "left", "right" ],
+ am => "full,binary",
+ emit => '. sub%M %binop',
+ units => [ "GP" ],
+ mode => $mode_gp,
+ modified_flags => $status_flags
+},
+
+SubMem => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ emit => '. sub%M %SI3, %AM',
+ units => [ "GP" ],
+ mode => 'mode_M',
+ modified_flags => $status_flags
+},
+
+SubMem8Bit => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ emit => '. sub%M %SB3, %AM',
+ units => [ "GP" ],
+ mode => 'mode_M',
+ modified_flags => $status_flags
+},
+
+Sbb => {
+ reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], out => [ "in_r4 !in_r5" ] },
+ ins => [ "base", "index", "mem", "left", "right", "eflags" ],
+ am => "full,binary",
+ emit => '. sbb%M %binop',
+ units => [ "GP" ],
+ mode => $mode_gp,
+ modified_flags => $status_flags
+},
+
+l_Sub => {
+ reg_req => { in => [ "none", "none" ], out => [ "none" ] },
+ ins => [ "left", "right" ],
+},
+
+l_Sbb => {
+ reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
+ ins => [ "left", "right", "eflags" ],
+},
+
+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