[Mono-dev] JIT: MonoReg to replace gssize for registers

Mark Mason mmason at upwardaccess.com
Sat Dec 13 16:12:31 EST 2008


Hello,

Yes. Sparcv9 had something similar as well - at least on a few  
embedded systems (I did the VxWorks port for that ABI, and some of the  
gcc work - ages ago now).

The mips/n32 ABI is growing in popularity, both in the embedded space  
and at the higher end (As I understand it, the SiCortex systems are  
n32). It's higher performance, and it allows the compiler to take  
advantage of the 64-bit register file and ALU without having to port  
the code to a full 64-bit API (w/ 64 bit pointers and such). Even code  
that doesn't generally use 64-bit ints will run faster due to the  
changes in the calling convention[*]. Most (embedded) systems don't  
need the extended addressing of 64-bits, but if they're on a MIPS64  
device they want access to the full 64-bit ALU and register set (yes,  
there are some embedded systems that would like pointers to be 64-bit,  
but they're few in number so far).

So, n32 is a generally useful middle ground between the strict 32-bit  
ABI (o32) and the full 64-bit ABI (n64) - probably more so than SPE is  
for ppc. That last bit is speculation on my part, as ppc is one of the  
modern instruction sets I'm less than familiar with. This is despite  
the fact that a lot of the MIPS JIT for Mono was written by reverse  
engineering the PPC port ;).

Andreas - the way I'm handling the code generation differences on MIPS  
is through a set of macros (basically pseudo-ops) that either produce  
the 32 or 64-bit versions of opcodes depending on which ABI we're  
compiling for. It's the same basic technique that's been in use on  
MIPS for writing ABI independent assembly code since the first 64-bit  
MIPS chips were introduced (back around '90 or so). It requires  
keeping a bit more context in your head when reading/writing the code,  
but it keeps from polluting the mini-mips.c file with a lot of extra  
#ifdef tests.

The main thing I'm working through right now is finding and fixing a  
few of the macros in ir-emit.h to keep them 'doing the right thing'  
without warnings when inst_p0 and inst_p1 are MonoReg (an integral  
type) rather than a gpointer. Due to the way that OP_PCONST and a few  
other opcodes are handled, there's an assumption that inst_p* and  
inst_c* are type punned through the union. It's close to working, and  
I'm trying to keep the changes as small as possible. There's probably  
another day or two of spare-time work on it before I'm ready to post  
it for review.

/Mark

[*] the trade off is that on o64, n32 and n64 stack slots are 64-bits  
- which means that for any given call stack you tend to burn through  
your D-cache faster. On the plus side, n32 and n64 (1) provide for  
passing the first 8 arguments in registers (instead of the first  
four), and (2) doesn't require the caller allocating backing space in  
the stack frame for register arguments (which cuts down on the stack  
footprint and gets you back some of the performance loss due to the  
larger stack slots). The o32->o64 transition however tends to cost  
~5-7% in performance for otherwise 32-bit code because you're still  
limited to 4 arguments in registers and backing stack slots allocated  
by the caller. I don't suggest we support o64 - it was never an  
official ABI, never was supported under Linux and is in the process of  
being phased out from the embedded systems that supported in (in favor  
of n32).

On Dec 13, 2008, at 12:27 PM, Andreas Färber wrote:

> Hi,
>
> On ppc there is a similar feature, SPE, which allows some 64-bit ops  
> on a 32-bit machine.
>
> There, the general-purpose registers appear to be all 64-bit but  
> regular instructions only access the lower 32 bits. Special  
> instructions are used to access full 64-bit registers, similar to  
> Altivec instructions using (separate) 128-bit registers on an  
> otherwise 32- or 64-bit system.
>
> From that point of view, technically the MonoReg distinction makes  
> sense, to allow sizeof(MonoReg) >= sizeof(gssize).
>
> But as pointed out below, changing the variable type is only a  
> start. Should anyone want to make Mono use SPE on ppc, probably all  
> places that save and restore registers would need to be reworked,  
> introducing a special code path for those systems that support it.  
> The only Mono feature benefitting would probably be System.Int64, so  
> I'm not sure if this is really needed.
>
> Andreas
>
> Am 13.12.2008 um 19:55 schrieb Mark Mason:
>
>> Hello,
>>
>> Not ... necessarily.  The mips/n32 abi is one example.  Code runs  
>> in a
>> 32-bit address space (so pointers, and sizeof(void *) are 32-bits),
>> but with 64-bit registers and 64-bit operations available.
>>
>> This is distinct from n64, which does have 64-bit pointers.
>>
>> /Mark
>>
>> On Dec 13, 2008, at 7:01 AM, Zoltan Varga wrote:
>>
>>> Hi,
>>>
>>> gssize is the size needed to hold a memory address, if the machine
>>> has 64 bit registers,
>>> this is 64 bits. On that mips machine, this is 32 bits ?
>>>
>>>                Zoltan
>>>
>>> On Thu, Dec 11, 2008 at 8:40 PM, Mark Mason
>>> <mmason at upwardaccess.com> wrote:
>>>> Hello all,
>>>>
>>>> Along the same lines as the SIZEOF_VOID_P change, I'd like to offer
>>>> the
>>>> following new type to replace to use of 'gssize' when referring  
>>>> to a
>>>> machine register. 'gssize' comes from glib, and simply represents  
>>>> the
>>>> size of an integer -- which is not necessarily always the same as  
>>>> the
>>>> size of the underlying integer registers.
>>>>
>>>> There are some other uses of gssize in mini/ that will need to be
>>>> updated as well, but this is a start.
>>>>
>>>> Comments most welcome.
>>>>
>>>> Thanks in advance,
>>>> Mark
>>>>
>>>> Index: mini.h
>>>> ===================================================================
>>>> --- mini.h      (revision 121269)
>>>> +++ mini.h      (working copy)
>>>> @@ -400,6 +400,13 @@
>>>>     int size, align;
>>>> } MonoMemcpyArgs;
>>>>
>>>> +/* C type matching the size of a machine register. Not always the
>>>> same
>>>> as 'int' */
>>>> +#if SIZEOF_REGISTER == 4
>>>> +typedef gint32 MonoReg;
>>>> +#elif SIZEOF_REGISTER == 8
>>>> +typedef gint64 MonoReg;
>>>> +#endif
>>>> +
>>>> struct MonoInst {
>>>>     guint16 opcode;
>>>>     guint8  type; /* stack type */
>>>> @@ -415,7 +422,7 @@
>>>>             union {
>>>>                     MonoInst *src;
>>>>                     MonoMethodVar *var;
>>>> -                       gssize const_val;
>>>> +                       MonoReg const_val;
>>>>                     gpointer p;
>>>>                     MonoMethod *method;
>>>>                     MonoMethodSignature *signature;
>>>>
>>>>
>>>> _______________________________________________
>>>> Mono-devel-list mailing list
>>>> Mono-devel-list at lists.ximian.com
>>>> http://lists.ximian.com/mailman/listinfo/mono-devel-list
>>>>
>>
>> _______________________________________________
>> Mono-devel-list mailing list
>> Mono-devel-list at lists.ximian.com
>> http://lists.ximian.com/mailman/listinfo/mono-devel-list
>



More information about the Mono-devel-list mailing list