Merge branch 'develop' of https://github.com/Minres/DBT-RISE-RiscV.git
into develop Conflicts: dbt-core
This commit is contained in:
		| @@ -12,8 +12,8 @@ DBT-RISE-RiscV uses libGIS (https://github.com/vsergeev/libGIS) as well as ELFIO | |||||||
|  |  | ||||||
| **What's missing** | **What's missing** | ||||||
|  |  | ||||||
| * RV64I is only preliminary verified | * F & D standard extensions for 32bit to be implemented | ||||||
| * F & D standard extensions to be implemented | * MACF &D standard extensions for 64bit to be implemented and verified | ||||||
|  |  | ||||||
| **Planned features** | **Planned features** | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,6 +12,13 @@ InsructionSet RV32CI { | |||||||
| 				PC[XLEN](is_pc) | 				PC[XLEN](is_pc) | ||||||
| 	} | 	} | ||||||
| 	instructions{ | 	instructions{ | ||||||
|  |         JALR(no_cont){ // overwriting the implementation if rv32i, alignment does not need to be word | ||||||
|  |             encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111; | ||||||
|  |             args_disass: "x%rd$d, x%rs1$d, 0x%imm$x"; | ||||||
|  |             if(rd!=0) X[rd] <= PC+4; | ||||||
|  |             val ret[XLEN] <= X[rs1]+ imm; | ||||||
|  |             PC<=ret& ~0x1; | ||||||
|  |         } | ||||||
| 		C.ADDI4SPN { //(RES, imm=0) | 		C.ADDI4SPN { //(RES, imm=0) | ||||||
| 			encoding: b000 | imm[5:4] | imm[9:6] | imm[2:2] | imm[3:3] | rd[2:0] | b00; | 			encoding: b000 | imm[5:4] | imm[9:6] | imm[2:2] | imm[3:3] | rd[2:0] | b00; | ||||||
| 			args_disass: "x%rd$d, 0x%imm$05x"; | 			args_disass: "x%rd$d, 0x%imm$05x"; | ||||||
|   | |||||||
| @@ -38,9 +38,14 @@ InsructionSet RV32IBase { | |||||||
| 	    JALR(no_cont){ | 	    JALR(no_cont){ | ||||||
| 	    	encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111; | 	    	encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111; | ||||||
| 		    args_disass: "x%rd$d, x%rs1$d, 0x%imm$x"; | 		    args_disass: "x%rd$d, x%rs1$d, 0x%imm$x"; | ||||||
|  |             val new_pc[XLEN] <= X[rs1]+ imm; | ||||||
|  |             val align[XLEN] <= new_pc & 0x2; | ||||||
|  | 		    if(align != 0){ | ||||||
|  | 		        raise(0, 0) | ||||||
|  | 		    } else { | ||||||
|         		if(rd!=0) X[rd] <= PC+4; |         		if(rd!=0) X[rd] <= PC+4; | ||||||
|     		val ret[XLEN] <= X[rs1]+ imm; |         		PC<=new_pc & ~0x1; | ||||||
|     		PC<=ret& ~0x1; |     		} | ||||||
| 	    } | 	    } | ||||||
| 		BEQ(no_cont){ | 		BEQ(no_cont){ | ||||||
| 		    encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:1]s | imm[11:11]s | b1100011; | 		    encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:1]s | imm[11:11]s | b1100011; | ||||||
| @@ -154,18 +159,30 @@ InsructionSet RV32IBase { | |||||||
| 		SLLI { | 		SLLI { | ||||||
| 		    encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0010011; | 		    encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0010011; | ||||||
| 		    args_disass:"x%rd$d, x%rs1$d, %shamt%"; | 		    args_disass:"x%rd$d, x%rs1$d, %shamt%"; | ||||||
|  | 		    if(shamt > 31){ | ||||||
|  | 		        raise(0,0) | ||||||
|  | 		    } else { | ||||||
| 		        if(rd != 0) X[rd] <= shll(X[rs1], shamt); | 		        if(rd != 0) X[rd] <= shll(X[rs1], shamt); | ||||||
| 		    } | 		    } | ||||||
|  | 		} | ||||||
| 		SRLI { | 		SRLI { | ||||||
| 		    encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; | 		    encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; | ||||||
| 		    args_disass:"x%rd$d, x%rs1$d, %shamt%"; | 		    args_disass:"x%rd$d, x%rs1$d, %shamt%"; | ||||||
|  |             if(shamt > 31){ | ||||||
|  |                 raise(0,0) | ||||||
|  |             } else { | ||||||
| 		        if(rd != 0) X[rd] <= shrl(X[rs1], shamt); | 		        if(rd != 0) X[rd] <= shrl(X[rs1], shamt); | ||||||
| 		    } | 		    } | ||||||
|  | 		} | ||||||
| 		SRAI { | 		SRAI { | ||||||
| 		    encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; | 		    encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; | ||||||
| 		    args_disass:"x%rd$d, x%rs1$d, %shamt%"; | 		    args_disass:"x%rd$d, x%rs1$d, %shamt%"; | ||||||
|  | 		    if(shamt > 31){ | ||||||
|  |                 raise(0,0) | ||||||
|  |             } else { | ||||||
| 		        if(rd != 0) X[rd] <= shra(X[rs1], shamt); | 		        if(rd != 0) X[rd] <= shra(X[rs1], shamt); | ||||||
| 		    } | 		    } | ||||||
|  | 		} | ||||||
| 		ADD { | 		ADD { | ||||||
| 		    encoding: b0000000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011; | 		    encoding: b0000000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011; | ||||||
| 		    args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; | 		    args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| import "RV64IBase.core_desc" | import "RV64IBase.core_desc" | ||||||
|  | import "RV32A.core_desc" | ||||||
|  |  | ||||||
| InsructionSet RV64A extends RV64IBase{ | InsructionSet RV64A extends RV64IBase { | ||||||
| 	  | 	  | ||||||
| 	address_spaces {  | 	address_spaces {  | ||||||
| 		RES[8] | 		RES[8] | ||||||
|   | |||||||
| @@ -39,7 +39,7 @@ InsructionSet RV64IBase extends RV32IBase { | |||||||
| 			encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0011011; | 			encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0011011; | ||||||
| 			args_disass:"x%rd$d, x%rs1$d, %imm%"; | 			args_disass:"x%rd$d, x%rs1$d, %imm%"; | ||||||
| 			if(rd != 0){ | 			if(rd != 0){ | ||||||
| 				val res[32] <= X[rs1]{32} + imm{32}; | 				val res[32] <= X[rs1]{32} + imm; | ||||||
| 				X[rd] <= sext(res); | 				X[rd] <= sext(res); | ||||||
| 			}  | 			}  | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ import "RV64IBase.core_desc" | |||||||
| //import "RV64M.core_desc" | //import "RV64M.core_desc" | ||||||
| import "RV64A.core_desc" | import "RV64A.core_desc" | ||||||
|  |  | ||||||
| Core RV32IMAC provides RV32IBase,RV32M,RV32A, RV32CI  { | Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32CI { | ||||||
|     template:"vm_riscv.in.cpp"; |     template:"vm_riscv.in.cpp"; | ||||||
|     constants { |     constants { | ||||||
|         XLEN:=32; |         XLEN:=32; | ||||||
| @@ -25,7 +25,7 @@ Core RV32IMAC provides RV32IBase,RV32M,RV32A, RV32CI  { | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| Core RV64IA provides RV64IBase,RV64A { | Core RV64IA provides RV64IBase, RV64A, RV32A { | ||||||
|     template:"vm_riscv.in.cpp"; |     template:"vm_riscv.in.cpp"; | ||||||
|     constants { |     constants { | ||||||
|         XLEN:=64; |         XLEN:=64; | ||||||
| @@ -37,7 +37,7 @@ Core RV64IA provides RV64IBase,RV64A { | |||||||
|         fencevmal:=2; |         fencevmal:=2; | ||||||
|         fencevmau:=3; |         fencevmau:=3; | ||||||
|         //          XL    ZYXWVUTSRQPONMLKJIHGFEDCBA |         //          XL    ZYXWVUTSRQPONMLKJIHGFEDCBA | ||||||
|         MISA_VAL:=0b10000000000001000001000100000000; |         MISA_VAL:=0b10000000000001000000000100000001; | ||||||
|         PGSIZE := 4096; //1 << 12; |         PGSIZE := 4096; //1 << 12; | ||||||
|         PGMASK := 4095; //PGSIZE-1 |         PGMASK := 4095; //PGSIZE-1 | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -970,12 +970,13 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned lengt | |||||||
|                 if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { |                 if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { | ||||||
|                     switch (hostvar >> 48) { |                     switch (hostvar >> 48) { | ||||||
|                     case 0: |                     case 0: | ||||||
|                         if (hostvar != 0x1) |                         if (hostvar != 0x1){ | ||||||
|                             LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar |                             LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar | ||||||
|                                        << "), stopping simulation"; |                                        << "), stopping simulation"; | ||||||
|                         else |                         }else{ | ||||||
|                             LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar |                             LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar | ||||||
|                                       << "), stopping simulation"; |                                       << "), stopping simulation"; | ||||||
|  |                         } | ||||||
|                         throw(iss::simulation_stopped(hostvar)); |                         throw(iss::simulation_stopped(hostvar)); | ||||||
|                     case 0x0101: { |                     case 0x0101: { | ||||||
|                         char c = static_cast<char>(hostvar & 0xff); |                         char c = static_cast<char>(hostvar & 0xff); | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ | |||||||
| // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||||
| // POSSIBILITY OF SUCH DAMAGE. | // POSSIBILITY OF SUCH DAMAGE. | ||||||
| //  | //  | ||||||
| // Created on: Fri Nov 17 20:34:49 CET 2017 | // Created on: Sun Nov 19 14:05:47 CET 2017 | ||||||
| //             *      rv32imac.h Author: <CoreDSL Generator> | //             *      rv32imac.h Author: <CoreDSL Generator> | ||||||
| // | // | ||||||
| //////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ | |||||||
| // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||||
| // POSSIBILITY OF SUCH DAMAGE. | // POSSIBILITY OF SUCH DAMAGE. | ||||||
| //  | //  | ||||||
| // Created on: Fri Nov 17 20:34:49 CET 2017 | // Created on: Sun Nov 19 14:05:47 CET 2017 | ||||||
| //             *      rv64ia.h Author: <CoreDSL Generator> | //             *      rv64ia.h Author: <CoreDSL Generator> | ||||||
| // | // | ||||||
| //////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||||||
| @@ -48,7 +48,7 @@ struct rv64ia; | |||||||
| template<> | template<> | ||||||
| struct traits<rv64ia> { | struct traits<rv64ia> { | ||||||
|  |  | ||||||
|     enum constants {XLEN=64,XLEN2=128,XLEN_BIT_MASK=63,PCLEN=64,fence=0,fencei=1,fencevmal=2,fencevmau=3,MISA_VAL=2147750144,PGSIZE=4096,PGMASK=4095}; |     enum constants {XLEN=64,XLEN2=128,XLEN_BIT_MASK=63,PCLEN=64,fence=0,fencei=1,fencevmal=2,fencevmau=3,MISA_VAL=2147746049,PGSIZE=4096,PGMASK=4095}; | ||||||
|  |  | ||||||
|     enum reg_e { |     enum reg_e { | ||||||
|         X0, |         X0, | ||||||
|   | |||||||
| @@ -222,16 +222,24 @@ private: | |||||||
|      ****************************************************************************/ |      ****************************************************************************/ | ||||||
|     std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, |     std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, | ||||||
|                                                                           llvm::BasicBlock *bb) { |                                                                           llvm::BasicBlock *bb) { | ||||||
|         // this->gen_sync(iss::PRE_SYNC); |         bb->setName("illegal_instruction"); | ||||||
|         this->builder->CreateStore(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true), |  | ||||||
|                                    get_reg_ptr(traits<ARCH>::PC), true); |         this->gen_sync(iss::PRE_SYNC); | ||||||
|         this->builder->CreateStore( |         if(this->disass_enabled){ | ||||||
|             this->builder->CreateAdd(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true), |             /* generate console output when executing the command */ | ||||||
|                                      this->gen_const(64U, 1)), |             /* generate console output when executing the command */ | ||||||
|             get_reg_ptr(traits<ARCH>::ICOUNT), true); |             boost::format ins_fmter("DB x%1$d"); | ||||||
|         if (this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC); |             ins_fmter % (uint64_t)instr; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|         pc = pc + ((instr & 3) == 3 ? 4 : 2); |         pc = pc + ((instr & 3) == 3 ? 4 : 2); | ||||||
|         this->gen_raise_trap(0, 2);     // illegal instruction trap |  | ||||||
|  |         this->gen_raise_trap(0, 2); | ||||||
|         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|         this->gen_trap_check(this->leave_blk); |         this->gen_trap_check(this->leave_blk); | ||||||
|         return std::make_tuple(iss::vm::BRANCH, nullptr); |         return std::make_tuple(iss::vm::BRANCH, nullptr); | ||||||
|   | |||||||
| @@ -215,7 +215,7 @@ private: | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     /* start generated code */ |     /* start generated code */ | ||||||
|     const InstructionDesriptor instr_descr[75] = { |     const InstructionDesriptor instr_descr[86] = { | ||||||
|         /* entries are: valid value, valid mask, function ptr */ |         /* entries are: valid value, valid mask, function ptr */ | ||||||
|         /* instruction LWU */ |         /* instruction LWU */ | ||||||
|         {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, |         {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, | ||||||
| @@ -223,12 +223,6 @@ private: | |||||||
|         {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, &this_class::__ld}, |         {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, &this_class::__ld}, | ||||||
|         /* instruction SD */ |         /* instruction SD */ | ||||||
|         {32, 0b00000000000000000011000000100011, 0b00000000000000000111000001111111, &this_class::__sd}, |         {32, 0b00000000000000000011000000100011, 0b00000000000000000111000001111111, &this_class::__sd}, | ||||||
|         /* instruction SLLI */ |  | ||||||
|         {32, 0b00000000000000000001000000010011, 0b11111100000000000111000001111111, &this_class::__slli}, |  | ||||||
|         /* instruction SRLI */ |  | ||||||
|         {32, 0b00000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srli}, |  | ||||||
|         /* instruction SRAI */ |  | ||||||
|         {32, 0b01000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srai}, |  | ||||||
|         /* instruction ADDIW */ |         /* instruction ADDIW */ | ||||||
|         {32, 0b00000000000000000000000000011011, 0b00000000000000000111000001111111, &this_class::__addiw}, |         {32, 0b00000000000000000000000000011011, 0b00000000000000000111000001111111, &this_class::__addiw}, | ||||||
|         /* instruction SLLIW */ |         /* instruction SLLIW */ | ||||||
| @@ -295,6 +289,12 @@ private: | |||||||
|         {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, |         {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, | ||||||
|         /* instruction ANDI */ |         /* instruction ANDI */ | ||||||
|         {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, |         {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, | ||||||
|  |         /* instruction SLLI */ | ||||||
|  |         {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, | ||||||
|  |         /* instruction SRLI */ | ||||||
|  |         {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, | ||||||
|  |         /* instruction SRAI */ | ||||||
|  |         {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, | ||||||
|         /* instruction ADD */ |         /* instruction ADD */ | ||||||
|         {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, |         {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, | ||||||
|         /* instruction SUB */ |         /* instruction SUB */ | ||||||
| @@ -367,6 +367,28 @@ private: | |||||||
|         {32, 0b11000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_d}, |         {32, 0b11000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_d}, | ||||||
|         /* instruction AMOMAXU.D */ |         /* instruction AMOMAXU.D */ | ||||||
|         {32, 0b11100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_d}, |         {32, 0b11100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_d}, | ||||||
|  |         /* instruction LR.W */ | ||||||
|  |         {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lr_w}, | ||||||
|  |         /* instruction SC.W */ | ||||||
|  |         {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__sc_w}, | ||||||
|  |         /* instruction AMOSWAP.W */ | ||||||
|  |         {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_w}, | ||||||
|  |         /* instruction AMOADD.W */ | ||||||
|  |         {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_w}, | ||||||
|  |         /* instruction AMOXOR.W */ | ||||||
|  |         {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_w}, | ||||||
|  |         /* instruction AMOAND.W */ | ||||||
|  |         {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_w}, | ||||||
|  |         /* instruction AMOOR.W */ | ||||||
|  |         {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_w}, | ||||||
|  |         /* instruction AMOMIN.W */ | ||||||
|  |         {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_w}, | ||||||
|  |         /* instruction AMOMAX.W */ | ||||||
|  |         {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_w}, | ||||||
|  |         /* instruction AMOMINU.W */ | ||||||
|  |         {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_w}, | ||||||
|  |         /* instruction AMOMAXU.W */ | ||||||
|  |         {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_w}, | ||||||
|     }; |     }; | ||||||
|     // instruction LWU |     // instruction LWU | ||||||
|     std::tuple<vm::continuation_e, llvm::BasicBlock*> __lwu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __lwu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
| @@ -483,111 +505,6 @@ private: | |||||||
|         return std::make_tuple(vm::CONT, bb); |         return std::make_tuple(vm::CONT, bb); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     // instruction SLLI |  | ||||||
|     std::tuple<vm::continuation_e, llvm::BasicBlock*> __slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ |  | ||||||
|         bb->setName("SLLI"); |  | ||||||
|      |  | ||||||
|         this->gen_sync(iss::PRE_SYNC); |  | ||||||
|      |  | ||||||
|         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); |  | ||||||
|         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); |  | ||||||
|         uint8_t fld_shamt_val = 0 | (bit_sub<20,6>(instr)); |  | ||||||
|         if(this->disass_enabled){ |  | ||||||
|             /* generate console output when executing the command */ |  | ||||||
|             boost::format ins_fmter("SLLI x%1$d, x%2$d, %3%"); |  | ||||||
|             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; |  | ||||||
|             std::vector<llvm::Value*> 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); |  | ||||||
|         } |  | ||||||
|         pc=pc+4; |  | ||||||
|      |  | ||||||
|         if(fld_rd_val != 0){ |  | ||||||
|             Value* X_rd_val = this->builder->CreateShl( |  | ||||||
|                 this->gen_reg_load(fld_rs1_val, 0), |  | ||||||
|                 this->gen_const(64U, fld_shamt_val)); |  | ||||||
|             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); |  | ||||||
|         } |  | ||||||
|         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); |  | ||||||
|         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ |  | ||||||
|         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 SRLI |  | ||||||
|     std::tuple<vm::continuation_e, llvm::BasicBlock*> __srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ |  | ||||||
|         bb->setName("SRLI"); |  | ||||||
|      |  | ||||||
|         this->gen_sync(iss::PRE_SYNC); |  | ||||||
|      |  | ||||||
|         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); |  | ||||||
|         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); |  | ||||||
|         uint8_t fld_shamt_val = 0 | (bit_sub<20,6>(instr)); |  | ||||||
|         if(this->disass_enabled){ |  | ||||||
|             /* generate console output when executing the command */ |  | ||||||
|             boost::format ins_fmter("SRLI x%1$d, x%2$d, %3%"); |  | ||||||
|             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; |  | ||||||
|             std::vector<llvm::Value*> 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); |  | ||||||
|         } |  | ||||||
|         pc=pc+4; |  | ||||||
|      |  | ||||||
|         if(fld_rd_val != 0){ |  | ||||||
|             Value* X_rd_val = this->builder->CreateLShr( |  | ||||||
|                 this->gen_reg_load(fld_rs1_val, 0), |  | ||||||
|                 this->gen_const(64U, fld_shamt_val)); |  | ||||||
|             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); |  | ||||||
|         } |  | ||||||
|         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); |  | ||||||
|         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ |  | ||||||
|         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 SRAI |  | ||||||
|     std::tuple<vm::continuation_e, llvm::BasicBlock*> __srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ |  | ||||||
|         bb->setName("SRAI"); |  | ||||||
|      |  | ||||||
|         this->gen_sync(iss::PRE_SYNC); |  | ||||||
|      |  | ||||||
|         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); |  | ||||||
|         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); |  | ||||||
|         uint8_t fld_shamt_val = 0 | (bit_sub<20,6>(instr)); |  | ||||||
|         if(this->disass_enabled){ |  | ||||||
|             /* generate console output when executing the command */ |  | ||||||
|             boost::format ins_fmter("SRAI x%1$d, x%2$d, %3%"); |  | ||||||
|             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; |  | ||||||
|             std::vector<llvm::Value*> 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); |  | ||||||
|         } |  | ||||||
|         pc=pc+4; |  | ||||||
|      |  | ||||||
|         if(fld_rd_val != 0){ |  | ||||||
|             Value* X_rd_val = this->builder->CreateAShr( |  | ||||||
|                 this->gen_reg_load(fld_rs1_val, 0), |  | ||||||
|                 this->gen_const(64U, fld_shamt_val)); |  | ||||||
|             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); |  | ||||||
|         } |  | ||||||
|         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); |  | ||||||
|         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ |  | ||||||
|         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 ADDIW |     // instruction ADDIW | ||||||
|     std::tuple<vm::continuation_e, llvm::BasicBlock*> __addiw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __addiw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|         bb->setName("ADDIW"); |         bb->setName("ADDIW"); | ||||||
| @@ -1113,19 +1030,43 @@ private: | |||||||
|         } |         } | ||||||
|         pc=pc+4; |         pc=pc+4; | ||||||
|      |      | ||||||
|  |         Value* new_pc_val = this->builder->CreateAdd( | ||||||
|  |             this->gen_reg_load(fld_rs1_val, 0), | ||||||
|  |             this->gen_const(64U, fld_imm_val)); | ||||||
|  |         Value* align_val = this->builder->CreateAnd( | ||||||
|  |             new_pc_val, | ||||||
|  |             this->gen_const(64U, 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(64U, 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){ |             if(fld_rd_val != 0){ | ||||||
|                 Value* X_rd_val = this->builder->CreateAdd( |                 Value* X_rd_val = this->builder->CreateAdd( | ||||||
|                 this->gen_reg_load(traits<ARCH>::PC, 0), |                     this->gen_reg_load(traits<ARCH>::PC, 1), | ||||||
|                     this->gen_const(64U, 4)); |                     this->gen_const(64U, 4)); | ||||||
|                 this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); |                 this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|             } |             } | ||||||
|         Value* ret_val = this->builder->CreateAdd( |  | ||||||
|             this->gen_reg_load(fld_rs1_val, 0), |  | ||||||
|             this->gen_const(64U, fld_imm_val)); |  | ||||||
|             Value* PC_val = this->builder->CreateAnd( |             Value* PC_val = this->builder->CreateAnd( | ||||||
|             ret_val, |                 new_pc_val, | ||||||
|                 this->builder->CreateNot(this->gen_const(64U, 1))); |                 this->builder->CreateNot(this->gen_const(64U, 1))); | ||||||
|             this->builder->CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false); |             this->builder->CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false); | ||||||
|  |         } | ||||||
|  |         this->builder->CreateBr(bbnext); | ||||||
|  |         bb=bbnext; | ||||||
|  |         this->builder->SetInsertPoint(bb); | ||||||
|         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|         this->gen_trap_check(this->leave_blk); |         this->gen_trap_check(this->leave_blk); | ||||||
|         return std::make_tuple(iss::vm::BRANCH, nullptr); |         return std::make_tuple(iss::vm::BRANCH, nullptr); | ||||||
| @@ -1914,6 +1855,111 @@ private: | |||||||
|         return std::make_tuple(vm::CONT, bb); |         return std::make_tuple(vm::CONT, bb); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |     // instruction SLLI | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("SLLI"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("SLLI x%1$d, x%2$d, %3%"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = this->builder->CreateShl( | ||||||
|  |                 this->gen_reg_load(fld_rs1_val, 0), | ||||||
|  |                 this->gen_const(64U, fld_shamt_val)); | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 SRLI | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("SRLI"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("SRLI x%1$d, x%2$d, %3%"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = this->builder->CreateLShr( | ||||||
|  |                 this->gen_reg_load(fld_rs1_val, 0), | ||||||
|  |                 this->gen_const(64U, fld_shamt_val)); | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 SRAI | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("SRAI"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("SRAI x%1$d, x%2$d, %3%"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = this->builder->CreateAShr( | ||||||
|  |                 this->gen_reg_load(fld_rs1_val, 0), | ||||||
|  |                 this->gen_const(64U, fld_shamt_val)); | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 ADD |     // instruction ADD | ||||||
|     std::tuple<vm::continuation_e, llvm::BasicBlock*> __add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|         bb->setName("ADD"); |         bb->setName("ADD"); | ||||||
| @@ -3374,22 +3420,600 @@ private: | |||||||
|         return std::make_tuple(vm::CONT, bb); |         return std::make_tuple(vm::CONT, bb); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |     // instruction LR.W | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __lr_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("LR.W"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); | ||||||
|  |         uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("LR.W x%1$d, x%2$d"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); | ||||||
|  |             Value* X_rd_val = this->gen_ext( | ||||||
|  |                 this->gen_read_mem(traits<ARCH>::MEM, offs_val, 32/8), | ||||||
|  |                 64, | ||||||
|  |                 true); | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |             Value* RES_offs_val = this->gen_ext( | ||||||
|  |                 this->builder->CreateNeg(this->gen_const(8U, 1)), | ||||||
|  |                 32, | ||||||
|  |                 true); | ||||||
|  |             this->gen_write_mem( | ||||||
|  |                 traits<ARCH>::RES, | ||||||
|  |                 offs_val, | ||||||
|  |                 this->builder->CreateZExtOrTrunc(RES_offs_val,this->get_type(32))); | ||||||
|  |         } | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 SC.W | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __sc_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("SC.W"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); | ||||||
|  |         uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("SC.W x%1$d, x%2$d, x%3$d"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); | ||||||
|  |         Value* res1_val = this->gen_read_mem(traits<ARCH>::RES, offs_val, 32/8); | ||||||
|  |         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); | ||||||
|  |         // this->builder->SetInsertPoint(bb); | ||||||
|  |         this->gen_cond_branch(this->builder->CreateICmp( | ||||||
|  |             ICmpInst::ICMP_NE, | ||||||
|  |             res1_val, | ||||||
|  |             this->gen_const(32U, 0)), | ||||||
|  |             bb_then, | ||||||
|  |             bbnext); | ||||||
|  |         this->builder->SetInsertPoint(bb_then); | ||||||
|  |         { | ||||||
|  |             Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 1); | ||||||
|  |             this->gen_write_mem( | ||||||
|  |                 traits<ARCH>::MEM, | ||||||
|  |                 offs_val, | ||||||
|  |                 this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); | ||||||
|  |         } | ||||||
|  |         this->builder->CreateBr(bbnext); | ||||||
|  |         bb=bbnext; | ||||||
|  |         this->builder->SetInsertPoint(bb); | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = this->gen_choose( | ||||||
|  |                 this->builder->CreateICmp( | ||||||
|  |                     ICmpInst::ICMP_NE, | ||||||
|  |                     res1_val, | ||||||
|  |                     this->gen_const(64U, 0)), | ||||||
|  |                 this->gen_const(64U, 0), | ||||||
|  |                 this->gen_const(64U, 1), | ||||||
|  |                 64); | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 AMOSWAP.W | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __amoswap_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("AMOSWAP.W"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); | ||||||
|  |         uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("AMOSWAP.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = this->gen_ext( | ||||||
|  |                 this->gen_read_mem(traits<ARCH>::MEM, offs_val, 32/8), | ||||||
|  |                 64, | ||||||
|  |                 true); | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); | ||||||
|  |         this->gen_write_mem( | ||||||
|  |             traits<ARCH>::MEM, | ||||||
|  |             offs_val, | ||||||
|  |             this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 AMOADD.W | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __amoadd_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("AMOADD.W"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); | ||||||
|  |         uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("AMOADD.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); | ||||||
|  |         Value* res1_val = this->gen_ext( | ||||||
|  |             this->gen_read_mem(traits<ARCH>::MEM, offs_val, 32/8), | ||||||
|  |             64, | ||||||
|  |             true); | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = res1_val; | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         Value* res2_val = this->builder->CreateAdd( | ||||||
|  |             res1_val, | ||||||
|  |             this->gen_reg_load(fld_rs2_val, 0)); | ||||||
|  |         Value* MEM_offs_val = res2_val; | ||||||
|  |         this->gen_write_mem( | ||||||
|  |             traits<ARCH>::MEM, | ||||||
|  |             offs_val, | ||||||
|  |             this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 AMOXOR.W | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __amoxor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("AMOXOR.W"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); | ||||||
|  |         uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("AMOXOR.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); | ||||||
|  |         Value* res1_val = this->gen_ext( | ||||||
|  |             this->gen_read_mem(traits<ARCH>::MEM, offs_val, 32/8), | ||||||
|  |             64, | ||||||
|  |             true); | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = res1_val; | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         Value* res2_val = this->builder->CreateXor( | ||||||
|  |             res1_val, | ||||||
|  |             this->gen_reg_load(fld_rs2_val, 0)); | ||||||
|  |         Value* MEM_offs_val = res2_val; | ||||||
|  |         this->gen_write_mem( | ||||||
|  |             traits<ARCH>::MEM, | ||||||
|  |             offs_val, | ||||||
|  |             this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 AMOAND.W | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __amoand_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("AMOAND.W"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); | ||||||
|  |         uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("AMOAND.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); | ||||||
|  |         Value* res1_val = this->gen_ext( | ||||||
|  |             this->gen_read_mem(traits<ARCH>::MEM, offs_val, 32/8), | ||||||
|  |             64, | ||||||
|  |             true); | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = res1_val; | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         Value* res2_val = this->builder->CreateAnd( | ||||||
|  |             res1_val, | ||||||
|  |             this->gen_reg_load(fld_rs2_val, 0)); | ||||||
|  |         Value* MEM_offs_val = res2_val; | ||||||
|  |         this->gen_write_mem( | ||||||
|  |             traits<ARCH>::MEM, | ||||||
|  |             offs_val, | ||||||
|  |             this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 AMOOR.W | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __amoor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("AMOOR.W"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); | ||||||
|  |         uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("AMOOR.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); | ||||||
|  |         Value* res1_val = this->gen_ext( | ||||||
|  |             this->gen_read_mem(traits<ARCH>::MEM, offs_val, 32/8), | ||||||
|  |             64, | ||||||
|  |             true); | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = res1_val; | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         Value* res2_val = this->builder->CreateOr( | ||||||
|  |             res1_val, | ||||||
|  |             this->gen_reg_load(fld_rs2_val, 0)); | ||||||
|  |         Value* MEM_offs_val = res2_val; | ||||||
|  |         this->gen_write_mem( | ||||||
|  |             traits<ARCH>::MEM, | ||||||
|  |             offs_val, | ||||||
|  |             this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 AMOMIN.W | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __amomin_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("AMOMIN.W"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); | ||||||
|  |         uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("AMOMIN.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); | ||||||
|  |         Value* res1_val = this->gen_ext( | ||||||
|  |             this->gen_read_mem(traits<ARCH>::MEM, offs_val, 32/8), | ||||||
|  |             64, | ||||||
|  |             true); | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = res1_val; | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         Value* res2_val = this->gen_choose( | ||||||
|  |             this->builder->CreateICmp( | ||||||
|  |                 ICmpInst::ICMP_SGT, | ||||||
|  |                 this->gen_ext( | ||||||
|  |                     res1_val, | ||||||
|  |                     64, true), | ||||||
|  |                 this->gen_ext( | ||||||
|  |                     this->gen_reg_load(fld_rs2_val, 0), | ||||||
|  |                     64, true)), | ||||||
|  |             this->gen_reg_load(fld_rs2_val, 0), | ||||||
|  |             res1_val, | ||||||
|  |             64); | ||||||
|  |         Value* MEM_offs_val = res2_val; | ||||||
|  |         this->gen_write_mem( | ||||||
|  |             traits<ARCH>::MEM, | ||||||
|  |             offs_val, | ||||||
|  |             this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 AMOMAX.W | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __amomax_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("AMOMAX.W"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); | ||||||
|  |         uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("AMOMAX.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); | ||||||
|  |         Value* res1_val = this->gen_ext( | ||||||
|  |             this->gen_read_mem(traits<ARCH>::MEM, offs_val, 32/8), | ||||||
|  |             64, | ||||||
|  |             true); | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = res1_val; | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         Value* res2_val = this->gen_choose( | ||||||
|  |             this->builder->CreateICmp( | ||||||
|  |                 ICmpInst::ICMP_SLT, | ||||||
|  |                 this->gen_ext( | ||||||
|  |                     res1_val, | ||||||
|  |                     64, true), | ||||||
|  |                 this->gen_ext( | ||||||
|  |                     this->gen_reg_load(fld_rs2_val, 0), | ||||||
|  |                     64, true)), | ||||||
|  |             this->gen_reg_load(fld_rs2_val, 0), | ||||||
|  |             res1_val, | ||||||
|  |             64); | ||||||
|  |         Value* MEM_offs_val = res2_val; | ||||||
|  |         this->gen_write_mem( | ||||||
|  |             traits<ARCH>::MEM, | ||||||
|  |             offs_val, | ||||||
|  |             this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 AMOMINU.W | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __amominu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("AMOMINU.W"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); | ||||||
|  |         uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("AMOMINU.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); | ||||||
|  |         Value* res1_val = this->gen_ext( | ||||||
|  |             this->gen_read_mem(traits<ARCH>::MEM, offs_val, 32/8), | ||||||
|  |             64, | ||||||
|  |             false); | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = res1_val; | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         Value* res2_val = this->gen_choose( | ||||||
|  |             this->builder->CreateICmp( | ||||||
|  |                 ICmpInst::ICMP_UGT, | ||||||
|  |                 res1_val, | ||||||
|  |                 this->gen_reg_load(fld_rs2_val, 0)), | ||||||
|  |             this->gen_reg_load(fld_rs2_val, 0), | ||||||
|  |             res1_val, | ||||||
|  |             64); | ||||||
|  |         Value* MEM_offs_val = res2_val; | ||||||
|  |         this->gen_write_mem( | ||||||
|  |             traits<ARCH>::MEM, | ||||||
|  |             offs_val, | ||||||
|  |             this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 AMOMAXU.W | ||||||
|  |     std::tuple<vm::continuation_e, llvm::BasicBlock*> __amomaxu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ | ||||||
|  |         bb->setName("AMOMAXU.W"); | ||||||
|  |      | ||||||
|  |         this->gen_sync(iss::PRE_SYNC); | ||||||
|  |      | ||||||
|  |         uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); | ||||||
|  |         uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); | ||||||
|  |         uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); | ||||||
|  |         uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); | ||||||
|  |         uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); | ||||||
|  |         if(this->disass_enabled){ | ||||||
|  |             /* generate console output when executing the command */ | ||||||
|  |             boost::format ins_fmter("AMOMAXU.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); | ||||||
|  |             ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|  |         pc=pc+4; | ||||||
|  |      | ||||||
|  |         Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); | ||||||
|  |         Value* res1_val = this->gen_ext( | ||||||
|  |             this->gen_read_mem(traits<ARCH>::MEM, offs_val, 32/8), | ||||||
|  |             64, | ||||||
|  |             false); | ||||||
|  |         if(fld_rd_val != 0){ | ||||||
|  |             Value* X_rd_val = res1_val; | ||||||
|  |             this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); | ||||||
|  |         } | ||||||
|  |         Value* res2_val = this->gen_choose( | ||||||
|  |             this->builder->CreateICmp( | ||||||
|  |                 ICmpInst::ICMP_ULT, | ||||||
|  |                 this->gen_ext( | ||||||
|  |                     res1_val, | ||||||
|  |                     64, false), | ||||||
|  |                 this->gen_ext( | ||||||
|  |                     this->gen_reg_load(fld_rs2_val, 0), | ||||||
|  |                     64, false)), | ||||||
|  |             this->gen_reg_load(fld_rs2_val, 0), | ||||||
|  |             res1_val, | ||||||
|  |             64); | ||||||
|  |         Value* MEM_offs_val = res2_val; | ||||||
|  |         this->gen_write_mem( | ||||||
|  |             traits<ARCH>::MEM, | ||||||
|  |             offs_val, | ||||||
|  |             this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); | ||||||
|  |         this->gen_set_pc(pc, traits<ARCH>::NEXT_PC); | ||||||
|  |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|  |         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 generated code  */ | /* end generated code  */ | ||||||
|     /**************************************************************************** |     /**************************************************************************** | ||||||
|      * end opcode definitions |      * end opcode definitions | ||||||
|      ****************************************************************************/ |      ****************************************************************************/ | ||||||
|     std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, |     std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, | ||||||
|                                                                           llvm::BasicBlock *bb) { |                                                                           llvm::BasicBlock *bb) { | ||||||
|         // this->gen_sync(iss::PRE_SYNC); |         bb->setName("illegal_instruction"); | ||||||
|         this->builder->CreateStore(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true), |  | ||||||
|                                    get_reg_ptr(traits<ARCH>::PC), true); |         this->gen_sync(iss::PRE_SYNC); | ||||||
|         this->builder->CreateStore( |         if(this->disass_enabled){ | ||||||
|             this->builder->CreateAdd(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true), |             /* generate console output when executing the command */ | ||||||
|                                      this->gen_const(64U, 1)), |             /* generate console output when executing the command */ | ||||||
|             get_reg_ptr(traits<ARCH>::ICOUNT), true); |             boost::format ins_fmter("DB 0x%1$x"); | ||||||
|         if (this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC); |             ins_fmter % (uint64_t)instr; | ||||||
|  |             std::vector<llvm::Value*> 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); | ||||||
|  |         } | ||||||
|         pc = pc + ((instr & 3) == 3 ? 4 : 2); |         pc = pc + ((instr & 3) == 3 ? 4 : 2); | ||||||
|         this->gen_raise_trap(0, 2);     // illegal instruction trap |  | ||||||
|  |         this->gen_raise_trap(0, 2); | ||||||
|         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ |         this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ | ||||||
|         this->gen_trap_check(this->leave_blk); |         this->gen_trap_check(this->leave_blk); | ||||||
|         return std::make_tuple(iss::vm::BRANCH, nullptr); |         return std::make_tuple(iss::vm::BRANCH, nullptr); | ||||||
|   | |||||||
| @@ -54,23 +54,24 @@ int main(int argc, char *argv[]) { | |||||||
|     // clang-format off |     // clang-format off | ||||||
|     desc.add_options() |     desc.add_options() | ||||||
|         ("help,h", "Print help message") |         ("help,h", "Print help message") | ||||||
|         ("verbose,v", po::value<int>()->implicit_value(0), "Sets logging verbosity") |         ("loglevel,l", po::value<int>()->implicit_value(2), "Sets logging verbosity") | ||||||
|         ("log-file", po::value<std::string>(), "Sets default log file.") |         ("logfile,f", po::value<std::string>(), "Sets default log file.") | ||||||
|         ("disass,d", po::value<std::string>()->implicit_value(""), "Enables disassembly") |         ("disass,d", po::value<std::string>()->implicit_value(""), "Enables disassembly") | ||||||
|         ("elf,l", po::value<std::vector<std::string>>(), "ELF file(s) to load") |         ("elf", po::value<std::vector<std::string>>(), "ELF file(s) to load") | ||||||
|         ("gdb-port,g", po::value<unsigned>()->default_value(0), "enable gdb server and specify port to use") |         ("gdb-port,g", po::value<unsigned>()->default_value(0), "enable gdb server and specify port to use") | ||||||
|         ("input,i", po::value<std::string>(), "the elf file to load (instead of hex files)") |         ("input,i", po::value<std::string>(), "the elf file to load (instead of hex files)") | ||||||
|         ("dump-ir", "dump the intermediate representation") |         ("dump-ir", "dump the intermediate representation") | ||||||
|         ("cycles,c", po::value<int64_t>()->default_value(-1), "number of cycles to run") |         ("cycles,c", po::value<int64_t>()->default_value(-1), "number of cycles to run") | ||||||
|         ("systemc,s", "Run as SystemC simulation") |         ("systemc,s", "Run as SystemC simulation") | ||||||
|         ("time", po::value<int>(), "SystemC siimulation time in ms") |         ("time", po::value<int>(), "SystemC simulation time in ms") | ||||||
|         ("reset,r", po::value<std::string>(), "reset address") |         ("reset,r", po::value<std::string>(), "reset address") | ||||||
|         ("trace", po::value<uint8_t>(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX compressed text, 6=TX in SQLite") |         ("trace", po::value<uint8_t>(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX compressed text, 6=TX in SQLite") | ||||||
|         ("mem,m", po::value<std::string>(), "the memory input file") |         ("mem,m", po::value<std::string>(), "the memory input file") | ||||||
|         ("rv64", "run RV64"); |         ("isa", po::value<std::string>()->default_value("rv32imac"), "isa to use for simulation"); | ||||||
|     // clang-format on |     // clang-format on | ||||||
|  |     auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); | ||||||
|     try { |     try { | ||||||
|         po::store(po::parse_command_line(argc, argv, desc), clim); // can throw |         po::store(parsed, clim); // can throw | ||||||
|         // --help option |         // --help option | ||||||
|         if (clim.count("help")) { |         if (clim.count("help")) { | ||||||
|             std::cout << "DBT-RISE-RiscV simulator for RISC-V" << std::endl << desc << std::endl; |             std::cout << "DBT-RISE-RiscV simulator for RISC-V" << std::endl << desc << std::endl; | ||||||
| @@ -83,14 +84,16 @@ int main(int argc, char *argv[]) { | |||||||
|         std::cerr << desc << std::endl; |         std::cerr << desc << std::endl; | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|     if (clim.count("verbose")) { |     std::vector<std::string> args = collect_unrecognized(parsed.options, po::include_positional); | ||||||
|         auto l = logging::as_log_level(clim["verbose"].as<int>()); |  | ||||||
|  |     if (clim.count("loglevel")) { | ||||||
|  |         auto l = logging::as_log_level(clim["loglevel"].as<int>()); | ||||||
|         LOGGER(DEFAULT)::reporting_level() = l; |         LOGGER(DEFAULT)::reporting_level() = l; | ||||||
|         LOGGER(connection)::reporting_level() = l; |         LOGGER(connection)::reporting_level() = l; | ||||||
|     } |     } | ||||||
|     if (clim.count("log-file")) { |     if (clim.count("logfile")) { | ||||||
|         // configure the connection logger |         // configure the connection logger | ||||||
|         auto f = fopen(clim["log-file"].as<std::string>().c_str(), "w"); |         auto f = fopen(clim["logfile"].as<std::string>().c_str(), "w"); | ||||||
|         LOG_OUTPUT(DEFAULT)::stream() = f; |         LOG_OUTPUT(DEFAULT)::stream() = f; | ||||||
|         LOG_OUTPUT(connection)::stream() = f; |         LOG_OUTPUT(connection)::stream() = f; | ||||||
|     } |     } | ||||||
| @@ -101,19 +104,21 @@ int main(int argc, char *argv[]) { | |||||||
|         bool dump = clim.count("dump-ir"); |         bool dump = clim.count("dump-ir"); | ||||||
|         // instantiate the simulator |         // instantiate the simulator | ||||||
|         std::unique_ptr<iss::vm_if> vm{nullptr}; |         std::unique_ptr<iss::vm_if> vm{nullptr}; | ||||||
|         if (clim.count("rv64") == 1) { |         if (clim["isa"].as<std::string>().substr(0, 4)=="rv64") { | ||||||
|             auto cpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv64ia>(); |             iss::arch::rv64ia* cpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv64ia>(); | ||||||
|             vm = iss::create<iss::arch::rv64ia>(cpu, clim["gdb-port"].as<unsigned>(), dump); |             vm = iss::create(cpu, clim["gdb-port"].as<unsigned>(), dump); | ||||||
|  |         } else if (clim["isa"].as<std::string>().substr(0, 4)=="rv32") { | ||||||
|  |             iss::arch::rv32imac* cpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv32imac>(); | ||||||
|  |             vm = iss::create(cpu, clim["gdb-port"].as<unsigned>(), dump); | ||||||
|         } else { |         } else { | ||||||
|             auto cpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv32imac>(); |             LOG(ERROR) << "Illegal argument value for '--isa': " << clim["isa"].as<std::string>() << std::endl; | ||||||
|             vm = iss::create<iss::arch::rv32imac>(cpu, clim["gdb-port"].as<unsigned>(), dump); |             return 127; | ||||||
|         } |         } | ||||||
|         if (clim.count("elf")) { |         if (clim.count("elf")) | ||||||
|             for (std::string input : clim["elf"].as<std::vector<std::string>>()) vm->get_arch()->load_file(input); |             for (std::string input : clim["elf"].as<std::vector<std::string>>()) vm->get_arch()->load_file(input); | ||||||
|         } else if (clim.count("mem")) { |         if (clim.count("mem")) | ||||||
|             vm->get_arch()->load_file(clim["mem"].as<std::string>(), iss::arch::traits<iss::arch::rv32imac>::MEM); |             vm->get_arch()->load_file(clim["mem"].as<std::string>(), iss::arch::traits<iss::arch::rv32imac>::MEM); | ||||||
|         } |         for (std::string input : args) vm->get_arch()->load_file(input);// treat remaining arguments as elf files | ||||||
|  |  | ||||||
|         if (clim.count("disass")) { |         if (clim.count("disass")) { | ||||||
|             vm->setDisassEnabled(true); |             vm->setDisassEnabled(true); | ||||||
|             LOGGER(disass)::reporting_level() = logging::INFO; |             LOGGER(disass)::reporting_level() = logging::INFO; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user