diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 741a608739..24a664b928 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -35,6 +35,7 @@
 #include "cpregs.h"
 #include "translate-a64.h"
 #include "qemu/atomic128.h"
+#include "native/native-defs.h"
 
 static TCGv_i64 cpu_X[32];
 static TCGv_i64 cpu_pc;
@@ -2331,11 +2332,35 @@ static void disas_exc(DisasContext *s, uint32_t insn)
         /* BRK */
         gen_exception_bkpt_insn(s, syn_aa64_bkpt(imm16));
         break;
-    case 2:
+    case 2: /* HLT */
         if (op2_ll != 0) {
             unallocated_encoding(s);
             break;
         }
+        if (native_call_enabled() && (!s->native_call_status)) {
+            s->native_call_status = true;
+            s->native_call_id = imm16;
+            break;
+        } else if (native_call_enabled() && (s->native_call_status)) {
+            TCGv_i64 arg1 = tcg_temp_new_i64();
+            TCGv_i64 arg2 = tcg_temp_new_i64();
+            TCGv_i64 arg3 = tcg_temp_new_i64();
+
+            tcg_gen_mov_i64(arg1, cpu_reg(s, 0));
+            tcg_gen_mov_i64(arg2, cpu_reg(s, 1));
+            tcg_gen_mov_i64(arg3, cpu_reg(s, 2));
+
+            TCGv_i32 abi_map = tcg_constant_i32(imm16);
+            TCGv_i32 func_id = tcg_constant_i32(s->native_call_id);
+            TCGv_i64 res = tcg_temp_new_i64();
+            TCGv_i32 mmu_idx = tcg_constant_i32(MMU_USER_IDX);
+            gen_helper_native_call(res, cpu_env, arg1, arg2, arg3,
+                                    abi_map, func_id, mmu_idx);
+            tcg_gen_mov_i64(cpu_reg(s, 0), res);
+            s->native_call_status = false;
+            s->native_call_id = 0;
+            break;
+        }
         /* HLT. This has two purposes.
          * Architecturally, it is an external halting debug instruction.
          * Since QEMU doesn't implement external debug, we treat this as
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index 7468476724..7b90ce50d0 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -34,7 +34,7 @@
 #include "exec/helper-gen.h"
 #include "exec/log.h"
 #include "cpregs.h"
-
+#include "native/native-defs.h"
 
 #define ENABLE_ARCH_4T    arm_dc_feature(s, ARM_FEATURE_V4T)
 #define ENABLE_ARCH_5     arm_dc_feature(s, ARM_FEATURE_V5)
@@ -58,6 +58,7 @@ TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
 TCGv_i64 cpu_exclusive_addr;
 TCGv_i64 cpu_exclusive_val;
 
+
 #include "exec/gen-icount.h"
 
 static const char * const regnames[] =
@@ -1147,12 +1148,32 @@ static inline void gen_hlt(DisasContext *s, int imm)
      * semihosting, to provide some semblance of security
      * (and for consistency with our 32-bit semihosting).
      */
+    if (native_call_enabled() && (!s->native_call_status)) {
+        s->native_call_status = true;
+        s->native_call_id = imm;
+        return;
+    } else if (native_call_enabled() && (s->native_call_status)) {
+        TCGv_i32 arg1 = load_reg(s, 0);
+        TCGv_i32 arg2 = load_reg(s, 1);
+        TCGv_i32 arg3 = load_reg(s, 2);
+
+        TCGv_i32 abi_map = tcg_constant_i32(imm);
+        TCGv_i32 func_id = tcg_constant_i32(s->native_call_id);
+        TCGv_i32 res = tcg_temp_new_i32();
+        TCGv_i32 mmu_idx = tcg_constant_i32(MMU_USER_IDX);
+        gen_helper_native_call_i32(res, cpu_env, arg1, arg2, arg3,
+                                    abi_map, func_id, mmu_idx);
+
+        store_reg(s, 0, res);
+        s->native_call_status = false;
+        s->native_call_id = 0;
+        return;
+    }
     if (semihosting_enabled(s->current_el == 0) &&
         (imm == (s->thumb ? 0x3c : 0xf000))) {
         gen_exception_internal_insn(s, EXCP_SEMIHOST);
         return;
     }
-
     unallocated_encoding(s);
 }
 
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
index a9d1f4adc2..280f8ba215 100644
--- a/target/arm/tcg/translate.h
+++ b/target/arm/tcg/translate.h
@@ -149,6 +149,12 @@ typedef struct DisasContext {
     int c15_cpar;
     /* TCG op of the current insn_start.  */
     TCGOp *insn_start;
+    /*
+     * Indicate whether the next instruction is a native function call (true)
+     * or not (false).
+     */
+    bool native_call_status;
+    int native_call_id;
 } DisasContext;
 
 typedef struct DisasCompare {
