public void TestResolveLabel_Backward() { target.Emit(target.AsmOne("addi $3, $0, 5")); target.Emit(target.AsmOne("addi $3, $0, 5")); target.Emit(target.AsmOne("addi $3, $0, 5")); target.AsmOne("hoge:"); target.Emit(target.AsmOne("addi $3, $0, 5")); target.Emit(target.AsmOne("j hoge")); target.ResolveLabel(); Assert.AreEqual("08000003", target.binStore.bins[4]); target.Clear(); }
protected void BitwiseArithmetic(Register aRegister, string aOpBitwise, object aValue) { OpCode xOpCode = GetBitwiseOpCode(aOpBitwise); switch (aValue) { case Register xRegister: Asm.Emit(xOpCode, aRegister, xRegister); break; case uint xNum: Asm.Emit(xOpCode, aRegister, xNum); break; case string xString: string xValue = Compiler.GetFullName($"Const_{xString}"); Asm.Emit(xOpCode, aRegister, xValue); break; case x86.Params.Address xAddress: xAddress.AddPrefix(Compiler.CurrentNamespace); Asm.Emit(xOpCode, aRegister, xAddress); break; default: throw new Exception($"Unknown bitwise operand type."); } }
protected void VariableAssignment(Address aVariableName, string aOpEquals, object aValue) { // TODO: Do this better? Use Compiler.GetFullName() so things are consistent. aVariableName.AddPrefix(Compiler.CurrentNamespace); string size; switch (aValue) { case uint _: size = "dword"; Asm.Emit(OpCode.Mov, size, aVariableName, aValue); break; case Register aValueReg: size = aValueReg.RegSize; Asm.Emit(OpCode.Mov, size, aVariableName, aValue); break; case string _: //TODO: verify this aValue = Compiler.GetFullName($"Const_{aValue}"); Asm.Emit(OpCode.Mov, aVariableName, aValue); break; } }
protected void RegMathVar(Register aReg, string aOpMath, Address aVal) { switch (aOpMath) { case "+=": Asm.Emit(OpCode.Add, aReg, aReg.RegSize, aVal.AddPrefix($"{Compiler.CurrentNamespace}_")); break; case "-=": Asm.Emit(OpCode.Sub, aReg, aReg.RegSize, aVal.AddPrefix($"{Compiler.CurrentNamespace}_")); break; case "*=": Asm.Emit(OpCode.Mul, aReg, aReg.RegSize, aVal.AddPrefix($"{Compiler.CurrentNamespace}_")); break; case "/=": Asm.Emit(OpCode.Div, aReg, aReg.RegSize, aVal.AddPrefix($"{Compiler.CurrentNamespace}_")); break; case "%=": Asm.Emit(OpCode.Rem, aReg, aReg.RegSize, aVal.AddPrefix($"{Compiler.CurrentNamespace}_")); break; default: throw new Exception("Unsupported math operator"); } }
protected void RegMathConst(Register aReg, string aOpMath, string aVal) { switch (aOpMath) { case "+=": Asm.Emit(OpCode.Add, aReg, $"{Compiler.CurrentNamespace}_Const_{aVal}"); break; case "-=": Asm.Emit(OpCode.Sub, aReg, $"{Compiler.CurrentNamespace}_Const_{aVal}"); break; case "*=": Asm.Emit(OpCode.Mul, aReg, $"{Compiler.CurrentNamespace}_Const_{aVal}"); break; case "/=": Asm.Emit(OpCode.Div, aReg, $"{Compiler.CurrentNamespace}_Const_{aVal}"); break; case "%=": Asm.Emit(OpCode.Rem, aReg, $"{Compiler.CurrentNamespace}_Const_{aVal}"); break; default: throw new Exception("Unsupported math operator"); } }
protected void PortOut(string aPortKeyword, string aOpOpenBracket, Register aPortReg, string aOpCloseBracket, string aOpEquals, Register aSrcReg) { aPortReg.CheckIsDX(); aSrcReg.CheckIsAccumulator(); Asm.Emit(OpCode.Out, aPortReg, aSrcReg); }
protected void PortIn(Register aDestReg, string aOpEquals, string aPortKeyword, string aOpOpenBracket, Register aPortReg, string aOpCloseBracket) { aDestReg.CheckIsAccumulator(); aPortReg.CheckIsDX(); Asm.Emit(OpCode.In, aDestReg, aPortReg); }
protected void RegMathVar(Register aReg, string aOpMath, Address aVal) { // TODO: Do this better? Use Compiler.GetFullName() so things are consistent. aVal.AddPrefix(Compiler.CurrentNamespace); switch (aOpMath) { case "+=": Asm.Emit(OpCode.Add, aReg, aReg.RegSize, aVal); break; case "-=": Asm.Emit(OpCode.Sub, aReg, aReg.RegSize, aVal); break; case "*=": Asm.Emit(OpCode.Mul, aReg, aReg.RegSize, aVal); break; case "/=": Asm.Emit(OpCode.Div, aReg, aReg.RegSize, aVal); break; case "%=": Asm.Emit(OpCode.Rem, aReg, aReg.RegSize, aVal); break; default: throw new Exception("Unsupported math operator"); } }
[Emitter(typeof(Reg32), typeof(OpMath), typeof(Int32u))] // EAX += 1 protected void RegMathNum(Register aDestReg, string aOpMath, object aVal) { switch (aOpMath) { case "+=": Asm.Emit(OpCode.Add, aDestReg, aVal); break; case "-=": Asm.Emit(OpCode.Sub, aDestReg, aVal); break; case "*=": Asm.Emit(OpCode.Mul, aDestReg, aVal); break; case "/=": Asm.Emit(OpCode.Div, aDestReg, aVal); break; case "%=": Asm.Emit(OpCode.Rem, aDestReg, aVal); break; default: throw new Exception("Unsupported math operator"); } }
protected void BitwiseArithmetic(Register aRegister, string aOpBitwise, string aValue) { OpCode xOpCode = GetBitwiseOpCode(aOpBitwise); string xValue = Compiler.GetFullName(aValue); Asm.Emit(xOpCode, aRegister, xValue); }
protected void IfRegisterConditionRegisterReturn(string aOpIf, Register aRegister, string aOpCompare, object aValue, object aOpReturn) { var xJumpOpCode = GetJumpOpCode(aOpCompare); Asm.Emit(OpCode.Cmp, aRegister, aValue); Asm.Emit(xJumpOpCode, Compiler.CurrentFunctionExitLabel); }
protected void RegMathConst(Register aReg, string aOpMath, string aVal) { string xConstName = Compiler.GetFullName($"Const_{aVal}"); switch (aOpMath) { case "+=": Asm.Emit(OpCode.Add, aReg, xConstName); break; case "-=": Asm.Emit(OpCode.Sub, aReg, xConstName); break; case "*=": Asm.Emit(OpCode.Mul, aReg, xConstName); break; case "/=": Asm.Emit(OpCode.Div, aReg, xConstName); break; case "%=": Asm.Emit(OpCode.Rem, aReg, xConstName); break; default: throw new Exception("Unsupported math operator"); } }
protected void IfSizeRegisterConditionVariableReturn(string aOpIf, string aSize, Register aRegister, string aOpCompare, Address aValue, object aOpReturn) { var xJumpOpCode = GetJumpOpCode(aOpCompare); aValue.AddPrefix(Compiler.CurrentNamespace); Asm.Emit(OpCode.Cmp, aSize, aRegister, aValue); Asm.Emit(xJumpOpCode, Compiler.CurrentFunctionExitLabel); }
protected void IfRegisterConditionConst(string aOpIf, Register aRegister, string aOpCompare, object aValue, object aOpOpenBrace) { Compiler.Blocks.StartBlock(Compiler.BlockType.If); var xJumpOpCode = GetOppositeJumpOpCode(aOpCompare); Asm.Emit(OpCode.Cmp, aRegister, aValue); Asm.Emit(xJumpOpCode, Compiler.Blocks.EndBlockLabel); }
protected void IfRegisterConditionVariableAddressReturn(string aOpIf, Register aRegister, string aOpCompare, string aValue, object aOpReturn) { var xJumpOpCode = GetJumpOpCode(aOpCompare); string xValue = Compiler.GetFullName(aValue); Asm.Emit(OpCode.Cmp, aRegister, xValue); Asm.Emit(xJumpOpCode, Compiler.CurrentFunctionExitLabel); }
protected void IfRegisterConditionVariable(string aOpIf, Register aRegister, string aOpCompare, Address aValue, object aOpOpenBrace) { Compiler.Blocks.StartBlock(Compiler.BlockType.If); var xJumpOpCode = GetOppositeJumpOpCode(aOpCompare); aValue.AddPrefix(Compiler.CurrentNamespace); Asm.Emit(OpCode.Cmp, aRegister, aValue); Asm.Emit(xJumpOpCode, Compiler.Blocks.EndBlockLabel); }
protected void IfRegisterConditionVariableAddress(string aOpIf, Register aRegister, string aOpCompare, string aValue, object aOpOpenBrace) { Compiler.Blocks.StartBlock(Compiler.BlockType.If); var xJumpOpCode = GetOppositeJumpOpCode(aOpCompare); string xValue = Compiler.GetFullName(aValue); Asm.Emit(OpCode.Cmp, aRegister, xValue); Asm.Emit(xJumpOpCode, Compiler.Blocks.EndBlockLabel); }
protected void IfRegisterConditionIntGoto(string aOpIf, Register aRegister, string aOpCompare, object aValue, string aGotoKeyword, string aLabel) { var xJumpOpCode = GetJumpOpCode(aOpCompare); Asm.Emit(OpCode.Cmp, aRegister, aValue); string xLabel = Compiler.GetFullName(aLabel, true); Asm.Emit(xJumpOpCode, xLabel); }
protected void ZeroParamOp(OpCode aOpCode) { if (aOpCode == OpCode.Ret && Compiler.Blocks.Current()?.Type == Compiler.BlockType.If) { Asm.Emit(OpCode.Jmp, Compiler.CurrentFunctionExitLabel); return; } Asm.Emit(aOpCode); }
protected void IfRegisterConditionVariable(string aOpIf, Register aRegister, string aOpCompare, Address aValue, string aGotoKeyword, string aLabel) { var xJumpOpCode = GetJumpOpCode(aOpCompare); aValue.AddPrefix(Compiler.CurrentNamespace); Asm.Emit(OpCode.Cmp, aRegister, aValue); string xLabel = Compiler.GetFullName(aLabel, true); Asm.Emit(xJumpOpCode, xLabel); }
protected void IfSizeAdressConditionConst(string aOpIf, string aSize, Address aAdress, string aOpCompare, string aConstant, object aOpOpenBrace) { Compiler.Blocks.StartBlock(Compiler.BlockType.If); var xJumpOpCode = GetOppositeJumpOpCode(aOpCompare); aAdress.AddPrefix(Compiler.CurrentNamespace); string xConstant = Compiler.GetFullName($"Const_{aConstant}"); Asm.Emit(OpCode.Cmp, aSize, aAdress, xConstant); Asm.Emit(xJumpOpCode, Compiler.Blocks.EndBlockLabel); }
protected void IncrementDecrementRegister(Register aRegister, string aOpIncrementDecrement) { switch (aOpIncrementDecrement) { case "++": Asm.Emit(OpCode.Inc, aRegister); break; case "--": Asm.Emit(OpCode.Dec, aRegister); break; default: throw new Exception("Unsupported increment decrement operator"); } }
protected void RotateRegister(Register aRegister, object aOpRotate, object aNumBits) { switch (aOpRotate) { case "<~": Asm.Emit(OpCode.Rol, aRegister, aNumBits); break; case "~>": Asm.Emit(OpCode.Ror, aRegister, aNumBits); break; default: throw new Exception("Unsupported rotate operator"); } }
protected void ShiftRegister(Register aRegister, string aOpShift, object aNumBits) { switch (aOpShift) { case "<<": Asm.Emit(OpCode.Shl, aRegister, aNumBits); break; case ">>": Asm.Emit(OpCode.Shr, aRegister, aNumBits); break; default: throw new Exception("Unsupported shift operator"); } }
protected void BlockEnd(string opCloseBrace) { var xBlock = Compiler.Blocks.Current(); if (xBlock != null) { switch (xBlock.Type) { case Compiler.BlockType.If: case Compiler.BlockType.While: case Compiler.BlockType.Repeat: Compiler.Blocks.EndBlock(); break; } } else { // No current block. Must be a function or interrupt. if (!Compiler.FunctionExitLabelFound) { // Need to emit an 'Exit:' label. Compiler.WriteLine($"{Compiler.CurrentFunctionExitLabel}:"); } Asm.Emit(OpCode.Mov, "dword", new x86.Params.Address("INTS_LastKnownAddress"), Compiler.CurrentFunctionExitLabel); switch (Compiler.CurrentFunctionType) { case Compiler.BlockType.Function: Asm.Emit(OpCode.Ret); break; case Compiler.BlockType.Interrupt: Asm.Emit(OpCode.IRet); break; } Compiler.CurrentFunction = ""; Compiler.CurrentFunctionType = Compiler.BlockType.None; Compiler.Blocks.Reset(); } }
protected void VariableAssignment(Address aVariableName, string aOpEquals, object aValue) { string size; switch (aValue) { case uint _: size = "dword"; Asm.Emit(OpCode.Mov, size, aVariableName.AddPrefix(Compiler.GetPrefixForVar), aValue); break; case Register aValueReg: size = aValueReg.RegSize; Asm.Emit(OpCode.Mov, size, aVariableName.AddPrefix(Compiler.GetPrefixForVar), aValue); break; case string _: //TODO: verify this aValue = $"{Compiler.GetPrefixForConst}{aValue}"; Asm.Emit(OpCode.Mov, aVariableName.AddPrefix(Compiler.GetPrefixForVar), aValue); break; } }
protected void ZeroParamOp(OpCode aOpCode) { Asm.Emit(aOpCode); }
protected void Goto(string aGotoKeyword, string aLabelName) { string xLabelName = Compiler.GetFullName(aLabelName, true); Asm.Emit(OpCode.Jmp, $"{xLabelName}"); }
protected void PopAddr(string aOpPlus, string value) { Asm.Emit(OpCode.Pop, $"{Compiler.CurrentNamespace}_{value}"); }
protected void PopVar(string aOpPlus, Address value) { // TODO: Do this better? Use Compiler.GetFullName() so things are consistent. value.AddPrefix(Compiler.CurrentNamespace); Asm.Emit(OpCode.Pop, value); }