--- /dev/null 2018-09-25 19:24:10.000000000 +0300 +++ new/src/hotspot/cpu/aarch32/assembler_aarch32.cpp 2018-09-25 19:24:09.000000000 +0300 @@ -0,0 +1,2149 @@ +/* + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 2015, Linaro Ltd. All rights reserved. + * Copyright (c) 2015-2018, Azul Systems, Inc. All rights reserved. + * reserved. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE + * HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include +#include + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" +#include "compiler/disassembler.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "register_aarch32.hpp" +#include "vm_version_aarch32.hpp" + +extern "C" void entry(CodeBuffer *cb); + +#define __ _masm. +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#else +#define BLOCK_COMMENT(str) block_comment(str) +#endif + +#define BIND(label) bind(label); __ BLOCK_COMMENT(#label ":") + +void entry(CodeBuffer *cb) { + + // { + // for (int i = 0; i < 256; i+=16) + // { + // printf("\"%20.20g\", ", unpack(i)); + // printf("\"%20.20g\", ", unpack(i+1)); + // } + // printf("\n"); + // } + +#if defined(ASSERT) && !defined (__SOFTFP__) + Assembler _masm(cb); + address entry = __ pc(); + + // Smoke test for assembler + + // we're checking the code generation, not applicability of the code to the actual target + // so temporarily override the detected cpu to allow emission of all instructions + const ProcessorFeatures detected_features = VM_Version::features(); + VM_Version::features(FT_ALL); + +// BEGIN Generated code -- do not edit +// Generated by aarch32-asmtest.py + Label back, forth, near, near_post, near_flt, near_post_flt; + __ bind(back); + +// ThreeRegSft + __ add(r8, r2, r11, ::lsr(10)); // add r8, r2, r11, lsr #10 + __ adds(r1, r3, r7, ::asr(1), Assembler::EQ); // addEQs r1, r3, r7, asr #1 + __ eor(r0, r9, r4, ::lsl(5)); // eor r0, r9, r4, lsl #5 + __ eors(r9, r2, r6, ::rrx(), Assembler::GT); // eorGTs r9, r2, r6, rrx + __ sub(r0, r12, lr, ::lsr(0), Assembler::GT); // subGT r0, r12, lr, lsr #0 + __ subs(r8, r2, r4, ::ror(6), Assembler::EQ); // subEQs r8, r2, r4, ror #6 + __ rsb(r8, r9, sp, ::lsl(3)); // rsb r8, r9, sp, lsl #3 + __ rsbs(r8, r0, r4, ::ror(16), Assembler::VS); // rsbVSs r8, r0, r4, ror #16 + __ add(r9, r5, r1, ::lsr(15), Assembler::LE); // addLE r9, r5, r1, lsr #15 + __ adds(r1, sp, r6, ::asr(5)); // adds r1, sp, r6, asr #5 + __ adc(r11, sp, r7, ::asr(1), Assembler::GT); // adcGT r11, sp, r7, asr #1 + __ adcs(r0, r8, r9, ::lsr(6)); // adcs r0, r8, r9, lsr #6 + __ sbc(r9, r3, r6, ::ror(5)); // sbc r9, r3, r6, ror #5 + __ sbcs(r1, sp, r5, ::asr(16), Assembler::HI); // sbcHIs r1, sp, r5, asr #16 + __ rsc(r8, r2, r6, ::lsl(9), Assembler::CC); // rscCC r8, r2, r6, lsl #9 + __ rscs(r10, r4, sp, ::ror(14)); // rscs r10, r4, sp, ror #14 + __ orr(r11, sp, r5, ::lsl(15), Assembler::NE); // orrNE r11, sp, r5, lsl #15 + __ orrs(r9, r10, r4, ::ror(14)); // orrs r9, r10, r4, ror #14 + __ bic(r9, sp, r5, ::ror(1)); // bic r9, sp, r5, ror #1 + __ bics(r0, r2, r7, ::asr(10)); // bics r0, r2, r7, asr #10 + +// ThreeRegRSR + __ add(sp, r6, r7, ::ror(r7)); // add sp, r6, r7, ror r7 + __ adds(r4, r12, r6, ::ror(r7), Assembler::HI); // addHIs r4, r12, r6, ror r7 + __ eor(r5, r6, r7, ::asr(r12), Assembler::LS); // eorLS r5, r6, r7, asr r12 + __ eors(r8, r5, sp, ::lsl(r4), Assembler::AL); // eorALs r8, r5, sp, lsl r4 + __ sub(r2, r12, r5, ::asr(r0)); // sub r2, r12, r5, asr r0 + __ subs(r9, r3, r7, ::lsl(r12), Assembler::HS); // subHSs r9, r3, r7, lsl r12 + __ rsb(r9, r12, r4, ::lsl(r6), Assembler::GT); // rsbGT r9, r12, r4, lsl r6 + __ rsbs(r8, r2, r12, ::lsl(r1)); // rsbs r8, r2, r12, lsl r1 + __ add(r4, r12, sp, ::lsl(sp)); // add r4, r12, sp, lsl sp + __ adds(r8, r11, r6, ::ror(sp)); // adds r8, r11, r6, ror sp + __ adc(r0, r2, r5, ::lsl(r4), Assembler::NE); // adcNE r0, r2, r5, lsl r4 + __ adcs(r11, lr, r6, ::asr(r2)); // adcs r11, lr, r6, asr r2 + __ sbc(r8, r10, lr, ::asr(r3), Assembler::HI); // sbcHI r8, r10, lr, asr r3 + __ sbcs(r1, r12, r5, ::lsl(r6)); // sbcs r1, r12, r5, lsl r6 + __ rsc(r4, r5, lr, ::ror(r10), Assembler::VS); // rscVS r4, r5, lr, ror r10 + __ rscs(r1, r12, sp, ::lsl(r8)); // rscs r1, r12, sp, lsl r8 + __ orr(r8, r1, r6, ::ror(r0), Assembler::VS); // orrVS r8, r1, r6, ror r0 + __ orrs(r11, sp, r7, ::ror(r5)); // orrs r11, sp, r7, ror r5 + __ bic(r4, lr, r6, ::lsl(r2), Assembler::AL); // bicAL r4, lr, r6, lsl r2 + __ bics(r10, r11, sp, ::lsl(r3)); // bics r10, r11, sp, lsl r3 + +// TwoRegImm + __ add(r8, sp, (unsigned)268435462U, Assembler::HI); // addHI r8, sp, #268435462 + __ adds(sp, lr, (unsigned)162529280U); // adds sp, lr, #162529280 + __ eor(lr, r6, (unsigned)8192000U); // eor lr, r6, #8192000 + __ eors(r2, r3, (unsigned)292U); // eors r2, r3, #292 + __ sub(r4, sp, (unsigned)227540992U); // sub r4, sp, #227540992 + __ subs(r1, lr, (unsigned)33554432U, Assembler::LT); // subLTs r1, lr, #33554432 + __ rsb(r0, r5, (unsigned)2483027968U); // rsb r0, r5, #2483027968 + __ rsbs(r8, r4, (unsigned)3080192U, Assembler::LO); // rsbLOs r8, r4, #3080192 + __ add(r9, r4, (unsigned)2147483648U, Assembler::LT); // addLT r9, r4, #2147483648 + __ adds(r8, r4, (unsigned)32768U, Assembler::AL); // addALs r8, r4, #32768 + __ adc(r10, lr, (unsigned)10752U, Assembler::CS); // adcCS r10, lr, #10752 + __ adcs(r10, r6, (unsigned)774144U); // adcs r10, r6, #774144 + __ sbc(r2, r12, (unsigned)637534208U); // sbc r2, r12, #637534208 + __ sbcs(r8, r10, (unsigned)692060160U); // sbcs r8, r10, #692060160 + __ rsc(sp, r6, (unsigned)7405568U); // rsc sp, r6, #7405568 + __ rscs(r10, r11, (unsigned)244318208U, Assembler::NE); // rscNEs r10, r11, #244318208 + __ orr(r3, r7, (unsigned)66846720U, Assembler::VS); // orrVS r3, r7, #66846720 + __ orrs(r2, r5, (unsigned)1327104U, Assembler::EQ); // orrEQs r2, r5, #1327104 + __ bic(r8, r1, (unsigned)3744U, Assembler::VS); // bicVS r8, r1, #3744 + __ bics(r0, r2, (unsigned)2684354560U, Assembler::LO); // bicLOs r0, r2, #2684354560 + +// TwoRegSft + __ tst(r8, sp, ::lsl(5)); // tst r8, sp, lsl #5 + __ teq(r6, r7, ::lsr(3)); // teq r6, r7, lsr #3 + __ cmp(r12, r4, ::ror(2)); // cmp r12, r4, ror #2 + __ cmn(r5, r7, ::lsl(16), Assembler::LT); // cmnLT r5, r7, lsl #16 + +// TwoRegRSR + __ tst(r2, lr, ::lsr(r7)); // tst r2, lr, lsr r7 + __ teq(r0, r2, ::ror(r5), Assembler::CC); // teqCC r0, r2, ror r5 + __ cmp(lr, r7, ::lsr(r11), Assembler::LS); // cmpLS lr, r7, lsr r11 + __ cmn(r10, r7, ::lsl(r11), Assembler::VS); // cmnVS r10, r7, lsl r11 + +// OneRegImm + __ tst(r2, (unsigned)557842432U); // tst r2, #557842432 + __ teq(lr, (unsigned)7077888U, Assembler::MI); // teqMI lr, #7077888 + __ cmp(r5, (unsigned)939524096U); // cmp r5, #939524096 + __ cmn(r7, (unsigned)2147483650U, Assembler::LO); // cmnLO r7, #2147483650 + +// Shift op + __ lsl(r0, r4, (unsigned)23U); // lsl r0, r4, #23 + __ lsls(r1, r4, (unsigned)9U); // lsls r1, r4, #9 + __ lsr(r0, r10, (unsigned)3U); // lsr r0, r10, #3 + __ lsrs(r0, r10, (unsigned)20U); // lsrs r0, r10, #20 + __ asr(r1, r9, (unsigned)11U); // asr r1, r9, #11 + __ asrs(r2, r11, (unsigned)10U, Assembler::VS); // asrVSs r2, r11, #10 + +// shift op + __ ror(r8, r2, (unsigned)31U, Assembler::CC); // rorCC r8, r2, #31 + __ rors(r9, r12, (unsigned)8U); // rors r9, r12, #8 + +// ThreeRegNon + __ ror(r8, lr, r7); // ror r8, lr, r7 + __ rors(r12, r3, r4); // rors r12, r3, r4 + __ lsl(r12, sp, lr, Assembler::GT); // lslGT r12, sp, lr + __ lsls(r12, sp, r6, Assembler::AL); // lslALs r12, sp, r6 + __ lsr(r0, r1, r9, Assembler::GT); // lsrGT r0, r1, r9 + __ lsrs(r11, r3, r12, Assembler::GT); // lsrGTs r11, r3, r12 + __ asr(r2, r12, r6, Assembler::LE); // asrLE r2, r12, r6 + __ asrs(r1, r10, r6, Assembler::LT); // asrLTs r1, r10, r6 + +// TwoRegNon + __ mov(r10, r3); // mov r10, r3 + __ movs(r0, r9); // movs r0, r9 + +// OneRegImm + __ mov_i(r3, (unsigned)656U, Assembler::VC); // movVC r3, #656 + __ movs_i(r4, (unsigned)2064384U); // movs r4, #2064384 + +// TwoRegSft + __ mov(r12, r6, ::lsr(3)); // mov r12, r6, lsr #3 + __ movs(r5, sp, ::asr(10), Assembler::VC); // movVCs r5, sp, asr #10 + +// TwoRegRSR + __ mov(r1, lr, ::ror(r3)); // mov r1, lr, ror r3 + __ movs(r8, r12, ::ror(r9), Assembler::EQ); // movEQs r8, r12, ror r9 + +// OneRegImm16 + __ movw_i(r11, (unsigned)53041U, Assembler::LO); // movwLO r11, #53041 + __ movt_i(r9, (unsigned)11255U, Assembler::LO); // movtLO r9, #11255 + +// ThreeRegNon + __ mul(r1, sp, r5, Assembler::LE); // mulLE r1, sp, r5 + __ muls(r0, r10, r11); // muls r0, r10, r11 + +// FourRegNon + __ mla(r0, r3, r12, r7); // mla r0, r3, r12, r7 + __ mlas(r8, r11, r3, r6, Assembler::EQ); // mlaEQs r8, r11, r3, r6 + __ umull(lr, r4, r5, r6); // umull lr, r4, r5, r6 + __ umulls(r0, r4, r6, r7); // umulls r0, r4, r6, r7 + __ umlal(r8, r0, r11, lr); // umlal r8, r0, r11, lr + __ umlals(r11, r4, lr, r7); // umlals r11, r4, lr, r7 + __ smull(r1, r5, r6, r7, Assembler::HS); // smullHS r1, r5, r6, r7 + __ smulls(r0, r11, r12, r5, Assembler::MI); // smullMIs r0, r11, r12, r5 + +// FourRegNon + __ umaal(r8, r9, r2, r5); // umaal r8, r9, r2, r5 + __ mls(r0, r4, sp, lr, Assembler::EQ); // mlsEQ r0, r4, sp, lr + +// ThreeRegNon + __ qadd(r9, r4, sp, Assembler::PL); // qaddPL r9, r4, sp + __ qsub(r0, r12, r5, Assembler::MI); // qsubMI r0, r12, r5 + __ qdadd(r3, r5, r7); // qdadd r3, r5, r7 + __ qdsub(r9, r2, r4); // qdsub r9, r2, r4 + +// FourRegNon + __ smlabb(r1, r12, r5, r6); // smlabb r1, r12, r5, r6 + __ smlabt(r0, r10, r12, r6); // smlabt r0, r10, r12, r6 + __ smlatb(r8, r1, r3, lr); // smlatb r8, r1, r3, lr + __ smlatt(r1, sp, r6, r7); // smlatt r1, sp, r6, r7 + __ smlawb(r0, r3, r4, r6); // smlawb r0, r3, r4, r6 + __ smlawt(r11, r4, lr, r7); // smlawt r11, r4, lr, r7 + __ smlalbb(r0, r10, r6, r7); // smlalbb r0, r10, r6, r7 + __ smlalbt(r3, r11, r4, lr, Assembler::LS); // smlalbtLS r3, r11, r4, lr + __ smlaltb(r8, r11, r3, r12); // smlaltb r8, r11, r3, r12 + __ smlaltt(r8, r1, r3, r5); // smlaltt r8, r1, r3, r5 + +// ThreeRegNon + __ smulwb(r2, r12, sp, Assembler::HS); // smulwbHS r2, r12, sp + __ smulwt(r8, r12, r6); // smulwt r8, r12, r6 + __ smulbb(r2, r6, lr, Assembler::GE); // smulbbGE r2, r6, lr + __ smulbt(r8, r12, r7); // smulbt r8, r12, r7 + __ smultb(r10, r3, lr, Assembler::EQ); // smultbEQ r10, r3, lr + __ smultt(r0, r3, sp); // smultt r0, r3, sp + +// MemoryOp + __ ldr(r10, Address(r7, r9, lsl(), Address::ADD, Address::post)); // ldr r10, [r7], r9 + __ ldrb(r0, Address(r9, 196)); // ldrb r0, [r9, #196] + __ ldrh(lr, Address(r4, r6, lsl(), Address::ADD, Address::pre)); // ldrh lr, [r4, r6]! + __ ldrsb(r6, Address(__ pre(r9, 232))); // ldrsb r6, [r9, #232]! + __ ldrsh(r2, Address(r1, r1, lsl(), Address::ADD, Address::post)); // ldrsh r2, [r1], r1 + __ str(r0, Address(r9, r4, lsl(), Address::ADD, Address::post)); // str r0, [r9], r4 + __ strb(r3, Address(__ pre(r5, 92))); // strb r3, [r5, #92]! + __ strh(r2, Address(r8, 160)); // strh r2, [r8, #160] + +// MemoryOp + __ ldr(r8, Address(r12, r8, lsl(), Address::ADD, Address::off)); // ldr r8, [r12, r8] + __ ldrb(r11, Address(__ post(r10, 16))); // ldrb r11, [r10], #16 + __ ldrh(r11, Address(r10, r6, lsl(), Address::ADD, Address::off)); // ldrh r11, [r10, r6] + __ ldrsb(r5, Address(r11, r10, lsl(), Address::ADD, Address::pre)); // ldrsb r5, [r11, r10]! + __ ldrsh(r6, Address(r3, r7, lsl(), Address::ADD, Address::off)); // ldrsh r6, [r3, r7] + __ str(r7, Address(sp, r5, lsl(), Address::ADD, Address::pre)); // str r7, [sp, r5]! + __ strb(r2, Address(r10)); // strb r2, [r10] + __ strh(r6, Address(r4, r3, lsl(), Address::ADD, Address::post)); // strh r6, [r4], r3 + +// MemoryOp + __ ldr(r10, Address(r12)); // ldr r10, [r12] + __ ldrb(r4, Address(__ post(r11, 132))); // ldrb r4, [r11], #132 + __ ldrh(r9, Address(r9, r12, lsl(), Address::ADD, Address::post)); // ldrh r9, [r9], r12 + __ ldrsb(r9, Address(__ post(r3, 148))); // ldrsb r9, [r3], #148 + __ ldrsh(r11, Address(__ pre(r2, 148))); // ldrsh r11, [r2, #148]! + __ str(r11, Address(sp, r11, lsl(), Address::ADD, Address::off)); // str r11, [sp, r11] + __ strb(r1, Address(sp, r10, lsl(), Address::ADD, Address::off)); // strb r1, [sp, r10] + __ strh(r10, Address(lr, r9, lsl(), Address::ADD, Address::post)); // strh r10, [lr], r9 + +// MemoryOp + __ ldr(r6, Address(r3, r4, lsl(), Address::ADD, Address::pre)); // ldr r6, [r3, r4]! + __ ldrb(r4, Address(r6, sp, lsl(), Address::ADD, Address::pre)); // ldrb r4, [r6, sp]! + __ ldrh(r6, Address(r7, r10, lsl(), Address::ADD, Address::post)); // ldrh r6, [r7], r10 + __ ldrsb(r0, Address(r6, r11, lsl(), Address::ADD, Address::pre)); // ldrsb r0, [r6, r11]! + __ ldrsh(r10, Address(r6, sp, lsl(), Address::ADD, Address::post)); // ldrsh r10, [r6], sp + __ str(r7, Address(r3, r12, lsl(), Address::ADD, Address::off)); // str r7, [r3, r12] + __ strb(r3, Address(r8, r1, lsl(), Address::ADD, Address::pre)); // strb r3, [r8, r1]! + __ strh(r4, Address(r12, 64)); // strh r4, [r12, #64] + + __ bind(near); + +// LitMemoryOp + __ ldr(r1, near); // ldr r1, near + __ ldrb(r7, __ pc()); // ldrb r7, . + __ ldrh(r2, near); // ldrh r2, near + __ ldrsb(r10, __ pc()); // ldrsb r10, . + __ ldrsh(lr, near_post); // ldrsh lr, near_post + +// LitMemoryOp + __ ldr(r2, __ pc()); // ldr r2, . + __ ldrb(r3, __ pc()); // ldrb r3, . + __ ldrh(r7, near_post); // ldrh r7, near_post + __ ldrsb(sp, __ pc()); // ldrsb sp, . + __ ldrsh(r10, near); // ldrsh r10, near + +// LitMemoryOp + __ ldr(r5, __ pc()); // ldr r5, . + __ ldrb(lr, near_post); // ldrb lr, near_post + __ ldrh(r5, near_post); // ldrh r5, near_post + __ ldrsb(r6, near); // ldrsb r6, near + __ ldrsh(r11, near); // ldrsh r11, near + +// LitMemoryOp + __ ldr(r7, near_post); // ldr r7, near_post + __ ldrb(r5, near_post); // ldrb r5, near_post + __ ldrh(r10, near); // ldrh r10, near + __ ldrsb(r6, near_post); // ldrsb r6, near_post + __ ldrsh(r9, __ pc()); // ldrsh r9, . + + __ bind(near_post); + +// MemoryRegRegSftOp + __ ldr(r0, Address(r0, r10, ::ror(6), Address::ADD, Address::post)); // ldr r0, [r0], r10, ror #6 + __ ldrb(r3, Address(r8, lr, ::lsl(9), Address::ADD, Address::off)); // ldrb r3, [r8, lr, lsl #9] + __ str(r5, Address(sp, r3, ::lsl(15), Address::ADD, Address::off)); // str r5, [sp, r3, lsl #15] + __ strb(r9, Address(r9, r5, ::asr(2), Address::ADD, Address::post)); // strb r9, [r9], r5, asr #2 + +// MemoryRegRegSftOp + __ ldr(r5, Address(r4, r0, ::ror(6), Address::ADD, Address::off)); // ldr r5, [r4, r0, ror #6] + __ ldrb(lr, Address(r0, r4, ::lsr(9), Address::ADD, Address::off)); // ldrb lr, [r0, r4, lsr #9] + __ str(r5, Address(r12, r12, ::asr(5), Address::ADD, Address::post)); // str r5, [r12], r12, asr #5 + __ strb(r3, Address(r1, r7, ::ror(12), Address::ADD, Address::pre)); // strb r3, [r1, r7, ror #12]! + +// MemoryRegRegSftOp + __ ldr(r6, Address(r2, r3, ::rrx(), Address::ADD, Address::pre)); // ldr r6, [r2, r3, rrx]! + __ ldrb(r8, Address(lr, r2, ::asr(16), Address::ADD, Address::pre)); // ldrb r8, [lr, r2, asr #16]! + __ str(r6, Address(r3, r6, ::ror(7), Address::ADD, Address::pre)); // str r6, [r3, r6, ror #7]! + __ strb(r3, Address(r8, r2, ::lsl(10), Address::ADD, Address::off)); // strb r3, [r8, r2, lsl #10] + +// MemoryRegRegSftOp + __ ldr(r11, Address(sp, lr, ::lsl(8), Address::ADD, Address::off)); // ldr r11, [sp, lr, lsl #8] + __ ldrb(r10, Address(sp, r12, ::lsl(4), Address::ADD, Address::pre)); // ldrb r10, [sp, r12, lsl #4]! + __ str(sp, Address(r9, r2, ::asr(2), Address::ADD, Address::off)); // str sp, [r9, r2, asr #2] + __ strb(r7, Address(r11, lr, ::asr(14), Address::ADD, Address::pre)); // strb r7, [r11, lr, asr #14]! + +// LdStOne + __ ldrex(r12, r11); // ldrex r12, [r11] + __ ldrexb(r4, r12); // ldrexb r4, [r12] + __ ldrexh(r11, r11); // ldrexh r11, [r11] + +// LdStTwo + __ strex(r1, r7, lr); // strex r1, r7, [lr] + __ strexb(r12, r6, r4); // strexb r12, r6, [r4] + __ strexh(r4, r6, r7, Assembler::HS); // strexhHS r4, r6, [r7] + +// ThreeRegNon + __ sadd16(r3, r4, r7); // sadd16 r3, r4, r7 + __ sasx(r9, r10, r3, Assembler::AL); // sasxAL r9, r10, r3 + __ ssax(r12, r5, r6); // ssax r12, r5, r6 + __ ssub16(r12, r5, lr); // ssub16 r12, r5, lr + __ sadd8(r0, r10, r7); // sadd8 r0, r10, r7 + __ ssub8(r0, r8, r2, Assembler::VS); // ssub8VS r0, r8, r2 + __ qadd16(r11, r4, r5, Assembler::PL); // qadd16PL r11, r4, r5 + __ qasx(r11, r3, r12, Assembler::VS); // qasxVS r11, r3, r12 + __ qsax(r0, r3, r5); // qsax r0, r3, r5 + __ ssub16(r10, r12, r5, Assembler::AL); // ssub16AL r10, r12, r5 + __ qadd8(r10, r6, lr, Assembler::CC); // qadd8CC r10, r6, lr + __ qsub8(r10, r11, r7); // qsub8 r10, r11, r7 + __ shadd16(r9, r4, lr, Assembler::PL); // shadd16PL r9, r4, lr + __ shasx(r1, lr, r7); // shasx r1, lr, r7 + __ shsax(r9, r11, r5, Assembler::LO); // shsaxLO r9, r11, r5 + __ shsub16(r3, r1, r11, Assembler::GE); // shsub16GE r3, r1, r11 + __ shadd8(sp, r5, r7, Assembler::GT); // shadd8GT sp, r5, r7 + __ shsub8(r1, r5, r7); // shsub8 r1, r5, r7 + +// ThreeRegNon + __ uadd16(r10, r4, r7); // uadd16 r10, r4, r7 + __ uasx(r1, r9, r7, Assembler::HS); // uasxHS r1, r9, r7 + __ usax(r11, sp, r7); // usax r11, sp, r7 + __ usub16(r11, r4, lr); // usub16 r11, r4, lr + __ uadd8(r2, sp, r7, Assembler::LO); // uadd8LO r2, sp, r7 + __ usub8(r8, r10, lr, Assembler::GT); // usub8GT r8, r10, lr + __ uqadd16(r3, r12, sp); // uqadd16 r3, r12, sp + __ uqasx(r4, sp, r6); // uqasx r4, sp, r6 + __ uqsax(r1, r10, lr); // uqsax r1, r10, lr + __ uqsub16(r2, sp, lr, Assembler::LE); // uqsub16LE r2, sp, lr + __ uqadd8(r1, r12, r5); // uqadd8 r1, r12, r5 + __ uqsub8(r0, r4, sp, Assembler::GT); // uqsub8GT r0, r4, sp + __ uhadd16(r0, r10, r5, Assembler::HI); // uhadd16HI r0, r10, r5 + __ uhasx(r11, r4, r7, Assembler::LE); // uhasxLE r11, r4, r7 + __ uhsax(r1, lr, r9, Assembler::GE); // uhsaxGE r1, lr, r9 + __ uhsub16(r2, r11, lr); // uhsub16 r2, r11, lr + __ uhadd8(r9, r4, r5, Assembler::GE); // uhadd8GE r9, r4, r5 + __ uhsub8(r2, sp, lr, Assembler::HI); // uhsub8HI r2, sp, lr + +// PKUPSATREV + __ sxtab16(r10, r3, r7, ::ror(16)); // sxtab16 r10, r3, r7, ROR #16 + __ sxtab(r9, r5, r7, ::ror(24), Assembler::CS); // sxtabCS r9, r5, r7, ROR #24 + __ sxtah(r3, r5, r7, ::ror(8)); // sxtah r3, r5, r7, ROR #8 + __ uxtab16(r8, r4, r6, ::ror(8), Assembler::AL); // uxtab16AL r8, r4, r6, ROR #8 + __ uxtab(r0, r11, sp, ::rrx(), Assembler::EQ); // uxtabEQ r0, r11, sp, ROR #0 + __ uxtah(r9, r12, r5, ::rrx()); // uxtah r9, r12, r5, ROR #0 + +// PKUPSATREV + __ sxtb16(r3, r11, ::ror(16), Assembler::GE); // sxtb16GE r3, r11, ROR #16 + __ sxtb(r2, r6, ::rrx(), Assembler::HI); // sxtbHI r2, r6, ROR #0 + __ sxth(r3, sp, ::ror(24), Assembler::GT); // sxthGT r3, sp, ROR #24 + __ uxtb16(r12, r5, ::ror(16)); // uxtb16 r12, r5, ROR #16 + __ uxtb(r12, r5, ::ror(16)); // uxtb r12, r5, ROR #16 + __ uxth(r8, r5, ::ror(16)); // uxth r8, r5, ROR #16 + +// TwoRegNon + __ rev(r10, r4, Assembler::EQ); // revEQ r10, r4 + __ rev16(r8, r12, Assembler::GE); // rev16GE r8, r12 + __ rbit(lr, r7); // rbit lr, r7 + __ revsh(sp, r7, Assembler::GT); // revshGT sp, r7 + +// ThreeRegNon + __ sdiv(r9, sp, lr); // sdiv r9, sp, lr + __ udiv(r2, r12, r6); // udiv r2, r12, r6 + +// TwoRegTwoImm + __ sbfx(r0, r1, (unsigned)20U, (unsigned)3U, Assembler::MI); // sbfxMI r0, r1, #20, #3 + __ ubfx(r9, r2, (unsigned)16U, (unsigned)15U); // ubfx r9, r2, #16, #15 + __ bfi(r1, r11, (unsigned)27U, (unsigned)3U, Assembler::HI); // bfiHI r1, r11, #27, #3 + +// TwoRegTwoImm + __ bfc(r3, (unsigned)7U, (unsigned)10U); // bfc r3, #7, #10 + +// MultipleMemOp + __ stmda(r6, 3435U, false); // stmda r6, {r0, r1, r3, r5, r6, r8, r10, r11} + __ stmed(r4, 14559U, false); // stmed r4, {r0, r1, r2, r3, r4, r6, r7, r11, r12, sp} + __ ldmda(r0, 57812U, false); // ldmda r0, {r2, r4, r6, r7, r8, sp, lr, pc} + __ ldmfa(r12, 39027U, true); // ldmfa r12!, {r0, r1, r4, r5, r6, r11, r12, pc} + __ stmia(r9, 12733U, true); // stmia r9!, {r0, r2, r3, r4, r5, r7, r8, r12, sp} + __ stmea(r11, 21955U, false); // stmea r11, {r0, r1, r6, r7, r8, r10, r12, lr} + __ ldmia(r12, 48418U, true); // ldmia r12!, {r1, r5, r8, r10, r11, r12, sp, pc} + __ ldmfd(sp, 41226U, true); // ldmfd sp!, {r1, r3, r8, sp, pc} + __ stmdb(r11, 8729U, true); // stmdb r11!, {r0, r3, r4, r9, sp} + __ stmfd(r9, 36309U, true); // stmfd r9!, {r0, r2, r4, r6, r7, r8, r10, r11, pc} + __ ldmdb(r5, 24667U, true); // ldmdb r5!, {r0, r1, r3, r4, r6, sp, lr} + __ ldmea(r1, 37287U, false); // ldmea r1, {r0, r1, r2, r5, r7, r8, r12, pc} + __ stmib(r11, 28266U, true); // stmib r11!, {r1, r3, r5, r6, r9, r10, r11, sp, lr} + __ stmfa(r11, 17671U, false); // stmfa r11, {r0, r1, r2, r8, r10, lr} + __ ldmib(r0, 21452U, true); // ldmib r0!, {r2, r3, r6, r7, r8, r9, r12, lr} + __ ldmed(r1, 11751U, false); // ldmed r1, {r0, r1, r2, r5, r6, r7, r8, r10, r11, sp} + +// BranchLabel + __ b(forth, Assembler::CS); // bCS forth + __ bl(__ pc(), Assembler::MI); // blMI . + +// OneRegNon + __ b(r0, Assembler::VS); // bxVS r0 + __ bl(r3); // blx r3 + +// BranchLabel + __ b(__ pc(), Assembler::AL); // bAL . + __ bl(__ pc()); // bl . + +// OneRegNon + __ b(r0, Assembler::VS); // bxVS r0 + __ bl(r5); // blx r5 + +// BranchLabel + __ b(forth, Assembler::LE); // bLE forth + __ bl(__ pc(), Assembler::MI); // blMI . + +// OneRegNon + __ b(r9, Assembler::NE); // bxNE r9 + __ bl(r12); // blx r12 + +// BranchLabel + __ b(back); // b back + __ bl(__ pc(), Assembler::HI); // blHI . + +// OneRegNon + __ b(r1, Assembler::VC); // bxVC r1 + __ bl(r7, Assembler::GT); // blxGT r7 + +// BranchLabel + __ b(back, Assembler::GE); // bGE back + __ bl(__ pc(), Assembler::HI); // blHI . + +// OneRegNon + __ b(r12); // bx r12 + __ bl(r7, Assembler::CC); // blxCC r7 + +// BranchLabel + __ b(__ pc()); // b . + __ bl(back, Assembler::GT); // blGT back + +// OneRegNon + __ b(r1, Assembler::GE); // bxGE r1 + __ bl(r0); // blx r0 + +// BranchLabel + __ b(__ pc()); // b . + __ bl(forth); // bl forth + +// OneRegNon + __ b(lr, Assembler::GT); // bxGT lr + __ bl(r11, Assembler::NE); // blxNE r11 + +// BranchLabel + __ b(__ pc(), Assembler::CS); // bCS . + __ bl(__ pc()); // bl . + +// OneRegNon + __ b(r10, Assembler::HS); // bxHS r10 + __ bl(r4); // blx r4 + +// BranchLabel + __ b(back, Assembler::AL); // bAL back + __ bl(__ pc()); // bl . + +// OneRegNon + __ b(r12, Assembler::LO); // bxLO r12 + __ bl(r8); // blx r8 + +// BranchLabel + __ b(forth); // b forth + __ bl(__ pc()); // bl . + +// OneRegNon + __ b(r10); // bx r10 + __ bl(r1); // blx r1 + +// ThreeFltNon + __ vmla_f32(f4, f8, f12, Assembler::MI); // vmlaMI.f32 s4, s8, s12 + __ vmls_f32(f4, f10, f10); // vmls.f32 s4, s10, s10 + __ vnmla_f32(f2, f10, f12); // vnmla.f32 s2, s10, s12 + __ vnmls_f32(f8, f6, f8, Assembler::LT); // vnmlsLT.f32 s8, s6, s8 + __ vnmul_f32(f6, f12, f14, Assembler::MI); // vnmulMI.f32 s6, s12, s14 + __ vadd_f32(f0, f2, f0); // vadd.f32 s0, s2, s0 + __ vsub_f32(f2, f4, f10, Assembler::AL); // vsubAL.f32 s2, s4, s10 + __ vdiv_f32(f0, f2, f12, Assembler::CS); // vdivCS.f32 s0, s2, s12 + +// ThreeFltNon + __ vmla_f64(d0, d3, d6); // vmla.f64 d0, d3, d6 + __ vmls_f64(d0, d1, d5); // vmls.f64 d0, d1, d5 + __ vnmla_f64(d1, d4, d6); // vnmla.f64 d1, d4, d6 + __ vnmls_f64(d0, d1, d1, Assembler::NE); // vnmlsNE.f64 d0, d1, d1 + __ vnmul_f64(d3, d5, d5, Assembler::NE); // vnmulNE.f64 d3, d5, d5 + __ vadd_f64(d0, d2, d4, Assembler::LO); // vaddLO.f64 d0, d2, d4 + __ vsub_f64(d1, d2, d4); // vsub.f64 d1, d2, d4 + __ vdiv_f64(d0, d1, d5, Assembler::MI); // vdivMI.f64 d0, d1, d5 + +// TwoFltNon + __ vabs_f32(f6, f6); // vabs.f32 s6, s6 + __ vneg_f32(f6, f8, Assembler::PL); // vnegPL.f32 s6, s8 + __ vsqrt_f32(f0, f8); // vsqrt.f32 s0, s8 + +// TwoFltNon + __ vabs_f64(d0, d4); // vabs.f64 d0, d4 + __ vneg_f64(d1, d4); // vneg.f64 d1, d4 + __ vsqrt_f64(d0, d1); // vsqrt.f64 d0, d1 + +// vmov_f32 + __ vmov_f32(f0, lr, Assembler::PL); // vmovPL.f32 s0, lr + +// vmov_f32 + __ vmov_f32(r11, f8); // vmov.f32 r11, s8 + +// vmov_f64 + __ vmov_f64(d1, r11, lr, Assembler::LT); // vmovLT.f64 d1, r11, lr + +// vmov_f64 + __ vmov_f64(r7, r5, d5); // vmov.f64 r7, r5, d5 + +// vmov_f32 + __ vmov_f32(f8, f12); // vmov.f32 s8, s12 + +// vmov_f64 + __ vmov_f64(d1, d2, Assembler::HI); // vmovHI.f64 d1, d2 + +// vmov_f32 + __ vmov_f32(f4, 1.0f, Assembler::VS); // vmovVS.f32 s4, #1.0 + +// vmov_f64 + __ vmov_f64(d2, 1.0); // vmov.f64 d2, #1.0 + +// vmov_f32 + __ vmov_f32(f6, 2.0f); // vmov.f32 s6, #2.0 + +// vmov_f64 + __ vmov_f64(d1, 2.0); // vmov.f64 d1, #2.0 + +// vector memory + __ vldr_f32(f4, Address(r5, 116)); // vldr.f32 s4, [r5, #116] + __ vstr_f32(f2, Address(r1, 56), Assembler::CC); // vstrCC.f32 s2, [r1, #56] + +// vector memory + __ vldr_f64(d7, Address(r5, 16), Assembler::NE); // vldrNE.f64 d7, [r5, #16] + __ vstr_f64(d6, Address(r1, 228)); // vstr.f64 d6, [r1, #228] + + __ bind(near_flt); + +// vector memory + __ vldr_f32(f2, near_post_flt); // vldr.f32 s2, near_post_flt + __ vstr_f32(f6, near_post_flt); // vstr.f32 s6, near_post_flt + +// vector memory + __ vldr_f64(d2, near_flt, Assembler::LT); // vldrLT.f64 d2, near_flt + __ vstr_f64(d3, __ pc(), Assembler::GT); // vstrGT.f64 d3, . + +// vector memory + __ vldr_f32(f4, near_post_flt, Assembler::CC); // vldrCC.f32 s4, near_post_flt + __ vstr_f32(f0, near_post_flt); // vstr.f32 s0, near_post_flt + +// vector memory + __ vldr_f64(d4, near_post_flt, Assembler::GT); // vldrGT.f64 d4, near_post_flt + __ vstr_f64(d0, near_flt); // vstr.f64 d0, near_flt + +// vector memory + __ vldr_f32(f8, near_post_flt); // vldr.f32 s8, near_post_flt + __ vstr_f32(f6, near_post_flt); // vstr.f32 s6, near_post_flt + +// vector memory + __ vldr_f64(d4, near_flt, Assembler::PL); // vldrPL.f64 d4, near_flt + __ vstr_f64(d5, near_flt); // vstr.f64 d5, near_flt + +// vector memory + __ vldr_f32(f8, near_post_flt, Assembler::LS); // vldrLS.f32 s8, near_post_flt + __ vstr_f32(f12, __ pc(), Assembler::CC); // vstrCC.f32 s12, . + +// vector memory + __ vldr_f64(d6, near_post_flt, Assembler::AL); // vldrAL.f64 d6, near_post_flt + __ vstr_f64(d1, near_post_flt, Assembler::LT); // vstrLT.f64 d1, near_post_flt + + __ bind(near_post_flt); + +// FltMultMemOp + __ vldmia_f32(r1, FloatRegSet::of(f4).bits(), false); // vldmia.f32 r1, {s4} + __ vstmia_f32(r6, FloatRegSet::of(f4).bits(), true, Assembler::CS); // vstmiaCS.f32 r6!, {s4} + +// DblMultMemOp + __ vldmia_f64(r9, DoubleFloatRegSet::of(d1, d2, d3, d4).bits(), true); // vldmia.f64 r9!, {d1, d2, d3, d4} + __ vstmia_f64(r3, DoubleFloatRegSet::of(d6, d7).bits(), true); // vstmia.f64 r3!, {d6, d7} + +// FltMultMemOp + __ vldmdb_f32(r2, FloatRegSet::of(f6).bits(), Assembler::VS); // vldmdbVS.f32 r2!, {s6} + __ vstmdb_f32(r6, FloatRegSet::of(f14).bits()); // vstmdb.f32 r6!, {s14} + +// DblMultMemOp + __ vldmdb_f64(sp, DoubleFloatRegSet::of(d4, d5, d6, d7).bits()); // vldmdb.f64 sp!, {d4, d5, d6, d7} + __ vstmdb_f64(r0, DoubleFloatRegSet::of(d5, d6, d7).bits()); // vstmdb.f64 r0!, {d5, d6, d7} + +// vcmp_f32 + __ vcmp_f32(f2, f2); // vcmp.f32 s2, s2 + +// vcmpe_f32 + __ vcmpe_f32(f8, f8, Assembler::VC); // vcmpeVC.f32 s8, s8 + +// vcmp_f64 + __ vcmp_f64(d0, d6); // vcmp.f64 d0, d6 + +// vcmpe_f64 + __ vcmpe_f64(d3, d7, Assembler::GE); // vcmpeGE.f64 d3, d7 + +// vcmp_f32 + __ vcmp_f32(f2, 0.0f, Assembler::LT); // vcmpLT.f32 s2, #0.0 + +// vcmpe_f32 + __ vcmpe_f32(f14, 0.0f, Assembler::GT); // vcmpeGT.f32 s14, #0.0 + +// vcmp_f64 + __ vcmp_f64(d4, 0.0); // vcmp.f64 d4, #0.0 + +// vcmpe_f64 + __ vcmpe_f64(d1, 0.0); // vcmpe.f64 d1, #0.0 + +// vcvt + __ vcvt_s32_f32(f2, f6, Assembler::VS); // vcvtVS.s32.f32 s2, s6 + __ vcvt_u32_f32(f6, f14, Assembler::GT); // vcvtGT.u32.f32 s6, s14 + __ vcvt_f32_s32(f0, f2, Assembler::CC); // vcvtCC.f32.s32 s0, s2 + __ vcvt_f32_u32(f2, f4, Assembler::CC); // vcvtCC.f32.u32 s2, s4 + +// vcvt + __ vcvt_s32_f64(f4, d4, Assembler::HI); // vcvtHI.s32.f64 s4, d4 + __ vcvt_u32_f64(f6, d6, Assembler::HI); // vcvtHI.u32.f64 s6, d6 + __ vcvt_f32_f64(f6, d7, Assembler::LS); // vcvtLS.f32.f64 s6, d7 + +// vcvt + __ vcvt_f64_s32(d3, f8); // vcvt.f64.s32 d3, s8 + __ vcvt_f64_u32(d5, f14, Assembler::EQ); // vcvtEQ.f64.u32 d5, s14 + __ vcvt_f64_f32(d4, f10, Assembler::AL); // vcvtAL.f64.f32 d4, s10 + +// BKPT + __ bkpt((unsigned)26U); // bkpt #26 + + __ bind(forth); + +/* +aarch32ops.o: file format elf32-littlearm + + +Disassembly of section .text: + +00000000 : + 0: e082852b add r8, r2, fp, lsr #10 + 4: 009310c7 addseq r1, r3, r7, asr #1 + 8: e0290284 eor r0, r9, r4, lsl #5 + c: c0329066 eorsgt r9, r2, r6, rrx + 10: c04c000e subgt r0, ip, lr + 14: 00528364 subseq r8, r2, r4, ror #6 + 18: e069818d rsb r8, r9, sp, lsl #3 + 1c: 60708864 rsbsvs r8, r0, r4, ror #16 + 20: d08597a1 addle r9, r5, r1, lsr #15 + 24: e09d12c6 adds r1, sp, r6, asr #5 + 28: c0adb0c7 adcgt fp, sp, r7, asr #1 + 2c: e0b80329 adcs r0, r8, r9, lsr #6 + 30: e0c392e6 sbc r9, r3, r6, ror #5 + 34: 80dd1845 sbcshi r1, sp, r5, asr #16 + 38: 30e28486 rsccc r8, r2, r6, lsl #9 + 3c: e0f4a76d rscs sl, r4, sp, ror #14 + 40: 118db785 orrne fp, sp, r5, lsl #15 + 44: e19a9764 orrs r9, sl, r4, ror #14 + 48: e1cd90e5 bic r9, sp, r5, ror #1 + 4c: e1d20547 bics r0, r2, r7, asr #10 + 50: e086d777 add sp, r6, r7, ror r7 + 54: 809c4776 addshi r4, ip, r6, ror r7 + 58: 90265c57 eorls r5, r6, r7, asr ip + 5c: e035841d eors r8, r5, sp, lsl r4 + 60: e04c2055 sub r2, ip, r5, asr r0 + 64: 20539c17 subscs r9, r3, r7, lsl ip + 68: c06c9614 rsbgt r9, ip, r4, lsl r6 + 6c: e072811c rsbs r8, r2, ip, lsl r1 + 70: e08c4d1d add r4, ip, sp, lsl sp + 74: e09b8d76 adds r8, fp, r6, ror sp + 78: 10a20415 adcne r0, r2, r5, lsl r4 + 7c: e0beb256 adcs fp, lr, r6, asr r2 + 80: 80ca835e sbchi r8, sl, lr, asr r3 + 84: e0dc1615 sbcs r1, ip, r5, lsl r6 + 88: 60e54a7e rscvs r4, r5, lr, ror sl + 8c: e0fc181d rscs r1, ip, sp, lsl r8 + 90: 61818076 orrvs r8, r1, r6, ror r0 + 94: e19db577 orrs fp, sp, r7, ror r5 + 98: e1ce4216 bic r4, lr, r6, lsl r2 + 9c: e1dba31d bics sl, fp, sp, lsl r3 + a0: 828d8261 addhi r8, sp, #268435462 ; 0x10000006 + a4: e29ed69b adds sp, lr, #162529280 ; 0x9b00000 + a8: e226e87d eor lr, r6, #8192000 ; 0x7d0000 + ac: e2332f49 eors r2, r3, #292 ; 0x124 + b0: e24d46d9 sub r4, sp, #227540992 ; 0xd900000 + b4: b25e1402 subslt r1, lr, #33554432 ; 0x2000000 + b8: e2650325 rsb r0, r5, #-1811939328 ; 0x94000000 + bc: 3274882f rsbscc r8, r4, #3080192 ; 0x2f0000 + c0: b2849102 addlt r9, r4, #-2147483648 ; 0x80000000 + c4: e2948902 adds r8, r4, #32768 ; 0x8000 + c8: 22aeac2a adccs sl, lr, #10752 ; 0x2a00 + cc: e2b6aabd adcs sl, r6, #774144 ; 0xbd000 + d0: e2cc2426 sbc r2, ip, #637534208 ; 0x26000000 + d4: e2da85a5 sbcs r8, sl, #692060160 ; 0x29400000 + d8: e2e6d871 rsc sp, r6, #7405568 ; 0x710000 + dc: 12fba6e9 rscsne sl, fp, #244318208 ; 0xe900000 + e0: 638737ff orrvs r3, r7, #66846720 ; 0x3fc0000 + e4: 03952951 orrseq r2, r5, #1327104 ; 0x144000 + e8: 63c18eea bicvs r8, r1, #3744 ; 0xea0 + ec: 33d2020a bicscc r0, r2, #-1610612736 ; 0xa0000000 + f0: e118028d tst r8, sp, lsl #5 + f4: e13601a7 teq r6, r7, lsr #3 + f8: e15c0164 cmp ip, r4, ror #2 + fc: b1750807 cmnlt r5, r7, lsl #16 + 100: e112073e tst r2, lr, lsr r7 + 104: 31300572 teqcc r0, r2, ror r5 + 108: 915e0b37 cmpls lr, r7, lsr fp + 10c: 617a0b17 cmnvs sl, r7, lsl fp + 110: e3120585 tst r2, #557842432 ; 0x21400000 + 114: 433e071b teqmi lr, #7077888 ; 0x6c0000 + 118: e355030e cmp r5, #939524096 ; 0x38000000 + 11c: 3377010a cmncc r7, #-2147483646 ; 0x80000002 + 120: e1a00b84 lsl r0, r4, #23 + 124: e1b01484 lsls r1, r4, #9 + 128: e1a001aa lsr r0, sl, #3 + 12c: e1b00a2a lsrs r0, sl, #20 + 130: e1a015c9 asr r1, r9, #11 + 134: 61b0254b asrsvs r2, fp, #10 + 138: 31a08fe2 rorcc r8, r2, #31 + 13c: e1b0946c rors r9, ip, #8 + 140: e1a0877e ror r8, lr, r7 + 144: e1b0c473 rors ip, r3, r4 + 148: c1a0ce1d lslgt ip, sp, lr + 14c: e1b0c61d lsls ip, sp, r6 + 150: c1a00931 lsrgt r0, r1, r9 + 154: c1b0bc33 lsrsgt fp, r3, ip + 158: d1a0265c asrle r2, ip, r6 + 15c: b1b0165a asrslt r1, sl, r6 + 160: e1a0a003 mov sl, r3 + 164: e1b00009 movs r0, r9 + 168: 73a03e29 movvc r3, #656 ; 0x290 + 16c: e3b0497e movs r4, #2064384 ; 0x1f8000 + 170: e1a0c1a6 lsr ip, r6, #3 + 174: 71b0554d asrsvc r5, sp, #10 + 178: e1a0137e ror r1, lr, r3 + 17c: 01b0897c rorseq r8, ip, r9 + 180: 330cbf31 movwcc fp, #53041 ; 0xcf31 + 184: 33429bf7 movtcc r9, #11255 ; 0x2bf7 + 188: d001059d mulle r1, sp, r5 + 18c: e0100b9a muls r0, sl, fp + 190: e0207c93 mla r0, r3, ip, r7 + 194: 0038639b mlaseq r8, fp, r3, r6 + 198: e084e695 umull lr, r4, r5, r6 + 19c: e0940796 umulls r0, r4, r6, r7 + 1a0: e0a08e9b umlal r8, r0, fp, lr + 1a4: e0b4b79e umlals fp, r4, lr, r7 + 1a8: 20c51796 smullcs r1, r5, r6, r7 + 1ac: 40db059c smullsmi r0, fp, ip, r5 + 1b0: e0498592 umaal r8, r9, r2, r5 + 1b4: 0060ed94 mlseq r0, r4, sp, lr + 1b8: 510d9054 qaddpl r9, r4, sp + 1bc: 4125005c qsubmi r0, ip, r5 + 1c0: e1473055 qdadd r3, r5, r7 + 1c4: e1649052 qdsub r9, r2, r4 + 1c8: e101658c smlabb r1, ip, r5, r6 + 1cc: e1006cca smlabt r0, sl, ip, r6 + 1d0: e108e3a1 smlatb r8, r1, r3, lr + 1d4: e10176ed smlatt r1, sp, r6, r7 + 1d8: e1206483 smlawb r0, r3, r4, r6 + 1dc: e12b7ec4 smlawt fp, r4, lr, r7 + 1e0: e14a0786 smlalbb r0, sl, r6, r7 + 1e4: 914b3ec4 smlalbtls r3, fp, r4, lr + 1e8: e14b8ca3 smlaltb r8, fp, r3, ip + 1ec: e14185e3 smlaltt r8, r1, r3, r5 + 1f0: 21220dac smulwbcs r2, ip, sp + 1f4: e12806ec smulwt r8, ip, r6 + 1f8: a1620e86 smulbbge r2, r6, lr + 1fc: e16807cc smulbt r8, ip, r7 + 200: 016a0ea3 smultbeq sl, r3, lr + 204: e1600de3 smultt r0, r3, sp + 208: e697a009 ldr sl, [r7], r9 + 20c: e5d900c4 ldrb r0, [r9, #196] ; 0xc4 + 210: e1b4e0b6 ldrh lr, [r4, r6]! + 214: e1f96ed8 ldrsb r6, [r9, #232]! ; 0xe8 + 218: e09120f1 ldrsh r2, [r1], r1 + 21c: e6890004 str r0, [r9], r4 + 220: e5e5305c strb r3, [r5, #92]! ; 0x5c + 224: e1c82ab0 strh r2, [r8, #160] ; 0xa0 + 228: e79c8008 ldr r8, [ip, r8] + 22c: e4dab010 ldrb fp, [sl], #16 + 230: e19ab0b6 ldrh fp, [sl, r6] + 234: e1bb50da ldrsb r5, [fp, sl]! + 238: e19360f7 ldrsh r6, [r3, r7] + 23c: e7ad7005 str r7, [sp, r5]! + 240: e5ca2000 strb r2, [sl] + 244: e08460b3 strh r6, [r4], r3 + 248: e59ca000 ldr sl, [ip] + 24c: e4db4084 ldrb r4, [fp], #132 ; 0x84 + 250: e09990bc ldrh r9, [r9], ip + 254: e0d399d4 ldrsb r9, [r3], #148 ; 0x94 + 258: e1f2b9f4 ldrsh fp, [r2, #148]! ; 0x94 + 25c: e78db00b str fp, [sp, fp] + 260: e7cd100a strb r1, [sp, sl] + 264: e08ea0b9 strh sl, [lr], r9 + 268: e7b36004 ldr r6, [r3, r4]! + 26c: e7f6400d ldrb r4, [r6, sp]! + 270: e09760ba ldrh r6, [r7], sl + 274: e1b600db ldrsb r0, [r6, fp]! + 278: e096a0fd ldrsh sl, [r6], sp + 27c: e783700c str r7, [r3, ip] + 280: e7e83001 strb r3, [r8, r1]! + 284: e1cc44b0 strh r4, [ip, #64] ; 0x40 + +00000288 : + 288: e51f1008 ldr r1, [pc, #-8] ; 288 + 28c: e55f7008 ldrb r7, [pc, #-8] ; 28c + 290: e15f21b0 ldrh r2, [pc, #-16] ; 288 + 294: e15fa0d8 ldrsb sl, [pc, #-8] ; 294 + 298: e1dfe3f8 ldrsh lr, [pc, #56] ; 2d8 + 29c: e51f2008 ldr r2, [pc, #-8] ; 29c + 2a0: e55f3008 ldrb r3, [pc, #-8] ; 2a0 + 2a4: e1df72bc ldrh r7, [pc, #44] ; 2d8 + 2a8: e15fd0d8 ldrsb sp, [pc, #-8] ; 2a8 + 2ac: e15fa2fc ldrsh sl, [pc, #-44] ; 288 + 2b0: e51f5008 ldr r5, [pc, #-8] ; 2b0 + 2b4: e5dfe01c ldrb lr, [pc, #28] ; 2d8 + 2b8: e1df51b8 ldrh r5, [pc, #24] ; 2d8 + 2bc: e15f63dc ldrsb r6, [pc, #-60] ; 288 + 2c0: e15fb4f0 ldrsh fp, [pc, #-64] ; 288 + 2c4: e59f700c ldr r7, [pc, #12] ; 2d8 + 2c8: e5df5008 ldrb r5, [pc, #8] ; 2d8 + 2cc: e15fa4bc ldrh sl, [pc, #-76] ; 288 + 2d0: e1df60d0 ldrsb r6, [pc] ; 2d8 + 2d4: e15f90f8 ldrsh r9, [pc, #-8] ; 2d4 + +000002d8 : + 2d8: e690036a ldr r0, [r0], sl, ror #6 + 2dc: e7d8348e ldrb r3, [r8, lr, lsl #9] + 2e0: e78d5783 str r5, [sp, r3, lsl #15] + 2e4: e6c99145 strb r9, [r9], r5, asr #2 + 2e8: e7945360 ldr r5, [r4, r0, ror #6] + 2ec: e7d0e4a4 ldrb lr, [r0, r4, lsr #9] + 2f0: e68c52cc str r5, [ip], ip, asr #5 + 2f4: e7e13667 strb r3, [r1, r7, ror #12]! + 2f8: e7b26063 ldr r6, [r2, r3, rrx]! + 2fc: e7fe8842 ldrb r8, [lr, r2, asr #16]! + 300: e7a363e6 str r6, [r3, r6, ror #7]! + 304: e7c83502 strb r3, [r8, r2, lsl #10] + 308: e79db40e ldr fp, [sp, lr, lsl #8] + 30c: e7fda20c ldrb sl, [sp, ip, lsl #4]! + 310: e789d142 str sp, [r9, r2, asr #2] + 314: e7eb774e strb r7, [fp, lr, asr #14]! + 318: e19bcf9f ldrex r12, [fp] + 31c: e1dc4f9f ldrexb r4, [ip] + 320: e1fbbf9f ldrexh fp, [fp] + 324: e18e1f97 strex r1, r7, [lr] + 328: e1c4cf96 strexb ip, r6, [r4] + 32c: 21e74f96 strexhcs r4, r6, [r7] + 330: e6143f17 sadd16 r3, r4, r7 + 334: e61a9f33 sasx r9, sl, r3 + 338: e615cf56 ssax ip, r5, r6 + 33c: e615cf7e ssub16 ip, r5, lr + 340: e61a0f97 sadd8 r0, sl, r7 + 344: 66180ff2 ssub8vs r0, r8, r2 + 348: 5624bf15 qadd16pl fp, r4, r5 + 34c: 6623bf3c qasxvs fp, r3, ip + 350: e6230f55 qsax r0, r3, r5 + 354: e61caf75 ssub16 sl, ip, r5 + 358: 3626af9e qadd8cc sl, r6, lr + 35c: e62baff7 qsub8 sl, fp, r7 + 360: 56349f1e shadd16pl r9, r4, lr + 364: e63e1f37 shasx r1, lr, r7 + 368: 363b9f55 shsaxcc r9, fp, r5 + 36c: a6313f7b shsub16ge r3, r1, fp + 370: c635df97 shadd8gt sp, r5, r7 + 374: e6351ff7 shsub8 r1, r5, r7 + 378: e654af17 uadd16 sl, r4, r7 + 37c: 26591f37 uasxcs r1, r9, r7 + 380: e65dbf57 usax fp, sp, r7 + 384: e654bf7e usub16 fp, r4, lr + 388: 365d2f97 uadd8cc r2, sp, r7 + 38c: c65a8ffe usub8gt r8, sl, lr + 390: e66c3f1d uqadd16 r3, ip, sp + 394: e66d4f36 uqasx r4, sp, r6 + 398: e66a1f5e uqsax r1, sl, lr + 39c: d66d2f7e uqsub16le r2, sp, lr + 3a0: e66c1f95 uqadd8 r1, ip, r5 + 3a4: c6640ffd uqsub8gt r0, r4, sp + 3a8: 867a0f15 uhadd16hi r0, sl, r5 + 3ac: d674bf37 uhasxle fp, r4, r7 + 3b0: a67e1f59 uhsaxge r1, lr, r9 + 3b4: e67b2f7e uhsub16 r2, fp, lr + 3b8: a6749f95 uhadd8ge r9, r4, r5 + 3bc: 867d2ffe uhsub8hi r2, sp, lr + 3c0: e683a877 sxtab16 sl, r3, r7, ror #16 + 3c4: 26a59c77 sxtabcs r9, r5, r7, ror #24 + 3c8: e6b53477 sxtah r3, r5, r7, ror #8 + 3cc: e6c48476 uxtab16 r8, r4, r6, ror #8 + 3d0: 06eb007d uxtabeq r0, fp, sp + 3d4: e6fc9075 uxtah r9, ip, r5 + 3d8: a68f387b sxtb16ge r3, fp, ror #16 + 3dc: 86af2076 sxtbhi r2, r6 + 3e0: c6bf3c7d sxthgt r3, sp, ror #24 + 3e4: e6cfc875 uxtb16 ip, r5, ror #16 + 3e8: e6efc875 uxtb ip, r5, ror #16 + 3ec: e6ff8875 uxth r8, r5, ror #16 + 3f0: 06bfaf34 reveq sl, r4 + 3f4: a6bf8fbc rev16ge r8, ip + 3f8: e6ffef37 rbit lr, r7 + 3fc: c6ffdfb7 revshgt sp, r7 + 400: e719fe1d sdiv r9, sp, lr + 404: e732f61c udiv r2, ip, r6 + 408: 47a20a51 sbfxmi r0, r1, #20, #3 + 40c: e7ee9852 ubfx r9, r2, #16, #15 + 410: 87dd1d9b bfihi r1, fp, #27, #3 + 414: e7d0339f bfc r3, #7, #10 + 418: e8060d6b stmda r6, {r0, r1, r3, r5, r6, r8, sl, fp} + 41c: e80438df stmda r4, {r0, r1, r2, r3, r4, r6, r7, fp, ip, sp} + 420: e810e1d4 ldmda r0, {r2, r4, r6, r7, r8, sp, lr, pc} + 424: e83c9873 ldmda ip!, {r0, r1, r4, r5, r6, fp, ip, pc} + 428: e8a931bd stmia r9!, {r0, r2, r3, r4, r5, r7, r8, ip, sp} + 42c: e88b55c3 stm fp, {r0, r1, r6, r7, r8, sl, ip, lr} + 430: e8bcbd22 ldm ip!, {r1, r5, r8, sl, fp, ip, sp, pc} + 434: e8bda10a pop {r1, r3, r8, sp, pc} + 438: e92b2219 stmdb fp!, {r0, r3, r4, r9, sp} + 43c: e9298dd5 stmdb r9!, {r0, r2, r4, r6, r7, r8, sl, fp, pc} + 440: e935605b ldmdb r5!, {r0, r1, r3, r4, r6, sp, lr} + 444: e91191a7 ldmdb r1, {r0, r1, r2, r5, r7, r8, ip, pc} + 448: e9ab6e6a stmib fp!, {r1, r3, r5, r6, r9, sl, fp, sp, lr} + 44c: e98b4507 stmib fp, {r0, r1, r2, r8, sl, lr} + 450: e9b053cc ldmib r0!, {r2, r3, r6, r7, r8, r9, ip, lr} + 454: e9912de7 ldmib r1, {r0, r1, r2, r5, r6, r7, r8, sl, fp, sp} + 458: 2a000075 bcs 634 + 45c: 4bfffffe blmi 45c + 460: 612fff10 bxvs r0 + 464: e12fff33 blx r3 + 468: eafffffe b 468 + 46c: ebfffffe bl 46c + 470: 612fff10 bxvs r0 + 474: e12fff35 blx r5 + 478: da00006d ble 634 + 47c: 4bfffffe blmi 47c + 480: 112fff19 bxne r9 + 484: e12fff3c blx ip + 488: eafffedc b 0 + 48c: 8bfffffe blhi 48c + 490: 712fff11 bxvc r1 + 494: c12fff37 blxgt r7 + 498: aafffed8 bge 0 + 49c: 8bfffffe blhi 49c + 4a0: e12fff1c bx ip + 4a4: 312fff37 blxcc r7 + 4a8: eafffffe b 4a8 + 4ac: cbfffed3 blgt 0 + 4b0: a12fff11 bxge r1 + 4b4: e12fff30 blx r0 + 4b8: eafffffe b 4b8 + 4bc: eb00005c bl 634 + 4c0: c12fff1e bxgt lr + 4c4: 112fff3b blxne fp + 4c8: 2afffffe bcs 4c8 + 4cc: ebfffffe bl 4cc + 4d0: 212fff1a bxcs sl + 4d4: e12fff34 blx r4 + 4d8: eafffec8 b 0 + 4dc: ebfffffe bl 4dc + 4e0: 312fff1c bxcc ip + 4e4: e12fff38 blx r8 + 4e8: ea000051 b 634 + 4ec: ebfffffe bl 4ec + 4f0: e12fff1a bx sl + 4f4: e12fff31 blx r1 + 4f8: 4e042a06 vmlami.f32 s4, s8, s12 + 4fc: ee052a45 vmls.f32 s4, s10, s10 + 500: ee151a46 vnmla.f32 s2, s10, s12 + 504: be134a04 vnmlslt.f32 s8, s6, s8 + 508: 4e263a47 vnmulmi.f32 s6, s12, s14 + 50c: ee310a00 vadd.f32 s0, s2, s0 + 510: ee321a45 vsub.f32 s2, s4, s10 + 514: 2e810a06 vdivcs.f32 s0, s2, s12 + 518: ee030b06 vmla.f64 d0, d3, d6 + 51c: ee010b45 vmls.f64 d0, d1, d5 + 520: ee141b46 vnmla.f64 d1, d4, d6 + 524: 1e110b01 vnmlsne.f64 d0, d1, d1 + 528: 1e253b45 vnmulne.f64 d3, d5, d5 + 52c: 3e320b04 vaddcc.f64 d0, d2, d4 + 530: ee321b44 vsub.f64 d1, d2, d4 + 534: 4e810b05 vdivmi.f64 d0, d1, d5 + 538: eeb03ac3 vabs.f32 s6, s6 + 53c: 5eb13a44 vnegpl.f32 s6, s8 + 540: eeb10ac4 vsqrt.f32 s0, s8 + 544: eeb00bc4 vabs.f64 d0, d4 + 548: eeb11b44 vneg.f64 d1, d4 + 54c: eeb10bc1 vsqrt.f64 d0, d1 + 550: 5e00ea10 vmovpl s0, lr + 554: ee14ba10 vmov fp, s8 + 558: bc4ebb11 vmovlt d1, fp, lr + 55c: ec557b15 vmov r7, r5, d5 + 560: eeb04a46 vmov.f32 s8, s12 + 564: 8eb01b42 vmovhi.f64 d1, d2 + 568: 6eb72a00 vmovvs.f32 s4, #112 ; 0x70 + 56c: eeb72b00 vmov.f64 d2, #112 ; 0x70 + 570: eeb03a00 vmov.f32 s6, #0 + 574: eeb01b00 vmov.f64 d1, #0 + 578: ed952a1d vldr s4, [r5, #116] ; 0x74 + 57c: 3d811a0e vstrcc s2, [r1, #56] ; 0x38 + 580: 1d957b04 vldrne d7, [r5, #16] + 584: ed816b39 vstr d6, [r1, #228] ; 0xe4 + +00000588 : + 588: ed9f1a0e vldr s2, [pc, #56] ; 5c8 + 58c: ed8f3a0d vstr s6, [pc, #52] ; 5c8 + 590: bd1f2b04 vldrlt d2, [pc, #-16] ; 588 + 594: cd0f3b02 vstrgt d3, [pc, #-8] ; 594 + 598: 3d9f2a0a vldrcc s4, [pc, #40] ; 5c8 + 59c: ed8f0a09 vstr s0, [pc, #36] ; 5c8 + 5a0: cd9f4b08 vldrgt d4, [pc, #32] ; 5c8 + 5a4: ed0f0b09 vstr d0, [pc, #-36] ; 588 + 5a8: ed9f4a06 vldr s8, [pc, #24] ; 5c8 + 5ac: ed8f3a05 vstr s6, [pc, #20] ; 5c8 + 5b0: 5d1f4b0c vldrpl d4, [pc, #-48] ; 588 + 5b4: ed0f5b0d vstr d5, [pc, #-52] ; 588 + 5b8: 9d9f4a02 vldrls s8, [pc, #8] ; 5c8 + 5bc: 3d0f6a02 vstrcc s12, [pc, #-8] ; 5bc + 5c0: ed9f6b00 vldr d6, [pc] ; 5c8 + 5c4: bd0f1b01 vstrlt d1, [pc, #-4] ; 5c8 + +000005c8 : + 5c8: ec912a01 vldmia r1, {s4} + 5cc: 2ca62a01 vstmiacs r6!, {s4} + 5d0: ecb91b08 vldmia r9!, {d1-d4} + 5d4: eca36b04 vstmia r3!, {d6-d7} + 5d8: 6d323a01 vldmdbvs r2!, {s6} + 5dc: ed267a01 vstmdb r6!, {s14} + 5e0: ed3d4b08 vldmdb sp!, {d4-d7} + 5e4: ed205b06 vstmdb r0!, {d5-d7} + 5e8: eeb41a41 vcmp.f32 s2, s2 + 5ec: 7eb44ac4 vcmpevc.f32 s8, s8 + 5f0: eeb40b46 vcmp.f64 d0, d6 + 5f4: aeb43bc7 vcmpege.f64 d3, d7 + 5f8: beb51a40 vcmplt.f32 s2, #0.0 + 5fc: ceb57ac0 vcmpegt.f32 s14, #0.0 + 600: eeb54b40 vcmp.f64 d4, #0.0 + 604: eeb51bc0 vcmpe.f64 d1, #0.0 + 608: 6ebd1ac3 vcvtvs.s32.f32 s2, s6 + 60c: cebc3ac7 vcvtgt.u32.f32 s6, s14 + 610: 3eb80ac1 vcvtcc.f32.s32 s0, s2 + 614: 3eb81a42 vcvtcc.f32.u32 s2, s4 + 618: 8ebd2bc4 vcvthi.s32.f64 s4, d4 + 61c: 8ebc3bc6 vcvthi.u32.f64 s6, d6 + 620: 9eb73bc7 vcvtls.f32.f64 s6, d7 + 624: eeb83bc4 vcvt.f64.s32 d3, s8 + 628: 0eb85b47 vcvteq.f64.u32 d5, s14 + 62c: eeb74ac5 vcvt.f64.f32 d4, s10 + 630: e120017a bkpt 0x001a + */ + + static const unsigned int insns[] = + { + 0xe082852b, 0x009310c7, 0xe0290284, 0xc0329066, + 0xc04c000e, 0x00528364, 0xe069818d, 0x60708864, + 0xd08597a1, 0xe09d12c6, 0xc0adb0c7, 0xe0b80329, + 0xe0c392e6, 0x80dd1845, 0x30e28486, 0xe0f4a76d, + 0x118db785, 0xe19a9764, 0xe1cd90e5, 0xe1d20547, + 0xe086d777, 0x809c4776, 0x90265c57, 0xe035841d, + 0xe04c2055, 0x20539c17, 0xc06c9614, 0xe072811c, + 0xe08c4d1d, 0xe09b8d76, 0x10a20415, 0xe0beb256, + 0x80ca835e, 0xe0dc1615, 0x60e54a7e, 0xe0fc181d, + 0x61818076, 0xe19db577, 0xe1ce4216, 0xe1dba31d, + 0x828d8261, 0xe29ed69b, 0xe226e87d, 0xe2332f49, + 0xe24d46d9, 0xb25e1402, 0xe2650325, 0x3274882f, + 0xb2849102, 0xe2948902, 0x22aeac2a, 0xe2b6aabd, + 0xe2cc2426, 0xe2da85a5, 0xe2e6d871, 0x12fba6e9, + 0x638737ff, 0x03952951, 0x63c18eea, 0x33d2020a, + 0xe118028d, 0xe13601a7, 0xe15c0164, 0xb1750807, + 0xe112073e, 0x31300572, 0x915e0b37, 0x617a0b17, + 0xe3120585, 0x433e071b, 0xe355030e, 0x3377010a, + 0xe1a00b84, 0xe1b01484, 0xe1a001aa, 0xe1b00a2a, + 0xe1a015c9, 0x61b0254b, 0x31a08fe2, 0xe1b0946c, + 0xe1a0877e, 0xe1b0c473, 0xc1a0ce1d, 0xe1b0c61d, + 0xc1a00931, 0xc1b0bc33, 0xd1a0265c, 0xb1b0165a, + 0xe1a0a003, 0xe1b00009, 0x73a03e29, 0xe3b0497e, + 0xe1a0c1a6, 0x71b0554d, 0xe1a0137e, 0x01b0897c, + 0x330cbf31, 0x33429bf7, 0xd001059d, 0xe0100b9a, + 0xe0207c93, 0x0038639b, 0xe084e695, 0xe0940796, + 0xe0a08e9b, 0xe0b4b79e, 0x20c51796, 0x40db059c, + 0xe0498592, 0x0060ed94, 0x510d9054, 0x4125005c, + 0xe1473055, 0xe1649052, 0xe101658c, 0xe1006cca, + 0xe108e3a1, 0xe10176ed, 0xe1206483, 0xe12b7ec4, + 0xe14a0786, 0x914b3ec4, 0xe14b8ca3, 0xe14185e3, + 0x21220dac, 0xe12806ec, 0xa1620e86, 0xe16807cc, + 0x016a0ea3, 0xe1600de3, 0xe697a009, 0xe5d900c4, + 0xe1b4e0b6, 0xe1f96ed8, 0xe09120f1, 0xe6890004, + 0xe5e5305c, 0xe1c82ab0, 0xe79c8008, 0xe4dab010, + 0xe19ab0b6, 0xe1bb50da, 0xe19360f7, 0xe7ad7005, + 0xe5ca2000, 0xe08460b3, 0xe59ca000, 0xe4db4084, + 0xe09990bc, 0xe0d399d4, 0xe1f2b9f4, 0xe78db00b, + 0xe7cd100a, 0xe08ea0b9, 0xe7b36004, 0xe7f6400d, + 0xe09760ba, 0xe1b600db, 0xe096a0fd, 0xe783700c, + 0xe7e83001, 0xe1cc44b0, 0xe51f1008, 0xe55f7008, + 0xe15f21b0, 0xe15fa0d8, 0xe1dfe3f8, 0xe51f2008, + 0xe55f3008, 0xe1df72bc, 0xe15fd0d8, 0xe15fa2fc, + 0xe51f5008, 0xe5dfe01c, 0xe1df51b8, 0xe15f63dc, + 0xe15fb4f0, 0xe59f700c, 0xe5df5008, 0xe15fa4bc, + 0xe1df60d0, 0xe15f90f8, 0xe690036a, 0xe7d8348e, + 0xe78d5783, 0xe6c99145, 0xe7945360, 0xe7d0e4a4, + 0xe68c52cc, 0xe7e13667, 0xe7b26063, 0xe7fe8842, + 0xe7a363e6, 0xe7c83502, 0xe79db40e, 0xe7fda20c, + 0xe789d142, 0xe7eb774e, 0xe19bcf9f, 0xe1dc4f9f, + 0xe1fbbf9f, 0xe18e1f97, 0xe1c4cf96, 0x21e74f96, + 0xe6143f17, 0xe61a9f33, 0xe615cf56, 0xe615cf7e, + 0xe61a0f97, 0x66180ff2, 0x5624bf15, 0x6623bf3c, + 0xe6230f55, 0xe61caf75, 0x3626af9e, 0xe62baff7, + 0x56349f1e, 0xe63e1f37, 0x363b9f55, 0xa6313f7b, + 0xc635df97, 0xe6351ff7, 0xe654af17, 0x26591f37, + 0xe65dbf57, 0xe654bf7e, 0x365d2f97, 0xc65a8ffe, + 0xe66c3f1d, 0xe66d4f36, 0xe66a1f5e, 0xd66d2f7e, + 0xe66c1f95, 0xc6640ffd, 0x867a0f15, 0xd674bf37, + 0xa67e1f59, 0xe67b2f7e, 0xa6749f95, 0x867d2ffe, + 0xe683a877, 0x26a59c77, 0xe6b53477, 0xe6c48476, + 0x06eb007d, 0xe6fc9075, 0xa68f387b, 0x86af2076, + 0xc6bf3c7d, 0xe6cfc875, 0xe6efc875, 0xe6ff8875, + 0x06bfaf34, 0xa6bf8fbc, 0xe6ffef37, 0xc6ffdfb7, + 0xe719fe1d, 0xe732f61c, 0x47a20a51, 0xe7ee9852, + 0x87dd1d9b, 0xe7d0339f, 0xe8060d6b, 0xe80438df, + 0xe810e1d4, 0xe83c9873, 0xe8a931bd, 0xe88b55c3, + 0xe8bcbd22, 0xe8bda10a, 0xe92b2219, 0xe9298dd5, + 0xe935605b, 0xe91191a7, 0xe9ab6e6a, 0xe98b4507, + 0xe9b053cc, 0xe9912de7, 0x2a000075, 0x4bfffffe, + 0x612fff10, 0xe12fff33, 0xeafffffe, 0xebfffffe, + 0x612fff10, 0xe12fff35, 0xda00006d, 0x4bfffffe, + 0x112fff19, 0xe12fff3c, 0xeafffedc, 0x8bfffffe, + 0x712fff11, 0xc12fff37, 0xaafffed8, 0x8bfffffe, + 0xe12fff1c, 0x312fff37, 0xeafffffe, 0xcbfffed3, + 0xa12fff11, 0xe12fff30, 0xeafffffe, 0xeb00005c, + 0xc12fff1e, 0x112fff3b, 0x2afffffe, 0xebfffffe, + 0x212fff1a, 0xe12fff34, 0xeafffec8, 0xebfffffe, + 0x312fff1c, 0xe12fff38, 0xea000051, 0xebfffffe, + 0xe12fff1a, 0xe12fff31, 0x4e042a06, 0xee052a45, + 0xee151a46, 0xbe134a04, 0x4e263a47, 0xee310a00, + 0xee321a45, 0x2e810a06, 0xee030b06, 0xee010b45, + 0xee141b46, 0x1e110b01, 0x1e253b45, 0x3e320b04, + 0xee321b44, 0x4e810b05, 0xeeb03ac3, 0x5eb13a44, + 0xeeb10ac4, 0xeeb00bc4, 0xeeb11b44, 0xeeb10bc1, + 0x5e00ea10, 0xee14ba10, 0xbc4ebb11, 0xec557b15, + 0xeeb04a46, 0x8eb01b42, 0x6eb72a00, 0xeeb72b00, + 0xeeb03a00, 0xeeb01b00, 0xed952a1d, 0x3d811a0e, + 0x1d957b04, 0xed816b39, 0xed9f1a0e, 0xed8f3a0d, + 0xbd1f2b04, 0xcd0f3b02, 0x3d9f2a0a, 0xed8f0a09, + 0xcd9f4b08, 0xed0f0b09, 0xed9f4a06, 0xed8f3a05, + 0x5d1f4b0c, 0xed0f5b0d, 0x9d9f4a02, 0x3d0f6a02, + 0xed9f6b00, 0xbd0f1b01, 0xec912a01, 0x2ca62a01, + 0xecb91b08, 0xeca36b04, 0x6d323a01, 0xed267a01, + 0xed3d4b08, 0xed205b06, 0xeeb41a41, 0x7eb44ac4, + 0xeeb40b46, 0xaeb43bc7, 0xbeb51a40, 0xceb57ac0, + 0xeeb54b40, 0xeeb51bc0, 0x6ebd1ac3, 0xcebc3ac7, + 0x3eb80ac1, 0x3eb81a42, 0x8ebd2bc4, 0x8ebc3bc6, + 0x9eb73bc7, 0xeeb83bc4, 0x0eb85b47, 0xeeb74ac5, + 0xe120017a, + }; +// END Generated code -- do not edit + + // reset the detected cpu feature set + VM_Version::features(detected_features); + + { + bool ok = true; + unsigned int *insns1 = (unsigned int *)entry; + for (unsigned int i = 0; i < sizeof insns / sizeof insns[0]; i++) { + if (insns[i] != insns1[i]) { + ok = false; + printf("Ours:\n"); + Disassembler::decode((address)&insns1[i], (address)&insns1[i+1]); + printf(" Raw: 0x%x\n", insns1[i]); + printf("Theirs:\n"); + Disassembler::decode((address)&insns[i], (address)&insns[i+1]); + printf(" Raw: 0x%x\n", insns[i]); + printf("\n"); + } + } + assert(ok, "Assembler smoke test failed"); + } +#endif // ASSERT +} + +#undef __ +void Address::AddressConstruct(Register base, RegisterOrConstant index, enum reg_op op, + shift_op shift, enum wb_mode mode) { + _base = base; + _wb_mode = mode; + _shift = shift; + _target = 0; + if (index.is_register()) { + _acc_mode = reg; + _index = index.as_register(); + _offset = 0; + _as_op = op; + } else { + assert(shift == lsl(), "should be"); + assert(index.is_constant(), "should be"); + _acc_mode = imm; + // _index = no_reg; + _offset = index.as_constant(); + if(SUB == _as_op) + _offset = -_offset; + } +} + +void Address::encode(Instruction_aarch32 *i, CodeSection *sec, address pc) const { + long offset = _offset; + access_mode mode = _acc_mode; + + if(lit == mode) { + //Create the offset from the address + offset = _target - pc; + mode = imm; + } + + //Correct the offset if the base is the PC + if(r15_pc == _base && imm == mode) { + offset -= 8; + } + + int U = (offset >= 0 && _acc_mode == imm) || (_as_op == ADD && _acc_mode == reg); + int P = pre == _wb_mode || off == _wb_mode; + int W = pre == _wb_mode; + i->f(P, 24), i->f(U, 23), i->f(W, 21), i->rf(_base, 16); + + offset = offset < 0 ? -offset : offset; + int opc = i->get(27, 25); + + if (imm == mode) { + switch(opc) { + case 0b010: + // LDR, LDRB + // STR, STRB + i->f(offset, 11, 0); + break; + case 0b000: + // LDRH, LDRSH, LDRSB, LDRD + // STRH, STRD + i->f(1, 22); + assert(offset < (1 << 8), "Offset larger than a byte"); + i->f(offset & 0xF, 3, 0); + i->f(offset >> 4, 11, 8); + break; + default: + ShouldNotReachHere(); + } + } else if (reg == mode) { + assert(r15_pc->encoding_nocheck() != + _base->encoding_nocheck(), "Remove this if you have your offsets right"); + switch(opc) { + case 0b010: + // LDR, LDRB + // STR, STRB + //Need to set bit 25 as Register 0b011 + i->f(1, 25); + i->f(_shift.shift(), 11, 7); + i->f(_shift.kind(), 6, 5); + i->f(0, 4); + i->rf(_index, 0); + break; + case 0b000: + // LDRH, LDRSH, LDRSB, LDRD + // STRH, STRD + //Need to clear bit 22 as Register + i->f(0, 22); + assert(_shift == lsl(), "Type of load/store does not support shift"); + i->f(0b0000, 11, 8); + i->rf(_index, 0); + break; + default: + ShouldNotReachHere(); + } + } else { + ShouldNotReachHere(); + } + + if(lit == _acc_mode) { + sec->relocate(pc, _rspec); + } +} + +void Address::fp_encode(Instruction_aarch32 *i, CodeSection *sec, address pc) const { + // ATM works only for immediate + assert(_wb_mode == off, "Can't do pre or post addressing for vldr, vstr"); + long offset = _offset; + if(imm == _acc_mode) { + if(r15_pc == _base) { + //Correct the offset if the base is the PC + offset -= 8; + } + bool U = offset >= 0; + assert(0 == (offset & 3), "Can only access aligned data"); + unsigned imm8 = uabs(offset) / 4; + i->f(U, 23), i->rf(_base, 16), i->f(imm8, 7, 0); + } else { + ShouldNotReachHere(); + } +} + +#define __ as-> +void Address::lea(MacroAssembler *as, Register r) const { + Relocation* reloc = _rspec.reloc(); + relocInfo::relocType rtype = (relocInfo::relocType) reloc->type(); + + //TODO Potentially remove this - added as aarch64 doesn't contain + // any method of handling pre or post + assert( _wb_mode != pre && _wb_mode != post, "Wrong wb mode"); + // could probably permit post however + switch(_acc_mode) { + case imm: { + if (_offset == 0 && _base == r) // it's a nop + break; + if (_offset > 0) + __ add(r, _base, _offset); + else + __ sub(r, _base, -_offset); + break; + } + case reg: { + switch (_as_op) { + case ADD: + __ add(r, _base, _index, _shift); + break; + case SUB: + __ sub(r, _base, _index, _shift); + break; + } + break; + } + case lit: { + if (rtype == relocInfo::none) + __ mov(r, target()); + else + __ movptr(r, (uint32_t)target()); + break; + } + default: + ShouldNotReachHere(); + } +} +#undef __ + +#define __ as-> +class Address; + +// Adapts given Address to the capabilities of instructions respective to the +// provided data type. E.g. some of the instructions cannot use index register +// while others cannot have an offset field. +// Returns a copy of this Address is it's good or constructs a new Address +// good for respective instructions by emitting necessary code to calculate +// the address in tmp register +Address Address::safe_for(InsnDataType type, MacroAssembler *as, Register tmp) { + if (is_safe_for(type)) + return *this; + assert(tmp->is_valid(), "must be"); + lea(as, tmp); + return Address(tmp); +} +#undef __ + +bool Address::is_safe_for(InsnDataType type) { + switch (_acc_mode) { + case imm: + case lit: + return offset_ok_for_immed(_offset, type); + case reg: + return shift_ok_for_index(_shift, type); + case no_mode: + default: + ShouldNotReachHere(); + return false; + } +} + + +bool Address::offset_ok_for_immed(long offset, InsnDataType type) { + const int o = offset < 0 ? -offset : offset; + switch (type) { + case IDT_INT: + case IDT_BOOLEAN: + case IDT_OBJECT: + case IDT_ADDRESS: + case IDT_METADATA: + case IDT_ARRAY: + return o <= 0xfff; + case IDT_BYTE: + case IDT_SHORT: + case IDT_LONG: + case IDT_CHAR: + return o <= 0xff; + case IDT_FLOAT: + case IDT_DOUBLE: + return !(o & ~0x3fc); + case IDT_LEA: + return true; + case IDT_ATOMIC: + case IDT_MULTIWORD: + return !o; + default: + ShouldNotReachHere(); + return false; + } +} + +bool Address::shift_ok_for_index(shift_op shift, InsnDataType type) { + switch (type) { + case IDT_INT: + case IDT_BOOLEAN: + case IDT_OBJECT: + case IDT_ADDRESS: + case IDT_METADATA: + case IDT_ARRAY: + return !shift.is_register(); + case IDT_BYTE: + case IDT_SHORT: + case IDT_LONG: + case IDT_CHAR: + return !shift.is_register() && shift.shift() == 0; + case IDT_LEA: + return true; + case IDT_FLOAT: + case IDT_DOUBLE: + case IDT_ATOMIC: + case IDT_MULTIWORD: + return false; + default: + ShouldNotReachHere(); + return false; + } +} + +void Assembler::emit_data64(jlong data, + relocInfo::relocType rtype, + int format) { + if (rtype == relocInfo::none) { + emit_int64(data); + } else { + emit_data64(data, Relocation::spec_simple(rtype), format); + } +} + +void Assembler::emit_data64(jlong data, + RelocationHolder const& rspec, + int format) { + + assert(inst_mark() != NULL, "must be inside InstructionMark"); + // Do not use AbstractAssembler::relocate, which is not intended for + // embedded words. Instead, relocate to the enclosing instruction. + code_section()->relocate(inst_mark(), rspec, format); + emit_int64(data); +} + +extern "C" { + void das(uint64_t start, int len) { + ResourceMark rm; + len <<= 2; + if (len < 0) + Disassembler::decode((address)start + len, (address)start); + else + Disassembler::decode((address)start, (address)start + len); + } + + JNIEXPORT void das1(unsigned long insn) { + das(insn, 1); + } +} + +#define starti Instruction_aarch32 do_not_use(this); set_current(&do_not_use) + + void Assembler::adr(Register Rd, address adr, Condition cond) { + int offset = adr - pc() - 8; + adr_encode(Rd, offset, cond); + } + +#undef starti + +Address::Address(address target, relocInfo::relocType rtype) + : _acc_mode(lit), _base(sp), _offset(0), _wb_mode(off) { + //TODO we don't complete _wb_mode - what about Addresses that are pre/post accessed? + _is_lval = false; + _target = target; + switch (rtype) { + case relocInfo::oop_type: + case relocInfo::metadata_type: + // Oops are a special case. Normally they would be their own section + // but in cases like icBuffer they are literals in the code stream that + // we don't have a section for. We use none so that we get a literal address + // which is always patchable. + break; + case relocInfo::external_word_type: + _rspec = external_word_Relocation::spec(target); + break; + case relocInfo::internal_word_type: + _rspec = internal_word_Relocation::spec(target); + break; + case relocInfo::opt_virtual_call_type: + _rspec = opt_virtual_call_Relocation::spec(); + break; + case relocInfo::static_call_type: + _rspec = static_call_Relocation::spec(); + break; + case relocInfo::runtime_call_type: + _rspec = runtime_call_Relocation::spec(); + break; + case relocInfo::poll_type: + case relocInfo::poll_return_type: + _rspec = Relocation::spec_simple(rtype); + break; + case relocInfo::none: + _rspec = RelocationHolder::none; + break; + default: + ShouldNotReachHere(); + break; + } +} + +#ifdef COMPILER2 +Address Address::make_raw(int base, int index, int scale, unsigned long o, relocInfo::relocType disp_reloc) { + RelocationHolder rspec; + if (disp_reloc != relocInfo::none) { + rspec = Relocation::spec_simple(disp_reloc); + } + if (as_Register(index) == r15_pc) { + assert(scale == 0, "unsupported"); + Address a(as_Register(base), o); + a._rspec = rspec; + return a; + } else { + assert(o == 0, "unsupported"); + Address a(as_Register(base), as_Register(index), lsl(scale)); + a._rspec = rspec; + return a; + } +} +#endif + +void Assembler::adr(Register r, const Address &dest, Condition cond) { + code_section()->relocate(pc(), dest.rspec()); + adr(r, dest.target()); +} + +void Assembler::wrap_label(Label &L, Assembler::uncond_branch_insn insn) { + if (L.is_bound()) { + (this->*insn)(target(L)); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(pc()); + } +} +void Assembler::wrap_label(Label &L, Condition cond, + Assembler::cond_branch_insn insn) { + if (L.is_bound()) { + (this->*insn)(target(L), cond); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(pc(), cond); + } +} + +void Assembler::wrap_label(Register r, Label &L, Condition cond, + Assembler::cond_ldst_insn insn) { + if (L.is_bound()) { + (this->*insn)(r, target(L), cond); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(r, pc(), cond); + } +} + + +void Assembler::wrap_label(FloatRegister r, Label &L, Condition cond, + Assembler::cond_fp_ldst_insn insn) { + if (L.is_bound()) { + (this->*insn)(r, target(L), cond); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(r, pc(), cond); + } +} + + +uint32_t Assembler::encode_imm12(int imm) { + assert(is_valid_for_imm12(imm), + "only valid immediates allowed, call is_valid_for_imm12 first"); + uint32_t n = imm; + if ((n & 0xFFFFFF00) == 0) { + return n; + } + if ((n & 0xFC000000) == 0) { + const int lshift = __builtin_ctz(n) & 0xFFFFFFFE; + return ((32 - lshift) << 7) | (n >> lshift); + } + n = (n << 16) | (n >> 16); + const int lshift = __builtin_ctz(n) & 0xFFFFFFFE; + return ((16 - lshift) << 7) | (n >> lshift); +} + +int Assembler::decode_imm12(uint32_t imm12) { + assert((imm12 & 0xFFFFF000) == 0, "bad imm12"); + uint32_t shift = (imm12 & 0x00000F00) >> 7; + uint32_t value = imm12 & 0x000000FF; + return (int) ((value >> shift) | (value << (32 - shift))); +} + +bool Assembler::is_valid_for_imm12(int imm) { + uint32_t n = (uint32_t) imm; + uint32_t shift = __builtin_clz(n) & 0xFFFFFFFE; + uint32_t result = n << shift; + if ((result & 0x00FFFFFF) == 0) { + return true; + } + n = (n << 16) | (n >> 16); + shift = __builtin_clz(n) & 0xFFFFFFFE; + result = n << shift; + if ((result & 0x00FFFFFF) == 0) { + return true; + } + return false; +} + +bool Assembler::operand_valid_for_logical_immediate(bool is32, uint64_t imm) { + return is32 && is_valid_for_imm12(imm); +} + +bool Assembler::operand_valid_for_add_sub_immediate(int imm) { + return is_valid_for_imm12(imm); +} + +bool Assembler::operand_valid_for_add_sub_immediate(unsigned long imm) { + return is_valid_for_imm12(imm); +} + +bool Assembler::operand_valid_for_add_sub_immediate(unsigned imm) { + return is_valid_for_imm12(imm); +} + +bool Assembler::operand_valid_for_add_sub_immediate(jlong imm) { + return is_valid_for_imm12(imm >> 32) && is_valid_for_imm12(imm); +} + +// n.b. this is implemented in subclass MacroAssembler +void Assembler::bang_stack_with_offset(int offset) { Unimplemented(); } + +int AbstractAssembler::code_fill_byte() { + return 0; +} + +void Assembler::mov_immediate(Register dst, uint32_t imm32, Condition cond, bool s) { +#ifndef PRODUCT + { + char buffer[64]; + snprintf(buffer, sizeof(buffer), "0x%"PRIX32, imm32); + block_comment(buffer); + } +#endif + if(is_valid_for_imm12(imm32)) { + if(s) movs_i(dst, (unsigned)imm32, cond); + else mov_i (dst, (unsigned)imm32, cond); + } else if(is_valid_for_imm12(~imm32)) { + if(s) mvns_i(dst, (unsigned)~imm32, cond); + else mvn_i (dst, (unsigned)~imm32, cond); + } else if (!s && VM_Version::features() & (FT_ARMV7 | FT_ARMV6T2) && + (imm32 < (1 << 16))) { + movw_i(dst, (unsigned)imm32, cond); + } else if (!s && VM_Version::features() & (FT_ARMV7 | FT_ARMV6T2) && + !(imm32 & ((1 << 16) - 1))) { + movw_i(dst, (unsigned)0, cond); + movt_i(dst, (unsigned)(imm32 >> 16), cond); + } else { // TODO Could expand to varied numbers of mov and orrs + //Need to do a full 32 bits + mov_immediate32(dst, imm32, cond, s); + } +} + +//This should really be in the macroassembler +void Assembler::mov_immediate32(Register dst, uint32_t imm32, Condition cond, bool s) +{ + // Need to move a full 32 bit immediate, for example if we're loading an address that + // might change later and therefore need to be updated. + if (VM_Version::features() & (FT_ARMV7 | FT_ARMV6T2)) { + //Use a movw and a movt + Assembler::movw_i(dst, (unsigned)(imm32 & 0xffff), cond); + Assembler::movt_i(dst, (unsigned)(imm32 >> 16), cond); + if(s) { + //Additionally emit a cmp instruction + Assembler::cmp(dst, 0); + } + } else { + // Sadly we don't have movw, movt + // instead emit a mov and three orr + mov_i(dst, imm32 & (0xff ), cond); + orr(dst, dst, imm32 & (0xff << 8 ), cond); + orr(dst, dst, imm32 & (0xff << 16), cond); + if(s) orrs(dst, dst, imm32 & (0xff << 24), cond); + else orr (dst, dst, imm32 & (0xff << 24), cond); + } +} + +#define starti Instruction_aarch32 do_not_use(this); set_current(&do_not_use) +void Assembler::add_sub_imm(int decode, Register Rd, Register Rn, int imm, + Condition cond, bool s) { + int cpart = 0; + switch(decode) { + case 0b0100: cpart = 0b0010; break; // ADD -> SUB + case 0b0010: // SUB -> ADD + case 0b0011: cpart = 0b0100; break; // RSB -> ADD + case 0b0101: cpart = 0b0110; break; // ADC -> SUBC + case 0b0110: // SUBC -> ADC + case 0b0111: cpart = 0b0101; break; // RSC -> ADC + default: ShouldNotReachHere(); + } + //try both possible imm_instrs + if(imm_instr(decode, Rd, Rn, imm, cond, s)) return; + if(imm_instr(cpart, Rd, Rn, -imm, cond, s)) return; + + //Try plan B - a mov first - need to have destination that is not an arg + assert(Rd != Rn, "Can't use imm and can't do a mov. I'm in a jam."); + mov_immediate(Rd, (uint32_t)uabs(imm), cond, s); + //Now do the non immediate version - copied from the immediate encodings + { + starti; + reg_instr( imm < 0 ? cpart : decode, lsl(), cond, s); + rf(Rn, 16), rf(Rd, 12), rf(Rd, 0); + } +} + +bool Assembler::can_ldst_multiple( unsigned regset, const Address& adr) { + int nbits = count_bits(regset); + return adr.get_mode() == Address::imm && + !(adr.base()->bit() & regset) && // FIXME, this could be relaxed + (((adr.offset() == 0 || adr.offset() == wordSize || adr.offset() == -nbits * wordSize) && + (adr.get_wb_mode() == Address::pre || adr.get_wb_mode() == Address::off)) || + ((adr.offset() == 0 || adr.offset() == -wordSize || adr.offset() == nbits * wordSize) && + adr.get_wb_mode() == Address::post)); +} + +unsigned Assembler::count_bits(unsigned val) { + unsigned i, count; + for(i = 0, count = 0; i < 8 * sizeof(val); val >>= 1, i++) + if( val & 1 ) count++; + return count; +} + + +void Assembler::vmov_imm(FloatRegister Rd, unsigned imm, bool is64bit, + Condition cond) { + starti; + fp_instr_base(is64bit, cond); + f(0b1011, 23, 20); + // double register passed (see 'd0'-'dN' encoding), not reencode it's number + fp_rencode(Rd, false, 12, 22); + f(0b0000, 7, 4); + f(imm & 0xf, 3, 0); + f(imm >> 4, 19, 16); +} + +void Assembler::vmov_imm(FloatRegister Rd, unsigned imm) { + assert(operand_valid_for_double_immediate(0), "operand should be valid for immediate"); + int cmod = 0b0000; + { + starti; + f(0b1111001, 31, 25); + f(0, 24); // imm1 + f(0b10000, 23, 19); + // double register passed (see 'd0'-'dN' encoding), not reencode it's number + fp_rencode(Rd, false, 12, 22); + f(cmod, 11, 8); + f(0b000, 7, 5); + f(1, 4); + f(imm & 0xf, 3, 0); //imm4 + f(imm >> 4, 18, 16); //imm3 + } +} + +void Assembler::vmov_imm_zero(FloatRegister Rd, bool is64bit, + Condition cond) { + // Note that this is not a floating point vmov but instead + // an integer vmov from the SIMD instructions. + // cannot be conditional. + assert(operand_valid_for_double_immediate(0), "operand should be valid for immediate"); + assert(is64bit, "SIMD loading available only for double registers"); + assert(cond == C_DFLT, "Unable to vmov #0 conditionally"); + //int cmod = is64bit? 0b1110 : 0b0000; // ? I64 : I32 + int cmod = 0b1110; + { + starti; + f(0b1111001, 31, 25); + f(0, 24); // imm1 + f(0b10000, 23, 19); + // double register passed (see 'd0'-'dN' encoding), not reencode it's number + fp_rencode(Rd, false, 12, 22); + f(0b000, 18, 16); //imm3 + f(cmod, 11, 8); + f(0b00, 7, 6); + f(is64bit, 5); + f(1, 4); + f(0b0000, 3, 0); //imm4 + } +} + +bool Assembler::operand_valid_for_float_immediate(float v) { + if (!(VM_Version::features() & FT_VFPV3)) { + return false; + } + union ufloat { + float f; + uint32_t u; + } imm; + unsigned tmp; + imm.f = v; + + if (imm.u & ((1 << 19) - 1)) + return false; + + tmp = (imm.u >> 25) & ((1 << 6) - 1); + return tmp == 32 || tmp == 31; +} + +bool Assembler::operand_valid_for_double_immediate(double v) { + if (!(VM_Version::features() & FT_VFPV3)) { + return false; + } + union ufloat { + double f; + uint64_t u; + } imm; + unsigned tmp; + imm.f = v; + + if ((VM_Version::features() & FT_AdvSIMD) && imm.u == 0) + return true; + + if (imm.u & (uint64_t) 0xffffffffffffLL) + return false; + + imm.u >>= 48; + + tmp = (imm.u >> 6) & ((1 << 9) - 1); + return tmp == 0x100 || tmp == 0xff; +} + +unsigned Assembler::encode_float_fp_imm(float imm_f) { + assert(operand_valid_for_float_immediate(imm_f), "operand should be valid for immediate"); + union ufloat { + float f; + uint32_t u; + } imm; + unsigned tmp, imm8; + imm.f = imm_f; + + assert(!(imm.u & ((1 << 19) - 1)), "Invalid float imm"); + tmp = (imm.u >> 25) & ((1 << 6) - 1); + assert(tmp == 32 || tmp == 31, "Invalid float imm"); + + imm8 = (imm.u >> 24) & 0x80; // set a + imm8 |= (imm.u >> 19) & 0x7F; // set bcdefgh + return imm8; +} + +unsigned Assembler::encode_double_fp_imm(double imm_f) { + assert(operand_valid_for_double_immediate(imm_f), "operand should be valid for immediate"); + union ufloat { + double f; + uint64_t u; + } imm; + unsigned tmp, imm8; + imm.f = imm_f; + + assert(!(imm.u & (uint64_t)0xffffffffffffLL), "Invalid float imm"); + imm.u >>= 48; + + tmp = (imm.u >> 6) & ((1 << 9) - 1); + assert(tmp == 0x100 || tmp == 0xff, "Invalid float imm"); + + imm8 = (imm.u >> 8) & 0x80; // set a + imm8 |= imm.u & 0x7F; // set bcdefgh + return imm8; +} + + +void Assembler::fp_ldst_instr(int decode, bool is64bit, const Address& adr, + Condition cond) { + f(cond, 31, 28), f(0b110, 27, 25), f(decode, 24, 20); + f(0b101, 11, 9), f(is64bit, 8); + adr.fp_encode(current, code_section(), pc()); +} + +void Assembler::fp_ldst_mul(Register Rn, uint32_t regset, bool load, bool is64bit, + enum fp_mode mode, Condition cond) { + starti; + bool P = db_wb == mode; + bool U = ia_wb == mode || ia == mode; + bool W = ia_wb == mode || db_wb == mode; + // Encode registers + unsigned i, fp_first_reg, nregs = 1; + bool enc_z = false; + for(fp_first_reg = 0; !(regset & 1); regset >>= 1, fp_first_reg++); + FloatRegister Rd = (FloatRegister) fp_first_reg; + for(i = 0; i + fp_first_reg < 8 * sizeof(int); i++) { + regset >>= 1; + if(regset & 1) { + assert(!enc_z, "Unable to encode non-consecutive registers in fp_ldst_mul"); + nregs++; + } else { + enc_z = true; + } + } + assert(!is64bit || nregs <= 16, "Too many registers in a set"); + f(cond, 31, 28), f(0b110, 27, 25); f(P, 24), f(U, 23), f(W, 21), f(load, 20); + // vstm/vstm uses double register number, not it's encoding. Should reencode it. + rf(Rn, 16), fp_rencode(Rd, is64bit, 12, 22), f(0b101, 11, 9), f(is64bit, 8); + f(is64bit ? nregs * 2 : nregs, 7, 0); +} + +void Assembler::simd_ldst(FloatRegister Rd, unsigned type, unsigned size, unsigned num_regs, + const Address &addr, enum SIMD_Align align, unsigned encode) { + starti; + assert(addr.get_mode() == Address::imm && + (addr.get_wb_mode() == Address::off && addr.offset() == 0) || + (addr.get_wb_mode() == Address::post && addr.offset() == long(8*num_regs)), "Unsupported"); + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + f(0b1111, 31, 28), f(0b0100, 27, 24), f(0, 23), f(encode, 21, 20); + rf(addr.base(), 16), fp_rencode(Rd, false, 12, 22), f(type, 11, 8), f(size, 7, 6); + f((unsigned)align, 5, 4), f(addr.get_wb_mode() == Address::post ? 0b1101 : 0b1111, 3, 0); +} + +void Assembler::simd_ldst_single(FloatRegister Rd, unsigned size, unsigned index, + const Address &addr, bool align, unsigned encode) { + starti; + assert(addr.get_mode() == Address::imm && + (addr.get_wb_mode() == Address::off && addr.offset() == 0) || + (addr.get_wb_mode() == Address::post && addr.offset() == long(1<>2)&3, 22, 21), f(bit20, 20); + fp_rencode(Dd, false, 16, 7), f(opc>>4, 23); + rf(Rt, 12), f(0b1011, 11, 8), f(opc & 3, 6, 5), f(0b10000, 4, 0); +} + +void Assembler::simd_logicalop(FloatRegister Dd, FloatRegister Dn, FloatRegister Dm, unsigned q, + unsigned a, unsigned b, unsigned u, unsigned c) { + starti; + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + assert(!q || ((Dd->encoding() & 2) == 0 && (Dm->encoding() & 2) == 0), "Odd registers"); + f(0b1111001, 31, 25), f(u, 24), f(0, 23), f(c, 21, 20), fp_rencode(Dd, false, 12, 22); + fp_rencode(Dn, false, 16, 7), f(a, 11, 8), fp_rencode(Dm, false, 0, 5), f(q, 6), f(b, 4); +} + +void Assembler::simd_vmul(FloatRegister Dd, FloatRegister Dn, FloatRegister Dm, + unsigned bit24, unsigned bits109, unsigned size, unsigned mul, unsigned bit6) { + starti; + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + f(0b1111001, 31, 25), f(bit24, 24), f(size, 21, 20), fp_rencode(Dd, false, 12, 22); + f(mul^1, 23), fp_rencode(Dn, false, 16, 7), f(1, 11), f(bits109, 10, 9); + f(mul, 8), f(bit6, 6), f(mul, 4), fp_rencode(Dm, false, 0, 5); +} + +void Assembler::simd_vuzp(FloatRegister Dd, FloatRegister Dm, unsigned size, unsigned q) { + starti; + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + assert(!q || ((Dd->encoding() & 2) == 0 && (Dm->encoding() & 2) == 0), "Odd registers"); + f(0b111100111, 31, 23), fp_rencode(Dd, false, 12, 22), f(0b11, 21, 20), f(size, 19, 18); + f(0b10, 17, 16), f(0b00010, 11, 7), f(q, 6), f(0, 4), fp_rencode(Dm, false, 0, 5); +} + +void Assembler::simd_vshl(FloatRegister Dd, FloatRegister Dm, unsigned imm, + unsigned q, unsigned u, unsigned encode) { + starti; + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + assert(!q || ((Dd->encoding() & 2) == 0 && (Dm->encoding() & 2) == 0), "Odd registers"); + f(0b1111001, 31, 25), f(u, 24), f(1, 23), fp_rencode(Dd, false, 12, 22); + f(imm & 0b111111, 21, 16), f(imm >> 6, 7), f(q, 6); + f(encode, 11, 8), fp_rencode(Dm, false, 0, 5), f(1, 4); +} + +void Assembler::simd_vshl(FloatRegister Dd, FloatRegister Dm, FloatRegister Dn, unsigned size, + unsigned q, unsigned u) { + starti; + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + assert(!q || ((Dd->encoding() & 2) == 0 && (Dm->encoding() & 2) == 0), "Odd registers"); + f(0b1111001, 31, 25), f(u, 24), f(0b0, 23), f(size, 21, 20), fp_rencode(Dn, false, 16, 7); + fp_rencode(Dd, false, 12, 22), f(0b0100, 11, 8), f(q, 6), fp_rencode(Dm, false, 0, 5), f(0, 4); +} + +// Two registers miscellaneous +void Assembler::simd_insn(FloatRegister Dd, FloatRegister Dm, unsigned q, unsigned a, + unsigned b, unsigned size) { + starti; + assert(!q || ((Dd->encoding() & 2) == 0 && (Dm->encoding() & 2) == 0), "Odd registers"); + f(0b111100111, 31, 23), fp_rencode(Dd, false, 12, 22), f(0b11, 21, 20); + f(size, 19, 18), f(a, 17, 16), f(0b0, 11), f(b, 10, 6); + fp_rencode(Dm, false, 0, 5), f(0, 4); +} + +void Assembler::simd_cnt(FloatRegister Dd, FloatRegister Dm, unsigned q) { + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + starti; + assert(!q || ((Dd->encoding() & 2) == 0 && (Dm->encoding() & 2) == 0), "Odd registers"); + f(0b111100111, 31, 23), fp_rencode(Dd, false, 12, 22), f(0b110000, 21, 16); + f(0b01010, 11, 7), f(q, 6), fp_rencode(Dm, false, 0, 5), f(0b0, 4); +} + +void Assembler::simd_padl(FloatRegister Dd, FloatRegister Dm, unsigned q, unsigned size, + unsigned op, unsigned encode) { + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + starti; + assert(!q || ((Dd->encoding() & 2) == 0 && (Dm->encoding() & 2) == 0), "Odd registers"); + assert(size != 0b11, "unsupported"); + f(0b111100111, 31, 23), f(0b11, 21, 20), f(0b00, 17, 16), f(0b0, 11); + fp_rencode(Dd, false, 12, 22), f(0b0, 4), fp_rencode(Dm, false, 0, 5); + f(size, 19, 18), f(op, 7), f(q, 6), f(encode, 10, 8); +} + +void Assembler::simd_dup(FloatRegister Dd, Register Rt, unsigned q, unsigned size) { + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + assert(size != 0b11, "must be"); + assert(!q || (Dd->encoding() & 2) == 0, "Odd register"); + starti; + f(0b111011101, 31, 23), f(size >> 1, 22), f(q, 21), f(0, 20), fp_rencode(Dd, false, 16, 7); + rf(Rt, 12), f(0b1011, 11, 8), f(size & 1, 6, 5), f(0b10000, 4, 0); +} + +void Assembler::simd_dup(FloatRegister Dd, FloatRegister Dm, unsigned index, unsigned q, unsigned size) { + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + assert(size != 0b11, "must be"); + assert(!q || ((Dd->encoding() & 2) == 0 && (Dm->encoding() & 2) == 0), "Odd registers"); + starti; + f(0b111100111, 31, 23), fp_rencode(Dd, false, 12, 22), f(0b11, 21, 20); + f(((index<<1)|1)<<(2-size), 19, 16), f(0b11000, 11, 7), f(q, 6), fp_rencode(Dm, false, 0, 5), f(0b0, 4); +} + +void Assembler::simd_neg(FloatRegister Dd, FloatRegister Dm, unsigned q, unsigned size) { + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + assert(size != 0b11, "must be"); + assert(!q || ((Dd->encoding() & 2) == 0 && (Dm->encoding() & 2) == 0), "Odd registers"); + starti; + f(0b111100111, 31, 23), fp_rencode(Dd, false, 12, 22), f(0b11, 21, 20), f(size, 19, 18); + f(0b01, 17, 16), f(0b00111, 11, 7), f(q, 6), fp_rencode(Dm, false, 0, 5), f(0b0, 4); +} + +void Assembler::simd_vmov(FloatRegister Dd, unsigned imm, unsigned q, unsigned op_cmode) { + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + assert(!q || (Dd->encoding() & 2) == 0, "Odd register"); + assert(!(imm >> 8), "must be imm8"); + starti; + f(0b1111001, 31, 25), f(imm>>7, 24), f(0b1, 23), fp_rencode(Dd, false, 12, 22); + f(0b000, 21, 19), f((imm>>4)&0x7, 18, 16), f(op_cmode&0xf, 11, 8), f(0b0, 7); + f(q, 6); f(op_cmode>>4, 5), f(0b1, 4), f(imm&0xf, 3, 0); +} + +void Assembler::simd_insn(FloatRegister Dd, FloatRegister Dn, FloatRegister Dm, + unsigned q, unsigned a, unsigned b, unsigned u, unsigned c) { + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + assert(!q || (Dd->encoding() & 2) == 0, "Odd register"); + starti; + f(0b1111001, 31, 25), f(u, 24), f(0b0, 23), f(c, 21, 20), f(a, 11, 8), f(b, 4), f(q, 6); + fp_rencode(Dn, false, 16, 7), fp_rencode(Dd, false, 12, 22), fp_rencode(Dm, false, 0, 5); +} + +void Assembler::simd_mvn(FloatRegister Dd, FloatRegister Dm, unsigned q) { + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + starti; + f(0b111100111, 31, 23), fp_rencode(Dd, false, 12, 22), f(0b11, 21, 20), f(0b00, 19, 18); + f(0b00, 17, 16), f(0b01011, 11, 7), f(q, 6), fp_rencode(Dm, false, 0, 5), f(0b0, 4); +} + +void Assembler::simd_insn(FloatRegister Dd, FloatRegister Dn, FloatRegister Dm, + unsigned qn, unsigned a, unsigned b, unsigned u) { + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + assert((Dd->encoding() & 2) == 0, "Odd register"); + assert(!qn || (Dn->encoding() & 2) == 0, "Odd operand register"); + starti; + f(0b1111001, 31, 25), f(u, 24), f(0b1, 23), f(b, 21, 20), f(a, 11, 8), f(0b0, 4), f(0b0, 6); + fp_rencode(Dn, false, 16, 7), fp_rencode(Dd, false, 12, 22), fp_rencode(Dm, false, 0, 5); +} + +void Assembler::simd_vext(FloatRegister Dd, FloatRegister Dn, FloatRegister Dm, unsigned q, unsigned imm) { + assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required"); + assert(!q || ((Dd->encoding() & 2) == 0 && (Dn->encoding() & 2) == 0 && (Dm->encoding() & 2) == 0), "Odd register"); + starti; + f(0b111100101, 31, 23), f(0b11, 21, 20), f(imm, 11, 8), f(q, 6), f(0b0, 4); + fp_rencode(Dn, false, 16, 7), fp_rencode(Dd, false, 12, 22), fp_rencode(Dm, false, 0, 5); +} + +#undef starti