LoongArch: Add some instruction opcodes and formats

According to the "Table of Instruction Encoding" in LoongArch Reference
Manual [1], add some instruction opcodes and formats which are used in
the BPF JIT for LoongArch.

[1] https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#table-of-instruction-encoding

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
This commit is contained in:
Tiezhu Yang 2022-10-12 16:36:19 +08:00 committed by Huacai Chen
parent 8a34228eb3
commit 4e59e5a469
1 changed files with 174 additions and 5 deletions

View File

@ -8,6 +8,8 @@
#include <linux/types.h>
#include <asm/asm.h>
#define INSN_BREAK 0x002a0000
#define ADDR_IMMMASK_LU52ID 0xFFF0000000000000
#define ADDR_IMMMASK_LU32ID 0x000FFFFF00000000
#define ADDR_IMMMASK_ADDU16ID 0x00000000FFFF0000
@ -18,9 +20,16 @@
#define ADDR_IMM(addr, INSN) ((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN)
enum reg0i26_op {
b_op = 0x14,
bl_op = 0x15,
};
enum reg1i20_op {
lu12iw_op = 0x0a,
lu32id_op = 0x0b,
pcaddu12i_op = 0x0e,
pcaddu18i_op = 0x0f,
};
enum reg1i21_op {
@ -28,10 +37,34 @@ enum reg1i21_op {
bnez_op = 0x11,
};
enum reg2_op {
revb2h_op = 0x0c,
revb4h_op = 0x0d,
revb2w_op = 0x0e,
revbd_op = 0x0f,
revh2w_op = 0x10,
revhd_op = 0x11,
};
enum reg2i5_op {
slliw_op = 0x81,
srliw_op = 0x89,
sraiw_op = 0x91,
};
enum reg2i6_op {
sllid_op = 0x41,
srlid_op = 0x45,
sraid_op = 0x49,
};
enum reg2i12_op {
addiw_op = 0x0a,
addid_op = 0x0b,
lu52id_op = 0x0c,
andi_op = 0x0d,
ori_op = 0x0e,
xori_op = 0x0f,
ldb_op = 0xa0,
ldh_op = 0xa1,
ldw_op = 0xa2,
@ -40,6 +73,20 @@ enum reg2i12_op {
sth_op = 0xa5,
stw_op = 0xa6,
std_op = 0xa7,
ldbu_op = 0xa8,
ldhu_op = 0xa9,
ldwu_op = 0xaa,
};
enum reg2i14_op {
llw_op = 0x20,
scw_op = 0x21,
lld_op = 0x22,
scd_op = 0x23,
ldptrw_op = 0x24,
stptrw_op = 0x25,
ldptrd_op = 0x26,
stptrd_op = 0x27,
};
enum reg2i16_op {
@ -52,6 +99,71 @@ enum reg2i16_op {
bgeu_op = 0x1b,
};
enum reg2bstrd_op {
bstrinsd_op = 0x2,
bstrpickd_op = 0x3,
};
enum reg3_op {
addw_op = 0x20,
addd_op = 0x21,
subw_op = 0x22,
subd_op = 0x23,
nor_op = 0x28,
and_op = 0x29,
or_op = 0x2a,
xor_op = 0x2b,
orn_op = 0x2c,
andn_op = 0x2d,
sllw_op = 0x2e,
srlw_op = 0x2f,
sraw_op = 0x30,
slld_op = 0x31,
srld_op = 0x32,
srad_op = 0x33,
mulw_op = 0x38,
mulhw_op = 0x39,
mulhwu_op = 0x3a,
muld_op = 0x3b,
mulhd_op = 0x3c,
mulhdu_op = 0x3d,
divw_op = 0x40,
modw_op = 0x41,
divwu_op = 0x42,
modwu_op = 0x43,
divd_op = 0x44,
modd_op = 0x45,
divdu_op = 0x46,
moddu_op = 0x47,
ldxb_op = 0x7000,
ldxh_op = 0x7008,
ldxw_op = 0x7010,
ldxd_op = 0x7018,
stxb_op = 0x7020,
stxh_op = 0x7028,
stxw_op = 0x7030,
stxd_op = 0x7038,
ldxbu_op = 0x7040,
ldxhu_op = 0x7048,
ldxwu_op = 0x7050,
amswapw_op = 0x70c0,
amswapd_op = 0x70c1,
amaddw_op = 0x70c2,
amaddd_op = 0x70c3,
amandw_op = 0x70c4,
amandd_op = 0x70c5,
amorw_op = 0x70c6,
amord_op = 0x70c7,
amxorw_op = 0x70c8,
amxord_op = 0x70c9,
};
enum reg3sa2_op {
alslw_op = 0x02,
alslwu_op = 0x03,
alsld_op = 0x16,
};
struct reg0i26_format {
unsigned int immediate_h : 10;
unsigned int immediate_l : 16;
@ -71,6 +183,26 @@ struct reg1i21_format {
unsigned int opcode : 6;
};
struct reg2_format {
unsigned int rd : 5;
unsigned int rj : 5;
unsigned int opcode : 22;
};
struct reg2i5_format {
unsigned int rd : 5;
unsigned int rj : 5;
unsigned int immediate : 5;
unsigned int opcode : 17;
};
struct reg2i6_format {
unsigned int rd : 5;
unsigned int rj : 5;
unsigned int immediate : 6;
unsigned int opcode : 16;
};
struct reg2i12_format {
unsigned int rd : 5;
unsigned int rj : 5;
@ -78,6 +210,13 @@ struct reg2i12_format {
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;
@ -85,13 +224,43 @@ struct reg2i16_format {
unsigned int opcode : 6;
};
struct reg2bstrd_format {
unsigned int rd : 5;
unsigned int rj : 5;
unsigned int lsbd : 6;
unsigned int msbd : 6;
unsigned int opcode : 10;
};
struct reg3_format {
unsigned int rd : 5;
unsigned int rj : 5;
unsigned int rk : 5;
unsigned int opcode : 17;
};
struct reg3sa2_format {
unsigned int rd : 5;
unsigned int rj : 5;
unsigned int rk : 5;
unsigned int immediate : 2;
unsigned int opcode : 15;
};
union loongarch_instruction {
unsigned int word;
struct reg0i26_format reg0i26_format;
struct reg1i20_format reg1i20_format;
struct reg1i21_format reg1i21_format;
struct reg2i12_format reg2i12_format;
struct reg2i16_format reg2i16_format;
struct reg0i26_format reg0i26_format;
struct reg1i20_format reg1i20_format;
struct reg1i21_format reg1i21_format;
struct reg2_format reg2_format;
struct reg2i5_format reg2i5_format;
struct reg2i6_format reg2i6_format;
struct reg2i12_format reg2i12_format;
struct reg2i14_format reg2i14_format;
struct reg2i16_format reg2i16_format;
struct reg2bstrd_format reg2bstrd_format;
struct reg3_format reg3_format;
struct reg3sa2_format reg3sa2_format;
};
#define LOONGARCH_INSN_SIZE sizeof(union loongarch_instruction)