CodeReading: GCC MIPSを読み解く (2)
Kazuki Ohta, 2006/02/10
今回は実際にmips依存部分のコードを読む事にする。mips.mdではなく、mips.[ch]から読んで行く。今回はregister回りのTarget Description Macroを読む事にする。
まずは「Register Basics」に載っているマクロを見ていく。
- REGISTER_NAMES
#define REGISTER_NAMES \
{ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", \
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", \
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", \
"$24", "$25", "$26", "$27", "$28", "$sp", "$fp", "$31", \
"$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", \
"$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \
"hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", \
"$fcc5","$fcc6","$fcc7","", "", "$arg", "$frame", "$fakec", \
"$c0r0", "$c0r1", "$c0r2", "$c0r3", "$c0r4", "$c0r5", "$c0r6", "$c0r7", \
"$c0r8", "$c0r9", "$c0r10","$c0r11","$c0r12","$c0r13","$c0r14","$c0r15", \
"$c0r16","$c0r17","$c0r18","$c0r19","$c0r20","$c0r21","$c0r22","$c0r23", \
"$c0r24","$c0r25","$c0r26","$c0r27","$c0r28","$c0r29","$c0r30","$c0r31", \
"$c2r0", "$c2r1", "$c2r2", "$c2r3", "$c2r4", "$c2r5", "$c2r6", "$c2r7", \
"$c2r8", "$c2r9", "$c2r10","$c2r11","$c2r12","$c2r13","$c2r14","$c2r15", \
"$c2r16","$c2r17","$c2r18","$c2r19","$c2r20","$c2r21","$c2r22","$c2r23", \
"$c2r24","$c2r25","$c2r26","$c2r27","$c2r28","$c2r29","$c2r30","$c2r31", \
"$c3r0", "$c3r1", "$c3r2", "$c3r3", "$c3r4", "$c3r5", "$c3r6", "$c3r7", \
"$c3r8", "$c3r9", "$c3r10","$c3r11","$c3r12","$c3r13","$c3r14","$c3r15", \
"$c3r16","$c3r17","$c3r18","$c3r19","$c3r20","$c3r21","$c3r22","$c3r23", \
"$c3r24","$c3r25","$c3r26","$c3r27","$c3r28","$c3r29","$c3r30","$c3r31" }
- FIRST_PSEUDO_REGISTER
- FIXED_REGISTERS
- $0: 常に0
- $1: ?
- $26: kernel register
- $27: kernel register
- $28: global pointer
- $29 ($sp): stack pointer
- $66: ?
- $75: ?
- $76: ?
- $77 ($arg): ?
- $78 ($frame): ?
- $79 ($fakec): ?
- $80 - $175: 32 registers for each 3 co-processors
/* Number of hardware registers. We have:
- 32 integer registers
- 32 floating point registers
- 8 condition code registers
- 2 accumulator registers (hi and lo)
- 32 registers each for coprocessors 0, 2 and 3
- 3 fake registers:
- ARG_POINTER_REGNUM
- FRAME_POINTER_REGNUM
- FAKE_CALL_REGNO (see the comment above load_callsi for details)
- 3 dummy entries that were used at various times in the past. */
#define FIRST_PSEUDO_REGISTER 176
/* By default, fix the kernel registers ($26 and $27), the global
pointer ($28) and the stack pointer ($29). This can change
depending on the command-line options.
Regarding coprocessor registers: without evidence to the contrary,
it's best to assume that each coprocessor register has a unique
use. This can be overridden, in, e.g., override_options() or
CONDITIONAL_REGISTER_USAGE should the assumption be inappropriate
for a particular target. */
#define FIXED_REGISTERS \
{ \
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, \
/* COP0 registers */ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
/* COP2 registers */ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
/* COP3 registers */ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \
}
FIXED_REGISTERSはレジスタテーブルを初期化する為のマクロで、stack pointerやframe pointer等、特定の用途で使われるregisterの場所にフラグを立てる。1が立っているレジスタは以下の通り。
- CONDITIONAL_REGISTER_USAGE
#define CONDITIONAL_REGISTER_USAGE mips_conditional_register_usage ()
- CALL_USED_REGISTERS
/* Set up this array for o32 by default.
Note that we don't mark $31 as a call-clobbered register. The idea is
that it's really the call instructions themselves which clobber $31.
We don't care what the called function does with it afterwards.
This approach makes it easier to implement sibcalls. Unlike normal
calls, sibcalls don't clobber $31, so the register reaches the
called function in tact. EPILOGUE_USES says that $31 is useful
to the called function. */
#define CALL_USED_REGISTERS \
{ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
/* COP0 registers */ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
/* COP2 registers */ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
/* COP3 registers */ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \
}
- CALL_REALLY_USED_REGISTERS
/* Define this since $28, though fixed, is call-saved in many ABIs. */
#define CALL_REALLY_USED_REGISTERS \
{ /* General registers. */ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, \
/* Floating-point registers. */ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
/* Others. */ \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
/* COP0 registers */ \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
/* COP2 registers */ \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
/* COP3 registers */ \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
}
結構定義されていないマクロが有るのね。さて、次は「Allocation Order」の部分。
- REG_ALLOC_ORDER
/* REG_ALLOC_ORDER is to order in which to allocate registers. This
is the default value (allocate the registers in numeric order). We
define it just so that we can override it for the mips16 target in
ORDER_REGS_FOR_LOCAL_ALLOC. */
#define REG_ALLOC_ORDER \
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, \
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, \
96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111, \
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, \
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, \
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, \
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175 \
}
- ORDER_REGS_FOR_LOCAL_ALLOC
/* ORDER_REGS_FOR_LOCAL_ALLOC is a macro which permits reg_alloc_order
to be rearranged based on a particular function. On the mips16, we
want to allocate $24 (T_REG) before other registers for
instructions for which it is possible. */
#define ORDER_REGS_FOR_LOCAL_ALLOC mips_order_regs_for_local_alloc ()
/* On the mips16, we want to allocate $24 (T_REG) before other
registers for instructions for which it is possible. This helps
avoid shuffling registers around in order to set up for an xor,
encouraging the compiler to use a cmp instead. */
void
mips_order_regs_for_local_alloc (void)
{
register int i;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
reg_alloc_order[i] = i;
if (TARGET_MIPS16)
{
/* It really doesn't matter where we put register 0, since it is
a fixed register anyhow. */
reg_alloc_order[0] = 24;
reg_alloc_order[24] = 0;
}
}
次は「Values in Registers」の部分。
- HARD_REGNO_NREGS
#define HARD_REGNO_NREGS(REGNO, MODE) mips_hard_regno_nregs (REGNO, MODE)
/* Implement HARD_REGNO_NREGS. The size of FP registers is controlled
by UNITS_PER_FPREG. The size of FP status registers is always 4, because
they only hold condition code modes, and CCmode is always considered to
be 4 bytes wide. All other registers are word sized. */
unsigned int
mips_hard_regno_nregs (int regno, enum machine_mode mode)
{
if (ST_REG_P (regno))
return ((GET_MODE_SIZE (mode) + 3) / 4);
else if (! FP_REG_P (regno))
return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
else
return ((GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG);
}
#define ST_REG_FIRST 67 #define ST_REG_LAST 74 #define ST_REG_NUM (ST_REG_LAST - ST_REG_FIRST + 1) #define ST_REG_P(REGNO) \ ((unsigned int) ((int) (REGNO) - ST_REG_FIRST) < ST_REG_NUM)
/* Width of a word, in units (bytes). */ #define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4)
まとめると、mips_hard_regno_nregs関数にはregnoとmodeが渡ってきて、あるmodeの値を格納するのにregno版目のレジスタからいくつ連続するレジスタが必要かを求める処理が書かれている。
- HARD_REGNO_MODE_OK
/* To make the code simpler, HARD_REGNO_MODE_OK just references an
array built in override_options. Because machmodes.h is not yet
included before this file is processed, the MODE bound can't be
expressed here. */
extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
mips_hard_regno_mode_ok[ (int)(MODE) ][ (REGNO) ]
- AVOID_CCMODE_COPIES
/* Define if copies to/from condition code registers should be avoided.
This is needed for the MIPS because reload_outcc is not complete;
it needs to handle cases where the source is a general or another
condition code register. */
#define AVOID_CCMODE_COPIES
「Leaf Functions」に該当するマクロは無し。「Stack Registers」に該当するものも無し。
(続く)
[ return ]