Instruction ParseBinOp(BinOpKind op) { DestRegister dst = ParseDestReg (); SrcRegister src1 = ParseSrcReg (); SrcRegister src2 = ParseSrcReg (); return new BinaryOp (op, dst, src1, src2); }
public BinaryOp(BinOpKind op, DestRegister dest, SrcRegister src1, SrcRegister src2) { this.op = op; this.dest = dest; this.src1 = src1; this.src2 = src2; }
internal void EmitBinary(BinOpKind op) { //FIXME if might be an issue if arguments are not of type Vector4f MethodInfo mi = null; switch (op) { case BinOpKind.Add: mi = typeof (Vector4f).GetMethod ("op_Addition"); break; case BinOpKind.Mul: mi = typeof (Vector4f).GetMethod ("op_Multiply"); break; default: throw new Exception ("can't handle binop " + op); } ilgen.Emit (OpCodes.Call, mi); }
/* Given a binary operator EXPRKIND, get the BinOpKind and flags. */ private bool GetBinopKindAndFlags(ExpressionKind ek, out BinOpKind pBinopKind, out EXPRFLAG flags) { flags = 0; switch (ek) { case ExpressionKind.EK_ADD: if (Context.CheckedNormal) { flags |= EXPRFLAG.EXF_CHECKOVERFLOW; } pBinopKind = BinOpKind.Add; break; case ExpressionKind.EK_SUB: if (Context.CheckedNormal) { flags |= EXPRFLAG.EXF_CHECKOVERFLOW; } pBinopKind = BinOpKind.Sub; break; case ExpressionKind.EK_DIV: case ExpressionKind.EK_MOD: // EXPRKIND.EK_DIV and EXPRKIND.EK_MOD need to be treated special for hasSideEffects, // hence the EXPRFLAG.EXF_ASSGOP. Yes, this is a hack. flags |= EXPRFLAG.EXF_ASSGOP; if (Context.CheckedNormal) { flags |= EXPRFLAG.EXF_CHECKOVERFLOW; } pBinopKind = BinOpKind.Mul; break; case ExpressionKind.EK_MUL: if (Context.CheckedNormal) { flags |= EXPRFLAG.EXF_CHECKOVERFLOW; } pBinopKind = BinOpKind.Mul; break; case ExpressionKind.EK_BITAND: case ExpressionKind.EK_BITOR: pBinopKind = BinOpKind.Bitwise; break; case ExpressionKind.EK_BITXOR: pBinopKind = BinOpKind.BitXor; break; case ExpressionKind.EK_LSHIFT: case ExpressionKind.EK_RSHIFT: pBinopKind = BinOpKind.Shift; break; case ExpressionKind.EK_LOGOR: case ExpressionKind.EK_LOGAND: pBinopKind = BinOpKind.Logical; break; case ExpressionKind.EK_LT: case ExpressionKind.EK_LE: case ExpressionKind.EK_GT: case ExpressionKind.EK_GE: pBinopKind = BinOpKind.Compare; break; case ExpressionKind.EK_EQ: case ExpressionKind.EK_NE: pBinopKind = BinOpKind.Equal; break; default: VSFAIL("Bad ek"); pBinopKind = BinOpKind.Add; return false; } return true; }
internal void EmitBinary(BinOpKind op) { //FIXME it might be an issue if arguments are not of type Vector4f MethodInfo mi = null; switch (op) { case BinOpKind.Add: mi = typeof (Vector4f).GetMethod ("op_Addition"); break; case BinOpKind.Sub: mi = typeof (Vector4f).GetMethod ("op_Subtraction"); break; case BinOpKind.Mul: mi = typeof (Vector4f).GetMethod ("op_Multiply"); break; case BinOpKind.Max: mi = typeof (VectorOperations).GetMethod ("Max", new Type[] { typeof (Vector4f), typeof (Vector4f)}); break; case BinOpKind.Dp3: //This is a very f**k'd up code sequence, figure out how to speed it up ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Multiply")); ilgen.Emit (OpCodes.Dup); ilgen.Emit (OpCodes.Dup); //FIXME we could use HorizontalAdd for this step EmitShuffle (ShuffleSel.XFromY); //[x,y,z,w] [x,y,z,w] [y,y,z,w] ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition")); //[x,y,z,w] [x + y,_,_,_] EmitShuffle (ShuffleSel.ZFromY); //[x,y,z,w] [_,_,x + y, _] ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition")); //[_,_, x + y + z, _] EmitShuffle (ShuffleSel.ExpandZ); //[dp3, dp3, dp3, dp3] break; case BinOpKind.Dp4: //We should use things like HorizontalAdd or the new Dp instruction ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Multiply")); ilgen.Emit (OpCodes.Dup); EmitShuffle (ShuffleSel.XFromY | ShuffleSel.ZFromW); //[x,y,z,w] [y,y,w,w] ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition")); //[x + y,_,z + w,_] ilgen.Emit (OpCodes.Dup); //[x + y,_,z + w,_] [x + y,_,z + w,_] EmitShuffle (ShuffleSel.XFromZ); //[x + y,_,_,_] [z + w,_,_,_] ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition")); //[x + y + z + w,_,_,_] EmitShuffle (ShuffleSel.ExpandX); //[dp4, dp4, dp4, dp4] break; case BinOpKind.Min: mi = typeof (VectorOperations).GetMethod ("Min", new Type[] { typeof (Vector4f), typeof (Vector4f)}); break; case BinOpKind.Slt: case BinOpKind.Sge: //XXX hoist the constant out of the loop mi = typeof (VectorOperations).GetMethod ("CompareLessThan", new Type[] { typeof (Vector4f), typeof (Vector4f)}); ilgen.Emit (OpCodes.Ldc_R4, 1f); ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetConstructor (new Type [] {typeof (float) })); if (op == BinOpKind.Slt) ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_BitwiseAnd")); else ilgen.Emit (OpCodes.Call, typeof (VectorOperations).GetMethod ("AndNot", new Type[] { typeof (Vector4f), typeof (Vector4f)})); break; default: throw new Exception ("can't handle binop " + op); } if (mi != null) ilgen.Emit (OpCodes.Call, mi); }