Updated compressed instructions for RV32D

This commit is contained in:
Eyck Jentzsch 2018-04-24 15:48:42 +02:00
parent 96700d00f9
commit 65ceedd157
3 changed files with 263 additions and 55 deletions

View File

@ -218,9 +218,9 @@ InsructionSet RV32FC extends RV32IC{
val res[32] <= MEM[offs]{32};
if(FLEN==32)
F[rd_idx] <= res;
else {
val upper[FLEN] <= (-1<<31);
F[rd_idx] <= upper*2 | res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
C.FSW {
@ -239,9 +239,9 @@ InsructionSet RV32FC extends RV32IC{
val res[32] <= MEM[offs]{32};
if(FLEN==32)
F[rd] <= res;
else {
val upper[FLEN] <= (-1<<31);
F[rd] <= upper*2 | res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
C.FSWSP {
@ -249,7 +249,7 @@ InsructionSet RV32FC extends RV32IC{
args_disass:"f%rs2$d, %uimm%(x2), ";
val x2_idx[5] <= 2;
val offs[XLEN] <= X[x2_idx]+uimm;
MEM[offs]{32}<=F[rs2];
MEM[offs]{32}<=F[rs2]{32};
}
}
}
@ -268,15 +268,45 @@ InsructionSet RV32DC extends RV32IC{
instructions{
C.FLD { //(RV32/64)
encoding: b001 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00;
args_disass:"f(8+%rd$d), %uimm%(x(8+%rs1$d))";
val rs1_idx[5] <= rs1+8;
val rd_idx[5] <= rd+8;
val offs[XLEN] <= X[rs1_idx]+uimm;
val res[64] <= MEM[offs]{64};
if(FLEN==64)
F[rd_idx] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd_idx] <= (upper<<64) | res;
}
}
C.FSD { //(RV32/64)
encoding: b101 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00;
args_disass:"f(8+%rs2$d), %uimm%(x(8+%rs1$d))";
val rs1_idx[5] <= rs1+8;
val rs2_idx[5] <= rs2+8;
val offs[XLEN] <= X[rs1_idx]+uimm;
MEM[offs]{64}<=F[rs2_idx]{64};
}
C.FLDSP {//(RV32/64)
encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10;
args_disass:"f%rd$d, %uimm%(x2)";
val x2_idx[5] <= 2;
val offs[XLEN] <= X[x2_idx]+uimm;
val res[64] <= MEM[offs]{64};
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | zext(res, FLEN);
}
}
C.FSDSP {//(RV32/64)
encoding:b101 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10;
args_disass:"f%rs2$d, %uimm%(x2), ";
val x2_idx[5] <= 2;
val offs[XLEN] <= X[x2_idx]+uimm;
MEM[offs]{64}<=F[rs2]{64};
}
}
}

View File

@ -27,7 +27,7 @@ Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32IC {
}
}
Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC, RV32D {
Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC, RV32D, RV32DC {
constants {
XLEN:=32;
FLEN:=64;

View File

@ -194,7 +194,7 @@ private:
compile_func op;
};
const std::array<InstructionDesriptor, 155> instr_descr = {{
const std::array<InstructionDesriptor, 159> instr_descr = {{
/* entries are: size, valid value, valid mask, function ptr */
/* instruction LUI */
{32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui},
@ -506,6 +506,14 @@ private:
{32, 0b11010010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_w},
/* instruction FCVT.D.WU */
{32, 0b11010010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_wu},
/* instruction C.FLD */
{16, 0b0010000000000000, 0b1110000000000011, &this_class::__c_fld},
/* instruction C.FSD */
{16, 0b1010000000000000, 0b1110000000000011, &this_class::__c_fsd},
/* instruction C.FLDSP */
{16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_fldsp},
/* instruction C.FSDSP */
{16, 0b1010000000000010, 0b1110000000000011, &this_class::__c_fsdsp},
}};
/* instruction definitions */
@ -641,43 +649,19 @@ private:
Value* cur_pc_val = this->gen_const(32, pc.val);
pc=pc+4;
Value* new_pc_val = this->builder.CreateAdd(
if(fld_rd_val != 0){
Value* X_rd_val = this->builder.CreateAdd(
cur_pc_val,
this->gen_const(32U, 4));
this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::X0), false);
}
Value* ret_val = this->builder.CreateAdd(
this->gen_reg_load(fld_rs1_val + traits<ARCH>::X0, 0),
this->gen_const(32U, fld_imm_val));
Value* align_val = this->builder.CreateAnd(
new_pc_val,
this->gen_const(32U, 2));
llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk);
llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext);
llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext);
// this->builder.SetInsertPoint(bb);
this->gen_cond_branch(this->builder.CreateICmp(
ICmpInst::ICMP_NE,
align_val,
this->gen_const(32U, 0)),
bb_then,
bb_else);
this->builder.SetInsertPoint(bb_then);
{
this->gen_raise_trap(0, 0);
}
this->builder.CreateBr(bbnext);
this->builder.SetInsertPoint(bb_else);
{
if(fld_rd_val != 0){
Value* X_rd_val = this->builder.CreateAdd(
cur_pc_val,
this->gen_const(32U, 4));
this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::X0), false);
}
Value* PC_val = this->builder.CreateAnd(
new_pc_val,
this->builder.CreateNot(this->gen_const(32U, 1)));
this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
}
this->builder.CreateBr(bbnext);
bb=bbnext;
this->builder.SetInsertPoint(bb);
Value* PC_val = this->builder.CreateAnd(
ret_val,
this->builder.CreateNot(this->gen_const(32U, 1)));
this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->gen_sync(iss::POST_SYNC, 3);
this->gen_trap_check(this->leave_blk);
return std::make_tuple(iss::vm::BRANCH, nullptr);
@ -6368,13 +6352,16 @@ private:
Value* F_rd_idx_val = res_val;
this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits<ARCH>::F0), false);
} else {
uint64_t upper_val = (-1) << 31;
Value* F_rd_idx_val = this->builder.CreateOr(
this->builder.CreateMul(
uint64_t upper_val = (-1);
Value* F_rd_val = this->builder.CreateOr(
this->builder.CreateShl(
this->gen_const(64U, upper_val),
this->gen_const(64U, 2)),
res_val);
this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits<ARCH>::F0), false);
this->gen_const(64U, 32)),
this->gen_ext(
res_val,
64,
false));
this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::F0), false);
}
this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
this->gen_sync(iss::POST_SYNC, 125);
@ -6459,12 +6446,15 @@ private:
Value* F_rd_val = res_val;
this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::F0), false);
} else {
uint64_t upper_val = (-1) << 31;
uint64_t upper_val = (-1);
Value* F_rd_val = this->builder.CreateOr(
this->builder.CreateMul(
this->builder.CreateShl(
this->gen_const(64U, upper_val),
this->gen_const(64U, 2)),
res_val);
this->gen_const(64U, 32)),
this->gen_ext(
res_val,
64,
false));
this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::F0), false);
}
this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
@ -6501,7 +6491,10 @@ private:
Value* offs_val = this->builder.CreateAdd(
this->gen_reg_load(x2_idx_val + traits<ARCH>::X0, 0),
this->gen_const(32U, fld_uimm_val));
Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits<ARCH>::F0, 0);
Value* MEM_offs_val = this->builder.CreateTrunc(
this->gen_reg_load(fld_rs2_val + traits<ARCH>::F0, 0),
this-> get_type(32)
);
this->gen_write_mem(
traits<ARCH>::MEM,
offs_val,
@ -8096,6 +8089,191 @@ private:
return std::make_tuple(vm::CONT, bb);
}
/* instruction 155: C.FLD */
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_fld(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.FLD");
this->gen_sync(iss::PRE_SYNC, 155);
uint8_t fld_rd_val = 0 | (bit_sub<2,3>(instr));
uint8_t fld_uimm_val = 0 | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3);
uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.FLD f(8+%1$d), %2%(x(8+%3$d))");
ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val;
std::vector<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);
}
Value* cur_pc_val = this->gen_const(32, pc.val);
pc=pc+2;
uint8_t rs1_idx_val = (fld_rs1_val + 8);
uint8_t rd_idx_val = (fld_rd_val + 8);
Value* offs_val = this->builder.CreateAdd(
this->gen_reg_load(rs1_idx_val + traits<ARCH>::X0, 0),
this->gen_const(32U, fld_uimm_val));
Value* res_val = this->gen_read_mem(traits<ARCH>::MEM, offs_val, 64/8);
if(64 == 64){
Value* F_rd_idx_val = res_val;
this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits<ARCH>::F0), false);
} else {
uint64_t upper_val = (-1);
Value* F_rd_idx_val = this->builder.CreateOr(
this->builder.CreateShl(
this->gen_const(64U, upper_val),
this->gen_const(64U, 64)),
res_val);
this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits<ARCH>::F0), false);
}
this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
this->gen_sync(iss::POST_SYNC, 155);
bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */
this->gen_trap_check(bb);
return std::make_tuple(vm::CONT, bb);
}
/* instruction 156: C.FSD */
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_fsd(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.FSD");
this->gen_sync(iss::PRE_SYNC, 156);
uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr));
uint8_t fld_uimm_val = 0 | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3);
uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.FSD f(8+%1$d), %2%(x(8+%3$d))");
ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val;
std::vector<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);
}
Value* cur_pc_val = this->gen_const(32, pc.val);
pc=pc+2;
uint8_t rs1_idx_val = (fld_rs1_val + 8);
uint8_t rs2_idx_val = (fld_rs2_val + 8);
Value* offs_val = this->builder.CreateAdd(
this->gen_reg_load(rs1_idx_val + traits<ARCH>::X0, 0),
this->gen_const(32U, fld_uimm_val));
Value* MEM_offs_val = this->builder.CreateTrunc(
this->gen_reg_load(rs2_idx_val + traits<ARCH>::F0, 0),
this-> get_type(64)
);
this->gen_write_mem(
traits<ARCH>::MEM,
offs_val,
this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(64)));
this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
this->gen_sync(iss::POST_SYNC, 156);
bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */
this->gen_trap_check(bb);
return std::make_tuple(vm::CONT, bb);
}
/* instruction 157: C.FLDSP */
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_fldsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.FLDSP");
this->gen_sync(iss::PRE_SYNC, 157);
uint16_t fld_uimm_val = 0 | (bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5);
uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr));
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.FLDSP f%1$d, %2%(x2)");
ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val;
std::vector<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);
}
Value* cur_pc_val = this->gen_const(32, pc.val);
pc=pc+2;
uint8_t x2_idx_val = 2;
Value* offs_val = this->builder.CreateAdd(
this->gen_reg_load(x2_idx_val + traits<ARCH>::X0, 0),
this->gen_const(32U, fld_uimm_val));
Value* res_val = this->gen_read_mem(traits<ARCH>::MEM, offs_val, 64/8);
if(64 == 64){
Value* F_rd_val = res_val;
this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::F0), false);
} else {
uint64_t upper_val = (-1);
Value* F_rd_val = this->builder.CreateOr(
this->builder.CreateShl(
this->gen_const(64U, upper_val),
this->gen_const(64U, 64)),
this->gen_ext(
res_val,
64,
false));
this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::F0), false);
}
this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
this->gen_sync(iss::POST_SYNC, 157);
bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */
this->gen_trap_check(bb);
return std::make_tuple(vm::CONT, bb);
}
/* instruction 158: C.FSDSP */
std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_fsdsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
bb->setName("C.FSDSP");
this->gen_sync(iss::PRE_SYNC, 158);
uint8_t fld_rs2_val = 0 | (bit_sub<2,5>(instr));
uint16_t fld_uimm_val = 0 | (bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3);
if(this->disass_enabled){
/* generate console output when executing the command */
boost::format ins_fmter("C.FSDSP f%1$d, %2%(x2), ");
ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val;
std::vector<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);
}
Value* cur_pc_val = this->gen_const(32, pc.val);
pc=pc+2;
uint8_t x2_idx_val = 2;
Value* offs_val = this->builder.CreateAdd(
this->gen_reg_load(x2_idx_val + traits<ARCH>::X0, 0),
this->gen_const(32U, fld_uimm_val));
Value* MEM_offs_val = this->builder.CreateTrunc(
this->gen_reg_load(fld_rs2_val + traits<ARCH>::F0, 0),
this-> get_type(64)
);
this->gen_write_mem(
traits<ARCH>::MEM,
offs_val,
this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(64)));
this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
this->gen_sync(iss::POST_SYNC, 158);
bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */
this->gen_trap_check(bb);
return std::make_tuple(vm::CONT, bb);
}
/****************************************************************************
* end opcode definitions
****************************************************************************/