Beispiel #1
0
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))

}
Beispiel #2
0
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)
		}
	}
}
Beispiel #3
0
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
}