diff --git a/riscv/gen_input/RV32C.core_desc b/riscv/gen_input/RV32C.core_desc index c19b9e3..fba428c 100644 --- a/riscv/gen_input/RV32C.core_desc +++ b/riscv/gen_input/RV32C.core_desc @@ -218,9 +218,9 @@ InsructionSet RV32FC extends RV32IC{ val res[32] <= MEM[offs]{32}; if(FLEN==32) F[rd_idx] <= res; - else { - val upper[FLEN] <= (-1<<31); - F[rd_idx] <= upper*2 | res; + else { // NaN boxing + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); } } C.FSW { @@ -239,9 +239,9 @@ InsructionSet RV32FC extends RV32IC{ val res[32] <= MEM[offs]{32}; if(FLEN==32) F[rd] <= res; - else { - val upper[FLEN] <= (-1<<31); - F[rd] <= upper*2 | res; + else { // NaN boxing + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); } } C.FSWSP { @@ -249,7 +249,7 @@ InsructionSet RV32FC extends RV32IC{ args_disass:"f%rs2$d, %uimm%(x2), "; val x2_idx[5] <= 2; val offs[XLEN] <= X[x2_idx]+uimm; - MEM[offs]{32}<=F[rs2]; + MEM[offs]{32}<=F[rs2]{32}; } } } @@ -268,15 +268,45 @@ InsructionSet RV32DC extends RV32IC{ instructions{ C.FLD { //(RV32/64) encoding: b001 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00; + args_disass:"f(8+%rd$d), %uimm%(x(8+%rs1$d))"; + val rs1_idx[5] <= rs1+8; + val rd_idx[5] <= rd+8; + val offs[XLEN] <= X[rs1_idx]+uimm; + val res[64] <= MEM[offs]{64}; + if(FLEN==64) + F[rd_idx] <= res; + else { // NaN boxing + val upper[FLEN] <= -1; + F[rd_idx] <= (upper<<64) | res; + } } C.FSD { //(RV32/64) encoding: b101 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00; + args_disass:"f(8+%rs2$d), %uimm%(x(8+%rs1$d))"; + val rs1_idx[5] <= rs1+8; + val rs2_idx[5] <= rs2+8; + val offs[XLEN] <= X[rs1_idx]+uimm; + MEM[offs]{64}<=F[rs2_idx]{64}; } C.FLDSP {//(RV32/64) encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10; + args_disass:"f%rd$d, %uimm%(x2)"; + val x2_idx[5] <= 2; + val offs[XLEN] <= X[x2_idx]+uimm; + val res[64] <= MEM[offs]{64}; + if(FLEN==64) + F[rd] <= res; + else { // NaN boxing + val upper[FLEN] <= -1; + F[rd] <= (upper<<64) | zext(res, FLEN); + } } C.FSDSP {//(RV32/64) encoding:b101 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10; + args_disass:"f%rs2$d, %uimm%(x2), "; + val x2_idx[5] <= 2; + val offs[XLEN] <= X[x2_idx]+uimm; + MEM[offs]{64}<=F[rs2]{64}; } } } diff --git a/riscv/gen_input/minres_rv.core_desc b/riscv/gen_input/minres_rv.core_desc index 5b5485f..a2b662b 100644 --- a/riscv/gen_input/minres_rv.core_desc +++ b/riscv/gen_input/minres_rv.core_desc @@ -27,7 +27,7 @@ Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32IC { } } -Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC, RV32D { +Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC, RV32D, RV32DC { constants { XLEN:=32; FLEN:=64; diff --git a/riscv/src/internal/vm_rv32gc.cpp b/riscv/src/internal/vm_rv32gc.cpp index 1bab6fe..854952c 100644 --- a/riscv/src/internal/vm_rv32gc.cpp +++ b/riscv/src/internal/vm_rv32gc.cpp @@ -194,7 +194,7 @@ private: compile_func op; }; - const std::array instr_descr = {{ + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, @@ -506,6 +506,14 @@ private: {32, 0b11010010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_w}, /* instruction FCVT.D.WU */ {32, 0b11010010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_wu}, + /* instruction C.FLD */ + {16, 0b0010000000000000, 0b1110000000000011, &this_class::__c_fld}, + /* instruction C.FSD */ + {16, 0b1010000000000000, 0b1110000000000011, &this_class::__c_fsd}, + /* instruction C.FLDSP */ + {16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_fldsp}, + /* instruction C.FSDSP */ + {16, 0b1010000000000010, 0b1110000000000011, &this_class::__c_fsdsp}, }}; /* instruction definitions */ @@ -641,43 +649,19 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* new_pc_val = this->builder.CreateAdd( + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 4)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* ret_val = this->builder.CreateAdd( this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); - Value* align_val = this->builder.CreateAnd( - new_pc_val, - this->gen_const(32U, 2)); - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - align_val, - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - this->gen_raise_trap(0, 0); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* PC_val = this->builder.CreateAnd( - new_pc_val, - this->builder.CreateNot(this->gen_const(32U, 1))); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - this->builder.SetInsertPoint(bb); + Value* PC_val = this->builder.CreateAnd( + ret_val, + this->builder.CreateNot(this->gen_const(32U, 1))); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC, 3); this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); @@ -6368,13 +6352,16 @@ private: Value* F_rd_idx_val = res_val; this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits::F0), false); } else { - uint64_t upper_val = (-1) << 31; - Value* F_rd_idx_val = this->builder.CreateOr( - this->builder.CreateMul( + uint64_t upper_val = (-1); + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateShl( this->gen_const(64U, upper_val), - this->gen_const(64U, 2)), - res_val); - this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits::F0), false); + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 125); @@ -6459,12 +6446,15 @@ private: Value* F_rd_val = res_val; this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); } else { - uint64_t upper_val = (-1) << 31; + uint64_t upper_val = (-1); Value* F_rd_val = this->builder.CreateOr( - this->builder.CreateMul( + this->builder.CreateShl( this->gen_const(64U, upper_val), - this->gen_const(64U, 2)), - res_val); + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -6501,7 +6491,10 @@ private: Value* offs_val = this->builder.CreateAdd( this->gen_reg_load(x2_idx_val + traits::X0, 0), this->gen_const(32U, fld_uimm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::F0, 0); + Value* MEM_offs_val = this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ); this->gen_write_mem( traits::MEM, offs_val, @@ -8096,6 +8089,191 @@ private: return std::make_tuple(vm::CONT, bb); } + /* instruction 155: C.FLD */ + std::tuple __c_fld(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.FLD"); + + this->gen_sync(iss::PRE_SYNC, 155); + + uint8_t fld_rd_val = 0 | (bit_sub<2,3>(instr)); + uint8_t fld_uimm_val = 0 | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.FLD f(8+%1$d), %2%(x(8+%3$d))"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rs1_idx_val = (fld_rs1_val + 8); + uint8_t rd_idx_val = (fld_rd_val + 8); + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 64/8); + if(64 == 64){ + Value* F_rd_idx_val = res_val; + this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits::F0), false); + } else { + uint64_t upper_val = (-1); + Value* F_rd_idx_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 64)), + res_val); + this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 155); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 156: C.FSD */ + std::tuple __c_fsd(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.FSD"); + + this->gen_sync(iss::PRE_SYNC, 156); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); + uint8_t fld_uimm_val = 0 | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.FSD f(8+%1$d), %2%(x(8+%3$d))"); + ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rs1_idx_val = (fld_rs1_val + 8); + uint8_t rs2_idx_val = (fld_rs2_val + 8); + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* MEM_offs_val = this->builder.CreateTrunc( + this->gen_reg_load(rs2_idx_val + traits::F0, 0), + this-> get_type(64) + ); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 156); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 157: C.FLDSP */ + std::tuple __c_fldsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.FLDSP"); + + this->gen_sync(iss::PRE_SYNC, 157); + + uint16_t fld_uimm_val = 0 | (bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5); + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.FLDSP f%1$d, %2%(x2)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t x2_idx_val = 2; + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(x2_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 64/8); + if(64 == 64){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint64_t upper_val = (-1); + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 64)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 157); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 158: C.FSDSP */ + std::tuple __c_fsdsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.FSDSP"); + + this->gen_sync(iss::PRE_SYNC, 158); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,5>(instr)); + uint16_t fld_uimm_val = 0 | (bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.FSDSP f%1$d, %2%(x2), "); + ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t x2_idx_val = 2; + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(x2_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* MEM_offs_val = this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(64) + ); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 158); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + /**************************************************************************** * end opcode definitions ****************************************************************************/