public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { int stackOffset = 0x40; //$BUG: look this up! ccr.LowLevelDetails(arch.WordWidth.Size, stackOffset); if (dtRet != null) { SetReturnRegister(ccr, dtRet); } int fr = 0; int gr = 0; for (int i = 0; i < dtParams.Count; ++i) { var dtArg = dtParams[i]; var prim = dtArg as PrimitiveType; if (prim != null && prim.Domain == Domain.Real) { if (fr > 8) { ccr.StackParam(dtArg); } else { ccr.RegParam(fregs[fr]); ++fr; } } else if (dtArg.Size <= 4) { if (gr >= iregs.Length) { ccr.StackParam(dtArg); } else { ccr.RegParam(iregs[gr]); ++gr; } } else if (dtArg.Size <= 8) { if (gr >= iregs.Length - 1) { ccr.StackParam(dtArg); } else { if ((gr & 1) == 1) { ++gr; } ccr.SequenceParam(iregs[gr], iregs[gr + 1]); gr += 2; } } else { throw new NotImplementedException(); } } }
public void SetReturnRegisters(ICallingConventionEmitter ccr, DataType dtRet) { //$TODO: use dtRet? ccr.RegReturn(arch.GetRegister("r0") !); }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { /* * To find the register where a function argument is passed, initialize the register number * Rn with R26 and follow this procedure: * * If the argument size is an odd number of bytes, round up the size to the next even number. * Subtract the rounded size from the register number Rn. * * If the new Rn is at least R8 and the size of the object is non-zero, then the low-byte of * the argument is passed in Rn. Subsequent bytes of the argument are passed in the subsequent * registers, i.e. in increasing register numbers. * * If the new register number Rn is smaller than R8 or the size of the argument is zero, the * argument will be passed in memory. * * If the current argument is passed in memory, stop the procedure: All subsequent arguments * will also be passed in memory. * If there are arguments left, goto 1. and proceed with the next argument. * * Return values with a size of 1 byte up to and including a size of 8 bytes will be returned * in registers. Return values whose size is outside that range will be returned in memory. * If a return value cannot be returned in registers, the caller will allocate stack space and * pass the address as implicit first pointer argument to the callee. The callee will put the * return value into the space provided by the caller. * * If the return value of a function is returned in registers, the same registers are used as * if the value was the first parameter of a non-varargs function. For example, an 8-bit value is returned in R24 and an 32-bit value is returned R22...R25. * Arguments of varargs functions are passed on the stack. This applies even to the named arguments. */ ccr.LowLevelDetails(1, 2); if (dtRet != null && dtRet != VoidType.Instance) { GenerateReturnValue(dtRet, ccr); } int iReg = 26; foreach (var dtParam in dtParams) { int size = dtParam.Size; if ((size & 1) != 0) // odd sized register occupies two regs { // Round size to even # of bytes. size = dtParam.Size + 1; } iReg -= size; if (iReg >= 8) { var reg = argRegs[iReg - 8]; if (dtParam.Size == 1) { ccr.RegParam(reg); continue; } SequenceStorage seq = null; for (int r = iReg + 1, i = 1; i < dtParam.Size; ++i, ++r) { var regNext = argRegs[r - 8]; if (seq != null) { seq = new SequenceStorage(PrimitiveType.CreateWord(regNext.DataType.BitSize + seq.DataType.BitSize), regNext, seq); } else { seq = new SequenceStorage(PrimitiveType.CreateWord(regNext.DataType.BitSize + reg.DataType.BitSize), regNext, reg); } } ccr.SequenceParam(seq); } else { ccr.StackParam(dtParam); } } }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(8, 0x0040); int iReg = 0; int iFloat = 0; int iStackOffset = 0; var adjusted = PrepadExtendParameters(dtParams); foreach (var(dom, bs) in adjusted) { var byteSize = bs; if (dom == Domain.Real) { if (dom == Domain.Real && iFloat < floatRegs.Length) { ccr.RegParam(floatRegs[iFloat]); ++iFloat; } else { // HFA / HVA's not supported yet. if (byteSize >= 8) { iStackOffset = AlignUp(iStackOffset, Math.Max(8, byteSize)); } if (byteSize < 8) { byteSize = 8; } ccr.StackParam(PrimitiveType.CreateWord(byteSize * 8)); } } else { if (byteSize <= 8 && iReg < argRegs.Length) { ccr.RegParam(argRegs[iReg]); ++iReg; } else if (byteSize == 16 && iReg < argRegs.Length - 1 && (iReg & 1) == 1) { ++iReg; if (iReg < argRegs.Length - 1) { ccr.SequenceParam(argRegs[iReg], argRegs[iReg + 1]); iReg += 2; } } else if (byteSize <= (8 - iReg) * 8) { throw new NotImplementedException("Need to allow arbitrary sequences of regs"); } else { iReg = 8; if (byteSize >= 8) { iStackOffset = AlignUp(iStackOffset, Math.Max(8, byteSize)); } if (byteSize < 8) { byteSize = 8; } ccr.StackParam(PrimitiveType.CreateWord(byteSize * 8)); } } } if (dtRet != null) { if (dtRet is PrimitiveType pt && pt.Domain == Domain.Real) { if (pt.Size < 8) { ccr.RegReturn(floatRegs[0]); } else if (pt.Size < 16) { ccr.SequenceReturn(floatRegs[1], floatRegs[0]); } else { throw new NotImplementedException(); } } else if (dtRet != null) { if (dtRet.Size <= 8) { ccr.RegReturn(argRegs[0]); } else if (dtRet.Size <= 16) { ccr.SequenceReturn(argRegs[1], argRegs[0]); } else { throw new NotImplementedException(); } } }
public void Setup() { this.arch = new RiscVArchitecture(new ServiceContainer(), "riscV"); this.cc = new RiscVCallingConvention(arch); this.ccr = new CallingConventionEmitter(); }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { throw new NotImplementedException(); }
// https://en.wikipedia.org/wiki/Calling_convention#SuperH // https://www.renesas.com/en-eu/doc/products/tool/001/rej10b0152_sh.pdf public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(4, 0x14); if (dtRet != null && !(dtRet is VoidType)) { RegisterStorage reg; var pt = dtRet as PrimitiveType; if (pt != null && pt.Domain == Domain.Real) { if (pt.Size == 4) { reg = arch.GetRegister("fr0"); } else { reg = arch.GetRegister("dr0"); } ccr.RegReturn(reg); } else { if (dtRet.Size > 4) { throw new NotImplementedException(); } else { ccr.RegReturn(arch.GetRegister("r0")); } } } int ir = 0; int fr = 0; if (dtThis != null) { ccr.ImplicitThisRegister(iregs[ir]); ++ir; } foreach (var dtParam in dtParams) { var pt = dtParam as PrimitiveType; if (pt != null && pt.Domain == Domain.Real) { if (pt.Size == 4) { if (fr < fregs.Length) { ccr.RegParam(fregs[fr]); ++fr; } else { ccr.StackParam(dtParam); } } else { var dr = (fr + 1) >> 1; if (dr < dregs.Length) { ccr.RegParam(dregs[dr]); fr = 2 * (dr + 1); } else { ccr.StackParam(dtParam); } } } else if (ir >= iregs.Length || dtParam.Size > 4) { ccr.StackParam(dtParam); } else { ccr.RegParam(iregs[ir]); ++ir; } } }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { //$TODO: finding it hard to locate information about the calling // convention on PowerPC Win32. May have to reverse engineer it. }
private void Given_CallingConvention() { this.cc = new Arm32CallingConvention(arch); this.ccr = new CallingConventionEmitter(); }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(arch.WordWidth.Size, 0x10); if (dtRet != null) { SetReturnRegister(ccr, dtRet); } int ir = 0; bool firstArgIntegral = false; for (int i = 0; i < dtParams.Count; ++i) { var dtParam = dtParams[i]; var prim = dtParam as PrimitiveType; if (prim != null && prim.Domain == Domain.Real && !firstArgIntegral) { if ((ir % 2) != 0) { ++ir; } if (ir >= fregs.Length) { ccr.StackParam(dtParam); } else { if (prim.Size == 4) { ccr.RegParam(fregs[ir]); ir += 1; } else if (prim.Size == 8) { ccr.SequenceParam(fregs[ir], fregs[ir + 1]); ir += 2; } else { throw new NotSupportedException(string.Format("Real type of size {0} not supported.", prim.Size)); } } } else { if (ir == 0) { firstArgIntegral = true; } if (dtParam.Size <= 4) { if (ir >= 4) { ccr.StackParam(dtParam); } else { ccr.RegParam(iregs[ir]); ++ir; } } else if (dtParam.Size <= 8) { if ((ir & 1) != 0) { ++ir; } if (ir >= 4) { ccr.StackParam(dtParam); } else { ccr.SequenceParam(iregs[ir], iregs[ir + 1]); ir += 2; } } else { throw new NotImplementedException(); } } } }
public void Setup() { this.cc = new X86_64CallingConvention(); this.ccr = new CallingConventionEmitter(); }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { //$TODO: make this happen }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(arch.WordWidth.Size, 0); if (dtRet != null) { var pt = dtRet as PrimitiveType; if (pt != null && pt.Domain == Domain.Real) { //$TODO floats > 64 bits ccr.RegReturn(fregs[0]); } else { if (dtRet.Size <= arch.PointerType.Size) { ccr.RegReturn(iregs[0]); } else if (dtRet.Size <= arch.PointerType.Size * 2) { ccr.SequenceReturn(iregs[1], iregs[0]); } else { //$TODO: return values > 128 bits. throw new NotImplementedException(); } } } int ir = 0; for (int i = 0; i < dtParams.Count; ++i) { var dtParam = dtParams[i]; var pt = dtParam as PrimitiveType; if (pt != null && pt.Domain == Domain.Real) { if (ir >= fregs.Length) { ccr.StackParam(dtParam); } else { ccr.RegParam(fregs[ir]); ++ir; } } else if (ir >= iregs.Length) { ccr.StackParam(dtParam); } else if (dtParam.Size <= arch.PointerType.Size) { ccr.RegParam(iregs[ir]); ++ir; } else if (dtParam.Size <= arch.PointerType.Size * 2) { if ((ir & 1) != 0) { ++ir; } if (ir >= iregs.Length) { ccr.StackParam(dtParam); } else { ccr.SequenceParam(iregs[ir + 1], iregs[ir]); ir += 2; } } else { throw new NotImplementedException(); } } }