code_generator_mips64.h revision 3acee732f9475fbfc6b046e0044b764e7ff5ac01
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// InvokeDexCallingConvention registers
314dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
324dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr GpuRegister kParameterCoreRegisters[] =
334dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { A1, A2, A3, A4, A5, A6, A7 };
344dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
354dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
364dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr FpuRegister kParameterFpuRegisters[] =
374dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { F13, F14, F15, F16, F17, F18, F19 };
384dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr size_t kParameterFpuRegistersLength = arraysize(kParameterFpuRegisters);
394dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
404dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
414dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze// InvokeRuntimeCallingConvention registers
424dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
434dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr GpuRegister kRuntimeParameterCoreRegisters[] =
444dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { A0, A1, A2, A3, A4, A5, A6, A7 };
454dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr size_t kRuntimeParameterCoreRegistersLength =
464dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    arraysize(kRuntimeParameterCoreRegisters);
474dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
484dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr FpuRegister kRuntimeParameterFpuRegisters[] =
494dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { F12, F13, F14, F15, F16, F17, F18, F19 };
504dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr size_t kRuntimeParameterFpuRegistersLength =
514dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    arraysize(kRuntimeParameterFpuRegisters);
524dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
534dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
544dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr GpuRegister kCoreCalleeSaves[] =
554dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { S0, S1, S2, S3, S4, S5, S6, S7, GP, S8, RA };  // TODO: review
564dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzestatic constexpr FpuRegister kFpuCalleeSaves[] =
574dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    { F24, F25, F26, F27, F28, F29, F30, F31 };
584dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
594dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
604dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass CodeGeneratorMIPS64;
614dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
624dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass InvokeDexCallingConvention : public CallingConvention<GpuRegister, FpuRegister> {
634dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
644dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InvokeDexCallingConvention()
654dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze      : CallingConvention(kParameterCoreRegisters,
664dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kParameterCoreRegistersLength,
674dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kParameterFpuRegisters,
684dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kParameterFpuRegistersLength,
694dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kMips64PointerSize) {}
704dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
714dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
724dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
734dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
744dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
754dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass InvokeDexCallingConventionVisitorMIPS64 : public InvokeDexCallingConventionVisitor {
764dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
774dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InvokeDexCallingConventionVisitorMIPS64() {}
784dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  virtual ~InvokeDexCallingConventionVisitorMIPS64() {}
794dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
804dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Location GetNextLocation(Primitive::Type type) OVERRIDE;
814dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Location GetReturnLocation(Primitive::Type type) const OVERRIDE;
824dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Location GetMethodLocation() const OVERRIDE;
834dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
844dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
854dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InvokeDexCallingConvention calling_convention;
864dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
874dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorMIPS64);
884dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
894dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
904dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass InvokeRuntimeCallingConvention : public CallingConvention<GpuRegister, FpuRegister> {
914dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
924dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InvokeRuntimeCallingConvention()
934dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze      : CallingConvention(kRuntimeParameterCoreRegisters,
944dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kRuntimeParameterCoreRegistersLength,
954dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kRuntimeParameterFpuRegisters,
964dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kRuntimeParameterFpuRegistersLength,
974dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                          kMips64PointerSize) {}
984dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
994dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Location GetReturnLocation(Primitive::Type return_type);
1004dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1014dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
1024dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
1034dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
1044dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
105e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravleclass FieldAccessCallingConventionMIPS64 : public FieldAccessCallingConvention {
106e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle public:
107e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  FieldAccessCallingConventionMIPS64() {}
108e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
109e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetObjectLocation() const OVERRIDE {
110e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return Location::RegisterLocation(A1);
111e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
112e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetFieldIndexLocation() const OVERRIDE {
113e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return Location::RegisterLocation(A0);
114e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
115e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetReturnLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE {
1168c34ec1ede2608eb99a7e26253b6253931dcb7abGoran Jakovljevic    return Location::RegisterLocation(V0);
117e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
11800580bdbbb119a354c94a9c19928c1dcbd14a8f4Alexey Frunze  Location GetSetValueLocation(Primitive::Type type, bool is_instance) const OVERRIDE {
11900580bdbbb119a354c94a9c19928c1dcbd14a8f4Alexey Frunze    return Primitive::Is64BitType(type)
12000580bdbbb119a354c94a9c19928c1dcbd14a8f4Alexey Frunze        ? Location::RegisterLocation(A2)
12100580bdbbb119a354c94a9c19928c1dcbd14a8f4Alexey Frunze        : (is_instance
12200580bdbbb119a354c94a9c19928c1dcbd14a8f4Alexey Frunze            ? Location::RegisterLocation(A2)
12300580bdbbb119a354c94a9c19928c1dcbd14a8f4Alexey Frunze            : Location::RegisterLocation(A1));
124e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
125e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE {
126e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return Location::FpuRegisterLocation(F0);
127e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
128e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
129e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle private:
130e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConventionMIPS64);
131e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle};
132e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
1334dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass ParallelMoveResolverMIPS64 : public ParallelMoveResolverWithSwap {
1344dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
1354dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  ParallelMoveResolverMIPS64(ArenaAllocator* allocator, CodeGeneratorMIPS64* codegen)
1364dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze      : ParallelMoveResolverWithSwap(allocator), codegen_(codegen) {}
1374dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1384dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void EmitMove(size_t index) OVERRIDE;
1394dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void EmitSwap(size_t index) OVERRIDE;
1404dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void SpillScratch(int reg) OVERRIDE;
1414dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void RestoreScratch(int reg) OVERRIDE;
1424dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1434dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void Exchange(int index1, int index2, bool double_slot);
1444dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1454dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Mips64Assembler* GetAssembler() const;
1464dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1474dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
1484dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  CodeGeneratorMIPS64* const codegen_;
1494dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1504dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverMIPS64);
1514dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
1524dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1534dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass SlowPathCodeMIPS64 : public SlowPathCode {
1544dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
1554dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  SlowPathCodeMIPS64() : entry_label_(), exit_label_() {}
1564dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
157a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  Mips64Label* GetEntryLabel() { return &entry_label_; }
158a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  Mips64Label* GetExitLabel() { return &exit_label_; }
1594dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1604dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
161a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  Mips64Label entry_label_;
162a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  Mips64Label exit_label_;
1634dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1644dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(SlowPathCodeMIPS64);
1654dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
1664dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1674dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass LocationsBuilderMIPS64 : public HGraphVisitor {
1684dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
1694dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  LocationsBuilderMIPS64(HGraph* graph, CodeGeneratorMIPS64* codegen)
1704dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze      : HGraphVisitor(graph), codegen_(codegen) {}
1714dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1724dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#define DECLARE_VISIT_INSTRUCTION(name, super)     \
173f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  void Visit##name(H##name* instr) OVERRIDE;
1744dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
175f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION)
176f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(DECLARE_VISIT_INSTRUCTION)
1774dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
1784dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#undef DECLARE_VISIT_INSTRUCTION
1794dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
180f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  void VisitInstruction(HInstruction* instruction) OVERRIDE {
181f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames    LOG(FATAL) << "Unreachable instruction " << instruction->DebugName()
182f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames               << " (id " << instruction->GetId() << ")";
183f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames  }
184f39e0641a6d1a6561b20f6a130d1e763788cd70bAlexandre Rames
1854dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
1864dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleInvoke(HInvoke* invoke);
1874dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleBinaryOp(HBinaryOperation* operation);
1885f7b58ea1adfc0639dd605b65f59198d3763f801Vladimir Marko  void HandleCondition(HCondition* instruction);
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
20042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bikclass InstructionCodeGeneratorMIPS64 : public InstructionCodeGenerator {
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  void GenerateClassInitializationCheck(SlowPathCodeMIPS64* slow_path, GpuRegister class_reg);
2214dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateMemoryBarrier(MemBarrierKind kind);
2224dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateSuspendCheck(HSuspendCheck* check, HBasicBlock* successor);
2234dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleBinaryOp(HBinaryOperation* operation);
2245f7b58ea1adfc0639dd605b65f59198d3763f801Vladimir Marko  void HandleCondition(HCondition* instruction);
2254dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void HandleShift(HBinaryOperation* operation);
2268ed1826a9da054920f2d39d34dfc7ba43337e4c9Goran Jakovljevic  void HandleFieldSet(HInstruction* instruction,
2278ed1826a9da054920f2d39d34dfc7ba43337e4c9Goran Jakovljevic                      const FieldInfo& field_info,
2288ed1826a9da054920f2d39d34dfc7ba43337e4c9Goran Jakovljevic                      bool value_can_be_null);
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,
2330debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil                             size_t condition_input_index,
234a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze                             Mips64Label* true_target,
235a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze                             Mips64Label* false_target);
236c857c746707dfd45d74b75cb7fa84484ca68cc2aAlexey Frunze  void DivRemOneOrMinusOne(HBinaryOperation* instruction);
237c857c746707dfd45d74b75cb7fa84484ca68cc2aAlexey Frunze  void DivRemByPowerOfTwo(HBinaryOperation* instruction);
238c857c746707dfd45d74b75cb7fa84484ca68cc2aAlexey Frunze  void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction);
239c857c746707dfd45d74b75cb7fa84484ca68cc2aAlexey Frunze  void GenerateDivRemIntegral(HBinaryOperation* instruction);
240299a93993fb8f3efbf0465cf674d80c3bcfdc66cAlexey Frunze  void GenerateIntLongCompare(IfCondition cond, bool is64bit, LocationSummary* locations);
241299a93993fb8f3efbf0465cf674d80c3bcfdc66cAlexey Frunze  void GenerateIntLongCompareAndBranch(IfCondition cond,
242299a93993fb8f3efbf0465cf674d80c3bcfdc66cAlexey Frunze                                       bool is64bit,
243299a93993fb8f3efbf0465cf674d80c3bcfdc66cAlexey Frunze                                       LocationSummary* locations,
244299a93993fb8f3efbf0465cf674d80c3bcfdc66cAlexey Frunze                                       Mips64Label* label);
245299a93993fb8f3efbf0465cf674d80c3bcfdc66cAlexey Frunze  void GenerateFpCompareAndBranch(IfCondition cond,
246299a93993fb8f3efbf0465cf674d80c3bcfdc66cAlexey Frunze                                  bool gt_bias,
247299a93993fb8f3efbf0465cf674d80c3bcfdc66cAlexey Frunze                                  Primitive::Type type,
248299a93993fb8f3efbf0465cf674d80c3bcfdc66cAlexey Frunze                                  LocationSummary* locations,
249299a93993fb8f3efbf0465cf674d80c3bcfdc66cAlexey Frunze                                  Mips64Label* label);
250fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  void HandleGoto(HInstruction* got, HBasicBlock* successor);
2514dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2524dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Mips64Assembler* const assembler_;
2534dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  CodeGeneratorMIPS64* const codegen_;
2544dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2554dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorMIPS64);
2564dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
2574dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2584dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunzeclass CodeGeneratorMIPS64 : public CodeGenerator {
2594dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze public:
2604dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  CodeGeneratorMIPS64(HGraph* graph,
2614dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                      const Mips64InstructionSetFeatures& isa_features,
262ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                      const CompilerOptions& compiler_options,
263ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                      OptimizingCompilerStats* stats = nullptr);
2644dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  virtual ~CodeGeneratorMIPS64() {}
2654dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2664dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateFrameEntry() OVERRIDE;
2674dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void GenerateFrameExit() OVERRIDE;
2684dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2694dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void Bind(HBasicBlock* block) OVERRIDE;
2704dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2714dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
2724dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
273d967266cdfc8011c81ba6e9857a247c4a73bd0fcLazar Trsic  size_t GetWordSize() const OVERRIDE { return kMips64DoublewordSize; }
2744dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
275d967266cdfc8011c81ba6e9857a247c4a73bd0fcLazar Trsic  size_t GetFloatingPointSpillSlotSize() const OVERRIDE { return kMips64DoublewordSize; }
2764dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2774dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  uintptr_t GetAddressOf(HBasicBlock* block) const OVERRIDE {
278a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze    return assembler_.GetLabelLocation(GetLabelOf(block));
2794dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  }
2804dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2814dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  HGraphVisitor* GetLocationBuilder() OVERRIDE { return &location_builder_; }
2824dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  HGraphVisitor* GetInstructionVisitor() OVERRIDE { return &instruction_visitor_; }
2834dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Mips64Assembler* GetAssembler() OVERRIDE { return &assembler_; }
284eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  const Mips64Assembler& GetAssembler() const OVERRIDE { return assembler_; }
2854dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2868ed1826a9da054920f2d39d34dfc7ba43337e4c9Goran Jakovljevic  void MarkGCCard(GpuRegister object, GpuRegister value, bool value_can_be_null);
2874dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2884dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // Register allocation.
2894dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
29058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  void SetupBlockedRegisters() const OVERRIDE;
2914dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2924dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
2934dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2944dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id);
2954dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id);
2964dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id);
2974dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id);
2984dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
2994dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
3004dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
3014dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3024dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InstructionSet GetInstructionSet() const OVERRIDE { return InstructionSet::kMips64; }
3034dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3044dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  const Mips64InstructionSetFeatures& GetInstructionSetFeatures() const {
3054dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze    return isa_features_;
3064dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  }
3074dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
308a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  Mips64Label* GetLabelOf(HBasicBlock* block) const {
309a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze    return CommonGetLabelOf<Mips64Label>(block_labels_, block);
3104dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  }
3114dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3124dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void Initialize() OVERRIDE {
313a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze    block_labels_ = CommonInitializeLabels<Mips64Label>();
3144dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  }
3154dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3164dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void Finalize(CodeAllocator* allocator) OVERRIDE;
3174dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3184dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // Code generation helpers.
319e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE;
3204dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
321175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  void MoveConstant(Location destination, int32_t value) OVERRIDE;
322175dc732c80e6f2afd83209348124df349290ba8Calin Juravle
323e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE;
324e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
325e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
3264dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void SwapLocations(Location loc1, Location loc2, Primitive::Type type);
3274dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3284dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // Generate code to invoke a runtime entry point.
329175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  void InvokeRuntime(QuickEntrypointEnum entrypoint,
330175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                     HInstruction* instruction,
331175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                     uint32_t dex_pc,
332175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                     SlowPathCode* slow_path) OVERRIDE;
333175dc732c80e6f2afd83209348124df349290ba8Calin Juravle
3344dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  void InvokeRuntime(int32_t offset,
3354dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                     HInstruction* instruction,
3364dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                     uint32_t dex_pc,
3374dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze                     SlowPathCode* slow_path);
3384dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3394dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  ParallelMoveResolver* GetMoveResolver() OVERRIDE { return &move_resolver_; }
3404dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3414dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const { return false; }
3424dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
343dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko  // Check if the desired_dispatch_info is supported. If it is, return it,
344dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko  // otherwise return a fall-back info that should be used instead.
345dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko  HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
346dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko      const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
347dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko      MethodReference target_method) OVERRIDE;
348dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko
34985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE;
35053afca191ace3d7447b09097f9ea82a513075c52Alexey Frunze  void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE;
35185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
35285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED,
35385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe                              Primitive::Type type ATTRIBUTE_UNUSED) OVERRIDE {
3543acee732f9475fbfc6b046e0044b764e7ff5ac01Chris Larsen    UNIMPLEMENTED(FATAL) << "Not implemented on MIPS64";
35585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
3564dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3574dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze private:
3584dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  // Labels for each block that will be compiled.
359a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  Mips64Label* block_labels_;  // Indexed by block id.
360a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  Mips64Label frame_entry_label_;
3614dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  LocationsBuilderMIPS64 location_builder_;
3624dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  InstructionCodeGeneratorMIPS64 instruction_visitor_;
3634dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  ParallelMoveResolverMIPS64 move_resolver_;
3644dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  Mips64Assembler assembler_;
3654dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  const Mips64InstructionSetFeatures& isa_features_;
3664dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3674dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze  DISALLOW_COPY_AND_ASSIGN(CodeGeneratorMIPS64);
3684dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze};
3694dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3704dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze}  // namespace mips64
3714dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze}  // namespace art
3724dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze
3734dda3376b71209fae07f5c3c8ac3eb4b54207aa8Alexey Frunze#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS64_H_
374