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 
ArmToMipsAssembler(const sp<Assembly> & assembly,char * abuf,int linesz,int instr_count)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 
~ArmToMipsAssembler()99 ArmToMipsAssembler::~ArmToMipsAssembler()
100 {
101     delete mMips;
102     free((void *) mArmPC);
103 }
104 
pc() const105 uint32_t* ArmToMipsAssembler::pc() const
106 {
107     return mMips->pc();
108 }
109 
base() const110 uint32_t* ArmToMipsAssembler::base() const
111 {
112     return mMips->base();
113 }
114 
reset()115 void ArmToMipsAssembler::reset()
116 {
117     cond.labelnum = 0;
118     mInum = 0;
119     mMips->reset();
120 }
121 
getCodegenArch()122 int ArmToMipsAssembler::getCodegenArch()
123 {
124     return CODEGEN_ARCH_MIPS;
125 }
126 
comment(const char * string)127 void ArmToMipsAssembler::comment(const char* string)
128 {
129     mMips->comment(string);
130 }
131 
label(const char * theLabel)132 void ArmToMipsAssembler::label(const char* theLabel)
133 {
134     mMips->label(theLabel);
135 }
136 
disassemble(const char * name)137 void ArmToMipsAssembler::disassemble(const char* name)
138 {
139     mMips->disassemble(name);
140 }
141 
init_conditional_labels()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 
prolog()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 
epilog(uint32_t touched)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 
generate(const char * name)184 int ArmToMipsAssembler::generate(const char* name)
185 {
186     return mMips->generate(name);
187 }
188 
pcForLabel(const char * label)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)
buildImmediate(uint32_t immediate,uint32_t & rot,uint32_t & imm)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 
isValidImmediate(uint32_t immediate)216 bool ArmToMipsAssembler::isValidImmediate(uint32_t immediate)
217 {
218     // for MIPS, any 32-bit immediate is OK
219     return true;
220 }
221 
imm(uint32_t immediate)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 
reg_imm(int Rm,int type,uint32_t shift)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 
reg_rrx(int Rm)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 
reg_reg(int Rm,int type,int Rs)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)
immed12_pre(int32_t immed12,int W)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 
immed12_post(int32_t immed12)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 
reg_scale_pre(int Rm,int type,uint32_t shift,int W)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 
reg_scale_post(int Rm,int type,uint32_t shift)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)
immed8_pre(int32_t immed8,int W)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 
immed8_post(int32_t immed8)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 
reg_pre(int Rm,int W)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 
reg_post(int Rm)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 
protectConditionalOperands(int Rd)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
dataProcAdrModes(int op,int & source,bool _signed,int tmpReg)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 
dataProcessing(int opcode,int cc,int s,int Rd,int Rn,uint32_t Op2)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
MLA(int cc,int s,int Rd,int Rm,int Rs,int Rn)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 
MUL(int cc,int s,int Rd,int Rm,int Rs)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 
UMULL(int cc,int s,int RdLo,int RdHi,int Rm,int Rs)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 
UMUAL(int cc,int s,int RdLo,int RdHi,int Rm,int Rs)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 
SMULL(int cc,int s,int RdLo,int RdHi,int Rm,int Rs)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 }
SMUAL(int cc,int s,int RdLo,int RdHi,int Rm,int Rs)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 
B(int cc,const char * label)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 
BL(int cc,const char * label)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 ....
B(int cc,uint32_t * to_pc)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 
BL(int cc,uint32_t * to_pc)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 
BX(int cc,int Rn)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...
LDR(int cc,int Rd,int Rn,uint32_t offset)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 
LDRB(int cc,int Rd,int Rn,uint32_t offset)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 
STR(int cc,int Rd,int Rn,uint32_t offset)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 
STRB(int cc,int Rd,int Rn,uint32_t offset)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 
LDRH(int cc,int Rd,int Rn,uint32_t offset)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 
LDRSB(int cc,int Rd,int Rn,uint32_t offset)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 
LDRSH(int cc,int Rd,int Rn,uint32_t offset)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 
STRH(int cc,int Rd,int Rn,uint32_t offset)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...
LDM(int cc,int dir,int Rn,int W,uint32_t reg_list)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 
STM(int cc,int dir,int Rn,int W,uint32_t reg_list)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...
SWP(int cc,int Rn,int Rd,int Rm)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 
SWPB(int cc,int Rn,int Rd,int Rm)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 
SWI(int cc,uint32_t comment)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...
PLD(int Rn,uint32_t offset)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 
CLZ(int cc,int Rd,int Rm)1037 void ArmToMipsAssembler::CLZ(int cc, int Rd, int Rm)
1038 {
1039     mArmPC[mInum++] = pc();
1040     mMips->CLZ(Rd, Rm);
1041 }
1042 
QADD(int cc,int Rd,int Rm,int Rn)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 
QDADD(int cc,int Rd,int Rm,int Rn)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 
QSUB(int cc,int Rd,int Rm,int Rn)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 
QDSUB(int cc,int Rd,int Rm,int Rn)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)
SMUL(int cc,int xy,int Rd,int Rm,int Rs)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
SMULW(int cc,int y,int Rd,int Rm,int Rs)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
SMLA(int cc,int xy,int Rd,int Rm,int Rs,int 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 
SMLAL(int cc,int xy,int RdHi,int RdLo,int Rs,int Rm)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 
SMLAW(int cc,int y,int Rd,int Rm,int Rs,int Rn)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
UXTB16(int cc,int Rd,int Rm,int rotate)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 
UBFX(int cc,int Rd,int Rn,int lsb,int width)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 
MIPSAssembler(const sp<Assembly> & assembly,ArmToMipsAssembler * parent)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 
MIPSAssembler(void * assembly)1254 MIPSAssembler::MIPSAssembler(void* assembly)
1255     : mParent(NULL), mAssembly(NULL)
1256 {
1257     mBase = mPC = (uint32_t *)assembly;
1258 }
1259 
~MIPSAssembler()1260 MIPSAssembler::~MIPSAssembler()
1261 {
1262 }
1263 
1264 
pc() const1265 uint32_t* MIPSAssembler::pc() const
1266 {
1267     return mPC;
1268 }
1269 
base() const1270 uint32_t* MIPSAssembler::base() const
1271 {
1272     return mBase;
1273 }
1274 
reset()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
string_detab(char * s)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 
string_pad(char * s,int padded_len)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 
disassemble(const char * name)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 
comment(const char * string)1367 void MIPSAssembler::comment(const char* string)
1368 {
1369     mComments.add(pc(), string);
1370 }
1371 
label(const char * theLabel)1372 void MIPSAssembler::label(const char* theLabel)
1373 {
1374     mLabels.add(theLabel, pc());
1375     mLabelsInverseMapping.add(pc(), theLabel);
1376 }
1377 
1378 
prolog()1379 void MIPSAssembler::prolog()
1380 {
1381     // empty - done in ArmToMipsAssembler
1382 }
1383 
epilog(uint32_t touched)1384 void MIPSAssembler::epilog(uint32_t touched)
1385 {
1386     // empty - done in ArmToMipsAssembler
1387 }
1388 
generate(const char * name)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 
pcForLabel(const char * label)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 
ADDU(int Rd,int Rs,int Rt)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
ADDIU(int Rt,int Rs,int16_t imm)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 
SUBU(int Rd,int Rs,int Rt)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 
SUBIU(int Rt,int Rs,int16_t imm)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 
NEGU(int Rd,int Rs)1459 void MIPSAssembler::NEGU(int Rd, int Rs)    // really subu(d, zero, s)
1460 {
1461     MIPSAssembler::SUBU(Rd, 0, Rs);
1462 }
1463 
MUL(int Rd,int Rs,int Rt)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 
MULT(int Rs,int Rt)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 
MULTU(int Rs,int Rt)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 
MADD(int Rs,int Rt)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 
MADDU(int Rs,int Rt)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 
MSUB(int Rs,int Rt)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 
MSUBU(int Rs,int Rt)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 
SEB(int Rd,int Rt)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 
SEH(int Rd,int Rt)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 
SLT(int Rd,int Rs,int Rt)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 
SLTI(int Rt,int Rs,int16_t imm)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 
SLTU(int Rd,int Rs,int Rt)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 
SLTIU(int Rt,int Rs,int16_t imm)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 
AND(int Rd,int Rs,int Rt)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 
ANDI(int Rt,int Rs,uint16_t imm)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 
OR(int Rd,int Rs,int Rt)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 
ORI(int Rt,int Rs,uint16_t imm)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 
NOR(int Rd,int Rs,int Rt)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 
NOT(int Rd,int Rs)1580 void MIPSAssembler::NOT(int Rd, int Rs)
1581 {
1582     MIPSAssembler::NOR(Rd, Rs, 0);  // NOT(d,s) = NOR(d,s,zero)
1583 }
1584 
XOR(int Rd,int Rs,int Rt)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 
XORI(int Rt,int Rs,uint16_t imm)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 
SLL(int Rd,int Rt,int shft)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 
SLLV(int Rd,int Rt,int Rs)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 
SRL(int Rd,int Rt,int shft)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 
SRLV(int Rd,int Rt,int Rs)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 
SRA(int Rd,int Rt,int shft)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 
SRAV(int Rd,int Rt,int Rs)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 
ROTR(int Rd,int Rt,int shft)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 
ROTRV(int Rd,int Rt,int Rs)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)
RORsyn(int Rd,int Rt,int Rs)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)
RORIsyn(int Rd,int Rt,int rot)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 
CLO(int Rd,int Rs)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 
CLZ(int Rd,int Rs)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 
WSBH(int Rd,int Rt)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 
LW(int Rt,int Rbase,int16_t offset)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 
SW(int Rt,int Rbase,int16_t offset)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
LB(int Rt,int Rbase,int16_t offset)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 
LBU(int Rt,int Rbase,int16_t offset)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 
SB(int Rt,int Rbase,int16_t offset)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
LH(int Rt,int Rbase,int16_t offset)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 
LHU(int Rt,int Rbase,int16_t offset)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 
SH(int Rt,int Rbase,int16_t offset)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 
LUI(int Rt,int16_t offset)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 
MOVE(int Rd,int Rs)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 
MOVN(int Rd,int Rs,int Rt)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 
MOVZ(int Rd,int Rs,int Rt)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 
MFHI(int Rd)1766 void MIPSAssembler::MFHI(int Rd)
1767 {
1768     *mPC++ = (spec_op<<OP_SHF) | (mfhi_fn<<FUNC_SHF) | (Rd<<RD_SHF);
1769 }
1770 
MFLO(int Rd)1771 void MIPSAssembler::MFLO(int Rd)
1772 {
1773     *mPC++ = (spec_op<<OP_SHF) | (mflo_fn<<FUNC_SHF) | (Rd<<RD_SHF);
1774 }
1775 
MTHI(int Rs)1776 void MIPSAssembler::MTHI(int Rs)
1777 {
1778     *mPC++ = (spec_op<<OP_SHF) | (mthi_fn<<FUNC_SHF) | (Rs<<RS_SHF);
1779 }
1780 
MTLO(int Rs)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
B(const char * label)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 
BEQ(int Rs,int Rt,const char * label)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 
BNE(int Rs,int Rt,const char * label)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 
BLEZ(int Rs,const char * label)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 
BLTZ(int Rs,const char * label)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 
BGTZ(int Rs,const char * label)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 
BGEZ(int Rs,const char * label)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 
JR(int Rs)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)
BEQZ(int Rs,const char * label)1862 void MIPSAssembler::BEQZ(int Rs, const char* label)
1863 {
1864     BEQ(Rs, R_zero, label);
1865 }
1866 
BNEZ(int Rs,const char * label)1867 void MIPSAssembler::BNEZ(int Rs, const char* label)
1868 {
1869     BNE(R_at, R_zero, label);
1870 }
1871 
BGE(int Rs,int Rt,const char * label)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 
BGEU(int Rs,int Rt,const char * label)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 
BGT(int Rs,int Rt,const char * label)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 
BGTU(int Rs,int Rt,const char * label)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 
BLE(int Rs,int Rt,const char * label)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 
BLEU(int Rs,int Rt,const char * label)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 
BLT(int Rs,int Rt,const char * label)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 
BLTU(int Rs,int Rt,const char * label)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 
NOP(void)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
NOP2(void)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
UNIMPL(void)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