/*
 * 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.
 * 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 <stdio.h>
#include <sys/types.h>

#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.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");
  // }

#ifdef ASSERT
  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 <back>:
   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 <near>:
 288:   e51f1008        ldr     r1, [pc, #-8]   ; 288 <near>
 28c:   e55f7008        ldrb    r7, [pc, #-8]   ; 28c <near+0x4>
 290:   e15f21b0        ldrh    r2, [pc, #-16]  ; 288 <near>
 294:   e15fa0d8        ldrsb   sl, [pc, #-8]   ; 294 <near+0xc>
 298:   e1dfe3f8        ldrsh   lr, [pc, #56]   ; 2d8 <near_post>
 29c:   e51f2008        ldr     r2, [pc, #-8]   ; 29c <near+0x14>
 2a0:   e55f3008        ldrb    r3, [pc, #-8]   ; 2a0 <near+0x18>
 2a4:   e1df72bc        ldrh    r7, [pc, #44]   ; 2d8 <near_post>
 2a8:   e15fd0d8        ldrsb   sp, [pc, #-8]   ; 2a8 <near+0x20>
 2ac:   e15fa2fc        ldrsh   sl, [pc, #-44]  ; 288 <near>
 2b0:   e51f5008        ldr     r5, [pc, #-8]   ; 2b0 <near+0x28>
 2b4:   e5dfe01c        ldrb    lr, [pc, #28]   ; 2d8 <near_post>
 2b8:   e1df51b8        ldrh    r5, [pc, #24]   ; 2d8 <near_post>
 2bc:   e15f63dc        ldrsb   r6, [pc, #-60]  ; 288 <near>
 2c0:   e15fb4f0        ldrsh   fp, [pc, #-64]  ; 288 <near>
 2c4:   e59f700c        ldr     r7, [pc, #12]   ; 2d8 <near_post>
 2c8:   e5df5008        ldrb    r5, [pc, #8]    ; 2d8 <near_post>
 2cc:   e15fa4bc        ldrh    sl, [pc, #-76]  ; 288 <near>
 2d0:   e1df60d0        ldrsb   r6, [pc]        ; 2d8 <near_post>
 2d4:   e15f90f8        ldrsh   r9, [pc, #-8]   ; 2d4 <near+0x4c>

000002d8 <near_post>:
 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 <forth>
 45c:   4bfffffe        blmi    45c <near_post+0x184>
 460:   612fff10        bxvs    r0
 464:   e12fff33        blx     r3
 468:   eafffffe        b       468 <near_post+0x190>
 46c:   ebfffffe        bl      46c <near_post+0x194>
 470:   612fff10        bxvs    r0
 474:   e12fff35        blx     r5
 478:   da00006d        ble     634 <forth>
 47c:   4bfffffe        blmi    47c <near_post+0x1a4>
 480:   112fff19        bxne    r9
 484:   e12fff3c        blx     ip
 488:   eafffedc        b       0 <back>
 48c:   8bfffffe        blhi    48c <near_post+0x1b4>
 490:   712fff11        bxvc    r1
 494:   c12fff37        blxgt   r7
 498:   aafffed8        bge     0 <back>
 49c:   8bfffffe        blhi    49c <near_post+0x1c4>
 4a0:   e12fff1c        bx      ip
 4a4:   312fff37        blxcc   r7
 4a8:   eafffffe        b       4a8 <near_post+0x1d0>
 4ac:   cbfffed3        blgt    0 <back>
 4b0:   a12fff11        bxge    r1
 4b4:   e12fff30        blx     r0
 4b8:   eafffffe        b       4b8 <near_post+0x1e0>
 4bc:   eb00005c        bl      634 <forth>
 4c0:   c12fff1e        bxgt    lr
 4c4:   112fff3b        blxne   fp
 4c8:   2afffffe        bcs     4c8 <near_post+0x1f0>
 4cc:   ebfffffe        bl      4cc <near_post+0x1f4>
 4d0:   212fff1a        bxcs    sl
 4d4:   e12fff34        blx     r4
 4d8:   eafffec8        b       0 <back>
 4dc:   ebfffffe        bl      4dc <near_post+0x204>
 4e0:   312fff1c        bxcc    ip
 4e4:   e12fff38        blx     r8
 4e8:   ea000051        b       634 <forth>
 4ec:   ebfffffe        bl      4ec <near_post+0x214>
 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 <near_flt>:
 588:   ed9f1a0e        vldr    s2, [pc, #56]   ; 5c8 <near_post_flt>
 58c:   ed8f3a0d        vstr    s6, [pc, #52]   ; 5c8 <near_post_flt>
 590:   bd1f2b04        vldrlt  d2, [pc, #-16]  ; 588 <near_flt>
 594:   cd0f3b02        vstrgt  d3, [pc, #-8]   ; 594 <near_flt+0xc>
 598:   3d9f2a0a        vldrcc  s4, [pc, #40]   ; 5c8 <near_post_flt>
 59c:   ed8f0a09        vstr    s0, [pc, #36]   ; 5c8 <near_post_flt>
 5a0:   cd9f4b08        vldrgt  d4, [pc, #32]   ; 5c8 <near_post_flt>
 5a4:   ed0f0b09        vstr    d0, [pc, #-36]  ; 588 <near_flt>
 5a8:   ed9f4a06        vldr    s8, [pc, #24]   ; 5c8 <near_post_flt>
 5ac:   ed8f3a05        vstr    s6, [pc, #20]   ; 5c8 <near_post_flt>
 5b0:   5d1f4b0c        vldrpl  d4, [pc, #-48]  ; 588 <near_flt>
 5b4:   ed0f5b0d        vstr    d5, [pc, #-52]  ; 588 <near_flt>
 5b8:   9d9f4a02        vldrls  s8, [pc, #8]    ; 5c8 <near_post_flt>
 5bc:   3d0f6a02        vstrcc  s12, [pc, #-8]  ; 5bc <near_flt+0x34>
 5c0:   ed9f6b00        vldr    d6, [pc]        ; 5c8 <near_post_flt>
 5c4:   bd0f1b01        vstrlt  d1, [pc, #-4]   ; 5c8 <near_post_flt>

000005c8 <near_post_flt>:
 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: {
    __ add(r, _base, _index, _shift);
    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_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_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;
  }
}

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);
  }
}

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_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;
}

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;
}
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));
}

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, int 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_ld(FloatRegister Rd, unsigned type, unsigned size, unsigned num_regs,
        const Address &addr, enum SIMD_Align align) {
  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");
  if (addr.get_wb_mode() == Address::post)
  f(0b1111, 31, 28), f(0b0100, 27, 24), f(0, 23), f(0b10, 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_vmov(FloatRegister Dd, unsigned index, Register Rt, bool advsimd,
          unsigned index_bits, unsigned bit20, unsigned opc, Condition cond) {
  starti;
  assert(index < (1u<<index_bits), "Illegal element index");
  assert(!advsimd || (VM_Version::features() & FT_AdvSIMD), "SIMD coprocessor required");
  opc |= index << (3 - index_bits);
  f(cond, 31, 28), f(0b1110, 27, 24), f((opc>>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_eor(FloatRegister Dd, FloatRegister Dn, FloatRegister Dm, 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(0b111100110, 31, 23), f(0b00, 21, 20), fp_rencode(Dd, false, 12, 22);
  fp_rencode(Dn, false, 16, 7), f(0b0001, 11, 8), fp_rencode(Dm, false, 0, 5), f(q, 6), f(1, 4);
}

void Assembler::simd_vmul(FloatRegister Dd, FloatRegister Dn, FloatRegister Dm,
          unsigned bit24, unsigned bit9, 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(mul^1, 10), f(bit9, 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 size,
        unsigned q, unsigned bit24, unsigned encode) {
  starti;
  assert(VM_Version::features() & FT_AdvSIMD, "SIMD coprocessor required");
  assert(imm < (1u << size), "Shift is too big");
  assert(!q || ((Dd->encoding() & 2) == 0 && (Dm->encoding() & 2) == 0), "Odd registers");
  f(0b1111001, 31, 25), f(bit24, 24), f(1, 23), fp_rencode(Dd, false, 12, 22);
  f(((1u << size) | imm) & 0b111111, 21, 16), f(size == 6 ? 1 : 0, 7), f(q, 6);
  f(encode, 11, 8), fp_rencode(Dm, false, 0, 5), f(1, 4);
}

void Assembler::simd_rev(FloatRegister Dd, FloatRegister Dm, unsigned q, unsigned size,
          unsigned op) {
  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(0b00, 17, 16), f(0b000, 11, 9), f(op, 8, 7);
  f(q, 6), fp_rencode(Dm, false, 0, 5), f(0, 4);
}

void Assembler::v8_crc32(Register Rd, Register Rn, Register Rm, unsigned size, Condition cond) {
  starti;
  assert(VM_Version::features() & FT_CRC32, "Instruction is not supported by CPU");
  f(cond, 31, 28), f(0b00010, 27, 23), f(size, 22, 21), f(0, 20), rf(Rn, 16), rf(Rd, 12);
  f(0b00000100, 11, 4), rf(Rm, 0);
}

#undef starti
