1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4 */
5 #ifndef _ASM_INST_H
6 #define _ASM_INST_H
7
8 #include <linux/types.h>
9 #include <asm/asm.h>
10 #include <asm/ptrace.h>
11
12 #define INSN_NOP 0x03400000
13 #define INSN_BREAK 0x002a0000
14
15 #define ADDR_IMMMASK_LU52ID 0xFFF0000000000000
16 #define ADDR_IMMMASK_LU32ID 0x000FFFFF00000000
17 #define ADDR_IMMMASK_LU12IW 0x00000000FFFFF000
18 #define ADDR_IMMMASK_ADDU16ID 0x00000000FFFF0000
19
20 #define ADDR_IMMSHIFT_LU52ID 52
21 #define ADDR_IMMSHIFT_LU32ID 32
22 #define ADDR_IMMSHIFT_LU12IW 12
23 #define ADDR_IMMSHIFT_ADDU16ID 16
24
25 #define ADDR_IMM(addr, INSN) ((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN)
26
27 enum reg0i15_op {
28 break_op = 0x54,
29 };
30
31 enum reg0i26_op {
32 b_op = 0x14,
33 bl_op = 0x15,
34 };
35
36 enum reg1i20_op {
37 lu12iw_op = 0x0a,
38 lu32id_op = 0x0b,
39 pcaddi_op = 0x0c,
40 pcalau12i_op = 0x0d,
41 pcaddu12i_op = 0x0e,
42 pcaddu18i_op = 0x0f,
43 };
44
45 enum reg1i21_op {
46 beqz_op = 0x10,
47 bnez_op = 0x11,
48 bceqz_op = 0x12, /* bits[9:8] = 0x00 */
49 bcnez_op = 0x12, /* bits[9:8] = 0x01 */
50 };
51
52 enum reg2_op {
53 revb2h_op = 0x0c,
54 revb4h_op = 0x0d,
55 revb2w_op = 0x0e,
56 revbd_op = 0x0f,
57 revh2w_op = 0x10,
58 revhd_op = 0x11,
59 };
60
61 enum reg2i5_op {
62 slliw_op = 0x81,
63 srliw_op = 0x89,
64 sraiw_op = 0x91,
65 };
66
67 enum reg2i6_op {
68 sllid_op = 0x41,
69 srlid_op = 0x45,
70 sraid_op = 0x49,
71 };
72
73 enum reg2i12_op {
74 addiw_op = 0x0a,
75 addid_op = 0x0b,
76 lu52id_op = 0x0c,
77 andi_op = 0x0d,
78 ori_op = 0x0e,
79 xori_op = 0x0f,
80 ldb_op = 0xa0,
81 ldh_op = 0xa1,
82 ldw_op = 0xa2,
83 ldd_op = 0xa3,
84 stb_op = 0xa4,
85 sth_op = 0xa5,
86 stw_op = 0xa6,
87 std_op = 0xa7,
88 ldbu_op = 0xa8,
89 ldhu_op = 0xa9,
90 ldwu_op = 0xaa,
91 flds_op = 0xac,
92 fsts_op = 0xad,
93 fldd_op = 0xae,
94 fstd_op = 0xaf,
95 };
96
97 enum reg2i14_op {
98 llw_op = 0x20,
99 scw_op = 0x21,
100 lld_op = 0x22,
101 scd_op = 0x23,
102 ldptrw_op = 0x24,
103 stptrw_op = 0x25,
104 ldptrd_op = 0x26,
105 stptrd_op = 0x27,
106 };
107
108 enum reg2i16_op {
109 jirl_op = 0x13,
110 beq_op = 0x16,
111 bne_op = 0x17,
112 blt_op = 0x18,
113 bge_op = 0x19,
114 bltu_op = 0x1a,
115 bgeu_op = 0x1b,
116 };
117
118 enum reg2bstrd_op {
119 bstrinsd_op = 0x2,
120 bstrpickd_op = 0x3,
121 };
122
123 enum reg3_op {
124 addw_op = 0x20,
125 addd_op = 0x21,
126 subw_op = 0x22,
127 subd_op = 0x23,
128 nor_op = 0x28,
129 and_op = 0x29,
130 or_op = 0x2a,
131 xor_op = 0x2b,
132 orn_op = 0x2c,
133 andn_op = 0x2d,
134 sllw_op = 0x2e,
135 srlw_op = 0x2f,
136 sraw_op = 0x30,
137 slld_op = 0x31,
138 srld_op = 0x32,
139 srad_op = 0x33,
140 mulw_op = 0x38,
141 mulhw_op = 0x39,
142 mulhwu_op = 0x3a,
143 muld_op = 0x3b,
144 mulhd_op = 0x3c,
145 mulhdu_op = 0x3d,
146 divw_op = 0x40,
147 modw_op = 0x41,
148 divwu_op = 0x42,
149 modwu_op = 0x43,
150 divd_op = 0x44,
151 modd_op = 0x45,
152 divdu_op = 0x46,
153 moddu_op = 0x47,
154 ldxb_op = 0x7000,
155 ldxh_op = 0x7008,
156 ldxw_op = 0x7010,
157 ldxd_op = 0x7018,
158 stxb_op = 0x7020,
159 stxh_op = 0x7028,
160 stxw_op = 0x7030,
161 stxd_op = 0x7038,
162 ldxbu_op = 0x7040,
163 ldxhu_op = 0x7048,
164 ldxwu_op = 0x7050,
165 fldxs_op = 0x7060,
166 fldxd_op = 0x7068,
167 fstxs_op = 0x7070,
168 fstxd_op = 0x7078,
169 amswapw_op = 0x70c0,
170 amswapd_op = 0x70c1,
171 amaddw_op = 0x70c2,
172 amaddd_op = 0x70c3,
173 amandw_op = 0x70c4,
174 amandd_op = 0x70c5,
175 amorw_op = 0x70c6,
176 amord_op = 0x70c7,
177 amxorw_op = 0x70c8,
178 amxord_op = 0x70c9,
179 };
180
181 enum reg3sa2_op {
182 alslw_op = 0x02,
183 alslwu_op = 0x03,
184 alsld_op = 0x16,
185 };
186
187 struct reg0i15_format {
188 unsigned int immediate : 15;
189 unsigned int opcode : 17;
190 };
191
192 struct reg0i26_format {
193 unsigned int immediate_h : 10;
194 unsigned int immediate_l : 16;
195 unsigned int opcode : 6;
196 };
197
198 struct reg1i20_format {
199 unsigned int rd : 5;
200 unsigned int immediate : 20;
201 unsigned int opcode : 7;
202 };
203
204 struct reg1i21_format {
205 unsigned int immediate_h : 5;
206 unsigned int rj : 5;
207 unsigned int immediate_l : 16;
208 unsigned int opcode : 6;
209 };
210
211 struct reg2_format {
212 unsigned int rd : 5;
213 unsigned int rj : 5;
214 unsigned int opcode : 22;
215 };
216
217 struct reg2i5_format {
218 unsigned int rd : 5;
219 unsigned int rj : 5;
220 unsigned int immediate : 5;
221 unsigned int opcode : 17;
222 };
223
224 struct reg2i6_format {
225 unsigned int rd : 5;
226 unsigned int rj : 5;
227 unsigned int immediate : 6;
228 unsigned int opcode : 16;
229 };
230
231 struct reg2i12_format {
232 unsigned int rd : 5;
233 unsigned int rj : 5;
234 unsigned int immediate : 12;
235 unsigned int opcode : 10;
236 };
237
238 struct reg2i14_format {
239 unsigned int rd : 5;
240 unsigned int rj : 5;
241 unsigned int immediate : 14;
242 unsigned int opcode : 8;
243 };
244
245 struct reg2i16_format {
246 unsigned int rd : 5;
247 unsigned int rj : 5;
248 unsigned int immediate : 16;
249 unsigned int opcode : 6;
250 };
251
252 struct reg2bstrd_format {
253 unsigned int rd : 5;
254 unsigned int rj : 5;
255 unsigned int lsbd : 6;
256 unsigned int msbd : 6;
257 unsigned int opcode : 10;
258 };
259
260 struct reg3_format {
261 unsigned int rd : 5;
262 unsigned int rj : 5;
263 unsigned int rk : 5;
264 unsigned int opcode : 17;
265 };
266
267 struct reg3sa2_format {
268 unsigned int rd : 5;
269 unsigned int rj : 5;
270 unsigned int rk : 5;
271 unsigned int immediate : 2;
272 unsigned int opcode : 15;
273 };
274
275 union loongarch_instruction {
276 unsigned int word;
277 struct reg0i15_format reg0i15_format;
278 struct reg0i26_format reg0i26_format;
279 struct reg1i20_format reg1i20_format;
280 struct reg1i21_format reg1i21_format;
281 struct reg2_format reg2_format;
282 struct reg2i5_format reg2i5_format;
283 struct reg2i6_format reg2i6_format;
284 struct reg2i12_format reg2i12_format;
285 struct reg2i14_format reg2i14_format;
286 struct reg2i16_format reg2i16_format;
287 struct reg2bstrd_format reg2bstrd_format;
288 struct reg3_format reg3_format;
289 struct reg3sa2_format reg3sa2_format;
290 };
291
292 #define LOONGARCH_INSN_SIZE sizeof(union loongarch_instruction)
293
294 enum loongarch_gpr {
295 LOONGARCH_GPR_ZERO = 0,
296 LOONGARCH_GPR_RA = 1,
297 LOONGARCH_GPR_TP = 2,
298 LOONGARCH_GPR_SP = 3,
299 LOONGARCH_GPR_A0 = 4, /* Reused as V0 for return value */
300 LOONGARCH_GPR_A1, /* Reused as V1 for return value */
301 LOONGARCH_GPR_A2,
302 LOONGARCH_GPR_A3,
303 LOONGARCH_GPR_A4,
304 LOONGARCH_GPR_A5,
305 LOONGARCH_GPR_A6,
306 LOONGARCH_GPR_A7,
307 LOONGARCH_GPR_T0 = 12,
308 LOONGARCH_GPR_T1,
309 LOONGARCH_GPR_T2,
310 LOONGARCH_GPR_T3,
311 LOONGARCH_GPR_T4,
312 LOONGARCH_GPR_T5,
313 LOONGARCH_GPR_T6,
314 LOONGARCH_GPR_T7,
315 LOONGARCH_GPR_T8,
316 LOONGARCH_GPR_FP = 22,
317 LOONGARCH_GPR_S0 = 23,
318 LOONGARCH_GPR_S1,
319 LOONGARCH_GPR_S2,
320 LOONGARCH_GPR_S3,
321 LOONGARCH_GPR_S4,
322 LOONGARCH_GPR_S5,
323 LOONGARCH_GPR_S6,
324 LOONGARCH_GPR_S7,
325 LOONGARCH_GPR_S8,
326 LOONGARCH_GPR_MAX
327 };
328
329 #define is_imm12_negative(val) is_imm_negative(val, 12)
330
is_imm_negative(unsigned long val,unsigned int bit)331 static inline bool is_imm_negative(unsigned long val, unsigned int bit)
332 {
333 return val & (1UL << (bit - 1));
334 }
335
is_break_ins(union loongarch_instruction * ip)336 static inline bool is_break_ins(union loongarch_instruction *ip)
337 {
338 return ip->reg0i15_format.opcode == break_op;
339 }
340
is_pc_ins(union loongarch_instruction * ip)341 static inline bool is_pc_ins(union loongarch_instruction *ip)
342 {
343 return ip->reg1i20_format.opcode >= pcaddi_op &&
344 ip->reg1i20_format.opcode <= pcaddu18i_op;
345 }
346
is_branch_ins(union loongarch_instruction * ip)347 static inline bool is_branch_ins(union loongarch_instruction *ip)
348 {
349 return ip->reg1i21_format.opcode >= beqz_op &&
350 ip->reg1i21_format.opcode <= bgeu_op;
351 }
352
is_ra_save_ins(union loongarch_instruction * ip)353 static inline bool is_ra_save_ins(union loongarch_instruction *ip)
354 {
355 /* st.d $ra, $sp, offset */
356 return ip->reg2i12_format.opcode == std_op &&
357 ip->reg2i12_format.rj == LOONGARCH_GPR_SP &&
358 ip->reg2i12_format.rd == LOONGARCH_GPR_RA &&
359 !is_imm12_negative(ip->reg2i12_format.immediate);
360 }
361
is_stack_alloc_ins(union loongarch_instruction * ip)362 static inline bool is_stack_alloc_ins(union loongarch_instruction *ip)
363 {
364 /* addi.d $sp, $sp, -imm */
365 return ip->reg2i12_format.opcode == addid_op &&
366 ip->reg2i12_format.rj == LOONGARCH_GPR_SP &&
367 ip->reg2i12_format.rd == LOONGARCH_GPR_SP &&
368 is_imm12_negative(ip->reg2i12_format.immediate);
369 }
370
is_self_loop_ins(union loongarch_instruction * ip,struct pt_regs * regs)371 static inline bool is_self_loop_ins(union loongarch_instruction *ip, struct pt_regs *regs)
372 {
373 switch (ip->reg0i26_format.opcode) {
374 case b_op:
375 case bl_op:
376 if (ip->reg0i26_format.immediate_l == 0
377 && ip->reg0i26_format.immediate_h == 0)
378 return true;
379 }
380
381 switch (ip->reg1i21_format.opcode) {
382 case beqz_op:
383 case bnez_op:
384 case bceqz_op:
385 if (ip->reg1i21_format.immediate_l == 0
386 && ip->reg1i21_format.immediate_h == 0)
387 return true;
388 }
389
390 switch (ip->reg2i16_format.opcode) {
391 case beq_op:
392 case bne_op:
393 case blt_op:
394 case bge_op:
395 case bltu_op:
396 case bgeu_op:
397 if (ip->reg2i16_format.immediate == 0)
398 return true;
399 break;
400 case jirl_op:
401 if (regs->regs[ip->reg2i16_format.rj] +
402 ((unsigned long)ip->reg2i16_format.immediate << 2) == (unsigned long)ip)
403 return true;
404 }
405
406 return false;
407 }
408
409 void simu_pc(struct pt_regs *regs, union loongarch_instruction insn);
410 void simu_branch(struct pt_regs *regs, union loongarch_instruction insn);
411
412 int larch_insn_read(void *addr, u32 *insnp);
413 int larch_insn_write(void *addr, u32 insn);
414 int larch_insn_patch_text(void *addr, u32 insn);
415
416 u32 larch_insn_gen_nop(void);
417 u32 larch_insn_gen_b(unsigned long pc, unsigned long dest);
418 u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest);
419
420 u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongarch_gpr rk);
421 u32 larch_insn_gen_move(enum loongarch_gpr rd, enum loongarch_gpr rj);
422
423 u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm);
424 u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm);
425 u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm);
426 u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest);
427
signed_imm_check(long val,unsigned int bit)428 static inline bool signed_imm_check(long val, unsigned int bit)
429 {
430 return -(1L << (bit - 1)) <= val && val < (1L << (bit - 1));
431 }
432
unsigned_imm_check(unsigned long val,unsigned int bit)433 static inline bool unsigned_imm_check(unsigned long val, unsigned int bit)
434 {
435 return val < (1UL << bit);
436 }
437
438 #define DEF_EMIT_REG0I26_FORMAT(NAME, OP) \
439 static inline void emit_##NAME(union loongarch_instruction *insn, \
440 int offset) \
441 { \
442 unsigned int immediate_l, immediate_h; \
443 \
444 immediate_l = offset & 0xffff; \
445 offset >>= 16; \
446 immediate_h = offset & 0x3ff; \
447 \
448 insn->reg0i26_format.opcode = OP; \
449 insn->reg0i26_format.immediate_l = immediate_l; \
450 insn->reg0i26_format.immediate_h = immediate_h; \
451 }
452
453 DEF_EMIT_REG0I26_FORMAT(b, b_op)
454 DEF_EMIT_REG0I26_FORMAT(bl, bl_op)
455
456 #define DEF_EMIT_REG1I20_FORMAT(NAME, OP) \
457 static inline void emit_##NAME(union loongarch_instruction *insn, \
458 enum loongarch_gpr rd, int imm) \
459 { \
460 insn->reg1i20_format.opcode = OP; \
461 insn->reg1i20_format.immediate = imm; \
462 insn->reg1i20_format.rd = rd; \
463 }
464
465 DEF_EMIT_REG1I20_FORMAT(lu12iw, lu12iw_op)
466 DEF_EMIT_REG1I20_FORMAT(lu32id, lu32id_op)
467 DEF_EMIT_REG1I20_FORMAT(pcaddu18i, pcaddu18i_op)
468
469 #define DEF_EMIT_REG2_FORMAT(NAME, OP) \
470 static inline void emit_##NAME(union loongarch_instruction *insn, \
471 enum loongarch_gpr rd, \
472 enum loongarch_gpr rj) \
473 { \
474 insn->reg2_format.opcode = OP; \
475 insn->reg2_format.rd = rd; \
476 insn->reg2_format.rj = rj; \
477 }
478
479 DEF_EMIT_REG2_FORMAT(revb2h, revb2h_op)
480 DEF_EMIT_REG2_FORMAT(revb2w, revb2w_op)
481 DEF_EMIT_REG2_FORMAT(revbd, revbd_op)
482
483 #define DEF_EMIT_REG2I5_FORMAT(NAME, OP) \
484 static inline void emit_##NAME(union loongarch_instruction *insn, \
485 enum loongarch_gpr rd, \
486 enum loongarch_gpr rj, \
487 int imm) \
488 { \
489 insn->reg2i5_format.opcode = OP; \
490 insn->reg2i5_format.immediate = imm; \
491 insn->reg2i5_format.rd = rd; \
492 insn->reg2i5_format.rj = rj; \
493 }
494
495 DEF_EMIT_REG2I5_FORMAT(slliw, slliw_op)
496 DEF_EMIT_REG2I5_FORMAT(srliw, srliw_op)
497 DEF_EMIT_REG2I5_FORMAT(sraiw, sraiw_op)
498
499 #define DEF_EMIT_REG2I6_FORMAT(NAME, OP) \
500 static inline void emit_##NAME(union loongarch_instruction *insn, \
501 enum loongarch_gpr rd, \
502 enum loongarch_gpr rj, \
503 int imm) \
504 { \
505 insn->reg2i6_format.opcode = OP; \
506 insn->reg2i6_format.immediate = imm; \
507 insn->reg2i6_format.rd = rd; \
508 insn->reg2i6_format.rj = rj; \
509 }
510
511 DEF_EMIT_REG2I6_FORMAT(sllid, sllid_op)
512 DEF_EMIT_REG2I6_FORMAT(srlid, srlid_op)
513 DEF_EMIT_REG2I6_FORMAT(sraid, sraid_op)
514
515 #define DEF_EMIT_REG2I12_FORMAT(NAME, OP) \
516 static inline void emit_##NAME(union loongarch_instruction *insn, \
517 enum loongarch_gpr rd, \
518 enum loongarch_gpr rj, \
519 int imm) \
520 { \
521 insn->reg2i12_format.opcode = OP; \
522 insn->reg2i12_format.immediate = imm; \
523 insn->reg2i12_format.rd = rd; \
524 insn->reg2i12_format.rj = rj; \
525 }
526
527 DEF_EMIT_REG2I12_FORMAT(addiw, addiw_op)
528 DEF_EMIT_REG2I12_FORMAT(addid, addid_op)
529 DEF_EMIT_REG2I12_FORMAT(lu52id, lu52id_op)
530 DEF_EMIT_REG2I12_FORMAT(andi, andi_op)
531 DEF_EMIT_REG2I12_FORMAT(ori, ori_op)
532 DEF_EMIT_REG2I12_FORMAT(xori, xori_op)
533 DEF_EMIT_REG2I12_FORMAT(ldbu, ldbu_op)
534 DEF_EMIT_REG2I12_FORMAT(ldhu, ldhu_op)
535 DEF_EMIT_REG2I12_FORMAT(ldwu, ldwu_op)
536 DEF_EMIT_REG2I12_FORMAT(ldd, ldd_op)
537 DEF_EMIT_REG2I12_FORMAT(stb, stb_op)
538 DEF_EMIT_REG2I12_FORMAT(sth, sth_op)
539 DEF_EMIT_REG2I12_FORMAT(stw, stw_op)
540 DEF_EMIT_REG2I12_FORMAT(std, std_op)
541
542 #define DEF_EMIT_REG2I14_FORMAT(NAME, OP) \
543 static inline void emit_##NAME(union loongarch_instruction *insn, \
544 enum loongarch_gpr rd, \
545 enum loongarch_gpr rj, \
546 int imm) \
547 { \
548 insn->reg2i14_format.opcode = OP; \
549 insn->reg2i14_format.immediate = imm; \
550 insn->reg2i14_format.rd = rd; \
551 insn->reg2i14_format.rj = rj; \
552 }
553
554 DEF_EMIT_REG2I14_FORMAT(llw, llw_op)
555 DEF_EMIT_REG2I14_FORMAT(scw, scw_op)
556 DEF_EMIT_REG2I14_FORMAT(lld, lld_op)
557 DEF_EMIT_REG2I14_FORMAT(scd, scd_op)
558 DEF_EMIT_REG2I14_FORMAT(ldptrw, ldptrw_op)
559 DEF_EMIT_REG2I14_FORMAT(stptrw, stptrw_op)
560 DEF_EMIT_REG2I14_FORMAT(ldptrd, ldptrd_op)
561 DEF_EMIT_REG2I14_FORMAT(stptrd, stptrd_op)
562
563 #define DEF_EMIT_REG2I16_FORMAT(NAME, OP) \
564 static inline void emit_##NAME(union loongarch_instruction *insn, \
565 enum loongarch_gpr rj, \
566 enum loongarch_gpr rd, \
567 int offset) \
568 { \
569 insn->reg2i16_format.opcode = OP; \
570 insn->reg2i16_format.immediate = offset; \
571 insn->reg2i16_format.rj = rj; \
572 insn->reg2i16_format.rd = rd; \
573 }
574
575 DEF_EMIT_REG2I16_FORMAT(beq, beq_op)
576 DEF_EMIT_REG2I16_FORMAT(bne, bne_op)
577 DEF_EMIT_REG2I16_FORMAT(blt, blt_op)
578 DEF_EMIT_REG2I16_FORMAT(bge, bge_op)
579 DEF_EMIT_REG2I16_FORMAT(bltu, bltu_op)
580 DEF_EMIT_REG2I16_FORMAT(bgeu, bgeu_op)
581 DEF_EMIT_REG2I16_FORMAT(jirl, jirl_op)
582
583 #define DEF_EMIT_REG2BSTRD_FORMAT(NAME, OP) \
584 static inline void emit_##NAME(union loongarch_instruction *insn, \
585 enum loongarch_gpr rd, \
586 enum loongarch_gpr rj, \
587 int msbd, \
588 int lsbd) \
589 { \
590 insn->reg2bstrd_format.opcode = OP; \
591 insn->reg2bstrd_format.msbd = msbd; \
592 insn->reg2bstrd_format.lsbd = lsbd; \
593 insn->reg2bstrd_format.rj = rj; \
594 insn->reg2bstrd_format.rd = rd; \
595 }
596
597 DEF_EMIT_REG2BSTRD_FORMAT(bstrpickd, bstrpickd_op)
598
599 #define DEF_EMIT_REG3_FORMAT(NAME, OP) \
600 static inline void emit_##NAME(union loongarch_instruction *insn, \
601 enum loongarch_gpr rd, \
602 enum loongarch_gpr rj, \
603 enum loongarch_gpr rk) \
604 { \
605 insn->reg3_format.opcode = OP; \
606 insn->reg3_format.rd = rd; \
607 insn->reg3_format.rj = rj; \
608 insn->reg3_format.rk = rk; \
609 }
610
611 DEF_EMIT_REG3_FORMAT(addd, addd_op)
612 DEF_EMIT_REG3_FORMAT(subd, subd_op)
613 DEF_EMIT_REG3_FORMAT(muld, muld_op)
614 DEF_EMIT_REG3_FORMAT(divdu, divdu_op)
615 DEF_EMIT_REG3_FORMAT(moddu, moddu_op)
616 DEF_EMIT_REG3_FORMAT(and, and_op)
617 DEF_EMIT_REG3_FORMAT(or, or_op)
618 DEF_EMIT_REG3_FORMAT(xor, xor_op)
619 DEF_EMIT_REG3_FORMAT(sllw, sllw_op)
620 DEF_EMIT_REG3_FORMAT(slld, slld_op)
621 DEF_EMIT_REG3_FORMAT(srlw, srlw_op)
622 DEF_EMIT_REG3_FORMAT(srld, srld_op)
623 DEF_EMIT_REG3_FORMAT(sraw, sraw_op)
624 DEF_EMIT_REG3_FORMAT(srad, srad_op)
625 DEF_EMIT_REG3_FORMAT(ldxbu, ldxbu_op)
626 DEF_EMIT_REG3_FORMAT(ldxhu, ldxhu_op)
627 DEF_EMIT_REG3_FORMAT(ldxwu, ldxwu_op)
628 DEF_EMIT_REG3_FORMAT(ldxd, ldxd_op)
629 DEF_EMIT_REG3_FORMAT(stxb, stxb_op)
630 DEF_EMIT_REG3_FORMAT(stxh, stxh_op)
631 DEF_EMIT_REG3_FORMAT(stxw, stxw_op)
632 DEF_EMIT_REG3_FORMAT(stxd, stxd_op)
633 DEF_EMIT_REG3_FORMAT(amaddw, amaddw_op)
634 DEF_EMIT_REG3_FORMAT(amaddd, amaddd_op)
635 DEF_EMIT_REG3_FORMAT(amandw, amandw_op)
636 DEF_EMIT_REG3_FORMAT(amandd, amandd_op)
637 DEF_EMIT_REG3_FORMAT(amorw, amorw_op)
638 DEF_EMIT_REG3_FORMAT(amord, amord_op)
639 DEF_EMIT_REG3_FORMAT(amxorw, amxorw_op)
640 DEF_EMIT_REG3_FORMAT(amxord, amxord_op)
641 DEF_EMIT_REG3_FORMAT(amswapw, amswapw_op)
642 DEF_EMIT_REG3_FORMAT(amswapd, amswapd_op)
643
644 #define DEF_EMIT_REG3SA2_FORMAT(NAME, OP) \
645 static inline void emit_##NAME(union loongarch_instruction *insn, \
646 enum loongarch_gpr rd, \
647 enum loongarch_gpr rj, \
648 enum loongarch_gpr rk, \
649 int imm) \
650 { \
651 insn->reg3sa2_format.opcode = OP; \
652 insn->reg3sa2_format.immediate = imm; \
653 insn->reg3sa2_format.rd = rd; \
654 insn->reg3sa2_format.rj = rj; \
655 insn->reg3sa2_format.rk = rk; \
656 }
657
658 DEF_EMIT_REG3SA2_FORMAT(alsld, alsld_op)
659
660 struct pt_regs;
661
662 void emulate_load_store_insn(struct pt_regs *regs, void __user *addr, unsigned int *pc);
663 unsigned long unaligned_read(void __user *addr, void *value, unsigned long n, bool sign);
664 unsigned long unaligned_write(void __user *addr, unsigned long value, unsigned long n);
665
666 #endif /* _ASM_INST_H */
667