func (v Target) genIntBinOp(a *allocator, instr *ssa.BinOp, opIndex int) { ops := ssa.GetOperands(instr) sz := TypeSizeInBits(ops[0].Type()) suffix := sizeSuffixBits(sz) rax := regToSize("rax", sz) rcx := regToSize("rcx", sz) v.moveIntToReg(a, ops[0], rax) v.moveIntToReg(a, ops[1], rcx) switch instr.BinOpType() { case ssa.BinOpAdd, ssa.BinOpSub, ssa.BinOpAnd, ssa.BinOpOr, ssa.BinOpXor: v.wop("%s%s #%s, #%s", binOpIntOpStrs[opIndex], suffix, rcx, rax) case ssa.BinOpMul: v.wop("mul%s #%s", suffix, rcx) case ssa.BinOpShl, ssa.BinOpAShr, ssa.BinOpLShr: v.wop("%s%s #cl, #%s", binOpIntOpStrs[opIndex], suffix, rax) default: panic("unim") } if sz == 1 { v.wop("andq $1, #%s", rax) } v.wop("mov%s #%s, %s", suffix, rax, a.valStr(instr)) }
func (v Target) genBinOp(a *allocator, instr *ssa.BinOp) { checkTypeSupported(instr.Type()) //floatOps := []ssa.BinOpType{ssa.BinOpFAdd, ssa.BinOpFSub, ssa.BinOpFMul, ssa.BinOpFDiv, ssa.BinOpFRem} for i, intOp := range binOpIntOps { if instr.BinOpType() == intOp { v.genIntBinOp(a, instr, i) } } }
func checkBinOp(instr *ssa.BinOp) error { ops := ssa.GetOperands(instr) if err := errIfMismatchedTypes(ops[0].Type(), ops[1].Type(), instr); err != nil { return err } switch instr.BinOpType() { case ssa.BinOpAdd, ssa.BinOpSub, ssa.BinOpMul, ssa.BinOpSDiv, ssa.BinOpUDiv, ssa.BinOpSRem, ssa.BinOpURem, ssa.BinOpShl, ssa.BinOpLShr, ssa.BinOpAShr, ssa.BinOpAnd, ssa.BinOpOr, ssa.BinOpXor: _, ok := ops[0].Type().(*types.Int) if !ok { return &InstrError{ Instr: instr, Message: "`" + instr.BinOpType().String() + "` requires int", } } case ssa.BinOpFAdd, ssa.BinOpFSub, ssa.BinOpFMul, ssa.BinOpFDiv, ssa.BinOpFRem: _, ok := ops[0].Type().(*types.Float) if !ok { return &InstrError{ Instr: instr, Message: "`" + instr.BinOpType().String() + "` requires float", } } default: panic("unim") } return nil }