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 564