1 /* libs/pixelflinger/codeflinger/MIPS64Assembler.h
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 #ifndef ANDROID_MIPS64ASSEMBLER_H
19 #define ANDROID_MIPS64ASSEMBLER_H
20 
21 #include <stdint.h>
22 #include <sys/types.h>
23 
24 #include "utils/KeyedVector.h"
25 #include "utils/Vector.h"
26 #include "tinyutils/smartpointer.h"
27 
28 #include "ARMAssemblerInterface.h"
29 #include "MIPSAssembler.h"
30 #include "CodeCache.h"
31 
32 namespace android {
33 
34 class MIPS64Assembler;    // forward reference
35 
36 // this class mimics ARMAssembler interface
37 // intent is to translate each ARM instruction to 1 or more MIPS instr
38 // implementation calls MIPS64Assembler class to generate mips code
39 class ArmToMips64Assembler : public ARMAssemblerInterface
40 {
41 public:
42                 ArmToMips64Assembler(const sp<Assembly>& assembly,
43                         char *abuf = 0, int linesz = 0, int instr_count = 0);
44                 ArmToMips64Assembler(void* assembly);
45     virtual     ~ArmToMips64Assembler();
46 
47     uint32_t*   base() const;
48     uint32_t*   pc() const;
49     void        disassemble(const char* name);
50 
51     virtual void    reset();
52 
53     virtual int     generate(const char* name);
54     virtual int     getCodegenArch();
55 
56     virtual void    prolog();
57     virtual void    epilog(uint32_t touched);
58     virtual void    comment(const char* string);
59     // for testing purposes
60     void        fix_branches();
61     void        set_condition(int mode, int R1, int R2);
62 
63 
64     // -----------------------------------------------------------------------
65     // shifters and addressing modes
66     // -----------------------------------------------------------------------
67 
68     // shifters...
69     virtual bool        isValidImmediate(uint32_t immed);
70     virtual int         buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
71 
72     virtual uint32_t    imm(uint32_t immediate);
73     virtual uint32_t    reg_imm(int Rm, int type, uint32_t shift);
74     virtual uint32_t    reg_rrx(int Rm);
75     virtual uint32_t    reg_reg(int Rm, int type, int Rs);
76 
77     // addressing modes...
78     // LDR(B)/STR(B)/PLD
79     // (immediate and Rm can be negative, which indicates U=0)
80     virtual uint32_t    immed12_pre(int32_t immed12, int W=0);
81     virtual uint32_t    immed12_post(int32_t immed12);
82     virtual uint32_t    reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
83     virtual uint32_t    reg_scale_post(int Rm, int type=0, uint32_t shift=0);
84 
85     // LDRH/LDRSB/LDRSH/STRH
86     // (immediate and Rm can be negative, which indicates U=0)
87     virtual uint32_t    immed8_pre(int32_t immed8, int W=0);
88     virtual uint32_t    immed8_post(int32_t immed8);
89     virtual uint32_t    reg_pre(int Rm, int W=0);
90     virtual uint32_t    reg_post(int Rm);
91 
92 
93 
94 
95     virtual void    dataProcessing(int opcode, int cc, int s,
96                                 int Rd, int Rn,
97                                 uint32_t Op2);
98     virtual void MLA(int cc, int s,
99                 int Rd, int Rm, int Rs, int Rn);
100     virtual void MUL(int cc, int s,
101                 int Rd, int Rm, int Rs);
102     virtual void UMULL(int cc, int s,
103                 int RdLo, int RdHi, int Rm, int Rs);
104     virtual void UMUAL(int cc, int s,
105                 int RdLo, int RdHi, int Rm, int Rs);
106     virtual void SMULL(int cc, int s,
107                 int RdLo, int RdHi, int Rm, int Rs);
108     virtual void SMUAL(int cc, int s,
109                 int RdLo, int RdHi, int Rm, int Rs);
110 
111     virtual void B(int cc, uint32_t* pc);
112     virtual void BL(int cc, uint32_t* pc);
113     virtual void BX(int cc, int Rn);
114     virtual void label(const char* theLabel);
115     virtual void B(int cc, const char* label);
116     virtual void BL(int cc, const char* label);
117 
118     virtual uint32_t* pcForLabel(const char* label);
119 
120     virtual void LDR (int cc, int Rd,
121                 int Rn, uint32_t offset = 0);
122     virtual void LDRB(int cc, int Rd,
123                 int Rn, uint32_t offset = 0);
124     virtual void STR (int cc, int Rd,
125                 int Rn, uint32_t offset = 0);
126     virtual void STRB(int cc, int Rd,
127                 int Rn, uint32_t offset = 0);
128     virtual void LDRH (int cc, int Rd,
129                 int Rn, uint32_t offset = 0);
130     virtual void LDRSB(int cc, int Rd,
131                 int Rn, uint32_t offset = 0);
132     virtual void LDRSH(int cc, int Rd,
133                 int Rn, uint32_t offset = 0);
134     virtual void STRH (int cc, int Rd,
135                 int Rn, uint32_t offset = 0);
136 
137     virtual void LDM(int cc, int dir,
138                 int Rn, int W, uint32_t reg_list);
139     virtual void STM(int cc, int dir,
140                 int Rn, int W, uint32_t reg_list);
141 
142     virtual void SWP(int cc, int Rn, int Rd, int Rm);
143     virtual void SWPB(int cc, int Rn, int Rd, int Rm);
144     virtual void SWI(int cc, uint32_t comment);
145 
146     virtual void PLD(int Rn, uint32_t offset);
147     virtual void CLZ(int cc, int Rd, int Rm);
148     virtual void QADD(int cc, int Rd, int Rm, int Rn);
149     virtual void QDADD(int cc, int Rd, int Rm, int Rn);
150     virtual void QSUB(int cc, int Rd, int Rm, int Rn);
151     virtual void QDSUB(int cc, int Rd, int Rm, int Rn);
152     virtual void SMUL(int cc, int xy,
153                 int Rd, int Rm, int Rs);
154     virtual void SMULW(int cc, int y,
155                 int Rd, int Rm, int Rs);
156     virtual void SMLA(int cc, int xy,
157                 int Rd, int Rm, int Rs, int Rn);
158     virtual void SMLAL(int cc, int xy,
159                 int RdHi, int RdLo, int Rs, int Rm);
160     virtual void SMLAW(int cc, int y,
161                 int Rd, int Rm, int Rs, int Rn);
162 
163     // byte/half word extract...
164     virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
165 
166     // bit manipulation...
167     virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
168 
169     // Address loading/storing/manipulation
170     virtual void ADDR_LDR(int cc, int Rd, int Rn, uint32_t offset = __immed12_pre(0));
171     virtual void ADDR_STR(int cc, int Rd, int Rn, uint32_t offset = __immed12_pre(0));
172     virtual void ADDR_ADD(int cc, int s, int Rd, int Rn, uint32_t Op2);
173     virtual void ADDR_SUB(int cc, int s, int Rd, int Rn, uint32_t Op2);
174 
175     // this is some crap to share is MIPS64Assembler class for debug
176     char *      mArmDisassemblyBuffer;
177     int         mArmLineLength;
178     int         mArmInstrCount;
179 
180     int         mInum;      // current arm instuction number (0..n)
181     uint32_t**  mArmPC;     // array: PC for 1st mips instr of
182                             //      each translated ARM instr
183 
184 
185 private:
186     ArmToMips64Assembler(const ArmToMips64Assembler& rhs);
187     ArmToMips64Assembler& operator = (const ArmToMips64Assembler& rhs);
188 
189     void init_conditional_labels(void);
190 
191     void protectConditionalOperands(int Rd);
192 
193     // reg__tmp set to MIPS AT, reg 1
194     int dataProcAdrModes(int op, int& source, bool sign = false, int reg_tmp = 1);
195 
196     sp<Assembly>        mAssembly;
197     MIPS64Assembler*    mMips;
198 
199 
200     enum misc_constants_t {
201         ARM_MAX_INSTUCTIONS = 512  // based on ASSEMBLY_SCRATCH_SIZE
202     };
203 
204     enum {
205         SRC_REG = 0,
206         SRC_IMM,
207         SRC_ERROR = -1
208     };
209 
210     enum addr_modes {
211         // start above the range of legal mips reg #'s (0-31)
212         AMODE_REG = 0x20,
213         AMODE_IMM, AMODE_REG_IMM,               // for data processing
214         AMODE_IMM_12_PRE, AMODE_IMM_12_POST,    // for load/store
215         AMODE_REG_SCALE_PRE, AMODE_IMM_8_PRE,
216         AMODE_IMM_8_POST, AMODE_REG_PRE,
217         AMODE_UNSUPPORTED
218     };
219 
220     struct addr_mode_t {    // address modes for current ARM instruction
221         int         reg;
222         int         stype;
223         uint32_t    value;
224         bool        writeback;  // writeback the adr reg after modification
225     } amode;
226 
227     enum cond_types {
228         CMP_COND = 1,
229         SBIT_COND
230     };
231 
232     struct cond_mode_t {    // conditional-execution info for current ARM instruction
233         cond_types  type;
234         int         r1;
235         int         r2;
236         int         labelnum;
237         char        label[100][10];
238     } cond;
239 };
240 
241 
242 
243 
244 // ----------------------------------------------------------------------------
245 // ----------------------------------------------------------------------------
246 // ----------------------------------------------------------------------------
247 
248 // This is the basic MIPS64 assembler, which just creates the opcodes in memory.
249 // All the more complicated work is done in ArmToMips64Assember above.
250 // Inherits MIPSAssembler class, and overrides only MIPS64r6 specific stuff
251 
252 class MIPS64Assembler : public MIPSAssembler
253 {
254 public:
255                 MIPS64Assembler(const sp<Assembly>& assembly, ArmToMips64Assembler *parent);
256                 MIPS64Assembler(void* assembly, ArmToMips64Assembler *parent);
257     virtual     ~MIPS64Assembler();
258 
259     virtual void        reset();
260     virtual void        disassemble(const char* name);
261 
262     void        fix_branches();
263 
264     // ------------------------------------------------------------------------
265     // MIPS64AssemblerInterface...
266     // ------------------------------------------------------------------------
267 
268 #if 0
269 #pragma mark -
270 #pragma mark Arithmetic...
271 #endif
272 
273     void DADDU(int Rd, int Rs, int Rt);
274     void DADDIU(int Rt, int Rs, int16_t imm);
275     void DSUBU(int Rd, int Rs, int Rt);
276     void DSUBIU(int Rt, int Rs, int16_t imm);
277     virtual void MUL(int Rd, int Rs, int Rt);
278     void MUH(int Rd, int Rs, int Rt);
279 
280 #if 0
281 #pragma mark -
282 #pragma mark Logical...
283 #endif
284 
285     virtual void CLO(int Rd, int Rs);
286     virtual void CLZ(int Rd, int Rs);
287 
288 #if 0
289 #pragma mark -
290 #pragma mark Load/store...
291 #endif
292 
293     void LD(int Rt, int Rbase, int16_t offset);
294     void SD(int Rt, int Rbase, int16_t offset);
295     virtual void LUI(int Rt, int16_t offset);
296 
297 #if 0
298 #pragma mark -
299 #pragma mark Branch...
300 #endif
301 
302     void JR(int Rs);
303 
304 
305 protected:
306     ArmToMips64Assembler *mParent;
307 
308     // opcode field of all instructions
309     enum opcode_field {
310         spec_op, regimm_op, j_op, jal_op,                  // 0x00 - 0x03
311         beq_op, bne_op, pop06_op, pop07_op,                // 0x04 - 0x07
312         pop10_op, addiu_op, slti_op, sltiu_op,             // 0x08 - 0x0b
313         andi_op, ori_op, xori_op, aui_op,                  // 0x0c - 0x0f
314         cop0_op, cop1_op, cop2_op, rsrv_opc_0,             // 0x10 - 0x13
315         rsrv_opc_1, rsrv_opc_2, pop26_op, pop27_op,        // 0x14 - 0x17
316         pop30_op, daddiu_op, rsrv_opc_3, rsrv_opc_4,       // 0x18 - 0x1b
317         rsrv_opc_5, daui_op, msa_op, spec3_op,             // 0x1c - 0x1f
318         lb_op, lh_op, rsrv_opc_6, lw_op,                   // 0x20 - 0x23
319         lbu_op, lhu_op, rsrv_opc_7, lwu_op,                // 0x24 - 0x27
320         sb_op, sh_op, rsrv_opc_8, sw_op,                   // 0x28 - 0x2b
321         rsrv_opc_9, rsrv_opc_10, rsrv_opc_11, rsrv_opc_12, // 0x2c - 0x2f
322         rsrv_opc_13, lwc1_op, bc_op, rsrv_opc_14,          // 0x2c - 0x2f
323         rsrv_opc_15, ldc1_op, pop66_op, ld_op,             // 0x30 - 0x33
324         rsrv_opc_16, swc1_op, balc_op, pcrel_op,           // 0x34 - 0x37
325         rsrv_opc_17, sdc1_op, pop76_op, sd_op              // 0x38 - 0x3b
326     };
327 
328 
329     // func field for special opcode
330     enum func_spec_op {
331         sll_fn, rsrv_spec_0, srl_fn, sra_fn,
332         sllv_fn, lsa_fn, srlv_fn, srav_fn,
333         rsrv_spec_1, jalr_fn, rsrv_spec_2, rsrv_spec_3,
334         syscall_fn, break_fn, sdbbp_fn, sync_fn,
335         clz_fn, clo_fn, dclz_fn, dclo_fn,
336         dsllv_fn, dlsa_fn, dsrlv_fn, dsrav_fn,
337         sop30_fn, sop31_fn, sop32_fn, sop33_fn,
338         sop34_fn, sop35_fn, sop36_fn, sop37_fn,
339         add_fn, addu_fn, sub_fn, subu_fn,
340         and_fn, or_fn, xor_fn, nor_fn,
341         rsrv_spec_4, rsrv_spec_5, slt_fn, sltu_fn,
342         dadd_fn, daddu_fn, dsub_fn, dsubu_fn,
343         tge_fn, tgeu_fn, tlt_fn, tltu_fn,
344         teq_fn, seleqz_fn, tne_fn, selnez_fn,
345         dsll_fn, rsrv_spec_6, dsrl_fn, dsra_fn,
346         dsll32_fn, rsrv_spec_7, dsrl32_fn, dsra32_fn
347     };
348 
349     // func field for spec3 opcode
350     enum func_spec3_op {
351         ext_fn, dextm_fn, dextu_fn, dext_fn,
352         ins_fn, dinsm_fn, dinsu_fn, dins_fn,
353         cachee_fn = 0x1b, sbe_fn, she_fn, sce_fn, swe_fn,
354         bshfl_fn, prefe_fn = 0x23, dbshfl_fn, cache_fn, sc_fn, scd_fn,
355         lbue_fn, lhue_fn, lbe_fn = 0x2c, lhe_fn, lle_fn, lwe_fn,
356         pref_fn = 0x35, ll_fn, lld_fn, rdhwr_fn = 0x3b
357     };
358 
359     // sa field for spec3 opcodes, with BSHFL function
360     enum func_spec3_bshfl {
361         bitswap_fn,
362         wsbh_fn = 0x02,
363         dshd_fn = 0x05,
364         seb_fn = 0x10,
365         seh_fn = 0x18
366     };
367 
368     // rt field of regimm opcodes.
369     enum regimm_fn {
370         bltz_fn, bgez_fn,
371         dahi_fn = 0x6,
372         nal_fn = 0x10, bal_fn, bltzall_fn, bgezall_fn,
373         sigrie_fn = 0x17,
374         dati_fn = 0x1e, synci_fn
375     };
376 
377     enum muldiv_fn {
378         mul_fn = 0x02, muh_fn
379     };
380 
381     enum mips_inst_shifts {
382         OP_SHF       = 26,
383         JTARGET_SHF  = 0,
384         RS_SHF       = 21,
385         RT_SHF       = 16,
386         RD_SHF       = 11,
387         RE_SHF       = 6,
388         SA_SHF       = RE_SHF,  // synonym
389         IMM_SHF      = 0,
390         FUNC_SHF     = 0,
391 
392         // mask values
393         MSK_16       = 0xffff,
394 
395 
396         CACHEOP_SHF  = 18,
397         CACHESEL_SHF = 16,
398     };
399 };
400 
401 
402 }; // namespace android
403 
404 #endif //ANDROID_MIPS64ASSEMBLER_H
405