예제 #1
0
        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();
            }
        }
예제 #2
0
        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;
                    }
                }
예제 #3
0
 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();
             }
         }
     }
예제 #4
0
 // 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);
             }
         }
     }
예제 #5
0
        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);
            }
        }
예제 #6
0
        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();
                }
            }
        }
예제 #7
0
        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]);
                }
            }
        }
예제 #8
0
        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);
        }
예제 #9
0
        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();
                    }
                }
            }
        }
예제 #10
0
        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
        }
예제 #11
0
        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);
        }
예제 #12
0
 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);
 }
예제 #13
0
 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"));
     }
 }
예제 #14
0
 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);
     }
 }
예제 #15
0
 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") !);
     }
 }
예제 #16
0
        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;
            }
        }
예제 #17
0
 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);
     }
 }
예제 #18
0
 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") !);
     }
 }
예제 #19
0
        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);
        }
예제 #20
0
        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]);
            }
예제 #21
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;
                }
예제 #22
0
        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);
        }
예제 #23
0
        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);
                }
            }
        }
예제 #24
0
        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);
                }
            }
        }
예제 #25
0
        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;
            }
        }
예제 #26
0
        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);
                }
            }
        }
예제 #27
0
        /// <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();
        }
예제 #28
0
        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);
        }
예제 #29
0
        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);
                }
            }
        }
예제 #30
0
        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();
                    }
                }
            }