/*
 * Copyright (C) 2011 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.
 */

#include "jni_internal.h"
#include "mirror/array.h"
#include "oat/utils/arm/assembler_arm.h"
#include "oat/runtime/oat_support_entrypoints.h"
#include "oat/runtime/stub.h"
#include "stack_indirect_reference_table.h"
#include "sirt_ref.h"

#define __ assembler->

namespace art {
namespace arm {

mirror::ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) {
  UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
#if !defined(ART_USE_LLVM_COMPILER)
  // | Out args |
  // | Method*  | <- SP on entry
  // | LR       |    return address into caller
  // | ...      |    callee saves
  // | R3       |    possible argument
  // | R2       |    possible argument
  // | R1       |    possible argument
  // | R0       |    junk on call to UnresolvedDirectMethodTrampolineFromCode, holds result Method*
  // | Method*  |    Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
  // Save callee saves and ready frame for exception delivery
  RegList save = (1 << R1) | (1 << R2) | (1 << R3) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8) |
                 (1 << R10) | (1 << R11) | (1 << LR);
  // TODO: enable when GetCalleeSaveMethod is available at stub generation time
  // DCHECK_EQ(save, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetCoreSpillMask());
  __ PushList(save);
  __ LoadFromOffset(kLoadWord, R12, TR,
                    ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
  __ mov(R2, ShifterOperand(TR));  // Pass Thread::Current() in R2
  __ LoadImmediate(R3, type);
  __ IncreaseFrameSize(8);         // 2 words of space for alignment
  __ mov(R1, ShifterOperand(SP));  // Pass SP
  // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
  __ blx(R12);
  __ mov(R12, ShifterOperand(R0));  // Save code address returned into R12
  // Restore registers which may have been modified by GC, "R0" will hold the Method*
  __ DecreaseFrameSize(4);
  __ PopList((1 << R0) | save);
  __ bx(R12);  // Leaf call to method's code

  __ bkpt(0);
#else // ART_USE_LLVM_COMPILER
  RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
  __ PushList(save);
  __ LoadFromOffset(kLoadWord, R12, TR,
                    ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
  __ mov(R2, ShifterOperand(TR));  // Pass Thread::Current() in R2
  __ LoadImmediate(R3, type);  // Pass is_static
  __ mov(R1, ShifterOperand(SP));  // Pass sp for Method** callee_addr
  __ IncreaseFrameSize(12);         // 3 words of space for alignment
  // Call to unresolved direct method trampoline (callee, callee_addr, Thread*, is_static)
  __ blx(R12);
  __ mov(R12, ShifterOperand(R0));  // Save code address returned into R12
  __ DecreaseFrameSize(12);
  __ PopList(save);
  __ cmp(R12, ShifterOperand(0));
  __ bx(R12, NE);                   // If R12 != 0 tail call method's code

  __ bx(LR);                        // Return to caller to handle exception
#endif // ART_USE_LLVM_COMPILER

  assembler->EmitSlowPaths();
  size_t cs = assembler->CodeSize();
  Thread* self = Thread::Current();
  SirtRef<mirror::ByteArray> resolution_trampoline(self, mirror::ByteArray::Alloc(self, cs));
  CHECK(resolution_trampoline.get() != NULL);
  MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
  assembler->FinalizeInstructions(code);

  return resolution_trampoline.get();
}

typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*);

mirror::ByteArray* CreateAbstractMethodErrorStub() {
  UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
#if !defined(ART_USE_LLVM_COMPILER)
  // Save callee saves and ready frame for exception delivery
  RegList save = (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8) | (1 << R9) |
                 (1 << R10) | (1 << R11) | (1 << LR);
  // TODO: enable when GetCalleeSaveMethod is available at stub generation time
  // DCHECK_EQ(save, Runtime::Current()->GetCalleeSaveMethod(Runtime::kSaveAll)->GetCoreSpillMask());
  __ PushList(save);         // push {r4-r11, lr} - 9 words of callee saves
  // TODO: enable when GetCalleeSaveMethod is available at stub generation time
  // DCHECK_EQ(Runtime::Current()->GetCalleeSaveMethod(Runtime::kSaveAll)->GetFpSpillMask(), 0xFFFFU);
  __ Emit(0xed2d0a20);       // vpush {s0-s31}

  __ IncreaseFrameSize(12);  // 3 words of space, bottom word will hold callee save Method*

  // R0 is the Method* already
  __ mov(R1, ShifterOperand(R9));  // Pass Thread::Current() in R1
  __ mov(R2, ShifterOperand(SP));  // Pass SP in R2
  // Call to throw AbstractMethodError
  __ LoadFromOffset(kLoadWord, R12, TR, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode));
  __ mov(PC, ShifterOperand(R12));  // Leaf call to routine that never returns

  __ bkpt(0);
#else // ART_USE_LLVM_COMPILER
  // R0 is the Method* already
  __ mov(R1, ShifterOperand(R9));  // Pass Thread::Current() in R1
  // Call to throw AbstractMethodError
  __ LoadFromOffset(kLoadWord, R12, TR, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode));
  __ mov(PC, ShifterOperand(R12));  // Leaf call to routine that never returns

  __ bkpt(0);
#endif // ART_USE_LLVM_COMPILER

  assembler->EmitSlowPaths();

  size_t cs = assembler->CodeSize();
  Thread* self = Thread::Current();
  SirtRef<mirror::ByteArray> abstract_stub(self, mirror::ByteArray::Alloc(self, cs));
  CHECK(abstract_stub.get() != NULL);
  MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
  assembler->FinalizeInstructions(code);

  return abstract_stub.get();
}

mirror::ByteArray* CreateJniDlsymLookupStub() {
  UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
  // Build frame and save argument registers and LR.
  RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
  __ PushList(save);
  __ AddConstant(SP, -12);         // Ensure 16-byte alignment
  __ mov(R0, ShifterOperand(R9));  // Pass Thread::Current() in R0
  // Call FindNativeMethod
  __ LoadFromOffset(kLoadWord, R12, TR, ENTRYPOINT_OFFSET(pFindNativeMethod));
  __ blx(R12);
  __ mov(R12, ShifterOperand(R0));  // Save result of FindNativeMethod in R12
  __ AddConstant(SP, 12);           // Restore registers (including outgoing arguments)
  __ PopList(save);
  __ cmp(R12, ShifterOperand(0));
  __ bx(R12, NE);                   // If R12 != 0 tail call into native code
  __ bx(LR);                        // Return to caller to handle exception

  assembler->EmitSlowPaths();

  size_t cs = assembler->CodeSize();
  Thread* self = Thread::Current();
  SirtRef<mirror::ByteArray> jni_stub(self, mirror::ByteArray::Alloc(self, cs));
  CHECK(jni_stub.get() != NULL);
  MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
  assembler->FinalizeInstructions(code);

  return jni_stub.get();
}

} // namespace arm
} // namespace art
