duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

operands-aarch32.cc (15779B)


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