Home | History | Annotate | Download | only in test_generator
      1 # Copyright 2016, VIXL authors
      2 # All rights reserved.
      3 #
      4 # Redistribution and use in source and binary forms, with or without
      5 # modification, are permitted provided that the following conditions are met:
      6 #
      7 #   * Redistributions of source code must retain the above copyright notice,
      8 #     this list of conditions and the following disclaimer.
      9 #   * Redistributions in binary form must reproduce the above copyright notice,
     10 #     this list of conditions and the following disclaimer in the documentation
     11 #     and/or other materials provided with the distribution.
     12 #   * Neither the name of ARM Limited nor the names of its contributors may be
     13 #     used to endorse or promote products derived from this software without
     14 #     specific prior written permission.
     15 #
     16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
     17 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
     20 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     23 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 
     27 class OperandBase(object):
     28   """
     29   Base class for operands. An operand represents an argument passed to the
     30   macro-assembler to generate an instruction. For example, registers, conditions
     31   or C++ `Operand` and `MemOperand` objects are operands. We can think of them
     32   as "assemble-time" data.
     33 
     34   An operand is described with a type name, corresponding to the C++ type used
     35   to represent it (e.g. "Register", "ShiftType", "MemOperand", ...) and a name
     36   to identify it.
     37 
     38   Attributes:
     39     name      Name for the operand. It is used to declare variable names.
     40     type_name C++ type for the operand.
     41   """
     42 
     43   def __init__(self, name, type_name):
     44     self.name = name
     45     self.type_name = type_name
     46 
     47   @staticmethod
     48   def __iter__():
     49     """
     50     Operand types have to act as an iterator so that `generator.OperandList` can
     51     unwrap them (see `OperandWrapper` and `generator.OperandList.unwrap()`).
     52     """
     53     raise NotImplementedError()
     54 
     55   @staticmethod
     56   def GetArgumentType():
     57     """
     58     Return the type to be printed when passing this operand as an argument. For
     59     example, we could pass it by value or by reference.
     60     """
     61     raise NotImplementedError()
     62 
     63   @staticmethod
     64   def Declare():
     65     """
     66     Generate code to declare the operand `struct Operands`.
     67     """
     68     raise NotImplementedError()
     69 
     70   @staticmethod
     71   def Instantiate():
     72     """
     73     Generate code to instantiate the operand from inside a `kTests` loop, with
     74     `i` being the index variable.
     75     """
     76     raise NotImplementedError()
     77 
     78 
     79 class Operand(OperandBase):
     80   """
     81   Representation of a single operand. An operand has different variants
     82   (e.g. "r0", "r1", "LSL", ...) and a default one.
     83 
     84   Attributes:
     85     variants  List of variants the operand can take.
     86     default   Default variant to use.
     87 
     88   Note that the `variants` and `default` attributes are not used from inside the
     89   class. They are public fields used by the `TestCase` object to generate C++.
     90   """
     91 
     92   def __init__(self, name, type_name, variants, default):
     93     super().__init__(name, type_name)
     94     self.variants = variants
     95     self.default = default
     96 
     97   def __iter__(self):
     98     """
     99     Iterating over a single operand just yields the operand object.
    100     """
    101     yield self
    102 
    103   def GetArgumentType(self):
    104     """
    105     A single operand is passed to the macro-assembler by value. We just print
    106     the type name as it is.
    107     """
    108     return self.type_name
    109 
    110   def Declare(self):
    111     """
    112     Generate code to declare the operand as a single member in
    113     `struct Operands`.
    114     """
    115     return "{type_name} {name};".format(type_name=self.type_name,
    116                                         name=self.name)
    117 
    118   def Instantiate(self):
    119     """
    120     Generate code to instantiate the operand as a single local variable.
    121     """
    122     code = "{type_name} {name} = kTests[i].operands.{name};"
    123     return code.format(type_name=self.type_name, name=self.name)
    124 
    125 
    126 class OperandWrapper(OperandBase):
    127   """
    128   Representation for an operand type which wraps a list of more operands. It
    129   corresponds to C++ objects such as `Operand` or `MemOperand`.
    130 
    131   Attributes:
    132     operand_list  List of operand that this object wraps.
    133   """
    134 
    135   def __init__(self, name, type_name, operand_list):
    136     super().__init__(name, type_name)
    137     self.operand_list = operand_list
    138 
    139   def __iter__(self):
    140     """
    141     Iterate through the list of operands. This is required by
    142     `OperandList.unwrap()`.
    143     """
    144     return iter(self.operand_list)
    145 
    146   def GetArgumentType(self):
    147     """
    148     An operand wrapper object will be passed to the macro-assembler by
    149     reference.
    150     """
    151     return "const " + self.type_name + "&"
    152 
    153   def Declare(self):
    154     """
    155     An `OperandWrapper` object does not need to be declared in
    156     `struct Operands`. Although we do need to declare all underlying operands.
    157     """
    158     return "\n".join([operand.Declare() for operand in self.operand_list])
    159 
    160   def Instantiate(self):
    161     """
    162     Instantiate the underlying operands first and then finally instantiate the
    163     wrapper object.
    164 
    165     For example, if the object represents a C++ `Operand` type for a shifted
    166     register we would get:
    167 
    168     ~~~
    169     Register rm = kTests[i].operands.rm;
    170     Shift shift_type = kTests[i].operands.shift_type;
    171     uint32_t amount = kTests[i].operands.amount;
    172     Operand op(rm, shift_type, amount);
    173     ~~~
    174     """
    175     instantiate_wrapped_operands = "\n".join([
    176         operand.Instantiate()
    177         for operand in self.operand_list
    178     ])
    179     instantiate_this = "{type_name} {name}({arguments});".format(
    180         type_name=self.type_name,
    181         name=self.name,
    182         arguments=", ".join([operand.name for operand in self.operand_list]))
    183     return instantiate_wrapped_operands + "\n" + instantiate_this
    184 
    185 
    186 class Input(object):
    187   """
    188   Base class for all input types instantiated from a JSON description. This
    189   class should not be instantiated directly, instead, we create subclasses for
    190   each kind of input we have.
    191 
    192   As opposed to operands, an input represents data passed to an instruction at
    193   runtime. For example, it will be the value you write to a register before
    194   executing the instruction under test.
    195 
    196   Attributes:
    197     name    Name of the input. It is used to declare variable names.
    198 
    199     values  List of values this input can take.
    200     default Default value to use.
    201   """
    202 
    203   def __init__(self, name, values, default):
    204     self.name = name
    205 
    206     self.values = values
    207     self.default = default
    208 
    209   @staticmethod
    210   def Prologue():
    211     """
    212     Return a string describing what C++ code to emit before the instruction
    213     under test is emitted.
    214     """
    215     raise NotImplementedError()
    216 
    217   @staticmethod
    218   def Epilogue():
    219     """
    220     Return a string describing what C++ code to emit after the instruction under
    221     test is emitted.
    222     """
    223     raise NotImplementedError()
    224 
    225   @staticmethod
    226   def Declare():
    227     """
    228     Generate code to declare the input in `struct Inputs`.
    229     """
    230     raise NotImplementedError()
    231 
    232   @staticmethod
    233   def PrintInput(suffix = ""):
    234     """
    235     Generate code to print the input referred to by `self.name`. Optionally add
    236     `suffix` to the input's name.
    237     """
    238     raise NotImplementedError()
    239 
    240   @staticmethod
    241   def PrintOutput():
    242     """
    243     Generate code to print the input from the result buffer, indexed with `i`
    244     and `j`.
    245     """
    246     raise NotImplementedError()
    247 
    248   @staticmethod
    249   def InstantiateResult(suffix = ""):
    250     """
    251     Generate code to instantiate an input from the result buffer, indexed with
    252     `i`. Optionally add `suffix` to the input's name.
    253     """
    254     raise NotImplementedError()
    255 
    256   @staticmethod
    257   def InstantiateInput(suffix = ""):
    258     """
    259     Generate code to instantiate an input from the input buffer, indexed with
    260     `i`. Optionally add `suffix` to the input's name.
    261     """
    262     raise NotImplementedError()
    263 
    264   @staticmethod
    265   def InstantiateReference(suffix = ""):
    266     """
    267     Generate code to instantiate an input from the reference buffer, indexed
    268     with `i`. Optionally add `suffix` to the input's name.
    269     """
    270     raise NotImplementedError()
    271 
    272   @staticmethod
    273   def Compare(left_suffix, operand, right_suffix):
    274     """
    275     Generate code as a C++ expression comparing two inputs of this type.
    276     """
    277     raise NotImplementedError()
    278 
    279 
    280 class Scalar(Input):
    281   """
    282   Base class for inputs that are represented as a single scalar value.
    283   Subclasses should implement `TypeName()`, `Pri()` and `NDigit()` to specify
    284   how they should be represented and printed, see the `U32` class for an
    285   example.
    286   """
    287 
    288   @staticmethod
    289   def TypeName():
    290     """
    291     Return the type name as used to declare and instantiate this input.
    292     """
    293     raise NotImplementedError()
    294 
    295   @staticmethod
    296   def Pri():
    297     """
    298     Return the format string used to generate a call to `printf` to print this
    299     input type. For example, "PRIx32".
    300     """
    301     raise NotImplementedError()
    302 
    303   @staticmethod
    304   def NDigit():
    305     """
    306     Return the number of digits to use to print this input type.
    307     """
    308     raise NotImplementedError()
    309 
    310   def Declare(self):
    311     """
    312     A scalar input is declared as a single member in `struct Inputs`.
    313     """
    314     return "{type_name} {name};".format(type_name=self.TypeName(),
    315                                         name=self.name)
    316 
    317   def PrintInput(self, suffix = ""):
    318     code = "printf(\"0x%0{n_digit}\" {pri}, {name});"
    319     return code.format(n_digit=self.NDigit(), pri=self.Pri(),
    320                        name=self.name + suffix)
    321 
    322   def PrintOutput(self):
    323     code = "printf(\"0x%0{n_digit}\" {pri}, results[i]->outputs[j].{name});"
    324     return code.format(n_digit=self.NDigit(), pri=self.Pri(), name=self.name)
    325 
    326   def InstantiateResult(self, suffix = ""):
    327     code = "{type_name} {name}{suffix} = results[i]->outputs[j].{name};"
    328     return code.format(type_name=self.TypeName(), name=self.name, suffix=suffix)
    329 
    330   def InstantiateInput(self, suffix = ""):
    331     code = "{type_name} {name}{suffix} = kTests[i].inputs[j].{name};"
    332     return code.format(type_name=self.TypeName(), name=self.name, suffix=suffix)
    333 
    334   def InstantiateReference(self, suffix = ""):
    335     code = "{type_name} {name}{suffix} = reference[i].outputs[j].{name};"
    336     return code.format(type_name=self.TypeName(), name=self.name, suffix=suffix)
    337 
    338   def Compare(self, left_suffix, operand, right_suffix):
    339     return """
    340       ({name}{left_suffix} {operand} {name}{right_suffix})
    341       """.format(name=self.name, left_suffix=left_suffix, operand=operand,
    342                  right_suffix=right_suffix)
    343 
    344 
    345 class U32(Scalar):
    346   """
    347   Base class for inputs that can be represented as 32 bit unsigned words.
    348   """
    349 
    350   @staticmethod
    351   def TypeName():
    352     return "uint32_t"
    353 
    354   @staticmethod
    355   def Pri():
    356     return "PRIx32"
    357 
    358   @staticmethod
    359   def NDigit():
    360     return 8
    361 
    362 
    363 class Register(U32):
    364   """
    365   Description of a Register input. The `Prologue` and `Epilogue` methods
    366   describe what C++ code to emit to set and record the value of a register
    367   before and after executing an instruction.
    368   """
    369 
    370   def Prologue(self):
    371     code = "__ Ldr({name}, MemOperand(input_ptr, offsetof(Inputs, {name})));"
    372     return code.format(name=self.name)
    373 
    374   def Epilogue(self):
    375     code = "__ Str({name}, MemOperand(result_ptr, offsetof(Inputs, {name})));"
    376     return code.format(name=self.name)
    377 
    378 
    379 class NZCV(U32):
    380   """
    381   Description of NZCV flags as inputs to an instruction.
    382 
    383   The `Prologue` and `Epilogue` methods describe what C++ code to emit to set
    384   and record the NZCV flags before and after emitting the instruction under
    385   test.
    386   """
    387 
    388   def Prologue(self):
    389     # When setting the `NZCV` flags, we need to make sure we do not override the
    390     # `Q` bit. Therefore we use two scratch registers that we push on the stack
    391     # first to allow the instruction to use them as operands.
    392     code = """{{
    393           UseScratchRegisterScope temp_registers(&masm);
    394           Register nzcv_bits = temp_registers.Acquire();
    395           Register saved_q_bit = temp_registers.Acquire();
    396           // Save the `Q` bit flag.
    397           __ Mrs(saved_q_bit, APSR);
    398           __ And(saved_q_bit, saved_q_bit, QFlag);
    399           // Set the `NZCV` and `Q` flags together.
    400           __ Ldr(nzcv_bits, MemOperand(input_ptr, offsetof(Inputs, {})));
    401           __ Orr(nzcv_bits, nzcv_bits, saved_q_bit);
    402           __ Msr(APSR_nzcvq, nzcv_bits);
    403         }}
    404         """
    405     return code.format(self.name)
    406 
    407   def Epilogue(self):
    408     code = """{{
    409           UseScratchRegisterScope temp_registers(&masm);
    410           Register nzcv_bits = temp_registers.Acquire();
    411           __ Mrs(nzcv_bits, APSR);
    412           // Only record the NZCV bits.
    413           __ And(nzcv_bits, nzcv_bits, NZCVFlag);
    414           __ Str(nzcv_bits, MemOperand(result_ptr, offsetof(Inputs, {})));
    415         }}
    416         """
    417     return code.format(self.name)
    418 
    419 
    420 class Q(U32):
    421   """
    422   Description of the Q flag as inputs to an instruction.
    423 
    424   The `Prologue` and `Epilogue` methods describe what C++ code to emit to set
    425   and record the Q flag before and after emitting the instruction under test.
    426   """
    427 
    428   def Prologue(self):
    429     # When clearing or setting the `Q` bit, we need to make sure the `NZCV`
    430     # flags are not overriden. Therefore we use two scratch registers that we
    431     # push on the stack first to allow the instruction to use them as operands.
    432     code = """{{
    433           UseScratchRegisterScope temp_registers(&masm);
    434           Register q_bit = temp_registers.Acquire();
    435           Register saved_nzcv_bits = temp_registers.Acquire();
    436           // Save the `NZCV` flags.
    437           __ Mrs(saved_nzcv_bits, APSR);
    438           __ And(saved_nzcv_bits, saved_nzcv_bits, NZCVFlag);
    439           // Set the `NZCV` and `Q` flags together.
    440           __ Ldr(q_bit, MemOperand(input_ptr, offsetof(Inputs, {})));
    441           __ Orr(q_bit, q_bit, saved_nzcv_bits);
    442           __ Msr(APSR_nzcvq, q_bit);
    443         }}
    444         """
    445     return code.format(self.name)
    446 
    447   def Epilogue(self):
    448     code = """{{
    449           UseScratchRegisterScope temp_registers(&masm);
    450           Register q_bit = temp_registers.Acquire();
    451           __ Mrs(q_bit, APSR);
    452           // Only record the Q bit.
    453           __ And(q_bit, q_bit, QFlag);
    454           __ Str(q_bit, MemOperand(result_ptr, offsetof(Inputs, {})));
    455         }}
    456         """
    457     return code.format(self.name)
    458 
    459 
    460 class GE(U32):
    461   """
    462   Description of the GE flag as inputs to an instruction.
    463 
    464   The `Prologue` and `Epilogue` methods describe what C++ code to emit to set
    465   and record the GE flags before and after emitting the instruction under test.
    466   """
    467 
    468   def Prologue(self):
    469     # We need a scratch register to load the `GE` flags. It may alias a register
    470     # used by the instruction so we save it on the stack.
    471     code = """{{
    472           UseScratchRegisterScope temp_registers(&masm);
    473           Register ge_bits = temp_registers.Acquire();
    474           __ Ldr(ge_bits, MemOperand(input_ptr, offsetof(Inputs, {})));
    475           __ Msr(APSR_g, ge_bits);
    476         }}
    477         """
    478     return code.format(self.name)
    479 
    480   def Epilogue(self):
    481     code = """{{
    482           UseScratchRegisterScope temp_registers(&masm);
    483           Register ge_bits = temp_registers.Acquire();
    484           __ Mrs(ge_bits, APSR);
    485           // Only record the GE bits.
    486           __ And(ge_bits, ge_bits, GEFlags);
    487           __ Str(ge_bits, MemOperand(result_ptr, offsetof(Inputs, {})));
    488         }}
    489         """
    490     return code.format(self.name)
    491 
    492 
    493 class MemOperand(Input):
    494   """
    495   Description of a memory location input, used to test a `MemOperand` operand.
    496 
    497   A memory location input is a compound type and is represented as an
    498   array of two `uint32_t` values, an "offset" and a "data":
    499 
    500   ~~~
    501   {
    502     0x0,       // Offset used to record the base register in case it was
    503                // updated.
    504     0xabababab // 32 bit value in memory the instruction should work with.
    505   }
    506   ~~~
    507   """
    508 
    509   def Declare(self):
    510     """
    511     Declare the input as a two element array.
    512     """
    513     return "uint32_t {name}[2];".format(name=self.name)
    514 
    515   def PrintInput(self, suffix = ""):
    516     code = '''printf("{{0x%08" PRIx32 ", 0x%08" PRIx32 "}}",
    517                      {name}[0], {name}[1]);'''
    518     return code.format(name=self.name + suffix)
    519 
    520   def PrintOutput(self):
    521     code = '''printf("{{0x%08" PRIx32 ", 0x%08" PRIx32 "}}",
    522                      results[i]->outputs[j].{name}[0],
    523                      results[i]->outputs[j].{name}[1]);'''
    524     return code.format(name=self.name)
    525 
    526   def InstantiateResult(self, suffix = ""):
    527     code = """uint32_t {name}{suffix}[2] = {{
    528         results[i]->outputs[j].{name}[0],
    529         results[i]->outputs[j].{name}[1]
    530       }};
    531       """
    532     return code.format(name=self.name, suffix=suffix)
    533 
    534   def InstantiateInput(self, suffix = ""):
    535     code = """uint32_t {name}{suffix}[2] = {{
    536         kTests[i].inputs[j].{name}[0],
    537         kTests[i].inputs[j].{name}[1]
    538       }};
    539       """
    540     return code.format(name=self.name, suffix=suffix)
    541 
    542   def InstantiateReference(self, suffix = ""):
    543     code = """uint32_t {name}{suffix}[2] = {{
    544         results[i]->outputs[j].{name}[0],
    545         results[i]->outputs[j].{name}[1]
    546       }};
    547       """
    548     return code.format(name=self.name, suffix=suffix)
    549 
    550   def Compare(self, left_suffix, operand, right_suffix):
    551     return """
    552       (({name}{left_suffix}[0] {operand} {name}{right_suffix}[0]) &&
    553        ({name}{left_suffix}[1] {operand} {name}{right_suffix}[1]))
    554       """.format(name=self.name, left_suffix=left_suffix, operand=operand,
    555                  right_suffix=right_suffix)
    556 
    557   def Prologue(self):
    558     return """
    559       // Allocate 4 bytes for the instruction to work with.
    560       scratch_memory_buffers[i] = new byte[4];
    561       {{
    562         UseScratchRegisterScope temp_registers(&masm);
    563 
    564         Register {name}_tmp = temp_registers.Acquire();
    565         Register base_register = {name}.GetBaseRegister();
    566 
    567         // Write the expected data into the scratch buffer.
    568         __ Mov(base_register, Operand::From(scratch_memory_buffers[i]));
    569         __ Ldr({name}_tmp, MemOperand(input_ptr, offsetof(Inputs, {name}) + 4));
    570         __ Str({name}_tmp, MemOperand(base_register));
    571 
    572         // Compute the address to put into the base register so that the
    573         // `MemOperand` points to the right location.
    574         // TODO: Support more kinds of `MemOperand`.
    575         if (!{name}.IsPostIndex()) {{
    576           if ({name}.IsImmediate()) {{
    577             if ({name}.GetSign().IsPlus()) {{
    578               __ Mov({name}_tmp, {name}.GetOffsetImmediate());
    579               __ Sub(base_register, base_register, {name}_tmp);
    580             }} else {{
    581               __ Mov({name}_tmp, -{name}.GetOffsetImmediate());
    582               __ Add(base_register, base_register, {name}_tmp);
    583             }}
    584           }} else if ({name}.IsShiftedRegister()) {{
    585             __ Mov({name}_tmp, Operand({name}.GetOffsetRegister(),
    586                                        {name}.GetShift(),
    587                                        {name}.GetShiftAmount()));
    588             if ({name}.GetSign().IsPlus()) {{
    589               __ Sub(base_register, base_register, {name}_tmp);
    590             }} else {{
    591               __ Add(base_register, base_register, {name}_tmp);
    592             }}
    593           }}
    594         }}
    595       }}
    596       """.format(name=self.name)
    597 
    598   def Epilogue(self):
    599     # TODO: This generated code does not support recording the state for
    600     # instructions where the base register is the same as another register used
    601     # in the instruction. It is possible to do so but requires more temporary
    602     # registers which is not trivial to implement without
    603     # `UseScratchRegisterScope`. We will be able to lift this restriction when
    604     # it is implemented.
    605     return """{{
    606         UseScratchRegisterScope temp_registers(&masm);
    607         Register {name}_tmp = temp_registers.Acquire();
    608         Register base_register = {name}.GetBaseRegister();
    609 
    610         // Compute the address of the scratch buffer by from the base register. If
    611         // the instruction has updated the base register, we will be able to
    612         // record it.
    613         if (!{name}.IsPostIndex()) {{
    614           if ({name}.IsImmediate()) {{
    615             if ({name}.GetSign().IsPlus()) {{
    616               __ Mov({name}_tmp, {name}.GetOffsetImmediate());
    617               __ Add(base_register, base_register, {name}_tmp);
    618             }} else {{
    619               __ Mov({name}_tmp, -{name}.GetOffsetImmediate());
    620               __ Sub(base_register, base_register, {name}_tmp);
    621             }}
    622           }} else if ({name}.IsShiftedRegister()) {{
    623             __ Mov({name}_tmp, Operand({name}.GetOffsetRegister(),
    624                                        {name}.GetShift(),
    625                                        {name}.GetShiftAmount()));
    626             if ({name}.GetSign().IsPlus()) {{
    627               __ Add(base_register, base_register, {name}_tmp);
    628             }} else {{
    629               __ Sub(base_register, base_register, {name}_tmp);
    630             }}
    631           }}
    632         }}
    633 
    634         // Record the value of the base register, as an offset from the scratch
    635         // buffer's address.
    636         __ Mov({name}_tmp, Operand::From(scratch_memory_buffers[i]));
    637         __ Sub(base_register, base_register, {name}_tmp);
    638         __ Str(base_register, MemOperand(result_ptr, offsetof(Inputs, {name})));
    639 
    640         // Record the 32 bit word from memory.
    641         __ Ldr({name}_tmp, MemOperand({name}_tmp));
    642         __ Str({name}_tmp, MemOperand(result_ptr, offsetof(Inputs, {name}) + 4));
    643       }}
    644       """.format(name=self.name)
    645