diff options
Diffstat (limited to 'gcc/config/mxp/mxp-genregset.c')
-rw-r--r-- | gcc/config/mxp/mxp-genregset.c | 464 |
1 files changed, 464 insertions, 0 deletions
diff --git a/gcc/config/mxp/mxp-genregset.c b/gcc/config/mxp/mxp-genregset.c new file mode 100644 index 00000000000..13d23a48a56 --- /dev/null +++ b/gcc/config/mxp/mxp-genregset.c @@ -0,0 +1,464 @@ +/* Generate the machine mode enumeration and associated tables. + Copyright (C) 2003, 2004, 2008 + Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ + +#include "config/mxp/regset-config.h" +#include "bconfig.h" +#include "system.h" +#include "errors.h" + +int vec_lanes[] = MXP_VEC_LANE_SETS; +int acc_lanes[] = MXP_FLAG_ACC_LANE_SETS; +#define flag_lanes acc_lanes +int scalar_lanes[] = MXP_SCALAR_LANE_SETS; +const char *fake_reg_names[] = MXP_FAKE_REG_NAMES; +const int regs_per_vreg = 16 / MXP_UNITS_PER_MXP_VEC_REG; + +#define SCALAR_NSETS ARRAY_SIZE(scalar_lanes) +#define VEC_NSETS ARRAY_SIZE(vec_lanes) +#define ACC_NSETS ARRAY_SIZE(acc_lanes) +#define FLAG_NSETS ARRAY_SIZE(flag_lanes) +#define N_RCLASS ((int) (SCALAR_NSETS * VEC_NSETS * ACC_NSETS * FLAG_NSETS)) + + +/* Return element I of the array LANESET_SET. */ +static int +laneset (int i, int *laneset_set) +{ + return laneset_set[i]; +} + +#define DECODE_REGCLASS \ + int scalar = laneset (i % SCALAR_NSETS, scalar_lanes); \ + int vec = laneset ((i /= SCALAR_NSETS) % VEC_NSETS, vec_lanes);\ + int flags = laneset ((i /= VEC_NSETS) % FLAG_NSETS, flag_lanes); \ + int acc = laneset((i /= FLAG_NSETS) % ACC_NSETS, acc_lanes); + +static int +valid_regclass (int i) +{ + DECODE_REGCLASS + + return MXP_VALID_REG_CLASS (scalar, vec, flags, acc); +} + +static void +emit_regclass_name (int i) +{ + if (i == 0) + printf ("NO_REGS"); + else if (i == N_RCLASS - 1) + printf ("ALL_REGS"); + else + { + DECODE_REGCLASS + + if (scalar) + printf ("S%02x", scalar); + if (vec) + printf ("V%02x", vec); + if (flags) + printf ("F%02x", flags); + if (acc) + printf ("A%02x", acc); + printf ("_REGS"); + } +} + +static void +emit_regclass_content (int i) +{ + long shift, mask; + int n_words = 0; + DECODE_REGCLASS + +#define INC_SHIFT(UNITS) \ + do \ + { \ + shift += (UNITS) / MXP_UNITS_PER_MXP_VEC_REG; \ + if (shift >= 32) \ + { \ + if (n_words++ > 5) \ + { \ + printf (" \\\n "); \ + n_words = 1; \ + } \ + printf (" 0x%08lx,", mask); \ + mask = shift = 0; \ + } \ + } \ + while (0) + + /* vr0 / vr1 contain scalar regs. */ + mask = scalar | (scalar << 8); + shift = 16; + /* vr2 .. vr62 are (inasmuch as implemented) non-scalar vector registers. */ + for (i = 2; i < 62; i++) + { + mask |= vec << shift; + INC_SHIFT (16); + } + /* accumulator */ + mask |= acc << shift; + INC_SHIFT (16); + /* vflags */ + mask |= flags << shift; + INC_SHIFT (16); + /* Fake registers. */ + for (i = 0; i < (int) ARRAY_SIZE (fake_reg_names); i++) + { + INC_SHIFT (0); + if (scalar & MXP_FAKE_REG_LANES) + mask |= 1 << shift++; + } + INC_SHIFT (256); +} + +static void +upputs (const char *s) +{ + while (*s) +#if 0 + putchar (TOUPPER (*s++)); +#else + { + putchar (*s >= 'a' && *s <= 'z' ? *s - 'a' + 'A': *s); + s++; + } +#endif +} + +static void +regno_reg_class_1 (char letter, int *a, int size) +{ + int mask, seen = 0; + int i; + + for (i = 0; i < size; i++) + { + mask = a[i]; + if (!(mask & ~seen)) + continue; + seen |= mask; + if (seen != 0xff) + printf ("1 << VREG_LANE (N) & %d ? %c%02x_REGS : ", mask, letter, mask); + else + printf ("%c%02x_REGS", letter, mask); + } +} + +static void +regno_reg_class_2 (void) +{ + printf ("#define REGNO_REG_CLASS(N) \\\n" + " ((N) < ACC_REG \\\n" + " ? ((N) < VR2_REG \\\n" + " ? ("); + regno_reg_class_1 ('S', scalar_lanes, ARRAY_SIZE (scalar_lanes)); + printf (") \\\n" + " : ("); + regno_reg_class_1 ('V', vec_lanes, VEC_NSETS); + printf (")) \\\n" + " : ((N) < VFLAGS_REG \\\n" + " ? ("); + regno_reg_class_1 ('A', acc_lanes, ACC_NSETS); + printf (") \\\n" + " : ("); + regno_reg_class_1 ('F', flag_lanes, FLAG_NSETS); + printf (")))\n\n"); +} + +/* Print FIXED_REGISTERS / CALL_USED_REGISTERS according to PREFIX. + For call used registers, the call used scalars are marked in SCALAR_USED, + and the call used non-scalar vector registers are marked in VREG_USED. */ +static void +print_fixed_regs (const char *prefix, long scalar_used, long vreg_used) +{ + int n_printed = 0; + int i, j; + +#define PRINT_VAL(VAL) \ + do \ + { \ + printf ("%d, ", (VAL) != 0); \ + if (++n_printed > 15) \ + { \ + printf ("\\\n "); \ + n_printed = 0; \ + } \ + } while (0) + + printf ("#define %s_REGISTERS \\\n{ \\\n " + "/* Scalar registers. Stack pointer and bss base are fixed. */ \\\n" + " ", prefix); + for (i = 0; i < 16; i++) + PRINT_VAL (i == STACK_POINTER_REGNUM || i == BSS_BASE_REGNUM + || ((1 << i) & scalar_used)); + printf ("/* vr2-vr30: non-scalar vector registers. */ \\\n "); + for (i = 2; i < 31; i++) + for (j = 0; j < regs_per_vreg; j++) + PRINT_VAL ((1 << i) & vreg_used); + printf ("/* vr31: call stack; vr32-vr61: reserved. */ \\\n "); + for (i = 31; i < 62; i++) + for (j = 0; j < regs_per_vreg; j++) + PRINT_VAL (1); + printf ("/* Accumulator and flags are not fixed to allow lane allocation. */ \\\n "); + for (i = 62; i < 64; i++) + for (j = 0; j < regs_per_vreg; j++) + PRINT_VAL (scalar_used); + for (i = 0; i < (int) ARRAY_SIZE (fake_reg_names); i++) + printf ("1 /* %s */, ", fake_reg_names[i]); + printf ("\\\n}\n\n"); +} + +static void +emit_regsets (void) +{ + int i, j; + int n_printed; + const char *name; + int n_regs = 0; + +#define COUNT_REG \ + do \ + { \ + n_regs++; \ + if (++n_printed > 7) \ + { \ + printf ("\\\n "); \ + n_printed = 0; \ + } \ + } while (0) + + printf ("#define REGISTER_NAMES \\\n{ \\\n" + " \"i0\", \"i1\", \"i2\", \"i3\", \"i4\", \"i5\", \"i6\", \"i7\", \\\n" + " \"i8\", \"i9\", \"i10\", \"i11\", \"i12\", \"i13\", \"i14\", \"i15\", \\\n "); + n_regs += 16; + for (i = 2, n_printed = 0; i < 62; i++) + { + for (j = 0; j < 16 / MXP_UNITS_PER_MXP_VEC_REG; j++) + { + if (j) + printf ("\"vr%d_%d\",%s", i, j * MXP_UNITS_PER_MXP_VEC_REG / 2, + " " + (i > 9)); + else + printf ("\"vr%d\",%s", i, " " + (i > 9)); + COUNT_REG; + } + } + name = "acc"; + do + { + for (j = 0; j < 16 / MXP_UNITS_PER_MXP_VEC_REG; j++) + { + if (j) + printf ("\"%s_%d\",%s", name, j, " " + (*name != 'a')); + else + printf ("\"%s\",%s", name, " " + (*name != 'a')); + COUNT_REG; + } + } while (*name == 'a' && (name = "vflags")); + for (i = 0; i < (int) ARRAY_SIZE (fake_reg_names); i++) + { + printf ("\"%s\", ", fake_reg_names[i]); + COUNT_REG; + } + if (n_printed) + printf ("\\\n"); + printf("}\n\n"); + printf ("#define ADDITIONAL_REGISTER_NAMES" + " { { \"vr0\", 0}, { \"vr1\", 8} }\n\n"); + + printf ("#define LAST_SCALAR_REG %d\n\n", 15); + printf ("#define SCALAR_REGNO_P(N) \\\n" + " ((N) <= LAST_SCALAR_REG || ((N) >= "); + upputs (fake_reg_names[0]); + printf ("_REG && n <= "); + upputs (fake_reg_names[ARRAY_SIZE (fake_reg_names)-1]); + printf ("_REG))\n"); + printf ("#define LANES_PER_REG %d\n", MXP_UNITS_PER_MXP_VEC_REG / 2); + printf ("#define LANE0_REGNO(N) ((N) & -%d)\n", regs_per_vreg); + printf ("#define VREG_LANE(N) (((N) & %d) * LANES_PER_REG)\n", + regs_per_vreg - 1); + printf ("#define REGS_PER_VREG %d\n\n", regs_per_vreg); + printf ("#define FIRST_PSEUDO_REGISTER %d\n\n", n_regs); + regno_reg_class_2 (); + + print_fixed_regs ("FIXED", 0, 0); + print_fixed_regs ("CALL_USED", 0xff, 0x1ffff); + + printf ("enum reg_class\n{"); + for (i = j = 0; i < N_RCLASS; i++) + { + if (!valid_regclass (i)) + continue; + if (j++ % 4 == 0) + printf ("\n "); + else + printf (" "); + emit_regclass_name (i); + printf (","); + } + printf (" LIM_REG_CLASSES\n};\n\n" + "#define N_REG_CLASSES (int) LIM_REG_CLASSES\n\n" + "#define REG_CLASS_NAMES \\\n{"); + for (i = j = 0; i < N_RCLASS; i++) + { + if (!valid_regclass (i)) + continue; + if (j++ % 4 == 0) + printf (" \\\n \""); + else + printf (" \""); + emit_regclass_name (i); + printf ("\","); + } + printf (" \"LIM_REG_CLASSES\" \\\n};\n\n"); + printf ("#define REG_CLASS_CONTENTS \\\n{ \\\n"); + for (i = 0; i < N_RCLASS; i++) + { + if (!valid_regclass (i)) + continue; + printf ("/* "); + emit_regclass_name (i); + printf (" */ \\\n { "); + emit_regclass_content (i); + printf (" }, \\\n"); + } + printf ("}\n"); + printf ("\n" + "#define REG_ALLOC_ORDER \\\n" + "{ \\\n" + " /* Non-scalar general registers. */ \\\n "); + for (i = 2, n_printed = 0; i < 62; i++) + { + for (j = 0; j < 8 / MXP_UNITS_PER_MXP_VEC_REG; j++) + { + printf ("%d, ", i * 16 / MXP_UNITS_PER_MXP_VEC_REG + j); + COUNT_REG; + } + } + printf ("/* Other non-scalar vector registers. */ \\\n "); + for (i = 2, n_printed = 0; i < 62; i++) + { + for (j = 8 / MXP_UNITS_PER_MXP_VEC_REG; + j < 16 / MXP_UNITS_PER_MXP_VEC_REG; j++) + { + printf ("%d, ", i * 16 / MXP_UNITS_PER_MXP_VEC_REG + j); + COUNT_REG; + } + } + printf ("/* Scalar registers */ \\\n" + " 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 0, 8,\\\n" + " /* Accumulator */ \\\n "); + for (j = 0; j < 16 / MXP_UNITS_PER_MXP_VEC_REG; j++) + printf ("%d, ", 62 * 16 / MXP_UNITS_PER_MXP_VEC_REG + j); + printf ("\\\n}\n"); + +} + +static void +emit_md (void) +{ + int n_regs = 0; + int i; + + printf ("(define_constants\n"); + n_regs += 16; /* Scalar regs. */ + printf (" [(VR2_REG\t\t%d)\n", n_regs); + n_regs += 29 * regs_per_vreg; /* Advance past vr2..vr30. */ + printf (" (CALL_STACK_REG\t%d)\n", n_regs); + printf (" (VR32_REG\t\t%d)\n", n_regs += regs_per_vreg); + n_regs += 30 * regs_per_vreg; /* Advance past vr32..vr62. */ + printf (" (ACC_REG\t\t%d)\n", n_regs); + printf (" (ACCH_REG\t\t%d)\n", n_regs + regs_per_vreg/2); + printf (" (VFLAGS_REG\t\t%d)\n", n_regs += regs_per_vreg); + printf (" (VFLAGSH_REG\t\t%d)\n", n_regs + regs_per_vreg/2); + n_regs += regs_per_vreg; + for (i = 0; i < (int) ARRAY_SIZE (fake_reg_names); i++) + { + printf (" ("); + upputs (fake_reg_names[i]); + printf ("_REG\t\t%d)\n", n_regs++); + } + printf (" ])\n"); +} + +static void +emit_c (void) +{ + int j; + const char *s = "scalar_"; + int n_printed = 0; + + printf ( +"#include \"multi-target.h\"\n" +"START_TARGET_SPECIFIC\n" +"/* For each register class, indicate the lanes relevant for potential\n" +" cross-lane moves. For move destinations, we can disregard scalar\n" +" registers, since they allow cheap cross-lane moves. */\n"); + do + { + printf ("\nunsigned char class_%svec_lanes[] =\n{\n ", s); + for (j = 0; j < N_RCLASS; j++) + { + int i = j; + DECODE_REGCLASS + + if (!valid_regclass (j)) + continue; + if (n_printed++ > 12) + { + printf ("\n "); + n_printed = 1; + } + printf (" %d,", vec | flags | acc | (*s ? scalar : 0)); + } + printf ("\n};\n"); + } + while (*s && (s = "")); + printf ("END_TARGET_SPECIFIC"); +} + +int +main (int argc, char **argv) +{ + bool gen_header = false, gen_md = false; + char *progname = argv[0]; + + if (argc == 1) + ; + else if (argc == 2 && !strcmp (argv[1], "-h")) + gen_header = true; + else if (argc == 2 && !strcmp (argv[1], "-m")) + gen_md = true; + else + { + error ("usage: %s -h|-m > file", progname); + return FATAL_EXIT_CODE; + } + if (gen_header) + emit_regsets (); + else if (gen_md) + emit_md (); + else + emit_c (); + return 0; +} |