assembler.hpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996, LongView Technologies L.L.C. $Revision: 1.34 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 const int nofRegisters = 8;     // total number of registers
00025 
00026 class Register: public ValueObj {
00027  private:
00028   int _number;
00029   
00030  public:
00031   // creation
00032   Register(void): _number(-1)                   {}
00033   Register(int number, char f): _number(number) {}      // f is only to make sure that
00034                                                         // an int is not accidentially
00035                                                         // converted into a Register...
00036 
00037   // attributes
00038   int number() const            { assert(isValid(), "not a register"); return _number; }
00039   bool isValid() const          { return (0 <= _number) && (_number < nofRegisters); }
00040   bool hasByteRegister() const  { return 0 <= _number && _number <= 3; }
00041 
00042   // comparison
00043   friend bool operator == (Register x, Register y) { return x._number == y._number; }
00044   friend bool operator != (Register x, Register y) { return x._number != y._number; }
00045 
00046   // debugging
00047   char* name() const;
00048 };
00049 
00050 
00051 // Available registers
00052 const Register eax = Register(0, ' ');
00053 const Register ecx = Register(1, ' ');
00054 const Register edx = Register(2, ' ');
00055 const Register ebx = Register(3, ' ');
00056 const Register esp = Register(4, ' ');
00057 const Register ebp = Register(5, ' ');
00058 const Register esi = Register(6, ' ');
00059 const Register edi = Register(7, ' ');
00060 const Register noreg; // Dummy register used in Load, LoadAddr, and Store.
00061 
00062 
00063 // Label represent a target destination for jumps, calls and non-local returns.
00064 // After declaration they can be freely used to denote known or (yet) unknown
00065 // target destinations. Assembler::bind is used to bind a label to the current
00066 // code position. A label can be bound only once.
00067 
00068 class Label : public ValueObj {
00069  private:
00070   // _pos encodes both the binding state (via its sign)
00071   // and the binding position (via its value) of a label.
00072   //
00073   // _pos <  0  bound label, pos() returns the target (jump) position
00074   // _pos == 0  unused label
00075   // _pos >  0  unbound label, pos() returns the last displacement (see .cpp file) in the chain
00076   int _pos;
00077 
00078   int pos() const {
00079     if (_pos < 0) return -_pos - 1;
00080     if (_pos > 0) return  _pos - 1;
00081     ShouldNotReachHere();
00082     return 0;
00083   }
00084 
00085   void bind_to(int pos)         { assert(pos >= 0, "illegal position"); _pos = -pos - 1; }
00086   void link_to(int pos)         { assert(pos >= 0, "illegal position"); _pos =  pos + 1; }
00087   void unuse()                  { _pos = 0; }
00088 
00089  public:
00090   bool is_bound() const         { return _pos <  0; }
00091   bool is_unbound() const       { return _pos >  0; }
00092   bool is_unused() const        { return _pos == 0; }
00093 
00094   Label() : _pos(0)             {}
00095   ~Label()                      { assert(!is_unbound(), "unbound label"); }
00096 
00097   friend class Assembler;
00098   friend class MacroAssembler;
00099   friend class Displacement;
00100 };
00101 
00102 
00103 // Address operands for assembler
00104 
00105 class Address: public ValueObj {
00106  public:
00107   enum ScaleFactor {
00108     no_scale    = -1,
00109     times_1     =  0,
00110     times_2     =  1,
00111     times_4     =  2,
00112     times_8     =  3
00113   };
00114 
00115  private:
00116   Register              _base;
00117   Register              _index;
00118   ScaleFactor           _scale;
00119   int                   _disp;
00120   relocInfo::relocType  _rtype;
00121 
00122  public:
00123   Address();
00124   Address(int disp, relocInfo::relocType rtype);
00125   Address(Register base, int disp = 0, relocInfo::relocType rtype = relocInfo::none);
00126   Address(Register base, Register index, ScaleFactor scale, int disp = 0, relocInfo::relocType rtype = relocInfo::none);
00127 
00128   friend class Assembler;
00129 };
00130 
00131 
00132 // The assembler for the new backend
00133 
00134 class Assembler: public ResourceObj {
00135  protected:
00136   CodeBuffer* _code;
00137 
00138   char* _code_begin;                    // first byte of code buffer
00139   char* _code_limit;                    // first byte after code buffer
00140   char* _code_pos;                      // current code generation position
00141 
00142   Label _unbound_label;                 // the last label to be bound to _binding_pos, if unbound
00143   int   _binding_pos;                   // the position to which _unbound_label has to be bound, if there
00144 
00145   char* addr_at(int pos)                { return _code_begin + pos; }
00146 
00147   int  byte_at(int pos)                 { return *(unsigned char*)addr_at(pos); }
00148   void byte_at_put(int pos, int x)      { *(unsigned char*)addr_at(pos) = (unsigned char)x; }
00149 
00150   int  long_at(int pos)                 { return *(int*)addr_at(pos); }
00151   void long_at_put(int pos, int x)      { *(int*)addr_at(pos) = x; }
00152 
00153   bool is8bit(int x)                    { return -0x80 <= x && x < 0x80; }
00154   bool isByte(int x)                    { return 0 <= x && x < 0x100; }
00155   bool isShiftCount(int x)              { return 0 <= x && x < 32; }
00156 
00157   inline void emit_byte(int x);
00158   inline void emit_long(int x);
00159   inline void emit_data(int data, relocInfo::relocType rtype);
00160 
00161   void emit_arith_b(int op1, int op2, Register dst, int imm8);
00162 
00163   void emit_arith(int op1, int op2, Register dst, int imm32);
00164   void emit_arith(int op1, int op2, Register dst, oop obj);
00165   void emit_arith(int op1, int op2, Register dst, Register src);
00166 
00167   void emit_operand(Register reg, Register base, Register index, Address::ScaleFactor scale, int disp, relocInfo::relocType rtype);
00168   void emit_operand(Register reg, Address adr);
00169 
00170   void emit_farith(int b1, int b2, int i);
00171 
00172   void print  (Label& L);
00173   void bind_to(Label& L, int pos);
00174   void link_to(Label& L, Label& appendix);
00175 
00176  public:
00177   enum Condition {
00178     zero        = 0x4,
00179     notZero     = 0x5,
00180     equal       = 0x4,
00181     notEqual    = 0x5,
00182     less        = 0xc,
00183     lessEqual   = 0xe,
00184     greater     = 0xf,
00185     greaterEqual= 0xd,
00186     below       = 0x2,
00187     belowEqual  = 0x6,
00188     above       = 0x7,
00189     aboveEqual  = 0x3,
00190     overflow    = 0x0,
00191     noOverflow  = 0x1,
00192     carrySet    = 0x2,
00193     carryClear  = 0x3,
00194     negative    = 0x8,
00195     positive    = 0x9,
00196   };
00197 
00198   enum Constants {
00199     sizeOfCall = 5                      // length of call instruction in bytes
00200   };
00201 
00202   Assembler(CodeBuffer* code);
00203 
00204   void          finalize();             // call this before using/copying the code
00205   CodeBuffer*   code() const            { return _code; }
00206   char*         pc() const              { return _code_pos; }
00207   int           offset() const          { return _code_pos - _code_begin; }
00208 
00209   // Stack
00210   void pushad();
00211   void popad();
00212 
00213   void pushl(int imm32);
00214   void pushl(oop obj);
00215   void pushl(Register src);
00216   void pushl(Address src);
00217 
00218   void popl(Register dst);
00219   void popl(Address dst);
00220 
00221   // Moves
00222   void movb(Register dst, Address src);
00223   void movb(Address dst, int imm8);
00224   void movb(Address dst, Register src);
00225 
00226   void movw(Register dst, Address src);
00227   void movw(Address dst, Register src);
00228 
00229   void movl(Register dst, int imm32);
00230   void movl(Register dst, oop obj);
00231   void movl(Register dst, Register src);
00232   void movl(Register dst, Address src);
00233 
00234   void movl(Address dst, int imm32);
00235   void movl(Address dst, oop obj);
00236   void movl(Address dst, Register src);
00237 
00238   void movsxb(Register dst, Address src);
00239   void movsxb(Register dst, Register src);
00240 
00241   void movsxw(Register dst, Address src);
00242   void movsxw(Register dst, Register src);
00243 
00244   // Conditional moves (P6 only)
00245   void cmovccl(Condition cc, Register dst, int imm32);
00246   void cmovccl(Condition cc, Register dst, oop obj);
00247   void cmovccl(Condition cc, Register dst, Register src);
00248   void cmovccl(Condition cc, Register dst, Address src);
00249 
00250   // Arithmetics
00251   void adcl(Register dst, int imm32);
00252   void adcl(Register dst, Register src);
00253 
00254   void addl(Address dst, int imm32);
00255   void addl(Register dst, int imm32);
00256   void addl(Register dst, Register src);
00257 
00258   void andl(Register dst, int imm32);
00259   void andl(Register dst, Register src);
00260 
00261   void cmpl(Address dst, int imm32);
00262   void cmpl(Address dst, oop obj);
00263   void cmpl(Register dst, int imm32);
00264   void cmpl(Register dst, oop obj);
00265   void cmpl(Register dst, Register src);
00266   void cmpl(Register dst, Address src);
00267 
00268   void decb(Register dst);
00269   void decl(Register dst);
00270 
00271   void idivl(Register src);
00272 
00273   void imull(Register dst, Register src);
00274   void imull(Register dst, Register src, int value);
00275 
00276   void incl(Register dst);
00277   void incl(Address dst);
00278 
00279   void leal(Register dst, Address src);
00280 
00281   void mull(Register src);
00282 
00283   void negl(Register dst);
00284 
00285   void notl(Register dst);
00286 
00287   void orl(Register dst, int imm32);
00288   void orl(Register dst, Register src);
00289   void orl(Register dst, Address src);
00290 
00291   void rcll(Register dst, int imm8);
00292 
00293   void sarl(Register dst, int imm8);
00294   void sarl(Register dst);
00295 
00296   void sbbl(Register dst, int imm32);
00297   void sbbl(Register dst, Register src);
00298 
00299   void shldl(Register dst, Register src);
00300 
00301   void shll(Register dst, int imm8);
00302   void shll(Register dst);
00303 
00304   void shrdl(Register dst, Register src);
00305 
00306   void shrl(Register dst, int imm8);
00307   void shrl(Register dst);
00308 
00309   void subl(Register dst, int imm32);
00310   void subl(Register dst, Register src);
00311 
00312   void testb(Register dst, int imm8);
00313   void testl(Register dst, int imm32);
00314   void testl(Register dst, Register src);
00315 
00316   void xorl(Register dst, int imm32);
00317   void xorl(Register dst, Register src);
00318 
00319   // Miscellaneous
00320   void hlt();
00321   void int3();
00322   void nop();
00323   void ret(int imm16);
00324 
00325   // Labels
00326 
00327   void bind(Label& L);                  // binds an unbound label L to the current code position
00328   void merge(Label& L, Label& with);    // merges L and with, L is the merged label
00329 
00330   // Calls
00331   void call(Label& L);
00332   void call(char* entry, relocInfo::relocType rtype);
00333   void call(Register reg);
00334   void call(Address adr);
00335   
00336   // Jumps
00337   void jmp(char* entry, relocInfo::relocType rtype);
00338   void jmp(Register reg);
00339   void jmp(Address adr);
00340 
00341   // Label operations & relative jumps (PPUM Appendix D)
00342   void jmp(Label& L);           // unconditional jump to L
00343 
00344   // jccI is the generic conditional branch generator to run-
00345   // time routines, jcc is used for branches to labels. jcc
00346   // takes a branch opcode (cc) and a label (L) and generates
00347   // either a backward branch or a forward branch and links it
00348   // to the label fixup chain. Usage:
00349   //
00350   // Label L;           // unbound label
00351   // jcc(cc, L);        // forward branch to unbound label
00352   // bind(L);           // bind label to the current pc
00353   // jcc(cc, L);        // backward branch to bound label
00354   // bind(L);           // illegal: a label may be bound only once
00355   //
00356   // Note: The same Label can be used for forward and backward branches
00357   // but it may be bound only once.
00358 
00359   void jcc(Condition cc, char* dst, relocInfo::relocType rtype = relocInfo::runtime_call_type);
00360   void jcc(Condition cc, Label& L);
00361 
00362   // Support for inline cache information (see also IC_Info)
00363   void ic_info(Label& L, int flags);
00364   
00365   // Floating-point operations
00366   void fld1();
00367   void fldz();
00368 
00369   void fld_s(Address adr);
00370   void fld_d(Address adr);
00371 
00372   void fstp_s(Address adr);
00373   void fstp_d(Address adr);
00374 
00375   void fild_s(Address adr);
00376   void fild_d(Address adr);
00377 
00378   void fistp_s(Address adr);
00379   void fistp_d(Address adr);
00380 
00381   void fabs();
00382   void fchs();
00383 
00384   void fadd(int i);
00385   void fsub(int i);
00386   void fmul(int i);
00387   void fdiv(int i);
00388 
00389   void faddp(int i = 1);
00390   void fsubp(int i = 1);
00391   void fsubrp(int i = 1);
00392   void fmulp(int i = 1);
00393   void fdivp(int i = 1);
00394   void fprem();
00395   void fprem1();
00396 
00397   void fxch(int i = 1);
00398   void fincstp();
00399   void ffree(int i = 0);
00400 
00401   void ftst();
00402   void fcompp();
00403   void fnstsw_ax();
00404   void fwait();
00405 
00406   // For compatibility with old assembler only - should be removed at some point
00407   void Load (Register base, int disp, Register dst) { movl(dst, Address(base, disp)); }
00408   void Store(Register src, Register base, int disp) { movl(Address(base, disp), src); }
00409 };
00410 
00411 
00412 // MacroAssembler extends Assembler by a few macros used for
00413 // generating the interpreter and for compiled code.
00414 
00415 class MacroAssembler: public Assembler {
00416  public:
00417   MacroAssembler(CodeBuffer* code) : Assembler(code) {}
00418 
00419   // Alignment
00420   void align(int modulus);
00421 
00422   // Test-Instructions optimized for length
00423   void test (Register dst, int imm8);           // use testb if possible, testl otherwise
00424   
00425   // Stack frame operations
00426   void enter();
00427   void leave();
00428 
00429   // Support for inlined data
00430 
00431   void inline_oop(oop o);
00432 
00433   // C calls
00434   void set_last_Delta_frame_before_call();      // assumes that the return address has not been pushed yet
00435   void set_last_Delta_frame_after_call();       // assumes that the return address has been pushed already
00436   void reset_last_Delta_frame();
00437 
00438   void call_C(Label& L);
00439   void call_C(Label& L, Label& nlrTestPoint);
00440 
00441   void call_C(char* entry, relocInfo::relocType rtype);
00442   void call_C(char* entry, relocInfo::relocType rtype, Label& nlrTestPoint);
00443 
00444   void call_C(Register entry);
00445   void call_C(Register entry, Label& nlrTestPoint);
00446 
00447   // C calls to run-time routines with arguments (args are not preserved)
00448   void call_C(char* entry, Register arg1);
00449   void call_C(char* entry, Register arg1, Register arg2);
00450   void call_C(char* entry, Register arg1, Register arg2, Register arg3);
00451   void call_C(char* entry, Register arg1, Register arg2, Register arg3, Register arg4);
00452 
00453   // Stores
00454   void store_check(Register obj, Register tmp);
00455 
00456   // Floating-point comparisons
00457   // To jump conditionally on cc, test FPU status word with mask and
00458   // jump conditionally using cond.
00459   static void fpu_mask_and_cond_for(Condition cc, int& mask, Condition& cond);
00460 
00461   // Pop ST (ffree & fincstp combined)
00462   void fpop();
00463 
00464   // debugging
00465   static void print_reg(char* name, oop obj);
00466   static void inspector(oop edi, oop esi, oop ebp, oop esp, oop ebx, oop edx, oop ecx, oop eax, char* eip);
00467   void inspect(char* title = NULL);
00468 };

Generated on Mon Oct 9 13:37:01 2006 for Strongtalk VM by  doxygen 1.4.7