func (mach X86) ConversionOp(code gen.RegCoder, oper uint16, resultType types.T, source values.Operand) (result values.Operand) { if oper == opers.Wrap { source.Type = types.I32 // short mov; useful zeroExt flag reg, zeroExt := mach.opMaybeResultReg(code, source, false) return values.TempRegOperand(resultType, reg, zeroExt) } reg, zeroExt := mach.opMaybeResultReg(code, source, false) // TODO: for int<->float ops: borrow source reg, allocate target reg switch oper { case opers.ExtendS: Movsxd.opFromReg(code, 0, reg, reg) result = values.TempRegOperand(resultType, reg, false) case opers.ExtendU: if !zeroExt { Mov.opFromReg(code, types.I32, reg, reg) } result = values.TempRegOperand(resultType, reg, false) case opers.Mote: Cvts2sSSE.opFromReg(code, source.Type, reg, reg) result = values.TempRegOperand(resultType, reg, false) case opers.TruncS: panic(fmt.Errorf("%s.trunc_s/%s not implemented", resultType, source.Type)) case opers.TruncU: panic(fmt.Errorf("%s.trunc_u/%s not implemented", resultType, source.Type)) case opers.ConvertS: Cvtsi2sSSE.opReg(code, resultType, source.Type, regResult, reg) code.FreeReg(source.Type, reg) result = values.TempRegOperand(resultType, regResult, false) case opers.ConvertU: if source.Type == types.I32 { if !zeroExt { Mov.opFromReg(code, types.I32, reg, reg) } Cvtsi2sSSE.opReg(code, resultType, types.I64, regResult, reg) } else { mach.opConvertUnsignedI64ToFloat(code, resultType, reg) } code.FreeReg(source.Type, reg) result = values.TempRegOperand(resultType, regResult, false) case opers.Reinterpret: if source.Type.Category() == types.Int { MovSSE.opFromReg(code, source.Type, regResult, reg) } else { MovSSE.opToReg(code, source.Type, regResult, reg) } code.FreeReg(source.Type, reg) result = values.TempRegOperand(resultType, regResult, true) } return }
func (mach X86) binaryShiftOp(code gen.RegCoder, index uint8, a, b values.Operand) values.Operand { insn := binaryShiftInsns[index] var targetReg regs.R switch b.Storage { case values.Imm: targetReg, _ = mach.opMaybeResultReg(code, a, true) insn.imm.op(code, b.Type, targetReg, uint8(b.ImmValue())) default: if b.Storage.IsReg() && b.Reg() == regShiftCount { targetReg, _ = mach.opMaybeResultReg(code, a, false) defer code.Discard(b) } else { if code.RegAllocated(types.I32, regShiftCount) { targetReg, _ = mach.opMaybeResultReg(code, a, true) if targetReg == regShiftCount { Mov.opFromReg(code, a.Type, regResult, regShiftCount) targetReg = regResult defer code.FreeReg(types.I32, regShiftCount) } else { // unknown operand in regShiftCount Mov.opFromReg(code, types.I64, regScratch, regShiftCount) defer Mov.opFromReg(code, types.I64, regShiftCount, regScratch) } } else { code.AllocSpecificReg(types.I32, regShiftCount) defer code.FreeReg(types.I32, regShiftCount) targetReg, _ = mach.opMaybeResultReg(code, a, true) } b.Type = types.I32 // TODO: 8-bit mov mach.OpMove(code, regShiftCount, b, false) } insn.opReg(code, a.Type, targetReg) } return values.TempRegOperand(a.Type, targetReg, true) }