コード例 #1
0
ファイル: x86.go プロジェクト: tsavola/wag
// opBorrowMaybeResultReg returns either the register of the given operand, or
// the reserved result register with the value of the operand.
func (mach X86) opBorrowMaybeResultReg(code gen.RegCoder, x values.Operand, preserveFlags bool) (reg regs.R, zeroExt, own bool) {
	if x.Storage == values.VarReg {
		reg = x.Reg()
		zeroExt = x.RegZeroExt()
	} else {
		reg, zeroExt = mach.opMaybeResultReg(code, x, preserveFlags)
		own = (reg != regResult)
	}
	return
}
コード例 #2
0
ファイル: x86.go プロジェクト: tsavola/wag
// opBorrowMaybeScratchReg returns either the register of the given operand, or
// the reserved scratch register with the value of the operand.
func (mach X86) opBorrowMaybeScratchReg(code gen.Coder, x values.Operand, preserveFlags bool) (reg regs.R, zeroExt, own bool) {
	if x.Storage.IsReg() {
		reg = x.Reg()
		zeroExt = x.RegZeroExt()
	} else {
		reg = regScratch
		zeroExt = mach.OpMove(code, reg, x, preserveFlags)
	}
	own = (x.Storage == values.TempReg)
	return
}
コード例 #3
0
ファイル: x86.go プロジェクト: tsavola/wag
// opMaybeResultReg returns either the register of the given operand, or the
// reserved result register with the value of the operand.  The caller has
// exclusive ownership of the register.
func (mach X86) opMaybeResultReg(code gen.RegCoder, x values.Operand, preserveFlags bool) (reg regs.R, zeroExt bool) {
	if x.Storage == values.TempReg {
		reg = x.Reg()
		zeroExt = x.RegZeroExt()
	} else {
		var ok bool

		reg, ok = code.TryAllocReg(x.Type)
		if !ok {
			reg = regResult
		}

		if x.Storage != values.Nowhere {
			mach.OpMove(code, reg, x, preserveFlags)
			zeroExt = true
		}
	}
	return
}
コード例 #4
0
ファイル: x86.go プロジェクト: tsavola/wag
// OpMove must not update CPU's condition flags if preserveFlags is set.
//
// X86 implementation note: must not blindly rely on regScratch or regResult in
// this function because we may be moving to one of them.
func (mach X86) OpMove(code gen.Coder, targetReg regs.R, x values.Operand, preserveFlags bool) (zeroExt bool) {
	switch x.Type.Category() {
	case types.Int:
		switch x.Storage {
		case values.Imm:
			if value := x.ImmValue(); value == 0 && !preserveFlags {
				Xor.opFromReg(code, types.I32, targetReg, targetReg)
			} else {
				MovImm64.op(code, x.Type, targetReg, value)
			}
			zeroExt = true

		case values.VarMem:
			Mov.opFromStack(code, x.Type, targetReg, x.VarMemOffset())
			zeroExt = true

		case values.VarReg:
			if sourceReg := x.Reg(); sourceReg != targetReg {
				Mov.opFromReg(code, x.Type, targetReg, sourceReg)
				zeroExt = true
			}

		case values.TempReg:
			if sourceReg := x.Reg(); sourceReg != targetReg {
				Mov.opFromReg(code, x.Type, targetReg, sourceReg)
				zeroExt = true
			} else if targetReg == regResult {
				zeroExt = x.RegZeroExt()
			} else {
				panic("moving temporary integer register to itself")
			}

		case values.Stack:
			Pop.op(code, targetReg)

		case values.ConditionFlags:
			if x.Type != types.I32 {
				panic(x)
			}

			var end links.L

			cond := x.Condition()
			setcc := conditionInsns[cond].setcc

			switch {
			case cond >= values.MinUnorderedOrCondition:
				MovImm.opImm(code, x.Type, targetReg, 1) // true
				Jp.rel8.opStub(code)                     // if unordered, else
				end.AddSite(code.Len())                  //
				setcc.opReg(code, targetReg)             // cond

			case cond >= values.MinOrderedAndCondition:
				MovImm.opImm(code, x.Type, targetReg, 0) // false
				Jp.rel8.opStub(code)                     // if unordered, else
				end.AddSite(code.Len())                  //
				setcc.opReg(code, targetReg)             // cond

			default:
				setcc.opReg(code, targetReg)
				Movzx8.opFromReg(code, x.Type, targetReg, targetReg)
			}

			end.Addr = code.Len()
			mach.updateBranches8(code, &end)

			zeroExt = true

		default:
			panic(x)
		}

	case types.Float:
		switch x.Storage {
		case values.Imm:
			if value := x.ImmValue(); value == 0 {
				PxorSSE.opFromReg(code, x.Type, targetReg, targetReg)
			} else {
				MovImm64.op(code, x.Type, regScratch, value) // integer scratch register
				MovSSE.opFromReg(code, x.Type, targetReg, regScratch)
			}

		case values.VarMem:
			MovsSSE.opFromStack(code, x.Type, targetReg, x.VarMemOffset())

		case values.VarReg:
			if sourceReg := x.Reg(); sourceReg != targetReg {
				MovsSSE.opFromReg(code, x.Type, targetReg, sourceReg)
			}

		case values.TempReg:
			if sourceReg := x.Reg(); sourceReg != targetReg {
				MovsSSE.opFromReg(code, x.Type, targetReg, sourceReg)
			} else if targetReg != regResult {
				panic("moving temporary float register to itself")
			}

		case values.Stack:
			popFloatOp(code, x.Type, targetReg)

		default:
			panic(x)
		}

	default:
		panic(x)
	}

	code.Consumed(x)

	return
}