From 3b0b4b9d09baae7234fc26b7970b3ec55560735e Mon Sep 17 00:00:00 2001 From: Bill Buzbee Date: Tue, 2 Feb 2016 13:45:36 +0000 Subject: [PATCH] Revert "Revert "ART: Mterp for arm64"" Looks like some of our assemblers disagree on valid arm64 assembly syntax Force use of clang for art runtime. In a subsequent CL, will use form that both gcc and clang accept. This reverts commit 43f3fb960bce978df699c8a68a972be2a0d0d221. Change-Id: Ice83072171ab502c43d492e2238b446c4814ea67 --- runtime/Android.mk | 4 +- runtime/interpreter/interpreter.cc | 4 +- runtime/interpreter/mterp/arm64/alt_stub.S | 12 + runtime/interpreter/mterp/arm64/bincmp.S | 37 + runtime/interpreter/mterp/arm64/binop.S | 33 + runtime/interpreter/mterp/arm64/binop2addr.S | 30 + runtime/interpreter/mterp/arm64/binopLit16.S | 28 + runtime/interpreter/mterp/arm64/binopLit8.S | 30 + runtime/interpreter/mterp/arm64/binopWide.S | 30 + runtime/interpreter/mterp/arm64/binopWide2addr.S | 29 + runtime/interpreter/mterp/arm64/entry.S | 63 + runtime/interpreter/mterp/arm64/fallback.S | 3 + runtime/interpreter/mterp/arm64/fbinop.S | 19 + runtime/interpreter/mterp/arm64/fbinop2addr.S | 18 + runtime/interpreter/mterp/arm64/fcmp.S | 20 + runtime/interpreter/mterp/arm64/footer.S | 170 + runtime/interpreter/mterp/arm64/funopNarrow.S | 18 + runtime/interpreter/mterp/arm64/funopNarrower.S | 17 + runtime/interpreter/mterp/arm64/funopWide.S | 17 + runtime/interpreter/mterp/arm64/funopWider.S | 17 + runtime/interpreter/mterp/arm64/header.S | 288 + runtime/interpreter/mterp/arm64/invoke.S | 19 + runtime/interpreter/mterp/arm64/op_add_double.S | 1 + .../interpreter/mterp/arm64/op_add_double_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_add_float.S | 1 + .../interpreter/mterp/arm64/op_add_float_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_add_int.S | 1 + runtime/interpreter/mterp/arm64/op_add_int_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_add_int_lit16.S | 1 + runtime/interpreter/mterp/arm64/op_add_int_lit8.S | 1 + runtime/interpreter/mterp/arm64/op_add_long.S | 1 + .../interpreter/mterp/arm64/op_add_long_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_aget.S | 28 + runtime/interpreter/mterp/arm64/op_aget_boolean.S | 1 + runtime/interpreter/mterp/arm64/op_aget_byte.S | 1 + runtime/interpreter/mterp/arm64/op_aget_char.S | 1 + runtime/interpreter/mterp/arm64/op_aget_object.S | 20 + runtime/interpreter/mterp/arm64/op_aget_short.S | 1 + runtime/interpreter/mterp/arm64/op_aget_wide.S | 21 + runtime/interpreter/mterp/arm64/op_and_int.S | 1 + runtime/interpreter/mterp/arm64/op_and_int_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_and_int_lit16.S | 1 + runtime/interpreter/mterp/arm64/op_and_int_lit8.S | 1 + runtime/interpreter/mterp/arm64/op_and_long.S | 1 + .../interpreter/mterp/arm64/op_and_long_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_aput.S | 28 + runtime/interpreter/mterp/arm64/op_aput_boolean.S | 1 + runtime/interpreter/mterp/arm64/op_aput_byte.S | 1 + runtime/interpreter/mterp/arm64/op_aput_char.S | 1 + runtime/interpreter/mterp/arm64/op_aput_object.S | 13 + runtime/interpreter/mterp/arm64/op_aput_short.S | 1 + runtime/interpreter/mterp/arm64/op_aput_wide.S | 21 + runtime/interpreter/mterp/arm64/op_array_length.S | 12 + runtime/interpreter/mterp/arm64/op_check_cast.S | 16 + runtime/interpreter/mterp/arm64/op_cmp_long.S | 13 + runtime/interpreter/mterp/arm64/op_cmpg_double.S | 1 + runtime/interpreter/mterp/arm64/op_cmpg_float.S | 1 + runtime/interpreter/mterp/arm64/op_cmpl_double.S | 1 + runtime/interpreter/mterp/arm64/op_cmpl_float.S | 1 + runtime/interpreter/mterp/arm64/op_const.S | 9 + runtime/interpreter/mterp/arm64/op_const_16.S | 7 + runtime/interpreter/mterp/arm64/op_const_4.S | 8 + runtime/interpreter/mterp/arm64/op_const_class.S | 12 + runtime/interpreter/mterp/arm64/op_const_high16.S | 8 + runtime/interpreter/mterp/arm64/op_const_string.S | 12 + .../mterp/arm64/op_const_string_jumbo.S | 14 + runtime/interpreter/mterp/arm64/op_const_wide.S | 13 + runtime/interpreter/mterp/arm64/op_const_wide_16.S | 8 + runtime/interpreter/mterp/arm64/op_const_wide_32.S | 10 + .../interpreter/mterp/arm64/op_const_wide_high16.S | 8 + runtime/interpreter/mterp/arm64/op_div_double.S | 1 + .../interpreter/mterp/arm64/op_div_double_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_div_float.S | 1 + .../interpreter/mterp/arm64/op_div_float_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_div_int.S | 1 + runtime/interpreter/mterp/arm64/op_div_int_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_div_int_lit16.S | 1 + runtime/interpreter/mterp/arm64/op_div_int_lit8.S | 1 + runtime/interpreter/mterp/arm64/op_div_long.S | 1 + .../interpreter/mterp/arm64/op_div_long_2addr.S | 1 + .../interpreter/mterp/arm64/op_double_to_float.S | 1 + runtime/interpreter/mterp/arm64/op_double_to_int.S | 1 + .../interpreter/mterp/arm64/op_double_to_long.S | 1 + .../interpreter/mterp/arm64/op_fill_array_data.S | 13 + .../interpreter/mterp/arm64/op_filled_new_array.S | 18 + .../mterp/arm64/op_filled_new_array_range.S | 1 + .../interpreter/mterp/arm64/op_float_to_double.S | 1 + runtime/interpreter/mterp/arm64/op_float_to_int.S | 1 + runtime/interpreter/mterp/arm64/op_float_to_long.S | 1 + runtime/interpreter/mterp/arm64/op_goto.S | 28 + runtime/interpreter/mterp/arm64/op_goto_16.S | 23 + runtime/interpreter/mterp/arm64/op_goto_32.S | 32 + runtime/interpreter/mterp/arm64/op_if_eq.S | 1 + runtime/interpreter/mterp/arm64/op_if_eqz.S | 1 + runtime/interpreter/mterp/arm64/op_if_ge.S | 1 + runtime/interpreter/mterp/arm64/op_if_gez.S | 1 + runtime/interpreter/mterp/arm64/op_if_gt.S | 1 + runtime/interpreter/mterp/arm64/op_if_gtz.S | 1 + runtime/interpreter/mterp/arm64/op_if_le.S | 1 + runtime/interpreter/mterp/arm64/op_if_lez.S | 1 + runtime/interpreter/mterp/arm64/op_if_lt.S | 1 + runtime/interpreter/mterp/arm64/op_if_ltz.S | 1 + runtime/interpreter/mterp/arm64/op_if_ne.S | 1 + runtime/interpreter/mterp/arm64/op_if_nez.S | 1 + runtime/interpreter/mterp/arm64/op_iget.S | 25 + runtime/interpreter/mterp/arm64/op_iget_boolean.S | 1 + .../mterp/arm64/op_iget_boolean_quick.S | 1 + runtime/interpreter/mterp/arm64/op_iget_byte.S | 1 + .../interpreter/mterp/arm64/op_iget_byte_quick.S | 1 + runtime/interpreter/mterp/arm64/op_iget_char.S | 1 + .../interpreter/mterp/arm64/op_iget_char_quick.S | 1 + runtime/interpreter/mterp/arm64/op_iget_object.S | 1 + .../interpreter/mterp/arm64/op_iget_object_quick.S | 15 + runtime/interpreter/mterp/arm64/op_iget_quick.S | 15 + runtime/interpreter/mterp/arm64/op_iget_short.S | 1 + .../interpreter/mterp/arm64/op_iget_short_quick.S | 1 + runtime/interpreter/mterp/arm64/op_iget_wide.S | 21 + .../interpreter/mterp/arm64/op_iget_wide_quick.S | 12 + runtime/interpreter/mterp/arm64/op_instance_of.S | 23 + runtime/interpreter/mterp/arm64/op_int_to_byte.S | 1 + runtime/interpreter/mterp/arm64/op_int_to_char.S | 1 + runtime/interpreter/mterp/arm64/op_int_to_double.S | 1 + runtime/interpreter/mterp/arm64/op_int_to_float.S | 1 + runtime/interpreter/mterp/arm64/op_int_to_long.S | 1 + runtime/interpreter/mterp/arm64/op_int_to_short.S | 1 + runtime/interpreter/mterp/arm64/op_invoke_direct.S | 1 + .../mterp/arm64/op_invoke_direct_range.S | 1 + .../interpreter/mterp/arm64/op_invoke_interface.S | 8 + .../mterp/arm64/op_invoke_interface_range.S | 1 + runtime/interpreter/mterp/arm64/op_invoke_static.S | 2 + .../mterp/arm64/op_invoke_static_range.S | 1 + runtime/interpreter/mterp/arm64/op_invoke_super.S | 8 + .../mterp/arm64/op_invoke_super_range.S | 1 + .../interpreter/mterp/arm64/op_invoke_virtual.S | 8 + .../mterp/arm64/op_invoke_virtual_quick.S | 1 + .../mterp/arm64/op_invoke_virtual_range.S | 1 + .../mterp/arm64/op_invoke_virtual_range_quick.S | 1 + runtime/interpreter/mterp/arm64/op_iput.S | 21 + runtime/interpreter/mterp/arm64/op_iput_boolean.S | 1 + .../mterp/arm64/op_iput_boolean_quick.S | 1 + runtime/interpreter/mterp/arm64/op_iput_byte.S | 1 + .../interpreter/mterp/arm64/op_iput_byte_quick.S | 1 + runtime/interpreter/mterp/arm64/op_iput_char.S | 1 + .../interpreter/mterp/arm64/op_iput_char_quick.S | 1 + runtime/interpreter/mterp/arm64/op_iput_object.S | 10 + .../interpreter/mterp/arm64/op_iput_object_quick.S | 9 + runtime/interpreter/mterp/arm64/op_iput_quick.S | 14 + runtime/interpreter/mterp/arm64/op_iput_short.S | 1 + .../interpreter/mterp/arm64/op_iput_short_quick.S | 1 + runtime/interpreter/mterp/arm64/op_iput_wide.S | 15 + .../interpreter/mterp/arm64/op_iput_wide_quick.S | 13 + .../interpreter/mterp/arm64/op_long_to_double.S | 1 + runtime/interpreter/mterp/arm64/op_long_to_float.S | 1 + runtime/interpreter/mterp/arm64/op_long_to_int.S | 1 + runtime/interpreter/mterp/arm64/op_monitor_enter.S | 13 + runtime/interpreter/mterp/arm64/op_monitor_exit.S | 17 + runtime/interpreter/mterp/arm64/op_move.S | 14 + runtime/interpreter/mterp/arm64/op_move_16.S | 14 + .../interpreter/mterp/arm64/op_move_exception.S | 9 + runtime/interpreter/mterp/arm64/op_move_from16.S | 14 + runtime/interpreter/mterp/arm64/op_move_object.S | 1 + .../interpreter/mterp/arm64/op_move_object_16.S | 1 + .../mterp/arm64/op_move_object_from16.S | 1 + runtime/interpreter/mterp/arm64/op_move_result.S | 14 + .../mterp/arm64/op_move_result_object.S | 1 + .../interpreter/mterp/arm64/op_move_result_wide.S | 9 + runtime/interpreter/mterp/arm64/op_move_wide.S | 9 + runtime/interpreter/mterp/arm64/op_move_wide_16.S | 9 + .../interpreter/mterp/arm64/op_move_wide_from16.S | 9 + runtime/interpreter/mterp/arm64/op_mul_double.S | 1 + .../interpreter/mterp/arm64/op_mul_double_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_mul_float.S | 1 + .../interpreter/mterp/arm64/op_mul_float_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_mul_int.S | 2 + runtime/interpreter/mterp/arm64/op_mul_int_2addr.S | 2 + runtime/interpreter/mterp/arm64/op_mul_int_lit16.S | 2 + runtime/interpreter/mterp/arm64/op_mul_int_lit8.S | 2 + runtime/interpreter/mterp/arm64/op_mul_long.S | 1 + .../interpreter/mterp/arm64/op_mul_long_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_neg_double.S | 1 + runtime/interpreter/mterp/arm64/op_neg_float.S | 1 + runtime/interpreter/mterp/arm64/op_neg_int.S | 1 + runtime/interpreter/mterp/arm64/op_neg_long.S | 1 + runtime/interpreter/mterp/arm64/op_new_array.S | 18 + runtime/interpreter/mterp/arm64/op_new_instance.S | 13 + runtime/interpreter/mterp/arm64/op_nop.S | 3 + runtime/interpreter/mterp/arm64/op_not_int.S | 1 + runtime/interpreter/mterp/arm64/op_not_long.S | 1 + runtime/interpreter/mterp/arm64/op_or_int.S | 1 + runtime/interpreter/mterp/arm64/op_or_int_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_or_int_lit16.S | 1 + runtime/interpreter/mterp/arm64/op_or_int_lit8.S | 1 + runtime/interpreter/mterp/arm64/op_or_long.S | 1 + runtime/interpreter/mterp/arm64/op_or_long_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_packed_switch.S | 39 + runtime/interpreter/mterp/arm64/op_rem_double.S | 13 + .../interpreter/mterp/arm64/op_rem_double_2addr.S | 12 + runtime/interpreter/mterp/arm64/op_rem_float.S | 2 + .../interpreter/mterp/arm64/op_rem_float_2addr.S | 13 + runtime/interpreter/mterp/arm64/op_rem_int.S | 1 + runtime/interpreter/mterp/arm64/op_rem_int_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_rem_int_lit16.S | 1 + runtime/interpreter/mterp/arm64/op_rem_int_lit8.S | 1 + runtime/interpreter/mterp/arm64/op_rem_long.S | 1 + .../interpreter/mterp/arm64/op_rem_long_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_return.S | 19 + runtime/interpreter/mterp/arm64/op_return_object.S | 1 + runtime/interpreter/mterp/arm64/op_return_void.S | 12 + .../mterp/arm64/op_return_void_no_barrier.S | 10 + runtime/interpreter/mterp/arm64/op_return_wide.S | 18 + runtime/interpreter/mterp/arm64/op_rsub_int.S | 2 + runtime/interpreter/mterp/arm64/op_rsub_int_lit8.S | 1 + runtime/interpreter/mterp/arm64/op_sget.S | 27 + runtime/interpreter/mterp/arm64/op_sget_boolean.S | 1 + runtime/interpreter/mterp/arm64/op_sget_byte.S | 1 + runtime/interpreter/mterp/arm64/op_sget_char.S | 1 + runtime/interpreter/mterp/arm64/op_sget_object.S | 1 + runtime/interpreter/mterp/arm64/op_sget_short.S | 1 + runtime/interpreter/mterp/arm64/op_sget_wide.S | 19 + runtime/interpreter/mterp/arm64/op_shl_int.S | 1 + runtime/interpreter/mterp/arm64/op_shl_int_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_shl_int_lit8.S | 1 + runtime/interpreter/mterp/arm64/op_shl_long.S | 1 + .../interpreter/mterp/arm64/op_shl_long_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_shr_int.S | 1 + runtime/interpreter/mterp/arm64/op_shr_int_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_shr_int_lit8.S | 1 + runtime/interpreter/mterp/arm64/op_shr_long.S | 1 + .../interpreter/mterp/arm64/op_shr_long_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_sparse_switch.S | 1 + runtime/interpreter/mterp/arm64/op_sput.S | 19 + runtime/interpreter/mterp/arm64/op_sput_boolean.S | 1 + runtime/interpreter/mterp/arm64/op_sput_byte.S | 1 + runtime/interpreter/mterp/arm64/op_sput_char.S | 1 + runtime/interpreter/mterp/arm64/op_sput_object.S | 10 + runtime/interpreter/mterp/arm64/op_sput_short.S | 1 + runtime/interpreter/mterp/arm64/op_sput_wide.S | 18 + runtime/interpreter/mterp/arm64/op_sub_double.S | 1 + .../interpreter/mterp/arm64/op_sub_double_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_sub_float.S | 1 + .../interpreter/mterp/arm64/op_sub_float_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_sub_int.S | 1 + runtime/interpreter/mterp/arm64/op_sub_int_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_sub_long.S | 1 + .../interpreter/mterp/arm64/op_sub_long_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_throw.S | 10 + runtime/interpreter/mterp/arm64/op_unused_3e.S | 1 + runtime/interpreter/mterp/arm64/op_unused_3f.S | 1 + runtime/interpreter/mterp/arm64/op_unused_40.S | 1 + runtime/interpreter/mterp/arm64/op_unused_41.S | 1 + runtime/interpreter/mterp/arm64/op_unused_42.S | 1 + runtime/interpreter/mterp/arm64/op_unused_43.S | 1 + runtime/interpreter/mterp/arm64/op_unused_73.S | 1 + runtime/interpreter/mterp/arm64/op_unused_79.S | 1 + runtime/interpreter/mterp/arm64/op_unused_7a.S | 1 + runtime/interpreter/mterp/arm64/op_unused_f3.S | 1 + runtime/interpreter/mterp/arm64/op_unused_f4.S | 1 + runtime/interpreter/mterp/arm64/op_unused_f5.S | 1 + runtime/interpreter/mterp/arm64/op_unused_f6.S | 1 + runtime/interpreter/mterp/arm64/op_unused_f7.S | 1 + runtime/interpreter/mterp/arm64/op_unused_f8.S | 1 + runtime/interpreter/mterp/arm64/op_unused_f9.S | 1 + runtime/interpreter/mterp/arm64/op_unused_fa.S | 1 + runtime/interpreter/mterp/arm64/op_unused_fb.S | 1 + runtime/interpreter/mterp/arm64/op_unused_fc.S | 1 + runtime/interpreter/mterp/arm64/op_unused_fd.S | 1 + runtime/interpreter/mterp/arm64/op_unused_fe.S | 1 + runtime/interpreter/mterp/arm64/op_unused_ff.S | 1 + runtime/interpreter/mterp/arm64/op_ushr_int.S | 1 + .../interpreter/mterp/arm64/op_ushr_int_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_ushr_int_lit8.S | 1 + runtime/interpreter/mterp/arm64/op_ushr_long.S | 1 + .../interpreter/mterp/arm64/op_ushr_long_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_xor_int.S | 1 + runtime/interpreter/mterp/arm64/op_xor_int_2addr.S | 1 + runtime/interpreter/mterp/arm64/op_xor_int_lit16.S | 1 + runtime/interpreter/mterp/arm64/op_xor_int_lit8.S | 1 + runtime/interpreter/mterp/arm64/op_xor_long.S | 1 + .../interpreter/mterp/arm64/op_xor_long_2addr.S | 1 + runtime/interpreter/mterp/arm64/shiftWide.S | 20 + runtime/interpreter/mterp/arm64/shiftWide2addr.S | 16 + runtime/interpreter/mterp/arm64/unop.S | 20 + runtime/interpreter/mterp/arm64/unopWide.S | 18 + runtime/interpreter/mterp/arm64/unused.S | 4 + runtime/interpreter/mterp/arm64/zcmp.S | 33 + runtime/interpreter/mterp/config_arm64 | 513 +- runtime/interpreter/mterp/out/mterp_arm64.S | 11726 +++++++++++++++++++ runtime/interpreter/mterp/rebuild.sh | 2 +- 288 files changed, 14210 insertions(+), 260 deletions(-) create mode 100644 runtime/interpreter/mterp/arm64/alt_stub.S create mode 100644 runtime/interpreter/mterp/arm64/bincmp.S create mode 100644 runtime/interpreter/mterp/arm64/binop.S create mode 100644 runtime/interpreter/mterp/arm64/binop2addr.S create mode 100644 runtime/interpreter/mterp/arm64/binopLit16.S create mode 100644 runtime/interpreter/mterp/arm64/binopLit8.S create mode 100644 runtime/interpreter/mterp/arm64/binopWide.S create mode 100644 runtime/interpreter/mterp/arm64/binopWide2addr.S create mode 100644 runtime/interpreter/mterp/arm64/entry.S create mode 100644 runtime/interpreter/mterp/arm64/fallback.S create mode 100644 runtime/interpreter/mterp/arm64/fbinop.S create mode 100644 runtime/interpreter/mterp/arm64/fbinop2addr.S create mode 100644 runtime/interpreter/mterp/arm64/fcmp.S create mode 100644 runtime/interpreter/mterp/arm64/footer.S create mode 100644 runtime/interpreter/mterp/arm64/funopNarrow.S create mode 100644 runtime/interpreter/mterp/arm64/funopNarrower.S create mode 100644 runtime/interpreter/mterp/arm64/funopWide.S create mode 100644 runtime/interpreter/mterp/arm64/funopWider.S create mode 100644 runtime/interpreter/mterp/arm64/header.S create mode 100644 runtime/interpreter/mterp/arm64/invoke.S create mode 100644 runtime/interpreter/mterp/arm64/op_add_double.S create mode 100644 runtime/interpreter/mterp/arm64/op_add_double_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_add_float.S create mode 100644 runtime/interpreter/mterp/arm64/op_add_float_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_add_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_add_int_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_add_int_lit16.S create mode 100644 runtime/interpreter/mterp/arm64/op_add_int_lit8.S create mode 100644 runtime/interpreter/mterp/arm64/op_add_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_add_long_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_aget.S create mode 100644 runtime/interpreter/mterp/arm64/op_aget_boolean.S create mode 100644 runtime/interpreter/mterp/arm64/op_aget_byte.S create mode 100644 runtime/interpreter/mterp/arm64/op_aget_char.S create mode 100644 runtime/interpreter/mterp/arm64/op_aget_object.S create mode 100644 runtime/interpreter/mterp/arm64/op_aget_short.S create mode 100644 runtime/interpreter/mterp/arm64/op_aget_wide.S create mode 100644 runtime/interpreter/mterp/arm64/op_and_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_and_int_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_and_int_lit16.S create mode 100644 runtime/interpreter/mterp/arm64/op_and_int_lit8.S create mode 100644 runtime/interpreter/mterp/arm64/op_and_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_and_long_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_aput.S create mode 100644 runtime/interpreter/mterp/arm64/op_aput_boolean.S create mode 100644 runtime/interpreter/mterp/arm64/op_aput_byte.S create mode 100644 runtime/interpreter/mterp/arm64/op_aput_char.S create mode 100644 runtime/interpreter/mterp/arm64/op_aput_object.S create mode 100644 runtime/interpreter/mterp/arm64/op_aput_short.S create mode 100644 runtime/interpreter/mterp/arm64/op_aput_wide.S create mode 100644 runtime/interpreter/mterp/arm64/op_array_length.S create mode 100644 runtime/interpreter/mterp/arm64/op_check_cast.S create mode 100644 runtime/interpreter/mterp/arm64/op_cmp_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_cmpg_double.S create mode 100644 runtime/interpreter/mterp/arm64/op_cmpg_float.S create mode 100644 runtime/interpreter/mterp/arm64/op_cmpl_double.S create mode 100644 runtime/interpreter/mterp/arm64/op_cmpl_float.S create mode 100644 runtime/interpreter/mterp/arm64/op_const.S create mode 100644 runtime/interpreter/mterp/arm64/op_const_16.S create mode 100644 runtime/interpreter/mterp/arm64/op_const_4.S create mode 100644 runtime/interpreter/mterp/arm64/op_const_class.S create mode 100644 runtime/interpreter/mterp/arm64/op_const_high16.S create mode 100644 runtime/interpreter/mterp/arm64/op_const_string.S create mode 100644 runtime/interpreter/mterp/arm64/op_const_string_jumbo.S create mode 100644 runtime/interpreter/mterp/arm64/op_const_wide.S create mode 100644 runtime/interpreter/mterp/arm64/op_const_wide_16.S create mode 100644 runtime/interpreter/mterp/arm64/op_const_wide_32.S create mode 100644 runtime/interpreter/mterp/arm64/op_const_wide_high16.S create mode 100644 runtime/interpreter/mterp/arm64/op_div_double.S create mode 100644 runtime/interpreter/mterp/arm64/op_div_double_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_div_float.S create mode 100644 runtime/interpreter/mterp/arm64/op_div_float_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_div_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_div_int_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_div_int_lit16.S create mode 100644 runtime/interpreter/mterp/arm64/op_div_int_lit8.S create mode 100644 runtime/interpreter/mterp/arm64/op_div_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_div_long_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_double_to_float.S create mode 100644 runtime/interpreter/mterp/arm64/op_double_to_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_double_to_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_fill_array_data.S create mode 100644 runtime/interpreter/mterp/arm64/op_filled_new_array.S create mode 100644 runtime/interpreter/mterp/arm64/op_filled_new_array_range.S create mode 100644 runtime/interpreter/mterp/arm64/op_float_to_double.S create mode 100644 runtime/interpreter/mterp/arm64/op_float_to_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_float_to_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_goto.S create mode 100644 runtime/interpreter/mterp/arm64/op_goto_16.S create mode 100644 runtime/interpreter/mterp/arm64/op_goto_32.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_eq.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_eqz.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_ge.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_gez.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_gt.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_gtz.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_le.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_lez.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_lt.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_ltz.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_ne.S create mode 100644 runtime/interpreter/mterp/arm64/op_if_nez.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_boolean.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_boolean_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_byte.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_byte_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_char.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_char_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_object.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_object_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_short.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_short_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_wide.S create mode 100644 runtime/interpreter/mterp/arm64/op_iget_wide_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_instance_of.S create mode 100644 runtime/interpreter/mterp/arm64/op_int_to_byte.S create mode 100644 runtime/interpreter/mterp/arm64/op_int_to_char.S create mode 100644 runtime/interpreter/mterp/arm64/op_int_to_double.S create mode 100644 runtime/interpreter/mterp/arm64/op_int_to_float.S create mode 100644 runtime/interpreter/mterp/arm64/op_int_to_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_int_to_short.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_direct.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_direct_range.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_interface.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_interface_range.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_static.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_static_range.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_super.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_super_range.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_virtual.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_virtual_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_virtual_range.S create mode 100644 runtime/interpreter/mterp/arm64/op_invoke_virtual_range_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_boolean.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_boolean_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_byte.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_byte_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_char.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_char_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_object.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_object_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_short.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_short_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_wide.S create mode 100644 runtime/interpreter/mterp/arm64/op_iput_wide_quick.S create mode 100644 runtime/interpreter/mterp/arm64/op_long_to_double.S create mode 100644 runtime/interpreter/mterp/arm64/op_long_to_float.S create mode 100644 runtime/interpreter/mterp/arm64/op_long_to_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_monitor_enter.S create mode 100644 runtime/interpreter/mterp/arm64/op_monitor_exit.S create mode 100644 runtime/interpreter/mterp/arm64/op_move.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_16.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_exception.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_from16.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_object.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_object_16.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_object_from16.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_result.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_result_object.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_result_wide.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_wide.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_wide_16.S create mode 100644 runtime/interpreter/mterp/arm64/op_move_wide_from16.S create mode 100644 runtime/interpreter/mterp/arm64/op_mul_double.S create mode 100644 runtime/interpreter/mterp/arm64/op_mul_double_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_mul_float.S create mode 100644 runtime/interpreter/mterp/arm64/op_mul_float_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_mul_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_mul_int_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_mul_int_lit16.S create mode 100644 runtime/interpreter/mterp/arm64/op_mul_int_lit8.S create mode 100644 runtime/interpreter/mterp/arm64/op_mul_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_mul_long_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_neg_double.S create mode 100644 runtime/interpreter/mterp/arm64/op_neg_float.S create mode 100644 runtime/interpreter/mterp/arm64/op_neg_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_neg_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_new_array.S create mode 100644 runtime/interpreter/mterp/arm64/op_new_instance.S create mode 100644 runtime/interpreter/mterp/arm64/op_nop.S create mode 100644 runtime/interpreter/mterp/arm64/op_not_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_not_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_or_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_or_int_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_or_int_lit16.S create mode 100644 runtime/interpreter/mterp/arm64/op_or_int_lit8.S create mode 100644 runtime/interpreter/mterp/arm64/op_or_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_or_long_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_packed_switch.S create mode 100644 runtime/interpreter/mterp/arm64/op_rem_double.S create mode 100644 runtime/interpreter/mterp/arm64/op_rem_double_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_rem_float.S create mode 100644 runtime/interpreter/mterp/arm64/op_rem_float_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_rem_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_rem_int_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_rem_int_lit16.S create mode 100644 runtime/interpreter/mterp/arm64/op_rem_int_lit8.S create mode 100644 runtime/interpreter/mterp/arm64/op_rem_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_rem_long_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_return.S create mode 100644 runtime/interpreter/mterp/arm64/op_return_object.S create mode 100644 runtime/interpreter/mterp/arm64/op_return_void.S create mode 100644 runtime/interpreter/mterp/arm64/op_return_void_no_barrier.S create mode 100644 runtime/interpreter/mterp/arm64/op_return_wide.S create mode 100644 runtime/interpreter/mterp/arm64/op_rsub_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_rsub_int_lit8.S create mode 100644 runtime/interpreter/mterp/arm64/op_sget.S create mode 100644 runtime/interpreter/mterp/arm64/op_sget_boolean.S create mode 100644 runtime/interpreter/mterp/arm64/op_sget_byte.S create mode 100644 runtime/interpreter/mterp/arm64/op_sget_char.S create mode 100644 runtime/interpreter/mterp/arm64/op_sget_object.S create mode 100644 runtime/interpreter/mterp/arm64/op_sget_short.S create mode 100644 runtime/interpreter/mterp/arm64/op_sget_wide.S create mode 100644 runtime/interpreter/mterp/arm64/op_shl_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_shl_int_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_shl_int_lit8.S create mode 100644 runtime/interpreter/mterp/arm64/op_shl_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_shl_long_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_shr_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_shr_int_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_shr_int_lit8.S create mode 100644 runtime/interpreter/mterp/arm64/op_shr_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_shr_long_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_sparse_switch.S create mode 100644 runtime/interpreter/mterp/arm64/op_sput.S create mode 100644 runtime/interpreter/mterp/arm64/op_sput_boolean.S create mode 100644 runtime/interpreter/mterp/arm64/op_sput_byte.S create mode 100644 runtime/interpreter/mterp/arm64/op_sput_char.S create mode 100644 runtime/interpreter/mterp/arm64/op_sput_object.S create mode 100644 runtime/interpreter/mterp/arm64/op_sput_short.S create mode 100644 runtime/interpreter/mterp/arm64/op_sput_wide.S create mode 100644 runtime/interpreter/mterp/arm64/op_sub_double.S create mode 100644 runtime/interpreter/mterp/arm64/op_sub_double_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_sub_float.S create mode 100644 runtime/interpreter/mterp/arm64/op_sub_float_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_sub_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_sub_int_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_sub_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_sub_long_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_throw.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_3e.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_3f.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_40.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_41.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_42.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_43.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_73.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_79.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_7a.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_f3.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_f4.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_f5.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_f6.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_f7.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_f8.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_f9.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_fa.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_fb.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_fc.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_fd.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_fe.S create mode 100644 runtime/interpreter/mterp/arm64/op_unused_ff.S create mode 100644 runtime/interpreter/mterp/arm64/op_ushr_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_ushr_int_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_ushr_int_lit8.S create mode 100644 runtime/interpreter/mterp/arm64/op_ushr_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_ushr_long_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_xor_int.S create mode 100644 runtime/interpreter/mterp/arm64/op_xor_int_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/op_xor_int_lit16.S create mode 100644 runtime/interpreter/mterp/arm64/op_xor_int_lit8.S create mode 100644 runtime/interpreter/mterp/arm64/op_xor_long.S create mode 100644 runtime/interpreter/mterp/arm64/op_xor_long_2addr.S create mode 100644 runtime/interpreter/mterp/arm64/shiftWide.S create mode 100644 runtime/interpreter/mterp/arm64/shiftWide2addr.S create mode 100644 runtime/interpreter/mterp/arm64/unop.S create mode 100644 runtime/interpreter/mterp/arm64/unopWide.S create mode 100644 runtime/interpreter/mterp/arm64/unused.S create mode 100644 runtime/interpreter/mterp/arm64/zcmp.S create mode 100644 runtime/interpreter/mterp/out/mterp_arm64.S diff --git a/runtime/Android.mk b/runtime/Android.mk index 7bf6d2104..288f95e89 100644 --- a/runtime/Android.mk +++ b/runtime/Android.mk @@ -263,7 +263,8 @@ LIBART_TARGET_SRC_FILES_arm := \ arch/arm/fault_handler_arm.cc LIBART_TARGET_SRC_FILES_arm64 := \ - interpreter/mterp/mterp_stub.cc \ + interpreter/mterp/mterp.cc \ + interpreter/mterp/out/mterp_arm64.S \ arch/arm64/context_arm64.cc \ arch/arm64/entrypoints_init_arm64.cc \ arch/arm64/jni_entrypoints_arm64.S \ @@ -508,6 +509,7 @@ endif ifeq ($$(art_target_or_host),target) $$(eval $$(call set-target-local-clang-vars)) $$(eval $$(call set-target-local-cflags-vars,$(2))) + LOCAL_CLANG_arm64 := true LOCAL_CFLAGS_$(DEX2OAT_TARGET_ARCH) += -DART_DEFAULT_INSTRUCTION_SET_FEATURES="$(LIBART_TARGET_DEFAULT_INSTRUCTION_SET_FEATURES)" LOCAL_CFLAGS_$(2ND_DEX2OAT_TARGET_ARCH) += -DART_DEFAULT_INSTRUCTION_SET_FEATURES="$(2ND_LIBART_TARGET_DEFAULT_INSTRUCTION_SET_FEATURES)" else # host diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index e93bbdbf5..3eff7fc69 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -240,7 +240,7 @@ static std::ostream& operator<<(std::ostream& os, const InterpreterImplKind& rhs } #if !defined(__clang__) -#if (defined(__arm__) || defined(__i386__)) +#if (defined(__arm__) || defined(__i386__) || defined(__aarch64__)) // TODO: remove when all targets implemented. static constexpr InterpreterImplKind kInterpreterImplKind = kMterpImplKind; #else @@ -248,7 +248,7 @@ static constexpr InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKin #endif #else // Clang 3.4 fails to build the goto interpreter implementation. -#if (defined(__arm__) || defined(__i386__)) +#if (defined(__arm__) || defined(__i386__) || defined(__aarch64__)) static constexpr InterpreterImplKind kInterpreterImplKind = kMterpImplKind; #else static constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImplKind; diff --git a/runtime/interpreter/mterp/arm64/alt_stub.S b/runtime/interpreter/mterp/arm64/alt_stub.S new file mode 100644 index 000000000..9b8b16d72 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/alt_stub.S @@ -0,0 +1,12 @@ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (${opnum} * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. diff --git a/runtime/interpreter/mterp/arm64/bincmp.S b/runtime/interpreter/mterp/arm64/bincmp.S new file mode 100644 index 000000000..ecab2ceba --- /dev/null +++ b/runtime/interpreter/mterp/arm64/bincmp.S @@ -0,0 +1,37 @@ + /* + * Generic two-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le + */ + /* if-cmp vA, vB, +CCCC */ +#if MTERP_SUSPEND + mov w1, wINST, lsr #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, w3 // compare (vA, vB) + mov${condition} w1, #2 // w1<- BYTE branch dist for not-taken + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh rIBASE + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w1, wINST, #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Offset if branch not taken + cmp w2, w3 // compare (vA, vB) + csel w1, w1, w0, ${condition} // Branch if true + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif diff --git a/runtime/interpreter/mterp/arm64/binop.S b/runtime/interpreter/mterp/arm64/binop.S new file mode 100644 index 000000000..b629b0b37 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/binop.S @@ -0,0 +1,33 @@ +%default {"preinstr":"", "result":"w0", "chkzero":"0"} + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if $chkzero + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + $preinstr // optional op; may set condition codes + $instr // $result<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG $result, w9 // vAA<- $result + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ diff --git a/runtime/interpreter/mterp/arm64/binop2addr.S b/runtime/interpreter/mterp/arm64/binop2addr.S new file mode 100644 index 000000000..a480a7d55 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/binop2addr.S @@ -0,0 +1,30 @@ +%default {"preinstr":"", "result":"w0", "chkzero":"0"} + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if $chkzero + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + $preinstr // optional op; may set condition codes + $instr // $result<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG $result, w9 // vAA<- $result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ diff --git a/runtime/interpreter/mterp/arm64/binopLit16.S b/runtime/interpreter/mterp/arm64/binopLit16.S new file mode 100644 index 000000000..4f9d205b3 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/binopLit16.S @@ -0,0 +1,28 @@ +%default {"preinstr":"", "result":"w0", "chkzero":"0"} + /* + * Generic 32-bit "lit16" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, + * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 + */ + /* binop/lit16 vA, vB, #+CCCC */ + FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) + lsr w2, wINST, #12 // w2<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w0, w2 // w0<- vB + .if $chkzero + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + $preinstr + $instr // $result<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG $result, w9 // vAA<- $result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ diff --git a/runtime/interpreter/mterp/arm64/binopLit8.S b/runtime/interpreter/mterp/arm64/binopLit8.S new file mode 100644 index 000000000..326c65765 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/binopLit8.S @@ -0,0 +1,30 @@ +%default {"preinstr":"", "result":"w0", "chkzero":"0"} + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if $chkzero + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + $preinstr // optional op; may set condition codes + $instr // $result<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG $result, w9 // vAA<- $result + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ diff --git a/runtime/interpreter/mterp/arm64/binopWide.S b/runtime/interpreter/mterp/arm64/binopWide.S new file mode 100644 index 000000000..9de24f1c2 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/binopWide.S @@ -0,0 +1,30 @@ +%default {"preinstr":"", "instr":"add x0, x1, x2", "result":"x0", "r1":"x1", "r2":"x2", "chkzero":"0"} + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE $r2, w2 // w2<- vCC + GET_VREG_WIDE $r1, w1 // w1<- vBB + .if $chkzero + cbz $r2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + $preinstr + $instr // $result<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE $result, w4 // vAA<- $result + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ diff --git a/runtime/interpreter/mterp/arm64/binopWide2addr.S b/runtime/interpreter/mterp/arm64/binopWide2addr.S new file mode 100644 index 000000000..d9927a2ca --- /dev/null +++ b/runtime/interpreter/mterp/arm64/binopWide2addr.S @@ -0,0 +1,29 @@ +%default {"preinstr":"", "instr":"add x0, x0, x1", "r0":"x0", "r1":"x1", "chkzero":"0"} + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE $r1, w1 // x1<- vB + GET_VREG_WIDE $r0, w2 // x0<- vA + .if $chkzero + cbz $r1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + $preinstr + $instr // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE $r0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ diff --git a/runtime/interpreter/mterp/arm64/entry.S b/runtime/interpreter/mterp/arm64/entry.S new file mode 100644 index 000000000..f9073ab5d --- /dev/null +++ b/runtime/interpreter/mterp/arm64/entry.S @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + .text + +/* + * Interpreter entry point. + * On entry: + * x0 Thread* self/ + * x1 code_item + * x2 ShadowFrame + * x3 JValue* result_register + * + */ + .global ExecuteMterpImpl + .type ExecuteMterpImpl, %function + .balign 16 + +ExecuteMterpImpl: + .cfi_startproc + stp xIBASE, xREFS, [sp, #-64]! + stp xSELF, xINST, [sp, #16] + stp xPC, xFP, [sp, #32] + stp fp, lr, [sp, #48] + add fp, sp, #48 + + /* Remember the return register */ + str x3, [x2, #SHADOWFRAME_RESULT_REGISTER_OFFSET] + + /* Remember the code_item */ + str x1, [x2, #SHADOWFRAME_CODE_ITEM_OFFSET] + + /* set up "named" registers */ + mov xSELF, x0 + ldr w0, [x2, #SHADOWFRAME_NUMBER_OF_VREGS_OFFSET] + add xFP, x2, #SHADOWFRAME_VREGS_OFFSET // point to insns[] (i.e. - the dalivk byte code). + add xREFS, xFP, w0, lsl #2 // point to reference array in shadow frame + ldr w0, [x2, #SHADOWFRAME_DEX_PC_OFFSET] // Get starting dex_pc. + add xPC, x1, #CODEITEM_INSNS_OFFSET // Point to base of insns[] + add xPC, xPC, w0, lsl #1 // Create direct pointer to 1st dex opcode + EXPORT_PC + + /* Starting ibase */ + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] + + /* start executing the instruction at rPC */ + FETCH_INST // load wINST from rPC + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + /* NOTE: no fallthrough */ diff --git a/runtime/interpreter/mterp/arm64/fallback.S b/runtime/interpreter/mterp/arm64/fallback.S new file mode 100644 index 000000000..44e7e1220 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/fallback.S @@ -0,0 +1,3 @@ +/* Transfer stub to alternate interpreter */ + b MterpFallback + diff --git a/runtime/interpreter/mterp/arm64/fbinop.S b/runtime/interpreter/mterp/arm64/fbinop.S new file mode 100644 index 000000000..926d0783d --- /dev/null +++ b/runtime/interpreter/mterp/arm64/fbinop.S @@ -0,0 +1,19 @@ +%default {} + /*: + * Generic 32-bit floating-point operation. + * + * For: add-float, sub-float, mul-float, div-float + * form: s0, s0, s1 + */ + /* floatop vAA, vBB, vCC */ + FETCH w0, 1 // r0<- CCBB + lsr w1, w0, #8 // r2<- CC + and w0, w0, #255 // r1<- BB + GET_VREG s1, w1 + GET_VREG s0, w0 + $instr // s0<- op + lsr w1, wINST, #8 // r1<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s0, w1 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/fbinop2addr.S b/runtime/interpreter/mterp/arm64/fbinop2addr.S new file mode 100644 index 000000000..0d57cbf2c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/fbinop2addr.S @@ -0,0 +1,18 @@ + /* + * Generic 32-bit floating point "/2addr" binary operation. Provide + * an "instr" line that specifies an instruction that performs + * "s2 = s0 op s1". + * + * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w9, wINST, #8 // w9<- A+ + and w9, w9, #15 // w9<- A + GET_VREG s1, w3 + GET_VREG s0, w9 + $instr // s2<- op + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s2, w9 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/fcmp.S b/runtime/interpreter/mterp/arm64/fcmp.S new file mode 100644 index 000000000..a45e789f6 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/fcmp.S @@ -0,0 +1,20 @@ +%default {"wide":"", "r1":"s1", "r2":"s2", "default_val":"-1","cond":"le"} + /* + * Compare two floating-point values. Puts 0, 1, or -1 into the + * destination register based on the results of the comparison. + */ + /* op vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + and w2, w0, #255 // w2<- BB + lsr w3, w0, #8 // w3<- CC + GET_VREG$wide $r1, w2 + GET_VREG$wide $r2, w3 + mov w0, #$default_val + fcmp $r1, $r2 + csneg w0, w0, w0, $cond + csel w0, wzr, w0, eq + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w4 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/footer.S b/runtime/interpreter/mterp/arm64/footer.S new file mode 100644 index 000000000..b360539a8 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/footer.S @@ -0,0 +1,170 @@ +/* + * =========================================================================== + * Common subroutines and data + * =========================================================================== + */ + + +/* + * We've detected a condition that will result in an exception, but the exception + * has not yet been thrown. Just bail out to the reference interpreter to deal with it. + * TUNING: for consistency, we may want to just go ahead and handle these here. + */ +#define MTERP_LOGGING 0 +common_errDivideByZero: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogDivideByZeroException +#endif + b MterpCommonFallback + +common_errArrayIndex: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogArrayIndexException +#endif + b MterpCommonFallback + +common_errNegativeArraySize: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogNegativeArraySizeException +#endif + b MterpCommonFallback + +common_errNoSuchMethod: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogNoSuchMethodException +#endif + b MterpCommonFallback + +common_errNullObject: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogNullObjectException +#endif + b MterpCommonFallback + +common_exceptionThrown: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogExceptionThrownException +#endif + b MterpCommonFallback + +MterpSuspendFallback: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + ldr x2, [xSELF, #THREAD_FLAGS_OFFSET] + bl MterpLogSuspendFallback +#endif + b MterpCommonFallback + +/* + * If we're here, something is out of the ordinary. If there is a pending + * exception, handle it. Otherwise, roll back and retry with the reference + * interpreter. + */ +MterpPossibleException: + ldr x0, [xSELF, #THREAD_EXCEPTION_OFFSET] + cbz x0, MterpFallback // If not, fall back to reference interpreter. + /* intentional fallthrough - handle pending exception. */ +/* + * On return from a runtime helper routine, we've found a pending exception. + * Can we handle it here - or need to bail out to caller? + * + */ +MterpException: + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpHandleException // (self, shadow_frame) + cbz w0, MterpExceptionReturn // no local catch, back to caller. + ldr x0, [xFP, #OFF_FP_CODE_ITEM] + ldr w1, [xFP, #OFF_FP_DEX_PC] + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] + add xPC, x0, #CODEITEM_INSNS_OFFSET + add xPC, xPC, x1, lsl #1 // generate new dex_pc_ptr + str xPC, [xFP, #OFF_FP_DEX_PC_PTR] + /* resume execution at catch block */ + FETCH_INST + GET_INST_OPCODE ip + GOTO_OPCODE ip + /* NOTE: no fallthrough */ + +/* + * Check for suspend check request. Assumes wINST already loaded, xPC advanced and + * still needs to get the opcode and branch to it, and flags are in lr. + */ +MterpCheckSuspendAndContinue: + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh xIBASE + ands w7, w7, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.ne check1 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +check1: + EXPORT_PC + mov x0, xSELF + bl MterpSuspendCheck // (self) + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* + * Bail out to reference interpreter. + */ +MterpFallback: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogFallback +#endif +MterpCommonFallback: + mov x0, #0 // signal retry with reference interpreter. + b MterpDone + +/* + * We pushed some registers on the stack in ExecuteMterpImpl, then saved + * SP and LR. Here we restore SP, restore the registers, and then restore + * LR to PC. + * + * On entry: + * uint32_t* xFP (should still be live, pointer to base of vregs) + */ +MterpExceptionReturn: + mov x0, #1 // signal return to caller. + b MterpDone +MterpReturn: + ldr x2, [xFP, #OFF_FP_RESULT_REGISTER] + ldr lr, [xSELF, #THREAD_FLAGS_OFFSET] + str x0, [x2] + mov x0, xSELF + ands lr, lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.eq check2 + bl MterpSuspendCheck // (self) +check2: + mov x0, #1 // signal return to caller. +MterpDone: + ldp fp, lr, [sp, #48] + ldp xPC, xFP, [sp, #32] + ldp xSELF, xINST, [sp, #16] + ldp xIBASE, xREFS, [sp], #64 + ret + + .cfi_endproc + .size ExecuteMterpImpl, .-ExecuteMterpImpl + diff --git a/runtime/interpreter/mterp/arm64/funopNarrow.S b/runtime/interpreter/mterp/arm64/funopNarrow.S new file mode 100644 index 000000000..9f5ad1e87 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/funopNarrow.S @@ -0,0 +1,18 @@ +%default {"srcreg":"s0", "tgtreg":"d0"} + /* + * Generic 32bit-to-32bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "$tgtreg = op $srcreg". + * + * For: int-to-float, float-to-int + * TODO: refactor all of the conversions - parameterize width and use same template. + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG $srcreg, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + $instr // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG $tgtreg, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/funopNarrower.S b/runtime/interpreter/mterp/arm64/funopNarrower.S new file mode 100644 index 000000000..411396b29 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/funopNarrower.S @@ -0,0 +1,17 @@ +%default {"srcreg":"s0", "tgtreg":"d0"} + /* + * Generic 64bit-to-32bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "$tgtreg = op $srcreg". + * + * For: int-to-double, float-to-double, float-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG_WIDE $srcreg, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + $instr // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG $tgtreg, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/funopWide.S b/runtime/interpreter/mterp/arm64/funopWide.S new file mode 100644 index 000000000..d83b39c25 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/funopWide.S @@ -0,0 +1,17 @@ +%default {"srcreg":"s0", "tgtreg":"d0"} + /* + * Generic 64bit-to-64bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "$tgtreg = op $srcreg". + * + * For: long-to-double, double-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG_WIDE $srcreg, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + $instr // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE $tgtreg, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/funopWider.S b/runtime/interpreter/mterp/arm64/funopWider.S new file mode 100644 index 000000000..50a73f199 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/funopWider.S @@ -0,0 +1,17 @@ +%default {"srcreg":"s0", "tgtreg":"d0"} + /* + * Generic 32bit-to-64bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "$tgtreg = op $srcreg". + * + * For: int-to-double, float-to-double, float-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG $srcreg, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + $instr // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE $tgtreg, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/header.S b/runtime/interpreter/mterp/arm64/header.S new file mode 100644 index 000000000..351a6075c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/header.S @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + Art assembly interpreter notes: + + First validate assembly code by implementing ExecuteXXXImpl() style body (doesn't + handle invoke, allows higher-level code to create frame & shadow frame. + + Once that's working, support direct entry code & eliminate shadow frame (and + excess locals allocation. + + Some (hopefully) temporary ugliness. We'll treat xFP as pointing to the + base of the vreg array within the shadow frame. Access the other fields, + dex_pc_, method_ and number_of_vregs_ via negative offsets. For now, we'll continue + the shadow frame mechanism of double-storing object references - via xFP & + number_of_vregs_. + + */ + +/* +ARM64 Runtime register usage conventions. + + r0 : w0 is 32-bit return register and x0 is 64-bit. + r0-r7 : Argument registers. + r8-r15 : Caller save registers (used as temporary registers). + r16-r17: Also known as ip0-ip1, respectively. Used as scratch registers by + the linker, by the trampolines and other stubs (the backend uses + these as temporary registers). + r18 : Caller save register (used as temporary register). + r19 : Pointer to thread-local storage. + r20-r29: Callee save registers. + r30 : (lr) is reserved (the link register). + rsp : (sp) is reserved (the stack pointer). + rzr : (zr) is reserved (the zero register). + + Floating-point registers + v0-v31 + + v0 : s0 is return register for singles (32-bit) and d0 for doubles (64-bit). + This is analogous to the C/C++ (hard-float) calling convention. + v0-v7 : Floating-point argument registers in both Dalvik and C/C++ conventions. + Also used as temporary and codegen scratch registers. + + v0-v7 and v16-v31 : trashed across C calls. + v8-v15 : bottom 64-bits preserved across C calls (d8-d15 are preserved). + + v16-v31: Used as codegen temp/scratch. + v8-v15 : Can be used for promotion. + + Must maintain 16-byte stack alignment. + +Mterp notes: + +The following registers have fixed assignments: + + reg nick purpose + x20 xPC interpreted program counter, used for fetching instructions + x21 xFP interpreted frame pointer, used for accessing locals and args + x22 xSELF self (Thread) pointer + x23 xINST first 16-bit code unit of current instruction + x24 xIBASE interpreted instruction base pointer, used for computed goto + x25 xREFS base of object references in shadow frame (ideally, we'll get rid of this later). + x16 ip scratch reg + x17 ip2 scratch reg (used by macros) + +Macros are provided for common operations. They MUST NOT alter unspecified registers or condition +codes. +*/ + +/* + * This is a #include, not a %include, because we want the C pre-processor + * to expand the macros into assembler assignment statements. + */ +#include "asm_support.h" + +/* During bringup, we'll use the shadow frame model instead of xFP */ +/* single-purpose registers, given names for clarity */ +#define xPC x20 +#define xFP x21 +#define xSELF x22 +#define xINST x23 +#define wINST w23 +#define xIBASE x24 +#define xREFS x25 +#define ip x16 +#define ip2 x17 + +/* + * Instead of holding a pointer to the shadow frame, we keep xFP at the base of the vregs. So, + * to access other shadow frame fields, we need to use a backwards offset. Define those here. + */ +#define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET) +#define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET) +#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET) +#define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET) +#define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET) +#define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET) +#define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET) +#define OFF_FP_CODE_ITEM OFF_FP(SHADOWFRAME_CODE_ITEM_OFFSET) +#define OFF_FP_SHADOWFRAME (-SHADOWFRAME_VREGS_OFFSET) + +/* + * + * The reference interpreter performs explicit suspect checks, which is somewhat wasteful. + * Dalvik's interpreter folded suspend checks into the jump table mechanism, and eventually + * mterp should do so as well. + */ +#define MTERP_SUSPEND 0 + +/* + * "export" the PC to dex_pc field in the shadow frame, f/b/o future exception objects. Must + * be done *before* something throws. + * + * It's okay to do this more than once. + * + * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped + * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction + * offset into the code_items_[] array. For effiency, we will "export" the + * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC + * to convert to a dex pc when needed. + */ +.macro EXPORT_PC + str xPC, [xFP, #OFF_FP_DEX_PC_PTR] +.endm + +/* + * Fetch the next instruction from xPC into wINST. Does not advance xPC. + */ +.macro FETCH_INST + ldrh wINST, [xPC] +.endm + +/* + * Fetch the next instruction from the specified offset. Advances xPC + * to point to the next instruction. "_count" is in 16-bit code units. + * + * Because of the limited size of immediate constants on ARM, this is only + * suitable for small forward movements (i.e. don't try to implement "goto" + * with this). + * + * This must come AFTER anything that can throw an exception, or the + * exception catch may miss. (This also implies that it must come after + * EXPORT_PC.) + */ +.macro FETCH_ADVANCE_INST count + ldrh wINST, [xPC, #((\count)*2)]! +.endm + +/* + * The operation performed here is similar to FETCH_ADVANCE_INST, except the + * src and dest registers are parameterized (not hard-wired to xPC and xINST). + */ +.macro PREFETCH_ADVANCE_INST dreg, sreg, count + ldrh \dreg, [\sreg, #((\count)*2)]! +.endm + +/* + * Similar to FETCH_ADVANCE_INST, but does not update xPC. Used to load + * xINST ahead of possible exception point. Be sure to manually advance xPC + * later. + */ +.macro PREFETCH_INST count + ldrh wINST, [xPC, #((\count)*2)] +.endm + +/* Advance xPC by some number of code units. */ +.macro ADVANCE count + add xPC, xPC, #((\count)*2) +.endm + +/* + * Fetch the next instruction from an offset specified by _reg and advance xPC. + * xPC to point to the next instruction. "_reg" must specify the distance + * in bytes, *not* 16-bit code units, and may be a signed value. Must not set flags. + * + */ +.macro FETCH_ADVANCE_INST_RB reg + add xPC, xPC, \reg, sxtw + ldrh wINST, [xPC] +.endm + +/* + * Fetch a half-word code unit from an offset past the current PC. The + * "_count" value is in 16-bit code units. Does not advance xPC. + * + * The "_S" variant works the same but treats the value as signed. + */ +.macro FETCH reg, count + ldrh \reg, [xPC, #((\count)*2)] +.endm + +.macro FETCH_S reg, count + ldrsh \reg, [xPC, #((\count)*2)] +.endm + +/* + * Fetch one byte from an offset past the current PC. Pass in the same + * "_count" as you would for FETCH, and an additional 0/1 indicating which + * byte of the halfword you want (lo/hi). + */ +.macro FETCH_B reg, count, byte + ldrb \reg, [xPC, #((\count)*2+(\byte))] +.endm + +/* + * Put the instruction's opcode field into the specified register. + */ +.macro GET_INST_OPCODE reg + and \reg, xINST, #255 +.endm + +/* + * Put the prefetched instruction's opcode field into the specified register. + */ +.macro GET_PREFETCHED_OPCODE oreg, ireg + and \oreg, \ireg, #255 +.endm + +/* + * Begin executing the opcode in _reg. Clobbers reg + */ + +.macro GOTO_OPCODE reg + add \reg, xIBASE, \reg, lsl #${handler_size_bits} + br \reg +.endm +.macro GOTO_OPCODE_BASE base,reg + add \reg, \base, \reg, lsl #${handler_size_bits} + br \reg +.endm + +/* + * Get/set the 32-bit value from a Dalvik register. + */ +.macro GET_VREG reg, vreg + ldr \reg, [xFP, \vreg, uxtw #2] +.endm +.macro SET_VREG reg, vreg + str \reg, [xFP, \vreg, uxtw #2] + str wzr, [xREFS, \vreg, uxtw #2] +.endm +.macro SET_VREG_OBJECT reg, vreg, tmpreg + str \reg, [xFP, \vreg, uxtw #2] + str \reg, [xREFS, \vreg, uxtw #2] +.endm + +/* + * Get/set the 64-bit value from a Dalvik register. + * TUNING: can we do better here? + */ +.macro GET_VREG_WIDE reg, vreg + add ip2, xFP, \vreg, lsl #2 + ldr \reg, [ip2] +.endm +.macro SET_VREG_WIDE reg, vreg + add ip2, xFP, \vreg, lsl #2 + str \reg, [ip2] + add ip2, xREFS, \vreg, lsl #2 + str xzr, [ip2] +.endm + +/* + * Convert a virtual register index into an address. + */ +.macro VREG_INDEX_TO_ADDR reg, vreg + add \reg, xFP, \vreg, lsl #2 /* WARNING/FIXME: handle shadow frame vreg zero if store */ +.endm + +/* + * Refresh handler table. + */ +.macro REFRESH_IBASE + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] +.endm diff --git a/runtime/interpreter/mterp/arm64/invoke.S b/runtime/interpreter/mterp/arm64/invoke.S new file mode 100644 index 000000000..ff1974c51 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/invoke.S @@ -0,0 +1,19 @@ +%default { "helper":"UndefinedInvokeHandler" } + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern $helper + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl $helper + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + diff --git a/runtime/interpreter/mterp/arm64/op_add_double.S b/runtime/interpreter/mterp/arm64/op_add_double.S new file mode 100644 index 000000000..8509f7030 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_add_double.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"instr":"fadd d0, d1, d2", "result":"d0", "r1":"d1", "r2":"d2"} diff --git a/runtime/interpreter/mterp/arm64/op_add_double_2addr.S b/runtime/interpreter/mterp/arm64/op_add_double_2addr.S new file mode 100644 index 000000000..61fd58f4b --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_add_double_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"instr":"fadd d0, d0, d1", "r0":"d0", "r1":"d1"} diff --git a/runtime/interpreter/mterp/arm64/op_add_float.S b/runtime/interpreter/mterp/arm64/op_add_float.S new file mode 100644 index 000000000..7d09fef10 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_add_float.S @@ -0,0 +1 @@ +%include "arm64/fbinop.S" {"instr":"fadd s0, s0, s1"} diff --git a/runtime/interpreter/mterp/arm64/op_add_float_2addr.S b/runtime/interpreter/mterp/arm64/op_add_float_2addr.S new file mode 100644 index 000000000..7b378e288 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_add_float_2addr.S @@ -0,0 +1 @@ +%include "arm64/fbinop2addr.S" {"instr":"fadd s2, s0, s1"} diff --git a/runtime/interpreter/mterp/arm64/op_add_int.S b/runtime/interpreter/mterp/arm64/op_add_int.S new file mode 100644 index 000000000..6eadb5441 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_add_int.S @@ -0,0 +1 @@ +%include "arm64/binop.S" {"instr":"add w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_add_int_2addr.S b/runtime/interpreter/mterp/arm64/op_add_int_2addr.S new file mode 100644 index 000000000..d35bc8ecc --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_add_int_2addr.S @@ -0,0 +1 @@ +%include "arm64/binop2addr.S" {"instr":"add w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_add_int_lit16.S b/runtime/interpreter/mterp/arm64/op_add_int_lit16.S new file mode 100644 index 000000000..4930ad771 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_add_int_lit16.S @@ -0,0 +1 @@ +%include "arm64/binopLit16.S" {"instr":"add w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_add_int_lit8.S b/runtime/interpreter/mterp/arm64/op_add_int_lit8.S new file mode 100644 index 000000000..196ea9934 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_add_int_lit8.S @@ -0,0 +1 @@ +%include "arm64/binopLit8.S" {"instr":"add w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_add_long.S b/runtime/interpreter/mterp/arm64/op_add_long.S new file mode 100644 index 000000000..bc334aa3b --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_add_long.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"instr":"add x0, x1, x2"} diff --git a/runtime/interpreter/mterp/arm64/op_add_long_2addr.S b/runtime/interpreter/mterp/arm64/op_add_long_2addr.S new file mode 100644 index 000000000..5e5dbce73 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_add_long_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"instr":"add x0, x0, x1"} diff --git a/runtime/interpreter/mterp/arm64/op_aget.S b/runtime/interpreter/mterp/arm64/op_aget.S new file mode 100644 index 000000000..662c9cc7c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aget.S @@ -0,0 +1,28 @@ +%default { "load":"ldr", "shift":"2", "data_offset":"MIRROR_INT_ARRAY_DATA_OFFSET" } + /* + * Array get, 32 bits or less. vAA <- vBB[vCC]. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aget, aget-boolean, aget-byte, aget-char, aget-short + * + * NOTE: assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz x0, common_errNullObject // bail if null array object. + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, uxtw #$shift // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + $load w2, [x0, #$data_offset] // w2<- vBB[vCC] + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w2, w9 // vAA<- w2 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_aget_boolean.S b/runtime/interpreter/mterp/arm64/op_aget_boolean.S new file mode 100644 index 000000000..6ab6cc1bf --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aget_boolean.S @@ -0,0 +1 @@ +%include "arm64/op_aget.S" { "load":"ldrb", "shift":"0", "data_offset":"MIRROR_BOOLEAN_ARRAY_DATA_OFFSET" } diff --git a/runtime/interpreter/mterp/arm64/op_aget_byte.S b/runtime/interpreter/mterp/arm64/op_aget_byte.S new file mode 100644 index 000000000..c7f5b23eb --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aget_byte.S @@ -0,0 +1 @@ +%include "arm64/op_aget.S" { "load":"ldrsb", "shift":"0", "data_offset":"MIRROR_BYTE_ARRAY_DATA_OFFSET" } diff --git a/runtime/interpreter/mterp/arm64/op_aget_char.S b/runtime/interpreter/mterp/arm64/op_aget_char.S new file mode 100644 index 000000000..9fddf1787 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aget_char.S @@ -0,0 +1 @@ +%include "arm64/op_aget.S" { "load":"ldrh", "shift":"1", "data_offset":"MIRROR_CHAR_ARRAY_DATA_OFFSET" } diff --git a/runtime/interpreter/mterp/arm64/op_aget_object.S b/runtime/interpreter/mterp/arm64/op_aget_object.S new file mode 100644 index 000000000..1bbe3e8a3 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aget_object.S @@ -0,0 +1,20 @@ + /* + * Array object get. vAA <- vBB[vCC]. + * + * for: aget-object + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + FETCH_B w3, 1, 1 // w3<- CC + EXPORT_PC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + bl artAGetObjectFromMterp // (array, index) + ldr x1, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w2, wINST, #8 // w9<- AA + PREFETCH_INST 2 + cbnz w1, MterpException + SET_VREG_OBJECT w0, w2 + ADVANCE 2 + GET_INST_OPCODE ip + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_aget_short.S b/runtime/interpreter/mterp/arm64/op_aget_short.S new file mode 100644 index 000000000..39554de6e --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aget_short.S @@ -0,0 +1 @@ +%include "arm64/op_aget.S" { "load":"ldrsh", "shift":"1", "data_offset":"MIRROR_SHORT_ARRAY_DATA_OFFSET" } diff --git a/runtime/interpreter/mterp/arm64/op_aget_wide.S b/runtime/interpreter/mterp/arm64/op_aget_wide.S new file mode 100644 index 000000000..6f990ba0c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aget_wide.S @@ -0,0 +1,21 @@ + /* + * Array get, 64 bits. vAA <- vBB[vCC]. + * + */ + /* aget-wide vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + and w2, w0, #255 // w2<- BB + lsr w3, w0, #8 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz w0, common_errNullObject // yes, bail + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, lsl #3 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + ldr x2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET] // x2<- vBB[vCC] + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x2, w4 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_and_int.S b/runtime/interpreter/mterp/arm64/op_and_int.S new file mode 100644 index 000000000..31f3f73e7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_and_int.S @@ -0,0 +1 @@ +%include "arm64/binop.S" {"instr":"and w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_and_int_2addr.S b/runtime/interpreter/mterp/arm64/op_and_int_2addr.S new file mode 100644 index 000000000..e59632cd0 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_and_int_2addr.S @@ -0,0 +1 @@ +%include "arm64/binop2addr.S" {"instr":"and w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_and_int_lit16.S b/runtime/interpreter/mterp/arm64/op_and_int_lit16.S new file mode 100644 index 000000000..6540f8155 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_and_int_lit16.S @@ -0,0 +1 @@ +%include "arm64/binopLit16.S" {"instr":"and w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_and_int_lit8.S b/runtime/interpreter/mterp/arm64/op_and_int_lit8.S new file mode 100644 index 000000000..167b40ecf --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_and_int_lit8.S @@ -0,0 +1 @@ +%include "arm64/binopLit8.S" {"instr":"and w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_and_long.S b/runtime/interpreter/mterp/arm64/op_and_long.S new file mode 100644 index 000000000..ede047d08 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_and_long.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"instr":"and x0, x1, x2"} diff --git a/runtime/interpreter/mterp/arm64/op_and_long_2addr.S b/runtime/interpreter/mterp/arm64/op_and_long_2addr.S new file mode 100644 index 000000000..d62ccef89 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_and_long_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"instr":"and x0, x0, x1"} diff --git a/runtime/interpreter/mterp/arm64/op_aput.S b/runtime/interpreter/mterp/arm64/op_aput.S new file mode 100644 index 000000000..175b483d7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aput.S @@ -0,0 +1,28 @@ +%default { "store":"str", "shift":"2", "data_offset":"MIRROR_INT_ARRAY_DATA_OFFSET" } + /* + * Array put, 32 bits or less. vBB[vCC] <- vAA. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aput, aput-boolean, aput-byte, aput-char, aput-short + * + * NOTE: this assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz w0, common_errNullObject // bail if null + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, lsl #$shift // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_VREG w2, w9 // w2<- vAA + GET_INST_OPCODE ip // extract opcode from rINST + $store w2, [x0, #$data_offset] // vBB[vCC]<- w2 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_aput_boolean.S b/runtime/interpreter/mterp/arm64/op_aput_boolean.S new file mode 100644 index 000000000..5e7a86f15 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aput_boolean.S @@ -0,0 +1 @@ +%include "arm64/op_aput.S" { "store":"strb", "shift":"0", "data_offset":"MIRROR_BOOLEAN_ARRAY_DATA_OFFSET" } diff --git a/runtime/interpreter/mterp/arm64/op_aput_byte.S b/runtime/interpreter/mterp/arm64/op_aput_byte.S new file mode 100644 index 000000000..d659ebc3d --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aput_byte.S @@ -0,0 +1 @@ +%include "arm64/op_aput.S" { "store":"strb", "shift":"0", "data_offset":"MIRROR_BYTE_ARRAY_DATA_OFFSET" } diff --git a/runtime/interpreter/mterp/arm64/op_aput_char.S b/runtime/interpreter/mterp/arm64/op_aput_char.S new file mode 100644 index 000000000..7547c8087 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aput_char.S @@ -0,0 +1 @@ +%include "arm64/op_aput.S" { "store":"strh", "shift":"1", "data_offset":"MIRROR_CHAR_ARRAY_DATA_OFFSET" } diff --git a/runtime/interpreter/mterp/arm64/op_aput_object.S b/runtime/interpreter/mterp/arm64/op_aput_object.S new file mode 100644 index 000000000..0146fdc95 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aput_object.S @@ -0,0 +1,13 @@ + /* + * Store an object into an array. vBB[vCC] <- vAA. + */ + /* op vAA, vBB, vCC */ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov w2, wINST + bl MterpAputObject + cbz w0, MterpPossibleException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_aput_short.S b/runtime/interpreter/mterp/arm64/op_aput_short.S new file mode 100644 index 000000000..8631e2807 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aput_short.S @@ -0,0 +1 @@ +%include "arm64/op_aput.S" { "store":"strh", "shift":"1", "data_offset":"MIRROR_SHORT_ARRAY_DATA_OFFSET" } diff --git a/runtime/interpreter/mterp/arm64/op_aput_wide.S b/runtime/interpreter/mterp/arm64/op_aput_wide.S new file mode 100644 index 000000000..e1cf9c1c2 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_aput_wide.S @@ -0,0 +1,21 @@ + /* + * Array put, 64 bits. vBB[vCC] <- vAA. + * + */ + /* aput-wide vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + and w2, w0, #255 // w2<- BB + lsr w3, w0, #8 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz w0, common_errNullObject // bail if null + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, lsl #3 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + GET_VREG_WIDE x1, w4 + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + str x1, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET] + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_array_length.S b/runtime/interpreter/mterp/arm64/op_array_length.S new file mode 100644 index 000000000..0cce917ff --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_array_length.S @@ -0,0 +1,12 @@ + /* + * Return the length of an array. + */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w0, w1 // w0<- vB (object ref) + cbz w0, common_errNullObject // yup, fail + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- array length + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w3, w2 // vB<- length + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_check_cast.S b/runtime/interpreter/mterp/arm64/op_check_cast.S new file mode 100644 index 000000000..cb9f6068e --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_check_cast.S @@ -0,0 +1,16 @@ + /* + * Check to see if a cast from one class to another is allowed. + */ + /* check-cast vAA, class//BBBB */ + EXPORT_PC + FETCH w0, 1 // w0<- BBBB + lsr w1, wINST, #8 // w1<- AA + VREG_INDEX_TO_ADDR x1, w1 // w1<- &object + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- method + mov x3, xSELF // w3<- self + bl MterpCheckCast // (index, &obj, method, self) + PREFETCH_INST 2 + cbnz w0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_cmp_long.S b/runtime/interpreter/mterp/arm64/op_cmp_long.S new file mode 100644 index 000000000..982e5b161 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_cmp_long.S @@ -0,0 +1,13 @@ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + and w2, w0, #255 // w2<- BB + lsr w3, w0, #8 // w3<- CC + GET_VREG_WIDE x1, w2 + GET_VREG_WIDE x2, w3 + cmp x1, x2 + csinc w0, wzr, wzr, eq + csneg w0, w0, w0, ge + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + SET_VREG w0, w4 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_cmpg_double.S b/runtime/interpreter/mterp/arm64/op_cmpg_double.S new file mode 100644 index 000000000..14f9ff8a0 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_cmpg_double.S @@ -0,0 +1 @@ +%include "arm64/fcmp.S" {"wide":"_WIDE", "r1":"d1", "r2":"d2", "default_val":"1", "cond":"pl"} diff --git a/runtime/interpreter/mterp/arm64/op_cmpg_float.S b/runtime/interpreter/mterp/arm64/op_cmpg_float.S new file mode 100644 index 000000000..3a20cbae1 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_cmpg_float.S @@ -0,0 +1 @@ +%include "arm64/fcmp.S" {"wide":"", "r1":"s1", "r2":"s2", "default_val":"1", "cond":"pl"} diff --git a/runtime/interpreter/mterp/arm64/op_cmpl_double.S b/runtime/interpreter/mterp/arm64/op_cmpl_double.S new file mode 100644 index 000000000..06d59179e --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_cmpl_double.S @@ -0,0 +1 @@ +%include "arm64/fcmp.S" {"wide":"_WIDE", "r1":"d1", "r2":"d2", "default_val":"-1", "cond":"le"} diff --git a/runtime/interpreter/mterp/arm64/op_cmpl_float.S b/runtime/interpreter/mterp/arm64/op_cmpl_float.S new file mode 100644 index 000000000..d87d08625 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_cmpl_float.S @@ -0,0 +1 @@ +%include "arm64/fcmp.S" {"wide":"", "r1":"s1", "r2":"s2", "default_val":"-1", "cond":"le"} diff --git a/runtime/interpreter/mterp/arm64/op_const.S b/runtime/interpreter/mterp/arm64/op_const.S new file mode 100644 index 000000000..031ede1fb --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_const.S @@ -0,0 +1,9 @@ + /* const vAA, #+BBBBbbbb */ + lsr w3, wINST, #8 // w3<- AA + FETCH w0, 1 // w0<- bbbb (low + FETCH w1, 2 // w1<- BBBB (high + FETCH_ADVANCE_INST 3 // advance rPC, load wINST + orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG w0, w3 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_const_16.S b/runtime/interpreter/mterp/arm64/op_const_16.S new file mode 100644 index 000000000..27f527313 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_const_16.S @@ -0,0 +1,7 @@ + /* const/16 vAA, #+BBBB */ + FETCH_S w0, 1 // w0<- ssssBBBB (sign-extended + lsr w3, wINST, #8 // w3<- AA + FETCH_ADVANCE_INST 2 // advance xPC, load wINST + SET_VREG w0, w3 // vAA<- w0 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_const_4.S b/runtime/interpreter/mterp/arm64/op_const_4.S new file mode 100644 index 000000000..04cd4f81b --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_const_4.S @@ -0,0 +1,8 @@ + /* const/4 vA, #+B */ + lsl w1, wINST, #16 // w1<- Bxxx0000 + ubfx w0, wINST, #8, #4 // w0<- A + FETCH_ADVANCE_INST 1 // advance xPC, load wINST + asr w1, w1, #28 // w1<- sssssssB (sign-extended) + GET_INST_OPCODE ip // ip<- opcode from xINST + SET_VREG w1, w0 // fp[A]<- w1 + GOTO_OPCODE ip // execute next instruction diff --git a/runtime/interpreter/mterp/arm64/op_const_class.S b/runtime/interpreter/mterp/arm64/op_const_class.S new file mode 100644 index 000000000..971cfa08b --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_const_class.S @@ -0,0 +1,12 @@ + /* const/class vAA, Class//BBBB */ + EXPORT_PC + FETCH w0, 1 // w0<- BBBB + lsr w1, wINST, #8 // w1<- AA + add x2, xFP, #OFF_FP_SHADOWFRAME + mov x3, xSELF + bl MterpConstClass // (index, tgt_reg, shadow_frame, self) + PREFETCH_INST 2 + cbnz w0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_const_high16.S b/runtime/interpreter/mterp/arm64/op_const_high16.S new file mode 100644 index 000000000..dd51ce1eb --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_const_high16.S @@ -0,0 +1,8 @@ + /* const/high16 vAA, #+BBBB0000 */ + FETCH w0, 1 // r0<- 0000BBBB (zero-extended + lsr w3, wINST, #8 // r3<- AA + lsl w0, w0, #16 // r0<- BBBB0000 + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + SET_VREG w0, w3 // vAA<- r0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_const_string.S b/runtime/interpreter/mterp/arm64/op_const_string.S new file mode 100644 index 000000000..896f1e710 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_const_string.S @@ -0,0 +1,12 @@ + /* const/string vAA, String//BBBB */ + EXPORT_PC + FETCH w0, 1 // w0<- BBBB + lsr w1, wINST, #8 // w1<- AA + add x2, xFP, #OFF_FP_SHADOWFRAME + mov x3, xSELF + bl MterpConstString // (index, tgt_reg, shadow_frame, self) + PREFETCH_INST 2 // load rINST + cbnz w0, MterpPossibleException // let reference interpreter deal with it. + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_const_string_jumbo.S b/runtime/interpreter/mterp/arm64/op_const_string_jumbo.S new file mode 100644 index 000000000..e1a733987 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_const_string_jumbo.S @@ -0,0 +1,14 @@ + /* const/string vAA, String//BBBBBBBB */ + EXPORT_PC + FETCH w0, 1 // w0<- bbbb (low + FETCH w2, 2 // w2<- BBBB (high + lsr w1, wINST, #8 // w1<- AA + orr w0, w0, w2, lsl #16 // w1<- BBBBbbbb + add x2, xFP, #OFF_FP_SHADOWFRAME + mov x3, xSELF + bl MterpConstString // (index, tgt_reg, shadow_frame, self) + PREFETCH_INST 3 // advance rPC + cbnz w0, MterpPossibleException // let reference interpreter deal with it. + ADVANCE 3 // advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_const_wide.S b/runtime/interpreter/mterp/arm64/op_const_wide.S new file mode 100644 index 000000000..8f57ddacf --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_const_wide.S @@ -0,0 +1,13 @@ + /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ + FETCH w0, 1 // w0<- bbbb (low) + FETCH w1, 2 // w1<- BBBB (low middle) + FETCH w2, 3 // w2<- hhhh (high middle) + FETCH w3, 4 // w3<- HHHH (high) + lsr w4, wINST, #8 // r4<- AA + FETCH_ADVANCE_INST 5 // advance rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb + orr x0, x0, x2, lsl #32 // w0<- hhhhBBBBbbbb + orr x0, x0, x3, lsl #48 // w0<- HHHHhhhhBBBBbbbb + SET_VREG_WIDE x0, w4 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_const_wide_16.S b/runtime/interpreter/mterp/arm64/op_const_wide_16.S new file mode 100644 index 000000000..e43628bcc --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_const_wide_16.S @@ -0,0 +1,8 @@ + /* const-wide/16 vAA, #+BBBB */ + FETCH_S w0, 1 // w0<- ssssBBBB (sign-extended + lsr w3, wINST, #8 // w3<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + sbfm x0, x0, 0, 31 + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w3 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_const_wide_32.S b/runtime/interpreter/mterp/arm64/op_const_wide_32.S new file mode 100644 index 000000000..527f7d816 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_const_wide_32.S @@ -0,0 +1,10 @@ + /* const-wide/32 vAA, #+BBBBbbbb */ + FETCH w0, 1 // w0<- 0000bbbb (low) + lsr w3, wINST, #8 // w3<- AA + FETCH_S w2, 2 // w2<- ssssBBBB (high) + FETCH_ADVANCE_INST 3 // advance rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + orr w0, w0, w2, lsl #16 // w0<- BBBBbbbb + sbfm x0, x0, 0, 31 + SET_VREG_WIDE x0, w3 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_const_wide_high16.S b/runtime/interpreter/mterp/arm64/op_const_wide_high16.S new file mode 100644 index 000000000..94ab9876c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_const_wide_high16.S @@ -0,0 +1,8 @@ + /* const-wide/high16 vAA, #+BBBB000000000000 */ + FETCH w0, 1 // w0<- 0000BBBB (zero-extended) + lsr w1, wINST, #8 // w1<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + lsl x0, x0, #48 + SET_VREG_WIDE x0, w1 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_div_double.S b/runtime/interpreter/mterp/arm64/op_div_double.S new file mode 100644 index 000000000..1f7dad091 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_div_double.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"instr":"fdiv d0, d1, d2", "result":"d0", "r1":"d1", "r2":"d2"} diff --git a/runtime/interpreter/mterp/arm64/op_div_double_2addr.S b/runtime/interpreter/mterp/arm64/op_div_double_2addr.S new file mode 100644 index 000000000..414a17565 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_div_double_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"instr":"fdiv d0, d0, d1", "r0":"d0", "r1":"d1"} diff --git a/runtime/interpreter/mterp/arm64/op_div_float.S b/runtime/interpreter/mterp/arm64/op_div_float.S new file mode 100644 index 000000000..f24a26c09 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_div_float.S @@ -0,0 +1 @@ +%include "arm64/fbinop.S" {"instr":"fdiv s0, s0, s1"} diff --git a/runtime/interpreter/mterp/arm64/op_div_float_2addr.S b/runtime/interpreter/mterp/arm64/op_div_float_2addr.S new file mode 100644 index 000000000..2888049c9 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_div_float_2addr.S @@ -0,0 +1 @@ +%include "arm64/fbinop2addr.S" {"instr":"fdiv s2, s0, s1"} diff --git a/runtime/interpreter/mterp/arm64/op_div_int.S b/runtime/interpreter/mterp/arm64/op_div_int.S new file mode 100644 index 000000000..88371c08d --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_div_int.S @@ -0,0 +1 @@ +%include "arm64/binop.S" {"instr":"sdiv w0, w0, w1", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_div_int_2addr.S b/runtime/interpreter/mterp/arm64/op_div_int_2addr.S new file mode 100644 index 000000000..5f5a80fe5 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_div_int_2addr.S @@ -0,0 +1 @@ +%include "arm64/binop2addr.S" {"instr":"sdiv w0, w0, w1", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_div_int_lit16.S b/runtime/interpreter/mterp/arm64/op_div_int_lit16.S new file mode 100644 index 000000000..dc7a484c6 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_div_int_lit16.S @@ -0,0 +1 @@ +%include "arm64/binopLit16.S" {"instr":"sdiv w0, w0, w1", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_div_int_lit8.S b/runtime/interpreter/mterp/arm64/op_div_int_lit8.S new file mode 100644 index 000000000..c06521c4b --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_div_int_lit8.S @@ -0,0 +1 @@ +%include "arm64/binopLit8.S" {"instr":"sdiv w0, w0, w1", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_div_long.S b/runtime/interpreter/mterp/arm64/op_div_long.S new file mode 100644 index 000000000..820ae3db6 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_div_long.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"instr":"sdiv x0, x1, x2", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_div_long_2addr.S b/runtime/interpreter/mterp/arm64/op_div_long_2addr.S new file mode 100644 index 000000000..da7eabdc9 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_div_long_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"instr":"sdiv x0, x0, x1", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_double_to_float.S b/runtime/interpreter/mterp/arm64/op_double_to_float.S new file mode 100644 index 000000000..c1555fdaf --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_double_to_float.S @@ -0,0 +1 @@ +%include "arm64/funopNarrower.S" {"instr":"fcvt s0, d0", "srcreg":"d0", "tgtreg":"s0"} diff --git a/runtime/interpreter/mterp/arm64/op_double_to_int.S b/runtime/interpreter/mterp/arm64/op_double_to_int.S new file mode 100644 index 000000000..7244bac2f --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_double_to_int.S @@ -0,0 +1 @@ +%include "arm64/funopNarrower.S" {"instr":"fcvtzs w0, d0", "srcreg":"d0", "tgtreg":"w0"} diff --git a/runtime/interpreter/mterp/arm64/op_double_to_long.S b/runtime/interpreter/mterp/arm64/op_double_to_long.S new file mode 100644 index 000000000..741160b56 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_double_to_long.S @@ -0,0 +1 @@ +%include "arm64/funopWide.S" {"instr":"fcvtzs x0, d0", "srcreg":"d0", "tgtreg":"x0"} diff --git a/runtime/interpreter/mterp/arm64/op_fill_array_data.S b/runtime/interpreter/mterp/arm64/op_fill_array_data.S new file mode 100644 index 000000000..f50d9e40a --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_fill_array_data.S @@ -0,0 +1,13 @@ + /* fill-array-data vAA, +BBBBBBBB */ + EXPORT_PC + FETCH w0, 1 // w0<- bbbb (lo) + FETCH w1, 2 // w1<- BBBB (hi) + lsr w3, wINST, #8 // w3<- AA + orr w1, w0, w1, lsl #16 // w1<- BBBBbbbb + GET_VREG w0, w3 // w0<- vAA (array object) + add x1, xPC, w1, lsl #1 // w1<- PC + BBBBbbbb*2 (array data off.) + bl MterpFillArrayData // (obj, payload) + cbz w0, MterpPossibleException // exception? + FETCH_ADVANCE_INST 3 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_filled_new_array.S b/runtime/interpreter/mterp/arm64/op_filled_new_array.S new file mode 100644 index 000000000..806a1b120 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_filled_new_array.S @@ -0,0 +1,18 @@ +%default { "helper":"MterpFilledNewArray" } + /* + * Create a new array with elements filled from registers. + * + * for: filled-new-array, filled-new-array/range + */ + /* op vB, {vD, vE, vF, vG, vA}, class//CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, type//BBBB */ + .extern $helper + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov x2, xSELF + bl $helper + cbz w0, MterpPossibleException + FETCH_ADVANCE_INST 3 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_filled_new_array_range.S b/runtime/interpreter/mterp/arm64/op_filled_new_array_range.S new file mode 100644 index 000000000..3c9a41962 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_filled_new_array_range.S @@ -0,0 +1 @@ +%include "arm64/op_filled_new_array.S" { "helper":"MterpFilledNewArrayRange" } diff --git a/runtime/interpreter/mterp/arm64/op_float_to_double.S b/runtime/interpreter/mterp/arm64/op_float_to_double.S new file mode 100644 index 000000000..892feca21 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_float_to_double.S @@ -0,0 +1 @@ +%include "arm64/funopWider.S" {"instr":"fcvt d0, s0", "srcreg":"s0", "tgtreg":"d0"} diff --git a/runtime/interpreter/mterp/arm64/op_float_to_int.S b/runtime/interpreter/mterp/arm64/op_float_to_int.S new file mode 100644 index 000000000..c849d8165 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_float_to_int.S @@ -0,0 +1 @@ +%include "arm64/funopNarrow.S" {"instr":"fcvtzs w0, s0", "srcreg":"s0", "tgtreg":"w0"} diff --git a/runtime/interpreter/mterp/arm64/op_float_to_long.S b/runtime/interpreter/mterp/arm64/op_float_to_long.S new file mode 100644 index 000000000..c3de16f9f --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_float_to_long.S @@ -0,0 +1 @@ +%include "arm64/funopWider.S" {"instr":"fcvtzs x0, s0", "srcreg":"s0", "tgtreg":"x0"} diff --git a/runtime/interpreter/mterp/arm64/op_goto.S b/runtime/interpreter/mterp/arm64/op_goto.S new file mode 100644 index 000000000..db98a45fa --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_goto.S @@ -0,0 +1,28 @@ + /* + * Unconditional branch, 8-bit offset. + * + * The branch distance is a signed code-unit offset, which we need to + * double to get a byte offset. + */ + /* goto +AA */ + /* tuning: use sbfx for 6t2+ targets */ +#if MTERP_SUSPEND + mov w0, wINST, lsl #16 // w0<- AAxx0000 + movs w1, w0, asr #24 // w1<- ssssssAA (sign-extended) + add w2, w1, w1 // w2<- byte offset, set flags + // If backwards branch refresh rIBASE + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh handler base + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] // Preload flags for MterpCheckSuspendAndContinue + lsl w0, wINST, #16 // w0<- AAxx0000 + asr w0, w0, #24 // w0<- ssssssAA (sign-extended) + adds w1, w0, w0 // Convert dalvik offset to byte offset, setting flags + FETCH_ADVANCE_INST_RB w1 // load wINST and advance xPC + // If backwards branch refresh rIBASE + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif diff --git a/runtime/interpreter/mterp/arm64/op_goto_16.S b/runtime/interpreter/mterp/arm64/op_goto_16.S new file mode 100644 index 000000000..ff66a23c4 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_goto_16.S @@ -0,0 +1,23 @@ + /* + * Unconditional branch, 16-bit offset. + * + * The branch distance is a signed code-unit offset, which we need to + * double to get a byte offset. + */ + /* goto/16 +AAAA */ +#if MTERP_SUSPEND + FETCH_S w0, 1 // w0<- ssssAAAA (sign-extended) + adds w1, w0, w0 // w1<- byte offset, flags set + FETCH_ADVANCE_INST_RB w1 // update rPC, load rINST + ldrmi xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh handler base + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction +#else + FETCH_S w0, 1 // w0<- ssssAAAA (sign-extended) + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + adds w1, w0, w0 // w1<- byte offset, flags set + FETCH_ADVANCE_INST_RB w1 // update rPC, load rINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction +#endif diff --git a/runtime/interpreter/mterp/arm64/op_goto_32.S b/runtime/interpreter/mterp/arm64/op_goto_32.S new file mode 100644 index 000000000..8a6980ece --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_goto_32.S @@ -0,0 +1,32 @@ + /* + * Unconditional branch, 32-bit offset. + * + * The branch distance is a signed code-unit offset, which we need to + * double to get a byte offset. + * + * Unlike most opcodes, this one is allowed to branch to itself, so + * our "backward branch" test must be "<=0" instead of "<0". Because + * we need the V bit set, we'll use an adds to convert from Dalvik + * offset to byte offset. + */ + /* goto/32 +AAAAAAAA */ +#if MTERP_SUSPEND + FETCH w0, 1 // w0<- aaaa (lo) + FETCH w1, 2 // w1<- AAAA (hi) + orr w0, w0, w1, lsl #16 // w0<- AAAAaaaa + adds w1, w0, w0 // w1<- byte offset + FETCH_ADVANCE_INST_RB w1 // update rPC, load xINST + ldrle xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh handler base + GET_INST_OPCODE ip // extract opcode from xINST + GOTO_OPCODE ip // jump to next instruction +#else + FETCH w0, 1 // w0<- aaaa (lo) + FETCH w1, 2 // w1<- AAAA (hi) + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + orr w0, w0, w1, lsl #16 // w0<- AAAAaaaa + adds w1, w0, w0 // w1<- byte offset + FETCH_ADVANCE_INST_RB w1 // update rPC, load xINST + b.le MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from xINST + GOTO_OPCODE ip // jump to next instruction +#endif diff --git a/runtime/interpreter/mterp/arm64/op_if_eq.S b/runtime/interpreter/mterp/arm64/op_if_eq.S new file mode 100644 index 000000000..aa4a0f16a --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_eq.S @@ -0,0 +1 @@ +%include "arm64/bincmp.S" { "condition":"eq" } diff --git a/runtime/interpreter/mterp/arm64/op_if_eqz.S b/runtime/interpreter/mterp/arm64/op_if_eqz.S new file mode 100644 index 000000000..1d3202e16 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_eqz.S @@ -0,0 +1 @@ +%include "arm64/zcmp.S" { "condition":"eq" } diff --git a/runtime/interpreter/mterp/arm64/op_if_ge.S b/runtime/interpreter/mterp/arm64/op_if_ge.S new file mode 100644 index 000000000..d6ec761bf --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_ge.S @@ -0,0 +1 @@ +%include "arm64/bincmp.S" { "condition":"ge" } diff --git a/runtime/interpreter/mterp/arm64/op_if_gez.S b/runtime/interpreter/mterp/arm64/op_if_gez.S new file mode 100644 index 000000000..8e3abd355 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_gez.S @@ -0,0 +1 @@ +%include "arm64/zcmp.S" { "condition":"ge" } diff --git a/runtime/interpreter/mterp/arm64/op_if_gt.S b/runtime/interpreter/mterp/arm64/op_if_gt.S new file mode 100644 index 000000000..7db8e9d91 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_gt.S @@ -0,0 +1 @@ +%include "arm64/bincmp.S" { "condition":"gt" } diff --git a/runtime/interpreter/mterp/arm64/op_if_gtz.S b/runtime/interpreter/mterp/arm64/op_if_gtz.S new file mode 100644 index 000000000..a4f2f6b66 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_gtz.S @@ -0,0 +1 @@ +%include "arm64/zcmp.S" { "condition":"gt" } diff --git a/runtime/interpreter/mterp/arm64/op_if_le.S b/runtime/interpreter/mterp/arm64/op_if_le.S new file mode 100644 index 000000000..ca3a83fff --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_le.S @@ -0,0 +1 @@ +%include "arm64/bincmp.S" { "condition":"le" } diff --git a/runtime/interpreter/mterp/arm64/op_if_lez.S b/runtime/interpreter/mterp/arm64/op_if_lez.S new file mode 100644 index 000000000..c1425fddc --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_lez.S @@ -0,0 +1 @@ +%include "arm64/zcmp.S" { "condition":"le" } diff --git a/runtime/interpreter/mterp/arm64/op_if_lt.S b/runtime/interpreter/mterp/arm64/op_if_lt.S new file mode 100644 index 000000000..56450a15c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_lt.S @@ -0,0 +1 @@ +%include "arm64/bincmp.S" { "condition":"lt" } diff --git a/runtime/interpreter/mterp/arm64/op_if_ltz.S b/runtime/interpreter/mterp/arm64/op_if_ltz.S new file mode 100644 index 000000000..03cd3d697 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_ltz.S @@ -0,0 +1 @@ +%include "arm64/zcmp.S" { "condition":"lt" } diff --git a/runtime/interpreter/mterp/arm64/op_if_ne.S b/runtime/interpreter/mterp/arm64/op_if_ne.S new file mode 100644 index 000000000..14d9e13dc --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_ne.S @@ -0,0 +1 @@ +%include "arm64/bincmp.S" { "condition":"ne" } diff --git a/runtime/interpreter/mterp/arm64/op_if_nez.S b/runtime/interpreter/mterp/arm64/op_if_nez.S new file mode 100644 index 000000000..21e1bc217 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_if_nez.S @@ -0,0 +1 @@ +%include "arm64/zcmp.S" { "condition":"ne" } diff --git a/runtime/interpreter/mterp/arm64/op_iget.S b/runtime/interpreter/mterp/arm64/op_iget.S new file mode 100644 index 000000000..165c7308e --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget.S @@ -0,0 +1,25 @@ +%default { "is_object":"0", "helper":"artGet32InstanceFromCode"} + /* + * General instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer + mov x3, xSELF // w3<- self + bl $helper + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + ubfx w2, wINST, #8, #4 // w2<- A + PREFETCH_INST 2 + cbnz x3, MterpPossibleException // bail out + .if $is_object + SET_VREG_OBJECT w0, w2 // fp[A]<- w0 + .else + SET_VREG w0, w2 // fp[A]<- w0 + .endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_iget_boolean.S b/runtime/interpreter/mterp/arm64/op_iget_boolean.S new file mode 100644 index 000000000..36a9b6beb --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_boolean.S @@ -0,0 +1 @@ +%include "arm64/op_iget.S" { "helper":"artGetBooleanInstanceFromCode", "extend":"uxtb w0, w0" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_boolean_quick.S b/runtime/interpreter/mterp/arm64/op_iget_boolean_quick.S new file mode 100644 index 000000000..2ceccb9ef --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_boolean_quick.S @@ -0,0 +1 @@ +%include "arm64/op_iget_quick.S" { "load":"ldrb" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_byte.S b/runtime/interpreter/mterp/arm64/op_iget_byte.S new file mode 100644 index 000000000..fd3f16451 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_byte.S @@ -0,0 +1 @@ +%include "arm64/op_iget.S" { "helper":"artGetByteInstanceFromCode", "extend":"sxtb w0, w0" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_byte_quick.S b/runtime/interpreter/mterp/arm64/op_iget_byte_quick.S new file mode 100644 index 000000000..6e97b7218 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_byte_quick.S @@ -0,0 +1 @@ +%include "arm64/op_iget_quick.S" { "load":"ldrsb" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_char.S b/runtime/interpreter/mterp/arm64/op_iget_char.S new file mode 100644 index 000000000..ea2327522 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_char.S @@ -0,0 +1 @@ +%include "arm64/op_iget.S" { "helper":"artGetCharInstanceFromCode", "extend":"uxth w0, w0" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_char_quick.S b/runtime/interpreter/mterp/arm64/op_iget_char_quick.S new file mode 100644 index 000000000..325dd1cf9 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_char_quick.S @@ -0,0 +1 @@ +%include "arm64/op_iget_quick.S" { "load":"ldrh" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_object.S b/runtime/interpreter/mterp/arm64/op_iget_object.S new file mode 100644 index 000000000..03be78d2a --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_object.S @@ -0,0 +1 @@ +%include "arm64/op_iget.S" { "is_object":"1", "helper":"artGetObjInstanceFromCode" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_object_quick.S b/runtime/interpreter/mterp/arm64/op_iget_object_quick.S new file mode 100644 index 000000000..e9a797dfe --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_object_quick.S @@ -0,0 +1,15 @@ + /* For: iget-object-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + EXPORT_PC + GET_VREG w0, w2 // w0<- object we're operating on + bl artIGetObjectFromMterp // (obj, offset) + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + ubfx w2, wINST, #8, #4 // w2<- A + PREFETCH_INST 2 + cbnz w3, MterpPossibleException // bail out + SET_VREG_OBJECT w0, w2 // fp[A]<- w0 + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_iget_quick.S b/runtime/interpreter/mterp/arm64/op_iget_quick.S new file mode 100644 index 000000000..45c68a3a7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_quick.S @@ -0,0 +1,15 @@ +%default { "load":"ldr", "extend":"" } + /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- object we're operating on + ubfx w2, wINST, #8, #4 // w2<- A + cmp x3, #0 // check object for null + beq common_errNullObject // object was null + $load w0, [x3, x1] // w0<- obj.field + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + $extend + SET_VREG w0, w2 // fp[A]<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_iget_short.S b/runtime/interpreter/mterp/arm64/op_iget_short.S new file mode 100644 index 000000000..c347542f0 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_short.S @@ -0,0 +1 @@ +%include "arm64/op_iget.S" { "helper":"artGetShortInstanceFromCode", "extend":"sxth w0, w0" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_short_quick.S b/runtime/interpreter/mterp/arm64/op_iget_short_quick.S new file mode 100644 index 000000000..83670701c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_short_quick.S @@ -0,0 +1 @@ +%include "arm64/op_iget_quick.S" { "load":"ldrsh" } diff --git a/runtime/interpreter/mterp/arm64/op_iget_wide.S b/runtime/interpreter/mterp/arm64/op_iget_wide.S new file mode 100644 index 000000000..9718390c3 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_wide.S @@ -0,0 +1,21 @@ + /* + * 64-bit instance field get. + * + * for: iget-wide + */ + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer + mov x3, xSELF // w3<- self + bl artGet64InstanceFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + ubfx w2, wINST, #8, #4 // w2<- A + PREFETCH_INST 2 + cmp w3, #0 + cbnz w3, MterpException // bail out + SET_VREG_WIDE x0, w2 + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_iget_wide_quick.S b/runtime/interpreter/mterp/arm64/op_iget_wide_quick.S new file mode 100644 index 000000000..2480d2d22 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iget_wide_quick.S @@ -0,0 +1,12 @@ + /* iget-wide-quick vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w4, 1 // w4<- field byte offset + GET_VREG w3, w2 // w3<- object we're operating on + ubfx w2, wINST, #8, #4 // w2<- A + cbz w3, common_errNullObject // object was null + add x4, x3, x4 // create direct pointer + ldr x0, [x4] + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + SET_VREG_WIDE x0, w2 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_instance_of.S b/runtime/interpreter/mterp/arm64/op_instance_of.S new file mode 100644 index 000000000..647bc75cf --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_instance_of.S @@ -0,0 +1,23 @@ + /* + * Check to see if an object reference is an instance of a class. + * + * Most common situation is a non-null object, being compared against + * an already-resolved class. + */ + /* instance-of vA, vB, class//CCCC */ + EXPORT_PC + FETCH w0, 1 // w0<- CCCC + lsr w1, wINST, #12 // w1<- B + VREG_INDEX_TO_ADDR x1, w1 // w1<- &object + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- method + mov x3, xSELF // w3<- self + bl MterpInstanceOf // (index, &obj, method, self) + ldr x1, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w2, wINST, #8 // w2<- A+ + and w2, w2, #15 // w2<- A + PREFETCH_INST 2 + cbnz x1, MterpException + ADVANCE 2 // advance rPC + SET_VREG w0, w2 // vA<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_int_to_byte.S b/runtime/interpreter/mterp/arm64/op_int_to_byte.S new file mode 100644 index 000000000..43f814820 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_int_to_byte.S @@ -0,0 +1 @@ +%include "arm64/unop.S" {"instr":"sxtb w0, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_int_to_char.S b/runtime/interpreter/mterp/arm64/op_int_to_char.S new file mode 100644 index 000000000..f09217068 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_int_to_char.S @@ -0,0 +1 @@ +%include "arm64/unop.S" {"instr":"uxth w0, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_int_to_double.S b/runtime/interpreter/mterp/arm64/op_int_to_double.S new file mode 100644 index 000000000..3dee75a14 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_int_to_double.S @@ -0,0 +1 @@ +%include "arm64/funopWider.S" {"instr":"scvtf d0, w0", "srcreg":"w0", "tgtreg":"d0"} diff --git a/runtime/interpreter/mterp/arm64/op_int_to_float.S b/runtime/interpreter/mterp/arm64/op_int_to_float.S new file mode 100644 index 000000000..3ebbdc7cb --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_int_to_float.S @@ -0,0 +1 @@ +%include "arm64/funopNarrow.S" {"instr":"scvtf s0, w0", "srcreg":"w0", "tgtreg":"s0"} diff --git a/runtime/interpreter/mterp/arm64/op_int_to_long.S b/runtime/interpreter/mterp/arm64/op_int_to_long.S new file mode 100644 index 000000000..13d212039 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_int_to_long.S @@ -0,0 +1 @@ +%include "arm64/funopWider.S" {"instr":"sbfm x0, x0, 0, 31", "srcreg":"w0", "tgtreg":"x0"} diff --git a/runtime/interpreter/mterp/arm64/op_int_to_short.S b/runtime/interpreter/mterp/arm64/op_int_to_short.S new file mode 100644 index 000000000..87fb80466 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_int_to_short.S @@ -0,0 +1 @@ +%include "arm64/unop.S" {"instr":"sxth w0, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_invoke_direct.S b/runtime/interpreter/mterp/arm64/op_invoke_direct.S new file mode 100644 index 000000000..c117232d9 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_direct.S @@ -0,0 +1 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeDirect" } diff --git a/runtime/interpreter/mterp/arm64/op_invoke_direct_range.S b/runtime/interpreter/mterp/arm64/op_invoke_direct_range.S new file mode 100644 index 000000000..efc54c71d --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_direct_range.S @@ -0,0 +1 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeDirectRange" } diff --git a/runtime/interpreter/mterp/arm64/op_invoke_interface.S b/runtime/interpreter/mterp/arm64/op_invoke_interface.S new file mode 100644 index 000000000..12dfa592d --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_interface.S @@ -0,0 +1,8 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeInterface" } + /* + * Handle an interface method call. + * + * for: invoke-interface, invoke-interface/range + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ diff --git a/runtime/interpreter/mterp/arm64/op_invoke_interface_range.S b/runtime/interpreter/mterp/arm64/op_invoke_interface_range.S new file mode 100644 index 000000000..61caaf47e --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_interface_range.S @@ -0,0 +1 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeInterfaceRange" } diff --git a/runtime/interpreter/mterp/arm64/op_invoke_static.S b/runtime/interpreter/mterp/arm64/op_invoke_static.S new file mode 100644 index 000000000..634eda273 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_static.S @@ -0,0 +1,2 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeStatic" } + diff --git a/runtime/interpreter/mterp/arm64/op_invoke_static_range.S b/runtime/interpreter/mterp/arm64/op_invoke_static_range.S new file mode 100644 index 000000000..32cdcddaa --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_static_range.S @@ -0,0 +1 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeStaticRange" } diff --git a/runtime/interpreter/mterp/arm64/op_invoke_super.S b/runtime/interpreter/mterp/arm64/op_invoke_super.S new file mode 100644 index 000000000..def2c552f --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_super.S @@ -0,0 +1,8 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeSuper" } + /* + * Handle a "super" method call. + * + * for: invoke-super, invoke-super/range + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ diff --git a/runtime/interpreter/mterp/arm64/op_invoke_super_range.S b/runtime/interpreter/mterp/arm64/op_invoke_super_range.S new file mode 100644 index 000000000..27fb8591a --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_super_range.S @@ -0,0 +1 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeSuperRange" } diff --git a/runtime/interpreter/mterp/arm64/op_invoke_virtual.S b/runtime/interpreter/mterp/arm64/op_invoke_virtual.S new file mode 100644 index 000000000..66d050217 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_virtual.S @@ -0,0 +1,8 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeVirtual" } + /* + * Handle a virtual method call. + * + * for: invoke-virtual, invoke-virtual/range + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ diff --git a/runtime/interpreter/mterp/arm64/op_invoke_virtual_quick.S b/runtime/interpreter/mterp/arm64/op_invoke_virtual_quick.S new file mode 100644 index 000000000..4300c3464 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_virtual_quick.S @@ -0,0 +1 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeVirtualQuick" } diff --git a/runtime/interpreter/mterp/arm64/op_invoke_virtual_range.S b/runtime/interpreter/mterp/arm64/op_invoke_virtual_range.S new file mode 100644 index 000000000..b43955c6d --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_virtual_range.S @@ -0,0 +1 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeVirtualRange" } diff --git a/runtime/interpreter/mterp/arm64/op_invoke_virtual_range_quick.S b/runtime/interpreter/mterp/arm64/op_invoke_virtual_range_quick.S new file mode 100644 index 000000000..90c7b6574 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_invoke_virtual_range_quick.S @@ -0,0 +1 @@ +%include "arm64/invoke.S" { "helper":"MterpInvokeVirtualQuickRange" } diff --git a/runtime/interpreter/mterp/arm64/op_iput.S b/runtime/interpreter/mterp/arm64/op_iput.S new file mode 100644 index 000000000..a8c0e61a8 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput.S @@ -0,0 +1,21 @@ +%default { "is_object":"0", "handler":"artSet32InstanceFromMterp" } + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op vA, vB, field//CCCC */ + .extern $handler + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w2, w2 // w2<- fp[A] + ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer + PREFETCH_INST 2 + bl $handler + cbnz w0, MterpPossibleException + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_iput_boolean.S b/runtime/interpreter/mterp/arm64/op_iput_boolean.S new file mode 100644 index 000000000..bbf53192c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_boolean.S @@ -0,0 +1 @@ +%include "arm64/op_iput.S" { "handler":"artSet8InstanceFromMterp" } diff --git a/runtime/interpreter/mterp/arm64/op_iput_boolean_quick.S b/runtime/interpreter/mterp/arm64/op_iput_boolean_quick.S new file mode 100644 index 000000000..25c61d7c2 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_boolean_quick.S @@ -0,0 +1 @@ +%include "arm64/op_iput_quick.S" { "store":"strb" } diff --git a/runtime/interpreter/mterp/arm64/op_iput_byte.S b/runtime/interpreter/mterp/arm64/op_iput_byte.S new file mode 100644 index 000000000..bbf53192c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_byte.S @@ -0,0 +1 @@ +%include "arm64/op_iput.S" { "handler":"artSet8InstanceFromMterp" } diff --git a/runtime/interpreter/mterp/arm64/op_iput_byte_quick.S b/runtime/interpreter/mterp/arm64/op_iput_byte_quick.S new file mode 100644 index 000000000..25c61d7c2 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_byte_quick.S @@ -0,0 +1 @@ +%include "arm64/op_iput_quick.S" { "store":"strb" } diff --git a/runtime/interpreter/mterp/arm64/op_iput_char.S b/runtime/interpreter/mterp/arm64/op_iput_char.S new file mode 100644 index 000000000..150d8794c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_char.S @@ -0,0 +1 @@ +%include "arm64/op_iput.S" { "handler":"artSet16InstanceFromMterp" } diff --git a/runtime/interpreter/mterp/arm64/op_iput_char_quick.S b/runtime/interpreter/mterp/arm64/op_iput_char_quick.S new file mode 100644 index 000000000..c6ef46ab8 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_char_quick.S @@ -0,0 +1 @@ +%include "arm64/op_iput_quick.S" { "store":"strh" } diff --git a/runtime/interpreter/mterp/arm64/op_iput_object.S b/runtime/interpreter/mterp/arm64/op_iput_object.S new file mode 100644 index 000000000..37a649be6 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_object.S @@ -0,0 +1,10 @@ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov w2, wINST + mov x3, xSELF + bl MterpIputObject + cbz w0, MterpException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_iput_object_quick.S b/runtime/interpreter/mterp/arm64/op_iput_object_quick.S new file mode 100644 index 000000000..6fbf2b1da --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_object_quick.S @@ -0,0 +1,9 @@ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov w2, wINST + bl MterpIputObjectQuick + cbz w0, MterpException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_iput_quick.S b/runtime/interpreter/mterp/arm64/op_iput_quick.S new file mode 100644 index 000000000..2afc51bee --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_quick.S @@ -0,0 +1,14 @@ +%default { "store":"str" } + /* For: iput-quick, iput-object-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + cmp w3, #0 // check object for null + cbz w3, common_errNullObject // object was null + GET_VREG w0, w2 // w0<- fp[A] + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + $store w0, [x3, x1] // obj.field<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_iput_short.S b/runtime/interpreter/mterp/arm64/op_iput_short.S new file mode 100644 index 000000000..150d8794c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_short.S @@ -0,0 +1 @@ +%include "arm64/op_iput.S" { "handler":"artSet16InstanceFromMterp" } diff --git a/runtime/interpreter/mterp/arm64/op_iput_short_quick.S b/runtime/interpreter/mterp/arm64/op_iput_short_quick.S new file mode 100644 index 000000000..c6ef46ab8 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_short_quick.S @@ -0,0 +1 @@ +%include "arm64/op_iput_quick.S" { "store":"strh" } diff --git a/runtime/interpreter/mterp/arm64/op_iput_wide.S b/runtime/interpreter/mterp/arm64/op_iput_wide.S new file mode 100644 index 000000000..4ce95251f --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_wide.S @@ -0,0 +1,15 @@ + /* iput-wide vA, vB, field//CCCC */ + .extern artSet64InstanceFromMterp + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + add x2, xFP, x2, lsl #2 // w2<- &fp[A] + ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer + PREFETCH_INST 2 + bl artSet64InstanceFromMterp + cbnz w0, MterpPossibleException + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_iput_wide_quick.S b/runtime/interpreter/mterp/arm64/op_iput_wide_quick.S new file mode 100644 index 000000000..27b5dc57b --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_iput_wide_quick.S @@ -0,0 +1,13 @@ + /* iput-wide-quick vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w3, 1 // w3<- field byte offset + GET_VREG w2, w2 // w2<- fp[B], the object pointer + ubfx w0, wINST, #8, #4 // w0<- A + cmp w2, #0 // check object for null + beq common_errNullObject // object was null + GET_VREG_WIDE x0, w0 // x0-< fp[A] + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + add x1, x2, x3 // create a direct pointer + str x0, [x1] + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_long_to_double.S b/runtime/interpreter/mterp/arm64/op_long_to_double.S new file mode 100644 index 000000000..a3f59c204 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_long_to_double.S @@ -0,0 +1 @@ +%include "arm64/funopWide.S" {"instr":"scvtf d0, x0", "srcreg":"x0", "tgtreg":"d0"} diff --git a/runtime/interpreter/mterp/arm64/op_long_to_float.S b/runtime/interpreter/mterp/arm64/op_long_to_float.S new file mode 100644 index 000000000..e9c9145ce --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_long_to_float.S @@ -0,0 +1 @@ +%include "arm64/funopNarrower.S" {"instr":"scvtf s0, x0", "srcreg":"x0", "tgtreg":"s0"} diff --git a/runtime/interpreter/mterp/arm64/op_long_to_int.S b/runtime/interpreter/mterp/arm64/op_long_to_int.S new file mode 100644 index 000000000..360a69b90 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_long_to_int.S @@ -0,0 +1 @@ +%include "arm64/funopNarrower.S" {"instr":"", "srcreg":"x0", "tgtreg":"w0"} diff --git a/runtime/interpreter/mterp/arm64/op_monitor_enter.S b/runtime/interpreter/mterp/arm64/op_monitor_enter.S new file mode 100644 index 000000000..6fbd9ae72 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_monitor_enter.S @@ -0,0 +1,13 @@ + /* + * Synchronize on an object. + */ + /* monitor-enter vAA */ + EXPORT_PC + lsr w2, wINST, #8 // w2<- AA + GET_VREG w0, w2 // w0<- vAA (object) + mov x1, xSELF // w1<- self + bl artLockObjectFromCode + cbnz w0, MterpException + FETCH_ADVANCE_INST 1 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_monitor_exit.S b/runtime/interpreter/mterp/arm64/op_monitor_exit.S new file mode 100644 index 000000000..26e2d8d7b --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_monitor_exit.S @@ -0,0 +1,17 @@ + /* + * Unlock an object. + * + * Exceptions that occur when unlocking a monitor need to appear as + * if they happened at the following instruction. See the Dalvik + * instruction spec. + */ + /* monitor-exit vAA */ + EXPORT_PC + lsr w2, wINST, #8 // w2<- AA + GET_VREG w0, w2 // w0<- vAA (object) + mov x1, xSELF // w0<- self + bl artUnlockObjectFromCode // w0<- success for unlock(self, obj) + cbnz w0, MterpException + FETCH_ADVANCE_INST 1 // before throw: advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_move.S b/runtime/interpreter/mterp/arm64/op_move.S new file mode 100644 index 000000000..195b7eb62 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move.S @@ -0,0 +1,14 @@ +%default { "is_object":"0" } + /* for move, move-object, long-to-int */ + /* op vA, vB */ + lsr w1, wINST, #12 // x1<- B from 15:12 + ubfx w0, wINST, #8, #4 // x0<- A from 11:8 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + GET_VREG w2, w1 // x2<- fp[B] + GET_INST_OPCODE ip // ip<- opcode from wINST + .if $is_object + SET_VREG_OBJECT w2, w0 // fp[A]<- x2 + .else + SET_VREG w2, w0 // fp[A]<- x2 + .endif + GOTO_OPCODE ip // execute next instruction diff --git a/runtime/interpreter/mterp/arm64/op_move_16.S b/runtime/interpreter/mterp/arm64/op_move_16.S new file mode 100644 index 000000000..5146e3d6e --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_16.S @@ -0,0 +1,14 @@ +%default { "is_object":"0" } + /* for: move/16, move-object/16 */ + /* op vAAAA, vBBBB */ + FETCH w1, 2 // w1<- BBBB + FETCH w0, 1 // w0<- AAAA + FETCH_ADVANCE_INST 3 // advance xPC, load xINST + GET_VREG w2, w1 // w2<- fp[BBBB] + GET_INST_OPCODE ip // extract opcode from xINST + .if $is_object + SET_VREG_OBJECT w2, w0 // fp[AAAA]<- w2 + .else + SET_VREG w2, w0 // fp[AAAA]<- w2 + .endif + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_move_exception.S b/runtime/interpreter/mterp/arm64/op_move_exception.S new file mode 100644 index 000000000..b29298fd1 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_exception.S @@ -0,0 +1,9 @@ + /* move-exception vAA */ + lsr w2, wINST, #8 // w2<- AA + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + mov x1, #0 // w1<- 0 + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + SET_VREG_OBJECT w3, w2 // fp[AA]<- exception obj + GET_INST_OPCODE ip // extract opcode from rINST + str x1, [xSELF, #THREAD_EXCEPTION_OFFSET] // clear exception + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_move_from16.S b/runtime/interpreter/mterp/arm64/op_move_from16.S new file mode 100644 index 000000000..78f344db6 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_from16.S @@ -0,0 +1,14 @@ +%default { "is_object":"0" } + /* for: move/from16, move-object/from16 */ + /* op vAA, vBBBB */ + FETCH w1, 1 // r1<- BBBB + lsr w0, wINST, #8 // r0<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + GET_VREG w2, w1 // r2<- fp[BBBB] + GET_INST_OPCODE ip // extract opcode from wINST + .if $is_object + SET_VREG_OBJECT w2, w0 // fp[AA]<- r2 + .else + SET_VREG w2, w0 // fp[AA]<- r2 + .endif + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_move_object.S b/runtime/interpreter/mterp/arm64/op_move_object.S new file mode 100644 index 000000000..a5adc59e8 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_object.S @@ -0,0 +1 @@ +%include "arm64/op_move.S" {"is_object":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_move_object_16.S b/runtime/interpreter/mterp/arm64/op_move_object_16.S new file mode 100644 index 000000000..ef86c4508 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_object_16.S @@ -0,0 +1 @@ +%include "arm64/op_move_16.S" {"is_object":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_move_object_from16.S b/runtime/interpreter/mterp/arm64/op_move_object_from16.S new file mode 100644 index 000000000..0c73b3b04 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_object_from16.S @@ -0,0 +1 @@ +%include "arm64/op_move_from16.S" {"is_object":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_move_result.S b/runtime/interpreter/mterp/arm64/op_move_result.S new file mode 100644 index 000000000..06fe96269 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_result.S @@ -0,0 +1,14 @@ +%default { "is_object":"0" } + /* for: move-result, move-result-object */ + /* op vAA */ + lsr w2, wINST, #8 // r2<- AA + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + ldr x0, [xFP, #OFF_FP_RESULT_REGISTER] // get pointer to result JType. + ldr w0, [x0] // r0 <- result.i. + GET_INST_OPCODE ip // extract opcode from wINST + .if $is_object + SET_VREG_OBJECT w0, w2, w1 // fp[AA]<- r0 + .else + SET_VREG w0, w2 // fp[AA]<- r0 + .endif + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_move_result_object.S b/runtime/interpreter/mterp/arm64/op_move_result_object.S new file mode 100644 index 000000000..da2bbee66 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_result_object.S @@ -0,0 +1 @@ +%include "arm64/op_move_result.S" {"is_object":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_move_result_wide.S b/runtime/interpreter/mterp/arm64/op_move_result_wide.S new file mode 100644 index 000000000..f90a33f01 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_result_wide.S @@ -0,0 +1,9 @@ + /* for: move-result-wide */ + /* op vAA */ + lsr w2, wINST, #8 // r2<- AA + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + ldr x0, [xFP, #OFF_FP_RESULT_REGISTER] // get pointer to result JType. + ldr x0, [x0] // r0 <- result.i. + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x0, x2 // fp[AA]<- r0 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_move_wide.S b/runtime/interpreter/mterp/arm64/op_move_wide.S new file mode 100644 index 000000000..538f07973 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_wide.S @@ -0,0 +1,9 @@ + /* move-wide vA, vB */ + /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ + lsr w3, wINST, #12 // w3<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE x3, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x3, w2 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_move_wide_16.S b/runtime/interpreter/mterp/arm64/op_move_wide_16.S new file mode 100644 index 000000000..c79cdc500 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_wide_16.S @@ -0,0 +1,9 @@ + /* move-wide/16 vAAAA, vBBBB */ + /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ + FETCH w3, 2 // w3<- BBBB + FETCH w2, 1 // w2<- AAAA + GET_VREG_WIDE x3, w3 + FETCH_ADVANCE_INST 3 // advance rPC, load rINST + SET_VREG_WIDE x3, w2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_move_wide_from16.S b/runtime/interpreter/mterp/arm64/op_move_wide_from16.S new file mode 100644 index 000000000..70dbe9903 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_move_wide_from16.S @@ -0,0 +1,9 @@ + /* move-wide/from16 vAA, vBBBB */ + /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ + FETCH w3, 1 // w3<- BBBB + lsr w2, wINST, #8 // w2<- AA + GET_VREG_WIDE x3, w3 + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x3, w2 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_mul_double.S b/runtime/interpreter/mterp/arm64/op_mul_double.S new file mode 100644 index 000000000..8d35b81b1 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_mul_double.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"instr":"fmul d0, d1, d2", "result":"d0", "r1":"d1", "r2":"d2"} diff --git a/runtime/interpreter/mterp/arm64/op_mul_double_2addr.S b/runtime/interpreter/mterp/arm64/op_mul_double_2addr.S new file mode 100644 index 000000000..526cb3bcc --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_mul_double_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"instr":"fmul d0, d0, d1", "r0":"d0", "r1":"d1"} diff --git a/runtime/interpreter/mterp/arm64/op_mul_float.S b/runtime/interpreter/mterp/arm64/op_mul_float.S new file mode 100644 index 000000000..eea7733db --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_mul_float.S @@ -0,0 +1 @@ +%include "arm64/fbinop.S" {"instr":"fmul s0, s0, s1"} diff --git a/runtime/interpreter/mterp/arm64/op_mul_float_2addr.S b/runtime/interpreter/mterp/arm64/op_mul_float_2addr.S new file mode 100644 index 000000000..c1f23765a --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_mul_float_2addr.S @@ -0,0 +1 @@ +%include "arm64/fbinop2addr.S" {"instr":"fmul s2, s0, s1"} diff --git a/runtime/interpreter/mterp/arm64/op_mul_int.S b/runtime/interpreter/mterp/arm64/op_mul_int.S new file mode 100644 index 000000000..d14cae12e --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_mul_int.S @@ -0,0 +1,2 @@ +/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ +%include "arm64/binop.S" {"instr":"mul w0, w1, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_mul_int_2addr.S b/runtime/interpreter/mterp/arm64/op_mul_int_2addr.S new file mode 100644 index 000000000..f07911817 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_mul_int_2addr.S @@ -0,0 +1,2 @@ +/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ +%include "arm64/binop2addr.S" {"instr":"mul w0, w1, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_mul_int_lit16.S b/runtime/interpreter/mterp/arm64/op_mul_int_lit16.S new file mode 100644 index 000000000..a37855954 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_mul_int_lit16.S @@ -0,0 +1,2 @@ +/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ +%include "arm64/binopLit16.S" {"instr":"mul w0, w1, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_mul_int_lit8.S b/runtime/interpreter/mterp/arm64/op_mul_int_lit8.S new file mode 100644 index 000000000..b3d40141a --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_mul_int_lit8.S @@ -0,0 +1,2 @@ +/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ +%include "arm64/binopLit8.S" {"instr":"mul w0, w1, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_mul_long.S b/runtime/interpreter/mterp/arm64/op_mul_long.S new file mode 100644 index 000000000..bc0dcbd14 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_mul_long.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"instr":"mul x0, x1, x2"} diff --git a/runtime/interpreter/mterp/arm64/op_mul_long_2addr.S b/runtime/interpreter/mterp/arm64/op_mul_long_2addr.S new file mode 100644 index 000000000..fa1cdf8a7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_mul_long_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"instr":"mul x0, x0, x1"} diff --git a/runtime/interpreter/mterp/arm64/op_neg_double.S b/runtime/interpreter/mterp/arm64/op_neg_double.S new file mode 100644 index 000000000..e9064c47c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_neg_double.S @@ -0,0 +1 @@ +%include "arm64/unopWide.S" {"preinstr":"mov x1, #0x8000000000000000", "instr":"add x0, x0, x1"} diff --git a/runtime/interpreter/mterp/arm64/op_neg_float.S b/runtime/interpreter/mterp/arm64/op_neg_float.S new file mode 100644 index 000000000..49d51afa5 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_neg_float.S @@ -0,0 +1 @@ +%include "arm64/unop.S" {"preinstr":"mov w4, #0x80000000", "instr":"add w0, w0, w4"} diff --git a/runtime/interpreter/mterp/arm64/op_neg_int.S b/runtime/interpreter/mterp/arm64/op_neg_int.S new file mode 100644 index 000000000..59c14a908 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_neg_int.S @@ -0,0 +1 @@ +%include "arm64/unop.S" {"instr":"sub w0, wzr, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_neg_long.S b/runtime/interpreter/mterp/arm64/op_neg_long.S new file mode 100644 index 000000000..0c71ea7de --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_neg_long.S @@ -0,0 +1 @@ +%include "arm64/unopWide.S" {"instr":"sub x0, xzr, x0"} diff --git a/runtime/interpreter/mterp/arm64/op_new_array.S b/runtime/interpreter/mterp/arm64/op_new_array.S new file mode 100644 index 000000000..886120a94 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_new_array.S @@ -0,0 +1,18 @@ + /* + * Allocate an array of objects, specified with the array class + * and a count. + * + * The verifier guarantees that this is an array class, so we don't + * check for it here. + */ + /* new-array vA, vB, class//CCCC */ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov w2, wINST + mov x3, xSELF + bl MterpNewArray + cbz w0, MterpPossibleException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_new_instance.S b/runtime/interpreter/mterp/arm64/op_new_instance.S new file mode 100644 index 000000000..c171ac58f --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_new_instance.S @@ -0,0 +1,13 @@ + /* + * Create a new instance of a class. + */ + /* new-instance vAA, class//BBBB */ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xSELF + mov w2, wINST + bl MterpNewInstance // (shadow_frame, self, inst_data) + cbz w0, MterpPossibleException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_nop.S b/runtime/interpreter/mterp/arm64/op_nop.S new file mode 100644 index 000000000..80c2d452f --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_nop.S @@ -0,0 +1,3 @@ + FETCH_ADVANCE_INST 1 // advance to next instr, load rINST + GET_INST_OPCODE ip // ip<- opcode from rINST + GOTO_OPCODE ip // execute it diff --git a/runtime/interpreter/mterp/arm64/op_not_int.S b/runtime/interpreter/mterp/arm64/op_not_int.S new file mode 100644 index 000000000..55d77502a --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_not_int.S @@ -0,0 +1 @@ +%include "arm64/unop.S" {"instr":"mvn w0, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_not_long.S b/runtime/interpreter/mterp/arm64/op_not_long.S new file mode 100644 index 000000000..e5ebdd6e6 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_not_long.S @@ -0,0 +1 @@ +%include "arm64/unopWide.S" {"instr":"mvn x0, x0"} diff --git a/runtime/interpreter/mterp/arm64/op_or_int.S b/runtime/interpreter/mterp/arm64/op_or_int.S new file mode 100644 index 000000000..648c1e685 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_or_int.S @@ -0,0 +1 @@ +%include "arm64/binop.S" {"instr":"orr w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_or_int_2addr.S b/runtime/interpreter/mterp/arm64/op_or_int_2addr.S new file mode 100644 index 000000000..abdf599fe --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_or_int_2addr.S @@ -0,0 +1 @@ +%include "arm64/binop2addr.S" {"instr":"orr w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_or_int_lit16.S b/runtime/interpreter/mterp/arm64/op_or_int_lit16.S new file mode 100644 index 000000000..db7f4ffb0 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_or_int_lit16.S @@ -0,0 +1 @@ +%include "arm64/binopLit16.S" {"instr":"orr w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_or_int_lit8.S b/runtime/interpreter/mterp/arm64/op_or_int_lit8.S new file mode 100644 index 000000000..51675f8b8 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_or_int_lit8.S @@ -0,0 +1 @@ +%include "arm64/binopLit8.S" {"instr":"orr w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_or_long.S b/runtime/interpreter/mterp/arm64/op_or_long.S new file mode 100644 index 000000000..dd137ce85 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_or_long.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"instr":"orr x0, x1, x2"} diff --git a/runtime/interpreter/mterp/arm64/op_or_long_2addr.S b/runtime/interpreter/mterp/arm64/op_or_long_2addr.S new file mode 100644 index 000000000..f785230e1 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_or_long_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"instr":"orr x0, x0, x1"} diff --git a/runtime/interpreter/mterp/arm64/op_packed_switch.S b/runtime/interpreter/mterp/arm64/op_packed_switch.S new file mode 100644 index 000000000..f087d23c0 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_packed_switch.S @@ -0,0 +1,39 @@ +%default { "func":"MterpDoPackedSwitch" } + /* + * Handle a packed-switch or sparse-switch instruction. In both cases + * we decode it and hand it off to a helper function. + * + * We don't really expect backward branches in a switch statement, but + * they're perfectly legal, so we check for them here. + * + * for: packed-switch, sparse-switch + */ + /* op vAA, +BBBB */ +#if MTERP_SUSPEND + FETCH w0, 1 // w0<- bbbb (lo) + FETCH w1, 2 // w1<- BBBB (hi) + mov w3, wINST, lsr #8 // w3<- AA + orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb + GET_VREG w1, w3 // w1<- vAA + add w0, rPC, w0, lsl #1 // w0<- PC + BBBBbbbb*2 + bl $func // w0<- code-unit branch offset + adds w1, w0, w0 // w1<- byte offset; clear V + ldrle rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh handler base + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + FETCH w0, 1 // w0<- bbbb (lo) + FETCH w1, 2 // w1<- BBBB (hi) + lsr w3, wINST, #8 // w3<- AA + orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb + GET_VREG w1, w3 // w1<- vAA + add x0, xPC, w0, lsl #1 // w0<- PC + BBBBbbbb*2 + bl $func // w0<- code-unit branch offset + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + adds w1, w0, w0 // w1<- byte offset; clear V + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + b.le MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif diff --git a/runtime/interpreter/mterp/arm64/op_rem_double.S b/runtime/interpreter/mterp/arm64/op_rem_double.S new file mode 100644 index 000000000..c631ddbfe --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rem_double.S @@ -0,0 +1,13 @@ + /* rem vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE d1, w2 // d1<- vCC + GET_VREG_WIDE d0, w1 // d0<- vBB + bl fmod + lsr w4, wINST, #8 // w4<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w4 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ diff --git a/runtime/interpreter/mterp/arm64/op_rem_double_2addr.S b/runtime/interpreter/mterp/arm64/op_rem_double_2addr.S new file mode 100644 index 000000000..db18aa7ee --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rem_double_2addr.S @@ -0,0 +1,12 @@ + /* rem vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE d1, w1 // d1<- vB + GET_VREG_WIDE d0, w2 // d0<- vA + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + bl fmod + ubfx w2, wINST, #8, #4 // w2<- A (need to reload - killed across call) + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ diff --git a/runtime/interpreter/mterp/arm64/op_rem_float.S b/runtime/interpreter/mterp/arm64/op_rem_float.S new file mode 100644 index 000000000..73f7060cf --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rem_float.S @@ -0,0 +1,2 @@ +/* EABI doesn't define a float remainder function, but libm does */ +%include "arm64/fbinop.S" {"instr":"bl fmodf"} diff --git a/runtime/interpreter/mterp/arm64/op_rem_float_2addr.S b/runtime/interpreter/mterp/arm64/op_rem_float_2addr.S new file mode 100644 index 000000000..0b918910c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rem_float_2addr.S @@ -0,0 +1,13 @@ + /* rem vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w9, wINST, #8 // w9<- A+ + and w9, w9, #15 // w9<- A + GET_VREG s1, w3 + GET_VREG s0, w9 + bl fmodf + lsr w9, wINST, #8 // w9<- A+ + and w9, w9, #15 // w9<- A + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s0, w9 + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_rem_int.S b/runtime/interpreter/mterp/arm64/op_rem_int.S new file mode 100644 index 000000000..dd9dfda08 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rem_int.S @@ -0,0 +1 @@ +%include "arm64/binop.S" {"preinstr":"sdiv w2, w0, w1", "instr":"msub w0, w2, w1, w0", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_rem_int_2addr.S b/runtime/interpreter/mterp/arm64/op_rem_int_2addr.S new file mode 100644 index 000000000..57fc4971b --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rem_int_2addr.S @@ -0,0 +1 @@ +%include "arm64/binop2addr.S" {"preinstr":"sdiv w2, w0, w1", "instr":"msub w0, w2, w1, w0", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_rem_int_lit16.S b/runtime/interpreter/mterp/arm64/op_rem_int_lit16.S new file mode 100644 index 000000000..b51a739d2 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rem_int_lit16.S @@ -0,0 +1 @@ +%include "arm64/binopLit16.S" {"preinstr":"sdiv w3, w0, w1", "instr":"msub w0, w3, w1, w0", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_rem_int_lit8.S b/runtime/interpreter/mterp/arm64/op_rem_int_lit8.S new file mode 100644 index 000000000..03ea32420 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rem_int_lit8.S @@ -0,0 +1 @@ +%include "arm64/binopLit8.S" {"preinstr":"sdiv w3, w0, w1", "instr":"msub w0, w3, w1, w0", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_rem_long.S b/runtime/interpreter/mterp/arm64/op_rem_long.S new file mode 100644 index 000000000..f133f86a6 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rem_long.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"preinstr":"sdiv x3, x1, x2","instr":"msub x0, x3, x2, x1", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_rem_long_2addr.S b/runtime/interpreter/mterp/arm64/op_rem_long_2addr.S new file mode 100644 index 000000000..b45e2a95c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rem_long_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"preinstr":"sdiv x3, x0, x1", "instr":"msub x0, x3, x1, x0", "chkzero":"1"} diff --git a/runtime/interpreter/mterp/arm64/op_return.S b/runtime/interpreter/mterp/arm64/op_return.S new file mode 100644 index 000000000..28630eed4 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_return.S @@ -0,0 +1,19 @@ + /* + * Return a 32-bit value. + * + * for: return, return-object + */ + /* op vAA */ + .extern MterpThreadFenceForConstructor + bl MterpThreadFenceForConstructor + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov x0, xSELF + ands w7, w7, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.ne .L${opcode}_check +.L${opcode}_return: + lsr w2, wINST, #8 // r2<- AA + GET_VREG w0, w2 // r0<- vAA + b MterpReturn +.L${opcode}_check: + bl MterpSuspendCheck // (self) + b .L${opcode}_return diff --git a/runtime/interpreter/mterp/arm64/op_return_object.S b/runtime/interpreter/mterp/arm64/op_return_object.S new file mode 100644 index 000000000..b6cb532b5 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_return_object.S @@ -0,0 +1 @@ +%include "arm64/op_return.S" diff --git a/runtime/interpreter/mterp/arm64/op_return_void.S b/runtime/interpreter/mterp/arm64/op_return_void.S new file mode 100644 index 000000000..3a5aa5616 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_return_void.S @@ -0,0 +1,12 @@ + .extern MterpThreadFenceForConstructor + bl MterpThreadFenceForConstructor + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov x0, xSELF + ands w7, w7, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.ne .L${opcode}_check +.L${opcode}_return: + mov x0, #0 + b MterpReturn +.L${opcode}_check: + bl MterpSuspendCheck // (self) + b .L${opcode}_return diff --git a/runtime/interpreter/mterp/arm64/op_return_void_no_barrier.S b/runtime/interpreter/mterp/arm64/op_return_void_no_barrier.S new file mode 100644 index 000000000..1e0695374 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_return_void_no_barrier.S @@ -0,0 +1,10 @@ + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov x0, xSELF + ands w7, w7, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.ne .L${opcode}_check +.L${opcode}_return: + mov x0, #0 + b MterpReturn +.L${opcode}_check: + bl MterpSuspendCheck // (self) + b .L${opcode}_return diff --git a/runtime/interpreter/mterp/arm64/op_return_wide.S b/runtime/interpreter/mterp/arm64/op_return_wide.S new file mode 100644 index 000000000..c6e1d9da8 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_return_wide.S @@ -0,0 +1,18 @@ + /* + * Return a 64-bit value. + */ + /* return-wide vAA */ + /* op vAA */ + .extern MterpThreadFenceForConstructor + bl MterpThreadFenceForConstructor + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov x0, xSELF + ands w7, w7, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.ne .L${opcode}_check +.L${opcode}_return: + lsr w2, wINST, #8 // w2<- AA + GET_VREG_WIDE x0, w2 // x0<- vAA + b MterpReturn +.L${opcode}_check: + bl MterpSuspendCheck // (self) + b .L${opcode}_return diff --git a/runtime/interpreter/mterp/arm64/op_rsub_int.S b/runtime/interpreter/mterp/arm64/op_rsub_int.S new file mode 100644 index 000000000..3bf45fe65 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rsub_int.S @@ -0,0 +1,2 @@ +/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ +%include "arm64/binopLit16.S" {"instr":"sub w0, w1, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_rsub_int_lit8.S b/runtime/interpreter/mterp/arm64/op_rsub_int_lit8.S new file mode 100644 index 000000000..7a3572b36 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_rsub_int_lit8.S @@ -0,0 +1 @@ +%include "arm64/binopLit8.S" {"instr":"sub w0, w1, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_sget.S b/runtime/interpreter/mterp/arm64/op_sget.S new file mode 100644 index 000000000..6352ce059 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sget.S @@ -0,0 +1,27 @@ +%default { "is_object":"0", "helper":"artGet32StaticFromCode", "extend":"" } + /* + * General SGET handler wrapper. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op vAA, field//BBBB */ + + .extern $helper + EXPORT_PC + FETCH w0, 1 // w0<- field ref BBBB + ldr x1, [xFP, #OFF_FP_METHOD] + mov x2, xSELF + bl $helper + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w2, wINST, #8 // w2<- AA + $extend + PREFETCH_INST 2 + cbnz x3, MterpException // bail out +.if $is_object + SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 +.else + SET_VREG w0, w2 // fp[AA]<- w0 +.endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip diff --git a/runtime/interpreter/mterp/arm64/op_sget_boolean.S b/runtime/interpreter/mterp/arm64/op_sget_boolean.S new file mode 100644 index 000000000..c40dbdd7d --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sget_boolean.S @@ -0,0 +1 @@ +%include "arm64/op_sget.S" {"helper":"artGetBooleanStaticFromCode", "extend":"uxtb w0, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_sget_byte.S b/runtime/interpreter/mterp/arm64/op_sget_byte.S new file mode 100644 index 000000000..6cf69a382 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sget_byte.S @@ -0,0 +1 @@ +%include "arm64/op_sget.S" {"helper":"artGetByteStaticFromCode", "extend":"sxtb w0, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_sget_char.S b/runtime/interpreter/mterp/arm64/op_sget_char.S new file mode 100644 index 000000000..8924a349a --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sget_char.S @@ -0,0 +1 @@ +%include "arm64/op_sget.S" {"helper":"artGetCharStaticFromCode", "extend":"uxth w0, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_sget_object.S b/runtime/interpreter/mterp/arm64/op_sget_object.S new file mode 100644 index 000000000..620b0bab0 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sget_object.S @@ -0,0 +1 @@ +%include "arm64/op_sget.S" {"is_object":"1", "helper":"artGetObjStaticFromCode"} diff --git a/runtime/interpreter/mterp/arm64/op_sget_short.S b/runtime/interpreter/mterp/arm64/op_sget_short.S new file mode 100644 index 000000000..19dbba6f7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sget_short.S @@ -0,0 +1 @@ +%include "arm64/op_sget.S" {"helper":"artGetShortStaticFromCode", "extend":"sxth w0, w0"} diff --git a/runtime/interpreter/mterp/arm64/op_sget_wide.S b/runtime/interpreter/mterp/arm64/op_sget_wide.S new file mode 100644 index 000000000..287f66dae --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sget_wide.S @@ -0,0 +1,19 @@ + /* + * SGET_WIDE handler wrapper. + * + */ + /* sget-wide vAA, field//BBBB */ + + .extern artGet64StaticFromCode + EXPORT_PC + FETCH w0, 1 // w0<- field ref BBBB + ldr x1, [xFP, #OFF_FP_METHOD] + mov x2, xSELF + bl artGet64StaticFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w4, wINST, #8 // w4<- AA + cbnz x3, MterpException // bail out + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + SET_VREG_WIDE x0, w4 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_shl_int.S b/runtime/interpreter/mterp/arm64/op_shl_int.S new file mode 100644 index 000000000..bd0f237cf --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_shl_int.S @@ -0,0 +1 @@ +%include "arm64/binop.S" {"preinstr":"and w1, w1, #31", "instr":"lsl w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_shl_int_2addr.S b/runtime/interpreter/mterp/arm64/op_shl_int_2addr.S new file mode 100644 index 000000000..b4671d2f1 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_shl_int_2addr.S @@ -0,0 +1 @@ +%include "arm64/binop2addr.S" {"preinstr":"and w1, w1, #31", "instr":"lsl w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_shl_int_lit8.S b/runtime/interpreter/mterp/arm64/op_shl_int_lit8.S new file mode 100644 index 000000000..4dd32e08a --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_shl_int_lit8.S @@ -0,0 +1 @@ +%include "arm64/binopLit8.S" {"preinstr":"and w1, w1, #31", "instr":"lsl w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_shl_long.S b/runtime/interpreter/mterp/arm64/op_shl_long.S new file mode 100644 index 000000000..bbf960095 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_shl_long.S @@ -0,0 +1 @@ +%include "arm64/shiftWide.S" {"opcode":"lsl"} diff --git a/runtime/interpreter/mterp/arm64/op_shl_long_2addr.S b/runtime/interpreter/mterp/arm64/op_shl_long_2addr.S new file mode 100644 index 000000000..a5c4013bf --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_shl_long_2addr.S @@ -0,0 +1 @@ +%include "arm64/shiftWide2addr.S" {"opcode":"lsl"} diff --git a/runtime/interpreter/mterp/arm64/op_shr_int.S b/runtime/interpreter/mterp/arm64/op_shr_int.S new file mode 100644 index 000000000..c214a18fd --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_shr_int.S @@ -0,0 +1 @@ +%include "arm64/binop.S" {"preinstr":"and w1, w1, #31", "instr":"asr w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_shr_int_2addr.S b/runtime/interpreter/mterp/arm64/op_shr_int_2addr.S new file mode 100644 index 000000000..3c1484b0c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_shr_int_2addr.S @@ -0,0 +1 @@ +%include "arm64/binop2addr.S" {"preinstr":"and w1, w1, #31", "instr":"asr w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_shr_int_lit8.S b/runtime/interpreter/mterp/arm64/op_shr_int_lit8.S new file mode 100644 index 000000000..26d5024a2 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_shr_int_lit8.S @@ -0,0 +1 @@ +%include "arm64/binopLit8.S" {"preinstr":"and w1, w1, #31", "instr":"asr w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_shr_long.S b/runtime/interpreter/mterp/arm64/op_shr_long.S new file mode 100644 index 000000000..4d332359a --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_shr_long.S @@ -0,0 +1 @@ +%include "arm64/shiftWide.S" {"opcode":"asr"} diff --git a/runtime/interpreter/mterp/arm64/op_shr_long_2addr.S b/runtime/interpreter/mterp/arm64/op_shr_long_2addr.S new file mode 100644 index 000000000..0a4a386c9 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_shr_long_2addr.S @@ -0,0 +1 @@ +%include "arm64/shiftWide2addr.S" {"opcode":"asr"} diff --git a/runtime/interpreter/mterp/arm64/op_sparse_switch.S b/runtime/interpreter/mterp/arm64/op_sparse_switch.S new file mode 100644 index 000000000..5a8d7489b --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sparse_switch.S @@ -0,0 +1 @@ +%include "arm64/op_packed_switch.S" { "func":"MterpDoSparseSwitch" } diff --git a/runtime/interpreter/mterp/arm64/op_sput.S b/runtime/interpreter/mterp/arm64/op_sput.S new file mode 100644 index 000000000..75f27abdc --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sput.S @@ -0,0 +1,19 @@ +%default { "helper":"artSet32StaticFromCode"} + /* + * General SPUT handler wrapper. + * + * for: sput, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op vAA, field//BBBB */ + EXPORT_PC + FETCH w0, 1 // r0<- field ref BBBB + lsr w3, wINST, #8 // r3<- AA + GET_VREG w1, w3 // r1<= fp[AA] + ldr x2, [xFP, #OFF_FP_METHOD] + mov x3, xSELF + PREFETCH_INST 2 // Get next inst, but don't advance rPC + bl $helper + cbnz w0, MterpException // 0 on success + ADVANCE 2 // Past exception point - now advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_sput_boolean.S b/runtime/interpreter/mterp/arm64/op_sput_boolean.S new file mode 100644 index 000000000..11c55e529 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sput_boolean.S @@ -0,0 +1 @@ +%include "arm64/op_sput.S" {"helper":"artSet8StaticFromCode"} diff --git a/runtime/interpreter/mterp/arm64/op_sput_byte.S b/runtime/interpreter/mterp/arm64/op_sput_byte.S new file mode 100644 index 000000000..11c55e529 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sput_byte.S @@ -0,0 +1 @@ +%include "arm64/op_sput.S" {"helper":"artSet8StaticFromCode"} diff --git a/runtime/interpreter/mterp/arm64/op_sput_char.S b/runtime/interpreter/mterp/arm64/op_sput_char.S new file mode 100644 index 000000000..b4dd5aa76 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sput_char.S @@ -0,0 +1 @@ +%include "arm64/op_sput.S" {"helper":"artSet16StaticFromCode"} diff --git a/runtime/interpreter/mterp/arm64/op_sput_object.S b/runtime/interpreter/mterp/arm64/op_sput_object.S new file mode 100644 index 000000000..c176da273 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sput_object.S @@ -0,0 +1,10 @@ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov x2, xINST + mov x3, xSELF + bl MterpSputObject + cbz w0, MterpException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_sput_short.S b/runtime/interpreter/mterp/arm64/op_sput_short.S new file mode 100644 index 000000000..b4dd5aa76 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sput_short.S @@ -0,0 +1 @@ +%include "arm64/op_sput.S" {"helper":"artSet16StaticFromCode"} diff --git a/runtime/interpreter/mterp/arm64/op_sput_wide.S b/runtime/interpreter/mterp/arm64/op_sput_wide.S new file mode 100644 index 000000000..1d034ecf2 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sput_wide.S @@ -0,0 +1,18 @@ + /* + * SPUT_WIDE handler wrapper. + * + */ + /* sput-wide vAA, field//BBBB */ + .extern artSet64IndirectStaticFromMterp + EXPORT_PC + FETCH w0, 1 // w0<- field ref BBBB + ldr x1, [xFP, #OFF_FP_METHOD] + lsr w2, wINST, #8 // w3<- AA + add x2, xFP, w2, lsl #2 + mov x3, xSELF + PREFETCH_INST 2 // Get next inst, but don't advance rPC + bl artSet64IndirectStaticFromMterp + cbnz w0, MterpException // 0 on success, -1 on failure + ADVANCE 2 // Past exception point - now advance rPC + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction diff --git a/runtime/interpreter/mterp/arm64/op_sub_double.S b/runtime/interpreter/mterp/arm64/op_sub_double.S new file mode 100644 index 000000000..e8e3401e1 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sub_double.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"instr":"fsub d0, d1, d2", "result":"d0", "r1":"d1", "r2":"d2"} diff --git a/runtime/interpreter/mterp/arm64/op_sub_double_2addr.S b/runtime/interpreter/mterp/arm64/op_sub_double_2addr.S new file mode 100644 index 000000000..ddab55e9f --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sub_double_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"instr":"fsub d0, d0, d1", "r0":"d0", "r1":"d1"} diff --git a/runtime/interpreter/mterp/arm64/op_sub_float.S b/runtime/interpreter/mterp/arm64/op_sub_float.S new file mode 100644 index 000000000..227b15fdf --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sub_float.S @@ -0,0 +1 @@ +%include "arm64/fbinop.S" {"instr":"fsub s0, s0, s1"} diff --git a/runtime/interpreter/mterp/arm64/op_sub_float_2addr.S b/runtime/interpreter/mterp/arm64/op_sub_float_2addr.S new file mode 100644 index 000000000..19ac8d561 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sub_float_2addr.S @@ -0,0 +1 @@ +%include "arm64/fbinop2addr.S" {"instr":"fsub s2, s0, s1"} diff --git a/runtime/interpreter/mterp/arm64/op_sub_int.S b/runtime/interpreter/mterp/arm64/op_sub_int.S new file mode 100644 index 000000000..0e7ce0e6e --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sub_int.S @@ -0,0 +1 @@ +%include "arm64/binop.S" {"instr":"sub w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_sub_int_2addr.S b/runtime/interpreter/mterp/arm64/op_sub_int_2addr.S new file mode 100644 index 000000000..d2c1bd307 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sub_int_2addr.S @@ -0,0 +1 @@ +%include "arm64/binop2addr.S" {"instr":"sub w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_sub_long.S b/runtime/interpreter/mterp/arm64/op_sub_long.S new file mode 100644 index 000000000..263c70d6e --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sub_long.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"instr":"sub x0, x1, x2"} diff --git a/runtime/interpreter/mterp/arm64/op_sub_long_2addr.S b/runtime/interpreter/mterp/arm64/op_sub_long_2addr.S new file mode 100644 index 000000000..5be377267 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_sub_long_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"instr":"sub x0, x0, x1"} diff --git a/runtime/interpreter/mterp/arm64/op_throw.S b/runtime/interpreter/mterp/arm64/op_throw.S new file mode 100644 index 000000000..9a951af30 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_throw.S @@ -0,0 +1,10 @@ + /* + * Throw an exception object in the current thread. + */ + /* throw vAA */ + EXPORT_PC + lsr w2, wINST, #8 // r2<- AA + GET_VREG w1, w2 // r1<- vAA (exception object) + cbz w1, common_errNullObject + str x1, [xSELF, #THREAD_EXCEPTION_OFFSET] // thread->exception<- obj + b MterpException diff --git a/runtime/interpreter/mterp/arm64/op_unused_3e.S b/runtime/interpreter/mterp/arm64/op_unused_3e.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_3e.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_3f.S b/runtime/interpreter/mterp/arm64/op_unused_3f.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_3f.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_40.S b/runtime/interpreter/mterp/arm64/op_unused_40.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_40.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_41.S b/runtime/interpreter/mterp/arm64/op_unused_41.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_41.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_42.S b/runtime/interpreter/mterp/arm64/op_unused_42.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_42.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_43.S b/runtime/interpreter/mterp/arm64/op_unused_43.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_43.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_73.S b/runtime/interpreter/mterp/arm64/op_unused_73.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_73.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_79.S b/runtime/interpreter/mterp/arm64/op_unused_79.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_79.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_7a.S b/runtime/interpreter/mterp/arm64/op_unused_7a.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_7a.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_f3.S b/runtime/interpreter/mterp/arm64/op_unused_f3.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_f3.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_f4.S b/runtime/interpreter/mterp/arm64/op_unused_f4.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_f4.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_f5.S b/runtime/interpreter/mterp/arm64/op_unused_f5.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_f5.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_f6.S b/runtime/interpreter/mterp/arm64/op_unused_f6.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_f6.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_f7.S b/runtime/interpreter/mterp/arm64/op_unused_f7.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_f7.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_f8.S b/runtime/interpreter/mterp/arm64/op_unused_f8.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_f8.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_f9.S b/runtime/interpreter/mterp/arm64/op_unused_f9.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_f9.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_fa.S b/runtime/interpreter/mterp/arm64/op_unused_fa.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_fa.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_fb.S b/runtime/interpreter/mterp/arm64/op_unused_fb.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_fb.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_fc.S b/runtime/interpreter/mterp/arm64/op_unused_fc.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_fc.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_fd.S b/runtime/interpreter/mterp/arm64/op_unused_fd.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_fd.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_fe.S b/runtime/interpreter/mterp/arm64/op_unused_fe.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_fe.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_unused_ff.S b/runtime/interpreter/mterp/arm64/op_unused_ff.S new file mode 100644 index 000000000..204eceff7 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_unused_ff.S @@ -0,0 +1 @@ +%include "arm64/unused.S" diff --git a/runtime/interpreter/mterp/arm64/op_ushr_int.S b/runtime/interpreter/mterp/arm64/op_ushr_int.S new file mode 100644 index 000000000..bb8382b92 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_ushr_int.S @@ -0,0 +1 @@ +%include "arm64/binop.S" {"preinstr":"and w1, w1, #31", "instr":"lsr w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_ushr_int_2addr.S b/runtime/interpreter/mterp/arm64/op_ushr_int_2addr.S new file mode 100644 index 000000000..dbccb9952 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_ushr_int_2addr.S @@ -0,0 +1 @@ +%include "arm64/binop2addr.S" {"preinstr":"and w1, w1, #31", "instr":"lsr w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_ushr_int_lit8.S b/runtime/interpreter/mterp/arm64/op_ushr_int_lit8.S new file mode 100644 index 000000000..35090c46d --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_ushr_int_lit8.S @@ -0,0 +1 @@ +%include "arm64/binopLit8.S" {"preinstr":"and w1, w1, #31", "instr":"lsr w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_ushr_long.S b/runtime/interpreter/mterp/arm64/op_ushr_long.S new file mode 100644 index 000000000..e13c86a48 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_ushr_long.S @@ -0,0 +1 @@ +%include "arm64/shiftWide.S" {"opcode":"lsr"} diff --git a/runtime/interpreter/mterp/arm64/op_ushr_long_2addr.S b/runtime/interpreter/mterp/arm64/op_ushr_long_2addr.S new file mode 100644 index 000000000..67ec91e96 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_ushr_long_2addr.S @@ -0,0 +1 @@ +%include "arm64/shiftWide2addr.S" {"opcode":"lsr"} diff --git a/runtime/interpreter/mterp/arm64/op_xor_int.S b/runtime/interpreter/mterp/arm64/op_xor_int.S new file mode 100644 index 000000000..74836635f --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_xor_int.S @@ -0,0 +1 @@ +%include "arm64/binop.S" {"instr":"eor w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_xor_int_2addr.S b/runtime/interpreter/mterp/arm64/op_xor_int_2addr.S new file mode 100644 index 000000000..2f9a2c735 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_xor_int_2addr.S @@ -0,0 +1 @@ +%include "arm64/binop2addr.S" {"instr":"eor w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_xor_int_lit16.S b/runtime/interpreter/mterp/arm64/op_xor_int_lit16.S new file mode 100644 index 000000000..6b72c560f --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_xor_int_lit16.S @@ -0,0 +1 @@ +%include "arm64/binopLit16.S" {"instr":"eor w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_xor_int_lit8.S b/runtime/interpreter/mterp/arm64/op_xor_int_lit8.S new file mode 100644 index 000000000..6d187b579 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_xor_int_lit8.S @@ -0,0 +1 @@ +%include "arm64/binopLit8.S" {"instr":"eor w0, w0, w1"} diff --git a/runtime/interpreter/mterp/arm64/op_xor_long.S b/runtime/interpreter/mterp/arm64/op_xor_long.S new file mode 100644 index 000000000..3880d5d19 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_xor_long.S @@ -0,0 +1 @@ +%include "arm64/binopWide.S" {"instr":"eor x0, x1, x2"} diff --git a/runtime/interpreter/mterp/arm64/op_xor_long_2addr.S b/runtime/interpreter/mterp/arm64/op_xor_long_2addr.S new file mode 100644 index 000000000..36905529d --- /dev/null +++ b/runtime/interpreter/mterp/arm64/op_xor_long_2addr.S @@ -0,0 +1 @@ +%include "arm64/binopWide2addr.S" {"instr":"eor x0, x0, x1"} diff --git a/runtime/interpreter/mterp/arm64/shiftWide.S b/runtime/interpreter/mterp/arm64/shiftWide.S new file mode 100644 index 000000000..6306fca5c --- /dev/null +++ b/runtime/interpreter/mterp/arm64/shiftWide.S @@ -0,0 +1,20 @@ +%default {"opcode":"shl"} + /* + * 64-bit shift operation. + * + * For: shl-long, shr-long, ushr-long + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w3, wINST, #8 // w3<- AA + lsr w2, w0, #8 // w2<- CC + GET_VREG w2, w2 // w2<- vCC (shift count) + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x1, w1 // x1<- vBB + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + and x2, x2, #63 // Mask low 6 + $opcode x0, x1, x2 // Do the shift. + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w3 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ diff --git a/runtime/interpreter/mterp/arm64/shiftWide2addr.S b/runtime/interpreter/mterp/arm64/shiftWide2addr.S new file mode 100644 index 000000000..77d104a62 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/shiftWide2addr.S @@ -0,0 +1,16 @@ +%default {"opcode":"lsl"} + /* + * Generic 64-bit shift operation. + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + and x1, x1, #63 // Mask low 6 bits. + $opcode x0, x0, x1 + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ diff --git a/runtime/interpreter/mterp/arm64/unop.S b/runtime/interpreter/mterp/arm64/unop.S new file mode 100644 index 000000000..474a96183 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/unop.S @@ -0,0 +1,20 @@ +%default {"preinstr":""} + /* + * Generic 32-bit unary operation. Provide an "instr" line that + * specifies an instruction that performs "result = op w0". + * This could be an ARM instruction or a function call. + * + * for: neg-int, not-int, neg-float, int-to-float, float-to-int, + * int-to-byte, int-to-char, int-to-short + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + GET_VREG w0, w3 // w0<- vB + ubfx w9, wINST, #8, #4 // w9<- A + $preinstr // optional op; may set condition codes + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + $instr // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 8-9 instructions */ diff --git a/runtime/interpreter/mterp/arm64/unopWide.S b/runtime/interpreter/mterp/arm64/unopWide.S new file mode 100644 index 000000000..109302a12 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/unopWide.S @@ -0,0 +1,18 @@ +%default {"instr":"sub x0, xzr, x0", "preinstr":""} + /* + * Generic 64-bit unary operation. Provide an "instr" line that + * specifies an instruction that performs "result = op x0". + * + * For: neg-long, not-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w4, wINST, #8, #4 // w4<- A + GET_VREG_WIDE x0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + $preinstr + $instr + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x0, w4 + GOTO_OPCODE ip // jump to next instruction + /* 10-11 instructions */ diff --git a/runtime/interpreter/mterp/arm64/unused.S b/runtime/interpreter/mterp/arm64/unused.S new file mode 100644 index 000000000..ffa00becf --- /dev/null +++ b/runtime/interpreter/mterp/arm64/unused.S @@ -0,0 +1,4 @@ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback diff --git a/runtime/interpreter/mterp/arm64/zcmp.S b/runtime/interpreter/mterp/arm64/zcmp.S new file mode 100644 index 000000000..d4856d266 --- /dev/null +++ b/runtime/interpreter/mterp/arm64/zcmp.S @@ -0,0 +1,33 @@ + /* + * Generic one-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez + */ + /* if-cmp vAA, +BBBB */ +#if MTERP_SUSPEND + mov w0, wINST, lsr #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, #0 // compare (vA, 0) + mov${condition} w1, #2 // w1<- inst branch dist for not-taken + adds w1, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh table base + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w0, wINST, #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Branch offset if not taken + cmp w2, #0 // compare (vA, 0) + csel w1, w1, w0, ${condition} // Branch if true + adds w2, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif diff --git a/runtime/interpreter/mterp/config_arm64 b/runtime/interpreter/mterp/config_arm64 index ef3c721df..57206d25b 100644 --- a/runtime/interpreter/mterp/config_arm64 +++ b/runtime/interpreter/mterp/config_arm64 @@ -1,3 +1,4 @@ + # Copyright (C) 2015 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,262 +37,262 @@ op-start arm64 # (override example:) op OP_SUB_FLOAT_2ADDR arm-vfp # (fallback example:) op OP_SUB_FLOAT_2ADDR FALLBACK - op op_nop FALLBACK - op op_move FALLBACK - op op_move_from16 FALLBACK - op op_move_16 FALLBACK - op op_move_wide FALLBACK - op op_move_wide_from16 FALLBACK - op op_move_wide_16 FALLBACK - op op_move_object FALLBACK - op op_move_object_from16 FALLBACK - op op_move_object_16 FALLBACK - op op_move_result FALLBACK - op op_move_result_wide FALLBACK - op op_move_result_object FALLBACK - op op_move_exception FALLBACK - op op_return_void FALLBACK - op op_return FALLBACK - op op_return_wide FALLBACK - op op_return_object FALLBACK - op op_const_4 FALLBACK - op op_const_16 FALLBACK - op op_const FALLBACK - op op_const_high16 FALLBACK - op op_const_wide_16 FALLBACK - op op_const_wide_32 FALLBACK - op op_const_wide FALLBACK - op op_const_wide_high16 FALLBACK - op op_const_string FALLBACK - op op_const_string_jumbo FALLBACK - op op_const_class FALLBACK - op op_monitor_enter FALLBACK - op op_monitor_exit FALLBACK - op op_check_cast FALLBACK - op op_instance_of FALLBACK - op op_array_length FALLBACK - op op_new_instance FALLBACK - op op_new_array FALLBACK - op op_filled_new_array FALLBACK - op op_filled_new_array_range FALLBACK - op op_fill_array_data FALLBACK - op op_throw FALLBACK - op op_goto FALLBACK - op op_goto_16 FALLBACK - op op_goto_32 FALLBACK - op op_packed_switch FALLBACK - op op_sparse_switch FALLBACK - op op_cmpl_float FALLBACK - op op_cmpg_float FALLBACK - op op_cmpl_double FALLBACK - op op_cmpg_double FALLBACK - op op_cmp_long FALLBACK - op op_if_eq FALLBACK - op op_if_ne FALLBACK - op op_if_lt FALLBACK - op op_if_ge FALLBACK - op op_if_gt FALLBACK - op op_if_le FALLBACK - op op_if_eqz FALLBACK - op op_if_nez FALLBACK - op op_if_ltz FALLBACK - op op_if_gez FALLBACK - op op_if_gtz FALLBACK - op op_if_lez FALLBACK - op_unused_3e FALLBACK - op_unused_3f FALLBACK - op_unused_40 FALLBACK - op_unused_41 FALLBACK - op_unused_42 FALLBACK - op_unused_43 FALLBACK - op op_aget FALLBACK - op op_aget_wide FALLBACK - op op_aget_object FALLBACK - op op_aget_boolean FALLBACK - op op_aget_byte FALLBACK - op op_aget_char FALLBACK - op op_aget_short FALLBACK - op op_aput FALLBACK - op op_aput_wide FALLBACK - op op_aput_object FALLBACK - op op_aput_boolean FALLBACK - op op_aput_byte FALLBACK - op op_aput_char FALLBACK - op op_aput_short FALLBACK - op op_iget FALLBACK - op op_iget_wide FALLBACK - op op_iget_object FALLBACK - op op_iget_boolean FALLBACK - op op_iget_byte FALLBACK - op op_iget_char FALLBACK - op op_iget_short FALLBACK - op op_iput FALLBACK - op op_iput_wide FALLBACK - op op_iput_object FALLBACK - op op_iput_boolean FALLBACK - op op_iput_byte FALLBACK - op op_iput_char FALLBACK - op op_iput_short FALLBACK - op op_sget FALLBACK - op op_sget_wide FALLBACK - op op_sget_object FALLBACK - op op_sget_boolean FALLBACK - op op_sget_byte FALLBACK - op op_sget_char FALLBACK - op op_sget_short FALLBACK - op op_sput FALLBACK - op op_sput_wide FALLBACK - op op_sput_object FALLBACK - op op_sput_boolean FALLBACK - op op_sput_byte FALLBACK - op op_sput_char FALLBACK - op op_sput_short FALLBACK - op op_invoke_virtual FALLBACK - op op_invoke_super FALLBACK - op op_invoke_direct FALLBACK - op op_invoke_static FALLBACK - op op_invoke_interface FALLBACK - op op_return_void_no_barrier FALLBACK - op op_invoke_virtual_range FALLBACK - op op_invoke_super_range FALLBACK - op op_invoke_direct_range FALLBACK - op op_invoke_static_range FALLBACK - op op_invoke_interface_range FALLBACK - op_unused_79 FALLBACK - op_unused_7a FALLBACK - op op_neg_int FALLBACK - op op_not_int FALLBACK - op op_neg_long FALLBACK - op op_not_long FALLBACK - op op_neg_float FALLBACK - op op_neg_double FALLBACK - op op_int_to_long FALLBACK - op op_int_to_float FALLBACK - op op_int_to_double FALLBACK - op op_long_to_int FALLBACK - op op_long_to_float FALLBACK - op op_long_to_double FALLBACK - op op_float_to_int FALLBACK - op op_float_to_long FALLBACK - op op_float_to_double FALLBACK - op op_double_to_int FALLBACK - op op_double_to_long FALLBACK - op op_double_to_float FALLBACK - op op_int_to_byte FALLBACK - op op_int_to_char FALLBACK - op op_int_to_short FALLBACK - op op_add_int FALLBACK - op op_sub_int FALLBACK - op op_mul_int FALLBACK - op op_div_int FALLBACK - op op_rem_int FALLBACK - op op_and_int FALLBACK - op op_or_int FALLBACK - op op_xor_int FALLBACK - op op_shl_int FALLBACK - op op_shr_int FALLBACK - op op_ushr_int FALLBACK - op op_add_long FALLBACK - op op_sub_long FALLBACK - op op_mul_long FALLBACK - op op_div_long FALLBACK - op op_rem_long FALLBACK - op op_and_long FALLBACK - op op_or_long FALLBACK - op op_xor_long FALLBACK - op op_shl_long FALLBACK - op op_shr_long FALLBACK - op op_ushr_long FALLBACK - op op_add_float FALLBACK - op op_sub_float FALLBACK - op op_mul_float FALLBACK - op op_div_float FALLBACK - op op_rem_float FALLBACK - op op_add_double FALLBACK - op op_sub_double FALLBACK - op op_mul_double FALLBACK - op op_div_double FALLBACK - op op_rem_double FALLBACK - op op_add_int_2addr FALLBACK - op op_sub_int_2addr FALLBACK - op op_mul_int_2addr FALLBACK - op op_div_int_2addr FALLBACK - op op_rem_int_2addr FALLBACK - op op_and_int_2addr FALLBACK - op op_or_int_2addr FALLBACK - op op_xor_int_2addr FALLBACK - op op_shl_int_2addr FALLBACK - op op_shr_int_2addr FALLBACK - op op_ushr_int_2addr FALLBACK - op op_add_long_2addr FALLBACK - op op_sub_long_2addr FALLBACK - op op_mul_long_2addr FALLBACK - op op_div_long_2addr FALLBACK - op op_rem_long_2addr FALLBACK - op op_and_long_2addr FALLBACK - op op_or_long_2addr FALLBACK - op op_xor_long_2addr FALLBACK - op op_shl_long_2addr FALLBACK - op op_shr_long_2addr FALLBACK - op op_ushr_long_2addr FALLBACK - op op_add_float_2addr FALLBACK - op op_sub_float_2addr FALLBACK - op op_mul_float_2addr FALLBACK - op op_div_float_2addr FALLBACK - op op_rem_float_2addr FALLBACK - op op_add_double_2addr FALLBACK - op op_sub_double_2addr FALLBACK - op op_mul_double_2addr FALLBACK - op op_div_double_2addr FALLBACK - op op_rem_double_2addr FALLBACK - op op_add_int_lit16 FALLBACK - op op_rsub_int FALLBACK - op op_mul_int_lit16 FALLBACK - op op_div_int_lit16 FALLBACK - op op_rem_int_lit16 FALLBACK - op op_and_int_lit16 FALLBACK - op op_or_int_lit16 FALLBACK - op op_xor_int_lit16 FALLBACK - op op_add_int_lit8 FALLBACK - op op_rsub_int_lit8 FALLBACK - op op_mul_int_lit8 FALLBACK - op op_div_int_lit8 FALLBACK - op op_rem_int_lit8 FALLBACK - op op_and_int_lit8 FALLBACK - op op_or_int_lit8 FALLBACK - op op_xor_int_lit8 FALLBACK - op op_shl_int_lit8 FALLBACK - op op_shr_int_lit8 FALLBACK - op op_ushr_int_lit8 FALLBACK - op op_iget_quick FALLBACK - op op_iget_wide_quick FALLBACK - op op_iget_object_quick FALLBACK - op op_iput_quick FALLBACK - op op_iput_wide_quick FALLBACK - op op_iput_object_quick FALLBACK - op op_invoke_virtual_quick FALLBACK - op op_invoke_virtual_range_quick FALLBACK - op op_iput_boolean_quick FALLBACK - op op_iput_byte_quick FALLBACK - op op_iput_char_quick FALLBACK - op op_iput_short_quick FALLBACK - op op_iget_boolean_quick FALLBACK - op op_iget_byte_quick FALLBACK - op op_iget_char_quick FALLBACK - op op_iget_short_quick FALLBACK - op_unused_f3 FALLBACK - op_unused_f4 FALLBACK - op_unused_f5 FALLBACK - op_unused_f6 FALLBACK - op_unused_f7 FALLBACK - op_unused_f8 FALLBACK - op_unused_f9 FALLBACK - op_unused_fa FALLBACK - op_unused_fb FALLBACK - op_unused_fc FALLBACK - op_unused_fd FALLBACK - op_unused_fe FALLBACK - op_unused_ff FALLBACK + # op op_nop FALLBACK + # op op_move FALLBACK + # op op_move_from16 FALLBACK + # op op_move_16 FALLBACK + # op op_move_wide FALLBACK + # op op_move_wide_from16 FALLBACK + # op op_move_wide_16 FALLBACK + # op op_move_object FALLBACK + # op op_move_object_from16 FALLBACK + # op op_move_object_16 FALLBACK + # op op_move_result FALLBACK + # op op_move_result_wide FALLBACK + # op op_move_result_object FALLBACK + # op op_move_exception FALLBACK + # op op_return_void FALLBACK + # op op_return FALLBACK + # op op_return_wide FALLBACK + # op op_return_object FALLBACK + # op op_const_4 FALLBACK + # op op_const_16 FALLBACK + # op op_const FALLBACK + # op op_const_high16 FALLBACK + # op op_const_wide_16 FALLBACK + # op op_const_wide_32 FALLBACK + # op op_const_wide FALLBACK + # op op_const_wide_high16 FALLBACK + # op op_const_string FALLBACK + # op op_const_string_jumbo FALLBACK + # op op_const_class FALLBACK + # op op_monitor_enter FALLBACK + # op op_monitor_exit FALLBACK + # op op_check_cast FALLBACK + # op op_instance_of FALLBACK + # op op_array_length FALLBACK + # op op_new_instance FALLBACK + # op op_new_array FALLBACK + # op op_filled_new_array FALLBACK + # op op_filled_new_array_range FALLBACK + # op op_fill_array_data FALLBACK + # op op_throw FALLBACK + # op op_goto FALLBACK + # op op_goto_16 FALLBACK + # op op_goto_32 FALLBACK + # op op_packed_switch FALLBACK + # op op_sparse_switch FALLBACK + # op op_cmpl_float FALLBACK + # op op_cmpg_float FALLBACK + # op op_cmpl_double FALLBACK + # op op_cmpg_double FALLBACK + # op op_cmp_long FALLBACK + # op op_if_eq FALLBACK + # op op_if_ne FALLBACK + # op op_if_lt FALLBACK + # op op_if_ge FALLBACK + # op op_if_gt FALLBACK + # op op_if_le FALLBACK + # op op_if_eqz FALLBACK + # op op_if_nez FALLBACK + # op op_if_ltz FALLBACK + # op op_if_gez FALLBACK + # op op_if_gtz FALLBACK + # op op_if_lez FALLBACK + # op op_unused_3e FALLBACK + # op op_unused_3f FALLBACK + # op op_unused_40 FALLBACK + # op op_unused_41 FALLBACK + # op op_unused_42 FALLBACK + # op op_unused_43 FALLBACK + # op op_aget FALLBACK + # op op_aget_wide FALLBACK + # op op_aget_object FALLBACK + # op op_aget_boolean FALLBACK + # op op_aget_byte FALLBACK + # op op_aget_char FALLBACK + # op op_aget_short FALLBACK + # op op_aput FALLBACK + # op op_aput_wide FALLBACK + # op op_aput_object FALLBACK + # op op_aput_boolean FALLBACK + # op op_aput_byte FALLBACK + # op op_aput_char FALLBACK + # op op_aput_short FALLBACK + # op op_iget FALLBACK + # op op_iget_wide FALLBACK + # op op_iget_object FALLBACK + # op op_iget_boolean FALLBACK + # op op_iget_byte FALLBACK + # op op_iget_char FALLBACK + # op op_iget_short FALLBACK + # op op_iput FALLBACK + # op op_iput_wide FALLBACK + # op op_iput_object FALLBACK + # op op_iput_boolean FALLBACK + # op op_iput_byte FALLBACK + # op op_iput_char FALLBACK + # op op_iput_short FALLBACK + # op op_sget FALLBACK + # op op_sget_wide FALLBACK + # op op_sget_object FALLBACK + # op op_sget_boolean FALLBACK + # op op_sget_byte FALLBACK + # op op_sget_char FALLBACK + # op op_sget_short FALLBACK + # op op_sput FALLBACK + # op op_sput_wide FALLBACK + # op op_sput_object FALLBACK + # op op_sput_boolean FALLBACK + # op op_sput_byte FALLBACK + # op op_sput_char FALLBACK + # op op_sput_short FALLBACK + # op op_invoke_virtual FALLBACK + # op op_invoke_super FALLBACK + # op op_invoke_direct FALLBACK + # op op_invoke_static FALLBACK + # op op_invoke_interface FALLBACK + # op op_return_void_no_barrier FALLBACK + # op op_invoke_virtual_range FALLBACK + # op op_invoke_super_range FALLBACK + # op op_invoke_direct_range FALLBACK + # op op_invoke_static_range FALLBACK + # op op_invoke_interface_range FALLBACK + # op op_unused_79 FALLBACK + # op op_unused_7a FALLBACK + # op op_neg_int FALLBACK + # op op_not_int FALLBACK + # op op_neg_long FALLBACK + # op op_not_long FALLBACK + # op op_neg_float FALLBACK + # op op_neg_double FALLBACK + # op op_int_to_long FALLBACK + # op op_int_to_float FALLBACK + # op op_int_to_double FALLBACK + # op op_long_to_int FALLBACK + # op op_long_to_float FALLBACK + # op op_long_to_double FALLBACK + # op op_float_to_int FALLBACK + # op op_float_to_long FALLBACK + # op op_float_to_double FALLBACK + # op op_double_to_int FALLBACK + # op op_double_to_long FALLBACK + # op op_double_to_float FALLBACK + # op op_int_to_byte FALLBACK + # op op_int_to_char FALLBACK + # op op_int_to_short FALLBACK + # op op_add_int FALLBACK + # op op_sub_int FALLBACK + # op op_mul_int FALLBACK + # op op_div_int FALLBACK + # op op_rem_int FALLBACK + # op op_and_int FALLBACK + # op op_or_int FALLBACK + # op op_xor_int FALLBACK + # op op_shl_int FALLBACK + # op op_shr_int FALLBACK + # op op_ushr_int FALLBACK + # op op_add_long FALLBACK + # op op_sub_long FALLBACK + # op op_mul_long FALLBACK + # op op_div_long FALLBACK + # op op_rem_long FALLBACK + # op op_and_long FALLBACK + # op op_or_long FALLBACK + # op op_xor_long FALLBACK + # op op_shl_long FALLBACK + # op op_shr_long FALLBACK + # op op_ushr_long FALLBACK + # op op_add_float FALLBACK + # op op_sub_float FALLBACK + # op op_mul_float FALLBACK + # op op_div_float FALLBACK + # op op_rem_float FALLBACK + # op op_add_double FALLBACK + # op op_sub_double FALLBACK + # op op_mul_double FALLBACK + # op op_div_double FALLBACK + # op op_rem_double FALLBACK + # op op_add_int_2addr FALLBACK + # op op_sub_int_2addr FALLBACK + # op op_mul_int_2addr FALLBACK + # op op_div_int_2addr FALLBACK + # op op_rem_int_2addr FALLBACK + # op op_and_int_2addr FALLBACK + # op op_or_int_2addr FALLBACK + # op op_xor_int_2addr FALLBACK + # op op_shl_int_2addr FALLBACK + # op op_shr_int_2addr FALLBACK + # op op_ushr_int_2addr FALLBACK + # op op_add_long_2addr FALLBACK + # op op_sub_long_2addr FALLBACK + # op op_mul_long_2addr FALLBACK + # op op_div_long_2addr FALLBACK + # op op_rem_long_2addr FALLBACK + # op op_and_long_2addr FALLBACK + # op op_or_long_2addr FALLBACK + # op op_xor_long_2addr FALLBACK + # op op_shl_long_2addr FALLBACK + # op op_shr_long_2addr FALLBACK + # op op_ushr_long_2addr FALLBACK + # op op_add_float_2addr FALLBACK + # op op_sub_float_2addr FALLBACK + # op op_mul_float_2addr FALLBACK + # op op_div_float_2addr FALLBACK + # op op_rem_float_2addr FALLBACK + # op op_add_double_2addr FALLBACK + # op op_sub_double_2addr FALLBACK + # op op_mul_double_2addr FALLBACK + # op op_div_double_2addr FALLBACK + # op op_rem_double_2addr FALLBACK + # op op_add_int_lit16 FALLBACK + # op op_rsub_int FALLBACK + # op op_mul_int_lit16 FALLBACK + # op op_div_int_lit16 FALLBACK + # op op_rem_int_lit16 FALLBACK + # op op_and_int_lit16 FALLBACK + # op op_or_int_lit16 FALLBACK + # op op_xor_int_lit16 FALLBACK + # op op_add_int_lit8 FALLBACK + # op op_rsub_int_lit8 FALLBACK + # op op_mul_int_lit8 FALLBACK + # op op_div_int_lit8 FALLBACK + # op op_rem_int_lit8 FALLBACK + # op op_and_int_lit8 FALLBACK + # op op_or_int_lit8 FALLBACK + # op op_xor_int_lit8 FALLBACK + # op op_shl_int_lit8 FALLBACK + # op op_shr_int_lit8 FALLBACK + # op op_ushr_int_lit8 FALLBACK + # op op_iget_quick FALLBACK + # op op_iget_wide_quick FALLBACK + # op op_iget_object_quick FALLBACK + # op op_iput_quick FALLBACK + # op op_iput_wide_quick FALLBACK + # op op_iput_object_quick FALLBACK + # op op_invoke_virtual_quick FALLBACK + # op op_invoke_virtual_range_quick FALLBACK + # op op_iput_boolean_quick FALLBACK + # op op_iput_byte_quick FALLBACK + # op op_iput_char_quick FALLBACK + # op op_iput_short_quick FALLBACK + # op op_iget_boolean_quick FALLBACK + # op op_iget_byte_quick FALLBACK + # op op_iget_char_quick FALLBACK + # op op_iget_short_quick FALLBACK + op op_invoke_lambda FALLBACK + # op op_unused_f4 FALLBACK + op op_capture_variable FALLBACK + op op_create_lambda FALLBACK + op op_liberate_variable FALLBACK + op op_box_lambda FALLBACK + op op_unbox_lambda FALLBACK + # op op_unused_fa FALLBACK + # op op_unused_fb FALLBACK + # op op_unused_fc FALLBACK + # op op_unused_fd FALLBACK + # op op_unused_fe FALLBACK + # op op_unused_ff FALLBACK op-end # common subroutines for asm diff --git a/runtime/interpreter/mterp/out/mterp_arm64.S b/runtime/interpreter/mterp/out/mterp_arm64.S new file mode 100644 index 000000000..e9d28abf8 --- /dev/null +++ b/runtime/interpreter/mterp/out/mterp_arm64.S @@ -0,0 +1,11726 @@ +/* + * This file was generated automatically by gen-mterp.py for 'arm64'. + * + * --> DO NOT EDIT <-- + */ + +/* File: arm64/header.S */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + Art assembly interpreter notes: + + First validate assembly code by implementing ExecuteXXXImpl() style body (doesn't + handle invoke, allows higher-level code to create frame & shadow frame. + + Once that's working, support direct entry code & eliminate shadow frame (and + excess locals allocation. + + Some (hopefully) temporary ugliness. We'll treat xFP as pointing to the + base of the vreg array within the shadow frame. Access the other fields, + dex_pc_, method_ and number_of_vregs_ via negative offsets. For now, we'll continue + the shadow frame mechanism of double-storing object references - via xFP & + number_of_vregs_. + + */ + +/* +ARM64 Runtime register usage conventions. + + r0 : w0 is 32-bit return register and x0 is 64-bit. + r0-r7 : Argument registers. + r8-r15 : Caller save registers (used as temporary registers). + r16-r17: Also known as ip0-ip1, respectively. Used as scratch registers by + the linker, by the trampolines and other stubs (the backend uses + these as temporary registers). + r18 : Caller save register (used as temporary register). + r19 : Pointer to thread-local storage. + r20-r29: Callee save registers. + r30 : (lr) is reserved (the link register). + rsp : (sp) is reserved (the stack pointer). + rzr : (zr) is reserved (the zero register). + + Floating-point registers + v0-v31 + + v0 : s0 is return register for singles (32-bit) and d0 for doubles (64-bit). + This is analogous to the C/C++ (hard-float) calling convention. + v0-v7 : Floating-point argument registers in both Dalvik and C/C++ conventions. + Also used as temporary and codegen scratch registers. + + v0-v7 and v16-v31 : trashed across C calls. + v8-v15 : bottom 64-bits preserved across C calls (d8-d15 are preserved). + + v16-v31: Used as codegen temp/scratch. + v8-v15 : Can be used for promotion. + + Must maintain 16-byte stack alignment. + +Mterp notes: + +The following registers have fixed assignments: + + reg nick purpose + x20 xPC interpreted program counter, used for fetching instructions + x21 xFP interpreted frame pointer, used for accessing locals and args + x22 xSELF self (Thread) pointer + x23 xINST first 16-bit code unit of current instruction + x24 xIBASE interpreted instruction base pointer, used for computed goto + x25 xREFS base of object references in shadow frame (ideally, we'll get rid of this later). + x16 ip scratch reg + x17 ip2 scratch reg (used by macros) + +Macros are provided for common operations. They MUST NOT alter unspecified registers or condition +codes. +*/ + +/* + * This is a #include, not a %include, because we want the C pre-processor + * to expand the macros into assembler assignment statements. + */ +#include "asm_support.h" + +/* During bringup, we'll use the shadow frame model instead of xFP */ +/* single-purpose registers, given names for clarity */ +#define xPC x20 +#define xFP x21 +#define xSELF x22 +#define xINST x23 +#define wINST w23 +#define xIBASE x24 +#define xREFS x25 +#define ip x16 +#define ip2 x17 + +/* + * Instead of holding a pointer to the shadow frame, we keep xFP at the base of the vregs. So, + * to access other shadow frame fields, we need to use a backwards offset. Define those here. + */ +#define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET) +#define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET) +#define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET) +#define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET) +#define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET) +#define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET) +#define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET) +#define OFF_FP_CODE_ITEM OFF_FP(SHADOWFRAME_CODE_ITEM_OFFSET) +#define OFF_FP_SHADOWFRAME (-SHADOWFRAME_VREGS_OFFSET) + +/* + * + * The reference interpreter performs explicit suspect checks, which is somewhat wasteful. + * Dalvik's interpreter folded suspend checks into the jump table mechanism, and eventually + * mterp should do so as well. + */ +#define MTERP_SUSPEND 0 + +/* + * "export" the PC to dex_pc field in the shadow frame, f/b/o future exception objects. Must + * be done *before* something throws. + * + * It's okay to do this more than once. + * + * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped + * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction + * offset into the code_items_[] array. For effiency, we will "export" the + * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC + * to convert to a dex pc when needed. + */ +.macro EXPORT_PC + str xPC, [xFP, #OFF_FP_DEX_PC_PTR] +.endm + +/* + * Fetch the next instruction from xPC into wINST. Does not advance xPC. + */ +.macro FETCH_INST + ldrh wINST, [xPC] +.endm + +/* + * Fetch the next instruction from the specified offset. Advances xPC + * to point to the next instruction. "_count" is in 16-bit code units. + * + * Because of the limited size of immediate constants on ARM, this is only + * suitable for small forward movements (i.e. don't try to implement "goto" + * with this). + * + * This must come AFTER anything that can throw an exception, or the + * exception catch may miss. (This also implies that it must come after + * EXPORT_PC.) + */ +.macro FETCH_ADVANCE_INST count + ldrh wINST, [xPC, #((\count)*2)]! +.endm + +/* + * The operation performed here is similar to FETCH_ADVANCE_INST, except the + * src and dest registers are parameterized (not hard-wired to xPC and xINST). + */ +.macro PREFETCH_ADVANCE_INST dreg, sreg, count + ldrh \dreg, [\sreg, #((\count)*2)]! +.endm + +/* + * Similar to FETCH_ADVANCE_INST, but does not update xPC. Used to load + * xINST ahead of possible exception point. Be sure to manually advance xPC + * later. + */ +.macro PREFETCH_INST count + ldrh wINST, [xPC, #((\count)*2)] +.endm + +/* Advance xPC by some number of code units. */ +.macro ADVANCE count + add xPC, xPC, #((\count)*2) +.endm + +/* + * Fetch the next instruction from an offset specified by _reg and advance xPC. + * xPC to point to the next instruction. "_reg" must specify the distance + * in bytes, *not* 16-bit code units, and may be a signed value. Must not set flags. + * + */ +.macro FETCH_ADVANCE_INST_RB reg + add xPC, xPC, \reg, sxtw + ldrh wINST, [xPC] +.endm + +/* + * Fetch a half-word code unit from an offset past the current PC. The + * "_count" value is in 16-bit code units. Does not advance xPC. + * + * The "_S" variant works the same but treats the value as signed. + */ +.macro FETCH reg, count + ldrh \reg, [xPC, #((\count)*2)] +.endm + +.macro FETCH_S reg, count + ldrsh \reg, [xPC, #((\count)*2)] +.endm + +/* + * Fetch one byte from an offset past the current PC. Pass in the same + * "_count" as you would for FETCH, and an additional 0/1 indicating which + * byte of the halfword you want (lo/hi). + */ +.macro FETCH_B reg, count, byte + ldrb \reg, [xPC, #((\count)*2+(\byte))] +.endm + +/* + * Put the instruction's opcode field into the specified register. + */ +.macro GET_INST_OPCODE reg + and \reg, xINST, #255 +.endm + +/* + * Put the prefetched instruction's opcode field into the specified register. + */ +.macro GET_PREFETCHED_OPCODE oreg, ireg + and \oreg, \ireg, #255 +.endm + +/* + * Begin executing the opcode in _reg. Clobbers reg + */ + +.macro GOTO_OPCODE reg + add \reg, xIBASE, \reg, lsl #7 + br \reg +.endm +.macro GOTO_OPCODE_BASE base,reg + add \reg, \base, \reg, lsl #7 + br \reg +.endm + +/* + * Get/set the 32-bit value from a Dalvik register. + */ +.macro GET_VREG reg, vreg + ldr \reg, [xFP, \vreg, uxtw #2] +.endm +.macro SET_VREG reg, vreg + str \reg, [xFP, \vreg, uxtw #2] + str wzr, [xREFS, \vreg, uxtw #2] +.endm +.macro SET_VREG_OBJECT reg, vreg, tmpreg + str \reg, [xFP, \vreg, uxtw #2] + str \reg, [xREFS, \vreg, uxtw #2] +.endm + +/* + * Get/set the 64-bit value from a Dalvik register. + * TUNING: can we do better here? + */ +.macro GET_VREG_WIDE reg, vreg + add ip2, xFP, \vreg, lsl #2 + ldr \reg, [ip2] +.endm +.macro SET_VREG_WIDE reg, vreg + add ip2, xFP, \vreg, lsl #2 + str \reg, [ip2] + add ip2, xREFS, \vreg, lsl #2 + str xzr, [ip2] +.endm + +/* + * Convert a virtual register index into an address. + */ +.macro VREG_INDEX_TO_ADDR reg, vreg + add \reg, xFP, \vreg, lsl #2 /* WARNING/FIXME: handle shadow frame vreg zero if store */ +.endm + +/* + * Refresh handler table. + */ +.macro REFRESH_IBASE + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] +.endm + +/* File: arm64/entry.S */ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + .text + +/* + * Interpreter entry point. + * On entry: + * x0 Thread* self/ + * x1 code_item + * x2 ShadowFrame + * x3 JValue* result_register + * + */ + .global ExecuteMterpImpl + .type ExecuteMterpImpl, %function + .balign 16 + +ExecuteMterpImpl: + .cfi_startproc + stp xIBASE, xREFS, [sp, #-64]! + stp xSELF, xINST, [sp, #16] + stp xPC, xFP, [sp, #32] + stp fp, lr, [sp, #48] + add fp, sp, #48 + + /* Remember the return register */ + str x3, [x2, #SHADOWFRAME_RESULT_REGISTER_OFFSET] + + /* Remember the code_item */ + str x1, [x2, #SHADOWFRAME_CODE_ITEM_OFFSET] + + /* set up "named" registers */ + mov xSELF, x0 + ldr w0, [x2, #SHADOWFRAME_NUMBER_OF_VREGS_OFFSET] + add xFP, x2, #SHADOWFRAME_VREGS_OFFSET // point to insns[] (i.e. - the dalivk byte code). + add xREFS, xFP, w0, lsl #2 // point to reference array in shadow frame + ldr w0, [x2, #SHADOWFRAME_DEX_PC_OFFSET] // Get starting dex_pc. + add xPC, x1, #CODEITEM_INSNS_OFFSET // Point to base of insns[] + add xPC, xPC, w0, lsl #1 // Create direct pointer to 1st dex opcode + EXPORT_PC + + /* Starting ibase */ + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] + + /* start executing the instruction at rPC */ + FETCH_INST // load wINST from rPC + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + /* NOTE: no fallthrough */ + + + .global artMterpAsmInstructionStart + .type artMterpAsmInstructionStart, %function +artMterpAsmInstructionStart = .L_op_nop + .text + +/* ------------------------------ */ + .balign 128 +.L_op_nop: /* 0x00 */ +/* File: arm64/op_nop.S */ + FETCH_ADVANCE_INST 1 // advance to next instr, load rINST + GET_INST_OPCODE ip // ip<- opcode from rINST + GOTO_OPCODE ip // execute it + +/* ------------------------------ */ + .balign 128 +.L_op_move: /* 0x01 */ +/* File: arm64/op_move.S */ + /* for move, move-object, long-to-int */ + /* op vA, vB */ + lsr w1, wINST, #12 // x1<- B from 15:12 + ubfx w0, wINST, #8, #4 // x0<- A from 11:8 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + GET_VREG w2, w1 // x2<- fp[B] + GET_INST_OPCODE ip // ip<- opcode from wINST + .if 0 + SET_VREG_OBJECT w2, w0 // fp[A]<- x2 + .else + SET_VREG w2, w0 // fp[A]<- x2 + .endif + GOTO_OPCODE ip // execute next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_move_from16: /* 0x02 */ +/* File: arm64/op_move_from16.S */ + /* for: move/from16, move-object/from16 */ + /* op vAA, vBBBB */ + FETCH w1, 1 // r1<- BBBB + lsr w0, wINST, #8 // r0<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + GET_VREG w2, w1 // r2<- fp[BBBB] + GET_INST_OPCODE ip // extract opcode from wINST + .if 0 + SET_VREG_OBJECT w2, w0 // fp[AA]<- r2 + .else + SET_VREG w2, w0 // fp[AA]<- r2 + .endif + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_move_16: /* 0x03 */ +/* File: arm64/op_move_16.S */ + /* for: move/16, move-object/16 */ + /* op vAAAA, vBBBB */ + FETCH w1, 2 // w1<- BBBB + FETCH w0, 1 // w0<- AAAA + FETCH_ADVANCE_INST 3 // advance xPC, load xINST + GET_VREG w2, w1 // w2<- fp[BBBB] + GET_INST_OPCODE ip // extract opcode from xINST + .if 0 + SET_VREG_OBJECT w2, w0 // fp[AAAA]<- w2 + .else + SET_VREG w2, w0 // fp[AAAA]<- w2 + .endif + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_move_wide: /* 0x04 */ +/* File: arm64/op_move_wide.S */ + /* move-wide vA, vB */ + /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ + lsr w3, wINST, #12 // w3<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE x3, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x3, w2 + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_move_wide_from16: /* 0x05 */ +/* File: arm64/op_move_wide_from16.S */ + /* move-wide/from16 vAA, vBBBB */ + /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ + FETCH w3, 1 // w3<- BBBB + lsr w2, wINST, #8 // w2<- AA + GET_VREG_WIDE x3, w3 + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x3, w2 + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_move_wide_16: /* 0x06 */ +/* File: arm64/op_move_wide_16.S */ + /* move-wide/16 vAAAA, vBBBB */ + /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ + FETCH w3, 2 // w3<- BBBB + FETCH w2, 1 // w2<- AAAA + GET_VREG_WIDE x3, w3 + FETCH_ADVANCE_INST 3 // advance rPC, load rINST + SET_VREG_WIDE x3, w2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_move_object: /* 0x07 */ +/* File: arm64/op_move_object.S */ +/* File: arm64/op_move.S */ + /* for move, move-object, long-to-int */ + /* op vA, vB */ + lsr w1, wINST, #12 // x1<- B from 15:12 + ubfx w0, wINST, #8, #4 // x0<- A from 11:8 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + GET_VREG w2, w1 // x2<- fp[B] + GET_INST_OPCODE ip // ip<- opcode from wINST + .if 1 + SET_VREG_OBJECT w2, w0 // fp[A]<- x2 + .else + SET_VREG w2, w0 // fp[A]<- x2 + .endif + GOTO_OPCODE ip // execute next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_move_object_from16: /* 0x08 */ +/* File: arm64/op_move_object_from16.S */ +/* File: arm64/op_move_from16.S */ + /* for: move/from16, move-object/from16 */ + /* op vAA, vBBBB */ + FETCH w1, 1 // r1<- BBBB + lsr w0, wINST, #8 // r0<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + GET_VREG w2, w1 // r2<- fp[BBBB] + GET_INST_OPCODE ip // extract opcode from wINST + .if 1 + SET_VREG_OBJECT w2, w0 // fp[AA]<- r2 + .else + SET_VREG w2, w0 // fp[AA]<- r2 + .endif + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_move_object_16: /* 0x09 */ +/* File: arm64/op_move_object_16.S */ +/* File: arm64/op_move_16.S */ + /* for: move/16, move-object/16 */ + /* op vAAAA, vBBBB */ + FETCH w1, 2 // w1<- BBBB + FETCH w0, 1 // w0<- AAAA + FETCH_ADVANCE_INST 3 // advance xPC, load xINST + GET_VREG w2, w1 // w2<- fp[BBBB] + GET_INST_OPCODE ip // extract opcode from xINST + .if 1 + SET_VREG_OBJECT w2, w0 // fp[AAAA]<- w2 + .else + SET_VREG w2, w0 // fp[AAAA]<- w2 + .endif + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_move_result: /* 0x0a */ +/* File: arm64/op_move_result.S */ + /* for: move-result, move-result-object */ + /* op vAA */ + lsr w2, wINST, #8 // r2<- AA + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + ldr x0, [xFP, #OFF_FP_RESULT_REGISTER] // get pointer to result JType. + ldr w0, [x0] // r0 <- result.i. + GET_INST_OPCODE ip // extract opcode from wINST + .if 0 + SET_VREG_OBJECT w0, w2, w1 // fp[AA]<- r0 + .else + SET_VREG w0, w2 // fp[AA]<- r0 + .endif + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_move_result_wide: /* 0x0b */ +/* File: arm64/op_move_result_wide.S */ + /* for: move-result-wide */ + /* op vAA */ + lsr w2, wINST, #8 // r2<- AA + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + ldr x0, [xFP, #OFF_FP_RESULT_REGISTER] // get pointer to result JType. + ldr x0, [x0] // r0 <- result.i. + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x0, x2 // fp[AA]<- r0 + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_move_result_object: /* 0x0c */ +/* File: arm64/op_move_result_object.S */ +/* File: arm64/op_move_result.S */ + /* for: move-result, move-result-object */ + /* op vAA */ + lsr w2, wINST, #8 // r2<- AA + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + ldr x0, [xFP, #OFF_FP_RESULT_REGISTER] // get pointer to result JType. + ldr w0, [x0] // r0 <- result.i. + GET_INST_OPCODE ip // extract opcode from wINST + .if 1 + SET_VREG_OBJECT w0, w2, w1 // fp[AA]<- r0 + .else + SET_VREG w0, w2 // fp[AA]<- r0 + .endif + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_move_exception: /* 0x0d */ +/* File: arm64/op_move_exception.S */ + /* move-exception vAA */ + lsr w2, wINST, #8 // w2<- AA + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + mov x1, #0 // w1<- 0 + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + SET_VREG_OBJECT w3, w2 // fp[AA]<- exception obj + GET_INST_OPCODE ip // extract opcode from rINST + str x1, [xSELF, #THREAD_EXCEPTION_OFFSET] // clear exception + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_return_void: /* 0x0e */ +/* File: arm64/op_return_void.S */ + .extern MterpThreadFenceForConstructor + bl MterpThreadFenceForConstructor + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov x0, xSELF + ands w7, w7, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.ne .Lop_return_void_check +.Lop_return_void_return: + mov x0, #0 + b MterpReturn +.Lop_return_void_check: + bl MterpSuspendCheck // (self) + b .Lop_return_void_return + +/* ------------------------------ */ + .balign 128 +.L_op_return: /* 0x0f */ +/* File: arm64/op_return.S */ + /* + * Return a 32-bit value. + * + * for: return, return-object + */ + /* op vAA */ + .extern MterpThreadFenceForConstructor + bl MterpThreadFenceForConstructor + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov x0, xSELF + ands w7, w7, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.ne .Lop_return_check +.Lop_return_return: + lsr w2, wINST, #8 // r2<- AA + GET_VREG w0, w2 // r0<- vAA + b MterpReturn +.Lop_return_check: + bl MterpSuspendCheck // (self) + b .Lop_return_return + +/* ------------------------------ */ + .balign 128 +.L_op_return_wide: /* 0x10 */ +/* File: arm64/op_return_wide.S */ + /* + * Return a 64-bit value. + */ + /* return-wide vAA */ + /* op vAA */ + .extern MterpThreadFenceForConstructor + bl MterpThreadFenceForConstructor + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov x0, xSELF + ands w7, w7, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.ne .Lop_return_wide_check +.Lop_return_wide_return: + lsr w2, wINST, #8 // w2<- AA + GET_VREG_WIDE x0, w2 // x0<- vAA + b MterpReturn +.Lop_return_wide_check: + bl MterpSuspendCheck // (self) + b .Lop_return_wide_return + +/* ------------------------------ */ + .balign 128 +.L_op_return_object: /* 0x11 */ +/* File: arm64/op_return_object.S */ +/* File: arm64/op_return.S */ + /* + * Return a 32-bit value. + * + * for: return, return-object + */ + /* op vAA */ + .extern MterpThreadFenceForConstructor + bl MterpThreadFenceForConstructor + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov x0, xSELF + ands w7, w7, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.ne .Lop_return_object_check +.Lop_return_object_return: + lsr w2, wINST, #8 // r2<- AA + GET_VREG w0, w2 // r0<- vAA + b MterpReturn +.Lop_return_object_check: + bl MterpSuspendCheck // (self) + b .Lop_return_object_return + + +/* ------------------------------ */ + .balign 128 +.L_op_const_4: /* 0x12 */ +/* File: arm64/op_const_4.S */ + /* const/4 vA, #+B */ + lsl w1, wINST, #16 // w1<- Bxxx0000 + ubfx w0, wINST, #8, #4 // w0<- A + FETCH_ADVANCE_INST 1 // advance xPC, load wINST + asr w1, w1, #28 // w1<- sssssssB (sign-extended) + GET_INST_OPCODE ip // ip<- opcode from xINST + SET_VREG w1, w0 // fp[A]<- w1 + GOTO_OPCODE ip // execute next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_const_16: /* 0x13 */ +/* File: arm64/op_const_16.S */ + /* const/16 vAA, #+BBBB */ + FETCH_S w0, 1 // w0<- ssssBBBB (sign-extended + lsr w3, wINST, #8 // w3<- AA + FETCH_ADVANCE_INST 2 // advance xPC, load wINST + SET_VREG w0, w3 // vAA<- w0 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_const: /* 0x14 */ +/* File: arm64/op_const.S */ + /* const vAA, #+BBBBbbbb */ + lsr w3, wINST, #8 // w3<- AA + FETCH w0, 1 // w0<- bbbb (low + FETCH w1, 2 // w1<- BBBB (high + FETCH_ADVANCE_INST 3 // advance rPC, load wINST + orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG w0, w3 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_const_high16: /* 0x15 */ +/* File: arm64/op_const_high16.S */ + /* const/high16 vAA, #+BBBB0000 */ + FETCH w0, 1 // r0<- 0000BBBB (zero-extended + lsr w3, wINST, #8 // r3<- AA + lsl w0, w0, #16 // r0<- BBBB0000 + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + SET_VREG w0, w3 // vAA<- r0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_const_wide_16: /* 0x16 */ +/* File: arm64/op_const_wide_16.S */ + /* const-wide/16 vAA, #+BBBB */ + FETCH_S w0, 1 // w0<- ssssBBBB (sign-extended + lsr w3, wINST, #8 // w3<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + sbfm x0, x0, 0, 31 + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w3 + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_const_wide_32: /* 0x17 */ +/* File: arm64/op_const_wide_32.S */ + /* const-wide/32 vAA, #+BBBBbbbb */ + FETCH w0, 1 // w0<- 0000bbbb (low) + lsr w3, wINST, #8 // w3<- AA + FETCH_S w2, 2 // w2<- ssssBBBB (high) + FETCH_ADVANCE_INST 3 // advance rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + orr w0, w0, w2, lsl #16 // w0<- BBBBbbbb + sbfm x0, x0, 0, 31 + SET_VREG_WIDE x0, w3 + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_const_wide: /* 0x18 */ +/* File: arm64/op_const_wide.S */ + /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ + FETCH w0, 1 // w0<- bbbb (low) + FETCH w1, 2 // w1<- BBBB (low middle) + FETCH w2, 3 // w2<- hhhh (high middle) + FETCH w3, 4 // w3<- HHHH (high) + lsr w4, wINST, #8 // r4<- AA + FETCH_ADVANCE_INST 5 // advance rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb + orr x0, x0, x2, lsl #32 // w0<- hhhhBBBBbbbb + orr x0, x0, x3, lsl #48 // w0<- HHHHhhhhBBBBbbbb + SET_VREG_WIDE x0, w4 + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_const_wide_high16: /* 0x19 */ +/* File: arm64/op_const_wide_high16.S */ + /* const-wide/high16 vAA, #+BBBB000000000000 */ + FETCH w0, 1 // w0<- 0000BBBB (zero-extended) + lsr w1, wINST, #8 // w1<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + lsl x0, x0, #48 + SET_VREG_WIDE x0, w1 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_const_string: /* 0x1a */ +/* File: arm64/op_const_string.S */ + /* const/string vAA, String//BBBB */ + EXPORT_PC + FETCH w0, 1 // w0<- BBBB + lsr w1, wINST, #8 // w1<- AA + add x2, xFP, #OFF_FP_SHADOWFRAME + mov x3, xSELF + bl MterpConstString // (index, tgt_reg, shadow_frame, self) + PREFETCH_INST 2 // load rINST + cbnz w0, MterpPossibleException // let reference interpreter deal with it. + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_const_string_jumbo: /* 0x1b */ +/* File: arm64/op_const_string_jumbo.S */ + /* const/string vAA, String//BBBBBBBB */ + EXPORT_PC + FETCH w0, 1 // w0<- bbbb (low + FETCH w2, 2 // w2<- BBBB (high + lsr w1, wINST, #8 // w1<- AA + orr w0, w0, w2, lsl #16 // w1<- BBBBbbbb + add x2, xFP, #OFF_FP_SHADOWFRAME + mov x3, xSELF + bl MterpConstString // (index, tgt_reg, shadow_frame, self) + PREFETCH_INST 3 // advance rPC + cbnz w0, MterpPossibleException // let reference interpreter deal with it. + ADVANCE 3 // advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_const_class: /* 0x1c */ +/* File: arm64/op_const_class.S */ + /* const/class vAA, Class//BBBB */ + EXPORT_PC + FETCH w0, 1 // w0<- BBBB + lsr w1, wINST, #8 // w1<- AA + add x2, xFP, #OFF_FP_SHADOWFRAME + mov x3, xSELF + bl MterpConstClass // (index, tgt_reg, shadow_frame, self) + PREFETCH_INST 2 + cbnz w0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_monitor_enter: /* 0x1d */ +/* File: arm64/op_monitor_enter.S */ + /* + * Synchronize on an object. + */ + /* monitor-enter vAA */ + EXPORT_PC + lsr w2, wINST, #8 // w2<- AA + GET_VREG w0, w2 // w0<- vAA (object) + mov x1, xSELF // w1<- self + bl artLockObjectFromCode + cbnz w0, MterpException + FETCH_ADVANCE_INST 1 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_monitor_exit: /* 0x1e */ +/* File: arm64/op_monitor_exit.S */ + /* + * Unlock an object. + * + * Exceptions that occur when unlocking a monitor need to appear as + * if they happened at the following instruction. See the Dalvik + * instruction spec. + */ + /* monitor-exit vAA */ + EXPORT_PC + lsr w2, wINST, #8 // w2<- AA + GET_VREG w0, w2 // w0<- vAA (object) + mov x1, xSELF // w0<- self + bl artUnlockObjectFromCode // w0<- success for unlock(self, obj) + cbnz w0, MterpException + FETCH_ADVANCE_INST 1 // before throw: advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_check_cast: /* 0x1f */ +/* File: arm64/op_check_cast.S */ + /* + * Check to see if a cast from one class to another is allowed. + */ + /* check-cast vAA, class//BBBB */ + EXPORT_PC + FETCH w0, 1 // w0<- BBBB + lsr w1, wINST, #8 // w1<- AA + VREG_INDEX_TO_ADDR x1, w1 // w1<- &object + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- method + mov x3, xSELF // w3<- self + bl MterpCheckCast // (index, &obj, method, self) + PREFETCH_INST 2 + cbnz w0, MterpPossibleException + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_instance_of: /* 0x20 */ +/* File: arm64/op_instance_of.S */ + /* + * Check to see if an object reference is an instance of a class. + * + * Most common situation is a non-null object, being compared against + * an already-resolved class. + */ + /* instance-of vA, vB, class//CCCC */ + EXPORT_PC + FETCH w0, 1 // w0<- CCCC + lsr w1, wINST, #12 // w1<- B + VREG_INDEX_TO_ADDR x1, w1 // w1<- &object + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- method + mov x3, xSELF // w3<- self + bl MterpInstanceOf // (index, &obj, method, self) + ldr x1, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w2, wINST, #8 // w2<- A+ + and w2, w2, #15 // w2<- A + PREFETCH_INST 2 + cbnz x1, MterpException + ADVANCE 2 // advance rPC + SET_VREG w0, w2 // vA<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_array_length: /* 0x21 */ +/* File: arm64/op_array_length.S */ + /* + * Return the length of an array. + */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w0, w1 // w0<- vB (object ref) + cbz w0, common_errNullObject // yup, fail + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- array length + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w3, w2 // vB<- length + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_new_instance: /* 0x22 */ +/* File: arm64/op_new_instance.S */ + /* + * Create a new instance of a class. + */ + /* new-instance vAA, class//BBBB */ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xSELF + mov w2, wINST + bl MterpNewInstance // (shadow_frame, self, inst_data) + cbz w0, MterpPossibleException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_new_array: /* 0x23 */ +/* File: arm64/op_new_array.S */ + /* + * Allocate an array of objects, specified with the array class + * and a count. + * + * The verifier guarantees that this is an array class, so we don't + * check for it here. + */ + /* new-array vA, vB, class//CCCC */ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov w2, wINST + mov x3, xSELF + bl MterpNewArray + cbz w0, MterpPossibleException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_filled_new_array: /* 0x24 */ +/* File: arm64/op_filled_new_array.S */ + /* + * Create a new array with elements filled from registers. + * + * for: filled-new-array, filled-new-array/range + */ + /* op vB, {vD, vE, vF, vG, vA}, class//CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, type//BBBB */ + .extern MterpFilledNewArray + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov x2, xSELF + bl MterpFilledNewArray + cbz w0, MterpPossibleException + FETCH_ADVANCE_INST 3 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_filled_new_array_range: /* 0x25 */ +/* File: arm64/op_filled_new_array_range.S */ +/* File: arm64/op_filled_new_array.S */ + /* + * Create a new array with elements filled from registers. + * + * for: filled-new-array, filled-new-array/range + */ + /* op vB, {vD, vE, vF, vG, vA}, class//CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, type//BBBB */ + .extern MterpFilledNewArrayRange + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov x2, xSELF + bl MterpFilledNewArrayRange + cbz w0, MterpPossibleException + FETCH_ADVANCE_INST 3 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_fill_array_data: /* 0x26 */ +/* File: arm64/op_fill_array_data.S */ + /* fill-array-data vAA, +BBBBBBBB */ + EXPORT_PC + FETCH w0, 1 // w0<- bbbb (lo) + FETCH w1, 2 // w1<- BBBB (hi) + lsr w3, wINST, #8 // w3<- AA + orr w1, w0, w1, lsl #16 // w1<- BBBBbbbb + GET_VREG w0, w3 // w0<- vAA (array object) + add x1, xPC, w1, lsl #1 // w1<- PC + BBBBbbbb*2 (array data off.) + bl MterpFillArrayData // (obj, payload) + cbz w0, MterpPossibleException // exception? + FETCH_ADVANCE_INST 3 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_throw: /* 0x27 */ +/* File: arm64/op_throw.S */ + /* + * Throw an exception object in the current thread. + */ + /* throw vAA */ + EXPORT_PC + lsr w2, wINST, #8 // r2<- AA + GET_VREG w1, w2 // r1<- vAA (exception object) + cbz w1, common_errNullObject + str x1, [xSELF, #THREAD_EXCEPTION_OFFSET] // thread->exception<- obj + b MterpException + +/* ------------------------------ */ + .balign 128 +.L_op_goto: /* 0x28 */ +/* File: arm64/op_goto.S */ + /* + * Unconditional branch, 8-bit offset. + * + * The branch distance is a signed code-unit offset, which we need to + * double to get a byte offset. + */ + /* goto +AA */ + /* tuning: use sbfx for 6t2+ targets */ +#if MTERP_SUSPEND + mov w0, wINST, lsl #16 // w0<- AAxx0000 + movs w1, w0, asr #24 // w1<- ssssssAA (sign-extended) + add w2, w1, w1 // w2<- byte offset, set flags + // If backwards branch refresh rIBASE + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh handler base + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] // Preload flags for MterpCheckSuspendAndContinue + lsl w0, wINST, #16 // w0<- AAxx0000 + asr w0, w0, #24 // w0<- ssssssAA (sign-extended) + adds w1, w0, w0 // Convert dalvik offset to byte offset, setting flags + FETCH_ADVANCE_INST_RB w1 // load wINST and advance xPC + // If backwards branch refresh rIBASE + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + +/* ------------------------------ */ + .balign 128 +.L_op_goto_16: /* 0x29 */ +/* File: arm64/op_goto_16.S */ + /* + * Unconditional branch, 16-bit offset. + * + * The branch distance is a signed code-unit offset, which we need to + * double to get a byte offset. + */ + /* goto/16 +AAAA */ +#if MTERP_SUSPEND + FETCH_S w0, 1 // w0<- ssssAAAA (sign-extended) + adds w1, w0, w0 // w1<- byte offset, flags set + FETCH_ADVANCE_INST_RB w1 // update rPC, load rINST + ldrmi xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh handler base + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction +#else + FETCH_S w0, 1 // w0<- ssssAAAA (sign-extended) + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + adds w1, w0, w0 // w1<- byte offset, flags set + FETCH_ADVANCE_INST_RB w1 // update rPC, load rINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction +#endif + +/* ------------------------------ */ + .balign 128 +.L_op_goto_32: /* 0x2a */ +/* File: arm64/op_goto_32.S */ + /* + * Unconditional branch, 32-bit offset. + * + * The branch distance is a signed code-unit offset, which we need to + * double to get a byte offset. + * + * Unlike most opcodes, this one is allowed to branch to itself, so + * our "backward branch" test must be "<=0" instead of "<0". Because + * we need the V bit set, we'll use an adds to convert from Dalvik + * offset to byte offset. + */ + /* goto/32 +AAAAAAAA */ +#if MTERP_SUSPEND + FETCH w0, 1 // w0<- aaaa (lo) + FETCH w1, 2 // w1<- AAAA (hi) + orr w0, w0, w1, lsl #16 // w0<- AAAAaaaa + adds w1, w0, w0 // w1<- byte offset + FETCH_ADVANCE_INST_RB w1 // update rPC, load xINST + ldrle xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh handler base + GET_INST_OPCODE ip // extract opcode from xINST + GOTO_OPCODE ip // jump to next instruction +#else + FETCH w0, 1 // w0<- aaaa (lo) + FETCH w1, 2 // w1<- AAAA (hi) + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + orr w0, w0, w1, lsl #16 // w0<- AAAAaaaa + adds w1, w0, w0 // w1<- byte offset + FETCH_ADVANCE_INST_RB w1 // update rPC, load xINST + b.le MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from xINST + GOTO_OPCODE ip // jump to next instruction +#endif + +/* ------------------------------ */ + .balign 128 +.L_op_packed_switch: /* 0x2b */ +/* File: arm64/op_packed_switch.S */ + /* + * Handle a packed-switch or sparse-switch instruction. In both cases + * we decode it and hand it off to a helper function. + * + * We don't really expect backward branches in a switch statement, but + * they're perfectly legal, so we check for them here. + * + * for: packed-switch, sparse-switch + */ + /* op vAA, +BBBB */ +#if MTERP_SUSPEND + FETCH w0, 1 // w0<- bbbb (lo) + FETCH w1, 2 // w1<- BBBB (hi) + mov w3, wINST, lsr #8 // w3<- AA + orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb + GET_VREG w1, w3 // w1<- vAA + add w0, rPC, w0, lsl #1 // w0<- PC + BBBBbbbb*2 + bl MterpDoPackedSwitch // w0<- code-unit branch offset + adds w1, w0, w0 // w1<- byte offset; clear V + ldrle rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh handler base + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + FETCH w0, 1 // w0<- bbbb (lo) + FETCH w1, 2 // w1<- BBBB (hi) + lsr w3, wINST, #8 // w3<- AA + orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb + GET_VREG w1, w3 // w1<- vAA + add x0, xPC, w0, lsl #1 // w0<- PC + BBBBbbbb*2 + bl MterpDoPackedSwitch // w0<- code-unit branch offset + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + adds w1, w0, w0 // w1<- byte offset; clear V + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + b.le MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + +/* ------------------------------ */ + .balign 128 +.L_op_sparse_switch: /* 0x2c */ +/* File: arm64/op_sparse_switch.S */ +/* File: arm64/op_packed_switch.S */ + /* + * Handle a packed-switch or sparse-switch instruction. In both cases + * we decode it and hand it off to a helper function. + * + * We don't really expect backward branches in a switch statement, but + * they're perfectly legal, so we check for them here. + * + * for: packed-switch, sparse-switch + */ + /* op vAA, +BBBB */ +#if MTERP_SUSPEND + FETCH w0, 1 // w0<- bbbb (lo) + FETCH w1, 2 // w1<- BBBB (hi) + mov w3, wINST, lsr #8 // w3<- AA + orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb + GET_VREG w1, w3 // w1<- vAA + add w0, rPC, w0, lsl #1 // w0<- PC + BBBBbbbb*2 + bl MterpDoSparseSwitch // w0<- code-unit branch offset + adds w1, w0, w0 // w1<- byte offset; clear V + ldrle rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh handler base + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + FETCH w0, 1 // w0<- bbbb (lo) + FETCH w1, 2 // w1<- BBBB (hi) + lsr w3, wINST, #8 // w3<- AA + orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb + GET_VREG w1, w3 // w1<- vAA + add x0, xPC, w0, lsl #1 // w0<- PC + BBBBbbbb*2 + bl MterpDoSparseSwitch // w0<- code-unit branch offset + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + adds w1, w0, w0 // w1<- byte offset; clear V + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + b.le MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_cmpl_float: /* 0x2d */ +/* File: arm64/op_cmpl_float.S */ +/* File: arm64/fcmp.S */ + /* + * Compare two floating-point values. Puts 0, 1, or -1 into the + * destination register based on the results of the comparison. + */ + /* op vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + and w2, w0, #255 // w2<- BB + lsr w3, w0, #8 // w3<- CC + GET_VREG s1, w2 + GET_VREG s2, w3 + mov w0, #-1 + fcmp s1, s2 + csneg w0, w0, w0, le + csel w0, wzr, w0, eq + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w4 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_cmpg_float: /* 0x2e */ +/* File: arm64/op_cmpg_float.S */ +/* File: arm64/fcmp.S */ + /* + * Compare two floating-point values. Puts 0, 1, or -1 into the + * destination register based on the results of the comparison. + */ + /* op vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + and w2, w0, #255 // w2<- BB + lsr w3, w0, #8 // w3<- CC + GET_VREG s1, w2 + GET_VREG s2, w3 + mov w0, #1 + fcmp s1, s2 + csneg w0, w0, w0, pl + csel w0, wzr, w0, eq + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w4 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_cmpl_double: /* 0x2f */ +/* File: arm64/op_cmpl_double.S */ +/* File: arm64/fcmp.S */ + /* + * Compare two floating-point values. Puts 0, 1, or -1 into the + * destination register based on the results of the comparison. + */ + /* op vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + and w2, w0, #255 // w2<- BB + lsr w3, w0, #8 // w3<- CC + GET_VREG_WIDE d1, w2 + GET_VREG_WIDE d2, w3 + mov w0, #-1 + fcmp d1, d2 + csneg w0, w0, w0, le + csel w0, wzr, w0, eq + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w4 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_cmpg_double: /* 0x30 */ +/* File: arm64/op_cmpg_double.S */ +/* File: arm64/fcmp.S */ + /* + * Compare two floating-point values. Puts 0, 1, or -1 into the + * destination register based on the results of the comparison. + */ + /* op vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + and w2, w0, #255 // w2<- BB + lsr w3, w0, #8 // w3<- CC + GET_VREG_WIDE d1, w2 + GET_VREG_WIDE d2, w3 + mov w0, #1 + fcmp d1, d2 + csneg w0, w0, w0, pl + csel w0, wzr, w0, eq + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w4 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_cmp_long: /* 0x31 */ +/* File: arm64/op_cmp_long.S */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + and w2, w0, #255 // w2<- BB + lsr w3, w0, #8 // w3<- CC + GET_VREG_WIDE x1, w2 + GET_VREG_WIDE x2, w3 + cmp x1, x2 + csinc w0, wzr, wzr, eq + csneg w0, w0, w0, ge + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + SET_VREG w0, w4 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_if_eq: /* 0x32 */ +/* File: arm64/op_if_eq.S */ +/* File: arm64/bincmp.S */ + /* + * Generic two-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le + */ + /* if-cmp vA, vB, +CCCC */ +#if MTERP_SUSPEND + mov w1, wINST, lsr #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, w3 // compare (vA, vB) + moveq w1, #2 // w1<- BYTE branch dist for not-taken + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh rIBASE + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w1, wINST, #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Offset if branch not taken + cmp w2, w3 // compare (vA, vB) + csel w1, w1, w0, eq // Branch if true + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_if_ne: /* 0x33 */ +/* File: arm64/op_if_ne.S */ +/* File: arm64/bincmp.S */ + /* + * Generic two-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le + */ + /* if-cmp vA, vB, +CCCC */ +#if MTERP_SUSPEND + mov w1, wINST, lsr #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, w3 // compare (vA, vB) + movne w1, #2 // w1<- BYTE branch dist for not-taken + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh rIBASE + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w1, wINST, #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Offset if branch not taken + cmp w2, w3 // compare (vA, vB) + csel w1, w1, w0, ne // Branch if true + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_if_lt: /* 0x34 */ +/* File: arm64/op_if_lt.S */ +/* File: arm64/bincmp.S */ + /* + * Generic two-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le + */ + /* if-cmp vA, vB, +CCCC */ +#if MTERP_SUSPEND + mov w1, wINST, lsr #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, w3 // compare (vA, vB) + movlt w1, #2 // w1<- BYTE branch dist for not-taken + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh rIBASE + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w1, wINST, #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Offset if branch not taken + cmp w2, w3 // compare (vA, vB) + csel w1, w1, w0, lt // Branch if true + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_if_ge: /* 0x35 */ +/* File: arm64/op_if_ge.S */ +/* File: arm64/bincmp.S */ + /* + * Generic two-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le + */ + /* if-cmp vA, vB, +CCCC */ +#if MTERP_SUSPEND + mov w1, wINST, lsr #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, w3 // compare (vA, vB) + movge w1, #2 // w1<- BYTE branch dist for not-taken + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh rIBASE + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w1, wINST, #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Offset if branch not taken + cmp w2, w3 // compare (vA, vB) + csel w1, w1, w0, ge // Branch if true + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_if_gt: /* 0x36 */ +/* File: arm64/op_if_gt.S */ +/* File: arm64/bincmp.S */ + /* + * Generic two-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le + */ + /* if-cmp vA, vB, +CCCC */ +#if MTERP_SUSPEND + mov w1, wINST, lsr #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, w3 // compare (vA, vB) + movgt w1, #2 // w1<- BYTE branch dist for not-taken + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh rIBASE + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w1, wINST, #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Offset if branch not taken + cmp w2, w3 // compare (vA, vB) + csel w1, w1, w0, gt // Branch if true + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_if_le: /* 0x37 */ +/* File: arm64/op_if_le.S */ +/* File: arm64/bincmp.S */ + /* + * Generic two-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le + */ + /* if-cmp vA, vB, +CCCC */ +#if MTERP_SUSPEND + mov w1, wINST, lsr #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, w3 // compare (vA, vB) + movle w1, #2 // w1<- BYTE branch dist for not-taken + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh rIBASE + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w1, wINST, #12 // w1<- B + ubfx w0, wINST, #8, #4 // w0<- A + GET_VREG w3, w1 // w3<- vB + GET_VREG w2, w0 // w2<- vA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Offset if branch not taken + cmp w2, w3 // compare (vA, vB) + csel w1, w1, w0, le // Branch if true + adds w2, w1, w1 // convert to bytes, check sign + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_if_eqz: /* 0x38 */ +/* File: arm64/op_if_eqz.S */ +/* File: arm64/zcmp.S */ + /* + * Generic one-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez + */ + /* if-cmp vAA, +BBBB */ +#if MTERP_SUSPEND + mov w0, wINST, lsr #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, #0 // compare (vA, 0) + moveq w1, #2 // w1<- inst branch dist for not-taken + adds w1, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh table base + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w0, wINST, #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Branch offset if not taken + cmp w2, #0 // compare (vA, 0) + csel w1, w1, w0, eq // Branch if true + adds w2, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_if_nez: /* 0x39 */ +/* File: arm64/op_if_nez.S */ +/* File: arm64/zcmp.S */ + /* + * Generic one-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez + */ + /* if-cmp vAA, +BBBB */ +#if MTERP_SUSPEND + mov w0, wINST, lsr #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, #0 // compare (vA, 0) + movne w1, #2 // w1<- inst branch dist for not-taken + adds w1, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh table base + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w0, wINST, #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Branch offset if not taken + cmp w2, #0 // compare (vA, 0) + csel w1, w1, w0, ne // Branch if true + adds w2, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_if_ltz: /* 0x3a */ +/* File: arm64/op_if_ltz.S */ +/* File: arm64/zcmp.S */ + /* + * Generic one-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez + */ + /* if-cmp vAA, +BBBB */ +#if MTERP_SUSPEND + mov w0, wINST, lsr #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, #0 // compare (vA, 0) + movlt w1, #2 // w1<- inst branch dist for not-taken + adds w1, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh table base + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w0, wINST, #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Branch offset if not taken + cmp w2, #0 // compare (vA, 0) + csel w1, w1, w0, lt // Branch if true + adds w2, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_if_gez: /* 0x3b */ +/* File: arm64/op_if_gez.S */ +/* File: arm64/zcmp.S */ + /* + * Generic one-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez + */ + /* if-cmp vAA, +BBBB */ +#if MTERP_SUSPEND + mov w0, wINST, lsr #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, #0 // compare (vA, 0) + movge w1, #2 // w1<- inst branch dist for not-taken + adds w1, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh table base + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w0, wINST, #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Branch offset if not taken + cmp w2, #0 // compare (vA, 0) + csel w1, w1, w0, ge // Branch if true + adds w2, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_if_gtz: /* 0x3c */ +/* File: arm64/op_if_gtz.S */ +/* File: arm64/zcmp.S */ + /* + * Generic one-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez + */ + /* if-cmp vAA, +BBBB */ +#if MTERP_SUSPEND + mov w0, wINST, lsr #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, #0 // compare (vA, 0) + movgt w1, #2 // w1<- inst branch dist for not-taken + adds w1, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh table base + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w0, wINST, #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Branch offset if not taken + cmp w2, #0 // compare (vA, 0) + csel w1, w1, w0, gt // Branch if true + adds w2, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_if_lez: /* 0x3d */ +/* File: arm64/op_if_lez.S */ +/* File: arm64/zcmp.S */ + /* + * Generic one-operand compare-and-branch operation. Provide a "revcmp" + * fragment that specifies the *reverse* comparison to perform, e.g. + * for "if-le" you would use "gt". + * + * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez + */ + /* if-cmp vAA, +BBBB */ +#if MTERP_SUSPEND + mov w0, wINST, lsr #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + cmp w2, #0 // compare (vA, 0) + movle w1, #2 // w1<- inst branch dist for not-taken + adds w1, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w1 // update rPC, load wINST + ldrmi rIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh table base + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#else + lsr w0, wINST, #8 // w0<- AA + GET_VREG w2, w0 // w2<- vAA + FETCH_S w1, 1 // w1<- branch offset, in code units + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov w0, #2 // Branch offset if not taken + cmp w2, #0 // compare (vA, 0) + csel w1, w1, w0, le // Branch if true + adds w2, w1, w1 // convert to bytes & set flags + FETCH_ADVANCE_INST_RB w2 // update rPC, load wINST + b.mi MterpCheckSuspendAndContinue + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +#endif + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_3e: /* 0x3e */ +/* File: arm64/op_unused_3e.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_3f: /* 0x3f */ +/* File: arm64/op_unused_3f.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_40: /* 0x40 */ +/* File: arm64/op_unused_40.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_41: /* 0x41 */ +/* File: arm64/op_unused_41.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_42: /* 0x42 */ +/* File: arm64/op_unused_42.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_43: /* 0x43 */ +/* File: arm64/op_unused_43.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_aget: /* 0x44 */ +/* File: arm64/op_aget.S */ + /* + * Array get, 32 bits or less. vAA <- vBB[vCC]. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aget, aget-boolean, aget-byte, aget-char, aget-short + * + * NOTE: assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz x0, common_errNullObject // bail if null array object. + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, uxtw #2 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + ldr w2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w2, w9 // vAA<- w2 + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_aget_wide: /* 0x45 */ +/* File: arm64/op_aget_wide.S */ + /* + * Array get, 64 bits. vAA <- vBB[vCC]. + * + */ + /* aget-wide vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + and w2, w0, #255 // w2<- BB + lsr w3, w0, #8 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz w0, common_errNullObject // yes, bail + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, lsl #3 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + ldr x2, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET] // x2<- vBB[vCC] + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x2, w4 + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_aget_object: /* 0x46 */ +/* File: arm64/op_aget_object.S */ + /* + * Array object get. vAA <- vBB[vCC]. + * + * for: aget-object + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + FETCH_B w3, 1, 1 // w3<- CC + EXPORT_PC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + bl artAGetObjectFromMterp // (array, index) + ldr x1, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w2, wINST, #8 // w9<- AA + PREFETCH_INST 2 + cbnz w1, MterpException + SET_VREG_OBJECT w0, w2 + ADVANCE 2 + GET_INST_OPCODE ip + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_aget_boolean: /* 0x47 */ +/* File: arm64/op_aget_boolean.S */ +/* File: arm64/op_aget.S */ + /* + * Array get, 32 bits or less. vAA <- vBB[vCC]. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aget, aget-boolean, aget-byte, aget-char, aget-short + * + * NOTE: assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz x0, common_errNullObject // bail if null array object. + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, uxtw #0 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + ldrb w2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w2, w9 // vAA<- w2 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_aget_byte: /* 0x48 */ +/* File: arm64/op_aget_byte.S */ +/* File: arm64/op_aget.S */ + /* + * Array get, 32 bits or less. vAA <- vBB[vCC]. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aget, aget-boolean, aget-byte, aget-char, aget-short + * + * NOTE: assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz x0, common_errNullObject // bail if null array object. + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, uxtw #0 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + ldrsb w2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w2, w9 // vAA<- w2 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_aget_char: /* 0x49 */ +/* File: arm64/op_aget_char.S */ +/* File: arm64/op_aget.S */ + /* + * Array get, 32 bits or less. vAA <- vBB[vCC]. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aget, aget-boolean, aget-byte, aget-char, aget-short + * + * NOTE: assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz x0, common_errNullObject // bail if null array object. + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, uxtw #1 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + ldrh w2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w2, w9 // vAA<- w2 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_aget_short: /* 0x4a */ +/* File: arm64/op_aget_short.S */ +/* File: arm64/op_aget.S */ + /* + * Array get, 32 bits or less. vAA <- vBB[vCC]. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aget, aget-boolean, aget-byte, aget-char, aget-short + * + * NOTE: assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz x0, common_errNullObject // bail if null array object. + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, uxtw #1 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + ldrsh w2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET] // w2<- vBB[vCC] + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w2, w9 // vAA<- w2 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_aput: /* 0x4b */ +/* File: arm64/op_aput.S */ + /* + * Array put, 32 bits or less. vBB[vCC] <- vAA. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aput, aput-boolean, aput-byte, aput-char, aput-short + * + * NOTE: this assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz w0, common_errNullObject // bail if null + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, lsl #2 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_VREG w2, w9 // w2<- vAA + GET_INST_OPCODE ip // extract opcode from rINST + str w2, [x0, #MIRROR_INT_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_aput_wide: /* 0x4c */ +/* File: arm64/op_aput_wide.S */ + /* + * Array put, 64 bits. vBB[vCC] <- vAA. + * + */ + /* aput-wide vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + and w2, w0, #255 // w2<- BB + lsr w3, w0, #8 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz w0, common_errNullObject // bail if null + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, lsl #3 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + GET_VREG_WIDE x1, w4 + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + GET_INST_OPCODE ip // extract opcode from wINST + str x1, [x0, #MIRROR_WIDE_ARRAY_DATA_OFFSET] + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_aput_object: /* 0x4d */ +/* File: arm64/op_aput_object.S */ + /* + * Store an object into an array. vBB[vCC] <- vAA. + */ + /* op vAA, vBB, vCC */ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov w2, wINST + bl MterpAputObject + cbz w0, MterpPossibleException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_aput_boolean: /* 0x4e */ +/* File: arm64/op_aput_boolean.S */ +/* File: arm64/op_aput.S */ + /* + * Array put, 32 bits or less. vBB[vCC] <- vAA. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aput, aput-boolean, aput-byte, aput-char, aput-short + * + * NOTE: this assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz w0, common_errNullObject // bail if null + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, lsl #0 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_VREG w2, w9 // w2<- vAA + GET_INST_OPCODE ip // extract opcode from rINST + strb w2, [x0, #MIRROR_BOOLEAN_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_aput_byte: /* 0x4f */ +/* File: arm64/op_aput_byte.S */ +/* File: arm64/op_aput.S */ + /* + * Array put, 32 bits or less. vBB[vCC] <- vAA. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aput, aput-boolean, aput-byte, aput-char, aput-short + * + * NOTE: this assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz w0, common_errNullObject // bail if null + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, lsl #0 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_VREG w2, w9 // w2<- vAA + GET_INST_OPCODE ip // extract opcode from rINST + strb w2, [x0, #MIRROR_BYTE_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_aput_char: /* 0x50 */ +/* File: arm64/op_aput_char.S */ +/* File: arm64/op_aput.S */ + /* + * Array put, 32 bits or less. vBB[vCC] <- vAA. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aput, aput-boolean, aput-byte, aput-char, aput-short + * + * NOTE: this assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz w0, common_errNullObject // bail if null + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, lsl #1 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_VREG w2, w9 // w2<- vAA + GET_INST_OPCODE ip // extract opcode from rINST + strh w2, [x0, #MIRROR_CHAR_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_aput_short: /* 0x51 */ +/* File: arm64/op_aput_short.S */ +/* File: arm64/op_aput.S */ + /* + * Array put, 32 bits or less. vBB[vCC] <- vAA. + * + * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 + * instructions. We use a pair of FETCH_Bs instead. + * + * for: aput, aput-boolean, aput-byte, aput-char, aput-short + * + * NOTE: this assumes data offset for arrays is the same for all non-wide types. + * If this changes, specialize. + */ + /* op vAA, vBB, vCC */ + FETCH_B w2, 1, 0 // w2<- BB + lsr w9, wINST, #8 // w9<- AA + FETCH_B w3, 1, 1 // w3<- CC + GET_VREG w0, w2 // w0<- vBB (array object) + GET_VREG w1, w3 // w1<- vCC (requested index) + cbz w0, common_errNullObject // bail if null + ldr w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET] // w3<- arrayObj->length + add x0, x0, w1, lsl #1 // w0<- arrayObj + index*width + cmp w1, w3 // compare unsigned index, length + bcs common_errArrayIndex // index >= length, bail + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_VREG w2, w9 // w2<- vAA + GET_INST_OPCODE ip // extract opcode from rINST + strh w2, [x0, #MIRROR_SHORT_ARRAY_DATA_OFFSET] // vBB[vCC]<- w2 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iget: /* 0x52 */ +/* File: arm64/op_iget.S */ + /* + * General instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer + mov x3, xSELF // w3<- self + bl artGet32InstanceFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + ubfx w2, wINST, #8, #4 // w2<- A + PREFETCH_INST 2 + cbnz x3, MterpPossibleException // bail out + .if 0 + SET_VREG_OBJECT w0, w2 // fp[A]<- w0 + .else + SET_VREG w0, w2 // fp[A]<- w0 + .endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_iget_wide: /* 0x53 */ +/* File: arm64/op_iget_wide.S */ + /* + * 64-bit instance field get. + * + * for: iget-wide + */ + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer + mov x3, xSELF // w3<- self + bl artGet64InstanceFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + ubfx w2, wINST, #8, #4 // w2<- A + PREFETCH_INST 2 + cmp w3, #0 + cbnz w3, MterpException // bail out + SET_VREG_WIDE x0, w2 + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_iget_object: /* 0x54 */ +/* File: arm64/op_iget_object.S */ +/* File: arm64/op_iget.S */ + /* + * General instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer + mov x3, xSELF // w3<- self + bl artGetObjInstanceFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + ubfx w2, wINST, #8, #4 // w2<- A + PREFETCH_INST 2 + cbnz x3, MterpPossibleException // bail out + .if 1 + SET_VREG_OBJECT w0, w2 // fp[A]<- w0 + .else + SET_VREG w0, w2 // fp[A]<- w0 + .endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iget_boolean: /* 0x55 */ +/* File: arm64/op_iget_boolean.S */ +/* File: arm64/op_iget.S */ + /* + * General instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer + mov x3, xSELF // w3<- self + bl artGetBooleanInstanceFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + ubfx w2, wINST, #8, #4 // w2<- A + PREFETCH_INST 2 + cbnz x3, MterpPossibleException // bail out + .if 0 + SET_VREG_OBJECT w0, w2 // fp[A]<- w0 + .else + SET_VREG w0, w2 // fp[A]<- w0 + .endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iget_byte: /* 0x56 */ +/* File: arm64/op_iget_byte.S */ +/* File: arm64/op_iget.S */ + /* + * General instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer + mov x3, xSELF // w3<- self + bl artGetByteInstanceFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + ubfx w2, wINST, #8, #4 // w2<- A + PREFETCH_INST 2 + cbnz x3, MterpPossibleException // bail out + .if 0 + SET_VREG_OBJECT w0, w2 // fp[A]<- w0 + .else + SET_VREG w0, w2 // fp[A]<- w0 + .endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iget_char: /* 0x57 */ +/* File: arm64/op_iget_char.S */ +/* File: arm64/op_iget.S */ + /* + * General instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer + mov x3, xSELF // w3<- self + bl artGetCharInstanceFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + ubfx w2, wINST, #8, #4 // w2<- A + PREFETCH_INST 2 + cbnz x3, MterpPossibleException // bail out + .if 0 + SET_VREG_OBJECT w0, w2 // fp[A]<- w0 + .else + SET_VREG w0, w2 // fp[A]<- w0 + .endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iget_short: /* 0x58 */ +/* File: arm64/op_iget_short.S */ +/* File: arm64/op_iget.S */ + /* + * General instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ldr x2, [xFP, #OFF_FP_METHOD] // w2<- referrer + mov x3, xSELF // w3<- self + bl artGetShortInstanceFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + ubfx w2, wINST, #8, #4 // w2<- A + PREFETCH_INST 2 + cbnz x3, MterpPossibleException // bail out + .if 0 + SET_VREG_OBJECT w0, w2 // fp[A]<- w0 + .else + SET_VREG w0, w2 // fp[A]<- w0 + .endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iput: /* 0x59 */ +/* File: arm64/op_iput.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op vA, vB, field//CCCC */ + .extern artSet32InstanceFromMterp + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w2, w2 // w2<- fp[A] + ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer + PREFETCH_INST 2 + bl artSet32InstanceFromMterp + cbnz w0, MterpPossibleException + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_iput_wide: /* 0x5a */ +/* File: arm64/op_iput_wide.S */ + /* iput-wide vA, vB, field//CCCC */ + .extern artSet64InstanceFromMterp + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + add x2, xFP, x2, lsl #2 // w2<- &fp[A] + ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer + PREFETCH_INST 2 + bl artSet64InstanceFromMterp + cbnz w0, MterpPossibleException + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_iput_object: /* 0x5b */ +/* File: arm64/op_iput_object.S */ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov w2, wINST + mov x3, xSELF + bl MterpIputObject + cbz w0, MterpException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_iput_boolean: /* 0x5c */ +/* File: arm64/op_iput_boolean.S */ +/* File: arm64/op_iput.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op vA, vB, field//CCCC */ + .extern artSet8InstanceFromMterp + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w2, w2 // w2<- fp[A] + ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer + PREFETCH_INST 2 + bl artSet8InstanceFromMterp + cbnz w0, MterpPossibleException + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iput_byte: /* 0x5d */ +/* File: arm64/op_iput_byte.S */ +/* File: arm64/op_iput.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op vA, vB, field//CCCC */ + .extern artSet8InstanceFromMterp + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w2, w2 // w2<- fp[A] + ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer + PREFETCH_INST 2 + bl artSet8InstanceFromMterp + cbnz w0, MterpPossibleException + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iput_char: /* 0x5e */ +/* File: arm64/op_iput_char.S */ +/* File: arm64/op_iput.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op vA, vB, field//CCCC */ + .extern artSet16InstanceFromMterp + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w2, w2 // w2<- fp[A] + ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer + PREFETCH_INST 2 + bl artSet16InstanceFromMterp + cbnz w0, MterpPossibleException + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iput_short: /* 0x5f */ +/* File: arm64/op_iput_short.S */ +/* File: arm64/op_iput.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op vA, vB, field//CCCC */ + .extern artSet16InstanceFromMterp + EXPORT_PC + FETCH w0, 1 // w0<- field ref CCCC + lsr w1, wINST, #12 // w1<- B + GET_VREG w1, w1 // w1<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w2, w2 // w2<- fp[A] + ldr x3, [xFP, #OFF_FP_METHOD] // w3<- referrer + PREFETCH_INST 2 + bl artSet16InstanceFromMterp + cbnz w0, MterpPossibleException + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_sget: /* 0x60 */ +/* File: arm64/op_sget.S */ + /* + * General SGET handler wrapper. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op vAA, field//BBBB */ + + .extern artGet32StaticFromCode + EXPORT_PC + FETCH w0, 1 // w0<- field ref BBBB + ldr x1, [xFP, #OFF_FP_METHOD] + mov x2, xSELF + bl artGet32StaticFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w2, wINST, #8 // w2<- AA + + PREFETCH_INST 2 + cbnz x3, MterpException // bail out +.if 0 + SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 +.else + SET_VREG w0, w2 // fp[AA]<- w0 +.endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip + +/* ------------------------------ */ + .balign 128 +.L_op_sget_wide: /* 0x61 */ +/* File: arm64/op_sget_wide.S */ + /* + * SGET_WIDE handler wrapper. + * + */ + /* sget-wide vAA, field//BBBB */ + + .extern artGet64StaticFromCode + EXPORT_PC + FETCH w0, 1 // w0<- field ref BBBB + ldr x1, [xFP, #OFF_FP_METHOD] + mov x2, xSELF + bl artGet64StaticFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w4, wINST, #8 // w4<- AA + cbnz x3, MterpException // bail out + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + SET_VREG_WIDE x0, w4 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_sget_object: /* 0x62 */ +/* File: arm64/op_sget_object.S */ +/* File: arm64/op_sget.S */ + /* + * General SGET handler wrapper. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op vAA, field//BBBB */ + + .extern artGetObjStaticFromCode + EXPORT_PC + FETCH w0, 1 // w0<- field ref BBBB + ldr x1, [xFP, #OFF_FP_METHOD] + mov x2, xSELF + bl artGetObjStaticFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w2, wINST, #8 // w2<- AA + + PREFETCH_INST 2 + cbnz x3, MterpException // bail out +.if 1 + SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 +.else + SET_VREG w0, w2 // fp[AA]<- w0 +.endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip + + +/* ------------------------------ */ + .balign 128 +.L_op_sget_boolean: /* 0x63 */ +/* File: arm64/op_sget_boolean.S */ +/* File: arm64/op_sget.S */ + /* + * General SGET handler wrapper. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op vAA, field//BBBB */ + + .extern artGetBooleanStaticFromCode + EXPORT_PC + FETCH w0, 1 // w0<- field ref BBBB + ldr x1, [xFP, #OFF_FP_METHOD] + mov x2, xSELF + bl artGetBooleanStaticFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w2, wINST, #8 // w2<- AA + uxtb w0, w0 + PREFETCH_INST 2 + cbnz x3, MterpException // bail out +.if 0 + SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 +.else + SET_VREG w0, w2 // fp[AA]<- w0 +.endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip + + +/* ------------------------------ */ + .balign 128 +.L_op_sget_byte: /* 0x64 */ +/* File: arm64/op_sget_byte.S */ +/* File: arm64/op_sget.S */ + /* + * General SGET handler wrapper. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op vAA, field//BBBB */ + + .extern artGetByteStaticFromCode + EXPORT_PC + FETCH w0, 1 // w0<- field ref BBBB + ldr x1, [xFP, #OFF_FP_METHOD] + mov x2, xSELF + bl artGetByteStaticFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w2, wINST, #8 // w2<- AA + sxtb w0, w0 + PREFETCH_INST 2 + cbnz x3, MterpException // bail out +.if 0 + SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 +.else + SET_VREG w0, w2 // fp[AA]<- w0 +.endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip + + +/* ------------------------------ */ + .balign 128 +.L_op_sget_char: /* 0x65 */ +/* File: arm64/op_sget_char.S */ +/* File: arm64/op_sget.S */ + /* + * General SGET handler wrapper. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op vAA, field//BBBB */ + + .extern artGetCharStaticFromCode + EXPORT_PC + FETCH w0, 1 // w0<- field ref BBBB + ldr x1, [xFP, #OFF_FP_METHOD] + mov x2, xSELF + bl artGetCharStaticFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w2, wINST, #8 // w2<- AA + uxth w0, w0 + PREFETCH_INST 2 + cbnz x3, MterpException // bail out +.if 0 + SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 +.else + SET_VREG w0, w2 // fp[AA]<- w0 +.endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip + + +/* ------------------------------ */ + .balign 128 +.L_op_sget_short: /* 0x66 */ +/* File: arm64/op_sget_short.S */ +/* File: arm64/op_sget.S */ + /* + * General SGET handler wrapper. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op vAA, field//BBBB */ + + .extern artGetShortStaticFromCode + EXPORT_PC + FETCH w0, 1 // w0<- field ref BBBB + ldr x1, [xFP, #OFF_FP_METHOD] + mov x2, xSELF + bl artGetShortStaticFromCode + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + lsr w2, wINST, #8 // w2<- AA + sxth w0, w0 + PREFETCH_INST 2 + cbnz x3, MterpException // bail out +.if 0 + SET_VREG_OBJECT w0, w2 // fp[AA]<- w0 +.else + SET_VREG w0, w2 // fp[AA]<- w0 +.endif + ADVANCE 2 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip + + +/* ------------------------------ */ + .balign 128 +.L_op_sput: /* 0x67 */ +/* File: arm64/op_sput.S */ + /* + * General SPUT handler wrapper. + * + * for: sput, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op vAA, field//BBBB */ + EXPORT_PC + FETCH w0, 1 // r0<- field ref BBBB + lsr w3, wINST, #8 // r3<- AA + GET_VREG w1, w3 // r1<= fp[AA] + ldr x2, [xFP, #OFF_FP_METHOD] + mov x3, xSELF + PREFETCH_INST 2 // Get next inst, but don't advance rPC + bl artSet32StaticFromCode + cbnz w0, MterpException // 0 on success + ADVANCE 2 // Past exception point - now advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_sput_wide: /* 0x68 */ +/* File: arm64/op_sput_wide.S */ + /* + * SPUT_WIDE handler wrapper. + * + */ + /* sput-wide vAA, field//BBBB */ + .extern artSet64IndirectStaticFromMterp + EXPORT_PC + FETCH w0, 1 // w0<- field ref BBBB + ldr x1, [xFP, #OFF_FP_METHOD] + lsr w2, wINST, #8 // w3<- AA + add x2, xFP, w2, lsl #2 + mov x3, xSELF + PREFETCH_INST 2 // Get next inst, but don't advance rPC + bl artSet64IndirectStaticFromMterp + cbnz w0, MterpException // 0 on success, -1 on failure + ADVANCE 2 // Past exception point - now advance rPC + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_sput_object: /* 0x69 */ +/* File: arm64/op_sput_object.S */ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov x2, xINST + mov x3, xSELF + bl MterpSputObject + cbz w0, MterpException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_sput_boolean: /* 0x6a */ +/* File: arm64/op_sput_boolean.S */ +/* File: arm64/op_sput.S */ + /* + * General SPUT handler wrapper. + * + * for: sput, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op vAA, field//BBBB */ + EXPORT_PC + FETCH w0, 1 // r0<- field ref BBBB + lsr w3, wINST, #8 // r3<- AA + GET_VREG w1, w3 // r1<= fp[AA] + ldr x2, [xFP, #OFF_FP_METHOD] + mov x3, xSELF + PREFETCH_INST 2 // Get next inst, but don't advance rPC + bl artSet8StaticFromCode + cbnz w0, MterpException // 0 on success + ADVANCE 2 // Past exception point - now advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_sput_byte: /* 0x6b */ +/* File: arm64/op_sput_byte.S */ +/* File: arm64/op_sput.S */ + /* + * General SPUT handler wrapper. + * + * for: sput, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op vAA, field//BBBB */ + EXPORT_PC + FETCH w0, 1 // r0<- field ref BBBB + lsr w3, wINST, #8 // r3<- AA + GET_VREG w1, w3 // r1<= fp[AA] + ldr x2, [xFP, #OFF_FP_METHOD] + mov x3, xSELF + PREFETCH_INST 2 // Get next inst, but don't advance rPC + bl artSet8StaticFromCode + cbnz w0, MterpException // 0 on success + ADVANCE 2 // Past exception point - now advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_sput_char: /* 0x6c */ +/* File: arm64/op_sput_char.S */ +/* File: arm64/op_sput.S */ + /* + * General SPUT handler wrapper. + * + * for: sput, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op vAA, field//BBBB */ + EXPORT_PC + FETCH w0, 1 // r0<- field ref BBBB + lsr w3, wINST, #8 // r3<- AA + GET_VREG w1, w3 // r1<= fp[AA] + ldr x2, [xFP, #OFF_FP_METHOD] + mov x3, xSELF + PREFETCH_INST 2 // Get next inst, but don't advance rPC + bl artSet16StaticFromCode + cbnz w0, MterpException // 0 on success + ADVANCE 2 // Past exception point - now advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_sput_short: /* 0x6d */ +/* File: arm64/op_sput_short.S */ +/* File: arm64/op_sput.S */ + /* + * General SPUT handler wrapper. + * + * for: sput, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op vAA, field//BBBB */ + EXPORT_PC + FETCH w0, 1 // r0<- field ref BBBB + lsr w3, wINST, #8 // r3<- AA + GET_VREG w1, w3 // r1<= fp[AA] + ldr x2, [xFP, #OFF_FP_METHOD] + mov x3, xSELF + PREFETCH_INST 2 // Get next inst, but don't advance rPC + bl artSet16StaticFromCode + cbnz w0, MterpException // 0 on success + ADVANCE 2 // Past exception point - now advance rPC + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_virtual: /* 0x6e */ +/* File: arm64/op_invoke_virtual.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeVirtual + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeVirtual + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + /* + * Handle a virtual method call. + * + * for: invoke-virtual, invoke-virtual/range + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_super: /* 0x6f */ +/* File: arm64/op_invoke_super.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeSuper + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeSuper + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + /* + * Handle a "super" method call. + * + * for: invoke-super, invoke-super/range + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_direct: /* 0x70 */ +/* File: arm64/op_invoke_direct.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeDirect + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeDirect + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_static: /* 0x71 */ +/* File: arm64/op_invoke_static.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeStatic + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeStatic + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_interface: /* 0x72 */ +/* File: arm64/op_invoke_interface.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeInterface + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeInterface + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + /* + * Handle an interface method call. + * + * for: invoke-interface, invoke-interface/range + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + +/* ------------------------------ */ + .balign 128 +.L_op_return_void_no_barrier: /* 0x73 */ +/* File: arm64/op_return_void_no_barrier.S */ + ldr w7, [xSELF, #THREAD_FLAGS_OFFSET] + mov x0, xSELF + ands w7, w7, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.ne .Lop_return_void_no_barrier_check +.Lop_return_void_no_barrier_return: + mov x0, #0 + b MterpReturn +.Lop_return_void_no_barrier_check: + bl MterpSuspendCheck // (self) + b .Lop_return_void_no_barrier_return + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_virtual_range: /* 0x74 */ +/* File: arm64/op_invoke_virtual_range.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeVirtualRange + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeVirtualRange + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_super_range: /* 0x75 */ +/* File: arm64/op_invoke_super_range.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeSuperRange + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeSuperRange + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_direct_range: /* 0x76 */ +/* File: arm64/op_invoke_direct_range.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeDirectRange + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeDirectRange + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_static_range: /* 0x77 */ +/* File: arm64/op_invoke_static_range.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeStaticRange + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeStaticRange + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_interface_range: /* 0x78 */ +/* File: arm64/op_invoke_interface_range.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeInterfaceRange + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeInterfaceRange + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_79: /* 0x79 */ +/* File: arm64/op_unused_79.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_7a: /* 0x7a */ +/* File: arm64/op_unused_7a.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_neg_int: /* 0x7b */ +/* File: arm64/op_neg_int.S */ +/* File: arm64/unop.S */ + /* + * Generic 32-bit unary operation. Provide an "instr" line that + * specifies an instruction that performs "result = op w0". + * This could be an ARM instruction or a function call. + * + * for: neg-int, not-int, neg-float, int-to-float, float-to-int, + * int-to-byte, int-to-char, int-to-short + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + GET_VREG w0, w3 // w0<- vB + ubfx w9, wINST, #8, #4 // w9<- A + // optional op; may set condition codes + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + sub w0, wzr, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 8-9 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_not_int: /* 0x7c */ +/* File: arm64/op_not_int.S */ +/* File: arm64/unop.S */ + /* + * Generic 32-bit unary operation. Provide an "instr" line that + * specifies an instruction that performs "result = op w0". + * This could be an ARM instruction or a function call. + * + * for: neg-int, not-int, neg-float, int-to-float, float-to-int, + * int-to-byte, int-to-char, int-to-short + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + GET_VREG w0, w3 // w0<- vB + ubfx w9, wINST, #8, #4 // w9<- A + // optional op; may set condition codes + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + mvn w0, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 8-9 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_neg_long: /* 0x7d */ +/* File: arm64/op_neg_long.S */ +/* File: arm64/unopWide.S */ + /* + * Generic 64-bit unary operation. Provide an "instr" line that + * specifies an instruction that performs "result = op x0". + * + * For: neg-long, not-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w4, wINST, #8, #4 // w4<- A + GET_VREG_WIDE x0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + + sub x0, xzr, x0 + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x0, w4 + GOTO_OPCODE ip // jump to next instruction + /* 10-11 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_not_long: /* 0x7e */ +/* File: arm64/op_not_long.S */ +/* File: arm64/unopWide.S */ + /* + * Generic 64-bit unary operation. Provide an "instr" line that + * specifies an instruction that performs "result = op x0". + * + * For: neg-long, not-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w4, wINST, #8, #4 // w4<- A + GET_VREG_WIDE x0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + + mvn x0, x0 + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x0, w4 + GOTO_OPCODE ip // jump to next instruction + /* 10-11 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_neg_float: /* 0x7f */ +/* File: arm64/op_neg_float.S */ +/* File: arm64/unop.S */ + /* + * Generic 32-bit unary operation. Provide an "instr" line that + * specifies an instruction that performs "result = op w0". + * This could be an ARM instruction or a function call. + * + * for: neg-int, not-int, neg-float, int-to-float, float-to-int, + * int-to-byte, int-to-char, int-to-short + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + GET_VREG w0, w3 // w0<- vB + ubfx w9, wINST, #8, #4 // w9<- A + mov w4, #0x80000000 // optional op; may set condition codes + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + add w0, w0, w4 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 8-9 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_neg_double: /* 0x80 */ +/* File: arm64/op_neg_double.S */ +/* File: arm64/unopWide.S */ + /* + * Generic 64-bit unary operation. Provide an "instr" line that + * specifies an instruction that performs "result = op x0". + * + * For: neg-long, not-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w4, wINST, #8, #4 // w4<- A + GET_VREG_WIDE x0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + mov x1, #0x8000000000000000 + add x0, x0, x1 + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x0, w4 + GOTO_OPCODE ip // jump to next instruction + /* 10-11 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_int_to_long: /* 0x81 */ +/* File: arm64/op_int_to_long.S */ +/* File: arm64/funopWider.S */ + /* + * Generic 32bit-to-64bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "x0 = op w0". + * + * For: int-to-double, float-to-double, float-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG w0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + sbfm x0, x0, 0, 31 // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_int_to_float: /* 0x82 */ +/* File: arm64/op_int_to_float.S */ +/* File: arm64/funopNarrow.S */ + /* + * Generic 32bit-to-32bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "s0 = op w0". + * + * For: int-to-float, float-to-int + * TODO: refactor all of the conversions - parameterize width and use same template. + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG w0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + scvtf s0, w0 // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG s0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_int_to_double: /* 0x83 */ +/* File: arm64/op_int_to_double.S */ +/* File: arm64/funopWider.S */ + /* + * Generic 32bit-to-64bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "d0 = op w0". + * + * For: int-to-double, float-to-double, float-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG w0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + scvtf d0, w0 // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE d0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_long_to_int: /* 0x84 */ +/* File: arm64/op_long_to_int.S */ +/* File: arm64/funopNarrower.S */ + /* + * Generic 64bit-to-32bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "w0 = op x0". + * + * For: int-to-double, float-to-double, float-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG_WIDE x0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG w0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_long_to_float: /* 0x85 */ +/* File: arm64/op_long_to_float.S */ +/* File: arm64/funopNarrower.S */ + /* + * Generic 64bit-to-32bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "s0 = op x0". + * + * For: int-to-double, float-to-double, float-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG_WIDE x0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + scvtf s0, x0 // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG s0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_long_to_double: /* 0x86 */ +/* File: arm64/op_long_to_double.S */ +/* File: arm64/funopWide.S */ + /* + * Generic 64bit-to-64bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "d0 = op x0". + * + * For: long-to-double, double-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG_WIDE x0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + scvtf d0, x0 // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE d0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_float_to_int: /* 0x87 */ +/* File: arm64/op_float_to_int.S */ +/* File: arm64/funopNarrow.S */ + /* + * Generic 32bit-to-32bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "w0 = op s0". + * + * For: int-to-float, float-to-int + * TODO: refactor all of the conversions - parameterize width and use same template. + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG s0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + fcvtzs w0, s0 // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG w0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_float_to_long: /* 0x88 */ +/* File: arm64/op_float_to_long.S */ +/* File: arm64/funopWider.S */ + /* + * Generic 32bit-to-64bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "x0 = op s0". + * + * For: int-to-double, float-to-double, float-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG s0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + fcvtzs x0, s0 // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_float_to_double: /* 0x89 */ +/* File: arm64/op_float_to_double.S */ +/* File: arm64/funopWider.S */ + /* + * Generic 32bit-to-64bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "d0 = op s0". + * + * For: int-to-double, float-to-double, float-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG s0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + fcvt d0, s0 // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE d0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_double_to_int: /* 0x8a */ +/* File: arm64/op_double_to_int.S */ +/* File: arm64/funopNarrower.S */ + /* + * Generic 64bit-to-32bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "w0 = op d0". + * + * For: int-to-double, float-to-double, float-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG_WIDE d0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + fcvtzs w0, d0 // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG w0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_double_to_long: /* 0x8b */ +/* File: arm64/op_double_to_long.S */ +/* File: arm64/funopWide.S */ + /* + * Generic 64bit-to-64bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "x0 = op d0". + * + * For: long-to-double, double-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG_WIDE d0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + fcvtzs x0, d0 // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG_WIDE x0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_double_to_float: /* 0x8c */ +/* File: arm64/op_double_to_float.S */ +/* File: arm64/funopNarrower.S */ + /* + * Generic 64bit-to-32bit floating point unary operation. Provide an + * "instr" line that specifies an instruction that performs "s0 = op d0". + * + * For: int-to-double, float-to-double, float-to-long + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w4, wINST, #8 // w4<- A+ + GET_VREG_WIDE d0, w3 + FETCH_ADVANCE_INST 1 // advance rPC, load wINST + and w4, w4, #15 // w4<- A + fcvt s0, d0 // d0<- op + GET_INST_OPCODE ip // extract opcode from wINST + SET_VREG s0, w4 // vA<- d0 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_int_to_byte: /* 0x8d */ +/* File: arm64/op_int_to_byte.S */ +/* File: arm64/unop.S */ + /* + * Generic 32-bit unary operation. Provide an "instr" line that + * specifies an instruction that performs "result = op w0". + * This could be an ARM instruction or a function call. + * + * for: neg-int, not-int, neg-float, int-to-float, float-to-int, + * int-to-byte, int-to-char, int-to-short + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + GET_VREG w0, w3 // w0<- vB + ubfx w9, wINST, #8, #4 // w9<- A + // optional op; may set condition codes + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + sxtb w0, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 8-9 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_int_to_char: /* 0x8e */ +/* File: arm64/op_int_to_char.S */ +/* File: arm64/unop.S */ + /* + * Generic 32-bit unary operation. Provide an "instr" line that + * specifies an instruction that performs "result = op w0". + * This could be an ARM instruction or a function call. + * + * for: neg-int, not-int, neg-float, int-to-float, float-to-int, + * int-to-byte, int-to-char, int-to-short + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + GET_VREG w0, w3 // w0<- vB + ubfx w9, wINST, #8, #4 // w9<- A + // optional op; may set condition codes + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + uxth w0, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 8-9 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_int_to_short: /* 0x8f */ +/* File: arm64/op_int_to_short.S */ +/* File: arm64/unop.S */ + /* + * Generic 32-bit unary operation. Provide an "instr" line that + * specifies an instruction that performs "result = op w0". + * This could be an ARM instruction or a function call. + * + * for: neg-int, not-int, neg-float, int-to-float, float-to-int, + * int-to-byte, int-to-char, int-to-short + */ + /* unop vA, vB */ + lsr w3, wINST, #12 // w3<- B + GET_VREG w0, w3 // w0<- vB + ubfx w9, wINST, #8, #4 // w9<- A + // optional op; may set condition codes + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + sxth w0, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 8-9 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_add_int: /* 0x90 */ +/* File: arm64/op_add_int.S */ +/* File: arm64/binop.S */ + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if 0 + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + add w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_sub_int: /* 0x91 */ +/* File: arm64/op_sub_int.S */ +/* File: arm64/binop.S */ + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if 0 + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + sub w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_mul_int: /* 0x92 */ +/* File: arm64/op_mul_int.S */ +/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ +/* File: arm64/binop.S */ + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if 0 + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + mul w0, w1, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_div_int: /* 0x93 */ +/* File: arm64/op_div_int.S */ +/* File: arm64/binop.S */ + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if 1 + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + sdiv w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_rem_int: /* 0x94 */ +/* File: arm64/op_rem_int.S */ +/* File: arm64/binop.S */ + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if 1 + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + sdiv w2, w0, w1 // optional op; may set condition codes + msub w0, w2, w1, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_and_int: /* 0x95 */ +/* File: arm64/op_and_int.S */ +/* File: arm64/binop.S */ + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if 0 + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + and w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_or_int: /* 0x96 */ +/* File: arm64/op_or_int.S */ +/* File: arm64/binop.S */ + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if 0 + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + orr w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_xor_int: /* 0x97 */ +/* File: arm64/op_xor_int.S */ +/* File: arm64/binop.S */ + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if 0 + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + eor w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_shl_int: /* 0x98 */ +/* File: arm64/op_shl_int.S */ +/* File: arm64/binop.S */ + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if 0 + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + and w1, w1, #31 // optional op; may set condition codes + lsl w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_shr_int: /* 0x99 */ +/* File: arm64/op_shr_int.S */ +/* File: arm64/binop.S */ + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if 0 + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + and w1, w1, #31 // optional op; may set condition codes + asr w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_ushr_int: /* 0x9a */ +/* File: arm64/op_ushr_int.S */ +/* File: arm64/binop.S */ + /* + * Generic 32-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. Note that we + * *don't* check for (INT_MIN / -1) here, because the ARM math lib + * handles it correctly. + * + * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, + * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, + * mul-float, div-float, rem-float + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w9, wINST, #8 // w9<- AA + lsr w3, w0, #8 // w3<- CC + and w2, w0, #255 // w2<- BB + GET_VREG w1, w3 // w1<- vCC + GET_VREG w0, w2 // w0<- vBB + .if 0 + cbz w1, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + and w1, w1, #31 // optional op; may set condition codes + lsr w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_add_long: /* 0x9b */ +/* File: arm64/op_add_long.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x2, w2 // w2<- vCC + GET_VREG_WIDE x1, w1 // w1<- vBB + .if 0 + cbz x2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + add x0, x1, x2 // x0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w4 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_sub_long: /* 0x9c */ +/* File: arm64/op_sub_long.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x2, w2 // w2<- vCC + GET_VREG_WIDE x1, w1 // w1<- vBB + .if 0 + cbz x2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + sub x0, x1, x2 // x0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w4 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_mul_long: /* 0x9d */ +/* File: arm64/op_mul_long.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x2, w2 // w2<- vCC + GET_VREG_WIDE x1, w1 // w1<- vBB + .if 0 + cbz x2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + mul x0, x1, x2 // x0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w4 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_div_long: /* 0x9e */ +/* File: arm64/op_div_long.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x2, w2 // w2<- vCC + GET_VREG_WIDE x1, w1 // w1<- vBB + .if 1 + cbz x2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + sdiv x0, x1, x2 // x0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w4 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_rem_long: /* 0x9f */ +/* File: arm64/op_rem_long.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x2, w2 // w2<- vCC + GET_VREG_WIDE x1, w1 // w1<- vBB + .if 1 + cbz x2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + sdiv x3, x1, x2 + msub x0, x3, x2, x1 // x0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w4 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_and_long: /* 0xa0 */ +/* File: arm64/op_and_long.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x2, w2 // w2<- vCC + GET_VREG_WIDE x1, w1 // w1<- vBB + .if 0 + cbz x2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + and x0, x1, x2 // x0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w4 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_or_long: /* 0xa1 */ +/* File: arm64/op_or_long.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x2, w2 // w2<- vCC + GET_VREG_WIDE x1, w1 // w1<- vBB + .if 0 + cbz x2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + orr x0, x1, x2 // x0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w4 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_xor_long: /* 0xa2 */ +/* File: arm64/op_xor_long.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x2, w2 // w2<- vCC + GET_VREG_WIDE x1, w1 // w1<- vBB + .if 0 + cbz x2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + eor x0, x1, x2 // x0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w4 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_shl_long: /* 0xa3 */ +/* File: arm64/op_shl_long.S */ +/* File: arm64/shiftWide.S */ + /* + * 64-bit shift operation. + * + * For: shl-long, shr-long, ushr-long + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w3, wINST, #8 // w3<- AA + lsr w2, w0, #8 // w2<- CC + GET_VREG w2, w2 // w2<- vCC (shift count) + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x1, w1 // x1<- vBB + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + and x2, x2, #63 // Mask low 6 + lsl x0, x1, x2 // Do the shift. + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w3 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_shr_long: /* 0xa4 */ +/* File: arm64/op_shr_long.S */ +/* File: arm64/shiftWide.S */ + /* + * 64-bit shift operation. + * + * For: shl-long, shr-long, ushr-long + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w3, wINST, #8 // w3<- AA + lsr w2, w0, #8 // w2<- CC + GET_VREG w2, w2 // w2<- vCC (shift count) + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x1, w1 // x1<- vBB + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + and x2, x2, #63 // Mask low 6 + asr x0, x1, x2 // Do the shift. + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w3 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_ushr_long: /* 0xa5 */ +/* File: arm64/op_ushr_long.S */ +/* File: arm64/shiftWide.S */ + /* + * 64-bit shift operation. + * + * For: shl-long, shr-long, ushr-long + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w3, wINST, #8 // w3<- AA + lsr w2, w0, #8 // w2<- CC + GET_VREG w2, w2 // w2<- vCC (shift count) + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE x1, w1 // x1<- vBB + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + and x2, x2, #63 // Mask low 6 + lsr x0, x1, x2 // Do the shift. + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w3 // vAA<- x0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_add_float: /* 0xa6 */ +/* File: arm64/op_add_float.S */ +/* File: arm64/fbinop.S */ + /*: + * Generic 32-bit floating-point operation. + * + * For: add-float, sub-float, mul-float, div-float + * form: s0, s0, s1 + */ + /* floatop vAA, vBB, vCC */ + FETCH w0, 1 // r0<- CCBB + lsr w1, w0, #8 // r2<- CC + and w0, w0, #255 // r1<- BB + GET_VREG s1, w1 + GET_VREG s0, w0 + fadd s0, s0, s1 // s0<- op + lsr w1, wINST, #8 // r1<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s0, w1 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_sub_float: /* 0xa7 */ +/* File: arm64/op_sub_float.S */ +/* File: arm64/fbinop.S */ + /*: + * Generic 32-bit floating-point operation. + * + * For: add-float, sub-float, mul-float, div-float + * form: s0, s0, s1 + */ + /* floatop vAA, vBB, vCC */ + FETCH w0, 1 // r0<- CCBB + lsr w1, w0, #8 // r2<- CC + and w0, w0, #255 // r1<- BB + GET_VREG s1, w1 + GET_VREG s0, w0 + fsub s0, s0, s1 // s0<- op + lsr w1, wINST, #8 // r1<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s0, w1 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_mul_float: /* 0xa8 */ +/* File: arm64/op_mul_float.S */ +/* File: arm64/fbinop.S */ + /*: + * Generic 32-bit floating-point operation. + * + * For: add-float, sub-float, mul-float, div-float + * form: s0, s0, s1 + */ + /* floatop vAA, vBB, vCC */ + FETCH w0, 1 // r0<- CCBB + lsr w1, w0, #8 // r2<- CC + and w0, w0, #255 // r1<- BB + GET_VREG s1, w1 + GET_VREG s0, w0 + fmul s0, s0, s1 // s0<- op + lsr w1, wINST, #8 // r1<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s0, w1 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_div_float: /* 0xa9 */ +/* File: arm64/op_div_float.S */ +/* File: arm64/fbinop.S */ + /*: + * Generic 32-bit floating-point operation. + * + * For: add-float, sub-float, mul-float, div-float + * form: s0, s0, s1 + */ + /* floatop vAA, vBB, vCC */ + FETCH w0, 1 // r0<- CCBB + lsr w1, w0, #8 // r2<- CC + and w0, w0, #255 // r1<- BB + GET_VREG s1, w1 + GET_VREG s0, w0 + fdiv s0, s0, s1 // s0<- op + lsr w1, wINST, #8 // r1<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s0, w1 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_rem_float: /* 0xaa */ +/* File: arm64/op_rem_float.S */ +/* EABI doesn't define a float remainder function, but libm does */ +/* File: arm64/fbinop.S */ + /*: + * Generic 32-bit floating-point operation. + * + * For: add-float, sub-float, mul-float, div-float + * form: s0, s0, s1 + */ + /* floatop vAA, vBB, vCC */ + FETCH w0, 1 // r0<- CCBB + lsr w1, w0, #8 // r2<- CC + and w0, w0, #255 // r1<- BB + GET_VREG s1, w1 + GET_VREG s0, w0 + bl fmodf // s0<- op + lsr w1, wINST, #8 // r1<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s0, w1 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_add_double: /* 0xab */ +/* File: arm64/op_add_double.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE d2, w2 // w2<- vCC + GET_VREG_WIDE d1, w1 // w1<- vBB + .if 0 + cbz d2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + fadd d0, d1, d2 // d0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w4 // vAA<- d0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_sub_double: /* 0xac */ +/* File: arm64/op_sub_double.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE d2, w2 // w2<- vCC + GET_VREG_WIDE d1, w1 // w1<- vBB + .if 0 + cbz d2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + fsub d0, d1, d2 // d0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w4 // vAA<- d0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_mul_double: /* 0xad */ +/* File: arm64/op_mul_double.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE d2, w2 // w2<- vCC + GET_VREG_WIDE d1, w1 // w1<- vBB + .if 0 + cbz d2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + fmul d0, d1, d2 // d0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w4 // vAA<- d0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_div_double: /* 0xae */ +/* File: arm64/op_div_double.S */ +/* File: arm64/binopWide.S */ + /* + * Generic 64-bit binary operation. Provide an "instr" line that + * specifies an instruction that performs "result = x1 op x2". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than x0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, + * xor-long, add-double, sub-double, mul-double, div-double, rem-double + */ + /* binop vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w4, wINST, #8 // w4<- AA + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE d2, w2 // w2<- vCC + GET_VREG_WIDE d1, w1 // w1<- vBB + .if 0 + cbz d2, common_errDivideByZero // is second operand zero? + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + fdiv d0, d1, d2 // d0<- op, w0-w4 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w4 // vAA<- d0 + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_rem_double: /* 0xaf */ +/* File: arm64/op_rem_double.S */ + /* rem vAA, vBB, vCC */ + FETCH w0, 1 // w0<- CCBB + lsr w2, w0, #8 // w2<- CC + and w1, w0, #255 // w1<- BB + GET_VREG_WIDE d1, w2 // d1<- vCC + GET_VREG_WIDE d0, w1 // d0<- vBB + bl fmod + lsr w4, wINST, #8 // w4<- AA + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w4 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 11-14 instructions */ + +/* ------------------------------ */ + .balign 128 +.L_op_add_int_2addr: /* 0xb0 */ +/* File: arm64/op_add_int_2addr.S */ +/* File: arm64/binop2addr.S */ + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + // optional op; may set condition codes + add w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_sub_int_2addr: /* 0xb1 */ +/* File: arm64/op_sub_int_2addr.S */ +/* File: arm64/binop2addr.S */ + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + // optional op; may set condition codes + sub w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_mul_int_2addr: /* 0xb2 */ +/* File: arm64/op_mul_int_2addr.S */ +/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ +/* File: arm64/binop2addr.S */ + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + // optional op; may set condition codes + mul w0, w1, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_div_int_2addr: /* 0xb3 */ +/* File: arm64/op_div_int_2addr.S */ +/* File: arm64/binop2addr.S */ + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if 1 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + // optional op; may set condition codes + sdiv w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_rem_int_2addr: /* 0xb4 */ +/* File: arm64/op_rem_int_2addr.S */ +/* File: arm64/binop2addr.S */ + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if 1 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + sdiv w2, w0, w1 // optional op; may set condition codes + msub w0, w2, w1, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_and_int_2addr: /* 0xb5 */ +/* File: arm64/op_and_int_2addr.S */ +/* File: arm64/binop2addr.S */ + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + // optional op; may set condition codes + and w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_or_int_2addr: /* 0xb6 */ +/* File: arm64/op_or_int_2addr.S */ +/* File: arm64/binop2addr.S */ + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + // optional op; may set condition codes + orr w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_xor_int_2addr: /* 0xb7 */ +/* File: arm64/op_xor_int_2addr.S */ +/* File: arm64/binop2addr.S */ + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + // optional op; may set condition codes + eor w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_shl_int_2addr: /* 0xb8 */ +/* File: arm64/op_shl_int_2addr.S */ +/* File: arm64/binop2addr.S */ + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + and w1, w1, #31 // optional op; may set condition codes + lsl w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_shr_int_2addr: /* 0xb9 */ +/* File: arm64/op_shr_int_2addr.S */ +/* File: arm64/binop2addr.S */ + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + and w1, w1, #31 // optional op; may set condition codes + asr w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_ushr_int_2addr: /* 0xba */ +/* File: arm64/op_ushr_int_2addr.S */ +/* File: arm64/binop2addr.S */ + /* + * Generic 32-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, + * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, + * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, + * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w1, w3 // w1<- vB + GET_VREG w0, w9 // w0<- vA + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + and w1, w1, #31 // optional op; may set condition codes + lsr w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_add_long_2addr: /* 0xbb */ +/* File: arm64/op_add_long_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE x1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + .if 0 + cbz x1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + + add x0, x0, x1 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_sub_long_2addr: /* 0xbc */ +/* File: arm64/op_sub_long_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE x1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + .if 0 + cbz x1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + + sub x0, x0, x1 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_mul_long_2addr: /* 0xbd */ +/* File: arm64/op_mul_long_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE x1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + .if 0 + cbz x1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + + mul x0, x0, x1 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_div_long_2addr: /* 0xbe */ +/* File: arm64/op_div_long_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE x1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + .if 1 + cbz x1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + + sdiv x0, x0, x1 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_rem_long_2addr: /* 0xbf */ +/* File: arm64/op_rem_long_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE x1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + .if 1 + cbz x1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + sdiv x3, x0, x1 + msub x0, x3, x1, x0 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_and_long_2addr: /* 0xc0 */ +/* File: arm64/op_and_long_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE x1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + .if 0 + cbz x1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + + and x0, x0, x1 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_or_long_2addr: /* 0xc1 */ +/* File: arm64/op_or_long_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE x1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + .if 0 + cbz x1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + + orr x0, x0, x1 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_xor_long_2addr: /* 0xc2 */ +/* File: arm64/op_xor_long_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE x1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + .if 0 + cbz x1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + + eor x0, x0, x1 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_shl_long_2addr: /* 0xc3 */ +/* File: arm64/op_shl_long_2addr.S */ +/* File: arm64/shiftWide2addr.S */ + /* + * Generic 64-bit shift operation. + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + and x1, x1, #63 // Mask low 6 bits. + lsl x0, x0, x1 + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_shr_long_2addr: /* 0xc4 */ +/* File: arm64/op_shr_long_2addr.S */ +/* File: arm64/shiftWide2addr.S */ + /* + * Generic 64-bit shift operation. + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + and x1, x1, #63 // Mask low 6 bits. + asr x0, x0, x1 + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_ushr_long_2addr: /* 0xc5 */ +/* File: arm64/op_ushr_long_2addr.S */ +/* File: arm64/shiftWide2addr.S */ + /* + * Generic 64-bit shift operation. + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG w1, w1 // x1<- vB + GET_VREG_WIDE x0, w2 // x0<- vA + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + and x1, x1, #63 // Mask low 6 bits. + lsr x0, x0, x1 + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE x0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_add_float_2addr: /* 0xc6 */ +/* File: arm64/op_add_float_2addr.S */ +/* File: arm64/fbinop2addr.S */ + /* + * Generic 32-bit floating point "/2addr" binary operation. Provide + * an "instr" line that specifies an instruction that performs + * "s2 = s0 op s1". + * + * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w9, wINST, #8 // w9<- A+ + and w9, w9, #15 // w9<- A + GET_VREG s1, w3 + GET_VREG s0, w9 + fadd s2, s0, s1 // s2<- op + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s2, w9 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_sub_float_2addr: /* 0xc7 */ +/* File: arm64/op_sub_float_2addr.S */ +/* File: arm64/fbinop2addr.S */ + /* + * Generic 32-bit floating point "/2addr" binary operation. Provide + * an "instr" line that specifies an instruction that performs + * "s2 = s0 op s1". + * + * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w9, wINST, #8 // w9<- A+ + and w9, w9, #15 // w9<- A + GET_VREG s1, w3 + GET_VREG s0, w9 + fsub s2, s0, s1 // s2<- op + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s2, w9 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_mul_float_2addr: /* 0xc8 */ +/* File: arm64/op_mul_float_2addr.S */ +/* File: arm64/fbinop2addr.S */ + /* + * Generic 32-bit floating point "/2addr" binary operation. Provide + * an "instr" line that specifies an instruction that performs + * "s2 = s0 op s1". + * + * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w9, wINST, #8 // w9<- A+ + and w9, w9, #15 // w9<- A + GET_VREG s1, w3 + GET_VREG s0, w9 + fmul s2, s0, s1 // s2<- op + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s2, w9 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_div_float_2addr: /* 0xc9 */ +/* File: arm64/op_div_float_2addr.S */ +/* File: arm64/fbinop2addr.S */ + /* + * Generic 32-bit floating point "/2addr" binary operation. Provide + * an "instr" line that specifies an instruction that performs + * "s2 = s0 op s1". + * + * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr + */ + /* binop/2addr vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w9, wINST, #8 // w9<- A+ + and w9, w9, #15 // w9<- A + GET_VREG s1, w3 + GET_VREG s0, w9 + fdiv s2, s0, s1 // s2<- op + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s2, w9 + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_rem_float_2addr: /* 0xca */ +/* File: arm64/op_rem_float_2addr.S */ + /* rem vA, vB */ + lsr w3, wINST, #12 // w3<- B + lsr w9, wINST, #8 // w9<- A+ + and w9, w9, #15 // w9<- A + GET_VREG s1, w3 + GET_VREG s0, w9 + bl fmodf + lsr w9, wINST, #8 // w9<- A+ + and w9, w9, #15 // w9<- A + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG s0, w9 + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_add_double_2addr: /* 0xcb */ +/* File: arm64/op_add_double_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE d1, w1 // x1<- vB + GET_VREG_WIDE d0, w2 // x0<- vA + .if 0 + cbz d1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + + fadd d0, d0, d1 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_sub_double_2addr: /* 0xcc */ +/* File: arm64/op_sub_double_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE d1, w1 // x1<- vB + GET_VREG_WIDE d0, w2 // x0<- vA + .if 0 + cbz d1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + + fsub d0, d0, d1 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_mul_double_2addr: /* 0xcd */ +/* File: arm64/op_mul_double_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE d1, w1 // x1<- vB + GET_VREG_WIDE d0, w2 // x0<- vA + .if 0 + cbz d1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + + fmul d0, d0, d1 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_div_double_2addr: /* 0xce */ +/* File: arm64/op_div_double_2addr.S */ +/* File: arm64/binopWide2addr.S */ + /* + * Generic 64-bit "/2addr" binary operation. Provide an "instr" line + * that specifies an instruction that performs "x0 = x0 op x1". + * This must not be a function call, as we keep w2 live across it. + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, + * and-long/2addr, or-long/2addr, xor-long/2addr, + * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, + * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr + */ + /* binop/2addr vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE d1, w1 // x1<- vB + GET_VREG_WIDE d0, w2 // x0<- vA + .if 0 + cbz d1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + + fdiv d0, d0, d1 // result<- op + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_rem_double_2addr: /* 0xcf */ +/* File: arm64/op_rem_double_2addr.S */ + /* rem vA, vB */ + lsr w1, wINST, #12 // w1<- B + ubfx w2, wINST, #8, #4 // w2<- A + GET_VREG_WIDE d1, w1 // d1<- vB + GET_VREG_WIDE d0, w2 // d0<- vA + FETCH_ADVANCE_INST 1 // advance rPC, load rINST + bl fmod + ubfx w2, wINST, #8, #4 // w2<- A (need to reload - killed across call) + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG_WIDE d0, w2 // vAA<- result + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + +/* ------------------------------ */ + .balign 128 +.L_op_add_int_lit16: /* 0xd0 */ +/* File: arm64/op_add_int_lit16.S */ +/* File: arm64/binopLit16.S */ + /* + * Generic 32-bit "lit16" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, + * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 + */ + /* binop/lit16 vA, vB, #+CCCC */ + FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) + lsr w2, wINST, #12 // w2<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w0, w2 // w0<- vB + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + add w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_rsub_int: /* 0xd1 */ +/* File: arm64/op_rsub_int.S */ +/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ +/* File: arm64/binopLit16.S */ + /* + * Generic 32-bit "lit16" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, + * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 + */ + /* binop/lit16 vA, vB, #+CCCC */ + FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) + lsr w2, wINST, #12 // w2<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w0, w2 // w0<- vB + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + sub w0, w1, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_mul_int_lit16: /* 0xd2 */ +/* File: arm64/op_mul_int_lit16.S */ +/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ +/* File: arm64/binopLit16.S */ + /* + * Generic 32-bit "lit16" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, + * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 + */ + /* binop/lit16 vA, vB, #+CCCC */ + FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) + lsr w2, wINST, #12 // w2<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w0, w2 // w0<- vB + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + mul w0, w1, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_div_int_lit16: /* 0xd3 */ +/* File: arm64/op_div_int_lit16.S */ +/* File: arm64/binopLit16.S */ + /* + * Generic 32-bit "lit16" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, + * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 + */ + /* binop/lit16 vA, vB, #+CCCC */ + FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) + lsr w2, wINST, #12 // w2<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w0, w2 // w0<- vB + .if 1 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + sdiv w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_rem_int_lit16: /* 0xd4 */ +/* File: arm64/op_rem_int_lit16.S */ +/* File: arm64/binopLit16.S */ + /* + * Generic 32-bit "lit16" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, + * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 + */ + /* binop/lit16 vA, vB, #+CCCC */ + FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) + lsr w2, wINST, #12 // w2<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w0, w2 // w0<- vB + .if 1 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + sdiv w3, w0, w1 + msub w0, w3, w1, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_and_int_lit16: /* 0xd5 */ +/* File: arm64/op_and_int_lit16.S */ +/* File: arm64/binopLit16.S */ + /* + * Generic 32-bit "lit16" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, + * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 + */ + /* binop/lit16 vA, vB, #+CCCC */ + FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) + lsr w2, wINST, #12 // w2<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w0, w2 // w0<- vB + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + and w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_or_int_lit16: /* 0xd6 */ +/* File: arm64/op_or_int_lit16.S */ +/* File: arm64/binopLit16.S */ + /* + * Generic 32-bit "lit16" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, + * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 + */ + /* binop/lit16 vA, vB, #+CCCC */ + FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) + lsr w2, wINST, #12 // w2<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w0, w2 // w0<- vB + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + orr w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_xor_int_lit16: /* 0xd7 */ +/* File: arm64/op_xor_int_lit16.S */ +/* File: arm64/binopLit16.S */ + /* + * Generic 32-bit "lit16" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, + * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 + */ + /* binop/lit16 vA, vB, #+CCCC */ + FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) + lsr w2, wINST, #12 // w2<- B + ubfx w9, wINST, #8, #4 // w9<- A + GET_VREG w0, w2 // w0<- vB + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + eor w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-13 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_add_int_lit8: /* 0xd8 */ +/* File: arm64/op_add_int_lit8.S */ +/* File: arm64/binopLit8.S */ + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + add w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_rsub_int_lit8: /* 0xd9 */ +/* File: arm64/op_rsub_int_lit8.S */ +/* File: arm64/binopLit8.S */ + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + sub w0, w1, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_mul_int_lit8: /* 0xda */ +/* File: arm64/op_mul_int_lit8.S */ +/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ +/* File: arm64/binopLit8.S */ + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + mul w0, w1, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_div_int_lit8: /* 0xdb */ +/* File: arm64/op_div_int_lit8.S */ +/* File: arm64/binopLit8.S */ + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if 1 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + sdiv w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_rem_int_lit8: /* 0xdc */ +/* File: arm64/op_rem_int_lit8.S */ +/* File: arm64/binopLit8.S */ + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if 1 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + sdiv w3, w0, w1 // optional op; may set condition codes + msub w0, w3, w1, w0 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_and_int_lit8: /* 0xdd */ +/* File: arm64/op_and_int_lit8.S */ +/* File: arm64/binopLit8.S */ + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + and w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_or_int_lit8: /* 0xde */ +/* File: arm64/op_or_int_lit8.S */ +/* File: arm64/binopLit8.S */ + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + orr w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_xor_int_lit8: /* 0xdf */ +/* File: arm64/op_xor_int_lit8.S */ +/* File: arm64/binopLit8.S */ + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + // optional op; may set condition codes + eor w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_shl_int_lit8: /* 0xe0 */ +/* File: arm64/op_shl_int_lit8.S */ +/* File: arm64/binopLit8.S */ + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + and w1, w1, #31 // optional op; may set condition codes + lsl w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_shr_int_lit8: /* 0xe1 */ +/* File: arm64/op_shr_int_lit8.S */ +/* File: arm64/binopLit8.S */ + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + and w1, w1, #31 // optional op; may set condition codes + asr w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_ushr_int_lit8: /* 0xe2 */ +/* File: arm64/op_ushr_int_lit8.S */ +/* File: arm64/binopLit8.S */ + /* + * Generic 32-bit "lit8" binary operation. Provide an "instr" line + * that specifies an instruction that performs "result = w0 op w1". + * This could be an ARM instruction or a function call. (If the result + * comes back in a register other than w0, you can override "result".) + * + * If "chkzero" is set to 1, we perform a divide-by-zero check on + * vCC (w1). Useful for integer division and modulus. + * + * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, + * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, + * shl-int/lit8, shr-int/lit8, ushr-int/lit8 + */ + /* binop/lit8 vAA, vBB, #+CC */ + FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC + lsr w9, wINST, #8 // w9<- AA + and w2, w3, #255 // w2<- BB + GET_VREG w0, w2 // w0<- vBB + asr w1, w3, #8 // w1<- ssssssCC (sign extended) + .if 0 + cbz w1, common_errDivideByZero + .endif + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + and w1, w1, #31 // optional op; may set condition codes + lsr w0, w0, w1 // w0<- op, w0-w3 changed + GET_INST_OPCODE ip // extract opcode from rINST + SET_VREG w0, w9 // vAA<- w0 + GOTO_OPCODE ip // jump to next instruction + /* 10-12 instructions */ + + +/* ------------------------------ */ + .balign 128 +.L_op_iget_quick: /* 0xe3 */ +/* File: arm64/op_iget_quick.S */ + /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- object we're operating on + ubfx w2, wINST, #8, #4 // w2<- A + cmp x3, #0 // check object for null + beq common_errNullObject // object was null + ldr w0, [x3, x1] // w0<- obj.field + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + SET_VREG w0, w2 // fp[A]<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_iget_wide_quick: /* 0xe4 */ +/* File: arm64/op_iget_wide_quick.S */ + /* iget-wide-quick vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w4, 1 // w4<- field byte offset + GET_VREG w3, w2 // w3<- object we're operating on + ubfx w2, wINST, #8, #4 // w2<- A + cbz w3, common_errNullObject // object was null + add x4, x3, x4 // create direct pointer + ldr x0, [x4] + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + SET_VREG_WIDE x0, w2 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_iget_object_quick: /* 0xe5 */ +/* File: arm64/op_iget_object_quick.S */ + /* For: iget-object-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + EXPORT_PC + GET_VREG w0, w2 // w0<- object we're operating on + bl artIGetObjectFromMterp // (obj, offset) + ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] + ubfx w2, wINST, #8, #4 // w2<- A + PREFETCH_INST 2 + cbnz w3, MterpPossibleException // bail out + SET_VREG_OBJECT w0, w2 // fp[A]<- w0 + ADVANCE 2 // advance rPC + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_iput_quick: /* 0xe6 */ +/* File: arm64/op_iput_quick.S */ + /* For: iput-quick, iput-object-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + cmp w3, #0 // check object for null + cbz w3, common_errNullObject // object was null + GET_VREG w0, w2 // w0<- fp[A] + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + str w0, [x3, x1] // obj.field<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_iput_wide_quick: /* 0xe7 */ +/* File: arm64/op_iput_wide_quick.S */ + /* iput-wide-quick vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w3, 1 // w3<- field byte offset + GET_VREG w2, w2 // w2<- fp[B], the object pointer + ubfx w0, wINST, #8, #4 // w0<- A + cmp w2, #0 // check object for null + beq common_errNullObject // object was null + GET_VREG_WIDE x0, w0 // x0-< fp[A] + FETCH_ADVANCE_INST 2 // advance rPC, load wINST + add x1, x2, x3 // create a direct pointer + str x0, [x1] + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_iput_object_quick: /* 0xe8 */ +/* File: arm64/op_iput_object_quick.S */ + EXPORT_PC + add x0, xFP, #OFF_FP_SHADOWFRAME + mov x1, xPC + mov w2, wINST + bl MterpIputObjectQuick + cbz w0, MterpException + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_virtual_quick: /* 0xe9 */ +/* File: arm64/op_invoke_virtual_quick.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeVirtualQuick + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeVirtualQuick + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_virtual_range_quick: /* 0xea */ +/* File: arm64/op_invoke_virtual_range_quick.S */ +/* File: arm64/invoke.S */ + /* + * Generic invoke handler wrapper. + */ + /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ + /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ + .extern MterpInvokeVirtualQuickRange + EXPORT_PC + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + mov x2, xPC + // and x3, xINST, 0xFFFF + mov x3, xINST + bl MterpInvokeVirtualQuickRange + cbz w0, MterpException + FETCH_ADVANCE_INST 3 + GET_INST_OPCODE ip + GOTO_OPCODE ip + + + +/* ------------------------------ */ + .balign 128 +.L_op_iput_boolean_quick: /* 0xeb */ +/* File: arm64/op_iput_boolean_quick.S */ +/* File: arm64/op_iput_quick.S */ + /* For: iput-quick, iput-object-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + cmp w3, #0 // check object for null + cbz w3, common_errNullObject // object was null + GET_VREG w0, w2 // w0<- fp[A] + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + strb w0, [x3, x1] // obj.field<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iput_byte_quick: /* 0xec */ +/* File: arm64/op_iput_byte_quick.S */ +/* File: arm64/op_iput_quick.S */ + /* For: iput-quick, iput-object-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + cmp w3, #0 // check object for null + cbz w3, common_errNullObject // object was null + GET_VREG w0, w2 // w0<- fp[A] + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + strb w0, [x3, x1] // obj.field<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iput_char_quick: /* 0xed */ +/* File: arm64/op_iput_char_quick.S */ +/* File: arm64/op_iput_quick.S */ + /* For: iput-quick, iput-object-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + cmp w3, #0 // check object for null + cbz w3, common_errNullObject // object was null + GET_VREG w0, w2 // w0<- fp[A] + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + strh w0, [x3, x1] // obj.field<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iput_short_quick: /* 0xee */ +/* File: arm64/op_iput_short_quick.S */ +/* File: arm64/op_iput_quick.S */ + /* For: iput-quick, iput-object-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- fp[B], the object pointer + ubfx w2, wINST, #8, #4 // w2<- A + cmp w3, #0 // check object for null + cbz w3, common_errNullObject // object was null + GET_VREG w0, w2 // w0<- fp[A] + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + strh w0, [x3, x1] // obj.field<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iget_boolean_quick: /* 0xef */ +/* File: arm64/op_iget_boolean_quick.S */ +/* File: arm64/op_iget_quick.S */ + /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- object we're operating on + ubfx w2, wINST, #8, #4 // w2<- A + cmp x3, #0 // check object for null + beq common_errNullObject // object was null + ldrb w0, [x3, x1] // w0<- obj.field + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + SET_VREG w0, w2 // fp[A]<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iget_byte_quick: /* 0xf0 */ +/* File: arm64/op_iget_byte_quick.S */ +/* File: arm64/op_iget_quick.S */ + /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- object we're operating on + ubfx w2, wINST, #8, #4 // w2<- A + cmp x3, #0 // check object for null + beq common_errNullObject // object was null + ldrsb w0, [x3, x1] // w0<- obj.field + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + SET_VREG w0, w2 // fp[A]<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iget_char_quick: /* 0xf1 */ +/* File: arm64/op_iget_char_quick.S */ +/* File: arm64/op_iget_quick.S */ + /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- object we're operating on + ubfx w2, wINST, #8, #4 // w2<- A + cmp x3, #0 // check object for null + beq common_errNullObject // object was null + ldrh w0, [x3, x1] // w0<- obj.field + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + SET_VREG w0, w2 // fp[A]<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_iget_short_quick: /* 0xf2 */ +/* File: arm64/op_iget_short_quick.S */ +/* File: arm64/op_iget_quick.S */ + /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */ + /* op vA, vB, offset//CCCC */ + lsr w2, wINST, #12 // w2<- B + FETCH w1, 1 // w1<- field byte offset + GET_VREG w3, w2 // w3<- object we're operating on + ubfx w2, wINST, #8, #4 // w2<- A + cmp x3, #0 // check object for null + beq common_errNullObject // object was null + ldrsh w0, [x3, x1] // w0<- obj.field + FETCH_ADVANCE_INST 2 // advance rPC, load rINST + + SET_VREG w0, w2 // fp[A]<- w0 + GET_INST_OPCODE ip // extract opcode from rINST + GOTO_OPCODE ip // jump to next instruction + + +/* ------------------------------ */ + .balign 128 +.L_op_invoke_lambda: /* 0xf3 */ +/* Transfer stub to alternate interpreter */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_f4: /* 0xf4 */ +/* File: arm64/op_unused_f4.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_capture_variable: /* 0xf5 */ +/* Transfer stub to alternate interpreter */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_create_lambda: /* 0xf6 */ +/* Transfer stub to alternate interpreter */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_liberate_variable: /* 0xf7 */ +/* Transfer stub to alternate interpreter */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_box_lambda: /* 0xf8 */ +/* Transfer stub to alternate interpreter */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unbox_lambda: /* 0xf9 */ +/* Transfer stub to alternate interpreter */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_fa: /* 0xfa */ +/* File: arm64/op_unused_fa.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_fb: /* 0xfb */ +/* File: arm64/op_unused_fb.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_fc: /* 0xfc */ +/* File: arm64/op_unused_fc.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_fd: /* 0xfd */ +/* File: arm64/op_unused_fd.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_fe: /* 0xfe */ +/* File: arm64/op_unused_fe.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + +/* ------------------------------ */ + .balign 128 +.L_op_unused_ff: /* 0xff */ +/* File: arm64/op_unused_ff.S */ +/* File: arm64/unused.S */ +/* + * Bail to reference interpreter to throw. + */ + b MterpFallback + + + .balign 128 + .size artMterpAsmInstructionStart, .-artMterpAsmInstructionStart + .global artMterpAsmInstructionEnd +artMterpAsmInstructionEnd: + +/* + * =========================================================================== + * Sister implementations + * =========================================================================== + */ + .global artMterpAsmSisterStart + .type artMterpAsmSisterStart, %function + .text + .balign 4 +artMterpAsmSisterStart: + + .size artMterpAsmSisterStart, .-artMterpAsmSisterStart + .global artMterpAsmSisterEnd +artMterpAsmSisterEnd: + + + .global artMterpAsmAltInstructionStart + .type artMterpAsmAltInstructionStart, %function + .text + +artMterpAsmAltInstructionStart = .L_ALT_op_nop +/* ------------------------------ */ + .balign 128 +.L_ALT_op_nop: /* 0x00 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (0 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move: /* 0x01 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (1 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_from16: /* 0x02 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (2 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_16: /* 0x03 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (3 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_wide: /* 0x04 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (4 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_wide_from16: /* 0x05 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (5 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_wide_16: /* 0x06 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (6 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_object: /* 0x07 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (7 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_object_from16: /* 0x08 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (8 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_object_16: /* 0x09 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (9 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_result: /* 0x0a */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (10 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_result_wide: /* 0x0b */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (11 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_result_object: /* 0x0c */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (12 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_move_exception: /* 0x0d */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (13 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_return_void: /* 0x0e */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (14 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_return: /* 0x0f */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (15 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_return_wide: /* 0x10 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (16 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_return_object: /* 0x11 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (17 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_const_4: /* 0x12 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (18 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_const_16: /* 0x13 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (19 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_const: /* 0x14 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (20 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_const_high16: /* 0x15 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (21 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_const_wide_16: /* 0x16 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (22 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_const_wide_32: /* 0x17 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (23 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_const_wide: /* 0x18 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (24 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_const_wide_high16: /* 0x19 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (25 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_const_string: /* 0x1a */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (26 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_const_string_jumbo: /* 0x1b */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (27 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_const_class: /* 0x1c */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (28 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_monitor_enter: /* 0x1d */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (29 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_monitor_exit: /* 0x1e */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (30 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_check_cast: /* 0x1f */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (31 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_instance_of: /* 0x20 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (32 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_array_length: /* 0x21 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (33 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_new_instance: /* 0x22 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (34 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_new_array: /* 0x23 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (35 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_filled_new_array: /* 0x24 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (36 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_filled_new_array_range: /* 0x25 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (37 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_fill_array_data: /* 0x26 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (38 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_throw: /* 0x27 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (39 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_goto: /* 0x28 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (40 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_goto_16: /* 0x29 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (41 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_goto_32: /* 0x2a */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (42 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_packed_switch: /* 0x2b */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (43 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sparse_switch: /* 0x2c */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (44 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_cmpl_float: /* 0x2d */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (45 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_cmpg_float: /* 0x2e */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (46 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_cmpl_double: /* 0x2f */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (47 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_cmpg_double: /* 0x30 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (48 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_cmp_long: /* 0x31 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (49 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_eq: /* 0x32 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (50 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_ne: /* 0x33 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (51 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_lt: /* 0x34 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (52 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_ge: /* 0x35 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (53 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_gt: /* 0x36 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (54 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_le: /* 0x37 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (55 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_eqz: /* 0x38 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (56 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_nez: /* 0x39 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (57 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_ltz: /* 0x3a */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (58 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_gez: /* 0x3b */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (59 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_gtz: /* 0x3c */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (60 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_if_lez: /* 0x3d */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (61 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_3e: /* 0x3e */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (62 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_3f: /* 0x3f */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (63 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_40: /* 0x40 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (64 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_41: /* 0x41 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (65 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_42: /* 0x42 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (66 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_43: /* 0x43 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (67 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aget: /* 0x44 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (68 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aget_wide: /* 0x45 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (69 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aget_object: /* 0x46 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (70 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aget_boolean: /* 0x47 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (71 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aget_byte: /* 0x48 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (72 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aget_char: /* 0x49 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (73 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aget_short: /* 0x4a */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (74 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aput: /* 0x4b */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (75 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aput_wide: /* 0x4c */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (76 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aput_object: /* 0x4d */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (77 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aput_boolean: /* 0x4e */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (78 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aput_byte: /* 0x4f */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (79 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aput_char: /* 0x50 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (80 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_aput_short: /* 0x51 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (81 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget: /* 0x52 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (82 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_wide: /* 0x53 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (83 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_object: /* 0x54 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (84 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_boolean: /* 0x55 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (85 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_byte: /* 0x56 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (86 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_char: /* 0x57 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (87 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_short: /* 0x58 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (88 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput: /* 0x59 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (89 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_wide: /* 0x5a */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (90 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_object: /* 0x5b */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (91 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_boolean: /* 0x5c */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (92 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_byte: /* 0x5d */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (93 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_char: /* 0x5e */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (94 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_short: /* 0x5f */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (95 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sget: /* 0x60 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (96 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sget_wide: /* 0x61 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (97 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sget_object: /* 0x62 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (98 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sget_boolean: /* 0x63 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (99 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sget_byte: /* 0x64 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (100 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sget_char: /* 0x65 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (101 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sget_short: /* 0x66 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (102 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sput: /* 0x67 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (103 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sput_wide: /* 0x68 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (104 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sput_object: /* 0x69 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (105 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sput_boolean: /* 0x6a */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (106 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sput_byte: /* 0x6b */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (107 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sput_char: /* 0x6c */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (108 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sput_short: /* 0x6d */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (109 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_virtual: /* 0x6e */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (110 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_super: /* 0x6f */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (111 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_direct: /* 0x70 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (112 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_static: /* 0x71 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (113 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_interface: /* 0x72 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (114 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_return_void_no_barrier: /* 0x73 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (115 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_virtual_range: /* 0x74 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (116 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_super_range: /* 0x75 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (117 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_direct_range: /* 0x76 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (118 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_static_range: /* 0x77 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (119 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_interface_range: /* 0x78 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (120 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_79: /* 0x79 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (121 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_7a: /* 0x7a */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (122 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_neg_int: /* 0x7b */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (123 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_not_int: /* 0x7c */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (124 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_neg_long: /* 0x7d */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (125 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_not_long: /* 0x7e */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (126 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_neg_float: /* 0x7f */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (127 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_neg_double: /* 0x80 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (128 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_int_to_long: /* 0x81 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (129 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_int_to_float: /* 0x82 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (130 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_int_to_double: /* 0x83 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (131 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_long_to_int: /* 0x84 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (132 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_long_to_float: /* 0x85 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (133 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_long_to_double: /* 0x86 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (134 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_float_to_int: /* 0x87 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (135 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_float_to_long: /* 0x88 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (136 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_float_to_double: /* 0x89 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (137 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_double_to_int: /* 0x8a */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (138 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_double_to_long: /* 0x8b */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (139 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_double_to_float: /* 0x8c */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (140 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_int_to_byte: /* 0x8d */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (141 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_int_to_char: /* 0x8e */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (142 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_int_to_short: /* 0x8f */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (143 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_add_int: /* 0x90 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (144 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sub_int: /* 0x91 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (145 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_mul_int: /* 0x92 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (146 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_div_int: /* 0x93 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (147 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rem_int: /* 0x94 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (148 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_and_int: /* 0x95 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (149 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_or_int: /* 0x96 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (150 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_xor_int: /* 0x97 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (151 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_shl_int: /* 0x98 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (152 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_shr_int: /* 0x99 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (153 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_ushr_int: /* 0x9a */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (154 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_add_long: /* 0x9b */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (155 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sub_long: /* 0x9c */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (156 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_mul_long: /* 0x9d */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (157 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_div_long: /* 0x9e */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (158 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rem_long: /* 0x9f */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (159 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_and_long: /* 0xa0 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (160 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_or_long: /* 0xa1 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (161 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_xor_long: /* 0xa2 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (162 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_shl_long: /* 0xa3 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (163 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_shr_long: /* 0xa4 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (164 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_ushr_long: /* 0xa5 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (165 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_add_float: /* 0xa6 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (166 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sub_float: /* 0xa7 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (167 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_mul_float: /* 0xa8 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (168 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_div_float: /* 0xa9 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (169 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rem_float: /* 0xaa */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (170 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_add_double: /* 0xab */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (171 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sub_double: /* 0xac */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (172 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_mul_double: /* 0xad */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (173 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_div_double: /* 0xae */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (174 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rem_double: /* 0xaf */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (175 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_add_int_2addr: /* 0xb0 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (176 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sub_int_2addr: /* 0xb1 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (177 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_mul_int_2addr: /* 0xb2 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (178 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_div_int_2addr: /* 0xb3 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (179 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rem_int_2addr: /* 0xb4 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (180 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_and_int_2addr: /* 0xb5 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (181 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_or_int_2addr: /* 0xb6 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (182 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_xor_int_2addr: /* 0xb7 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (183 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_shl_int_2addr: /* 0xb8 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (184 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_shr_int_2addr: /* 0xb9 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (185 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_ushr_int_2addr: /* 0xba */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (186 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_add_long_2addr: /* 0xbb */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (187 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sub_long_2addr: /* 0xbc */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (188 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_mul_long_2addr: /* 0xbd */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (189 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_div_long_2addr: /* 0xbe */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (190 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rem_long_2addr: /* 0xbf */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (191 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_and_long_2addr: /* 0xc0 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (192 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_or_long_2addr: /* 0xc1 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (193 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_xor_long_2addr: /* 0xc2 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (194 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_shl_long_2addr: /* 0xc3 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (195 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_shr_long_2addr: /* 0xc4 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (196 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_ushr_long_2addr: /* 0xc5 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (197 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_add_float_2addr: /* 0xc6 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (198 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sub_float_2addr: /* 0xc7 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (199 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_mul_float_2addr: /* 0xc8 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (200 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_div_float_2addr: /* 0xc9 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (201 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rem_float_2addr: /* 0xca */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (202 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_add_double_2addr: /* 0xcb */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (203 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_sub_double_2addr: /* 0xcc */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (204 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_mul_double_2addr: /* 0xcd */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (205 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_div_double_2addr: /* 0xce */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (206 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rem_double_2addr: /* 0xcf */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (207 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_add_int_lit16: /* 0xd0 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (208 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rsub_int: /* 0xd1 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (209 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_mul_int_lit16: /* 0xd2 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (210 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_div_int_lit16: /* 0xd3 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (211 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rem_int_lit16: /* 0xd4 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (212 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_and_int_lit16: /* 0xd5 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (213 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_or_int_lit16: /* 0xd6 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (214 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_xor_int_lit16: /* 0xd7 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (215 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_add_int_lit8: /* 0xd8 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (216 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rsub_int_lit8: /* 0xd9 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (217 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_mul_int_lit8: /* 0xda */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (218 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_div_int_lit8: /* 0xdb */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (219 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_rem_int_lit8: /* 0xdc */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (220 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_and_int_lit8: /* 0xdd */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (221 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_or_int_lit8: /* 0xde */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (222 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_xor_int_lit8: /* 0xdf */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (223 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_shl_int_lit8: /* 0xe0 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (224 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_shr_int_lit8: /* 0xe1 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (225 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_ushr_int_lit8: /* 0xe2 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (226 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_quick: /* 0xe3 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (227 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_wide_quick: /* 0xe4 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (228 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_object_quick: /* 0xe5 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (229 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_quick: /* 0xe6 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (230 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_wide_quick: /* 0xe7 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (231 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_object_quick: /* 0xe8 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (232 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_virtual_quick: /* 0xe9 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (233 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_virtual_range_quick: /* 0xea */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (234 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_boolean_quick: /* 0xeb */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (235 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_byte_quick: /* 0xec */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (236 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_char_quick: /* 0xed */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (237 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iput_short_quick: /* 0xee */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (238 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_boolean_quick: /* 0xef */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (239 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_byte_quick: /* 0xf0 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (240 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_char_quick: /* 0xf1 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (241 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_iget_short_quick: /* 0xf2 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (242 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_invoke_lambda: /* 0xf3 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (243 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_f4: /* 0xf4 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (244 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_capture_variable: /* 0xf5 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (245 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_create_lambda: /* 0xf6 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (246 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_liberate_variable: /* 0xf7 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (247 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_box_lambda: /* 0xf8 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (248 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unbox_lambda: /* 0xf9 */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (249 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_fa: /* 0xfa */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (250 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_fb: /* 0xfb */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (251 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_fc: /* 0xfc */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (252 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_fd: /* 0xfd */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (253 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_fe: /* 0xfe */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (254 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + +/* ------------------------------ */ + .balign 128 +.L_ALT_op_unused_ff: /* 0xff */ +/* File: arm64/alt_stub.S */ +/* + * Inter-instruction transfer stub. Call out to MterpCheckBefore to handle + * any interesting requests and then jump to the real instruction + * handler. Note that the call to MterpCheckBefore is done as a tail call. + */ + .extern MterpCheckBefore + EXPORT_PC + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh IBASE. + adr lr, artMterpAsmInstructionStart + (255 * 128) // Addr of primary handler. + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + b MterpCheckBefore // (self, shadow_frame) Note: tail call. + + .balign 128 + .size artMterpAsmAltInstructionStart, .-artMterpAsmAltInstructionStart + .global artMterpAsmAltInstructionEnd +artMterpAsmAltInstructionEnd: +/* File: arm64/footer.S */ +/* + * =========================================================================== + * Common subroutines and data + * =========================================================================== + */ + + +/* + * We've detected a condition that will result in an exception, but the exception + * has not yet been thrown. Just bail out to the reference interpreter to deal with it. + * TUNING: for consistency, we may want to just go ahead and handle these here. + */ +#define MTERP_LOGGING 0 +common_errDivideByZero: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogDivideByZeroException +#endif + b MterpCommonFallback + +common_errArrayIndex: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogArrayIndexException +#endif + b MterpCommonFallback + +common_errNegativeArraySize: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogNegativeArraySizeException +#endif + b MterpCommonFallback + +common_errNoSuchMethod: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogNoSuchMethodException +#endif + b MterpCommonFallback + +common_errNullObject: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogNullObjectException +#endif + b MterpCommonFallback + +common_exceptionThrown: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogExceptionThrownException +#endif + b MterpCommonFallback + +MterpSuspendFallback: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + ldr x2, [xSELF, #THREAD_FLAGS_OFFSET] + bl MterpLogSuspendFallback +#endif + b MterpCommonFallback + +/* + * If we're here, something is out of the ordinary. If there is a pending + * exception, handle it. Otherwise, roll back and retry with the reference + * interpreter. + */ +MterpPossibleException: + ldr x0, [xSELF, #THREAD_EXCEPTION_OFFSET] + cbz x0, MterpFallback // If not, fall back to reference interpreter. + /* intentional fallthrough - handle pending exception. */ +/* + * On return from a runtime helper routine, we've found a pending exception. + * Can we handle it here - or need to bail out to caller? + * + */ +MterpException: + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpHandleException // (self, shadow_frame) + cbz w0, MterpExceptionReturn // no local catch, back to caller. + ldr x0, [xFP, #OFF_FP_CODE_ITEM] + ldr w1, [xFP, #OFF_FP_DEX_PC] + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] + add xPC, x0, #CODEITEM_INSNS_OFFSET + add xPC, xPC, x1, lsl #1 // generate new dex_pc_ptr + str xPC, [xFP, #OFF_FP_DEX_PC_PTR] + /* resume execution at catch block */ + FETCH_INST + GET_INST_OPCODE ip + GOTO_OPCODE ip + /* NOTE: no fallthrough */ + +/* + * Check for suspend check request. Assumes wINST already loaded, xPC advanced and + * still needs to get the opcode and branch to it, and flags are in lr. + */ +MterpCheckSuspendAndContinue: + ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] // refresh xIBASE + ands w7, w7, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.ne check1 + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction +check1: + EXPORT_PC + mov x0, xSELF + bl MterpSuspendCheck // (self) + GET_INST_OPCODE ip // extract opcode from wINST + GOTO_OPCODE ip // jump to next instruction + +/* + * Bail out to reference interpreter. + */ +MterpFallback: + EXPORT_PC +#if MTERP_LOGGING + mov x0, xSELF + add x1, xFP, #OFF_FP_SHADOWFRAME + bl MterpLogFallback +#endif +MterpCommonFallback: + mov x0, #0 // signal retry with reference interpreter. + b MterpDone + +/* + * We pushed some registers on the stack in ExecuteMterpImpl, then saved + * SP and LR. Here we restore SP, restore the registers, and then restore + * LR to PC. + * + * On entry: + * uint32_t* xFP (should still be live, pointer to base of vregs) + */ +MterpExceptionReturn: + mov x0, #1 // signal return to caller. + b MterpDone +MterpReturn: + ldr x2, [xFP, #OFF_FP_RESULT_REGISTER] + ldr lr, [xSELF, #THREAD_FLAGS_OFFSET] + str x0, [x2] + mov x0, xSELF + ands lr, lr, #(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST) + b.eq check2 + bl MterpSuspendCheck // (self) +check2: + mov x0, #1 // signal return to caller. +MterpDone: + ldp fp, lr, [sp, #48] + ldp xPC, xFP, [sp, #32] + ldp xSELF, xINST, [sp, #16] + ldp xIBASE, xREFS, [sp], #64 + ret + + .cfi_endproc + .size ExecuteMterpImpl, .-ExecuteMterpImpl + + diff --git a/runtime/interpreter/mterp/rebuild.sh b/runtime/interpreter/mterp/rebuild.sh index 8b2697632..ac8794581 100755 --- a/runtime/interpreter/mterp/rebuild.sh +++ b/runtime/interpreter/mterp/rebuild.sh @@ -21,4 +21,4 @@ set -e # for arch in arm x86 mips arm64 x86_64 mips64; do TARGET_ARCH_EXT=$arch make -f Makefile_mterp; done -for arch in arm x86; do TARGET_ARCH_EXT=$arch make -f Makefile_mterp; done +for arch in arm x86 arm64 ; do TARGET_ARCH_EXT=$arch make -f Makefile_mterp; done -- 2.11.0