@@ -398,7 +398,18 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
398398 p .To .Type = obj .TYPE_REG
399399 p .To .Reg = r
400400
401- case ssa .OpAMD64CMOVQEQ , ssa .OpAMD64CMOVLEQ :
401+ case ssa .OpAMD64CMOVQEQ , ssa .OpAMD64CMOVLEQ , ssa .OpAMD64CMOVWEQ ,
402+ ssa .OpAMD64CMOVQLT , ssa .OpAMD64CMOVLLT , ssa .OpAMD64CMOVWLT ,
403+ ssa .OpAMD64CMOVQNE , ssa .OpAMD64CMOVLNE , ssa .OpAMD64CMOVWNE ,
404+ ssa .OpAMD64CMOVQGT , ssa .OpAMD64CMOVLGT , ssa .OpAMD64CMOVWGT ,
405+ ssa .OpAMD64CMOVQLE , ssa .OpAMD64CMOVLLE , ssa .OpAMD64CMOVWLE ,
406+ ssa .OpAMD64CMOVQGE , ssa .OpAMD64CMOVLGE , ssa .OpAMD64CMOVWGE ,
407+ ssa .OpAMD64CMOVQHI , ssa .OpAMD64CMOVLHI , ssa .OpAMD64CMOVWHI ,
408+ ssa .OpAMD64CMOVQLS , ssa .OpAMD64CMOVLLS , ssa .OpAMD64CMOVWLS ,
409+ ssa .OpAMD64CMOVQCC , ssa .OpAMD64CMOVLCC , ssa .OpAMD64CMOVWCC ,
410+ ssa .OpAMD64CMOVQCS , ssa .OpAMD64CMOVLCS , ssa .OpAMD64CMOVWCS ,
411+ ssa .OpAMD64CMOVQGTF , ssa .OpAMD64CMOVLGTF , ssa .OpAMD64CMOVWGTF ,
412+ ssa .OpAMD64CMOVQGEF , ssa .OpAMD64CMOVLGEF , ssa .OpAMD64CMOVWGEF :
402413 r := v .Reg ()
403414 if r != v .Args [0 ].Reg () {
404415 v .Fatalf ("input[0] and output not in same register %s" , v .LongString ())
@@ -409,6 +420,71 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
409420 p .To .Type = obj .TYPE_REG
410421 p .To .Reg = r
411422
423+ case ssa .OpAMD64CMOVQNEF , ssa .OpAMD64CMOVLNEF , ssa .OpAMD64CMOVWNEF :
424+ r := v .Reg ()
425+ if r != v .Args [0 ].Reg () {
426+ v .Fatalf ("input[0] and output not in same register %s" , v .LongString ())
427+ }
428+ // Flag condition: ^ZERO || PARITY
429+ // Generate:
430+ // CMOV*NE SRC,DST
431+ // CMOV*PS SRC,DST
432+ p := s .Prog (v .Op .Asm ())
433+ p .From .Type = obj .TYPE_REG
434+ p .From .Reg = v .Args [1 ].Reg ()
435+ p .To .Type = obj .TYPE_REG
436+ p .To .Reg = r
437+ var q * obj.Prog
438+ if v .Op == ssa .OpAMD64CMOVQNEF {
439+ q = s .Prog (x86 .ACMOVQPS )
440+ } else if v .Op == ssa .OpAMD64CMOVLNEF {
441+ q = s .Prog (x86 .ACMOVLPS )
442+ } else {
443+ q = s .Prog (x86 .ACMOVWPS )
444+ }
445+ q .From .Type = obj .TYPE_REG
446+ q .From .Reg = v .Args [1 ].Reg ()
447+ q .To .Type = obj .TYPE_REG
448+ q .To .Reg = r
449+
450+ case ssa .OpAMD64CMOVQEQF , ssa .OpAMD64CMOVLEQF , ssa .OpAMD64CMOVWEQF :
451+ r := v .Reg ()
452+ if r != v .Args [0 ].Reg () {
453+ v .Fatalf ("input[0] and output not in same register %s" , v .LongString ())
454+ }
455+
456+ // Flag condition: ZERO && !PARITY
457+ // Generate:
458+ // MOV SRC,AX
459+ // CMOV*NE DST,AX
460+ // CMOV*PC AX,DST
461+ //
462+ // TODO(rasky): we could generate:
463+ // CMOV*NE DST,SRC
464+ // CMOV*PC SRC,DST
465+ // But this requires a way for regalloc to know that SRC might be
466+ // clobbered by this instruction.
467+ if v .Args [1 ].Reg () != x86 .REG_AX {
468+ opregreg (s , moveByType (v .Type ), x86 .REG_AX , v .Args [1 ].Reg ())
469+ }
470+ p := s .Prog (v .Op .Asm ())
471+ p .From .Type = obj .TYPE_REG
472+ p .From .Reg = r
473+ p .To .Type = obj .TYPE_REG
474+ p .To .Reg = x86 .REG_AX
475+ var q * obj.Prog
476+ if v .Op == ssa .OpAMD64CMOVQEQF {
477+ q = s .Prog (x86 .ACMOVQPC )
478+ } else if v .Op == ssa .OpAMD64CMOVLEQF {
479+ q = s .Prog (x86 .ACMOVLPC )
480+ } else {
481+ q = s .Prog (x86 .ACMOVWPC )
482+ }
483+ q .From .Type = obj .TYPE_REG
484+ q .From .Reg = x86 .REG_AX
485+ q .To .Type = obj .TYPE_REG
486+ q .To .Reg = r
487+
412488 case ssa .OpAMD64MULQconst , ssa .OpAMD64MULLconst :
413489 r := v .Reg ()
414490 p := s .Prog (v .Op .Asm ())
0 commit comments