#include "riscv32.h" #include "riscv32_def.h" #include 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)}, }; void init_rv32_prog(rv32_prog_t* prog, strpool_t* strpool) { if (strpool == NULL) { prog->strpool = salloc_alloc(sizeof(strpool_t)); init_strpool(prog->strpool); } else { prog->strpool = strpool; } prog->data_base_address = 0; vector_init(prog->data); prog->text_base_address = 0; vector_init(prog->text); vector_init(prog->rinstrs); init_symtab_asm(&prog->symtab); } static inline int valid_reg(rv_reg_t reg) { // return reg >= REG_X0 && reg <= REG_X31; return !(reg & ~0x1F); } // static int valid_instr // (rv_instr_type_t type, u32_t imm, rv_reg_t rs1, rv_reg_t rs2, rv_reg_t rd) { // Assert(type >= 0 && type < RV_INSTR_TYPE_COUNT); // rv_fmt_t fmt = rv32_instrs[type].format; // switch (fmt) { // case RV_R_TYPE: // if (valid_reg(rd) && valid_reg(rs1) && valid_reg(rs2)) { // return 1; // } // break; // case RV_I_TYPE: // if (valid_reg(rd) && valid_reg(rs1) && rs2 == 0 && (imm & ~0xFFF) == 0) { // return 1; // } // break; // case RV_S_TYPE: // if (rd == 0 && valid_reg(rs1) && valid_reg(rs2) && (imm & ~0xFFF) == 0) { // return 1; // } // break; // case RV_B_TYPE: // if (rd == 0 && valid_reg(rs1) && valid_reg(rs2) && (imm & ~(0xFFF << 1)) == 0) { // return 1; // } // break; // case RV_U_TYPE: // if (valid_reg(rd) && rs1 == 0 && rs2 == 0 && (imm & ~(0xFFFFF << 12)) == 0) { // return 1; // } // break; // case RV_J_TYPE: // if (valid_reg(rd) && rs1 == 0 && rs2 == 0 && (imm & ~(0xFFFFF)) == 0) { // return 1; // } // break; // } // return 0; // } int emit_rv32_instr(rv32_prog_t* prog, rv32_instr_t *instr, u32_t idx, symasm_entry_t *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); rotated_instr_t rinstr = { .instr = *instr, .address = prog->text.size, .target = *target, }; vector_push(prog->rinstrs, rinstr); // GOTO idx == -1 } if (idx == -1) { vector_push(prog->text, instr->instr); return idx; } else if (idx >= 0 && idx < prog->text.size) { vector_at(prog->text, idx) = instr->instr; return prog->text.size - 1; } else { Panic("Invalid instruction index"); } return -1; } // int gen_rv32_instr(rv32_prog_t* prog) { // vector_header(rinstrs_g, rotated_instr_t); // vector_init(rinstrs_g); // for (int i = 0; i < prog->rinstrs.size; i++) { // rotated_instr_t* rinstr = &prog->rinstrs.data[i]; // // FIXME address typedef needed // u32_t* ptr = symtab_get(&prog->symtab, &rinstr->target); // if (ptr == NULL) { // vector_push(rinstrs_g, *rinstr); // continue; // } // u32_t target_address = *ptr; // rv32_instr_t *back_instr = &rinstr->instr; // // FIXME 重定向类别 // back_instr->imm = target_address; // emit_rv32_instr(prog, back_instr, target_address, NULL); // } // vector_free(prog->rinstrs); // prog->rinstrs.cap = rinstrs_g.cap; // }