Home | History | Annotate | Download | only in aarch32
      1 // Copyright 2015, 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
     10 //     notice, this list of conditions and the following disclaimer in the
     11 //     documentation and/or other materials provided with the distribution.
     12 //   * Neither the name of ARM Limited nor the names of its contributors may
     13 //     be used to endorse or promote products derived from this software
     14 //     without 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
     18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     20 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26 // POSSIBILITY OF SUCH DAMAGE.
     27 
     28 extern "C" {
     29 #include <stdint.h>
     30 #include <inttypes.h>
     31 }
     32 
     33 #include <cassert>
     34 #include <cmath>
     35 #include <cstdio>
     36 #include <cstdlib>
     37 #include <cstring>
     38 #include <iostream>
     39 
     40 #include "utils-vixl.h"
     41 #include "aarch32/constants-aarch32.h"
     42 #include "aarch32/instructions-aarch32.h"
     43 #include "aarch32/operands-aarch32.h"
     44 
     45 namespace vixl {
     46 namespace aarch32 {
     47 
     48 // Operand
     49 
     50 std::ostream& operator<<(std::ostream& os, const Operand& operand) {
     51   if (operand.IsImmediate()) {
     52     return os << "#" << operand.GetImmediate();
     53   }
     54   if (operand.IsImmediateShiftedRegister()) {
     55     if ((operand.GetShift().IsLSL() || operand.GetShift().IsROR()) &&
     56         (operand.GetShiftAmount() == 0)) {
     57       return os << operand.GetBaseRegister();
     58     }
     59     if (operand.GetShift().IsRRX()) {
     60       return os << operand.GetBaseRegister() << ", rrx";
     61     }
     62     return os << operand.GetBaseRegister() << ", " << operand.GetShift() << " #"
     63               << operand.GetShiftAmount();
     64   }
     65   if (operand.IsRegisterShiftedRegister()) {
     66     return os << operand.GetBaseRegister() << ", " << operand.GetShift() << " "
     67               << operand.GetShiftRegister();
     68   }
     69   VIXL_UNREACHABLE();
     70   return os;
     71 }
     72 
     73 std::ostream& operator<<(std::ostream& os, const NeonImmediate& neon_imm) {
     74   if (neon_imm.IsDouble()) {
     75     if (neon_imm.imm_.d_ == 0) {
     76       if (copysign(1.0, neon_imm.imm_.d_) < 0.0) {
     77         return os << "#-0.0";
     78       }
     79       return os << "#0.0";
     80     }
     81     return os << "#" << std::setprecision(9) << neon_imm.imm_.d_;
     82   }
     83   if (neon_imm.IsFloat()) {
     84     if (neon_imm.imm_.f_ == 0) {
     85       if (copysign(1.0, neon_imm.imm_.d_) < 0.0) return os << "#-0.0";
     86       return os << "#0.0";
     87     }
     88     return os << "#" << std::setprecision(9) << neon_imm.imm_.f_;
     89   }
     90   if (neon_imm.IsInteger64()) {
     91     return os << "#0x" << std::hex << std::setw(16) << std::setfill('0')
     92               << neon_imm.imm_.u64_ << std::dec;
     93   }
     94   return os << "#" << neon_imm.imm_.u32_;
     95 }
     96 
     97 // SOperand
     98 
     99 std::ostream& operator<<(std::ostream& os, const SOperand& operand) {
    100   if (operand.IsImmediate()) {
    101     return os << operand.GetNeonImmediate();
    102   }
    103   return os << operand.GetRegister();
    104 }
    105 
    106 // DOperand
    107 
    108 std::ostream& operator<<(std::ostream& os, const DOperand& operand) {
    109   if (operand.IsImmediate()) {
    110     return os << operand.GetNeonImmediate();
    111   }
    112   return os << operand.GetRegister();
    113 }
    114 
    115 // QOperand
    116 
    117 std::ostream& operator<<(std::ostream& os, const QOperand& operand) {
    118   if (operand.IsImmediate()) {
    119     return os << operand.GetNeonImmediate();
    120   }
    121   return os << operand.GetRegister();
    122 }
    123 
    124 
    125 ImmediateVbic::ImmediateVbic(DataType dt, const NeonImmediate& neon_imm) {
    126   if (neon_imm.IsInteger32()) {
    127     uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
    128     if (dt.GetValue() == I16) {
    129       if ((immediate & ~0xff) == 0) {
    130         SetEncodingValue(0x9);
    131         SetEncodedImmediate(immediate);
    132       } else if ((immediate & ~0xff00) == 0) {
    133         SetEncodingValue(0xb);
    134         SetEncodedImmediate(immediate >> 8);
    135       }
    136     } else if (dt.GetValue() == I32) {
    137       if ((immediate & ~0xff) == 0) {
    138         SetEncodingValue(0x1);
    139         SetEncodedImmediate(immediate);
    140       } else if ((immediate & ~0xff00) == 0) {
    141         SetEncodingValue(0x3);
    142         SetEncodedImmediate(immediate >> 8);
    143       } else if ((immediate & ~0xff0000) == 0) {
    144         SetEncodingValue(0x5);
    145         SetEncodedImmediate(immediate >> 16);
    146       } else if ((immediate & ~0xff000000) == 0) {
    147         SetEncodingValue(0x7);
    148         SetEncodedImmediate(immediate >> 24);
    149       }
    150     }
    151   }
    152 }
    153 
    154 
    155 DataType ImmediateVbic::DecodeDt(uint32_t cmode) {
    156   switch (cmode) {
    157     case 0x1:
    158     case 0x3:
    159     case 0x5:
    160     case 0x7:
    161       return I32;
    162     case 0x9:
    163     case 0xb:
    164       return I16;
    165     default:
    166       break;
    167   }
    168   VIXL_UNREACHABLE();
    169   return kDataTypeValueInvalid;
    170 }
    171 
    172 
    173 NeonImmediate ImmediateVbic::DecodeImmediate(uint32_t cmode,
    174                                              uint32_t immediate) {
    175   switch (cmode) {
    176     case 0x1:
    177     case 0x9:
    178       return immediate;
    179     case 0x3:
    180     case 0xb:
    181       return immediate << 8;
    182     case 0x5:
    183       return immediate << 16;
    184     case 0x7:
    185       return immediate << 24;
    186     default:
    187       break;
    188   }
    189   VIXL_UNREACHABLE();
    190   return 0;
    191 }
    192 
    193 
    194 ImmediateVmov::ImmediateVmov(DataType dt, const NeonImmediate& neon_imm) {
    195   if (neon_imm.IsInteger()) {
    196     switch (dt.GetValue()) {
    197       case I8:
    198         if (neon_imm.CanConvert<uint8_t>()) {
    199           SetEncodingValue(0xe);
    200           SetEncodedImmediate(neon_imm.GetImmediate<uint8_t>());
    201         }
    202         break;
    203       case I16:
    204         if (neon_imm.IsInteger32()) {
    205           uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
    206           if ((immediate & ~0xff) == 0) {
    207             SetEncodingValue(0x8);
    208             SetEncodedImmediate(immediate);
    209           } else if ((immediate & ~0xff00) == 0) {
    210             SetEncodingValue(0xa);
    211             SetEncodedImmediate(immediate >> 8);
    212           }
    213         }
    214         break;
    215       case I32:
    216         if (neon_imm.IsInteger32()) {
    217           uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
    218           if ((immediate & ~0xff) == 0) {
    219             SetEncodingValue(0x0);
    220             SetEncodedImmediate(immediate);
    221           } else if ((immediate & ~0xff00) == 0) {
    222             SetEncodingValue(0x2);
    223             SetEncodedImmediate(immediate >> 8);
    224           } else if ((immediate & ~0xff0000) == 0) {
    225             SetEncodingValue(0x4);
    226             SetEncodedImmediate(immediate >> 16);
    227           } else if ((immediate & ~0xff000000) == 0) {
    228             SetEncodingValue(0x6);
    229             SetEncodedImmediate(immediate >> 24);
    230           } else if ((immediate & ~0xff00) == 0xff) {
    231             SetEncodingValue(0xc);
    232             SetEncodedImmediate(immediate >> 8);
    233           } else if ((immediate & ~0xff0000) == 0xffff) {
    234             SetEncodingValue(0xd);
    235             SetEncodedImmediate(immediate >> 16);
    236           }
    237         }
    238         break;
    239       case I64: {
    240         bool is_valid = true;
    241         uint32_t encoding = 0;
    242         if (neon_imm.IsInteger32()) {
    243           uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
    244           uint32_t mask = 0xff000000;
    245           for (uint32_t set_bit = 1 << 3; set_bit != 0; set_bit >>= 1) {
    246             if ((immediate & mask) == mask) {
    247               encoding |= set_bit;
    248             } else if ((immediate & mask) != 0) {
    249               is_valid = false;
    250               break;
    251             }
    252             mask >>= 8;
    253           }
    254         } else {
    255           uint64_t immediate = neon_imm.GetImmediate<uint64_t>();
    256           uint64_t mask = UINT64_C(0xff) << 56;
    257           for (uint32_t set_bit = 1 << 7; set_bit != 0; set_bit >>= 1) {
    258             if ((immediate & mask) == mask) {
    259               encoding |= set_bit;
    260             } else if ((immediate & mask) != 0) {
    261               is_valid = false;
    262               break;
    263             }
    264             mask >>= 8;
    265           }
    266         }
    267         if (is_valid) {
    268           SetEncodingValue(0x1e);
    269           SetEncodedImmediate(encoding);
    270         }
    271         break;
    272       }
    273       default:
    274         break;
    275     }
    276   } else {
    277     switch (dt.GetValue()) {
    278       case F32:
    279         if (neon_imm.IsFloat() || neon_imm.IsDouble()) {
    280           ImmediateVFP vfp(neon_imm.GetImmediate<float>());
    281           if (vfp.IsValid()) {
    282             SetEncodingValue(0xf);
    283             SetEncodedImmediate(vfp.GetEncodingValue());
    284           }
    285         }
    286         break;
    287       default:
    288         break;
    289     }
    290   }
    291 }
    292 
    293 
    294 DataType ImmediateVmov::DecodeDt(uint32_t cmode) {
    295   switch (cmode & 0xf) {
    296     case 0x0:
    297     case 0x2:
    298     case 0x4:
    299     case 0x6:
    300     case 0xc:
    301     case 0xd:
    302       return I32;
    303     case 0x8:
    304     case 0xa:
    305       return I16;
    306     case 0xe:
    307       return ((cmode & 0x10) == 0) ? I8 : I64;
    308     case 0xf:
    309       if ((cmode & 0x10) == 0) return F32;
    310       break;
    311     default:
    312       break;
    313   }
    314   VIXL_UNREACHABLE();
    315   return kDataTypeValueInvalid;
    316 }
    317 
    318 
    319 NeonImmediate ImmediateVmov::DecodeImmediate(uint32_t cmode,
    320                                              uint32_t immediate) {
    321   switch (cmode & 0xf) {
    322     case 0x8:
    323     case 0x0:
    324       return immediate;
    325     case 0x2:
    326     case 0xa:
    327       return immediate << 8;
    328     case 0x4:
    329       return immediate << 16;
    330     case 0x6:
    331       return immediate << 24;
    332     case 0xc:
    333       return (immediate << 8) | 0xff;
    334     case 0xd:
    335       return (immediate << 16) | 0xffff;
    336     case 0xe: {
    337       if (cmode == 0x1e) {
    338         uint64_t encoding = 0;
    339         for (uint32_t set_bit = 1 << 7; set_bit != 0; set_bit >>= 1) {
    340           encoding <<= 8;
    341           if ((immediate & set_bit) != 0) {
    342             encoding |= 0xff;
    343           }
    344         }
    345         return encoding;
    346       } else {
    347         return immediate;
    348       }
    349     }
    350     case 0xf: {
    351       return ImmediateVFP::Decode<float>(immediate);
    352     }
    353     default:
    354       break;
    355   }
    356   VIXL_UNREACHABLE();
    357   return 0;
    358 }
    359 
    360 
    361 ImmediateVmvn::ImmediateVmvn(DataType dt, const NeonImmediate& neon_imm) {
    362   if (neon_imm.IsInteger32()) {
    363     uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
    364     switch (dt.GetValue()) {
    365       case I16:
    366         if ((immediate & ~0xff) == 0) {
    367           SetEncodingValue(0x8);
    368           SetEncodedImmediate(immediate);
    369         } else if ((immediate & ~0xff00) == 0) {
    370           SetEncodingValue(0xa);
    371           SetEncodedImmediate(immediate >> 8);
    372         }
    373         break;
    374       case I32:
    375         if ((immediate & ~0xff) == 0) {
    376           SetEncodingValue(0x0);
    377           SetEncodedImmediate(immediate);
    378         } else if ((immediate & ~0xff00) == 0) {
    379           SetEncodingValue(0x2);
    380           SetEncodedImmediate(immediate >> 8);
    381         } else if ((immediate & ~0xff0000) == 0) {
    382           SetEncodingValue(0x4);
    383           SetEncodedImmediate(immediate >> 16);
    384         } else if ((immediate & ~0xff000000) == 0) {
    385           SetEncodingValue(0x6);
    386           SetEncodedImmediate(immediate >> 24);
    387         } else if ((immediate & ~0xff00) == 0xff) {
    388           SetEncodingValue(0xc);
    389           SetEncodedImmediate(immediate >> 8);
    390         } else if ((immediate & ~0xff0000) == 0xffff) {
    391           SetEncodingValue(0xd);
    392           SetEncodedImmediate(immediate >> 16);
    393         }
    394         break;
    395       default:
    396         break;
    397     }
    398   }
    399 }
    400 
    401 
    402 DataType ImmediateVmvn::DecodeDt(uint32_t cmode) {
    403   switch (cmode) {
    404     case 0x0:
    405     case 0x2:
    406     case 0x4:
    407     case 0x6:
    408     case 0xc:
    409     case 0xd:
    410       return I32;
    411     case 0x8:
    412     case 0xa:
    413       return I16;
    414     default:
    415       break;
    416   }
    417   VIXL_UNREACHABLE();
    418   return kDataTypeValueInvalid;
    419 }
    420 
    421 
    422 NeonImmediate ImmediateVmvn::DecodeImmediate(uint32_t cmode,
    423                                              uint32_t immediate) {
    424   switch (cmode) {
    425     case 0x0:
    426     case 0x8:
    427       return immediate;
    428     case 0x2:
    429     case 0xa:
    430       return immediate << 8;
    431     case 0x4:
    432       return immediate << 16;
    433     case 0x6:
    434       return immediate << 24;
    435     case 0xc:
    436       return (immediate << 8) | 0xff;
    437     case 0xd:
    438       return (immediate << 16) | 0xffff;
    439     default:
    440       break;
    441   }
    442   VIXL_UNREACHABLE();
    443   return 0;
    444 }
    445 
    446 
    447 ImmediateVorr::ImmediateVorr(DataType dt, const NeonImmediate& neon_imm) {
    448   if (neon_imm.IsInteger32()) {
    449     uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
    450     if (dt.GetValue() == I16) {
    451       if ((immediate & ~0xff) == 0) {
    452         SetEncodingValue(0x9);
    453         SetEncodedImmediate(immediate);
    454       } else if ((immediate & ~0xff00) == 0) {
    455         SetEncodingValue(0xb);
    456         SetEncodedImmediate(immediate >> 8);
    457       }
    458     } else if (dt.GetValue() == I32) {
    459       if ((immediate & ~0xff) == 0) {
    460         SetEncodingValue(0x1);
    461         SetEncodedImmediate(immediate);
    462       } else if ((immediate & ~0xff00) == 0) {
    463         SetEncodingValue(0x3);
    464         SetEncodedImmediate(immediate >> 8);
    465       } else if ((immediate & ~0xff0000) == 0) {
    466         SetEncodingValue(0x5);
    467         SetEncodedImmediate(immediate >> 16);
    468       } else if ((immediate & ~0xff000000) == 0) {
    469         SetEncodingValue(0x7);
    470         SetEncodedImmediate(immediate >> 24);
    471       }
    472     }
    473   }
    474 }
    475 
    476 
    477 DataType ImmediateVorr::DecodeDt(uint32_t cmode) {
    478   switch (cmode) {
    479     case 0x1:
    480     case 0x3:
    481     case 0x5:
    482     case 0x7:
    483       return I32;
    484     case 0x9:
    485     case 0xb:
    486       return I16;
    487     default:
    488       break;
    489   }
    490   VIXL_UNREACHABLE();
    491   return kDataTypeValueInvalid;
    492 }
    493 
    494 
    495 NeonImmediate ImmediateVorr::DecodeImmediate(uint32_t cmode,
    496                                              uint32_t immediate) {
    497   switch (cmode) {
    498     case 0x1:
    499     case 0x9:
    500       return immediate;
    501     case 0x3:
    502     case 0xb:
    503       return immediate << 8;
    504     case 0x5:
    505       return immediate << 16;
    506     case 0x7:
    507       return immediate << 24;
    508     default:
    509       break;
    510   }
    511   VIXL_UNREACHABLE();
    512   return 0;
    513 }
    514 
    515 // MemOperand
    516 
    517 std::ostream& operator<<(std::ostream& os, const MemOperand& operand) {
    518   os << "[" << operand.GetBaseRegister();
    519   if (operand.GetAddrMode() == PostIndex) {
    520     os << "]";
    521   }
    522   if (operand.IsImmediate()) {
    523     if ((operand.GetOffsetImmediate() != 0) || operand.GetSign().IsMinus() ||
    524         ((operand.GetAddrMode() != Offset) && !operand.IsRegisterOnly())) {
    525       if (operand.GetOffsetImmediate() == 0) {
    526         os << ", #" << operand.GetSign() << operand.GetOffsetImmediate();
    527       } else {
    528         os << ", #" << operand.GetOffsetImmediate();
    529       }
    530     }
    531   } else if (operand.IsPlainRegister()) {
    532     os << ", " << operand.GetSign() << operand.GetOffsetRegister();
    533   } else if (operand.IsShiftedRegister()) {
    534     os << ", " << operand.GetSign() << operand.GetOffsetRegister()
    535        << ImmediateShiftOperand(operand.GetShift(), operand.GetShiftAmount());
    536   } else {
    537     VIXL_UNREACHABLE();
    538     return os;
    539   }
    540   if (operand.GetAddrMode() == Offset) {
    541     os << "]";
    542   } else if (operand.GetAddrMode() == PreIndex) {
    543     os << "]!";
    544   }
    545   return os;
    546 }
    547 
    548 std::ostream& operator<<(std::ostream& os, const AlignedMemOperand& operand) {
    549   os << "[" << operand.GetBaseRegister() << operand.GetAlignment() << "]";
    550   if (operand.GetAddrMode() == PostIndex) {
    551     if (operand.IsPlainRegister()) {
    552       os << ", " << operand.GetOffsetRegister();
    553     } else {
    554       os << "!";
    555     }
    556   }
    557   return os;
    558 }
    559 
    560 }  // namespace aarch32
    561 }  // namespace vixl
    562