| /* 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, |
| }; |
| |
| 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; |
| }; |
| |
| 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; |
| }; |
| |
| #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 */ |