private void RetInstr(OptimizationToken tkn) { Emitter.AddRegConst(AssemRegisters.Rsp, LocalTopSize); if (tkn.Parameters.Length == 1) { Emitter.MovRegisterToRegisterRelativeAddress(tkn.ParameterRegisters[0], AssemRegisters.Rsp, MachineSpec.PointerSize); } else if (tkn.Parameters.Length != 0) { throw new Exception("Unexpected parameter count."); } Emitter.Ret(); }
private void CallInstr(OptimizationToken[] tkns, int idx) { var tkn = tkns[idx]; switch (tkn.Strings[0]) { case "mthd_s_MSIL2ASM_Builtins_x86_64_Halt_0System_Void_r_": Emitter.Hlt(); return; case "mthd_s_MSIL2ASM_Builtins_x86_64_Sti_0System_Void_r_": Emitter.Sti(); return; case "mthd_s_MSIL2ASM_Builtins_x86_64_Cli_0System_Void_r_": Emitter.Cli(); return; case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_UInt32_2System_Void_r_": case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_Int32_2System_Void_r_": OutOp(tkn, 4); return; case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_UInt16_2System_Void_r_": case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_Int16_2System_Void_r_": OutOp(tkn, 2); return; case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_Byte_2System_Void_r_": case "mthd_s_MSIL2ASM_Builtins_x86_64_Out_0System_UInt16_1System_SByte_2System_Void_r_": OutOp(tkn, 1); return; case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_UInt32_$addr_o_2System_Void_r_": case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_UInt16_$addr_o_2System_Void_r_": case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_Byte_$addr_o_2System_Void_r_": case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_Int32_$addr_o_2System_Void_r_": case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_Int16_$addr_o_2System_Void_r_": case "mthd_s_MSIL2ASM_Builtins_x86_64_In_0System_UInt16_1System_SByte_$addr_o_2System_Void_r_": InOp(tkn); return; } //Emit extern if (!tkn.Strings[0].Contains(prefix) && !externals.Contains(tkn.Strings[0])) { externals.Add(tkn.Strings[0]); } if (tkn.Strings[0] == "ctor_System_Object_0System_Object_i_1System_Object_r_" && !externals.Contains(tkn.Strings[0])) { externals.Add(tkn.Strings[0]); } //Determine active registers, save them var activeRegs = GetActiveRegistersInclusive(tkns, idx).ToList(); if (tkn.ResultRegisters.Length == 1 && activeRegs.Contains(tkn.ResultRegisters[0])) { activeRegs.Remove(tkn.ResultRegisters[0]); } for (int i = 0; i < activeRegs.Count; i++) { Emitter.Push(activeRegs[i]); } //Push arguments onto stack for (int i = tkn.Parameters.Length - 1; i >= 0; i--) //for (int i = 0; i < tkn.Parameters.Length; i++) { if (tkn.Parameters[i].ParameterLocation == OptimizationParameterLocation.Const) { Emitter.MovConstantToRegisterSize(tkn.Parameters[i].Value, tkn.ParameterRegisters[i], tkn.Parameters[i].Size); } Emitter.Push(tkn.ParameterRegisters[i]); } //Push return value onto stack Emitter.Push(AssemRegisters.R10); //Emit call instruction Emitter.CallLabel(tkn.Strings[0]); //Pop return value from stack if (tkn.ResultRegisters.Length == 1) { Emitter.Pop(tkn.ResultRegisters[0]); } //Remove arguments from stack Emitter.AddRegConst(AssemRegisters.Rsp, tkn.Parameters.Length * MachineSpec.PointerSize + ((tkn.ResultRegisters.Length == 1) ? 0 : MachineSpec.PointerSize)); //Restore active registers for (int i = 0; i < activeRegs.Count; i++) { Emitter.Pop(activeRegs[i]); } }