public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(stackAlignment, retAddressOnStack); SetReturnStorage(ccr, dtRet, stackAlignment); if (dtThis != null) { ccr.ImplicitThisStack(dtThis); } if (reverseArguments) { for (int i = dtParams.Count - 1; i >= 0; --i) { ccr.StackParam(dtParams[i]); } ccr.ReverseParameters(); } else { for (int i = 0; i < dtParams.Count; ++i) { ccr.StackParam(dtParams[i]); } } if (callerCleanup) { ccr.CallerCleanup(retAddressOnStack); } else { ccr.CalleeCleanup(); } }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { //$TODO: verify the stack offset ccr.LowLevelDetails(arch.WordWidth.Size, 0x40); if (dtRet != null) { SetReturnRegister(ccr, dtRet); } int gr = 0; int fr = 0; for (int iArg = 0; iArg < dtParams.Count; ++iArg) { var dtArg = dtParams[iArg]; if (dtArg is PrimitiveType prim && prim.Domain == Domain.Real) { if (fr >= fregs.Length) { ccr.StackParam(dtArg); } else { ccr.RegParam(fregs[fr]); ++fr; } }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(arch.WordWidth.Size, 0); if (dtRet != null) { if (dtRet is PrimitiveType pt && 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(); } } }
// 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; if (dtRet is PrimitiveType pt && pt.Domain == Domain.Real) { if (pt.Size == 4) { reg = fret; } else { reg = dret; } ccr.RegReturn(reg); } else { if (dtRet.Size > 4) { throw new NotImplementedException(); } else { ccr.RegReturn(iret); } } }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(stackAlignment, retSizeOnStack); ccr.CallerCleanup(retSizeOnStack); int iReg = 0; if (dtThis != null) { ccr.ImplicitThisRegister(iArgs[iReg++]); } foreach (var dtParam in dtParams) { if (iReg < iArgs.Length) { ccr.RegParam(iArgs[iReg++]); } else { ccr.StackParam(dtParam); } } if (dtRet != null) { ccr.RegReturn(Registers.eax); } }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(arch.WordWidth.Size, 0x0018); if (dtRet != null) { SetReturnRegister(ccr, dtRet); } int ir = 0; for (int iArg = 0; iArg < dtParams.Count; ++iArg) { var dtArg = dtParams[iArg]; var prim = dtArg as PrimitiveType; if (dtArg.Size <= 8) { if (ir >= regs.Length) { ccr.StackParam(dtArg); } else { ccr.RegParam(regs[ir]); ++ir; } } else { throw new NotImplementedException(); } } }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(2, 0); if (dtRet != null && !(dtRet is VoidType)) { if (dtRet.Size <= 2) { ccr.RegReturn(iregs[0]); } else if (dtRet.Size <= 4) { ccr.SequenceReturn(iregs[1], iregs[0]); } else { throw new NotImplementedException(); } } int iReg = 0; for (int i = 0; i < dtParams.Count; ++i) { //$BUG: clearly not correct yet, but we need to start somewhere. if (iReg < iregs.Length) { ccr.RegParam(iregs[iReg]); ++iReg; } else { ccr.StackParam(dtParams[i]); } } }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(4, 4); if (dtRet != null) { if (dtRet is PrimitiveType pt && pt.Domain == Domain.Real) { ccr.RegReturn(fp0); } if (dtRet.BitSize > 64) { throw new NotImplementedException(); } ccr.RegReturn(d0); } var args = new List <Storage>(); int stOffset = arch.PointerType.Size; foreach (var dtParam in dtParams) { ccr.StackParam(dtParam); } ccr.CallerCleanup(arch.PointerType.Size); }
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; int fr = 0; for (int iArg = 0; iArg < dtParams.Count; ++iArg) { var dtArg = dtParams[iArg]; var prim = dtArg as PrimitiveType; if (prim != null && prim.Domain == Domain.Real) { if (fr >= fregs.Length) { ccr.StackParam(dtArg); } else { ccr.RegParam(fregs[fr]); ++fr; } } else if (dtArg.Size <= 4) { if (ir >= iregs.Length) { ccr.StackParam(dtArg); } else { ccr.RegParam(iregs[ir]); ++ir; } } else { int regsNeeded = (dtArg.Size + 3) / 4; if (regsNeeded > 4 || ir + regsNeeded >= iregs.Length) { ccr.StackParam(dtArg); } else if (regsNeeded == 2) { ccr.SequenceParam(iregs[ir], iregs[ir + 1]); ir += 2; } else { throw new NotImplementedException(); } } } }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(4, 0); //Return values of types up to 8 bytes are returned in r2 and r3.For return values //greater than 8 bytes, the caller must allocate memory for the result and must pass //the address of the result memory as a hidden zero argument. int i = 0; if (dtRet != null) { if (dtRet.Size <= 4) { ccr.RegReturn(retLo); } else if (dtRet.Size <= 8) { ccr.SequenceReturn(retHi, retLo); } else { ccr.RegParam(iregs[i++]); } } foreach (var dtParam in dtParams) { if (dtParam.Size <= 4) { if (i < iregs.Length) { ccr.RegParam(iregs[i++]); } else { ccr.StackParam(dtParam); } } else { //$TODO: wider args ccr.StackParam(dtParam); } } //The first 16 bytes to a function are passed in registers r4 through r7. The arguments //are passed as if a structure containing the types of the arguments were constructed, //and the first 16 bytes of the structure are located in r4 through r7. //A simple example: // int function(int a, int b); //The equivalent structure representing the arguments is: // struct { int a; int b; }; //The first 16 bytes of the struct are assigned to r4 through r7.Therefore r4 is //assigned the value of a and r5 the value of b. //The first 16 bytes to a function taking variable arguments are passed the same way as //a function not taking variable arguments.The called function must clean up the stack //as necessary to support the variable arguments. //Refer to Stack Frame for a Function with Variable Arguments }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(arch.PointerType.Size, 0x0008); if (dtRet != null) { SetReturnRegister(ccr, dtRet); } int fr = 0; int ir = 0; // The SysV calling convention specifies that there is no // "reserved slot" prior to the return address on the stack, in // contrast with Windows where 4*8 bytes are allocated for // space for the four registers foreach (var dtParam in dtParams) { var prim = dtParam as PrimitiveType; if (prim != null && prim.Domain == Domain.Real) { if (fr >= fregs.Length) { ccr.StackParam(dtParam); } else { ccr.RegParam(fregs[fr]); ++fr; } } else if (dtParam.Size <= 8) { if (ir >= iregs.Length) { ccr.StackParam(dtParam); } else { ccr.RegParam(iregs[ir]); ++ir; } } else { int regsNeeded = (dtParam.Size + 7) / 8; if (regsNeeded > 4 || ir + regsNeeded >= iregs.Length) { ccr.StackParam(dtParam); } else { throw new NotImplementedException(); } } } ccr.CallerCleanup(arch.PointerType.Size); }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(8, 0x0028); if (dtRet != null) { if (dtRet.Size > 8) { throw new NotImplementedException(); } var pt = dtRet as PrimitiveType; if (pt != null && pt.Domain == Domain.Real) { ccr.RegReturn(Registers.xmm0); } else if (dtRet.Size <= 1) { ccr.RegReturn(Registers.al); } else if (dtRet.Size <= 2) { ccr.RegReturn(Registers.ax); } else if (dtRet.Size <= 4) { ccr.RegReturn(Registers.eax); } else { ccr.RegReturn(Registers.rax); } } for (int i = 0; i < dtParams.Count; ++i) { var dt = dtParams[i]; if (dt.Size > 8) { throw new NotImplementedException(); } var pt = dt as PrimitiveType; if (pt != null && pt.Domain == Domain.Real && i < fRegs.Length) { ccr.RegParam(fRegs[i]); } else if (i < iRegs.Length) { ccr.RegParam(iRegs[i]); } else { ccr.StackParam(dt); } } ccr.CallerCleanup(8); }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(4, 0); foreach (var dt in dtParams) { ccr.StackParam(dt); } if (dtRet != null) { ccr.RegReturn(arch.GetRegister("r12")); } }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(4, 4); foreach (var dtParam in dtParams) { ccr.StackParam(dtParam); } if (dtRet != null) { ccr.RegReturn(regRet); } }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { //$BUG: this is all just to get the ELF loader up and running. ccr.LowLevelDetails(4, 0); if (dtRet != null && !(dtRet is VoidType)) { ccr.RegReturn(arch.GetRegister("r0") !); } foreach (var dt in dtParams) { ccr.RegParam(arch.GetRegister("r0") !); } }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(8, 0x0010); //$TODO: need to deal with large args and stack parameters. int iReg = 0; foreach (var dtParam in dtParams) { ccr.RegParam(argRegs[iReg]); ++iReg; } }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(2, 4); for (int i = dtParams.Count - 1; i >= 0; --i) { ccr.StackParam(dtParams[i]); } ccr.ReverseParameters(); ccr.CalleeCleanup(); if (dtRet != null && !(dtRet is VoidType)) { ccr.StackReturn(dtRet); } }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { //$BUG: this is all just to get the ELF loader up and running. // fill in with details from // https://blackfin.uclinux.org/doku.php?id=toolchain:application_binary_interface ccr.LowLevelDetails(4, 0); if (dtRet != null && !(dtRet is VoidType)) { ccr.RegReturn(arch.GetRegister("R0") !); } foreach (var dt in dtParams) { ccr.RegParam(arch.GetRegister("R0") !); } }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { int stackOffset = 4; // return address ccr.LowLevelDetails(4, stackOffset); if (dtRet != null) { ccr.RegReturn(Registers.d0); } for (int i = 0; i < dtParams.Count; ++i) { ccr.StackParam(dtParams[i]); } ccr.CallerCleanup(4); }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { int fr = 0; int gr = 0; ccr.LowLevelDetails(8, 160); for (int i = 0; i < dtParams.Count; ++i) { var dt = dtParams[i]; switch (dt) { case PrimitiveType pt: if (pt.Domain == Domain.Real) { if (fr < this.fregs.Length) { ccr.RegParam(fregs[fr]); ++fr; } else { ccr.StackParam(dt); } break; } goto default; default: if (dt.BitSize <= 64) { if (gr < this.iregs.Length) { ccr.RegParam(iregs[gr]); ++gr; break; } } ccr.StackParam(dt); break; } } if (dtRet is PrimitiveType ptRet && ptRet.Domain == Domain.Real) { ccr.RegReturn(fregs[0]); }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { //$TODO: full implementation needed. Currently can't handle varargs, args whose bit size > 64, or more than 8 args. int stackSaveOffset = 0x48; ccr.LowLevelDetails(arch.WordWidth.Size, stackSaveOffset); GenerateReturn(ccr, dtRet); int iReg = 0; int fReg = 0; foreach (var dtParam in dtParams) { if (dtParam is PrimitiveType pt && pt.Domain == Domain.Real) { ccr.RegParam(fregs[fReg]); ++fReg; }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(2, 2); if (dtRet != null) { SetReturnRegisters(ccr, dtRet); } int gr = 0; for (int iArg = 0; iArg < dtParams.Count; ++iArg) { var arg = arch.GetRegister("r" + gr) !; ++gr; ccr.RegParam(arg); } ccr.CallerCleanup(arch.PointerType.Size); }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(4, 0); if (dtRet != null) { SetReturnRegister(ccr, dtRet.BitSize); } // The first four registers r0 - r3 are used to pass argument values into a subroutine and to return a result // value from a function. int ncrn = 0; foreach (var dt in dtParams) { var sizeInWords = (dt.Size + 3) / 4; if (sizeInWords == 2 && (ncrn & 1) == 1) { ++ncrn; } if (sizeInWords <= argRegs.Length - ncrn) { if (sizeInWords == 2) { ccr.SequenceParam( argRegs[ncrn], argRegs[ncrn + 1]); ncrn += 2; } else { ccr.RegParam(argRegs[ncrn]); ncrn += 1; } } else { ccr.StackParam(dt); } } }
public void Generate(ICallingConventionEmitter ccr, DataType?dtRet, DataType?dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(4, 0x0010); int ncrn = 0; // mem arg forb ret val if (dtRet != null) { SetReturnRegister(ccr, dtRet.BitSize); } foreach (var dt in dtParams) { var sizeInWords = (dt.Size + 3) / 4; if (sizeInWords == 2 && (ncrn & 1) == 1) { ++ncrn; } if (sizeInWords <= argRegs.Length - ncrn) { if (sizeInWords == 2) { ccr.SequenceParam( argRegs[ncrn], argRegs[ncrn + 1]); ncrn += 2; } else { ccr.RegParam(argRegs[ncrn]); ncrn += 1; } } else { ccr.StackParam(dt); } } }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(4, 0); if (dtRet != null) { var a2 = (StorageDomain)2; //$TODO: size > 4 bytes? ccr.RegReturn(arch.GetRegister(a2, r32)); } int iReg = 2; foreach (var dtParam in dtParams) { //$TODO: size > 4 bytes? //$TODO: iReg > 6? var arg = (StorageDomain)iReg; ccr.RegParam(arch.GetRegister(arg, r32)); ++iReg; } }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(8, 0); //$BUGBUG: the '0' is incorrect, but we need a reliable spec for WinAlpha to determine exact value. if (dtRet != null) { ccr.RegReturn(iRet); } int iReg = 0; foreach (var dtParam in dtParams) { if (iReg < iRegs.Length) { ccr.RegParam(iRegs[iReg]); ++iReg; } else { ccr.StackParam(PrimitiveType.Word64); } } }
/// <summary> /// If dtThis is supplied, it is known that it is the `this` /// corresponding to an enclosing C++ class. If dtThis is null, then /// the first of the dtParams will be treated as a `this`. /// </summary> public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { ccr.LowLevelDetails(stackAlignment, retAddressOnStack); X86CallingConvention.SetReturnStorage(ccr, dtRet, stackAlignment); int i = 0; if (dtThis != null) { ccr.ImplicitThisRegister(this.ecxThis); } else if (dtParams.Count > 0) { ccr.RegParam(this.ecxThis); i = 1; } for (; i < dtParams.Count; ++i) { ccr.StackParam(dtParams[i]); } ccr.CalleeCleanup(); }
public void Generate(ICallingConventionEmitter ccr, DataType dtRet, DataType dtThis, List <DataType> dtParams) { int stackOffset = 4 + 4; // Skip the system call selector + return address. ccr.LowLevelDetails(4, stackOffset); if (dtRet != null) { ccr.RegReturn(Registers.d0); } if (dtThis != null) { //ImplicitThis = null, //$TODO throw new NotImplementedException("C++ implicit `this` arguments are not implemented for Atari TOS."); } for (int iArg = 0; iArg < dtParams.Count; ++iArg) { ccr.StackParam(dtParams[iArg]); } // AFAIK the calling convention on Atari TOS is caller-cleanup, // so the only thing we clean up is the return value on the stack. ccr.CallerCleanup(4); }
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(regNext, seq, PrimitiveType.CreateWord(regNext.DataType.BitSize + seq.DataType.BitSize)); } else { seq = new SequenceStorage(regNext, reg, PrimitiveType.CreateWord(regNext.DataType.BitSize + reg.DataType.BitSize)); } } 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(); } } }