Coverage for /Syzygy/assm/assembler_base.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%770.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  //
  15    :  // This file declares implementation classes to generate assembly code.
  16    :  // The API to the assembler is intentionally very close to the API exposed
  17    :  // by the V8 assembler (see src/ia32/assembler-ia32.* in V8 repository).
  18    :  
  19    :  #ifndef SYZYGY_ASSM_ASSEMBLER_BASE_H_
  20    :  #define SYZYGY_ASSM_ASSEMBLER_BASE_H_
  21    :  
  22    :  #include "syzygy/assm/cond.h"
  23    :  #include "syzygy/assm/label_base.h"
  24    :  #include "syzygy/assm/operand_base.h"
  25    :  #include "syzygy/assm/register.h"
  26    :  #include "syzygy/assm/value_base.h"
  27    :  
  28    :  namespace assm {
  29    :  
  30    :  // The reference sizes the assembler supports coincides with register sizes.
  31    :  typedef RegisterSize ReferenceSize;
  32    :  
  33    :  // The assembler takes care of maintaining an output location (address), and
  34    :  // generating a stream of bytes and references as instructions are assembled.
  35    :  template <class ReferenceType>
  36    :  class AssemblerBase {
  37    :   public:
  38    :    typedef DisplacementBase<ReferenceType> Displacement;
  39    :    typedef ImmediateBase<ReferenceType> Immediate;
  40    :    typedef OperandBase<ReferenceType> Operand;
  41    :    typedef LabelBase<ReferenceType> Label;
  42    :  
  43    :    // Tracks a single embedded reference in the instruction.
  44    :    struct ReferenceInfo {
  45    :      size_t offset;
  46    :      ReferenceType reference;
  47    :      ReferenceSize size;
  48    :      bool pc_relative;
  49    :    };
  50    :  
  51    :    // The assembler pushes instructions and references to
  52    :    // one of these for serialization.
  53    :    class InstructionSerializer {
  54    :     public:
  55    :      virtual void AppendInstruction(uint32 location,
  56    :                                     const uint8* bytes,
  57    :                                     size_t num_bytes,
  58    :                                     const ReferenceInfo* refs,
  59    :                                     size_t num_refs) = 0;
  60    :      virtual bool FinalizeLabel(uint32 location,
  61    :                                 const uint8* bytes,
  62    :                                 size_t num_bytes) = 0;
  63    :    };
  64    :  
  65    :    // Constructs an assembler that assembles to @p delegate
  66    :    // starting at @p location.
  67    :    AssemblerBase(uint32 location, InstructionSerializer* serializer);
  68    :  
  69    :    // @name Accessors.
  70    :    // @{
  71  E :    uint32 location() const { return location_; }
  72  E :    void set_location(uint32 location) { location_ = location; }
  73    :    // @}
  74    :  
  75    :    // Emits one or more NOP instructions, their total length being @p size
  76    :    // bytes.
  77    :    // @param size The number of bytes of NOPs to generate.
  78    :    // @note For a generated NOP sequence of optimal performance it is best to
  79    :    //     call nop once rather than successively (ie: the NOP sequence generated
  80    :    //     by nop(x) nop(y) may perform worse than that generated by nop(x + y).
  81    :    void nop(size_t size);
  82    :  
  83    :    // @name Call instructions.
  84    :    // @{
  85    :    void call(const Immediate& dst);
  86    :    void call(const Operand& dst);
  87    :    // @}
  88    :  
  89    :   protected:
  90    :    // @name Control flow instructions.
  91    :    // These instructions are protected, as they're not appropriate to expose
  92    :    // for all assembler subclasses.
  93    :    // @{
  94    :    void j(ConditionCode cc, const Immediate& dst);
  95    :  
  96    :    // @param cc the condition code to generate.
  97    :    // @param dst the label to jump to.
  98    :    // @param size the requested size/reach of the instruction. Will generate the
  99    :    //     optimal reach if kSizeNone and the label is bound. Will generate long
 100    :    //     reach if kSizeNone and the label is unbound.
 101    :    // @returns true if successful, false if the requested reach is
 102    :    //     inappropriate.
 103    :    bool j(ConditionCode cc, Label* dst, RegisterSize size);
 104    :    bool j(ConditionCode cc, Label* dst);
 105    :    void jecxz(const Immediate& dst);
 106    :    void jmp(const Immediate& dst);
 107    :    void jmp(const Operand& dst);
 108    :    void jmp(const Register32& dst);
 109    :    void l(LoopCode lc, const Immediate& dst);
 110    :  
 111    :   public:
 112    :    void ret();
 113    :    void ret(uint16 n);
 114    :    // @}
 115    :  
 116    :    // @name Set flags.
 117    :    // @{
 118    :    void set(ConditionCode cc, const Register32& src);
 119    :    // @}
 120    :  
 121    :    // @name Byte mov varieties.
 122    :    // @{
 123    :    void mov_b(const Operand& dst, const Immediate& src);
 124    :    void movzx_b(const Register32& dst, const Operand& src);
 125    :    // @}
 126    :  
 127    :    // @name Double-word mov varieties.
 128    :    // @{
 129    :    void mov(const Register32& dst, const Register32& src);
 130    :    void mov(const Register32& dst, const Operand& src);
 131    :    void mov(const Operand& dst, const Register32& src);
 132    :    void mov(const Register32& dst, const Immediate& src);
 133    :    void mov(const Operand& dst, const Immediate& src);
 134    :    void mov_fs(const Register32& dst, const Operand& src);
 135    :    void mov_fs(const Operand& dst, const Register32& src);
 136    :    // @}
 137    :  
 138    :    // @name Load effective address.
 139    :    void lea(const Register32& dst, const Operand& src);
 140    :  
 141    :    // @name Stack manipulation.
 142    :    // @{
 143    :    void push(const Register32& src);
 144    :    void push(const Immediate& src);
 145    :    void push(const Operand& src);
 146    :    void pushad();
 147    :  
 148    :    void pop(const Register32& dst);
 149    :    void pop(const Operand& dst);
 150    :    void popad();
 151    :    // @}
 152    :  
 153    :    // @name Flag manipulation.
 154    :    // @{
 155    :    void pushfd();
 156    :    void popfd();
 157    :    void lahf();
 158    :    void sahf();
 159    :    // @}
 160    :  
 161    :    // @name Arithmetic operations.
 162    :    // @{
 163    :    void test(const Register8& dst, const Register8& src);
 164    :    void test(const Register8& dst, const Immediate& src);
 165    :  
 166    :    void test(const Register32& dst, const Register32& src);
 167    :    void test(const Register32& dst, const Operand& src);
 168    :    void test(const Operand& dst, const Register32& src);
 169    :    void test(const Register32& dst, const Immediate& src);
 170    :    void test(const Operand& dst, const Immediate& src);
 171    :  
 172    :    void cmp(const Register8& dst, const Register8& src);
 173    :    void cmp(const Register8& dst, const Immediate& src);
 174    :  
 175    :    void cmp(const Register32& dst, const Register32& src);
 176    :    void cmp(const Register32& dst, const Operand& src);
 177    :    void cmp(const Operand& dst, const Register32& src);
 178    :    void cmp(const Register32& dst, const Immediate& src);
 179    :    void cmp(const Operand& dst, const Immediate& src);
 180    :  
 181    :    void add(const Register8& dst, const Register8& src);
 182    :    void add(const Register8& dst, const Immediate& src);
 183    :  
 184    :    void add(const Register32& dst, const Register32& src);
 185    :    void add(const Register32& dst, const Operand& src);
 186    :    void add(const Operand& dst, const Register32& src);
 187    :    void add(const Register32& dst, const Immediate& src);
 188    :    void add(const Operand& dst, const Immediate& src);
 189    :  
 190    :    void sub(const Register8& dst, const Register8& src);
 191    :    void sub(const Register8& dst, const Immediate& src);
 192    :  
 193    :    void sub(const Register32& dst, const Register32& src);
 194    :    void sub(const Register32& dst, const Operand& src);
 195    :    void sub(const Operand& dst, const Register32& src);
 196    :    void sub(const Register32& dst, const Immediate& src);
 197    :    void sub(const Operand& dst, const Immediate& src);
 198    :    // @}
 199    :  
 200    :    // @name Logical operations.
 201    :    // @{
 202    :    void and(const Register8& dst, const Register8& src);
 203    :    void and(const Register8& dst, const Immediate& src);
 204    :  
 205    :    void and(const Register32& dst, const Register32& src);
 206    :    void and(const Register32& dst, const Operand& src);
 207    :    void and(const Operand& dst, const Register32& src);
 208    :    void and(const Register32& dst, const Immediate& src);
 209    :    void and(const Operand& dst, const Immediate& src);
 210    :  
 211    :    void xor(const Register8& dst, const Register8& src);
 212    :    void xor(const Register8& dst, const Immediate& src);
 213    :  
 214    :    void xor(const Register32& dst, const Register32& src);
 215    :    void xor(const Register32& dst, const Operand& src);
 216    :    void xor(const Operand& dst, const Register32& src);
 217    :    void xor(const Register32& dst, const Immediate& src);
 218    :    void xor(const Operand& dst, const Immediate& src);
 219    :    // @}
 220    :  
 221    :    // @name Shifting operations.
 222    :    // @{
 223    :    void shl(const Register32& dst, const Immediate& src);
 224    :    void shr(const Register32& dst, const Immediate& src);
 225    :    // @}
 226    :  
 227    :    // Exchange contents of two registers.
 228    :    // @param dst The destination register.
 229    :    // @param src The source register.
 230    :    // @note Exchanges involving eax generate shorter byte code.
 231    :    void xchg(const Register32& dst, const Register32& src);
 232    :    void xchg(const Register16& dst, const Register16& src);
 233    :    void xchg(const Register8& dst, const Register8& src);
 234    :  
 235    :    // Exchange contents of a register and memory.
 236    :    // @param dst The destination register.
 237    :    // @param src The source memory location.
 238    :    // @note This instruction can be used as a primitive for writing
 239    :    //     synchronization mechanisms as there is an implicit lock taken
 240    :    //     on @p src during execution.
 241    :    void xchg(const Register32& dst, const Operand& src);
 242    :  
 243    :    // @name Aliases
 244    :    // @{
 245  E :    void loop(const Immediate& dst) { l(kLoopOnCounter, dst); }
 246  E :    void loope(const Immediate& dst) { l(kLoopOnCounterAndZeroFlag, dst); }
 247  E :    void loopne(const Immediate& dst) {
 248  E :      l(kLoopOnCounterAndNotZeroFlag, dst);
 249  E :    }
 250    :    // @}
 251    :  
 252    :   private:
 253    :    friend class Label;
 254    :    class InstructionBuffer;
 255    :  
 256    :    // @name Nop instruction helpers.
 257    :    // @{
 258    :    // Each of these corresponds to a basic suggested NOP sequence. They
 259    :    // can each be extended by prefixing with 1 or more operand size (0x66)
 260    :    // prefixes. These are not exposed directly as the user should simply
 261    :    // call 'nop' instead.
 262    :    // @param prefix_count The number of operand size prefix bytes to apply.
 263    :    void nop1(size_t prefix_count);
 264    :    void nop4(size_t prefix_count);
 265    :    void nop5(size_t prefix_count);
 266    :    void nop7(size_t prefix_count);
 267    :    void nop8(size_t prefix_count);
 268    :    // @}
 269    :  
 270    :    // Output the instruction data in @p instr to our delegate.
 271    :    void Output(const InstructionBuffer& instr);
 272    :  
 273    :    // Finalizes the use of an unbound label.
 274    :    bool FinalizeLabel(uint32 location, uint32 destination, RegisterSize size);
 275    :  
 276    :    // Stores the current location of assembly.
 277    :    uint32 location_;
 278    :  
 279    :    // The delegate we push instructions at.
 280    :    InstructionSerializer* serializer_;
 281    :  };
 282    :  
 283    :  }  // namespace assm
 284    :  
 285    :  #include "syzygy/assm/assembler_base_impl.h"
 286    :  
 287    :  #endif  // SYZYGY_ASSM_ASSEMBLER_BASE_H_

Coverage information generated Thu Jan 14 17:40:38 2016.