tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] More than 3 integer registers?


From: Peter \"Firefly\" Lund
Subject: [Tinycc-devel] More than 3 integer registers?
Date: Thu, 17 Apr 2003 00:13:50 +0200 (MEST)

I am currently trying to understand i386-gen.c (and the value stack).
This rambling email is a brain dump of some of the parts I think I
understand now...

Is it correct that something like the following would enable the use of
EBX in addition to EAX, ECX, and EDX?

#define NB_REGS 5

enum {
  TREG_EAX = 0,
  TREG_ECX,
  TREG_EDX,
  TREG_EBX,
  TREG_ST0,
};

int reg_classes[NB_REGS] = {
  /* eax */ RC_INT | RC_EAX,
  /* ecx */ RC_INT | RC_ECX,
  /* edx */ RC_INT | RC_EDX,
  /* ebx */ RC_INT,
  /* st0 */ RC_FLOAT | RC_ST0,
};

No other part of the code would need to change, as far as I can see.
No further register class would need to be defined, either.

RC_EAX is necessary because sometimes we really need to use EAX:
integer and pointer return values, for storing the floating point flags
after a floating-point comparison, and because mul/div instructions are
hardwired to use (EDX:)EAX.

RC_ECX is necessary because sometimes we really need to use ECX:
variable length shifts and mul/div.  (we don't use the rep prefix or the
loop instructions)

RC_EDX is necessary because sometimes we really need to use EDX:
64-bit values (where the low 32-bit would always be in EAX) and because
mul/div instructions are hardwired to use (EDX:)EAX.

EBX could be used with the XLAT or BOUNDS instruction (if I remember
correctly) and for addressing but we don't use any of that, so no RC_EBX
register class is necessary.

I haven't gone through all the opcodes emitted in i386-gen.c (and outside
of it, in the value stack manipulation code) but it doesn't look like
there are any instruction sequences that are hardwired to use EBX -- it
therefore seems free to use as a general purpose register.

TREG_EAX/TREG_ECX/TREG_EDX/TREG_EBX are placed in that order on purpose,
because their ordinal value just happens to have the right bits for use
directly in the instruction encodings.

TREG_ST0 can have any value as long as it is distinct from the integer
register numbers and the VT_CONST/VT_LLOCAL/VT_LOCAL/VT_CMP/VT_JMP/VT_JMPI
values (they share the low byte of the r field in a vstack entry with the
register number -- the low byte can be one of the VT_XXX values or a
register number... and actually it doesn't have to be exactly eight bits,
that's just what VT_VALMASK is currently defined to).


Why not go even further and use ESI and EDI, too?

There is the little problem that they are callee-save registers, that is
to say that it is the responsibility of the called function to ensure that
they aren't changed upon return.

gfunc_prolog() could emit push esi, push edi and gfunc_epilog() could emit
pop edi, pop esi but that seems wasteful if they aren't used in a
function.  We can't currently nuke instructions in a function or splice
functions together from snippets of emitted code so it's either emit
push/pop unconditionally or not use those registers at all.

We probably wouldn't be able to get much mileage out of them:
 o each expression is register allocated in isolation
 o the register storage class is ignored
 o the gcc register extension that assigns variables to specific registers
   is not supported yet.
 o tcc doesn't (yet) remember whatever value it last put into a register
 o for/do/while expressions don't use esi/edi for loop variables

The conclusion is that they are not useful for the time being.  That might
change when other parts of the code generator have been improved.

If we wanted to support them we would rewrite the code snippet from the
beginning of this email like this:

#define NB_REGS 9

enum {
  TREG_EAX = 0,
  TREG_ECX,
  TREG_EDX,
  TREG_EBX,
  TREG_dummy1,
  TREG_dummy2,
  TREG_ESI,
  TREG_EDI,
  TREG_ST0,
};

int reg_classes[NB_REGS] = {
  /*  eax  */ RC_INT | RC_EAX,
  /*  ecx  */ RC_INT | RC_ECX,
  /*  edx  */ RC_INT | RC_EDX,
  /*  ebx  */ RC_INT,
  /* (esp) */ 0,
  /* (ebp) */ 0,
  /*  esi  */ RC_INT,
  /*  edi  */ RC_INT,
  /*  st0  */ RC_FLOAT | RC_ST0,
};


Comments?

-Peter

It took the computational power of three Commodore 64s to fly to the moon.
It takes a 486 to run Windows 95.  Something is wrong here. -- SC sig file




reply via email to

[Prev in Thread] Current Thread [Next in Thread]