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