// Result[0] (the quotient) is in AX.
// Result[1] (the remainder) is in DX.
r := v.Args[1].Reg()
- var j1 *obj.Prog
var opCMP, opNEG, opSXD obj.As
switch v.Op {
// CPU faults upon signed overflow, which occurs when the most
// negative int is divided by -1. Handle divide by -1 as a special case.
+ var j1, j2 *obj.Prog
if ssa.DivisionNeedsFixUp(v) {
c := s.Prog(opCMP)
c.From.Type = obj.TYPE_REG
c.From.Reg = r
c.To.Type = obj.TYPE_CONST
c.To.Offset = -1
- j1 = s.Prog(x86.AJEQ)
- j1.To.Type = obj.TYPE_BRANCH
- }
-
- // Sign extend dividend and perform division.
- s.Prog(opSXD)
- p := s.Prog(v.Op.Asm())
- p.From.Type = obj.TYPE_REG
- p.From.Reg = r
- if j1 != nil {
- // Skip over -1 fixup code.
- j2 := s.Prog(obj.AJMP)
- j2.To.Type = obj.TYPE_BRANCH
+ // Divisor is not -1, proceed with normal division.
+ j1 = s.Prog(x86.AJNE)
+ j1.To.Type = obj.TYPE_BRANCH
- // Issue -1 fixup code.
+ // Divisor is -1, manually compute quotient and remainder via fixup code.
// n / -1 = -n
n1 := s.Prog(opNEG)
n1.To.Type = obj.TYPE_REG
// TODO(khr): issue only the -1 fixup code we need.
// For instance, if only the quotient is used, no point in zeroing the remainder.
- j1.To.SetTarget(n1)
+ // Skip over normal division.
+ j2 = s.Prog(obj.AJMP)
+ j2.To.Type = obj.TYPE_BRANCH
+ }
+
+ // Sign extend dividend and perform division.
+ p := s.Prog(opSXD)
+ if j1 != nil {
+ j1.To.SetTarget(p)
+ }
+ p = s.Prog(v.Op.Asm())
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = r
+
+ if j2 != nil {
j2.To.SetTarget(s.Pc())
}