165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison/* 265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * Copyright (C) 2014 The Android Open Source Project 365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * 465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * Licensed under the Apache License, Version 2.0 (the "License"); 565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * you may not use this file except in compliance with the License. 665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * You may obtain a copy of the License at 765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * 865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * http://www.apache.org/licenses/LICENSE-2.0 965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * 1065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * Unless required by applicable law or agreed to in writing, software 1165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * distributed under the License is distributed on an "AS IS" BASIS, 1265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * See the License for the specific language governing permissions and 1465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * limitations under the License. 1565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison */ 1665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 1765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_ 1865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#define ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_ 1965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 20cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko#include <deque> 217cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe#include <utility> 2265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include <vector> 2365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 24d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko#include "base/arena_containers.h" 2565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include "base/logging.h" 2665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include "constants_arm.h" 2765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include "utils/arm/managed_register_arm.h" 2865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include "utils/arm/assembler_arm.h" 296b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko#include "utils/array_ref.h" 3065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include "offsets.h" 3165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 3265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allisonnamespace art { 3365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allisonnamespace arm { 3465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 3565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allisonclass Thumb2Assembler FINAL : public ArmAssembler { 3665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison public: 37d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko explicit Thumb2Assembler(ArenaAllocator* arena, bool can_relocate_branches = true) 38d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko : ArmAssembler(arena), 39d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko can_relocate_branches_(can_relocate_branches), 408d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray force_32bit_(false), 418d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray it_cond_index_(kNoItCondition), 42cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko next_condition_(AL), 43d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko fixups_(arena->Adapter(kArenaAllocAssembler)), 44d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko fixup_dependents_(arena->Adapter(kArenaAllocAssembler)), 45d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko literals_(arena->Adapter(kArenaAllocAssembler)), 46d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko jump_tables_(arena->Adapter(kArenaAllocAssembler)), 47cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko last_position_adjustment_(0u), 48cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko last_old_position_(0u), 49cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko last_fixup_id_(0u) { 5010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko cfi().DelayEmittingAdvancePCs(); 5165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } 5265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 5365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison virtual ~Thumb2Assembler() { 5465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } 5565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 5665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison bool IsThumb() const OVERRIDE { 5765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison return true; 5865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } 5965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 6065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison bool IsForced32Bit() const { 6165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison return force_32bit_; 6265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } 6365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 64d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray bool CanRelocateBranches() const { 65d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray return can_relocate_branches_; 668d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray } 678d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray 68cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void FinalizeCode() OVERRIDE; 6965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 7065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Data-processing instructions. 7173cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void and_(Register rd, Register rn, const ShifterOperand& so, 7273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 7365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 7473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void eor(Register rd, Register rn, const ShifterOperand& so, 7573cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 7665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 7773cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void sub(Register rd, Register rn, const ShifterOperand& so, 7873cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 7965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 8073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void rsb(Register rd, Register rn, const ShifterOperand& so, 8173cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 8265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 8373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void add(Register rd, Register rn, const ShifterOperand& so, 8473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 8565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 8673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void adc(Register rd, Register rn, const ShifterOperand& so, 8773cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 8865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 8973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void sbc(Register rd, Register rn, const ShifterOperand& so, 9073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 9165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 9273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void rsc(Register rd, Register rn, const ShifterOperand& so, 9373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 9465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 9565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void tst(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 9665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 9765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void teq(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 9865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 9965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 10065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 10165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 10265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 10373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void orr(Register rd, Register rn, const ShifterOperand& so, 10473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 10565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 106d2b4ca2d02c86b1ce1826fd2b35ce6c9c58c1ff1Vladimir Marko virtual void orn(Register rd, Register rn, const ShifterOperand& so, 107d2b4ca2d02c86b1ce1826fd2b35ce6c9c58c1ff1Vladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 108d2b4ca2d02c86b1ce1826fd2b35ce6c9c58c1ff1Vladimir Marko 10973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void mov(Register rd, const ShifterOperand& so, 11073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 11165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 11273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void bic(Register rd, Register rn, const ShifterOperand& so, 11373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 11465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 11573cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void mvn(Register rd, const ShifterOperand& so, 11673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 11765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 11865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Miscellaneous data-processing instructions. 11965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void clz(Register rd, Register rm, Condition cond = AL) OVERRIDE; 12065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void movw(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE; 12165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void movt(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE; 1229ee23f4273efed8d6378f6ad8e63c65e30a17139Scott Wakeling void rbit(Register rd, Register rm, Condition cond = AL) OVERRIDE; 123c257da7b0fb6737f65aba426add8831e45404755Artem Serov void rev(Register rd, Register rm, Condition cond = AL) OVERRIDE; 124c257da7b0fb6737f65aba426add8831e45404755Artem Serov void rev16(Register rd, Register rm, Condition cond = AL) OVERRIDE; 125c257da7b0fb6737f65aba426add8831e45404755Artem Serov void revsh(Register rd, Register rm, Condition cond = AL) OVERRIDE; 12665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 12765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Multiply instructions. 12865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void mul(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE; 12965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void mla(Register rd, Register rn, Register rm, Register ra, 13065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Condition cond = AL) OVERRIDE; 13165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void mls(Register rd, Register rn, Register rm, Register ra, 13265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Condition cond = AL) OVERRIDE; 133c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu void smull(Register rd_lo, Register rd_hi, Register rn, Register rm, 134c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu Condition cond = AL) OVERRIDE; 13565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void umull(Register rd_lo, Register rd_hi, Register rn, Register rm, 13665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Condition cond = AL) OVERRIDE; 13765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 13865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE; 13965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void udiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE; 14065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 141981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain // Bit field extract instructions. 14251d3fc40637fc73d4156ad617cd451b844cbb75eRoland Levillain void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE; 143981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE; 14451d3fc40637fc73d4156ad617cd451b844cbb75eRoland Levillain 14565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Load/store instructions. 14665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void ldr(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 14765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void str(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 14865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 14965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void ldrb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 15065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void strb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 15165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 15265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void ldrh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 15365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void strh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 15465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 15565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void ldrsb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 15665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void ldrsh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 15765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 1584af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // Load/store register dual instructions using registers `rd` and `rd` + 1. 15965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void ldrd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 16065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void strd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 16165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 1624af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // Load/store register dual instructions using registers `rd` and `rd2`. 1634af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // Note that contrary to the ARM A1 encoding, the Thumb-2 T1 encoding 1644af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // does not require `rd` to be even, nor `rd2' to be equal to `rd` + 1. 1654af147eb3296a26eea566f53a7f687194638d46bRoland Levillain void ldrd(Register rd, Register rd2, const Address& ad, Condition cond); 1664af147eb3296a26eea566f53a7f687194638d46bRoland Levillain void strd(Register rd, Register rd2, const Address& ad, Condition cond); 1674af147eb3296a26eea566f53a7f687194638d46bRoland Levillain 1684af147eb3296a26eea566f53a7f687194638d46bRoland Levillain 16965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void ldm(BlockAddressMode am, Register base, 17065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison RegList regs, Condition cond = AL) OVERRIDE; 17165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void stm(BlockAddressMode am, Register base, 17265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison RegList regs, Condition cond = AL) OVERRIDE; 17365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 17465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void ldrex(Register rd, Register rn, Condition cond = AL) OVERRIDE; 17565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void strex(Register rd, Register rt, Register rn, Condition cond = AL) OVERRIDE; 17665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 17765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void ldrex(Register rd, Register rn, uint16_t imm, Condition cond = AL); 17865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void strex(Register rd, Register rt, Register rn, uint16_t imm, Condition cond = AL); 17965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 18052c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE; 18152c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE; 18265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 18365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Miscellaneous instructions. 18465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void clrex(Condition cond = AL) OVERRIDE; 18565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void nop(Condition cond = AL) OVERRIDE; 18665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 18765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void bkpt(uint16_t imm16) OVERRIDE; 18865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void svc(uint32_t imm24) OVERRIDE; 18965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 19065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // If-then 19165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void it(Condition firstcond, ItState i1 = kItOmitted, 19265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison ItState i2 = kItOmitted, ItState i3 = kItOmitted) OVERRIDE; 19365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 19465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void cbz(Register rn, Label* target) OVERRIDE; 19565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void cbnz(Register rn, Label* target) OVERRIDE; 19665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 19765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles). 19865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmovsr(SRegister sn, Register rt, Condition cond = AL) OVERRIDE; 19965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmovrs(Register rt, SRegister sn, Condition cond = AL) OVERRIDE; 20065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) OVERRIDE; 20165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) OVERRIDE; 20265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) OVERRIDE; 20365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) OVERRIDE; 20465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmovs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 20565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmovd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE; 20665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 20765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Returns false if the immediate cannot be encoded. 20865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison bool vmovs(SRegister sd, float s_imm, Condition cond = AL) OVERRIDE; 20965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison bool vmovd(DRegister dd, double d_imm, Condition cond = AL) OVERRIDE; 21065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 21165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vldrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE; 21265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vstrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE; 21365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vldrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE; 21465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vstrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE; 21565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 21665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 21765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 21865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 21965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 22065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 22165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 22265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 22365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 22465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 22565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 22665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 22765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 22865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 22965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vabss(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 23065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vabsd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE; 23165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vnegs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 23265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vnegd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE; 23365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 23465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE; 23565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 23665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE; 23765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE; 23865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 23965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE; 24065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 24165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE; 24265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 24365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE; 24465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 24565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE; 24665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 24765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcmps(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 24865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE; 24965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcmpsz(SRegister sd, Condition cond = AL) OVERRIDE; 25065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vcmpdz(DRegister dd, Condition cond = AL) OVERRIDE; 25165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vmstat(Condition cond = AL) OVERRIDE; // VMRS APSR_nzcv, FPSCR 25265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 25365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vpushs(SRegister reg, int nregs, Condition cond = AL) OVERRIDE; 25465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vpushd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE; 25565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vpops(SRegister reg, int nregs, Condition cond = AL) OVERRIDE; 25665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void vpopd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE; 25765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 25865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Branch instructions. 25965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void b(Label* label, Condition cond = AL); 26065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void bl(Label* label, Condition cond = AL); 26165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void blx(Label* label); 26265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void blx(Register rm, Condition cond = AL) OVERRIDE; 26365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void bx(Register rm, Condition cond = AL) OVERRIDE; 26465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 26573cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, 26673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 26773cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, 26873cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 26973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void Asr(Register rd, Register rm, uint32_t shift_imm, 27073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 27173cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void Ror(Register rd, Register rm, uint32_t shift_imm, 27273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 27373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void Rrx(Register rd, Register rm, 27473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 27573cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko 27673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void Lsl(Register rd, Register rm, Register rn, 27773cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 27873cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void Lsr(Register rd, Register rm, Register rn, 27973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 28073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void Asr(Register rd, Register rm, Register rn, 28173cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 28273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko virtual void Ror(Register rd, Register rm, Register rn, 28373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 28465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 28565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void Push(Register rd, Condition cond = AL) OVERRIDE; 28665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void Pop(Register rd, Condition cond = AL) OVERRIDE; 28765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 28865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void PushList(RegList regs, Condition cond = AL) OVERRIDE; 28965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void PopList(RegList regs, Condition cond = AL) OVERRIDE; 29065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 29165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void Mov(Register rd, Register rm, Condition cond = AL) OVERRIDE; 29265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 29365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void CompareAndBranchIfZero(Register r, Label* label) OVERRIDE; 29465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void CompareAndBranchIfNonZero(Register r, Label* label) OVERRIDE; 29565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 29619a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray // Memory barriers. 29719a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray void dmb(DmbOptions flavor) OVERRIDE; 29819a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray 299cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Get the final position of a label after local fixup based on the old position 300cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // recorded before FinalizeCode(). 301cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t GetAdjustedPosition(uint32_t old_position) OVERRIDE; 302cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 303cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko using ArmAssembler::NewLiteral; // Make the helper template visible. 304cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 305cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Literal* NewLiteral(size_t size, const uint8_t* data) OVERRIDE; 306cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void LoadLiteral(Register rt, Literal* literal) OVERRIDE; 307cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void LoadLiteral(Register rt, Register rt2, Literal* literal) OVERRIDE; 308cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void LoadLiteral(SRegister sd, Literal* literal) OVERRIDE; 309cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void LoadLiteral(DRegister dd, Literal* literal) OVERRIDE; 310cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 31165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Add signed constant value to rd. May clobber IP. 31265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void AddConstant(Register rd, Register rn, int32_t value, 313449b10922daacc880374d7862dbb5977c7657f6dVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE; 31465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 3157cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe void CmpConstant(Register rn, int32_t value, Condition cond = AL) OVERRIDE; 3167cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 31765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Load and Store. May clobber IP. 31865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void LoadImmediate(Register rd, int32_t value, Condition cond = AL) OVERRIDE; 31965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void MarkExceptionHandler(Label* label) OVERRIDE; 32065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void LoadFromOffset(LoadOperandType type, 32165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register reg, 32265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register base, 32365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t offset, 32465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Condition cond = AL) OVERRIDE; 32565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void StoreToOffset(StoreOperandType type, 32665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register reg, 32765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register base, 32865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t offset, 32965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Condition cond = AL) OVERRIDE; 33065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void LoadSFromOffset(SRegister reg, 33165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register base, 33265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t offset, 33365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Condition cond = AL) OVERRIDE; 33465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void StoreSToOffset(SRegister reg, 33565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register base, 33665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t offset, 33765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Condition cond = AL) OVERRIDE; 33865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void LoadDFromOffset(DRegister reg, 33965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register base, 34065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t offset, 34165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Condition cond = AL) OVERRIDE; 34265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void StoreDToOffset(DRegister reg, 34365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register base, 34465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t offset, 34565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Condition cond = AL) OVERRIDE; 34665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 3473bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray bool ShifterOperandCanHold(Register rd, 3483bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray Register rn, 3493bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray Opcode opcode, 3503bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray uint32_t immediate, 351f5c09c3ed5bca4c34d8476dd9ed2714106fafbcfVladimir Marko SetCc set_cc, 3523bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray ShifterOperand* shifter_op) OVERRIDE; 353f5c09c3ed5bca4c34d8476dd9ed2714106fafbcfVladimir Marko using ArmAssembler::ShifterOperandCanHold; // Don't hide the non-virtual override. 3545bd05a5c9492189ec28edaf6396d6a39ddf03367Nicolas Geoffray 3555bd05a5c9492189ec28edaf6396d6a39ddf03367Nicolas Geoffray bool ShifterOperandCanAlwaysHold(uint32_t immediate) OVERRIDE; 3563bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray 35765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 35813735955f39b3b304c37d2b2840663c131262c18Ian Rogers static bool IsInstructionForExceptionHandling(uintptr_t pc); 35965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 36065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Emit data (e.g. encoded instruction or immediate) to the. 36165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // instruction stream. 36265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void Emit32(int32_t value); // Emit a 32 bit instruction in thumb format. 36365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void Emit16(int16_t value); // Emit a 16 bit instruction in little endian format. 36465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void Bind(Label* label) OVERRIDE; 36565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 36665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void MemoryBarrier(ManagedRegister scratch) OVERRIDE; 36765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 36865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Force the assembler to generate 32 bit instructions. 36965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void Force32Bit() { 37065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison force_32bit_ = true; 37165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } 37265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 3737cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Emit an ADR (or a sequence of instructions) to load the jump table address into base_reg. This 3747cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // will generate a fixup. 3757cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe JumpTable* CreateJumpTable(std::vector<Label*>&& labels, Register base_reg) OVERRIDE; 3767cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Emit an ADD PC, X to dispatch a jump-table jump. This will generate a fixup. 3777cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe void EmitJumpTableDispatch(JumpTable* jump_table, Register displacement_reg) OVERRIDE; 3787cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 37965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison private: 380cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko typedef uint16_t FixupId; 381cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 382cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Fixup: branches and literal pool references. 383cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // 384cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // The thumb2 architecture allows branches to be either 16 or 32 bit instructions. This 385cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // depends on both the type of branch and the offset to which it is branching. The 16-bit 386cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // cbz and cbnz instructions may also need to be replaced with a separate 16-bit compare 387cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // instruction and a 16- or 32-bit branch instruction. Load from a literal pool can also be 388cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // 16-bit or 32-bit instruction and, if the method is large, we may need to use a sequence 389cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // of instructions to make up for the limited range of load literal instructions (up to 390cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // 4KiB for the 32-bit variant). When generating code for these insns we don't know the 391cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // size before hand, so we assume it is the smallest available size and determine the final 392cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // code offsets and sizes and emit code in FinalizeCode(). 393cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // 394cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // To handle this, we keep a record of every branch and literal pool load in the program. 395cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // The actual instruction encoding for these is delayed until we know the final size of 396cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // every instruction. When we bind a label to a branch we don't know the final location yet 397cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // as some preceding instructions may need to be expanded, so we record a non-final offset. 398cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // In FinalizeCode(), we expand the sizes of branches and literal loads that are out of 399cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // range. With each expansion, we need to update dependent Fixups, i.e. insntructios with 400cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // target on the other side of the expanded insn, as their offsets change and this may 401cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // trigger further expansion. 402cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // 403cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // All Fixups have a 'fixup id' which is a 16 bit unsigned number used to identify the 404cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Fixup. For each unresolved label we keep a singly-linked list of all Fixups pointing 405cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // to it, using the fixup ids as links. The first link is stored in the label's position 406cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // (the label is linked but not bound), the following links are stored in the code buffer, 407cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // in the placeholder where we will eventually emit the actual code. 408cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 409cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko class Fixup { 410cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko public: 411cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Branch type. 412cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko enum Type : uint8_t { 413cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kConditional, // B<cond>. 414cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kUnconditional, // B. 415cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kUnconditionalLink, // BL. 416cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kUnconditionalLinkX, // BLX. 417cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kCompareAndBranchXZero, // cbz/cbnz. 418cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLoadLiteralNarrow, // Load narrrow integer literal. 419cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLoadLiteralWide, // Load wide integer literal. 4207cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe kLoadLiteralAddr, // Load address of literal (used for jump table). 421cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLoadFPLiteralSingle, // Load FP literal single. 422cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLoadFPLiteralDouble, // Load FP literal double. 423cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko }; 424cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 425cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Calculated size of branch instruction based on type and offset. 426cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko enum Size : uint8_t { 427cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Branch variants. 428cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kBranch16Bit, 429cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kBranch32Bit, 430cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // NOTE: We don't support branches which would require multiple instructions, i.e. 431cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // conditinoal branches beyond +-1MiB and unconditional branches beyond +-16MiB. 432cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 433cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // CBZ/CBNZ variants. 434cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kCbxz16Bit, // CBZ/CBNZ rX, label; X < 8; 7-bit positive offset. 435cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kCbxz32Bit, // CMP rX, #0 + Bcc label; X < 8; 16-bit Bcc; +-8-bit offset. 436cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kCbxz48Bit, // CMP rX, #0 + Bcc label; X < 8; 32-bit Bcc; up to +-1MiB offset. 437cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 438cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Load integer literal variants. 439cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // LDR rX, label; X < 8; 16-bit variant up to 1KiB offset; 2 bytes. 440cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLiteral1KiB, 441cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // LDR rX, label; 32-bit variant up to 4KiB offset; 4 bytes. 442cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLiteral4KiB, 443cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // MOV rX, imm16 + ADD rX, pc + LDR rX, [rX]; X < 8; up to 64KiB offset; 8 bytes. 444cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLiteral64KiB, 445cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // MOV rX, modimm + ADD rX, pc + LDR rX, [rX, #imm12]; up to 1MiB offset; 10 bytes. 446cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLiteral1MiB, 447cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // NOTE: We don't provide the 12-byte version of kLiteralFar below where the LDR is 16-bit. 448cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // MOV rX, imm16 + MOVT rX, imm16 + ADD rX, pc + LDR rX, [rX]; any offset; 14 bytes. 449cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLiteralFar, 450cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 4517cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Load literal base addr. 4527cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // ADR rX, label; X < 8; 8 bit immediate, shifted to 10 bit. 2 bytes. 4537cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe kLiteralAddr1KiB, 4547cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // ADR rX, label; 4KiB offset. 4 bytes. 4557cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe kLiteralAddr4KiB, 4567cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // MOV rX, imm16 + ADD rX, pc; 64KiB offset. 6 bytes. 4577cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe kLiteralAddr64KiB, 4587cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // MOV rX, imm16 + MOVT rX, imm16 + ADD rX, pc; any offset; 10 bytes. 4597cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe kLiteralAddrFar, 4607cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 461cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Load long or FP literal variants. 462cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // VLDR s/dX, label; 32-bit insn, up to 1KiB offset; 4 bytes. 463cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLongOrFPLiteral1KiB, 464cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // MOV ip, modimm + ADD ip, pc + VLDR s/dX, [IP, #imm8*4]; up to 256KiB offset; 10 bytes. 465cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLongOrFPLiteral256KiB, 466cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // MOV ip, imm16 + MOVT ip, imm16 + ADD ip, pc + VLDR s/dX, [IP]; any offset; 14 bytes. 467cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko kLongOrFPLiteralFar, 468cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko }; 469cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 470cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Unresolved branch possibly with a condition. 471cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static Fixup Branch(uint32_t location, Type type, Size size = kBranch16Bit, 472cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Condition cond = AL) { 473cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK(type == kConditional || type == kUnconditional || 474cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko type == kUnconditionalLink || type == kUnconditionalLinkX); 475cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK(size == kBranch16Bit || size == kBranch32Bit); 476cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK(size == kBranch32Bit || (type == kConditional || type == kUnconditional)); 477cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return Fixup(kNoRegister, kNoRegister, kNoSRegister, kNoDRegister, 478cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko cond, type, size, location); 479cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 480cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 481cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Unresolved compare-and-branch instruction with a register and condition (EQ or NE). 482cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static Fixup CompareAndBranch(uint32_t location, Register rn, Condition cond) { 483cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK(cond == EQ || cond == NE); 484cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return Fixup(rn, kNoRegister, kNoSRegister, kNoDRegister, 485cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko cond, kCompareAndBranchXZero, kCbxz16Bit, location); 486cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 487cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 488cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Load narrow literal. 4897cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe static Fixup LoadNarrowLiteral(uint32_t location, Register rt, Size size) { 490cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK(size == kLiteral1KiB || size == kLiteral4KiB || size == kLiteral64KiB || 491cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko size == kLiteral1MiB || size == kLiteralFar); 492cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK(!IsHighRegister(rt) || (size != kLiteral1KiB && size != kLiteral64KiB)); 493cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return Fixup(rt, kNoRegister, kNoSRegister, kNoDRegister, 494cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko AL, kLoadLiteralNarrow, size, location); 495cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 496cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 497cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Load wide literal. 498cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static Fixup LoadWideLiteral(uint32_t location, Register rt, Register rt2, 499cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Size size = kLongOrFPLiteral1KiB) { 500cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral256KiB || 501cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko size == kLongOrFPLiteralFar); 502cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK(!IsHighRegister(rt) || (size != kLiteral1KiB && size != kLiteral64KiB)); 503cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return Fixup(rt, rt2, kNoSRegister, kNoDRegister, 504cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko AL, kLoadLiteralWide, size, location); 505cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 506cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 507cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Load FP single literal. 508cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static Fixup LoadSingleLiteral(uint32_t location, SRegister sd, 509cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Size size = kLongOrFPLiteral1KiB) { 510cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral256KiB || 511cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko size == kLongOrFPLiteralFar); 512cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return Fixup(kNoRegister, kNoRegister, sd, kNoDRegister, 513cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko AL, kLoadFPLiteralSingle, size, location); 514cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 515cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 516cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Load FP double literal. 517cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static Fixup LoadDoubleLiteral(uint32_t location, DRegister dd, 518cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Size size = kLongOrFPLiteral1KiB) { 519cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral256KiB || 520cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko size == kLongOrFPLiteralFar); 521cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return Fixup(kNoRegister, kNoRegister, kNoSRegister, dd, 522cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko AL, kLoadFPLiteralDouble, size, location); 523cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 524cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 5257cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe static Fixup LoadLiteralAddress(uint32_t location, Register rt, Size size) { 5267cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe DCHECK(size == kLiteralAddr1KiB || size == kLiteralAddr4KiB || size == kLiteralAddr64KiB || 5277cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe size == kLiteralAddrFar); 5287cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe DCHECK(!IsHighRegister(rt) || size != kLiteralAddr1KiB); 5297cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe return Fixup(rt, kNoRegister, kNoSRegister, kNoDRegister, 5307cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe AL, kLoadLiteralAddr, size, location); 5317cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 5327cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 533cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Type GetType() const { 534cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return type_; 535cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 536cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 537663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko bool IsLoadLiteral() const { 538663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko return GetType() >= kLoadLiteralNarrow; 539663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko } 540663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko 541f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko // Returns whether the Fixup can expand from the original size. 542f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko bool CanExpand() const { 543f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko switch (GetOriginalSize()) { 544f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko case kBranch32Bit: 545f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko case kCbxz48Bit: 546f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko case kLiteralFar: 547f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko case kLiteralAddrFar: 548f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko case kLongOrFPLiteralFar: 549f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko return false; 550f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko default: 551f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko return true; 552f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko } 553f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko } 554f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko 555cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Size GetOriginalSize() const { 556cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return original_size_; 557cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 558cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 559cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Size GetSize() const { 560cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return size_; 561cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 562cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 563cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t GetOriginalSizeInBytes() const; 564cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 565cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t GetSizeInBytes() const; 566cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 567cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t GetLocation() const { 568cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return location_; 569cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 570cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 571cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t GetAdjustment() const { 572cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return adjustment_; 573cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 574cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 5756b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko // Prepare the assembler->fixup_dependents_ and each Fixup's dependents_start_/count_. 5766b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko static void PrepareDependents(Thumb2Assembler* assembler); 577cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 578d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko ArrayRef<const FixupId> Dependents(const Thumb2Assembler& assembler) const { 579d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko return ArrayRef<const FixupId>(assembler.fixup_dependents_).SubArray(dependents_start_, 580d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko dependents_count_); 581cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 582cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 583cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Resolve a branch when the target is known. 584cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void Resolve(uint32_t target) { 585cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK_EQ(target_, kUnresolved); 586cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK_NE(target, kUnresolved); 587cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko target_ = target; 588cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 589cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 590cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Check if the current size is OK for current location_, target_ and adjustment_. 591cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // If not, increase the size. Return the size increase, 0 if unchanged. 592cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // If the target if after this Fixup, also add the difference to adjustment_, 593cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // so that we don't need to consider forward Fixups as their own dependencies. 594cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t AdjustSizeIfNeeded(uint32_t current_code_size); 595cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 596cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Increase adjustments. This is called for dependents of a Fixup when its size changes. 597cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void IncreaseAdjustment(uint32_t increase) { 598cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko adjustment_ += increase; 599cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 600cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 601cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Finalize the branch with an adjustment to the location. Both location and target are updated. 602cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void Finalize(uint32_t location_adjustment) { 603cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK_NE(target_, kUnresolved); 604cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko location_ += location_adjustment; 605cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko target_ += location_adjustment; 606cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 607cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 608cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Emit the branch instruction into the assembler buffer. This does the 609cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // encoding into the thumb instruction. 610cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void Emit(AssemblerBuffer* buffer, uint32_t code_size) const; 611cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 612cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko private: 613cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Fixup(Register rn, Register rt2, SRegister sd, DRegister dd, 614cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Condition cond, Type type, Size size, uint32_t location) 615cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko : rn_(rn), 616cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko rt2_(rt2), 617cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko sd_(sd), 618cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko dd_(dd), 619cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko cond_(cond), 620cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko type_(type), 621cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko original_size_(size), size_(size), 622cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko location_(location), 623cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko target_(kUnresolved), 624cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko adjustment_(0u), 6256b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko dependents_count_(0u), 6266b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko dependents_start_(0u) { 627cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 628f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko 629cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static size_t SizeInBytes(Size size); 630cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 631cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // The size of padding added before the literal pool. 632cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static size_t LiteralPoolPaddingSize(uint32_t current_code_size); 633cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 634cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Returns the offset from the PC-using insn to the target. 635cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko int32_t GetOffset(uint32_t current_code_size) const; 636cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 637cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko size_t IncreaseSize(Size new_size); 638cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 639cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko int32_t LoadWideOrFpEncoding(Register rbase, int32_t offset) const; 640cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 641f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko template <typename Function> 642f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko static void ForExpandableDependencies(Thumb2Assembler* assembler, Function fn); 643f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko 644cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static constexpr uint32_t kUnresolved = 0xffffffff; // Value for target_ for unresolved. 645cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 646cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko const Register rn_; // Rn for cbnz/cbz, Rt for literal loads. 647cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Register rt2_; // For kLoadLiteralWide. 648cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko SRegister sd_; // For kLoadFPLiteralSingle. 649cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DRegister dd_; // For kLoadFPLiteralDouble. 650cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko const Condition cond_; 651cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko const Type type_; 652cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Size original_size_; 653cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Size size_; 654cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t location_; // Offset into assembler buffer in bytes. 655cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t target_; // Offset into assembler buffer in bytes. 656cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t adjustment_; // The number of extra bytes inserted between location_ and target_. 6576b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko // Fixups that require adjustment when current size changes are stored in a single 6586b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko // array in the assembler and we store only the start index and count here. 6596b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko uint32_t dependents_count_; 6606b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko uint32_t dependents_start_; 661cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko }; 662cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 66365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Emit a single 32 or 16 bit data processing instruction. 66465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void EmitDataProcessing(Condition cond, 6656a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Opcode opcode, 66673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko SetCc set_cc, 6676a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Register rn, 6686a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Register rd, 6696a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers const ShifterOperand& so); 67065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 671c257da7b0fb6737f65aba426add8831e45404755Artem Serov // Emit a single 32 bit miscellaneous instruction. 672c257da7b0fb6737f65aba426add8831e45404755Artem Serov void Emit32Miscellaneous(uint8_t op1, 673c257da7b0fb6737f65aba426add8831e45404755Artem Serov uint8_t op2, 674c257da7b0fb6737f65aba426add8831e45404755Artem Serov uint32_t rest_encoding); 675c257da7b0fb6737f65aba426add8831e45404755Artem Serov 676c257da7b0fb6737f65aba426add8831e45404755Artem Serov // Emit reverse byte instructions: rev, rev16, revsh. 677c257da7b0fb6737f65aba426add8831e45404755Artem Serov void EmitReverseBytes(Register rd, Register rm, uint32_t op); 678c257da7b0fb6737f65aba426add8831e45404755Artem Serov 679c257da7b0fb6737f65aba426add8831e45404755Artem Serov // Emit a single 16 bit miscellaneous instruction. 680c257da7b0fb6737f65aba426add8831e45404755Artem Serov void Emit16Miscellaneous(uint32_t rest_encoding); 681c257da7b0fb6737f65aba426add8831e45404755Artem Serov 68265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Must the instruction be 32 bits or can it possibly be encoded 68365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // in 16 bits? 68465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison bool Is32BitDataProcessing(Condition cond, 6856a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Opcode opcode, 68673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko SetCc set_cc, 6876a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Register rn, 6886a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Register rd, 6896a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers const ShifterOperand& so); 69065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 69165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Emit a 32 bit data processing instruction. 69265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void Emit32BitDataProcessing(Condition cond, 6936a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Opcode opcode, 69473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko SetCc set_cc, 6956a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Register rn, 6966a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Register rd, 6976a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers const ShifterOperand& so); 69865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 69965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Emit a 16 bit data processing instruction. 70065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void Emit16BitDataProcessing(Condition cond, 7016a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Opcode opcode, 70273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko SetCc set_cc, 7036a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Register rn, 7046a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Register rd, 7056a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers const ShifterOperand& so); 70665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 70765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void Emit16BitAddSub(Condition cond, 70865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Opcode opcode, 70973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko SetCc set_cc, 71065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register rn, 71165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register rd, 71265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison const ShifterOperand& so); 71365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 71465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison uint16_t EmitCompareAndBranch(Register rn, uint16_t prev, bool n); 71565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 71665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void EmitLoadStore(Condition cond, 7176a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers bool load, 7186a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers bool byte, 7196a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers bool half, 7206a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers bool is_signed, 7216a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers Register rd, 7226a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers const Address& ad); 72365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 72465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void EmitMemOpAddressMode3(Condition cond, 72565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t mode, 72665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register rd, 72765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison const Address& ad); 72865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 72965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void EmitMultiMemOp(Condition cond, 73065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison BlockAddressMode am, 73165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison bool load, 73265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register base, 73365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison RegList regs); 73465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 73565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void EmitMulOp(Condition cond, 73665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t opcode, 73765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register rd, 73865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register rn, 73965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register rm, 74065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Register rs); 74165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 74265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void EmitVFPsss(Condition cond, 74365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t opcode, 74465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison SRegister sd, 74565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison SRegister sn, 74665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison SRegister sm); 74765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 74865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void EmitVFPddd(Condition cond, 74965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t opcode, 75065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison DRegister dd, 75165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison DRegister dn, 75265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison DRegister dm); 75365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 75465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void EmitVFPsd(Condition cond, 75565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t opcode, 75665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison SRegister sd, 75765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison DRegister dm); 75865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 75965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void EmitVFPds(Condition cond, 76065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison int32_t opcode, 76165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison DRegister dd, 76265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison SRegister sm); 76365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 76465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond); 76565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 766cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void EmitBranch(Condition cond, Label* label, bool link, bool x); 76765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison static int32_t EncodeBranchOffset(int32_t offset, int32_t inst); 76865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison static int DecodeBranchOffset(int32_t inst); 76973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, 77073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare); 77173cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko void EmitShift(Register rd, Register rn, Shift shift, Register rm, 77273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko Condition cond = AL, SetCc set_cc = kCcDontCare); 77365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 7746fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko static int32_t GetAllowedLoadOffsetBits(LoadOperandType type); 7756fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko static int32_t GetAllowedStoreOffsetBits(StoreOperandType type); 7766fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko bool CanSplitLoadStoreOffset(int32_t allowed_offset_bits, 7776fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko int32_t offset, 7786fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko /*out*/ int32_t* add_to_base, 7796fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko /*out*/ int32_t* offset_for_load_store); 7806fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko int32_t AdjustLoadStoreOffset(int32_t allowed_offset_bits, 7816fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko Register temp, 7826fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko Register base, 7836fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko int32_t offset, 7846fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko Condition cond); 7856fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko 786d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray // Whether the assembler can relocate branches. If false, unresolved branches will be 787d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray // emitted on 32bits. 788d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray bool can_relocate_branches_; 789d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray 790d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray // Force the assembler to use 32 bit thumb2 instructions. 791d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray bool force_32bit_; 79265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 79365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // IfThen conditions. Used to check that conditional instructions match the preceding IT. 79465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Condition it_conditions_[4]; 79565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison uint8_t it_cond_index_; 79665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison Condition next_condition_; 79765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 79865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void SetItCondition(ItState s, Condition cond, uint8_t index); 79965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 80065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void CheckCondition(Condition cond) { 80165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison CHECK_EQ(cond, next_condition_); 80265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 80365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Move to the next condition if there is one. 80465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison if (it_cond_index_ < 3) { 80565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison ++it_cond_index_; 80665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison next_condition_ = it_conditions_[it_cond_index_]; 80765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } else { 80865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison next_condition_ = AL; 80965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } 81065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } 81165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 81265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison void CheckConditionLastIt(Condition cond) { 81365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison if (it_cond_index_ < 3) { 81465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // Check that the next condition is AL. This means that the 81565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison // current condition is the last in the IT block. 81665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison CHECK_EQ(it_conditions_[it_cond_index_ + 1], AL); 81765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } 81865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison CheckCondition(cond); 81965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } 82065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 821cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko FixupId AddFixup(Fixup fixup) { 822cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko FixupId fixup_id = static_cast<FixupId>(fixups_.size()); 823cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko fixups_.push_back(fixup); 824cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // For iterating using FixupId, we need the next id to be representable. 825cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK_EQ(static_cast<size_t>(static_cast<FixupId>(fixups_.size())), fixups_.size()); 826cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return fixup_id; 82765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } 82865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 829cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Fixup* GetFixup(FixupId fixup_id) { 830cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DCHECK_LT(fixup_id, fixups_.size()); 831cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return &fixups_[fixup_id]; 83265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison } 83365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 834cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void BindLabel(Label* label, uint32_t bound_pc); 8357cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe uint32_t BindLiterals(); 8367cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe void BindJumpTables(uint32_t code_size); 837cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void AdjustFixupIfNeeded(Fixup* fixup, uint32_t* current_code_size, 838cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::deque<FixupId>* fixups_to_recalculate); 839cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t AdjustFixups(); 840cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void EmitFixups(uint32_t adjusted_code_size); 841cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko void EmitLiterals(); 8427cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe void EmitJumpTables(); 84310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko void PatchCFI(); 844cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 845cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int16_t BEncoding16(int32_t offset, Condition cond); 846cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int32_t BEncoding32(int32_t offset, Condition cond); 847cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int16_t CbxzEncoding16(Register rn, int32_t offset, Condition cond); 848cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int16_t CmpRnImm8Encoding16(Register rn, int32_t value); 849cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int16_t AddRdnRmEncoding16(Register rdn, Register rm); 850cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int32_t MovwEncoding32(Register rd, int32_t value); 851cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int32_t MovtEncoding32(Register rd, int32_t value); 852cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int32_t MovModImmEncoding32(Register rd, int32_t value); 853cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int16_t LdrLitEncoding16(Register rt, int32_t offset); 854cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int32_t LdrLitEncoding32(Register rt, int32_t offset); 855cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int32_t LdrdEncoding32(Register rt, Register rt2, Register rn, int32_t offset); 856cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int32_t VldrsEncoding32(SRegister sd, Register rn, int32_t offset); 857cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int32_t VldrdEncoding32(DRegister dd, Register rn, int32_t offset); 858cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int16_t LdrRtRnImm5Encoding16(Register rt, Register rn, int32_t offset); 859cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko static int32_t LdrRtRnImm12Encoding(Register rt, Register rn, int32_t offset); 8607cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe static int16_t AdrEncoding16(Register rd, int32_t offset); 8617cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe static int32_t AdrEncoding32(Register rd, int32_t offset); 862cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 863d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko ArenaVector<Fixup> fixups_; 864d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko ArenaVector<FixupId> fixup_dependents_; 865cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 866cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Use std::deque<> for literal labels to allow insertions at the end 867cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // without invalidating pointers and references to existing elements. 868d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko ArenaDeque<Literal> literals_; 869cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 8707cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Jump table list. 871d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko ArenaDeque<JumpTable> jump_tables_; 8727cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 873cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // Data for AdjustedPosition(), see the description there. 874cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t last_position_adjustment_; 875cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko uint32_t last_old_position_; 876cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko FixupId last_fixup_id_; 87765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison}; 87865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 87965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison} // namespace arm 88065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison} // namespace art 88165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison 88265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_ 883