Home | History | Annotate | Download | only in codeflinger
      1 /* libs/pixelflinger/codeflinger/MIPS64Assembler.cpp
      2 **
      3 ** Copyright 2015, 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 /* MIPS64 assembler and ARM->MIPS64 assembly translator
     20 **
     21 ** The approach is utilize MIPSAssembler generator, using inherited MIPS64Assembler
     22 ** that overrides just the specific MIPS64r6 instructions.
     23 ** For now ArmToMips64Assembler is copied over from ArmToMipsAssembler class,
     24 ** changing some MIPS64r6 related stuff.
     25 **
     26 */
     27 
     28 #define LOG_TAG "MIPS64Assembler"
     29 
     30 #include <stdio.h>
     31 #include <stdlib.h>
     32 
     33 #include <cutils/properties.h>
     34 #include <log/log.h>
     35 #include <private/pixelflinger/ggl_context.h>
     36 
     37 #include "MIPS64Assembler.h"
     38 #include "CodeCache.h"
     39 #include "mips64_disassem.h"
     40 
     41 #define NOT_IMPLEMENTED()  LOG_ALWAYS_FATAL("Arm instruction %s not yet implemented\n", __func__)
     42 
     43 // ----------------------------------------------------------------------------
     44 
     45 namespace android {
     46 
     47 // ----------------------------------------------------------------------------
     48 #if 0
     49 #pragma mark -
     50 #pragma mark ArmToMips64Assembler...
     51 #endif
     52 
     53 ArmToMips64Assembler::ArmToMips64Assembler(const sp<Assembly>& assembly,
     54                                            char *abuf, int linesz, int instr_count)
     55     :   ARMAssemblerInterface(),
     56         mArmDisassemblyBuffer(abuf),
     57         mArmLineLength(linesz),
     58         mArmInstrCount(instr_count),
     59         mInum(0),
     60         mAssembly(assembly)
     61 {
     62     mMips = new MIPS64Assembler(assembly, this);
     63     mArmPC = (uint32_t **) malloc(ARM_MAX_INSTUCTIONS * sizeof(uint32_t *));
     64     init_conditional_labels();
     65 }
     66 
     67 ArmToMips64Assembler::ArmToMips64Assembler(void* assembly)
     68     :   ARMAssemblerInterface(),
     69         mArmDisassemblyBuffer(NULL),
     70         mInum(0),
     71         mAssembly(NULL)
     72 {
     73     mMips = new MIPS64Assembler(assembly, this);
     74     mArmPC = (uint32_t **) malloc(ARM_MAX_INSTUCTIONS * sizeof(uint32_t *));
     75     init_conditional_labels();
     76 }
     77 
     78 ArmToMips64Assembler::~ArmToMips64Assembler()
     79 {
     80     delete mMips;
     81     free((void *) mArmPC);
     82 }
     83 
     84 uint32_t* ArmToMips64Assembler::pc() const
     85 {
     86     return mMips->pc();
     87 }
     88 
     89 uint32_t* ArmToMips64Assembler::base() const
     90 {
     91     return mMips->base();
     92 }
     93 
     94 void ArmToMips64Assembler::reset()
     95 {
     96     cond.labelnum = 0;
     97     mInum = 0;
     98     mMips->reset();
     99 }
    100 
    101 int ArmToMips64Assembler::getCodegenArch()
    102 {
    103     return CODEGEN_ARCH_MIPS64;
    104 }
    105 
    106 void ArmToMips64Assembler::comment(const char* string)
    107 {
    108     mMips->comment(string);
    109 }
    110 
    111 void ArmToMips64Assembler::label(const char* theLabel)
    112 {
    113     mMips->label(theLabel);
    114 }
    115 
    116 void ArmToMips64Assembler::disassemble(const char* name)
    117 {
    118     mMips->disassemble(name);
    119 }
    120 
    121 void ArmToMips64Assembler::init_conditional_labels()
    122 {
    123     int i;
    124     for (i=0;i<99; ++i) {
    125         sprintf(cond.label[i], "cond_%d", i);
    126     }
    127 }
    128 
    129 
    130 
    131 #if 0
    132 #pragma mark -
    133 #pragma mark Prolog/Epilog & Generate...
    134 #endif
    135 
    136 void ArmToMips64Assembler::prolog()
    137 {
    138     mArmPC[mInum++] = pc();  // save starting PC for this instr
    139 
    140     mMips->DADDIU(R_sp, R_sp, -(5 * 8));
    141     mMips->SD(R_s0, R_sp, 0);
    142     mMips->SD(R_s1, R_sp, 8);
    143     mMips->SD(R_s2, R_sp, 16);
    144     mMips->SD(R_s3, R_sp, 24);
    145     mMips->SD(R_s4, R_sp, 32);
    146     mMips->MOVE(R_v0, R_a0);    // move context * passed in a0 to v0 (arm r0)
    147 }
    148 
    149 void ArmToMips64Assembler::epilog(uint32_t touched)
    150 {
    151     mArmPC[mInum++] = pc();  // save starting PC for this instr
    152 
    153     mMips->LD(R_s0, R_sp, 0);
    154     mMips->LD(R_s1, R_sp, 8);
    155     mMips->LD(R_s2, R_sp, 16);
    156     mMips->LD(R_s3, R_sp, 24);
    157     mMips->LD(R_s4, R_sp, 32);
    158     mMips->DADDIU(R_sp, R_sp, (5 * 8));
    159     mMips->JR(R_ra);
    160 
    161 }
    162 
    163 int ArmToMips64Assembler::generate(const char* name)
    164 {
    165     return mMips->generate(name);
    166 }
    167 
    168 void ArmToMips64Assembler::fix_branches()
    169 {
    170     mMips->fix_branches();
    171 }
    172 
    173 uint32_t* ArmToMips64Assembler::pcForLabel(const char* label)
    174 {
    175     return mMips->pcForLabel(label);
    176 }
    177 
    178 void ArmToMips64Assembler::set_condition(int mode, int R1, int R2) {
    179     if (mode == 2) {
    180         cond.type = SBIT_COND;
    181     } else {
    182         cond.type = CMP_COND;
    183     }
    184     cond.r1 = R1;
    185     cond.r2 = R2;
    186 }
    187 
    188 //----------------------------------------------------------
    189 
    190 #if 0
    191 #pragma mark -
    192 #pragma mark Addressing modes & shifters...
    193 #endif
    194 
    195 
    196 // do not need this for MIPS, but it is in the Interface (virtual)
    197 int ArmToMips64Assembler::buildImmediate(
    198         uint32_t immediate, uint32_t& rot, uint32_t& imm)
    199 {
    200     // for MIPS, any 32-bit immediate is OK
    201     rot = 0;
    202     imm = immediate;
    203     return 0;
    204 }
    205 
    206 // shifters...
    207 
    208 bool ArmToMips64Assembler::isValidImmediate(uint32_t immediate)
    209 {
    210     // for MIPS, any 32-bit immediate is OK
    211     return true;
    212 }
    213 
    214 uint32_t ArmToMips64Assembler::imm(uint32_t immediate)
    215 {
    216     amode.value = immediate;
    217     return AMODE_IMM;
    218 }
    219 
    220 uint32_t ArmToMips64Assembler::reg_imm(int Rm, int type, uint32_t shift)
    221 {
    222     amode.reg = Rm;
    223     amode.stype = type;
    224     amode.value = shift;
    225     return AMODE_REG_IMM;
    226 }
    227 
    228 uint32_t ArmToMips64Assembler::reg_rrx(int Rm)
    229 {
    230     // reg_rrx mode is not used in the GLLAssember code at this time
    231     return AMODE_UNSUPPORTED;
    232 }
    233 
    234 uint32_t ArmToMips64Assembler::reg_reg(int Rm, int type, int Rs)
    235 {
    236     // reg_reg mode is not used in the GLLAssember code at this time
    237     return AMODE_UNSUPPORTED;
    238 }
    239 
    240 
    241 // addressing modes...
    242 // LDR(B)/STR(B)/PLD (immediate and Rm can be negative, which indicate U=0)
    243 uint32_t ArmToMips64Assembler::immed12_pre(int32_t immed12, int W)
    244 {
    245     LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
    246                         "LDR(B)/STR(B)/PLD immediate too big (%08x)",
    247                         immed12);
    248     amode.value = immed12;
    249     amode.writeback = W;
    250     return AMODE_IMM_12_PRE;
    251 }
    252 
    253 uint32_t ArmToMips64Assembler::immed12_post(int32_t immed12)
    254 {
    255     LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
    256                         "LDR(B)/STR(B)/PLD immediate too big (%08x)",
    257                         immed12);
    258 
    259     amode.value = immed12;
    260     return AMODE_IMM_12_POST;
    261 }
    262 
    263 uint32_t ArmToMips64Assembler::reg_scale_pre(int Rm, int type,
    264         uint32_t shift, int W)
    265 {
    266     LOG_ALWAYS_FATAL_IF(W | type | shift, "reg_scale_pre adv modes not yet implemented");
    267 
    268     amode.reg = Rm;
    269     // amode.stype = type;      // more advanced modes not used in GGLAssembler yet
    270     // amode.value = shift;
    271     // amode.writeback = W;
    272     return AMODE_REG_SCALE_PRE;
    273 }
    274 
    275 uint32_t ArmToMips64Assembler::reg_scale_post(int Rm, int type, uint32_t shift)
    276 {
    277     LOG_ALWAYS_FATAL("adr mode reg_scale_post not yet implemented\n");
    278     return AMODE_UNSUPPORTED;
    279 }
    280 
    281 // LDRH/LDRSB/LDRSH/STRH (immediate and Rm can be negative, which indicate U=0)
    282 uint32_t ArmToMips64Assembler::immed8_pre(int32_t immed8, int W)
    283 {
    284     LOG_ALWAYS_FATAL("adr mode immed8_pre not yet implemented\n");
    285 
    286     LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
    287                         "LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
    288                         immed8);
    289     return AMODE_IMM_8_PRE;
    290 }
    291 
    292 uint32_t ArmToMips64Assembler::immed8_post(int32_t immed8)
    293 {
    294     LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
    295                         "LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
    296                         immed8);
    297     amode.value = immed8;
    298     return AMODE_IMM_8_POST;
    299 }
    300 
    301 uint32_t ArmToMips64Assembler::reg_pre(int Rm, int W)
    302 {
    303     LOG_ALWAYS_FATAL_IF(W, "reg_pre writeback not yet implemented");
    304     amode.reg = Rm;
    305     return AMODE_REG_PRE;
    306 }
    307 
    308 uint32_t ArmToMips64Assembler::reg_post(int Rm)
    309 {
    310     LOG_ALWAYS_FATAL("adr mode reg_post not yet implemented\n");
    311     return AMODE_UNSUPPORTED;
    312 }
    313 
    314 
    315 
    316 // ----------------------------------------------------------------------------
    317 
    318 #if 0
    319 #pragma mark -
    320 #pragma mark Data Processing...
    321 #endif
    322 
    323 
    324 static const char * const dpOpNames[] = {
    325     "AND", "EOR", "SUB", "RSB", "ADD", "ADC", "SBC", "RSC",
    326     "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN"
    327 };
    328 
    329 // check if the operand registers from a previous CMP or S-bit instruction
    330 // would be overwritten by this instruction. If so, move the value to a
    331 // safe register.
    332 // Note that we cannot tell at _this_ instruction time if a future (conditional)
    333 // instruction will _also_ use this value (a defect of the simple 1-pass, one-
    334 // instruction-at-a-time translation). Therefore we must be conservative and
    335 // save the value before it is overwritten. This costs an extra MOVE instr.
    336 
    337 void ArmToMips64Assembler::protectConditionalOperands(int Rd)
    338 {
    339     if (Rd == cond.r1) {
    340         mMips->MOVE(R_cmp, cond.r1);
    341         cond.r1 = R_cmp;
    342     }
    343     if (cond.type == CMP_COND && Rd == cond.r2) {
    344         mMips->MOVE(R_cmp2, cond.r2);
    345         cond.r2 = R_cmp2;
    346     }
    347 }
    348 
    349 
    350 // interprets the addressing mode, and generates the common code
    351 // used by the majority of data-processing ops. Many MIPS instructions
    352 // have a register-based form and a different immediate form. See
    353 // opAND below for an example. (this could be inlined)
    354 //
    355 // this works with the imm(), reg_imm() methods above, which are directly
    356 // called by the GLLAssembler.
    357 // note: _signed parameter defaults to false (un-signed)
    358 // note: tmpReg parameter defaults to 1, MIPS register AT
    359 int ArmToMips64Assembler::dataProcAdrModes(int op, int& source, bool _signed, int tmpReg)
    360 {
    361     if (op < AMODE_REG) {
    362         source = op;
    363         return SRC_REG;
    364     } else if (op == AMODE_IMM) {
    365         if ((!_signed && amode.value > 0xffff)
    366                 || (_signed && ((int)amode.value < -32768 || (int)amode.value > 32767) )) {
    367             mMips->LUI(tmpReg, (amode.value >> 16));
    368             if (amode.value & 0x0000ffff) {
    369                 mMips->ORI(tmpReg, tmpReg, (amode.value & 0x0000ffff));
    370             }
    371             source = tmpReg;
    372             return SRC_REG;
    373         } else {
    374             source = amode.value;
    375             return SRC_IMM;
    376         }
    377     } else if (op == AMODE_REG_IMM) {
    378         switch (amode.stype) {
    379             case LSL: mMips->SLL(tmpReg, amode.reg, amode.value); break;
    380             case LSR: mMips->SRL(tmpReg, amode.reg, amode.value); break;
    381             case ASR: mMips->SRA(tmpReg, amode.reg, amode.value); break;
    382             case ROR: mMips->ROTR(tmpReg, amode.reg, amode.value); break;
    383         }
    384         source = tmpReg;
    385         return SRC_REG;
    386     } else {  // adr mode RRX is not used in GGL Assembler at this time
    387         // we are screwed, this should be exception, assert-fail or something
    388         LOG_ALWAYS_FATAL("adr mode reg_rrx not yet implemented\n");
    389         return SRC_ERROR;
    390     }
    391 }
    392 
    393 
    394 void ArmToMips64Assembler::dataProcessing(int opcode, int cc,
    395         int s, int Rd, int Rn, uint32_t Op2)
    396 {
    397     int src;    // src is modified by dataProcAdrModes() - passed as int&
    398 
    399     if (cc != AL) {
    400         protectConditionalOperands(Rd);
    401         // the branch tests register(s) set by prev CMP or instr with 'S' bit set
    402         // inverse the condition to jump past this conditional instruction
    403         ArmToMips64Assembler::B(cc^1, cond.label[++cond.labelnum]);
    404     } else {
    405         mArmPC[mInum++] = pc();  // save starting PC for this instr
    406     }
    407 
    408     switch (opcode) {
    409     case opAND:
    410         if (dataProcAdrModes(Op2, src) == SRC_REG) {
    411             mMips->AND(Rd, Rn, src);
    412         } else {                        // adr mode was SRC_IMM
    413             mMips->ANDI(Rd, Rn, src);
    414         }
    415         break;
    416 
    417     case opADD:
    418         // set "signed" to true for adr modes
    419         if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
    420             mMips->ADDU(Rd, Rn, src);
    421         } else {                        // adr mode was SRC_IMM
    422             mMips->ADDIU(Rd, Rn, src);
    423         }
    424         break;
    425 
    426     case opSUB:
    427         // set "signed" to true for adr modes
    428         if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
    429             mMips->SUBU(Rd, Rn, src);
    430         } else {                        // adr mode was SRC_IMM
    431             mMips->SUBIU(Rd, Rn, src);
    432         }
    433         break;
    434 
    435     case opADD64:
    436         // set "signed" to true for adr modes
    437         if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
    438             mMips->DADDU(Rd, Rn, src);
    439         } else {                        // adr mode was SRC_IMM
    440             mMips->DADDIU(Rd, Rn, src);
    441         }
    442         break;
    443 
    444     case opSUB64:
    445         // set "signed" to true for adr modes
    446         if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
    447             mMips->DSUBU(Rd, Rn, src);
    448         } else {                        // adr mode was SRC_IMM
    449             mMips->DSUBIU(Rd, Rn, src);
    450         }
    451         break;
    452 
    453     case opEOR:
    454         if (dataProcAdrModes(Op2, src) == SRC_REG) {
    455             mMips->XOR(Rd, Rn, src);
    456         } else {                        // adr mode was SRC_IMM
    457             mMips->XORI(Rd, Rn, src);
    458         }
    459         break;
    460 
    461     case opORR:
    462         if (dataProcAdrModes(Op2, src) == SRC_REG) {
    463             mMips->OR(Rd, Rn, src);
    464         } else {                        // adr mode was SRC_IMM
    465             mMips->ORI(Rd, Rn, src);
    466         }
    467         break;
    468 
    469     case opBIC:
    470         if (dataProcAdrModes(Op2, src) == SRC_IMM) {
    471             // if we are 16-bit imnmediate, load to AT reg
    472             mMips->ORI(R_at, 0, src);
    473             src = R_at;
    474         }
    475         mMips->NOT(R_at, src);
    476         mMips->AND(Rd, Rn, R_at);
    477         break;
    478 
    479     case opRSB:
    480         if (dataProcAdrModes(Op2, src) == SRC_IMM) {
    481             // if we are 16-bit imnmediate, load to AT reg
    482             mMips->ORI(R_at, 0, src);
    483             src = R_at;
    484         }
    485         mMips->SUBU(Rd, src, Rn);   // subu with the parameters reversed
    486         break;
    487 
    488     case opMOV:
    489         if (Op2 < AMODE_REG) {  // op2 is reg # in this case
    490             mMips->MOVE(Rd, Op2);
    491         } else if (Op2 == AMODE_IMM) {
    492             if (amode.value > 0xffff) {
    493                 mMips->LUI(Rd, (amode.value >> 16));
    494                 if (amode.value & 0x0000ffff) {
    495                     mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff));
    496                 }
    497              } else {
    498                 mMips->ORI(Rd, 0, amode.value);
    499             }
    500         } else if (Op2 == AMODE_REG_IMM) {
    501             switch (amode.stype) {
    502             case LSL: mMips->SLL(Rd, amode.reg, amode.value); break;
    503             case LSR: mMips->SRL(Rd, amode.reg, amode.value); break;
    504             case ASR: mMips->SRA(Rd, amode.reg, amode.value); break;
    505             case ROR: mMips->ROTR(Rd, amode.reg, amode.value); break;
    506             }
    507         }
    508         else {
    509             // adr mode RRX is not used in GGL Assembler at this time
    510             mMips->UNIMPL();
    511         }
    512         break;
    513 
    514     case opMVN:     // this is a 1's complement: NOT
    515         if (Op2 < AMODE_REG) {  // op2 is reg # in this case
    516             mMips->NOR(Rd, Op2, 0);     // NOT is NOR with 0
    517             break;
    518         } else if (Op2 == AMODE_IMM) {
    519             if (amode.value > 0xffff) {
    520                 mMips->LUI(Rd, (amode.value >> 16));
    521                 if (amode.value & 0x0000ffff) {
    522                     mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff));
    523                 }
    524              } else {
    525                 mMips->ORI(Rd, 0, amode.value);
    526              }
    527         } else if (Op2 == AMODE_REG_IMM) {
    528             switch (amode.stype) {
    529             case LSL: mMips->SLL(Rd, amode.reg, amode.value); break;
    530             case LSR: mMips->SRL(Rd, amode.reg, amode.value); break;
    531             case ASR: mMips->SRA(Rd, amode.reg, amode.value); break;
    532             case ROR: mMips->ROTR(Rd, amode.reg, amode.value); break;
    533             }
    534         }
    535         else {
    536             // adr mode RRX is not used in GGL Assembler at this time
    537             mMips->UNIMPL();
    538         }
    539         mMips->NOR(Rd, Rd, 0);     // NOT is NOR with 0
    540         break;
    541 
    542     case opCMP:
    543         // Either operand of a CMP instr could get overwritten by a subsequent
    544         // conditional instruction, which is ok, _UNLESS_ there is a _second_
    545         // conditional instruction. Under MIPS, this requires doing the comparison
    546         // again (SLT), and the original operands must be available. (and this
    547         // pattern of multiple conditional instructions from same CMP _is_ used
    548         // in GGL-Assembler)
    549         //
    550         // For now, if a conditional instr overwrites the operands, we will
    551         // move them to dedicated temp regs. This is ugly, and inefficient,
    552         // and should be optimized.
    553         //
    554         // WARNING: making an _Assumption_ that CMP operand regs will NOT be
    555         // trashed by intervening NON-conditional instructions. In the general
    556         // case this is legal, but it is NOT currently done in GGL-Assembler.
    557 
    558         cond.type = CMP_COND;
    559         cond.r1 = Rn;
    560         if (dataProcAdrModes(Op2, src, false, R_cmp2) == SRC_REG) {
    561             cond.r2 = src;
    562         } else {                        // adr mode was SRC_IMM
    563             mMips->ORI(R_cmp2, R_zero, src);
    564             cond.r2 = R_cmp2;
    565         }
    566 
    567         break;
    568 
    569 
    570     case opTST:
    571     case opTEQ:
    572     case opCMN:
    573     case opADC:
    574     case opSBC:
    575     case opRSC:
    576         mMips->UNIMPL(); // currently unused in GGL Assembler code
    577         break;
    578     }
    579 
    580     if (cc != AL) {
    581         mMips->label(cond.label[cond.labelnum]);
    582     }
    583     if (s && opcode != opCMP) {
    584         cond.type = SBIT_COND;
    585         cond.r1 = Rd;
    586     }
    587 }
    588 
    589 
    590 
    591 #if 0
    592 #pragma mark -
    593 #pragma mark Multiply...
    594 #endif
    595 
    596 // multiply, accumulate
    597 void ArmToMips64Assembler::MLA(int cc, int s,
    598         int Rd, int Rm, int Rs, int Rn) {
    599 
    600     //ALOGW("MLA");
    601     mArmPC[mInum++] = pc();  // save starting PC for this instr
    602 
    603     mMips->MUL(R_at, Rm, Rs);
    604     mMips->ADDU(Rd, R_at, Rn);
    605     if (s) {
    606         cond.type = SBIT_COND;
    607         cond.r1 = Rd;
    608     }
    609 }
    610 
    611 void ArmToMips64Assembler::MUL(int cc, int s,
    612         int Rd, int Rm, int Rs) {
    613     mArmPC[mInum++] = pc();
    614     mMips->MUL(Rd, Rm, Rs);
    615     if (s) {
    616         cond.type = SBIT_COND;
    617         cond.r1 = Rd;
    618     }
    619 }
    620 
    621 void ArmToMips64Assembler::UMULL(int cc, int s,
    622         int RdLo, int RdHi, int Rm, int Rs) {
    623     mArmPC[mInum++] = pc();
    624     mMips->MUH(RdHi, Rm, Rs);
    625     mMips->MUL(RdLo, Rm, Rs);
    626 
    627     if (s) {
    628         cond.type = SBIT_COND;
    629         cond.r1 = RdHi;     // BUG...
    630         LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n");
    631     }
    632 }
    633 
    634 void ArmToMips64Assembler::UMUAL(int cc, int s,
    635         int RdLo, int RdHi, int Rm, int Rs) {
    636     LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
    637                         "UMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
    638     // *mPC++ =    (cc<<28) | (1<<23) | (1<<21) | (s<<20) |
    639     //             (RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
    640     mArmPC[mInum++] = pc();
    641     mMips->NOP2();
    642     NOT_IMPLEMENTED();
    643     if (s) {
    644         cond.type = SBIT_COND;
    645         cond.r1 = RdHi;     // BUG...
    646         LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n");
    647     }
    648 }
    649 
    650 void ArmToMips64Assembler::SMULL(int cc, int s,
    651         int RdLo, int RdHi, int Rm, int Rs) {
    652     LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
    653                         "SMULL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
    654     // *mPC++ =    (cc<<28) | (1<<23) | (1<<22) | (s<<20) |
    655     //             (RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
    656     mArmPC[mInum++] = pc();
    657     mMips->NOP2();
    658     NOT_IMPLEMENTED();
    659     if (s) {
    660         cond.type = SBIT_COND;
    661         cond.r1 = RdHi;     // BUG...
    662         LOG_ALWAYS_FATAL("Condition on SMULL must be on 64-bit result\n");
    663     }
    664 }
    665 void ArmToMips64Assembler::SMUAL(int cc, int s,
    666         int RdLo, int RdHi, int Rm, int Rs) {
    667     LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
    668                         "SMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
    669     // *mPC++ =    (cc<<28) | (1<<23) | (1<<22) | (1<<21) | (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 SMUAL must be on 64-bit result\n");
    678     }
    679 }
    680 
    681 
    682 
    683 #if 0
    684 #pragma mark -
    685 #pragma mark Branches...
    686 #endif
    687 
    688 // branches...
    689 
    690 void ArmToMips64Assembler::B(int cc, const char* label)
    691 {
    692     mArmPC[mInum++] = pc();
    693     if (cond.type == SBIT_COND) { cond.r2 = R_zero; }
    694 
    695     switch(cc) {
    696         case EQ: mMips->BEQ(cond.r1, cond.r2, label); break;
    697         case NE: mMips->BNE(cond.r1, cond.r2, label); break;
    698         case HS: mMips->BGEU(cond.r1, cond.r2, label); break;
    699         case LO: mMips->BLTU(cond.r1, cond.r2, label); break;
    700         case MI: mMips->BLT(cond.r1, cond.r2, label); break;
    701         case PL: mMips->BGE(cond.r1, cond.r2, label); break;
    702 
    703         case HI: mMips->BGTU(cond.r1, cond.r2, label); break;
    704         case LS: mMips->BLEU(cond.r1, cond.r2, label); break;
    705         case GE: mMips->BGE(cond.r1, cond.r2, label); break;
    706         case LT: mMips->BLT(cond.r1, cond.r2, label); break;
    707         case GT: mMips->BGT(cond.r1, cond.r2, label); break;
    708         case LE: mMips->BLE(cond.r1, cond.r2, label); break;
    709         case AL: mMips->B(label); break;
    710         case NV: /* B Never - no instruction */ break;
    711 
    712         case VS:
    713         case VC:
    714         default:
    715             LOG_ALWAYS_FATAL("Unsupported cc: %02x\n", cc);
    716             break;
    717     }
    718 }
    719 
    720 void ArmToMips64Assembler::BL(int cc, const char* label)
    721 {
    722     LOG_ALWAYS_FATAL("branch-and-link not supported yet\n");
    723     mArmPC[mInum++] = pc();
    724 }
    725 
    726 // no use for Branches with integer PC, but they're in the Interface class ....
    727 void ArmToMips64Assembler::B(int cc, uint32_t* to_pc)
    728 {
    729     LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
    730     mArmPC[mInum++] = pc();
    731 }
    732 
    733 void ArmToMips64Assembler::BL(int cc, uint32_t* to_pc)
    734 {
    735     LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
    736     mArmPC[mInum++] = pc();
    737 }
    738 
    739 void ArmToMips64Assembler::BX(int cc, int Rn)
    740 {
    741     LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
    742     mArmPC[mInum++] = pc();
    743 }
    744 
    745 
    746 
    747 #if 0
    748 #pragma mark -
    749 #pragma mark Data Transfer...
    750 #endif
    751 
    752 // data transfer...
    753 void ArmToMips64Assembler::LDR(int cc, int Rd, int Rn, uint32_t offset)
    754 {
    755     mArmPC[mInum++] = pc();
    756     // work-around for ARM default address mode of immed12_pre(0)
    757     if (offset > AMODE_UNSUPPORTED) offset = 0;
    758     switch (offset) {
    759         case 0:
    760             amode.value = 0;
    761             amode.writeback = 0;
    762             // fall thru to next case ....
    763         case AMODE_IMM_12_PRE:
    764             if (Rn == ARMAssemblerInterface::SP) {
    765                 Rn = R_sp;      // convert LDR via Arm SP to LW via Mips SP
    766             }
    767             mMips->LW(Rd, Rn, amode.value);
    768             if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
    769                 mMips->DADDIU(Rn, Rn, amode.value);
    770             }
    771             break;
    772         case AMODE_IMM_12_POST:
    773             if (Rn == ARMAssemblerInterface::SP) {
    774                 Rn = R_sp;      // convert STR thru Arm SP to STR thru Mips SP
    775             }
    776             mMips->LW(Rd, Rn, 0);
    777             mMips->DADDIU(Rn, Rn, amode.value);
    778             break;
    779         case AMODE_REG_SCALE_PRE:
    780             // we only support simple base + index, no advanced modes for this one yet
    781             mMips->DADDU(R_at, Rn, amode.reg);
    782             mMips->LW(Rd, R_at, 0);
    783             break;
    784     }
    785 }
    786 
    787 void ArmToMips64Assembler::LDRB(int cc, int Rd, int Rn, uint32_t offset)
    788 {
    789     mArmPC[mInum++] = pc();
    790     // work-around for ARM default address mode of immed12_pre(0)
    791     if (offset > AMODE_UNSUPPORTED) offset = 0;
    792     switch (offset) {
    793         case 0:
    794             amode.value = 0;
    795             amode.writeback = 0;
    796             // fall thru to next case ....
    797         case AMODE_IMM_12_PRE:
    798             mMips->LBU(Rd, Rn, amode.value);
    799             if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
    800                 mMips->DADDIU(Rn, Rn, amode.value);
    801             }
    802             break;
    803         case AMODE_IMM_12_POST:
    804             mMips->LBU(Rd, Rn, 0);
    805             mMips->DADDIU(Rn, Rn, amode.value);
    806             break;
    807         case AMODE_REG_SCALE_PRE:
    808             // we only support simple base + index, no advanced modes for this one yet
    809             mMips->DADDU(R_at, Rn, amode.reg);
    810             mMips->LBU(Rd, R_at, 0);
    811             break;
    812     }
    813 
    814 }
    815 
    816 void ArmToMips64Assembler::STR(int cc, int Rd, int Rn, uint32_t offset)
    817 {
    818     mArmPC[mInum++] = pc();
    819     // work-around for ARM default address mode of immed12_pre(0)
    820     if (offset > AMODE_UNSUPPORTED) offset = 0;
    821     switch (offset) {
    822         case 0:
    823             amode.value = 0;
    824             amode.writeback = 0;
    825             // fall thru to next case ....
    826         case AMODE_IMM_12_PRE:
    827             if (Rn == ARMAssemblerInterface::SP) {
    828                 Rn = R_sp;  // convert STR thru Arm SP to SW thru Mips SP
    829             }
    830             if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
    831                 // If we will writeback, then update the index reg, then store.
    832                 // This correctly handles stack-push case.
    833                 mMips->DADDIU(Rn, Rn, amode.value);
    834                 mMips->SW(Rd, Rn, 0);
    835             } else {
    836                 // No writeback so store offset by value
    837                 mMips->SW(Rd, Rn, amode.value);
    838             }
    839             break;
    840         case AMODE_IMM_12_POST:
    841             mMips->SW(Rd, Rn, 0);
    842             mMips->DADDIU(Rn, Rn, amode.value);  // post index always writes back
    843             break;
    844         case AMODE_REG_SCALE_PRE:
    845             // we only support simple base + index, no advanced modes for this one yet
    846             mMips->DADDU(R_at, Rn, amode.reg);
    847             mMips->SW(Rd, R_at, 0);
    848             break;
    849     }
    850 }
    851 
    852 void ArmToMips64Assembler::STRB(int cc, int Rd, int Rn, uint32_t offset)
    853 {
    854     mArmPC[mInum++] = pc();
    855     // work-around for ARM default address mode of immed12_pre(0)
    856     if (offset > AMODE_UNSUPPORTED) offset = 0;
    857     switch (offset) {
    858         case 0:
    859             amode.value = 0;
    860             amode.writeback = 0;
    861             // fall thru to next case ....
    862         case AMODE_IMM_12_PRE:
    863             mMips->SB(Rd, Rn, amode.value);
    864             if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
    865                 mMips->DADDIU(Rn, Rn, amode.value);
    866             }
    867             break;
    868         case AMODE_IMM_12_POST:
    869             mMips->SB(Rd, Rn, 0);
    870             mMips->DADDIU(Rn, Rn, amode.value);
    871             break;
    872         case AMODE_REG_SCALE_PRE:
    873             // we only support simple base + index, no advanced modes for this one yet
    874             mMips->DADDU(R_at, Rn, amode.reg);
    875             mMips->SB(Rd, R_at, 0);
    876             break;
    877     }
    878 }
    879 
    880 void ArmToMips64Assembler::LDRH(int cc, int Rd, int Rn, uint32_t offset)
    881 {
    882     mArmPC[mInum++] = pc();
    883     // work-around for ARM default address mode of immed8_pre(0)
    884     if (offset > AMODE_UNSUPPORTED) offset = 0;
    885     switch (offset) {
    886         case 0:
    887             amode.value = 0;
    888             // fall thru to next case ....
    889         case AMODE_IMM_8_PRE:      // no support yet for writeback
    890             mMips->LHU(Rd, Rn, amode.value);
    891             break;
    892         case AMODE_IMM_8_POST:
    893             mMips->LHU(Rd, Rn, 0);
    894             mMips->DADDIU(Rn, Rn, amode.value);
    895             break;
    896         case AMODE_REG_PRE:
    897             // we only support simple base +/- index
    898             if (amode.reg >= 0) {
    899                 mMips->DADDU(R_at, Rn, amode.reg);
    900             } else {
    901                 mMips->DSUBU(R_at, Rn, abs(amode.reg));
    902             }
    903             mMips->LHU(Rd, R_at, 0);
    904             break;
    905     }
    906 }
    907 
    908 void ArmToMips64Assembler::LDRSB(int cc, int Rd, int Rn, uint32_t offset)
    909 {
    910     mArmPC[mInum++] = pc();
    911     mMips->NOP2();
    912     NOT_IMPLEMENTED();
    913 }
    914 
    915 void ArmToMips64Assembler::LDRSH(int cc, int Rd, int Rn, uint32_t offset)
    916 {
    917     mArmPC[mInum++] = pc();
    918     mMips->NOP2();
    919     NOT_IMPLEMENTED();
    920 }
    921 
    922 void ArmToMips64Assembler::STRH(int cc, int Rd, int Rn, uint32_t offset)
    923 {
    924     mArmPC[mInum++] = pc();
    925     // work-around for ARM default address mode of immed8_pre(0)
    926     if (offset > AMODE_UNSUPPORTED) offset = 0;
    927     switch (offset) {
    928         case 0:
    929             amode.value = 0;
    930             // fall thru to next case ....
    931         case AMODE_IMM_8_PRE:      // no support yet for writeback
    932             mMips->SH(Rd, Rn, amode.value);
    933             break;
    934         case AMODE_IMM_8_POST:
    935             mMips->SH(Rd, Rn, 0);
    936             mMips->DADDIU(Rn, Rn, amode.value);
    937             break;
    938         case AMODE_REG_PRE:
    939             // we only support simple base +/- index
    940             if (amode.reg >= 0) {
    941                 mMips->DADDU(R_at, Rn, amode.reg);
    942             } else {
    943                 mMips->DSUBU(R_at, Rn, abs(amode.reg));
    944             }
    945             mMips->SH(Rd, R_at, 0);
    946             break;
    947     }
    948 }
    949 
    950 
    951 
    952 #if 0
    953 #pragma mark -
    954 #pragma mark Block Data Transfer...
    955 #endif
    956 
    957 // block data transfer...
    958 void ArmToMips64Assembler::LDM(int cc, int dir,
    959         int Rn, int W, uint32_t reg_list)
    960 {   //                        ED FD EA FA      IB IA DB DA
    961     // const uint8_t P[8] = { 1, 0, 1, 0,      1, 0, 1, 0 };
    962     // const uint8_t U[8] = { 1, 1, 0, 0,      1, 1, 0, 0 };
    963     // *mPC++ = (cc<<28) | (4<<25) | (uint32_t(P[dir])<<24) |
    964     //         (uint32_t(U[dir])<<23) | (1<<20) | (W<<21) | (Rn<<16) | reg_list;
    965     mArmPC[mInum++] = pc();
    966     mMips->NOP2();
    967     NOT_IMPLEMENTED();
    968 }
    969 
    970 void ArmToMips64Assembler::STM(int cc, int dir,
    971         int Rn, int W, uint32_t reg_list)
    972 {   //                        FA EA FD ED      IB IA DB DA
    973     // const uint8_t P[8] = { 0, 1, 0, 1,      1, 0, 1, 0 };
    974     // const uint8_t U[8] = { 0, 0, 1, 1,      1, 1, 0, 0 };
    975     // *mPC++ = (cc<<28) | (4<<25) | (uint32_t(P[dir])<<24) |
    976     //         (uint32_t(U[dir])<<23) | (0<<20) | (W<<21) | (Rn<<16) | reg_list;
    977     mArmPC[mInum++] = pc();
    978     mMips->NOP2();
    979     NOT_IMPLEMENTED();
    980 }
    981 
    982 
    983 
    984 #if 0
    985 #pragma mark -
    986 #pragma mark Special...
    987 #endif
    988 
    989 // special...
    990 void ArmToMips64Assembler::SWP(int cc, int Rn, int Rd, int Rm) {
    991     // *mPC++ = (cc<<28) | (2<<23) | (Rn<<16) | (Rd << 12) | 0x90 | Rm;
    992     mArmPC[mInum++] = pc();
    993     mMips->NOP2();
    994     NOT_IMPLEMENTED();
    995 }
    996 
    997 void ArmToMips64Assembler::SWPB(int cc, int Rn, int Rd, int Rm) {
    998     // *mPC++ = (cc<<28) | (2<<23) | (1<<22) | (Rn<<16) | (Rd << 12) | 0x90 | Rm;
    999     mArmPC[mInum++] = pc();
   1000     mMips->NOP2();
   1001     NOT_IMPLEMENTED();
   1002 }
   1003 
   1004 void ArmToMips64Assembler::SWI(int cc, uint32_t comment) {
   1005     // *mPC++ = (cc<<28) | (0xF<<24) | comment;
   1006     mArmPC[mInum++] = pc();
   1007     mMips->NOP2();
   1008     NOT_IMPLEMENTED();
   1009 }
   1010 
   1011 
   1012 #if 0
   1013 #pragma mark -
   1014 #pragma mark DSP instructions...
   1015 #endif
   1016 
   1017 // DSP instructions...
   1018 void ArmToMips64Assembler::PLD(int Rn, uint32_t offset) {
   1019     LOG_ALWAYS_FATAL_IF(!((offset&(1<<24)) && !(offset&(1<<21))),
   1020                         "PLD only P=1, W=0");
   1021     // *mPC++ = 0xF550F000 | (Rn<<16) | offset;
   1022     mArmPC[mInum++] = pc();
   1023     mMips->NOP2();
   1024     NOT_IMPLEMENTED();
   1025 }
   1026 
   1027 void ArmToMips64Assembler::CLZ(int cc, int Rd, int Rm)
   1028 {
   1029     mArmPC[mInum++] = pc();
   1030     mMips->CLZ(Rd, Rm);
   1031 }
   1032 
   1033 void ArmToMips64Assembler::QADD(int cc,  int Rd, int Rm, int Rn)
   1034 {
   1035     // *mPC++ = (cc<<28) | 0x1000050 | (Rn<<16) | (Rd<<12) | Rm;
   1036     mArmPC[mInum++] = pc();
   1037     mMips->NOP2();
   1038     NOT_IMPLEMENTED();
   1039 }
   1040 
   1041 void ArmToMips64Assembler::QDADD(int cc,  int Rd, int Rm, int Rn)
   1042 {
   1043     // *mPC++ = (cc<<28) | 0x1400050 | (Rn<<16) | (Rd<<12) | Rm;
   1044     mArmPC[mInum++] = pc();
   1045     mMips->NOP2();
   1046     NOT_IMPLEMENTED();
   1047 }
   1048 
   1049 void ArmToMips64Assembler::QSUB(int cc,  int Rd, int Rm, int Rn)
   1050 {
   1051     // *mPC++ = (cc<<28) | 0x1200050 | (Rn<<16) | (Rd<<12) | Rm;
   1052     mArmPC[mInum++] = pc();
   1053     mMips->NOP2();
   1054     NOT_IMPLEMENTED();
   1055 }
   1056 
   1057 void ArmToMips64Assembler::QDSUB(int cc,  int Rd, int Rm, int Rn)
   1058 {
   1059     // *mPC++ = (cc<<28) | 0x1600050 | (Rn<<16) | (Rd<<12) | Rm;
   1060     mArmPC[mInum++] = pc();
   1061     mMips->NOP2();
   1062     NOT_IMPLEMENTED();
   1063 }
   1064 
   1065 // 16 x 16 signed multiply (like SMLAxx without the accumulate)
   1066 void ArmToMips64Assembler::SMUL(int cc, int xy,
   1067                 int Rd, int Rm, int Rs)
   1068 {
   1069     mArmPC[mInum++] = pc();
   1070 
   1071     // the 16 bits may be in the top or bottom half of 32-bit source reg,
   1072     // as defined by the codes BB, BT, TB, TT (compressed param xy)
   1073     // where x corresponds to Rm and y to Rs
   1074 
   1075     // select half-reg for Rm
   1076     if (xy & xyTB) {
   1077         // use top 16-bits
   1078         mMips->SRA(R_at, Rm, 16);
   1079     } else {
   1080         // use bottom 16, but sign-extend to 32
   1081         mMips->SEH(R_at, Rm);
   1082     }
   1083     // select half-reg for Rs
   1084     if (xy & xyBT) {
   1085         // use top 16-bits
   1086         mMips->SRA(R_at2, Rs, 16);
   1087     } else {
   1088         // use bottom 16, but sign-extend to 32
   1089         mMips->SEH(R_at2, Rs);
   1090     }
   1091     mMips->MUL(Rd, R_at, R_at2);
   1092 }
   1093 
   1094 // signed 32b x 16b multiple, save top 32-bits of 48-bit result
   1095 void ArmToMips64Assembler::SMULW(int cc, int y,
   1096                 int Rd, int Rm, int Rs)
   1097 {
   1098     mArmPC[mInum++] = pc();
   1099 
   1100     // the selector yT or yB refers to reg Rs
   1101     if (y & yT) {
   1102         // zero the bottom 16-bits, with 2 shifts, it can affect result
   1103         mMips->SRL(R_at, Rs, 16);
   1104         mMips->SLL(R_at, R_at, 16);
   1105 
   1106     } else {
   1107         // move low 16-bit half, to high half
   1108         mMips->SLL(R_at, Rs, 16);
   1109     }
   1110     mMips->MUH(Rd, Rm, R_at);
   1111 }
   1112 
   1113 // 16 x 16 signed multiply, accumulate: Rd = Rm{16} * Rs{16} + Rn
   1114 void ArmToMips64Assembler::SMLA(int cc, int xy,
   1115                 int Rd, int Rm, int Rs, int Rn)
   1116 {
   1117     mArmPC[mInum++] = pc();
   1118 
   1119     // the 16 bits may be in the top or bottom half of 32-bit source reg,
   1120     // as defined by the codes BB, BT, TB, TT (compressed param xy)
   1121     // where x corresponds to Rm and y to Rs
   1122 
   1123     // select half-reg for Rm
   1124     if (xy & xyTB) {
   1125         // use top 16-bits
   1126         mMips->SRA(R_at, Rm, 16);
   1127     } else {
   1128         // use bottom 16, but sign-extend to 32
   1129         mMips->SEH(R_at, Rm);
   1130     }
   1131     // select half-reg for Rs
   1132     if (xy & xyBT) {
   1133         // use top 16-bits
   1134         mMips->SRA(R_at2, Rs, 16);
   1135     } else {
   1136         // use bottom 16, but sign-extend to 32
   1137         mMips->SEH(R_at2, Rs);
   1138     }
   1139 
   1140     mMips->MUL(R_at, R_at, R_at2);
   1141     mMips->ADDU(Rd, R_at, Rn);
   1142 }
   1143 
   1144 void ArmToMips64Assembler::SMLAL(int cc, int xy,
   1145                 int RdHi, int RdLo, int Rs, int Rm)
   1146 {
   1147     // *mPC++ = (cc<<28) | 0x1400080 | (RdHi<<16) | (RdLo<<12) | (Rs<<8) | (xy<<4) | Rm;
   1148     mArmPC[mInum++] = pc();
   1149     mMips->NOP2();
   1150     NOT_IMPLEMENTED();
   1151 }
   1152 
   1153 void ArmToMips64Assembler::SMLAW(int cc, int y,
   1154                 int Rd, int Rm, int Rs, int Rn)
   1155 {
   1156     // *mPC++ = (cc<<28) | 0x1200080 | (Rd<<16) | (Rn<<12) | (Rs<<8) | (y<<4) | Rm;
   1157     mArmPC[mInum++] = pc();
   1158     mMips->NOP2();
   1159     NOT_IMPLEMENTED();
   1160 }
   1161 
   1162 // used by ARMv6 version of GGLAssembler::filter32
   1163 void ArmToMips64Assembler::UXTB16(int cc, int Rd, int Rm, int rotate)
   1164 {
   1165     mArmPC[mInum++] = pc();
   1166 
   1167     //Rd[31:16] := ZeroExtend((Rm ROR (8 * sh))[23:16]),
   1168     //Rd[15:0] := ZeroExtend((Rm ROR (8 * sh))[7:0]). sh 0-3.
   1169 
   1170     mMips->ROTR(R_at2, Rm, rotate * 8);
   1171     mMips->LUI(R_at, 0xFF);
   1172     mMips->ORI(R_at, R_at, 0xFF);
   1173     mMips->AND(Rd, R_at2, R_at);
   1174 }
   1175 
   1176 void ArmToMips64Assembler::UBFX(int cc, int Rd, int Rn, int lsb, int width)
   1177 {
   1178      /* Placeholder for UBFX */
   1179      mArmPC[mInum++] = pc();
   1180 
   1181      mMips->NOP2();
   1182      NOT_IMPLEMENTED();
   1183 }
   1184 
   1185 // ----------------------------------------------------------------------------
   1186 // Address Processing...
   1187 // ----------------------------------------------------------------------------
   1188 
   1189 void ArmToMips64Assembler::ADDR_ADD(int cc,
   1190         int s, int Rd, int Rn, uint32_t Op2)
   1191 {
   1192 //    if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
   1193 //    if(s  != 0) { NOT_IMPLEMENTED(); return;} //Not required
   1194     dataProcessing(opADD64, cc, s, Rd, Rn, Op2);
   1195 }
   1196 
   1197 void ArmToMips64Assembler::ADDR_SUB(int cc,
   1198         int s, int Rd, int Rn, uint32_t Op2)
   1199 {
   1200 //    if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
   1201 //    if(s  != 0) { NOT_IMPLEMENTED(); return;} //Not required
   1202     dataProcessing(opSUB64, cc, s, Rd, Rn, Op2);
   1203 }
   1204 
   1205 void ArmToMips64Assembler::ADDR_LDR(int cc, int Rd, int Rn, uint32_t offset) {
   1206     mArmPC[mInum++] = pc();
   1207     // work-around for ARM default address mode of immed12_pre(0)
   1208     if (offset > AMODE_UNSUPPORTED) offset = 0;
   1209     switch (offset) {
   1210         case 0:
   1211             amode.value = 0;
   1212             amode.writeback = 0;
   1213             // fall thru to next case ....
   1214         case AMODE_IMM_12_PRE:
   1215             if (Rn == ARMAssemblerInterface::SP) {
   1216                 Rn = R_sp;      // convert LDR via Arm SP to LW via Mips SP
   1217             }
   1218             mMips->LD(Rd, Rn, amode.value);
   1219             if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
   1220                 mMips->DADDIU(Rn, Rn, amode.value);
   1221             }
   1222             break;
   1223         case AMODE_IMM_12_POST:
   1224             if (Rn == ARMAssemblerInterface::SP) {
   1225                 Rn = R_sp;      // convert STR thru Arm SP to STR thru Mips SP
   1226             }
   1227             mMips->LD(Rd, Rn, 0);
   1228             mMips->DADDIU(Rn, Rn, amode.value);
   1229             break;
   1230         case AMODE_REG_SCALE_PRE:
   1231             // we only support simple base + index, no advanced modes for this one yet
   1232             mMips->DADDU(R_at, Rn, amode.reg);
   1233             mMips->LD(Rd, R_at, 0);
   1234             break;
   1235     }
   1236 }
   1237 
   1238 void ArmToMips64Assembler::ADDR_STR(int cc, int Rd, int Rn, uint32_t offset) {
   1239     mArmPC[mInum++] = pc();
   1240     // work-around for ARM default address mode of immed12_pre(0)
   1241     if (offset > AMODE_UNSUPPORTED) offset = 0;
   1242     switch (offset) {
   1243         case 0:
   1244             amode.value = 0;
   1245             amode.writeback = 0;
   1246             // fall thru to next case ....
   1247         case AMODE_IMM_12_PRE:
   1248             if (Rn == ARMAssemblerInterface::SP) {
   1249                 Rn = R_sp;  // convert STR thru Arm SP to SW thru Mips SP
   1250             }
   1251             if (amode.writeback) {      // OPTIONAL writeback on pre-index mode
   1252                 // If we will writeback, then update the index reg, then store.
   1253                 // This correctly handles stack-push case.
   1254                 mMips->DADDIU(Rn, Rn, amode.value);
   1255                 mMips->SD(Rd, Rn, 0);
   1256             } else {
   1257                 // No writeback so store offset by value
   1258                 mMips->SD(Rd, Rn, amode.value);
   1259             }
   1260             break;
   1261         case AMODE_IMM_12_POST:
   1262             mMips->SD(Rd, Rn, 0);
   1263             mMips->DADDIU(Rn, Rn, amode.value);  // post index always writes back
   1264             break;
   1265         case AMODE_REG_SCALE_PRE:
   1266             // we only support simple base + index, no advanced modes for this one yet
   1267             mMips->DADDU(R_at, Rn, amode.reg);
   1268             mMips->SD(Rd, R_at, 0);
   1269             break;
   1270     }
   1271 }
   1272 
   1273 #if 0
   1274 #pragma mark -
   1275 #pragma mark MIPS Assembler...
   1276 #endif
   1277 
   1278 
   1279 //**************************************************************************
   1280 //**************************************************************************
   1281 //**************************************************************************
   1282 
   1283 
   1284 /* MIPS64 assembler
   1285 ** this is a subset of mips64r6, targeted specifically at ARM instruction
   1286 ** replacement in the pixelflinger/codeflinger code.
   1287 **
   1288 ** This class is extended from MIPSAssembler class and overrides only
   1289 ** MIPS64r6 specific stuff.
   1290 */
   1291 
   1292 MIPS64Assembler::MIPS64Assembler(const sp<Assembly>& assembly, ArmToMips64Assembler *parent)
   1293     : mParent(parent),
   1294     MIPSAssembler::MIPSAssembler(assembly, NULL)
   1295 {
   1296 }
   1297 
   1298 MIPS64Assembler::MIPS64Assembler(void* assembly, ArmToMips64Assembler *parent)
   1299     : mParent(parent),
   1300     MIPSAssembler::MIPSAssembler(assembly)
   1301 {
   1302 }
   1303 
   1304 MIPS64Assembler::~MIPS64Assembler()
   1305 {
   1306 }
   1307 
   1308 void MIPS64Assembler::reset()
   1309 {
   1310     if (mAssembly != NULL) {
   1311         mBase = mPC = (uint32_t *)mAssembly->base();
   1312     } else {
   1313         mPC = mBase = base();
   1314     }
   1315     mBranchTargets.clear();
   1316     mLabels.clear();
   1317     mLabelsInverseMapping.clear();
   1318     mComments.clear();
   1319 }
   1320 
   1321 
   1322 void MIPS64Assembler::disassemble(const char* name)
   1323 {
   1324     char di_buf[140];
   1325 
   1326     bool arm_disasm_fmt = (mParent->mArmDisassemblyBuffer == NULL) ? false : true;
   1327 
   1328     typedef char dstr[40];
   1329     dstr *lines = (dstr *)mParent->mArmDisassemblyBuffer;
   1330 
   1331     if (mParent->mArmDisassemblyBuffer != NULL) {
   1332         for (int i=0; i<mParent->mArmInstrCount; ++i) {
   1333             string_detab(lines[i]);
   1334         }
   1335     }
   1336 
   1337     // iArm is an index to Arm instructions 1...n for this assembly sequence
   1338     // mArmPC[iArm] holds the value of the Mips-PC for the first MIPS
   1339     // instruction corresponding to that Arm instruction number
   1340 
   1341     int iArm = 0;
   1342     size_t count = pc()-base();
   1343     uint32_t* mipsPC = base();
   1344 
   1345     while (count--) {
   1346         ssize_t label = mLabelsInverseMapping.indexOfKey(mipsPC);
   1347         if (label >= 0) {
   1348             ALOGW("%s:\n", mLabelsInverseMapping.valueAt(label));
   1349         }
   1350         ssize_t comment = mComments.indexOfKey(mipsPC);
   1351         if (comment >= 0) {
   1352             ALOGW("; %s\n", mComments.valueAt(comment));
   1353         }
   1354         ::mips_disassem(mipsPC, di_buf, arm_disasm_fmt);
   1355         string_detab(di_buf);
   1356         string_pad(di_buf, 30);
   1357         ALOGW("%08lx:    %08x    %s", uintptr_t(mipsPC), uint32_t(*mipsPC), di_buf);
   1358         mipsPC++;
   1359     }
   1360 }
   1361 
   1362 void MIPS64Assembler::fix_branches()
   1363 {
   1364     // fixup all the branches
   1365     size_t count = mBranchTargets.size();
   1366     while (count--) {
   1367         const branch_target_t& bt = mBranchTargets[count];
   1368         uint32_t* target_pc = mLabels.valueFor(bt.label);
   1369         LOG_ALWAYS_FATAL_IF(!target_pc,
   1370                 "error resolving branch targets, target_pc is null");
   1371         int32_t offset = int32_t(target_pc - (bt.pc+1));
   1372         *bt.pc |= offset & 0x00FFFF;
   1373     }
   1374 }
   1375 
   1376 void MIPS64Assembler::DADDU(int Rd, int Rs, int Rt)
   1377 {
   1378     *mPC++ = (spec_op<<OP_SHF) | (daddu_fn<<FUNC_SHF)
   1379                     | (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF);
   1380 }
   1381 
   1382 void MIPS64Assembler::DADDIU(int Rt, int Rs, int16_t imm)
   1383 {
   1384     *mPC++ = (daddiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16);
   1385 }
   1386 
   1387 void MIPS64Assembler::DSUBU(int Rd, int Rs, int Rt)
   1388 {
   1389     *mPC++ = (spec_op<<OP_SHF) | (dsubu_fn<<FUNC_SHF) |
   1390                         (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ;
   1391 }
   1392 
   1393 void MIPS64Assembler::DSUBIU(int Rt, int Rs, int16_t imm)   // really addiu(d, s, -j)
   1394 {
   1395     *mPC++ = (daddiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | ((-imm) & MSK_16);
   1396 }
   1397 
   1398 void MIPS64Assembler::MUL(int Rd, int Rs, int Rt)
   1399 {
   1400     *mPC++ = (spec_op<<OP_SHF) | (mul_fn<<RE_SHF) | (sop30_fn<<FUNC_SHF) |
   1401                         (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ;
   1402 }
   1403 
   1404 void MIPS64Assembler::MUH(int Rd, int Rs, int Rt)
   1405 {
   1406     *mPC++ = (spec_op<<OP_SHF) | (muh_fn<<RE_SHF) | (sop30_fn<<FUNC_SHF) |
   1407                         (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ;
   1408 }
   1409 
   1410 void MIPS64Assembler::CLO(int Rd, int Rs)
   1411 {
   1412     *mPC++ = (spec_op<<OP_SHF) | (17<<FUNC_SHF) |
   1413                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (1<<RE_SHF);
   1414 }
   1415 
   1416 void MIPS64Assembler::CLZ(int Rd, int Rs)
   1417 {
   1418     *mPC++ = (spec_op<<OP_SHF) | (16<<FUNC_SHF) |
   1419                         (Rd<<RD_SHF) | (Rs<<RS_SHF) | (1<<RE_SHF);
   1420 }
   1421 
   1422 void MIPS64Assembler::LD(int Rt, int Rbase, int16_t offset)
   1423 {
   1424     *mPC++ = (ld_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1425 }
   1426 
   1427 void MIPS64Assembler::SD(int Rt, int Rbase, int16_t offset)
   1428 {
   1429     *mPC++ = (sd_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1430 }
   1431 
   1432 void MIPS64Assembler::LUI(int Rt, int16_t offset)
   1433 {
   1434     *mPC++ = (aui_op<<OP_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
   1435 }
   1436 
   1437 
   1438 void MIPS64Assembler::JR(int Rs)
   1439 {
   1440         *mPC++ = (spec_op<<OP_SHF) | (Rs<<RS_SHF) | (jalr_fn << FUNC_SHF);
   1441         MIPS64Assembler::NOP();
   1442 }
   1443 
   1444 }; // namespace android:
   1445