Home | History | Annotate | Download | only in codeflinger
      1 /* libs/pixelflinger/codeflinger/MIPSAssembler.cpp
      2 **
      3 ** Copyright 2012, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 
     19 /* MIPS assembler and ARM->MIPS assembly translator
     20 **
     21 ** The approach is to leave the GGLAssembler and associated files largely
     22 ** un-changed, still utilizing all Arm instruction generation. Via the
     23 ** ArmToMipsAssembler (subclassed from ArmAssemblerInterface) each Arm
     24 ** instruction is translated to one or more Mips instructions as necessary. This
     25 ** is clearly less efficient than a direct implementation within the
     26 ** GGLAssembler, but is far cleaner, more maintainable, and has yielded very
     27 ** significant performance gains on Mips compared to the generic pixel pipeline.
     28 **
     29 **
     30 ** GGLAssembler changes
     31 **
     32 ** - The register allocator has been modified to re-map Arm registers 0-15 to mips
     33 ** registers 2-17. Mips register 0 cannot be used as general-purpose register,
     34 ** and register 1 has traditional uses as a short-term temporary.
     35 **
     36 ** - Added some early bailouts for OUT_OF_REGISTERS in texturing.cpp and
     37 ** GGLAssembler.cpp, since this is not fatal, and can be retried at lower
     38 ** optimization level.
     39 **
     40 **
     41 ** ARMAssembler and ARMAssemblerInterface changes
     42 **
     43 ** Refactored ARM address-mode static functions (imm(), reg_imm(), imm12_pre(), etc.)
     44 ** to virtual, so they can be overridden in MIPSAssembler. The implementation of these
     45 ** functions on ARM is moved from ARMAssemblerInterface.cpp to ARMAssembler.cpp, and
     46 ** is unchanged from the original. (This required duplicating 2 of these as static
     47 ** functions in ARMAssemblerInterface.cpp so they could be used as static initializers).
     48 */
     49 
     50 
     51 #define LOG_TAG "MIPSAssembler"
     52 
     53 #include <stdio.h>
     54 #include <stdlib.h>
     55 #include <cutils/log.h>
     56 #include <cutils/properties.h>
     57 
     58 #if defined(WITH_LIB_HARDWARE)
     59 #include <hardware_legacy/qemu_tracing.h>
     60 #endif
     61 
     62 #include <private/pixelflinger/ggl_context.h>
     63 
     64 #include "MIPSAssembler.h"
     65 #include "CodeCache.h"
     66 #include "mips_disassem.h"
     67 
     68 // Choose MIPS arch variant following gcc flags
     69 #if defined(__mips__) && __mips==32 && __mips_isa_rev>=2
     70 #define mips32r2 1
     71 #else
     72 #define mips32r2 0
     73 #endif
     74 
     75 
     76 #define NOT_IMPLEMENTED()  LOG_ALWAYS_FATAL("Arm instruction %s not yet implemented\n", __func__)
     77 
     78 
     79 
     80 // ----------------------------------------------------------------------------
     81 
     82 namespace android {
     83 
     84 // ----------------------------------------------------------------------------
     85 #if 0
     86 #pragma mark -
     87 #pragma mark ArmToMipsAssembler...
     88 #endif
     89 
     90 ArmToMipsAssembler::ArmToMipsAssembler(const sp<Assembly>& assembly,
     91                                        char *abuf, int linesz, int instr_count)
     92     :   ARMAssemblerInterface(),
     93         mArmDisassemblyBuffer(abuf),
     94         mArmLineLength(linesz),
     95         mArmInstrCount(instr_count),
     96         mInum(0),
     97         mAssembly(assembly)
     98 {
     99     mMips = new MIPSAssembler(assembly, this);
    100     mArmPC = (uint32_t **) malloc(ARM_MAX_INSTUCTIONS * sizeof(uint32_t *));
    101     init_conditional_labels();
    102 }
    103 
    104 ArmToMipsAssembler::~ArmToMipsAssembler()
    105 {
    106     delete mMips;
    107     free((void *) mArmPC);
    108 }
    109 
    110 uint32_t* ArmToMipsAssembler::pc() const
    111 {
    112     return mMips->pc();
    113 }
    114 
    115 uint32_t* ArmToMipsAssembler::base() const
    116 {
    117     return mMips->base();
    118 }
    119 
    120 void ArmToMipsAssembler::reset()
    121 {
    122     cond.labelnum = 0;
    123     mInum = 0;
    124     mMips->reset();
    125 }
    126 
    127 int ArmToMipsAssembler::getCodegenArch()
    128 {
    129     return CODEGEN_ARCH_MIPS;
    130 }
    131 
    132 void ArmToMipsAssembler::comment(const char* string)
    133 {
    134     mMips->comment(string);
    135 }
    136 
    137 void ArmToMipsAssembler::label(const char* theLabel)
    138 {
    139     mMips->label(theLabel);
    140 }
    141 
    142 void ArmToMipsAssembler::disassemble(const char* name)
    143 {
    144     mMips->disassemble(name);
    145 }
    146 
    147 void ArmToMipsAssembler::init_conditional_labels()
    148 {
    149     int i;
    150     for (i=0;i<99; ++i) {
    151         sprintf(cond.label[i], "cond_%d", i);
    152     }
    153 }
    154 
    155 
    156 
    157 #if 0
    158 #pragma mark -
    159 #pragma mark Prolog/Epilog & Generate...
    160 #endif
    161 
    162 void ArmToMipsAssembler::prolog()
    163 {
    164     mArmPC[mInum++] = pc();  // save starting PC for this instr
    165 
    166     mMips->ADDIU(R_sp, R_sp, -(5 * 4));
    167     mMips->SW(R_s0, R_sp, 0);
    168     mMips->SW(R_s1, R_sp, 4);
    169     mMips->SW(R_s2, R_sp, 8);
    170     mMips->SW(R_s3, R_sp, 12);
    171     mMips->SW(R_s4, R_sp, 16);
    172     mMips->MOVE(R_v0, R_a0);    // move context * passed in a0 to v0 (arm r0)
    173 }
    174 
    175 void ArmToMipsAssembler::epilog(uint32_t touched)
    176 {
    177     mArmPC[mInum++] = pc();  // save starting PC for this instr
    178 
    179     mMips->LW(R_s0, R_sp, 0);
    180     mMips->LW(R_s1, R_sp, 4);
    181     mMips->LW(R_s2, R_sp, 8);
    182     mMips->LW(R_s3, R_sp, 12);
    183     mMips->LW(R_s4, R_sp, 16);
    184     mMips->ADDIU(R_sp, R_sp, (5 * 4));
    185     mMips->JR(R_ra);
    186 
    187 }
    188 
    189 int ArmToMipsAssembler::generate(const char* name)
    190 {
    191     return mMips->generate(name);
    192 }
    193 
    194 uint32_t* ArmToMipsAssembler::pcForLabel(const char* label)
    195 {
    196     return mMips->pcForLabel(label);
    197 }
    198 
    199 
    200 
    201 //----------------------------------------------------------
    202 
    203 #if 0
    204 #pragma mark -
    205 #pragma mark Addressing modes & shifters...
    206 #endif
    207 
    208 
    209 // do not need this for MIPS, but it is in the Interface (virtual)
    210 int ArmToMipsAssembler::buildImmediate(
    211         uint32_t immediate, uint32_t& rot, uint32_t& imm)
    212 {
    213     // for MIPS, any 32-bit immediate is OK
    214     rot = 0;
    215     imm = immediate;
    216     return 0;
    217 }
    218 
    219 // shifters...
    220 
    221 bool ArmToMipsAssembler::isValidImmediate(uint32_t immediate)
    222 {
    223     // for MIPS, any 32-bit immediate is OK
    224     return true;
    225 }
    226 
    227 uint32_t ArmToMipsAssembler::imm(uint32_t immediate)
    228 {
    229     // ALOGW("immediate value %08x at pc %08x\n", immediate, (int)pc());
    230     amode.value = immediate;
    231     return AMODE_IMM;
    232 }
    233 
    234 uint32_t ArmToMipsAssembler::reg_imm(int Rm, int type, uint32_t shift)
    235 {
    236     amode.reg = Rm;
    237     amode.stype = type;
    238     amode.value = shift;
    239     return AMODE_REG_IMM;
    240 }
    241 
    242 uint32_t ArmToMipsAssembler::reg_rrx(int Rm)
    243 {
    244     // reg_rrx mode is not used in the GLLAssember code at this time
    245     return AMODE_UNSUPPORTED;
    246 }
    247 
    248 uint32_t ArmToMipsAssembler::reg_reg(int Rm, int type, int Rs)
    249 {
    250     // reg_reg mode is not used in the GLLAssember code at this time
    251     return AMODE_UNSUPPORTED;
    252 }
    253 
    254 
    255 // addressing modes...
    256 // LDR(B)/STR(B)/PLD (immediate and Rm can be negative, which indicate U=0)
    257 uint32_t ArmToMipsAssembler::immed12_pre(int32_t immed12, int W)
    258 {
    259     LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
    260                         "LDR(B)/STR(B)/PLD immediate too big (%08x)",
    261                         immed12);
    262     amode.value = immed12;
    263     amode.writeback = W;
    264     return AMODE_IMM_12_PRE;
    265 }
    266 
    267 uint32_t ArmToMipsAssembler::immed12_post(int32_t immed12)
    268 {
    269     LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
    270                         "LDR(B)/STR(B)/PLD immediate too big (%08x)",
    271                         immed12);
    272 
    273     amode.value = immed12;
    274     return AMODE_IMM_12_POST;
    275 }
    276 
    277 uint32_t ArmToMipsAssembler::reg_scale_pre(int Rm, int type,
    278         uint32_t shift, int W)
    279 {
    280     LOG_ALWAYS_FATAL_IF(W | type | shift, "reg_scale_pre adv modes not yet implemented");
    281 
    282     amode.reg = Rm;
    283     // amode.stype = type;      // more advanced modes not used in GGLAssembler yet
    284     // amode.value = shift;
    285     // amode.writeback = W;
    286     return AMODE_REG_SCALE_PRE;
    287 }
    288 
    289 uint32_t ArmToMipsAssembler::reg_scale_post(int Rm, int type, uint32_t shift)
    290 {
    291     LOG_ALWAYS_FATAL("adr mode reg_scale_post not yet implemented\n");
    292     return AMODE_UNSUPPORTED;
    293 }
    294 
    295 // LDRH/LDRSB/LDRSH/STRH (immediate and Rm can be negative, which indicate U=0)
    296 uint32_t ArmToMipsAssembler::immed8_pre(int32_t immed8, int W)
    297 {
    298     // uint32_t offset = abs(immed8);
    299 
    300     LOG_ALWAYS_FATAL("adr mode immed8_pre not yet implemented\n");
    301 
    302     LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
    303                         "LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
    304                         immed8);
    305     return AMODE_IMM_8_PRE;
    306 }
    307 
    308 uint32_t ArmToMipsAssembler::immed8_post(int32_t immed8)
    309 {
    310     // uint32_t offset = abs(immed8);
    311 
    312     LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
    313                         "LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
    314                         immed8);
    315     amode.value = immed8;
    316     return AMODE_IMM_8_POST;
    317 }
    318 
    319 uint32_t ArmToMipsAssembler::reg_pre(int Rm, int W)
    320 {
    321     LOG_ALWAYS_FATAL_IF(W, "reg_pre writeback not yet implemented");
    322     amode.reg = Rm;
    323     return AMODE_REG_PRE;
    324 }
    325 
    326 uint32_t ArmToMipsAssembler::reg_post(int Rm)
    327 {
    328     LOG_ALWAYS_FATAL("adr mode reg_post not yet implemented\n");
    329     return AMODE_UNSUPPORTED;
    330 }
    331 
    332 
    333 
    334 // ----------------------------------------------------------------------------
    335 
    336 #if 0
    337 #pragma mark -
    338 #pragma mark Data Processing...
    339 #endif
    340 
    341 
    342 static const char * const dpOpNames[] = {
    343     "AND", "EOR", "SUB", "RSB", "ADD", "ADC", "SBC", "RSC",
    344     "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN"
    345 };
    346 
    347 // check if the operand registers from a previous CMP or S-bit instruction
    348 // would be overwritten by this instruction. If so, move the value to a
    349 // safe register.
    350 // Note that we cannot tell at _this_ instruction time if a future (conditional)
    351 // instruction will _also_ use this value (a defect of the simple 1-pass, one-
    352 // instruction-at-a-time translation). Therefore we must be conservative and
    353 // save the value before it is overwritten. This costs an extra MOVE instr.
    354 
    355 void ArmToMipsAssembler::protectConditionalOperands(int Rd)
    356 {
    357     if (Rd == cond.r1) {
    358         mMips->MOVE(R_cmp, cond.r1);
    359         cond.r1 = R_cmp;
    360     }
    361     if (cond.type == CMP_COND && Rd == cond.r2) {
    362         mMips->MOVE(R_cmp2, cond.r2);
    363         cond.r2 = R_cmp2;
    364     }
    365 }
    366 
    367 
    368 // interprets the addressing mode, and generates the common code
    369 // used by the majority of data-processing ops. Many MIPS instructions
    370 // have a register-based form and a different immediate form. See
    371 // opAND below for an example. (this could be inlined)
    372 //
    373 // this works with the imm(), reg_imm() methods above, which are directly
    374 // called by the GLLAssembler.
    375 // note: _signed parameter defaults to false (un-signed)
    376 // note: tmpReg parameter defaults to 1, MIPS register AT
    377 int ArmToMipsAssembler::dataProcAdrModes(int op, int& source, bool _signed, int tmpReg)
    378 {
    379     if (op < AMODE_REG) {
    380         source = op;
    381         return SRC_REG;
    382     } else if (op == AMODE_IMM) {
    383         if ((!_signed && amode.value > 0xffff)
    384                 || (_signed && ((int)amode.value < -32768 || (int)amode.value > 32767) )) {
    385             mMips->LUI(tmpReg, (amode.value >> 16));
    386             if (amode.value & 0x0000ffff) {
    387                 mMips->ORI(tmpReg, tmpReg, (amode.value & 0x0000ffff));
    388             }
    389             source = tmpReg;
    390             return SRC_REG;
    391         } else {
    392             source = amode.value;
    393             return SRC_IMM;
    394         }
    395     } else if (op == AMODE_REG_IMM) {
    396         switch (amode.stype) {
    397             case LSL: mMips->SLL(tmpReg, amode.reg, amode.value); break;
    398             case LSR: mMips->SRL(tmpReg, amode.reg, amode.value); break;
    399             case ASR: mMips->SRA(tmpReg, amode.reg, amode.value); break;
    400             case ROR: if (mips32r2) {
    401                           mMips->ROTR(tmpReg, amode.reg, amode.value);
    402                       } else {
    403                           mMips->RORIsyn(tmpReg, amode.reg, amode.value);
    404                       }
    405                       break;
    406         }
    407         source = tmpReg;
    408         return SRC_REG;
    409     } else {  // adr mode RRX is not used in GGL Assembler at this time
    410         // we are screwed, this should be exception, assert-fail or something
    411         LOG_ALWAYS_FATAL("adr mode reg_rrx not yet implemented\n");
    412         return SRC_ERROR;
    413     }
    414 }
    415 
    416 
    417 void ArmToMipsAssembler::dataProcessing(int opcode, int cc,
    418         int s, int Rd, int Rn, uint32_t Op2)
    419 {
    420     int src;    // src is modified by dataProcAdrModes() - passed as int&
    421 
    422 
    423     if (cc != AL) {
    424         protectConditionalOperands(Rd);
    425         // the branch tests register(s) set by prev CMP or instr with 'S' bit set
    426         // inverse the condition to jump past this conditional instruction
    427         ArmToMipsAssembler::B(cc^1, cond.label[++cond.labelnum]);
    428     } else {
    429         mArmPC[mInum++] = pc();  // save starting PC for this instr
    430     }
    431 
    432     switch (opcode) {
    433     case opAND:
    434         if (dataProcAdrModes(Op2, src) == SRC_REG) {
    435             mMips->AND(Rd, Rn, src);
    436         } else {                        // adr mode was SRC_IMM
    437             mMips->ANDI(Rd, Rn, src);
    438         }
    439         break;
    440 
    441     case opADD:
    442         // set "signed" to true for adr modes
    443         if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
    444             mMips->ADDU(Rd, Rn, src);
    445         } else {                        // adr mode was SRC_IMM
    446             mMips->ADDIU(Rd, Rn, src);
    447         }
    448         break;
    449 
    450     case opSUB:
    451         // set "signed" to true for adr modes
    452         if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
    453             mMips->SUBU(Rd, Rn, src);
    454         } else {                        // adr mode was SRC_IMM
    455             mMips->SUBIU(Rd, Rn, src);
    456         }
    457         break;
    458 
    459     case opEOR:
    460         if (dataProcAdrModes(Op2, src) == SRC_REG) {
    461             mMips->XOR(Rd, Rn, src);
    462         } else {                        // adr mode was SRC_IMM
    463             mMips->XORI(Rd, Rn, src);
    464         }
    465         break;
    466 
    467     case opORR:
    468         if (dataProcAdrModes(Op2, src) == SRC_REG) {
    469             mMips->OR(Rd, Rn, src);
    470         } else {                        // adr mode was SRC_IMM
    471             mMips->ORI(Rd, Rn, src);
    472         }
    473         break;
    474 
    475     case opBIC:
    476         if (dataProcAdrModes(Op2, src) == SRC_IMM) {
    477             // if we are 16-bit imnmediate, load to AT reg
    478             mMips->ORI(R_at, 0, src);
    479             src = R_at;
    480         }
    481         mMips->NOT(R_at, src);
    482         mMips->AND(Rd, Rn, R_at);
    483         break;
    484 
    485     case opRSB:
    486         if (dataProcAdrModes(Op2, src) == SRC_IMM) {
    487             // if we are 16-bit imnmediate, load to AT reg
    488             mMips->ORI(R_at, 0, src);
    489             src = R_at;
    490         }
    491         mMips->SUBU(Rd, src, Rn);   // subu with the parameters reversed
    492         break;
    493 
    494     case opMOV:
    495         if (Op2 < AMODE_REG) {  // op2 is reg # in this case
    496             mMips->MOVE(Rd, Op2);
    497         } else if (Op2 == AMODE_IMM) {
    498             if (amode.value > 0xffff) {
    499                 mMips->LUI(Rd, (amode.value >> 16));
    500                 if (amode.value & 0x0000ffff) {
    501                     mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff));
    502                 }
    503              } else {
    504                 mMips->ORI(Rd, 0, amode.value);
    505             }
    506         } else if (Op2 == AMODE_REG_IMM) {
    507             switch (amode.stype) {
    508             case LSL: mMips->SLL(Rd, amode.reg, amode.value); break;
    509             case LSR: mMips->SRL(Rd, amode.reg, amode.value); break;
    510             case ASR: mMips->SRA(Rd, amode.reg, amode.value); break;
    511             case ROR: if (mips32r2) {
    512                           mMips->ROTR(Rd, amode.reg, amode.value);
    513                       } else {
    514                           mMips->RORIsyn(Rd, amode.reg, amode.value);
    515                       }
    516                       break;
    517             }
    518         }
    519         else {
    520             // adr mode RRX is not used in GGL Assembler at this time
    521             mMips->UNIMPL();
    522         }
    523         break;
    524 
    525     case opMVN:     // this is a 1's complement: NOT
    526         if (Op2 < AMODE_REG) {  // op2 is reg # in this case
    527             mMips->NOR(Rd, Op2, 0);     // NOT is NOR with 0
    528             break;
    529         } else if (Op2 == AMODE_IMM) {
    530             if (amode.value > 0xffff) {
    531                 mMips->LUI(Rd, (amode.value >> 16));
    532                 if (amode.value & 0x0000ffff) {
    533                     mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff));
    534                 }
    535              } else {
    536                 mMips->ORI(Rd, 0, amode.value);
    537              }
    538         } else if (Op2 == AMODE_REG_IMM) {
    539             switch (amode.stype) {
    540             case LSL: mMips->SLL(Rd, amode.reg, amode.value); break;
    541             case LSR: mMips->SRL(Rd, amode.reg, amode.value); break;
    542             case ASR: mMips->SRA(Rd, amode.reg, amode.value); break;
    543             case ROR: if (mips32r2) {
    544                           mMips->ROTR(Rd, amode.reg, amode.value);
    545                       } else {
    546                           mMips->RORIsyn(Rd, amode.reg, amode.value);
    547                       }
    548                       break;
    549             }
    550         }
    551         else {
    552             // adr mode RRX is not used in GGL Assembler at this time
    553             mMips->UNIMPL();
    554         }
    555         mMips->NOR(Rd, Rd, 0);     // NOT is NOR with 0
    556         break;
    557 
    558     case opCMP:
    559         // Either operand of a CMP instr could get overwritten by a subsequent
    560         // conditional instruction, which is ok, _UNLESS_ there is a _second_
    561         // conditional instruction. Under MIPS, this requires doing the comparison
    562         // again (SLT), and the original operands must be available. (and this
    563         // pattern of multiple conditional instructions from same CMP _is_ used
    564         // in GGL-Assembler)
    565         //
    566         // For now, if a conditional instr overwrites the operands, we will
    567         // move them to dedicated temp regs. This is ugly, and inefficient,
    568         // and should be optimized.
    569         //
    570         // WARNING: making an _Assumption_ that CMP operand regs will NOT be
    571         // trashed by intervening NON-conditional instructions. In the general
    572         // case this is legal, but it is NOT currently done in GGL-Assembler.
    573 
    574         cond.type = CMP_COND;
    575         cond.r1 = Rn;
    576         if (dataProcAdrModes(Op2, src, false, R_cmp2) == SRC_REG) {
    577             cond.r2 = src;
    578         } else {                        // adr mode was SRC_IMM
    579             mMips->ORI(R_cmp2, R_zero, src);
    580             cond.r2 = R_cmp2;
    581         }
    582 
    583         break;
    584 
    585 
    586     case opTST:
    587     case opTEQ:
    588     case opCMN:
    589     case opADC:
    590     case opSBC:
    591     case opRSC:
    592         mMips->UNIMPL(); // currently unused in GGL Assembler code
    593         break;
    594     }
    595 
    596     if (cc != AL) {
    597         mMips->label(cond.label[cond.labelnum]);
    598     }
    599     if (s && opcode != opCMP) {
    600         cond.type = SBIT_COND;
    601         cond.r1 = Rd;
    602     }
    603 }
    604 
    605 
    606 
    607 #if 0
    608 #pragma mark -
    609 #pragma mark Multiply...
    610 #endif
    611 
    612 // multiply, accumulate
    613 void ArmToMipsAssembler::MLA(int cc, int s,
    614         int Rd, int Rm, int Rs, int Rn) {
    615 
    616     mArmPC[mInum++] = pc();  // save starting PC for this instr
    617 
    618     mMips->MUL(R_at, Rm, Rs);
    619     mMips->ADDU(Rd, R_at, Rn);
    620     if (s) {
    621         cond.type = SBIT_COND;
    622         cond.r1 = Rd;
    623     }
    624 }
    625 
    626 void ArmToMipsAssembler::MUL(int cc, int s,
    627         int Rd, int Rm, int Rs) {
    628     mArmPC[mInum++] = pc();
    629     mMips->MUL(Rd, Rm, Rs);
    630     if (s) {
    631         cond.type = SBIT_COND;
    632         cond.r1 = Rd;
    633     }
    634 }
    635 
    636 void ArmToMipsAssembler::UMULL(int cc, int s,
    637         int RdLo, int RdHi, int Rm, int Rs) {
    638     mArmPC[mInum++] = pc();
    639     mMips->MULT(Rm, Rs);
    640     mMips->MFHI(RdHi);
    641     mMips->MFLO(RdLo);
    642     if (s) {
    643         cond.type = SBIT_COND;
    644         cond.r1 = RdHi;     // BUG...
    645         LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n");
    646     }
    647 }
    648 
    649 void ArmToMipsAssembler::UMUAL(int cc, int s,
    650         int RdLo, int RdHi, int Rm, int Rs) {
    651     LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
    652                         "UMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
    653     // *mPC++ =    (cc<<28) | (1<<23) | (1<<21) | (s<<20) |
    654     //             (RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
    655     mArmPC[mInum++] = pc();
    656     mMips->NOP2();
    657     NOT_IMPLEMENTED();
    658     if (s) {
    659         cond.type = SBIT_COND;
    660         cond.r1 = RdHi;     // BUG...
    661         LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n");
    662     }
    663 }
    664 
    665 void ArmToMipsAssembler::SMULL(int cc, int s,
    666         int RdLo, int RdHi, int Rm, int Rs) {
    667     LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
    668                         "SMULL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
    669     // *mPC++ =    (cc<<28) | (1<<23) | (1<<22) | (s<<20) |
    670     //             (RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
    671     mArmPC[mInum++] = pc();
    672     mMips->NOP2();
    673     NOT_IMPLEMENTED();
    674     if (s) {
    675         cond.type = SBIT_COND;
    676         cond.r1 = RdHi;     // BUG...
    677         LOG_ALWAYS_FATAL("Condition on SMULL must be on 64-bit result\n");
    678     }
    679 }
    680 void ArmToMipsAssembler::SMUAL(int cc, int s,
    681         int RdLo, int RdHi, int Rm, int Rs) {
    682     LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
    683                         "SMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
    684     // *mPC++ =    (cc<<28) | (1<<23) | (1<<22) | (1<<21) | (s<<20) |
    685     //             (RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
    686     mArmPC[mInum++] = pc();
    687     mMips->NOP2();
    688     NOT_IMPLEMENTED();
    689     if (s) {
    690         cond.type = SBIT_COND;
    691         cond.r1 = RdHi;     // BUG...
    692         LOG_ALWAYS_FATAL("Condition on SMUAL must be on 64-bit result\n");
    693     }
    694 }
    695 
    696 
    697 
    698 #if 0
    699 #pragma mark -
    700 #pragma mark Branches...
    701 #endif
    702 
    703 // branches...
    704 
    705 void ArmToMipsAssembler::B(int cc, const char* label)
    706 {
    707     mArmPC[mInum++] = pc();
    708     if (cond.type == SBIT_COND) { cond.r2 = R_zero; }
    709 
    710     switch(cc) {
    711         case EQ: mMips->BEQ(cond.r1, cond.r2, label); break;
    712         case NE: mMips->BNE(cond.r1, cond.r2, label); break;
    713         case HS: mMips->BGEU(cond.r1, cond.r2, label); break;
    714         case LO: mMips->BLTU(cond.r1, cond.r2, label); break;
    715         case MI: mMips->BLT(cond.r1, cond.r2, label); break;
    716         case PL: mMips->BGE(cond.r1, cond.r2, label); break;
    717 
    718         case HI: mMips->BGTU(cond.r1, cond.r2, label); break;
    719         case LS: mMips->BLEU(cond.r1, cond.r2, label); break;
    720         case GE: mMips->BGE(cond.r1, cond.r2, label); break;
    721         case LT: mMips->BLT(cond.r1, cond.r2, label); break;
    722         case GT: mMips->BGT(cond.r1, cond.r2, label); break;
    723         case LE: mMips->BLE(cond.r1, cond.r2, label); break;
    724         case AL: mMips->B(label); break;
    725         case NV: /* B Never - no instruction */ break;
    726 
    727         case VS:
    728         case VC:
    729         default:
    730             LOG_ALWAYS_FATAL("Unsupported cc: %02x\n", cc);
    731             break;
    732     }
    733 }
    734 
    735 void ArmToMipsAssembler::BL(int cc, const char* label)
    736 {
    737     LOG_ALWAYS_FATAL("branch-and-link not supported yet\n");
    738     mArmPC[mInum++] = pc();
    739 }
    740 
    741 // no use for Branches with integer PC, but they're in the Interface class ....
    742 void ArmToMipsAssembler::B(int cc, uint32_t* to_pc)
    743 {
    744     LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
    745     mArmPC[mInum++] = pc();
    746 }
    747 
    748 void ArmToMipsAssembler::BL(int cc, uint32_t* to_pc)
    749 {
    750     LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
    751     mArmPC[mInum++] = pc();
    752 }
    753 
    754 void ArmToMipsAssembler::BX(int cc, int Rn)
    755 {
    756     LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
    757     mArmPC[mInum++] = pc();
    758 }
    759 
    760 
    761 
    762 #if 0
    763 #pragma mark -
    764 #pragma mark Data Transfer...
    765 #endif
    766 
    767 // data transfer...
    768 void ArmToMipsAssembler::LDR(int cc, int Rd, int Rn, uint32_t offset)
    769 {
    770     mArmPC[mInum++] = pc();
    771     // work-around for ARM default address mode of immed12_pre(0)
    772     if (offset > AMODE_UNSUPPORTED) offset = 0;
    773     switch (offset) {
    774         case 0:
    775             amode.value = 0;
    776             amode.writeback = 0;
    777             // fall thru to next case ....
    778         case AMODE_IMM_12_PRE:
    779             if (Rn == ARMAssemblerInterface::SP) {
    780                 Rn = R_sp;      // convert LDR via Arm SP to LW via Mips SP
    781             }
    782             mMips->LW(Rd, Rn, amode.value);
    783             if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
    784                 mMips->ADDIU(Rn, Rn, amode.value);
    785             }
    786             break;
    787         case AMODE_IMM_12_POST:
    788             if (Rn == ARMAssemblerInterface::SP) {
    789                 Rn = R_sp;      // convert STR thru Arm SP to STR thru Mips SP
    790             }
    791             mMips->LW(Rd, Rn, 0);
    792             mMips->ADDIU(Rn, Rn, amode.value);
    793             break;
    794         case AMODE_REG_SCALE_PRE:
    795             // we only support simple base + index, no advanced modes for this one yet
    796             mMips->ADDU(R_at, Rn, amode.reg);
    797             mMips->LW(Rd, R_at, 0);
    798             break;
    799     }
    800 }
    801 
    802 void ArmToMipsAssembler::LDRB(int cc, int Rd, int Rn, uint32_t offset)
    803 {
    804     mArmPC[mInum++] = pc();
    805     // work-around for ARM default address mode of immed12_pre(0)
    806     if (offset > AMODE_UNSUPPORTED) offset = 0;
    807     switch (offset) {
    808         case 0:
    809             amode.value = 0;
    810             amode.writeback = 0;
    811             // fall thru to next case ....
    812         case AMODE_IMM_12_PRE:
    813             mMips->LBU(Rd, Rn, amode.value);
    814             if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
    815                 mMips->ADDIU(Rn, Rn, amode.value);
    816             }
    817             break;
    818         case AMODE_IMM_12_POST:
    819             mMips->LBU(Rd, Rn, 0);
    820             mMips->ADDIU(Rn, Rn, amode.value);
    821             break;
    822         case AMODE_REG_SCALE_PRE:
    823             // we only support simple base + index, no advanced modes for this one yet
    824             mMips->ADDU(R_at, Rn, amode.reg);
    825             mMips->LBU(Rd, R_at, 0);
    826             break;
    827     }
    828 
    829 }
    830 
    831 void ArmToMipsAssembler::STR(int cc, int Rd, int Rn, uint32_t offset)
    832 {
    833     mArmPC[mInum++] = pc();
    834     // work-around for ARM default address mode of immed12_pre(0)
    835     if (offset > AMODE_UNSUPPORTED) offset = 0;
    836     switch (offset) {
    837         case 0:
    838             amode.value = 0;
    839             amode.writeback = 0;
    840             // fall thru to next case ....
    841         case AMODE_IMM_12_PRE:
    842             if (Rn == ARMAssemblerInterface::SP) {
    843                 Rn = R_sp;  // convert STR thru Arm SP to SW thru Mips SP
    844             }
    845             if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
    846                 // If we will writeback, then update the index reg, then store.
    847                 // This correctly handles stack-push case.
    848                 mMips->ADDIU(Rn, Rn, amode.value);
    849                 mMips->SW(Rd, Rn, 0);
    850             } else {
    851                 // No writeback so store offset by value
    852                 mMips->SW(Rd, Rn, amode.value);
    853             }
    854             break;
    855         case AMODE_IMM_12_POST:
    856             mMips->SW(Rd, Rn, 0);
    857             mMips->ADDIU(Rn, Rn, amode.value);  // post index always writes back
    858             break;
    859         case AMODE_REG_SCALE_PRE:
    860             // we only support simple base + index, no advanced modes for this one yet
    861             mMips->ADDU(R_at, Rn, amode.reg);
    862             mMips->SW(Rd, R_at, 0);
    863             break;
    864     }
    865 }
    866 
    867 void ArmToMipsAssembler::STRB(int cc, int Rd, int Rn, uint32_t offset)
    868 {
    869     mArmPC[mInum++] = pc();
    870     // work-around for ARM default address mode of immed12_pre(0)
    871     if (offset > AMODE_UNSUPPORTED) offset = 0;
    872     switch (offset) {
    873         case 0:
    874             amode.value = 0;
    875             amode.writeback = 0;
    876             // fall thru to next case ....
    877         case AMODE_IMM_12_PRE:
    878             mMips->SB(Rd, Rn, amode.value);
    879             if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
    880                 mMips->ADDIU(Rn, Rn, amode.value);
    881             }
    882             break;
    883         case AMODE_IMM_12_POST:
    884             mMips->SB(Rd, Rn, 0);
    885             mMips->ADDIU(Rn, Rn, amode.value);
    886             break;
    887         case AMODE_REG_SCALE_PRE:
    888             // we only support simple base + index, no advanced modes for this one yet
    889             mMips->ADDU(R_at, Rn, amode.reg);
    890             mMips->SB(Rd, R_at, 0);
    891             break;
    892     }
    893 }
    894 
    895 void ArmToMipsAssembler::LDRH(int cc, int Rd, int Rn, uint32_t offset)
    896 {
    897     mArmPC[mInum++] = pc();
    898     // work-around for ARM default address mode of immed8_pre(0)
    899     if (offset > AMODE_UNSUPPORTED) offset = 0;
    900     switch (offset) {
    901         case 0:
    902             amode.value = 0;
    903             // fall thru to next case ....
    904         case AMODE_IMM_8_PRE:      // no support yet for writeback
    905             mMips->LHU(Rd, Rn, amode.value);
    906             break;
    907         case AMODE_IMM_8_POST:
    908             mMips->LHU(Rd, Rn, 0);
    909             mMips->ADDIU(Rn, Rn, amode.value);
    910             break;
    911         case AMODE_REG_PRE:
    912             // we only support simple base +/- index
    913             if (amode.reg >= 0) {
    914                 mMips->ADDU(R_at, Rn, amode.reg);
    915             } else {
    916                 mMips->SUBU(R_at, Rn, abs(amode.reg));
    917             }
    918             mMips->LHU(Rd, R_at, 0);
    919             break;
    920     }
    921 }
    922 
    923 void ArmToMipsAssembler::LDRSB(int cc, int Rd, int Rn, uint32_t offset)
    924 {
    925     mArmPC[mInum++] = pc();
    926     mMips->NOP2();
    927     NOT_IMPLEMENTED();
    928 }
    929 
    930 void ArmToMipsAssembler::LDRSH(int cc, int Rd, int Rn, uint32_t offset)
    931 {
    932     mArmPC[mInum++] = pc();
    933     mMips->NOP2();
    934     NOT_IMPLEMENTED();
    935 }
    936 
    937 void ArmToMipsAssembler::STRH(int cc, int Rd, int Rn, uint32_t offset)
    938 {
    939     mArmPC[mInum++] = pc();
    940     // work-around for ARM default address mode of immed8_pre(0)
    941     if (offset > AMODE_UNSUPPORTED) offset = 0;
    942     switch (offset) {
    943         case 0:
    944             amode.value = 0;
    945             // fall thru to next case ....
    946         case AMODE_IMM_8_PRE:      // no support yet for writeback
    947             mMips->SH(Rd, Rn, amode.value);
    948             break;
    949         case AMODE_IMM_8_POST:
    950             mMips->SH(Rd, Rn, 0);
    951             mMips->ADDIU(Rn, Rn, amode.value);
    952             break;
    953         case AMODE_REG_PRE:
    954             // we only support simple base +/- index
    955             if (amode.reg >= 0) {
    956                 mMips->ADDU(R_at, Rn, amode.reg);
    957             } else {
    958                 mMips->SUBU(R_at, Rn, abs(amode.reg));
    959             }
    960             mMips->SH(Rd, R_at, 0);
    961             break;
    962     }
    963 }
    964 
    965 
    966 
    967 #if 0
    968 #pragma mark -
    969 #pragma mark Block Data Transfer...
    970 #endif
    971 
    972 // block data transfer...
    973 void ArmToMipsAssembler::LDM(int cc, int dir,
    974         int Rn, int W, uint32_t reg_list)
    975 {   //                        ED FD EA FA      IB IA DB DA
    976     // const uint8_t P[8] = { 1, 0, 1, 0,      1, 0, 1, 0 };
    977     // const uint8_t U[8] = { 1, 1, 0, 0,      1, 1, 0, 0 };
    978     // *mPC++ = (cc<<28) | (4<<25) | (uint32_t(P[dir])<<24) |
    979     //         (uint32_t(U[dir])<<23) | (1<<20) | (W<<21) | (Rn<<16) | reg_list;
    980     mArmPC[mInum++] = pc();
    981     mMips->NOP2();
    982     NOT_IMPLEMENTED();
    983 }
    984 
    985 void ArmToMipsAssembler::STM(int cc, int dir,
    986         int Rn, int W, uint32_t reg_list)
    987 {   //                        FA EA FD ED      IB IA DB DA
    988     // const uint8_t P[8] = { 0, 1, 0, 1,      1, 0, 1, 0 };
    989     // const uint8_t U[8] = { 0, 0, 1, 1,      1, 1, 0, 0 };
    990     // *mPC++ = (cc<<28) | (4<<25) | (uint32_t(P[dir])<<24) |
    991     //         (uint32_t(U[dir])<<23) | (0<<20) | (W<<21) | (Rn<<16) | reg_list;
    992     mArmPC[mInum++] = pc();
    993     mMips->NOP2();
    994     NOT_IMPLEMENTED();
    995 }
    996 
    997 
    998 
    999 #if 0
   1000 #pragma mark -
   1001 #pragma mark Special...
   1002 #endif
   1003 
   1004 // special...
   1005 void ArmToMipsAssembler::SWP(int cc, int Rn, int Rd, int Rm) {
   1006     // *mPC++ = (cc<<28) | (2<<23) | (Rn<<16) | (Rd << 12) | 0x90 | Rm;
   1007     mArmPC[mInum++] = pc();
   1008     mMips->NOP2();
   1009     NOT_IMPLEMENTED();
   1010 }
   1011 
   1012 void ArmToMipsAssembler::SWPB(int cc, int Rn, int Rd, int Rm) {
   1013     // *mPC++ = (cc<<28) | (2<<23) | (1<<22) | (Rn<<16) | (Rd << 12) | 0x90 | Rm;
   1014     mArmPC[mInum++] = pc();
   1015     mMips->NOP2();
   1016     NOT_IMPLEMENTED();
   1017 }
   1018 
   1019 void ArmToMipsAssembler::SWI(int cc, uint32_t comment) {
   1020     // *mPC++ = (cc<<28) | (0xF<<24) | comment;
   1021     mArmPC[mInum++] = pc();
   1022     mMips->NOP2();
   1023     NOT_IMPLEMENTED();
   1024 }
   1025 
   1026 
   1027 #if 0
   1028 #pragma mark -
   1029 #pragma mark DSP instructions...
   1030 #endif
   1031 
   1032 // DSP instructions...
   1033 void ArmToMipsAssembler::PLD(int Rn, uint32_t offset) {
   1034     LOG_ALWAYS_FATAL_IF(!((offset&(1<<24)) && !(offset&(1<<21))),
   1035                         "PLD only P=1, W=0");
   1036     // *mPC++ = 0xF550F000 | (Rn<<16) | offset;
   1037     mArmPC[mInum++] = pc();
   1038     mMips->NOP2();
   1039     NOT_IMPLEMENTED();
   1040 }
   1041 
   1042 void ArmToMipsAssembler::CLZ(int cc, int Rd, int Rm)
   1043 {
   1044     mArmPC[mInum++] = pc();
   1045     mMips->CLZ(Rd, Rm);
   1046 }
   1047 
   1048 void ArmToMipsAssembler::QADD(int cc,  int Rd, int Rm, int Rn)
   1049 {
   1050     // *mPC++ = (cc<<28) | 0x1000050 | (Rn<<16) | (Rd<<12) | Rm;
   1051     mArmPC[mInum++] = pc();
   1052     mMips->NOP2();
   1053     NOT_IMPLEMENTED();
   1054 }
   1055 
   1056 void ArmToMipsAssembler::QDADD(int cc,  int Rd, int Rm, int Rn)
   1057 {
   1058     // *mPC++ = (cc<<28) | 0x1400050 | (Rn<<16) | (Rd<<12) | Rm;
   1059     mArmPC[mInum++] = pc();
   1060     mMips->NOP2();
   1061     NOT_IMPLEMENTED();
   1062 }
   1063 
   1064 void ArmToMipsAssembler::QSUB(int cc,  int Rd, int Rm, int Rn)
   1065 {
   1066     // *mPC++ = (cc<<28) | 0x1200050 | (Rn<<16) | (Rd<<12) | Rm;
   1067     mArmPC[mInum++] = pc();
   1068     mMips->NOP2();
   1069     NOT_IMPLEMENTED();
   1070 }
   1071 
   1072 void ArmToMipsAssembler::QDSUB(int cc,  int Rd, int Rm, int Rn)
   1073 {
   1074     // *mPC++ = (cc<<28) | 0x1600050 | (Rn<<16) | (Rd<<12) | Rm;
   1075     mArmPC[mInum++] = pc();
   1076     mMips->NOP2();
   1077     NOT_IMPLEMENTED();
   1078 }
   1079 
   1080 // 16 x 16 signed multiply (like SMLAxx without the accumulate)
   1081 void ArmToMipsAssembler::SMUL(int cc, int xy,
   1082                 int Rd, int Rm, int Rs)
   1083 {
   1084     mArmPC[mInum++] = pc();
   1085 
   1086     // the 16 bits may be in the top or bottom half of 32-bit source reg,
   1087     // as defined by the codes BB, BT, TB, TT (compressed param xy)
   1088     // where x corresponds to Rm and y to Rs
   1089 
   1090     // select half-reg for Rm
   1091     if (xy & xyTB) {
   1092         // use top 16-bits
   1093         mMips->SRA(R_at, Rm, 16);
   1094     } else {
   1095         // use bottom 16, but sign-extend to 32
   1096         if (mips32r2) {
   1097             mMips->SEH(R_at, Rm);
   1098         } else {
   1099             mMips->SLL(R_at, Rm, 16);
   1100             mMips->SRA(R_at, R_at, 16);
   1101         }
   1102     }
   1103     // select half-reg for Rs
   1104     if (xy & xyBT) {
   1105         // use top 16-bits
   1106         mMips->SRA(R_at2, Rs, 16);
   1107     } else {
   1108         // use bottom 16, but sign-extend to 32
   1109         if (mips32r2) {
   1110             mMips->SEH(R_at2, Rs);
   1111         } else {
   1112             mMips->SLL(R_at2, Rs, 16);
   1113             mMips->SRA(R_at2, R_at2, 16);
   1114         }
   1115     }
   1116     mMips->MUL(Rd, R_at, R_at2);
   1117 }
   1118 
   1119 // signed 32b x 16b multiple, save top 32-bits of 48-bit result
   1120 void ArmToMipsAssembler::SMULW(int cc, int y,
   1121                 int Rd, int Rm, int Rs)
   1122 {
   1123     mArmPC[mInum++] = pc();
   1124 
   1125     // the selector yT or yB refers to reg Rs
   1126     if (y & yT) {
   1127         // zero the bottom 16-bits, with 2 shifts, it can affect result
   1128         mMips->SRL(R_at, Rs, 16);
   1129         mMips->SLL(R_at, R_at, 16);
   1130 
   1131     } else {
   1132         // move low 16-bit half, to high half
   1133         mMips->SLL(R_at, Rs, 16);
   1134     }
   1135     mMips->MULT(Rm, R_at);
   1136     mMips->MFHI(Rd);
   1137 }
   1138 
   1139 // 16 x 16 signed multiply, accumulate: Rd = Rm{16} * Rs{16} + Rn
   1140 void ArmToMipsAssembler::SMLA(int cc, int xy,
   1141                 int Rd, int Rm, int Rs, int Rn)
   1142 {
   1143     mArmPC[mInum++] = pc();
   1144 
   1145     // the 16 bits may be in the top or bottom half of 32-bit source reg,
   1146     // as defined by the codes BB, BT, TB, TT (compressed param xy)
   1147     // where x corresponds to Rm and y to Rs
   1148 
   1149     // select half-reg for Rm
   1150     if (xy & xyTB) {
   1151         // use top 16-bits
   1152         mMips->SRA(R_at, Rm, 16);
   1153     } else {
   1154         // use bottom 16, but sign-extend to 32
   1155         if (mips32r2) {
   1156             mMips->SEH(R_at, Rm);
   1157         } else {
   1158             mMips->SLL(R_at, Rm, 16);
   1159             mMips->SRA(R_at, R_at, 16);
   1160         }
   1161     }
   1162     // select half-reg for Rs
   1163     if (xy & xyBT) {
   1164         // use top 16-bits
   1165         mMips->SRA(R_at2, Rs, 16);
   1166     } else {
   1167         // use bottom 16, but sign-extend to 32
   1168         if (mips32r2) {
   1169             mMips->SEH(R_at2, Rs);
   1170         } else {
   1171             mMips->SLL(R_at2, Rs, 16);
   1172             mMips->SRA(R_at2, R_at2, 16);
   1173         }
   1174     }
   1175 
   1176     mMips->MUL(R_at, R_at, R_at2);
   1177     mMips->ADDU(Rd, R_at, Rn);
   1178 }
   1179 
   1180 void ArmToMipsAssembler::SMLAL(int cc, int xy,
   1181                 int RdHi, int RdLo, int Rs, int Rm)
   1182 {
   1183     // *mPC++ = (cc<<28) | 0x1400080 | (RdHi<<16) | (RdLo<<12) | (Rs<<8) | (xy<<4) | Rm;
   1184     mArmPC[mInum++] = pc();
   1185     mMips->NOP2();
   1186     NOT_IMPLEMENTED();
   1187 }
   1188 
   1189 void ArmToMipsAssembler::SMLAW(int cc, int y,
   1190                 int Rd, int Rm, int Rs, int Rn)
   1191 {
   1192     // *mPC++ = (cc<<28) | 0x1200080 | (Rd<<16) | (Rn<<12) | (Rs<<8) | (y<<4) | Rm;
   1193     mArmPC[mInum++] = pc();
   1194     mMips->NOP2();
   1195     NOT_IMPLEMENTED();
   1196 }
   1197 
   1198 // used by ARMv6 version of GGLAssembler::filter32
   1199 void ArmToMipsAssembler::UXTB16(int cc, int Rd, int Rm, int rotate)
   1200 {
   1201     mArmPC[mInum++] = pc();
   1202 
   1203     //Rd[31:16] := ZeroExtend((Rm ROR (8 * sh))[23:16]),
   1204     //Rd[15:0] := ZeroExtend((Rm ROR (8 * sh))[7:0]). sh 0-3.
   1205 
   1206     mMips->ROTR(Rm, Rm, rotate * 8);
   1207     mMips->AND(Rd, Rm, 0x00FF00FF);
   1208 }
   1209 
   1210 void ArmToMipsAssembler::UBFX(int cc, int Rd, int Rn, int lsb, int width)
   1211 {
   1212      /* Placeholder for UBFX */
   1213      mArmPC[mInum++] = pc();
   1214 
   1215      mMips->NOP2();
   1216      NOT_IMPLEMENTED();
   1217 }
   1218 
   1219 
   1220 
   1221 
   1222 
   1223 #if 0
   1224 #pragma mark -
   1225 #pragma mark MIPS Assembler...
   1226 #endif
   1227 
   1228 
   1229 //**************************************************************************
   1230 //**************************************************************************
   1231 //**************************************************************************
   1232 
   1233 
   1234 /* mips assembler
   1235 ** this is a subset of mips32r2, targeted specifically at ARM instruction
   1236 ** replacement in the pixelflinger/codeflinger code.
   1237 **
   1238 ** To that end, there is no need for floating point, or priviledged
   1239 ** instructions. This all runs in user space, no float.
   1240 **
   1241 ** The syntax makes no attempt to be as complete as the assember, with
   1242 ** synthetic instructions, and automatic recognition of immedate operands
   1243 ** (use the immediate form of the instruction), etc.
   1244 **
   1245 ** We start with mips32r1, and may add r2 and dsp extensions if cpu
   1246 ** supports. Decision will be made at compile time, based on gcc
   1247 ** options. (makes sense since android will be built for a a specific
   1248 ** device)
   1249 */
   1250 
   1251 MIPSAssembler::MIPSAssembler(const sp<Assembly>& assembly, ArmToMipsAssembler *parent)
   1252     : mParent(parent),
   1253     mAssembly(assembly)
   1254 {
   1255     mBase = mPC = (uint32_t *)assembly->base();
   1256     mDuration = ggl_system_time();
   1257 }
   1258 
   1259 MIPSAssembler::~MIPSAssembler()
   1260 {
   1261 }
   1262 
   1263 
   1264 uint32_t* MIPSAssembler::pc() const
   1265 {
   1266     return mPC;
   1267 }
   1268 
   1269 uint32_t* MIPSAssembler::base() const
   1270 {
   1271     return mBase;
   1272 }
   1273 
   1274 void MIPSAssembler::reset()
   1275 {
   1276     mBase = mPC = (uint32_t *)mAssembly->base();
   1277     mBranchTargets.clear();
   1278     mLabels.clear();
   1279     mLabelsInverseMapping.clear();
   1280     mComments.clear();
   1281 }
   1282 
   1283 
   1284 // convert tabs to spaces, and remove any newline
   1285 // works with strings of limited size (makes a temp copy)
   1286 #define TABSTOP 8
   1287 void MIPSAssembler::string_detab(char *s)
   1288 {
   1289     char *os = s;
   1290     char temp[100];
   1291     char *t = temp;
   1292     int len = 99;
   1293     int i = TABSTOP;
   1294 
   1295     while (*s && len-- > 0) {
   1296         if (*s == '\n') { s++; continue; }
   1297         if (*s == '\t') {
   1298             s++;
   1299             for ( ; i>0; i--) {*t++ = ' '; len--; }
   1300         } else {
   1301             *t++ = *s++;
   1302         }
   1303         if (i <= 0) i = TABSTOP;
   1304         i--;
   1305     }
   1306     *t = '\0';
   1307     strcpy(os, temp);
   1308 }
   1309 
   1310 void MIPSAssembler::string_pad(char *s, int padded_len)
   1311 {
   1312     int len = strlen(s);
   1313     s += len;
   1314     for (int i = padded_len - len; i > 0; --i) {
   1315         *s++ = ' ';
   1316     }
   1317     *s = '\0';
   1318 }
   1319 
   1320 // ----------------------------------------------------------------------------
   1321 
   1322 void MIPSAssembler::disassemble(const char* name)
   1323 {
   1324     char di_buf[140];
   1325 
   1326     if (name) {
   1327         ALOGW("%s:\n", name);
   1328     }
   1329 
   1330     bool arm_disasm_fmt = (mParent->mArmDisassemblyBuffer == NULL) ? false : true;
   1331 
   1332     typedef char dstr[40];
   1333     dstr *lines = (dstr *)mParent->mArmDisassemblyBuffer;
   1334 
   1335     if (mParent->mArmDisassemblyBuffer != NULL) {
   1336         for (int i=0; i<mParent->mArmInstrCount; ++i) {
   1337             string_detab(lines[i]);
   1338         }
   1339     }
   1340 
   1341     // iArm is an index to Arm instructions 1...n for this assembly sequence
   1342     // mArmPC[iArm] holds the value of the Mips-PC for the first MIPS
   1343     // instruction corresponding to that Arm instruction number
   1344 
   1345     int iArm = 0;
   1346     size_t count = pc()-base();
   1347     uint32_t* mipsPC = base();
   1348     while (count--) {
   1349         ssize_t label = mLabelsInverseMapping.indexOfKey(mipsPC);
   1350         if (label >= 0) {
   1351             ALOGW("%s:\n", mLabelsInverseMapping.valueAt(label));
   1352         }
   1353         ssize_t comment = mComments.indexOfKey(mipsPC);
   1354         if (comment >= 0) {
   1355             ALOGW("; %s\n", mComments.valueAt(comment));
   1356         }
   1357         // ALOGW("%08x:    %08x    ", int(i), int(i[0]));
   1358         ::mips_disassem(mipsPC, di_buf, arm_disasm_fmt);
   1359         string_detab(di_buf);
   1360         string_pad(di_buf, 30);
   1361         ALOGW("%08x:    %08x    %s", uint32_t(mipsPC), uint32_t(*mipsPC), di_buf);
   1362         mipsPC++;
   1363     }
   1364 }
   1365 
   1366 void MIPSAssembler::comment(const char* string)
   1367 {
   1368     mComments.add(pc(), string);
   1369 }
   1370 
   1371 void MIPSAssembler::label(const char* theLabel)
   1372 {
   1373     mLabels.add(theLabel, pc());
   1374     mLabelsInverseMapping.add(pc(), theLabel);
   1375 }
   1376 
   1377 
   1378 void MIPSAssembler::prolog()
   1379 {
   1380     // empty - done in ArmToMipsAssembler
   1381 }
   1382 
   1383 void MIPSAssembler::epilog(uint32_t touched)
   1384 {
   1385     // empty - done in ArmToMipsAssembler
   1386 }
   1387 
   1388 int MIPSAssembler::generate(const char* name)
   1389 {
   1390     // fixup all the branches
   1391     size_t count = mBranchTargets.size();
   1392     while (count--) {
   1393         const branch_target_t& bt = mBranchTargets[count];
   1394         uint32_t* target_pc = mLabels.valueFor(bt.label);
   1395         LOG_ALWAYS_FATAL_IF(!target_pc,
   1396                 "error resolving branch targets, target_pc is null");
   1397         int32_t offset = int32_t(target_pc - (bt.pc+1));
   1398         *bt.pc |= offset & 0x00FFFF;
   1399     }
   1400 
   1401     mAssembly->resize( int(pc()-base())*4 );
   1402 
   1403     // the instruction & data caches are flushed by CodeCache
   1404     const int64_t duration = ggl_system_time() - mDuration;
   1405     const char * const format = "generated %s (%d ins) at [%p:%p] in %lld ns\n";
   1406     ALOGI(format, name, int(pc()-base()), base(), pc(), duration);
   1407 
   1408 #if defined(WITH_LIB_HARDWARE)
   1409     if (__builtin_expect(mQemuTracing, 0)) {
   1410         int err = qemu_add_mapping(int(base()), name);
   1411         mQemuTracing = (err >= 0);
   1412     }
   1413 #endif
   1414 
   1415     char value[PROPERTY_VALUE_MAX];
   1416     value[0] = '\0';
   1417 
   1418     property_get("debug.pf.disasm", value, "0");
   1419 
   1420     if (atoi(value) != 0) {
   1421         disassemble(name);
   1422     }
   1423 
   1424     return NO_ERROR;
   1425 }
   1426 
   1427 uint32_t* MIPSAssembler::pcForLabel(const char* label)
   1428 {
   1429     return mLabels.valueFor(label);
   1430 }
   1431 
   1432 
   1433 
   1434 #if 0
   1435 #pragma mark -
   1436 #pragma mark Arithmetic...
   1437 #endif
   1438 
   1439 void MIPSAssembler::ADDU(int Rd, int Rs, int Rt)
   1440 {
   1441     *mPC++ = (spec_op<<OP_SHF) | (addu_fn<<FUNC_SHF)
   1442                     | (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF);
   1443 }
   1444 
   1445 // MD00086 pdf says this is: ADDIU rt, rs, imm -- they do not use Rd
   1446 void MIPSAssembler::ADDIU(int Rt, int Rs, int16_t imm)
   1447 {
   1448     *mPC++ = (addiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16);
   1449 }
   1450 
   1451 
   1452 void MIPSAssembler::SUBU(int Rd, int Rs, int Rt)
   1453 {
   1454     *mPC++ = (spec_op<<OP_SHF) | (subu_fn<<FUNC_SHF) |
   1455                         (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ;
   1456 }
   1457 
   1458 
   1459 void MIPSAssembler::SUBIU(int Rt, int Rs, int16_t imm)   // really addiu(d, s, -j)
   1460 {
   1461     *mPC++ = (addiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | ((-imm) & MSK_16);
   1462 }
   1463 
   1464 
   1465 void MIPSAssembler::NEGU(int Rd, int Rs)    // really subu(d, zero, s)
   1466 {
   1467     MIPSAssembler::SUBU(Rd, 0, Rs);
   1468 }
   1469 
   1470 void MIPSAssembler::MUL(int Rd, int Rs, int Rt)
   1471 {
   1472     *mPC++ = (spec2_op<<OP_SHF) | (mul_fn<<FUNC_SHF) |
   1473                         (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ;
   1474 }
   1475 
   1476 void MIPSAssembler::MULT(int Rs, int Rt)    // dest is hi,lo
   1477 {
   1478     *mPC++ = (spec_op<<OP_SHF) | (mult_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF);
   1479 }
   1480 
   1481 void MIPSAssembler::MULTU(int Rs, int Rt)    // dest is hi,lo
   1482 {
   1483     *mPC++ = (spec_op<<OP_SHF) | (multu_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF);
   1484 }
   1485 
   1486 void MIPSAssembler::MADD(int Rs, int Rt)    // hi,lo = hi,lo + Rs * Rt
   1487 {
   1488     *mPC++ = (spec2_op<<OP_SHF) | (madd_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF);
   1489 }
   1490 
   1491 void MIPSAssembler::MADDU(int Rs, int Rt)    // hi,lo = hi,lo + Rs * Rt
   1492 {
   1493     *mPC++ = (spec2_op<<OP_SHF) | (maddu_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF);
   1494 }
   1495 
   1496 
   1497 void MIPSAssembler::MSUB(int Rs, int Rt)    // hi,lo = hi,lo - Rs * Rt
   1498 {
   1499     *mPC++ = (spec2_op<<OP_SHF) | (msub_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF);
   1500 }
   1501 
   1502 void MIPSAssembler::MSUBU(int Rs, int Rt)    // hi,lo = hi,lo - Rs * Rt
   1503 {
   1504     *mPC++ = (spec2_op<<OP_SHF) | (msubu_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF);
   1505 }
   1506 
   1507 
   1508 void MIPSAssembler::SEB(int Rd, int Rt)    // sign-extend byte (mips32r2)
   1509 {
   1510     *mPC++ = (spec3_op<<OP_SHF) | (bshfl_fn<<FUNC_SHF) | (seb_fn << SA_SHF) |
   1511                     (Rt<<RT_SHF) | (Rd<<RD_SHF);
   1512 }
   1513 
   1514 void MIPSAssembler::SEH(int Rd, int Rt)    // sign-extend half-word (mips32r2)
   1515 {
   1516     *mPC++ = (spec3_op<<OP_SHF) | (bshfl_fn<<FUNC_SHF) | (seh_fn << SA_SHF) |
   1517                     (Rt<<RT_SHF) | (Rd<<RD_SHF);
   1518 }
   1519 
   1520 
   1521 
   1522 #if 0
   1523 #pragma mark -
   1524 #pragma mark Comparisons...
   1525 #endif
   1526 
   1527 void MIPSAssembler::SLT(int Rd, int Rs, int Rt)
   1528 {
   1529     *mPC++ = (spec_op<<OP_SHF) | (slt_fn<<FUNC_SHF) |
   1530                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF);
   1531 }
   1532 
   1533 void MIPSAssembler::SLTI(int Rt, int Rs, int16_t imm)
   1534 {
   1535     *mPC++ = (slti_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16);
   1536 }
   1537 
   1538 
   1539 void MIPSAssembler::SLTU(int Rd, int Rs, int Rt)
   1540 {
   1541     *mPC++ = (spec_op<<OP_SHF) | (sltu_fn<<FUNC_SHF) |
   1542                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF);
   1543 }
   1544 
   1545 void MIPSAssembler::SLTIU(int Rt, int Rs, int16_t imm)
   1546 {
   1547     *mPC++ = (sltiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16);
   1548 }
   1549 
   1550 
   1551 
   1552 #if 0
   1553 #pragma mark -
   1554 #pragma mark Logical...
   1555 #endif
   1556 
   1557 void MIPSAssembler::AND(int Rd, int Rs, int Rt)
   1558 {
   1559     *mPC++ = (spec_op<<OP_SHF) | (and_fn<<FUNC_SHF) |
   1560                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF);
   1561 }
   1562 
   1563 void MIPSAssembler::ANDI(int Rt, int Rs, uint16_t imm)      // todo: support larger immediate
   1564 {
   1565     *mPC++ = (andi_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16);
   1566 }
   1567 
   1568 
   1569 void MIPSAssembler::OR(int Rd, int Rs, int Rt)
   1570 {
   1571     *mPC++ = (spec_op<<OP_SHF) | (or_fn<<FUNC_SHF) |
   1572                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF);
   1573 }
   1574 
   1575 void MIPSAssembler::ORI(int Rt, int Rs, uint16_t imm)
   1576 {
   1577     *mPC++ = (ori_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16);
   1578 }
   1579 
   1580 void MIPSAssembler::NOR(int Rd, int Rs, int Rt)
   1581 {
   1582     *mPC++ = (spec_op<<OP_SHF) | (nor_fn<<FUNC_SHF) |
   1583                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF);
   1584 }
   1585 
   1586 void MIPSAssembler::NOT(int Rd, int Rs)
   1587 {
   1588     MIPSAssembler::NOR(Rd, Rs, 0);  // NOT(d,s) = NOR(d,s,zero)
   1589 }
   1590 
   1591 void MIPSAssembler::XOR(int Rd, int Rs, int Rt)
   1592 {
   1593     *mPC++ = (spec_op<<OP_SHF) | (xor_fn<<FUNC_SHF) |
   1594                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF);
   1595 }
   1596 
   1597 void MIPSAssembler::XORI(int Rt, int Rs, uint16_t imm)  // todo: support larger immediate
   1598 {
   1599     *mPC++ = (xori_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16);
   1600 }
   1601 
   1602 void MIPSAssembler::SLL(int Rd, int Rt, int shft)
   1603 {
   1604     *mPC++ = (spec_op<<OP_SHF) | (sll_fn<<FUNC_SHF) |
   1605                         (Rd<<RD_SHF) | (Rt<<RT_SHF) | (shft<<RE_SHF);
   1606 }
   1607 
   1608 void MIPSAssembler::SLLV(int Rd, int Rt, int Rs)
   1609 {
   1610     *mPC++ = (spec_op<<OP_SHF) | (sllv_fn<<FUNC_SHF) |
   1611                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF);
   1612 }
   1613 
   1614 void MIPSAssembler::SRL(int Rd, int Rt, int shft)
   1615 {
   1616     *mPC++ = (spec_op<<OP_SHF) | (srl_fn<<FUNC_SHF) |
   1617                         (Rd<<RD_SHF) | (Rt<<RT_SHF) | (shft<<RE_SHF);
   1618 }
   1619 
   1620 void MIPSAssembler::SRLV(int Rd, int Rt, int Rs)
   1621 {
   1622     *mPC++ = (spec_op<<OP_SHF) | (srlv_fn<<FUNC_SHF) |
   1623                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF);
   1624 }
   1625 
   1626 void MIPSAssembler::SRA(int Rd, int Rt, int shft)
   1627 {
   1628     *mPC++ = (spec_op<<OP_SHF) | (sra_fn<<FUNC_SHF) |
   1629                         (Rd<<RD_SHF) | (Rt<<RT_SHF) | (shft<<RE_SHF);
   1630 }
   1631 
   1632 void MIPSAssembler::SRAV(int Rd, int Rt, int Rs)
   1633 {
   1634     *mPC++ = (spec_op<<OP_SHF) | (srav_fn<<FUNC_SHF) |
   1635                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF);
   1636 }
   1637 
   1638 void MIPSAssembler::ROTR(int Rd, int Rt, int shft)      // mips32r2
   1639 {
   1640     // note weird encoding (SRL + 1)
   1641     *mPC++ = (spec_op<<OP_SHF) | (srl_fn<<FUNC_SHF) |
   1642                         (1<<RS_SHF) | (Rd<<RD_SHF) | (Rt<<RT_SHF) | (shft<<RE_SHF);
   1643 }
   1644 
   1645 void MIPSAssembler::ROTRV(int Rd, int Rt, int Rs)       // mips32r2
   1646 {
   1647     // note weird encoding (SRLV + 1)
   1648     *mPC++ = (spec_op<<OP_SHF) | (srlv_fn<<FUNC_SHF) |
   1649                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF) | (1<<RE_SHF);
   1650 }
   1651 
   1652 // uses at2 register (mapped to some appropriate mips reg)
   1653 void MIPSAssembler::RORsyn(int Rd, int Rt, int Rs)
   1654 {
   1655     // synthetic: d = t rotated by s
   1656     MIPSAssembler::NEGU(R_at2, Rs);
   1657     MIPSAssembler::SLLV(R_at2, Rt, R_at2);
   1658     MIPSAssembler::SRLV(Rd, Rt, Rs);
   1659     MIPSAssembler::OR(Rd, Rd, R_at2);
   1660 }
   1661 
   1662 // immediate version - uses at2 register (mapped to some appropriate mips reg)
   1663 void MIPSAssembler::RORIsyn(int Rd, int Rt, int rot)
   1664 {
   1665     // synthetic: d = t rotated by immed rot
   1666     // d = s >> rot | s << (32-rot)
   1667     MIPSAssembler::SLL(R_at2, Rt, 32-rot);
   1668     MIPSAssembler::SRL(Rd, Rt, rot);
   1669     MIPSAssembler::OR(Rd, Rd, R_at2);
   1670 }
   1671 
   1672 void MIPSAssembler::CLO(int Rd, int Rs)
   1673 {
   1674     // Rt field must have same gpr # as Rd
   1675     *mPC++ = (spec2_op<<OP_SHF) | (clo_fn<<FUNC_SHF) |
   1676                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rd<<RT_SHF);
   1677 }
   1678 
   1679 void MIPSAssembler::CLZ(int Rd, int Rs)
   1680 {
   1681     // Rt field must have same gpr # as Rd
   1682     *mPC++ = (spec2_op<<OP_SHF) | (clz_fn<<FUNC_SHF) |
   1683                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rd<<RT_SHF);
   1684 }
   1685 
   1686 void MIPSAssembler::WSBH(int Rd, int Rt)      // mips32r2
   1687 {
   1688     *mPC++ = (spec3_op<<OP_SHF) | (bshfl_fn<<FUNC_SHF) | (wsbh_fn << SA_SHF) |
   1689                         (Rt<<RT_SHF) | (Rd<<RD_SHF);
   1690 }
   1691 
   1692 
   1693 
   1694 #if 0
   1695 #pragma mark -
   1696 #pragma mark Load/store...
   1697 #endif
   1698 
   1699 void MIPSAssembler::LW(int Rt, int Rbase, int16_t offset)
   1700 {
   1701     *mPC++ = (lw_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1702 }
   1703 
   1704 void MIPSAssembler::SW(int Rt, int Rbase, int16_t offset)
   1705 {
   1706     *mPC++ = (sw_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1707 }
   1708 
   1709 // lb is sign-extended
   1710 void MIPSAssembler::LB(int Rt, int Rbase, int16_t offset)
   1711 {
   1712     *mPC++ = (lb_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1713 }
   1714 
   1715 void MIPSAssembler::LBU(int Rt, int Rbase, int16_t offset)
   1716 {
   1717     *mPC++ = (lbu_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1718 }
   1719 
   1720 void MIPSAssembler::SB(int Rt, int Rbase, int16_t offset)
   1721 {
   1722     *mPC++ = (sb_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1723 }
   1724 
   1725 // lh is sign-extended
   1726 void MIPSAssembler::LH(int Rt, int Rbase, int16_t offset)
   1727 {
   1728     *mPC++ = (lh_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1729 }
   1730 
   1731 void MIPSAssembler::LHU(int Rt, int Rbase, int16_t offset)
   1732 {
   1733     *mPC++ = (lhu_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1734 }
   1735 
   1736 void MIPSAssembler::SH(int Rt, int Rbase, int16_t offset)
   1737 {
   1738     *mPC++ = (sh_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1739 }
   1740 
   1741 void MIPSAssembler::LUI(int Rt, int16_t offset)
   1742 {
   1743     *mPC++ = (lui_op<<OP_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1744 }
   1745 
   1746 
   1747 
   1748 #if 0
   1749 #pragma mark -
   1750 #pragma mark Register move...
   1751 #endif
   1752 
   1753 void MIPSAssembler::MOVE(int Rd, int Rs)
   1754 {
   1755     // encoded as "or rd, rs, zero"
   1756     *mPC++ = (spec_op<<OP_SHF) | (or_fn<<FUNC_SHF) |
   1757                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (0<<RT_SHF);
   1758 }
   1759 
   1760 void MIPSAssembler::MOVN(int Rd, int Rs, int Rt)
   1761 {
   1762     *mPC++ = (spec_op<<OP_SHF) | (movn_fn<<FUNC_SHF) |
   1763                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF);
   1764 }
   1765 
   1766 void MIPSAssembler::MOVZ(int Rd, int Rs, int Rt)
   1767 {
   1768     *mPC++ = (spec_op<<OP_SHF) | (movz_fn<<FUNC_SHF) |
   1769                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF);
   1770 }
   1771 
   1772 void MIPSAssembler::MFHI(int Rd)
   1773 {
   1774     *mPC++ = (spec_op<<OP_SHF) | (mfhi_fn<<FUNC_SHF) | (Rd<<RD_SHF);
   1775 }
   1776 
   1777 void MIPSAssembler::MFLO(int Rd)
   1778 {
   1779     *mPC++ = (spec_op<<OP_SHF) | (mflo_fn<<FUNC_SHF) | (Rd<<RD_SHF);
   1780 }
   1781 
   1782 void MIPSAssembler::MTHI(int Rs)
   1783 {
   1784     *mPC++ = (spec_op<<OP_SHF) | (mthi_fn<<FUNC_SHF) | (Rs<<RS_SHF);
   1785 }
   1786 
   1787 void MIPSAssembler::MTLO(int Rs)
   1788 {
   1789     *mPC++ = (spec_op<<OP_SHF) | (mtlo_fn<<FUNC_SHF) | (Rs<<RS_SHF);
   1790 }
   1791 
   1792 
   1793 
   1794 #if 0
   1795 #pragma mark -
   1796 #pragma mark Branch...
   1797 #endif
   1798 
   1799 // temporarily forcing a NOP into branch-delay slot, just to be safe
   1800 // todo: remove NOP, optimze use of delay slots
   1801 void MIPSAssembler::B(const char* label)
   1802 {
   1803     mBranchTargets.add(branch_target_t(label, mPC));
   1804 
   1805     // encoded as BEQ zero, zero, offset
   1806     *mPC++ = (beq_op<<OP_SHF) | (0<<RT_SHF)
   1807                         | (0<<RS_SHF) | 0;  // offset filled in later
   1808 
   1809     MIPSAssembler::NOP();
   1810 }
   1811 
   1812 void MIPSAssembler::BEQ(int Rs, int Rt, const char* label)
   1813 {
   1814     mBranchTargets.add(branch_target_t(label, mPC));
   1815     *mPC++ = (beq_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | 0;
   1816     MIPSAssembler::NOP();
   1817 }
   1818 
   1819 void MIPSAssembler::BNE(int Rs, int Rt, const char* label)
   1820 {
   1821     mBranchTargets.add(branch_target_t(label, mPC));
   1822     *mPC++ = (bne_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | 0;
   1823     MIPSAssembler::NOP();
   1824 }
   1825 
   1826 void MIPSAssembler::BLEZ(int Rs, const char* label)
   1827 {
   1828     mBranchTargets.add(branch_target_t(label, mPC));
   1829     *mPC++ = (blez_op<<OP_SHF) | (0<<RT_SHF) | (Rs<<RS_SHF) | 0;
   1830     MIPSAssembler::NOP();
   1831 }
   1832 
   1833 void MIPSAssembler::BLTZ(int Rs, const char* label)
   1834 {
   1835     mBranchTargets.add(branch_target_t(label, mPC));
   1836     *mPC++ = (regimm_op<<OP_SHF) | (bltz_fn<<RT_SHF) | (Rs<<RS_SHF) | 0;
   1837     MIPSAssembler::NOP();
   1838 }
   1839 
   1840 void MIPSAssembler::BGTZ(int Rs, const char* label)
   1841 {
   1842     mBranchTargets.add(branch_target_t(label, mPC));
   1843     *mPC++ = (bgtz_op<<OP_SHF) | (0<<RT_SHF) | (Rs<<RS_SHF) | 0;
   1844     MIPSAssembler::NOP();
   1845 }
   1846 
   1847 
   1848 void MIPSAssembler::BGEZ(int Rs, const char* label)
   1849 {
   1850     mBranchTargets.add(branch_target_t(label, mPC));
   1851     *mPC++ = (regimm_op<<OP_SHF) | (bgez_fn<<RT_SHF) | (Rs<<RS_SHF) | 0;
   1852     MIPSAssembler::NOP();
   1853 }
   1854 
   1855 void MIPSAssembler::JR(int Rs)
   1856 {
   1857     *mPC++ = (spec_op<<OP_SHF) | (Rs<<RS_SHF) | (jr_fn << FUNC_SHF);
   1858     MIPSAssembler::NOP();
   1859 }
   1860 
   1861 
   1862 #if 0
   1863 #pragma mark -
   1864 #pragma mark Synthesized Branch...
   1865 #endif
   1866 
   1867 // synthetic variants of branches (using slt & friends)
   1868 void MIPSAssembler::BEQZ(int Rs, const char* label)
   1869 {
   1870     BEQ(Rs, R_zero, label);
   1871 }
   1872 
   1873 void MIPSAssembler::BNEZ(int Rs, const char* label)
   1874 {
   1875     BNE(R_at, R_zero, label);
   1876 }
   1877 
   1878 void MIPSAssembler::BGE(int Rs, int Rt, const char* label)
   1879 {
   1880     SLT(R_at, Rs, Rt);
   1881     BEQ(R_at, R_zero, label);
   1882 }
   1883 
   1884 void MIPSAssembler::BGEU(int Rs, int Rt, const char* label)
   1885 {
   1886     SLTU(R_at, Rs, Rt);
   1887     BEQ(R_at, R_zero, label);
   1888 }
   1889 
   1890 void MIPSAssembler::BGT(int Rs, int Rt, const char* label)
   1891 {
   1892     SLT(R_at, Rt, Rs);   // rev
   1893     BNE(R_at, R_zero, label);
   1894 }
   1895 
   1896 void MIPSAssembler::BGTU(int Rs, int Rt, const char* label)
   1897 {
   1898     SLTU(R_at, Rt, Rs);   // rev
   1899     BNE(R_at, R_zero, label);
   1900 }
   1901 
   1902 void MIPSAssembler::BLE(int Rs, int Rt, const char* label)
   1903 {
   1904     SLT(R_at, Rt, Rs);   // rev
   1905     BEQ(R_at, R_zero, label);
   1906 }
   1907 
   1908 void MIPSAssembler::BLEU(int Rs, int Rt, const char* label)
   1909 {
   1910     SLTU(R_at, Rt, Rs);  // rev
   1911     BEQ(R_at, R_zero, label);
   1912 }
   1913 
   1914 void MIPSAssembler::BLT(int Rs, int Rt, const char* label)
   1915 {
   1916     SLT(R_at, Rs, Rt);
   1917     BNE(R_at, R_zero, label);
   1918 }
   1919 
   1920 void MIPSAssembler::BLTU(int Rs, int Rt, const char* label)
   1921 {
   1922     SLTU(R_at, Rs, Rt);
   1923     BNE(R_at, R_zero, label);
   1924 }
   1925 
   1926 
   1927 
   1928 
   1929 #if 0
   1930 #pragma mark -
   1931 #pragma mark Misc...
   1932 #endif
   1933 
   1934 void MIPSAssembler::NOP(void)
   1935 {
   1936     // encoded as "sll zero, zero, 0", which is all zero
   1937     *mPC++ = (spec_op<<OP_SHF) | (sll_fn<<FUNC_SHF);
   1938 }
   1939 
   1940 // using this as special opcode for not-yet-implemented ARM instruction
   1941 void MIPSAssembler::NOP2(void)
   1942 {
   1943     // encoded as "sll zero, zero, 2", still a nop, but a unique code
   1944     *mPC++ = (spec_op<<OP_SHF) | (sll_fn<<FUNC_SHF) | (2 << RE_SHF);
   1945 }
   1946 
   1947 // using this as special opcode for purposefully NOT implemented ARM instruction
   1948 void MIPSAssembler::UNIMPL(void)
   1949 {
   1950     // encoded as "sll zero, zero, 3", still a nop, but a unique code
   1951     *mPC++ = (spec_op<<OP_SHF) | (sll_fn<<FUNC_SHF) | (3 << RE_SHF);
   1952 }
   1953 
   1954 
   1955 }; // namespace android:
   1956 
   1957 
   1958