Added RV32D extension
This commit is contained in:
		
							
								
								
									
										298
									
								
								riscv/gen_input/RV32D.core_desc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								riscv/gen_input/RV32D.core_desc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,298 @@ | ||||
| import "RV32IBase.core_desc" | ||||
|  | ||||
| InsructionSet RV32D extends RV32IBase{ | ||||
| 	constants { | ||||
| 		FLEN, FFLAG_MASK | ||||
| 	}  | ||||
| 	registers { | ||||
| 		[31:0]    F[FLEN],  FCSR[32] | ||||
|     }	 | ||||
| 	instructions{ | ||||
| 		FLD { | ||||
| 			encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000111; | ||||
| 			args_disass:"f%rd$d, %imm%(x%rs1$d)"; | ||||
| 			val offs[XLEN] <= X[rs1]+imm; | ||||
| 			val res[64] <= MEM[offs]{64}; | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 		} | ||||
| 		FSD { | ||||
| 			encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100111; | ||||
| 			args_disass:"f%rs2$d, %imm%(x%rs1$d)"; | ||||
| 			val offs[XLEN] <= X[rs1]+imm; | ||||
| 			MEM[offs]{64}<=F[rs2]{64}; | ||||
| 		} | ||||
| 		FMADD.D { | ||||
| 			encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; | ||||
| 			//F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f; | ||||
| 			val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(0, 64), choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FMSUB.D { | ||||
| 			encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; | ||||
| 			//F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f; | ||||
| 			val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};	 | ||||
| 		} | ||||
| 		FNMADD.D { | ||||
| 			encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; | ||||
| 			//F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f; | ||||
| 			val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FNMSUB.D { | ||||
| 			encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; | ||||
| 			//F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f; | ||||
| 			val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FADD.D { | ||||
| 			encoding: b0000001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			// F[rd]f <= F[rs1]f + F[rs2]f; | ||||
| 			val res[64] <= fdispatch_fadd_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FSUB.D { | ||||
| 			encoding: b0000101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			// F[rd]f <= F[rs1]f - F[rs2]f; | ||||
| 			val res[64] <= fdispatch_fsub_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FMUL.D { | ||||
| 			encoding: b0001001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			// F[rd]f <= F[rs1]f * F[rs2]f; | ||||
| 			val res[64] <= fdispatch_fmul_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FDIV.D { | ||||
| 			encoding: b0001101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			// F[rd]f <= F[rs1]f / F[rs2]f; | ||||
| 			val res[64] <= fdispatch_fdiv_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FSQRT.D { | ||||
| 			encoding: b0101101 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d"; | ||||
| 			//F[rd]f<=sqrt(F[rs1]f); | ||||
| 			val res[64] <= fdispatch_fsqrt_d(F[rs1]{64}, choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FSGNJ.D { | ||||
| 			encoding: b0010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; | ||||
| 			args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			val res[64] <= (F[rs1]{64} & 0x7fffffff) | (F[rs2]{64} & 0x80000000); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 		} | ||||
| 		FSGNJN.D { | ||||
| 			encoding: b0010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; | ||||
| 			args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			val res[64] <= (F[rs1]{64} & 0x7fffffff) | (~F[rs2]{64} & 0x80000000); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 		} | ||||
| 		FSGNJX.D { | ||||
| 			encoding: b0010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; | ||||
| 			args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & 0x80000000); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 		} | ||||
| 		FMIN.D  { | ||||
| 			encoding: b0010101 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; | ||||
| 			args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			//F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f); | ||||
| 			val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32)); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FMAX.D { | ||||
| 			encoding: b0010101 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; | ||||
| 			args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			//F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f); | ||||
| 			val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FCVT.S.D { | ||||
| 			encoding: b0100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"f%rd$d, f%rs1$d"; | ||||
| 			val res[32] <= fdispatch_fconv_d2f(F[rs1], rm{8}); | ||||
| 			// NaN boxing | ||||
| 			val upper[FLEN] <= -1; | ||||
| 			F[rd] <= upper<<32 | zext(res, FLEN); | ||||
| 		} | ||||
| 		FCVT.D.S { | ||||
| 			encoding: b0100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"f%rd$d, f%rs1$d"; | ||||
| 			val res[64] <= fdispatch_fconv_f2d(F[rs1]{32}, rm{8}); | ||||
| 			if(FLEN==64){ | ||||
| 				F[rd] <= res; | ||||
| 			} else { | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 		} | ||||
| 		FEQ.D { | ||||
| 			encoding: b1010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32)); | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FLT.D { | ||||
| 			encoding: b1010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32)); | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FLE.D { | ||||
| 			encoding: b1010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)); | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FCLASS.D { | ||||
| 			encoding: b1110001 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d"; | ||||
| 			X[rd]<=fdispatch_fclass_d(F[rs1]{64}); | ||||
| 		} | ||||
| 		FCVT.W.D { | ||||
| 			encoding: b1100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d"; | ||||
| 			X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(0, 32), rm{8}), XLEN); | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FCVT.WU.D { | ||||
| 			encoding: b1100001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d"; | ||||
| 			X[rd]<= zext(fdispatch_fcvt_d(F[rs1]{64}, zext(1, 32), rm{8}), XLEN); | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FCVT.D.W { | ||||
| 			encoding: b1101001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"f%rd$d, x%rs1$d"; | ||||
| 			val res[64] <= fdispatch_fcvt_d(sext(X[rs1],64), zext(2, 32), rm{8}); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 		} | ||||
| 		FCVT.D.WU { | ||||
| 			encoding: b1101001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"f%rd$d, x%rs1$d"; | ||||
| 			val res[64] <=fdispatch_fcvt_d(zext(X[rs1],64), zext(3,32), rm{8}); | ||||
| 			if(FLEN==64) | ||||
| 				F[rd] <= res; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<64) | res; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -15,9 +15,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			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); | ||||
| 			} | ||||
| 		} | ||||
| 		FSW { | ||||
| @@ -33,9 +33,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(0, 32), choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			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); | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| @@ -47,9 +47,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			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); | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};	 | ||||
| @@ -61,9 +61,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			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); | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| @@ -75,79 +75,79 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			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); | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FADD.S { | ||||
| 			encoding: b0000000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			// F[rd]f <= F[rs1]f + F[rs2]f; | ||||
| 			val res[32] <= fdispatch_fadd_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			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); | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FSUB.S { | ||||
| 			encoding: b0000100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			// F[rd]f <= F[rs1]f - F[rs2]f; | ||||
| 			val res[32] <= fdispatch_fsub_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			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); | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FMUL.S { | ||||
| 			encoding: b0001000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			// F[rd]f <= F[rs1]f * F[rs2]f; | ||||
| 			val res[32] <= fdispatch_fmul_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			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); | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FDIV.S { | ||||
| 			encoding: b0001100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
| 			// F[rd]f <= F[rs1]f / F[rs2]f; | ||||
| 			val res[32] <= fdispatch_fdiv_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			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); | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| 		} | ||||
| 		FSQRT.S { | ||||
| 			encoding: b0101100 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
| 			args_disass:"x%rd$d, f%rs1$d"; | ||||
| 			args_disass:"f%rd$d, f%rs1$d"; | ||||
| 			//F[rd]f<=sqrt(F[rs1]f); | ||||
| 			val res[32] <= fdispatch_fsqrt_s(F[rs1]{32}, choose(rm<7, rm{8}, FCSR{8})); | ||||
| 			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); | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| @@ -158,9 +158,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			val res[32] <= (F[rs1]{32} & 0x7fffffff) | (F[rs2]{32} & 0x80000000); | ||||
| 			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); | ||||
| 			} | ||||
| 		} | ||||
| 		FSGNJN.S { | ||||
| @@ -169,9 +169,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			val res[32] <= (F[rs1]{32} & 0x7fffffff) | (~F[rs2]{32} & 0x80000000); | ||||
| 			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); | ||||
| 			} | ||||
| 		} | ||||
| 		FSGNJX.S { | ||||
| @@ -180,9 +180,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			val res[32] <= F[rs1]{32} ^ (F[rs2]{32} & 0x80000000); | ||||
| 			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); | ||||
| 			} | ||||
| 		} | ||||
| 		FMIN.S  { | ||||
| @@ -192,9 +192,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(0, 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); | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| @@ -206,9 +206,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(1, 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); | ||||
| 			} | ||||
| 			val flags[32] <= fdispatch_fget_flags(); | ||||
| 			FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
| @@ -259,9 +259,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			val res[32] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8}); | ||||
| 			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); | ||||
| 			} | ||||
| 		} | ||||
| 		FCVT.S.WU { | ||||
| @@ -270,9 +270,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			val res[32] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8}); | ||||
| 			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); | ||||
| 			} | ||||
| 		} | ||||
| 		FMV.X.W { | ||||
| @@ -285,9 +285,9 @@ InsructionSet RV32F extends RV32IBase{ | ||||
| 			args_disass:"f%rd$d, x%rs1$d"; | ||||
| 			if(FLEN==32) | ||||
| 				F[rd] <= X[rs1]; | ||||
| 			else { | ||||
| 				val upper[FLEN] <= -1<<31; | ||||
| 				F[rd] <= upper*2 | X[rs1]; | ||||
| 			else { // NaN boxing | ||||
| 				val upper[FLEN] <= -1; | ||||
| 				F[rd] <= (upper<<32) | zext(X[rs1], FLEN); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -3,6 +3,7 @@ import "RV32M.core_desc" | ||||
| import "RV32A.core_desc" | ||||
| import "RV32C.core_desc" | ||||
| import "RV32F.core_desc" | ||||
| import "RV32D.core_desc" | ||||
| import "RV64IBase.core_desc" | ||||
| //import "RV64M.core_desc" | ||||
| import "RV64A.core_desc" | ||||
| @@ -26,10 +27,10 @@ Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32IC { | ||||
|     } | ||||
| } | ||||
|  | ||||
| Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC { | ||||
| Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC, RV32D { | ||||
|     constants { | ||||
|         XLEN:=32; | ||||
|         FLEN:=32; | ||||
|         FLEN:=64; | ||||
|         XLEN2:=64; | ||||
|         XLEN_BIT_MASK:=0x1f; | ||||
|         PCLEN:=32; | ||||
|   | ||||
| @@ -56,6 +56,8 @@ struct traits<${coreDef.name.toLowerCase()}> { | ||||
|      | ||||
|     enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}}; | ||||
|  | ||||
|     constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0}; | ||||
|  | ||||
|     enum reg_e {<% | ||||
|      	allRegs.each { reg ->  | ||||
|     		if( reg instanceof RegisterFile) { | ||||
| @@ -99,9 +101,6 @@ struct traits<${coreDef.name.toLowerCase()}> { | ||||
|     enum sreg_flag_e {FLAGS}; | ||||
|  | ||||
|     enum mem_type_e {${allSpaces.collect{s -> s.name}.join(', ')}}; | ||||
|  | ||||
| 	constexpr static bool has_fp_regs = ${allRegs.find {it.name=='FCSR'}!= null ?'true':'false'}; | ||||
|      | ||||
| }; | ||||
|  | ||||
| struct ${coreDef.name.toLowerCase()}: public arch_if { | ||||
|   | ||||
| @@ -50,7 +50,7 @@ | ||||
| namespace iss { | ||||
| namespace vm { | ||||
| namespace fp_impl{ | ||||
| void add_fp_functions_2_module(llvm::Module *mod); | ||||
| void add_fp_functions_2_module(llvm::Module *, unsigned); | ||||
| } | ||||
| } | ||||
|  | ||||
| @@ -89,7 +89,7 @@ protected: | ||||
|  | ||||
|     void setup_module(llvm::Module* m) override { | ||||
|         super::setup_module(m); | ||||
|         vm::fp_impl::add_fp_functions_2_module(m); | ||||
|         vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE); | ||||
|     } | ||||
|  | ||||
|     inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, | ||||
|   | ||||
| @@ -48,7 +48,9 @@ struct traits<rv32gc> { | ||||
|  | ||||
| 	constexpr static char const* const core_type = "RV32GC"; | ||||
|      | ||||
|     enum constants {XLEN=32, FLEN=32, XLEN2=64, XLEN_BIT_MASK=31, PCLEN=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=1075056897, PGSIZE=4096, PGMASK=4095, FFLAG_MASK=31}; | ||||
|     enum constants {XLEN=32, FLEN=64, XLEN2=64, XLEN_BIT_MASK=31, PCLEN=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=1075056897, PGSIZE=4096, PGMASK=4095, FFLAG_MASK=31}; | ||||
|  | ||||
|     constexpr static unsigned FP_REGS_SIZE = 64; | ||||
|  | ||||
|     enum reg_e { | ||||
|         X0, | ||||
| @@ -136,12 +138,12 @@ struct traits<rv32gc> { | ||||
|     using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; | ||||
|  | ||||
|     constexpr static unsigned reg_bit_width(unsigned r) { | ||||
|         constexpr std::array<const uint32_t, 71> RV32GC_reg_size{{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64}}; | ||||
|         constexpr std::array<const uint32_t, 71> RV32GC_reg_size{{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,32,64}}; | ||||
|         return RV32GC_reg_size[r]; | ||||
|     } | ||||
|  | ||||
|     constexpr static unsigned reg_byte_offset(unsigned r) { | ||||
|     	constexpr std::array<const uint32_t, 72> RV32GC_reg_byte_offset{{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,288}}; | ||||
|     	constexpr std::array<const uint32_t, 72> RV32GC_reg_byte_offset{{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,416,424}}; | ||||
|         return RV32GC_reg_byte_offset[r]; | ||||
|     } | ||||
|  | ||||
| @@ -150,9 +152,6 @@ struct traits<rv32gc> { | ||||
|     enum sreg_flag_e {FLAGS}; | ||||
|  | ||||
|     enum mem_type_e {MEM, CSR, FENCE, RES}; | ||||
|  | ||||
| 	constexpr static bool has_fp_regs = true; | ||||
|      | ||||
| }; | ||||
|  | ||||
| struct rv32gc: public arch_if { | ||||
| @@ -227,38 +226,38 @@ protected: | ||||
|         uint32_t X30 = 0; | ||||
|         uint32_t X31 = 0; | ||||
|         uint32_t PC = 0; | ||||
|         uint32_t F0 = 0; | ||||
|         uint32_t F1 = 0; | ||||
|         uint32_t F2 = 0; | ||||
|         uint32_t F3 = 0; | ||||
|         uint32_t F4 = 0; | ||||
|         uint32_t F5 = 0; | ||||
|         uint32_t F6 = 0; | ||||
|         uint32_t F7 = 0; | ||||
|         uint32_t F8 = 0; | ||||
|         uint32_t F9 = 0; | ||||
|         uint32_t F10 = 0; | ||||
|         uint32_t F11 = 0; | ||||
|         uint32_t F12 = 0; | ||||
|         uint32_t F13 = 0; | ||||
|         uint32_t F14 = 0; | ||||
|         uint32_t F15 = 0; | ||||
|         uint32_t F16 = 0; | ||||
|         uint32_t F17 = 0; | ||||
|         uint32_t F18 = 0; | ||||
|         uint32_t F19 = 0; | ||||
|         uint32_t F20 = 0; | ||||
|         uint32_t F21 = 0; | ||||
|         uint32_t F22 = 0; | ||||
|         uint32_t F23 = 0; | ||||
|         uint32_t F24 = 0; | ||||
|         uint32_t F25 = 0; | ||||
|         uint32_t F26 = 0; | ||||
|         uint32_t F27 = 0; | ||||
|         uint32_t F28 = 0; | ||||
|         uint32_t F29 = 0; | ||||
|         uint32_t F30 = 0; | ||||
|         uint32_t F31 = 0; | ||||
|         uint64_t F0 = 0; | ||||
|         uint64_t F1 = 0; | ||||
|         uint64_t F2 = 0; | ||||
|         uint64_t F3 = 0; | ||||
|         uint64_t F4 = 0; | ||||
|         uint64_t F5 = 0; | ||||
|         uint64_t F6 = 0; | ||||
|         uint64_t F7 = 0; | ||||
|         uint64_t F8 = 0; | ||||
|         uint64_t F9 = 0; | ||||
|         uint64_t F10 = 0; | ||||
|         uint64_t F11 = 0; | ||||
|         uint64_t F12 = 0; | ||||
|         uint64_t F13 = 0; | ||||
|         uint64_t F14 = 0; | ||||
|         uint64_t F15 = 0; | ||||
|         uint64_t F16 = 0; | ||||
|         uint64_t F17 = 0; | ||||
|         uint64_t F18 = 0; | ||||
|         uint64_t F19 = 0; | ||||
|         uint64_t F20 = 0; | ||||
|         uint64_t F21 = 0; | ||||
|         uint64_t F22 = 0; | ||||
|         uint64_t F23 = 0; | ||||
|         uint64_t F24 = 0; | ||||
|         uint64_t F25 = 0; | ||||
|         uint64_t F26 = 0; | ||||
|         uint64_t F27 = 0; | ||||
|         uint64_t F28 = 0; | ||||
|         uint64_t F29 = 0; | ||||
|         uint64_t F30 = 0; | ||||
|         uint64_t F31 = 0; | ||||
|         uint32_t FCSR = 0; | ||||
|         uint32_t NEXT_PC = 0; | ||||
|         uint32_t trap_state = 0, pending_trap = 0, machine_state = 0; | ||||
|   | ||||
| @@ -50,6 +50,8 @@ struct traits<rv32imac> { | ||||
|      | ||||
|     enum constants {XLEN=32, XLEN2=64, XLEN_BIT_MASK=31, PCLEN=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=1075056897, PGSIZE=4096, PGMASK=4095}; | ||||
|  | ||||
|     constexpr static unsigned FP_REGS_SIZE = 0; | ||||
|  | ||||
|     enum reg_e { | ||||
|         X0, | ||||
|         X1, | ||||
| @@ -117,9 +119,6 @@ struct traits<rv32imac> { | ||||
|     enum sreg_flag_e {FLAGS}; | ||||
|  | ||||
|     enum mem_type_e {MEM, CSR, FENCE, RES}; | ||||
|  | ||||
| 	constexpr static bool has_fp_regs = false; | ||||
|      | ||||
| }; | ||||
|  | ||||
| struct rv32imac: public arch_if { | ||||
|   | ||||
| @@ -50,6 +50,8 @@ 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=2147746049, PGSIZE=4096, PGMASK=4095}; | ||||
|  | ||||
|     constexpr static unsigned FP_REGS_SIZE = 0; | ||||
|  | ||||
|     enum reg_e { | ||||
|         X0, | ||||
|         X1, | ||||
| @@ -117,9 +119,6 @@ struct traits<rv64ia> { | ||||
|     enum sreg_flag_e {FLAGS}; | ||||
|  | ||||
|     enum mem_type_e {MEM, CSR, FENCE, RES}; | ||||
|  | ||||
| 	constexpr static bool has_fp_regs = false; | ||||
|      | ||||
| }; | ||||
|  | ||||
| struct rv64ia: public arch_if { | ||||
|   | ||||
| @@ -41,6 +41,8 @@ extern "C" { | ||||
| #include "specialize.h" | ||||
| } | ||||
|  | ||||
| #include <limits> | ||||
|  | ||||
| namespace iss { | ||||
| namespace vm { | ||||
| namespace fp_impl { | ||||
| @@ -68,18 +70,34 @@ using namespace std; | ||||
|  | ||||
| using namespace llvm; | ||||
|  | ||||
| void add_fp_functions_2_module(Module *mod) { | ||||
|     FDECL(fget_flags, INT_TYPE(32)); | ||||
|     FDECL(fadd_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fsub_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fmul_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fdiv_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fsqrt_s,    INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fcmp_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); | ||||
|     FDECL(fcvt_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fmadd_s,    INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|     FDECL(fsel_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); | ||||
|     FDECL(fclass_s,   INT_TYPE(32), INT_TYPE(32)); | ||||
| void add_fp_functions_2_module(Module *mod, uint32_t flen) { | ||||
|     if(flen){ | ||||
|         FDECL(fget_flags, INT_TYPE(32)); | ||||
|         FDECL(fadd_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fsub_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fmul_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fdiv_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fsqrt_s,    INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fcmp_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); | ||||
|         FDECL(fcvt_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fmadd_s,    INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); | ||||
|         FDECL(fsel_s,     INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); | ||||
|         FDECL(fclass_s,   INT_TYPE(32), INT_TYPE(32)); | ||||
|         if(flen>32){ | ||||
|             FDECL(fconv_d2f,  INT_TYPE(32), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fconv_f2d,  INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); | ||||
|             FDECL(fadd_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fsub_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fmul_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fdiv_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fsqrt_d,    INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); | ||||
|             FDECL(fcmp_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); | ||||
|             FDECL(fcvt_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); | ||||
|             FDECL(fmadd_d,    INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); | ||||
|             FDECL(fsel_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); | ||||
|             FDECL(fclass_d,   INT_TYPE(64), INT_TYPE(64)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| } | ||||
| @@ -202,14 +220,14 @@ uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mod | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float32_t res = softfloat_mulAddF32(v1, v2, v3, op&0x1); | ||||
|     if(op>1) res.v ^= 0x80000000UL; | ||||
|     if(op>1) res.v ^= 1ULL<<31; | ||||
|     return res.v; | ||||
| } | ||||
|  | ||||
| uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op) { | ||||
|     softfloat_exceptionFlags = 0; | ||||
|     bool v1_nan = (v1 & defaultNaNF32UI) == quiet_nan32; | ||||
|     bool v2_nan = (v2 & defaultNaNF32UI) == quiet_nan32; | ||||
|     bool v1_nan = (v1 & defaultNaNF32UI) == defaultNaNF32UI; | ||||
|     bool v2_nan = (v2 & defaultNaNF32UI) == defaultNaNF32UI; | ||||
|     bool v1_snan = softfloat_isSigNaNF32UI(v1); | ||||
|     bool v2_snan = softfloat_isSigNaNF32UI(v2); | ||||
|     if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid); | ||||
| @@ -257,6 +275,156 @@ uint32_t fclass_s( uint32_t v1 ){ | ||||
|         ( isNaN && !isSNaN )                       << 9; | ||||
| } | ||||
|  | ||||
| uint32_t fconv_d2f(uint64_t v1, uint8_t mode){ | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     bool nan = (v1 & defaultNaNF64UI)==defaultNaNF64UI; | ||||
|     if(nan){ | ||||
|         return defaultNaNF32UI; | ||||
|     } else { | ||||
|         float32_t res = f64_to_f32(float64_t{v1}); | ||||
|         return res.v; | ||||
|     } | ||||
| } | ||||
|  | ||||
| uint64_t fconv_f2d(uint32_t v1, uint8_t mode){ | ||||
|     bool nan = (v1 & defaultNaNF32UI)==defaultNaNF32UI; | ||||
|     if(nan){ | ||||
|         return defaultNaNF64UI; | ||||
|     } else { | ||||
|         softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|         float64_t res = f32_to_f64(float32_t{v1}); | ||||
|         return res.v; | ||||
|     } | ||||
| } | ||||
|  | ||||
| uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode) { | ||||
|     bool nan = (v1&defaultNaNF32UI)==quiet_nan32; | ||||
|     bool snan = softfloat_isSigNaNF32UI(v1); | ||||
|    float64_t v1f{v1},v2f{v2}; | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r =f64_add(v1f, v2f); | ||||
|     return r.v; | ||||
| } | ||||
|  | ||||
| uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) { | ||||
|     float64_t v1f{v1},v2f{v2}; | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r=f64_sub(v1f, v2f); | ||||
|     return r.v; | ||||
| } | ||||
|  | ||||
| uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) { | ||||
|     float64_t v1f{v1},v2f{v2}; | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r=f64_mul(v1f, v2f); | ||||
|     return r.v; | ||||
| } | ||||
|  | ||||
| uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) { | ||||
|     float64_t v1f{v1},v2f{v2}; | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r=f64_div(v1f, v2f); | ||||
|     return r.v; | ||||
| } | ||||
|  | ||||
| uint64_t fsqrt_d(uint64_t v1, uint8_t mode) { | ||||
|     float64_t v1f{v1}; | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r=f64_sqrt(v1f); | ||||
|     return r.v; | ||||
| } | ||||
|  | ||||
| uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) { | ||||
|     float64_t v1f{v1},v2f{v2}; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     bool nan = (v1&defaultNaNF64UI)==quiet_nan32 || (v2&defaultNaNF64UI)==quiet_nan32; | ||||
|     bool snan = softfloat_isSigNaNF64UI(v1) || softfloat_isSigNaNF64UI(v2); | ||||
|     switch(op){ | ||||
|     case 0: | ||||
|         if(nan | snan){ | ||||
|             if(snan) softfloat_raiseFlags(softfloat_flag_invalid); | ||||
|             return 0; | ||||
|         } else | ||||
|             return f64_eq(v1f,v2f )?1:0; | ||||
|     case 1: | ||||
|         if(nan | snan){ | ||||
|             softfloat_raiseFlags(softfloat_flag_invalid); | ||||
|             return 0; | ||||
|         } else | ||||
|             return f64_le(v1f,v2f )?1:0; | ||||
|     case 2: | ||||
|         if(nan | snan){ | ||||
|             softfloat_raiseFlags(softfloat_flag_invalid); | ||||
|             return 0; | ||||
|         } else | ||||
|             return f64_lt(v1f,v2f )?1:0; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) { | ||||
|     float64_t v1f{v1}; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r; | ||||
|     int32_t res; | ||||
|     switch(op){ | ||||
|     case 0: //w->s, fp to int32 | ||||
|         res = f64_to_i64(v1f,rmm_map[mode&0x7],true); | ||||
|         return (uint64_t)res; | ||||
|     case 1: //wu->s | ||||
|         return f64_to_ui64(v1f,rmm_map[mode&0x7],true); | ||||
|     case 2: //s->w | ||||
|         r=i64_to_f64(v1); | ||||
|         return r.v; | ||||
|     case 3: //s->wu | ||||
|         r=ui64_to_f64(v1); | ||||
|         return r.v; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode) { | ||||
|     // op should be {softfloat_mulAdd_subProd(2), softfloat_mulAdd_subC(1)} | ||||
|     softfloat_roundingMode=rmm_map[mode&0x7]; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t res = softfloat_mulAddF64(v1, v2, v3, op&0x1); | ||||
|     if(op>1) res.v ^= 1ULL<<63; | ||||
|     return res.v; | ||||
| } | ||||
|  | ||||
| uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op) { | ||||
|     softfloat_exceptionFlags = 0; | ||||
|     bool v1_nan = (v1 & defaultNaNF64UI) == defaultNaNF64UI; | ||||
|     bool v2_nan = (v2 & defaultNaNF64UI) == defaultNaNF64UI; | ||||
|     bool v1_snan = softfloat_isSigNaNF64UI(v1); | ||||
|     bool v2_snan = softfloat_isSigNaNF64UI(v2); | ||||
|     if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid); | ||||
|     if (v1_nan || v1_snan) | ||||
|         return (v2_nan || v2_snan) ? defaultNaNF64UI : v2; | ||||
|     else | ||||
|         if (v2_nan || v2_snan) | ||||
|             return v1; | ||||
|         else { | ||||
|             if ((v1 & std::numeric_limits<int64_t>::max()) == 0 && (v2 & std::numeric_limits<int64_t>::max()) == 0) { | ||||
|                 return op == 0 ? | ||||
|                         ((v1 & std::numeric_limits<int64_t>::min()) ? v1 : v2) : | ||||
|                         ((v1 & std::numeric_limits<int64_t>::min()) ? v2 : v1); | ||||
|             } else { | ||||
|                 float64_t v1f{ v1 }, v2f{ v2 }; | ||||
|                 return op == 0 ? | ||||
|                         (f64_lt(v1f, v2f) ? v1 : v2) : | ||||
|                         (f64_lt(v1f, v2f) ? v2 : v1); | ||||
|             } | ||||
|         } | ||||
| } | ||||
|  | ||||
| uint64_t fclass_d(uint64_t v1  ){ | ||||
|  | ||||
|     float64_t a{v1}; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -50,7 +50,7 @@ | ||||
| namespace iss { | ||||
| namespace vm { | ||||
| namespace fp_impl{ | ||||
| void add_fp_functions_2_module(llvm::Module *mod); | ||||
| void add_fp_functions_2_module(llvm::Module *, unsigned); | ||||
| } | ||||
| } | ||||
|  | ||||
| @@ -89,7 +89,7 @@ protected: | ||||
|  | ||||
|     void setup_module(llvm::Module* m) override { | ||||
|         super::setup_module(m); | ||||
|         vm::fp_impl::add_fp_functions_2_module(m); | ||||
|         vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE); | ||||
|     } | ||||
|  | ||||
|     inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, | ||||
|   | ||||
| @@ -50,7 +50,7 @@ | ||||
| namespace iss { | ||||
| namespace vm { | ||||
| namespace fp_impl{ | ||||
| void add_fp_functions_2_module(llvm::Module *mod); | ||||
| void add_fp_functions_2_module(llvm::Module *, unsigned); | ||||
| } | ||||
| } | ||||
|  | ||||
| @@ -89,7 +89,7 @@ protected: | ||||
|  | ||||
|     void setup_module(llvm::Module* m) override { | ||||
|         super::setup_module(m); | ||||
|         vm::fp_impl::add_fp_functions_2_module(m); | ||||
|         vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE); | ||||
|     } | ||||
|  | ||||
|     inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user