12bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind/* libs/pixelflinger/codeflinger/MIPSAssembler.cpp
22bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
32bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** Copyright 2012, The Android Open Source Project
42bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
52bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** Licensed under the Apache License, Version 2.0 (the "License");
62bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** you may not use this file except in compliance with the License.
72bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** You may obtain a copy of the License at
82bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
92bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**     http://www.apache.org/licenses/LICENSE-2.0
102bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
112bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** Unless required by applicable law or agreed to in writing, software
122bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** distributed under the License is distributed on an "AS IS" BASIS,
132bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
142bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** See the License for the specific language governing permissions and
152bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** limitations under the License.
162bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind*/
172bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
182bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
192bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind/* MIPS assembler and ARM->MIPS assembly translator
202bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
212bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** The approach is to leave the GGLAssembler and associated files largely
222bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** un-changed, still utilizing all Arm instruction generation. Via the
232bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** ArmToMipsAssembler (subclassed from ArmAssemblerInterface) each Arm
242bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** instruction is translated to one or more Mips instructions as necessary. This
252bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** is clearly less efficient than a direct implementation within the
262bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** GGLAssembler, but is far cleaner, more maintainable, and has yielded very
272bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** significant performance gains on Mips compared to the generic pixel pipeline.
282bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
292bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
302bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** GGLAssembler changes
312bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
322bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** - The register allocator has been modified to re-map Arm registers 0-15 to mips
332bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** registers 2-17. Mips register 0 cannot be used as general-purpose register,
342bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** and register 1 has traditional uses as a short-term temporary.
352bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
362bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** - Added some early bailouts for OUT_OF_REGISTERS in texturing.cpp and
372bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** GGLAssembler.cpp, since this is not fatal, and can be retried at lower
382bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** optimization level.
392bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
402bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
412bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** ARMAssembler and ARMAssemblerInterface changes
422bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind**
432bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** Refactored ARM address-mode static functions (imm(), reg_imm(), imm12_pre(), etc.)
442bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** to virtual, so they can be overridden in MIPSAssembler. The implementation of these
452bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** functions on ARM is moved from ARMAssemblerInterface.cpp to ARMAssembler.cpp, and
462bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** is unchanged from the original. (This required duplicating 2 of these as static
472bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind** functions in ARMAssemblerInterface.cpp so they could be used as static initializers).
482bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind*/
492bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
502bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
512bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#define LOG_TAG "MIPSAssembler"
522bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
532bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#include <stdio.h>
542bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#include <stdlib.h>
552bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#include <cutils/log.h>
562bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#include <cutils/properties.h>
572bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
582bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if defined(WITH_LIB_HARDWARE)
592bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#include <hardware_legacy/qemu_tracing.h>
602bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#endif
612bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
622bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#include <private/pixelflinger/ggl_context.h>
632bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
642bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#include "codeflinger/MIPSAssembler.h"
652bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#include "codeflinger/CodeCache.h"
662bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#include "codeflinger/mips_disassem.h"
672bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// Choose MIPS arch variant following gcc flags
692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if defined(__mips__) && __mips==32 && __mips_isa_rev>=2
702bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#define mips32r2 1
712bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#else
722bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#define mips32r2 0
732bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#endif
742bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
752bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
762bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#define NOT_IMPLEMENTED()  LOG_ALWAYS_FATAL("Arm instruction %s not yet implemented\n", __func__)
772bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
782bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
792bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
802bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// ----------------------------------------------------------------------------
812bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
822bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindnamespace android {
832bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
842bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// ----------------------------------------------------------------------------
852bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if 0
862bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark -
872bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark ArmToMipsAssembler...
882bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#endif
892bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
902bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul LindArmToMipsAssembler::ArmToMipsAssembler(const sp<Assembly>& assembly,
912bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                                       char *abuf, int linesz, int instr_count)
922bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    :   ARMAssemblerInterface(),
932bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mArmDisassemblyBuffer(abuf),
942bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mArmLineLength(linesz),
952bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mArmInstrCount(instr_count),
962bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mInum(0),
972bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mAssembly(assembly)
982bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
992bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips = new MIPSAssembler(assembly, this);
1002bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC = (uint32_t **) malloc(ARM_MAX_INSTUCTIONS * sizeof(uint32_t *));
1012bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    init_conditional_labels();
1022bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1032bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1042bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul LindArmToMipsAssembler::~ArmToMipsAssembler()
1052bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1062bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    delete mMips;
1072bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    free((void *) mArmPC);
1082bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1092bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1102bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t* ArmToMipsAssembler::pc() const
1112bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1122bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return mMips->pc();
1132bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1142bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1152bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t* ArmToMipsAssembler::base() const
1162bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1172bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return mMips->base();
1182bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1192bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1202bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::reset()
1212bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1222bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    cond.labelnum = 0;
1232bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mInum = 0;
1242bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->reset();
1252bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1262bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1272bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindint ArmToMipsAssembler::getCodegenArch()
1282bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1292bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return CODEGEN_ARCH_MIPS;
1302bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1312bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1322bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::comment(const char* string)
1332bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1342bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->comment(string);
1352bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1362bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1372bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::label(const char* theLabel)
1382bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1392bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->label(theLabel);
1402bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1412bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1422bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::disassemble(const char* name)
1432bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1442bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->disassemble(name);
1452bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1462bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1472bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::init_conditional_labels()
1482bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1492bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    int i;
1502bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    for (i=0;i<99; ++i) {
1512bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        sprintf(cond.label[i], "cond_%d", i);
1522bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
1532bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1542bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1552bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1562bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1572bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if 0
1582bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark -
1592bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark Prolog/Epilog & Generate...
1602bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#endif
1612bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1622bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::prolog()
1632bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1642bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();  // save starting PC for this instr
1652bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1662bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->ADDIU(R_sp, R_sp, -(5 * 4));
1672bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->SW(R_s0, R_sp, 0);
1682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->SW(R_s1, R_sp, 4);
1692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->SW(R_s2, R_sp, 8);
1702bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->SW(R_s3, R_sp, 12);
1712bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->SW(R_s4, R_sp, 16);
1722bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->MOVE(R_v0, R_a0);    // move context * passed in a0 to v0 (arm r0)
1732bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1742bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1752bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::epilog(uint32_t touched)
1762bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1772bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();  // save starting PC for this instr
1782bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1792bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->LW(R_s0, R_sp, 0);
1802bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->LW(R_s1, R_sp, 4);
1812bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->LW(R_s2, R_sp, 8);
1822bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->LW(R_s3, R_sp, 12);
1832bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->LW(R_s4, R_sp, 16);
1842bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->ADDIU(R_sp, R_sp, (5 * 4));
1852bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->JR(R_ra);
1862bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1872bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1882bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1892bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindint ArmToMipsAssembler::generate(const char* name)
1902bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1912bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return mMips->generate(name);
1922bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1932bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1942bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t* ArmToMipsAssembler::pcForLabel(const char* label)
1952bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
1962bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return mMips->pcForLabel(label);
1972bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
1982bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
1992bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2002bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2012bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind//----------------------------------------------------------
2022bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2032bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if 0
2042bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark -
2052bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark Addressing modes & shifters...
2062bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#endif
2072bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2082bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2092bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// do not need this for MIPS, but it is in the Interface (virtual)
2102bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindint ArmToMipsAssembler::buildImmediate(
2112bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        uint32_t immediate, uint32_t& rot, uint32_t& imm)
2122bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
2132bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // for MIPS, any 32-bit immediate is OK
2142bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    rot = 0;
2152bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    imm = immediate;
2162bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return 0;
2172bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
2182bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2192bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// shifters...
2202bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2212bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindbool ArmToMipsAssembler::isValidImmediate(uint32_t immediate)
2222bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
2232bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // for MIPS, any 32-bit immediate is OK
2242bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return true;
2252bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
2262bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2272bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::imm(uint32_t immediate)
2282bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
2292bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // ALOGW("immediate value %08x at pc %08x\n", immediate, (int)pc());
2302bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    amode.value = immediate;
2312bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_IMM;
2322bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
2332bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2342bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::reg_imm(int Rm, int type, uint32_t shift)
2352bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
2362bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    amode.reg = Rm;
2372bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    amode.stype = type;
2382bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    amode.value = shift;
2392bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_REG_IMM;
2402bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
2412bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2422bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::reg_rrx(int Rm)
2432bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
2442bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // reg_rrx mode is not used in the GLLAssember code at this time
2452bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_UNSUPPORTED;
2462bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
2472bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2482bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::reg_reg(int Rm, int type, int Rs)
2492bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
2502bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // reg_reg mode is not used in the GLLAssember code at this time
2512bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_UNSUPPORTED;
2522bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
2532bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2542bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2552bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// addressing modes...
2562bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// LDR(B)/STR(B)/PLD (immediate and Rm can be negative, which indicate U=0)
2572bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::immed12_pre(int32_t immed12, int W)
2582bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
2592bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
2602bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                        "LDR(B)/STR(B)/PLD immediate too big (%08x)",
2612bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                        immed12);
2622bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    amode.value = immed12;
2632bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    amode.writeback = W;
2642bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_IMM_12_PRE;
2652bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
2662bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2672bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::immed12_post(int32_t immed12)
2682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
2692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
2702bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                        "LDR(B)/STR(B)/PLD immediate too big (%08x)",
2712bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                        immed12);
2722bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2732bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    amode.value = immed12;
2742bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_IMM_12_POST;
2752bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
2762bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2772bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::reg_scale_pre(int Rm, int type,
2782bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        uint32_t shift, int W)
2792bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
2802bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL_IF(W | type | shift, "reg_scale_pre adv modes not yet implemented");
2812bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2822bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    amode.reg = Rm;
2832bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // amode.stype = type;      // more advanced modes not used in GGLAssembler yet
2842bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // amode.value = shift;
2852bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // amode.writeback = W;
2862bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_REG_SCALE_PRE;
2872bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
2882bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2892bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::reg_scale_post(int Rm, int type, uint32_t shift)
2902bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
2912bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL("adr mode reg_scale_post not yet implemented\n");
2922bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_UNSUPPORTED;
2932bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
2942bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
2952bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// LDRH/LDRSB/LDRSH/STRH (immediate and Rm can be negative, which indicate U=0)
2962bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::immed8_pre(int32_t immed8, int W)
2972bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
2982bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // uint32_t offset = abs(immed8);
2992bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3002bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL("adr mode immed8_pre not yet implemented\n");
3012bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3022bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
3032bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                        "LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
3042bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                        immed8);
3052bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_IMM_8_PRE;
3062bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
3072bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3082bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::immed8_post(int32_t immed8)
3092bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
3102bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // uint32_t offset = abs(immed8);
3112bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3122bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
3132bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                        "LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
3142bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                        immed8);
3152bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    amode.value = immed8;
3162bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_IMM_8_POST;
3172bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
3182bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3192bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::reg_pre(int Rm, int W)
3202bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
3212bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL_IF(W, "reg_pre writeback not yet implemented");
3222bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    amode.reg = Rm;
3232bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_REG_PRE;
3242bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
3252bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3262bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Linduint32_t ArmToMipsAssembler::reg_post(int Rm)
3272bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
3282bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL("adr mode reg_post not yet implemented\n");
3292bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    return AMODE_UNSUPPORTED;
3302bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
3312bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3322bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3332bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3342bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// ----------------------------------------------------------------------------
3352bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3362bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if 0
3372bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark -
3382bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark Data Processing...
3392bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#endif
3402bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3412bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3422bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindstatic const char * const dpOpNames[] = {
3432bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    "AND", "EOR", "SUB", "RSB", "ADD", "ADC", "SBC", "RSC",
3442bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN"
3452bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind};
3462bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3472bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// check if the operand registers from a previous CMP or S-bit instruction
3482bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// would be overwritten by this instruction. If so, move the value to a
3492bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// safe register.
3502bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// Note that we cannot tell at _this_ instruction time if a future (conditional)
3512bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// instruction will _also_ use this value (a defect of the simple 1-pass, one-
3522bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// instruction-at-a-time translation). Therefore we must be conservative and
3532bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// save the value before it is overwritten. This costs an extra MOVE instr.
3542bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3552bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::protectConditionalOperands(int Rd)
3562bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
3572bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (Rd == cond.r1) {
3582bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mMips->MOVE(R_cmp, cond.r1);
3592bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.r1 = R_cmp;
3602bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
3612bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (cond.type == CMP_COND && Rd == cond.r2) {
3622bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mMips->MOVE(R_cmp2, cond.r2);
3632bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.r2 = R_cmp2;
3642bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
3652bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
3662bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3672bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
3682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// interprets the addressing mode, and generates the common code
3692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// used by the majority of data-processing ops. Many MIPS instructions
3702bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// have a register-based form and a different immediate form. See
3712bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// opAND below for an example. (this could be inlined)
3722bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind//
3732bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// this works with the imm(), reg_imm() methods above, which are directly
3742bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// called by the GLLAssembler.
3752bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// note: _signed parameter defaults to false (un-signed)
3762bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// note: tmpReg parameter defaults to 1, MIPS register AT
3772bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindint ArmToMipsAssembler::dataProcAdrModes(int op, int& source, bool _signed, int tmpReg)
3782bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
3792bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (op < AMODE_REG) {
3802bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        source = op;
3812bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        return SRC_REG;
3822bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    } else if (op == AMODE_IMM) {
3832bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        if ((!_signed && amode.value > 0xffff)
3842bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                || (_signed && ((int)amode.value < -32768 || (int)amode.value > 32767) )) {
3852bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->LUI(tmpReg, (amode.value >> 16));
3862bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (amode.value & 0x0000ffff) {
3872bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->ORI(tmpReg, tmpReg, (amode.value & 0x0000ffff));
3882bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
3892bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            source = tmpReg;
3902bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            return SRC_REG;
3912bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        } else {
3922bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            source = amode.value;
3932bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            return SRC_IMM;
3942bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
3952bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    } else if (op == AMODE_REG_IMM) {
3962bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        switch (amode.stype) {
3972bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case LSL: mMips->SLL(tmpReg, amode.reg, amode.value); break;
3982bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case LSR: mMips->SRL(tmpReg, amode.reg, amode.value); break;
3992bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case ASR: mMips->SRA(tmpReg, amode.reg, amode.value); break;
4002bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case ROR: if (mips32r2) {
4012bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                          mMips->ROTR(tmpReg, amode.reg, amode.value);
4022bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                      } else {
4032bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                          mMips->RORIsyn(tmpReg, amode.reg, amode.value);
4042bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                      }
4052bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                      break;
4062bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
4072bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        source = tmpReg;
4082bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        return SRC_REG;
4092bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    } else {  // adr mode RRX is not used in GGL Assembler at this time
4102bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // we are screwed, this should be exception, assert-fail or something
4112bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        LOG_ALWAYS_FATAL("adr mode reg_rrx not yet implemented\n");
4122bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        return SRC_ERROR;
4132bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
4142bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
4152bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4162bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4172bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::dataProcessing(int opcode, int cc,
4182bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        int s, int Rd, int Rn, uint32_t Op2)
4192bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
4202bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    int src;    // src is modified by dataProcAdrModes() - passed as int&
4212bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4222bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4232bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (cc != AL) {
4242bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        protectConditionalOperands(Rd);
4252bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // the branch tests register(s) set by prev CMP or instr with 'S' bit set
4262bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // inverse the condition to jump past this conditional instruction
4272bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        ArmToMipsAssembler::B(cc^1, cond.label[++cond.labelnum]);
4282bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    } else {
4292bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mArmPC[mInum++] = pc();  // save starting PC for this instr
4302bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
4312bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4322bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    switch (opcode) {
4332bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opAND:
4342bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        if (dataProcAdrModes(Op2, src) == SRC_REG) {
4352bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->AND(Rd, Rn, src);
4362bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        } else {                        // adr mode was SRC_IMM
4372bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ANDI(Rd, Rn, src);
4382bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
4392bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        break;
4402bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4412bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opADD:
4422bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // set "signed" to true for adr modes
4432bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
4442bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDU(Rd, Rn, src);
4452bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        } else {                        // adr mode was SRC_IMM
4462bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDIU(Rd, Rn, src);
4472bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
4482bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        break;
4492bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4502bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opSUB:
4512bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // set "signed" to true for adr modes
4522bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
4532bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->SUBU(Rd, Rn, src);
4542bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        } else {                        // adr mode was SRC_IMM
4552bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->SUBIU(Rd, Rn, src);
4562bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
4572bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        break;
4582bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4592bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opEOR:
4602bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        if (dataProcAdrModes(Op2, src) == SRC_REG) {
4612bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->XOR(Rd, Rn, src);
4622bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        } else {                        // adr mode was SRC_IMM
4632bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->XORI(Rd, Rn, src);
4642bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
4652bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        break;
4662bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4672bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opORR:
4682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        if (dataProcAdrModes(Op2, src) == SRC_REG) {
4692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->OR(Rd, Rn, src);
4702bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        } else {                        // adr mode was SRC_IMM
4712bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ORI(Rd, Rn, src);
4722bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
4732bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        break;
4742bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4752bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opBIC:
4762bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        if (dataProcAdrModes(Op2, src) == SRC_IMM) {
4772bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // if we are 16-bit imnmediate, load to AT reg
4782bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ORI(R_at, 0, src);
4792bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            src = R_at;
4802bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
4812bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mMips->NOT(R_at, src);
4822bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mMips->AND(Rd, Rn, R_at);
4832bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        break;
4842bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4852bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opRSB:
4862bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        if (dataProcAdrModes(Op2, src) == SRC_IMM) {
4872bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // if we are 16-bit imnmediate, load to AT reg
4882bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ORI(R_at, 0, src);
4892bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            src = R_at;
4902bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
4912bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mMips->SUBU(Rd, src, Rn);   // subu with the parameters reversed
4922bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        break;
4932bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4942bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opMOV:
4952bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        if (Op2 < AMODE_REG) {  // op2 is reg # in this case
4962bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->MOVE(Rd, Op2);
4972bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        } else if (Op2 == AMODE_IMM) {
4982bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (amode.value > 0xffff) {
4992bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->LUI(Rd, (amode.value >> 16));
5002bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                if (amode.value & 0x0000ffff) {
5012bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                    mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff));
5022bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                }
5032bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind             } else {
5042bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->ORI(Rd, 0, amode.value);
5052bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
5062bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        } else if (Op2 == AMODE_REG_IMM) {
5072bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            switch (amode.stype) {
5082bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case LSL: mMips->SLL(Rd, amode.reg, amode.value); break;
5092bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case LSR: mMips->SRL(Rd, amode.reg, amode.value); break;
5102bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case ASR: mMips->SRA(Rd, amode.reg, amode.value); break;
5112bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case ROR: if (mips32r2) {
5122bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                          mMips->ROTR(Rd, amode.reg, amode.value);
5132bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                      } else {
5142bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                          mMips->RORIsyn(Rd, amode.reg, amode.value);
5152bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                      }
5162bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                      break;
5172bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
5182bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
5192bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        else {
5202bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // adr mode RRX is not used in GGL Assembler at this time
5212bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->UNIMPL();
5222bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
5232bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        break;
5242bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
5252bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opMVN:     // this is a 1's complement: NOT
5262bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        if (Op2 < AMODE_REG) {  // op2 is reg # in this case
5272bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->NOR(Rd, Op2, 0);     // NOT is NOR with 0
5282bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
5292bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        } else if (Op2 == AMODE_IMM) {
5302bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (amode.value > 0xffff) {
5312bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->LUI(Rd, (amode.value >> 16));
5322bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                if (amode.value & 0x0000ffff) {
5332bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                    mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff));
5342bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                }
5352bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind             } else {
5362bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->ORI(Rd, 0, amode.value);
5372bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind             }
5382bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        } else if (Op2 == AMODE_REG_IMM) {
5392bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            switch (amode.stype) {
5402bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case LSL: mMips->SLL(Rd, amode.reg, amode.value); break;
5412bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case LSR: mMips->SRL(Rd, amode.reg, amode.value); break;
5422bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case ASR: mMips->SRA(Rd, amode.reg, amode.value); break;
5432bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            case ROR: if (mips32r2) {
5442bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                          mMips->ROTR(Rd, amode.reg, amode.value);
5452bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                      } else {
5462bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                          mMips->RORIsyn(Rd, amode.reg, amode.value);
5472bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                      }
5482bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                      break;
5492bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
5502bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
5512bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        else {
5522bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // adr mode RRX is not used in GGL Assembler at this time
5532bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->UNIMPL();
5542bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
5552bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mMips->NOR(Rd, Rd, 0);     // NOT is NOR with 0
5562bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        break;
5572bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
5582bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opCMP:
5592bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // Either operand of a CMP instr could get overwritten by a subsequent
5602bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // conditional instruction, which is ok, _UNLESS_ there is a _second_
5612bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // conditional instruction. Under MIPS, this requires doing the comparison
5622bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // again (SLT), and the original operands must be available. (and this
5632bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // pattern of multiple conditional instructions from same CMP _is_ used
5642bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // in GGL-Assembler)
5652bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        //
5662bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // For now, if a conditional instr overwrites the operands, we will
5672bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // move them to dedicated temp regs. This is ugly, and inefficient,
5682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // and should be optimized.
5692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        //
5702bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // WARNING: making an _Assumption_ that CMP operand regs will NOT be
5712bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // trashed by intervening NON-conditional instructions. In the general
5722bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        // case this is legal, but it is NOT currently done in GGL-Assembler.
5732bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
5742bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.type = CMP_COND;
5752bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.r1 = Rn;
5762bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        if (dataProcAdrModes(Op2, src, false, R_cmp2) == SRC_REG) {
5772bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            cond.r2 = src;
5782bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        } else {                        // adr mode was SRC_IMM
5792bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ORI(R_cmp2, R_zero, src);
5802bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            cond.r2 = R_cmp2;
5812bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        }
5822bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
5832bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        break;
5842bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
5852bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
5862bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opTST:
5872bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opTEQ:
5882bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opCMN:
5892bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opADC:
5902bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opSBC:
5912bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    case opRSC:
5922bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mMips->UNIMPL(); // currently unused in GGL Assembler code
5932bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        break;
5942bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
5952bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
5962bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (cc != AL) {
5972bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        mMips->label(cond.label[cond.labelnum]);
5982bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
5992bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (s && opcode != opCMP) {
6002bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.type = SBIT_COND;
6012bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.r1 = Rd;
6022bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
6032bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
6042bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6052bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6062bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6072bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if 0
6082bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark -
6092bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark Multiply...
6102bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#endif
6112bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6122bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// multiply, accumulate
6132bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::MLA(int cc, int s,
6142bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        int Rd, int Rm, int Rs, int Rn) {
6152bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6162bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();  // save starting PC for this instr
6172bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6182bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->MUL(R_at, Rm, Rs);
6192bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->ADDU(Rd, R_at, Rn);
6202bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (s) {
6212bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.type = SBIT_COND;
6222bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.r1 = Rd;
6232bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
6242bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
6252bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6262bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::MUL(int cc, int s,
6272bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        int Rd, int Rm, int Rs) {
6282bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
6292bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->MUL(Rd, Rm, Rs);
6302bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (s) {
6312bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.type = SBIT_COND;
6322bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.r1 = Rd;
6332bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
6342bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
6352bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6362bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::UMULL(int cc, int s,
6372bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        int RdLo, int RdHi, int Rm, int Rs) {
6382bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
6392bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->MULT(Rm, Rs);
6402bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->MFHI(RdHi);
6412bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->MFLO(RdLo);
6422bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (s) {
6432bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.type = SBIT_COND;
6442bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.r1 = RdHi;     // BUG...
6452bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n");
6462bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
6472bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
6482bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6492bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::UMUAL(int cc, int s,
6502bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        int RdLo, int RdHi, int Rm, int Rs) {
6512bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
6522bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                        "UMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
6532bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // *mPC++ =    (cc<<28) | (1<<23) | (1<<21) | (s<<20) |
6542bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    //             (RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
6552bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
6562bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->NOP2();
6572bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    NOT_IMPLEMENTED();
6582bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (s) {
6592bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.type = SBIT_COND;
6602bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.r1 = RdHi;     // BUG...
6612bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n");
6622bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
6632bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
6642bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6652bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::SMULL(int cc, int s,
6662bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        int RdLo, int RdHi, int Rm, int Rs) {
6672bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
6682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                        "SMULL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
6692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // *mPC++ =    (cc<<28) | (1<<23) | (1<<22) | (s<<20) |
6702bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    //             (RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
6712bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
6722bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->NOP2();
6732bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    NOT_IMPLEMENTED();
6742bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (s) {
6752bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.type = SBIT_COND;
6762bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.r1 = RdHi;     // BUG...
6772bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        LOG_ALWAYS_FATAL("Condition on SMULL must be on 64-bit result\n");
6782bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
6792bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
6802bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::SMUAL(int cc, int s,
6812bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        int RdLo, int RdHi, int Rm, int Rs) {
6822bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
6832bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                        "SMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
6842bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // *mPC++ =    (cc<<28) | (1<<23) | (1<<22) | (1<<21) | (s<<20) |
6852bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    //             (RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
6862bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
6872bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->NOP2();
6882bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    NOT_IMPLEMENTED();
6892bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (s) {
6902bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.type = SBIT_COND;
6912bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        cond.r1 = RdHi;     // BUG...
6922bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        LOG_ALWAYS_FATAL("Condition on SMUAL must be on 64-bit result\n");
6932bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
6942bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
6952bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6962bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6972bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6982bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if 0
6992bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark -
7002bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark Branches...
7012bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#endif
7022bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7032bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// branches...
7042bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7052bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::B(int cc, const char* label)
7062bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
7072bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
7082bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (cond.type == SBIT_COND) { cond.r2 = R_zero; }
7092bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7102bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    switch(cc) {
7112bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case EQ: mMips->BEQ(cond.r1, cond.r2, label); break;
7122bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case NE: mMips->BNE(cond.r1, cond.r2, label); break;
7132bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case HS: mMips->BGEU(cond.r1, cond.r2, label); break;
7142bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case LO: mMips->BLTU(cond.r1, cond.r2, label); break;
7152bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case MI: mMips->BLT(cond.r1, cond.r2, label); break;
7162bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case PL: mMips->BGE(cond.r1, cond.r2, label); break;
7172bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7182bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case HI: mMips->BGTU(cond.r1, cond.r2, label); break;
7192bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case LS: mMips->BLEU(cond.r1, cond.r2, label); break;
7202bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case GE: mMips->BGE(cond.r1, cond.r2, label); break;
7212bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case LT: mMips->BLT(cond.r1, cond.r2, label); break;
7222bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case GT: mMips->BGT(cond.r1, cond.r2, label); break;
7232bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case LE: mMips->BLE(cond.r1, cond.r2, label); break;
7242bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AL: mMips->B(label); break;
7252bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case NV: /* B Never - no instruction */ break;
7262bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7272bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case VS:
7282bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case VC:
7292bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        default:
7302bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            LOG_ALWAYS_FATAL("Unsupported cc: %02x\n", cc);
7312bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
7322bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
7332bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
7342bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7352bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::BL(int cc, const char* label)
7362bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
7372bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL("branch-and-link not supported yet\n");
7382bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
7392bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
7402bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7412bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// no use for Branches with integer PC, but they're in the Interface class ....
7422bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::B(int cc, uint32_t* to_pc)
7432bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
7442bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
7452bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
7462bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
7472bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7482bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::BL(int cc, uint32_t* to_pc)
7492bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
7502bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
7512bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
7522bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
7532bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7542bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::BX(int cc, int Rn)
7552bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
7562bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
7572bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
7582bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
7592bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7602bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7612bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7622bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if 0
7632bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark -
7642bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark Data Transfer...
7652bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#endif
7662bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
7672bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// data transfer...
7682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::LDR(int cc, int Rd, int Rn, uint32_t offset)
7692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
7702bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
7712bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // work-around for ARM default address mode of immed12_pre(0)
7722bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (offset > AMODE_UNSUPPORTED) offset = 0;
7732bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    switch (offset) {
7742bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case 0:
7752bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            amode.value = 0;
7762bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            amode.writeback = 0;
7772bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // fall thru to next case ....
7782bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_12_PRE:
7792bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (Rn == ARMAssemblerInterface::SP) {
7802bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                Rn = R_sp;      // convert LDR via Arm SP to LW via Mips SP
7812bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
7822bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->LW(Rd, Rn, amode.value);
7832bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
7842bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->ADDIU(Rn, Rn, amode.value);
7852bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
7862bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
7872bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_12_POST:
7882bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (Rn == ARMAssemblerInterface::SP) {
7892bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                Rn = R_sp;      // convert STR thru Arm SP to STR thru Mips SP
7902bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
7912bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->LW(Rd, Rn, 0);
7922bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDIU(Rn, Rn, amode.value);
7932bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
7942bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_REG_SCALE_PRE:
7952bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // we only support simple base + index, no advanced modes for this one yet
7962bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDU(R_at, Rn, amode.reg);
7972bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->LW(Rd, R_at, 0);
7982bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
7992bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
8002bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
8012bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
8022bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::LDRB(int cc, int Rd, int Rn, uint32_t offset)
8032bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
8042bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
8052bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // work-around for ARM default address mode of immed12_pre(0)
8062bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (offset > AMODE_UNSUPPORTED) offset = 0;
8072bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    switch (offset) {
8082bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case 0:
8092bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            amode.value = 0;
8102bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            amode.writeback = 0;
8112bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // fall thru to next case ....
8122bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_12_PRE:
8132bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->LBU(Rd, Rn, amode.value);
8142bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
8152bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->ADDIU(Rn, Rn, amode.value);
8162bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
8172bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
8182bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_12_POST:
8192bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->LBU(Rd, Rn, 0);
8202bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDIU(Rn, Rn, amode.value);
8212bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
8222bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_REG_SCALE_PRE:
8232bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // we only support simple base + index, no advanced modes for this one yet
8242bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDU(R_at, Rn, amode.reg);
8252bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->LBU(Rd, R_at, 0);
8262bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
8272bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
8282bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
8292bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
8302bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
8312bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::STR(int cc, int Rd, int Rn, uint32_t offset)
8322bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
8332bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
8342bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // work-around for ARM default address mode of immed12_pre(0)
8352bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (offset > AMODE_UNSUPPORTED) offset = 0;
8362bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    switch (offset) {
8372bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case 0:
8382bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            amode.value = 0;
8392bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            amode.writeback = 0;
8402bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // fall thru to next case ....
8412bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_12_PRE:
8422bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (Rn == ARMAssemblerInterface::SP) {
8432bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                Rn = R_sp;  // convert STR thru Arm SP to SW thru Mips SP
8442bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
8452bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
8462bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                // If we will writeback, then update the index reg, then store.
8472bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                // This correctly handles stack-push case.
8482bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->ADDIU(Rn, Rn, amode.value);
8492bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->SW(Rd, Rn, 0);
8502bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            } else {
8512bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                // No writeback so store offset by value
8522bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->SW(Rd, Rn, amode.value);
8532bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
8542bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
8552bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_12_POST:
8562bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->SW(Rd, Rn, 0);
8572bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDIU(Rn, Rn, amode.value);  // post index always writes back
8582bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
8592bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_REG_SCALE_PRE:
8602bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // we only support simple base + index, no advanced modes for this one yet
8612bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDU(R_at, Rn, amode.reg);
8622bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->SW(Rd, R_at, 0);
8632bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
8642bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
8652bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
8662bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
8672bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::STRB(int cc, int Rd, int Rn, uint32_t offset)
8682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
8692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
8702bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // work-around for ARM default address mode of immed12_pre(0)
8712bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (offset > AMODE_UNSUPPORTED) offset = 0;
8722bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    switch (offset) {
8732bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case 0:
8742bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            amode.value = 0;
8752bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            amode.writeback = 0;
8762bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // fall thru to next case ....
8772bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_12_PRE:
8782bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->SB(Rd, Rn, amode.value);
8792bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
8802bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->ADDIU(Rn, Rn, amode.value);
8812bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
8822bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
8832bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_12_POST:
8842bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->SB(Rd, Rn, 0);
8852bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDIU(Rn, Rn, amode.value);
8862bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
8872bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_REG_SCALE_PRE:
8882bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // we only support simple base + index, no advanced modes for this one yet
8892bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDU(R_at, Rn, amode.reg);
8902bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->SB(Rd, R_at, 0);
8912bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
8922bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
8932bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
8942bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
8952bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::LDRH(int cc, int Rd, int Rn, uint32_t offset)
8962bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
8972bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
8982bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // work-around for ARM default address mode of immed8_pre(0)
8992bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (offset > AMODE_UNSUPPORTED) offset = 0;
9002bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    switch (offset) {
9012bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case 0:
9022bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            amode.value = 0;
9032bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // fall thru to next case ....
9042bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_8_PRE:      // no support yet for writeback
9052bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->LHU(Rd, Rn, amode.value);
9062bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
9072bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_8_POST:
9082bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->LHU(Rd, Rn, 0);
9092bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDIU(Rn, Rn, amode.value);
9102bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
9112bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_REG_PRE:
9122bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // we only support simple base +/- index
9132bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (amode.reg >= 0) {
9142bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->ADDU(R_at, Rn, amode.reg);
9152bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            } else {
9162bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->SUBU(R_at, Rn, abs(amode.reg));
9172bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
9182bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->LHU(Rd, R_at, 0);
9192bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
9202bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
9212bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
9222bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
9232bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::LDRSB(int cc, int Rd, int Rn, uint32_t offset)
9242bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
9252bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
9262bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->NOP2();
9272bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    NOT_IMPLEMENTED();
9282bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
9292bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
9302bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::LDRSH(int cc, int Rd, int Rn, uint32_t offset)
9312bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
9322bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
9332bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mMips->NOP2();
9342bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    NOT_IMPLEMENTED();
9352bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
9362bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
9372bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::STRH(int cc, int Rd, int Rn, uint32_t offset)
9382bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{
9392bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    mArmPC[mInum++] = pc();
9402bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    // work-around for ARM default address mode of immed8_pre(0)
9412bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    if (offset > AMODE_UNSUPPORTED) offset = 0;
9422bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    switch (offset) {
9432bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case 0:
9442bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            amode.value = 0;
9452bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // fall thru to next case ....
9462bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_8_PRE:      // no support yet for writeback
9472bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->SH(Rd, Rn, amode.value);
9482bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
9492bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_IMM_8_POST:
9502bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->SH(Rd, Rn, 0);
9512bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->ADDIU(Rn, Rn, amode.value);
9522bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
9532bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        case AMODE_REG_PRE:
9542bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            // we only support simple base +/- index
9552bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (amode.reg >= 0) {
9562bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->ADDU(R_at, Rn, amode.reg);
9572bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            } else {
9582bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                mMips->SUBU(R_at, Rn, abs(amode.reg));
9592bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            }
9602bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            mMips->SH(Rd, R_at, 0);
9612bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            break;
9622bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind    }
9632bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind}
9642bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
9652bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
9662bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
9672bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if 0
9682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark -
9692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#pragma mark Block Data Transfer...
9702bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#endif
9712bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
9722bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// block data transfer...
9732bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lindvoid ArmToMipsAssembler::LDM(int cc, int dir,
9742bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind        int Rn, int W, uint32_t reg_list)
9752bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind{   //                        ED FD EA FA      IB IA DB DA
976