protected IReadable EvaluateToHelper(IReference storage, ActionOnThreeLowRegisters regAction, ActionOnTwoLowRegistersAndAByte byteAction) { var f = FuncBuilder.Instance; using (f.OpenScope("indirectReferenceEval")) { var declarer = f.Declare; var baseStorage = declarer.Int("base"); var offsetStorage = declarer.Int("offset"); var baseResult = baseAddress.EvaluateTo(baseStorage); var offsetResult = offset.EvaluateTo(offsetStorage); var storageReg = storage.ProposeRegisterOrScratch0(); var baseReg = baseResult.ToRegister(f.Scratch0); var offsetRegOrByte = offsetResult.ToRegisterOrUnsignedConstant(exclusiveUpperBoundForConstantOffset, f.Scratch1); if (offsetRegOrByte.IsRegister) { regAction(storageReg, baseReg, offsetRegOrByte.Register); } else { byteAction(storageReg, baseReg, offsetRegOrByte.Byte); } storage.FromRegister(storageReg); return(storage); } }
public static IReadable Invoke(string scopeName, IReference storage, IntExpression lhs, IntExpression rhs, ActionOnThreeLowRegisters registerAction, ActionOnTwoLowRegistersAndAByte byteAction) { var f = FuncBuilder.Instance; using (f.OpenScope(scopeName)) { var sm = new StorageManager(storage); var lhsResult = lhs.EvaluateTo(sm.ForLhs(rhs)); var rhsResult = rhs.EvaluateTo(sm.ForRhs(lhsResult)); var storageReg = storage.ProposeRegisterOrScratch0(); var lhsReg = lhsResult.ToRegister(f.Scratch0); var rhsRegOrByte = rhsResult.ToRegisterOrByte(f.Scratch1); if (rhsRegOrByte.IsRegister) { registerAction(storageReg, lhsReg, rhsRegOrByte.Register); } else { byteAction(storageReg, lhsReg, rhsRegOrByte.Byte); } storage.FromRegister(storageReg); return(storage); } }
protected override IReadable EvaluateToHelper(IReference storage) { var emitter = CodeGenerator.Emitter; var exprResult = expr.EvaluateTo(storage); var storageReg = storage.ProposeRegisterOrScratch0(); var exprReg = exprResult.ToRegister(storageReg); emitter.Emit(OpCodes.Format4OpCode.NEG, storageReg, exprReg); storage.FromRegister(storageReg); return(storage); }
public static void Return(this FuncBuilder f, IntExpression expr) { using(f.OpenScope("return")) { var emitter=CodeGenerator.Emitter; var resultStorage=f.Declare.Int("result"); var exprResult=expr.EvaluateTo(resultStorage); var exprRegOrByte=exprResult.ToRegisterOrByte(f.Scratch0); if(exprRegOrByte.IsRegister) { emitter.EmitRegisterMoveIfDifferent(Register.R0, exprRegOrByte.Register); } else { emitter.Emit(Format3OpCode.MOV, Register.R0, exprRegOrByte.Byte); } BranchLogic.UnconditionalBranchTo(f.TheExitLabel); } }
protected void AssignFromHelper(IntExpression value, ActionOnThreeLowRegisters regAction, ActionOnTwoLowRegistersAndAByte byteAction) { var f = FuncBuilder.Instance; using (f.OpenScope("indirectReferenceAssign")) { var declarer = f.Declare; var valueTemp = declarer.Int("value"); var baseTemp = declarer.Int("baseAddress"); var offsetTemp = declarer.Int("offset"); var valueResult = value.EvaluateTo(valueTemp); var baseResult = baseAddress.EvaluateTo(baseTemp); var offsetResult = offset.EvaluateTo(offsetTemp); //Oh crap. I need three readable registers to accomplish this instruction. //The other instructions only need two registers. //If indeed I do need three scratch registers, I'm going to do the super hack job from hell //(namely, swapping some other register with LR) var baseReg = baseResult.ToRegister(f.Scratch0); var offsetRegOrByte = offsetResult.ToRegisterOrUnsignedConstant(exclusiveUpperBoundForConstantOffset, f.Scratch1); if (offsetRegOrByte.IsRegister) { var offsetReg = offsetRegOrByte.Register; var valuePropReg = ProposeRegisterForValue(valueResult, baseReg, offsetReg); LowRegister valueReg; if (valuePropReg != null) { valueReg = valueResult.ToRegister(valuePropReg); } else { //out of scratch registers. Burn another instruction to do base+=offset so that you can free up offset CodeGenerator.Emitter.Emit(Format2OpCode.ADD, baseReg, offsetReg, 0); //now the register in offsetReg, which is known to be scratch, can be used to hold the value valueReg = valueResult.ToRegister(offsetReg); } regAction(valueReg, baseReg, offsetReg); } else { var valueReg = valueResult.ToRegister(f.Scratch1); byteAction(valueReg, baseReg, offsetRegOrByte.Byte); } } }
public static IReadable Invoke(string scopeName, IReference storage, IntExpression lhs, IntExpression rhs, ActionOnThreeLowRegisters registerAction, ActionOnTwoLowRegistersAndAByte byteAction) { var f=FuncBuilder.Instance; using(f.OpenScope(scopeName)) { var sm=new StorageManager(storage); var lhsResult=lhs.EvaluateTo(sm.ForLhs(rhs)); var rhsResult=rhs.EvaluateTo(sm.ForRhs(lhsResult)); var storageReg=storage.ProposeRegisterOrScratch0(); var lhsReg=lhsResult.ToRegister(f.Scratch0); var rhsRegOrByte=rhsResult.ToRegisterOrByte(f.Scratch1); if(rhsRegOrByte.IsRegister) { registerAction(storageReg, lhsReg, rhsRegOrByte.Register); } else { byteAction(storageReg, lhsReg, rhsRegOrByte.Byte); } storage.FromRegister(storageReg); return storage; } }
protected void AssignFromHelper(IntExpression value, ActionOnThreeLowRegisters regAction, ActionOnTwoLowRegistersAndAByte byteAction) { var f=FuncBuilder.Instance; using(f.OpenScope("indirectReferenceAssign")) { var declarer=f.Declare; var valueTemp=declarer.Int("value"); var baseTemp=declarer.Int("baseAddress"); var offsetTemp=declarer.Int("offset"); var valueResult=value.EvaluateTo(valueTemp); var baseResult=baseAddress.EvaluateTo(baseTemp); var offsetResult=offset.EvaluateTo(offsetTemp); //Oh crap. I need three readable registers to accomplish this instruction. //The other instructions only need two registers. //If indeed I do need three scratch registers, I'm going to do the super hack job from hell //(namely, swapping some other register with LR) var baseReg=baseResult.ToRegister(f.Scratch0); var offsetRegOrByte=offsetResult.ToRegisterOrUnsignedConstant(exclusiveUpperBoundForConstantOffset, f.Scratch1); if(offsetRegOrByte.IsRegister) { var offsetReg=offsetRegOrByte.Register; var valuePropReg=ProposeRegisterForValue(valueResult, baseReg, offsetReg); LowRegister valueReg; if(valuePropReg!=null) { valueReg=valueResult.ToRegister(valuePropReg); } else { //out of scratch registers. Burn another instruction to do base+=offset so that you can free up offset CodeGenerator.Emitter.Emit(Format2OpCode.ADD, baseReg, offsetReg, 0); //now the register in offsetReg, which is known to be scratch, can be used to hold the value valueReg=valueResult.ToRegister(offsetReg); } regAction(valueReg, baseReg, offsetReg); } else { var valueReg=valueResult.ToRegister(f.Scratch1); byteAction(valueReg, baseReg, offsetRegOrByte.Byte); } } }