| /* SPDX-License-Identifier: GPL-2.0 */ | |
| /* | |
| * Copyright (C) 2020-2022 Loongson Technology Corporation Limited | |
| */ | |
| #ifndef _ASM_INST_H | |
| #define _ASM_INST_H | |
| #include <linux/bitops.h> | |
| #define LOONGARCH_INSN_NOP 0x03400000 | |
| enum reg0i15_op { | |
| break_op = 0x54, | |
| }; | |
| enum reg0i26_op { | |
| b_op = 0x14, | |
| bl_op = 0x15, | |
| }; | |
| enum reg1i21_op { | |
| beqz_op = 0x10, | |
| bnez_op = 0x11, | |
| bceqz_op = 0x12, /* bits[9:8] = 0x00 */ | |
| bcnez_op = 0x12, /* bits[9:8] = 0x01 */ | |
| }; | |
| enum reg2_op { | |
| ertn_op = 0x1920e, | |
| }; | |
| enum reg2i12_op { | |
| addid_op = 0x0b, | |
| andi_op = 0x0d, | |
| ldd_op = 0xa3, | |
| std_op = 0xa7, | |
| }; | |
| enum reg2i14_op { | |
| ldptrd_op = 0x26, | |
| stptrd_op = 0x27, | |
| }; | |
| enum reg2i16_op { | |
| jirl_op = 0x13, | |
| beq_op = 0x16, | |
| bne_op = 0x17, | |
| blt_op = 0x18, | |
| bge_op = 0x19, | |
| bltu_op = 0x1a, | |
| bgeu_op = 0x1b, | |
| }; | |
| enum reg3_op { | |
| amswapw_op = 0x70c0, | |
| }; | |
| struct reg0i15_format { | |
| unsigned int immediate : 15; | |
| unsigned int opcode : 17; | |
| }; | |
| struct reg0i26_format { | |
| unsigned int immediate_h : 10; | |
| unsigned int immediate_l : 16; | |
| unsigned int opcode : 6; | |
| }; | |
| struct reg1i21_format { | |
| unsigned int immediate_h : 5; | |
| unsigned int rj : 5; | |
| unsigned int immediate_l : 16; | |
| unsigned int opcode : 6; | |
| }; | |
| struct reg2_format { | |
| unsigned int rd : 5; | |
| unsigned int rj : 5; | |
| unsigned int opcode : 22; | |
| }; | |
| struct reg2i12_format { | |
| unsigned int rd : 5; | |
| unsigned int rj : 5; | |
| unsigned int immediate : 12; | |
| unsigned int opcode : 10; | |
| }; | |
| struct reg2i14_format { | |
| unsigned int rd : 5; | |
| unsigned int rj : 5; | |
| unsigned int immediate : 14; | |
| unsigned int opcode : 8; | |
| }; | |
| struct reg2i16_format { | |
| unsigned int rd : 5; | |
| unsigned int rj : 5; | |
| unsigned int immediate : 16; | |
| unsigned int opcode : 6; | |
| }; | |
| struct reg3_format { | |
| unsigned int rd : 5; | |
| unsigned int rj : 5; | |
| unsigned int rk : 5; | |
| unsigned int opcode : 17; | |
| }; | |
| union loongarch_instruction { | |
| unsigned int word; | |
| struct reg0i15_format reg0i15_format; | |
| struct reg0i26_format reg0i26_format; | |
| struct reg1i21_format reg1i21_format; | |
| struct reg2_format reg2_format; | |
| struct reg2i12_format reg2i12_format; | |
| struct reg2i14_format reg2i14_format; | |
| struct reg2i16_format reg2i16_format; | |
| struct reg3_format reg3_format; | |
| }; | |
| #define LOONGARCH_INSN_SIZE sizeof(union loongarch_instruction) | |
| enum loongarch_gpr { | |
| LOONGARCH_GPR_ZERO = 0, | |
| LOONGARCH_GPR_RA = 1, | |
| LOONGARCH_GPR_TP = 2, | |
| LOONGARCH_GPR_SP = 3, | |
| LOONGARCH_GPR_A0 = 4, /* Reused as V0 for return value */ | |
| LOONGARCH_GPR_A1, /* Reused as V1 for return value */ | |
| LOONGARCH_GPR_A2, | |
| LOONGARCH_GPR_A3, | |
| LOONGARCH_GPR_A4, | |
| LOONGARCH_GPR_A5, | |
| LOONGARCH_GPR_A6, | |
| LOONGARCH_GPR_A7, | |
| LOONGARCH_GPR_T0 = 12, | |
| LOONGARCH_GPR_T1, | |
| LOONGARCH_GPR_T2, | |
| LOONGARCH_GPR_T3, | |
| LOONGARCH_GPR_T4, | |
| LOONGARCH_GPR_T5, | |
| LOONGARCH_GPR_T6, | |
| LOONGARCH_GPR_T7, | |
| LOONGARCH_GPR_T8, | |
| LOONGARCH_GPR_FP = 22, | |
| LOONGARCH_GPR_S0 = 23, | |
| LOONGARCH_GPR_S1, | |
| LOONGARCH_GPR_S2, | |
| LOONGARCH_GPR_S3, | |
| LOONGARCH_GPR_S4, | |
| LOONGARCH_GPR_S5, | |
| LOONGARCH_GPR_S6, | |
| LOONGARCH_GPR_S7, | |
| LOONGARCH_GPR_S8, | |
| LOONGARCH_GPR_MAX | |
| }; | |
| #define DEF_EMIT_REG2I16_FORMAT(NAME, OP) \ | |
| static inline void emit_##NAME(union loongarch_instruction *insn, \ | |
| enum loongarch_gpr rj, \ | |
| enum loongarch_gpr rd, \ | |
| int offset) \ | |
| { \ | |
| insn->reg2i16_format.opcode = OP; \ | |
| insn->reg2i16_format.immediate = offset; \ | |
| insn->reg2i16_format.rj = rj; \ | |
| insn->reg2i16_format.rd = rd; \ | |
| } | |
| DEF_EMIT_REG2I16_FORMAT(jirl, jirl_op) | |
| #endif /* _ASM_INST_H */ |