/*
 * 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 "stubs/stubs.h"

#include "entrypoints/quick/quick_entrypoints.h"
#include "jni_internal.h"
#include "utils/arm/assembler_arm.h"
#include "utils/mips/assembler_mips.h"
#include "utils/x86/assembler_x86.h"
#include "stack_indirect_reference_table.h"
#include "sirt_ref.h"

#define __ assembler->

namespace art {

namespace arm {
const std::vector<uint8_t>* CreatePortableResolutionTrampoline() {
  UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
  RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);

  __ PushList(save);
  __ LoadFromOffset(kLoadWord, R12, TR,
                    PORTABLE_ENTRYPOINT_OFFSET(pPortableResolutionTrampolineFromCode));
  __ mov(R3, ShifterOperand(TR));  // Pass Thread::Current() in R3
  __ mov(R2, ShifterOperand(SP));  // Pass sp for Method** callee_addr
  __ IncreaseFrameSize(12);         // 3 words of space for alignment
  // Call to resolution trampoline (callee, receiver, callee_addr, Thread*)
  __ 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

  assembler->EmitSlowPaths();
  size_t cs = assembler->CodeSize();
  UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
  MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
  assembler->FinalizeInstructions(code);

  return resolution_trampoline.release();
}
}  // namespace arm

namespace mips {
const std::vector<uint8_t>* CreatePortableResolutionTrampoline() {
  UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
  // Build frame and save argument registers and RA.
  __ AddConstant(SP, SP, -32);
  __ StoreToOffset(kStoreWord, RA, SP, 28);
  __ StoreToOffset(kStoreWord, A3, SP, 12);
  __ StoreToOffset(kStoreWord, A2, SP, 8);
  __ StoreToOffset(kStoreWord, A1, SP, 4);
  __ StoreToOffset(kStoreWord, A0, SP, 0);

  __ LoadFromOffset(kLoadWord, T9, S1,
                    PORTABLE_ENTRYPOINT_OFFSET(pPortableResolutionTrampolineFromCode));
  __ Move(A3, S1);  // Pass Thread::Current() in A3
  __ Move(A2, SP);  // Pass SP for Method** callee_addr
  __ Jalr(T9);  // Call to resolution trampoline (callee, receiver, callee_addr, Thread*)

  // Restore frame, argument registers, and RA.
  __ LoadFromOffset(kLoadWord, A0, SP, 0);
  __ LoadFromOffset(kLoadWord, A1, SP, 4);
  __ LoadFromOffset(kLoadWord, A2, SP, 8);
  __ LoadFromOffset(kLoadWord, A3, SP, 12);
  __ LoadFromOffset(kLoadWord, RA, SP, 28);
  __ AddConstant(SP, SP, 32);

  Label resolve_fail;
  __ EmitBranch(V0, ZERO, &resolve_fail, true);
  __ Jr(V0);  // If V0 != 0 tail call method's code
  __ Bind(&resolve_fail, false);
  __ Jr(RA);  // Return to caller to handle exception

  assembler->EmitSlowPaths();
  size_t cs = assembler->CodeSize();
  UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
  MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
  assembler->FinalizeInstructions(code);

  return resolution_trampoline.release();
}
}  // namespace mips

namespace x86 {
const std::vector<uint8_t>* CreatePortableResolutionTrampoline() {
  UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));

  __ pushl(EBP);
  __ movl(EBP, ESP);          // save ESP
  __ subl(ESP, Immediate(8));  // Align stack
  __ movl(EAX, Address(EBP, 8));  // Method* called
  __ leal(EDX, Address(EBP, 8));  // Method** called_addr
  __ fs()->pushl(Address::Absolute(Thread::SelfOffset()));  // pass thread
  __ pushl(EDX);  // pass called_addr
  __ pushl(ECX);  // pass receiver
  __ pushl(EAX);  // pass called
  // Call to resolve method.
  __ Call(ThreadOffset(PORTABLE_ENTRYPOINT_OFFSET(pPortableResolutionTrampolineFromCode)),
          X86ManagedRegister::FromCpuRegister(ECX));
  __ leave();

  Label resolve_fail;  // forward declaration
  __ cmpl(EAX, Immediate(0));
  __ j(kEqual, &resolve_fail);
  __ jmp(EAX);
  // Tail call to intended method.
  __ Bind(&resolve_fail);
  __ ret();

  assembler->EmitSlowPaths();
  size_t cs = assembler->CodeSize();
  UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
  MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
  assembler->FinalizeInstructions(code);

  return resolution_trampoline.release();
}
}  // namespace x86

}  // namespace art
