@@ -209,89 +209,87 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
209
209
}
210
210
opregreg (v .Op .Asm (), r , gc .SSARegNum (v .Args [1 ]))
211
211
212
- case ssa .OpAMD64DIVQ , ssa .OpAMD64DIVL , ssa .OpAMD64DIVW ,
213
- ssa .OpAMD64DIVQU , ssa .OpAMD64DIVLU , ssa .OpAMD64DIVWU ,
214
- ssa .OpAMD64MODQ , ssa .OpAMD64MODL , ssa .OpAMD64MODW ,
215
- ssa .OpAMD64MODQU , ssa .OpAMD64MODLU , ssa .OpAMD64MODWU :
212
+ case ssa .OpAMD64DIVQU , ssa .OpAMD64DIVLU , ssa .OpAMD64DIVWU :
213
+ // Arg[0] (the dividend) is in AX.
214
+ // Arg[1] (the divisor) can be in any other register.
215
+ // Result[0] (the quotient) is in AX.
216
+ // Result[1] (the remainder) is in DX.
217
+ r := gc .SSARegNum (v .Args [1 ])
216
218
217
- // Arg[0] is already in AX as it's the only register we allow
218
- // and AX is the only output
219
- x := gc .SSARegNum (v .Args [1 ])
220
-
221
- // CPU faults upon signed overflow, which occurs when most
222
- // negative int is divided by -1.
223
- var j * obj.Prog
224
- if v .Op == ssa .OpAMD64DIVQ || v .Op == ssa .OpAMD64DIVL ||
225
- v .Op == ssa .OpAMD64DIVW || v .Op == ssa .OpAMD64MODQ ||
226
- v .Op == ssa .OpAMD64MODL || v .Op == ssa .OpAMD64MODW {
227
-
228
- var c * obj.Prog
229
- switch v .Op {
230
- case ssa .OpAMD64DIVQ , ssa .OpAMD64MODQ :
231
- c = gc .Prog (x86 .ACMPQ )
232
- j = gc .Prog (x86 .AJEQ )
233
- // go ahead and sign extend to save doing it later
234
- gc .Prog (x86 .ACQO )
219
+ // Zero extend dividend.
220
+ c := gc .Prog (x86 .AXORL )
221
+ c .From .Type = obj .TYPE_REG
222
+ c .From .Reg = x86 .REG_DX
223
+ c .To .Type = obj .TYPE_REG
224
+ c .To .Reg = x86 .REG_DX
235
225
236
- case ssa .OpAMD64DIVL , ssa .OpAMD64MODL :
237
- c = gc .Prog (x86 .ACMPL )
238
- j = gc .Prog (x86 .AJEQ )
239
- gc .Prog (x86 .ACDQ )
240
-
241
- case ssa .OpAMD64DIVW , ssa .OpAMD64MODW :
242
- c = gc .Prog (x86 .ACMPW )
243
- j = gc .Prog (x86 .AJEQ )
244
- gc .Prog (x86 .ACWD )
245
- }
246
- c .From .Type = obj .TYPE_REG
247
- c .From .Reg = x
248
- c .To .Type = obj .TYPE_CONST
249
- c .To .Offset = - 1
226
+ // Issue divide.
227
+ p := gc .Prog (v .Op .Asm ())
228
+ p .From .Type = obj .TYPE_REG
229
+ p .From .Reg = r
250
230
251
- j .To .Type = obj .TYPE_BRANCH
231
+ case ssa .OpAMD64DIVQ , ssa .OpAMD64DIVL , ssa .OpAMD64DIVW :
232
+ // Arg[0] (the dividend) is in AX.
233
+ // Arg[1] (the divisor) can be in any other register.
234
+ // Result[0] (the quotient) is in AX.
235
+ // Result[1] (the remainder) is in DX.
236
+ r := gc .SSARegNum (v .Args [1 ])
252
237
238
+ // CPU faults upon signed overflow, which occurs when the most
239
+ // negative int is divided by -1. Handle divide by -1 as a special case.
240
+ var c * obj.Prog
241
+ switch v .Op {
242
+ case ssa .OpAMD64DIVQ :
243
+ c = gc .Prog (x86 .ACMPQ )
244
+ case ssa .OpAMD64DIVL :
245
+ c = gc .Prog (x86 .ACMPL )
246
+ case ssa .OpAMD64DIVW :
247
+ c = gc .Prog (x86 .ACMPW )
253
248
}
249
+ c .From .Type = obj .TYPE_REG
250
+ c .From .Reg = r
251
+ c .To .Type = obj .TYPE_CONST
252
+ c .To .Offset = - 1
253
+ j1 := gc .Prog (x86 .AJEQ )
254
+ j1 .To .Type = obj .TYPE_BRANCH
254
255
255
- // for unsigned ints, we sign extend by setting DX = 0
256
- // signed ints were sign extended above
257
- if v .Op == ssa .OpAMD64DIVQU || v .Op == ssa .OpAMD64MODQU ||
258
- v .Op == ssa .OpAMD64DIVLU || v .Op == ssa .OpAMD64MODLU ||
259
- v .Op == ssa .OpAMD64DIVWU || v .Op == ssa .OpAMD64MODWU {
260
- c := gc .Prog (x86 .AXORQ )
261
- c .From .Type = obj .TYPE_REG
262
- c .From .Reg = x86 .REG_DX
263
- c .To .Type = obj .TYPE_REG
264
- c .To .Reg = x86 .REG_DX
256
+ // Sign extend dividend.
257
+ switch v .Op {
258
+ case ssa .OpAMD64DIVQ :
259
+ gc .Prog (x86 .ACQO )
260
+ case ssa .OpAMD64DIVL :
261
+ gc .Prog (x86 .ACDQ )
262
+ case ssa .OpAMD64DIVW :
263
+ gc .Prog (x86 .ACWD )
265
264
}
266
265
266
+ // Issue divide.
267
267
p := gc .Prog (v .Op .Asm ())
268
268
p .From .Type = obj .TYPE_REG
269
- p .From .Reg = x
269
+ p .From .Reg = r
270
270
271
- // signed division, rest of the check for -1 case
272
- if j != nil {
273
- j2 := gc .Prog (obj .AJMP )
274
- j2 .To .Type = obj .TYPE_BRANCH
271
+ // Skip over -1 fixup code.
272
+ j2 := gc .Prog (obj .AJMP )
273
+ j2 .To .Type = obj .TYPE_BRANCH
275
274
276
- var n * obj.Prog
277
- if v .Op == ssa .OpAMD64DIVQ || v .Op == ssa .OpAMD64DIVL ||
278
- v .Op == ssa .OpAMD64DIVW {
279
- // n * -1 = -n
280
- n = gc .Prog (x86 .ANEGQ )
281
- n .To .Type = obj .TYPE_REG
282
- n .To .Reg = x86 .REG_AX
283
- } else {
284
- // n % -1 == 0
285
- n = gc .Prog (x86 .AXORQ )
286
- n .From .Type = obj .TYPE_REG
287
- n .From .Reg = x86 .REG_DX
288
- n .To .Type = obj .TYPE_REG
289
- n .To .Reg = x86 .REG_DX
290
- }
275
+ // Issue -1 fixup code.
276
+ // n / -1 = -n
277
+ n1 := gc .Prog (x86 .ANEGQ )
278
+ n1 .To .Type = obj .TYPE_REG
279
+ n1 .To .Reg = x86 .REG_AX
291
280
292
- j .To .Val = n
293
- j2 .To .Val = s .Pc ()
294
- }
281
+ // n % -1 == 0
282
+ n2 := gc .Prog (x86 .AXORL )
283
+ n2 .From .Type = obj .TYPE_REG
284
+ n2 .From .Reg = x86 .REG_DX
285
+ n2 .To .Type = obj .TYPE_REG
286
+ n2 .To .Reg = x86 .REG_DX
287
+
288
+ // TODO(khr): issue only the -1 fixup code we need.
289
+ // For instance, if only the quotient is used, no point in zeroing the remainder.
290
+
291
+ j1 .To .Val = n1
292
+ j2 .To .Val = s .Pc ()
295
293
296
294
case ssa .OpAMD64HMULQ , ssa .OpAMD64HMULL , ssa .OpAMD64HMULW , ssa .OpAMD64HMULB ,
297
295
ssa .OpAMD64HMULQU , ssa .OpAMD64HMULLU , ssa .OpAMD64HMULWU , ssa .OpAMD64HMULBU :
@@ -818,6 +816,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
818
816
p .To .Reg = gc .SSARegNum (v )
819
817
case ssa .OpSP , ssa .OpSB :
820
818
// nothing to do
819
+ case ssa .OpSelect0 , ssa .OpSelect1 :
820
+ // nothing to do
821
821
case ssa .OpAMD64SETEQ , ssa .OpAMD64SETNE ,
822
822
ssa .OpAMD64SETL , ssa .OpAMD64SETLE ,
823
823
ssa .OpAMD64SETG , ssa .OpAMD64SETGE ,
0 commit comments