1 /*
   2  * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_ASM_REGISTER_HPP
  26 #define SHARE_VM_ASM_REGISTER_HPP
  27 
  28 #include "utilities/debug.hpp"
  29 #include "utilities/globalDefinitions.hpp"
  30 
  31 // Use AbstractRegister as shortcut
  32 class AbstractRegisterImpl;
  33 typedef AbstractRegisterImpl* AbstractRegister;
  34 
  35 
  36 // The super class for platform specific registers. Instead of using value objects,
  37 // registers are implemented as pointers. Subclassing is used so all registers can
  38 // use the debugging suport below. No virtual functions are used for efficiency.
  39 // They are canonicalized; i.e., registers are equal if their pointers are equal,
  40 // and vice versa. A concrete implementation may just map the register onto 'this'.
  41 
  42 class AbstractRegisterImpl {
  43  protected:
  44   int value() const                              { return (int)(intx)this; }
  45 };
  46 
  47 
  48 //
  49 // Macros for use in defining Register instances.  We'd like to be
  50 // able to simply define const instances of the RegisterImpl* for each
  51 // of the registers needed on a system in a header file.  However many
  52 // compilers don't handle this very well and end up producing a
  53 // private definition in every file which includes the header file.
  54 // Along with the static constructors necessary for initialization it
  55 // can consume a significant amount of space in the result library.
  56 //
  57 // The following macros allow us to declare the instance in a .hpp and
  58 // produce an enumeration value which has the same number.  Then in a
  59 // .cpp the the register instance can be defined using the enumeration
  60 // value.  This avoids the use of static constructors and multiple
  61 // definitions per .cpp.  In addition #defines for the register can be
  62 // produced so that the constant registers can be inlined.  These
  63 // macros should not be used inside other macros, because you may get
  64 // multiple evaluations of the macros which can give bad results.
  65 //
  66 // Here are some example uses and expansions.  Note that the macro
  67 // invocation is terminated with a ;.
  68 //
  69 // CONSTANT_REGISTER_DECLARATION(Register, G0, 0);
  70 //
  71 // extern const Register G0 ;
  72 // enum { G0_RegisterEnumValue = 0 } ;
  73 //
  74 // REGISTER_DECLARATION(Register, Gmethod, G5);
  75 //
  76 // extern const Register Gmethod ;
  77 // enum { Gmethod_RegisterEnumValue = G5_RegisterEnumValue } ;
  78 //
  79 // REGISTER_DEFINITION(Register, G0);
  80 //
  81 // const Register G0 = ( ( Register ) G0_RegisterEnumValue ) ;
  82 //
  83 
  84 #define AS_REGISTER(type,name)         ((type)name##_##type##EnumValue)
  85 
  86 #define CONSTANT_REGISTER_DECLARATION(type, name, value) \
  87 extern const type name;                                  \
  88 enum { name##_##type##EnumValue = (value) }
  89 
  90 #define REGISTER_DECLARATION(type, name, value) \
  91 extern const type name;                         \
  92 enum { name##_##type##EnumValue = value##_##type##EnumValue }
  93 
  94 #define REGISTER_DEFINITION(type, name) \
  95 const type name = ((type)name##_##type##EnumValue)
  96 
  97 #ifdef TARGET_ARCH_x86
  98 # include "register_x86.hpp"
  99 #endif
 100 #ifdef TARGET_ARCH_sparc
 101 # include "register_sparc.hpp"
 102 #endif
 103 #ifdef TARGET_ARCH_zero
 104 # include "register_zero.hpp"
 105 #endif
 106 #ifdef TARGET_ARCH_arm
 107 # include "register_arm.hpp"
 108 #endif
 109 #ifdef TARGET_ARCH_ppc
 110 # include "register_ppc.hpp"
 111 #endif
 112 #ifdef TARGET_ARCH_aarch64
 113 # include "register_aarch64.hpp"
 114 #endif
 115 
 116 
 117 // Debugging support
 118 
 119 inline void assert_different_registers(
 120   AbstractRegister a,
 121   AbstractRegister b
 122 ) {
 123   assert(
 124     a != b,
 125     "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT "", p2i(a), p2i(b)
 126   );
 127 }
 128 
 129 
 130 inline void assert_different_registers(
 131   AbstractRegister a,
 132   AbstractRegister b,
 133   AbstractRegister c
 134 ) {
 135   assert(
 136     a != b && a != c
 137            && b != c,
 138     "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
 139     ", c=" INTPTR_FORMAT "",
 140     p2i(a), p2i(b), p2i(c)
 141   );
 142 }
 143 
 144 
 145 inline void assert_different_registers(
 146   AbstractRegister a,
 147   AbstractRegister b,
 148   AbstractRegister c,
 149   AbstractRegister d
 150 ) {
 151   assert(
 152     a != b && a != c && a != d
 153            && b != c && b != d
 154                      && c != d,
 155     "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
 156     ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT "",
 157     p2i(a), p2i(b), p2i(c), p2i(d)
 158   );
 159 }
 160 
 161 
 162 inline void assert_different_registers(
 163   AbstractRegister a,
 164   AbstractRegister b,
 165   AbstractRegister c,
 166   AbstractRegister d,
 167   AbstractRegister e
 168 ) {
 169   assert(
 170     a != b && a != c && a != d && a != e
 171            && b != c && b != d && b != e
 172                      && c != d && c != e
 173                                && d != e,
 174     "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
 175     ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT "",
 176     p2i(a), p2i(b), p2i(c), p2i(d), p2i(e)
 177   );
 178 }
 179 
 180 
 181 inline void assert_different_registers(
 182   AbstractRegister a,
 183   AbstractRegister b,
 184   AbstractRegister c,
 185   AbstractRegister d,
 186   AbstractRegister e,
 187   AbstractRegister f
 188 ) {
 189   assert(
 190     a != b && a != c && a != d && a != e && a != f
 191            && b != c && b != d && b != e && b != f
 192                      && c != d && c != e && c != f
 193                                && d != e && d != f
 194                                          && e != f,
 195     "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
 196     ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
 197     ", f=" INTPTR_FORMAT "",
 198     p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f)
 199   );
 200 }
 201 
 202 
 203 inline void assert_different_registers(
 204   AbstractRegister a,
 205   AbstractRegister b,
 206   AbstractRegister c,
 207   AbstractRegister d,
 208   AbstractRegister e,
 209   AbstractRegister f,
 210   AbstractRegister g
 211 ) {
 212   assert(
 213     a != b && a != c && a != d && a != e && a != f && a != g
 214            && b != c && b != d && b != e && b != f && b != g
 215                      && c != d && c != e && c != f && c != g
 216                                && d != e && d != f && d != g
 217                                          && e != f && e != g
 218                                                    && f != g,
 219     "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
 220     ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
 221     ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT "",
 222     p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g)
 223   );
 224 }
 225 
 226 
 227 inline void assert_different_registers(
 228   AbstractRegister a,
 229   AbstractRegister b,
 230   AbstractRegister c,
 231   AbstractRegister d,
 232   AbstractRegister e,
 233   AbstractRegister f,
 234   AbstractRegister g,
 235   AbstractRegister h
 236 ) {
 237   assert(
 238     a != b && a != c && a != d && a != e && a != f && a != g && a != h
 239            && b != c && b != d && b != e && b != f && b != g && b != h
 240                      && c != d && c != e && c != f && c != g && c != h
 241                                && d != e && d != f && d != g && d != h
 242                                          && e != f && e != g && e != h
 243                                                    && f != g && f != h
 244                                                              && g != h,
 245     "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
 246     ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
 247     ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT "",
 248     p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h)
 249   );
 250 }
 251 
 252 
 253 inline void assert_different_registers(
 254   AbstractRegister a,
 255   AbstractRegister b,
 256   AbstractRegister c,
 257   AbstractRegister d,
 258   AbstractRegister e,
 259   AbstractRegister f,
 260   AbstractRegister g,
 261   AbstractRegister h,
 262   AbstractRegister i
 263 ) {
 264   assert(
 265     a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i
 266            && b != c && b != d && b != e && b != f && b != g && b != h && b != i
 267                      && c != d && c != e && c != f && c != g && c != h && c != i
 268                                && d != e && d != f && d != g && d != h && d != i
 269                                          && e != f && e != g && e != h && e != i
 270                                                    && f != g && f != h && f != i
 271                                                              && g != h && g != i
 272                                                                        && h != i,
 273     "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
 274     ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
 275     ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
 276     ", i=" INTPTR_FORMAT "",
 277     p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i)
 278   );
 279 }
 280 
 281 inline void assert_different_registers(
 282   AbstractRegister a,
 283   AbstractRegister b,
 284   AbstractRegister c,
 285   AbstractRegister d,
 286   AbstractRegister e,
 287   AbstractRegister f,
 288   AbstractRegister g,
 289   AbstractRegister h,
 290   AbstractRegister i,
 291   AbstractRegister j
 292 ) {
 293   assert(
 294     a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j
 295            && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j
 296                      && c != d && c != e && c != f && c != g && c != h && c != i && c != j
 297                                && d != e && d != f && d != g && d != h && d != i && d != j
 298                                          && e != f && e != g && e != h && e != i && e != j
 299                                                    && f != g && f != h && f != i && f != j
 300                                                              && g != h && g != i && g != j
 301                                                                        && h != i && h != j
 302                                                                                  && i != j,
 303     "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
 304     ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
 305     ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
 306     ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT "",
 307     p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j)
 308   );
 309 }
 310 
 311 inline void assert_different_registers(
 312   AbstractRegister a,
 313   AbstractRegister b,
 314   AbstractRegister c,
 315   AbstractRegister d,
 316   AbstractRegister e,
 317   AbstractRegister f,
 318   AbstractRegister g,
 319   AbstractRegister h,
 320   AbstractRegister i,
 321   AbstractRegister j,
 322   AbstractRegister k
 323 ) {
 324   assert(
 325     a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j && a !=k
 326            && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j && b !=k
 327                      && c != d && c != e && c != f && c != g && c != h && c != i && c != j && c !=k
 328                                && d != e && d != f && d != g && d != h && d != i && d != j && d !=k
 329                                          && e != f && e != g && e != h && e != i && e != j && e !=k
 330                                                    && f != g && f != h && f != i && f != j && f !=k
 331                                                              && g != h && g != i && g != j && g !=k
 332                                                                        && h != i && h != j && h !=k
 333                                                                                  && i != j && i !=k
 334                                                                                            && j !=k,
 335     "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
 336     ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
 337     ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
 338     ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT ", k=" INTPTR_FORMAT "",
 339     p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j), p2i(k)
 340   );
 341 }
 342 
 343 inline void assert_different_registers(
 344   AbstractRegister a,
 345   AbstractRegister b,
 346   AbstractRegister c,
 347   AbstractRegister d,
 348   AbstractRegister e,
 349   AbstractRegister f,
 350   AbstractRegister g,
 351   AbstractRegister h,
 352   AbstractRegister i,
 353   AbstractRegister j,
 354   AbstractRegister k,
 355   AbstractRegister l
 356 ) {
 357   assert(
 358     a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j && a !=k && a !=l
 359            && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j && b !=k && b !=l
 360                      && c != d && c != e && c != f && c != g && c != h && c != i && c != j && c !=k && c !=l
 361                                && d != e && d != f && d != g && d != h && d != i && d != j && d !=k && d !=l
 362                                          && e != f && e != g && e != h && e != i && e != j && e !=k && e !=l
 363                                                    && f != g && f != h && f != i && f != j && f !=k && f !=l
 364                                                              && g != h && g != i && g != j && g !=k && g !=l
 365                                                                        && h != i && h != j && h !=k && h !=l
 366                                                                                  && i != j && i !=k && i !=l
 367                                                                                            && j !=k && j !=l
 368                                                                                                     && k !=l,
 369     "registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
 370     ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
 371     ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
 372     ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT ", k=" INTPTR_FORMAT
 373     ", l=" INTPTR_FORMAT "",
 374     p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j), p2i(k), p2i(l)
 375   );
 376 }
 377 
 378 #endif // SHARE_VM_ASM_REGISTER_HPP