blob: b43e5da0492982e00eadda47f2d33a3679430920 [file] [log] [blame]
bigbiff673c7ae2020-12-02 19:44:56 -05001/* 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
32namespace android {
33
34class 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
39class ArmToMips64Assembler : public ARMAssemblerInterface
40{
41public:
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
185private:
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
252class MIPS64Assembler : public MIPSAssembler
253{
254public:
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
305protected:
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