152 lines
7.1 KiB
C
152 lines
7.1 KiB
C
#include "riscv32_mcode.h"
|
|
|
|
static const rv32_instr_t rv32_instrs[] = {
|
|
[RV_LUI] = {RV32_I_EXT, RV_U_TYPE, RV_LUI, "lui", 0x37},
|
|
[RV_AUIPC] = {RV32_I_EXT, RV_U_TYPE, RV_AUIPC, "auipc", 0x17},
|
|
|
|
[RV_JAL] = {RV32_I_EXT, RV_J_TYPE, RV_JAL, "jal", 0x6F},
|
|
|
|
[RV_JALR] = {RV32_I_EXT, RV_I_TYPE, RV_JALR, "jalr", 0x67},
|
|
|
|
[RV_LB] = {RV32_I_EXT, RV_I_TYPE, RV_LB, "lb", 0x03 | RV_F3(0x0)},
|
|
[RV_LH] = {RV32_I_EXT, RV_I_TYPE, RV_LH, "lh", 0x03 | RV_F3(0x1)},
|
|
[RV_LW] = {RV32_I_EXT, RV_I_TYPE, RV_LW, "lw", 0x03 | RV_F3(0x2)},
|
|
[RV_LBU] = {RV32_I_EXT, RV_I_TYPE, RV_LBU, "lbu", 0x03 | RV_F3(0x4)},
|
|
[RV_LHU] = {RV32_I_EXT, RV_I_TYPE, RV_LHU, "lhu", 0x03 | RV_F3(0x5)},
|
|
|
|
[RV_ADDI] = {RV32_I_EXT, RV_I_TYPE, RV_ADDI, "addi", 0x13 | RV_F3(0x0)},
|
|
[RV_SLTI] = {RV32_I_EXT, RV_I_TYPE, RV_SLTI, "slti", 0x13 | RV_F3(0x2)},
|
|
[RV_SLTIU] = {RV32_I_EXT, RV_I_TYPE, RV_SLTIU, "sltiu", 0x13 | RV_F3(0x3)},
|
|
[RV_XORI] = {RV32_I_EXT, RV_I_TYPE, RV_XORI, "xori", 0x13 | RV_F3(0x4)},
|
|
[RV_ORI] = {RV32_I_EXT, RV_I_TYPE, RV_ORI, "ori", 0x13 | RV_F3(0x6)},
|
|
[RV_ANDI] = {RV32_I_EXT, RV_I_TYPE, RV_ANDI, "andi", 0x13 | RV_F3(0x7)},
|
|
|
|
[RV_SLLI] = {RV32_I_EXT, RV_I_TYPE, RV_SLLI, "slli", 0x13 | RV_F3(0x0)},
|
|
[RV_SRLI] = {RV32_I_EXT, RV_I_TYPE, RV_SRLI, "srli", 0x13 | RV_F3(0x5)},
|
|
[RV_SRAI] = {RV32_I_EXT, RV_I_TYPE, RV_SRAI, "srai", 0x13 | RV_F3(0x5)},
|
|
|
|
[RV_BEQ] = {RV32_I_EXT, RV_B_TYPE, RV_BEQ, "beq", 0x63 | RV_F3(0x0)},
|
|
[RV_BNE] = {RV32_I_EXT, RV_B_TYPE, RV_BNE, "bne", 0x63 | RV_F3(0x1)},
|
|
[RV_BLT] = {RV32_I_EXT, RV_B_TYPE, RV_BLT, "blt", 0x63 | RV_F3(0x4)},
|
|
[RV_BGE] = {RV32_I_EXT, RV_B_TYPE, RV_BGE, "bge", 0x63 | RV_F3(0x5)},
|
|
[RV_BLTU] = {RV32_I_EXT, RV_B_TYPE, RV_BLTU, "bltu", 0x63 | RV_F3(0x6)},
|
|
[RV_BGEU] = {RV32_I_EXT, RV_B_TYPE, RV_BGEU, "bgeu", 0x63 | RV_F3(0x7)},
|
|
|
|
[RV_SB] = {RV32_I_EXT, RV_S_TYPE, RV_SB, "sb", 0x23 | RV_F3(0x0)},
|
|
[RV_SH] = {RV32_I_EXT, RV_S_TYPE, RV_SH, "sh", 0x23 | RV_F3(0x1)},
|
|
[RV_SW] = {RV32_I_EXT, RV_S_TYPE, RV_SW, "sw", 0x23 | RV_F3(0x2)},
|
|
|
|
[RV_ADD] = {RV32_I_EXT, RV_R_TYPE, RV_ADD, "add", 0x33 | RV_F3(0x0) | RV_F7(0x00)},
|
|
[RV_SUB] = {RV32_I_EXT, RV_R_TYPE, RV_SUB, "sub", 0x33 | RV_F3(0x0) | RV_F7(0x20)},
|
|
[RV_SLL] = {RV32_I_EXT, RV_R_TYPE, RV_SLL, "sll", 0x33 | RV_F3(0x1) | RV_F7(0x00)},
|
|
[RV_SLT] = {RV32_I_EXT, RV_R_TYPE, RV_SLT, "slt", 0x33 | RV_F3(0x2) | RV_F7(0x00)},
|
|
[RV_SLTU] = {RV32_I_EXT, RV_R_TYPE, RV_SLTU, "sltu", 0x33 | RV_F3(0x3) | RV_F7(0x00)},
|
|
[RV_XOR] = {RV32_I_EXT, RV_R_TYPE, RV_XOR, "xor", 0x33 | RV_F3(0x4) | RV_F7(0x00)},
|
|
[RV_SRL] = {RV32_I_EXT, RV_R_TYPE, RV_SRL, "srl", 0x33 | RV_F3(0x5) | RV_F7(0x00)},
|
|
[RV_SRA] = {RV32_I_EXT, RV_R_TYPE, RV_SRA, "sra", 0x33 | RV_F3(0x5) | RV_F7(0x20)},
|
|
[RV_OR] = {RV32_I_EXT, RV_R_TYPE, RV_OR, "or", 0x33 | RV_F3(0x6) | RV_F7(0x00)},
|
|
[RV_AND] = {RV32_I_EXT, RV_R_TYPE, RV_AND, "and", 0x33 | RV_F3(0x7) | RV_F7(0x00)},
|
|
|
|
// {RV32_I_EXT, RV_I_TYPE, RV_FENCE, "fence", 0x0F},
|
|
[RV_ECALL] = {RV32_I_EXT, RV_I_TYPE, RV_ECALL, "ecall", 0x73},
|
|
[RV_EBREAK] = {RV32_I_EXT, RV_I_TYPE, RV_EBREAK,"ebreak",0x100073},
|
|
|
|
[RV_MUL] = {RV32_M_EXT, RV_R_TYPE, RV_MUL, "mul", 0x33 | RV_F3(0x0) | RV_F7(0x01)},
|
|
[RV_DIV] = {RV32_M_EXT, RV_R_TYPE, RV_DIV, "div", 0x33 | RV_F3(0x0) | RV_F7(0x05)},
|
|
[RV_REM] = {RV32_M_EXT, RV_R_TYPE, RV_REM, "rem", 0x33 | RV_F3(0x0) | RV_F7(0x07)},
|
|
};
|
|
|
|
static inline int valid_reg(rv_reg_t reg) {
|
|
// return reg >= REG_X0 && reg <= REG_X31;
|
|
return !(reg & ~0x1F);
|
|
}
|
|
|
|
void init_rv32_mcode(mcode_rv32_t* mcode, int target_size) {
|
|
vector_init(mcode->code);
|
|
vector_init(mcode->rinstrs);
|
|
mcode->target_size = target_size;
|
|
}
|
|
|
|
int decode_rv32_instr(u32_t instr, rv32_instr_t *out) {
|
|
return 0;
|
|
}
|
|
|
|
int emit_rv32_instr(mcode_rv32_t* mcode, rv32_instr_t *instr, u32_t idx, void *target) {
|
|
// TODO check out input data
|
|
instr->extention = rv32_instrs[instr->instr_type].extention;
|
|
instr->format = rv32_instrs[instr->instr_type].format;
|
|
instr->instr_name = rv32_instrs[instr->instr_type].instr_name;
|
|
instr->instr = rv32_instrs[instr->instr_type].instr;
|
|
|
|
switch (instr->format) {
|
|
case RV_R_TYPE:
|
|
instr->instr |= (instr->rd << 7) | (instr->rs1 << 15) | (instr->rs2 << 20);
|
|
break;
|
|
case RV_I_TYPE:
|
|
instr->instr |= (instr->rd << 7) | (instr->rs1 << 15) | (instr->imm << 20);
|
|
break;
|
|
case RV_S_TYPE:
|
|
instr->instr |= (instr->rs1 << 15) | (instr->rs2 << 20) |
|
|
((instr->imm & 0x1F) << 7) | ((instr->imm & 0xFE0) << 20);
|
|
break;
|
|
case RV_B_TYPE:
|
|
instr->instr |= (instr->rs1 << 15) | (instr->rs2 << 20) |
|
|
(((instr->imm) >> 12) & 0x1) << 31 | /* imm[12:12] -> instr[31:31] */ \
|
|
(((instr->imm) >> 5) & 0x3F) << 25 | /* imm[10:5] -> instr[30:25] */ \
|
|
(((instr->imm) >> 1) & 0xF) << 8 | /* imm[4:1] -> instr[11:8] */ \
|
|
(((instr->imm) >> 11) & 0x1) << 7; /* imm[11:11] -> instr[7:7] */
|
|
break;
|
|
case RV_U_TYPE:
|
|
instr->instr |= (instr->rd << 7) | (instr->imm & 0xFFFFF000);
|
|
break;
|
|
case RV_J_TYPE:
|
|
instr->instr |= (instr->rd << 7) |
|
|
(((instr->imm) >> 20) & 0x1) << 31 | /* imm[20:20] -> instr[31:31] */ \
|
|
(((instr->imm) >> 1) & 0x3FF)<< 21 | /* imm[10:1] -> instr[30:21] */ \
|
|
(((instr->imm) >> 11) & 0x1) << 20 | /* imm[11:11] -> instr[20:20] */ \
|
|
(((instr->imm) >> 12) & 0xFF) << 12; /* imm[19:12] -> instr[19:12] */
|
|
break;
|
|
default:
|
|
Panic("Invalid instruction format");
|
|
}
|
|
|
|
if (target != NULL) {
|
|
Assert(idx == -1);
|
|
void* ptr;
|
|
if (mcode->target_size >= 0) {
|
|
ptr = salloc_alloc(mcode->target_size);
|
|
if (ptr == NULL) {
|
|
LOG_FATAL("malloc failure");
|
|
}
|
|
rt_memcpy(ptr, target, mcode->target_size);
|
|
} else {
|
|
ptr = target;
|
|
}
|
|
rotated_instr_t rinstr = {
|
|
.instr = *instr,
|
|
.pos = mcode->code.size,
|
|
.target = ptr,
|
|
};
|
|
vector_push(mcode->rinstrs, rinstr);
|
|
// GOTO idx == -1
|
|
}
|
|
|
|
if (idx == -1) {
|
|
// 32bit instr
|
|
int idx = mcode->code.size;
|
|
vector_push(mcode->code, 0);
|
|
vector_push(mcode->code, 0);
|
|
vector_push(mcode->code, 0);
|
|
vector_push(mcode->code, 0);
|
|
u32_t* pinstr = (u32_t*)(&vector_at(mcode->code, idx));
|
|
*pinstr = instr->instr;
|
|
return idx;
|
|
} else if (idx >= 0 && idx < mcode->code.size) {
|
|
*(u32_t*)&vector_at(mcode->code, idx) = instr->instr;
|
|
return mcode->code.size - 1;
|
|
} else {
|
|
Panic("Invalid instruction index");
|
|
}
|
|
return -1;
|
|
}
|