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