1/* DO NOT EDIT: This file was generated by gen-mterp.py. */ 2/* 3 * Copyright (C) 2020 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18/* 19 * This is a #include, not a %include, because we want the C pre-processor 20 * to expand the macros into assembler assignment statements. 21 */ 22#include "asm_support.h" 23#include "arch/arm64/asm_support_arm64.S" 24 25/** 26 * ARM64 Runtime register usage conventions. 27 * 28 * r0 : w0 is 32-bit return register and x0 is 64-bit. 29 * r0-r7 : Argument registers. 30 * r8-r15 : Caller save registers (used as temporary registers). 31 * r16-r17: Also known as ip0-ip1, respectively. Used as scratch registers by 32 * the linker, by the trampolines and other stubs (the compiler uses 33 * these as temporary registers). 34 * r18 : Reserved for platform (SCS, shadow call stack) 35 * r19 : Pointer to thread-local storage. 36 * r20-r29: Callee save registers. 37 * r30 : (lr) is reserved (the link register). 38 * rsp : (sp) is reserved (the stack pointer). 39 * rzr : (zr) is reserved (the zero register). 40 * 41 * Floating-point registers 42 * v0-v31 43 * 44 * v0 : s0 is return register for singles (32-bit) and d0 for doubles (64-bit). 45 * This is analogous to the C/C++ (hard-float) calling convention. 46 * v0-v7 : Floating-point argument registers in both Dalvik and C/C++ conventions. 47 * Also used as temporary and codegen scratch registers. 48 * 49 * v0-v7 and v16-v31 : Caller save registers (used as temporary registers). 50 * v8-v15 : bottom 64-bits preserved across C calls (d8-d15 are preserved). 51 * 52 * v16-v31: Used as codegen temp/scratch. 53 * v8-v15 : Can be used for promotion. 54 * 55 * Must maintain 16-byte stack alignment. 56 * 57 * Nterp notes: 58 * 59 * The following registers have fixed assignments: 60 * 61 * reg nick purpose 62 * x19 xSELF self (Thread) pointer 63 * x20 wMR marking register 64 * x21 xSUSPEND suspend check register 65 * x29 xFP interpreted frame pointer, used for accessing locals and args 66 * x22 xPC interpreted program counter, used for fetching instructions 67 * x23 xINST first 16-bit code unit of current instruction 68 * x24 xIBASE interpreted instruction base pointer, used for computed goto 69 * x25 xREFS base of object references of dex registers. 70 * x16 ip scratch reg 71 * x17 ip2 scratch reg (used by macros) 72 * 73 * Macros are provided for common operations. They MUST NOT alter unspecified registers or 74 * condition codes. 75*/ 76 77/* single-purpose registers, given names for clarity */ 78#define CFI_DEX 22 // DWARF register number of the register holding dex-pc (xPC). 79#define CFI_TMP 0 // DWARF register number of the first argument register (r0). 80#define xPC x22 81#define xINST x23 82#define wINST w23 83#define xIBASE x24 84#define xREFS x25 85#define CFI_REFS 25 86#define ip x16 87#define ip2 x17 88#define wip w16 89#define wip2 w17 90 91// To avoid putting ifdefs arond the use of wMR, make sure it's defined. 92// IsNterpSupported returns false for configurations that don't have wMR (typically CMS). 93#ifndef wMR 94#define wMR w20 95#endif 96 97// Temporary registers while setting up a frame. 98#define xNEW_FP x26 99#define xNEW_REFS x27 100#define CFI_NEW_REFS 27 101 102// +8 for the ArtMethod of the caller. 103#define OFFSET_TO_FIRST_ARGUMENT_IN_STACK (CALLEE_SAVES_SIZE + 8) 104 105/* 106 * Fetch the next instruction from xPC into wINST. Does not advance xPC. 107 */ 108.macro FETCH_INST 109 ldrh wINST, [xPC] 110.endm 111 112/* 113 * Fetch the next instruction from the specified offset. Advances xPC 114 * to point to the next instruction. "count" is in 16-bit code units. 115 * 116 * Because of the limited size of immediate constants on ARM, this is only 117 * suitable for small forward movements (i.e. don't try to implement "goto" 118 * with this). 119 * 120 * This must come AFTER anything that can throw an exception, or the 121 * exception catch may miss. (This also implies that it must come after 122 * EXPORT_PC.) 123 */ 124.macro FETCH_ADVANCE_INST count 125 ldrh wINST, [xPC, #((\count)*2)]! 126.endm 127 128/* 129 * Similar to FETCH_ADVANCE_INST, but does not update xPC. Used to load 130 * xINST ahead of possible exception point. Be sure to manually advance xPC 131 * later. 132 */ 133.macro PREFETCH_INST count 134 ldrh wINST, [xPC, #((\count)*2)] 135.endm 136 137/* Advance xPC by some number of code units. */ 138.macro ADVANCE count 139 add xPC, xPC, #((\count)*2) 140.endm 141 142/* 143 * Fetch a half-word code unit from an offset past the current PC. The 144 * "count" value is in 16-bit code units. Does not advance xPC. 145 * 146 * The "_S" variant works the same but treats the value as signed. 147 */ 148.macro FETCH reg, count 149 ldrh \reg, [xPC, #((\count)*2)] 150.endm 151 152.macro FETCH_S reg, count 153 ldrsh \reg, [xPC, #((\count)*2)] 154.endm 155 156/* 157 * Fetch one byte from an offset past the current PC. Pass in the same 158 * "count" as you would for FETCH, and an additional 0/1 indicating which 159 * byte of the halfword you want (lo/hi). 160 */ 161.macro FETCH_B reg, count, byte 162 ldrb \reg, [xPC, #((\count)*2+(\byte))] 163.endm 164 165/* 166 * Put the instruction's opcode field into the specified register. 167 */ 168.macro GET_INST_OPCODE reg 169 and \reg, xINST, #255 170.endm 171 172/* 173 * Begin executing the opcode in _reg. Clobbers reg 174 */ 175 176.macro GOTO_OPCODE reg 177 add \reg, xIBASE, \reg, lsl #NTERP_HANDLER_SIZE_LOG2 178 br \reg 179.endm 180 181/* 182 * Get/set the 32-bit value from a Dalvik register. 183 */ 184.macro GET_VREG reg, vreg 185 ldr \reg, [xFP, \vreg, uxtw #2] 186.endm 187.macro GET_VREG_OBJECT reg, vreg 188 ldr \reg, [xREFS, \vreg, uxtw #2] 189.endm 190.macro SET_VREG reg, vreg 191 str \reg, [xFP, \vreg, uxtw #2] 192 str wzr, [xREFS, \vreg, uxtw #2] 193.endm 194.macro SET_VREG_OBJECT reg, vreg 195 str \reg, [xFP, \vreg, uxtw #2] 196 str \reg, [xREFS, \vreg, uxtw #2] 197.endm 198.macro SET_VREG_FLOAT reg, vreg 199 str \reg, [xFP, \vreg, uxtw #2] 200 str wzr, [xREFS, \vreg, uxtw #2] 201.endm 202 203/* 204 * Get/set the 64-bit value from a Dalvik register. 205 */ 206.macro LOAD_SCALED_VREG_MASK scaled_mask_reg, unscaled_mask 207 mov \scaled_mask_reg, \unscaled_mask << 2 208.endm 209.macro EXTRACT_SCALED_VREG scaled_vreg, scaled_mask_reg, src_reg, lsb 210 .if \lsb < 2 211 and \scaled_vreg, \scaled_mask_reg, \src_reg, lsl #(2 - \lsb) 212 .else 213 and \scaled_vreg, \scaled_mask_reg, \src_reg, lsr #(\lsb - 2) 214 .endif 215.endm 216.macro GET_VREG_WIDE_PRESCALED reg, scaled_vreg 217 ldr \reg, [xFP, \scaled_vreg, uxtw] 218.endm 219.macro GET_VREG_WIDE reg, vreg 220 lsl wip2, \vreg, #2 221 GET_VREG_WIDE_PRESCALED \reg, wip2 222.endm 223.macro SET_VREG_WIDE_PRESCALED reg, scaled_vreg 224 str \reg, [xFP, \scaled_vreg, uxtw] 225 str xzr, [xREFS, \scaled_vreg, uxtw] 226.endm 227.macro SET_VREG_WIDE reg, vreg 228 lsl wip2, \vreg, #2 229 SET_VREG_WIDE_PRESCALED \reg, wip2 230.endm 231.macro GET_VREG_DOUBLE_PRESCALED reg, scaled_vreg 232 GET_VREG_WIDE_PRESCALED \reg, \scaled_vreg 233.endm 234.macro GET_VREG_DOUBLE reg, vreg 235 GET_VREG_WIDE \reg, \vreg 236.endm 237.macro SET_VREG_DOUBLE reg, vreg 238 SET_VREG_WIDE \reg, \vreg 239.endm 240 241/* 242 * Get the 32-bit value from a Dalvik register and sign-extend to 64-bit. 243 * Used to avoid an extra instruction in int-to-long. 244 */ 245.macro GET_VREG_S reg, vreg 246 ldrsw \reg, [xFP, \vreg, uxtw #2] 247.endm 248 249// An assembly entry for nterp. 250.macro OAT_ENTRY name 251 .type \name, #function 252 .hidden \name 253 .global \name 254 .balign 16 255\name: 256.endm 257 258.macro SIZE name 259 .size \name, .-\name 260.endm 261 262.macro NAME_START name 263 .type \name, #function 264 .hidden \name // Hide this as a global symbol, so we do not incur plt calls. 265 .global \name 266 /* Cache alignment for function entry */ 267 .balign 16 268\name: 269.endm 270 271.macro NAME_END name 272 SIZE \name 273.endm 274 275// Macro for defining entrypoints into runtime. We don't need to save registers 276// (we're not holding references there), but there is no 277// kDontSave runtime method. So just use the kSaveRefsOnly runtime method. 278.macro NTERP_TRAMPOLINE name, helper 279ENTRY \name 280 SETUP_SAVE_REFS_ONLY_FRAME 281 bl \helper 282 RESTORE_SAVE_REFS_ONLY_FRAME 283 REFRESH_MARKING_REGISTER 284 ldr xIP0, [xSELF, # THREAD_EXCEPTION_OFFSET] // Get exception field. 285 cbnz xIP0, nterp_deliver_pending_exception 286 ret 287END \name 288.endm 289 290.macro CLEAR_STATIC_VOLATILE_MARKER reg 291 and \reg, \reg, #-2 292.endm 293 294.macro CLEAR_INSTANCE_VOLATILE_MARKER reg 295 neg \reg, \reg 296.endm 297 298.macro EXPORT_PC 299 str xPC, [xREFS, #-16] 300.endm 301 302.macro BRANCH 303 add xPC, xPC, wINST, sxtw #1 // update xPC 304 // Update method counter and do a suspend check if the branch is negative or zero. 305 cmp wINST, #0 306 b.le 2f 3071: 308 FETCH wINST, 0 // load wINST 309 GET_INST_OPCODE ip // extract opcode from wINST 310 GOTO_OPCODE ip // jump to next instruction 3112: 312 ldr x0, [sp] 313 ldrh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET] 314#if (NTERP_HOTNESS_VALUE != 0) 315#error Expected 0 for hotness value 316#endif 317 // If the counter is at zero, handle this in the runtime. 318 cbz w2, NterpHandleHotnessOverflow 319 add x2, x2, #-1 320 strh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET] 321 DO_SUSPEND_CHECK continue_label=1b 322 b 1b 323.endm 324 325// Uses x12, x13, and x14 as temporaries. 326.macro FETCH_CODE_ITEM_INFO code_item, registers, outs, ins, load_ins 327 // Fetch dex register size. 328 ldrh \registers, [\code_item, #CODE_ITEM_REGISTERS_SIZE_OFFSET] 329 // Fetch outs size. 330 ldrh \outs, [\code_item, #CODE_ITEM_OUTS_SIZE_OFFSET] 331 .if \load_ins 332 ldrh \ins, [\code_item, #CODE_ITEM_INS_SIZE_OFFSET] 333 .endif 334 add \code_item, \code_item, #CODE_ITEM_INSNS_OFFSET 335.endm 336 337.macro TEST_IF_MARKING label 338 cbnz wMR, \label 339.endm 340 341// Setup the stack to start executing the method. Expects: 342// - x0 to contain the ArtMethod 343// 344// Outputs 345// - ip contains the dex registers size 346// - x28 contains the old stack pointer. 347// - \code_item is replaced with a pointer to the instructions 348// - if load_ins is 1, w15 contains the ins 349// 350// Uses ip, ip2, x12, x13, x14 as temporaries. 351.macro SETUP_STACK_FRAME code_item, refs, fp, cfi_refs, load_ins 352 FETCH_CODE_ITEM_INFO \code_item, wip, wip2, w15, \load_ins 353 354 // Compute required frame size: ((2 * ip) + ip2) * 4 + 24 355 // 24 is for saving the previous frame, pc, and method being executed. 356 add x14, ip, ip 357 add x14, x14, ip2 358 lsl x14, x14, #2 359 add x14, x14, #24 360 361 // Compute new stack pointer in x14 362 sub x14, sp, x14 363 // Alignment 364 and x14, x14, #-16 365 366 // Set reference and dex registers, align to pointer size for previous frame and dex pc. 367 add \refs, x14, ip2, lsl #2 368 add \refs, \refs, 28 369 and \refs, \refs, #(-__SIZEOF_POINTER__) 370 add \fp, \refs, ip, lsl #2 371 372 // Now setup the stack pointer. 373 mov x28, sp 374 .cfi_def_cfa_register x28 375 mov sp, x14 376 str x28, [\refs, #-8] 377 CFI_DEF_CFA_BREG_PLUS_UCONST \cfi_refs, -8, CALLEE_SAVES_SIZE 378 379 // Put nulls in reference frame. 380 cbz ip, 2f 381 mov ip2, \refs 3821: 383 str xzr, [ip2], #8 // May clear vreg[0]. 384 cmp ip2, \fp 385 b.lo 1b 3862: 387 // Save the ArtMethod. 388 str x0, [sp] 389.endm 390 391// Increase method hotness and do suspend check before starting executing the method. 392.macro START_EXECUTING_INSTRUCTIONS 393 ldr x0, [sp] 394 ldrh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET] 395#if (NTERP_HOTNESS_VALUE != 0) 396#error Expected 0 for hotness value 397#endif 398 // If the counter is at zero, handle this in the runtime. 399 cbz w2, 3f 400 add x2, x2, #-1 401 strh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET] 4021: 403 DO_SUSPEND_CHECK continue_label=2f 4042: 405 FETCH_INST 406 GET_INST_OPCODE ip 407 GOTO_OPCODE ip 4083: 409 CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot=4f, if_not_hot=1b 4104: 411 mov x1, xzr 412 mov x2, xFP 413 bl nterp_hot_method 414 b 2b 415.endm 416 417.macro SPILL_ALL_CALLEE_SAVES 418 INCREASE_FRAME CALLEE_SAVES_SIZE 419 // Note: we technically don't need to save x19 and x20, 420 // but the runtime will expect those values to be there when unwinding 421 // (see Arm64Context::DoLongJump checking for the thread register). 422 SAVE_ALL_CALLEE_SAVES 0 423.endm 424 425.macro RESTORE_ALL_CALLEE_SAVES 426 // FP callee-saves 427 ldp d8, d9, [sp, #0] 428 ldp d10, d11, [sp, #16] 429 ldp d12, d13, [sp, #32] 430 ldp d14, d15, [sp, #48] 431 432 // GP callee-saves. 433 // No need to restore x19 (it's always the thread), and 434 // don't restore x20 (the marking register) as it may have been updated, 435 // don't restore x21 (the suspend check register) as it may have been updated. 436 RESTORE_REG x22, 88 437 RESTORE_TWO_REGS x23, x24, 96 438 RESTORE_TWO_REGS x25, x26, 112 439 RESTORE_TWO_REGS x27, x28, 128 440 RESTORE_TWO_REGS x29, lr, 144 441 442 DECREASE_FRAME CALLEE_SAVES_SIZE 443.endm 444 445.macro SPILL_ALL_ARGUMENTS 446 stp x0, x1, [sp, #-128]! 447 stp x2, x3, [sp, #16] 448 stp x4, x5, [sp, #32] 449 stp x6, x7, [sp, #48] 450 stp d0, d1, [sp, #64] 451 stp d2, d3, [sp, #80] 452 stp d4, d5, [sp, #96] 453 stp d6, d7, [sp, #112] 454.endm 455 456.macro RESTORE_ALL_ARGUMENTS 457 ldp x2, x3, [sp, #16] 458 ldp x4, x5, [sp, #32] 459 ldp x6, x7, [sp, #48] 460 ldp d0, d1, [sp, #64] 461 ldp d2, d3, [sp, #80] 462 ldp d4, d5, [sp, #96] 463 ldp d6, d7, [sp, #112] 464 ldp x0, x1, [sp], #128 465.endm 466 467// Helper to setup the stack after doing a nterp to nterp call. This will setup: 468// - xNEW_FP: the new pointer to dex registers 469// - xNEW_REFS: the new pointer to references 470// - xPC: the new PC pointer to execute 471// - x2: value in instruction to decode the number of arguments. 472// - x3: first dex register 473// - x4: top of dex register array 474// 475// The method expects: 476// - x0 to contain the ArtMethod 477// - x8 to contain the code item 478.macro SETUP_STACK_FOR_INVOKE 479 // We do the same stack overflow check as the compiler. See CanMethodUseNterp 480 // in how we limit the maximum nterp frame size. 481 sub x16, sp, #STACK_OVERFLOW_RESERVED_BYTES 482 ldr wzr, [x16] 483 484 // Spill all callee saves to have a consistent stack frame whether we 485 // are called by compiled code or nterp. 486 SPILL_ALL_CALLEE_SAVES 487 488 // Setup the frame. 489 SETUP_STACK_FRAME x8, xNEW_REFS, xNEW_FP, CFI_NEW_REFS, load_ins=0 490 // Make x4 point to the top of the dex register array. 491 add x4, xNEW_FP, ip, uxtx #2 492 493 // Fetch instruction information before replacing xPC. 494 // TODO: move this down to the method that uses it, fetching it directly from wINST. 495 FETCH_B w2, 0, 1 496 // TODO: we could avoid this as instance invokes already fetch it. 497 FETCH w3, 2 498 499 // Set the dex pc pointer. 500 mov xPC, x8 501 CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0) 502.endm 503 504// Setup arguments based on a non-range nterp to nterp call, and start executing 505// the method. We expect: 506// - xNEW_FP: the new pointer to dex registers 507// - xNEW_REFS: the new pointer to references 508// - xPC: the new PC pointer to execute 509// - x2: number of arguments (bits 4-7), 5th argument if any (bits 0-3) 510// - x3: first dex register 511// - x4: top of dex register array 512// - x1: receiver if non-static. 513.macro SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0 514 // /* op vA, vB, {vC...vG} */ 515 asr ip2, x2, #4 516 cbz ip2, 6f 517 mov ip, #-4 518 cmp ip2, #2 519 b.lt 1f 520 b.eq 2f 521 cmp ip2, #4 522 b.lt 3f 523 b.eq 4f 524 525 // We use a decrementing ip to store references relative 526 // to xNEW_FP and dex registers relative to x4 527 // 528 // TODO: We could set up ip as the number of registers (this can be an additional output from 529 // SETUP_STACK_FOR_INVOKE) and then just decrement it by one before copying each arg. 530 // Maybe even introduce macros NEW_VREG_ADDRESS/NEW_VREG_REF_ADDRESS. 5315: 532 and x2, x2, #15 533 GET_VREG_OBJECT w5, w2 534 str w5, [xNEW_FP, ip] 535 GET_VREG w5, w2 536 str w5, [x4, ip] 537 sub ip, ip, #4 5384: 539 asr x2, x3, #12 540 GET_VREG_OBJECT w5, w2 541 str w5, [xNEW_FP, ip] 542 GET_VREG w5, w2 543 str w5, [x4, ip] 544 sub ip, ip, #4 5453: 546 ubfx x2, x3, #8, #4 547 GET_VREG_OBJECT w5, w2 548 str w5, [xNEW_FP, ip] 549 GET_VREG w5, w2 550 str w5, [x4, ip] 551 sub ip, ip, #4 5522: 553 ubfx x2, x3, #4, #4 554 GET_VREG_OBJECT w5, w2 555 str w5, [xNEW_FP, ip] 556 GET_VREG w5, w2 557 str w5, [x4, ip] 558 .if !\is_string_init 559 sub ip, ip, #4 560 .endif 5611: 562 .if \is_string_init 563 // Ignore the first argument 564 .elseif \is_static 565 and x2, x3, #0xf 566 GET_VREG_OBJECT w5, w2 567 str w5, [xNEW_FP, ip] 568 GET_VREG w5, w2 569 str w5, [x4, ip] 570 .else 571 str w1, [xNEW_FP, ip] 572 str w1, [x4, ip] 573 .endif 574 5756: 576 // Start executing the method. 577 mov xFP, xNEW_FP 578 mov xREFS, xNEW_REFS 579 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 580 START_EXECUTING_INSTRUCTIONS 581.endm 582 583// Setup arguments based on a range nterp to nterp call, and start executing 584// the method. 585// - xNEW_FP: the new pointer to dex registers 586// - xNEW_REFS: the new pointer to references 587// - xPC: the new PC pointer to execute 588// - x2: number of arguments 589// - x3: first dex register 590// - x4: top of dex register array 591// - x1: receiver if non-static. 592// 593// Uses ip, ip2, x5, x6 as temporaries. 594.macro SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0 595 mov ip, #-4 596 .if \is_string_init 597 // Ignore the first argument 598 sub x2, x2, #1 599 add x3, x3, #1 600 .elseif !\is_static 601 sub x2, x2, #1 602 add x3, x3, #1 603 .endif 604 605 cbz x2, 2f 606 add ip2, xREFS, x3, lsl #2 // pointer to first argument in reference array 607 add ip2, ip2, x2, lsl #2 // pointer to last argument in reference array 608 add x5, xFP, x3, lsl #2 // pointer to first argument in register array 609 add x6, x5, x2, lsl #2 // pointer to last argument in register array 6101: 611 ldr w7, [ip2, #-4]! 612 str w7, [xNEW_FP, ip] 613 sub x2, x2, 1 614 ldr w7, [x6, #-4]! 615 str w7, [x4, ip] 616 sub ip, ip, 4 617 cbnz x2, 1b 6182: 619 .if \is_string_init 620 // Ignore first argument 621 .elseif !\is_static 622 str w1, [xNEW_FP, ip] 623 str w1, [x4, ip] 624 .endif 625 mov xFP, xNEW_FP 626 mov xREFS, xNEW_REFS 627 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 628 START_EXECUTING_INSTRUCTIONS 629.endm 630 631.macro GET_SHORTY dest, is_interface, is_polymorphic, is_custom 632 stp x0, x1, [sp, #-16]! 633 .if \is_polymorphic 634 ldr x0, [sp, #16] 635 mov x1, xPC 636 bl NterpGetShortyFromInvokePolymorphic 637 .elseif \is_custom 638 ldr x0, [sp, #16] 639 mov x1, xPC 640 bl NterpGetShortyFromInvokeCustom 641 .elseif \is_interface 642 ldr x0, [sp, #16] 643 FETCH w1, 1 644 bl NterpGetShortyFromMethodId 645 .else 646 bl NterpGetShorty 647 .endif 648 mov \dest, x0 649 ldp x0, x1, [sp], #16 650.endm 651 652.macro GET_SHORTY_SLOW_PATH dest, is_interface 653 // Save all registers that can hold arguments in the fast path. 654 stp x0, x1, [sp, #-32]! 655 str w2, [sp, #16] 656 str s0, [sp, #20] 657 .if \is_interface 658 ldr x0, [sp, #32] 659 FETCH w1, 1 660 bl NterpGetShortyFromMethodId 661 .else 662 bl NterpGetShorty 663 .endif 664 mov \dest, x0 665 ldr w2, [sp, #16] 666 ldr s0, [sp, #20] 667 ldp x0, x1, [sp], #32 668.endm 669 670// Input: x0 contains the ArtMethod 671// Output: x8 contains the code item 672.macro GET_CODE_ITEM 673 ldr x8, [x0, #ART_METHOD_DATA_OFFSET_64] 674.endm 675 676.macro DO_ENTRY_POINT_CHECK call_compiled_code 677 // On entry, the method is x0, the instance is x1 678 adr x2, ExecuteNterpImpl 679 ldr x3, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64] 680 cmp x2, x3 681 b.ne \call_compiled_code 682.endm 683 684.macro UPDATE_REGISTERS_FOR_STRING_INIT old_value, new_value 685 mov wip, wzr 6861: 687 GET_VREG_OBJECT wip2, wip 688 cmp wip2, \old_value 689 b.ne 2f 690 SET_VREG_OBJECT \new_value, wip 6912: 692 add wip, wip, #1 693 add ip2, xREFS, wip, uxtw #2 694 cmp ip2, xFP 695 b.ne 1b 696.endm 697 698// Puts the next floating point argument into the expected register, 699// fetching values based on a non-range invoke. 700// Uses ip and ip2. 701.macro LOOP_OVER_SHORTY_LOADING_FPS dreg, sreg, inst, shorty, arg_index, finished 7021: // LOOP 703 ldrb wip, [\shorty], #1 // Load next character in shorty, and increment. 704 cbz wip, \finished // if (wip == '\0') goto finished 705 cmp wip, #68 // if (wip == 'D') goto FOUND_DOUBLE 706 b.eq 2f 707 cmp wip, #70 // if (wip == 'F') goto FOUND_FLOAT 708 b.eq 3f 709 lsr \inst, \inst, #4 710 add \arg_index, \arg_index, #1 711 // Handle extra argument in arg array taken by a long. 712 cmp wip, #74 // if (wip != 'J') goto LOOP 713 b.ne 1b 714 lsr \inst, \inst, #4 715 add \arg_index, \arg_index, #1 716 b 1b // goto LOOP 7172: // FOUND_DOUBLE 718 and ip, \inst, #0xf 719 GET_VREG wip, wip 720 lsr \inst, \inst, #4 721 add \arg_index, \arg_index, #1 722 cmp \arg_index, #4 723 b.eq 5f 724 and ip2, \inst, #0xf 725 lsr \inst, \inst, #4 726 add \arg_index, \arg_index, #1 727 b 6f 7285: 729 // TODO: Extract from wINST here and below? (Requires using a different register 730 // in the COMMON_INVOKE_NON_RANGE.) 731 FETCH_B wip2, 0, 1 732 and wip2, wip2, #0xf 7336: 734 GET_VREG wip2, wip2 735 add ip, ip, ip2, lsl #32 736 fmov \dreg, ip 737 b 4f 7383: // FOUND_FLOAT 739 cmp \arg_index, #4 740 b.eq 7f 741 and ip, \inst, #0xf 742 lsr \inst, \inst, #4 743 add \arg_index, \arg_index, #1 744 b 8f 7457: 746 FETCH_B wip, 0, 1 747 and wip, wip, #0xf 7488: 749 GET_VREG \sreg, wip 7504: 751.endm 752 753// Puts the next int/long/object argument in the expected register, 754// fetching values based on a non-range invoke. 755// Uses ip and ip2. 756.macro LOOP_OVER_SHORTY_LOADING_GPRS gpr_reg64, gpr_reg32, inst, shorty, arg_index, finished 7571: // LOOP 758 ldrb wip, [\shorty], #1 // Load next character in shorty, and increment. 759 cbz wip, \finished // if (wip == '\0') goto finished 760 cmp wip, #74 // if (wip == 'J') goto FOUND_LONG 761 b.eq 2f 762 cmp wip, #70 // if (wip == 'F') goto SKIP_FLOAT 763 b.eq 3f 764 cmp wip, #68 // if (wip == 'D') goto SKIP_DOUBLE 765 b.eq 4f 766 cmp \arg_index, #4 767 b.eq 7f 768 and ip, \inst, #0xf 769 lsr \inst, \inst, #4 770 add \arg_index, \arg_index, #1 771 b 8f 7727: 773 FETCH_B wip, 0, 1 774 and wip, wip, #0xf 7758: 776 GET_VREG \gpr_reg32, wip 777 b 5f 7782: // FOUND_LONG 779 and ip, \inst, #0xf 780 GET_VREG wip, wip 781 lsr \inst, \inst, #4 782 add \arg_index, \arg_index, #1 783 cmp \arg_index, #4 784 b.eq 9f 785 and ip2, \inst, #0xf 786 lsr \inst, \inst, #4 787 add \arg_index, \arg_index, #1 788 b 10f 7899: 790 FETCH_B wip2, 0, 1 791 and wip2, wip2, #0xf 79210: 793 GET_VREG wip2, wip2 794 add \gpr_reg64, ip, ip2, lsl #32 795 b 5f 7963: // SKIP_FLOAT 797 lsr \inst, \inst, #4 798 add \arg_index, \arg_index, #1 799 b 1b 8004: // SKIP_DOUBLE 801 lsr \inst, \inst, #4 802 add \arg_index, \arg_index, #1 803 cmp \arg_index, #4 804 b.eq 1b 805 lsr \inst, \inst, #4 806 add \arg_index, \arg_index, #1 807 b 1b 8085: 809.endm 810 811.macro SETUP_RETURN_VALUE shorty 812 ldrb wip, [\shorty] 813 cmp ip, #68 // Test if result type char == 'D'. 814 b.eq 1f 815 cmp ip, #70 // Test if result type char == 'F'. 816 b.ne 2f 817 fmov w0, s0 818 b 2f 8191: 820 fmov x0, d0 8212: 822.endm 823 824.macro COMMON_INVOKE_NON_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0 825 .if \is_polymorphic 826 // We always go to compiled code for polymorphic calls. 827 .elseif \is_custom 828 // We always go to compiled code for custom calls. 829 .else 830 DO_ENTRY_POINT_CHECK .Lcall_compiled_code_\suffix 831 GET_CODE_ITEM 832 .if \is_string_init 833 bl nterp_to_nterp_string_init_non_range 834 .elseif \is_static 835 bl nterp_to_nterp_static_non_range 836 .else 837 bl nterp_to_nterp_instance_non_range 838 .endif 839 b .Ldone_return_\suffix 840 .endif 841 842.Lcall_compiled_code_\suffix: 843 .if \is_polymorphic 844 // No fast path for polymorphic calls. 845 .elseif \is_custom 846 // No fast path for custom calls. 847 .elseif \is_string_init 848 // No fast path for string.init. 849 .else 850 ldr wip, [x0, #ART_METHOD_ACCESS_FLAGS_OFFSET] 851 tbz wip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG_BIT, .Lfast_path_with_few_args_\suffix 852 FETCH_B wip2, 0, 1 853 asr ip, ip2, #4 854 .if \is_static 855 cbz ip, .Linvoke_fast_path_\suffix 856 .else 857 cmp ip, #1 858 b.eq .Linvoke_fast_path_\suffix 859 .endif 860 FETCH w8, 2 861 cmp ip, #2 862 .if \is_static 863 b.lt .Lone_arg_fast_path_\suffix 864 .endif 865 b.eq .Ltwo_args_fast_path_\suffix 866 cmp ip, #4 867 b.lt .Lthree_args_fast_path_\suffix 868 b.eq .Lfour_args_fast_path_\suffix 869 870 and ip, ip2, #15 871 GET_VREG w5, wip 872.Lfour_args_fast_path_\suffix: 873 asr ip, x8, #12 874 GET_VREG w4, wip 875.Lthree_args_fast_path_\suffix: 876 ubfx ip, x8, #8, #4 877 GET_VREG w3, wip 878.Ltwo_args_fast_path_\suffix: 879 ubfx ip, x8, #4, #4 880 GET_VREG w2, wip 881.Lone_arg_fast_path_\suffix: 882 .if \is_static 883 and ip, x8, #0xf 884 GET_VREG w1, wip 885 .else 886 // First argument already in w1. 887 .endif 888.Linvoke_fast_path_\suffix: 889 .if \is_interface 890 // Setup hidden argument. 891 mov ip2, x26 892 .endif 893 ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64] 894 blr lr 895 FETCH_ADVANCE_INST 3 896 GET_INST_OPCODE ip 897 GOTO_OPCODE ip 898 899.Lfast_path_with_few_args_\suffix: 900 // Fast path when we have zero or one argument (modulo 'this'). If there 901 // is one argument, we can put it in both floating point and core register. 902 FETCH_B w2, 0, 1 903 .if \is_static 904 cmp w2, #(2 << 4) 905 .else 906 cmp w2, #(3 << 4) 907 .endif 908 b.ge .Lget_shorty_\suffix 909 .if \is_static 910 tbz w2, #4, .Linvoke_with_few_args_\suffix 911 .else 912 tbnz w2, #4, .Linvoke_with_few_args_\suffix 913 .endif 914 FETCH w2, 2 915 .if \is_static 916 and w2, w2, #0xf // dex register of first argument 917 GET_VREG w1, w2 918 fmov s0, w1 919 .else 920 ubfx x2, x2, #4, #4 // dex register of second argument 921 GET_VREG w2, w2 922 fmov s0, w2 923 .endif 924.Linvoke_with_few_args_\suffix: 925 // Check if the next instruction is move-result or move-result-wide. 926 // If it is, we fetch the shorty and jump to the regular invocation. 927 FETCH w27, 3 928 and ip, x27, #0xfe 929 cmp ip, #0x0a 930 b.eq .Lget_shorty_and_invoke_\suffix 931 .if \is_interface 932 // Setup hidden argument. 933 mov ip2, x26 934 .endif 935 ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64] 936 blr lr 937 # TODO: Use some other register for shorty and prefetch the instruction directly to wINST. 938 mov xINST, x27 939 ADVANCE 3 940 GET_INST_OPCODE ip 941 GOTO_OPCODE ip 942.Lget_shorty_and_invoke_\suffix: 943 GET_SHORTY_SLOW_PATH xINST, \is_interface 944 b .Lgpr_setup_finished_\suffix 945 .endif 946 947.Lget_shorty_\suffix: 948 GET_SHORTY xINST, \is_interface, \is_polymorphic, \is_custom 949 // From this point: 950 // - xINST contains shorty (in callee-save to switch over return value after call). 951 // - x0 contains method 952 // - x1 contains 'this' pointer for instance method. 953 // - for interface calls, x26 contains the interface method. 954 add x9, xINST, #1 // shorty + 1 ; ie skip return arg character 955 FETCH w11, 2 // arguments 956 .if \is_string_init 957 lsr x11, x11, #4 958 mov x10, #1 // ignore first argument 959 .elseif \is_static 960 mov x10, xzr // arg_index 961 .else 962 lsr x11, x11, #4 963 mov x10, #1 // ignore first argument 964 .endif 965 LOOP_OVER_SHORTY_LOADING_FPS d0, s0, x11, x9, x10, .Lxmm_setup_finished_\suffix 966 LOOP_OVER_SHORTY_LOADING_FPS d1, s1, x11, x9, x10, .Lxmm_setup_finished_\suffix 967 LOOP_OVER_SHORTY_LOADING_FPS d2, s2, x11, x9, x10, .Lxmm_setup_finished_\suffix 968 LOOP_OVER_SHORTY_LOADING_FPS d3, s3, x11, x9, x10, .Lxmm_setup_finished_\suffix 969 LOOP_OVER_SHORTY_LOADING_FPS d4, s4, x11, x9, x10, .Lxmm_setup_finished_\suffix 970.Lxmm_setup_finished_\suffix: 971 add x9, xINST, #1 // shorty + 1 ; ie skip return arg character 972 FETCH w11, 2 // arguments 973 .if \is_string_init 974 lsr x11, x11, #4 975 mov x10, #1 // ignore first argument 976 LOOP_OVER_SHORTY_LOADING_GPRS x1, w1, x11, x9, x10, .Lgpr_setup_finished_\suffix 977 .elseif \is_static 978 mov x10, xzr // arg_index 979 LOOP_OVER_SHORTY_LOADING_GPRS x1, w1, x11, x9, x10, .Lgpr_setup_finished_\suffix 980 .else 981 lsr x11, x11, #4 982 mov x10, #1 // ignore first argument 983 .endif 984 LOOP_OVER_SHORTY_LOADING_GPRS x2, w2, x11, x9, x10, .Lgpr_setup_finished_\suffix 985 LOOP_OVER_SHORTY_LOADING_GPRS x3, w3, x11, x9, x10, .Lgpr_setup_finished_\suffix 986 LOOP_OVER_SHORTY_LOADING_GPRS x4, w4, x11, x9, x10, .Lgpr_setup_finished_\suffix 987 LOOP_OVER_SHORTY_LOADING_GPRS x5, w5, x11, x9, x10, .Lgpr_setup_finished_\suffix 988.Lgpr_setup_finished_\suffix: 989 .if \is_polymorphic 990 bl art_quick_invoke_polymorphic 991 .elseif \is_custom 992 bl art_quick_invoke_custom 993 .else 994 .if \is_interface 995 // Setup hidden argument. 996 mov ip2, x26 997 .endif 998 ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64] 999 blr lr 1000 .endif 1001 SETUP_RETURN_VALUE xINST 1002.Ldone_return_\suffix: 1003 /* resume execution of caller */ 1004 .if \is_string_init 1005 FETCH w11, 2 // arguments 1006 and x11, x11, #0xf 1007 GET_VREG w1, w11 1008 UPDATE_REGISTERS_FOR_STRING_INIT w1, w0 1009 .endif 1010 1011 .if \is_polymorphic 1012 FETCH_ADVANCE_INST 4 1013 .else 1014 FETCH_ADVANCE_INST 3 1015 .endif 1016 GET_INST_OPCODE ip 1017 GOTO_OPCODE ip 1018.endm 1019 1020// Puts the next floating point argument into the expected register, 1021// fetching values based on a range invoke. 1022// Uses ip as temporary. 1023.macro LOOP_RANGE_OVER_SHORTY_LOADING_FPS dreg, sreg, shorty, arg_index, stack_index, finished 10241: // LOOP 1025 ldrb wip, [\shorty], #1 // Load next character in shorty, and increment. 1026 cbz wip, \finished // if (wip == '\0') goto finished 1027 cmp wip, #68 // if (wip == 'D') goto FOUND_DOUBLE 1028 b.eq 2f 1029 cmp wip, #70 // if (wip == 'F') goto FOUND_FLOAT 1030 b.eq 3f 1031 add \arg_index, \arg_index, #1 1032 add \stack_index, \stack_index, #1 1033 // Handle extra argument in arg array taken by a long. 1034 cmp wip, #74 // if (wip != 'J') goto LOOP 1035 b.ne 1b 1036 add \arg_index, \arg_index, #1 1037 add \stack_index, \stack_index, #1 1038 b 1b // goto LOOP 10392: // FOUND_DOUBLE 1040 GET_VREG_DOUBLE \dreg, \arg_index 1041 add \arg_index, \arg_index, #2 1042 add \stack_index, \stack_index, #2 1043 b 4f 10443: // FOUND_FLOAT 1045 GET_VREG \sreg, \arg_index 1046 add \arg_index, \arg_index, #1 1047 add \stack_index, \stack_index, #1 10484: 1049.endm 1050 1051// Puts the next floating point argument into the expected stack slot, 1052// fetching values based on a range invoke. 1053// Uses ip as temporary. 1054// 1055// TODO: We could just copy all the vregs to the stack slots in a simple loop 1056// without looking at the shorty at all. (We could also drop 1057// the "stack_index" from the macros for loading registers.) We could also do 1058// that conditionally if argument word count > 6; otherwise we know that all 1059// args fit into registers. 1060.macro LOOP_RANGE_OVER_FPs shorty, arg_index, stack_index, finished 10611: // LOOP 1062 ldrb wip, [\shorty], #1 // Load next character in shorty, and increment. 1063 cbz wip, \finished // if (wip == '\0') goto finished 1064 cmp wip, #68 // if (wip == 'D') goto FOUND_DOUBLE 1065 b.eq 2f 1066 cmp wip, #70 // if (wip == 'F') goto FOUND_FLOAT 1067 b.eq 3f 1068 add \arg_index, \arg_index, #1 1069 add \stack_index, \stack_index, #1 1070 // Handle extra argument in arg array taken by a long. 1071 cmp wip, #74 // if (wip != 'J') goto LOOP 1072 b.ne 1b 1073 add \arg_index, \arg_index, #1 1074 add \stack_index, \stack_index, #1 1075 b 1b // goto LOOP 10762: // FOUND_DOUBLE 1077 GET_VREG_WIDE ip, \arg_index 1078 add ip2, sp, \stack_index, uxtw #2 1079 str ip, [ip2] 1080 add \arg_index, \arg_index, #2 1081 add \stack_index, \stack_index, #2 1082 b 1b 10833: // FOUND_FLOAT 1084 GET_VREG wip, \arg_index 1085 str wip, [sp, \stack_index, uxtw #2] 1086 add \arg_index, \arg_index, #1 1087 add \stack_index, \stack_index, #1 1088 b 1b 1089.endm 1090 1091// Puts the next int/long/object argument in the expected register, 1092// fetching values based on a range invoke. 1093// Uses ip as temporary. 1094.macro LOOP_RANGE_OVER_SHORTY_LOADING_GPRS reg64, reg32, shorty, arg_index, stack_index, finished 10951: // LOOP 1096 ldrb wip, [\shorty], #1 // Load next character in shorty, and increment. 1097 cbz wip, \finished // if (wip == '\0') goto finished 1098 cmp wip, #74 // if (wip == 'J') goto FOUND_LONG 1099 b.eq 2f 1100 cmp wip, #70 // if (wip == 'F') goto SKIP_FLOAT 1101 b.eq 3f 1102 cmp wip, #68 // if (wip == 'D') goto SKIP_DOUBLE 1103 b.eq 4f 1104 GET_VREG \reg32, \arg_index 1105 add \arg_index, \arg_index, #1 1106 add \stack_index, \stack_index, #1 1107 b 5f 11082: // FOUND_LONG 1109 GET_VREG_WIDE \reg64, \arg_index 1110 add \arg_index, \arg_index, #2 1111 add \stack_index, \stack_index, #2 1112 b 5f 11133: // SKIP_FLOAT 1114 add \arg_index, \arg_index, #1 1115 add \stack_index, \stack_index, #1 1116 b 1b 11174: // SKIP_DOUBLE 1118 add \arg_index, \arg_index, #2 1119 add \stack_index, \stack_index, #2 1120 b 1b 11215: 1122.endm 1123 1124// Puts the next int/long/object argument in the expected stack slot, 1125// fetching values based on a range invoke. 1126// Uses ip as temporary. 1127.macro LOOP_RANGE_OVER_INTs shorty, arg_index, stack_index, finished 11281: // LOOP 1129 ldrb wip, [\shorty], #1 // Load next character in shorty, and increment. 1130 cbz wip, \finished // if (wip == '\0') goto finished 1131 cmp wip, #74 // if (wip == 'J') goto FOUND_LONG 1132 b.eq 2f 1133 cmp wip, #70 // if (wip == 'F') goto SKIP_FLOAT 1134 b.eq 3f 1135 cmp wip, #68 // if (wip == 'D') goto SKIP_DOUBLE 1136 b.eq 4f 1137 GET_VREG wip, \arg_index 1138 str wip, [sp, \stack_index, uxtw #2] 1139 add \arg_index, \arg_index, #1 1140 add \stack_index, \stack_index, #1 1141 b 1b 11422: // FOUND_LONG 1143 GET_VREG_WIDE ip, \arg_index 1144 add ip2, sp, \stack_index, uxtw #2 1145 str ip, [ip2] 1146 add \arg_index, \arg_index, #2 1147 add \stack_index, \stack_index, #2 1148 b 1b 11493: // SKIP_FLOAT 1150 add \arg_index, \arg_index, #1 1151 add \stack_index, \stack_index, #1 1152 b 1b 11534: // SKIP_DOUBLE 1154 add \arg_index, \arg_index, #2 1155 add \stack_index, \stack_index, #2 1156 b 1b 1157.endm 1158 1159.macro COMMON_INVOKE_RANGE is_static=0, is_interface=0, suffix="", is_string_init=0, is_polymorphic=0, is_custom=0 1160 .if \is_polymorphic 1161 // We always go to compiled code for polymorphic calls. 1162 .elseif \is_custom 1163 // We always go to compiled code for custom calls. 1164 .else 1165 DO_ENTRY_POINT_CHECK .Lcall_compiled_code_range_\suffix 1166 GET_CODE_ITEM 1167 .if \is_string_init 1168 bl nterp_to_nterp_string_init_range 1169 .elseif \is_static 1170 bl nterp_to_nterp_static_range 1171 .else 1172 bl nterp_to_nterp_instance_range 1173 .endif 1174 b .Ldone_return_range_\suffix 1175 .endif 1176 1177.Lcall_compiled_code_range_\suffix: 1178 .if \is_polymorphic 1179 // No fast path for polymorphic calls. 1180 .elseif \is_custom 1181 // No fast path for custom calls. 1182 .elseif \is_string_init 1183 // No fast path for string.init. 1184 .else 1185 ldr wip, [x0, #ART_METHOD_ACCESS_FLAGS_OFFSET] 1186 tbz wip, #ART_METHOD_NTERP_INVOKE_FAST_PATH_FLAG_BIT, .Lfast_path_with_few_args_range_\suffix 1187 FETCH_B wip2, 0, 1 // Number of arguments 1188 .if \is_static 1189 cbz ip2, .Linvoke_fast_path_range_\suffix 1190 .else 1191 cmp ip2, #1 1192 b.eq .Linvoke_fast_path_range_\suffix 1193 .endif 1194 FETCH wip, 2 // dex register of first argument 1195 add x8, xFP, wip, uxtw #2 // location of first dex register value 1196 cmp ip2, #2 1197 .if \is_static 1198 b.lt .Lone_arg_fast_path_range_\suffix 1199 .endif 1200 b.eq .Ltwo_args_fast_path_range_\suffix 1201 cmp ip2, #4 1202 b.lt .Lthree_args_fast_path_range_\suffix 1203 b.eq .Lfour_args_fast_path_range_\suffix 1204 cmp ip2, #6 1205 b.lt .Lfive_args_fast_path_range_\suffix 1206 b.eq .Lsix_args_fast_path_range_\suffix 1207 cmp ip2, #7 1208 b.eq .Lseven_args_fast_path_range_\suffix 1209 // Setup x8 to point to the stack location of parameters we do not need 1210 // to put parameters in. 1211 add x9, sp, #8 // Add space for the ArtMethod 1212 1213.Lloop_over_fast_path_range_\suffix: 1214 sub ip2, ip2, #1 1215 ldr wip, [x8, ip2, lsl #2] 1216 str wip, [x9, ip2, lsl #2] 1217 cmp ip2, #7 1218 b.ne .Lloop_over_fast_path_range_\suffix 1219 1220.Lseven_args_fast_path_range_\suffix: 1221 ldr w7, [x8, #24] 1222.Lsix_args_fast_path_range_\suffix: 1223 ldr w6, [x8, #20] 1224.Lfive_args_fast_path_range_\suffix: 1225 ldr w5, [x8, #16] 1226.Lfour_args_fast_path_range_\suffix: 1227 ldr w4, [x8, #12] 1228.Lthree_args_fast_path_range_\suffix: 1229 ldr w3, [x8, #8] 1230.Ltwo_args_fast_path_range_\suffix: 1231 ldr w2, [x8, #4] 1232.Lone_arg_fast_path_range_\suffix: 1233 .if \is_static 1234 ldr w1, [x8, #0] 1235 .else 1236 // First argument already in w1. 1237 .endif 1238.Linvoke_fast_path_range_\suffix: 1239 .if \is_interface 1240 // Setup hidden argument. 1241 mov ip2, x26 1242 .endif 1243 ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64] 1244 blr lr 1245 FETCH_ADVANCE_INST 3 1246 GET_INST_OPCODE ip 1247 GOTO_OPCODE ip 1248 1249.Lfast_path_with_few_args_range_\suffix: 1250 // Fast path when we have zero or one argument (modulo 'this'). If there 1251 // is one argument, we can put it in both floating point and core register. 1252 FETCH_B w2, 0, 1 // number of arguments 1253 .if \is_static 1254 cmp w2, #1 1255 .else 1256 cmp w2, #2 1257 .endif 1258 b.lt .Linvoke_with_few_args_range_\suffix 1259 b.ne .Lget_shorty_range_\suffix 1260 FETCH w3, 2 // dex register of first argument 1261 .if \is_static 1262 GET_VREG w1, w3 1263 fmov s0, w1 1264 .else 1265 add w3, w3, #1 // Add 1 for next argument 1266 GET_VREG w2, w3 1267 fmov s0, w2 1268 .endif 1269.Linvoke_with_few_args_range_\suffix: 1270 // Check if the next instruction is move-result or move-result-wide. 1271 // If it is, we fetch the shorty and jump to the regular invocation. 1272 FETCH w27, 3 1273 and ip, x27, #0xfe 1274 cmp ip, #0x0a 1275 b.eq .Lget_shorty_and_invoke_range_\suffix 1276 .if \is_interface 1277 // Setup hidden argument. 1278 mov ip2, x26 1279 .endif 1280 ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64] 1281 blr lr 1282 mov xINST, x27 1283 ADVANCE 3 1284 GET_INST_OPCODE ip 1285 GOTO_OPCODE ip 1286.Lget_shorty_and_invoke_range_\suffix: 1287 GET_SHORTY_SLOW_PATH xINST, \is_interface 1288 b .Lgpr_setup_finished_range_\suffix 1289 .endif 1290 1291.Lget_shorty_range_\suffix: 1292 GET_SHORTY xINST, \is_interface, \is_polymorphic, \is_custom 1293 // From this point: 1294 // - xINST contains shorty (in callee-save to switch over return value after call). 1295 // - x0 contains method 1296 // - x1 contains 'this' pointer for instance method. 1297 // - for interface calls, x26 contains the interface method. 1298 add x9, xINST, #1 // shorty + 1 ; ie skip return arg character 1299 FETCH w10, 2 // arguments 1300 .if \is_string_init 1301 add x10, x10, #1 // arg start index 1302 mov x11, #1 // index in stack 1303 .elseif \is_static 1304 mov x11, xzr // index in stack 1305 .else 1306 add x10, x10, #1 // arg start index 1307 mov x11, #1 // index in stack 1308 .endif 1309 LOOP_RANGE_OVER_SHORTY_LOADING_FPS d0, s0, x9, w10, w11, .Lxmm_setup_finished_range_\suffix 1310 LOOP_RANGE_OVER_SHORTY_LOADING_FPS d1, s1, x9, w10, w11, .Lxmm_setup_finished_range_\suffix 1311 LOOP_RANGE_OVER_SHORTY_LOADING_FPS d2, s2, x9, w10, w11, .Lxmm_setup_finished_range_\suffix 1312 LOOP_RANGE_OVER_SHORTY_LOADING_FPS d3, s3, x9, w10, w11, .Lxmm_setup_finished_range_\suffix 1313 LOOP_RANGE_OVER_SHORTY_LOADING_FPS d4, s4, x9, w10, w11, .Lxmm_setup_finished_range_\suffix 1314 LOOP_RANGE_OVER_SHORTY_LOADING_FPS d5, s5, x9, w10, w11, .Lxmm_setup_finished_range_\suffix 1315 LOOP_RANGE_OVER_SHORTY_LOADING_FPS d6, s6, x9, w10, w11, .Lxmm_setup_finished_range_\suffix 1316 LOOP_RANGE_OVER_SHORTY_LOADING_FPS d7, s7, x9, w10, w11, .Lxmm_setup_finished_range_\suffix 1317 // Store in the outs array (stored above the ArtMethod in the stack) 1318 add x11, x11, #2 // Add two words for the ArtMethod stored before the outs. 1319 LOOP_RANGE_OVER_FPs x9, w10, w11, .Lxmm_setup_finished_range_\suffix 1320.Lxmm_setup_finished_range_\suffix: 1321 add x9, xINST, #1 // shorty + 1 ; ie skip return arg character 1322 FETCH w10, 2 // arguments 1323 .if \is_string_init 1324 add x10, x10, #1 // arg start index 1325 mov x11, #1 // index in stack 1326 LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x1, w1, x9, w10, w11, .Lgpr_setup_finished_range_\suffix 1327 .elseif \is_static 1328 mov x11, xzr // index in stack 1329 LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x1, w1, x9, w10, w11 .Lgpr_setup_finished_range_\suffix 1330 .else 1331 add x10, x10, #1 // arg start index 1332 mov x11, #1 // index in stack 1333 .endif 1334 LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x2, w2, x9, w10, w11, .Lgpr_setup_finished_range_\suffix 1335 LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x3, w3, x9, w10, w11, .Lgpr_setup_finished_range_\suffix 1336 LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x4, w4, x9, w10, w11, .Lgpr_setup_finished_range_\suffix 1337 LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x5, w5, x9, w10, w11, .Lgpr_setup_finished_range_\suffix 1338 LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x6, w6, x9, w10, w11, .Lgpr_setup_finished_range_\suffix 1339 LOOP_RANGE_OVER_SHORTY_LOADING_GPRS x7, w7, x9, w10, w11, .Lgpr_setup_finished_range_\suffix 1340 // Store in the outs array (stored above the ArtMethod in the stack) 1341 add x11, x11, #2 // Add two words for the ArtMethod stored before the outs. 1342 LOOP_RANGE_OVER_INTs x9, w10, w11, .Lgpr_setup_finished_range_\suffix 1343.Lgpr_setup_finished_range_\suffix: 1344 .if \is_polymorphic 1345 bl art_quick_invoke_polymorphic 1346 .elseif \is_custom 1347 bl art_quick_invoke_custom 1348 .else 1349 .if \is_interface 1350 // Setup hidden argument. 1351 mov ip2, x26 1352 .endif 1353 ldr lr, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64] 1354 blr lr 1355 .endif 1356 SETUP_RETURN_VALUE xINST 1357.Ldone_return_range_\suffix: 1358 /* resume execution of caller */ 1359 .if \is_string_init 1360 FETCH w11, 2 // arguments 1361 GET_VREG w1, w11 1362 UPDATE_REGISTERS_FOR_STRING_INIT w1, w0 1363 .endif 1364 1365 .if \is_polymorphic 1366 FETCH_ADVANCE_INST 4 1367 .else 1368 FETCH_ADVANCE_INST 3 1369 .endif 1370 GET_INST_OPCODE ip 1371 GOTO_OPCODE ip 1372.endm 1373 1374.macro POISON_HEAP_REF_IF_OBJECT is_object, rRef 1375 .if \is_object 1376 POISON_HEAP_REF \rRef 1377 .endif 1378.endm 1379 1380.macro WRITE_BARRIER_IF_OBJECT is_object, value, holder, label 1381 .if \is_object 1382 cbz \value, \label 1383 ldr ip, [xSELF, #THREAD_CARD_TABLE_OFFSET] 1384 lsr wip2, \holder, #CARD_TABLE_CARD_SHIFT 1385 strb wip, [ip, ip2] 1386\label: 1387 .endif 1388.endm 1389 1390// Puts the next int/long/object parameter passed in physical register 1391// in the expected dex register array entry, and in case of object in the 1392// expected reference array entry. 1393.macro LOOP_OVER_SHORTY_STORING_GPRS gpr_64, gpr_32, shorty, arg_offset, regs, refs, finished 13941: // LOOP 1395 ldrb wip, [\shorty], #1 // Load next character in shorty, and increment. 1396 cbz wip, \finished // if (wip == '\0') goto finished 1397 cmp wip, #74 // if (wip == 'J') goto FOUND_LONG 1398 b.eq 2f 1399 cmp wip, #70 // if (wip == 'F') goto SKIP_FLOAT 1400 b.eq 3f 1401 cmp wip, #68 // if (wip == 'D') goto SKIP_DOUBLE 1402 b.eq 4f 1403 str \gpr_32, [\regs, \arg_offset] 1404 cmp wip, #76 // if (wip != 'L') goto NOT_REFERENCE 1405 b.ne 6f 1406 str \gpr_32, [\refs, \arg_offset] 14076: // NOT_REFERENCE 1408 add \arg_offset, \arg_offset, #4 1409 b 5f 14102: // FOUND_LONG 1411 str \gpr_64, [\regs, \arg_offset] 1412 add \arg_offset, \arg_offset, #8 1413 b 5f 14143: // SKIP_FLOAT 1415 add \arg_offset, \arg_offset, #4 1416 b 1b 14174: // SKIP_DOUBLE 1418 add \arg_offset, \arg_offset, #8 1419 b 1b 14205: 1421.endm 1422 1423// Puts the next floating point parameter passed in physical register 1424// in the expected dex register array entry. 1425// Uses ip as temporary. 1426.macro LOOP_OVER_SHORTY_STORING_FPS dreg, sreg, shorty, arg_offset, fp, finished 14271: // LOOP 1428 ldrb wip, [\shorty], #1 // Load next character in shorty, and increment. 1429 cbz wip, \finished // if (wip == '\0') goto finished 1430 cmp wip, #68 // if (wip == 'D') goto FOUND_DOUBLE 1431 b.eq 2f 1432 cmp wip, #70 // if (wip == 'F') goto FOUND_FLOAT 1433 b.eq 3f 1434 add \arg_offset, \arg_offset, #4 1435 // Handle extra argument in arg array taken by a long. 1436 cmp wip, #74 // if (wip != 'J') goto LOOP 1437 b.ne 1b 1438 add \arg_offset, \arg_offset, #4 1439 b 1b // goto LOOP 14402: // FOUND_DOUBLE 1441 str \dreg, [\fp, \arg_offset] 1442 add \arg_offset, \arg_offset, #8 1443 b 4f 14443: // FOUND_FLOAT 1445 str \sreg, [\fp, \arg_offset] 1446 add \arg_offset, \arg_offset, #4 14474: 1448.endm 1449 1450// Puts the next floating point parameter passed in stack 1451// in the expected dex register array entry. 1452// Uses ip as temporary. 1453// 1454// TODO: Or we could just spill regs to the reserved slots in the caller's 1455// frame and copy all regs in a simple loop. This time, however, we would 1456// need to look at the shorty anyway to look for the references. 1457// (The trade-off is different for passing arguments and receiving them.) 1458.macro LOOP_OVER_FPs shorty, arg_offset, regs, stack_ptr, finished 14591: // LOOP 1460 ldrb wip, [\shorty], #1 // Load next character in shorty, and increment. 1461 cbz wip, \finished // if (wip == '\0') goto finished 1462 cmp wip, #68 // if (wip == 'D') goto FOUND_DOUBLE 1463 b.eq 2f 1464 cmp wip, #70 // if (wip == 'F') goto FOUND_FLOAT 1465 b.eq 3f 1466 add \arg_offset, \arg_offset, #4 1467 // Handle extra argument in arg array taken by a long. 1468 cmp wip, #74 // if (wip != 'J') goto LOOP 1469 b.ne 1b 1470 add \arg_offset, \arg_offset, #4 1471 b 1b // goto LOOP 14722: // FOUND_DOUBLE 1473 add ip, \stack_ptr, \arg_offset 1474 ldr ip, [ip, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK] 1475 str ip, [\regs, \arg_offset] 1476 add \arg_offset, \arg_offset, #8 1477 b 1b 14783: // FOUND_FLOAT 1479 add ip, \stack_ptr, \arg_offset 1480 ldr wip, [ip, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK] 1481 str wip, [\regs, \arg_offset] 1482 add \arg_offset, \arg_offset, #4 1483 b 1b 1484.endm 1485 1486// Puts the next int/long/object parameter passed in stack 1487// in the expected dex register array entry, and in case of object in the 1488// expected reference array entry. 1489// Uses ip and ip2 as temporary. 1490.macro LOOP_OVER_INTs shorty, arg_offset, regs, refs, stack_ptr, finished 14911: // LOOP 1492 ldrb wip, [\shorty], #1 // Load next character in shorty, and increment. 1493 cbz wip, \finished // if (wip == '\0') goto finished 1494 cmp wip, #74 // if (wip == 'J') goto FOUND_LONG 1495 b.eq 2f 1496 cmp wip, #70 // if (wip == 'F') goto SKIP_FLOAT 1497 b.eq 3f 1498 cmp wip, #68 // if (wip == 'D') goto SKIP_DOUBLE 1499 b.eq 4f 1500 add ip2, \stack_ptr, \arg_offset 1501 ldr wip2, [ip2, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK] 1502 str wip2, [\regs, \arg_offset] 1503 cmp wip, #76 // if (wip != 'L') goto loop 1504 b.ne 3f 1505 str wip2, [\refs, \arg_offset] 1506 add \arg_offset, \arg_offset, #4 1507 b 1b 15082: // FOUND_LONG 1509 add ip, \stack_ptr, \arg_offset 1510 ldr ip, [ip, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK] 1511 str ip, [\regs, \arg_offset] 1512 add \arg_offset, \arg_offset, #8 1513 b 1b 15143: // SKIP_FLOAT 1515 add \arg_offset, \arg_offset, #4 1516 b 1b 15174: // SKIP_DOUBLE 1518 add \arg_offset, \arg_offset, #8 1519 b 1b 1520.endm 1521 1522.macro SETUP_REFERENCE_PARAMETER_IN_GPR gpr32, regs, refs, ins, arg_offset, finished 1523 str \gpr32, [\regs, \arg_offset] 1524 sub \ins, \ins, #1 1525 str \gpr32, [\refs, \arg_offset] 1526 add \arg_offset, \arg_offset, #4 1527 cbz \ins, \finished 1528.endm 1529 1530// Uses ip2 as temporary. 1531.macro SETUP_REFERENCE_PARAMETERS_IN_STACK regs, refs, ins, stack_ptr, arg_offset 15321: 1533 ldr wip2, [\stack_ptr, \arg_offset] 1534 sub \ins, \ins, #1 1535 str wip2, [\regs, \arg_offset] 1536 str wip2, [\refs, \arg_offset] 1537 add \arg_offset, \arg_offset, #4 1538 cbnz \ins, 1b 1539.endm 1540 1541.macro CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot, if_not_hot 1542 ldr wip, [x0, #ART_METHOD_ACCESS_FLAGS_OFFSET] 1543 tbz wip, #ART_METHOD_IS_MEMORY_SHARED_FLAG_BIT, \if_hot 1544 // Intrinsics are always in the boot image and considered hot. 1545 tbnz wip, #ART_METHOD_IS_INTRINSIC_FLAG_BIT, \if_hot 1546 ldr wip, [xSELF, #THREAD_SHARED_METHOD_HOTNESS_OFFSET] 1547 cbz wip, \if_hot 1548 add wip, wip, #-1 1549 str wip, [xSELF, #THREAD_SHARED_METHOD_HOTNESS_OFFSET] 1550 b \if_not_hot 1551.endm 1552 1553.macro DO_SUSPEND_CHECK continue_label 1554 ldr wip, [xSELF, #THREAD_FLAGS_OFFSET] 1555 tst wip, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST 1556 b.eq \continue_label 1557 EXPORT_PC 1558 bl art_quick_test_suspend 1559.endm 1560 1561/* 1562 * ArtMethod entry point. 1563 * 1564 * On entry: 1565 * x0 ArtMethod* callee 1566 * rest method parameters 1567 */ 1568 1569OAT_ENTRY ExecuteNterpWithClinitImpl 1570 .cfi_startproc 1571 // For simplicity, we don't do a read barrier here, but instead rely 1572 // on art_quick_resolution_trampoline to always have a suspend point before 1573 // calling back here. 1574 ldr wip, [x0, #ART_METHOD_DECLARING_CLASS_OFFSET] 1575 ldr wip2, [ip, #MIRROR_CLASS_STATUS_OFFSET] 1576 lsr wip2, wip2, #MIRROR_CLASS_STATUS_SHIFT 1577 cmp wip2, #MIRROR_CLASS_STATUS_VISIBLY_INITIALIZED 1578 b.hs ExecuteNterpImpl 1579 cmp wip2, #MIRROR_CLASS_STATUS_INITIALIZED 1580 b.lo .Linitializing_check 1581 dmb ish 1582 b ExecuteNterpImpl 1583.Linitializing_check: 1584 cmp wip2, #MIRROR_CLASS_STATUS_INITIALIZING 1585 b.lo .Lresolution_trampoline 1586 ldr wip2, [ip, #MIRROR_CLASS_CLINIT_THREAD_ID_OFFSET] 1587 ldr wip, [xSELF, #THREAD_TID_OFFSET] 1588 cmp wip, wip2 1589 b.eq ExecuteNterpImpl 1590.Lresolution_trampoline: 1591 b art_quick_resolution_trampoline 1592 .cfi_endproc 1593 .type EndExecuteNterpWithClinitImpl, #function 1594 .hidden EndExecuteNterpWithClinitImpl 1595 .global EndExecuteNterpWithClinitImpl 1596EndExecuteNterpWithClinitImpl: 1597 1598OAT_ENTRY ExecuteNterpImpl 1599 .cfi_startproc 1600 sub x16, sp, #STACK_OVERFLOW_RESERVED_BYTES 1601 ldr wzr, [x16] 1602 /* Spill callee save regs */ 1603 SPILL_ALL_CALLEE_SAVES 1604 1605 ldr xPC, [x0, #ART_METHOD_DATA_OFFSET_64] 1606 // Setup the stack for executing the method. 1607 SETUP_STACK_FRAME xPC, xREFS, xFP, CFI_REFS, load_ins=1 1608 1609 // Setup the parameters 1610 cbz w15, .Lxmm_setup_finished 1611 1612 sub ip2, ip, x15 1613 ldr w26, [x0, #ART_METHOD_ACCESS_FLAGS_OFFSET] 1614 lsl x27, ip2, #2 // x27 is now the offset for inputs into the registers array. 1615 1616 tbz w26, #ART_METHOD_NTERP_ENTRY_POINT_FAST_PATH_FLAG_BIT, .Lsetup_slow_path 1617 // Setup pointer to inputs in FP and pointer to inputs in REFS 1618 add x10, xFP, x27 1619 add x11, xREFS, x27 1620 mov x12, #0 1621 SETUP_REFERENCE_PARAMETER_IN_GPR w1, x10, x11, w15, x12, .Lxmm_setup_finished 1622 SETUP_REFERENCE_PARAMETER_IN_GPR w2, x10, x11, w15, x12, .Lxmm_setup_finished 1623 SETUP_REFERENCE_PARAMETER_IN_GPR w3, x10, x11, w15, x12, .Lxmm_setup_finished 1624 SETUP_REFERENCE_PARAMETER_IN_GPR w4, x10, x11, w15, x12, .Lxmm_setup_finished 1625 SETUP_REFERENCE_PARAMETER_IN_GPR w5, x10, x11, w15, x12, .Lxmm_setup_finished 1626 SETUP_REFERENCE_PARAMETER_IN_GPR w6, x10, x11, w15, x12, .Lxmm_setup_finished 1627 SETUP_REFERENCE_PARAMETER_IN_GPR w7, x10, x11, w15, x12, .Lxmm_setup_finished 1628 add x28, x28, #OFFSET_TO_FIRST_ARGUMENT_IN_STACK 1629 SETUP_REFERENCE_PARAMETERS_IN_STACK x10, x11, w15, x28, x12 1630 b .Lxmm_setup_finished 1631 1632.Lsetup_slow_path: 1633 // If the method is not static and there is one argument ('this'), we don't need to fetch the 1634 // shorty. 1635 tbnz w26, #ART_METHOD_IS_STATIC_FLAG_BIT, .Lsetup_with_shorty 1636 str w1, [xFP, x27] 1637 str w1, [xREFS, x27] 1638 cmp w15, #1 1639 b.eq .Lxmm_setup_finished 1640 1641.Lsetup_with_shorty: 1642 // TODO: Get shorty in a better way and remove below 1643 SPILL_ALL_ARGUMENTS 1644 bl NterpGetShorty 1645 // Save shorty in callee-save xIBASE. 1646 mov xIBASE, x0 1647 RESTORE_ALL_ARGUMENTS 1648 1649 // Setup pointer to inputs in FP and pointer to inputs in REFS 1650 add x10, xFP, x27 1651 add x11, xREFS, x27 1652 mov x12, #0 1653 1654 add x9, xIBASE, #1 // shorty + 1 ; ie skip return arg character 1655 tbnz w26, #ART_METHOD_IS_STATIC_FLAG_BIT, .Lhandle_static_method 1656 add x10, x10, #4 1657 add x11, x11, #4 1658 add x28, x28, #4 1659 b .Lcontinue_setup_gprs 1660.Lhandle_static_method: 1661 LOOP_OVER_SHORTY_STORING_GPRS x1, w1, x9, x12, x10, x11, .Lgpr_setup_finished 1662.Lcontinue_setup_gprs: 1663 LOOP_OVER_SHORTY_STORING_GPRS x2, w2, x9, x12, x10, x11, .Lgpr_setup_finished 1664 LOOP_OVER_SHORTY_STORING_GPRS x3, w3, x9, x12, x10, x11, .Lgpr_setup_finished 1665 LOOP_OVER_SHORTY_STORING_GPRS x4, w4, x9, x12, x10, x11, .Lgpr_setup_finished 1666 LOOP_OVER_SHORTY_STORING_GPRS x5, w5, x9, x12, x10, x11, .Lgpr_setup_finished 1667 LOOP_OVER_SHORTY_STORING_GPRS x6, w6, x9, x12, x10, x11, .Lgpr_setup_finished 1668 LOOP_OVER_SHORTY_STORING_GPRS x7, w7, x9, x12, x10, x11, .Lgpr_setup_finished 1669 LOOP_OVER_INTs x9, x12, x10, x11, x28, .Lgpr_setup_finished 1670.Lgpr_setup_finished: 1671 add x9, xIBASE, #1 // shorty + 1 ; ie skip return arg character 1672 mov x12, #0 // reset counter 1673 LOOP_OVER_SHORTY_STORING_FPS d0, s0, x9, x12, x10, .Lxmm_setup_finished 1674 LOOP_OVER_SHORTY_STORING_FPS d1, s1, x9, x12, x10, .Lxmm_setup_finished 1675 LOOP_OVER_SHORTY_STORING_FPS d2, s2, x9, x12, x10, .Lxmm_setup_finished 1676 LOOP_OVER_SHORTY_STORING_FPS d3, s3, x9, x12, x10, .Lxmm_setup_finished 1677 LOOP_OVER_SHORTY_STORING_FPS d4, s4, x9, x12, x10, .Lxmm_setup_finished 1678 LOOP_OVER_SHORTY_STORING_FPS d5, s5, x9, x12, x10, .Lxmm_setup_finished 1679 LOOP_OVER_SHORTY_STORING_FPS d6, s6, x9, x12, x10, .Lxmm_setup_finished 1680 LOOP_OVER_SHORTY_STORING_FPS d7, s7, x9, x12, x10, .Lxmm_setup_finished 1681 LOOP_OVER_FPs x9, x12, x10, x28, .Lxmm_setup_finished 1682.Lxmm_setup_finished: 1683 CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0) 1684 1685 // Set rIBASE 1686 adr xIBASE, artNterpAsmInstructionStart 1687 /* start executing the instruction at xPC */ 1688 START_EXECUTING_INSTRUCTIONS 1689 /* NOTE: no fallthrough */ 1690 // cfi info continues, and covers the whole nterp implementation. 1691 SIZE ExecuteNterpImpl 1692 1693 .type artNterpAsmInstructionStart, #function 1694 .hidden artNterpAsmInstructionStart 1695 .global artNterpAsmInstructionStart 1696artNterpAsmInstructionStart = .L_op_nop 1697 .text 1698 1699/* ------------------------------ */ 1700 .balign NTERP_HANDLER_SIZE 1701.L_op_nop: /* 0x00 */ 1702 NAME_START nterp_op_nop 1703 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1704 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1705 1706 FETCH_ADVANCE_INST 1 // advance to next instr, load rINST 1707 GET_INST_OPCODE ip // ip<- opcode from rINST 1708 GOTO_OPCODE ip // execute it 1709 1710 NAME_END nterp_op_nop 1711 // Advance to the end of this handler. Causes error if we are past that point. 1712 .org nterp_op_nop + NTERP_HANDLER_SIZE // op_nop handler is too big! 1713 1714/* ------------------------------ */ 1715 .balign NTERP_HANDLER_SIZE 1716.L_op_move: /* 0x01 */ 1717 NAME_START nterp_op_move 1718 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1719 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1720 1721 /* for move, move-object, long-to-int */ 1722 /* op vA, vB */ 1723 lsr w1, wINST, #12 // x1<- B from 15:12 1724 ubfx w0, wINST, #8, #4 // x0<- A from 11:8 1725 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 1726 GET_VREG w2, w1 // x2<- fp[B] 1727 GET_INST_OPCODE ip // ip<- opcode from wINST 1728 .if 0 1729 SET_VREG_OBJECT w2, w0 // fp[A]<- x2 1730 .else 1731 SET_VREG w2, w0 // fp[A]<- x2 1732 .endif 1733 GOTO_OPCODE ip // execute next instruction 1734 1735 NAME_END nterp_op_move 1736 // Advance to the end of this handler. Causes error if we are past that point. 1737 .org nterp_op_move + NTERP_HANDLER_SIZE // op_move handler is too big! 1738 1739/* ------------------------------ */ 1740 .balign NTERP_HANDLER_SIZE 1741.L_op_move_from16: /* 0x02 */ 1742 NAME_START nterp_op_move_from16 1743 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1744 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1745 1746 /* for: move/from16, move-object/from16 */ 1747 /* op vAA, vBBBB */ 1748 FETCH w1, 1 // r1<- BBBB 1749 lsr w0, wINST, #8 // r0<- AA 1750 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 1751 GET_VREG w2, w1 // r2<- fp[BBBB] 1752 GET_INST_OPCODE ip // extract opcode from wINST 1753 .if 0 1754 SET_VREG_OBJECT w2, w0 // fp[AA]<- r2 1755 .else 1756 SET_VREG w2, w0 // fp[AA]<- r2 1757 .endif 1758 GOTO_OPCODE ip // jump to next instruction 1759 1760 NAME_END nterp_op_move_from16 1761 // Advance to the end of this handler. Causes error if we are past that point. 1762 .org nterp_op_move_from16 + NTERP_HANDLER_SIZE // op_move_from16 handler is too big! 1763 1764/* ------------------------------ */ 1765 .balign NTERP_HANDLER_SIZE 1766.L_op_move_16: /* 0x03 */ 1767 NAME_START nterp_op_move_16 1768 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1769 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1770 1771 /* for: move/16, move-object/16 */ 1772 /* op vAAAA, vBBBB */ 1773 FETCH w1, 2 // w1<- BBBB 1774 FETCH w0, 1 // w0<- AAAA 1775 FETCH_ADVANCE_INST 3 // advance xPC, load xINST 1776 GET_VREG w2, w1 // w2<- fp[BBBB] 1777 GET_INST_OPCODE ip // extract opcode from xINST 1778 .if 0 1779 SET_VREG_OBJECT w2, w0 // fp[AAAA]<- w2 1780 .else 1781 SET_VREG w2, w0 // fp[AAAA]<- w2 1782 .endif 1783 GOTO_OPCODE ip // jump to next instruction 1784 1785 NAME_END nterp_op_move_16 1786 // Advance to the end of this handler. Causes error if we are past that point. 1787 .org nterp_op_move_16 + NTERP_HANDLER_SIZE // op_move_16 handler is too big! 1788 1789/* ------------------------------ */ 1790 .balign NTERP_HANDLER_SIZE 1791.L_op_move_wide: /* 0x04 */ 1792 NAME_START nterp_op_move_wide 1793 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1794 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1795 1796 /* move-wide vA, vB */ 1797 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 1798 lsr w3, wINST, #12 // w3<- B 1799 ubfx w2, wINST, #8, #4 // w2<- A 1800 GET_VREG_WIDE x3, w3 1801 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 1802 GET_INST_OPCODE ip // extract opcode from wINST 1803 SET_VREG_WIDE x3, w2 1804 GOTO_OPCODE ip // jump to next instruction 1805 1806 NAME_END nterp_op_move_wide 1807 // Advance to the end of this handler. Causes error if we are past that point. 1808 .org nterp_op_move_wide + NTERP_HANDLER_SIZE // op_move_wide handler is too big! 1809 1810/* ------------------------------ */ 1811 .balign NTERP_HANDLER_SIZE 1812.L_op_move_wide_from16: /* 0x05 */ 1813 NAME_START nterp_op_move_wide_from16 1814 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1815 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1816 1817 /* move-wide/from16 vAA, vBBBB */ 1818 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 1819 FETCH w3, 1 // w3<- BBBB 1820 lsr w2, wINST, #8 // w2<- AA 1821 GET_VREG_WIDE x3, w3 1822 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 1823 GET_INST_OPCODE ip // extract opcode from wINST 1824 SET_VREG_WIDE x3, w2 1825 GOTO_OPCODE ip // jump to next instruction 1826 1827 NAME_END nterp_op_move_wide_from16 1828 // Advance to the end of this handler. Causes error if we are past that point. 1829 .org nterp_op_move_wide_from16 + NTERP_HANDLER_SIZE // op_move_wide_from16 handler is too big! 1830 1831/* ------------------------------ */ 1832 .balign NTERP_HANDLER_SIZE 1833.L_op_move_wide_16: /* 0x06 */ 1834 NAME_START nterp_op_move_wide_16 1835 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1836 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1837 1838 /* move-wide/16 vAAAA, vBBBB */ 1839 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 1840 FETCH w3, 2 // w3<- BBBB 1841 FETCH w2, 1 // w2<- AAAA 1842 GET_VREG_WIDE x3, w3 1843 FETCH_ADVANCE_INST 3 // advance rPC, load rINST 1844 SET_VREG_WIDE x3, w2 1845 GET_INST_OPCODE ip // extract opcode from rINST 1846 GOTO_OPCODE ip // jump to next instruction 1847 1848 NAME_END nterp_op_move_wide_16 1849 // Advance to the end of this handler. Causes error if we are past that point. 1850 .org nterp_op_move_wide_16 + NTERP_HANDLER_SIZE // op_move_wide_16 handler is too big! 1851 1852/* ------------------------------ */ 1853 .balign NTERP_HANDLER_SIZE 1854.L_op_move_object: /* 0x07 */ 1855 NAME_START nterp_op_move_object 1856 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1857 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1858 1859 /* for move, move-object, long-to-int */ 1860 /* op vA, vB */ 1861 lsr w1, wINST, #12 // x1<- B from 15:12 1862 ubfx w0, wINST, #8, #4 // x0<- A from 11:8 1863 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 1864 GET_VREG w2, w1 // x2<- fp[B] 1865 GET_INST_OPCODE ip // ip<- opcode from wINST 1866 .if 1 1867 SET_VREG_OBJECT w2, w0 // fp[A]<- x2 1868 .else 1869 SET_VREG w2, w0 // fp[A]<- x2 1870 .endif 1871 GOTO_OPCODE ip // execute next instruction 1872 1873 NAME_END nterp_op_move_object 1874 // Advance to the end of this handler. Causes error if we are past that point. 1875 .org nterp_op_move_object + NTERP_HANDLER_SIZE // op_move_object handler is too big! 1876 1877/* ------------------------------ */ 1878 .balign NTERP_HANDLER_SIZE 1879.L_op_move_object_from16: /* 0x08 */ 1880 NAME_START nterp_op_move_object_from16 1881 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1882 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1883 1884 /* for: move/from16, move-object/from16 */ 1885 /* op vAA, vBBBB */ 1886 FETCH w1, 1 // r1<- BBBB 1887 lsr w0, wINST, #8 // r0<- AA 1888 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 1889 GET_VREG w2, w1 // r2<- fp[BBBB] 1890 GET_INST_OPCODE ip // extract opcode from wINST 1891 .if 1 1892 SET_VREG_OBJECT w2, w0 // fp[AA]<- r2 1893 .else 1894 SET_VREG w2, w0 // fp[AA]<- r2 1895 .endif 1896 GOTO_OPCODE ip // jump to next instruction 1897 1898 NAME_END nterp_op_move_object_from16 1899 // Advance to the end of this handler. Causes error if we are past that point. 1900 .org nterp_op_move_object_from16 + NTERP_HANDLER_SIZE // op_move_object_from16 handler is too big! 1901 1902/* ------------------------------ */ 1903 .balign NTERP_HANDLER_SIZE 1904.L_op_move_object_16: /* 0x09 */ 1905 NAME_START nterp_op_move_object_16 1906 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1907 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1908 1909 /* for: move/16, move-object/16 */ 1910 /* op vAAAA, vBBBB */ 1911 FETCH w1, 2 // w1<- BBBB 1912 FETCH w0, 1 // w0<- AAAA 1913 FETCH_ADVANCE_INST 3 // advance xPC, load xINST 1914 GET_VREG w2, w1 // w2<- fp[BBBB] 1915 GET_INST_OPCODE ip // extract opcode from xINST 1916 .if 1 1917 SET_VREG_OBJECT w2, w0 // fp[AAAA]<- w2 1918 .else 1919 SET_VREG w2, w0 // fp[AAAA]<- w2 1920 .endif 1921 GOTO_OPCODE ip // jump to next instruction 1922 1923 NAME_END nterp_op_move_object_16 1924 // Advance to the end of this handler. Causes error if we are past that point. 1925 .org nterp_op_move_object_16 + NTERP_HANDLER_SIZE // op_move_object_16 handler is too big! 1926 1927/* ------------------------------ */ 1928 .balign NTERP_HANDLER_SIZE 1929.L_op_move_result: /* 0x0a */ 1930 NAME_START nterp_op_move_result 1931 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1932 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1933 1934 /* for: move-result, move-result-object */ 1935 /* op vAA */ 1936 lsr w2, wINST, #8 // r2<- AA 1937 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 1938 GET_INST_OPCODE ip // extract opcode from wINST 1939 .if 0 1940 SET_VREG_OBJECT w0, w2 // fp[AA]<- r0 1941 .else 1942 SET_VREG w0, w2 // fp[AA]<- r0 1943 .endif 1944 GOTO_OPCODE ip // jump to next instruction 1945 1946 NAME_END nterp_op_move_result 1947 // Advance to the end of this handler. Causes error if we are past that point. 1948 .org nterp_op_move_result + NTERP_HANDLER_SIZE // op_move_result handler is too big! 1949 1950/* ------------------------------ */ 1951 .balign NTERP_HANDLER_SIZE 1952.L_op_move_result_wide: /* 0x0b */ 1953 NAME_START nterp_op_move_result_wide 1954 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1955 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1956 1957 /* for: move-result-wide */ 1958 /* op vAA */ 1959 lsr w2, wINST, #8 // r2<- AA 1960 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 1961 GET_INST_OPCODE ip // extract opcode from wINST 1962 SET_VREG_WIDE x0, w2 // fp[AA]<- r0 1963 GOTO_OPCODE ip // jump to next instruction 1964 1965 NAME_END nterp_op_move_result_wide 1966 // Advance to the end of this handler. Causes error if we are past that point. 1967 .org nterp_op_move_result_wide + NTERP_HANDLER_SIZE // op_move_result_wide handler is too big! 1968 1969/* ------------------------------ */ 1970 .balign NTERP_HANDLER_SIZE 1971.L_op_move_result_object: /* 0x0c */ 1972 NAME_START nterp_op_move_result_object 1973 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1974 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1975 1976 /* for: move-result, move-result-object */ 1977 /* op vAA */ 1978 lsr w2, wINST, #8 // r2<- AA 1979 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 1980 GET_INST_OPCODE ip // extract opcode from wINST 1981 .if 1 1982 SET_VREG_OBJECT w0, w2 // fp[AA]<- r0 1983 .else 1984 SET_VREG w0, w2 // fp[AA]<- r0 1985 .endif 1986 GOTO_OPCODE ip // jump to next instruction 1987 1988 NAME_END nterp_op_move_result_object 1989 // Advance to the end of this handler. Causes error if we are past that point. 1990 .org nterp_op_move_result_object + NTERP_HANDLER_SIZE // op_move_result_object handler is too big! 1991 1992/* ------------------------------ */ 1993 .balign NTERP_HANDLER_SIZE 1994.L_op_move_exception: /* 0x0d */ 1995 NAME_START nterp_op_move_exception 1996 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 1997 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 1998 1999 /* move-exception vAA */ 2000 lsr w2, wINST, #8 // w2<- AA 2001 ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] 2002 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 2003 SET_VREG_OBJECT w3, w2 // fp[AA]<- exception obj 2004 GET_INST_OPCODE ip // extract opcode from rINST 2005 str xzr, [xSELF, #THREAD_EXCEPTION_OFFSET] // clear exception 2006 GOTO_OPCODE ip // jump to next instruction 2007 2008 NAME_END nterp_op_move_exception 2009 // Advance to the end of this handler. Causes error if we are past that point. 2010 .org nterp_op_move_exception + NTERP_HANDLER_SIZE // op_move_exception handler is too big! 2011 2012/* ------------------------------ */ 2013 .balign NTERP_HANDLER_SIZE 2014.L_op_return_void: /* 0x0e */ 2015 NAME_START nterp_op_return_void 2016 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2017 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2018 2019 .if 1 2020 // Thread fence for constructor 2021 dmb ishst 2022 .else 2023 lsr w2, wINST, #8 // w2<- AA 2024 .if 0 2025 GET_VREG_WIDE x0, w2 // x0<- vAA 2026 // In case we're going back to compiled code, put the 2027 // result also in d0 2028 fmov d0, x0 2029 .else 2030 GET_VREG w0, w2 // r0<- vAA 2031 .if !0 2032 // In case we're going back to compiled code, put the 2033 // result also in s0. 2034 fmov s0, w0 2035 .endif 2036 .endif 2037 .endif 2038 .cfi_remember_state 2039 ldr ip, [xREFS, #-8] 2040 mov sp, ip 2041 .cfi_def_cfa sp, CALLEE_SAVES_SIZE 2042 RESTORE_ALL_CALLEE_SAVES 2043 ret 2044 .cfi_restore_state 2045 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2046 2047 NAME_END nterp_op_return_void 2048 // Advance to the end of this handler. Causes error if we are past that point. 2049 .org nterp_op_return_void + NTERP_HANDLER_SIZE // op_return_void handler is too big! 2050 2051/* ------------------------------ */ 2052 .balign NTERP_HANDLER_SIZE 2053.L_op_return: /* 0x0f */ 2054 NAME_START nterp_op_return 2055 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2056 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2057 2058 .if 0 2059 // Thread fence for constructor 2060 dmb ishst 2061 .else 2062 lsr w2, wINST, #8 // w2<- AA 2063 .if 0 2064 GET_VREG_WIDE x0, w2 // x0<- vAA 2065 // In case we're going back to compiled code, put the 2066 // result also in d0 2067 fmov d0, x0 2068 .else 2069 GET_VREG w0, w2 // r0<- vAA 2070 .if !0 2071 // In case we're going back to compiled code, put the 2072 // result also in s0. 2073 fmov s0, w0 2074 .endif 2075 .endif 2076 .endif 2077 .cfi_remember_state 2078 ldr ip, [xREFS, #-8] 2079 mov sp, ip 2080 .cfi_def_cfa sp, CALLEE_SAVES_SIZE 2081 RESTORE_ALL_CALLEE_SAVES 2082 ret 2083 .cfi_restore_state 2084 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2085 2086 NAME_END nterp_op_return 2087 // Advance to the end of this handler. Causes error if we are past that point. 2088 .org nterp_op_return + NTERP_HANDLER_SIZE // op_return handler is too big! 2089 2090/* ------------------------------ */ 2091 .balign NTERP_HANDLER_SIZE 2092.L_op_return_wide: /* 0x10 */ 2093 NAME_START nterp_op_return_wide 2094 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2095 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2096 2097 .if 0 2098 // Thread fence for constructor 2099 dmb ishst 2100 .else 2101 lsr w2, wINST, #8 // w2<- AA 2102 .if 1 2103 GET_VREG_WIDE x0, w2 // x0<- vAA 2104 // In case we're going back to compiled code, put the 2105 // result also in d0 2106 fmov d0, x0 2107 .else 2108 GET_VREG w0, w2 // r0<- vAA 2109 .if !0 2110 // In case we're going back to compiled code, put the 2111 // result also in s0. 2112 fmov s0, w0 2113 .endif 2114 .endif 2115 .endif 2116 .cfi_remember_state 2117 ldr ip, [xREFS, #-8] 2118 mov sp, ip 2119 .cfi_def_cfa sp, CALLEE_SAVES_SIZE 2120 RESTORE_ALL_CALLEE_SAVES 2121 ret 2122 .cfi_restore_state 2123 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2124 2125 NAME_END nterp_op_return_wide 2126 // Advance to the end of this handler. Causes error if we are past that point. 2127 .org nterp_op_return_wide + NTERP_HANDLER_SIZE // op_return_wide handler is too big! 2128 2129/* ------------------------------ */ 2130 .balign NTERP_HANDLER_SIZE 2131.L_op_return_object: /* 0x11 */ 2132 NAME_START nterp_op_return_object 2133 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2134 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2135 2136 .if 0 2137 // Thread fence for constructor 2138 dmb ishst 2139 .else 2140 lsr w2, wINST, #8 // w2<- AA 2141 .if 0 2142 GET_VREG_WIDE x0, w2 // x0<- vAA 2143 // In case we're going back to compiled code, put the 2144 // result also in d0 2145 fmov d0, x0 2146 .else 2147 GET_VREG w0, w2 // r0<- vAA 2148 .if !1 2149 // In case we're going back to compiled code, put the 2150 // result also in s0. 2151 fmov s0, w0 2152 .endif 2153 .endif 2154 .endif 2155 .cfi_remember_state 2156 ldr ip, [xREFS, #-8] 2157 mov sp, ip 2158 .cfi_def_cfa sp, CALLEE_SAVES_SIZE 2159 RESTORE_ALL_CALLEE_SAVES 2160 ret 2161 .cfi_restore_state 2162 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2163 2164 NAME_END nterp_op_return_object 2165 // Advance to the end of this handler. Causes error if we are past that point. 2166 .org nterp_op_return_object + NTERP_HANDLER_SIZE // op_return_object handler is too big! 2167 2168/* ------------------------------ */ 2169 .balign NTERP_HANDLER_SIZE 2170.L_op_const_4: /* 0x12 */ 2171 NAME_START nterp_op_const_4 2172 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2173 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2174 2175 /* const/4 vA, #+B */ 2176 sbfx w1, wINST, #12, #4 // w1<- sssssssB 2177 ubfx w0, wINST, #8, #4 // w0<- A 2178 FETCH_ADVANCE_INST 1 // advance xPC, load wINST 2179 GET_INST_OPCODE ip // ip<- opcode from xINST 2180 SET_VREG w1, w0 // fp[A]<- w1 2181 GOTO_OPCODE ip // execute next instruction 2182 2183 NAME_END nterp_op_const_4 2184 // Advance to the end of this handler. Causes error if we are past that point. 2185 .org nterp_op_const_4 + NTERP_HANDLER_SIZE // op_const_4 handler is too big! 2186 2187/* ------------------------------ */ 2188 .balign NTERP_HANDLER_SIZE 2189.L_op_const_16: /* 0x13 */ 2190 NAME_START nterp_op_const_16 2191 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2192 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2193 2194 /* const/16 vAA, #+BBBB */ 2195 FETCH_S w0, 1 // w0<- ssssBBBB (sign-extended) 2196 lsr w3, wINST, #8 // w3<- AA 2197 FETCH_ADVANCE_INST 2 // advance xPC, load wINST 2198 SET_VREG w0, w3 // vAA<- w0 2199 GET_INST_OPCODE ip // extract opcode from wINST 2200 GOTO_OPCODE ip // jump to next instruction 2201 2202 NAME_END nterp_op_const_16 2203 // Advance to the end of this handler. Causes error if we are past that point. 2204 .org nterp_op_const_16 + NTERP_HANDLER_SIZE // op_const_16 handler is too big! 2205 2206/* ------------------------------ */ 2207 .balign NTERP_HANDLER_SIZE 2208.L_op_const: /* 0x14 */ 2209 NAME_START nterp_op_const 2210 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2211 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2212 2213 /* const vAA, #+BBBBbbbb */ 2214 lsr w3, wINST, #8 // w3<- AA 2215 FETCH w0, 1 // w0<- bbbb (low) 2216 FETCH w1, 2 // w1<- BBBB (high) 2217 FETCH_ADVANCE_INST 3 // advance rPC, load wINST 2218 orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb 2219 GET_INST_OPCODE ip // extract opcode from wINST 2220 SET_VREG w0, w3 // vAA<- w0 2221 GOTO_OPCODE ip // jump to next instruction 2222 2223 NAME_END nterp_op_const 2224 // Advance to the end of this handler. Causes error if we are past that point. 2225 .org nterp_op_const + NTERP_HANDLER_SIZE // op_const handler is too big! 2226 2227/* ------------------------------ */ 2228 .balign NTERP_HANDLER_SIZE 2229.L_op_const_high16: /* 0x15 */ 2230 NAME_START nterp_op_const_high16 2231 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2232 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2233 2234 /* const/high16 vAA, #+BBBB0000 */ 2235 FETCH w0, 1 // r0<- 0000BBBB (zero-extended) 2236 lsr w3, wINST, #8 // r3<- AA 2237 lsl w0, w0, #16 // r0<- BBBB0000 2238 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 2239 SET_VREG w0, w3 // vAA<- r0 2240 GET_INST_OPCODE ip // extract opcode from rINST 2241 GOTO_OPCODE ip // jump to next instruction 2242 2243 NAME_END nterp_op_const_high16 2244 // Advance to the end of this handler. Causes error if we are past that point. 2245 .org nterp_op_const_high16 + NTERP_HANDLER_SIZE // op_const_high16 handler is too big! 2246 2247/* ------------------------------ */ 2248 .balign NTERP_HANDLER_SIZE 2249.L_op_const_wide_16: /* 0x16 */ 2250 NAME_START nterp_op_const_wide_16 2251 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2252 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2253 2254 /* const-wide/16 vAA, #+BBBB */ 2255 FETCH_S x0, 1 // x0<- ssssssssssssBBBB (sign-extended) 2256 lsr w3, wINST, #8 // w3<- AA 2257 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 2258 GET_INST_OPCODE ip // extract opcode from rINST 2259 SET_VREG_WIDE x0, w3 2260 GOTO_OPCODE ip // jump to next instruction 2261 2262 NAME_END nterp_op_const_wide_16 2263 // Advance to the end of this handler. Causes error if we are past that point. 2264 .org nterp_op_const_wide_16 + NTERP_HANDLER_SIZE // op_const_wide_16 handler is too big! 2265 2266/* ------------------------------ */ 2267 .balign NTERP_HANDLER_SIZE 2268.L_op_const_wide_32: /* 0x17 */ 2269 NAME_START nterp_op_const_wide_32 2270 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2271 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2272 2273 /* const-wide/32 vAA, #+BBBBbbbb */ 2274 FETCH w0, 1 // x0<- 000000000000bbbb (low) 2275 lsr w3, wINST, #8 // w3<- AA 2276 FETCH_S x2, 2 // x2<- ssssssssssssBBBB (high) 2277 FETCH_ADVANCE_INST 3 // advance rPC, load wINST 2278 GET_INST_OPCODE ip // extract opcode from wINST 2279 orr x0, x0, x2, lsl #16 // x0<- ssssssssBBBBbbbb 2280 SET_VREG_WIDE x0, w3 2281 GOTO_OPCODE ip // jump to next instruction 2282 2283 NAME_END nterp_op_const_wide_32 2284 // Advance to the end of this handler. Causes error if we are past that point. 2285 .org nterp_op_const_wide_32 + NTERP_HANDLER_SIZE // op_const_wide_32 handler is too big! 2286 2287/* ------------------------------ */ 2288 .balign NTERP_HANDLER_SIZE 2289.L_op_const_wide: /* 0x18 */ 2290 NAME_START nterp_op_const_wide 2291 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2292 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2293 2294 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 2295 FETCH w0, 1 // w0<- bbbb (low) 2296 FETCH w1, 2 // w1<- BBBB (low middle) 2297 FETCH w2, 3 // w2<- hhhh (high middle) 2298 FETCH w3, 4 // w3<- HHHH (high) 2299 lsr w4, wINST, #8 // r4<- AA 2300 FETCH_ADVANCE_INST 5 // advance rPC, load wINST 2301 GET_INST_OPCODE ip // extract opcode from wINST 2302 orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb 2303 orr x0, x0, x2, lsl #32 // w0<- hhhhBBBBbbbb 2304 orr x0, x0, x3, lsl #48 // w0<- HHHHhhhhBBBBbbbb 2305 SET_VREG_WIDE x0, w4 2306 GOTO_OPCODE ip // jump to next instruction 2307 2308 NAME_END nterp_op_const_wide 2309 // Advance to the end of this handler. Causes error if we are past that point. 2310 .org nterp_op_const_wide + NTERP_HANDLER_SIZE // op_const_wide handler is too big! 2311 2312/* ------------------------------ */ 2313 .balign NTERP_HANDLER_SIZE 2314.L_op_const_wide_high16: /* 0x19 */ 2315 NAME_START nterp_op_const_wide_high16 2316 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2317 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2318 2319 /* const-wide/high16 vAA, #+BBBB000000000000 */ 2320 FETCH w0, 1 // w0<- 0000BBBB (zero-extended) 2321 lsr w1, wINST, #8 // w1<- AA 2322 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 2323 lsl x0, x0, #48 2324 SET_VREG_WIDE x0, w1 2325 GET_INST_OPCODE ip // extract opcode from wINST 2326 GOTO_OPCODE ip // jump to next instruction 2327 2328 NAME_END nterp_op_const_wide_high16 2329 // Advance to the end of this handler. Causes error if we are past that point. 2330 .org nterp_op_const_wide_high16 + NTERP_HANDLER_SIZE // op_const_wide_high16 handler is too big! 2331 2332/* ------------------------------ */ 2333 .balign NTERP_HANDLER_SIZE 2334.L_op_const_string: /* 0x1a */ 2335 NAME_START nterp_op_const_string 2336 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2337 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2338 2339 /* const/string vAA, String@BBBB */ 2340 // Fast-path which gets the object from thread-local cache. 2341 // Fetch some information from the thread cache. 2342 // Uses ip and ip2 as temporaries. 2343 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 2344 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 2345 add ip, ip, ip2, lsl #4 // entry address within the cache 2346 ldp ip, x0, [ip] // entry key (pc) and value (offset) 2347 cmp ip, xPC 2348 b.ne 2f 2349 2350 TEST_IF_MARKING 3f 23511: 2352 lsr w1, wINST, #8 // w1<- AA 2353 .if 0 2354 FETCH_ADVANCE_INST 3 // advance rPC, load wINST 2355 .else 2356 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 2357 .endif 2358 GET_INST_OPCODE ip // extract opcode from wINST 2359 SET_VREG_OBJECT w0, w1 // vAA <- value 2360 GOTO_OPCODE ip // jump to next instruction 23612: 2362 EXPORT_PC 2363 mov x0, xSELF 2364 ldr x1, [sp] 2365 mov x2, xPC 2366 bl nterp_load_object 2367 b 1b 23683: 2369 bl art_quick_read_barrier_mark_reg00 2370 b 1b 2371 2372 NAME_END nterp_op_const_string 2373 // Advance to the end of this handler. Causes error if we are past that point. 2374 .org nterp_op_const_string + NTERP_HANDLER_SIZE // op_const_string handler is too big! 2375 2376/* ------------------------------ */ 2377 .balign NTERP_HANDLER_SIZE 2378.L_op_const_string_jumbo: /* 0x1b */ 2379 NAME_START nterp_op_const_string_jumbo 2380 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2381 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2382 2383 /* const/string vAA, String@BBBBBBBB */ 2384 // Fast-path which gets the object from thread-local cache. 2385 // Fetch some information from the thread cache. 2386 // Uses ip and ip2 as temporaries. 2387 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 2388 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 2389 add ip, ip, ip2, lsl #4 // entry address within the cache 2390 ldp ip, x0, [ip] // entry key (pc) and value (offset) 2391 cmp ip, xPC 2392 b.ne 2f 2393 2394 TEST_IF_MARKING 3f 23951: 2396 lsr w1, wINST, #8 // w1<- AA 2397 .if 1 2398 FETCH_ADVANCE_INST 3 // advance rPC, load wINST 2399 .else 2400 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 2401 .endif 2402 GET_INST_OPCODE ip // extract opcode from wINST 2403 SET_VREG_OBJECT w0, w1 // vAA <- value 2404 GOTO_OPCODE ip // jump to next instruction 24052: 2406 EXPORT_PC 2407 mov x0, xSELF 2408 ldr x1, [sp] 2409 mov x2, xPC 2410 bl nterp_load_object 2411 b 1b 24123: 2413 bl art_quick_read_barrier_mark_reg00 2414 b 1b 2415 2416 NAME_END nterp_op_const_string_jumbo 2417 // Advance to the end of this handler. Causes error if we are past that point. 2418 .org nterp_op_const_string_jumbo + NTERP_HANDLER_SIZE // op_const_string_jumbo handler is too big! 2419 2420/* ------------------------------ */ 2421 .balign NTERP_HANDLER_SIZE 2422.L_op_const_class: /* 0x1c */ 2423 NAME_START nterp_op_const_class 2424 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2425 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2426 2427 // Fast-path which gets the object from thread-local cache. 2428 // Fetch some information from the thread cache. 2429 // Uses ip and ip2 as temporaries. 2430 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 2431 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 2432 add ip, ip, ip2, lsl #4 // entry address within the cache 2433 ldp ip, x0, [ip] // entry key (pc) and value (offset) 2434 cmp ip, xPC 2435 b.ne 2f 2436 2437 TEST_IF_MARKING 3f 24381: 2439 lsr w1, wINST, #8 // w1<- AA 2440 .if 0 2441 FETCH_ADVANCE_INST 3 // advance rPC, load wINST 2442 .else 2443 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 2444 .endif 2445 GET_INST_OPCODE ip // extract opcode from wINST 2446 SET_VREG_OBJECT w0, w1 // vAA <- value 2447 GOTO_OPCODE ip // jump to next instruction 24482: 2449 EXPORT_PC 2450 mov x0, xSELF 2451 ldr x1, [sp] 2452 mov x2, xPC 2453 bl nterp_get_class 2454 b 1b 24553: 2456 bl art_quick_read_barrier_mark_reg00 2457 b 1b 2458 2459 NAME_END nterp_op_const_class 2460 // Advance to the end of this handler. Causes error if we are past that point. 2461 .org nterp_op_const_class + NTERP_HANDLER_SIZE // op_const_class handler is too big! 2462 2463/* ------------------------------ */ 2464 .balign NTERP_HANDLER_SIZE 2465.L_op_monitor_enter: /* 0x1d */ 2466 NAME_START nterp_op_monitor_enter 2467 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2468 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2469 2470/* 2471 * Synchronize on an object. 2472 */ 2473 /* monitor-enter vAA */ 2474 EXPORT_PC 2475 lsr w2, wINST, #8 // w2<- AA 2476 GET_VREG w0, w2 2477 bl art_quick_lock_object 2478 FETCH_ADVANCE_INST 1 2479 GET_INST_OPCODE ip // extract opcode from rINST 2480 GOTO_OPCODE ip // jump to next instruction 2481 2482 NAME_END nterp_op_monitor_enter 2483 // Advance to the end of this handler. Causes error if we are past that point. 2484 .org nterp_op_monitor_enter + NTERP_HANDLER_SIZE // op_monitor_enter handler is too big! 2485 2486/* ------------------------------ */ 2487 .balign NTERP_HANDLER_SIZE 2488.L_op_monitor_exit: /* 0x1e */ 2489 NAME_START nterp_op_monitor_exit 2490 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2491 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2492 2493/* 2494 * Unlock an object. 2495 * 2496 * Exceptions that occur when unlocking a monitor need to appear as 2497 * if they happened at the following instruction. See the Dalvik 2498 * instruction spec. 2499 */ 2500 /* monitor-exit vAA */ 2501 EXPORT_PC 2502 lsr w2, wINST, #8 // w2<- AA 2503 GET_VREG w0, w2 2504 bl art_quick_unlock_object 2505 FETCH_ADVANCE_INST 1 2506 GET_INST_OPCODE ip // extract opcode from rINST 2507 GOTO_OPCODE ip // jump to next instruction 2508 2509 NAME_END nterp_op_monitor_exit 2510 // Advance to the end of this handler. Causes error if we are past that point. 2511 .org nterp_op_monitor_exit + NTERP_HANDLER_SIZE // op_monitor_exit handler is too big! 2512 2513/* ------------------------------ */ 2514 .balign NTERP_HANDLER_SIZE 2515.L_op_check_cast: /* 0x1f */ 2516 NAME_START nterp_op_check_cast 2517 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2518 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2519 2520 // Fast-path which gets the class from thread-local cache. 2521 // Fetch some information from the thread cache. 2522 // Uses ip and ip2 as temporaries. 2523 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 2524 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 2525 add ip, ip, ip2, lsl #4 // entry address within the cache 2526 ldp ip, x1, [ip] // entry key (pc) and value (offset) 2527 cmp ip, xPC 2528 b.ne 2f 2529 25301: 2531 lsr w2, wINST, #8 // w2<- A 2532 GET_VREG w0, w2 // w0<- vA (object) 2533 cbz w0, .Lop_check_cast_resume 2534 ldr w2, [x0, #MIRROR_OBJECT_CLASS_OFFSET] 2535 UNPOISON_HEAP_REF w2 2536 // Fast path: do a comparison without read barrier. 2537 cmp w1, w2 2538 bne nterp_op_check_cast_slow_path 2539.Lop_check_cast_resume: 2540 FETCH_ADVANCE_INST 2 2541 GET_INST_OPCODE ip 2542 GOTO_OPCODE ip 25432: 2544 EXPORT_PC 2545 mov x0, xSELF 2546 ldr x1, [sp] 2547 mov x2, xPC 2548 bl nterp_get_class 2549 mov x1, x0 2550 b 1b 2551 2552 NAME_END nterp_op_check_cast 2553 // Advance to the end of this handler. Causes error if we are past that point. 2554 .org nterp_op_check_cast + NTERP_HANDLER_SIZE // op_check_cast handler is too big! 2555 2556/* ------------------------------ */ 2557 .balign NTERP_HANDLER_SIZE 2558.L_op_instance_of: /* 0x20 */ 2559 NAME_START nterp_op_instance_of 2560 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2561 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2562 2563 /* instance-of vA, vB, class@CCCC */ 2564 // Fast-path which gets the class from thread-local cache. 2565 // Fetch some information from the thread cache. 2566 // Uses ip and ip2 as temporaries. 2567 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 2568 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 2569 add ip, ip, ip2, lsl #4 // entry address within the cache 2570 ldp ip, x1, [ip] // entry key (pc) and value (offset) 2571 cmp ip, xPC 2572 b.ne 2f 2573 25741: 2575 lsr w2, wINST, #12 // w2<- B 2576 GET_VREG w0, w2 // w0<- vB (object) 2577 cbz w0, .Lop_instance_of_resume 2578 ldr w2, [x0, #MIRROR_OBJECT_CLASS_OFFSET] 2579 UNPOISON_HEAP_REF w2 2580 // Fast path: do a comparison without read barrier. 2581 cmp w1, w2 2582 bne nterp_op_instance_of_slow_path 2583.Lop_instance_of_set_one: 2584 mov w0, #1 2585.Lop_instance_of_resume: 2586 ubfx w1, wINST, #8, #4 // w1<- A 2587 SET_VREG w0, w1 2588 FETCH_ADVANCE_INST 2 2589 GET_INST_OPCODE ip 2590 GOTO_OPCODE ip 25912: 2592 EXPORT_PC 2593 mov x0, xSELF 2594 ldr x1, [sp] 2595 mov x2, xPC 2596 bl nterp_get_class 2597 mov x1, x0 2598 b 1b 2599 2600 NAME_END nterp_op_instance_of 2601 // Advance to the end of this handler. Causes error if we are past that point. 2602 .org nterp_op_instance_of + NTERP_HANDLER_SIZE // op_instance_of handler is too big! 2603 2604/* ------------------------------ */ 2605 .balign NTERP_HANDLER_SIZE 2606.L_op_array_length: /* 0x21 */ 2607 NAME_START nterp_op_array_length 2608 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2609 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2610 2611 /* 2612 * Return the length of an array. 2613 */ 2614 lsr w1, wINST, #12 // w1<- B 2615 ubfx w2, wINST, #8, #4 // w2<- A 2616 GET_VREG w0, w1 // w0<- vB (object ref) 2617 cbz w0, common_errNullObject // bail if null 2618 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 2619 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- array length 2620 GET_INST_OPCODE ip // extract opcode from rINST 2621 SET_VREG w3, w2 // vB<- length 2622 GOTO_OPCODE ip // jump to next instruction 2623 2624 NAME_END nterp_op_array_length 2625 // Advance to the end of this handler. Causes error if we are past that point. 2626 .org nterp_op_array_length + NTERP_HANDLER_SIZE // op_array_length handler is too big! 2627 2628/* ------------------------------ */ 2629 .balign NTERP_HANDLER_SIZE 2630.L_op_new_instance: /* 0x22 */ 2631 NAME_START nterp_op_new_instance 2632 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2633 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2634 2635 EXPORT_PC 2636 // Fast-path which gets the class from thread-local cache. 2637 // Fetch some information from the thread cache. 2638 // Uses ip and ip2 as temporaries. 2639 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 2640 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 2641 add ip, ip, ip2, lsl #4 // entry address within the cache 2642 ldp ip, x0, [ip] // entry key (pc) and value (offset) 2643 cmp ip, xPC 2644 b.ne 2f 2645 2646 TEST_IF_MARKING 3f 26474: 2648 ldr lr, [xSELF, #THREAD_ALLOC_OBJECT_ENTRYPOINT_OFFSET] 2649 blr lr 2650 dmb ishst // need fence for making object's class visible 26511: 2652 lsr w1, wINST, #8 // w1 <- A 2653 SET_VREG_OBJECT w0, w1 // fp[A] <- value 2654 FETCH_ADVANCE_INST 2 2655 GET_INST_OPCODE ip 2656 GOTO_OPCODE ip 26572: 2658 mov x0, xSELF 2659 ldr x1, [sp] 2660 mov x2, xPC 2661 bl nterp_allocate_object 2662 b 1b 26633: 2664 bl art_quick_read_barrier_mark_reg00 2665 b 4b 2666 NAME_END nterp_op_new_instance 2667 // Advance to the end of this handler. Causes error if we are past that point. 2668 .org nterp_op_new_instance + NTERP_HANDLER_SIZE // op_new_instance handler is too big! 2669 2670/* ------------------------------ */ 2671 .balign NTERP_HANDLER_SIZE 2672.L_op_new_array: /* 0x23 */ 2673 NAME_START nterp_op_new_array 2674 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2675 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2676 2677 /* new-array vA, vB, class@CCCC */ 2678 EXPORT_PC 2679 // Fast-path which gets the class from thread-local cache. 2680 // Fetch some information from the thread cache. 2681 // Uses ip and ip2 as temporaries. 2682 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 2683 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 2684 add ip, ip, ip2, lsl #4 // entry address within the cache 2685 ldp ip, x0, [ip] // entry key (pc) and value (offset) 2686 cmp ip, xPC 2687 b.ne 2f 2688 2689 TEST_IF_MARKING 3f 26901: 2691 lsr w1, wINST, #12 // w1<- B 2692 GET_VREG w1, w1 // w1<- vB (array length) 2693 ldr lr, [xSELF, #THREAD_ALLOC_ARRAY_ENTRYPOINT_OFFSET] 2694 blr lr 2695 dmb ishst // need fence for making array's class visible 2696 ubfx w1, wINST, #8, #4 // w1<- A 2697 SET_VREG_OBJECT w0, w1 2698 FETCH_ADVANCE_INST 2 2699 GET_INST_OPCODE ip 2700 GOTO_OPCODE ip 27012: 2702 mov x0, xSELF 2703 ldr x1, [sp, 0] 2704 mov x2, xPC 2705 bl nterp_get_class 2706 b 1b 27073: 2708 bl art_quick_read_barrier_mark_reg00 2709 b 1b 2710 NAME_END nterp_op_new_array 2711 // Advance to the end of this handler. Causes error if we are past that point. 2712 .org nterp_op_new_array + NTERP_HANDLER_SIZE // op_new_array handler is too big! 2713 2714/* ------------------------------ */ 2715 .balign NTERP_HANDLER_SIZE 2716.L_op_filled_new_array: /* 0x24 */ 2717 NAME_START nterp_op_filled_new_array 2718 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2719 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2720 2721/* 2722 * Create a new array with elements filled from registers. 2723 * 2724 * for: filled-new-array, filled-new-array/range 2725 */ 2726 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 2727 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 2728 EXPORT_PC 2729 mov x0, xSELF 2730 ldr x1, [sp] 2731 mov x2, xFP 2732 mov x3, xPC 2733 bl nterp_filled_new_array 2734 FETCH_ADVANCE_INST 3 // advance rPC, load rINST 2735 GET_INST_OPCODE ip // extract opcode from rINST 2736 GOTO_OPCODE ip // jump to next instruction 2737 2738 NAME_END nterp_op_filled_new_array 2739 // Advance to the end of this handler. Causes error if we are past that point. 2740 .org nterp_op_filled_new_array + NTERP_HANDLER_SIZE // op_filled_new_array handler is too big! 2741 2742/* ------------------------------ */ 2743 .balign NTERP_HANDLER_SIZE 2744.L_op_filled_new_array_range: /* 0x25 */ 2745 NAME_START nterp_op_filled_new_array_range 2746 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2747 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2748 2749/* 2750 * Create a new array with elements filled from registers. 2751 * 2752 * for: filled-new-array, filled-new-array/range 2753 */ 2754 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 2755 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 2756 EXPORT_PC 2757 mov x0, xSELF 2758 ldr x1, [sp] 2759 mov x2, xFP 2760 mov x3, xPC 2761 bl nterp_filled_new_array_range 2762 FETCH_ADVANCE_INST 3 // advance rPC, load rINST 2763 GET_INST_OPCODE ip // extract opcode from rINST 2764 GOTO_OPCODE ip // jump to next instruction 2765 2766 NAME_END nterp_op_filled_new_array_range 2767 // Advance to the end of this handler. Causes error if we are past that point. 2768 .org nterp_op_filled_new_array_range + NTERP_HANDLER_SIZE // op_filled_new_array_range handler is too big! 2769 2770/* ------------------------------ */ 2771 .balign NTERP_HANDLER_SIZE 2772.L_op_fill_array_data: /* 0x26 */ 2773 NAME_START nterp_op_fill_array_data 2774 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2775 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2776 2777 /* fill-array-data vAA, +BBBBBBBB */ 2778 EXPORT_PC 2779 FETCH w0, 1 // x0<- 000000000000bbbb (lo) 2780 FETCH_S x1, 2 // x1<- ssssssssssssBBBB (hi) 2781 lsr w3, wINST, #8 // w3<- AA 2782 orr x0, x0, x1, lsl #16 // x0<- ssssssssBBBBbbbb 2783 GET_VREG w1, w3 // w1<- vAA (array object) 2784 add x0, xPC, x0, lsl #1 // x0<- PC + ssssssssBBBBbbbb*2 (array data off.) 2785 bl art_quick_handle_fill_data 2786 FETCH_ADVANCE_INST 3 // advance rPC, load rINST 2787 GET_INST_OPCODE ip // extract opcode from rINST 2788 GOTO_OPCODE ip // jump to next instruction 2789 2790 NAME_END nterp_op_fill_array_data 2791 // Advance to the end of this handler. Causes error if we are past that point. 2792 .org nterp_op_fill_array_data + NTERP_HANDLER_SIZE // op_fill_array_data handler is too big! 2793 2794/* ------------------------------ */ 2795 .balign NTERP_HANDLER_SIZE 2796.L_op_throw: /* 0x27 */ 2797 NAME_START nterp_op_throw 2798 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2799 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2800 2801 EXPORT_PC 2802 lsr w2, wINST, #8 // r2<- AA 2803 GET_VREG w0, w2 // r0<- vAA (exception object) 2804 mov x1, xSELF 2805 bl art_quick_deliver_exception 2806 brk 0 2807 NAME_END nterp_op_throw 2808 // Advance to the end of this handler. Causes error if we are past that point. 2809 .org nterp_op_throw + NTERP_HANDLER_SIZE // op_throw handler is too big! 2810 2811/* ------------------------------ */ 2812 .balign NTERP_HANDLER_SIZE 2813.L_op_goto: /* 0x28 */ 2814 NAME_START nterp_op_goto 2815 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2816 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2817 2818/* 2819 * Unconditional branch, 8-bit offset. 2820 * 2821 * The branch distance is a signed code-unit offset, which we need to 2822 * double to get a byte offset. 2823 */ 2824 /* goto +AA */ 2825 sbfx wINST, wINST, #8, #8 // wINST<- ssssssAA (sign-extended) 2826 BRANCH 2827 2828 NAME_END nterp_op_goto 2829 // Advance to the end of this handler. Causes error if we are past that point. 2830 .org nterp_op_goto + NTERP_HANDLER_SIZE // op_goto handler is too big! 2831 2832/* ------------------------------ */ 2833 .balign NTERP_HANDLER_SIZE 2834.L_op_goto_16: /* 0x29 */ 2835 NAME_START nterp_op_goto_16 2836 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2837 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2838 2839/* 2840 * Unconditional branch, 16-bit offset. 2841 * 2842 * The branch distance is a signed code-unit offset, which we need to 2843 * double to get a byte offset. 2844 */ 2845 /* goto/16 +AAAA */ 2846 FETCH_S wINST, 1 // wINST<- ssssAAAA (sign-extended) 2847 BRANCH 2848 2849 NAME_END nterp_op_goto_16 2850 // Advance to the end of this handler. Causes error if we are past that point. 2851 .org nterp_op_goto_16 + NTERP_HANDLER_SIZE // op_goto_16 handler is too big! 2852 2853/* ------------------------------ */ 2854 .balign NTERP_HANDLER_SIZE 2855.L_op_goto_32: /* 0x2a */ 2856 NAME_START nterp_op_goto_32 2857 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2858 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2859 2860/* 2861 * Unconditional branch, 32-bit offset. 2862 * 2863 * The branch distance is a signed code-unit offset, which we need to 2864 * double to get a byte offset. 2865 * 2866 * Because we need the SF bit set, we'll use an adds 2867 * to convert from Dalvik offset to byte offset. 2868 */ 2869 /* goto/32 +AAAAAAAA */ 2870 FETCH w0, 1 // w0<- aaaa (lo) 2871 FETCH w1, 2 // w1<- AAAA (hi) 2872 orr wINST, w0, w1, lsl #16 // wINST<- AAAAaaaa 2873 BRANCH 2874 2875 NAME_END nterp_op_goto_32 2876 // Advance to the end of this handler. Causes error if we are past that point. 2877 .org nterp_op_goto_32 + NTERP_HANDLER_SIZE // op_goto_32 handler is too big! 2878 2879/* ------------------------------ */ 2880 .balign NTERP_HANDLER_SIZE 2881.L_op_packed_switch: /* 0x2b */ 2882 NAME_START nterp_op_packed_switch 2883 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2884 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2885 2886/* 2887 * Handle a packed-switch or sparse-switch instruction. In both cases 2888 * we decode it and hand it off to a helper function. 2889 * 2890 * We don't really expect backward branches in a switch statement, but 2891 * they're perfectly legal, so we check for them here. 2892 * 2893 * for: packed-switch, sparse-switch 2894 */ 2895 /* op vAA, +BBBB */ 2896 FETCH w0, 1 // x0<- 000000000000bbbb (lo) 2897 FETCH_S x1, 2 // x1<- ssssssssssssBBBB (hi) 2898 lsr w3, wINST, #8 // w3<- AA 2899 orr x0, x0, x1, lsl #16 // x0<- ssssssssBBBBbbbb 2900 GET_VREG w1, w3 // w1<- vAA 2901 add x0, xPC, x0, lsl #1 // x0<- PC + ssssssssBBBBbbbb*2 2902 bl NterpDoPackedSwitch // w0<- code-unit branch offset 2903 sxtw xINST, w0 2904 BRANCH 2905 2906 NAME_END nterp_op_packed_switch 2907 // Advance to the end of this handler. Causes error if we are past that point. 2908 .org nterp_op_packed_switch + NTERP_HANDLER_SIZE // op_packed_switch handler is too big! 2909 2910/* ------------------------------ */ 2911 .balign NTERP_HANDLER_SIZE 2912.L_op_sparse_switch: /* 0x2c */ 2913 NAME_START nterp_op_sparse_switch 2914 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2915 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2916 2917/* 2918 * Handle a packed-switch or sparse-switch instruction. In both cases 2919 * we decode it and hand it off to a helper function. 2920 * 2921 * We don't really expect backward branches in a switch statement, but 2922 * they're perfectly legal, so we check for them here. 2923 * 2924 * for: packed-switch, sparse-switch 2925 */ 2926 /* op vAA, +BBBB */ 2927 FETCH w0, 1 // x0<- 000000000000bbbb (lo) 2928 FETCH_S x1, 2 // x1<- ssssssssssssBBBB (hi) 2929 lsr w3, wINST, #8 // w3<- AA 2930 orr x0, x0, x1, lsl #16 // x0<- ssssssssBBBBbbbb 2931 GET_VREG w1, w3 // w1<- vAA 2932 add x0, xPC, x0, lsl #1 // x0<- PC + ssssssssBBBBbbbb*2 2933 bl NterpDoSparseSwitch // w0<- code-unit branch offset 2934 sxtw xINST, w0 2935 BRANCH 2936 2937/* 2938 * Return a 32-bit value. 2939 */ 2940 NAME_END nterp_op_sparse_switch 2941 // Advance to the end of this handler. Causes error if we are past that point. 2942 .org nterp_op_sparse_switch + NTERP_HANDLER_SIZE // op_sparse_switch handler is too big! 2943 2944/* ------------------------------ */ 2945 .balign NTERP_HANDLER_SIZE 2946.L_op_cmpl_float: /* 0x2d */ 2947 NAME_START nterp_op_cmpl_float 2948 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2949 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2950 2951 /* 2952 * Compare two floating-point values. Puts 0, 1, or -1 into the 2953 * destination register based on the results of the comparison. 2954 */ 2955 /* op vAA, vBB, vCC */ 2956 FETCH w0, 1 // w0<- CCBB 2957 lsr w4, wINST, #8 // w4<- AA 2958 and w2, w0, #255 // w2<- BB 2959 lsr w3, w0, #8 // w3<- CC 2960 GET_VREG s1, w2 2961 GET_VREG s2, w3 2962 fcmp s1, s2 2963 cset w0, ne 2964 cneg w0, w0, lt 2965 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 2966 GET_INST_OPCODE ip // extract opcode from rINST 2967 SET_VREG w0, w4 // vAA<- w0 2968 GOTO_OPCODE ip // jump to next instruction 2969 2970 NAME_END nterp_op_cmpl_float 2971 // Advance to the end of this handler. Causes error if we are past that point. 2972 .org nterp_op_cmpl_float + NTERP_HANDLER_SIZE // op_cmpl_float handler is too big! 2973 2974/* ------------------------------ */ 2975 .balign NTERP_HANDLER_SIZE 2976.L_op_cmpg_float: /* 0x2e */ 2977 NAME_START nterp_op_cmpg_float 2978 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 2979 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 2980 2981 /* 2982 * Compare two floating-point values. Puts 0, 1, or -1 into the 2983 * destination register based on the results of the comparison. 2984 */ 2985 /* op vAA, vBB, vCC */ 2986 FETCH w0, 1 // w0<- CCBB 2987 lsr w4, wINST, #8 // w4<- AA 2988 and w2, w0, #255 // w2<- BB 2989 lsr w3, w0, #8 // w3<- CC 2990 GET_VREG s1, w2 2991 GET_VREG s2, w3 2992 fcmp s1, s2 2993 cset w0, ne 2994 cneg w0, w0, cc 2995 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 2996 GET_INST_OPCODE ip // extract opcode from rINST 2997 SET_VREG w0, w4 // vAA<- w0 2998 GOTO_OPCODE ip // jump to next instruction 2999 3000 NAME_END nterp_op_cmpg_float 3001 // Advance to the end of this handler. Causes error if we are past that point. 3002 .org nterp_op_cmpg_float + NTERP_HANDLER_SIZE // op_cmpg_float handler is too big! 3003 3004/* ------------------------------ */ 3005 .balign NTERP_HANDLER_SIZE 3006.L_op_cmpl_double: /* 0x2f */ 3007 NAME_START nterp_op_cmpl_double 3008 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3009 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3010 3011 /* 3012 * Compare two floating-point values. Puts 0, 1, or -1 into the 3013 * destination register based on the results of the comparison. 3014 */ 3015 /* op vAA, vBB, vCC */ 3016 FETCH w0, 1 // w0<- CCBB 3017 LOAD_SCALED_VREG_MASK w5, 0xff // w4<- ff * sizeof(vreg) 3018 lsr w4, wINST, #8 // w4<- AA 3019 EXTRACT_SCALED_VREG w2, w5, w0, 0 // w2<- BB * sizeof(vreg) 3020 EXTRACT_SCALED_VREG w3, w5, w0, 8 // w3<- CC * sizeof(vreg) 3021 GET_VREG_DOUBLE_PRESCALED d1, w2 3022 GET_VREG_DOUBLE_PRESCALED d2, w3 3023 fcmp d1, d2 3024 cset w0, ne 3025 cneg w0, w0, lt 3026 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 3027 GET_INST_OPCODE ip // extract opcode from rINST 3028 SET_VREG w0, w4 // vAA<- w0 3029 GOTO_OPCODE ip // jump to next instruction 3030 3031 NAME_END nterp_op_cmpl_double 3032 // Advance to the end of this handler. Causes error if we are past that point. 3033 .org nterp_op_cmpl_double + NTERP_HANDLER_SIZE // op_cmpl_double handler is too big! 3034 3035/* ------------------------------ */ 3036 .balign NTERP_HANDLER_SIZE 3037.L_op_cmpg_double: /* 0x30 */ 3038 NAME_START nterp_op_cmpg_double 3039 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3040 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3041 3042 /* 3043 * Compare two floating-point values. Puts 0, 1, or -1 into the 3044 * destination register based on the results of the comparison. 3045 */ 3046 /* op vAA, vBB, vCC */ 3047 FETCH w0, 1 // w0<- CCBB 3048 LOAD_SCALED_VREG_MASK w5, 0xff // w4<- ff * sizeof(vreg) 3049 lsr w4, wINST, #8 // w4<- AA 3050 EXTRACT_SCALED_VREG w2, w5, w0, 0 // w2<- BB * sizeof(vreg) 3051 EXTRACT_SCALED_VREG w3, w5, w0, 8 // w3<- CC * sizeof(vreg) 3052 GET_VREG_DOUBLE_PRESCALED d1, w2 3053 GET_VREG_DOUBLE_PRESCALED d2, w3 3054 fcmp d1, d2 3055 cset w0, ne 3056 cneg w0, w0, cc 3057 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 3058 GET_INST_OPCODE ip // extract opcode from rINST 3059 SET_VREG w0, w4 // vAA<- w0 3060 GOTO_OPCODE ip // jump to next instruction 3061 3062 NAME_END nterp_op_cmpg_double 3063 // Advance to the end of this handler. Causes error if we are past that point. 3064 .org nterp_op_cmpg_double + NTERP_HANDLER_SIZE // op_cmpg_double handler is too big! 3065 3066/* ------------------------------ */ 3067 .balign NTERP_HANDLER_SIZE 3068.L_op_cmp_long: /* 0x31 */ 3069 NAME_START nterp_op_cmp_long 3070 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3071 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3072 3073 FETCH w0, 1 // w0<- CCBB 3074 LOAD_SCALED_VREG_MASK w5, 0xff // w4<- ff * sizeof(vreg) 3075 lsr w4, wINST, #8 // w4<- AA 3076 EXTRACT_SCALED_VREG w2, w5, w0, 0 // w2<- BB * sizeof(vreg) 3077 EXTRACT_SCALED_VREG w3, w5, w0, 8 // w3<- CC * sizeof(vreg) 3078 GET_VREG_WIDE_PRESCALED x1, w2 3079 GET_VREG_WIDE_PRESCALED x2, w3 3080 cmp x1, x2 3081 cset w0, ne 3082 cneg w0, w0, lt 3083 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 3084 SET_VREG w0, w4 3085 GET_INST_OPCODE ip // extract opcode from wINST 3086 GOTO_OPCODE ip // jump to next instruction 3087 3088 NAME_END nterp_op_cmp_long 3089 // Advance to the end of this handler. Causes error if we are past that point. 3090 .org nterp_op_cmp_long + NTERP_HANDLER_SIZE // op_cmp_long handler is too big! 3091 3092/* ------------------------------ */ 3093 .balign NTERP_HANDLER_SIZE 3094.L_op_if_eq: /* 0x32 */ 3095 NAME_START nterp_op_if_eq 3096 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3097 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3098 3099 /* 3100 * Generic two-operand compare-and-branch operation. Provide a "condition" 3101 * fragment that specifies the comparison to perform. 3102 * 3103 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 3104 */ 3105 /* if-cmp vA, vB, +CCCC */ 3106 lsr w1, wINST, #12 // w1<- B 3107 ubfx w0, wINST, #8, #4 // w0<- A 3108 GET_VREG w3, w1 // w3<- vB 3109 GET_VREG w2, w0 // w2<- vA 3110 cmp w2, w3 // compare (vA, vB) 3111 b.eq 1f 3112 FETCH_ADVANCE_INST 2 3113 GET_INST_OPCODE ip // extract opcode from wINST 3114 GOTO_OPCODE ip // jump to next instruction 31151: 3116 FETCH_S wINST, 1 // wINST<- branch offset, in code units 3117 BRANCH 3118 3119 NAME_END nterp_op_if_eq 3120 // Advance to the end of this handler. Causes error if we are past that point. 3121 .org nterp_op_if_eq + NTERP_HANDLER_SIZE // op_if_eq handler is too big! 3122 3123/* ------------------------------ */ 3124 .balign NTERP_HANDLER_SIZE 3125.L_op_if_ne: /* 0x33 */ 3126 NAME_START nterp_op_if_ne 3127 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3128 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3129 3130 /* 3131 * Generic two-operand compare-and-branch operation. Provide a "condition" 3132 * fragment that specifies the comparison to perform. 3133 * 3134 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 3135 */ 3136 /* if-cmp vA, vB, +CCCC */ 3137 lsr w1, wINST, #12 // w1<- B 3138 ubfx w0, wINST, #8, #4 // w0<- A 3139 GET_VREG w3, w1 // w3<- vB 3140 GET_VREG w2, w0 // w2<- vA 3141 cmp w2, w3 // compare (vA, vB) 3142 b.ne 1f 3143 FETCH_ADVANCE_INST 2 3144 GET_INST_OPCODE ip // extract opcode from wINST 3145 GOTO_OPCODE ip // jump to next instruction 31461: 3147 FETCH_S wINST, 1 // wINST<- branch offset, in code units 3148 BRANCH 3149 3150 NAME_END nterp_op_if_ne 3151 // Advance to the end of this handler. Causes error if we are past that point. 3152 .org nterp_op_if_ne + NTERP_HANDLER_SIZE // op_if_ne handler is too big! 3153 3154/* ------------------------------ */ 3155 .balign NTERP_HANDLER_SIZE 3156.L_op_if_lt: /* 0x34 */ 3157 NAME_START nterp_op_if_lt 3158 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3159 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3160 3161 /* 3162 * Generic two-operand compare-and-branch operation. Provide a "condition" 3163 * fragment that specifies the comparison to perform. 3164 * 3165 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 3166 */ 3167 /* if-cmp vA, vB, +CCCC */ 3168 lsr w1, wINST, #12 // w1<- B 3169 ubfx w0, wINST, #8, #4 // w0<- A 3170 GET_VREG w3, w1 // w3<- vB 3171 GET_VREG w2, w0 // w2<- vA 3172 cmp w2, w3 // compare (vA, vB) 3173 b.lt 1f 3174 FETCH_ADVANCE_INST 2 3175 GET_INST_OPCODE ip // extract opcode from wINST 3176 GOTO_OPCODE ip // jump to next instruction 31771: 3178 FETCH_S wINST, 1 // wINST<- branch offset, in code units 3179 BRANCH 3180 3181 NAME_END nterp_op_if_lt 3182 // Advance to the end of this handler. Causes error if we are past that point. 3183 .org nterp_op_if_lt + NTERP_HANDLER_SIZE // op_if_lt handler is too big! 3184 3185/* ------------------------------ */ 3186 .balign NTERP_HANDLER_SIZE 3187.L_op_if_ge: /* 0x35 */ 3188 NAME_START nterp_op_if_ge 3189 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3190 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3191 3192 /* 3193 * Generic two-operand compare-and-branch operation. Provide a "condition" 3194 * fragment that specifies the comparison to perform. 3195 * 3196 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 3197 */ 3198 /* if-cmp vA, vB, +CCCC */ 3199 lsr w1, wINST, #12 // w1<- B 3200 ubfx w0, wINST, #8, #4 // w0<- A 3201 GET_VREG w3, w1 // w3<- vB 3202 GET_VREG w2, w0 // w2<- vA 3203 cmp w2, w3 // compare (vA, vB) 3204 b.ge 1f 3205 FETCH_ADVANCE_INST 2 3206 GET_INST_OPCODE ip // extract opcode from wINST 3207 GOTO_OPCODE ip // jump to next instruction 32081: 3209 FETCH_S wINST, 1 // wINST<- branch offset, in code units 3210 BRANCH 3211 3212 NAME_END nterp_op_if_ge 3213 // Advance to the end of this handler. Causes error if we are past that point. 3214 .org nterp_op_if_ge + NTERP_HANDLER_SIZE // op_if_ge handler is too big! 3215 3216/* ------------------------------ */ 3217 .balign NTERP_HANDLER_SIZE 3218.L_op_if_gt: /* 0x36 */ 3219 NAME_START nterp_op_if_gt 3220 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3221 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3222 3223 /* 3224 * Generic two-operand compare-and-branch operation. Provide a "condition" 3225 * fragment that specifies the comparison to perform. 3226 * 3227 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 3228 */ 3229 /* if-cmp vA, vB, +CCCC */ 3230 lsr w1, wINST, #12 // w1<- B 3231 ubfx w0, wINST, #8, #4 // w0<- A 3232 GET_VREG w3, w1 // w3<- vB 3233 GET_VREG w2, w0 // w2<- vA 3234 cmp w2, w3 // compare (vA, vB) 3235 b.gt 1f 3236 FETCH_ADVANCE_INST 2 3237 GET_INST_OPCODE ip // extract opcode from wINST 3238 GOTO_OPCODE ip // jump to next instruction 32391: 3240 FETCH_S wINST, 1 // wINST<- branch offset, in code units 3241 BRANCH 3242 3243 NAME_END nterp_op_if_gt 3244 // Advance to the end of this handler. Causes error if we are past that point. 3245 .org nterp_op_if_gt + NTERP_HANDLER_SIZE // op_if_gt handler is too big! 3246 3247/* ------------------------------ */ 3248 .balign NTERP_HANDLER_SIZE 3249.L_op_if_le: /* 0x37 */ 3250 NAME_START nterp_op_if_le 3251 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3252 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3253 3254 /* 3255 * Generic two-operand compare-and-branch operation. Provide a "condition" 3256 * fragment that specifies the comparison to perform. 3257 * 3258 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 3259 */ 3260 /* if-cmp vA, vB, +CCCC */ 3261 lsr w1, wINST, #12 // w1<- B 3262 ubfx w0, wINST, #8, #4 // w0<- A 3263 GET_VREG w3, w1 // w3<- vB 3264 GET_VREG w2, w0 // w2<- vA 3265 cmp w2, w3 // compare (vA, vB) 3266 b.le 1f 3267 FETCH_ADVANCE_INST 2 3268 GET_INST_OPCODE ip // extract opcode from wINST 3269 GOTO_OPCODE ip // jump to next instruction 32701: 3271 FETCH_S wINST, 1 // wINST<- branch offset, in code units 3272 BRANCH 3273 3274 NAME_END nterp_op_if_le 3275 // Advance to the end of this handler. Causes error if we are past that point. 3276 .org nterp_op_if_le + NTERP_HANDLER_SIZE // op_if_le handler is too big! 3277 3278/* ------------------------------ */ 3279 .balign NTERP_HANDLER_SIZE 3280.L_op_if_eqz: /* 0x38 */ 3281 NAME_START nterp_op_if_eqz 3282 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3283 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3284 3285 /* 3286 * Generic one-operand compare-and-branch operation. Provide a "condition" 3287 * fragment that specifies the comparison to perform. 3288 * 3289 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 3290 */ 3291 /* if-cmp vAA, +BBBB */ 3292 lsr w0, wINST, #8 // w0<- AA 3293 GET_VREG w2, w0 // w2<- vAA 3294 .if 0 3295 cmp w2, #0 // compare (vA, 0) 3296 .endif 3297 cbz w2, 1f 3298 FETCH_ADVANCE_INST 2 3299 GET_INST_OPCODE ip // extract opcode from wINST 3300 GOTO_OPCODE ip // jump to next instruction 33011: 3302 FETCH_S wINST, 1 // w1<- branch offset, in code units 3303 BRANCH 3304 3305 NAME_END nterp_op_if_eqz 3306 // Advance to the end of this handler. Causes error if we are past that point. 3307 .org nterp_op_if_eqz + NTERP_HANDLER_SIZE // op_if_eqz handler is too big! 3308 3309/* ------------------------------ */ 3310 .balign NTERP_HANDLER_SIZE 3311.L_op_if_nez: /* 0x39 */ 3312 NAME_START nterp_op_if_nez 3313 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3314 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3315 3316 /* 3317 * Generic one-operand compare-and-branch operation. Provide a "condition" 3318 * fragment that specifies the comparison to perform. 3319 * 3320 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 3321 */ 3322 /* if-cmp vAA, +BBBB */ 3323 lsr w0, wINST, #8 // w0<- AA 3324 GET_VREG w2, w0 // w2<- vAA 3325 .if 0 3326 cmp w2, #0 // compare (vA, 0) 3327 .endif 3328 cbnz w2, 1f 3329 FETCH_ADVANCE_INST 2 3330 GET_INST_OPCODE ip // extract opcode from wINST 3331 GOTO_OPCODE ip // jump to next instruction 33321: 3333 FETCH_S wINST, 1 // w1<- branch offset, in code units 3334 BRANCH 3335 3336 NAME_END nterp_op_if_nez 3337 // Advance to the end of this handler. Causes error if we are past that point. 3338 .org nterp_op_if_nez + NTERP_HANDLER_SIZE // op_if_nez handler is too big! 3339 3340/* ------------------------------ */ 3341 .balign NTERP_HANDLER_SIZE 3342.L_op_if_ltz: /* 0x3a */ 3343 NAME_START nterp_op_if_ltz 3344 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3345 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3346 3347 /* 3348 * Generic one-operand compare-and-branch operation. Provide a "condition" 3349 * fragment that specifies the comparison to perform. 3350 * 3351 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 3352 */ 3353 /* if-cmp vAA, +BBBB */ 3354 lsr w0, wINST, #8 // w0<- AA 3355 GET_VREG w2, w0 // w2<- vAA 3356 .if 0 3357 cmp w2, #0 // compare (vA, 0) 3358 .endif 3359 tbnz w2, #31, 1f 3360 FETCH_ADVANCE_INST 2 3361 GET_INST_OPCODE ip // extract opcode from wINST 3362 GOTO_OPCODE ip // jump to next instruction 33631: 3364 FETCH_S wINST, 1 // w1<- branch offset, in code units 3365 BRANCH 3366 3367 NAME_END nterp_op_if_ltz 3368 // Advance to the end of this handler. Causes error if we are past that point. 3369 .org nterp_op_if_ltz + NTERP_HANDLER_SIZE // op_if_ltz handler is too big! 3370 3371/* ------------------------------ */ 3372 .balign NTERP_HANDLER_SIZE 3373.L_op_if_gez: /* 0x3b */ 3374 NAME_START nterp_op_if_gez 3375 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3376 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3377 3378 /* 3379 * Generic one-operand compare-and-branch operation. Provide a "condition" 3380 * fragment that specifies the comparison to perform. 3381 * 3382 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 3383 */ 3384 /* if-cmp vAA, +BBBB */ 3385 lsr w0, wINST, #8 // w0<- AA 3386 GET_VREG w2, w0 // w2<- vAA 3387 .if 0 3388 cmp w2, #0 // compare (vA, 0) 3389 .endif 3390 tbz w2, #31, 1f 3391 FETCH_ADVANCE_INST 2 3392 GET_INST_OPCODE ip // extract opcode from wINST 3393 GOTO_OPCODE ip // jump to next instruction 33941: 3395 FETCH_S wINST, 1 // w1<- branch offset, in code units 3396 BRANCH 3397 3398 NAME_END nterp_op_if_gez 3399 // Advance to the end of this handler. Causes error if we are past that point. 3400 .org nterp_op_if_gez + NTERP_HANDLER_SIZE // op_if_gez handler is too big! 3401 3402/* ------------------------------ */ 3403 .balign NTERP_HANDLER_SIZE 3404.L_op_if_gtz: /* 0x3c */ 3405 NAME_START nterp_op_if_gtz 3406 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3407 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3408 3409 /* 3410 * Generic one-operand compare-and-branch operation. Provide a "condition" 3411 * fragment that specifies the comparison to perform. 3412 * 3413 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 3414 */ 3415 /* if-cmp vAA, +BBBB */ 3416 lsr w0, wINST, #8 // w0<- AA 3417 GET_VREG w2, w0 // w2<- vAA 3418 .if 1 3419 cmp w2, #0 // compare (vA, 0) 3420 .endif 3421 b.gt 1f 3422 FETCH_ADVANCE_INST 2 3423 GET_INST_OPCODE ip // extract opcode from wINST 3424 GOTO_OPCODE ip // jump to next instruction 34251: 3426 FETCH_S wINST, 1 // w1<- branch offset, in code units 3427 BRANCH 3428 3429 NAME_END nterp_op_if_gtz 3430 // Advance to the end of this handler. Causes error if we are past that point. 3431 .org nterp_op_if_gtz + NTERP_HANDLER_SIZE // op_if_gtz handler is too big! 3432 3433/* ------------------------------ */ 3434 .balign NTERP_HANDLER_SIZE 3435.L_op_if_lez: /* 0x3d */ 3436 NAME_START nterp_op_if_lez 3437 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3438 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3439 3440 /* 3441 * Generic one-operand compare-and-branch operation. Provide a "condition" 3442 * fragment that specifies the comparison to perform. 3443 * 3444 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 3445 */ 3446 /* if-cmp vAA, +BBBB */ 3447 lsr w0, wINST, #8 // w0<- AA 3448 GET_VREG w2, w0 // w2<- vAA 3449 .if 1 3450 cmp w2, #0 // compare (vA, 0) 3451 .endif 3452 b.le 1f 3453 FETCH_ADVANCE_INST 2 3454 GET_INST_OPCODE ip // extract opcode from wINST 3455 GOTO_OPCODE ip // jump to next instruction 34561: 3457 FETCH_S wINST, 1 // w1<- branch offset, in code units 3458 BRANCH 3459 3460 NAME_END nterp_op_if_lez 3461 // Advance to the end of this handler. Causes error if we are past that point. 3462 .org nterp_op_if_lez + NTERP_HANDLER_SIZE // op_if_lez handler is too big! 3463 3464/* ------------------------------ */ 3465 .balign NTERP_HANDLER_SIZE 3466.L_op_unused_3e: /* 0x3e */ 3467 NAME_START nterp_op_unused_3e 3468 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3469 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3470 3471 brk 42 3472 3473 NAME_END nterp_op_unused_3e 3474 // Advance to the end of this handler. Causes error if we are past that point. 3475 .org nterp_op_unused_3e + NTERP_HANDLER_SIZE // op_unused_3e handler is too big! 3476 3477/* ------------------------------ */ 3478 .balign NTERP_HANDLER_SIZE 3479.L_op_unused_3f: /* 0x3f */ 3480 NAME_START nterp_op_unused_3f 3481 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3482 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3483 3484 brk 42 3485 3486 NAME_END nterp_op_unused_3f 3487 // Advance to the end of this handler. Causes error if we are past that point. 3488 .org nterp_op_unused_3f + NTERP_HANDLER_SIZE // op_unused_3f handler is too big! 3489 3490/* ------------------------------ */ 3491 .balign NTERP_HANDLER_SIZE 3492.L_op_unused_40: /* 0x40 */ 3493 NAME_START nterp_op_unused_40 3494 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3495 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3496 3497 brk 42 3498 3499 NAME_END nterp_op_unused_40 3500 // Advance to the end of this handler. Causes error if we are past that point. 3501 .org nterp_op_unused_40 + NTERP_HANDLER_SIZE // op_unused_40 handler is too big! 3502 3503/* ------------------------------ */ 3504 .balign NTERP_HANDLER_SIZE 3505.L_op_unused_41: /* 0x41 */ 3506 NAME_START nterp_op_unused_41 3507 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3508 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3509 3510 brk 42 3511 3512 NAME_END nterp_op_unused_41 3513 // Advance to the end of this handler. Causes error if we are past that point. 3514 .org nterp_op_unused_41 + NTERP_HANDLER_SIZE // op_unused_41 handler is too big! 3515 3516/* ------------------------------ */ 3517 .balign NTERP_HANDLER_SIZE 3518.L_op_unused_42: /* 0x42 */ 3519 NAME_START nterp_op_unused_42 3520 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3521 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3522 3523 brk 42 3524 3525 NAME_END nterp_op_unused_42 3526 // Advance to the end of this handler. Causes error if we are past that point. 3527 .org nterp_op_unused_42 + NTERP_HANDLER_SIZE // op_unused_42 handler is too big! 3528 3529/* ------------------------------ */ 3530 .balign NTERP_HANDLER_SIZE 3531.L_op_unused_43: /* 0x43 */ 3532 NAME_START nterp_op_unused_43 3533 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3534 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3535 3536 brk 42 3537 3538 NAME_END nterp_op_unused_43 3539 // Advance to the end of this handler. Causes error if we are past that point. 3540 .org nterp_op_unused_43 + NTERP_HANDLER_SIZE // op_unused_43 handler is too big! 3541 3542/* ------------------------------ */ 3543 .balign NTERP_HANDLER_SIZE 3544.L_op_aget: /* 0x44 */ 3545 NAME_START nterp_op_aget 3546 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3547 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3548 3549/* 3550 * Array get. vAA <- vBB[vCC]. 3551 * 3552 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object 3553 * 3554 */ 3555 FETCH_B w2, 1, 0 // w2<- BB 3556 lsr w9, wINST, #8 // w9<- AA 3557 FETCH_B w3, 1, 1 // w3<- CC 3558 GET_VREG w0, w2 // w0<- vBB (array object) 3559 GET_VREG w1, w3 // w1<- vCC (requested index) 3560 cbz x0, common_errNullObject // bail if null array object. 3561 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 3562 add x0, x0, w1, uxtw #2 // w0<- arrayObj + index*width 3563 cmp w1, w3 // compare unsigned index, length 3564 bcs common_errArrayIndex // index >= length, bail 3565 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 3566 GET_INST_OPCODE x10 // extract opcode from wINST 3567 .if 0 3568 ldr x2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET] // x2<- vBB[vCC] 3569 SET_VREG_WIDE x2, w9 3570 GOTO_OPCODE x10 // jump to next instruction 3571 .elseif 0 3572 ldr w2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3573 UNPOISON_HEAP_REF w2 3574 TEST_IF_MARKING 2f 35751: 3576 SET_VREG_OBJECT w2, w9 // vAA<- w2 3577 GOTO_OPCODE x10 // jump to next instruction 35782: 3579 bl art_quick_read_barrier_mark_reg02 3580 b 1b 3581 .else 3582 ldr w2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3583 SET_VREG w2, w9 // vAA<- w2 3584 GOTO_OPCODE x10 // jump to next instruction 3585 .endif 3586 3587 NAME_END nterp_op_aget 3588 // Advance to the end of this handler. Causes error if we are past that point. 3589 .org nterp_op_aget + NTERP_HANDLER_SIZE // op_aget handler is too big! 3590 3591/* ------------------------------ */ 3592 .balign NTERP_HANDLER_SIZE 3593.L_op_aget_wide: /* 0x45 */ 3594 NAME_START nterp_op_aget_wide 3595 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3596 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3597 3598/* 3599 * Array get. vAA <- vBB[vCC]. 3600 * 3601 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object 3602 * 3603 */ 3604 FETCH_B w2, 1, 0 // w2<- BB 3605 lsr w9, wINST, #8 // w9<- AA 3606 FETCH_B w3, 1, 1 // w3<- CC 3607 GET_VREG w0, w2 // w0<- vBB (array object) 3608 GET_VREG w1, w3 // w1<- vCC (requested index) 3609 cbz x0, common_errNullObject // bail if null array object. 3610 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 3611 add x0, x0, w1, uxtw #3 // w0<- arrayObj + index*width 3612 cmp w1, w3 // compare unsigned index, length 3613 bcs common_errArrayIndex // index >= length, bail 3614 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 3615 GET_INST_OPCODE x10 // extract opcode from wINST 3616 .if 1 3617 ldr x2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET] // x2<- vBB[vCC] 3618 SET_VREG_WIDE x2, w9 3619 GOTO_OPCODE x10 // jump to next instruction 3620 .elseif 0 3621 ldr w2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3622 UNPOISON_HEAP_REF w2 3623 TEST_IF_MARKING 2f 36241: 3625 SET_VREG_OBJECT w2, w9 // vAA<- w2 3626 GOTO_OPCODE x10 // jump to next instruction 36272: 3628 bl art_quick_read_barrier_mark_reg02 3629 b 1b 3630 .else 3631 ldr w2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3632 SET_VREG w2, w9 // vAA<- w2 3633 GOTO_OPCODE x10 // jump to next instruction 3634 .endif 3635 3636 NAME_END nterp_op_aget_wide 3637 // Advance to the end of this handler. Causes error if we are past that point. 3638 .org nterp_op_aget_wide + NTERP_HANDLER_SIZE // op_aget_wide handler is too big! 3639 3640/* ------------------------------ */ 3641 .balign NTERP_HANDLER_SIZE 3642.L_op_aget_object: /* 0x46 */ 3643 NAME_START nterp_op_aget_object 3644 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3645 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3646 3647/* 3648 * Array get. vAA <- vBB[vCC]. 3649 * 3650 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object 3651 * 3652 */ 3653 FETCH_B w2, 1, 0 // w2<- BB 3654 lsr w9, wINST, #8 // w9<- AA 3655 FETCH_B w3, 1, 1 // w3<- CC 3656 GET_VREG w0, w2 // w0<- vBB (array object) 3657 GET_VREG w1, w3 // w1<- vCC (requested index) 3658 cbz x0, common_errNullObject // bail if null array object. 3659 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 3660 add x0, x0, w1, uxtw #2 // w0<- arrayObj + index*width 3661 cmp w1, w3 // compare unsigned index, length 3662 bcs common_errArrayIndex // index >= length, bail 3663 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 3664 GET_INST_OPCODE x10 // extract opcode from wINST 3665 .if 0 3666 ldr x2, [x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET] // x2<- vBB[vCC] 3667 SET_VREG_WIDE x2, w9 3668 GOTO_OPCODE x10 // jump to next instruction 3669 .elseif 1 3670 ldr w2, [x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3671 UNPOISON_HEAP_REF w2 3672 TEST_IF_MARKING 2f 36731: 3674 SET_VREG_OBJECT w2, w9 // vAA<- w2 3675 GOTO_OPCODE x10 // jump to next instruction 36762: 3677 bl art_quick_read_barrier_mark_reg02 3678 b 1b 3679 .else 3680 ldr w2, [x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3681 SET_VREG w2, w9 // vAA<- w2 3682 GOTO_OPCODE x10 // jump to next instruction 3683 .endif 3684 3685 NAME_END nterp_op_aget_object 3686 // Advance to the end of this handler. Causes error if we are past that point. 3687 .org nterp_op_aget_object + NTERP_HANDLER_SIZE // op_aget_object handler is too big! 3688 3689/* ------------------------------ */ 3690 .balign NTERP_HANDLER_SIZE 3691.L_op_aget_boolean: /* 0x47 */ 3692 NAME_START nterp_op_aget_boolean 3693 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3694 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3695 3696/* 3697 * Array get. vAA <- vBB[vCC]. 3698 * 3699 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object 3700 * 3701 */ 3702 FETCH_B w2, 1, 0 // w2<- BB 3703 lsr w9, wINST, #8 // w9<- AA 3704 FETCH_B w3, 1, 1 // w3<- CC 3705 GET_VREG w0, w2 // w0<- vBB (array object) 3706 GET_VREG w1, w3 // w1<- vCC (requested index) 3707 cbz x0, common_errNullObject // bail if null array object. 3708 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 3709 add x0, x0, w1, uxtw #0 // w0<- arrayObj + index*width 3710 cmp w1, w3 // compare unsigned index, length 3711 bcs common_errArrayIndex // index >= length, bail 3712 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 3713 GET_INST_OPCODE x10 // extract opcode from wINST 3714 .if 0 3715 ldr x2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET] // x2<- vBB[vCC] 3716 SET_VREG_WIDE x2, w9 3717 GOTO_OPCODE x10 // jump to next instruction 3718 .elseif 0 3719 ldrb w2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3720 UNPOISON_HEAP_REF w2 3721 TEST_IF_MARKING 2f 37221: 3723 SET_VREG_OBJECT w2, w9 // vAA<- w2 3724 GOTO_OPCODE x10 // jump to next instruction 37252: 3726 bl art_quick_read_barrier_mark_reg02 3727 b 1b 3728 .else 3729 ldrb w2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3730 SET_VREG w2, w9 // vAA<- w2 3731 GOTO_OPCODE x10 // jump to next instruction 3732 .endif 3733 3734 NAME_END nterp_op_aget_boolean 3735 // Advance to the end of this handler. Causes error if we are past that point. 3736 .org nterp_op_aget_boolean + NTERP_HANDLER_SIZE // op_aget_boolean handler is too big! 3737 3738/* ------------------------------ */ 3739 .balign NTERP_HANDLER_SIZE 3740.L_op_aget_byte: /* 0x48 */ 3741 NAME_START nterp_op_aget_byte 3742 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3743 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3744 3745/* 3746 * Array get. vAA <- vBB[vCC]. 3747 * 3748 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object 3749 * 3750 */ 3751 FETCH_B w2, 1, 0 // w2<- BB 3752 lsr w9, wINST, #8 // w9<- AA 3753 FETCH_B w3, 1, 1 // w3<- CC 3754 GET_VREG w0, w2 // w0<- vBB (array object) 3755 GET_VREG w1, w3 // w1<- vCC (requested index) 3756 cbz x0, common_errNullObject // bail if null array object. 3757 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 3758 add x0, x0, w1, uxtw #0 // w0<- arrayObj + index*width 3759 cmp w1, w3 // compare unsigned index, length 3760 bcs common_errArrayIndex // index >= length, bail 3761 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 3762 GET_INST_OPCODE x10 // extract opcode from wINST 3763 .if 0 3764 ldr x2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET] // x2<- vBB[vCC] 3765 SET_VREG_WIDE x2, w9 3766 GOTO_OPCODE x10 // jump to next instruction 3767 .elseif 0 3768 ldrsb w2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3769 UNPOISON_HEAP_REF w2 3770 TEST_IF_MARKING 2f 37711: 3772 SET_VREG_OBJECT w2, w9 // vAA<- w2 3773 GOTO_OPCODE x10 // jump to next instruction 37742: 3775 bl art_quick_read_barrier_mark_reg02 3776 b 1b 3777 .else 3778 ldrsb w2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3779 SET_VREG w2, w9 // vAA<- w2 3780 GOTO_OPCODE x10 // jump to next instruction 3781 .endif 3782 3783 NAME_END nterp_op_aget_byte 3784 // Advance to the end of this handler. Causes error if we are past that point. 3785 .org nterp_op_aget_byte + NTERP_HANDLER_SIZE // op_aget_byte handler is too big! 3786 3787/* ------------------------------ */ 3788 .balign NTERP_HANDLER_SIZE 3789.L_op_aget_char: /* 0x49 */ 3790 NAME_START nterp_op_aget_char 3791 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3792 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3793 3794/* 3795 * Array get. vAA <- vBB[vCC]. 3796 * 3797 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object 3798 * 3799 */ 3800 FETCH_B w2, 1, 0 // w2<- BB 3801 lsr w9, wINST, #8 // w9<- AA 3802 FETCH_B w3, 1, 1 // w3<- CC 3803 GET_VREG w0, w2 // w0<- vBB (array object) 3804 GET_VREG w1, w3 // w1<- vCC (requested index) 3805 cbz x0, common_errNullObject // bail if null array object. 3806 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 3807 add x0, x0, w1, uxtw #1 // w0<- arrayObj + index*width 3808 cmp w1, w3 // compare unsigned index, length 3809 bcs common_errArrayIndex // index >= length, bail 3810 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 3811 GET_INST_OPCODE x10 // extract opcode from wINST 3812 .if 0 3813 ldr x2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET] // x2<- vBB[vCC] 3814 SET_VREG_WIDE x2, w9 3815 GOTO_OPCODE x10 // jump to next instruction 3816 .elseif 0 3817 ldrh w2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3818 UNPOISON_HEAP_REF w2 3819 TEST_IF_MARKING 2f 38201: 3821 SET_VREG_OBJECT w2, w9 // vAA<- w2 3822 GOTO_OPCODE x10 // jump to next instruction 38232: 3824 bl art_quick_read_barrier_mark_reg02 3825 b 1b 3826 .else 3827 ldrh w2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3828 SET_VREG w2, w9 // vAA<- w2 3829 GOTO_OPCODE x10 // jump to next instruction 3830 .endif 3831 3832 NAME_END nterp_op_aget_char 3833 // Advance to the end of this handler. Causes error if we are past that point. 3834 .org nterp_op_aget_char + NTERP_HANDLER_SIZE // op_aget_char handler is too big! 3835 3836/* ------------------------------ */ 3837 .balign NTERP_HANDLER_SIZE 3838.L_op_aget_short: /* 0x4a */ 3839 NAME_START nterp_op_aget_short 3840 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3841 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3842 3843/* 3844 * Array get. vAA <- vBB[vCC]. 3845 * 3846 * for: aget, aget-boolean, aget-byte, aget-char, aget-short, aget-wide, aget-object 3847 * 3848 */ 3849 FETCH_B w2, 1, 0 // w2<- BB 3850 lsr w9, wINST, #8 // w9<- AA 3851 FETCH_B w3, 1, 1 // w3<- CC 3852 GET_VREG w0, w2 // w0<- vBB (array object) 3853 GET_VREG w1, w3 // w1<- vCC (requested index) 3854 cbz x0, common_errNullObject // bail if null array object. 3855 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 3856 add x0, x0, w1, uxtw #1 // w0<- arrayObj + index*width 3857 cmp w1, w3 // compare unsigned index, length 3858 bcs common_errArrayIndex // index >= length, bail 3859 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 3860 GET_INST_OPCODE x10 // extract opcode from wINST 3861 .if 0 3862 ldr x2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET] // x2<- vBB[vCC] 3863 SET_VREG_WIDE x2, w9 3864 GOTO_OPCODE x10 // jump to next instruction 3865 .elseif 0 3866 ldrsh w2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3867 UNPOISON_HEAP_REF w2 3868 TEST_IF_MARKING 2f 38691: 3870 SET_VREG_OBJECT w2, w9 // vAA<- w2 3871 GOTO_OPCODE x10 // jump to next instruction 38722: 3873 bl art_quick_read_barrier_mark_reg02 3874 b 1b 3875 .else 3876 ldrsh w2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] 3877 SET_VREG w2, w9 // vAA<- w2 3878 GOTO_OPCODE x10 // jump to next instruction 3879 .endif 3880 3881 NAME_END nterp_op_aget_short 3882 // Advance to the end of this handler. Causes error if we are past that point. 3883 .org nterp_op_aget_short + NTERP_HANDLER_SIZE // op_aget_short handler is too big! 3884 3885/* ------------------------------ */ 3886 .balign NTERP_HANDLER_SIZE 3887.L_op_aput: /* 0x4b */ 3888 NAME_START nterp_op_aput 3889 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3890 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3891 3892/* 3893 * Array put. vBB[vCC] <- vAA. 3894 * 3895 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object 3896 * 3897 */ 3898 FETCH_B w2, 1, 0 // w2<- BB 3899 lsr w9, wINST, #8 // w9<- AA 3900 FETCH_B w3, 1, 1 // w3<- CC 3901 GET_VREG w0, w2 // w0<- vBB (array object) 3902 GET_VREG w1, w3 // w1<- vCC (requested index) 3903 cbz w0, common_errNullObject // bail if null 3904 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 3905 .if !0 3906 add x0, x0, w1, uxtw #2 // w0<- arrayObj + index*width 3907 .endif 3908 cmp w1, w3 // compare unsigned index, length 3909 bcs common_errArrayIndex // index >= length, bail 3910 .if 0 3911 EXPORT_PC // Export PC before overwriting it. 3912 .endif 3913 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 3914 .if 0 3915 GET_VREG_WIDE x2, w9 // x2<- vAA 3916 .else 3917 GET_VREG w2, w9 // w2<- vAA 3918 .endif 3919 .if 0 3920 str x2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET] // vBB[vCC]<- x2 3921 .elseif 0 3922 bl art_quick_aput_obj 3923 .else 3924 str w2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 3925 .endif 3926 GET_INST_OPCODE ip // extract opcode from rINST 3927 GOTO_OPCODE ip // jump to next instruction 3928 3929 NAME_END nterp_op_aput 3930 // Advance to the end of this handler. Causes error if we are past that point. 3931 .org nterp_op_aput + NTERP_HANDLER_SIZE // op_aput handler is too big! 3932 3933/* ------------------------------ */ 3934 .balign NTERP_HANDLER_SIZE 3935.L_op_aput_wide: /* 0x4c */ 3936 NAME_START nterp_op_aput_wide 3937 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3938 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3939 3940/* 3941 * Array put. vBB[vCC] <- vAA. 3942 * 3943 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object 3944 * 3945 */ 3946 FETCH_B w2, 1, 0 // w2<- BB 3947 lsr w9, wINST, #8 // w9<- AA 3948 FETCH_B w3, 1, 1 // w3<- CC 3949 GET_VREG w0, w2 // w0<- vBB (array object) 3950 GET_VREG w1, w3 // w1<- vCC (requested index) 3951 cbz w0, common_errNullObject // bail if null 3952 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 3953 .if !0 3954 add x0, x0, w1, uxtw #3 // w0<- arrayObj + index*width 3955 .endif 3956 cmp w1, w3 // compare unsigned index, length 3957 bcs common_errArrayIndex // index >= length, bail 3958 .if 0 3959 EXPORT_PC // Export PC before overwriting it. 3960 .endif 3961 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 3962 .if 1 3963 GET_VREG_WIDE x2, w9 // x2<- vAA 3964 .else 3965 GET_VREG w2, w9 // w2<- vAA 3966 .endif 3967 .if 1 3968 str x2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET] // vBB[vCC]<- x2 3969 .elseif 0 3970 bl art_quick_aput_obj 3971 .else 3972 str w2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 3973 .endif 3974 GET_INST_OPCODE ip // extract opcode from rINST 3975 GOTO_OPCODE ip // jump to next instruction 3976 3977 NAME_END nterp_op_aput_wide 3978 // Advance to the end of this handler. Causes error if we are past that point. 3979 .org nterp_op_aput_wide + NTERP_HANDLER_SIZE // op_aput_wide handler is too big! 3980 3981/* ------------------------------ */ 3982 .balign NTERP_HANDLER_SIZE 3983.L_op_aput_object: /* 0x4d */ 3984 NAME_START nterp_op_aput_object 3985 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 3986 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 3987 3988/* 3989 * Array put. vBB[vCC] <- vAA. 3990 * 3991 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object 3992 * 3993 */ 3994 FETCH_B w2, 1, 0 // w2<- BB 3995 lsr w9, wINST, #8 // w9<- AA 3996 FETCH_B w3, 1, 1 // w3<- CC 3997 GET_VREG w0, w2 // w0<- vBB (array object) 3998 GET_VREG w1, w3 // w1<- vCC (requested index) 3999 cbz w0, common_errNullObject // bail if null 4000 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 4001 .if !1 4002 add x0, x0, w1, uxtw #2 // w0<- arrayObj + index*width 4003 .endif 4004 cmp w1, w3 // compare unsigned index, length 4005 bcs common_errArrayIndex // index >= length, bail 4006 .if 1 4007 EXPORT_PC // Export PC before overwriting it. 4008 .endif 4009 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 4010 .if 0 4011 GET_VREG_WIDE x2, w9 // x2<- vAA 4012 .else 4013 GET_VREG w2, w9 // w2<- vAA 4014 .endif 4015 .if 0 4016 str x2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET] // vBB[vCC]<- x2 4017 .elseif 1 4018 bl art_quick_aput_obj 4019 .else 4020 str w2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 4021 .endif 4022 GET_INST_OPCODE ip // extract opcode from rINST 4023 GOTO_OPCODE ip // jump to next instruction 4024 4025 NAME_END nterp_op_aput_object 4026 // Advance to the end of this handler. Causes error if we are past that point. 4027 .org nterp_op_aput_object + NTERP_HANDLER_SIZE // op_aput_object handler is too big! 4028 4029/* ------------------------------ */ 4030 .balign NTERP_HANDLER_SIZE 4031.L_op_aput_boolean: /* 0x4e */ 4032 NAME_START nterp_op_aput_boolean 4033 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4034 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4035 4036/* 4037 * Array put. vBB[vCC] <- vAA. 4038 * 4039 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object 4040 * 4041 */ 4042 FETCH_B w2, 1, 0 // w2<- BB 4043 lsr w9, wINST, #8 // w9<- AA 4044 FETCH_B w3, 1, 1 // w3<- CC 4045 GET_VREG w0, w2 // w0<- vBB (array object) 4046 GET_VREG w1, w3 // w1<- vCC (requested index) 4047 cbz w0, common_errNullObject // bail if null 4048 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 4049 .if !0 4050 add x0, x0, w1, uxtw #0 // w0<- arrayObj + index*width 4051 .endif 4052 cmp w1, w3 // compare unsigned index, length 4053 bcs common_errArrayIndex // index >= length, bail 4054 .if 0 4055 EXPORT_PC // Export PC before overwriting it. 4056 .endif 4057 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 4058 .if 0 4059 GET_VREG_WIDE x2, w9 // x2<- vAA 4060 .else 4061 GET_VREG w2, w9 // w2<- vAA 4062 .endif 4063 .if 0 4064 strb x2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET] // vBB[vCC]<- x2 4065 .elseif 0 4066 bl art_quick_aput_obj 4067 .else 4068 strb w2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 4069 .endif 4070 GET_INST_OPCODE ip // extract opcode from rINST 4071 GOTO_OPCODE ip // jump to next instruction 4072 4073 NAME_END nterp_op_aput_boolean 4074 // Advance to the end of this handler. Causes error if we are past that point. 4075 .org nterp_op_aput_boolean + NTERP_HANDLER_SIZE // op_aput_boolean handler is too big! 4076 4077/* ------------------------------ */ 4078 .balign NTERP_HANDLER_SIZE 4079.L_op_aput_byte: /* 0x4f */ 4080 NAME_START nterp_op_aput_byte 4081 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4082 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4083 4084/* 4085 * Array put. vBB[vCC] <- vAA. 4086 * 4087 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object 4088 * 4089 */ 4090 FETCH_B w2, 1, 0 // w2<- BB 4091 lsr w9, wINST, #8 // w9<- AA 4092 FETCH_B w3, 1, 1 // w3<- CC 4093 GET_VREG w0, w2 // w0<- vBB (array object) 4094 GET_VREG w1, w3 // w1<- vCC (requested index) 4095 cbz w0, common_errNullObject // bail if null 4096 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 4097 .if !0 4098 add x0, x0, w1, uxtw #0 // w0<- arrayObj + index*width 4099 .endif 4100 cmp w1, w3 // compare unsigned index, length 4101 bcs common_errArrayIndex // index >= length, bail 4102 .if 0 4103 EXPORT_PC // Export PC before overwriting it. 4104 .endif 4105 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 4106 .if 0 4107 GET_VREG_WIDE x2, w9 // x2<- vAA 4108 .else 4109 GET_VREG w2, w9 // w2<- vAA 4110 .endif 4111 .if 0 4112 strb x2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET] // vBB[vCC]<- x2 4113 .elseif 0 4114 bl art_quick_aput_obj 4115 .else 4116 strb w2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 4117 .endif 4118 GET_INST_OPCODE ip // extract opcode from rINST 4119 GOTO_OPCODE ip // jump to next instruction 4120 4121 NAME_END nterp_op_aput_byte 4122 // Advance to the end of this handler. Causes error if we are past that point. 4123 .org nterp_op_aput_byte + NTERP_HANDLER_SIZE // op_aput_byte handler is too big! 4124 4125/* ------------------------------ */ 4126 .balign NTERP_HANDLER_SIZE 4127.L_op_aput_char: /* 0x50 */ 4128 NAME_START nterp_op_aput_char 4129 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4130 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4131 4132/* 4133 * Array put. vBB[vCC] <- vAA. 4134 * 4135 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object 4136 * 4137 */ 4138 FETCH_B w2, 1, 0 // w2<- BB 4139 lsr w9, wINST, #8 // w9<- AA 4140 FETCH_B w3, 1, 1 // w3<- CC 4141 GET_VREG w0, w2 // w0<- vBB (array object) 4142 GET_VREG w1, w3 // w1<- vCC (requested index) 4143 cbz w0, common_errNullObject // bail if null 4144 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 4145 .if !0 4146 add x0, x0, w1, uxtw #1 // w0<- arrayObj + index*width 4147 .endif 4148 cmp w1, w3 // compare unsigned index, length 4149 bcs common_errArrayIndex // index >= length, bail 4150 .if 0 4151 EXPORT_PC // Export PC before overwriting it. 4152 .endif 4153 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 4154 .if 0 4155 GET_VREG_WIDE x2, w9 // x2<- vAA 4156 .else 4157 GET_VREG w2, w9 // w2<- vAA 4158 .endif 4159 .if 0 4160 strh x2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET] // vBB[vCC]<- x2 4161 .elseif 0 4162 bl art_quick_aput_obj 4163 .else 4164 strh w2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 4165 .endif 4166 GET_INST_OPCODE ip // extract opcode from rINST 4167 GOTO_OPCODE ip // jump to next instruction 4168 4169 NAME_END nterp_op_aput_char 4170 // Advance to the end of this handler. Causes error if we are past that point. 4171 .org nterp_op_aput_char + NTERP_HANDLER_SIZE // op_aput_char handler is too big! 4172 4173/* ------------------------------ */ 4174 .balign NTERP_HANDLER_SIZE 4175.L_op_aput_short: /* 0x51 */ 4176 NAME_START nterp_op_aput_short 4177 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4178 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4179 4180/* 4181 * Array put. vBB[vCC] <- vAA. 4182 * 4183 * for: aput, aput-boolean, aput-byte, aput-char, aput-short, aput-wide, aput-object 4184 * 4185 */ 4186 FETCH_B w2, 1, 0 // w2<- BB 4187 lsr w9, wINST, #8 // w9<- AA 4188 FETCH_B w3, 1, 1 // w3<- CC 4189 GET_VREG w0, w2 // w0<- vBB (array object) 4190 GET_VREG w1, w3 // w1<- vCC (requested index) 4191 cbz w0, common_errNullObject // bail if null 4192 ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length 4193 .if !0 4194 add x0, x0, w1, uxtw #1 // w0<- arrayObj + index*width 4195 .endif 4196 cmp w1, w3 // compare unsigned index, length 4197 bcs common_errArrayIndex // index >= length, bail 4198 .if 0 4199 EXPORT_PC // Export PC before overwriting it. 4200 .endif 4201 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 4202 .if 0 4203 GET_VREG_WIDE x2, w9 // x2<- vAA 4204 .else 4205 GET_VREG w2, w9 // w2<- vAA 4206 .endif 4207 .if 0 4208 strh x2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET] // vBB[vCC]<- x2 4209 .elseif 0 4210 bl art_quick_aput_obj 4211 .else 4212 strh w2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 4213 .endif 4214 GET_INST_OPCODE ip // extract opcode from rINST 4215 GOTO_OPCODE ip // jump to next instruction 4216 4217 NAME_END nterp_op_aput_short 4218 // Advance to the end of this handler. Causes error if we are past that point. 4219 .org nterp_op_aput_short + NTERP_HANDLER_SIZE // op_aput_short handler is too big! 4220 4221/* ------------------------------ */ 4222 .balign NTERP_HANDLER_SIZE 4223.L_op_iget: /* 0x52 */ 4224 NAME_START nterp_op_iget 4225 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4226 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4227 4228 // Fast-path which gets the field from thread-local cache. 4229 // Fetch some information from the thread cache. 4230 // Uses ip and ip2 as temporaries. 4231 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4232 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4233 add ip, ip, ip2, lsl #4 // entry address within the cache 4234 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4235 cmp ip, xPC 4236 b.ne nterp_op_iget_slow_path 4237 4238.Lop_iget_resume: 4239 lsr w2, wINST, #12 // w2<- B 4240 GET_VREG w3, w2 // w3<- object we're operating on 4241 ubfx w2, wINST, #8, #4 // w2<- A 4242 cbz w3, common_errNullObject // object was null 4243 .if 0 4244 ldr x0, [x3, x0] 4245 SET_VREG_WIDE x0, w2 // fp[A] <- value 4246 .elseif 0 4247 ldr w0, [x3, x0] 4248 UNPOISON_HEAP_REF w0 4249 TEST_IF_MARKING .Lop_iget_read_barrier 4250.Lop_iget_resume_after_read_barrier: 4251 SET_VREG_OBJECT w0, w2 // fp[A] <- value 4252 .else 4253 ldr w0, [x3, x0] 4254 SET_VREG w0, w2 // fp[A] <- value 4255 .endif 4256 FETCH_ADVANCE_INST 2 4257 GET_INST_OPCODE ip 4258 GOTO_OPCODE ip 4259 .if 0 4260.Lop_iget_read_barrier: 4261 bl art_quick_read_barrier_mark_reg00 4262 b .Lop_iget_resume_after_read_barrier 4263 .endif 4264 4265 NAME_END nterp_op_iget 4266 // Advance to the end of this handler. Causes error if we are past that point. 4267 .org nterp_op_iget + NTERP_HANDLER_SIZE // op_iget handler is too big! 4268 4269/* ------------------------------ */ 4270 .balign NTERP_HANDLER_SIZE 4271.L_op_iget_wide: /* 0x53 */ 4272 NAME_START nterp_op_iget_wide 4273 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4274 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4275 4276 // Fast-path which gets the field from thread-local cache. 4277 // Fetch some information from the thread cache. 4278 // Uses ip and ip2 as temporaries. 4279 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4280 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4281 add ip, ip, ip2, lsl #4 // entry address within the cache 4282 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4283 cmp ip, xPC 4284 b.ne nterp_op_iget_wide_slow_path 4285 4286.Lop_iget_wide_resume: 4287 lsr w2, wINST, #12 // w2<- B 4288 GET_VREG w3, w2 // w3<- object we're operating on 4289 ubfx w2, wINST, #8, #4 // w2<- A 4290 cbz w3, common_errNullObject // object was null 4291 .if 1 4292 ldr x0, [x3, x0] 4293 SET_VREG_WIDE x0, w2 // fp[A] <- value 4294 .elseif 0 4295 ldr w0, [x3, x0] 4296 UNPOISON_HEAP_REF w0 4297 TEST_IF_MARKING .Lop_iget_wide_read_barrier 4298.Lop_iget_wide_resume_after_read_barrier: 4299 SET_VREG_OBJECT w0, w2 // fp[A] <- value 4300 .else 4301 ldr w0, [x3, x0] 4302 SET_VREG w0, w2 // fp[A] <- value 4303 .endif 4304 FETCH_ADVANCE_INST 2 4305 GET_INST_OPCODE ip 4306 GOTO_OPCODE ip 4307 .if 0 4308.Lop_iget_wide_read_barrier: 4309 bl art_quick_read_barrier_mark_reg00 4310 b .Lop_iget_wide_resume_after_read_barrier 4311 .endif 4312 4313 NAME_END nterp_op_iget_wide 4314 // Advance to the end of this handler. Causes error if we are past that point. 4315 .org nterp_op_iget_wide + NTERP_HANDLER_SIZE // op_iget_wide handler is too big! 4316 4317/* ------------------------------ */ 4318 .balign NTERP_HANDLER_SIZE 4319.L_op_iget_object: /* 0x54 */ 4320 NAME_START nterp_op_iget_object 4321 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4322 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4323 4324 // Fast-path which gets the field from thread-local cache. 4325 // Fetch some information from the thread cache. 4326 // Uses ip and ip2 as temporaries. 4327 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4328 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4329 add ip, ip, ip2, lsl #4 // entry address within the cache 4330 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4331 cmp ip, xPC 4332 b.ne nterp_op_iget_object_slow_path 4333 4334.Lop_iget_object_resume: 4335 lsr w2, wINST, #12 // w2<- B 4336 GET_VREG w3, w2 // w3<- object we're operating on 4337 ubfx w2, wINST, #8, #4 // w2<- A 4338 cbz w3, common_errNullObject // object was null 4339 .if 0 4340 ldr x0, [x3, x0] 4341 SET_VREG_WIDE x0, w2 // fp[A] <- value 4342 .elseif 1 4343 ldr w0, [x3, x0] 4344 UNPOISON_HEAP_REF w0 4345 TEST_IF_MARKING .Lop_iget_object_read_barrier 4346.Lop_iget_object_resume_after_read_barrier: 4347 SET_VREG_OBJECT w0, w2 // fp[A] <- value 4348 .else 4349 ldr w0, [x3, x0] 4350 SET_VREG w0, w2 // fp[A] <- value 4351 .endif 4352 FETCH_ADVANCE_INST 2 4353 GET_INST_OPCODE ip 4354 GOTO_OPCODE ip 4355 .if 1 4356.Lop_iget_object_read_barrier: 4357 bl art_quick_read_barrier_mark_reg00 4358 b .Lop_iget_object_resume_after_read_barrier 4359 .endif 4360 4361 NAME_END nterp_op_iget_object 4362 // Advance to the end of this handler. Causes error if we are past that point. 4363 .org nterp_op_iget_object + NTERP_HANDLER_SIZE // op_iget_object handler is too big! 4364 4365/* ------------------------------ */ 4366 .balign NTERP_HANDLER_SIZE 4367.L_op_iget_boolean: /* 0x55 */ 4368 NAME_START nterp_op_iget_boolean 4369 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4370 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4371 4372 // Fast-path which gets the field from thread-local cache. 4373 // Fetch some information from the thread cache. 4374 // Uses ip and ip2 as temporaries. 4375 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4376 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4377 add ip, ip, ip2, lsl #4 // entry address within the cache 4378 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4379 cmp ip, xPC 4380 b.ne nterp_op_iget_boolean_slow_path 4381 4382.Lop_iget_boolean_resume: 4383 lsr w2, wINST, #12 // w2<- B 4384 GET_VREG w3, w2 // w3<- object we're operating on 4385 ubfx w2, wINST, #8, #4 // w2<- A 4386 cbz w3, common_errNullObject // object was null 4387 .if 0 4388 ldrb x0, [x3, x0] 4389 SET_VREG_WIDE x0, w2 // fp[A] <- value 4390 .elseif 0 4391 ldrb w0, [x3, x0] 4392 UNPOISON_HEAP_REF w0 4393 TEST_IF_MARKING .Lop_iget_boolean_read_barrier 4394.Lop_iget_boolean_resume_after_read_barrier: 4395 SET_VREG_OBJECT w0, w2 // fp[A] <- value 4396 .else 4397 ldrb w0, [x3, x0] 4398 SET_VREG w0, w2 // fp[A] <- value 4399 .endif 4400 FETCH_ADVANCE_INST 2 4401 GET_INST_OPCODE ip 4402 GOTO_OPCODE ip 4403 .if 0 4404.Lop_iget_boolean_read_barrier: 4405 bl art_quick_read_barrier_mark_reg00 4406 b .Lop_iget_boolean_resume_after_read_barrier 4407 .endif 4408 4409 NAME_END nterp_op_iget_boolean 4410 // Advance to the end of this handler. Causes error if we are past that point. 4411 .org nterp_op_iget_boolean + NTERP_HANDLER_SIZE // op_iget_boolean handler is too big! 4412 4413/* ------------------------------ */ 4414 .balign NTERP_HANDLER_SIZE 4415.L_op_iget_byte: /* 0x56 */ 4416 NAME_START nterp_op_iget_byte 4417 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4418 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4419 4420 // Fast-path which gets the field from thread-local cache. 4421 // Fetch some information from the thread cache. 4422 // Uses ip and ip2 as temporaries. 4423 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4424 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4425 add ip, ip, ip2, lsl #4 // entry address within the cache 4426 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4427 cmp ip, xPC 4428 b.ne nterp_op_iget_byte_slow_path 4429 4430.Lop_iget_byte_resume: 4431 lsr w2, wINST, #12 // w2<- B 4432 GET_VREG w3, w2 // w3<- object we're operating on 4433 ubfx w2, wINST, #8, #4 // w2<- A 4434 cbz w3, common_errNullObject // object was null 4435 .if 0 4436 ldrsb x0, [x3, x0] 4437 SET_VREG_WIDE x0, w2 // fp[A] <- value 4438 .elseif 0 4439 ldrsb w0, [x3, x0] 4440 UNPOISON_HEAP_REF w0 4441 TEST_IF_MARKING .Lop_iget_byte_read_barrier 4442.Lop_iget_byte_resume_after_read_barrier: 4443 SET_VREG_OBJECT w0, w2 // fp[A] <- value 4444 .else 4445 ldrsb w0, [x3, x0] 4446 SET_VREG w0, w2 // fp[A] <- value 4447 .endif 4448 FETCH_ADVANCE_INST 2 4449 GET_INST_OPCODE ip 4450 GOTO_OPCODE ip 4451 .if 0 4452.Lop_iget_byte_read_barrier: 4453 bl art_quick_read_barrier_mark_reg00 4454 b .Lop_iget_byte_resume_after_read_barrier 4455 .endif 4456 4457 NAME_END nterp_op_iget_byte 4458 // Advance to the end of this handler. Causes error if we are past that point. 4459 .org nterp_op_iget_byte + NTERP_HANDLER_SIZE // op_iget_byte handler is too big! 4460 4461/* ------------------------------ */ 4462 .balign NTERP_HANDLER_SIZE 4463.L_op_iget_char: /* 0x57 */ 4464 NAME_START nterp_op_iget_char 4465 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4466 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4467 4468 // Fast-path which gets the field from thread-local cache. 4469 // Fetch some information from the thread cache. 4470 // Uses ip and ip2 as temporaries. 4471 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4472 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4473 add ip, ip, ip2, lsl #4 // entry address within the cache 4474 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4475 cmp ip, xPC 4476 b.ne nterp_op_iget_char_slow_path 4477 4478.Lop_iget_char_resume: 4479 lsr w2, wINST, #12 // w2<- B 4480 GET_VREG w3, w2 // w3<- object we're operating on 4481 ubfx w2, wINST, #8, #4 // w2<- A 4482 cbz w3, common_errNullObject // object was null 4483 .if 0 4484 ldrh x0, [x3, x0] 4485 SET_VREG_WIDE x0, w2 // fp[A] <- value 4486 .elseif 0 4487 ldrh w0, [x3, x0] 4488 UNPOISON_HEAP_REF w0 4489 TEST_IF_MARKING .Lop_iget_char_read_barrier 4490.Lop_iget_char_resume_after_read_barrier: 4491 SET_VREG_OBJECT w0, w2 // fp[A] <- value 4492 .else 4493 ldrh w0, [x3, x0] 4494 SET_VREG w0, w2 // fp[A] <- value 4495 .endif 4496 FETCH_ADVANCE_INST 2 4497 GET_INST_OPCODE ip 4498 GOTO_OPCODE ip 4499 .if 0 4500.Lop_iget_char_read_barrier: 4501 bl art_quick_read_barrier_mark_reg00 4502 b .Lop_iget_char_resume_after_read_barrier 4503 .endif 4504 4505 NAME_END nterp_op_iget_char 4506 // Advance to the end of this handler. Causes error if we are past that point. 4507 .org nterp_op_iget_char + NTERP_HANDLER_SIZE // op_iget_char handler is too big! 4508 4509/* ------------------------------ */ 4510 .balign NTERP_HANDLER_SIZE 4511.L_op_iget_short: /* 0x58 */ 4512 NAME_START nterp_op_iget_short 4513 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4514 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4515 4516 // Fast-path which gets the field from thread-local cache. 4517 // Fetch some information from the thread cache. 4518 // Uses ip and ip2 as temporaries. 4519 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4520 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4521 add ip, ip, ip2, lsl #4 // entry address within the cache 4522 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4523 cmp ip, xPC 4524 b.ne nterp_op_iget_short_slow_path 4525 4526.Lop_iget_short_resume: 4527 lsr w2, wINST, #12 // w2<- B 4528 GET_VREG w3, w2 // w3<- object we're operating on 4529 ubfx w2, wINST, #8, #4 // w2<- A 4530 cbz w3, common_errNullObject // object was null 4531 .if 0 4532 ldrsh x0, [x3, x0] 4533 SET_VREG_WIDE x0, w2 // fp[A] <- value 4534 .elseif 0 4535 ldrsh w0, [x3, x0] 4536 UNPOISON_HEAP_REF w0 4537 TEST_IF_MARKING .Lop_iget_short_read_barrier 4538.Lop_iget_short_resume_after_read_barrier: 4539 SET_VREG_OBJECT w0, w2 // fp[A] <- value 4540 .else 4541 ldrsh w0, [x3, x0] 4542 SET_VREG w0, w2 // fp[A] <- value 4543 .endif 4544 FETCH_ADVANCE_INST 2 4545 GET_INST_OPCODE ip 4546 GOTO_OPCODE ip 4547 .if 0 4548.Lop_iget_short_read_barrier: 4549 bl art_quick_read_barrier_mark_reg00 4550 b .Lop_iget_short_resume_after_read_barrier 4551 .endif 4552 4553 NAME_END nterp_op_iget_short 4554 // Advance to the end of this handler. Causes error if we are past that point. 4555 .org nterp_op_iget_short + NTERP_HANDLER_SIZE // op_iget_short handler is too big! 4556 4557/* ------------------------------ */ 4558 .balign NTERP_HANDLER_SIZE 4559.L_op_iput: /* 0x59 */ 4560 NAME_START nterp_op_iput 4561 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4562 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4563 4564 ubfx w1, wINST, #8, #4 // w1<- A 4565 .if 0 4566 GET_VREG_WIDE x26, w1 // x26<- fp[A]/fp[A+1] 4567 .else 4568 GET_VREG w26, w1 // w26 <- v[A] 4569 .endif 4570 // Fast-path which gets the field from thread-local cache. 4571 // Fetch some information from the thread cache. 4572 // Uses ip and ip2 as temporaries. 4573 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4574 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4575 add ip, ip, ip2, lsl #4 // entry address within the cache 4576 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4577 cmp ip, xPC 4578 b.ne nterp_op_iput_slow_path 4579 4580.Lop_iput_resume: 4581 lsr w2, wINST, #12 // w2<- B 4582 GET_VREG w2, w2 // vB (object we're operating on) 4583 cbz w2, common_errNullObject 4584 .if 0 4585 str x26, [x2, x0] 4586 .else 4587 POISON_HEAP_REF_IF_OBJECT 0, w26 4588 str w26, [x2, x0] 4589 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_skip_write_barrier 4590 .endif 4591 FETCH_ADVANCE_INST 2 4592 GET_INST_OPCODE ip 4593 GOTO_OPCODE ip 4594 4595 NAME_END nterp_op_iput 4596 // Advance to the end of this handler. Causes error if we are past that point. 4597 .org nterp_op_iput + NTERP_HANDLER_SIZE // op_iput handler is too big! 4598 4599/* ------------------------------ */ 4600 .balign NTERP_HANDLER_SIZE 4601.L_op_iput_wide: /* 0x5a */ 4602 NAME_START nterp_op_iput_wide 4603 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4604 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4605 4606 ubfx w1, wINST, #8, #4 // w1<- A 4607 .if 1 4608 GET_VREG_WIDE x26, w1 // x26<- fp[A]/fp[A+1] 4609 .else 4610 GET_VREG w26, w1 // w26 <- v[A] 4611 .endif 4612 // Fast-path which gets the field from thread-local cache. 4613 // Fetch some information from the thread cache. 4614 // Uses ip and ip2 as temporaries. 4615 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4616 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4617 add ip, ip, ip2, lsl #4 // entry address within the cache 4618 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4619 cmp ip, xPC 4620 b.ne nterp_op_iput_wide_slow_path 4621 4622.Lop_iput_wide_resume: 4623 lsr w2, wINST, #12 // w2<- B 4624 GET_VREG w2, w2 // vB (object we're operating on) 4625 cbz w2, common_errNullObject 4626 .if 1 4627 str x26, [x2, x0] 4628 .else 4629 POISON_HEAP_REF_IF_OBJECT 0, w26 4630 str w26, [x2, x0] 4631 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_wide_skip_write_barrier 4632 .endif 4633 FETCH_ADVANCE_INST 2 4634 GET_INST_OPCODE ip 4635 GOTO_OPCODE ip 4636 4637 NAME_END nterp_op_iput_wide 4638 // Advance to the end of this handler. Causes error if we are past that point. 4639 .org nterp_op_iput_wide + NTERP_HANDLER_SIZE // op_iput_wide handler is too big! 4640 4641/* ------------------------------ */ 4642 .balign NTERP_HANDLER_SIZE 4643.L_op_iput_object: /* 0x5b */ 4644 NAME_START nterp_op_iput_object 4645 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4646 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4647 4648 ubfx w1, wINST, #8, #4 // w1<- A 4649 .if 0 4650 GET_VREG_WIDE x26, w1 // x26<- fp[A]/fp[A+1] 4651 .else 4652 GET_VREG w26, w1 // w26 <- v[A] 4653 .endif 4654 // Fast-path which gets the field from thread-local cache. 4655 // Fetch some information from the thread cache. 4656 // Uses ip and ip2 as temporaries. 4657 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4658 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4659 add ip, ip, ip2, lsl #4 // entry address within the cache 4660 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4661 cmp ip, xPC 4662 b.ne nterp_op_iput_object_slow_path 4663 4664.Lop_iput_object_resume: 4665 lsr w2, wINST, #12 // w2<- B 4666 GET_VREG w2, w2 // vB (object we're operating on) 4667 cbz w2, common_errNullObject 4668 .if 0 4669 str x26, [x2, x0] 4670 .else 4671 POISON_HEAP_REF_IF_OBJECT 1, w26 4672 str w26, [x2, x0] 4673 WRITE_BARRIER_IF_OBJECT 1, w26, w2, .Lop_iput_object_skip_write_barrier 4674 .endif 4675 FETCH_ADVANCE_INST 2 4676 GET_INST_OPCODE ip 4677 GOTO_OPCODE ip 4678 4679 NAME_END nterp_op_iput_object 4680 // Advance to the end of this handler. Causes error if we are past that point. 4681 .org nterp_op_iput_object + NTERP_HANDLER_SIZE // op_iput_object handler is too big! 4682 4683/* ------------------------------ */ 4684 .balign NTERP_HANDLER_SIZE 4685.L_op_iput_boolean: /* 0x5c */ 4686 NAME_START nterp_op_iput_boolean 4687 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4688 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4689 4690 ubfx w1, wINST, #8, #4 // w1<- A 4691 .if 0 4692 GET_VREG_WIDE x26, w1 // x26<- fp[A]/fp[A+1] 4693 .else 4694 GET_VREG w26, w1 // w26 <- v[A] 4695 .endif 4696 // Fast-path which gets the field from thread-local cache. 4697 // Fetch some information from the thread cache. 4698 // Uses ip and ip2 as temporaries. 4699 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4700 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4701 add ip, ip, ip2, lsl #4 // entry address within the cache 4702 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4703 cmp ip, xPC 4704 b.ne nterp_op_iput_boolean_slow_path 4705 4706.Lop_iput_boolean_resume: 4707 lsr w2, wINST, #12 // w2<- B 4708 GET_VREG w2, w2 // vB (object we're operating on) 4709 cbz w2, common_errNullObject 4710 .if 0 4711 strb x26, [x2, x0] 4712 .else 4713 POISON_HEAP_REF_IF_OBJECT 0, w26 4714 strb w26, [x2, x0] 4715 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_boolean_skip_write_barrier 4716 .endif 4717 FETCH_ADVANCE_INST 2 4718 GET_INST_OPCODE ip 4719 GOTO_OPCODE ip 4720 4721 NAME_END nterp_op_iput_boolean 4722 // Advance to the end of this handler. Causes error if we are past that point. 4723 .org nterp_op_iput_boolean + NTERP_HANDLER_SIZE // op_iput_boolean handler is too big! 4724 4725/* ------------------------------ */ 4726 .balign NTERP_HANDLER_SIZE 4727.L_op_iput_byte: /* 0x5d */ 4728 NAME_START nterp_op_iput_byte 4729 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4730 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4731 4732 ubfx w1, wINST, #8, #4 // w1<- A 4733 .if 0 4734 GET_VREG_WIDE x26, w1 // x26<- fp[A]/fp[A+1] 4735 .else 4736 GET_VREG w26, w1 // w26 <- v[A] 4737 .endif 4738 // Fast-path which gets the field from thread-local cache. 4739 // Fetch some information from the thread cache. 4740 // Uses ip and ip2 as temporaries. 4741 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4742 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4743 add ip, ip, ip2, lsl #4 // entry address within the cache 4744 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4745 cmp ip, xPC 4746 b.ne nterp_op_iput_byte_slow_path 4747 4748.Lop_iput_byte_resume: 4749 lsr w2, wINST, #12 // w2<- B 4750 GET_VREG w2, w2 // vB (object we're operating on) 4751 cbz w2, common_errNullObject 4752 .if 0 4753 strb x26, [x2, x0] 4754 .else 4755 POISON_HEAP_REF_IF_OBJECT 0, w26 4756 strb w26, [x2, x0] 4757 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_byte_skip_write_barrier 4758 .endif 4759 FETCH_ADVANCE_INST 2 4760 GET_INST_OPCODE ip 4761 GOTO_OPCODE ip 4762 4763 NAME_END nterp_op_iput_byte 4764 // Advance to the end of this handler. Causes error if we are past that point. 4765 .org nterp_op_iput_byte + NTERP_HANDLER_SIZE // op_iput_byte handler is too big! 4766 4767/* ------------------------------ */ 4768 .balign NTERP_HANDLER_SIZE 4769.L_op_iput_char: /* 0x5e */ 4770 NAME_START nterp_op_iput_char 4771 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4772 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4773 4774 ubfx w1, wINST, #8, #4 // w1<- A 4775 .if 0 4776 GET_VREG_WIDE x26, w1 // x26<- fp[A]/fp[A+1] 4777 .else 4778 GET_VREG w26, w1 // w26 <- v[A] 4779 .endif 4780 // Fast-path which gets the field from thread-local cache. 4781 // Fetch some information from the thread cache. 4782 // Uses ip and ip2 as temporaries. 4783 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4784 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4785 add ip, ip, ip2, lsl #4 // entry address within the cache 4786 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4787 cmp ip, xPC 4788 b.ne nterp_op_iput_char_slow_path 4789 4790.Lop_iput_char_resume: 4791 lsr w2, wINST, #12 // w2<- B 4792 GET_VREG w2, w2 // vB (object we're operating on) 4793 cbz w2, common_errNullObject 4794 .if 0 4795 strh x26, [x2, x0] 4796 .else 4797 POISON_HEAP_REF_IF_OBJECT 0, w26 4798 strh w26, [x2, x0] 4799 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_char_skip_write_barrier 4800 .endif 4801 FETCH_ADVANCE_INST 2 4802 GET_INST_OPCODE ip 4803 GOTO_OPCODE ip 4804 4805 NAME_END nterp_op_iput_char 4806 // Advance to the end of this handler. Causes error if we are past that point. 4807 .org nterp_op_iput_char + NTERP_HANDLER_SIZE // op_iput_char handler is too big! 4808 4809/* ------------------------------ */ 4810 .balign NTERP_HANDLER_SIZE 4811.L_op_iput_short: /* 0x5f */ 4812 NAME_START nterp_op_iput_short 4813 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4814 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4815 4816 ubfx w1, wINST, #8, #4 // w1<- A 4817 .if 0 4818 GET_VREG_WIDE x26, w1 // x26<- fp[A]/fp[A+1] 4819 .else 4820 GET_VREG w26, w1 // w26 <- v[A] 4821 .endif 4822 // Fast-path which gets the field from thread-local cache. 4823 // Fetch some information from the thread cache. 4824 // Uses ip and ip2 as temporaries. 4825 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4826 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4827 add ip, ip, ip2, lsl #4 // entry address within the cache 4828 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4829 cmp ip, xPC 4830 b.ne nterp_op_iput_short_slow_path 4831 4832.Lop_iput_short_resume: 4833 lsr w2, wINST, #12 // w2<- B 4834 GET_VREG w2, w2 // vB (object we're operating on) 4835 cbz w2, common_errNullObject 4836 .if 0 4837 strh x26, [x2, x0] 4838 .else 4839 POISON_HEAP_REF_IF_OBJECT 0, w26 4840 strh w26, [x2, x0] 4841 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_short_skip_write_barrier 4842 .endif 4843 FETCH_ADVANCE_INST 2 4844 GET_INST_OPCODE ip 4845 GOTO_OPCODE ip 4846 4847 NAME_END nterp_op_iput_short 4848 // Advance to the end of this handler. Causes error if we are past that point. 4849 .org nterp_op_iput_short + NTERP_HANDLER_SIZE // op_iput_short handler is too big! 4850 4851/* ------------------------------ */ 4852 .balign NTERP_HANDLER_SIZE 4853.L_op_sget: /* 0x60 */ 4854 NAME_START nterp_op_sget 4855 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4856 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4857 4858 // Fast-path which gets the field from thread-local cache. 4859 // Fetch some information from the thread cache. 4860 // Uses ip and ip2 as temporaries. 4861 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4862 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4863 add ip, ip, ip2, lsl #4 // entry address within the cache 4864 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4865 cmp ip, xPC 4866 b.ne nterp_op_sget_slow_path 4867 4868.Lop_sget_resume: 4869 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 4870 lsr w2, wINST, #8 // w2 <- A 4871 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 4872 TEST_IF_MARKING .Lop_sget_read_barrier 4873.Lop_sget_resume_after_read_barrier: 4874 .if 0 4875 ldr x0, [x0, x1] 4876 SET_VREG_WIDE x0, w2 // fp[A] <- value 4877 .elseif 0 4878 ldr w0, [x0, x1] 4879 UNPOISON_HEAP_REF w0 4880 // No need to check the marking register, we know it's not set here. 4881.Lop_sget_after_reference_load: 4882 SET_VREG_OBJECT w0, w2 // fp[A] <- value 4883 .else 4884 ldr w0, [x0, x1] 4885 SET_VREG w0, w2 // fp[A] <- value 4886 .endif 4887 FETCH_ADVANCE_INST 2 4888 GET_INST_OPCODE ip 4889 GOTO_OPCODE ip 4890.Lop_sget_read_barrier: 4891 bl art_quick_read_barrier_mark_reg00 4892 .if 0 4893 ldr w0, [x0, x1] 4894 UNPOISON_HEAP_REF w0 4895.Lop_sget_mark_after_load: 4896 // Here, we know the marking register is set. 4897 bl art_quick_read_barrier_mark_reg00 4898 b .Lop_sget_after_reference_load 4899 .else 4900 b .Lop_sget_resume_after_read_barrier 4901 .endif 4902 4903 NAME_END nterp_op_sget 4904 // Advance to the end of this handler. Causes error if we are past that point. 4905 .org nterp_op_sget + NTERP_HANDLER_SIZE // op_sget handler is too big! 4906 4907/* ------------------------------ */ 4908 .balign NTERP_HANDLER_SIZE 4909.L_op_sget_wide: /* 0x61 */ 4910 NAME_START nterp_op_sget_wide 4911 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4912 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4913 4914 // Fast-path which gets the field from thread-local cache. 4915 // Fetch some information from the thread cache. 4916 // Uses ip and ip2 as temporaries. 4917 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4918 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4919 add ip, ip, ip2, lsl #4 // entry address within the cache 4920 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4921 cmp ip, xPC 4922 b.ne nterp_op_sget_wide_slow_path 4923 4924.Lop_sget_wide_resume: 4925 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 4926 lsr w2, wINST, #8 // w2 <- A 4927 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 4928 TEST_IF_MARKING .Lop_sget_wide_read_barrier 4929.Lop_sget_wide_resume_after_read_barrier: 4930 .if 1 4931 ldr x0, [x0, x1] 4932 SET_VREG_WIDE x0, w2 // fp[A] <- value 4933 .elseif 0 4934 ldr w0, [x0, x1] 4935 UNPOISON_HEAP_REF w0 4936 // No need to check the marking register, we know it's not set here. 4937.Lop_sget_wide_after_reference_load: 4938 SET_VREG_OBJECT w0, w2 // fp[A] <- value 4939 .else 4940 ldr w0, [x0, x1] 4941 SET_VREG w0, w2 // fp[A] <- value 4942 .endif 4943 FETCH_ADVANCE_INST 2 4944 GET_INST_OPCODE ip 4945 GOTO_OPCODE ip 4946.Lop_sget_wide_read_barrier: 4947 bl art_quick_read_barrier_mark_reg00 4948 .if 0 4949 ldr w0, [x0, x1] 4950 UNPOISON_HEAP_REF w0 4951.Lop_sget_wide_mark_after_load: 4952 // Here, we know the marking register is set. 4953 bl art_quick_read_barrier_mark_reg00 4954 b .Lop_sget_wide_after_reference_load 4955 .else 4956 b .Lop_sget_wide_resume_after_read_barrier 4957 .endif 4958 4959 NAME_END nterp_op_sget_wide 4960 // Advance to the end of this handler. Causes error if we are past that point. 4961 .org nterp_op_sget_wide + NTERP_HANDLER_SIZE // op_sget_wide handler is too big! 4962 4963/* ------------------------------ */ 4964 .balign NTERP_HANDLER_SIZE 4965.L_op_sget_object: /* 0x62 */ 4966 NAME_START nterp_op_sget_object 4967 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 4968 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 4969 4970 // Fast-path which gets the field from thread-local cache. 4971 // Fetch some information from the thread cache. 4972 // Uses ip and ip2 as temporaries. 4973 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 4974 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 4975 add ip, ip, ip2, lsl #4 // entry address within the cache 4976 ldp ip, x0, [ip] // entry key (pc) and value (offset) 4977 cmp ip, xPC 4978 b.ne nterp_op_sget_object_slow_path 4979 4980.Lop_sget_object_resume: 4981 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 4982 lsr w2, wINST, #8 // w2 <- A 4983 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 4984 TEST_IF_MARKING .Lop_sget_object_read_barrier 4985.Lop_sget_object_resume_after_read_barrier: 4986 .if 0 4987 ldr x0, [x0, x1] 4988 SET_VREG_WIDE x0, w2 // fp[A] <- value 4989 .elseif 1 4990 ldr w0, [x0, x1] 4991 UNPOISON_HEAP_REF w0 4992 // No need to check the marking register, we know it's not set here. 4993.Lop_sget_object_after_reference_load: 4994 SET_VREG_OBJECT w0, w2 // fp[A] <- value 4995 .else 4996 ldr w0, [x0, x1] 4997 SET_VREG w0, w2 // fp[A] <- value 4998 .endif 4999 FETCH_ADVANCE_INST 2 5000 GET_INST_OPCODE ip 5001 GOTO_OPCODE ip 5002.Lop_sget_object_read_barrier: 5003 bl art_quick_read_barrier_mark_reg00 5004 .if 1 5005 ldr w0, [x0, x1] 5006 UNPOISON_HEAP_REF w0 5007.Lop_sget_object_mark_after_load: 5008 // Here, we know the marking register is set. 5009 bl art_quick_read_barrier_mark_reg00 5010 b .Lop_sget_object_after_reference_load 5011 .else 5012 b .Lop_sget_object_resume_after_read_barrier 5013 .endif 5014 5015 NAME_END nterp_op_sget_object 5016 // Advance to the end of this handler. Causes error if we are past that point. 5017 .org nterp_op_sget_object + NTERP_HANDLER_SIZE // op_sget_object handler is too big! 5018 5019/* ------------------------------ */ 5020 .balign NTERP_HANDLER_SIZE 5021.L_op_sget_boolean: /* 0x63 */ 5022 NAME_START nterp_op_sget_boolean 5023 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5024 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5025 5026 // Fast-path which gets the field from thread-local cache. 5027 // Fetch some information from the thread cache. 5028 // Uses ip and ip2 as temporaries. 5029 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5030 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5031 add ip, ip, ip2, lsl #4 // entry address within the cache 5032 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5033 cmp ip, xPC 5034 b.ne nterp_op_sget_boolean_slow_path 5035 5036.Lop_sget_boolean_resume: 5037 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 5038 lsr w2, wINST, #8 // w2 <- A 5039 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 5040 TEST_IF_MARKING .Lop_sget_boolean_read_barrier 5041.Lop_sget_boolean_resume_after_read_barrier: 5042 .if 0 5043 ldr x0, [x0, x1] 5044 SET_VREG_WIDE x0, w2 // fp[A] <- value 5045 .elseif 0 5046 ldrb w0, [x0, x1] 5047 UNPOISON_HEAP_REF w0 5048 // No need to check the marking register, we know it's not set here. 5049.Lop_sget_boolean_after_reference_load: 5050 SET_VREG_OBJECT w0, w2 // fp[A] <- value 5051 .else 5052 ldrb w0, [x0, x1] 5053 SET_VREG w0, w2 // fp[A] <- value 5054 .endif 5055 FETCH_ADVANCE_INST 2 5056 GET_INST_OPCODE ip 5057 GOTO_OPCODE ip 5058.Lop_sget_boolean_read_barrier: 5059 bl art_quick_read_barrier_mark_reg00 5060 .if 0 5061 ldrb w0, [x0, x1] 5062 UNPOISON_HEAP_REF w0 5063.Lop_sget_boolean_mark_after_load: 5064 // Here, we know the marking register is set. 5065 bl art_quick_read_barrier_mark_reg00 5066 b .Lop_sget_boolean_after_reference_load 5067 .else 5068 b .Lop_sget_boolean_resume_after_read_barrier 5069 .endif 5070 5071 NAME_END nterp_op_sget_boolean 5072 // Advance to the end of this handler. Causes error if we are past that point. 5073 .org nterp_op_sget_boolean + NTERP_HANDLER_SIZE // op_sget_boolean handler is too big! 5074 5075/* ------------------------------ */ 5076 .balign NTERP_HANDLER_SIZE 5077.L_op_sget_byte: /* 0x64 */ 5078 NAME_START nterp_op_sget_byte 5079 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5080 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5081 5082 // Fast-path which gets the field from thread-local cache. 5083 // Fetch some information from the thread cache. 5084 // Uses ip and ip2 as temporaries. 5085 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5086 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5087 add ip, ip, ip2, lsl #4 // entry address within the cache 5088 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5089 cmp ip, xPC 5090 b.ne nterp_op_sget_byte_slow_path 5091 5092.Lop_sget_byte_resume: 5093 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 5094 lsr w2, wINST, #8 // w2 <- A 5095 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 5096 TEST_IF_MARKING .Lop_sget_byte_read_barrier 5097.Lop_sget_byte_resume_after_read_barrier: 5098 .if 0 5099 ldr x0, [x0, x1] 5100 SET_VREG_WIDE x0, w2 // fp[A] <- value 5101 .elseif 0 5102 ldrsb w0, [x0, x1] 5103 UNPOISON_HEAP_REF w0 5104 // No need to check the marking register, we know it's not set here. 5105.Lop_sget_byte_after_reference_load: 5106 SET_VREG_OBJECT w0, w2 // fp[A] <- value 5107 .else 5108 ldrsb w0, [x0, x1] 5109 SET_VREG w0, w2 // fp[A] <- value 5110 .endif 5111 FETCH_ADVANCE_INST 2 5112 GET_INST_OPCODE ip 5113 GOTO_OPCODE ip 5114.Lop_sget_byte_read_barrier: 5115 bl art_quick_read_barrier_mark_reg00 5116 .if 0 5117 ldrsb w0, [x0, x1] 5118 UNPOISON_HEAP_REF w0 5119.Lop_sget_byte_mark_after_load: 5120 // Here, we know the marking register is set. 5121 bl art_quick_read_barrier_mark_reg00 5122 b .Lop_sget_byte_after_reference_load 5123 .else 5124 b .Lop_sget_byte_resume_after_read_barrier 5125 .endif 5126 5127 NAME_END nterp_op_sget_byte 5128 // Advance to the end of this handler. Causes error if we are past that point. 5129 .org nterp_op_sget_byte + NTERP_HANDLER_SIZE // op_sget_byte handler is too big! 5130 5131/* ------------------------------ */ 5132 .balign NTERP_HANDLER_SIZE 5133.L_op_sget_char: /* 0x65 */ 5134 NAME_START nterp_op_sget_char 5135 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5136 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5137 5138 // Fast-path which gets the field from thread-local cache. 5139 // Fetch some information from the thread cache. 5140 // Uses ip and ip2 as temporaries. 5141 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5142 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5143 add ip, ip, ip2, lsl #4 // entry address within the cache 5144 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5145 cmp ip, xPC 5146 b.ne nterp_op_sget_char_slow_path 5147 5148.Lop_sget_char_resume: 5149 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 5150 lsr w2, wINST, #8 // w2 <- A 5151 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 5152 TEST_IF_MARKING .Lop_sget_char_read_barrier 5153.Lop_sget_char_resume_after_read_barrier: 5154 .if 0 5155 ldr x0, [x0, x1] 5156 SET_VREG_WIDE x0, w2 // fp[A] <- value 5157 .elseif 0 5158 ldrh w0, [x0, x1] 5159 UNPOISON_HEAP_REF w0 5160 // No need to check the marking register, we know it's not set here. 5161.Lop_sget_char_after_reference_load: 5162 SET_VREG_OBJECT w0, w2 // fp[A] <- value 5163 .else 5164 ldrh w0, [x0, x1] 5165 SET_VREG w0, w2 // fp[A] <- value 5166 .endif 5167 FETCH_ADVANCE_INST 2 5168 GET_INST_OPCODE ip 5169 GOTO_OPCODE ip 5170.Lop_sget_char_read_barrier: 5171 bl art_quick_read_barrier_mark_reg00 5172 .if 0 5173 ldrh w0, [x0, x1] 5174 UNPOISON_HEAP_REF w0 5175.Lop_sget_char_mark_after_load: 5176 // Here, we know the marking register is set. 5177 bl art_quick_read_barrier_mark_reg00 5178 b .Lop_sget_char_after_reference_load 5179 .else 5180 b .Lop_sget_char_resume_after_read_barrier 5181 .endif 5182 5183 NAME_END nterp_op_sget_char 5184 // Advance to the end of this handler. Causes error if we are past that point. 5185 .org nterp_op_sget_char + NTERP_HANDLER_SIZE // op_sget_char handler is too big! 5186 5187/* ------------------------------ */ 5188 .balign NTERP_HANDLER_SIZE 5189.L_op_sget_short: /* 0x66 */ 5190 NAME_START nterp_op_sget_short 5191 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5192 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5193 5194 // Fast-path which gets the field from thread-local cache. 5195 // Fetch some information from the thread cache. 5196 // Uses ip and ip2 as temporaries. 5197 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5198 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5199 add ip, ip, ip2, lsl #4 // entry address within the cache 5200 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5201 cmp ip, xPC 5202 b.ne nterp_op_sget_short_slow_path 5203 5204.Lop_sget_short_resume: 5205 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 5206 lsr w2, wINST, #8 // w2 <- A 5207 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 5208 TEST_IF_MARKING .Lop_sget_short_read_barrier 5209.Lop_sget_short_resume_after_read_barrier: 5210 .if 0 5211 ldr x0, [x0, x1] 5212 SET_VREG_WIDE x0, w2 // fp[A] <- value 5213 .elseif 0 5214 ldrsh w0, [x0, x1] 5215 UNPOISON_HEAP_REF w0 5216 // No need to check the marking register, we know it's not set here. 5217.Lop_sget_short_after_reference_load: 5218 SET_VREG_OBJECT w0, w2 // fp[A] <- value 5219 .else 5220 ldrsh w0, [x0, x1] 5221 SET_VREG w0, w2 // fp[A] <- value 5222 .endif 5223 FETCH_ADVANCE_INST 2 5224 GET_INST_OPCODE ip 5225 GOTO_OPCODE ip 5226.Lop_sget_short_read_barrier: 5227 bl art_quick_read_barrier_mark_reg00 5228 .if 0 5229 ldrsh w0, [x0, x1] 5230 UNPOISON_HEAP_REF w0 5231.Lop_sget_short_mark_after_load: 5232 // Here, we know the marking register is set. 5233 bl art_quick_read_barrier_mark_reg00 5234 b .Lop_sget_short_after_reference_load 5235 .else 5236 b .Lop_sget_short_resume_after_read_barrier 5237 .endif 5238 5239 NAME_END nterp_op_sget_short 5240 // Advance to the end of this handler. Causes error if we are past that point. 5241 .org nterp_op_sget_short + NTERP_HANDLER_SIZE // op_sget_short handler is too big! 5242 5243/* ------------------------------ */ 5244 .balign NTERP_HANDLER_SIZE 5245.L_op_sput: /* 0x67 */ 5246 NAME_START nterp_op_sput 5247 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5248 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5249 5250 lsr w2, wINST, #8 // w2 <- A 5251 .if 0 5252 GET_VREG_WIDE x26, w2 // x26 <- v[A] 5253 .else 5254 GET_VREG w26, w2 // w26 <- v[A] 5255 .endif 5256 // Fast-path which gets the field from thread-local cache. 5257 // Fetch some information from the thread cache. 5258 // Uses ip and ip2 as temporaries. 5259 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5260 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5261 add ip, ip, ip2, lsl #4 // entry address within the cache 5262 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5263 cmp ip, xPC 5264 b.ne nterp_op_sput_slow_path 5265 5266.Lop_sput_resume: 5267 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 5268 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 5269 TEST_IF_MARKING .Lop_sput_read_barrier 5270.Lop_sput_resume_after_read_barrier: 5271 .if 0 5272 str x26, [x0, x1] 5273 .else 5274 POISON_HEAP_REF_IF_OBJECT 0, w26 5275 str w26, [x0, x1] 5276 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_skip_write_barrier 5277 .endif 5278 FETCH_ADVANCE_INST 2 5279 GET_INST_OPCODE ip 5280 GOTO_OPCODE ip 5281.Lop_sput_read_barrier: 5282 bl art_quick_read_barrier_mark_reg00 5283 b .Lop_sput_resume_after_read_barrier 5284 5285 NAME_END nterp_op_sput 5286 // Advance to the end of this handler. Causes error if we are past that point. 5287 .org nterp_op_sput + NTERP_HANDLER_SIZE // op_sput handler is too big! 5288 5289/* ------------------------------ */ 5290 .balign NTERP_HANDLER_SIZE 5291.L_op_sput_wide: /* 0x68 */ 5292 NAME_START nterp_op_sput_wide 5293 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5294 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5295 5296 lsr w2, wINST, #8 // w2 <- A 5297 .if 1 5298 GET_VREG_WIDE x26, w2 // x26 <- v[A] 5299 .else 5300 GET_VREG w26, w2 // w26 <- v[A] 5301 .endif 5302 // Fast-path which gets the field from thread-local cache. 5303 // Fetch some information from the thread cache. 5304 // Uses ip and ip2 as temporaries. 5305 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5306 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5307 add ip, ip, ip2, lsl #4 // entry address within the cache 5308 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5309 cmp ip, xPC 5310 b.ne nterp_op_sput_wide_slow_path 5311 5312.Lop_sput_wide_resume: 5313 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 5314 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 5315 TEST_IF_MARKING .Lop_sput_wide_read_barrier 5316.Lop_sput_wide_resume_after_read_barrier: 5317 .if 1 5318 str x26, [x0, x1] 5319 .else 5320 POISON_HEAP_REF_IF_OBJECT 0, w26 5321 str w26, [x0, x1] 5322 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_wide_skip_write_barrier 5323 .endif 5324 FETCH_ADVANCE_INST 2 5325 GET_INST_OPCODE ip 5326 GOTO_OPCODE ip 5327.Lop_sput_wide_read_barrier: 5328 bl art_quick_read_barrier_mark_reg00 5329 b .Lop_sput_wide_resume_after_read_barrier 5330 5331 NAME_END nterp_op_sput_wide 5332 // Advance to the end of this handler. Causes error if we are past that point. 5333 .org nterp_op_sput_wide + NTERP_HANDLER_SIZE // op_sput_wide handler is too big! 5334 5335/* ------------------------------ */ 5336 .balign NTERP_HANDLER_SIZE 5337.L_op_sput_object: /* 0x69 */ 5338 NAME_START nterp_op_sput_object 5339 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5340 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5341 5342 lsr w2, wINST, #8 // w2 <- A 5343 .if 0 5344 GET_VREG_WIDE x26, w2 // x26 <- v[A] 5345 .else 5346 GET_VREG w26, w2 // w26 <- v[A] 5347 .endif 5348 // Fast-path which gets the field from thread-local cache. 5349 // Fetch some information from the thread cache. 5350 // Uses ip and ip2 as temporaries. 5351 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5352 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5353 add ip, ip, ip2, lsl #4 // entry address within the cache 5354 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5355 cmp ip, xPC 5356 b.ne nterp_op_sput_object_slow_path 5357 5358.Lop_sput_object_resume: 5359 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 5360 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 5361 TEST_IF_MARKING .Lop_sput_object_read_barrier 5362.Lop_sput_object_resume_after_read_barrier: 5363 .if 0 5364 str x26, [x0, x1] 5365 .else 5366 POISON_HEAP_REF_IF_OBJECT 1, w26 5367 str w26, [x0, x1] 5368 WRITE_BARRIER_IF_OBJECT 1, w26, w0, .Lop_sput_object_skip_write_barrier 5369 .endif 5370 FETCH_ADVANCE_INST 2 5371 GET_INST_OPCODE ip 5372 GOTO_OPCODE ip 5373.Lop_sput_object_read_barrier: 5374 bl art_quick_read_barrier_mark_reg00 5375 b .Lop_sput_object_resume_after_read_barrier 5376 5377 NAME_END nterp_op_sput_object 5378 // Advance to the end of this handler. Causes error if we are past that point. 5379 .org nterp_op_sput_object + NTERP_HANDLER_SIZE // op_sput_object handler is too big! 5380 5381/* ------------------------------ */ 5382 .balign NTERP_HANDLER_SIZE 5383.L_op_sput_boolean: /* 0x6a */ 5384 NAME_START nterp_op_sput_boolean 5385 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5386 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5387 5388 lsr w2, wINST, #8 // w2 <- A 5389 .if 0 5390 GET_VREG_WIDE x26, w2 // x26 <- v[A] 5391 .else 5392 GET_VREG w26, w2 // w26 <- v[A] 5393 .endif 5394 // Fast-path which gets the field from thread-local cache. 5395 // Fetch some information from the thread cache. 5396 // Uses ip and ip2 as temporaries. 5397 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5398 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5399 add ip, ip, ip2, lsl #4 // entry address within the cache 5400 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5401 cmp ip, xPC 5402 b.ne nterp_op_sput_boolean_slow_path 5403 5404.Lop_sput_boolean_resume: 5405 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 5406 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 5407 TEST_IF_MARKING .Lop_sput_boolean_read_barrier 5408.Lop_sput_boolean_resume_after_read_barrier: 5409 .if 0 5410 strb x26, [x0, x1] 5411 .else 5412 POISON_HEAP_REF_IF_OBJECT 0, w26 5413 strb w26, [x0, x1] 5414 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_boolean_skip_write_barrier 5415 .endif 5416 FETCH_ADVANCE_INST 2 5417 GET_INST_OPCODE ip 5418 GOTO_OPCODE ip 5419.Lop_sput_boolean_read_barrier: 5420 bl art_quick_read_barrier_mark_reg00 5421 b .Lop_sput_boolean_resume_after_read_barrier 5422 5423 NAME_END nterp_op_sput_boolean 5424 // Advance to the end of this handler. Causes error if we are past that point. 5425 .org nterp_op_sput_boolean + NTERP_HANDLER_SIZE // op_sput_boolean handler is too big! 5426 5427/* ------------------------------ */ 5428 .balign NTERP_HANDLER_SIZE 5429.L_op_sput_byte: /* 0x6b */ 5430 NAME_START nterp_op_sput_byte 5431 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5432 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5433 5434 lsr w2, wINST, #8 // w2 <- A 5435 .if 0 5436 GET_VREG_WIDE x26, w2 // x26 <- v[A] 5437 .else 5438 GET_VREG w26, w2 // w26 <- v[A] 5439 .endif 5440 // Fast-path which gets the field from thread-local cache. 5441 // Fetch some information from the thread cache. 5442 // Uses ip and ip2 as temporaries. 5443 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5444 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5445 add ip, ip, ip2, lsl #4 // entry address within the cache 5446 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5447 cmp ip, xPC 5448 b.ne nterp_op_sput_byte_slow_path 5449 5450.Lop_sput_byte_resume: 5451 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 5452 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 5453 TEST_IF_MARKING .Lop_sput_byte_read_barrier 5454.Lop_sput_byte_resume_after_read_barrier: 5455 .if 0 5456 strb x26, [x0, x1] 5457 .else 5458 POISON_HEAP_REF_IF_OBJECT 0, w26 5459 strb w26, [x0, x1] 5460 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_byte_skip_write_barrier 5461 .endif 5462 FETCH_ADVANCE_INST 2 5463 GET_INST_OPCODE ip 5464 GOTO_OPCODE ip 5465.Lop_sput_byte_read_barrier: 5466 bl art_quick_read_barrier_mark_reg00 5467 b .Lop_sput_byte_resume_after_read_barrier 5468 5469 NAME_END nterp_op_sput_byte 5470 // Advance to the end of this handler. Causes error if we are past that point. 5471 .org nterp_op_sput_byte + NTERP_HANDLER_SIZE // op_sput_byte handler is too big! 5472 5473/* ------------------------------ */ 5474 .balign NTERP_HANDLER_SIZE 5475.L_op_sput_char: /* 0x6c */ 5476 NAME_START nterp_op_sput_char 5477 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5478 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5479 5480 lsr w2, wINST, #8 // w2 <- A 5481 .if 0 5482 GET_VREG_WIDE x26, w2 // x26 <- v[A] 5483 .else 5484 GET_VREG w26, w2 // w26 <- v[A] 5485 .endif 5486 // Fast-path which gets the field from thread-local cache. 5487 // Fetch some information from the thread cache. 5488 // Uses ip and ip2 as temporaries. 5489 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5490 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5491 add ip, ip, ip2, lsl #4 // entry address within the cache 5492 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5493 cmp ip, xPC 5494 b.ne nterp_op_sput_char_slow_path 5495 5496.Lop_sput_char_resume: 5497 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 5498 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 5499 TEST_IF_MARKING .Lop_sput_char_read_barrier 5500.Lop_sput_char_resume_after_read_barrier: 5501 .if 0 5502 strh x26, [x0, x1] 5503 .else 5504 POISON_HEAP_REF_IF_OBJECT 0, w26 5505 strh w26, [x0, x1] 5506 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_char_skip_write_barrier 5507 .endif 5508 FETCH_ADVANCE_INST 2 5509 GET_INST_OPCODE ip 5510 GOTO_OPCODE ip 5511.Lop_sput_char_read_barrier: 5512 bl art_quick_read_barrier_mark_reg00 5513 b .Lop_sput_char_resume_after_read_barrier 5514 5515 NAME_END nterp_op_sput_char 5516 // Advance to the end of this handler. Causes error if we are past that point. 5517 .org nterp_op_sput_char + NTERP_HANDLER_SIZE // op_sput_char handler is too big! 5518 5519/* ------------------------------ */ 5520 .balign NTERP_HANDLER_SIZE 5521.L_op_sput_short: /* 0x6d */ 5522 NAME_START nterp_op_sput_short 5523 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5524 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5525 5526 lsr w2, wINST, #8 // w2 <- A 5527 .if 0 5528 GET_VREG_WIDE x26, w2 // x26 <- v[A] 5529 .else 5530 GET_VREG w26, w2 // w26 <- v[A] 5531 .endif 5532 // Fast-path which gets the field from thread-local cache. 5533 // Fetch some information from the thread cache. 5534 // Uses ip and ip2 as temporaries. 5535 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5536 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5537 add ip, ip, ip2, lsl #4 // entry address within the cache 5538 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5539 cmp ip, xPC 5540 b.ne nterp_op_sput_short_slow_path 5541 5542.Lop_sput_short_resume: 5543 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 5544 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 5545 TEST_IF_MARKING .Lop_sput_short_read_barrier 5546.Lop_sput_short_resume_after_read_barrier: 5547 .if 0 5548 strh x26, [x0, x1] 5549 .else 5550 POISON_HEAP_REF_IF_OBJECT 0, w26 5551 strh w26, [x0, x1] 5552 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_short_skip_write_barrier 5553 .endif 5554 FETCH_ADVANCE_INST 2 5555 GET_INST_OPCODE ip 5556 GOTO_OPCODE ip 5557.Lop_sput_short_read_barrier: 5558 bl art_quick_read_barrier_mark_reg00 5559 b .Lop_sput_short_resume_after_read_barrier 5560 5561 NAME_END nterp_op_sput_short 5562 // Advance to the end of this handler. Causes error if we are past that point. 5563 .org nterp_op_sput_short + NTERP_HANDLER_SIZE // op_sput_short handler is too big! 5564 5565/* ------------------------------ */ 5566 .balign NTERP_HANDLER_SIZE 5567.L_op_invoke_virtual: /* 0x6e */ 5568 NAME_START nterp_op_invoke_virtual 5569 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5570 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5571 5572 EXPORT_PC 5573 // Fast-path which gets the method from thread-local cache. 5574 // Fetch some information from the thread cache. 5575 // Uses ip and ip2 as temporaries. 5576 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5577 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5578 add ip, ip, ip2, lsl #4 // entry address within the cache 5579 ldp ip, x2, [ip] // entry key (pc) and value (offset) 5580 cmp ip, xPC 5581 b.ne 2f 5582 55831: 5584 FETCH w1, 2 5585 .if !0 5586 and w1, w1, #0xf 5587 .endif 5588 GET_VREG w1, w1 5589 // Note: if w1 is null, this will be handled by our SIGSEGV handler. 5590 ldr w0, [x1, #MIRROR_OBJECT_CLASS_OFFSET] 5591 UNPOISON_HEAP_REF w0 5592 add w0, w0, #MIRROR_CLASS_VTABLE_OFFSET_64 5593 ldr x0, [x0, w2, uxtw #3] 5594 b NterpCommonInvokeInstance 55952: 5596 mov x0, xSELF 5597 ldr x1, [sp] 5598 mov x2, xPC 5599 bl nterp_get_method 5600 mov x2, x0 5601 b 1b 5602 5603 NAME_END nterp_op_invoke_virtual 5604 // Advance to the end of this handler. Causes error if we are past that point. 5605 .org nterp_op_invoke_virtual + NTERP_HANDLER_SIZE // op_invoke_virtual handler is too big! 5606 5607/* ------------------------------ */ 5608 .balign NTERP_HANDLER_SIZE 5609.L_op_invoke_super: /* 0x6f */ 5610 NAME_START nterp_op_invoke_super 5611 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5612 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5613 5614 EXPORT_PC 5615 // Fast-path which gets the method from thread-local cache. 5616 // Fetch some information from the thread cache. 5617 // Uses ip and ip2 as temporaries. 5618 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5619 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5620 add ip, ip, ip2, lsl #4 // entry address within the cache 5621 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5622 cmp ip, xPC 5623 b.ne 2f 5624 56251: 5626 // Load the first argument (the 'this' pointer). 5627 FETCH w1, 2 5628 .if !0 5629 and w1, w1, #0xf 5630 .endif 5631 GET_VREG w1, w1 5632 cbz w1, common_errNullObject // bail if null 5633 b NterpCommonInvokeInstance 56342: 5635 mov x0, xSELF 5636 ldr x1, [sp] 5637 mov x2, xPC 5638 bl nterp_get_method 5639 .if 1 5640 b 1b 5641 .else 5642 tbz x0, #0, 1b 5643 and x0, x0, #-2 // Remove the extra bit that marks it's a String.<init> method. 5644 .if 0 5645 b NterpHandleStringInitRange 5646 .else 5647 b NterpHandleStringInit 5648 .endif 5649 .endif 5650 5651 NAME_END nterp_op_invoke_super 5652 // Advance to the end of this handler. Causes error if we are past that point. 5653 .org nterp_op_invoke_super + NTERP_HANDLER_SIZE // op_invoke_super handler is too big! 5654 5655/* ------------------------------ */ 5656 .balign NTERP_HANDLER_SIZE 5657.L_op_invoke_direct: /* 0x70 */ 5658 NAME_START nterp_op_invoke_direct 5659 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5660 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5661 5662 EXPORT_PC 5663 // Fast-path which gets the method from thread-local cache. 5664 // Fetch some information from the thread cache. 5665 // Uses ip and ip2 as temporaries. 5666 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5667 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5668 add ip, ip, ip2, lsl #4 // entry address within the cache 5669 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5670 cmp ip, xPC 5671 b.ne 2f 5672 56731: 5674 // Load the first argument (the 'this' pointer). 5675 FETCH w1, 2 5676 .if !0 5677 and w1, w1, #0xf 5678 .endif 5679 GET_VREG w1, w1 5680 cbz w1, common_errNullObject // bail if null 5681 b NterpCommonInvokeInstance 56822: 5683 mov x0, xSELF 5684 ldr x1, [sp] 5685 mov x2, xPC 5686 bl nterp_get_method 5687 .if 0 5688 b 1b 5689 .else 5690 tbz x0, #0, 1b 5691 and x0, x0, #-2 // Remove the extra bit that marks it's a String.<init> method. 5692 .if 0 5693 b NterpHandleStringInitRange 5694 .else 5695 b NterpHandleStringInit 5696 .endif 5697 .endif 5698 5699 NAME_END nterp_op_invoke_direct 5700 // Advance to the end of this handler. Causes error if we are past that point. 5701 .org nterp_op_invoke_direct + NTERP_HANDLER_SIZE // op_invoke_direct handler is too big! 5702 5703/* ------------------------------ */ 5704 .balign NTERP_HANDLER_SIZE 5705.L_op_invoke_static: /* 0x71 */ 5706 NAME_START nterp_op_invoke_static 5707 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5708 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5709 5710 EXPORT_PC 5711 // Fast-path which gets the method from thread-local cache. 5712 // Fetch some information from the thread cache. 5713 // Uses ip and ip2 as temporaries. 5714 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5715 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5716 add ip, ip, ip2, lsl #4 // entry address within the cache 5717 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5718 cmp ip, xPC 5719 b.ne 1f 5720 5721 b NterpCommonInvokeStatic 57221: 5723 mov x0, xSELF 5724 ldr x1, [sp] 5725 mov x2, xPC 5726 bl nterp_get_method 5727 b NterpCommonInvokeStatic 5728 5729 NAME_END nterp_op_invoke_static 5730 // Advance to the end of this handler. Causes error if we are past that point. 5731 .org nterp_op_invoke_static + NTERP_HANDLER_SIZE // op_invoke_static handler is too big! 5732 5733/* ------------------------------ */ 5734 .balign NTERP_HANDLER_SIZE 5735.L_op_invoke_interface: /* 0x72 */ 5736 NAME_START nterp_op_invoke_interface 5737 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5738 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5739 5740 EXPORT_PC 5741 // Fast-path which gets the method from thread-local cache. 5742 // Fetch some information from the thread cache. 5743 // Uses ip and ip2 as temporaries. 5744 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5745 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5746 add ip, ip, ip2, lsl #4 // entry address within the cache 5747 ldp ip, x26, [ip] // entry key (pc) and value (offset) 5748 cmp ip, xPC 5749 b.ne nterp_op_invoke_interface_slow_path 5750 5751.Lop_invoke_interface_resume: 5752 // First argument is the 'this' pointer. 5753 FETCH w1, 2 5754 .if !0 5755 and w1, w1, #0xf 5756 .endif 5757 GET_VREG w1, w1 5758 // Note: if w1 is null, this will be handled by our SIGSEGV handler. 5759 ldr w2, [x1, #MIRROR_OBJECT_CLASS_OFFSET] 5760 UNPOISON_HEAP_REF w2 5761 // Test the first two bits of the fetched ArtMethod: 5762 // - If the first bit is set, this is a method on j.l.Object 5763 // - If the second bit is set, this is a default method. 5764 tst w26, #0x3 5765 b.ne 2f 5766 ldrh w3, [x26, #ART_METHOD_IMT_INDEX_OFFSET] 57671: 5768 ldr x2, [x2, #MIRROR_CLASS_IMT_PTR_OFFSET_64] 5769 ldr x0, [x2, w3, uxtw #3] 5770 .if 0 5771 b NterpCommonInvokeInterfaceRange 5772 .else 5773 b NterpCommonInvokeInterface 5774 .endif 57752: 5776 tbnz w26, #0, 3f 5777 and x26, x26, #-4 5778 ldrh w3, [x26, #ART_METHOD_METHOD_INDEX_OFFSET] 5779 and w3, w3, #ART_METHOD_IMT_MASK 5780 b 1b 57813: 5782 lsr w26, w26, #16 5783 add w2, w2, #MIRROR_CLASS_VTABLE_OFFSET_64 5784 ldr x0, [x2, w26, uxtw #3] 5785 .if 0 5786 b NterpCommonInvokeInstanceRange 5787 .else 5788 b NterpCommonInvokeInstance 5789 .endif 5790 5791 NAME_END nterp_op_invoke_interface 5792 // Advance to the end of this handler. Causes error if we are past that point. 5793 .org nterp_op_invoke_interface + NTERP_HANDLER_SIZE // op_invoke_interface handler is too big! 5794 5795/* ------------------------------ */ 5796 .balign NTERP_HANDLER_SIZE 5797.L_op_unused_73: /* 0x73 */ 5798 NAME_START nterp_op_unused_73 5799 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5800 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5801 5802 brk 42 5803 5804 NAME_END nterp_op_unused_73 5805 // Advance to the end of this handler. Causes error if we are past that point. 5806 .org nterp_op_unused_73 + NTERP_HANDLER_SIZE // op_unused_73 handler is too big! 5807 5808/* ------------------------------ */ 5809 .balign NTERP_HANDLER_SIZE 5810.L_op_invoke_virtual_range: /* 0x74 */ 5811 NAME_START nterp_op_invoke_virtual_range 5812 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5813 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5814 5815 EXPORT_PC 5816 // Fast-path which gets the method from thread-local cache. 5817 // Fetch some information from the thread cache. 5818 // Uses ip and ip2 as temporaries. 5819 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5820 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5821 add ip, ip, ip2, lsl #4 // entry address within the cache 5822 ldp ip, x2, [ip] // entry key (pc) and value (offset) 5823 cmp ip, xPC 5824 b.ne 2f 5825 58261: 5827 FETCH w1, 2 5828 .if !1 5829 and w1, w1, #0xf 5830 .endif 5831 GET_VREG w1, w1 5832 // Note: if w1 is null, this will be handled by our SIGSEGV handler. 5833 ldr w0, [x1, #MIRROR_OBJECT_CLASS_OFFSET] 5834 UNPOISON_HEAP_REF w0 5835 add w0, w0, #MIRROR_CLASS_VTABLE_OFFSET_64 5836 ldr x0, [x0, w2, uxtw #3] 5837 b NterpCommonInvokeInstanceRange 58382: 5839 mov x0, xSELF 5840 ldr x1, [sp] 5841 mov x2, xPC 5842 bl nterp_get_method 5843 mov x2, x0 5844 b 1b 5845 5846 NAME_END nterp_op_invoke_virtual_range 5847 // Advance to the end of this handler. Causes error if we are past that point. 5848 .org nterp_op_invoke_virtual_range + NTERP_HANDLER_SIZE // op_invoke_virtual_range handler is too big! 5849 5850/* ------------------------------ */ 5851 .balign NTERP_HANDLER_SIZE 5852.L_op_invoke_super_range: /* 0x75 */ 5853 NAME_START nterp_op_invoke_super_range 5854 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5855 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5856 5857 EXPORT_PC 5858 // Fast-path which gets the method from thread-local cache. 5859 // Fetch some information from the thread cache. 5860 // Uses ip and ip2 as temporaries. 5861 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5862 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5863 add ip, ip, ip2, lsl #4 // entry address within the cache 5864 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5865 cmp ip, xPC 5866 b.ne 2f 5867 58681: 5869 // Load the first argument (the 'this' pointer). 5870 FETCH w1, 2 5871 .if !1 5872 and w1, w1, #0xf 5873 .endif 5874 GET_VREG w1, w1 5875 cbz w1, common_errNullObject // bail if null 5876 b NterpCommonInvokeInstanceRange 58772: 5878 mov x0, xSELF 5879 ldr x1, [sp] 5880 mov x2, xPC 5881 bl nterp_get_method 5882 .if 1 5883 b 1b 5884 .else 5885 tbz x0, #0, 1b 5886 and x0, x0, #-2 // Remove the extra bit that marks it's a String.<init> method. 5887 .if 1 5888 b NterpHandleStringInitRange 5889 .else 5890 b NterpHandleStringInit 5891 .endif 5892 .endif 5893 5894 NAME_END nterp_op_invoke_super_range 5895 // Advance to the end of this handler. Causes error if we are past that point. 5896 .org nterp_op_invoke_super_range + NTERP_HANDLER_SIZE // op_invoke_super_range handler is too big! 5897 5898/* ------------------------------ */ 5899 .balign NTERP_HANDLER_SIZE 5900.L_op_invoke_direct_range: /* 0x76 */ 5901 NAME_START nterp_op_invoke_direct_range 5902 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5903 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5904 5905 EXPORT_PC 5906 // Fast-path which gets the method from thread-local cache. 5907 // Fetch some information from the thread cache. 5908 // Uses ip and ip2 as temporaries. 5909 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5910 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5911 add ip, ip, ip2, lsl #4 // entry address within the cache 5912 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5913 cmp ip, xPC 5914 b.ne 2f 5915 59161: 5917 // Load the first argument (the 'this' pointer). 5918 FETCH w1, 2 5919 .if !1 5920 and w1, w1, #0xf 5921 .endif 5922 GET_VREG w1, w1 5923 cbz w1, common_errNullObject // bail if null 5924 b NterpCommonInvokeInstanceRange 59252: 5926 mov x0, xSELF 5927 ldr x1, [sp] 5928 mov x2, xPC 5929 bl nterp_get_method 5930 .if 0 5931 b 1b 5932 .else 5933 tbz x0, #0, 1b 5934 and x0, x0, #-2 // Remove the extra bit that marks it's a String.<init> method. 5935 .if 1 5936 b NterpHandleStringInitRange 5937 .else 5938 b NterpHandleStringInit 5939 .endif 5940 .endif 5941 5942 NAME_END nterp_op_invoke_direct_range 5943 // Advance to the end of this handler. Causes error if we are past that point. 5944 .org nterp_op_invoke_direct_range + NTERP_HANDLER_SIZE // op_invoke_direct_range handler is too big! 5945 5946/* ------------------------------ */ 5947 .balign NTERP_HANDLER_SIZE 5948.L_op_invoke_static_range: /* 0x77 */ 5949 NAME_START nterp_op_invoke_static_range 5950 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5951 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5952 5953 EXPORT_PC 5954 // Fast-path which gets the method from thread-local cache. 5955 // Fetch some information from the thread cache. 5956 // Uses ip and ip2 as temporaries. 5957 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5958 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5959 add ip, ip, ip2, lsl #4 // entry address within the cache 5960 ldp ip, x0, [ip] // entry key (pc) and value (offset) 5961 cmp ip, xPC 5962 b.ne 1f 5963 5964 b NterpCommonInvokeStaticRange 59651: 5966 mov x0, xSELF 5967 ldr x1, [sp] 5968 mov x2, xPC 5969 bl nterp_get_method 5970 b NterpCommonInvokeStaticRange 5971 5972 NAME_END nterp_op_invoke_static_range 5973 // Advance to the end of this handler. Causes error if we are past that point. 5974 .org nterp_op_invoke_static_range + NTERP_HANDLER_SIZE // op_invoke_static_range handler is too big! 5975 5976/* ------------------------------ */ 5977 .balign NTERP_HANDLER_SIZE 5978.L_op_invoke_interface_range: /* 0x78 */ 5979 NAME_START nterp_op_invoke_interface_range 5980 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 5981 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 5982 5983 EXPORT_PC 5984 // Fast-path which gets the method from thread-local cache. 5985 // Fetch some information from the thread cache. 5986 // Uses ip and ip2 as temporaries. 5987 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 5988 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 5989 add ip, ip, ip2, lsl #4 // entry address within the cache 5990 ldp ip, x26, [ip] // entry key (pc) and value (offset) 5991 cmp ip, xPC 5992 b.ne nterp_op_invoke_interface_range_slow_path 5993 5994.Lop_invoke_interface_range_resume: 5995 // First argument is the 'this' pointer. 5996 FETCH w1, 2 5997 .if !1 5998 and w1, w1, #0xf 5999 .endif 6000 GET_VREG w1, w1 6001 // Note: if w1 is null, this will be handled by our SIGSEGV handler. 6002 ldr w2, [x1, #MIRROR_OBJECT_CLASS_OFFSET] 6003 UNPOISON_HEAP_REF w2 6004 // Test the first two bits of the fetched ArtMethod: 6005 // - If the first bit is set, this is a method on j.l.Object 6006 // - If the second bit is set, this is a default method. 6007 tst w26, #0x3 6008 b.ne 2f 6009 ldrh w3, [x26, #ART_METHOD_IMT_INDEX_OFFSET] 60101: 6011 ldr x2, [x2, #MIRROR_CLASS_IMT_PTR_OFFSET_64] 6012 ldr x0, [x2, w3, uxtw #3] 6013 .if 1 6014 b NterpCommonInvokeInterfaceRange 6015 .else 6016 b NterpCommonInvokeInterface 6017 .endif 60182: 6019 tbnz w26, #0, 3f 6020 and x26, x26, #-4 6021 ldrh w3, [x26, #ART_METHOD_METHOD_INDEX_OFFSET] 6022 and w3, w3, #ART_METHOD_IMT_MASK 6023 b 1b 60243: 6025 lsr w26, w26, #16 6026 add w2, w2, #MIRROR_CLASS_VTABLE_OFFSET_64 6027 ldr x0, [x2, w26, uxtw #3] 6028 .if 1 6029 b NterpCommonInvokeInstanceRange 6030 .else 6031 b NterpCommonInvokeInstance 6032 .endif 6033 6034 NAME_END nterp_op_invoke_interface_range 6035 // Advance to the end of this handler. Causes error if we are past that point. 6036 .org nterp_op_invoke_interface_range + NTERP_HANDLER_SIZE // op_invoke_interface_range handler is too big! 6037 6038/* ------------------------------ */ 6039 .balign NTERP_HANDLER_SIZE 6040.L_op_unused_79: /* 0x79 */ 6041 NAME_START nterp_op_unused_79 6042 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6043 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6044 6045 brk 42 6046 6047 NAME_END nterp_op_unused_79 6048 // Advance to the end of this handler. Causes error if we are past that point. 6049 .org nterp_op_unused_79 + NTERP_HANDLER_SIZE // op_unused_79 handler is too big! 6050 6051/* ------------------------------ */ 6052 .balign NTERP_HANDLER_SIZE 6053.L_op_unused_7a: /* 0x7a */ 6054 NAME_START nterp_op_unused_7a 6055 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6056 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6057 6058 brk 42 6059 6060 NAME_END nterp_op_unused_7a 6061 // Advance to the end of this handler. Causes error if we are past that point. 6062 .org nterp_op_unused_7a + NTERP_HANDLER_SIZE // op_unused_7a handler is too big! 6063 6064/* ------------------------------ */ 6065 .balign NTERP_HANDLER_SIZE 6066.L_op_neg_int: /* 0x7b */ 6067 NAME_START nterp_op_neg_int 6068 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6069 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6070 6071 /* 6072 * Generic 32-bit unary operation. Provide an "instr" line that 6073 * specifies an instruction that performs "result = op w0". 6074 * This could be an ARM instruction or a function call. 6075 * 6076 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 6077 * int-to-byte, int-to-char, int-to-short 6078 */ 6079 /* unop vA, vB */ 6080 lsr w3, wINST, #12 // w3<- B 6081 GET_VREG w0, w3 // w0<- vB 6082 ubfx w9, wINST, #8, #4 // w9<- A 6083 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 6084 sub w0, wzr, w0 // w0<- op, w0-w3 changed 6085 GET_INST_OPCODE ip // extract opcode from rINST 6086 SET_VREG w0, w9 // vAA<- w0 6087 GOTO_OPCODE ip // jump to next instruction 6088 /* 8-9 instructions */ 6089 6090 NAME_END nterp_op_neg_int 6091 // Advance to the end of this handler. Causes error if we are past that point. 6092 .org nterp_op_neg_int + NTERP_HANDLER_SIZE // op_neg_int handler is too big! 6093 6094/* ------------------------------ */ 6095 .balign NTERP_HANDLER_SIZE 6096.L_op_not_int: /* 0x7c */ 6097 NAME_START nterp_op_not_int 6098 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6099 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6100 6101 /* 6102 * Generic 32-bit unary operation. Provide an "instr" line that 6103 * specifies an instruction that performs "result = op w0". 6104 * This could be an ARM instruction or a function call. 6105 * 6106 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 6107 * int-to-byte, int-to-char, int-to-short 6108 */ 6109 /* unop vA, vB */ 6110 lsr w3, wINST, #12 // w3<- B 6111 GET_VREG w0, w3 // w0<- vB 6112 ubfx w9, wINST, #8, #4 // w9<- A 6113 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 6114 mvn w0, w0 // w0<- op, w0-w3 changed 6115 GET_INST_OPCODE ip // extract opcode from rINST 6116 SET_VREG w0, w9 // vAA<- w0 6117 GOTO_OPCODE ip // jump to next instruction 6118 /* 8-9 instructions */ 6119 6120 NAME_END nterp_op_not_int 6121 // Advance to the end of this handler. Causes error if we are past that point. 6122 .org nterp_op_not_int + NTERP_HANDLER_SIZE // op_not_int handler is too big! 6123 6124/* ------------------------------ */ 6125 .balign NTERP_HANDLER_SIZE 6126.L_op_neg_long: /* 0x7d */ 6127 NAME_START nterp_op_neg_long 6128 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6129 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6130 6131 /* 6132 * Generic 64-bit unary operation. Provide an "instr" line that 6133 * specifies an instruction that performs "result = op x0". 6134 * 6135 * For: neg-long, not-long 6136 */ 6137 /* unop vA, vB */ 6138 lsr w3, wINST, #12 // w3<- B 6139 ubfx w4, wINST, #8, #4 // w4<- A 6140 GET_VREG_WIDE x0, w3 6141 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6142 sub x0, xzr, x0 6143 GET_INST_OPCODE ip // extract opcode from wINST 6144 SET_VREG_WIDE x0, w4 6145 GOTO_OPCODE ip // jump to next instruction 6146 /* 10-11 instructions */ 6147 6148 NAME_END nterp_op_neg_long 6149 // Advance to the end of this handler. Causes error if we are past that point. 6150 .org nterp_op_neg_long + NTERP_HANDLER_SIZE // op_neg_long handler is too big! 6151 6152/* ------------------------------ */ 6153 .balign NTERP_HANDLER_SIZE 6154.L_op_not_long: /* 0x7e */ 6155 NAME_START nterp_op_not_long 6156 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6157 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6158 6159 /* 6160 * Generic 64-bit unary operation. Provide an "instr" line that 6161 * specifies an instruction that performs "result = op x0". 6162 * 6163 * For: neg-long, not-long 6164 */ 6165 /* unop vA, vB */ 6166 lsr w3, wINST, #12 // w3<- B 6167 ubfx w4, wINST, #8, #4 // w4<- A 6168 GET_VREG_WIDE x0, w3 6169 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6170 mvn x0, x0 6171 GET_INST_OPCODE ip // extract opcode from wINST 6172 SET_VREG_WIDE x0, w4 6173 GOTO_OPCODE ip // jump to next instruction 6174 /* 10-11 instructions */ 6175 6176 NAME_END nterp_op_not_long 6177 // Advance to the end of this handler. Causes error if we are past that point. 6178 .org nterp_op_not_long + NTERP_HANDLER_SIZE // op_not_long handler is too big! 6179 6180/* ------------------------------ */ 6181 .balign NTERP_HANDLER_SIZE 6182.L_op_neg_float: /* 0x7f */ 6183 NAME_START nterp_op_neg_float 6184 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6185 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6186 6187 /* 6188 * Generic 32-bit unary operation. Provide an "instr" line that 6189 * specifies an instruction that performs "result = op w0". 6190 * This could be an ARM instruction or a function call. 6191 * 6192 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 6193 * int-to-byte, int-to-char, int-to-short 6194 */ 6195 /* unop vA, vB */ 6196 lsr w3, wINST, #12 // w3<- B 6197 GET_VREG w0, w3 // w0<- vB 6198 ubfx w9, wINST, #8, #4 // w9<- A 6199 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 6200 eor w0, w0, #0x80000000 // w0<- op, w0-w3 changed 6201 GET_INST_OPCODE ip // extract opcode from rINST 6202 SET_VREG w0, w9 // vAA<- w0 6203 GOTO_OPCODE ip // jump to next instruction 6204 /* 8-9 instructions */ 6205 6206 NAME_END nterp_op_neg_float 6207 // Advance to the end of this handler. Causes error if we are past that point. 6208 .org nterp_op_neg_float + NTERP_HANDLER_SIZE // op_neg_float handler is too big! 6209 6210/* ------------------------------ */ 6211 .balign NTERP_HANDLER_SIZE 6212.L_op_neg_double: /* 0x80 */ 6213 NAME_START nterp_op_neg_double 6214 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6215 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6216 6217 /* 6218 * Generic 64-bit unary operation. Provide an "instr" line that 6219 * specifies an instruction that performs "result = op x0". 6220 * 6221 * For: neg-long, not-long 6222 */ 6223 /* unop vA, vB */ 6224 lsr w3, wINST, #12 // w3<- B 6225 ubfx w4, wINST, #8, #4 // w4<- A 6226 GET_VREG_WIDE x0, w3 6227 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6228 eor x0, x0, #0x8000000000000000 6229 GET_INST_OPCODE ip // extract opcode from wINST 6230 SET_VREG_WIDE x0, w4 6231 GOTO_OPCODE ip // jump to next instruction 6232 /* 10-11 instructions */ 6233 6234 NAME_END nterp_op_neg_double 6235 // Advance to the end of this handler. Causes error if we are past that point. 6236 .org nterp_op_neg_double + NTERP_HANDLER_SIZE // op_neg_double handler is too big! 6237 6238/* ------------------------------ */ 6239 .balign NTERP_HANDLER_SIZE 6240.L_op_int_to_long: /* 0x81 */ 6241 NAME_START nterp_op_int_to_long 6242 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6243 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6244 6245 /* int-to-long vA, vB */ 6246 lsr w3, wINST, #12 // w3<- B 6247 ubfx w4, wINST, #8, #4 // w4<- A 6248 GET_VREG_S x0, w3 // x0<- sign_extend(fp[B]) 6249 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6250 GET_INST_OPCODE ip // extract opcode from wINST 6251 SET_VREG_WIDE x0, w4 // fp[A]<- x0 6252 GOTO_OPCODE ip // jump to next instruction 6253 6254 NAME_END nterp_op_int_to_long 6255 // Advance to the end of this handler. Causes error if we are past that point. 6256 .org nterp_op_int_to_long + NTERP_HANDLER_SIZE // op_int_to_long handler is too big! 6257 6258/* ------------------------------ */ 6259 .balign NTERP_HANDLER_SIZE 6260.L_op_int_to_float: /* 0x82 */ 6261 NAME_START nterp_op_int_to_float 6262 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6263 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6264 6265 /* 6266 * Generic 32bit-to-32bit floating point unary operation. Provide an 6267 * "instr" line that specifies an instruction that performs "s0 = op w0". 6268 * 6269 * For: int-to-float, float-to-int 6270 * TODO: refactor all of the conversions - parameterize width and use same template. 6271 */ 6272 /* unop vA, vB */ 6273 lsr w3, wINST, #12 // w3<- B 6274 ubfx w4, wINST, #8, #4 // w4<- A 6275 GET_VREG w0, w3 6276 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6277 scvtf s0, w0 // d0<- op 6278 GET_INST_OPCODE ip // extract opcode from wINST 6279 SET_VREG_FLOAT s0, w4 // vA<- d0 6280 GOTO_OPCODE ip // jump to next instruction 6281 6282 NAME_END nterp_op_int_to_float 6283 // Advance to the end of this handler. Causes error if we are past that point. 6284 .org nterp_op_int_to_float + NTERP_HANDLER_SIZE // op_int_to_float handler is too big! 6285 6286/* ------------------------------ */ 6287 .balign NTERP_HANDLER_SIZE 6288.L_op_int_to_double: /* 0x83 */ 6289 NAME_START nterp_op_int_to_double 6290 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6291 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6292 6293 /* 6294 * Generic 32bit-to-64bit floating point unary operation. Provide an 6295 * "instr" line that specifies an instruction that performs "d0 = op w0". 6296 * 6297 * For: int-to-double, float-to-double, float-to-long 6298 */ 6299 /* unop vA, vB */ 6300 lsr w3, wINST, #12 // w3<- B 6301 ubfx w4, wINST, #8, #4 // w4<- A 6302 GET_VREG w0, w3 6303 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6304 scvtf d0, w0 // d0<- op 6305 GET_INST_OPCODE ip // extract opcode from wINST 6306 SET_VREG_WIDE d0, w4 // vA<- d0 6307 GOTO_OPCODE ip // jump to next instruction 6308 6309 NAME_END nterp_op_int_to_double 6310 // Advance to the end of this handler. Causes error if we are past that point. 6311 .org nterp_op_int_to_double + NTERP_HANDLER_SIZE // op_int_to_double handler is too big! 6312 6313/* ------------------------------ */ 6314 .balign NTERP_HANDLER_SIZE 6315.L_op_long_to_int: /* 0x84 */ 6316 NAME_START nterp_op_long_to_int 6317 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6318 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6319 6320/* we ignore the high word, making this equivalent to a 32-bit reg move */ 6321 /* for move, move-object, long-to-int */ 6322 /* op vA, vB */ 6323 lsr w1, wINST, #12 // x1<- B from 15:12 6324 ubfx w0, wINST, #8, #4 // x0<- A from 11:8 6325 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6326 GET_VREG w2, w1 // x2<- fp[B] 6327 GET_INST_OPCODE ip // ip<- opcode from wINST 6328 .if 0 6329 SET_VREG_OBJECT w2, w0 // fp[A]<- x2 6330 .else 6331 SET_VREG w2, w0 // fp[A]<- x2 6332 .endif 6333 GOTO_OPCODE ip // execute next instruction 6334 6335 NAME_END nterp_op_long_to_int 6336 // Advance to the end of this handler. Causes error if we are past that point. 6337 .org nterp_op_long_to_int + NTERP_HANDLER_SIZE // op_long_to_int handler is too big! 6338 6339/* ------------------------------ */ 6340 .balign NTERP_HANDLER_SIZE 6341.L_op_long_to_float: /* 0x85 */ 6342 NAME_START nterp_op_long_to_float 6343 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6344 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6345 6346 /* 6347 * Generic 64bit-to-32bit floating point unary operation. Provide an 6348 * "instr" line that specifies an instruction that performs "s0 = op x0". 6349 * 6350 * For: int-to-double, float-to-double, float-to-long 6351 */ 6352 /* unop vA, vB */ 6353 lsr w3, wINST, #12 // w3<- B 6354 ubfx w4, wINST, #8, #4 // w4<- A 6355 GET_VREG_WIDE x0, w3 6356 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6357 scvtf s0, x0 // d0<- op 6358 GET_INST_OPCODE ip // extract opcode from wINST 6359 SET_VREG_FLOAT s0, w4 // vA<- d0 6360 GOTO_OPCODE ip // jump to next instruction 6361 6362 NAME_END nterp_op_long_to_float 6363 // Advance to the end of this handler. Causes error if we are past that point. 6364 .org nterp_op_long_to_float + NTERP_HANDLER_SIZE // op_long_to_float handler is too big! 6365 6366/* ------------------------------ */ 6367 .balign NTERP_HANDLER_SIZE 6368.L_op_long_to_double: /* 0x86 */ 6369 NAME_START nterp_op_long_to_double 6370 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6371 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6372 6373 /* 6374 * Generic 64bit-to-64bit floating point unary operation. Provide an 6375 * "instr" line that specifies an instruction that performs "d0 = op x0". 6376 * 6377 * For: long-to-double, double-to-long 6378 */ 6379 /* unop vA, vB */ 6380 lsr w3, wINST, #12 // w3<- B 6381 ubfx w4, wINST, #8, #4 // w4<- A 6382 GET_VREG_WIDE x0, w3 6383 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6384 scvtf d0, x0 // d0<- op 6385 GET_INST_OPCODE ip // extract opcode from wINST 6386 SET_VREG_DOUBLE d0, w4 // vA<- d0 6387 GOTO_OPCODE ip // jump to next instruction 6388 6389 NAME_END nterp_op_long_to_double 6390 // Advance to the end of this handler. Causes error if we are past that point. 6391 .org nterp_op_long_to_double + NTERP_HANDLER_SIZE // op_long_to_double handler is too big! 6392 6393/* ------------------------------ */ 6394 .balign NTERP_HANDLER_SIZE 6395.L_op_float_to_int: /* 0x87 */ 6396 NAME_START nterp_op_float_to_int 6397 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6398 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6399 6400 /* 6401 * Generic 32bit-to-32bit floating point unary operation. Provide an 6402 * "instr" line that specifies an instruction that performs "w0 = op s0". 6403 * 6404 * For: int-to-float, float-to-int 6405 * TODO: refactor all of the conversions - parameterize width and use same template. 6406 */ 6407 /* unop vA, vB */ 6408 lsr w3, wINST, #12 // w3<- B 6409 ubfx w4, wINST, #8, #4 // w4<- A 6410 GET_VREG s0, w3 6411 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6412 fcvtzs w0, s0 // d0<- op 6413 GET_INST_OPCODE ip // extract opcode from wINST 6414 SET_VREG_FLOAT w0, w4 // vA<- d0 6415 GOTO_OPCODE ip // jump to next instruction 6416 6417 NAME_END nterp_op_float_to_int 6418 // Advance to the end of this handler. Causes error if we are past that point. 6419 .org nterp_op_float_to_int + NTERP_HANDLER_SIZE // op_float_to_int handler is too big! 6420 6421/* ------------------------------ */ 6422 .balign NTERP_HANDLER_SIZE 6423.L_op_float_to_long: /* 0x88 */ 6424 NAME_START nterp_op_float_to_long 6425 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6426 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6427 6428 /* 6429 * Generic 32bit-to-64bit floating point unary operation. Provide an 6430 * "instr" line that specifies an instruction that performs "x0 = op s0". 6431 * 6432 * For: int-to-double, float-to-double, float-to-long 6433 */ 6434 /* unop vA, vB */ 6435 lsr w3, wINST, #12 // w3<- B 6436 ubfx w4, wINST, #8, #4 // w4<- A 6437 GET_VREG s0, w3 6438 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6439 fcvtzs x0, s0 // d0<- op 6440 GET_INST_OPCODE ip // extract opcode from wINST 6441 SET_VREG_WIDE x0, w4 // vA<- d0 6442 GOTO_OPCODE ip // jump to next instruction 6443 6444 NAME_END nterp_op_float_to_long 6445 // Advance to the end of this handler. Causes error if we are past that point. 6446 .org nterp_op_float_to_long + NTERP_HANDLER_SIZE // op_float_to_long handler is too big! 6447 6448/* ------------------------------ */ 6449 .balign NTERP_HANDLER_SIZE 6450.L_op_float_to_double: /* 0x89 */ 6451 NAME_START nterp_op_float_to_double 6452 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6453 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6454 6455 /* 6456 * Generic 32bit-to-64bit floating point unary operation. Provide an 6457 * "instr" line that specifies an instruction that performs "d0 = op s0". 6458 * 6459 * For: int-to-double, float-to-double, float-to-long 6460 */ 6461 /* unop vA, vB */ 6462 lsr w3, wINST, #12 // w3<- B 6463 ubfx w4, wINST, #8, #4 // w4<- A 6464 GET_VREG s0, w3 6465 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6466 fcvt d0, s0 // d0<- op 6467 GET_INST_OPCODE ip // extract opcode from wINST 6468 SET_VREG_WIDE d0, w4 // vA<- d0 6469 GOTO_OPCODE ip // jump to next instruction 6470 6471 NAME_END nterp_op_float_to_double 6472 // Advance to the end of this handler. Causes error if we are past that point. 6473 .org nterp_op_float_to_double + NTERP_HANDLER_SIZE // op_float_to_double handler is too big! 6474 6475/* ------------------------------ */ 6476 .balign NTERP_HANDLER_SIZE 6477.L_op_double_to_int: /* 0x8a */ 6478 NAME_START nterp_op_double_to_int 6479 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6480 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6481 6482 /* 6483 * Generic 64bit-to-32bit floating point unary operation. Provide an 6484 * "instr" line that specifies an instruction that performs "w0 = op d0". 6485 * 6486 * For: int-to-double, float-to-double, float-to-long 6487 */ 6488 /* unop vA, vB */ 6489 lsr w3, wINST, #12 // w3<- B 6490 ubfx w4, wINST, #8, #4 // w4<- A 6491 GET_VREG_DOUBLE d0, w3 6492 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6493 fcvtzs w0, d0 // d0<- op 6494 GET_INST_OPCODE ip // extract opcode from wINST 6495 SET_VREG_FLOAT w0, w4 // vA<- d0 6496 GOTO_OPCODE ip // jump to next instruction 6497 6498 NAME_END nterp_op_double_to_int 6499 // Advance to the end of this handler. Causes error if we are past that point. 6500 .org nterp_op_double_to_int + NTERP_HANDLER_SIZE // op_double_to_int handler is too big! 6501 6502/* ------------------------------ */ 6503 .balign NTERP_HANDLER_SIZE 6504.L_op_double_to_long: /* 0x8b */ 6505 NAME_START nterp_op_double_to_long 6506 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6507 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6508 6509 /* 6510 * Generic 64bit-to-64bit floating point unary operation. Provide an 6511 * "instr" line that specifies an instruction that performs "x0 = op d0". 6512 * 6513 * For: long-to-double, double-to-long 6514 */ 6515 /* unop vA, vB */ 6516 lsr w3, wINST, #12 // w3<- B 6517 ubfx w4, wINST, #8, #4 // w4<- A 6518 GET_VREG_DOUBLE d0, w3 6519 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6520 fcvtzs x0, d0 // d0<- op 6521 GET_INST_OPCODE ip // extract opcode from wINST 6522 SET_VREG_WIDE x0, w4 // vA<- d0 6523 GOTO_OPCODE ip // jump to next instruction 6524 6525 NAME_END nterp_op_double_to_long 6526 // Advance to the end of this handler. Causes error if we are past that point. 6527 .org nterp_op_double_to_long + NTERP_HANDLER_SIZE // op_double_to_long handler is too big! 6528 6529/* ------------------------------ */ 6530 .balign NTERP_HANDLER_SIZE 6531.L_op_double_to_float: /* 0x8c */ 6532 NAME_START nterp_op_double_to_float 6533 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6534 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6535 6536 /* 6537 * Generic 64bit-to-32bit floating point unary operation. Provide an 6538 * "instr" line that specifies an instruction that performs "s0 = op d0". 6539 * 6540 * For: int-to-double, float-to-double, float-to-long 6541 */ 6542 /* unop vA, vB */ 6543 lsr w3, wINST, #12 // w3<- B 6544 ubfx w4, wINST, #8, #4 // w4<- A 6545 GET_VREG_DOUBLE d0, w3 6546 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 6547 fcvt s0, d0 // d0<- op 6548 GET_INST_OPCODE ip // extract opcode from wINST 6549 SET_VREG_FLOAT s0, w4 // vA<- d0 6550 GOTO_OPCODE ip // jump to next instruction 6551 6552 NAME_END nterp_op_double_to_float 6553 // Advance to the end of this handler. Causes error if we are past that point. 6554 .org nterp_op_double_to_float + NTERP_HANDLER_SIZE // op_double_to_float handler is too big! 6555 6556/* ------------------------------ */ 6557 .balign NTERP_HANDLER_SIZE 6558.L_op_int_to_byte: /* 0x8d */ 6559 NAME_START nterp_op_int_to_byte 6560 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6561 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6562 6563 /* 6564 * Generic 32-bit unary operation. Provide an "instr" line that 6565 * specifies an instruction that performs "result = op w0". 6566 * This could be an ARM instruction or a function call. 6567 * 6568 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 6569 * int-to-byte, int-to-char, int-to-short 6570 */ 6571 /* unop vA, vB */ 6572 lsr w3, wINST, #12 // w3<- B 6573 GET_VREG w0, w3 // w0<- vB 6574 ubfx w9, wINST, #8, #4 // w9<- A 6575 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 6576 sxtb w0, w0 // w0<- op, w0-w3 changed 6577 GET_INST_OPCODE ip // extract opcode from rINST 6578 SET_VREG w0, w9 // vAA<- w0 6579 GOTO_OPCODE ip // jump to next instruction 6580 /* 8-9 instructions */ 6581 6582 NAME_END nterp_op_int_to_byte 6583 // Advance to the end of this handler. Causes error if we are past that point. 6584 .org nterp_op_int_to_byte + NTERP_HANDLER_SIZE // op_int_to_byte handler is too big! 6585 6586/* ------------------------------ */ 6587 .balign NTERP_HANDLER_SIZE 6588.L_op_int_to_char: /* 0x8e */ 6589 NAME_START nterp_op_int_to_char 6590 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6591 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6592 6593 /* 6594 * Generic 32-bit unary operation. Provide an "instr" line that 6595 * specifies an instruction that performs "result = op w0". 6596 * This could be an ARM instruction or a function call. 6597 * 6598 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 6599 * int-to-byte, int-to-char, int-to-short 6600 */ 6601 /* unop vA, vB */ 6602 lsr w3, wINST, #12 // w3<- B 6603 GET_VREG w0, w3 // w0<- vB 6604 ubfx w9, wINST, #8, #4 // w9<- A 6605 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 6606 uxth w0, w0 // w0<- op, w0-w3 changed 6607 GET_INST_OPCODE ip // extract opcode from rINST 6608 SET_VREG w0, w9 // vAA<- w0 6609 GOTO_OPCODE ip // jump to next instruction 6610 /* 8-9 instructions */ 6611 6612 NAME_END nterp_op_int_to_char 6613 // Advance to the end of this handler. Causes error if we are past that point. 6614 .org nterp_op_int_to_char + NTERP_HANDLER_SIZE // op_int_to_char handler is too big! 6615 6616/* ------------------------------ */ 6617 .balign NTERP_HANDLER_SIZE 6618.L_op_int_to_short: /* 0x8f */ 6619 NAME_START nterp_op_int_to_short 6620 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6621 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6622 6623 /* 6624 * Generic 32-bit unary operation. Provide an "instr" line that 6625 * specifies an instruction that performs "result = op w0". 6626 * This could be an ARM instruction or a function call. 6627 * 6628 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 6629 * int-to-byte, int-to-char, int-to-short 6630 */ 6631 /* unop vA, vB */ 6632 lsr w3, wINST, #12 // w3<- B 6633 GET_VREG w0, w3 // w0<- vB 6634 ubfx w9, wINST, #8, #4 // w9<- A 6635 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 6636 sxth w0, w0 // w0<- op, w0-w3 changed 6637 GET_INST_OPCODE ip // extract opcode from rINST 6638 SET_VREG w0, w9 // vAA<- w0 6639 GOTO_OPCODE ip // jump to next instruction 6640 /* 8-9 instructions */ 6641 6642 NAME_END nterp_op_int_to_short 6643 // Advance to the end of this handler. Causes error if we are past that point. 6644 .org nterp_op_int_to_short + NTERP_HANDLER_SIZE // op_int_to_short handler is too big! 6645 6646/* ------------------------------ */ 6647 .balign NTERP_HANDLER_SIZE 6648.L_op_add_int: /* 0x90 */ 6649 NAME_START nterp_op_add_int 6650 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6651 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6652 6653 /* 6654 * Generic 32-bit binary operation. Provide an "instr" line that 6655 * specifies an instruction that performs "result = w0 op w1". 6656 * This could be an ARM instruction or a function call. (If the result 6657 * comes back in a register other than w0, you can override "result".) 6658 * 6659 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6660 * vCC (w1). Useful for integer division and modulus. Note that we 6661 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 6662 * handles it correctly. 6663 * 6664 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 6665 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 6666 * mul-float, div-float, rem-float 6667 */ 6668 /* binop vAA, vBB, vCC */ 6669 FETCH w0, 1 // w0<- CCBB 6670 lsr w9, wINST, #8 // w9<- AA 6671 lsr w3, w0, #8 // w3<- CC 6672 and w2, w0, #255 // w2<- BB 6673 GET_VREG w1, w3 // w1<- vCC 6674 GET_VREG w0, w2 // w0<- vBB 6675 .if 0 6676 cbz w1, common_errDivideByZero // is second operand zero? 6677 .endif 6678 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 6679 // optional op; may set condition codes 6680 add w0, w0, w1 // w0<- op, w0-w3 changed 6681 GET_INST_OPCODE ip // extract opcode from rINST 6682 SET_VREG w0, w9 // vAA<- w0 6683 GOTO_OPCODE ip // jump to next instruction 6684 /* 11-14 instructions */ 6685 6686 NAME_END nterp_op_add_int 6687 // Advance to the end of this handler. Causes error if we are past that point. 6688 .org nterp_op_add_int + NTERP_HANDLER_SIZE // op_add_int handler is too big! 6689 6690/* ------------------------------ */ 6691 .balign NTERP_HANDLER_SIZE 6692.L_op_sub_int: /* 0x91 */ 6693 NAME_START nterp_op_sub_int 6694 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6695 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6696 6697 /* 6698 * Generic 32-bit binary operation. Provide an "instr" line that 6699 * specifies an instruction that performs "result = w0 op w1". 6700 * This could be an ARM instruction or a function call. (If the result 6701 * comes back in a register other than w0, you can override "result".) 6702 * 6703 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6704 * vCC (w1). Useful for integer division and modulus. Note that we 6705 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 6706 * handles it correctly. 6707 * 6708 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 6709 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 6710 * mul-float, div-float, rem-float 6711 */ 6712 /* binop vAA, vBB, vCC */ 6713 FETCH w0, 1 // w0<- CCBB 6714 lsr w9, wINST, #8 // w9<- AA 6715 lsr w3, w0, #8 // w3<- CC 6716 and w2, w0, #255 // w2<- BB 6717 GET_VREG w1, w3 // w1<- vCC 6718 GET_VREG w0, w2 // w0<- vBB 6719 .if 0 6720 cbz w1, common_errDivideByZero // is second operand zero? 6721 .endif 6722 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 6723 // optional op; may set condition codes 6724 sub w0, w0, w1 // w0<- op, w0-w3 changed 6725 GET_INST_OPCODE ip // extract opcode from rINST 6726 SET_VREG w0, w9 // vAA<- w0 6727 GOTO_OPCODE ip // jump to next instruction 6728 /* 11-14 instructions */ 6729 6730 NAME_END nterp_op_sub_int 6731 // Advance to the end of this handler. Causes error if we are past that point. 6732 .org nterp_op_sub_int + NTERP_HANDLER_SIZE // op_sub_int handler is too big! 6733 6734/* ------------------------------ */ 6735 .balign NTERP_HANDLER_SIZE 6736.L_op_mul_int: /* 0x92 */ 6737 NAME_START nterp_op_mul_int 6738 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6739 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6740 6741/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ 6742 /* 6743 * Generic 32-bit binary operation. Provide an "instr" line that 6744 * specifies an instruction that performs "result = w0 op w1". 6745 * This could be an ARM instruction or a function call. (If the result 6746 * comes back in a register other than w0, you can override "result".) 6747 * 6748 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6749 * vCC (w1). Useful for integer division and modulus. Note that we 6750 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 6751 * handles it correctly. 6752 * 6753 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 6754 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 6755 * mul-float, div-float, rem-float 6756 */ 6757 /* binop vAA, vBB, vCC */ 6758 FETCH w0, 1 // w0<- CCBB 6759 lsr w9, wINST, #8 // w9<- AA 6760 lsr w3, w0, #8 // w3<- CC 6761 and w2, w0, #255 // w2<- BB 6762 GET_VREG w1, w3 // w1<- vCC 6763 GET_VREG w0, w2 // w0<- vBB 6764 .if 0 6765 cbz w1, common_errDivideByZero // is second operand zero? 6766 .endif 6767 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 6768 // optional op; may set condition codes 6769 mul w0, w1, w0 // w0<- op, w0-w3 changed 6770 GET_INST_OPCODE ip // extract opcode from rINST 6771 SET_VREG w0, w9 // vAA<- w0 6772 GOTO_OPCODE ip // jump to next instruction 6773 /* 11-14 instructions */ 6774 6775 NAME_END nterp_op_mul_int 6776 // Advance to the end of this handler. Causes error if we are past that point. 6777 .org nterp_op_mul_int + NTERP_HANDLER_SIZE // op_mul_int handler is too big! 6778 6779/* ------------------------------ */ 6780 .balign NTERP_HANDLER_SIZE 6781.L_op_div_int: /* 0x93 */ 6782 NAME_START nterp_op_div_int 6783 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6784 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6785 6786 /* 6787 * Generic 32-bit binary operation. Provide an "instr" line that 6788 * specifies an instruction that performs "result = w0 op w1". 6789 * This could be an ARM instruction or a function call. (If the result 6790 * comes back in a register other than w0, you can override "result".) 6791 * 6792 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6793 * vCC (w1). Useful for integer division and modulus. Note that we 6794 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 6795 * handles it correctly. 6796 * 6797 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 6798 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 6799 * mul-float, div-float, rem-float 6800 */ 6801 /* binop vAA, vBB, vCC */ 6802 FETCH w0, 1 // w0<- CCBB 6803 lsr w9, wINST, #8 // w9<- AA 6804 lsr w3, w0, #8 // w3<- CC 6805 and w2, w0, #255 // w2<- BB 6806 GET_VREG w1, w3 // w1<- vCC 6807 GET_VREG w0, w2 // w0<- vBB 6808 .if 1 6809 cbz w1, common_errDivideByZero // is second operand zero? 6810 .endif 6811 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 6812 // optional op; may set condition codes 6813 sdiv w0, w0, w1 // w0<- op, w0-w3 changed 6814 GET_INST_OPCODE ip // extract opcode from rINST 6815 SET_VREG w0, w9 // vAA<- w0 6816 GOTO_OPCODE ip // jump to next instruction 6817 /* 11-14 instructions */ 6818 6819 NAME_END nterp_op_div_int 6820 // Advance to the end of this handler. Causes error if we are past that point. 6821 .org nterp_op_div_int + NTERP_HANDLER_SIZE // op_div_int handler is too big! 6822 6823/* ------------------------------ */ 6824 .balign NTERP_HANDLER_SIZE 6825.L_op_rem_int: /* 0x94 */ 6826 NAME_START nterp_op_rem_int 6827 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6828 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6829 6830 /* 6831 * Generic 32-bit binary operation. Provide an "instr" line that 6832 * specifies an instruction that performs "result = w0 op w1". 6833 * This could be an ARM instruction or a function call. (If the result 6834 * comes back in a register other than w0, you can override "result".) 6835 * 6836 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6837 * vCC (w1). Useful for integer division and modulus. Note that we 6838 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 6839 * handles it correctly. 6840 * 6841 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 6842 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 6843 * mul-float, div-float, rem-float 6844 */ 6845 /* binop vAA, vBB, vCC */ 6846 FETCH w0, 1 // w0<- CCBB 6847 lsr w9, wINST, #8 // w9<- AA 6848 lsr w3, w0, #8 // w3<- CC 6849 and w2, w0, #255 // w2<- BB 6850 GET_VREG w1, w3 // w1<- vCC 6851 GET_VREG w0, w2 // w0<- vBB 6852 .if 1 6853 cbz w1, common_errDivideByZero // is second operand zero? 6854 .endif 6855 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 6856 sdiv w2, w0, w1 // optional op; may set condition codes 6857 msub w0, w2, w1, w0 // w0<- op, w0-w3 changed 6858 GET_INST_OPCODE ip // extract opcode from rINST 6859 SET_VREG w0, w9 // vAA<- w0 6860 GOTO_OPCODE ip // jump to next instruction 6861 /* 11-14 instructions */ 6862 6863 NAME_END nterp_op_rem_int 6864 // Advance to the end of this handler. Causes error if we are past that point. 6865 .org nterp_op_rem_int + NTERP_HANDLER_SIZE // op_rem_int handler is too big! 6866 6867/* ------------------------------ */ 6868 .balign NTERP_HANDLER_SIZE 6869.L_op_and_int: /* 0x95 */ 6870 NAME_START nterp_op_and_int 6871 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6872 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6873 6874 /* 6875 * Generic 32-bit binary operation. Provide an "instr" line that 6876 * specifies an instruction that performs "result = w0 op w1". 6877 * This could be an ARM instruction or a function call. (If the result 6878 * comes back in a register other than w0, you can override "result".) 6879 * 6880 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6881 * vCC (w1). Useful for integer division and modulus. Note that we 6882 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 6883 * handles it correctly. 6884 * 6885 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 6886 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 6887 * mul-float, div-float, rem-float 6888 */ 6889 /* binop vAA, vBB, vCC */ 6890 FETCH w0, 1 // w0<- CCBB 6891 lsr w9, wINST, #8 // w9<- AA 6892 lsr w3, w0, #8 // w3<- CC 6893 and w2, w0, #255 // w2<- BB 6894 GET_VREG w1, w3 // w1<- vCC 6895 GET_VREG w0, w2 // w0<- vBB 6896 .if 0 6897 cbz w1, common_errDivideByZero // is second operand zero? 6898 .endif 6899 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 6900 // optional op; may set condition codes 6901 and w0, w0, w1 // w0<- op, w0-w3 changed 6902 GET_INST_OPCODE ip // extract opcode from rINST 6903 SET_VREG w0, w9 // vAA<- w0 6904 GOTO_OPCODE ip // jump to next instruction 6905 /* 11-14 instructions */ 6906 6907 NAME_END nterp_op_and_int 6908 // Advance to the end of this handler. Causes error if we are past that point. 6909 .org nterp_op_and_int + NTERP_HANDLER_SIZE // op_and_int handler is too big! 6910 6911/* ------------------------------ */ 6912 .balign NTERP_HANDLER_SIZE 6913.L_op_or_int: /* 0x96 */ 6914 NAME_START nterp_op_or_int 6915 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6916 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6917 6918 /* 6919 * Generic 32-bit binary operation. Provide an "instr" line that 6920 * specifies an instruction that performs "result = w0 op w1". 6921 * This could be an ARM instruction or a function call. (If the result 6922 * comes back in a register other than w0, you can override "result".) 6923 * 6924 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6925 * vCC (w1). Useful for integer division and modulus. Note that we 6926 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 6927 * handles it correctly. 6928 * 6929 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 6930 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 6931 * mul-float, div-float, rem-float 6932 */ 6933 /* binop vAA, vBB, vCC */ 6934 FETCH w0, 1 // w0<- CCBB 6935 lsr w9, wINST, #8 // w9<- AA 6936 lsr w3, w0, #8 // w3<- CC 6937 and w2, w0, #255 // w2<- BB 6938 GET_VREG w1, w3 // w1<- vCC 6939 GET_VREG w0, w2 // w0<- vBB 6940 .if 0 6941 cbz w1, common_errDivideByZero // is second operand zero? 6942 .endif 6943 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 6944 // optional op; may set condition codes 6945 orr w0, w0, w1 // w0<- op, w0-w3 changed 6946 GET_INST_OPCODE ip // extract opcode from rINST 6947 SET_VREG w0, w9 // vAA<- w0 6948 GOTO_OPCODE ip // jump to next instruction 6949 /* 11-14 instructions */ 6950 6951 NAME_END nterp_op_or_int 6952 // Advance to the end of this handler. Causes error if we are past that point. 6953 .org nterp_op_or_int + NTERP_HANDLER_SIZE // op_or_int handler is too big! 6954 6955/* ------------------------------ */ 6956 .balign NTERP_HANDLER_SIZE 6957.L_op_xor_int: /* 0x97 */ 6958 NAME_START nterp_op_xor_int 6959 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 6960 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 6961 6962 /* 6963 * Generic 32-bit binary operation. Provide an "instr" line that 6964 * specifies an instruction that performs "result = w0 op w1". 6965 * This could be an ARM instruction or a function call. (If the result 6966 * comes back in a register other than w0, you can override "result".) 6967 * 6968 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6969 * vCC (w1). Useful for integer division and modulus. Note that we 6970 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 6971 * handles it correctly. 6972 * 6973 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 6974 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 6975 * mul-float, div-float, rem-float 6976 */ 6977 /* binop vAA, vBB, vCC */ 6978 FETCH w0, 1 // w0<- CCBB 6979 lsr w9, wINST, #8 // w9<- AA 6980 lsr w3, w0, #8 // w3<- CC 6981 and w2, w0, #255 // w2<- BB 6982 GET_VREG w1, w3 // w1<- vCC 6983 GET_VREG w0, w2 // w0<- vBB 6984 .if 0 6985 cbz w1, common_errDivideByZero // is second operand zero? 6986 .endif 6987 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 6988 // optional op; may set condition codes 6989 eor w0, w0, w1 // w0<- op, w0-w3 changed 6990 GET_INST_OPCODE ip // extract opcode from rINST 6991 SET_VREG w0, w9 // vAA<- w0 6992 GOTO_OPCODE ip // jump to next instruction 6993 /* 11-14 instructions */ 6994 6995 NAME_END nterp_op_xor_int 6996 // Advance to the end of this handler. Causes error if we are past that point. 6997 .org nterp_op_xor_int + NTERP_HANDLER_SIZE // op_xor_int handler is too big! 6998 6999/* ------------------------------ */ 7000 .balign NTERP_HANDLER_SIZE 7001.L_op_shl_int: /* 0x98 */ 7002 NAME_START nterp_op_shl_int 7003 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7004 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7005 7006 /* 7007 * Generic 32-bit binary operation. Provide an "instr" line that 7008 * specifies an instruction that performs "result = w0 op w1". 7009 * This could be an ARM instruction or a function call. (If the result 7010 * comes back in a register other than w0, you can override "result".) 7011 * 7012 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7013 * vCC (w1). Useful for integer division and modulus. Note that we 7014 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 7015 * handles it correctly. 7016 * 7017 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 7018 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 7019 * mul-float, div-float, rem-float 7020 */ 7021 /* binop vAA, vBB, vCC */ 7022 FETCH w0, 1 // w0<- CCBB 7023 lsr w9, wINST, #8 // w9<- AA 7024 lsr w3, w0, #8 // w3<- CC 7025 and w2, w0, #255 // w2<- BB 7026 GET_VREG w1, w3 // w1<- vCC 7027 GET_VREG w0, w2 // w0<- vBB 7028 .if 0 7029 cbz w1, common_errDivideByZero // is second operand zero? 7030 .endif 7031 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7032 // optional op; may set condition codes 7033 lsl w0, w0, w1 // w0<- op, w0-w3 changed 7034 GET_INST_OPCODE ip // extract opcode from rINST 7035 SET_VREG w0, w9 // vAA<- w0 7036 GOTO_OPCODE ip // jump to next instruction 7037 /* 11-14 instructions */ 7038 7039 NAME_END nterp_op_shl_int 7040 // Advance to the end of this handler. Causes error if we are past that point. 7041 .org nterp_op_shl_int + NTERP_HANDLER_SIZE // op_shl_int handler is too big! 7042 7043/* ------------------------------ */ 7044 .balign NTERP_HANDLER_SIZE 7045.L_op_shr_int: /* 0x99 */ 7046 NAME_START nterp_op_shr_int 7047 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7048 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7049 7050 /* 7051 * Generic 32-bit binary operation. Provide an "instr" line that 7052 * specifies an instruction that performs "result = w0 op w1". 7053 * This could be an ARM instruction or a function call. (If the result 7054 * comes back in a register other than w0, you can override "result".) 7055 * 7056 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7057 * vCC (w1). Useful for integer division and modulus. Note that we 7058 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 7059 * handles it correctly. 7060 * 7061 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 7062 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 7063 * mul-float, div-float, rem-float 7064 */ 7065 /* binop vAA, vBB, vCC */ 7066 FETCH w0, 1 // w0<- CCBB 7067 lsr w9, wINST, #8 // w9<- AA 7068 lsr w3, w0, #8 // w3<- CC 7069 and w2, w0, #255 // w2<- BB 7070 GET_VREG w1, w3 // w1<- vCC 7071 GET_VREG w0, w2 // w0<- vBB 7072 .if 0 7073 cbz w1, common_errDivideByZero // is second operand zero? 7074 .endif 7075 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7076 // optional op; may set condition codes 7077 asr w0, w0, w1 // w0<- op, w0-w3 changed 7078 GET_INST_OPCODE ip // extract opcode from rINST 7079 SET_VREG w0, w9 // vAA<- w0 7080 GOTO_OPCODE ip // jump to next instruction 7081 /* 11-14 instructions */ 7082 7083 NAME_END nterp_op_shr_int 7084 // Advance to the end of this handler. Causes error if we are past that point. 7085 .org nterp_op_shr_int + NTERP_HANDLER_SIZE // op_shr_int handler is too big! 7086 7087/* ------------------------------ */ 7088 .balign NTERP_HANDLER_SIZE 7089.L_op_ushr_int: /* 0x9a */ 7090 NAME_START nterp_op_ushr_int 7091 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7092 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7093 7094 /* 7095 * Generic 32-bit binary operation. Provide an "instr" line that 7096 * specifies an instruction that performs "result = w0 op w1". 7097 * This could be an ARM instruction or a function call. (If the result 7098 * comes back in a register other than w0, you can override "result".) 7099 * 7100 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7101 * vCC (w1). Useful for integer division and modulus. Note that we 7102 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 7103 * handles it correctly. 7104 * 7105 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 7106 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 7107 * mul-float, div-float, rem-float 7108 */ 7109 /* binop vAA, vBB, vCC */ 7110 FETCH w0, 1 // w0<- CCBB 7111 lsr w9, wINST, #8 // w9<- AA 7112 lsr w3, w0, #8 // w3<- CC 7113 and w2, w0, #255 // w2<- BB 7114 GET_VREG w1, w3 // w1<- vCC 7115 GET_VREG w0, w2 // w0<- vBB 7116 .if 0 7117 cbz w1, common_errDivideByZero // is second operand zero? 7118 .endif 7119 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7120 // optional op; may set condition codes 7121 lsr w0, w0, w1 // w0<- op, w0-w3 changed 7122 GET_INST_OPCODE ip // extract opcode from rINST 7123 SET_VREG w0, w9 // vAA<- w0 7124 GOTO_OPCODE ip // jump to next instruction 7125 /* 11-14 instructions */ 7126 7127 NAME_END nterp_op_ushr_int 7128 // Advance to the end of this handler. Causes error if we are past that point. 7129 .org nterp_op_ushr_int + NTERP_HANDLER_SIZE // op_ushr_int handler is too big! 7130 7131/* ------------------------------ */ 7132 .balign NTERP_HANDLER_SIZE 7133.L_op_add_long: /* 0x9b */ 7134 NAME_START nterp_op_add_long 7135 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7136 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7137 7138 /* 7139 * Generic 64-bit binary operation. Provide an "instr" line that 7140 * specifies an instruction that performs "result = x1 op x2". 7141 * This could be an ARM instruction or a function call. (If the result 7142 * comes back in a register other than x0, you can override "result".) 7143 * 7144 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7145 * vCC (w1). Useful for integer division and modulus. 7146 * 7147 * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, 7148 * xor-long, add-double, sub-double, mul-double, div-double, rem-double 7149 */ 7150 /* binop vAA, vBB, vCC */ 7151 FETCH w0, 1 // w0<- CCBB 7152 LOAD_SCALED_VREG_MASK w5, 0xff // w5<- ff * sizeof(vreg) 7153 EXTRACT_SCALED_VREG w4, w5, wINST, 8 // w4<- AA * sizeof(vreg) 7154 EXTRACT_SCALED_VREG w2, w5, w0, 8 // w2<- CC * sizeof(vreg) 7155 EXTRACT_SCALED_VREG w1, w5, w0, 0 // w1<- BB * sizeof(vreg) 7156 GET_VREG_WIDE_PRESCALED x2, w2 // w2<- vCC 7157 GET_VREG_WIDE_PRESCALED x1, w1 // w1<- vBB 7158 .if 0 7159 cbz x2, common_errDivideByZero // is second operand zero? 7160 .endif 7161 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7162 7163 add x0, x1, x2 // x0<- op, w0-w4 changed 7164 GET_INST_OPCODE ip // extract opcode from rINST 7165 SET_VREG_WIDE_PRESCALED x0, w4 // vAA<- x0 7166 GOTO_OPCODE ip // jump to next instruction 7167 /* 11-14 instructions */ 7168 7169 NAME_END nterp_op_add_long 7170 // Advance to the end of this handler. Causes error if we are past that point. 7171 .org nterp_op_add_long + NTERP_HANDLER_SIZE // op_add_long handler is too big! 7172 7173/* ------------------------------ */ 7174 .balign NTERP_HANDLER_SIZE 7175.L_op_sub_long: /* 0x9c */ 7176 NAME_START nterp_op_sub_long 7177 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7178 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7179 7180 /* 7181 * Generic 64-bit binary operation. Provide an "instr" line that 7182 * specifies an instruction that performs "result = x1 op x2". 7183 * This could be an ARM instruction or a function call. (If the result 7184 * comes back in a register other than x0, you can override "result".) 7185 * 7186 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7187 * vCC (w1). Useful for integer division and modulus. 7188 * 7189 * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, 7190 * xor-long, add-double, sub-double, mul-double, div-double, rem-double 7191 */ 7192 /* binop vAA, vBB, vCC */ 7193 FETCH w0, 1 // w0<- CCBB 7194 LOAD_SCALED_VREG_MASK w5, 0xff // w5<- ff * sizeof(vreg) 7195 EXTRACT_SCALED_VREG w4, w5, wINST, 8 // w4<- AA * sizeof(vreg) 7196 EXTRACT_SCALED_VREG w2, w5, w0, 8 // w2<- CC * sizeof(vreg) 7197 EXTRACT_SCALED_VREG w1, w5, w0, 0 // w1<- BB * sizeof(vreg) 7198 GET_VREG_WIDE_PRESCALED x2, w2 // w2<- vCC 7199 GET_VREG_WIDE_PRESCALED x1, w1 // w1<- vBB 7200 .if 0 7201 cbz x2, common_errDivideByZero // is second operand zero? 7202 .endif 7203 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7204 7205 sub x0, x1, x2 // x0<- op, w0-w4 changed 7206 GET_INST_OPCODE ip // extract opcode from rINST 7207 SET_VREG_WIDE_PRESCALED x0, w4 // vAA<- x0 7208 GOTO_OPCODE ip // jump to next instruction 7209 /* 11-14 instructions */ 7210 7211 NAME_END nterp_op_sub_long 7212 // Advance to the end of this handler. Causes error if we are past that point. 7213 .org nterp_op_sub_long + NTERP_HANDLER_SIZE // op_sub_long handler is too big! 7214 7215/* ------------------------------ */ 7216 .balign NTERP_HANDLER_SIZE 7217.L_op_mul_long: /* 0x9d */ 7218 NAME_START nterp_op_mul_long 7219 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7220 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7221 7222 /* 7223 * Generic 64-bit binary operation. Provide an "instr" line that 7224 * specifies an instruction that performs "result = x1 op x2". 7225 * This could be an ARM instruction or a function call. (If the result 7226 * comes back in a register other than x0, you can override "result".) 7227 * 7228 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7229 * vCC (w1). Useful for integer division and modulus. 7230 * 7231 * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, 7232 * xor-long, add-double, sub-double, mul-double, div-double, rem-double 7233 */ 7234 /* binop vAA, vBB, vCC */ 7235 FETCH w0, 1 // w0<- CCBB 7236 LOAD_SCALED_VREG_MASK w5, 0xff // w5<- ff * sizeof(vreg) 7237 EXTRACT_SCALED_VREG w4, w5, wINST, 8 // w4<- AA * sizeof(vreg) 7238 EXTRACT_SCALED_VREG w2, w5, w0, 8 // w2<- CC * sizeof(vreg) 7239 EXTRACT_SCALED_VREG w1, w5, w0, 0 // w1<- BB * sizeof(vreg) 7240 GET_VREG_WIDE_PRESCALED x2, w2 // w2<- vCC 7241 GET_VREG_WIDE_PRESCALED x1, w1 // w1<- vBB 7242 .if 0 7243 cbz x2, common_errDivideByZero // is second operand zero? 7244 .endif 7245 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7246 7247 mul x0, x1, x2 // x0<- op, w0-w4 changed 7248 GET_INST_OPCODE ip // extract opcode from rINST 7249 SET_VREG_WIDE_PRESCALED x0, w4 // vAA<- x0 7250 GOTO_OPCODE ip // jump to next instruction 7251 /* 11-14 instructions */ 7252 7253 NAME_END nterp_op_mul_long 7254 // Advance to the end of this handler. Causes error if we are past that point. 7255 .org nterp_op_mul_long + NTERP_HANDLER_SIZE // op_mul_long handler is too big! 7256 7257/* ------------------------------ */ 7258 .balign NTERP_HANDLER_SIZE 7259.L_op_div_long: /* 0x9e */ 7260 NAME_START nterp_op_div_long 7261 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7262 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7263 7264 /* 7265 * Generic 64-bit binary operation. Provide an "instr" line that 7266 * specifies an instruction that performs "result = x1 op x2". 7267 * This could be an ARM instruction or a function call. (If the result 7268 * comes back in a register other than x0, you can override "result".) 7269 * 7270 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7271 * vCC (w1). Useful for integer division and modulus. 7272 * 7273 * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, 7274 * xor-long, add-double, sub-double, mul-double, div-double, rem-double 7275 */ 7276 /* binop vAA, vBB, vCC */ 7277 FETCH w0, 1 // w0<- CCBB 7278 LOAD_SCALED_VREG_MASK w5, 0xff // w5<- ff * sizeof(vreg) 7279 EXTRACT_SCALED_VREG w4, w5, wINST, 8 // w4<- AA * sizeof(vreg) 7280 EXTRACT_SCALED_VREG w2, w5, w0, 8 // w2<- CC * sizeof(vreg) 7281 EXTRACT_SCALED_VREG w1, w5, w0, 0 // w1<- BB * sizeof(vreg) 7282 GET_VREG_WIDE_PRESCALED x2, w2 // w2<- vCC 7283 GET_VREG_WIDE_PRESCALED x1, w1 // w1<- vBB 7284 .if 1 7285 cbz x2, common_errDivideByZero // is second operand zero? 7286 .endif 7287 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7288 7289 sdiv x0, x1, x2 // x0<- op, w0-w4 changed 7290 GET_INST_OPCODE ip // extract opcode from rINST 7291 SET_VREG_WIDE_PRESCALED x0, w4 // vAA<- x0 7292 GOTO_OPCODE ip // jump to next instruction 7293 /* 11-14 instructions */ 7294 7295 NAME_END nterp_op_div_long 7296 // Advance to the end of this handler. Causes error if we are past that point. 7297 .org nterp_op_div_long + NTERP_HANDLER_SIZE // op_div_long handler is too big! 7298 7299/* ------------------------------ */ 7300 .balign NTERP_HANDLER_SIZE 7301.L_op_rem_long: /* 0x9f */ 7302 NAME_START nterp_op_rem_long 7303 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7304 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7305 7306 /* 7307 * Generic 64-bit binary operation. Provide an "instr" line that 7308 * specifies an instruction that performs "result = x1 op x2". 7309 * This could be an ARM instruction or a function call. (If the result 7310 * comes back in a register other than x0, you can override "result".) 7311 * 7312 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7313 * vCC (w1). Useful for integer division and modulus. 7314 * 7315 * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, 7316 * xor-long, add-double, sub-double, mul-double, div-double, rem-double 7317 */ 7318 /* binop vAA, vBB, vCC */ 7319 FETCH w0, 1 // w0<- CCBB 7320 LOAD_SCALED_VREG_MASK w5, 0xff // w5<- ff * sizeof(vreg) 7321 EXTRACT_SCALED_VREG w4, w5, wINST, 8 // w4<- AA * sizeof(vreg) 7322 EXTRACT_SCALED_VREG w2, w5, w0, 8 // w2<- CC * sizeof(vreg) 7323 EXTRACT_SCALED_VREG w1, w5, w0, 0 // w1<- BB * sizeof(vreg) 7324 GET_VREG_WIDE_PRESCALED x2, w2 // w2<- vCC 7325 GET_VREG_WIDE_PRESCALED x1, w1 // w1<- vBB 7326 .if 1 7327 cbz x2, common_errDivideByZero // is second operand zero? 7328 .endif 7329 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7330 sdiv x3, x1, x2 7331 msub x0, x3, x2, x1 // x0<- op, w0-w4 changed 7332 GET_INST_OPCODE ip // extract opcode from rINST 7333 SET_VREG_WIDE_PRESCALED x0, w4 // vAA<- x0 7334 GOTO_OPCODE ip // jump to next instruction 7335 /* 11-14 instructions */ 7336 7337 NAME_END nterp_op_rem_long 7338 // Advance to the end of this handler. Causes error if we are past that point. 7339 .org nterp_op_rem_long + NTERP_HANDLER_SIZE // op_rem_long handler is too big! 7340 7341/* ------------------------------ */ 7342 .balign NTERP_HANDLER_SIZE 7343.L_op_and_long: /* 0xa0 */ 7344 NAME_START nterp_op_and_long 7345 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7346 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7347 7348 /* 7349 * Generic 64-bit binary operation. Provide an "instr" line that 7350 * specifies an instruction that performs "result = x1 op x2". 7351 * This could be an ARM instruction or a function call. (If the result 7352 * comes back in a register other than x0, you can override "result".) 7353 * 7354 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7355 * vCC (w1). Useful for integer division and modulus. 7356 * 7357 * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, 7358 * xor-long, add-double, sub-double, mul-double, div-double, rem-double 7359 */ 7360 /* binop vAA, vBB, vCC */ 7361 FETCH w0, 1 // w0<- CCBB 7362 LOAD_SCALED_VREG_MASK w5, 0xff // w5<- ff * sizeof(vreg) 7363 EXTRACT_SCALED_VREG w4, w5, wINST, 8 // w4<- AA * sizeof(vreg) 7364 EXTRACT_SCALED_VREG w2, w5, w0, 8 // w2<- CC * sizeof(vreg) 7365 EXTRACT_SCALED_VREG w1, w5, w0, 0 // w1<- BB * sizeof(vreg) 7366 GET_VREG_WIDE_PRESCALED x2, w2 // w2<- vCC 7367 GET_VREG_WIDE_PRESCALED x1, w1 // w1<- vBB 7368 .if 0 7369 cbz x2, common_errDivideByZero // is second operand zero? 7370 .endif 7371 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7372 7373 and x0, x1, x2 // x0<- op, w0-w4 changed 7374 GET_INST_OPCODE ip // extract opcode from rINST 7375 SET_VREG_WIDE_PRESCALED x0, w4 // vAA<- x0 7376 GOTO_OPCODE ip // jump to next instruction 7377 /* 11-14 instructions */ 7378 7379 NAME_END nterp_op_and_long 7380 // Advance to the end of this handler. Causes error if we are past that point. 7381 .org nterp_op_and_long + NTERP_HANDLER_SIZE // op_and_long handler is too big! 7382 7383/* ------------------------------ */ 7384 .balign NTERP_HANDLER_SIZE 7385.L_op_or_long: /* 0xa1 */ 7386 NAME_START nterp_op_or_long 7387 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7388 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7389 7390 /* 7391 * Generic 64-bit binary operation. Provide an "instr" line that 7392 * specifies an instruction that performs "result = x1 op x2". 7393 * This could be an ARM instruction or a function call. (If the result 7394 * comes back in a register other than x0, you can override "result".) 7395 * 7396 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7397 * vCC (w1). Useful for integer division and modulus. 7398 * 7399 * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, 7400 * xor-long, add-double, sub-double, mul-double, div-double, rem-double 7401 */ 7402 /* binop vAA, vBB, vCC */ 7403 FETCH w0, 1 // w0<- CCBB 7404 LOAD_SCALED_VREG_MASK w5, 0xff // w5<- ff * sizeof(vreg) 7405 EXTRACT_SCALED_VREG w4, w5, wINST, 8 // w4<- AA * sizeof(vreg) 7406 EXTRACT_SCALED_VREG w2, w5, w0, 8 // w2<- CC * sizeof(vreg) 7407 EXTRACT_SCALED_VREG w1, w5, w0, 0 // w1<- BB * sizeof(vreg) 7408 GET_VREG_WIDE_PRESCALED x2, w2 // w2<- vCC 7409 GET_VREG_WIDE_PRESCALED x1, w1 // w1<- vBB 7410 .if 0 7411 cbz x2, common_errDivideByZero // is second operand zero? 7412 .endif 7413 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7414 7415 orr x0, x1, x2 // x0<- op, w0-w4 changed 7416 GET_INST_OPCODE ip // extract opcode from rINST 7417 SET_VREG_WIDE_PRESCALED x0, w4 // vAA<- x0 7418 GOTO_OPCODE ip // jump to next instruction 7419 /* 11-14 instructions */ 7420 7421 NAME_END nterp_op_or_long 7422 // Advance to the end of this handler. Causes error if we are past that point. 7423 .org nterp_op_or_long + NTERP_HANDLER_SIZE // op_or_long handler is too big! 7424 7425/* ------------------------------ */ 7426 .balign NTERP_HANDLER_SIZE 7427.L_op_xor_long: /* 0xa2 */ 7428 NAME_START nterp_op_xor_long 7429 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7430 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7431 7432 /* 7433 * Generic 64-bit binary operation. Provide an "instr" line that 7434 * specifies an instruction that performs "result = x1 op x2". 7435 * This could be an ARM instruction or a function call. (If the result 7436 * comes back in a register other than x0, you can override "result".) 7437 * 7438 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7439 * vCC (w1). Useful for integer division and modulus. 7440 * 7441 * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, 7442 * xor-long, add-double, sub-double, mul-double, div-double, rem-double 7443 */ 7444 /* binop vAA, vBB, vCC */ 7445 FETCH w0, 1 // w0<- CCBB 7446 LOAD_SCALED_VREG_MASK w5, 0xff // w5<- ff * sizeof(vreg) 7447 EXTRACT_SCALED_VREG w4, w5, wINST, 8 // w4<- AA * sizeof(vreg) 7448 EXTRACT_SCALED_VREG w2, w5, w0, 8 // w2<- CC * sizeof(vreg) 7449 EXTRACT_SCALED_VREG w1, w5, w0, 0 // w1<- BB * sizeof(vreg) 7450 GET_VREG_WIDE_PRESCALED x2, w2 // w2<- vCC 7451 GET_VREG_WIDE_PRESCALED x1, w1 // w1<- vBB 7452 .if 0 7453 cbz x2, common_errDivideByZero // is second operand zero? 7454 .endif 7455 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7456 7457 eor x0, x1, x2 // x0<- op, w0-w4 changed 7458 GET_INST_OPCODE ip // extract opcode from rINST 7459 SET_VREG_WIDE_PRESCALED x0, w4 // vAA<- x0 7460 GOTO_OPCODE ip // jump to next instruction 7461 /* 11-14 instructions */ 7462 7463 NAME_END nterp_op_xor_long 7464 // Advance to the end of this handler. Causes error if we are past that point. 7465 .org nterp_op_xor_long + NTERP_HANDLER_SIZE // op_xor_long handler is too big! 7466 7467/* ------------------------------ */ 7468 .balign NTERP_HANDLER_SIZE 7469.L_op_shl_long: /* 0xa3 */ 7470 NAME_START nterp_op_shl_long 7471 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7472 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7473 7474 /* 7475 * 64-bit shift operation. 7476 * 7477 * For: shl-long, shr-long, ushr-long 7478 */ 7479 /* binop vAA, vBB, vCC */ 7480 FETCH w0, 1 // w0<- CCBB 7481 lsr w3, wINST, #8 // w3<- AA 7482 lsr w2, w0, #8 // w2<- CC 7483 GET_VREG w2, w2 // w2<- vCC (shift count) 7484 and w1, w0, #255 // w1<- BB 7485 GET_VREG_WIDE x1, w1 // x1<- vBB 7486 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7487 lsl x0, x1, x2 // Do the shift. Only low 6 bits of x2 are used. 7488 GET_INST_OPCODE ip // extract opcode from rINST 7489 SET_VREG_WIDE x0, w3 // vAA<- x0 7490 GOTO_OPCODE ip // jump to next instruction 7491 /* 11-14 instructions */ 7492 7493 NAME_END nterp_op_shl_long 7494 // Advance to the end of this handler. Causes error if we are past that point. 7495 .org nterp_op_shl_long + NTERP_HANDLER_SIZE // op_shl_long handler is too big! 7496 7497/* ------------------------------ */ 7498 .balign NTERP_HANDLER_SIZE 7499.L_op_shr_long: /* 0xa4 */ 7500 NAME_START nterp_op_shr_long 7501 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7502 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7503 7504 /* 7505 * 64-bit shift operation. 7506 * 7507 * For: shl-long, shr-long, ushr-long 7508 */ 7509 /* binop vAA, vBB, vCC */ 7510 FETCH w0, 1 // w0<- CCBB 7511 lsr w3, wINST, #8 // w3<- AA 7512 lsr w2, w0, #8 // w2<- CC 7513 GET_VREG w2, w2 // w2<- vCC (shift count) 7514 and w1, w0, #255 // w1<- BB 7515 GET_VREG_WIDE x1, w1 // x1<- vBB 7516 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7517 asr x0, x1, x2 // Do the shift. Only low 6 bits of x2 are used. 7518 GET_INST_OPCODE ip // extract opcode from rINST 7519 SET_VREG_WIDE x0, w3 // vAA<- x0 7520 GOTO_OPCODE ip // jump to next instruction 7521 /* 11-14 instructions */ 7522 7523 NAME_END nterp_op_shr_long 7524 // Advance to the end of this handler. Causes error if we are past that point. 7525 .org nterp_op_shr_long + NTERP_HANDLER_SIZE // op_shr_long handler is too big! 7526 7527/* ------------------------------ */ 7528 .balign NTERP_HANDLER_SIZE 7529.L_op_ushr_long: /* 0xa5 */ 7530 NAME_START nterp_op_ushr_long 7531 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7532 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7533 7534 /* 7535 * 64-bit shift operation. 7536 * 7537 * For: shl-long, shr-long, ushr-long 7538 */ 7539 /* binop vAA, vBB, vCC */ 7540 FETCH w0, 1 // w0<- CCBB 7541 lsr w3, wINST, #8 // w3<- AA 7542 lsr w2, w0, #8 // w2<- CC 7543 GET_VREG w2, w2 // w2<- vCC (shift count) 7544 and w1, w0, #255 // w1<- BB 7545 GET_VREG_WIDE x1, w1 // x1<- vBB 7546 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7547 lsr x0, x1, x2 // Do the shift. Only low 6 bits of x2 are used. 7548 GET_INST_OPCODE ip // extract opcode from rINST 7549 SET_VREG_WIDE x0, w3 // vAA<- x0 7550 GOTO_OPCODE ip // jump to next instruction 7551 /* 11-14 instructions */ 7552 7553 NAME_END nterp_op_ushr_long 7554 // Advance to the end of this handler. Causes error if we are past that point. 7555 .org nterp_op_ushr_long + NTERP_HANDLER_SIZE // op_ushr_long handler is too big! 7556 7557/* ------------------------------ */ 7558 .balign NTERP_HANDLER_SIZE 7559.L_op_add_float: /* 0xa6 */ 7560 NAME_START nterp_op_add_float 7561 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7562 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7563 7564 /* 7565 * Generic 32-bit floating-point operation. 7566 * 7567 * For: add-float, sub-float, mul-float, div-float 7568 * form: <op> s0, s0, s1 7569 */ 7570 /* floatop vAA, vBB, vCC */ 7571 FETCH w0, 1 // r0<- CCBB 7572 lsr w1, w0, #8 // r2<- CC 7573 and w0, w0, #255 // r1<- BB 7574 GET_VREG s1, w1 7575 GET_VREG s0, w0 7576 fadd s0, s0, s1 // s0<- op 7577 lsr w1, wINST, #8 // r1<- AA 7578 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7579 GET_INST_OPCODE ip // extract opcode from rINST 7580 SET_VREG_FLOAT s0, w1 7581 GOTO_OPCODE ip // jump to next instruction 7582 7583 NAME_END nterp_op_add_float 7584 // Advance to the end of this handler. Causes error if we are past that point. 7585 .org nterp_op_add_float + NTERP_HANDLER_SIZE // op_add_float handler is too big! 7586 7587/* ------------------------------ */ 7588 .balign NTERP_HANDLER_SIZE 7589.L_op_sub_float: /* 0xa7 */ 7590 NAME_START nterp_op_sub_float 7591 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7592 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7593 7594 /* 7595 * Generic 32-bit floating-point operation. 7596 * 7597 * For: add-float, sub-float, mul-float, div-float 7598 * form: <op> s0, s0, s1 7599 */ 7600 /* floatop vAA, vBB, vCC */ 7601 FETCH w0, 1 // r0<- CCBB 7602 lsr w1, w0, #8 // r2<- CC 7603 and w0, w0, #255 // r1<- BB 7604 GET_VREG s1, w1 7605 GET_VREG s0, w0 7606 fsub s0, s0, s1 // s0<- op 7607 lsr w1, wINST, #8 // r1<- AA 7608 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7609 GET_INST_OPCODE ip // extract opcode from rINST 7610 SET_VREG_FLOAT s0, w1 7611 GOTO_OPCODE ip // jump to next instruction 7612 7613 NAME_END nterp_op_sub_float 7614 // Advance to the end of this handler. Causes error if we are past that point. 7615 .org nterp_op_sub_float + NTERP_HANDLER_SIZE // op_sub_float handler is too big! 7616 7617/* ------------------------------ */ 7618 .balign NTERP_HANDLER_SIZE 7619.L_op_mul_float: /* 0xa8 */ 7620 NAME_START nterp_op_mul_float 7621 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7622 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7623 7624 /* 7625 * Generic 32-bit floating-point operation. 7626 * 7627 * For: add-float, sub-float, mul-float, div-float 7628 * form: <op> s0, s0, s1 7629 */ 7630 /* floatop vAA, vBB, vCC */ 7631 FETCH w0, 1 // r0<- CCBB 7632 lsr w1, w0, #8 // r2<- CC 7633 and w0, w0, #255 // r1<- BB 7634 GET_VREG s1, w1 7635 GET_VREG s0, w0 7636 fmul s0, s0, s1 // s0<- op 7637 lsr w1, wINST, #8 // r1<- AA 7638 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7639 GET_INST_OPCODE ip // extract opcode from rINST 7640 SET_VREG_FLOAT s0, w1 7641 GOTO_OPCODE ip // jump to next instruction 7642 7643 NAME_END nterp_op_mul_float 7644 // Advance to the end of this handler. Causes error if we are past that point. 7645 .org nterp_op_mul_float + NTERP_HANDLER_SIZE // op_mul_float handler is too big! 7646 7647/* ------------------------------ */ 7648 .balign NTERP_HANDLER_SIZE 7649.L_op_div_float: /* 0xa9 */ 7650 NAME_START nterp_op_div_float 7651 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7652 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7653 7654 /* 7655 * Generic 32-bit floating-point operation. 7656 * 7657 * For: add-float, sub-float, mul-float, div-float 7658 * form: <op> s0, s0, s1 7659 */ 7660 /* floatop vAA, vBB, vCC */ 7661 FETCH w0, 1 // r0<- CCBB 7662 lsr w1, w0, #8 // r2<- CC 7663 and w0, w0, #255 // r1<- BB 7664 GET_VREG s1, w1 7665 GET_VREG s0, w0 7666 fdiv s0, s0, s1 // s0<- op 7667 lsr w1, wINST, #8 // r1<- AA 7668 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7669 GET_INST_OPCODE ip // extract opcode from rINST 7670 SET_VREG_FLOAT s0, w1 7671 GOTO_OPCODE ip // jump to next instruction 7672 7673 NAME_END nterp_op_div_float 7674 // Advance to the end of this handler. Causes error if we are past that point. 7675 .org nterp_op_div_float + NTERP_HANDLER_SIZE // op_div_float handler is too big! 7676 7677/* ------------------------------ */ 7678 .balign NTERP_HANDLER_SIZE 7679.L_op_rem_float: /* 0xaa */ 7680 NAME_START nterp_op_rem_float 7681 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7682 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7683 7684/* EABI doesn't define a float remainder function, but libm does */ 7685 /* 7686 * Generic 32-bit floating-point operation. 7687 * 7688 * For: add-float, sub-float, mul-float, div-float 7689 * form: <op> s0, s0, s1 7690 */ 7691 /* floatop vAA, vBB, vCC */ 7692 FETCH w0, 1 // r0<- CCBB 7693 lsr w1, w0, #8 // r2<- CC 7694 and w0, w0, #255 // r1<- BB 7695 GET_VREG s1, w1 7696 GET_VREG s0, w0 7697 bl fmodf // s0<- op 7698 lsr w1, wINST, #8 // r1<- AA 7699 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7700 GET_INST_OPCODE ip // extract opcode from rINST 7701 SET_VREG_FLOAT s0, w1 7702 GOTO_OPCODE ip // jump to next instruction 7703 7704 NAME_END nterp_op_rem_float 7705 // Advance to the end of this handler. Causes error if we are past that point. 7706 .org nterp_op_rem_float + NTERP_HANDLER_SIZE // op_rem_float handler is too big! 7707 7708/* ------------------------------ */ 7709 .balign NTERP_HANDLER_SIZE 7710.L_op_add_double: /* 0xab */ 7711 NAME_START nterp_op_add_double 7712 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7713 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7714 7715 /* 7716 * Generic 64-bit floating-point operation. 7717 */ 7718 /* binop vAA, vBB, vCC */ 7719 FETCH w0, 1 // w0<- CCBB 7720 lsr w4, wINST, #8 // w4<- AA 7721 lsr w2, w0, #8 // w2<- CC 7722 and w1, w0, #255 // w1<- BB 7723 GET_VREG_DOUBLE d2, w2 // w2<- vCC 7724 GET_VREG_DOUBLE d1, w1 // w1<- vBB 7725 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7726 fadd d0, d1, d2 // d0<- op, w0-w4 changed 7727 GET_INST_OPCODE ip // extract opcode from rINST 7728 SET_VREG_DOUBLE d0, w4 // vAA<- d0 7729 GOTO_OPCODE ip // jump to next instruction 7730 7731 NAME_END nterp_op_add_double 7732 // Advance to the end of this handler. Causes error if we are past that point. 7733 .org nterp_op_add_double + NTERP_HANDLER_SIZE // op_add_double handler is too big! 7734 7735/* ------------------------------ */ 7736 .balign NTERP_HANDLER_SIZE 7737.L_op_sub_double: /* 0xac */ 7738 NAME_START nterp_op_sub_double 7739 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7740 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7741 7742 /* 7743 * Generic 64-bit floating-point operation. 7744 */ 7745 /* binop vAA, vBB, vCC */ 7746 FETCH w0, 1 // w0<- CCBB 7747 lsr w4, wINST, #8 // w4<- AA 7748 lsr w2, w0, #8 // w2<- CC 7749 and w1, w0, #255 // w1<- BB 7750 GET_VREG_DOUBLE d2, w2 // w2<- vCC 7751 GET_VREG_DOUBLE d1, w1 // w1<- vBB 7752 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7753 fsub d0, d1, d2 // d0<- op, w0-w4 changed 7754 GET_INST_OPCODE ip // extract opcode from rINST 7755 SET_VREG_DOUBLE d0, w4 // vAA<- d0 7756 GOTO_OPCODE ip // jump to next instruction 7757 7758 NAME_END nterp_op_sub_double 7759 // Advance to the end of this handler. Causes error if we are past that point. 7760 .org nterp_op_sub_double + NTERP_HANDLER_SIZE // op_sub_double handler is too big! 7761 7762/* ------------------------------ */ 7763 .balign NTERP_HANDLER_SIZE 7764.L_op_mul_double: /* 0xad */ 7765 NAME_START nterp_op_mul_double 7766 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7767 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7768 7769 /* 7770 * Generic 64-bit floating-point operation. 7771 */ 7772 /* binop vAA, vBB, vCC */ 7773 FETCH w0, 1 // w0<- CCBB 7774 lsr w4, wINST, #8 // w4<- AA 7775 lsr w2, w0, #8 // w2<- CC 7776 and w1, w0, #255 // w1<- BB 7777 GET_VREG_DOUBLE d2, w2 // w2<- vCC 7778 GET_VREG_DOUBLE d1, w1 // w1<- vBB 7779 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7780 fmul d0, d1, d2 // d0<- op, w0-w4 changed 7781 GET_INST_OPCODE ip // extract opcode from rINST 7782 SET_VREG_DOUBLE d0, w4 // vAA<- d0 7783 GOTO_OPCODE ip // jump to next instruction 7784 7785 NAME_END nterp_op_mul_double 7786 // Advance to the end of this handler. Causes error if we are past that point. 7787 .org nterp_op_mul_double + NTERP_HANDLER_SIZE // op_mul_double handler is too big! 7788 7789/* ------------------------------ */ 7790 .balign NTERP_HANDLER_SIZE 7791.L_op_div_double: /* 0xae */ 7792 NAME_START nterp_op_div_double 7793 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7794 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7795 7796 /* 7797 * Generic 64-bit floating-point operation. 7798 */ 7799 /* binop vAA, vBB, vCC */ 7800 FETCH w0, 1 // w0<- CCBB 7801 lsr w4, wINST, #8 // w4<- AA 7802 lsr w2, w0, #8 // w2<- CC 7803 and w1, w0, #255 // w1<- BB 7804 GET_VREG_DOUBLE d2, w2 // w2<- vCC 7805 GET_VREG_DOUBLE d1, w1 // w1<- vBB 7806 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7807 fdiv d0, d1, d2 // d0<- op, w0-w4 changed 7808 GET_INST_OPCODE ip // extract opcode from rINST 7809 SET_VREG_DOUBLE d0, w4 // vAA<- d0 7810 GOTO_OPCODE ip // jump to next instruction 7811 7812 NAME_END nterp_op_div_double 7813 // Advance to the end of this handler. Causes error if we are past that point. 7814 .org nterp_op_div_double + NTERP_HANDLER_SIZE // op_div_double handler is too big! 7815 7816/* ------------------------------ */ 7817 .balign NTERP_HANDLER_SIZE 7818.L_op_rem_double: /* 0xaf */ 7819 NAME_START nterp_op_rem_double 7820 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7821 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7822 7823 /* rem vAA, vBB, vCC */ 7824 FETCH w0, 1 // w0<- CCBB 7825 lsr w2, w0, #8 // w2<- CC 7826 and w1, w0, #255 // w1<- BB 7827 GET_VREG_DOUBLE d1, w2 // d1<- vCC 7828 GET_VREG_DOUBLE d0, w1 // d0<- vBB 7829 bl fmod 7830 lsr w4, wINST, #8 // w4<- AA 7831 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 7832 GET_INST_OPCODE ip // extract opcode from rINST 7833 SET_VREG_WIDE d0, w4 // vAA<- result 7834 GOTO_OPCODE ip // jump to next instruction 7835 /* 11-14 instructions */ 7836 7837 NAME_END nterp_op_rem_double 7838 // Advance to the end of this handler. Causes error if we are past that point. 7839 .org nterp_op_rem_double + NTERP_HANDLER_SIZE // op_rem_double handler is too big! 7840 7841/* ------------------------------ */ 7842 .balign NTERP_HANDLER_SIZE 7843.L_op_add_int_2addr: /* 0xb0 */ 7844 NAME_START nterp_op_add_int_2addr 7845 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7846 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7847 7848 /* 7849 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 7850 * that specifies an instruction that performs "result = w0 op w1". 7851 * This could be an ARM instruction or a function call. (If the result 7852 * comes back in a register other than w0, you can override "result".) 7853 * 7854 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7855 * vCC (w1). Useful for integer division and modulus. 7856 * 7857 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 7858 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 7859 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 7860 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 7861 */ 7862 /* binop/2addr vA, vB */ 7863 lsr w3, wINST, #12 // w3<- B 7864 ubfx w9, wINST, #8, #4 // w9<- A 7865 GET_VREG w1, w3 // w1<- vB 7866 GET_VREG w0, w9 // w0<- vA 7867 .if 0 7868 cbz w1, common_errDivideByZero 7869 .endif 7870 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 7871 // optional op; may set condition codes 7872 add w0, w0, w1 // w0<- op, w0-w3 changed 7873 GET_INST_OPCODE ip // extract opcode from rINST 7874 SET_VREG w0, w9 // vAA<- w0 7875 GOTO_OPCODE ip // jump to next instruction 7876 /* 10-13 instructions */ 7877 7878 NAME_END nterp_op_add_int_2addr 7879 // Advance to the end of this handler. Causes error if we are past that point. 7880 .org nterp_op_add_int_2addr + NTERP_HANDLER_SIZE // op_add_int_2addr handler is too big! 7881 7882/* ------------------------------ */ 7883 .balign NTERP_HANDLER_SIZE 7884.L_op_sub_int_2addr: /* 0xb1 */ 7885 NAME_START nterp_op_sub_int_2addr 7886 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7887 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7888 7889 /* 7890 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 7891 * that specifies an instruction that performs "result = w0 op w1". 7892 * This could be an ARM instruction or a function call. (If the result 7893 * comes back in a register other than w0, you can override "result".) 7894 * 7895 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7896 * vCC (w1). Useful for integer division and modulus. 7897 * 7898 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 7899 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 7900 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 7901 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 7902 */ 7903 /* binop/2addr vA, vB */ 7904 lsr w3, wINST, #12 // w3<- B 7905 ubfx w9, wINST, #8, #4 // w9<- A 7906 GET_VREG w1, w3 // w1<- vB 7907 GET_VREG w0, w9 // w0<- vA 7908 .if 0 7909 cbz w1, common_errDivideByZero 7910 .endif 7911 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 7912 // optional op; may set condition codes 7913 sub w0, w0, w1 // w0<- op, w0-w3 changed 7914 GET_INST_OPCODE ip // extract opcode from rINST 7915 SET_VREG w0, w9 // vAA<- w0 7916 GOTO_OPCODE ip // jump to next instruction 7917 /* 10-13 instructions */ 7918 7919 NAME_END nterp_op_sub_int_2addr 7920 // Advance to the end of this handler. Causes error if we are past that point. 7921 .org nterp_op_sub_int_2addr + NTERP_HANDLER_SIZE // op_sub_int_2addr handler is too big! 7922 7923/* ------------------------------ */ 7924 .balign NTERP_HANDLER_SIZE 7925.L_op_mul_int_2addr: /* 0xb2 */ 7926 NAME_START nterp_op_mul_int_2addr 7927 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7928 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7929 7930/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ 7931 /* 7932 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 7933 * that specifies an instruction that performs "result = w0 op w1". 7934 * This could be an ARM instruction or a function call. (If the result 7935 * comes back in a register other than w0, you can override "result".) 7936 * 7937 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7938 * vCC (w1). Useful for integer division and modulus. 7939 * 7940 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 7941 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 7942 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 7943 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 7944 */ 7945 /* binop/2addr vA, vB */ 7946 lsr w3, wINST, #12 // w3<- B 7947 ubfx w9, wINST, #8, #4 // w9<- A 7948 GET_VREG w1, w3 // w1<- vB 7949 GET_VREG w0, w9 // w0<- vA 7950 .if 0 7951 cbz w1, common_errDivideByZero 7952 .endif 7953 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 7954 // optional op; may set condition codes 7955 mul w0, w1, w0 // w0<- op, w0-w3 changed 7956 GET_INST_OPCODE ip // extract opcode from rINST 7957 SET_VREG w0, w9 // vAA<- w0 7958 GOTO_OPCODE ip // jump to next instruction 7959 /* 10-13 instructions */ 7960 7961 NAME_END nterp_op_mul_int_2addr 7962 // Advance to the end of this handler. Causes error if we are past that point. 7963 .org nterp_op_mul_int_2addr + NTERP_HANDLER_SIZE // op_mul_int_2addr handler is too big! 7964 7965/* ------------------------------ */ 7966 .balign NTERP_HANDLER_SIZE 7967.L_op_div_int_2addr: /* 0xb3 */ 7968 NAME_START nterp_op_div_int_2addr 7969 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 7970 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 7971 7972 /* 7973 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 7974 * that specifies an instruction that performs "result = w0 op w1". 7975 * This could be an ARM instruction or a function call. (If the result 7976 * comes back in a register other than w0, you can override "result".) 7977 * 7978 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7979 * vCC (w1). Useful for integer division and modulus. 7980 * 7981 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 7982 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 7983 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 7984 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 7985 */ 7986 /* binop/2addr vA, vB */ 7987 lsr w3, wINST, #12 // w3<- B 7988 ubfx w9, wINST, #8, #4 // w9<- A 7989 GET_VREG w1, w3 // w1<- vB 7990 GET_VREG w0, w9 // w0<- vA 7991 .if 1 7992 cbz w1, common_errDivideByZero 7993 .endif 7994 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 7995 // optional op; may set condition codes 7996 sdiv w0, w0, w1 // w0<- op, w0-w3 changed 7997 GET_INST_OPCODE ip // extract opcode from rINST 7998 SET_VREG w0, w9 // vAA<- w0 7999 GOTO_OPCODE ip // jump to next instruction 8000 /* 10-13 instructions */ 8001 8002 NAME_END nterp_op_div_int_2addr 8003 // Advance to the end of this handler. Causes error if we are past that point. 8004 .org nterp_op_div_int_2addr + NTERP_HANDLER_SIZE // op_div_int_2addr handler is too big! 8005 8006/* ------------------------------ */ 8007 .balign NTERP_HANDLER_SIZE 8008.L_op_rem_int_2addr: /* 0xb4 */ 8009 NAME_START nterp_op_rem_int_2addr 8010 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8011 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8012 8013 /* 8014 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 8015 * that specifies an instruction that performs "result = w0 op w1". 8016 * This could be an ARM instruction or a function call. (If the result 8017 * comes back in a register other than w0, you can override "result".) 8018 * 8019 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8020 * vCC (w1). Useful for integer division and modulus. 8021 * 8022 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 8023 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 8024 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 8025 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 8026 */ 8027 /* binop/2addr vA, vB */ 8028 lsr w3, wINST, #12 // w3<- B 8029 ubfx w9, wINST, #8, #4 // w9<- A 8030 GET_VREG w1, w3 // w1<- vB 8031 GET_VREG w0, w9 // w0<- vA 8032 .if 1 8033 cbz w1, common_errDivideByZero 8034 .endif 8035 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8036 sdiv w2, w0, w1 // optional op; may set condition codes 8037 msub w0, w2, w1, w0 // w0<- op, w0-w3 changed 8038 GET_INST_OPCODE ip // extract opcode from rINST 8039 SET_VREG w0, w9 // vAA<- w0 8040 GOTO_OPCODE ip // jump to next instruction 8041 /* 10-13 instructions */ 8042 8043 NAME_END nterp_op_rem_int_2addr 8044 // Advance to the end of this handler. Causes error if we are past that point. 8045 .org nterp_op_rem_int_2addr + NTERP_HANDLER_SIZE // op_rem_int_2addr handler is too big! 8046 8047/* ------------------------------ */ 8048 .balign NTERP_HANDLER_SIZE 8049.L_op_and_int_2addr: /* 0xb5 */ 8050 NAME_START nterp_op_and_int_2addr 8051 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8052 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8053 8054 /* 8055 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 8056 * that specifies an instruction that performs "result = w0 op w1". 8057 * This could be an ARM instruction or a function call. (If the result 8058 * comes back in a register other than w0, you can override "result".) 8059 * 8060 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8061 * vCC (w1). Useful for integer division and modulus. 8062 * 8063 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 8064 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 8065 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 8066 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 8067 */ 8068 /* binop/2addr vA, vB */ 8069 lsr w3, wINST, #12 // w3<- B 8070 ubfx w9, wINST, #8, #4 // w9<- A 8071 GET_VREG w1, w3 // w1<- vB 8072 GET_VREG w0, w9 // w0<- vA 8073 .if 0 8074 cbz w1, common_errDivideByZero 8075 .endif 8076 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8077 // optional op; may set condition codes 8078 and w0, w0, w1 // w0<- op, w0-w3 changed 8079 GET_INST_OPCODE ip // extract opcode from rINST 8080 SET_VREG w0, w9 // vAA<- w0 8081 GOTO_OPCODE ip // jump to next instruction 8082 /* 10-13 instructions */ 8083 8084 NAME_END nterp_op_and_int_2addr 8085 // Advance to the end of this handler. Causes error if we are past that point. 8086 .org nterp_op_and_int_2addr + NTERP_HANDLER_SIZE // op_and_int_2addr handler is too big! 8087 8088/* ------------------------------ */ 8089 .balign NTERP_HANDLER_SIZE 8090.L_op_or_int_2addr: /* 0xb6 */ 8091 NAME_START nterp_op_or_int_2addr 8092 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8093 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8094 8095 /* 8096 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 8097 * that specifies an instruction that performs "result = w0 op w1". 8098 * This could be an ARM instruction or a function call. (If the result 8099 * comes back in a register other than w0, you can override "result".) 8100 * 8101 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8102 * vCC (w1). Useful for integer division and modulus. 8103 * 8104 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 8105 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 8106 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 8107 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 8108 */ 8109 /* binop/2addr vA, vB */ 8110 lsr w3, wINST, #12 // w3<- B 8111 ubfx w9, wINST, #8, #4 // w9<- A 8112 GET_VREG w1, w3 // w1<- vB 8113 GET_VREG w0, w9 // w0<- vA 8114 .if 0 8115 cbz w1, common_errDivideByZero 8116 .endif 8117 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8118 // optional op; may set condition codes 8119 orr w0, w0, w1 // w0<- op, w0-w3 changed 8120 GET_INST_OPCODE ip // extract opcode from rINST 8121 SET_VREG w0, w9 // vAA<- w0 8122 GOTO_OPCODE ip // jump to next instruction 8123 /* 10-13 instructions */ 8124 8125 NAME_END nterp_op_or_int_2addr 8126 // Advance to the end of this handler. Causes error if we are past that point. 8127 .org nterp_op_or_int_2addr + NTERP_HANDLER_SIZE // op_or_int_2addr handler is too big! 8128 8129/* ------------------------------ */ 8130 .balign NTERP_HANDLER_SIZE 8131.L_op_xor_int_2addr: /* 0xb7 */ 8132 NAME_START nterp_op_xor_int_2addr 8133 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8134 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8135 8136 /* 8137 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 8138 * that specifies an instruction that performs "result = w0 op w1". 8139 * This could be an ARM instruction or a function call. (If the result 8140 * comes back in a register other than w0, you can override "result".) 8141 * 8142 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8143 * vCC (w1). Useful for integer division and modulus. 8144 * 8145 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 8146 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 8147 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 8148 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 8149 */ 8150 /* binop/2addr vA, vB */ 8151 lsr w3, wINST, #12 // w3<- B 8152 ubfx w9, wINST, #8, #4 // w9<- A 8153 GET_VREG w1, w3 // w1<- vB 8154 GET_VREG w0, w9 // w0<- vA 8155 .if 0 8156 cbz w1, common_errDivideByZero 8157 .endif 8158 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8159 // optional op; may set condition codes 8160 eor w0, w0, w1 // w0<- op, w0-w3 changed 8161 GET_INST_OPCODE ip // extract opcode from rINST 8162 SET_VREG w0, w9 // vAA<- w0 8163 GOTO_OPCODE ip // jump to next instruction 8164 /* 10-13 instructions */ 8165 8166 NAME_END nterp_op_xor_int_2addr 8167 // Advance to the end of this handler. Causes error if we are past that point. 8168 .org nterp_op_xor_int_2addr + NTERP_HANDLER_SIZE // op_xor_int_2addr handler is too big! 8169 8170/* ------------------------------ */ 8171 .balign NTERP_HANDLER_SIZE 8172.L_op_shl_int_2addr: /* 0xb8 */ 8173 NAME_START nterp_op_shl_int_2addr 8174 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8175 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8176 8177 /* 8178 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 8179 * that specifies an instruction that performs "result = w0 op w1". 8180 * This could be an ARM instruction or a function call. (If the result 8181 * comes back in a register other than w0, you can override "result".) 8182 * 8183 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8184 * vCC (w1). Useful for integer division and modulus. 8185 * 8186 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 8187 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 8188 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 8189 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 8190 */ 8191 /* binop/2addr vA, vB */ 8192 lsr w3, wINST, #12 // w3<- B 8193 ubfx w9, wINST, #8, #4 // w9<- A 8194 GET_VREG w1, w3 // w1<- vB 8195 GET_VREG w0, w9 // w0<- vA 8196 .if 0 8197 cbz w1, common_errDivideByZero 8198 .endif 8199 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8200 // optional op; may set condition codes 8201 lsl w0, w0, w1 // w0<- op, w0-w3 changed 8202 GET_INST_OPCODE ip // extract opcode from rINST 8203 SET_VREG w0, w9 // vAA<- w0 8204 GOTO_OPCODE ip // jump to next instruction 8205 /* 10-13 instructions */ 8206 8207 NAME_END nterp_op_shl_int_2addr 8208 // Advance to the end of this handler. Causes error if we are past that point. 8209 .org nterp_op_shl_int_2addr + NTERP_HANDLER_SIZE // op_shl_int_2addr handler is too big! 8210 8211/* ------------------------------ */ 8212 .balign NTERP_HANDLER_SIZE 8213.L_op_shr_int_2addr: /* 0xb9 */ 8214 NAME_START nterp_op_shr_int_2addr 8215 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8216 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8217 8218 /* 8219 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 8220 * that specifies an instruction that performs "result = w0 op w1". 8221 * This could be an ARM instruction or a function call. (If the result 8222 * comes back in a register other than w0, you can override "result".) 8223 * 8224 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8225 * vCC (w1). Useful for integer division and modulus. 8226 * 8227 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 8228 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 8229 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 8230 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 8231 */ 8232 /* binop/2addr vA, vB */ 8233 lsr w3, wINST, #12 // w3<- B 8234 ubfx w9, wINST, #8, #4 // w9<- A 8235 GET_VREG w1, w3 // w1<- vB 8236 GET_VREG w0, w9 // w0<- vA 8237 .if 0 8238 cbz w1, common_errDivideByZero 8239 .endif 8240 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8241 // optional op; may set condition codes 8242 asr w0, w0, w1 // w0<- op, w0-w3 changed 8243 GET_INST_OPCODE ip // extract opcode from rINST 8244 SET_VREG w0, w9 // vAA<- w0 8245 GOTO_OPCODE ip // jump to next instruction 8246 /* 10-13 instructions */ 8247 8248 NAME_END nterp_op_shr_int_2addr 8249 // Advance to the end of this handler. Causes error if we are past that point. 8250 .org nterp_op_shr_int_2addr + NTERP_HANDLER_SIZE // op_shr_int_2addr handler is too big! 8251 8252/* ------------------------------ */ 8253 .balign NTERP_HANDLER_SIZE 8254.L_op_ushr_int_2addr: /* 0xba */ 8255 NAME_START nterp_op_ushr_int_2addr 8256 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8257 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8258 8259 /* 8260 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 8261 * that specifies an instruction that performs "result = w0 op w1". 8262 * This could be an ARM instruction or a function call. (If the result 8263 * comes back in a register other than w0, you can override "result".) 8264 * 8265 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8266 * vCC (w1). Useful for integer division and modulus. 8267 * 8268 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 8269 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 8270 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 8271 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 8272 */ 8273 /* binop/2addr vA, vB */ 8274 lsr w3, wINST, #12 // w3<- B 8275 ubfx w9, wINST, #8, #4 // w9<- A 8276 GET_VREG w1, w3 // w1<- vB 8277 GET_VREG w0, w9 // w0<- vA 8278 .if 0 8279 cbz w1, common_errDivideByZero 8280 .endif 8281 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8282 // optional op; may set condition codes 8283 lsr w0, w0, w1 // w0<- op, w0-w3 changed 8284 GET_INST_OPCODE ip // extract opcode from rINST 8285 SET_VREG w0, w9 // vAA<- w0 8286 GOTO_OPCODE ip // jump to next instruction 8287 /* 10-13 instructions */ 8288 8289 NAME_END nterp_op_ushr_int_2addr 8290 // Advance to the end of this handler. Causes error if we are past that point. 8291 .org nterp_op_ushr_int_2addr + NTERP_HANDLER_SIZE // op_ushr_int_2addr handler is too big! 8292 8293/* ------------------------------ */ 8294 .balign NTERP_HANDLER_SIZE 8295.L_op_add_long_2addr: /* 0xbb */ 8296 NAME_START nterp_op_add_long_2addr 8297 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8298 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8299 8300 /* 8301 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 8302 * that specifies an instruction that performs "x0 = x0 op x1". 8303 * This must not be a function call, as we keep w2 live across it. 8304 * 8305 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8306 * vCC (w1). Useful for integer division and modulus. 8307 * 8308 * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, 8309 * and-long/2addr, or-long/2addr, xor-long/2addr, 8310 * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, 8311 * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr 8312 */ 8313 /* binop/2addr vA, vB */ 8314 lsr w1, wINST, #12 // w1<- B 8315 ubfx w2, wINST, #8, #4 // w2<- A 8316 GET_VREG_WIDE x1, w1 // x1<- vB 8317 GET_VREG_WIDE x0, w2 // x0<- vA 8318 .if 0 8319 cbz x1, common_errDivideByZero 8320 .endif 8321 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8322 8323 add x0, x0, x1 // result<- op 8324 GET_INST_OPCODE ip // extract opcode from rINST 8325 SET_VREG_WIDE x0, w2 // vAA<- result 8326 GOTO_OPCODE ip // jump to next instruction 8327 /* 10-13 instructions */ 8328 8329 NAME_END nterp_op_add_long_2addr 8330 // Advance to the end of this handler. Causes error if we are past that point. 8331 .org nterp_op_add_long_2addr + NTERP_HANDLER_SIZE // op_add_long_2addr handler is too big! 8332 8333/* ------------------------------ */ 8334 .balign NTERP_HANDLER_SIZE 8335.L_op_sub_long_2addr: /* 0xbc */ 8336 NAME_START nterp_op_sub_long_2addr 8337 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8338 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8339 8340 /* 8341 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 8342 * that specifies an instruction that performs "x0 = x0 op x1". 8343 * This must not be a function call, as we keep w2 live across it. 8344 * 8345 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8346 * vCC (w1). Useful for integer division and modulus. 8347 * 8348 * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, 8349 * and-long/2addr, or-long/2addr, xor-long/2addr, 8350 * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, 8351 * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr 8352 */ 8353 /* binop/2addr vA, vB */ 8354 lsr w1, wINST, #12 // w1<- B 8355 ubfx w2, wINST, #8, #4 // w2<- A 8356 GET_VREG_WIDE x1, w1 // x1<- vB 8357 GET_VREG_WIDE x0, w2 // x0<- vA 8358 .if 0 8359 cbz x1, common_errDivideByZero 8360 .endif 8361 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8362 8363 sub x0, x0, x1 // result<- op 8364 GET_INST_OPCODE ip // extract opcode from rINST 8365 SET_VREG_WIDE x0, w2 // vAA<- result 8366 GOTO_OPCODE ip // jump to next instruction 8367 /* 10-13 instructions */ 8368 8369 NAME_END nterp_op_sub_long_2addr 8370 // Advance to the end of this handler. Causes error if we are past that point. 8371 .org nterp_op_sub_long_2addr + NTERP_HANDLER_SIZE // op_sub_long_2addr handler is too big! 8372 8373/* ------------------------------ */ 8374 .balign NTERP_HANDLER_SIZE 8375.L_op_mul_long_2addr: /* 0xbd */ 8376 NAME_START nterp_op_mul_long_2addr 8377 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8378 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8379 8380 /* 8381 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 8382 * that specifies an instruction that performs "x0 = x0 op x1". 8383 * This must not be a function call, as we keep w2 live across it. 8384 * 8385 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8386 * vCC (w1). Useful for integer division and modulus. 8387 * 8388 * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, 8389 * and-long/2addr, or-long/2addr, xor-long/2addr, 8390 * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, 8391 * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr 8392 */ 8393 /* binop/2addr vA, vB */ 8394 lsr w1, wINST, #12 // w1<- B 8395 ubfx w2, wINST, #8, #4 // w2<- A 8396 GET_VREG_WIDE x1, w1 // x1<- vB 8397 GET_VREG_WIDE x0, w2 // x0<- vA 8398 .if 0 8399 cbz x1, common_errDivideByZero 8400 .endif 8401 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8402 8403 mul x0, x0, x1 // result<- op 8404 GET_INST_OPCODE ip // extract opcode from rINST 8405 SET_VREG_WIDE x0, w2 // vAA<- result 8406 GOTO_OPCODE ip // jump to next instruction 8407 /* 10-13 instructions */ 8408 8409 NAME_END nterp_op_mul_long_2addr 8410 // Advance to the end of this handler. Causes error if we are past that point. 8411 .org nterp_op_mul_long_2addr + NTERP_HANDLER_SIZE // op_mul_long_2addr handler is too big! 8412 8413/* ------------------------------ */ 8414 .balign NTERP_HANDLER_SIZE 8415.L_op_div_long_2addr: /* 0xbe */ 8416 NAME_START nterp_op_div_long_2addr 8417 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8418 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8419 8420 /* 8421 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 8422 * that specifies an instruction that performs "x0 = x0 op x1". 8423 * This must not be a function call, as we keep w2 live across it. 8424 * 8425 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8426 * vCC (w1). Useful for integer division and modulus. 8427 * 8428 * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, 8429 * and-long/2addr, or-long/2addr, xor-long/2addr, 8430 * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, 8431 * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr 8432 */ 8433 /* binop/2addr vA, vB */ 8434 lsr w1, wINST, #12 // w1<- B 8435 ubfx w2, wINST, #8, #4 // w2<- A 8436 GET_VREG_WIDE x1, w1 // x1<- vB 8437 GET_VREG_WIDE x0, w2 // x0<- vA 8438 .if 1 8439 cbz x1, common_errDivideByZero 8440 .endif 8441 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8442 8443 sdiv x0, x0, x1 // result<- op 8444 GET_INST_OPCODE ip // extract opcode from rINST 8445 SET_VREG_WIDE x0, w2 // vAA<- result 8446 GOTO_OPCODE ip // jump to next instruction 8447 /* 10-13 instructions */ 8448 8449 NAME_END nterp_op_div_long_2addr 8450 // Advance to the end of this handler. Causes error if we are past that point. 8451 .org nterp_op_div_long_2addr + NTERP_HANDLER_SIZE // op_div_long_2addr handler is too big! 8452 8453/* ------------------------------ */ 8454 .balign NTERP_HANDLER_SIZE 8455.L_op_rem_long_2addr: /* 0xbf */ 8456 NAME_START nterp_op_rem_long_2addr 8457 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8458 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8459 8460 /* 8461 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 8462 * that specifies an instruction that performs "x0 = x0 op x1". 8463 * This must not be a function call, as we keep w2 live across it. 8464 * 8465 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8466 * vCC (w1). Useful for integer division and modulus. 8467 * 8468 * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, 8469 * and-long/2addr, or-long/2addr, xor-long/2addr, 8470 * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, 8471 * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr 8472 */ 8473 /* binop/2addr vA, vB */ 8474 lsr w1, wINST, #12 // w1<- B 8475 ubfx w2, wINST, #8, #4 // w2<- A 8476 GET_VREG_WIDE x1, w1 // x1<- vB 8477 GET_VREG_WIDE x0, w2 // x0<- vA 8478 .if 1 8479 cbz x1, common_errDivideByZero 8480 .endif 8481 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8482 sdiv x3, x0, x1 8483 msub x0, x3, x1, x0 // result<- op 8484 GET_INST_OPCODE ip // extract opcode from rINST 8485 SET_VREG_WIDE x0, w2 // vAA<- result 8486 GOTO_OPCODE ip // jump to next instruction 8487 /* 10-13 instructions */ 8488 8489 NAME_END nterp_op_rem_long_2addr 8490 // Advance to the end of this handler. Causes error if we are past that point. 8491 .org nterp_op_rem_long_2addr + NTERP_HANDLER_SIZE // op_rem_long_2addr handler is too big! 8492 8493/* ------------------------------ */ 8494 .balign NTERP_HANDLER_SIZE 8495.L_op_and_long_2addr: /* 0xc0 */ 8496 NAME_START nterp_op_and_long_2addr 8497 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8498 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8499 8500 /* 8501 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 8502 * that specifies an instruction that performs "x0 = x0 op x1". 8503 * This must not be a function call, as we keep w2 live across it. 8504 * 8505 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8506 * vCC (w1). Useful for integer division and modulus. 8507 * 8508 * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, 8509 * and-long/2addr, or-long/2addr, xor-long/2addr, 8510 * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, 8511 * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr 8512 */ 8513 /* binop/2addr vA, vB */ 8514 lsr w1, wINST, #12 // w1<- B 8515 ubfx w2, wINST, #8, #4 // w2<- A 8516 GET_VREG_WIDE x1, w1 // x1<- vB 8517 GET_VREG_WIDE x0, w2 // x0<- vA 8518 .if 0 8519 cbz x1, common_errDivideByZero 8520 .endif 8521 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8522 8523 and x0, x0, x1 // result<- op 8524 GET_INST_OPCODE ip // extract opcode from rINST 8525 SET_VREG_WIDE x0, w2 // vAA<- result 8526 GOTO_OPCODE ip // jump to next instruction 8527 /* 10-13 instructions */ 8528 8529 NAME_END nterp_op_and_long_2addr 8530 // Advance to the end of this handler. Causes error if we are past that point. 8531 .org nterp_op_and_long_2addr + NTERP_HANDLER_SIZE // op_and_long_2addr handler is too big! 8532 8533/* ------------------------------ */ 8534 .balign NTERP_HANDLER_SIZE 8535.L_op_or_long_2addr: /* 0xc1 */ 8536 NAME_START nterp_op_or_long_2addr 8537 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8538 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8539 8540 /* 8541 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 8542 * that specifies an instruction that performs "x0 = x0 op x1". 8543 * This must not be a function call, as we keep w2 live across it. 8544 * 8545 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8546 * vCC (w1). Useful for integer division and modulus. 8547 * 8548 * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, 8549 * and-long/2addr, or-long/2addr, xor-long/2addr, 8550 * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, 8551 * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr 8552 */ 8553 /* binop/2addr vA, vB */ 8554 lsr w1, wINST, #12 // w1<- B 8555 ubfx w2, wINST, #8, #4 // w2<- A 8556 GET_VREG_WIDE x1, w1 // x1<- vB 8557 GET_VREG_WIDE x0, w2 // x0<- vA 8558 .if 0 8559 cbz x1, common_errDivideByZero 8560 .endif 8561 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8562 8563 orr x0, x0, x1 // result<- op 8564 GET_INST_OPCODE ip // extract opcode from rINST 8565 SET_VREG_WIDE x0, w2 // vAA<- result 8566 GOTO_OPCODE ip // jump to next instruction 8567 /* 10-13 instructions */ 8568 8569 NAME_END nterp_op_or_long_2addr 8570 // Advance to the end of this handler. Causes error if we are past that point. 8571 .org nterp_op_or_long_2addr + NTERP_HANDLER_SIZE // op_or_long_2addr handler is too big! 8572 8573/* ------------------------------ */ 8574 .balign NTERP_HANDLER_SIZE 8575.L_op_xor_long_2addr: /* 0xc2 */ 8576 NAME_START nterp_op_xor_long_2addr 8577 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8578 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8579 8580 /* 8581 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 8582 * that specifies an instruction that performs "x0 = x0 op x1". 8583 * This must not be a function call, as we keep w2 live across it. 8584 * 8585 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8586 * vCC (w1). Useful for integer division and modulus. 8587 * 8588 * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, 8589 * and-long/2addr, or-long/2addr, xor-long/2addr, 8590 * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, 8591 * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr 8592 */ 8593 /* binop/2addr vA, vB */ 8594 lsr w1, wINST, #12 // w1<- B 8595 ubfx w2, wINST, #8, #4 // w2<- A 8596 GET_VREG_WIDE x1, w1 // x1<- vB 8597 GET_VREG_WIDE x0, w2 // x0<- vA 8598 .if 0 8599 cbz x1, common_errDivideByZero 8600 .endif 8601 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8602 8603 eor x0, x0, x1 // result<- op 8604 GET_INST_OPCODE ip // extract opcode from rINST 8605 SET_VREG_WIDE x0, w2 // vAA<- result 8606 GOTO_OPCODE ip // jump to next instruction 8607 /* 10-13 instructions */ 8608 8609 NAME_END nterp_op_xor_long_2addr 8610 // Advance to the end of this handler. Causes error if we are past that point. 8611 .org nterp_op_xor_long_2addr + NTERP_HANDLER_SIZE // op_xor_long_2addr handler is too big! 8612 8613/* ------------------------------ */ 8614 .balign NTERP_HANDLER_SIZE 8615.L_op_shl_long_2addr: /* 0xc3 */ 8616 NAME_START nterp_op_shl_long_2addr 8617 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8618 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8619 8620 /* 8621 * Generic 64-bit shift operation. 8622 */ 8623 /* binop/2addr vA, vB */ 8624 lsr w1, wINST, #12 // w1<- B 8625 ubfx w2, wINST, #8, #4 // w2<- A 8626 GET_VREG w1, w1 // x1<- vB 8627 GET_VREG_WIDE x0, w2 // x0<- vA 8628 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8629 lsl x0, x0, x1 // Do the shift. Only low 6 bits of x1 are used. 8630 GET_INST_OPCODE ip // extract opcode from rINST 8631 SET_VREG_WIDE x0, w2 // vAA<- result 8632 GOTO_OPCODE ip // jump to next instruction 8633 /* 10-13 instructions */ 8634 8635 NAME_END nterp_op_shl_long_2addr 8636 // Advance to the end of this handler. Causes error if we are past that point. 8637 .org nterp_op_shl_long_2addr + NTERP_HANDLER_SIZE // op_shl_long_2addr handler is too big! 8638 8639/* ------------------------------ */ 8640 .balign NTERP_HANDLER_SIZE 8641.L_op_shr_long_2addr: /* 0xc4 */ 8642 NAME_START nterp_op_shr_long_2addr 8643 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8644 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8645 8646 /* 8647 * Generic 64-bit shift operation. 8648 */ 8649 /* binop/2addr vA, vB */ 8650 lsr w1, wINST, #12 // w1<- B 8651 ubfx w2, wINST, #8, #4 // w2<- A 8652 GET_VREG w1, w1 // x1<- vB 8653 GET_VREG_WIDE x0, w2 // x0<- vA 8654 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8655 asr x0, x0, x1 // Do the shift. Only low 6 bits of x1 are used. 8656 GET_INST_OPCODE ip // extract opcode from rINST 8657 SET_VREG_WIDE x0, w2 // vAA<- result 8658 GOTO_OPCODE ip // jump to next instruction 8659 /* 10-13 instructions */ 8660 8661 NAME_END nterp_op_shr_long_2addr 8662 // Advance to the end of this handler. Causes error if we are past that point. 8663 .org nterp_op_shr_long_2addr + NTERP_HANDLER_SIZE // op_shr_long_2addr handler is too big! 8664 8665/* ------------------------------ */ 8666 .balign NTERP_HANDLER_SIZE 8667.L_op_ushr_long_2addr: /* 0xc5 */ 8668 NAME_START nterp_op_ushr_long_2addr 8669 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8670 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8671 8672 /* 8673 * Generic 64-bit shift operation. 8674 */ 8675 /* binop/2addr vA, vB */ 8676 lsr w1, wINST, #12 // w1<- B 8677 ubfx w2, wINST, #8, #4 // w2<- A 8678 GET_VREG w1, w1 // x1<- vB 8679 GET_VREG_WIDE x0, w2 // x0<- vA 8680 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8681 lsr x0, x0, x1 // Do the shift. Only low 6 bits of x1 are used. 8682 GET_INST_OPCODE ip // extract opcode from rINST 8683 SET_VREG_WIDE x0, w2 // vAA<- result 8684 GOTO_OPCODE ip // jump to next instruction 8685 /* 10-13 instructions */ 8686 8687 NAME_END nterp_op_ushr_long_2addr 8688 // Advance to the end of this handler. Causes error if we are past that point. 8689 .org nterp_op_ushr_long_2addr + NTERP_HANDLER_SIZE // op_ushr_long_2addr handler is too big! 8690 8691/* ------------------------------ */ 8692 .balign NTERP_HANDLER_SIZE 8693.L_op_add_float_2addr: /* 0xc6 */ 8694 NAME_START nterp_op_add_float_2addr 8695 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8696 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8697 8698 /* 8699 * Generic 32-bit floating point "/2addr" binary operation. Provide 8700 * an "instr" line that specifies an instruction that performs 8701 * "s2 = s0 op s1". 8702 * 8703 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 8704 */ 8705 /* binop/2addr vA, vB */ 8706 lsr w3, wINST, #12 // w3<- B 8707 ubfx w9, wINST, #8, #4 // w9<- A 8708 GET_VREG s1, w3 8709 GET_VREG s0, w9 8710 fadd s2, s0, s1 // s2<- op 8711 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8712 GET_INST_OPCODE ip // extract opcode from rINST 8713 SET_VREG_FLOAT s2, w9 8714 GOTO_OPCODE ip // jump to next instruction 8715 8716 NAME_END nterp_op_add_float_2addr 8717 // Advance to the end of this handler. Causes error if we are past that point. 8718 .org nterp_op_add_float_2addr + NTERP_HANDLER_SIZE // op_add_float_2addr handler is too big! 8719 8720/* ------------------------------ */ 8721 .balign NTERP_HANDLER_SIZE 8722.L_op_sub_float_2addr: /* 0xc7 */ 8723 NAME_START nterp_op_sub_float_2addr 8724 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8725 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8726 8727 /* 8728 * Generic 32-bit floating point "/2addr" binary operation. Provide 8729 * an "instr" line that specifies an instruction that performs 8730 * "s2 = s0 op s1". 8731 * 8732 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 8733 */ 8734 /* binop/2addr vA, vB */ 8735 lsr w3, wINST, #12 // w3<- B 8736 ubfx w9, wINST, #8, #4 // w9<- A 8737 GET_VREG s1, w3 8738 GET_VREG s0, w9 8739 fsub s2, s0, s1 // s2<- op 8740 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8741 GET_INST_OPCODE ip // extract opcode from rINST 8742 SET_VREG_FLOAT s2, w9 8743 GOTO_OPCODE ip // jump to next instruction 8744 8745 NAME_END nterp_op_sub_float_2addr 8746 // Advance to the end of this handler. Causes error if we are past that point. 8747 .org nterp_op_sub_float_2addr + NTERP_HANDLER_SIZE // op_sub_float_2addr handler is too big! 8748 8749/* ------------------------------ */ 8750 .balign NTERP_HANDLER_SIZE 8751.L_op_mul_float_2addr: /* 0xc8 */ 8752 NAME_START nterp_op_mul_float_2addr 8753 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8754 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8755 8756 /* 8757 * Generic 32-bit floating point "/2addr" binary operation. Provide 8758 * an "instr" line that specifies an instruction that performs 8759 * "s2 = s0 op s1". 8760 * 8761 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 8762 */ 8763 /* binop/2addr vA, vB */ 8764 lsr w3, wINST, #12 // w3<- B 8765 ubfx w9, wINST, #8, #4 // w9<- A 8766 GET_VREG s1, w3 8767 GET_VREG s0, w9 8768 fmul s2, s0, s1 // s2<- op 8769 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8770 GET_INST_OPCODE ip // extract opcode from rINST 8771 SET_VREG_FLOAT s2, w9 8772 GOTO_OPCODE ip // jump to next instruction 8773 8774 NAME_END nterp_op_mul_float_2addr 8775 // Advance to the end of this handler. Causes error if we are past that point. 8776 .org nterp_op_mul_float_2addr + NTERP_HANDLER_SIZE // op_mul_float_2addr handler is too big! 8777 8778/* ------------------------------ */ 8779 .balign NTERP_HANDLER_SIZE 8780.L_op_div_float_2addr: /* 0xc9 */ 8781 NAME_START nterp_op_div_float_2addr 8782 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8783 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8784 8785 /* 8786 * Generic 32-bit floating point "/2addr" binary operation. Provide 8787 * an "instr" line that specifies an instruction that performs 8788 * "s2 = s0 op s1". 8789 * 8790 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 8791 */ 8792 /* binop/2addr vA, vB */ 8793 lsr w3, wINST, #12 // w3<- B 8794 ubfx w9, wINST, #8, #4 // w9<- A 8795 GET_VREG s1, w3 8796 GET_VREG s0, w9 8797 fdiv s2, s0, s1 // s2<- op 8798 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8799 GET_INST_OPCODE ip // extract opcode from rINST 8800 SET_VREG_FLOAT s2, w9 8801 GOTO_OPCODE ip // jump to next instruction 8802 8803 NAME_END nterp_op_div_float_2addr 8804 // Advance to the end of this handler. Causes error if we are past that point. 8805 .org nterp_op_div_float_2addr + NTERP_HANDLER_SIZE // op_div_float_2addr handler is too big! 8806 8807/* ------------------------------ */ 8808 .balign NTERP_HANDLER_SIZE 8809.L_op_rem_float_2addr: /* 0xca */ 8810 NAME_START nterp_op_rem_float_2addr 8811 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8812 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8813 8814 /* rem vA, vB */ 8815 lsr w3, wINST, #12 // w3<- B 8816 ubfx w9, wINST, #8, #4 // w9<- A 8817 GET_VREG s1, w3 8818 GET_VREG s0, w9 8819 bl fmodf 8820 ubfx w9, wINST, #8, #4 // w9<- A 8821 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8822 GET_INST_OPCODE ip // extract opcode from rINST 8823 SET_VREG_FLOAT s0, w9 8824 GOTO_OPCODE ip // jump to next instruction 8825 8826 NAME_END nterp_op_rem_float_2addr 8827 // Advance to the end of this handler. Causes error if we are past that point. 8828 .org nterp_op_rem_float_2addr + NTERP_HANDLER_SIZE // op_rem_float_2addr handler is too big! 8829 8830/* ------------------------------ */ 8831 .balign NTERP_HANDLER_SIZE 8832.L_op_add_double_2addr: /* 0xcb */ 8833 NAME_START nterp_op_add_double_2addr 8834 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8835 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8836 8837 /* 8838 * Generic 64-bit floating point "/2addr" binary operation. 8839 */ 8840 /* binop/2addr vA, vB */ 8841 lsr w1, wINST, #12 // w1<- B 8842 ubfx w2, wINST, #8, #4 // w2<- A 8843 GET_VREG_DOUBLE d1, w1 // x1<- vB 8844 GET_VREG_DOUBLE d0, w2 // x0<- vA 8845 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8846 fadd d0, d0, d1 // result<- op 8847 GET_INST_OPCODE ip // extract opcode from rINST 8848 SET_VREG_DOUBLE d0, w2 // vAA<- result 8849 GOTO_OPCODE ip // jump to next instruction 8850 8851 NAME_END nterp_op_add_double_2addr 8852 // Advance to the end of this handler. Causes error if we are past that point. 8853 .org nterp_op_add_double_2addr + NTERP_HANDLER_SIZE // op_add_double_2addr handler is too big! 8854 8855/* ------------------------------ */ 8856 .balign NTERP_HANDLER_SIZE 8857.L_op_sub_double_2addr: /* 0xcc */ 8858 NAME_START nterp_op_sub_double_2addr 8859 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8860 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8861 8862 /* 8863 * Generic 64-bit floating point "/2addr" binary operation. 8864 */ 8865 /* binop/2addr vA, vB */ 8866 lsr w1, wINST, #12 // w1<- B 8867 ubfx w2, wINST, #8, #4 // w2<- A 8868 GET_VREG_DOUBLE d1, w1 // x1<- vB 8869 GET_VREG_DOUBLE d0, w2 // x0<- vA 8870 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8871 fsub d0, d0, d1 // result<- op 8872 GET_INST_OPCODE ip // extract opcode from rINST 8873 SET_VREG_DOUBLE d0, w2 // vAA<- result 8874 GOTO_OPCODE ip // jump to next instruction 8875 8876 NAME_END nterp_op_sub_double_2addr 8877 // Advance to the end of this handler. Causes error if we are past that point. 8878 .org nterp_op_sub_double_2addr + NTERP_HANDLER_SIZE // op_sub_double_2addr handler is too big! 8879 8880/* ------------------------------ */ 8881 .balign NTERP_HANDLER_SIZE 8882.L_op_mul_double_2addr: /* 0xcd */ 8883 NAME_START nterp_op_mul_double_2addr 8884 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8885 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8886 8887 /* 8888 * Generic 64-bit floating point "/2addr" binary operation. 8889 */ 8890 /* binop/2addr vA, vB */ 8891 lsr w1, wINST, #12 // w1<- B 8892 ubfx w2, wINST, #8, #4 // w2<- A 8893 GET_VREG_DOUBLE d1, w1 // x1<- vB 8894 GET_VREG_DOUBLE d0, w2 // x0<- vA 8895 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8896 fmul d0, d0, d1 // result<- op 8897 GET_INST_OPCODE ip // extract opcode from rINST 8898 SET_VREG_DOUBLE d0, w2 // vAA<- result 8899 GOTO_OPCODE ip // jump to next instruction 8900 8901 NAME_END nterp_op_mul_double_2addr 8902 // Advance to the end of this handler. Causes error if we are past that point. 8903 .org nterp_op_mul_double_2addr + NTERP_HANDLER_SIZE // op_mul_double_2addr handler is too big! 8904 8905/* ------------------------------ */ 8906 .balign NTERP_HANDLER_SIZE 8907.L_op_div_double_2addr: /* 0xce */ 8908 NAME_START nterp_op_div_double_2addr 8909 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8910 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8911 8912 /* 8913 * Generic 64-bit floating point "/2addr" binary operation. 8914 */ 8915 /* binop/2addr vA, vB */ 8916 lsr w1, wINST, #12 // w1<- B 8917 ubfx w2, wINST, #8, #4 // w2<- A 8918 GET_VREG_DOUBLE d1, w1 // x1<- vB 8919 GET_VREG_DOUBLE d0, w2 // x0<- vA 8920 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8921 fdiv d0, d0, d1 // result<- op 8922 GET_INST_OPCODE ip // extract opcode from rINST 8923 SET_VREG_DOUBLE d0, w2 // vAA<- result 8924 GOTO_OPCODE ip // jump to next instruction 8925 8926 NAME_END nterp_op_div_double_2addr 8927 // Advance to the end of this handler. Causes error if we are past that point. 8928 .org nterp_op_div_double_2addr + NTERP_HANDLER_SIZE // op_div_double_2addr handler is too big! 8929 8930/* ------------------------------ */ 8931 .balign NTERP_HANDLER_SIZE 8932.L_op_rem_double_2addr: /* 0xcf */ 8933 NAME_START nterp_op_rem_double_2addr 8934 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8935 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8936 8937 /* rem vA, vB */ 8938 lsr w1, wINST, #12 // w1<- B 8939 ubfx w2, wINST, #8, #4 // w2<- A 8940 GET_VREG_DOUBLE d1, w1 // d1<- vB 8941 GET_VREG_DOUBLE d0, w2 // d0<- vA 8942 bl fmod 8943 ubfx w2, wINST, #8, #4 // w2<- A (need to reload - killed across call) 8944 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 8945 GET_INST_OPCODE ip // extract opcode from rINST 8946 SET_VREG_WIDE d0, w2 // vAA<- result 8947 GOTO_OPCODE ip // jump to next instruction 8948 /* 10-13 instructions */ 8949 8950 NAME_END nterp_op_rem_double_2addr 8951 // Advance to the end of this handler. Causes error if we are past that point. 8952 .org nterp_op_rem_double_2addr + NTERP_HANDLER_SIZE // op_rem_double_2addr handler is too big! 8953 8954/* ------------------------------ */ 8955 .balign NTERP_HANDLER_SIZE 8956.L_op_add_int_lit16: /* 0xd0 */ 8957 NAME_START nterp_op_add_int_lit16 8958 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8959 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8960 8961 /* 8962 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 8963 * that specifies an instruction that performs "result = w0 op w1". 8964 * This could be an ARM instruction or a function call. (If the result 8965 * comes back in a register other than w0, you can override "result".) 8966 * 8967 * If "chkzero" is set to 1, we perform a divide-by-zero check on 8968 * vCC (w1). Useful for integer division and modulus. 8969 * 8970 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 8971 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 8972 */ 8973 /* binop/lit16 vA, vB, #+CCCC */ 8974 FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) 8975 lsr w2, wINST, #12 // w2<- B 8976 ubfx w9, wINST, #8, #4 // w9<- A 8977 GET_VREG w0, w2 // w0<- vB 8978 .if 0 8979 cbz w1, common_errDivideByZero 8980 .endif 8981 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 8982 8983 add w0, w0, w1 // w0<- op, w0-w3 changed 8984 GET_INST_OPCODE ip // extract opcode from rINST 8985 SET_VREG w0, w9 // vAA<- w0 8986 GOTO_OPCODE ip // jump to next instruction 8987 /* 10-13 instructions */ 8988 8989 NAME_END nterp_op_add_int_lit16 8990 // Advance to the end of this handler. Causes error if we are past that point. 8991 .org nterp_op_add_int_lit16 + NTERP_HANDLER_SIZE // op_add_int_lit16 handler is too big! 8992 8993/* ------------------------------ */ 8994 .balign NTERP_HANDLER_SIZE 8995.L_op_rsub_int: /* 0xd1 */ 8996 NAME_START nterp_op_rsub_int 8997 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 8998 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 8999 9000/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 9001 /* 9002 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 9003 * that specifies an instruction that performs "result = w0 op w1". 9004 * This could be an ARM instruction or a function call. (If the result 9005 * comes back in a register other than w0, you can override "result".) 9006 * 9007 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9008 * vCC (w1). Useful for integer division and modulus. 9009 * 9010 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 9011 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 9012 */ 9013 /* binop/lit16 vA, vB, #+CCCC */ 9014 FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) 9015 lsr w2, wINST, #12 // w2<- B 9016 ubfx w9, wINST, #8, #4 // w9<- A 9017 GET_VREG w0, w2 // w0<- vB 9018 .if 0 9019 cbz w1, common_errDivideByZero 9020 .endif 9021 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9022 9023 sub w0, w1, w0 // w0<- op, w0-w3 changed 9024 GET_INST_OPCODE ip // extract opcode from rINST 9025 SET_VREG w0, w9 // vAA<- w0 9026 GOTO_OPCODE ip // jump to next instruction 9027 /* 10-13 instructions */ 9028 9029 NAME_END nterp_op_rsub_int 9030 // Advance to the end of this handler. Causes error if we are past that point. 9031 .org nterp_op_rsub_int + NTERP_HANDLER_SIZE // op_rsub_int handler is too big! 9032 9033/* ------------------------------ */ 9034 .balign NTERP_HANDLER_SIZE 9035.L_op_mul_int_lit16: /* 0xd2 */ 9036 NAME_START nterp_op_mul_int_lit16 9037 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9038 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9039 9040/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ 9041 /* 9042 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 9043 * that specifies an instruction that performs "result = w0 op w1". 9044 * This could be an ARM instruction or a function call. (If the result 9045 * comes back in a register other than w0, you can override "result".) 9046 * 9047 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9048 * vCC (w1). Useful for integer division and modulus. 9049 * 9050 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 9051 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 9052 */ 9053 /* binop/lit16 vA, vB, #+CCCC */ 9054 FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) 9055 lsr w2, wINST, #12 // w2<- B 9056 ubfx w9, wINST, #8, #4 // w9<- A 9057 GET_VREG w0, w2 // w0<- vB 9058 .if 0 9059 cbz w1, common_errDivideByZero 9060 .endif 9061 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9062 9063 mul w0, w1, w0 // w0<- op, w0-w3 changed 9064 GET_INST_OPCODE ip // extract opcode from rINST 9065 SET_VREG w0, w9 // vAA<- w0 9066 GOTO_OPCODE ip // jump to next instruction 9067 /* 10-13 instructions */ 9068 9069 NAME_END nterp_op_mul_int_lit16 9070 // Advance to the end of this handler. Causes error if we are past that point. 9071 .org nterp_op_mul_int_lit16 + NTERP_HANDLER_SIZE // op_mul_int_lit16 handler is too big! 9072 9073/* ------------------------------ */ 9074 .balign NTERP_HANDLER_SIZE 9075.L_op_div_int_lit16: /* 0xd3 */ 9076 NAME_START nterp_op_div_int_lit16 9077 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9078 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9079 9080 /* 9081 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 9082 * that specifies an instruction that performs "result = w0 op w1". 9083 * This could be an ARM instruction or a function call. (If the result 9084 * comes back in a register other than w0, you can override "result".) 9085 * 9086 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9087 * vCC (w1). Useful for integer division and modulus. 9088 * 9089 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 9090 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 9091 */ 9092 /* binop/lit16 vA, vB, #+CCCC */ 9093 FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) 9094 lsr w2, wINST, #12 // w2<- B 9095 ubfx w9, wINST, #8, #4 // w9<- A 9096 GET_VREG w0, w2 // w0<- vB 9097 .if 1 9098 cbz w1, common_errDivideByZero 9099 .endif 9100 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9101 9102 sdiv w0, w0, w1 // w0<- op, w0-w3 changed 9103 GET_INST_OPCODE ip // extract opcode from rINST 9104 SET_VREG w0, w9 // vAA<- w0 9105 GOTO_OPCODE ip // jump to next instruction 9106 /* 10-13 instructions */ 9107 9108 NAME_END nterp_op_div_int_lit16 9109 // Advance to the end of this handler. Causes error if we are past that point. 9110 .org nterp_op_div_int_lit16 + NTERP_HANDLER_SIZE // op_div_int_lit16 handler is too big! 9111 9112/* ------------------------------ */ 9113 .balign NTERP_HANDLER_SIZE 9114.L_op_rem_int_lit16: /* 0xd4 */ 9115 NAME_START nterp_op_rem_int_lit16 9116 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9117 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9118 9119 /* 9120 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 9121 * that specifies an instruction that performs "result = w0 op w1". 9122 * This could be an ARM instruction or a function call. (If the result 9123 * comes back in a register other than w0, you can override "result".) 9124 * 9125 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9126 * vCC (w1). Useful for integer division and modulus. 9127 * 9128 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 9129 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 9130 */ 9131 /* binop/lit16 vA, vB, #+CCCC */ 9132 FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) 9133 lsr w2, wINST, #12 // w2<- B 9134 ubfx w9, wINST, #8, #4 // w9<- A 9135 GET_VREG w0, w2 // w0<- vB 9136 .if 1 9137 cbz w1, common_errDivideByZero 9138 .endif 9139 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9140 sdiv w3, w0, w1 9141 msub w0, w3, w1, w0 // w0<- op, w0-w3 changed 9142 GET_INST_OPCODE ip // extract opcode from rINST 9143 SET_VREG w0, w9 // vAA<- w0 9144 GOTO_OPCODE ip // jump to next instruction 9145 /* 10-13 instructions */ 9146 9147 NAME_END nterp_op_rem_int_lit16 9148 // Advance to the end of this handler. Causes error if we are past that point. 9149 .org nterp_op_rem_int_lit16 + NTERP_HANDLER_SIZE // op_rem_int_lit16 handler is too big! 9150 9151/* ------------------------------ */ 9152 .balign NTERP_HANDLER_SIZE 9153.L_op_and_int_lit16: /* 0xd5 */ 9154 NAME_START nterp_op_and_int_lit16 9155 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9156 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9157 9158 /* 9159 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 9160 * that specifies an instruction that performs "result = w0 op w1". 9161 * This could be an ARM instruction or a function call. (If the result 9162 * comes back in a register other than w0, you can override "result".) 9163 * 9164 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9165 * vCC (w1). Useful for integer division and modulus. 9166 * 9167 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 9168 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 9169 */ 9170 /* binop/lit16 vA, vB, #+CCCC */ 9171 FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) 9172 lsr w2, wINST, #12 // w2<- B 9173 ubfx w9, wINST, #8, #4 // w9<- A 9174 GET_VREG w0, w2 // w0<- vB 9175 .if 0 9176 cbz w1, common_errDivideByZero 9177 .endif 9178 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9179 9180 and w0, w0, w1 // w0<- op, w0-w3 changed 9181 GET_INST_OPCODE ip // extract opcode from rINST 9182 SET_VREG w0, w9 // vAA<- w0 9183 GOTO_OPCODE ip // jump to next instruction 9184 /* 10-13 instructions */ 9185 9186 NAME_END nterp_op_and_int_lit16 9187 // Advance to the end of this handler. Causes error if we are past that point. 9188 .org nterp_op_and_int_lit16 + NTERP_HANDLER_SIZE // op_and_int_lit16 handler is too big! 9189 9190/* ------------------------------ */ 9191 .balign NTERP_HANDLER_SIZE 9192.L_op_or_int_lit16: /* 0xd6 */ 9193 NAME_START nterp_op_or_int_lit16 9194 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9195 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9196 9197 /* 9198 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 9199 * that specifies an instruction that performs "result = w0 op w1". 9200 * This could be an ARM instruction or a function call. (If the result 9201 * comes back in a register other than w0, you can override "result".) 9202 * 9203 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9204 * vCC (w1). Useful for integer division and modulus. 9205 * 9206 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 9207 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 9208 */ 9209 /* binop/lit16 vA, vB, #+CCCC */ 9210 FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) 9211 lsr w2, wINST, #12 // w2<- B 9212 ubfx w9, wINST, #8, #4 // w9<- A 9213 GET_VREG w0, w2 // w0<- vB 9214 .if 0 9215 cbz w1, common_errDivideByZero 9216 .endif 9217 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9218 9219 orr w0, w0, w1 // w0<- op, w0-w3 changed 9220 GET_INST_OPCODE ip // extract opcode from rINST 9221 SET_VREG w0, w9 // vAA<- w0 9222 GOTO_OPCODE ip // jump to next instruction 9223 /* 10-13 instructions */ 9224 9225 NAME_END nterp_op_or_int_lit16 9226 // Advance to the end of this handler. Causes error if we are past that point. 9227 .org nterp_op_or_int_lit16 + NTERP_HANDLER_SIZE // op_or_int_lit16 handler is too big! 9228 9229/* ------------------------------ */ 9230 .balign NTERP_HANDLER_SIZE 9231.L_op_xor_int_lit16: /* 0xd7 */ 9232 NAME_START nterp_op_xor_int_lit16 9233 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9234 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9235 9236 /* 9237 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 9238 * that specifies an instruction that performs "result = w0 op w1". 9239 * This could be an ARM instruction or a function call. (If the result 9240 * comes back in a register other than w0, you can override "result".) 9241 * 9242 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9243 * vCC (w1). Useful for integer division and modulus. 9244 * 9245 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 9246 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 9247 */ 9248 /* binop/lit16 vA, vB, #+CCCC */ 9249 FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) 9250 lsr w2, wINST, #12 // w2<- B 9251 ubfx w9, wINST, #8, #4 // w9<- A 9252 GET_VREG w0, w2 // w0<- vB 9253 .if 0 9254 cbz w1, common_errDivideByZero 9255 .endif 9256 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9257 9258 eor w0, w0, w1 // w0<- op, w0-w3 changed 9259 GET_INST_OPCODE ip // extract opcode from rINST 9260 SET_VREG w0, w9 // vAA<- w0 9261 GOTO_OPCODE ip // jump to next instruction 9262 /* 10-13 instructions */ 9263 9264 NAME_END nterp_op_xor_int_lit16 9265 // Advance to the end of this handler. Causes error if we are past that point. 9266 .org nterp_op_xor_int_lit16 + NTERP_HANDLER_SIZE // op_xor_int_lit16 handler is too big! 9267 9268/* ------------------------------ */ 9269 .balign NTERP_HANDLER_SIZE 9270.L_op_add_int_lit8: /* 0xd8 */ 9271 NAME_START nterp_op_add_int_lit8 9272 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9273 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9274 9275 /* 9276 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 9277 * that specifies an instruction that performs "result = w0 op w1". 9278 * This could be an ARM instruction or a function call. (If the result 9279 * comes back in a register other than w0, you can override "result".) 9280 * 9281 * You can override "extract" if the extraction of the literal value 9282 * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 9283 * can be omitted completely if the shift is embedded in "instr". 9284 * 9285 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9286 * vCC (w1). Useful for integer division and modulus. 9287 * 9288 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 9289 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 9290 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 9291 */ 9292 /* binop/lit8 vAA, vBB, #+CC */ 9293 FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 9294 lsr w9, wINST, #8 // w9<- AA 9295 and w2, w3, #255 // w2<- BB 9296 GET_VREG w0, w2 // w0<- vBB 9297 // optional; typically w1<- ssssssCC (sign extended) 9298 .if 0 9299 cbz w1, common_errDivideByZero 9300 .endif 9301 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9302 // optional op; may set condition codes 9303 add w0, w0, w3, asr #8 // w0<- op, w0-w3 changed 9304 GET_INST_OPCODE ip // extract opcode from rINST 9305 SET_VREG w0, w9 // vAA<- w0 9306 GOTO_OPCODE ip // jump to next instruction 9307 /* 10-12 instructions */ 9308 9309 NAME_END nterp_op_add_int_lit8 9310 // Advance to the end of this handler. Causes error if we are past that point. 9311 .org nterp_op_add_int_lit8 + NTERP_HANDLER_SIZE // op_add_int_lit8 handler is too big! 9312 9313/* ------------------------------ */ 9314 .balign NTERP_HANDLER_SIZE 9315.L_op_rsub_int_lit8: /* 0xd9 */ 9316 NAME_START nterp_op_rsub_int_lit8 9317 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9318 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9319 9320 /* 9321 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 9322 * that specifies an instruction that performs "result = w0 op w1". 9323 * This could be an ARM instruction or a function call. (If the result 9324 * comes back in a register other than w0, you can override "result".) 9325 * 9326 * You can override "extract" if the extraction of the literal value 9327 * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 9328 * can be omitted completely if the shift is embedded in "instr". 9329 * 9330 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9331 * vCC (w1). Useful for integer division and modulus. 9332 * 9333 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 9334 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 9335 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 9336 */ 9337 /* binop/lit8 vAA, vBB, #+CC */ 9338 FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 9339 lsr w9, wINST, #8 // w9<- AA 9340 and w2, w3, #255 // w2<- BB 9341 GET_VREG w0, w2 // w0<- vBB 9342 asr w1, w3, #8 // optional; typically w1<- ssssssCC (sign extended) 9343 .if 0 9344 cbz w1, common_errDivideByZero 9345 .endif 9346 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9347 // optional op; may set condition codes 9348 sub w0, w1, w0 // w0<- op, w0-w3 changed 9349 GET_INST_OPCODE ip // extract opcode from rINST 9350 SET_VREG w0, w9 // vAA<- w0 9351 GOTO_OPCODE ip // jump to next instruction 9352 /* 10-12 instructions */ 9353 9354 NAME_END nterp_op_rsub_int_lit8 9355 // Advance to the end of this handler. Causes error if we are past that point. 9356 .org nterp_op_rsub_int_lit8 + NTERP_HANDLER_SIZE // op_rsub_int_lit8 handler is too big! 9357 9358/* ------------------------------ */ 9359 .balign NTERP_HANDLER_SIZE 9360.L_op_mul_int_lit8: /* 0xda */ 9361 NAME_START nterp_op_mul_int_lit8 9362 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9363 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9364 9365/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ 9366 /* 9367 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 9368 * that specifies an instruction that performs "result = w0 op w1". 9369 * This could be an ARM instruction or a function call. (If the result 9370 * comes back in a register other than w0, you can override "result".) 9371 * 9372 * You can override "extract" if the extraction of the literal value 9373 * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 9374 * can be omitted completely if the shift is embedded in "instr". 9375 * 9376 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9377 * vCC (w1). Useful for integer division and modulus. 9378 * 9379 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 9380 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 9381 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 9382 */ 9383 /* binop/lit8 vAA, vBB, #+CC */ 9384 FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 9385 lsr w9, wINST, #8 // w9<- AA 9386 and w2, w3, #255 // w2<- BB 9387 GET_VREG w0, w2 // w0<- vBB 9388 asr w1, w3, #8 // optional; typically w1<- ssssssCC (sign extended) 9389 .if 0 9390 cbz w1, common_errDivideByZero 9391 .endif 9392 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9393 // optional op; may set condition codes 9394 mul w0, w1, w0 // w0<- op, w0-w3 changed 9395 GET_INST_OPCODE ip // extract opcode from rINST 9396 SET_VREG w0, w9 // vAA<- w0 9397 GOTO_OPCODE ip // jump to next instruction 9398 /* 10-12 instructions */ 9399 9400 NAME_END nterp_op_mul_int_lit8 9401 // Advance to the end of this handler. Causes error if we are past that point. 9402 .org nterp_op_mul_int_lit8 + NTERP_HANDLER_SIZE // op_mul_int_lit8 handler is too big! 9403 9404/* ------------------------------ */ 9405 .balign NTERP_HANDLER_SIZE 9406.L_op_div_int_lit8: /* 0xdb */ 9407 NAME_START nterp_op_div_int_lit8 9408 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9409 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9410 9411 /* 9412 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 9413 * that specifies an instruction that performs "result = w0 op w1". 9414 * This could be an ARM instruction or a function call. (If the result 9415 * comes back in a register other than w0, you can override "result".) 9416 * 9417 * You can override "extract" if the extraction of the literal value 9418 * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 9419 * can be omitted completely if the shift is embedded in "instr". 9420 * 9421 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9422 * vCC (w1). Useful for integer division and modulus. 9423 * 9424 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 9425 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 9426 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 9427 */ 9428 /* binop/lit8 vAA, vBB, #+CC */ 9429 FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 9430 lsr w9, wINST, #8 // w9<- AA 9431 and w2, w3, #255 // w2<- BB 9432 GET_VREG w0, w2 // w0<- vBB 9433 asr w1, w3, #8 // optional; typically w1<- ssssssCC (sign extended) 9434 .if 1 9435 cbz w1, common_errDivideByZero 9436 .endif 9437 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9438 // optional op; may set condition codes 9439 sdiv w0, w0, w1 // w0<- op, w0-w3 changed 9440 GET_INST_OPCODE ip // extract opcode from rINST 9441 SET_VREG w0, w9 // vAA<- w0 9442 GOTO_OPCODE ip // jump to next instruction 9443 /* 10-12 instructions */ 9444 9445 NAME_END nterp_op_div_int_lit8 9446 // Advance to the end of this handler. Causes error if we are past that point. 9447 .org nterp_op_div_int_lit8 + NTERP_HANDLER_SIZE // op_div_int_lit8 handler is too big! 9448 9449/* ------------------------------ */ 9450 .balign NTERP_HANDLER_SIZE 9451.L_op_rem_int_lit8: /* 0xdc */ 9452 NAME_START nterp_op_rem_int_lit8 9453 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9454 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9455 9456 /* 9457 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 9458 * that specifies an instruction that performs "result = w0 op w1". 9459 * This could be an ARM instruction or a function call. (If the result 9460 * comes back in a register other than w0, you can override "result".) 9461 * 9462 * You can override "extract" if the extraction of the literal value 9463 * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 9464 * can be omitted completely if the shift is embedded in "instr". 9465 * 9466 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9467 * vCC (w1). Useful for integer division and modulus. 9468 * 9469 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 9470 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 9471 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 9472 */ 9473 /* binop/lit8 vAA, vBB, #+CC */ 9474 FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 9475 lsr w9, wINST, #8 // w9<- AA 9476 and w2, w3, #255 // w2<- BB 9477 GET_VREG w0, w2 // w0<- vBB 9478 asr w1, w3, #8 // optional; typically w1<- ssssssCC (sign extended) 9479 .if 1 9480 cbz w1, common_errDivideByZero 9481 .endif 9482 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9483 sdiv w3, w0, w1 // optional op; may set condition codes 9484 msub w0, w3, w1, w0 // w0<- op, w0-w3 changed 9485 GET_INST_OPCODE ip // extract opcode from rINST 9486 SET_VREG w0, w9 // vAA<- w0 9487 GOTO_OPCODE ip // jump to next instruction 9488 /* 10-12 instructions */ 9489 9490 NAME_END nterp_op_rem_int_lit8 9491 // Advance to the end of this handler. Causes error if we are past that point. 9492 .org nterp_op_rem_int_lit8 + NTERP_HANDLER_SIZE // op_rem_int_lit8 handler is too big! 9493 9494/* ------------------------------ */ 9495 .balign NTERP_HANDLER_SIZE 9496.L_op_and_int_lit8: /* 0xdd */ 9497 NAME_START nterp_op_and_int_lit8 9498 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9499 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9500 9501 /* 9502 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 9503 * that specifies an instruction that performs "result = w0 op w1". 9504 * This could be an ARM instruction or a function call. (If the result 9505 * comes back in a register other than w0, you can override "result".) 9506 * 9507 * You can override "extract" if the extraction of the literal value 9508 * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 9509 * can be omitted completely if the shift is embedded in "instr". 9510 * 9511 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9512 * vCC (w1). Useful for integer division and modulus. 9513 * 9514 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 9515 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 9516 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 9517 */ 9518 /* binop/lit8 vAA, vBB, #+CC */ 9519 FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 9520 lsr w9, wINST, #8 // w9<- AA 9521 and w2, w3, #255 // w2<- BB 9522 GET_VREG w0, w2 // w0<- vBB 9523 // optional; typically w1<- ssssssCC (sign extended) 9524 .if 0 9525 cbz w1, common_errDivideByZero 9526 .endif 9527 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9528 // optional op; may set condition codes 9529 and w0, w0, w3, asr #8 // w0<- op, w0-w3 changed 9530 GET_INST_OPCODE ip // extract opcode from rINST 9531 SET_VREG w0, w9 // vAA<- w0 9532 GOTO_OPCODE ip // jump to next instruction 9533 /* 10-12 instructions */ 9534 9535 NAME_END nterp_op_and_int_lit8 9536 // Advance to the end of this handler. Causes error if we are past that point. 9537 .org nterp_op_and_int_lit8 + NTERP_HANDLER_SIZE // op_and_int_lit8 handler is too big! 9538 9539/* ------------------------------ */ 9540 .balign NTERP_HANDLER_SIZE 9541.L_op_or_int_lit8: /* 0xde */ 9542 NAME_START nterp_op_or_int_lit8 9543 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9544 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9545 9546 /* 9547 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 9548 * that specifies an instruction that performs "result = w0 op w1". 9549 * This could be an ARM instruction or a function call. (If the result 9550 * comes back in a register other than w0, you can override "result".) 9551 * 9552 * You can override "extract" if the extraction of the literal value 9553 * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 9554 * can be omitted completely if the shift is embedded in "instr". 9555 * 9556 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9557 * vCC (w1). Useful for integer division and modulus. 9558 * 9559 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 9560 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 9561 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 9562 */ 9563 /* binop/lit8 vAA, vBB, #+CC */ 9564 FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 9565 lsr w9, wINST, #8 // w9<- AA 9566 and w2, w3, #255 // w2<- BB 9567 GET_VREG w0, w2 // w0<- vBB 9568 // optional; typically w1<- ssssssCC (sign extended) 9569 .if 0 9570 cbz w1, common_errDivideByZero 9571 .endif 9572 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9573 // optional op; may set condition codes 9574 orr w0, w0, w3, asr #8 // w0<- op, w0-w3 changed 9575 GET_INST_OPCODE ip // extract opcode from rINST 9576 SET_VREG w0, w9 // vAA<- w0 9577 GOTO_OPCODE ip // jump to next instruction 9578 /* 10-12 instructions */ 9579 9580 NAME_END nterp_op_or_int_lit8 9581 // Advance to the end of this handler. Causes error if we are past that point. 9582 .org nterp_op_or_int_lit8 + NTERP_HANDLER_SIZE // op_or_int_lit8 handler is too big! 9583 9584/* ------------------------------ */ 9585 .balign NTERP_HANDLER_SIZE 9586.L_op_xor_int_lit8: /* 0xdf */ 9587 NAME_START nterp_op_xor_int_lit8 9588 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9589 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9590 9591 /* 9592 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 9593 * that specifies an instruction that performs "result = w0 op w1". 9594 * This could be an ARM instruction or a function call. (If the result 9595 * comes back in a register other than w0, you can override "result".) 9596 * 9597 * You can override "extract" if the extraction of the literal value 9598 * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 9599 * can be omitted completely if the shift is embedded in "instr". 9600 * 9601 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9602 * vCC (w1). Useful for integer division and modulus. 9603 * 9604 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 9605 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 9606 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 9607 */ 9608 /* binop/lit8 vAA, vBB, #+CC */ 9609 FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 9610 lsr w9, wINST, #8 // w9<- AA 9611 and w2, w3, #255 // w2<- BB 9612 GET_VREG w0, w2 // w0<- vBB 9613 // optional; typically w1<- ssssssCC (sign extended) 9614 .if 0 9615 cbz w1, common_errDivideByZero 9616 .endif 9617 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9618 // optional op; may set condition codes 9619 eor w0, w0, w3, asr #8 // w0<- op, w0-w3 changed 9620 GET_INST_OPCODE ip // extract opcode from rINST 9621 SET_VREG w0, w9 // vAA<- w0 9622 GOTO_OPCODE ip // jump to next instruction 9623 /* 10-12 instructions */ 9624 9625 NAME_END nterp_op_xor_int_lit8 9626 // Advance to the end of this handler. Causes error if we are past that point. 9627 .org nterp_op_xor_int_lit8 + NTERP_HANDLER_SIZE // op_xor_int_lit8 handler is too big! 9628 9629/* ------------------------------ */ 9630 .balign NTERP_HANDLER_SIZE 9631.L_op_shl_int_lit8: /* 0xe0 */ 9632 NAME_START nterp_op_shl_int_lit8 9633 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9634 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9635 9636 /* 9637 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 9638 * that specifies an instruction that performs "result = w0 op w1". 9639 * This could be an ARM instruction or a function call. (If the result 9640 * comes back in a register other than w0, you can override "result".) 9641 * 9642 * You can override "extract" if the extraction of the literal value 9643 * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 9644 * can be omitted completely if the shift is embedded in "instr". 9645 * 9646 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9647 * vCC (w1). Useful for integer division and modulus. 9648 * 9649 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 9650 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 9651 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 9652 */ 9653 /* binop/lit8 vAA, vBB, #+CC */ 9654 FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 9655 lsr w9, wINST, #8 // w9<- AA 9656 and w2, w3, #255 // w2<- BB 9657 GET_VREG w0, w2 // w0<- vBB 9658 ubfx w1, w3, #8, #5 // optional; typically w1<- ssssssCC (sign extended) 9659 .if 0 9660 cbz w1, common_errDivideByZero 9661 .endif 9662 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9663 // optional op; may set condition codes 9664 lsl w0, w0, w1 // w0<- op, w0-w3 changed 9665 GET_INST_OPCODE ip // extract opcode from rINST 9666 SET_VREG w0, w9 // vAA<- w0 9667 GOTO_OPCODE ip // jump to next instruction 9668 /* 10-12 instructions */ 9669 9670 NAME_END nterp_op_shl_int_lit8 9671 // Advance to the end of this handler. Causes error if we are past that point. 9672 .org nterp_op_shl_int_lit8 + NTERP_HANDLER_SIZE // op_shl_int_lit8 handler is too big! 9673 9674/* ------------------------------ */ 9675 .balign NTERP_HANDLER_SIZE 9676.L_op_shr_int_lit8: /* 0xe1 */ 9677 NAME_START nterp_op_shr_int_lit8 9678 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9679 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9680 9681 /* 9682 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 9683 * that specifies an instruction that performs "result = w0 op w1". 9684 * This could be an ARM instruction or a function call. (If the result 9685 * comes back in a register other than w0, you can override "result".) 9686 * 9687 * You can override "extract" if the extraction of the literal value 9688 * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 9689 * can be omitted completely if the shift is embedded in "instr". 9690 * 9691 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9692 * vCC (w1). Useful for integer division and modulus. 9693 * 9694 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 9695 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 9696 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 9697 */ 9698 /* binop/lit8 vAA, vBB, #+CC */ 9699 FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 9700 lsr w9, wINST, #8 // w9<- AA 9701 and w2, w3, #255 // w2<- BB 9702 GET_VREG w0, w2 // w0<- vBB 9703 ubfx w1, w3, #8, #5 // optional; typically w1<- ssssssCC (sign extended) 9704 .if 0 9705 cbz w1, common_errDivideByZero 9706 .endif 9707 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9708 // optional op; may set condition codes 9709 asr w0, w0, w1 // w0<- op, w0-w3 changed 9710 GET_INST_OPCODE ip // extract opcode from rINST 9711 SET_VREG w0, w9 // vAA<- w0 9712 GOTO_OPCODE ip // jump to next instruction 9713 /* 10-12 instructions */ 9714 9715 NAME_END nterp_op_shr_int_lit8 9716 // Advance to the end of this handler. Causes error if we are past that point. 9717 .org nterp_op_shr_int_lit8 + NTERP_HANDLER_SIZE // op_shr_int_lit8 handler is too big! 9718 9719/* ------------------------------ */ 9720 .balign NTERP_HANDLER_SIZE 9721.L_op_ushr_int_lit8: /* 0xe2 */ 9722 NAME_START nterp_op_ushr_int_lit8 9723 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9724 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9725 9726 /* 9727 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 9728 * that specifies an instruction that performs "result = w0 op w1". 9729 * This could be an ARM instruction or a function call. (If the result 9730 * comes back in a register other than w0, you can override "result".) 9731 * 9732 * You can override "extract" if the extraction of the literal value 9733 * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 9734 * can be omitted completely if the shift is embedded in "instr". 9735 * 9736 * If "chkzero" is set to 1, we perform a divide-by-zero check on 9737 * vCC (w1). Useful for integer division and modulus. 9738 * 9739 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 9740 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 9741 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 9742 */ 9743 /* binop/lit8 vAA, vBB, #+CC */ 9744 FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 9745 lsr w9, wINST, #8 // w9<- AA 9746 and w2, w3, #255 // w2<- BB 9747 GET_VREG w0, w2 // w0<- vBB 9748 ubfx w1, w3, #8, #5 // optional; typically w1<- ssssssCC (sign extended) 9749 .if 0 9750 cbz w1, common_errDivideByZero 9751 .endif 9752 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 9753 // optional op; may set condition codes 9754 lsr w0, w0, w1 // w0<- op, w0-w3 changed 9755 GET_INST_OPCODE ip // extract opcode from rINST 9756 SET_VREG w0, w9 // vAA<- w0 9757 GOTO_OPCODE ip // jump to next instruction 9758 /* 10-12 instructions */ 9759 9760 NAME_END nterp_op_ushr_int_lit8 9761 // Advance to the end of this handler. Causes error if we are past that point. 9762 .org nterp_op_ushr_int_lit8 + NTERP_HANDLER_SIZE // op_ushr_int_lit8 handler is too big! 9763 9764/* ------------------------------ */ 9765 .balign NTERP_HANDLER_SIZE 9766.L_op_unused_e3: /* 0xe3 */ 9767 NAME_START nterp_op_unused_e3 9768 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9769 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9770 9771 brk 42 9772 9773 NAME_END nterp_op_unused_e3 9774 // Advance to the end of this handler. Causes error if we are past that point. 9775 .org nterp_op_unused_e3 + NTERP_HANDLER_SIZE // op_unused_e3 handler is too big! 9776 9777/* ------------------------------ */ 9778 .balign NTERP_HANDLER_SIZE 9779.L_op_unused_e4: /* 0xe4 */ 9780 NAME_START nterp_op_unused_e4 9781 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9782 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9783 9784 brk 42 9785 9786 NAME_END nterp_op_unused_e4 9787 // Advance to the end of this handler. Causes error if we are past that point. 9788 .org nterp_op_unused_e4 + NTERP_HANDLER_SIZE // op_unused_e4 handler is too big! 9789 9790/* ------------------------------ */ 9791 .balign NTERP_HANDLER_SIZE 9792.L_op_unused_e5: /* 0xe5 */ 9793 NAME_START nterp_op_unused_e5 9794 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9795 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9796 9797 brk 42 9798 9799 NAME_END nterp_op_unused_e5 9800 // Advance to the end of this handler. Causes error if we are past that point. 9801 .org nterp_op_unused_e5 + NTERP_HANDLER_SIZE // op_unused_e5 handler is too big! 9802 9803/* ------------------------------ */ 9804 .balign NTERP_HANDLER_SIZE 9805.L_op_unused_e6: /* 0xe6 */ 9806 NAME_START nterp_op_unused_e6 9807 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9808 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9809 9810 brk 42 9811 9812 NAME_END nterp_op_unused_e6 9813 // Advance to the end of this handler. Causes error if we are past that point. 9814 .org nterp_op_unused_e6 + NTERP_HANDLER_SIZE // op_unused_e6 handler is too big! 9815 9816/* ------------------------------ */ 9817 .balign NTERP_HANDLER_SIZE 9818.L_op_unused_e7: /* 0xe7 */ 9819 NAME_START nterp_op_unused_e7 9820 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9821 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9822 9823 brk 42 9824 9825 NAME_END nterp_op_unused_e7 9826 // Advance to the end of this handler. Causes error if we are past that point. 9827 .org nterp_op_unused_e7 + NTERP_HANDLER_SIZE // op_unused_e7 handler is too big! 9828 9829/* ------------------------------ */ 9830 .balign NTERP_HANDLER_SIZE 9831.L_op_unused_e8: /* 0xe8 */ 9832 NAME_START nterp_op_unused_e8 9833 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9834 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9835 9836 brk 42 9837 9838 NAME_END nterp_op_unused_e8 9839 // Advance to the end of this handler. Causes error if we are past that point. 9840 .org nterp_op_unused_e8 + NTERP_HANDLER_SIZE // op_unused_e8 handler is too big! 9841 9842/* ------------------------------ */ 9843 .balign NTERP_HANDLER_SIZE 9844.L_op_unused_e9: /* 0xe9 */ 9845 NAME_START nterp_op_unused_e9 9846 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9847 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9848 9849 brk 42 9850 9851 NAME_END nterp_op_unused_e9 9852 // Advance to the end of this handler. Causes error if we are past that point. 9853 .org nterp_op_unused_e9 + NTERP_HANDLER_SIZE // op_unused_e9 handler is too big! 9854 9855/* ------------------------------ */ 9856 .balign NTERP_HANDLER_SIZE 9857.L_op_unused_ea: /* 0xea */ 9858 NAME_START nterp_op_unused_ea 9859 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9860 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9861 9862 brk 42 9863 9864 NAME_END nterp_op_unused_ea 9865 // Advance to the end of this handler. Causes error if we are past that point. 9866 .org nterp_op_unused_ea + NTERP_HANDLER_SIZE // op_unused_ea handler is too big! 9867 9868/* ------------------------------ */ 9869 .balign NTERP_HANDLER_SIZE 9870.L_op_unused_eb: /* 0xeb */ 9871 NAME_START nterp_op_unused_eb 9872 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9873 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9874 9875 brk 42 9876 9877 NAME_END nterp_op_unused_eb 9878 // Advance to the end of this handler. Causes error if we are past that point. 9879 .org nterp_op_unused_eb + NTERP_HANDLER_SIZE // op_unused_eb handler is too big! 9880 9881/* ------------------------------ */ 9882 .balign NTERP_HANDLER_SIZE 9883.L_op_unused_ec: /* 0xec */ 9884 NAME_START nterp_op_unused_ec 9885 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9886 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9887 9888 brk 42 9889 9890 NAME_END nterp_op_unused_ec 9891 // Advance to the end of this handler. Causes error if we are past that point. 9892 .org nterp_op_unused_ec + NTERP_HANDLER_SIZE // op_unused_ec handler is too big! 9893 9894/* ------------------------------ */ 9895 .balign NTERP_HANDLER_SIZE 9896.L_op_unused_ed: /* 0xed */ 9897 NAME_START nterp_op_unused_ed 9898 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9899 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9900 9901 brk 42 9902 9903 NAME_END nterp_op_unused_ed 9904 // Advance to the end of this handler. Causes error if we are past that point. 9905 .org nterp_op_unused_ed + NTERP_HANDLER_SIZE // op_unused_ed handler is too big! 9906 9907/* ------------------------------ */ 9908 .balign NTERP_HANDLER_SIZE 9909.L_op_unused_ee: /* 0xee */ 9910 NAME_START nterp_op_unused_ee 9911 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9912 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9913 9914 brk 42 9915 9916 NAME_END nterp_op_unused_ee 9917 // Advance to the end of this handler. Causes error if we are past that point. 9918 .org nterp_op_unused_ee + NTERP_HANDLER_SIZE // op_unused_ee handler is too big! 9919 9920/* ------------------------------ */ 9921 .balign NTERP_HANDLER_SIZE 9922.L_op_unused_ef: /* 0xef */ 9923 NAME_START nterp_op_unused_ef 9924 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9925 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9926 9927 brk 42 9928 9929 NAME_END nterp_op_unused_ef 9930 // Advance to the end of this handler. Causes error if we are past that point. 9931 .org nterp_op_unused_ef + NTERP_HANDLER_SIZE // op_unused_ef handler is too big! 9932 9933/* ------------------------------ */ 9934 .balign NTERP_HANDLER_SIZE 9935.L_op_unused_f0: /* 0xf0 */ 9936 NAME_START nterp_op_unused_f0 9937 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9938 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9939 9940 brk 42 9941 9942 NAME_END nterp_op_unused_f0 9943 // Advance to the end of this handler. Causes error if we are past that point. 9944 .org nterp_op_unused_f0 + NTERP_HANDLER_SIZE // op_unused_f0 handler is too big! 9945 9946/* ------------------------------ */ 9947 .balign NTERP_HANDLER_SIZE 9948.L_op_unused_f1: /* 0xf1 */ 9949 NAME_START nterp_op_unused_f1 9950 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9951 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9952 9953 brk 42 9954 9955 NAME_END nterp_op_unused_f1 9956 // Advance to the end of this handler. Causes error if we are past that point. 9957 .org nterp_op_unused_f1 + NTERP_HANDLER_SIZE // op_unused_f1 handler is too big! 9958 9959/* ------------------------------ */ 9960 .balign NTERP_HANDLER_SIZE 9961.L_op_unused_f2: /* 0xf2 */ 9962 NAME_START nterp_op_unused_f2 9963 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9964 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9965 9966 brk 42 9967 9968 NAME_END nterp_op_unused_f2 9969 // Advance to the end of this handler. Causes error if we are past that point. 9970 .org nterp_op_unused_f2 + NTERP_HANDLER_SIZE // op_unused_f2 handler is too big! 9971 9972/* ------------------------------ */ 9973 .balign NTERP_HANDLER_SIZE 9974.L_op_unused_f3: /* 0xf3 */ 9975 NAME_START nterp_op_unused_f3 9976 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9977 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9978 9979 brk 42 9980 9981 NAME_END nterp_op_unused_f3 9982 // Advance to the end of this handler. Causes error if we are past that point. 9983 .org nterp_op_unused_f3 + NTERP_HANDLER_SIZE // op_unused_f3 handler is too big! 9984 9985/* ------------------------------ */ 9986 .balign NTERP_HANDLER_SIZE 9987.L_op_unused_f4: /* 0xf4 */ 9988 NAME_START nterp_op_unused_f4 9989 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 9990 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 9991 9992 brk 42 9993 9994 NAME_END nterp_op_unused_f4 9995 // Advance to the end of this handler. Causes error if we are past that point. 9996 .org nterp_op_unused_f4 + NTERP_HANDLER_SIZE // op_unused_f4 handler is too big! 9997 9998/* ------------------------------ */ 9999 .balign NTERP_HANDLER_SIZE 10000.L_op_unused_f5: /* 0xf5 */ 10001 NAME_START nterp_op_unused_f5 10002 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 10003 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 10004 10005 brk 42 10006 10007 NAME_END nterp_op_unused_f5 10008 // Advance to the end of this handler. Causes error if we are past that point. 10009 .org nterp_op_unused_f5 + NTERP_HANDLER_SIZE // op_unused_f5 handler is too big! 10010 10011/* ------------------------------ */ 10012 .balign NTERP_HANDLER_SIZE 10013.L_op_unused_f6: /* 0xf6 */ 10014 NAME_START nterp_op_unused_f6 10015 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 10016 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 10017 10018 brk 42 10019 10020 NAME_END nterp_op_unused_f6 10021 // Advance to the end of this handler. Causes error if we are past that point. 10022 .org nterp_op_unused_f6 + NTERP_HANDLER_SIZE // op_unused_f6 handler is too big! 10023 10024/* ------------------------------ */ 10025 .balign NTERP_HANDLER_SIZE 10026.L_op_unused_f7: /* 0xf7 */ 10027 NAME_START nterp_op_unused_f7 10028 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 10029 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 10030 10031 brk 42 10032 10033 NAME_END nterp_op_unused_f7 10034 // Advance to the end of this handler. Causes error if we are past that point. 10035 .org nterp_op_unused_f7 + NTERP_HANDLER_SIZE // op_unused_f7 handler is too big! 10036 10037/* ------------------------------ */ 10038 .balign NTERP_HANDLER_SIZE 10039.L_op_unused_f8: /* 0xf8 */ 10040 NAME_START nterp_op_unused_f8 10041 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 10042 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 10043 10044 brk 42 10045 10046 NAME_END nterp_op_unused_f8 10047 // Advance to the end of this handler. Causes error if we are past that point. 10048 .org nterp_op_unused_f8 + NTERP_HANDLER_SIZE // op_unused_f8 handler is too big! 10049 10050/* ------------------------------ */ 10051 .balign NTERP_HANDLER_SIZE 10052.L_op_unused_f9: /* 0xf9 */ 10053 NAME_START nterp_op_unused_f9 10054 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 10055 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 10056 10057 brk 42 10058 10059 NAME_END nterp_op_unused_f9 10060 // Advance to the end of this handler. Causes error if we are past that point. 10061 .org nterp_op_unused_f9 + NTERP_HANDLER_SIZE // op_unused_f9 handler is too big! 10062 10063/* ------------------------------ */ 10064 .balign NTERP_HANDLER_SIZE 10065.L_op_invoke_polymorphic: /* 0xfa */ 10066 NAME_START nterp_op_invoke_polymorphic 10067 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 10068 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 10069 10070 EXPORT_PC 10071 // No need to fetch the target method. 10072 // Load the first argument (the 'this' pointer). 10073 FETCH w1, 2 10074 and w1, w1, #0xf 10075 GET_VREG w1, w1 10076 cbz w1, common_errNullObject // bail if null 10077 b NterpCommonInvokePolymorphic 10078 10079 NAME_END nterp_op_invoke_polymorphic 10080 // Advance to the end of this handler. Causes error if we are past that point. 10081 .org nterp_op_invoke_polymorphic + NTERP_HANDLER_SIZE // op_invoke_polymorphic handler is too big! 10082 10083/* ------------------------------ */ 10084 .balign NTERP_HANDLER_SIZE 10085.L_op_invoke_polymorphic_range: /* 0xfb */ 10086 NAME_START nterp_op_invoke_polymorphic_range 10087 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 10088 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 10089 10090 EXPORT_PC 10091 // No need to fetch the target method. 10092 // Load the first argument (the 'this' pointer). 10093 FETCH w1, 2 10094 GET_VREG w1, w1 10095 cbz w1, common_errNullObject // bail if null 10096 b NterpCommonInvokePolymorphicRange 10097 10098 NAME_END nterp_op_invoke_polymorphic_range 10099 // Advance to the end of this handler. Causes error if we are past that point. 10100 .org nterp_op_invoke_polymorphic_range + NTERP_HANDLER_SIZE // op_invoke_polymorphic_range handler is too big! 10101 10102/* ------------------------------ */ 10103 .balign NTERP_HANDLER_SIZE 10104.L_op_invoke_custom: /* 0xfc */ 10105 NAME_START nterp_op_invoke_custom 10106 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 10107 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 10108 10109 EXPORT_PC 10110 FETCH w0, 1 // call_site index, first argument of runtime call. 10111 b NterpCommonInvokeCustom 10112 10113 NAME_END nterp_op_invoke_custom 10114 // Advance to the end of this handler. Causes error if we are past that point. 10115 .org nterp_op_invoke_custom + NTERP_HANDLER_SIZE // op_invoke_custom handler is too big! 10116 10117/* ------------------------------ */ 10118 .balign NTERP_HANDLER_SIZE 10119.L_op_invoke_custom_range: /* 0xfd */ 10120 NAME_START nterp_op_invoke_custom_range 10121 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 10122 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 10123 10124 EXPORT_PC 10125 FETCH w0, 1 // call_site index, first argument of runtime call. 10126 b NterpCommonInvokeCustomRange 10127 10128 NAME_END nterp_op_invoke_custom_range 10129 // Advance to the end of this handler. Causes error if we are past that point. 10130 .org nterp_op_invoke_custom_range + NTERP_HANDLER_SIZE // op_invoke_custom_range handler is too big! 10131 10132/* ------------------------------ */ 10133 .balign NTERP_HANDLER_SIZE 10134.L_op_const_method_handle: /* 0xfe */ 10135 NAME_START nterp_op_const_method_handle 10136 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 10137 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 10138 10139 // Fast-path which gets the object from thread-local cache. 10140 // Fetch some information from the thread cache. 10141 // Uses ip and ip2 as temporaries. 10142 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 10143 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 10144 add ip, ip, ip2, lsl #4 // entry address within the cache 10145 ldp ip, x0, [ip] // entry key (pc) and value (offset) 10146 cmp ip, xPC 10147 b.ne 2f 10148 10149 TEST_IF_MARKING 3f 101501: 10151 lsr w1, wINST, #8 // w1<- AA 10152 .if 0 10153 FETCH_ADVANCE_INST 3 // advance rPC, load wINST 10154 .else 10155 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 10156 .endif 10157 GET_INST_OPCODE ip // extract opcode from wINST 10158 SET_VREG_OBJECT w0, w1 // vAA <- value 10159 GOTO_OPCODE ip // jump to next instruction 101602: 10161 EXPORT_PC 10162 mov x0, xSELF 10163 ldr x1, [sp] 10164 mov x2, xPC 10165 bl nterp_load_object 10166 b 1b 101673: 10168 bl art_quick_read_barrier_mark_reg00 10169 b 1b 10170 10171 NAME_END nterp_op_const_method_handle 10172 // Advance to the end of this handler. Causes error if we are past that point. 10173 .org nterp_op_const_method_handle + NTERP_HANDLER_SIZE // op_const_method_handle handler is too big! 10174 10175/* ------------------------------ */ 10176 .balign NTERP_HANDLER_SIZE 10177.L_op_const_method_type: /* 0xff */ 10178 NAME_START nterp_op_const_method_type 10179 # Explicitly restore CFA, just in case the previous opcode clobbered it (by .cfi_def_*). 10180 CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -8, CALLEE_SAVES_SIZE 10181 10182 // Fast-path which gets the object from thread-local cache. 10183 // Fetch some information from the thread cache. 10184 // Uses ip and ip2 as temporaries. 10185 add ip, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 10186 ubfx ip2, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 10187 add ip, ip, ip2, lsl #4 // entry address within the cache 10188 ldp ip, x0, [ip] // entry key (pc) and value (offset) 10189 cmp ip, xPC 10190 b.ne 2f 10191 10192 TEST_IF_MARKING 3f 101931: 10194 lsr w1, wINST, #8 // w1<- AA 10195 .if 0 10196 FETCH_ADVANCE_INST 3 // advance rPC, load wINST 10197 .else 10198 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 10199 .endif 10200 GET_INST_OPCODE ip // extract opcode from wINST 10201 SET_VREG_OBJECT w0, w1 // vAA <- value 10202 GOTO_OPCODE ip // jump to next instruction 102032: 10204 EXPORT_PC 10205 mov x0, xSELF 10206 ldr x1, [sp] 10207 mov x2, xPC 10208 bl nterp_load_object 10209 b 1b 102103: 10211 bl art_quick_read_barrier_mark_reg00 10212 b 1b 10213 10214 NAME_END nterp_op_const_method_type 10215 // Advance to the end of this handler. Causes error if we are past that point. 10216 .org nterp_op_const_method_type + NTERP_HANDLER_SIZE // op_const_method_type handler is too big! 10217 10218 .balign NTERP_HANDLER_SIZE 10219 10220 .type artNterpAsmInstructionEnd, #function 10221 .hidden artNterpAsmInstructionEnd 10222 .global artNterpAsmInstructionEnd 10223artNterpAsmInstructionEnd: 10224 // artNterpAsmInstructionEnd is used as landing pad for exception handling. 10225 FETCH_INST 10226 GET_INST_OPCODE ip 10227 GOTO_OPCODE ip 10228 10229 NAME_START nterp_op_check_cast_slow_path 10230 // We don't do read barriers for simplicity. However, this means that x1 10231 // (and all other fetched objects) may be a from-space reference. Tthat's OK as 10232 // we only fetch constant information from the references. 10233 // This also means that some of the comparisons below may lead to false negative, 10234 // but it will eventually be handled in the runtime. 10235 ldr w3, [x1, #MIRROR_CLASS_ACCESS_FLAGS_OFFSET] 10236 tbnz w3, #MIRROR_CLASS_IS_INTERFACE_FLAG_BIT, 2f 10237 ldr w3, [x1, #MIRROR_CLASS_COMPONENT_TYPE_OFFSET] 10238 UNPOISON_HEAP_REF w3 10239 cbnz w3, 5f 102401: 10241 ldr w2, [x2, #MIRROR_CLASS_SUPER_CLASS_OFFSET] 10242 UNPOISON_HEAP_REF w2 10243 cmp w1, w2 10244 beq .Lop_check_cast_resume 10245 cbnz w2, 1b 102462: 10247 TEST_IF_MARKING 4f 102483: 10249 EXPORT_PC 10250 bl art_quick_check_instance_of 10251 b .Lop_check_cast_resume 102524: 10253 bl art_quick_read_barrier_mark_reg01 10254 b 3b 102555: 10256 // Class in w1 is an array, w3 is the component type. 10257 ldr w2, [x2, #MIRROR_CLASS_COMPONENT_TYPE_OFFSET] 10258 UNPOISON_HEAP_REF w2 10259 // Check if object is an array. 10260 cbz w2, 2b 10261 ldr w4, [x3, #MIRROR_CLASS_SUPER_CLASS_OFFSET] 10262 UNPOISON_HEAP_REF w4 10263 // If the super class of the component type is not null, go slow path. 10264 cbnz w4, 2b 10265 ldrh w3, [x3, #MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET] 10266 // If the component type is primitive, go slow path. 10267 cbnz w3, 2b 10268 // Check if the object is a primitive array. 10269 ldrh w2, [x2, #MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET] 10270 cbz w2, .Lop_check_cast_resume 10271 // Go slow path for throwing the exception. 10272 b 2b 10273 10274 NAME_END nterp_op_check_cast_slow_path 10275 NAME_START nterp_op_iget_boolean_slow_path 10276 mov x0, xSELF 10277 ldr x1, [sp] 10278 mov x2, xPC 10279 mov x3, #0 10280 EXPORT_PC 10281 bl nterp_get_instance_field_offset 10282 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10283 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10284 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10285 mov w0, w0 10286 tbz w0, #31, .Lop_iget_boolean_resume 10287 CLEAR_INSTANCE_VOLATILE_MARKER w0 10288 lsr w2, wINST, #12 // w2<- B 10289 GET_VREG w3, w2 // w3<- object we're operating on 10290 ubfx w2, wINST, #8, #4 // w2<- A 10291 cbz w3, common_errNullObject // object was null 10292 add x3, x3, x0 10293 .if 0 10294 ldarb x0, [x3] 10295 SET_VREG_WIDE x0, w2 // fp[A] <- value 10296 .elseif 0 10297 ldarb w0, [x3] 10298 UNPOISON_HEAP_REF w0 10299 TEST_IF_MARKING .Lop_iget_boolean_read_barrier 10300 SET_VREG_OBJECT w0, w2 // fp[A] <- value 10301 .else 10302 ldarb w0, [x3] 10303 10304 SET_VREG w0, w2 // fp[A] <- value 10305 .endif 10306 FETCH_ADVANCE_INST 2 10307 GET_INST_OPCODE ip 10308 GOTO_OPCODE ip 10309 10310 NAME_END nterp_op_iget_boolean_slow_path 10311 NAME_START nterp_op_iget_byte_slow_path 10312 mov x0, xSELF 10313 ldr x1, [sp] 10314 mov x2, xPC 10315 mov x3, #0 10316 EXPORT_PC 10317 bl nterp_get_instance_field_offset 10318 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10319 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10320 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10321 mov w0, w0 10322 tbz w0, #31, .Lop_iget_byte_resume 10323 CLEAR_INSTANCE_VOLATILE_MARKER w0 10324 lsr w2, wINST, #12 // w2<- B 10325 GET_VREG w3, w2 // w3<- object we're operating on 10326 ubfx w2, wINST, #8, #4 // w2<- A 10327 cbz w3, common_errNullObject // object was null 10328 add x3, x3, x0 10329 .if 0 10330 ldarb x0, [x3] 10331 SET_VREG_WIDE x0, w2 // fp[A] <- value 10332 .elseif 0 10333 ldarb w0, [x3] 10334 UNPOISON_HEAP_REF w0 10335 TEST_IF_MARKING .Lop_iget_byte_read_barrier 10336 SET_VREG_OBJECT w0, w2 // fp[A] <- value 10337 .else 10338 ldarb w0, [x3] 10339 sxtb w0, w0 10340 SET_VREG w0, w2 // fp[A] <- value 10341 .endif 10342 FETCH_ADVANCE_INST 2 10343 GET_INST_OPCODE ip 10344 GOTO_OPCODE ip 10345 10346 NAME_END nterp_op_iget_byte_slow_path 10347 NAME_START nterp_op_iget_char_slow_path 10348 mov x0, xSELF 10349 ldr x1, [sp] 10350 mov x2, xPC 10351 mov x3, #0 10352 EXPORT_PC 10353 bl nterp_get_instance_field_offset 10354 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10355 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10356 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10357 mov w0, w0 10358 tbz w0, #31, .Lop_iget_char_resume 10359 CLEAR_INSTANCE_VOLATILE_MARKER w0 10360 lsr w2, wINST, #12 // w2<- B 10361 GET_VREG w3, w2 // w3<- object we're operating on 10362 ubfx w2, wINST, #8, #4 // w2<- A 10363 cbz w3, common_errNullObject // object was null 10364 add x3, x3, x0 10365 .if 0 10366 ldarh x0, [x3] 10367 SET_VREG_WIDE x0, w2 // fp[A] <- value 10368 .elseif 0 10369 ldarh w0, [x3] 10370 UNPOISON_HEAP_REF w0 10371 TEST_IF_MARKING .Lop_iget_char_read_barrier 10372 SET_VREG_OBJECT w0, w2 // fp[A] <- value 10373 .else 10374 ldarh w0, [x3] 10375 10376 SET_VREG w0, w2 // fp[A] <- value 10377 .endif 10378 FETCH_ADVANCE_INST 2 10379 GET_INST_OPCODE ip 10380 GOTO_OPCODE ip 10381 10382 NAME_END nterp_op_iget_char_slow_path 10383 NAME_START nterp_op_iget_object_slow_path 10384 mov x0, xSELF 10385 ldr x1, [sp] 10386 mov x2, xPC 10387 mov x3, #0 10388 EXPORT_PC 10389 bl nterp_get_instance_field_offset 10390 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10391 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10392 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10393 mov w0, w0 10394 tbz w0, #31, .Lop_iget_object_resume 10395 CLEAR_INSTANCE_VOLATILE_MARKER w0 10396 lsr w2, wINST, #12 // w2<- B 10397 GET_VREG w3, w2 // w3<- object we're operating on 10398 ubfx w2, wINST, #8, #4 // w2<- A 10399 cbz w3, common_errNullObject // object was null 10400 add x3, x3, x0 10401 .if 0 10402 ldar x0, [x3] 10403 SET_VREG_WIDE x0, w2 // fp[A] <- value 10404 .elseif 1 10405 ldar w0, [x3] 10406 UNPOISON_HEAP_REF w0 10407 TEST_IF_MARKING .Lop_iget_object_read_barrier 10408 SET_VREG_OBJECT w0, w2 // fp[A] <- value 10409 .else 10410 ldar w0, [x3] 10411 10412 SET_VREG w0, w2 // fp[A] <- value 10413 .endif 10414 FETCH_ADVANCE_INST 2 10415 GET_INST_OPCODE ip 10416 GOTO_OPCODE ip 10417 10418 NAME_END nterp_op_iget_object_slow_path 10419 NAME_START nterp_op_iget_short_slow_path 10420 mov x0, xSELF 10421 ldr x1, [sp] 10422 mov x2, xPC 10423 mov x3, #0 10424 EXPORT_PC 10425 bl nterp_get_instance_field_offset 10426 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10427 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10428 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10429 mov w0, w0 10430 tbz w0, #31, .Lop_iget_short_resume 10431 CLEAR_INSTANCE_VOLATILE_MARKER w0 10432 lsr w2, wINST, #12 // w2<- B 10433 GET_VREG w3, w2 // w3<- object we're operating on 10434 ubfx w2, wINST, #8, #4 // w2<- A 10435 cbz w3, common_errNullObject // object was null 10436 add x3, x3, x0 10437 .if 0 10438 ldarh x0, [x3] 10439 SET_VREG_WIDE x0, w2 // fp[A] <- value 10440 .elseif 0 10441 ldarh w0, [x3] 10442 UNPOISON_HEAP_REF w0 10443 TEST_IF_MARKING .Lop_iget_short_read_barrier 10444 SET_VREG_OBJECT w0, w2 // fp[A] <- value 10445 .else 10446 ldarh w0, [x3] 10447 sxth w0, w0 10448 SET_VREG w0, w2 // fp[A] <- value 10449 .endif 10450 FETCH_ADVANCE_INST 2 10451 GET_INST_OPCODE ip 10452 GOTO_OPCODE ip 10453 10454 NAME_END nterp_op_iget_short_slow_path 10455 NAME_START nterp_op_iget_slow_path 10456 mov x0, xSELF 10457 ldr x1, [sp] 10458 mov x2, xPC 10459 mov x3, #0 10460 EXPORT_PC 10461 bl nterp_get_instance_field_offset 10462 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10463 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10464 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10465 mov w0, w0 10466 tbz w0, #31, .Lop_iget_resume 10467 CLEAR_INSTANCE_VOLATILE_MARKER w0 10468 lsr w2, wINST, #12 // w2<- B 10469 GET_VREG w3, w2 // w3<- object we're operating on 10470 ubfx w2, wINST, #8, #4 // w2<- A 10471 cbz w3, common_errNullObject // object was null 10472 add x3, x3, x0 10473 .if 0 10474 ldar x0, [x3] 10475 SET_VREG_WIDE x0, w2 // fp[A] <- value 10476 .elseif 0 10477 ldar w0, [x3] 10478 UNPOISON_HEAP_REF w0 10479 TEST_IF_MARKING .Lop_iget_read_barrier 10480 SET_VREG_OBJECT w0, w2 // fp[A] <- value 10481 .else 10482 ldar w0, [x3] 10483 10484 SET_VREG w0, w2 // fp[A] <- value 10485 .endif 10486 FETCH_ADVANCE_INST 2 10487 GET_INST_OPCODE ip 10488 GOTO_OPCODE ip 10489 10490 NAME_END nterp_op_iget_slow_path 10491 NAME_START nterp_op_iget_wide_slow_path 10492 mov x0, xSELF 10493 ldr x1, [sp] 10494 mov x2, xPC 10495 mov x3, #0 10496 EXPORT_PC 10497 bl nterp_get_instance_field_offset 10498 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10499 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10500 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10501 mov w0, w0 10502 tbz w0, #31, .Lop_iget_wide_resume 10503 CLEAR_INSTANCE_VOLATILE_MARKER w0 10504 lsr w2, wINST, #12 // w2<- B 10505 GET_VREG w3, w2 // w3<- object we're operating on 10506 ubfx w2, wINST, #8, #4 // w2<- A 10507 cbz w3, common_errNullObject // object was null 10508 add x3, x3, x0 10509 .if 1 10510 ldar x0, [x3] 10511 SET_VREG_WIDE x0, w2 // fp[A] <- value 10512 .elseif 0 10513 ldar w0, [x3] 10514 UNPOISON_HEAP_REF w0 10515 TEST_IF_MARKING .Lop_iget_wide_read_barrier 10516 SET_VREG_OBJECT w0, w2 // fp[A] <- value 10517 .else 10518 ldar w0, [x3] 10519 10520 SET_VREG w0, w2 // fp[A] <- value 10521 .endif 10522 FETCH_ADVANCE_INST 2 10523 GET_INST_OPCODE ip 10524 GOTO_OPCODE ip 10525 10526 NAME_END nterp_op_iget_wide_slow_path 10527 NAME_START nterp_op_instance_of_slow_path 10528 // Go slow path if we are marking. Checking now allows 10529 // not going to slow path if the super class hierarchy check fails. 10530 TEST_IF_MARKING 4f 10531 ldr w3, [x1, #MIRROR_CLASS_ACCESS_FLAGS_OFFSET] 10532 tbnz w3, #MIRROR_CLASS_IS_INTERFACE_FLAG_BIT, 5f 10533 ldr w3, [x1, #MIRROR_CLASS_COMPONENT_TYPE_OFFSET] 10534 UNPOISON_HEAP_REF w3 10535 cbnz w3, 3f 105361: 10537 ldr w2, [x2, #MIRROR_CLASS_SUPER_CLASS_OFFSET] 10538 UNPOISON_HEAP_REF w2 10539 cmp w1, w2 10540 beq .Lop_instance_of_set_one 10541 cbnz w2, 1b 105422: 10543 mov w0, #0 10544 b .Lop_instance_of_resume 105453: 10546 // Class in x1 is an array, x3 is the component type of x1, and x2 is the class of the object. 10547 ldr w2, [x2, #MIRROR_CLASS_COMPONENT_TYPE_OFFSET] 10548 UNPOISON_HEAP_REF w2 10549 // Check if object is an array. 10550 cbz w2, 2b 10551 // Check of x1 is Object[] 10552 ldr w4, [x3, #MIRROR_CLASS_SUPER_CLASS_OFFSET] 10553 UNPOISON_HEAP_REF w4 10554 // If the super class is not Object, go to slow path. 10555 cbnz w4, 5f 10556 // Super class is null, this could either be a primitive array or Object[]. 10557 ldrh w3, [x3, #MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET] 10558 // If x1 is a primitive array class, we know the check is false. 10559 cbnz w3, 2b 10560 // Check if x2 is a primitive array class. 10561 ldrh w2, [x2, #MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET] 10562 cmp w2, #0 10563 cset w0, eq 10564 b .Lop_instance_of_resume 105654: 10566 bl art_quick_read_barrier_mark_reg01 105675: 10568 EXPORT_PC 10569 bl artInstanceOfFromCode 10570 b .Lop_instance_of_resume 10571 10572 NAME_END nterp_op_instance_of_slow_path 10573 NAME_START nterp_op_invoke_interface_range_slow_path 10574 mov x0, xSELF 10575 ldr x1, [sp] 10576 mov x2, xPC 10577 bl nterp_get_method 10578 mov x26, x0 10579 b .Lop_invoke_interface_range_resume 10580 10581 NAME_END nterp_op_invoke_interface_range_slow_path 10582 NAME_START nterp_op_invoke_interface_slow_path 10583 mov x0, xSELF 10584 ldr x1, [sp] 10585 mov x2, xPC 10586 bl nterp_get_method 10587 mov x26, x0 10588 b .Lop_invoke_interface_resume 10589 10590 NAME_END nterp_op_invoke_interface_slow_path 10591 NAME_START nterp_op_iput_boolean_slow_path 10592 mov x0, xSELF 10593 ldr x1, [sp] 10594 mov x2, xPC 10595 .if 0 10596 mov x3, x26 10597 .else 10598 mov x3, #0 10599 .endif 10600 EXPORT_PC 10601 bl nterp_get_instance_field_offset 10602 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10603 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10604 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10605 mov w0, w0 10606 .if 0 10607 // Reload the value as it may have moved. 10608 ubfx w1, wINST, #8, #4 // w1<- A 10609 GET_VREG w26, w1 // w26 <- v[A] 10610 .endif 10611 tbz w0, #31, .Lop_iput_boolean_resume 10612 CLEAR_INSTANCE_VOLATILE_MARKER w0 10613 lsr w2, wINST, #12 // w2<- B 10614 GET_VREG w2, w2 // vB (object we're operating on) 10615 cbz w2, common_errNullObject 10616 add x3, x2, x0 10617 .if 0 10618 stlrb x26, [x3] 10619 .else 10620 POISON_HEAP_REF_IF_OBJECT 0, w26 10621 stlrb w26, [x3] 10622 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_boolean_slow_path_skip_write_barrier 10623 .endif 10624 FETCH_ADVANCE_INST 2 10625 GET_INST_OPCODE ip 10626 GOTO_OPCODE ip 10627 10628 NAME_END nterp_op_iput_boolean_slow_path 10629 NAME_START nterp_op_iput_byte_slow_path 10630 mov x0, xSELF 10631 ldr x1, [sp] 10632 mov x2, xPC 10633 .if 0 10634 mov x3, x26 10635 .else 10636 mov x3, #0 10637 .endif 10638 EXPORT_PC 10639 bl nterp_get_instance_field_offset 10640 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10641 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10642 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10643 mov w0, w0 10644 .if 0 10645 // Reload the value as it may have moved. 10646 ubfx w1, wINST, #8, #4 // w1<- A 10647 GET_VREG w26, w1 // w26 <- v[A] 10648 .endif 10649 tbz w0, #31, .Lop_iput_byte_resume 10650 CLEAR_INSTANCE_VOLATILE_MARKER w0 10651 lsr w2, wINST, #12 // w2<- B 10652 GET_VREG w2, w2 // vB (object we're operating on) 10653 cbz w2, common_errNullObject 10654 add x3, x2, x0 10655 .if 0 10656 stlrb x26, [x3] 10657 .else 10658 POISON_HEAP_REF_IF_OBJECT 0, w26 10659 stlrb w26, [x3] 10660 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_byte_slow_path_skip_write_barrier 10661 .endif 10662 FETCH_ADVANCE_INST 2 10663 GET_INST_OPCODE ip 10664 GOTO_OPCODE ip 10665 10666 NAME_END nterp_op_iput_byte_slow_path 10667 NAME_START nterp_op_iput_char_slow_path 10668 mov x0, xSELF 10669 ldr x1, [sp] 10670 mov x2, xPC 10671 .if 0 10672 mov x3, x26 10673 .else 10674 mov x3, #0 10675 .endif 10676 EXPORT_PC 10677 bl nterp_get_instance_field_offset 10678 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10679 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10680 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10681 mov w0, w0 10682 .if 0 10683 // Reload the value as it may have moved. 10684 ubfx w1, wINST, #8, #4 // w1<- A 10685 GET_VREG w26, w1 // w26 <- v[A] 10686 .endif 10687 tbz w0, #31, .Lop_iput_char_resume 10688 CLEAR_INSTANCE_VOLATILE_MARKER w0 10689 lsr w2, wINST, #12 // w2<- B 10690 GET_VREG w2, w2 // vB (object we're operating on) 10691 cbz w2, common_errNullObject 10692 add x3, x2, x0 10693 .if 0 10694 stlrh x26, [x3] 10695 .else 10696 POISON_HEAP_REF_IF_OBJECT 0, w26 10697 stlrh w26, [x3] 10698 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_char_slow_path_skip_write_barrier 10699 .endif 10700 FETCH_ADVANCE_INST 2 10701 GET_INST_OPCODE ip 10702 GOTO_OPCODE ip 10703 10704 NAME_END nterp_op_iput_char_slow_path 10705 NAME_START nterp_op_iput_object_slow_path 10706 mov x0, xSELF 10707 ldr x1, [sp] 10708 mov x2, xPC 10709 .if 1 10710 mov x3, x26 10711 .else 10712 mov x3, #0 10713 .endif 10714 EXPORT_PC 10715 bl nterp_get_instance_field_offset 10716 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10717 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10718 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10719 mov w0, w0 10720 .if 1 10721 // Reload the value as it may have moved. 10722 ubfx w1, wINST, #8, #4 // w1<- A 10723 GET_VREG w26, w1 // w26 <- v[A] 10724 .endif 10725 tbz w0, #31, .Lop_iput_object_resume 10726 CLEAR_INSTANCE_VOLATILE_MARKER w0 10727 lsr w2, wINST, #12 // w2<- B 10728 GET_VREG w2, w2 // vB (object we're operating on) 10729 cbz w2, common_errNullObject 10730 add x3, x2, x0 10731 .if 0 10732 stlr x26, [x3] 10733 .else 10734 POISON_HEAP_REF_IF_OBJECT 1, w26 10735 stlr w26, [x3] 10736 WRITE_BARRIER_IF_OBJECT 1, w26, w2, .Lop_iput_object_slow_path_skip_write_barrier 10737 .endif 10738 FETCH_ADVANCE_INST 2 10739 GET_INST_OPCODE ip 10740 GOTO_OPCODE ip 10741 10742 NAME_END nterp_op_iput_object_slow_path 10743 NAME_START nterp_op_iput_short_slow_path 10744 mov x0, xSELF 10745 ldr x1, [sp] 10746 mov x2, xPC 10747 .if 0 10748 mov x3, x26 10749 .else 10750 mov x3, #0 10751 .endif 10752 EXPORT_PC 10753 bl nterp_get_instance_field_offset 10754 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10755 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10756 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10757 mov w0, w0 10758 .if 0 10759 // Reload the value as it may have moved. 10760 ubfx w1, wINST, #8, #4 // w1<- A 10761 GET_VREG w26, w1 // w26 <- v[A] 10762 .endif 10763 tbz w0, #31, .Lop_iput_short_resume 10764 CLEAR_INSTANCE_VOLATILE_MARKER w0 10765 lsr w2, wINST, #12 // w2<- B 10766 GET_VREG w2, w2 // vB (object we're operating on) 10767 cbz w2, common_errNullObject 10768 add x3, x2, x0 10769 .if 0 10770 stlrh x26, [x3] 10771 .else 10772 POISON_HEAP_REF_IF_OBJECT 0, w26 10773 stlrh w26, [x3] 10774 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_short_slow_path_skip_write_barrier 10775 .endif 10776 FETCH_ADVANCE_INST 2 10777 GET_INST_OPCODE ip 10778 GOTO_OPCODE ip 10779 10780 NAME_END nterp_op_iput_short_slow_path 10781 NAME_START nterp_op_iput_slow_path 10782 mov x0, xSELF 10783 ldr x1, [sp] 10784 mov x2, xPC 10785 .if 0 10786 mov x3, x26 10787 .else 10788 mov x3, #0 10789 .endif 10790 EXPORT_PC 10791 bl nterp_get_instance_field_offset 10792 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10793 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10794 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10795 mov w0, w0 10796 .if 0 10797 // Reload the value as it may have moved. 10798 ubfx w1, wINST, #8, #4 // w1<- A 10799 GET_VREG w26, w1 // w26 <- v[A] 10800 .endif 10801 tbz w0, #31, .Lop_iput_resume 10802 CLEAR_INSTANCE_VOLATILE_MARKER w0 10803 lsr w2, wINST, #12 // w2<- B 10804 GET_VREG w2, w2 // vB (object we're operating on) 10805 cbz w2, common_errNullObject 10806 add x3, x2, x0 10807 .if 0 10808 stlr x26, [x3] 10809 .else 10810 POISON_HEAP_REF_IF_OBJECT 0, w26 10811 stlr w26, [x3] 10812 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_slow_path_skip_write_barrier 10813 .endif 10814 FETCH_ADVANCE_INST 2 10815 GET_INST_OPCODE ip 10816 GOTO_OPCODE ip 10817 10818 NAME_END nterp_op_iput_slow_path 10819 NAME_START nterp_op_iput_wide_slow_path 10820 mov x0, xSELF 10821 ldr x1, [sp] 10822 mov x2, xPC 10823 .if 0 10824 mov x3, x26 10825 .else 10826 mov x3, #0 10827 .endif 10828 EXPORT_PC 10829 bl nterp_get_instance_field_offset 10830 // Zero extension (nterp_get_instance_field_offset returns uint32_t) of the return value is 10831 // needed as the value is used below via wider X0 register - AARCH64 AAPCS specifies that 10832 // "... any unused bits in the register have unspecified value" (see 6.8.2, 6.9). 10833 mov w0, w0 10834 .if 0 10835 // Reload the value as it may have moved. 10836 ubfx w1, wINST, #8, #4 // w1<- A 10837 GET_VREG w26, w1 // w26 <- v[A] 10838 .endif 10839 tbz w0, #31, .Lop_iput_wide_resume 10840 CLEAR_INSTANCE_VOLATILE_MARKER w0 10841 lsr w2, wINST, #12 // w2<- B 10842 GET_VREG w2, w2 // vB (object we're operating on) 10843 cbz w2, common_errNullObject 10844 add x3, x2, x0 10845 .if 1 10846 stlr x26, [x3] 10847 .else 10848 POISON_HEAP_REF_IF_OBJECT 0, w26 10849 stlr w26, [x3] 10850 WRITE_BARRIER_IF_OBJECT 0, w26, w2, .Lop_iput_wide_slow_path_skip_write_barrier 10851 .endif 10852 FETCH_ADVANCE_INST 2 10853 GET_INST_OPCODE ip 10854 GOTO_OPCODE ip 10855 10856 NAME_END nterp_op_iput_wide_slow_path 10857 NAME_START nterp_op_sget_boolean_slow_path 10858 mov x0, xSELF 10859 ldr x1, [sp] 10860 mov x2, xPC 10861 mov x3, #0 10862 EXPORT_PC 10863 bl nterp_get_static_field 10864 tbz x0, #0, .Lop_sget_boolean_resume 10865 CLEAR_STATIC_VOLATILE_MARKER x0 10866 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 10867 lsr w2, wINST, #8 // w2 <- A 10868 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 10869 TEST_IF_MARKING .Lop_sget_boolean_slow_path_read_barrier 10870.Lop_sget_boolean_slow_path_resume_after_read_barrier: 10871 add x0, x0, x1 10872 .if 0 10873 ldar x0, [x0] 10874 SET_VREG_WIDE x0, w2 // fp[A] <- value 10875 .elseif 0 10876 ldarb w0, [x0] 10877 UNPOISON_HEAP_REF w0 10878 TEST_IF_MARKING .Lop_sget_boolean_mark_after_load 10879 SET_VREG_OBJECT w0, w2 // fp[A] <- value 10880 .else 10881 ldarb w0, [x0] 10882 10883 SET_VREG w0, w2 // fp[A] <- value 10884 .endif 10885 FETCH_ADVANCE_INST 2 10886 GET_INST_OPCODE ip 10887 GOTO_OPCODE ip 10888.Lop_sget_boolean_slow_path_read_barrier: 10889 bl art_quick_read_barrier_mark_reg00 10890 b .Lop_sget_boolean_slow_path_resume_after_read_barrier 10891 10892 NAME_END nterp_op_sget_boolean_slow_path 10893 NAME_START nterp_op_sget_byte_slow_path 10894 mov x0, xSELF 10895 ldr x1, [sp] 10896 mov x2, xPC 10897 mov x3, #0 10898 EXPORT_PC 10899 bl nterp_get_static_field 10900 tbz x0, #0, .Lop_sget_byte_resume 10901 CLEAR_STATIC_VOLATILE_MARKER x0 10902 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 10903 lsr w2, wINST, #8 // w2 <- A 10904 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 10905 TEST_IF_MARKING .Lop_sget_byte_slow_path_read_barrier 10906.Lop_sget_byte_slow_path_resume_after_read_barrier: 10907 add x0, x0, x1 10908 .if 0 10909 ldar x0, [x0] 10910 SET_VREG_WIDE x0, w2 // fp[A] <- value 10911 .elseif 0 10912 ldarb w0, [x0] 10913 UNPOISON_HEAP_REF w0 10914 TEST_IF_MARKING .Lop_sget_byte_mark_after_load 10915 SET_VREG_OBJECT w0, w2 // fp[A] <- value 10916 .else 10917 ldarb w0, [x0] 10918 sxtb w0, w0 10919 SET_VREG w0, w2 // fp[A] <- value 10920 .endif 10921 FETCH_ADVANCE_INST 2 10922 GET_INST_OPCODE ip 10923 GOTO_OPCODE ip 10924.Lop_sget_byte_slow_path_read_barrier: 10925 bl art_quick_read_barrier_mark_reg00 10926 b .Lop_sget_byte_slow_path_resume_after_read_barrier 10927 10928 NAME_END nterp_op_sget_byte_slow_path 10929 NAME_START nterp_op_sget_char_slow_path 10930 mov x0, xSELF 10931 ldr x1, [sp] 10932 mov x2, xPC 10933 mov x3, #0 10934 EXPORT_PC 10935 bl nterp_get_static_field 10936 tbz x0, #0, .Lop_sget_char_resume 10937 CLEAR_STATIC_VOLATILE_MARKER x0 10938 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 10939 lsr w2, wINST, #8 // w2 <- A 10940 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 10941 TEST_IF_MARKING .Lop_sget_char_slow_path_read_barrier 10942.Lop_sget_char_slow_path_resume_after_read_barrier: 10943 add x0, x0, x1 10944 .if 0 10945 ldar x0, [x0] 10946 SET_VREG_WIDE x0, w2 // fp[A] <- value 10947 .elseif 0 10948 ldarh w0, [x0] 10949 UNPOISON_HEAP_REF w0 10950 TEST_IF_MARKING .Lop_sget_char_mark_after_load 10951 SET_VREG_OBJECT w0, w2 // fp[A] <- value 10952 .else 10953 ldarh w0, [x0] 10954 10955 SET_VREG w0, w2 // fp[A] <- value 10956 .endif 10957 FETCH_ADVANCE_INST 2 10958 GET_INST_OPCODE ip 10959 GOTO_OPCODE ip 10960.Lop_sget_char_slow_path_read_barrier: 10961 bl art_quick_read_barrier_mark_reg00 10962 b .Lop_sget_char_slow_path_resume_after_read_barrier 10963 10964 NAME_END nterp_op_sget_char_slow_path 10965 NAME_START nterp_op_sget_object_slow_path 10966 mov x0, xSELF 10967 ldr x1, [sp] 10968 mov x2, xPC 10969 mov x3, #0 10970 EXPORT_PC 10971 bl nterp_get_static_field 10972 tbz x0, #0, .Lop_sget_object_resume 10973 CLEAR_STATIC_VOLATILE_MARKER x0 10974 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 10975 lsr w2, wINST, #8 // w2 <- A 10976 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 10977 TEST_IF_MARKING .Lop_sget_object_slow_path_read_barrier 10978.Lop_sget_object_slow_path_resume_after_read_barrier: 10979 add x0, x0, x1 10980 .if 0 10981 ldar x0, [x0] 10982 SET_VREG_WIDE x0, w2 // fp[A] <- value 10983 .elseif 1 10984 ldar w0, [x0] 10985 UNPOISON_HEAP_REF w0 10986 TEST_IF_MARKING .Lop_sget_object_mark_after_load 10987 SET_VREG_OBJECT w0, w2 // fp[A] <- value 10988 .else 10989 ldar w0, [x0] 10990 10991 SET_VREG w0, w2 // fp[A] <- value 10992 .endif 10993 FETCH_ADVANCE_INST 2 10994 GET_INST_OPCODE ip 10995 GOTO_OPCODE ip 10996.Lop_sget_object_slow_path_read_barrier: 10997 bl art_quick_read_barrier_mark_reg00 10998 b .Lop_sget_object_slow_path_resume_after_read_barrier 10999 11000 NAME_END nterp_op_sget_object_slow_path 11001 NAME_START nterp_op_sget_short_slow_path 11002 mov x0, xSELF 11003 ldr x1, [sp] 11004 mov x2, xPC 11005 mov x3, #0 11006 EXPORT_PC 11007 bl nterp_get_static_field 11008 tbz x0, #0, .Lop_sget_short_resume 11009 CLEAR_STATIC_VOLATILE_MARKER x0 11010 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 11011 lsr w2, wINST, #8 // w2 <- A 11012 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 11013 TEST_IF_MARKING .Lop_sget_short_slow_path_read_barrier 11014.Lop_sget_short_slow_path_resume_after_read_barrier: 11015 add x0, x0, x1 11016 .if 0 11017 ldar x0, [x0] 11018 SET_VREG_WIDE x0, w2 // fp[A] <- value 11019 .elseif 0 11020 ldarh w0, [x0] 11021 UNPOISON_HEAP_REF w0 11022 TEST_IF_MARKING .Lop_sget_short_mark_after_load 11023 SET_VREG_OBJECT w0, w2 // fp[A] <- value 11024 .else 11025 ldarh w0, [x0] 11026 sxth w0, w0 11027 SET_VREG w0, w2 // fp[A] <- value 11028 .endif 11029 FETCH_ADVANCE_INST 2 11030 GET_INST_OPCODE ip 11031 GOTO_OPCODE ip 11032.Lop_sget_short_slow_path_read_barrier: 11033 bl art_quick_read_barrier_mark_reg00 11034 b .Lop_sget_short_slow_path_resume_after_read_barrier 11035 11036 NAME_END nterp_op_sget_short_slow_path 11037 NAME_START nterp_op_sget_slow_path 11038 mov x0, xSELF 11039 ldr x1, [sp] 11040 mov x2, xPC 11041 mov x3, #0 11042 EXPORT_PC 11043 bl nterp_get_static_field 11044 tbz x0, #0, .Lop_sget_resume 11045 CLEAR_STATIC_VOLATILE_MARKER x0 11046 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 11047 lsr w2, wINST, #8 // w2 <- A 11048 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 11049 TEST_IF_MARKING .Lop_sget_slow_path_read_barrier 11050.Lop_sget_slow_path_resume_after_read_barrier: 11051 add x0, x0, x1 11052 .if 0 11053 ldar x0, [x0] 11054 SET_VREG_WIDE x0, w2 // fp[A] <- value 11055 .elseif 0 11056 ldar w0, [x0] 11057 UNPOISON_HEAP_REF w0 11058 TEST_IF_MARKING .Lop_sget_mark_after_load 11059 SET_VREG_OBJECT w0, w2 // fp[A] <- value 11060 .else 11061 ldar w0, [x0] 11062 11063 SET_VREG w0, w2 // fp[A] <- value 11064 .endif 11065 FETCH_ADVANCE_INST 2 11066 GET_INST_OPCODE ip 11067 GOTO_OPCODE ip 11068.Lop_sget_slow_path_read_barrier: 11069 bl art_quick_read_barrier_mark_reg00 11070 b .Lop_sget_slow_path_resume_after_read_barrier 11071 11072 NAME_END nterp_op_sget_slow_path 11073 NAME_START nterp_op_sget_wide_slow_path 11074 mov x0, xSELF 11075 ldr x1, [sp] 11076 mov x2, xPC 11077 mov x3, #0 11078 EXPORT_PC 11079 bl nterp_get_static_field 11080 tbz x0, #0, .Lop_sget_wide_resume 11081 CLEAR_STATIC_VOLATILE_MARKER x0 11082 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 11083 lsr w2, wINST, #8 // w2 <- A 11084 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 11085 TEST_IF_MARKING .Lop_sget_wide_slow_path_read_barrier 11086.Lop_sget_wide_slow_path_resume_after_read_barrier: 11087 add x0, x0, x1 11088 .if 1 11089 ldar x0, [x0] 11090 SET_VREG_WIDE x0, w2 // fp[A] <- value 11091 .elseif 0 11092 ldar w0, [x0] 11093 UNPOISON_HEAP_REF w0 11094 TEST_IF_MARKING .Lop_sget_wide_mark_after_load 11095 SET_VREG_OBJECT w0, w2 // fp[A] <- value 11096 .else 11097 ldar w0, [x0] 11098 11099 SET_VREG w0, w2 // fp[A] <- value 11100 .endif 11101 FETCH_ADVANCE_INST 2 11102 GET_INST_OPCODE ip 11103 GOTO_OPCODE ip 11104.Lop_sget_wide_slow_path_read_barrier: 11105 bl art_quick_read_barrier_mark_reg00 11106 b .Lop_sget_wide_slow_path_resume_after_read_barrier 11107 11108 NAME_END nterp_op_sget_wide_slow_path 11109 NAME_START nterp_op_sput_boolean_slow_path 11110 mov x0, xSELF 11111 ldr x1, [sp] 11112 mov x2, xPC 11113 .if 0 11114 mov x3, x26 11115 .else 11116 mov x3, #0 11117 .endif 11118 EXPORT_PC 11119 bl nterp_get_static_field 11120 .if 0 11121 // Reload the value as it may have moved. 11122 lsr w2, wINST, #8 // w2 <- A 11123 GET_VREG w26, w2 // w26 <- v[A] 11124 .endif 11125 tbz x0, #0, .Lop_sput_boolean_resume 11126 CLEAR_STATIC_VOLATILE_MARKER x0 11127 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 11128 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 11129 TEST_IF_MARKING .Lop_sput_boolean_slow_path_read_barrier 11130.Lop_sput_boolean_slow_path_resume_after_read_barrier: 11131 add x1, x0, x1 11132 .if 0 11133 stlrb x26, [x1] 11134 .else 11135 POISON_HEAP_REF_IF_OBJECT 0, w26 11136 stlrb w26, [x1] 11137 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_boolean_slow_path_skip_write_barrier 11138 .endif 11139 FETCH_ADVANCE_INST 2 11140 GET_INST_OPCODE ip 11141 GOTO_OPCODE ip 11142.Lop_sput_boolean_slow_path_read_barrier: 11143 bl art_quick_read_barrier_mark_reg00 11144 b .Lop_sput_boolean_slow_path_resume_after_read_barrier 11145 11146 NAME_END nterp_op_sput_boolean_slow_path 11147 NAME_START nterp_op_sput_byte_slow_path 11148 mov x0, xSELF 11149 ldr x1, [sp] 11150 mov x2, xPC 11151 .if 0 11152 mov x3, x26 11153 .else 11154 mov x3, #0 11155 .endif 11156 EXPORT_PC 11157 bl nterp_get_static_field 11158 .if 0 11159 // Reload the value as it may have moved. 11160 lsr w2, wINST, #8 // w2 <- A 11161 GET_VREG w26, w2 // w26 <- v[A] 11162 .endif 11163 tbz x0, #0, .Lop_sput_byte_resume 11164 CLEAR_STATIC_VOLATILE_MARKER x0 11165 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 11166 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 11167 TEST_IF_MARKING .Lop_sput_byte_slow_path_read_barrier 11168.Lop_sput_byte_slow_path_resume_after_read_barrier: 11169 add x1, x0, x1 11170 .if 0 11171 stlrb x26, [x1] 11172 .else 11173 POISON_HEAP_REF_IF_OBJECT 0, w26 11174 stlrb w26, [x1] 11175 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_byte_slow_path_skip_write_barrier 11176 .endif 11177 FETCH_ADVANCE_INST 2 11178 GET_INST_OPCODE ip 11179 GOTO_OPCODE ip 11180.Lop_sput_byte_slow_path_read_barrier: 11181 bl art_quick_read_barrier_mark_reg00 11182 b .Lop_sput_byte_slow_path_resume_after_read_barrier 11183 11184 NAME_END nterp_op_sput_byte_slow_path 11185 NAME_START nterp_op_sput_char_slow_path 11186 mov x0, xSELF 11187 ldr x1, [sp] 11188 mov x2, xPC 11189 .if 0 11190 mov x3, x26 11191 .else 11192 mov x3, #0 11193 .endif 11194 EXPORT_PC 11195 bl nterp_get_static_field 11196 .if 0 11197 // Reload the value as it may have moved. 11198 lsr w2, wINST, #8 // w2 <- A 11199 GET_VREG w26, w2 // w26 <- v[A] 11200 .endif 11201 tbz x0, #0, .Lop_sput_char_resume 11202 CLEAR_STATIC_VOLATILE_MARKER x0 11203 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 11204 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 11205 TEST_IF_MARKING .Lop_sput_char_slow_path_read_barrier 11206.Lop_sput_char_slow_path_resume_after_read_barrier: 11207 add x1, x0, x1 11208 .if 0 11209 stlrh x26, [x1] 11210 .else 11211 POISON_HEAP_REF_IF_OBJECT 0, w26 11212 stlrh w26, [x1] 11213 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_char_slow_path_skip_write_barrier 11214 .endif 11215 FETCH_ADVANCE_INST 2 11216 GET_INST_OPCODE ip 11217 GOTO_OPCODE ip 11218.Lop_sput_char_slow_path_read_barrier: 11219 bl art_quick_read_barrier_mark_reg00 11220 b .Lop_sput_char_slow_path_resume_after_read_barrier 11221 11222 NAME_END nterp_op_sput_char_slow_path 11223 NAME_START nterp_op_sput_object_slow_path 11224 mov x0, xSELF 11225 ldr x1, [sp] 11226 mov x2, xPC 11227 .if 1 11228 mov x3, x26 11229 .else 11230 mov x3, #0 11231 .endif 11232 EXPORT_PC 11233 bl nterp_get_static_field 11234 .if 1 11235 // Reload the value as it may have moved. 11236 lsr w2, wINST, #8 // w2 <- A 11237 GET_VREG w26, w2 // w26 <- v[A] 11238 .endif 11239 tbz x0, #0, .Lop_sput_object_resume 11240 CLEAR_STATIC_VOLATILE_MARKER x0 11241 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 11242 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 11243 TEST_IF_MARKING .Lop_sput_object_slow_path_read_barrier 11244.Lop_sput_object_slow_path_resume_after_read_barrier: 11245 add x1, x0, x1 11246 .if 0 11247 stlr x26, [x1] 11248 .else 11249 POISON_HEAP_REF_IF_OBJECT 1, w26 11250 stlr w26, [x1] 11251 WRITE_BARRIER_IF_OBJECT 1, w26, w0, .Lop_sput_object_slow_path_skip_write_barrier 11252 .endif 11253 FETCH_ADVANCE_INST 2 11254 GET_INST_OPCODE ip 11255 GOTO_OPCODE ip 11256.Lop_sput_object_slow_path_read_barrier: 11257 bl art_quick_read_barrier_mark_reg00 11258 b .Lop_sput_object_slow_path_resume_after_read_barrier 11259 11260 NAME_END nterp_op_sput_object_slow_path 11261 NAME_START nterp_op_sput_short_slow_path 11262 mov x0, xSELF 11263 ldr x1, [sp] 11264 mov x2, xPC 11265 .if 0 11266 mov x3, x26 11267 .else 11268 mov x3, #0 11269 .endif 11270 EXPORT_PC 11271 bl nterp_get_static_field 11272 .if 0 11273 // Reload the value as it may have moved. 11274 lsr w2, wINST, #8 // w2 <- A 11275 GET_VREG w26, w2 // w26 <- v[A] 11276 .endif 11277 tbz x0, #0, .Lop_sput_short_resume 11278 CLEAR_STATIC_VOLATILE_MARKER x0 11279 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 11280 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 11281 TEST_IF_MARKING .Lop_sput_short_slow_path_read_barrier 11282.Lop_sput_short_slow_path_resume_after_read_barrier: 11283 add x1, x0, x1 11284 .if 0 11285 stlrh x26, [x1] 11286 .else 11287 POISON_HEAP_REF_IF_OBJECT 0, w26 11288 stlrh w26, [x1] 11289 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_short_slow_path_skip_write_barrier 11290 .endif 11291 FETCH_ADVANCE_INST 2 11292 GET_INST_OPCODE ip 11293 GOTO_OPCODE ip 11294.Lop_sput_short_slow_path_read_barrier: 11295 bl art_quick_read_barrier_mark_reg00 11296 b .Lop_sput_short_slow_path_resume_after_read_barrier 11297 11298 NAME_END nterp_op_sput_short_slow_path 11299 NAME_START nterp_op_sput_slow_path 11300 mov x0, xSELF 11301 ldr x1, [sp] 11302 mov x2, xPC 11303 .if 0 11304 mov x3, x26 11305 .else 11306 mov x3, #0 11307 .endif 11308 EXPORT_PC 11309 bl nterp_get_static_field 11310 .if 0 11311 // Reload the value as it may have moved. 11312 lsr w2, wINST, #8 // w2 <- A 11313 GET_VREG w26, w2 // w26 <- v[A] 11314 .endif 11315 tbz x0, #0, .Lop_sput_resume 11316 CLEAR_STATIC_VOLATILE_MARKER x0 11317 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 11318 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 11319 TEST_IF_MARKING .Lop_sput_slow_path_read_barrier 11320.Lop_sput_slow_path_resume_after_read_barrier: 11321 add x1, x0, x1 11322 .if 0 11323 stlr x26, [x1] 11324 .else 11325 POISON_HEAP_REF_IF_OBJECT 0, w26 11326 stlr w26, [x1] 11327 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_slow_path_skip_write_barrier 11328 .endif 11329 FETCH_ADVANCE_INST 2 11330 GET_INST_OPCODE ip 11331 GOTO_OPCODE ip 11332.Lop_sput_slow_path_read_barrier: 11333 bl art_quick_read_barrier_mark_reg00 11334 b .Lop_sput_slow_path_resume_after_read_barrier 11335 11336 NAME_END nterp_op_sput_slow_path 11337 NAME_START nterp_op_sput_wide_slow_path 11338 mov x0, xSELF 11339 ldr x1, [sp] 11340 mov x2, xPC 11341 .if 0 11342 mov x3, x26 11343 .else 11344 mov x3, #0 11345 .endif 11346 EXPORT_PC 11347 bl nterp_get_static_field 11348 .if 0 11349 // Reload the value as it may have moved. 11350 lsr w2, wINST, #8 // w2 <- A 11351 GET_VREG w26, w2 // w26 <- v[A] 11352 .endif 11353 tbz x0, #0, .Lop_sput_wide_resume 11354 CLEAR_STATIC_VOLATILE_MARKER x0 11355 ldr w1, [x0, #ART_FIELD_OFFSET_OFFSET] 11356 ldr w0, [x0, #ART_FIELD_DECLARING_CLASS_OFFSET] 11357 TEST_IF_MARKING .Lop_sput_wide_slow_path_read_barrier 11358.Lop_sput_wide_slow_path_resume_after_read_barrier: 11359 add x1, x0, x1 11360 .if 1 11361 stlr x26, [x1] 11362 .else 11363 POISON_HEAP_REF_IF_OBJECT 0, w26 11364 stlr w26, [x1] 11365 WRITE_BARRIER_IF_OBJECT 0, w26, w0, .Lop_sput_wide_slow_path_skip_write_barrier 11366 .endif 11367 FETCH_ADVANCE_INST 2 11368 GET_INST_OPCODE ip 11369 GOTO_OPCODE ip 11370.Lop_sput_wide_slow_path_read_barrier: 11371 bl art_quick_read_barrier_mark_reg00 11372 b .Lop_sput_wide_slow_path_resume_after_read_barrier 11373 11374 NAME_END nterp_op_sput_wide_slow_path 11375/* 11376 * =========================================================================== 11377 * Common subroutines and data 11378 * =========================================================================== 11379 */ 11380 11381 .text 11382 .align 2 11383 11384// Enclose all code below in a symbol (which gets printed in backtraces). 11385NAME_START nterp_helper 11386 11387// Note: mterp also uses the common_* names below for helpers, but that's OK 11388// as the assembler compiled each interpreter separately. 11389common_errDivideByZero: 11390 EXPORT_PC 11391 bl art_quick_throw_div_zero 11392 11393// Expect index in w1, length in w3. 11394common_errArrayIndex: 11395 EXPORT_PC 11396 mov x0, x1 11397 mov x1, x3 11398 bl art_quick_throw_array_bounds 11399 11400common_errNullObject: 11401 EXPORT_PC 11402 bl art_quick_throw_null_pointer_exception 11403 11404NterpCommonInvokeStatic: 11405 COMMON_INVOKE_NON_RANGE is_static=1, suffix="invokeStatic" 11406 11407NterpCommonInvokeStaticRange: 11408 COMMON_INVOKE_RANGE is_static=1, suffix="invokeStatic" 11409 11410NterpCommonInvokeInstance: 11411 COMMON_INVOKE_NON_RANGE suffix="invokeInstance" 11412 11413NterpCommonInvokeInstanceRange: 11414 COMMON_INVOKE_RANGE suffix="invokeInstance" 11415 11416NterpCommonInvokeInterface: 11417 COMMON_INVOKE_NON_RANGE is_interface=1, suffix="invokeInterface" 11418 11419NterpCommonInvokeInterfaceRange: 11420 COMMON_INVOKE_RANGE is_interface=1, suffix="invokeInterface" 11421 11422NterpCommonInvokePolymorphic: 11423 COMMON_INVOKE_NON_RANGE is_polymorphic=1, suffix="invokePolymorphic" 11424 11425NterpCommonInvokePolymorphicRange: 11426 COMMON_INVOKE_RANGE is_polymorphic=1, suffix="invokePolymorphic" 11427 11428NterpCommonInvokeCustom: 11429 COMMON_INVOKE_NON_RANGE is_static=1, is_custom=1, suffix="invokeCustom" 11430 11431NterpCommonInvokeCustomRange: 11432 COMMON_INVOKE_RANGE is_static=1, is_custom=1, suffix="invokeCustom" 11433 11434NterpHandleStringInit: 11435 COMMON_INVOKE_NON_RANGE is_string_init=1, suffix="stringInit" 11436 11437NterpHandleStringInitRange: 11438 COMMON_INVOKE_RANGE is_string_init=1, suffix="stringInit" 11439 11440NterpHandleHotnessOverflow: 11441 CHECK_AND_UPDATE_SHARED_MEMORY_METHOD if_hot=1f, if_not_hot=5f 114421: 11443 mov x1, xPC 11444 mov x2, xFP 11445 bl nterp_hot_method 11446 cbnz x0, 3f 114472: 11448 FETCH wINST, 0 // load wINST 11449 GET_INST_OPCODE ip // extract opcode from wINST 11450 GOTO_OPCODE ip // jump to next instruction 114513: 11452 // Drop the current frame. 11453 ldr ip, [xREFS, #-8] 11454 mov sp, ip 11455 .cfi_def_cfa sp, CALLEE_SAVES_SIZE 11456 11457 // The transition frame of type SaveAllCalleeSaves saves x19 and x20, 11458 // but not managed ABI. So we need to restore callee-saves of the nterp frame, 11459 // and save managed ABI callee saves, which will be restored by the callee upon 11460 // return. 11461 RESTORE_ALL_CALLEE_SAVES 11462 INCREASE_FRAME ((CALLEE_SAVES_SIZE) - 16) 11463 11464 // FP callee-saves 11465 stp d8, d9, [sp, #0] 11466 stp d10, d11, [sp, #16] 11467 stp d12, d13, [sp, #32] 11468 stp d14, d15, [sp, #48] 11469 11470 // GP callee-saves. 11471 SAVE_TWO_REGS x21, x22, 64 11472 SAVE_TWO_REGS x23, x24, 80 11473 SAVE_TWO_REGS x25, x26, 96 11474 SAVE_TWO_REGS x27, x28, 112 11475 SAVE_TWO_REGS x29, lr, 128 11476 11477 // Setup the new frame 11478 ldr x1, [x0, #OSR_DATA_FRAME_SIZE] 11479 // Given stack size contains all callee saved registers, remove them. 11480 sub x1, x1, #(CALLEE_SAVES_SIZE - 16) 11481 11482 // We know x1 cannot be 0, as it at least contains the ArtMethod. 11483 11484 // Remember CFA in a callee-save register. 11485 mov xINST, sp 11486 .cfi_def_cfa_register xINST 11487 11488 sub sp, sp, x1 11489 11490 add x2, x0, #OSR_DATA_MEMORY 114914: 11492 sub x1, x1, #8 11493 ldr ip, [x2, x1] 11494 str ip, [sp, x1] 11495 cbnz x1, 4b 11496 11497 // Fetch the native PC to jump to and save it in a callee-save register. 11498 ldr xFP, [x0, #OSR_DATA_NATIVE_PC] 11499 11500 // Free the memory holding OSR Data. 11501 bl free 11502 11503 // Jump to the compiled code. 11504 br xFP 115055: 11506 DO_SUSPEND_CHECK continue_label=2b 11507 b 2b 11508 11509// This is the logical end of ExecuteNterpImpl, where the frame info applies. 11510// EndExecuteNterpImpl includes the methods below as we want the runtime to 11511// see them as part of the Nterp PCs. 11512.cfi_endproc 11513 11514nterp_to_nterp_static_non_range: 11515 .cfi_startproc 11516 SETUP_STACK_FOR_INVOKE 11517 SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=1, is_string_init=0 11518 .cfi_endproc 11519 11520nterp_to_nterp_string_init_non_range: 11521 .cfi_startproc 11522 SETUP_STACK_FOR_INVOKE 11523 SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1 11524 .cfi_endproc 11525 11526nterp_to_nterp_instance_non_range: 11527 .cfi_startproc 11528 SETUP_STACK_FOR_INVOKE 11529 SETUP_NON_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=0 11530 .cfi_endproc 11531 11532nterp_to_nterp_static_range: 11533 .cfi_startproc 11534 SETUP_STACK_FOR_INVOKE 11535 SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=1 11536 .cfi_endproc 11537 11538nterp_to_nterp_instance_range: 11539 .cfi_startproc 11540 SETUP_STACK_FOR_INVOKE 11541 SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0 11542 .cfi_endproc 11543 11544nterp_to_nterp_string_init_range: 11545 .cfi_startproc 11546 SETUP_STACK_FOR_INVOKE 11547 SETUP_RANGE_ARGUMENTS_AND_EXECUTE is_static=0, is_string_init=1 11548 .cfi_endproc 11549 11550NAME_END nterp_helper 11551 11552// This is the end of PCs contained by the OatQuickMethodHeader created for the interpreter 11553// entry point. 11554 .type EndExecuteNterpImpl, #function 11555 .hidden EndExecuteNterpImpl 11556 .global EndExecuteNterpImpl 11557EndExecuteNterpImpl: 11558 11559// Entrypoints into runtime. 11560NTERP_TRAMPOLINE nterp_get_static_field, NterpGetStaticField 11561NTERP_TRAMPOLINE nterp_get_instance_field_offset, NterpGetInstanceFieldOffset 11562NTERP_TRAMPOLINE nterp_filled_new_array, NterpFilledNewArray 11563NTERP_TRAMPOLINE nterp_filled_new_array_range, NterpFilledNewArrayRange 11564NTERP_TRAMPOLINE nterp_get_class, NterpGetClass 11565NTERP_TRAMPOLINE nterp_allocate_object, NterpAllocateObject 11566NTERP_TRAMPOLINE nterp_get_method, NterpGetMethod 11567NTERP_TRAMPOLINE nterp_hot_method, NterpHotMethod 11568NTERP_TRAMPOLINE nterp_load_object, NterpLoadObject 11569 11570ENTRY nterp_deliver_pending_exception 11571 DELIVER_PENDING_EXCEPTION 11572END nterp_deliver_pending_exception 11573 11574// gen_mterp.py will inline the following definitions 11575// within [ExecuteNterpImpl, EndExecuteNterpImpl). 11576