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 F64(Scalar):
    364   @staticmethod
    365   def TypeName():
    366     return "uint64_t"
    367 
    368   @staticmethod
    369   def Pri():
    370     return "PRIx64"
    371 
    372   @staticmethod
    373   def NDigit():
    374     return 16
    375 
    376   def PrintInput(self, suffix = ""):
    377     code = "printf(\"0x%0{n_digit}\" {pri} \"(%g)\", {name}, RawbitsToDouble({name}));"
    378     return code.format(n_digit=self.NDigit(), pri=self.Pri(),
    379                        name=self.name + suffix)
    380 
    381 
    382 class Register(U32):
    383   """
    384   Description of a Register input. The `Prologue` and `Epilogue` methods
    385   describe what C++ code to emit to set and record the value of a register
    386   before and after executing an instruction.
    387   """
    388 
    389   def Prologue(self):
    390     code = "__ Ldr({name}, MemOperand(input_ptr, offsetof(Inputs, {name})));"
    391     return code.format(name=self.name)
    392 
    393   def Epilogue(self):
    394     code = "__ Str({name}, MemOperand(result_ptr, offsetof(Inputs, {name})));"
    395     return code.format(name=self.name)
    396 
    397 
    398 class DRegisterF64(F64):
    399   def Prologue(self):
    400     code = "__ Vldr({name}, MemOperand(input_ptr, offsetof(Inputs, {name})));"
    401     return code.format(name=self.name)
    402 
    403   def Epilogue(self):
    404     code = "__ Vstr({name}, MemOperand(result_ptr, offsetof(Inputs, {name})));"
    405     return code.format(name=self.name)
    406 
    407 
    408 class NZCV(U32):
    409   """
    410   Description of NZCV flags as inputs to an instruction.
    411 
    412   The `Prologue` and `Epilogue` methods describe what C++ code to emit to set
    413   and record the NZCV flags before and after emitting the instruction under
    414   test.
    415   """
    416 
    417   def Prologue(self):
    418     # When setting the `NZCV` flags, we need to make sure we do not override the
    419     # `Q` bit. Therefore we use two scratch registers that we push on the stack
    420     # first to allow the instruction to use them as operands.
    421     code = """{{
    422           UseScratchRegisterScope temp_registers(&masm);
    423           Register nzcv_bits = temp_registers.Acquire();
    424           Register saved_q_bit = temp_registers.Acquire();
    425           // Save the `Q` bit flag.
    426           __ Mrs(saved_q_bit, APSR);
    427           __ And(saved_q_bit, saved_q_bit, QFlag);
    428           // Set the `NZCV` and `Q` flags together.
    429           __ Ldr(nzcv_bits, MemOperand(input_ptr, offsetof(Inputs, {})));
    430           __ Orr(nzcv_bits, nzcv_bits, saved_q_bit);
    431           __ Msr(APSR_nzcvq, nzcv_bits);
    432         }}
    433         """
    434     return code.format(self.name)
    435 
    436   def Epilogue(self):
    437     code = """{{
    438           UseScratchRegisterScope temp_registers(&masm);
    439           Register nzcv_bits = temp_registers.Acquire();
    440           __ Mrs(nzcv_bits, APSR);
    441           // Only record the NZCV bits.
    442           __ And(nzcv_bits, nzcv_bits, NZCVFlag);
    443           __ Str(nzcv_bits, MemOperand(result_ptr, offsetof(Inputs, {})));
    444         }}
    445         """
    446     return code.format(self.name)
    447 
    448 
    449 class Q(U32):
    450   """
    451   Description of the Q flag as inputs to an instruction.
    452 
    453   The `Prologue` and `Epilogue` methods describe what C++ code to emit to set
    454   and record the Q flag before and after emitting the instruction under test.
    455   """
    456 
    457   def Prologue(self):
    458     # When clearing or setting the `Q` bit, we need to make sure the `NZCV`
    459     # flags are not overriden. Therefore we use two scratch registers that we
    460     # push on the stack first to allow the instruction to use them as operands.
    461     code = """{{
    462           UseScratchRegisterScope temp_registers(&masm);
    463           Register q_bit = temp_registers.Acquire();
    464           Register saved_nzcv_bits = temp_registers.Acquire();
    465           // Save the `NZCV` flags.
    466           __ Mrs(saved_nzcv_bits, APSR);
    467           __ And(saved_nzcv_bits, saved_nzcv_bits, NZCVFlag);
    468           // Set the `NZCV` and `Q` flags together.
    469           __ Ldr(q_bit, MemOperand(input_ptr, offsetof(Inputs, {})));
    470           __ Orr(q_bit, q_bit, saved_nzcv_bits);
    471           __ Msr(APSR_nzcvq, q_bit);
    472         }}
    473         """
    474     return code.format(self.name)
    475 
    476   def Epilogue(self):
    477     code = """{{
    478           UseScratchRegisterScope temp_registers(&masm);
    479           Register q_bit = temp_registers.Acquire();
    480           __ Mrs(q_bit, APSR);
    481           // Only record the Q bit.
    482           __ And(q_bit, q_bit, QFlag);
    483           __ Str(q_bit, MemOperand(result_ptr, offsetof(Inputs, {})));
    484         }}
    485         """
    486     return code.format(self.name)
    487 
    488 
    489 class GE(U32):
    490   """
    491   Description of the GE flag as inputs to an instruction.
    492 
    493   The `Prologue` and `Epilogue` methods describe what C++ code to emit to set
    494   and record the GE flags before and after emitting the instruction under test.
    495   """
    496 
    497   def Prologue(self):
    498     # We need a scratch register to load the `GE` flags.
    499     code = """{{
    500           UseScratchRegisterScope temp_registers(&masm);
    501           Register ge_bits = temp_registers.Acquire();
    502           __ Ldr(ge_bits, MemOperand(input_ptr, offsetof(Inputs, {})));
    503           __ Msr(APSR_g, ge_bits);
    504         }}
    505         """
    506     return code.format(self.name)
    507 
    508   def Epilogue(self):
    509     code = """{{
    510           UseScratchRegisterScope temp_registers(&masm);
    511           Register ge_bits = temp_registers.Acquire();
    512           __ Mrs(ge_bits, APSR);
    513           // Only record the GE bits.
    514           __ And(ge_bits, ge_bits, GEFlags);
    515           __ Str(ge_bits, MemOperand(result_ptr, offsetof(Inputs, {})));
    516         }}
    517         """
    518     return code.format(self.name)
    519 
    520 
    521 class FPSCR(U32):
    522   def Prologue(self):
    523     # We need a scratch register to load the `FPCSR` flags.
    524     code = """{{
    525           UseScratchRegisterScope temp_registers(&masm);
    526           Register fpsr_bits = temp_registers.Acquire();
    527           __ Ldr(fpsr_bits, MemOperand(input_ptr, offsetof(Inputs, {})));
    528           __ Vmsr(FPSCR, fpsr_bits);
    529         }}
    530         """
    531     return code.format(self.name)
    532 
    533   def Epilogue(self):
    534     code = """{{
    535           UseScratchRegisterScope temp_registers(&masm);
    536           Register fpsr_bits = temp_registers.Acquire();
    537           __ Vmrs(RegisterOrAPSR_nzcv(fpsr_bits.GetCode()), FPSCR);
    538           __ Str(fpsr_bits, MemOperand(result_ptr, offsetof(Inputs, {})));
    539         }}
    540         """
    541     return code.format(self.name)
    542 
    543 
    544 class MemOperand(Input):
    545   """
    546   Description of a memory location input, used to test a `MemOperand` operand.
    547 
    548   A memory location input is a compound type and is represented as an
    549   array of two `uint32_t` values, an "offset" and a "data":
    550 
    551   ~~~
    552   {
    553     0x0,       // Offset used to record the base register in case it was
    554                // updated.
    555     0xabababab // 32 bit value in memory the instruction should work with.
    556   }
    557   ~~~
    558   """
    559 
    560   def Declare(self):
    561     """
    562     Declare the input as a two element array.
    563     """
    564     return "uint32_t {name}[2];".format(name=self.name)
    565 
    566   def PrintInput(self, suffix = ""):
    567     code = '''printf("{{0x%08" PRIx32 ", 0x%08" PRIx32 "}}",
    568                      {name}[0], {name}[1]);'''
    569     return code.format(name=self.name + suffix)
    570 
    571   def PrintOutput(self):
    572     code = '''printf("{{0x%08" PRIx32 ", 0x%08" PRIx32 "}}",
    573                      results[i]->outputs[j].{name}[0],
    574                      results[i]->outputs[j].{name}[1]);'''
    575     return code.format(name=self.name)
    576 
    577   def InstantiateResult(self, suffix = ""):
    578     code = """uint32_t {name}{suffix}[2] = {{
    579         results[i]->outputs[j].{name}[0],
    580         results[i]->outputs[j].{name}[1]
    581       }};
    582       """
    583     return code.format(name=self.name, suffix=suffix)
    584 
    585   def InstantiateInput(self, suffix = ""):
    586     code = """uint32_t {name}{suffix}[2] = {{
    587         kTests[i].inputs[j].{name}[0],
    588         kTests[i].inputs[j].{name}[1]
    589       }};
    590       """
    591     return code.format(name=self.name, suffix=suffix)
    592 
    593   def InstantiateReference(self, suffix = ""):
    594     code = """uint32_t {name}{suffix}[2] = {{
    595         results[i]->outputs[j].{name}[0],
    596         results[i]->outputs[j].{name}[1]
    597       }};
    598       """
    599     return code.format(name=self.name, suffix=suffix)
    600 
    601   def Compare(self, left_suffix, operand, right_suffix):
    602     return """
    603       (({name}{left_suffix}[0] {operand} {name}{right_suffix}[0]) &&
    604        ({name}{left_suffix}[1] {operand} {name}{right_suffix}[1]))
    605       """.format(name=self.name, left_suffix=left_suffix, operand=operand,
    606                  right_suffix=right_suffix)
    607 
    608   def Prologue(self):
    609     return """
    610       // Allocate 4 bytes for the instruction to work with.
    611       scratch_memory_buffers[i] = new byte[4];
    612       {{
    613         UseScratchRegisterScope temp_registers(&masm);
    614 
    615         Register {name}_tmp = temp_registers.Acquire();
    616         Register base_register = {name}.GetBaseRegister();
    617 
    618         // Write the expected data into the scratch buffer.
    619         __ Mov(base_register, Operand::From(scratch_memory_buffers[i]));
    620         __ Ldr({name}_tmp, MemOperand(input_ptr, offsetof(Inputs, {name}) + 4));
    621         __ Str({name}_tmp, MemOperand(base_register));
    622 
    623         // Compute the address to put into the base register so that the
    624         // `MemOperand` points to the right location.
    625         // TODO: Support more kinds of `MemOperand`.
    626         if (!{name}.IsPostIndex()) {{
    627           if ({name}.IsImmediate()) {{
    628             if ({name}.GetSign().IsPlus()) {{
    629               __ Mov({name}_tmp, {name}.GetOffsetImmediate());
    630               __ Sub(base_register, base_register, {name}_tmp);
    631             }} else {{
    632               __ Mov({name}_tmp, -{name}.GetOffsetImmediate());
    633               __ Add(base_register, base_register, {name}_tmp);
    634             }}
    635           }} else if ({name}.IsShiftedRegister()) {{
    636             __ Mov({name}_tmp, Operand({name}.GetOffsetRegister(),
    637                                        {name}.GetShift(),
    638                                        {name}.GetShiftAmount()));
    639             if ({name}.GetSign().IsPlus()) {{
    640               __ Sub(base_register, base_register, {name}_tmp);
    641             }} else {{
    642               __ Add(base_register, base_register, {name}_tmp);
    643             }}
    644           }}
    645         }}
    646       }}
    647       """.format(name=self.name)
    648 
    649   def Epilogue(self):
    650     # TODO: This generated code does not support recording the state for
    651     # instructions where the base register is the same as another register used
    652     # in the instruction. It is possible to do so but requires more temporary
    653     # registers which is not trivial to implement without
    654     # `UseScratchRegisterScope`. We will be able to lift this restriction when
    655     # it is implemented.
    656     return """{{
    657         UseScratchRegisterScope temp_registers(&masm);
    658         Register {name}_tmp = temp_registers.Acquire();
    659         Register base_register = {name}.GetBaseRegister();
    660 
    661         // Compute the address of the scratch buffer by from the base register. If
    662         // the instruction has updated the base register, we will be able to
    663         // record it.
    664         if (!{name}.IsPostIndex()) {{
    665           if ({name}.IsImmediate()) {{
    666             if ({name}.GetSign().IsPlus()) {{
    667               __ Mov({name}_tmp, {name}.GetOffsetImmediate());
    668               __ Add(base_register, base_register, {name}_tmp);
    669             }} else {{
    670               __ Mov({name}_tmp, -{name}.GetOffsetImmediate());
    671               __ Sub(base_register, base_register, {name}_tmp);
    672             }}
    673           }} else if ({name}.IsShiftedRegister()) {{
    674             __ Mov({name}_tmp, Operand({name}.GetOffsetRegister(),
    675                                        {name}.GetShift(),
    676                                        {name}.GetShiftAmount()));
    677             if ({name}.GetSign().IsPlus()) {{
    678               __ Add(base_register, base_register, {name}_tmp);
    679             }} else {{
    680               __ Sub(base_register, base_register, {name}_tmp);
    681             }}
    682           }}
    683         }}
    684 
    685         // Record the value of the base register, as an offset from the scratch
    686         // buffer's address.
    687         __ Mov({name}_tmp, Operand::From(scratch_memory_buffers[i]));
    688         __ Sub(base_register, base_register, {name}_tmp);
    689         __ Str(base_register, MemOperand(result_ptr, offsetof(Inputs, {name})));
    690 
    691         // Record the 32 bit word from memory.
    692         __ Ldr({name}_tmp, MemOperand({name}_tmp));
    693         __ Str({name}_tmp, MemOperand(result_ptr, offsetof(Inputs, {name}) + 4));
    694       }}
    695       """.format(name=self.name)
    696