1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #define LOG_TAG "ArmToArm64Assembler" 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 35 #include <cutils/log.h> 36 #include <cutils/properties.h> 37 #include <private/pixelflinger/ggl_context.h> 38 39 #include "codeflinger/Arm64Assembler.h" 40 #include "codeflinger/CodeCache.h" 41 #include "codeflinger/Arm64Disassembler.h" 42 43 44 /* 45 ** -------------------------------------------- 46 ** Support for Arm64 in GGLAssembler JIT 47 ** -------------------------------------------- 48 ** 49 ** Approach 50 ** - GGLAssembler and associated files are largely un-changed. 51 ** - A translator class maps ArmAssemblerInterface calls to 52 ** generate Arm64 instructions. 53 ** 54 ** ---------------------- 55 ** ArmToArm64Assembler 56 ** ---------------------- 57 ** 58 ** - Subclassed from ArmAssemblerInterface 59 ** 60 ** - Translates each ArmAssemblerInterface call to generate 61 ** one or more Arm64 instructions as necessary. 62 ** 63 ** - Does not implement ArmAssemblerInterface portions unused by GGLAssembler 64 ** It calls NOT_IMPLEMENTED() for such cases, which in turn logs 65 ** a fatal message. 66 ** 67 ** - Uses A64_.. series of functions to generate instruction machine code 68 ** for Arm64 instructions. These functions also log the instruction 69 ** to LOG, if ARM64_ASM_DEBUG define is set to 1 70 ** 71 ** - Dumps machine code and eqvt assembly if "debug.pf.disasm" option is set 72 ** It uses arm64_disassemble to perform disassembly 73 ** 74 ** - Uses register 13 (SP in ARM), 15 (PC in ARM), 16, 17 for storing 75 ** intermediate results. GGLAssembler does not use SP and PC as these 76 ** registers are marked as reserved. The temporary registers are not 77 ** saved/restored on stack as these are caller-saved registers in Arm64 78 ** 79 ** - Uses CSEL instruction to support conditional execution. The result is 80 ** stored in a temporary register and then copied to the target register 81 ** if the condition is true. 82 ** 83 ** - In the case of conditional data transfer instructions, conditional 84 ** branch is used to skip over instruction, if the condition is false 85 ** 86 ** - Wherever possible, immediate values are transferred to temporary 87 ** register prior to processing. This simplifies overall implementation 88 ** as instructions requiring immediate values are converted to 89 ** move immediate instructions followed by register-register instruction. 90 ** 91 ** -------------------------------------------- 92 ** ArmToArm64Assembler unit test bench 93 ** -------------------------------------------- 94 ** 95 ** - Tests ArmToArm64Assembler interface for all the possible 96 ** ways in which GGLAssembler uses ArmAssemblerInterface interface. 97 ** 98 ** - Uses test jacket (written in assembly) to set the registers, 99 ** condition flags prior to calling generated instruction. It also 100 ** copies registers and flags at the end of execution. Caller then 101 ** checks if generated code performed correct operation based on 102 ** output registers and flags. 103 ** 104 ** - Broadly contains three type of tests, (i) data operation tests 105 ** (ii) data transfer tests and (iii) LDM/STM tests. 106 ** 107 ** ---------------------- 108 ** Arm64 disassembler 109 ** ---------------------- 110 ** - This disassembler disassembles only those machine codes which can be 111 ** generated by ArmToArm64Assembler. It has a unit testbench which 112 ** tests all the instructions supported by the disassembler. 113 ** 114 ** ------------------------------------------------------------------ 115 ** ARMAssembler/ARMAssemblerInterface/ARMAssemblerProxy changes 116 ** ------------------------------------------------------------------ 117 ** 118 ** - In existing code, addresses were being handled as 32 bit values at 119 ** certain places. 120 ** 121 ** - Added a new set of functions for address load/store/manipulation. 122 ** These are ADDR_LDR, ADDR_STR, ADDR_ADD, ADDR_SUB and they map to 123 ** default 32 bit implementations in ARMAssemblerInterface. 124 ** 125 ** - ArmToArm64Assembler maps these functions to appropriate 64 bit 126 ** functions. 127 ** 128 ** ---------------------- 129 ** GGLAssembler changes 130 ** ---------------------- 131 ** - Since ArmToArm64Assembler can generate 4 Arm64 instructions for 132 ** each call in worst case, the memory required is set to 4 times 133 ** ARM memory 134 ** 135 ** - Address load/store/manipulation were changed to use new functions 136 ** added in the ARMAssemblerInterface. 137 ** 138 */ 139 140 141 #define NOT_IMPLEMENTED() LOG_FATAL("Arm instruction %s not yet implemented\n", __func__) 142 143 #define ARM64_ASM_DEBUG 0 144 145 #if ARM64_ASM_DEBUG 146 #define LOG_INSTR(...) ALOGD("\t" __VA_ARGS__) 147 #define LOG_LABEL(...) ALOGD(__VA_ARGS__) 148 #else 149 #define LOG_INSTR(...) ((void)0) 150 #define LOG_LABEL(...) ((void)0) 151 #endif 152 153 namespace android { 154 155 static const char* shift_codes[] = 156 { 157 "LSL", "LSR", "ASR", "ROR" 158 }; 159 static const char *cc_codes[] = 160 { 161 "EQ", "NE", "CS", "CC", "MI", 162 "PL", "VS", "VC", "HI", "LS", 163 "GE", "LT", "GT", "LE", "AL", "NV" 164 }; 165 166 ArmToArm64Assembler::ArmToArm64Assembler(const sp<Assembly>& assembly) 167 : ARMAssemblerInterface(), 168 mAssembly(assembly) 169 { 170 mBase = mPC = (uint32_t *)assembly->base(); 171 mDuration = ggl_system_time(); 172 mZeroReg = 13; 173 mTmpReg1 = 15; 174 mTmpReg2 = 16; 175 mTmpReg3 = 17; 176 } 177 178 ArmToArm64Assembler::ArmToArm64Assembler(void *base) 179 : ARMAssemblerInterface(), mAssembly(NULL) 180 { 181 mBase = mPC = (uint32_t *)base; 182 mDuration = ggl_system_time(); 183 // Regs 13, 15, 16, 17 are used as temporary registers 184 mZeroReg = 13; 185 mTmpReg1 = 15; 186 mTmpReg2 = 16; 187 mTmpReg3 = 17; 188 } 189 190 ArmToArm64Assembler::~ArmToArm64Assembler() 191 { 192 } 193 194 uint32_t* ArmToArm64Assembler::pc() const 195 { 196 return mPC; 197 } 198 199 uint32_t* ArmToArm64Assembler::base() const 200 { 201 return mBase; 202 } 203 204 void ArmToArm64Assembler::reset() 205 { 206 if(mAssembly == NULL) 207 mPC = mBase; 208 else 209 mBase = mPC = (uint32_t *)mAssembly->base(); 210 mBranchTargets.clear(); 211 mLabels.clear(); 212 mLabelsInverseMapping.clear(); 213 mComments.clear(); 214 #if ARM64_ASM_DEBUG 215 ALOGI("RESET\n"); 216 #endif 217 } 218 219 int ArmToArm64Assembler::getCodegenArch() 220 { 221 return CODEGEN_ARCH_ARM64; 222 } 223 224 // ---------------------------------------------------------------------------- 225 226 void ArmToArm64Assembler::disassemble(const char* name) 227 { 228 if(name) 229 { 230 printf("%s:\n", name); 231 } 232 size_t count = pc()-base(); 233 uint32_t* i = base(); 234 while (count--) 235 { 236 ssize_t label = mLabelsInverseMapping.indexOfKey(i); 237 if (label >= 0) 238 { 239 printf("%s:\n", mLabelsInverseMapping.valueAt(label)); 240 } 241 ssize_t comment = mComments.indexOfKey(i); 242 if (comment >= 0) 243 { 244 printf("; %s\n", mComments.valueAt(comment)); 245 } 246 printf("%p: %08x ", i, uint32_t(i[0])); 247 { 248 char instr[256]; 249 ::arm64_disassemble(*i, instr); 250 printf("%s\n", instr); 251 } 252 i++; 253 } 254 } 255 256 void ArmToArm64Assembler::comment(const char* string) 257 { 258 mComments.add(mPC, string); 259 LOG_INSTR("//%s\n", string); 260 } 261 262 void ArmToArm64Assembler::label(const char* theLabel) 263 { 264 mLabels.add(theLabel, mPC); 265 mLabelsInverseMapping.add(mPC, theLabel); 266 LOG_LABEL("%s:\n", theLabel); 267 } 268 269 void ArmToArm64Assembler::B(int cc, const char* label) 270 { 271 mBranchTargets.add(branch_target_t(label, mPC)); 272 LOG_INSTR("B%s %s\n", cc_codes[cc], label ); 273 *mPC++ = (0x54 << 24) | cc; 274 } 275 276 void ArmToArm64Assembler::BL(int /*cc*/, const char* /*label*/) 277 { 278 NOT_IMPLEMENTED(); //Not Required 279 } 280 281 // ---------------------------------------------------------------------------- 282 //Prolog/Epilog & Generate... 283 // ---------------------------------------------------------------------------- 284 285 void ArmToArm64Assembler::prolog() 286 { 287 // write prolog code 288 mPrologPC = mPC; 289 *mPC++ = A64_MOVZ_X(mZeroReg,0,0); 290 } 291 292 void ArmToArm64Assembler::epilog(uint32_t /*touched*/) 293 { 294 // write epilog code 295 static const int XLR = 30; 296 *mPC++ = A64_RET(XLR); 297 } 298 299 int ArmToArm64Assembler::generate(const char* name) 300 { 301 // fixup all the branches 302 size_t count = mBranchTargets.size(); 303 while (count--) 304 { 305 const branch_target_t& bt = mBranchTargets[count]; 306 uint32_t* target_pc = mLabels.valueFor(bt.label); 307 LOG_ALWAYS_FATAL_IF(!target_pc, 308 "error resolving branch targets, target_pc is null"); 309 int32_t offset = int32_t(target_pc - bt.pc); 310 *bt.pc |= (offset & 0x7FFFF) << 5; 311 } 312 313 if(mAssembly != NULL) 314 mAssembly->resize( int(pc()-base())*4 ); 315 316 // the instruction cache is flushed by CodeCache 317 const int64_t duration = ggl_system_time() - mDuration; 318 const char * const format = "generated %s (%d ins) at [%p:%p] in %ld ns\n"; 319 ALOGI(format, name, int(pc()-base()), base(), pc(), duration); 320 321 322 char value[PROPERTY_VALUE_MAX]; 323 property_get("debug.pf.disasm", value, "0"); 324 if (atoi(value) != 0) 325 { 326 printf(format, name, int(pc()-base()), base(), pc(), duration); 327 disassemble(name); 328 } 329 return NO_ERROR; 330 } 331 332 uint32_t* ArmToArm64Assembler::pcForLabel(const char* label) 333 { 334 return mLabels.valueFor(label); 335 } 336 337 // ---------------------------------------------------------------------------- 338 // Data Processing... 339 // ---------------------------------------------------------------------------- 340 void ArmToArm64Assembler::dataProcessingCommon(int opcode, 341 int s, int Rd, int Rn, uint32_t Op2) 342 { 343 if(opcode != opSUB && s == 1) 344 { 345 NOT_IMPLEMENTED(); //Not required 346 return; 347 } 348 349 if(opcode != opSUB && opcode != opADD && opcode != opAND && 350 opcode != opORR && opcode != opMVN) 351 { 352 NOT_IMPLEMENTED(); //Not required 353 return; 354 } 355 356 if(Op2 == OPERAND_REG_IMM && mAddrMode.reg_imm_shift > 31) 357 { 358 NOT_IMPLEMENTED(); 359 return; 360 } 361 362 //Store immediate in temporary register and convert 363 //immediate operation into register operation 364 if(Op2 == OPERAND_IMM) 365 { 366 int imm = mAddrMode.immediate; 367 *mPC++ = A64_MOVZ_W(mTmpReg2, imm & 0x0000FFFF, 0); 368 *mPC++ = A64_MOVK_W(mTmpReg2, (imm >> 16) & 0x0000FFFF, 16); 369 Op2 = mTmpReg2; 370 } 371 372 373 { 374 uint32_t shift; 375 uint32_t amount; 376 uint32_t Rm; 377 378 if(Op2 == OPERAND_REG_IMM) 379 { 380 shift = mAddrMode.reg_imm_type; 381 amount = mAddrMode.reg_imm_shift; 382 Rm = mAddrMode.reg_imm_Rm; 383 } 384 else if(Op2 < OPERAND_REG) 385 { 386 shift = 0; 387 amount = 0; 388 Rm = Op2; 389 } 390 else 391 { 392 NOT_IMPLEMENTED(); //Not required 393 return; 394 } 395 396 switch(opcode) 397 { 398 case opADD: *mPC++ = A64_ADD_W(Rd, Rn, Rm, shift, amount); break; 399 case opAND: *mPC++ = A64_AND_W(Rd, Rn, Rm, shift, amount); break; 400 case opORR: *mPC++ = A64_ORR_W(Rd, Rn, Rm, shift, amount); break; 401 case opMVN: *mPC++ = A64_ORN_W(Rd, Rn, Rm, shift, amount); break; 402 case opSUB: *mPC++ = A64_SUB_W(Rd, Rn, Rm, shift, amount, s);break; 403 }; 404 405 } 406 } 407 408 void ArmToArm64Assembler::dataProcessing(int opcode, int cc, 409 int s, int Rd, int Rn, uint32_t Op2) 410 { 411 uint32_t Wd; 412 413 if(cc != AL) 414 Wd = mTmpReg1; 415 else 416 Wd = Rd; 417 418 if(opcode == opADD || opcode == opAND || opcode == opORR ||opcode == opSUB) 419 { 420 dataProcessingCommon(opcode, s, Wd, Rn, Op2); 421 } 422 else if(opcode == opCMP) 423 { 424 dataProcessingCommon(opSUB, 1, mTmpReg3, Rn, Op2); 425 } 426 else if(opcode == opRSB) 427 { 428 dataProcessingCommon(opSUB, s, Wd, Rn, Op2); 429 dataProcessingCommon(opSUB, s, Wd, mZeroReg, Wd); 430 } 431 else if(opcode == opMOV) 432 { 433 dataProcessingCommon(opORR, 0, Wd, mZeroReg, Op2); 434 if(s == 1) 435 { 436 dataProcessingCommon(opSUB, 1, mTmpReg3, Wd, mZeroReg); 437 } 438 } 439 else if(opcode == opMVN) 440 { 441 dataProcessingCommon(opMVN, s, Wd, mZeroReg, Op2); 442 } 443 else if(opcode == opBIC) 444 { 445 dataProcessingCommon(opMVN, s, mTmpReg3, mZeroReg, Op2); 446 dataProcessingCommon(opAND, s, Wd, Rn, mTmpReg3); 447 } 448 else 449 { 450 NOT_IMPLEMENTED(); 451 return; 452 } 453 454 if(cc != AL) 455 { 456 *mPC++ = A64_CSEL_W(Rd, mTmpReg1, Rd, cc); 457 } 458 } 459 // ---------------------------------------------------------------------------- 460 // Address Processing... 461 // ---------------------------------------------------------------------------- 462 463 void ArmToArm64Assembler::ADDR_ADD(int cc, 464 int s, int Rd, int Rn, uint32_t Op2) 465 { 466 if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required 467 if(s != 0) { NOT_IMPLEMENTED(); return;} //Not required 468 469 470 if(Op2 == OPERAND_REG_IMM && mAddrMode.reg_imm_type == LSL) 471 { 472 int Rm = mAddrMode.reg_imm_Rm; 473 int amount = mAddrMode.reg_imm_shift; 474 *mPC++ = A64_ADD_X_Wm_SXTW(Rd, Rn, Rm, amount); 475 } 476 else if(Op2 < OPERAND_REG) 477 { 478 int Rm = Op2; 479 int amount = 0; 480 *mPC++ = A64_ADD_X_Wm_SXTW(Rd, Rn, Rm, amount); 481 } 482 else if(Op2 == OPERAND_IMM) 483 { 484 int imm = mAddrMode.immediate; 485 *mPC++ = A64_MOVZ_W(mTmpReg1, imm & 0x0000FFFF, 0); 486 *mPC++ = A64_MOVK_W(mTmpReg1, (imm >> 16) & 0x0000FFFF, 16); 487 488 int Rm = mTmpReg1; 489 int amount = 0; 490 *mPC++ = A64_ADD_X_Wm_SXTW(Rd, Rn, Rm, amount); 491 } 492 else 493 { 494 NOT_IMPLEMENTED(); //Not required 495 } 496 } 497 498 void ArmToArm64Assembler::ADDR_SUB(int cc, 499 int s, int Rd, int Rn, uint32_t Op2) 500 { 501 if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required 502 if(s != 0) { NOT_IMPLEMENTED(); return;} //Not required 503 504 if(Op2 == OPERAND_REG_IMM && mAddrMode.reg_imm_type == LSR) 505 { 506 *mPC++ = A64_ADD_W(mTmpReg1, mZeroReg, mAddrMode.reg_imm_Rm, 507 LSR, mAddrMode.reg_imm_shift); 508 *mPC++ = A64_SUB_X_Wm_SXTW(Rd, Rn, mTmpReg1, 0); 509 } 510 else 511 { 512 NOT_IMPLEMENTED(); //Not required 513 } 514 } 515 516 // ---------------------------------------------------------------------------- 517 // multiply... 518 // ---------------------------------------------------------------------------- 519 void ArmToArm64Assembler::MLA(int cc, int s,int Rd, int Rm, int Rs, int Rn) 520 { 521 if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required 522 523 *mPC++ = A64_MADD_W(Rd, Rm, Rs, Rn); 524 if(s == 1) 525 dataProcessingCommon(opSUB, 1, mTmpReg1, Rd, mZeroReg); 526 } 527 void ArmToArm64Assembler::MUL(int cc, int s, int Rd, int Rm, int Rs) 528 { 529 if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required 530 if(s != 0) { NOT_IMPLEMENTED(); return;} //Not required 531 *mPC++ = A64_MADD_W(Rd, Rm, Rs, mZeroReg); 532 } 533 void ArmToArm64Assembler::UMULL(int /*cc*/, int /*s*/, 534 int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/) 535 { 536 NOT_IMPLEMENTED(); //Not required 537 } 538 void ArmToArm64Assembler::UMUAL(int /*cc*/, int /*s*/, 539 int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/) 540 { 541 NOT_IMPLEMENTED(); //Not required 542 } 543 void ArmToArm64Assembler::SMULL(int /*cc*/, int /*s*/, 544 int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/) 545 { 546 NOT_IMPLEMENTED(); //Not required 547 } 548 void ArmToArm64Assembler::SMUAL(int /*cc*/, int /*s*/, 549 int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/) 550 { 551 NOT_IMPLEMENTED(); //Not required 552 } 553 554 // ---------------------------------------------------------------------------- 555 // branches relative to PC... 556 // ---------------------------------------------------------------------------- 557 void ArmToArm64Assembler::B(int /*cc*/, uint32_t* /*pc*/){ 558 NOT_IMPLEMENTED(); //Not required 559 } 560 561 void ArmToArm64Assembler::BL(int /*cc*/, uint32_t* /*pc*/){ 562 NOT_IMPLEMENTED(); //Not required 563 } 564 565 void ArmToArm64Assembler::BX(int /*cc*/, int /*Rn*/){ 566 NOT_IMPLEMENTED(); //Not required 567 } 568 569 // ---------------------------------------------------------------------------- 570 // data transfer... 571 // ---------------------------------------------------------------------------- 572 enum dataTransferOp 573 { 574 opLDR,opLDRB,opLDRH,opSTR,opSTRB,opSTRH 575 }; 576 577 void ArmToArm64Assembler::dataTransfer(int op, int cc, 578 int Rd, int Rn, uint32_t op_type, uint32_t size) 579 { 580 const int XSP = 31; 581 if(Rn == SP) 582 Rn = XSP; 583 584 if(op_type == OPERAND_IMM) 585 { 586 int addrReg; 587 int imm = mAddrMode.immediate; 588 if(imm >= 0 && imm < (1<<12)) 589 *mPC++ = A64_ADD_IMM_X(mTmpReg1, mZeroReg, imm, 0); 590 else if(imm < 0 && -imm < (1<<12)) 591 *mPC++ = A64_SUB_IMM_X(mTmpReg1, mZeroReg, -imm, 0); 592 else 593 { 594 NOT_IMPLEMENTED(); 595 return; 596 } 597 598 addrReg = Rn; 599 if(mAddrMode.preindex == true || mAddrMode.postindex == true) 600 { 601 *mPC++ = A64_ADD_X(mTmpReg2, addrReg, mTmpReg1); 602 if(mAddrMode.preindex == true) 603 addrReg = mTmpReg2; 604 } 605 606 if(cc != AL) 607 *mPC++ = A64_B_COND(cc^1, 8); 608 609 *mPC++ = A64_LDRSTR_Wm_SXTW_0(op, size, Rd, addrReg, mZeroReg); 610 611 if(mAddrMode.writeback == true) 612 *mPC++ = A64_CSEL_X(Rn, mTmpReg2, Rn, cc); 613 } 614 else if(op_type == OPERAND_REG_OFFSET) 615 { 616 if(cc != AL) 617 *mPC++ = A64_B_COND(cc^1, 8); 618 *mPC++ = A64_LDRSTR_Wm_SXTW_0(op, size, Rd, Rn, mAddrMode.reg_offset); 619 620 } 621 else if(op_type > OPERAND_UNSUPPORTED) 622 { 623 if(cc != AL) 624 *mPC++ = A64_B_COND(cc^1, 8); 625 *mPC++ = A64_LDRSTR_Wm_SXTW_0(op, size, Rd, Rn, mZeroReg); 626 } 627 else 628 { 629 NOT_IMPLEMENTED(); // Not required 630 } 631 return; 632 633 } 634 void ArmToArm64Assembler::ADDR_LDR(int cc, int Rd, int Rn, uint32_t op_type) 635 { 636 return dataTransfer(opLDR, cc, Rd, Rn, op_type, 64); 637 } 638 void ArmToArm64Assembler::ADDR_STR(int cc, int Rd, int Rn, uint32_t op_type) 639 { 640 return dataTransfer(opSTR, cc, Rd, Rn, op_type, 64); 641 } 642 void ArmToArm64Assembler::LDR(int cc, int Rd, int Rn, uint32_t op_type) 643 { 644 return dataTransfer(opLDR, cc, Rd, Rn, op_type); 645 } 646 void ArmToArm64Assembler::LDRB(int cc, int Rd, int Rn, uint32_t op_type) 647 { 648 return dataTransfer(opLDRB, cc, Rd, Rn, op_type); 649 } 650 void ArmToArm64Assembler::STR(int cc, int Rd, int Rn, uint32_t op_type) 651 { 652 return dataTransfer(opSTR, cc, Rd, Rn, op_type); 653 } 654 655 void ArmToArm64Assembler::STRB(int cc, int Rd, int Rn, uint32_t op_type) 656 { 657 return dataTransfer(opSTRB, cc, Rd, Rn, op_type); 658 } 659 660 void ArmToArm64Assembler::LDRH(int cc, int Rd, int Rn, uint32_t op_type) 661 { 662 return dataTransfer(opLDRH, cc, Rd, Rn, op_type); 663 } 664 void ArmToArm64Assembler::LDRSB(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/) 665 { 666 NOT_IMPLEMENTED(); //Not required 667 } 668 void ArmToArm64Assembler::LDRSH(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/) 669 { 670 NOT_IMPLEMENTED(); //Not required 671 } 672 673 void ArmToArm64Assembler::STRH(int cc, int Rd, int Rn, uint32_t op_type) 674 { 675 return dataTransfer(opSTRH, cc, Rd, Rn, op_type); 676 } 677 678 // ---------------------------------------------------------------------------- 679 // block data transfer... 680 // ---------------------------------------------------------------------------- 681 void ArmToArm64Assembler::LDM(int cc, int dir, 682 int Rn, int W, uint32_t reg_list) 683 { 684 const int XSP = 31; 685 if(cc != AL || dir != IA || W == 0 || Rn != SP) 686 { 687 NOT_IMPLEMENTED(); 688 return; 689 } 690 691 for(int i = 0; i < 32; ++i) 692 { 693 if((reg_list & (1 << i))) 694 { 695 int reg = i; 696 int size = 16; 697 *mPC++ = A64_LDR_IMM_PostIndex(reg, XSP, size); 698 } 699 } 700 } 701 702 void ArmToArm64Assembler::STM(int cc, int dir, 703 int Rn, int W, uint32_t reg_list) 704 { 705 const int XSP = 31; 706 if(cc != AL || dir != DB || W == 0 || Rn != SP) 707 { 708 NOT_IMPLEMENTED(); 709 return; 710 } 711 712 for(int i = 31; i >= 0; --i) 713 { 714 if((reg_list & (1 << i))) 715 { 716 int size = -16; 717 int reg = i; 718 *mPC++ = A64_STR_IMM_PreIndex(reg, XSP, size); 719 } 720 } 721 } 722 723 // ---------------------------------------------------------------------------- 724 // special... 725 // ---------------------------------------------------------------------------- 726 void ArmToArm64Assembler::SWP(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/) 727 { 728 NOT_IMPLEMENTED(); //Not required 729 } 730 void ArmToArm64Assembler::SWPB(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/) 731 { 732 NOT_IMPLEMENTED(); //Not required 733 } 734 void ArmToArm64Assembler::SWI(int /*cc*/, uint32_t /*comment*/) 735 { 736 NOT_IMPLEMENTED(); //Not required 737 } 738 739 // ---------------------------------------------------------------------------- 740 // DSP instructions... 741 // ---------------------------------------------------------------------------- 742 void ArmToArm64Assembler::PLD(int /*Rn*/, uint32_t /*offset*/) { 743 NOT_IMPLEMENTED(); //Not required 744 } 745 746 void ArmToArm64Assembler::CLZ(int /*cc*/, int /*Rd*/, int /*Rm*/) 747 { 748 NOT_IMPLEMENTED(); //Not required 749 } 750 751 void ArmToArm64Assembler::QADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/) 752 { 753 NOT_IMPLEMENTED(); //Not required 754 } 755 756 void ArmToArm64Assembler::QDADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/) 757 { 758 NOT_IMPLEMENTED(); //Not required 759 } 760 761 void ArmToArm64Assembler::QSUB(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/) 762 { 763 NOT_IMPLEMENTED(); //Not required 764 } 765 766 void ArmToArm64Assembler::QDSUB(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/) 767 { 768 NOT_IMPLEMENTED(); //Not required 769 } 770 771 // ---------------------------------------------------------------------------- 772 // 16 x 16 multiplication 773 // ---------------------------------------------------------------------------- 774 void ArmToArm64Assembler::SMUL(int cc, int xy, 775 int Rd, int Rm, int Rs) 776 { 777 if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required 778 779 if (xy & xyTB) 780 *mPC++ = A64_SBFM_W(mTmpReg1, Rm, 16, 31); 781 else 782 *mPC++ = A64_SBFM_W(mTmpReg1, Rm, 0, 15); 783 784 if (xy & xyBT) 785 *mPC++ = A64_SBFM_W(mTmpReg2, Rs, 16, 31); 786 else 787 *mPC++ = A64_SBFM_W(mTmpReg2, Rs, 0, 15); 788 789 *mPC++ = A64_MADD_W(Rd,mTmpReg1,mTmpReg2, mZeroReg); 790 } 791 // ---------------------------------------------------------------------------- 792 // 32 x 16 multiplication 793 // ---------------------------------------------------------------------------- 794 void ArmToArm64Assembler::SMULW(int cc, int y, int Rd, int Rm, int Rs) 795 { 796 if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required 797 798 if (y & yT) 799 *mPC++ = A64_SBFM_W(mTmpReg1, Rs, 16, 31); 800 else 801 *mPC++ = A64_SBFM_W(mTmpReg1, Rs, 0, 15); 802 803 *mPC++ = A64_SBFM_W(mTmpReg2, Rm, 0, 31); 804 *mPC++ = A64_SMADDL(mTmpReg3,mTmpReg1,mTmpReg2, mZeroReg); 805 *mPC++ = A64_UBFM_X(Rd,mTmpReg3, 16, 47); 806 } 807 // ---------------------------------------------------------------------------- 808 // 16 x 16 multiplication and accumulate 809 // ---------------------------------------------------------------------------- 810 void ArmToArm64Assembler::SMLA(int cc, int xy, int Rd, int Rm, int Rs, int Rn) 811 { 812 if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required 813 if(xy != xyBB) { NOT_IMPLEMENTED(); return;} //Not required 814 815 *mPC++ = A64_SBFM_W(mTmpReg1, Rm, 0, 15); 816 *mPC++ = A64_SBFM_W(mTmpReg2, Rs, 0, 15); 817 *mPC++ = A64_MADD_W(Rd, mTmpReg1, mTmpReg2, Rn); 818 } 819 820 void ArmToArm64Assembler::SMLAL(int /*cc*/, int /*xy*/, 821 int /*RdHi*/, int /*RdLo*/, int /*Rs*/, int /*Rm*/) 822 { 823 NOT_IMPLEMENTED(); //Not required 824 return; 825 } 826 827 void ArmToArm64Assembler::SMLAW(int /*cc*/, int /*y*/, 828 int /*Rd*/, int /*Rm*/, int /*Rs*/, int /*Rn*/) 829 { 830 NOT_IMPLEMENTED(); //Not required 831 return; 832 } 833 834 // ---------------------------------------------------------------------------- 835 // Byte/half word extract and extend 836 // ---------------------------------------------------------------------------- 837 void ArmToArm64Assembler::UXTB16(int cc, int Rd, int Rm, int rotate) 838 { 839 if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required 840 841 *mPC++ = A64_EXTR_W(mTmpReg1, Rm, Rm, rotate * 8); 842 843 uint32_t imm = 0x00FF00FF; 844 *mPC++ = A64_MOVZ_W(mTmpReg2, imm & 0xFFFF, 0); 845 *mPC++ = A64_MOVK_W(mTmpReg2, (imm >> 16) & 0x0000FFFF, 16); 846 *mPC++ = A64_AND_W(Rd,mTmpReg1, mTmpReg2); 847 } 848 849 // ---------------------------------------------------------------------------- 850 // Bit manipulation 851 // ---------------------------------------------------------------------------- 852 void ArmToArm64Assembler::UBFX(int cc, int Rd, int Rn, int lsb, int width) 853 { 854 if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required 855 *mPC++ = A64_UBFM_W(Rd, Rn, lsb, lsb + width - 1); 856 } 857 // ---------------------------------------------------------------------------- 858 // Shifters... 859 // ---------------------------------------------------------------------------- 860 int ArmToArm64Assembler::buildImmediate( 861 uint32_t immediate, uint32_t& rot, uint32_t& imm) 862 { 863 rot = 0; 864 imm = immediate; 865 return 0; // Always true 866 } 867 868 869 bool ArmToArm64Assembler::isValidImmediate(uint32_t immediate) 870 { 871 uint32_t rot, imm; 872 return buildImmediate(immediate, rot, imm) == 0; 873 } 874 875 uint32_t ArmToArm64Assembler::imm(uint32_t immediate) 876 { 877 mAddrMode.immediate = immediate; 878 mAddrMode.writeback = false; 879 mAddrMode.preindex = false; 880 mAddrMode.postindex = false; 881 return OPERAND_IMM; 882 883 } 884 885 uint32_t ArmToArm64Assembler::reg_imm(int Rm, int type, uint32_t shift) 886 { 887 mAddrMode.reg_imm_Rm = Rm; 888 mAddrMode.reg_imm_type = type; 889 mAddrMode.reg_imm_shift = shift; 890 return OPERAND_REG_IMM; 891 } 892 893 uint32_t ArmToArm64Assembler::reg_rrx(int /*Rm*/) 894 { 895 NOT_IMPLEMENTED(); 896 return OPERAND_UNSUPPORTED; 897 } 898 899 uint32_t ArmToArm64Assembler::reg_reg(int /*Rm*/, int /*type*/, int /*Rs*/) 900 { 901 NOT_IMPLEMENTED(); //Not required 902 return OPERAND_UNSUPPORTED; 903 } 904 // ---------------------------------------------------------------------------- 905 // Addressing modes... 906 // ---------------------------------------------------------------------------- 907 uint32_t ArmToArm64Assembler::immed12_pre(int32_t immed12, int W) 908 { 909 mAddrMode.immediate = immed12; 910 mAddrMode.writeback = W; 911 mAddrMode.preindex = true; 912 mAddrMode.postindex = false; 913 return OPERAND_IMM; 914 } 915 916 uint32_t ArmToArm64Assembler::immed12_post(int32_t immed12) 917 { 918 mAddrMode.immediate = immed12; 919 mAddrMode.writeback = true; 920 mAddrMode.preindex = false; 921 mAddrMode.postindex = true; 922 return OPERAND_IMM; 923 } 924 925 uint32_t ArmToArm64Assembler::reg_scale_pre(int Rm, int type, 926 uint32_t shift, int W) 927 { 928 if(type != 0 || shift != 0 || W != 0) 929 { 930 NOT_IMPLEMENTED(); //Not required 931 return OPERAND_UNSUPPORTED; 932 } 933 else 934 { 935 mAddrMode.reg_offset = Rm; 936 return OPERAND_REG_OFFSET; 937 } 938 } 939 940 uint32_t ArmToArm64Assembler::reg_scale_post(int /*Rm*/, int /*type*/, uint32_t /*shift*/) 941 { 942 NOT_IMPLEMENTED(); //Not required 943 return OPERAND_UNSUPPORTED; 944 } 945 946 uint32_t ArmToArm64Assembler::immed8_pre(int32_t immed8, int W) 947 { 948 mAddrMode.immediate = immed8; 949 mAddrMode.writeback = W; 950 mAddrMode.preindex = true; 951 mAddrMode.postindex = false; 952 return OPERAND_IMM; 953 } 954 955 uint32_t ArmToArm64Assembler::immed8_post(int32_t immed8) 956 { 957 mAddrMode.immediate = immed8; 958 mAddrMode.writeback = true; 959 mAddrMode.preindex = false; 960 mAddrMode.postindex = true; 961 return OPERAND_IMM; 962 } 963 964 uint32_t ArmToArm64Assembler::reg_pre(int Rm, int W) 965 { 966 if(W != 0) 967 { 968 NOT_IMPLEMENTED(); //Not required 969 return OPERAND_UNSUPPORTED; 970 } 971 else 972 { 973 mAddrMode.reg_offset = Rm; 974 return OPERAND_REG_OFFSET; 975 } 976 } 977 978 uint32_t ArmToArm64Assembler::reg_post(int /*Rm*/) 979 { 980 NOT_IMPLEMENTED(); //Not required 981 return OPERAND_UNSUPPORTED; 982 } 983 984 // ---------------------------------------------------------------------------- 985 // A64 instructions 986 // ---------------------------------------------------------------------------- 987 988 static const char * dataTransferOpName[] = 989 { 990 "LDR","LDRB","LDRH","STR","STRB","STRH" 991 }; 992 993 static const uint32_t dataTransferOpCode [] = 994 { 995 ((0xB8u << 24) | (0x3 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11)), 996 ((0x38u << 24) | (0x3 << 21) | (0x6 << 13) | (0x1 << 12) |(0x1 << 11)), 997 ((0x78u << 24) | (0x3 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11)), 998 ((0xB8u << 24) | (0x1 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11)), 999 ((0x38u << 24) | (0x1 << 21) | (0x6 << 13) | (0x1 << 12) |(0x1 << 11)), 1000 ((0x78u << 24) | (0x1 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11)) 1001 }; 1002 uint32_t ArmToArm64Assembler::A64_LDRSTR_Wm_SXTW_0(uint32_t op, 1003 uint32_t size, uint32_t Rt, 1004 uint32_t Rn, uint32_t Rm) 1005 { 1006 if(size == 32) 1007 { 1008 LOG_INSTR("%s W%d, [X%d, W%d, SXTW #0]\n", 1009 dataTransferOpName[op], Rt, Rn, Rm); 1010 return(dataTransferOpCode[op] | (Rm << 16) | (Rn << 5) | Rt); 1011 } 1012 else 1013 { 1014 LOG_INSTR("%s X%d, [X%d, W%d, SXTW #0]\n", 1015 dataTransferOpName[op], Rt, Rn, Rm); 1016 return(dataTransferOpCode[op] | (0x1<<30) | (Rm<<16) | (Rn<<5)|Rt); 1017 } 1018 } 1019 1020 uint32_t ArmToArm64Assembler::A64_STR_IMM_PreIndex(uint32_t Rt, 1021 uint32_t Rn, int32_t simm) 1022 { 1023 if(Rn == 31) 1024 LOG_INSTR("STR W%d, [SP, #%d]!\n", Rt, simm); 1025 else 1026 LOG_INSTR("STR W%d, [X%d, #%d]!\n", Rt, Rn, simm); 1027 1028 uint32_t imm9 = (unsigned)(simm) & 0x01FF; 1029 return (0xB8 << 24) | (imm9 << 12) | (0x3 << 10) | (Rn << 5) | Rt; 1030 } 1031 1032 uint32_t ArmToArm64Assembler::A64_LDR_IMM_PostIndex(uint32_t Rt, 1033 uint32_t Rn, int32_t simm) 1034 { 1035 if(Rn == 31) 1036 LOG_INSTR("LDR W%d, [SP], #%d\n",Rt,simm); 1037 else 1038 LOG_INSTR("LDR W%d, [X%d], #%d\n",Rt, Rn, simm); 1039 1040 uint32_t imm9 = (unsigned)(simm) & 0x01FF; 1041 return (0xB8 << 24) | (0x1 << 22) | 1042 (imm9 << 12) | (0x1 << 10) | (Rn << 5) | Rt; 1043 1044 } 1045 uint32_t ArmToArm64Assembler::A64_ADD_X_Wm_SXTW(uint32_t Rd, 1046 uint32_t Rn, 1047 uint32_t Rm, 1048 uint32_t amount) 1049 { 1050 LOG_INSTR("ADD X%d, X%d, W%d, SXTW #%d\n", Rd, Rn, Rm, amount); 1051 return ((0x8B << 24) | (0x1 << 21) |(Rm << 16) | 1052 (0x6 << 13) | (amount << 10) | (Rn << 5) | Rd); 1053 1054 } 1055 1056 uint32_t ArmToArm64Assembler::A64_SUB_X_Wm_SXTW(uint32_t Rd, 1057 uint32_t Rn, 1058 uint32_t Rm, 1059 uint32_t amount) 1060 { 1061 LOG_INSTR("SUB X%d, X%d, W%d, SXTW #%d\n", Rd, Rn, Rm, amount); 1062 return ((0xCB << 24) | (0x1 << 21) |(Rm << 16) | 1063 (0x6 << 13) | (amount << 10) | (Rn << 5) | Rd); 1064 1065 } 1066 1067 uint32_t ArmToArm64Assembler::A64_B_COND(uint32_t cc, uint32_t offset) 1068 { 1069 LOG_INSTR("B.%s #.+%d\n", cc_codes[cc], offset); 1070 return (0x54 << 24) | ((offset/4) << 5) | (cc); 1071 1072 } 1073 uint32_t ArmToArm64Assembler::A64_ADD_X(uint32_t Rd, uint32_t Rn, 1074 uint32_t Rm, uint32_t shift, 1075 uint32_t amount) 1076 { 1077 LOG_INSTR("ADD X%d, X%d, X%d, %s #%d\n", 1078 Rd, Rn, Rm, shift_codes[shift], amount); 1079 return ((0x8B << 24) | (shift << 22) | ( Rm << 16) | 1080 (amount << 10) |(Rn << 5) | Rd); 1081 } 1082 uint32_t ArmToArm64Assembler::A64_ADD_IMM_X(uint32_t Rd, uint32_t Rn, 1083 uint32_t imm, uint32_t shift) 1084 { 1085 LOG_INSTR("ADD X%d, X%d, #%d, LSL #%d\n", Rd, Rn, imm, shift); 1086 return (0x91 << 24) | ((shift/12) << 22) | (imm << 10) | (Rn << 5) | Rd; 1087 } 1088 1089 uint32_t ArmToArm64Assembler::A64_SUB_IMM_X(uint32_t Rd, uint32_t Rn, 1090 uint32_t imm, uint32_t shift) 1091 { 1092 LOG_INSTR("SUB X%d, X%d, #%d, LSL #%d\n", Rd, Rn, imm, shift); 1093 return (0xD1 << 24) | ((shift/12) << 22) | (imm << 10) | (Rn << 5) | Rd; 1094 } 1095 1096 uint32_t ArmToArm64Assembler::A64_ADD_W(uint32_t Rd, uint32_t Rn, 1097 uint32_t Rm, uint32_t shift, 1098 uint32_t amount) 1099 { 1100 LOG_INSTR("ADD W%d, W%d, W%d, %s #%d\n", 1101 Rd, Rn, Rm, shift_codes[shift], amount); 1102 return ((0x0B << 24) | (shift << 22) | ( Rm << 16) | 1103 (amount << 10) |(Rn << 5) | Rd); 1104 } 1105 1106 uint32_t ArmToArm64Assembler::A64_SUB_W(uint32_t Rd, uint32_t Rn, 1107 uint32_t Rm, uint32_t shift, 1108 uint32_t amount, 1109 uint32_t setflag) 1110 { 1111 if(setflag == 0) 1112 { 1113 LOG_INSTR("SUB W%d, W%d, W%d, %s #%d\n", 1114 Rd, Rn, Rm, shift_codes[shift], amount); 1115 return ((0x4B << 24) | (shift << 22) | ( Rm << 16) | 1116 (amount << 10) |(Rn << 5) | Rd); 1117 } 1118 else 1119 { 1120 LOG_INSTR("SUBS W%d, W%d, W%d, %s #%d\n", 1121 Rd, Rn, Rm, shift_codes[shift], amount); 1122 return ((0x6B << 24) | (shift << 22) | ( Rm << 16) | 1123 (amount << 10) |(Rn << 5) | Rd); 1124 } 1125 } 1126 1127 uint32_t ArmToArm64Assembler::A64_AND_W(uint32_t Rd, uint32_t Rn, 1128 uint32_t Rm, uint32_t shift, 1129 uint32_t amount) 1130 { 1131 LOG_INSTR("AND W%d, W%d, W%d, %s #%d\n", 1132 Rd, Rn, Rm, shift_codes[shift], amount); 1133 return ((0x0A << 24) | (shift << 22) | ( Rm << 16) | 1134 (amount << 10) |(Rn << 5) | Rd); 1135 } 1136 1137 uint32_t ArmToArm64Assembler::A64_ORR_W(uint32_t Rd, uint32_t Rn, 1138 uint32_t Rm, uint32_t shift, 1139 uint32_t amount) 1140 { 1141 LOG_INSTR("ORR W%d, W%d, W%d, %s #%d\n", 1142 Rd, Rn, Rm, shift_codes[shift], amount); 1143 return ((0x2A << 24) | (shift << 22) | ( Rm << 16) | 1144 (amount << 10) |(Rn << 5) | Rd); 1145 } 1146 1147 uint32_t ArmToArm64Assembler::A64_ORN_W(uint32_t Rd, uint32_t Rn, 1148 uint32_t Rm, uint32_t shift, 1149 uint32_t amount) 1150 { 1151 LOG_INSTR("ORN W%d, W%d, W%d, %s #%d\n", 1152 Rd, Rn, Rm, shift_codes[shift], amount); 1153 return ((0x2A << 24) | (shift << 22) | (0x1 << 21) | ( Rm << 16) | 1154 (amount << 10) |(Rn << 5) | Rd); 1155 } 1156 1157 uint32_t ArmToArm64Assembler::A64_CSEL_X(uint32_t Rd, uint32_t Rn, 1158 uint32_t Rm, uint32_t cond) 1159 { 1160 LOG_INSTR("CSEL X%d, X%d, X%d, %s\n", Rd, Rn, Rm, cc_codes[cond]); 1161 return ((0x9A << 24)|(0x1 << 23)|(Rm << 16) |(cond << 12)| (Rn << 5) | Rd); 1162 } 1163 1164 uint32_t ArmToArm64Assembler::A64_CSEL_W(uint32_t Rd, uint32_t Rn, 1165 uint32_t Rm, uint32_t cond) 1166 { 1167 LOG_INSTR("CSEL W%d, W%d, W%d, %s\n", Rd, Rn, Rm, cc_codes[cond]); 1168 return ((0x1A << 24)|(0x1 << 23)|(Rm << 16) |(cond << 12)| (Rn << 5) | Rd); 1169 } 1170 1171 uint32_t ArmToArm64Assembler::A64_RET(uint32_t Rn) 1172 { 1173 LOG_INSTR("RET X%d\n", Rn); 1174 return ((0xD6 << 24) | (0x1 << 22) | (0x1F << 16) | (Rn << 5)); 1175 } 1176 1177 uint32_t ArmToArm64Assembler::A64_MOVZ_X(uint32_t Rd, uint32_t imm, 1178 uint32_t shift) 1179 { 1180 LOG_INSTR("MOVZ X%d, #0x%x, LSL #%d\n", Rd, imm, shift); 1181 return(0xD2 << 24) | (0x1 << 23) | ((shift/16) << 21) | (imm << 5) | Rd; 1182 } 1183 1184 uint32_t ArmToArm64Assembler::A64_MOVK_W(uint32_t Rd, uint32_t imm, 1185 uint32_t shift) 1186 { 1187 LOG_INSTR("MOVK W%d, #0x%x, LSL #%d\n", Rd, imm, shift); 1188 return (0x72 << 24) | (0x1 << 23) | ((shift/16) << 21) | (imm << 5) | Rd; 1189 } 1190 1191 uint32_t ArmToArm64Assembler::A64_MOVZ_W(uint32_t Rd, uint32_t imm, 1192 uint32_t shift) 1193 { 1194 LOG_INSTR("MOVZ W%d, #0x%x, LSL #%d\n", Rd, imm, shift); 1195 return(0x52 << 24) | (0x1 << 23) | ((shift/16) << 21) | (imm << 5) | Rd; 1196 } 1197 1198 uint32_t ArmToArm64Assembler::A64_SMADDL(uint32_t Rd, uint32_t Rn, 1199 uint32_t Rm, uint32_t Ra) 1200 { 1201 LOG_INSTR("SMADDL X%d, W%d, W%d, X%d\n",Rd, Rn, Rm, Ra); 1202 return ((0x9B << 24) | (0x1 << 21) | (Rm << 16)|(Ra << 10)|(Rn << 5) | Rd); 1203 } 1204 1205 uint32_t ArmToArm64Assembler::A64_MADD_W(uint32_t Rd, uint32_t Rn, 1206 uint32_t Rm, uint32_t Ra) 1207 { 1208 LOG_INSTR("MADD W%d, W%d, W%d, W%d\n",Rd, Rn, Rm, Ra); 1209 return ((0x1B << 24) | (Rm << 16) | (Ra << 10) |(Rn << 5) | Rd); 1210 } 1211 1212 uint32_t ArmToArm64Assembler::A64_SBFM_W(uint32_t Rd, uint32_t Rn, 1213 uint32_t immr, uint32_t imms) 1214 { 1215 LOG_INSTR("SBFM W%d, W%d, #%d, #%d\n", Rd, Rn, immr, imms); 1216 return ((0x13 << 24) | (immr << 16) | (imms << 10) | (Rn << 5) | Rd); 1217 1218 } 1219 uint32_t ArmToArm64Assembler::A64_UBFM_W(uint32_t Rd, uint32_t Rn, 1220 uint32_t immr, uint32_t imms) 1221 { 1222 LOG_INSTR("UBFM W%d, W%d, #%d, #%d\n", Rd, Rn, immr, imms); 1223 return ((0x53 << 24) | (immr << 16) | (imms << 10) | (Rn << 5) | Rd); 1224 1225 } 1226 uint32_t ArmToArm64Assembler::A64_UBFM_X(uint32_t Rd, uint32_t Rn, 1227 uint32_t immr, uint32_t imms) 1228 { 1229 LOG_INSTR("UBFM X%d, X%d, #%d, #%d\n", Rd, Rn, immr, imms); 1230 return ((0xD3 << 24) | (0x1 << 22) | 1231 (immr << 16) | (imms << 10) | (Rn << 5) | Rd); 1232 1233 } 1234 uint32_t ArmToArm64Assembler::A64_EXTR_W(uint32_t Rd, uint32_t Rn, 1235 uint32_t Rm, uint32_t lsb) 1236 { 1237 LOG_INSTR("EXTR W%d, W%d, W%d, #%d\n", Rd, Rn, Rm, lsb); 1238 return (0x13 << 24)|(0x1 << 23) | (Rm << 16) | (lsb << 10)|(Rn << 5) | Rd; 1239 } 1240 1241 }; // namespace android 1242 1243