Files
scc/src/mcode/riscv32/riscv32_instr.h
ZZY b57f21556a stable 重构文件结构
抽象出Machine Code
2025-04-01 23:27:25 +08:00

940 lines
18 KiB
C

#ifndef __SMCC_RISCV32_INSTR_H__
#define __SMCC_RISCV32_INSTR_H__
#include "riscv32_mcode.h"
#include "riscv32_def.h"
#define EMIT_PUSH_BACK (-1)
/* base integer instruction */
/**
* ADD
*
* add rd, rs1, rs2
*
* rd = rs1 + rs2
*/
static inline int
rv32_add(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, rv_reg_t rs2) {
rv32_instr_t instr = {
.instr_type = RV_ADD,
.rd = rd,
.rs1 = rs1,
.rs2 = rs2,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* ADD Immediate
*
* addi rd, rs1, imm
*
* rd = rs1 + imm (imm maybe cut)
*/
static inline int
rv32_addi(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_ADDI,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* AND
*
* and rd, rs1, rs2
*
* rd = rs1 & rs2
*/
static inline int
rv32_and(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, rv_reg_t rs2) {
rv32_instr_t instr = {
.instr_type = RV_AND,
.rd = rd,
.rs1 = rs1,
.rs2 = rs2,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* AND Immediate
*
* andi rd, rs1, imm
*
* rd = rs1 & imm (imm maybe cut)
*/
static inline int
rv32_andi(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_ANDI,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Add Upper Immediate to PC
*
* auipc rd, imm{12}
*
* rd = PC + imm{12}
*/
static inline int
rv32_auipc(mcode_rv32_t* prog, rv_reg_t rd, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_AUIPC,
.rd = rd,
.rs1 = REG_NULL,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Branch EQual
*
* beq rs1, rs2, imm
*
* if (rs1 == rs2) PC += imm{alian2}
*/
static inline int
rv32_beq(mcode_rv32_t* prog, rv_reg_t rs1, rv_reg_t rs2, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_BEQ,
.rd = REG_NULL,
.rs1 = rs1,
.rs2 = rs2,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Branch Greater than or Equal
*
* bge rs1, rs2, imm
*
* if (rs1 >= rs2) PC += imm{alian2}
*/
static inline int
rv32_bge(mcode_rv32_t* prog, rv_reg_t rs1, rv_reg_t rs2, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_BGE,
.rd = REG_NULL,
.rs1 = rs1,
.rs2 = rs2,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Branch Greater than or Equal Unsigned
*
* bgeu rs1, rs2, imm
*
* if (rs1 >= u rs2) PC += imm{alian2}
*/
static inline int
rv32_bgeu(mcode_rv32_t* prog, rv_reg_t rs1, rv_reg_t rs2, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_BGEU,
.rd = REG_NULL,
.rs1 = rs1,
.rs2 = rs2,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Branch Less Than
*
* blt rs1, rs2, imm
*
* if (rs1 < rs2) PC += imm{alian2}
*/
static inline int
rv32_blt(mcode_rv32_t* prog, rv_reg_t rs1, rv_reg_t rs2, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_BLT,
.rd = REG_NULL,
.rs1 = rs1,
.rs2 = rs2,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Branch Less Than Unsigned
*
* bltu rs1, rs2, imm
*
* if (rs1 < u rs2) PC += imm{alian2}
*/
static inline int
rv32_bltu(mcode_rv32_t* prog, rv_reg_t rs1, rv_reg_t rs2, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_BLTU,
.rd = REG_NULL,
.rs1 = rs1,
.rs2 = rs2,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Branch Not Equal
*
* bne rs1, rs2, imm
*
* if (rs1 != rs2) PC += imm{alian2}
*/
static inline int
rv32_bne(mcode_rv32_t* prog, rv_reg_t rs1, rv_reg_t rs2, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_BNE,
.rd = REG_NULL,
.rs1 = rs1,
.rs2 = rs2,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Environment BREAK
*
* ebreak
*
* Transfer control to debugger
*/
static inline int
rv32_ebreak(mcode_rv32_t* prog) {
rv32_instr_t instr = {
.instr_type = RV_EBREAK,
.rd = REG_NULL,
.rs1 = REG_NULL,
.rs2 = REG_NULL,
.imm = 1,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Environment CALL
*
* ecall
*
* Transfer control to operating system
*/
static inline int
rv32_ecall(mcode_rv32_t* prog) {
rv32_instr_t instr = {
.instr_type = RV_ECALL,
.rd = REG_NULL,
.rs1 = REG_NULL,
.rs2 = REG_NULL,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Jump And Link
*
* jal rd, imm
*
* rd = PC + 4; PC += imm{alian2}
*/
static inline int
rv32_jal(mcode_rv32_t* prog, rv_reg_t rd, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_JAL,
.rd = rd,
.rs1 = REG_NULL,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Jump And Link Register
*
* jalr rd, rs1, imm
*
* rd = PC + 4; PC = rs1 + imm
*/
static inline int
rv32_jalr(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_JALR,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Load Byte
*
* lb rd, rs1, imm
*
* rd = (8 bit) M[rs1+imm]
*/
static inline int
rv32_lb(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_LB,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Load Byte Unsigned
*
* lbu rd, rs1, imm
*
* rd = (8 bit) M[rs1+imm]
*/
static inline int
rv32_lbu(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_LBU,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* ld
* lh
* lhu
*/
/**
* Load Upper Immediate
*
* lui rd, imm
*
* rd = (32 bit) imm
*/
static inline int
rv32_lui(mcode_rv32_t* prog, rv_reg_t rd, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_LUI,
.rd = rd,
.rs1 = REG_NULL,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Load Word
*
* lw rd, rs1, imm
*
* rd = (32 bit) M[rs1+imm]
*/
static inline int
rv32_lw(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_LW,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Load Word Unsigned
*
* lwu rd, rs1, imm
*
* rd = (32 bit) u M[rs1+imm]
*/
// static inline int
// rv32_lwu(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
// return emit_rv32_instr(prog, RV_LWU, rd, rs1, REG_NULL, imm);
// }
/**
* OR
*
* or rd, rs1, rs2
*
* rd = rs1 | rs2
*/
static inline int
rv32_or(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, rv_reg_t rs2) {
rv32_instr_t instr = {
.instr_type = RV_OR,
.rd = rd,
.rs1 = rs1,
.rs2 = rs2,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* OR Immediate
*
* ori rd, rs1, imm
*
* rd = rs1 | imm (imm maybe cut)
*/
static inline int
rv32_ori(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_ORI,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Store Byte
*
* sb rs2, rs1, imm
*
* M[rs1+imm] = rs2
*/
static inline int
rv32_sb(mcode_rv32_t* prog, rv_reg_t rs2, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_SB,
.rd = REG_NULL,
.rs1 = rs1,
.rs2 = rs2,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* sd sh
*/
/**
* Shift Left
*
* sll rd, rs1, rs2
*
* rd = rs1 << rs2
*/
static inline int
rv32_sll(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, rv_reg_t rs2) {
rv32_instr_t instr = {
.instr_type = RV_SLL,
.rd = rd,
.rs1 = rs1,
.rs2 = rs2,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Shift Left Immediate
*
* slli rd, rs1, imm
*
* rd = rs1 << imm (maybe cut it)
*/
static inline int
rv32_slli(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_SLLI,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Set Less Than
*
* slt rd, rs1, rs2
*
* rd = (rs1 < rs2) ? 1 : 0
*/
static inline int
rv32_slt(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, rv_reg_t rs2) {
rv32_instr_t instr = {
.instr_type = RV_SLT,
.rd = rd,
.rs1 = rs1,
.rs2 = rs2,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Set Less Than Immediate
*
* slti rd, rs1, imm
*
* rd = (rs1 < imm) ? 1 : 0
*/
static inline int
rv32_slti(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_SLTI,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Set Less Than Immediate Unsigned
*
* sltiu rd, rs1, imm
*
* rd = (u rs1 < imm) ? 1 : 0
*/
static inline int
rv32_sltiu(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_SLTIU,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Set Less Than Unsigned
*
* sltu rd, rs1, rs2
*
* rd = (u rs1 < u rs2) ? 1 : 0
*/
static inline int
rv32_sltu(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, rv_reg_t rs2) {
rv32_instr_t instr = {
.instr_type = RV_SLTU,
.rd = rd,
.rs1 = rs1,
.rs2 = rs2,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Shift Right Arithmetic
*
* sra rd, rs1, rs2
*
* rd = rs1 >> rs2
*/
static inline int
rv32_sra(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, rv_reg_t rs2) {
rv32_instr_t instr = {
.instr_type = RV_SRA,
.rd = rd,
.rs1 = rs1,
.rs2 = rs2,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Shift Right Arithmetic Immediate
*
* srai rd, rs1, imm
*
* rd = rs1 >> imm (maybe cut it)
*/
static inline int
rv32_srai(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_SRAI,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Shift Right Logical
*
* srl rd, rs1, rs2
*
* rd = (u rs1) >> rs2
*/
static inline int
rv32_srl(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, rv_reg_t rs2) {
rv32_instr_t instr = {
.instr_type = RV_SRL,
.rd = rd,
.rs1 = rs1,
.rs2 = rs2,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Shift Right Logical Immediate
*
* srli rd, rs1, imm
*
* rd = (u rs1) >> imm (maybe cut it)
*/
static inline int
rv32_srli(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_SRLI,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* SUBtract
*
* sub rd, rs1, rs2
*
* rd = rs1 - rs2
*/
static inline int
rv32_sub(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, rv_reg_t rs2) {
rv32_instr_t instr = {
.instr_type = RV_SUB,
.rd = rd,
.rs1 = rs1,
.rs2 = rs2,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* Store Word
*
* sw rs2, rs1, imm
*
* M[rs1+imm] = rs2
*/
static inline int
rv32_sw(mcode_rv32_t* prog, rv_reg_t rs2, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_SW,
.rd = REG_NULL,
.rs1 = rs1,
.rs2 = rs2,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* XOR
*
* xor rd, rs1, rs2
*
* rd = rs1 ^ rs2
*/
static inline int
rv32_xor(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, rv_reg_t rs2) {
rv32_instr_t instr = {
.instr_type = RV_XOR,
.rd = rd,
.rs1 = rs1,
.rs2 = rs2,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/**
* XOR Immediate
*
* xori rd, rs1, imm
*
* rd = rs1 ^ imm (maybe cut it)
*/
static inline int
rv32_xori(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1, u32_t imm) {
rv32_instr_t instr = {
.instr_type = RV_XORI,
.rd = rd,
.rs1 = rs1,
.rs2 = REG_NULL,
.imm = imm,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, NULL);
}
/* pseudo instruction */
/**
* branch equal zero
*
* beqz rs1, imm
*
* if (rs1 == 0) PC += imm{alian2}
*/
static inline int
rv32_beqz(mcode_rv32_t* prog, rv_reg_t rs1, u32_t imm) {
return rv32_beq(prog, rs1, REG_X0, imm);
}
/**
* branch not equal zero
*
* bnez rs1, imm
*
* if (rs1 != 0) PC += imm{alian2}
*/
static inline int
rv32_bnez(mcode_rv32_t* prog, rv_reg_t rs1, u32_t imm) {
return rv32_bne(prog, rs1, REG_X0, imm);
}
/**
* fabs.s fabs.d
* fmv.s fmv.d
* fneg.s fneg.d
*/
/**
* jump
*
* j imm
*
* PC = imm{alian2}
*/
static inline int
rv32_j(mcode_rv32_t* prog, u32_t imm) {
// TODO
return rv32_jal(prog, REG_X0, imm);
}
/**
* jump register
*
* jr rs1
*
* PC = rs1
*/
static inline int
rv32_jr(mcode_rv32_t* prog, rv_reg_t rs1) {
// TODO
return rv32_jalr(prog, REG_X0, rs1, 0);
}
/**
* load address
*
* la rd
*
* rd = address
*/
static inline int
rv32_la(mcode_rv32_t* prog, rv_reg_t rd, u32_t imm) {
// TODO
return rv32_auipc(prog, rd, imm);
}
/**
* load immediate
*
* li rd, imm
*
* rd = imm
*/
static inline int
rv32_li(mcode_rv32_t* prog, rv_reg_t rd, i32_t imm) {
if (imm >= -2048 && imm <= 2047) {
return rv32_addi(prog, rd, REG_X0, imm);
} else {
int ret = rv32_lui(prog, rd, imm);
rv32_addi(prog, rd, rd, imm);
return ret;
}
}
/**
* move
*
* mv rd, rs1
*
* rd = rs1
*/
static inline int
rv32_mv(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1) {
return rv32_addi(prog, rd, rs1, 0);
}
/**
* negate
*
* neg rd, rs1
*
* rd = -rs1
*/
static inline int
rv32_neg(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1) {
return rv32_sub(prog, rd, REG_X0, rs1);
}
/**
* no opreation
*
* nop
*
* x0 = x0
*/
static inline int
rv32_nop(mcode_rv32_t* prog) {
return rv32_addi(prog, REG_X0, REG_X0, 0);
}
/**
* not
*
* not rd, rs1
*
* rd = ~rs1
*/
static inline int
rv32_not(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1) {
return rv32_xori(prog, rd, rs1, ~0);
}
/**
* return
*
* ret
*
* PC = ra
*/
static inline int
rv32_ret(mcode_rv32_t* prog) {
return rv32_jalr(prog, REG_X0, REG_RA, 0);
}
/**
* set equal zero
*
* seqz rd, rs1
*
* rd = (rs1 == 0) ? 1 : 0
*/
static inline int
rv32_seqz(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1) {
// TODO
return rv32_sltiu(prog, rd, rs1, 1);
}
/**
* set not equal zero
*
* snez rd, rs1
*
* rd = (rs1 != 0) ? 1 : 0
*/
static inline int
rv32_snez(mcode_rv32_t* prog, rv_reg_t rd, rv_reg_t rs1) {
// TODO
return rv32_sltu(prog, rd, rs1, REG_X0);
}
/* instruction of rotated (using label) */
static inline int
rv32_bne_l(mcode_rv32_t* prog, rv_reg_t rs1, rv_reg_t rs2, void* label) {
rv32_instr_t instr = {
.instr_type = RV_BNE,
.rd = REG_NULL,
.rs1 = rs1,
.rs2 = rs2,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, label);
}
static inline int
rv32_jal_l(mcode_rv32_t* prog, rv_reg_t rd, void* label) {
rv32_instr_t instr = {
.instr_type = RV_JAL,
.rd = rd,
.rs1 = REG_NULL,
.rs2 = REG_NULL,
.imm = 0,
};
return emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, label);
}
static inline int
rv32_call_l(mcode_rv32_t* prog, void* label) {
rv32_instr_t instr;
instr.instr_type = RV_JAL;
instr.rd = REG_NULL;
instr.rs1 = REG_NULL;
instr.rs2 = REG_NULL;
instr.imm = 0;
int ret = rv32_auipc(prog, REG_RA, REG_X0);
instr.instr_type = RV_JALR;
instr.rd = REG_RA;
instr.rs1 = REG_RA;
instr.rs2 = REG_NULL;
instr.imm = 4;
emit_rv32_instr(prog, &instr, EMIT_PUSH_BACK, label);
return ret;
}
#endif