Arm64Assembler.cpp revision 3078b13b98ad8d29dcb2b7e3665c0c92944404a9
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 153namespace android { 154 155static const char* shift_codes[] = 156{ 157 "LSL", "LSR", "ASR", "ROR" 158}; 159static 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 166ArmToArm64Assembler::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 178ArmToArm64Assembler::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 190ArmToArm64Assembler::~ArmToArm64Assembler() 191{ 192} 193 194uint32_t* ArmToArm64Assembler::pc() const 195{ 196 return mPC; 197} 198 199uint32_t* ArmToArm64Assembler::base() const 200{ 201 return mBase; 202} 203 204void 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 219int ArmToArm64Assembler::getCodegenArch() 220{ 221 return CODEGEN_ARCH_ARM64; 222} 223 224// ---------------------------------------------------------------------------- 225 226void 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 256void ArmToArm64Assembler::comment(const char* string) 257{ 258 mComments.add(mPC, string); 259 LOG_INSTR("//%s\n", string); 260} 261 262void ArmToArm64Assembler::label(const char* theLabel) 263{ 264 mLabels.add(theLabel, mPC); 265 mLabelsInverseMapping.add(mPC, theLabel); 266 LOG_LABEL("%s:\n", theLabel); 267} 268 269void 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 276void ArmToArm64Assembler::BL(int /*cc*/, const char* /*label*/) 277{ 278 NOT_IMPLEMENTED(); //Not Required 279} 280 281// ---------------------------------------------------------------------------- 282//Prolog/Epilog & Generate... 283// ---------------------------------------------------------------------------- 284 285void ArmToArm64Assembler::prolog() 286{ 287 // write prolog code 288 mPrologPC = mPC; 289 *mPC++ = A64_MOVZ_X(mZeroReg,0,0); 290} 291 292void ArmToArm64Assembler::epilog(uint32_t /*touched*/) 293{ 294 // write epilog code 295 static const int XLR = 30; 296 *mPC++ = A64_RET(XLR); 297} 298 299int 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 332uint32_t* ArmToArm64Assembler::pcForLabel(const char* label) 333{ 334 return mLabels.valueFor(label); 335} 336 337// ---------------------------------------------------------------------------- 338// Data Processing... 339// ---------------------------------------------------------------------------- 340void 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 408void 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 463void 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 498void 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// ---------------------------------------------------------------------------- 519void 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} 527void 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} 533void ArmToArm64Assembler::UMULL(int /*cc*/, int /*s*/, 534 int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/) 535{ 536 NOT_IMPLEMENTED(); //Not required 537} 538void ArmToArm64Assembler::UMUAL(int /*cc*/, int /*s*/, 539 int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/) 540{ 541 NOT_IMPLEMENTED(); //Not required 542} 543void ArmToArm64Assembler::SMULL(int /*cc*/, int /*s*/, 544 int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/) 545{ 546 NOT_IMPLEMENTED(); //Not required 547} 548void 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// ---------------------------------------------------------------------------- 557void ArmToArm64Assembler::B(int /*cc*/, uint32_t* /*pc*/){ 558 NOT_IMPLEMENTED(); //Not required 559} 560 561void ArmToArm64Assembler::BL(int /*cc*/, uint32_t* /*pc*/){ 562 NOT_IMPLEMENTED(); //Not required 563} 564 565void ArmToArm64Assembler::BX(int /*cc*/, int /*Rn*/){ 566 NOT_IMPLEMENTED(); //Not required 567} 568 569// ---------------------------------------------------------------------------- 570// data transfer... 571// ---------------------------------------------------------------------------- 572enum dataTransferOp 573{ 574 opLDR,opLDRB,opLDRH,opSTR,opSTRB,opSTRH 575}; 576 577void 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} 634void 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} 638void 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} 642void ArmToArm64Assembler::LDR(int cc, int Rd, int Rn, uint32_t op_type) 643{ 644 return dataTransfer(opLDR, cc, Rd, Rn, op_type); 645} 646void ArmToArm64Assembler::LDRB(int cc, int Rd, int Rn, uint32_t op_type) 647{ 648 return dataTransfer(opLDRB, cc, Rd, Rn, op_type); 649} 650void ArmToArm64Assembler::STR(int cc, int Rd, int Rn, uint32_t op_type) 651{ 652 return dataTransfer(opSTR, cc, Rd, Rn, op_type); 653} 654 655void ArmToArm64Assembler::STRB(int cc, int Rd, int Rn, uint32_t op_type) 656{ 657 return dataTransfer(opSTRB, cc, Rd, Rn, op_type); 658} 659 660void ArmToArm64Assembler::LDRH(int cc, int Rd, int Rn, uint32_t op_type) 661{ 662 return dataTransfer(opLDRH, cc, Rd, Rn, op_type); 663} 664void ArmToArm64Assembler::LDRSB(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/) 665{ 666 NOT_IMPLEMENTED(); //Not required 667} 668void ArmToArm64Assembler::LDRSH(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/) 669{ 670 NOT_IMPLEMENTED(); //Not required 671} 672 673void 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// ---------------------------------------------------------------------------- 681void 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 702void 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// ---------------------------------------------------------------------------- 726void ArmToArm64Assembler::SWP(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/) 727{ 728 NOT_IMPLEMENTED(); //Not required 729} 730void ArmToArm64Assembler::SWPB(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/) 731{ 732 NOT_IMPLEMENTED(); //Not required 733} 734void ArmToArm64Assembler::SWI(int /*cc*/, uint32_t /*comment*/) 735{ 736 NOT_IMPLEMENTED(); //Not required 737} 738 739// ---------------------------------------------------------------------------- 740// DSP instructions... 741// ---------------------------------------------------------------------------- 742void ArmToArm64Assembler::PLD(int /*Rn*/, uint32_t /*offset*/) { 743 NOT_IMPLEMENTED(); //Not required 744} 745 746void ArmToArm64Assembler::CLZ(int /*cc*/, int /*Rd*/, int /*Rm*/) 747{ 748 NOT_IMPLEMENTED(); //Not required 749} 750 751void ArmToArm64Assembler::QADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/) 752{ 753 NOT_IMPLEMENTED(); //Not required 754} 755 756void ArmToArm64Assembler::QDADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/) 757{ 758 NOT_IMPLEMENTED(); //Not required 759} 760 761void ArmToArm64Assembler::QSUB(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/) 762{ 763 NOT_IMPLEMENTED(); //Not required 764} 765 766void 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// ---------------------------------------------------------------------------- 774void 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// ---------------------------------------------------------------------------- 794void 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// ---------------------------------------------------------------------------- 810void 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 820void 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 827void 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// ---------------------------------------------------------------------------- 837void 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// ---------------------------------------------------------------------------- 852void 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// ---------------------------------------------------------------------------- 860int 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 869bool ArmToArm64Assembler::isValidImmediate(uint32_t immediate) 870{ 871 uint32_t rot, imm; 872 return buildImmediate(immediate, rot, imm) == 0; 873} 874 875uint32_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 885uint32_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 893uint32_t ArmToArm64Assembler::reg_rrx(int /*Rm*/) 894{ 895 NOT_IMPLEMENTED(); 896 return OPERAND_UNSUPPORTED; 897} 898 899uint32_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// ---------------------------------------------------------------------------- 907uint32_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 916uint32_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 925uint32_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 940uint32_t ArmToArm64Assembler::reg_scale_post(int /*Rm*/, int /*type*/, uint32_t /*shift*/) 941{ 942 NOT_IMPLEMENTED(); //Not required 943 return OPERAND_UNSUPPORTED; 944} 945 946uint32_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 955uint32_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 964uint32_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 978uint32_t ArmToArm64Assembler::reg_post(int /*Rm*/) 979{ 980 NOT_IMPLEMENTED(); //Not required 981 return OPERAND_UNSUPPORTED; 982} 983 984// ---------------------------------------------------------------------------- 985// A64 instructions 986// ---------------------------------------------------------------------------- 987 988static const char * dataTransferOpName[] = 989{ 990 "LDR","LDRB","LDRH","STR","STRB","STRH" 991}; 992 993static 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}; 1002uint32_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 1020uint32_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 1032uint32_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} 1045uint32_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 1056uint32_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 1067uint32_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} 1073uint32_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} 1082uint32_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 1089uint32_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 1096uint32_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 1106uint32_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 1127uint32_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 1137uint32_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 1147uint32_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 1157uint32_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 1164uint32_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 1171uint32_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 1177uint32_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 1184uint32_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 1191uint32_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 1198uint32_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 1205uint32_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 1212uint32_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} 1219uint32_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} 1226uint32_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} 1234uint32_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