code_generator_mips64.h revision 8c34ec1ede2608eb99a7e26253b6253931dcb7ab
14dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze/*
24dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze * Copyright (C) 2015 The Android Open Source Project
34dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze *
44dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze * Licensed under the Apache License, Version 2.0 (the "License");
54dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze * you may not use this file except in compliance with the License.
64dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze * You may obtain a copy of the License at
74dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze *
84dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze *      http://www.apache.org/licenses/LICENSE-2.0
94dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze *
104dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze * Unless required by applicable law or agreed to in writing, software
114dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze * distributed under the License is distributed on an "AS IS" BASIS,
124dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze * See the License for the specific language governing permissions and
144dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze * limitations under the License.
154dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze */
164dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
174dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS64_H_
184dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS64_H_
194dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
204dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#include "code_generator.h"
214dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#include "dex/compiler_enums.h"
224dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#include "driver/compiler_options.h"
234dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#include "nodes.h"
244dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#include "parallel_move_resolver.h"
254dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#include "utils/mips64/assembler_mips64.h"
264dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
274dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzenamespace art {
284dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzenamespace mips64 {
294dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
304dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze// Use a local definition to prevent copying mistakes.
314dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr size_t kMips64WordSize = kMips64PointerSize;
324dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
334dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
344dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze// InvokeDexCallingConvention registers
354dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
364dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr GpuRegister kParameterCoreRegisters[] =
374dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { A1, A2, A3, A4, A5, A6, A7 };
384dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
394dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
404dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr FpuRegister kParameterFpuRegisters[] =
414dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { F13, F14, F15, F16, F17, F18, F19 };
424dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr size_t kParameterFpuRegistersLength = arraysize(kParameterFpuRegisters);
434dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
444dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
454dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze// InvokeRuntimeCallingConvention registers
464dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
474dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr GpuRegister kRuntimeParameterCoreRegisters[] =
484dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { A0, A1, A2, A3, A4, A5, A6, A7 };
494dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr size_t kRuntimeParameterCoreRegistersLength =
504dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    arraysize(kRuntimeParameterCoreRegisters);
514dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
524dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr FpuRegister kRuntimeParameterFpuRegisters[] =
534dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { F12, F13, F14, F15, F16, F17, F18, F19 };
544dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr size_t kRuntimeParameterFpuRegistersLength =
554dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    arraysize(kRuntimeParameterFpuRegisters);
564dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
574dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
584dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr GpuRegister kCoreCalleeSaves[] =
594dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { S0, S1, S2, S3, S4, S5, S6, S7, GP, S8, RA };  // TODO: review
604dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr FpuRegister kFpuCalleeSaves[] =
614dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { F24, F25, F26, F27, F28, F29, F30, F31 };
624dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
634dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
644dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass CodeGeneratorMIPS64;
654dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
664dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass InvokeDexCallingConvention : public CallingConvention<GpuRegister, FpuRegister> {
674dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
684dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InvokeDexCallingConvention()
694dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze      : CallingConvention(kParameterCoreRegisters,
704dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kParameterCoreRegistersLength,
714dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kParameterFpuRegisters,
724dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kParameterFpuRegistersLength,
734dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kMips64PointerSize) {}
744dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
754dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
764dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
774dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
784dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
794dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass InvokeDexCallingConventionVisitorMIPS64 : public InvokeDexCallingConventionVisitor {
804dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
814dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InvokeDexCallingConventionVisitorMIPS64() {}
824dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  virtual ~InvokeDexCallingConventionVisitorMIPS64() {}
834dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
844dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Location GetNextLocation(Primitive::Type type) OVERRIDE;
854dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Location GetReturnLocation(Primitive::Type type) const OVERRIDE;
864dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Location GetMethodLocation() const OVERRIDE;
874dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
884dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
894dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InvokeDexCallingConvention calling_convention;
904dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
914dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorMIPS64);
924dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
934dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
944dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass InvokeRuntimeCallingConvention : public CallingConvention<GpuRegister, FpuRegister> {
954dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
964dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InvokeRuntimeCallingConvention()
974dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze      : CallingConvention(kRuntimeParameterCoreRegisters,
984dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kRuntimeParameterCoreRegistersLength,
994dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kRuntimeParameterFpuRegisters,
1004dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kRuntimeParameterFpuRegistersLength,
1014dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kMips64PointerSize) {}
1024dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1034dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Location GetReturnLocation(Primitive::Type return_type);
1044dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1054dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
1064dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
1074dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
1084dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
109e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravleclass FieldAccessCallingConventionMIPS64 : public FieldAccessCallingConvention {
110e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle public:
111e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  FieldAccessCallingConventionMIPS64() {}
112e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
113e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetObjectLocation() const OVERRIDE {
114e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return Location::RegisterLocation(A1);
115e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
116e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetFieldIndexLocation() const OVERRIDE {
117e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return Location::RegisterLocation(A0);
118e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
119e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetReturnLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE {
1208c34ec1ede2608eb99a7e26253b6253931dcb7abGoran Jakovljevic    return Location::RegisterLocation(V0);
121e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
122e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetSetValueLocation(
123e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle      Primitive::Type type ATTRIBUTE_UNUSED, bool is_instance) const OVERRIDE {
124e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return is_instance ? Location::RegisterLocation(A2) : Location::RegisterLocation(A1);
125e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
126e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE {
127e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return Location::FpuRegisterLocation(F0);
128e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
129e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
130e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle private:
131e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConventionMIPS64);
132e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle};
133e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
1344dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass ParallelMoveResolverMIPS64 : public ParallelMoveResolverWithSwap {
1354dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
1364dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  ParallelMoveResolverMIPS64(ArenaAllocator* allocator, CodeGeneratorMIPS64* codegen)
1374dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze      : ParallelMoveResolverWithSwap(allocator), codegen_(codegen) {}
1384dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1394dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void EmitMove(size_t index) OVERRIDE;
1404dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void EmitSwap(size_t index) OVERRIDE;
1414dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void SpillScratch(int reg) OVERRIDE;
1424dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void RestoreScratch(int reg) OVERRIDE;
1434dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1444dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void Exchange(int index1, int index2, bool double_slot);
1454dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1464dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Mips64Assembler* GetAssembler() const;
1474dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1484dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
1494dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  CodeGeneratorMIPS64* const codegen_;
1504dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1514dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverMIPS64);
1524dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
1534dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1544dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass SlowPathCodeMIPS64 : public SlowPathCode {
1554dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
1564dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  SlowPathCodeMIPS64() : entry_label_(), exit_label_() {}
1574dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1584dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Label* GetEntryLabel() { return &entry_label_; }
1594dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Label* GetExitLabel() { return &exit_label_; }
1604dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1614dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
1624dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Label entry_label_;
1634dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Label exit_label_;
1644dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1654dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(SlowPathCodeMIPS64);
1664dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
1674dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1684dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass LocationsBuilderMIPS64 : public HGraphVisitor {
1694dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
1704dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  LocationsBuilderMIPS64(HGraph* graph, CodeGeneratorMIPS64* codegen)
1714dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze      : HGraphVisitor(graph), codegen_(codegen) {}
1724dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1734dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#define DECLARE_VISIT_INSTRUCTION(name, super)     \
174f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  void Visit##name(H##name* instr) OVERRIDE;
1754dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
176f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION)
177f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(DECLARE_VISIT_INSTRUCTION)
1784dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1794dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#undef DECLARE_VISIT_INSTRUCTION
1804dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
181f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  void VisitInstruction(HInstruction* instruction) OVERRIDE {
182f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames    LOG(FATAL) << "Unreachable instruction " << instruction->DebugName()
183f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames               << " (id " << instruction->GetId() << ")";
184f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  }
185f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames
1864dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
1874dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleInvoke(HInvoke* invoke);
1884dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleBinaryOp(HBinaryOperation* operation);
1894dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleShift(HBinaryOperation* operation);
1904dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
1914dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
1924dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1934dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InvokeDexCallingConventionVisitorMIPS64 parameter_visitor_;
1944dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1954dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  CodeGeneratorMIPS64* const codegen_;
1964dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1974dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(LocationsBuilderMIPS64);
1984dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
1994dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2004dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass InstructionCodeGeneratorMIPS64 : public HGraphVisitor {
2014dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
2024dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InstructionCodeGeneratorMIPS64(HGraph* graph, CodeGeneratorMIPS64* codegen);
2034dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2044dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#define DECLARE_VISIT_INSTRUCTION(name, super)     \
205f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  void Visit##name(H##name* instr) OVERRIDE;
2064dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
207f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION)
208f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(DECLARE_VISIT_INSTRUCTION)
2094dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2104dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#undef DECLARE_VISIT_INSTRUCTION
2114dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
212f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  void VisitInstruction(HInstruction* instruction) OVERRIDE {
213f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames    LOG(FATAL) << "Unreachable instruction " << instruction->DebugName()
214f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames               << " (id " << instruction->GetId() << ")";
215f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  }
216f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames
2174dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Mips64Assembler* GetAssembler() const { return assembler_; }
2184dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2194dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
2204dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // Generate code for the given suspend check. If not null, `successor`
2214dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // is the block to branch to if the suspend check is not needed, and after
2224dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // the suspend call.
2234dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateClassInitializationCheck(SlowPathCodeMIPS64* slow_path, GpuRegister class_reg);
2244dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateMemoryBarrier(MemBarrierKind kind);
2254dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateSuspendCheck(HSuspendCheck* check, HBasicBlock* successor);
2264dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleBinaryOp(HBinaryOperation* operation);
2274dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleShift(HBinaryOperation* operation);
2284dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
2294dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
2304dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateImplicitNullCheck(HNullCheck* instruction);
2314dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateExplicitNullCheck(HNullCheck* instruction);
2324dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateTestAndBranch(HInstruction* instruction,
2334dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                             Label* true_target,
2344dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                             Label* false_target,
2354dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                             Label* always_true_target);
236fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  void HandleGoto(HInstruction* got, HBasicBlock* successor);
2374dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2384dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Mips64Assembler* const assembler_;
2394dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  CodeGeneratorMIPS64* const codegen_;
2404dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2414dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorMIPS64);
2424dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
2434dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2444dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass CodeGeneratorMIPS64 : public CodeGenerator {
2454dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
2464dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  CodeGeneratorMIPS64(HGraph* graph,
2474dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                      const Mips64InstructionSetFeatures& isa_features,
248ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                      const CompilerOptions& compiler_options,
249ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                      OptimizingCompilerStats* stats = nullptr);
2504dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  virtual ~CodeGeneratorMIPS64() {}
2514dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2524dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateFrameEntry() OVERRIDE;
2534dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateFrameExit() OVERRIDE;
2544dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2554dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void Bind(HBasicBlock* block) OVERRIDE;
2564dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2574dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
2584dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2594dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  size_t GetWordSize() const OVERRIDE { return kMips64WordSize; }
2604dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2614dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  size_t GetFloatingPointSpillSlotSize() const OVERRIDE { return kMips64WordSize; }
2624dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2634dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  uintptr_t GetAddressOf(HBasicBlock* block) const OVERRIDE {
2644dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    return GetLabelOf(block)->Position();
2654dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  }
2664dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2674dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  HGraphVisitor* GetLocationBuilder() OVERRIDE { return &location_builder_; }
2684dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  HGraphVisitor* GetInstructionVisitor() OVERRIDE { return &instruction_visitor_; }
2694dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Mips64Assembler* GetAssembler() OVERRIDE { return &assembler_; }
270eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  const Mips64Assembler& GetAssembler() const OVERRIDE { return assembler_; }
2714dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2724dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void MarkGCCard(GpuRegister object, GpuRegister value);
2734dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2744dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // Register allocation.
2754dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2764dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void SetupBlockedRegisters(bool is_baseline) const OVERRIDE;
2774dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // AllocateFreeRegister() is only used when allocating registers locally
2784dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // during CompileBaseline().
2794dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Location AllocateFreeRegister(Primitive::Type type) const OVERRIDE;
2804dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2814dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
2824dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2834dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id);
2844dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id);
2854dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id);
2864dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id);
2874dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2884dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
2894dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
2904dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2914dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InstructionSet GetInstructionSet() const OVERRIDE { return InstructionSet::kMips64; }
2924dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2934dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  const Mips64InstructionSetFeatures& GetInstructionSetFeatures() const {
2944dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    return isa_features_;
2954dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  }
2964dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2974dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Label* GetLabelOf(HBasicBlock* block) const {
298225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko    return CommonGetLabelOf<Label>(block_labels_, block);
2994dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  }
3004dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3014dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void Initialize() OVERRIDE {
302225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko    block_labels_ = CommonInitializeLabels<Label>();
3034dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  }
3044dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3054dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void Finalize(CodeAllocator* allocator) OVERRIDE;
3064dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3074dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // Code generation helpers.
308e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE;
3094dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
310175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  void MoveConstant(Location destination, int32_t value) OVERRIDE;
311175dc732c80e6f2afd83209348124df349290ba8Calin Juravle
312e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE;
313e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
314e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
3154dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void SwapLocations(Location loc1, Location loc2, Primitive::Type type);
3164dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3174dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // Generate code to invoke a runtime entry point.
318175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  void InvokeRuntime(QuickEntrypointEnum entrypoint,
319175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                     HInstruction* instruction,
320175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                     uint32_t dex_pc,
321175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                     SlowPathCode* slow_path) OVERRIDE;
322175dc732c80e6f2afd83209348124df349290ba8Calin Juravle
3234dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void InvokeRuntime(int32_t offset,
3244dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                     HInstruction* instruction,
3254dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                     uint32_t dex_pc,
3264dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                     SlowPathCode* slow_path);
3274dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3284dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  ParallelMoveResolver* GetMoveResolver() OVERRIDE { return &move_resolver_; }
3294dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3304dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const { return false; }
3314dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
33285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE;
33385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void GenerateVirtualCall(HInvokeVirtual* invoke ATTRIBUTE_UNUSED,
33485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe                           Location temp ATTRIBUTE_UNUSED) OVERRIDE {
33585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    UNIMPLEMENTED(FATAL);
33685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
33785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
33885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED,
33985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe                              Primitive::Type type ATTRIBUTE_UNUSED) OVERRIDE {
34085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    UNIMPLEMENTED(FATAL);
34185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
3424dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3434dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
3444dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // Labels for each block that will be compiled.
345225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko  Label* block_labels_;  // Indexed by block id.
3464dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Label frame_entry_label_;
3474dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  LocationsBuilderMIPS64 location_builder_;
3484dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InstructionCodeGeneratorMIPS64 instruction_visitor_;
3494dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  ParallelMoveResolverMIPS64 move_resolver_;
3504dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Mips64Assembler assembler_;
3514dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  const Mips64InstructionSetFeatures& isa_features_;
3524dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3534dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(CodeGeneratorMIPS64);
3544dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
3554dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3564dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze}  // namespace mips64
3574dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze}  // namespace art
3584dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3594dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS64_H_
360